diff --git a/data/renderer/GoogleSansCode-Regular.ttf b/data/renderer/GoogleSansCode-Regular.ttf new file mode 100644 index 0000000..5c520ad Binary files /dev/null and b/data/renderer/GoogleSansCode-Regular.ttf differ diff --git a/data/renderer/Inconsolata-Regular.ttf b/data/renderer/Inconsolata-Regular.ttf new file mode 100644 index 0000000..ff1e6bb Binary files /dev/null and b/data/renderer/Inconsolata-Regular.ttf differ diff --git a/src/main/java/de/extio/game_engine/renderer/g2d/G2DAutoConfiguration.java b/src/main/java/de/extio/game_engine/renderer/g2d/G2DAutoConfiguration.java index c785dd2..ca8a409 100644 --- a/src/main/java/de/extio/game_engine/renderer/g2d/G2DAutoConfiguration.java +++ b/src/main/java/de/extio/game_engine/renderer/g2d/G2DAutoConfiguration.java @@ -32,7 +32,10 @@ import de.extio.game_engine.renderer.g2d.theme.SpacecraftPatternRenderer; import de.extio.game_engine.renderer.g2d.theme.SteampunkPatternRenderer; import de.extio.game_engine.renderer.g2d.theme.UrbanPatternRenderer; import de.extio.game_engine.renderer.g2d.theme.VintagePatternRenderer; +import de.extio.game_engine.renderer.g2d.theme.TerminalPatternRenderer; +import de.extio.game_engine.renderer.g2d.theme.AsciiPatternRenderer; import de.extio.game_engine.renderer.g2d.theme.BevelDarkThemeFactoryBean; +import de.extio.game_engine.renderer.g2d.theme.AsciiThemeFactoryBean; import de.extio.game_engine.renderer.g2d.theme.BevelLightThemeFactoryBean; import de.extio.game_engine.renderer.g2d.theme.BlueprintThemeFactoryBean; import de.extio.game_engine.renderer.g2d.theme.ChronicleThemeFactoryBean; @@ -47,6 +50,7 @@ import de.extio.game_engine.renderer.g2d.theme.SteampunkThemeFactoryBean; import de.extio.game_engine.renderer.g2d.theme.Theme; import de.extio.game_engine.renderer.g2d.theme.UrbanThemeFactoryBean; import de.extio.game_engine.renderer.g2d.theme.VintageThemeFactoryBean; +import de.extio.game_engine.renderer.g2d.theme.TerminalThemeFactoryBean; import de.extio.game_engine.resource.StaticResourceService; import de.extio.game_engine.storage.StorageService; @@ -155,6 +159,16 @@ public class G2DAutoConfiguration { return new SteampunkThemeFactoryBean(); } + @Bean + FactoryBean asciiTheme() { + return new AsciiThemeFactoryBean(); + } + + @Bean + FactoryBean terminalTheme() { + return new TerminalThemeFactoryBean(); + } + @Bean @ConditionalOnMissingBean G2DDrawBackground g2dDrawBackground() { @@ -275,4 +289,16 @@ public class G2DAutoConfiguration { return new VintagePatternRenderer(); } + @Bean + @ConditionalOnMissingBean + AsciiPatternRenderer asciiPatternRenderer() { + return new AsciiPatternRenderer(); + } + + @Bean + @ConditionalOnMissingBean + TerminalPatternRenderer terminalPatternRenderer() { + return new TerminalPatternRenderer(); + } + } diff --git a/src/main/java/de/extio/game_engine/renderer/g2d/theme/AsciiPatternRenderer.java b/src/main/java/de/extio/game_engine/renderer/g2d/theme/AsciiPatternRenderer.java new file mode 100644 index 0000000..4e1afc1 --- /dev/null +++ b/src/main/java/de/extio/game_engine/renderer/g2d/theme/AsciiPatternRenderer.java @@ -0,0 +1,198 @@ +package de.extio.game_engine.renderer.g2d.theme; + +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.image.BufferedImage; + +import de.extio.game_engine.renderer.g2d.bo.rendering.G2DDrawFont; +import de.extio.game_engine.spatial2.model.CoordI2; + +public class AsciiPatternRenderer implements PatternRenderer { + + @Override + public void drawDecorativeBorder(final Graphics2D g2d, final int x, final int y, final int width, final int height, final int strength, final Color color) { + g2d.setColor(color); + + // Use simple ASCII characters for borders + final int fontSize = Math.max(8, strength * 4); // Scale font size with strength + + // Get character dimensions + final var horizDim = G2DDrawFont.getTextDimensions("-", g2d, fontSize, 1.0); + final var vertDim = G2DDrawFont.getTextDimensions("|", g2d, fontSize, 1.0); + final var cornerDim = G2DDrawFont.getTextDimensions("+", g2d, fontSize, 1.0); + + final int charWidth = Math.max(1, (int)horizDim.getX()); + final int charHeight = Math.max(1, (int)cornerDim.getY()); + + final int horizChars = Math.max(0, (width - 2 * charWidth) / charWidth); + final int vertChars = Math.max(0, (height - 2 * charHeight) / charHeight); + + final int totalWidth = (horizChars + 2) * charWidth; + final int totalHeight = (vertChars + 2) * charHeight; + final int offsetX = x + Math.max(0, (width - totalWidth) / 2); + final int offsetY = y + Math.max(0, (height - totalHeight) / 2); + + // Top border + G2DDrawFont.renderText(g2d, cornerDim, 1.0, offsetX, offsetY, fontSize, "+"); + for (int i = 0; i < horizChars; i++) { + G2DDrawFont.renderText(g2d, horizDim, 1.0, offsetX + charWidth + i * charWidth, offsetY, fontSize, "-"); + } + G2DDrawFont.renderText(g2d, cornerDim, 1.0, offsetX + charWidth + horizChars * charWidth, offsetY, fontSize, "+"); + + // Bottom border + G2DDrawFont.renderText(g2d, cornerDim, 1.0, offsetX, offsetY + charHeight + vertChars * charHeight, fontSize, "+"); + for (int i = 0; i < horizChars; i++) { + G2DDrawFont.renderText(g2d, horizDim, 1.0, offsetX + charWidth + i * charWidth, offsetY + (int)(charHeight * 1.5) + vertChars * charHeight, fontSize, "-"); + } + G2DDrawFont.renderText(g2d, cornerDim, 1.0, offsetX + charWidth + horizChars * charWidth, offsetY + charHeight + vertChars * charHeight, fontSize, "+"); + + // Left and right borders + for (int i = 0; i < vertChars; i++) { + G2DDrawFont.renderText(g2d, vertDim, 1.0, offsetX, offsetY + charHeight + i * charHeight, fontSize, "|"); + G2DDrawFont.renderText(g2d, vertDim, 1.0, offsetX + charWidth + horizChars * charWidth, offsetY + charHeight + i * charHeight, fontSize, "|"); + } + } + + @Override + public void drawDecorativeBorderFilled(final Graphics2D g2d, final int x, final int y, final int width, final int height, final int strength, final Color borderColor, final Color backgroundColor) { + final var s = Math.max(1, strength); + g2d.setColor(backgroundColor); + g2d.fillRect(x + s, y + s, Math.max(0, width - s * 2), Math.max(0, height - s * 2)); + this.drawDecorativeBorder(g2d, x, y, width, height, s, borderColor); + } + + @Override + public void drawWindowPanel(final Graphics2D g2d, final int x, final int y, final int width, final int height, final boolean thickBorder, final Color innerBorderColor, final Color outerBorderColor, final Color backgroundColor, final double scaleFactor) { + final var s = Math.max((thickBorder ? 2 : 1), (int) ((thickBorder ? 3 : 2) * scaleFactor)); + final var s2 = s * 2; + + final var bg = new Color(backgroundColor.getRed(), backgroundColor.getGreen(), backgroundColor.getBlue(), 240); + this.drawDecorativeBorderFilled(g2d, x + s, y + s, width - s2, height - s2, s, innerBorderColor, bg); + this.drawDecorativeBorder(g2d, x, y, width, height, s, outerBorderColor); + } + + @Override + public void drawCloseButton(final Graphics2D g2d, final int width, final int height, final boolean enabled, final boolean pressed, final boolean hovered, final boolean toggled, final Color backgroundColor, final double scaleFactor, final Theme theme) { + final var highlight = (hovered || toggled); + + Color bgColor = backgroundColor; + if (bgColor == null) { + bgColor = theme.getBorderInner().toColor(); + } + if (highlight) { + bgColor = theme.getBackgroundNormal().toColor(); + } + if (pressed) { + bgColor = theme.getSelectionPrimary().toColor(); + } + + g2d.setColor(bgColor); + g2d.fillRect(0, 0, width, height); + + final var s = Math.max(1, (int) (1 * scaleFactor)); + this.drawDecorativeBorder(g2d, 0, 0, width, height, s, theme.getBorderOuter().toColor()); + + if (!enabled) { + return; + } + + final Color textColor; + if (pressed) { + textColor = theme.getTextNormal().toColor(); + } + else if (highlight) { + textColor = theme.getSelectionSecondary().toColor(); + } + else { + textColor = theme.getTextDisabled().toColor(); + } + g2d.setColor(textColor); + + final var fontSize = (int) (12 * scaleFactor); + final var textDim = G2DDrawFont.getTextDimensions("X", g2d, 12, scaleFactor); + G2DDrawFont.renderText(g2d, textDim, 1.0, ((width - textDim.getX()) / 2), ((height - textDim.getY()) / 2), fontSize, "X"); + } + + private java.awt.image.BufferedImage patternCache; + + private java.awt.image.BufferedImage getPatternCache() { + if (this.patternCache == null) { + final int spacing = 40; + this.patternCache = new BufferedImage(spacing, spacing, java.awt.image.BufferedImage.TYPE_INT_ARGB); + final Graphics2D g2d = this.patternCache.createGraphics(); + + g2d.setBackground(new Color(0, 0, 0, 0)); + g2d.clearRect(0, 0, spacing, spacing); + + // Simple ASCII-like pattern - just dots + g2d.setColor(new Color(0, 255, 0, 30)); + g2d.fillRect(spacing / 2 - 1, spacing / 2 - 1, 2, 2); + + g2d.dispose(); + } + return this.patternCache; + } + + @Override + public void drawBackgroundPattern(final Graphics2D g2d, final CoordI2 offset, final CoordI2 viewPort) { + final var cache = this.getPatternCache(); + final int spacing = cache.getWidth(); + + final int offX = Math.floorMod(offset.getX(), spacing); + final int offY = Math.floorMod(offset.getY(), spacing); + + for (int x = -spacing; x < viewPort.getX() + spacing; x += spacing) { + for (int y = -spacing; y < viewPort.getY() + spacing; y += spacing) { + g2d.drawImage(cache, x + offX, y + offY, null); + } + } + } + + @Override + public void drawButton(final Graphics2D g2d, final int x, final int y, final int width, final int height, final boolean enabled, final boolean pressed, final boolean hovered, final boolean toggled, final Color backgroundColor, final double scaleFactor, final Theme theme) { + Color bgColor; + if (backgroundColor == null) { + final var baseColor = !toggled ? theme.getBackgroundNormal() : theme.getBackgroundSelected(); + float b = baseColor.getBrightness(); + + if (pressed) { + b += theme.getPressedBrightnessAdjustment(); + } + else if (hovered) { + b += theme.getHoverBrightnessAdjustment(); + } + + b = Math.max(0.0f, Math.min(1.0f, b)); + bgColor = Color.getHSBColor(baseColor.getHue(), baseColor.getSaturation(), b); + } + else { + final var hsb = new float[3]; + Color.RGBtoHSB(backgroundColor.getRed(), backgroundColor.getGreen(), backgroundColor.getBlue(), hsb); + + float b = !toggled ? 0.25F : 0.45F; + if (pressed) { + b += theme.getPressedBrightnessAdjustment(); + } + else if (hovered) { + b += theme.getHoverBrightnessAdjustment(); + } + + b = Math.max(0.0f, Math.min(1.0f, b)); + bgColor = Color.getHSBColor(hsb[0], hsb[1], b); + } + + if (!enabled) { + final var hsb = Color.RGBtoHSB(bgColor.getRed(), bgColor.getGreen(), bgColor.getBlue(), null); + bgColor = Color.getHSBColor(hsb[0], Math.min(1.0f, hsb[1] * 0.1f), Math.min(1.0f, hsb[2] * 0.5f)); + } + + // Simple flat fill, no gradient for ASCII style + g2d.setColor(bgColor); + g2d.fillRect(x, y, width, height); + + // Simple border + final var borderStrength = Math.max(1, (int) (1 * scaleFactor)); + final var borderColor = hovered ? theme.getSelectionPrimary().toColor() : theme.getBorderOuter().toColor(); + this.drawDecorativeBorder(g2d, x, y, width, height, borderStrength, borderColor); + } +} \ No newline at end of file diff --git a/src/main/java/de/extio/game_engine/renderer/g2d/theme/AsciiThemeFactoryBean.java b/src/main/java/de/extio/game_engine/renderer/g2d/theme/AsciiThemeFactoryBean.java new file mode 100644 index 0000000..99ba425 --- /dev/null +++ b/src/main/java/de/extio/game_engine/renderer/g2d/theme/AsciiThemeFactoryBean.java @@ -0,0 +1,37 @@ +package de.extio.game_engine.renderer.g2d.theme; + +import org.springframework.beans.factory.FactoryBean; + +public class AsciiThemeFactoryBean implements FactoryBean { + + @Override + public Theme getObject() { + return Theme.builder() + .name("ASCII") + .font("Inconsolata-Regular.ttf") + .patternRendererName("asciiPatternRenderer") + .borderOuter(new HSBColor(0.00f, 0.00f, 0.30f)) + .borderInner(new HSBColor(0.00f, 0.00f, 0.50f)) + .borderInnerDisabled(new HSBColor(0.00f, 0.00f, 0.15f)) + .backgroundNormal(new HSBColor(0.00f, 0.00f, 0.10f)) + .backgroundSelected(new HSBColor(0.50f, 0.50f, 0.30f)) + .textNormal(new HSBColor(0.33f, 1.00f, 0.80f)) + .textDisabled(new HSBColor(0.33f, 0.50f, 0.50f)) + .selectionPrimary(new HSBColor(0.50f, 0.50f, 0.50f)) + .selectionSecondary(new HSBColor(0.50f, 0.70f, 0.70f)) + .windowBackground(new HSBColor(0.00f, 0.00f, 0.05f)) + .hoverBrightnessAdjustment(0.15f) + .pressedBrightnessAdjustment(0.30f) + .build(); + } + + @Override + public Class getObjectType() { + return Theme.class; + } + + @Override + public boolean isSingleton() { + return true; + } +} \ No newline at end of file diff --git a/src/main/java/de/extio/game_engine/renderer/g2d/theme/TerminalPatternRenderer.java b/src/main/java/de/extio/game_engine/renderer/g2d/theme/TerminalPatternRenderer.java new file mode 100644 index 0000000..b72d20e --- /dev/null +++ b/src/main/java/de/extio/game_engine/renderer/g2d/theme/TerminalPatternRenderer.java @@ -0,0 +1,235 @@ +package de.extio.game_engine.renderer.g2d.theme; + +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.image.BufferedImage; + +import de.extio.game_engine.renderer.g2d.bo.rendering.G2DDrawFont; +import de.extio.game_engine.spatial2.model.CoordI2; + +public class TerminalPatternRenderer implements PatternRenderer { + + private BufferedImage patternCache; + + @Override + public void drawDecorativeBorder(final Graphics2D g2d, final int x, final int y, final int width, final int height, final int strength, final Color color) { + final var s = Math.max(1, strength); + final var tick = Math.max(1, s * 2); + final var glyph = Math.max(1, s); + + g2d.setColor(color); + final var step = glyph * 4; + final var seg = glyph * 2; + + for (int gx = x; gx <= x + width - seg; gx += step) { + g2d.fillRect(gx, y, seg, s); + g2d.fillRect(gx + glyph, y + s, glyph, s); + g2d.fillRect(gx, y + height - s, seg, s); + g2d.fillRect(gx + glyph, y + height - s - s, glyph, s); + } + + for (int gy = y; gy <= y + height - seg; gy += step) { + g2d.fillRect(x, gy, s, seg); + g2d.fillRect(x + s, gy + glyph, s, glyph); + g2d.fillRect(x + width - s, gy, s, seg); + g2d.fillRect(x + width - s - s, gy + glyph, s, glyph); + } + + g2d.fillRect(x + s, y + s, tick, s); + g2d.fillRect(x + width - s - tick, y + s, tick, s); + g2d.fillRect(x + s, y + height - s - s, tick, s); + g2d.fillRect(x + width - s - tick, y + height - s - s, tick, s); + + final var innerLeft = x + s + glyph * 3; + final var innerRight = x + width - s - glyph * 3; + final var innerTop = y + s + glyph * 2; + final var innerBottom = y + height - s - glyph * 2; + + for (int gx = innerLeft; gx <= innerRight; gx += glyph * 6) { + g2d.fillRect(gx, y + s, glyph * 2, glyph); + g2d.fillRect(gx + glyph * 3, y + s, glyph, glyph); + g2d.fillRect(gx, y + height - s - glyph, glyph * 2, glyph); + g2d.fillRect(gx + glyph * 3, y + height - s - glyph, glyph, glyph); + } + + for (int gy = innerTop; gy <= innerBottom; gy += glyph * 6) { + g2d.fillRect(x + s, gy, glyph, glyph * 2); + g2d.fillRect(x + s, gy + glyph * 3, glyph, glyph); + g2d.fillRect(x + width - s - glyph, gy, glyph, glyph * 2); + g2d.fillRect(x + width - s - glyph, gy + glyph * 3, glyph, glyph); + } + } + + @Override + public void drawDecorativeBorderFilled(final Graphics2D g2d, final int x, final int y, final int width, final int height, final int strength, final Color borderColor, final Color backgroundColor) { + final var s = Math.max(1, strength); + g2d.setColor(backgroundColor); + g2d.fillRect(x + s, y + s, Math.max(0, width - s * 2), Math.max(0, height - s * 2)); + this.drawDecorativeBorder(g2d, x, y, width, height, s, borderColor); + } + + @Override + public void drawWindowPanel(final Graphics2D g2d, final int x, final int y, final int width, final int height, final boolean thickBorder, final Color innerBorderColor, final Color outerBorderColor, final Color backgroundColor, final double scaleFactor) { + final var s = Math.max((thickBorder ? 2 : 1), (int) ((thickBorder ? 3 : 2) * scaleFactor)); + final var s2 = s * 2; + + final var bg = new Color(backgroundColor.getRed(), backgroundColor.getGreen(), backgroundColor.getBlue(), 230); + this.drawDecorativeBorderFilled(g2d, x + s, y + s, width - s2, height - s2, s, innerBorderColor, bg); + this.drawDecorativeBorder(g2d, x, y, width, height, s, outerBorderColor); + } + + @Override + public void drawCloseButton(final Graphics2D g2d, final int width, final int height, final boolean enabled, final boolean pressed, final boolean hovered, final boolean toggled, final Color backgroundColor, final double scaleFactor, final Theme theme) { + final var highlight = (hovered || toggled); + + Color bgColor = backgroundColor; + if (bgColor == null) { + bgColor = theme.getBorderInner().toColor(); + } + if (highlight) { + bgColor = theme.getBackgroundNormal().toColor(); + } + if (pressed) { + bgColor = theme.getSelectionPrimary().toColor(); + } + + g2d.setColor(bgColor); + g2d.fillRect(0, 0, width, height); + + final var s = Math.max(1, (int) (1 * scaleFactor)); + this.drawDecorativeBorder(g2d, 0, 0, width, height, s, theme.getBorderOuter().toColor()); + + if (!enabled) { + return; + } + + final Color textColor; + if (pressed) { + textColor = theme.getTextNormal().toColor(); + } + else if (highlight) { + textColor = theme.getSelectionSecondary().toColor(); + } + else { + textColor = theme.getTextDisabled().toColor(); + } + g2d.setColor(textColor); + + final var fontSize = (int) (12 * scaleFactor); + final var textDim = G2DDrawFont.getTextDimensions("X", g2d, 12, scaleFactor); + G2DDrawFont.renderText(g2d, textDim, 1.0, ((width - textDim.getX()) / 2), ((height - textDim.getY()) / 2), fontSize, "X"); + } + + private BufferedImage getPatternCache() { + if (this.patternCache == null) { + final int spacing = 56; + this.patternCache = new BufferedImage(spacing, spacing, BufferedImage.TYPE_INT_ARGB); + final Graphics2D g2d = this.patternCache.createGraphics(); + + g2d.setBackground(new Color(0, 0, 0, 0)); + g2d.clearRect(0, 0, spacing, spacing); + + g2d.setColor(new Color(255, 225, 170, 14)); + for (int y = 0; y < spacing; y += 7) { + g2d.fillRect(0, y, spacing, 1); + } + + final var soft = new Color(255, 210, 140, 26); + final var strong = new Color(255, 205, 120, 36); + + final int cx = spacing / 2; + final int cy = spacing / 2; + + g2d.setColor(soft); + g2d.fillRect(cx - 10, cy - 10, 2, 2); + g2d.fillRect(cx + 8, cy - 10, 2, 2); + g2d.fillRect(cx - 10, cy + 8, 2, 2); + g2d.fillRect(cx + 8, cy + 8, 2, 2); + + g2d.setColor(strong); + g2d.fillRect(cx - 3, cy - 6, 1, 12); + g2d.fillRect(cx - 6, cy - 3, 12, 1); + + g2d.setColor(soft); + g2d.fillRect(cx + 14, cy + 14, 3, 1); + g2d.fillRect(cx + 16, cy + 12, 1, 3); + + g2d.fillRect(cx - 18, cy + 6, 6, 1); + g2d.fillRect(cx - 18, cy + 6, 1, 4); + g2d.fillRect(cx - 13, cy + 6, 1, 4); + g2d.fillRect(cx - 16, cy + 9, 3, 1); + + g2d.fillRect(cx + 2, cy - 16, 6, 1); + g2d.fillRect(cx + 7, cy - 16, 1, 4); + g2d.dispose(); + } + return this.patternCache; + } + + @Override + public void drawBackgroundPattern(final Graphics2D g2d, final CoordI2 offset, final CoordI2 viewPort) { + final var cache = this.getPatternCache(); + final int spacing = cache.getWidth(); + + final int offX = Math.floorMod(offset.getX(), spacing); + final int offY = Math.floorMod(offset.getY(), spacing); + + for (int x = -spacing; x < viewPort.getX() + spacing; x += spacing) { + for (int y = -spacing; y < viewPort.getY() + spacing; y += spacing) { + g2d.drawImage(cache, x + offX, y + offY, null); + } + } + } + + @Override + public void drawButton(final Graphics2D g2d, final int x, final int y, final int width, final int height, final boolean enabled, final boolean pressed, final boolean hovered, final boolean toggled, final Color backgroundColor, final double scaleFactor, final Theme theme) { + Color bgColor; + if (backgroundColor == null) { + final var baseColor = !toggled ? theme.getBackgroundNormal() : theme.getBackgroundSelected(); + float b = baseColor.getBrightness(); + + if (pressed) { + b += theme.getPressedBrightnessAdjustment(); + } + else if (hovered) { + b += theme.getHoverBrightnessAdjustment(); + } + + b = Math.max(0.0f, Math.min(1.0f, b)); + bgColor = Color.getHSBColor(baseColor.getHue(), baseColor.getSaturation(), b); + } + else { + final var hsb = new float[3]; + Color.RGBtoHSB(backgroundColor.getRed(), backgroundColor.getGreen(), backgroundColor.getBlue(), hsb); + + float b = !toggled ? 0.20F : 0.40F; + if (pressed) { + b += theme.getPressedBrightnessAdjustment(); + } + else if (hovered) { + b += theme.getHoverBrightnessAdjustment(); + } + + b = Math.max(0.0f, Math.min(1.0f, b)); + bgColor = Color.getHSBColor(hsb[0], hsb[1], b); + } + + if (!enabled) { + final var hsb = Color.RGBtoHSB(bgColor.getRed(), bgColor.getGreen(), bgColor.getBlue(), null); + bgColor = Color.getHSBColor(hsb[0], Math.min(1.0f, hsb[1] * 0.15f), Math.min(1.0f, hsb[2] * 0.45f)); + } + + g2d.setColor(bgColor); + g2d.fillRect(x, y, width, height); + + final var borderStrength = Math.max(1, (int) (1 * scaleFactor)); + final var outer = hovered || toggled ? theme.getSelectionPrimary().toColor() : theme.getBorderOuter().toColor(); + final var inner = enabled ? theme.getBorderInner().toColor() : theme.getBorderInnerDisabled().toColor(); + this.drawDecorativeBorder(g2d, x, y, width, height, borderStrength, outer); + + final var inset = Math.max(1, borderStrength); + if (width > inset * 3 && height > inset * 3) { + this.drawDecorativeBorder(g2d, x + inset, y + inset, width - inset * 2, height - inset * 2, Math.max(1, borderStrength), inner); + } + } +} diff --git a/src/main/java/de/extio/game_engine/renderer/g2d/theme/TerminalThemeFactoryBean.java b/src/main/java/de/extio/game_engine/renderer/g2d/theme/TerminalThemeFactoryBean.java new file mode 100644 index 0000000..ef59231 --- /dev/null +++ b/src/main/java/de/extio/game_engine/renderer/g2d/theme/TerminalThemeFactoryBean.java @@ -0,0 +1,37 @@ +package de.extio.game_engine.renderer.g2d.theme; + +import org.springframework.beans.factory.FactoryBean; + +public class TerminalThemeFactoryBean implements FactoryBean { + + @Override + public Theme getObject() { + return Theme.builder() + .name("Terminal") + .font("GoogleSansCode-Regular.ttf") + .patternRendererName("terminalPatternRenderer") + .borderOuter(new HSBColor(0.10f, 0.45f, 0.45f)) + .borderInner(new HSBColor(0.10f, 0.30f, 0.70f)) + .borderInnerDisabled(new HSBColor(0.10f, 0.15f, 0.25f)) + .backgroundNormal(new HSBColor(0.08f, 0.65f, 0.12f)) + .backgroundSelected(new HSBColor(0.12f, 0.70f, 0.35f)) + .textNormal(new HSBColor(0.12f, 0.85f, 0.95f)) + .textDisabled(new HSBColor(0.12f, 0.45f, 0.60f)) + .selectionPrimary(new HSBColor(0.10f, 0.75f, 0.55f)) + .selectionSecondary(new HSBColor(0.14f, 0.80f, 0.85f)) + .windowBackground(new HSBColor(0.08f, 0.55f, 0.08f)) + .hoverBrightnessAdjustment(0.18f) + .pressedBrightnessAdjustment(0.32f) + .build(); + } + + @Override + public Class getObjectType() { + return Theme.class; + } + + @Override + public boolean isSingleton() { + return true; + } +}