Skip to content

Commit fb02e48

Browse files
author
Benjamin Yap
committed
Implement GUI element priority rendering in Panel
Panels store GUI elements in a List with elements of the same priority, and they are stored in a HashMap with their respective priorities. Panels hold a list of sorted elements which is updated every time an element is added or removed.
1 parent 1def220 commit fb02e48

File tree

5 files changed

+120
-44
lines changed

5 files changed

+120
-44
lines changed

src/com/bwyap/engine/gui/GUIInterface.java

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
package com.bwyap.engine.gui;
22

3-
import java.util.List;
4-
53
import com.bwyap.engine.gui.interfaces.GUIElementInterface;
64
import com.bwyap.engine.input.InputHandler;
75

@@ -44,10 +42,4 @@ public interface GUIInterface {
4442
*/
4543
public boolean removeElement(GUIElementInterface e);
4644

47-
48-
/**
49-
* Gets all GUI elements in this GUI.
50-
* @return
51-
*/
52-
public List<GUIElementInterface> getElements();
5345
}

src/com/bwyap/engine/gui/element/base/Panel.java

Lines changed: 105 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
package com.bwyap.engine.gui.element.base;
22

33
import java.util.ArrayList;
4+
import java.util.Collections;
5+
import java.util.HashMap;
6+
import java.util.Iterator;
47
import java.util.List;
8+
import java.util.Map;
59

