| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839 | 
							- from .node_container_common import *
 
- from .base_definitions import MantisNode, NodeSocket
 
- def TellClasses():
 
-              
 
-     return [ 
 
-              # xForm
 
-              xFormArmature,
 
-              xFormBone,
 
-              xFormGeometryObject,
 
-              xFormObjectInstance,
 
-            ]
 
- #*#-------------------------------#++#-------------------------------#*#
 
- # X - F O R M   N O D E S
 
- #*#-------------------------------#++#-------------------------------#*#
 
- def reset_object_data(ob):
 
-     # moving this to a common function so I can figure out the details later
 
-     ob.constraints.clear()
 
-     ob.animation_data_clear() # this is a little dangerous. TODO find a better solution since this can wipe animation the user wants to keep
 
-     ob.modifiers.clear() # I would also like a way to copy modifiers and their settings, or bake them down. oh well
 
- def get_parent(node_container, type = 'XFORM'):
 
-     # type variable for selecting whether to get either 
 
-     #   the parent xForm  or the inheritance node
 
-     node_line, socket = trace_single_line(node_container, "Relationship")
 
-     parent_nc = None
 
-     for i in range(len(node_line)):
 
-         # check each of the possible parent types.
 
-         if ( (node_line[ i ].__class__.__name__ == 'LinkInherit') ):
 
-             try: # it's the next one
 
-                 if (type == 'XFORM'):
 
-                     return node_line[ i + 1 ]
 
-                 else: # type = 'LINK'
 
-                     return node_line[ i ]
 
-             except IndexError: # if there is no next one...
 
-                 return None # then there's no parent!
 
-     return None
 
- class xFormArmature(MantisNode):
 
-     '''A node representing an armature object'''
 
-     
 
-     bObject = None
 
-     
 
-     def __init__(self, signature, base_tree):
 
-         super().__init__(signature, base_tree)
 
-         inputs = [
 
-             "Name"           ,
 
-             "Rotation Order" ,
 
-             "Matrix"         ,
 
-             "Relationship"   ,
 
-         ]
 
-         outputs = [
 
-          "xForm Out",
 
-         ]
 
-         self.inputs.init_sockets(inputs)
 
-         self.outputs.init_sockets(outputs)
 
-         self.init_parameters()
 
-         self.set_traverse([("Relationship", "xForm Out")])
 
-         self.node_type = 'XFORM'
 
-         self.prepared = True
 
-     
 
-     def bExecute(self, bContext = None,):
 
-         # from .utilities import get_node_prototype
 
-         
 
-         import bpy
 
-         if (not isinstance(bContext, bpy.types.Context)):
 
-             raise RuntimeError("Incorrect context")
 
-         name = self.evaluate_input("Name")
 
-         if not ( matrix := self.evaluate_input('Matrix')):
 
-             raise RuntimeError(wrapRed(f"No matrix found for Armature {self}"))
 
-         self.parameters['Matrix'] = matrix
 
-         reset_transforms = False
 
-         #check if an object by the name exists
 
-         if (name) and (ob := bpy.data.objects.get(name)):
 
-             if (ob.animation_data):
 
-                 while (ob.animation_data.drivers):
 
-                         ob.animation_data.drivers.remove(ob.animation_data.drivers[-1])
 
-             for pb in ob.pose.bones:
 
-                 # clear it, even after deleting the edit bones, 
 
-                 #  if we create them again the pose bones will be reused 
 
-                 while (pb.constraints):
 
-                     pb.constraints.remove(pb.constraints[-1])
 
-                 if reset_transforms:
 
-                     pb.location = (0,0,0)
 
-                     pb.rotation_euler = (0,0,0)
 
-                     pb.rotation_quaternion = (1.0,0,0,0)
 
-                     pb.rotation_axis_angle = (0,0,1.0,0)
 
-                     pb.scale = (1.0,1.0,1.0)
 
-             # feels ugly and bad, whatever
 
-             collections = []
 
-             for bc in ob.data.collections:
 
-                 collections.append(bc)
 
-             for bc in collections:
 
-                 ob.data.collections.remove(bc)
 
-             del collections
 
-             # end ugly/bad
 
-         else:
 
-             # Create the Object
 
-             ob = bpy.data.objects.new(name, bpy.data.armatures.new(name)) #create ob
 
-             if (ob.name != name):
 
-                 raise RuntimeError("Could not create xForm object", name)
 
-             
 
-         self.bObject = ob.name
 
-         ob.matrix_world = matrix.copy()
 
-         ob.data.pose_position = 'REST'
 
-         
 
-         if True:
 
-             from bpy.types import EditBone
 
-             parent_nc = get_parent(self, type='LINK')
 
-             if parent_nc:
 
-                 parent = parent_nc.inputs['Parent'].links[0].from_node.bGetObject(mode = 'OBJECT')
 
-                 ob.parent = parent
 
-             
 
-         
 
