Motion transfer setup #1

Manually merged
Sybren A. Stüvel merged 18 commits from cgtinker/powership:motion_transfer into main 2023-06-05 12:06:15 +02:00
2 changed files with 26 additions and 21 deletions
Showing only changes of commit 2c79d687f0 - Show all commits

View File

@ -101,7 +101,6 @@ def run_node_tree(
return
powership_mode = scene.powership_mode
if powership_mode == "AUTO":
cgtinker marked this conversation as resolved Outdated

This seems like the same logic as the depsgraph update callback. Maybe move it into a separate function and call that from both places?

This seems like the same logic as the depsgraph update callback. Maybe move it into a separate function and call that from both places?
# TODO: don't use the global context here.
powership_mode = _choose_auto_mode(bpy.context)

View File

@ -251,7 +251,14 @@ class AbstractPowerShipNode(bpy.types.Node):
return link.from_socket.default_value
return input_socket.default_value
def _get_input_value(self, input_socket_name: str, expectType: T) -> T | None:
def _get_input_value(self, input_socket_name: str, expectType: type[T]) -> T | None:
"""Return the socket value, or None in some cases.
None is returned only when the socket value is None, for example with
empty ID pointer sockets. Even though this may not be applicable to many
node types, the code is generic and thus can technically always return a
None value.
"""
input_socket = self.inputs[input_socket_name]
value = self._get_input_socket_value(input_socket)
if value is None:
@ -262,7 +269,15 @@ class AbstractPowerShipNode(bpy.types.Node):
def _get_optional_input_value(
self, input_socket_name: str, expectType: type[T]
) -> T | None:
"""Return the connected socket value, or None if not connected."""
"""Return the connected socket value, or None if not connected.
Note that the 'optional' in the name indicates optional functionality.
cgtinker marked this conversation as resolved Outdated

Keep formatting changes out of the patch. You can use git gui or some other tool to cherry-pick which lines you do (not) want to include in a commit. That way you can exclude such changes, commit the rest, then revert the unwanted formatting changes to get rid of them.

Keep formatting changes out of the patch. You can use `git gui` or some other tool to cherry-pick which lines you do (not) want to include in a commit. That way you can exclude such changes, commit the rest, then revert the unwanted formatting changes to get rid of them.
It does *not* refer to optionally being connected; that's always
optional for any input socket.
An example of optional functionality would be to only set a bone's
rotation when the 'Rotation' socket is connected.
"""
input_socket = self.inputs[input_socket_name]
for link in input_socket.links:
convertedValue = expectType(link.from_socket.default_value) # type: ignore
@ -898,17 +913,6 @@ class SetBoneNode(AbstractPowerShipNode):
bl_label = "Set Bone"
bl_icon = "BONE_DATA"
space: bpy.props.EnumProperty( # type: ignore
name="Space",
items=_enum_control_space,
)
def draw_buttons(
self, context: bpy.types.Context, layout: bpy.types.UILayout
) -> None:
super().draw_buttons(context, layout)
layout.prop(self, "space")
def init(self, context):
self.add_execution_sockets()
@ -940,8 +944,8 @@ class SetBoneNode(AbstractPowerShipNode):
arm_eval: bpy.types.Object = arm_ob.evaluated_get(depsgraph)
arm_matrix = arm_eval.matrix_world
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:
loc = control_location
if control_rotation is not None:
@ -1111,6 +1115,8 @@ class ToEulerNode(AbstractPowerShipNode):
def execute(self, depsgraph: bpy.types.Depsgraph) -> None:
rotation = self._get_input_value("Rotation", Quaternion)
if rotation is None:
return
euler = rotation.to_euler(self.order)
self.outputs["X"].default_value = degrees(euler.x)
self.outputs["Y"].default_value = degrees(euler.y)
@ -1142,9 +1148,9 @@ class FromEulerNode(AbstractPowerShipNode):
self.inputs.new("NodeSocketFloat", "Z")
def execute(self, depsgraph: bpy.types.Depsgraph) -> None:
x = self._get_input_value("X", float)
y = self._get_input_value("Y", float)
z = self._get_input_value("Z", float)
x: float = self._get_input_value("X", float) or 0.0
y: float = self._get_input_value("Y", float) or 0.0
z: float = self._get_input_value("Z", float) or 0.0
euler = Euler((radians(x), radians(y), radians(z)), self.order)
self.outputs["Rotation"].default_value = euler.to_quaternion()
@ -1164,9 +1170,9 @@ class ClampNode(AbstractPowerShipNode):
self.outputs.new("NodeSocketFloat", "Result")
def execute(self, depsgraph: bpy.types.Depsgraph) -> None:
value = self._get_input_value("Value", float)
minimum = self._get_input_value("Minimum", float)
maximum = self._get_input_value("Maximum", float)
value = self._get_input_value("Value", float) or 0.0
minimum = self._get_input_value("Minimum", float) or 0.0
maximum = self._get_input_value("Maximum", float) or 0.0
clamped = max(minimum, min(value, maximum))
self.outputs["Result"].default_value = clamped