610
import com.bwyap.engine.gui.element.properties.VectorShapeColourProperties;
711
import com.bwyap.engine.gui.interfaces.GUIBoundsInterface;
@@ -18,21 +22,33 @@
1822
* @author bwyap
1923
*
2024
*/
21-
public abstract class Panel extends SelectableElement implements IColouredVectorShape {
25+
public abstract class Panel extends SelectableElement implements IColouredVectorShape, Iterable<GUIElementInterface>, Iterator<GUIElementInterface> {
26+
27+
protected static final int DEFAULT_PRIORITY = 100;
2228

23-
protected List<GUIElementInterface> elements;
2429
protected final VectorShapeColourProperties colours;
25-
30+
2631
private boolean renderShape;
2732
private boolean clip;
2833

34+
// Use a hash map to keep track of GUI elements with given priorities
35+
private final Map<Integer, List<GUIElementInterface>> elements;
36+
37+
// Auxiliary variables for keeping track of GUI elements with given priorities
38+
private int elementCount = 0;
39+
private int iteratorNext = 0;
40+
private boolean elementsModified = false;
41+
private List<GUIElementInterface> sortedElements;
42+
2943

3044
public Panel(float x, float y, float width, float height) {
3145
super(x, y, width, height);
3246
colours = new VectorShapeColourProperties();
33-
elements = new ArrayList<GUIElementInterface>();
3447
renderShape = true;
3548
clip = true;
49+
50+
elements = new HashMap<Integer, List<GUIElementInterface>>();
51+
sortedElements = new ArrayList<GUIElementInterface>();
3652
}
3753

3854

@@ -43,43 +59,73 @@ public VectorShapeColourProperties colourProperties() {
4359

4460

4561
/**
46-
* Add an element to the panel at the given co-ordinates.
47-
* Co-ordinates are relative to the panel.
62+
* Add an element to the panel at the given co-ordinates
63+
* with the default priority. Co-ordinates are relative to the panel.
4864
* @param e
4965
*/
5066
public void addElement(GUIElementInterface e, float x, float y) {
5167
e.setPosition(x, y);
52-
elements.add(e);
68+
addElement(DEFAULT_PRIORITY, e);
69+
}
70+
71+
/**
72+
* Add an element to the panel at the given co-ordinates
73+
* with the specified priority. Co-ordinates are relative to the panel.
74+
* @param e
75+
*/
76+
public void addElement(int priority, GUIElementInterface e, float x, float y) {
77+
e.setPosition(x, y);
78+
addElement(priority, e);
5379
}
5480

5581

5682
/**
57-
* Add an element to the panel.
83+
* Add an element to the panel with the default priority (100).
5884
* @param e
5985
*/
6086
public void addElement(GUIElementInterface e) {
61-
elements.add(e);
87+
addElement(DEFAULT_PRIORITY, e);
6288
}
6389

6490

6591
/**
66-
* Removes an element from the panel.
92+
* Add an element to the panel with the specified priority.
93+
* @param priority
6794
* @param e
68-
* @return
6995
*/
70-
public boolean removeElement(GUIElementInterface e) {
71-
return elements.remove(e);
96+
public void addElement(int priority, GUIElementInterface e) {
97+
elementsModified = true;
98+
elementCount++;
99+
if (elements.containsKey(priority)) {
100+
elements.get(priority).add(e);
101+
}
102+
else {
103+
List<GUIElementInterface> list = new ArrayList<GUIElementInterface>();
104+
list.add(e);
105+
elements.put(priority, list);
106+
}
72107
}
73108

74109

110+
75111
/**
76-
* Get the GUI elements in this panel
112+
* Removes an element from the panel.
113+
* @param e
77114
* @return
78115
*/
79-
public List<GUIElementInterface> getElements() {
80-
return elements;
116+
public boolean removeElement(GUIElementInterface e) {
117+
elementsModified = true;
118+
elementCount--;
119+
120+
// Find the element and remove it
121+
for (int k : elements.keySet()) {
122+
if (elements.get(k).contains(e)) {
123+
return elements.get(k).remove(e);
124+
}
125+
}
126+
return false;
81127
}
82-
128+
83129

84130
/**
85131
* Set whether the panel should clip all GUI
@@ -123,47 +169,75 @@ public void onHandleInput(InputHandler input, GUIBoundsInterface bounds) {
123169
setSelected(false);
124170
}
125171

126-
for (GUIElementInterface e : elements) {
127-
e.handleInput(input, this);
128-
}
172+
Iterator<GUIElementInterface> it = iterator();
173+
while (it.hasNext()) {
174+
it.next().handleInput(input, bounds);
175+
}
129176
}
130177

131178

132179
@Override
133180
public final void update(float timestep) {
134-
for (GUIElementInterface e : elements) {
135-
e.update(timestep);
181+
Iterator<GUIElementInterface> it = iterator();
182+
while(it.hasNext()) {
183+
it.next().update(timestep);
136184
}
137185
onUpdate(timestep);
138186
}
139187

188+
189+
@Override
190+
public Iterator<GUIElementInterface> iterator() {
191+
iteratorNext = 0;
192+
193+
// Sort element order if new element has been added
194+
if (elementsModified) {
195+
elementsModified = false;
196+
List<Integer> keys = new ArrayList<Integer>(elements.keySet());
197+
198+
Collections.sort(keys, Collections.reverseOrder());
199+
200+
sortedElements.clear();
201+
for (int k : keys) {
202+
sortedElements.addAll(elements.get(k));
203+
}
204+
}
205+
return this;
206+
}
207+
208+
209+
@Override
210+
public boolean hasNext() {
211+
return iteratorNext < elementCount;
212+
}
213+
214+
215+
@Override
216+
public GUIElementInterface next() {
217+
return sortedElements.get(iteratorNext++);
218+
}
219+
140220

141221
/**
142222
* Override this method for custom update functionality
143223
* @param timestep
144224
*/
145-
public void onUpdate(float timestep) {
146-
147-
}
225+
public void onUpdate(float timestep) { }
148226

149227

150228
/**
151229
* Override this method for custom onSelect functionality
152230
* @param timestep
153231
*/
154232
@Override
155-
public void onSelect() {
156-
157-
}
233+
public void onSelect() { }
158234

159235

160236
/**
161237
* Override this method for custom onDeselect functionality
162238
* @param timestep
163239
*/
164240
@Override
165-
public void onDeselect() {
166-
167-
}
241+
public void onDeselect() { }
168242

169243
}

src/com/bwyap/engine/gui/element/base/ScrollArea.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package com.bwyap.engine.gui.element.base;
22

3+
import java.util.Iterator;
4+
35
import org.joml.Vector2f;
46

57
import com.bwyap.engine.gui.interfaces.GUIBoundsInterface;
@@ -200,7 +202,9 @@ public void updateBounds(BoundsInterface window, Vector2f parent) {
200202
scrollBar.updateBounds(this, parent);
201203

202204
// Set position of GUI elements
203-
for (GUIElementInterface e : elements) {
205+
Iterator<GUIElementInterface> it = iterator();
206+
while (it.hasNext()) {
207+
GUIElementInterface e = it.next();
204208
if (scrollDirection == ScrollDirection.VERTICAL)
205209
e.setPosition(e.getAbsolutePosition().x, e.getAbsolutePosition().y + scrollDelta * SCROLL_SPEED);
206210
else if (scrollDirection == ScrollDirection.HORIZONTAL)

src/com/bwyap/enginedriver/game/test/TestGUI.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ protected void initElements() { }
163163
window.addElement(box2);
164164
window.setReactToMouseOver(false);
165165
window.setResizable(true);
166-
addElement(window);
166+
addElement(1, window);
167167

168168
}
169169

src/com/bwyap/lwjgl/engine/gui/nanovg/NVGRenderer.java

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import static org.lwjgl.nanovg.NanoVG.NVG_ALIGN_TOP;
99
import static org.lwjgl.nanovg.NanoVG.nvgBeginFrame;
1010
import static org.lwjgl.nanovg.NanoVG.nvgBeginPath;
11+
import static org.lwjgl.nanovg.NanoVG.nvgCircle;
1112
import static org.lwjgl.nanovg.NanoVG.nvgEllipse;
1213
import static org.lwjgl.nanovg.NanoVG.nvgEndFrame;
1314
import static org.lwjgl.nanovg.NanoVG.nvgFill;
@@ -18,6 +19,8 @@
1819
import static org.lwjgl.nanovg.NanoVG.nvgGlobalAlpha;
1920
import static org.lwjgl.nanovg.NanoVG.nvgImagePattern;
2021
import static org.lwjgl.nanovg.NanoVG.nvgIntersectScissor;
22+
import static org.lwjgl.nanovg.NanoVG.nvgLineTo;
23+
import static org.lwjgl.nanovg.NanoVG.nvgMoveTo;
2124
import static org.lwjgl.nanovg.NanoVG.nvgRect;
2225
import static org.lwjgl.nanovg.NanoVG.nvgResetScissor;
2326
import static org.lwjgl.nanovg.NanoVG.nvgRoundedRect;
@@ -27,7 +30,6 @@
2730
import static org.lwjgl.nanovg.NanoVG.nvgText;
2831
import static org.lwjgl.nanovg.NanoVG.nvgTextAlign;
2932
import static org.lwjgl.nanovg.NanoVG.nvgTextBox;
30-
import static org.lwjgl.nanovg.NanoVG.*;
3133
import static org.lwjgl.nanovg.NanoVGGL3.NVG_ANTIALIAS;
3234
import static org.lwjgl.nanovg.NanoVGGL3.NVG_STENCIL_STROKES;
3335
import static org.lwjgl.nanovg.NanoVGGL3.nvgCreateGL3;
@@ -41,6 +43,7 @@
4143

4244
import java.util.ArrayList;
4345
import java.util.HashSet;
46+
import java.util.Iterator;
4447
import java.util.Set;
4548

4649
import org.joml.Vector2f;
@@ -168,7 +171,10 @@ public void renderPanel(Panel panel, WindowInterface window, Vector2f parent) {
168171
panel.getBounds().y - panel.getPaddingBottom());
169172
}
170173

171-
for (GUIElementInterface e : panel.getElements()) {
174+
Iterator<GUIElementInterface> it = panel.iterator();
175+
while (it.hasNext()) {
176+
GUIElementInterface e = it.next();
177+
172178
// Update the element's bounds
173179
e.updateBounds(panel, panel.getPosition());
174180

@@ -185,7 +191,7 @@ else if (e instanceof Panel) {
185191
resetAlpha = true;
186192
}
187193
}
188-
194+
189195
// Render any text it may have
190196
if (panel instanceof ITextDisplay) {
191197
renderText(((ITextDisplay)panel).getTextComponent(), panel);

0 commit comments

Comments
 (0)