-         # Link to Scene:
 
-         if (ob.name not in bContext.view_layer.active_layer_collection.collection.objects):
 
-             bContext.view_layer.active_layer_collection.collection.objects.link(ob)
 
-         #self.bParent(bContext)
 
-         
 
-         print( wrapGreen("Created Armature object: ")+ wrapWhite(ob.name))
 
-         # Finalize the action
 
-         # oddly, overriding context doesn't seem to work
 
-         try:
 
-             bpy.ops.object.select_all(action='DESELECT')
 
-         except RuntimeError:
 
-             pass # we're already in edit mode, should be OK to do this.
 
-         bContext.view_layer.objects.active = ob
 
-         selected=[]
 
-         for other_ob in bpy.data.objects:
 
-             if other_ob.mode == "EDIT":
 
-                 selected.append(other_ob)
 
-         selected.append(ob)
 
-         context_override = {"active_object":ob, "selected_objects":selected}
 
-         print("Changing Armature Mode to " +wrapPurple("EDIT"))
 
-         with bContext.temp_override(**context_override):
 
-             bpy.ops.object.mode_set(mode='EDIT')
 
-         if ob.mode != "EDIT":
 
-             prRed("eh?")
 
-         # clear it
 
-         while (len(ob.data.edit_bones) > 0):
 
-             ob.data.edit_bones.remove(ob.data.edit_bones[0])
 
-         # bContext.view_layer.objects.active = prevAct
 
-         
 
-         
 
-         self.executed = True
 
-     
 
-     def bGetObject(self, mode = ''):
 
-         import bpy; return bpy.data.objects[self.bObject]
 
- bone_inputs= [
 
-          "Name",
 
-          "Rotation Order",
 
-          "Matrix",
 
-          "Relationship",
 
-          # IK settings
 
-          "IK Stretch",
 
-          "Lock IK",
 
-          "IK Stiffness",
 
-          "Limit IK",
 
-          "X Min",
 
-          "X Max",
 
-          "Y Min",
 
-          "Y Max",
 
-          "Z Min",
 
-          "Z Max",
 
-          # Visual stuff
 
-          "Bone Collection",
 
-          "Hide",
 
-          "Custom Object",
 
-          "Custom Object xForm Override",
 
-          "Custom Object Scale to Bone Length",
 
-          "Custom Object Wireframe",
 
-          "Custom Object Scale",
 
-          "Custom Object Translation",
 
-          "Custom Object Rotation",
 
-          # Deform Stuff
 
-          "Deform",
 
-          "Envelope Distance",
 
-          "Envelope Weight",
 
-          "Envelope Multiply",
 
-          "Envelope Head Radius",
 
-          "Envelope Tail Radius",
 
-          # BBone stuff:
 
-          "BBone Segments",
 
-          "BBone X Size",
 
-          "BBone Z Size",
 
-          "BBone HQ Deformation",
 
-          "BBone X Curve-In",
 
-          "BBone Z Curve-In",
 
-          "BBone X Curve-Out",
 
-          "BBone Z Curve-Out",
 
-          "BBone Roll-In",
 
-          "BBone Roll-Out",
 
-          "BBone Inherit End Roll",
 
-          "BBone Scale-In",
 
-          "BBone Scale-Out",
 
-          "BBone Ease-In",
 
-          "BBone Ease-Out",
 
-          "BBone Easing",
 
-          "BBone Start Handle Type",
 
-          "BBone Custom Start Handle",
 
-          "BBone Start Handle Scale",
 
-          "BBone Start Handle Ease",
 
-          "BBone End Handle Type",
 
-          "BBone Custom End Handle",
 
-          "BBone End Handle Scale",
 
-          "BBone End Handle Ease",
 
-          # locks
 
-          "Lock Location",
 
-          "Lock Rotation",
 
-          "Lock Scale",
 
- ]
 
- class xFormBone(MantisNode):
 
-     '''A node representing a bone in an armature'''
 
-     # DO: make a way to identify which armature this belongs to
 
-     def __init__(self, signature, base_tree):
 
-         super().__init__(signature, base_tree)
 
-         outputs = [
 
-          "xForm Out",
 
-         ]
 
-         self.inputs.init_sockets(bone_inputs)
 
-         self.outputs.init_sockets(outputs)
 
-         self.init_parameters()
 
-         self.set_traverse([("Relationship", "xForm Out")])
 
-         self.node_type = 'XFORM'
 
-         self.prepared = True
 
-         self.bObject=None
 
-     
 
-     def bGetParentArmature(self):
 
-         finished = False
 
-         if (trace := trace_single_line(self, "Relationship")[0] ) :
 
-             for i in range(len(trace)):
 
-                 # have to look in reverse, actually TODO
 
-                 if ( isinstance(trace[ i ], xFormArmature ) ):
 
-                     return trace[ i ].bGetObject()
 
-         return None
 
-         #should do the trick...
 
-     
 
