@@ -183,7 +183,7 @@ public synchronized void setButtonPosition(String logicalId, float x, float y) {
183183 markUpdateNeeded ();
184184 }
185185
186- public Vector2f getButtonPosition (String logicalId ) {
186+ public synchronized Vector2f getButtonPosition (String logicalId ) {
187187 Element element = element (buttons , logicalId );
188188 return new Vector2f (element .positionX , element .positionY );
189189 }
@@ -194,7 +194,7 @@ public synchronized void setButtonVisible(String logicalId, boolean visible) {
194194 markUpdateNeeded ();
195195 }
196196
197- public boolean isButtonVisible (String logicalId ) {
197+ public synchronized boolean isButtonVisible (String logicalId ) {
198198 return element (buttons , logicalId ).visible ;
199199 }
200200
@@ -203,7 +203,7 @@ public synchronized void setAxisPosition(String logicalId, float x, float y) {
203203 markUpdateNeeded ();
204204 }
205205
206- public Vector2f getAxisPosition (String logicalId ) {
206+ public synchronized Vector2f getAxisPosition (String logicalId ) {
207207 Element element = axisElement (logicalId );
208208 return new Vector2f (element .positionX , element .positionY );
209209 }
@@ -214,7 +214,7 @@ public synchronized void setAxisVisible(String logicalId, boolean visible) {
214214 markUpdateNeeded ();
215215 }
216216
217- public boolean isAxisVisible (String logicalId ) {
217+ public synchronized boolean isAxisVisible (String logicalId ) {
218218 return axisElement (logicalId ).visible ;
219219 }
220220
@@ -287,11 +287,11 @@ public Element getToggleElement() {
287287 return toggleElement ;
288288 }
289289
290- public Element getButtonElement (String logicalId ) {
290+ public synchronized Element getButtonElement (String logicalId ) {
291291 return buttons .get (logicalId );
292292 }
293293
294- public Element getAxisElement (String logicalId ) {
294+ public synchronized Element getAxisElement (String logicalId ) {
295295 return findAxisElement (logicalId );
296296 }
297297
@@ -386,11 +386,7 @@ public static class Element implements Savable {
386386 volatile float shortOffsetX ;
387387 volatile float shortOffsetY ;
388388 volatile boolean visible = true ;
389- transient volatile float pixelX ;
390- transient volatile float pixelY ;
391- transient volatile float pixelSize ;
392- transient volatile float pixelWidth ;
393- transient volatile float pixelHeight ;
389+ private transient volatile Bounds bounds = Bounds .EMPTY ;
394390 transient volatile float nubX ;
395391 transient volatile float nubY ;
396392 transient Node node ;
@@ -465,18 +461,28 @@ public synchronized Element setIconTextureKey(TextureKey iconTextureKey) {
465461 }
466462
467463 boolean contains (float x , float y ) {
468- return Math .abs (x - pixelX ) <= pixelWidth * 0.5f
469- && Math .abs (y - pixelY ) <= pixelHeight * 0.5f ;
464+ Bounds current = bounds ;
465+ return Math .abs (x - current .x ) <= current .width * 0.5f
466+ && Math .abs (y - current .y ) <= current .height * 0.5f ;
467+ }
468+
469+ void copyBoundsTo (BoundsSnapshot target ) {
470+ Bounds current = bounds ;
471+ target .x = current .x ;
472+ target .y = current .y ;
473+ target .size = current .size ;
474+ target .width = current .width ;
475+ target .height = current .height ;
470476 }
471477
472478 void sync (int width , int height , float scale , boolean pressed ) {
473479 float shortSide = Math .min (width , height );
474480 float scaledShortSide = shortSide * scale ;
475- pixelSize = Math .max (scaledShortSide * size , 1f );
476- pixelWidth = pixelSize * aspect ;
477- pixelHeight = pixelSize ;
478- pixelX = positionX * width + shortOffsetX * scaledShortSide ;
479- pixelY = positionY * height + shortOffsetY * scaledShortSide ;
481+ float pixelSize = Math .max (scaledShortSide * size , 1f );
482+ float pixelWidth = pixelSize * aspect ;
483+ float pixelHeight = pixelSize ;
484+ float pixelX = positionX * width + shortOffsetX * scaledShortSide ;
485+ float pixelY = positionY * height + shortOffsetY * scaledShortSide ;
480486 if (pixelWidth < width ) {
481487 pixelX = FastMath .clamp (pixelX , pixelWidth * 0.5f , width - pixelWidth * 0.5f );
482488 } else {
@@ -562,6 +568,11 @@ void sync(int width, int height, float scale, boolean pressed) {
562568 lastNodeY = pixelY ;
563569 nodePositionSynced = true ;
564570 }
571+ Bounds current = bounds ;
572+ if (current .x != pixelX || current .y != pixelY || current .size != pixelSize
573+ || current .width != pixelWidth || current .height != pixelHeight ) {
574+ publishBounds (pixelX , pixelY , pixelSize , pixelWidth , pixelHeight );
575+ }
565576 }
566577
567578 synchronized void clearVisuals () {
@@ -573,6 +584,7 @@ synchronized void clearVisuals() {
573584 nub = null ;
574585 icon = null ;
575586 text = null ;
587+ publishBounds (0f , 0f , 0f , 0f , 0f );
576588 clearSyncState ();
577589 }
578590
@@ -593,6 +605,38 @@ private void clearSyncState() {
593605 nodePositionSynced = false ;
594606 }
595607
608+ private void publishBounds (float x , float y , float size , float width , float height ) {
609+ bounds = x == 0f && y == 0f && size == 0f && width == 0f && height == 0f
610+ ? Bounds .EMPTY
611+ : new Bounds (x , y , size , width , height );
612+ }
613+
614+ private static final class Bounds {
615+ static final Bounds EMPTY = new Bounds (0f , 0f , 0f , 0f , 0f );
616+
617+ final float x ;
618+ final float y ;
619+ final float size ;
620+ final float width ;
621+ final float height ;
622+
623+ Bounds (float x , float y , float size , float width , float height ) {
624+ this .x = x ;
625+ this .y = y ;
626+ this .size = size ;
627+ this .width = width ;
628+ this .height = height ;
629+ }
630+ }
631+
632+ static final class BoundsSnapshot {
633+ float x ;
634+ float y ;
635+ float size ;
636+ float width ;
637+ float height ;
638+ }
639+
596640 @ Override
597641 public synchronized void write (JmeExporter ex ) throws IOException {
598642 OutputCapsule capsule = ex .getCapsule (this );
0 commit comments