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:
2026-05-26 23:47:38 +02:00
parent f208e7fc00
commit 7fbda8c289
5 changed files with 308 additions and 5 deletions
+112
View File
@@ -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: