UI work for level editor
All checks were successful
studiorailgun/Renderer/pipeline/head This commit looks good

This commit is contained in:
austin 2024-04-13 14:15:04 -04:00
parent 3e5cade90e
commit 34403c3155
8 changed files with 225 additions and 73 deletions

View File

@ -215,6 +215,10 @@ UI Work
Terrain editing UI
- Menu to select palette to generate, populated based on data
(04/13/2024)
UI Work
- Level editor ability to destroy an entity on server, have it also destroy on client, AND not persist on save
# TODO
More Debug menus
@ -258,6 +262,8 @@ Build a lod system
- LOD trees aggressively
- LOD foliage cells aggressively
Refactor attach logic to better encapsulate semantic attachment
Light Manager
- Creates and manages light entities
- Uses priority queue mechanism like foliage manager to only draw the most important lights

View File

@ -522,16 +522,6 @@ public class CollisionEngine {
spaceLock.release();
}
public void deregisterRigidBody(DBody body){
if(bodies.contains(body)){
bodies.remove(body);
}
if((body) != null){
body.destroy();
// world.removeRigidBody(body);
}
}
public void destroyEntityThatHasPhysics(Entity e){
//make uncollidable
if(e.containsKey(EntityDataStrings.PHYSICS_COLLISION_BODY)){

View File

@ -4,6 +4,7 @@ import org.joml.Vector3d;
import electrosphere.engine.Globals;
import electrosphere.entity.types.collision.CollisionObjUtils;
import electrosphere.net.parser.net.message.EntityMessage;
import electrosphere.server.datacell.Realm;
import electrosphere.server.datacell.ServerDataCell;
import electrosphere.server.datacell.utils.DataCellSearchUtils;
@ -74,4 +75,20 @@ public class ServerEntityUtils {
CollisionObjUtils.serverPositionCharacter(entity, position);
}
/**
* Destroys an entity on the server
* @param entity the entity to destroy
*/
public static void destroyEntity(Entity entity){
ServerDataCell cell = DataCellSearchUtils.getEntityDataCell(entity);
Realm realm = Globals.realmManager.getEntityRealm(entity);
if(cell != null){
cell.broadcastNetworkMessage(EntityMessage.constructDestroyMessage(entity.getId()));
//if the entity had physics, remove them from the world
realm.getCollisionEngine().destroyEntityThatHasPhysics(entity);
}
EntityUtils.cleanUpEntity(entity);
}
}

View File

@ -21,6 +21,9 @@ public class LoggerInterface {
public static Logger loggerAudio;
public static Logger loggerUI;
/**
* Initializes all logic objects
*/
public static void initLoggers(){
loggerStartup = new Logger(LogLevel.WARNING);
loggerNetworking = new Logger(LogLevel.WARNING);
@ -31,7 +34,7 @@ public class LoggerInterface {
loggerAuth = new Logger(LogLevel.WARNING);
loggerDB = new Logger(LogLevel.WARNING);
loggerAudio = new Logger(LogLevel.WARNING);
loggerUI = new Logger(LogLevel.DEBUG);
loggerUI = new Logger(LogLevel.WARNING);
loggerStartup.INFO("Initialized loggers");
}
}

View File

@ -6,15 +6,21 @@ import org.joml.Vector3d;
import org.lwjgl.util.yoga.Yoga;
import electrosphere.engine.Globals;
import electrosphere.entity.Entity;
import electrosphere.entity.ServerEntityUtils;
import electrosphere.entity.types.camera.CameraEntityUtils;
import electrosphere.entity.types.creature.CreatureUtils;
import electrosphere.entity.types.foliage.FoliageUtils;
import electrosphere.entity.types.item.ItemUtils;
import electrosphere.entity.types.object.ObjectUtils;
import electrosphere.game.data.creature.type.CreatureType;
import electrosphere.game.data.foliage.type.FoliageType;
import electrosphere.logger.LoggerInterface;
import electrosphere.menu.WindowStrings;
import electrosphere.menu.WindowUtils;
import electrosphere.renderer.ui.elements.Button;
import electrosphere.renderer.ui.elements.Div;
import electrosphere.renderer.ui.elements.Label;
import electrosphere.renderer.ui.elements.VirtualScrollable;
import electrosphere.renderer.ui.elements.Window;
import electrosphere.renderer.ui.elementtypes.ClickableElement.ClickEventCallback;
@ -22,35 +28,38 @@ import electrosphere.renderer.ui.elementtypes.NavigableElement.NavigationEventCa
import electrosphere.renderer.ui.events.ClickEvent;
import electrosphere.renderer.ui.events.NavigationEvent;
import electrosphere.server.datacell.Realm;
import electrosphere.server.datacell.utils.EntityLookupUtils;
/**
* Menu generators for level editor
*/
public class MenuGeneratorsLevelEditor {
static Window rVal;
//
//side panel
static Window mainSidePanel;
//width of the side panel
static final int SIDE_PANEL_WIDTH = 500;
/**
* Creates the level editor side panel top view
* @return
*/
public static Window createLevelEditorSidePanel(){
//setup window
rVal = new Window(0,0,SIDE_PANEL_WIDTH,Globals.WINDOW_HEIGHT,true);
rVal.setParentAlignContent(Yoga.YGAlignFlexEnd);
rVal.setParentJustifyContent(Yoga.YGJustifyFlexEnd);
rVal.setParentAlignItem(Yoga.YGAlignFlexEnd);
rVal.setAlignContent(Yoga.YGAlignFlexStart);
rVal.setAlignItems(Yoga.YGAlignFlexStart);
rVal.setJustifyContent(Yoga.YGJustifyFlexStart);
mainSidePanel = new Window(0,0,SIDE_PANEL_WIDTH,Globals.WINDOW_HEIGHT,true);
mainSidePanel.setParentAlignContent(Yoga.YGAlignFlexEnd);
mainSidePanel.setParentJustifyContent(Yoga.YGJustifyFlexEnd);
mainSidePanel.setParentAlignItem(Yoga.YGAlignFlexEnd);
mainSidePanel.setAlignContent(Yoga.YGAlignFlexStart);
mainSidePanel.setAlignItems(Yoga.YGAlignFlexStart);
mainSidePanel.setJustifyContent(Yoga.YGJustifyFlexStart);
//scrollable
VirtualScrollable scrollable = new VirtualScrollable(SIDE_PANEL_WIDTH, Globals.WINDOW_HEIGHT);
rVal.addChild(scrollable);
rVal.setOnNavigationCallback(new NavigationEventCallback() {public boolean execute(NavigationEvent event){
mainSidePanel.addChild(scrollable);
mainSidePanel.setOnNavigationCallback(new NavigationEventCallback() {public boolean execute(NavigationEvent event){
WindowUtils.closeWindow(WindowStrings.LEVEL_EDTIOR_SIDE_PANEL);
return false;
}});
@ -58,9 +67,9 @@ public class MenuGeneratorsLevelEditor {
fillInDefaultContent(scrollable);
rVal.applyYoga();
mainSidePanel.applyYoga();
return rVal;
return mainSidePanel;
}
/**
@ -95,7 +104,13 @@ public class MenuGeneratorsLevelEditor {
return false;
}}));
rVal.applyYoga();
//entity tree view
scrollable.addChild(Button.createButton("View Entity Tree", new ClickEventCallback() {public boolean execute(ClickEvent event){
fillInEntityTreeContent(scrollable);
return false;
}}));
mainSidePanel.applyYoga();
}
@ -127,7 +142,7 @@ public class MenuGeneratorsLevelEditor {
}}));
}
rVal.applyYoga();
mainSidePanel.applyYoga();
}
private static void fillInSpawnFoliageContent(VirtualScrollable scrollable){
@ -153,7 +168,79 @@ public class MenuGeneratorsLevelEditor {
}}));
}
rVal.applyYoga();
mainSidePanel.applyYoga();
}
/**
* Creates tree view of entities in server
* @param scrollable
*/
private static void fillInEntityTreeContent(VirtualScrollable scrollable){
scrollable.clearChildren();
//back button
scrollable.addChild(Button.createButton("Close", new ClickEventCallback() {public boolean execute(ClickEvent event){
fillInDefaultContent(scrollable);
return false;
}}));
//elements for the entity
for(Entity entity : EntityLookupUtils.getAllEntities()){
if(
CreatureUtils.isCreature(entity) ||
ItemUtils.isItem(entity) ||
ObjectUtils.isObject(entity) ||
FoliageUtils.isFoliage(entity)
){
Div div = new Div();
div.setFlexDirection(Yoga.YGFlexDirectionRow);
div.setMaxHeight(30);
div.setMarginBottom(5);
div.setMarginLeft(5);
div.setMarginRight(5);
div.setMarginTop(5);
//delete button
Button deleteButton = Button.createButton("X", new ClickEventCallback() {public boolean execute(ClickEvent event){
LoggerInterface.loggerEngine.INFO("Delete " + entity.getId());
ServerEntityUtils.destroyEntity(entity);
return false;
}});
deleteButton.setMarginRight(5);
deleteButton.setMarginLeft(5);
div.addChild(deleteButton);
Label entityName = new Label(1.0f);
entityName.setText("(" + entity.getId() + ") " + getEntityString(entity));
div.addChild(entityName);
scrollable.addChild(div);
}
}
mainSidePanel.applyYoga();
}
/**
* Gets the string to display for this entity in the entity tree view
* @param e the entity
* @return the string to display
*/
private static String getEntityString(Entity e){
if(CreatureUtils.isCreature(e)){
return "Object - " + CreatureUtils.getType(e);
} else if(ItemUtils.isItem(e)){
return "Object - " + ItemUtils.getType(e);
} else if(FoliageUtils.isFoliage(e)){
return "Object - " + FoliageUtils.getFoliageType(e).getName();
} else if(ObjectUtils.isObject(e)){
return "Object - " + ObjectUtils.getType(e);
}
return "Entity Unknown Type";
}
}

View File

@ -1,11 +1,9 @@
package electrosphere.net.client.protocol;
import org.joml.Quaterniond;
import org.joml.Quaternionf;
import org.joml.Vector3d;
import electrosphere.engine.Globals;
import electrosphere.engine.Main;
import electrosphere.entity.ClientEntityUtils;
import electrosphere.entity.Entity;
import electrosphere.entity.EntityUtils;
@ -18,15 +16,32 @@ import electrosphere.logger.LoggerInterface;
import electrosphere.net.parser.net.message.EntityMessage;
import electrosphere.util.Utilities;
/**
* Client entity network protocol
*/
public class EntityProtocol {
/**
* Handles a single clientbound entity message
* @param message The message to handle
*/
protected static void handleEntityMessage(EntityMessage message){
Globals.profiler.beginCpuSample("EntityProtocol.handleEntityMessage");
LoggerInterface.loggerNetworking.DEBUG("Parse entity message of type " + message.getMessageSubtype());
Entity newlySpawnedEntity;
switch(message.getMessageSubtype()){
//
//
// SPAWNING STUFF IN
//
//
case CREATE:
LoggerInterface.loggerNetworking.DEBUG("Spawn ID " + message.getentityID() + " of type " + message.getentityCategory() + " subtype " + message.getentitySubtype());
LoggerInterface.loggerNetworking.DEBUG(
"Spawn ID " + message.getentityID() + " of type " + message.getentityCategory() + " subtype " + message.getentitySubtype() +
" @ " + message.getpositionX() + " " + message.getpositionY() + " " + message.getpositionZ()
);
switch(message.getentityCategory()){
case 0:
// newlySpawnedEntity = CreatureUtils.spawnBasicCreature(message.getentitySubtype());
@ -42,14 +57,14 @@ public class EntityProtocol {
break;
}
break;
case SPAWNCREATURE:
case SPAWNCREATURE: {
LoggerInterface.loggerNetworking.DEBUG("Spawn Creature " + message.getentityID() + " at " + message.getpositionX() + " " + message.getpositionY() + " " + message.getpositionZ());
CreatureTemplate template = Utilities.deserialize(message.getcreatureTemplate(), CreatureTemplate.class);
newlySpawnedEntity = CreatureUtils.clientSpawnBasicCreature(template.getCreatureType(),template);
ClientEntityUtils.initiallyPositionEntity(newlySpawnedEntity, new Vector3d(message.getpositionX(),message.getpositionY(),message.getpositionZ()));
Globals.clientSceneWrapper.mapIdToId(newlySpawnedEntity.getId(), message.getentityID());
break;
case SPAWNITEM:
} break;
case SPAWNITEM: {
if(!Globals.RUN_SERVER){
LoggerInterface.loggerNetworking.DEBUG("Spawn Item " + message.getentityID() + " at " + message.getpositionX() + " " + message.getpositionY() + " " + message.getpositionZ());
//spawn item
@ -59,26 +74,29 @@ public class EntityProtocol {
ClientEntityUtils.initiallyPositionEntity(newlySpawnedEntity, new Vector3d(message.getpositionX(),message.getpositionY(),message.getpositionZ()));
Globals.clientSceneWrapper.mapIdToId(newlySpawnedEntity.getId(), message.getentityID());
}
break;
case DESTROY:
//only obey if we're not also the server
if(!Globals.RUN_SERVER){
EntityUtils.cleanUpEntity(Globals.clientSceneWrapper.getEntityFromServerId(message.getentityID()));
} break;
case SPAWNFOLIAGESEED: {
LoggerInterface.loggerNetworking.DEBUG("Spawn foliage " + message.getentityID() + " at " + message.getpositionX() + " " + message.getpositionY() + " " + message.getpositionZ());
String type = message.getcreatureTemplate();
newlySpawnedEntity = FoliageUtils.spawnBasicFoliage(type,message.getfoliageSeed());
ClientEntityUtils.initiallyPositionEntity(newlySpawnedEntity, new Vector3d(message.getpositionX(),message.getpositionY(),message.getpositionZ()));
Globals.clientSceneWrapper.mapIdToId(newlySpawnedEntity.getId(), message.getentityID());
} break;
//
//
// UPDATING PROPERTIES
//
//
case MOVE: {
Entity target = Globals.clientSceneWrapper.getEntityFromServerId(message.getentityID());
LoggerInterface.loggerNetworking.DEBUG("ID: " + message.getentityID());
if(target != null){
EntityUtils.getPosition(target).set(message.getpositionX(),message.getpositionY(),message.getpositionZ());
}
break;
case MOVE:
//literally just adding this to scope so I can use `` Entity target; `` again
if(message.getentityID() != -1){
Entity target = Globals.clientSceneWrapper.getEntityFromServerId(message.getentityID());
LoggerInterface.loggerNetworking.DEBUG("ID: " + message.getentityID());
if(target != null){
EntityUtils.getPosition(target).set(message.getpositionX(),message.getpositionY(),message.getpositionZ());
}
}
// CreatureUtils.attachEntityMessageToMovementTree(Globals.entityManager.getEntityFromId(message.getId()),message);
break;
case SETBEHAVIORTREE:
break;
} break;
case SETPROPERTY: {
if(Globals.clientSceneWrapper.serverToClientMapContainsId(message.getentityID())){
if(message.getpropertyType() == 0){
@ -95,33 +113,51 @@ public class EntityProtocol {
//TODO: bounce message
}
} break;
case ATTACHENTITYTOENTITY:
case ATTACHENTITYTOENTITY: {
Entity child = Globals.clientSceneWrapper.getEntityFromServerId(message.getentityID());
Entity parent = Globals.clientSceneWrapper.getEntityFromServerId(message.gettargetID());
LoggerInterface.loggerNetworking.DEBUG("Attach " + message.getentityID() + " to " + message.gettargetID() + " on bone " + message.getbone());
if(child != null && parent != null){
AttachUtils.clientAttachEntityToEntityAtBone(parent, child, message.getbone(), new Quaterniond());
}
break;
case MOVEUPDATE:
CreatureUtils.clientAttachEntityMessageToMovementTree(Globals.clientSceneWrapper.getEntityFromServerId(message.getentityID()),message);
break;
case ATTACKUPDATE:
CreatureUtils.attachEntityMessageToAttackTree(Globals.clientSceneWrapper.getEntityFromServerId(message.getentityID()),message);
break;
case KILL:
break;
case SETPOSITION:
break;
case SETFACING:
break;
case SPAWNFOLIAGESEED: {
LoggerInterface.loggerNetworking.DEBUG("Spawn foliage " + message.getentityID() + " at " + message.getpositionX() + " " + message.getpositionY() + " " + message.getpositionZ());
String type = message.getcreatureTemplate();
newlySpawnedEntity = FoliageUtils.spawnBasicFoliage(type,message.getfoliageSeed());
ClientEntityUtils.initiallyPositionEntity(newlySpawnedEntity, new Vector3d(message.getpositionX(),message.getpositionY(),message.getpositionZ()));
Globals.clientSceneWrapper.mapIdToId(newlySpawnedEntity.getId(), message.getentityID());
} break;
case MOVEUPDATE: {
CreatureUtils.clientAttachEntityMessageToMovementTree(Globals.clientSceneWrapper.getEntityFromServerId(message.getentityID()),message);
} break;
case ATTACKUPDATE: {
CreatureUtils.attachEntityMessageToAttackTree(Globals.clientSceneWrapper.getEntityFromServerId(message.getentityID()),message);
} break;
//
//
// DESTROYING AND DESTRUCTING STUFF
//
//
case DESTROY: {
EntityUtils.cleanUpEntity(Globals.clientSceneWrapper.getEntityFromServerId(message.getentityID()));
} break;
//
//
// TODO
//
//
case KILL:
case SETPOSITION:
case SETFACING:
//to be implemented
throw new UnsupportedOperationException();
case SETBEHAVIORTREE:
case SETBTREEPROPERTYDOUBLE:
case SETBTREEPROPERTYENUM:
case SETBTREEPROPERTYFLOAT:
case SETBTREEPROPERTYINT:
case SETBTREEPROPERTYSTRING:
//unused
break;
}
Globals.profiler.endCpuSample();
}

View File

@ -101,9 +101,12 @@ public class PhysicsDataCell {
// realm.getCollisionEngine().registerPhysicsEntity(physicsEntity);
}
/**
* Destroys the physics for this data cell
*/
public void destroyPhysics(){
Realm realm = Globals.realmManager.getEntityRealm(physicsEntity);
realm.getCollisionEngine().deregisterRigidBody((DBody)physicsObject);
realm.getCollisionEngine().destroyEntityThatHasPhysics(physicsEntity);
}
/**

View File

@ -1,5 +1,6 @@
package electrosphere.server.datacell.utils;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
@ -47,5 +48,14 @@ public class EntityLookupUtils {
public static boolean isServerEntity(Entity entity){
return idToEntityMap.containsKey(entity.getId());
}
/**
* !!!DANGER!!! USE IN DEBUG/LEVEL EDITOR ONLY
* Gets all entities tracked by the entity lookup utils
* @return The collection of all server entities
*/
public static Collection<Entity> getAllEntities(){
return idToEntityMap.values();
}
}