-     def bSetParent(self, eb):
 
-         # print (self.bObject)
 
-         from bpy.types import EditBone
 
-         parent_nc = get_parent(self, type='LINK')
 
-         # print (self, parent_nc.inputs['Parent'].from_node)
 
-         parent=None
 
-         if parent_nc.inputs['Parent'].links[0].from_node.node_type == 'XFORM':
 
-             parent = parent_nc.inputs['Parent'].links[0].from_node.bGetObject(mode = 'EDIT')
 
-         else:
 
-             raise RuntimeError(wrapRed(f"Cannot set parent for node {self}"))
 
-         if isinstance(parent, EditBone):
 
-             eb.parent = parent
 
-         
 
-         #DUMMY
 
-         # I NEED TO GET THE LINK NC
 
-         # IDIOT
 
-             
 
-         eb.use_connect = parent_nc.evaluate_input("Connected")
 
-         eb.use_inherit_rotation = parent_nc.evaluate_input("Inherit Rotation")
 
-         eb.inherit_scale = parent_nc.evaluate_input("Inherit Scale")
 
-         # otherwise, no need to do anything.
 
-         
 
-     
 
-     def bExecute(self, bContext = None,): #possibly will need to pass context?
 
-         import bpy
 
-         from mathutils import Vector
 
-         if not (name := self.evaluate_input("Name")):
 
-             raise RuntimeError(wrapRed(f"Could not set name for bone in {self}"))
 
-         if (not isinstance(bContext, bpy.types.Context)):
 
-             raise RuntimeError("Incorrect context")
 
-         if not (xF := self.bGetParentArmature()):
 
-             raise RuntimeError("Could not create edit bone: ", name, " from node:", self.signature, " Reason: No armature object to add bone to.")
 
-         
 
-         if not ( matrix := self.evaluate_input('Matrix')):
 
-             # print(self.inputs['Matrix'].links[0].from_node.parameters)
 
-             raise RuntimeError(wrapRed(f"No matrix found for Bone {self}"))
 
-         
 
-         self.parameters['Matrix'] = matrix
 
-         length = matrix[3][3]
 
-         
 
-         if (xF):
 
-             if (xF.mode != "EDIT"):
 
-                 raise RuntimeError("Armature Object Not in Edit Mode, exiting...")
 
-         #
 
-         # Create the Object
 
-         d = xF.data
 
-         eb = d.edit_bones.new(name)
 
-         # Bone Collections:
 
-         #    We treat each separate string as a Bone Collection that this object belongs to
 
-         #    Bone Collections are fully qualified by their hierarchy.
 
-         #    Separate Strings with "|" and indicate hierarchy with ">". These are special characters.
 
-         # NOTE: if the user names the collections differently at different times, this will take the FIRST definition and go with it
 
-         sCols = self.evaluate_input("Bone Collection")
 
-         bone_collections = sCols.split("|")
 
-         for collection_list in bone_collections:
 
-             hierarchy = collection_list.split(">")
 
-             col_parent = None
 
-             for sCol in hierarchy:
 
-                 if ( col := d.collections.get(sCol) ) is None:
 
-                     col = d.collections.new(sCol)
 
-                 col.parent = col_parent
 
-                 col_parent = col
 
-             col.assign(eb)
 
-         
 
-         if (eb.name != name):
 
-             prRed(f"Expected bone of name: {name}, got {eb.name} instead.")
 
-             raise RuntimeError("Could not create bone ", name, "; Perhaps there is a duplicate bone name in the node tree?")
 
-         eb.matrix  = matrix.copy()
 
-         tailoffset = Vector((0,length,0)) #Vector((0,self.tailoffset, 0))
 
-         tailoffset = matrix.copy().to_3x3() @ tailoffset
 
-         eb.tail    = eb.head + tailoffset
 
-         if (eb.name != name):
 
-             raise RuntimeError("Could not create edit bone: ", name)
 
-         assert (eb.name), "Bone must have a name."
 
-         self.bObject = eb.name
 
-         # The bone should have relationships going in at this point.
 
-         
 
-         self.bSetParent(eb)
 
-         if eb.head == eb.tail:
 
-             raise RuntimeError(wrapRed(f"Could not create edit bone: {name} because bone head was located in the same place as bone tail."))
 
-         
 
-         # Setup Deform attributes...
 
-         eb.use_deform            = self.evaluate_input("Deform")
 
-         eb.envelope_distance     = self.evaluate_input("Envelope Distance")
 
-         eb.envelope_weight       = self.evaluate_input("Envelope Weight")
 
-         eb.use_envelope_multiply = self.evaluate_input("Envelope Multiply")
 
-         eb.head_radius           = self.evaluate_input("Envelope Head Radius")
 
-         eb.tail_radius           = self.evaluate_input("Envelope Tail Radius")
 
-         print( wrapGreen("Created Bone: ") + wrapOrange(eb.name) + wrapGreen(" in ") + wrapWhite(self.bGetParentArmature().name))
 
