properly leverage animation masks
Some checks failed
studiorailgun/Renderer/pipeline/head There was a failure building this commit

This commit is contained in:
austin 2024-07-28 16:56:58 -04:00
parent 126a8f79c8
commit 4b0064b761
13 changed files with 212 additions and 157 deletions

View File

@ -299,8 +299,12 @@
"variants": [
{
"variantId": "blockWeaponRight",
"mainAnimation" : "HoldItemR2HBlock",
"mainFirstPersonAnimation" : "HoldItemR2HBlock",
"mainAnimation" : {
"nameThirdPerson": "HoldItemR2HBlock",
"nameFirstPerson": "HoldItemR2HBlock",
"priorityCategory": "MOVEMENT_MODIFIER",
"boneGroups" : ["armLeft", "armRight", "handLeft", "handRight"]
},
"defaults" : [
{
"equipPoint" : "handRight",

View File

@ -244,7 +244,7 @@ public class Main {
try {
Globals.profiler.beginRootCpuSample("frame");
LoggerInterface.loggerEngine.DEBUG("Begin Main Loop Frame");
LoggerInterface.loggerEngine.DEBUG_LOOP("Begin Main Loop Frame");
//
//Update timekeeper
@ -258,7 +258,7 @@ public class Main {
///
if(Globals.RUN_CLIENT){
Globals.profiler.beginCpuSample("Load Assets");
LoggerInterface.loggerEngine.DEBUG("Begin load assets");
LoggerInterface.loggerEngine.DEBUG_LOOP("Begin load assets");
Globals.assetManager.loadAssetsInQueue();
Globals.profiler.endCpuSample();
}
@ -272,7 +272,7 @@ public class Main {
//Why is this its own function? Just to get the networking code out of main()
if(Globals.clientConnection != null){
Globals.profiler.beginCpuSample("Client networking");
LoggerInterface.loggerEngine.DEBUG("Begin parse client messages");
LoggerInterface.loggerEngine.DEBUG_LOOP("Begin parse client messages");
Globals.clientConnection.parseMessages();
Globals.profiler.endCpuSample();
}
@ -285,7 +285,7 @@ public class Main {
//Poll controls
if(Globals.RUN_CLIENT){
Globals.profiler.beginCpuSample("Poll Controls");
LoggerInterface.loggerEngine.DEBUG("Begin recapture screen");
LoggerInterface.loggerEngine.DEBUG_LOOP("Begin recapture screen");
Globals.controlHandler.pollControls();
RenderingEngine.recaptureIfNecessary();
Globals.profiler.endCpuSample();
@ -312,7 +312,7 @@ public class Main {
///
/// C L I E N T S I M U L A T I O N S T U F F
///
LoggerInterface.loggerEngine.DEBUG("Begin client simulation");
LoggerInterface.loggerEngine.DEBUG_LOOP("Begin client simulation");
if(Globals.clientSimulation != null){
Globals.profiler.beginCpuSample("Client simulation");
Globals.clientSimulation.simulate();
@ -343,7 +343,7 @@ public class Main {
///
/// M A I N R E N D E R F U N C T I O N
///
LoggerInterface.loggerEngine.DEBUG("Begin rendering call");
LoggerInterface.loggerEngine.DEBUG_LOOP("Begin rendering call");
if(Globals.RUN_CLIENT && !Globals.HEADLESS){
Globals.profiler.beginCpuSample("render");
Globals.renderingEngine.drawScreen();
@ -404,7 +404,7 @@ public class Main {
//
// End main loop
//
LoggerInterface.loggerEngine.DEBUG("End Main Loop Frame");
LoggerInterface.loggerEngine.DEBUG_LOOP("End Main Loop Frame");
Globals.profiler.endCpuSample();
} catch (NullPointerException ex){

View File

@ -6,6 +6,7 @@ import electrosphere.audio.VirtualAudioSourceManager.VirtualAudioSourceType;
import electrosphere.engine.Globals;
import electrosphere.entity.Entity;
import electrosphere.entity.EntityUtils;
import electrosphere.entity.state.AnimationPriorities;
import electrosphere.entity.state.client.firstPerson.FirstPersonTree;
import electrosphere.game.data.common.TreeDataAnimation;
import electrosphere.game.data.common.TreeDataAudio;
@ -101,23 +102,21 @@ public class StateTransitionUtil {
private static void simulateClientState(Entity parent, StateTransitionUtilItem state){
Actor actor = EntityUtils.getActor(parent);
if(actor != null){
//determine the third person animation to play
String thirdPersonAnimation = state.getThirdPersonAnimation();
//determine the first person animation to play
String firstPersonAnimation = state.getFirstPersonAnimation();
//get the animation to play
TreeDataAnimation animation = state.animation;
if(state.getAnimation != null && state.getAnimation.get() != null){
animation = state.getAnimation.get();
}
//Main simulation
if(!actor.isPlayingAnimation() && state.onComplete != null && state.startedAnimation == true && thirdPersonAnimation != null){
if(!actor.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(thirdPersonAnimation)){
} else if(!actor.isPlayingAnimation() || !actor.isPlayingAnimation(animation)){
//play animation, audio, etc, for state
if(parent == Globals.playerEntity && !Globals.controlHandler.cameraIsThirdPerson() && thirdPersonAnimation != null){
if(parent == Globals.playerEntity && !Globals.controlHandler.cameraIsThirdPerson() && animation != null){
//first person
//play first person audio
if(state.audioData != null && state.audioData.getAudioPath() != null){
@ -130,21 +129,17 @@ public class StateTransitionUtil {
}
}
if(state.animation == null){
actor.playAnimation(firstPersonAnimation, state.getAnimationPriority());
} else {
actor.playAnimation(state.animation,true);
if(animation != null){
actor.playAnimation(animation,true);
}
actor.incrementAnimationTime(0.0001);
state.startedAnimation = true;
} else if(thirdPersonAnimation == null && state.onComplete != null){
} else if(state.animation == null && state.onComplete != null){
state.onComplete.run();
state.startedAnimation = false;
}
if(state.animation == null){
FirstPersonTree.conditionallyPlayAnimation(Globals.firstPersonEntity, firstPersonAnimation, state.getAnimationPriority());
} else if(firstPersonAnimation != null){
FirstPersonTree.conditionallyPlayAnimation(Globals.firstPersonEntity, state.animation);
if(animation != null){
FirstPersonTree.conditionallyPlayAnimation(Globals.firstPersonEntity, animation);
}
}
}
@ -157,25 +152,24 @@ public class StateTransitionUtil {
private static void simulateServerState(Entity parent, StateTransitionUtilItem state){
PoseActor poseActor = EntityUtils.getPoseActor(parent);
if(poseActor != null){
//determine the third person animation to play
String thirdPersonAnimation = state.getThirdPersonAnimation();
//get the animation to play
TreeDataAnimation animation = state.animation;
if(state.getAnimation != null && state.getAnimation.get() != null){
animation = state.getAnimation.get();
}
//Main simulation
if(!poseActor.isPlayingAnimation() && state.onComplete != null && state.startedAnimation == true && thirdPersonAnimation != null){
if(!poseActor.isPlayingAnimation() && state.onComplete != null && state.startedAnimation == true && animation != null){
//state transition if this isn't set to loop
state.onComplete.run();
state.startedAnimation = false;
} else if(thirdPersonAnimation != null && (!poseActor.isPlayingAnimation() || !poseActor.isPlayingAnimation(thirdPersonAnimation))){
} else if(state.animation != null && (!poseActor.isPlayingAnimation() || !poseActor.isPlayingAnimation(animation))){
//play animation for state
if(state.animation == null){
poseActor.playAnimation(thirdPersonAnimation, state.getAnimationPriority());
} else {
poseActor.playAnimation(state.animation,true);
}
poseActor.playAnimation(animation, true);
poseActor.incrementAnimationTime(0.0001);
state.startedAnimation = true;
} else if(thirdPersonAnimation == null && state.onComplete != null){
} else if(state.animation == null && state.onComplete != null){
state.onComplete.run();
state.startedAnimation = false;
}
@ -190,17 +184,11 @@ public class StateTransitionUtil {
//The enum value for this state
Object stateEnum;
//the priority of this animation in particular
int animPriority;
//The animation to play
TreeDataAnimation animation;
//Gets the first person animation's name
Supplier<String> getFirstPersonAnimation;
//Gets the third person animation's name
Supplier<String> getThirdPersonAnimation;
//Gets the first person animation
Supplier<TreeDataAnimation> getAnimation;
//The audio data
TreeDataAudio audioData;
@ -211,44 +199,17 @@ public class StateTransitionUtil {
//Tracks whether the animation has been played or not
boolean startedAnimation = false;
/**
* Gets the animation to play for third person
* @return The animation's name
*/
String getThirdPersonAnimation(){
String toPlay = null;
if(animation != null){
toPlay = animation.getNameThirdPerson();
}
if(getThirdPersonAnimation != null){
toPlay = getThirdPersonAnimation.get();
}
return toPlay;
}
/**
* Gets the animation to play for first person
* @return The animation's name
*/
String getFirstPersonAnimation(){
String toPlay = null;
if(animation != null){
toPlay = animation.getNameFirstPerson();
}
if(getFirstPersonAnimation != null){
toPlay = getFirstPersonAnimation.get();
}
return toPlay;
}
/**
* Gets the animation priority
* @return The animation priority
*/
int getAnimationPriority(){
int priority = this.animPriority;
int priority = AnimationPriorities.getValue(AnimationPriorities.DEFAULT);
if(animation != null && animation.getPriority() != null){
priority = animation.getPriority();
} else if(getAnimation != null && getAnimation.get().getPriority() != null){
priority = getAnimation.get().getPriority();
}
return priority;
}
@ -273,16 +234,12 @@ public class StateTransitionUtil {
*/
private StateTransitionUtilItem(
Object stateEnum,
int animPriority,
Supplier<String> getFirstPersonAnimation,
Supplier<String> getThirdPersonAnimation,
Supplier<TreeDataAnimation> getAnimation,
TreeDataAudio audioData,
Runnable onComplete
){
this.stateEnum = stateEnum;
this.animPriority = animPriority;
this.getFirstPersonAnimation = getFirstPersonAnimation;
this.getThirdPersonAnimation = getThirdPersonAnimation;
this.getAnimation = getAnimation;
this.audioData = audioData;
this.onComplete = onComplete;
}
@ -292,25 +249,19 @@ public class StateTransitionUtil {
* This decouples the animations from the initialization of the tree.
* The intended usecase is if the animation could change based on some state in the tree.
* @param stateEnum The enum value for this state
* @param animPriority The priority of this state's animations
* @param getFirstPersonAnimation The supplier for a first person animation name. If it is null, it will not play any animation in first person
* @param getThirdPersonAnimation The supplier for a third person animation name. If it is null, it will not play any animation in the third person
* @param getAnimationData The supplier for the animation data. If it is null, it will not play any animation
* @param audioData The path to an audio file to play on starting the animation. If null, no audio will be played
* @param onComplete !!Must transition to the next state!! Fires when the animation completes. If not supplied, animations and autio will loop
*/
public static StateTransitionUtilItem create(
Object stateEnum,
int animPriority,
Supplier<String> getFirstPersonAnimation,
Supplier<String> getThirdPersonAnimation,
Supplier<TreeDataAnimation> getAnimation,
TreeDataAudio audioData,
Runnable onComplete
){
return new StateTransitionUtilItem(
stateEnum,
animPriority,
getFirstPersonAnimation,
getThirdPersonAnimation,
getAnimation,
audioData,
onComplete
);

View File

@ -7,7 +7,6 @@ import electrosphere.entity.EntityDataStrings;
import electrosphere.entity.btree.BehaviorTree;
import electrosphere.entity.btree.StateTransitionUtil;
import electrosphere.entity.btree.StateTransitionUtil.StateTransitionUtilItem;
import electrosphere.entity.state.AnimationPriorities;
import electrosphere.game.data.creature.type.block.BlockSystem;
import electrosphere.net.synchronization.BehaviorTreeIdEnums;
@ -56,24 +55,18 @@ public class ClientBlockTree implements BehaviorTree {
this.stateTransitionUtil = StateTransitionUtil.create(parent, false, new StateTransitionUtilItem[]{
StateTransitionUtilItem.create(
BlockState.WIND_UP,
AnimationPriorities.getValue(AnimationPriorities.MODIFIER_HIGH),
() -> {return this.blockSystem.getBlockVariant(this.currentBlockVariant).getWindUpFirstPersonAnimation();},
() -> {return this.blockSystem.getBlockVariant(this.currentBlockVariant).getWindUpAnimation();},
null,
null
),
StateTransitionUtilItem.create(
BlockState.BLOCKING,
AnimationPriorities.getValue(AnimationPriorities.MODIFIER_HIGH),
() -> {return this.blockSystem.getBlockVariant(this.currentBlockVariant).getMainFirstPersonAnimation();},
() -> {return this.blockSystem.getBlockVariant(this.currentBlockVariant).getMainAnimation();},
null,
null
),
StateTransitionUtilItem.create(
BlockState.COOLDOWN,
AnimationPriorities.getValue(AnimationPriorities.MODIFIER_HIGH),
() -> {return this.blockSystem.getBlockVariant(this.currentBlockVariant).getCooldownFirstPersonAnimation();},
() -> {return this.blockSystem.getBlockVariant(this.currentBlockVariant).getCooldownAnimation();},
null,
null

View File

@ -14,7 +14,6 @@ import electrosphere.server.datacell.utils.ServerBehaviorTreeUtils;
import electrosphere.net.parser.net.message.SynchronizationMessage;
import electrosphere.server.datacell.utils.DataCellSearchUtils;
import electrosphere.entity.state.AnimationPriorities;
import electrosphere.entity.state.block.ClientBlockTree.BlockState;
import electrosphere.game.data.creature.type.block.BlockSystem;
import electrosphere.net.synchronization.annotation.SyncedField;
@ -50,24 +49,18 @@ public class ServerBlockTree implements BehaviorTree {
this.stateTransitionUtil = StateTransitionUtil.create(parent, true, new StateTransitionUtilItem[]{
StateTransitionUtilItem.create(
BlockState.WIND_UP,
AnimationPriorities.getValue(AnimationPriorities.MODIFIER_HIGH),
null,
() -> {return this.blockSystem.getBlockVariant(this.currentBlockVariant).getWindUpAnimation();},
null,
() -> {this.setState(BlockState.BLOCKING);}
),
StateTransitionUtilItem.create(
BlockState.BLOCKING,
AnimationPriorities.getValue(AnimationPriorities.MODIFIER_HIGH),
null,
() -> {return this.blockSystem.getBlockVariant(this.currentBlockVariant).getMainAnimation();},
null,
null
),
StateTransitionUtilItem.create(
BlockState.COOLDOWN,
AnimationPriorities.getValue(AnimationPriorities.MODIFIER_HIGH),
null,
() -> {return this.blockSystem.getBlockVariant(this.currentBlockVariant).getCooldownAnimation();},
null,
() -> {this.setState(BlockState.NOT_BLOCKING);}

View File

@ -18,6 +18,7 @@ import electrosphere.entity.state.attack.ServerAttackTree;
import electrosphere.entity.state.attack.ShooterTree;
import electrosphere.entity.state.block.ClientBlockTree;
import electrosphere.entity.state.block.ServerBlockTree;
import electrosphere.entity.state.client.firstPerson.FirstPersonTree;
import electrosphere.entity.state.equip.ClientEquipState;
import electrosphere.entity.state.equip.ServerEquipState;
import electrosphere.entity.state.gravity.ClientGravityTree;
@ -359,6 +360,10 @@ public class CreatureUtils {
rVal.putData(EntityDataStrings.CLIENT_ROTATOR_TREE, rotatorTree);
Globals.clientScene.registerBehaviorTree(rotatorTree);
}
//bone groups
if(rawType.getBoneGroups() != null){
creatureActor.setBoneGroups(rawType.getBoneGroups());
}
//add health system
if(rawType.getHealthSystem() != null){
ClientLifeTree.attachTree(rVal,rawType.getHealthSystem());
@ -648,6 +653,11 @@ public class CreatureUtils {
ServerBehaviorTreeUtils.attachBTreeToEntity(rVal, rotatorTree);
}
//bone groups
if(rawType.getBoneGroups() != null){
creatureActor.setBoneGroups(rawType.getBoneGroups());
}
///
///
/// AI (This SHOULD only be applied on the server with the way AI architected currently)
@ -681,6 +691,37 @@ public class CreatureUtils {
return rVal;
}
/**
* Creates a viewmodel entity on the client side
* @param type The type of creature
* @param template The template for the creature
* @return The entity
*/
public static Entity clientCreateViewModel(
String type,
CreatureTemplate template
){
CreatureData rawType = Globals.gameConfigCurrent.getCreatureTypeLoader().getCreature(type);
Entity rVal = EntityCreationUtils.createClientSpatialEntity();
if(rawType.getViewModelData() != null){
EntityCreationUtils.makeEntityDrawable(rVal, rawType.getViewModelData().getFirstPersonModelPath());
FirstPersonTree.attachTree(
rVal,
rawType.getViewModelData().getHeightFromOrigin(),
rawType.getViewModelData().getCameraViewDirOffsetY(),
rawType.getViewModelData().getCameraViewDirOffsetZ()
);
}
Actor creatureActor = EntityUtils.getActor(rVal);
if(rawType.getBoneGroups() != null){
creatureActor.setBoneGroups(rawType.getBoneGroups());
}
return rVal;
}
public static void sendEntityToPlayer(Player player, Entity creature){
int id = creature.getId();

View File

@ -2,6 +2,8 @@ package electrosphere.game.data.creature.type.block;
import java.util.List;
import electrosphere.game.data.common.TreeDataAnimation;
/**
* A variant of data that can be loaded into the block system. Variants are for different types of equip states.
* IE: holding just a sword in your right hand will have a different block animation vs a shield in your right
@ -13,22 +15,13 @@ public class BlockVariant {
String variantId;
//the animation to play when winding up
String windUpAnimation;
TreeDataAnimation windUpAnimation;
//the main animation to play while blocking
String mainAnimation;
TreeDataAnimation mainAnimation;
//the animation to play when cooling down
String cooldownAnimation;
//the animation to play in first person when winding up
String windUpFirstPersonAnimation;
//the main animation to play in first person while blocking
String mainFirstPersonAnimation;
//the animation to play in first person when cooling down
String cooldownFirstPersonAnimation;
TreeDataAnimation cooldownAnimation;
//the list of default equipment cases that this variant should be used for
List<VariantDefaults> defaults;
@ -45,7 +38,7 @@ public class BlockVariant {
* The animation to play when winding up
* @return
*/
public String getWindUpAnimation(){
public TreeDataAnimation getWindUpAnimation(){
return windUpAnimation;
}
@ -53,7 +46,7 @@ public class BlockVariant {
* The main animation to play while blocking
* @return
*/
public String getMainAnimation(){
public TreeDataAnimation getMainAnimation(){
return mainAnimation;
}
@ -61,34 +54,10 @@ public class BlockVariant {
* The animation to play when cooling down
* @return
*/
public String getCooldownAnimation(){
public TreeDataAnimation getCooldownAnimation(){
return cooldownAnimation;
}
/**
* The animation to play in first person when winding up
* @return
*/
public String getWindUpFirstPersonAnimation(){
return windUpFirstPersonAnimation;
}
/**
* The main animation to play in first person while blocking
* @return
*/
public String getMainFirstPersonAnimation(){
return mainFirstPersonAnimation;
}
/**
* The animation to play in first person when cooling down
* @return
*/
public String getCooldownFirstPersonAnimation(){
return cooldownFirstPersonAnimation;
}
/**
* the list of default equipment cases that this variant should be used for
* @return

View File

@ -2,7 +2,7 @@ package electrosphere.menu.debug;
import java.util.LinkedList;
import java.util.List;
import java.util.PriorityQueue;
import java.util.Set;
import org.joml.Quaterniond;
import org.joml.Vector3d;
@ -162,7 +162,7 @@ public class ImGuiEntityMacros {
//animation queue
if(ImGui.collapsingHeader("Animation Queue")){
PriorityQueue<ActorAnimationMask> animationQueue = actor.getAnimationQueue();
Set<ActorAnimationMask> animationQueue = actor.getAnimationQueue();
for(ActorAnimationMask mask : animationQueue){
ImGui.text(mask.getAnimationName() + " - " + mask.getPriority());
ImGui.text(mask.getDuration() + " " + mask.getTime());

View File

@ -175,9 +175,10 @@ public class EntityProtocol {
Globals.clientCharacterID = message.getentityID();
Globals.playerEntity = target;
if(viewModelData != null && viewModelData.getFirstPersonModelPath() != null){
Globals.firstPersonEntity = EntityCreationUtils.createClientSpatialEntity();
EntityCreationUtils.makeEntityDrawable(Globals.firstPersonEntity, viewModelData.getFirstPersonModelPath());
FirstPersonTree.attachTree(Globals.firstPersonEntity, viewModelData.getHeightFromOrigin(), viewModelData.getCameraViewDirOffsetY(), viewModelData.getCameraViewDirOffsetZ());
Globals.firstPersonEntity = CreatureUtils.clientCreateViewModel(
creatureTypeRaw,
null
);
}
}
}

View File

@ -3,6 +3,8 @@ package electrosphere.renderer.actor;
import electrosphere.engine.Globals;
import electrosphere.entity.state.AnimationPriorities;
import electrosphere.game.data.common.TreeDataAnimation;
import electrosphere.game.data.creature.type.bonegroups.BoneGroup;
import electrosphere.logger.LoggerInterface;
import electrosphere.renderer.OpenGLState;
import electrosphere.renderer.RenderPipelineState;
import electrosphere.renderer.model.Bone;
@ -13,7 +15,8 @@ import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.PriorityQueue;
import java.util.Set;
import java.util.TreeSet;
import org.joml.AxisAngle4f;
import org.joml.Matrix4d;
@ -47,7 +50,7 @@ public class Actor {
float animationScalar = 1.0f;
//The stack of animations being applied to a given actor
PriorityQueue<ActorAnimationMask> animationQueue = new PriorityQueue<ActorAnimationMask>();
Set<ActorAnimationMask> animationQueue = new TreeSet<ActorAnimationMask>();
//Mask for overwriting meshes in a given actor
ActorMeshMask meshMask = new ActorMeshMask();
@ -64,6 +67,9 @@ public class Actor {
//static morph for this specific actor
ActorStaticMorph staticMorph;
//The list of bone groups
List<BoneGroup> boneGroups;
//Controls whether the actor should obey frustum culling
boolean frustumCull = true;
@ -111,6 +117,26 @@ public class Actor {
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(ActorAnimationMask mask : animationQueue){
if(mask.getAnimationName().contains(animationData.getNameFirstPerson())){
return true;
}
if(mask.getAnimationName().contains(animationData.getNameThirdPerson())){
return true;
}
}
return false;
}
public boolean isPlayingAnimation(){
return animationQueue.size() > 0;
}
@ -183,9 +209,27 @@ public class Actor {
//Gets the mask
List<String> boneMask = null;
if(animation.getBoneGroups() != 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(this.boneGroups == null){
LoggerInterface.loggerRenderer.WARNING("Trying to play animation on pose actor that uses bone groups, but the actor's bone group isn't defined!");
}
@ -258,10 +302,14 @@ public class Actor {
* Gets the animation queue
* @return The animation queue
*/
public PriorityQueue<ActorAnimationMask> getAnimationQueue(){
public Set<ActorAnimationMask> getAnimationQueue(){
return animationQueue;
}
/**
* Applies the animation masks in this actor to the provided model
* @param model The model
*/
void applyAnimationMasks(Model model){
List<String> bonesUsed = new LinkedList<String>();
List<String> currentAnimationMask = new LinkedList<String>();
@ -532,6 +580,14 @@ 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;
}
/**

View File

@ -24,14 +24,14 @@ public class MainServerFunctions {
//
//Micro simulation (ie simulating each scene on the server)
Globals.profiler.beginCpuSample("Server micro simulation");
LoggerInterface.loggerEngine.DEBUG("Begin server micro simulation");
LoggerInterface.loggerEngine.DEBUG_LOOP("Begin server micro simulation");
if(Globals.realmManager != null){
Globals.realmManager.simulate();
}
//
//Macro simulation (ie simulating the larger world macro data)
LoggerInterface.loggerEngine.DEBUG("Server macro simulation");
LoggerInterface.loggerEngine.DEBUG_LOOP("Server macro simulation");
if(Globals.macroSimulation != null && Globals.macroSimulation.isReady()){
Globals.macroSimulation.simulate();
}

View File

@ -312,6 +312,8 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
){
LoggerInterface.loggerEngine.DEBUG("Get server data cell key: " + getServerDataCellKey(worldPos));
rVal = groundDataCells.get(getServerDataCellKey(worldPos));
} else {
LoggerInterface.loggerEngine.DEBUG("Failed to get server data cell at: " + worldPos);
}
return rVal;
}

View File

@ -16,6 +16,8 @@ import org.joml.Vector4d;
import electrosphere.engine.Globals;
import electrosphere.entity.state.AnimationPriorities;
import electrosphere.game.data.common.TreeDataAnimation;
import electrosphere.game.data.creature.type.bonegroups.BoneGroup;
import electrosphere.logger.LoggerInterface;
import electrosphere.renderer.actor.ActorAnimationMask;
import electrosphere.renderer.actor.ActorBoneRotator;
import electrosphere.renderer.actor.ActorStaticMorph;
@ -36,6 +38,9 @@ public class PoseActor {
//static morph used to apply an initial, static modification to the layout of bones in the pose model
ActorStaticMorph staticMorph;
//The bone groups for this pose actor
List<BoneGroup> boneGroups;
/**
* Constructor
@ -94,6 +99,20 @@ public class PoseActor {
return false;
}
/**
* Gets whether the animation is currently playing or not
* @param animationName The animation
* @return True if the animation is playing, false otherwise
*/
public boolean isPlayingAnimation(TreeDataAnimation animationName){
for(ActorAnimationMask mask : animationQueue){
if(mask.getAnimationName().contains(animationName.getNameThirdPerson())){
return true;
}
}
return false;
}
/**
* Gets whether the actor is playing ANY animation
* @return True if the actor is playing ANY animation, false otherwise
@ -171,9 +190,27 @@ public class PoseActor {
//Gets the mask
List<String> boneMask = null;
if(animation.getBoneGroups() != 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){
boneMask.addAll(group.getBoneNamesThirdPerson());
}
if(group != null && isThirdPerson == false){
boneMask.addAll(group.getBoneNamesFirstPerson());
}
}
} else if(this.boneGroups == null){
LoggerInterface.loggerRenderer.WARNING("Trying to play animation on pose actor that uses bone groups, but the actor's bone group isn't defined!");
}
@ -359,6 +396,14 @@ public class PoseActor {
return rVal;
}
/**
* Sets the bone groups
* @param boneGroups The bone groups
*/
public void setBoneGroups(List<BoneGroup> boneGroups){
this.boneGroups = boneGroups;
}
/**
* Checks if the pose model is loaded
* @return True if the pose model is loaded, false otherwise