Stempel-Stil-Bulk-Apply + Manager-Tab in ProjectSettings
PHASE 1 — Bulk-Apply auf mehrere selektierte Raeume: - Backend _cmd_apply_raum_stil: leere ids im Patch → nimmt automatisch alle aktuell SELEKTIERTEN raum_outlines aus dem Doc (Bulk-Fallback) - Frontend sendet leere ids fuer die Default-Bulk-Variante. User selektiert N Raeume im Viewport → klickt Stil im Properties-Picker → Stil wird auf alle angewendet. Inkludiert immer den Properties-Raum. PHASE 2 — Stil-Manager als Settings-Tab: - Neuer Tab "Raumstile" in ProjectSettings-Dialog - Liste aller Stile mit Drag-Reorder (HTML5 native), Inline-Rename, Duplicate (content_copy-Icon), Delete (mit Confirm) - Mini-Preview: zeigt Layout-Struktur (z.B. "nummer·name / funktion / area") und der Name wird mit Font/Bold/Italic des Stils gerendert als Vorschau - Backend _cmd_reorder_raum_stile + _cmd_duplicate_raum_stil in elemente.py - ProjectSettings-Bridge dispatcht direkt zu elemente.load/save_raum_stempel_stile (kein Roundtrip via Elemente-Bridge noetig) - STILE_UPDATED-Message nach jeder Op pusht die neue Liste zum Dialog - params bei _open_project_settings enthalten jetzt raumStempelStile + fonts Bridge-Exports: reorderRaumStile / duplicateRaumStil in rhinoBridge.js
This commit is contained in:
+68
-4
@@ -6457,6 +6457,12 @@ class ElementeBridge(panel_base.BaseBridge):
|
||||
# Wendet einen gespeicherten Stil auf die im Patch genannten
|
||||
# raum_outline element_ids an. p = {stilId, ids=[…]}.
|
||||
self._cmd_apply_raum_stil(p)
|
||||
elif t == "REORDER_RAUM_STILE":
|
||||
# p = {ids: [stil_id, ...]} in neuer Reihenfolge
|
||||
self._cmd_reorder_raum_stile(p)
|
||||
elif t == "DUPLICATE_RAUM_STIL":
|
||||
# p = {id, newName?} → kopiert Stil mit neuer uuid + Name
|
||||
self._cmd_duplicate_raum_stil(p)
|
||||
elif t == "OPEN_ELEMENTE_UEBERSICHT":
|
||||
try:
|
||||
import elemente_uebersicht
|
||||
@@ -8601,16 +8607,74 @@ class ElementeBridge(panel_base.BaseBridge):
|
||||
print("[ELEMENTE] Stempel-Stil {} geloescht".format(sid))
|
||||
self._send_state()
|
||||
|
||||
def _cmd_reorder_raum_stile(self, p):
|
||||
"""Setzt die Reihenfolge der Stile auf die uebergebene id-Liste.
|
||||
Nicht-erwaehnte Stile bleiben am Ende erhalten."""
|
||||
doc = Rhino.RhinoDoc.ActiveDoc
|
||||
if doc is None: return
|
||||
new_order = p.get("ids") or []
|
||||
if not isinstance(new_order, list) or not new_order: return
|
||||
stile = load_raum_stempel_stile(doc)
|
||||
by_id = {s.get("id"): s for s in stile if s.get("id")}
|
||||
ordered = []
|
||||
seen = set()
|
||||
for sid in new_order:
|
||||
if sid in by_id and sid not in seen:
|
||||
ordered.append(by_id[sid]); seen.add(sid)
|
||||
# Reste anhaengen
|
||||
for s in stile:
|
||||
sid = s.get("id")
|
||||
if sid and sid not in seen:
|
||||
ordered.append(s); seen.add(sid)
|
||||
save_raum_stempel_stile(doc, ordered)
|
||||
self._send_state()
|
||||
|
||||
def _cmd_duplicate_raum_stil(self, p):
|
||||
"""Kopiert einen Stil mit neuer uuid. Payload: {id, newName?}."""
|
||||
doc = Rhino.RhinoDoc.ActiveDoc
|
||||
if doc is None: return
|
||||
sid = (p.get("id") or "").strip()
|
||||
if not sid: return
|
||||
stile = load_raum_stempel_stile(doc)
|
||||
src = next((s for s in stile if s.get("id") == sid), None)
|
||||
if src is None: return
|
||||
new_name = (p.get("newName") or "").strip() or (
|
||||
"{} (Kopie)".format(src.get("name", "Stil")))
|
||||
new_stil = dict(src)
|
||||
new_stil["id"] = "stil_" + uuid.uuid4().hex[:8]
|
||||
new_stil["name"] = new_name
|
||||
# Einfuegen direkt nach Original
|
||||
try:
|
||||
i = next(j for j, s in enumerate(stile) if s.get("id") == sid)
|
||||
stile.insert(i + 1, new_stil)
|
||||
except StopIteration:
|
||||
stile.append(new_stil)
|
||||
save_raum_stempel_stile(doc, stile)
|
||||
print("[ELEMENTE] Stempel-Stil '{}' dupliziert -> '{}'".format(
|
||||
src.get("name"), new_name))
|
||||
self._send_state()
|
||||
|
||||
def _cmd_apply_raum_stil(self, p):
|
||||
"""Wendet einen Stil auf eine Liste von raum_outline-Element-IDs
|
||||
an. Payload: {stilId, ids: [element_id, ...]}. Schreibt die Stil-
|
||||
Felder auf die Source-Outlines + triggert Regen pro Raum.
|
||||
"""Wendet einen Stil auf raum_outline-Element-IDs an. Payload:
|
||||
{stilId, ids: [element_id, ...]}. Wenn ids leer/missing → nimmt
|
||||
alle aktuell SELEKTIERTEN raum_outline-Objekte (Bulk-Apply).
|
||||
Schreibt Stil-Felder auf die Source-Outlines + triggert Regen.
|
||||
"""
|
||||
doc = Rhino.RhinoDoc.ActiveDoc
|
||||
if doc is None: return
|
||||
sid = (p.get("stilId") or "").strip()
|
||||
ids = p.get("ids") or []
|
||||
if not sid or not ids: return
|
||||
if not sid: return
|
||||
# Bulk-Fallback: keine ids im Patch → alle selektierten Raeume
|
||||
if not ids:
|
||||
for obj in doc.Objects:
|
||||
try:
|
||||
if obj.IsSelected(False) <= 0: continue
|
||||
m = _read_meta(obj)
|
||||
if m and m.get("type") == "raum_outline":
|
||||
ids.append(m["id"])
|
||||
except Exception: pass
|
||||
if not ids: return
|
||||
stile = load_raum_stempel_stile(doc)
|
||||
stil = next((s for s in stile if s.get("id") == sid), None)
|
||||
if stil is None:
|
||||
|
||||
@@ -961,6 +961,14 @@ class EbenenBridge(panel_base.BaseBridge):
|
||||
lib_root = library.library_root()
|
||||
except Exception:
|
||||
lib_items = []; lib_root = ""
|
||||
# Raumstempel-Stile + Fonts aus elemente fuer den "Raumstile"-Tab
|
||||
try:
|
||||
import elemente as _el
|
||||
raum_stile = _el.load_raum_stempel_stile(doc)
|
||||
fonts_list = _el._list_system_fonts()
|
||||
except Exception:
|
||||
raum_stile = []
|
||||
fonts_list = []
|
||||
params = {
|
||||
"defaults": current.get("defaults", {}),
|
||||
"project": current.get("project", {}),
|
||||
@@ -971,6 +979,8 @@ class EbenenBridge(panel_base.BaseBridge):
|
||||
"linetypes": _list_linetypes_full(doc),
|
||||
"libraryItems": lib_items,
|
||||
"libraryRoot": lib_root,
|
||||
"raumStempelStile": raum_stile,
|
||||
"fonts": fonts_list,
|
||||
}
|
||||
def on_save(updated):
|
||||
doc2 = Rhino.RhinoDoc.ActiveDoc
|
||||
@@ -1078,6 +1088,108 @@ class EbenenBridge(panel_base.BaseBridge):
|
||||
self._delete_library_item(p)
|
||||
elif t == "SAVE_SELECTION_AS_LIBRARY":
|
||||
self._save_selection_as_library(p)
|
||||
elif t == "SAVE_RAUM_STIL":
|
||||
self._raum_stil_save(p)
|
||||
elif t == "DELETE_RAUM_STIL":
|
||||
self._raum_stil_delete(p)
|
||||
elif t == "DUPLICATE_RAUM_STIL":
|
||||
self._raum_stil_duplicate(p)
|
||||
elif t == "REORDER_RAUM_STILE":
|
||||
self._raum_stil_reorder(p)
|
||||
|
||||
# ---- Raumstempel-Stile (Settings-Tab "Raumstile") ----
|
||||
# Dispatcht direkt zu elemente.py — kein Roundtrip via Elemente-
|
||||
# Bridge noetig. Nach jeder Op wird die neue Liste an's Frontend
|
||||
# gepushed via STILE_UPDATED.
|
||||
def _raum_stil_send_updated(self):
|
||||
try:
|
||||
import elemente as _el
|
||||
d = Rhino.RhinoDoc.ActiveDoc
|
||||
self.send("STILE_UPDATED",
|
||||
{"raumStempelStile": _el.load_raum_stempel_stile(d)})
|
||||
except Exception as ex:
|
||||
print("[PROJECT-SETTINGS] STILE_UPDATED:", ex)
|
||||
|
||||
def _raum_stil_save(self, p):
|
||||
try:
|
||||
import elemente as _el
|
||||
d = Rhino.RhinoDoc.ActiveDoc
|
||||
name = (p.get("name") or "").strip()
|
||||
if not name: return
|
||||
sid = (p.get("id") or "").strip() or (
|
||||
"stil_" + __import__("uuid").uuid4().hex[:8])
|
||||
stile = _el.load_raum_stempel_stile(d)
|
||||
settings = p.get("settings") or {}
|
||||
new_stil = {"id": sid, "name": name}
|
||||
for f in _el._RAUM_STIL_FIELDS:
|
||||
if f in settings: new_stil[f] = settings[f]
|
||||
found = False
|
||||
for i, s in enumerate(stile):
|
||||
if s.get("id") == sid:
|
||||
stile[i] = new_stil; found = True; break
|
||||
if not found: stile.append(new_stil)
|
||||
_el.save_raum_stempel_stile(d, stile)
|
||||
except Exception as ex:
|
||||
print("[PROJECT-SETTINGS] raum_stil save:", ex)
|
||||
self._raum_stil_send_updated()
|
||||
|
||||
def _raum_stil_delete(self, p):
|
||||
try:
|
||||
import elemente as _el
|
||||
d = Rhino.RhinoDoc.ActiveDoc
|
||||
sid = (p.get("id") or "").strip()
|
||||
if not sid: return
|
||||
stile = _el.load_raum_stempel_stile(d)
|
||||
stile = [s for s in stile if s.get("id") != sid]
|
||||
_el.save_raum_stempel_stile(d, stile)
|
||||
except Exception as ex:
|
||||
print("[PROJECT-SETTINGS] raum_stil delete:", ex)
|
||||
self._raum_stil_send_updated()
|
||||
|
||||
def _raum_stil_duplicate(self, p):
|
||||
try:
|
||||
import elemente as _el
|
||||
import uuid as _uuid
|
||||
d = Rhino.RhinoDoc.ActiveDoc
|
||||
sid = (p.get("id") or "").strip()
|
||||
if not sid: return
|
||||
stile = _el.load_raum_stempel_stile(d)
|
||||
src = next((s for s in stile if s.get("id") == sid), None)
|
||||
if src is None: return
|
||||
new_name = (p.get("newName") or "").strip() or (
|
||||
"{} (Kopie)".format(src.get("name", "Stil")))
|
||||
new_stil = dict(src)
|
||||
new_stil["id"] = "stil_" + _uuid.uuid4().hex[:8]
|
||||
new_stil["name"] = new_name
|
||||
try:
|
||||
i = next(j for j, s in enumerate(stile) if s.get("id") == sid)
|
||||
stile.insert(i + 1, new_stil)
|
||||
except StopIteration:
|
||||
stile.append(new_stil)
|
||||
_el.save_raum_stempel_stile(d, stile)
|
||||
except Exception as ex:
|
||||
print("[PROJECT-SETTINGS] raum_stil duplicate:", ex)
|
||||
self._raum_stil_send_updated()
|
||||
|
||||
def _raum_stil_reorder(self, p):
|
||||
try:
|
||||
import elemente as _el
|
||||
d = Rhino.RhinoDoc.ActiveDoc
|
||||
new_order = p.get("ids") or []
|
||||
if not isinstance(new_order, list) or not new_order: return
|
||||
stile = _el.load_raum_stempel_stile(d)
|
||||
by_id = {s.get("id"): s for s in stile if s.get("id")}
|
||||
ordered = []; seen = set()
|
||||
for i in new_order:
|
||||
if i in by_id and i not in seen:
|
||||
ordered.append(by_id[i]); seen.add(i)
|
||||
for s in stile:
|
||||
if s.get("id") and s["id"] not in seen:
|
||||
ordered.append(s); seen.add(s["id"])
|
||||
_el.save_raum_stempel_stile(d, ordered)
|
||||
except Exception as ex:
|
||||
print("[PROJECT-SETTINGS] raum_stil reorder:", ex)
|
||||
self._raum_stil_send_updated()
|
||||
def _pick_texture(self, payload):
|
||||
slot = payload.get("slot") or "diffuse"
|
||||
try:
|
||||
|
||||
Reference in New Issue
Block a user