-         self.executed = True
 
-     def bFinalize(self, bContext = None):
 
-         do_bb=False
 
-         b = self.bGetParentArmature().data.bones[self.bObject]
 
-         b.bbone_x = self.evaluate_input("BBone X Size"); b.bbone_x = max(b.bbone_x, 0.0002)
 
-         b.bbone_z = self.evaluate_input("BBone Z Size"); b.bbone_z = max(b.bbone_z, 0.0002)
 
-         if (segs := self.evaluate_input("BBone Segments")) > 1:
 
-             do_bb=True
 
-             b.bbone_segments = segs
 
-             b.bbone_x = self.evaluate_input("BBone X Size")
 
-             b.bbone_z = self.evaluate_input("BBone Z Size")
 
-             if self.evaluate_input("BBone HQ Deformation"):
 
-                 b.bbone_mapping_mode = "CURVED"
 
-             # 'bbone_handle_type_start'    : ("BBone Start Handle Type", "AUTO"),
 
-             # 'bbone_handle_type_end'      : ("BBone End Handle Type", "AUTO"),
 
-             # 'bbone_custom_handle_start'  : ("BBone Custom Start Handle", "AUTO"),
 
-             # 'bbone_custom_handle_end'    : ("BBone Custom End Handle", "AUTO"),
 
-             if handle_type := self.evaluate_input("BBone Start Handle Type"):
 
-                 b.bbone_handle_type_start = handle_type
 
-             if handle_type := self.evaluate_input("BBone End Handle Type"):
 
-                 b.bbone_handle_type_end = handle_type
 
-             
 
-             try:
 
-                 if (custom_handle := self.evaluate_input("BBone Custom Start Handle")):
 
-                     b.bbone_custom_handle_start = self.bGetParentArmature().data.bones[custom_handle]
 
-                 # hypothetically we should support xForm inputs.... but we won't do that for now
 
-                 # elif custom_handle is None:
 
-                 #     b.bbone_custom_handle_start = self.inputs["BBone Custom Start Handle"].links[0].from_node.bGetObject().name
 
-                 if (custom_handle := self.evaluate_input("BBone Custom End Handle")):
 
-                     b.bbone_custom_handle_end = self.bGetParentArmature().data.bones[custom_handle]
 
-             except KeyError:
 
-                 prRed("Warning: BBone start or end handle not set because of missing bone in armature.")
 
-             
 
-             b.bbone_curveinx = self.evaluate_input("BBone X Curve-In")
 
-             b.bbone_curveinz = self.evaluate_input("BBone Z Curve-In")
 
-             b.bbone_curveoutx = self.evaluate_input("BBone X Curve-Out")
 
-             b.bbone_curveoutz = self.evaluate_input("BBone Z Curve-Out")
 
-             # 'bbone_curveinx'             : ("BBone X Curve-In", pb.bone.bbone_curveinx),
 
-             # 'bbone_curveinz'             : ("BBone Z Curve-In", pb.bone.bbone_curveinz),
 
-             # 'bbone_curveoutx'            : ("BBone X Curve-Out", pb.bone.bbone_curveoutx),
 
-             # 'bbone_curveoutz'            : ("BBone Z Curve-Out", pb.bone.bbone_curveoutz),
 
-             # TODO this section should be done with props-socket thing
 
-             b.bbone_handle_use_scale_start = self.evaluate_input("BBone Start Handle Scale")
 
-             b.bbone_handle_use_scale_end = self.evaluate_input("BBone End Handle Scale")
 
-             
 
-         import bpy
 
-         from .drivers import MantisDriver
 
-         # prevAct = bContext.view_layer.objects.active
 
-         # bContext.view_layer.objects.active = ob
 
-         # bpy.ops.object.mode_set(mode='OBJECT')
 
-         # bContext.view_layer.objects.active = prevAct
 
-         #
 
-         #get relationship
 
-         # ensure we have a pose bone...
 
-         # set the ik parameters
 
-         #
 
-         #
 
-         # Don't need to bother about whatever that was
 
-         
 
-         pb = self.bGetParentArmature().pose.bones[self.bObject]
 
-         rotation_mode = self.evaluate_input("Rotation Order")
 
-         if rotation_mode == "AUTO": rotation_mode = "XYZ"
 
-         pb.rotation_mode = rotation_mode
 
-         pb.id_properties_clear()
 
-         # these are kept around unless explicitly deleted.
 
-         # from .utilities import get_node_prototype
 
-         # np = get_node_prototype(self.signature, self.base_tree)
 
-         driver = None
 
-         do_prints=False
 
-         # detect custom inputs
 
-         for i, inp in enumerate(self.inputs.values()):
 
-             if inp.name in bone_inputs:
 
-                 continue
 
-             
 
-             
 
-             name = inp.name
 
-             try:
 
