diff --git a/assets/Data/entity/creatures/human.json b/assets/Data/entity/creatures/human.json index b3969152..d74fe631 100644 --- a/assets/Data/entity/creatures/human.json +++ b/assets/Data/entity/creatures/human.json @@ -683,7 +683,10 @@ "Leg.R", "LowerLeg.R", "Foot.R" ] } - ] + ], + "buttonInteraction" : { + "onInteract" : "dialog" + } } ], "files" : [] diff --git a/src/main/java/electrosphere/client/interact/ButtonInteraction.java b/src/main/java/electrosphere/client/interact/ButtonInteraction.java new file mode 100644 index 00000000..f0583493 --- /dev/null +++ b/src/main/java/electrosphere/client/interact/ButtonInteraction.java @@ -0,0 +1,70 @@ +package electrosphere.client.interact; + +import org.joml.Vector3d; + +import electrosphere.client.entity.camera.CameraEntityUtils; +import electrosphere.client.entity.crosshair.Crosshair; +import electrosphere.client.ui.menu.WindowUtils; +import electrosphere.client.ui.menu.dialog.DialogMenuGenerator; +import electrosphere.engine.Globals; +import electrosphere.entity.Entity; +import electrosphere.entity.state.equip.ClientEquipState; +import electrosphere.entity.state.inventory.InventoryUtils; +import electrosphere.entity.types.common.CommonEntityFlags; +import electrosphere.entity.types.common.CommonEntityUtils; +import electrosphere.game.data.common.interact.InteractionData; +import electrosphere.net.parser.net.message.EntityMessage; + +/** + * Stores logic for interaction button + */ +public class ButtonInteraction { + + /** + * Handles a button interaction event + */ + public static void handleButtonInteraction(){ + if(Globals.playerEntity != null && Globals.playerCamera != null){ + Entity camera = Globals.playerCamera; + Vector3d eyePos = new Vector3d(CameraEntityUtils.getCameraEye(camera)).mul(-1.0); + Vector3d centerPos = new Vector3d(CameraEntityUtils.getCameraCenter(camera)); + Entity target = ClientInteractionEngine.rayCast(centerPos, eyePos); + if(target != null && CommonEntityFlags.isInteractable(target)){ + Globals.interactionTarget = target; + ButtonInteraction.performInteraction(target); + } else if(ClientEquipState.hasEquipState(Globals.playerEntity) && Crosshair.hasTarget()){ + if(InventoryUtils.hasNaturalInventory(Globals.playerEntity)){ + InventoryUtils.clientAttemptStoreItem(Globals.playerEntity, Crosshair.getTarget()); + } + } + } + } + + /** + * Performs a button interaction + * @param target The targeted entity + */ + private static void performInteraction(Entity target){ + InteractionData interactionData = CommonEntityUtils.getCommonData(target).getButtonInteraction(); + switch(interactionData.getOnInteract()){ + case InteractionData.ON_INTERACT_MENU: { + WindowUtils.openInteractionMenu(interactionData.getWindowTarget(), interactionData.getWindowData()); + } break; + case InteractionData.ON_INTERACT_HARVEST: { + int serverEntityId = Globals.clientSceneWrapper.mapClientToServerId(target.getId()); + Globals.clientConnection.queueOutgoingMessage(EntityMessage.constructinteractMessage(serverEntityId, InteractionData.ON_INTERACT_HARVEST)); + } break; + case InteractionData.ON_INTERACT_DOOR: { + int serverEntityId = Globals.clientSceneWrapper.mapClientToServerId(target.getId()); + Globals.clientConnection.queueOutgoingMessage(EntityMessage.constructinteractMessage(serverEntityId, InteractionData.ON_INTERACT_DOOR)); + } break; + case InteractionData.ON_INTERACT_DIALOG: { + DialogMenuGenerator.displayDialog(target); + } break; + default: { + throw new Error("Unhandled interaction signal " + interactionData.getOnInteract()); + } + } + } + +} diff --git a/src/main/java/electrosphere/client/ui/menu/WindowStrings.java b/src/main/java/electrosphere/client/ui/menu/WindowStrings.java index 097456f6..f90aa33e 100644 --- a/src/main/java/electrosphere/client/ui/menu/WindowStrings.java +++ b/src/main/java/electrosphere/client/ui/menu/WindowStrings.java @@ -90,4 +90,9 @@ public class WindowStrings { */ public static final String TOOLBAR_PREVIEW = "toolbarPreview"; + /** + * The npc dialog window + */ + public static final String NPC_DIALOG = "npcDialog"; + } diff --git a/src/main/java/electrosphere/client/ui/menu/debug/ImGuiUIFramework.java b/src/main/java/electrosphere/client/ui/menu/debug/ImGuiUIFramework.java index 1b5c9452..582bd428 100644 --- a/src/main/java/electrosphere/client/ui/menu/debug/ImGuiUIFramework.java +++ b/src/main/java/electrosphere/client/ui/menu/debug/ImGuiUIFramework.java @@ -61,8 +61,8 @@ public class ImGuiUIFramework { private static void printUITrees(){ int i = 0; for(Element window : Globals.elementService.getWindowList()){ - LoggerInterface.loggerUI.WARNING("Window " + i); - printUITree(window, 1); + LoggerInterface.loggerUI.WARNING("Window " + i + " " + Globals.elementService.getWindowId(window)); + ImGuiUIFramework.printUITree(window, 1); LoggerInterface.loggerUI.WARNING("----\n\n"); i++; } diff --git a/src/main/java/electrosphere/client/ui/menu/dialog/DialogMenuGenerator.java b/src/main/java/electrosphere/client/ui/menu/dialog/DialogMenuGenerator.java index aa7b67d7..3906e6a5 100644 --- a/src/main/java/electrosphere/client/ui/menu/dialog/DialogMenuGenerator.java +++ b/src/main/java/electrosphere/client/ui/menu/dialog/DialogMenuGenerator.java @@ -6,36 +6,77 @@ import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.nodes.Node; +import electrosphere.client.ui.menu.WindowStrings; +import electrosphere.client.ui.menu.WindowUtils; import electrosphere.client.ui.parsing.HtmlParser; +import electrosphere.controls.ControlHandler.ControlsState; +import electrosphere.engine.Globals; +import electrosphere.engine.signal.Signal.SignalType; +import electrosphere.entity.Entity; import electrosphere.renderer.ui.elements.Div; -import electrosphere.renderer.ui.elementtypes.Element; +import electrosphere.renderer.ui.elements.Window; +import electrosphere.renderer.ui.elementtypes.ContainerElement.YogaAlignment; +import electrosphere.renderer.ui.elementtypes.ContainerElement.YogaJustification; +import electrosphere.renderer.ui.elementtypes.NavigableElement.NavigationEventCallback; +import electrosphere.renderer.ui.events.NavigationEvent; import electrosphere.util.FileUtils; /** * Generates dialog menus */ public class DialogMenuGenerator { + + /** + * Displays the appropriate dialog for opening a dialog window with a given entity + * @param target The entity + */ + public static void displayDialog(Entity target){ + WindowUtils.replaceWindow(WindowStrings.NPC_DIALOG, DialogMenuGenerator.displayDialog("Data/menu/npcintro.html")); + Globals.controlHandler.hintUpdateControlState(ControlsState.IN_GAME_MAIN_MENU); + } /** * Displays a dialog menu * @param path The path to the html * @return The element that is the root for the window */ - public static Element displayDialog(String path){ + public static Window displayDialog(String path){ + // + //Boilerplate for window itself + // + Window rVal = Window.createExpandableCenterAligned(Globals.renderingEngine.getOpenGLState()); + rVal.setParentAlignItem(YogaAlignment.Center); + rVal.setParentJustifyContent(YogaJustification.Center); + rVal.setOnNavigationCallback(new NavigationEventCallback() {public boolean execute(NavigationEvent event){ + WindowUtils.recursiveSetVisible(Globals.elementService.getWindow(WindowStrings.NPC_DIALOG), false); + return false; + }}); + + // + //main dialog ui logic + // Div container = Div.createCol(); try { String content = FileUtils.getAssetFileAsString(path); Document doc = Jsoup.parseBodyFragment(content); Node bodyNode = doc.getElementsByTag("body").first(); for(Node node : bodyNode.childNodes()){ - container.addChild( - HtmlParser.recursivelyParseChildren(node)); + container.addChild(HtmlParser.recursivelyParseChildren(node)); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } - return container; + rVal.addChild(container); + + + // + //Final setup + // + + Globals.signalSystem.post(SignalType.YOGA_APPLY, rVal); + + return rVal; } } diff --git a/src/main/java/electrosphere/client/ui/parsing/HtmlParser.java b/src/main/java/electrosphere/client/ui/parsing/HtmlParser.java index b0940a55..daa38047 100644 --- a/src/main/java/electrosphere/client/ui/parsing/HtmlParser.java +++ b/src/main/java/electrosphere/client/ui/parsing/HtmlParser.java @@ -40,7 +40,7 @@ public class HtmlParser { throw new Error("Unsupported element type " + tag); } } - return Div.createDiv(); + return rVal; } } diff --git a/src/main/java/electrosphere/controls/categories/ControlCategoryMainGame.java b/src/main/java/electrosphere/controls/categories/ControlCategoryMainGame.java index 195c493a..ac3a8eeb 100644 --- a/src/main/java/electrosphere/controls/categories/ControlCategoryMainGame.java +++ b/src/main/java/electrosphere/controls/categories/ControlCategoryMainGame.java @@ -9,7 +9,7 @@ import org.lwjgl.glfw.GLFW; import electrosphere.audio.VirtualAudioSourceManager.VirtualAudioSourceType; import electrosphere.client.entity.camera.CameraEntityUtils; import electrosphere.client.entity.crosshair.Crosshair; -import electrosphere.client.interact.ClientInteractionEngine; +import electrosphere.client.interact.ButtonInteraction; import electrosphere.client.interact.ItemActions; import electrosphere.client.ui.components.PlayerInventoryWindow; import electrosphere.client.ui.menu.WindowStrings; @@ -40,12 +40,8 @@ import electrosphere.entity.state.movement.groundmove.ClientGroundMovementTree.M import electrosphere.entity.state.movement.jump.ClientJumpTree; import electrosphere.entity.state.movement.sprint.ClientSprintTree; import electrosphere.entity.state.movement.walk.ClientWalkTree; -import electrosphere.entity.types.common.CommonEntityFlags; -import electrosphere.entity.types.common.CommonEntityUtils; import electrosphere.entity.types.creature.CreatureUtils; -import electrosphere.game.data.common.interact.InteractionData; import electrosphere.game.data.item.Item; -import electrosphere.net.parser.net.message.EntityMessage; import electrosphere.renderer.ui.elements.Window; import electrosphere.renderer.ui.events.MouseEvent; import electrosphere.renderer.ui.events.ScrollEvent; @@ -654,36 +650,7 @@ public class ControlCategoryMainGame { */ mainGameControlList.add(controlMap.get(INPUT_CODE_INTERACT)); controlMap.get(INPUT_CODE_INTERACT).setOnPress(new ControlMethod(){public void execute(MouseState mouseState){ - if(Globals.playerEntity != null && Globals.playerCamera != null){ - Entity camera = Globals.playerCamera; - Vector3d eyePos = new Vector3d(CameraEntityUtils.getCameraEye(camera)).mul(-1.0); - Vector3d centerPos = new Vector3d(CameraEntityUtils.getCameraCenter(camera)); - Entity target = ClientInteractionEngine.rayCast(centerPos, eyePos); - if(target != null && CommonEntityFlags.isInteractable(target)){ - Globals.interactionTarget = target; - InteractionData interactionData = CommonEntityUtils.getCommonData(target).getButtonInteraction(); - switch(interactionData.getOnInteract()){ - case InteractionData.ON_INTERACT_MENU: { - WindowUtils.openInteractionMenu(interactionData.getWindowTarget(), interactionData.getWindowData()); - } break; - case InteractionData.ON_INTERACT_HARVEST: { - int serverEntityId = Globals.clientSceneWrapper.mapClientToServerId(target.getId()); - Globals.clientConnection.queueOutgoingMessage(EntityMessage.constructinteractMessage(serverEntityId, InteractionData.ON_INTERACT_HARVEST)); - } break; - case InteractionData.ON_INTERACT_DOOR: { - int serverEntityId = Globals.clientSceneWrapper.mapClientToServerId(target.getId()); - Globals.clientConnection.queueOutgoingMessage(EntityMessage.constructinteractMessage(serverEntityId, InteractionData.ON_INTERACT_DOOR)); - } break; - default: { - throw new Error("Unhandled interaction signal " + interactionData.getOnInteract()); - } - } - } else if(ClientEquipState.hasEquipState(Globals.playerEntity) && Crosshair.hasTarget()){ - if(InventoryUtils.hasNaturalInventory(Globals.playerEntity)){ - InventoryUtils.clientAttemptStoreItem(Globals.playerEntity, Crosshair.getTarget()); - } - } - } + ButtonInteraction.handleButtonInteraction(); }}); /* diff --git a/src/main/java/electrosphere/game/data/common/interact/InteractionData.java b/src/main/java/electrosphere/game/data/common/interact/InteractionData.java index d1d38370..ff298e28 100644 --- a/src/main/java/electrosphere/game/data/common/interact/InteractionData.java +++ b/src/main/java/electrosphere/game/data/common/interact/InteractionData.java @@ -21,6 +21,11 @@ public class InteractionData { * Try opening/closing a door */ public static final String ON_INTERACT_DOOR = "door"; + + /** + * A dialog interaction + */ + public static final String ON_INTERACT_DIALOG = "dialog"; /** * The function to run on interaction @@ -42,6 +47,11 @@ public class InteractionData { */ CollidableTemplate interactionShape; + /** + * Configures the interaction to be client-side only + */ + Boolean clientOnly; + /** * Gets the function to run on interaction * @return The function to run on interaction diff --git a/src/main/java/electrosphere/renderer/ui/ElementService.java b/src/main/java/electrosphere/renderer/ui/ElementService.java index 2a4ff0de..fcdb7bda 100644 --- a/src/main/java/electrosphere/renderer/ui/ElementService.java +++ b/src/main/java/electrosphere/renderer/ui/ElementService.java @@ -4,6 +4,7 @@ import java.util.LinkedList; import java.util.List; import java.util.ListIterator; import java.util.Map; +import java.util.Map.Entry; import java.util.Set; import java.util.Stack; import java.util.concurrent.ConcurrentHashMap; @@ -124,6 +125,25 @@ public class ElementService extends SignalServiceImpl { lock.unlock(); } + /** + * Gets the id of a window + * @param window The window + * @return The id if it has an assigned id, null otherwise + */ + public String getWindowId(Element window){ + for(Entry windowEntry : this.elementMap.entrySet()){ + if(windowEntry.getValue().equals(window)){ + return windowEntry.getKey(); + } + } + return null; + } + + /** + * Checks if the element service contains a window + * @param name The name of the window + * @return true if the service contains the window, false otheriwse + */ public boolean containsWindow(String name){ lock.lock(); boolean rVal = elementMap.containsKey(name); @@ -131,6 +151,10 @@ public class ElementService extends SignalServiceImpl { return rVal; } + /** + * Pushes a window to the front of the drawing stack + * @param window The window + */ public void pushWindowToFront(Window window){ lock.lock(); elementList.remove(window);