feat(renderer): Refactor resource handling to use StaticResource for icons and backgrounds in rendering components

This commit is contained in:
extio-de
2025-12-26 15:15:00 +01:00
parent 09b0e28c5f
commit 9c12d54341
10 changed files with 117 additions and 78 deletions

View File

@@ -50,7 +50,6 @@ public class Container extends AbstractClientModule implements InitializingBean
this.rendererControl = rendererControl;
this.eventService = eventService;
this.rendererWorkingSet = rendererWorkingSet;
}
@Override

View File

@@ -1,13 +1,10 @@
package de.extio.game_engine.renderer.g2d.bo.rendering;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.awt.image.VolatileImage;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
@@ -24,6 +21,7 @@ import de.extio.game_engine.renderer.model.RenderingBo;
import de.extio.game_engine.renderer.model.RenderingBoLayer;
import de.extio.game_engine.renderer.model.color.ImmutableRgbaColor;
import de.extio.game_engine.renderer.model.color.RgbaColor;
import de.extio.game_engine.resource.StaticResource;
import de.extio.game_engine.spatial2.model.CoordI2;
import de.extio.game_engine.spatial2.model.ImmutableCoordI2;
import de.extio.game_engine.spatial2.model.MutableCoordI2;
@@ -37,7 +35,7 @@ public class G2DDrawBackground extends G2DAbstractRenderingBo {
private static BufferedImage BACKGROUND_BUFFEREDIMAGE;
private static String BACKGROUND_KEY;
private static StaticResource BACKGROUND_KEY;
private final static int[] BUILTIN_SCROLL_OFFSET_X = new int[2];
@@ -62,10 +60,10 @@ public class G2DDrawBackground extends G2DAbstractRenderingBo {
}
@Override
public void apply(RenderingBo other) {
public void apply(final RenderingBo other) {
super.apply(other);
if (other instanceof G2DDrawBackground o) {
if (other instanceof final G2DDrawBackground o) {
this.bgrOffset.setXY(o.bgrOffset);
this.sourceOffset.setXY(o.sourceOffset);
this.destPosition.setXY(o.destPosition);
@@ -95,16 +93,16 @@ public class G2DDrawBackground extends G2DAbstractRenderingBo {
final var windowDim = ((G2DRendererControl) this.rendererData.getRendererControl()).getAbsoluteViewportDimension();
this.scroll(0, this.rendererData.getUiOptions().isBackgroundScrolling0(), this.rendererData.getUiOptions().isBackgroundScrollingReverse0(), windowDim);
this.tileBackground(graphics, 0, this.rendererData.getUiOptions().getBackgroundResourceName0(),
this.tileBackground(graphics, 0, this.rendererData.getUiOptions().getBackgroundResource0(),
this.bgrOffset.setXY(this.rendererData.getUiOptions().getBackgroundOffset0()).add(BUILTIN_SCROLL_OFFSET_X[0], 0), windowDim);
this.scroll(1, this.rendererData.getUiOptions().isBackgroundScrolling1(), this.rendererData.getUiOptions().isBackgroundScrollingReverse1(), windowDim);
this.drawStars(graphics, this.bgrOffset.setXY(this.rendererData.getUiOptions().getBackgroundOffset1()).add(BUILTIN_SCROLL_OFFSET_X[1], 0), windowDim);
}
private void tileBackground(final Graphics2D graphics, final int index, final String backgroundName, final CoordI2 offset, final CoordI2 viewPort) {
if (!Objects.equals(backgroundName, G2DDrawBackground.BACKGROUND_KEY)) {
this.loadImage(graphics, index, backgroundName);
private void tileBackground(final Graphics2D graphics, final int index, final StaticResource backgroundResource, final CoordI2 offset, final CoordI2 viewPort) {
if (!Objects.equals(backgroundResource, G2DDrawBackground.BACKGROUND_KEY)) {
this.loadImage(graphics, index, backgroundResource);
}
if (G2DDrawBackground.BACKGROUND_IMAGE == null) {
return;
@@ -186,7 +184,8 @@ public class G2DDrawBackground extends G2DAbstractRenderingBo {
}
}
private void loadImage(final Graphics2D graphics, final int index, final String backgroundName) {
@SuppressWarnings("resource")
private void loadImage(final Graphics2D graphics, final int index, final StaticResource backgroundResource) {
if (G2DDrawBackground.BACKGROUND_IMAGE != null) {
G2DDrawBackground.BACKGROUND_IMAGE.flush();
G2DDrawBackground.BACKGROUND_BUFFEREDIMAGE.flush();
@@ -196,18 +195,21 @@ public class G2DDrawBackground extends G2DAbstractRenderingBo {
G2DDrawBackground.BACKGROUND_KEY = null;
G2DDrawBackground.BUILTIN_SCROLL_OFFSET_X[index] = 0;
if (backgroundName != null && !backgroundName.isEmpty()) {
try (InputStream stream = new FileInputStream(backgroundName)) {
if (stream != null) {
G2DDrawBackground.BACKGROUND_KEY = backgroundName;
G2DDrawBackground.BACKGROUND_BUFFEREDIMAGE = ImageIO.read(stream);
this.createVolatileBackgroundImage(graphics, index);
if (backgroundResource != null) {
final var in = this.rendererData.getStaticResourceService().loadStreamByPath(backgroundResource);
if (in.isPresent()) {
try (var stream = in.get()) {
if (stream != null) {
G2DDrawBackground.BACKGROUND_KEY = backgroundResource;
G2DDrawBackground.BACKGROUND_BUFFEREDIMAGE = ImageIO.read(stream);
this.createVolatileBackgroundImage(graphics, index);
}
}
catch (final IOException e) {
throw new RuntimeException(e);
}
}
catch (final IOException e) {
throw new RuntimeException(e);
}
}
}

View File

@@ -4,7 +4,6 @@ import java.awt.AlphaComposite;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
@@ -12,7 +11,6 @@ import java.util.Map;
import javax.imageio.ImageIO;
import org.springframework.context.annotation.Conditional;
import org.springframework.stereotype.Component;
@@ -21,6 +19,7 @@ import de.extio.game_engine.renderer.g2d.G2DRendererCondition;
import de.extio.game_engine.renderer.model.RenderingBo;
import de.extio.game_engine.renderer.model.RenderingBoLayer;
import de.extio.game_engine.renderer.model.bo.DrawImageRenderingBo;
import de.extio.game_engine.resource.StaticResource;
@Conditional(G2DRendererCondition.class)
@Component
@@ -28,12 +27,14 @@ public class G2DDrawImage extends G2DAbstractRenderingBo implements DrawImageRen
private static Map<String, CachedImage> IMAGE_CACHE = new HashMap<>();
private String resourceName;
private StaticResource resource;
private float transparency;
private byte[] imageData;
private String imageName;
private int scaledX;
private int scaledY;
@@ -45,8 +46,8 @@ public class G2DDrawImage extends G2DAbstractRenderingBo implements DrawImageRen
}
@Override
public DrawImageRenderingBo setResourceName(final String resourceName) {
this.resourceName = resourceName;
public DrawImageRenderingBo setResource(final StaticResource resource) {
this.resource = resource;
return this;
}
@@ -62,22 +63,32 @@ public class G2DDrawImage extends G2DAbstractRenderingBo implements DrawImageRen
return this;
}
@Override
public DrawImageRenderingBo setImageName(final String name) {
this.imageName = name;
return this;
}
@SuppressWarnings("resource")
@Override
public void render(final Graphics2D graphics, final double scaleFactor, final boolean force) {
var cachedImage = IMAGE_CACHE.get(this.resourceName);
final var key = this.imageName != null && !this.imageName.isBlank() ? this.imageName : this.resource.toString();
var cachedImage = IMAGE_CACHE.get(key);
if (cachedImage == null) {
cachedImage = new CachedImage();
cachedImage.setName(this.resourceName);
cachedImage.setName(key);
if (this.imageData == null) {
try (InputStream stream = new FileInputStream(this.resourceName)) {
if (stream != null) {
cachedImage.setImage(ImageIO.read(stream));
final var in = this.rendererData.getStaticResourceService().loadStreamByPath(this.resource);
if (in.isPresent()) {
try (var stream = in.get()) {
if (stream != null) {
cachedImage.setImage(ImageIO.read(stream));
}
}
catch (final IOException e) {
throw new RuntimeException(e);
}
}
catch (final IOException e) {
throw new RuntimeException(e);
}
}
else {
@@ -90,7 +101,7 @@ public class G2DDrawImage extends G2DAbstractRenderingBo implements DrawImageRen
}
}
IMAGE_CACHE.put(this.resourceName, cachedImage);
IMAGE_CACHE.put(key, cachedImage);
LOGGER.debug("Added image to cache: " + cachedImage.getName());
}
@@ -118,25 +129,27 @@ public class G2DDrawImage extends G2DAbstractRenderingBo implements DrawImageRen
}
@Override
public void apply(RenderingBo other) {
public void apply(final RenderingBo other) {
super.apply(other);
if (other instanceof final G2DDrawImage o) {
this.resourceName = o.resourceName;
this.resource = o.resource;
this.transparency = o.transparency;
this.imageData = o.imageData;
this.imageName = o.imageName;
this.scaledX = o.scaledX;
this.scaledY = o.scaledY;
}
}
@Override
public void close() throws Exception {
super.close();
this.resourceName = null;
this.resource = null;
this.transparency = 1.0f;
this.imageData = null;
this.imageName = null;
this.scaledX = 0;
this.scaledY = 0;
}

View File

@@ -28,6 +28,7 @@ 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.resource.StaticResource;
import de.extio.game_engine.renderer.model.color.RgbaColor;
@Conditional(G2DRendererCondition.class)
@@ -245,8 +246,8 @@ public class G2DDrawControl extends G2DAbstractRenderingBo implements ControlRen
if (this.customData instanceof Boolean) {
((ToggleButtonControl) control).setToggled(((Boolean) this.customData).booleanValue());
}
if (this.customData2 instanceof String) {
((ButtonControl) control).setIconResourceName((String) this.customData2);
if (this.customData2 instanceof StaticResource) {
((ButtonControl) control).setIconResource((StaticResource) this.customData2);
}
}
else if (this.clazz == SwitchControl.class) {
@@ -254,8 +255,8 @@ public class G2DDrawControl extends G2DAbstractRenderingBo implements ControlRen
if (this.customData instanceof Boolean) {
((SwitchControl) control).setToggled(((Boolean) this.customData).booleanValue());
}
if (this.customData2 instanceof String) {
((ButtonControl) control).setIconResourceName((String) this.customData2);
if (this.customData2 instanceof StaticResource) {
((ButtonControl) control).setIconResource((StaticResource) this.customData2);
}
if (this.customData4 instanceof Boolean) {
((SwitchControl) control).setDrawBorder(((Boolean) this.customData4).booleanValue());
@@ -263,8 +264,8 @@ public class G2DDrawControl extends G2DAbstractRenderingBo implements ControlRen
}
else if (this.clazz == ButtonControl.class) {
((ButtonControl) control).setBackgroundColor(this.color);
if (this.customData2 instanceof String) {
((ButtonControl) control).setIconResourceName((String) this.customData2);
if (this.customData2 instanceof StaticResource) {
((ButtonControl) control).setIconResource((StaticResource) this.customData2);
}
}
else if (this.clazz == WindowCloseButtonControl.class) {

View File

@@ -9,12 +9,12 @@ import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.awt.image.BufferedImage;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import javax.imageio.ImageIO;
import de.extio.game_engine.resource.StaticResource;
import de.extio.game_engine.resource.StaticResourceService;
import de.extio.game_engine.spatial2.model.CoordI2;
import de.extio.game_engine.spatial2.model.ImmutableCoordI2;
@@ -41,14 +41,16 @@ public abstract class CustomAbstractButton extends Component {
protected boolean dirty = true;
protected String iconResourceName;
protected StaticResource iconResource;
protected String loadedIconResourceName;
protected StaticResource loadedIconResource;
protected BufferedImage icon;
protected Color backgroundColor;
protected StaticResourceService staticResourceService;
protected CoordI2 lastMousePosition;
public void setCaption(final String caption) {
@@ -86,8 +88,12 @@ public abstract class CustomAbstractButton extends Component {
this.dirty = dirty;
}
public void setIconResourceName(final String iconResourceName) {
this.iconResourceName = iconResourceName;
public void setIconResource(final StaticResource iconResource) {
this.iconResource = iconResource;
}
public void setStaticResourceService(final StaticResourceService staticResourceService) {
this.staticResourceService = staticResourceService;
}
public void setBackgroundColor(final Color backgroundColor) {
@@ -180,20 +186,26 @@ public abstract class CustomAbstractButton extends Component {
this.flushIcon();
}
@SuppressWarnings("resource")
protected void loadIcon() {
if (this.iconResourceName != null) {
this.loadedIconResourceName = this.iconResourceName;
if (this.iconResource != null && this.staticResourceService != null) {
this.loadedIconResource = this.iconResource;
this.flushIcon();
try (InputStream stream = new FileInputStream(this.iconResourceName)) {
this.icon = ImageIO.read(stream);
}
catch (final IOException e) {
throw new RuntimeException(e);
final var in = this.staticResourceService.loadStreamByPath(this.iconResource);
if (in.isPresent()) {
try (var stream = in.get()) {
if (stream != null) {
this.icon = ImageIO.read(stream);
}
}
catch (final IOException e) {
throw new RuntimeException(e);
}
}
if (this.icon == null) {
throw new RuntimeException("Resource not found: " + this.iconResourceName);
throw new RuntimeException("Resource not found: " + this.iconResource);
}
}
}

View File

@@ -63,7 +63,7 @@ public class CustomButton extends CustomAbstractButton {
g2d.setColor(Color.getHSBColor(h, s, b));
g2d.fillRect(2 + bgrStrength, 2 + bgrStrength, this.getWidth() - 5 - bgrStrength * 2, this.getHeight() - 5 - bgrStrength * 2);
if (this.iconResourceName != null && (this.icon == null || !this.iconResourceName.equals(this.loadedIconResourceName))) {
if (this.iconResource != null && (this.icon == null || !this.iconResource.equals(this.loadedIconResource))) {
this.loadIcon();
}
if (this.icon != null) {

View File

@@ -9,12 +9,13 @@ import de.extio.game_engine.renderer.model.bo.ControlRenderingBo.BaseControl;
import de.extio.game_engine.renderer.model.bo.ControlRenderingBo.ButtonControl;
import de.extio.game_engine.renderer.model.color.RgbaColor;
import de.extio.game_engine.renderer.model.event.UiControlEvent;
import de.extio.game_engine.resource.StaticResource;
public class G2DButtonControlImpl extends G2DBaseControlImpl implements ButtonControl {
protected CustomAbstractButton control;
protected String iconResourceName;
protected StaticResource iconResource;
private RgbaColor backgroundColor;
@@ -80,7 +81,8 @@ public class G2DButtonControlImpl extends G2DBaseControlImpl implements ButtonCo
this.control.setScaleFactor(this.scaleFactor);
this.control.setEnabled(this.enabled);
this.control.setVisible(this.visible);
this.control.setIconResourceName(this.iconResourceName);
this.control.setIconResource(this.iconResource);
this.control.setStaticResourceService(this.rendererData.getStaticResourceService());
if (this.backgroundColor == null) {
this.control.setBackgroundColor(null);
}
@@ -104,14 +106,14 @@ public class G2DButtonControlImpl extends G2DBaseControlImpl implements ButtonCo
}
@Override
public void setIconResourceName(final String iconResourceName) {
this.modified |= !Objects.equals(this.iconResourceName, iconResourceName);
this.iconResourceName = iconResourceName;
public void setIconResource(final StaticResource iconResource) {
this.modified |= !Objects.equals(this.iconResource, iconResource);
this.iconResource = iconResource;
}
@Override
public String getIconResourceName() {
return this.iconResourceName;
public StaticResource getIconResource() {
return this.iconResource;
}
@Override

View File

@@ -5,6 +5,7 @@ import java.util.List;
import de.extio.game_engine.renderer.RendererData;
import de.extio.game_engine.renderer.model.RenderingBoHasDimension;
import de.extio.game_engine.renderer.model.color.RgbaColor;
import de.extio.game_engine.resource.StaticResource;
/**
* This bo renders ui controls (buttons, ...)
@@ -125,9 +126,9 @@ public interface ControlRenderingBo extends RenderingBoHasDimension {
void setBackgroundColor(RgbaColor backgroundColor);
void setIconResourceName(String iconResourceName);
void setIconResource(StaticResource iconResource);
String getIconResourceName();
StaticResource getIconResource();
}

View File

@@ -1,15 +1,24 @@
package de.extio.game_engine.renderer.model.bo;
import de.extio.game_engine.renderer.model.RenderingBoHasDimension;
import de.extio.game_engine.resource.StaticResource;
/**
* Draws an image. You can either set the resource name (and optional mod name) or the raw image data as byte[] in png format.
*/
public interface DrawImageRenderingBo extends RenderingBoHasDimension {
DrawImageRenderingBo setResourceName(String resourceName);
DrawImageRenderingBo setResource(StaticResource resourceName);
/**
* Also ImageName must be set if byte[] image data is used.
*/
DrawImageRenderingBo setImageData(byte[] data);
/**
* Must be set if byte[] image data is used.
*/
DrawImageRenderingBo setImageName(String name);
/**
* @param transparency Values between 0.0 and 1.0

View File

@@ -10,7 +10,7 @@ public final class UiOptions {
private boolean drawFps = true;
private String backgroundResourceName0 = null;
private StaticResource backgroundResource0 = null;
private boolean backgroundScrolling0;
@@ -40,12 +40,12 @@ public final class UiOptions {
this.drawFps = drawFps;
}
public String getBackgroundResourceName0() {
return this.backgroundResourceName0;
public StaticResource getBackgroundResource0() {
return this.backgroundResource0;
}
public void setBackgroundResourceName0(final String background0) {
this.backgroundResourceName0 = background0;
public void setBackgroundResource0(final StaticResource backgroundResource0) {
this.backgroundResource0 = backgroundResource0;
}
public boolean isBackgroundScrolling0() {