-                 value = self.evaluate_input(inp.name)
 
-             except KeyError as e:
 
-                 trace = trace_single_line(self, inp.name)
 
-                 if do_prints: print(trace[0][-1], trace[1])
 
-                 if do_prints: print (trace[0][-1].parameters)
 
-                 raise e
 
-             # This may be driven, so let's do this:
 
-             if do_prints: print (value)
 
-             if (isinstance(value, tuple)):
 
-                 # it's either a CombineThreeBool or a CombineVector.
 
-                 prRed("COMITTING SUICIDE NOW!!")
 
-                 bpy.ops.wm.quit_blender()
 
-             if (isinstance(value, MantisDriver)):
 
-                 # the value should be the default for its socket...
 
-                 if do_prints: print (type(self.parameters[inp.name]))
 
-                 type_val_map = {
 
-                     str:"",
 
-                     bool:False,
 
-                     int:0,
 
-                     float:0.0,
 
-                     bpy.types.bpy_prop_array:(0,0,0),
 
-                     }
 
-                 driver = value
 
-                 value = type_val_map[type(self.parameters[inp.name])]
 
-             if (value is None):
 
-                 prRed("This is probably not supposed to happen")
 
-                 value = 0
 
-                 raise RuntimeError("Could not set value of custom parameter")
 
-                 # it creates a more confusing error later sometimes, better to catch it here.
 
-             
 
-             # IMPORTANT: Is it possible for more than one driver to
 
-             #   come through here, and for the variable to be
 
-             #   overwritten?
 
-                 
 
-             #TODO important
 
-             #from rna_prop_ui import rna_idprop_ui_create
 
-             # use this ^
 
-             
 
-             # add the custom properties to the **Pose Bone**
 
-             pb[name] = value
 
-             # This is much simpler now.
 
-             ui_data = pb.id_properties_ui(name)
 
-             description=''
 
-             ui_data.update(
 
-                 description=description,#inp.description,
 
-                 default=value,)
 
-             #if a number
 
-             
 
-             if type(value) == float:
 
-                 ui_data.update(
 
-                     min = inp.min,
 
-                     max = inp.max,
 
-                     soft_min = inp.soft_min,
 
-                     soft_max = inp.soft_max,)
 
-                         
 
-             elif type(value) == int:
 
-                 ui_data.update(
 
-                     min = int(inp.min),
 
-                     max = int(inp.max),
 
-                     soft_min = int(inp.soft_min),
 
-                     soft_max = int(inp.soft_max),)
 
-             elif type(value) == bool:
 
-                 ui_data.update() # TODO I can't figure out what the update function expects because it isn't documented
 
-         
 
-         if (pb.is_in_ik_chain):
 
-             # this  props_socket thing wasn't really meant to work here but it does, neat
 
-             props_sockets = {
 
-             'ik_stretch'          : ("IK Stretch", 0),
 
-             'lock_ik_x'           : (("Lock IK", 0), False),
 
-             'lock_ik_y'           : (("Lock IK", 1), False),
 
-             'lock_ik_z'           : (("Lock IK", 2), False),
 
-             'ik_stiffness_x'      : (("IK Stiffness", 0), 0.0),
 
-             'ik_stiffness_y'      : (("IK Stiffness", 1), 0.0),
 
-             'ik_stiffness_z'      : (("IK Stiffness", 2), 0.0),
 
-             'use_ik_limit_x'      : (("Limit IK", 0), False),
 
-             'use_ik_limit_y'      : (("Limit IK", 1), False),
 
-             'use_ik_limit_z'      : (("Limit IK", 2), False),
 
-             'ik_min_x'            : ("X Min", 0),
 
-             'ik_max_x'            : ("X Max", 0),
 
-             'ik_min_y'            : ("Y Min", 0),
 
-             'ik_max_y'            : ("Y Max", 0),
 
-             'ik_min_z'            : ("Z Min", 0),
 
-             'ik_max_z'            : ("Z Max", 0),
 
-             }
 
-             evaluate_sockets(self, pb, props_sockets)
 
-         if do_bb:
 
-             props_sockets = {
 
-             'bbone_curveinx'             : ("BBone X Curve-In", pb.bone.bbone_curveinx),
 
-             'bbone_curveinz'             : ("BBone Z Curve-In", pb.bone.bbone_curveinz),
 
-             'bbone_curveoutx'            : ("BBone X Curve-Out", pb.bone.bbone_curveoutx),
 
-             'bbone_curveoutz'            : ("BBone Z Curve-Out", pb.bone.bbone_curveoutz),
 
-             'bbone_easein'               : ("BBone Ease-In", 0),
 
-             'bbone_easeout'              : ("BBone Ease-Out", 0),
 
-             'bbone_rollin'               : ("BBone Roll-In", 0),
 
-             'bbone_rollout'              : ("BBone Roll-Out", 0),
 
-             'bbone_scalein'              : ("BBone Scale-In", (1,1,1)),
 
-             'bbone_scaleout'             : ("BBone Scale-Out", (1,1,1)),
 
-             }
 
