| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268 |
- import bpy
- from .base_definitions import xFormNode
- from bpy.types import Node
- from mantis.utilities import (prRed, prGreen, prPurple, prWhite,
- prOrange,
- wrapRed, wrapGreen, wrapPurple, wrapWhite,
- wrapOrange,)
- from .base_definitions import get_signature_from_edited_tree
- def TellClasses():
- return [
- # xFormNullNode,
- xFormBoneNode,
- xFormRootNode,
- xFormArmatureNode,
- xFormGeometryObjectNode,
- ]
- def default_traverse(self, socket):
- if (socket == self.outputs["xForm Out"]):
- return self.inputs["Relationship"]
- if (socket == self.inputs["Relationship"]):
- return self.outputs["xForm Out"]
- return None
- # Representing an Empty or non-armature-Object
- # class xFormNullNode(Node, xFormNode):
- # '''A node representing a Null node'''
- # bl_idname = 'xFormNullNode'
- # bl_label = "Null"
- # bl_icon = 'EMPTY_AXIS'
- # # === Optional Functions ===
- # def init(self, context):
- # self.inputs.new('StringSocket', "Name")
- # self.inputs.new('RelationshipSocket', "Relationship")
- # self.inputs.new('RotationOrderSocket', "Rotation Order")
- # self.inputs.new('MatrixSocket', "Matrix")
- # self.outputs.new('xFormSocket', "xForm Out")
- def check_if_connected(start, end, line):
- started=False
- for path_nc in line:
- prWhite(" ", path_nc.signature)
- if path_nc.signature == start.signature:
- started = True
- elif path_nc.signature == end.signature:
- break
- if started:
- if path_nc.inputs.get("Connected"):
- if path_nc.evaluate_input("Connected") == False:
- return False
- else:
- return False
- return True
- class xFormRootNode(Node, xFormNode):
- '''A node representing the world node'''
- bl_idname = 'xFormRootNode'
- bl_label = "World Root"
- bl_icon = 'WORLD'
- def init(self, context):
- self.outputs.new('RelationshipSocket', "World Out")
-
- class xFormBoneNode(Node, xFormNode):
- '''A node representing a Bone'''
- bl_idname = 'xFormBoneNode'
- bl_label = "Bone"
- bl_icon = 'BONE_DATA'
-
- display_ik_settings : bpy.props.BoolProperty(default=False)
- display_vp_settings : bpy.props.BoolProperty(default=False)
- display_def_settings : bpy.props.BoolProperty(default=False)
- socket_count : bpy.props.IntProperty()
-
- def init(self, context):
- self.inputs.new('StringSocket', "Name")
- self.inputs.new('RotationOrderSocket', "Rotation Order")
- self.inputs.new('RelationshipSocket', "Relationship")
- self.inputs.new('MatrixSocket', "Matrix")
- # IK SETTINGS
- a = []
- # a.append(self.inputs.new ('LabelSocket', "IK Settings"))
- a.append(self.inputs.new ('FloatFactorSocket', "IK Stretch"))
- a.append(self.inputs.new ('BooleanThreeTupleSocket', "Lock IK"))
- a.append(self.inputs.new ('NodeSocketVector', "IK Stiffness"))
- a.append(self.inputs.new ('BooleanThreeTupleSocket', "Limit IK"))
- a.append(self.inputs.new ('NodeSocketFloatAngle', "X Min"))
- a.append(self.inputs.new ('NodeSocketFloatAngle', "X Max"))
- a.append(self.inputs.new ('NodeSocketFloatAngle', "Y Min"))
- a.append(self.inputs.new ('NodeSocketFloatAngle', "Y Max"))
- a.append(self.inputs.new ('NodeSocketFloatAngle', "Z Min"))
- a.append(self.inputs.new ('NodeSocketFloatAngle', "Z Max"))
- #4-14
-
- # visual settings:
- b = []
- b.append(self.inputs.new ('LayerMaskSocket', "Layer Mask"))
- b.append(self.inputs.new ('xFormSocket', "Custom Object"))
- b.append(self.inputs.new ('xFormSocket', "Custom Object xForm Override"))
- b.append(self.inputs.new ('BooleanSocket', "Custom Object Scale to Bone Length"))
- b.append(self.inputs.new ('BooleanSocket', "Custom Object Wireframe"))
- b.append(self.inputs.new ('VectorScaleSocket', "Custom Object Scale"))
- b.append(self.inputs.new ('VectorSocket', "Custom Object Translation"))
- b.append(self.inputs.new ('VectorEulerSocket', "Custom Object Rotation"))
- b.append(self.inputs.new ('StringSocket', "Bone Group"))
- # 16-22
- # Deform Settings:
- c = []
- c.append(self.inputs.new ('BooleanSocket', "Deform"))
- c.append(self.inputs.new ('FloatPositiveSocket', "Envelope Distance"))
- c.append(self.inputs.new ('FloatFactorSocket', "Envelope Weight"))
- c.append(self.inputs.new ('BooleanSocket', "Envelope Multiply"))
- c.append(self.inputs.new ('FloatPositiveSocket', "Envelope Head Radius"))
- c.append(self.inputs.new ('FloatPositiveSocket', "Envelope Tail Radius"))
- #24-28
-
- # c[0].default_value=False
-
- # Hide should be last
- b.append(self.inputs.new ('HideSocket', "Hide"))
-
-
- for sock in a:
- sock.hide = True
- for sock in b:
- if sock.name in ['Custom Object', 'Layer Mask']:
- continue
- sock.hide = True
- for sock in c:
- if sock.name == 'Deform':
- continue
- sock.hide = True
-
- # Thinking about using colors for nodes, why not?
- # cxForm = (0.443137, 0.242157, 0.188235,) #could even fetch the theme colors...
- # self.color=cxForm
- # self.use_custom_color=True
- self.socket_count = len(self.inputs)
- #
- self.outputs.new('xFormSocket', "xForm Out")
-
- def draw_buttons(self, context, layout):
- layout.operator("mantis.add_custom_property", text='+Add Custom Parameter')
- # layout.label(text="Edit Parameter ... not implemented")
- if (len(self.inputs) > self.socket_count):
- layout.operator("mantis.remove_custom_property", text='-Remove Custom Parameter')
- else:
- layout.label(text="")
-
- def display_update(self, parsed_tree, context):
- if context.space_data:
- node_tree = context.space_data.path[0].node_tree
- nc = parsed_tree.get(get_signature_from_edited_tree(self, context))
- other_nc = None
- if len(self.inputs.get("Relationship").links)>0:
- prev_node = self.inputs.get("Relationship").links[0].from_node
- if prev_node:
- other_nc = parsed_tree.get(get_signature_from_edited_tree(prev_node, context))
-
- if nc and other_nc:
- self.display_vp_settings = nc.inputs["Custom Object"].is_connected
- self.display_def_settings = nc.evaluate_input("Deform")
- self.display_ik_settings = False
- #
- from .node_container_common import ( trace_all_lines_up,
- trace_single_line)
- trace = trace_all_lines_up(nc, "xForm Out")
-
- for key in trace.keys():
- if (ik_nc:= parsed_tree.get(key)):
- if ik_nc.__class__.__name__ in ["LinkInverseKinematics"]:
- # if the tree is invalid? This shouldn't be necessary.
- if ik_nc.inputs["Input Relationship"].is_connected:
- chain_count = ik_nc.evaluate_input("Chain Length")
- if chain_count == 0:
- self.display_ik_settings = True
- else:
- if ik_nc.evaluate_input("Use Tail") == False:
- chain_count+=1
- for line in trace[key]:
- # preprocess it to get rid of non-xForms:
- xForm_line=[]
- for path_nc in line:
- if path_nc == ik_nc:
- if ik_nc.inputs["Input Relationship"].links[0].from_node != prev_path_nc:
- break # not a constraint connection
- if path_nc.node_type == 'XFORM':
- xForm_line.append(path_nc)
- prev_path_nc = path_nc
-
- else:
- if len(xForm_line) < chain_count:
- self.display_ik_settings = True
-
- inp = nc.inputs["Relationship"]
- link = None
- if inp.is_connected:
- link = inp.links[0]
- while(link):
- if link.from_node.__class__.__name__ in ["LinkInverseKinematics"]:
- self.display_ik_settings = link.from_node.evaluate_input("Use Tail")
- break
- inp = link.from_node.outputs[link.from_socket]
- inp = inp.traverse_target
- if not inp:
- break
- if inp.links:
- link = inp.links[0]
- else:
- link = None
- #
- if self.display_ik_settings == True:
- for inp in self.inputs[4:14]:
- inp.hide = False
- else:
- for inp in self.inputs[4:14]:
- inp.hide = True
- if self.display_vp_settings == True:
- for inp in self.inputs[16:22]:
- inp.hide = False
- else:
- for inp in self.inputs[16:22]:
- inp.hide = True
- #
- if self.display_def_settings == True:
- for inp in self.inputs[24:29]:
- inp.hide = False
- else:
- for inp in self.inputs[24:29]:
- inp.hide = True
-
-
- # def copy(ectype, archtype):
- # # TODO: automatically avoid duplicating names
- # ectype.inputs["Name"].default_value = ""
- class xFormArmatureNode(Node, xFormNode):
- '''A node representing an Armature object node'''
- bl_idname = 'xFormArmatureNode'
- bl_label = "Armature"
- bl_icon = 'OUTLINER_OB_ARMATURE'
- def init(self, context):
- self.inputs.new('StringSocket', "Name")
- self.inputs.new('RelationshipSocket', "Relationship")
- self.inputs.new('RotationOrderSocket', "Rotation Order")
- self.inputs.new('MatrixSocket', "Matrix")
- self.outputs.new('xFormSocket', "xForm Out")
- class xFormGeometryObjectNode(Node, xFormNode):
- """Represents a curve or mesh object."""
- bl_idname = "xFormGeometryObject"
- bl_label = "Geometry Object"
- bl_icon = "EMPTY_AXIS"
-
- def init(self, context):
- self.inputs.new('StringSocket', "Name")
- self.inputs.new('GeometrySocket', "Geometry")
- self.inputs.new('MatrixSocket', "Matrix")
- self.inputs.new('RelationshipSocket', "Relationship")
- self.outputs.new('xFormSocket', "xForm Out")
|