Motion transfer setup #1
163
nodes.py
163
nodes.py
@ -724,10 +724,8 @@ class RotateTowards(AbstractPowerShipNode):
|
|||||||
|
|
||||||
# Set the rotation of the control
|
# Set the rotation of the control
|
||||||
vec = Vector((destination - origin))
|
vec = Vector((destination - origin))
|
||||||
# vec.normalize()
|
|
||||||
rot = vec.to_track_quat(self.track, self.up)
|
rot = vec.to_track_quat(self.track, self.up)
|
||||||
rot.normalize()
|
self.outputs["Rotation"].default_value = rot.normalized()
|
||||||
self.outputs["Rotation"].default_value = rot
|
|
||||||
|
|
||||||
|
|
||||||
class OffsetRotation(AbstractPowerShipNode):
|
class OffsetRotation(AbstractPowerShipNode):
|
||||||
@ -776,20 +774,15 @@ class MapRange(AbstractPowerShipNode):
|
|||||||
self.outputs["Result"].default_value = slope * val + offset
|
self.outputs["Result"].default_value = slope * val + offset
|
||||||
|
|
||||||
|
|
||||||
class RotationFromAngle(AbstractPowerShipNode):
|
class AngleFromVectors(AbstractPowerShipNode):
|
||||||
bl_idname = "RotationFromAngle"
|
bl_idname = "AngleFromVectors"
|
||||||
bl_label = "Rotation From Vector Angle"
|
bl_label = "Angle From Vectors"
|
||||||
bl_icon = "EMPTY_ARROWS"
|
bl_icon = "EMPTY_ARROWS"
|
||||||
|
|
||||||
axis: bpy.props.EnumProperty( # type: ignore
|
|
||||||
name="Axis",
|
|
||||||
items=_enum_up_axis_items,
|
|
||||||
)
|
|
||||||
|
|
||||||
angle_type: bpy.props.EnumProperty( # type: ignore
|
angle_type: bpy.props.EnumProperty( # type: ignore
|
||||||
name="Type",
|
name="Type",
|
||||||
items=[
|
items=[
|
||||||
("DEFAULT", "Default", ""),
|
("DEFAULT", "Unsigned", ""),
|
||||||
("SIGNED", "Signed", ""),
|
("SIGNED", "Signed", ""),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
@ -798,13 +791,12 @@ class RotationFromAngle(AbstractPowerShipNode):
|
|||||||
self, context: bpy.types.Context, layout: bpy.types.UILayout
|
self, context: bpy.types.Context, layout: bpy.types.UILayout
|
||||||
) -> None:
|
) -> None:
|
||||||
super().draw_buttons(context, layout)
|
super().draw_buttons(context, layout)
|
||||||
layout.prop(self, "axis")
|
|
||||||
layout.prop(self, "angle_type")
|
layout.prop(self, "angle_type")
|
||||||
|
|
||||||
def init(self, context):
|
def init(self, context):
|
||||||
self.add_optional_input_socket("NodeSocketVector", "U")
|
self.add_optional_input_socket("NodeSocketVector", "U")
|
||||||
self.add_optional_input_socket("NodeSocketVector", "V")
|
self.add_optional_input_socket("NodeSocketVector", "V")
|
||||||
self.outputs.new("NodeSocketQuaternion", "Rotation")
|
self.outputs.new("NodeSocketFloat", "Angle")
|
||||||
|
|
||||||
def execute(self, depsgraph: bpy.types.Depsgraph) -> None:
|
def execute(self, depsgraph: bpy.types.Depsgraph) -> None:
|
||||||
u = self._get_optional_input_value("U", Vector)
|
u = self._get_optional_input_value("U", Vector)
|
||||||
@ -818,10 +810,7 @@ class RotationFromAngle(AbstractPowerShipNode):
|
|||||||
else:
|
else:
|
||||||
angle = u.angle(v)
|
angle = u.angle(v)
|
||||||
|
|
||||||
m = Matrix.Rotation(angle, 3, self.axis)
|
self.outputs["Angle"].default_value = angle
|
||||||
res = m.to_quaternion()
|
|
||||||
|
|
||||||
self.outputs["Rotation"].default_value = res
|
|
||||||
|
|
||||||
|
|
||||||
_enum_vector_math_operations = [
|
_enum_vector_math_operations = [
|
||||||
@ -1006,6 +995,7 @@ class SetBoneNode(AbstractPowerShipNode):
|
|||||||
bone_mat_world: Matrix = arm_matrix @ bone.matrix
|
bone_mat_world: Matrix = arm_matrix @ bone.matrix
|
||||||
|
|
||||||
loc, rot, scale = bone_mat_world.decompose()
|
loc, rot, scale = bone_mat_world.decompose()
|
||||||
|
|
||||||
if control_location is not None:
|
if control_location is not None:
|
||||||
loc = control_location
|
loc = control_location
|
||||||
if control_rotation is not None:
|
if control_rotation is not None:
|
||||||
@ -1013,24 +1003,27 @@ class SetBoneNode(AbstractPowerShipNode):
|
|||||||
if control_scale is not None:
|
if control_scale is not None:
|
||||||
scale = control_scale
|
scale = control_scale
|
||||||
|
|
||||||
match self.space:
|
# TODO: Fix jittering bone scale which happens
|
||||||
case "WORLD":
|
# esp. when multiple bones are parented to the rotated bone
|
||||||
bone_mat_world = Matrix.LocRotScale(loc, rot, scale)
|
# rounding helps but does not entirely fix the issue.
|
||||||
case "CHANNELS":
|
scale = [round(x, 4) for x in scale]
|
||||||
# Not sure what causes the scale to flip, however...
|
|
||||||
# The y/z-scale flips on update if multiple rotations are chained,
|
|
||||||
# this generates jitter when running const updates - flipping seems to temp fix it.
|
|
||||||
scale = [scale[i] for i in [0, 2, 1]]
|
|
||||||
v_nil = Vector((0, 0, 0))
|
v_nil = Vector((0, 0, 0))
|
||||||
bone_rest_rot_scale = bone.bone.matrix_local.copy()
|
bone_rest_rot_scale = bone.bone.matrix_local.copy()
|
||||||
|
|
||||||
|
match self.space:
|
||||||
|
case "WORLD":
|
||||||
|
bone_mat_world = Matrix.LocRotScale(
|
||||||
|
loc, rot.normalized(), scale)
|
||||||
|
loc, rot, scale = bone_mat_world.decompose()
|
||||||
|
case "CHANNELS":
|
||||||
bone_rest_rot_scale.translation = v_nil
|
bone_rest_rot_scale.translation = v_nil
|
||||||
bone_rest_rot = bone_rest_rot_scale.to_quaternion()
|
|
||||||
mat_rot_scale = Matrix.LocRotScale(
|
mat_rot_scale = Matrix.LocRotScale(
|
||||||
v_nil, rot, scale) @ bone_rest_rot.to_matrix().to_4x4()
|
v_nil, rot, scale) @ bone_rest_rot_scale
|
||||||
mat_loc = Matrix.Translation(loc)
|
mat_loc = Matrix.Translation(loc)
|
||||||
bone_mat_world = mat_loc @ mat_rot_scale
|
bone_mat_world = mat_loc @ mat_rot_scale
|
||||||
|
|
||||||
bone.matrix = arm_matrix.inverted() @ bone_mat_world
|
bone.matrix = arm_matrix.inverted() @ bone_mat_world
|
||||||
|
loc, rot, scale = bone.matrix.decompose()
|
||||||
|
|
||||||
|
|
||||||
class TwoBoneIKNode(AbstractPowerShipNode):
|
class TwoBoneIKNode(AbstractPowerShipNode):
|
||||||
@ -1237,61 +1230,61 @@ class ClampNode(AbstractPowerShipNode):
|
|||||||
self.outputs["Result"].default_value = clamped
|
self.outputs["Result"].default_value = clamped
|
||||||
|
|
||||||
|
|
||||||
class AbstractTwoValueMathNode(AbstractPowerShipNode):
|
# class AbstractTwoValueMathNode(AbstractPowerShipNode):
|
||||||
def init(self, context: bpy.types.Context) -> None:
|
# def init(self, context: bpy.types.Context) -> None:
|
||||||
self.inputs.new("NodeSocketFloat", "A")
|
# self.inputs.new("NodeSocketFloat", "A")
|
||||||
self.inputs.new("NodeSocketFloat", "B")
|
# self.inputs.new("NodeSocketFloat", "B")
|
||||||
self.outputs.new("NodeSocketFloat", "Result")
|
# self.outputs.new("NodeSocketFloat", "Result")
|
||||||
|
#
|
||||||
def execute(self, depsgraph: bpy.types.Depsgraph) -> None:
|
# def execute(self, depsgraph: bpy.types.Depsgraph) -> None:
|
||||||
a = self._get_input_value("A", float)
|
# a = self._get_input_value("A", float)
|
||||||
b = self._get_input_value("B", float)
|
# b = self._get_input_value("B", float)
|
||||||
self.outputs["Result"].default_value = self.calculate(a, b)
|
# self.outputs["Result"].default_value = self.calculate(a, b)
|
||||||
|
#
|
||||||
def calculate(self, a: float, b: float) -> float:
|
# def calculate(self, a: float, b: float) -> float:
|
||||||
return 0
|
# return 0
|
||||||
|
#
|
||||||
|
#
|
||||||
class AddNode(AbstractTwoValueMathNode):
|
# class AddNode(AbstractTwoValueMathNode):
|
||||||
"""Add two values"""
|
# """Add two values"""
|
||||||
|
#
|
||||||
bl_idname = "AddNode"
|
# bl_idname = "AddNode"
|
||||||
bl_label = "Add"
|
# bl_label = "Add"
|
||||||
|
#
|
||||||
def calculate(self, a: float, b: float) -> float:
|
# def calculate(self, a: float, b: float) -> float:
|
||||||
return a + b
|
# return a + b
|
||||||
|
#
|
||||||
|
#
|
||||||
class SubtractNode(AbstractTwoValueMathNode):
|
# class SubtractNode(AbstractTwoValueMathNode):
|
||||||
"""Subtract two values"""
|
# """Subtract two values"""
|
||||||
|
#
|
||||||
bl_idname = "SubtractNode"
|
# bl_idname = "SubtractNode"
|
||||||
bl_label = "Subtract"
|
# bl_label = "Subtract"
|
||||||
|
#
|
||||||
def calculate(self, a: float, b: float) -> float:
|
# def calculate(self, a: float, b: float) -> float:
|
||||||
return a - b
|
# return a - b
|
||||||
|
#
|
||||||
|
#
|
||||||
class MultiplyNode(AbstractTwoValueMathNode):
|
# class MultiplyNode(AbstractTwoValueMathNode):
|
||||||
"""Multiply two values"""
|
# """Multiply two values"""
|
||||||
|
#
|
||||||
bl_idname = "MultiplyNode"
|
# bl_idname = "MultiplyNode"
|
||||||
bl_label = "Multiply"
|
# bl_label = "Multiply"
|
||||||
|
#
|
||||||
def calculate(self, a: float, b: float) -> float:
|
# def calculate(self, a: float, b: float) -> float:
|
||||||
return a * b
|
# return a * b
|
||||||
|
#
|
||||||
|
#
|
||||||
class DivideNode(AbstractTwoValueMathNode):
|
# class DivideNode(AbstractTwoValueMathNode):
|
||||||
"""Divide two values; division by zero results in NaN"""
|
# """Divide two values; division by zero results in NaN"""
|
||||||
|
#
|
||||||
bl_idname = "DivideNode"
|
# bl_idname = "DivideNode"
|
||||||
bl_label = "Divide"
|
# bl_label = "Divide"
|
||||||
|
#
|
||||||
def calculate(self, a: float, b: float) -> float:
|
# def calculate(self, a: float, b: float) -> float:
|
||||||
if b == 0:
|
# if b == 0:
|
||||||
return float("nan")
|
# return float("nan")
|
||||||
return a / b
|
# return a / b
|
||||||
|
|
||||||
|
|
||||||
def _on_num_sockets_change(self: "SequenceNode", context: bpy.types.Context) -> None:
|
def _on_num_sockets_change(self: "SequenceNode", context: bpy.types.Context) -> None:
|
||||||
@ -1394,7 +1387,7 @@ node_categories = [
|
|||||||
items=[
|
items=[
|
||||||
nodeitems_utils.NodeItem("RotateTowards"),
|
nodeitems_utils.NodeItem("RotateTowards"),
|
||||||
nodeitems_utils.NodeItem("OffsetRotation"),
|
nodeitems_utils.NodeItem("OffsetRotation"),
|
||||||
nodeitems_utils.NodeItem("RotationFromAngle"),
|
nodeitems_utils.NodeItem("AngleFromVectors"),
|
||||||
nodeitems_utils.NodeItem("NormalFromPoints"),
|
nodeitems_utils.NodeItem("NormalFromPoints"),
|
||||||
nodeitems_utils.NodeItem("SplitVector"),
|
nodeitems_utils.NodeItem("SplitVector"),
|
||||||
nodeitems_utils.NodeItem("ToVector"),
|
nodeitems_utils.NodeItem("ToVector"),
|
||||||
@ -1439,7 +1432,7 @@ classes = (
|
|||||||
SequenceNode,
|
SequenceNode,
|
||||||
# Math Nodes
|
# Math Nodes
|
||||||
RotateTowards,
|
RotateTowards,
|
||||||
RotationFromAngle,
|
AngleFromVectors,
|
||||||
OffsetRotation,
|
OffsetRotation,
|
||||||
NormalFromPoints,
|
NormalFromPoints,
|
||||||
ToVector,
|
ToVector,
|
||||||
|
Binary file not shown.
Loading…
Reference in New Issue
Block a user