-             prRed("BBone Implementation is not complete, expect errors and missing features for now")
 
-             evaluate_sockets(self, pb, props_sockets)
 
-             # we need to clear this stuff since our only real goal was to get some drivers from the above
 
-             for attr_name in props_sockets.keys():
 
-                 try:
 
-                     setattr(pb, attr_name, 0) # just clear it
 
-                 except ValueError:
 
-                     setattr(pb, attr_name, (1.0,1.0,1.0)) # scale needs to be set to 1
 
-             # important TODO... all of the drivers and stuff should be handled this way, right?
 
-         # time to set up drivers!
 
-         # just gonna add this to the end and build off it I guess
 
-         props_sockets = {
 
-             "lock_location"               : ("Lock Location", [False, False, False]),
 
-             "lock_rotation"               : ("Lock Rotation", [False, False, False]),
 
-             "lock_scale"                  : ("Lock Scale", [False, False, False]),
 
-             'custom_shape_scale_xyz'      : ("Custom Object Scale",  (0.0,0.0,0.0) ),
 
-             'custom_shape_translation'    : ("Custom Object Translation",  (0.0,0.0,0.0) ),
 
-             'custom_shape_rotation_euler' : ("Custom Object Rotation",  (0.0,0.0,0.0) ),
 
-             'use_custom_shape_bone_size'  : ("Custom Object Scale to Bone Length",  True,)
 
-         }
 
-         evaluate_sockets(self, pb, props_sockets)
 
-         # this could probably be moved to bExecute
 
-         props_sockets = {
 
-             'hide'      : ("Hide", False),
 
-             'show_wire' : ("Custom Object Wireframe", False),
 
-         }
 
-         evaluate_sockets(self, pb.bone, props_sockets)
 
-         
 
-         if (driver):
 
-             pass
 
-         # whatever I was doing there.... was stupid. CLEAN UP TODO
 
-         # this is the right thing to do.
 
-         finish_drivers(self)
 
-         #
 
-         # OK, visual settings
 
-         #
 
-         # Get the override xform's bone:
 
-         pb.custom_shape_transform = None
 
-         pb.custom_shape = None
 
-         
 
-         if len(self.inputs["Custom Object xForm Override"].links) > 0:
 
-             trace = trace_single_line(self, "Custom Object xForm Override")
 
-             try:
 
-                 pb.custom_shape_transform = trace[0][1].bGetObject()
 
-             except AttributeError:
 
-                 pass
 
-                     
 
-         if len(self.inputs["Custom Object"].links) > 0:
 
-             trace = trace_single_line(self, "Custom Object")
 
-             try:
 
-                 ob = trace[0][1].bGetObject()
 
-             except AttributeError:
 
-                 ob=None
 
-             if type(ob) in [bpy.types.Object]:
 
-                 pb.custom_shape = ob 
 
-     def bGetObject(self, mode = 'POSE'):
 
-         if self.bObject is None: return None
 
-         if mode in ["POSE", "OBJECT"] and self.bGetParentArmature().mode == "EDIT":
 
-             raise RuntimeError("Cannot get Bone or PoseBone in Edit mode.")
 
-         elif mode == "EDIT" and self.bGetParentArmature().mode != "EDIT":
 
-             raise RuntimeError("Cannot get EditBone except in Edit mode.")
 
-         try:
 
-             if   (mode == 'EDIT'):
 
-                 return self.bGetParentArmature().data.edit_bones[self.bObject]
 
-             elif (mode == 'OBJECT'):
 
-                 return self.bGetParentArmature().data.bones[self.bObject]
 
-             elif (mode == 'POSE'):
 
-                 return self.bGetParentArmature().pose.bones[self.bObject]
 
-         except Exception as e:
 
-             prRed ("Cannot get bone for %s" % self)
 
-             raise e
 
-     def fill_parameters(self, prototype=None):
 
-         # this is the fill_parameters that is run if it isn't a schema
 
-         setup_custom_props(self)
 
-         super().fill_parameters(prototype)
 
-         # otherwise we will do this from the schema 
 
-         # LEGIBILITY TODO - why? explain this?
 
- class xFormGeometryObject(MantisNode):
 
-     '''A node representing an armature object'''
 
-     def __init__(self, signature, base_tree):
 
-         super().__init__(signature, base_tree)
 
-         inputs = [
 
-             "Name"             ,
 
-             "Geometry"         ,
 
-             "Matrix"           ,
 
-             "Relationship"     ,
 
-             "Deformer"         ,
 
-             "Hide in Viewport" ,
 
-             "Hide in Render"   ,
 
-         ]
 
-         outputs = [
 
-           "xForm Out",
 
-         ]
 
-         self.inputs.init_sockets(inputs)
 
-         self.outputs.init_sockets(outputs)
 
