diff --git a/src/main/java/de/extio/game_engine/renderer/g2d/control/G2DDrawControl.java b/src/main/java/de/extio/game_engine/renderer/g2d/control/G2DDrawControl.java index da05b5b..bc2f318 100644 --- a/src/main/java/de/extio/game_engine/renderer/g2d/control/G2DDrawControl.java +++ b/src/main/java/de/extio/game_engine/renderer/g2d/control/G2DDrawControl.java @@ -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.bo.ControlRenderingBo; 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.spatial2.SpatialUtils2; import de.extio.game_engine.spatial2.model.Area2; 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) @Component @@ -67,6 +68,12 @@ public class G2DDrawControl extends G2DAbstractRenderingBo implements ControlRen private String tooltip; + private Area2 visibleArea = null; + + private Area2 controlArea = null; + + private final Area2 tempArea = new Area2(MutableCoordI2.create(), MutableCoordI2.create()); + public G2DDrawControl() { super(RenderingBoLayer.UI0); } @@ -137,13 +144,33 @@ public class G2DDrawControl extends G2DAbstractRenderingBo implements ControlRen 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 public void render(final Graphics2D graphics, final double scaleFactor, final boolean force) { 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)); - final var visibleArea = new Area2(ImmutableCoordI2.create(this.visibleAreaX, this.visibleAreaY), ImmutableCoordI2.create(this.visibleAreaWidth, this.visibleAreaHeight)); - final var intersection = SpatialUtils2.intersectAreas(controlArea, visibleArea); - if (intersection == null) { + if (this.controlArea == null || + this.controlArea.getPosition().getX() != this.x || + this.controlArea.getPosition().getY() != this.y || + 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; } } @@ -216,7 +243,7 @@ public class G2DDrawControl extends G2DAbstractRenderingBo implements ControlRen LOGGER.debug("Added control " + control.toString()); } - + this.setControlProps(control, scaleFactor); control.setMainFrameGraphics(graphics); control.setInUse(true); @@ -347,6 +374,8 @@ public class G2DDrawControl extends G2DAbstractRenderingBo implements ControlRen this.visible = o.visible; this.enabled = o.enabled; 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.enabled = true; this.tooltip = null; + this.visibleArea = null; + this.controlArea = null; } @Override diff --git a/src/main/java/de/extio/game_engine/spatial2/SpatialUtils2.java b/src/main/java/de/extio/game_engine/spatial2/SpatialUtils2.java index 735c041..cb253e8 100644 --- a/src/main/java/de/extio/game_engine/spatial2/SpatialUtils2.java +++ b/src/main/java/de/extio/game_engine/spatial2/SpatialUtils2.java @@ -1,6 +1,5 @@ package de.extio.game_engine.spatial2; -import java.awt.Rectangle; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -188,19 +187,16 @@ public final class SpatialUtils2 { */ // @Deprecated 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 CoordI2 size1 = ImmutableCoordI2.create(r1.getC1().getX() - r1.getC0().getX(), r1.getC1().getY() - r1.getC0().getY()); - final var rect0 = new Rectangle(r0.getC0().getX(), r0.getC0().getY(), size0.getX(), size0.getY()); - final var rect1 = new Rectangle(r1.getC0().getX(), r1.getC0().getY(), size1.getX(), size1.getY()); - - final var intersection = rect0.intersection(rect1); - if (intersection.isEmpty()) { + final Area2 a0 = new Area2(r0.getC0(), r0.getC1().toImmutableCoordI2().substract(r0.getC0())); + final Area2 a1 = new Area2(r1.getC0(), r1.getC1().toImmutableCoordI2().substract(r1.getC0())); + final Area2 intersection = new Area2(MutableCoordI2.create(), MutableCoordI2.create()); + final boolean intersects = SpatialUtils2.intersectAreasMutable(a0, a1, intersection); + if (!intersects) { return null; } - return new RectI2( - ImmutableCoordI2.create((int) intersection.getX(), (int) intersection.getY()), - ImmutableCoordI2.create((int) (intersection.getX() + intersection.getWidth()), (int) (intersection.getY() + intersection.getHeight()))); + intersection.getPosition().toImmutableCoordI2(), + 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 */ 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 var rect1 = new Rectangle(a1.getPosition().getX(), a1.getPosition().getY(), a1.getDimension().getX(), a1.getDimension().getY()); - - final var intersection = rect0.intersection(rect1); - if (intersection.isEmpty()) { + final Area2 intersection = new Area2(MutableCoordI2.create(), MutableCoordI2.create()); + final boolean intersects = SpatialUtils2.intersectAreasMutable(a0, a1, intersection); + if (!intersects) { return null; } + intersection.setPosition(intersection.getPosition().toImmutableCoordI2()); + intersection.setDimension(intersection.getDimension().toImmutableCoordI2()); + return intersection; + } + + /** + * Intersects 2 areas and writes the result into a mutable result area + * @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); - return new Area2( - ImmutableCoordI2.create((int) intersection.getX(), (int) intersection.getY()), - ImmutableCoordI2.create((int) intersection.getWidth(), (int) intersection.getHeight())); + mutableResult.getPosition().setXY(tx1, ty1); + mutableResult.getDimension().setXY((int) tx2, (int) ty2); + return (tx2 > 0) && (ty2 > 0); } /**