3 Angajamente 4fd017ca30 ... 81cbd7f96f

Autor SHA1 Permisiunea de a trimite mesaje. Dacă este dezactivată, utilizatorul nu va putea trimite nici un fel de mesaj Data
  Joseph Brandenburg 81cbd7f96f small edits after the previous patch 10 luni în urmă
  josephbburg bb10cfd7d3 Merge branch 'link-attribute-geo-transform' into 'master' 10 luni în urmă
  Trung 2cdf7bea7d init geometry attribute constraint 10 luni în urmă
6 a modificat fișierele cu 196 adăugiri și 31 ștergeri
  1. 1 0
      __init__.py
  2. 22 0
      link_nodes.py
  3. 38 12
      link_nodes_ui.py
  4. 28 0
      link_socket_templates.py
  5. 20 19
      ops_generate_tree.py
  6. 87 0
      socket_definitions.py

+ 1 - 0
__init__.py

@@ -95,6 +95,7 @@ link_transform_category = [
         NodeItem("LinkLimitRotation"),
         NodeItem("LinkLimitDistance"),
         NodeItem("LinkTransformation"),
+        NodeItem("LinkGeometryAttribute"),
         NodeItem("LinkFloor"),
     ]
 link_tracking_category = [

+ 22 - 0
link_nodes.py

@@ -32,6 +32,7 @@ def TellClasses():
              # stuff that snaps or limits a bone
              LinkFloor,
              LinkShrinkWrap,
+             LinkGeometryAttribute,
              # Drivers
              LinkDrivenParameter,
             ]
@@ -910,3 +911,24 @@ class LinkShrinkWrap(MantisLinkNode):
             # self.set_custom_space() # this needs to be overridden for me TODO
             evaluate_sockets(self, c, props_sockets)
         self.executed = True
+
+
+class LinkGeometryAttribute(MantisLinkNode):
+    '''A node representing a geometry attribute relationship.'''
+    def __init__(self, signature, base_tree,):
+        super().__init__(signature, base_tree, LinkGeometryAttributeSockets)
+        self.init_parameters(additional_parameters={"Name":None })
+        self.set_traverse([("Input Relationship", "Output Relationship")])
+
+    def bRelationshipPass(self, bContext = None,):
+        prepare_parameters(self)
+        for xf in self.GetxForm():
+            print
+            c = xf.bGetObject().constraints.new('GEOMETRY_ATTRIBUTE')
+            self.get_target_and_subtarget(c)
+            if constraint_name := self.evaluate_input("Name"):
+                c.name = constraint_name
+            props_sockets = self.gen_property_socket_map()
+            self.bObject.append(c)
+            evaluate_sockets(self, c, props_sockets)
+        self.executed = True

+ 38 - 12
link_nodes_ui.py

@@ -30,12 +30,13 @@ def TellClasses():
              LinkSplineIKNode,
              LinkFloorNode,
              LinkShrinkWrapNode,
+             LinkGeometryAttribute,
              LinkTransformationNode,
            ]
 
 from mathutils import Color # these colors were sampled from Blender's UI
 # TODO: maybe read the relevant colors from the Theme
-linkColor = Color((0.028034, 0.093164, 0.070379)).from_scene_linear_to_srgb()
+linkTransformColor = Color((0.028034, 0.093164, 0.070379)).from_scene_linear_to_srgb()
 inheritColor = Color((0.083213, 0.131242, 0.116497)).from_scene_linear_to_srgb()
 trackingColor = Color((0.033114, 0.049013, 0.131248)).from_scene_linear_to_srgb()
 ikColor = Color((0.131117, 0.131248, 0.006971)).from_scene_linear_to_srgb()
@@ -116,7 +117,7 @@ class LinkCopyLocationNode(Node, LinkNode):
     def init(self, context):
         self.init_sockets(LinkCopyLocationSockets)
         self.use_custom_color = True
-        self.color = linkColor
+        self.color = linkTransformColor
         self.initialized = True
 
 
@@ -131,7 +132,7 @@ class LinkCopyRotationNode(Node, LinkNode):
     def init(self, context):
         self.init_sockets(LinkCopyRotationSockets)
         self.use_custom_color = True
-        self.color = linkColor
+        self.color = linkTransformColor
         self.initialized = True
 
 
@@ -147,7 +148,7 @@ class LinkCopyScaleNode(Node, LinkNode):
     def init(self, context):
         self.init_sockets(LinkCopyScaleSockets)
         self.use_custom_color = True
-        self.color = linkColor
+        self.color = linkTransformColor
         self.initialized = True
 
 
