Skip to content
Snippets Groups Projects
random_vertices.py 4.22 KiB
Newer Older
  • Learn to ignore specific revisions
  • # SPDX-License-Identifier: GPL-2.0-or-later
    
    
    bl_info = {
        "name": "Random Vertices",
        "author": "Oscurart, Greg",
        "version": (1, 3),
        "blender": (2, 63, 0),
        "location": "Object > Transform > Random Vertices",
        "description": "Randomize selected components of active object",
        "warning": "",
    
        "doc_url": "",
        "category": "Mesh",
    }
    
    
    
    import bpy
    from bpy.types import Operator
    import random
    import bmesh
    from bpy.props import (
            BoolProperty,
            FloatProperty,
            IntVectorProperty,
            )
    
    
    def add_object(self, context, valmin, valmax, factor, vgfilter):
        # select an option with weight map or not
        mode = bpy.context.active_object.mode
        # generate variables
        objact = bpy.context.active_object
        listver = []
        warn_message = False
    
        # switch to edit mode
        bpy.ops.object.mode_set(mode='OBJECT')
        bpy.ops.object.mode_set(mode='EDIT')
    
        # bmesh object
        odata = bmesh.from_edit_mesh(objact.data)
        odata.select_flush(False)
    
        # if the vertex is selected add to the list
        for vertice in odata.verts[:]:
            if vertice.select:
                listver.append(vertice.index)
    
        # If the minimum value is greater than the maximum,
        # it adds a value to the maximum
        if valmin[0] >= valmax[0]:
            valmax[0] = valmin[0] + 1
    
        if valmin[1] >= valmax[1]:
            valmax[1] = valmin[1] + 1
    
        if valmin[2] >= valmax[2]:
            valmax[2] = valmin[2] + 1
    
        odata.verts.ensure_lookup_table()
    
        random_factor = factor
        for vertice in listver:
            odata.verts.ensure_lookup_table()
            if odata.verts[vertice].select:
                if vgfilter is True:
                    has_group = getattr(objact.data.vertices[vertice], "groups", None)
                    vertex_group = has_group[0] if has_group else None
                    vertexweight = getattr(vertex_group, "weight", None)
                    if vertexweight:
                        random_factor = factor * vertexweight
                    else:
                        random_factor = factor
                        warn_message = True
    
                odata.verts[vertice].co = (
                    (((random.randrange(valmin[0], valmax[0], 1)) * random_factor) / 1000) +
                    odata.verts[vertice].co[0],
                    (((random.randrange(valmin[1], valmax[1], 1)) * random_factor) / 1000) +
                    odata.verts[vertice].co[1],
                    (((random.randrange(valmin[2], valmax[2], 1)) * random_factor) / 1000) +
                    odata.verts[vertice].co[2]
                    )
    
        if warn_message:
            self.report({'WARNING'},
                        "Some of the Selected Vertices don't have a Group with Vertex Weight assigned")
        bpy.ops.object.mode_set(mode=mode)
    
    
    class MESH_OT_random_vertices(Operator):
        bl_idname = "mesh.random_vertices"
        bl_label = "Random Vertices"
        bl_description = ("Randomize the location of vertices by a specified\n"
                          "Multiplier Factor and random values in the defined range\n"
                          "or a multiplication of them and the Vertex Weights")
        bl_options = {'REGISTER', 'UNDO'}
    
        vgfilter: BoolProperty(
                name="Vertex Group",
                description="Use Vertex Weight defined in the Active Group",
                default=False
                )
        factor: FloatProperty(
                name="Factor",
                description="Base Multiplier of the randomization effect",
                default=1
                )
        valmin: IntVectorProperty(
                name="Min XYZ",
                description="Define the minimum range of randomization values",
                default=(0, 0, 0)
                )
        valmax: IntVectorProperty(
                name="Max XYZ",
                description="Define the maximum range of randomization values",
                default=(1, 1, 1)
                )
    
        @classmethod
        def poll(cls, context):
            return (context.object and context.object.type == "MESH" and
                   context.mode == "EDIT_MESH")
    
        def execute(self, context):
            add_object(self, context, self.valmin, self.valmax, self.factor, self.vgfilter)
    
            return {'FINISHED'}
    
    
    # Registration
    
    def register():
        bpy.utils.register_class(MESH_OT_random_vertices)
    
    
    def unregister():
        bpy.utils.unregister_class(MESH_OT_random_vertices)
    
    
    if __name__ == '__main__':
        register()