diff --git a/rhino/elemente.py b/rhino/elemente.py index 54cdad6..04bb32e 100644 --- a/rhino/elemente.py +++ b/rhino/elemente.py @@ -6917,6 +6917,10 @@ class ElementeBridge(panel_base.BaseBridge): self._cmd_delete_stempel_stil(p) elif t == "APPLY_STEMPEL_STIL": self._cmd_apply_stempel_stil(p) + elif t == "DUPLICATE_STEMPEL_STIL": + self._cmd_duplicate_stempel_stil(p) + elif t == "REORDER_STEMPEL_STILE": + self._cmd_reorder_stempel_stile(p) elif t == "OPEN_ELEMENTE_UEBERSICHT": try: import elemente_uebersicht @@ -9339,6 +9343,46 @@ class ElementeBridge(panel_base.BaseBridge): stil.get("name"), n)) self._send_state() + def _cmd_duplicate_stempel_stil(self, p): + doc = Rhino.RhinoDoc.ActiveDoc + if doc is None: return + sid = (p.get("id") or "").strip() + if not sid: return + stile = load_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"] = "stestil_" + 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) + save_stempel_stile(doc, stile) + print("[ELEMENTE] Stempel-Stil '{}' dupliziert -> '{}'".format( + src.get("name"), new_name)) + self._send_state() + + def _cmd_reorder_stempel_stile(self, p): + 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_stempel_stile(doc) + 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"]) + save_stempel_stile(doc, ordered) + self._send_state() + def _cmd_create_symbol(self, p): """Platziert ein Library-Item (symbol/object) im Doc. Interactive GetPoint im aktiven Viewport — User klickt Position. diff --git a/rhino/rhinopanel.py b/rhino/rhinopanel.py index d209a87..d45c9cc 100644 --- a/rhino/rhinopanel.py +++ b/rhino/rhinopanel.py @@ -961,13 +961,16 @@ 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 + # Raumstempel-Stile + Stempel-Stile + Fonts aus elemente fuer die + # "Raumstile" und "Stempelstile" Tabs try: import elemente as _el - raum_stile = _el.load_raum_stempel_stile(doc) - fonts_list = _el._list_system_fonts() + raum_stile = _el.load_raum_stempel_stile(doc) + stempel_stile = _el.load_stempel_stile(doc) + fonts_list = _el._list_system_fonts() except Exception: raum_stile = [] + stempel_stile = [] fonts_list = [] params = { "defaults": current.get("defaults", {}), @@ -980,6 +983,7 @@ class EbenenBridge(panel_base.BaseBridge): "libraryItems": lib_items, "libraryRoot": lib_root, "raumStempelStile": raum_stile, + "stempelStile": stempel_stile, "fonts": fonts_list, } def on_save(updated): @@ -1096,6 +1100,14 @@ class EbenenBridge(panel_base.BaseBridge): self._raum_stil_duplicate(p) elif t == "REORDER_RAUM_STILE": self._raum_stil_reorder(p) + elif t == "SAVE_STEMPEL_STIL": + self._stempel_stil_save(p) + elif t == "DELETE_STEMPEL_STIL": + self._stempel_stil_delete(p) + elif t == "DUPLICATE_STEMPEL_STIL": + self._stempel_stil_duplicate(p) + elif t == "REORDER_STEMPEL_STILE": + self._stempel_stil_reorder(p) # ---- Raumstempel-Stile (Settings-Tab "Raumstile") ---- # Dispatcht direkt zu elemente.py — kein Roundtrip via Elemente- @@ -1190,6 +1202,99 @@ class EbenenBridge(panel_base.BaseBridge): except Exception as ex: print("[PROJECT-SETTINGS] raum_stil reorder:", ex) self._raum_stil_send_updated() + + # ---- Stempel-Stile (analog Raum-Stil-Pattern) ---- + def _stempel_stil_send_updated(self): + try: + import elemente as _el + d = Rhino.RhinoDoc.ActiveDoc + self.send("STEMPEL_STILE_UPDATED", + {"stempelStile": _el.load_stempel_stile(d)}) + except Exception as ex: + print("[PROJECT-SETTINGS] STEMPEL_STILE_UPDATED:", ex) + + def _stempel_stil_save(self, p): + try: + import elemente as _el + import uuid as _uuid + d = Rhino.RhinoDoc.ActiveDoc + name = (p.get("name") or "").strip() + if not name: return + sid = (p.get("id") or "").strip() or ( + "stestil_" + _uuid.uuid4().hex[:8]) + settings = p.get("settings") or {} + stile = _el.load_stempel_stile(d) + new_stil = {"id": sid, "name": name} + for f in _el._STEMPEL_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_stempel_stile(d, stile) + except Exception as ex: + print("[PROJECT-SETTINGS] stempel_stil save:", ex) + self._stempel_stil_send_updated() + + def _stempel_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_stempel_stile(d) + stile = [s for s in stile if s.get("id") != sid] + _el.save_stempel_stile(d, stile) + except Exception as ex: + print("[PROJECT-SETTINGS] stempel_stil delete:", ex) + self._stempel_stil_send_updated() + + def _stempel_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_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"] = "stestil_" + _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_stempel_stile(d, stile) + except Exception as ex: + print("[PROJECT-SETTINGS] stempel_stil duplicate:", ex) + self._stempel_stil_send_updated() + + def _stempel_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_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_stempel_stile(d, ordered) + except Exception as ex: + print("[PROJECT-SETTINGS] stempel_stil reorder:", ex) + self._stempel_stil_send_updated() + def _pick_texture(self, payload): slot = payload.get("slot") or "diffuse" try: diff --git a/src/components/ProjectSettingsDialog.jsx b/src/components/ProjectSettingsDialog.jsx index bd48bd8..f25f1e7 100644 --- a/src/components/ProjectSettingsDialog.jsx +++ b/src/components/ProjectSettingsDialog.jsx @@ -10,6 +10,7 @@ import { listLibraryItems, addLibraryFile, updateLibraryItem, deleteLibraryItem, saveSelectionAsLibrary, saveRaumStil, deleteRaumStil, duplicateRaumStil, reorderRaumStile, + saveStempelStil, deleteStempelStil, duplicateStempelStil, reorderStempelStile, } from '../lib/rhinoBridge' /* Field — Stack-Layout fuer komplexe Inputs (mehrere Felder nebeneinander) */ @@ -651,6 +652,9 @@ export default function ProjectSettingsDialog({ // wenn Backend CRUD-Op fertig ist. Drag-Reorder lokal + commit beim Drop. const [raumStile, setRaumStile] = useState(initial.raumStempelStile || []) const [dragStilIdx, setDragStilIdx] = useState(null) + // Stempel-Stile (Bilanz-Stempel-Presets) — parallele Liste + const [stempelStile, setStempelStile] = useState(initial.stempelStile || []) + const [dragStempelIdx, setDragStempelIdx] = useState(null) const fontsList = initial.fonts || [] // Aktuell ausgewaehltes Material aus Selection ableiten @@ -691,6 +695,9 @@ export default function ProjectSettingsDialog({ onMessage('STILE_UPDATED', ({ raumStempelStile }) => { if (Array.isArray(raumStempelStile)) setRaumStile(raumStempelStile) }) + onMessage('STEMPEL_STILE_UPDATED', ({ stempelStile: ss }) => { + if (Array.isArray(ss)) setStempelStile(ss) + }) }, []) // Backend-File-Picker-Antwort: aktualisiert das Slot im aktuell @@ -760,12 +767,13 @@ export default function ProjectSettingsDialog({