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
Contributor

I've been testing out powership and tried to transfer raw tracking data to a rig with it. On the run I added various math and utility nodes, basically, making it work. While doing so, the math nodes (which I removed) and muting change has been introduced which may not work with all introduced nodes properly (b.e. you currently cannot split a vector, do math operations and combine it again without unexpected results).

Besides there are no drastic changes and to support keyframed controls I added a "on_frame_changed" handler.

I've been testing out powership and tried to transfer raw tracking data to a rig with it. On the run I added various math and utility nodes, basically, making it work. While doing so, the math nodes (which I removed) and muting change has been introduced which may not work with all introduced nodes properly (b.e. you currently cannot split a vector, do math operations and combine it again without unexpected results). Besides there are no drastic changes and to support keyframed controls I added a "on_frame_changed" handler.
Denys Hsu added 4 commits 2023-05-24 21:47:41 +02:00
Denys Hsu added 1 commit 2023-05-25 19:06:19 +02:00
Sybren A. Stüvel requested changes 2023-05-26 17:24:50 +02:00
Sybren A. Stüvel left a comment
Owner

This is great!

I haven’t been able to do a full review, just had time for a small peek and a few notes.

This is great! I haven’t been able to do a full review, just had time for a small peek and a few notes.
execute.py Outdated
@ -50,7 +50,6 @@ def execute_tree(
# The running of this tree will trigger another depsgraph update, which
# should not trigger yet another execution.
global _skip_next_autorun

Please don’t include formatting changes like this. Formatting changes shouldn’t be in the same PR as functional changes.

Please don’t include formatting changes like this. Formatting changes shouldn’t be in the same PR as functional changes.
cgtinker marked this conversation as resolved
execute.py Outdated
@ -3,2 +3,3 @@
is_first_load = "nodes" not in locals()
import bpy
from . import nodes
is_first_load = "nodes" not in locals()

Please keep this block as-is. These changes will break the reloading mechanism.

Please keep this block as-is. These changes will break the reloading mechanism.

Please keep this block as-is. These changes will break the reloading mechanism.

Please keep this block as-is. These changes will break the reloading mechanism.
Author
Contributor

That's why it hasn't been updating!
My lsp destroyed the formatting a bit, doing my best to fix it – pylance has been fighting against mypy and no-one has been the winner I guess. Pep8 came to the rescue and yea well, here we are :)

