| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302 |
- #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 bpy.app import version as bpy_version
- from .utilities import prRed, prGreen, prPurple
- def version_upgrade_very_old(*args, **kwargs):
- 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: return# major version must be 0
- if current_minor_version > 11: return# minor version must be 12 or less
- # this is the old node update, very inneficient and strange and badly organized
- 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),]
- # 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),
- ]
- rename_jobs = []
- node_tree = kwargs['node_tree']
- try:
- 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)
- except Exception as e:
- prRed(f"Error updating version in node: {node.id_data.name}::{node.name}; see error:")
- print(e)
- 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!
- prPurple(f"Updating \"Bone Collection\" Socket in {node.name}")
- 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:
- prPurple(f"Adding \"Color\" Socket to {node.name}")
- 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)
- def up_0_12_1_add_inherit_color(*args, **kwargs):
- # add an inherit color input.
- node = kwargs['node']
- current_major_version = node.id_data.mantis_version[0]
- current_minor_version = node.id_data.mantis_version[1]
- current_sub_version = node.id_data.mantis_version[2]
- if current_major_version > 0: return# major version must be 0
- if current_minor_version > 12: return# minor version must be 12 or less
- if current_minor_version == 12 and current_sub_version > 9: return # sub version must be 8 or less
- # I am having it do 8 or less because there was a bug in this function prior to 9
- # sub version doesn't matter since any subversion of 11 should trigger this task
- prPurple(f"Adding \"Inherit Color\" socket to {node.name}")
- try:
- inh_color = node.inputs.get('Inherit Color')
- if inh_color and inh_color.bl_idname != 'BooleanSocket':
- node.inputs.remove(inh_color)
- inh_color = None
- if inh_color is None:
- s = node.inputs.new('BooleanSocket', 'Inherit Color',)
- node.inputs.move(len(node.inputs)-1, 23)
- s.default_value=True
- except Exception as e:
- prRed(f"Error updating version in node: {node.id_data.name}::{node.name}; see error:")
- print(e)
- def up_0_12_13_add_widget_scale(*args, **kwargs):
- # add an inherit color input.
- node = kwargs['node']
- current_major_version = node.id_data.mantis_version[0]
- current_minor_version = node.id_data.mantis_version[1]
- current_sub_version = node.id_data.mantis_version[2]
- if current_major_version > 0: return# major version must be 0
- if current_minor_version > 12: return# minor version must be 12 or less
- if current_minor_version == 12 and current_sub_version > 12: return
- # sub version must be 12 or less
- prPurple(f"Adding \"Scale\" socket to {node.name}")
- try:
- scale = node.inputs.get('Scale')
- if scale is None:
- s = node.inputs.new('VectorScaleSocket', 'Scale',)
- s.default_value=[1.0,1.0,1.0]
- node.inputs.move(len(node.inputs)-1, 1)
- except Exception as e:
- prRed(f"Error updating version in node: {node.id_data.name}::{node.name}; see error:")
- print(e)
- # versioning tasks that involve Blender versions rather than Mantis versions:
- error_description_4_5_0_LTS = 'There is a bug in Blender 4.5.0 LTS, that is why these sockets are blue.'\
- ' This will be fixed in future Blender versions.'
- def cleanup_4_5_0_LTS_interface_workaround(*args, **kwargs):
- # this is a function for cleaning up the workaround up above
- tree = kwargs['tree']
- if bpy_version == (4,5,0): return
- if not hasattr(tree, "interface_helper"):
- return
- import json
- try:
- interface_helper = json.loads(tree.interface_helper)
- except:
- return # this should mean it was never a problem to begin with.
- prPurple(f"Restoring Tree Interface for {tree.name}.")
- for interface_item in tree.interface.items_tree:
- if interface_item.item_type == 'PANEL': continue
- # now we need to restore the socket types, which are in the interface helper
- # keep the interface stuff around, I'll use it for marking arrays in the future
- int_info = interface_helper[interface_item.identifier]
- socket_type = int_info['bl_socket_idname']
- interface_item.socket_type = socket_type
- if interface_item.description == error_description_4_5_0_LTS:
- interface_item.description = ''
- # that should be enough!
- def up_0_12_25_replace_floor_offset_type(*args, **kwargs):
- # add an inherit color input.
- node = kwargs['node']
- current_major_version = node.id_data.mantis_version[0]
- current_minor_version = node.id_data.mantis_version[1]
- current_sub_version = node.id_data.mantis_version[2]
- if current_major_version > 0: return# major version must be 0
- if current_minor_version > 12: return# minor version must be 12 or less
- if current_minor_version == 12 and current_sub_version > 24: return
- from .utilities import get_socket_maps, do_relink
- socket_maps = get_socket_maps(node)
- prPurple(f"Fixing \"Offset\" socket in {node.name}")
- try:
- offset = node.inputs["Offset"]
- node.inputs.remove(offset)
- s = node.inputs.new('FloatSocket', 'Offset',)
- node.inputs.move(len(node.inputs)-1, 2)
- do_relink(node, s, socket_maps[0])
- 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
- (['ALL'], version_upgrade_very_old, ['node_tree', 'node'],),
- (['xFormBoneNode'], version_upgrade_bone_0_12_0_from_older, ['node'],),
- (['xFormBoneNode'], up_0_12_1_add_inherit_color, ['node'],),
- (['MantisTree', 'SchemaTree'], cleanup_4_5_0_LTS_interface_workaround, ['tree']),
- (['InputWidget'], up_0_12_13_add_widget_scale, ['node']),
- (['LinkFloor'], up_0_12_25_replace_floor_offset_type, ['node']),
- ]
- # WORKAROUNDS for bugs should go here:
- # 4.5.0 LTS valid socket types bug:
- def workaround_4_5_0_interface_update(tree, name, in_out, sock_type, parent_name, do_parent=False):
- # TODO: dedupe this code from i_o.py
- prRed("There is a bug in Blender 4.5.0 regarding node-group interface sockets. Working around it.")
- sock = tree.interface.new_socket(name=name, in_out=in_out, socket_type="NodeSocketGeometry")
- import json
- interface_helper = {} # initialize it if it is empty
- if tree.interface_helper: # may be empty, check here
- interface_helper = json.loads(tree.interface_helper)
- error_message = error_description_4_5_0_LTS
- interface_helper[sock.identifier] = {
- 'name' : sock.name,
- 'identifier' : sock.identifier,
- 'in_out' : sock.in_out,
- 'socket_type' : sock_type,
- 'bl_socket_idname' : sock_type,
- 'mantis_socket_category' : parent_name,
- 'description' : error_message,
- }
- sock.description = error_message # this tells the user why the socket looks weird.
- tree.interface_helper = json.dumps(interface_helper)
- if do_parent and (parent := tree.interface.items_tree.get(parent_name)):
- tree.interface.move_to_parent(
- sock,
- parent,
- 0, # what to do here?
- )
- return sock
- def socket_add_workaround_for_4_5_0_LTS(item, socket_collection, multi):
- import json
- tree = item.id_data
- interface_helper = json.loads(tree.interface_helper)
- socket_info = interface_helper.get(item.identifier)
- if not socket_info: raise RuntimeError(f"There has been an error adding the socket {item.name}")
- s = socket_collection.new(
- type=socket_info['bl_socket_idname'],
- name=item.name, # in case the user has changed it
- identifier=item.identifier,
- use_multi_input=multi, )
- return s
|