feat(renderer): enhance G2DDrawControl with visible area management and optimize intersection checks in SpatialUtils2

This commit is contained in:
extio-de
2025-12-31 12:13:58 +01:00
parent 87c3444d90
commit 6fafc81e53
2 changed files with 85 additions and 25 deletions

View File

@@ -29,11 +29,12 @@ import de.extio.game_engine.renderer.model.RenderingBo;
import de.extio.game_engine.renderer.model.RenderingBoLayer; import de.extio.game_engine.renderer.model.RenderingBoLayer;
import de.extio.game_engine.renderer.model.bo.ControlRenderingBo; import de.extio.game_engine.renderer.model.bo.ControlRenderingBo;
import de.extio.game_engine.renderer.model.bo.HorizontalAlignment; import de.extio.game_engine.renderer.model.bo.HorizontalAlignment;
import de.extio.game_engine.renderer.model.color.RgbaColor;
import de.extio.game_engine.resource.StaticResource; import de.extio.game_engine.resource.StaticResource;
import de.extio.game_engine.spatial2.SpatialUtils2; import de.extio.game_engine.spatial2.SpatialUtils2;
import de.extio.game_engine.spatial2.model.Area2; import de.extio.game_engine.spatial2.model.Area2;
import de.extio.game_engine.spatial2.model.ImmutableCoordI2; import de.extio.game_engine.spatial2.model.ImmutableCoordI2;
import de.extio.game_engine.renderer.model.color.RgbaColor; import de.extio.game_engine.spatial2.model.MutableCoordI2;
@Conditional(G2DRendererCondition.class) @Conditional(G2DRendererCondition.class)
@Component @Component
@@ -67,6 +68,12 @@ public class G2DDrawControl extends G2DAbstractRenderingBo implements ControlRen
private String tooltip; private String tooltip;
private Area2 visibleArea = null;
private Area2 controlArea = null;
private final Area2 tempArea = new Area2(MutableCoordI2.create(), MutableCoordI2.create());
public G2DDrawControl() { public G2DDrawControl() {
super(RenderingBoLayer.UI0); super(RenderingBoLayer.UI0);
} }
@@ -137,13 +144,33 @@ public class G2DDrawControl extends G2DAbstractRenderingBo implements ControlRen
return this; return this;
} }
@Override
public RenderingBo withVisibleArea(final int x, final int y, final int width, final int height) {
if (this.visibleArea == null ||
this.visibleArea.getPosition().getX() != x ||
this.visibleArea.getPosition().getY() != y ||
this.visibleArea.getDimension().getX() != width ||
this.visibleArea.getDimension().getY() != height) {
this.visibleArea = new Area2(ImmutableCoordI2.create(x, y), ImmutableCoordI2.create(width, height));
super.withVisibleArea(x, y, width, height);
}
return this;
}
@Override @Override
public void render(final Graphics2D graphics, final double scaleFactor, final boolean force) { public void render(final Graphics2D graphics, final double scaleFactor, final boolean force) {
if (visibleAreaX != 0 || visibleAreaY != 0 || visibleAreaWidth != 0 || visibleAreaHeight != 0) { if (visibleAreaX != 0 || visibleAreaY != 0 || visibleAreaWidth != 0 || visibleAreaHeight != 0) {
final var controlArea = new Area2(ImmutableCoordI2.create(this.x, this.y), ImmutableCoordI2.create(this.width, this.height)); if (this.controlArea == null ||
final var visibleArea = new Area2(ImmutableCoordI2.create(this.visibleAreaX, this.visibleAreaY), ImmutableCoordI2.create(this.visibleAreaWidth, this.visibleAreaHeight)); this.controlArea.getPosition().getX() != this.x ||
final var intersection = SpatialUtils2.intersectAreas(controlArea, visibleArea); this.controlArea.getPosition().getY() != this.y ||
if (intersection == null) { this.controlArea.getDimension().getX() != this.width ||
this.controlArea.getDimension().getY() != this.height) {
this.controlArea = new Area2(ImmutableCoordI2.create(this.x, this.y), ImmutableCoordI2.create(this.width, this.height));
}
if (!SpatialUtils2.intersectAreasMutable(this.controlArea, this.visibleArea, this.tempArea)) {
return; return;
} }
} }
@@ -347,6 +374,8 @@ public class G2DDrawControl extends G2DAbstractRenderingBo implements ControlRen
this.visible = o.visible; this.visible = o.visible;
this.enabled = o.enabled; this.enabled = o.enabled;
this.tooltip = o.tooltip; this.tooltip = o.tooltip;
this.visibleArea = o.visibleArea;
this.controlArea = o.controlArea;
} }
} }
@@ -366,6 +395,8 @@ public class G2DDrawControl extends G2DAbstractRenderingBo implements ControlRen
this.visible = false; this.visible = false;
this.enabled = true; this.enabled = true;
this.tooltip = null; this.tooltip = null;
this.visibleArea = null;
this.controlArea = null;
} }
@Override @Override

View File

