Nodes/Avatar Graph/Object Join Shapes
ComfyUI Node

Object Join Shapes

Copying shape keys from every selected mesh onto one — the blendshape collector

By avatechai·Created 3 years ago·Updated 2 years ago· 265
Object Join Shapes
  • BPY_OBJ
  • BPY_OBJ

Shape keys are what make an avatar blink, talk, and smile - each key is a saved deformation of the mesh ("blink", "mouth open", "smile"), and animating the character is mostly just sliding those key values. Avatar Graph is built around them: the pack's whole schtick is generating a character whose eyes and mouth are shape-key driven so the Avatech editor can animate them in real time.

Object_JoinShapes is the node that pulls shape keys from several meshes onto one. It calls bpy.ops.object.join_shapes() - Blender's "Join Shapes" operation - which copies the shape keys from every selected object onto the active object. If you rigged your eye blink on the face mesh and your mouth shapes on a separate mouth layer, this is how both end up on the final single mesh.

How it works

Like the rest of the pack, BPY_OBJ sets the active object in the embedded scene and passes back through unchanged. The operator then walks the selected objects, finds their shape keys, and adds matching keys to the active mesh. It's a copy, not a move - the source objects keep their keys, and the source meshes need matching vertex counts with the target for the keys to make sense (shape keys are per-vertex offsets, so topology matters).

A couple of practical notes: key names come along, so you can keep the same "blink"/"mouth_open" names across layers and they merge cleanly. And because selection drives the whole thing, your graph needs the source layers selected upstream - connect BPY_OBJ to the target, make sure the sources are selected, and fire.

When you'd use it in an avatar graph

Whenever your deformation work is split across layers. The classic Avatar Graph template builds eye-blend and mouth-movement on separate mesh layers, then needs them on one object for the runtime shape flow. Run Object_JoinShapes before joining the geometry with Object_Join, or after, depending on whether you prefer to merge keys into a layer first. Either way, it's the node that consolidates your character's whole expression set onto the object that becomes the avatar.

Inputs and outputs

  • BPY_OBJ - the mesh receiving the shape keys; returned unchanged.
  • BPY_OBJ output - pass-through.

No other parameters - selection is your only control.

Installing it

Part of Avatar Graph (avatechai/avatar-graph-comfyui). ComfyUI Manager: search "Avatar Graph". Manual:

cd ComfyUI/custom_nodes
git clone https://github.com/avatechai/avatar-graph-comfyui
cd avatar-graph-comfyui && python -m pip install -r requirements.txt

Pack-level gotchas: bpy==3.6.0 requires Python 3.10.x (the wheel won't build on 3.11+), and first launch auto-downloads the SAM ViT-H checkpoint (~2.5 GB) plus MediaPipe landmarkers.

Common issues

The dominant failure is topology mismatch: if the source and target meshes have different vertex counts, the copied keys apply garbage offsets. That happens when you join meshes with modifiers that changed topology, or when sources weren't rebuilt identically in the scene. Also, selection again - connect the target but forget to select the sources and nothing transfers. And a subtle one: joining geometry with Object_Join after copying keys is fine, but joining first and then copying from the old sources can fail because the source vertex counts changed. Order your graph so the sources still match.

Categoryblender

Inputs (1)

NameTypeDefaultDescription
BPY_OBJoptBPY_OBJ

Outputs (1)

NameTypeDescription
BPY_OBJBPY_OBJ