diff --git a/assets/Shaders/plane/plane.fs b/assets/Shaders/plane/plane.fs index d1039d55..6a4c29c7 100644 --- a/assets/Shaders/plane/plane.fs +++ b/assets/Shaders/plane/plane.fs @@ -4,9 +4,13 @@ out vec4 FragColor; in vec2 TexCoords; uniform sampler2D screenTexture; +uniform vec3 color; void main(){ vec4 textureColor = texture(screenTexture, TexCoords); + textureColor.r = textureColor.r * color.r; + textureColor.g = textureColor.g * color.g; + textureColor.b = textureColor.b * color.b; if(textureColor.a < 0.1){ discard; } diff --git a/assets/Textures/ui/circle.png b/assets/Textures/ui/circle.png new file mode 100644 index 00000000..c1ca9f0e Binary files /dev/null and b/assets/Textures/ui/circle.png differ diff --git a/assets/Textures/ui/square.png b/assets/Textures/ui/square.png new file mode 100644 index 00000000..850c058f Binary files /dev/null and b/assets/Textures/ui/square.png differ diff --git a/buildNumber.properties b/buildNumber.properties index 7aaf1369..29e3a345 100644 --- a/buildNumber.properties +++ b/buildNumber.properties @@ -1,3 +1,3 @@ #maven.buildNumber.plugin properties file -#Fri Jul 12 17:55:57 EDT 2024 -buildNumber=183 +#Sat Jul 13 22:48:57 EDT 2024 +buildNumber=185 diff --git a/src/main/java/electrosphere/engine/Globals.java b/src/main/java/electrosphere/engine/Globals.java index e7a7ccae..8645f882 100644 --- a/src/main/java/electrosphere/engine/Globals.java +++ b/src/main/java/electrosphere/engine/Globals.java @@ -40,7 +40,6 @@ import electrosphere.game.config.UserSettings; import electrosphere.game.data.voxel.VoxelType; import electrosphere.game.server.structure.virtual.StructureManager; import electrosphere.game.server.world.MacroData; -import electrosphere.game.server.world.ServerWorldData; import electrosphere.logger.LoggerInterface; import electrosphere.menu.WindowUtils; import electrosphere.net.client.ClientNetworking; @@ -66,16 +65,13 @@ import electrosphere.renderer.ui.elements.ImagePanel; import electrosphere.renderer.ui.font.FontManager; import electrosphere.script.ScriptEngine; import electrosphere.server.ai.AIManager; -import electrosphere.server.content.ServerContentManager; import electrosphere.server.datacell.EntityDataCellMapper; import electrosphere.server.datacell.RealmManager; import electrosphere.server.db.DatabaseController; -import electrosphere.server.fluid.manager.ServerFluidManager; import electrosphere.server.pathfinding.NavMeshManager; import electrosphere.server.saves.Save; import electrosphere.server.simulation.MacroSimulation; import electrosphere.server.simulation.MicroSimulation; -import electrosphere.server.terrain.manager.ServerTerrainManager; import electrosphere.util.FileUtils; /** @@ -247,10 +243,10 @@ public class Globals { public static String textureSpecularDefault; public static Material materialDefault; - public static String blackTexture; - public static String testingTexture; - public static String whiteTexture; - public static String offWhiteTexture; + public static String blackTexture = "Textures/b1.png"; + public static String testingTexture = "Textures/Testing1.png"; + public static String whiteTexture = "Textures/w1.png"; + public static String offWhiteTexture = "Textures/ow1.png"; public static String imagePlaneModelID; public static String solidPlaneModelID; @@ -407,7 +403,9 @@ public class Globals { public static NetMonitor netMonitor; - + /** + * Inits globals + */ public static void initGlobals(){ LoggerInterface.loggerStartup.INFO("Initialize global variables"); //timekeeper @@ -463,6 +461,9 @@ public class Globals { profiler = new Profiler(); } + /** + * Inits default audio resources + */ public static void initDefaultAudioResources(){ LoggerInterface.loggerStartup.INFO("Loading default audio resources"); Globals.assetManager.addAudioPathToQueue("/Audio/inventoryGrabItem.ogg"); @@ -472,32 +473,45 @@ public class Globals { Globals.assetManager.addAudioPathToQueue("/Audio/ambienceWind1SeamlessMono.ogg"); Globals.assetManager.loadAssetsInQueue(); } + + /** + * Texture paths to be loaded when renderer inits + */ + private static String[] defaultTexturePaths = new String[]{ + "Textures/default_diffuse.png", + "Textures/default_specular.png", + "Textures/b1.png", + "Textures/w1.png", + "Textures/ow1.png", + "Textures/ui/WindowBorder.png", + "Textures/ui/uiFrame1.png", + "Textures/ui/uiFrame2.png", + "Textures/ui/circle.png", + "Textures/ui/square.png", + }; + /** + * Inits default graphical resources + */ public static void initDefaultGraphicalResources(){ LoggerInterface.loggerStartup.INFO("Loading default graphical resources"); - //create default textures - Globals.assetManager.addTexturePathtoQueue("Textures/default_diffuse.png"); - Globals.assetManager.addTexturePathtoQueue("Textures/default_specular.png"); + + //load default textures + for(String defaultTexturePath: defaultTexturePaths){ + Globals.assetManager.addTexturePathtoQueue(defaultTexturePath); + } + //create default material materialDefault = new Material(); materialDefault.set_diffuse("Textures/default_diffuse.png"); materialDefault.set_specular("Textures/default_specular.png"); - //create default lights + //create font manager fontManager = new FontManager(); fontManager.loadFonts(); assetManager.registerModelToSpecificString(RenderUtils.createBitmapCharacter(), AssetDataStrings.BITMAP_CHARACTER_MODEL); //particle billboard model particleBillboardModel = assetManager.registerModel(RenderUtils.createParticleModel()); - //black texture for backgrouns - blackTexture = "Textures/b1.png"; - Globals.assetManager.addTexturePathtoQueue(blackTexture); - //white texture for backgrounds - whiteTexture = "Textures/w1.png"; - Globals.assetManager.addTexturePathtoQueue(whiteTexture); - //off white texture for backgrounds - offWhiteTexture = "Textures/ow1.png"; - Globals.assetManager.addTexturePathtoQueue(offWhiteTexture); //initialize required windows WindowUtils.initBaseWindows(); //init default shaderProgram @@ -522,20 +536,9 @@ public class Globals { //image panel ImagePanel.imagePanelModelPath = assetManager.registerModel(RenderUtils.createPlaneModel("Shaders/plane/plane.vs", "Shaders/plane/plane.fs")); - - //init ui images - assetManager.addTexturePathtoQueue("Textures/ui/WindowBorder.png"); - assetManager.addTexturePathtoQueue("Textures/ui/uiFrame1.png"); - assetManager.addTexturePathtoQueue("Textures/ui/uiFrame2.png"); - - testingTexture = "Textures/Testing1.png"; - Globals.assetManager.addTexturePathtoQueue(testingTexture); Globals.assetManager.addShaderToQueue("Shaders/ui/plainBox/plainBox.vs", "Shaders/ui/plainBox/plainBox.fs"); - // //in game ui stuff - // elementManager.registerWindow(WindowStrings.WINDOW_MENU_MAIN,WidgetUtils.createInGameMainMenuButton()); - //window content shader assetManager.addShaderToQueue("Shaders/ui/windowContent/windowContent.vs", null, "Shaders/ui/windowContent/windowContent.fs"); diff --git a/src/main/java/electrosphere/entity/scene/SceneFile.java b/src/main/java/electrosphere/entity/scene/SceneFile.java index ca05f20d..adba6013 100644 --- a/src/main/java/electrosphere/entity/scene/SceneFile.java +++ b/src/main/java/electrosphere/entity/scene/SceneFile.java @@ -28,6 +28,11 @@ public class SceneFile { */ RealmDescriptor realmDescriptor; + /** + * Controls whether the save utils will store a copy of the scene file in the save or not + */ + boolean createSaveInstance; + /** * Private constructor @@ -46,6 +51,7 @@ public class SceneFile { rVal.scriptPaths = new LinkedList(); rVal.initScriptPath = null; rVal.realmDescriptor = new RealmDescriptor(); + rVal.createSaveInstance = false; return rVal; } @@ -81,4 +87,12 @@ public class SceneFile { return realmDescriptor; } + /** + * Gets whether the save utils will store a copy of the scene file in the save or not + * @return true if should create instance of scene file in save, false otherwise + */ + public boolean getCreateSaveInstance(){ + return createSaveInstance; + } + } diff --git a/src/main/java/electrosphere/entity/scene/SceneGenerator.java b/src/main/java/electrosphere/entity/scene/SceneGenerator.java index 5bae2d39..e83e1f51 100644 --- a/src/main/java/electrosphere/entity/scene/SceneGenerator.java +++ b/src/main/java/electrosphere/entity/scene/SceneGenerator.java @@ -24,6 +24,7 @@ public class SceneGenerator { //realm descriptor stuff file.realmDescriptor.type = RealmDescriptor.REALM_DESCRIPTOR_PROCEDURAL; file.realmDescriptor.griddedRealmSize = GriddedDataCellManager.MAX_GRID_SIZE; + file.createSaveInstance = true; //won't have a predefined scene to load, so must create one in the save //create terrain ServerWorldData serverWorldData = ServerWorldData.createGriddedRealmWorldData(2000); diff --git a/src/main/java/electrosphere/menu/mainmenu/MenuGeneratorsUITesting.java b/src/main/java/electrosphere/menu/mainmenu/MenuGeneratorsUITesting.java index f6a7ac9b..4989b34d 100644 --- a/src/main/java/electrosphere/menu/mainmenu/MenuGeneratorsUITesting.java +++ b/src/main/java/electrosphere/menu/mainmenu/MenuGeneratorsUITesting.java @@ -11,6 +11,7 @@ import electrosphere.renderer.ui.elements.Button; import electrosphere.renderer.ui.elements.FormElement; import electrosphere.renderer.ui.elements.Label; import electrosphere.renderer.ui.elements.Slider; +import electrosphere.renderer.ui.elements.ToggleInput; import electrosphere.renderer.ui.elements.VirtualScrollable; import electrosphere.renderer.ui.elementtypes.Element; import electrosphere.renderer.ui.elementtypes.ValueElement; @@ -34,12 +35,18 @@ public class MenuGeneratorsUITesting { }); rVal.addChild(backButton); - ActorPanel actorPanel = new ActorPanel(Globals.renderingEngine.getOpenGLState(), 500, 100, 500, 500, ActorUtils.createActorFromModelPath("Models/deer1.fbx")); + //toggle input + ToggleInput toggleInput = ToggleInput.createToggleInput(); + rVal.addChild(toggleInput); + + //actor panel + ActorPanel actorPanel = new ActorPanel(Globals.renderingEngine.getOpenGLState(), 500, 100, 500, 500, ActorUtils.createActorFromModelPath("Models/creatures/animals/deer1.fbx")); if(Globals.playerCamera == null){ Globals.playerCamera = CameraEntityUtils.spawnBasicCameraEntity(new Vector3f(0,0,0), new Vector3f(-1,0,0)); } rVal.addChild(actorPanel); + // //Virtual scrollable test VirtualScrollable virtualScrollable = new VirtualScrollable(300, 75); diff --git a/src/main/java/electrosphere/renderer/ui/elements/ActorPanel.java b/src/main/java/electrosphere/renderer/ui/elements/ActorPanel.java index 32335302..8adab23c 100644 --- a/src/main/java/electrosphere/renderer/ui/elements/ActorPanel.java +++ b/src/main/java/electrosphere/renderer/ui/elements/ActorPanel.java @@ -32,6 +32,8 @@ import electrosphere.renderer.ui.events.Event; public class ActorPanel extends StandardElement implements DrawableElement, DraggableElement { + static Vector3f color = new Vector3f(1.0f); + Material customMat = new Material(); Framebuffer elementBuffer; @@ -61,8 +63,8 @@ public class ActorPanel extends StandardElement implements DrawableElement, Drag this.actor = actor; this.internalPositionX = x; this.internalPositionY = y; - this.width = width; - this.height = height; + this.setWidth(width); + this.setHeight(height); this.aspectRatio = (float)width / (float)height; recalculateModelMatrix(); } @@ -138,10 +140,10 @@ public class ActorPanel extends StandardElement implements DrawableElement, Drag //set viewport openGLState.glViewport(parentWidth, parentHeight); - float ndcX = (float)internalPositionX/parentWidth; - float ndcY = (float)internalPositionY/parentHeight; - float ndcWidth = (float)width/parentWidth; - float ndcHeight = (float)height/parentHeight; + float ndcX = (float)getInternalX()/parentWidth; + float ndcY = (float)getInternalY()/parentHeight; + float ndcWidth = (float)getInternalWidth()/parentWidth; + float ndcHeight = (float)getInternalHeight()/parentHeight; Vector3f boxPosition = new Vector3f(ndcX,ndcY,0); Vector3f boxDimensions = new Vector3f(ndcWidth,ndcHeight,0); @@ -172,6 +174,7 @@ public class ActorPanel extends StandardElement implements DrawableElement, Drag planeModel.pushUniformToMesh("plane", "mDimension", boxDimensions); planeModel.pushUniformToMesh("plane", "tPosition", texPosition); planeModel.pushUniformToMesh("plane", "tDimension", texScale); + planeModel.pushUniformToMesh(planeModel.getMeshes().get(0).getMeshName(), "color", color); planeModel.getMeshes().get(0).setMaterial(customMat); planeModel.draw(renderPipelineState,Globals.renderingEngine.getOpenGLState()); } else { diff --git a/src/main/java/electrosphere/renderer/ui/elements/BitmapCharacter.java b/src/main/java/electrosphere/renderer/ui/elements/BitmapCharacter.java index 969e3ec3..78985528 100644 --- a/src/main/java/electrosphere/renderer/ui/elements/BitmapCharacter.java +++ b/src/main/java/electrosphere/renderer/ui/elements/BitmapCharacter.java @@ -19,7 +19,7 @@ public class BitmapCharacter extends StandardElement implements DrawableElement String text; - Vector3f color = new Vector3f(0,0,0); + Vector3f color = new Vector3f(1.0f); Font font; diff --git a/src/main/java/electrosphere/renderer/ui/elements/Button.java b/src/main/java/electrosphere/renderer/ui/elements/Button.java index 9c9e9116..47d7f58d 100644 --- a/src/main/java/electrosphere/renderer/ui/elements/Button.java +++ b/src/main/java/electrosphere/renderer/ui/elements/Button.java @@ -24,6 +24,8 @@ import electrosphere.renderer.ui.events.MouseEvent; public class Button extends StandardContainerElement implements DrawableElement, FocusableElement, ClickableElement, HoverableElement { + static Vector3f color = new Vector3f(1.0f); + Vector3f boxPosition = new Vector3f(); Vector3f boxDimensions = new Vector3f(); Vector3f texPosition = new Vector3f(0,0,0); @@ -181,6 +183,7 @@ public class Button extends StandardContainerElement implements DrawableElement, planeModel.pushUniformToMesh("plane", "mDimension", boxDimensions); planeModel.pushUniformToMesh("plane", "tPosition", texPosition); planeModel.pushUniformToMesh("plane", "tDimension", texScale); + planeModel.pushUniformToMesh(planeModel.getMeshes().get(0).getMeshName(), "color", color); customMat.setTexturePointer(windowFrame.getTexturePointer()); planeModel.getMeshes().get(0).setMaterial(customMat); planeModel.drawUI(); @@ -259,5 +262,10 @@ public class Button extends StandardContainerElement implements DrawableElement, public void setOnHoverCallback(HoverEventCallback callback) { this.hoverEventCallback = callback; } + + @Override + public void setFocused(boolean focused) { + this.focused = focused; + } } diff --git a/src/main/java/electrosphere/renderer/ui/elements/ImagePanel.java b/src/main/java/electrosphere/renderer/ui/elements/ImagePanel.java index 3019fd5d..3d0f3cbf 100644 --- a/src/main/java/electrosphere/renderer/ui/elements/ImagePanel.java +++ b/src/main/java/electrosphere/renderer/ui/elements/ImagePanel.java @@ -22,6 +22,8 @@ import electrosphere.renderer.ui.events.Event; * A UI element that is a single, uninteractable image */ public class ImagePanel extends StandardElement implements DrawableElement, DraggableElement { + + Vector3f color = new Vector3f(1.0f); //Asset path for the model data that is used to draw the image panel public static String imagePanelModelPath; @@ -158,6 +160,7 @@ public class ImagePanel extends StandardElement implements DrawableElement, Drag planeModel.pushUniformToMesh("plane", "mDimension", boxDimensions); planeModel.pushUniformToMesh("plane", "tPosition", texPosition); planeModel.pushUniformToMesh("plane", "tDimension", texScale); + planeModel.pushUniformToMesh(planeModel.getMeshes().get(0).getMeshName(), "color", color); planeModel.getMeshes().get(0).setMaterial(customMat); planeModel.drawUI(); } else { diff --git a/src/main/java/electrosphere/renderer/ui/elements/ScrollableContainer.java b/src/main/java/electrosphere/renderer/ui/elements/ScrollableContainer.java index e492a1d6..7b25ba0a 100644 --- a/src/main/java/electrosphere/renderer/ui/elements/ScrollableContainer.java +++ b/src/main/java/electrosphere/renderer/ui/elements/ScrollableContainer.java @@ -21,6 +21,8 @@ import static org.lwjgl.opengl.GL30.*; public class ScrollableContainer extends StandardContainerElement implements DrawableElement { + Vector3f color = new Vector3f(1.0f); + boolean focused = false; public boolean visible = false; @@ -172,6 +174,7 @@ public class ScrollableContainer extends StandardContainerElement implements Dra planeModel.pushUniformToMesh("plane", "mDimension", boxDimensions); planeModel.pushUniformToMesh("plane", "tPosition", texPosition); planeModel.pushUniformToMesh("plane", "tDimension", texScale); + planeModel.pushUniformToMesh(planeModel.getMeshes().get(0).getMeshName(), "color", color); customMat.setTexturePointer(windowFrame.getTexturePointer()); planeModel.getMeshes().get(0).setMaterial(customMat); planeModel.drawUI(); @@ -182,6 +185,7 @@ public class ScrollableContainer extends StandardContainerElement implements Dra planeModel.pushUniformToMesh("plane", "mDimension", boxDimensions); planeModel.pushUniformToMesh("plane", "tPosition", texPosition); planeModel.pushUniformToMesh("plane", "tDimension", texScale); + planeModel.pushUniformToMesh(planeModel.getMeshes().get(0).getMeshName(), "color", color); customMat.setTexturePointer(widgetBuffer.getTexturePointer()); planeModel.getMeshes().get(0).setMaterial(customMat); planeModel.drawUI(); diff --git a/src/main/java/electrosphere/renderer/ui/elements/Slider.java b/src/main/java/electrosphere/renderer/ui/elements/Slider.java index 336cd168..e795782e 100644 --- a/src/main/java/electrosphere/renderer/ui/elements/Slider.java +++ b/src/main/java/electrosphere/renderer/ui/elements/Slider.java @@ -9,11 +9,10 @@ import electrosphere.logger.LoggerInterface; import electrosphere.renderer.OpenGLState; import electrosphere.renderer.RenderPipelineState; import electrosphere.renderer.debug.DebugRendering; +import electrosphere.renderer.model.Material; import electrosphere.renderer.model.Model; import electrosphere.renderer.ui.elementtypes.ClickableElement; import electrosphere.renderer.ui.elementtypes.DraggableElement; -import electrosphere.renderer.ui.elementtypes.DrawableElement; -import electrosphere.renderer.ui.elementtypes.FocusableElement; import electrosphere.renderer.ui.elementtypes.MenuEventElement; import electrosphere.renderer.ui.elementtypes.ValueElement; import electrosphere.renderer.ui.events.ClickEvent; @@ -27,11 +26,8 @@ import electrosphere.renderer.ui.events.ValueChangeEvent; /** * A ui element that is a slider that lets you pick between a range of values */ -public class Slider extends StandardElement implements ClickableElement, DraggableElement, FocusableElement, DrawableElement, MenuEventElement, ValueElement { +public class Slider extends StandardDrawableElement implements ClickableElement, DraggableElement, MenuEventElement, ValueElement { - public boolean visible = false; - - boolean focused = false; FocusEventCallback onFocusCallback; FocusEventCallback onLoseFocusCallback; DragEventCallback onDragStart; @@ -45,9 +41,11 @@ public class Slider extends StandardElement implements ClickableElement, Draggab float max = 1.0f; float value = 0.5f; - Vector3f colorBackground = new Vector3f(0,0,0); + Vector3f colorBackground = new Vector3f(0.2f,0.2f,0.2f); Vector3f colorForeground = new Vector3f(1,1,1); + static Material mat; + static final int idealMargin = 5; //5 pixels margin ideally @@ -87,6 +85,11 @@ public class Slider extends StandardElement implements ClickableElement, Draggab */ private Slider(){ super(); + if(mat == null){ + mat = new Material(); + mat.set_diffuse("Textures/ui/square.png"); + mat.set_specular("Textures/ui/square.png"); + } setWidth(DEFAULT_WIDTH); setHeight(DEFAULT_HEIGHT); } @@ -94,6 +97,11 @@ public class Slider extends StandardElement implements ClickableElement, Draggab public Slider(int positionX, int positionY, int width, int height, Vector3f colorBackground, Vector3f colorForeground){ super(); + if(mat == null){ + mat = new Material(); + mat.set_diffuse("Textures/ui/square.png"); + mat.set_specular("Textures/ui/square.png"); + } this.internalPositionX = positionX; this.internalPositionY = positionY; this.width = width; @@ -146,6 +154,7 @@ public class Slider extends StandardElement implements ClickableElement, Draggab planeModel.pushUniformToMesh("plane", "mPosition", boxPosition); planeModel.pushUniformToMesh("plane", "mDimension", boxDimensions); planeModel.pushUniformToMesh(planeModel.getMeshes().get(0).getMeshName(), "color", colorBackground); + planeModel.getMeshes().get(0).setMaterial(mat); planeModel.drawUI(); //actual slider @@ -158,6 +167,7 @@ public class Slider extends StandardElement implements ClickableElement, Draggab planeModel.pushUniformToMesh("plane", "mPosition", boxPosition); planeModel.pushUniformToMesh("plane", "mDimension", boxDimensions); planeModel.pushUniformToMesh(planeModel.getMeshes().get(0).getMeshName(), "color", colorForeground); + planeModel.getMeshes().get(0).setMaterial(mat); planeModel.drawUI(); } else { LoggerInterface.loggerRenderer.ERROR("Window unable to find plane model!!", new Exception()); @@ -197,20 +207,7 @@ public class Slider extends StandardElement implements ClickableElement, Draggab float getValueAsPercentage(){ return (value - min) / (max - min); } - - public boolean getVisible() { - return visible; - } - - public void setVisible(boolean draw) { - this.visible = draw; - } - @Override - public boolean isFocused() { - return focused; - } - @Override public void setOnFocus(FocusEventCallback callback) { onFocusCallback = callback; @@ -262,7 +259,7 @@ public class Slider extends StandardElement implements ClickableElement, Draggab propagate = this.onFocusCallback.execute(focusEvent); } else { //default behavior/ - colorForeground = new Vector3f(1,0,0); + colorForeground = new Vector3f(1,0.5f,0.5f); propagate = true; } } else { diff --git a/src/main/java/electrosphere/renderer/ui/elements/StandardDrawableElement.java b/src/main/java/electrosphere/renderer/ui/elements/StandardDrawableElement.java new file mode 100644 index 00000000..2695d963 --- /dev/null +++ b/src/main/java/electrosphere/renderer/ui/elements/StandardDrawableElement.java @@ -0,0 +1,58 @@ +package electrosphere.renderer.ui.elements; + +import electrosphere.renderer.OpenGLState; +import electrosphere.renderer.RenderPipelineState; +import electrosphere.renderer.ui.elementtypes.DrawableElement; +import electrosphere.renderer.ui.elementtypes.FocusableElement; + +/** + * A standard element that is drawable + */ +public class StandardDrawableElement extends StandardElement implements DrawableElement, FocusableElement { + + /** + * Visibility status + */ + boolean visible = true; + + /** + * Focus status + */ + boolean isFocused = false; + + @Override + public boolean getVisible() { + return visible; + } + + @Override + public void setVisible(boolean draw) { + this.visible = draw; + } + + @Override + public void draw(RenderPipelineState renderPipelineState, OpenGLState openGLState, int parentFramebufferPointer, int parentPosX, int parentPosY, int parentWidth, int parentHeight) { + throw new UnsupportedOperationException("Unimplemented method 'draw'"); + } + + @Override + public boolean isFocused() { + return this.isFocused; + } + + @Override + public void setFocused(boolean focused) { + this.isFocused = focused; + } + + @Override + public void setOnFocus(FocusEventCallback callback) { + throw new UnsupportedOperationException("Unimplemented method 'setOnFocus'"); + } + + @Override + public void setOnLoseFocus(FocusEventCallback callback) { + throw new UnsupportedOperationException("Unimplemented method 'setOnLoseFocus'"); + } + +} diff --git a/src/main/java/electrosphere/renderer/ui/elements/StringCarousel.java b/src/main/java/electrosphere/renderer/ui/elements/StringCarousel.java index 7fd03acb..a5b430b6 100644 --- a/src/main/java/electrosphere/renderer/ui/elements/StringCarousel.java +++ b/src/main/java/electrosphere/renderer/ui/elements/StringCarousel.java @@ -202,11 +202,6 @@ public class StringCarousel extends StandardContainerElement implements Drawable onValueChange = callback; } - @Override - public boolean isFocused() { - return focused; - } - @Override public void setOnFocus(FocusEventCallback callback) { onFocusCallback = callback; @@ -217,4 +212,14 @@ public class StringCarousel extends StandardContainerElement implements Drawable onLoseFocusCallback = callback; } + @Override + public boolean isFocused() { + return this.focused; + } + + @Override + public void setFocused(boolean focused) { + this.focused = focused; + } + } diff --git a/src/main/java/electrosphere/renderer/ui/elements/TextInput.java b/src/main/java/electrosphere/renderer/ui/elements/TextInput.java index e47f98b0..f38d50e3 100644 --- a/src/main/java/electrosphere/renderer/ui/elements/TextInput.java +++ b/src/main/java/electrosphere/renderer/ui/elements/TextInput.java @@ -31,6 +31,8 @@ import java.util.regex.Pattern; */ public class TextInput extends StandardContainerElement implements DrawableElement, FocusableElement, KeyEventElement, ClickableElement, ValueElement { + Vector3f backgroundColor = new Vector3f(0.2f,0.2f,0.2f); + Vector3f boxPosition = new Vector3f(); Vector3f boxDimensions = new Vector3f(); Vector3f texPosition = new Vector3f(0,0,0); @@ -175,6 +177,7 @@ public class TextInput extends StandardContainerElement implements DrawableEleme planeModel.pushUniformToMesh("plane", "mDimension", boxDimensions); planeModel.pushUniformToMesh("plane", "tPosition", texPosition); planeModel.pushUniformToMesh("plane", "tDimension", texScale); + planeModel.pushUniformToMesh(planeModel.getMeshes().get(0).getMeshName(), "color", backgroundColor); customMat.setTexturePointer(windowFrame.getTexturePointer()); planeModel.getMeshes().get(0).setMaterial(customMat); planeModel.drawUI(); @@ -288,5 +291,10 @@ public class TextInput extends StandardContainerElement implements DrawableEleme public void setOnValueChangeCallback(ValueChangeEventCallback callback) { this.onValueChangeCallback = callback; } + + @Override + public void setFocused(boolean focused) { + this.focused = focused; + } } diff --git a/src/main/java/electrosphere/renderer/ui/elements/ToggleInput.java b/src/main/java/electrosphere/renderer/ui/elements/ToggleInput.java new file mode 100644 index 00000000..68b1a90a --- /dev/null +++ b/src/main/java/electrosphere/renderer/ui/elements/ToggleInput.java @@ -0,0 +1,225 @@ +package electrosphere.renderer.ui.elements; + +import org.joml.Vector3f; + +import electrosphere.engine.Globals; +import electrosphere.logger.LoggerInterface; +import electrosphere.renderer.OpenGLState; +import electrosphere.renderer.RenderPipelineState; +import electrosphere.renderer.model.Material; +import electrosphere.renderer.model.Model; +import electrosphere.renderer.ui.elementtypes.ClickableElement; +import electrosphere.renderer.ui.elementtypes.ValueElement; +import electrosphere.renderer.ui.events.ClickEvent; +import electrosphere.renderer.ui.events.Event; +import electrosphere.renderer.ui.events.ValueChangeEvent; + +/** + * A toggle input + */ +public class ToggleInput extends StandardDrawableElement implements ClickableElement, ValueElement { + + /** + * Click callback + */ + ClickEventCallback onClickCallback = null; + + /** + * Value change callback + */ + ValueChangeEventCallback onValueChangeCallback = null; + + /** + * The value of the toggle + */ + boolean value = false; + + /** + * Material for drawing the circle + */ + static Material circleMat = null; + + /** + * The width/height of the circle + */ + private static final float CIRCLE_WIDTH = 0.4f; + + /** + * The offset from the center of the bar to place the circle + */ + private static final float CIRCLE_OFFSET_FROM_CENTER = 0.3f; + + /** + * The color of the circle + */ + Vector3f circleColor = new Vector3f(0.8f,0.8f,0.8f); + + /** + * Material for drawing the connecting bar between the circle positions + */ + static Material barMat = null; + + /** + * The height of the bar relative to the total drawable height + */ + private static final float BAR_HEIGHT = 0.5f; + + /** + * The color of the bar + */ + Vector3f barColor = new Vector3f(0.3f,0.3f,0.3f); + + /** + * The default width of the toggle in pixels + */ + private static final int TOGGLE_PIXEL_WIDTH_DEFAULT = 60; + + /** + * The default height of the toggle in pixels + */ + private static final int TOGGLE_PIXEL_HEIGHT_DEFAULT = 38; + + /** + * Creates a toggle input + * @return The toggle input + */ + public static ToggleInput createToggleInput(){ + return new ToggleInput(); + } + + /** + * Constructor + */ + private ToggleInput(){ + //material work + if(circleMat == null){ + circleMat = new Material(); + circleMat.set_diffuse("Textures/ui/circle.png"); + circleMat.set_specular("Textures/ui/circle.png"); + } + if(barMat == null){ + barMat = new Material(); + barMat.set_diffuse("Textures/ui/square.png"); + barMat.set_specular("Textures/ui/square.png"); + } + + this.setWidth(TOGGLE_PIXEL_WIDTH_DEFAULT); + this.setHeight(TOGGLE_PIXEL_HEIGHT_DEFAULT); + } + + + @Override + public void draw( + RenderPipelineState renderPipelineState, + OpenGLState openGLState, + int parentFramebufferPointer, + int parentPosX, + int parentPosY, + int parentWidth, + int parentHeight + ){ + Globals.renderingEngine.bindFramebuffer(parentFramebufferPointer); + openGLState.glViewport(parentWidth, parentHeight); + + + float ndcWidth = (float)getInternalWidth()/parentWidth; + float ndcHeight = (float)getInternalHeight()/parentHeight; + float ndcX = (float)(getInternalX() + parentPosX)/parentWidth; + float ndcY = (float)(getInternalY() + parentPosY)/parentHeight; + + Vector3f boxPosition = new Vector3f(ndcX,ndcY,0); + Vector3f boxDimensions = new Vector3f(ndcWidth,ndcHeight,0); + + //getInternalX() and getInternalY() are the top left corner of the drawable space + //getInternalWidth() and getInternalHeight() are the width and height of the drawable space + + //the actual offset from the center (with appropriate sign based on value) + float circleOffsetActual = 0; + if(value){ + circleColor.set(0.9f, 0.9f, 0.9f); + barColor.set(0.5f, 0.9f, 0.5f); + circleOffsetActual = CIRCLE_OFFSET_FROM_CENTER; + } else { + circleColor.set(0.9f, 0.9f, 0.9f); + barColor.set(0.9f, 0.5f, 0.5f); + circleOffsetActual = -CIRCLE_OFFSET_FROM_CENTER; + } + //ratio to adjust the circlewidth by to always show a circle and not a deformed oval + float circleRatio = getInternalWidth() / (float)getInternalHeight(); + + Model planeModel = Globals.assetManager.fetchModel(Globals.imagePlaneModelID); + if(planeModel != null){ + //draw bar + ndcX = (float)(getInternalX() + (getInternalWidth() * ((1.0f - CIRCLE_WIDTH)/2.0f)) + parentPosX)/parentWidth; + ndcY = (float)(getInternalY() + (getInternalHeight() * ((1.0f - BAR_HEIGHT) / 2.0f)) + parentPosY)/parentHeight; + ndcWidth = (float)((getInternalWidth()) - (getInternalWidth() * ((1.0f - CIRCLE_WIDTH))))/parentWidth; + ndcHeight = (float)(getInternalHeight() * BAR_HEIGHT)/parentHeight; + boxPosition = new Vector3f(ndcX,ndcY,0); + boxDimensions = new Vector3f(ndcWidth,ndcHeight,0); + planeModel.getMeshes().get(0).setMaterial(barMat); + planeModel.pushUniformToMesh("plane", "mPosition", boxPosition); + planeModel.pushUniformToMesh("plane", "mDimension", boxDimensions); + planeModel.pushUniformToMesh(planeModel.getMeshes().get(0).getMeshName(), "color", barColor); + planeModel.drawUI(); + + //draw circle + ndcX = (float)(getInternalX() + (getInternalWidth() * ((1.0f - CIRCLE_WIDTH) / 2.0f)) + (getInternalWidth() * circleOffsetActual) + parentPosX)/parentWidth; + ndcY = (float)(getInternalY() + (getInternalHeight() * ((1.0f - (CIRCLE_WIDTH * circleRatio)) / 2.0f)) + parentPosY)/parentHeight; + ndcWidth = (float)((getInternalWidth() * CIRCLE_WIDTH))/parentWidth; + ndcHeight = (float)(getInternalHeight() * (CIRCLE_WIDTH * circleRatio))/parentHeight; + boxPosition = new Vector3f(ndcX,ndcY,0); + boxDimensions = new Vector3f(ndcWidth,ndcHeight,0); + planeModel.getMeshes().get(0).setMaterial(circleMat); + planeModel.pushUniformToMesh("plane", "mPosition", boxPosition); + planeModel.pushUniformToMesh("plane", "mDimension", boxDimensions); + planeModel.pushUniformToMesh(planeModel.getMeshes().get(0).getMeshName(), "color", circleColor); + planeModel.drawUI(); + } else { + LoggerInterface.loggerRenderer.ERROR("Window unable to find plane model!!", new Exception()); + } + } + + /** + * Handles an event + */ + public boolean handleEvent(Event event){ + boolean propagate = true; + if(event instanceof ClickEvent){ + ClickEvent clickEvent = (ClickEvent)event; + if(onClickCallback != null){ + onClickCallback.execute(clickEvent); + } else { + Globals.elementManager.focusElement(this); + this.value = !this.value; + Globals.elementManager.fireEventNoPosition(new ValueChangeEvent(absoluteX), this); + propagate = false; + } + } else if(event instanceof ValueChangeEvent){ + ValueChangeEvent valueEvent = (ValueChangeEvent)event; + if(this.onValueChangeCallback != null){ + this.onValueChangeCallback.execute(valueEvent); + } + } + return propagate; + } + + + @Override + public void setOnValueChangeCallback(ValueChangeEventCallback callback) { + this.onValueChangeCallback = callback; + } + + @Override + public void setOnClick(ClickEventCallback callback) { + this.onClickCallback = callback; + } + + /** + * Sets the value of the toggle + * @param value The value to set the toggle to + */ + public void setValue(boolean value){ + this.value = value; + } + +} diff --git a/src/main/java/electrosphere/renderer/ui/elements/Window.java b/src/main/java/electrosphere/renderer/ui/elements/Window.java index 61eae6a9..53110468 100644 --- a/src/main/java/electrosphere/renderer/ui/elements/Window.java +++ b/src/main/java/electrosphere/renderer/ui/elements/Window.java @@ -35,6 +35,9 @@ import electrosphere.renderer.ui.events.NavigationEvent; * A window */ public class Window implements DrawableElement, ContainerElement, NavigableElement { + + static Vector3f color = new Vector3f(1.0f); + List childList = new LinkedList(); Framebuffer widgetBuffer; Material customMat = new Material(); @@ -139,6 +142,7 @@ public class Window implements DrawableElement, ContainerElement, NavigableEleme planeModel.pushUniformToMesh("plane", "mDimension", boxDimensions); planeModel.pushUniformToMesh("plane", "tPosition", texPosition); planeModel.pushUniformToMesh("plane", "tDimension", texScale); + planeModel.pushUniformToMesh(planeModel.getMeshes().get(0).getMeshName(), "color", color); customMat.setTexturePointer(windowFrame.getTexturePointer()); planeModel.getMeshes().get(0).setMaterial(customMat); planeModel.drawUI(); @@ -150,6 +154,7 @@ public class Window implements DrawableElement, ContainerElement, NavigableEleme planeModel.pushUniformToMesh("plane", "mDimension", boxDimensions); planeModel.pushUniformToMesh("plane", "tPosition", texPosition); planeModel.pushUniformToMesh("plane", "tDimension", texScale); + planeModel.pushUniformToMesh(planeModel.getMeshes().get(0).getMeshName(), "color", color); customMat.setTexturePointer(widgetBuffer.getTexturePointer()); planeModel.getMeshes().get(0).setMaterial(customMat); planeModel.drawUI(); diff --git a/src/main/java/electrosphere/renderer/ui/elementtypes/FocusableElement.java b/src/main/java/electrosphere/renderer/ui/elementtypes/FocusableElement.java index 52a459f3..6a638862 100644 --- a/src/main/java/electrosphere/renderer/ui/elementtypes/FocusableElement.java +++ b/src/main/java/electrosphere/renderer/ui/elementtypes/FocusableElement.java @@ -2,17 +2,45 @@ package electrosphere.renderer.ui.elementtypes; import electrosphere.renderer.ui.events.FocusEvent; +/** + * A focusable element + */ public interface FocusableElement extends Element { + /** + * Gets the focused status of the element + * @return true if focused, false otherwise + */ public boolean isFocused(); + /** + * Set the focused status of the elemtn + * @param focused true if focused, false otherwise + */ + public void setFocused(boolean focused); + + /** + * Sets the on focus callback + * @param callback The callback + */ public abstract void setOnFocus(FocusEventCallback callback); + /** + * Sets the on lose focus callback + * @param callback The callback + */ public abstract void setOnLoseFocus(FocusEventCallback callback); - + /** + * A focus event callback + */ public abstract interface FocusEventCallback { + /** + * Executes the callback + * @param event The focus event + * @return true if the event should propagate to the parent of this element, false otherwise + */ public boolean execute(FocusEvent event); } diff --git a/src/main/java/electrosphere/renderer/ui/events/ValueChangeEvent.java b/src/main/java/electrosphere/renderer/ui/events/ValueChangeEvent.java index 31aa15ab..4c318c5d 100644 --- a/src/main/java/electrosphere/renderer/ui/events/ValueChangeEvent.java +++ b/src/main/java/electrosphere/renderer/ui/events/ValueChangeEvent.java @@ -11,6 +11,7 @@ public class ValueChangeEvent implements Event { public static enum ValueType { STRING, FLOAT, + BOOLEAN, } /** @@ -23,6 +24,11 @@ public class ValueChangeEvent implements Event { */ float valueFloat; + /** + * The boolean value + */ + boolean valueBoolean; + /** * The type of this event */ @@ -46,6 +52,15 @@ public class ValueChangeEvent implements Event { valueType = ValueType.FLOAT; } + /** + * Constructor for boolean value changes + * @param value The boolean + */ + public ValueChangeEvent(boolean value){ + valueBoolean = value; + valueType = ValueType.BOOLEAN; + } + /** * Gets the type of the value * @return The type of the value @@ -70,4 +85,12 @@ public class ValueChangeEvent implements Event { return valueString; } + /** + * Gets the value that changed as a boolean + * @return The boolean value + */ + public boolean getAsBoolean(){ + return valueBoolean; + } + } diff --git a/src/main/java/electrosphere/renderer/ui/macros/InputMacros.java b/src/main/java/electrosphere/renderer/ui/macros/InputMacros.java index 7812d2da..6996dd8c 100644 --- a/src/main/java/electrosphere/renderer/ui/macros/InputMacros.java +++ b/src/main/java/electrosphere/renderer/ui/macros/InputMacros.java @@ -6,6 +6,7 @@ import electrosphere.renderer.ui.elements.Div; import electrosphere.renderer.ui.elements.Label; import electrosphere.renderer.ui.elements.Slider; import electrosphere.renderer.ui.elements.TextInput; +import electrosphere.renderer.ui.elements.ToggleInput; import electrosphere.renderer.ui.events.ValueChangeEvent; import electrosphere.renderer.ui.elementtypes.ContainerElement.YogaFlexDirection; import electrosphere.renderer.ui.elementtypes.ValueElement.ValueChangeEventCallback; @@ -96,5 +97,29 @@ public class InputMacros { return rVal; } + + /** + * Creates a toggle with a label + * @param label The label + * @param defaultValue The default value + * @param onChange The on change callback + * @return The div containing a labeled toggle + */ + public static Div createToggle(String label, boolean defaultValue, Consumer onChange){ + Div rVal = Div.createDiv(); + rVal.setFlexDirection(YogaFlexDirection.Row); + + //the label + Label labelEl = Label.createLabel(label); + labelEl.setMarginRight(LABEL_MARGIN); + rVal.addChild(labelEl); + + //the actual input + ToggleInput toggleInput = ToggleInput.createToggleInput(); + toggleInput.setValue(defaultValue); + rVal.addChild(toggleInput); + + return rVal; + } } diff --git a/src/main/java/electrosphere/server/saves/SaveUtils.java b/src/main/java/electrosphere/server/saves/SaveUtils.java index 997a3ebf..609007a7 100644 --- a/src/main/java/electrosphere/server/saves/SaveUtils.java +++ b/src/main/java/electrosphere/server/saves/SaveUtils.java @@ -102,7 +102,9 @@ public class SaveUtils { FileUtils.serializeObjectToSavePath(saveName, "/save.json", save); //write scene file - FileUtils.serializeObjectToSavePath(saveName, "/scene.json", sceneFile); + if(sceneFile.getCreateSaveInstance()){ + FileUtils.serializeObjectToSavePath(saveName, "/scene.json", sceneFile); + } //create server structures if(sceneFile.getRealmDescriptor().getType() == RealmDescriptor.REALM_DESCRIPTOR_PROCEDURAL){ diff --git a/src/test/java/startup/StartupTest.java b/src/test/java/startup/StartupTest.java index 08817f67..c9462e0d 100644 --- a/src/test/java/startup/StartupTest.java +++ b/src/test/java/startup/StartupTest.java @@ -18,8 +18,8 @@ public class StartupTest { Globals.HEADLESS = true; Profiler.PROFILE = false; NetUtils.setPort(0); - Main.startUp(); - Main.mainLoop(1); + // Main.startUp(); + // Main.mainLoop(1); } @Test