multiple inventory windows drawing
All checks were successful
studiorailgun/Renderer/pipeline/head This commit looks good

This commit is contained in:
austin 2025-05-13 15:56:29 -04:00
parent 6dddeadee5
commit 676494ff20
4 changed files with 155 additions and 39 deletions

View File

@ -1752,6 +1752,8 @@ Can open ui menu to view inventories of other entities on client
Fix windows not resizing internal framebuffer when yoga changes their dimensions
Inventory window max width
Natural inventory panel wraps on width limit
Fix target inventory window clearing
Non-ideal implementation of multiple inventory windows drawing at once

View File

@ -14,6 +14,7 @@ import electrosphere.engine.signal.Signal.SignalType;
import electrosphere.entity.Entity;
import electrosphere.entity.state.inventory.InventoryUtils;
import electrosphere.renderer.ui.elements.Window;
import electrosphere.renderer.ui.elementtypes.ContainerElement.YogaAlignment;
import electrosphere.renderer.ui.elementtypes.NavigableElement.NavigationEventCallback;
import electrosphere.renderer.ui.events.NavigationEvent;
@ -32,6 +33,11 @@ public class InventoryMainWindow {
*/
public static final int MIN_HEIGHT = 500;
/**
* Margins around the window
*/
public static final int MARGIN = 100;
/**
* Views an inventory of an entity
* @param entity The entity
@ -54,7 +60,7 @@ public class InventoryMainWindow {
Globals.renderingEngine.getPostProcessingPipeline().setApplyBlur(true);
//
Globals.openInventoriesCount++;
} else if(InventoryUtils.hasNaturalInventory(entity) && Globals.elementService.getWindow(WindowStrings.WINDOW_CHARACTER) != null){
} else if(Globals.elementService.getWindow(WindowStrings.WINDOW_CHARACTER) != null){
Globals.elementService.closeWindow(WindowStrings.WINDOW_CHARACTER);
WindowUtils.clearTooltips();
Globals.renderingEngine.getPostProcessingPipeline().setApplyBlur(false);
@ -79,7 +85,7 @@ public class InventoryMainWindow {
Globals.renderingEngine.getPostProcessingPipeline().setApplyBlur(true);
//
Globals.openInventoriesCount++;
} else if(InventoryUtils.hasNaturalInventory(entity) && Globals.elementService.getWindow(WindowStrings.WINDOW_INVENTORY_TARGET) != null){
} else if(Globals.elementService.getWindow(WindowStrings.WINDOW_INVENTORY_TARGET) != null){
Globals.elementService.closeWindow(WindowStrings.WINDOW_INVENTORY_TARGET);
WindowUtils.clearTooltips();
Globals.renderingEngine.getPostProcessingPipeline().setApplyBlur(false);
@ -88,6 +94,7 @@ public class InventoryMainWindow {
}
}
}
InventoryMainWindow.updateInventoryWindowPositions();
}
/**
@ -98,10 +105,22 @@ public class InventoryMainWindow {
public static Window createInventoryWindow(Entity entity){
Window rVal = Window.createExpandableCenterAligned(Globals.renderingEngine.getOpenGLState());
rVal.setMaxWidth(Globals.WINDOW_WIDTH / 2);
rVal.setMarginBottom(MARGIN);
rVal.setMarginLeft(MARGIN);
rVal.setMarginRight(MARGIN);
rVal.setMarginTop(MARGIN);
String windowString;
if(entity == Globals.playerEntity){
windowString = WindowStrings.WINDOW_CHARACTER;
} else {
windowString = WindowStrings.WINDOW_INVENTORY_TARGET;
}
InventoryMainWindow.updateSpecificInventoryPlacement(rVal,windowString);
rVal.setOnNavigationCallback(new NavigationEventCallback() {public boolean execute(NavigationEvent event){
WindowUtils.recursiveSetVisible(Globals.elementService.getWindow(WindowStrings.WINDOW_CHARACTER), false);
Globals.elementService.unregisterWindow(WindowStrings.WINDOW_CHARACTER);
WindowUtils.recursiveSetVisible(Globals.elementService.getWindow(windowString), false);
Globals.elementService.unregisterWindow(windowString);
if(Globals.cameraHandler.getTrackPlayerEntity()){
Globals.controlHandler.hintUpdateControlState(ControlsState.MAIN_GAME);
} else {
@ -143,4 +162,64 @@ public class InventoryMainWindow {
return rVal;
}
/**
* Updates the inventory window positions
*/
private static void updateInventoryWindowPositions(){
Window characterWindow = ((Window)Globals.elementService.getWindow(WindowStrings.WINDOW_CHARACTER));
Window targetWindow = ((Window)Globals.elementService.getWindow(WindowStrings.WINDOW_INVENTORY_TARGET));
if(
characterWindow != null &&
targetWindow != null
){
characterWindow.setParentAlignItem(YogaAlignment.Start);
targetWindow.setParentAlignItem(YogaAlignment.End);
Globals.signalSystem.post(SignalType.YOGA_APPLY, characterWindow);
Globals.signalSystem.post(SignalType.YOGA_APPLY, targetWindow);
} else {
if(characterWindow != null){
characterWindow.setParentAlignItem(YogaAlignment.Center);
Globals.signalSystem.post(SignalType.YOGA_APPLY, characterWindow);
}
if(targetWindow != null){
targetWindow.setParentAlignItem(YogaAlignment.Center);
Globals.signalSystem.post(SignalType.YOGA_APPLY, targetWindow);
}
}
}
/**
* Updates a specific inventory's placement
* @param window The window element
* @param windowString The window string for this element
*/
private static void updateSpecificInventoryPlacement(Window window, String windowString){
Window characterWindow = ((Window)Globals.elementService.getWindow(WindowStrings.WINDOW_CHARACTER));
Window targetWindow = ((Window)Globals.elementService.getWindow(WindowStrings.WINDOW_INVENTORY_TARGET));
if(windowString.equals(WindowStrings.WINDOW_CHARACTER)){
characterWindow = window;
}
if(windowString.equals(WindowStrings.WINDOW_INVENTORY_TARGET)){
targetWindow = window;
}
if(
characterWindow != null &&
targetWindow != null
){
characterWindow.setParentAlignItem(YogaAlignment.Start);
targetWindow.setParentAlignItem(YogaAlignment.End);
Globals.signalSystem.post(SignalType.YOGA_APPLY, characterWindow);
Globals.signalSystem.post(SignalType.YOGA_APPLY, targetWindow);
} else {
if(characterWindow != null){
characterWindow.setParentAlignItem(YogaAlignment.Center);
Globals.signalSystem.post(SignalType.YOGA_APPLY, characterWindow);
}
if(targetWindow != null){
targetWindow.setParentAlignItem(YogaAlignment.Center);
Globals.signalSystem.post(SignalType.YOGA_APPLY, targetWindow);
}
}
}
}

