JOGL v2.6.0-rc-20250706
JOGL, High-Performance Graphics Binding for Java™ (public API).
HUDShape.java
Go to the documentation of this file.
1/**
2 * Copyright 2024 JogAmp Community. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without modification, are
5 * permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright notice, this list of
8 * conditions and the following disclaimer.
9 *
10 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
11 * of conditions and the following disclaimer in the documentation and/or other materials
12 * provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
15 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
16 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
19 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
21 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
22 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 *
24 * The views and conclusions contained in the software and documentation are those of the
25 * authors and should not be interpreted as representing official policies, either expressed
26 * or implied, of JogAmp Community.
27 */
28package com.jogamp.graph.ui.shapes;
29
30import com.jogamp.graph.curve.Region;
31import com.jogamp.graph.curve.opengl.GLRegion;
32import com.jogamp.graph.ui.Group;
33import com.jogamp.graph.ui.Scene;
34import com.jogamp.graph.ui.Shape;
35import com.jogamp.graph.ui.layout.Alignment;
36import com.jogamp.graph.ui.layout.BoxLayout;
37import com.jogamp.graph.ui.layout.Padding;
38import com.jogamp.math.Vec2f;
39import com.jogamp.math.Vec3f;
40import com.jogamp.math.Vec4f;
41import com.jogamp.math.geom.AABBox;
42import com.jogamp.math.util.PMVMatrix4f;
43import com.jogamp.opengl.GL2ES2;
44import com.jogamp.opengl.GLProfile;
45import com.jogamp.opengl.util.texture.TextureSequence;
46
47import jogamp.graph.ui.TreeTool;
48
49/**
50 * A Head Up Display (HUD) {@link Shape} for a client {@link Shape} using `inner size and Mv position` to be displayed on top in a {@link Scene}.
51 * <p>
52 * Purpose of this class is to provide a convenient tool to create a HUD within {@link Scene}
53 * using a Mv-coordinates and size of a target shape within the tree w/o manually transforming them to {@link Scene}.
54 * </p>
55 * <p>
56 * Further, the client shape is wrapped in a layout group, not mutating it and hence allowing it for DAG usage.
57 * </p>
58 * <p>
59 * This instance determines initial size and position in {@link #validate(GL2ES2)}, having a valid target shape.
60 * </p>
61 */
62public class HUDShape extends Group {
63 private final boolean hasFrame;
64 private final Vec2f clientSize = new Vec2f();
65 private final Vec3f clientPos = new Vec3f();
66 private final Vec4f backColor = new Vec4f(0.9f, 0.9f, 0.9f, 0.9f);
67 private final Vec4f frontColor = new Vec4f(0.1f, 0.1f, 0.1f, 0.9f);
68 private final Rectangle frame;
69 private final Scene scene;
70 /** Target shape this HUD is put on top */
71 private final Shape targetShape;
72 /** Shape of this HUD */
73 private Shape clientShape;
74
75 private static final boolean DEBUG = false;
76
77 /**
78 * Ctor of {@link HUDShape}.
79 * <p>
80 * Adjust HUD position using {@code targetShape} object Mv-space coordinates via {@link #moveToHUDPos(Vec3f)} and {@link #moveHUDPos(Vec3f)}.
81 * </p>
82 * @param scene the {@link Scene} top-level container
83 * @param clientWidth width of this HUD in given {@code targetShape} object Mv-space, not {@code scene}.
84 * @param clientHeight height of this HUD in given {@code targetShape} object Mv-space, not {@code scene}.
85 * @param renderModes Graph's {@link Region} render modes, see {@link GLRegion#create(GLProfile, int, TextureSequence) create(..)}.
86 * @param targetShape target {@link Shape} this HUD is put on top, used to resolve the Mv matrix for HUD size and position
87 * @param clientShape client {@link Shape} to be presented in the HUD tip
88 */
89 public HUDShape(final Scene scene, final float clientWidth, final float clientHeight,
90 final int renderModes, final Shape targetShape, final Shape clientShape) {
91 this(scene, clientWidth, clientHeight, null, null, 0, null, renderModes, targetShape, clientShape);
92 }
93 /**
94 * Ctor of {@link HUDShape}.
95 * <p>
96 * Adjust HUD position using {@code targetShape} object Mv-space coordinates via {@link #moveToHUDPos(Vec3f)} and {@link #moveHUDPos(Vec3f)}.
97 * </p>
98 * @param scene the {@link Scene} top-level container
99 * @param clientWidth width of this HUD in given {@code targetShape} object Mv-space, not {@code scene}.
100 * @param clientHeight height of this HUD in given {@code targetShape} object Mv-space, not {@code scene}.
101 * @param backColor optional background color, will add a frame to this HUD if not {@code null}
102 * @param borderColor optional border color, only used with {@code backColor}
103 * @param borderThickness border thickness, only used with {@code backColor}
104 * @param padding optional padding for the given {@code clientShape} for the internal wrapper group
105 * @param renderModes Graph's {@link Region} render modes, see {@link GLRegion#create(GLProfile, int, TextureSequence) create(..)}.
106 * @param targetShape target {@link Shape} this HUD is put on top, used to resolve the Mv matrix for HUD size and position
107 * @param clientShape client {@link Shape} to be presented in the HUD tip
108 */
109 public HUDShape(final Scene scene, final float clientWidth, final float clientHeight,
110 final Vec4f backColor, final Vec4f borderColor, final float borderThickness,
111 final Padding padding, final int renderModes, final Shape targetShape, final Shape clientShape) {
112 super();
113 this.hasFrame = null != backColor;
114 this.clientSize.set(clientWidth, clientHeight);
115 if( hasFrame ) {
116 this.backColor.set(backColor);
117 }
118 if( null != frontColor ) {
119 this.frontColor.set(frontColor);
120 }
121 this.scene = scene;
122 this.targetShape = targetShape;
123 this.clientShape = clientShape;
124
125 if( hasFrame ) {
126 frame = (Rectangle) new Rectangle(renderModes, 1, 1, 0).setColor(backColor)
127 .setBorder(borderThickness).setBorderColor(frontColor)
128 .setName("HUD.frame").move(0, 0, -scene.getZEpsilon(16));
129 addShape(frame.setInteractive(false));
130 } else {
131 frame = null;
132 }
133
134 // wrapper ensures user 'clientShape' won't get mutated (scale, move) for DAG
135 final Group wrapper = new Group("HUD.wrapper", null, null, clientShape);
136 if( null != padding ) {
137 wrapper.setPaddding(padding);
138 }
139 addShape(wrapper);
140 setName("HUD");
142 }
143
144 @Override
145 protected void validateImpl(final GL2ES2 gl, final GLProfile glp) {
146 if( isShapeDirty() ) {
147 targetShape.validate(gl, glp);
148
149 final PMVMatrix4f pmv = new PMVMatrix4f();
150
151 tmpB0.reset().setSize(clientPos, tmpV0.set(clientPos).add(clientSize.x(), clientSize.y(), 0));
152 final Vec3f hudSize = tmpV0;
153 final Vec3f hudPos = tmpV1;
154 final AABBox targetHUDBox = new AABBox();
155 TreeTool.forOne(scene, pmv, targetShape, () -> {
156 targetShape.getBounds().transform(pmv.getMv(), targetHUDBox);
157 tmpB0.transform(pmv.getMv(), tmpB1);
158 hudSize.set(tmpB1.getWidth(), tmpB1.getHeight(), 0);
159 hudPos.set(tmpB1.getLow());
160 });
161 hudPos.add(0, 0, scene.getActiveTopLevelZOffsetScale()*scene.getZEpsilon(16));
162 final AABBox sb = scene.getBounds();
163 if( hudPos.x() < sb.getMinX() ) {
164 hudPos.setX( sb.getMinX() );
165 } else if( hudPos.x() + hudSize.x() > sb.getMaxX() ) {
166 hudPos.setX( sb.getMaxX() - hudSize.x() );
167 }
168 if( hudPos.y() < sb.getMinY() ) {
169 hudPos.setY( sb.getMinY() );
170 } else if( hudPos.y() + hudSize.y() > sb.getMaxY() ) {
171 hudPos.setY( sb.getMaxY() - hudSize.y() );
172 }
173 if( DEBUG ) {
174 System.err.println("HUD validate");
175 System.err.println("HUD Target b "+targetShape.getBounds());
176 System.err.println("HUD Scene b "+scene.getBounds());
177 }
178
179 if( !hudSizeOld.isEqual(hudSize) || null == this.getLayout() ) {
180 if( DEBUG ) {
181 System.err.println("HUD size.1 "+clientSize+" -> "+hudSize);
182 }
183 this.setLayout(new BoxLayout(hudSize.x(), hudSize.y(), Alignment.FillCenter));
184 hudSizeOld.set(hudSize);
185 } else if( DEBUG ) {
186 System.err.println("HUD size.0 "+clientSize+" -> "+hudSize);
187 }
188 this.moveTo(hudPos);
189
190 super.validateImpl(gl, glp);
191 if( DEBUG ) {
192 System.err.println("HUD client b "+clientShape.getBounds());
193 System.err.println("HUD this b "+this.getBounds());
194 System.err.println("HUD pos "+clientPos+" -> "+hudPos);
195 }
196 }
197 }
198 private final Vec3f hudSizeOld = new Vec3f();
199 private final AABBox tmpB0 = new AABBox();
200 private final AABBox tmpB1 = new AABBox();
201 private final Vec3f tmpV0 = new Vec3f();
202 private final Vec3f tmpV1 = new Vec3f();
203
204 /**
205 * Move to scaled HUD position with given {@code clientPos} in {@code targetShape} object Mv-space coordinates. See {@link #moveTo(Vec3f)}.
206 * @see #moveHUDPos(Vec3f)
207 */
208 public HUDShape moveToHUDPos(final Vec3f clientPos) {
209 this.clientPos.set(clientPos);
210 this.markShapeDirty();
211 return this;
212 }
213 /**
214 * Move about scaled HUD position with given {@code clientDelta} in {@code targetShape} object Mv-space coordinates. See {@link #move(Vec3f)}.
215 * @see #moveToHUDPos(Vec3f)
216 */
217 public HUDShape moveHUDPos(final Vec3f clientDelta) {
218 this.clientPos.add(clientDelta);
219 this.markShapeDirty();
220 return this;
221 }
222
223 /** Sets the client {@link Shape} size of this HUD in given {@code targetShape} object Mv-space, not {@link Scene}. */
224 public HUDShape setClientSize(final float clientWidth, final float clientHeight) {
225 this.clientSize.set(clientWidth, clientHeight);
226 this.markShapeDirty();
227 return this;
228 }
229 /** Returns the client {@link Shape} size of this HUD in given {@code targetShape} object Mv-space, not {@link Scene}. */
230 public Vec2f getClientSize() { return this.clientSize; }
231 /** Returns the client {@link Shape} position of this HUD in given {@code targetShape} object Mv-space, not {@link Scene}. */
232 public Vec3f getClientPos() { return this.clientPos; }
233 /** Returns the client {@link Shape} to be presented in the HUD tip */
234 public Shape getClientShape() { return this.clientShape; }
235 /** Returns the target {@link Shape} this HUD is put on top, used to resolve the Mv matrix for HUD size and position */
236 public Shape getTargetShape() { return this.targetShape; }
237
238 /**
239 * Removed the user provided client {@link Shape} from this HUD.
240 * <p>
241 * This allows the user to release its own passed client {@link Shape} back, e.g. before destruction.
242 * </p>
243 * @param tip created tip {@link Shape} via {@link #createTip(Scene, AABBox)}
244 * @return the user provided client {@link Shape}
245 */
247 final Shape cs = clientShape;
248 clientShape = null;
249 if( null != cs ) {
250 final Group tipWrapper = (Group)getShapeByIdx(1);
251 if( null == tipWrapper.removeShape(cs) ) {
252 System.err.println("HUDShape.destroyTip: Warning: ClientShape "+cs.getName()+" not contained in "+tipWrapper.getName()+"; Internal Group: ");
253 TreeTool.forAll(this, (final Shape s) -> {
254 System.err.println("- "+s.getName());
255 return false;
256 });
257 }
258 }
259 return cs;
260 }
261
262}
Group of Shapes, optionally utilizing a Group.Layout.
Definition: Group.java:61
Group()
Create a group of Shapes w/o Group.Layout.
Definition: Group.java:106
Shape getShapeByIdx(final int id)
Definition: Group.java:670
void addShape(final Shape s)
Adds a Shape.
Definition: Group.java:225
Shape removeShape(final Shape s)
Removes given shape, w/o Shape#destroy(GL2ES2, RegionRenderer).
Definition: Group.java:253
Group setLayout(final Layout l)
Set Group.Layout.
Definition: Group.java:153
boolean isShapeDirty()
Returns the shape's dirty state, see markShapeDirty().
Definition: Group.java:561
GraphUI Scene.
Definition: Scene.java:102
float getActiveTopLevelZOffsetScale()
Returns the general top-level widget Z-Offset scale, defaults to DEFAULT_ACTIVE_ZOFFSET_SCALE.
Definition: Scene.java:930
static float getZEpsilon(final int zBits, final PMVMatrixSetup setup)
Default Z precision on 16-bit depth buffer using -1 z-position and DEFAULT_ZNEAR.
Definition: Scene.java:126
AABBox getBounds(final PMVMatrix4f pmv, final Shape shape)
Returns AABBox dimension of given Shape from this container's perspective, i.e.
Definition: Scene.java:676
Generic Shape, potentially using a Graph via GraphShape or other means of representing content.
Definition: Shape.java:87
Shape setColor(final float r, final float g, final float b, final float a)
Set base color.
Definition: Shape.java:1389
Shape setName(final String name)
Set a symbolic name for this shape for identification.
Definition: Shape.java:339
final String getName()
Return the optional symbolic name for this shape, defaults to noname.
Definition: Shape.java:341
final Shape move(final float dtx, final float dty, final float dtz)
Move about scaled distance.
Definition: Shape.java:557
final Shape setInteractive(final boolean v)
Set whether this shape is interactive in general, i.e.
Definition: Shape.java:1711
final Shape moveTo(final float tx, final float ty, final float tz)
Move to scaled position.
Definition: Shape.java:543
final AABBox getBounds()
Returns the unscaled bounding AABBox for this shape, borrowing internal instance.
Definition: Shape.java:732
final Shape validate(final GL2ES2 gl)
Validates the shape's underlying GLRegion.
Definition: Shape.java:850
final void markShapeDirty()
Marks the shape dirty, causing next draw() to recreate the Graph shape and reset the region.
Definition: Shape.java:688
final Shape setPaddding(final Padding padding)
Sets the unscaled padding for this shape, which is included in unscaled getBounds() and also includes...
Definition: Shape.java:376
final Shape setBorderColor(final float r, final float g, final float b, final float a)
Set border color.
Definition: Shape.java:1489
final Shape setBorder(final float thickness)
Sets the thickness of the border, which is included in getBounds() and is outside of getPadding().
Definition: Shape.java:402
Immutable layout alignment options, including Bit#Fill.
Definition: Alignment.java:35
static final Alignment FillCenter
Bit#Fill, Bit#CenterHoriz and Bit#CenterVert alignment constant.
Definition: Alignment.java:45
GraphUI Stack Group.Layout.
Definition: BoxLayout.java:53
GraphUI CSS property Padding, unscaled space belonging to the element and included in the element's s...
Definition: Padding.java:38
A Head Up Display (HUD) Shape for a client Shape using inner size and Mv position to be displayed on ...
Definition: HUDShape.java:62
void validateImpl(final GL2ES2 gl, final GLProfile glp)
Definition: HUDShape.java:145
Shape getClientShape()
Returns the client Shape to be presented in the HUD tip.
Definition: HUDShape.java:234
Vec2f getClientSize()
Returns the client Shape size of this HUD in given targetShape object Mv-space, not Scene.
Definition: HUDShape.java:230
Shape removeClient()
Removed the user provided client Shape from this HUD.
Definition: HUDShape.java:246
HUDShape setClientSize(final float clientWidth, final float clientHeight)
Sets the client Shape size of this HUD in given targetShape object Mv-space, not Scene.
Definition: HUDShape.java:224
Vec3f getClientPos()
Returns the client Shape position of this HUD in given targetShape object Mv-space,...
Definition: HUDShape.java:232
HUDShape moveHUDPos(final Vec3f clientDelta)
Move about scaled HUD position with given clientDelta in targetShape object Mv-space coordinates.
Definition: HUDShape.java:217
HUDShape(final Scene scene, final float clientWidth, final float clientHeight, final Vec4f backColor, final Vec4f borderColor, final float borderThickness, final Padding padding, final int renderModes, final Shape targetShape, final Shape clientShape)
Ctor of HUDShape.
Definition: HUDShape.java:109
HUDShape(final Scene scene, final float clientWidth, final float clientHeight, final int renderModes, final Shape targetShape, final Shape clientShape)
Ctor of HUDShape.
Definition: HUDShape.java:89
HUDShape moveToHUDPos(final Vec3f clientPos)
Move to scaled HUD position with given clientPos in targetShape object Mv-space coordinates.
Definition: HUDShape.java:208
Shape getTargetShape()
Returns the target Shape this HUD is put on top, used to resolve the Mv matrix for HUD size and posit...
Definition: HUDShape.java:236
A GraphUI rectangle GraphShape.
Definition: Rectangle.java:47
2D Vector based upon two float components.
Definition: Vec2f.java:37
void set(final Vec2f o)
this = o, returns this.
Definition: Vec2f.java:73
3D Vector based upon three float components.
Definition: Vec3f.java:37
void setX(final float x)
Definition: Vec3f.java:158
boolean isEqual(final Vec3f o, final float epsilon)
Equals check using a given FloatUtil#EPSILON value and FloatUtil#isEqual(float, float,...
Definition: Vec3f.java:383
void setY(final float y)
Definition: Vec3f.java:159
Vec3f set(final Vec3f o)
this = o, returns this.
Definition: Vec3f.java:79
Vec3f add(final float dx, final float dy, final float dz)
this = this + { dx, dy, dz }, returns this.
Definition: Vec3f.java:239
4D Vector based upon four float components.
Definition: Vec4f.java:37
Vec4f set(final Vec4f o)
this = o, returns this.
Definition: Vec4f.java:67
Axis Aligned Bounding Box.
Definition: AABBox.java:54
final float getWidth()
Definition: AABBox.java:879
final Vec3f getLow()
Returns the minimum left-bottom-far (xyz) coordinate.
Definition: AABBox.java:140
final float getHeight()
Definition: AABBox.java:883
final AABBox reset()
Resets this box to the inverse low/high, allowing the next resize(float, float, float) command to hit...
Definition: AABBox.java:123
final AABBox setSize(final float[] low, final float[] high)
Set size of the AABBox specifying the coordinates of the low and high.
Definition: AABBox.java:173
AABBox transform(final Matrix4f mat, final AABBox out)
Transform this box using the given Matrix4f into out @endiliteral.
Definition: AABBox.java:933
PMVMatrix4f implements the basic computer graphics Matrix4f pack using projection (P),...
final Matrix4f getMv()
Returns the modelview matrix (Mv).
Specifies the the OpenGL profile.
Definition: GLProfile.java:77