@@ -183,7 +184,7 @@ class LinkCopyTransformNode(Node, LinkNode):
     def init(self, context):
         self.init_sockets(LinkCopyTransformsSockets)
         self.use_custom_color = True
-        self.color = linkColor
+        self.color = linkTransformColor
         self.initialized = True
 
 
@@ -256,7 +257,7 @@ class LinkLimitLocationNode(Node, LinkNode):
         self.init_sockets(LinkLimitLocationScaleSockets)
         self.initialized = True
         self.use_custom_color = True
-        self.color = linkColor
+        self.color = linkTransformColor
 
 class LinkLimitScaleNode(Node, LinkNode):
     '''A node representing Limit Scale'''
@@ -270,7 +271,7 @@ class LinkLimitScaleNode(Node, LinkNode):
         self.init_sockets(LinkLimitLocationScaleSockets)
         self.initialized = True
         self.use_custom_color = True
-        self.color = linkColor
+        self.color = linkTransformColor
 
 class LinkLimitRotationNode(Node, LinkNode):
     '''A node representing Limit Rotation'''
@@ -285,7 +286,7 @@ class LinkLimitRotationNode(Node, LinkNode):
         self.initialized = True
         # color
         self.use_custom_color = True
-        self.color = linkColor
+        self.color = linkTransformColor
 
 class LinkLimitDistanceNode(Node, LinkNode):
     '''A node representing Limit Distance'''
@@ -298,7 +299,7 @@ class LinkLimitDistanceNode(Node, LinkNode):
     def init(self, context):
         self.init_sockets(LinkLimitDistanceSockets)
         self.use_custom_color = True
-        self.color = linkColor
+        self.color = linkTransformColor
         self.initialized = True
 
 
@@ -313,7 +314,7 @@ class LinkTransformationNode(Node, LinkNode):
     def init(self, context):
         self.init_sockets(LinkTransformationSockets)
         self.use_custom_color = True
-        self.color = linkColor
+        self.color = linkTransformColor
         self.initialized = True
 
     def display_update(self, parsed_tree, context):
@@ -387,7 +388,7 @@ class LinkFloorNode(Node, LinkNode):
     def init(self, context):
         self.init_sockets(LinkFloorSockets)
         self.use_custom_color = True
-        self.color = linkColor
+        self.color = linkTransformColor
         self.initialized = True
 
 class LinkShrinkWrapNode(Node, LinkNode):
@@ -434,6 +435,31 @@ class LinkShrinkWrapNode(Node, LinkNode):
         # TODO: this stuff should be handled by input tags
         # once I get that working.
 
+class LinkGeometryAttribute(Node, LinkNode):
+    """A node representing Blender's Geometry Attribute Constraint"""
+    bl_idname = "LinkGeometryAttribute"
+    bl_label = "Geometry Attribute"
+    bl_icon = "CON_GEOMETRYATTRIBUTE"
+    initialized : bpy.props.BoolProperty(default = False)
+    mantis_node_class_name=bl_idname
+
+    def init(self, context):
+        self.init_sockets(LinkGeometryAttributeSockets)
+        self.use_custom_color = True
+        self.color = linkTransformColor
+        self.initialized = True
+
+    def display_update(self, parsed_tree, context):
+        data_type = self.inputs['Data Type'].default_value
+        if self.inputs['Data Type'].is_linked:
+            node_tree = context.space_data.path[0].node_tree
+            mantis_node = parsed_tree.get(get_signature_from_edited_tree(self, context))
+            if mantis_node: data_type = mantis_node.evaluate_input("Data Type")
+        not_matrix_mode = (data_type != 'FLOAT4X4')
+        self.inputs['Enabled Location'].hide=not_matrix_mode
+        self.inputs['Enabled Rotation'].hide=not_matrix_mode
+        self.inputs['Enabled Scale'].hide=not_matrix_mode
+
 # DRIVERS!!
 class LinkDrivenParameterNode(Node, LinkNode):
     """Represents a driven parameter in the downstream xForm node."""
@@ -446,7 +472,7 @@ class LinkDrivenParameterNode(Node, LinkNode):
     def init(self, context):
         self.init_sockets(LinkDrivenParameterSockets)
         self.use_custom_color = True
-        self.color = linkColor
+        self.color = linkTransformColor
         self.initialized = True
 
 # Set up the class property that ties the UI classes to the Mantis classes.

+ 28 - 0
link_socket_templates.py

@@ -463,6 +463,34 @@ LinkShrinkWrapSockets = [
     OutputRelationshipTemplate,
 ]
 
