Joining Armatures #84750
Labels
No Label
Interest
Alembic
Interest
Animation & Rigging
Interest
Asset Browser
Interest
Asset Browser Project Overview
Interest
Audio
Interest
Automated Testing
Interest
Blender Asset Bundle
Interest
BlendFile
Interest
Collada
Interest
Compatibility
Interest
Compositing
Interest
Core
Interest
Cycles
Interest
Dependency Graph
Interest
Development Management
Interest
EEVEE
Interest
EEVEE & Viewport
Interest
Freestyle
Interest
Geometry Nodes
Interest
Grease Pencil
Interest
ID Management
Interest
Images & Movies
Interest
Import Export
Interest
Line Art
Interest
Masking
Interest
Metal
Interest
Modeling
Interest
Modifiers
Interest
Motion Tracking
Interest
Nodes & Physics
Interest
OpenGL
Interest
Overlay
Interest
Overrides
Interest
Performance
Interest
Physics
Interest
Pipeline, Assets & IO
Interest
Platforms, Builds & Tests
Interest
Python API
Interest
Render & Cycles
Interest
Render Pipeline
Interest
Sculpt, Paint & Texture
Interest
Text Editor
Interest
Translations
Interest
Triaging
Interest
Undo
Interest
USD
Interest
User Interface
Interest
UV Editing
Interest
VFX & Video
Interest
Video Sequencer
Interest
Virtual Reality
Interest
Vulkan
Interest
Wayland
Interest
Workbench
Interest: X11
Legacy
Blender 2.8 Project
Legacy
Milestone 1: Basic, Local Asset Browser
Legacy
OpenGL Error
Meta
Good First Issue
Meta
Papercut
Meta
Retrospective
Meta
Security
Module
Animation & Rigging
Module
Core
Module
Development Management
Module
EEVEE & Viewport
Module
Grease Pencil
Module
Modeling
Module
Nodes & Physics
Module
Pipeline, Assets & IO
Module
Platforms, Builds & Tests
Module
Python API
Module
Render & Cycles
Module
Sculpt, Paint & Texture
Module
Triaging
Module
User Interface
Module
VFX & Video
Platform
FreeBSD
Platform
Linux
Platform
macOS
Platform
Windows
Priority
High
Priority
Low
Priority
Normal
Priority
Unbreak Now!
Status
Archived
Status
Confirmed
Status
Duplicate
Status
Needs Info from Developers
Status
Needs Information from User
Status
Needs Triage
Status
Resolved
Type
Bug
Type
Design
Type
Known Issue
Type
Patch
Type
Report
Type
To Do
No Milestone
No project
No Assignees
5 Participants
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: blender/blender#84750
Loading…
Reference in New Issue
No description provided.
Delete Branch "%!s(<nil>)"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Joining armatures is something that will become common in my workflow in the coming months and knowing this, I had to write an operator to facilitate this. But it feels like this should just work without an addon. I'd like to know if the rest of the animation module agrees, and this is something that could go into Blender's Join operator, or if any of these changes are controversial.
This is something I just might be able to implement myself, but I'd rather let a competent developer do it, if there are any volunteers. :)
Here are the current problems when simply trying to join two armatures:
Bone Groups
Bone Groups of the active armature are preserved, but bone groups of the source armature(s) are completely nuked, or worse, assigned seemingly at random.
Sometimes two armatures will have bone groups with the same name. In this case it would be best to "merge" these bone groups. It could happen that identically named bone groups have different colors, in which case this color data will be lost. In this case such bone groups could be suffixed with a .001 instead of being merged. But strictly only if the bone group colors do not match, otherwise just go ahead and merge them.
Parenting
Currently, when joining Armature A into Armature B, all objects that were parented to A are now parented to B. This is good! However, if the armatures weren't in the same place, the parented objects will move because their transform matrix and parent inverse matrix is not set. (Currently in my script I set the transform matrix, but I guess changing the parent inverse matrix would be more correct.)
Modifier's References
Sticking to the above A->B example, armature modifiers that were referencing A now reference nothing. I think these references should be redirected to Armature B.
Perhaps this can be applied more generally, so that when any objects are joined into an object O, all references to the merged objects should be remapped to O? Are there any cases where this would be bad?
(Note: I tried doing this with the current bpy.ops.outliner.remap_users() operator, but it segfaulted.)
Vertex Groups
Bone names can clash, and then they need to be appended with a .001 in their name. That's fine, but in this case the objects that were rigged with the original bone names now have vertex group names that did not get renamed. Fixing this is very painful. So, these vertex groups should be renamed along with the bones.
Speed
Just a nitpick, but I find it odd that joining complex rigs can take up to 10 seconds! I've added some timers to my python operator to show how just the Join operation is taking super long. Maybe some low hanging fruit optimization is possible there?
Test files:
simple_armatures_with_objects.blend (Just press Ctrl+J to see the usual result, and Alt+H to see the desired result)
complex_armatures.blend (For testing the speed)
CC @dr.sybren @jpbouza-4 @LucianoMunoz and any other people interested in rigging, for opinions :)
Added subscriber: @Mets
Added subscriber: @JerBot
Added subscribers: @LucianoMunoz, @jpbouza-4, @dr.sybren
I feel this could feel a bit arbitrary. Especially when the user doesn't know the color is the decisive factor here. I can imagine a situation where a rigger is less strict with the coloring; in that case a minute difference in hue/brightness would already impact whether the vertex groups are merged or not. How about a choice "Merge: Never/Same Name/Same Name And Color"? That way it's at least explicit that color is a factor in this.
Yes, this is exactly what the Parent Inverse matrix is for: to make it possible to change the parent without moving the object.
I agree. It's a "Join" operation, not a "Delete an armature and add new bones to an unrelated armature that just by sheer coincidence happen to match what was deleted" operator.
Calling operators should be avoided in Python code. You should be able to call
armature_a.users_remap(armature_b)
and maybe alsoarmature_object_a.users_remap(armature_object_b)
.Certainly.
That's a long time indeed! Do you have any idea where in the code this time is spent?
I'm all for choice! :D I guess the safest default then might be "Never".
As far as I can tell this isn't exposed to PyAPI? 👀 If you're saying it should be, I certainly agree! Heck, there should be some convention to always expose operator code as non-operator functions for PyAPI, but that's another discussion... :D
Nope, I didn't try touch or look at the C code, I just slapped my Python operator together and called it a day for now. But, I'd love to spend some of my free time banging my head against some C code again sometime :) (coding nights? ^^)
It is, but only if you spell it properly (my mistake): https://docs.blender.org/api/master/bpy.types.ID.html#bpy.types.ID.user_remap
I agree (on both statements ;-) )
Ok, if "the C code" is the best we get, that's fine :)
It doesn't help that I'm blind! :D
Yepyep, the existing Join operator seems to take several seconds when joining two complex armatures.
Added subscriber: @AquaticNightmare
Added subscriber: @lichtwerk
Changed status from 'Needs Triage' to: 'Confirmed'
Sounds like this is
Confirmed
.