What kind of formatter are you using? (probably will add a few more nodes in the future if you don't mind)

That's why it hasn't been updating! My lsp destroyed the formatting a bit, doing my best to fix it – pylance has been fighting against mypy and no-one has been the winner I guess. Pep8 came to the rescue and yea well, here we are :) What kind of formatter are you using? (probably will add a few more nodes in the future if you don't mind)
cgtinker marked this conversation as resolved
execute.py Outdated
@ -101,0 +101,4 @@
def _on_frame_changed_post(
scene: bpy.types.Scene, depsgraph: bpy.types.Depsgraph
) -> None:
global _skip_next_autorun

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?
cgtinker marked this conversation as resolved
@ -579,0 +627,4 @@
class Distance(AbstractPowerShipNode):
""" Calculate normal from three points. """

Does this calculate a normal vector? Or its length?

Does this calculate a normal vector? Or its length?
Author
Contributor

The length.
I went through the comments and updated them (some were unrelated and happened due to closed eyes copy pasting...)

The length. I went through the comments and updated them (some were unrelated and happened due to closed eyes copy pasting...)
cgtinker marked this conversation as resolved
Denys Hsu added 3 commits 2023-05-26 19:30:20 +02:00
Denys Hsu added 1 commit 2023-05-26 19:46:35 +02:00
Author
Contributor

Glad you like the patch!

I considered to remove the distance node and to just add a regular length node.
On the one hand nodes like a "distance node" are really easy to understand and kinda useful as they save you a node in the tree, but on the other hand a length node is way more useful overall. Personally I even prefer length squared but...
What do you think about "easy to read for a non-math background" nodes?

Stopped using a formatter for now, guess we should match them first.

Glad you like the patch! I considered to remove the distance node and to just add a regular length node. On the one hand nodes like a "distance node" are really easy to understand and kinda useful as they save you a node in the tree, but on the other hand a length node is way more useful overall. Personally I even prefer length squared but... What do you think about "easy to read for a non-math background" nodes? Stopped using a formatter for now, guess we should match them first.
Denys Hsu requested review from Sybren A. Stüvel 2023-05-26 20:08:03 +02:00

I considered to remove the distance node and to just add a regular length node.
On the one hand nodes like a "distance node" are really easy to understand and kinda useful as they save you a node in the tree, but on the other hand a length node is way more useful overall.

I think both would be useful; I would expect a "length" node to have a single vector input, whereas a "distance" node I would expect to have two vectors as input. Technically they'd be the same if one of the input vectors is the origin.

Personally I even prefer length squared but...

We could give the node two outputs and only compute connected ones? That way you can choose between the length of the squared length whenever you use the node.

What do you think about "easy to read for a non-math background" nodes?

That might be a good choice, indeed. Which I think would lead us to having two nodes, "distance" and "length", as that would make them easier to find in the "Add node" menu.

What kind of formatter are you using? (probably will add a few more nodes in the future if you don't mind)

I'm using black.

> I considered to remove the distance node and to just add a regular length node. > On the one hand nodes like a "distance node" are really easy to understand and kinda useful as they save you a node in the tree, but on the other hand a length node is way more useful overall. I think both would be useful; I would expect a "length" node to have a single vector input, whereas a "distance" node I would expect to have two vectors as input. Technically they'd be the same if one of the input vectors is the origin. > Personally I even prefer length squared but... We could give the node two outputs and only compute connected ones? That way you can choose between the length of the squared length whenever you use the node. > What do you think about "easy to read for a non-math background" nodes? That might be a good choice, indeed. Which I think would lead us to having two nodes, "distance" and "length", as that would make them easier to find in the "Add node" menu. > What kind of formatter are you using? (probably will add a few more nodes in the future if you don't mind) I'm using [black](https://pypi.org/project/black/).
Sybren A. Stüvel requested changes 2023-06-01 11:58:03 +02:00
Sybren A. Stüvel left a comment
Owner

Thanks for the updates! I found a bunch of things to adjust, but I think they're all minor and easily done.

Please check the code with mypy ., there's a bunch of errors. I've also solved a few of those in the main branch, so be sure to merge that before looking at this. If you need a hand with that, let me know.

Thanks for the updates! I found a bunch of things to adjust, but I think they're all minor and easily done. Please check the code with `mypy .`, there's a bunch of errors. I've also solved a few of those in the `main` branch, so be sure to merge that before looking at this. If you need a hand with that, let me know.
.gitignore Outdated
@ -1,3 +1,6 @@
/.venv
/.vscode
__pycache__
*.DS_Store

Please don't add platform/IDE-specific files here. These can go into .git/info/exclude (which does the same but isn't tracked) or in your global gitignore file (if you want to have those available to all Git projects you work on).

Please don't add platform/IDE-specific files here. These can go into `.git/info/exclude` (which does the same but isn't tracked) or in your global gitignore file (if you want to have those available to all Git projects you work on).
cgtinker marked this conversation as resolved
@ -75,0 +81,4 @@
) -> None:
global _skip_next_autorun
if not _skip_next_autorun:
_skip_next_autorun = True

Since _skip_next_autorun is a boolean, the if condition can be removed.

Since `_skip_next_autorun` is a boolean, the `if` condition can be removed.
cgtinker marked this conversation as resolved
nodes.py Outdated
@ -6,2 +6,2 @@
from math import degrees, radians
from typing import TypeVar, Callable, Optional, Iterable
from math import degrees, radians, sqrt
from typing import TypeVar, Callable, Optional, Iterable, Any

Both sqrt and Any are unused.

