| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523 | import bpyfrom bpy.types import Nodefrom .base_definitions import MantisNodedef TellClasses():    return [ InputFloatNode,             InputVectorNode,             InputBooleanNode,             InputBooleanThreeTupleNode,             InputRotationOrderNode,             InputTransformSpaceNode,             InputStringNode,             InputQuaternionNode,             InputQuaternionNodeAA,             InputMatrixNode,             InputLayerMaskNode,             # InputGeometryNode,             InputExistingGeometryObjectNode,             InputExistingGeometryDataNode,                         #  ComposeMatrixNode,             MetaRigMatrixNode,            #  ScaleBoneLengthNode,             UtilityMetaRigNode,             UtilityBonePropertiesNode,             UtilityDriverVariableNode,             UtilityFCurveNode,             UtilityDriverNode,             UtilitySwitchNode,             UtilityCombineThreeBoolNode,             UtilityCombineVectorNode,             UtilityCatStringsNode,            ]def default_traverse(self,socket):    return Noneclass InputFloatNode(Node, MantisNode):    '''A node representing inheritance'''    bl_idname = 'InputFloatNode'    bl_label = "Float"    bl_icon = 'NODE'    def init(self, context):        self.outputs.new('FloatSocket', "Float Input").input = True    class InputVectorNode(Node, MantisNode):    '''A node representing inheritance'''    bl_idname = 'InputVectorNode'    bl_label = "Vector"    bl_icon = 'NODE'    def init(self, context):        self.outputs.new('VectorSocket', "").input = Trueclass InputBooleanNode(Node, MantisNode):    '''A node representing inheritance'''    bl_idname = 'InputBooleanNode'    bl_label = "Boolean"    bl_icon = 'NODE'    def init(self, context):        self.outputs.new('BooleanSocket', "").input = Trueclass InputBooleanThreeTupleNode(Node, MantisNode):    '''A node representing inheritance'''    bl_idname = 'InputBooleanThreeTupleNode'    bl_label = "Boolean Vector"    bl_icon = 'NODE'    def init(self, context):        self.outputs.new('BooleanThreeTupleSocket', "")class InputRotationOrderNode(Node, MantisNode):    '''A node representing inheritance'''    bl_idname = 'InputRotationOrderNode'    bl_label = "Rotation Order"    bl_icon = 'NODE'    def init(self, context):        self.outputs.new('RotationOrderSocket', "").input = Trueclass InputTransformSpaceNode(Node, MantisNode):    '''A node representing inheritance'''    bl_idname = 'InputTransformSpaceNode'    bl_label = "Transform Space"    bl_icon = 'NODE'    def init(self, context):        self.outputs.new('TransformSpaceSocket', "").input = Trueclass InputStringNode(Node, MantisNode):    '''A node representing inheritance'''    bl_idname = 'InputStringNode'    bl_label = "String"    bl_icon = 'NODE'    def init(self, context):        self.outputs.new('StringSocket', "").input = Trueclass InputQuaternionNode(Node, MantisNode):    '''A node representing inheritance'''    bl_idname = 'InputQuaternionNode'    bl_label = "Quaternion"    bl_icon = 'NODE'    def init(self, context):        self.outputs.new('QuaternionSocket', "").input = Trueclass InputQuaternionNodeAA(Node, MantisNode):    '''A node representing inheritance'''    bl_idname = 'InputQuaternionNodeAA'    bl_label = "Axis Angle"    bl_icon = 'NODE'    def init(self, context):        self.outputs.new('QuaternionSocketAA', "").input = Trueclass InputMatrixNode(Node, MantisNode):    '''A node representing inheritance'''    bl_idname = 'InputMatrixNode'    bl_label = "Matrix"    bl_icon = 'NODE'    first_row  : bpy.props.FloatVectorProperty(name="", size=4, default = (1.0, 0.0, 0.0, 0.0,))    second_row : bpy.props.FloatVectorProperty(name="", size=4, default = (0.0, 1.0, 0.0, 0.0,))    third_row  : bpy.props.FloatVectorProperty(name="", size=4, default = (0.0, 0.0, 1.0, 0.0,))    fourth_row : bpy.props.FloatVectorProperty(name="", size=4, default = (0.0, 0.0, 0.0, 1.0,))    def set_matrix(self):        return (self.first_row[ 0], self.first_row[ 1], self.first_row[ 2], self.first_row[ 3],                self.second_row[0], self.second_row[1], self.second_row[2], self.second_row[3],                self.third_row[ 0], self.third_row[ 1], self.third_row[ 2], self.third_row[ 3],                self.fourth_row[0], self.fourth_row[1], self.fourth_row[2], self.fourth_row[3],)    def init(self, context):        self.outputs.new('MatrixSocket', "Matrix")            def update_node(self, context):        self.outputs["Matrix"].default_value = self.set_matrix()    def draw_buttons(self, context, layout):        layout.prop(self, "first_row")        layout.prop(self, "second_row")        layout.prop(self, "third_row")        layout.prop(self, "fourth_row")    def update(self):        mat_sock = self.outputs[0]        mat_sock.default_value = self.set_matrix()# TODO: reimplement the nodes beneath here# from .utilities import QuerySocket, to_mathutils_value# class ComposeMatrixNode(Node, MantisNode):#     '''A utility node for composing a matrix'''#     bl_idname = 'ComposeMatrixNode'#     bl_label = "Compose Matrix"#     bl_icon = 'NODE'#     def init(self, context):#         self.inputs.new('VectorTranslationSocket', "Translation")#         self.inputs.new('GenericRotationSocket', "Rotation")#         self.inputs.new('VectorScaleSocket', "Scale")#         self.outputs.new('MatrixSocket', "Matrix")#     def update_node(self, context = None):#         from mathutils import Matrix, Euler, Quaternion, Vector#         mat_sock = self.outputs[0]#         rotation = Matrix.Identity(4)#         scale = Matrix.Identity(4)#         translation = Matrix.Identity(4)#         sock = QuerySocket(self.inputs["Rotation"])[0]#         val = to_mathutils_value(sock)#         if (val):#             if (isinstance(val, Vector)):#                 val = Euler((val[0], val[1], val[2]), 'XYZ')#             rotation = val.to_matrix().to_4x4()#         sock = QuerySocket(self.inputs["Scale"])[0]#         val = to_mathutils_value(sock)#         if (val):#             if (isinstance(val, Vector)):#                 scale = Matrix.Scale(val[0],4,(1.0,0.0,0.0)) @ Matrix.Scale(val[1],4,(0.0,1.0,0.0)) @ Matrix.Scale(val[2],4,(0.0,0.0,1.0))#         sock = QuerySocket(self.inputs["Translation"])[0]#         val = to_mathutils_value(sock)#         if (val):#             if (isinstance(val, Vector)):#                 translation = Matrix.Translation((val))        #         mat = translation @ rotation @ scale#         mat_sock.default_value = ( mat[0][0], mat[0][1], mat[0][2], mat[0][3],#                                    mat[1][0], mat[1][1], mat[1][2], mat[1][3],#                                    mat[2][0], mat[2][1], mat[2][2], mat[2][3],#                                    mat[3][0], mat[3][1], mat[3][2], mat[3][3], )class ScaleBoneLengthNode(Node, MantisNode):    '''Scale Bone Length'''    bl_idname = 'ScaleBoneLength'    bl_label = "Scale Bone Length"    bl_icon = 'NODE'    # === Optional Functions ===    def init(self, context):        self.inputs.new('MatrixSocket', "In Matrix")        self.inputs.new('FloatSocket', "Factor")        self.outputs.new('MatrixSocket', "Out Matrix")class MetaRigMatrixNode(Node, MantisNode):    # Identical to the above, except    '''A node representing a bone's matrix'''    bl_idname = 'MetaRigMatrixNode'    bl_label = "Matrix"    bl_icon = 'NODE'    first_row  : bpy.props.FloatVectorProperty(name="", size=4, default = (1.0, 0.0, 0.0, 0.0,))    second_row : bpy.props.FloatVectorProperty(name="", size=4, default = (0.0, 1.0, 0.0, 0.0,))    third_row  : bpy.props.FloatVectorProperty(name="", size=4, default = (0.0, 0.0, 1.0, 0.0,))    fourth_row : bpy.props.FloatVectorProperty(name="", size=4, default = (0.0, 0.0, 0.0, 1.0,))    def set_matrix(self):        return (self.first_row[ 0], self.first_row[ 1], self.first_row[ 2], self.first_row[ 3],                self.second_row[0], self.second_row[1], self.second_row[2], self.second_row[3],                self.third_row[ 0], self.third_row[ 1], self.third_row[ 2], self.third_row[ 3],                self.fourth_row[0], self.fourth_row[1], self.fourth_row[2], self.fourth_row[3],)    def init(self, context):        self.outputs.new('MatrixSocket', "Matrix")        def traverse(self, context):        from mathutils import Matrix        v = self.outputs[0].default_value        # print( Matrix( ( ( v[ 0], v[ 1], v[ 2], v[ 3],),        #                  ( v[ 4], v[ 5], v[ 6], v[ 7],),        #                  ( v[ 8], v[ 9], v[10], v[11],),        #                  ( v[12], v[13], v[14], v[15],), ) ) )        return None        def update_node(self, context):        self.outputs["Matrix"].default_value = self.set_matrix()    def update(self):        mat_sock = self.outputs[0]        mat_sock.default_value = self.set_matrix()class UtilityMetaRigNode(Node, MantisNode):    """Gets a matrix from a meta-rig bone."""    bl_idname = "UtilityMetaRig"    bl_label = "Meta-Rig"    bl_icon = "NODE"        armature:bpy.props.StringProperty()    pose_bone:bpy.props.StringProperty()        def init(self, context):        armt = self.inputs.new("EnumMetaRigSocket", "Meta-Armature")        bone = self.inputs.new("EnumMetaBoneSocket", "Meta-Bone")        armt.icon = "OUTLINER_OB_ARMATURE"        bone.icon = "BONE_DATA"        bone.hide=True        self.outputs.new("MatrixSocket", "Matrix")        def display_update(self, parsed_tree, context):        from .base_definitions import get_signature_from_edited_tree        nc = parsed_tree.get(get_signature_from_edited_tree(self, context))        if nc:            self.armature= nc.evaluate_input("Meta-Armature")            self.pose_bone= nc.evaluate_input("Meta-Bone")        if not self.armature:            self.inputs["Meta-Bone"].hide=True        else:            self.inputs["Meta-Bone"].hide=Falseclass UtilityBonePropertiesNode(Node, MantisNode):    """Provides as sockets strings identifying bone transform properties."""    bl_idname = "UtilityBoneProperties"    bl_label = "Bone Properties"    bl_icon = "NODE"    #bl_width_default = 250        def init(self, context):        self.outputs.new("ParameterStringSocket", "matrix")        self.outputs.new("ParameterStringSocket", "matrix_local")        self.outputs.new("ParameterStringSocket", "matrix_basis")        self.outputs.new("ParameterStringSocket", "head")        self.outputs.new("ParameterStringSocket", "tail")        self.outputs.new("ParameterStringSocket", "length")        self.outputs.new("ParameterStringSocket", "rotation")        self.outputs.new("ParameterStringSocket", "location")        self.outputs.new("ParameterStringSocket", "scale")                for o in self.outputs:            o.text_only = Trueclass UtilityDriverVariableNode(Node, MantisNode):    """Creates a variable for use in a driver."""    bl_idname = "UtilityDriverVariable"    bl_label = "Driver Variable"    bl_icon = "NODE"            def init(self, context):        self.inputs.new("EnumDriverVariableType", "Variable Type")        self.inputs.new("ParameterStringSocket", "Property")        self.inputs.new("IntSocket", "Property Index")        self.inputs.new("EnumDriverVariableEvaluationSpace", "Evaluation Space")        self.inputs.new("EnumDriverRotationMode", "Rotation Mode")        self.inputs.new("xFormSocket", "xForm 1")        self.inputs.new("xFormSocket", "xForm 2")        self.outputs.new("DriverVariableSocket", "Driver Variable")            def update_on_socket_change(self, context):        self.update()        def display_update(self, parsed_tree, context):        from .base_definitions import get_signature_from_edited_tree        if context.space_data:            node_tree = context.space_data.path[0].node_tree            nc = parsed_tree.get(get_signature_from_edited_tree(self, context))            if nc:                driver_type = nc.evaluate_input("Variable Type")                if driver_type == 'SINGLE_PROP':                    self.inputs[0].hide = False                    self.inputs[1].hide = False                    self.inputs[2].hide = False                    self.inputs[3].hide = False                    self.inputs[4].hide = False                    self.inputs[5].hide = False                    self.inputs[6].hide = True                elif driver_type == 'LOC_DIFF':                    self.inputs[0].hide = False                    self.inputs[1].hide = True                    self.inputs[2].hide = True                    self.inputs[3].hide = True                    self.inputs[4].hide = True                    self.inputs[5].hide = False                    self.inputs[6].hide = False                elif driver_type == 'ROTATION_DIFF':                    self.inputs[0].hide = False                    self.inputs[1].hide = True                    self.inputs[2].hide = True                    self.inputs[3].hide = True                    self.inputs[4].hide = False                    self.inputs[5].hide = False                    self.inputs[6].hide = False    class UtilityFCurveNode(Node, MantisNode):    """Creates an fCurve for use with a driver."""    bl_idname = "UtilityFCurve"    bl_label = "fCurve"    bl_icon = "NODE"        use_kf_nodes   : bpy.props.BoolProperty(default=False)    fake_fcurve_ob : bpy.props.PointerProperty(type=bpy.types.Object)        def init(self, context):        self.outputs.new("FCurveSocket", "fCurve")        if not self.fake_fcurve_ob:            ob = bpy.data.objects.new("fake_ob_"+self.name, None)            self.fake_fcurve_ob = ob            ob.animation_data_create()            ob.animation_data.action = bpy.data.actions.new('fake_action_'+self.name)            fc = ob.animation_data.action.fcurves.new('location', index=0, action_group='location')            fc.keyframe_points.add(2)            kf0 = fc.keyframe_points[0]; kf0.co_ui = (0, 0)            kf1 = fc.keyframe_points[1]; kf1.co_ui = (1, 1)            #            kf0.interpolation = 'BEZIER'            kf0.handle_left_type  = 'AUTO_CLAMPED'            kf0.handle_right_type = 'AUTO_CLAMPED'            kf1.interpolation = 'BEZIER'            kf1.handle_left_type  = 'AUTO_CLAMPED'            kf1.handle_right_type = 'AUTO_CLAMPED'            #                def draw_buttons(self, context, layout):        if self.use_kf_nodes:            layout.prop(self, "use_kf_nodes",  text="[ Use fCurve data ]", toggle=True, invert_checkbox=True)            layout.operator( 'mantis.fcurve_node_add_kf' )            if (len(self.inputs) > 0):                layout.operator( 'mantis.fcurve_node_remove_kf' )        else:            layout.prop(self, "use_kf_nodes",  text="[ Use Keyframe Nodes ]", toggle=True)            layout.operator('mantis.edit_fcurve_node')                            # THE DIFFICULT part is getting it to show up in the graph editor    # TRY:    #       a modal operator that opens the Graph Editor    #       and then finishes when it is closed    #       it would reveal the object holding the fCurve before    #       showing the Graph Editor    #       And hide it after closing it.    #                                class UtilityDriverNode(Node, MantisNode):    """Represents a Driver relationship"""    bl_idname = "UtilityDriver"    bl_label = "Driver"    bl_icon = "NODE"        def init(self, context):        self.inputs.new("EnumDriverType", "Driver Type")        self.inputs.new("FCurveSocket", "fCurve")        self.inputs.new("StringSocket", "Expression")        self.outputs.new("DriverSocket", "Driver")            def update(self):        return        context = bpy.context        try:            tree = context.space_data.path[0].node_tree            proceed = True        except AttributeError:            proceed = False        if proceed:            from mantis.f_nodegraph import (GetDownstreamXFormNodes, get_node_container)            if (node_container := get_node_container(self, context)[0]):                dType = node_container.evaluate_input("Driver Type")            else:                dType = self.inputs[0].default_value                        if dType == 'SCRIPTED':                self.inputs["Expression"].hide = False            else:                self.inputs["Expression"].hide = True        def draw_buttons(self, context, layout):        layout.operator( 'mantis.driver_node_add_variable' )        if (len(self.inputs) > 2):            layout.operator( 'mantis.driver_node_remove_variable' )class UtilitySwitchNode(Node, MantisNode):    """Represents a switch relationship between one driver property and one or more driven properties."""    bl_idname = "UtilitySwitch"    bl_label = "Switch"    bl_icon = "NODE"        def init(self, context):        self.inputs.new("xFormSocket", "xForm")        self.inputs.new("ParameterStringSocket", "Parameter")        self.inputs.new("IntSocket", "Parameter Index")        self.inputs.new("BooleanSocket", "Invert Switch")        self.outputs.new("DriverSocket", "Driver")class UtilityCombineThreeBoolNode(Node, MantisNode):    """Combines three booleans into a three-bool."""    bl_idname = "UtilityCombineThreeBool"    bl_label = "CombineThreeBool"    bl_icon = "NODE"        def init(self, context):        self.inputs.new("BooleanSocket", "X")        self.inputs.new("BooleanSocket", "Y")        self.inputs.new("BooleanSocket", "Z")        self.outputs.new("BooleanThreeTupleSocket", "Three-Bool")        # this node should eventually just be a Combine Boolean Three-Tuple node        # and the "Driver" output will need to be figured out some other wayclass UtilityCombineVectorNode(Node, MantisNode):    """Combines three floats into a vector."""    bl_idname = "UtilityCombineVector"    bl_label = "CombineVector"    bl_icon = "NODE"        def init(self, context):        self.inputs.new("FloatSocket", "X")        self.inputs.new("FloatSocket", "Y")        self.inputs.new("FloatSocket", "Z")        self.outputs.new("VectorSocket", "Vector")        # this node should eventually just be a Combine Boolean Three-Tuple node        # and the "Driver" output will need to be figured out some other way        class UtilityCatStringsNode(Node, MantisNode):    """Adds a suffix to a string"""    bl_idname = "UtilityCatStrings"    bl_label = "Concatenate Strings"    bl_icon = "NODE"        def init(self, context):        self.inputs.new("StringSocket", "String_1")        self.inputs.new("StringSocket", "String_2")        self.outputs.new("StringSocket", "OutputString")    class InputLayerMaskNode(Node, MantisNode):    """Represents a layer mask for a bone."""    bl_idname = "InputLayerMaskNode"    bl_label = "Layer Mask"    bl_icon = "NODE"        def init(self, context):        self.outputs.new("LayerMaskInputSocket", "Layer Mask")class InputExistingGeometryObjectNode(Node, MantisNode):    """Represents an existing geometry object from within the scene."""    bl_idname = "InputExistingGeometryObject"    bl_label = "Existing Object"    bl_icon = "NODE"        def init(self, context):        self.inputs.new("StringSocket", "Name")        self.outputs.new("xFormSocket", "Object")class InputExistingGeometryDataNode(Node, MantisNode):    """Represents a mesh or curve datablock from the scene."""    bl_idname = "InputExistingGeometryData"    bl_label = "Existing Geometry"    bl_icon = "NODE"        def init(self, context):        self.inputs.new("StringSocket", "Name")        self.outputs.new("GeometrySocket", "Geometry")
 |