-         self.init_parameters()
 
-         self.set_traverse([("Relationship", "xForm Out")])
 
-         self.node_type = "XFORM"
 
-         self.bObject = None
 
-         self.has_shape_keys = False
 
-     def bSetParent(self):
 
-         from bpy.types import Object
 
-         parent_nc = get_parent(self, type='LINK')
 
-         if (parent_nc):
 
-             parent = None
 
-             if self.inputs["Relationship"].is_linked:
 
-                 trace = trace_single_line(self, "Relationship")
 
-                 for node in trace[0]:
 
-                     if node is self: continue # lol
 
-                     if (node.node_type == 'XFORM'):
 
-                         parent = node; break
 
-                 if parent is None:
 
-                     prWhite(f"INFO: no parent set for {self}.")
 
-                     return
 
-                 
 
-                 if (parent_object := parent.bGetObject()) is None:
 
-                     raise GraphError(f"Could not get parent object from node {parent} for {self}")
 
-                 if isinstance(parent, xFormBone):
 
-                     armOb= parent.bGetParentArmature()
 
-                     self.bObject.parent = armOb
 
-                     self.bObject.parent_type = 'BONE'
 
-                     self.bObject.parent_bone = parent.bObject
 
-                     # self.bObject.matrix_parent_inverse = parent.parameters["Matrix"].inverted()
 
-                 elif isinstance(parent_object, Object):
 
-                     self.bObject.parent = parent.bGetObject()
 
-     def bPrepare(self, bContext = None,):
 
-         import bpy
 
-         if not self.evaluate_input("Name"):
 
-             self.prepared = True
 
-             self.executed = True
 
-             # and return an error if there are any dependencies:
 
-             if self.hierarchy_connections:
 
-                 raise GraphError(wrapRed(f"Cannot Generate object {self} because the chosen name is empty or invalid."))
 
-             return
 
-         self.bObject = bpy.data.objects.get(self.evaluate_input("Name"))
 
-         trace = trace_single_line(self, "Geometry")
 
-         if (not self.bObject):
 
-             if trace[-1]:
 
-                 self.bObject = bpy.data.objects.new(self.evaluate_input("Name"), trace[-1].node.bGetObject())
 
-         # handle mismatched data.
 
-         data_wrong = False; data  = None
 
-         if (self.inputs["Geometry"].is_linked and self.bObject.type == "EMPTY"):
 
-             data_wrong = True; data = trace[-1].node.bGetObject()
 
-         elif (not self.inputs["Geometry"].is_linked and not self.bObject.type == "EMPTY"):
 
-             data_wrong = True
 
-         # clumsy but functional
 
-         if data_wrong:
 
-             unlink_me = self.bObject
 
-             unlink_me.name = "MANTIS_TRASH.000"
 
-             for col in unlink_me.users_collection:
 
-                 col.objects.unlink(unlink_me)
 
-             self.bObject = bpy.data.objects.new(self.evaluate_input("Name"), data)
 
-         if self.bObject and (self.inputs["Geometry"].is_linked and self.bObject.type  in ["MESH", "CURVE"]):
 
-             self.bObject.data = trace[-1].node.bGetObject()
 
-         
 
-         reset_object_data(self.bObject)
 
-         self.prepared = True
 
-     def bExecute(self, bContext = None,):
 
-         try:
 
-             bContext.collection.objects.link(self.bObject)
 
-         except RuntimeError: #already in; but a dangerous thing to pass.
 
-             pass
 
-         self.has_shape_keys = False
 
-         # putting this in bExecute simply prevents it from being run more than once.
 
-         # maybe I should do that with the rest of bPrepare, too.
 
-         props_sockets = {
 
-             'hide_viewport'    : ("Hide in Viewport", False),
 
-             'hide_render'      : ("Hide in Render", False),
 
-         }
 
-         evaluate_sockets(self, self.bObject, props_sockets)
 
-         self.executed = True
 
-     def bFinalize(self, bContext = None):
 
-         self.bSetParent()
 
-         matrix = self.evaluate_input("Matrix")
 
-         self.parameters['Matrix'] = matrix
 
-         self.bObject.matrix_world = matrix
 
-         for i, (driver_key, driver_item) in enumerate(self.drivers.items()):
 
-             print (wrapGreen(i), wrapWhite(self), wrapPurple(driver_key))
 
-             prOrange(driver_item)
 
-         finish_drivers(self)
 
-             
 
-         
 
-     def bGetObject(self, mode = 'POSE'):
 
-         return self.bObject
 
- class xFormObjectInstance(MantisNode):
 
-     """Represents an instance of an existing geometry object."""
 
-     def __init__(self, signature, base_tree):
 
-         super().__init__(signature, base_tree)
 
-         inputs = [
 
-             "Name"             ,
 
-             "Source Object"    ,
 
-             "As Instance"      ,
 
-             "Matrix"           ,
 
-             "Relationship"     ,
 
-             "Deformer"         ,
 
-             "Hide in Viewport" ,
 
-             "Hide in Render"   ,
 
-         ]
 
