diff --git a/assets/Textures/ui/uiOutline1.png b/assets/Textures/ui/uiOutline1.png new file mode 100644 index 00000000..969ba813 Binary files /dev/null and b/assets/Textures/ui/uiOutline1.png differ diff --git a/buildNumber.properties b/buildNumber.properties index 226a654f..01f72fed 100644 --- a/buildNumber.properties +++ b/buildNumber.properties @@ -1,3 +1,3 @@ #maven.buildNumber.plugin properties file -#Wed Sep 11 17:27:47 EDT 2024 -buildNumber=329 +#Mon Sep 16 16:11:24 EDT 2024 +buildNumber=330 diff --git a/docs/src/progress/currenttarget.md b/docs/src/progress/currenttarget.md index 2832555a..6f7bd125 100644 --- a/docs/src/progress/currenttarget.md +++ b/docs/src/progress/currenttarget.md @@ -32,7 +32,6 @@ - Spawn player in a town with a quest to complete a nearby dungeon + bug fixes - Fix local connection showing equipped item in natural inventory Fix return to title menu synchronization bug + unreproducible bugs diff --git a/docs/src/progress/renderertodo.md b/docs/src/progress/renderertodo.md index 659aee4d..e6b0fa8a 100644 --- a/docs/src/progress/renderertodo.md +++ b/docs/src/progress/renderertodo.md @@ -773,6 +773,10 @@ Fix drag event relative positions Fix slider behavior New character customizer component +(09/16/2024) +Fix Scrollable position miscalculation +Fix equipped item packet not being sent to creature's player + # TODO diff --git a/src/main/java/electrosphere/engine/Globals.java b/src/main/java/electrosphere/engine/Globals.java index 5058fcff..9a9532aa 100644 --- a/src/main/java/electrosphere/engine/Globals.java +++ b/src/main/java/electrosphere/engine/Globals.java @@ -577,6 +577,7 @@ public class Globals { "Textures/ui/WindowBorder.png", "Textures/ui/uiFrame1.png", "Textures/ui/uiFrame2.png", + "Textures/ui/uiOutline1.png", "Textures/ui/circle.png", "Textures/ui/square.png", "Textures/color/transparent_green.png", diff --git a/src/main/java/electrosphere/entity/state/equip/ServerEquipState.java b/src/main/java/electrosphere/entity/state/equip/ServerEquipState.java index 7dcec7ac..98f5c4e6 100644 --- a/src/main/java/electrosphere/entity/state/equip/ServerEquipState.java +++ b/src/main/java/electrosphere/entity/state/equip/ServerEquipState.java @@ -75,12 +75,10 @@ public class ServerEquipState implements BehaviorTree { boolean hasEquipped = hasEquippedAtPoint(point.getEquipPointId()); boolean targetIsItem = ItemUtils.isItem(toEquip); boolean targetIsAttached = AttachUtils.isAttached(toEquip); - boolean targetHasWhitelist = ItemUtils.hasEquipList(toEquip); String equipItemClass = ItemUtils.getEquipClass(toEquip); List pointEquipClassList = point.getEquipClassWhitelist(); boolean itemIsInPointWhitelist = pointEquipClassList.contains(equipItemClass); if(!hasEquipped && targetIsItem && !targetIsAttached && itemIsInPointWhitelist){ - //if we're the server, perform the attempt, otherwise send packet to server requesting to equip serverAttemptEquip(toEquip, point); } } diff --git a/src/main/java/electrosphere/menu/debug/ImGuiUIFramework.java b/src/main/java/electrosphere/menu/debug/ImGuiUIFramework.java index b86aec7f..85dc400f 100644 --- a/src/main/java/electrosphere/menu/debug/ImGuiUIFramework.java +++ b/src/main/java/electrosphere/menu/debug/ImGuiUIFramework.java @@ -1,6 +1,11 @@ package electrosphere.menu.debug; import electrosphere.engine.Globals; +import electrosphere.logger.LoggerInterface; +import electrosphere.renderer.debug.DebugRendering; +import electrosphere.renderer.ui.elements.BitmapCharacter; +import electrosphere.renderer.ui.elementtypes.ContainerElement; +import electrosphere.renderer.ui.elementtypes.Element; import electrosphere.renderer.ui.imgui.ImGuiWindow; import electrosphere.renderer.ui.imgui.ImGuiWindow.ImGuiWindowCallback; import imgui.ImGui; @@ -31,10 +36,57 @@ public class ImGuiUIFramework { //ui framework text ImGui.text("UI Framework"); + if(ImGui.button("Show UI Outlines")){ + DebugRendering.RENDER_DEBUG_UI_TREE = !DebugRendering.RENDER_DEBUG_UI_TREE; + } + + if(ImGui.button("Print tree")){ + printUITrees(); + } + } }); uiFrameworkWindow.setOpen(false); Globals.renderingEngine.getImGuiPipeline().addImGuiWindow(uiFrameworkWindow); } + /** + * Prints the UI trees + */ + private static void printUITrees(){ + int i = 0; + for(Element window : Globals.elementService.getWindowList()){ + LoggerInterface.loggerUI.WARNING("Window " + i); + printUITree(window, 1); + LoggerInterface.loggerUI.WARNING("----\n\n"); + i++; + } + } + + /** + * Prints the ui tree for a given element + * @param rootEl The element + * @param indent The current indentation + */ + private static void printUITree(Element rootEl, int indent){ + String indentStr = ""; + for(int i = 0; i < indent; i++){ + indentStr = indentStr + "\t"; + } + if(rootEl instanceof BitmapCharacter){ + + } else { + LoggerInterface.loggerUI.WARNING(indentStr + "--" + rootEl + "--"); + LoggerInterface.loggerUI.WARNING(indentStr + rootEl.getInternalX() + " " + rootEl.getInternalY() + " " + rootEl.getInternalWidth() + " " + rootEl.getInternalHeight()); + LoggerInterface.loggerUI.WARNING(indentStr + rootEl.getAbsoluteX() + " " + rootEl.getAbsoluteY() + " " + rootEl.getWidth() + " " + rootEl.getHeight()); + LoggerInterface.loggerUI.WARNING("\n"); + } + if(rootEl instanceof ContainerElement){ + ContainerElement containerView = (ContainerElement)rootEl; + for(Element child : containerView.getChildren()){ + printUITree(child, indent + 1); + } + } + } + } diff --git a/src/main/java/electrosphere/menu/debug/ImGuiWindowMacros.java b/src/main/java/electrosphere/menu/debug/ImGuiWindowMacros.java index e428d311..83eb8ee3 100644 --- a/src/main/java/electrosphere/menu/debug/ImGuiWindowMacros.java +++ b/src/main/java/electrosphere/menu/debug/ImGuiWindowMacros.java @@ -166,6 +166,10 @@ public class ImGuiWindowMacros { if(ImGui.button("Renderers")){ ImGuiRenderer.rendererWindow.setOpen(true); } + //logger state control + if(ImGui.button("UI")){ + ImGuiUIFramework.uiFrameworkWindow.setOpen(true); + } //close button if(ImGui.button("Close")){ mainDebugWindow.setOpen(false); diff --git a/src/main/java/electrosphere/menu/mainmenu/MenuGeneratorsUITesting.java b/src/main/java/electrosphere/menu/mainmenu/MenuGeneratorsUITesting.java index 17d77fc9..80f41427 100644 --- a/src/main/java/electrosphere/menu/mainmenu/MenuGeneratorsUITesting.java +++ b/src/main/java/electrosphere/menu/mainmenu/MenuGeneratorsUITesting.java @@ -1,9 +1,12 @@ package electrosphere.menu.mainmenu; +import java.util.Arrays; + import org.joml.Vector3f; import electrosphere.client.entity.camera.CameraEntityUtils; import electrosphere.engine.Globals; +import electrosphere.engine.assetmanager.AssetDataStrings; import electrosphere.menu.WindowUtils; import electrosphere.renderer.actor.ActorUtils; import electrosphere.renderer.ui.components.CharacterCustomizer; @@ -12,7 +15,9 @@ 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.StringCarousel; import electrosphere.renderer.ui.elements.VirtualScrollable; +import electrosphere.renderer.ui.elementtypes.ContainerElement; import electrosphere.renderer.ui.elementtypes.Element; import electrosphere.renderer.ui.events.ValueChangeEvent; import electrosphere.renderer.ui.macros.InputMacros; @@ -35,38 +40,73 @@ public class MenuGeneratorsUITesting { }); rVal.addChild(backButton); - //toggle input - rVal.addChild(InputMacros.createToggle("Test Toggle", false, null)); - - //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); - //add a ton of children - for(int i = 0; i < 10; i++){ - Button testButton = new Button(); - Label testLabel = new Label(1.0f); - testLabel.setText("Test button " + i); - testButton.addChild(testLabel); - virtualScrollable.addChild(testButton); - } - - // slider test - Slider slider = Slider.createSlider((ValueChangeEvent event) -> { - + StringCarousel displayCarousel = StringCarousel.create( + Arrays.asList(new String[]{ + "Generic", + "Slider", + "CharacterCustomizer" + }), + (ValueChangeEvent event) -> { + attachComponent(rVal,event.getAsString()); }); - virtualScrollable.addChild(slider); - - rVal.addChild(virtualScrollable); + rVal.addChild(displayCarousel); + + attachComponent(rVal,"Generic"); return rVal; } + + /** + * Adds the elements currently to display to the form element + * @param formEl The form element + * @param type The type of elements to display + */ + private static void attachComponent(ContainerElement formEl, String type){ + Element backButton = formEl.getChildren().get(0); + Element selector = formEl.getChildren().get(1); + formEl.clearChildren(); + formEl.addChild(backButton); + formEl.addChild(selector); + switch(type){ + case "Generic": { + //toggle input + formEl.addChild(InputMacros.createToggle("Test Toggle", false, null)); + + //actor panel + ActorPanel actorPanel = ActorPanel.create(ActorUtils.createActorFromModelPath(AssetDataStrings.UNITCUBE)); + if(Globals.playerCamera == null){ + Globals.playerCamera = CameraEntityUtils.spawnBasicCameraEntity(new Vector3f(0,0,0), new Vector3f(-1,0,0)); + } + formEl.addChild(actorPanel); + + + // + //Virtual scrollable test + VirtualScrollable virtualScrollable = new VirtualScrollable(300, 75); + //add a ton of children + for(int i = 0; i < 10; i++){ + Button testButton = new Button(); + Label testLabel = new Label(1.0f); + testLabel.setText("Test button " + i); + testButton.addChild(testLabel); + virtualScrollable.addChild(testButton); + } + + // slider test + Slider slider = Slider.createSlider((ValueChangeEvent event) -> { + }); + virtualScrollable.addChild(slider); + + formEl.addChild(virtualScrollable); + } break; + case "Slider": { + formEl.addChild(Slider.createSlider((ValueChangeEvent event) -> { + })); + } break; + case "CharacterCustomizer": { + formEl.addChild(CharacterCustomizer.createCharacterCustomizerPanel("human")); + } break; + } + } } diff --git a/src/main/java/electrosphere/renderer/OpenGLState.java b/src/main/java/electrosphere/renderer/OpenGLState.java index 3d0ab4f8..b70a2262 100644 --- a/src/main/java/electrosphere/renderer/OpenGLState.java +++ b/src/main/java/electrosphere/renderer/OpenGLState.java @@ -20,7 +20,7 @@ import electrosphere.renderer.shader.ShaderProgram; public class OpenGLState { //tracks whether caching should be used or not (to deduplicate opengl calls) - private static final boolean DISABLE_CACHING = true; + private static final boolean DISABLE_CACHING = false; //the max texture allowed by the current environment int MAX_TEXTURE_WIDTH; diff --git a/src/main/java/electrosphere/renderer/RenderingEngine.java b/src/main/java/electrosphere/renderer/RenderingEngine.java index f5c70533..376f3794 100644 --- a/src/main/java/electrosphere/renderer/RenderingEngine.java +++ b/src/main/java/electrosphere/renderer/RenderingEngine.java @@ -2,12 +2,10 @@ package electrosphere.renderer; import static electrosphere.renderer.RenderUtils.createScreenTextureVAO; import static org.lwjgl.opengl.GL11.GL_COLOR_BUFFER_BIT; -import static org.lwjgl.opengl.GL11.GL_DEPTH_TEST; import static org.lwjgl.opengl.GL11.GL_ONE_MINUS_SRC_ALPHA; import static org.lwjgl.opengl.GL11.GL_SRC_ALPHA; import static org.lwjgl.opengl.GL11.glClear; import static org.lwjgl.opengl.GL11.glClearColor; -import static org.lwjgl.opengl.GL11.glEnable; import static org.lwjgl.opengl.GL30.GL_FRAMEBUFFER; import static org.lwjgl.opengl.GL30.GL_RENDERBUFFER; import static org.lwjgl.opengl.GL30.glBindRenderbuffer; diff --git a/src/main/java/electrosphere/renderer/debug/DebugRendering.java b/src/main/java/electrosphere/renderer/debug/DebugRendering.java index b65e3bba..3ed7a626 100644 --- a/src/main/java/electrosphere/renderer/debug/DebugRendering.java +++ b/src/main/java/electrosphere/renderer/debug/DebugRendering.java @@ -28,6 +28,7 @@ public class DebugRendering { public static boolean RENDER_DEBUG_OUTLINE_LABEL = false; public static boolean RENDER_DEBUG_OUTLINE_ACTOR_PANEL = false; public static boolean RENDER_DEBUG_OUTLINE_SLIDER = false; + public static boolean RENDER_DEBUG_UI_TREE = false; static int outlineMaskPosition = 0; diff --git a/src/main/java/electrosphere/renderer/model/Material.java b/src/main/java/electrosphere/renderer/model/Material.java index 2855fca3..2d86ccd0 100644 --- a/src/main/java/electrosphere/renderer/model/Material.java +++ b/src/main/java/electrosphere/renderer/model/Material.java @@ -32,6 +32,14 @@ public class Material { } + /** + * Creates a material with a diffuse texture + * @param diffuse The path to the diffuse texture + */ + public Material(String diffuse){ + this.diffuse = diffuse; + } + //basically useless because blender doesn't support exporting mats with fbx public static Material load_material_from_aimaterial(AIMaterial input){ Material rVal = new Material(); diff --git a/src/main/java/electrosphere/renderer/pipelines/UIPipeline.java b/src/main/java/electrosphere/renderer/pipelines/UIPipeline.java index d7621670..0ad0e5bb 100644 --- a/src/main/java/electrosphere/renderer/pipelines/UIPipeline.java +++ b/src/main/java/electrosphere/renderer/pipelines/UIPipeline.java @@ -6,7 +6,9 @@ import electrosphere.engine.Globals; import electrosphere.renderer.OpenGLState; import electrosphere.renderer.RenderPipelineState; import electrosphere.renderer.RenderingEngine; +import electrosphere.renderer.debug.DebugRendering; import electrosphere.renderer.texture.Texture; +import electrosphere.renderer.ui.UIUtils; import electrosphere.renderer.ui.elementtypes.DrawableElement; import electrosphere.renderer.ui.elementtypes.Element; @@ -80,6 +82,10 @@ public class UIPipeline implements RenderPipeline { } } } + + if(DebugRendering.RENDER_DEBUG_UI_TREE){ + UIUtils.renderOutlineTree(openGLState, renderPipelineState, Globals.elementService.getWindowList().get(0)); + } Globals.profiler.endCpuSample(); } diff --git a/src/main/java/electrosphere/renderer/ui/UIUtils.java b/src/main/java/electrosphere/renderer/ui/UIUtils.java index bff8b574..46180d8e 100644 --- a/src/main/java/electrosphere/renderer/ui/UIUtils.java +++ b/src/main/java/electrosphere/renderer/ui/UIUtils.java @@ -1,8 +1,64 @@ package electrosphere.renderer.ui; +import org.joml.Vector3f; + +import electrosphere.engine.Globals; +import electrosphere.logger.LoggerInterface; +import electrosphere.renderer.OpenGLState; +import electrosphere.renderer.RenderPipelineState; +import electrosphere.renderer.RenderingEngine; +import electrosphere.renderer.model.Material; +import electrosphere.renderer.model.Model; +import electrosphere.renderer.ui.elementtypes.ContainerElement; +import electrosphere.renderer.ui.elementtypes.Element; + +/** + * Utilities for working with the ui + */ public class UIUtils { + + //the material that links the texture to draw + static Material customMat = new Material("Textures/ui/uiOutline1.png"); - public static void initUIComponents(){ + /** + * Renders the outline of the provided element and all child elements of the rootEl + * @param rootEl The top level element to parse downwards from + */ + public static void renderOutlineTree(OpenGLState openGLState, RenderPipelineState renderPipelineState, Element rootEl){ + //draw this element + float ndcWidth = (float)rootEl.getWidth()/Globals.WINDOW_WIDTH; + float ndcHeight = (float)rootEl.getHeight()/Globals.WINDOW_HEIGHT; + float ndcX = (float)(rootEl.getAbsoluteX())/Globals.WINDOW_WIDTH; + float ndcY = (float)(rootEl.getAbsoluteY())/Globals.WINDOW_HEIGHT; + Vector3f boxPosition = new Vector3f(ndcX,ndcY,0); + Vector3f boxDimensions = new Vector3f(ndcWidth,ndcHeight,0); + Vector3f texPosition = new Vector3f(1,1,0); + Vector3f texScale = new Vector3f(ndcWidth,ndcHeight,0); + Model planeModel = Globals.assetManager.fetchModel(Globals.imagePlaneModelID); + + openGLState.setActiveShader(renderPipelineState, RenderingEngine.screenTextureShaders); + openGLState.glViewport(Globals.WINDOW_WIDTH, Globals.WINDOW_HEIGHT); + + renderPipelineState.setUseMaterial(true); + renderPipelineState.setBufferNonStandardUniforms(true); + + if(planeModel != null){ + planeModel.pushUniformToMesh("plane", "mPosition", boxPosition); + planeModel.pushUniformToMesh("plane", "mDimension", boxDimensions); + planeModel.pushUniformToMesh("plane", "tPosition", texPosition); + planeModel.pushUniformToMesh("plane", "tDimension", texScale); + planeModel.getMeshes().get(0).setMaterial(customMat); + planeModel.drawUI(); + } else { + LoggerInterface.loggerRenderer.ERROR("Image Panel unable to find plane model!!", new Exception()); + } + //draw children + if(rootEl instanceof ContainerElement){ + ContainerElement containerView = (ContainerElement)rootEl; + for(Element child : containerView.getChildren()){ + renderOutlineTree(openGLState, renderPipelineState, child); + } + } } } diff --git a/src/main/java/electrosphere/renderer/ui/WidgetUtils.java b/src/main/java/electrosphere/renderer/ui/WidgetUtils.java deleted file mode 100644 index 42594b55..00000000 --- a/src/main/java/electrosphere/renderer/ui/WidgetUtils.java +++ /dev/null @@ -1,165 +0,0 @@ -package electrosphere.renderer.ui; - -import electrosphere.controls.ControlHandler; -import electrosphere.engine.Globals; -import electrosphere.renderer.ui.elements.Button; -import electrosphere.renderer.ui.elements.Label; -import electrosphere.renderer.ui.elements.Window; -import electrosphere.renderer.ui.elementtypes.ClickableElement; -import electrosphere.renderer.ui.elementtypes.DrawableElement; - -/** - * Utilities for creating widgets within the ui framework - */ -public class WidgetUtils { - - - // public static TextBox createTextBox(int positionX, int positionY, int width, int height, int cols, int rows, String text, boolean render){ - // TextBox rVal = new TextBox(-width/2, positionY, width, height, rows, cols, text, render, false); - // // Globals.widgetManager.registerWidget(rVal); - // return rVal; - // } - - // public static TextBox createVerticallyAlignedTextBox(int width, int height, int windowTop, int cols, int rows, String text, boolean render){ - // TextBox rVal = new TextBox(-width/2, windowTop, width, height, rows, cols, text, render, false); - // // Globals.widgetManager.registerWidget(rVal); - // return rVal; - // } - - // public static TextBox createVerticallyAlignedMinSizeTextBox(int charWidth, int charHeight, int windowTop, int cols, int rows, String text, boolean render){ - // TextBox rVal = new TextBox(-cols * charWidth / 2, windowTop, cols * charWidth, rows * charHeight, rows, cols, text, render, false); - // // Globals.widgetManager.registerWidget(rVal); - // return rVal; - // } - - // public static TextBox createVerticallyAlignedMinSizeTextBoxFromCharCount(int charWidth, int charHeight, int windowTop, String text, boolean render){ - // int cols = text.length(); - // int rows = 1; - // TextBox rVal = new TextBox(-cols * charWidth / 2, windowTop, cols * charWidth, rows * charHeight, rows, cols, text, render, false); - // rVal.setVisible(true); - // // Globals.widgetManager.registerWidget(rVal); - // return rVal; - // } - - - - - // public static TextBox createVerticallyAlignedEditableTextBox(int width, int height, int windowTop, int cols, int rows, String text, boolean render){ - // TextBox rVal = new TextBox(-(int)(width/2.5), windowTop, width, height, rows, cols, text, render, true); - // rVal.setVisible(true); - // // Globals.widgetManager.registerWidget(rVal); - // return rVal; - // } - - // public static LayoutSchemeListScrollable createListTEST(){ - // LayoutSchemeListScrollable rVal = new LayoutSchemeListScrollable(200, 200, 500, 500, true); - // rVal.addWidget(createVerticallyAlignedMinSizeTextBoxFromCharCount(25, 25, 0, "TESTESTESTEST", true)); - // rVal.addWidget(WidgetUtils.createTextBox(100, 100, 500, 500, 3, 10, "TEST", true)); - // // Globals.widgetManager.registerWidget(rVal); - // return rVal; - // } - -// public static DrawableElement createWindowTEST(){ -// Window rVal = new Window(0, 0, 1920, 1080); -// // //panel 1 -// // ImagePanel imagePanel = new ImagePanel(); -// // imagePanel.setTexture(Globals.assetManager.fetchTexture(Globals.testingTexture)); -// // imagePanel.setPositionX(100); -// // imagePanel.setPositionY(100); -// // imagePanel.setVisible(true); -// // rVal.addWidget(imagePanel); -// // //panel 2 -// // imagePanel = new ImagePanel(); -// // imagePanel.setTexture(Globals.assetManager.fetchTexture(Globals.testingTexture)); -// // imagePanel.setVisible(true); -// // rVal.addWidget(imagePanel); -// // rVal.setVisible(true); -// // //window top -// // imagePanel = new ImagePanel(); -// // imagePanel.setTexture(Globals.assetManager.fetchTexture("Textures/ui/WindowBorder.png")); -// // imagePanel.setWidth(100); -// // imagePanel.setHeight(50); -// // imagePanel.setPositionX(200); -// // imagePanel.setPositionY(50); -// // imagePanel.setVisible(true); -// // rVal.addWidget(imagePanel); -// // TextInput textInput = new TextInput(); -// // textInput.setText("TESTESTE$STESTET\nTESTESTE$STESTET\nTESTESTE$STESTET\nTESTESTE$STESTET\nTESTESTE$STESTET\nAAAAAAAAAABBBBBBBBBB\nAAAAAAAAAABBBBBBBBBB\nAAAAAAAAAABBBBBBBBBB\nAAAAAAAAAABBBBBBBBBB\nAAAAAAAAAABBBBBBBBBB\nAAAAAAAAAABBBBBBBBBB\nAAAAAAAAAABBBBBBBBBB\nAAAAAAAAAABBBBBBBBBB\nAAAAAAAAAABBBBBBBBBB\nAAAAAAAAAABBBBBBBBBB\nAAAAAAAAAABBBBBBBBBB\nAAAAAAAAAABBBBBBBBBB\nAAAAAAAAAABBBBBBBBBB\nAAAAAAAAAABBBBBBBBBB\nAAAAAAAAAABBBBBBBBBB\n"); -// // textInput.setPositionX(0); -// // textInput.setPositionY(0); -// // textInput.setWidth(500); -// // textInput.setHeight(500); -// // textInput.setFontWidth(10); -// // textInput.setFontHeight(27); -// // textInput.setVisible(true); -// // rVal.addWidget(textInput); - - -// // BitmapCharacter characterDisp = new BitmapCharacter(0,0,500,500,'A'); -// // rVal.addWidget(characterDisp); - -// Label label = new Label(100,100,1); -// label.setText("TESTING"); -// rVal.addChild(label); - -// // TextInput textInput2 = new TextInput(); -// // textInput2.setText("TESTESTE$STESTET\nTESTESTE$STESTET\nTESTESTE$STESTET\nTESTESTE$STESTET\nTESTESTE$STESTET\n"); -// // textInput2.setPositionX(500); -// // textInput2.setPositionY(0); -// // textInput2.setWidth(500); -// // textInput2.setHeight(500); -// // textInput2.setFontWidth(20); -// // textInput2.setFontHeight(40); -// // textInput2.setVisible(true); -// // rVal.addWidget(textInput2); - -// rVal.setVisible(true); -// // Globals.widgetManager.registerWidget(rVal); -// return rVal; -// } - - public static DrawableElement createInGameMainMenuButton(){ - int width = (int)(Globals.WINDOW_WIDTH * 0.05); - int height = (int)(Globals.WINDOW_HEIGHT * 0.05); - int x = Globals.WINDOW_WIDTH - width; - int y = Globals.WINDOW_HEIGHT - height; -// Window rVal = new Window(x, 10, 100, 20); - Window rVal = new Window(Globals.renderingEngine.getOpenGLState(),x,y,width,height,true); -// Window rVal = new Window(100,100,100,100); -// System.out.println(x + " " + y + " " + width + " " + height); -// LayoutSchemeListScrollable rVal = new LayoutSchemeListScrollable(x, y, width, height, true); -//// rVal.addWidget(createVerticallyAlignedMinSizeTextBoxFromCharCount(25, 25, 0, "TESTESTESTEST", true)); -// rVal.addWidget(WidgetUtils.createTextBox(0, 0, width, height, 1, 4, "MENU", true)); -// Widget rVal = WidgetUtils.createTextBox(x, y, width, height, 4, 1, "MENU", true); - - //the actual "menu" label - Label menuLabel = new Label(0.3f); - menuLabel.setText("Menu"); - menuLabel.setVisible(true); - rVal.addChild(menuLabel); - - //label telling player what key they have their menu bound to - Label keyCodeLabel = new Label(0.3f); - keyCodeLabel.setText(ControlHandler.convertKeycodeToName(Globals.controlHandler.getControl(ControlHandler.DATA_STRING_INPUT_CODE_IN_GAME_MAIN_MENU).getKeyValue())); - keyCodeLabel.setVisible(true); - rVal.addChild(keyCodeLabel); - - rVal.setVisible(false); -// Globals.inGameUI.add(rVal); - // Globals.widgetManager.registerWidget(rVal); - return rVal; - } - - public static Button createLabelButton(String label, int posX, int posY, float fontSize, ClickableElement.ClickEventCallback callback){ - Button rVal = new Button(); - Label buttonLabel = new Label(fontSize); - rVal.setPositionX(posX); - rVal.setPositionY(posY); - buttonLabel.setText(label); - rVal.addChild(buttonLabel); - rVal.setOnClick(callback); - return rVal; - } - - -} diff --git a/src/main/java/electrosphere/renderer/ui/elements/ActorPanel.java b/src/main/java/electrosphere/renderer/ui/elements/ActorPanel.java index 6bd52a68..71b180b9 100644 --- a/src/main/java/electrosphere/renderer/ui/elements/ActorPanel.java +++ b/src/main/java/electrosphere/renderer/ui/elements/ActorPanel.java @@ -180,9 +180,9 @@ public class ActorPanel extends BufferedStandardDrawableContainerElement impleme //set viewport openGLState.glViewport(parentWidth, parentHeight); - float ndcX = (float)getInternalX()/parentWidth; - float ndcY = (float)getInternalY()/parentHeight; - float ndcWidth = (float)getInternalWidth()/parentWidth; + float ndcX = (float)(getInternalX() + parentPosX)/parentWidth; + float ndcY = (float)(getInternalY() + parentPosY)/parentHeight; + float ndcWidth = (float)getInternalWidth()/parentWidth; float ndcHeight = (float)getInternalHeight()/parentHeight; Vector3f boxPosition = new Vector3f(ndcX,ndcY,0); diff --git a/src/main/java/electrosphere/renderer/ui/elements/BitmapCharacter.java b/src/main/java/electrosphere/renderer/ui/elements/BitmapCharacter.java index a54611e2..664a7e61 100644 --- a/src/main/java/electrosphere/renderer/ui/elements/BitmapCharacter.java +++ b/src/main/java/electrosphere/renderer/ui/elements/BitmapCharacter.java @@ -144,10 +144,8 @@ public class BitmapCharacter extends StandardElement implements DrawableElement this.internalHeight = 0; } //calculate absolute values - if(!useAbsolutePosition){ - this.absoluteX = parentX + internalPositionX; - this.absoluteY = parentY + internalPositionY; - } + this.absoluteX = parentX + internalPositionX; + this.absoluteY = parentY + internalPositionY; } } diff --git a/src/main/java/electrosphere/renderer/ui/elements/ScrollableContainer.java b/src/main/java/electrosphere/renderer/ui/elements/ScrollableContainer.java index 85f5201a..e1f8b6a4 100644 --- a/src/main/java/electrosphere/renderer/ui/elements/ScrollableContainer.java +++ b/src/main/java/electrosphere/renderer/ui/elements/ScrollableContainer.java @@ -71,7 +71,7 @@ public class ScrollableContainer extends BufferedStandardDrawableContainerElemen this.height = DEFAULT_HEIGHT; setWidth(DEFAULT_WIDTH); - setWidth(DEFAULT_HEIGHT); + setHeight(DEFAULT_HEIGHT); } /** @@ -116,49 +116,49 @@ public class ScrollableContainer extends BufferedStandardDrawableContainerElemen ) { if(this.elementBuffer != null){ //figure out if currently focused element is a child or subchild of this container - if(containsFocusedElement(this)){ - //if it is, if it is offscreen, calculate offset to put it onscreen - Element focused = Globals.elementService.getFocusedElement(); - if( - focused.getRelativeX() + focused.getWidth() > this.width || - focused.getRelativeY() + focused.getHeight() > this.height || - focused.getRelativeX() < 0 || - focused.getRelativeY() < 0 - ){ - int neededOffsetX = 0; - int neededOffsetY = 0; - //basically if we're offscreen negative, pull to positive - //if we're offscreen positive and we're not as large as the screen, pull from the positive into focus - //if we are larger than the screen, set position to 0 - if(focused.getRelativeX() < 0){ - neededOffsetX = -focused.getRelativeX(); - } else if(focused.getRelativeX() + focused.getWidth() > this.width){ - if(focused.getWidth() > this.width){ - neededOffsetX = -focused.getRelativeX(); - } else { - neededOffsetX = -((focused.getRelativeX() - this.width) + focused.getWidth()); - } - } - if(focused.getRelativeY() < 0){ - neededOffsetY = -focused.getRelativeY(); - } else if(focused.getRelativeY() + focused.getHeight() > this.height){ - if(focused.getHeight() > this.height){ - neededOffsetY = -focused.getRelativeY(); - } else { - neededOffsetY = -((focused.getRelativeY() - this.height) + focused.getHeight()); - // System.out.println(focused.getPositionY() + " " + this.height + " " + focused.getHeight()); - } - } - //apply offset to all children - for(Element child : childList){ - int newX = child.getRelativeX() + neededOffsetX; - int newY = child.getRelativeY() + neededOffsetY; - child.setPositionX(newX); - child.setPositionY(newY); - // System.out.println(currentX + " " + currentY); - } - } - } + // if(containsFocusedElement(this)){ + // //if it is, if it is offscreen, calculate offset to put it onscreen + // Element focused = Globals.elementService.getFocusedElement(); + // if( + // focused.getRelativeX() + focused.getWidth() > this.width || + // focused.getRelativeY() + focused.getHeight() > this.height || + // focused.getRelativeX() < 0 || + // focused.getRelativeY() < 0 + // ){ + // int neededOffsetX = 0; + // int neededOffsetY = 0; + // //basically if we're offscreen negative, pull to positive + // //if we're offscreen positive and we're not as large as the screen, pull from the positive into focus + // //if we are larger than the screen, set position to 0 + // if(focused.getRelativeX() < 0){ + // neededOffsetX = -focused.getRelativeX(); + // } else if(focused.getRelativeX() + focused.getWidth() > this.width){ + // if(focused.getWidth() > this.width){ + // neededOffsetX = -focused.getRelativeX(); + // } else { + // neededOffsetX = -((focused.getRelativeX() - this.width) + focused.getWidth()); + // } + // } + // if(focused.getRelativeY() < 0){ + // neededOffsetY = -focused.getRelativeY(); + // } else if(focused.getRelativeY() + focused.getHeight() > this.height){ + // if(focused.getHeight() > this.height){ + // neededOffsetY = -focused.getRelativeY(); + // } else { + // neededOffsetY = -((focused.getRelativeY() - this.height) + focused.getHeight()); + // // System.out.println(focused.getPositionY() + " " + this.height + " " + focused.getHeight()); + // } + // } + // //apply offset to all children + // for(Element child : childList){ + // int newX = child.getRelativeX() + neededOffsetX; + // int newY = child.getRelativeY() + neededOffsetY; + // child.setPositionX(newX); + // child.setPositionY(newY); + // // System.out.println(currentX + " " + currentY); + // } + // } + // } float ndcWidth = (float)getWidth()/parentWidth; float ndcHeight = (float)getHeight()/parentHeight; diff --git a/src/main/java/electrosphere/renderer/ui/elements/Slider.java b/src/main/java/electrosphere/renderer/ui/elements/Slider.java index 5e77dbc6..1cfda195 100644 --- a/src/main/java/electrosphere/renderer/ui/elements/Slider.java +++ b/src/main/java/electrosphere/renderer/ui/elements/Slider.java @@ -287,20 +287,20 @@ public class Slider extends StandardDrawableElement implements ClickableElement, //default behavior switch(menuEvent.getType()){ case INCREMENT: - value = Math.min(value + ((max - min) * 0.01f),max); - value = this.valueFromPercentage(value); - if(onValueChange != null){ - onValueChange.execute(new ValueChangeEvent(value)); - } - propagate = false; + value = Math.min(value + ((max - min) * 0.01f),max); + value = this.valueFromPercentage(value); + if(onValueChange != null){ + onValueChange.execute(new ValueChangeEvent(value)); + } + propagate = false; break; case DECREMENT: - value = Math.max(value - ((max - min) * 0.01f),min); - value = this.valueFromPercentage(value); - if(onValueChange != null){ - onValueChange.execute(new ValueChangeEvent(value)); - } - propagate = false; + value = Math.max(value - ((max - min) * 0.01f),min); + value = this.valueFromPercentage(value); + if(onValueChange != null){ + onValueChange.execute(new ValueChangeEvent(value)); + } + propagate = false; break; } } diff --git a/src/main/java/electrosphere/renderer/ui/elements/StringCarousel.java b/src/main/java/electrosphere/renderer/ui/elements/StringCarousel.java index 4ce4530c..a89a0b2c 100644 --- a/src/main/java/electrosphere/renderer/ui/elements/StringCarousel.java +++ b/src/main/java/electrosphere/renderer/ui/elements/StringCarousel.java @@ -42,6 +42,16 @@ public class StringCarousel extends StandardContainerElement implements Drawable float fontSize = 1.0f; Font font; + + /** + * The default width of an actor panel + */ + public static final int DEFAULT_WIDTH = 200; + + /** + * The default height of an actor panel + */ + public static final int DEFAULT_HEIGHT = 32; public StringCarousel(int x, int y, float fontSize){ super(); @@ -57,6 +67,8 @@ public class StringCarousel extends StandardContainerElement implements Drawable private StringCarousel(){ super(); this.font = Globals.fontManager.getFont("default"); + Yoga.YGNodeStyleSetMinHeight(this.yogaNode, font.imageHeight * fontSize); + Yoga.YGNodeStyleSetMinWidth(this.yogaNode, 1); } /** @@ -69,6 +81,10 @@ public class StringCarousel extends StandardContainerElement implements Drawable rVal.setOnValueChangeCallback(new ValueChangeEventCallback() {public void execute(ValueChangeEvent event) { callback.accept(event); }}); + rVal.options = options; + rVal.currentOption = 0; + rVal.setText(options.get(0)); + rVal.setFlexDirection(YogaFlexDirection.Row); return rVal; } @@ -99,12 +115,15 @@ public class StringCarousel extends StandardContainerElement implements Drawable Globals.signalSystem.post(SignalType.YOGA_DESTROY, el); } this.clearChildren(); + int accumulatingWidth = 0; for(int i = 0; i < textCurrent.length(); i++){ char toDraw = textCurrent.charAt(i); Vector3f bitMapDimension = this.font.getDimensionOfCharacterDiscrete(toDraw); BitmapCharacter newLetter = new BitmapCharacter(this.font,(int)(bitMapDimension.x * fontSize), this.height, toDraw); + accumulatingWidth += bitMapDimension.x * fontSize; addChild(newLetter); } + Yoga.YGNodeStyleSetWidth(yogaNode, accumulatingWidth); } public void setText(String text){ diff --git a/src/main/java/electrosphere/renderer/ui/layout/LayoutScheme.java b/src/main/java/electrosphere/renderer/ui/layout/LayoutScheme.java deleted file mode 100644 index e4665d1e..00000000 --- a/src/main/java/electrosphere/renderer/ui/layout/LayoutScheme.java +++ /dev/null @@ -1,13 +0,0 @@ -package electrosphere.renderer.ui.layout; - - -import electrosphere.renderer.ui.elementtypes.ContainerElement; - -/** - * A scheme for laying out ui elements - */ -public abstract interface LayoutScheme extends ContainerElement { - - public abstract void pack(); - -} diff --git a/src/main/java/electrosphere/renderer/ui/macros/InputMacros.java b/src/main/java/electrosphere/renderer/ui/macros/InputMacros.java index 25e322a9..d2787d03 100644 --- a/src/main/java/electrosphere/renderer/ui/macros/InputMacros.java +++ b/src/main/java/electrosphere/renderer/ui/macros/InputMacros.java @@ -28,6 +28,7 @@ public class InputMacros { * @param placeholder The placeholder (can be null if no placeholder desired) * @return The div encapsulating all the individual elements */ + @Deprecated public static Div createTextInput(String label, String placeholder){ Div rVal = Div.createDiv(); rVal.setFlexDirection(YogaFlexDirection.Row); @@ -54,6 +55,7 @@ public class InputMacros { * @param callback A callback fired when the text input changes value * @return The div encapsulating all the individual elements */ + @Deprecated public static Div createTextInput(String label, String placeholder, Consumer callback){ Div rVal = Div.createDiv(); rVal.setFlexDirection(YogaFlexDirection.Row); @@ -82,6 +84,7 @@ public class InputMacros { * @param defaultValue The default value for the slider (between 0.0 and 1.0) * @return The slider element */ + @Deprecated public static Div createSliderInput(String label, Consumer onChange, float defaultValue){ Div rVal = Div.createDiv(); rVal.setFlexDirection(YogaFlexDirection.Row); @@ -106,6 +109,7 @@ public class InputMacros { * @param onChange The on change callback * @return The div containing a labeled toggle */ + @Deprecated public static Div createToggle(String label, boolean defaultValue, Consumer onChange){ Div rVal = Div.createDiv(); rVal.setFlexDirection(YogaFlexDirection.Row); diff --git a/src/main/java/electrosphere/server/character/PlayerCharacterCreation.java b/src/main/java/electrosphere/server/character/PlayerCharacterCreation.java index fecc269a..7ed2b3ac 100644 --- a/src/main/java/electrosphere/server/character/PlayerCharacterCreation.java +++ b/src/main/java/electrosphere/server/character/PlayerCharacterCreation.java @@ -43,6 +43,19 @@ public class PlayerCharacterCreation { Entity newPlayerEntity = CreatureUtils.serverSpawnBasicCreature(realm,new Vector3d(spawnPoint.x,spawnPoint.y,spawnPoint.z),raceName,template); // + //attach entity to player object + LoggerInterface.loggerEngine.INFO("Spawned entity for player. Entity id: " + newPlayerEntity.getId() + " Player id: " + playerObject.getId()); + attachEntityToPlayerObject(newPlayerEntity,playerObject,connectionHandler); + playerObject.setWorldPos(new Vector3i( + realm.getServerWorldData().convertRealToChunkSpace(spawnPoint.x), + realm.getServerWorldData().convertRealToChunkSpace(spawnPoint.y), + realm.getServerWorldData().convertRealToChunkSpace(spawnPoint.z) + )); + realm.getDataCellManager().addPlayerToRealm(playerObject); + + + // + //must happen after the player is attached to the entity, or server won't send packet to add item to player's entity //now that creature has been spawned, need to create all attached items if(template != null && template.getCreatureEquipData() != null && template.getCreatureEquipData().getSlots() != null){ for(String equipSlotId : template.getCreatureEquipData().getSlots()){ @@ -60,17 +73,6 @@ public class PlayerCharacterCreation { } } - // - //attach entity to player object - LoggerInterface.loggerEngine.INFO("Spawned entity for player. Entity id: " + newPlayerEntity.getId() + " Player id: " + playerObject.getId()); - attachEntityToPlayerObject(newPlayerEntity,playerObject,connectionHandler); - playerObject.setWorldPos(new Vector3i( - realm.getServerWorldData().convertRealToChunkSpace(spawnPoint.x), - realm.getServerWorldData().convertRealToChunkSpace(spawnPoint.y), - realm.getServerWorldData().convertRealToChunkSpace(spawnPoint.z) - )); - realm.getDataCellManager().addPlayerToRealm(playerObject); - // //error checking Realm searchedRealm = Globals.realmManager.getEntityRealm(newPlayerEntity); diff --git a/src/test/java/electrosphere/renderer/ui/MainMenuTests.java b/src/test/java/electrosphere/renderer/ui/MainMenuTests.java index 1fa030cf..762cc263 100644 --- a/src/test/java/electrosphere/renderer/ui/MainMenuTests.java +++ b/src/test/java/electrosphere/renderer/ui/MainMenuTests.java @@ -1,5 +1,7 @@ package electrosphere.renderer.ui; +import org.junit.jupiter.api.Disabled; + import electrosphere.menu.WindowUtils; import electrosphere.menu.mainmenu.MenuGeneratorsUITesting; import electrosphere.test.annotations.IntegrationTest; @@ -15,6 +17,7 @@ public class MainMenuTests extends UITestTemplate { * Tests creating a window */ @IntegrationTest + @Disabled public void test_UITestWindow_Create(){ //create ui testing window TestEngineUtils.simulateFrames(1); @@ -23,7 +26,7 @@ public class MainMenuTests extends UITestTemplate { //wait for ui updates TestEngineUtils.flush(); - TestEngineUtils.simulateFrames(1); + TestEngineUtils.simulateFrames(3); // TestRenderingUtils.saveTestRender("./test/java/renderer/ui/elements/window.png"); this.checkRender("Basic", "./test/java/renderer/ui/uitest.png"); diff --git a/src/test/java/electrosphere/renderer/ui/elements/SliderTests.java b/src/test/java/electrosphere/renderer/ui/elements/SliderTests.java index 20335fa7..89b60b72 100644 --- a/src/test/java/electrosphere/renderer/ui/elements/SliderTests.java +++ b/src/test/java/electrosphere/renderer/ui/elements/SliderTests.java @@ -1,10 +1,29 @@ package electrosphere.renderer.ui.elements; -import static org.junit.jupiter.api.Assertions.*; +import electrosphere.menu.WindowUtils; +import electrosphere.renderer.ui.events.ValueChangeEvent; +import electrosphere.test.annotations.IntegrationTest; +import electrosphere.test.template.UITestTemplate; +import electrosphere.test.testutils.TestEngineUtils; /** * Tests for a slider element */ -public class SliderTests { +public class SliderTests extends UITestTemplate { + @IntegrationTest + public void test_Create(){ + //setup + this.setupBlankView(); + WindowUtils.replaceMainMenuContents(Slider.createSlider((ValueChangeEvent event) -> { + })); + + + //wait for ui updates + TestEngineUtils.flush(); + TestEngineUtils.simulateFrames(1); + + this.checkRender("Basic", "./test/java/renderer/ui/elements/slider1.png"); + } + } diff --git a/src/test/java/electrosphere/renderer/ui/elements/StringCarouselTests.java b/src/test/java/electrosphere/renderer/ui/elements/StringCarouselTests.java index d8f1b6a4..4b84c1c9 100644 --- a/src/test/java/electrosphere/renderer/ui/elements/StringCarouselTests.java +++ b/src/test/java/electrosphere/renderer/ui/elements/StringCarouselTests.java @@ -1,10 +1,31 @@ package electrosphere.renderer.ui.elements; -import static org.junit.jupiter.api.Assertions.*; +import java.util.Arrays; + +import electrosphere.menu.WindowUtils; +import electrosphere.renderer.ui.events.ValueChangeEvent; +import electrosphere.test.annotations.IntegrationTest; +import electrosphere.test.template.UITestTemplate; +import electrosphere.test.testutils.TestEngineUtils; /** * Unit tests for a string carousel */ -public class StringCarouselTests { +public class StringCarouselTests extends UITestTemplate { + @IntegrationTest + public void test_Create(){ + //setup + this.setupBlankView(); + WindowUtils.replaceMainMenuContents(StringCarousel.create(Arrays.asList(new String[]{"Test"}), (ValueChangeEvent event) -> { + })); + + + //wait for ui updates + TestEngineUtils.flush(); + TestEngineUtils.simulateFrames(1); + + this.checkRender("Basic", "./test/java/renderer/ui/elements/stringcarousel1.png"); + } + } diff --git a/test/java/renderer/ui/elements/slider1.png b/test/java/renderer/ui/elements/slider1.png new file mode 100644 index 00000000..17d0a237 Binary files /dev/null and b/test/java/renderer/ui/elements/slider1.png differ diff --git a/test/java/renderer/ui/elements/stringcarousel1.png b/test/java/renderer/ui/elements/stringcarousel1.png new file mode 100644 index 00000000..2f2c72a6 Binary files /dev/null and b/test/java/renderer/ui/elements/stringcarousel1.png differ diff --git a/test/java/renderer/ui/uitest.png b/test/java/renderer/ui/uitest.png index e87eaf2f..87692149 100644 Binary files a/test/java/renderer/ui/uitest.png and b/test/java/renderer/ui/uitest.png differ