expanding buttons and dynamic gui areas

bottom-bar
Ivory 2023-01-18 06:38:31 -05:00
parent 58618b97bc
commit 0f73574f13
10 changed files with 164 additions and 71 deletions

View File

@ -18,7 +18,9 @@ import xyz.valnet.hadean.util.Layers;
public abstract class ImmediateUI extends GameObject implements IMouseCaptureArea {
@SuppressWarnings("unused")
private boolean active;
@SuppressWarnings("unused")
private boolean mouseDown;
public void render() {
@ -27,6 +29,17 @@ public abstract class ImmediateUI extends GameObject implements IMouseCaptureAre
end();
}
public void renderAlpha() {
float f = 99;
Assets.flat.pushColor(new Vector4f(1, 0, 0, 0.3f));
for(Vector4f box : guiAreas) {
Drawing.setLayer(f += 0.001f);
Assets.fillColor.draw(box);
}
Assets.flat.popColor();
}
@Override
public void mouseEnter() {
active = true;
@ -47,8 +60,6 @@ public abstract class ImmediateUI extends GameObject implements IMouseCaptureAre
if(button == 0) mouseDown = false;
}
public abstract Vector4f getGuiBox();
@Override
public float getLayer() {
return Layers.GENERAL_UI_INTERACTABLE;
@ -59,17 +70,18 @@ public abstract class ImmediateUI extends GameObject implements IMouseCaptureAre
private record StackingContext(
boolean fixedSize,
Vector4f box,
Vector4f occlusionBox
Vector4f occlusionBox,
boolean hasRegisteredGuiArea
// layout manager?
) {}
private StackingContext context;
private Stack<StackingContext> contextStack;
private transient StackingContext context;
private transient Stack<StackingContext> contextStack = new Stack<StackingContext>();;
private transient Map<String, Button> buttons = new HashMap<String, Button>();
private Set<String> usedButtonId = new HashSet<String>();
private transient Set<String> usedButtonId = new HashSet<String>();
private transient Map<Button, Integer> clicks = new HashMap<Button, Integer>();
private int buttonCount;
private transient int buttonCount;
private String genButtonId() {
buttonCount ++;
@ -113,33 +125,96 @@ public abstract class ImmediateUI extends GameObject implements IMouseCaptureAre
}
}
@Override
public final List<Vector4f> getGuiBoxes() {
return guiAreas;
}
private transient List<Vector4f> guiAreas = new ArrayList<Vector4f>();
// === ELEMENTS ===
//
protected void begin() {
buttonCount = 0;
usedButtonId.clear();
Drawing.setLayer(Layers.GENERAL_UI_INTERACTABLE);
context = new StackingContext(true, getGuiBox(), getGuiBox());
contextStack = new Stack<StackingContext>();
Assets.uiFrame.draw(context.occlusionBox);
pad();
contextStack.clear();
guiAreas.clear();
}
protected void root(int x, int y, int w, int h) {
assert context == null : "root can only be a root element";
Vector4f box = new Vector4f(x, y, w, h);
context = new StackingContext(true, box, box, false);
}
protected void rootEnd() {
assert contextStack.size() == 0 : "cannot end fixedFrame with un-ended elements inside";
context = null;
}
protected void fixedFrame(int w, int h) {
contextStack.push(context);
context = new StackingContext(
true,
new Vector4f(context.box.x, context.box.y, w, h),
context.occlusionBox.copy(),
true
);
}
protected void dynamicFrame() {
contextStack.push(context);
context = new StackingContext(
false,
new Vector4f(context.box.x, context.box.y, context.box.z, 0),
context.occlusionBox.copy(),
true
);
}
// TODO this will add _all_ frames, not just root frames to guiareas.
// not a problem, but not efficient. revisit.
protected void frameEnd() {
Drawing.setLayer(getLayer() + contextStack.size() - 1);
if(!context.fixedSize) {
Assets.uiFrame.draw(context.box);
guiAreas.add(context.box);
} else {
Assets.uiFrame.draw(context.occlusionBox);
guiAreas.add(context.occlusionBox);
}
context = contextStack.pop();
}
protected boolean button(String text) {
return button(genButtonId(), text);
return button(genButtonId(), text, false);
}
protected boolean button(String text, boolean expand) {
return button(genButtonId(), text, expand);
}
protected boolean button(String id, String text) {
return button(id, text, false);
}
protected boolean button(String id, String text, boolean expand) {
float h = 32;
if(expand && context.fixedSize) {
h = context.box.w;
}
Vector4f buttonBox = new Vector4f(context.box.x, context.box.y, context.box.z, h);
Button btn = getButton(id);
if(!context.hasRegisteredGuiArea) {
guiAreas.add(buttonBox);
}
btn.setText(text);
btn.setPosition((int) buttonBox.x, (int) buttonBox.y);
btn.setSize((int) buttonBox.z, (int) buttonBox.w);
btn.setLayer(Layers.GENERAL_UI_INTERACTABLE + contextStack.size());
// System.out.println("" + buttonBox);
btn.setLayer(getLayer() + contextStack.size() + 1);
adjustBox(h);
@ -160,7 +235,8 @@ public abstract class ImmediateUI extends GameObject implements IMouseCaptureAre
new Vector4f(
context.box.x, context.box.y, context.box.z, 0
),
context.occlusionBox.copy()
context.occlusionBox.copy(),
context.hasRegisteredGuiArea
);
pad();
}
@ -181,14 +257,16 @@ public abstract class ImmediateUI extends GameObject implements IMouseCaptureAre
new Vector4f(
context.box.x + 8, context.box.y + 8, context.box.z - 16, context.box.w - 16
),
context.occlusionBox.copy()
context.occlusionBox.copy(),
context.hasRegisteredGuiArea
);
} else {
context = new StackingContext(false,
new Vector4f(
context.box.x + 8, context.box.y + 8, context.box.z - 16, 0
),
context.occlusionBox.copy()
context.occlusionBox.copy(),
context.hasRegisteredGuiArea
);
}
}
@ -200,7 +278,6 @@ public abstract class ImmediateUI extends GameObject implements IMouseCaptureAre
}
protected void end() {
padEnd();
List<String> buttonIdsToRemove = new ArrayList<String>();

View File

@ -1,5 +1,7 @@
package xyz.valnet.engine.scenegraph;
import java.util.List;
import xyz.valnet.engine.math.Vector4f;
public interface IMouseCaptureArea {
@ -8,6 +10,6 @@ public interface IMouseCaptureArea {
public void mouseDown(int button);
public void mouseUp(int button);
public Vector4f getGuiBox();
public List<Vector4f> getGuiBoxes();
public float getLayer();
}

View File

@ -13,6 +13,7 @@ import java.util.Map.Entry;
import java.util.stream.Collectors;
import xyz.valnet.engine.App;
import xyz.valnet.engine.math.Vector4f;
public abstract class SceneGraph implements IScene {
protected final List<GameObject> objects = new ArrayList<GameObject>();
@ -72,6 +73,10 @@ public abstract class SceneGraph implements IScene {
obj.update(dTime);
}
mouseUpdate();
}
private void mouseUpdate() {
// DO MOUSE UPDATES!
List<IMouseCaptureArea> mouseListeners = getAll(IMouseCaptureArea.class);
mouseListeners.sort(new Comparator<IMouseCaptureArea>() {
@ -82,22 +87,25 @@ public abstract class SceneGraph implements IScene {
return al < bl ? 1 : bl < al ? -1 : 0;
}
});
for(IMouseCaptureArea listener : mouseListeners) {
boolean currentlyEntered = listener.getGuiBox().contains(App.mouseX, App.mouseY);
if(currentlyEntered) {
if(listener != hoveredMouseListener) {
if(hoveredMouseListener != null) {
hoveredMouseListener.mouseLeave();
for(Vector4f guiBox : listener.getGuiBoxes()) {
boolean currentlyEntered = guiBox.contains(App.mouseX, App.mouseY);
if(currentlyEntered) {
if(listener != hoveredMouseListener) {
if(hoveredMouseListener != null) {
hoveredMouseListener.mouseLeave();
}
hoveredMouseListener = listener;
listener.mouseEnter();
}
hoveredMouseListener = listener;
listener.mouseEnter();
return;
} else if(listener == hoveredMouseListener) {
// this is the one that is currently hovered, but it isnt!
// turn that shit OFF
hoveredMouseListener.mouseLeave();
hoveredMouseListener = null;
}
break;
} else if(listener == hoveredMouseListener) {
// this is the one that is currently hovered, but it isnt!
// turn that shit OFF
hoveredMouseListener.mouseLeave();
hoveredMouseListener = null;
}
}
}

View File

@ -71,12 +71,6 @@ public class SelectionUI extends ImmediateUI implements ISelectionChangeListener
}
}
@Override
public Vector4f getGuiBox() {
if(selected.isEmpty()) return Vector4f.zero;
return new Vector4f(10, 576 - BottomBar.bottomBarHeight - height - padding, width, height);
}
@Override
public float getLayer() {
return Layers.GENERAL_UI;

View File

@ -1,5 +1,7 @@
package xyz.valnet.hadean.gameobjects.inputlayer;
import java.util.List;
import xyz.valnet.engine.App;
import xyz.valnet.engine.math.Vector2i;
import xyz.valnet.engine.math.Vector4f;
@ -129,8 +131,8 @@ public class BuildLayer extends GameObject implements IMouseCaptureArea, ITransi
}
@Override
public Vector4f getGuiBox() {
return active ? new Vector4f(0, 0, 1024, 576) : Vector4f.zero;
public List<Vector4f> getGuiBoxes() {
return List.of(active ? new Vector4f(0, 0, 1024, 576) : Vector4f.zero);
}
@Override

View File

@ -181,8 +181,8 @@ public class SelectionLayer extends GameObject implements IMouseCaptureArea, ITr
}
@Override
public Vector4f getGuiBox() {
return new Vector4f(0, 0, 1000, 1000);
public List<Vector4f> getGuiBoxes() {
return List.of(new Vector4f(0, 0, 1000, 1000));
}
@Override

View File

@ -1,34 +1,42 @@
package xyz.valnet.hadean.gameobjects.ui;
import xyz.valnet.engine.graphics.ImmediateUI;
import xyz.valnet.engine.math.Vector4f;
public class Popup extends ImmediateUI {
@Override
public Vector4f getGuiBox() {
return new Vector4f(256, 100, 512, 300);
}
@Override
protected void gui() {
header(" Popup Test");
text("1\n1.5");
text("2");
group();
text("This should be in a frame!");
text("And this!");
groupEnd();
root(100, 100, 200, 200); {
fixedFrame(200, 100); {
pad(); {
header(" Popup Test");
text("But not this...");
text("1\n1.5");
text("2");
group(); {
text("This should be in a frame!");
text("And this!");
} groupEnd();
text("But not this...");
if(button("Click Me!")) {
System.out.println("The Event!");
}
text("This after button...");
} padEnd();
} frameEnd();
} rootEnd();
if(button("Click Me!")) {
System.out.println("The Event!");
}
text("This after button...");
root(724, 100, 200, 200);
// text("Test Frame!");
button("Test Button Expand!", true);
button("Test Button Expand 2!", true);
rootEnd();
}
}

View File

@ -289,8 +289,8 @@ public class BuildTab extends Tab implements ISelectionChangeListener, IMouseCap
public void mouseUp(int button) {}
@Override
public Vector4f getGuiBox() {
return new Vector4f(padding, 576 - BottomBar.bottomBarHeight - padding - height, width, height);
public List<Vector4f> getGuiBoxes() {
return List.of(new Vector4f(padding, 576 - BottomBar.bottomBarHeight - padding - height, width, height));
}
@Override

View File

@ -1,6 +1,8 @@
package xyz.valnet.hadean.input;
import static xyz.valnet.engine.util.Math.lerp;
import static xyz.valnet.engine.util.Math.*;
import java.util.List;
import xyz.valnet.engine.graphics.Drawing;
import xyz.valnet.engine.graphics.Tile9;
@ -222,8 +224,8 @@ public class Button extends GameObject implements IMouseCaptureArea, ITransient
}
@Override
public Vector4f getGuiBox() {
return new Vector4f(x, y, width, height);
public List<Vector4f> getGuiBoxes() {
return List.of(new Vector4f(x, y, width, height));
}
@Override

View File

@ -45,7 +45,7 @@ public class GameScene extends SceneGraph {
}
objects.add(new SelectionLayer());
objects.add(new SelectionUI());
// objects.add(new SelectionUI());
objects.add(new BuildLayer());
@ -59,7 +59,7 @@ public class GameScene extends SceneGraph {
objects.add(new SaveTab());
objects.add(new LoadTab());
// objects.add(new Popup());
objects.add(new Popup());
}
}