[Bf-extensions-cvs] [ea424564] master: Fix T53579: Move the settings into a Tools Panel, use wm property group

lijenstina noreply at git.blender.org
Sat Jan 6 07:25:06 CET 2018


Commit: ea4245645cbf68421738d445c2380ef54919186d
Author: lijenstina
Date:   Sat Jan 6 07:23:58 2018 +0100
Branches: master
https://developer.blender.org/rBAea4245645cbf68421738d445c2380ef54919186d

Fix T53579: Move the settings into a Tools Panel, use wm property group

Bump version to 1.1.4
Remove some dead code
Use register class instead of register_module

Adress the F6 redo menu Blender crash issue by:
1) Moving the properties from the operator to a property group
of window manager type (bpy.types.WindowManager.ivy_gen_props)
2) Only the update is exposed in the operator undo (a boolprop)
3) Settings moved into the CURVE_PT_IvyGenPanel located under the
Tools Region > Create > Ivy Generator

Functionality should be the same as before:

Since the window manager props are not jumping back on operator redo
the operator just pulls them in execute which allows change in the Panel
while operator is still active

The default values are assigned by setting the operator defaultIvy to True

===================================================================

M	add_curve_ivygen.py

===================================================================

diff --git a/add_curve_ivygen.py b/add_curve_ivygen.py
index dd523102..7a90b3b9 100644
--- a/add_curve_ivygen.py
+++ b/add_curve_ivygen.py
@@ -21,9 +21,9 @@
 bl_info = {
     "name": "IvyGen",
     "author": "testscreenings, PKHG, TrumanBlending",
-    "version": (0, 1, 2),
+    "version": (0, 1, 4),
     "blender": (2, 59, 0),
-    "location": "View3D > Add > Curve",
+    "location": "View3D > Tool Shelf > Create > Ivy Generator",
     "description": "Adds generated ivy to a mesh object starting "
                    "at the 3D cursor",
     "warning": "",
@@ -34,10 +34,16 @@ bl_info = {
 
 
 import bpy
+from bpy.types import (
+        Operator,
+        Panel,
+        PropertyGroup,
+        )
 from bpy.props import (
+        BoolProperty,
         FloatProperty,
         IntProperty,
-        BoolProperty,
+        PointerProperty,
         )
 from mathutils import (
         Vector,
@@ -191,7 +197,7 @@ def createIvyGeometry(IVY, growLeaves):
 
     if growLeaves:
         faceList = [[4 * i + l for l in range(4)] for i in
-                                                     range(len(vertList) // 4)]
+                    range(len(vertList) // 4)]
 
         # Generate the new leaf mesh and link
         me = bpy.data.meshes.new('IvyLeaf')
@@ -212,24 +218,6 @@ def createIvyGeometry(IVY, growLeaves):
         ob.parent = newCurve
 
 
-'''
-def computeBoundingSphere(ob):
-    # Get the mesh data
-    me = ob.data
-    # Intialise the center
-    center = Vector((0.0, 0.0, 0.0))
-    # Add all vertex coords
-    for v in me.vertices:
-        center += v.co
-    # Average over all verts
-    center /= len(me.vertices)
-    # Create the iterator and find its max
-    length_iter = ((center - v.co).length for v in me.vertices)
-    radius = max(length_iter)
-    return radius
-'''
-
-
 class IvyNode:
     """ The basic class used for each point on the ivy which is grown."""
     __slots__ = ('pos', 'primaryDir', 'adhesionVector', 'adhesionLength',
@@ -463,12 +451,204 @@ def check_mesh_faces(ob):
     return False
 
 
-class IvyGen(bpy.types.Operator):
+class IvyGen(Operator):
     bl_idname = "curve.ivy_gen"
     bl_label = "IvyGen"
     bl_description = "Generate Ivy on an Mesh Object"
     bl_options = {'REGISTER', 'UNDO'}
 
+    updateIvy = BoolProperty(
+            name="Update Ivy",
+            description="Update the Ivy location based on the cursor and Panel settings",
+            default=False
+            )
+    defaultIvy = BoolProperty(
+            name="Default Ivy",
+            options={"HIDDEN", "SKIP_SAVE"},
+            default=False
+            )
+
+    @classmethod
+    def poll(self, context):
+        # Check if there's an object and whether it's a mesh
+        ob = context.active_object
+        return ((ob is not None) and
+                (ob.type == 'MESH') and
+                (context.mode == 'OBJECT'))
+
+    def invoke(self, context, event):
+        self.updateIvy = True
+        return self.execute(context)
+
+    def execute(self, context):
+        # scene = context.scene
+        ivyProps = context.window_manager.ivy_gen_props
+
+        if not self.updateIvy:
+            return {'PASS_THROUGH'}
+
+        # assign the variables, check if it is default
+        # Note: update the values if window_manager props defaults are changed
+        randomSeed = ivyProps.randomSeed if not self.defaultIvy else 0
+        maxTime = ivyProps.maxTime if not self.defaultIvy else 0
+        maxIvyLength = ivyProps.maxIvyLength if not self.defaultIvy else 1.0
+        ivySize = ivyProps.ivySize if not self.defaultIvy else 0.02
+        maxFloatLength = ivyProps.maxFloatLength if not self.defaultIvy else 0.5
+        maxAdhesionDistance = ivyProps.maxAdhesionDistance if not self.defaultIvy else 1.0
+        primaryWeight = ivyProps.primaryWeight if not self.defaultIvy else 0.5
+        randomWeight = ivyProps.randomWeight if not self.defaultIvy else 0.2
+        gravityWeight = ivyProps.gravityWeight if not self.defaultIvy else 1.0
+        adhesionWeight = ivyProps.adhesionWeight if not self.defaultIvy else 0.1
+        branchingProbability = ivyProps.branchingProbability if not self.defaultIvy else 0.05
+        leafProbability = ivyProps.leafProbability if not self.defaultIvy else 0.35
+        ivyBranchSize = ivyProps.ivyBranchSize if not self.defaultIvy else 0.001
+        ivyLeafSize = ivyProps.ivyLeafSize if not self.defaultIvy else 0.02
+        growLeaves = ivyProps.growLeaves if not self.defaultIvy else True
+
+        bpy.ops.object.mode_set(mode='EDIT', toggle=False)
+        bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
+
+        # Get the selected object
+        ob = context.active_object
+
+        # Check if the mesh has at least one polygon since some functions
+        # are expecting them in the object's data (see T51753)
+        check_face = check_mesh_faces(ob)
+        if check_face is False:
+            self.report({'WARNING'},
+                        "Mesh Object doesn't have at least one Face. "
+                        "Operation Cancelled")
+            return {"CANCELLED"}
+
+        # Compute bounding sphere radius
+        # radius = computeBoundingSphere(ob)  # Not needed anymore
+
+        # Get the seeding point
+        seedPoint = context.scene.cursor_location
+
+        # Fix the random seed
+        rand_seed(randomSeed)
+
+        # Make the new ivy
+        IVY = Ivy(
+            primaryWeight=primaryWeight,
+            randomWeight=randomWeight,
+            gravityWeight=gravityWeight,
+            adhesionWeight=adhesionWeight,
+            branchingProbability=branchingProbability,
+            leafProbability=leafProbability,
+            ivySize=ivySize,
+            ivyLeafSize=ivyLeafSize,
+            ivyBranchSize=ivyBranchSize,
+            maxFloatLength=maxFloatLength,
+            maxAdhesionDistance=maxAdhesionDistance
+            )
+        # Generate first root and node
+        IVY.seed(seedPoint)
+
+        checkTime = False
+        maxLength = maxIvyLength  # * radius
+
+        # If we need to check time set the flag
+        if maxTime != 0.0:
+            checkTime = True
+
+        t = time.time()
+        startPercent = 0.0
+        checkAliveIter = [True, ]
+
+        # Grow until 200 roots is reached or backup counter exceeds limit
+        while (any(checkAliveIter) and
+               (IVY.maxLength < maxLength) and
+               (not checkTime or (time.time() - t < maxTime))):
+            # Grow the ivy for this iteration
+            IVY.grow(ob)
+
+            # Print the proportion of ivy growth to console
+            if (IVY.maxLength / maxLength * 100) > 10 * startPercent // 10:
+                print('%0.2f%% of Ivy nodes have grown' %
+                                         (IVY.maxLength / maxLength * 100))
+                startPercent += 10
+                if IVY.maxLength / maxLength > 1:
+                    print("Halting Growth")
+
+            # Make an iterator to check if all are alive
+            checkAliveIter = (r.alive for r in IVY.ivyRoots)
+
+        # Create the curve and leaf geometry
+        createIvyGeometry(IVY, growLeaves)
+        print("Geometry Generation Complete")
+
+        print("Ivy generated in %0.2f s" % (time.time() - t))
+
+        self.updateIvy = False
+        self.defaultIvy = False
+
+        return {'FINISHED'}
+
+    def draw(self, context):
+        layout = self.layout
+
+        layout.prop(self, "updateIvy", icon="FILE_REFRESH")
+
+
+class CURVE_PT_IvyGenPanel(Panel):
+    bl_label = "Ivy Generator"
+    bl_idname = "CURVE_PT_IvyGenPanel"
+    bl_space_type = "VIEW_3D"
+    bl_region_type = "TOOLS"
+    bl_category = "Create"
+    bl_context = 'objectmode'
+    bl_options = {"DEFAULT_CLOSED"}
+
+    def draw(self, context):
+        layout = self.layout
+        wm = context.window_manager
+        col = layout.column(align=True)
+
+        prop_new = col.operator("curve.ivy_gen", text="Add New Ivy", icon="OUTLINER_OB_CURVE")
+        prop_new.defaultIvy = False
+        prop_new.updateIvy = True
+
+        prop_def = col.operator("curve.ivy_gen", text="Add New Default Ivy", icon="CURVE_DATA")
+        prop_def.defaultIvy = True
+        prop_def.updateIvy = True
+
+        col = layout.column(align=True)
+        col.label("Generation Settings:")
+        col.prop(wm.ivy_gen_props, "randomSeed")
+        col.prop(wm.ivy_gen_props, "maxTime")
+
+        col = layout.column(align=True)
+        col.label("Size Settings:")
+        col.prop(wm.ivy_gen_props, "maxIvyLength")
+        col.prop(wm.ivy_gen_props, "ivySize")
+        col.prop(wm.ivy_gen_props, "maxFloatLength")
+        col.prop(wm.ivy_gen_props, "maxAdhesionDistance")
+
+        col = layout.column(align=True)
+        col.label("Weight Settings:")
+        col.prop(wm.ivy_gen_props, "primaryWeight")
+        col.prop(wm.ivy_gen_props, "randomWeight")
+        col.prop(wm.ivy_gen_props, "gravityWeight")
+        col.prop(wm.ivy_gen_props, "adhesionWeight")
+
+        col = layout.column(align=True)
+        col.label("Branch Settings:")
+        col.prop(wm.ivy_gen_props, "branchingProbability")
+        col.prop(wm.ivy_gen_props, "ivyBranchSize")
+
+        col = layout.column(align=True)
+        col.prop(wm.ivy_gen_props, "growLeaves")
+
+        if wm.ivy_gen_props.growLeaves:
+            col = layout.column(align=True)
+            col.label("Leaf Settings:")
+            col.prop(wm.ivy_gen_props, "ivyLeafSize")
+            col.prop(wm.ivy_gen_props, "leafProbability")
+
+
+class IvyGenProperties(PropertyGroup):
     maxIvyLength = FloatProperty(
             name="Max Ivy Length",
             description="Maximum ivy length in Blender Units",
@@ -551,7 +731,8 @@ class IvyGen(bpy.types.Operator):
                         "can live while floating",
             default=0.5,
             min=0.0,
-            soft_max=1.0)
+            soft_max=1.0
+            )
     maxAdhesionDistance = FloatProperty(
             name="Max Adhesion Length",
             description="The maximum distance that a branch "
@@ -580,168 +761,29 @@ class IvyGen(bpy.types.Operator):
             description="Grow leaves or not",

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-extensions-cvs mailing list