Эх сурвалжийг харах

Fix: Versioning for Rename & Driven Parameter

Needed to update LinkDrivenParameter to use the common socket evaluation
code in evaluate_sockets(). This also required an update to the
versioning code to do socket renaming.
Joseph Brandenburg 8 сар өмнө
parent
commit
da30369c13

+ 68 - 26
__init__.py

@@ -17,7 +17,7 @@ from .utilities import prRed
 
 MANTIS_VERSION_MAJOR=0
 MANTIS_VERSION_MINOR=9
-MANTIS_VERSION_SUB=9
+MANTIS_VERSION_SUB=10
 
 
 classLists = [module.TellClasses() for module in [
@@ -128,6 +128,7 @@ utility_category = [
         NodeItem("UtilityChoose"),
         NodeItem("UtilityCompare"),
         NodeItem("UtilityPrint"),
+        NodeItem("UtilitySeparateVector"),
     ]
 matrix_category = [
         NodeItem("UtilityMetaRig"),
@@ -239,39 +240,80 @@ def execute_handler(scene):
                 node_tree.tree_valid = False
 
 
+
+def do_version_update(node_tree):
+    from .base_definitions import NODES_REMOVED, SOCKETS_REMOVED, SOCKETS_RENAMED, SOCKETS_ADDED
+    node_tree.mantis_version[0] = MANTIS_VERSION_MAJOR
+    node_tree.mantis_version[1] = MANTIS_VERSION_MINOR
+    node_tree.mantis_version[2] = MANTIS_VERSION_SUB
+    for n in node_tree.nodes:
+        rename_jobs = []
+
+        if n.bl_idname in NODES_REMOVED:
+            print(f"INFO: removing node {n.name} of type {n.bl_idname} because it has been deprecated.")
+            n.inputs.remove(socket)
+            continue
+        for i, socket in enumerate(n.inputs.values()):
+            if (n.bl_idname, socket.identifier) in SOCKETS_REMOVED:
+                print(f"INFO: removing socket {socket.identifier} of node {n.name} of type {n.bl_idname} because it has been deprecated.")
+                n.inputs.remove(socket)
+            for old_class, old_bl_idname, old_name, new_bl_idname, new_name, multi in SOCKETS_RENAMED:
+                if (n.bl_idname == old_class and socket.bl_idname == old_bl_idname and socket.name == old_name):
+                    rename_jobs.append((socket, i, new_bl_idname, new_name, multi))
+        for i, socket in enumerate(n.outputs.values()):
+            if (n.bl_idname, socket.identifier) in SOCKETS_REMOVED:
+                print(f"INFO: removing socket {socket.identifier} of node {n.name} of type {n.bl_idname} because it has been deprecated.")
+                n.outputs.remove(socket)
+            for old_class, old_bl_idname, old_name, new_bl_idname, new_name, multi in SOCKETS_RENAMED:
+                if (n.bl_idname == old_class and socket.bl_idname == old_bl_idname and socket.name == old_name):
+                    rename_jobs.append((socket, i, new_bl_idname, new_name, multi))
+
+        for bl_idname, in_out, socket_type, socket_name, index, use_multi_input, default_val in SOCKETS_ADDED:
+            if n.bl_idname != bl_idname:
+                continue
+            if in_out == 'INPUT' and n.inputs.get(socket_name) is None:
+                print(f"INFO: adding socket \"{socket_name}\" of type {socket_type} to node {n.name} of type {n.bl_idname}.")
+                s = n.inputs.new(socket_type, socket_name, use_multi_input=use_multi_input)
+                s.default_value = default_val
+                n.inputs.move(len(n.inputs), index)
+        socket_map = None
+        if rename_jobs:
+            from .utilities import get_socket_maps
+            socket_maps = get_socket_maps(n)
+        for socket, socket_index, new_bl_idname, new_name, multi in rename_jobs:
+            old_id = socket.identifier
+            print (f"Renaming socket {socket.identifier} to {new_name} in node {n.name}")
+            from .utilities import do_relink
+            if socket.is_output:
+                index = 1
+                in_out = "OUTPUT"
+                n.outputs.remove(socket)
+                s = n.outputs.new(new_bl_idname, new_name, identifier=new_name, use_multi_input=multi)
+                n.outputs.move(len(n.outputs)-1, socket_index)
+                socket_map = socket_maps[1]
+            else:
+                index = 0
+                in_out = "INPUT"
+                n.inputs.remove(socket)
+                s = n.inputs.new(new_bl_idname, new_name, identifier=new_name, use_multi_input=multi)
+                n.inputs.move(len(n.inputs)-1, socket_index)
+                socket_map = socket_maps[0]
+
+            socket_map[new_name] = socket_map[old_id]; del socket_map[old_id]
+
+            do_relink(n, s, socket_map)
+
+
+
 @persistent
 def version_update_handler(filename):
-    from .base_definitions import NODES_REMOVED, SOCKETS_REMOVED, SOCKETS_RENAMED, SOCKETS_ADDED
     for node_tree in bpy.data.node_groups:
         if node_tree.bl_idname in ["MantisTree", "SchemaTree"]:
             if (node_tree.mantis_version[0] < MANTIS_VERSION_MAJOR) or \
                (node_tree.mantis_version[1] < MANTIS_VERSION_MINOR) or \
                (node_tree.mantis_version[2] < MANTIS_VERSION_SUB):
                 print (f"Updating tree {node_tree.name} to {MANTIS_VERSION_MAJOR}.{MANTIS_VERSION_MINOR}.{MANTIS_VERSION_SUB}")
-                node_tree.mantis_version[0] = MANTIS_VERSION_MAJOR
-                node_tree.mantis_version[1] = MANTIS_VERSION_MINOR
-                node_tree.mantis_version[2] = MANTIS_VERSION_SUB
-                for n in node_tree.nodes:
-                    if n.bl_idname in NODES_REMOVED:
-                        print(f"INFO: removing node {n.name} of type {n.bl_idname} because it has been deprecated.")
-                        n.inputs.remove(socket)
-                        continue
-                    for socket in n.inputs.values():
-                        if (n.bl_idname, socket.identifier) in SOCKETS_REMOVED:
-                            print(f"INFO: removing socket {socket.identifier} of node {n.name} of type {n.bl_idname} because it has been deprecated.")
-                            n.inputs.remove(socket)
-                    for socket in n.outputs.values():
-                        if (n.bl_idname, socket.identifier) in SOCKETS_REMOVED:
-                            print(f"INFO: removing socket {socket.identifier} of node {n.name} of type {n.bl_idname} because it has been deprecated.")
-                            n.outputs.remove(socket)
-                    for bl_idname, in_out, socket_type, socket_name, index, use_multi_input, default_val in SOCKETS_ADDED:
-                        if n.bl_idname != bl_idname:
-                            continue
-                        if in_out == 'INPUT' and n.inputs.get(socket_name) is None:
-                            print(f"INFO: adding socket \"{socket_name}\" of type {socket_type} to node {n.name} of type {n.bl_idname}.")
-                            s = n.inputs.new(socket_type, socket_name, use_multi_input=use_multi_input)
-                            s.default_value = default_val
-                            n.inputs.move(len(n.inputs), index)
+                do_version_update(node_tree)
                 
                 
 

+ 7 - 3
base_definitions.py

@@ -352,10 +352,14 @@ class SchemaGroup(Node, MantisNode):
 
 
 NODES_REMOVED=["xFormRootNode"]
-SOCKETS_REMOVED=[("UtilityDriverVariable","Transform Channel"),
+                 # Node bl_idname, # Socket Name
+SOCKETS_REMOVED=[("UtilityDriverVariable", "Transform Channel"),
                  ("xFormRootNode","World Out"),
-                 ("UtilitySwitch","xForm")]
-SOCKETS_RENAMED=[]
+                 ("UtilitySwitch","xForm"),
+                 ("LinkDrivenParameter", "Enable")]
+                  # Node Class           #Prior bl_idname  # prior name # new bl_idname # new name, # Multi
+SOCKETS_RENAMED=[ ("LinkDrivenParameter", "DriverSocket",   "Driver",     "FloatSocket",  "Value",  False)]
+
                 # NODE CLASS NAME             IN_OUT    SOCKET TYPE     SOCKET NAME     INDEX   MULTI     DEFAULT
 SOCKETS_ADDED=[("DeformerMorphTargetDeform", 'INPUT', 'BooleanSocket', "Use Shape Key", 1,      False,    False),
                ("DeformerMorphTargetDeform", 'INPUT', 'BooleanSocket', "Use Offset", 2,         False,     True),]

+ 1 - 1
blender_manifest.toml

@@ -3,7 +3,7 @@ schema_version = "1.0.0"
 # Example of manifest file for a Blender extension
 # Change the values according to your extension
 id = "mantis"
-version = "0.9.9"
+version = "0.9.10"
 name = "Mantis"
 tagline = "Mantis is a rigging nodes toolkit"
 maintainer = "Nodespaghetti <josephbburg@protonmail.com>"

+ 57 - 46
link_containers.py

@@ -1649,29 +1649,26 @@ class LinkDrivenParameter:
         self.executed = False
         self.signature = signature
         self.inputs = {
-        "Input Relationship" : NodeSocket(is_input = True, name = "Input Relationship", node = self,),
-          "Driver"      : NodeSocket(is_input = True, name = "Driver", node = self),
-          "Parameter"   : NodeSocket(is_input = True, name = "Parameter", node = self),
-          "Index"       : NodeSocket(is_input = True, name = "Index", node = self),
+            "Input Relationship" : NodeSocket(is_input = True, name = "Input Relationship", node = self,),
+            "Value"      : NodeSocket(is_input = True, name = "Value", node = self),
+            "Parameter"   : NodeSocket(is_input = True, name = "Parameter", node = self),
+            "Index"       : NodeSocket(is_input = True, name = "Index", node = self),
         }
         self.outputs = {
-          "Output Relationship" : NodeSocket(name = "Output Relationship", node=self), }
+            "Output Relationship" : NodeSocket(name = "Output Relationship", node=self), }
         self.parameters = {
-          "Input Relationship":None, 
-          "Driver":None, 
-          "Parameter":None,
-          "Index":None,
+            "Input Relationship":None, 
+            "Value":None, 
+            "Parameter":None,
+            "Index":None,
         }
         # now set up the traverse target...
         self.inputs["Input Relationship"].set_traverse_target(self.outputs["Output Relationship"])
         self.outputs["Output Relationship"].set_traverse_target(self.inputs["Input Relationship"])
         self.node_type = "LINK"
-        self.hierarchy_connections = []
-        self.connections = []
-        self.hierarchy_dependencies = []
-        self.dependencies = []
-        self.prepared = True
-        self.executed = False
+        self.hierarchy_connections,self.connections = [], []
+        self.hierarchy_dependencies, self.dependencies = [], []
+        self.prepared, self.executed = True, False
 
     def GetxForm(self):
         return GetxForm(self)
@@ -1682,28 +1679,48 @@ class LinkDrivenParameter:
     def bExecute(self, bContext = None,):
         prepare_parameters(self)
         prGreen("Executing Driven Parameter node")
-        
-        # example_ driver ={
-                    # "owner":None,
-                    # "prop":None, # will be filled out in the node that uses the driver
-                    # "ind":-1, # same here
-                    # "type": self.evaluate_input("Driver Type"),
-                    # "vars": my_vars,
-                    # "keys": self.evaluate_input("fCurve"),}
-                    
-        driver = self.evaluate_input("Driver")
-        driver["owner"] = self.GetxForm().bGetObject()
-        driver["prop"] = self.evaluate_input("Parameter")
-        driver["ind"] = self.evaluate_input("Index")
-        
-        self.parameters["Driver"] = driver
+        prop = self.evaluate_input("Parameter")
+        index = self.evaluate_input("Index")
+        value = self.evaluate_input("Value")
+        xf = self.GetxForm()
+        ob = xf.bGetObject(mode="POSE")
+        # IMPORTANT: this node only works on pose bone attributes.
+        self.bObject = ob
+        length=1
+        if hasattr(ob, prop):
+            try:
+                length = len(getattr(ob, prop))
+            except TypeError:
+                pass
+            except AttributeError:
+                pass
+        else:
+            raise AttributeError(f"Cannot Set value {prop} on object because it does not exist.")
+        def_value = 0.0
+        if length>1:
+            def_value=[0.0]*length
+            self.parameters["Value"] = tuple( 0.0 if i != index else value for i in range(length))
+
+        props_sockets = {
+            prop: ("Value", def_value)
+        }
+        evaluate_sockets(self, ob, props_sockets)
+
         self.executed = True
 
     def bFinalize(self, bContext = None):
-        # TODO HACK BUG
-        # This probably no longer works
-        from .drivers import CreateDrivers
-        CreateDrivers( [ self.parameters["Driver"] ] )
+        driver = self.evaluate_input("Value")
+        try:
+            for i, val in enumerate(self.parameters["Value"]):
+                from .drivers import MantisDriver
+                if isinstance(val, MantisDriver):
+                    driver["ind"] = i
+                    val = driver
+        except AttributeError:
+            self.parameters["Value"] = driver
+        except TypeError:
+            self.parameters["Value"] = driver
+        finish_drivers(self)
         
 
         
@@ -1737,12 +1754,9 @@ class LinkArmature:
         self.outputs["Output Relationship"].set_traverse_target(self.inputs["Input Relationship"])
         self.node_type = "LINK"
         setup_custom_props(self)
-        self.hierarchy_connections = []
-        self.connections = []
-        self.hierarchy_dependencies = []
-        self.dependencies = []
-        self.prepared = True
-        self.executed = False
+        self.hierarchy_connections,self.connections = [], []
+        self.hierarchy_dependencies, self.dependencies = [], []
+        self.prepared, self.executed = True, False
 
 
     def GetxForm(self):
@@ -1831,12 +1845,9 @@ class LinkSplineIK:
         self.inputs["Input Relationship"].set_traverse_target(self.outputs["Output Relationship"])
         self.outputs["Output Relationship"].set_traverse_target(self.inputs["Input Relationship"])
         self.node_type = "LINK"
-        self.hierarchy_connections = []
-        self.connections = []
-        self.hierarchy_dependencies = []
-        self.dependencies = []
-        self.prepared = True
-        self.executed = False
+        self.hierarchy_connections,self.connections = [], []
+        self.hierarchy_dependencies, self.dependencies = [], []
+        self.prepared, self.executed = True, False
 
     def evaluate_input(self, input_name):
         return default_evaluate_input(self, input_name)

+ 1 - 1
link_definitions.py

@@ -684,7 +684,7 @@ class LinkDrivenParameterNode(Node, LinkNode):
     
     def init(self, context):
         self.inputs.new ( "RelationshipSocket", "Input Relationship" )
-        self.inputs.new ( "DriverSocket", "Driver" )
+        self.inputs.new ( "FloatSocket", "Value" )
         self.inputs.new ( "ParameterStringSocket", "Parameter" )
         self.inputs.new ( "IntSocket", "Index" )
         self.inputs.new ('EnableSocket', "Enable")

+ 3 - 3
utilities.py

@@ -260,17 +260,17 @@ def update_interface(interface, name, in_out, sock_type, parent_name):
     else:
         raise RuntimeError(wrapRed("Cannot add interface item to tree without specifying type."))
 
-def relink_socket_map(node, node_collection, map, item, in_out=None):
+def relink_socket_map(node, socket_collection, map, item, in_out=None):
     from bpy.types import NodeSocket
     if not in_out: in_out=item.in_out
     if node.bl_idname in ['MantisSchemaGroup'] and item.parent and item.parent.name == 'Array':
         multi = False
         if in_out == 'INPUT':
             multi=True
-        s = node_collection.new(type=item.socket_type, name=item.name, identifier=item.identifier,  use_multi_input=multi)
+        s = socket_collection.new(type=item.socket_type, name=item.name, identifier=item.identifier,  use_multi_input=multi)
         # s.link_limit = node.schema_length TODO
     else:
-        s = node_collection.new(type=item.socket_type, name=item.name, identifier=item.identifier)
+        s = socket_collection.new(type=item.socket_type, name=item.name, identifier=item.identifier)
     if item.parent.name == 'Array': s.display_shape = 'SQUARE_DOT'
     do_relink(node, s, map)