hitboxes, ui, bug fixes, network fixes, etc
All checks were successful
studiorailgun/Renderer/pipeline/head This commit looks good
All checks were successful
studiorailgun/Renderer/pipeline/head This commit looks good
This commit is contained in:
parent
4ae09e7afb
commit
e671cda62d
@ -241,10 +241,10 @@
|
||||
"equipPoints" : [
|
||||
{
|
||||
"equipPointId" : "handLeft",
|
||||
"bone" : "MiddleLower.L",
|
||||
"bone" : "Hand.L",
|
||||
"firstPersonBone" : "hand.L",
|
||||
"offsetVector" : [],
|
||||
"offsetRotation" : [],
|
||||
"offsetVector" : [0,0,0],
|
||||
"offsetRotation" : [0,0,0,1],
|
||||
"equipClassWhitelist" : [
|
||||
"tool",
|
||||
"shield",
|
||||
@ -253,10 +253,10 @@
|
||||
},
|
||||
{
|
||||
"equipPointId" : "handRight",
|
||||
"bone" : "MiddleLower.R",
|
||||
"bone" : "Hand.R",
|
||||
"firstPersonBone" : "hand.R",
|
||||
"offsetVector" : [],
|
||||
"offsetRotation" : [0.3057,0.2926,0.09933,0.9006],
|
||||
"offsetVector" : [0,0,0],
|
||||
"offsetRotation" : [-0.334,0.145,-0.28,0.89],
|
||||
"equipClassWhitelist" : [
|
||||
"tool",
|
||||
"weapon",
|
||||
|
||||
@ -11,17 +11,17 @@
|
||||
"damage" : 10,
|
||||
"hitboxes" : [
|
||||
{
|
||||
"type": "hit",
|
||||
"type": "hit_connected",
|
||||
"bone": "Blade1",
|
||||
"radius": 0.04
|
||||
},
|
||||
{
|
||||
"type": "hit",
|
||||
"type": "hit_connected",
|
||||
"bone": "Blade2",
|
||||
"radius": 0.04
|
||||
},
|
||||
{
|
||||
"type": "hit",
|
||||
"type": "hit_connected",
|
||||
"bone": "Blade3",
|
||||
"radius": 0.04
|
||||
}
|
||||
|
||||
@ -26,6 +26,7 @@
|
||||
],
|
||||
"files" : [
|
||||
"Data/objects/floatingisland.json",
|
||||
"Data/objects/testscene1objects.json"
|
||||
"Data/objects/testscene1objects.json",
|
||||
"Data/objects/debug_objects.json"
|
||||
]
|
||||
}
|
||||
18
assets/Data/objects/debug_objects.json
Normal file
18
assets/Data/objects/debug_objects.json
Normal file
@ -0,0 +1,18 @@
|
||||
{
|
||||
"objects" : [
|
||||
|
||||
{
|
||||
"objectId" : "hitboxTester",
|
||||
"hitboxData" : [
|
||||
{
|
||||
"type": "static_capsule",
|
||||
"radius": 2,
|
||||
"length": 5
|
||||
}
|
||||
],
|
||||
"tokens": []
|
||||
}
|
||||
|
||||
],
|
||||
"files" : []
|
||||
}
|
||||
10
assets/Data/tutorial/hints.json
Normal file
10
assets/Data/tutorial/hints.json
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"hints": [
|
||||
{
|
||||
"id": "Basic Navigation",
|
||||
"titleString": "Navigation",
|
||||
"descriptionString": "You can move the mouse to move the camera around. Also, you can use the W, A, S, and D keys to move your character.",
|
||||
"image": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
BIN
assets/Models/basic/geometry/unitcapsule.glb
Normal file
BIN
assets/Models/basic/geometry/unitcapsule.glb
Normal file
Binary file not shown.
Binary file not shown.
@ -1,3 +1,3 @@
|
||||
#maven.buildNumber.plugin properties file
|
||||
#Sat Jun 01 15:22:11 EDT 2024
|
||||
buildNumber=134
|
||||
#Fri Jun 14 13:45:11 EDT 2024
|
||||
buildNumber=137
|
||||
|
||||
@ -334,16 +334,83 @@ Redo hitboxes to have capsules and also chaining between frames (but not between
|
||||
Redo hitboxes to have capsules and also chaining between frames (but not between swinging the camera around)
|
||||
- Write custom callback for the collision engine for just hitboxes
|
||||
|
||||
(06/04/2024)
|
||||
Redo hitboxes to have capsules and also chaining between frames (but not between swinging the camera around)
|
||||
- Need to have an object attached to creature that stores the rigid body
|
||||
- When creating the creature, for each hitbox, create shapes for the rigid body
|
||||
- Attach the overall object to the creature entity
|
||||
|
||||
(06/07/2024)
|
||||
Hitboxes work to properly use capsules (constantly destroy/recreate every frane because od4j doesn't allow rescaling :<)
|
||||
|
||||
(06/10/2024)
|
||||
Add flow for demo menu/level loading
|
||||
|
||||
(06/11/2024)
|
||||
Redo hitboxes to have capsules and also chaining between frames (but not between swinging the camera around)
|
||||
- Properly calculate the capsule that bridges from previous frame to current frame hitbox location
|
||||
- Write custom callback for the collision engine for just hitboxes
|
||||
Fix player model side-jog animations
|
||||
|
||||
(06/13/2024)
|
||||
Fix newly exported model not rendering correctly
|
||||
- All bones are passed into the shader every render call, the bone values must be corrupted
|
||||
- NIGHTMARE BUG
|
||||
Fix equipping an item spawning two items
|
||||
|
||||
(06/14/2024)
|
||||
Fix inventory ui not closing when you hit 'i' key (will need to update utility functions to manage input mode so you're not doing it in callback)
|
||||
Develop debug ui for equip points
|
||||
|
||||
# TODO
|
||||
|
||||
|
||||
Demo requirements:
|
||||
= Assets =
|
||||
Block animation in first person
|
||||
Block animation in third person
|
||||
Fix attack animation bone rotations for hand
|
||||
Clean up equip state data
|
||||
Audio FX for everything
|
||||
|
||||
|
||||
= Coding =
|
||||
Fix items falling below the ground
|
||||
Control rebinding menu from title screen
|
||||
Redo hitboxes to have capsules and also chaining between frames (but not between swinging the camera around)
|
||||
- Introduce block hitbox (blockbox) type
|
||||
Enemy AI
|
||||
Probably some kind of tutorial text
|
||||
Network-able ui messages
|
||||
Ability to display video both on title screen as well as in game windows for tutorials
|
||||
better scaffolding for scripting engine with hooks for equipping items, spawning entities, pausing/resuming play, etc
|
||||
Ability for private realms to have time start/stop based on the player's feedback <-- sync this up to tutorial ui via script
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
BIG BIG BIG BIG IMMEDIATE TO DO:
|
||||
always enforce opengl interface across all opengl calls jesus christ the bone uniform bug was impossible
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Redo hitboxes to have capsules and also chaining between frames (but not between swinging the camera around)
|
||||
- Introduce block hitbox (blockbox) type
|
||||
|
||||
Fix voxel type selection menu not showing textures
|
||||
- The quads are off screen because the calculation for ndcX/ndcY are putting it wayyy to the right -- will need to revisit calcs for all that
|
||||
|
||||
Fix being able to walk off far side of the world (ie in level editor)
|
||||
|
||||
Grass System properly LOD
|
||||
- Have foliage dynamically time out cells to be reconsidered based on distance from player (if close, short cooldown, if far long cooldown)
|
||||
|
||||
Would be nice to be able to cut clients that stream their logs to my server
|
||||
|
||||
Data Cleanup
|
||||
- Clean up creatures
|
||||
- Remove unused ones
|
||||
|
||||
@ -2,6 +2,9 @@ package electrosphere.audio;
|
||||
|
||||
import org.joml.Vector3d;
|
||||
import org.joml.Vector3f;
|
||||
|
||||
import electrosphere.util.MathUtils;
|
||||
|
||||
import static org.lwjgl.openal.AL10.*;
|
||||
|
||||
/**
|
||||
@ -13,7 +16,7 @@ public class AudioListener {
|
||||
Vector3d position;
|
||||
|
||||
//eye vector for listener
|
||||
Vector3f eye = new Vector3f(1,0,0);
|
||||
Vector3f eye = MathUtils.getOriginVectorf();
|
||||
|
||||
//up vector for listener
|
||||
Vector3f up = new Vector3f(0,1,0);
|
||||
|
||||
@ -154,7 +154,7 @@ public class ClientSceneWrapper {
|
||||
CollisionResolutionCallback resolutionCallback = new CollisionResolutionCallback() {
|
||||
@Override
|
||||
public void resolve(DContactGeom geom, Collidable impactor, Collidable receiver, Vector3d normal, Vector3d localPosition, Vector3d worldPos, float magnitude) {
|
||||
HitboxUtils.clientDamageHitboxColision(impactor.getParent(), receiver.getParent());
|
||||
HitboxUtils.clientDamageHitboxColision(geom, impactor, receiver, normal, localPosition, worldPos, magnitude);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -54,7 +54,7 @@ public class ClientSimulation {
|
||||
//simulate bullet physics engine step
|
||||
Globals.clientSceneWrapper.getCollisionEngine().simulatePhysics((float)Globals.timekeeper.getSimFrameTime());
|
||||
Globals.clientSceneWrapper.getCollisionEngine().updateDynamicObjectTransforms();
|
||||
//
|
||||
|
||||
//update actor animations
|
||||
Globals.profiler.beginCpuSample("update actor animations");
|
||||
for(Entity currentEntity : Globals.clientSceneWrapper.getScene().getEntitiesWithTag(EntityTags.DRAWABLE)){
|
||||
|
||||
@ -11,6 +11,7 @@ import org.lwjgl.assimp.AIVector3D;
|
||||
import org.ode4j.math.DMatrix3;
|
||||
import org.ode4j.ode.DBody;
|
||||
import org.ode4j.ode.DBox;
|
||||
import org.ode4j.ode.DCapsule;
|
||||
import org.ode4j.ode.DCylinder;
|
||||
import org.ode4j.ode.DGeom;
|
||||
import org.ode4j.ode.DSphere;
|
||||
@ -24,6 +25,7 @@ import electrosphere.entity.types.terrain.TerrainChunkData;
|
||||
public class CollisionBodyCreation {
|
||||
|
||||
//Matrix for correcting initial axis of eg cylinders or capsules
|
||||
//this rotates by 90 degrees along the x axis
|
||||
public static final DMatrix3 AXIS_CORRECTION_MATRIX = new DMatrix3(
|
||||
1.0000000, 0.0000000, 0.0000000,
|
||||
0.0000000, 0.0000000, -1.0000000,
|
||||
@ -95,12 +97,25 @@ public class CollisionBodyCreation {
|
||||
* Creates a sphere shape
|
||||
* @param collisionEngine the collision engine
|
||||
* @param radius the radius of the sphere
|
||||
* @param categoryBits the category bits for the shape
|
||||
* @return the sphere shape
|
||||
*/
|
||||
public static DSphere createShapeSphere(CollisionEngine collisionEngine, double radius, long categoryBits){
|
||||
return collisionEngine.createSphereGeom(radius, categoryBits);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a capsule shape
|
||||
* @param collisionEngine The collision engine
|
||||
* @param radius the radius of the capsule
|
||||
* @param length the length of the capsule
|
||||
* @param categoryBits the category bits for the shape
|
||||
* @return the capsule shape
|
||||
*/
|
||||
public static DCapsule createCapsuleShape(CollisionEngine collisionEngine, double radius, double length, long categoryBits){
|
||||
return collisionEngine.createCapsuleGeom(radius, length, categoryBits);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the provided body to be a kinematic body (no gravity applied)
|
||||
* @param collisionEngine The collision engine
|
||||
@ -130,6 +145,35 @@ public class CollisionBodyCreation {
|
||||
collisionEngine.setOffsetPosition(body, offsetPosition);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a geom from a body
|
||||
* @param collisionEngine the collision engine
|
||||
* @param body the body
|
||||
* @param geom the geometry
|
||||
*/
|
||||
public static void removeShapeFromBody(CollisionEngine collisionEngine, DBody body, DGeom geom){
|
||||
collisionEngine.removeGeometryFromBody(body, geom);
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroys a geometry
|
||||
* @param collisionEngine The collision engine
|
||||
* @param geom the geometry
|
||||
*/
|
||||
public static void destroyShape(CollisionEngine collisionEngine, DGeom geom){
|
||||
collisionEngine.destroyGeom(geom);
|
||||
}
|
||||
|
||||
/**
|
||||
* Attaches a geom to a body
|
||||
* @param collisionEngine the collision engine
|
||||
* @param body the body
|
||||
* @param geom the geometry
|
||||
*/
|
||||
public static void attachGeomToBody(CollisionEngine collisionEngine, DBody body, DGeom geom){
|
||||
collisionEngine.attachGeomToBody(body, geom);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates an ode DBody from a terrain chunk data object
|
||||
|
||||
@ -842,6 +842,32 @@ public class CollisionEngine {
|
||||
body.getGeomIterator().next().setOffsetPosition(offsetVector.x,offsetVector.y,offsetVector.z);
|
||||
spaceLock.release();
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the geometry from the body
|
||||
* @param body the body
|
||||
* @param geom the geometry
|
||||
*/
|
||||
protected void removeGeometryFromBody(DBody body, DGeom geom){
|
||||
geom.setBody(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroys a geometry
|
||||
* @param geom The geometry
|
||||
*/
|
||||
protected void destroyGeom(DGeom geom){
|
||||
geom.destroy();
|
||||
}
|
||||
|
||||
/**
|
||||
* Attaches a geom to a body
|
||||
* @param body the body
|
||||
* @param geom the geom
|
||||
*/
|
||||
protected void attachGeomToBody(DBody body, DGeom geom){
|
||||
geom.setBody(body);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@ -6,7 +6,6 @@ import org.joml.Quaterniond;
|
||||
import org.joml.Vector3d;
|
||||
import org.joml.Vector3f;
|
||||
import org.ode4j.ode.DBody;
|
||||
import org.ode4j.ode.DCylinder;
|
||||
import org.ode4j.ode.DGeom;
|
||||
import org.ode4j.ode.DTriMesh;
|
||||
|
||||
|
||||
@ -3,7 +3,7 @@ package electrosphere.collision.hitbox;
|
||||
import electrosphere.collision.CollisionEngine;
|
||||
import electrosphere.collision.CollisionEngine.CollisionResolutionCallback;
|
||||
import electrosphere.engine.Globals;
|
||||
import electrosphere.entity.state.hitbox.HitboxState;
|
||||
import electrosphere.entity.state.hitbox.HitboxCollectionState;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
/**
|
||||
@ -12,7 +12,7 @@ import java.util.concurrent.CopyOnWriteArrayList;
|
||||
public class HitboxManager {
|
||||
|
||||
//the list of all hitboxes
|
||||
CopyOnWriteArrayList<HitboxState> hitboxes = new CopyOnWriteArrayList<HitboxState>();
|
||||
CopyOnWriteArrayList<HitboxCollectionState> hitboxes = new CopyOnWriteArrayList<HitboxCollectionState>();
|
||||
|
||||
//the collision engine for this hitbox manager
|
||||
CollisionEngine collisionEngine;
|
||||
@ -33,7 +33,7 @@ public class HitboxManager {
|
||||
* Registers a hitbox to the manager
|
||||
* @param hitbox the hitbox to register
|
||||
*/
|
||||
public void registerHitbox(HitboxState hitbox){
|
||||
public void registerHitbox(HitboxCollectionState hitbox){
|
||||
hitboxes.add(hitbox);
|
||||
idIncrementer++;
|
||||
}
|
||||
@ -42,7 +42,7 @@ public class HitboxManager {
|
||||
* Gets all hitboxes in the manager
|
||||
* @return all hitboxes in the manager
|
||||
*/
|
||||
public CopyOnWriteArrayList<HitboxState> getAllHitboxes(){
|
||||
public CopyOnWriteArrayList<HitboxCollectionState> getAllHitboxes(){
|
||||
return hitboxes;
|
||||
}
|
||||
|
||||
@ -50,7 +50,7 @@ public class HitboxManager {
|
||||
* Deregisters a hitbox from the manager
|
||||
* @param hitbox the hitbox to deregister
|
||||
*/
|
||||
public void deregisterHitbox(HitboxState hitbox){
|
||||
public void deregisterHitbox(HitboxCollectionState hitbox){
|
||||
hitboxes.remove(hitbox);
|
||||
}
|
||||
|
||||
@ -68,7 +68,8 @@ public class HitboxManager {
|
||||
public void simulate(){
|
||||
//update all positions
|
||||
Globals.profiler.beginCpuSample("Update hitbox positions");
|
||||
for(HitboxState state : hitboxes){
|
||||
for(HitboxCollectionState state : hitboxes){
|
||||
state.clearCollisions();
|
||||
state.updateHitboxPositions(this.collisionEngine);
|
||||
}
|
||||
Globals.profiler.endCpuSample();
|
||||
|
||||
@ -1,25 +1,20 @@
|
||||
package electrosphere.collision.hitbox;
|
||||
|
||||
import electrosphere.engine.Globals;
|
||||
import electrosphere.collision.collidable.Collidable;
|
||||
import electrosphere.entity.Entity;
|
||||
import electrosphere.entity.EntityCreationUtils;
|
||||
import electrosphere.entity.EntityDataStrings;
|
||||
import electrosphere.entity.EntityUtils;
|
||||
import electrosphere.entity.types.attach.AttachUtils;
|
||||
import electrosphere.entity.types.creature.CreatureUtils;
|
||||
import electrosphere.entity.types.item.ItemUtils;
|
||||
import electrosphere.entity.state.life.LifeState;
|
||||
import electrosphere.entity.state.life.LifeUtils;
|
||||
import electrosphere.entity.state.movement.ProjectileTree;
|
||||
import electrosphere.entity.state.hitbox.HitboxCollectionState;
|
||||
import electrosphere.entity.state.hitbox.HitboxCollectionState.HitboxState;
|
||||
import electrosphere.entity.state.hitbox.HitboxCollectionState.HitboxType;
|
||||
import electrosphere.game.data.collidable.HitboxData;
|
||||
import electrosphere.game.server.effects.ParticleEffects;
|
||||
import electrosphere.server.datacell.Realm;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.joml.Quaterniond;
|
||||
import org.joml.Vector3d;
|
||||
import org.joml.Vector3f;
|
||||
import org.ode4j.ode.DContactGeom;
|
||||
import org.ode4j.ode.DGeom;
|
||||
|
||||
/**
|
||||
* Utilities for working with hitboxes
|
||||
@ -237,8 +232,38 @@ public class HitboxUtils {
|
||||
* @param impactor the entity initiating the collision
|
||||
* @param receiver the entity receiving the collision
|
||||
*/
|
||||
public static void clientDamageHitboxColision(Entity impactor, Entity receiver){
|
||||
public static void clientDamageHitboxColision(DContactGeom contactGeom, Collidable impactor, Collidable receiver, Vector3d normal, Vector3d localPosition, Vector3d worldPos, float magnitude){
|
||||
|
||||
Entity impactorParent = impactor.getParent();
|
||||
Entity receiverParent = receiver.getParent();
|
||||
HitboxCollectionState impactorState = HitboxCollectionState.getHitboxState(impactorParent);
|
||||
HitboxCollectionState receiverState = HitboxCollectionState.getHitboxState(receiverParent);
|
||||
DGeom impactorGeom = contactGeom.g1;
|
||||
DGeom receiverGeom = contactGeom.g2;
|
||||
HitboxState impactorShapeStatus = impactorState.getShapeStatus(impactorGeom);
|
||||
HitboxState receiverShapeStatus = receiverState.getShapeStatus(receiverGeom);
|
||||
|
||||
|
||||
//currently, impactor needs to be an item, and the receiver must not be an item
|
||||
boolean isDamageEvent =
|
||||
impactorShapeStatus != null &&
|
||||
receiverShapeStatus != null &&
|
||||
impactorShapeStatus.getType() == HitboxType.HIT &&
|
||||
receiverShapeStatus.getType() == HitboxType.HURT &&
|
||||
AttachUtils.getParent(impactorParent) != receiverParent
|
||||
;
|
||||
|
||||
if(impactorShapeStatus != null){
|
||||
impactorShapeStatus.setHadCollision(true);
|
||||
}
|
||||
if(receiverShapeStatus != null){
|
||||
receiverShapeStatus.setHadCollision(true);
|
||||
}
|
||||
|
||||
if(isDamageEvent){
|
||||
//TODO: client logic for audio etc
|
||||
}
|
||||
|
||||
// Entity hitboxParent = (Entity)impactor.getData(EntityDataStrings.COLLISION_ENTITY_DATA_PARENT);
|
||||
// Entity hurtboxParent = (Entity)receiver.getData(EntityDataStrings.COLLISION_ENTITY_DATA_PARENT);
|
||||
|
||||
|
||||
@ -12,18 +12,34 @@ import electrosphere.entity.EntityUtils;
|
||||
import electrosphere.entity.types.camera.CameraEntityUtils;
|
||||
import electrosphere.net.parser.net.message.EntityMessage;
|
||||
import electrosphere.renderer.ui.events.MouseEvent;
|
||||
import electrosphere.util.MathUtils;
|
||||
|
||||
/**
|
||||
* Handler for camera-related events and controls
|
||||
*/
|
||||
public class CameraHandler {
|
||||
|
||||
//the horizontal mouse sensitivity
|
||||
float mouseSensitivityHorizontal = .1f;
|
||||
//the vertical mouse sensitivity
|
||||
float mouseSensitivityVertical = .08f;
|
||||
//the speed of the freecam
|
||||
float cameraSpeed;
|
||||
//the current yaw
|
||||
float yaw = 150;
|
||||
//the current pitch
|
||||
float pitch = 50;
|
||||
//the camera's rotation vector
|
||||
Vector3f cameraRotationVector = new Vector3f();
|
||||
//the radial offset of the camera
|
||||
Vector3f radialOffset = new Vector3f(0,1,0);
|
||||
//if set to true, the camera will track the player's entity
|
||||
boolean trackPlayerEntity = true;
|
||||
|
||||
/**
|
||||
* Handles a mouse event
|
||||
* @param event The mouse event
|
||||
*/
|
||||
public void handleMouseEvent(MouseEvent event){
|
||||
|
||||
if(Globals.controlHandler != null && !Globals.controlHandler.isMouseVisible()){
|
||||
@ -41,10 +57,17 @@ public class CameraHandler {
|
||||
updateGlobalCamera();
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the radial offset
|
||||
* @param offset the radial offset
|
||||
*/
|
||||
public void updateRadialOffset(Vector3f offset){
|
||||
radialOffset = offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the global camera
|
||||
*/
|
||||
public void updateGlobalCamera(){
|
||||
Globals.profiler.beginCpuSample("updateGlobalCamera");
|
||||
if(Globals.playerCamera != null){
|
||||
@ -83,7 +106,7 @@ public class CameraHandler {
|
||||
// float pitchRad = pitch / 180.0f * (float)Math.PI;
|
||||
// float rollRad = 0.0f;
|
||||
// pitchQuat.mul(yawQuat);
|
||||
cameraRotationVector = pitchQuat.transform(new Vector3f(0,0,1));
|
||||
cameraRotationVector = pitchQuat.transform(MathUtils.getOriginVectorf());
|
||||
cameraRotationVector = yawQuat.transform(cameraRotationVector);
|
||||
cameraRotationVector.normalize();
|
||||
|
||||
@ -150,10 +173,18 @@ public class CameraHandler {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the yaw of the camera handler
|
||||
* @return the yaw
|
||||
*/
|
||||
public float getYaw(){
|
||||
return yaw;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the pitch of the camera handler
|
||||
* @return the pitch
|
||||
*/
|
||||
public float getPitch(){
|
||||
return pitch;
|
||||
}
|
||||
|
||||
@ -61,6 +61,7 @@ import static org.lwjgl.glfw.GLFW.GLFW_MOUSE_BUTTON_RIGHT;
|
||||
import static org.lwjgl.glfw.GLFW.glfwGetCursorPos;
|
||||
import static org.lwjgl.glfw.GLFW.glfwSetInputMode;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
@ -107,8 +108,7 @@ import electrosphere.renderer.ui.events.MouseEvent;
|
||||
import electrosphere.renderer.ui.events.ScrollEvent;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author amaterasu
|
||||
* Main handler for controls
|
||||
*/
|
||||
public class ControlHandler {
|
||||
|
||||
@ -204,7 +204,9 @@ public class ControlHandler {
|
||||
public static final String FREECAM_RIGHT = "freecamRight";
|
||||
public static final String FREECAM_MOUSE = "freecamMouse";
|
||||
|
||||
|
||||
/**
|
||||
* The different buckets of inputs that the control handler be configured to scan for each frame
|
||||
*/
|
||||
public static enum ControlsState {
|
||||
TITLE_PAGE,
|
||||
TITLE_MENU,
|
||||
@ -215,15 +217,40 @@ public class ControlHandler {
|
||||
NO_INPUT,
|
||||
}
|
||||
|
||||
//The bucket of inputs that the control handler is currently scanning for
|
||||
ControlsState state = ControlsState.TITLE_MENU;
|
||||
|
||||
|
||||
/**
|
||||
* The list of control states that have the mouse visible and enabled
|
||||
*/
|
||||
static ControlsState[] mouseEnabledStates = new ControlsState[]{
|
||||
ControlsState.TITLE_PAGE,
|
||||
ControlsState.TITLE_MENU,
|
||||
ControlsState.IN_GAME_MAIN_MENU,
|
||||
ControlsState.INVENTORY,
|
||||
};
|
||||
|
||||
|
||||
//controls whether the mouse is visible or not
|
||||
boolean mouseIsVisible = true;
|
||||
|
||||
//if set to true, opengl will try to capture the screen next frame
|
||||
boolean shouldRecaptureScreen = false;
|
||||
|
||||
//controls whether the camera is first or third person
|
||||
boolean cameraIsThirdPerson = true;
|
||||
|
||||
//The list of window strings that would block main game controls
|
||||
static String[] controlBlockingWindows = new String[]{
|
||||
WindowStrings.LEVEL_EDTIOR_SIDE_PANEL,
|
||||
WindowStrings.VOXEL_TYPE_SELECTION,
|
||||
WindowStrings.WINDOW_CHARACTER,
|
||||
WindowStrings.WINDOW_DEBUG,
|
||||
WindowStrings.WINDOW_MENU_INGAME_MAIN,
|
||||
WindowStrings.WINDOW_MENU_INVENTORY,
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
Mouse event parsing related stuff
|
||||
@ -234,10 +261,10 @@ public class ControlHandler {
|
||||
double ypos = 300;
|
||||
double mouse_X_Buffer[] = new double[1];
|
||||
double mouse_Y_Buffer[] = new double[1];
|
||||
boolean dragging = false;
|
||||
boolean dragging = false; //tracks whether the mouse is doing a drag input or not
|
||||
|
||||
|
||||
|
||||
//The map of data string -> control object
|
||||
HashMap<String, Control> controls;
|
||||
|
||||
List<Control> mainGameControlList = new LinkedList<Control>();
|
||||
@ -248,10 +275,17 @@ public class ControlHandler {
|
||||
List<Control> alwaysOnDebugControlList = new LinkedList<Control>();
|
||||
List<Control> freeCameraControlList = new LinkedList<Control>();
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
ControlHandler(){
|
||||
controls = new HashMap<String, Control>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates an example controls map
|
||||
* @return the example controls map object
|
||||
*/
|
||||
public static ControlHandler generateExampleControlsMap(){
|
||||
ControlHandler handler = new ControlHandler();
|
||||
/*
|
||||
@ -355,11 +389,6 @@ public class ControlHandler {
|
||||
framestep controls
|
||||
*/
|
||||
handler.addControl(DEBUG_FRAMESTEP, new Control(ControlType.KEY, GLFW_KEY_P));
|
||||
|
||||
/*
|
||||
set state
|
||||
*/
|
||||
handler.setHandlerState(ControlsState.TITLE_MENU);
|
||||
|
||||
/*
|
||||
* Free camera
|
||||
@ -393,7 +422,9 @@ public class ControlHandler {
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Polls the currently set bucket of controls
|
||||
*/
|
||||
public void pollControls(){
|
||||
switch(state){
|
||||
|
||||
@ -446,7 +477,9 @@ public class ControlHandler {
|
||||
Globals.scrollCallback.clear();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Attaches callbacks to each of the control objects
|
||||
*/
|
||||
public void setCallbacks(){
|
||||
setMainGameControls();
|
||||
setInGameDebugControls();
|
||||
@ -457,6 +490,10 @@ public class ControlHandler {
|
||||
setFreecamControls();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets callbacks for the main game controls
|
||||
*/
|
||||
void setMainGameControls(){
|
||||
/*
|
||||
Camera rotation
|
||||
@ -909,7 +946,7 @@ public class ControlHandler {
|
||||
mainGameControlList.add(controls.get(DATA_STRING_INPUT_CODE_IN_GAME_MAIN_MENU));
|
||||
controls.get(DATA_STRING_INPUT_CODE_IN_GAME_MAIN_MENU).setOnClick(new ControlMethod(){public void execute(){
|
||||
// Globals.elementManager.registerWindow(WindowStrings.WINDOW_MENU_INGAME_MAIN, MenuGenerators.createInGameMainMenu());
|
||||
// Globals.controlHandler.setHandlerState(ControlsState.IN_GAME_MAIN_MENU);
|
||||
// Globals.controlHandler.hintUpdateControlState(ControlsState.IN_GAME_MAIN_MENU);
|
||||
|
||||
// Window mainMenuWindow = new Window(0, 0, Globals.WINDOW_WIDTH, Globals.WINDOW_HEIGHT);
|
||||
Window mainMenuInGame = MenuGeneratorsInGame.createInGameMainMenu();
|
||||
@ -917,8 +954,7 @@ public class ControlHandler {
|
||||
Globals.elementManager.registerWindow(WindowStrings.WINDOW_MENU_INGAME_MAIN, mainMenuInGame);
|
||||
WindowUtils.recursiveSetVisible(Globals.elementManager.getWindow(WindowStrings.WINDOW_MENU_INGAME_MAIN), true);
|
||||
Globals.elementManager.focusFirstElement();
|
||||
Globals.controlHandler.setHandlerState(ControlsState.IN_GAME_MAIN_MENU);
|
||||
Globals.controlHandler.showMouse();
|
||||
Globals.controlHandler.hintUpdateControlState(ControlsState.IN_GAME_MAIN_MENU);
|
||||
//play sound effect
|
||||
Globals.virtualAudioSourceManager.createVirtualAudioSource("/Audio/openMenu.ogg", VirtualAudioSourceType.UI, false);
|
||||
}});
|
||||
@ -939,12 +975,13 @@ public class ControlHandler {
|
||||
//make visible
|
||||
WindowUtils.recursiveSetVisible(Globals.elementManager.getWindow(WindowUtils.getInventoryWindowID(inventory.getId())), true);
|
||||
//controls
|
||||
Globals.controlHandler.setHandlerState(ControlsState.INVENTORY);
|
||||
Globals.controlHandler.showMouse();
|
||||
Globals.controlHandler.hintUpdateControlState(ControlsState.INVENTORY);
|
||||
//play sound effect
|
||||
Globals.virtualAudioSourceManager.createVirtualAudioSource("/Audio/openMenu.ogg", VirtualAudioSourceType.UI, false);
|
||||
//
|
||||
Globals.openInventoriesCount++;
|
||||
} else if(InventoryUtils.hasNaturalInventory(Globals.playerEntity) && Globals.elementManager.getWindow(WindowUtils.getInventoryWindowID(InventoryUtils.getNaturalInventory(Globals.playerEntity).getId())) != null){
|
||||
Globals.elementManager.closeWindow(WindowUtils.getInventoryWindowID(InventoryUtils.getNaturalInventory(Globals.playerEntity).getId()));
|
||||
}
|
||||
}});
|
||||
controls.get(INPUT_CODE_INVENTORY_OPEN).setRepeatTimeout(0.5f * Main.targetFrameRate);
|
||||
@ -957,18 +994,19 @@ public class ControlHandler {
|
||||
controls.get(INPUT_CODE_CHARACTER_OPEN).setOnClick(new ControlMethod(){public void execute(){
|
||||
if(InventoryUtils.hasEquipInventory(Globals.playerEntity) && Globals.elementManager.getWindow(WindowStrings.WINDOW_CHARACTER) == null){
|
||||
//create window
|
||||
Window mainMenuWindow = MenuGeneratorsInventory.createCharacterInventoryMenu(InventoryUtils.getEquipInventory(Globals.playerEntity));
|
||||
Window characterInventoryMenu = MenuGeneratorsInventory.createCharacterInventoryMenu(InventoryUtils.getEquipInventory(Globals.playerEntity));
|
||||
//register
|
||||
Globals.elementManager.registerWindow(WindowStrings.WINDOW_CHARACTER, mainMenuWindow);
|
||||
Globals.elementManager.registerWindow(WindowStrings.WINDOW_CHARACTER, characterInventoryMenu);
|
||||
//make visible
|
||||
WindowUtils.recursiveSetVisible(Globals.elementManager.getWindow(WindowStrings.WINDOW_CHARACTER), true);
|
||||
//controls
|
||||
Globals.controlHandler.setHandlerState(ControlsState.INVENTORY);
|
||||
Globals.controlHandler.showMouse();
|
||||
Globals.controlHandler.hintUpdateControlState(ControlsState.INVENTORY);
|
||||
//play sound effect
|
||||
Globals.virtualAudioSourceManager.createVirtualAudioSource("/Audio/openMenu.ogg", VirtualAudioSourceType.UI, false);
|
||||
//
|
||||
Globals.openInventoriesCount++;
|
||||
} else if(InventoryUtils.hasEquipInventory(Globals.playerEntity) && Globals.elementManager.getWindow(WindowStrings.WINDOW_CHARACTER) != null){
|
||||
Globals.elementManager.closeWindow(WindowStrings.WINDOW_CHARACTER);
|
||||
}
|
||||
}});
|
||||
controls.get(INPUT_CODE_CHARACTER_OPEN).setRepeatTimeout(0.5f * Main.targetFrameRate);
|
||||
@ -1037,6 +1075,10 @@ public class ControlHandler {
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the in game debug control callbacks
|
||||
*/
|
||||
void setInGameDebugControls(){
|
||||
mainGameDebugControlList.add(controls.get(DATA_STRING_INPUT_CODE_DEBUG_SPAWN_ITEM));
|
||||
controls.get(DATA_STRING_INPUT_CODE_DEBUG_SPAWN_ITEM).setOnPress(new ControlMethod(){public void execute(){
|
||||
@ -1050,6 +1092,10 @@ public class ControlHandler {
|
||||
controls.get(DEBUG_FRAMESTEP).setOnRelease(new ControlMethod(){public void execute(){
|
||||
Main.setFramestep(1);
|
||||
}});
|
||||
controls.get(DEBUG_FRAMESTEP).setOnRepeat(new ControlMethod(){public void execute(){
|
||||
Main.setFramestep(1);
|
||||
}});
|
||||
controls.get(DEBUG_FRAMESTEP).setRepeatTimeout(0.5f * Main.targetFrameRate);
|
||||
// RenderingEngine.incrementOutputFramebuffer();
|
||||
}
|
||||
|
||||
@ -1197,6 +1243,9 @@ public class ControlHandler {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the freecam control callbacks
|
||||
*/
|
||||
void setFreecamControls(){
|
||||
freeCameraControlList.add(controls.get(FREECAM_UP));
|
||||
controls.get(FREECAM_UP).setOnRepeat(new ControlMethod(){public void execute(){
|
||||
@ -1269,6 +1318,9 @@ public class ControlHandler {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the typing control callbacks
|
||||
*/
|
||||
void setTypingControls(){
|
||||
|
||||
String[] typeKeybinds = {
|
||||
@ -1332,6 +1384,9 @@ public class ControlHandler {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the inventory control callbacks
|
||||
*/
|
||||
void setInventoryControls(){
|
||||
/*
|
||||
Close inventory
|
||||
@ -1380,6 +1435,10 @@ public class ControlHandler {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Checks a list of controls to see if the corresponding key/mouse event is firing this frame
|
||||
* @param controls The list of controls to check
|
||||
*/
|
||||
public void runHandlers(List<Control> controls){
|
||||
|
||||
//construct mouse event
|
||||
@ -1461,6 +1520,55 @@ public class ControlHandler {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if any menus are open that would intercept player input (main menu, inventory, debug, etc)
|
||||
* @return true if such a menu is open, false otherwise
|
||||
*/
|
||||
private boolean hasControlBlockingMenuOpen(){
|
||||
boolean rVal = false;
|
||||
//check main ui framework windows
|
||||
for(String windowString : controlBlockingWindows){
|
||||
rVal = rVal || WindowUtils.windowIsOpen(windowString);
|
||||
}
|
||||
//check imgui windows
|
||||
rVal = rVal || Globals.renderingEngine.getImGuiPipeline().shouldCaptureControls();
|
||||
return rVal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hints to the engine that it should update the control state
|
||||
* The provided control state will be overwritten if, for instance,
|
||||
* there is a menu open that demands mouse input and you are trying
|
||||
* to tell the engine to convert to immediate player control
|
||||
* @param desiredState The desired control state
|
||||
*/
|
||||
public void hintUpdateControlState(ControlsState desiredState){
|
||||
ControlsState properState = desiredState;
|
||||
//correct for freecam or actual ingame control based on value of getTrackPlayerEntity
|
||||
if(desiredState == ControlsState.IN_GAME_FREE_CAMERA && Globals.cameraHandler.getTrackPlayerEntity()){
|
||||
properState = ControlsState.MAIN_GAME;
|
||||
}
|
||||
if(desiredState == ControlsState.MAIN_GAME && !Globals.cameraHandler.getTrackPlayerEntity()){
|
||||
properState = ControlsState.IN_GAME_FREE_CAMERA;
|
||||
}
|
||||
|
||||
//set to menu state if a menu is open, otherwise use the hinted control scheme
|
||||
if(hasControlBlockingMenuOpen()){
|
||||
setHandlerState(ControlsState.IN_GAME_MAIN_MENU);
|
||||
} else {
|
||||
setHandlerState(properState);
|
||||
}
|
||||
//checks if the current handler state should have mouse enabled or not
|
||||
if(Arrays.binarySearch(mouseEnabledStates,getHandlerState()) >= 0){
|
||||
showMouse();
|
||||
} else {
|
||||
hideMouse();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Transfers the mouse position from the glfw buffer to variables stored inside the control handler
|
||||
*/
|
||||
void getMousePositionInBuffer(){
|
||||
//only if not headless, gather position
|
||||
if(!Globals.HEADLESS){
|
||||
@ -1470,6 +1578,10 @@ public class ControlHandler {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the mouse button 1 is currently pressed
|
||||
* @return true if pressed, false otherwise
|
||||
*/
|
||||
boolean getButton1Raw(){
|
||||
if(Globals.HEADLESS){
|
||||
return false;
|
||||
@ -1478,6 +1590,10 @@ public class ControlHandler {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the mouse button 2 is currently pressed
|
||||
* @return true if pressed, false otherwise
|
||||
*/
|
||||
boolean getButton2Raw(){
|
||||
if(Globals.HEADLESS){
|
||||
return false;
|
||||
@ -1502,33 +1618,51 @@ public class ControlHandler {
|
||||
controls.put(controlName, c);
|
||||
}
|
||||
|
||||
public void setHandlerState(ControlsState state){
|
||||
/**
|
||||
* Sets the state of the controls handler
|
||||
* @param state the state
|
||||
*/
|
||||
private void setHandlerState(ControlsState state){
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current state of the controls handler
|
||||
* @return the state
|
||||
*/
|
||||
public ControlsState getHandlerState(){
|
||||
return state;
|
||||
}
|
||||
|
||||
public ControlsState getState(){
|
||||
return state;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hides the mouse
|
||||
*/
|
||||
public void hideMouse(){
|
||||
glfwSetInputMode(Globals.window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
|
||||
glfwSetInputMode(Globals.window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
|
||||
mouseIsVisible = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows the mouse
|
||||
*/
|
||||
public void showMouse(){
|
||||
glfwSetInputMode(Globals.window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
|
||||
mouseIsVisible = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether the mouse is visible or not
|
||||
* @return true if visible, false otherwise
|
||||
*/
|
||||
public boolean isMouseVisible(){
|
||||
return mouseIsVisible;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the mouse position as a vector2f
|
||||
* @return The vector containing the mouse position
|
||||
*/
|
||||
public Vector2f getMousePosition(){
|
||||
double posX[] = new double[1];
|
||||
double posY[] = new double[1];
|
||||
@ -1537,6 +1671,11 @@ public class ControlHandler {
|
||||
return rVal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a keycode to a string containing a code related to the keycode (ie "A" for 65, "Escape" for 256, etc)
|
||||
* @param code The keycode
|
||||
* @return The corresponding string code
|
||||
*/
|
||||
public static String convertKeycodeToName(int code){
|
||||
String rVal = "";
|
||||
switch(code){
|
||||
@ -1667,10 +1806,18 @@ public class ControlHandler {
|
||||
return rVal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether the engine should try to recapture window focus next frame or not
|
||||
* @param shouldRecapture true if should try to recapture next frame, false otherwise
|
||||
*/
|
||||
public void setRecapture(boolean shouldRecapture){
|
||||
this.shouldRecaptureScreen = shouldRecapture;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the engine should try to recapture window focus next frame or not
|
||||
* @return true if it should try to recapture, false otherwise
|
||||
*/
|
||||
public boolean shouldRecapture(){
|
||||
return this.shouldRecaptureScreen;
|
||||
}
|
||||
|
||||
@ -138,6 +138,7 @@ public class Globals {
|
||||
//Client connection to server
|
||||
//
|
||||
public static ClientNetworking clientConnection;
|
||||
public static boolean RUN_DEMO = false;
|
||||
public static boolean RUN_CLIENT = true;
|
||||
public static int clientCharacterID;
|
||||
|
||||
@ -526,6 +527,7 @@ public class Globals {
|
||||
assetManager.addModelPathToQueue("Models/basic/geometry/unitsphere_grey.fbx");
|
||||
assetManager.addModelPathToQueue("Models/basic/geometry/SmallCube.fbx");
|
||||
assetManager.addModelPathToQueue("Models/basic/geometry/unitcylinder.fbx");
|
||||
assetManager.addModelPathToQueue("Models/basic/geometry/unitcapsule.glb");
|
||||
assetManager.addModelPathToQueue("Models/basic/geometry/unitplane.fbx");
|
||||
assetManager.addModelPathToQueue("Models/basic/geometry/unitcube.fbx");
|
||||
imagePlaneModelID = assetManager.registerModel(RenderUtils.createPlaneModel("Shaders/plane/plane.vs", "Shaders/plane/plane.fs"));
|
||||
|
||||
@ -11,6 +11,7 @@ import org.ode4j.ode.OdeHelper;
|
||||
import electrosphere.audio.AudioEngine;
|
||||
import electrosphere.audio.VirtualAudioSourceManager;
|
||||
import electrosphere.controls.ControlHandler;
|
||||
import electrosphere.controls.ControlHandler.ControlsState;
|
||||
import electrosphere.engine.cli.CLIParser;
|
||||
import electrosphere.engine.loadingthreads.LoadingThread;
|
||||
import electrosphere.engine.time.Timekeeper;
|
||||
@ -22,7 +23,9 @@ import electrosphere.renderer.RenderingEngine;
|
||||
import electrosphere.server.simulation.MacroSimulation;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* The main class
|
||||
*/
|
||||
public class Main {
|
||||
|
||||
|
||||
@ -140,6 +143,9 @@ public class Main {
|
||||
Globals.initDefaultGraphicalResources();
|
||||
ImGuiWindowMacros.initImGuiWindows();
|
||||
|
||||
//inits the controls state of the control handler
|
||||
Globals.controlHandler.hintUpdateControlState(ControlsState.TITLE_MENU);
|
||||
|
||||
//start initial asset loading
|
||||
new Thread(Globals.initialAssetLoadingThread).start();
|
||||
}
|
||||
@ -186,7 +192,11 @@ public class Main {
|
||||
|
||||
//fire off a loading thread for the title menus/screen
|
||||
LoggerInterface.loggerStartup.INFO("Fire off loading thread");
|
||||
if(Globals.RUN_CLIENT){
|
||||
if(Globals.RUN_DEMO){
|
||||
LoadingThread serverThread = new LoadingThread(LoadingThread.LOAD_DEMO_MENU);
|
||||
Globals.loadingThreadsList.add(serverThread);
|
||||
serverThread.start();
|
||||
} else if(Globals.RUN_CLIENT){
|
||||
LoadingThread serverThread = new LoadingThread(LoadingThread.LOAD_TITLE_MENU);
|
||||
Globals.loadingThreadsList.add(serverThread);
|
||||
serverThread.start();
|
||||
@ -217,7 +227,6 @@ public class Main {
|
||||
*/
|
||||
public static void mainLoop(long maxFrames){
|
||||
|
||||
double functionTrackTimeStart = 0;
|
||||
//main loop
|
||||
while (running) {
|
||||
|
||||
@ -400,6 +409,11 @@ public class Main {
|
||||
|
||||
} catch (NullPointerException ex){
|
||||
LoggerInterface.loggerEngine.ERROR("Main frame uncaught NPE", ex);
|
||||
//after a while, jvm will stop reporting stack traces with errors
|
||||
//need to explicitly kill the vm if you want to see the stack trace
|
||||
if(Globals.ENGINE_DEBUG){
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -209,7 +209,7 @@ public class ArenaLoading {
|
||||
// public void simulate(){
|
||||
// if(i < 100){
|
||||
// i++;
|
||||
// CollisionObjUtils.getCollidable(sword).addImpulse(new Impulse(new Vector3d(0,0,1), new Vector3d(-1,0,0), 0.001, Collidable.TYPE_CREATURE));
|
||||
// CollisionObjUtils.getCollidable(sword).addImpulse(new Impulse(MathUtils.ORIGIN_VECTOR, new Vector3d(-1,0,0), 0.001, Collidable.TYPE_CREATURE));
|
||||
// EntityUtils.getPosition(sword).set(1,0.2f,2);
|
||||
// }
|
||||
// }});
|
||||
|
||||
@ -38,6 +38,7 @@ import electrosphere.net.NetUtils;
|
||||
import electrosphere.net.client.ClientNetworking;
|
||||
import electrosphere.renderer.ui.elements.Window;
|
||||
import electrosphere.server.datacell.EntityDataCellMapper;
|
||||
import electrosphere.util.MathUtils;
|
||||
|
||||
public class ClientLoading {
|
||||
|
||||
@ -55,7 +56,7 @@ public class ClientLoading {
|
||||
WindowUtils.replaceMainMenuContents(MenuGenerators.createEmptyMainMenu());
|
||||
loadingWindow.setVisible(true);
|
||||
//disable menu input
|
||||
Globals.controlHandler.setHandlerState(ControlHandler.ControlsState.NO_INPUT);
|
||||
Globals.controlHandler.hintUpdateControlState(ControlHandler.ControlsState.NO_INPUT);
|
||||
//initialize the client thread (client)
|
||||
initClientThread();
|
||||
//while we don't know what races are playable, wait
|
||||
@ -77,7 +78,7 @@ public class ClientLoading {
|
||||
//log
|
||||
LoggerInterface.loggerEngine.INFO("[Client]Finished loading character creation menu");
|
||||
//set menu controls again
|
||||
Globals.controlHandler.setHandlerState(ControlHandler.ControlsState.TITLE_MENU);
|
||||
Globals.controlHandler.hintUpdateControlState(ControlHandler.ControlsState.TITLE_MENU);
|
||||
}
|
||||
|
||||
|
||||
@ -87,7 +88,7 @@ public class ClientLoading {
|
||||
WindowUtils.replaceMainMenuContents(MenuGenerators.createEmptyMainMenu());
|
||||
loadingWindow.setVisible(true);
|
||||
//disable menu input
|
||||
Globals.controlHandler.setHandlerState(ControlHandler.ControlsState.NO_INPUT);
|
||||
Globals.controlHandler.hintUpdateControlState(ControlHandler.ControlsState.NO_INPUT);
|
||||
//initialize the "real" objects simulation
|
||||
initClientSimulation();
|
||||
//init foliage manager
|
||||
@ -104,8 +105,6 @@ public class ClientLoading {
|
||||
setSimulationsToReady();
|
||||
//init culling manager and other graphics-focused non-simulation items
|
||||
initEntityCullingManager();
|
||||
//hide cursor
|
||||
Globals.controlHandler.hideMouse();
|
||||
//make loading window disappear
|
||||
loadingWindow.setVisible(false);
|
||||
//recapture screen
|
||||
@ -119,7 +118,7 @@ public class ClientLoading {
|
||||
Globals.RENDER_FLAG_RENDER_WHITE_BACKGROUND = false;
|
||||
LoggerInterface.loggerEngine.INFO("[Client]Finished loading main game");
|
||||
//set controls state
|
||||
Globals.controlHandler.setHandlerState(ControlHandler.ControlsState.MAIN_GAME);
|
||||
Globals.controlHandler.hintUpdateControlState(ControlHandler.ControlsState.MAIN_GAME);
|
||||
}
|
||||
|
||||
|
||||
@ -177,9 +176,9 @@ public class ClientLoading {
|
||||
|
||||
*/
|
||||
if(Globals.controlHandler.cameraIsThirdPerson()){
|
||||
Globals.playerCamera = CameraEntityUtils.spawnPlayerEntityTrackingCameraEntity(new Vector3f(1,0,1), new Vector3f(0,0,1));
|
||||
Globals.playerCamera = CameraEntityUtils.spawnPlayerEntityTrackingCameraEntity(new Vector3f(1,0,1), MathUtils.getOriginVectorf());
|
||||
} else {
|
||||
Globals.playerCamera = CameraEntityUtils.spawnPlayerEntityTrackingCameraFirstPersonEntity(new Vector3f(1,0,1), new Vector3f(0,0,1));
|
||||
Globals.playerCamera = CameraEntityUtils.spawnPlayerEntityTrackingCameraFirstPersonEntity(new Vector3f(1,0,1), MathUtils.getOriginVectorf());
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -0,0 +1,31 @@
|
||||
package electrosphere.engine.loadingthreads;
|
||||
|
||||
import electrosphere.engine.Globals;
|
||||
import electrosphere.menu.WindowStrings;
|
||||
import electrosphere.menu.WindowUtils;
|
||||
import electrosphere.menu.mainmenu.MenuGeneratorsDemo;
|
||||
import electrosphere.renderer.ui.elements.Window;
|
||||
|
||||
/**
|
||||
* Loading routines for the demo version of the game
|
||||
*/
|
||||
public class DemoLoading {
|
||||
|
||||
//the name of the save for the demo version of the game
|
||||
public static final String DEMO_LEVEL_PATH = "demo";
|
||||
|
||||
/**
|
||||
* Loads the title menu elements for the demo version of the engine
|
||||
*/
|
||||
public static void loadDemoMenu(){
|
||||
Globals.currentSaveName = DEMO_LEVEL_PATH;
|
||||
|
||||
WindowUtils.replaceMainMenuContents(MenuGeneratorsDemo.createTitleMenu());
|
||||
|
||||
Window loadingWindow = (Window)Globals.elementManager.getWindow(WindowStrings.WINDOW_LOADING);
|
||||
WindowUtils.recursiveSetVisible(loadingWindow,false);
|
||||
WindowUtils.focusWindow(WindowStrings.WINDOW_MENU_MAIN);
|
||||
WindowUtils.recursiveSetVisible(Globals.elementManager.getWindow(WindowStrings.WINDOW_MENU_MAIN), true);
|
||||
}
|
||||
|
||||
}
|
||||
@ -3,24 +3,30 @@ package electrosphere.engine.loadingthreads;
|
||||
import java.util.concurrent.Semaphore;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author amaterasu
|
||||
* Threads for loading engine state
|
||||
*/
|
||||
public class LoadingThread extends Thread {
|
||||
|
||||
public static final int LOAD_TITLE_MENU = 0;
|
||||
public static final int LOAD_MAIN_GAME = 1;
|
||||
public static final int LOAD_ARENA = 2;
|
||||
public static final int LOAD_CHARACTER_SERVER = 3;
|
||||
public static final int LOAD_CLIENT_WORLD = 4;
|
||||
public static final int LOAD_DEBUG_RANDOM_SP_WORLD = 5;
|
||||
public static final int LOAD_LEVEL_EDITOR = 6;
|
||||
public static final int LOAD_LEVEL = 7;
|
||||
public static final int LOAD_TITLE_MENU = 0; //loads the main game title menu
|
||||
public static final int LOAD_MAIN_GAME = 1; //loads the main game
|
||||
public static final int LOAD_ARENA = 2; //loads the arena
|
||||
public static final int LOAD_CHARACTER_SERVER = 3; //loads the character creation menus on the client
|
||||
public static final int LOAD_CLIENT_WORLD = 4; //loads the client world
|
||||
public static final int LOAD_DEBUG_RANDOM_SP_WORLD = 5; //loads a random singleplayer debug world
|
||||
public static final int LOAD_LEVEL_EDITOR = 6; //loads the level editor
|
||||
public static final int LOAD_LEVEL = 7; //loads a level
|
||||
public static final int LOAD_DEMO_MENU = 8; //loads the main menu ui for the demo version of the client
|
||||
|
||||
//the type of loading to do
|
||||
int threadType;
|
||||
|
||||
//a lock to track when the loading had completed and block until then
|
||||
Semaphore lock;
|
||||
|
||||
/**
|
||||
* Creates the work for a loading thread
|
||||
* @param type The type of thread
|
||||
*/
|
||||
public LoadingThread(int type){
|
||||
threadType = type;
|
||||
lock = new Semaphore(1);
|
||||
@ -52,7 +58,7 @@ public class LoadingThread extends Thread {
|
||||
} break;
|
||||
|
||||
|
||||
//intended to act like you went through the steps of setting up a vanilla settings SP world
|
||||
//intended to act like you went through the steps of setting up a vanilla settings SP world
|
||||
case LOAD_DEBUG_RANDOM_SP_WORLD: {
|
||||
DebugSPWorldLoading.loadDebugSPWorld();
|
||||
} break;
|
||||
@ -66,12 +72,20 @@ public class LoadingThread extends Thread {
|
||||
case LOAD_LEVEL: {
|
||||
LevelLoading.loadLevel();
|
||||
} break;
|
||||
|
||||
//the demo menu ui
|
||||
case LOAD_DEMO_MENU: {
|
||||
DemoLoading.loadDemoMenu();
|
||||
} break;
|
||||
|
||||
}
|
||||
lock.release();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Checks if the thread has finished loading
|
||||
* @return true if it has finished, false otherwise
|
||||
*/
|
||||
public boolean isDone(){
|
||||
boolean rVal = lock.tryAcquire();
|
||||
if(rVal == true){
|
||||
|
||||
@ -198,8 +198,15 @@ public class LoadingUtils {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Loads graphics assets necessary for the client of the game engine. This should be stuff that is used essentially universally (ie textures for debugging).
|
||||
*/
|
||||
static void initGameGraphicalEntities(){
|
||||
|
||||
Globals.assetManager.addTexturePathtoQueue("Textures/transparent_red.png");
|
||||
Globals.assetManager.addTexturePathtoQueue("Textures/transparent_blue.png");
|
||||
Globals.assetManager.addTexturePathtoQueue("Textures/transparent_grey.png");
|
||||
|
||||
|
||||
float skyR = 100;
|
||||
float skyG = 150;
|
||||
|
||||
@ -256,7 +256,6 @@ public class EntityDataStrings {
|
||||
/*
|
||||
Equip state
|
||||
*/
|
||||
public static final String EQUIP_STATE = "equipState";
|
||||
public static final String TREE_CLIENTEQUIPSTATE = "treeClientEquipState";
|
||||
public static final String EQUIP_INVENTORY = "equipInventory";
|
||||
public static final String TREE_SERVEREQUIPSTATE = "treeServerEquipState";
|
||||
|
||||
@ -8,6 +8,7 @@ import electrosphere.server.datacell.ServerDataCell;
|
||||
import electrosphere.server.datacell.utils.EntityLookupUtils;
|
||||
import electrosphere.server.poseactor.PoseActor;
|
||||
import electrosphere.server.poseactor.PoseActorUtils;
|
||||
import electrosphere.util.MathUtils;
|
||||
|
||||
import org.joml.Quaterniond;
|
||||
import org.joml.Vector3d;
|
||||
@ -62,7 +63,7 @@ public class EntityUtils {
|
||||
Entity rVal = new Entity();
|
||||
rVal.putData(EntityDataStrings.DATA_STRING_ACTOR, ActorUtils.createActorOfLoadingModel(modelPath));
|
||||
rVal.putData(EntityDataStrings.DATA_STRING_POSITION, new Vector3d(0,0,0));
|
||||
rVal.putData(EntityDataStrings.DATA_STRING_ROTATION, new Quaterniond().rotateAxis(0, new Vector3d(1,0,0)));
|
||||
rVal.putData(EntityDataStrings.DATA_STRING_ROTATION, new Quaterniond().rotateAxis(0, MathUtils.getOriginVector()));
|
||||
rVal.putData(EntityDataStrings.DATA_STRING_SCALE, new Vector3f(1,1,1));
|
||||
rVal.putData(EntityDataStrings.DATA_STRING_DRAW, true);
|
||||
rVal.putData(EntityDataStrings.DRAW_SOLID_PASS, true);
|
||||
@ -92,7 +93,7 @@ public class EntityUtils {
|
||||
Entity rVal = new Entity();
|
||||
rVal.putData(EntityDataStrings.DATA_STRING_ACTOR, ActorUtils.createActorFromModelPath(modelPath));
|
||||
rVal.putData(EntityDataStrings.DATA_STRING_POSITION, new Vector3d(0,0,0));
|
||||
rVal.putData(EntityDataStrings.DATA_STRING_ROTATION, new Quaterniond().rotateAxis(0, new Vector3d(1,0,0)));
|
||||
rVal.putData(EntityDataStrings.DATA_STRING_ROTATION, new Quaterniond().rotateAxis(0, MathUtils.getOriginVector()));
|
||||
rVal.putData(EntityDataStrings.DATA_STRING_SCALE, new Vector3f(1,1,1));
|
||||
rVal.putData(EntityDataStrings.DATA_STRING_UI_ELEMENT, true);
|
||||
Globals.clientScene.registerEntity(rVal);
|
||||
|
||||
@ -11,7 +11,7 @@ import electrosphere.entity.btree.BehaviorTree;
|
||||
import electrosphere.entity.state.client.firstPerson.FirstPersonTree;
|
||||
import electrosphere.entity.state.collidable.Impulse;
|
||||
import electrosphere.entity.state.equip.ClientEquipState;
|
||||
import electrosphere.entity.state.hitbox.HitboxState;
|
||||
import electrosphere.entity.state.hitbox.HitboxCollectionState;
|
||||
import electrosphere.entity.state.rotator.RotatorTree;
|
||||
import electrosphere.entity.types.attach.AttachUtils;
|
||||
import electrosphere.entity.types.collision.CollisionObjUtils;
|
||||
@ -267,8 +267,8 @@ public class ClientAttackTree implements BehaviorTree {
|
||||
//activate hitboxes
|
||||
List<Entity> attachedEntities = AttachUtils.getChildrenList(parent);
|
||||
for(Entity currentAttached : attachedEntities){
|
||||
if(HitboxState.hasHitboxState(currentAttached)){
|
||||
HitboxState currentState = HitboxState.getHitboxState(currentAttached);
|
||||
if(HitboxCollectionState.hasHitboxState(currentAttached)){
|
||||
HitboxCollectionState currentState = HitboxCollectionState.getHitboxState(currentAttached);
|
||||
currentState.setActive(true);
|
||||
}
|
||||
}
|
||||
@ -277,8 +277,8 @@ public class ClientAttackTree implements BehaviorTree {
|
||||
//deactive hitboxes
|
||||
List<Entity> attachedEntities = AttachUtils.getChildrenList(parent);
|
||||
for(Entity currentAttached : attachedEntities){
|
||||
if(HitboxState.hasHitboxState(currentAttached)){
|
||||
HitboxState currentState = HitboxState.getHitboxState(currentAttached);
|
||||
if(HitboxCollectionState.hasHitboxState(currentAttached)){
|
||||
HitboxCollectionState currentState = HitboxCollectionState.getHitboxState(currentAttached);
|
||||
currentState.setActive(false);
|
||||
}
|
||||
}
|
||||
@ -308,7 +308,7 @@ public class ClientAttackTree implements BehaviorTree {
|
||||
String rVal = null;
|
||||
if(ClientEquipState.hasEquipState(parent)){
|
||||
ClientEquipState equipState = ClientEquipState.getEquipState(parent);
|
||||
for(String point : equipState.equippedPoints()){
|
||||
for(String point : equipState.getEquippedPoints()){
|
||||
Entity item = equipState.getEquippedItemAtPoint(point);
|
||||
if(ItemUtils.isWeapon(item)){
|
||||
attackingPoint = point;
|
||||
|
||||
@ -19,7 +19,7 @@ import electrosphere.entity.state.attack.ClientAttackTree.AttackTreeState;
|
||||
import electrosphere.entity.state.client.firstPerson.FirstPersonTree;
|
||||
import electrosphere.entity.state.collidable.Impulse;
|
||||
import electrosphere.entity.state.equip.ServerEquipState;
|
||||
import electrosphere.entity.state.hitbox.HitboxState;
|
||||
import electrosphere.entity.state.hitbox.HitboxCollectionState;
|
||||
import electrosphere.entity.state.movement.groundmove.ServerGroundMovementTree;
|
||||
import electrosphere.entity.state.rotator.ServerRotatorTree;
|
||||
import electrosphere.entity.types.attach.AttachUtils;
|
||||
@ -35,6 +35,7 @@ import electrosphere.net.synchronization.annotation.SynchronizedBehaviorTree;
|
||||
import electrosphere.renderer.actor.Actor;
|
||||
import electrosphere.server.datacell.Realm;
|
||||
import electrosphere.server.poseactor.PoseActor;
|
||||
import electrosphere.util.MathUtils;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
@ -139,7 +140,7 @@ public class ServerAttackTree implements BehaviorTree {
|
||||
}
|
||||
}
|
||||
Vector3d movementVector = CreatureUtils.getFacingVector(parent);
|
||||
EntityUtils.getRotation(parent).rotationTo(new Vector3d(0,0,1), new Vector3d(movementVector.x,movementVector.y,movementVector.z));
|
||||
EntityUtils.getRotation(parent).rotationTo(MathUtils.getOriginVector(), new Vector3d(movementVector.x,movementVector.y,movementVector.z));
|
||||
//set initial stuff (this alerts the client as well)
|
||||
setCurrentMoveId(currentMove.getAttackMoveId());
|
||||
setState(AttackTreeState.WINDUP);
|
||||
@ -267,8 +268,8 @@ public class ServerAttackTree implements BehaviorTree {
|
||||
//activate hitboxes
|
||||
List<Entity> attachedEntities = AttachUtils.getChildrenList(parent);
|
||||
for(Entity currentAttached : attachedEntities){
|
||||
if(HitboxState.hasHitboxState(currentAttached)){
|
||||
HitboxState currentState = HitboxState.getHitboxState(currentAttached);
|
||||
if(HitboxCollectionState.hasHitboxState(currentAttached)){
|
||||
HitboxCollectionState currentState = HitboxCollectionState.getHitboxState(currentAttached);
|
||||
currentState.setActive(true);
|
||||
}
|
||||
}
|
||||
@ -299,7 +300,7 @@ public class ServerAttackTree implements BehaviorTree {
|
||||
// EntityUtils.getRotation(currentEntity).set(rotation).normalize();
|
||||
// Vector3d facingAngle = CreatureUtils.getFacingVector(parent);
|
||||
arrowRotation = parentActor.getBoneRotation(targetBone);
|
||||
// EntityUtils.getRotation(currentEntity).rotationTo(new Vector3f(0,0,1), new Vector3f((float)facingAngle.x,(float)facingAngle.y,(float)facingAngle.z)).mul(parentActor.getBoneRotation(targetBone)).normalize();
|
||||
// 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();
|
||||
Realm parentRealm = Globals.realmManager.getEntityRealm(parent);
|
||||
@ -328,8 +329,8 @@ public class ServerAttackTree implements BehaviorTree {
|
||||
//deactive hitboxes
|
||||
List<Entity> attachedEntities = AttachUtils.getChildrenList(parent);
|
||||
for(Entity currentAttached : attachedEntities){
|
||||
if(HitboxState.hasHitboxState(currentAttached)){
|
||||
HitboxState currentState = HitboxState.getHitboxState(currentAttached);
|
||||
if(HitboxCollectionState.hasHitboxState(currentAttached)){
|
||||
HitboxCollectionState currentState = HitboxCollectionState.getHitboxState(currentAttached);
|
||||
currentState.setActive(false);
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,27 @@
|
||||
package electrosphere.entity.state.block;
|
||||
|
||||
import electrosphere.net.synchronization.annotation.SyncedField;
|
||||
import electrosphere.net.synchronization.annotation.SynchronizableEnum;
|
||||
import electrosphere.net.synchronization.annotation.SynchronizedBehaviorTree;
|
||||
|
||||
@SynchronizedBehaviorTree(name = "clientBlockTree", isServer = false, correspondingTree="serverBlockTree")
|
||||
/**
|
||||
* Client block tree
|
||||
*/
|
||||
public class ClientBlockTree {
|
||||
|
||||
@SynchronizableEnum
|
||||
/**
|
||||
* The state of the block tree
|
||||
*/
|
||||
public enum BlockState {
|
||||
BLOCKING,
|
||||
NOT_BLOCKING,
|
||||
}
|
||||
|
||||
@SyncedField
|
||||
BlockState state;
|
||||
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,16 @@
|
||||
package electrosphere.entity.state.block;
|
||||
|
||||
import electrosphere.entity.state.block.ClientBlockTree.BlockState;
|
||||
import electrosphere.net.synchronization.annotation.SyncedField;
|
||||
import electrosphere.net.synchronization.annotation.SynchronizedBehaviorTree;
|
||||
|
||||
@SynchronizedBehaviorTree(name = "serverBlockTree", isServer = true, correspondingTree="clientBlockTree")
|
||||
/**
|
||||
* Server block tree
|
||||
*/
|
||||
public class ServerBlockTree {
|
||||
|
||||
@SyncedField
|
||||
BlockState state;
|
||||
|
||||
}
|
||||
@ -48,7 +48,7 @@ public class ClientEquipState implements BehaviorTree {
|
||||
* @param parent the entity this is attached to
|
||||
* @param equipPoints the list of available points
|
||||
*/
|
||||
public ClientEquipState(Entity parent, List<EquipPoint> equipPoints){
|
||||
private ClientEquipState(Entity parent, List<EquipPoint> equipPoints){
|
||||
this.parent = parent;
|
||||
for(EquipPoint point : equipPoints){
|
||||
this.equipPoints.add(point);
|
||||
@ -59,10 +59,19 @@ public class ClientEquipState implements BehaviorTree {
|
||||
* Gets the list of equipped points
|
||||
* @return the list
|
||||
*/
|
||||
public List<String> equippedPoints(){
|
||||
public List<String> getEquippedPoints(){
|
||||
return new LinkedList<String>(equipMap.keySet());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the list of all equip points
|
||||
* @return The list of all equip points
|
||||
*/
|
||||
public List<EquipPoint> getAllEquipPoints(){
|
||||
return equipPoints;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to equip the item
|
||||
* @param toEquip the item to equip
|
||||
@ -221,7 +230,7 @@ public class ClientEquipState implements BehaviorTree {
|
||||
* @return True if the entity contains an equip state, false otherwise
|
||||
*/
|
||||
public static boolean hasEquipState(Entity entity){
|
||||
return entity.containsKey(EntityDataStrings.EQUIP_STATE);
|
||||
return entity.containsKey(EntityDataStrings.TREE_CLIENTEQUIPSTATE);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -230,7 +239,7 @@ public class ClientEquipState implements BehaviorTree {
|
||||
* @return The equip state on the entity
|
||||
*/
|
||||
public static ClientEquipState getEquipState(Entity entity){
|
||||
return (ClientEquipState)entity.getData(EntityDataStrings.EQUIP_STATE);
|
||||
return (ClientEquipState)entity.getData(EntityDataStrings.TREE_CLIENTEQUIPSTATE);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -239,7 +248,7 @@ public class ClientEquipState implements BehaviorTree {
|
||||
* @param equipState The equip state to attach
|
||||
*/
|
||||
public static void setEquipState(Entity entity, ClientEquipState equipState){
|
||||
entity.putData(EntityDataStrings.EQUIP_STATE, equipState);
|
||||
entity.putData(EntityDataStrings.TREE_CLIENTEQUIPSTATE, equipState);
|
||||
}
|
||||
|
||||
// public void drop(Entity entity){
|
||||
|
||||
@ -190,7 +190,7 @@ public class ServerEquipState implements BehaviorTree {
|
||||
* @return True if the entity contains an equip state, false otherwise
|
||||
*/
|
||||
public static boolean hasEquipState(Entity entity){
|
||||
return entity.containsKey(EntityDataStrings.EQUIP_STATE);
|
||||
return entity.containsKey(EntityDataStrings.TREE_SERVEREQUIPSTATE);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -199,7 +199,7 @@ public class ServerEquipState implements BehaviorTree {
|
||||
* @return The equip state on the entity
|
||||
*/
|
||||
public static ServerEquipState getEquipState(Entity entity){
|
||||
return (ServerEquipState)entity.getData(EntityDataStrings.EQUIP_STATE);
|
||||
return (ServerEquipState)entity.getData(EntityDataStrings.TREE_SERVEREQUIPSTATE);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -208,7 +208,7 @@ public class ServerEquipState implements BehaviorTree {
|
||||
* @param equipState The equip state to attach
|
||||
*/
|
||||
public static void setEquipState(Entity entity, ServerEquipState equipState){
|
||||
entity.putData(EntityDataStrings.EQUIP_STATE, equipState);
|
||||
entity.putData(EntityDataStrings.TREE_SERVEREQUIPSTATE, equipState);
|
||||
}
|
||||
|
||||
// public void drop(Entity entity){
|
||||
|
||||
@ -52,7 +52,7 @@ public class AmbientFoliage implements BehaviorTree {
|
||||
|
||||
//rotate to face cameras
|
||||
// Vector3f cameraEyeVector = CameraEntityUtils.getCameraEye(Globals.playerCamera);
|
||||
// EntityUtils.getRotation(parent).rotateTo(new Vector3d(1,0,0), new Vector3d(cameraEyeVector));
|
||||
// EntityUtils.getRotation(parent).rotateTo(MathUtils.ORIGIN_VECTOR, new Vector3d(cameraEyeVector));
|
||||
|
||||
|
||||
//TODO: simulate wind offset
|
||||
|
||||
@ -0,0 +1,594 @@
|
||||
package electrosphere.entity.state.hitbox;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.joml.Quaterniond;
|
||||
import org.joml.Vector3d;
|
||||
import org.joml.Vector3f;
|
||||
import org.ode4j.ode.DBody;
|
||||
import org.ode4j.ode.DGeom;
|
||||
|
||||
import electrosphere.collision.CollisionBodyCreation;
|
||||
import electrosphere.collision.CollisionEngine;
|
||||
import electrosphere.collision.PhysicsEntityUtils;
|
||||
import electrosphere.collision.PhysicsUtils;
|
||||
import electrosphere.collision.collidable.Collidable;
|
||||
import electrosphere.collision.hitbox.HitboxManager;
|
||||
import electrosphere.collision.hitbox.HitboxUtils.HitboxPositionCallback;
|
||||
import electrosphere.entity.Entity;
|
||||
import electrosphere.entity.EntityDataStrings;
|
||||
import electrosphere.entity.EntityUtils;
|
||||
import electrosphere.entity.state.hitbox.HitboxCollectionState.HitboxState.HitboxShapeType;
|
||||
import electrosphere.game.data.collidable.HitboxData;
|
||||
import electrosphere.util.MathUtils;
|
||||
|
||||
/**
|
||||
* The state of the collection of all hitboxes on this entity
|
||||
* Ie, it stores the state of each hitbox that is attached to this entity
|
||||
*/
|
||||
public class HitboxCollectionState {
|
||||
|
||||
/**
|
||||
* Types of hitboxes
|
||||
*/
|
||||
public enum HitboxType {
|
||||
HIT, // damages another entity
|
||||
HURT, // receives damage from another entity
|
||||
BLOCK, // blocks a hit from another entity
|
||||
}
|
||||
|
||||
//the parent entity of the hitbox state
|
||||
Entity parent;
|
||||
|
||||
//the body that contains all the hitbox shapes
|
||||
DBody body;
|
||||
|
||||
//The collidable associated with the body
|
||||
Collidable collidable;
|
||||
|
||||
//the list of all geoms in the collection state
|
||||
List<DGeom> geoms = new LinkedList<DGeom>();
|
||||
//the map of bone -> hitbox shape in ode4j
|
||||
Map<String,DGeom> hitboxGeomMap = new HashMap<String,DGeom>();
|
||||
//the map of geometry -> hitbox shape status, useful for finding data about a given hitbox during collision
|
||||
Map<DGeom,HitboxState> geomStateMap = new HashMap<DGeom,HitboxState>();
|
||||
|
||||
//callback to provide a position for the hitbox each frame
|
||||
HitboxPositionCallback positionCallback;
|
||||
|
||||
//controls whether the hitbox state is active or not
|
||||
boolean active = true;
|
||||
|
||||
//the associated manager
|
||||
HitboxManager manager;
|
||||
|
||||
//controls whether this hitbox collection thinks its on the server or client
|
||||
boolean isServer = true;
|
||||
|
||||
|
||||
/**
|
||||
* Create hitbox state for an entity
|
||||
* @param collisionEngine the collision engine
|
||||
* @param entity The entity to attach the state to
|
||||
* @param hitboxListRaw The list of hitbox data to apply
|
||||
* @return The hitbox state that has been attached to the entity
|
||||
*/
|
||||
public static HitboxCollectionState attachHitboxState(HitboxManager manager, boolean isServer, Entity entity, List<HitboxData> hitboxListRaw){
|
||||
HitboxCollectionState rVal = new HitboxCollectionState();
|
||||
|
||||
rVal.isServer = isServer;
|
||||
//create the shapes
|
||||
for(HitboxData hitboxDataRaw : hitboxListRaw){
|
||||
DGeom geom = null;
|
||||
HitboxType type = HitboxType.HIT;
|
||||
HitboxShapeType shapeType = HitboxShapeType.SPHERE;
|
||||
switch(hitboxDataRaw.getType()){
|
||||
case HitboxData.HITBOX_TYPE_HIT: {
|
||||
type = HitboxType.HIT;
|
||||
shapeType = HitboxShapeType.SPHERE;
|
||||
geom = CollisionBodyCreation.createShapeSphere(manager.getCollisionEngine(), hitboxDataRaw.getRadius(), Collidable.TYPE_OBJECT_BIT);
|
||||
} break;
|
||||
case HitboxData.HITBOX_TYPE_HURT: {
|
||||
type = HitboxType.HURT;
|
||||
shapeType = HitboxShapeType.SPHERE;
|
||||
geom = CollisionBodyCreation.createShapeSphere(manager.getCollisionEngine(), hitboxDataRaw.getRadius(), Collidable.TYPE_OBJECT_BIT);
|
||||
} break;
|
||||
case HitboxData.HITBOX_TYPE_HIT_CONNECTED: {
|
||||
type = HitboxType.HIT;
|
||||
shapeType = HitboxShapeType.CAPSULE;
|
||||
geom = CollisionBodyCreation.createShapeSphere(manager.getCollisionEngine(), hitboxDataRaw.getRadius(), Collidable.TYPE_OBJECT_BIT);
|
||||
} break;
|
||||
case HitboxData.HITBOX_TYPE_HURT_CONNECTED: {
|
||||
type = HitboxType.HURT;
|
||||
shapeType = HitboxShapeType.CAPSULE;
|
||||
geom = CollisionBodyCreation.createShapeSphere(manager.getCollisionEngine(), hitboxDataRaw.getRadius(), Collidable.TYPE_OBJECT_BIT);
|
||||
} break;
|
||||
case HitboxData.HITBOX_TYPE_STATIC_CAPSULE: {
|
||||
type = HitboxType.HURT;
|
||||
shapeType = HitboxShapeType.STATIC_CAPSULE;
|
||||
geom = CollisionBodyCreation.createCapsuleShape(manager.getCollisionEngine(), hitboxDataRaw.getRadius(), hitboxDataRaw.getLength(), Collidable.TYPE_OBJECT_BIT);
|
||||
} break;
|
||||
}
|
||||
if(hitboxDataRaw.getBone() != null){
|
||||
rVal.hitboxGeomMap.put(hitboxDataRaw.getBone(),geom);
|
||||
}
|
||||
rVal.geoms.add(geom);
|
||||
rVal.geomStateMap.put(geom,new HitboxState(hitboxDataRaw.getBone(), hitboxDataRaw, type, shapeType, true));
|
||||
}
|
||||
|
||||
//create body with all the shapes
|
||||
DGeom[] geomArray = rVal.geoms.toArray(new DGeom[rVal.geoms.size()]);
|
||||
rVal.body = CollisionBodyCreation.createBodyWithShapes(manager.getCollisionEngine(), geomArray);
|
||||
|
||||
//register collidable with collision engine
|
||||
Collidable collidable = new Collidable(entity, Collidable.TYPE_OBJECT);
|
||||
manager.getCollisionEngine().registerCollisionObject(rVal.body, collidable);
|
||||
|
||||
//attach
|
||||
entity.putData(EntityDataStrings.HITBOX_DATA, rVal);
|
||||
rVal.parent = entity;
|
||||
|
||||
//register
|
||||
manager.registerHitbox(rVal);
|
||||
rVal.manager = manager;
|
||||
|
||||
return rVal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create hitbox state for an entity
|
||||
* @param collisionEngine the collision engine
|
||||
* @param entity The entity to attach the state to
|
||||
* @param data The hitbox data to apply
|
||||
* @param callback The callback that provides a position for the hitbox each frame
|
||||
* @return The hitbox state that has been attached to the entity
|
||||
*/
|
||||
public static HitboxCollectionState attachHitboxStateWithCallback(HitboxManager manager, CollisionEngine collisionEngine, Entity entity, HitboxData data, HitboxPositionCallback callback){
|
||||
HitboxCollectionState rVal = new HitboxCollectionState();
|
||||
|
||||
//create the shapes
|
||||
rVal.hitboxGeomMap.put(data.getBone(),CollisionBodyCreation.createShapeSphere(collisionEngine, data.getRadius(), Collidable.TYPE_OBJECT_BIT));
|
||||
|
||||
//create body with all the shapes
|
||||
DGeom[] geomArray = rVal.hitboxGeomMap.values().toArray(new DGeom[rVal.hitboxGeomMap.values().size()]);
|
||||
rVal.body = CollisionBodyCreation.createBodyWithShapes(collisionEngine, geomArray);
|
||||
|
||||
//register collidable with collision engine
|
||||
Collidable collidable = new Collidable(entity, Collidable.TYPE_OBJECT);
|
||||
collisionEngine.registerCollisionObject(rVal.body, collidable);
|
||||
|
||||
//attach
|
||||
entity.putData(EntityDataStrings.HITBOX_DATA, rVal);
|
||||
rVal.parent = entity;
|
||||
|
||||
//register
|
||||
manager.registerHitbox(rVal);
|
||||
rVal.manager = manager;
|
||||
|
||||
return rVal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the collision status of all shapes
|
||||
*/
|
||||
public void clearCollisions(){
|
||||
for(DGeom geom : this.geoms){
|
||||
HitboxState shapeStatus = this.geomStateMap.get(geom);
|
||||
shapeStatus.setHadCollision(false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the positions of all hitboxes
|
||||
*/
|
||||
public void updateHitboxPositions(CollisionEngine collisionEngine){
|
||||
if(parent != null && !isServer && EntityUtils.getActor(parent) != null){
|
||||
if(!this.hitboxGeomMap.isEmpty()){
|
||||
Vector3d entityPosition = EntityUtils.getPosition(parent);
|
||||
this.body.setPosition(PhysicsUtils.jomlVecToOdeVec(entityPosition));
|
||||
for(String boneName : this.hitboxGeomMap.keySet()){
|
||||
Vector3f bonePosition = EntityUtils.getActor(parent).getBonePosition(boneName);
|
||||
DGeom geom = this.hitboxGeomMap.get(boneName);
|
||||
HitboxState shapeStatus = this.geomStateMap.get(geom);
|
||||
switch(shapeStatus.shapeType){
|
||||
case SPHERE: {
|
||||
this.updateSphereShapePosition(collisionEngine,boneName,bonePosition);
|
||||
} break;
|
||||
case CAPSULE: {
|
||||
this.updateCapsuleShapePosition(collisionEngine,boneName,bonePosition);
|
||||
} break;
|
||||
case STATIC_CAPSULE: {
|
||||
} break;
|
||||
}
|
||||
}
|
||||
} else if(positionCallback != null){
|
||||
DGeom geom = body.getGeomIterator().next();
|
||||
Vector3d worldPosition = this.positionCallback.getPosition();
|
||||
Quaterniond rotation = new Quaterniond().identity();
|
||||
|
||||
PhysicsEntityUtils.setGeometryPosition(collisionEngine, geom, worldPosition, rotation);
|
||||
}
|
||||
} else if(parent != null && isServer && EntityUtils.getPoseActor(parent) != null){
|
||||
if(!this.hitboxGeomMap.isEmpty()){
|
||||
Vector3d entityPosition = EntityUtils.getPosition(parent);
|
||||
this.body.setPosition(PhysicsUtils.jomlVecToOdeVec(entityPosition));
|
||||
for(String boneName : this.hitboxGeomMap.keySet()){
|
||||
Vector3f bonePosition = EntityUtils.getPoseActor(parent).getBonePosition(boneName);
|
||||
DGeom geom = this.hitboxGeomMap.get(boneName);
|
||||
HitboxState shapeStatus = this.geomStateMap.get(geom);
|
||||
switch(shapeStatus.shapeType){
|
||||
case SPHERE: {
|
||||
this.updateSphereShapePosition(collisionEngine,boneName,bonePosition);
|
||||
} break;
|
||||
case CAPSULE: {
|
||||
this.updateCapsuleShapePosition(collisionEngine,boneName,bonePosition);
|
||||
} break;
|
||||
case STATIC_CAPSULE: {
|
||||
} break;
|
||||
}
|
||||
}
|
||||
} else if(positionCallback != null){
|
||||
DGeom geom = body.getGeomIterator().next();
|
||||
Vector3d worldPosition = this.positionCallback.getPosition();
|
||||
Quaterniond rotation = new Quaterniond().identity();
|
||||
|
||||
PhysicsEntityUtils.setGeometryPosition(collisionEngine, geom, worldPosition, rotation);
|
||||
}
|
||||
} else if(parent != null && isServer){
|
||||
for(DGeom geom : this.geoms){
|
||||
HitboxState shapeStatus = this.geomStateMap.get(geom);
|
||||
switch(shapeStatus.shapeType){
|
||||
case SPHERE: {
|
||||
} break;
|
||||
case CAPSULE: {
|
||||
} break;
|
||||
case STATIC_CAPSULE: {
|
||||
this.updateStaticCapsulePosition(collisionEngine, geom, shapeStatus);
|
||||
} break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the position of the geom for a static capsule
|
||||
* @param collisionEngine The collision engine
|
||||
* @param boneName The name of the bone the static capsule is attached to
|
||||
* @param bonePosition The position of the bone
|
||||
*/
|
||||
private void updateStaticCapsulePosition(CollisionEngine collisionEngine, DGeom geom, HitboxState shapeStatus){
|
||||
Vector3d parentPos = EntityUtils.getPosition(parent);
|
||||
PhysicsEntityUtils.setGeometryPosition(collisionEngine, geom, parentPos, new Quaterniond(0.707,0,0,0.707));
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the position of a sphere-shape-type hitbox
|
||||
* @param collisionEngine The collision engine
|
||||
* @param boneName The name of the bone
|
||||
* @param bonePosition the position of the bone
|
||||
*/
|
||||
private void updateSphereShapePosition(CollisionEngine collisionEngine, String boneName, Vector3f bonePosition){
|
||||
DGeom geom = this.hitboxGeomMap.get(boneName);
|
||||
Quaterniond parentRotation = EntityUtils.getRotation(parent);
|
||||
Vector3f positionScale = EntityUtils.getScale(parent);
|
||||
Vector3d worldPosition = new Vector3d();
|
||||
Vector3d parentPos = EntityUtils.getPosition(parent);
|
||||
Quaterniond rotation = new Quaterniond(parentRotation);
|
||||
|
||||
//calculate new world pos
|
||||
worldPosition.set(bonePosition.x,bonePosition.y,bonePosition.z);
|
||||
worldPosition = worldPosition.mul(positionScale);
|
||||
worldPosition = worldPosition.rotate(rotation);
|
||||
worldPosition.add(new Vector3f((float)parentPos.x,(float)parentPos.y,(float)parentPos.z));
|
||||
|
||||
PhysicsEntityUtils.setGeometryPosition(collisionEngine, geom, worldPosition, rotation);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the position of a capsule-shape hitbox
|
||||
* @param collisionEngine
|
||||
* @param boneName
|
||||
* @param bonePosition
|
||||
*/
|
||||
private void updateCapsuleShapePosition(CollisionEngine collisionEngine, String boneName, Vector3f bonePosition){
|
||||
DGeom geom = this.hitboxGeomMap.get(boneName);
|
||||
HitboxState shapeStatus = this.geomStateMap.get(geom);
|
||||
Quaterniond parentRotation = EntityUtils.getRotation(parent);
|
||||
Vector3f positionScale = EntityUtils.getScale(parent);
|
||||
Vector3d worldPosition = new Vector3d();
|
||||
Vector3d parentPos = EntityUtils.getPosition(parent);
|
||||
Quaterniond rotation = new Quaterniond(parentRotation);
|
||||
Vector3d previousWorldPos = shapeStatus.getPreviousWorldPos();
|
||||
|
||||
//calculate new world pos
|
||||
worldPosition.set(bonePosition.x,bonePosition.y,bonePosition.z);
|
||||
worldPosition = worldPosition.mul(positionScale);
|
||||
worldPosition = worldPosition.rotate(rotation);
|
||||
worldPosition.add(new Vector3f((float)parentPos.x,(float)parentPos.y,(float)parentPos.z));
|
||||
double length = shapeStatus.getHitboxData().getRadius();
|
||||
double radius = shapeStatus.getHitboxData().getRadius();
|
||||
|
||||
if(previousWorldPos != null){
|
||||
//called all subsequent updates to hitbox position
|
||||
|
||||
//destroy old capsule
|
||||
this.geomStateMap.remove(geom);
|
||||
this.geoms.remove(geom);
|
||||
CollisionBodyCreation.destroyShape(collisionEngine, geom);
|
||||
|
||||
//calculate position between new world point and old world point
|
||||
Vector3d bodyPosition = new Vector3d(worldPosition).lerp(previousWorldPos, 0.5);
|
||||
|
||||
//calculate rotation from old position to new position
|
||||
//the second quaternion is a rotation along the x axis. This is used to put the hitbox rotation into ode's space
|
||||
//ode is Z-axis-up
|
||||
rotation = MathUtils.calculateRotationFromPointToPoint(previousWorldPos,worldPosition).mul(new Quaterniond(0,0,0.707,0.707));
|
||||
|
||||
//create new capsule
|
||||
length = previousWorldPos.distance(worldPosition) / 2.0;
|
||||
if(length > 5000 || Double.isNaN(length) || Double.isInfinite(length) || length <= 0){
|
||||
length = 0.1;
|
||||
System.out.println("HitboxState --- THIS IS NAN WHEN YOU SPAWN A KATANA BECAUSE THE BONE POSITION IS NAN???");
|
||||
}
|
||||
geom = CollisionBodyCreation.createCapsuleShape(manager.getCollisionEngine(), shapeStatus.getHitboxData().getRadius(), length, Collidable.TYPE_OBJECT_BIT);
|
||||
CollisionBodyCreation.attachGeomToBody(collisionEngine,body,geom);
|
||||
PhysicsEntityUtils.setGeometryPosition(collisionEngine, geom, bodyPosition, rotation);
|
||||
} else {
|
||||
//called first time the hitbox updates position
|
||||
this.geomStateMap.remove(geom);
|
||||
this.geoms.remove(geom);
|
||||
CollisionBodyCreation.destroyShape(collisionEngine, geom);
|
||||
|
||||
//create new capsule
|
||||
geom = CollisionBodyCreation.createCapsuleShape(manager.getCollisionEngine(), shapeStatus.getHitboxData().getRadius(), length, Collidable.TYPE_OBJECT_BIT);
|
||||
CollisionBodyCreation.attachGeomToBody(collisionEngine,body,geom);
|
||||
}
|
||||
//update maps and other variables for next frame
|
||||
this.hitboxGeomMap.put(boneName,geom);
|
||||
this.geomStateMap.put(geom,shapeStatus);
|
||||
this.geoms.add(geom);
|
||||
shapeStatus.setPreviousWorldPos(worldPosition);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the status of a shape in the hitbox object
|
||||
* @param geom The geometry that is the shape within the hitbox data
|
||||
* @return The status of the shape
|
||||
*/
|
||||
public HitboxState getShapeStatus(DGeom geom){
|
||||
return this.geomStateMap.get(geom);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the hitbox state of the entity
|
||||
* @param entity the entity
|
||||
* @return the hitbox state if it exists
|
||||
*/
|
||||
public static HitboxCollectionState getHitboxState(Entity entity){
|
||||
return (HitboxCollectionState)entity.getData(EntityDataStrings.HITBOX_DATA);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the entity has hitbox state or not
|
||||
* @param entity the entity to check
|
||||
* @return true if there is hitbox state, false otherwise
|
||||
*/
|
||||
public static boolean hasHitboxState(Entity entity){
|
||||
return entity.containsKey(EntityDataStrings.HITBOX_DATA);
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroys the hitbox state and removes it from the entity
|
||||
* @param entity the entity
|
||||
* @return The hitbox state if it exists, null otherwise
|
||||
*/
|
||||
public static HitboxCollectionState destroyHitboxState(Entity entity){
|
||||
HitboxCollectionState state = null;
|
||||
if(hasHitboxState(entity)){
|
||||
state = getHitboxState(entity);
|
||||
state.manager.deregisterHitbox(state);
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether the hitbox state is active or not
|
||||
* @return true if active, false otherwise
|
||||
*/
|
||||
public boolean isActive(){
|
||||
return active;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the active state of the hitbox
|
||||
* @param state true to make it active, false otherwise
|
||||
*/
|
||||
public void setActive(boolean state){
|
||||
this.active = state;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the list of all DGeoms in the data
|
||||
* @return the list of all DGeoms
|
||||
*/
|
||||
public List<DGeom> getGeometries(){
|
||||
return this.geoms;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the set of bone names in the state data
|
||||
* @return The set of bone names in the state data
|
||||
*/
|
||||
public Set<String> getBones(){
|
||||
return this.hitboxGeomMap.keySet();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets geometry on a single hitbox based on its bone name
|
||||
* @param boneName the bone name
|
||||
* @return the hitbox geometry
|
||||
*/
|
||||
public DGeom getGeometry(String boneName){
|
||||
return this.hitboxGeomMap.get(boneName);
|
||||
}
|
||||
|
||||
/**
|
||||
* The status of a single shape inside the overall hitbox data
|
||||
* IE a single sphere on the overall body
|
||||
*/
|
||||
public static class HitboxState {
|
||||
|
||||
/**
|
||||
* Types of geometry that can be used as individual shapes within a hitbox
|
||||
*/
|
||||
public enum HitboxShapeType {
|
||||
//this is a true sphere. It will teleport every frame to its new position
|
||||
SPHERE,
|
||||
//for this one, the shape is a capsule in the collision engine, however
|
||||
//the capsule is used to have continuity between the last position the hitbox occupied and the current one
|
||||
CAPSULE,
|
||||
//this is a true static capsule, it doesn't act as two connected spheres but is instead a capsule that teleports between frames
|
||||
STATIC_CAPSULE,
|
||||
}
|
||||
|
||||
//the name of the bone the hitbox is attached to
|
||||
String boneName;
|
||||
|
||||
//the type of hitbox
|
||||
HitboxType type;
|
||||
|
||||
//the type of geometry
|
||||
HitboxShapeType shapeType;
|
||||
|
||||
//controls whether the hitbox is active
|
||||
boolean isActive;
|
||||
|
||||
//the previous position of this hitbox shape
|
||||
Vector3d previousWorldPos = null;
|
||||
|
||||
//if true, just had a collision
|
||||
boolean hadCollision = false;
|
||||
|
||||
//the data of the hitbox
|
||||
HitboxData data;
|
||||
|
||||
/**
|
||||
* Creates a status object for a hitbox
|
||||
* @param boneName The name of the bone the hitbox is attached to, if any
|
||||
* @param data the hitbox data object
|
||||
* @param type The type of hitbox
|
||||
* @param shapeType The type of shape the hitbox is
|
||||
* @param isActive if the hitbox is active or not
|
||||
*/
|
||||
public HitboxState(String boneName, HitboxData data, HitboxType type, HitboxShapeType shapeType, boolean isActive){
|
||||
this.boneName = boneName;
|
||||
this.data = data;
|
||||
this.type = type;
|
||||
this.shapeType = shapeType;
|
||||
this.isActive = isActive;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of the bone the hitbox is attached to
|
||||
* @return The name of the bone
|
||||
*/
|
||||
public String getBoneName(){
|
||||
return boneName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the name of the bone the hitbox is attached to
|
||||
* @param boneName The bone name
|
||||
*/
|
||||
public void setBoneName(String boneName){
|
||||
this.boneName = boneName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the hitbox data for this shape
|
||||
* @return The data
|
||||
*/
|
||||
public HitboxData getHitboxData(){
|
||||
return this.data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the hitbox data for this shape
|
||||
* @param data The data
|
||||
*/
|
||||
public void setHitboxData(HitboxData data){
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the type of hitbox
|
||||
* @return The type
|
||||
*/
|
||||
public HitboxType getType(){
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the type of hitbox
|
||||
* @param type The type
|
||||
*/
|
||||
public void setType(HitboxType type){
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether the hitbox is active or not
|
||||
* @return true if active, false otherwise
|
||||
*/
|
||||
public boolean isActive(){
|
||||
return isActive;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether the hitbox is active or not
|
||||
* @param active true for active, false otherwise
|
||||
*/
|
||||
public void setActive(boolean active){
|
||||
this.isActive = active;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the previous world position of this hitbox
|
||||
* @return The previous world position
|
||||
*/
|
||||
public Vector3d getPreviousWorldPos(){
|
||||
return this.previousWorldPos;
|
||||
}
|
||||
|
||||
/**
|
||||
* sets the previous world position of this hitbox shape
|
||||
* @param previousWorldPos The previous world position
|
||||
*/
|
||||
public void setPreviousWorldPos(Vector3d previousWorldPos){
|
||||
this.previousWorldPos = previousWorldPos;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the status of whether this hitbox just had a collision or not
|
||||
* @param hadCollision true if had a collision, false otherwise
|
||||
*/
|
||||
public void setHadCollision(boolean hadCollision){
|
||||
this.hadCollision = hadCollision;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the collision status of the hitbox
|
||||
* @return true if had a collision, false otherwise
|
||||
*/
|
||||
public boolean getHadCollision(){
|
||||
return this.hadCollision;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,370 +0,0 @@
|
||||
package electrosphere.entity.state.hitbox;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.joml.Quaterniond;
|
||||
import org.joml.Vector3d;
|
||||
import org.joml.Vector3f;
|
||||
import org.ode4j.ode.DBody;
|
||||
import org.ode4j.ode.DGeom;
|
||||
|
||||
import electrosphere.collision.CollisionBodyCreation;
|
||||
import electrosphere.collision.CollisionEngine;
|
||||
import electrosphere.collision.PhysicsEntityUtils;
|
||||
import electrosphere.collision.PhysicsUtils;
|
||||
import electrosphere.collision.collidable.Collidable;
|
||||
import electrosphere.collision.hitbox.HitboxManager;
|
||||
import electrosphere.collision.hitbox.HitboxUtils.HitboxPositionCallback;
|
||||
import electrosphere.entity.Entity;
|
||||
import electrosphere.entity.EntityDataStrings;
|
||||
import electrosphere.entity.EntityUtils;
|
||||
import electrosphere.game.data.collidable.HitboxData;
|
||||
|
||||
/**
|
||||
* The hitbox state of this entity
|
||||
*/
|
||||
public class HitboxState {
|
||||
|
||||
/**
|
||||
* Types of hitboxes
|
||||
*/
|
||||
public enum HitboxType {
|
||||
HIT, // damages another entity
|
||||
HURT, // receives damage from another entity
|
||||
BLOCK, // blocks a hit from another entity
|
||||
}
|
||||
|
||||
//the parent entity of the hitbox state
|
||||
Entity parent;
|
||||
|
||||
//the body that contains all the hitbox shapes
|
||||
DBody body;
|
||||
|
||||
//The collidable associated with the body
|
||||
Collidable collidable;
|
||||
|
||||
//the map of bone -> hitbox shape in ode4j
|
||||
Map<String,DGeom> hitboxGeomMap = new HashMap<String,DGeom>();
|
||||
//the map of geometry -> hitbox shape status, useful for finding data about a given hitbox during collision
|
||||
Map<DGeom,HitboxShapeStatus> geomBoneMap = new HashMap<DGeom,HitboxShapeStatus>();
|
||||
|
||||
//callback to provide a position for the hitbox each frame
|
||||
HitboxPositionCallback positionCallback;
|
||||
|
||||
//controls whether the hitbox state is active or not
|
||||
boolean active = true;
|
||||
|
||||
//the associated manager
|
||||
HitboxManager manager;
|
||||
|
||||
|
||||
/**
|
||||
* Create hitbox state for an entity
|
||||
* @param collisionEngine the collision engine
|
||||
* @param entity The entity to attach the state to
|
||||
* @param hitboxListRaw The list of hitbox data to apply
|
||||
* @return The hitbox state that has been attached to the entity
|
||||
*/
|
||||
public static HitboxState attachHitboxState(HitboxManager manager, Entity entity, List<HitboxData> hitboxListRaw){
|
||||
HitboxState rVal = new HitboxState();
|
||||
|
||||
//create the shapes
|
||||
for(HitboxData hitboxDataRaw : hitboxListRaw){
|
||||
DGeom geom = CollisionBodyCreation.createShapeSphere(manager.getCollisionEngine(), hitboxDataRaw.getRadius(), Collidable.TYPE_OBJECT_BIT);
|
||||
rVal.hitboxGeomMap.put(hitboxDataRaw.getBone(),geom);
|
||||
HitboxType type = HitboxType.HIT;
|
||||
switch(hitboxDataRaw.getType()){
|
||||
case "HIT": {
|
||||
type = HitboxType.HIT;
|
||||
} break;
|
||||
case "HURT": {
|
||||
type = HitboxType.HURT;
|
||||
} break;
|
||||
}
|
||||
rVal.geomBoneMap.put(geom,new HitboxShapeStatus(hitboxDataRaw.getBone(), type, true));
|
||||
}
|
||||
|
||||
//create body with all the shapes
|
||||
DGeom[] geomArray = rVal.hitboxGeomMap.values().toArray(new DGeom[rVal.hitboxGeomMap.values().size()]);
|
||||
rVal.body = CollisionBodyCreation.createBodyWithShapes(manager.getCollisionEngine(), geomArray);
|
||||
|
||||
//register collidable with collision engine
|
||||
Collidable collidable = new Collidable(entity, Collidable.TYPE_OBJECT);
|
||||
manager.getCollisionEngine().registerCollisionObject(rVal.body, collidable);
|
||||
|
||||
//attach
|
||||
entity.putData(EntityDataStrings.HITBOX_DATA, rVal);
|
||||
rVal.parent = entity;
|
||||
|
||||
//register
|
||||
manager.registerHitbox(rVal);
|
||||
rVal.manager = manager;
|
||||
|
||||
return rVal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create hitbox state for an entity
|
||||
* @param collisionEngine the collision engine
|
||||
* @param entity The entity to attach the state to
|
||||
* @param data The hitbox data to apply
|
||||
* @param callback The callback that provides a position for the hitbox each frame
|
||||
* @return The hitbox state that has been attached to the entity
|
||||
*/
|
||||
public static HitboxState attachHitboxStateWithCallback(HitboxManager manager, CollisionEngine collisionEngine, Entity entity, HitboxData data, HitboxPositionCallback callback){
|
||||
HitboxState rVal = new HitboxState();
|
||||
|
||||
//create the shapes
|
||||
rVal.hitboxGeomMap.put(data.getBone(),CollisionBodyCreation.createShapeSphere(collisionEngine, data.getRadius(), Collidable.TYPE_OBJECT_BIT));
|
||||
|
||||
//create body with all the shapes
|
||||
DGeom[] geomArray = rVal.hitboxGeomMap.values().toArray(new DGeom[rVal.hitboxGeomMap.values().size()]);
|
||||
rVal.body = CollisionBodyCreation.createBodyWithShapes(collisionEngine, geomArray);
|
||||
|
||||
//register collidable with collision engine
|
||||
Collidable collidable = new Collidable(entity, Collidable.TYPE_OBJECT);
|
||||
collisionEngine.registerCollisionObject(rVal.body, collidable);
|
||||
|
||||
//attach
|
||||
entity.putData(EntityDataStrings.HITBOX_DATA, rVal);
|
||||
rVal.parent = entity;
|
||||
|
||||
//register
|
||||
manager.registerHitbox(rVal);
|
||||
rVal.manager = manager;
|
||||
|
||||
return rVal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the positions of all hitboxes
|
||||
*/
|
||||
public void updateHitboxPositions(CollisionEngine collisionEngine){
|
||||
if(parent != null && EntityUtils.getActor(parent) != null){
|
||||
if(!this.hitboxGeomMap.isEmpty()){
|
||||
Vector3d entityPosition = EntityUtils.getPosition(parent);
|
||||
this.body.setPosition(PhysicsUtils.jomlVecToOdeVec(entityPosition));
|
||||
for(String boneName : this.hitboxGeomMap.keySet()){
|
||||
DGeom geom = this.hitboxGeomMap.get(boneName);
|
||||
Quaterniond parentRotation = EntityUtils.getRotation(parent);
|
||||
Vector3f positionScale = EntityUtils.getScale(parent);
|
||||
Vector3d worldPosition = new Vector3d();
|
||||
Vector3f bonePosition = EntityUtils.getActor(parent).getBonePosition(boneName);
|
||||
Vector3d parentPos = EntityUtils.getPosition(parent);
|
||||
worldPosition.set(bonePosition.x,bonePosition.y,bonePosition.z);
|
||||
Quaterniond rotation = new Quaterniond(parentRotation);
|
||||
|
||||
worldPosition = worldPosition.mul(positionScale);
|
||||
|
||||
worldPosition = worldPosition.rotate(rotation);
|
||||
|
||||
|
||||
worldPosition.add(new Vector3f((float)parentPos.x,(float)parentPos.y,(float)parentPos.z));
|
||||
|
||||
PhysicsEntityUtils.setGeometryPosition(collisionEngine, geom, worldPosition, rotation);
|
||||
}
|
||||
} else if(positionCallback != null){
|
||||
DGeom geom = body.getGeomIterator().next();
|
||||
Vector3d worldPosition = this.positionCallback.getPosition();
|
||||
Quaterniond rotation = new Quaterniond().identity();
|
||||
|
||||
PhysicsEntityUtils.setGeometryPosition(collisionEngine, geom, worldPosition, rotation);
|
||||
}
|
||||
} else if(parent != null && EntityUtils.getPoseActor(parent) != null){
|
||||
if(!this.hitboxGeomMap.isEmpty()){
|
||||
Vector3d entityPosition = EntityUtils.getPosition(parent);
|
||||
this.body.setPosition(PhysicsUtils.jomlVecToOdeVec(entityPosition));
|
||||
for(String boneName : this.hitboxGeomMap.keySet()){
|
||||
DGeom geom = this.hitboxGeomMap.get(boneName);
|
||||
Quaterniond parentRotation = EntityUtils.getRotation(parent);
|
||||
Vector3f positionScale = EntityUtils.getScale(parent);
|
||||
Vector3d worldPosition = new Vector3d();
|
||||
Vector3f bonePosition = EntityUtils.getPoseActor(parent).getBonePosition(boneName);
|
||||
Vector3d parentPos = EntityUtils.getPosition(parent);
|
||||
worldPosition.set(bonePosition.x,bonePosition.y,bonePosition.z);
|
||||
Quaterniond rotation = new Quaterniond(parentRotation);
|
||||
|
||||
worldPosition = worldPosition.mul(positionScale);
|
||||
|
||||
worldPosition = worldPosition.rotate(rotation);
|
||||
|
||||
|
||||
worldPosition.add(new Vector3f((float)parentPos.x,(float)parentPos.y,(float)parentPos.z));
|
||||
|
||||
PhysicsEntityUtils.setGeometryPosition(collisionEngine, geom, worldPosition, rotation);
|
||||
}
|
||||
} else if(positionCallback != null){
|
||||
DGeom geom = body.getGeomIterator().next();
|
||||
Vector3d worldPosition = this.positionCallback.getPosition();
|
||||
Quaterniond rotation = new Quaterniond().identity();
|
||||
|
||||
PhysicsEntityUtils.setGeometryPosition(collisionEngine, geom, worldPosition, rotation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the status of a shape in the hitbox object
|
||||
* @param geom The geometry that is the shape within the hitbox data
|
||||
* @return The status of the shape
|
||||
*/
|
||||
public HitboxShapeStatus getShapeStatus(DGeom geom){
|
||||
return this.geomBoneMap.get(geom);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the hitbox state of the entity
|
||||
* @param entity the entity
|
||||
* @return the hitbox state if it exists
|
||||
*/
|
||||
public static HitboxState getHitboxState(Entity entity){
|
||||
return (HitboxState)entity.getData(EntityDataStrings.HITBOX_DATA);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the entity has hitbox state or not
|
||||
* @param entity the entity to check
|
||||
* @return true if there is hitbox state, false otherwise
|
||||
*/
|
||||
public static boolean hasHitboxState(Entity entity){
|
||||
return entity.containsKey(EntityDataStrings.HITBOX_DATA);
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroys the hitbox state and removes it from the entity
|
||||
* @param entity the entity
|
||||
* @return The hitbox state if it exists, null otherwise
|
||||
*/
|
||||
public static HitboxState destroyHitboxState(Entity entity){
|
||||
HitboxState state = null;
|
||||
if(hasHitboxState(entity)){
|
||||
state = getHitboxState(entity);
|
||||
state.manager.deregisterHitbox(state);
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether the hitbox state is active or not
|
||||
* @return true if active, false otherwise
|
||||
*/
|
||||
public boolean isActive(){
|
||||
return active;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the active state of the hitbox
|
||||
* @param state true to make it active, false otherwise
|
||||
*/
|
||||
public void setActive(boolean state){
|
||||
this.active = state;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the collection of all DGeoms in the data
|
||||
* @return the collection of all DGeoms
|
||||
*/
|
||||
public Collection<DGeom> getGeometries(){
|
||||
return this.hitboxGeomMap.values();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the set of bone names in the state data
|
||||
* @return The set of bone names in the state data
|
||||
*/
|
||||
public Set<String> getBones(){
|
||||
return this.hitboxGeomMap.keySet();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets geometry on a single hitbox based on its bone name
|
||||
* @param boneName the bone name
|
||||
* @return the hitbox geometry
|
||||
*/
|
||||
public DGeom getGeometry(String boneName){
|
||||
return this.hitboxGeomMap.get(boneName);
|
||||
}
|
||||
|
||||
/**
|
||||
* The status of a single shape inside the overall hitbox data
|
||||
* IE a single sphere on the overall body
|
||||
*/
|
||||
public static class HitboxShapeStatus {
|
||||
|
||||
//the name of the bone the hitbox is attached to
|
||||
String boneName;
|
||||
|
||||
//the type of hitbox
|
||||
HitboxType type;
|
||||
|
||||
//controls whether the hitbox is active
|
||||
boolean isActive;
|
||||
|
||||
/**
|
||||
* Creates a status object for a hitbox
|
||||
* @param boneName The name of the bone the hitbox is attached to, if any
|
||||
* @param type The type of hitbox
|
||||
* @param isActive if the hitbox is active or not
|
||||
*/
|
||||
public HitboxShapeStatus(String boneName, HitboxType type, boolean isActive){
|
||||
this.boneName = boneName;
|
||||
this.type = type;
|
||||
this.isActive = isActive;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of the bone the hitbox is attached to
|
||||
* @return The name of the bone
|
||||
*/
|
||||
public String getBoneName(){
|
||||
return boneName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the name of the bone the hitbox is attached to
|
||||
* @param boneName The bone name
|
||||
*/
|
||||
public void setBoneName(String boneName){
|
||||
this.boneName = boneName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the type of hitbox
|
||||
* @return The type
|
||||
*/
|
||||
public HitboxType getType(){
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the type of hitbox
|
||||
* @param type The type
|
||||
*/
|
||||
public void setType(HitboxType type){
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether the hitbox is active or not
|
||||
* @return true if active, false otherwise
|
||||
*/
|
||||
public boolean isActive(){
|
||||
return isActive;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether the hitbox is active or not
|
||||
* @param active true for active, false otherwise
|
||||
*/
|
||||
public void setActive(boolean active){
|
||||
this.isActive = active;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -28,7 +28,7 @@ import electrosphere.renderer.anim.Animation;
|
||||
/**
|
||||
* Tree for playing an idle animation when an entity isn't doing anything
|
||||
*/
|
||||
public class IdleTree implements BehaviorTree {
|
||||
public class ClientIdleTree implements BehaviorTree {
|
||||
|
||||
@SynchronizableEnum
|
||||
public static enum IdleTreeState {
|
||||
@ -42,11 +42,19 @@ public class IdleTree implements BehaviorTree {
|
||||
Entity parent;
|
||||
IdleData idleData;
|
||||
|
||||
public IdleTree(Entity e){
|
||||
/**
|
||||
* Creates an idle tree
|
||||
* @param e the entity to attach the tree to
|
||||
*/
|
||||
public ClientIdleTree(Entity e){
|
||||
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));
|
||||
idleData = creatureType.getIdleData();
|
||||
if(creatureType != null){
|
||||
idleData = creatureType.getIdleData();
|
||||
}
|
||||
//TODO: if object, check if object has idle data and add accordingly
|
||||
}
|
||||
|
||||
/**
|
||||
@ -139,8 +147,8 @@ public class IdleTree implements BehaviorTree {
|
||||
* @param entity The entity to attach to
|
||||
* @param tree The behavior tree to attach
|
||||
*/
|
||||
public static IdleTree attachTree(Entity parent){
|
||||
IdleTree rVal = new IdleTree(parent);
|
||||
public static ClientIdleTree attachTree(Entity parent){
|
||||
ClientIdleTree rVal = new ClientIdleTree(parent);
|
||||
//put manual code here (setting params, etc)
|
||||
|
||||
|
||||
@ -194,8 +202,8 @@ public class IdleTree implements BehaviorTree {
|
||||
* @param entity the entity
|
||||
* @return The IdleTree
|
||||
*/
|
||||
public static IdleTree getIdleTree(Entity entity){
|
||||
return (IdleTree)entity.getData(EntityDataStrings.TREE_IDLE);
|
||||
public static ClientIdleTree getIdleTree(Entity entity){
|
||||
return (ClientIdleTree)entity.getData(EntityDataStrings.TREE_IDLE);
|
||||
}
|
||||
/**
|
||||
* <p> Automatically generated </p>
|
||||
@ -2,7 +2,7 @@ package electrosphere.entity.state.idle;
|
||||
|
||||
import electrosphere.entity.state.attack.ClientAttackTree.AttackTreeState;
|
||||
import electrosphere.entity.state.attack.ServerAttackTree;
|
||||
import electrosphere.entity.state.idle.IdleTree.IdleTreeState;
|
||||
import electrosphere.entity.state.idle.ClientIdleTree.IdleTreeState;
|
||||
import electrosphere.entity.state.movement.AirplaneMovementTree;
|
||||
import electrosphere.entity.state.movement.groundmove.ClientGroundMovementTree.MovementTreeState;
|
||||
import electrosphere.entity.state.movement.groundmove.ServerGroundMovementTree;
|
||||
@ -12,6 +12,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.net.parser.net.message.EntityMessage;
|
||||
import electrosphere.net.parser.net.message.SynchronizationMessage;
|
||||
import electrosphere.net.synchronization.BehaviorTreeIdEnums;
|
||||
@ -39,6 +40,10 @@ public class ServerIdleTree implements BehaviorTree {
|
||||
|
||||
CopyOnWriteArrayList<EntityMessage> networkMessageQueue = new CopyOnWriteArrayList<EntityMessage>();
|
||||
|
||||
/**
|
||||
* Creates a server idle tree
|
||||
* @param e The entity to attach it to
|
||||
*/
|
||||
public ServerIdleTree(Entity e){
|
||||
state = IdleTreeState.IDLE;
|
||||
parent = e;
|
||||
@ -68,7 +73,7 @@ public class ServerIdleTree implements BehaviorTree {
|
||||
}
|
||||
|
||||
public void simulate(float deltaTime){
|
||||
PoseActor entityActor = EntityUtils.getPoseActor(parent);
|
||||
PoseActor poseActor = EntityUtils.getPoseActor(parent);
|
||||
|
||||
boolean movementTreeIsIdle = movementTreeIsIdle();
|
||||
|
||||
@ -83,12 +88,12 @@ public class ServerIdleTree implements BehaviorTree {
|
||||
//state machine
|
||||
switch(state){
|
||||
case IDLE:
|
||||
if(entityActor != null){
|
||||
if(poseActor != null){
|
||||
if(
|
||||
(!entityActor.isPlayingAnimation() || !entityActor.isPlayingAnimation(Animation.ANIMATION_IDLE_1))
|
||||
(!poseActor.isPlayingAnimation() || !poseActor.isPlayingAnimation(Animation.ANIMATION_IDLE_1))
|
||||
){
|
||||
entityActor.playAnimation(Animation.ANIMATION_IDLE_1,3);
|
||||
entityActor.incrementAnimationTime(0.0001);
|
||||
poseActor.playAnimation(Animation.ANIMATION_IDLE_1,3);
|
||||
poseActor.incrementAnimationTime(0.0001);
|
||||
}
|
||||
}
|
||||
isIdle = true;
|
||||
@ -184,7 +189,7 @@ public class ServerIdleTree implements BehaviorTree {
|
||||
*/
|
||||
public void setState(IdleTreeState state){
|
||||
this.state = state;
|
||||
int value = IdleTree.getIdleTreeStateEnumAsShort(state);
|
||||
int value = ClientIdleTree.getIdleTreeStateEnumAsShort(state);
|
||||
DataCellSearchUtils.getEntityDataCell(parent).broadcastNetworkMessage(SynchronizationMessage.constructUpdateClientStateMessage(parent.getId(), 7, 9, value));
|
||||
}
|
||||
|
||||
|
||||
@ -5,7 +5,6 @@ import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import org.joml.Vector3d;
|
||||
|
||||
import electrosphere.engine.Globals;
|
||||
import electrosphere.engine.Main;
|
||||
import electrosphere.entity.Entity;
|
||||
import electrosphere.entity.EntityUtils;
|
||||
import electrosphere.entity.btree.BehaviorTree;
|
||||
@ -17,6 +16,9 @@ import electrosphere.net.parser.net.message.EntityMessage;
|
||||
import electrosphere.renderer.actor.Actor;
|
||||
import electrosphere.server.datacell.utils.DataCellSearchUtils;
|
||||
|
||||
/**
|
||||
* The status of the life value of a given entity
|
||||
*/
|
||||
public class LifeState implements BehaviorTree {
|
||||
|
||||
|
||||
@ -108,7 +110,6 @@ public class LifeState implements BehaviorTree {
|
||||
public void damage(int damage){
|
||||
if(!isInvincible){
|
||||
lifeCurrent = lifeCurrent - damage;
|
||||
System.out.println(lifeCurrent);
|
||||
isInvincible = true;
|
||||
if(lifeCurrent < 0){
|
||||
lifeCurrent = 0;
|
||||
|
||||
@ -20,6 +20,7 @@ import electrosphere.net.parser.net.message.EntityMessage;
|
||||
import electrosphere.renderer.actor.Actor;
|
||||
import electrosphere.renderer.anim.Animation;
|
||||
import electrosphere.server.datacell.utils.DataCellSearchUtils;
|
||||
import electrosphere.util.MathUtils;
|
||||
|
||||
@Deprecated
|
||||
public class AirplaneMovementTree implements BehaviorTree {
|
||||
@ -83,7 +84,7 @@ public class AirplaneMovementTree implements BehaviorTree {
|
||||
Actor entityActor = EntityUtils.getActor(parent);
|
||||
Vector3d position = EntityUtils.getPosition(parent);
|
||||
Vector3d facingVector = CreatureUtils.getFacingVector(parent);
|
||||
Quaterniond movementQuaternion = new Quaterniond().rotationTo(new Vector3d(0,0,1), new Vector3d(facingVector.x,0,facingVector.z)).normalize();
|
||||
Quaterniond movementQuaternion = new Quaterniond().rotationTo(MathUtils.getOriginVector(), new Vector3d(facingVector.x,0,facingVector.z)).normalize();
|
||||
Quaterniond rotation = EntityUtils.getRotation(parent);
|
||||
//
|
||||
//handle network messages
|
||||
@ -187,15 +188,15 @@ public class AirplaneMovementTree implements BehaviorTree {
|
||||
|
||||
|
||||
Quaterniond yawQuat = new Quaterniond().fromAxisAngleRad(new Vector3d(0,1,0), yaw);
|
||||
Quaterniond pitchQuat = new Quaterniond().fromAxisAngleRad(new Vector3d(1,0,0), pitch);
|
||||
Quaterniond rollQuat = new Quaterniond().fromAxisAngleRad(new Vector3d(0,0,1), rollVal);
|
||||
Quaterniond pitchQuat = new Quaterniond().fromAxisAngleRad(MathUtils.getOriginVector(), pitch);
|
||||
Quaterniond rollQuat = new Quaterniond().fromAxisAngleRad(MathUtils.getOriginVector(), rollVal);
|
||||
|
||||
rotation.slerp(yawQuat.mul(pitchQuat).mul(rollQuat),0.1);
|
||||
|
||||
|
||||
|
||||
//rotate thrust vector
|
||||
rotationVector.set(rotation.transform(new Vector3d(0,0,1)));
|
||||
rotationVector.set(rotation.transform(MathUtils.getOriginVector()));
|
||||
// rotationVector.set(new Vector3f((float)rotationVector.x,(float)rotationVector.y,(float)rotationVector.z).mul(1.0f - this.maxRotationSpeed).add(new Vector3f(cameraEyeVector).mul(-this.maxRotationSpeed)));
|
||||
|
||||
|
||||
@ -211,7 +212,7 @@ public class AirplaneMovementTree implements BehaviorTree {
|
||||
* @param collidable The collidable of the entity
|
||||
*/
|
||||
void addMovementForce(float velocity, Quaterniond rotation, Collidable collidable){
|
||||
Vector3d impulseDir = rotation.transform(new Vector3d(0,0,1));
|
||||
Vector3d impulseDir = rotation.transform(MathUtils.getOriginVector());
|
||||
collidable.addImpulse(new Impulse(new Vector3d(impulseDir), new Vector3d(0,0,0), new Vector3d(0,0,0), velocity * Globals.timekeeper.getSimFrameTime(), "movement"));
|
||||
}
|
||||
|
||||
|
||||
@ -5,6 +5,7 @@ import electrosphere.entity.EntityDataStrings;
|
||||
import electrosphere.entity.EntityUtils;
|
||||
import electrosphere.entity.btree.BehaviorTree;
|
||||
import electrosphere.renderer.actor.Actor;
|
||||
import electrosphere.server.poseactor.PoseActor;
|
||||
|
||||
public class ServerFallTree implements BehaviorTree {
|
||||
|
||||
@ -28,17 +29,17 @@ public class ServerFallTree implements BehaviorTree {
|
||||
|
||||
@Override
|
||||
public void simulate(float deltaTime) {
|
||||
Actor entityActor = EntityUtils.getActor(parent);
|
||||
PoseActor poseActor = EntityUtils.getPoseActor(parent);
|
||||
switch(state){
|
||||
case ACTIVE:
|
||||
if(entityActor != null){
|
||||
if(poseActor != null){
|
||||
String animationToPlay = determineCorrectAnimation();
|
||||
if(
|
||||
!entityActor.isPlayingAnimation() || !entityActor.isPlayingAnimation(animationToPlay) &&
|
||||
!poseActor.isPlayingAnimation() || !poseActor.isPlayingAnimation(animationToPlay) &&
|
||||
(jumpTree == null || !jumpTree.isJumping())
|
||||
){
|
||||
entityActor.playAnimation(animationToPlay,1);
|
||||
entityActor.incrementAnimationTime(0.0001);
|
||||
poseActor.playAnimation(animationToPlay,1);
|
||||
poseActor.incrementAnimationTime(0.0001);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -58,14 +59,14 @@ public class ServerFallTree implements BehaviorTree {
|
||||
public void land(){
|
||||
if(state != FallState.INACTIVE){
|
||||
state = FallState.INACTIVE;
|
||||
Actor entityActor = EntityUtils.getActor(parent);
|
||||
if(entityActor != null){
|
||||
PoseActor poseActor = EntityUtils.getPoseActor(parent);
|
||||
if(poseActor != null){
|
||||
String animationToPlay = determineCorrectAnimation();
|
||||
if(
|
||||
!entityActor.isPlayingAnimation() || !entityActor.isPlayingAnimation(animationToPlay)
|
||||
!poseActor.isPlayingAnimation() || !poseActor.isPlayingAnimation(animationToPlay)
|
||||
){
|
||||
entityActor.playAnimation(animationToPlay,1);
|
||||
entityActor.incrementAnimationTime(0.0001);
|
||||
poseActor.playAnimation(animationToPlay,1);
|
||||
poseActor.incrementAnimationTime(0.0001);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -14,6 +14,7 @@ import electrosphere.entity.state.collidable.Impulse;
|
||||
import electrosphere.entity.state.gravity.GravityUtils;
|
||||
import electrosphere.entity.types.collision.CollisionObjUtils;
|
||||
import electrosphere.renderer.actor.Actor;
|
||||
import electrosphere.server.poseactor.PoseActor;
|
||||
|
||||
public class ServerJumpTree implements BehaviorTree {
|
||||
|
||||
@ -53,14 +54,14 @@ public class ServerJumpTree implements BehaviorTree {
|
||||
|
||||
@Override
|
||||
public void simulate(float deltaTime) {
|
||||
Actor entityActor = EntityUtils.getActor(parent);
|
||||
PoseActor poseActor = EntityUtils.getPoseActor(parent);
|
||||
switch(state){
|
||||
case ACTIVE:
|
||||
if(entityActor != null){
|
||||
if(poseActor != null){
|
||||
String animationToPlay = determineCorrectAnimation();
|
||||
if(!entityActor.isPlayingAnimation() || !entityActor.isPlayingAnimation(animationToPlay)){
|
||||
entityActor.playAnimation(animationToPlay,1);
|
||||
entityActor.incrementAnimationTime(0.0001);
|
||||
if(!poseActor.isPlayingAnimation() || !poseActor.isPlayingAnimation(animationToPlay)){
|
||||
poseActor.playAnimation(animationToPlay,1);
|
||||
poseActor.incrementAnimationTime(0.0001);
|
||||
}
|
||||
}
|
||||
currentFrame++;
|
||||
|
||||
@ -26,6 +26,7 @@ import electrosphere.net.synchronization.annotation.SyncedField;
|
||||
import electrosphere.net.synchronization.annotation.SynchronizableEnum;
|
||||
import electrosphere.net.synchronization.annotation.SynchronizedBehaviorTree;
|
||||
import electrosphere.renderer.anim.Animation;
|
||||
import electrosphere.util.MathUtils;
|
||||
import electrosphere.renderer.actor.Actor;
|
||||
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
@ -217,7 +218,7 @@ public class ClientGroundMovementTree implements BehaviorTree {
|
||||
break;
|
||||
}
|
||||
// float movementYaw = CameraEntityUtils.getCameraYaw(Globals.playerCamera);
|
||||
Quaterniond movementQuaternion = new Quaterniond().rotationTo(new Vector3d(0,0,1), new Vector3d(facingVector.x,0,facingVector.z)).normalize();
|
||||
Quaterniond movementQuaternion = new Quaterniond().rotationTo(MathUtils.getOriginVector(), new Vector3d(facingVector.x,0,facingVector.z)).normalize();
|
||||
Quaterniond rotation = EntityUtils.getRotation(parent);
|
||||
//TODO: optimize away and document (I know for the moment if this exception isn't here it will bite me in the ass later)
|
||||
if(facingVector.length() == 0){
|
||||
@ -258,7 +259,6 @@ public class ClientGroundMovementTree implements BehaviorTree {
|
||||
//this should only fire on the client, we don't want the server snap updating due to client position reporting
|
||||
lastServerPosition = new Vector3d(message.getpositionX(),message.getpositionY(),message.getpositionZ());
|
||||
if(position.distance(lastServerPosition) > STATE_DIFFERENCE_HARD_UPDATE_THRESHOLD){
|
||||
System.out.println(position + " - " + lastServerPosition);
|
||||
EntityUtils.getPosition(parent).set(lastServerPosition);
|
||||
} else if(position.distance(lastServerPosition) > STATE_DIFFERENCE_SOFT_UPDATE_THRESHOLD){
|
||||
EntityUtils.getPosition(parent).lerp(lastServerPosition,SOFT_UPDATE_MULTIPLIER);
|
||||
|
||||
@ -28,6 +28,7 @@ import electrosphere.net.synchronization.annotation.SynchronizedBehaviorTree;
|
||||
import electrosphere.renderer.anim.Animation;
|
||||
import electrosphere.server.datacell.utils.DataCellSearchUtils;
|
||||
import electrosphere.server.poseactor.PoseActor;
|
||||
import electrosphere.util.MathUtils;
|
||||
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
@ -153,7 +154,7 @@ public class ServerGroundMovementTree implements BehaviorTree {
|
||||
acceleration = CreatureUtils.getAcceleration(parent);
|
||||
maxNaturalVelocity = sprintTree != null && sprintTree.getState() == SprintTreeState.SPRINTING ? sprintTree.getMaxVelocity() : CreatureUtils.getMaxNaturalVelocity(parent);
|
||||
}
|
||||
PoseActor entityPoseActor = EntityUtils.getPoseActor(parent);
|
||||
PoseActor poseActor = EntityUtils.getPoseActor(parent);
|
||||
// Model entityModel = Globals.assetManager.fetchModel(EntityUtils.getEntityModelPath(parent));
|
||||
Vector3d position = EntityUtils.getPosition(parent);
|
||||
Vector3d facingVector = CreatureUtils.getFacingVector(parent);
|
||||
@ -189,7 +190,7 @@ public class ServerGroundMovementTree implements BehaviorTree {
|
||||
break;
|
||||
}
|
||||
// float movementYaw = CameraEntityUtils.getCameraYaw(Globals.playerCamera);
|
||||
Quaterniond movementQuaternion = new Quaterniond().rotationTo(new Vector3d(0,0,1), new Vector3d(facingVector.x,0,facingVector.z)).normalize();
|
||||
Quaterniond movementQuaternion = new Quaterniond().rotationTo(MathUtils.getOriginVector(), new Vector3d(facingVector.x,0,facingVector.z)).normalize();
|
||||
Quaterniond rotation = EntityUtils.getRotation(parent);
|
||||
//TODO: optimize away and document (I know for the moment if this exception isn't here it will bite me in the ass later)
|
||||
if(facingVector.length() == 0){
|
||||
@ -233,15 +234,15 @@ public class ServerGroundMovementTree implements BehaviorTree {
|
||||
//state machine
|
||||
switch(state){
|
||||
case STARTUP: {
|
||||
if(entityPoseActor != null){
|
||||
if(poseActor != null){
|
||||
String animationToPlay = determineCorrectAnimation();
|
||||
if(
|
||||
!entityPoseActor.isPlayingAnimation() || !entityPoseActor.isPlayingAnimation(animationToPlay) &&
|
||||
!poseActor.isPlayingAnimation() || !poseActor.isPlayingAnimation(animationToPlay) &&
|
||||
(jumpTree == null || !jumpTree.isJumping()) &&
|
||||
(fallTree == null || !fallTree.isFalling())
|
||||
){
|
||||
entityPoseActor.playAnimation(animationToPlay,1);
|
||||
entityPoseActor.incrementAnimationTime(0.0001);
|
||||
poseActor.playAnimation(animationToPlay,1);
|
||||
poseActor.incrementAnimationTime(0.0001);
|
||||
}
|
||||
}
|
||||
//run startup code
|
||||
@ -289,15 +290,15 @@ public class ServerGroundMovementTree implements BehaviorTree {
|
||||
case MOVE: {
|
||||
//check if can restart animation
|
||||
//if yes, restart animation
|
||||
if(entityPoseActor != null){
|
||||
if(poseActor != null){
|
||||
String animationToPlay = determineCorrectAnimation();
|
||||
if(
|
||||
!entityPoseActor.isPlayingAnimation() || !entityPoseActor.isPlayingAnimation(animationToPlay) &&
|
||||
!poseActor.isPlayingAnimation() || !poseActor.isPlayingAnimation(animationToPlay) &&
|
||||
(jumpTree == null || !jumpTree.isJumping()) &&
|
||||
(fallTree == null || !fallTree.isFalling())
|
||||
){
|
||||
entityPoseActor.playAnimation(animationToPlay,1);
|
||||
entityPoseActor.incrementAnimationTime(0.0001);
|
||||
poseActor.playAnimation(animationToPlay,1);
|
||||
poseActor.incrementAnimationTime(0.0001);
|
||||
}
|
||||
}
|
||||
if(velocity != maxNaturalVelocity){
|
||||
@ -339,15 +340,15 @@ public class ServerGroundMovementTree implements BehaviorTree {
|
||||
} break;
|
||||
case SLOWDOWN: {
|
||||
//run slowdown code
|
||||
if(entityPoseActor != null){
|
||||
if(poseActor != null){
|
||||
String animationToPlay = determineCorrectAnimation();
|
||||
if(
|
||||
!entityPoseActor.isPlayingAnimation() || !entityPoseActor.isPlayingAnimation(animationToPlay) &&
|
||||
!poseActor.isPlayingAnimation() || !poseActor.isPlayingAnimation(animationToPlay) &&
|
||||
(jumpTree == null || !jumpTree.isJumping()) &&
|
||||
(fallTree == null || !fallTree.isFalling())
|
||||
){
|
||||
entityPoseActor.playAnimation(animationToPlay,1);
|
||||
entityPoseActor.incrementAnimationTime(0.0001);
|
||||
poseActor.playAnimation(animationToPlay,1);
|
||||
poseActor.incrementAnimationTime(0.0001);
|
||||
}
|
||||
}
|
||||
//velocity stuff
|
||||
@ -356,10 +357,10 @@ public class ServerGroundMovementTree implements BehaviorTree {
|
||||
if(velocity <= 0){
|
||||
velocity = 0;
|
||||
state = MovementTreeState.IDLE;
|
||||
if(entityPoseActor != null){
|
||||
if(poseActor != null){
|
||||
String animationToPlay = determineCorrectAnimation();
|
||||
if(entityPoseActor.isPlayingAnimation() && entityPoseActor.isPlayingAnimation(animationToPlay)){
|
||||
entityPoseActor.stopAnimation(animationToPlay);
|
||||
if(poseActor.isPlayingAnimation() && poseActor.isPlayingAnimation(animationToPlay)){
|
||||
poseActor.stopAnimation(animationToPlay);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -10,6 +10,7 @@ import electrosphere.renderer.actor.Actor;
|
||||
import electrosphere.server.datacell.ServerDataCell;
|
||||
import electrosphere.server.datacell.utils.ServerEntityTagUtils;
|
||||
import electrosphere.server.poseactor.PoseActor;
|
||||
import electrosphere.util.MathUtils;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
@ -81,7 +82,7 @@ public class AttachUtils {
|
||||
Vector3d facingAngle = CreatureUtils.getFacingVector(parent);
|
||||
//calculate rotation of model
|
||||
EntityUtils.getRotation(currentEntity)
|
||||
.rotationTo(new Vector3d(0,0,1), new Vector3d(facingAngle.x,facingAngle.y,facingAngle.z))
|
||||
.rotationTo(MathUtils.getOriginVector(), new Vector3d(facingAngle.x,facingAngle.y,facingAngle.z))
|
||||
.mul(parentActor.getBoneRotation(targetBone))
|
||||
.mul(offsetRotation)
|
||||
.normalize();
|
||||
@ -200,11 +201,11 @@ public class AttachUtils {
|
||||
// EntityUtils.getRotation(currentEntity).set(rotation).normalize();
|
||||
Vector3d facingAngle = CreatureUtils.getFacingVector(parent);
|
||||
if(facingAngle == null){
|
||||
facingAngle = new Vector3d(0,0,1);
|
||||
facingAngle = MathUtils.getOriginVector();
|
||||
}
|
||||
//calculate rotation of model
|
||||
EntityUtils.getRotation(currentEntity)
|
||||
.rotationTo(new Vector3d(0,0,1), new Vector3d(facingAngle.x,facingAngle.y,facingAngle.z))
|
||||
.rotationTo(MathUtils.getOriginVector(), new Vector3d(facingAngle.x,facingAngle.y,facingAngle.z))
|
||||
.mul(parentActor.getBoneRotation(targetBone))
|
||||
.mul(offsetRotation)
|
||||
.normalize();
|
||||
@ -305,6 +306,13 @@ public class AttachUtils {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Attaches an entity to another entity at a given bone
|
||||
* @param parent The parent entity
|
||||
* @param toAttach The entity that will be attached
|
||||
* @param boneName The name of the bone
|
||||
* @param rotation The rotation applied
|
||||
*/
|
||||
public static void clientAttachEntityToEntityAtBone(Entity parent, Entity toAttach, String boneName, Quaterniond rotation){
|
||||
Globals.clientSceneWrapper.getScene().registerEntityToTag(toAttach, EntityTags.BONE_ATTACHED);
|
||||
toAttach.putData(EntityDataStrings.ATTACH_ENTITY_IS_ATTACHED, true);
|
||||
@ -488,6 +496,11 @@ public class AttachUtils {
|
||||
// GETTERS
|
||||
//
|
||||
|
||||
/**
|
||||
* Checks whether this entity is attached to another entity or not
|
||||
* @param e The entity
|
||||
* @return true if attached, false otherwise
|
||||
*/
|
||||
public static boolean isAttached(Entity e){
|
||||
return e.containsKey(EntityDataStrings.ATTACH_ENTITY_IS_ATTACHED);
|
||||
}
|
||||
@ -500,10 +513,24 @@ public class AttachUtils {
|
||||
return (Entity)e.getData(EntityDataStrings.ATTACH_PARENT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the rotation offset of a given entity
|
||||
* @param e The entity
|
||||
* @return The rotation offset
|
||||
*/
|
||||
protected static Quaterniond getRotationOffset(Entity e){
|
||||
return (Quaterniond)e.getData(EntityDataStrings.ATTACH_ROTATION_OFFSET);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the attached rotation offset
|
||||
* @param e the attached entity
|
||||
* @param rotation The rotation offset
|
||||
*/
|
||||
public static void setRotationOffset(Entity e, Quaterniond rotation){
|
||||
e.putData(EntityDataStrings.ATTACH_ROTATION_OFFSET, rotation);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the transform for a transform attached entity
|
||||
* @param e The entity
|
||||
|
||||
@ -30,8 +30,8 @@ import electrosphere.entity.state.equip.ClientEquipState;
|
||||
import electrosphere.entity.state.equip.ServerEquipState;
|
||||
import electrosphere.entity.state.gravity.ClientGravityTree;
|
||||
import electrosphere.entity.state.gravity.ServerGravityTree;
|
||||
import electrosphere.entity.state.hitbox.HitboxState;
|
||||
import electrosphere.entity.state.idle.IdleTree;
|
||||
import electrosphere.entity.state.hitbox.HitboxCollectionState;
|
||||
import electrosphere.entity.state.idle.ClientIdleTree;
|
||||
import electrosphere.entity.state.idle.ServerIdleTree;
|
||||
import electrosphere.entity.state.inventory.ClientInventoryState;
|
||||
import electrosphere.entity.state.inventory.InventoryUtils;
|
||||
@ -81,6 +81,7 @@ import electrosphere.server.datacell.utils.ServerBehaviorTreeUtils;
|
||||
import electrosphere.server.datacell.utils.ServerEntityTagUtils;
|
||||
import electrosphere.server.poseactor.PoseActor;
|
||||
import electrosphere.server.poseactor.PoseActorUtils;
|
||||
import electrosphere.util.MathUtils;
|
||||
import electrosphere.util.Utilities;
|
||||
|
||||
/**
|
||||
@ -111,7 +112,7 @@ public class CreatureUtils {
|
||||
/// HITBOX DATA
|
||||
///
|
||||
///
|
||||
HitboxState.attachHitboxState(Globals.clientSceneWrapper.getHitboxManager(), rVal, rawType.getHitboxes());
|
||||
HitboxCollectionState.attachHitboxState(Globals.clientSceneWrapper.getHitboxManager(), false, rVal, rawType.getHitboxes());
|
||||
|
||||
|
||||
//
|
||||
@ -166,7 +167,7 @@ public class CreatureUtils {
|
||||
}
|
||||
//round out end of move system
|
||||
rVal.putData(EntityDataStrings.CLIENT_MOVEMENT_BT, moveTree);
|
||||
CreatureUtils.setFacingVector(rVal, new Vector3d(0,0,1));
|
||||
CreatureUtils.setFacingVector(rVal, MathUtils.getOriginVector());
|
||||
rVal.putData(EntityDataStrings.DATA_STRING_MAX_NATURAL_VELOCITY, groundMovementSystem.getMaxVelocity());
|
||||
rVal.putData(EntityDataStrings.DATA_STRING_ACCELERATION, groundMovementSystem.getAcceleration());
|
||||
rVal.putData(EntityDataStrings.DATA_STRING_VELOCITY, 0f);
|
||||
@ -218,14 +219,14 @@ public class CreatureUtils {
|
||||
airplaneMovementTree.setMaxRotationSpeed(airplaneMovementSystem.getMaxRotationSpeed());
|
||||
//register misc stuff
|
||||
rVal.putData(EntityDataStrings.CLIENT_MOVEMENT_BT, airplaneMovementTree);
|
||||
CreatureUtils.setFacingVector(rVal, new Vector3d(0,0,1));
|
||||
CreatureUtils.setFacingVector(rVal, MathUtils.getOriginVector());
|
||||
Globals.clientScene.registerBehaviorTree(airplaneMovementTree);
|
||||
Globals.clientScene.registerEntityToTag(rVal, EntityTags.MOVEABLE);
|
||||
} break;
|
||||
}
|
||||
}
|
||||
if(rawType.getEquipPoints() != null && rawType.getEquipPoints().size() > 0){
|
||||
ClientEquipState.setEquipState(rVal, new ClientEquipState(rVal,rawType.getEquipPoints()));
|
||||
ClientEquipState.attachTree(rVal, rawType.getEquipPoints());
|
||||
rVal.putData(EntityDataStrings.EQUIP_INVENTORY, RelationalInventoryState.buildRelationalInventoryStateFromEquipList(rawType.getEquipPoints()));
|
||||
}
|
||||
for(String token : rawType.getTokens()){
|
||||
@ -367,11 +368,11 @@ public class CreatureUtils {
|
||||
rVal.putData(EntityDataStrings.LIFE_STATE, new LifeState(rVal, rawType.getHealthSystem()));
|
||||
Globals.clientScene.registerEntityToTag(rVal, EntityTags.LIFE_STATE);
|
||||
//idle tree & generic stuff all creatures have
|
||||
IdleTree idleTree = new IdleTree(rVal);
|
||||
ClientIdleTree idleTree = new ClientIdleTree(rVal);
|
||||
rVal.putData(EntityDataStrings.TREE_IDLE, idleTree);
|
||||
Globals.clientScene.registerBehaviorTree(idleTree);
|
||||
Globals.clientScene.registerEntityToTag(rVal, EntityTags.CREATURE);
|
||||
CreatureUtils.setFacingVector(rVal, new Vector3d(0,0,1));
|
||||
CreatureUtils.setFacingVector(rVal, MathUtils.getOriginVector());
|
||||
rVal.putData(EntityDataStrings.DRAW_CAST_SHADOW, true);
|
||||
return rVal;
|
||||
}
|
||||
@ -396,7 +397,7 @@ public class CreatureUtils {
|
||||
// Hitbox stuff
|
||||
//
|
||||
//
|
||||
HitboxState.attachHitboxState(realm.getHitboxManager(), rVal, rawType.getHitboxes());
|
||||
HitboxCollectionState.attachHitboxState(realm.getHitboxManager(), true, rVal, rawType.getHitboxes());
|
||||
//
|
||||
//
|
||||
// Physics stuff
|
||||
@ -448,7 +449,7 @@ public class CreatureUtils {
|
||||
}
|
||||
//round out end of move system
|
||||
rVal.putData(EntityDataStrings.SERVER_MOVEMENT_BT, moveTree);
|
||||
CreatureUtils.setFacingVector(rVal, new Vector3d(0,0,1));
|
||||
CreatureUtils.setFacingVector(rVal, MathUtils.getOriginVector());
|
||||
rVal.putData(EntityDataStrings.DATA_STRING_MAX_NATURAL_VELOCITY, groundMovementSystem.getMaxVelocity());
|
||||
rVal.putData(EntityDataStrings.DATA_STRING_ACCELERATION, groundMovementSystem.getAcceleration());
|
||||
rVal.putData(EntityDataStrings.DATA_STRING_VELOCITY, 0f);
|
||||
@ -506,7 +507,7 @@ public class CreatureUtils {
|
||||
airplaneMovementTree.setMaxRotationSpeed(airplaneMovementSystem.getMaxRotationSpeed());
|
||||
//register misc stuff
|
||||
rVal.putData(EntityDataStrings.SERVER_MOVEMENT_BT, airplaneMovementTree);
|
||||
CreatureUtils.setFacingVector(rVal, new Vector3d(0,0,1));
|
||||
CreatureUtils.setFacingVector(rVal, MathUtils.getOriginVector());
|
||||
ServerBehaviorTreeUtils.attachBTreeToEntity(rVal, airplaneMovementTree);
|
||||
ServerEntityTagUtils.attachTagToEntity(rVal, EntityTags.MOVEABLE);
|
||||
} break;
|
||||
@ -661,7 +662,7 @@ public class CreatureUtils {
|
||||
ServerEntityTagUtils.attachTagToEntity(rVal, EntityTags.CREATURE);
|
||||
EntityUtils.setEntityType(rVal, ENTITY_TYPE_CREATURE);
|
||||
EntityUtils.setEntitySubtype(rVal, type);
|
||||
CreatureUtils.setFacingVector(rVal, new Vector3d(0,0,1));
|
||||
CreatureUtils.setFacingVector(rVal, MathUtils.getOriginVector());
|
||||
rVal.putData(EntityDataStrings.DRAW_CAST_SHADOW, true);
|
||||
|
||||
//position entity
|
||||
@ -796,8 +797,8 @@ public class CreatureUtils {
|
||||
return (ServerAttackTree)e.getData(EntityDataStrings.TREE_SERVERATTACKTREE);
|
||||
}
|
||||
|
||||
public static IdleTree getIdleTree(Entity e){
|
||||
return (IdleTree)e.getData(EntityDataStrings.TREE_IDLE);
|
||||
public static ClientIdleTree getIdleTree(Entity e){
|
||||
return (ClientIdleTree)e.getData(EntityDataStrings.TREE_IDLE);
|
||||
}
|
||||
|
||||
public static SprintTree clientGetSprintTree(Entity e){
|
||||
|
||||
@ -12,7 +12,7 @@ import electrosphere.entity.EntityTags;
|
||||
import electrosphere.entity.EntityUtils;
|
||||
import electrosphere.entity.ServerEntityUtils;
|
||||
import electrosphere.entity.state.client.ambientaudio.ClientAmbientAudioTree;
|
||||
import electrosphere.entity.state.idle.IdleTree;
|
||||
import electrosphere.entity.state.idle.ClientIdleTree;
|
||||
import electrosphere.entity.types.collision.CollisionObjUtils;
|
||||
import electrosphere.entity.types.tree.ProceduralTree;
|
||||
import electrosphere.game.data.foliage.type.AmbientAudio;
|
||||
|
||||
@ -26,7 +26,7 @@ import electrosphere.entity.state.collidable.ClientCollidableTree;
|
||||
import electrosphere.entity.state.collidable.ServerCollidableTree;
|
||||
import electrosphere.entity.state.gravity.ClientGravityTree;
|
||||
import electrosphere.entity.state.gravity.ServerGravityTree;
|
||||
import electrosphere.entity.state.hitbox.HitboxState;
|
||||
import electrosphere.entity.state.hitbox.HitboxCollectionState;
|
||||
import electrosphere.game.data.collidable.CollidableTemplate;
|
||||
import electrosphere.game.data.collidable.HitboxData;
|
||||
import electrosphere.game.data.item.type.EquipWhitelist;
|
||||
@ -61,7 +61,7 @@ public class ItemUtils {
|
||||
rVal.putData(EntityDataStrings.ITEM_IS_WEAPON, true);
|
||||
WeaponData weaponData = item.getWeaponData();
|
||||
if(weaponData.getHitboxes() != null){
|
||||
HitboxState.attachHitboxState(Globals.clientSceneWrapper.getHitboxManager(), rVal, weaponData.getHitboxes());
|
||||
HitboxCollectionState.attachHitboxState(Globals.clientSceneWrapper.getHitboxManager(), false, rVal, weaponData.getHitboxes());
|
||||
}
|
||||
rVal.putData(EntityDataStrings.ITEM_WEAPON_CLASS,weaponData.getWeaponClass());
|
||||
rVal.putData(EntityDataStrings.ITEM_WEAPON_DATA_RAW,weaponData);
|
||||
@ -134,7 +134,7 @@ public class ItemUtils {
|
||||
rVal.putData(EntityDataStrings.ITEM_IS_WEAPON, true);
|
||||
WeaponData weaponData = item.getWeaponData();
|
||||
if(weaponData.getHitboxes() != null){
|
||||
HitboxState.attachHitboxState(realm.getHitboxManager(), rVal, weaponData.getHitboxes());
|
||||
HitboxCollectionState.attachHitboxState(realm.getHitboxManager(), true, rVal, weaponData.getHitboxes());
|
||||
}
|
||||
rVal.putData(EntityDataStrings.ITEM_WEAPON_CLASS,weaponData.getWeaponClass());
|
||||
rVal.putData(EntityDataStrings.ITEM_WEAPON_DATA_RAW,weaponData);
|
||||
@ -233,6 +233,7 @@ public class ItemUtils {
|
||||
String idleAnim = (String)item.getData(EntityDataStrings.ANIM_IDLE);
|
||||
if(!actor.isPlayingAnimation(idleAnim)){
|
||||
actor.playAnimation(idleAnim,1);
|
||||
actor.incrementAnimationTime(0.0001);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -247,6 +248,7 @@ public class ItemUtils {
|
||||
String idleAnim = (String)item.getData(EntityDataStrings.ANIM_IDLE);
|
||||
if(!actor.isPlayingAnimation(idleAnim)){
|
||||
actor.playAnimation(idleAnim,1);
|
||||
actor.incrementAnimationTime(0.0001);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -386,7 +388,7 @@ public class ItemUtils {
|
||||
//this deregisters from all four & unhooks rigid bodies from the physics runtime
|
||||
Globals.clientSceneWrapper.getCollisionEngine().destroyEntityThatHasPhysics(item);
|
||||
//destroy hitboxes
|
||||
HitboxState.destroyHitboxState(item);
|
||||
HitboxCollectionState.destroyHitboxState(item);
|
||||
//destroy graphics
|
||||
EntityUtils.cleanUpEntity(item);
|
||||
}
|
||||
@ -403,7 +405,7 @@ public class ItemUtils {
|
||||
if(itemRealm != null){
|
||||
itemRealm.getCollisionEngine().destroyEntityThatHasPhysics(item);
|
||||
//destroy hitboxes
|
||||
HitboxState.destroyHitboxState(item);
|
||||
HitboxCollectionState.destroyHitboxState(item);
|
||||
}
|
||||
//destroy graphics
|
||||
EntityUtils.cleanUpEntity(item);
|
||||
|
||||
@ -22,7 +22,9 @@ import electrosphere.entity.state.collidable.ClientCollidableTree;
|
||||
import electrosphere.entity.state.collidable.ServerCollidableTree;
|
||||
import electrosphere.entity.state.gravity.ClientGravityTree;
|
||||
import electrosphere.entity.state.gravity.ServerGravityTree;
|
||||
import electrosphere.entity.state.idle.IdleTree;
|
||||
import electrosphere.entity.state.hitbox.HitboxCollectionState;
|
||||
import electrosphere.entity.state.idle.ClientIdleTree;
|
||||
import electrosphere.entity.state.idle.ServerIdleTree;
|
||||
import electrosphere.entity.state.inventory.ClientInventoryState;
|
||||
import electrosphere.entity.state.inventory.InventoryUtils;
|
||||
import electrosphere.entity.state.inventory.ServerInventoryState;
|
||||
@ -44,11 +46,17 @@ public class ObjectUtils {
|
||||
//the entity type value
|
||||
public static final int ENTITY_TYPE_OBJECT = 2;
|
||||
|
||||
/**
|
||||
* Spawns an object in the client scene
|
||||
* @param type The type of object
|
||||
* @return The object entity
|
||||
*/
|
||||
public static Entity clientSpawnBasicObject(String type){
|
||||
ObjectData rawType = Globals.gameConfigCurrent.getObjectTypeLoader().getObject(type);
|
||||
Entity rVal = EntityCreationUtils.createClientSpatialEntity();
|
||||
EntityCreationUtils.makeEntityPoseable(rVal, rawType.getModelPath());
|
||||
Actor creatureActor = EntityUtils.getActor(rVal);
|
||||
if(rawType.getModelPath() != null){
|
||||
EntityCreationUtils.makeEntityDrawable(rVal, rawType.getModelPath());
|
||||
}
|
||||
//forward-searching tokens
|
||||
boolean collisionMakeDynamic = true;
|
||||
for(String token : rawType.getTokens()){
|
||||
@ -112,11 +120,14 @@ public class ObjectUtils {
|
||||
} break;
|
||||
}
|
||||
}
|
||||
if(rawType.getHitboxData() != null){
|
||||
HitboxCollectionState.attachHitboxState(Globals.clientSceneWrapper.getHitboxManager(), false, rVal, rawType.getHitboxData());
|
||||
}
|
||||
//add health system
|
||||
// rVal.putData(EntityDataStrings.LIFE_STATE, new LifeState(rVal, rawType.getHealthSystem()));
|
||||
// Globals.entityManager.registerLifeStateEntity(rVal);
|
||||
//idle tree & generic stuff all objects have
|
||||
rVal.putData(EntityDataStrings.TREE_IDLE, new IdleTree(rVal));
|
||||
rVal.putData(EntityDataStrings.TREE_IDLE, new ClientIdleTree(rVal));
|
||||
rVal.putData(EntityDataStrings.DRAW_CAST_SHADOW, true);
|
||||
rVal.putData(EntityDataStrings.ENTITY_TYPE, ENTITY_TYPE_OBJECT);
|
||||
rVal.putData(EntityDataStrings.ENTITY_SUBTYPE, type);
|
||||
@ -133,9 +144,10 @@ public class ObjectUtils {
|
||||
public static Entity serverSpawnBasicObject(Realm realm, Vector3d position, String type){
|
||||
ObjectData rawType = Globals.gameConfigCurrent.getObjectTypeLoader().getObject(type);
|
||||
Entity rVal = EntityCreationUtils.createServerEntity(realm, position);
|
||||
EntityCreationUtils.makeEntityPoseable(rVal, rawType.getModelPath());
|
||||
|
||||
PoseActor creatureActor = EntityUtils.getPoseActor(rVal);
|
||||
if(rawType.getModelPath() != null){
|
||||
EntityCreationUtils.makeEntityPoseable(rVal, rawType.getModelPath());
|
||||
}
|
||||
//forward-searching tokens
|
||||
boolean collisionMakeDynamic = true;
|
||||
for(String token : rawType.getTokens()){
|
||||
@ -199,12 +211,11 @@ public class ObjectUtils {
|
||||
} break;
|
||||
}
|
||||
}
|
||||
//add health system
|
||||
// rVal.putData(EntityDataStrings.LIFE_STATE, new LifeState(rVal, rawType.getHealthSystem()));
|
||||
// Globals.entityManager.registerLifeStateEntity(rVal);
|
||||
if(rawType.getHitboxData() != null){
|
||||
HitboxCollectionState.attachHitboxState(realm.getHitboxManager(), true, rVal, rawType.getHitboxData());
|
||||
}
|
||||
//idle tree & generic stuff all objects have
|
||||
rVal.putData(EntityDataStrings.TREE_IDLE, new IdleTree(rVal));
|
||||
rVal.putData(EntityDataStrings.DRAW_CAST_SHADOW, true);
|
||||
ServerIdleTree.attachTree(rVal);
|
||||
|
||||
|
||||
//position entity
|
||||
|
||||
@ -16,12 +16,13 @@ import electrosphere.entity.Entity;
|
||||
import electrosphere.entity.EntityCreationUtils;
|
||||
import electrosphere.entity.EntityUtils;
|
||||
import electrosphere.entity.ServerEntityUtils;
|
||||
import electrosphere.entity.state.hitbox.HitboxState;
|
||||
import electrosphere.entity.state.hitbox.HitboxCollectionState;
|
||||
import electrosphere.entity.state.movement.ProjectileTree;
|
||||
import electrosphere.game.data.collidable.HitboxData;
|
||||
import electrosphere.game.data.projectile.ProjectileType;
|
||||
import electrosphere.server.datacell.Realm;
|
||||
import electrosphere.server.datacell.utils.ServerBehaviorTreeUtils;
|
||||
import electrosphere.util.MathUtils;
|
||||
|
||||
public class ProjectileUtils {
|
||||
|
||||
@ -41,7 +42,7 @@ public class ProjectileUtils {
|
||||
Globals.assetManager.addModelPathToQueue(model);
|
||||
ProjectileTree tree = new ProjectileTree(rVal,maxLife,new Vector3d(initialVector),velocity);
|
||||
EntityUtils.getPosition(rVal).set(initialPosition);
|
||||
EntityUtils.getRotation(rVal).rotationTo(new Vector3d(0,0,1), new Vector3d(initialVector.x,initialVector.y,initialVector.z)).normalize();
|
||||
EntityUtils.getRotation(rVal).rotationTo(MathUtils.getOriginVector(), new Vector3d(initialVector.x,initialVector.y,initialVector.z)).normalize();
|
||||
Globals.clientSceneWrapper.getScene().registerBehaviorTree(tree);
|
||||
return rVal;
|
||||
}
|
||||
@ -61,8 +62,8 @@ public class ProjectileUtils {
|
||||
Globals.assetManager.addModelPathToQueue(model);
|
||||
ProjectileTree tree = new ProjectileTree(rVal,maxLife,new Vector3d(initialVector),velocity);
|
||||
EntityUtils.getPosition(rVal).set(initialPosition);
|
||||
// EntityUtils.getRotation(currentEntity).rotationTo(new Vector3f(0,0,1), new Vector3f((float)facingAngle.x,(float)facingAngle.y,(float)facingAngle.z)).mul(parentActor.getBoneRotation(targetBone)).normalize();
|
||||
EntityUtils.getRotation(rVal).rotationTo(new Vector3d(0,0,1), new Vector3d(initialVector.x,initialVector.y,initialVector.z)).normalize();
|
||||
// EntityUtils.getRotation(currentEntity).rotationTo(MathUtils.ORIGIN_VECTORF, new Vector3f((float)facingAngle.x,(float)facingAngle.y,(float)facingAngle.z)).mul(parentActor.getBoneRotation(targetBone)).normalize();
|
||||
EntityUtils.getRotation(rVal).rotationTo(MathUtils.getOriginVector(), new Vector3d(initialVector.x,initialVector.y,initialVector.z)).normalize();
|
||||
// ParticleTree particleTree = new ParticleTree(rVal, maxLife, destination, velocity, acceleration, true);
|
||||
// rVal.putData(EntityDataStrings.PARTICLE_TREE, particleTree);
|
||||
// rVal.putData(EntityDataStrings.IS_PARTICLE, true);
|
||||
@ -84,7 +85,7 @@ public class ProjectileUtils {
|
||||
Entity rVal = EntityCreationUtils.createClientSpatialEntity();
|
||||
EntityCreationUtils.makeEntityDrawable(rVal, rawType.getModelPath());
|
||||
//initial coordinates
|
||||
EntityUtils.getRotation(rVal).rotationTo(new Vector3d(0,0,1), new Vector3d(initialVector.x,initialVector.y,initialVector.z)).normalize();
|
||||
EntityUtils.getRotation(rVal).rotationTo(MathUtils.getOriginVector(), new Vector3d(initialVector.x,initialVector.y,initialVector.z)).normalize();
|
||||
EntityUtils.getPosition(rVal).set(initialPosition);
|
||||
//projectile behavior tree
|
||||
ProjectileTree tree = new ProjectileTree(rVal,rawType.getMaxLife(),initialVector,rawType.getVelocity(), rawType.getDamage());
|
||||
@ -96,7 +97,7 @@ public class ProjectileUtils {
|
||||
//collidable
|
||||
HitboxData hitboxData = new HitboxData();
|
||||
hitboxData.setRadius(rawType.getHitboxRadius());
|
||||
HitboxState.attachHitboxStateWithCallback(Globals.clientSceneWrapper.getHitboxManager(), Globals.clientSceneWrapper.getCollisionEngine(), rVal, hitboxData,
|
||||
HitboxCollectionState.attachHitboxStateWithCallback(Globals.clientSceneWrapper.getHitboxManager(), Globals.clientSceneWrapper.getCollisionEngine(), rVal, hitboxData,
|
||||
new HitboxPositionCallback() {
|
||||
public Vector3d getPosition(){
|
||||
return EntityUtils.getPosition(rVal);
|
||||
@ -119,7 +120,7 @@ public class ProjectileUtils {
|
||||
ProjectileType rawType = Globals.gameConfigCurrent.getProjectileMap().getType(projectileType);
|
||||
Entity rVal = EntityCreationUtils.createServerEntity(realm, initialPosition);
|
||||
//initial coordinates
|
||||
EntityUtils.getRotation(rVal).rotationTo(new Vector3d(0,0,1), new Vector3d(initialVector.x,initialVector.y,initialVector.z)).normalize();
|
||||
EntityUtils.getRotation(rVal).rotationTo(MathUtils.getOriginVector(), new Vector3d(initialVector.x,initialVector.y,initialVector.z)).normalize();
|
||||
EntityUtils.getPosition(rVal).set(initialPosition);
|
||||
//projectile behavior tree
|
||||
ProjectileTree tree = new ProjectileTree(rVal,rawType.getMaxLife(),initialVector,rawType.getVelocity(), rawType.getDamage());
|
||||
@ -131,7 +132,7 @@ public class ProjectileUtils {
|
||||
//collidable
|
||||
HitboxData hitboxData = new HitboxData();
|
||||
hitboxData.setRadius(rawType.getHitboxRadius());
|
||||
HitboxState.attachHitboxStateWithCallback(realm.getHitboxManager(), realm.getCollisionEngine(), rVal, hitboxData,
|
||||
HitboxCollectionState.attachHitboxStateWithCallback(realm.getHitboxManager(), realm.getCollisionEngine(), rVal, hitboxData,
|
||||
new HitboxPositionCallback() {
|
||||
public Vector3d getPosition(){
|
||||
return EntityUtils.getPosition(rVal);
|
||||
|
||||
@ -10,6 +10,20 @@ import electrosphere.entity.Entity;
|
||||
*/
|
||||
public class HitboxData {
|
||||
|
||||
//a hitbox sphere that teleports to its new position between frames
|
||||
public static final String HITBOX_TYPE_HIT = "hit";
|
||||
//a hurtbox sphere that teleports to its new position between frames
|
||||
public static final String HITBOX_TYPE_HURT = "hurt";
|
||||
//a hitbox sphere that is connected to its previous position by a capsule. The capsule is used for collision checks
|
||||
public static final String HITBOX_TYPE_HIT_CONNECTED = "hit_connected";
|
||||
//a hurtbox sphere that is connected to its previous position by a capsule. The capsule is used for collision checks
|
||||
public static final String HITBOX_TYPE_HURT_CONNECTED = "hurt_connected";
|
||||
//a block sphere that is connected to its previous position by a capsule. The capsule is used for collision checks
|
||||
public static final String HITBOX_TYPE_BLOCK_CONNECTED = "block_connected";
|
||||
|
||||
//used for debugging -- to show whether a hitbox is colliding with it or not
|
||||
public static final String HITBOX_TYPE_STATIC_CAPSULE = "static_capsule";
|
||||
|
||||
//the type of hitbox
|
||||
String type;
|
||||
|
||||
@ -19,6 +33,9 @@ public class HitboxData {
|
||||
//the radius of the hitbox
|
||||
float radius;
|
||||
|
||||
//the length of a static capsule hitbox
|
||||
float length;
|
||||
|
||||
//controls whether the hitbox is active or not
|
||||
boolean active = false;
|
||||
|
||||
@ -52,6 +69,14 @@ public class HitboxData {
|
||||
return radius;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the length of hitbox if applicable
|
||||
* @return The length
|
||||
*/
|
||||
public float getLength(){
|
||||
return length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the hitbox is active or not
|
||||
* @return true if the hitbox is active, false otherwise
|
||||
|
||||
@ -60,6 +60,14 @@ public class EquipPoint {
|
||||
return offsetRotation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the offset rotation (used primarily for debug and engine testing)
|
||||
* @param offsetRotation The new offset rotation
|
||||
*/
|
||||
public void setOffsetRotation(List<Float> offsetRotation){
|
||||
this.offsetRotation = offsetRotation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the equip classes that are whitelisted for this equip point
|
||||
* @return the classes
|
||||
|
||||
@ -3,9 +3,14 @@ package electrosphere.game.data.graphics;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* A graphics template for an entity
|
||||
*/
|
||||
public class GraphicsTemplate {
|
||||
|
||||
//a list of shader overrides
|
||||
List<String> shaderOverrideMeshList;
|
||||
//??? TODO: investigate
|
||||
Map<String,ShaderSet> shaderMap;
|
||||
|
||||
public List<String> getShaderOverrideMeshList(){
|
||||
|
||||
@ -6,32 +6,70 @@ import electrosphere.game.data.graphics.GraphicsTemplate;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Metadata about a type of object
|
||||
*/
|
||||
public class ObjectData {
|
||||
|
||||
//the id of the object
|
||||
String objectId;
|
||||
//the path for the model for this object
|
||||
String modelPath;
|
||||
//tokens associated with this object
|
||||
List<String> tokens;
|
||||
//the collidable template for this object
|
||||
CollidableTemplate collidable;
|
||||
//the graphics template for this object
|
||||
GraphicsTemplate graphicsTemplate;
|
||||
//the hitbox data for this object
|
||||
List<HitboxData> hitboxData;
|
||||
|
||||
/**
|
||||
* Gets the id of the object
|
||||
* @return the id
|
||||
*/
|
||||
public String getObjectId() {
|
||||
return objectId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the model path of the object
|
||||
* @return the model path
|
||||
*/
|
||||
public String getModelPath() {
|
||||
return modelPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all tokens associated with this object
|
||||
* @return the list of all tokens
|
||||
*/
|
||||
public List<String> getTokens() {
|
||||
return tokens;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the collidable data for this object
|
||||
* @return the collidable data
|
||||
*/
|
||||
public CollidableTemplate getCollidable(){
|
||||
return collidable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the graphics template for this object
|
||||
* @return the graphics template
|
||||
*/
|
||||
public GraphicsTemplate getGraphicsTemplate(){
|
||||
return graphicsTemplate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the hitbox data for this object
|
||||
* @return the hitbox data
|
||||
*/
|
||||
public List<HitboxData> getHitboxData(){
|
||||
return this.hitboxData;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -7,14 +7,40 @@ import java.util.Map;
|
||||
|
||||
import electrosphere.game.data.object.type.ObjectData;
|
||||
|
||||
/**
|
||||
* An interface for grabbing data about objects available to the game engine
|
||||
*/
|
||||
public class ObjectTypeLoader {
|
||||
|
||||
//the map that stores all object types by name
|
||||
Map<String,ObjectData> objectMap = new HashMap<String,ObjectData>();
|
||||
|
||||
public void putObject(String name, ObjectData type){
|
||||
objectMap.put(name,type);
|
||||
//the list of all object data
|
||||
List<ObjectData> objectList = new LinkedList<ObjectData>();
|
||||
|
||||
/**
|
||||
* Gets the list of all object types loaded into memory
|
||||
* @return The list
|
||||
*/
|
||||
public List<ObjectData> getAllObjectTypes(){
|
||||
return objectList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts an object in the map
|
||||
* @param name The name of the object
|
||||
* @param type The object type data
|
||||
*/
|
||||
public void putObject(String name, ObjectData type){
|
||||
objectMap.put(name,type);
|
||||
objectList.add(type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets object data by its name
|
||||
* @param name The name of the object type
|
||||
* @return The object data if it exists, otherwise null
|
||||
*/
|
||||
public ObjectData getObject(String name){
|
||||
return objectMap.get(name);
|
||||
}
|
||||
|
||||
@ -3,15 +3,29 @@ package electrosphere.game.data.object.type.model;
|
||||
import electrosphere.game.data.object.type.ObjectData;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* The raw list of object data read from disk
|
||||
*/
|
||||
public class ObjectTypeMap {
|
||||
|
||||
//the objects stored in this file
|
||||
List<ObjectData> objects;
|
||||
//all children files to recursively parse for more object data
|
||||
List<String> files;
|
||||
|
||||
/**
|
||||
* Gets the list of all objects in this file
|
||||
* @return the list
|
||||
*/
|
||||
public List<ObjectData> getObjects() {
|
||||
return objects;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the object data for an object in this file by its name
|
||||
* @param name the name of the object
|
||||
* @return The object data
|
||||
*/
|
||||
public ObjectData getObject(String name){
|
||||
ObjectData rVal = null;
|
||||
for(ObjectData item : objects){
|
||||
@ -23,6 +37,10 @@ public class ObjectTypeMap {
|
||||
return rVal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the list of all children files of this file
|
||||
* @return The list of all children files
|
||||
*/
|
||||
public List<String> getFiles(){
|
||||
return files;
|
||||
}
|
||||
|
||||
@ -1,46 +1,90 @@
|
||||
package electrosphere.logger;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author amaterasu
|
||||
* A channel for logging messages
|
||||
*/
|
||||
public class Logger {
|
||||
|
||||
/**
|
||||
* The different logging levels
|
||||
*/
|
||||
public enum LogLevel {
|
||||
LOOP_DEBUG, //this should be used for debugging messages that are executed very rapidly/every frame
|
||||
DEBUG,
|
||||
INFO,
|
||||
WARNING,
|
||||
ERROR,
|
||||
}
|
||||
|
||||
//the level of this log
|
||||
LogLevel level;
|
||||
|
||||
/**
|
||||
* Creates a logger channel
|
||||
* @param level The level of message to report on this channel
|
||||
*/
|
||||
public Logger(LogLevel level){
|
||||
this.level = level;
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs a loop debug message.
|
||||
* This should be used for debugging messages that are executed very rapidly/every frame
|
||||
* @param message The message to report
|
||||
*/
|
||||
public void DEBUG_LOOP(String message){
|
||||
if(level == LogLevel.LOOP_DEBUG){
|
||||
System.out.println(message);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Logs a debug message.
|
||||
* This should be used for debugging messages that are executed on a given condition that won't necessarily be every loop (ie all network messages)
|
||||
* @param message The message to report
|
||||
*/
|
||||
public void DEBUG(String message){
|
||||
if(level == LogLevel.DEBUG){
|
||||
if(level == LogLevel.LOOP_DEBUG || level == LogLevel.DEBUG){
|
||||
System.out.println(message);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Logs an info message.
|
||||
* This should be used for messages that would have interest to someone running a server (ie specific network messages, account creation, etc)
|
||||
* @param message The message to report
|
||||
*/
|
||||
public void INFO(String message){
|
||||
if(level == LogLevel.DEBUG || level == LogLevel.INFO){
|
||||
if(level == LogLevel.LOOP_DEBUG || level == LogLevel.DEBUG || level == LogLevel.INFO){
|
||||
System.out.println(message);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Logs a warning message.
|
||||
* This should be used for reporting events that happen in the engine that are concerning but don't mean the engine has failed to execute (ie a texture failed to load)
|
||||
* @param message The message to report
|
||||
*/
|
||||
public void WARNING(String message){
|
||||
if(level == LogLevel.DEBUG || level == LogLevel.INFO || level == LogLevel.WARNING){
|
||||
if(level == LogLevel.LOOP_DEBUG || level == LogLevel.DEBUG || level == LogLevel.INFO || level == LogLevel.WARNING){
|
||||
System.out.println(message);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Logs an error message.
|
||||
* This should be used every time we throw any kind of error in the engine
|
||||
* @param message The message to report
|
||||
*/
|
||||
public void ERROR(String message, Exception e){
|
||||
if(level == LogLevel.DEBUG || level == LogLevel.INFO || level == LogLevel.WARNING || level == LogLevel.ERROR){
|
||||
System.out.println(message);
|
||||
if(level == LogLevel.LOOP_DEBUG || level == LogLevel.DEBUG || level == LogLevel.INFO || level == LogLevel.WARNING || level == LogLevel.ERROR){
|
||||
System.err.println(message);
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -12,8 +12,15 @@ import electrosphere.renderer.ui.elementtypes.ContainerElement;
|
||||
import electrosphere.renderer.ui.elementtypes.DrawableElement;
|
||||
import electrosphere.renderer.ui.elementtypes.Element;
|
||||
|
||||
/**
|
||||
* Utils for native windowing framework
|
||||
*/
|
||||
public class WindowUtils {
|
||||
|
||||
/**
|
||||
* Replaces the main menu contents
|
||||
* @param newMenu The new contents
|
||||
*/
|
||||
public static void replaceMainMenuContents(Element newMenu){
|
||||
Element mainMenuEl = Globals.elementManager.getWindow(WindowStrings.WINDOW_MENU_MAIN);
|
||||
if(mainMenuEl != null && mainMenuEl instanceof Window){
|
||||
@ -26,6 +33,11 @@ public class WindowUtils {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively sets a window as visible or not
|
||||
* @param topLevelMenu The window element
|
||||
* @param visible true for visible, false for invisible
|
||||
*/
|
||||
public static void recursiveSetVisible(Element topLevelMenu, boolean visible){
|
||||
if(topLevelMenu instanceof DrawableElement){
|
||||
((DrawableElement)topLevelMenu).setVisible(visible);
|
||||
@ -40,6 +52,29 @@ public class WindowUtils {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the window registered to the provided string is open
|
||||
* @param windowString The window string
|
||||
* @return true if the window is open, false otherwise
|
||||
*/
|
||||
public static boolean windowIsOpen(String windowString){
|
||||
Element windowElement = Globals.elementManager.getWindow(windowString);
|
||||
return Globals.elementManager.getWindowList().contains(windowElement);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a window is open or not
|
||||
* @return The window
|
||||
*/
|
||||
public static boolean controlBlockingWindowIsOpen(){
|
||||
return windowIsOpen(WindowStrings.LEVEL_EDTIOR_SIDE_PANEL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an inventory window string by the id of the inventory
|
||||
* @param id the id
|
||||
* @return the window string for said inventory window
|
||||
*/
|
||||
public static String getInventoryWindowID(int id){
|
||||
return "INVENTORY-" + id;
|
||||
}
|
||||
@ -76,8 +111,8 @@ public class WindowUtils {
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to close a window
|
||||
* @param window the window to close
|
||||
* Cleans up a window visually and removes it from the element manager
|
||||
* @param window the window to clean up
|
||||
*/
|
||||
public static void closeWindow(String window){
|
||||
Element windowEl = Globals.elementManager.getWindow(window);
|
||||
|
||||
@ -1,15 +1,27 @@
|
||||
package electrosphere.menu.debug;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import org.joml.Quaterniond;
|
||||
|
||||
import electrosphere.engine.Globals;
|
||||
import electrosphere.entity.Entity;
|
||||
import electrosphere.entity.EntityUtils;
|
||||
import electrosphere.entity.state.equip.ClientEquipState;
|
||||
import electrosphere.entity.types.attach.AttachUtils;
|
||||
import electrosphere.entity.types.creature.CreatureUtils;
|
||||
import electrosphere.entity.types.foliage.FoliageUtils;
|
||||
import electrosphere.entity.types.item.ItemUtils;
|
||||
import electrosphere.renderer.RenderingEngine;
|
||||
import electrosphere.game.data.creature.type.equip.EquipPoint;
|
||||
import electrosphere.logger.LoggerInterface;
|
||||
import electrosphere.renderer.actor.Actor;
|
||||
import electrosphere.renderer.actor.ActorMeshMask;
|
||||
import electrosphere.renderer.anim.AnimChannel;
|
||||
import electrosphere.renderer.anim.Animation;
|
||||
import electrosphere.renderer.model.Bone;
|
||||
import electrosphere.renderer.model.Mesh;
|
||||
import electrosphere.renderer.model.Model;
|
||||
import electrosphere.renderer.ui.imgui.ImGuiWindow;
|
||||
import electrosphere.renderer.ui.imgui.ImGuiWindow.ImGuiWindowCallback;
|
||||
import imgui.ImGui;
|
||||
@ -19,11 +31,17 @@ import imgui.ImGui;
|
||||
*/
|
||||
public class ImGuiEntityMacros {
|
||||
|
||||
//window for viewing main player entity's stats on both client and server
|
||||
protected static ImGuiWindow clientEntityWindow;
|
||||
private static boolean filterToCreatures = false;
|
||||
private static boolean filterToCreatures = false; //filters the entity list to just creatures
|
||||
|
||||
//views stats about an actor
|
||||
protected static ImGuiWindow actorView;
|
||||
static Entity actorViewEntity;
|
||||
static Entity actorViewEntity; //the entity whose actor we're viewing in the actor window
|
||||
|
||||
//views stats about equip state
|
||||
protected static ImGuiWindow equipStateView;
|
||||
static Entity equipViewEntity; //the entity whose equip state we're viewing in the equip window
|
||||
|
||||
/**
|
||||
* Creates the windows in this file
|
||||
@ -31,6 +49,7 @@ public class ImGuiEntityMacros {
|
||||
protected static void createClientEntityWindows(){
|
||||
createClientEntityDebugWindow();
|
||||
createActorViewDebugWindow();
|
||||
createEquipStateDebugWindow();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -54,9 +73,17 @@ public class ImGuiEntityMacros {
|
||||
ImGui.beginGroup();
|
||||
ImGui.text("Id: " + entity.getId() + " (" + getEntityName(entity) + ")");
|
||||
if(CreatureUtils.isCreature(entity)){
|
||||
if(ImGui.button("Actor View")){
|
||||
actorViewEntity = entity;
|
||||
actorView.setOpen(true);
|
||||
if(EntityUtils.getActor(entity) != null){
|
||||
if(ImGui.button("Actor View")){
|
||||
actorViewEntity = entity;
|
||||
actorView.setOpen(true);
|
||||
}
|
||||
}
|
||||
if(ClientEquipState.getClientEquipState(entity) != null){
|
||||
if(ImGui.button("Client Equip State View")){
|
||||
equipViewEntity = entity;
|
||||
equipStateView.setOpen(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
ImGui.endGroup();
|
||||
@ -64,7 +91,7 @@ public class ImGuiEntityMacros {
|
||||
}
|
||||
});
|
||||
clientEntityWindow.setOpen(false);
|
||||
RenderingEngine.addImGuiWindow(clientEntityWindow);
|
||||
Globals.renderingEngine.getImGuiPipeline().addImGuiWindow(clientEntityWindow);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -90,11 +117,88 @@ public class ImGuiEntityMacros {
|
||||
ImGui.text(blocked);
|
||||
}
|
||||
}
|
||||
|
||||
//print bone values
|
||||
if(ImGui.button("Print current bone values")){
|
||||
for(Bone bone : actor.getBoneValues()){
|
||||
LoggerInterface.loggerRenderer.DEBUG(bone.boneID);
|
||||
LoggerInterface.loggerRenderer.DEBUG("" + bone.getFinalTransform());
|
||||
}
|
||||
}
|
||||
|
||||
//print animation keys
|
||||
if(ImGui.button("Print animation keys")){
|
||||
Model model = Globals.assetManager.fetchModel(actor.getModelPath());
|
||||
model.describeAllAnimations();
|
||||
}
|
||||
|
||||
//Browsable list of all animations with their data
|
||||
if(ImGui.collapsingHeader("Animation Channel Data")){
|
||||
Model model = Globals.assetManager.fetchModel(actor.getModelPath());
|
||||
for(Animation animation : model.getAnimations()){
|
||||
ImGui.text(" - " + animation.name);
|
||||
for(AnimChannel channel : animation.channels){
|
||||
ImGui.text("=" + channel.getNodeID() + "=");
|
||||
ImGui.text("" + channel.getCurrentPosition());
|
||||
ImGui.text("" + channel.getCurrentRotation());
|
||||
ImGui.text("" + channel.getCurrentScale());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
actorView.setOpen(false);
|
||||
RenderingEngine.addImGuiWindow(actorView);
|
||||
Globals.renderingEngine.getImGuiPipeline().addImGuiWindow(actorView);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Client scene equip state view
|
||||
*/
|
||||
protected static void createEquipStateDebugWindow(){
|
||||
equipStateView = new ImGuiWindow("Client Equip State View");
|
||||
equipStateView.setCallback(new ImGuiWindowCallback() {
|
||||
|
||||
//stores the edited rotation values
|
||||
float[] rotationValues = new float[]{
|
||||
0,0,0
|
||||
};
|
||||
|
||||
@Override
|
||||
public void exec() {
|
||||
if(equipViewEntity != null && ClientEquipState.getClientEquipState(equipViewEntity) != null){
|
||||
ClientEquipState clientEquipState = ClientEquipState.getClientEquipState(equipViewEntity);
|
||||
|
||||
if(ImGui.collapsingHeader("All Equip Points")){
|
||||
for(EquipPoint point : clientEquipState.getAllEquipPoints()){
|
||||
if(ImGui.collapsingHeader(point.getEquipPointId())){
|
||||
ImGui.text("Has item equipped: " + (clientEquipState.getEquippedItemAtPoint(point.getEquipPointId()) != null));
|
||||
ImGui.text("Bone (Third Person): " + point.getBone());
|
||||
ImGui.text("Bone (First Person): " + point.getFirstPersonBone());
|
||||
ImGui.text("Rotation: " + AttachUtils.getEquipPointRotationOffset(point.getOffsetRotation()));
|
||||
if(ImGui.sliderFloat3("Rotation (In Euler along x,y,z)", rotationValues, 0, (float)(Math.PI * 2))){
|
||||
Quaterniond rotation = new Quaterniond().rotateXYZ(rotationValues[0], rotationValues[1], rotationValues[2]);
|
||||
List<Float> newValues = new LinkedList<Float>();
|
||||
newValues.add((float)rotation.x);
|
||||
newValues.add((float)rotation.y);
|
||||
newValues.add((float)rotation.z);
|
||||
newValues.add((float)rotation.w);
|
||||
point.setOffsetRotation(newValues);
|
||||
Entity equippedEntity = clientEquipState.getEquippedItemAtPoint(point.getEquipPointId());
|
||||
if(equippedEntity != null){
|
||||
AttachUtils.setRotationOffset(equippedEntity, AttachUtils.getEquipPointRotationOffset(point.getOffsetRotation()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
equipStateView.setOpen(false);
|
||||
Globals.renderingEngine.getImGuiPipeline().addImGuiWindow(equipStateView);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
8
src/main/java/electrosphere/menu/debug/ImGuiUtils.java
Normal file
8
src/main/java/electrosphere/menu/debug/ImGuiUtils.java
Normal file
@ -0,0 +1,8 @@
|
||||
package electrosphere.menu.debug;
|
||||
|
||||
/**
|
||||
* Utilities for dealing with imgui
|
||||
*/
|
||||
public class ImGuiUtils {
|
||||
|
||||
}
|
||||
@ -7,13 +7,13 @@ import org.ode4j.ode.DBody;
|
||||
|
||||
import electrosphere.audio.VirtualAudioSource;
|
||||
import electrosphere.collision.PhysicsEntityUtils;
|
||||
import electrosphere.controls.ControlHandler.ControlsState;
|
||||
import electrosphere.engine.Globals;
|
||||
import electrosphere.entity.Entity;
|
||||
import electrosphere.entity.EntityUtils;
|
||||
import electrosphere.entity.state.attack.ClientAttackTree;
|
||||
import electrosphere.entity.state.server.ServerPlayerViewDirTree;
|
||||
import electrosphere.entity.types.creature.CreatureUtils;
|
||||
import electrosphere.renderer.RenderingEngine;
|
||||
import electrosphere.renderer.ui.imgui.ImGuiLinePlot;
|
||||
import electrosphere.renderer.ui.imgui.ImGuiWindow;
|
||||
import electrosphere.renderer.ui.imgui.ImGuiLinePlot.ImGuiLinePlotDataset;
|
||||
@ -75,7 +75,15 @@ public class ImGuiWindowMacros {
|
||||
initFramerateGraphSeries("controls");
|
||||
globalFrametimeWindow.addElement(globalFrametimePlot);
|
||||
globalFrametimeWindow.setOpen(false);
|
||||
RenderingEngine.addImGuiWindow(globalFrametimeWindow);
|
||||
Globals.renderingEngine.getImGuiPipeline().addImGuiWindow(globalFrametimeWindow);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the main debug window
|
||||
* @return the main debug window
|
||||
*/
|
||||
public static ImGuiWindow getMainDebugWindow(){
|
||||
return mainDebugWindow;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -158,7 +166,7 @@ public class ImGuiWindowMacros {
|
||||
}
|
||||
});
|
||||
audioDebugMenu.setOpen(false);
|
||||
RenderingEngine.addImGuiWindow(audioDebugMenu);
|
||||
Globals.renderingEngine.getImGuiPipeline().addImGuiWindow(audioDebugMenu);
|
||||
}
|
||||
|
||||
|
||||
@ -210,7 +218,7 @@ public class ImGuiWindowMacros {
|
||||
}
|
||||
});
|
||||
playerEntityWindow.setOpen(false);
|
||||
RenderingEngine.addImGuiWindow(playerEntityWindow);
|
||||
Globals.renderingEngine.getImGuiPipeline().addImGuiWindow(playerEntityWindow);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -229,7 +237,7 @@ public class ImGuiWindowMacros {
|
||||
}
|
||||
});
|
||||
fluidWindow.setOpen(false);
|
||||
RenderingEngine.addImGuiWindow(fluidWindow);
|
||||
Globals.renderingEngine.getImGuiPipeline().addImGuiWindow(fluidWindow);
|
||||
}
|
||||
|
||||
|
||||
@ -268,7 +276,7 @@ public class ImGuiWindowMacros {
|
||||
}
|
||||
});
|
||||
mainDebugWindow.setOpen(false);
|
||||
RenderingEngine.addImGuiWindow(mainDebugWindow);
|
||||
Globals.renderingEngine.getImGuiPipeline().addImGuiWindow(mainDebugWindow);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -276,6 +284,11 @@ public class ImGuiWindowMacros {
|
||||
*/
|
||||
public static void toggleMainDebugMenu(){
|
||||
mainDebugWindow.setOpen(!mainDebugWindow.isOpen());
|
||||
if(mainDebugWindow.isOpen()){
|
||||
Globals.controlHandler.hintUpdateControlState(ControlsState.IN_GAME_MAIN_MENU);
|
||||
} else {
|
||||
Globals.controlHandler.hintUpdateControlState(ControlsState.MAIN_GAME);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -51,11 +51,10 @@ public class MenuGeneratorsInGame {
|
||||
WindowUtils.recursiveSetVisible(Globals.elementManager.getWindow(WindowStrings.WINDOW_MENU_INGAME_MAIN), false);
|
||||
Globals.elementManager.unregisterWindow(WindowStrings.WINDOW_MENU_INGAME_MAIN);
|
||||
if(Globals.cameraHandler.getTrackPlayerEntity()){
|
||||
Globals.controlHandler.setHandlerState(ControlsState.MAIN_GAME);
|
||||
Globals.controlHandler.hintUpdateControlState(ControlsState.MAIN_GAME);
|
||||
} else {
|
||||
Globals.controlHandler.setHandlerState(ControlsState.IN_GAME_FREE_CAMERA);
|
||||
Globals.controlHandler.hintUpdateControlState(ControlsState.IN_GAME_FREE_CAMERA);
|
||||
}
|
||||
Globals.controlHandler.hideMouse();
|
||||
return false;
|
||||
}});
|
||||
|
||||
@ -76,11 +75,10 @@ public class MenuGeneratorsInGame {
|
||||
WindowUtils.recursiveSetVisible(Globals.elementManager.getWindow(WindowStrings.WINDOW_MENU_INGAME_MAIN), false);
|
||||
Globals.elementManager.unregisterWindow(WindowStrings.WINDOW_MENU_INGAME_MAIN);
|
||||
if(Globals.cameraHandler.getTrackPlayerEntity()){
|
||||
Globals.controlHandler.setHandlerState(ControlsState.MAIN_GAME);
|
||||
Globals.controlHandler.hintUpdateControlState(ControlsState.MAIN_GAME);
|
||||
} else {
|
||||
Globals.controlHandler.setHandlerState(ControlsState.IN_GAME_FREE_CAMERA);
|
||||
Globals.controlHandler.hintUpdateControlState(ControlsState.IN_GAME_FREE_CAMERA);
|
||||
}
|
||||
Globals.controlHandler.hideMouse();
|
||||
return false;
|
||||
}});
|
||||
|
||||
|
||||
@ -50,8 +50,7 @@ public class MenuGeneratorsInventory {
|
||||
//
|
||||
Globals.openInventoriesCount--;
|
||||
if(Globals.openInventoriesCount == 0){
|
||||
Globals.controlHandler.setHandlerState(ControlsState.MAIN_GAME);
|
||||
Globals.controlHandler.hideMouse();
|
||||
Globals.controlHandler.hintUpdateControlState(ControlsState.MAIN_GAME);
|
||||
}
|
||||
//play sound effect
|
||||
Globals.virtualAudioSourceManager.createVirtualAudioSource("/Audio/closeMenu.ogg", VirtualAudioSourceType.UI, false);
|
||||
@ -223,8 +222,7 @@ public class MenuGeneratorsInventory {
|
||||
//
|
||||
Globals.openInventoriesCount--;
|
||||
if(Globals.openInventoriesCount == 0){
|
||||
Globals.controlHandler.setHandlerState(ControlsState.MAIN_GAME);
|
||||
Globals.controlHandler.hideMouse();
|
||||
Globals.controlHandler.hintUpdateControlState(ControlsState.MAIN_GAME);
|
||||
}
|
||||
//play sound effect
|
||||
Globals.virtualAudioSourceManager.createVirtualAudioSource("/Audio/closeMenu.ogg", VirtualAudioSourceType.UI, false);
|
||||
|
||||
@ -17,6 +17,7 @@ import electrosphere.entity.types.object.ObjectUtils;
|
||||
import electrosphere.game.data.creature.type.CreatureType;
|
||||
import electrosphere.game.data.foliage.type.FoliageType;
|
||||
import electrosphere.game.data.item.type.Item;
|
||||
import electrosphere.game.data.object.type.ObjectData;
|
||||
import electrosphere.logger.LoggerInterface;
|
||||
import electrosphere.menu.WindowStrings;
|
||||
import electrosphere.menu.WindowUtils;
|
||||
@ -114,6 +115,12 @@ public class MenuGeneratorsLevelEditor {
|
||||
return false;
|
||||
}}));
|
||||
|
||||
//spawn object button
|
||||
scrollable.addChild(Button.createButton("Spawn Object", new ClickEventCallback() {public boolean execute(ClickEvent event){
|
||||
fillInSpawnObjectContent(scrollable);
|
||||
return false;
|
||||
}}));
|
||||
|
||||
//select voxel button
|
||||
scrollable.addChild(Button.createButton("Select Voxel Type", new ClickEventCallback() {public boolean execute(ClickEvent event){
|
||||
if(voxelWindowOpen){
|
||||
@ -235,6 +242,37 @@ public class MenuGeneratorsLevelEditor {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Level editor menu content for spawning objects
|
||||
* @param scrollable
|
||||
*/
|
||||
private static void fillInSpawnObjectContent(VirtualScrollable scrollable){
|
||||
scrollable.clearChildren();
|
||||
|
||||
//back button
|
||||
scrollable.addChild(Button.createButton("Back", new ClickEventCallback() {public boolean execute(ClickEvent event){
|
||||
fillInDefaultContent(scrollable);
|
||||
return false;
|
||||
}}));
|
||||
|
||||
//button for spawning all foliage types
|
||||
for(ObjectData object : Globals.gameConfigCurrent.getObjectTypeLoader().getAllObjectTypes()){
|
||||
//spawn foliage button
|
||||
scrollable.addChild(Button.createButton("Spawn " + object.getObjectId(), new ClickEventCallback() {public boolean execute(ClickEvent event){
|
||||
LoggerInterface.loggerEngine.INFO("spawn " + object.getObjectId() + "!");
|
||||
Vector3d eyePos = new Vector3d(CameraEntityUtils.getCameraEye(Globals.playerCamera));
|
||||
Vector3d centerPos = new Vector3d(CameraEntityUtils.getCameraCenter(Globals.playerCamera));
|
||||
Realm realm = Globals.realmManager.getRealms().iterator().next();
|
||||
Vector3d cursorPos = realm.getCollisionEngine().rayCastPosition(new Vector3d(centerPos), new Vector3d(eyePos).mul(-1.0), 5.0);
|
||||
ObjectUtils.serverSpawnBasicObject(realm, cursorPos, object.getObjectId());
|
||||
return false;
|
||||
}}));
|
||||
}
|
||||
|
||||
mainSidePanel.applyYoga(0,0);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates tree view of entities in server
|
||||
* @param scrollable
|
||||
|
||||
@ -125,6 +125,9 @@ public class MenuGeneratorsTerrainEditing {
|
||||
voxelLabel.setText(type.getName());
|
||||
//icon/model
|
||||
ImagePanel texturePanel = ImagePanel.createImagePanel(type.getTexture());
|
||||
if(type.getTexture() != null){
|
||||
Globals.assetManager.addTexturePathtoQueue(type.getTexture());
|
||||
}
|
||||
texturePanel.setWidth(VOXEL_BUTTON_TEXTURE_DIM);
|
||||
texturePanel.setHeight(VOXEL_BUTTON_TEXTURE_DIM);
|
||||
newButton.addChild(texturePanel);
|
||||
|
||||
@ -0,0 +1,57 @@
|
||||
package electrosphere.menu.mainmenu;
|
||||
|
||||
import org.lwjgl.util.yoga.Yoga;
|
||||
|
||||
import electrosphere.engine.Globals;
|
||||
import electrosphere.engine.loadingthreads.LoadingThread;
|
||||
import electrosphere.menu.WindowUtils;
|
||||
import electrosphere.renderer.ui.elements.Button;
|
||||
import electrosphere.renderer.ui.elements.FormElement;
|
||||
import electrosphere.renderer.ui.elements.Label;
|
||||
import electrosphere.renderer.ui.elementtypes.ClickableElement;
|
||||
import electrosphere.renderer.ui.elementtypes.Element;
|
||||
import electrosphere.renderer.ui.events.ClickEvent;
|
||||
|
||||
/**
|
||||
* Generates menu items for the demo version of the engine
|
||||
*/
|
||||
public class MenuGeneratorsDemo {
|
||||
|
||||
/**
|
||||
* Creates the title menu for the demo
|
||||
* @return The content element to embed in a title window
|
||||
*/
|
||||
public static Element createTitleMenu(){
|
||||
FormElement rVal = new FormElement();
|
||||
//top-bottom
|
||||
rVal.setJustifyContent(Yoga.YGJustifyCenter);
|
||||
//left-right
|
||||
rVal.setAlignItems(Yoga.YGAlignCenter);
|
||||
rVal.setAlignContent(Yoga.YGAlignFlexStart);
|
||||
|
||||
//label (title)
|
||||
Label titleLabel = new Label(1.0f);
|
||||
titleLabel.setText("ORPG");
|
||||
rVal.addChild(titleLabel);
|
||||
|
||||
//button (arena)
|
||||
Button arenaButton = new Button();
|
||||
Label arenaLabel = new Label(1.0f);
|
||||
arenaLabel.setText("Start");
|
||||
arenaButton.addChild(arenaLabel);
|
||||
rVal.addChild(arenaButton);
|
||||
arenaButton.setOnClick(new ClickableElement.ClickEventCallback(){public boolean execute(ClickEvent event){
|
||||
LoadingThread serverThread = new LoadingThread(LoadingThread.LOAD_LEVEL);
|
||||
Globals.loadingThreadsList.add(serverThread);
|
||||
Globals.RUN_CLIENT = true;
|
||||
Globals.RUN_SERVER = true;
|
||||
serverThread.start();
|
||||
WindowUtils.replaceMainMenuContents(MenuGeneratorsArena.createArenaHostLoginMenu());
|
||||
return false;
|
||||
}});
|
||||
arenaButton.setMarginTop(50);
|
||||
|
||||
return rVal;
|
||||
}
|
||||
|
||||
}
|
||||
@ -27,7 +27,7 @@ public class InventoryProtocol {
|
||||
//translate equipper id
|
||||
Entity equipper = Globals.clientSceneWrapper.getEntityFromServerId(message.getequipperId());
|
||||
//spawn in world id
|
||||
Entity inWorldEntity = ItemUtils.clientSpawnBasicItem(message.getitemTemplate());
|
||||
Entity inWorldEntity = Globals.clientSceneWrapper.getEntityFromServerId(message.getentityId());
|
||||
if(inWorldEntity != null){
|
||||
//translate id
|
||||
Globals.clientSceneWrapper.mapIdToId(inWorldEntity.getId(), message.getentityId());
|
||||
|
||||
@ -4,7 +4,7 @@ package electrosphere.net.synchronization;
|
||||
import electrosphere.entity.state.movement.groundmove.ClientGroundMovementTree;
|
||||
|
||||
import electrosphere.entity.state.movement.groundmove.ServerGroundMovementTree;
|
||||
|
||||
import electrosphere.logger.LoggerInterface;
|
||||
import electrosphere.entity.state.equip.ClientEquipState;
|
||||
|
||||
import electrosphere.entity.state.attack.ClientAttackTree;
|
||||
@ -17,7 +17,7 @@ import electrosphere.entity.state.gravity.ServerGravityTree;
|
||||
|
||||
import electrosphere.entity.state.idle.ServerIdleTree;
|
||||
|
||||
import electrosphere.entity.state.idle.IdleTree;
|
||||
import electrosphere.entity.state.idle.ClientIdleTree;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
@ -49,7 +49,7 @@ public class ClientSynchronizationManager {
|
||||
public void processMessages(){
|
||||
List<SynchronizationMessage> messagesToClear = new LinkedList<SynchronizationMessage>();
|
||||
for(SynchronizationMessage message : messages){
|
||||
if(Globals.clientSceneWrapper.containsServerId(message.getentityId())){
|
||||
if(Globals.clientSceneWrapper.containsServerId(message.getentityId()) && Globals.clientSceneWrapper.getEntityFromServerId(message.getentityId()) != null){
|
||||
messagesToClear.add(message);
|
||||
switch(message.getMessageSubtype()){
|
||||
case UPDATECLIENTSTATE:{
|
||||
@ -74,6 +74,8 @@ public class ClientSynchronizationManager {
|
||||
int entityId = message.getentityId();
|
||||
} break;
|
||||
}
|
||||
} else if(Globals.clientSceneWrapper.getEntityFromServerId(message.getentityId()) == null){
|
||||
LoggerInterface.loggerNetworking.WARNING("Client received synchronization packet for entity that no longer exists on client!");
|
||||
}
|
||||
}
|
||||
for(SynchronizationMessage message : messagesToClear){
|
||||
@ -123,8 +125,8 @@ public class ClientSynchronizationManager {
|
||||
case BehaviorTreeIdEnums.BTREE_SERVERIDLE_ID: {
|
||||
switch(message.getfieldId()){
|
||||
case 9:{
|
||||
IdleTree tree = IdleTree.getIdleTree(entity);
|
||||
tree.setState(IdleTree.getIdleTreeStateShortAsEnum((short)message.getbTreeValue()));
|
||||
ClientIdleTree tree = ClientIdleTree.getIdleTree(entity);
|
||||
tree.setState(ClientIdleTree.getIdleTreeStateShortAsEnum((short)message.getbTreeValue()));
|
||||
} break;
|
||||
}
|
||||
} break;
|
||||
|
||||
@ -80,21 +80,8 @@ import org.lwjgl.opengl.GL15;
|
||||
import org.lwjgl.opengl.GL20;
|
||||
import org.lwjgl.opengl.GL30;
|
||||
|
||||
import electrosphere.collision.collidable.Collidable;
|
||||
import electrosphere.collision.hitbox.HitboxUtils;
|
||||
import electrosphere.engine.Globals;
|
||||
import electrosphere.entity.Entity;
|
||||
import electrosphere.entity.EntityDataStrings;
|
||||
import electrosphere.entity.EntityTags;
|
||||
import electrosphere.entity.EntityUtils;
|
||||
import electrosphere.entity.types.camera.CameraEntityUtils;
|
||||
import electrosphere.game.data.collidable.CollidableTemplate;
|
||||
import electrosphere.game.data.collidable.HitboxData;
|
||||
import electrosphere.logger.LoggerInterface;
|
||||
import electrosphere.renderer.RenderPipelineState.SelectedShaderEnum;
|
||||
import electrosphere.renderer.actor.Actor;
|
||||
import electrosphere.renderer.actor.instance.InstancedActor;
|
||||
import electrosphere.renderer.buffer.ShaderAttribute;
|
||||
import electrosphere.renderer.debug.DebugRendering;
|
||||
import electrosphere.renderer.framebuffer.Framebuffer;
|
||||
import electrosphere.renderer.framebuffer.FramebufferUtils;
|
||||
@ -104,6 +91,7 @@ import electrosphere.renderer.model.Model;
|
||||
import electrosphere.renderer.pipelines.CompositePipeline;
|
||||
import electrosphere.renderer.pipelines.DebugContentPipeline;
|
||||
import electrosphere.renderer.pipelines.FirstPersonItemsPipeline;
|
||||
import electrosphere.renderer.pipelines.ImGuiPipeline;
|
||||
import electrosphere.renderer.pipelines.MainContentNoOITPipeline;
|
||||
import electrosphere.renderer.pipelines.MainContentPipeline;
|
||||
import electrosphere.renderer.pipelines.NormalsForOutlinePipeline;
|
||||
@ -114,19 +102,6 @@ import electrosphere.renderer.pipelines.UIPipeline;
|
||||
import electrosphere.renderer.pipelines.VolumeBufferPipeline;
|
||||
import electrosphere.renderer.shader.ShaderProgram;
|
||||
import electrosphere.renderer.texture.Texture;
|
||||
import electrosphere.renderer.ui.elementtypes.DrawableElement;
|
||||
import electrosphere.renderer.ui.elementtypes.Element;
|
||||
import electrosphere.renderer.ui.imgui.ImGuiLinePlot;
|
||||
import electrosphere.renderer.ui.imgui.ImGuiWindow;
|
||||
import electrosphere.renderer.ui.imgui.ImGuiLinePlot.ImGuiLinePlotDataset;
|
||||
import electrosphere.server.pathfinding.navmesh.NavCube;
|
||||
import electrosphere.server.pathfinding.navmesh.NavMesh;
|
||||
import electrosphere.server.pathfinding.navmesh.NavShape;
|
||||
import imgui.ImGui;
|
||||
import imgui.extension.implot.ImPlot;
|
||||
import imgui.gl3.ImGuiImplGl3;
|
||||
import imgui.glfw.ImGuiImplGlfw;
|
||||
import imgui.internal.ImGuiContext;
|
||||
|
||||
public class RenderingEngine {
|
||||
|
||||
@ -145,20 +120,9 @@ public class RenderingEngine {
|
||||
|
||||
|
||||
|
||||
//
|
||||
//imgui related
|
||||
//
|
||||
//imgui internal objects
|
||||
private static final ImGuiImplGlfw imGuiGlfw = new ImGuiImplGlfw();
|
||||
private static final ImGuiImplGl3 imGuiGl13 = new ImGuiImplGl3();
|
||||
|
||||
//the version of glsl to init imgui with
|
||||
private static String glslVersion = null;
|
||||
//the context pointer for the core imgui objects
|
||||
private static ImGuiContext imGuiContext = null;
|
||||
//if set to true, will render imgui windows
|
||||
private static boolean imGuiShouldRender = true;
|
||||
//All imgui windows that should be displayed
|
||||
private static List<ImGuiWindow> imGuiWindows = new CopyOnWriteArrayList<ImGuiWindow>();
|
||||
|
||||
|
||||
|
||||
@ -253,6 +217,7 @@ public class RenderingEngine {
|
||||
CompositePipeline compositePipeline = new CompositePipeline();
|
||||
UIPipeline uiPipeline = new UIPipeline();
|
||||
RenderScreenPipeline renderScreenPipeline = new RenderScreenPipeline();
|
||||
ImGuiPipeline imGuiPipeline;
|
||||
|
||||
|
||||
public void createOpenglContext(){
|
||||
@ -321,11 +286,8 @@ public class RenderingEngine {
|
||||
//Creates the OpenGL capabilities for the program.
|
||||
GL.createCapabilities();
|
||||
|
||||
//init imgui (must happen after gl.createCapabilities)
|
||||
imGuiContext = ImGui.createContext();
|
||||
ImPlot.createContext();
|
||||
imGuiGlfw.init(Globals.window,true);
|
||||
imGuiGl13.init(glslVersion);
|
||||
//init imgui pipeline
|
||||
imGuiPipeline = new ImGuiPipeline(Globals.window, glslVersion);
|
||||
|
||||
//This enables Z-buffering so that farther-back polygons are not drawn over nearer ones
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
@ -534,22 +496,14 @@ public class RenderingEngine {
|
||||
/**
|
||||
* Render imgui
|
||||
*/
|
||||
if(imGuiShouldRender){
|
||||
imGuiGlfw.newFrame();
|
||||
ImGui.newFrame();
|
||||
for(ImGuiWindow window : imGuiWindows){
|
||||
window.draw();
|
||||
}
|
||||
ImGui.render();
|
||||
imGuiGl13.renderDrawData(ImGui.getDrawData());
|
||||
}
|
||||
imGuiPipeline.render(openGLState, renderPipelineState);
|
||||
|
||||
|
||||
//check for errors
|
||||
// checkError();
|
||||
|
||||
//check and call events and swap the buffers
|
||||
LoggerInterface.loggerRenderer.DEBUG("Swap buffers");
|
||||
LoggerInterface.loggerRenderer.DEBUG_LOOP("Swap buffers");
|
||||
glfwSwapBuffers(Globals.window);
|
||||
glfwPollEvents();
|
||||
}
|
||||
@ -613,19 +567,11 @@ public class RenderingEngine {
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a window to the rendering engine
|
||||
* @param window The window
|
||||
* Gets the imgui pipeline
|
||||
* @return The imgui pipeline
|
||||
*/
|
||||
public static void addImGuiWindow(ImGuiWindow window){
|
||||
imGuiWindows.add(window);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes an imgui window from the rendering engine
|
||||
* @param window The window
|
||||
*/
|
||||
public static void removeImGuiWindow(ImGuiWindow window){
|
||||
imGuiWindows.remove(window);
|
||||
public ImGuiPipeline getImGuiPipeline(){
|
||||
return this.imGuiPipeline;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -281,7 +281,7 @@ public class Actor {
|
||||
// model.updateNodeTransform();
|
||||
Bone currentBone = model.getBoneMap().get(boneName);
|
||||
if(currentBone != null){
|
||||
Vector4d result = currentBone.final_transform.transform(new Matrix4d(currentBone.inverseBindPoseMatrix).invert().transform(new Vector4d(rVal.x,rVal.y,rVal.z,1)));
|
||||
Vector4d result = new Matrix4d(currentBone.getFinalTransform()).transform(currentBone.getMOffset().invert().transform(new Vector4d(rVal.x,rVal.y,rVal.z,1)));
|
||||
// currentBone.inverseBindPoseMatrix
|
||||
rVal.x = (float)result.x;
|
||||
rVal.y = (float)result.y;
|
||||
@ -304,7 +304,7 @@ public class Actor {
|
||||
Bone currentBone = model.getBoneMap().get(boneName);
|
||||
if(currentBone != null){
|
||||
AxisAngle4f axisAngle = new AxisAngle4f();
|
||||
new Matrix4f(currentBone.final_transform).getRotation(axisAngle);
|
||||
new Matrix4f(currentBone.getFinalTransform()).getRotation(axisAngle);
|
||||
Quaterniond rotation = new Quaterniond(axisAngle);
|
||||
rVal.set(rotation);
|
||||
}
|
||||
@ -325,7 +325,7 @@ public class Actor {
|
||||
// model.updateNodeTransform();
|
||||
Bone currentBone = model.getBoneMap().get(boneName);
|
||||
if(currentBone != null){
|
||||
rVal = currentBone.final_transform;
|
||||
rVal = currentBone.getFinalTransform();
|
||||
// currentBone.inverseBindPoseMatrix
|
||||
}
|
||||
// }
|
||||
@ -333,6 +333,20 @@ public class Actor {
|
||||
return rVal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the list of all bones
|
||||
* @return the list of all bones
|
||||
*/
|
||||
public List<Bone> getBoneValues(){
|
||||
Model model = Globals.assetManager.fetchModel(modelPath);
|
||||
if(model != null){
|
||||
applyAnimationMasks(model);
|
||||
calculateNodeTransforms(model);
|
||||
return model.getBones();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean modelIsLoaded(){
|
||||
Model model = Globals.assetManager.fetchModel(modelPath);
|
||||
if(model != null){
|
||||
|
||||
@ -12,7 +12,7 @@ import org.lwjgl.assimp.AINode;
|
||||
*/
|
||||
public class AnimNode {
|
||||
public String id;
|
||||
public Matrix4d transform;
|
||||
private Matrix4d transform;
|
||||
public AnimNode parent;
|
||||
public List<AnimNode> children;
|
||||
public boolean is_bone;
|
||||
@ -25,4 +25,12 @@ public class AnimNode {
|
||||
is_bone = false;
|
||||
this.raw_data = raw_data;
|
||||
}
|
||||
|
||||
public Matrix4d getTransform(){
|
||||
return new Matrix4d(transform);
|
||||
}
|
||||
|
||||
public void setTransform(Matrix4d transform){
|
||||
this.transform = new Matrix4d(transform);
|
||||
}
|
||||
}
|
||||
|
||||
@ -25,7 +25,6 @@ import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import org.lwjgl.assimp.AIScene;
|
||||
import static org.lwjgl.assimp.Assimp.*;
|
||||
import static org.lwjgl.assimp.Assimp.aiImportFile;
|
||||
|
||||
public class ModelLoader {
|
||||
public static AIScene loadAIScene(String path){
|
||||
|
||||
@ -180,25 +180,26 @@ public class MeshLoader {
|
||||
if(mesh.mTextureCoords().capacity() > 0){
|
||||
AIVector3D.Buffer texturecoords = mesh.mTextureCoords(0);
|
||||
try {
|
||||
int textureCoordCount = mesh.mTextureCoords(0).capacity();
|
||||
FloatBuffer TextureArrayBufferData;
|
||||
if(textureCoordCount > 0){
|
||||
TextureArrayBufferData = BufferUtils.createFloatBuffer(textureCoordCount * 2);
|
||||
float[] temp = new float[2];
|
||||
for (int i = 0; i < textureCoordCount; i++) {
|
||||
AIVector3D normal = texturecoords.get(i);
|
||||
temp[0] = normal.x();
|
||||
temp[1] = normal.y();
|
||||
// temp[2] = normal.z();
|
||||
TextureArrayBufferData.put(temp);
|
||||
if(texturecoords != null){
|
||||
int textureCoordCount = texturecoords.capacity();
|
||||
FloatBuffer TextureArrayBufferData;
|
||||
if(textureCoordCount > 0){
|
||||
TextureArrayBufferData = BufferUtils.createFloatBuffer(textureCoordCount * 2);
|
||||
float[] temp = new float[2];
|
||||
for (int i = 0; i < textureCoordCount; i++) {
|
||||
AIVector3D normal = texturecoords.get(i);
|
||||
temp[0] = normal.x();
|
||||
temp[1] = normal.y();
|
||||
// temp[2] = normal.z();
|
||||
TextureArrayBufferData.put(temp);
|
||||
}
|
||||
TextureArrayBufferData.flip();
|
||||
rVal.bufferTextureCoords(TextureArrayBufferData, 2);
|
||||
}
|
||||
TextureArrayBufferData.flip();
|
||||
rVal.bufferTextureCoords(TextureArrayBufferData, 2);
|
||||
}
|
||||
} catch (NullPointerException ex){
|
||||
ex.printStackTrace();
|
||||
LoggerInterface.loggerRenderer.ERROR("Error reading texture coordinates", ex);
|
||||
}
|
||||
//System.out.println("Enabled texture coordinates");
|
||||
}
|
||||
|
||||
|
||||
@ -226,7 +227,7 @@ public class MeshLoader {
|
||||
// System.out.println("Num weights: " + currentBoneData.mNumWeights());
|
||||
Bone currentBone = new Bone(currentBoneData);
|
||||
currentBone.boneID = currentBoneData.mName().dataString();
|
||||
currentBone.inverseBindPoseMatrix = electrosphere.util.Utilities.convertAIMatrixd(currentBoneData.mOffsetMatrix());
|
||||
currentBone.setMOffset(electrosphere.util.Utilities.convertAIMatrixd(currentBoneData.mOffsetMatrix()));
|
||||
Iterator<AIVertexWeight> weightIterator = currentBoneData.mWeights().iterator();
|
||||
while(weightIterator.hasNext()){
|
||||
AIVertexWeight currentWeightData = weightIterator.next();
|
||||
|
||||
@ -11,25 +11,45 @@ import org.lwjgl.assimp.AIBone;
|
||||
* Keeps track of bone data
|
||||
*/
|
||||
public class Bone {
|
||||
|
||||
//the name of the bone
|
||||
public String boneID;
|
||||
|
||||
//the number of vertices affected by this bone
|
||||
int numWeights;
|
||||
|
||||
//The map of index of vertex to weight of this bone on that vertex
|
||||
Map<Integer,Float> weights = new HashMap<Integer,Float>();
|
||||
public Matrix4d inverseBindPoseMatrix;
|
||||
public Matrix4d deform;
|
||||
public Matrix4d transform;
|
||||
public Matrix4d final_transform;
|
||||
|
||||
//the mOffsetMatrix -- transforms from mesh space to bone space in bind pose
|
||||
private Matrix4d mOffsetMatrix;
|
||||
|
||||
//the current deform value of the bone
|
||||
private Matrix4d deform;
|
||||
|
||||
//the final transform that is used for drawing, data, etc
|
||||
private Matrix4d finalTransform;
|
||||
|
||||
//the raw data for the bone
|
||||
public AIBone raw_data;
|
||||
|
||||
/**
|
||||
* Cnostructor
|
||||
*/
|
||||
public Bone(){
|
||||
transform = new Matrix4d();
|
||||
deform = new Matrix4d();
|
||||
final_transform = new Matrix4d();
|
||||
finalTransform = new Matrix4d();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param raw_data The raw assimp data
|
||||
*/
|
||||
public Bone(AIBone raw_data){
|
||||
transform = new Matrix4d();
|
||||
deform = new Matrix4d();
|
||||
final_transform = new Matrix4d();
|
||||
finalTransform = new Matrix4d();
|
||||
boneID = raw_data.mName().dataString();
|
||||
inverseBindPoseMatrix = electrosphere.util.Utilities.convertAIMatrixd(raw_data.mOffsetMatrix());
|
||||
mOffsetMatrix = electrosphere.util.Utilities.convertAIMatrixd(raw_data.mOffsetMatrix());
|
||||
numWeights = raw_data.mNumWeights();
|
||||
this.raw_data = raw_data;
|
||||
}
|
||||
@ -49,4 +69,36 @@ public class Bone {
|
||||
public Map<Integer,Float> getWeights(){
|
||||
return weights;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the offset matrix for this bone
|
||||
* @return The offset matrix
|
||||
*/
|
||||
public Matrix4d getMOffset(){
|
||||
return new Matrix4d(mOffsetMatrix);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the offset matrix for this bone
|
||||
* @param mTransform the offset matrix
|
||||
*/
|
||||
public void setMOffset(Matrix4d mOffset){
|
||||
this.mOffsetMatrix = new Matrix4d(mOffset);
|
||||
}
|
||||
|
||||
public Matrix4d getDeform(){
|
||||
return new Matrix4d(deform);
|
||||
}
|
||||
|
||||
public void setDeform(Matrix4d deform){
|
||||
this.deform = new Matrix4d(deform);
|
||||
}
|
||||
|
||||
public Matrix4d getFinalTransform(){
|
||||
return new Matrix4d(finalTransform);
|
||||
}
|
||||
|
||||
public void setFinalTransform(Matrix4d finalTransform){
|
||||
this.finalTransform = new Matrix4d(finalTransform);
|
||||
}
|
||||
}
|
||||
|
||||
@ -29,6 +29,27 @@ import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL15;
|
||||
|
||||
import org.lwjgl.opengl.GL20;
|
||||
|
||||
import static org.lwjgl.opengl.GL11.GL_FLOAT;
|
||||
import static org.lwjgl.opengl.GL11.GL_INT;
|
||||
import static org.lwjgl.opengl.GL11.GL_TEXTURE_2D;
|
||||
import static org.lwjgl.opengl.GL11.GL_TRIANGLES;
|
||||
import static org.lwjgl.opengl.GL11.GL_UNSIGNED_INT;
|
||||
import static org.lwjgl.opengl.GL13.GL_TEXTURE3;
|
||||
import static org.lwjgl.opengl.GL15.GL_ARRAY_BUFFER;
|
||||
import static org.lwjgl.opengl.GL15.GL_ELEMENT_ARRAY_BUFFER;
|
||||
import static org.lwjgl.opengl.GL15.GL_STATIC_DRAW;
|
||||
import static org.lwjgl.opengl.GL15.glBindBuffer;
|
||||
import static org.lwjgl.opengl.GL15.glGenBuffers;
|
||||
import static org.lwjgl.opengl.GL20.glEnableVertexAttribArray;
|
||||
import static org.lwjgl.opengl.GL20.glGetUniformLocation;
|
||||
import static org.lwjgl.opengl.GL20.glUniform1f;
|
||||
import static org.lwjgl.opengl.GL20.glUniform1i;
|
||||
import static org.lwjgl.opengl.GL20.glUniform3fv;
|
||||
import static org.lwjgl.opengl.GL20.glUniformMatrix4fv;
|
||||
import static org.lwjgl.opengl.GL20.glVertexAttribPointer;
|
||||
import static org.lwjgl.opengl.GL30.glBindVertexArray;
|
||||
import static org.lwjgl.opengl.GL30.glGenVertexArrays;
|
||||
import static org.lwjgl.opengl.GL40.*;
|
||||
|
||||
import org.lwjgl.opengl.GL45;
|
||||
@ -418,7 +439,7 @@ public class Mesh {
|
||||
Bone currentBone = parent.getBoneMap().get(boneName);
|
||||
String currentUniform = "bones[" + incrementer + "]";
|
||||
if(currentBone != null){
|
||||
Matrix4d currentMat = new Matrix4d(currentBone.final_transform);
|
||||
Matrix4d currentMat = currentBone.getFinalTransform();
|
||||
// currentMat.get(bufferarray);
|
||||
// if(boneName.equals("Torso")){
|
||||
// System.out.println("Found torso bone");
|
||||
@ -430,7 +451,8 @@ public class Mesh {
|
||||
} else {
|
||||
// System.out.println("Bonename: " + boneName);
|
||||
// System.exit(1);
|
||||
GL45.glUniformMatrix4fv(glGetUniformLocation(openGLState.getActiveShader().getShaderId(), currentUniform), false, new float[16]);
|
||||
openGLState.getActiveShader().setUniform(glGetUniformLocation(openGLState.getActiveShader().getShaderId(), currentUniform), new float[16]);
|
||||
// GL45.glUniformMatrix4fv(glGetUniformLocation(openGLState.getActiveShader().getShaderId(), currentUniform), false, new float[16]);
|
||||
}
|
||||
incrementer++;
|
||||
}
|
||||
|
||||
@ -24,7 +24,6 @@ import org.lwjgl.PointerBuffer;
|
||||
import org.lwjgl.assimp.AIMaterial;
|
||||
import org.lwjgl.assimp.AIMesh;
|
||||
import org.lwjgl.assimp.AIScene;
|
||||
import org.lwjgl.assimp.Assimp;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
@ -48,6 +47,7 @@ public class Model {
|
||||
private Vector3d worldPos = new Vector3d();
|
||||
|
||||
//an optional global transform applied to the parent bone. Typically found in models loaded from files
|
||||
private Matrix4d rootTransform = new Matrix4d();
|
||||
private Matrix4d globalInverseTransform = new Matrix4d();
|
||||
|
||||
//the meshes in the model
|
||||
@ -104,7 +104,6 @@ public class Model {
|
||||
//
|
||||
//load meshes
|
||||
//
|
||||
int meshCount = s.mNumMeshes();
|
||||
PointerBuffer meshesBuffer = s.mMeshes();
|
||||
rVal.meshes = new ArrayList<Mesh>();
|
||||
while(meshesBuffer.hasRemaining()){
|
||||
@ -170,12 +169,15 @@ public class Model {
|
||||
//parse animation nodes and form hierarchy
|
||||
//
|
||||
AINode rootNode = s.mRootNode();
|
||||
rVal.globalInverseTransform = electrosphere.util.Utilities.convertAIMatrixd(rootNode.mTransformation());
|
||||
//The mOffsetMatrix, inverted, is the bind pose matrix that we want to apply at the top of all anims: https://github.com/assimp/assimp/issues/4364
|
||||
//This version of assimp doesn't support it, unfortunately
|
||||
rVal.rootTransform = electrosphere.util.Utilities.convertAIMatrixd(rootNode.mTransformation());
|
||||
if(globalTransform != null){
|
||||
rVal.globalInverseTransform.scale(globalTransform.getScale());
|
||||
rVal.globalInverseTransform = new Matrix4d(rVal.rootTransform).invert().scale(globalTransform.getScale());
|
||||
rVal.rootTransform.scale(globalTransform.getScale());
|
||||
}
|
||||
LoggerInterface.loggerRenderer.DEBUG("Global Inverse Transform");
|
||||
LoggerInterface.loggerRenderer.DEBUG(rVal.globalInverseTransform + "");
|
||||
LoggerInterface.loggerRenderer.DEBUG(rVal.rootTransform + "");
|
||||
rVal.rootAnimNode = rVal.buildAnimNodeMap(s.mRootNode(),null);
|
||||
//
|
||||
//load animations
|
||||
@ -233,10 +235,13 @@ public class Model {
|
||||
for(Mesh toDraw : meshMask.getToDrawMeshes()){
|
||||
toDraw.setBones(bones);
|
||||
toDraw.setParent(this);
|
||||
//set shader
|
||||
ShaderProgram original = toDraw.getShader();
|
||||
ShaderProgram shader = getCorrectShader(shaderMask, toDraw, toDraw.getShader());
|
||||
toDraw.setShader(shader);
|
||||
//draw
|
||||
toDraw.complexDraw(renderPipelineState, openGLState);
|
||||
//reset shader
|
||||
toDraw.setShader(original);
|
||||
}
|
||||
}
|
||||
@ -279,10 +284,11 @@ public class Model {
|
||||
if(currentBone != null){
|
||||
// System.out.println("Applying to bone");
|
||||
//T * S * R
|
||||
currentBone.deform = new Matrix4d();
|
||||
currentBone.deform.translate(currentChannel.getCurrentPosition());
|
||||
currentBone.deform.rotate(currentChannel.getCurrentRotation());
|
||||
currentBone.deform.scale(new Vector3d(currentChannel.getCurrentScale()));
|
||||
Matrix4d deform = new Matrix4d();
|
||||
deform.translate(currentChannel.getCurrentPosition());
|
||||
deform.rotate(currentChannel.getCurrentRotation());
|
||||
deform.scale(new Vector3d(currentChannel.getCurrentScale()));
|
||||
currentBone.setDeform(deform);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -302,6 +308,21 @@ public class Model {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs all animations for a given model including individual key values
|
||||
*/
|
||||
public void describeAllAnimationsFully(){
|
||||
if(animations.size() > 0){
|
||||
LoggerInterface.loggerRenderer.DEBUG("=====================");
|
||||
LoggerInterface.loggerRenderer.DEBUG(animations.size() + " animations available in model!");
|
||||
Iterator<Animation> animIterator = animations.iterator();
|
||||
while(animIterator.hasNext()){
|
||||
Animation currentAnim = animIterator.next();
|
||||
currentAnim.fullDescribeAnimation();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively builds the bone tree
|
||||
@ -332,6 +353,7 @@ public class Model {
|
||||
if(this.rootAnimNode != null){
|
||||
updateNodeTransform(this.rootAnimNode,boneRotators,staticMorph);
|
||||
}
|
||||
//if the model doesn't have bones, rootAnimNode won't be defined (think terrain)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -341,33 +363,35 @@ public class Model {
|
||||
* @param staticMorph The static morph to apply
|
||||
*/
|
||||
void updateNodeTransform(AnimNode n, Map<String,ActorBoneRotator> boneRotators, ActorStaticMorph staticMorph){
|
||||
Matrix4d parentTransform = new Matrix4d();
|
||||
if(n.parent != null){
|
||||
n.transform = new Matrix4d(n.parent.transform);
|
||||
} else {
|
||||
n.transform = new Matrix4d();
|
||||
parentTransform = new Matrix4d(n.parent.getTransform());
|
||||
}
|
||||
if(n.is_bone){
|
||||
//
|
||||
//bone rotators (turrets, hair, etc)
|
||||
Bone target_bone = boneMap.get(n.id);
|
||||
n.transform = n.transform.mul(target_bone.deform);
|
||||
Matrix4d currentTransform = parentTransform.mul(target_bone.getDeform());
|
||||
if(boneRotators.containsKey(target_bone.boneID)){
|
||||
n.transform.rotate(boneRotators.get(target_bone.boneID).getRotation());
|
||||
currentTransform.rotate(boneRotators.get(target_bone.boneID).getRotation());
|
||||
}
|
||||
//
|
||||
//static morph (changing nose size, eye distance, etc)
|
||||
Matrix4d bone_matrix = new Matrix4d(n.transform);
|
||||
if(staticMorph != null && staticMorph.getBoneTransforms(n.id) != null){
|
||||
bone_matrix.mul(staticMorph.getBoneTransforms(n.id).getTransform());
|
||||
n.transform.mul(staticMorph.getBoneTransforms(n.id).getTransform());
|
||||
currentTransform.mul(staticMorph.getBoneTransforms(n.id).getTransform());
|
||||
}
|
||||
|
||||
//
|
||||
Matrix4d bone_matrix = new Matrix4d(currentTransform);
|
||||
n.setTransform(currentTransform);
|
||||
//
|
||||
//Calculate final offset from initial bone
|
||||
bone_matrix.mul(target_bone.inverseBindPoseMatrix);
|
||||
//https://stackoverflow.com/a/59869381
|
||||
bone_matrix.mul(target_bone.getMOffset());
|
||||
bone_matrix = new Matrix4d(globalInverseTransform).mul(bone_matrix);
|
||||
target_bone.final_transform = bone_matrix;
|
||||
target_bone.setFinalTransform(bone_matrix);
|
||||
} else {
|
||||
n.transform = n.transform.mul(electrosphere.util.Utilities.convertAIMatrix(n.raw_data.mTransformation()));
|
||||
n.setTransform(parentTransform.mul(electrosphere.util.Utilities.convertAIMatrix(n.raw_data.mTransformation())));
|
||||
}
|
||||
Iterator<AnimNode> node_iterator = n.children.iterator();
|
||||
while(node_iterator.hasNext()){
|
||||
@ -571,4 +595,12 @@ public class Model {
|
||||
public void setBoundingSphere(Sphered boundingSphere){
|
||||
this.boundingSphere = boundingSphere;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the list of all animations
|
||||
* @return The list of all animations
|
||||
*/
|
||||
public List<Animation> getAnimations(){
|
||||
return this.animations;
|
||||
}
|
||||
}
|
||||
|
||||
@ -6,6 +6,7 @@ import org.joml.Quaternionf;
|
||||
import org.joml.Vector3d;
|
||||
import org.joml.Vector3f;
|
||||
import org.lwjgl.opengl.GL40;
|
||||
import org.ode4j.ode.DCapsule;
|
||||
import org.ode4j.ode.DGeom;
|
||||
import org.ode4j.ode.DSphere;
|
||||
|
||||
@ -15,19 +16,24 @@ import electrosphere.engine.Globals;
|
||||
import electrosphere.entity.Entity;
|
||||
import electrosphere.entity.EntityDataStrings;
|
||||
import electrosphere.entity.EntityUtils;
|
||||
import electrosphere.entity.state.hitbox.HitboxState;
|
||||
import electrosphere.entity.state.hitbox.HitboxCollectionState;
|
||||
import electrosphere.entity.state.hitbox.HitboxCollectionState.HitboxState;
|
||||
import electrosphere.entity.types.camera.CameraEntityUtils;
|
||||
import electrosphere.game.data.collidable.CollidableTemplate;
|
||||
import electrosphere.renderer.OpenGLState;
|
||||
import electrosphere.renderer.RenderPipelineState;
|
||||
import electrosphere.renderer.RenderingEngine;
|
||||
import electrosphere.renderer.model.Model;
|
||||
import electrosphere.renderer.texture.Texture;
|
||||
import electrosphere.server.datacell.Realm;
|
||||
import electrosphere.server.datacell.utils.EntityLookupUtils;
|
||||
import electrosphere.server.pathfinding.navmesh.NavCube;
|
||||
import electrosphere.server.pathfinding.navmesh.NavMesh;
|
||||
import electrosphere.server.pathfinding.navmesh.NavShape;
|
||||
|
||||
/**
|
||||
* Pipeline for rendering content to assist debugging
|
||||
*/
|
||||
public class DebugContentPipeline implements RenderPipeline {
|
||||
|
||||
@Override
|
||||
@ -53,7 +59,7 @@ public class DebugContentPipeline implements RenderPipeline {
|
||||
renderPipelineState.setUseMeshShader(true);
|
||||
renderPipelineState.setBufferStandardUniforms(true);
|
||||
renderPipelineState.setBufferNonStandardUniforms(false);
|
||||
renderPipelineState.setUseMaterial(true);
|
||||
renderPipelineState.setUseMaterial(false);
|
||||
renderPipelineState.setUseShadowMap(true);
|
||||
renderPipelineState.setUseBones(true);
|
||||
renderPipelineState.setUseLight(true);
|
||||
@ -62,12 +68,22 @@ public class DebugContentPipeline implements RenderPipeline {
|
||||
|
||||
if(Globals.userSettings.getGraphicsDebugDrawCollisionSpheresClient()){
|
||||
Model hitboxModel;
|
||||
for(HitboxState hitboxState : Globals.clientSceneWrapper.getHitboxManager().getAllHitboxes()){
|
||||
for(String boneName : hitboxState.getBones()){
|
||||
DGeom geom = hitboxState.getGeometry(boneName);
|
||||
for(HitboxCollectionState hitboxState : Globals.clientSceneWrapper.getHitboxManager().getAllHitboxes()){
|
||||
for(DGeom geom : hitboxState.getGeometries()){
|
||||
if(geom instanceof DSphere){
|
||||
DSphere sphereView = (DSphere)geom;
|
||||
HitboxState shapeStatus = hitboxState.getShapeStatus(geom);
|
||||
if((hitboxModel = Globals.assetManager.fetchModel("Models/basic/geometry/unitsphere.glb")) != null){
|
||||
//set color based on collision status, type, etc
|
||||
Texture texture = null;
|
||||
if(shapeStatus.getHadCollision()){
|
||||
texture = Globals.assetManager.fetchTexture("Textures/transparent_red.png");
|
||||
} else {
|
||||
texture = Globals.assetManager.fetchTexture("Textures/transparent_grey.png");
|
||||
}
|
||||
if(texture != null){
|
||||
texture.bind(openGLState);
|
||||
}
|
||||
Vector3d position = PhysicsUtils.odeVecToJomlVec(sphereView.getPosition());
|
||||
//calculate camera-modified vector3f
|
||||
Vector3f cameraModifiedPosition = new Vector3f((float)position.x,(float)position.y,(float)position.z).sub(CameraEntityUtils.getCameraCenter(Globals.playerCamera));
|
||||
@ -79,6 +95,32 @@ public class DebugContentPipeline implements RenderPipeline {
|
||||
hitboxModel.draw(renderPipelineState,openGLState);
|
||||
}
|
||||
}
|
||||
if(geom instanceof DCapsule){
|
||||
DCapsule capsuleView = (DCapsule)geom;
|
||||
HitboxState shapeStatus = hitboxState.getShapeStatus(geom);
|
||||
if((hitboxModel = Globals.assetManager.fetchModel("Models/basic/geometry/unitcapsule.glb")) != null){
|
||||
//set color based on collision status, type, etc
|
||||
Texture texture = null;
|
||||
if(shapeStatus.getHadCollision()){
|
||||
texture = Globals.assetManager.fetchTexture("Textures/transparent_red.png");
|
||||
} else {
|
||||
texture = Globals.assetManager.fetchTexture("Textures/transparent_grey.png");
|
||||
}
|
||||
if(texture != null){
|
||||
texture.bind(openGLState);
|
||||
}
|
||||
Vector3d position = PhysicsUtils.odeVecToJomlVec(capsuleView.getPosition());
|
||||
//calculate camera-modified vector3f
|
||||
Vector3f cameraModifiedPosition = new Vector3f((float)position.x,(float)position.y,(float)position.z).sub(CameraEntityUtils.getCameraCenter(Globals.playerCamera));
|
||||
modelTransformMatrix.identity();
|
||||
modelTransformMatrix.translate(cameraModifiedPosition);
|
||||
//since you're directly accessing the quat from the body, need to adjust it to be in the correct orientation
|
||||
modelTransformMatrix.rotate(PhysicsUtils.odeQuatToJomlQuat(capsuleView.getQuaternion()).mul(new Quaterniond(0.707,0,0,0.707)));
|
||||
modelTransformMatrix.scale(capsuleView.getRadius(),capsuleView.getLength(),capsuleView.getRadius());
|
||||
hitboxModel.setModelMatrix(modelTransformMatrix);
|
||||
hitboxModel.draw(renderPipelineState,openGLState);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// for(Entity currentHitbox : Globals.clientHitboxManager.getAllHitboxes()){
|
||||
@ -130,12 +172,22 @@ public class DebugContentPipeline implements RenderPipeline {
|
||||
int serverIdForClientEntity = Globals.clientSceneWrapper.mapClientToServerId(Globals.playerEntity.getId());
|
||||
Entity serverPlayerEntity = EntityLookupUtils.getEntityById(serverIdForClientEntity);
|
||||
Realm playerRealm = Globals.realmManager.getEntityRealm(serverPlayerEntity);
|
||||
for(HitboxState hitboxState : playerRealm.getHitboxManager().getAllHitboxes()){
|
||||
for(String boneName : hitboxState.getBones()){
|
||||
DGeom geom = hitboxState.getGeometry(boneName);
|
||||
for(HitboxCollectionState hitboxState : playerRealm.getHitboxManager().getAllHitboxes()){
|
||||
for(DGeom geom : hitboxState.getGeometries()){
|
||||
if(geom instanceof DSphere){
|
||||
DSphere sphereView = (DSphere)geom;
|
||||
HitboxState shapeStatus = hitboxState.getShapeStatus(geom);
|
||||
if((hitboxModel = Globals.assetManager.fetchModel("Models/basic/geometry/unitsphere.glb")) != null){
|
||||
//set color based on collision status, type, etc
|
||||
Texture texture = null;
|
||||
if(shapeStatus.getHadCollision()){
|
||||
texture = Globals.assetManager.fetchTexture("Textures/transparent_red.png");
|
||||
} else {
|
||||
texture = Globals.assetManager.fetchTexture("Textures/transparent_grey.png");
|
||||
}
|
||||
if(texture != null){
|
||||
texture.bind(openGLState);
|
||||
}
|
||||
Vector3d position = PhysicsUtils.odeVecToJomlVec(sphereView.getPosition());
|
||||
//calculate camera-modified vector3f
|
||||
Vector3f cameraModifiedPosition = new Vector3f((float)position.x,(float)position.y,(float)position.z).sub(CameraEntityUtils.getCameraCenter(Globals.playerCamera));
|
||||
@ -147,10 +199,39 @@ public class DebugContentPipeline implements RenderPipeline {
|
||||
hitboxModel.draw(renderPipelineState,openGLState);
|
||||
}
|
||||
}
|
||||
if(geom instanceof DCapsule){
|
||||
DCapsule capsuleView = (DCapsule)geom;
|
||||
HitboxState shapeStatus = hitboxState.getShapeStatus(geom);
|
||||
if((hitboxModel = Globals.assetManager.fetchModel("Models/basic/geometry/unitcapsule.glb")) != null){
|
||||
//set color based on collision status, type, etc
|
||||
Texture texture = null;
|
||||
if(shapeStatus.getHadCollision()){
|
||||
texture = Globals.assetManager.fetchTexture("Textures/transparent_red.png");
|
||||
} else {
|
||||
texture = Globals.assetManager.fetchTexture("Textures/transparent_grey.png");
|
||||
}
|
||||
if(texture != null){
|
||||
texture.bind(openGLState);
|
||||
}
|
||||
Vector3d position = PhysicsUtils.odeVecToJomlVec(capsuleView.getPosition());
|
||||
//calculate camera-modified vector3f
|
||||
Vector3f cameraModifiedPosition = new Vector3f((float)position.x,(float)position.y,(float)position.z).sub(CameraEntityUtils.getCameraCenter(Globals.playerCamera));
|
||||
modelTransformMatrix.identity();
|
||||
modelTransformMatrix.translate(cameraModifiedPosition);
|
||||
//since you're directly accessing the quat from the body, need to adjust it to be in the correct orientation
|
||||
modelTransformMatrix.rotate(PhysicsUtils.odeQuatToJomlQuat(capsuleView.getQuaternion()).mul(new Quaterniond(0.707,0,0,0.707)));
|
||||
modelTransformMatrix.scale(capsuleView.getRadius(),capsuleView.getLength(),capsuleView.getRadius());
|
||||
hitboxModel.setModelMatrix(modelTransformMatrix);
|
||||
hitboxModel.draw(renderPipelineState,openGLState);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//update pipeline state to use mats again
|
||||
renderPipelineState.setUseMaterial(true);
|
||||
|
||||
if(Globals.userSettings.graphicsDebugDrawPhysicsObjects()){
|
||||
Model physicsGraphicsModel;
|
||||
for(Collidable collidable : Globals.clientSceneWrapper.getCollisionEngine().getCollidables()){
|
||||
|
||||
@ -0,0 +1,97 @@
|
||||
package electrosphere.renderer.pipelines;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
import electrosphere.engine.Globals;
|
||||
import electrosphere.menu.debug.ImGuiWindowMacros;
|
||||
import electrosphere.renderer.OpenGLState;
|
||||
import electrosphere.renderer.RenderPipelineState;
|
||||
import electrosphere.renderer.ui.imgui.ImGuiWindow;
|
||||
import imgui.ImGui;
|
||||
import imgui.extension.implot.ImPlot;
|
||||
import imgui.gl3.ImGuiImplGl3;
|
||||
import imgui.glfw.ImGuiImplGlfw;
|
||||
import imgui.internal.ImGuiContext;
|
||||
|
||||
/**
|
||||
* ImGui rendering pipeline
|
||||
*/
|
||||
public class ImGuiPipeline implements RenderPipeline {
|
||||
|
||||
//
|
||||
//imgui related
|
||||
//
|
||||
//imgui internal objects
|
||||
private final ImGuiImplGlfw imGuiGlfw = new ImGuiImplGlfw();
|
||||
private final ImGuiImplGl3 imGuiGl13 = new ImGuiImplGl3();
|
||||
|
||||
//the context pointer for the core imgui objects
|
||||
private ImGuiContext imGuiContext = null;
|
||||
//if set to true, will render imgui windows
|
||||
private boolean imGuiShouldRender = true;
|
||||
//All imgui windows that should be displayed
|
||||
private List<ImGuiWindow> imGuiWindows = new CopyOnWriteArrayList<ImGuiWindow>();
|
||||
|
||||
/**
|
||||
* Constructor for the pipeline
|
||||
* @param windowId The glfw window id
|
||||
* @param glfwVersion the glfw version
|
||||
*/
|
||||
public ImGuiPipeline(long windowId, String glslVersion){
|
||||
//init imgui (must happen after gl.createCapabilities)
|
||||
imGuiContext = ImGui.createContext();
|
||||
ImPlot.createContext();
|
||||
imGuiGlfw.init(Globals.window,true);
|
||||
imGuiGl13.init(glslVersion);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(OpenGLState openGLState, RenderPipelineState renderPipelineState) {
|
||||
/**
|
||||
* Render imgui
|
||||
*/
|
||||
if(imGuiShouldRender){
|
||||
imGuiGlfw.newFrame();
|
||||
ImGui.newFrame();
|
||||
for(ImGuiWindow window : imGuiWindows){
|
||||
window.draw();
|
||||
}
|
||||
ImGui.render();
|
||||
imGuiGl13.renderDrawData(ImGui.getDrawData());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adds a n imgui window to the pipeline
|
||||
* @param window The window
|
||||
*/
|
||||
public void addImGuiWindow(ImGuiWindow window){
|
||||
imGuiWindows.add(window);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes an imgui window from the pipeline
|
||||
* @param window The window
|
||||
*/
|
||||
public void removeImGuiWindow(ImGuiWindow window){
|
||||
imGuiWindows.remove(window);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if an imgui window is open that should capture controls
|
||||
* @return true if there is a control-capturing window open, false otherwise
|
||||
*/
|
||||
public boolean shouldCaptureControls(){
|
||||
for(ImGuiWindow window : imGuiWindows){
|
||||
if(window == ImGuiWindowMacros.getMainDebugWindow() && window.isOpen()){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@ -10,6 +10,7 @@ import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
import org.joml.Vector2i;
|
||||
|
||||
import electrosphere.engine.Globals;
|
||||
import electrosphere.renderer.ui.elements.Window;
|
||||
import electrosphere.renderer.ui.elementtypes.ContainerElement;
|
||||
import electrosphere.renderer.ui.elementtypes.DraggableElement;
|
||||
@ -90,6 +91,17 @@ public class ElementManager {
|
||||
elementList.add(window);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to navigate-close the window at a window string
|
||||
* @param windowString The window string
|
||||
*/
|
||||
public void closeWindow(String windowString){
|
||||
Element windowEl = Globals.elementManager.getWindow(windowString);
|
||||
if(windowEl instanceof Window){
|
||||
((Window)windowEl).handleEvent(new NavigationEvent(NavigationEventType.BACKWARD));
|
||||
}
|
||||
}
|
||||
|
||||
List<FocusableElement> getFocusableList(Element topLevel, List<FocusableElement> input){
|
||||
if(topLevel instanceof FocusableElement){
|
||||
input.add((FocusableElement)topLevel);
|
||||
|
||||
@ -20,24 +20,30 @@ import electrosphere.renderer.ui.events.DragEvent.DragEventType;
|
||||
import electrosphere.renderer.ui.events.Event;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author amaterasu
|
||||
* A UI element that is a single, uninteractable image
|
||||
*/
|
||||
public class ImagePanel extends StandardElement implements DrawableElement, DraggableElement {
|
||||
|
||||
//Asset path for the model data that is used to draw the image panel
|
||||
public static String imagePanelModelPath;
|
||||
|
||||
//the path to the texture to use for this panel
|
||||
String texturePath;
|
||||
//the material that links the texture to draw
|
||||
Material customMat = new Material();
|
||||
//tracks whether the texture has been loaded or not
|
||||
boolean hasLoadedTexture = false;
|
||||
//the texture to use
|
||||
Texture texture = null;
|
||||
|
||||
|
||||
//rendering data for positioning the model
|
||||
Vector3f texPosition = new Vector3f(0,0,0);
|
||||
Vector3f texScale = new Vector3f(1,1,0);
|
||||
Vector3f boxPosition = new Vector3f();
|
||||
Vector3f boxDimensions = new Vector3f();
|
||||
|
||||
//callbacks for different events this can accept
|
||||
DragEventCallback onDragStart;
|
||||
DragEventCallback onDrag;
|
||||
DragEventCallback onDragRelease;
|
||||
@ -71,6 +77,15 @@ public class ImagePanel extends StandardElement implements DrawableElement, Drag
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
/**
|
||||
* Public constructor used for legacy usage
|
||||
* @param x
|
||||
* @param y
|
||||
* @param width
|
||||
* @param height
|
||||
* @param texturePath
|
||||
*/
|
||||
public ImagePanel(int x, int y, int width, int height, String texturePath){
|
||||
super();
|
||||
this.texturePath = texturePath;
|
||||
@ -91,10 +106,18 @@ public class ImagePanel extends StandardElement implements DrawableElement, Drag
|
||||
this.internalHeight = height;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the texture for this image panel
|
||||
* @param texture The texture to use
|
||||
*/
|
||||
public void setTexture(Texture texture){
|
||||
customMat.setTexturePointer(texture.getTexturePointer());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the texture being used by this image panel
|
||||
* @return The texture
|
||||
*/
|
||||
public Texture getTexture(){
|
||||
return texture;
|
||||
}
|
||||
@ -122,6 +145,8 @@ public class ImagePanel extends StandardElement implements DrawableElement, Drag
|
||||
Model planeModel = Globals.assetManager.fetchModel(Globals.imagePlaneModelID);
|
||||
if(texture != null){
|
||||
customMat.setTexturePointer(texture.getTexturePointer());
|
||||
} else if(this.texturePath != null){
|
||||
texture = Globals.assetManager.fetchTexture(this.texturePath);
|
||||
}
|
||||
|
||||
//this call binds the screen as the "texture" we're rendering to
|
||||
@ -145,16 +170,20 @@ public class ImagePanel extends StandardElement implements DrawableElement, Drag
|
||||
}
|
||||
}
|
||||
|
||||
//controls whether the image panel is visible or not
|
||||
public boolean visible = false;
|
||||
|
||||
@Override
|
||||
public boolean getVisible() {
|
||||
return visible;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setVisible(boolean draw) {
|
||||
this.visible = draw;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handleEvent(Event event){
|
||||
boolean propagate = true;
|
||||
if(event instanceof DragEvent){
|
||||
|
||||
@ -15,6 +15,7 @@ import electrosphere.entity.types.item.ItemUtils;
|
||||
import electrosphere.server.ai.AI;
|
||||
import electrosphere.server.datacell.Realm;
|
||||
import electrosphere.server.datacell.utils.DataCellSearchUtils;
|
||||
import electrosphere.util.MathUtils;
|
||||
|
||||
import org.joml.Vector3f;
|
||||
import org.joml.Quaterniond;
|
||||
@ -260,7 +261,7 @@ public class OpportunisticAttacker extends AI {
|
||||
Vector3d position = EntityUtils.getPosition(character);
|
||||
Vector3d targetPosition = EntityUtils.getPosition(target);
|
||||
Vector3d movementVector = new Vector3d(targetPosition).sub(position).normalize();
|
||||
Quaterniond movementQuaternion = new Quaterniond().rotationTo(new Vector3d(0,0,1), new Vector3d(movementVector.x,0,movementVector.z)).normalize();
|
||||
Quaterniond movementQuaternion = new Quaterniond().rotationTo(MathUtils.getOriginVector(), new Vector3d(movementVector.x,0,movementVector.z)).normalize();
|
||||
CreatureUtils.setFacingVector(character, movementVector);
|
||||
EntityUtils.getRotation(character).set(movementQuaternion);
|
||||
}
|
||||
|
||||
@ -9,15 +9,14 @@ import electrosphere.collision.collidable.Collidable;
|
||||
import electrosphere.engine.Globals;
|
||||
import electrosphere.entity.Entity;
|
||||
import electrosphere.entity.EntityUtils;
|
||||
import electrosphere.entity.state.hitbox.HitboxState;
|
||||
import electrosphere.entity.state.hitbox.HitboxState.HitboxShapeStatus;
|
||||
import electrosphere.entity.state.hitbox.HitboxState.HitboxType;
|
||||
import electrosphere.entity.state.hitbox.HitboxCollectionState;
|
||||
import electrosphere.entity.state.hitbox.HitboxCollectionState.HitboxState;
|
||||
import electrosphere.entity.state.hitbox.HitboxCollectionState.HitboxType;
|
||||
import electrosphere.entity.state.life.LifeUtils;
|
||||
import electrosphere.entity.state.movement.ProjectileTree;
|
||||
import electrosphere.entity.types.attach.AttachUtils;
|
||||
import electrosphere.entity.types.creature.CreatureUtils;
|
||||
import electrosphere.entity.types.item.ItemUtils;
|
||||
import electrosphere.server.datacell.Realm;
|
||||
|
||||
/**
|
||||
* Callback for managing collisions on the server
|
||||
@ -28,13 +27,12 @@ public class ServerHitboxResolutionCallback implements CollisionResolutionCallba
|
||||
public void resolve(DContactGeom contactGeom, Collidable impactor, Collidable receiver, Vector3d normal, Vector3d localPosition, Vector3d worldPos, float magnitude) {
|
||||
Entity impactorParent = impactor.getParent();
|
||||
Entity receiverParent = receiver.getParent();
|
||||
HitboxState impactorState = HitboxState.getHitboxState(impactorParent);
|
||||
HitboxState receiverState = HitboxState.getHitboxState(receiverParent);
|
||||
HitboxCollectionState impactorState = HitboxCollectionState.getHitboxState(impactorParent);
|
||||
HitboxCollectionState receiverState = HitboxCollectionState.getHitboxState(receiverParent);
|
||||
DGeom impactorGeom = contactGeom.g1;
|
||||
DGeom receiverGeom = contactGeom.g2;
|
||||
HitboxShapeStatus impactorShapeStatus = impactorState.getShapeStatus(impactorGeom);
|
||||
HitboxShapeStatus receiverShapeStatus = receiverState.getShapeStatus(receiverGeom);
|
||||
Realm receiverRealm = Globals.realmManager.getEntityRealm(receiverParent);
|
||||
HitboxState impactorShapeStatus = impactorState.getShapeStatus(impactorGeom);
|
||||
HitboxState receiverShapeStatus = receiverState.getShapeStatus(receiverGeom);
|
||||
|
||||
|
||||
//currently, impactor needs to be an item, and the receiver must not be an item
|
||||
@ -47,6 +45,13 @@ public class ServerHitboxResolutionCallback implements CollisionResolutionCallba
|
||||
;
|
||||
|
||||
|
||||
if(impactorShapeStatus != null){
|
||||
impactorShapeStatus.setHadCollision(true);
|
||||
}
|
||||
if(receiverShapeStatus != null){
|
||||
receiverShapeStatus.setHadCollision(true);
|
||||
}
|
||||
|
||||
if(isDamageEvent){
|
||||
//if the entity is attached to is an item, we need to compare with the parent of the item
|
||||
//to make sure you don't stab yourself for instance
|
||||
@ -58,6 +63,7 @@ public class ServerHitboxResolutionCallback implements CollisionResolutionCallba
|
||||
int damage = ItemUtils.getWeaponDataRaw(impactorParent).getDamage();
|
||||
LifeUtils.getLifeState(receiverParent).damage(damage);
|
||||
if(!LifeUtils.getLifeState(receiverParent).isIsAlive()){
|
||||
System.out.println("ServerHitboxResolutionCallback - Unimplemented!!");
|
||||
EntityUtils.getPosition(receiverParent).set(Globals.spawnPoint);
|
||||
LifeUtils.getLifeState(receiverParent).revive();
|
||||
}
|
||||
@ -75,6 +81,7 @@ public class ServerHitboxResolutionCallback implements CollisionResolutionCallba
|
||||
}
|
||||
LifeUtils.getLifeState(receiverParent).damage(damage);
|
||||
if(!LifeUtils.getLifeState(receiverParent).isIsAlive()){
|
||||
System.out.println("ServerHitboxResolutionCallback - Unimplemented!!");
|
||||
EntityUtils.getPosition(receiverParent).set(Globals.spawnPoint);
|
||||
LifeUtils.getLifeState(receiverParent).revive();
|
||||
}
|
||||
|
||||
@ -123,7 +123,7 @@ public class PoseActor {
|
||||
*/
|
||||
public void playAnimation(String animationName, int priority){
|
||||
PoseModel model = Globals.assetManager.fetchPoseModel(modelPath);
|
||||
if(model != null){
|
||||
if(model != null && model.getAnimation(animationName) != null){
|
||||
double length = model.getAnimation(animationName).duration;
|
||||
ActorAnimationMask animMask = new ActorAnimationMask(priority, animationName, 0, length);
|
||||
for(Bone bone : model.bones){
|
||||
@ -243,7 +243,7 @@ public class PoseActor {
|
||||
Bone currentBone = model.boneMap.get(boneName);
|
||||
if(currentBone != null){
|
||||
AxisAngle4f axisAngle = new AxisAngle4f();
|
||||
new Matrix4f(currentBone.final_transform).getRotation(axisAngle);
|
||||
new Matrix4f(currentBone.getFinalTransform()).getRotation(axisAngle);
|
||||
Quaterniond rotation = new Quaterniond(axisAngle);
|
||||
rVal.set(rotation);
|
||||
}
|
||||
@ -268,7 +268,7 @@ public class PoseActor {
|
||||
// model.updateNodeTransform();
|
||||
Bone currentBone = model.boneMap.get(boneName);
|
||||
if(currentBone != null){
|
||||
Vector4d result = currentBone.final_transform.transform(new Matrix4d(currentBone.inverseBindPoseMatrix).invert().transform(new Vector4d(rVal.x,rVal.y,rVal.z,1)));
|
||||
Vector4d result = new Matrix4d(currentBone.getFinalTransform()).transform(currentBone.getMOffset().invert().transform(new Vector4d(rVal.x,rVal.y,rVal.z,1)));
|
||||
// currentBone.inverseBindPoseMatrix
|
||||
rVal.x = (float)result.x;
|
||||
rVal.y = (float)result.y;
|
||||
|
||||
@ -7,7 +7,6 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.joml.Matrix4d;
|
||||
import org.joml.Matrix4f;
|
||||
import org.joml.Vector3d;
|
||||
import org.lwjgl.PointerBuffer;
|
||||
import org.lwjgl.assimp.AIAnimation;
|
||||
@ -119,10 +118,11 @@ public class PoseModel {
|
||||
if(currentBone != null){
|
||||
// System.out.println("Applying to bone");
|
||||
//T * S * R
|
||||
currentBone.deform = new Matrix4d();
|
||||
currentBone.deform.translate(currentChannel.getCurrentPosition());
|
||||
currentBone.deform.rotate(currentChannel.getCurrentRotation());
|
||||
currentBone.deform.scale(new Vector3d(currentChannel.getCurrentScale()));
|
||||
Matrix4d deform = new Matrix4d();
|
||||
deform.translate(currentChannel.getCurrentPosition());
|
||||
deform.rotate(currentChannel.getCurrentRotation());
|
||||
deform.scale(new Vector3d(currentChannel.getCurrentScale()));
|
||||
currentBone.setDeform(deform);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -168,29 +168,31 @@ public class PoseModel {
|
||||
*/
|
||||
void updateNodeTransform(AnimNode n, Map<String,ActorBoneRotator> boneRotators, ActorStaticMorph staticMorph){
|
||||
//grab parent transform if exists
|
||||
Matrix4d parentTransform = new Matrix4d();
|
||||
if(n.parent != null){
|
||||
n.transform = new Matrix4d(n.parent.transform);
|
||||
} else {
|
||||
n.transform = new Matrix4d();
|
||||
parentTransform = new Matrix4d(n.parent.getTransform());
|
||||
}
|
||||
//if this is a bone, calculate the transform for the bone
|
||||
if(n.is_bone){
|
||||
Bone target_bone = boneMap.get(n.id);
|
||||
n.transform = n.transform.mul(target_bone.deform);
|
||||
Matrix4d deformTransform = parentTransform.mul(target_bone.getDeform());
|
||||
if(boneRotators.containsKey(target_bone.boneID)){
|
||||
n.transform.rotate(boneRotators.get(target_bone.boneID).getRotation());
|
||||
deformTransform.rotate(boneRotators.get(target_bone.boneID).getRotation());
|
||||
}
|
||||
Matrix4d bone_matrix = new Matrix4d(n.transform);
|
||||
Matrix4d bone_matrix = new Matrix4d(deformTransform);
|
||||
if(staticMorph != null && staticMorph.getBoneTransforms(n.id) != null){
|
||||
bone_matrix.mul(staticMorph.getBoneTransforms(n.id).getTransform());
|
||||
n.transform.mul(staticMorph.getBoneTransforms(n.id).getTransform());
|
||||
}
|
||||
bone_matrix.mul(target_bone.inverseBindPoseMatrix);
|
||||
n.setTransform(deformTransform);
|
||||
//
|
||||
//Calculate final offset from initial bone
|
||||
//https://stackoverflow.com/a/59869381
|
||||
bone_matrix.mul(target_bone.getMOffset());
|
||||
bone_matrix = new Matrix4d(globalInverseTransform).mul(bone_matrix);
|
||||
target_bone.final_transform = bone_matrix;
|
||||
target_bone.setFinalTransform(bone_matrix);
|
||||
} else {
|
||||
//not a bone, so use transform directly from data
|
||||
n.transform = n.transform.mul(electrosphere.util.Utilities.convertAIMatrix(n.raw_data.mTransformation()));
|
||||
n.setTransform(parentTransform.mul(electrosphere.util.Utilities.convertAIMatrix(n.raw_data.mTransformation())));
|
||||
}
|
||||
//update all children accordingly
|
||||
Iterator<AnimNode> node_iterator = n.children.iterator();
|
||||
|
||||
41
src/main/java/electrosphere/util/MathUtils.java
Normal file
41
src/main/java/electrosphere/util/MathUtils.java
Normal file
@ -0,0 +1,41 @@
|
||||
package electrosphere.util;
|
||||
|
||||
import org.joml.Quaterniond;
|
||||
import org.joml.Vector3d;
|
||||
import org.joml.Vector3f;
|
||||
|
||||
/**
|
||||
* Utility functions for doing math
|
||||
*/
|
||||
public class MathUtils {
|
||||
|
||||
|
||||
/**
|
||||
* Gets the origin vector of the engine
|
||||
* @return The origin vector
|
||||
*/
|
||||
public static Vector3d getOriginVector(){
|
||||
return new Vector3d(0,0,1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the origin vector of the engine, in Vector3f format
|
||||
* @return The origin vector
|
||||
*/
|
||||
public static Vector3f getOriginVectorf(){
|
||||
return new Vector3f(0,0,1);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Calculates the quaternion that rotates the origin vector to point from origin to destination
|
||||
* @param originPoint The point to begin at
|
||||
* @param destinationPoint The point end at
|
||||
* @return The quaternion
|
||||
*/
|
||||
public static Quaterniond calculateRotationFromPointToPoint(Vector3d originPoint, Vector3d destinationPoint){
|
||||
return getOriginVector().rotationTo(new Vector3d(originPoint).sub(destinationPoint).normalize(), new Quaterniond());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user