From 8484fad7da28293ffe9067c65319b5531e2df10e Mon Sep 17 00:00:00 2001 From: austin Date: Fri, 26 Jul 2024 20:59:59 -0400 Subject: [PATCH] animation flickering bugfixes --- docs/src/progress/renderertodo.md | 2 + .../entity/btree/StateTransitionUtil.java | 315 ++++++++++------- .../entity/state/AnimationPriorities.java | 34 ++ .../entity/state/attack/ClientAttackTree.java | 7 +- .../entity/state/attack/ServerAttackTree.java | 2 - .../entity/state/block/ClientBlockTree.java | 10 +- .../entity/state/block/ServerBlockTree.java | 11 +- .../client/firstPerson/FirstPersonTree.java | 41 +-- .../entity/state/idle/ClientIdleTree.java | 3 +- .../entity/state/movement/FallTree.java | 5 +- .../entity/state/movement/JumpTree.java | 3 +- .../groundmove/ClientGroundMovementTree.java | 7 +- .../menu/debug/ImGuiEntityMacros.java | 316 +++++++++++------- .../menu/debug/ImGuiWindowMacros.java | 2 +- .../electrosphere/renderer/actor/Actor.java | 8 + 15 files changed, 482 insertions(+), 284 deletions(-) create mode 100644 src/main/java/electrosphere/entity/state/AnimationPriorities.java diff --git a/docs/src/progress/renderertodo.md b/docs/src/progress/renderertodo.md index 425a966c..6369d30d 100644 --- a/docs/src/progress/renderertodo.md +++ b/docs/src/progress/renderertodo.md @@ -455,6 +455,8 @@ Devtools for updating first person attachment rotations (07/26/2024) Viewmodel equipped item rotates inverted to bone rotation Visually block +Utility object for reducing boilerplate when writing btree transitions that just play an animation then transition +First animations flickering in first person (enforce animation priority requirement) # TODO diff --git a/src/main/java/electrosphere/entity/btree/StateTransitionUtil.java b/src/main/java/electrosphere/entity/btree/StateTransitionUtil.java index 155db3d0..a87dee7c 100644 --- a/src/main/java/electrosphere/entity/btree/StateTransitionUtil.java +++ b/src/main/java/electrosphere/entity/btree/StateTransitionUtil.java @@ -125,7 +125,6 @@ public class StateTransitionUtil { if(state.audioPath != null){ Globals.virtualAudioSourceManager.createVirtualAudioSource(state.audioPath, VirtualAudioSourceType.CREATURE, false); } - FirstPersonTree.conditionallyPlayAnimation(Globals.firstPersonEntity, firstPersonAnimation); } else { //play third person audio if(state.audioPath != null){ @@ -133,13 +132,16 @@ public class StateTransitionUtil { } } - actor.playAnimation(animationToPlay,1); + actor.playAnimation(animationToPlay,state.animPriority); actor.incrementAnimationTime(0.0001); state.startedAnimation = true; } else if(animationToPlay == null && state.onComplete != null){ state.onComplete.run(); state.startedAnimation = false; } + if(firstPersonAnimation != null){ + FirstPersonTree.conditionallyPlayAnimation(Globals.firstPersonEntity, firstPersonAnimation, state.animPriority); + } } } @@ -165,7 +167,7 @@ public class StateTransitionUtil { state.startedAnimation = false; } else if(animationToPlay != null && (!poseActor.isPlayingAnimation() || !poseActor.isPlayingAnimation(animationToPlay))){ //play animation for state - poseActor.playAnimation(animationToPlay,1); + poseActor.playAnimation(animationToPlay,state.animPriority); poseActor.incrementAnimationTime(0.0001); state.startedAnimation = true; } else if(animationToPlay == null && state.onComplete != null){ @@ -183,6 +185,9 @@ public class StateTransitionUtil { //The enum value for this state Object stateEnum; + //the priority of this animation in particular + int animPriority; + //T1he animation to play in first person String firstPersonAnimation; @@ -206,62 +211,22 @@ public class StateTransitionUtil { /** * Constructor - * @param stateEnum The enum value for this state - * @param firstPersonAnimation The animation to play in first person. If this is null, it will not play any animation in first person. - * @param thirdPersonAnimation The animation to play in third person. If this is null, it will not play any animation in third person. - * @param audioPath The audio path to play when the animation starts. If this is null, it will not play any audio. - * @param onComplete The function to fire on completion (ie to transition to the next state). If this is null, the animation and audio will be looped on completion. */ - public StateTransitionUtilItem( + private StateTransitionUtilItem( Object stateEnum, + int animPriority, String firstPersonAnimation, - String thirdPersonAnimation, - String audioPath, - Runnable onComplete - ){ - this.stateEnum = stateEnum; - this.firstPersonAnimation = firstPersonAnimation; - this.thirdPersonAnimation = thirdPersonAnimation; - this.audioPath = audioPath; - this.onComplete = onComplete; - } - - /** - * Constructor - * @param stateEnum The enum value for this state - * @param firstPersonAnimation The animation to play in first person. If this is null, it will not play any animation in first person. - * @param thirdPersonAnimation The animation to play in third person. If this is null, it will not play any animation in third person. - * @param onComplete The function to fire on completion (ie to transition to the next state). If this is null, the animation and audio will be looped on completion. - */ - public StateTransitionUtilItem( - Object stateEnum, - String firstPersonAnimation, - String thirdPersonAnimation, - Runnable onComplete - ){ - this.stateEnum = stateEnum; - this.firstPersonAnimation = firstPersonAnimation; - this.thirdPersonAnimation = thirdPersonAnimation; - this.onComplete = onComplete; - } - - /** - * Constructor - * @param stateEnum The enum value for this state - * @param firstPersonAnimation The animation to play in first person. If this is null, it will not play any animation in first person. - * @param thirdPersonAnimation The animation to play in third person. If this is null, it will not play any animation in third person. - * @param audioPath The audio path to play when the animation starts. If this is null, it will not play any audio. - * @param onComplete The function to fire on completion (ie to transition to the next state). If this is null, the animation and audio will be looped on completion. - */ - public StateTransitionUtilItem( - Object stateEnum, Supplier getFirstPersonAnimation, + String thirdPersonAnimation, Supplier getThirdPersonAnimation, String audioPath, Runnable onComplete - ){ + ){ this.stateEnum = stateEnum; + this.animPriority = animPriority; + this.firstPersonAnimation = firstPersonAnimation; this.getFirstPersonAnimation = getFirstPersonAnimation; + this.thirdPersonAnimation = thirdPersonAnimation; this.getThirdPersonAnimation = getThirdPersonAnimation; this.audioPath = audioPath; this.onComplete = onComplete; @@ -270,83 +235,195 @@ public class StateTransitionUtil { /** * Constructor * @param stateEnum The enum value for this state - * @param firstPersonAnimation The animation to play in first person. If this is null, it will not play any animation in first person. - * @param thirdPersonAnimation The animation to play in third person. If this is null, it will not play any animation in third person. - * @param onComplete The function to fire on completion (ie to transition to the next state). If this is null, the animation and audio will be looped on completion. + * @param animPriority The priority of this state's animations + * @param firstPersonAnimation The animation to play in first person. If this is null, it will not play any animation in first person + * @param getFirstPersonAnimation The supplier for a first person animation name. If it is null, it will not play any animation in first person + * @param thirdPersonAnimation The animation to play in third person. If this is null, it will not play any animation in third person + * @param getThirdPersonAnimation The supplier for a third person animation name. If it is null, it will not play any animation in the third person + * @param audioPath The path to an audio file to play on starting the animation. If null, no audio will be played + * @param onComplete !!Must transition to the next state!! Fires when the animation completes. If not supplied, animations and autio will loop */ - public StateTransitionUtilItem( + public static StateTransitionUtilItem create( Object stateEnum, + int animPriority, + String firstPersonAnimation, Supplier getFirstPersonAnimation, - Supplier getThirdPersonAnimation, - Runnable onComplete - ){ - this.stateEnum = stateEnum; - this.getFirstPersonAnimation = getFirstPersonAnimation; - this.getThirdPersonAnimation = getThirdPersonAnimation; - this.onComplete = onComplete; - } - - /** - * Constructor - * @param stateEnum The enum value for this state - * @param thirdPersonAnimation The animation to play in third person. If this is null, it will not play any animation in third person. - * @param onComplete The function to fire on completion (ie to transition to the next state). If this is null, the animation and audio will be looped on completion. - */ - public StateTransitionUtilItem( - Object stateEnum, - Supplier getThirdPersonAnimation, - Runnable onComplete - ){ - this.stateEnum = stateEnum; - this.getThirdPersonAnimation = getThirdPersonAnimation; - this.onComplete = onComplete; - } - - /** - * Constructor - * @param stateEnum The enum value for this state - * @param firstPersonAnimation The animation to play in first person. If this is null, it will not play any animation in first person. - * @param thirdPersonAnimation The animation to play in third person. If this is null, it will not play any animation in third person. - */ - public StateTransitionUtilItem( - Object stateEnum, - Supplier getFirstPersonAnimation, - Supplier getThirdPersonAnimation - ){ - this.stateEnum = stateEnum; - this.getFirstPersonAnimation = getFirstPersonAnimation; - this.getThirdPersonAnimation = getThirdPersonAnimation; - } - - /** - * Constructor - * @param stateEnum The enum value for this state - * @param thirdPersonAnimation The animation to play in third person. If this is null, it will not play any animation in third person. - */ - public StateTransitionUtilItem( - Object stateEnum, - Supplier getThirdPersonAnimation - ){ - this.stateEnum = stateEnum; - this.getThirdPersonAnimation = getThirdPersonAnimation; - } - - /** - * Constructor - * @param stateEnum The enum value for this state - * @param thirdPersonAnimation The animation to play in third person. If this is null, it will not play any animation in third person. - * @param onComplete The function to fire on completion (ie to transition to the next state). If this is null, the animation and audio will be looped on completion. - */ - public StateTransitionUtilItem( - Object stateEnum, String thirdPersonAnimation, + Supplier getThirdPersonAnimation, + String audioPath, Runnable onComplete ){ - this.stateEnum = stateEnum; - this.thirdPersonAnimation = thirdPersonAnimation; - this.onComplete = onComplete; + return new StateTransitionUtilItem( + stateEnum, + animPriority, + firstPersonAnimation, + getFirstPersonAnimation, + thirdPersonAnimation, + getThirdPersonAnimation, + audioPath, + onComplete + ); } + /** + * Constructor + * @param stateEnum The enum value for this state + * @param animPriority The priority of this state's animations + * @param firstPersonAnimation The animation to play in first person. If this is null, it will not play any animation in first person + * @param thirdPersonAnimation The animation to play in third person. If this is null, it will not play any animation in third person + * @param audioPath The path to an audio file to play on starting the animation. If null, no audio will be played + * @param onComplete !!Must transition to the next state!! Fires when the animation completes. If not supplied, animations and autio will loop + */ + public static StateTransitionUtilItem create( + Object stateEnum, + int animPriority, + String firstPersonAnimation, + String thirdPersonAnimation, + String audioPath, + Runnable onComplete + ){ + return create( + stateEnum, + animPriority, + firstPersonAnimation, + null, + thirdPersonAnimation, + null, + audioPath, + onComplete + ); + } + + /** + * Constructor + * @param stateEnum The enum value for this state + * @param animPriority The priority of this state's animations + * @param getFirstPersonAnimation The supplier for a first person animation name. If it is null, it will not play any animation in first person + * @param getThirdPersonAnimation The supplier for a third person animation name. If it is null, it will not play any animation in the third person + * @param audioPath The path to an audio file to play on starting the animation. If null, no audio will be played + * @param onComplete !!Must transition to the next state!! Fires when the animation completes. If not supplied, animations and autio will loop + */ + public static StateTransitionUtilItem create( + Object stateEnum, + int animPriority, + Supplier getFirstPersonAnimation, + Supplier getThirdPersonAnimation, + String audioPath, + Runnable onComplete + ){ + return new StateTransitionUtilItem( + stateEnum, + animPriority, + null, + getFirstPersonAnimation, + null, + getThirdPersonAnimation, + audioPath, + onComplete + ); + } + + /** + * Constructor + * @param stateEnum The enum value for this state + * @param animPriority The priority of this state's animations + * @param getFirstPersonAnimation The supplier for a first person animation name. If it is null, it will not play any animation in first person + * @param getThirdPersonAnimation The supplier for a third person animation name. If it is null, it will not play any animation in the third person + * @param onComplete !!Must transition to the next state!! Fires when the animation completes. If not supplied, animations and autio will loop + */ + public static StateTransitionUtilItem create( + Object stateEnum, + int animPriority, + Supplier getFirstPersonAnimation, + Supplier getThirdPersonAnimation, + Runnable onComplete + ){ + return new StateTransitionUtilItem( + stateEnum, + animPriority, + null, + getFirstPersonAnimation, + null, + getThirdPersonAnimation, + null, + onComplete + ); + } + + /** + * Constructor + * @param stateEnum The enum value for this state + * @param animPriority The priority of this state's animations + * @param getThirdPersonAnimation The supplier for a third person animation name. If it is null, it will not play any animation in the third person + * @param onComplete !!Must transition to the next state!! Fires when the animation completes. If not supplied, animations and autio will loop + */ + public static StateTransitionUtilItem create( + Object stateEnum, + int animPriority, + Supplier getThirdPersonAnimation, + Runnable onComplete + ){ + return new StateTransitionUtilItem( + stateEnum, + animPriority, + null, + null, + null, + getThirdPersonAnimation, + null, + onComplete + ); + } + + /** + * Constructor + * @param stateEnum The enum value for this state + * @param animPriority The priority of this state's animations + * @param getThirdPersonAnimation The supplier for a third person animation name. If it is null, it will not play any animation in the third person + */ + public static StateTransitionUtilItem create( + Object stateEnum, + int animPriority, + Supplier getThirdPersonAnimation + ){ + return new StateTransitionUtilItem( + stateEnum, + animPriority, + null, + null, + null, + getThirdPersonAnimation, + null, + null + ); + } + + /** + * Constructor + * @param stateEnum The enum value for this state + * @param animPriority The priority of this state's animations + * @param getFirstPersonAnimation The supplier for a first person animation name. If it is null, it will not play any animation in first person + * @param getThirdPersonAnimation The supplier for a third person animation name. If it is null, it will not play any animation in the third person + */ + public static StateTransitionUtilItem create( + Object stateEnum, + int animPriority, + Supplier getFirstPersonAnimation, + Supplier getThirdPersonAnimation + ){ + return new StateTransitionUtilItem( + stateEnum, + animPriority, + null, + getFirstPersonAnimation, + null, + getThirdPersonAnimation, + null, + null + ); + } + + } } diff --git a/src/main/java/electrosphere/entity/state/AnimationPriorities.java b/src/main/java/electrosphere/entity/state/AnimationPriorities.java new file mode 100644 index 00000000..498f804a --- /dev/null +++ b/src/main/java/electrosphere/entity/state/AnimationPriorities.java @@ -0,0 +1,34 @@ +package electrosphere.entity.state; + +/** + * The list of animation priorities + */ +public class AnimationPriorities { + + + // + //2 + // + public static final int ATTACK = 2; + public static final int BLOCK = 2; + + // + //4 + // + public static final int FALL = 4; + public static final int JUMP = 4; + public static final int LAND = 4; + + // + //5 + // + public static final int GROUND_MOVE = 5; + + + + // + //10 + // + public static final int IDLE = 10; + +} diff --git a/src/main/java/electrosphere/entity/state/attack/ClientAttackTree.java b/src/main/java/electrosphere/entity/state/attack/ClientAttackTree.java index 392413b0..87d5dedf 100644 --- a/src/main/java/electrosphere/entity/state/attack/ClientAttackTree.java +++ b/src/main/java/electrosphere/entity/state/attack/ClientAttackTree.java @@ -8,6 +8,7 @@ import electrosphere.entity.Entity; import electrosphere.entity.EntityDataStrings; import electrosphere.entity.EntityUtils; import electrosphere.entity.btree.BehaviorTree; +import electrosphere.entity.state.AnimationPriorities; import electrosphere.entity.state.client.firstPerson.FirstPersonTree; import electrosphere.entity.state.collidable.Impulse; import electrosphere.entity.state.equip.ClientEquipState; @@ -243,7 +244,7 @@ public class ClientAttackTree implements BehaviorTree { entityActor.playAnimation(currentMove.getWindupAnimationName(),1); entityActor.incrementAnimationTime(0.0001); } - FirstPersonTree.conditionallyPlayAnimation(Globals.firstPersonEntity, currentMove.getAnimationFirstPersonWindup().getName()); + FirstPersonTree.conditionallyPlayAnimation(Globals.firstPersonEntity, currentMove.getAnimationFirstPersonWindup().getName(), AnimationPriorities.ATTACK); } } } break; @@ -253,7 +254,7 @@ public class ClientAttackTree implements BehaviorTree { entityActor.playAnimation(currentMove.getHoldAnimationName(),1); entityActor.incrementAnimationTime(0.0001); } - FirstPersonTree.conditionallyPlayAnimation(Globals.firstPersonEntity, currentMove.getAnimationFirstPersonHold().getName()); + FirstPersonTree.conditionallyPlayAnimation(Globals.firstPersonEntity, currentMove.getAnimationFirstPersonHold().getName(), AnimationPriorities.ATTACK); } } break; case ATTACK: { @@ -262,7 +263,7 @@ public class ClientAttackTree implements BehaviorTree { entityActor.playAnimation(currentMove.getAttackAnimationName(),1); entityActor.incrementAnimationTime(0.0001); } - FirstPersonTree.conditionallyPlayAnimation(Globals.firstPersonEntity, currentMove.getAnimationFirstPersonAttack().getName()); + FirstPersonTree.conditionallyPlayAnimation(Globals.firstPersonEntity, currentMove.getAnimationFirstPersonAttack().getName(), AnimationPriorities.ATTACK); } //activate hitboxes List attachedEntities = AttachUtils.getChildrenList(parent); diff --git a/src/main/java/electrosphere/entity/state/attack/ServerAttackTree.java b/src/main/java/electrosphere/entity/state/attack/ServerAttackTree.java index d6c5caae..93e4f4ec 100644 --- a/src/main/java/electrosphere/entity/state/attack/ServerAttackTree.java +++ b/src/main/java/electrosphere/entity/state/attack/ServerAttackTree.java @@ -17,7 +17,6 @@ import electrosphere.entity.EntityUtils; import electrosphere.entity.btree.BehaviorTree; import electrosphere.entity.state.attack.ClientAttackTree.AttackTreeDriftState; import electrosphere.entity.state.attack.ClientAttackTree.AttackTreeState; -import electrosphere.entity.state.client.firstPerson.FirstPersonTree; import electrosphere.entity.state.collidable.Impulse; import electrosphere.entity.state.equip.ServerEquipState; import electrosphere.entity.state.hitbox.HitboxCollectionState; @@ -264,7 +263,6 @@ public class ServerAttackTree implements BehaviorTree { entityPoseActor.playAnimation(currentMove.getAttackAnimationName(),1); entityPoseActor.incrementAnimationTime(0.0001); } - FirstPersonTree.conditionallyPlayAnimation(Globals.firstPersonEntity, currentMove.getAnimationFirstPersonAttack().getName()); } //activate hitboxes List attachedEntities = AttachUtils.getChildrenList(parent); diff --git a/src/main/java/electrosphere/entity/state/block/ClientBlockTree.java b/src/main/java/electrosphere/entity/state/block/ClientBlockTree.java index ee9ea0dd..e07d49e3 100644 --- a/src/main/java/electrosphere/entity/state/block/ClientBlockTree.java +++ b/src/main/java/electrosphere/entity/state/block/ClientBlockTree.java @@ -7,6 +7,7 @@ import electrosphere.entity.EntityDataStrings; import electrosphere.entity.btree.BehaviorTree; import electrosphere.entity.btree.StateTransitionUtil; import electrosphere.entity.btree.StateTransitionUtil.StateTransitionUtilItem; +import electrosphere.entity.state.AnimationPriorities; import electrosphere.game.data.creature.type.block.BlockSystem; import electrosphere.net.synchronization.BehaviorTreeIdEnums; @@ -53,18 +54,21 @@ public class ClientBlockTree implements BehaviorTree { this.parent = parent; this.blockSystem = blockSystem; this.stateTransitionUtil = StateTransitionUtil.create(parent, false, new StateTransitionUtilItem[]{ - new StateTransitionUtilItem( + StateTransitionUtilItem.create( BlockState.WIND_UP, + AnimationPriorities.BLOCK, () -> {return this.blockSystem.getBlockVariant(this.currentBlockVariant).getWindUpFirstPersonAnimation();}, () -> {return this.blockSystem.getBlockVariant(this.currentBlockVariant).getWindUpAnimation();} ), - new StateTransitionUtilItem( + StateTransitionUtilItem.create( BlockState.BLOCKING, + AnimationPriorities.BLOCK, () -> {return this.blockSystem.getBlockVariant(this.currentBlockVariant).getMainFirstPersonAnimation();}, () -> {return this.blockSystem.getBlockVariant(this.currentBlockVariant).getMainAnimation();} ), - new StateTransitionUtilItem( + StateTransitionUtilItem.create( BlockState.COOLDOWN, + AnimationPriorities.BLOCK, () -> {return this.blockSystem.getBlockVariant(this.currentBlockVariant).getCooldownFirstPersonAnimation();}, () -> {return this.blockSystem.getBlockVariant(this.currentBlockVariant).getCooldownAnimation();} ), diff --git a/src/main/java/electrosphere/entity/state/block/ServerBlockTree.java b/src/main/java/electrosphere/entity/state/block/ServerBlockTree.java index 017abaac..37b2b99c 100644 --- a/src/main/java/electrosphere/entity/state/block/ServerBlockTree.java +++ b/src/main/java/electrosphere/entity/state/block/ServerBlockTree.java @@ -14,7 +14,7 @@ import electrosphere.server.datacell.utils.ServerBehaviorTreeUtils; import electrosphere.net.parser.net.message.SynchronizationMessage; import electrosphere.server.datacell.utils.DataCellSearchUtils; - +import electrosphere.entity.state.AnimationPriorities; import electrosphere.entity.state.block.ClientBlockTree.BlockState; import electrosphere.game.data.creature.type.block.BlockSystem; import electrosphere.net.synchronization.annotation.SyncedField; @@ -48,17 +48,20 @@ public class ServerBlockTree implements BehaviorTree { this.parent = parent; this.blockSystem = blockSystem; this.stateTransitionUtil = StateTransitionUtil.create(parent, true, new StateTransitionUtilItem[]{ - new StateTransitionUtilItem( + StateTransitionUtilItem.create( BlockState.WIND_UP, + AnimationPriorities.BLOCK, () -> {return this.blockSystem.getBlockVariant(this.currentBlockVariant).getWindUpAnimation();}, () -> {this.setState(BlockState.BLOCKING);} ), - new StateTransitionUtilItem( + StateTransitionUtilItem.create( BlockState.BLOCKING, + AnimationPriorities.BLOCK, () -> {return this.blockSystem.getBlockVariant(this.currentBlockVariant).getMainAnimation();} ), - new StateTransitionUtilItem( + StateTransitionUtilItem.create( BlockState.COOLDOWN, + AnimationPriorities.BLOCK, () -> {return this.blockSystem.getBlockVariant(this.currentBlockVariant).getCooldownAnimation();}, () -> {this.setState(BlockState.NOT_BLOCKING);} ), diff --git a/src/main/java/electrosphere/entity/state/client/firstPerson/FirstPersonTree.java b/src/main/java/electrosphere/entity/state/client/firstPerson/FirstPersonTree.java index 42db18fb..5bdfa7c4 100644 --- a/src/main/java/electrosphere/entity/state/client/firstPerson/FirstPersonTree.java +++ b/src/main/java/electrosphere/entity/state/client/firstPerson/FirstPersonTree.java @@ -22,22 +22,8 @@ public class FirstPersonTree implements BehaviorTree { //the amount to pull behind the camera double cameraViewDirOffsetZ; - //the animation to play currently - String currentAnimation = "Idle"; - @Override public void simulate(float deltaTime) { - if(Globals.firstPersonEntity != null){ - Actor actor = EntityUtils.getActor(Globals.firstPersonEntity); - if( - (!actor.isPlayingAnimation() || !actor.isPlayingAnimation(currentAnimation)) && - (Globals.assetManager.fetchModel(actor.getModelPath()) != null && Globals.assetManager.fetchModel(actor.getModelPath()).getAnimation(currentAnimation) != null) - - ){ - actor.playAnimation(currentAnimation,3); - actor.incrementAnimationTime(0.0001); - } - } } /** @@ -105,16 +91,17 @@ public class FirstPersonTree implements BehaviorTree { * Plays an animation if it exists * @param animationName the name of the animation */ - public void playAnimation(String animationName){ - this.currentAnimation = animationName; - } - - /** - * Gets the animation currently playing - * @return The name of the animation - */ - public String getCurrentAnimation(){ - return currentAnimation; + public void playAnimation(String animationName, int priority){ + if(Globals.firstPersonEntity != null){ + Actor actor = EntityUtils.getActor(Globals.firstPersonEntity); + if( + (!actor.isPlayingAnimation() || !actor.isPlayingAnimation(animationName)) && + (Globals.assetManager.fetchModel(actor.getModelPath()) != null && Globals.assetManager.fetchModel(actor.getModelPath()).getAnimation(animationName) != null) + ){ + actor.playAnimation(animationName,priority); + actor.incrementAnimationTime(0.0001); + } + } } /** @@ -122,9 +109,9 @@ public class FirstPersonTree implements BehaviorTree { * @param entity The entity * @param animationName the name of the animation */ - public static void conditionallyPlayAnimation(Entity entity, String animationName){ - if(entity != null && hasTree(entity)){ - getTree(entity).playAnimation(animationName); + public static void conditionallyPlayAnimation(Entity entity, String animationName, int priority){ + if(entity != null && FirstPersonTree.hasTree(entity)){ + FirstPersonTree.getTree(entity).playAnimation(animationName, priority); } } diff --git a/src/main/java/electrosphere/entity/state/idle/ClientIdleTree.java b/src/main/java/electrosphere/entity/state/idle/ClientIdleTree.java index 9c0de1d8..e39a5c30 100644 --- a/src/main/java/electrosphere/entity/state/idle/ClientIdleTree.java +++ b/src/main/java/electrosphere/entity/state/idle/ClientIdleTree.java @@ -2,6 +2,7 @@ package electrosphere.entity.state.idle; import electrosphere.net.synchronization.BehaviorTreeIdEnums; +import electrosphere.entity.state.AnimationPriorities; import electrosphere.entity.state.attack.ClientAttackTree; import electrosphere.entity.state.client.firstPerson.FirstPersonTree; import electrosphere.entity.state.movement.AirplaneMovementTree; @@ -99,8 +100,8 @@ public class ClientIdleTree implements BehaviorTree { ){ entityActor.playAnimation(idleData.getIdleAnimation(),3); entityActor.incrementAnimationTime(0.0001); - FirstPersonTree.conditionallyPlayAnimation(Globals.firstPersonEntity, idleData.getFirstPersonIdleAnimation()); } + FirstPersonTree.conditionallyPlayAnimation(Globals.firstPersonEntity, idleData.getFirstPersonIdleAnimation(), AnimationPriorities.IDLE); } break; case NOT_IDLE: diff --git a/src/main/java/electrosphere/entity/state/movement/FallTree.java b/src/main/java/electrosphere/entity/state/movement/FallTree.java index eac1af94..e3427873 100644 --- a/src/main/java/electrosphere/entity/state/movement/FallTree.java +++ b/src/main/java/electrosphere/entity/state/movement/FallTree.java @@ -5,6 +5,7 @@ import electrosphere.entity.Entity; import electrosphere.entity.EntityDataStrings; import electrosphere.entity.EntityUtils; import electrosphere.entity.btree.BehaviorTree; +import electrosphere.entity.state.AnimationPriorities; import electrosphere.entity.state.client.firstPerson.FirstPersonTree; import electrosphere.game.data.creature.type.movement.FallMovementSystem; import electrosphere.renderer.actor.Actor; @@ -51,8 +52,8 @@ public class FallTree implements BehaviorTree { ){ entityActor.playAnimation(fallMovementSystem.getAnimationFall().getName(),1); entityActor.incrementAnimationTime(0.0001); - FirstPersonTree.conditionallyPlayAnimation(Globals.firstPersonEntity, fallMovementSystem.getAnimationFirstPersonFall().getName()); } + FirstPersonTree.conditionallyPlayAnimation(Globals.firstPersonEntity, fallMovementSystem.getAnimationFirstPersonFall().getName(), AnimationPriorities.FALL); } break; case INACTIVE: @@ -88,8 +89,8 @@ public class FallTree implements BehaviorTree { ){ entityActor.playAnimation(fallMovementSystem.getAnimationLand().getName(),1); entityActor.incrementAnimationTime(0.0001); - FirstPersonTree.conditionallyPlayAnimation(Globals.firstPersonEntity, fallMovementSystem.getAnimationFirstPersonLand().getName()); } + FirstPersonTree.conditionallyPlayAnimation(Globals.firstPersonEntity, fallMovementSystem.getAnimationFirstPersonLand().getName(), AnimationPriorities.LAND); } } } diff --git a/src/main/java/electrosphere/entity/state/movement/JumpTree.java b/src/main/java/electrosphere/entity/state/movement/JumpTree.java index 514bce8b..cb78144d 100644 --- a/src/main/java/electrosphere/entity/state/movement/JumpTree.java +++ b/src/main/java/electrosphere/entity/state/movement/JumpTree.java @@ -9,6 +9,7 @@ import electrosphere.entity.Entity; import electrosphere.entity.EntityDataStrings; import electrosphere.entity.EntityUtils; import electrosphere.entity.btree.BehaviorTree; +import electrosphere.entity.state.AnimationPriorities; import electrosphere.entity.state.client.firstPerson.FirstPersonTree; import electrosphere.entity.state.gravity.GravityUtils; import electrosphere.game.data.creature.type.movement.JumpMovementSystem; @@ -62,8 +63,8 @@ public class JumpTree implements BehaviorTree { if(!entityActor.isPlayingAnimation() || !entityActor.isPlayingAnimation(jumpData.getAnimationJump().getName())){ entityActor.playAnimation(jumpData.getAnimationJump().getName(),1); entityActor.incrementAnimationTime(0.0001); - FirstPersonTree.conditionallyPlayAnimation(Globals.firstPersonEntity, jumpData.getAnimationFirstPersonJump().getName()); } + FirstPersonTree.conditionallyPlayAnimation(Globals.firstPersonEntity, jumpData.getAnimationFirstPersonJump().getName(), AnimationPriorities.JUMP); } currentFrame++; currentJumpForce = currentJumpForce * jumpFalloff; diff --git a/src/main/java/electrosphere/entity/state/movement/groundmove/ClientGroundMovementTree.java b/src/main/java/electrosphere/entity/state/movement/groundmove/ClientGroundMovementTree.java index 95ec2fae..7b0d72df 100644 --- a/src/main/java/electrosphere/entity/state/movement/groundmove/ClientGroundMovementTree.java +++ b/src/main/java/electrosphere/entity/state/movement/groundmove/ClientGroundMovementTree.java @@ -14,6 +14,7 @@ import electrosphere.entity.Entity; import electrosphere.entity.EntityDataStrings; import electrosphere.entity.EntityUtils; import electrosphere.entity.btree.BehaviorTree; +import electrosphere.entity.state.AnimationPriorities; import electrosphere.entity.state.attack.ClientAttackTree; import electrosphere.entity.state.attack.ClientAttackTree.AttackTreeState; import electrosphere.entity.state.client.firstPerson.FirstPersonTree; @@ -292,8 +293,8 @@ public class ClientGroundMovementTree implements BehaviorTree { ){ entityActor.playAnimation(animationToPlay,1); entityActor.incrementAnimationTime(0.0001); - FirstPersonTree.conditionallyPlayAnimation(Globals.firstPersonEntity, groundMovementData.getAnimationFirstPersonStartup().getName()); } + FirstPersonTree.conditionallyPlayAnimation(Globals.firstPersonEntity, groundMovementData.getAnimationFirstPersonStartup().getName(), AnimationPriorities.GROUND_MOVE); } //run startup code velocity = velocity + acceleration * (float)Globals.timekeeper.getSimFrameTime(); @@ -326,8 +327,8 @@ public class ClientGroundMovementTree implements BehaviorTree { ){ entityActor.playAnimation(animationToPlay,1); entityActor.incrementAnimationTime(0.0001); - FirstPersonTree.conditionallyPlayAnimation(Globals.firstPersonEntity, groundMovementData.getAnimationFirstPersonLoop().getName()); } + FirstPersonTree.conditionallyPlayAnimation(Globals.firstPersonEntity, groundMovementData.getAnimationFirstPersonLoop().getName(), AnimationPriorities.GROUND_MOVE); } if(velocity != maxNaturalVelocity){ velocity = maxNaturalVelocity; @@ -354,8 +355,8 @@ public class ClientGroundMovementTree implements BehaviorTree { ){ entityActor.playAnimation(animationToPlay,1); entityActor.incrementAnimationTime(0.0001); - FirstPersonTree.conditionallyPlayAnimation(Globals.firstPersonEntity, groundMovementData.getAnimationFirstPersonWindDown().getName()); } + FirstPersonTree.conditionallyPlayAnimation(Globals.firstPersonEntity, groundMovementData.getAnimationFirstPersonWindDown().getName(), AnimationPriorities.GROUND_MOVE); } //velocity stuff velocity = velocity - acceleration * (float)Globals.timekeeper.getSimFrameTime(); diff --git a/src/main/java/electrosphere/menu/debug/ImGuiEntityMacros.java b/src/main/java/electrosphere/menu/debug/ImGuiEntityMacros.java index ce24cfbb..b36c6092 100644 --- a/src/main/java/electrosphere/menu/debug/ImGuiEntityMacros.java +++ b/src/main/java/electrosphere/menu/debug/ImGuiEntityMacros.java @@ -2,12 +2,14 @@ package electrosphere.menu.debug; import java.util.LinkedList; import java.util.List; +import java.util.PriorityQueue; import org.joml.Quaterniond; import electrosphere.engine.Globals; import electrosphere.entity.Entity; import electrosphere.entity.EntityUtils; +import electrosphere.entity.state.client.firstPerson.FirstPersonTree; import electrosphere.entity.state.equip.ClientEquipState; import electrosphere.entity.types.attach.AttachUtils; import electrosphere.entity.types.creature.CreatureUtils; @@ -16,6 +18,7 @@ import electrosphere.entity.types.item.ItemUtils; import electrosphere.game.data.creature.type.equip.EquipPoint; import electrosphere.logger.LoggerInterface; import electrosphere.renderer.actor.Actor; +import electrosphere.renderer.actor.ActorAnimationMask; import electrosphere.renderer.actor.ActorMeshMask; import electrosphere.renderer.anim.AnimChannel; import electrosphere.renderer.anim.Animation; @@ -31,33 +34,34 @@ import imgui.ImGui; */ public class ImGuiEntityMacros { - //window for viewing main player entity's stats on both client and server - protected static ImGuiWindow clientEntityWindow; - private static boolean filterToCreatures = false; //filters the entity list to just creatures + //window for selecting entities to view + protected static ImGuiWindow clientEntityListWindow; + private static boolean filterToCreatures = true; //filters the entity list to just creatures - //views stats about an actor - protected static ImGuiWindow actorView; - static Entity actorViewEntity; //the entity whose actor we're viewing in the actor window + //window for viewing details about an entity + protected static ImGuiWindow clientEntityDetailWindow; + private static Entity detailViewEntity = null; - //views stats about equip state - protected static ImGuiWindow equipStateView; - static Entity equipViewEntity; //the entity whose equip state we're viewing in the equip window + //tree node values + private static boolean showActorTab = false; //show the actor tab + private static boolean showEquipStateTab = false; //actor details + private static boolean showFirstPersonTab = false; //first person tab + private static boolean showLinkedEntitiesTab = false;//show linked entities /** * Creates the windows in this file */ protected static void createClientEntityWindows(){ - createClientEntityDebugWindow(); - createActorViewDebugWindow(); - createEquipStateDebugWindow(); + createClientEntityDetailWindow(); + createClientEntitySelectionWindow(); } /** * Client scene entity view */ - protected static void createClientEntityDebugWindow(){ - clientEntityWindow = new ImGuiWindow("Client Entities"); - clientEntityWindow.setCallback(new ImGuiWindowCallback() { + protected static void createClientEntitySelectionWindow(){ + clientEntityListWindow = new ImGuiWindow("Client Entities"); + clientEntityListWindow.setCallback(new ImGuiWindowCallback() { @Override public void exec() { //audio engine details @@ -73,53 +77,111 @@ public class ImGuiEntityMacros { ImGui.beginGroup(); ImGui.pushID(entity.getId()); ImGui.text("Id: " + entity.getId() + " (" + getEntityName(entity) + ")"); - if(CreatureUtils.isCreature(entity)){ - if(EntityUtils.getActor(entity) != null){ - if(ImGui.button("Actor View")){ - actorViewEntity = entity; - actorView.setOpen(true); - } - } - if(ClientEquipState.getClientEquipState(entity) != null){ - if(ImGui.button("Client Equip State View")){ - equipViewEntity = entity; - equipStateView.setOpen(true); - } - } + if(ImGui.button("Details")){ + showEntity(entity); } ImGui.popID(); ImGui.endGroup(); } } }); - clientEntityWindow.setOpen(false); - Globals.renderingEngine.getImGuiPipeline().addImGuiWindow(clientEntityWindow); + clientEntityListWindow.setOpen(false); + Globals.renderingEngine.getImGuiPipeline().addImGuiWindow(clientEntityListWindow); + } + + /** + * View details about a client entity + */ + protected static void createClientEntityDetailWindow(){ + clientEntityDetailWindow = new ImGuiWindow("Entity Data"); + + clientEntityDetailWindow.setCallback(new ImGuiWindowCallback() { + @Override + public void exec() { + ImGui.sameLine(); + if(ImGui.treeNode("Views")){ + if(EntityUtils.getActor(detailViewEntity) != null && ImGui.checkbox("Actor Details", showActorTab)){ + showActorTab = !showActorTab; + } + if(ClientEquipState.hasEquipState(detailViewEntity) && ImGui.checkbox("Equip State", showEquipStateTab)){ + showEquipStateTab = !showEquipStateTab; + } + if(FirstPersonTree.hasTree(detailViewEntity) && ImGui.checkbox("First Person", showFirstPersonTab)){ + showFirstPersonTab = !showFirstPersonTab; + } + if( + (AttachUtils.hasChildren(detailViewEntity) || AttachUtils.getParent(detailViewEntity) != null || detailViewEntity == Globals.firstPersonEntity || detailViewEntity == Globals.playerEntity) && + ImGui.checkbox("Linked entities`", showLinkedEntitiesTab) + ){ + showLinkedEntitiesTab = !showLinkedEntitiesTab; + } + ImGui.treePop(); + } + ImGui.nextColumn(); + drawActorView(); + drawEquipState(); + drawFirstPersonView(); + drawLinkedEntities(); + } + }); + clientEntityDetailWindow.setOpen(false); + Globals.renderingEngine.getImGuiPipeline().addImGuiWindow(clientEntityDetailWindow); + } + + /** + * Shows the entity window for a specific entity + * @param entity The entity + */ + protected static void showEntity(Entity entity){ + detailViewEntity = entity; + clientEntityDetailWindow.setOpen(true); } /** * Client scene entity view */ - protected static void createActorViewDebugWindow(){ - actorView = new ImGuiWindow("Actor View"); - actorView.setCallback(new ImGuiWindowCallback() { - @Override - public void exec() { - if(actorViewEntity != null && EntityUtils.getActor(actorViewEntity) != null){ - Actor actor = EntityUtils.getActor(actorViewEntity); + protected static void drawActorView(){ + if(showActorTab && ImGui.collapsingHeader("Actor Details")){ + if(detailViewEntity != null && EntityUtils.getActor(detailViewEntity) != null){ + Actor actor = EntityUtils.getActor(detailViewEntity); + + //mesh mask + if(ImGui.collapsingHeader("Mesh Mask")){ + ActorMeshMask meshMask = actor.getMeshMask(); + ImGui.text("To Draw Meshes:"); + for(Mesh mesh : meshMask.getToDrawMeshes()){ + ImGui.text(mesh.getMeshName()); + } + ImGui.text("Blocked Meshes:"); + for(String blocked : meshMask.getBlockedMeshes()){ + ImGui.text(blocked); + } + } - //mesh mask - if(ImGui.collapsingHeader("Mesh Mask")){ - ActorMeshMask meshMask = actor.getMeshMask(); - ImGui.text("To Draw Meshes:"); - for(Mesh mesh : meshMask.getToDrawMeshes()){ - ImGui.text(mesh.getMeshName()); - } - ImGui.text("Blocked Meshes:"); - for(String blocked : meshMask.getBlockedMeshes()){ - ImGui.text(blocked); + //animation queue + if(ImGui.collapsingHeader("Animation Queue")){ + PriorityQueue animationQueue = actor.getAnimationQueue(); + for(ActorAnimationMask mask : animationQueue){ + ImGui.text(mask.getPriority() + " " + mask.getAnimationName()); + } + } + + //Browsable list of all animations with their data + if(ImGui.collapsingHeader("Animation Channel Data")){ + Model model = Globals.assetManager.fetchModel(actor.getModelPath()); + for(Animation animation : model.getAnimations()){ + ImGui.text(" - " + animation.name); + for(AnimChannel channel : animation.channels){ + ImGui.text("=" + channel.getNodeID() + "="); + ImGui.text("" + channel.getCurrentPosition()); + ImGui.text("" + channel.getCurrentRotation()); + ImGui.text("" + channel.getCurrentScale()); } } + } + //print data macros + if(ImGui.collapsingHeader("Print Data")){ //print bone values if(ImGui.button("Print current bone values")){ for(Bone bone : actor.getBoneValues()){ @@ -127,97 +189,115 @@ public class ImGuiEntityMacros { LoggerInterface.loggerRenderer.DEBUG("" + bone.getFinalTransform()); } } - + //print animation keys if(ImGui.button("Print animation keys")){ Model model = Globals.assetManager.fetchModel(actor.getModelPath()); model.describeAllAnimations(); } - - //Browsable list of all animations with their data - if(ImGui.collapsingHeader("Animation Channel Data")){ - Model model = Globals.assetManager.fetchModel(actor.getModelPath()); - for(Animation animation : model.getAnimations()){ - ImGui.text(" - " + animation.name); - for(AnimChannel channel : animation.channels){ - ImGui.text("=" + channel.getNodeID() + "="); - ImGui.text("" + channel.getCurrentPosition()); - ImGui.text("" + channel.getCurrentRotation()); - ImGui.text("" + channel.getCurrentScale()); - } - } - } } } - }); - actorView.setOpen(false); - Globals.renderingEngine.getImGuiPipeline().addImGuiWindow(actorView); + } } + /** + * First person data + */ + protected static void drawFirstPersonView(){ + if(showFirstPersonTab && ImGui.collapsingHeader("First Person Tree")){ + FirstPersonTree firstPersonTree = FirstPersonTree.getTree(detailViewEntity); + } + } + + + //stores the edited rotation values + private static float[] rotationValuesFirstPerson = new float[]{ + 0,0,0 + }; + private static float[] rotationValuesThirdPerson = new float[]{ + 0,0,0 + }; /** * Client scene equip state view */ - protected static void createEquipStateDebugWindow(){ - equipStateView = new ImGuiWindow("Client Equip State View"); - equipStateView.setCallback(new ImGuiWindowCallback() { - - //stores the edited rotation values - float[] rotationValuesFirstPerson = new float[]{ - 0,0,0 - }; - float[] rotationValuesThirdPerson = new float[]{ - 0,0,0 - }; - - @Override - public void exec() { - if(equipViewEntity != null && ClientEquipState.getClientEquipState(equipViewEntity) != null){ - ClientEquipState clientEquipState = ClientEquipState.getClientEquipState(equipViewEntity); - - if(ImGui.collapsingHeader("All Equip Points")){ - for(EquipPoint point : clientEquipState.getAllEquipPoints()){ - if(ImGui.collapsingHeader(point.getEquipPointId())){ - ImGui.text("Has item equipped: " + (clientEquipState.getEquippedItemAtPoint(point.getEquipPointId()) != null)); - ImGui.text("Bone (Third Person): " + point.getBone()); - ImGui.text("Bone (First Person): " + point.getFirstPersonBone()); - ImGui.text("[Third Person] Rotation: " + AttachUtils.getEquipPointRotationOffset(point.getOffsetRotationThirdPerson())); - if(ImGui.sliderFloat3("[Third Person] Rotation (In Euler along x,y,z)", rotationValuesThirdPerson, 0, (float)(Math.PI * 2))){ - Quaterniond rotation = new Quaterniond().rotateXYZ(rotationValuesThirdPerson[0], rotationValuesThirdPerson[1], rotationValuesThirdPerson[2]); - List newValues = new LinkedList(); - newValues.add((float)rotation.x); - newValues.add((float)rotation.y); - newValues.add((float)rotation.z); - newValues.add((float)rotation.w); - point.setOffsetRotationThirdPerson(newValues); - Entity equippedEntity = clientEquipState.getEquippedItemAtPoint(point.getEquipPointId()); - if(equippedEntity != null){ - AttachUtils.setRotationOffset(equippedEntity, AttachUtils.getEquipPointRotationOffset(point.getOffsetRotationThirdPerson())); - } + protected static void drawEquipState(){ + if(showEquipStateTab && ImGui.collapsingHeader("Equip State Details")){ + if(detailViewEntity != null && ClientEquipState.getClientEquipState(detailViewEntity) != null){ + ClientEquipState clientEquipState = ClientEquipState.getClientEquipState(detailViewEntity); + if(ImGui.collapsingHeader("All Equip Points")){ + for(EquipPoint point : clientEquipState.getAllEquipPoints()){ + if(ImGui.collapsingHeader(point.getEquipPointId())){ + ImGui.text("Has item equipped: " + (clientEquipState.getEquippedItemAtPoint(point.getEquipPointId()) != null)); + ImGui.text("Bone (Third Person): " + point.getBone()); + ImGui.text("Bone (First Person): " + point.getFirstPersonBone()); + ImGui.text("[Third Person] Rotation: " + AttachUtils.getEquipPointRotationOffset(point.getOffsetRotationThirdPerson())); + if(ImGui.sliderFloat3("[Third Person] Rotation (In Euler along x,y,z)", rotationValuesThirdPerson, 0, (float)(Math.PI * 2))){ + Quaterniond rotation = new Quaterniond().rotateXYZ(rotationValuesThirdPerson[0], rotationValuesThirdPerson[1], rotationValuesThirdPerson[2]); + List newValues = new LinkedList(); + newValues.add((float)rotation.x); + newValues.add((float)rotation.y); + newValues.add((float)rotation.z); + newValues.add((float)rotation.w); + point.setOffsetRotationThirdPerson(newValues); + Entity equippedEntity = clientEquipState.getEquippedItemAtPoint(point.getEquipPointId()); + if(equippedEntity != null){ + AttachUtils.setRotationOffset(equippedEntity, AttachUtils.getEquipPointRotationOffset(point.getOffsetRotationThirdPerson())); } - ImGui.text("[First Person] Rotation: " + AttachUtils.getEquipPointRotationOffset(point.getOffsetRotationFirstPerson())); - if(ImGui.sliderFloat3("[First Person] Rotation (In Euler along x,y,z)", rotationValuesFirstPerson, 0, (float)(Math.PI * 2))){ - Quaterniond rotation = new Quaterniond().rotateXYZ(rotationValuesFirstPerson[0], rotationValuesFirstPerson[1], rotationValuesFirstPerson[2]); - List newValues = new LinkedList(); - newValues.add((float)rotation.x); - newValues.add((float)rotation.y); - newValues.add((float)rotation.z); - newValues.add((float)rotation.w); - point.setOffsetRotationFirstPerson(newValues); - Entity equippedEntity = clientEquipState.getEquippedItemAtPoint(point.getEquipPointId()); - if(equippedEntity != null){ - AttachUtils.setRotationOffset(equippedEntity, AttachUtils.getEquipPointRotationOffset(point.getOffsetRotationFirstPerson())); - } + } + ImGui.text("[First Person] Rotation: " + AttachUtils.getEquipPointRotationOffset(point.getOffsetRotationFirstPerson())); + if(ImGui.sliderFloat3("[First Person] Rotation (In Euler along x,y,z)", rotationValuesFirstPerson, 0, (float)(Math.PI * 2))){ + Quaterniond rotation = new Quaterniond().rotateXYZ(rotationValuesFirstPerson[0], rotationValuesFirstPerson[1], rotationValuesFirstPerson[2]); + List newValues = new LinkedList(); + newValues.add((float)rotation.x); + newValues.add((float)rotation.y); + newValues.add((float)rotation.z); + newValues.add((float)rotation.w); + point.setOffsetRotationFirstPerson(newValues); + Entity equippedEntity = clientEquipState.getEquippedItemAtPoint(point.getEquipPointId()); + if(equippedEntity != null){ + AttachUtils.setRotationOffset(equippedEntity, AttachUtils.getEquipPointRotationOffset(point.getOffsetRotationFirstPerson())); } } } } - + } + + } + } + } + + /** + * Client scene equip state view + */ + protected static void drawLinkedEntities(){ + if(showLinkedEntitiesTab && ImGui.collapsingHeader("Linked entities")){ + if(detailViewEntity == Globals.playerEntity && ImGui.button("View Model")){ + showEntity(Globals.firstPersonEntity); + } + if(detailViewEntity == Globals.firstPersonEntity && ImGui.button("3rd Person Model")){ + showEntity(Globals.playerEntity); + } + if(AttachUtils.getParent(detailViewEntity) != null && ImGui.button("Parent")){ + showEntity(AttachUtils.getParent(detailViewEntity)); + } + if(AttachUtils.hasChildren(detailViewEntity) && ImGui.collapsingHeader("Children")){ + for(Entity child : AttachUtils.getChildrenList(detailViewEntity)){ + if(ImGui.button("Child " + child.getId())){ + showEntity(child); + } } } - }); - equipStateView.setOpen(false); - Globals.renderingEngine.getImGuiPipeline().addImGuiWindow(equipStateView); + if(ClientEquipState.hasEquipState(detailViewEntity) && ImGui.collapsingHeader("Equipped")){ + ClientEquipState clientEquipState = ClientEquipState.getClientEquipState(detailViewEntity); + for(String equippedPoint : clientEquipState.getEquippedPoints()){ + Entity entity = clientEquipState.getEquippedItemAtPoint(equippedPoint); + if(ImGui.button("Slot: " + equippedPoint)){ + showEntity(entity); + } + } + } + } } /** diff --git a/src/main/java/electrosphere/menu/debug/ImGuiWindowMacros.java b/src/main/java/electrosphere/menu/debug/ImGuiWindowMacros.java index 55a9ee09..344f8748 100644 --- a/src/main/java/electrosphere/menu/debug/ImGuiWindowMacros.java +++ b/src/main/java/electrosphere/menu/debug/ImGuiWindowMacros.java @@ -277,7 +277,7 @@ public class ImGuiWindowMacros { } //client entity debug if(ImGui.button("Client Entity Debug")){ - ImGuiEntityMacros.clientEntityWindow.setOpen(true); + ImGuiEntityMacros.clientEntityListWindow.setOpen(true); } //controls state debug if(ImGui.button("Control State Debug")){ diff --git a/src/main/java/electrosphere/renderer/actor/Actor.java b/src/main/java/electrosphere/renderer/actor/Actor.java index 4086d291..8cf38f73 100644 --- a/src/main/java/electrosphere/renderer/actor/Actor.java +++ b/src/main/java/electrosphere/renderer/actor/Actor.java @@ -169,6 +169,14 @@ public class Actor { } } + /** + * Gets the animation queue + * @return The animation queue + */ + public PriorityQueue getAnimationQueue(){ + return animationQueue; + } + void applyAnimationMasks(Model model){ // Model model = Globals.assetManager.fetchModel(modelPath); // if(model != null){