2020import de .geolykt .starloader .api .gui .screen .ReactiveComponent ;
2121import de .geolykt .starloader .api .gui .screen .Screen ;
2222import de .geolykt .starloader .api .gui .screen .ScreenComponent ;
23+ import de .geolykt .starloader .impl .gui .ScreenComponentPositioningMeta .UnmodifableScreenComponentPositoningMetaIterator ;
2324
2425import snoddasmannen .galimulator .GalColor ;
2526
@@ -32,12 +33,14 @@ public class SLScreenWidget extends SLAbstractWidget implements Screen {
3233 /**
3334 * The list of components displayed by the screen instance.
3435 */
35- protected final @ NotNull List <@ NotNull ScreenComponent > components ;
36+ @ NotNull
37+ protected final List <@ NotNull ScreenComponent > components ;
3638
3739 /**
3840 * The colour of the header bar. Usually it is orange, however can be set to a different colour in the constructor.
3941 */
40- protected final @ NotNull GalColor headerColor ;
42+ @ NotNull
43+ protected final GalColor headerColor ;
4144
4245 /**
4346 * The value returned by {@link #isHeadless()}.
@@ -47,7 +50,8 @@ public class SLScreenWidget extends SLAbstractWidget implements Screen {
4750 /**
4851 * The title of the screen. Set in the constructor.
4952 */
50- protected final @ NotNull String title ;
53+ @ NotNull
54+ protected final String title ;
5155
5256 /**
5357 * The width of the screen, set by the constructor.
@@ -59,7 +63,13 @@ public class SLScreenWidget extends SLAbstractWidget implements Screen {
5963 * A dynamic provider for the width of the screen. This has to be null if {@link #width} is a non -1 value, but
6064 * cannot be null if {@link #width} has a -1 value.
6165 */
62- protected final @ Nullable IntSupplier widthProvider ;
66+ @ Nullable
67+ protected final IntSupplier widthProvider ;
68+
69+ @ NotNull
70+ private final List <ScreenComponentPositioningMeta > componentPositioningMeta = new ArrayList <>();
71+
72+ private double lastRenderHeight = Double .NaN ;
6373
6474 /**
6575 * The constructor of this screen instance.
@@ -217,11 +227,7 @@ public boolean isHeadless() {
217227
218228 @ Override
219229 public Iterator <Entry <Vector2 , ScreenComponent >> iterator () {
220- @ SuppressWarnings ("null" )
221- @ NotNull Iterator <ScreenComponent > components = this .components .iterator ();
222- Camera c = getCamera ();
223- int height = (c == null ? getHeight () : (int ) c .viewportHeight );
224- return new SLScreenWidgetIterator (height , isHeadless (), getInnerWidth (), components , true );
230+ return new UnmodifableScreenComponentPositoningMetaIterator (this .componentPositioningMeta );
225231 }
226232
227233 @ Override
@@ -246,31 +252,39 @@ protected final void paintBackground() {
246252 }
247253
248254 protected void renderSLChildComponents () {
255+ @ SuppressWarnings ("null" )
256+ @ NotNull Iterator <ScreenComponent > hackvar = this .components .iterator ();
249257 Camera c = NullUtils .requireNotNull (getCamera (), "The internal camera may not be null in order for draw operations to succeed." );
250- for (Map .Entry <Vector2 , ScreenComponent > component : this ) {
251- Vector2 pos = component .getKey ();
252- component .getValue ().renderAt ((int ) pos .x , (int ) pos .y , c ); // TODO originally the render operation had offsets, but not anymore. Explore why this may have been dumb to remove
258+ int height = getHeight ();
259+ Iterator <Map .Entry <Vector2 , ScreenComponent >> populator = new SLScreenWidgetPopulator (height , isHeadless (), getInnerWidth (), hackvar , false );
260+
261+ componentPositioningMeta .clear ();
262+ lastRenderHeight = height ;
263+ while (populator .hasNext ()) {
264+ Map .Entry <Vector2 , ScreenComponent > componentEntry = populator .next ();
265+ Vector2 pos = componentEntry .getKey ();
266+ ScreenComponent component = componentEntry .getValue ();
267+ int width = component .renderAt ((int ) pos .x , (int ) pos .y , c ); // TODO originally the render operation had offsets, but not anymore. Explore why this may have been dumb to remove. (#getInnerWidth does not make any sense anymore dummy.)
268+ componentPositioningMeta .add (new ScreenComponentPositioningMeta (pos , width , component .getHeight (), component ));
253269 }
254270 }
255271
256272 @ Override
257273 protected void tap (double x , double y , boolean isLongTap ) {
258- Camera c = NullUtils .requireNotNull (getCamera (), "Camera may not be null." );
259- for (Map .Entry <Vector2 , ScreenComponent > component : this ) {
260- // For galimulator, y = 0, x = 0 is the lower left edge, positive numbers go more towards the upper right.
261- // We follow the same principle within our screen API.
262- ScreenComponent comp = component .getValue ();
263- if (!(comp instanceof ReactiveComponent )) {
274+ Camera c = NullUtils .requireNotNull (getCamera ());
275+ double actualY = lastRenderHeight - y - 25.0D ; // GDX and galimulator are a bit strange, but it makes sense once you get the gist.
276+ for (ScreenComponentPositioningMeta posMeta : this .componentPositioningMeta ) {
277+ if (!(posMeta .component instanceof ReactiveComponent )) {
264278 continue ;
265279 }
266- Vector2 pos = component . getKey () ;
267- if (( x >= pos . x && x <= pos . x + comp . getWidth ())
268- && ( y < = pos .y && y > = pos .y - comp . getHeight ())) {
269- // FIXME galimulator provides values that I did not expect. Was my initial reverse-engineering wrong?
280+ ReactiveComponent component = ( ReactiveComponent ) posMeta . component ;
281+ Vector2 pos = posMeta . pos ;
282+ if (( x > = pos .x && x < = pos .x + posMeta . width )
283+ && ( pos . y <= actualY && ( pos . y + posMeta . height ) >= actualY )) {
270284 if (isLongTap ) {
271- (( ReactiveComponent ) comp ) .onLongClick ((int ) (x - pos .x ), (int ) (y - pos .y ) + comp . getHeight ( ), (int ) pos .x , (int ) pos .y , c );
285+ component .onLongClick ((int ) (x - pos .x ), (int ) (posMeta . height - ( actualY - pos .y )), (int ) pos .x , (int ) pos .y , c );
272286 } else {
273- (( ReactiveComponent ) comp ) .onClick ((int ) (x - pos .x ), (int ) (y - pos .y ) + comp . getHeight ( ), (int ) pos .x , (int ) pos .y , c );
287+ component .onClick ((int ) (x - pos .x ), (int ) (posMeta . height - ( actualY - pos .y )), (int ) pos .x , (int ) pos .y , c );
274288 }
275289 }
276290 }
0 commit comments