I'm pretty sure I know the answer to this, but I just need to ask to make sure I'm not missing something.
I'm trying to do something similar to how the Voronoi Fracture can generate selections and vertex maps. Selections have been going swell, its these pesky vertex maps! My plugin happens to be a tag, not a generator... not sure if that distinction matters in this context.
I don't know how c4d updates vertex maps when their host object's geometry changes, but it certainly doesn't happen when that host object is parametric. Once the geometry changes a replacement tag needs to be generated and the old vertex map's goals transferred to it. While I've been able to get this much of it working, once I attempt to delete the original tag it all falls apart. Even if I could get this working, I still don't know where I could safely call the following function in a NodeData plugin:
def RefreshVertexMapTag(vmap, obj, point_cnt):
# Make a brand new vertex map tag
replacement_tag = obj.MakeVariableTag(c4d.Tvertexmap, point_count, vmap)
# Disable the tag so that c4d doesn't try to update it
replacement_tag[c4d.EXPRESSION_ENABLE] = False
# transfer all goals to the new tag
vmap.TransferGoal(replacement_tag, False)
# Remove the original tag
vmap.Remove()
This very simplified function is based on a workaround posted by Maxime last year, simply to illustrate what it would entail to expose a vertex map on a generator who's data is of a variable size, noting that it is not suitable for production because it does some cross-threaded things that could crash c4d.
I've even tried updating the byte sequence manually using GetAllLowlevelDataW(), but since that's dealing with a memoryview it naturally doesn't work.
So, I've finally resigned to giving up on this effort, but not without at least asking if it's possible. Can a vertex map be updated to respond to the changing geometry of a parametric object/generator in a way that is safe to use in a NodeData plugin?
To recap:
-
SetAllHighlevelData(): throws an error when the passed data's size differs
-
GetAllLowlevelDataW(): basically same result as above, except quietly (no error, just never applies any of the changes to the byte sequence)
-
Fully replace tag: Works until you try to delete the old tag, then none of it works... but even if it did it's prone to crashing c4d.
Thanks in advance for either confirming the bad news... or for swooping in to save the day (if that's possible!)
Cheers!
Kevin