feat: Add multiple new themes and their corresponding pattern renderers
- Introduced new themes: Contemporary, Dream, Fantasy, Modern, Neon, Noir, and Urban. - Implemented FactoryBeans for each theme to facilitate their creation. - Developed pattern renderers for each theme to define their visual styles. - Updated G2DAutoConfiguration to include new theme beans. - Enhanced DemoModule to support dynamic theme selection with improved layout and positioning.
This commit is contained in:
@@ -12,8 +12,15 @@ import org.springframework.context.annotation.Bean;
|
||||
|
||||
import de.extio.game_engine.renderer.g2d.theme.G2DThemeManager;
|
||||
import de.extio.game_engine.renderer.g2d.theme.PatternRenderer;
|
||||
import de.extio.game_engine.renderer.g2d.theme.ContemporaryThemeFactoryBean;
|
||||
import de.extio.game_engine.renderer.g2d.theme.DreamThemeFactoryBean;
|
||||
import de.extio.game_engine.renderer.g2d.theme.FantasyThemeFactoryBean;
|
||||
import de.extio.game_engine.renderer.g2d.theme.ModernThemeFactoryBean;
|
||||
import de.extio.game_engine.renderer.g2d.theme.NeonThemeFactoryBean;
|
||||
import de.extio.game_engine.renderer.g2d.theme.NoirThemeFactoryBean;
|
||||
import de.extio.game_engine.renderer.g2d.theme.SpacecraftThemeFactoryBean;
|
||||
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.resource.StaticResourceService;
|
||||
|
||||
@@ -50,6 +57,41 @@ public class G2DAutoConfiguration {
|
||||
return new VintageThemeFactoryBean();
|
||||
}
|
||||
|
||||
@Bean
|
||||
FactoryBean<Theme> modernTheme() {
|
||||
return new ModernThemeFactoryBean();
|
||||
}
|
||||
|
||||
@Bean
|
||||
FactoryBean<Theme> contemporaryTheme() {
|
||||
return new ContemporaryThemeFactoryBean();
|
||||
}
|
||||
|
||||
@Bean
|
||||
FactoryBean<Theme> urbanTheme() {
|
||||
return new UrbanThemeFactoryBean();
|
||||
}
|
||||
|
||||
@Bean
|
||||
FactoryBean<Theme> dreamTheme() {
|
||||
return new DreamThemeFactoryBean();
|
||||
}
|
||||
|
||||
@Bean
|
||||
FactoryBean<Theme> fantasyTheme() {
|
||||
return new FantasyThemeFactoryBean();
|
||||
}
|
||||
|
||||
@Bean
|
||||
FactoryBean<Theme> noirTheme() {
|
||||
return new NoirThemeFactoryBean();
|
||||
}
|
||||
|
||||
@Bean
|
||||
FactoryBean<Theme> neonTheme() {
|
||||
return new NeonThemeFactoryBean();
|
||||
}
|
||||
|
||||
@Bean
|
||||
G2DThemeManager g2dThemeManager(
|
||||
final StaticResourceService staticResourceService,
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
package de.extio.game_engine.renderer.g2d.theme;
|
||||
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
|
||||
public class ContemporaryThemeFactoryBean implements FactoryBean<Theme> {
|
||||
|
||||
@Override
|
||||
public Theme getObject() {
|
||||
return Theme.builder()
|
||||
.name("Contemporary")
|
||||
.patternRendererName("modernPatternRenderer")
|
||||
.borderOuter(new HSBColor(0.88f, 0.12f, 0.75f))
|
||||
.borderInner(new HSBColor(0.88f, 0.10f, 0.92f))
|
||||
.borderInnerDisabled(new HSBColor(0.88f, 0.06f, 0.42f))
|
||||
.backgroundNormal(new HSBColor(0.92f, 0.55f, 0.22f))
|
||||
.backgroundSelected(new HSBColor(0.33f, 0.75f, 0.70f))
|
||||
.textNormal(new HSBColor(0.08f, 0.04f, 0.94f))
|
||||
.textDisabled(new HSBColor(0.08f, 0.02f, 0.62f))
|
||||
.selectionPrimary(new HSBColor(0.33f, 0.75f, 0.70f))
|
||||
.selectionSecondary(new HSBColor(0.58f, 0.25f, 0.95f))
|
||||
.windowBackground(new HSBColor(0.92f, 0.55f, 0.12f))
|
||||
.hoverBrightnessAdjustment(0.22f)
|
||||
.pressedBrightnessAdjustment(0.38f)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getObjectType() {
|
||||
return Theme.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSingleton() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
package de.extio.game_engine.renderer.g2d.theme;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Graphics2D;
|
||||
|
||||
import org.springframework.context.annotation.Conditional;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import de.extio.game_engine.renderer.g2d.G2DRendererCondition;
|
||||
import de.extio.game_engine.renderer.g2d.bo.rendering.G2DDrawFont;
|
||||
|
||||
@Conditional(G2DRendererCondition.class)
|
||||
@Component
|
||||
public class DreamPatternRenderer 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) {
|
||||
final var s = Math.max(1, strength);
|
||||
final var arc = Math.max(6, s * 6);
|
||||
|
||||
g2d.setColor(color);
|
||||
g2d.drawRoundRect(x, y, width - 1, height - 1, arc, arc);
|
||||
|
||||
final var dot = Math.max(2, s * 2);
|
||||
g2d.fillOval(x + s, y + s, dot, dot);
|
||||
g2d.fillOval(x + width - s - dot, y + s, dot, dot);
|
||||
g2d.fillOval(x + s, y + height - s - dot, dot, dot);
|
||||
g2d.fillOval(x + width - s - dot, y + height - s - dot, dot, dot);
|
||||
}
|
||||
|
||||
@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);
|
||||
final var arc = Math.max(6, s * 6);
|
||||
|
||||
g2d.setColor(backgroundColor);
|
||||
g2d.fillRoundRect(x + s, y + s, Math.max(0, width - s * 2), Math.max(0, height - s * 2), arc, arc);
|
||||
|
||||
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 ? 4 : 2), (int) ((thickBorder ? 6 : 3) * scaleFactor));
|
||||
final var s2 = s * 2;
|
||||
|
||||
final var bg = new Color(backgroundColor.getRed(), backgroundColor.getGreen(), backgroundColor.getBlue(), 160);
|
||||
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 int state, final Color backgroundColor, final double scaleFactor, final Theme theme) {
|
||||
final var STATE_HOVERED = 4;
|
||||
final var STATE_TOGGLED = 1;
|
||||
final var STATE_PRESSED = 2;
|
||||
|
||||
final var highlight = (state & (STATE_HOVERED | STATE_TOGGLED)) != 0;
|
||||
final var pressed = (state & STATE_PRESSED) != 0;
|
||||
|
||||
Color bg = backgroundColor;
|
||||
if (bg == null) {
|
||||
bg = theme.getWindowBackground().toColor();
|
||||
}
|
||||
if (highlight) {
|
||||
bg = theme.getSelectionSecondary().toColor();
|
||||
}
|
||||
if (pressed) {
|
||||
bg = theme.getSelectionPrimary().toColor();
|
||||
}
|
||||
|
||||
final var bg2 = new Color(bg.getRed(), bg.getGreen(), bg.getBlue(), 210);
|
||||
g2d.setColor(bg2);
|
||||
g2d.fillRoundRect(0, 0, width, height, Math.max(6, (int) (10 * scaleFactor)), Math.max(6, (int) (10 * scaleFactor)));
|
||||
|
||||
final var s = Math.max(1, (int) (2 * scaleFactor));
|
||||
this.drawDecorativeBorder(g2d, 0, 0, width, height, s, theme.getBorderOuter().toColor());
|
||||
|
||||
if (!enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
final Color fg;
|
||||
if (pressed) {
|
||||
fg = theme.getTextNormal().toColor();
|
||||
}
|
||||
else if (highlight) {
|
||||
fg = Color.BLACK;
|
||||
}
|
||||
else {
|
||||
fg = theme.getTextDisabled().toColor();
|
||||
}
|
||||
g2d.setColor(fg);
|
||||
|
||||
final var fontSize = (int) (15 * scaleFactor);
|
||||
final var textDim = G2DDrawFont.getTextDimensions("X", g2d, 15, scaleFactor);
|
||||
G2DDrawFont.renderText(g2d, textDim, 1.0, ((width - textDim.getX()) / 2), ((height - textDim.getY()) / 2), fontSize, "X");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package de.extio.game_engine.renderer.g2d.theme;
|
||||
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
|
||||
public class DreamThemeFactoryBean implements FactoryBean<Theme> {
|
||||
|
||||
@Override
|
||||
public Theme getObject() {
|
||||
return Theme.builder()
|
||||
.name("Dream")
|
||||
.patternRendererName("dreamPatternRenderer")
|
||||
.borderOuter(new HSBColor(0.74f, 0.22f, 0.80f))
|
||||
.borderInner(new HSBColor(0.83f, 0.18f, 0.95f))
|
||||
.borderInnerDisabled(new HSBColor(0.74f, 0.10f, 0.35f))
|
||||
.backgroundNormal(new HSBColor(0.74f, 0.55f, 0.16f))
|
||||
.backgroundSelected(new HSBColor(0.88f, 0.55f, 0.85f))
|
||||
.textNormal(new HSBColor(0.12f, 0.03f, 0.96f))
|
||||
.textDisabled(new HSBColor(0.12f, 0.02f, 0.70f))
|
||||
.selectionPrimary(new HSBColor(0.88f, 0.55f, 0.85f))
|
||||
.selectionSecondary(new HSBColor(0.55f, 0.30f, 0.95f))
|
||||
.windowBackground(new HSBColor(0.74f, 0.70f, 0.07f))
|
||||
.hoverBrightnessAdjustment(0.28f)
|
||||
.pressedBrightnessAdjustment(0.45f)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getObjectType() {
|
||||
return Theme.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSingleton() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
package de.extio.game_engine.renderer.g2d.theme;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Graphics2D;
|
||||
|
||||
import org.springframework.context.annotation.Conditional;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import de.extio.game_engine.renderer.g2d.G2DRendererCondition;
|
||||
|
||||
@Conditional(G2DRendererCondition.class)
|
||||
@Component
|
||||
public class FantasyPatternRenderer 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) {
|
||||
final var s = Math.max(1, strength);
|
||||
final var s2 = s * 2;
|
||||
final var s3 = s * 3;
|
||||
|
||||
g2d.setColor(color);
|
||||
|
||||
g2d.fillRect(x, y, width, s);
|
||||
g2d.fillRect(x, y + height - s, width, s);
|
||||
g2d.fillRect(x, y, s, height);
|
||||
g2d.fillRect(x + width - s, y, s, height);
|
||||
|
||||
g2d.fillRect(x + s2, y + s2, width - s3 * 2, s);
|
||||
g2d.fillRect(x + s2, y + height - s2 - s, width - s3 * 2, s);
|
||||
g2d.fillRect(x + s2, y + s2, s, height - s3 * 2);
|
||||
g2d.fillRect(x + width - s2 - s, y + s2, s, height - s3 * 2);
|
||||
|
||||
final var tri = Math.max(6, s * 4);
|
||||
g2d.fillPolygon(new int[] { x + s, x + tri, x + s }, new int[] { y + s, y + s, y + tri }, 3);
|
||||
g2d.fillPolygon(new int[] { x + width - s, x + width - tri, x + width - s }, new int[] { y + s, y + s, y + tri }, 3);
|
||||
g2d.fillPolygon(new int[] { x + s, x + tri, x + s }, new int[] { y + height - s, y + height - s, y + height - tri }, 3);
|
||||
g2d.fillPolygon(new int[] { x + width - s, x + width - tri, x + width - s }, new int[] { y + height - s, y + height - s, y + height - tri }, 3);
|
||||
}
|
||||
|
||||
@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 ? 5 : 3), (int) ((thickBorder ? 7 : 4) * scaleFactor));
|
||||
final var s2 = s * 2;
|
||||
|
||||
final var bg = new Color(backgroundColor.getRed(), backgroundColor.getGreen(), backgroundColor.getBlue(), 175);
|
||||
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 int state, final Color backgroundColor, final double scaleFactor, final Theme theme) {
|
||||
final var STATE_HOVERED = 4;
|
||||
final var STATE_TOGGLED = 1;
|
||||
final var STATE_PRESSED = 2;
|
||||
|
||||
final var highlight = (state & (STATE_HOVERED | STATE_TOGGLED)) != 0;
|
||||
final var pressed = (state & STATE_PRESSED) != 0;
|
||||
|
||||
Color bg = backgroundColor;
|
||||
if (bg == null) {
|
||||
bg = theme.getBorderInner().toColor();
|
||||
}
|
||||
if (highlight) {
|
||||
bg = theme.getSelectionSecondary().toColor();
|
||||
}
|
||||
if (pressed) {
|
||||
bg = theme.getSelectionPrimary().toColor();
|
||||
}
|
||||
|
||||
g2d.setColor(bg);
|
||||
g2d.fillRect(0, 0, width, height);
|
||||
|
||||
final var s = Math.max(1, (int) (2 * scaleFactor));
|
||||
this.drawDecorativeBorder(g2d, 0, 0, width, height, s, theme.getBorderOuter().toColor());
|
||||
|
||||
if (!enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
final Color fg;
|
||||
if (pressed) {
|
||||
fg = theme.getTextNormal().toColor();
|
||||
}
|
||||
else if (highlight) {
|
||||
fg = Color.BLACK;
|
||||
}
|
||||
else {
|
||||
fg = theme.getTextDisabled().toColor();
|
||||
}
|
||||
g2d.setColor(fg);
|
||||
|
||||
final var crossSize = Math.min(width, height) / 2;
|
||||
final var centerX = width / 2;
|
||||
final var centerY = height / 2;
|
||||
final var t = Math.max(1, (int) (2 * scaleFactor));
|
||||
g2d.fillRect(centerX - crossSize / 2, centerY - t / 2, crossSize, t);
|
||||
g2d.fillRect(centerX - t / 2, centerY - crossSize / 2, t, crossSize);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package de.extio.game_engine.renderer.g2d.theme;
|
||||
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
|
||||
public class FantasyThemeFactoryBean implements FactoryBean<Theme> {
|
||||
|
||||
@Override
|
||||
public Theme getObject() {
|
||||
return Theme.builder()
|
||||
.name("Fantasy")
|
||||
.patternRendererName("fantasyPatternRenderer")
|
||||
.borderOuter(new HSBColor(0.12f, 0.55f, 0.65f))
|
||||
.borderInner(new HSBColor(0.14f, 0.35f, 0.92f))
|
||||
.borderInnerDisabled(new HSBColor(0.12f, 0.25f, 0.25f))
|
||||
.backgroundNormal(new HSBColor(0.32f, 0.70f, 0.12f))
|
||||
.backgroundSelected(new HSBColor(0.13f, 0.80f, 0.75f))
|
||||
.textNormal(new HSBColor(0.12f, 0.10f, 0.96f))
|
||||
.textDisabled(new HSBColor(0.12f, 0.05f, 0.65f))
|
||||
.selectionPrimary(new HSBColor(0.13f, 0.80f, 0.75f))
|
||||
.selectionSecondary(new HSBColor(0.58f, 0.40f, 0.90f))
|
||||
.windowBackground(new HSBColor(0.32f, 0.75f, 0.06f))
|
||||
.hoverBrightnessAdjustment(0.18f)
|
||||
.pressedBrightnessAdjustment(0.34f)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getObjectType() {
|
||||
return Theme.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSingleton() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
package de.extio.game_engine.renderer.g2d.theme;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Graphics2D;
|
||||
|
||||
import org.springframework.context.annotation.Conditional;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import de.extio.game_engine.renderer.g2d.G2DRendererCondition;
|
||||
import de.extio.game_engine.renderer.g2d.bo.rendering.G2DDrawFont;
|
||||
|
||||
@Conditional(G2DRendererCondition.class)
|
||||
@Component
|
||||
public class ModernPatternRenderer 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) {
|
||||
final var s = Math.max(1, strength);
|
||||
final var s2 = s * 2;
|
||||
|
||||
g2d.setColor(color);
|
||||
|
||||
g2d.fillRect(x, y, width, s);
|
||||
g2d.fillRect(x, y + height - s, width, s);
|
||||
g2d.fillRect(x, y, s, height);
|
||||
g2d.fillRect(x + width - s, y, s, height);
|
||||
|
||||
final var notch = Math.max(1, s2);
|
||||
g2d.fillRect(x + s, y + s, notch, s);
|
||||
g2d.fillRect(x + width - s - notch, y + s, notch, s);
|
||||
g2d.fillRect(x + s, y + height - s - s, notch, s);
|
||||
g2d.fillRect(x + width - s - notch, y + height - s - s, notch, s);
|
||||
}
|
||||
|
||||
@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 ? 3 : 2), (int) ((thickBorder ? 5 : 3) * scaleFactor));
|
||||
final var s2 = s * 2;
|
||||
|
||||
final var bg = new Color(backgroundColor.getRed(), backgroundColor.getGreen(), backgroundColor.getBlue(), 210);
|
||||
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 int state, final Color backgroundColor, final double scaleFactor, final Theme theme) {
|
||||
final var STATE_HOVERED = 4;
|
||||
final var STATE_TOGGLED = 1;
|
||||
final var STATE_PRESSED = 2;
|
||||
|
||||
final var highlight = (state & (STATE_HOVERED | STATE_TOGGLED)) != 0;
|
||||
final var pressed = (state & STATE_PRESSED) != 0;
|
||||
|
||||
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) (2 * 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 = Color.BLACK;
|
||||
}
|
||||
g2d.setColor(textColor);
|
||||
|
||||
final var fontSize = (int) (14 * scaleFactor);
|
||||
final var textDim = G2DDrawFont.getTextDimensions("X", g2d, 14, scaleFactor);
|
||||
G2DDrawFont.renderText(g2d, textDim, 1.0, ((width - textDim.getX()) / 2), ((height - textDim.getY()) / 2), fontSize, "X");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package de.extio.game_engine.renderer.g2d.theme;
|
||||
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
|
||||
public class ModernThemeFactoryBean implements FactoryBean<Theme> {
|
||||
|
||||
@Override
|
||||
public Theme getObject() {
|
||||
return Theme.builder()
|
||||
.name("Modern")
|
||||
.patternRendererName("modernPatternRenderer")
|
||||
.borderOuter(new HSBColor(0.58f, 0.08f, 0.82f))
|
||||
.borderInner(new HSBColor(0.58f, 0.10f, 0.92f))
|
||||
.borderInnerDisabled(new HSBColor(0.58f, 0.05f, 0.45f))
|
||||
.backgroundNormal(new HSBColor(0.60f, 0.55f, 0.20f))
|
||||
.backgroundSelected(new HSBColor(0.14f, 0.75f, 0.78f))
|
||||
.textNormal(new HSBColor(0.00f, 0.00f, 0.92f))
|
||||
.textDisabled(new HSBColor(0.00f, 0.00f, 0.65f))
|
||||
.selectionPrimary(new HSBColor(0.14f, 0.75f, 0.78f))
|
||||
.selectionSecondary(new HSBColor(0.50f, 0.20f, 0.98f))
|
||||
.windowBackground(new HSBColor(0.60f, 0.45f, 0.10f))
|
||||
.hoverBrightnessAdjustment(0.20f)
|
||||
.pressedBrightnessAdjustment(0.35f)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getObjectType() {
|
||||
return Theme.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSingleton() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package de.extio.game_engine.renderer.g2d.theme;
|
||||
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
|
||||
public class NeonThemeFactoryBean implements FactoryBean<Theme> {
|
||||
|
||||
@Override
|
||||
public Theme getObject() {
|
||||
return Theme.builder()
|
||||
.name("Neon")
|
||||
.patternRendererName("dreamPatternRenderer")
|
||||
.borderOuter(new HSBColor(0.83f, 0.80f, 0.95f))
|
||||
.borderInner(new HSBColor(0.52f, 0.85f, 0.92f))
|
||||
.borderInnerDisabled(new HSBColor(0.83f, 0.20f, 0.25f))
|
||||
.backgroundNormal(new HSBColor(0.74f, 0.80f, 0.09f))
|
||||
.backgroundSelected(new HSBColor(0.52f, 0.85f, 0.92f))
|
||||
.textNormal(new HSBColor(0.00f, 0.00f, 0.98f))
|
||||
.textDisabled(new HSBColor(0.00f, 0.00f, 0.70f))
|
||||
.selectionPrimary(new HSBColor(0.52f, 0.85f, 0.92f))
|
||||
.selectionSecondary(new HSBColor(0.16f, 0.85f, 0.95f))
|
||||
.windowBackground(new HSBColor(0.74f, 0.90f, 0.05f))
|
||||
.hoverBrightnessAdjustment(0.30f)
|
||||
.pressedBrightnessAdjustment(0.55f)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getObjectType() {
|
||||
return Theme.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSingleton() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package de.extio.game_engine.renderer.g2d.theme;
|
||||
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
|
||||
public class NoirThemeFactoryBean implements FactoryBean<Theme> {
|
||||
|
||||
@Override
|
||||
public Theme getObject() {
|
||||
return Theme.builder()
|
||||
.name("Noir")
|
||||
.patternRendererName("urbanPatternRenderer")
|
||||
.borderOuter(new HSBColor(0.00f, 0.00f, 0.18f))
|
||||
.borderInner(new HSBColor(0.00f, 0.00f, 0.45f))
|
||||
.borderInnerDisabled(new HSBColor(0.00f, 0.00f, 0.12f))
|
||||
.backgroundNormal(new HSBColor(0.62f, 0.20f, 0.08f))
|
||||
.backgroundSelected(new HSBColor(0.12f, 0.15f, 0.85f))
|
||||
.textNormal(new HSBColor(0.00f, 0.00f, 0.92f))
|
||||
.textDisabled(new HSBColor(0.00f, 0.00f, 0.55f))
|
||||
.selectionPrimary(new HSBColor(0.12f, 0.15f, 0.85f))
|
||||
.selectionSecondary(new HSBColor(0.58f, 0.12f, 0.75f))
|
||||
.windowBackground(new HSBColor(0.62f, 0.30f, 0.05f))
|
||||
.hoverBrightnessAdjustment(0.12f)
|
||||
.pressedBrightnessAdjustment(0.26f)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getObjectType() {
|
||||
return Theme.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSingleton() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
package de.extio.game_engine.renderer.g2d.theme;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Graphics2D;
|
||||
|
||||
import org.springframework.context.annotation.Conditional;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import de.extio.game_engine.renderer.g2d.G2DRendererCondition;
|
||||
|
||||
@Conditional(G2DRendererCondition.class)
|
||||
@Component
|
||||
public class UrbanPatternRenderer 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) {
|
||||
final var s = Math.max(1, strength);
|
||||
final var seg = Math.max(s * 3, 6);
|
||||
final var gap = Math.max(s, 2);
|
||||
|
||||
g2d.setColor(color);
|
||||
|
||||
for (int xx = x; xx < x + width; xx += seg + gap) {
|
||||
final var w = Math.min(seg, x + width - xx);
|
||||
g2d.fillRect(xx, y, w, s);
|
||||
g2d.fillRect(xx, y + height - s, w, s);
|
||||
}
|
||||
|
||||
for (int yy = y; yy < y + height; yy += seg + gap) {
|
||||
final var h = Math.min(seg, y + height - yy);
|
||||
g2d.fillRect(x, yy, s, h);
|
||||
g2d.fillRect(x + width - s, yy, s, h);
|
||||
}
|
||||
|
||||
final var pin = Math.max(2, s * 2);
|
||||
g2d.fillRect(x + s, y + s, pin, pin);
|
||||
g2d.fillRect(x + width - s - pin, y + s, pin, pin);
|
||||
g2d.fillRect(x + s, y + height - s - pin, pin, pin);
|
||||
g2d.fillRect(x + width - s - pin, y + height - s - pin, pin, pin);
|
||||
}
|
||||
|
||||
@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 ? 4 : 2), (int) ((thickBorder ? 6 : 3) * scaleFactor));
|
||||
final var s2 = s * 2;
|
||||
|
||||
final var bg = new Color(backgroundColor.getRed(), backgroundColor.getGreen(), backgroundColor.getBlue(), 190);
|
||||
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 int state, final Color backgroundColor, final double scaleFactor, final Theme theme) {
|
||||
final var STATE_HOVERED = 4;
|
||||
final var STATE_TOGGLED = 1;
|
||||
final var STATE_PRESSED = 2;
|
||||
|
||||
final var highlight = (state & (STATE_HOVERED | STATE_TOGGLED)) != 0;
|
||||
final var pressed = (state & STATE_PRESSED) != 0;
|
||||
|
||||
final var base = (backgroundColor != null) ? backgroundColor : theme.getBorderInner().toColor();
|
||||
final var hsb = Color.RGBtoHSB(base.getRed(), base.getGreen(), base.getBlue(), null);
|
||||
|
||||
final Color bg;
|
||||
if (pressed) {
|
||||
bg = theme.getSelectionPrimary().toColor();
|
||||
}
|
||||
else if (highlight) {
|
||||
bg = theme.getSelectionSecondary().toColor();
|
||||
}
|
||||
else {
|
||||
bg = Color.getHSBColor(hsb[0], Math.min(1.0f, hsb[1] * 0.6f), Math.min(1.0f, hsb[2] * 0.35f));
|
||||
}
|
||||
|
||||
g2d.setColor(bg);
|
||||
g2d.fillRect(0, 0, width, height);
|
||||
|
||||
final var s = Math.max(1, (int) (2 * scaleFactor));
|
||||
this.drawDecorativeBorder(g2d, 0, 0, width, height, s, theme.getBorderOuter().toColor());
|
||||
|
||||
if (!enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
final var crossSize = Math.min(width, height) / 2;
|
||||
final var centerX = width / 2;
|
||||
final var centerY = height / 2;
|
||||
final var t = Math.max(1, (int) (2 * scaleFactor));
|
||||
|
||||
final Color fg;
|
||||
if (pressed) {
|
||||
fg = theme.getTextNormal().toColor();
|
||||
}
|
||||
else if (highlight) {
|
||||
fg = Color.BLACK;
|
||||
}
|
||||
else {
|
||||
fg = theme.getTextDisabled().toColor();
|
||||
}
|
||||
g2d.setColor(fg);
|
||||
|
||||
g2d.fillRect(centerX - crossSize / 2, centerY - t / 2, crossSize, t);
|
||||
g2d.fillRect(centerX - t / 2, centerY - crossSize / 2, t, crossSize);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package de.extio.game_engine.renderer.g2d.theme;
|
||||
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
|
||||
public class UrbanThemeFactoryBean implements FactoryBean<Theme> {
|
||||
|
||||
@Override
|
||||
public Theme getObject() {
|
||||
return Theme.builder()
|
||||
.name("Urban")
|
||||
.patternRendererName("urbanPatternRenderer")
|
||||
.borderOuter(new HSBColor(0.06f, 0.05f, 0.35f))
|
||||
.borderInner(new HSBColor(0.06f, 0.08f, 0.70f))
|
||||
.borderInnerDisabled(new HSBColor(0.06f, 0.04f, 0.22f))
|
||||
.backgroundNormal(new HSBColor(0.58f, 0.25f, 0.18f))
|
||||
.backgroundSelected(new HSBColor(0.02f, 0.75f, 0.70f))
|
||||
.textNormal(new HSBColor(0.12f, 0.05f, 0.92f))
|
||||
.textDisabled(new HSBColor(0.12f, 0.02f, 0.60f))
|
||||
.selectionPrimary(new HSBColor(0.02f, 0.75f, 0.70f))
|
||||
.selectionSecondary(new HSBColor(0.52f, 0.18f, 0.92f))
|
||||
.windowBackground(new HSBColor(0.58f, 0.30f, 0.10f))
|
||||
.hoverBrightnessAdjustment(0.18f)
|
||||
.pressedBrightnessAdjustment(0.32f)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getObjectType() {
|
||||
return Theme.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSingleton() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -24,6 +24,7 @@ import de.extio.game_engine.renderer.model.bo.HorizontalAlignment;
|
||||
import de.extio.game_engine.renderer.model.event.UiControlEvent;
|
||||
import de.extio.game_engine.renderer.work.RenderingBoPool;
|
||||
import de.extio.game_engine.resource.StaticResource;
|
||||
import de.extio.game_engine.spatial2.model.ImmutableCoordI2;
|
||||
|
||||
public class DemoModule extends AbstractClientModule {
|
||||
|
||||
@@ -48,7 +49,7 @@ public class DemoModule extends AbstractClientModule {
|
||||
private Window mainWindow;
|
||||
|
||||
private Window secondaryWindow;
|
||||
|
||||
|
||||
private Window themeSelectionWindow;
|
||||
|
||||
private final Map<String, String> themeSelectionByControlId = new HashMap<>();
|
||||
@@ -56,19 +57,19 @@ public class DemoModule extends AbstractClientModule {
|
||||
@Override
|
||||
public void onLoad() {
|
||||
this.mainWindow = this.applicationContext.getBean(Window.class);
|
||||
this.mainWindow.setNormalizedPosition(RendererControl.REFERENCE_RESOLUTION.divide(9));
|
||||
this.mainWindow.setNormalizedDimension(RendererControl.REFERENCE_RESOLUTION.divide(9).multiply(7));
|
||||
this.mainWindow.setNormalizedPosition(centeredPosition(this.mainWindow.getNormalizedDimension()));
|
||||
this.mainWindow.setDraggable(true);
|
||||
|
||||
this.secondaryWindow = this.applicationContext.getBean(Window.class);
|
||||
this.secondaryWindow.setNormalizedPosition(RendererControl.REFERENCE_RESOLUTION.divide(7).multiply(3));
|
||||
this.secondaryWindow.setNormalizedDimension(RendererControl.REFERENCE_RESOLUTION.divide(7).multiply(2));
|
||||
this.secondaryWindow.setNormalizedPosition(centeredPosition(this.secondaryWindow.getNormalizedDimension()));
|
||||
this.secondaryWindow.setDraggable(true);
|
||||
this.secondaryWindow.setCloseButton(true);
|
||||
|
||||
this.themeSelectionWindow = this.applicationContext.getBean(Window.class);
|
||||
this.themeSelectionWindow.setNormalizedPosition(RendererControl.REFERENCE_RESOLUTION.divide(7).multiply(3));
|
||||
this.themeSelectionWindow.setNormalizedDimension(RendererControl.REFERENCE_RESOLUTION.divide(7).multiply(2));
|
||||
this.themeSelectionWindow.setNormalizedPosition(centeredPosition(this.themeSelectionWindow.getNormalizedDimension()));
|
||||
this.themeSelectionWindow.setDraggable(true);
|
||||
this.themeSelectionWindow.setCloseButton(true);
|
||||
|
||||
@@ -209,38 +210,50 @@ public class DemoModule extends AbstractClientModule {
|
||||
final var title = themes.size() <= 1
|
||||
? "Theme"
|
||||
: "Select Theme";
|
||||
|
||||
final var paddingX = 20;
|
||||
final var paddingBottom = 24;
|
||||
final var columns = 2;
|
||||
final var columnGap = 24;
|
||||
final var buttonWidth = 340;
|
||||
final var buttonHeight = 54;
|
||||
final var headerHeight = 60;
|
||||
final var currentHeight = 40;
|
||||
final var startY = 150;
|
||||
final var gapY = 14;
|
||||
final var rows = (themes.size() + columns - 1) / columns;
|
||||
|
||||
final var desiredWidth = (paddingX * 2) + (columns * buttonWidth) + ((columns - 1) * columnGap);
|
||||
final var desiredHeight = startY + (rows * buttonHeight) + (Math.max(0, rows - 1) * gapY) + paddingBottom;
|
||||
this.themeSelectionWindow.setNormalizedDimension(ImmutableCoordI2.create(desiredWidth, desiredHeight));
|
||||
this.themeSelectionWindow.setNormalizedPosition(centeredPosition(ImmutableCoordI2.create(desiredWidth, desiredHeight)));
|
||||
|
||||
var bo = this.renderingBoPool.acquire("DemoModule_ThemeSelect_Label_Title", ControlRenderingBo.class)
|
||||
.setCaption(title)
|
||||
.setFontSize(42)
|
||||
.setType(LabelControl.class)
|
||||
.setVisible(true)
|
||||
.setEnabled(true)
|
||||
.withDimensionAbsolute(RendererControl.REFERENCE_RESOLUTION.divide(7).multiply(2).substract(20).getX(), 60)
|
||||
.withPositionRelative(10, 30);
|
||||
var bo = this.renderingBoPool.acquire("DemoModule_ThemeSelect_Text_Title", DrawFontRenderingBo.class)
|
||||
.setText(title)
|
||||
.setSize(42)
|
||||
.setAlignment(HorizontalAlignment.CENTER)
|
||||
.withDimensionAbsolute(desiredWidth - (paddingX * 2), headerHeight)
|
||||
.withPositionRelative(paddingX, 30);
|
||||
this.themeSelectionWindow.putRenderingBo(bo);
|
||||
|
||||
final var currentTheme = this.themeManager.getCurrentTheme();
|
||||
final var currentThemeName = currentTheme != null ? currentTheme.getName() : "";
|
||||
bo = this.renderingBoPool.acquire("DemoModule_ThemeSelect_Label_Current", ControlRenderingBo.class)
|
||||
.setCaption(currentThemeName.isBlank() ? "" : "Current: " + currentThemeName)
|
||||
.setFontSize(24)
|
||||
.setType(LabelControl.class)
|
||||
.setVisible(true)
|
||||
.setEnabled(true)
|
||||
.withDimensionAbsolute(RendererControl.REFERENCE_RESOLUTION.divide(7).multiply(2).substract(20).getX(), 40)
|
||||
.withPositionRelative(10, 95);
|
||||
bo = this.renderingBoPool.acquire("DemoModule_ThemeSelect_Text_Current", DrawFontRenderingBo.class)
|
||||
.setText(currentThemeName.isBlank() ? "" : "Current: " + currentThemeName)
|
||||
.setSize(24)
|
||||
.setAlignment(HorizontalAlignment.CENTER)
|
||||
.withDimensionAbsolute(desiredWidth - (paddingX * 2), currentHeight)
|
||||
.withPositionRelative(paddingX, 95);
|
||||
this.themeSelectionWindow.putRenderingBo(bo);
|
||||
|
||||
final var buttonWidth = 340;
|
||||
final var buttonHeight = 54;
|
||||
final var startY = 150;
|
||||
final var gap = 14;
|
||||
|
||||
for (var i = 0; i < themes.size(); i++) {
|
||||
final var themeName = themes.get(i);
|
||||
final var controlId = "DemoModule_ThemeSelect_Button_" + sanitizeThemeId(themeName);
|
||||
this.themeSelectionByControlId.put(controlId, themeName);
|
||||
final var column = i % columns;
|
||||
final var row = i / columns;
|
||||
final var x = paddingX + (column * (buttonWidth + columnGap));
|
||||
final var y = startY + (row * (buttonHeight + gapY));
|
||||
|
||||
bo = this.renderingBoPool.acquire(controlId, ControlRenderingBo.class)
|
||||
.setCaption(themeName)
|
||||
@@ -249,13 +262,20 @@ public class DemoModule extends AbstractClientModule {
|
||||
.setVisible(true)
|
||||
.setEnabled(true)
|
||||
.withDimensionAbsolute(buttonWidth, buttonHeight)
|
||||
.withPositionRelative((RendererControl.REFERENCE_RESOLUTION.divide(7).multiply(2).getX() - buttonWidth) / 2, startY + i * (buttonHeight + gap));
|
||||
.withPositionRelative(x, y);
|
||||
this.themeSelectionWindow.putRenderingBo(bo);
|
||||
}
|
||||
|
||||
this.themeSelectionWindow.draw();
|
||||
}
|
||||
|
||||
private static ImmutableCoordI2 centeredPosition(final de.extio.game_engine.spatial2.model.CoordI2 dimension) {
|
||||
final var ref = RendererControl.REFERENCE_RESOLUTION;
|
||||
final var x = Math.max(0, (ref.getX() - dimension.getX()) / 2);
|
||||
final var y = Math.max(0, (ref.getY() - dimension.getY()) / 2);
|
||||
return ImmutableCoordI2.create(x, y);
|
||||
}
|
||||
|
||||
private static String sanitizeThemeId(final String themeName) {
|
||||
if (themeName == null || themeName.isBlank()) {
|
||||
return "Unknown";
|
||||
|
||||
Reference in New Issue
Block a user