Ebenen-Split: FIRST_RUN-Race + Slice-Authoritaet fixen
Symptom: Nach Split funktionierten die Ebenen nicht und Container
erschienen doppelt.
Two bugs:
1. FIRST_RUN-Detection war global statt mode-aware:
- Beim ersten Plugin-Start war doc.Strings leer.
- Bridge A (z.B. Zeichnungsebenen) sah leer → sendete FIRST_RUN
→ React schickte APPLY mit `z=INITIAL_Z, e=[]`.
- Backend speicherte `[]` fuer dossier_ebenen → fortan war
doc.Strings nicht mehr leer.
- Bridge B (Ebenen) sah dossier_ebenen vorhanden ("[]") → sendete
STATE_SYNC mit leerer Liste statt FIRST_RUN → React-App
ueberschrieb INITIAL_EBENEN mit `[]` → leere UI.
Fix: `_on_ready` prueft jetzt mode-spezifisch ob SEINE Slice in
doc.Strings ist. "ebenen"-Mode schaut auf dossier_ebenen,
"zeichnungsebenen" auf dossier_zeichnungsebenen.
2. APPLY ueberschrieb fremde Slice mit Fallback-`[]`:
- Wenn nur eine Panel-Slice im Payload kam, las Backend die
andere aus doc.Strings (= leer beim ersten Mal) und schrieb
dann *beide* Slices, davon eine als `[]`.
- Naechstes READY sah die `[]` → STATE_SYNC statt FIRST_RUN →
Daten weg.
Fix: `_apply` bekommt `save_z`/`save_e` Flags. Jedes Panel ist
autoritativ fuer SEINE Slice. APPLY aus dem Ebenen-Panel
speichert NUR dossier_ebenen (save_z=False), aus Zeichnungs-
ebenen NUR dossier_zeichnungsebenen.
Effekt: Wenn Ebenen-Panel zuerst lädt → speichert ebenen, lässt z
unangetastet → Zeichnungsebenen-Panel sieht z fehlt → bekommt
FIRST_RUN → schickt INITIAL_Z → speichert z. Symmetrisch wenn
Zeichnungsebenen zuerst lädt.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
+25
-16
@@ -117,7 +117,12 @@ class EbenenBridge(panel_base.BaseBridge):
|
|||||||
doc = Rhino.RhinoDoc.ActiveDoc
|
doc = Rhino.RhinoDoc.ActiveDoc
|
||||||
z_raw = doc.Strings.GetValue("dossier_zeichnungsebenen")
|
z_raw = doc.Strings.GetValue("dossier_zeichnungsebenen")
|
||||||
e_raw = doc.Strings.GetValue("dossier_ebenen")
|
e_raw = doc.Strings.GetValue("dossier_ebenen")
|
||||||
if z_raw or e_raw:
|
# FIRST_RUN-Entscheidung ist MODE-AWARE: jedes Panel sendet FIRST_RUN
|
||||||
|
# wenn SEINE Slice in doc.Strings fehlt. Sonst race-conditiont das
|
||||||
|
# erste APPLY (das nur eine Slice schreibt) und das andere Panel
|
||||||
|
# kriegt STATE_SYNC mit leerer Slice → leere UI.
|
||||||
|
my_slice_present = (e_raw if self._mode == "ebenen" else z_raw)
|
||||||
|
if my_slice_present:
|
||||||
try:
|
try:
|
||||||
z = json.loads(z_raw) if z_raw else None
|
z = json.loads(z_raw) if z_raw else None
|
||||||
e = json.loads(e_raw) if e_raw else None
|
e = json.loads(e_raw) if e_raw else None
|
||||||
@@ -155,18 +160,20 @@ class EbenenBridge(panel_base.BaseBridge):
|
|||||||
if t == "READY":
|
if t == "READY":
|
||||||
self._on_ready()
|
self._on_ready()
|
||||||
elif t == "APPLY":
|
elif t == "APPLY":
|
||||||
# Beide Panels koennen APPLY schicken. Wenn nur eine Slice
|
# Jedes Panel ist autoritativ fuer SEINE Slice; die andere kommt
|
||||||
# gesendet wird, fehlende aus doc.Strings nachladen damit
|
# aus doc.Strings (Fallback) damit build_layers nicht mit leerer
|
||||||
# build_layers nicht mit leerer Liste arbeitet.
|
# Liste arbeitet. So ueberschreiben wir nicht versehentlich die
|
||||||
z_payload = p.get("zeichnungsebenen")
|
# andere Panel-Slice mit "[]" bei Split-APPLYs.
|
||||||
e_payload = p.get("ebenen")
|
if self._mode == "zeichnungsebenen":
|
||||||
if not z_payload:
|
z_payload = p.get("zeichnungsebenen") or []
|
||||||
z_raw = doc.Strings.GetValue("dossier_zeichnungsebenen")
|
|
||||||
z_payload = json.loads(z_raw) if z_raw else []
|
|
||||||
if not e_payload:
|
|
||||||
e_raw = doc.Strings.GetValue("dossier_ebenen")
|
e_raw = doc.Strings.GetValue("dossier_ebenen")
|
||||||
e_payload = json.loads(e_raw) if e_raw else []
|
e_payload = json.loads(e_raw) if e_raw else []
|
||||||
self._apply(z_payload, e_payload)
|
self._apply(z_payload, e_payload, save_z=True, save_e=False)
|
||||||
|
else:
|
||||||
|
e_payload = p.get("ebenen") or []
|
||||||
|
z_raw = doc.Strings.GetValue("dossier_zeichnungsebenen")
|
||||||
|
z_payload = json.loads(z_raw) if z_raw else []
|
||||||
|
self._apply(z_payload, e_payload, save_z=False, save_e=True)
|
||||||
elif t == "LAYER_STYLE":
|
elif t == "LAYER_STYLE":
|
||||||
layer_builder.update_layer_style(doc, p["code"], p.get("color"), p.get("lw"))
|
layer_builder.update_layer_style(doc, p["code"], p.get("color"), p.get("lw"))
|
||||||
if p.get("color") is not None:
|
if p.get("color") is not None:
|
||||||
@@ -210,10 +217,10 @@ class EbenenBridge(panel_base.BaseBridge):
|
|||||||
|
|
||||||
# ---- Helpers ----
|
# ---- Helpers ----
|
||||||
|
|
||||||
def _apply(self, zeichnungsebenen, ebenen):
|
def _apply(self, zeichnungsebenen, ebenen, save_z=True, save_e=True):
|
||||||
print("[EBENEN] _apply START z={} e={}".format(
|
print("[EBENEN] _apply START z={} e={} (save_z={} save_e={})".format(
|
||||||
len(zeichnungsebenen) if zeichnungsebenen else 0,
|
len(zeichnungsebenen) if zeichnungsebenen else 0,
|
||||||
len(ebenen) if ebenen else 0))
|
len(ebenen) if ebenen else 0, save_z, save_e))
|
||||||
doc = Rhino.RhinoDoc.ActiveDoc
|
doc = Rhino.RhinoDoc.ActiveDoc
|
||||||
|
|
||||||
# Vor dem Schreiben: alten Fill-Stand snapshotten, damit wir hinterher
|
# Vor dem Schreiben: alten Fill-Stand snapshotten, damit wir hinterher
|
||||||
@@ -260,8 +267,10 @@ class EbenenBridge(panel_base.BaseBridge):
|
|||||||
z_json = json.dumps(zeichnungsebenen, ensure_ascii=False)
|
z_json = json.dumps(zeichnungsebenen, ensure_ascii=False)
|
||||||
e_json = json.dumps(ebenen, ensure_ascii=False)
|
e_json = json.dumps(ebenen, ensure_ascii=False)
|
||||||
print("[EBENEN] _apply: SetString ...")
|
print("[EBENEN] _apply: SetString ...")
|
||||||
doc.Strings.SetString("dossier_zeichnungsebenen", z_json)
|
if save_z:
|
||||||
doc.Strings.SetString("dossier_ebenen", e_json)
|
doc.Strings.SetString("dossier_zeichnungsebenen", z_json)
|
||||||
|
if save_e:
|
||||||
|
doc.Strings.SetString("dossier_ebenen", e_json)
|
||||||
# Smart-Elemente (Waende) regenerieren — Geschoss-Hoehen/OKFF
|
# Smart-Elemente (Waende) regenerieren — Geschoss-Hoehen/OKFF
|
||||||
# haben sich evtl. geaendert, gebundene Waende muessen neu
|
# haben sich evtl. geaendert, gebundene Waende muessen neu
|
||||||
# extrudiert werden. Best-effort, faengt jeden Fehler ab.
|
# extrudiert werden. Best-effort, faengt jeden Fehler ab.
|
||||||
|
|||||||
Reference in New Issue
Block a user