Skip to content

Commit

Permalink
Refactoring progress
Browse files Browse the repository at this point in the history
  • Loading branch information
Trainguy9512 committed Jan 27, 2025
1 parent de94a78 commit 941c391
Show file tree
Hide file tree
Showing 19 changed files with 333 additions and 510 deletions.
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
package com.trainguy9512.animationoverhaul;


import com.trainguy9512.animationoverhaul.animation.LivingEntityAnimatorRegistry;
import com.trainguy9512.animationoverhaul.animation.animator.entity.PlayerJointAnimator;
import com.trainguy9512.animationoverhaul.animation.animator.JointAnimatorRegistry;
import com.trainguy9512.animationoverhaul.animation.animator.entity.FirstPersonPlayerJointAnimator;
import com.trainguy9512.animationoverhaul.animation.data.AnimationSequenceDataLoader;
import net.fabricmc.api.ModInitializer;
import net.fabricmc.fabric.api.resource.ResourceManagerHelper;
import net.minecraft.server.packs.PackType;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

Expand All @@ -20,9 +18,6 @@ public class AnimationOverhaulMain implements ModInitializer {

public static Logger LOGGER = LogManager.getLogger();

public static final LivingEntityAnimatorRegistry ENTITY_ANIMATORS = new LivingEntityAnimatorRegistry();
public static Entity debugEntity;


public static void onClientInit() {
registerTimelineGroupLoader();
Expand Down Expand Up @@ -55,7 +50,7 @@ public void onInitialize() {


private static void registerEntityAnimators(){
ENTITY_ANIMATORS.register(EntityType.PLAYER, new PlayerJointAnimator());
JointAnimatorRegistry.registerFirstPersonPlayerJointAnimator(new FirstPersonPlayerJointAnimator());
}

/*
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -9,41 +9,26 @@
* Uses a data reference and a joint skeleton to calculate a pose once per tick.
* @param <T> Object used for data reference
*/
public abstract class JointAnimator<T> {

protected final JointSkeleton jointSkeleton;

protected JointAnimator() {
this.jointSkeleton = buildSkeleton();
}

/**
* Returns the joint skeleton used by the animator as reference.
* @return Joint skeleton
*/
public JointSkeleton getJointSkeleton(){
return this.jointSkeleton;
}
public interface JointAnimator<T> {

/**
* Retrieves a joint skeleton created upon class construction
* @return Built joint skeleton
* Creates a joint skeleton created upon class construction
* @return Built joint skeleton
*/
protected abstract JointSkeleton buildSkeleton();
public JointSkeleton buildSkeleton();

/**
* Uses an object for data reference and updates the animation data container. Called once per tick, prior to pose samplers updating and pose calculation.
* @param dataReference Object used as reference for updating the animation data container
* @param animationDriverContainer Data container from the previous tick
* @return Resulting data container
* @param dataReference Object used as reference for updating the animation data container
* @param animationDriverContainer Data container from the previous tick
*/
public abstract AnimationDriverContainer extractAnimationData(T dataReference, AnimationDriverContainer animationDriverContainer);
public abstract void extractAnimationData(T dataReference, AnimationDriverContainer animationDriverContainer);

/**
* Calculates and returns an animation pose once per tick, after pose sampler update and animation data extraction
* @param animationDriverContainer Data container containing extracted animation variable data.
* @param poseSamplerStateContainer Data container containing pose sampler states, used for sampling poses.
* @return Calculated animation pose to be passed off to the baked animation pose
* @param animationDriverContainer Data container containing extracted animation variable data.
* @param poseSamplerStateContainer Data container containing pose sampler states, used for sampling poses.
* @return Calculated animation pose to be passed off to the baked animation pose
*/
public abstract AnimationPose calculatePose(AnimationDriverContainer animationDriverContainer, PoseSamplerStateContainer poseSamplerStateContainer);
public abstract AnimationPose calculatePose(AnimationDriverContainer animationDriverContainer, PoseSamplerStateContainer poseSamplerStateContainer, JointSkeleton jointSkeleton);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package com.trainguy9512.animationoverhaul.animation.animator;

import com.google.common.collect.Maps;
import com.trainguy9512.animationoverhaul.animation.animator.entity.EntityJointAnimator;
import com.trainguy9512.animationoverhaul.animation.animator.entity.LivingEntityJointAnimator;
import com.trainguy9512.animationoverhaul.animation.pose.JointSkeleton;
import net.minecraft.client.player.LocalPlayer;
import net.minecraft.client.renderer.entity.state.PlayerRenderState;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType;
import org.jetbrains.annotations.Nullable;

import java.util.HashMap;

public class JointAnimatorRegistry {

private static final HashMap<EntityType<?>, EntityJointAnimator<?, ?>> THIRD_PERSON_ENTITY_JOINT_ANIMATORS = Maps.newHashMap();
private static final HashMap<EntityType<?>, JointSkeleton> THIRD_PERSON_ENTITY_JOINT_SKELETONS = Maps.newHashMap();

private static LivingEntityJointAnimator<LocalPlayer, PlayerRenderState> FIRST_PERSON_PLAYER_JOINT_ANIMATOR = null;
private static JointSkeleton FIRST_PERSON_PLAYER_JOINT_SKELETON = null;

/**
* Registers a joint animator for use on third person living entities.
* @param entityType Type of entity associated with the living entity
* @param entityJointAnimator Newly constructed entity joint animator object
*/
public static <T extends Entity> void registerEntityJointAnimator(EntityType<T> entityType, EntityJointAnimator<T, ?> entityJointAnimator){
THIRD_PERSON_ENTITY_JOINT_ANIMATORS.put(entityType, entityJointAnimator);
THIRD_PERSON_ENTITY_JOINT_SKELETONS.put(entityType, entityJointAnimator.buildSkeleton());
}


public static void registerFirstPersonPlayerJointAnimator(LivingEntityJointAnimator<LocalPlayer, PlayerRenderState> firstPersonPlayerJointAnimator){
FIRST_PERSON_PLAYER_JOINT_ANIMATOR = firstPersonPlayerJointAnimator;
FIRST_PERSON_PLAYER_JOINT_SKELETON = firstPersonPlayerJointAnimator.buildSkeleton();
}

/**
* Returns whether the provided entity type has a registered joint animator.
* @param entityType Entity type
*/
public static boolean entityTypeRegisteredWithJointAnimator(EntityType<?> entityType){
return THIRD_PERSON_ENTITY_JOINT_ANIMATORS.containsKey(entityType);
}

/**
* Returns the entity joint animator for the provided entity type. If the entity type does not have a joint animator registered, null is returned.
* @param entityType Entity type
* @return Entity joint animator
*/
@Nullable
@SuppressWarnings("unchecked")
public static <T extends Entity> EntityJointAnimator<T, ?> getThirdPersonJointAnimator(EntityType<T> entityType){
return (EntityJointAnimator<T, ?>) THIRD_PERSON_ENTITY_JOINT_ANIMATORS.get(entityType);
}

/**
* Returns a joint skeleton for the provided entity type. If the entity type does not have a joint animator registered, null is returned.
* @param entityType Entity type
* @return Joint skeleton
*/
@Nullable
public static JointSkeleton getThirdPersonJointSkeleton(EntityType<?> entityType){
return THIRD_PERSON_ENTITY_JOINT_SKELETONS.get(entityType);
}

/**
* Returns the first person player joint animator, if it has been registered. If not, it returns null.
*/
@Nullable
public static LivingEntityJointAnimator<LocalPlayer, PlayerRenderState> getFirstPersonPlayerJointAnimator(){
return FIRST_PERSON_PLAYER_JOINT_ANIMATOR;
}

/**
* Returns the first person player joint skeleton, if it has been registered. If not, it returns null.
*/
@Nullable
public static JointSkeleton getFirstPersonPlayerJointSkeleton(){
return FIRST_PERSON_PLAYER_JOINT_SKELETON;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,55 +7,12 @@
import net.minecraft.client.renderer.entity.state.EntityRenderState;
import net.minecraft.world.entity.Entity;

public abstract class EntityJointAnimator<T extends Entity, S extends EntityRenderState> extends JointAnimator<T> {


//protected AnimationDataContainer entityAnimationData;

public EntityJointAnimator(){
super();
}

/*
protected WalkAnimationState getWalkAnimationState(){
return this.livingEntity != null ? this.livingEntity.walkAnimation : new WalkAnimationState();
}
public interface EntityJointAnimator<T extends Entity, S extends EntityRenderState> extends JointAnimator<T> {

/**
* Does some final operations on the entity model, similar to what would happen in the {@link EntityModel#setupAnim(EntityRenderState)} function. Called every frame after pose interpolation.\
* @param entityRenderState Entity render state
* @param rootModelPart Root model part of the entity model
*/

/*
public void overallTick(LivingEntity livingEntity){
BakedAnimationPose<L> bakedPose = EntityJointAnimatorDispatcher.INSTANCE.getBakedPose(livingEntity.getUUID());
AnimationDataContainer entityAnimationData = EntityJointAnimatorDispatcher.INSTANCE.getEntityAnimationData(livingEntity.getUUID());
this.tick(livingEntity, entityAnimationData);
entityAnimationData.tickAnimationStates();
if(bakedPose == null){
bakedPose = new BakedAnimationPose<L>();
}
if(!bakedPose.hasPose){
bakedPose.setPose(AnimationPose.of(this.jointSkeleton));
bakedPose.hasPose = true;
}
bakedPose.pushToOld();
//this.locatorRig.resetRig();
AnimationPose<L> animationPose = this.calculatePose();
if (animationPose == null){
animationPose = AnimationPose.of(this.jointSkeleton);
}
animationPose.applyDefaultPoseOffset();
bakedPose.setPose(animationPose.getCopy());
EntityJointAnimatorDispatcher.INSTANCE.saveBakedPose(livingEntity.getUUID(), bakedPose);
}
*/



public void postProcessModelParts(S entityRenderState, ModelPart rootModelPart){
}
public void postProcessModelParts(S entityRenderState, ModelPart rootModelPart);
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
package com.trainguy9512.animationoverhaul.animation;
package com.trainguy9512.animationoverhaul.animation.animator.entity;

import com.google.common.collect.Maps;
import com.trainguy9512.animationoverhaul.AnimationOverhaulMain;
import com.trainguy9512.animationoverhaul.animation.animator.entity.EntityJointAnimator;
import com.trainguy9512.animationoverhaul.animation.animator.JointAnimatorRegistry;
import com.trainguy9512.animationoverhaul.animation.data.AnimationDriverContainer;
import com.trainguy9512.animationoverhaul.animation.data.PoseSamplerStateContainer;
import com.trainguy9512.animationoverhaul.animation.pose.AnimationPose;
import com.trainguy9512.animationoverhaul.animation.pose.BakedAnimationPose;
import com.trainguy9512.animationoverhaul.animation.pose.JointSkeleton;
import net.minecraft.client.Minecraft;
import net.minecraft.client.player.LocalPlayer;
import net.minecraft.client.renderer.entity.state.PlayerRenderState;
import net.minecraft.world.entity.Entity;

import java.util.HashMap;
Expand All @@ -17,21 +19,25 @@ public class EntityJointAnimatorDispatcher {
public static final EntityJointAnimatorDispatcher INSTANCE = new EntityJointAnimatorDispatcher();

private final HashMap<UUID, AnimationDriverContainer> entityAnimationDataContainerStorage;
private final HashMap<UUID, BakedAnimationPose> entityBakedAnimationPoseStorage;
private final HashMap<UUID, PoseSamplerStateContainer> entityPoseSamplerStateContainerStorage;
private final HashMap<UUID, BakedAnimationPose> entityBakedAnimationPoseStorage;

private final AnimationDriverContainer firstPersonPlayerAnimationDriverContainer = new AnimationDriverContainer();
private PoseSamplerStateContainer firstPersonPoseSamplerStateContainer;
private BakedAnimationPose firstPersonPlayerBakedAnimationPose;

public EntityJointAnimatorDispatcher(){
this.entityAnimationDataContainerStorage = Maps.newHashMap();
this.entityBakedAnimationPoseStorage = Maps.newHashMap();
this.entityPoseSamplerStateContainerStorage = Maps.newHashMap();
}

public <T extends Entity> void tick(T entity){
public <T extends Entity> void tickThirdPersonJointAnimators(T entity){
UUID entityUUID = entity.getUUID();

@SuppressWarnings("unchecked")
EntityJointAnimator<T, ?> entityJointAnimator = (EntityJointAnimator<T, ?>) AnimationOverhaulMain.ENTITY_ANIMATORS.get(entity.getType());
JointSkeleton jointSkeleton = entityJointAnimator.getJointSkeleton();
EntityJointAnimator<T, ?> entityJointAnimator = (EntityJointAnimator<T, ?>) JointAnimatorRegistry.getThirdPersonJointAnimator(entity.getType());
JointSkeleton jointSkeleton = JointAnimatorRegistry.getThirdPersonJointSkeleton(entity.getType());

BakedAnimationPose bakedPose = this.getEntityBakedAnimationPose(entityUUID, jointSkeleton);
AnimationDriverContainer animationDriverContainer = this.getEntityAnimationDataContainer(entityUUID);
Expand All @@ -44,16 +50,48 @@ public <T extends Entity> void tick(T entity){
poseSamplerStateContainer.tick(animationDriverContainer);

// Step 3: Calculate pose
AnimationPose calculatedAnimationPose = entityJointAnimator.calculatePose(animationDriverContainer, poseSamplerStateContainer);
AnimationPose calculatedAnimationPose = entityJointAnimator.calculatePose(animationDriverContainer, poseSamplerStateContainer, jointSkeleton);
if (calculatedAnimationPose == null){
calculatedAnimationPose = AnimationPose.of(jointSkeleton);
}

// Step 4: Push the local space pose to the baked pose, and save the baked pose.
bakedPose.pushPose(calculatedAnimationPose.getConvertedToLocalSpace());
this.saveBakedPose(entityUUID, bakedPose);
}

public void tickFirstPersonJointAnimator(){
if(JointAnimatorRegistry.getFirstPersonPlayerJointAnimator() != null){
LivingEntityJointAnimator<LocalPlayer, PlayerRenderState> entityJointAnimator = JointAnimatorRegistry.getFirstPersonPlayerJointAnimator();
JointSkeleton jointSkeleton = JointAnimatorRegistry.getFirstPersonPlayerJointSkeleton();

// Initialize the pose sampler state container
if(this.firstPersonPoseSamplerStateContainer == null){
this.firstPersonPoseSamplerStateContainer = new PoseSamplerStateContainer(jointSkeleton);
}

// Initialize the baked animation pose
if(this.firstPersonPlayerBakedAnimationPose == null){
this.firstPersonPlayerBakedAnimationPose = new BakedAnimationPose(jointSkeleton);
}

LocalPlayer player = Minecraft.getInstance().player;

// Step 1: Extract animation driver data
entityJointAnimator.extractAnimationData(player, this.firstPersonPlayerAnimationDriverContainer);

// Step 2: Update pose samplers using animation driver data
this.firstPersonPoseSamplerStateContainer.tick(this.firstPersonPlayerAnimationDriverContainer);

// Step 3: Calculate pose
AnimationPose calculatedAnimationPose = entityJointAnimator.calculatePose(this.firstPersonPlayerAnimationDriverContainer, this.firstPersonPoseSamplerStateContainer, jointSkeleton);
if (calculatedAnimationPose == null){
calculatedAnimationPose = AnimationPose.of(jointSkeleton);
}

// Step 4: Push the local space pose to the baked pose, and save the baked pose.
this.firstPersonPlayerBakedAnimationPose.pushPose(calculatedAnimationPose.getConvertedToLocalSpace());
}
}

public <L extends Enum<L>> void saveBakedPose(UUID uuid, BakedAnimationPose bakedPose){
Expand Down Expand Up @@ -84,7 +122,7 @@ public <L extends Enum<L>> BakedAnimationPose getEntityBakedAnimationPose(UUID u
* @return Animation data container
*/
private AnimationDriverContainer getEntityAnimationDataContainer(UUID uuid){
return this.entityAnimationDataContainerStorage.getOrDefault(uuid, new AnimationDriverContainer());
return this.entityAnimationDataContainerStorage.computeIfAbsent(uuid, uuid1 -> new AnimationDriverContainer());
}

/**
Expand All @@ -94,4 +132,12 @@ private AnimationDriverContainer getEntityAnimationDataContainer(UUID uuid){
public boolean entityHasBakedAnimationPose(UUID uuid){
return this.entityAnimationDataContainerStorage.containsKey(uuid);
}

public BakedAnimationPose getFirstPersonPlayerBakedAnimationPose(){
return this.firstPersonPlayerBakedAnimationPose;
}

public AnimationDriverContainer getFirstPersonPlayerAnimationDriverContainer(){
return this.firstPersonPlayerAnimationDriverContainer;
}
}
Loading

0 comments on commit 941c391

Please sign in to comment.