From 974ee5765e26243fb1e45e96866ee8ce74af99b4 Mon Sep 17 00:00:00 2001 From: Mario Date: Wed, 19 Aug 2026 22:21:32 +0200 Subject: [PATCH] Ein wenig an der GUI gebastetl --- .../resources/Textures/menu/button_quit.png | Bin 6964 -> 7099 bytes .../main/java/de/blight/editor/EditorApp.java | 4 +- .../de/blight/game/config/MenuScreen.java | 124 ++++++++++++++++-- .../java/de/blight/game/config/NinePatch.java | 17 ++- 4 files changed, 132 insertions(+), 13 deletions(-) diff --git a/blight-assets/src/main/resources/Textures/menu/button_quit.png b/blight-assets/src/main/resources/Textures/menu/button_quit.png index 967bcf46393b8113cd08c6787d2cbe79016fbed4..4830c9852f22fa8e7a9ed346a3d0ece5f3ebd8d2 100644 GIT binary patch delta 3792 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 a{}ms0R)JmxVXpB20000NAQaP diff --git a/blight-editor/src/main/java/de/blight/editor/EditorApp.java b/blight-editor/src/main/java/de/blight/editor/EditorApp.java index 7365b7b..9491272 100644 --- a/blight-editor/src/main/java/de/blight/editor/EditorApp.java +++ b/blight-editor/src/main/java/de/blight/editor/EditorApp.java @@ -11326,8 +11326,10 @@ public class EditorApp extends Application { var clip = clipCombo.getValue(); if (action != null && clip != null) { String entry = action.name() + " → " + clip; - if (!animSetActionListView.getItems().contains(entry)) + if (!animSetActionListView.getItems().contains(entry)) { animSetActionListView.getItems().add(entry); + autoSaveAnimSet(); + } } }); } diff --git a/blight-game/src/main/java/de/blight/game/config/MenuScreen.java b/blight-game/src/main/java/de/blight/game/config/MenuScreen.java index 235c39d..58e2eb5 100644 --- a/blight-game/src/main/java/de/blight/game/config/MenuScreen.java +++ b/blight-game/src/main/java/de/blight/game/config/MenuScreen.java @@ -18,6 +18,12 @@ import com.jme3.renderer.queue.RenderQueue; import com.jme3.scene.Geometry; import com.jme3.scene.Node; import com.jme3.scene.shape.Quad; +import com.jme3.texture.Image; +import com.jme3.texture.Texture; +import com.jme3.texture.Texture2D; +import com.jme3.texture.image.ColorSpace; +import com.jme3.util.BufferUtils; +import java.nio.ByteBuffer; import de.blight.game.post.GaussianBlurFilter; import de.blight.game.scene.WorldScene; @@ -65,8 +71,15 @@ public abstract class MenuScreen extends BaseAppState { private final String MAP_CLICK = "_MsClick_" + System.identityHashCode(this); - private record Btn(float x, float y, float w, float h, Runnable action) {} + private record Btn(float x, float y, float w, float h, Runnable action, + Node patchNode, BitmapText label) {} private final List buttons = new ArrayList<>(); + private Btn pressedBtn = null; + private Btn hoveredBtn = null; + private Node hoverGlow = null; + private Texture2D glowTex = null; + private static final float PRESS_DX = 1f, PRESS_DY = -2f; + private static final float GLOW_PAD = 20f; // ── Lifecycle ───────────────────────────────────────────────────────────── @@ -114,6 +127,9 @@ public abstract class MenuScreen extends BaseAppState { if (canvasNode != null) { guiNode.detachChild(canvasNode); canvasNode = null; } panel = null; buttons.clear(); + pressedBtn = null; + hoveredBtn = null; + if (hoverGlow != null) { hoverGlow.removeFromParent(); hoverGlow = null; } if (withBlur()) removeBlur(); } @@ -171,7 +187,8 @@ public abstract class MenuScreen extends BaseAppState { case ARROW -> NinePatch.buttonArrow(assets); default -> NinePatch.button(assets); }; - parent.attachChild(patch.build(x, y, w, h, 0f)); + Node patchNode = patch.build(x, y, w, h, 0f); + parent.attachChild(patchNode); ColorRGBA col = (style == BtnStyle.DISABLED) ? UiTheme.COL_MUTED : UiTheme.COL_WHITE; BitmapText lbl = crispText(label, UiTheme.FONT_LABEL, col); @@ -180,21 +197,108 @@ public abstract class MenuScreen extends BaseAppState { parent.attachChild(lbl); if (style != BtnStyle.DISABLED && action != null) { - buttons.add(new Btn(x, y, w, h, action)); + buttons.add(new Btn(x, y, w, h, action, patchNode, lbl)); } } + // ── Update-Loop (Hover) ─────────────────────────────────────────────────── + + @Override + public void update(float tpf) { + if (buttons.isEmpty() || panel == null) return; + float[] v = toVirtual(app.getInputManager().getCursorPosition()); + Btn hovered = null; + for (Btn b : buttons) { + if (v[0] >= b.x() && v[0] <= b.x() + b.w() + && v[1] >= b.y() && v[1] <= b.y() + b.h()) { + hovered = b; + break; + } + } + if (hovered != hoveredBtn) { + if (hoverGlow != null) { hoverGlow.removeFromParent(); hoverGlow = null; } + hoveredBtn = hovered; + if (hoveredBtn != null) { + hoverGlow = buildHoverGlow(hoveredBtn); + panel.attachChild(hoverGlow); + } + } + if (hoverGlow != null) { + float dx = (pressedBtn == hoveredBtn) ? PRESS_DX : 0f; + float dy = (pressedBtn == hoveredBtn) ? PRESS_DY : 0f; + hoverGlow.setLocalTranslation(hoveredBtn.x() + dx, hoveredBtn.y() + dy, 0f); + } + } + + private Node buildHoverGlow(Btn b) { + Geometry q = new Geometry("glow", + new Quad(b.w() + GLOW_PAD * 2f, b.h() + GLOW_PAD * 2f)); + Material m = new Material(assets, "Common/MatDefs/Misc/Unshaded.j3md"); + m.setTexture("ColorMap", getGlowTex()); + m.getAdditionalRenderState().setBlendMode(RenderState.BlendMode.AlphaAdditive); + q.setQueueBucket(RenderQueue.Bucket.Gui); + q.setMaterial(m); + // -GLOW_PAD damit der Glow um den Button herausragt; Node selbst wird auf Button-Pos gesetzt + q.setLocalTranslation(-GLOW_PAD, -GLOW_PAD, -0.5f); + Node g = new Node("hover-glow"); + g.attachChild(q); + return g; + } + + private Texture2D getGlowTex() { + if (glowTex != null) return glowTex; + int W = 64, H = 64; + ByteBuffer buf = BufferUtils.createByteBuffer(W * H * 4); + for (int py = 0; py < H; py++) { + for (int px = 0; px < W; px++) { + float u = (px + 0.5f) / W; + float v = (py + 0.5f) / H; + float a = glowFade(u) * glowFade(v); + buf.put((byte) 13); // R ≈ 0.05 × 255 + buf.put((byte) 255); // G = neon + buf.put((byte) 51); // B ≈ 0.20 × 255 + buf.put((byte)(int)(a * 220f)); // A peak ≈ 86 % + } + } + buf.flip(); + glowTex = new Texture2D(new Image(Image.Format.RGBA8, W, H, buf, ColorSpace.Linear)); + glowTex.setMagFilter(Texture.MagFilter.Bilinear); + glowTex.setMinFilter(Texture.MinFilter.BilinearNoMipMaps); + return glowTex; + } + + private static float glowFade(float t) { + float d = Math.abs(t - 0.5f) * 2f; // 0 = Mitte, 1 = Rand + float x = 1f - Math.min(1f, d); + return x * x * (3f - 2f * x); // smoothstep + } + // ── Klick-Listener ──────────────────────────────────────────────────────── private final ActionListener clickListener = (name, pressed, tpf) -> { - if (!pressed) return; float[] v = toVirtual(app.getInputManager().getCursorPosition()); - onScreenClick(v); - for (Btn b : buttons) { - if (v[0] >= b.x() && v[0] <= b.x() + b.w() - && v[1] >= b.y() && v[1] <= b.y() + b.h()) { - b.action().run(); - return; + if (pressed) { + onScreenClick(v); + for (Btn b : buttons) { + if (v[0] >= b.x() && v[0] <= b.x() + b.w() + && v[1] >= b.y() && v[1] <= b.y() + b.h()) { + pressedBtn = b; + b.patchNode().move(PRESS_DX, PRESS_DY, 0f); + b.label().move(PRESS_DX, PRESS_DY, 0f); + return; + } + } + } else { + if (pressedBtn != null) { + pressedBtn.patchNode().move(-PRESS_DX, -PRESS_DY, 0f); + pressedBtn.label().move(-PRESS_DX, -PRESS_DY, 0f); + Btn released = pressedBtn; + pressedBtn = null; + // Aktion nur auslösen wenn Maus noch über dem Button + if (v[0] >= released.x() && v[0] <= released.x() + released.w() + && v[1] >= released.y() && v[1] <= released.y() + released.h()) { + released.action().run(); + } } } }; diff --git a/blight-game/src/main/java/de/blight/game/config/NinePatch.java b/blight-game/src/main/java/de/blight/game/config/NinePatch.java index a55ce17..979d0d7 100644 --- a/blight-game/src/main/java/de/blight/game/config/NinePatch.java +++ b/blight-game/src/main/java/de/blight/game/config/NinePatch.java @@ -171,6 +171,12 @@ public class NinePatch { int t = ty >= 0 ? ty + 1 : h / 4; int b = by >= 0 ? h - by : h / 4; + // Sicherstellen, dass Mittelbereich mindestens 1 Pixel groß ist. + // Fehlerhafte Guide-Erkennung (Pixel mit zufällig passendem Alpha) kann + // sonst l+r >= w oder t+b >= h erzeugen → Endlosschleife in den Tiling-Methoden. + if (l + r >= w) { l = w / 4; r = w / 4; } + if (t + b >= h) { t = h / 4; b = h / 4; } + return new int[]{l, r, t, b}; } @@ -182,12 +188,16 @@ public class NinePatch { * ty, by: Zeilenindizes der oberen/unteren Guide-Linie (PNG-Koordinaten) */ private static void stripGuides(BufferedImage img, int w, int h, int lx, int rx, int ty, int by) { - // Snapshot der Guide-Positionen (vor Modifikation) + // Snapshot der Guide-Positionen (vor Modifikation). + // Als Guide zählen: exakte Guide-Alphas ODER semi-transparente Pixel (alpha < 200) + // auf den bekannten Guide-Zeilen/-Spalten — entsteht durch Anti-Aliasing beim Malen. boolean[][] isGuide = new boolean[h][w]; for (int y = 0; y < h; y++) { for (int x = 0; x < w; x++) { int a = (img.getRGB(x, y) >> 24) & 0xff; - isGuide[y][x] = GUIDE_ALPHAS.contains(a); + boolean exactGuide = GUIDE_ALPHAS.contains(a); + boolean onGuideLine = (x == lx || x == rx || y == ty || y == by); + isGuide[y][x] = exactGuide || (onGuideLine && a < 200 && a > 0); } } @@ -332,6 +342,7 @@ public class NinePatch { float u1, float v1, float u2, float v2, float cw, float ch, float texW, float texH, float z) { + if (cw <= 0 || ch <= 0) return; int iz = 0; for (float py = sy1; py < sy2; py += ch, iz++) { float th = Math.min(ch, sy2 - py); @@ -352,6 +363,7 @@ public class NinePatch { float sx1, float py, float sx2, float ph, float u1, float u2, float vMin, float vMax, float cw, float texW, float z) { + if (cw <= 0) return; int ix = 0; for (float px = sx1; px < sx2; px += cw, ix++) { float tw = Math.min(cw, sx2 - px); @@ -366,6 +378,7 @@ public class NinePatch { float px, float sy1, float pw, float sy2, float uMin, float uMax, float v1, float v2, float ch, float texH, float z) { + if (ch <= 0) return; int iz = 0; for (float py = sy1; py < sy2; py += ch, iz++) { float th = Math.min(ch, sy2 - py);