-         outputs = [
 
-           "xForm Out",
 
-         ]
 
-         self.inputs.init_sockets(inputs)
 
-         self.outputs.init_sockets(outputs)
 
-         self.init_parameters()
 
-         self.links = {} # leave this empty for now!
 
-         # now set up the traverse target...
 
-         self.set_traverse([("Relationship", "xForm Out")])
 
-         self.node_type = "XFORM"
 
-         self.bObject = None
 
-         self.has_shape_keys = False # Shape Keys will make a dupe so this is OK
 
-     def bSetParent(self):
 
-         from bpy.types import Object
 
-         parent_nc = get_parent(self, type='LINK')
 
-         if (parent_nc):
 
-             parent = None
 
-             if self.inputs["Relationship"].is_linked:
 
-                 trace = trace_single_line(self, "Relationship")
 
-                 for node in trace[0]:
 
-                     if node is self: continue # lol
 
-                     if (node.node_type == 'XFORM'):
 
-                         parent = node; break
 
-                 if parent is None:
 
-                     prWhite(f"INFO: no parent set for {self}.")
 
-                     return
 
-                 
 
-                 if (parent_object := parent.bGetObject()) is None:
 
-                     raise GraphError(f"Could not get parent object from node {parent} for {self}")
 
-                 if isinstance(parent, xFormBone):
 
-                     armOb= parent.bGetParentArmature()
 
-                     self.bObject.parent = armOb
 
-                     self.bObject.parent_type = 'BONE'
 
-                     self.bObject.parent_bone = parent.bObject
 
-                     # self.bObject.matrix_parent_inverse = parent.parameters["Matrix"].inverted()
 
-                 elif isinstance(parent_object, Object):
 
-                     self.bObject.parent = parent.bGetObject()
 
-     def bPrepare(self, bContext = None,):
 
-         from bpy import data
 
-         empty_mesh = data.meshes.get("MANTIS_EMPTY_MESH")
 
-         if not empty_mesh:
 
-             empty_mesh = data.meshes.new("MANTIS_EMPTY_MESH")
 
-         if not self.evaluate_input("Name"):
 
-             self.prepared = True
 
-             self.executed = True
 
-             # and return an error if there are any dependencies:
 
-             if self.hierarchy_connections:
 
-                 raise GraphError(wrapRed(f"Cannot Generate object {self} because the chosen name is empty or invalid."))
 
-             return
 
-         self.bObject = data.objects.get(self.evaluate_input("Name"))
 
-         if (not self.bObject):
 
-                 self.bObject = data.objects.new(self.evaluate_input("Name"), empty_mesh)
 
-         reset_object_data(self.bObject)
 
-         self.prepared = True
 
-     def bExecute(self, bContext = None,):
 
-         try:
 
-             bContext.collection.objects.link(self.bObject)
 
-         except RuntimeError: #already in; but a dangerous thing to pass.
 
-             pass
 
-         self.has_shape_keys = False
 
-         # putting this in bExecute simply prevents it from being run more than once.
 
-         # maybe I should do that with the rest of bPrepare, too.
 
-         props_sockets = {
 
-             'hide_viewport'    : ("Hide in Viewport", False),
 
-             'hide_render'      : ("Hide in Render", False),
 
-         }
 
-         evaluate_sockets(self, self.bObject, props_sockets)
 
-         self.executed = True
 
-     def bFinalize(self, bContext = None):
 
-         # now we need to set the object instance up.
 
-         from bpy import data
 
-         trace = trace_single_line(self, "Source Object")
 
-         for node in trace[0]:
 
-             if node is self: continue # lol
 
-             if (node.node_type == 'XFORM'):
 
-                 source_ob = node.bGetObject(); break
 
-         modifier = self.bObject.modifiers.new("Object Instance", type='NODES')
 
-         ng = data.node_groups.get("Object Instance")
 
-         if ng is None:
 
-             from .geometry_node_graphgen import gen_object_instance_node_group
 
-             ng = gen_object_instance_node_group()
 
-         modifier.node_group = ng
 
-         modifier["Socket_0"] = source_ob
 
-         modifier["Socket_1"] = self.evaluate_input("As Instance")
 
-         self.bSetParent()
 
-         matrix = self.evaluate_input("Matrix") # has to be done after parenting
 
-         self.parameters['Matrix'] = matrix
 
-         self.bObject.matrix_world = matrix
 
-         for i, (driver_key, driver_item) in enumerate(self.drivers.items()):
 
-             print (wrapGreen(i), wrapWhite(self), wrapPurple(driver_key))
 
-             prOrange(driver_item)
 
-         finish_drivers(self)
 
-             
 
-         
 
-     def bGetObject(self, mode = 'POSE'):
 
-         return self.bObject
 
 
  |