versioning.py 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456
  1. #Versioning Tasks
  2. # this will be the new versioning system, and will deprecate the old SOCKETS_ADDED and such
  3. from bpy.types import Node, NodeSocket
  4. from bpy.app import version as bpy_version
  5. from .utilities.utilities import (prRed, prGreen, prPurple, prWhite,
  6. prOrange,
  7. wrapRed, wrapGreen, wrapPurple, wrapWhite,
  8. wrapOrange,
  9. get_socket_maps, do_relink, )
  10. def version_upgrade_very_old(*args, **kwargs):
  11. node = kwargs['node']
  12. current_major_version = node.id_data.mantis_version[0]
  13. current_minor_version = node.id_data.mantis_version[1]
  14. if current_major_version > 0: return# major version must be 0
  15. if current_minor_version > 11: return# minor version must be 12 or less
  16. # this is the old node update, very inneficient and strange and badly organized
  17. NODES_REMOVED=["xFormRootNode"]
  18. # Node bl_idname, # Socket Name
  19. SOCKETS_REMOVED=[("UtilityDriverVariable", "Transform Channel"),
  20. ("xFormRootNode","World Out"),
  21. ("UtilitySwitch","xForm"),
  22. ("LinkDrivenParameter", "Enable")]
  23. # Node Class #Prior bl_idname # prior name # new bl_idname # new name, # Multi
  24. SOCKETS_RENAMED=[ ("LinkDrivenParameter", "DriverSocket", "Driver", "FloatSocket", "Value", False),
  25. ("DeformerHook", "IntSocket", "Index", "UnsignedIntSocket", "Point Index", False),
  26. ("SchemaConstOutput", "IntSocket", "Expose when N==", "UnsignedIntSocket", "Expose at Index", False),]
  27. # NODE CLASS NAME IN_OUT SOCKET TYPE SOCKET NAME INDEX MULTI DEFAULT
  28. SOCKETS_ADDED=[("DeformerMorphTargetDeform", 'INPUT', 'BooleanSocket', "Use Shape Key", 1, False, False),
  29. ("DeformerMorphTargetDeform", 'INPUT', 'BooleanSocket', "Use Offset", 2, False, True),
  30. ("UtilityFCurve", 'INPUT', "eFCrvExtrapolationMode", "Extrapolation Mode", 0, False, 'CONSTANT'),
  31. ("LinkCopyScale", 'INPUT', "BooleanSocket", "Additive", 3, False, False),
  32. ("DeformerHook", 'INPUT', "FloatFactorSocket", "Influence",3, False, 1.0),
  33. ("DeformerHook", 'INPUT', "UnsignedIntSocket", "Spline Index", 2, False, 0),
  34. ("DeformerHook", 'INPUT', "BooleanSocket", "Auto-Bezier", 5, False, True),
  35. ("UtilityCompare", 'INPUT', "EnumCompareOperation", "Comparison", 0, False, 'EQUAL'),
  36. ("UtilityMatrixFromCurve", 'INPUT', "UnsignedIntSocket", "Spline Index", 1, False, 0),
  37. ("UtilityMatricesFromCurve", 'INPUT', "UnsignedIntSocket", "Spline Index", 1, False, 0),
  38. ("UtilityPointFromCurve", 'INPUT', "UnsignedIntSocket", "Spline Index", 1, False, 0),
  39. ("LinkCopyScale", 'INPUT', "FloatFactorSocket", "Power", 5, False, 1.0),
  40. ]
  41. rename_jobs = []
  42. node_tree = kwargs['node_tree']
  43. try:
  44. if node.bl_idname in NODES_REMOVED:
  45. print(f"INFO: removing node {node.name} of type {node.bl_idname} because it has been deprecated.")
  46. node.inputs.remove(socket)
  47. return
  48. for i, socket in enumerate(node.inputs.values()):
  49. if (node.bl_idname, socket.identifier) in SOCKETS_REMOVED:
  50. print(f"INFO: removing socket {socket.identifier} of node {node.name} of type {node.bl_idname} because it has been deprecated.")
  51. node.inputs.remove(socket)
  52. for old_class, old_bl_idname, old_name, new_bl_idname, new_name, multi in SOCKETS_RENAMED:
  53. if (node.bl_idname == old_class and socket.bl_idname == old_bl_idname and socket.name == old_name):
  54. rename_jobs.append((socket, i, new_bl_idname, new_name, multi))
  55. for i, socket in enumerate(node.outputs.values()):
  56. if (node.bl_idname, socket.identifier) in SOCKETS_REMOVED:
  57. print(f"INFO: removing socket {socket.identifier} of node {node.name} of type {node.bl_idname} because it has been deprecated.")
  58. node.outputs.remove(socket)
  59. for old_class, old_bl_idname, old_name, new_bl_idname, new_name, multi in SOCKETS_RENAMED:
  60. if (node.bl_idname == old_class and socket.bl_idname == old_bl_idname and socket.name == old_name):
  61. rename_jobs.append((socket, i, new_bl_idname, new_name, multi))
  62. for bl_idname, in_out, socket_type, socket_name, index, use_multi_input, default_val in SOCKETS_ADDED:
  63. if node.bl_idname != bl_idname:
  64. continue
  65. if in_out == 'INPUT' and node.inputs.get(socket_name) is None:
  66. print(f"INFO: adding socket \"{socket_name}\" of type {socket_type} to node {node.name} of type {node.bl_idname}.")
  67. s = node.inputs.new(socket_type, socket_name, use_multi_input=use_multi_input)
  68. try:
  69. s.default_value = default_val
  70. except AttributeError:
  71. pass # the socket is read-only
  72. node.inputs.move(len(node.inputs)-1, index)
  73. socket_map = None
  74. if rename_jobs:
  75. socket_maps = get_socket_maps(node)
  76. for socket, socket_index, new_bl_idname, new_name, multi in rename_jobs:
  77. old_id = socket.identifier
  78. print (f"Renaming socket {socket.identifier} to {new_name} in node {node.name}")
  79. if socket.is_output:
  80. index = 1
  81. in_out = "OUTPUT"
  82. node.outputs.remove(socket)
  83. s = node.outputs.new(new_bl_idname, new_name, identifier=new_name, use_multi_input=multi)
  84. node.outputs.move(len(node.outputs)-1, socket_index)
  85. socket_map = socket_maps[1]
  86. else:
  87. index = 0
  88. in_out = "INPUT"
  89. node.inputs.remove(socket)
  90. s = node.inputs.new(new_bl_idname, new_name, identifier=new_name, use_multi_input=multi)
  91. node.inputs.move(len(node.inputs)-1, socket_index)
  92. socket_map = socket_maps[0]
  93. socket_map[new_name] = socket_map[old_id]
  94. if new_name != old_id: del socket_map[old_id] # sometimes rename just changes the socket type or multi
  95. do_relink(node, s, socket_map)
  96. except Exception as e:
  97. prRed(f"Error updating version in node: {node.id_data.name}::{node.name}; see error:")
  98. print(e)
  99. def version_upgrade_bone_0_12_0_from_older(*args, **kwargs):
  100. # we need to check if it has an array collection input and a color input
  101. # then we need to solve each task
  102. node = kwargs['node']
  103. current_major_version = node.id_data.mantis_version[0]
  104. current_minor_version = node.id_data.mantis_version[1]
  105. if current_major_version > 0: # major version must be 0
  106. return
  107. if current_minor_version >= 12: # minor version must be 11 or less
  108. return
  109. # sub version doesn't matter since any subversion of 11 should trigger this task
  110. try:
  111. collection_input_is_array = node.inputs['Bone Collection'].is_multi_input
  112. if not collection_input_is_array: # it must be made into an array!
  113. prPurple(f"Updating \"Bone Collection\" Socket in {node.name}")
  114. from .utilities.utilities import get_socket_maps
  115. socket_maps = get_socket_maps(node)
  116. socket_map = socket_maps[0]
  117. for i, socket in enumerate(node.inputs):
  118. if socket.name == 'Bone Collection': break
  119. old_id = socket.identifier
  120. # it is an input
  121. node.inputs.remove(socket)
  122. s = node.inputs.new('BoneCollectionSocket', 'Bone Collection',
  123. identifier='Bone Collection', use_multi_input=True)
  124. node.inputs.move(len(node.inputs)-1, i)
  125. do_relink(node, s, socket_map, in_out='INPUT')
  126. if node.inputs.get('Color') is None:
  127. prPurple(f"Adding \"Color\" Socket to {node.name}")
  128. s = node.inputs.new('ColorSetSocket', 'Color',)
  129. node.inputs.move(len(node.inputs)-1, 22)
  130. except Exception as e:
  131. prRed(f"Error updating version in node: {node.id_data.name}::{node.name}; see error:")
  132. print(e)
  133. def up_0_12_1_add_inherit_color(*args, **kwargs):
  134. # add an inherit color input.
  135. node = kwargs['node']
  136. current_major_version = node.id_data.mantis_version[0]
  137. current_minor_version = node.id_data.mantis_version[1]
  138. current_sub_version = node.id_data.mantis_version[2]
  139. if current_major_version > 0: return# major version must be 0
  140. if current_minor_version > 12: return# minor version must be 12 or less
  141. if current_minor_version == 12 and current_sub_version > 9: return # sub version must be 8 or less
  142. # I am having it do 8 or less because there was a bug in this function prior to 9
  143. # sub version doesn't matter since any subversion of 11 should trigger this task
  144. prPurple(f"Adding \"Inherit Color\" socket to {node.name}")
  145. try:
  146. inh_color = node.inputs.get('Inherit Color')
  147. if inh_color and inh_color.bl_idname != 'BooleanSocket':
  148. node.inputs.remove(inh_color)
  149. inh_color = None
  150. if inh_color is None:
  151. s = node.inputs.new('BooleanSocket', 'Inherit Color',)
  152. node.inputs.move(len(node.inputs)-1, 23)
  153. s.default_value=True
  154. except Exception as e:
  155. prRed(f"Error updating version in node: {node.id_data.name}::{node.name}; see error:")
  156. print(e)
  157. def up_0_12_13_add_widget_scale(*args, **kwargs):
  158. node = kwargs['node']
  159. current_major_version = node.id_data.mantis_version[0]
  160. current_minor_version = node.id_data.mantis_version[1]
  161. current_sub_version = node.id_data.mantis_version[2]
  162. if current_major_version > 0: return# major version must be 0
  163. if current_minor_version > 12: return# minor version must be 12 or less
  164. if current_minor_version == 12 and current_sub_version > 12: return
  165. # sub version must be 12 or less
  166. prPurple(f"Adding \"Scale\" socket to {node.name}")
  167. try:
  168. scale = node.inputs.get('Scale')
  169. if scale is None:
  170. s = node.inputs.new('VectorScaleSocket', 'Scale',)
  171. s.default_value=[1.0,1.0,1.0]
  172. node.inputs.move(len(node.inputs)-1, 1)
  173. except Exception as e:
  174. prRed(f"Error updating version in node: {node.id_data.name}::{node.name}; see error:")
  175. print(e)
  176. def up_0_12_25_replace_floor_offset_type(*args, **kwargs):
  177. node = kwargs['node']
  178. current_major_version = node.id_data.mantis_version[0]
  179. current_minor_version = node.id_data.mantis_version[1]
  180. current_sub_version = node.id_data.mantis_version[2]
  181. if current_major_version > 0: return# major version must be 0
  182. if current_minor_version > 12: return# minor version must be 12 or less
  183. if current_minor_version == 12 and current_sub_version > 24: return
  184. socket_maps = get_socket_maps(node)
  185. prPurple(f"Fixing \"Offset\" socket in {node.name}")
  186. try:
  187. offset = node.inputs["Offset"]
  188. node.inputs.remove(offset)
  189. s = node.inputs.new('FloatSocket', 'Offset',)
  190. node.inputs.move(len(node.inputs)-1, 2)
  191. do_relink(node, s, socket_maps[0])
  192. except Exception as e:
  193. prRed(f"Error updating version in node: {node.id_data.name}::{node.name}; see error:")
  194. print(e)
  195. def get_absolute_location(node): # using this for version compatibility
  196. location = node.location.copy() # FUTURE: deprecate old blenders and use absolute_location
  197. while(node.parent):
  198. node = node.parent
  199. location+= node.location
  200. return location
  201. def up_0_13_0_new_custom_prop_node(*args, **kwargs):
  202. tree, node = kwargs['node_tree'], kwargs['node']
  203. current_major_version = tree.mantis_version[0]
  204. if current_major_version > 0: return# major version must be 0
  205. current_minor_version = tree.mantis_version[1]
  206. if current_minor_version >= 13: return# minor version must be 12 or less
  207. remove_me, prop_nodes = [], []
  208. from .xForm_nodes_ui import xFormBoneNode
  209. socket_map_in, socket_map_out = get_socket_maps(node)
  210. if isinstance(node, xFormBoneNode):
  211. for custom_input in reversed(list(node.inputs)):
  212. if 'Parameter' not in custom_input.bl_idname:
  213. continue
  214. custom_prop_node = tree.nodes.new('UtilityCustomProperty')
  215. prop_type = None
  216. if custom_input.bl_idname == 'ParameterBoolSocket':
  217. prop_type = 'BOOL'
  218. custom_prop_node.inputs['Default (Bool)'].default_value = getattr(custom_input, "default_value")
  219. elif custom_input.bl_idname == 'ParameterIntSocket':
  220. prop_type = 'INT'
  221. custom_prop_node.inputs['Default (Int)'].default_value = int( getattr(custom_input, "default_value") )
  222. custom_prop_node.inputs['Min (Int)'].default_value = int( getattr(custom_input, "min") )
  223. custom_prop_node.inputs['Max (Int)'].default_value = int( getattr(custom_input, "max") )
  224. custom_prop_node.inputs['Soft Min (Int)'].default_value = int( getattr(custom_input, "soft_min") )
  225. custom_prop_node.inputs['Soft Max (Int)'].default_value = int( getattr(custom_input, "soft_max") )
  226. elif custom_input.bl_idname == 'ParameterFloatSocket':
  227. prop_type = 'FLOAT'
  228. custom_prop_node.inputs['Default (Float)'].default_value = getattr(custom_input, "default_value")
  229. custom_prop_node.inputs['Min (Float)'].default_value = getattr(custom_input, "min")
  230. custom_prop_node.inputs['Max (Float)'].default_value = getattr(custom_input, "max")
  231. custom_prop_node.inputs['Soft Min (Float)'].default_value = getattr(custom_input, "soft_min")
  232. custom_prop_node.inputs['Soft Max (Float)'].default_value = getattr(custom_input, "soft_max")
  233. elif custom_input.bl_idname == 'ParameterVectorSocket':
  234. prop_type = 'VECTOR'
  235. custom_prop_node.inputs['Default (Vector)'].default_value = getattr(custom_input, "default_value")
  236. try:
  237. custom_prop_node.inputs['Min (Float)'].default_value = getattr(custom_input, "min")
  238. custom_prop_node.inputs['Max (Float)'].default_value = getattr(custom_input, "max")
  239. custom_prop_node.inputs['Soft Min (Float)'].default_value = getattr(custom_input, "soft_min")
  240. custom_prop_node.inputs['Soft Max (Float)'].default_value = getattr(custom_input, "soft_max")
  241. except AttributeError: # I don't know if I just never implemented these or if it is version specific
  242. pass # anyways this isn't critical and should not trigger even a warning
  243. elif custom_input.bl_idname == 'ParameterStringSocket':
  244. prop_type = 'STRING'
  245. custom_prop_node.inputs['Default (String)'].default_value = getattr(custom_input, "default_value")
  246. custom_prop_node.inputs['Name'].default_value = custom_input.name
  247. custom_prop_node.inputs['Type'].default_value = prop_type
  248. prop_nodes.append(custom_prop_node)
  249. remove_me.append(custom_input)
  250. # now we need to relink things, because the custom property socket could have had an
  251. # input supplying the default value
  252. relink_value = socket_map_in.get(custom_input.identifier, None)
  253. if isinstance(relink_value, list): # this indicates it is a list of links
  254. # CRITICALLY, we need to force display update before doing this.
  255. custom_prop_node.display_update({}, None) # parsed_tree and context, not needed
  256. input_socket = None
  257. match prop_type:
  258. case 'BOOL':
  259. input_socket = "Default (Bool)"
  260. case 'INT':
  261. input_socket = "Default (Int)"
  262. case 'FLOAT':
  263. input_socket = "Default (Float)"
  264. case 'VECTOR':
  265. input_socket = "Default (Vector)"
  266. case 'STRING':
  267. input_socket = "Default (String)"
  268. case _: # Should never never happen
  269. raise RuntimeError("Unexpected Code Path Reached, this is a bug.")
  270. do_relink(custom_prop_node, custom_prop_node.inputs[input_socket],
  271. {input_socket:relink_value})
  272. while remove_me:
  273. custom_input = remove_me.pop()
  274. node.inputs.remove(custom_input)
  275. new_input = node.inputs.new("CustomPropSocket", "Custom Properties", use_multi_input=True)
  276. from mathutils import Vector
  277. for i, prop_node in enumerate(prop_nodes):
  278. tree.links.new(input=prop_node.outputs[0], output=new_input)
  279. prop_node.location = get_absolute_location(node)
  280. prop_node.location = prop_node.location - Vector((180, -260*i))
  281. prop_node.select = False # it is annoying to select them all by default
  282. else: # just need to add the socket.
  283. new_input = node.inputs.new("CustomPropSocket", "Custom Properties", use_multi_input=True)
  284. def schema_enable_custom_interface_types(*args, **kwargs):
  285. tree = kwargs['tree']
  286. current_major_version = tree.mantis_version[0]
  287. current_minor_version = tree.mantis_version[1]
  288. current_sub_version = tree.mantis_version[2]
  289. if current_major_version > 0: return# major version must be 0
  290. if current_minor_version >= 13: return# minor version must be 12 or less
  291. # we need to set the new interface values on the schema interface stuff
  292. prGreen(f"Updating Schema tree {tree.name} to support new, improved UI!")
  293. tree.do_live_update = False
  294. for n in tree.nodes:
  295. if hasattr(n, "is_updating"):
  296. n.is_updating = True
  297. try:
  298. for item in tree.interface.items_tree:
  299. if item.item_type == 'PANEL':
  300. continue
  301. parent_name = 'Constant'
  302. if item.parent:
  303. parent_name=item.parent.name
  304. if hasattr(item, "is_array"):
  305. # if is_array exists we're in the custom interface class
  306. # so we'll assume the other attributes exist
  307. if parent_name == 'Array':
  308. item.is_array = True
  309. if parent_name == 'Connection':
  310. item.is_array = False
  311. item.is_connection=True
  312. item.connected_to=item.name
  313. # since heretofore it has been a requirement that the names match
  314. except Exception as e:
  315. prRed(f"Error updating version in tree: {tree.name}; see error:")
  316. print(e)
  317. finally:
  318. for n in tree.nodes:
  319. if hasattr(n, "is_updating"):
  320. n.is_updating = False
  321. tree.do_live_update = True
  322. def update_fcurve_and_armature_node_to_multi_socket(*args, **kwargs):
  323. node = kwargs['node']
  324. live_updates = node.id_data.do_live_update
  325. node.id_data.do_live_update = False
  326. # First we have to get the socket maps and re-init the sockets
  327. from .utilities.utilities import get_socket_maps, do_relink
  328. convert_keys = {'UtilityFCurve' : [ 'Keyframe', ],
  329. 'LinkArmature' : [ 'Target', 'Weight', ], }
  330. my_convert_keys = convert_keys[node.bl_idname]
  331. sockets_in, _sockets_out = get_socket_maps(node,)
  332. node.inputs.clear()
  333. input_templates = [st for st in node.socket_templates if st.is_input == True]
  334. node.init_sockets(input_templates)
  335. try:
  336. new_sockets_in = {}
  337. for convert_key in my_convert_keys:
  338. for socket_name, links in sockets_in.items():
  339. if links is None: continue
  340. if convert_key+'.' in socket_name:
  341. print (socket_name, links)
  342. if new_sockets_in.get(convert_key+'s'):
  343. # has to be in this order to come back alright.
  344. # assuming, that is, that the keys are sorted. they should be.
  345. new_sockets_in[convert_key+'s'] = sockets_in[socket_name] + new_sockets_in[convert_key+'s']
  346. else:
  347. new_sockets_in[convert_key+'s'] = sockets_in[socket_name]
  348. prWhite (new_sockets_in[convert_key+'s'])
  349. do_relink(node, node.inputs[convert_key+'s'], new_sockets_in, in_out="INPUT",)
  350. for socket_name, links in sockets_in.items():
  351. proceed = True
  352. for convert_key in my_convert_keys:
  353. if convert_key in socket_name:
  354. proceed = False
  355. if proceed:
  356. do_relink(node, node.inputs[socket_name], sockets_in, in_out='INPUT')
  357. finally:
  358. node.id_data.do_live_update = live_updates
  359. # versioning tasks that involve Blender versions rather than Mantis versions:
  360. error_description_4_5_0_LTS = 'There is a bug in Blender 4.5.0 LTS, that is why these sockets are blue.'\
  361. ' This will be fixed in future Blender versions.'
  362. def cleanup_4_5_0_LTS_interface_workaround(*args, **kwargs):
  363. # this is a function for cleaning up the workaround up above
  364. tree = kwargs['tree']
  365. if bpy_version == (4,5,0): return
  366. if not hasattr(tree, "interface_helper"): return
  367. import json
  368. try:
  369. interface_helper = json.loads(tree.interface_helper)
  370. except:
  371. return # this should mean it was never a problem to begin with.
  372. prPurple(f"Restoring Tree Interface for {tree.name}.")
  373. for interface_item in tree.interface.items_tree:
  374. if interface_item.item_type == 'PANEL': continue
  375. # now we need to restore the socket types, which are in the interface helper
  376. # keep the interface stuff around, I'll use it for marking arrays in the future
  377. int_info = interface_helper[interface_item.identifier]
  378. socket_type = int_info['bl_socket_idname']
  379. interface_item.socket_type = socket_type
  380. if interface_item.description == error_description_4_5_0_LTS:
  381. interface_item.description = ''
  382. versioning_tasks = [
  383. # node bl_idname task required keyword arguments
  384. (['ALL'], version_upgrade_very_old, ['node_tree', 'node'],),
  385. (['xFormBoneNode'], version_upgrade_bone_0_12_0_from_older, ['node'],),
  386. (['xFormBoneNode'], up_0_12_1_add_inherit_color, ['node'],),
  387. (['MantisTree', 'SchemaTree'], cleanup_4_5_0_LTS_interface_workaround, ['tree']),
  388. (['InputWidget'], up_0_12_13_add_widget_scale, ['node']),
  389. (['LinkFloor'], up_0_12_25_replace_floor_offset_type, ['node']),
  390. (['XFORM'], up_0_13_0_new_custom_prop_node, ['node', 'node_tree']),
  391. (['SchemaTree'], schema_enable_custom_interface_types, ['tree']),
  392. (['UtilityFCurve', 'LinkArmature'],
  393. update_fcurve_and_armature_node_to_multi_socket, ['node']),
  394. ]
  395. # WORKAROUNDS for bugs should go here:
  396. # 4.5.0 LTS valid socket types bug:
  397. def workaround_4_5_0_interface_update(tree, name, in_out, sock_type, parent_name, do_parent=False):
  398. # TODO: dedupe this code from i_o.py
  399. prRed("There is a bug in Blender 4.5.0 regarding node-group interface sockets. Working around it.")
  400. sock = tree.interface.new_socket(name=name, in_out=in_out, socket_type="NodeSocketGeometry")
  401. import json
  402. interface_helper = {} # initialize it if it is empty
  403. if tree.interface_helper: # may be empty, check here
  404. interface_helper = json.loads(tree.interface_helper)
  405. error_message = error_description_4_5_0_LTS
  406. interface_helper[sock.identifier] = {
  407. 'name' : sock.name,
  408. 'identifier' : sock.identifier,
  409. 'in_out' : sock.in_out,
  410. 'socket_type' : sock_type,
  411. 'bl_socket_idname' : sock_type,
  412. 'mantis_socket_category' : parent_name,
  413. 'description' : error_message,
  414. }
  415. sock.description = error_message # this tells the user why the socket looks weird.
  416. tree.interface_helper = json.dumps(interface_helper)
  417. if do_parent and (parent := tree.interface.items_tree.get(parent_name)):
  418. tree.interface.move_to_parent(
  419. sock,
  420. parent,
  421. 0, # what to do here?
  422. )
  423. return sock
  424. def socket_add_workaround_for_4_5_0_LTS(item, socket_collection, multi):
  425. import json
  426. tree = item.id_data
  427. interface_helper = json.loads(tree.interface_helper)
  428. socket_info = interface_helper.get(item.identifier)
  429. if not socket_info: raise RuntimeError(f"There has been an error adding the socket {item.name}")
  430. s = socket_collection.new(
  431. type=socket_info['bl_socket_idname'],
  432. name=item.name, # in case the user has changed it
  433. identifier=item.identifier,
  434. use_multi_input=multi, )
  435. return s