refactor animation logic into dedicated class
Some checks failed
studiorailgun/Renderer/pipeline/head There was a failure building this commit
Some checks failed
studiorailgun/Renderer/pipeline/head There was a failure building this commit
This commit is contained in:
parent
4f663a322c
commit
f7d8072122
@ -2060,6 +2060,7 @@ Code cleanup
|
||||
More tests
|
||||
Move actor masks into dedicated package
|
||||
Actor code cleanup
|
||||
Refactor animation logic into dedicated actor class
|
||||
|
||||
|
||||
|
||||
|
||||
@ -76,8 +76,8 @@ public class ClientSimulation {
|
||||
if(currentActor.getLodLevel() == Actor.LOD_LEVEL_STATIC){
|
||||
continue;
|
||||
}
|
||||
if(currentActor.isPlayingAnimation()){
|
||||
currentActor.incrementAnimationTime((float)Globals.engineState.timekeeper.getSimFrameTime());
|
||||
if(currentActor.getAnimationData().isPlayingAnimation()){
|
||||
currentActor.getAnimationData().incrementAnimationTime((float)Globals.engineState.timekeeper.getSimFrameTime());
|
||||
}
|
||||
}
|
||||
Globals.profiler.endCpuSample();
|
||||
|
||||
@ -97,7 +97,7 @@ public class CharacterCustomizer {
|
||||
sliderName.setMinWidth(200);
|
||||
//add a slider
|
||||
Slider boneSlider = Slider.createSlider((ValueChangeEvent event) -> {
|
||||
if(characterActor.getStaticMorph() != null){
|
||||
if(characterActor.getAnimationData().getStaticMorph() != null){
|
||||
staticMorph.updateValue(attribute.getSubtype(), attribute.getPrimaryBone(), event.getAsFloat());
|
||||
if(attribute.getMirrorBone() != null){
|
||||
staticMorph.updateValue(attribute.getSubtype(), attribute.getMirrorBone(), event.getAsFloat());
|
||||
@ -167,7 +167,7 @@ public class CharacterCustomizer {
|
||||
}
|
||||
}
|
||||
//finally set static morph
|
||||
characterActor.setActorStaticMorph(staticMorph);
|
||||
characterActor.getAnimationData().setActorStaticMorph(staticMorph);
|
||||
|
||||
//character create button
|
||||
Div createButtonContainer = Div.createDiv();
|
||||
|
||||
@ -75,7 +75,7 @@ public class ImGuiEntityActorTab {
|
||||
|
||||
//animation queue
|
||||
if(ImGui.collapsingHeader("Animation Queue")){
|
||||
Set<ActorAnimationMaskEntry> animationQueue = actor.getAnimationQueue();
|
||||
Set<ActorAnimationMaskEntry> animationQueue = actor.getAnimationData().getAnimationQueue();
|
||||
for(ActorAnimationMaskEntry mask : animationQueue){
|
||||
ImGui.text(mask.getAnimationName() + " - " + mask.getPriority());
|
||||
ImGui.text(mask.getDuration() + " " + mask.getTime());
|
||||
@ -84,10 +84,10 @@ public class ImGuiEntityActorTab {
|
||||
|
||||
//bone values
|
||||
if(ImGui.collapsingHeader("Bone Values")){
|
||||
for(Bone bone : actor.getBoneValues()){
|
||||
for(Bone bone : actor.getAnimationData().getBoneValues()){
|
||||
ImGui.text(bone.boneID);
|
||||
ImGui.text("Position: " + actor.getBonePosition(bone.boneID));
|
||||
ImGui.text("Rotation: " + actor.getBoneRotation(bone.boneID));
|
||||
ImGui.text("Position: " + actor.getAnimationData().getBonePosition(bone.boneID));
|
||||
ImGui.text("Rotation: " + actor.getAnimationData().getBoneRotation(bone.boneID));
|
||||
ImGui.text(bone.getFinalTransform() + "");
|
||||
}
|
||||
}
|
||||
@ -104,7 +104,7 @@ public class ImGuiEntityActorTab {
|
||||
for(Animation animation : model.getAnimations()){
|
||||
if(ImGui.collapsingHeader(animation.name)){
|
||||
if(ImGui.button("Play")){
|
||||
actor.playAnimation(animation.name, AnimationPriorities.getValue(AnimationPriorities.MODIFIER_MAX));
|
||||
actor.getAnimationData().playAnimation(animation.name, AnimationPriorities.getValue(AnimationPriorities.MODIFIER_MAX));
|
||||
}
|
||||
for(AnimChannel channel : animation.channels){
|
||||
ImGui.pushID(channel.getNodeID());
|
||||
@ -131,7 +131,7 @@ public class ImGuiEntityActorTab {
|
||||
if(ImGui.collapsingHeader("Print Data")){
|
||||
//print bone values
|
||||
if(ImGui.button("Print current bone values")){
|
||||
for(Bone bone : actor.getBoneValues()){
|
||||
for(Bone bone : actor.getAnimationData().getBoneValues()){
|
||||
LoggerInterface.loggerRenderer.DEBUG(bone.boneID);
|
||||
LoggerInterface.loggerRenderer.DEBUG("" + bone.getFinalTransform());
|
||||
}
|
||||
|
||||
@ -362,7 +362,7 @@ public class MenuGeneratorsInGame {
|
||||
|
||||
Entity playerEntity = Globals.clientState.playerEntity;
|
||||
Actor playerActor = EntityUtils.getActor(playerEntity);
|
||||
ActorStaticMorph staticMorph = playerActor.getStaticMorph();
|
||||
ActorStaticMorph staticMorph = playerActor.getAnimationData().getStaticMorph();
|
||||
CreatureData playeCreatureType = Globals.gameConfigCurrent.getCreatureTypeLoader().getType(CreatureUtils.getType(playerEntity));
|
||||
int offset = 0;
|
||||
for(VisualAttribute attribute : playeCreatureType.getVisualAttributes()){
|
||||
|
||||
@ -138,11 +138,11 @@ public class StateTransitionUtil {
|
||||
//
|
||||
//Play main animation
|
||||
//
|
||||
if(!actor.isPlayingAnimation() && state.onComplete != null && state.startedAnimation == true){
|
||||
if(!actor.getAnimationData().isPlayingAnimation() && state.onComplete != null && state.startedAnimation == true){
|
||||
//state transition if this isn't set to loop
|
||||
state.onComplete.run();
|
||||
state.startedAnimation = false;
|
||||
} else if(!actor.isPlayingAnimation() || !actor.isPlayingAnimation(animation)){
|
||||
} else if(!actor.getAnimationData().isPlayingAnimation() || !actor.getAnimationData().isPlayingAnimation(animation)){
|
||||
|
||||
//
|
||||
//if it isn't looping, only play on first go around
|
||||
@ -167,10 +167,10 @@ public class StateTransitionUtil {
|
||||
//
|
||||
//play animation
|
||||
if(animation != null){
|
||||
actor.playAnimation(animation,true);
|
||||
actor.getAnimationData().playAnimation(animation,true);
|
||||
shouldPlayFirstPerson = true;
|
||||
}
|
||||
actor.incrementAnimationTime(animationOffset);
|
||||
actor.getAnimationData().incrementAnimationTime(animationOffset);
|
||||
}
|
||||
state.startedAnimation = true;
|
||||
} else if(state.animation == null && state.onComplete != null){
|
||||
@ -272,8 +272,8 @@ public class StateTransitionUtil {
|
||||
//
|
||||
//Interrupt main animation
|
||||
//
|
||||
if(animation != null && actor.isPlayingAnimation() && actor.isPlayingAnimation(animation)){
|
||||
actor.interruptAnimation(animation, true);
|
||||
if(animation != null && actor.getAnimationData().isPlayingAnimation() && actor.getAnimationData().isPlayingAnimation(animation)){
|
||||
actor.getAnimationData().interruptAnimation(animation, true);
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
@ -208,8 +208,8 @@ public class AttachUtils {
|
||||
child,
|
||||
new Vector3d(offset),
|
||||
new Quaterniond(AttachUtils.getRotationOffset(child)),
|
||||
new Vector3d(parentActor.getBonePosition(targetBone)),
|
||||
new Quaterniond(parentActor.getBoneRotation(targetBone)),
|
||||
new Vector3d(parentActor.getAnimationData().getBonePosition(targetBone)),
|
||||
new Quaterniond(parentActor.getAnimationData().getBoneRotation(targetBone)),
|
||||
new Vector3d(EntityUtils.getPosition(parent)),
|
||||
new Quaterniond(EntityUtils.getRotation(parent)),
|
||||
new Vector3d(EntityUtils.getScale(parent))
|
||||
|
||||
@ -564,11 +564,11 @@ public class ClientAttackTree implements BehaviorTree {
|
||||
Actor actor = EntityUtils.getActor(parent);
|
||||
if(this.currentMove != null && this.currentMove.getHitstun() != null){
|
||||
String animName = this.currentMove.getAttackState().getAnimation().getNameThirdPerson();
|
||||
actor.setFreezeFrames(animName, this.currentMove.getHitstun());
|
||||
actor.getAnimationData().setFreezeFrames(animName, this.currentMove.getHitstun());
|
||||
if(parent == Globals.clientState.playerEntity && !Globals.controlHandler.cameraIsThirdPerson()){
|
||||
Actor viewmodelActor = EntityUtils.getActor(Globals.clientState.firstPersonEntity);
|
||||
animName = this.currentMove.getAttackState().getAnimation().getNameFirstPerson();
|
||||
viewmodelActor.setFreezeFrames(animName, this.currentMove.getHitstun());
|
||||
viewmodelActor.getAnimationData().setFreezeFrames(animName, this.currentMove.getHitstun());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -402,7 +402,7 @@ public class ServerAttackTree implements BehaviorTree {
|
||||
if(targetBone != null){
|
||||
Actor parentActor = EntityUtils.getActor(parent);
|
||||
//transform bone space
|
||||
spawnPosition = new Vector3d(parentActor.getBonePosition(targetBone));
|
||||
spawnPosition = new Vector3d(parentActor.getAnimationData().getBonePosition(targetBone));
|
||||
spawnPosition = spawnPosition.mul(((Vector3f)EntityUtils.getScale(parent)));
|
||||
Quaterniond rotation = EntityUtils.getRotation(parent);
|
||||
spawnPosition = spawnPosition.rotate(new Quaterniond(rotation.x,rotation.y,rotation.z,rotation.w));
|
||||
@ -414,7 +414,7 @@ public class ServerAttackTree implements BehaviorTree {
|
||||
// Quaternionf rotation = parentActor.getBoneRotation(targetBone);
|
||||
// EntityUtils.getRotation(currentEntity).set(rotation).normalize();
|
||||
// Vector3d facingAngle = CreatureUtils.getFacingVector(parent);
|
||||
arrowRotation = parentActor.getBoneRotation(targetBone);
|
||||
arrowRotation = parentActor.getAnimationData().getBoneRotation(targetBone);
|
||||
// EntityUtils.getRotation(currentEntity).rotationTo(MathUtils.ORIGIN_VECTORF, new Vector3f((float)facingAngle.x,(float)facingAngle.y,(float)facingAngle.z)).mul(parentActor.getBoneRotation(targetBone)).normalize();
|
||||
}
|
||||
Vector3f initialVector = new Vector3f((float)movementVector.x,(float)movementVector.y,(float)movementVector.z).normalize();
|
||||
|
||||
@ -106,11 +106,11 @@ public class FirstPersonTree implements BehaviorTree {
|
||||
if(Globals.clientState.firstPersonEntity != null){
|
||||
Actor actor = EntityUtils.getActor(Globals.clientState.firstPersonEntity);
|
||||
if(
|
||||
(!actor.isPlayingAnimation() || !actor.isPlayingAnimation(animationName)) &&
|
||||
(!actor.getAnimationData().isPlayingAnimation() || !actor.getAnimationData().isPlayingAnimation(animationName)) &&
|
||||
(Globals.assetManager.fetchModel(actor.getBaseModelPath()) != null && Globals.assetManager.fetchModel(actor.getBaseModelPath()).getAnimation(animationName) != null)
|
||||
){
|
||||
actor.playAnimation(animationName,priority);
|
||||
actor.incrementAnimationTime(offset);
|
||||
actor.getAnimationData().playAnimation(animationName,priority);
|
||||
actor.getAnimationData().incrementAnimationTime(offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -132,11 +132,11 @@ public class FirstPersonTree implements BehaviorTree {
|
||||
if(Globals.clientState.firstPersonEntity != null){
|
||||
Actor actor = EntityUtils.getActor(Globals.clientState.firstPersonEntity);
|
||||
if(
|
||||
(!actor.isPlayingAnimation() || !actor.isPlayingAnimation(animation.getNameFirstPerson())) &&
|
||||
(!actor.getAnimationData().isPlayingAnimation() || !actor.getAnimationData().isPlayingAnimation(animation.getNameFirstPerson())) &&
|
||||
(Globals.assetManager.fetchModel(actor.getBaseModelPath()) != null && Globals.assetManager.fetchModel(actor.getBaseModelPath()).getAnimation(animation.getNameFirstPerson()) != null)
|
||||
){
|
||||
actor.playAnimation(animation, false);
|
||||
actor.incrementAnimationTime(offset);
|
||||
actor.getAnimationData().playAnimation(animation, false);
|
||||
actor.getAnimationData().incrementAnimationTime(offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -149,10 +149,10 @@ public class FirstPersonTree implements BehaviorTree {
|
||||
if(Globals.clientState.firstPersonEntity != null){
|
||||
Actor actor = EntityUtils.getActor(Globals.clientState.firstPersonEntity);
|
||||
if(
|
||||
(actor.isPlayingAnimation() || actor.isPlayingAnimation(animation.getNameFirstPerson())) &&
|
||||
(actor.getAnimationData().isPlayingAnimation() || actor.getAnimationData().isPlayingAnimation(animation.getNameFirstPerson())) &&
|
||||
(Globals.assetManager.fetchModel(actor.getBaseModelPath()) != null && Globals.assetManager.fetchModel(actor.getBaseModelPath()).getAnimation(animation.getNameFirstPerson()) != null)
|
||||
){
|
||||
actor.interruptAnimation(animation, false);
|
||||
actor.getAnimationData().interruptAnimation(animation, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -361,11 +361,11 @@ public class ClientEquipState implements BehaviorTree {
|
||||
if(point.getEquippedAnimation() != null){
|
||||
TreeDataAnimation animation = point.getEquippedAnimation();
|
||||
//play third person
|
||||
if(thirdPersonActor.isPlayingAnimation() && thirdPersonActor.isPlayingAnimation(animation)){
|
||||
if(thirdPersonActor.getAnimationData().isPlayingAnimation() && thirdPersonActor.getAnimationData().isPlayingAnimation(animation)){
|
||||
if(animation != null){
|
||||
thirdPersonActor.interruptAnimation(animation,true);
|
||||
thirdPersonActor.getAnimationData().interruptAnimation(animation,true);
|
||||
}
|
||||
thirdPersonActor.incrementAnimationTime(0.0001);
|
||||
thirdPersonActor.getAnimationData().incrementAnimationTime(0.0001);
|
||||
}
|
||||
|
||||
//play first person
|
||||
@ -451,11 +451,11 @@ public class ClientEquipState implements BehaviorTree {
|
||||
if(this.hasEquippedAtPoint(point.getEquipPointId()) && point.getEquippedAnimation() != null){
|
||||
TreeDataAnimation animation = point.getEquippedAnimation();
|
||||
//play third person
|
||||
if(!thirdPersonActor.isPlayingAnimation() || !thirdPersonActor.isPlayingAnimation(animation)){
|
||||
if(!thirdPersonActor.getAnimationData().isPlayingAnimation() || !thirdPersonActor.getAnimationData().isPlayingAnimation(animation)){
|
||||
if(animation != null){
|
||||
thirdPersonActor.playAnimation(animation,true);
|
||||
thirdPersonActor.getAnimationData().playAnimation(animation,true);
|
||||
}
|
||||
thirdPersonActor.incrementAnimationTime(0.0001);
|
||||
thirdPersonActor.getAnimationData().incrementAnimationTime(0.0001);
|
||||
}
|
||||
|
||||
//play first person
|
||||
|
||||
@ -256,11 +256,11 @@ public class ClientToolbarState implements BehaviorTree {
|
||||
if(targetPoint.getEquippedAnimation() != null){
|
||||
TreeDataAnimation animation = targetPoint.getEquippedAnimation();
|
||||
//play third person
|
||||
if(thirdPersonActor.isPlayingAnimation() && thirdPersonActor.isPlayingAnimation(animation)){
|
||||
if(thirdPersonActor.getAnimationData().isPlayingAnimation() && thirdPersonActor.getAnimationData().isPlayingAnimation(animation)){
|
||||
if(animation != null){
|
||||
thirdPersonActor.interruptAnimation(animation,true);
|
||||
thirdPersonActor.getAnimationData().interruptAnimation(animation,true);
|
||||
}
|
||||
thirdPersonActor.incrementAnimationTime(0.0001);
|
||||
thirdPersonActor.getAnimationData().incrementAnimationTime(0.0001);
|
||||
}
|
||||
|
||||
//play first person
|
||||
|
||||
@ -339,8 +339,8 @@ public class HitboxCollectionState {
|
||||
}
|
||||
PhysicsUtils.setRigidBodyTransform(collisionEngine, entityPosition, new Quaterniond(), body);
|
||||
for(String boneName : this.boneHitboxMap.keySet()){
|
||||
if(EntityUtils.getActor(parent).containsBone(boneName)){
|
||||
Vector3d bonePosition = EntityUtils.getActor(parent).getBonePosition(boneName);
|
||||
if(EntityUtils.getActor(parent).getAnimationData().containsBone(boneName)){
|
||||
Vector3d bonePosition = EntityUtils.getActor(parent).getAnimationData().getBonePosition(boneName);
|
||||
for(HitboxState state : this.boneHitboxMap.get(boneName)){
|
||||
DGeom geom = this.stateGeomMap.get(state);
|
||||
HitboxState shapeStatus = this.geomStateMap.get(geom);
|
||||
|
||||
@ -78,15 +78,15 @@ public class ClientIdleTree implements BehaviorTree {
|
||||
if(entityActor != null){
|
||||
if(
|
||||
idleData != null &&
|
||||
(!entityActor.isPlayingAnimation() || !entityActor.isPlayingAnimation(idleData.getAnimation())) &&
|
||||
(!entityActor.getAnimationData().isPlayingAnimation() || !entityActor.getAnimationData().isPlayingAnimation(idleData.getAnimation())) &&
|
||||
(
|
||||
Globals.assetManager.fetchModel(entityActor.getBaseModelPath()) != null &&
|
||||
Globals.assetManager.fetchModel(entityActor.getBaseModelPath()).getAnimation(idleData.getAnimation().getNameThirdPerson()) != null
|
||||
)
|
||||
|
||||
){
|
||||
entityActor.playAnimation(idleData.getAnimation(),true);
|
||||
entityActor.incrementAnimationTime(0.0001);
|
||||
entityActor.getAnimationData().playAnimation(idleData.getAnimation(),true);
|
||||
entityActor.getAnimationData().incrementAnimationTime(0.0001);
|
||||
}
|
||||
if(idleData != null){
|
||||
FirstPersonTree.conditionallyPlayAnimation(parent, idleData.getAnimation());
|
||||
|
||||
@ -120,7 +120,7 @@ public class ClientFallTree implements BehaviorTree {
|
||||
boolean isPlayingJump = false;
|
||||
Actor entityActor = EntityUtils.getActor(parent);
|
||||
if(entityActor != null && ClientJumpTree.getClientJumpTree(parent) != null){
|
||||
isPlayingJump = entityActor.isPlayingAnimation(ClientJumpTree.getClientJumpTree(parent).getJumpData().getAnimationJump());
|
||||
isPlayingJump = entityActor.getAnimationData().isPlayingAnimation(ClientJumpTree.getClientJumpTree(parent).getJumpData().getAnimationJump());
|
||||
}
|
||||
boolean rVal =
|
||||
frameCurrent > ServerFallTree.MIN_FRAMES_BEFORE_ACTIVATION_SCAN &&
|
||||
@ -141,10 +141,10 @@ public class ClientFallTree implements BehaviorTree {
|
||||
Actor entityActor = EntityUtils.getActor(parent);
|
||||
if(entityActor != null){
|
||||
if(
|
||||
!entityActor.isPlayingAnimation() || !entityActor.isPlayingAnimation(fallMovementSystem.getLandState().getAnimation().getNameThirdPerson())
|
||||
!entityActor.getAnimationData().isPlayingAnimation() || !entityActor.getAnimationData().isPlayingAnimation(fallMovementSystem.getLandState().getAnimation().getNameThirdPerson())
|
||||
){
|
||||
entityActor.playAnimation(fallMovementSystem.getLandState().getAnimation().getNameThirdPerson(),AnimationPriorities.getValue(AnimationPriorities.MOVEMENT_MODIFIER));
|
||||
entityActor.incrementAnimationTime(0.0001);
|
||||
entityActor.getAnimationData().playAnimation(fallMovementSystem.getLandState().getAnimation().getNameThirdPerson(),AnimationPriorities.getValue(AnimationPriorities.MOVEMENT_MODIFIER));
|
||||
entityActor.getAnimationData().incrementAnimationTime(0.0001);
|
||||
}
|
||||
FirstPersonTree.conditionallyPlayAnimation(parent, fallMovementSystem.getLandState().getAnimation());
|
||||
}
|
||||
|
||||
@ -309,9 +309,9 @@ public class ClientGroundMovementTree implements BehaviorTree {
|
||||
//play animation
|
||||
String animationToPlay = determineCorrectAnimation(MovementTreeState.STARTUP);
|
||||
if(entityActor != null){
|
||||
if(!entityActor.isPlayingAnimation(animationToPlay)){
|
||||
entityActor.playAnimation(animationToPlay,AnimationPriorities.getValue(AnimationPriorities.CORE_MOVEMENT));
|
||||
entityActor.incrementAnimationTime(0.0001);
|
||||
if(!entityActor.getAnimationData().isPlayingAnimation(animationToPlay)){
|
||||
entityActor.getAnimationData().playAnimation(animationToPlay,AnimationPriorities.getValue(AnimationPriorities.CORE_MOVEMENT));
|
||||
entityActor.getAnimationData().incrementAnimationTime(0.0001);
|
||||
//reset footstep tracking
|
||||
this.playedFootstepFirst = false;
|
||||
this.playedFootstepSecond = false;
|
||||
@ -319,7 +319,7 @@ public class ClientGroundMovementTree implements BehaviorTree {
|
||||
FirstPersonTree.conditionallyPlayAnimation(parent, groundMovementData.getAnimationStartup().getNameFirstPerson(), AnimationPriorities.getValue(AnimationPriorities.CORE_MOVEMENT));
|
||||
}
|
||||
//conditionally play footstep audio
|
||||
this.playFootstepAudio(0,entityActor.getAnimationTime(animationToPlay),position);
|
||||
this.playFootstepAudio(0,entityActor.getAnimationData().getAnimationTime(animationToPlay),position);
|
||||
|
||||
this.updateVelocity();
|
||||
float velocity = this.getModifiedVelocity();
|
||||
@ -347,9 +347,9 @@ public class ClientGroundMovementTree implements BehaviorTree {
|
||||
//play animation
|
||||
String animationToPlay = determineCorrectAnimation(MovementTreeState.MOVE);
|
||||
if(entityActor != null){
|
||||
if(!entityActor.isPlayingAnimation(animationToPlay)){
|
||||
entityActor.playAnimation(animationToPlay,AnimationPriorities.getValue(AnimationPriorities.CORE_MOVEMENT));
|
||||
entityActor.incrementAnimationTime(0.0001);
|
||||
if(!entityActor.getAnimationData().isPlayingAnimation(animationToPlay)){
|
||||
entityActor.getAnimationData().playAnimation(animationToPlay,AnimationPriorities.getValue(AnimationPriorities.CORE_MOVEMENT));
|
||||
entityActor.getAnimationData().incrementAnimationTime(0.0001);
|
||||
//reset footstep tracking
|
||||
this.playedFootstepFirst = false;
|
||||
this.playedFootstepSecond = false;
|
||||
@ -358,7 +358,7 @@ public class ClientGroundMovementTree implements BehaviorTree {
|
||||
}
|
||||
|
||||
//conditionally play footstep audio
|
||||
this.playFootstepAudio(0,entityActor.getAnimationTime(animationToPlay),position);
|
||||
this.playFootstepAudio(0,entityActor.getAnimationData().getAnimationTime(animationToPlay),position);
|
||||
|
||||
this.updateVelocity();
|
||||
float velocity = this.getModifiedVelocity();
|
||||
@ -380,20 +380,20 @@ public class ClientGroundMovementTree implements BehaviorTree {
|
||||
String animationToPlay = determineCorrectAnimation(MovementTreeState.SLOWDOWN);
|
||||
if(entityActor != null){
|
||||
//play animations
|
||||
if(!entityActor.isPlayingAnimation(animationToPlay)){
|
||||
entityActor.playAnimation(animationToPlay,AnimationPriorities.getValue(AnimationPriorities.CORE_MOVEMENT));
|
||||
entityActor.incrementAnimationTime(0.0001);
|
||||
if(!entityActor.getAnimationData().isPlayingAnimation(animationToPlay)){
|
||||
entityActor.getAnimationData().playAnimation(animationToPlay,AnimationPriorities.getValue(AnimationPriorities.CORE_MOVEMENT));
|
||||
entityActor.getAnimationData().incrementAnimationTime(0.0001);
|
||||
//reset footstep tracking
|
||||
this.playedFootstepFirst = false;
|
||||
this.playedFootstepSecond = false;
|
||||
}
|
||||
FirstPersonTree.conditionallyPlayAnimation(parent, groundMovementData.getAnimationWindDown().getNameFirstPerson(), AnimationPriorities.getValue(AnimationPriorities.CORE_MOVEMENT));
|
||||
if(entityActor.isPlayingAnimation(determineCorrectAnimation(MovementTreeState.MOVE))){
|
||||
entityActor.stopAnimation(determineCorrectAnimation(MovementTreeState.MOVE));
|
||||
if(entityActor.getAnimationData().isPlayingAnimation(determineCorrectAnimation(MovementTreeState.MOVE))){
|
||||
entityActor.getAnimationData().stopAnimation(determineCorrectAnimation(MovementTreeState.MOVE));
|
||||
}
|
||||
}
|
||||
//conditionally play footstep audio
|
||||
this.playFootstepAudio(0,entityActor.getAnimationTime(animationToPlay),position);
|
||||
this.playFootstepAudio(0,entityActor.getAnimationData().getAnimationTime(animationToPlay),position);
|
||||
|
||||
//velocity stuff
|
||||
this.updateVelocity();
|
||||
@ -404,8 +404,8 @@ public class ClientGroundMovementTree implements BehaviorTree {
|
||||
state = MovementTreeState.IDLE;
|
||||
if(entityActor != null){
|
||||
animationToPlay = determineCorrectAnimation(MovementTreeState.SLOWDOWN);
|
||||
if(entityActor.isPlayingAnimation() && entityActor.isPlayingAnimation(animationToPlay)){
|
||||
entityActor.stopAnimation(animationToPlay);
|
||||
if(entityActor.getAnimationData().isPlayingAnimation() && entityActor.getAnimationData().isPlayingAnimation(animationToPlay)){
|
||||
entityActor.getAnimationData().stopAnimation(animationToPlay);
|
||||
}
|
||||
}
|
||||
CreatureUtils.setVelocity(parent, velocity);
|
||||
|
||||
@ -95,9 +95,9 @@ public class ClientJumpTree implements BehaviorTree {
|
||||
switch(state){
|
||||
case ACTIVE: {
|
||||
if(entityActor != null){
|
||||
if(!entityActor.isPlayingAnimation() || !entityActor.isPlayingAnimation(jumpData.getAnimationJump().getNameThirdPerson())){
|
||||
entityActor.playAnimation(jumpData.getAnimationJump().getNameThirdPerson(),AnimationPriorities.getValue(AnimationPriorities.MOVEMENT_MODIFIER));
|
||||
entityActor.incrementAnimationTime(0.0001);
|
||||
if(!entityActor.getAnimationData().isPlayingAnimation() || !entityActor.getAnimationData().isPlayingAnimation(jumpData.getAnimationJump().getNameThirdPerson())){
|
||||
entityActor.getAnimationData().playAnimation(jumpData.getAnimationJump().getNameThirdPerson(),AnimationPriorities.getValue(AnimationPriorities.MOVEMENT_MODIFIER));
|
||||
entityActor.getAnimationData().incrementAnimationTime(0.0001);
|
||||
}
|
||||
FirstPersonTree.conditionallyPlayAnimation(parent, jumpData.getAnimationJump());
|
||||
}
|
||||
|
||||
@ -42,7 +42,7 @@ public class RotatorTree implements BehaviorTree{
|
||||
state = RotatorTreeState.INACTIVE;
|
||||
//clear all modifications we've made up to this point
|
||||
for(RotatorHierarchyNode node : nodes){
|
||||
entityActor.getBoneRotator(node.getBone()).getRotation().identity();
|
||||
entityActor.getAnimationData().getBoneRotator(node.getBone()).getRotation().identity();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -70,7 +70,7 @@ public class RotatorTree implements BehaviorTree{
|
||||
// currentRotation.
|
||||
}
|
||||
if(followsView){
|
||||
ActorBoneRotator currentRotator = entityActor.getBoneRotator(node.getBone());
|
||||
ActorBoneRotator currentRotator = entityActor.getAnimationData().getBoneRotator(node.getBone());
|
||||
//apparently this isn't needed?
|
||||
//not sure I understand the math on this one
|
||||
// Vector3d facingVector = CreatureUtils.getFacingVector(parent);
|
||||
|
||||
@ -380,7 +380,7 @@ public class CommonEntityUtils {
|
||||
for(RotatorItem item : system.getRotatorItems()){
|
||||
//put actor rotator
|
||||
ActorBoneRotator newRotator = new ActorBoneRotator();
|
||||
creatureActor.addBoneRotator(item.getBoneName(), newRotator);
|
||||
creatureActor.getAnimationData().addBoneRotator(item.getBoneName(), newRotator);
|
||||
//construct node for tree
|
||||
RotatorHierarchyNode hierarchyNode = new RotatorHierarchyNode();
|
||||
hierarchyNode.setBone(item.getBoneName());
|
||||
@ -394,7 +394,7 @@ public class CommonEntityUtils {
|
||||
}
|
||||
//bone groups
|
||||
if(rawType.getBoneGroups() != null){
|
||||
creatureActor.setBoneGroups(rawType.getBoneGroups());
|
||||
creatureActor.getAnimationData().setBoneGroups(rawType.getBoneGroups());
|
||||
}
|
||||
//grid alignment
|
||||
if(rawType.getGridAlignedData() != null){
|
||||
|
||||
@ -107,7 +107,7 @@ public class CreatureUtils {
|
||||
if(attributeType.getType().equals("bone")){
|
||||
if(staticMorph == null){
|
||||
staticMorph = new ActorStaticMorph();
|
||||
creatureActor.setActorStaticMorph(staticMorph);
|
||||
creatureActor.getAnimationData().setActorStaticMorph(staticMorph);
|
||||
}
|
||||
if(attributeType.getPrimaryBone() != null && staticMorph.getBoneTransforms(attributeType.getPrimaryBone()) == null){
|
||||
staticMorph.initBoneTransforms(attributeType.getPrimaryBone());
|
||||
@ -380,7 +380,7 @@ public class CreatureUtils {
|
||||
Actor creatureActor = EntityUtils.getActor(rVal);
|
||||
|
||||
if(rawType.getBoneGroups() != null){
|
||||
creatureActor.setBoneGroups(rawType.getBoneGroups());
|
||||
creatureActor.getAnimationData().setBoneGroups(rawType.getBoneGroups());
|
||||
}
|
||||
|
||||
return rVal;
|
||||
|
||||
@ -331,9 +331,9 @@ public class ItemUtils {
|
||||
Actor actor = EntityUtils.getActor(item);
|
||||
if(actor != null && item.getData(EntityDataStrings.ANIM_IDLE) != null){
|
||||
String idleAnim = (String)item.getData(EntityDataStrings.ANIM_IDLE);
|
||||
if(!actor.isPlayingAnimation(idleAnim)){
|
||||
actor.playAnimation(idleAnim,AnimationPriorities.getValue(AnimationPriorities.INTERACTION));
|
||||
actor.incrementAnimationTime(0.0001);
|
||||
if(!actor.getAnimationData().isPlayingAnimation(idleAnim)){
|
||||
actor.getAnimationData().playAnimation(idleAnim,AnimationPriorities.getValue(AnimationPriorities.INTERACTION));
|
||||
actor.getAnimationData().incrementAnimationTime(0.0001);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,34 +1,25 @@
|
||||
package electrosphere.renderer.actor;
|
||||
|
||||
import electrosphere.data.entity.common.treedata.TreeDataAnimation;
|
||||
import electrosphere.data.entity.creature.bonegroups.BoneGroup;
|
||||
import electrosphere.engine.Globals;
|
||||
import electrosphere.entity.state.AnimationPriorities;
|
||||
import electrosphere.logger.LoggerInterface;
|
||||
import electrosphere.mem.JomlPool;
|
||||
import electrosphere.renderer.OpenGLState;
|
||||
import electrosphere.renderer.RenderPipelineState;
|
||||
import electrosphere.renderer.actor.mask.ActorAnimationMaskEntry;
|
||||
import electrosphere.renderer.actor.mask.ActorAnimationData;
|
||||
import electrosphere.renderer.actor.mask.ActorMeshMask;
|
||||
import electrosphere.renderer.actor.mask.ActorShaderMask;
|
||||
import electrosphere.renderer.actor.mask.ActorTextureMask;
|
||||
import electrosphere.renderer.actor.mask.ActorUniformMap;
|
||||
import electrosphere.renderer.actor.mask.ActorUniformMap.UniformValue;
|
||||
import electrosphere.renderer.model.Bone;
|
||||
import electrosphere.renderer.model.Model;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import org.joml.Matrix4d;
|
||||
import org.joml.Quaterniond;
|
||||
import org.joml.Sphered;
|
||||
import org.joml.Vector3d;
|
||||
import org.joml.Vector4d;
|
||||
|
||||
/**
|
||||
* An actor
|
||||
@ -43,11 +34,6 @@ import org.joml.Vector4d;
|
||||
*/
|
||||
public class Actor {
|
||||
|
||||
/**
|
||||
* Returned when the current time is requested of an animation that the actor is not playing
|
||||
*/
|
||||
public static final int INVALID_ANIMATION = -1;
|
||||
|
||||
/**
|
||||
* full-resolution lod level
|
||||
*/
|
||||
@ -83,11 +69,6 @@ public class Actor {
|
||||
*/
|
||||
private boolean frustumCull = true;
|
||||
|
||||
/**
|
||||
* scales the time that animations are played at
|
||||
*/
|
||||
private float animationScalar = 1.0f;
|
||||
|
||||
/**
|
||||
* Sets scaling applied at the actor level
|
||||
*/
|
||||
@ -129,9 +110,9 @@ public class Actor {
|
||||
private String lowResBaseModelPath;
|
||||
|
||||
/**
|
||||
* The stack of animations being applied to a given actor
|
||||
* The animation data for the actor
|
||||
*/
|
||||
private Set<ActorAnimationMaskEntry> animationQueue = new TreeSet<ActorAnimationMaskEntry>();
|
||||
private final ActorAnimationData animationData;
|
||||
|
||||
/**
|
||||
* Mask for overwriting meshes in a given actor
|
||||
@ -148,49 +129,10 @@ public class Actor {
|
||||
*/
|
||||
private Map<String,ActorTextureMask> textureMap = null;
|
||||
|
||||
/**
|
||||
* bone rotators
|
||||
*/
|
||||
private Map<String,ActorBoneRotator> boneRotators = new HashMap<String,ActorBoneRotator>();
|
||||
|
||||
/**
|
||||
* static morph for this specific actor
|
||||
*/
|
||||
private ActorStaticMorph staticMorph;
|
||||
|
||||
/**
|
||||
* The list of bone groups
|
||||
*/
|
||||
private List<BoneGroup> boneGroups;
|
||||
|
||||
/**
|
||||
* A map of mesh -> uniforms to apply to the mesh
|
||||
*/
|
||||
private ActorUniformMap uniformMap = new ActorUniformMap();
|
||||
|
||||
/**
|
||||
* Used for caching animation masks that should be removed
|
||||
*/
|
||||
private List<ActorAnimationMaskEntry> toRemoveMasks = new LinkedList<ActorAnimationMaskEntry>();
|
||||
|
||||
|
||||
|
||||
|
||||
//
|
||||
//
|
||||
// DATA CACHING
|
||||
//
|
||||
//
|
||||
|
||||
/**
|
||||
* Stores the positions of bones as they are updated
|
||||
*/
|
||||
private Map<String,Vector3d> bonePositionMap = new HashMap<String,Vector3d>();
|
||||
|
||||
/**
|
||||
* Stores the rotations of bones as they are updated
|
||||
*/
|
||||
private Map<String,Quaterniond> boneRotationMap = new HashMap<String,Quaterniond>();
|
||||
|
||||
|
||||
|
||||
@ -208,354 +150,7 @@ public class Actor {
|
||||
*/
|
||||
public Actor(String modelPath){
|
||||
this.baseModelPath = modelPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Increments the animation time of the actor
|
||||
* @param deltaTime The amount of time to increment by
|
||||
*/
|
||||
public void incrementAnimationTime(double deltaTime){
|
||||
toRemoveMasks.clear();
|
||||
for(ActorAnimationMaskEntry mask : animationQueue){
|
||||
if(mask.getFreezeFrames() > 0){
|
||||
mask.setFreezeFrames(mask.getFreezeFrames() - 1);
|
||||
} else {
|
||||
mask.setTime(mask.getTime() + deltaTime * animationScalar);
|
||||
if(mask.getTime() > mask.getDuration()){
|
||||
toRemoveMasks.add(mask);
|
||||
}
|
||||
}
|
||||
}
|
||||
for(ActorAnimationMaskEntry mask : toRemoveMasks){
|
||||
animationQueue.remove(mask);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current time of the given animation that is being played on this actor
|
||||
* @param animation The animation's name
|
||||
* @return The time into the animation, -1 if the animation is not being played
|
||||
*/
|
||||
public double getAnimationTime(String animation){
|
||||
ActorAnimationMaskEntry mask = this.getAnimationMask(animation);
|
||||
if(mask != null){
|
||||
return mask.getTime();
|
||||
}
|
||||
return INVALID_ANIMATION;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if an animation is being played on any meshes
|
||||
* @param animationName The animation name
|
||||
* @return true if the animation is being played on any meshes, false if the provided animation name is null or the animation is not being played on any meshes
|
||||
*/
|
||||
public boolean isPlayingAnimation(String animationName){
|
||||
if(animationName == null){
|
||||
return false;
|
||||
}
|
||||
for(ActorAnimationMaskEntry mask : animationQueue){
|
||||
if(mask.getAnimationName().equals(animationName)){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if an animation is being played on any meshes
|
||||
* @param animationData The animation data
|
||||
* @return true if the animation is being played on any meshes, false if the provided animation name is null or the animation is not being played on any meshes
|
||||
*/
|
||||
public boolean isPlayingAnimation(TreeDataAnimation animationData){
|
||||
if(animationData == null){
|
||||
return false;
|
||||
}
|
||||
for(ActorAnimationMaskEntry mask : animationQueue){
|
||||
if(animationData.getNameFirstPerson() != null && mask.getAnimationName().contains(animationData.getNameFirstPerson())){
|
||||
return true;
|
||||
}
|
||||
if(animationData.getNameThirdPerson() != null && mask.getAnimationName().contains(animationData.getNameThirdPerson())){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the actor is playing an animation
|
||||
* @return true if it is playing an animation, false otherwise
|
||||
*/
|
||||
public boolean isPlayingAnimation(){
|
||||
return animationQueue.size() > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops playing an animation on the actor
|
||||
* @param animationName The name of the animation
|
||||
*/
|
||||
public void stopAnimation(String animationName){
|
||||
List<ActorAnimationMaskEntry> toRemove = new LinkedList<ActorAnimationMaskEntry>();
|
||||
for(ActorAnimationMaskEntry mask : animationQueue){
|
||||
if(mask.getAnimationName().contains(animationName)){
|
||||
toRemove.add(mask);
|
||||
}
|
||||
}
|
||||
for(ActorAnimationMaskEntry mask : toRemove){
|
||||
animationQueue.remove(mask);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Plays an animation provided as a string with a given priority
|
||||
* @param animationName The name of the animation
|
||||
* @param priority The priority of the animation
|
||||
*/
|
||||
public void playAnimation(String animationName, int priority){
|
||||
Model model = Globals.assetManager.fetchModel(baseModelPath);
|
||||
if(model != null && model.getAnimation(animationName) != null){
|
||||
double length = model.getAnimation(animationName).duration;
|
||||
ActorAnimationMaskEntry animMask = new ActorAnimationMaskEntry(priority, animationName, 0, length);
|
||||
for(Bone bone : model.getBones()){
|
||||
animMask.addBone(bone.boneID);
|
||||
}
|
||||
toRemoveMasks.clear();
|
||||
for(ActorAnimationMaskEntry currentMask : animationQueue){
|
||||
if(currentMask.getPriority() == animMask.getPriority()){
|
||||
toRemoveMasks.add(currentMask);
|
||||
break;
|
||||
}
|
||||
}
|
||||
for(ActorAnimationMaskEntry currentMask : toRemoveMasks){
|
||||
animationQueue.remove(currentMask);
|
||||
}
|
||||
animationQueue.add(animMask);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Plays animation data
|
||||
* @param animation The animation data
|
||||
* @param isThirdPerson true if is third person, false if is first person
|
||||
*/
|
||||
public void playAnimation(TreeDataAnimation animation, boolean isThirdPerson){
|
||||
|
||||
//Get the animation's name
|
||||
String animationName = "";
|
||||
if(isThirdPerson){
|
||||
animationName = animation.getNameThirdPerson();
|
||||
} else {
|
||||
animationName = animation.getNameFirstPerson();
|
||||
}
|
||||
|
||||
//Get the animation's priority
|
||||
int priority = AnimationPriorities.getValue(AnimationPriorities.DEFAULT);
|
||||
if(animation.getPriority() != null){
|
||||
priority = animation.getPriority();
|
||||
}
|
||||
if(animation.getPriorityCategory() != null){
|
||||
priority = AnimationPriorities.getValue(animation.getPriorityCategory());
|
||||
}
|
||||
|
||||
//Gets the mask
|
||||
List<String> boneMask = null;
|
||||
if(animation.getBoneGroups() != null && this.boneGroups != null){
|
||||
boneMask = new LinkedList<String>();
|
||||
for(String boneGroupName : animation.getBoneGroups()){
|
||||
BoneGroup group = null;
|
||||
|
||||
for(BoneGroup currentGroup : this.boneGroups){
|
||||
if(currentGroup.getId().equals(boneGroupName)){
|
||||
group = currentGroup;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(group != null && isThirdPerson == true && group.getBoneNamesThirdPerson() != null && group.getBoneNamesThirdPerson().size() > 0){
|
||||
boneMask.addAll(group.getBoneNamesThirdPerson());
|
||||
}
|
||||
if(group != null && isThirdPerson == false && group.getBoneNamesFirstPerson() != null && group.getBoneNamesFirstPerson().size() > 0){
|
||||
boneMask.addAll(group.getBoneNamesFirstPerson());
|
||||
}
|
||||
}
|
||||
} else if(animation.getBoneGroups() != null && this.boneGroups == null){
|
||||
LoggerInterface.loggerRenderer.WARNING(
|
||||
"Trying to play animation on Actor that uses bone groups, but the Actor's bone group isn't defined!\n" +
|
||||
"Model path: " + baseModelPath + "\n" +
|
||||
"Animation name: " + animationName + "\n"
|
||||
);
|
||||
} else if(animation.getBoneGroups() == null){
|
||||
Model model = Globals.assetManager.fetchModel(this.baseModelPath);
|
||||
if(model != null){
|
||||
boneMask = new LinkedList<String>();
|
||||
for(Bone bone : model.getBones()){
|
||||
boneMask.add(bone.boneID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Model model = Globals.assetManager.fetchModel(baseModelPath);
|
||||
if(model != null && model.getAnimation(animationName) != null){
|
||||
|
||||
//get data from the actual animation in the model
|
||||
double length = model.getAnimation(animationName).duration;
|
||||
|
||||
//construct the animation mask
|
||||
ActorAnimationMaskEntry animMask;
|
||||
if(boneMask == null){
|
||||
animMask = new ActorAnimationMaskEntry(
|
||||
priority,
|
||||
animationName,
|
||||
length
|
||||
);
|
||||
} else {
|
||||
animMask = new ActorAnimationMaskEntry(
|
||||
priority,
|
||||
animationName,
|
||||
length,
|
||||
boneMask
|
||||
);
|
||||
}
|
||||
|
||||
//if a mask wasn't defined, apply this mask to all animations
|
||||
if(boneMask == null){
|
||||
for(Bone bone : model.getBones()){
|
||||
animMask.addBone(bone.boneID);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//clear existing masks that are lower priority
|
||||
toRemoveMasks.clear();
|
||||
for(ActorAnimationMaskEntry currentMask : animationQueue){
|
||||
if(currentMask.getPriority() == animMask.getPriority()){
|
||||
toRemoveMasks.add(currentMask);
|
||||
break;
|
||||
}
|
||||
}
|
||||
for(ActorAnimationMaskEntry currentMask : toRemoveMasks){
|
||||
animationQueue.remove(currentMask);
|
||||
}
|
||||
animationQueue.add(animMask);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Interrupts an animation, thereby causing it to stop playing
|
||||
* @param animation The animation to interrupt
|
||||
*/
|
||||
public void interruptAnimation(TreeDataAnimation animation, boolean isThirdPerson){
|
||||
//Get the animation's name
|
||||
String animationName = "";
|
||||
if(isThirdPerson){
|
||||
animationName = animation.getNameThirdPerson();
|
||||
} else {
|
||||
animationName = animation.getNameFirstPerson();
|
||||
}
|
||||
|
||||
//Get the animation's priority
|
||||
int priority = AnimationPriorities.getValue(AnimationPriorities.DEFAULT);
|
||||
if(animation.getPriority() != null){
|
||||
priority = animation.getPriority();
|
||||
}
|
||||
if(animation.getPriorityCategory() != null){
|
||||
priority = AnimationPriorities.getValue(animation.getPriorityCategory());
|
||||
}
|
||||
|
||||
toRemoveMasks.clear();
|
||||
for(ActorAnimationMaskEntry mask : this.animationQueue){
|
||||
if(mask.getAnimationName() == animationName && mask.getPriority() == priority){
|
||||
toRemoveMasks.add(mask);
|
||||
}
|
||||
}
|
||||
for(ActorAnimationMaskEntry currentMask : toRemoveMasks){
|
||||
animationQueue.remove(currentMask);
|
||||
}
|
||||
}
|
||||
|
||||
public void playAnimationWithMask(String animationName, int priority, List<String> boneMask){
|
||||
Model model = Globals.assetManager.fetchModel(baseModelPath);
|
||||
if(model != null){
|
||||
double length = model.getAnimation(animationName).duration;
|
||||
ActorAnimationMaskEntry animMask = new ActorAnimationMaskEntry(priority, animationName, 0, length, boneMask);
|
||||
toRemoveMasks.clear();
|
||||
for(ActorAnimationMaskEntry currentMask : animationQueue){
|
||||
if(currentMask.getPriority() == animMask.getPriority()){
|
||||
toRemoveMasks.add(currentMask);
|
||||
break;
|
||||
}
|
||||
}
|
||||
for(ActorAnimationMaskEntry currentMask : toRemoveMasks){
|
||||
animationQueue.remove(currentMask);
|
||||
}
|
||||
animationQueue.add(animMask);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the animation queue
|
||||
* @return The animation queue
|
||||
*/
|
||||
public Set<ActorAnimationMaskEntry> getAnimationQueue(){
|
||||
return animationQueue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the animation masks in this actor to the provided model
|
||||
* @param model The model
|
||||
*/
|
||||
private void applyAnimationMasks(Model model){
|
||||
List<String> bonesUsed = new LinkedList<String>();
|
||||
List<String> currentAnimationMask = new LinkedList<String>();
|
||||
for(ActorAnimationMaskEntry mask : animationQueue){
|
||||
currentAnimationMask.clear();
|
||||
for(String currentBone : mask.getBones()){
|
||||
if(!bonesUsed.contains(currentBone)){
|
||||
bonesUsed.add(currentBone);
|
||||
currentAnimationMask.add(currentBone);
|
||||
}
|
||||
}
|
||||
model.applyAnimationMask(mask.getAnimationName(), mask.getTime(), currentAnimationMask);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the node transforms for the actor
|
||||
* @param model The model that backs the actor
|
||||
*/
|
||||
private void calculateNodeTransforms(Model model){
|
||||
model.updateNodeTransform(boneRotators,staticMorph);
|
||||
for(Bone bone : model.getBones()){
|
||||
//store position
|
||||
Matrix4d betweenMat = new Matrix4d(bone.getMOffset()).invert();
|
||||
Vector4d result = betweenMat.transform(new Vector4d(0,0,0,1));
|
||||
betweenMat.set(bone.getFinalTransform());
|
||||
result = betweenMat.transform(result);
|
||||
this.bonePositionMap.put(bone.boneID,new Vector3d(result.x,result.y,result.z));
|
||||
//store rotation
|
||||
Quaterniond rotation = new Matrix4d(bone.getFinalTransform()).getNormalizedRotation(new Quaterniond());
|
||||
this.boneRotationMap.put(bone.boneID,rotation);
|
||||
}
|
||||
}
|
||||
|
||||
public void setAnimationScalar(float animationScalar) {
|
||||
this.animationScalar = animationScalar;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the animation mask for a given animation
|
||||
* @param animationName The animation's name
|
||||
* @return The animation mask if the actor is playing the animation, null otherwise
|
||||
*/
|
||||
public ActorAnimationMaskEntry getAnimationMask(String animationName){
|
||||
for(ActorAnimationMaskEntry mask : this.getAnimationQueue()){
|
||||
if(mask.getAnimationName().equals(animationName)){
|
||||
return mask;
|
||||
} else if(mask.getAnimationName().equalsIgnoreCase(animationName)){
|
||||
LoggerInterface.loggerEngine.WARNING("Animation mask failed to find, but there is an animation with a very similar name! " + animationName + " vs " + mask.getAnimationName());
|
||||
}
|
||||
}
|
||||
return null;
|
||||
this.animationData = new ActorAnimationData(this);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -594,7 +189,7 @@ public class Actor {
|
||||
|
||||
//frustum cull then draw
|
||||
if(Actor.isWithinFrustumBox(renderPipelineState,model,frustumCull)){
|
||||
this.applyAnimationMasks(model);
|
||||
this.animationData.applyAnimationMasks(model);
|
||||
meshMask.processMeshMaskQueue();
|
||||
model.setMeshMask(meshMask);
|
||||
model.setTextureMask(textureMap);
|
||||
@ -603,7 +198,7 @@ public class Actor {
|
||||
model.getShaderMask().put(shaderMask.getMeshName(),shaderMask);
|
||||
}
|
||||
}
|
||||
this.calculateNodeTransforms(model);
|
||||
this.animationData.calculateNodeTransforms(model);
|
||||
//apply uniform overrides
|
||||
if(this.uniformMap.getMeshes() != null && this.uniformMap.getMeshes().size() > 0){
|
||||
for(String meshName : this.uniformMap.getMeshes()){
|
||||
@ -635,12 +230,12 @@ public class Actor {
|
||||
this.lodLevel == Actor.LOD_LEVEL_STATIC ||
|
||||
//actor doesn't have anything complicated render-wise (animations, custom textures, etc)
|
||||
(
|
||||
this.animationQueue.size() == 0 &&
|
||||
this.animationData.isPlayingAnimation() &&
|
||||
this.meshMask.getBlockedMeshes().size() == 0 &&
|
||||
this.textureMap == null &&
|
||||
this.shaderMasks.size() == 0 &&
|
||||
this.uniformMap.isEmpty() &&
|
||||
this.staticMorph == null
|
||||
this.animationData.getStaticMorph() == null
|
||||
)
|
||||
;
|
||||
}
|
||||
@ -657,12 +252,12 @@ public class Actor {
|
||||
public String getStatisDrawStatus(){
|
||||
String rVal = "";
|
||||
rVal = rVal + this.isStaticDrawCall() + "\n";
|
||||
rVal = rVal + (this.animationQueue.size() == 0) + "\n";
|
||||
rVal = rVal + this.animationData.isPlayingAnimation() + "\n";
|
||||
rVal = rVal + (this.meshMask.getBlockedMeshes().size() == 0) + "\n";
|
||||
rVal = rVal + (this.textureMap == null) + "\n";
|
||||
rVal = rVal + (this.shaderMasks.size() == 0) + "\n";
|
||||
rVal = rVal + this.uniformMap.isEmpty() + "\n";
|
||||
rVal = rVal + (this.staticMorph == null) + "\n";
|
||||
rVal = rVal + (this.animationData.getStaticMorph() == null) + "\n";
|
||||
return rVal;
|
||||
}
|
||||
|
||||
@ -697,130 +292,6 @@ public class Actor {
|
||||
public String getBaseModelPath(){
|
||||
return baseModelPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the position of a bone in local space
|
||||
* @param boneName The name of the bone
|
||||
* @return The vector3d containing the position of the bone, or a vector of (0,0,0) if the model lookup fails
|
||||
* //TODO: refactor to make failure more transparent (both for model not existing and bone not existing)
|
||||
*/
|
||||
public Vector3d getBonePosition(String boneName){
|
||||
if(bonePositionMap.containsKey(boneName)){
|
||||
return bonePositionMap.get(boneName);
|
||||
}
|
||||
Vector3d rVal = new Vector3d();
|
||||
Model model = Globals.assetManager.fetchModel(baseModelPath);
|
||||
if(model != null){
|
||||
this.applyAnimationMasks(model);
|
||||
this.calculateNodeTransforms(model);
|
||||
Bone currentBone = model.getBoneMap().get(boneName);
|
||||
if(currentBone != null){
|
||||
Matrix4d betweenMat = new Matrix4d(currentBone.getMOffset()).invert();
|
||||
Vector4d result = betweenMat.transform(new Vector4d(rVal.x,rVal.y,rVal.z,1));
|
||||
betweenMat.set(currentBone.getFinalTransform());
|
||||
result = betweenMat.transform(result);
|
||||
rVal.x = (float)result.x;
|
||||
rVal.y = (float)result.y;
|
||||
rVal.z = (float)result.z;
|
||||
} else {
|
||||
String message = "Trying to get position of bone that does not exist on model!\n" +
|
||||
"boneName: " + boneName;
|
||||
throw new Error(message);
|
||||
}
|
||||
}
|
||||
if(!Double.isFinite(rVal.x)){
|
||||
throw new Error("Bone position that is not finite!");
|
||||
}
|
||||
return rVal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the rotation of a bone in local space
|
||||
* @param boneName The name of the bone
|
||||
* @return The Quaterniond containing the rotation of the bone, or an identity Quaterniond if the lookup fails
|
||||
*/
|
||||
public Quaterniond getBoneRotation(String boneName){
|
||||
if(boneRotationMap.containsKey(boneName)){
|
||||
return boneRotationMap.get(boneName);
|
||||
}
|
||||
Quaterniond rVal = new Quaterniond();
|
||||
Model model = Globals.assetManager.fetchModel(baseModelPath);
|
||||
if(model != null){
|
||||
this.applyAnimationMasks(model);
|
||||
this.calculateNodeTransforms(model);
|
||||
Bone currentBone = model.getBoneMap().get(boneName);
|
||||
if(currentBone != null){
|
||||
Quaterniond rotation = new Matrix4d(currentBone.getFinalTransform()).getNormalizedRotation(new Quaterniond());
|
||||
rVal.set(rotation);
|
||||
} else {
|
||||
String message = "Trying to get rotation of bone that does not exist on model!\n" +
|
||||
"boneName: " + boneName;
|
||||
throw new IllegalArgumentException(message);
|
||||
}
|
||||
}
|
||||
if(!Double.isFinite(rVal.x)){
|
||||
throw new IllegalStateException("Bone rotation that is not finite!");
|
||||
}
|
||||
return rVal;
|
||||
}
|
||||
|
||||
public Matrix4d getBoneTransform(String boneName){
|
||||
Matrix4d rVal = new Matrix4d();
|
||||
Model model = Globals.assetManager.fetchModel(baseModelPath);
|
||||
if(model != null){
|
||||
applyAnimationMasks(model);
|
||||
calculateNodeTransforms(model);
|
||||
Bone currentBone = model.getBoneMap().get(boneName);
|
||||
if(currentBone != null){
|
||||
rVal.set(currentBone.getFinalTransform());
|
||||
} else {
|
||||
throw new IllegalArgumentException("Trying to get rotation of bone that does not exist on model!");
|
||||
}
|
||||
}
|
||||
if(!Double.isFinite(rVal.m00())){
|
||||
throw new IllegalStateException("Bone rotation that is not finite!");
|
||||
}
|
||||
return rVal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the list of all bones
|
||||
* @return the list of all bones
|
||||
*/
|
||||
public List<Bone> getBoneValues(){
|
||||
Model model = Globals.assetManager.fetchModel(baseModelPath);
|
||||
if(model != null){
|
||||
applyAnimationMasks(model);
|
||||
calculateNodeTransforms(model);
|
||||
return model.getBones();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of a single bone
|
||||
* @return the bone
|
||||
*/
|
||||
public Bone getBone(String boneName){
|
||||
Model model = Globals.assetManager.fetchModel(baseModelPath);
|
||||
if(model != null){
|
||||
return model.getBoneMap().get(boneName);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the actor contains a bone
|
||||
* @param boneName The name of the bone
|
||||
* @return true if it exists, false otherwise
|
||||
*/
|
||||
public boolean containsBone(String boneName){
|
||||
Model model = Globals.assetManager.fetchModel(baseModelPath);
|
||||
if(model != null){
|
||||
return model.getBoneMap().containsKey(boneName);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the model is loaded for this actor
|
||||
@ -872,25 +343,6 @@ public class Actor {
|
||||
textureMap.put(textureMask.getMeshName(),textureMask);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adds a rotator to a bone on this actor
|
||||
* @param bone The name of the bone
|
||||
* @param rotator The rotator
|
||||
*/
|
||||
public void addBoneRotator(String bone, ActorBoneRotator rotator){
|
||||
boneRotators.put(bone, rotator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the rotator to apply to a bone
|
||||
* @param bone The name of the bone
|
||||
* @return The rotator to apply to that bone if it exists, null otherwise
|
||||
*/
|
||||
public ActorBoneRotator getBoneRotator(String bone){
|
||||
return boneRotators.get(bone);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of a uniform on a given mesh within this actor
|
||||
* @param meshName The name of the mesh
|
||||
@ -900,22 +352,6 @@ public class Actor {
|
||||
public void setUniformOnMesh(String meshName, String uniformName, Object value){
|
||||
this.uniformMap.setUniform(meshName, uniformName, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the static morph for this actor
|
||||
* @param staticMorph The static morph
|
||||
*/
|
||||
public void setActorStaticMorph(ActorStaticMorph staticMorph){
|
||||
this.staticMorph = staticMorph;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the static morph for this actor
|
||||
* @return The static morph for this actor
|
||||
*/
|
||||
public ActorStaticMorph getStaticMorph(){
|
||||
return this.staticMorph;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether this actor should frustum cull or not
|
||||
@ -933,31 +369,6 @@ public class Actor {
|
||||
return frustumCull;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the bone groups in the actor
|
||||
* @param boneGroups The bone groups
|
||||
*/
|
||||
public void setBoneGroups(List<BoneGroup> boneGroups){
|
||||
this.boneGroups = boneGroups;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the number of freeze frames for a given animation path if the animation is being played
|
||||
* @param animationPath The path to the animation
|
||||
* @param numFrames The number of frames to freeze for
|
||||
*/
|
||||
public void setFreezeFrames(String animationPath, int numFrames){
|
||||
if(numFrames < 1){
|
||||
throw new Error("Num frames less than 1 !" + numFrames);
|
||||
}
|
||||
for(ActorAnimationMaskEntry mask : this.animationQueue){
|
||||
if(mask.getAnimationName().contains(animationPath)){
|
||||
mask.setFreezeFrames(numFrames);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
@ -1047,5 +458,13 @@ public class Actor {
|
||||
this.lodLevel = lodLevel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the animation data for the actor
|
||||
* @return
|
||||
*/
|
||||
public ActorAnimationData getAnimationData(){
|
||||
return this.animationData;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -37,7 +37,7 @@ public class ActorUtils {
|
||||
*/
|
||||
public static ActorStaticMorph getStaticMorph(Entity actorEntity){
|
||||
Actor entityActor = EntityUtils.getActor(actorEntity);
|
||||
return entityActor.getStaticMorph();
|
||||
return entityActor.getAnimationData().getStaticMorph();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -0,0 +1,642 @@
|
||||
package electrosphere.renderer.actor.mask;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import org.joml.Matrix4d;
|
||||
import org.joml.Quaterniond;
|
||||
import org.joml.Vector3d;
|
||||
import org.joml.Vector4d;
|
||||
|
||||
import electrosphere.data.entity.common.treedata.TreeDataAnimation;
|
||||
import electrosphere.data.entity.creature.bonegroups.BoneGroup;
|
||||
import electrosphere.engine.Globals;
|
||||
import electrosphere.entity.state.AnimationPriorities;
|
||||
import electrosphere.logger.LoggerInterface;
|
||||
import electrosphere.renderer.actor.Actor;
|
||||
import electrosphere.renderer.actor.ActorBoneRotator;
|
||||
import electrosphere.renderer.actor.ActorStaticMorph;
|
||||
import electrosphere.renderer.model.Bone;
|
||||
import electrosphere.renderer.model.Model;
|
||||
|
||||
/**
|
||||
* The data about animations for a given actor
|
||||
*/
|
||||
public class ActorAnimationData {
|
||||
|
||||
/**
|
||||
* Returned when the current time is requested of an animation that the actor is not playing
|
||||
*/
|
||||
public static final int INVALID_ANIMATION = -1;
|
||||
|
||||
/**
|
||||
* The parent actor
|
||||
*/
|
||||
private final Actor parent;
|
||||
|
||||
/**
|
||||
* scales the time that animations are played at
|
||||
*/
|
||||
private float animationScalar = 1.0f;
|
||||
|
||||
/**
|
||||
* The stack of animations being applied to a given actor
|
||||
*/
|
||||
private Set<ActorAnimationMaskEntry> animationQueue = new TreeSet<ActorAnimationMaskEntry>();
|
||||
|
||||
/**
|
||||
* Used for caching animation masks that should be removed
|
||||
*/
|
||||
private List<ActorAnimationMaskEntry> toRemoveMasks = new LinkedList<ActorAnimationMaskEntry>();
|
||||
|
||||
/**
|
||||
* The list of bone groups
|
||||
*/
|
||||
private List<BoneGroup> boneGroups;
|
||||
|
||||
/**
|
||||
* static morph for this specific actor
|
||||
*/
|
||||
private ActorStaticMorph staticMorph;
|
||||
|
||||
/**
|
||||
* bone rotators
|
||||
*/
|
||||
private Map<String,ActorBoneRotator> boneRotators = new HashMap<String,ActorBoneRotator>();
|
||||
|
||||
//
|
||||
//
|
||||
// DATA CACHING
|
||||
//
|
||||
//
|
||||
|
||||
/**
|
||||
* Stores the positions of bones as they are updated
|
||||
*/
|
||||
private Map<String,Vector3d> bonePositionMap = new HashMap<String,Vector3d>();
|
||||
|
||||
/**
|
||||
* Stores the rotations of bones as they are updated
|
||||
*/
|
||||
private Map<String,Quaterniond> boneRotationMap = new HashMap<String,Quaterniond>();
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param parent The parent actor
|
||||
*/
|
||||
public ActorAnimationData(Actor parent){
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Increments the animation time of the actor
|
||||
* @param deltaTime The amount of time to increment by
|
||||
*/
|
||||
public void incrementAnimationTime(double deltaTime){
|
||||
toRemoveMasks.clear();
|
||||
for(ActorAnimationMaskEntry mask : animationQueue){
|
||||
if(mask.getFreezeFrames() > 0){
|
||||
mask.setFreezeFrames(mask.getFreezeFrames() - 1);
|
||||
} else {
|
||||
mask.setTime(mask.getTime() + deltaTime * animationScalar);
|
||||
if(mask.getTime() > mask.getDuration()){
|
||||
toRemoveMasks.add(mask);
|
||||
}
|
||||
}
|
||||
}
|
||||
for(ActorAnimationMaskEntry mask : toRemoveMasks){
|
||||
animationQueue.remove(mask);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current time of the given animation that is being played on this actor
|
||||
* @param animation The animation's name
|
||||
* @return The time into the animation, -1 if the animation is not being played
|
||||
*/
|
||||
public double getAnimationTime(String animation){
|
||||
ActorAnimationMaskEntry mask = this.getAnimationMask(animation);
|
||||
if(mask != null){
|
||||
return mask.getTime();
|
||||
}
|
||||
return INVALID_ANIMATION;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if an animation is being played on any meshes
|
||||
* @param animationName The animation name
|
||||
* @return true if the animation is being played on any meshes, false if the provided animation name is null or the animation is not being played on any meshes
|
||||
*/
|
||||
public boolean isPlayingAnimation(String animationName){
|
||||
if(animationName == null){
|
||||
return false;
|
||||
}
|
||||
for(ActorAnimationMaskEntry mask : animationQueue){
|
||||
if(mask.getAnimationName().equals(animationName)){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if an animation is being played on any meshes
|
||||
* @param animationData The animation data
|
||||
* @return true if the animation is being played on any meshes, false if the provided animation name is null or the animation is not being played on any meshes
|
||||
*/
|
||||
public boolean isPlayingAnimation(TreeDataAnimation animationData){
|
||||
if(animationData == null){
|
||||
return false;
|
||||
}
|
||||
for(ActorAnimationMaskEntry mask : animationQueue){
|
||||
if(animationData.getNameFirstPerson() != null && mask.getAnimationName().contains(animationData.getNameFirstPerson())){
|
||||
return true;
|
||||
}
|
||||
if(animationData.getNameThirdPerson() != null && mask.getAnimationName().contains(animationData.getNameThirdPerson())){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the actor is playing an animation
|
||||
* @return true if it is playing an animation, false otherwise
|
||||
*/
|
||||
public boolean isPlayingAnimation(){
|
||||
return animationQueue.size() > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops playing an animation on the actor
|
||||
* @param animationName The name of the animation
|
||||
*/
|
||||
public void stopAnimation(String animationName){
|
||||
List<ActorAnimationMaskEntry> toRemove = new LinkedList<ActorAnimationMaskEntry>();
|
||||
for(ActorAnimationMaskEntry mask : animationQueue){
|
||||
if(mask.getAnimationName().contains(animationName)){
|
||||
toRemove.add(mask);
|
||||
}
|
||||
}
|
||||
for(ActorAnimationMaskEntry mask : toRemove){
|
||||
animationQueue.remove(mask);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Plays an animation provided as a string with a given priority
|
||||
* @param animationName The name of the animation
|
||||
* @param priority The priority of the animation
|
||||
*/
|
||||
public void playAnimation(String animationName, int priority){
|
||||
Model model = Globals.assetManager.fetchModel(parent.getBaseModelPath());
|
||||
if(model != null && model.getAnimation(animationName) != null){
|
||||
double length = model.getAnimation(animationName).duration;
|
||||
ActorAnimationMaskEntry animMask = new ActorAnimationMaskEntry(priority, animationName, 0, length);
|
||||
for(Bone bone : model.getBones()){
|
||||
animMask.addBone(bone.boneID);
|
||||
}
|
||||
toRemoveMasks.clear();
|
||||
for(ActorAnimationMaskEntry currentMask : animationQueue){
|
||||
if(currentMask.getPriority() == animMask.getPriority()){
|
||||
toRemoveMasks.add(currentMask);
|
||||
break;
|
||||
}
|
||||
}
|
||||
for(ActorAnimationMaskEntry currentMask : toRemoveMasks){
|
||||
animationQueue.remove(currentMask);
|
||||
}
|
||||
animationQueue.add(animMask);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Plays animation data
|
||||
* @param animation The animation data
|
||||
* @param isThirdPerson true if is third person, false if is first person
|
||||
*/
|
||||
public void playAnimation(TreeDataAnimation animation, boolean isThirdPerson){
|
||||
|
||||
//Get the animation's name
|
||||
String animationName = "";
|
||||
if(isThirdPerson){
|
||||
animationName = animation.getNameThirdPerson();
|
||||
} else {
|
||||
animationName = animation.getNameFirstPerson();
|
||||
}
|
||||
|
||||
//Get the animation's priority
|
||||
int priority = AnimationPriorities.getValue(AnimationPriorities.DEFAULT);
|
||||
if(animation.getPriority() != null){
|
||||
priority = animation.getPriority();
|
||||
}
|
||||
if(animation.getPriorityCategory() != null){
|
||||
priority = AnimationPriorities.getValue(animation.getPriorityCategory());
|
||||
}
|
||||
|
||||
//Gets the mask
|
||||
List<String> boneMask = null;
|
||||
if(animation.getBoneGroups() != null && this.boneGroups != null){
|
||||
boneMask = new LinkedList<String>();
|
||||
for(String boneGroupName : animation.getBoneGroups()){
|
||||
BoneGroup group = null;
|
||||
|
||||
for(BoneGroup currentGroup : this.boneGroups){
|
||||
if(currentGroup.getId().equals(boneGroupName)){
|
||||
group = currentGroup;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(group != null && isThirdPerson == true && group.getBoneNamesThirdPerson() != null && group.getBoneNamesThirdPerson().size() > 0){
|
||||
boneMask.addAll(group.getBoneNamesThirdPerson());
|
||||
}
|
||||
if(group != null && isThirdPerson == false && group.getBoneNamesFirstPerson() != null && group.getBoneNamesFirstPerson().size() > 0){
|
||||
boneMask.addAll(group.getBoneNamesFirstPerson());
|
||||
}
|
||||
}
|
||||
} else if(animation.getBoneGroups() != null && this.boneGroups == null){
|
||||
LoggerInterface.loggerRenderer.WARNING(
|
||||
"Trying to play animation on Actor that uses bone groups, but the Actor's bone group isn't defined!\n" +
|
||||
"Model path: " + parent.getBaseModelPath() + "\n" +
|
||||
"Animation name: " + animationName + "\n"
|
||||
);
|
||||
} else if(animation.getBoneGroups() == null){
|
||||
Model model = Globals.assetManager.fetchModel(parent.getBaseModelPath());
|
||||
if(model != null){
|
||||
boneMask = new LinkedList<String>();
|
||||
for(Bone bone : model.getBones()){
|
||||
boneMask.add(bone.boneID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Model model = Globals.assetManager.fetchModel(parent.getBaseModelPath());
|
||||
if(model != null && model.getAnimation(animationName) != null){
|
||||
|
||||
//get data from the actual animation in the model
|
||||
double length = model.getAnimation(animationName).duration;
|
||||
|
||||
//construct the animation mask
|
||||
ActorAnimationMaskEntry animMask;
|
||||
if(boneMask == null){
|
||||
animMask = new ActorAnimationMaskEntry(
|
||||
priority,
|
||||
animationName,
|
||||
length
|
||||
);
|
||||
} else {
|
||||
animMask = new ActorAnimationMaskEntry(
|
||||
priority,
|
||||
animationName,
|
||||
length,
|
||||
boneMask
|
||||
);
|
||||
}
|
||||
|
||||
//if a mask wasn't defined, apply this mask to all animations
|
||||
if(boneMask == null){
|
||||
for(Bone bone : model.getBones()){
|
||||
animMask.addBone(bone.boneID);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//clear existing masks that are lower priority
|
||||
toRemoveMasks.clear();
|
||||
for(ActorAnimationMaskEntry currentMask : animationQueue){
|
||||
if(currentMask.getPriority() == animMask.getPriority()){
|
||||
toRemoveMasks.add(currentMask);
|
||||
break;
|
||||
}
|
||||
}
|
||||
for(ActorAnimationMaskEntry currentMask : toRemoveMasks){
|
||||
animationQueue.remove(currentMask);
|
||||
}
|
||||
animationQueue.add(animMask);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Interrupts an animation, thereby causing it to stop playing
|
||||
* @param animation The animation to interrupt
|
||||
*/
|
||||
public void interruptAnimation(TreeDataAnimation animation, boolean isThirdPerson){
|
||||
//Get the animation's name
|
||||
String animationName = "";
|
||||
if(isThirdPerson){
|
||||
animationName = animation.getNameThirdPerson();
|
||||
} else {
|
||||
animationName = animation.getNameFirstPerson();
|
||||
}
|
||||
|
||||
//Get the animation's priority
|
||||
int priority = AnimationPriorities.getValue(AnimationPriorities.DEFAULT);
|
||||
if(animation.getPriority() != null){
|
||||
priority = animation.getPriority();
|
||||
}
|
||||
if(animation.getPriorityCategory() != null){
|
||||
priority = AnimationPriorities.getValue(animation.getPriorityCategory());
|
||||
}
|
||||
|
||||
toRemoveMasks.clear();
|
||||
for(ActorAnimationMaskEntry mask : this.animationQueue){
|
||||
if(mask.getAnimationName() == animationName && mask.getPriority() == priority){
|
||||
toRemoveMasks.add(mask);
|
||||
}
|
||||
}
|
||||
for(ActorAnimationMaskEntry currentMask : toRemoveMasks){
|
||||
animationQueue.remove(currentMask);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Plays an animation on a specified set of bones
|
||||
* @param animationName The name of the animation
|
||||
* @param priority The priority of the animation
|
||||
* @param boneMask The set of bones to play the animation on
|
||||
*/
|
||||
public void playAnimationWithMask(String animationName, int priority, List<String> boneMask){
|
||||
Model model = Globals.assetManager.fetchModel(parent.getBaseModelPath());
|
||||
if(model != null){
|
||||
double length = model.getAnimation(animationName).duration;
|
||||
ActorAnimationMaskEntry animMask = new ActorAnimationMaskEntry(priority, animationName, 0, length, boneMask);
|
||||
toRemoveMasks.clear();
|
||||
for(ActorAnimationMaskEntry currentMask : animationQueue){
|
||||
if(currentMask.getPriority() == animMask.getPriority()){
|
||||
toRemoveMasks.add(currentMask);
|
||||
break;
|
||||
}
|
||||
}
|
||||
for(ActorAnimationMaskEntry currentMask : toRemoveMasks){
|
||||
animationQueue.remove(currentMask);
|
||||
}
|
||||
animationQueue.add(animMask);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the animation queue
|
||||
* @return The animation queue
|
||||
*/
|
||||
public Set<ActorAnimationMaskEntry> getAnimationQueue(){
|
||||
return animationQueue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the animation masks in this actor to the provided model
|
||||
* @param model The model
|
||||
*/
|
||||
public void applyAnimationMasks(Model model){
|
||||
List<String> bonesUsed = new LinkedList<String>();
|
||||
List<String> currentAnimationMask = new LinkedList<String>();
|
||||
for(ActorAnimationMaskEntry mask : animationQueue){
|
||||
currentAnimationMask.clear();
|
||||
for(String currentBone : mask.getBones()){
|
||||
if(!bonesUsed.contains(currentBone)){
|
||||
bonesUsed.add(currentBone);
|
||||
currentAnimationMask.add(currentBone);
|
||||
}
|
||||
}
|
||||
model.applyAnimationMask(mask.getAnimationName(), mask.getTime(), currentAnimationMask);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the node transforms for the actor
|
||||
* @param model The model that backs the actor
|
||||
*/
|
||||
public void calculateNodeTransforms(Model model){
|
||||
model.updateNodeTransform(boneRotators,staticMorph);
|
||||
for(Bone bone : model.getBones()){
|
||||
//store position
|
||||
Matrix4d betweenMat = new Matrix4d(bone.getMOffset()).invert();
|
||||
Vector4d result = betweenMat.transform(new Vector4d(0,0,0,1));
|
||||
betweenMat.set(bone.getFinalTransform());
|
||||
result = betweenMat.transform(result);
|
||||
this.bonePositionMap.put(bone.boneID,new Vector3d(result.x,result.y,result.z));
|
||||
//store rotation
|
||||
Quaterniond rotation = new Matrix4d(bone.getFinalTransform()).getNormalizedRotation(new Quaterniond());
|
||||
this.boneRotationMap.put(bone.boneID,rotation);
|
||||
}
|
||||
}
|
||||
|
||||
public void setAnimationScalar(float animationScalar) {
|
||||
this.animationScalar = animationScalar;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the animation mask for a given animation
|
||||
* @param animationName The animation's name
|
||||
* @return The animation mask if the actor is playing the animation, null otherwise
|
||||
*/
|
||||
public ActorAnimationMaskEntry getAnimationMask(String animationName){
|
||||
for(ActorAnimationMaskEntry mask : this.getAnimationQueue()){
|
||||
if(mask.getAnimationName().equals(animationName)){
|
||||
return mask;
|
||||
} else if(mask.getAnimationName().equalsIgnoreCase(animationName)){
|
||||
LoggerInterface.loggerEngine.WARNING("Animation mask failed to find, but there is an animation with a very similar name! " + animationName + " vs " + mask.getAnimationName());
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a rotator to a bone on this actor
|
||||
* @param bone The name of the bone
|
||||
* @param rotator The rotator
|
||||
*/
|
||||
public void addBoneRotator(String bone, ActorBoneRotator rotator){
|
||||
boneRotators.put(bone, rotator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the rotator to apply to a bone
|
||||
* @param bone The name of the bone
|
||||
* @return The rotator to apply to that bone if it exists, null otherwise
|
||||
*/
|
||||
public ActorBoneRotator getBoneRotator(String bone){
|
||||
return boneRotators.get(bone);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the static morph for this actor
|
||||
* @param staticMorph The static morph
|
||||
*/
|
||||
public void setActorStaticMorph(ActorStaticMorph staticMorph){
|
||||
this.staticMorph = staticMorph;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the static morph for this actor
|
||||
* @return The static morph for this actor
|
||||
*/
|
||||
public ActorStaticMorph getStaticMorph(){
|
||||
return this.staticMorph;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the bone groups in the actor
|
||||
* @param boneGroups The bone groups
|
||||
*/
|
||||
public void setBoneGroups(List<BoneGroup> boneGroups){
|
||||
this.boneGroups = boneGroups;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the number of freeze frames for a given animation path if the animation is being played
|
||||
* @param animationPath The path to the animation
|
||||
* @param numFrames The number of frames to freeze for
|
||||
*/
|
||||
public void setFreezeFrames(String animationPath, int numFrames){
|
||||
if(numFrames < 1){
|
||||
throw new Error("Num frames less than 1 !" + numFrames);
|
||||
}
|
||||
for(ActorAnimationMaskEntry mask : this.animationQueue){
|
||||
if(mask.getAnimationName().contains(animationPath)){
|
||||
mask.setFreezeFrames(numFrames);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the position of a bone in local space
|
||||
* @param boneName The name of the bone
|
||||
* @return The vector3d containing the position of the bone, or a vector of (0,0,0) if the model lookup fails
|
||||
* //TODO: refactor to make failure more transparent (both for model not existing and bone not existing)
|
||||
*/
|
||||
public Vector3d getBonePosition(String boneName){
|
||||
if(bonePositionMap.containsKey(boneName)){
|
||||
return bonePositionMap.get(boneName);
|
||||
}
|
||||
Vector3d rVal = new Vector3d();
|
||||
Model model = Globals.assetManager.fetchModel(parent.getBaseModelPath());
|
||||
if(model != null){
|
||||
this.applyAnimationMasks(model);
|
||||
this.calculateNodeTransforms(model);
|
||||
Bone currentBone = model.getBoneMap().get(boneName);
|
||||
if(currentBone != null){
|
||||
Matrix4d betweenMat = new Matrix4d(currentBone.getMOffset()).invert();
|
||||
Vector4d result = betweenMat.transform(new Vector4d(rVal.x,rVal.y,rVal.z,1));
|
||||
betweenMat.set(currentBone.getFinalTransform());
|
||||
result = betweenMat.transform(result);
|
||||
rVal.x = (float)result.x;
|
||||
rVal.y = (float)result.y;
|
||||
rVal.z = (float)result.z;
|
||||
} else {
|
||||
String message = "Trying to get position of bone that does not exist on model!\n" +
|
||||
"boneName: " + boneName;
|
||||
throw new Error(message);
|
||||
}
|
||||
}
|
||||
if(!Double.isFinite(rVal.x)){
|
||||
throw new Error("Bone position that is not finite!");
|
||||
}
|
||||
return rVal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the rotation of a bone in local space
|
||||
* @param boneName The name of the bone
|
||||
* @return The Quaterniond containing the rotation of the bone, or an identity Quaterniond if the lookup fails
|
||||
*/
|
||||
public Quaterniond getBoneRotation(String boneName){
|
||||
if(boneRotationMap.containsKey(boneName)){
|
||||
return boneRotationMap.get(boneName);
|
||||
}
|
||||
Quaterniond rVal = new Quaterniond();
|
||||
Model model = Globals.assetManager.fetchModel(parent.getBaseModelPath());
|
||||
if(model != null){
|
||||
this.applyAnimationMasks(model);
|
||||
this.calculateNodeTransforms(model);
|
||||
Bone currentBone = model.getBoneMap().get(boneName);
|
||||
if(currentBone != null){
|
||||
Quaterniond rotation = new Matrix4d(currentBone.getFinalTransform()).getNormalizedRotation(new Quaterniond());
|
||||
rVal.set(rotation);
|
||||
} else {
|
||||
String message = "Trying to get rotation of bone that does not exist on model!\n" +
|
||||
"boneName: " + boneName;
|
||||
throw new IllegalArgumentException(message);
|
||||
}
|
||||
}
|
||||
if(!Double.isFinite(rVal.x)){
|
||||
throw new IllegalStateException("Bone rotation that is not finite!");
|
||||
}
|
||||
return rVal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the bone transform for a bone on this actor
|
||||
* @param boneName The name of the bone
|
||||
* @return The transform
|
||||
*/
|
||||
public Matrix4d getBoneTransform(String boneName){
|
||||
Matrix4d rVal = new Matrix4d();
|
||||
Model model = Globals.assetManager.fetchModel(parent.getBaseModelPath());
|
||||
if(model != null){
|
||||
applyAnimationMasks(model);
|
||||
calculateNodeTransforms(model);
|
||||
Bone currentBone = model.getBoneMap().get(boneName);
|
||||
if(currentBone != null){
|
||||
rVal.set(currentBone.getFinalTransform());
|
||||
} else {
|
||||
throw new IllegalArgumentException("Trying to get rotation of bone that does not exist on model!");
|
||||
}
|
||||
}
|
||||
if(!Double.isFinite(rVal.m00())){
|
||||
throw new IllegalStateException("Bone rotation that is not finite!");
|
||||
}
|
||||
return rVal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the list of all bones
|
||||
* @return the list of all bones
|
||||
*/
|
||||
public List<Bone> getBoneValues(){
|
||||
Model model = Globals.assetManager.fetchModel(parent.getBaseModelPath());
|
||||
if(model != null){
|
||||
applyAnimationMasks(model);
|
||||
calculateNodeTransforms(model);
|
||||
return model.getBones();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of a single bone
|
||||
* @return the bone
|
||||
*/
|
||||
public Bone getBone(String boneName){
|
||||
Model model = Globals.assetManager.fetchModel(parent.getBaseModelPath());
|
||||
if(model != null){
|
||||
return model.getBoneMap().get(boneName);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the actor contains a bone
|
||||
* @param boneName The name of the bone
|
||||
* @return true if it exists, false otherwise
|
||||
*/
|
||||
public boolean containsBone(String boneName){
|
||||
Model model = Globals.assetManager.fetchModel(parent.getBaseModelPath());
|
||||
if(model != null){
|
||||
return model.getBoneMap().containsKey(boneName);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@ -70,7 +70,7 @@ public class DebugBonesPipeline implements RenderPipeline {
|
||||
Actor targetActor = EntityUtils.getActor(targetEntity);
|
||||
Model boneModel = Globals.assetManager.fetchModel(AssetDataStrings.UNITCYLINDER);
|
||||
boneModel.getMaterials().get(0).setDiffuse(Globals.assetManager.fetchTexture(AssetDataStrings.TEXTURE_DEFAULT));
|
||||
for(Bone bone : targetActor.getBoneValues()){
|
||||
for(Bone bone : targetActor.getAnimationData().getBoneValues()){
|
||||
Vector3d bonePos = MathBones.getBoneWorldPosition(targetEntity, bone.boneID);
|
||||
Quaterniond boneRot = MathBones.getBoneWorldRotation(targetEntity, bone.boneID);
|
||||
|
||||
|
||||
@ -226,12 +226,12 @@ public class ActorPanel extends BufferedStandardDrawableContainerElement impleme
|
||||
|
||||
Model actorModel = Globals.assetManager.fetchModel(actor.getBaseModelPath());
|
||||
if(currentAnim != null){
|
||||
if((!actor.isPlayingAnimation() || !actor.isPlayingAnimation(currentAnim)) &&
|
||||
if((!actor.getAnimationData().isPlayingAnimation() || !actor.getAnimationData().isPlayingAnimation(currentAnim)) &&
|
||||
actorModel != null &&
|
||||
actorModel.getAnimation(currentAnim) != null
|
||||
){
|
||||
actor.playAnimation(currentAnim,3);
|
||||
actor.incrementAnimationTime(0.0001);
|
||||
actor.getAnimationData().playAnimation(currentAnim,3);
|
||||
actor.getAnimationData().incrementAnimationTime(0.0001);
|
||||
}
|
||||
}
|
||||
if(!hasOffsetFromBoundingSphere && actorModel != null){
|
||||
|
||||
@ -22,7 +22,7 @@ public class MathBones {
|
||||
*/
|
||||
public static Vector3d getBoneWorldPosition(Entity actorEntity, String boneName){
|
||||
Actor actor = EntityUtils.getActor(actorEntity);
|
||||
Vector3d localPos = new Vector3d(actor.getBonePosition(boneName));
|
||||
Vector3d localPos = new Vector3d(actor.getAnimationData().getBonePosition(boneName));
|
||||
|
||||
//transform bone space
|
||||
Vector3d position = new Vector3d(localPos);
|
||||
@ -41,7 +41,7 @@ public class MathBones {
|
||||
*/
|
||||
public static Quaterniond getBoneWorldRotation(Entity actorEntity, String boneName){
|
||||
Actor actor = EntityUtils.getActor(actorEntity);
|
||||
Quaterniond localRot = actor.getBoneRotation(boneName);
|
||||
Quaterniond localRot = actor.getAnimationData().getBoneRotation(boneName);
|
||||
|
||||
Vector3d facingAngle = CreatureUtils.getFacingVector(actorEntity);
|
||||
if(facingAngle == null){
|
||||
|
||||
Loading…
Reference in New Issue
Block a user