+LinkGeometryAttributeSockets = [
+    InputRelationshipTemplate,
+    TargetTemplate,
+    OffsetTargetTransformTemplate:= SockTemplate(name="Offset target transform", is_input=True,
+            bl_idname="BooleanSocket", blender_property='apply_target_transform'),
+    AttributeTemplate:= SockTemplate(name="Attribute", bl_idname="ParameterStringSocket", is_input=True,
+                 default_value="position", blender_property='attribute_name'),
+    DataTypeTemplate := SockTemplate(name="Data Type",
+            bl_idname="EnumGeometryAttributeDataTypeSocket", is_input=True,
+            blender_property='data_type'),
+    DomainTemplate := SockTemplate(name="Domain",
+            bl_idname="EnumGeometryAttributeDomainSocket", is_input=True,
+            blender_property='domain'),
+    SampleIndex := SockTemplate(name="Sample Index", bl_idname='UnsignedIntSocket',
+        is_input=True, default_value=0,blender_property='sample_index'),
+    EnabledLocationTemplate:= SockTemplate(name="Enabled Location", is_input=True,
+            bl_idname="BooleanSocket", blender_property='mix_loc'),
+    EnabledRotationTemplate:= SockTemplate(name="Enabled Rotation", is_input=True,
+            bl_idname="BooleanSocket", blender_property='mix_rot'),
+    EnabledScaleTemplate:= SockTemplate(name="Enabled Scale", is_input=True,
+            bl_idname="BooleanSocket", blender_property='mix_scl'),
+    SockTemplate(name='Mix Mode',  bl_idname='EnumMixModeGeometryAttribute', is_input=True,
+                         default_value='REPLACE', blender_property='mix_mode'),
+    InfluenceTemplate,
+    EnableTemplate,
+    OutputRelationshipTemplate,
+]
+
 # Remove this socket because of Blender changes.
 if (app.version >= (4, 5, 0)):
     LinkSplineIKSockets.pop(9)

+ 20 - 19
ops_generate_tree.py

@@ -59,25 +59,26 @@ def get_pretty_name(name):
 
 
 constraint_link_map={
-    'COPY_LOCATION'   : "LinkCopyLocation",
-    'COPY_ROTATION'   : "LinkCopyRotation",
-    'COPY_SCALE'      : "LinkCopyScale",
-    'COPY_TRANSFORMS' : "LinkCopyTransforms",
-    'LIMIT_DISTANCE'  : "LinkLimitDistance",
-    'LIMIT_LOCATION'  : "LinkLimitLocation",
-    'LIMIT_ROTATION'  : "LinkLimitRotation",
-    'LIMIT_SCALE'     : "LinkLimitScale",
-    'DAMPED_TRACK'    : "LinkDampedTrack",
-    'LOCKED_TRACK'    : "LinkLockedTrack",
-    'STRETCH_TO'      : "LinkStretchTo",
-    'TRACK_TO'        : "LinkTrackTo",
-    'CHILD_OF'        : "LinkInheritConstraint",
-    'IK'              : "LinkInverseKinematics",
-    'ARMATURE'        : "LinkArmature",
-    'SPLINE_IK'       : "LinkSplineIK",
-    'TRANSFORM'       : "LinkTransformation",
-    'FLOOR'           : "LinkFloor",
-    'SHRINKWRAP'      : "LinkShrinkWrap"
+    'COPY_LOCATION'     : "LinkCopyLocation",
+    'COPY_ROTATION'     : "LinkCopyRotation",
+    'COPY_SCALE'        : "LinkCopyScale",
+    'COPY_TRANSFORMS'   : "LinkCopyTransforms",
+    'LIMIT_DISTANCE'    : "LinkLimitDistance",
+    'LIMIT_LOCATION'    : "LinkLimitLocation",
+    'LIMIT_ROTATION'    : "LinkLimitRotation",
+    'LIMIT_SCALE'       : "LinkLimitScale",
+    'DAMPED_TRACK'      : "LinkDampedTrack",
+    'LOCKED_TRACK'      : "LinkLockedTrack",
+    'STRETCH_TO'        : "LinkStretchTo",
+    'TRACK_TO'          : "LinkTrackTo",
+    'CHILD_OF'          : "LinkInheritConstraint",
+    'IK'                : "LinkInverseKinematics",
+    'ARMATURE'          : "LinkArmature",
+    'SPLINE_IK'         : "LinkSplineIK",
+    'TRANSFORM'         : "LinkTransformation",
+    'FLOOR'             : "LinkFloor",
+    'SHRINKWRAP'        : "LinkShrinkWrap",
+    'GEOMETRY_ATTRIBUTE': "LinkGeometryAttribute"
     }
 
 def create_relationship_node_for_constraint(node_tree, c):

+ 87 - 0
socket_definitions.py

