From 99ace36b326fd760945ca28925047589ad6c1b14 Mon Sep 17 00:00:00 2001 From: ZigyTheBird <105124180+ZigyTheBird@users.noreply.github.com> Date: Mon, 29 Dec 2025 20:13:41 +0330 Subject: [PATCH 1/5] Default bones can now be parents too --- .../animation/AnimationController.java | 17 +++++++++++++---- .../playeranimcore/util/MatrixUtil.java | 6 +++++- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/core/src/main/java/com/zigythebird/playeranimcore/animation/AnimationController.java b/core/src/main/java/com/zigythebird/playeranimcore/animation/AnimationController.java index 9f3caa3..5f79f2b 100644 --- a/core/src/main/java/com/zigythebird/playeranimcore/animation/AnimationController.java +++ b/core/src/main/java/com/zigythebird/playeranimcore/animation/AnimationController.java @@ -24,6 +24,7 @@ package com.zigythebird.playeranimcore.animation; +import com.zigythebird.playeranimcore.PlayerAnimLib; import com.zigythebird.playeranimcore.animation.keyframe.*; import com.zigythebird.playeranimcore.animation.keyframe.event.CustomKeyFrameEvents; import com.zigythebird.playeranimcore.animation.keyframe.event.data.CustomInstructionKeyframeData; @@ -639,19 +640,27 @@ protected void applyCustomPivotPoints() { bones1.add(pivotBone); } + List processedBones = new ArrayList<>(); + for (PlayerAnimBone bone : bones1) { if (parentsMap.containsKey(bone.getName())) { this.activeBones.put(bone.getName(), bone); - List parents = new ArrayList<>(); - PivotBone currentParent = this.pivotBones.get(parentsMap.get(bone.getName())); - parents.add(currentParent); + List parents = new ArrayList<>(); + PlayerAnimBone currentParent = bone; while (parentsMap.containsKey(currentParent.getName())) { - currentParent = this.pivotBones.get(parentsMap.get(currentParent.getName())); + String parentName = parentsMap.get(currentParent.getName()); + currentParent = this.pivotBones.containsKey(parentName) ? this.pivotBones.get(parentName) : this.bones.getOrDefault(parentName, null); + if (currentParent == null) { + PlayerAnimLib.LOGGER.error("Failed to find parent bone called {}", parentName); + break; + } parents.addFirst(currentParent); + if (processedBones.contains(currentParent.getName())) break; } MatrixUtil.applyParentsToChild(bone, parents, this::getBonePosition); + processedBones.add(bone.getName()); } } } diff --git a/core/src/main/java/com/zigythebird/playeranimcore/util/MatrixUtil.java b/core/src/main/java/com/zigythebird/playeranimcore/util/MatrixUtil.java index 52f4184..ad4b6d3 100644 --- a/core/src/main/java/com/zigythebird/playeranimcore/util/MatrixUtil.java +++ b/core/src/main/java/com/zigythebird/playeranimcore/util/MatrixUtil.java @@ -12,6 +12,10 @@ * Used for applying custom pivot bones to player bones */ public class MatrixUtil { + public static void translateMatrixForBone(ModMatrix4f matrix, PlayerAnimBone bone) { + matrix.translate(-bone.getPosX(), bone.getPosY(), -bone.getPosZ()); + } + public static void rotateMatrixAroundBone(ModMatrix4f matrix, PlayerAnimBone bone) { if (bone.getRotZ() != 0 || bone.getRotY() != 0 || bone.getRotX() != 0) matrix.rotateZ(bone.getRotZ()).rotateY(bone.getRotY()).rotateX(bone.getRotX()); @@ -31,6 +35,7 @@ public static void translateAwayFromPivotPoint(ModMatrix4f matrix, Vec3f pivot) public static void prepMatrixForBone(ModMatrix4f matrix, PlayerAnimBone bone, Vec3f pivot) { translateToPivotPoint(matrix, pivot); + translateMatrixForBone(matrix, bone); rotateMatrixAroundBone(matrix, bone); scaleMatrixForBone(matrix, bone); translateAwayFromPivotPoint(matrix, pivot); @@ -42,7 +47,6 @@ public static void applyParentsToChild(PlayerAnimBone child, Iterable Date: Sun, 25 Jan 2026 20:01:04 +0700 Subject: [PATCH 2/5] Update AnimationController.java --- .../animation/AnimationController.java | 44 ++++++++++++------- 1 file changed, 27 insertions(+), 17 deletions(-) diff --git a/core/src/main/java/com/zigythebird/playeranimcore/animation/AnimationController.java b/core/src/main/java/com/zigythebird/playeranimcore/animation/AnimationController.java index 5f79f2b..21fb2f0 100644 --- a/core/src/main/java/com/zigythebird/playeranimcore/animation/AnimationController.java +++ b/core/src/main/java/com/zigythebird/playeranimcore/animation/AnimationController.java @@ -634,33 +634,43 @@ protected void applyCustomPivotPoints() { Map parentsMap = this.currentAnimation.animation().parents(); if (parentsMap.isEmpty()) return; - List bones1 = new ArrayList<>(this.bones.values()); - for (PlayerAnimBone pivotBone : this.pivotBones.values()) { - if (!parentsMap.containsValue(pivotBone.getName())) - bones1.add(pivotBone); - } + Set bones1 = new LinkedHashSet<>(this.bones.values()); + bones1.addAll(this.pivotBones.values()); - List processedBones = new ArrayList<>(); + Set processedBones = new HashSet<>(); for (PlayerAnimBone bone : bones1) { - if (parentsMap.containsKey(bone.getName())) { - this.activeBones.put(bone.getName(), bone); + String boneName = bone.getName(); + + if (parentsMap.containsKey(boneName)) { + this.activeBones.put(boneName, bone); List parents = new ArrayList<>(); - PlayerAnimBone currentParent = bone; - while (parentsMap.containsKey(currentParent.getName())) { - String parentName = parentsMap.get(currentParent.getName()); - currentParent = this.pivotBones.containsKey(parentName) ? this.pivotBones.get(parentName) : this.bones.getOrDefault(parentName, null); - if (currentParent == null) { - PlayerAnimLib.LOGGER.error("Failed to find parent bone called {}", parentName); + + String currentParentName = parentsMap.get(boneName); + while (currentParentName != null) { + if (processedBones.contains(currentParentName)) { + PlayerAnimBone parent = this.pivotBones.get(currentParentName); + if (parent == null) parent = this.bones.get(currentParentName); + + if (parent != null) parents.addFirst(parent); break; } - parents.addFirst(currentParent); - if (processedBones.contains(currentParent.getName())) break; + + PlayerAnimBone parent = this.pivotBones.get(currentParentName); + if (parent == null) parent = this.bones.get(currentParentName); + + if (parent == null) { + PlayerAnimLib.LOGGER.error("Failed to find parent bone called {}", currentParentName); + break; + } + + parents.addFirst(parent); + currentParentName = parentsMap.get(currentParentName); } MatrixUtil.applyParentsToChild(bone, parents, this::getBonePosition); - processedBones.add(bone.getName()); + processedBones.add(boneName); } } } From 5cf0ea9fc9c34958340c887545fee4c0ea369499 Mon Sep 17 00:00:00 2001 From: dima_dencep Date: Sun, 25 Jan 2026 20:07:23 +0700 Subject: [PATCH 3/5] remove duplicate code --- .../animation/AnimationController.java | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/core/src/main/java/com/zigythebird/playeranimcore/animation/AnimationController.java b/core/src/main/java/com/zigythebird/playeranimcore/animation/AnimationController.java index 21fb2f0..73ebae7 100644 --- a/core/src/main/java/com/zigythebird/playeranimcore/animation/AnimationController.java +++ b/core/src/main/java/com/zigythebird/playeranimcore/animation/AnimationController.java @@ -649,14 +649,6 @@ protected void applyCustomPivotPoints() { String currentParentName = parentsMap.get(boneName); while (currentParentName != null) { - if (processedBones.contains(currentParentName)) { - PlayerAnimBone parent = this.pivotBones.get(currentParentName); - if (parent == null) parent = this.bones.get(currentParentName); - - if (parent != null) parents.addFirst(parent); - break; - } - PlayerAnimBone parent = this.pivotBones.get(currentParentName); if (parent == null) parent = this.bones.get(currentParentName); @@ -665,6 +657,11 @@ protected void applyCustomPivotPoints() { break; } + if (processedBones.contains(currentParentName)) { + parents.addFirst(parent); + break; + } + parents.addFirst(parent); currentParentName = parentsMap.get(currentParentName); } From 94e8857876d6b220a59eaa9886965bd506b30844 Mon Sep 17 00:00:00 2001 From: dima_dencep Date: Sun, 25 Jan 2026 20:16:41 +0700 Subject: [PATCH 4/5] reset pivot bones --- .../playeranimcore/animation/AnimationController.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/core/src/main/java/com/zigythebird/playeranimcore/animation/AnimationController.java b/core/src/main/java/com/zigythebird/playeranimcore/animation/AnimationController.java index 73ebae7..d469051 100644 --- a/core/src/main/java/com/zigythebird/playeranimcore/animation/AnimationController.java +++ b/core/src/main/java/com/zigythebird/playeranimcore/animation/AnimationController.java @@ -546,6 +546,9 @@ private void processCurrentAnimation(float adjustedTick, AnimationData animation for (AdvancedPlayerAnimBone bone : this.bones.values()) { bone.setToInitialPose(); } + for (PlayerAnimBone bone : this.pivotBones.values()) { + bone.setToInitialPose(); + } return; } @@ -563,6 +566,9 @@ private void processCurrentAnimation(float adjustedTick, AnimationData animation for (PlayerAnimBone bone : this.bones.values()) { bone.setToInitialPose(); } + for (PlayerAnimBone bone : this.pivotBones.values()) { + bone.setToInitialPose(); + } for (Map.Entry entry : animation.boneAnimations().entrySet()) { PlayerAnimBone bone = this.bones.getOrDefault(entry.getKey(), null); From 0d9c53e9a8a047960130c4872e369c0905a13c63 Mon Sep 17 00:00:00 2001 From: dima_dencep Date: Sun, 25 Jan 2026 20:46:20 +0700 Subject: [PATCH 5/5] Fix `processedBones` --- .../animation/AnimationController.java | 54 +++++++++---------- 1 file changed, 25 insertions(+), 29 deletions(-) diff --git a/core/src/main/java/com/zigythebird/playeranimcore/animation/AnimationController.java b/core/src/main/java/com/zigythebird/playeranimcore/animation/AnimationController.java index d469051..c9f76be 100644 --- a/core/src/main/java/com/zigythebird/playeranimcore/animation/AnimationController.java +++ b/core/src/main/java/com/zigythebird/playeranimcore/animation/AnimationController.java @@ -640,42 +640,38 @@ protected void applyCustomPivotPoints() { Map parentsMap = this.currentAnimation.animation().parents(); if (parentsMap.isEmpty()) return; - Set bones1 = new LinkedHashSet<>(this.bones.values()); - bones1.addAll(this.pivotBones.values()); - Set processedBones = new HashSet<>(); + for (PlayerAnimBone bone : this.bones.values()) { + processBoneHierarchy(bone, parentsMap, processedBones); + } + for (PlayerAnimBone bone : this.pivotBones.values()) { + processBoneHierarchy(bone, parentsMap, processedBones); + } + } - for (PlayerAnimBone bone : bones1) { - String boneName = bone.getName(); - - if (parentsMap.containsKey(boneName)) { - this.activeBones.put(boneName, bone); - - List parents = new ArrayList<>(); + private void processBoneHierarchy(PlayerAnimBone bone, Map parentsMap, Set processedBones) { + String boneName = bone.getName(); + if (processedBones.contains(boneName)) return; - String currentParentName = parentsMap.get(boneName); - while (currentParentName != null) { - PlayerAnimBone parent = this.pivotBones.get(currentParentName); - if (parent == null) parent = this.bones.get(currentParentName); + String parentName = parentsMap.get(boneName); + if (parentName == null) { + processedBones.add(boneName); + return; + } - if (parent == null) { - PlayerAnimLib.LOGGER.error("Failed to find parent bone called {}", currentParentName); - break; - } + PlayerAnimBone parent = this.pivotBones.get(parentName); + if (parent == null) parent = this.bones.get(parentName); + if (parent == null) { + PlayerAnimLib.LOGGER.error("Parent {} not found for {}", parentName, boneName); + return; + } - if (processedBones.contains(currentParentName)) { - parents.addFirst(parent); - break; - } + processBoneHierarchy(parent, parentsMap, processedBones); - parents.addFirst(parent); - currentParentName = parentsMap.get(currentParentName); - } + this.activeBones.put(boneName, bone); + MatrixUtil.applyParentsToChild(bone, Collections.singletonList(parent), this::getBonePosition); - MatrixUtil.applyParentsToChild(bone, parents, this::getBonePosition); - processedBones.add(boneName); - } - } + processedBones.add(boneName); } protected void handleCustomKeyframe(T[] keyframes, @Nullable CustomKeyFrameEvents.CustomKeyFrameHandler main, CustomKeyFrameEvents.CustomKeyFrameHandler event, float animationTick, AnimationData animationData) {