feat(renderer): add visible area handling to rendering components for improved clipping
This commit is contained in:
@@ -20,6 +20,9 @@ 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.DrawImageRenderingBo;
|
import de.extio.game_engine.renderer.model.bo.DrawImageRenderingBo;
|
||||||
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.model.Area2;
|
||||||
|
import de.extio.game_engine.spatial2.model.ImmutableCoordI2;
|
||||||
|
|
||||||
@Conditional(G2DRendererCondition.class)
|
@Conditional(G2DRendererCondition.class)
|
||||||
@Component
|
@Component
|
||||||
@@ -172,7 +175,8 @@ public class G2DDrawImage extends G2DAbstractRenderingBo implements DrawImageRen
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void doDraw(final Graphics2D graphics, final CachedImage cachedImage, final double scaleFactor) {
|
private void doDraw(final Graphics2D graphics, final CachedImage cachedImage, final double scaleFactor) {
|
||||||
int x, y;
|
int x, y, w, h;
|
||||||
|
final int visX, visY, visW, visH;
|
||||||
if (this.scaledX != 0 || this.scaledY != 0) {
|
if (this.scaledX != 0 || this.scaledY != 0) {
|
||||||
x = this.scaledX;
|
x = this.scaledX;
|
||||||
y = this.scaledY;
|
y = this.scaledY;
|
||||||
@@ -181,12 +185,48 @@ public class G2DDrawImage extends G2DAbstractRenderingBo implements DrawImageRen
|
|||||||
x = (int) (this.x * scaleFactor);
|
x = (int) (this.x * scaleFactor);
|
||||||
y = (int) (this.y * scaleFactor);
|
y = (int) (this.y * scaleFactor);
|
||||||
}
|
}
|
||||||
|
w = (int) ((this.width > 0 ? this.width : cachedImage.getImage().getWidth()) * scaleFactor);
|
||||||
if (this.width == 0 && this.height == 0) {
|
h = (int) ((this.height > 0 ? this.height : cachedImage.getImage().getHeight()) * scaleFactor);
|
||||||
|
visX = (int) (this.visibleAreaX * scaleFactor);
|
||||||
|
visY = (int) (this.visibleAreaY * scaleFactor);
|
||||||
|
visW = (int) (this.visibleAreaWidth * scaleFactor);
|
||||||
|
visH = (int) (this.visibleAreaHeight * scaleFactor);
|
||||||
|
|
||||||
|
Area2 intersection = null;
|
||||||
|
if (visX != 0 || visY != 0 || visW != 0 || visH != 0) {
|
||||||
|
final var controlArea = new Area2(ImmutableCoordI2.create(x, y), ImmutableCoordI2.create(w, h));
|
||||||
|
final var visibleArea = new Area2(ImmutableCoordI2.create(visX, visY), ImmutableCoordI2.create(visW, visH));
|
||||||
|
intersection = SpatialUtils2.intersectAreas(controlArea, visibleArea);
|
||||||
|
if (intersection == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (intersection != null) {
|
||||||
|
try {
|
||||||
|
final double dstPerSrcX = (double) w / (double) cachedImage.getImage().getWidth();
|
||||||
|
final double dstPerSrcY = (double) h / (double) cachedImage.getImage().getHeight();
|
||||||
|
graphics.drawImage(
|
||||||
|
cachedImage.getImage(),
|
||||||
|
intersection.getPosition().getX(),
|
||||||
|
intersection.getPosition().getY(),
|
||||||
|
intersection.getPosition().getX() + intersection.getDimension().getX(),
|
||||||
|
intersection.getPosition().getY() + intersection.getDimension().getY(),
|
||||||
|
Math.max(0, Math.min(cachedImage.getImage().getWidth(), (int) Math.round((intersection.getPosition().getX() - x) / dstPerSrcX))),
|
||||||
|
Math.max(0, Math.min(cachedImage.getImage().getHeight(), (int) Math.round((intersection.getPosition().getY() - y) / dstPerSrcY))),
|
||||||
|
Math.max(0, Math.min(cachedImage.getImage().getWidth(), (int) Math.round((intersection.getPosition().getX() - x + intersection.getDimension().getX()) / dstPerSrcX))),
|
||||||
|
Math.max(0, Math.min(cachedImage.getImage().getHeight(), (int) Math.round((intersection.getPosition().getY() - y + intersection.getDimension().getY()) / dstPerSrcY))),
|
||||||
|
null);
|
||||||
|
}
|
||||||
|
catch (final Exception e) {
|
||||||
|
LOGGER.error("Error drawing image '" + cachedImage.getName() + "': " + e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (this.width == 0 && this.height == 0) {
|
||||||
graphics.drawImage(cachedImage.getImage(), x, y, null);
|
graphics.drawImage(cachedImage.getImage(), x, y, null);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
graphics.drawImage(cachedImage.getImage(), x, y, (int) (this.width * scaleFactor), (int) (this.height * scaleFactor), null);
|
graphics.drawImage(cachedImage.getImage(), x, y, w, h, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -30,6 +30,9 @@ 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.resource.StaticResource;
|
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.renderer.model.color.RgbaColor;
|
||||||
|
|
||||||
@Conditional(G2DRendererCondition.class)
|
@Conditional(G2DRendererCondition.class)
|
||||||
@@ -136,6 +139,15 @@ public class G2DDrawControl extends G2DAbstractRenderingBo implements ControlRen
|
|||||||
|
|
||||||
@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) {
|
||||||
|
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) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var control = (G2DBaseControlImpl) CACHED_CONTROLS.get(this.id);
|
var control = (G2DBaseControlImpl) CACHED_CONTROLS.get(this.id);
|
||||||
if (control == null) {
|
if (control == null) {
|
||||||
if (this.clazz == ButtonControl.class) {
|
if (this.clazz == ButtonControl.class) {
|
||||||
@@ -173,7 +185,8 @@ public class G2DDrawControl extends G2DAbstractRenderingBo implements ControlRen
|
|||||||
control = new G2DTooltipControl();
|
control = new G2DTooltipControl();
|
||||||
}
|
}
|
||||||
else if (this.clazz == null) {
|
else if (this.clazz == null) {
|
||||||
throw new IllegalArgumentException("G2DDrawControl: control type not specified");
|
LOGGER.warn("G2DDrawControl: control type not specified for control id {}", this.id);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
throw new UnsupportedOperationException("Not implemented " + this.clazz.getName());
|
throw new UnsupportedOperationException("Not implemented " + this.clazz.getName());
|
||||||
@@ -203,7 +216,7 @@ public class G2DDrawControl extends G2DAbstractRenderingBo implements ControlRen
|
|||||||
|
|
||||||
LOGGER.debug("Added control " + control.toString());
|
LOGGER.debug("Added control " + control.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setControlProps(control, scaleFactor);
|
this.setControlProps(control, scaleFactor);
|
||||||
control.setMainFrameGraphics(graphics);
|
control.setMainFrameGraphics(graphics);
|
||||||
control.setInUse(true);
|
control.setInUse(true);
|
||||||
@@ -224,6 +237,11 @@ public class G2DDrawControl extends G2DAbstractRenderingBo implements ControlRen
|
|||||||
control.setTooltip(this.tooltip);
|
control.setTooltip(this.tooltip);
|
||||||
control.setZIndex(this.zIndex);
|
control.setZIndex(this.zIndex);
|
||||||
control.setLayer(this.layer);
|
control.setLayer(this.layer);
|
||||||
|
control.setVisibleArea(
|
||||||
|
(int) (this.visibleAreaX * scaleFactor),
|
||||||
|
(int) (this.visibleAreaY * scaleFactor),
|
||||||
|
(int) (this.visibleAreaWidth * scaleFactor),
|
||||||
|
(int) (this.visibleAreaHeight * scaleFactor));
|
||||||
|
|
||||||
if (this.clazz == LabelControl.class) {
|
if (this.clazz == LabelControl.class) {
|
||||||
((LabelControl) control).setForegroundColor(this.color);
|
((LabelControl) control).setForegroundColor(this.color);
|
||||||
@@ -311,11 +329,11 @@ public class G2DDrawControl extends G2DAbstractRenderingBo implements ControlRen
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void apply(final RenderingBo other) {
|
public void apply(final RenderingBo other) {
|
||||||
super.apply(other);
|
super.apply(other);
|
||||||
|
|
||||||
if (other instanceof final G2DDrawControl o) {
|
if (other instanceof final G2DDrawControl o) {
|
||||||
this.id = o.id;
|
this.id = o.id;
|
||||||
this.clazz = o.clazz;
|
this.clazz = o.clazz;
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import de.extio.game_engine.renderer.g2d.control.G2DDrawControlTooltip.TooltipRe
|
|||||||
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.BaseControl;
|
import de.extio.game_engine.renderer.model.bo.ControlRenderingBo.BaseControl;
|
||||||
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.CoordI2;
|
import de.extio.game_engine.spatial2.model.CoordI2;
|
||||||
import de.extio.game_engine.spatial2.model.ImmutableCoordI2;
|
import de.extio.game_engine.spatial2.model.ImmutableCoordI2;
|
||||||
|
|
||||||
@@ -36,6 +37,14 @@ public abstract class G2DBaseControlImpl implements BaseControl {
|
|||||||
|
|
||||||
protected int fontSize;
|
protected int fontSize;
|
||||||
|
|
||||||
|
protected int visibleAreaX;
|
||||||
|
|
||||||
|
protected int visibleAreaY;
|
||||||
|
|
||||||
|
protected int visibleAreaWidth;
|
||||||
|
|
||||||
|
protected int visibleAreaHeight;
|
||||||
|
|
||||||
protected Graphics2D mainFrameGraphics;
|
protected Graphics2D mainFrameGraphics;
|
||||||
|
|
||||||
protected RendererData rendererData;
|
protected RendererData rendererData;
|
||||||
@@ -67,7 +76,7 @@ public abstract class G2DBaseControlImpl implements BaseControl {
|
|||||||
protected short layer;
|
protected short layer;
|
||||||
|
|
||||||
protected boolean modified;
|
protected boolean modified;
|
||||||
|
|
||||||
protected boolean positionModified;
|
protected boolean positionModified;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -192,11 +201,41 @@ public abstract class G2DBaseControlImpl implements BaseControl {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public G2DBaseControlImpl setVisibleArea(final int x, final int y, final int width, final int height) {
|
||||||
|
this.modified |= this.visibleAreaX != x || this.visibleAreaY != y || this.visibleAreaWidth != width || this.visibleAreaHeight != height;
|
||||||
|
this.visibleAreaX = x;
|
||||||
|
this.visibleAreaY = y;
|
||||||
|
this.visibleAreaWidth = width;
|
||||||
|
this.visibleAreaHeight = height;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void render() {
|
public void render() {
|
||||||
if (this.visible && this.bufferedImage != null) {
|
if (this.visible && this.bufferedImage != null) {
|
||||||
this.mainFrameGraphics.drawImage(this.bufferedImage, this.x, this.y, null);
|
if (this.visibleAreaX == 0 && this.visibleAreaY == 0 && this.visibleAreaWidth == 0 && this.visibleAreaHeight == 0) {
|
||||||
this.drawToolTip();
|
this.mainFrameGraphics.drawImage(this.bufferedImage, this.x, this.y, null);
|
||||||
|
this.drawToolTip();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
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) {
|
||||||
|
this.mainFrameGraphics.drawImage(
|
||||||
|
this.bufferedImage,
|
||||||
|
intersection.getPosition().getX(),
|
||||||
|
intersection.getPosition().getY(),
|
||||||
|
intersection.getPosition().getX() + intersection.getDimension().getX(),
|
||||||
|
intersection.getPosition().getY() + intersection.getDimension().getY(),
|
||||||
|
intersection.getPosition().getX() - this.x,
|
||||||
|
intersection.getPosition().getY() - this.y,
|
||||||
|
intersection.getPosition().getX() - this.x + intersection.getDimension().getX(),
|
||||||
|
intersection.getPosition().getY() - this.y + intersection.getDimension().getY(),
|
||||||
|
null);
|
||||||
|
this.drawToolTip();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.modified) {
|
if (this.modified) {
|
||||||
|
|||||||
@@ -28,6 +28,14 @@ public abstract class AbstractRenderingBo implements RenderingBo {
|
|||||||
protected int width;
|
protected int width;
|
||||||
|
|
||||||
protected int height;
|
protected int height;
|
||||||
|
|
||||||
|
protected int visibleAreaX;
|
||||||
|
|
||||||
|
protected int visibleAreaY;
|
||||||
|
|
||||||
|
protected int visibleAreaWidth;
|
||||||
|
|
||||||
|
protected int visibleAreaHeight;
|
||||||
|
|
||||||
protected short layer;
|
protected short layer;
|
||||||
|
|
||||||
@@ -214,6 +222,14 @@ public abstract class AbstractRenderingBo implements RenderingBo {
|
|||||||
|
|
||||||
return (RenderingBoHasDimension) this;
|
return (RenderingBoHasDimension) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public RenderingBoHasDimension withVisibleArea(final int x, final int y, final int width, final int height) {
|
||||||
|
this.visibleAreaX = x;
|
||||||
|
this.visibleAreaY = y;
|
||||||
|
this.visibleAreaWidth = width;
|
||||||
|
this.visibleAreaHeight = height;
|
||||||
|
return (RenderingBoHasDimension) this;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void close() throws Exception {
|
public void close() throws Exception {
|
||||||
@@ -227,6 +243,10 @@ public abstract class AbstractRenderingBo implements RenderingBo {
|
|||||||
this.height = 0;
|
this.height = 0;
|
||||||
this.layer = this.defaultLayer;
|
this.layer = this.defaultLayer;
|
||||||
this.zIndex = 0;
|
this.zIndex = 0;
|
||||||
|
this.visibleAreaX = 0;
|
||||||
|
this.visibleAreaY = 0;
|
||||||
|
this.visibleAreaWidth = 0;
|
||||||
|
this.visibleAreaHeight = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -242,6 +262,10 @@ public abstract class AbstractRenderingBo implements RenderingBo {
|
|||||||
this.height = abstractRenderingBo.height;
|
this.height = abstractRenderingBo.height;
|
||||||
this.layer = abstractRenderingBo.layer;
|
this.layer = abstractRenderingBo.layer;
|
||||||
this.zIndex = abstractRenderingBo.zIndex;
|
this.zIndex = abstractRenderingBo.zIndex;
|
||||||
|
this.visibleAreaX = abstractRenderingBo.visibleAreaX;
|
||||||
|
this.visibleAreaY = abstractRenderingBo.visibleAreaY;
|
||||||
|
this.visibleAreaWidth = abstractRenderingBo.visibleAreaWidth;
|
||||||
|
this.visibleAreaHeight = abstractRenderingBo.visibleAreaHeight;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ public interface RenderingBoHasDimension extends RenderingBo {
|
|||||||
RenderingBoHasDimension withDimensionAbsolute(HasPosition2 dim);
|
RenderingBoHasDimension withDimensionAbsolute(HasPosition2 dim);
|
||||||
|
|
||||||
RenderingBoHasDimension withDimensionAbsolute(int width, int height);
|
RenderingBoHasDimension withDimensionAbsolute(int width, int height);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param width Range 0.0 (No width) to 1.0 (Viewport width)
|
* @param width Range 0.0 (No width) to 1.0 (Viewport width)
|
||||||
* @param height Range 0.0 (No height) to 1.0 (Viewport height)
|
* @param height Range 0.0 (No height) to 1.0 (Viewport height)
|
||||||
@@ -26,4 +26,6 @@ public interface RenderingBoHasDimension extends RenderingBo {
|
|||||||
RenderingBoHasDimension withDimensionIncrementalAbsolute(int width, int height);
|
RenderingBoHasDimension withDimensionIncrementalAbsolute(int width, int height);
|
||||||
|
|
||||||
RenderingBoHasDimension withDimensionIncrementalPercentual(double width, double height);
|
RenderingBoHasDimension withDimensionIncrementalPercentual(double width, double height);
|
||||||
|
|
||||||
|
RenderingBoHasDimension withVisibleArea(int x, int y, int width, int height);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user