@@ -246,6 +246,10 @@ def TellClasses() -> List[MantisSocket]:
              EnumShrinkwrapFaceCullSocket,
              EnumShrinkwrapProjectAxisSocket,
              EnumShrinkwrapModeSocket,
+             # Geometry Attribute
+             EnumGeometryAttributeDataTypeSocket,
+             EnumGeometryAttributeDomainSocket,
+             EnumMixModeGeometryAttribute,
              # Deformers
              EnumSkinning,
              MorphTargetSocket,
@@ -2448,6 +2452,89 @@ class EnumShrinkwrapModeSocket(MantisSocket):
         return self.color_simple
 
 
+eDataTypeMode = (
+       ('VECTOR', "Vector", "Vector", 0), 
+       ('QUATERNION', "Quaternion", "", 1), 
+       ('FLOAT4X4', "4x4 Matrix", "", 2), )
+
+class EnumGeometryAttributeDataTypeSocket(MantisSocket):
+    '''Shrinkwrap Mode Socket'''
+    bl_idname = 'EnumGeometryAttributeDataTypeSocket'
+    bl_label = "Datatype"
+    default_value: bpy.props.EnumProperty(
+        items=eDataTypeMode,
+        description="Select the data type of the attribute",
+        default = 'VECTOR',
+        update = update_socket,)
+    color_simple = cString
+    color : bpy.props.FloatVectorProperty(default=cString, size=4)
+    input : bpy.props.BoolProperty(default =False,)
+    def draw(self, context, layout, node, text):
+        ChooseDraw(self, context, layout, node, text, use_enum=False)
+    def draw_color(self, context, node):
+        return self.color
+    @classmethod
+    def draw_color_simple(self):
+        return self.color_simple
+
+eDomaineMode = (
+    ('POINT', "Point", "Point", 0), 
+    ('EDGE', "Edge", "Edge", 1), 
+    ('FACE', "Face", "Face", 2), 
+    ('FACE_CORNER', "Face Corner", "Face Corner", 3), 
+    ('SPLINE', "Spline", "Spline", 4), 
+    ('INSTANCE', "Instance", "Instance", 5), )
+
+class EnumGeometryAttributeDomainSocket(MantisSocket):
+    '''Shrinkwrap Mode Socket'''
+    bl_idname = 'EnumGeometryAttributeDomainSocket'
+    bl_label = "Domain"
+    default_value: bpy.props.EnumProperty(
+        items=eDomaineMode,
+        description="Select the data type of the attribute",
+        default = 'POINT',
+        update = update_socket,)
+    color_simple = cString
+    color : bpy.props.FloatVectorProperty(default=cString, size=4)
+    input : bpy.props.BoolProperty(default =False,)
+    def draw(self, context, layout, node, text):
+        ChooseDraw(self, context, layout, node, text, use_enum=False)
+    def draw_color(self, context, node):
+        return self.color
+    @classmethod
+    def draw_color_simple(self):
+        return self.color_simple
+
+eMix_geometryattribute =(
+        ('REPLACE', "Replace (Aligned)", "Fully inherit scale"),
+        ('BEFORE_SPLIT', "Before (Split Channels)", "Fully inherit scale"),
+        ('AFTER_SPLIT', "After (Split Channels)", "Fully inherit scale"),
+        ('BEFORE_FULL', "Before (Full)", "Fully inherit scale"),
+        ('AFTER_FULL', "After (Full)", "Fully inherit scale"),)
+
+class EnumMixModeGeometryAttribute(MantisSocket):
+    '''Custom node socket type'''
+    bl_idname = 'EnumMixModeGeometryAttribute'
+    bl_label = "Rotation Mix"
+
+    default_value: bpy.props.EnumProperty(
+        items=eMix_geometryattribute,
+        name="Mix Mode",
+        description="Mix mode",
+        default = 'REPLACE', #{'REPLACE'},
+        #options = {'ENUM_FLAG'}, # this sux
+        update = update_socket,)
+    color_simple = cString
+    color : bpy.props.FloatVectorProperty(default=cString, size=4)
+    input : bpy.props.BoolProperty(default =False,)
+    def draw(self, context, layout, node, text):
+        ChooseDraw(self, context, layout, node, text)
+    def draw_color(self, context, node):
+        return self.color
+    @classmethod
+    def draw_color_simple(self):
+        return self.color_simple
+
 eSkinningMethod = (('EXISTING_GROUPS', "Use Existing Groups", "Use the existing vertex groups, or create empty groups if not found.",),
                    ('AUTOMATIC_HEAT', "Automatic (Heat)", "Use Blender's heatmap automatic skinning",),
                    ('COPY_FROM_OBJECT', "Copy from object", "Copy skin weights from the selected object"),)