Operator-Nachbesserung nach dem Eigenstaendigkeits-Beweis (exportierte App, kein Client/Godot im Dateisystem): - SRC_TEX wird GESUCHT statt fest verdrahtet: SCOPEDVR_TEX_DIR -> assets/textures/military_desert -> assets/textures -> Ordner der Demonstration_Textures*.png unter assets/. Findet er nichts, gibt es einen HINWEIS samt Loesung (SCOPEDVR_TEX_DIR=/pfad). - Texturen werden FLACH nach models/textures/<name>.png gespiegelt — die App sucht sie dort; im Client liegen sie verschachtelt. - Modell-Spiegel schliesst den Unterordner textures/ aus (skip_top): vorher galt er als 'ueberfluessig' und wurde bei JEDEM Lauf geloescht, der Textur-Spiegel legte ihn neu an -> Endlosschleife, --check nie sauber. Belegt: 2. Lauf 0 Aenderungen, --check Exit 0; exportierte App findet baum_kiefer_1/stein_mittel_1 aus models/, fehlende_glbs=0, ERGEBNIS: OK.
222 lines
8.9 KiB
Bash
Executable file
222 lines
8.9 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
# Modelle-Sync für den eigenständigen Map Builder (Karte t_12cf94fe).
|
|
#
|
|
# Was das Script macht:
|
|
# Füllt den Ordner models/ DIREKT NEBEN der App (im Editor-Repo = Projekt-
|
|
# ordner, in der exportierten App = neben der EXE) mit den echten 3D-Modellen
|
|
# (.glb) und den Pack-Texturen — kopiert aus einem Client-Klon. Danach läuft
|
|
# der Map Builder auf jedem beliebigen PC OHNE Client/Godot-Installation.
|
|
#
|
|
# Spiegelstruktur (wichtig: die App erwartet die GLBs DIREKT im models-Ordner):
|
|
# models/<oid>.glb (flache GLBs)
|
|
# models/military_desert/<kategorie>/<oid>.glb (verschachtelte GLBs)
|
|
# models/textures/*.png (Pack-Palette)
|
|
#
|
|
# Aufruf (aus dem Map-Editor-Repo oder aus der exportierten App):
|
|
# tools/sync_models.sh # models/ füllen (idempotent — gefahrlos wiederholbar)
|
|
# tools/sync_models.sh --check # nur prüfen: Exit 0 = models/ aktuell,
|
|
# # Exit 1 = es fehlt/wich ab (ohne Änderung)
|
|
#
|
|
# Client-Klon finden: Umgebungsvariable SCOPEDVR_CLIENT_DIR, sonst die üblichen
|
|
# Nachbar-Ordner ../scopedvr-client und ../../scopedvr-client.
|
|
#
|
|
# Abhängigkeiten: python3 (Standard auf Linux/Mac; auf Windows python.org oder
|
|
# Git-Bash). KEINE rsync-Abhängigkeit — das Spiegeln (Kopieren + Überflüssiges
|
|
# löschen) macht ein eingebautes Python-Script, damit es auf jedem PC ohne
|
|
# Zusatzinstallation läuft (Slys Wunsch: keinerlei Abhängigkeiten).
|
|
#
|
|
# Lizenz (WICHTIG, siehe README_INSTALL.md): die Modelle/Texturen stammen aus
|
|
# dem ITHappy-Pack und dürfen NICHT weitergegeben werden — der models/-Ordner
|
|
# bleibt auf Slys eigenen Rechnern. Deshalb steht models/ auch in .gitignore.
|
|
#
|
|
set -u
|
|
MODE="sync"
|
|
if [ "${1:-}" = "--check" ]; then
|
|
MODE="check"
|
|
fi
|
|
if [ "${1:-}" != "" ] && [ "${1:-}" != "--check" ]; then
|
|
echo "Unbekannter Parameter: $1 (erlaubt: --check oder nichts)"
|
|
exit 2
|
|
fi
|
|
|
|
DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
TARGET="$DIR/models"
|
|
CLIENT="${SCOPEDVR_CLIENT_DIR:-}"
|
|
|
|
# --- Client-Klon finden (wie tools/sync_objects.sh) -------------------------
|
|
if [ -z "$CLIENT" ]; then
|
|
for k in "$DIR/../scopedvr-client" "$DIR/../../scopedvr-client"; do
|
|
[ -d "$k/assets/objekte" ] && CLIENT="$(cd "$k" && pwd)" && break
|
|
done
|
|
fi
|
|
if [ -z "$CLIENT" ] || [ ! -d "$CLIENT/assets/objekte" ]; then
|
|
echo "FEHLER: Client-Klon mit assets/objekte nicht gefunden."
|
|
echo " Ordner ../scopedvr-client neben den Map-Editor legen oder"
|
|
echo " SCOPEDVR_CLIENT_DIR=/pfad/zum/client setzen."
|
|
exit 1
|
|
fi
|
|
echo "Client: $CLIENT"
|
|
echo "models/: $TARGET"
|
|
echo "Modus: $MODE"
|
|
|
|
if ! command -v python3 >/dev/null 2>&1; then
|
|
echo "FEHLER: python3 fehlt (Standard auf Linux/Mac; auf Windows python.org installieren)."
|
|
exit 1
|
|
fi
|
|
|
|
# --- .gdignore: Godot soll models/ NICHT importieren/packen ------------------
|
|
# (FileAccess mit absoluten Pfaden funktioniert trotzdem — genau dafür
|
|
# ist der Ordner da. Fehlt die Datei, ist das eine Abweichung.)
|
|
GDIGNORE="$TARGET/.gdignore"
|
|
mkdir -p "$TARGET"
|
|
GDIGNORE_MISSING=0
|
|
if [ ! -f "$GDIGNORE" ]; then
|
|
GDIGNORE_MISSING=1
|
|
if [ "$MODE" = "check" ]; then
|
|
echo "ABWEICHUNG: $GDIGNORE fehlt (Godot würde den Ordner sonst importieren)."
|
|
else
|
|
touch "$GDIGNORE"
|
|
echo "angelegt: $GDIGNORE"
|
|
fi
|
|
fi
|
|
|
|
# --- Spiegeln: Objekte (GLBs) + Pack-Texturen, ohne .import-Leichen ---------
|
|
# WICHTIG (Karte t_12cf94fe): die App erwartet die GLBs DIREKT im models-Ordner
|
|
# (models/<oid>.glb) — NICHT verschachtelt in models/assets/objekte.
|
|
# Deshalb wird $CLIENT/assets/objekte nach $TARGET (models/) gespiegelt.
|
|
SRC_OBJEKTE="$CLIENT/assets/objekte"
|
|
DST_OBJEKTE="$TARGET"
|
|
DST_TEX="$TARGET/textures"
|
|
|
|
# Pack-Texturen FINDEN statt fest verdrahten (Operator-Nachbesserung 20.10.):
|
|
# Die Palette (Demonstration_Textures*.png) liegt je Client-Klon in einem anderen
|
|
# Unterordner und fehlt im Server-Container ganz. Reihenfolge: SCOPEDVR_TEX_DIR →
|
|
# assets/textures/military_desert → assets/textures → der Ordner, in dem die
|
|
# Palette irgendwo unter assets/ liegt. Erster Treffer gewinnt.
|
|
SRC_TEX="${SCOPEDVR_TEX_DIR:-}"
|
|
if [ -z "$SRC_TEX" ] || [ ! -d "$SRC_TEX" ]; then
|
|
for cand in "$CLIENT/assets/textures/military_desert" "$CLIENT/assets/textures"; do
|
|
if [ -d "$cand" ]; then SRC_TEX="$cand"; break; fi
|
|
done
|
|
fi
|
|
if [ -z "$SRC_TEX" ] || [ ! -d "$SRC_TEX" ]; then
|
|
PAL="$(find "$CLIENT/assets" -name 'Demonstration_Textures*.png' 2>/dev/null | head -1)"
|
|
if [ -n "$PAL" ]; then SRC_TEX="$(dirname "$PAL")"; fi
|
|
fi
|
|
if [ -z "$SRC_TEX" ] || [ ! -d "$SRC_TEX" ]; then
|
|
echo "HINWEIS: Pack-Texturen nicht gefunden — gesucht in SCOPEDVR_TEX_DIR,"
|
|
echo " assets/textures/military_desert, assets/textures und nach"
|
|
echo " Demonstration_Textures*.png unter assets/."
|
|
echo " Die Modelle werden trotzdem gespiegelt; die Optik nutzt dann"
|
|
echo " die Standardfarben. Nachreichen: SCOPEDVR_TEX_DIR=/pfad"
|
|
SRC_TEX="$CLIENT/assets/textures" # absichtlich nicht vorhanden -> HINWEIS statt stiller Leerlauf
|
|
fi
|
|
echo "Objekte: $SRC_OBJEKTE"
|
|
echo "Texturen: $SRC_TEX"
|
|
|
|
# Python macht das Spiegeln (copy2 + überflüssige Dateien löschen).
|
|
# --check (Dry-Run) zeigt Abweichungen OHNE etwas zu verändern.
|
|
python3 - "$SRC_OBJEKTE" "$DST_OBJEKTE" "$SRC_TEX" "$DST_TEX" "$MODE" <<'PY'
|
|
import os, sys, shutil, filecmp
|
|
|
|
pairs = [
|
|
("Objekte", sys.argv[1], sys.argv[2]),
|
|
("Texturen", sys.argv[3], sys.argv[4]),
|
|
]
|
|
mode = sys.argv[5]
|
|
|
|
|
|
def scan(root: str, skip_top: set = frozenset()) -> dict:
|
|
out = {}
|
|
if not os.path.isdir(root):
|
|
return out
|
|
for r, dirs, files in os.walk(root):
|
|
dirs[:] = [d for d in dirs if d != ".godot" and d not in skip_top]
|
|
for f in files:
|
|
if f.endswith(".import") or f == ".gdignore":
|
|
continue
|
|
full = os.path.join(r, f)
|
|
out[os.path.relpath(full, root)] = full
|
|
return out
|
|
|
|
|
|
def run(label: str, src: str, dst: str, flat: bool = False,
|
|
skip_top: set = frozenset()) -> int:
|
|
if not os.path.isdir(src):
|
|
print("ABWEICHUNG: Quelle fehlt: %s" % src)
|
|
return 1
|
|
s_map = scan(src, skip_top)
|
|
d_map = scan(dst, skip_top)
|
|
# flat=True (Pack-Texturen, Operator-Nachbesserung 20.10.): Die App sucht die
|
|
# Palette FLACH unter models/textures/<name>.png — im Client liegen die PNGs
|
|
# aber verschachtelt (assets/textures/<unterordner>/…). Deshalb ohne
|
|
# Unterordner spiegeln. Alte verschachtelte Reste erscheinen dadurch als
|
|
# "überflüssig" und werden automatisch entfernt (selbstheilend).
|
|
if flat:
|
|
s_map = {os.path.basename(p): p for p in s_map.values()}
|
|
changes = []
|
|
for rel, sp in s_map.items():
|
|
dp = os.path.join(dst, rel)
|
|
if not os.path.exists(dp):
|
|
changes.append(("neu", rel))
|
|
else:
|
|
try:
|
|
if not filecmp.cmp(sp, dp, shallow=False):
|
|
changes.append(("geändert", rel))
|
|
except OSError:
|
|
changes.append(("geändert", rel))
|
|
for rel in d_map:
|
|
if rel not in s_map:
|
|
changes.append(("überflüssig", rel))
|
|
if not changes:
|
|
return 0
|
|
if mode == "check":
|
|
for action, rel in changes[:20]:
|
|
print("ABWEICHUNG (%s): %s: %s" % (label, action, rel))
|
|
if len(changes) > 20:
|
|
print("ABWEICHUNG (%s): … und %d weitere" % (label, len(changes) - 20))
|
|
return 1
|
|
for action, rel in changes:
|
|
dp = os.path.join(dst, rel)
|
|
if action == "überflüssig":
|
|
if os.path.exists(dp):
|
|
os.remove(dp)
|
|
else:
|
|
os.makedirs(os.path.dirname(dp), exist_ok=True)
|
|
shutil.copy2(s_map[rel], dp)
|
|
print("%s: %d Änderungen übernommen." % (label, len(changes)))
|
|
return 0
|
|
|
|
|
|
dev = 0
|
|
# skip_top: der Modell-Spiegel darf den Textur-Unterordner NICHT als
|
|
# "überflüssig" löschen (Operator-Nachbesserung 20.10. — sonst löscht jeder
|
|
# Lauf models/textures/, der Textur-Spiegel legt ihn neu an: Endlosschleife,
|
|
# --check nie sauber).
|
|
dev |= run("Objekte", pairs[0][1], pairs[0][2], skip_top={"textures"})
|
|
dev |= run("Texturen", pairs[1][1], pairs[1][2], flat=True)
|
|
sys.exit(dev)
|
|
PY
|
|
DEVIATION=$?
|
|
|
|
# --- Größe + Zahl am Ende ----------------------------------------------------
|
|
GLB_COUNT="$(find "$DST_OBJEKTE" -name '*.glb' 2>/dev/null | wc -l)"
|
|
TEX_COUNT="$(find "$DST_TEX" -name '*.png' 2>/dev/null | wc -l)"
|
|
SIZE="$(du -sh "$TARGET" 2>/dev/null | cut -f1)"
|
|
echo "---"
|
|
echo "models/: $GLB_COUNT GLBs, $TEX_COUNT Pack-Texturen, Gesamtgröße: $SIZE"
|
|
|
|
if [ "$MODE" = "check" ]; then
|
|
if [ "$DEVIATION" -ne 0 ] || [ "$GDIGNORE_MISSING" -ne 0 ]; then
|
|
echo "--check: models/ weicht vom Client-Klon ab (Exit 1)."
|
|
exit 1
|
|
fi
|
|
echo "--check: models/ ist aktuell (Exit 0)."
|
|
exit 0
|
|
fi
|
|
|
|
if [ "$DEVIATION" -ne 0 ]; then
|
|
echo "Sync mit Fehlern (siehe oben)."
|
|
exit 1
|
|
fi
|
|
echo "Sync fertig: models/ ist auf dem Stand des Client-Klons."
|