unify animation data on disk
Some checks failed
studiorailgun/Renderer/pipeline/head There was a failure building this commit

This commit is contained in:
austin 2024-07-28 14:51:20 -04:00
parent ceb4786228
commit ad823fcbb4
29 changed files with 689 additions and 152 deletions

View File

@ -130,41 +130,33 @@
"acceleration" : 5000.0,
"maxVelocity" : 500.5,
"animationStartup" : {
"name" : "Jog",
"nameThirdPerson" : "Jog",
"length" : 1,
"loops" : false
},
"animationFirstPersonStartup" : {
"name" : "Jog"
"nameFirstPerson" : "Jog"
},
"animationLoop" : {
"name" : "Jog",
"length" : 1,
"loops" : false
"nameThirdPerson" : "Jog"
},
"animationFirstPersonLoop" : {
"name" : "Jog"
"nameFirstPerson" : "Jog"
},
"animationWindDown" : {
"name" : "Jog",
"length" : 1,
"loops" : false
"nameThirdPerson" : "Jog"
},
"animationFirstPersonWindDown" : {
"name" : "Jog"
"nameFirstPerson" : "Jog"
},
"sprintSystem" : {
"maxVelocity" : 0.058,
"staminaMax" : 500,
"animationStartUp" : {
"name" : "Sprint",
"length" : 1,
"loops" : false
"nameThirdPerson" : "Sprint"
},
"animationMain" : {
"name" : "Sprint",
"length" : 1,
"loops" : false
"nameThirdPerson" : "Sprint"
}
}
},
@ -173,33 +165,25 @@
"jumpFrames" : 3,
"jumpForce" : 500,
"animationJump" : {
"name" : "Jump",
"length" : 1,
"loops" : false
"nameThirdPerson" : "Jump"
},
"animationFirstPersonJump" : {
"name" : "Jump"
"nameFirstPerson" : "Jump"
}
},
{
"type" : "FALL",
"fallState" : {
"firstPersonAnimation" : {
"name" : "Fall",
"priority": 4
},
"thirdPersonAnimation" : {
"name" : "Fall",
"animation" : {
"nameThirdPerson" : "Fall",
"nameFirstPerson" : "Fall",
"priority": 4
}
},
"landState" : {
"firstPersonAnimation" : {
"name" : "Land",
"priority": 4
},
"thirdPersonAnimation" : {
"name" : "Land",
"animation" : {
"nameThirdPerson" : "Land",
"nameFirstPerson" : "Land",
"priority": 4
}
}
@ -270,7 +254,13 @@
"tool",
"weapon",
"item"
]
],
"equippedAnimation" : {
"nameThirdPerson" : "",
"nameFirstPerson" : "",
"priority" : 4,
"boneGroups" : ["handRight"]
}
},
{
"equipPointId" : "Torso",
@ -344,13 +334,13 @@
"driftFrameEnd" : 15,
"initialMove" : true,
"animationFirstPersonWindup" : {
"name" : "Jump"
"nameFirstPerson" : "Jump"
},
"animationFirstPersonHold" : {
"name" : "Jump"
"nameFirstPerson" : "Jump"
},
"animationFirstPersonAttack" : {
"name" : "Sword1HSlash1"
"nameFirstPerson" : "Sword1HSlash1"
}
},
{
@ -369,13 +359,13 @@
"driftFrameEnd" : 10,
"initialMove" : false,
"animationFirstPersonWindup" : {
"name" : "Jump"
"nameFirstPerson" : "Jump"
},
"animationFirstPersonHold" : {
"name" : "Jump"
"nameFirstPerson" : "Jump"
},
"animationFirstPersonAttack" : {
"name" : "Sword1HSlash2"
"nameFirstPerson" : "Sword1HSlash2"
}
},
{
@ -393,13 +383,13 @@
"driftFrameEnd" : 10,
"initialMove" : true,
"animationFirstPersonWindup" : {
"name" : "HoldItemR2H"
"nameFirstPerson" : "HoldItemR2H"
},
"animationFirstPersonHold" : {
"name" : "HoldItemR2H"
"nameFirstPerson" : "HoldItemR2H"
},
"animationFirstPersonAttack" : {
"name" : "SwordR2HSlash"
"nameFirstPerson" : "SwordR2HSlash"
}
},
{
@ -419,13 +409,13 @@
"movementGoal" : 0,
"initialMove" : true,
"animationFirstPersonWindup" : {
"name" : "Jump"
"nameFirstPerson" : "Jump"
},
"animationFirstPersonHold" : {
"name" : "Jump"
"nameFirstPerson" : "Jump"
},
"animationFirstPersonAttack" : {
"name" : "Jump"
"nameFirstPerson" : "Jump"
}
}
],
@ -451,6 +441,84 @@
"attackRange" : 2,
"stateChangeTimeout" : "240"
}
],
"boneGroups" : [
{
"id" : "torso",
"boneNamesThirdPerson" : [
"Bone", "UpperTorso", "Shoulder.R", "Shoulder.L", "Breast.R", "Breast.L", "Butt.L", "Butt.R"
]
},
{
"id" : "head",
"boneNamesThirdPerson" : [
"Neck", "Head", "Ear.L", "Ear.R", "Eye.L", "Eye.R", "Jaw", "Nose", "MouthCorner.R", "MouthCorner.L", "JawTop", "Iris.L", "Iris.R"
]
},
{
"id" : "armRight",
"boneNamesThirdPerson" : [
"Bicep.R", "Forearm.R"
],
"boneNamesFirstPerson" : [
"clavicle.R", "deltoid.R", "upper_arm.R", "forearm.R"
]
},
{
"id" : "handRight",
"boneNamesThirdPerson" : [
"Hand.R", "MiddleUpper.R", "ThumbUpper.R"
],
"boneNamesFirstPerson" : [
"hand.R",
"palm_pinky.R",
"f_pinky.01.R",
"f_pinky.02.R",
"f_pinky.03.R",
"palm_middle.R",
"f_middle.01.R",
"f_middle.02.R",
"f_middle.03.R",
"palm_ring.R",
"f_ring.01.R",
"f_ring.02.R",
"f_ring.03.R",
"thumb.01.R",
"thumb.02.R",
"thumb.03.R",
"palm_index.R",
"f_index.01.R",
"f_index.02.R",
"f_index.03.R"
]
},
{
"id" : "armLeft",
"boneNamesThirdPerson" : [
"Bicep.L", "Forearm.L"
],
"boneNamesFirstPerson" : [
"clavicle.L", "deltoid.L", "upper_arm.L", "forearm.L"
]
},
{
"id" : "handLeft",
"boneNamesThirdPerson" : [
"Hand.L", "MiddleUpper.L", "ThumbUpper.L"
]
},
{
"id" : "legLeft",
"boneNamesThirdPerson" : [
"Leg.L", "LowerLeg.L", "Foot.L"
]
},
{
"id" : "legRight",
"boneNamesThirdPerson" : [
"Leg.R", "LowerLeg.R", "Foot.R"
]
}
]
}
],

