animation flickering bugfixes
Some checks failed
studiorailgun/Renderer/pipeline/head There was a failure building this commit

This commit is contained in:
austin 2024-07-26 20:59:59 -04:00
parent 3092b70c1e
commit 8484fad7da
15 changed files with 482 additions and 284 deletions

View File

@ -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

View File

@ -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<String> getFirstPersonAnimation,
String thirdPersonAnimation,
Supplier<String> 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<String> getFirstPersonAnimation,
Supplier<String> 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<String> 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<String> getFirstPersonAnimation,
Supplier<String> 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<String> 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<String> 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<String> getFirstPersonAnimation,
Supplier<String> 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<String> getFirstPersonAnimation,
Supplier<String> 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<String> 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<String> 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<String> getFirstPersonAnimation,
Supplier<String> getThirdPersonAnimation
){
return new StateTransitionUtilItem(
stateEnum,
animPriority,
null,
getFirstPersonAnimation,
null,
getThirdPersonAnimation,
null,
null
);
}
}
}

View File

@ -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;
}

View File

@ -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<Entity> attachedEntities = AttachUtils.getChildrenList(parent);

View File

@ -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<Entity> attachedEntities = AttachUtils.getChildrenList(parent);

View File

@ -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();}
),

View File

@ -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);}
),

View File

@ -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;
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);
}
}
/**
* Gets the animation currently playing
* @return The name of the animation
*/
public String getCurrentAnimation(){
return currentAnimation;
}
/**
@ -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);
}
}

View File

@ -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:

View File

@ -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);
}
}
}

View File

@ -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;

View File

@ -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();

View File

@ -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,39 +77,73 @@ 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")){
@ -120,20 +158,14 @@ public class ImGuiEntityMacros {
}
}
//print bone values
if(ImGui.button("Print current bone values")){
for(Bone bone : actor.getBoneValues()){
LoggerInterface.loggerRenderer.DEBUG(bone.boneID);
LoggerInterface.loggerRenderer.DEBUG("" + bone.getFinalTransform());
//animation queue
if(ImGui.collapsingHeader("Animation Queue")){
PriorityQueue<ActorAnimationMask> animationQueue = actor.getAnimationQueue();
for(ActorAnimationMask mask : animationQueue){
ImGui.text(mask.getPriority() + " " + mask.getAnimationName());
}
}
//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());
@ -147,34 +179,52 @@ public class ImGuiEntityMacros {
}
}
}
//print data macros
if(ImGui.collapsingHeader("Print Data")){
//print bone values
if(ImGui.button("Print current bone values")){
for(Bone bone : actor.getBoneValues()){
LoggerInterface.loggerRenderer.DEBUG(bone.boneID);
LoggerInterface.loggerRenderer.DEBUG("" + bone.getFinalTransform());
}
}
});
actorView.setOpen(false);
Globals.renderingEngine.getImGuiPipeline().addImGuiWindow(actorView);
}
//print animation keys
if(ImGui.button("Print animation keys")){
Model model = Globals.assetManager.fetchModel(actor.getModelPath());
model.describeAllAnimations();
}
}
}
}
}
/**
* 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);
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())){
@ -215,9 +265,39 @@ public class ImGuiEntityMacros {
}
}
});
equipStateView.setOpen(false);
Globals.renderingEngine.getImGuiPipeline().addImGuiWindow(equipStateView);
}
/**
* 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);
}
}
}
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);
}
}
}
}
}
/**

View File

@ -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")){

View File

@ -169,6 +169,14 @@ public class Actor {
}
}
/**
* Gets the animation queue
* @return The animation queue
*/
public PriorityQueue<ActorAnimationMask> getAnimationQueue(){
return animationQueue;
}
void applyAnimationMasks(Model model){
// Model model = Globals.assetManager.fetchModel(modelPath);
// if(model != null){