Both `sqrt` and `Any` are unused.
cgtinker marked this conversation as resolved
nodes.py Outdated
@ -272,3 +272,3 @@
def _first_input_to_output(self) -> None:
"""Copy the first input's default value to the output, if the sockets are compatible."""

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.
cgtinker marked this conversation as resolved
nodes.py Outdated
@ -579,0 +582,4 @@
bl_icon = "EMPTY_ARROWS"
def init(self, context):
self.add_optional_input_socket("NodeSocketFloat", "X")

Here I think a regular input socket would be better. The "optional" ones (and I should document this better) are intended for sockets that will be ignored when they are unconnected. In this case I feel regular sockets would be better, as those allow you to enter their values manually when the socket is unconnected.

Here I think a regular input socket would be better. The "optional" ones (and I should document this better) are intended for sockets that will be ignored when they are unconnected. In this case I feel regular sockets would be better, as those allow you to enter their values manually when the socket is unconnected.
cgtinker marked this conversation as resolved
nodes.py Outdated
@ -579,0 +598,4 @@
if y is not None:
v.y = y
if z is not None:
v.z = z

This can be simplified by using shortcutting (a or b evaluates to b when a is falsey).

        x = self._get_optional_input_value("X", float) or 0.0
        y = self._get_optional_input_value("Y", float) or 0.0
        z = self._get_optional_input_value("Z", float) or 0.0

        v = Vector((x, y, z))
This can be simplified by using shortcutting (`a or b` evaluates to `b` when `a` is falsey). ```py x = self._get_optional_input_value("X", float) or 0.0 y = self._get_optional_input_value("Y", float) or 0.0 z = self._get_optional_input_value("Z", float) or 0.0 v = Vector((x, y, z)) ```
cgtinker marked this conversation as resolved
nodes.py Outdated
@ -579,0 +609,4 @@
bl_icon = "EMPTY_ARROWS"
def init(self, context):
self.add_optional_input_socket("NodeSocketVector", "Vector")

Same as above, this could be a regular vector input socket.

Same as above, this could be a regular vector input socket.
cgtinker marked this conversation as resolved
nodes.py Outdated
@ -579,0 +647,4 @@
bl_icon = "EMPTY_ARROWS"
def init(self, context):
self.add_optional_input_socket("NodeSocketVector", "U")

These should again be regular input sockets, as it makes no sense to do the computation without a full set of three points.

These should again be regular input sockets, as it makes no sense to do the computation without a full set of three points.
cgtinker marked this conversation as resolved
nodes.py Outdated
@ -579,0 +658,4 @@
w = self._get_optional_input_value("W", Vector)
a = v - u
b = w - u
normal = a.cross(b)

This only outputs a normal vector when a and b are perpendicular. Better to use a.cross(b).normalized()

This only outputs a normal vector when `a` and `b` are perpendicular. Better to use `a.cross(b).normalized()`
cgtinker marked this conversation as resolved
nodes.py Outdated
@ -579,0 +680,4 @@
class RotateTowards(AbstractPowerShipNode):
""" Calculate the rotation from a vector with a track and up axis
based on the given origin, destination. """

Follow PEP 257 (in this case, the initial line should be shorter, and the leading/trailing spaces should be removed). Same for other docstrings.

Wellll.... try to follow PEP 257 but also keep in mind that Blender uses those docstrings for the tooltips, and thus they shouldn't end in a period. Stupid, I know...

