diff --git a/assets/imported/animations/alive_again.glb b/assets/imported/animations/alive_again.glb new file mode 100644 index 0000000..107b63b Binary files /dev/null and b/assets/imported/animations/alive_again.glb differ diff --git a/assets/imported/animations/sit_down_bench.glb b/assets/imported/animations/sit_down_bench.glb new file mode 100644 index 0000000..5dd19b3 Binary files /dev/null and b/assets/imported/animations/sit_down_bench.glb differ diff --git a/blight-assets/src/main/resources/animations/clips/alive_again.j3o b/blight-assets/src/main/resources/animations/clips/alive_again.j3o new file mode 100644 index 0000000..a7891e2 Binary files /dev/null and b/blight-assets/src/main/resources/animations/clips/alive_again.j3o differ diff --git a/blight-assets/src/main/resources/animations/clips/get_up_sitting.j3o b/blight-assets/src/main/resources/animations/clips/get_up_sitting.j3o index d74e132..532b3de 100644 Binary files a/blight-assets/src/main/resources/animations/clips/get_up_sitting.j3o and b/blight-assets/src/main/resources/animations/clips/get_up_sitting.j3o differ diff --git a/blight-assets/src/main/resources/animations/clips/idle.j3o b/blight-assets/src/main/resources/animations/clips/idle.j3o index 7eab74f..8c90286 100644 Binary files a/blight-assets/src/main/resources/animations/clips/idle.j3o and b/blight-assets/src/main/resources/animations/clips/idle.j3o differ diff --git a/blight-assets/src/main/resources/animations/clips/idle_jump.j3o b/blight-assets/src/main/resources/animations/clips/idle_jump.j3o index 7a83452..b9d85bc 100644 Binary files a/blight-assets/src/main/resources/animations/clips/idle_jump.j3o and b/blight-assets/src/main/resources/animations/clips/idle_jump.j3o differ diff --git a/blight-assets/src/main/resources/animations/clips/pickup.j3o b/blight-assets/src/main/resources/animations/clips/pickup.j3o index 5d3d03d..63da92b 100644 Binary files a/blight-assets/src/main/resources/animations/clips/pickup.j3o and b/blight-assets/src/main/resources/animations/clips/pickup.j3o differ diff --git a/blight-assets/src/main/resources/animations/clips/running.j3o b/blight-assets/src/main/resources/animations/clips/running.j3o index fd4e64b..ffcb192 100644 Binary files a/blight-assets/src/main/resources/animations/clips/running.j3o and b/blight-assets/src/main/resources/animations/clips/running.j3o differ diff --git a/blight-assets/src/main/resources/animations/clips/running_jump.j3o b/blight-assets/src/main/resources/animations/clips/running_jump.j3o index 0c73e01..29ffd26 100644 Binary files a/blight-assets/src/main/resources/animations/clips/running_jump.j3o and b/blight-assets/src/main/resources/animations/clips/running_jump.j3o differ diff --git a/blight-assets/src/main/resources/animations/clips/sit_down.j3o b/blight-assets/src/main/resources/animations/clips/sit_down.j3o index ed565f9..b2e29e5 100644 Binary files a/blight-assets/src/main/resources/animations/clips/sit_down.j3o and b/blight-assets/src/main/resources/animations/clips/sit_down.j3o differ diff --git a/blight-assets/src/main/resources/animations/clips/sit_down_bench.j3o b/blight-assets/src/main/resources/animations/clips/sit_down_bench.j3o new file mode 100644 index 0000000..7bacac2 Binary files /dev/null and b/blight-assets/src/main/resources/animations/clips/sit_down_bench.j3o differ diff --git a/blight-assets/src/main/resources/animations/clips/sitting.j3o b/blight-assets/src/main/resources/animations/clips/sitting.j3o index 470b091..b99c62c 100644 Binary files a/blight-assets/src/main/resources/animations/clips/sitting.j3o and b/blight-assets/src/main/resources/animations/clips/sitting.j3o differ diff --git a/blight-assets/src/main/resources/animations/clips/sitting_floor.j3o b/blight-assets/src/main/resources/animations/clips/sitting_floor.j3o index 47bf788..bbabcfd 100644 Binary files a/blight-assets/src/main/resources/animations/clips/sitting_floor.j3o and b/blight-assets/src/main/resources/animations/clips/sitting_floor.j3o differ diff --git a/blight-assets/src/main/resources/animations/clips/sprinting.j3o b/blight-assets/src/main/resources/animations/clips/sprinting.j3o index a7204e4..faf84ac 100644 Binary files a/blight-assets/src/main/resources/animations/clips/sprinting.j3o and b/blight-assets/src/main/resources/animations/clips/sprinting.j3o differ diff --git a/blight-assets/src/main/resources/animations/clips/stand_up.j3o b/blight-assets/src/main/resources/animations/clips/stand_up.j3o index 12e168a..880f7b6 100644 Binary files a/blight-assets/src/main/resources/animations/clips/stand_up.j3o and b/blight-assets/src/main/resources/animations/clips/stand_up.j3o differ diff --git a/blight-assets/src/main/resources/animations/clips/standup.j3o b/blight-assets/src/main/resources/animations/clips/standup.j3o index 46bd9f6..88360ec 100644 Binary files a/blight-assets/src/main/resources/animations/clips/standup.j3o and b/blight-assets/src/main/resources/animations/clips/standup.j3o differ diff --git a/blight-assets/src/main/resources/animations/clips/tpose.j3o b/blight-assets/src/main/resources/animations/clips/tpose.j3o index 05d5a81..9720d41 100644 Binary files a/blight-assets/src/main/resources/animations/clips/tpose.j3o and b/blight-assets/src/main/resources/animations/clips/tpose.j3o differ diff --git a/blight-assets/src/main/resources/animations/clips/walking.j3o b/blight-assets/src/main/resources/animations/clips/walking.j3o index dbae7d0..4ce60b4 100644 Binary files a/blight-assets/src/main/resources/animations/clips/walking.j3o and b/blight-assets/src/main/resources/animations/clips/walking.j3o differ diff --git a/blight-assets/src/main/resources/character/hero.character b/blight-assets/src/main/resources/character/hero.character index f6a632a..c4600d0 100644 --- a/blight-assets/src/main/resources/character/hero.character +++ b/blight-assets/src/main/resources/character/hero.character @@ -3,11 +3,28 @@ "level": 0, "xp": 0, "currentHp": 0, - "maxHp": 0, "currentStamina": 0, - "maxStamina": 0, "currentMana": 0, - "myMana": 0, + "maxHp": 0, + "maxStamina": 0, + "maxMana": 0, + "openHpRegeneration": 0, + "openManaRegeneration": 0, + "openStaminaRegeneration": 0, + "restorationValue": 10, + "abilities": { + "lvlMagic": 1, + "lvlStaffCombat": 1, + "lvlSwordsmanship": 1, + "lvlArchery": 1, + "lvlHeavyWeapons": 1, + "lvlCrossbow": 1, + "lvlThievery": 0, + "lvlAlchemy": 0, + "lvlEngineering": 0, + "lvlSmithery": 0, + "lvlEnchanting": 0 + }, "listeners": [], "characterId": "hero", "name": { 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 6f09330..d45ebeb 100644 --- a/blight-editor/src/main/java/de/blight/editor/EditorApp.java +++ b/blight-editor/src/main/java/de/blight/editor/EditorApp.java @@ -498,6 +498,12 @@ public class EditorApp extends Application { if (charEditorStatusLabel != null) charEditorStatusLabel.setText(embedStatus); } + String stripStatus = input.animStripStatus; + if (stripStatus != null) { + input.animStripStatus = null; + if (charEditorStatusLabel != null) charEditorStatusLabel.setText(stripStatus); + } + String rts = input.randomTreeStatus; if (randomTreeStatusLabel != null && rts != null) { randomTreeStatusLabel.setText(rts); @@ -9452,6 +9458,19 @@ public class EditorApp extends Application { input.animEmbedRequest.set(new SharedInput.AnimEmbedRequest(modelPath, setName)); }); + Button stripClipsBtn = new Button("Eingebettete Clips löschen"); + stripClipsBtn.setMaxWidth(Double.MAX_VALUE); + stripClipsBtn.setDisable(true); + charModelCombo.valueProperty().addListener((obs, ov, nv) -> + stripClipsBtn.setDisable(nv == null || nv.isBlank())); + stripClipsBtn.setOnAction(e -> { + String modelPath = charModelCombo.getValue(); + if (modelPath == null || modelPath.isBlank()) return; + if (charEditorStatusLabel != null) + charEditorStatusLabel.setText("Entferne eingebettete Clips…"); + input.animStripClipsRequest.set(modelPath); + }); + charEditContainer.getChildren().addAll( new Label("ID:"), charIdField, new Label("Name:"), charNameField, @@ -9562,7 +9581,8 @@ public class EditorApp extends Application { charEditContainer.getChildren().addAll( new Label("Modell:"), charModelCombo, new Label("Anim-Set:"), charAnimSetCombo, - embedAnimBtn + embedAnimBtn, + stripClipsBtn ); // ── Aktions-Zuweisung ────────────────────────────────────────────────── diff --git a/blight-editor/src/main/java/de/blight/editor/SharedInput.java b/blight-editor/src/main/java/de/blight/editor/SharedInput.java index 5cf7587..068c769 100644 --- a/blight-editor/src/main/java/de/blight/editor/SharedInput.java +++ b/blight-editor/src/main/java/de/blight/editor/SharedInput.java @@ -594,10 +594,16 @@ public class SharedInput { public final java.util.concurrent.atomic.AtomicReference animEmbedRequest = new java.util.concurrent.atomic.AtomicReference<>(); + /** JavaFX → JME3: Modell-Pfad, aus dem alle eingebetteten AnimClips entfernt werden sollen. */ + public final java.util.concurrent.atomic.AtomicReference + animStripClipsRequest = new java.util.concurrent.atomic.AtomicReference<>(); + /** JME3 → JavaFX: Status-Meldung für Clip- und Set-Operationen. */ - public volatile String animOpStatus = null; + public volatile String animOpStatus = null; /** JME3 → JavaFX: Status-Meldung für Einbett-Operationen (Character Editor). */ - public volatile String animEmbedStatus = null; + public volatile String animEmbedStatus = null; + /** JME3 → JavaFX: Status-Meldung für Strip-Operationen (Clips aus Modell entfernen). */ + public volatile String animStripStatus = null; // ── Modell-Konvertierung ────────────────────────────────────────────────── /** diff --git a/blight-editor/src/main/java/de/blight/editor/state/AnimPreviewState.java b/blight-editor/src/main/java/de/blight/editor/state/AnimPreviewState.java index 8ce4637..e71bdd3 100644 --- a/blight-editor/src/main/java/de/blight/editor/state/AnimPreviewState.java +++ b/blight-editor/src/main/java/de/blight/editor/state/AnimPreviewState.java @@ -178,6 +178,9 @@ public class AnimPreviewState extends BaseAppState { SharedInput.AnimEmbedRequest embedReq = input.animEmbedRequest.getAndSet(null); if (embedReq != null) executeAnimEmbed(embedReq); + String stripPath = input.animStripClipsRequest.getAndSet(null); + if (stripPath != null) executeStripClips(stripPath); + // Geschwindigkeit live anpassen if (currentAction != null) { try { currentAction.setSpeed(input.animPreviewSpeed); } catch (Exception ignored) {} @@ -258,6 +261,19 @@ public class AnimPreviewState extends BaseAppState { currentModelPath = assetPath; previewHolder.attachChild(model); + // Alle Clips in-place snappen (verhindert Drift im Preview) + AnimComposer previewAC = findControl(model, AnimComposer.class); + SkinningControl previewSC = findControl(model, SkinningControl.class); + if (previewAC != null && previewSC != null) { + for (AnimClip c : new java.util.ArrayList<>(previewAC.getAnimClips())) { + AnimClip snapped = de.blight.game.animation.AnimationLibrary.snapRootBoneXZ(c, previewSC.getArmature()); + if (snapped != c) { + previewAC.removeAnimClip(c); + previewAC.addAnimClip(snapped); + } + } + } + // Kamera auf Bounding Box ausrichten model.updateGeometricState(); if (model.getWorldBound() instanceof BoundingBox bb) { @@ -498,9 +514,12 @@ public class AnimPreviewState extends BaseAppState { LOG.info("[AnimPreview] Clip '{}' als '{}' gespeichert (Dateiname-Alias)", name, saveName); } + // XZ-Drift einfrieren bevor gespeichert wird – Clip-Dateien bleiben immer sauber + com.jme3.anim.Armature snapArm = dstArm != null ? dstArm : srcArm; + toSave = de.blight.game.animation.AnimationLibrary.snapRootBoneXZ(toSave, snapArm); + // Direkt in die Clip-Bibliothek speichern – das Modell wird nicht modifiziert - saveClipToFile(toSave, dstArm != null ? dstArm : srcArm, - clipsDir.resolve(saveName + ".j3o")); + saveClipToFile(toSave, snapArm, clipsDir.resolve(saveName + ".j3o")); // Für den aktuellen Preview-Session auch auf das Modell anwenden (wenn geladen) if (targetAC != null) targetAC.addAnimClip(toSave); saved++; @@ -925,6 +944,29 @@ public class AnimPreviewState extends BaseAppState { } } + private void executeStripClips(String modelPath) { + try { + Spatial model = loadFresh(modelPath); + AnimComposer ac = findControl(model, AnimComposer.class); + if (ac == null) { + input.animStripStatus = "Fehler: kein AnimComposer in " + modelPath; + return; + } + int count = ac.getAnimClips().size(); + for (AnimClip c : new java.util.ArrayList<>(ac.getAnimClips())) { + ac.removeAnimClip(c); + } + java.nio.file.Path file = ASSET_ROOT.resolve(modelPath.replace('/', java.io.File.separatorChar)); + BinaryExporter.getInstance().save(model, file.toFile()); + assets.deleteFromCache(new com.jme3.asset.ModelKey(modelPath)); + input.animStripStatus = count + " eingebettete Clip(s) aus '" + modelPath + "' entfernt"; + LOG.info("[AnimStrip] {} Clips aus '{}' entfernt und gespeichert", count, modelPath); + } catch (Exception e) { + input.animStripStatus = "Strip-Fehler: " + e.getMessage(); + LOG.error("[AnimStrip] Fehler beim Strip von {}", modelPath, e); + } + } + private void saveClipToFile(AnimClip clip, com.jme3.anim.Armature armature, java.nio.file.Path outFile) throws Exception { Node holder = new Node("clip_" + clip.getName()); diff --git a/blight-game/src/main/java/de/blight/game/animation/AnimationAction.java b/blight-game/src/main/java/de/blight/game/animation/AnimationAction.java index c15d515..5bab08d 100644 --- a/blight-game/src/main/java/de/blight/game/animation/AnimationAction.java +++ b/blight-game/src/main/java/de/blight/game/animation/AnimationAction.java @@ -24,7 +24,8 @@ public enum AnimationAction { SITTING, SIT_DOWN_FLOOR, SITTING_FLOOR, - GET_UP_FLOOR; + GET_UP_FLOOR, + REVIVE; /** Lesbare Bezeichnung für UI-Anzeige, via TextRegistry aufgelöst. */ public String displayName() { @@ -48,6 +49,7 @@ public enum AnimationAction { case SIT_DOWN_FLOOR -> TextRegistry.resolve(null, key, "Hinsetzen (Boden)"); case SITTING_FLOOR -> TextRegistry.resolve(null, key, "Sitzen (Boden)"); case GET_UP_FLOOR -> TextRegistry.resolve(null, key, "Aufstehen (Boden)"); + case REVIVE -> TextRegistry.resolve(null, key, "Wiederbeleben"); }; } } diff --git a/blight-game/src/main/java/de/blight/game/animation/AnimationLibrary.java b/blight-game/src/main/java/de/blight/game/animation/AnimationLibrary.java index 0155f1a..f77fddf 100644 --- a/blight-game/src/main/java/de/blight/game/animation/AnimationLibrary.java +++ b/blight-game/src/main/java/de/blight/game/animation/AnimationLibrary.java @@ -270,7 +270,7 @@ public class AnimationLibrary extends BaseAppState { * wird Hips gesnappt. So passt der Snap zu beiden Rig-Strukturen. * Erstellt einen neuen in-memory-Clip; J3O-Dateien bleiben unverändert. */ - private static AnimClip snapRootBoneXZ(AnimClip clip, Armature armature) { + public static AnimClip snapRootBoneXZ(AnimClip clip, Armature armature) { if (clip == null || armature == null) return clip; // Tiefe des flachsten Joints mit Translation-Track bestimmen