diff --git a/blight-assets/src/main/resources/animations/clips/idle.j3o b/blight-assets/src/main/resources/animations/clips/idle.j3o index aac8cab..3339791 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/pickup.j3o b/blight-assets/src/main/resources/animations/clips/pickup.j3o index 394b217..d565c94 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 5a89ac2..4aff2bc 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 228a147..17a245f 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_bench.j3o b/blight-assets/src/main/resources/animations/clips/sit_down_bench.j3o index bc9a04f..5eccd21 100644 Binary files a/blight-assets/src/main/resources/animations/clips/sit_down_bench.j3o 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_floor.j3o b/blight-assets/src/main/resources/animations/clips/sitting_floor.j3o index d6d0833..9e91b05 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 d184823..a8d4f23 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 1812335..0103cae 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/walking.j3o b/blight-assets/src/main/resources/animations/clips/walking.j3o index 1bdf353..757854f 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-editor/src/main/java/de/blight/editor/state/AnimPreviewState.java b/blight-editor/src/main/java/de/blight/editor/state/AnimPreviewState.java index a502783..850bd44 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 @@ -249,9 +249,11 @@ public class AnimPreviewState extends BaseAppState { try { Spatial model = loadFresh(assetPath); - // SkinningControl nur aktiv lassen wenn eine Animation läuft, - // sonst kollabiert das Mesh durch uninitalisierte Skin-Matrizen. + // SkinningControl deaktiviert + Modell unsichtbar bis Animation läuft: + // das Armature-Node hat Rx(90°) aus dem GLB-Import → ohne Animation liegt + // das Mesh auf dem Boden (Bind-Pose × Rx90° = liegender Charakter). setSkinningEnabled(model, false); + model.setCullHint(com.jme3.scene.Spatial.CullHint.Always); // Im Animations-Editor soll der Charakter immer am Ursprung stehen. // Eventuelle Translation die beim GLB-Export eingebacken wurde entfernen. @@ -348,6 +350,8 @@ public class AnimPreviewState extends BaseAppState { // SkinningControls auf dem gesamten Modell aktivieren – AnimComposer und // SkinningControl sitzen oft auf verschiedenen Geschwisterknoten. setSkinningEnabled(currentModel, true); + // Modell erst nach Animation sichtbar machen (CullHint aus loadModel) + currentModel.setCullHint(com.jme3.scene.Spatial.CullHint.Inherit); playOnSpatial(currentModel, clipName); } @@ -380,6 +384,7 @@ public class AnimPreviewState extends BaseAppState { if (currentModel != null) { stopOnSpatial(currentModel); setSkinningEnabled(currentModel, false); + currentModel.setCullHint(com.jme3.scene.Spatial.CullHint.Always); } } diff --git a/blight-game/src/main/java/de/blight/game/control/PlayerInputControl.java b/blight-game/src/main/java/de/blight/game/control/PlayerInputControl.java index 7d39665..1b61bd2 100644 --- a/blight-game/src/main/java/de/blight/game/control/PlayerInputControl.java +++ b/blight-game/src/main/java/de/blight/game/control/PlayerInputControl.java @@ -579,16 +579,22 @@ public class PlayerInputControl { } private boolean tryPlay(String clip) { - if (animComposer == null || !animLib.ensureApplied(clip, visual)) { - log.info("[Anim] tryPlay('{}') → ensureApplied FAILED", clip); + if (animComposer == null || !animLib.applyTo(clip, visual)) { + log.info("[Anim] tryPlay('{}') → applyTo FAILED", clip); return false; } + // Erst Action setzen, DANN SkinningControl aktivieren – + // vermeidet 1 Frame in Bind-Pose × Armature-Rx90° = liegender Charakter. com.jme3.anim.tween.action.Action action = animComposer.setCurrentAction(clip); log.info("[Anim] setCurrentAction('{}') → {}", clip, action != null ? "OK" : "FAILED"); - if (action != null) { - runningClip = clip; - return true; + if (action == null) { + return false; } - return false; + if (skinningControl != null && !skinningControl.isEnabled()) { + skinningControl.setEnabled(true); + log.info("[Anim] SkinningControl aktiviert nach Action '{}'", clip); + } + runningClip = clip; + return true; } } diff --git a/blight-game/src/main/java/de/blight/game/scene/WorldScene.java b/blight-game/src/main/java/de/blight/game/scene/WorldScene.java index c9383f7..2885625 100644 --- a/blight-game/src/main/java/de/blight/game/scene/WorldScene.java +++ b/blight-game/src/main/java/de/blight/game/scene/WorldScene.java @@ -307,6 +307,10 @@ public class WorldScene extends BaseAppState { } } playerInput.setAnimationContext(animLib, setName, AnimationLibrary.findAssetRoot()); + // Charakter sichtbar machen: idle-Animation läuft jetzt + if (characterVisual != null) { + characterVisual.setCullHint(Spatial.CullHint.Inherit); + } } // CharacterControl setzt den Spatial auf den Kapsel-Mittelpunkt: radius=0.4, halfCyl=0.5 → 0.9m über dem Boden. @@ -343,6 +347,9 @@ public class WorldScene extends BaseAppState { Node rotNode = new Node("charRot"); loaded.setLocalTranslation(0, offsetY, 0); rotNode.attachChild(loaded); + // Charakter verstecken bis Animation läuft: das Armature-Node hat Rx(90°) aus dem + // GLB-Import → ohne laufende Animation liegt das Mesh auf dem Boden. + rotNode.setCullHint(Spatial.CullHint.Always); Node wrapper = new Node("character"); wrapper.attachChild(rotNode); @@ -359,30 +366,32 @@ public class WorldScene extends BaseAppState { return buildCharacter(); } - private static final String[] ASSET_SEARCH_ROOTS = { - "blight-assets/src/main/resources", - "blight-assets/build/resources/main", - "blight-assets/bin/main", - "assets", - }; private void stripEmbeddedClips(Spatial model, String modelPath) { com.jme3.anim.AnimComposer ac = de.blight.game.animation.RetargetingSystem.findAnimComposer(model); - if (ac == null || ac.getAnimClips().isEmpty()) return; + if (ac == null || ac.getAnimClips().isEmpty()) { + log.info("[WorldScene] Keine eingebetteten Clips in '{}' (AnimComposer={})", + modelPath, ac != null ? "leer" : "nicht gefunden"); + return; + } int count = ac.getAnimClips().size(); + log.info("[WorldScene] Entferne {} eingebettete Clips aus '{}'", count, modelPath); for (com.jme3.anim.AnimClip c : new java.util.ArrayList<>(ac.getAnimClips())) { ac.removeAnimClip(c); } - String rel = modelPath.replace('/', java.io.File.separatorChar); - for (String base : ASSET_SEARCH_ROOTS) { - java.nio.file.Path file = java.nio.file.Paths.get(base).resolve(rel); - if (!java.nio.file.Files.exists(file)) continue; - try { - com.jme3.export.binary.BinaryExporter.getInstance().save(model, file.toFile()); - log.info("[WorldScene] {} eingebettete Clips aus '{}' entfernt: {}", count, modelPath, file); - } catch (Exception e) { - log.warn("[WorldScene] Speichern fehlgeschlagen ({}): {}", file, e.getMessage()); - } + java.nio.file.Path assetRoot = AnimationLibrary.findAssetRoot(); + java.nio.file.Path file = assetRoot.resolve(modelPath.replace('/', java.io.File.separatorChar)); + if (!java.nio.file.Files.exists(file)) { + log.warn("[WorldScene] Modelldatei nicht gefunden zum Speichern: {} (assetRoot={})", + file.toAbsolutePath(), assetRoot.toAbsolutePath()); + assetManager.deleteFromCache(new com.jme3.asset.ModelKey(modelPath)); + return; + } + try { + com.jme3.export.binary.BinaryExporter.getInstance().save(model, file.toFile()); + log.info("[WorldScene] {} Clips entfernt, Datei gespeichert: {}", count, file.toAbsolutePath()); + } catch (Exception e) { + log.warn("[WorldScene] Speichern fehlgeschlagen ({}): {}", file, e.getMessage()); } assetManager.deleteFromCache(new com.jme3.asset.ModelKey(modelPath)); }