Browse Source

Add viewport/render isibility to GeometryObject and fix drivers to work with object properties.
Minor fixes for Geometry Object UX (less duplicating of objects and more consistent updating mesh data)

Joseph Brandenburg 9 months ago
parent
commit
c0dad05b98
3 changed files with 63 additions and 11 deletions
  1. 12 4
      drivers.py
  2. 49 7
      xForm_containers.py
  3. 2 0
      xForm_definitions.py

+ 12 - 4
drivers.py

@@ -82,11 +82,13 @@ def CreateDrivers(drivers):
             dVar = drv.variables.remove(v)
             
         for v in driver["vars"]:
+            pose_bone = False
             bone = ''; target2bone = ''
             vob, target2ob = None, None
             if (isinstance(v["owner"], Object)):
                 vob = v["owner"]
             else:
+                pose_bone = True
                 vob = v["owner"].id_data
                 bone = v["owner"].name
             #
@@ -118,11 +120,17 @@ def CreateDrivers(drivers):
                 dVar.targets[0].transform_space = v["space"]
                 dVar.targets[0].transform_type = v["channel"]
             if (dVar.type == 'SINGLE_PROP'):
-                stub = "pose.bones[\""+v["owner"].name+"\"]"
-                if (hasattr( v["owner"], v["prop"] )):
-                    dVar.targets[0].data_path = stub + "."+ (v["prop"])
+                if pose_bone:
+                    stub = "pose.bones[\""+v["owner"].name+"\"]"
+                    if (hasattr( v["owner"], v["prop"] )):
+                        dVar.targets[0].data_path = stub + "."+ (v["prop"])
+                    else:
+                        dVar.targets[0].data_path = stub + brackets(v["prop"])
                 else:
-                    dVar.targets[0].data_path = stub + brackets(v["prop"])
+                    if (hasattr( v["owner"], v["prop"] )):
+                        dVar.targets[0].data_path = (v["prop"])
+                    else:
+                        dVar.targets[0].data_path = brackets(v["prop"])
         # setup keyframe points
         kp = fc.keyframe_points
         for key in driver["keys"]:

+ 49 - 7
xForm_containers.py

@@ -844,7 +844,6 @@ class xFormBone:
         fill_parameters(self)
         # otherwise we will do this from the schema 
 
-
 class xFormGeometryObject:
     '''A node representing an armature object'''
 
@@ -859,6 +858,8 @@ class xFormGeometryObject:
           "Matrix"         : NodeSocket(is_input = True, name = "Matrix", node = self),
           "Relationship"   : NodeSocket(is_input = True, name = "Relationship", node = self),
           "Deformer"   : NodeSocket(is_input = True, name = "Relationship", node = self),
+          "Hide in Viewport"   : NodeSocket(is_input = True, name = "Hide in Viewport", node = self),
+          "Hide in Render"   : NodeSocket(is_input = True, name = "Hide in Render", node = self),
         }
         self.outputs = {
           "xForm Out" : NodeSocket(is_input = False, name="xForm Out", node = self), }
@@ -867,7 +868,9 @@ class xFormGeometryObject:
           "Geometry":None, 
           "Matrix":None, 
           "Relationship":None, 
-          "Deformer":None, 
+          "Deformer":None,
+          "Hide in Viewport":None,
+          "Hide in Render":None,
         }
         self.links = {} # leave this empty for now!
         # now set up the traverse target...
@@ -875,14 +878,16 @@ class xFormGeometryObject:
         self.outputs["xForm Out"].set_traverse_target(self.inputs["Relationship"])
         self.node_type = "XFORM"
         self.bObject = None
-        self.prepared = True
+        self.prepared = False
         self.executed = False
+        self.drivers = {}
 
     def bSetParent(self, ob):
         from bpy.types import Object, Bone
         parent_nc = get_parent(self, type='LINK')
         if (parent_nc):
-            parent = parent_nc.inputs['Parent'].links[0].from_node
+            #TODO: this is a lazy HACK that will lead to many a BUG. FIXME.
+            parent = parent_nc.inputs['Parent'].links[0].from_node # <===
             parent_bOb = parent.bGetObject(mode = 'EDIT')
             if isinstance(parent_bOb, Bone):
                 armOb= parent.bGetParentArmature()
@@ -895,19 +900,40 @@ class xFormGeometryObject:
             #   matrix after setting the parent.
             #
             # deal with parenting settings here, if necesary
+
     def bPrepare(self, bContext = None,):
         import bpy
+        if not self.evaluate_input("Name"):
+            self.prepared = True
+            self.executed = True
+            # and return an error if there are any dependencies:
+            if self.hierarchy_connections:
+                raise GraphError(wrapRed(f"Cannot Generate object {self} because the chosen name is empty or invalid."))
+            return
         self.bObject = bpy.data.objects.get(self.evaluate_input("Name"))
         trace = trace_single_line(self, "Geometry")
-        if (not self.bObject) or (self.inputs["Geometry"].is_linked and self.bObject.type == "EMPTY"):
+        if (not self.bObject):
             if trace[-1]:
                 self.bObject = bpy.data.objects.new(self.evaluate_input("Name"), trace[-1].node.bGetObject())
+        # handle mismatched data.
+        data_wrong = False; data  = None
+        if (self.inputs["Geometry"].is_linked and self.bObject.type == "EMPTY"):
+            data_wrong = True; data = trace[-1].node.bGetObject()
+        elif (not self.inputs["Geometry"].is_linked and not self.bObject.type == "EMPTY"):
+            data_wrong = True
+        # clumsy but functional
+        if data_wrong:
+            unlink_me = self.bObject
+            unlink_me.name = "MANTIS_TRASH.000"
+            for col in unlink_me.users_collection:
+                col.objects.unlink(unlink_me)
+            self.bObject = bpy.data.objects.new(self.evaluate_input("Name"), data)
         if self.bObject and (self.inputs["Geometry"].is_linked and self.bObject.type  in ["MESH", "CURVE"]):
             self.bObject.data = trace[-1].node.bGetObject()
         # clear it
         self.bObject.constraints.clear()
-        self.bObject.animation_data_clear() # this is a little dangerous.
-        self.bObject.modifiers.clear()
+        self.bObject.animation_data_clear() # this is a little dangerous. TODO find a better solution since this can wipe animation the user wants to keep
+        self.bObject.modifiers.clear() # I would also like a way to copy modifiers and their settings, or bake them down. oh well
                     
         try:
             bpy.context.collection.objects.link(self.bObject)
@@ -918,7 +944,23 @@ class xFormGeometryObject:
         matrix = self.evaluate_input("Matrix")
         self.parameters['Matrix'] = matrix
         self.bObject.matrix_world = matrix
+        self.prepared = True
+
+    def bExecute(self, bContext = None,):
+        # putting this in bExecute simply prevents it from being run more than once.
+        # maybe I should do that with the rest of bPrepare, too.
+        props_sockets = {
+            'hide_viewport'    : ("Hide in Viewport", False),
+            'hide_render'      : ("Hide in Render", False),
+        }
+        evaluate_sockets(self, self.bObject, props_sockets)
         self.executed = True
+
+    def bFinalize(self, bContext = None):
+        for i, (driver_key, driver_item) in enumerate(self.drivers.items()):
+            print (wrapGreen(i), wrapWhite(self), wrapPurple(driver_key))
+            prOrange(driver_item)
+        finish_drivers(self)
             
         
     def bGetObject(self, mode = 'POSE'):

+ 2 - 0
xForm_definitions.py

@@ -354,6 +354,8 @@ class xFormGeometryObjectNode(Node, xFormNode):
         self.inputs.new('MatrixSocket', "Matrix")
         self.inputs.new('RelationshipSocket', "Relationship")
         self.inputs.new('DeformerSocket', "Deformer")
+        self.inputs.new ("HideSocket", "Hide in Viewport")
+        self.inputs.new ("BooleanSocket", "Hide in Render")
         self.outputs.new('xFormSocket', "xForm Out")
 
         # color