feat(i18n): Add i18n configuration and resource management with localization support
feat(renderer): Integrate StaticResourceService for dynamic resource loading in renderer feat(font): Implement font resource management and update default font handling feat(resources): Add icon and font files for renderer and localization features
This commit is contained in:
@@ -1,5 +1,10 @@
|
||||
package de.extio.game_engine.i18n;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URI;
|
||||
import java.nio.file.Path;
|
||||
import java.util.stream.StreamSupport;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
@@ -8,28 +13,33 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
|
||||
import de.extio.game_engine.resource.StaticResource;
|
||||
import de.extio.game_engine.resource.StaticResourceService;
|
||||
|
||||
@AutoConfiguration
|
||||
@ConditionalOnProperty(name = "game-engine.i18n.enabled", havingValue = "true", matchIfMissing = true)
|
||||
public class LocalizationAutoConfiguration {
|
||||
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(LocalizationServiceImpl.class);
|
||||
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
LocalizationService localizationManager(@Value("${game-engine.i18n.load-on-start:true}") final boolean loadOnStart, @Value("${game-engine.i18n.resource:i18n.yaml}") final String resource) {
|
||||
LocalizationService localizationManager(@Value("${game-engine.i18n.load-on-start:true}") final boolean loadOnStart, @Value("${game-engine.i18n.resource:i18n/i18n.yaml}") final String resource, final StaticResourceService staticResourceService) {
|
||||
final var localizationManager = new LocalizationServiceImpl();
|
||||
|
||||
if (loadOnStart) {
|
||||
try (var resourceStream = LocalizationAutoConfiguration.class.getClassLoader().getResourceAsStream(resource)) {
|
||||
if (resourceStream != null) {
|
||||
localizationManager.load(resourceStream);
|
||||
final var path = new File(resource).toPath();
|
||||
final var staticResource = new StaticResource(path.getParent() != null ? StreamSupport.stream(path.getParent().spliterator(), false).map(Path::toString).toList() : null, path.getFileName().toString());
|
||||
staticResourceService.loadStreamByPath(staticResource).ifPresent(stream -> {
|
||||
try (stream) {
|
||||
localizationManager.load(stream);
|
||||
}
|
||||
}
|
||||
catch (final Exception exc) {
|
||||
LOGGER.error("An exception occured while loading localizations from resource: " + resource, exc);
|
||||
}
|
||||
catch (final Exception e) {
|
||||
LOGGER.error("An exception occured while loading localizations from resource: " + resource, e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
return localizationManager;
|
||||
}
|
||||
|
||||
|
||||
@@ -118,12 +118,12 @@ public class LocalizationEditor extends JFrame {
|
||||
public void run() {
|
||||
try {
|
||||
final LocalizationEditor frame = new LocalizationEditor();
|
||||
try (InputStream in = frame.getClass().getClassLoader().getResourceAsStream("icon.png")) {
|
||||
final BufferedImage icon = ImageIO.read(in);
|
||||
frame.setIconImage(icon);
|
||||
}
|
||||
catch (final Exception e) {
|
||||
}
|
||||
// try (InputStream in = frame.getClass().getClassLoader().getResourceAsStream("icon.png")) {
|
||||
// final BufferedImage icon = ImageIO.read(in);
|
||||
// frame.setIconImage(icon);
|
||||
// }
|
||||
// catch (final Exception e) {
|
||||
// }
|
||||
frame.setVisible(true);
|
||||
|
||||
frame.localizationManagerImpl.reset();
|
||||
|
||||
@@ -3,9 +3,7 @@ package de.extio.game_engine.renderer;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
@@ -21,6 +19,8 @@ import de.extio.game_engine.renderer.work.RendererWorkingSet;
|
||||
import de.extio.game_engine.renderer.work.RendererWorkingSetImpl;
|
||||
import de.extio.game_engine.renderer.work.RenderingBoPool;
|
||||
import de.extio.game_engine.renderer.work.RenderingBoPoolImpl;
|
||||
import de.extio.game_engine.resource.StaticResourceService;
|
||||
import de.extio.game_engine.resource.StaticResourceService;
|
||||
import de.extio.game_engine.storage.StorageService;
|
||||
|
||||
@AutoConfiguration
|
||||
@@ -59,9 +59,10 @@ public class RendererAutoConfiguration {
|
||||
final StorageService storageService,
|
||||
final RendererWorkingSet rendererWorkingSet,
|
||||
final ModuleService moduleManager,
|
||||
final ModuleExecutor moduleExecutor) {
|
||||
final ModuleExecutor moduleExecutor,
|
||||
final StaticResourceService staticResourceService) {
|
||||
|
||||
final var rendererData = new RendererData(applicationContext, renderer, rendererControl, renderingBoPool, keycodeRegistry, eventService, storageService, rendererWorkingSet, moduleManager, moduleExecutor);
|
||||
final var rendererData = new RendererData(applicationContext, renderer, rendererControl, renderingBoPool, keycodeRegistry, eventService, storageService, rendererWorkingSet, moduleManager, moduleExecutor, staticResourceService);
|
||||
renderer.setRendererData(rendererData);
|
||||
rendererControl.setRendererData(rendererData);
|
||||
renderingBoPool.setRendererData(rendererData);
|
||||
|
||||
@@ -13,6 +13,7 @@ import de.extio.game_engine.renderer.model.options.UiOptions;
|
||||
import de.extio.game_engine.renderer.model.options.VideoOptions;
|
||||
import de.extio.game_engine.renderer.work.RendererWorkingSet;
|
||||
import de.extio.game_engine.renderer.work.RenderingBoPool;
|
||||
import de.extio.game_engine.resource.StaticResourceService;
|
||||
import de.extio.game_engine.storage.StorageService;
|
||||
|
||||
public class RendererData {
|
||||
@@ -42,10 +43,12 @@ public class RendererData {
|
||||
private final ModuleService moduleManager;
|
||||
|
||||
private final ModuleExecutor moduleExecutor;
|
||||
|
||||
private final StaticResourceService staticResourceService;
|
||||
|
||||
private RendererLoop rendererLoop;
|
||||
|
||||
public RendererData(final ApplicationContext applicationContext, final Renderer renderer, final RendererControl rendererControl, final RenderingBoPool renderingBoPool, final KeycodeRegistry keycodeRegistry, final EventService eventService, final StorageService storageService, final RendererWorkingSet rendererWorkingSet, final ModuleService moduleManager, final ModuleExecutor moduleExecutor) {
|
||||
public RendererData(final ApplicationContext applicationContext, final Renderer renderer, final RendererControl rendererControl, final RenderingBoPool renderingBoPool, final KeycodeRegistry keycodeRegistry, final EventService eventService, final StorageService storageService, final RendererWorkingSet rendererWorkingSet, final ModuleService moduleManager, final ModuleExecutor moduleExecutor, final StaticResourceService staticResourceService) {
|
||||
this.applicationContext = applicationContext;
|
||||
this.renderer = renderer;
|
||||
this.rendererControl = rendererControl;
|
||||
@@ -56,6 +59,7 @@ public class RendererData {
|
||||
this.rendererWorkingSet = rendererWorkingSet;
|
||||
this.moduleManager = moduleManager;
|
||||
this.moduleExecutor = moduleExecutor;
|
||||
this.staticResourceService = staticResourceService;
|
||||
}
|
||||
|
||||
public ApplicationContext getApplicationContext() {
|
||||
@@ -121,4 +125,8 @@ public class RendererData {
|
||||
public ModuleExecutor getModuleExecutor() {
|
||||
return moduleExecutor;
|
||||
}
|
||||
|
||||
public StaticResourceService getStaticResourceService() {
|
||||
return staticResourceService;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import java.awt.event.MouseWheelListener;
|
||||
import java.awt.event.WindowEvent;
|
||||
import java.awt.event.WindowListener;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
@@ -63,15 +64,15 @@ public class G2DMainFrame extends Frame {
|
||||
this.setLayout(null);
|
||||
this.setBackground(Color.BLACK);
|
||||
|
||||
try (var in = this.getClass().getClassLoader().getResourceAsStream("icon.png")) {
|
||||
if (in != null) {
|
||||
this.rendererData.getStaticResourceService().loadStreamByPath(List.of("renderer"), "icon.png").ifPresent(stream -> {
|
||||
try (var in = stream) {
|
||||
final var icon = ImageIO.read(in);
|
||||
this.setIconImage(icon);
|
||||
}
|
||||
}
|
||||
catch (final IOException e) {
|
||||
LOGGER.error(e.getMessage(), e);
|
||||
}
|
||||
catch (final IOException e) {
|
||||
LOGGER.warn(e.getMessage(), e);
|
||||
}
|
||||
});
|
||||
|
||||
this.addWindowListener(new WindowListener() {
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ package de.extio.game_engine.renderer.g2d;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.EventQueue;
|
||||
import java.awt.Font;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Toolkit;
|
||||
import java.awt.image.BufferedImage;
|
||||
@@ -9,7 +10,9 @@ import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
@@ -22,8 +25,10 @@ import org.slf4j.LoggerFactory;
|
||||
import de.extio.game_engine.module.AbstractClientModule;
|
||||
import de.extio.game_engine.renderer.Renderer;
|
||||
import de.extio.game_engine.renderer.RendererData;
|
||||
import de.extio.game_engine.renderer.g2d.G2DRenderer.G2DRendererModule;
|
||||
import de.extio.game_engine.renderer.g2d.bo.rendering.G2DAbstractRenderingBo;
|
||||
import de.extio.game_engine.renderer.g2d.bo.rendering.G2DDrawBackground;
|
||||
import de.extio.game_engine.renderer.g2d.bo.rendering.G2DDrawFont;
|
||||
import de.extio.game_engine.renderer.g2d.bo.rendering.G2DDrawFpsHistory;
|
||||
import de.extio.game_engine.renderer.g2d.control.G2DDrawControl;
|
||||
import de.extio.game_engine.renderer.g2d.control.G2DDrawControlTooltip;
|
||||
@@ -32,6 +37,7 @@ import de.extio.game_engine.renderer.model.RenderingBoLayer;
|
||||
import de.extio.game_engine.renderer.model.bo.DrawFontRenderingBo;
|
||||
import de.extio.game_engine.renderer.model.color.RgbaColor;
|
||||
import de.extio.game_engine.renderer.model.event.TakeScreenshotEvent;
|
||||
import de.extio.game_engine.resource.StaticResource;
|
||||
import de.extio.game_engine.util.RingBuffer;
|
||||
|
||||
public class G2DRenderer implements Renderer {
|
||||
@@ -65,6 +71,8 @@ public class G2DRenderer implements Renderer {
|
||||
private String title;
|
||||
|
||||
private volatile boolean takeScreenshot;
|
||||
|
||||
private StaticResource previousDefaultFont = null;
|
||||
|
||||
public G2DRenderer() {
|
||||
LOGGER.info("ctor");
|
||||
@@ -140,11 +148,15 @@ public class G2DRenderer implements Renderer {
|
||||
}
|
||||
|
||||
final var viewPortDimension = this.rendererData.getRendererControl().getAbsoluteViewportDimension();
|
||||
|
||||
if (viewPortDimension.getX() < 10 || viewPortDimension.getY() < 10) {
|
||||
// Some race condition happens rarely (mainly Windows 11) that window size is not initialized after entering full screen. Put a plaster on it...
|
||||
throw new G2DRendererWindowNotInitializedException();
|
||||
}
|
||||
|
||||
if (this.previousDefaultFont == null && this.rendererData.getUiOptions().getFontResource() != null && !this.rendererData.getUiOptions().getFontResource().equals(this.previousDefaultFont)) {
|
||||
this.previousDefaultFont = this.rendererData.getUiOptions().getFontResource();
|
||||
G2DDrawFont.updateDefaultFont(this.rendererData.getStaticResourceService(), this.rendererData.getUiOptions().getFontResource());
|
||||
}
|
||||
|
||||
BufferedImage screenshotImg = null;
|
||||
Graphics2D screenshotGraphics = null;
|
||||
|
||||
@@ -162,6 +162,7 @@ public class G2DRendererControl implements RendererControl {
|
||||
.store(List.of("gameEngine"), "g2dRendererControlOptions", this.options);
|
||||
|
||||
this.recalculate();
|
||||
this.rendererData.getEventService().fire(new WindowResizeEvent());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -15,6 +15,8 @@ import de.extio.game_engine.renderer.g2d.G2DRendererCondition;
|
||||
import de.extio.game_engine.renderer.model.RenderingBoLayer;
|
||||
import de.extio.game_engine.renderer.model.bo.DrawFontRenderingBo;
|
||||
import de.extio.game_engine.renderer.model.bo.DrawFontRenderingBoTextAlignment;
|
||||
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;
|
||||
import de.extio.game_engine.spatial2.model.MutableCoordI2;
|
||||
@@ -27,20 +29,25 @@ public class G2DDrawFont extends G2DAbstractRenderingBo implements DrawFontRende
|
||||
|
||||
private final static int FONT_SIZE_DEFAULT = 14;
|
||||
|
||||
private final static Font baseFont;
|
||||
private static Font baseFont;
|
||||
|
||||
static {
|
||||
Font f;
|
||||
try {
|
||||
f = Font.createFont(Font.TRUETYPE_FONT, ClassLoader.getSystemClassLoader().getResourceAsStream("Roboto-Regular.ttf"));
|
||||
}
|
||||
catch (final Exception e) {
|
||||
final Map<TextAttribute, Object> attributes = new HashMap<>();
|
||||
attributes.put(TextAttribute.FAMILY, Font.SANS_SERIF);
|
||||
attributes.put(TextAttribute.WEIGHT, TextAttribute.WEIGHT_SEMIBOLD);
|
||||
f = Font.getFont(attributes);
|
||||
}
|
||||
baseFont = f;
|
||||
final Map<TextAttribute, Object> attributes = new HashMap<>();
|
||||
attributes.put(TextAttribute.FAMILY, Font.SANS_SERIF);
|
||||
attributes.put(TextAttribute.WEIGHT, TextAttribute.WEIGHT_SEMIBOLD);
|
||||
baseFont = Font.getFont(attributes);
|
||||
}
|
||||
|
||||
public static void updateDefaultFont(final StaticResourceService staticResourceService, final StaticResource resource) {
|
||||
staticResourceService.loadStreamByPath(resource).ifPresent(stream -> {
|
||||
try (var in = stream) {
|
||||
final var font = Font.createFont(Font.TRUETYPE_FONT, in);
|
||||
G2DDrawFont.baseFont = font;
|
||||
}
|
||||
catch (final Exception e) {
|
||||
LOGGER.warn(e.getMessage(), e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private String text;
|
||||
|
||||
@@ -1,10 +1,15 @@
|
||||
package de.extio.game_engine.renderer.model.options;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import de.extio.game_engine.resource.StaticResource;
|
||||
import de.extio.game_engine.spatial2.model.CoordI2;
|
||||
import de.extio.game_engine.spatial2.model.MutableCoordI2;
|
||||
|
||||
public final class UiOptions {
|
||||
|
||||
|
||||
private boolean drawFps = true;
|
||||
|
||||
private String backgroundResourceName0 = null;
|
||||
|
||||
private boolean backgroundScrolling0;
|
||||
@@ -15,12 +20,12 @@ public final class UiOptions {
|
||||
|
||||
private boolean backgroundScrollingReverse1;
|
||||
|
||||
private boolean drawFps = true;
|
||||
|
||||
private CoordI2 backgroundOffset0 = MutableCoordI2.create();
|
||||
|
||||
private CoordI2 backgroundOffset1 = MutableCoordI2.create();
|
||||
|
||||
private StaticResource fontResource = new StaticResource(List.of("renderer"), "Inter_24pt-Regular.ttf");
|
||||
|
||||
public UiOptions() {
|
||||
if ("true".equals(System.getProperty("debug"))) {
|
||||
this.drawFps = true;
|
||||
@@ -91,4 +96,11 @@ public final class UiOptions {
|
||||
this.backgroundOffset1 = backgroundOffset1;
|
||||
}
|
||||
|
||||
public StaticResource getFontResource() {
|
||||
return fontResource;
|
||||
}
|
||||
|
||||
public void setFontResource(final StaticResource fontResource) {
|
||||
this.fontResource = fontResource;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,6 @@ de.extio.game_engine.keyboard.KeycodeAutoConfiguration
|
||||
de.extio.game_engine.renderer.RendererAutoConfiguration
|
||||
de.extio.game_engine.renderer.g2d.G2DAutoConfiguration
|
||||
de.extio.game_engine.storage.StorageServiceAutoConfiguration
|
||||
de.extio.game_engine.module.ModuleManagerAutoConfiguration
|
||||
de.extio.game_engine.module.ModuleServiceAutoConfiguration
|
||||
de.extio.game_engine.i18n.LocalizationAutoConfiguration
|
||||
de.extio.game_engine.resource.StaticResourceAutoConfiguration
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
---
|
||||
curId: 2
|
||||
descriptions:
|
||||
test-2: ""
|
||||
test-1: "aaa"
|
||||
languages:
|
||||
en:
|
||||
test-1: "hello"
|
||||
test-2: "world"
|
||||
de:
|
||||
test-1: "hallo"
|
||||
test-2: "welt"
|
||||
languagesInfo:
|
||||
en:
|
||||
name: "English"
|
||||
shortName: "en"
|
||||
de:
|
||||
name: "Deutsch"
|
||||
shortName: "de"
|
||||
prefix: "test"
|
||||
Reference in New Issue
Block a user