Ver Fonte

v0.12.0 new task-based versioning system

This commit introduces a new, more robust versioning system
based on tasks. It is fairly rudimentary but should be more future-proof
than the old way that assumed I would make no mistakes...

Because this commit breaks versioning in a minor way, it is a new minor version
Joseph Brandenburg há 3 meses atrás
pai
commit
b4127de248
5 ficheiros alterados com 91 adições e 110 exclusões
  1. 27 78
      __init__.py
  2. 0 30
      base_definitions.py
  3. 1 1
      blender_manifest.toml
  4. 8 1
      i_o.py
  5. 55 0
      versioning.py

+ 27 - 78
__init__.py

@@ -17,8 +17,8 @@ from .ops_generate_tree import GenerateMantisTree
 from .utilities import prRed
 
 MANTIS_VERSION_MAJOR=0
-MANTIS_VERSION_MINOR=11
-MANTIS_VERSION_SUB=22
+MANTIS_VERSION_MINOR=12
+MANTIS_VERSION_SUB=0
 
 classLists = [module.TellClasses() for module in [
  link_definitions,
@@ -261,89 +261,39 @@ def execute_handler(scene):
                 node_tree.execute_tree(context)
                 node_tree.tree_valid=False
 
-versioning_node_tasks = [
-    #relevant bl_idnames      # task
-    #(['LinkTransformation'], transformation_constraint_radians_to_degrees)
-]
-
-
-def node_version_update(node_tree, node):
-    from .base_definitions import NODES_REMOVED, SOCKETS_REMOVED, SOCKETS_RENAMED, SOCKETS_ADDED
-    rename_jobs = []
-    if node.bl_idname in NODES_REMOVED:
-        print(f"INFO: removing node {node.name} of type {node.bl_idname} because it has been deprecated.")
-        node.inputs.remove(socket)
-        return
-    for i, socket in enumerate(node.inputs.values()):
-        if (node.bl_idname, socket.identifier) in SOCKETS_REMOVED:
-            print(f"INFO: removing socket {socket.identifier} of node {node.name} of type {node.bl_idname} because it has been deprecated.")
-            node.inputs.remove(socket)
-        for old_class, old_bl_idname, old_name, new_bl_idname, new_name, multi in SOCKETS_RENAMED:
-            if (node.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(node.outputs.values()):
-        if (node.bl_idname, socket.identifier) in SOCKETS_REMOVED:
-            print(f"INFO: removing socket {socket.identifier} of node {node.name} of type {node.bl_idname} because it has been deprecated.")
-            node.outputs.remove(socket)
-        for old_class, old_bl_idname, old_name, new_bl_idname, new_name, multi in SOCKETS_RENAMED:
-            if (node.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 node.bl_idname != bl_idname:
-            continue
-        if in_out == 'INPUT' and node.inputs.get(socket_name) is None:
-            print(f"INFO: adding socket \"{socket_name}\" of type {socket_type} to node {node.name} of type {node.bl_idname}.")
-            s = node.inputs.new(socket_type, socket_name, use_multi_input=use_multi_input)
-            try:
-                s.default_value = default_val
-            except AttributeError:
-                pass # the socket is read-only
-            node.inputs.move(len(node.inputs)-1, index)
-    socket_map = None
-    if rename_jobs:
-        from .utilities import get_socket_maps
-        socket_maps = get_socket_maps(node)
-    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 {node.name}")
-        from .utilities import do_relink
-        if socket.is_output:
-            index = 1
-            in_out = "OUTPUT"
-            node.outputs.remove(socket)
-            s = node.outputs.new(new_bl_idname, new_name, identifier=new_name, use_multi_input=multi)
-            node.outputs.move(len(node.outputs)-1, socket_index)
-            socket_map = socket_maps[1]
-        else:
-            index = 0
-            in_out = "INPUT"
-            node.inputs.remove(socket)
-            s = node.inputs.new(new_bl_idname, new_name, identifier=new_name, use_multi_input=multi)
-            node.inputs.move(len(node.inputs)-1, socket_index)
-            socket_map = socket_maps[0]
-        socket_map[new_name] = socket_map[old_id]
-        if new_name != old_id: del socket_map[old_id] # sometimes rename just changes the socket type or multi
-        do_relink(node, s, socket_map)
-    for bl_idname, task in versioning_node_tasks:
-        if node.bl_idname in bl_idname: task(node)
-
+from .versioning import versioning_tasks
+def node_version_update(node):
+    do_once = True
+    do_tasks = []
+    for bl_idname, task, required_kwargs in versioning_tasks:
+        arg_map = {}
+        if 'node' in required_kwargs:
+            arg_map['node']=node
+        if node.bl_idname in bl_idname:
+            task(**arg_map)
+            if do_once:
+                print (f"Updating tree {node.id_data.name} to "
+                       f"{MANTIS_VERSION_MAJOR}.{MANTIS_VERSION_MINOR}.{MANTIS_VERSION_SUB}")
+                do_once=False
 
 def do_version_update(node_tree):
+    # set updating status for dynamic nodes to prevent bugs in socket remapping
     for node in node_tree.nodes:
-        try:
-            node_version_update(node_tree, node)
-        except Exception as e:
-            prRed(f"Error updating version in node: {node_tree.name}::{node.name}; see error:")
-            print(e)
-            pass
+        if hasattr(node, 'is_updating'):
+            node.is_updating = True
+    # run the updates that have no prerequisites
+    for node in node_tree.nodes:
+        node_version_update(node)
+    # NOTE: if future versoning tasks have prerequisites, resolve them here and update again
+    # reset the updating status for dynamic nodes
+    for node in node_tree.nodes:
+        if hasattr(node, 'is_updating'):
+            node.is_updating = False
     # increment the version at the end
     node_tree.mantis_version[0] = MANTIS_VERSION_MAJOR
     node_tree.mantis_version[1] = MANTIS_VERSION_MINOR
     node_tree.mantis_version[2] = MANTIS_VERSION_SUB
 
-
-
 @persistent
 def version_update_handler(filename):
     for node_tree in bpy.data.node_groups: # ensure it can update again after file load.
@@ -355,7 +305,6 @@ def version_update_handler(filename):
             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}")
                 do_version_update(node_tree)
                 
 

+ 0 - 30
base_definitions.py

@@ -594,36 +594,6 @@ class SchemaGroup(Node, MantisUINode):
             self.is_updating = False
             self.id_data.do_live_update = live_update # ensure this remains the same
 
-
-
-NODES_REMOVED=["xFormRootNode"]
-                 # Node bl_idname, # Socket Name
-SOCKETS_REMOVED=[("UtilityDriverVariable", "Transform Channel"),
-                 ("xFormRootNode","World Out"),
-                 ("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),
-                  ("DeformerHook",        "IntSocket",      "Index",      "UnsignedIntSocket",  "Point Index",        False),
-                  ("SchemaConstOutput",   "IntSocket",      "Expose when N==",      "UnsignedIntSocket",  "Expose at Index", False),
-                  ("xFormBoneNode",   "BoneCollectionSocket",      "Bone Collection",      "BoneCollectionSocket",  "Bone Collection", True),]
-
-                # 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),
-               ("UtilityFCurve",             'INPUT',  "eFCrvExtrapolationMode", "Extrapolation Mode", 0, False, 'CONSTANT'),
-               ("LinkCopyScale",             'INPUT',  "BooleanSocket", "Additive",     3,      False,    False),
-               ("DeformerHook",              'INPUT',  "FloatFactorSocket", "Influence",3,      False,    1.0),
-               ("DeformerHook",              'INPUT',  "UnsignedIntSocket", "Spline Index", 2,  False,    0),
-               ("DeformerHook",              'INPUT',  "BooleanSocket", "Auto-Bezier",  5,      False,    True),
-               ("UtilityCompare",            'INPUT',  "EnumCompareOperation", "Comparison", 0, False,    'EQUAL'),
-               ("UtilityMatrixFromCurve",    'INPUT',  "UnsignedIntSocket", "Spline Index",  1, False,    0),
-               ("UtilityMatricesFromCurve",  'INPUT',  "UnsignedIntSocket", "Spline Index",  1, False,    0),
-               ("UtilityPointFromCurve",     'INPUT',  "UnsignedIntSocket", "Spline Index",  1, False,    0),
-               ("LinkCopyScale",             'INPUT',  "FloatFactorSocket", "Power",    5,      False,    1.0),
-               ("xFormBoneNode",             'INPUT',  "ColorSetSocket",    "Color",    22,     False,    None,),
-               ]
-
 # replace names with bl_idnames for reading the tree and solving schemas.
 replace_types = ["NodeGroupInput", "NodeGroupOutput", "SchemaIncomingConnection",
                  "SchemaArrayInput", "SchemaArrayInputAll", "SchemaConstInput", "SchemaConstOutput",

+ 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.11.22"
+version = "0.12.0"
 name = "Mantis"
 tagline = "Mantis is a rigging nodes toolkit"
 maintainer = "Nodespaghetti <josephbburg@protonmail.com>"

+ 8 - 1
i_o.py

@@ -7,7 +7,14 @@ from .utilities import (prRed, prGreen, prPurple, prWhite,
 
 from mathutils import  Vector
 
-from .base_definitions import NODES_REMOVED, SOCKETS_REMOVED
+NODES_REMOVED=["xFormRootNode"]
+                 # Node bl_idname, # Socket Name
+SOCKETS_REMOVED=[("UtilityDriverVariable", "Transform Channel"),
+                 ("xFormRootNode","World Out"),
+                 ("UtilitySwitch","xForm"),
+                 ("LinkDrivenParameter", "Enable")]
+                  # Node Class           #Prior bl_idname  # prior name # new bl_idname #       new name,          # Multi
+
 from bpy.app import version
 
 add_inputs_bl_idnames = [

+ 55 - 0
versioning.py

@@ -0,0 +1,55 @@
+#Versioning Tasks
+# this will be the new versioning system, and will deprecate the old SOCKETS_ADDED and such
+
+from bpy.types import Node, NodeSocket
+from .utilities import prRed, prGreen
+
+
+def version_upgrade_bone_0_12_0_from_older(*args, **kwargs):
+    # we need to check if it has an array collection input and a color input
+    # then we need to solve each task
+    node = kwargs['node']
+    current_major_version = node.id_data.mantis_version[0]
+    current_minor_version = node.id_data.mantis_version[1]
+    if  current_major_version > 0: # major version must be 0
+        return
+    if current_minor_version >= 12: # minor version must be 11 or less
+        return
+    # sub version doesn't matter since any subversion of 11 should trigger this task
+    try:
+        collection_input_is_array = node.inputs['Bone Collection'].is_multi_input
+        if not collection_input_is_array: # it must be made into an array!
+            from .utilities import get_socket_maps
+            socket_maps = get_socket_maps(node)
+            socket_map = socket_maps[0]
+            for i, socket in enumerate(node.inputs):
+                if socket.name == 'Bone Collection': break
+            old_id = socket.identifier
+            # it is an input
+            node.inputs.remove(socket)
+            s = node.inputs.new('BoneCollectionSocket', 'Bone Collection',
+                                identifier='Bone Collection', use_multi_input=True)
+            node.inputs.move(len(node.inputs)-1, i)
+            socket_map_from_old_socket = socket_map[old_id]
+            # there seems to be an error in do_relink
+            # gonna do it directly instead
+            if isinstance(socket_map_from_old_socket, list):
+                for map_info in socket_map_from_old_socket:
+                    if isinstance(map_info, Node ):
+                        l = node.id_data.links.new(input=map_info.outputs[0], output=s)
+                    elif isinstance(map_info, NodeSocket):
+                        l = node.id_data.links.new(input=map_info, output=s)
+            else:
+                s.default_value = socket_map_from_old_socket
+        if node.inputs.get('Color') is None:
+            s = node.inputs.new('ColorSetSocket', 'Color',)
+            node.inputs.move(len(node.inputs)-1, 22)
+    except Exception as e:
+        prRed(f"Error updating version in node: {node.id_data.name}::{node.name}; see error:")
+        print(e)
+
+
+versioning_tasks = [
+    # node bl_idname    task                required keyword arguments 
+    (['xFormBoneNode'], version_upgrade_bone_0_12_0_from_older, ['node'],),
+]