Anzeige von Areas aktualisiert
This commit is contained in:
@@ -14,7 +14,8 @@ import javafx.scene.layout.*;
|
|||||||
import javafx.util.Duration;
|
import javafx.util.Duration;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.Path;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.nio.file.*;
|
||||||
|
|
||||||
public class AreaEditorView extends BorderPane {
|
public class AreaEditorView extends BorderPane {
|
||||||
|
|
||||||
@@ -57,6 +58,7 @@ public class AreaEditorView extends BorderPane {
|
|||||||
current = saved;
|
current = saved;
|
||||||
reloading = false;
|
reloading = false;
|
||||||
persist();
|
persist();
|
||||||
|
writeDefaultLocalisationIfAbsent(saved.id());
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── Form panel ────────────────────────────────────────────────────────────
|
// ── Form panel ────────────────────────────────────────────────────────────
|
||||||
@@ -229,6 +231,53 @@ public class AreaEditorView extends BorderPane {
|
|||||||
catch (IOException e) { areas.clear(); }
|
catch (IOException e) { areas.clear(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ── Localisation defaults ──────────────────────────────────────────────────
|
||||||
|
|
||||||
|
private void writeDefaultLocalisationIfAbsent(String fullId) {
|
||||||
|
if (fullId == null || fullId.isBlank()) return;
|
||||||
|
String shortId = fullId.startsWith(PREFIX) ? fullId.substring(PREFIX.length()) : fullId;
|
||||||
|
if (shortId.isBlank()) return;
|
||||||
|
String key = fullId + ".name";
|
||||||
|
String defaultName = Character.toUpperCase(shortId.charAt(0)) + shortId.substring(1);
|
||||||
|
|
||||||
|
Path langSrc = ProjectRoot.resolve("blight-lang", "src", "main", "resources", "lang");
|
||||||
|
Path[] langMirrors = {
|
||||||
|
ProjectRoot.resolve("blight-lang", "bin", "main", "lang"),
|
||||||
|
ProjectRoot.resolve("blight-lang", "build", "resources", "main", "lang"),
|
||||||
|
};
|
||||||
|
for (String locale : new String[]{"de", "en"}) {
|
||||||
|
Path src = langSrc.resolve("messages_" + locale + ".properties");
|
||||||
|
try {
|
||||||
|
if (appendKeyIfAbsent(src, key, defaultName)) {
|
||||||
|
for (Path mirrorDir : langMirrors) {
|
||||||
|
Path mirror = mirrorDir.resolve("messages_" + locale + ".properties");
|
||||||
|
if (Files.exists(mirror)) {
|
||||||
|
Files.copy(src, mirror, StandardCopyOption.REPLACE_EXISTING);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
// non-critical
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Returns true if the key was absent and has been appended. */
|
||||||
|
private static boolean appendKeyIfAbsent(Path file, String key, String value) throws IOException {
|
||||||
|
if (!Files.exists(file)) return false;
|
||||||
|
String needle = key + "=";
|
||||||
|
String needleSpace = key + " =";
|
||||||
|
for (String line : Files.readAllLines(file, StandardCharsets.UTF_8)) {
|
||||||
|
String s = line.stripLeading();
|
||||||
|
if (s.startsWith(needle) || s.startsWith(needleSpace)) return false;
|
||||||
|
}
|
||||||
|
String existing = Files.readString(file, StandardCharsets.UTF_8);
|
||||||
|
String sep = existing.endsWith("\n") ? "" : "\n";
|
||||||
|
Files.writeString(file, existing + sep + key + "=" + value + "\n",
|
||||||
|
StandardCharsets.UTF_8, StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// ── Helpers ───────────────────────────────────────────────────────────────
|
// ── Helpers ───────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
private static Label sectionTitle(String text) {
|
private static Label sectionTitle(String text) {
|
||||||
|
|||||||
@@ -9,13 +9,17 @@ import com.jme3.audio.AudioNode;
|
|||||||
import com.jme3.audio.AudioSource;
|
import com.jme3.audio.AudioSource;
|
||||||
import com.jme3.font.BitmapFont;
|
import com.jme3.font.BitmapFont;
|
||||||
import com.jme3.font.BitmapText;
|
import com.jme3.font.BitmapText;
|
||||||
|
import com.jme3.material.Material;
|
||||||
import com.jme3.math.ColorRGBA;
|
import com.jme3.math.ColorRGBA;
|
||||||
import com.jme3.math.Vector3f;
|
import com.jme3.math.Vector3f;
|
||||||
|
import com.jme3.scene.Geometry;
|
||||||
import com.jme3.scene.Node;
|
import com.jme3.scene.Node;
|
||||||
|
import com.jme3.scene.Spatial;
|
||||||
import de.blight.common.AreaDefinition;
|
import de.blight.common.AreaDefinition;
|
||||||
import de.blight.common.AreaDefinitionIO;
|
import de.blight.common.AreaDefinitionIO;
|
||||||
import de.blight.common.AreaIO;
|
import de.blight.common.AreaIO;
|
||||||
import de.blight.common.PlacedArea;
|
import de.blight.common.PlacedArea;
|
||||||
|
import de.blight.game.config.NinePatch;
|
||||||
import de.blight.lang.TextResolver;
|
import de.blight.lang.TextResolver;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@@ -67,7 +71,11 @@ public class MusicSystem extends BaseAppState {
|
|||||||
private boolean isDaytime = true;
|
private boolean isDaytime = true;
|
||||||
|
|
||||||
private BitmapText areaNameText;
|
private BitmapText areaNameText;
|
||||||
|
private Node areaNamePanel = null;
|
||||||
|
private Material areaNamePanelMat = null;
|
||||||
private float areaNameTimer = 0f;
|
private float areaNameTimer = 0f;
|
||||||
|
private boolean areaNameFadingIn = false;
|
||||||
|
private float areaNameFadeInElapsed = 0f;
|
||||||
|
|
||||||
// ── Lifecycle ─────────────────────────────────────────────────────────────
|
// ── Lifecycle ─────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
@@ -97,7 +105,6 @@ public class MusicSystem extends BaseAppState {
|
|||||||
if (def == null) continue;
|
if (def == null) continue;
|
||||||
AudioNode day = loadTrack(def.dayTrack());
|
AudioNode day = loadTrack(def.dayTrack());
|
||||||
AudioNode night = loadTrack(def.nightTrack());
|
AudioNode night = loadTrack(def.nightTrack());
|
||||||
if (day == null && night == null) continue;
|
|
||||||
String rawId = def.id();
|
String rawId = def.id();
|
||||||
String shortId = rawId.startsWith("area.") ? rawId.substring("area.".length()) : rawId;
|
String shortId = rawId.startsWith("area.") ? rawId.substring("area.".length()) : rawId;
|
||||||
data.add(area);
|
data.add(area);
|
||||||
@@ -126,6 +133,7 @@ public class MusicSystem extends BaseAppState {
|
|||||||
phases.clear();
|
phases.clear();
|
||||||
activeSlot.clear();
|
activeSlot.clear();
|
||||||
pendingSlot.clear();
|
pendingSlot.clear();
|
||||||
|
if (areaNamePanel != null) { app.getGuiNode().detachChild(areaNamePanel); areaNamePanel = null; }
|
||||||
if (areaNameText != null) app.getGuiNode().detachChild(areaNameText);
|
if (areaNameText != null) app.getGuiNode().detachChild(areaNameText);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -152,15 +160,22 @@ public class MusicSystem extends BaseAppState {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void update(float tpf) {
|
public void update(float tpf) {
|
||||||
// area name display timer
|
// area name display: fade-in → visible → fade-out
|
||||||
if (areaNameTimer > 0f) {
|
if (areaNameFadingIn) {
|
||||||
|
areaNameFadeInElapsed += tpf;
|
||||||
|
float alpha = Math.min(areaNameFadeInElapsed / AREA_NAME_FADE, 1f);
|
||||||
|
setAreaNameAlpha(alpha);
|
||||||
|
if (areaNameFadeInElapsed >= AREA_NAME_FADE) {
|
||||||
|
areaNameFadingIn = false;
|
||||||
|
setAreaNameAlpha(1f);
|
||||||
|
}
|
||||||
|
} else if (areaNameTimer > 0f) {
|
||||||
areaNameTimer -= tpf;
|
areaNameTimer -= tpf;
|
||||||
if (areaNameTimer <= 0f) {
|
if (areaNameTimer <= 0f) {
|
||||||
areaNameText.setColor(new ColorRGBA(1f, 0.95f, 0.8f, 0f));
|
|
||||||
areaNameTimer = 0f;
|
areaNameTimer = 0f;
|
||||||
|
setAreaNameAlpha(0f);
|
||||||
} else if (areaNameTimer < AREA_NAME_FADE) {
|
} else if (areaNameTimer < AREA_NAME_FADE) {
|
||||||
float alpha = areaNameTimer / AREA_NAME_FADE;
|
setAreaNameAlpha(areaNameTimer / AREA_NAME_FADE);
|
||||||
areaNameText.setColor(new ColorRGBA(1f, 0.95f, 0.8f, alpha));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -205,7 +220,7 @@ public class MusicSystem extends BaseAppState {
|
|||||||
private void startArea(int i) {
|
private void startArea(int i) {
|
||||||
int slot = desiredSlot(i);
|
int slot = desiredSlot(i);
|
||||||
AudioNode n = nodes.get(i)[slot];
|
AudioNode n = nodes.get(i)[slot];
|
||||||
if (n == null) return;
|
if (n != null) {
|
||||||
n.setVolume(0f);
|
n.setVolume(0f);
|
||||||
n.setLooping(true);
|
n.setLooping(true);
|
||||||
rootNode.attachChild(n);
|
rootNode.attachChild(n);
|
||||||
@@ -214,6 +229,9 @@ public class MusicSystem extends BaseAppState {
|
|||||||
pendingSlot.set(i, -1);
|
pendingSlot.set(i, -1);
|
||||||
phases.set(i, Phase.FADING_IN);
|
phases.set(i, Phase.FADING_IN);
|
||||||
log.info("[MusicSystem] Area {} → slot {} gestartet", i, slot == SLOT_DAY ? "Tag" : "Nacht");
|
log.info("[MusicSystem] Area {} → slot {} gestartet", i, slot == SLOT_DAY ? "Tag" : "Nacht");
|
||||||
|
} else {
|
||||||
|
phases.set(i, Phase.ACTIVE);
|
||||||
|
}
|
||||||
showAreaName(i);
|
showAreaName(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -294,13 +312,41 @@ public class MusicSystem extends BaseAppState {
|
|||||||
|
|
||||||
areaNameText.setText(name);
|
areaNameText.setText(name);
|
||||||
float tw = areaNameText.getLineWidth() * 0.5f;
|
float tw = areaNameText.getLineWidth() * 0.5f;
|
||||||
|
float th = areaNameText.getLineHeight() * 0.5f;
|
||||||
float sw = app.getCamera().getWidth();
|
float sw = app.getCamera().getWidth();
|
||||||
float sh = app.getCamera().getHeight();
|
float sh = app.getCamera().getHeight();
|
||||||
areaNameText.setLocalTranslation((sw - tw) / 2f, sh - 40f, 0f);
|
|
||||||
areaNameText.setColor(new ColorRGBA(1f, 0.95f, 0.8f, 1f));
|
float padX = 20f, padY = 10f;
|
||||||
|
float textX = Math.round((sw - tw) / 2f);
|
||||||
|
float textY = sh - 40f;
|
||||||
|
float panelX = Math.round(textX - padX);
|
||||||
|
float panelY = Math.round(textY - th - padY);
|
||||||
|
float panelW = Math.round(tw + padX * 2f);
|
||||||
|
float panelH = Math.round(th + padY * 2f);
|
||||||
|
|
||||||
|
areaNameText.setLocalTranslation(textX, textY, 0f);
|
||||||
|
|
||||||
|
if (areaNamePanel != null) app.getGuiNode().detachChild(areaNamePanel);
|
||||||
|
areaNamePanel = NinePatch.panel(assets).build(panelX, panelY, panelW, panelH, -1f);
|
||||||
|
areaNamePanelMat = null;
|
||||||
|
for (Spatial s : areaNamePanel.getChildren()) {
|
||||||
|
if (s instanceof Geometry g) { areaNamePanelMat = g.getMaterial(); break; }
|
||||||
|
}
|
||||||
|
app.getGuiNode().attachChild(areaNamePanel);
|
||||||
|
|
||||||
|
setAreaNameAlpha(0f);
|
||||||
|
areaNameFadingIn = true;
|
||||||
|
areaNameFadeInElapsed = 0f;
|
||||||
areaNameTimer = AREA_NAME_SHOW;
|
areaNameTimer = AREA_NAME_SHOW;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setAreaNameAlpha(float alpha) {
|
||||||
|
areaNameText.setColor(new ColorRGBA(1f, 0.95f, 0.8f, alpha));
|
||||||
|
if (areaNamePanelMat != null) {
|
||||||
|
areaNamePanelMat.setColor("Color", new ColorRGBA(1f, 1f, 1f, alpha));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ── Helpers ───────────────────────────────────────────────────────────────
|
// ── Helpers ───────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
private float musicVol() {
|
private float musicVol() {
|
||||||
|
|||||||
2
blight-map/src/main/map/blight_area_definitions.bad
Normal file
2
blight-map/src/main/map/blight_area_definitions.bad
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
# id dayTrack nightTrack combatTrack
|
||||||
|
area.strand
|
||||||
@@ -1 +1,2 @@
|
|||||||
# polygon areaId triggersJson
|
# polygon areaId triggersJson
|
||||||
|
255.852,-828.388;281.186,-815.228;272.373,-782.936;237.423,-778.259;223.212,-812.720;227.232,-839.121 area.strand []
|
||||||
|
|||||||
Reference in New Issue
Block a user