feature/gltf-pipeline-v2 #18
@@ -208,12 +208,14 @@ public final class GltfPoseConverter {
|
||||
}
|
||||
}
|
||||
|
||||
// Selective: enable owned parts always, free parts only if they have keyframes
|
||||
// Selective: enable owned parts always, free parts only for "Full" animations
|
||||
// that explicitly opt into full-body control.
|
||||
enableSelectiveParts(
|
||||
builder,
|
||||
ownedParts,
|
||||
enabledParts,
|
||||
partsWithKeyframes
|
||||
partsWithKeyframes,
|
||||
animName
|
||||
);
|
||||
|
||||
KeyframeAnimation anim = builder.build();
|
||||
@@ -554,22 +556,35 @@ public final class GltfPoseConverter {
|
||||
*
|
||||
* <ul>
|
||||
* <li>Owned parts: always enabled (the item controls these bones)</li>
|
||||
* <li>Free parts WITH keyframes: enabled (the GLB has animation data for them)</li>
|
||||
* <li>Free parts WITHOUT keyframes: disabled (no data to animate, pass through to context)</li>
|
||||
* <li>Free parts WITH keyframes AND "Full" animation: enabled (explicit opt-in to full-body)</li>
|
||||
* <li>Free parts without "Full" prefix: disabled (prevents accidental bone hijacking)</li>
|
||||
* <li>Other items' parts: disabled (pass through to their own layer)</li>
|
||||
* </ul>
|
||||
*
|
||||
* <p>The "Full" prefix convention (FullIdle, FullStruggle, FullWalk) is the artist's
|
||||
* explicit declaration that this animation is designed to control the entire body,
|
||||
* not just the item's owned regions. Without this prefix, free bones are never enabled,
|
||||
* even if the GLB contains keyframes for them. This prevents accidental bone hijacking
|
||||
* when an artist keyframes all bones in Blender by default.</p>
|
||||
*
|
||||
* @param builder the animation builder with keyframes already added
|
||||
* @param ownedParts parts the item explicitly owns (always enabled)
|
||||
* @param enabledParts parts the item may animate (owned + free)
|
||||
* @param partsWithKeyframes parts that received actual animation data from the GLB
|
||||
* @param animName resolved animation name (checked for "Full" prefix)
|
||||
*/
|
||||
private static void enableSelectiveParts(
|
||||
KeyframeAnimation.AnimationBuilder builder,
|
||||
Set<String> ownedParts,
|
||||
Set<String> enabledParts,
|
||||
Set<String> partsWithKeyframes
|
||||
Set<String> partsWithKeyframes,
|
||||
String animName
|
||||
) {
|
||||
// Free bones are only enabled for "Full" animations (FullIdle, FullStruggle, etc.)
|
||||
// The "gltf_" prefix is added by convertClipSelective, so check for "gltf_Full"
|
||||
boolean isFullBodyAnimation = animName != null &&
|
||||
animName.startsWith("gltf_Full");
|
||||
|
||||
String[] allParts = {
|
||||
"head",
|
||||
"body",
|
||||
@@ -588,13 +603,16 @@ public final class GltfPoseConverter {
|
||||
// Always enable owned parts — the item controls these bones
|
||||
part.fullyEnablePart(false);
|
||||
} else if (
|
||||
isFullBodyAnimation &&
|
||||
enabledParts.contains(partName) &&
|
||||
partsWithKeyframes.contains(partName)
|
||||
) {
|
||||
// Free part WITH keyframes: enable so the GLB animation drives it
|
||||
// Full-body animation: free part WITH keyframes — enable.
|
||||
// The "Full" prefix is the artist's explicit opt-in to animate
|
||||
// bones outside their declared regions.
|
||||
part.fullyEnablePart(false);
|
||||
} else {
|
||||
// Other item's part, or free part without keyframes: disable.
|
||||
// Non-Full animation, other item's part, or free part without keyframes.
|
||||
// Disabled parts pass through to the lower-priority context layer.
|
||||
part.setEnabled(false);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user