display dialog on button interact with human
All checks were successful
studiorailgun/Renderer/pipeline/head This commit looks good

This commit is contained in:
austin 2025-05-05 18:11:20 -04:00
parent 800c45033b
commit f1b27c631b
9 changed files with 164 additions and 44 deletions

View File

@ -683,7 +683,10 @@
"Leg.R", "LowerLeg.R", "Foot.R" "Leg.R", "LowerLeg.R", "Foot.R"
] ]
} }
] ],
"buttonInteraction" : {
"onInteract" : "dialog"
}
} }
], ],
"files" : [] "files" : []

View File

@ -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());
}
}
}
}

View File

@ -90,4 +90,9 @@ public class WindowStrings {
*/ */
public static final String TOOLBAR_PREVIEW = "toolbarPreview"; public static final String TOOLBAR_PREVIEW = "toolbarPreview";
/**
* The npc dialog window
*/
public static final String NPC_DIALOG = "npcDialog";
} }

View File

@ -61,8 +61,8 @@ public class ImGuiUIFramework {
private static void printUITrees(){ private static void printUITrees(){
int i = 0; int i = 0;
for(Element window : Globals.elementService.getWindowList()){ for(Element window : Globals.elementService.getWindowList()){
LoggerInterface.loggerUI.WARNING("Window " + i); LoggerInterface.loggerUI.WARNING("Window " + i + " " + Globals.elementService.getWindowId(window));
printUITree(window, 1); ImGuiUIFramework.printUITree(window, 1);
LoggerInterface.loggerUI.WARNING("----\n\n"); LoggerInterface.loggerUI.WARNING("----\n\n");
i++; i++;
} }

View File

@ -6,9 +6,19 @@ import org.jsoup.Jsoup;
import org.jsoup.nodes.Document; import org.jsoup.nodes.Document;
import org.jsoup.nodes.Node; 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.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.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; import electrosphere.util.FileUtils;
/** /**
@ -16,26 +26,57 @@ import electrosphere.util.FileUtils;
*/ */
public class DialogMenuGenerator { 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 * Displays a dialog menu
* @param path The path to the html * @param path The path to the html
* @return The element that is the root for the window * @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(); Div container = Div.createCol();
try { try {
String content = FileUtils.getAssetFileAsString(path); String content = FileUtils.getAssetFileAsString(path);
Document doc = Jsoup.parseBodyFragment(content); Document doc = Jsoup.parseBodyFragment(content);
Node bodyNode = doc.getElementsByTag("body").first(); Node bodyNode = doc.getElementsByTag("body").first();
for(Node node : bodyNode.childNodes()){ for(Node node : bodyNode.childNodes()){
container.addChild( container.addChild(HtmlParser.recursivelyParseChildren(node));
HtmlParser.recursivelyParseChildren(node));
} }
} catch (IOException e) { } catch (IOException e) {
// TODO Auto-generated catch block // TODO Auto-generated catch block
e.printStackTrace(); e.printStackTrace();
} }
return container; rVal.addChild(container);
//
//Final setup
//
Globals.signalSystem.post(SignalType.YOGA_APPLY, rVal);
return rVal;
} }
} }

View File

@ -40,7 +40,7 @@ public class HtmlParser {
throw new Error("Unsupported element type " + tag); throw new Error("Unsupported element type " + tag);
} }
} }
return Div.createDiv(); return rVal;
} }
} }

View File

@ -9,7 +9,7 @@ import org.lwjgl.glfw.GLFW;
import electrosphere.audio.VirtualAudioSourceManager.VirtualAudioSourceType; import electrosphere.audio.VirtualAudioSourceManager.VirtualAudioSourceType;
import electrosphere.client.entity.camera.CameraEntityUtils; import electrosphere.client.entity.camera.CameraEntityUtils;
import electrosphere.client.entity.crosshair.Crosshair; import electrosphere.client.entity.crosshair.Crosshair;
import electrosphere.client.interact.ClientInteractionEngine; import electrosphere.client.interact.ButtonInteraction;
import electrosphere.client.interact.ItemActions; import electrosphere.client.interact.ItemActions;
import electrosphere.client.ui.components.PlayerInventoryWindow; import electrosphere.client.ui.components.PlayerInventoryWindow;
import electrosphere.client.ui.menu.WindowStrings; 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.jump.ClientJumpTree;
import electrosphere.entity.state.movement.sprint.ClientSprintTree; import electrosphere.entity.state.movement.sprint.ClientSprintTree;
import electrosphere.entity.state.movement.walk.ClientWalkTree; 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.entity.types.creature.CreatureUtils;
import electrosphere.game.data.common.interact.InteractionData;
import electrosphere.game.data.item.Item; import electrosphere.game.data.item.Item;
import electrosphere.net.parser.net.message.EntityMessage;
import electrosphere.renderer.ui.elements.Window; import electrosphere.renderer.ui.elements.Window;
import electrosphere.renderer.ui.events.MouseEvent; import electrosphere.renderer.ui.events.MouseEvent;
import electrosphere.renderer.ui.events.ScrollEvent; import electrosphere.renderer.ui.events.ScrollEvent;
@ -654,36 +650,7 @@ public class ControlCategoryMainGame {
*/ */
mainGameControlList.add(controlMap.get(INPUT_CODE_INTERACT)); mainGameControlList.add(controlMap.get(INPUT_CODE_INTERACT));
controlMap.get(INPUT_CODE_INTERACT).setOnPress(new ControlMethod(){public void execute(MouseState mouseState){ controlMap.get(INPUT_CODE_INTERACT).setOnPress(new ControlMethod(){public void execute(MouseState mouseState){
if(Globals.playerEntity != null && Globals.playerCamera != null){ ButtonInteraction.handleButtonInteraction();
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());
}
}
}
}}); }});
/* /*

View File

@ -22,6 +22,11 @@ public class InteractionData {
*/ */
public static final String ON_INTERACT_DOOR = "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 * The function to run on interaction
*/ */
@ -42,6 +47,11 @@ public class InteractionData {
*/ */
CollidableTemplate interactionShape; CollidableTemplate interactionShape;
/**
* Configures the interaction to be client-side only
*/
Boolean clientOnly;
/** /**
* Gets the function to run on interaction * Gets the function to run on interaction
* @return The function to run on interaction * @return The function to run on interaction

View File

@ -4,6 +4,7 @@ import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.ListIterator; import java.util.ListIterator;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry;
import java.util.Set; import java.util.Set;
import java.util.Stack; import java.util.Stack;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
@ -124,6 +125,25 @@ public class ElementService extends SignalServiceImpl {
lock.unlock(); 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<String,Element> 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){ public boolean containsWindow(String name){
lock.lock(); lock.lock();
boolean rVal = elementMap.containsKey(name); boolean rVal = elementMap.containsKey(name);
@ -131,6 +151,10 @@ public class ElementService extends SignalServiceImpl {
return rVal; return rVal;
} }
/**
* Pushes a window to the front of the drawing stack
* @param window The window
*/
public void pushWindowToFront(Window window){ public void pushWindowToFront(Window window){
lock.lock(); lock.lock();
elementList.remove(window); elementList.remove(window);