Follow PEP 257 (in this case, the initial line should be shorter, and the leading/trailing spaces should be removed). Same for other docstrings. Wellll.... try to follow PEP 257 but also keep in mind that Blender uses those docstrings for the tooltips, and thus they shouldn't end in a period. Stupid, I know...
cgtinker marked this conversation as resolved
nodes.py Outdated
@ -579,0 +695,4 @@
up: bpy.props.EnumProperty( # type: ignore
name="Up",
items=_enum_up_axis_items,
default='Y'

Why is Y the default up-vector, and not Z?

Why is `Y` the default up-vector, and not `Z`?
Author
Contributor

I thought it was like that in the python interface (and I was wrong).
Just checked in mathutils_Vector.c, there the up axis is Y and the track axis is Z. Should we follow that convention or go for Z as up axis and X as track axis?

I thought it was like that in the python interface (and I was wrong). Just checked in _mathutils_Vector.c_, there the up axis is **Y** and the track axis is **Z**. Should we follow that convention or go for **Z** as up axis and **X** as track axis?
nodes.py Outdated
@ -579,0 +707,4 @@
def init(self, context):
self.add_optional_input_socket("NodeSocketVector", "Origin")
self.add_optional_input_socket("NodeSocketVector", "Destination")

I think these names could be improved for clarity. How about "Vector" and "Rotate To"?

I think these names could be improved for clarity. How about "Vector" and "Rotate To"?
cgtinker marked this conversation as resolved
nodes.py Outdated
@ -579,0 +724,4 @@
bl_idname = "OffsetRotation"
bl_label = "Offset Rotation"
bl_icon = "EMPTY_ARROWS"
default_value = Quaternion()

default_value doesn't seem used.

`default_value` doesn't seem used.
cgtinker marked this conversation as resolved
nodes.py Outdated
@ -579,0 +772,4 @@
angle_type: bpy.props.EnumProperty( # type: ignore
name="Type",
items=[
("DEFAULT", "Unsigned", ""),

Why name it DEFAULT instead of UNSIGNED? And why is UNSIGNED the default value? Not saying that it should be the other one, just wondering about your thought process.

Why name it `DEFAULT` instead of `UNSIGNED`? And why is `UNSIGNED` the default value? Not saying that it should be the other one, just wondering about your thought process.
Author
Contributor

Usually an angle is not signed, you got to define something to sign it. That's why I thought unsigned angles should be the default.

I rechecked and to be honest, I neither knew that the "signed" vector method is only for 2D vectors nor how it actually signed an angle. So I guess I removed it and kept only the "unsigned" angle for now - my bad sorry. Kinda liked the idea of an easy to use signed angle.

So far, when I needed a signed angle, I ended up using a plane. Basically I've used the signed distance (based on the normal) from the plane to the destination of the vector and used the sign for the angle. This is possible with the current system without changes so I guess it's fine.

Usually an angle is not signed, you got to define something to sign it. That's why I thought unsigned angles should be the default. I rechecked and to be honest, I neither knew that the "signed" vector method is only for 2D vectors nor how it actually signed an angle. So I guess I removed it and kept only the "unsigned" angle for now - my bad sorry. Kinda liked the idea of an easy to use signed angle. So far, when I needed a signed angle, I ended up using a plane. Basically I've used the signed distance (based on the normal) from the plane to the destination of the vector and used the sign for the angle. This is possible with the current system without changes so I guess it's fine.
nodes.py Outdated
@ -579,0 +794,4 @@
signed = self.angle_type == 'SIGNED'
angle = 0
if not (u.length == 0 or v.length == 0):

Don't compute length when you can use length_squared as well.

Don't compute `length` when you can use `length_squared` as well.
cgtinker marked this conversation as resolved
nodes.py Outdated
@ -579,0 +845,4 @@
case 'SUBSTRACT':
res = u-v
case 'DIVIDE':
res = Vector([x/y if y != 0.0 else float("nan")

This could be an interesting design discussion. Not something to do here -- this code is fine. But in general, we have to decide how Powership is going to handle erroneous values. For example,. the Vector.normalized() function I suggested above will simply return (0, 0, 0) for zero vectors. I feel that maybe here it could also make sense to define x / 0 → 0 and return as many usable values as possible.

I actually had a little design discussion with @nathanvegdahl about this, and until we have a 'debug mode' that can visualise where NaNs are produced, it's better to stick to regular floats. So in this case x/y if y != 0.0 else 0.0

And another minor thing: the list comprehension can be replaced by a generator expression for a little bit of added performance and readability:

res = Vector(x/y if y != 0.0 else 0.0 for x, y in zip(u, v))
This could be an interesting design discussion. ~~Not something to do here -- this code is fine.~~ But in general, we have to decide how Powership is going to handle erroneous values. For example,. the `Vector.normalized()` function I suggested above will simply return `(0, 0, 0)` for zero vectors. I feel that maybe here it could also make sense to define `x / 0 → 0` and return as many usable values as possible. I actually had a little design discussion with @nathanvegdahl about this, and until we have a 'debug mode' that can visualise where NaNs are produced, it's better to stick to regular floats. So in this case `x/y if y != 0.0 else 0.0` And another minor thing: the list comprehension can be replaced by a generator expression for a little bit of added performance and readability: ```py res = Vector(x/y if y != 0.0 else 0.0 for x, y in zip(u, v)) ```
cgtinker marked this conversation as resolved
nodes.py Outdated
@ -579,0 +850,4 @@
case 'CROSS':
res = u.cross(v)
case _:
print("Vector math operation not found:", self.operation)

Either log/print, or raise an exception. Don't do both, as one issue will be reported twice.

Either log/print, or raise an exception. Don't do both, as one issue will be reported twice.
cgtinker marked this conversation as resolved
nodes.py Outdated
@ -579,0 +851,4 @@
res = u.cross(v)
case _:
print("Vector math operation not found:", self.operation)
raise ValueError

Don't use a class as exception, always instantiate it.

raise ValueError(f"Vector math operation not found: {self.operation!r}")
Don't use a class as exception, always instantiate it. ```py raise ValueError(f"Vector math operation not found: {self.operation!r}") ```
cgtinker marked this conversation as resolved
nodes.py Outdated
@ -579,0 +897,4 @@
case 'SUBSTRACT':
res = u-v
case 'DIVIDE':
res = u/v if v != 0 else float("nan")

nan → 0.0

nan → 0.0
cgtinker marked this conversation as resolved
nodes.py Outdated
@ -579,0 +900,4 @@
res = u/v if v != 0 else float("nan")
case _:
print("Math operation not found:", self.operation)
raise ValueError

Same as above.

Same as above.
cgtinker marked this conversation as resolved
nodes.py Outdated
@ -658,0 +997,4 @@
match self.space:
case "WORLD":
bone_mat_world = Matrix.LocRotScale(
loc, rot.normalized(), scale)

in which case would rot not be normalized? I'd expect bone_mat_world.decompose() to return a unit quaternion. If you want to normalize the socket value, do that above with rot = control_rotation.normalized().

in which case would `rot` not be normalized? I'd expect `bone_mat_world.decompose()` to return a unit quaternion. If you want to normalize the socket value, do that above with `rot = control_rotation.normalized()`.
Author
Contributor

I think that can be removed. I was confused because the quaternion affected the scale which indicates that it's not a unit quaternion. This happened on longer bone chains - rounding the scale seemed to fix the issue so I guess it has been some floating point error.

I think that can be removed. I was confused because the quaternion affected the scale which indicates that it's not a unit quaternion. This happened on longer bone chains - rounding the scale seemed to fix the issue so I guess it has been some floating point error.
nodes.py Outdated
@ -1023,3 +1321,3 @@
nodeitems_utils.NodeItem("ToEulerNode"),
nodeitems_utils.NodeItem("FromEulerNode"),
],
]

Always end in a comma, it keeps diffs clean when you want to add another parameter later.

Always end in a comma, it keeps diffs clean when you want to add another parameter later.
cgtinker marked this conversation as resolved
Denys Hsu added 3 commits 2023-06-04 19:50:30 +02:00
Denys Hsu added 1 commit 2023-06-04 21:32:15 +02:00
Denys Hsu added 1 commit 2023-06-04 22:00:03 +02:00
Author
Contributor

Thanks for the hints and information!
Good to know that generators are more efficient than list comprehensions. I always thought it's the other way around. Merged the changes from your main branch and fixed the issues.

I'm not sure how to go about mypy. Probably the stubs I use are not sufficient. I tried "blender stubs" and "bpy-fake-module-3.4" but as I get about 600 mypy errors something seems to go wrong.

Thanks for the hints and information! Good to know that generators are more efficient than list comprehensions. I always thought it's the other way around. Merged the changes from your main branch and fixed the issues. I'm not sure how to go about mypy. Probably the stubs I use are not sufficient. I tried "blender stubs" and "bpy-fake-module-3.4" but as I get about 600 mypy errors something seems to go wrong.
Denys Hsu requested review from Sybren A. Stüvel 2023-06-04 22:10:18 +02:00
Denys Hsu added 1 commit 2023-06-04 22:13:10 +02:00

Good to know that generators are more efficient than list comprehensions. I always thought it's the other way around.

List comprehensions are basically generators that collect the result into a list, so it needs more memory allocations.

I'm not sure how to go about mypy. Probably the stubs I use are not sufficient. I tried "blender stubs" and "bpy-fake-module-3.4" but as I get about 600 mypy errors something seems to go wrong.

I don't use those stubs, so mypy is arguably less useful in my setup, but I don't get any errors, at least not on the main branch. mypy.ini should be set up so that it ignores unknown modules. Be sure to run mypy from the powership directory itself, and not some higher-up directory, otherwise it may not find the mypy.ini file.

Update: also this PR produces no mypy errors any more on my system.

> Good to know that generators are more efficient than list comprehensions. I always thought it's the other way around. List comprehensions are basically generators that collect the result into a list, so it needs more memory allocations. > I'm not sure how to go about mypy. Probably the stubs I use are not sufficient. I tried "blender stubs" and "bpy-fake-module-3.4" but as I get about 600 mypy errors something seems to go wrong. I don't use those stubs, so mypy is arguably less useful in my setup, but I don't get any errors, at least not on the `main` branch. `mypy.ini` should be set up so that it ignores unknown modules. Be sure to run mypy from the powership directory itself, and not some higher-up directory, otherwise it may not find the `mypy.ini` file. Update: also this PR produces no mypy errors any more on my system.
Denys Hsu added 1 commit 2023-06-05 10:46:49 +02:00
Denys Hsu added 1 commit 2023-06-05 11:01:20 +02:00
Denys Hsu added 1 commit 2023-06-05 11:10:36 +02:00
Author
Contributor

I don't use those stubs, so mypy is arguably less useful in my setup, but I don't get any errors, at least not on the main branch. mypy.ini should be set up so that it ignores unknown modules. Be sure to run mypy from the powership directory itself, and not some higher-up directory, otherwise it may not find the mypy.ini file.

Alright, thanks! Sorry for the commits after asking for the review, I cleaned up some typing related stuff. Tried to get Matan Gover's mypy extension to work properly with stubs in vsc... But guess that's to much.

Update: also this PR produces no mypy errors any more on my system.

Running mypy globally like you described works for me swell.

> I don't use those stubs, so mypy is arguably less useful in my setup, but I don't get any errors, at least not on the `main` branch. `mypy.ini` should be set up so that it ignores unknown modules. Be sure to run mypy from the powership directory itself, and not some higher-up directory, otherwise it may not find the `mypy.ini` file. Alright, thanks! Sorry for the commits after asking for the review, I cleaned up some typing related stuff. Tried to get _Matan Gover's_ mypy extension to work properly with stubs in vsc... But guess that's to much. > Update: also this PR produces no mypy errors any more on my system. Running mypy globally like you described works for me swell.

I'm getting errors when opening powership_transfer.blend and changing a frame to force a forward solve:

Running tree PowerShip
    - ForwardSolveNode('Forward Solve.001')
    - SequenceNode('Sequence')
    - SetBoneNode('Set Bone.007')
      1 prerequisites, going there first
    - RotateTowards('Rotate Towards.007')
      2 prerequisites, going there first
    - VectorMath('Vector Math.003')
      2 prerequisites, going there first
    - VectorMath('Vector Math.002')
      2 prerequisites, going there first
    - GetControlNode('Get Control.009')
    - GetControlNode('Get Control.010')
    - VectorMath('Vector Math.002')
Disabling auto-run on <bpy_struct, PowerShipNodeTree("PowerShip") at 0x7f4e5f7ad8c8> due to an exception
Traceback (most recent call last):
  File "/home/sybren/.config/blender/4.0/scripts/addons/powership/execute.py", line 85, in _on_frame_changed_post
    run_node_tree(scene, depsgraph)
  File "/home/sybren/.config/blender/4.0/scripts/addons/powership/execute.py", line 108, in run_node_tree
    execute_tree(tree, depsgraph, powership_mode)
  File "/home/sybren/.config/blender/4.0/scripts/addons/powership/execute.py", line 55, in execute_tree
    tree.run_event(depsgraph, mode)
  File "/home/sybren/.config/blender/4.0/scripts/addons/powership/nodes.py", line 47, in run_event
    self._run_from_node(depsgraph, start_node)
  File "/home/sybren/.config/blender/4.0/scripts/addons/powership/nodes.py", line 102, in _run_from_node
    node.run(depsgraph)
  File "/home/sybren/.config/blender/4.0/scripts/addons/powership/nodes.py", line 239, in run
    self.execute(depsgraph)
  File "/home/sybren/.config/blender/4.0/scripts/addons/powership/nodes.py", line 822, in execute
    res = u + v
TypeError: unsupported operand type(s) for +: 'bpy_prop_array' and 'bpy_prop_array'

I'm working on a more generic solution for things like this ;-)

I'm getting errors when opening `powership_transfer.blend` and changing a frame to force a forward solve: ``` Running tree PowerShip - ForwardSolveNode('Forward Solve.001') - SequenceNode('Sequence') - SetBoneNode('Set Bone.007') 1 prerequisites, going there first - RotateTowards('Rotate Towards.007') 2 prerequisites, going there first - VectorMath('Vector Math.003') 2 prerequisites, going there first - VectorMath('Vector Math.002') 2 prerequisites, going there first - GetControlNode('Get Control.009') - GetControlNode('Get Control.010') - VectorMath('Vector Math.002') Disabling auto-run on <bpy_struct, PowerShipNodeTree("PowerShip") at 0x7f4e5f7ad8c8> due to an exception Traceback (most recent call last): File "/home/sybren/.config/blender/4.0/scripts/addons/powership/execute.py", line 85, in _on_frame_changed_post run_node_tree(scene, depsgraph) File "/home/sybren/.config/blender/4.0/scripts/addons/powership/execute.py", line 108, in run_node_tree execute_tree(tree, depsgraph, powership_mode) File "/home/sybren/.config/blender/4.0/scripts/addons/powership/execute.py", line 55, in execute_tree tree.run_event(depsgraph, mode) File "/home/sybren/.config/blender/4.0/scripts/addons/powership/nodes.py", line 47, in run_event self._run_from_node(depsgraph, start_node) File "/home/sybren/.config/blender/4.0/scripts/addons/powership/nodes.py", line 102, in _run_from_node node.run(depsgraph) File "/home/sybren/.config/blender/4.0/scripts/addons/powership/nodes.py", line 239, in run self.execute(depsgraph) File "/home/sybren/.config/blender/4.0/scripts/addons/powership/nodes.py", line 822, in execute res = u + v TypeError: unsupported operand type(s) for +: 'bpy_prop_array' and 'bpy_prop_array' ``` I'm working on a more generic solution for things like this ;-)
Sybren A. Stüvel approved these changes 2023-06-05 12:03:59 +02:00
Sybren A. Stüvel left a comment
Owner

Thanks again for the PR! I'll accept & merge it into the main branch, then do a few tweaks to improve upon things further. Your changes illuminated some shortcomings in my code, and it's easier for me to merge this PR first, then address those shortcomings directly on the main branch.

Thanks again for the PR! I'll accept & merge it into the `main` branch, then do a few tweaks to improve upon things further. Your changes illuminated some shortcomings in my code, and it's easier for me to merge this PR first, then address those shortcomings directly on the main branch.
Sybren A. Stüvel manually merged commit dddb76b997 into main 2023-06-05 12:06:15 +02:00
Sign in to join this conversation.
No reviewers
No Label
No Milestone
No project
No Assignees
2 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: dr.sybren/rignodes#1
No description provided.