View File

@ -11,7 +11,7 @@ import org.joml.Vector3i;
import electrosphere.auth.AuthenticationManager;
import electrosphere.engine.Globals;
import electrosphere.entity.types.creature.CreatureTemplate;
import electrosphere.game.data.creature.type.CreatureType;
import electrosphere.game.data.creature.type.CreatureData;
import electrosphere.game.data.creature.type.visualattribute.VisualAttribute;
import electrosphere.game.server.world.MacroData;
import electrosphere.net.NetUtils;
@ -152,7 +152,7 @@ public class LoadingUtils {
//
//send default template back
String race = Globals.gameConfigCurrent.getCreatureTypeLoader().getPlayableRaces().get(0);
CreatureType type = Globals.gameConfigCurrent.getCreatureTypeLoader().getCreature(race);
CreatureData type = Globals.gameConfigCurrent.getCreatureTypeLoader().getCreature(race);
CreatureTemplate template = new CreatureTemplate(race);
for(VisualAttribute attribute : type.getVisualAttributes()){
if(attribute.getType().equals(VisualAttribute.TYPE_BONE)){

View File

@ -130,15 +130,21 @@ public class StateTransitionUtil {
}
}
actor.playAnimation(thirdPersonAnimation,state.getAnimationPriority());
if(state.animation == null){
actor.playAnimation(firstPersonAnimation, state.getAnimationPriority());
} else {
actor.playAnimation(state.animation,true);
}
actor.incrementAnimationTime(0.0001);
state.startedAnimation = true;
} else if(thirdPersonAnimation == null && state.onComplete != null){
state.onComplete.run();
state.startedAnimation = false;
}
if(firstPersonAnimation != null){
if(state.animation == null){
FirstPersonTree.conditionallyPlayAnimation(Globals.firstPersonEntity, firstPersonAnimation, state.getAnimationPriority());
} else if(firstPersonAnimation != null){
FirstPersonTree.conditionallyPlayAnimation(Globals.firstPersonEntity, state.animation);
}
}
}
@ -162,7 +168,11 @@ public class StateTransitionUtil {
state.startedAnimation = false;
} else if(thirdPersonAnimation != null && (!poseActor.isPlayingAnimation() || !poseActor.isPlayingAnimation(thirdPersonAnimation))){
//play animation for state
poseActor.playAnimation(thirdPersonAnimation,state.getAnimationPriority());
if(state.animation == null){
poseActor.playAnimation(thirdPersonAnimation, state.getAnimationPriority());
} else {
poseActor.playAnimation(state.animation,true);
}
poseActor.incrementAnimationTime(0.0001);
state.startedAnimation = true;
} else if(thirdPersonAnimation == null && state.onComplete != null){
@ -183,14 +193,11 @@ public class StateTransitionUtil {
//the priority of this animation in particular
int animPriority;
//The animation to play in first person
TreeDataAnimation firstPersonAnimation;
//The animation to play
TreeDataAnimation animation;
//Gets the first person animation's name
Supplier<String> getFirstPersonAnimation;
//The animation to play in third person
TreeDataAnimation thirdPersonAnimation;
//Gets the third person animation's name
Supplier<String> getThirdPersonAnimation;
@ -210,8 +217,8 @@ public class StateTransitionUtil {
*/
String getThirdPersonAnimation(){
String toPlay = null;
if(thirdPersonAnimation != null){
toPlay = thirdPersonAnimation.getName();
if(animation != null){
toPlay = animation.getNameThirdPerson();
}
if(getThirdPersonAnimation != null){
toPlay = getThirdPersonAnimation.get();
@ -225,8 +232,8 @@ public class StateTransitionUtil {
*/
String getFirstPersonAnimation(){
String toPlay = null;
if(firstPersonAnimation != null){
toPlay = firstPersonAnimation.getName();
if(animation != null){
toPlay = animation.getNameFirstPerson();
}
if(getFirstPersonAnimation != null){
toPlay = getFirstPersonAnimation.get();
@ -240,8 +247,8 @@ public class StateTransitionUtil {
*/
int getAnimationPriority(){
int priority = this.animPriority;
if(thirdPersonAnimation != null && thirdPersonAnimation.getPriority() != null){
priority = thirdPersonAnimation.getPriority();
if(animation != null && animation.getPriority() != null){
priority = animation.getPriority();
}
return priority;
}
@ -251,14 +258,12 @@ public class StateTransitionUtil {
*/
private StateTransitionUtilItem(
Object stateEnum,
TreeDataAnimation firstPersonAnimation,
TreeDataAnimation thirdPersonAnimation,
TreeDataAnimation animation,
TreeDataAudio audioData,
Runnable onComplete
){
this.stateEnum = stateEnum;
this.firstPersonAnimation = firstPersonAnimation;
this.thirdPersonAnimation = thirdPersonAnimation;
this.animation = animation;
this.audioData = audioData;
this.onComplete = onComplete;
}
@ -326,8 +331,7 @@ public class StateTransitionUtil {
if(treeData != null){
rVal = new StateTransitionUtilItem(
stateEnum,
treeData.getFirstPersonAnimation(),
treeData.getThirdPersonAnimation(),
treeData.getAnimation(),
treeData.getAudioData(),
onComplete
);

View File

@ -244,7 +244,7 @@ public class ClientAttackTree implements BehaviorTree {
entityActor.playAnimation(currentMove.getWindupAnimationName(),AnimationPriorities.ATTACK);
entityActor.incrementAnimationTime(0.0001);
}
FirstPersonTree.conditionallyPlayAnimation(Globals.firstPersonEntity, currentMove.getAnimationFirstPersonWindup().getName(), AnimationPriorities.ATTACK);
FirstPersonTree.conditionallyPlayAnimation(Globals.firstPersonEntity, currentMove.getAnimationFirstPersonWindup().getNameFirstPerson(), AnimationPriorities.ATTACK);
}
}
} break;
@ -254,7 +254,7 @@ public class ClientAttackTree implements BehaviorTree {
entityActor.playAnimation(currentMove.getHoldAnimationName(),AnimationPriorities.ATTACK);
entityActor.incrementAnimationTime(0.0001);
}
FirstPersonTree.conditionallyPlayAnimation(Globals.firstPersonEntity, currentMove.getAnimationFirstPersonHold().getName(), AnimationPriorities.ATTACK);
FirstPersonTree.conditionallyPlayAnimation(Globals.firstPersonEntity, currentMove.getAnimationFirstPersonHold().getNameFirstPerson(), AnimationPriorities.ATTACK);
}
} break;
case ATTACK: {
@ -263,7 +263,7 @@ public class ClientAttackTree implements BehaviorTree {
entityActor.playAnimation(currentMove.getAttackAnimationName(),AnimationPriorities.ATTACK);
entityActor.incrementAnimationTime(0.0001);
}
FirstPersonTree.conditionallyPlayAnimation(Globals.firstPersonEntity, currentMove.getAnimationFirstPersonAttack().getName(), AnimationPriorities.ATTACK);
FirstPersonTree.conditionallyPlayAnimation(Globals.firstPersonEntity, currentMove.getAnimationFirstPersonAttack().getNameFirstPerson(), AnimationPriorities.ATTACK);
}
//activate hitboxes
List<Entity> attachedEntities = AttachUtils.getChildrenList(parent);

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.game.data.common.TreeDataAnimation;
import electrosphere.renderer.actor.Actor;
/**
@ -104,15 +105,44 @@ public class FirstPersonTree implements BehaviorTree {
}
}
/**
* Plays an animation if it exists
* @param animationName the name of the animation
*/
public void playAnimation(TreeDataAnimation animation){
if(Globals.firstPersonEntity != null){
Actor actor = EntityUtils.getActor(Globals.firstPersonEntity);
if(
(!actor.isPlayingAnimation() || !actor.isPlayingAnimation(animation.getNameFirstPerson())) &&
(Globals.assetManager.fetchModel(actor.getModelPath()) != null && Globals.assetManager.fetchModel(actor.getModelPath()).getAnimation(animation.getNameFirstPerson()) != null)
){
actor.playAnimation(animation, false);
actor.incrementAnimationTime(0.0001);
}
}
}
/**
* If the entity has a first person tree, plays the provided animation
* @param entity The entity
* @param animationName the name of the animation
* @param priority The priority of the animation
*/
public static void conditionallyPlayAnimation(Entity entity, String animationName, int priority){
if(entity != null && FirstPersonTree.hasTree(entity)){
FirstPersonTree.getTree(entity).playAnimation(animationName, priority);
}
}
/**
* If the entity has a first person tree, plays the provided animation
* @param entity The entity
* @param animationName the name of the animation
*/
public static void conditionallyPlayAnimation(Entity entity, TreeDataAnimation animation){
if(entity != null && FirstPersonTree.hasTree(entity)){
FirstPersonTree.getTree(entity).playAnimation(animation);
}
}
}

View File

@ -404,6 +404,9 @@ public class ClientEquipState implements BehaviorTree {
@Override
public void simulate(float deltaTime) {
}

View File

@ -14,7 +14,7 @@ import electrosphere.entity.EntityDataStrings;
import electrosphere.entity.EntityUtils;
import electrosphere.entity.btree.BehaviorTree;
import electrosphere.entity.types.creature.CreatureUtils;
import electrosphere.game.data.creature.type.CreatureType;
import electrosphere.game.data.creature.type.CreatureData;
import electrosphere.game.data.creature.type.IdleData;
import electrosphere.net.synchronization.annotation.SyncedField;
import electrosphere.net.synchronization.annotation.SynchronizableEnum;
@ -49,7 +49,7 @@ public class ClientIdleTree implements BehaviorTree {
state = IdleTreeState.IDLE;
parent = e;
//check if this is a creature, if so add its idle data
CreatureType creatureType = Globals.gameConfigCurrent.getCreatureTypeLoader().getCreature(CreatureUtils.getType(parent));
CreatureData creatureType = Globals.gameConfigCurrent.getCreatureTypeLoader().getCreature(CreatureUtils.getType(parent));
if(creatureType != null){
idleData = creatureType.getIdleData();
}

View File

@ -91,12 +91,12 @@ public class FallTree implements BehaviorTree {
Actor entityActor = EntityUtils.getActor(parent);
if(entityActor != null){
if(
!entityActor.isPlayingAnimation() || !entityActor.isPlayingAnimation(fallMovementSystem.getLandState().getThirdPersonAnimation().getName())
!entityActor.isPlayingAnimation() || !entityActor.isPlayingAnimation(fallMovementSystem.getLandState().getAnimation().getNameThirdPerson())
){
entityActor.playAnimation(fallMovementSystem.getLandState().getThirdPersonAnimation().getName(),AnimationPriorities.LAND);
entityActor.playAnimation(fallMovementSystem.getLandState().getAnimation().getNameThirdPerson(),AnimationPriorities.LAND);
entityActor.incrementAnimationTime(0.0001);
}
FirstPersonTree.conditionallyPlayAnimation(Globals.firstPersonEntity, fallMovementSystem.getLandState().getFirstPersonAnimation().getName(), AnimationPriorities.LAND);
FirstPersonTree.conditionallyPlayAnimation(Globals.firstPersonEntity, fallMovementSystem.getLandState().getAnimation().getNameFirstPerson(), AnimationPriorities.LAND);
}
}
}

View File

@ -60,11 +60,11 @@ public class JumpTree implements BehaviorTree {
switch(state){
case ACTIVE:
if(entityActor != null){
if(!entityActor.isPlayingAnimation() || !entityActor.isPlayingAnimation(jumpData.getAnimationJump().getName())){
entityActor.playAnimation(jumpData.getAnimationJump().getName(),AnimationPriorities.JUMP);
if(!entityActor.isPlayingAnimation() || !entityActor.isPlayingAnimation(jumpData.getAnimationJump().getNameThirdPerson())){
entityActor.playAnimation(jumpData.getAnimationJump().getNameThirdPerson(),AnimationPriorities.JUMP);
entityActor.incrementAnimationTime(0.0001);
}
FirstPersonTree.conditionallyPlayAnimation(Globals.firstPersonEntity, jumpData.getAnimationFirstPersonJump().getName(), AnimationPriorities.JUMP);
FirstPersonTree.conditionallyPlayAnimation(Globals.firstPersonEntity, jumpData.getAnimationFirstPersonJump().getNameFirstPerson(), AnimationPriorities.JUMP);
}
currentFrame++;
currentJumpForce = currentJumpForce * jumpFalloff;

View File

@ -294,7 +294,7 @@ public class ClientGroundMovementTree implements BehaviorTree {
entityActor.playAnimation(animationToPlay,AnimationPriorities.GROUND_MOVE);
entityActor.incrementAnimationTime(0.0001);
}
FirstPersonTree.conditionallyPlayAnimation(Globals.firstPersonEntity, groundMovementData.getAnimationFirstPersonStartup().getName(), AnimationPriorities.GROUND_MOVE);
FirstPersonTree.conditionallyPlayAnimation(Globals.firstPersonEntity, groundMovementData.getAnimationFirstPersonStartup().getNameThirdPerson(), AnimationPriorities.GROUND_MOVE);
}
//run startup code
velocity = velocity + acceleration * (float)Globals.timekeeper.getSimFrameTime();
@ -328,7 +328,7 @@ public class ClientGroundMovementTree implements BehaviorTree {
entityActor.playAnimation(animationToPlay,AnimationPriorities.GROUND_MOVE);
entityActor.incrementAnimationTime(0.0001);
}
FirstPersonTree.conditionallyPlayAnimation(Globals.firstPersonEntity, groundMovementData.getAnimationFirstPersonLoop().getName(), AnimationPriorities.GROUND_MOVE);
FirstPersonTree.conditionallyPlayAnimation(Globals.firstPersonEntity, groundMovementData.getAnimationFirstPersonLoop().getNameThirdPerson(), AnimationPriorities.GROUND_MOVE);
}
if(velocity != maxNaturalVelocity){
velocity = maxNaturalVelocity;
@ -356,7 +356,7 @@ public class ClientGroundMovementTree implements BehaviorTree {
entityActor.playAnimation(animationToPlay,AnimationPriorities.GROUND_MOVE);
entityActor.incrementAnimationTime(0.0001);
}
FirstPersonTree.conditionallyPlayAnimation(Globals.firstPersonEntity, groundMovementData.getAnimationFirstPersonWindDown().getName(), AnimationPriorities.GROUND_MOVE);
FirstPersonTree.conditionallyPlayAnimation(Globals.firstPersonEntity, groundMovementData.getAnimationFirstPersonWindDown().getNameThirdPerson(), AnimationPriorities.GROUND_MOVE);
}
//velocity stuff
velocity = velocity - acceleration * (float)Globals.timekeeper.getSimFrameTime();

View File

@ -46,7 +46,7 @@ import electrosphere.entity.state.rotator.RotatorTree;
import electrosphere.entity.state.rotator.ServerRotatorTree;
import electrosphere.entity.types.collision.CollisionObjUtils;
import electrosphere.game.data.collidable.CollidableTemplate;
import electrosphere.game.data.creature.type.CreatureType;
import electrosphere.game.data.creature.type.CreatureData;
import electrosphere.game.data.creature.type.SprintSystem;
import electrosphere.game.data.creature.type.attack.AttackMove;
import electrosphere.game.data.creature.type.movement.AirplaneMovementSystem;
@ -91,7 +91,7 @@ public class CreatureUtils {
* @return The creature entity
*/
public static Entity clientSpawnBasicCreature(String type, CreatureTemplate template){
CreatureType rawType = Globals.gameConfigCurrent.getCreatureTypeLoader().getCreature(type);
CreatureData rawType = Globals.gameConfigCurrent.getCreatureTypeLoader().getCreature(type);
Entity rVal = EntityCreationUtils.createClientSpatialEntity();
EntityCreationUtils.makeEntityDrawable(rVal, rawType.getModelPath());
Actor creatureActor = EntityUtils.getActor(rVal);
@ -130,26 +130,26 @@ public class CreatureUtils {
GroundMovementSystem groundMovementSystem = (GroundMovementSystem)movementSystem;
ClientGroundMovementTree moveTree = ClientGroundMovementTree.attachTree(rVal, CollisionObjUtils.getCollidable(rVal), groundMovementSystem);
if(groundMovementSystem.getAnimationStartup() != null){
moveTree.setAnimationStartUp(groundMovementSystem.getAnimationStartup().getName());
moveTree.setAnimationStartUp(groundMovementSystem.getAnimationStartup().getNameThirdPerson());
}
if(groundMovementSystem.getAnimationLoop() != null){
moveTree.setAnimationMain(groundMovementSystem.getAnimationLoop().getName());
moveTree.setAnimationMain(groundMovementSystem.getAnimationLoop().getNameThirdPerson());
}
if(groundMovementSystem.getAnimationWindDown()!= null){
moveTree.setAnimationSlowDown(groundMovementSystem.getAnimationWindDown().getName());
moveTree.setAnimationSlowDown(groundMovementSystem.getAnimationWindDown().getNameThirdPerson());
}
//sprint system
if(groundMovementSystem.getSprintSystem() != null){
SprintSystem sprintSystem = groundMovementSystem.getSprintSystem();
SprintTree sprintTree = new SprintTree(rVal,sprintSystem.getMaxVelocity(),sprintSystem.getStaminaMax());
if(sprintSystem.getAnimationStartUp()!= null){
moveTree.setAnimationSprintStartUp(sprintSystem.getAnimationStartUp().getName());
moveTree.setAnimationSprintStartUp(sprintSystem.getAnimationStartUp().getNameThirdPerson());
}
if(sprintSystem.getAnimationMain()!= null){
moveTree.setAnimationSprint(sprintSystem.getAnimationMain().getName());
moveTree.setAnimationSprint(sprintSystem.getAnimationMain().getNameThirdPerson());
}
if(sprintSystem.getAnimationWindDown()!= null){
moveTree.setAnimationSprintWindDown(sprintSystem.getAnimationWindDown().getName());
moveTree.setAnimationSprintWindDown(sprintSystem.getAnimationWindDown().getNameThirdPerson());
}
sprintTree.setGroundMovementTree(moveTree);
moveTree.setSprintTree(sprintTree);
@ -172,7 +172,7 @@ public class CreatureUtils {
JumpMovementSystem jumpMovementSystem = (JumpMovementSystem)movementSystem;
JumpTree jumpTree = new JumpTree(rVal, jumpMovementSystem.getJumpFrames(), jumpMovementSystem.getJumpForce(), jumpMovementSystem);
if(jumpMovementSystem.getAnimationJump() != null){
jumpTree.setAnimationJump(jumpMovementSystem.getAnimationJump().getName());
jumpTree.setAnimationJump(jumpMovementSystem.getAnimationJump().getNameThirdPerson());
}
if(CreatureUtils.clientGetEntityMovementTree(rVal) != null && CreatureUtils.clientGetEntityMovementTree(rVal) instanceof ClientGroundMovementTree){
((ClientGroundMovementTree)CreatureUtils.clientGetEntityMovementTree(rVal)).setClientJumpTree(jumpTree);
@ -384,7 +384,7 @@ public class CreatureUtils {
* @return The creature entity
*/
public static Entity serverSpawnBasicCreature(Realm realm, Vector3d position, String type, CreatureTemplate template){
CreatureType rawType = Globals.gameConfigCurrent.getCreatureTypeLoader().getCreature(type);
CreatureData rawType = Globals.gameConfigCurrent.getCreatureTypeLoader().getCreature(type);
Entity rVal = EntityCreationUtils.createServerEntity(realm, position);
EntityCreationUtils.makeEntityPoseable(rVal, rawType.getModelPath());
@ -417,26 +417,26 @@ public class CreatureUtils {
GroundMovementSystem groundMovementSystem = (GroundMovementSystem)movementSystem;
ServerGroundMovementTree moveTree = ServerGroundMovementTree.attachTree(rVal,CollisionObjUtils.getCollidable(rVal));
if(groundMovementSystem.getAnimationStartup() != null){
moveTree.setAnimationStartUp(groundMovementSystem.getAnimationStartup().getName());
moveTree.setAnimationStartUp(groundMovementSystem.getAnimationStartup().getNameThirdPerson());
}
if(groundMovementSystem.getAnimationLoop() != null){
moveTree.setAnimationMain(groundMovementSystem.getAnimationLoop().getName());
moveTree.setAnimationMain(groundMovementSystem.getAnimationLoop().getNameThirdPerson());
}
if(groundMovementSystem.getAnimationWindDown()!= null){
moveTree.setAnimationSlowDown(groundMovementSystem.getAnimationWindDown().getName());
moveTree.setAnimationSlowDown(groundMovementSystem.getAnimationWindDown().getNameThirdPerson());
}
//sprint system
if(groundMovementSystem.getSprintSystem() != null){
SprintSystem sprintSystem = groundMovementSystem.getSprintSystem();
ServerSprintTree sprintTree = new ServerSprintTree(rVal,sprintSystem.getMaxVelocity(),sprintSystem.getStaminaMax());
if(sprintSystem.getAnimationStartUp()!= null){
moveTree.setAnimationSprintStartUp(sprintSystem.getAnimationStartUp().getName());
moveTree.setAnimationSprintStartUp(sprintSystem.getAnimationStartUp().getNameThirdPerson());
}
if(sprintSystem.getAnimationMain()!= null){
moveTree.setAnimationSprint(sprintSystem.getAnimationMain().getName());
moveTree.setAnimationSprint(sprintSystem.getAnimationMain().getNameThirdPerson());
}
if(sprintSystem.getAnimationWindDown()!= null){
moveTree.setAnimationSprintWindDown(sprintSystem.getAnimationWindDown().getName());
moveTree.setAnimationSprintWindDown(sprintSystem.getAnimationWindDown().getNameThirdPerson());
}
sprintTree.setServerGroundMovementTree(moveTree);
moveTree.setServerSprintTree(sprintTree);
@ -459,7 +459,7 @@ public class CreatureUtils {
JumpMovementSystem jumpMovementSystem = (JumpMovementSystem)movementSystem;
ServerJumpTree jumpTree = new ServerJumpTree(rVal, jumpMovementSystem.getJumpFrames(), jumpMovementSystem.getJumpForce());
if(jumpMovementSystem.getAnimationJump() != null){
jumpTree.setAnimationJump(jumpMovementSystem.getAnimationJump().getName());
jumpTree.setAnimationJump(jumpMovementSystem.getAnimationJump().getNameThirdPerson());
}
if(CreatureUtils.serverGetEntityMovementTree(rVal) != null && CreatureUtils.serverGetEntityMovementTree(rVal) instanceof ClientGroundMovementTree){
((ServerGroundMovementTree)CreatureUtils.serverGetEntityMovementTree(rVal)).setServerJumpTree(jumpTree);

View File

@ -3,7 +3,7 @@ package electrosphere.game.data;
import java.util.LinkedList;
import java.util.List;
import electrosphere.game.data.creature.type.CreatureType;
import electrosphere.game.data.creature.type.CreatureData;
import electrosphere.game.data.creature.type.CreatureTypeLoader;
import electrosphere.game.data.creature.type.attack.AttackMoveResolver;
import electrosphere.game.data.creature.type.model.CreatureTypeMap;
@ -57,6 +57,11 @@ public class Config {
config.projectileTypeHolder = FileUtils.loadObjectFromAssetPath("Data/projectile.json", ProjectileTypeHolder.class);
config.hintData = FileUtils.loadObjectFromAssetPath("Data/tutorial/hints.json", HintDefinition.class);
config.projectileTypeHolder.init();
//validate
ConfigValidator.valdiate(config);
return config;
}
@ -65,17 +70,17 @@ public class Config {
* @param filename The filename
* @return The list of creatures in the file
*/
static List<CreatureType> readCreatureTypeFile(String filename){
List<CreatureType> typeList = new LinkedList<CreatureType>();
static List<CreatureData> readCreatureTypeFile(String filename){
List<CreatureData> typeList = new LinkedList<CreatureData>();
CreatureTypeMap typeMap = FileUtils.loadObjectFromAssetPath(filename, CreatureTypeMap.class);
//push the types from this file
for(CreatureType type : typeMap.getCreatures()){
for(CreatureData type : typeMap.getCreatures()){
typeList.add(type);
}
//push types from any other files
for(String filepath : typeMap.getFiles()){
List<CreatureType> parsedTypeList = readCreatureTypeFile(filepath);
for(CreatureType type : parsedTypeList){
List<CreatureData> parsedTypeList = readCreatureTypeFile(filepath);
for(CreatureData type : parsedTypeList){
typeList.add(type);
}
}
@ -89,8 +94,8 @@ public class Config {
*/
static CreatureTypeLoader loadCreatureTypes(String initialPath) {
CreatureTypeLoader loader = new CreatureTypeLoader();
List<CreatureType> typeList = readCreatureTypeFile(initialPath);
for(CreatureType type : typeList){
List<CreatureData> typeList = readCreatureTypeFile(initialPath);
for(CreatureData type : typeList){
if(type.getAttackMoves() != null){
type.setAttackMoveResolver(new AttackMoveResolver(type.getAttackMoves()));
}

View File

@ -0,0 +1,24 @@
package electrosphere.game.data;
import electrosphere.game.data.creature.type.CreatureData;
import electrosphere.game.data.creature.type.CreatureDataValidator;
import electrosphere.game.data.creature.type.CreatureTypeLoader;
/**
* Used to validate the config
*/
public class ConfigValidator {
/**
* Validates a config
* @param config The config
*/
public static void valdiate(Config config){
//validate the creatures
CreatureTypeLoader creatureTypeLoader = config.getCreatureTypeLoader();
for(CreatureData creatureData : creatureTypeLoader.getCreatures()){
CreatureDataValidator.validate(creatureData);
}
}
}

View File

@ -1,14 +1,21 @@
package electrosphere.game.data.common;
import java.util.List;
/**
* Data about an animation
*/
public class TreeDataAnimation {
/**
* The name of the animation if it exists, null otherwise
* The name of the animation to play in third person if it exists, null otherwise
*/
String name;
String nameThirdPerson;
/**
* The name of the animation to play in first person if it exists, null otherwise
*/
String nameFirstPerson;
/**
* The length of the animation in frames if it exists, null otherwise
@ -26,11 +33,24 @@ public class TreeDataAnimation {
Integer priority;
/**
* Gets the name of the animation
* @return The name of the animation
* The list of bone groups this animation applies to
*/
public String getName() {
return name;
List<String> boneGroups;
/**
* Gets the name of the animation to play in third person
* @return The name of the animation to play in third person
*/
public String getNameThirdPerson() {
return nameThirdPerson;
}
/**
* Gets the name of the animation to play in first person
* @return The name of the animation to play in first person
*/
public String getNameFirstPerson() {
return nameFirstPerson;
}
/**
@ -56,5 +76,13 @@ public class TreeDataAnimation {
public Integer getPriority(){
return priority;
}
/**
* Gets the bone groups this animation applies to
* @return The list of bone groups this animation applies to
*/
public List<String> getBoneGroups(){
return boneGroups;
}
}

View File

@ -6,14 +6,9 @@ package electrosphere.game.data.common;
public class TreeDataState {
/**
* The animation to play for the tree's state when in first person
* The animation to play for the tree's state
*/
TreeDataAnimation firstPersonAnimation;
/**
* The animation to play for the tree's state when in third person
*/
TreeDataAnimation thirdPersonAnimation;
TreeDataAnimation animation;
/**
* The audio to play when running this state of the tree
@ -21,19 +16,11 @@ public class TreeDataState {
TreeDataAudio audioData;
/**
* Gets the first person animation data
* @return The first person animation data if it exists, null otherwise
* Gets the animation data
* @return The animation data if it exists, null otherwise
*/
public TreeDataAnimation getFirstPersonAnimation(){
return firstPersonAnimation;
}
/**
* Gets the third person animation data
* @return The third person animation data if it exists, null otherwise
*/
public TreeDataAnimation getThirdPersonAnimation(){
return thirdPersonAnimation;
public TreeDataAnimation getAnimation(){
return animation;
}
/**

View File

@ -17,7 +17,7 @@ import java.util.List;
/**
* A given type of creature
*/
public class CreatureType {
public class CreatureData {
/**
* The id of the creature

View File

@ -0,0 +1,71 @@
package electrosphere.game.data.creature.type;
import java.util.LinkedList;
import java.util.List;
import electrosphere.game.data.creature.type.bonegroups.BoneGroup;
import electrosphere.logger.LoggerInterface;
/**
* Validates a creature
*/
public class CreatureDataValidator {
/**
* Validates a creature's data
* @param data The creature's data
*/
public static void validate(CreatureData data){
CreatureDataValidator.validateBoneGroups(data);
}
/**
* Validates the bone groups
* @param data The creature data
*/
static void validateBoneGroups(CreatureData data){
List<String> bonesUsedFirstPerson = new LinkedList<String>();
List<String> bonesUsedThirdPerson = new LinkedList<String>();
List<BoneGroup> boneGroups = data.getBoneGroups();
if(boneGroups != null){
for(BoneGroup group : boneGroups){
//check first person bones
if(group.getBoneNamesFirstPerson() != null){
for(String boneName : group.getBoneNamesFirstPerson()){
if(bonesUsedFirstPerson.contains(boneName)){
//same bone used in multiple groups
String message = "Two bone groups have the same bone in them!\n" +
"Bone name: " + boneName + "\n" +
"Second group: " + group.getId() + "\n" +
"Creature name: " + data.getCreatureId()
;
LoggerInterface.loggerEngine.WARNING(message);
} else {
bonesUsedFirstPerson.add(boneName);
}
}
}
//check third person bones
if(group.getBoneNamesThirdPerson() != null){
for(String boneName : group.getBoneNamesThirdPerson()){
if(bonesUsedThirdPerson.contains(boneName)){
//same bone used in multiple groups
String message = "Two bone groups have the same bone in them!\n" +
"Bone name: " + boneName + "\n" +
"Second group: " + group.getId() + "\n" +
"Creature name: " + data.getCreatureId()
;
LoggerInterface.loggerEngine.WARNING(message);
} else {
bonesUsedThirdPerson.add(boneName);
}
}
}
}
}
}
}

View File

@ -7,23 +7,49 @@ import java.util.List;
import java.util.Map;
import java.util.concurrent.Semaphore;
/**
* The creature type loader
*/
public class CreatureTypeLoader {
Map<String,CreatureType> creatureMap = new HashMap<String,CreatureType>();
/**
* The map of creature name -> creature data
*/
Map<String,CreatureData> creatureMap = new HashMap<String,CreatureData>();
/**
* The list of playable races
*/
List<String> playableRaceNames = new LinkedList<String>();
/**
* The lock on playable races
*/
Semaphore playableRaceLock = new Semaphore(1);
public void putCreature(String name, CreatureType type){
/**
* Adds creature data to the loader
* @param name The name of the creature
* @param type The creature data
*/
public void putCreature(String name, CreatureData type){
creatureMap.put(name,type);
}
/**
* Adds a playable race to the loader
* @param name The race name
*/
public void putPlayableRace(String name){
playableRaceNames.add(name);
}
public CreatureType getCreature(String name){
/**
* Gets creature data from the name of a creature
* @param name The name of the creature
* @return The creature data if it exists, null otherwise
*/
public CreatureData getCreature(String name){
return creatureMap.get(name);
}
@ -31,10 +57,14 @@ public class CreatureTypeLoader {
* Gets the collection of all creature data
* @return the collection of all creature data
*/
public Collection<CreatureType> getCreatures(){
public Collection<CreatureData> getCreatures(){
return creatureMap.values();
}
/**
* Gets the list of playable races
* @return The list of playable race names
*/
public List<String> getPlayableRaces(){
List<String> races = null;
playableRaceLock.acquireUninterruptibly();
@ -43,10 +73,17 @@ public class CreatureTypeLoader {
return races;
}
/**
* Clears the playable race list
*/
public void clearPlayableRaces(){
playableRaceNames.clear();
}
/**
* Loads the list of playable races
* @param races The list of playable races
*/
public void loadPlayableRaces(List<String> races){
playableRaceLock.acquireUninterruptibly();
playableRaceNames = races;

View File

@ -13,9 +13,14 @@ public class BoneGroup {
String id;
/**
* The list of names of bones that are within this group
* The list of names of bones that are within this group for the third person model
*/
List<String> boneNames;
List<String> boneNamesThirdPerson;
/**
* The list of names of bones that are within this group for the first person model
*/
List<String> boneNamesFirstPerson;
/**
* Gets the id of the bone group
@ -26,11 +31,19 @@ public class BoneGroup {
}
/**
* Gets the list of names of bones in the group
* Gets the list of names of bones in the group on the third person model
* @return The list of names of bones
*/
public List<String> getBoneNames(){
return boneNames;
public List<String> getBoneNamesThirdPerson(){
return boneNamesThirdPerson;
}
/**
* Gets the list of names of bones in the group on the first person model
* @return The list of names of bones
*/
public List<String> getBoneNamesFirstPerson(){
return boneNamesFirstPerson;
}
}

View File

@ -2,6 +2,8 @@ package electrosphere.game.data.creature.type.equip;
import java.util.List;
import electrosphere.game.data.common.TreeDataAnimation;
/**
* A portion of the creature that can have an item attached to it
*/
@ -9,23 +11,34 @@ public class EquipPoint {
//the id of the equip point
String equipPointId;
//the bone that can have the item attached to it (may not be defined depending on the type of equip point (think legs))
String bone;
//the bone to attach items to for the first person viewmodel (may not be defined based on the viewmodel)
String firstPersonBone;
//the offset to apply to items that are attached to the bone
List<Float> offsetVectorThirdPerson;
//the offset to apply to items that are attached to the bone
List<Float> offsetVectorFirstPerson;
//the rotation to apply to the items that are attached to the bone
List<Float> offsetRotationThirdPerson;
//the rotation to apply to the items that are attached to the view model's bone
List<Float> offsetRotationFirstPerson;
//signals that this equip point can block
boolean canBlock;
//the equip classes that are whitelisted for this equip point
List<String> equipClassWhitelist;
//The animation to play when this equip point has an item equipped (ie if a hand is grasping something)
TreeDataAnimation equippedAnimation;
/**
* Gets the equip point id
* @return the id of the equip point
@ -131,5 +144,13 @@ public class EquipPoint {
public List<String> getEquipClassWhitelist(){
return equipClassWhitelist;
}
/**
* Gets the animation to play when this point has an item equipped
* @return The animation if it exists, null otherwise
*/
public TreeDataAnimation getEquippedAnimation(){
return equippedAnimation;
}
}

View File

@ -1,14 +1,14 @@
package electrosphere.game.data.creature.type.model;
import electrosphere.game.data.creature.type.CreatureType;
import electrosphere.game.data.creature.type.CreatureData;
import java.util.List;
public class CreatureTypeMap {
List<CreatureType> creatures;
List<CreatureData> creatures;
List<String> files;
public List<CreatureType> getCreatures(){
public List<CreatureData> getCreatures(){
return creatures;
}

View File

@ -9,7 +9,7 @@ import electrosphere.entity.Entity;
import electrosphere.entity.EntityDataStrings;
import electrosphere.entity.EntityUtils;
import electrosphere.entity.types.creature.CreatureUtils;
import electrosphere.game.data.creature.type.CreatureType;
import electrosphere.game.data.creature.type.CreatureData;
import electrosphere.game.data.creature.type.visualattribute.VisualAttribute;
import electrosphere.menu.WindowStrings;
import electrosphere.menu.WindowUtils;
@ -376,7 +376,7 @@ public class MenuGeneratorsInGame {
Entity playerEntity = Globals.playerEntity;
Actor playerActor = EntityUtils.getActor(playerEntity);
ActorStaticMorph staticMorph = playerActor.getStaticMorph();
CreatureType playeCreatureType = Globals.gameConfigCurrent.getCreatureTypeLoader().getCreature(CreatureUtils.getType(playerEntity));
CreatureData playeCreatureType = Globals.gameConfigCurrent.getCreatureTypeLoader().getCreature(CreatureUtils.getType(playerEntity));
int offset = 0;
for(VisualAttribute attribute : playeCreatureType.getVisualAttributes()){
int posY = offset * 350 + 100;

View File

@ -13,7 +13,7 @@ import electrosphere.entity.types.creature.CreatureUtils;
import electrosphere.entity.types.foliage.FoliageUtils;
import electrosphere.entity.types.item.ItemUtils;
import electrosphere.entity.types.object.ObjectUtils;
import electrosphere.game.data.creature.type.CreatureType;
import electrosphere.game.data.creature.type.CreatureData;
import electrosphere.game.data.foliage.type.FoliageType;
import electrosphere.game.data.item.type.Item;
import electrosphere.game.data.object.type.ObjectData;
@ -159,7 +159,7 @@ public class MenuGeneratorsLevelEditor {
}));
//button for spawning all creatures
for(CreatureType data : Globals.gameConfigCurrent.getCreatureTypeLoader().getCreatures()){
for(CreatureData data : Globals.gameConfigCurrent.getCreatureTypeLoader().getCreatures()){
//spawn creature button
scrollable.addChild(Button.createButton("Spawn " + data.getCreatureId(), () -> {
LoggerInterface.loggerEngine.INFO("spawn " + data.getCreatureId() + "!");

View File

@ -8,7 +8,7 @@ import org.joml.Vector3f;
import electrosphere.engine.Globals;
import electrosphere.entity.types.camera.CameraEntityUtils;
import electrosphere.entity.types.creature.CreatureTemplate;
import electrosphere.game.data.creature.type.CreatureType;
import electrosphere.game.data.creature.type.CreatureData;
import electrosphere.game.data.creature.type.visualattribute.AttributeVariant;
import electrosphere.game.data.creature.type.visualattribute.VisualAttribute;
import electrosphere.menu.MenuGenerators;
@ -87,7 +87,7 @@ public class MenuGeneratorsMultiplayer {
int horizontalPosition = 300;
//figure out race data
CreatureType selectedRaceType = Globals.gameConfigCurrent.getCreatureTypeLoader().getCreature(race);
CreatureData selectedRaceType = Globals.gameConfigCurrent.getCreatureTypeLoader().getCreature(race);
//spawn camera so renderer doesn't crash (once render pipeline is modularized this shouldn't be necessary)
Globals.playerCamera = CameraEntityUtils.spawnBasicCameraEntity(new Vector3f(0,0,0), new Vector3f(0,0.3f,1).normalize());

View File

@ -16,7 +16,7 @@ import electrosphere.entity.types.creature.CreatureUtils;
import electrosphere.entity.types.foliage.FoliageUtils;
import electrosphere.entity.types.item.ItemUtils;
import electrosphere.entity.types.object.ObjectUtils;
import electrosphere.game.data.creature.type.CreatureType;
import electrosphere.game.data.creature.type.CreatureData;
import electrosphere.game.data.creature.type.ViewModelData;
import electrosphere.logger.LoggerInterface;
import electrosphere.net.parser.net.message.EntityMessage;
@ -169,7 +169,7 @@ public class EntityProtocol {
if(target != null){
CreatureUtils.setControllerPlayerId(target, message.getpropertyValue());
String creatureTypeRaw = CreatureUtils.getType(target);
CreatureType creatureType = Globals.gameConfigCurrent.getCreatureTypeLoader().getCreature(creatureTypeRaw);
CreatureData creatureType = Globals.gameConfigCurrent.getCreatureTypeLoader().getCreature(creatureTypeRaw);
ViewModelData viewModelData = creatureType.getViewModelData();
if(Globals.clientPlayer != null && message.getpropertyValue() == Globals.clientPlayer.getId()){
Globals.clientCharacterID = message.getentityID();

View File

@ -1,6 +1,8 @@
package electrosphere.renderer.actor;
import electrosphere.engine.Globals;
import electrosphere.entity.state.AnimationPriorities;
import electrosphere.game.data.common.TreeDataAnimation;
import electrosphere.renderer.OpenGLState;
import electrosphere.renderer.RenderPipelineState;
import electrosphere.renderer.model.Bone;
@ -125,6 +127,11 @@ public class Actor {
}
}
/**
* 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){
// animationTime = 0;
// playingAnimation = true;
@ -150,6 +157,81 @@ public class Actor {
}
}
/**
* 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.DEFAULT;
if(animation.getPriority() != null){
priority = animation.getPriority();
}
//Gets the mask
List<String> boneMask = null;
if(animation.getBoneGroups() != null){
boneMask = new LinkedList<String>();
}
Model model = Globals.assetManager.fetchModel(modelPath);
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
ActorAnimationMask animMask;
if(boneMask == null){
animMask = new ActorAnimationMask(
priority,
animationName,
length
);
} else {
animMask = new ActorAnimationMask(
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(ActorAnimationMask currentMask : animationQueue){
if(currentMask.getPriority() == animMask.getPriority()){
toRemoveMasks.add(currentMask);
break;
}
}
for(ActorAnimationMask currentMask : toRemoveMasks){
animationQueue.remove(currentMask);
}
animationQueue.add(animMask);
}
}
public void playAnimationWithMask(String animationName, int priority, List<String> boneMask){
Model model = Globals.assetManager.fetchModel(modelPath);
if(model != null){

View File

@ -3,14 +3,34 @@ package electrosphere.renderer.actor;
import java.util.LinkedList;
import java.util.List;
/**
* An animation mask. Combines an animation name, priority, and a list of bones to apply that animation to
*/
public class ActorAnimationMask implements Comparable<ActorAnimationMask> {
//The priority of the mask
int priority;
//The name of the animation
String animationName;
//The current time of this mask
double time;
//The maximum time to play this mask for
double timeMax;
//The mask of bones to apply this animation to
List<String> boneMask;
/**
* Constructor
* @param priority
* @param animationName
* @param time
* @param timeMax
* @param boneMask
*/
public ActorAnimationMask(int priority, String animationName, double time, double timeMax, List<String> boneMask){
this.priority = priority;
this.animationName = animationName;
@ -19,34 +39,93 @@ public class ActorAnimationMask implements Comparable<ActorAnimationMask> {
this.boneMask = boneMask;
}
/**
* Constructor
* @param priority
* @param animationName
* @param timeMax
* @param boneMask
*/
public ActorAnimationMask(int priority, String animationName, double timeMax, List<String> boneMask){
this.priority = priority;
this.animationName = animationName;
this.timeMax = timeMax;
this.boneMask = boneMask;
}
/**
* Constructor
* @param priority
* @param animationName
* @param time
* @param timeMax
*/
public ActorAnimationMask(int priority, String animationName, double time, double timeMax){
this(priority, animationName, time, timeMax, new LinkedList<String>());
}
/**
* Constructor
* @param priority
* @param animationName
* @param timeMax
*/
public ActorAnimationMask(int priority, String animationName, double timeMax){
this(priority, animationName, 0, timeMax, new LinkedList<String>());
}
/**
* Adds a bone to the mask
* @param boneName The name of the bone
*/
public void addBone(String boneName){
boneMask.add(boneName);
}
/**
* Gets the list of bones this mask applies to
* @return The list of bones
*/
public List<String> getBones(){
return boneMask;
}
/**
* Gets the name of the animation this mask uses
* @return The name of the animation
*/
public String getAnimationName(){
return animationName;
}
/**
* Gets the priority of the mask
* @return The priority
*/
public int getPriority(){
return priority;
}
/**
* Gets the time of the mask
* @return The time
*/
public double getTime(){
return time;
}
/**
* Sets the time of this mask
* @param time The time
*/
public void setTime(double time){
this.time = time;
}
/**
* Gets the duration of the mask
* @return The duration
*/
public double getDuration(){
return timeMax;
}

View File

@ -14,6 +14,8 @@ import org.joml.Vector3f;
import org.joml.Vector4d;
import electrosphere.engine.Globals;
import electrosphere.entity.state.AnimationPriorities;
import electrosphere.game.data.common.TreeDataAnimation;
import electrosphere.renderer.actor.ActorAnimationMask;
import electrosphere.renderer.actor.ActorBoneRotator;
import electrosphere.renderer.actor.ActorStaticMorph;
@ -143,6 +145,81 @@ public class PoseActor {
}
}
/**
* 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.DEFAULT;
if(animation.getPriority() != null){
priority = animation.getPriority();
}
//Gets the mask
List<String> boneMask = null;
if(animation.getBoneGroups() != null){
boneMask = new LinkedList<String>();
}
PoseModel model = Globals.assetManager.fetchPoseModel(modelPath);
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
ActorAnimationMask animMask;
if(boneMask == null){
animMask = new ActorAnimationMask(
priority,
animationName,
length
);
} else {
animMask = new ActorAnimationMask(
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(ActorAnimationMask currentMask : animationQueue){
if(currentMask.getPriority() == animMask.getPriority()){
toRemoveMasks.add(currentMask);
break;
}
}
for(ActorAnimationMask currentMask : toRemoveMasks){
animationQueue.remove(currentMask);
}
animationQueue.add(animMask);
}
}
/**
* Play an animation with a mask that makes the animation only apply to specific bones
* @param animationName The name of the animation

View File

@ -211,4 +211,12 @@ public class PoseModel {
return animMap.get(animName);
}
/**
* Gets the list of bones in this pose model
* @return The list of bones
*/
public List<Bone> getBones(){
return this.bones;
}
}