| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732 |
- #Mantis Nodes Base
- import bpy
- from bpy.props import BoolProperty, StringProperty, EnumProperty, CollectionProperty, IntProperty, PointerProperty, BoolVectorProperty
- from . import ops_nodegroup
- from bpy.types import NodeTree, Node, PropertyGroup, Operator, UIList, Panel
- from .utilities import (prRed, prGreen, prPurple, prWhite,
- prOrange,
- wrapRed, wrapGreen, wrapPurple, wrapWhite,
- wrapOrange,)
- from .utilities import get_socket_maps, relink_socket_map, do_relink
- from bpy.app.handlers import persistent
- def TellClasses():
- #Why use a function to do this? Because I don't need every class to register.
- return [ MantisTree,
- SchemaTree,
- # MantisNode,
- # SchemaNode,
- MantisNodeGroup,
- SchemaGroup,
- MantisVisualizeTree,
- MantisVisualizeNode,
- ]
- class MantisTree(NodeTree):
- '''A custom node tree type that will show up in the editor type list'''
- bl_idname = 'MantisTree'
- bl_label = "Rigging Nodes"
- bl_icon = 'OUTLINER_OB_ARMATURE'
-
- tree_valid:BoolProperty(default=False)
- do_live_update:BoolProperty(default=True) # use this to disable updates for e.g. scripts
- num_links:IntProperty(default=-1)
- filepath:StringProperty(default="", subtype='FILE_PATH')
- is_executing:BoolProperty(default=False)
- is_exporting:BoolProperty(default=False)
- execution_id:StringProperty(default='')
-
- parsed_tree={}
-
- def interface_update(self, context):
- # no idea what this does
- print ("Update Interface function in MantisTree class")
- if bpy.app.version >= (3, 2): # in 3.1 this can lead to a crash
- @classmethod
- def valid_socket_type(cls, socket_type: str):
- # https://docs.blender.org/api/master/bpy.types.NodeTree.html#bpy.types.NodeTree.valid_socket_type
- from .socket_definitions import Tell_bl_idnames
- return socket_type in Tell_bl_idnames()
- # thank you, Sverchok
-
- def update_tree(self, context = None):
- if self.is_exporting:
- return
- # return
- self.is_executing = True
- from . import readtree
- prGreen("Validating Tree: %s" % self.name)
- try:
- self.parsed_tree = readtree.parse_tree(self)
- if context:
- self.display_update(context)
- self.is_executing = False
- self.tree_valid = True
- except GraphError as e:
- prRed("Failed to update node tree due to error.")
- self.tree_valid = False
- self.is_executing = False
- raise e
-
- def display_update(self, context):
- if self.is_exporting:
- return
- current_tree = bpy.context.space_data.path[-1].node_tree
- for node in current_tree.nodes:
- if hasattr(node, "display_update"):
- try:
- node.display_update(self.parsed_tree, context)
- except Exception as e:
- print("Node \"%s\" failed to update display with error: %s" %(wrapGreen(node.name), wrapRed(e)))
- # raise e
- # from .utilities import all_trees_in_tree
- # all_my_trees = all_trees_in_tree(self,)
- # for tree in all_my_trees:
- # I think using the current visible tree is actually fine
- if True:
- # HACK
- for l in current_tree.links:
- l.is_valid = True # I don't want Blender marking these for me. No warning is better than a wrong warning.
- # end HACK
- # in the future, fix it properly. Here is a start.
- else: # this is harder to fix than I thought!
- tree_path_names=[None,]
- for i, path_item in enumerate(bpy.context.space_data.path[:-1]):
- tree_path_names.append(path_item.node_tree.nodes.active.name)
- for l in current_tree.links: # We need to loop through actual links so we can filter them
- if l.is_valid == False:
- if nc_from := self.parsed_tree.get( (*tree_path_names, l.from_node.name)) is None:
- continue
- for o in nc_from.outputs.values():
- for mlink in o.links:
- if (mlink.to_socket == l.to_socket.name) and (mlink.to_node.signature[-1] == l.to_node.name):
- l.is_valid = not mlink.is_hierarchy
- # in reality, we need to trace the link UP and find a cycle - then find a link in the cycle that is non-hierarchy
- # the actual link that BLENDER marks as invalid may be a hierarchy link.
- # let's see if this works
-
-
- def execute_tree(self,context):
- if self.is_exporting:
- return
- # return
- prGreen("Executing Tree: %s" % self.name)
- self.is_executing = True
- from . import readtree
- try:
- readtree.execute_tree(self.parsed_tree, self, context)
- except RecursionError as e:
- prRed("Recursion error while parsing tree.")
- # prRed(e); node_tree.do_live_update = False
- # except Exception:
- # pass
- finally: # first time I have ever used a finally block in my life.
- self.is_executing = False
-
- # class SchemaPropertyGroup(bpy.types.PropertyGroup):
- class SchemaTree(NodeTree):
- '''A node tree representing a schema to generate a Mantis tree'''
- bl_idname = 'SchemaTree'
- bl_label = "Rigging Nodes Schema"
- bl_icon = 'RIGID_BODY_CONSTRAINT'
- tree_valid:BoolProperty(default=False)
- do_live_update:BoolProperty(default=True) # use this to disable updates for e.g. scripts
- is_executing:BoolProperty(default=False)
- num_links:IntProperty(default=-1)
- # filepath:StringProperty(default="", subtype='FILE_PATH')
-
- parsed_tree={}
- # def update(self):
- # for n in self.nodes:
- # if hasattr(n, "update"): n.update()
- # def update_tree(self, context):
- # prRed("update tree for Schema Tree!")
- # # self.tree_valid = True
- # # return
- # from . import readtree
- # prGreen("Validating Tree: %s" % self.name)
- # parsed_tree = readtree.parse_tree(self)
- # self.parsed_tree=parsed_tree
- # current_tree = bpy.context.space_data.path[-1].node_tree
- # self.tree_valid = True
- # prWhite("Number of Nodes: %s" % (len(self.parsed_tree)))
- # self.display_update(context)
-
- # def display_update(self, context):
- # prRed("display update for Schema Tree!")
- # return
- # current_tree = bpy.context.space_data.path[-1].node_tree
- # for node in current_tree.nodes:
- # if hasattr(node, "display_update"):
- # try:
- # node.display_update(self.parsed_tree, context)
- # except Exception as e:
- # print("Node \"%s\" failed to update display with error: %s" %(wrapGreen(node.name), wrapRed(e)))
- # # raise e
- # def execute_tree(self,context):
- # self.is_executing = True
- # prRed("executing Schema Tree!")
- # self.tree_valid = False
- # self.is_executing = False
- # return
- # prGreen("Executing Tree: %s" % self.name)
- # from . import readtree
- # try:
- # readtree.execute_tree(self.parsed_tree, self, context)
- # except RecursionError as e:
- # prRed("Recursion error while parsing tree.")
- # prRed(e); node_tree.do_live_update = False
- if bpy.app.version >= (3, 2): # in 3.1 this can lead to a crash
- @classmethod
- def valid_socket_type(cls, socket_type: str):
- # https://docs.blender.org/api/master/bpy.types.NodeTree.html#bpy.types.NodeTree.valid_socket_type
- from .socket_definitions import Tell_bl_idnames
- return socket_type in Tell_bl_idnames()
- # thank you, Sverchok
-
- class MantisNode:
- # num_links:IntProperty(default=-1) # is this used anywhere?
- # is_triggering_execute:BoolProperty(default=False)
- # do_display_update:BoolProperty(default=False)
- @classmethod
- def poll(cls, ntree):
- return (ntree.bl_idname in ['MantisTree', 'SchemaTree'])
-
- def insert_link(self, link):
- context = bpy.context
- if context.space_data:
- node_tree = context.space_data.path[0].node_tree
- from . import readtree
- if node_tree.do_live_update:
- # prOrange("Updating from insert_link callback")
- node_tree.update_tree(context)
- if (link.to_socket.is_linked == False):
- node_tree.num_links+=1
- elif (link.to_socket.is_multi_input):# and
- #len(link.to_socket.links) < link.to_socket.link_limit ):
- # the above doesn't work and I can't be bothered to fix it right now TODO
- node_tree.num_links+=1
-
- class SchemaNode:
- # is_triggering_execute:BoolProperty(default=False)
- # do_display_update:BoolProperty(default=False)
- @classmethod
- def poll(cls, ntree):
- return (ntree.bl_idname in ['SchemaTree'])
-
- class LinkNode(MantisNode):
- useTarget : BoolProperty(default=False)
- @classmethod
- def poll(cls, ntree):
- return (ntree.bl_idname in ['MantisTree', 'SchemaTree'])
- class xFormNode(MantisNode):
- @classmethod
- def poll(cls, ntree):
- return (ntree.bl_idname in ['MantisTree', 'SchemaTree'])
- class DeformerNode(MantisNode):
- @classmethod
- def poll(cls, ntree):
- return (ntree.bl_idname in ['MantisTree', 'SchemaTree'])
- # from bpy.types import NodeCustomGroup
- def poll_node_tree(self, object):
- if isinstance(object, MantisTree):
- return True
- return False
- # TODO this should check ID's instead of name
- def node_group_update(node):
- toggle_update = node.id_data.do_live_update
- node.id_data.do_live_update = False
- # prWhite (node.name, len(node.inputs), len(node.outputs))
- identifiers_in={socket.identifier:socket for socket in node.inputs}
- identifiers_out={socket.identifier:socket for socket in node.outputs}
- if node.node_tree is None:
- node.inputs.clear(); node.outputs.clear()
- node.id_data.do_live_update = toggle_update
- return
- found_in, found_out = [], []
- update_input, update_output = False, False
- for item in node.node_tree.interface.items_tree:
- if item.item_type != "SOCKET": continue
- if item.in_out == 'OUTPUT':
- if s:= identifiers_out.get(item.identifier): # if the requested output doesn't exist, update
- found_out.append(item.identifier)
- if update_output: continue # done here
- if s.bl_idname != item.socket_type: update_output = True; continue
- else: update_output = True; continue # prRed(f"Not found: {item.name}");
- else:
- if s:= identifiers_in.get(item.identifier): # if the requested input doesn't exist, update
- found_in.append(item.identifier)
- if update_input: continue # done here
- if s.bl_idname != item.socket_type: update_input = True; continue
- else: update_input = True; continue # prGreen(f"Not found: {item.name}");
-
- # Schema has an extra input for Length and for Extend.
- if node.bl_idname == 'MantisSchemaGroup':
- found_in.extend(['Schema Length', ''])
- # if we have too many elements, just get rid of the ones we don't need
- if len(node.inputs) > len(found_in):#
- for inp in node.inputs:
- if inp.identifier in found_in: continue
- node.inputs.remove(inp)
- if len(node.outputs) > len(found_out):
- for out in node.outputs:
- if out.identifier in found_out: continue
- node.outputs.remove(out)
- #
- if len(node.inputs) > 0 and (inp := node.inputs[-1]).bl_idname == 'WildcardSocket' and inp.is_linked:
- # prPurple("oink! I am a piggy!")
- update_input = True
- if len(node.outputs) > 0 and (out := node.outputs[-1]).bl_idname == 'WildcardSocket' and out.is_linked:
- # prPurple("woof! I am a doggy!")
- update_output = True
- #
- if not (update_input or update_output):
- node.id_data.do_live_update = toggle_update
- return
- if update_input or update_output:
- socket_map_in, socket_map_out = get_socket_maps(node)
- if update_input :
- if node.bl_idname == 'MantisSchemaGroup':
- schema_length=0
- if sl := node.inputs.get("Schema Length"):
- schema_length = sl.default_value
- # sometimes this isn't available yet # TODO not happy about this solution
- node.inputs.clear()
- if node.bl_idname == 'MantisSchemaGroup':
- node.inputs.new("IntSocket", "Schema Length", identifier='Schema Length')
- node.inputs['Schema Length'].default_value = schema_length
- if update_output: node.outputs.clear()
- for item in node.node_tree.interface.items_tree:
- if item.item_type != "SOCKET": continue
- if (item.in_out == 'INPUT' and update_input):
- relink_socket_map(node, node.inputs, socket_map_in, item)
- if (item.in_out == 'OUTPUT' and update_output):
- relink_socket_map(node, node.outputs, socket_map_out, item)
-
- # at this point there is no wildcard socket
- if '__extend__' in socket_map_in.keys():
- do_relink(node, None, socket_map_in, in_out='INPUT', parent_name='Constant' )
- node.id_data.do_live_update = toggle_update
- def node_tree_prop_update(self, context):
- if self.is_updating: # this looks dumb... but update() can be called from update() in a sort of accidental way.
- return
- # prGreen("updating me...")
- self.is_updating = True
- node_group_update(self)
- self.is_updating = False
- if self.bl_idname in ['MantisSchemaGroup'] and self.node_tree is not None:
- if len(self.inputs) == 0:
- self.inputs.new("IntSocket", "Schema Length", identifier='Schema Length')
- if self.inputs[-1].bl_idname != "WildcardSocket":
- self.inputs.new("WildcardSocket", "", identifier="__extend__")
- from bpy.types import NodeCustomGroup
- class MantisNodeGroup(Node, MantisNode):
- bl_idname = "MantisNodeGroup"
- bl_label = "Node Group"
- node_tree:PointerProperty(type=NodeTree, poll=poll_node_tree, update=node_tree_prop_update,)
- is_updating:BoolProperty(default=False)
-
- def update(self):
- if self.is_updating: # this looks dumb... but update() can be called from update() in a sort of accidental way.
- return
- self.is_updating = True
- node_group_update(self)
- self.is_updating = False
- def draw_buttons(self, context, layout):
- row = layout.row(align=True)
- row.prop(self, "node_tree", text="")
- row.operator("mantis.edit_group", text="", icon='NODETREE', emboss=True)
-
- class CircularDependencyError(Exception):
- pass
- class GraphError(Exception):
- pass
- def get_signature_from_edited_tree(node, context):
- sig_path=[None,]
- for item in context.space_data.path[:-1]:
- sig_path.append(item.node_tree.nodes.active.name)
- return tuple(sig_path+[node.name])
- def poll_node_tree_schema(self, object):
- if isinstance(object, SchemaTree):
- return True
- return False
- # def update_schema_length(self, context):
- # pass # for now
- # TODO tiny UI problem - inserting new links into the tree will not place them in the right place.
- #this is a schema node in a mantis tree... kinda confusing
- class SchemaGroup(Node, MantisNode):
- bl_idname = "MantisSchemaGroup"
- bl_label = "Node Schema"
-
- node_tree:PointerProperty(type=NodeTree, poll=poll_node_tree_schema, update=node_tree_prop_update,)
- # schema_length:IntProperty(default=5, update=update_schema_length)
- is_updating:BoolProperty(default=False)
- # incoming link
- # from-node = name
- # from socket = index or identifier or something
- # property is unset as soon as it is used
- # so the update function checks this property and handles the incoming link in an allowed place
- # and actually the handle-link function can work as a switch - when the property is unset, it allows new links
- # otherwise it unsets the property and returns.
-
- # def init(self, context):
- # self.inputs.new("IntSocket", "Schema Length")
- # self.inputs.new("WildcardSocket", "")
- def draw_buttons(self, context, layout):
- row = layout.row(align=True)
- row.prop(self, "node_tree", text="")
- row.operator("mantis.edit_group", text="", icon='NODETREE', emboss=True)
- # layout.prop(self, "schema_length", text="n=")
-
- # WHAT IF:
- # - the function that creates the input/output map returns to a property in the node
- # - then the node handles the update in its update function.
- def update(self):
- if self.is_updating: # this looks dumb... but update() can be called from update() in a sort of accidental way.
- return
- self.is_updating = True
- node_group_update(self)
- # kinda dumb but necessary since update doesn't always fix this
- if self.node_tree:
- if len(self.inputs) == 0:
- self.inputs.new("IntSocket", "Schema Length", identifier='Schema Length')
- if self.inputs[-1].bl_idname != "WildcardSocket":
- self.inputs.new("WildcardSocket", "", identifier="__extend__")
- self.is_updating = False
- # def insert_link(self, link):
- # if self.node_tree is None:
- # link.is_valid = False
- # return
- # sock_type = link.from_socket.bl_idname
- # for i, sock in enumerate(self.inputs):
- # if sock == link.to_socket: # dumb but whatever
- # identifier = link.to_socket.identifier
- # if sock.bl_idname not in ["WildcardSocket"]:
- # if sock.is_linked == True:
- # links = [ getattr(l, "from_socket") for l in sock.links ]
- # name = sock.name
- # # self.inputs.remove(sock)
- # # new_input = self.inputs.new(sock_type, name, identifier=identifier, use_multi_input=True); self.inputs.move(-1, i)
- # sock.display_shape = 'SQUARE_DOT'
- # interface_item = self.node_tree.interface.items_tree[name]
- # if not (interface_parent := self.node_tree.interface.items_tree.get('Array')):
- # interface_parent = self.node_tree.interface.new_panel(name='Array')
- # self.node_tree.interface.move_to_parent(interface_item, interface_parent, len(interface_parent.interface_items))
- # # sock.link_limit = self.schema_length TODO this will be very hard to get at this point
- # # self.id_data.links.new()
- # else: #if link.to_socket == self.inputs[-1]:
- # self.inputs.remove(sock)#self.inputs[-1])
- # #
- # name_stem = link.from_socket.bl_idname.replace('Socket',''); num=0
- # if hasattr(link.from_socket, "default_value"):
- # name_stem = type(link.from_socket.default_value).__name__
- # for n in self.inputs:
- # if name_stem in n.name: num+=1
- # name = name_stem + '.' + str(num).zfill(3)
- # #
- # new_input = self.inputs.new(sock_type, name, identifier=identifier, use_multi_input=False); self.inputs.move(-1, i+1)
- # new_input.link_limit = 1
- # # link.to_socket = new_input
- # # this seems to work
- # self.inputs.new("WildcardSocket", "")
- # if not (interface_parent := self.node_tree.interface.items_tree.get('Constant')):
- # interface_parent = self.node_tree.interface.new_panel(name='Constant')
- # self.node_tree.interface.new_socket(name=name,in_out='INPUT', socket_type=sock_type, parent=interface_parent)
- # return
-
- # TODO: investigate whether this is necessary
- # @classmethod
- # def poll(cls, ntree):
- # return (ntree.bl_idname in ['MantisTree'])
- # handlers!
- #annoyingly these have to be persistent
- @persistent
- def update_handler(scene):
- context=bpy.context
- if context.space_data:
- if not hasattr(context.space_data, "path"):
- return
- trees = [p.node_tree for p in context.space_data.path]
- if not trees: return
- if (node_tree := trees[0]).bl_idname in ['MantisTree']:
- if node_tree.do_live_update and not (node_tree.is_executing or node_tree.is_exporting):
- prev_links = node_tree.num_links
- node_tree.num_links = len(node_tree.links)
- if (prev_links == -1):
- return
- if prev_links != node_tree.num_links:
- node_tree.tree_valid = False
- if node_tree.tree_valid == False:
- node_tree.update_tree(context)
- @persistent
- def execute_handler(scene):
- context = bpy.context
- if context.space_data:
- if not hasattr(context.space_data, "path"):
- return
- trees = [p.node_tree for p in context.space_data.path]
- if not trees: return
- if (node_tree := trees[0]).bl_idname in ['MantisTree']:
- if node_tree.tree_valid and node_tree.do_live_update and not (node_tree.is_executing or node_tree.is_exporting):
- node_tree.execute_tree(context)
- node_tree.tree_valid = False
- # @persistent
- # def load_post_handler(scene):
- # print ("cuss and darn")
- # # import bpy
- # import sys
- # def wrapRed(skk): return "\033[91m{}\033[00m".format(skk)
- # def intercept(fn, *args):
- # print(wrapRed("Intercepting:"), fn)
- # sys.stdout.flush()
- # fn(*args)
- # print(wrapRed("... done"))
- # sys.stdout.flush()
- # for attr in dir(bpy.app.handlers):
- # if attr.startswith("_"):
- # continue
- # handler_list = getattr(bpy.app.handlers, attr)
- # if attr =='load_post_handler':
- # continue
- # if not isinstance(handler_list, list):
- # continue
- # if not handler_list:
- # continue
- # print("Intercept Setup:", attr)
- # handler_list[:] = [lambda *args: intercept(fn, *args) for fn in handler_list]
- # # import cProfile
- # from os import environ
- # do_profile=False
- # print (environ.get("DOPROFILE"))
- # if environ.get("DOPROFILE"):
- # do_profile=True
- # if do_profile:
- # # cProfile.runctx("tree.update_tree(context)", None, locals())
- # # cProfile.runctx("tree.execute_tree(context)", None, locals())
- # import hunter
- # hunter.trace(stdlib=False, action=hunter.CallPrinter(force_colors=False))
- # # def msgbus_callback(*args):
- # # # print("something changed!")
- # # print("Something changed!", args)
- # # owner = object()
- # subscribe_to = (bpy.types.Node, "location")
- # subscribe_to = (bpy.types.Node, "color")
- # subscribe_to = (bpy.types.Node, "dimensions")
- # subscribe_to = (bpy.types.Node, "height")
- # subscribe_to = (bpy.types.Node, "width")
- # subscribe_to = (bpy.types.Node, "inputs")
- # subscribe_to = (bpy.types.Node, "outputs")
- # subscribe_to = (bpy.types.Node, "select")
- # subscribe_to = (bpy.types.Node, "name")
- # subscribe_to = (bpy.types.NodeSocket, "name")
- # subscribe_to = (bpy.types.NodeSocket, "display_shape")
- # bpy.msgbus.subscribe_rna(
- # key=subscribe_to,
- # owner=owner,
- # args=(1, 2, 3),
- # notify=msgbus_callback,
- # )
- # print ("cuss and darn")
- # bpy.app.handlers.load_post.append(set_tree_invalid)
- bpy.app.handlers.depsgraph_update_pre.append(update_handler)
- bpy.app.handlers.depsgraph_update_post.append(execute_handler)
- # bpy.app.handlers.load_post.append(load_post_handler)
- # # import bpy
- # import sys
- # def wrapRed(skk): return "\033[91m{}\033[00m".format(skk)
- # def intercept(fn, *args):
- # print(wrapRed("Intercepting:"), fn)
- # sys.stdout.flush()
- # fn(*args)
- # print(wrapRed("... done"))
- # sys.stdout.flush()
- # for attr in dir(bpy.app.handlers):
- # if attr.startswith("_"):
- # continue
- # handler_list = getattr(bpy.app.handlers, attr)
- # if attr =='load_post_handler':
- # continue
- # if not isinstance(handler_list, list):
- # continue
- # if not handler_list:
- # continue
- # print("Intercept Setup:", attr)
- # handler_list[:] = [lambda *args: intercept(fn, *args) for fn in handler_list]
- class MantisVisualizeTree(NodeTree):
- '''A custom node tree type that will show up in the editor type list'''
- bl_idname = 'MantisVisualizeTree'
- bl_label = "mantis output"
- bl_icon = 'HIDE_OFF'
- class MantisVisualizeNode(Node):
- bl_idname = "MantisVisualizeNode"
- bl_label = "Node"
- @classmethod
- def poll(cls, ntree):
- return (ntree.bl_idname in ['MantisVisualizeTree'])
-
- def init(self, context):
- pass
-
- def gen_data(self, nc, np = None):
- self.use_custom_color = True
- if nc.node_type == 'XFORM':
- self.color = (1.0 ,0.5, 0.0)
- if nc.node_type == 'LINK':
- self.color = (0.4 ,0.2, 1.0)
- if nc.node_type == 'UTILITY':
- self.color = (0.2 ,0.2, 0.2)
- if nc.node_type == 'SCHEMA':
- self.color = (0.85 ,0.95, 0.9)
- if nc.node_type == 'DUMMY':
- self.color = (0.05 ,0.05, 0.15)
- self.name = ''.join(nc.signature[1:])
- if np:
- if np.label:
- self.label=np.label
- else:
- self.label=np.name
- for inp in nc.inputs:
- s = self.inputs.new('WildcardSocket', inp)
- try:
- if sock := np.inputs.get(inp):
- s.color = inp.color
- except AttributeError: #default bl_idname types like Float and Vector, no biggie
- pass
- except KeyError:
- pass
- for out in nc.outputs:
- s = self.outputs.new('WildcardSocket', out)
- try:
- if sock := np.outputs.get(out):
- s.color = out.color
- except AttributeError: #default bl_idname types like Float and Vector, no biggie
- pass
- except KeyError:
- pass
- self.location = np.location # will get overwritten by Grandalf later.
- else:
- self.label = nc.signature[-1] # which is be the unique name.
- for inp in nc.inputs:
- self.inputs.new('WildcardSocket', inp)
- for out in nc.outputs:
- self.outputs.new('WildcardSocket', out)
-
- # replace names with bl_idnames for reading the tree and solving schemas.
- replace_types = ["NodeGroupInput", "NodeGroupOutput", "SchemaIncomingConnection",
- "SchemaArrayInput", "SchemaConstInput", "SchemaConstOutput", "SchemaIndex",
- "SchemaOutgoingConnection", "SchemaConstantOutput", "SchemaArrayOutput",
- "SchemaArrayInputGet",]
- # anything that gets properties added in the graph... this is a clumsy approach but I need to watch for this
- # in schema generation and this is the easiest way to do it for now.
- custom_props_types = ["LinkArmature", "UtilityKeyframe", "UtilityFCurve", "UtilityDriver", "xFormBone"]
- from_name_filter = ["Driver",]
- to_name_filter = [
- "Custom Object xForm Override",
- "Custom Object",
- "Deform Bones",
- ]
|