From 806a1e732d9190524c5de95c44c362c4da707a1d Mon Sep 17 00:00:00 2001 From: NotEvil Date: Fri, 17 Apr 2026 03:01:43 +0200 Subject: [PATCH] =?UTF-8?q?feat(animation):=20add=20FullHead=20convention?= =?UTF-8?q?=20=E2=80=94=20opt-in=20head=20animation=20in=20Full=20animatio?= =?UTF-8?q?ns?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit FullStruggle, FullWalk etc. animate body+legs but preserve head tracking. FullHeadStruggle, FullHeadWalk etc. also animate the head. The 'Head' keyword in the animation name is the opt-in signal. --- .../tiedup/remake/client/gltf/GltfPoseConverter.java | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/tiedup/remake/client/gltf/GltfPoseConverter.java b/src/main/java/com/tiedup/remake/client/gltf/GltfPoseConverter.java index 3946f1d..052b104 100644 --- a/src/main/java/com/tiedup/remake/client/gltf/GltfPoseConverter.java +++ b/src/main/java/com/tiedup/remake/client/gltf/GltfPoseConverter.java @@ -584,6 +584,10 @@ public final class GltfPoseConverter { // The "gltf_" prefix is added by convertClipSelective, so check for "gltf_Full" boolean isFullBodyAnimation = animName != null && animName.startsWith("gltf_Full"); + // Head is protected by default — only enabled as a free bone when the animation + // name contains "Head" (e.g., FullHeadStruggle, FullHeadIdle). + // This lets artists opt-in per animation without affecting the item's regions. + boolean allowFreeHead = isFullBodyAnimation && animName.contains("Head"); String[] allParts = { "head", @@ -606,14 +610,14 @@ public final class GltfPoseConverter { isFullBodyAnimation && enabledParts.contains(partName) && partsWithKeyframes.contains(partName) && - !"head".equals(partName) + (!"head".equals(partName) || allowFreeHead) ) { // 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. - // EXCEPTION: head is never enabled as a free bone — vanilla head - // tracking (mouse look) is always preserved unless the item - // explicitly owns a head region (HEAD, EYES, EARS, MOUTH). + // Head is protected by default (preserves vanilla head tracking). + // Use "Head" in the animation name (e.g., FullHeadStruggle) to + // explicitly opt-in to head control for that animation. part.fullyEnablePart(false); } else { // Non-Full animation, other item's part, or free part without keyframes.