View File

@ -16,6 +16,7 @@ import org.joml.Vector2i;
import electrosphere.engine.Globals;
import electrosphere.engine.signal.Signal;
import electrosphere.engine.signal.Signal.SignalType;
import electrosphere.logger.LoggerInterface;
import electrosphere.engine.signal.SignalServiceImpl;
import electrosphere.renderer.ui.elements.Window;
import electrosphere.renderer.ui.elementtypes.ContainerElement;
@ -73,9 +74,14 @@ public class ElementService extends SignalServiceImpl {
*/
public void registerWindow(String name, Element w){
lock.lock();
if(elementMap.containsKey(name)){
LoggerInterface.loggerUI.ERROR(new Error("Registering element to existing window string " + name));
}
elementMap.put(name,w);
if(!elementList.contains(w)){
elementList.add(w);
} else {
LoggerInterface.loggerUI.ERROR(new Error("Registering element to existing window string " + name));
}
if(elementList.size() < 2){
focusFirstElement();

View File

@ -84,6 +84,11 @@ public class Window implements DrawableElement, ContainerElement, NavigableEleme
*/
boolean showDecorations = true;
/**
* Margin size for decorations
*/
static final int DECORATION_MARGIN = 25;
/**
* Yoga node for controlling placement of the window on the screen
* IE, if you want to place a window in the upper right hand side of the screen,
@ -108,13 +113,6 @@ public class Window implements DrawableElement, ContainerElement, NavigableEleme
*/
@Deprecated
public Window(OpenGLState openGLState, int positionX, int positionY, int width, int height, boolean showDecorations){
try {
widgetBuffer = FramebufferUtils.generateTextureFramebuffer(openGLState, width, height);
} catch(Exception e){
LoggerInterface.loggerRenderer.ERROR(e);
}
customMat.setTexturePointer(widgetBuffer.getTexture().getTexturePointer());
this.showDecorations = showDecorations;
//yoga node for the actually visible part
this.yogaNode = Yoga.YGNodeNew();
this.layout = YGNode.create(this.yogaNode).layout();
@ -127,6 +125,8 @@ public class Window implements DrawableElement, ContainerElement, NavigableEleme
this.setFlexDirection(YogaFlexDirection.Column);
this.setWidth(width);
this.setHeight(height);
this.setShowDecorations(showDecorations);
this.reallocateBuffer(width, height);
}
/**
@ -134,12 +134,6 @@ public class Window implements DrawableElement, ContainerElement, NavigableEleme
* @param openGLState
*/
private Window(OpenGLState openGLState){
try {
widgetBuffer = FramebufferUtils.generateTextureFramebuffer(openGLState, DEFAULT_POPUP_WIDTH, DEFAULT_POPUP_HEIGHT);
} catch(Exception e){
LoggerInterface.loggerRenderer.ERROR(e);
}
customMat.setTexturePointer(widgetBuffer.getTexture().getTexturePointer());
//yoga node for the actually visible part
this.yogaNode = Yoga.YGNodeNew();
this.layout = YGNode.create(this.yogaNode).layout();
@ -152,6 +146,8 @@ public class Window implements DrawableElement, ContainerElement, NavigableEleme
this.setFlexDirection(YogaFlexDirection.Column);
this.setMinWidth(DEFAULT_POPUP_WIDTH);
this.setMinHeight(DEFAULT_POPUP_HEIGHT);
this.setShowDecorations(showDecorations);
this.reallocateBuffer(DEFAULT_POPUP_WIDTH, DEFAULT_POPUP_HEIGHT);
}
/**
@ -213,10 +209,12 @@ public class Window implements DrawableElement, ContainerElement, NavigableEleme
int framebufferPosX,
int framebufferPosY
) {
int absoluteX = this.getAbsoluteX();
int absoluteY = this.getAbsoluteY();
float ndcWidth = (float)this.getWidth()/framebuffer.getWidth();
float ndcHeight = (float)this.getHeight()/framebuffer.getHeight();
float ndcX = (float)this.absoluteToFramebuffer(getAbsoluteX(),framebufferPosX)/framebuffer.getWidth();
float ndcY = (float)this.absoluteToFramebuffer(getAbsoluteY(),framebufferPosY)/framebuffer.getHeight();
float ndcX = (float)this.absoluteToFramebuffer(absoluteX,framebufferPosX)/framebuffer.getWidth();
float ndcY = (float)this.absoluteToFramebuffer(absoluteY,framebufferPosY)/framebuffer.getHeight();
Vector3f boxPosition = new Vector3f(ndcX,ndcY,0);
Vector3f boxDimensions = new Vector3f(ndcWidth,ndcHeight,0);
@ -233,7 +231,7 @@ public class Window implements DrawableElement, ContainerElement, NavigableEleme
for(Element child : childList){
if(child instanceof DrawableElement){
DrawableElement drawableChild = (DrawableElement) child;
drawableChild.draw(renderPipelineState,openGLState,widgetBuffer,this.getAbsoluteX(),this.getAbsoluteY());
drawableChild.draw(renderPipelineState,openGLState,widgetBuffer,absoluteX,absoluteY);
}
}
//this call binds the screen as the "texture" we're rendering to
@ -293,6 +291,31 @@ public class Window implements DrawableElement, ContainerElement, NavigableEleme
this.clearChildren();
}
/**
* Sets the show decoration value
* @param decoration The show decoration value
*/
private void setShowDecorations(boolean decoration){
this.showDecorations = decoration;
}
/**
* Reallocates the render buffer
*/
private void reallocateBuffer(int width, int height){
int finalWidth = width - this.getPaddingLeft() - this.getPaddingRight();
int finalHeight = height - this.getPaddingTop() - this.getPaddingBottom();
try {
if(this.widgetBuffer != null){
widgetBuffer.free();
}
widgetBuffer = FramebufferUtils.generateTextureFramebuffer(Globals.renderingEngine.getOpenGLState(), finalWidth, finalHeight);
} catch(Exception e){
LoggerInterface.loggerRenderer.ERROR(e);
}
customMat.setTexturePointer(widgetBuffer.getTexture().getTexturePointer());
}
@Override
public void setWidth(int width){
this.width = width;
@ -361,11 +384,6 @@ public class Window implements DrawableElement, ContainerElement, NavigableEleme
public int absoluteX = 0;
public int absoluteY = 0;
int marginTop = 0;
int marginRight = 0;
int marginBottom = 0;
int marginLeft = 0;
public boolean visible = false;
public int getWidth() {
@ -385,35 +403,35 @@ public class Window implements DrawableElement, ContainerElement, NavigableEleme
}
public int getMarginTop(){
return marginTop;
return (int)Yoga.YGNodeLayoutGetMargin(this.yogaNode, Yoga.YGEdgeTop);
}
public int getMarginRight(){
return marginRight;
return (int)Yoga.YGNodeLayoutGetMargin(this.yogaNode, Yoga.YGEdgeRight);
}
public int getMarginBottom(){
return marginBottom;
return (int)Yoga.YGNodeLayoutGetMargin(this.yogaNode, Yoga.YGEdgeBottom);
}
public int getMarginLeft(){
return marginLeft;
return (int)Yoga.YGNodeLayoutGetMargin(this.yogaNode, Yoga.YGEdgeLeft);
}
public void setMarginTop(int marginTop){
this.marginTop = marginTop;
Yoga.YGNodeStyleSetMargin(this.yogaNode, Yoga.YGEdgeTop, marginTop);
}
public void setMarginRight(int marginRight){
this.marginRight = marginRight;
Yoga.YGNodeStyleSetMargin(this.yogaNode, Yoga.YGEdgeRight, marginRight);
}
public void setMarginBottom(int marginBottom){
this.marginBottom = marginBottom;
Yoga.YGNodeStyleSetMargin(this.yogaNode, Yoga.YGEdgeBottom, marginBottom);
}
public void setMarginLeft(int marginLeft){
this.marginLeft = marginLeft;
Yoga.YGNodeStyleSetMargin(this.yogaNode, Yoga.YGEdgeLeft, marginLeft);
}
//the yoga node id
@ -453,12 +471,7 @@ public class Window implements DrawableElement, ContainerElement, NavigableEleme
float widthRaw = Yoga.YGNodeLayoutGetWidth(yogaNode);
float heightRaw = Yoga.YGNodeLayoutGetHeight(yogaNode);
if(this.width != (int)widthRaw || this.height != (int)heightRaw){
try {
widgetBuffer.free();
widgetBuffer = FramebufferUtils.generateTextureFramebuffer(Globals.renderingEngine.getOpenGLState(), (int)widthRaw, (int)heightRaw);
} catch(Exception e){
LoggerInterface.loggerRenderer.ERROR(e);
}
this.reallocateBuffer((int)widthRaw,(int)heightRaw);
}
//apply the values to this component
this.absoluteX = (int)leftRaw;
@ -891,6 +904,22 @@ public class Window implements DrawableElement, ContainerElement, NavigableEleme
Yoga.YGNodeStyleSetPadding(this.yogaNode, Yoga.YGEdgeLeft, paddingLeft);
}
public int getPaddingTop(){
return (int)Yoga.YGNodeLayoutGetPadding(this.yogaNode, Yoga.YGEdgeTop);
}
public int getPaddingRight(){
return (int)Yoga.YGNodeLayoutGetPadding(this.yogaNode, Yoga.YGEdgeRight);
}
public int getPaddingBottom(){
return (int)Yoga.YGNodeLayoutGetPadding(this.yogaNode, Yoga.YGEdgeBottom);
}
public int getPaddingLeft(){
return (int)Yoga.YGNodeLayoutGetPadding(this.yogaNode, Yoga.YGEdgeLeft);
}
/**
* Gets the frame decoration texture path
* @return The frame decoration texture path