Weiter am Kampfsystem gearbeitet, hier Schwertkampf und die animationen

This commit is contained in:
2026-09-20 17:16:43 +02:00
parent bdaeed056c
commit 836b5d3d99
23 changed files with 376 additions and 136 deletions

View File

@@ -1562,17 +1562,22 @@ public class ModelEditorState extends BaseAppState {
headRot.fromAngleAxis(FastMath.HALF_PI, Vector3f.UNIT_X);
head.setLocalRotation(headRot);
// Klingenflosse: dünnes flaches Rechteck senkrecht zum Schaft entlang +Y,
// damit Rotation um Z (Roll) sichtbar ist. Breite 6cm, Dicke 2mm, entlang Schaft.
// Griffachsen-Zylinder: runder Zylinder senkrecht zum Schaft (+Y),
// zeigt die Roll-Richtung (ersetzt die frühere flache Klingenflosse).
// JME3-Cylinder liegt standardmäßig auf +Z → -90° um X dreht ihn nach +Y.
Material matFin = new Material(app.getAssetManager(), "Common/MatDefs/Misc/Unshaded.j3md");
matFin.setColor("Color", new ColorRGBA(1f, 0.8f, 0.1f, 1f));
Geometry fin = new Geometry("gFin", new Box(0.001f, 0.03f, shaftLen * 0.5f));
fin.setMaterial(matFin);
fin.setLocalTranslation(0f, 0.03f, shaftLen * 0.5f);
float axisLen = 0.06f;
Geometry gripAxis = new Geometry("gGripAxis", new Cylinder(4, 8, 0.006f, axisLen, true));
gripAxis.setMaterial(matFin);
Quaternion axisRot = new Quaternion();
axisRot.fromAngleAxis(-FastMath.HALF_PI, Vector3f.UNIT_X);
gripAxis.setLocalRotation(axisRot);
gripAxis.setLocalTranslation(0f, axisLen * 0.5f, 0f);
group.attachChild(marker);
group.attachChild(shaft);
group.attachChild(fin);
group.attachChild(gripAxis);
group.attachChild(head);
gripGizmoNode.attachChild(group);
gripGizmoNode.setCullHint(Spatial.CullHint.Inherit);

View File

@@ -51,6 +51,7 @@ public class AnimSetController implements ToolController {
private ListView<String> animSetPartsListView;
private java.util.Map<String, de.blight.game.animation.AnimSet.SubClipDef>
editableSubClips = new java.util.LinkedHashMap<>();
private java.util.Set<String> editableSnapClips = new java.util.LinkedHashSet<>();
private ListView<String> animSetSequenceListView;
private java.util.Map<String, java.util.List<String>>
editableSequences = new java.util.LinkedHashMap<>();
@@ -76,6 +77,16 @@ public class AnimSetController implements ToolController {
animSetCurrentName = setName;
animSetCurrentDir = setDir;
currentAnimSet = animSet;
editableSnapClips = new java.util.LinkedHashSet<>(animSet.getSnapClips());
// Migration: wenn snapClips noch leer, Fallback-Clips (LOCOMOTION_ACTIONS) einmalig übernehmen
// damit der Checkbox-Zustand die tatsächliche Snap-Konfiguration widerspiegelt.
if (editableSnapClips.isEmpty()) {
java.util.Set<String> locoFallback = java.util.Set.of(
"WALK", "RUN", "SPRINT", "JUMP", "RUNNING_JUMP", "IDLE", "DEFAULT");
animSet.getActionMap().forEach((action, clip) -> {
if (locoFallback.contains(action)) editableSnapClips.add(clip);
});
}
}
@Override
@@ -337,17 +348,14 @@ public class AnimSetController implements ToolController {
animSetClipListView.setPrefHeight(180);
editableSubClips = new java.util.LinkedHashMap<>(animSet.getSubClips());
editableSequences = new java.util.LinkedHashMap<>(animSet.getSequences());
// editableSnapClips wird bereits in openWithSet gesetzt (inkl. Migration)
ctx.input().animPreviewClipOffsets.clear();
for (var en : animSet.getAnimOffsets().entrySet()) {
de.blight.game.animation.AnimOffset o = en.getValue();
ctx.input().animPreviewClipOffsets.put(en.getKey(), new float[]{o.tx, o.ty, o.tz});
}
java.util.Set<String> locomotionActions = java.util.Set.of(
"WALK", "RUN", "SPRINT", "JUMP", "RUNNING_JUMP", "IDLE", "DEFAULT");
ctx.input().animPreviewLocomotionClips.clear();
animSet.getActionMap().forEach((action, clip) -> {
if (locomotionActions.contains(action)) ctx.input().animPreviewLocomotionClips.add(clip);
});
ctx.input().animPreviewLocomotionClips.addAll(editableSnapClips);
Path animRootDir = ctx.assetRoot().resolve("Characters");
@@ -454,10 +462,41 @@ public class AnimSetController implements ToolController {
autoSaveAnimSet();
});
CheckBox snapCB = new CheckBox("Root-Motion entfernen (auf der Stelle)");
snapCB.setDisable(true);
snapCB.setTooltip(new Tooltip("Bewegt sich die Animation durch den Raum (Walk/Run)?\nMit dieser Option bleibt der Charakter an Ort und Stelle\nund das Spiel übernimmt die Fortbewegung."));
final boolean[] snapCbUpdating = {false};
animSetClipListView.getSelectionModel().selectedItemProperty()
.addListener((obs, ov, nv) -> {
snapCB.setDisable(nv == null);
if (nv != null) {
snapCbUpdating[0] = true;
snapCB.setSelected(editableSnapClips.contains(nv));
snapCbUpdating[0] = false;
}
});
snapCB.selectedProperty().addListener((obs, ov, nv) -> {
if (snapCbUpdating[0]) return;
String sel = animSetClipListView.getSelectionModel().getSelectedItem();
if (sel == null) return;
if (nv) {
editableSnapClips.add(sel);
} else {
editableSnapClips.remove(sel);
}
ctx.input().animPreviewLocomotionClips.clear();
ctx.input().animPreviewLocomotionClips.addAll(editableSnapClips);
// Clip neu laden damit Snap-Änderung sofort in der Vorschau sichtbar wird
ctx.input().animImportQueue.offer(findAnimClipPath(sel));
autoSaveAnimSet();
});
HBox clipBtns = new HBox(6, addClipBtn, removeClipBtn);
HBox.setHgrow(addClipBtn, Priority.ALWAYS);
HBox.setHgrow(removeClipBtn, Priority.ALWAYS);
inner.getChildren().addAll(animSetClipListView, clipBtns);
inner.getChildren().addAll(animSetClipListView, snapCB, clipBtns);
// ── Clip-Teile (Sub-Clips) ─────────────────────────────────────────────
inner.getChildren().addAll(new Separator(), sectionTitle("Clip-Teile"), new Separator());
@@ -1172,12 +1211,9 @@ public class AnimSetController implements ToolController {
de.blight.game.animation.AnimOffset o = en.getValue();
ctx.input().animPreviewClipOffsets.put(en.getKey(), new float[]{o.tx, o.ty, o.tz});
}
java.util.Set<String> locoActions = java.util.Set.of(
"WALK", "RUN", "SPRINT", "JUMP", "RUNNING_JUMP", "IDLE", "DEFAULT");
animSet.setSnapClips(new java.util.LinkedHashSet<>(editableSnapClips));
ctx.input().animPreviewLocomotionClips.clear();
animSet.getActionMap().forEach((action, clip) -> {
if (locoActions.contains(action)) ctx.input().animPreviewLocomotionClips.add(clip);
});
ctx.input().animPreviewLocomotionClips.addAll(editableSnapClips);
if (animSetModelCombo != null && animSetModelCombo.getValue() != null
&& !animSetModelCombo.getValue().isBlank()) {
animSet.setPreviewModelPath(animSetModelCombo.getValue());