feat(renderer): Refactor resource handling to use StaticResource for icons and backgrounds in rendering components
This commit is contained in:
@@ -50,7 +50,6 @@ public class Container extends AbstractClientModule implements InitializingBean
|
||||
this.rendererControl = rendererControl;
|
||||
this.eventService = eventService;
|
||||
this.rendererWorkingSet = rendererWorkingSet;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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() {
|
||||
|
||||
Reference in New Issue
Block a user