@@ -1,6 +1,5 @@
package de.extio.game_engine.spatial2; package de.extio.game_engine.spatial2;
import java.awt.Rectangle;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
@@ -188,19 +187,16 @@ public final class SpatialUtils2 {
*/ */
// @Deprecated // @Deprecated
public static RectI2 intersectRectangles(final RectI2 r0, final RectI2 r1) { public static RectI2 intersectRectangles(final RectI2 r0, final RectI2 r1) {
final CoordI2 size0 = ImmutableCoordI2.create(r0.getC1().getX() - r0.getC0().getX(), r0.getC1().getY() - r0.getC0().getY()); final Area2 a0 = new Area2(r0.getC0(), r0.getC1().toImmutableCoordI2().substract(r0.getC0()));
final CoordI2 size1 = ImmutableCoordI2.create(r1.getC1().getX() - r1.getC0().getX(), r1.getC1().getY() - r1.getC0().getY()); final Area2 a1 = new Area2(r1.getC0(), r1.getC1().toImmutableCoordI2().substract(r1.getC0()));
final var rect0 = new Rectangle(r0.getC0().getX(), r0.getC0().getY(), size0.getX(), size0.getY()); final Area2 intersection = new Area2(MutableCoordI2.create(), MutableCoordI2.create());
final var rect1 = new Rectangle(r1.getC0().getX(), r1.getC0().getY(), size1.getX(), size1.getY()); final boolean intersects = SpatialUtils2.intersectAreasMutable(a0, a1, intersection);
if (!intersects) {
final var intersection = rect0.intersection(rect1);
if (intersection.isEmpty()) {
return null; return null;
} }
return new RectI2( return new RectI2(
ImmutableCoordI2.create((int) intersection.getX(), (int) intersection.getY()), intersection.getPosition().toImmutableCoordI2(),
ImmutableCoordI2.create((int) (intersection.getX() + intersection.getWidth()), (int) (intersection.getY() + intersection.getHeight()))); intersection.getPosition().toImmutableCoordI2().add(intersection.getDimension().toImmutableCoordI2()));
} }
/** /**
@@ -210,17 +206,50 @@ public final class SpatialUtils2 {
* @return The intersected area if r0 and r1 overlap, else null * @return The intersected area if r0 and r1 overlap, else null
*/ */
public static Area2 intersectAreas(final HasPositionAndDimension2 a0, final HasPositionAndDimension2 a1) { public static Area2 intersectAreas(final HasPositionAndDimension2 a0, final HasPositionAndDimension2 a1) {
final var rect0 = new Rectangle(a0.getPosition().getX(), a0.getPosition().getY(), a0.getDimension().getX(), a0.getDimension().getY()); final Area2 intersection = new Area2(MutableCoordI2.create(), MutableCoordI2.create());
final var rect1 = new Rectangle(a1.getPosition().getX(), a1.getPosition().getY(), a1.getDimension().getX(), a1.getDimension().getY()); final boolean intersects = SpatialUtils2.intersectAreasMutable(a0, a1, intersection);
if (!intersects) {
final var intersection = rect0.intersection(rect1);
if (intersection.isEmpty()) {
return null; return null;
} }
intersection.setPosition(intersection.getPosition().toImmutableCoordI2());
intersection.setDimension(intersection.getDimension().toImmutableCoordI2());
return intersection;
}
return new Area2( /**
ImmutableCoordI2.create((int) intersection.getX(), (int) intersection.getY()), * Intersects 2 areas and writes the result into a mutable result area
ImmutableCoordI2.create((int) intersection.getWidth(), (int) intersection.getHeight())); * @param r0 Area 0
* @param r1 Area 1
* @param mutableResult Area to write the result into. The position and dimension will be modified in-place and must be mutable.
* @return true if there is no intersection, false otherwise
*/
public static boolean intersectAreasMutable(final HasPositionAndDimension2 a0, final HasPositionAndDimension2 a1, final HasPositionAndDimension2 mutableResult) {
int tx1 = a0.getPosition().getX();
int ty1 = a0.getPosition().getY();
final int rx1 = a1.getPosition().getX();
final int ry1 = a1.getPosition().getY();
long tx2 = tx1 + a0.getDimension().getX();
long ty2 = ty1 + a0.getDimension().getY();
final long rx2 = rx1 + a1.getDimension().getX();
final long ry2 = ry1 + a1.getDimension().getY();
if (tx1 < rx1) {
tx1 = rx1;
}
if (ty1 < ry1) {
ty1 = ry1;
}
if (tx2 > rx2) {
tx2 = rx2;
}
if (ty2 > ry2) {
ty2 = ry2;
}
tx2 = Math.max(Integer.MIN_VALUE, tx2 - tx1);
ty2 = Math.max(Integer.MIN_VALUE, ty2 - ty1);
mutableResult.getPosition().setXY(tx1, ty1);
mutableResult.getDimension().setXY((int) tx2, (int) ty2);
return (tx2 > 0) && (ty2 > 0);
} }
/** /**