From 8d3b3af88253dbafb0f5d8ecdba399afedd76b42 Mon Sep 17 00:00:00 2001 From: karim Date: Mon, 25 May 2026 02:10:04 +0200 Subject: [PATCH] Material/Ebene-Separation: Hatch raus aus Material (Refactor a) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Material ist jetzt rein 3D — Section-Hatch (2D-Schnitt) wird nicht mehr am Material definiert, sondern am Layer (via Rhino-Layer-Dialog oder spaeter via Ebenen-Settings + neuer Hatch-Tab im Project-Settings). Schema-Aenderungen: - _normalize_material: hatch + scale entfernt - _MATERIAL_LIBRARY (elemente.py): hatch + scale aus allen Builtin-Mats - _get_all_materials: ohne hatch - _send_state materials payload: nur {name, color} - Library import_material: PBR + Texturen werden weitergegeben Backend: - _ensure_material_sublayer: erstellt Sublayer mit Color, RESETTET aber alten SectionHatchIndex auf -1 (= "kein eigener Hatch") damit Inheritance/User-Override greift. Vorher wurden alte Material-Hatch- Werte da haengen geblieben. Frontend: - MaterialDetail: Schraffur-Section entfernt - hatchPatterns-Prop entfernt Konsequenz: existierende Waende verlieren ihren Section-Hatch beim naechsten Regen. User definiert Section-Hatches jetzt auf Layer-Ebene. Co-Authored-By: Claude Opus 4.7 --- rhino/elemente.py | 46 +++++++++++++----------- rhino/library.py | 14 ++++---- rhino/rhinopanel.py | 16 ++++----- src/components/ProjectSettingsDialog.jsx | 28 ++------------- 4 files changed, 43 insertions(+), 61 deletions(-) diff --git a/rhino/elemente.py b/rhino/elemente.py index d7f1f57..b642e41 100644 --- a/rhino/elemente.py +++ b/rhino/elemente.py @@ -2195,26 +2195,25 @@ def _make_volume_geometry(axis_curve, dicke, uk, ok, referenz="mid", # konfiguriert — sobald der User eine Clipping Plane setzt, zeigt Rhino # automatisch die korrekte Schnitt-Symbolik pro Schicht. _MATERIAL_LIBRARY = { - "Beton": {"color": "#9a9a9a", "hatch": "Hatch3", "scale": 1.0}, - "Stahlbeton": {"color": "#888888", "hatch": "Hatch3", "scale": 0.5}, - "Mauerwerk": {"color": "#b67860", "hatch": "Hatch1", "scale": 1.0}, - "Dämmung": {"color": "#f4e4a0", "hatch": "Hatch2", "scale": 0.5}, - "Holz": {"color": "#c89a5a", "hatch": "HatchDash", "scale": 1.0}, - "Stahl": {"color": "#7a7a7a", "hatch": "Solid", "scale": 1.0}, - "Putz": {"color": "#ede4d6", "hatch": "Solid", "scale": 1.0}, - "Glas": {"color": "#bcd4e0", "hatch": "Solid", "scale": 1.0}, + "Beton": {"color": "#9a9a9a"}, + "Stahlbeton": {"color": "#888888"}, + "Mauerwerk": {"color": "#b67860"}, + "Dämmung": {"color": "#f4e4a0"}, + "Holz": {"color": "#c89a5a"}, + "Stahl": {"color": "#7a7a7a"}, + "Putz": {"color": "#ede4d6"}, + "Glas": {"color": "#bcd4e0", "transparency": 0.7, "iorN": 1.5}, } def _get_all_materials(doc): """Builtin _MATERIAL_LIBRARY + Projekt-Settings-Materialien gemerged. - Returns dict[name] -> full material dict (color/hatch/scale + PBR + - textures + uvScaleM). Projekt-Settings ueberschreibt builtin bei - Namensgleichheit. Builtin-Materialien bekommen leere PBR-Defaults.""" + Returns dict[name] -> full material dict (color + PBR + textures + + uvScaleM). Section-Hatch (2D-Schnitt) ist NICHT mehr im Material — + der wird per Ebenen-Settings am Layer konfiguriert.""" merged = {} for n, m in _MATERIAL_LIBRARY.items(): merged[n] = dict(m) - # Builtin: PBR-Defaults wenn nicht gesetzt merged[n].setdefault("roughness", 0.7) merged[n].setdefault("reflection", 0.1) merged[n].setdefault("transparency", 0.0) @@ -2228,8 +2227,6 @@ def _get_all_materials(doc): for m in ps.get("materials", []): n = m.get("name") if not n: continue - # Komplettes dict uebernehmen — _normalize_material hat - # bereits alle Felder validiert. merged[n] = dict(m) except Exception as ex: print("[ELEMENTE] _get_all_materials:", ex) @@ -2268,7 +2265,11 @@ def _set_layer_section_hatch(doc, layer_idx, hatch_name, scale=1.0, def _ensure_material_sublayer(doc, geschoss_name, material_name): """Stellt sicher dass `::20_WAENDE::` existiert, - mit Material-Farbe + Section-Hatch konfiguriert. Liefert Layer-Index. + mit Material-Farbe konfiguriert. Liefert Layer-Index. + Section-Hatch (2D-Schnitt) wird NICHT mehr aus dem Material gesetzt — + der kommt vom Parent-Layer (= Ebenen-Settings). Sub-Layer haben default + keine eigene Section-Hatch, sie inherit'en Rhino-typisch ihre Optik + fuer den Schnitt vom Parent. Bei leerem oder unbekanntem Material: Fallback auf das normale Wand-Volume-Layer (= Standard fuer Solid-Waende).""" all_mats = _get_all_materials(doc) @@ -2285,14 +2286,20 @@ def _ensure_material_sublayer(doc, geschoss_name, material_name): hex_str = mat["color"].lstrip("#") r = int(hex_str[0:2], 16); g = int(hex_str[2:4], 16); b = int(hex_str[4:6], 16) new_col = SD.Color.FromArgb(255, r, g, b) - # Nur aendern wenn die Farbe abweicht (vermeidet unnoetige Doc-Dirty) try: if int(layer.Color.ToArgb()) != int(new_col.ToArgb()): layer.Color = new_col doc.Layers.Modify(layer, idx, True) except Exception: pass - _set_layer_section_hatch(doc, idx, mat["hatch"], - mat.get("scale", 1.0)) + # Section-Hatch: legacy-fields hatch/scale am Sub-Layer LOESCHEN + # damit alte Setzungen weg sind. Index=-1 = "kein eigener Hatch, + # User kann in Rhino-Layer-Dialog oder Ebenen-Settings setzen". + try: + if hasattr(layer, "SectionHatchIndex"): + if layer.SectionHatchIndex >= 0: + layer.SectionHatchIndex = -1 + doc.Layers.Modify(layer, idx, True) + except Exception: pass except Exception as ex: print("[ELEMENTE] _ensure_material_sublayer:", ex) return idx @@ -6295,8 +6302,7 @@ class ElementeBridge(panel_base.BaseBridge): "siaFillMode": _sia_fill_enabled(doc), "hatchPatterns": _list_hatch_patterns(doc), "materials": [ - {"name": n, "color": m["color"], - "hatch": m.get("hatch", ""), "scale": m.get("scale", 1.0)} + {"name": n, "color": m["color"]} for n, m in _get_all_materials(doc).items()], "oeffStyles": list_oeff_styles(doc), } diff --git a/rhino/library.py b/rhino/library.py index cb50fc3..6d8127d 100644 --- a/rhino/library.py +++ b/rhino/library.py @@ -82,28 +82,28 @@ def _write_seed_manifest(path): "type": "material", "version": 1, "name": "Beton — Sichtbeton", "tags": ["beton", "tragwerk", "roh"], - "data": {"color": "#a8a39b", "hatch": "Solid", "scale": 1.0}, + "data": {"color": "#a8a39b"}, }, { "id": "mat-mauerwerk-backstein-v1", "type": "material", "version": 1, "name": "Mauerwerk — Backstein", "tags": ["mauerwerk", "stein"], - "data": {"color": "#a45a3c", "hatch": "Solid", "scale": 1.0}, + "data": {"color": "#a45a3c"}, }, { "id": "mat-daemmung-mineralwolle-v1", "type": "material", "version": 1, "name": "Daemmung — Mineralwolle", "tags": ["daemmung", "weich"], - "data": {"color": "#e8d36b", "hatch": "Solid", "scale": 1.0}, + "data": {"color": "#e8d36b"}, }, { "id": "mat-holz-fichte-v1", "type": "material", "version": 1, "name": "Holz — Fichte", "tags": ["holz", "ausbau"], - "data": {"color": "#c8a06a", "hatch": "Solid", "scale": 1.0}, + "data": {"color": "#c8a06a"}, }, { "id": "sym-nordpfeil-01", @@ -192,11 +192,13 @@ def import_material(doc, item): new_mat = { "name": item.get("name") or "Unbenannt", "color": data.get("color", "#888888"), - "hatch": data.get("hatch", "Solid"), - "scale": float(data.get("scale", 1.0) or 1.0), "source": "library", "libraryId": item.get("id"), } + # PBR + Textur-Felder, falls Library-Item welche hat + for k in ("roughness", "reflection", "transparency", "iorN", + "uvScaleM", "textures"): + if k in data: new_mat[k] = data[k] # Lazy-Import um Zyklen zu vermeiden import rhinopanel settings = rhinopanel.load_project_settings(doc) diff --git a/rhino/rhinopanel.py b/rhino/rhinopanel.py index 9c58854..7a5215e 100644 --- a/rhino/rhinopanel.py +++ b/rhino/rhinopanel.py @@ -141,11 +141,13 @@ _PROJECT_SETTINGS_DEFAULTS = { def _normalize_material(m): - """Garantiert Material-Schema. Felder: + """Garantiert Material-Schema. Material ist REIN 3D — Section-Hatch + (2D-Schnitt) wird via Ebenen-Settings am Layer konfiguriert. + Felder: - Identitaet: name, source ('local'|'library'|'builtin'), libraryId - - Section-Hatch (2D): color, hatch, scale - - PBR (3D-Render): roughness (0..1), reflection (0..1), - transparency (0..1), iorN (1.0..2.5) + - 3D-Farbe: color + - PBR (3D-Render): roughness, reflection, transparency (0..1), + iorN (1.0..2.5) - UV: uvScaleM (= 1 Welt-Meter ≙ wieviel der Textur) - Texturen: textures = { diffuse, bump, roughness, transparency } pro Slot {path: absolute string} oder null. Strength fuer Bump.""" @@ -158,7 +160,6 @@ def _normalize_material(m): p = t.get("path") if not p: return None out = {"path": str(p)} - # Bump hat zusaetzlich strength (-1..1, default 0.5) if slot == "bump": try: out["strength"] = float(t.get("strength", 0.5)) except Exception: out["strength"] = 0.5 @@ -166,18 +167,13 @@ def _normalize_material(m): return { "name": m.get("name") or "Unbenannt", "color": m.get("color") or "#888888", - "hatch": m.get("hatch") or "Solid", - "scale": float(m.get("scale", 1.0) or 1.0), "source": m.get("source") or "local", "libraryId": m.get("libraryId"), - # PBR (3D-Render) — alle 0..1 ausser iorN "roughness": _clamp01(m.get("roughness", 0.7)), "reflection": _clamp01(m.get("reflection", 0.1)), "transparency": _clamp01(m.get("transparency", 0.0)), "iorN": _clamp(m.get("iorN", 1.0), 1.0, 2.5), - # UV-Skalierung (1 m = uvScaleM Textur-Tiles) "uvScaleM": float(m.get("uvScaleM", 1.0) or 1.0), - # Texturen "textures": { "diffuse": _tex("diffuse"), "bump": _tex("bump"), diff --git a/src/components/ProjectSettingsDialog.jsx b/src/components/ProjectSettingsDialog.jsx index ea8a8d2..f075c20 100644 --- a/src/components/ProjectSettingsDialog.jsx +++ b/src/components/ProjectSettingsDialog.jsx @@ -208,8 +208,9 @@ function DetailSection({ title, children }) { } /* MaterialDetail — rechte Seite (ArchiCAD-Stil): editiert das aktuell - ausgewaehlte Material. Builtin: Name read-only. */ -function MaterialDetail({ mat, isBuiltin, hatchPatterns, onChange, onDelete }) { + ausgewaehlte Material. Material = REIN 3D (Color + PBR + Texturen). + Section-Hatch (2D-Schnitt) wird via Ebenen-Settings am Layer gesetzt. */ +function MaterialDetail({ mat, isBuiltin, onChange, onDelete }) { if (!mat) { return (
- -
- - onChange({ ...mat, scale: parseFloat(ev.target.value) || 1.0 })} - title="Skalierung" - style={{ width: 70, height: BAR_H, padding: '0 10px', - fontSize: 11, textAlign: 'right' }} /> -
-
- Hatch-Pattern + Skalierung fuer die Sektion-Ansicht (Clipping Plane). -
-
- { @@ -572,7 +551,6 @@ export default function ProjectSettingsDialog({