Commit Graph

204 Commits

Author SHA1 Message Date
karim d558fac2c3 Styles: default pen for new objects + csharp build doc
Gestaltung panel now shows pen controls (color, lineweight, linetype)
when nothing is selected. Settings persist in sticky and are stamped
onto every newly drawn object (curves, text, hatch, dims — not 3D
solids or DOSSIER element geometry) via the existing AddRhinoObject
listener. Active state shown with badge; resets by switching all back
to "Nach Ebene".

Also adds csharp/BUILD.md with full build + post-reinstall checklist.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 02:00:47 +02:00
karim e8da519d29 Tools + Elements: layout per display mode
- Symbol only ('icon'): uniform grid (square aligned tiles)
- Text / Symbol+Text: original ragged content-width pills that wrap freely
  (flex-wrap), like before the grid redesign
- Container switches grid↔flex-wrap on mode; pill switches full-width↔auto
- Dropdown picks the layout: density grid for icons, readable pills for text
2026-06-06 15:34:07 +02:00
karim cd87a0b7f4 Tools + Elements: horizontal tiles in grid + dropdown moved left
- Tile content back to horizontal (icon beside label, left-aligned) while
  keeping the aligned grid columns — per user choice 'Raster + horizontal'
- Wider 'both' column (86px) to fit icon+label in one row, single-row height
- Display-mode dropdown moved to the left (justify-content flex-start)
- icon-only and text-only modes stay centered; hasMenu chevron inline next
  to label (both/text) or as corner indicator (icon-only)
2026-06-06 15:23:52 +02:00
karim c0624c0a62 Tools + Elements: smaller tiles, display-mode dropdown, dark pill look
- Tiles shrunk (minHeight 46/38/30 per mode, tighter padding, smaller icons)
- Add display-mode dropdown (Symbol / Text / Symbol+Text) at top of each
  panel; choice persists in localStorage under 'dossier_tile_mode' and is
  shared between both panels
- Grid column min-width adapts per mode (icon 40 / text 66 / both 58)
- Restore dark pill look: --bg-input background + border-light, full
  border-radius — tiles read as distinct chips again
- Icon-only mode shows a small corner chevron on dropdown tiles
  (Treppe/Stuetze/Traeger) so the right-click menu stays discoverable
2026-06-06 15:14:29 +02:00
karim e531217cb7 Tools + Elements panels: ragged pills → uniform grid tiles
Both panels shared the same flex-wrap pill layout where each pill sized to
its content, producing a ragged, hard-to-scan right edge. Switch to a uniform
CSS grid (auto-fill, minmax(68px, 1fr)) of icon-over-label tiles:

- ToolsApp: ToolPill → ToolTile, PillGroup → GridSection
- ElementeApp: PillButton → vertical tile (keeps hasMenu chevron, badge as
  corner pill, disabled state); PillGroup → grid section
- Less chrome: borderless tiles on subtle --bg-item, accent border on hover
- Dropdown tiles (Treppe/Stütze/Träger) keep their relative-positioned
  wrapper so PopupMenu still anchors correctly
2026-06-06 14:43:17 +02:00
karim b6ba83eb5d DossierSettings: show restart-required hint after language change
Instead of a temporary 'saved' checkmark, show a persistent warn-colored
'Neustart erforderlich' / 'Restart required' badge (in the newly selected
language) until the window is closed. Guards against no-op clicks (same lang).
2026-06-06 14:34:22 +02:00
karim 05a289dd65 Fix language reload: hasattr('mode') → hasattr('_mode'), val.mode → val._mode
BaseBridge stores mode as self._mode, not self.mode — so the reload
loop never found any bridges and language switching did nothing.
2026-06-06 14:25:26 +02:00
karim 82d0939a18 Fix last German log remnants: [ELEMENTS], re-persisted, after LoadDefaults, exposes 2026-06-06 13:38:04 +02:00
karim 220a1e2bb3 Fix log tags + SAVE_LANG bridge bug
panel_base: add _MODE_LOG_TAG map + _tag() function so Panel
registered/opened use [LAYERS], [TOOLBAR] etc. instead of [EBENEN]/[OBERLEISTE]

toolbar: _open_dossier_settings_panel now uses a custom _SettingsBridge
that actually handles SAVE_LANG -> writes lang to settings + reloads
all panels. Previously the default _SatelliteBridge only handled SAVE/CANCEL
so language switching did nothing.
2026-06-06 13:09:54 +02:00
karim b9a2124026 Rename all log tags to match English module names
[EBENEN] → [LAYERS], [EBENEN-BE] → [LAYERS-BE]
[ZEICHNUNGSEBENEN] → [DRAWING-LEVELS]
[GESTALTUNG] → [STYLES]
[OBERLEISTE] → [TOOLBAR]
[WERKZEUGE] → [TOOLS]
[DIMENSIONEN] → [DIMENSIONS]
[AUSSCHNITTE] → [VIEWPORTS]
[MASSSTAB] → [SCALE]
[SCHNITT] → [SECTION], [SCHNITT_GRIPS] → [SECTION-GRIPS]
[WAND_GRIPS] → [WALL-GRIPS], [TREPPE_GRIPS] → [STAIR-GRIPS]
[CURVE_DOTS] → [CURVE-DOTS]
[panel_base] → [CORE]
[ALIAS-LOADER] → [ALIASES]
[BEGIN-CMD] → [CMD-HOOK]
2026-06-06 12:48:27 +02:00
karim 84ff943f92 Fix remaining partial translations in log messages 2026-06-06 12:35:36 +02:00
karim 24f6b76f06 Translate remaining internal log messages to English
- EBENEN: drawing levels updated, sublayer not found, saved/verified
- GESTALTUNG: Linetypes before/after, fill field, opened/focused
- CLIP: disabled done
- ELEMENTE: Bulk-op, Listener bail
- Global: not found, not available, unchanged, failed, present
2026-06-06 12:19:10 +02:00
karim 9fcada260e Fix remaining German log messages: Panel registered, Listener active, sync all files to PROJECTS
- Fix sed $-anchor issue: 'Panel registriert' now replaced globally
- Translate: Listener aktiv, Select-Handler, Closing-Hook, Doppelklick-Handler
- Translate SPLASH messages: gesetzt/angewendet
- Translate ALIAS-LOADER, WELCOME, ELEMENTE migration messages
- Full rsync of all rhino/*.py to PROJECTS (previously partial sync missed schnitte.py, wand_grips.py, treppe_grips.py, text_editor.py, welcome.py etc.)
2026-06-06 12:09:12 +02:00
karim b9f661cdb3 Translate Python log messages + fix rhinopanel import in PROJECTS
- startup.py: all user-visible messages translated to English
- panel_base.py: icon/rendering log messages translated
- toolbar.py: display mode check messages translated
- Global: Panel registered/opened/listener-active across all modules
- Fix: elemente.py and other files with stale 'import rhinopanel'
  were missing from PROJECTS sync — now properly copied
2026-06-06 11:38:20 +02:00
karim 375487c10c i18n DE/EN + DossierSettings panel + English file renames
i18n:
- src/i18n/de.json + en.json: 200+ keys covering all main panels
- src/i18n/index.js: t(key, vars) reads window.DOSSIER_LANG
- panel_base.py: injects window.DOSSIER_LANG from dossier_settings.json
- EbenenManager, GeschossManager, AusschnitteApp, LayoutsApp: all
  context menus and main labels use t()

DossierSettings panel:
- DossierSettingsApp.jsx: language toggle (DE/EN pill) + launcher status
- toolbar.py: OPEN_SETTINGS opens new Rhino-hosted satellite window,
  SAVE_LANG writes lang to dossier_settings.json + reloads all panels

File renames (JSX → English):
- ZeichnungsebenenApp → DrawingLevelsApp
- GeschossManager/Dialog/Settings → Floor*
- AusschnitteApp/Settings → Viewports*
- EbenenManager/Settings → Layer*
- GestaltungApp → StylesApp, OberleisteApp → ToolbarApp
- WerkzeugeApp → ToolsApp, DimensionenApp → DimensionsApp
- MassstabApp → ScaleApp, KameraApp → CameraApp
- MasseSettingsApp → UnitsSettingsApp
- ConfirmDeleteEbene → ConfirmDeleteLayer
- AusschnittLayerDialog → ViewportLayerDialog

Python module renames:
- rhinopanel.py → layers_panel.py
- oberleiste.py → toolbar.py
- gestaltung.py → styles.py
- werkzeuge.py → tools.py
- dimensionen.py → dimensions.py
- startup.py _MODULE_TO_PY updated, all cross-imports fixed
2026-06-06 11:09:33 +02:00
karim 92b4baa285 UX: WebView native-feel + Context-Menu Redesign + Startup-Fix
- Disable text selection (CSS user-select:none) + block browser
  context menu (contextmenu preventDefault) in all panels
- ContextMenu: pill items, accent hover, entrance animation,
  optional title header — controlled via single ContextMenu.css
- EbenenManager + GeschossManager: show layer name as menu title
- startup.py: skip splash on Cmd+N when plugin already loaded
- startup.py: hook NewDocument so display-modes apply to new docs
2026-06-06 05:27:48 +02:00
karim 18443b60c3 Layer-Smart-Join entfernt — nie verwendet, auto Phase 2 macht's
- Alt+Click bypass im Cluster-Volume-Select-Handler raus.
- _layer_join_attempt + dJoin-Detection in smart_join.py raus.

Phase 2 automatic handling deckt die Use-Cases ab. Falls Manual-Layer-
Merge spaeter doch noetig: commit 118bc51 hat den Code als Referenz.
2026-06-02 01:03:28 +02:00
karim dcfafb18d1 T-Junction angled: angle-aware Extension + Miter fuer flache T-Oberseite
Bei angled T-Junctions (nicht-90°) ragten Column-Ecken ueber Through-
Wand-Face raus (= "Stummel"). Fix in zwei Pfaden:

Cluster-Union (solid walls, _build_cluster_union_brep):
- Extension entlang my_tan = n_half / |cross(my_tan, n_tan)|. Fuer 90°
  bleibt = n_half, fuer angled wird laenger damit mitered End-Face auf
  Through-Body-Far-Face landet.
- Miter mit Nachbar-Tangent als miter_dir clippt L+R Curves an flache
  horizontale Linie aligned mit Through-Wand-Richtung.
- _make_volume_geometry erhaelt miter_start/_end.

Phase 2 (layered walls, _regenerate_element_body):
- Gleiches angle-aware Extension-Factor fuer _backbone_axis_ext.
- _layer_rect_2d erhaelt miter_start/_end Parameter.
- Backbone-col bekommt Miter am extended-end-Position.
- Non-backbone Spalten bekommen Std-Miter am Snap-Position.
- Beide aligned mit through-tan (b_tan) Richtung → T-Oberseite flach.

Diagnostic-Prints (bb-ext-calc, PRE-CARVE, CARVE cb, DO/SKIP carve)
bleiben drin fuer kommende Edge-Cases.
2026-06-02 00:50:09 +02:00
karim 118bc51cc5 T-Junction Phase 2 + Layer-Smart-Join: Backbone-Drill bis Stahl-Layer-Far-Face
Phase-2-Fixes:
- Backbone-Ext berechnet bis MATCHING-Layer (Stahl) far-face, nicht bis
  Body-far-face. Beton drillt durch Stahl-Band, nicht durch Daemm/Putz.
- Case A/B detection via dot(out_dir, RhinoPerp). Rhino Curve.Offset
  benutzt (tan × +z) = (b_tan.Y, -b_tan.X), nicht (-b_tan.Y, b_tan.X).
- Backbone-axis-ext separat von _my_axis_ext: nur Backbone-Column
  extended, non-backbone columns stoppen am Snap.
- Through-only Mats (z.B. Daemm wo T-stem keinen hat) werden auch
  durchlaufen damit hoehere-prio backbone diese carven kann.
- Post-Carve Union: gleiche-Material-Pieces mergen (Backbone-Beton-Col
  + Through-Stahl-Band → T-Shape).
- BBox-overlap strict-Filter vor BoolDiff: touching coplanar faces
  ueberspringen, vermeidet Rhino BoolDiff "punch-through" Artefakte.
- _has_my_cols guard: KeyError beim consume von T-stem-Layern fuer
  through-only mats verhindert.

Layer-Smart-Join (smart_join.py):
- Neue _layer_join_attempt: 2 selektierte wand_volume Breps gleicher
  Material via BoolUnion mergen. Manueller Override fuer Edge-Cases
  wo auto Phase 2 nicht reicht.

Cluster-Volume Select-Handler (elemente.py):
- Alt-Click bypassed Cluster-Swap → User kann einzelne Layer-Breps
  direkt anwaehlen (= fuer Layer-Smart-Join).
2026-06-01 21:54:02 +02:00
karim df56a54b66 T-Junction Phase 2 mit 3D Brep Union + Material-Prio-Carve
Asymmetric L-merge fuer Schichtdurchdringung:
- Backbone (= hoechste Material-Prio in beiden Waenden) bildet T-form
- Non-backbone Layer werden gecarved mit backbone-Column + through-Bands
  hoeherer Prio
- ext=0 fuer T-Stem-Axis (= column endet am snap, kein "drueber")
- 3D Brep Union via Brep.CreateBooleanUnion mit cross-junction safety
  (= aktueller through-Brep statt von Meta neu zu bauen)
- Cleanup: MergeCoplanarFaces

Plus:
- Innenwand Beton 20cm Style (Putz + Beton + Putz, ref-mid)
- curve_vertex_dots.py: gruene Vertex-Punkte fuer Polylinen/Curves
- Cluster-Volume Select Handler: Shift-Modifier fuer Multi-Select
- startup.py: Top-View maximieren on Doc-Open

Known limitation: Putz-Schicht kann in bestimmten Konfigurationen visuell
suedlich des Daemm-Band-Top weiter sichtbar sein (= edge case fuer
asymmetric layers). Naechster Schritt: manuelle 2D-Polygon-Konstruktion
statt 3D Boolean.
2026-06-01 14:32:55 +02:00
karim 9cce8199c3 T-Join 1-Wand-Modus: nur die zu snappende Wand selektieren reicht
UX-Verbesserung: User-Frage "muss ich nur das Element anwaehlen das ich
snappen moechte?" — jetzt ja.

Wenn nur 1 wand_axis in der Selection ist, sucht T-Join automatisch die
naechste andere Wand-Achse im Doc (innerhalb 1m) und snappt die selektierte
Wand auf jene. Die andere bleibt unangetastet — wie bei klassischem T-Stem
gegen Through-Wand.

2-Wand-Modus bleibt: dann werden GENAU die beiden selektierten betrachtet
(z.B. wenn 3+ Waende in der Nähe sind und User exakt eine andere meinen will).

Selection-Hint vereinfacht: nur noch warnen wenn 0 Wand-Achsen aber wand-
Objekte vorhanden (z.B. nur Volumen selektiert, wo Axis nicht mitkam).
2026-05-31 13:44:40 +02:00
karim e50134ce32 T-Join Tolerance auf 1m gelockert + Selection-Hint
User-Test: Bei T-Konfig waren Wand-Achsen 55cm auseinander (vermutlich
auf Outline statt Axis gesnappt). Mit 20cm tol fiel T-Join durch → L-Join
machte Tangent-Schnittpunkt (= L-Form falsch fuer T-Intent).

Fix: T-Join Snap-Radius von 20cm auf 1m. Generous genug fuer typische
Drift-Faelle (Outline-Snap statt Axis-Snap, ungefaehre Platzierung etc.),
aber tight genug damit absichtliche Lücken (>1m) nicht versehentlich
zugesnapped werden.

Plus: Hint wenn < 2 Wand-Achsen selektiert → User weiss explizit dass
GENAU 2 Wand selektiert sein muss.
2026-05-31 13:42:20 +02:00
karim c81d2c0c43 T-Join Diagnostic: zeigt warum jeder Endpunkt-Check verworfen wurde
User-Test: L-Join layered funktioniert (3/3 layers built). Aber T-Join laeuft
fuer layered immer in den L-Join-Fallback. Um zu sehen warum, jetzt fuer
jeden der 4 Endpunkt-Checks im T-Join:
- distance zur anderen Curve
- distance zur deren Endpunkten
- Reason warum verworfen (zu weit / nahe Endpunkt / schon snapped)

So koennen wir live im Log sehen ob T-Stem geometrisch zu weit weg ist
oder ob er an einem Endpunkt der Through-Wand landet (= L-Sache).
2026-05-31 13:20:27 +02:00
karim 26214a704d Replace-Listener: wand_layered/wand_layers/wand_style_id/wand_joint_rolle nach Replace bewahren
ROOT CAUSE: Wenn doc.Objects.Replace einer wand_axis ausgefuehrt wird (z.B.
nach L-Join von smart_join), prueft der Replace-Listener ob das neue Object
schon Meta hat. Wenn nicht, re-attached er via _attach_meta — aber die
wand-spezifischen Felder (wand_layered, wand_layers, wand_style_id,
wand_joint_rolle) wurden NICHT mit-uebergeben.

Effekt: layered Wand verlor wand_layered=True nach L-Join → naechster Regen
sieht is_layered=False → baut single SOLID Brep statt per-Layer-Breps →
"die gemerged walls sind dann leider solid walls".

Fix: Im Re-Attach-Aufruf die 4 wand-Felder mit weiterreichen aus meta.

Folge-Effekt: auch wand_style_id und wand_joint_rolle waren weg, was
Material-Lookup + Joint-Rolle-Override gebrochen hat. Beide jetzt fix.
2026-05-31 13:07:02 +02:00
karim 3e54fa46a6 smart_join: UserString-Key war FALSCH ("dossier_type" statt "dossier_element_type")
Bug: in _walls_and_curves_from_sel + safety check + diagnostic wurde
"dossier_type" als UserString-Key gelesen, aber der echte Key (definiert
in elemente.py via _KEY_TYPE) ist "dossier_element_type".

Effekt: kein einziges Objekt wurde als wand_axis/wand_volume erkannt.
ALLES landete im "elif t == '':" Branch (= generic curves).

Solid L-Join funktionierte per ZUFALL: bei Solid-Wand (axis + outline +
volume) sind nur 1 Curve open (axis); outline ist closed rectangle. Bei
2 Solid-Waenden waren also 2 offene Curves in generic → L-Join fand die
2 vermeintlich generic Curves (= eigentlich Achsen).

Bei Layered scheiterte es: 2 Achsen + 2 Centerlines = 4 offene Curves im
generic. L-Join Bedingung "len(generic) == 2" nicht erfuellt → silent
return → Fallthrough zu _Join.

Fix: alle 4 Vorkommen auf "dossier_element_type" gefixt. Jetzt erkennt
smart_join Waende richtig, dedupliziert per wall_id, und T-Join/L-Join/
Safety-Check funktionieren wie geplant.
2026-05-31 12:49:42 +02:00
karim 17ff7a8017 T-Junction-Toleranz auf 1cm gelockert + dJoin-Safety: keine _Join auf Achsen
T-Junction-Detection (_detect_t_junction): pos_tol von 1mm auf 1cm erhoeht.
User-Feedback: bei manuellem Snap kann's leicht ein paar mm danebengehen,
1mm war zu eng. 1cm ist immer noch tight genug fuer Architektur-Workflow.

smart_join (dJoin): Safety-Check vor _Join-Fallback. Wenn IRGENDEINE
wand_axis in der Selection ist (auch zusaetzlich zu anderen Curves), wird
NICHT auf Standard-_Join gefallen — sonst kleistert _Join mehrere Wand-
Achsen zu einer Polyline zusammen, der Listener detektiert das als
"Source-Duplikat" und vergibt neue Wall-IDs → alle Meta-Verknuepfungen
brechen.

Stattdessen: Print-Meldung dass T-Join/L-Join nicht gegriffen hat. User
muss GENAU 2 Waende selektieren die verbunden werden sollen.
2026-05-31 12:29:54 +02:00
karim 9999f3d0ad Schichtdurchdringung am T-Junction: pro Schicht material-basiertes Verbinden
Bisher: bei T-Junction stoppen ALLE Layers des T-Stems uniform am Near-Face
der Through-Wand (uniformer T-Miter pro Wand).

Neu: per-Schicht Logik im _make_wand_layer_breps:
- T-Stem-Schicht mit Material das in Through-Wand auch vorkommt → Layer-Axis
  extends um through_dicke/2 → Layer durchstoesst Through-Wand bis zur
  Far-Face → visuell verbunden, kein sichtbarer Joint
- Schicht ohne Material-Match in Through-Wand → standard T-Miter, stoppt
  am Near-Face

Beispiel "Aussenwand 30cm" (Beton/Daemmung/Putz) T auf gleicher Aussenwand:
alle 3 Schichten matchen → durchgehend gemerged.

Beispiel "Aussenwand 30cm" T auf "Beton solid 15cm":
- T-Stem Beton matched (Through-Solid hat Beton via Style) → durchstoesst
- T-Stem Daemmung/Putz: kein Match → stoppen am Through-Beton-Aussenkante

Implementation:
- _make_wand_layer_breps: per_layer_ext_start/end + per_layer_miter_start/end
- _t_junction_layer_overrides(doc, my_meta, through_meta, ...): baut die
  per-Layer Overrides via Material-Set-Lookup. Solid through wird via
  _wand_solid_material auf Style-Material aufgeloest.
- Regen-Pfad: t_junction_start/end speichern (oid+tan+dicke+ep+out_dir),
  vor _make_wand_layer_breps die Overrides bauen.
2026-05-31 12:07:32 +02:00
karim 3609236da9 dJoin: T-Join Ergaenzung — Endpunkt einer Wand mitten auf andere snappen
Bisher konnte dJoin nur L-Verbindungen herstellen (zwei Endpunkte zum
Schnittpunkt der verlaengerten Tangenten ziehen). Neu auch T-Verbindungen:

_t_join_attempt: pro Endpunkt-Kombination wird der naechste Punkt auf der
ANDEREN Curve gesucht. Wenn distance < 20cm UND nicht nahe deren Endpunkt
(= waere L-Sache) → snap diesen Endpunkt exakt auf die Curve. Die andere
Curve bleibt unveraendert (= Through-Wand stays).

_run: T-Join wird ZUERST probiert (spezifischer), L-Join als Fallback.

UX: User selektiert 2 Waende die fast aber nicht ganz verbinden →
Cmd+J (dJoin) → System erkennt T- oder L-Konfig und snappt entsprechend.
Predictable + intentional, kein auto-snap-Magic mehr.
2026-05-31 11:45:53 +02:00
karim e9e727c66f Auto-Snap on Move zurueckgenommen — zu magisch, User wollten Kontrolle
User-Feedback: bei vielen Waenden im Layout wurde unklar wann sich Wand-
Endpunkte automatisch verbinden und wann nicht. Auto-Snap auf Move/Mirror
machte das Verhalten unvorhersehbar.

Jetzt zurueck zum Standard-BIM-Workflow:
- Wand-Endpunkte verbinden sich NUR wenn User explizit Rhino's End/Mid-
  Snap nutzt (oder das L-Join in dJoin)
- T-Junction-Detection bleibt 1mm-tight → praezise Geometrie erforderlich
- Joint-Rolle (auto/durchgehend/anstossend) regelt weiterhin wer am
  geprueften T-Stoss durchgeht

Helper _snap_endpoint_to_other_wand_axis bleibt — fuer evtl. spaetere
explizite Connect-Befehle.
2026-05-31 11:42:53 +02:00
karim bc87ae1acc Per-Wand Joint-Rolle: explizit waehlen wer am T-Stoss durchgeht
Neues UserString-Feld 'dossier_wand_joint_rolle' per wand_axis:
- 'auto' (default): bisherige Logik. Bei beidseitig auto entscheidet die
  Style-Prio (hoehere = durchgehend)
- 'durchgehend': diese Wand ueberschreibt → ich gehe durch, T-Miter wird
  NICHT auf mich angewendet
- 'anstossend': diese Wand stoppt immer am Joint, auch wenn ich Prio-haerter waere

T-Junction-Detection in regen ruft jetzt _wand_should_apply_t_miter:
- my.rolle entscheidet zuerst
- bei my=auto: through.rolle entscheidet
- bei beide=auto: Prio-Vergleich (hoehere Prio = durchgehend)
- Default: T-Miter applied (= ich stoppe am Through)

Frontend: neue Dropdown 'Joint' in WallProperties zwischen Stil und Aufbau:
- Auto (Prio entscheidet)
- Durchgehend
- Anstossend

Backend-Pipeline: _attach_meta + _read_meta um wand_joint_rolle erweitert,
state-JSON sendet 'jointRolle', _update_wall_body handhabt jointRolle-Patch.
2026-05-31 08:04:17 +02:00
karim 0171785b42 dWall: Aufbau-Toggle (Solid/Mehrschichtig) + gefilterte Stil-Liste
Cluster-Dispatch: is_layered_meta Check zurueck — layered + non-linear (T,
Verzweigung) ist geometrisch sinnlos via per-Layer-Union (Schichten orthogonal
zwischen perpendikulaeren Waenden). Faellt zu Solo+Miter durch.

dWall-Prompt:
- Neue Option 'Aufbau' (Solid|Mehrschichtig)
- Stil-Liste gefiltert auf den gewaehlten Aufbau-Typ
- Beim Toggle: erster Style des neuen Typs uebernommen + dicke/referenz
- Default-Aufbau aus dem zuletzt verwendeten Style
2026-05-31 00:26:51 +02:00
karim f011e2ca94 Cascade-Cleanup: wand_centerline + wand_outline beim wand_axis-Delete mit-loeschen
Bug: nach _Delete einer Wand blieben die Hilfslinien (Centerline, Outline)
als Orphan-Curves stehen. _find_all_volumes filtert nur VOLUME_TYPES, in
denen Centerline/Outline nicht sind.

Fix: bei wand_axis-Delete-Event zusaetzlich alle wand_centerline/wand_outline
Curves mit derselben wall_id ID-Liste ergaenzen → nach 500ms cascade-delete
raeumt sie mit weg.

Layered Cluster + per-Layer BooleanUnion via _build_cluster_layered_breps
+ erweiterter _regen_cluster_anchor sind im selben commit drin (siehe
diff vor diesem Bugfix).
2026-05-31 00:03:10 +02:00
karim 5fdad504da Stale-Detection bei Project-Settings: nur betroffene Waende regenen
Bisher: bei jedem Project-Settings-Save wurden ALLE wand_axis im Doc regenert
(auch wenn nichts wand-relevantes geaendert wurde, z.B. nur ein Default-Wert
oder ein Library-Eintrag).

Jetzt: Diff der wand_styles + materials vor/nach Save. Sammle nur die Waende
die einen geaenderten Style nutzen ODER ein geaendertes Material (direkt via
Style oder als Schicht in layered Wand). Regen nur diese.

Plus: Joint-Cache-Batch-Flag waehrend des Regens setzen (war im sync-Pfad
sonst pro Regen invalidiert worden → unnoetiger Overhead).

Log zeigt jetzt z.B. "3 Waende regenert (1 Stile, 2 Materials geaendert)"
statt blind "N Waende regenert".
2026-05-30 23:45:45 +02:00
karim 0cc06364e8 Pre-warm OpenNURBS native libs am Plugin-Start
Beim install_listeners() werden dummy Curve.Offset, Extrusion.Create und
Brep.CreateBooleanUnion/Difference Aufrufe gemacht damit der lazy-loaded
native code geladen ist. Soll den First-Call-Lag bei der ersten echten
Wand-Operation reduzieren.

In der Praxis hilft das bei der Tech-Drawing-Failure nicht (das ist eine
Rhino-interne Limitation der Hidden-Line-Analyse die mit rapid brep
Delete+Add nicht klar kommt) — aber schadet auch nicht und kann andere
Cold-Start-Edge-Cases verbessern.
2026-05-30 23:39:59 +02:00
karim 5c7611ad40 Tech-Drawing-Fallback fix: batch-flag im sync Post-Cmd Regen
Bug: Beim Verbinden/Trennen zweier Waende via Move (= synchroner Replace-
Event-Pfad) lief jeder _regenerate_element-Call ohne den
_dossier_regen_batch_active Flag → jeder Regen invalidierte den Joint-Cache
neu (O(N²) Rebuilds) → Rhinos Technical-Drawing-Analyse choked →
"Switching all technical views to wireframe display".

Fix: Im post-Command Regen-Loop (line ~17285) den Flag setzen + Cache
einmal invalidieren bevor die affected_walls durchlaufen. Pattern analog
zur Idle-Batch-Logik die das schon hatte.

Outline + Centerline wieder aktiviert — waren nicht der Schuldige.
2026-05-30 23:16:09 +02:00
karim 66971eaa7a Wand-Outlines temporaer deaktiviert (Tech-Drawing-Konflikt)
Die Outline-Curves lagen exakt auf z=0 wie die unteren Brep-Edges. Rhinos
Technical-Drawing Hidden-Line-Analyse choked nach jedem Regen mit Duplikat-
Linien → wireframe-Fallback.

- _regen_wall_lines.outline branch auskommentiert
- _migrate_strip_wand_outlines_once raeumt existierende wand_outline-Curves
  beim naechsten Doc-Open weg
- Centerline (offset, dashed, locked) bleibt — kein Edge-Overlap

Wenn Outline-Visualisierung wieder gewollt: via Display-Conduit (visual-only,
keine Tech-Drawing-Interferenz).
2026-05-30 16:54:35 +02:00
karim 98824c1680 Wand-Stil im Elemente-Panel editierbar
Backend
- wand-State enthaelt jetzt styleId (aus _KEY_WAND_STYLE_ID)
- STATE-Payload sendet wandStyles (analog oeffStyles)
- _update_wall_body handhabt styleId-Patch: bei Stil-Wechsel uebernimmt die
  dicke aus dem Stil (wenn nicht explizit im selben Patch ueberschrieben);
  wand_style_id wird per _attach_meta auf die Achse persistiert

Frontend
- WallProperties bekommt wandStyles-Prop + zeigt Stil-Picker zwischen
  Geschoss und Aufbau (nur wenn Stile vorhanden)
- Dropdown: "kein Stil" + alle definierten Stile mit (dicke, prio)
- PropertiesView + ElementeApp + ElementePropertiesApp propagieren wandStyles
2026-05-30 16:48:54 +02:00
karim 080659ab95 Wand-Hilfslinien: Outline + Centerline auf allen Waenden, Petrol-Farbe, Pairing-Verfeinerung
Outline + Centerline
- Outline-Curves (geschlossenes Viereck) jetzt fuer ALLE Waende (auch
  Cluster/Chain-Member) — in_cluster-Flag suppressed Outline nicht mehr
- Mode = Normal (statt Locked) damit ObjectColor (Petrol #5fa896) durchschlaegt
  und doc.Objects.Replace bei Pure-Transform funktioniert
- Trade-off: User kann Hilfslinien greifen, aber jeder Axis-Regen schreibt sie
  neu (selbst-korrigierend)

Pure-Transform Sync
- wand_centerline + wand_outline werden im Pure-Transform-Pfad explizit
  mit-transformed (vorher nur SOURCE_TYPES + VOLUME_TYPES → Linien blieben
  in alter Position haengen)

Selection Pairing
- wand_axis zurueck in _PAIRED_SOURCE_TYPES → Achsen-Klick selektiert
  Outline + Centerline mit (alle "Referenzlinien" leuchten zusammen auf)
- _collect_partners special-case fuer wand_axis: NUR Hilfslinien als Partner,
  NICHT das Volume (sonst wuerde das ganze Brep mit-aufleuchten)
- wand_volume Pairing wie bisher: Volume-Klick → Achsen + Centerlines +
  Outlines aller Cluster-Members
2026-05-30 16:37:18 +02:00
karim 250853d7d0 Waende: Cluster-Boolean-Union + Click-UX + Outline/Centerline + Smart-L-Join
Geometrie
- _find_wall_cluster: BFS ueber alle same-material verbundenen Waende inkl.
  T-Junctions (Stem auf Through-Achse + Through-Wand-Mitte erkannt)
- _build_cluster_union_brep: per-Wand-Rect-Extrude + Boolean-Union zu einem
  einheitlichen Brep. Walls ueberlappen am Joint via Extension um
  nachbar_dicke/2 (Far-Face-Reach ohne Stummel)
- _regen_cluster_anchor: Anchor-Pattern wie Chain — anchor haelt cluster_brep
  + alle openings als BoolDiff cutouts pro Member-Wand
- _is_linear_chain: nur lineare 2-Wall-Endpoint-Sequenzen → existing
  Polyline-Extrude. Komplexe Cluster (verzweigt / mit T-Junction) → Union

Auto-T-Snap
- _t_snap_to_wand_axis mit zwei Pfaden:
  - Volume-Hit: IsPointInside (strict=False) auf wand_volume Brep → snap zur
    naechsten Cluster-Achse, unabhaengig von Wand-Dicke
  - Axis-Near: dynamische Toleranz max(15cm, dicke/2+10cm) → dicke Waende
    kriegen groessere Snap-Zone
- Endpunkt-Bias 10cm → naher Endpunkt gewinnt fuer saubere Corner
- Aufruf in _collect_wall_polyline + first-pt der Wand-Erstellung

Click-Verhalten
- _ClusterVolumeSelectHandler (MouseCallback): in Plan-View
  - Klick INNEN im Volume → naechste Achse selektieren
  - Klick auf Vertex (12 px) → Volume selektieren (Standard)
  - Klick auf Edge (8 px) → Volume selektieren (Standard)
  - Klick direkt auf Achse (5 px) → Rhino-Standard, Achse selektiert
- wand_axis aus _PAIRED_SOURCE_TYPES raus → Klick auf Linie selektiert NUR
  die Linie (kein Mit-Selektieren des Volumens)
- wand_volume bleibt in _PAIRED_VOLUME_TYPES + _collect_partners erweitert:
  Volume-Klick sammelt alle Cluster-Member-Achsen + Centerlines + Outlines
  → alle Referenzlinien leuchten bei Volume-Klick mit auf
- Auto-Group fuer alle Waende entfernt + Startup-Migration
  _migrate_strip_wall_auto_groups_once raeumt alte Memberships

Outline + Centerline
- _make_wall_centerline: parallele Achse-Offset bei ref != mid → Centerline
- _make_wall_outline: geschlossenes Viereck (linker + rechter Offset +
  perpendikulare Caps)
- _regen_wall_lines: LOCKED Curves auf Referenzen-Sublayer
  - Centerline (dashed): nur bei ref=left/right
  - Outline (solid): nur Solo-Waende (Cluster-Member ueber merged Brep)
- Beide mit dossier_type-Tag fuer Cleanup beim naechsten Regen

Smart-L-Join (dJoin)
- _l_join_attempt: 2 OFFENE Curves mit nicht-parallelen Tangenten →
  unendliche-Linien-Schnitt + Endpunkte beider Curves auf Schnittpunkt
  ersetzen (extend / shorten zu L)
- _walls_and_curves_from_sel: dedupliziert Selection via wall_id, akzeptiert
  axis+volume Auto-Group als 1 Wand
- Fallback zu Standard _Join wenn nicht passend

Performance
- Joint-Cache per-batch invalidieren statt per-regen (sticky
  _dossier_regen_batch_active)
2026-05-30 16:12:48 +02:00
karim 18d6d98e07 DOSSIER Multi-Phase: C#-Plugin + Yak + Wandstile + UX-Polish
- C#-Plugin "DOSSIER" mit 23 nativen Commands (dWall, dDoor, ..., dSection)
  - Native Command-Namen + Autocomplete + saubere History
  - Idle-Defer + RhinoCode-API → kein _-RunPythonScript-Echo
  - Yak-Paket via build.sh, Install in ~/Library/.../packages/8.0/
- Launcher (Tauri):
  - dossier_init Tauri-Command + Setup-Tab in Settings
  - Yak-Install + StartupCommands-XML + Window-Layout in einem Schritt
  - clean-rhino.sh fuer reproduzierbare Resets
  - check_dossier_initialized triggert Auto-Open-Setup beim ersten Start
- Wand-Architektur:
  - Chain-Logik DEAKTIVIERT → jede Wand baut eigenes Volume (individuell
    anwaehlbar, einzeln loeschbar)
  - Polyline-Wand: jedes Segment = eigene Wand
  - Smart-Split fuer wand_axis/decke/dach/raum/aussparung/traeger
  - Auto-Group axis+volume → kein ChooseOne-Dialog, Delete loescht beides
  - Stale-Mitre-Fix: Joint-Cache wird vor jedem Wand-Regen invalidiert
  - T-Junction-Tolerance auf 1mm (war 1cm, lieferte falsche T-Mitres)
- Wand-Stile:
  - Schema in dossier_project_settings.wand_styles (Material + Prio +
    Default-Dicke + Referenz, oder Layered mit Schichten)
  - dWall-Command Stil-Picker
  - ProjectSettingsDialog: Sidebar-Layout (Pill-Selection) +
    Wandstile-Tab mit Liste/Editor
  - _wand_chain_compat benutzt style_id
  - Prio-Dominanz: hoehere Prio gewinnt Eckverbindung, niedrigere wird
    T-mitered (siehe _resolve_corner_miter)
- Cmd+G fuer Group (Geschoss-Up auf Alias 'gu')
- Welcome + Cheatsheet borderless mit X/Back-Buttons
- BeginCommand-Hook fuer Gestaltung-Panel-Auto-Open
- panel_base: Python.NET-Enum-Fix fuer Material-Render
2026-05-30 12:46:53 +02:00
karim 7930705d01 L-Treppe: Schrittmass-Clamp bei Setzen + 3D-Podest Lage-aware
Bisher griff der Schrittmass-Clamp nur bei treppe_art=='gerade'.
Fuer L-Treppen jetzt:
- gp2 (Eck-Klick): clampt erste Lauf-Laenge auf [1-Stufe-min, (n-1)-Stufen-max]
- gp3 (End-Klick): schaetzt N1 aus erster Lauf-Laenge, clampt zweiten Lauf
  auf den S/A-konformen Bereich (mit cut_back kompensiert)

Volume-Fix _make_treppe_l_volume:
- cut_back am Eckpunkt war hardcoded half_b (= passt nur fuer Lage=mid).
  Fuer Lage=links/rechts wird die FULL breite cut-back gebraucht — sonst
  ueberlappen die Lauf-Volumen am Eckpunkt mit dem Podest falsch.
  Fix: cut_back = half_b if mid else breite.
2026-05-28 12:57:37 +02:00
karim d8966cc035 L-Treppe: 3-Punkt-Axis behalten + Referenz IMMER aussen
User-Feedback: L-Treppe bleibt 3-Punkt-Polyline (Start/Eck/End), Podest
ergibt sich aus dem Eckpunkt + Breite. Aber Referenz darf nie 'mid'
sein — sonst kollidieren die Laeufe am Eck. Constraint:
- _update_wall: bei treppe_art=='l' und tref=='mid' → 'links' erzwungen
- Frontend: REF_OPTIONS filtert 'mittig' raus wenn treppeArt=='l'

Dead-Code: _l_segments + _aussen_l_polygon + _lauflinie_l + _make_treppe_l_volume
behalten 4-Punkt-Handling als optionalen Pfad (gerade nicht erreicht weil
Creation immer 3-Punkt produziert) — schaden nicht, koennen spaeter
wieder aktiviert werden wenn Podest-als-Segment doch gewuenscht.

Schlafsession-Status: Trittmass-Lock + Lauflinie zentriert + Pfeile +
Cmd+Z + Pure-Transform fuer hidden Layer = alles in main.
2026-05-28 12:49:32 +02:00
karim e406e8d9b2 L-Aussen-Polygon: Z-Konsistenz fix + try/except defensive
_line_intersect_xy lieferte Z=0 was nicht zum Polygon-Z (=OKFF) passte,
PolylineCurve mit gemischten Z konnte fehlschlagen → 2D-Generierung
broken fuer L-Treppen. Fix: _at_z(p, fallback) Helper setzt Z explicit.
Plus try/except um die ganze Polygon-Konstruktion — Fallback auf
2-Rechteck-Variante bei Fehler.
2026-05-28 02:40:09 +02:00
karim bb64e4d41e Lock: Targets clearen bei Disable + Wendel-Sweep clamp auf 2π 2026-05-28 02:19:22 +02:00
karim 6060c74b17 Treppe L+Wendel: Lauflinie, Aussen-Polygon, Pfeil-voll, Lock + Cmd+Z
Cmd+Z:
- _update_wall wrapped in BeginUndoRecord/EndUndoRecord — sodass
  Property-Patches + Regen-Delete/Add als ein Undo-Schritt rueckgaengig

L-Treppe Aussenlinie:
- _aussen_l_polygon: sauberes 6-Punkt L-Polygon mit korrekt projizierten
  Ecken (Outer + Inner via Linien-Schnitt der mid-versetzten Seiten)
- _aussen_l: nutzt Polygon wenn kein Cut, faellt sonst zurueck auf
  per-Lauf Rechtecke mit Diagonal-Cut (wie bisher)

L-Treppe Lauflinie:
- ueber BEIDE Laeufe, mid-perp versetzt, Pfeil am Treppen-Ende
- Eck-Mitte als Linien-Schnitt der zwei versetzten Schaft-Linien →
  sauberer Übergang auch bei Lage=links/rechts (kein Versatz an der Ecke)
- 'voll'-Pfeil-Style mit wide-Offsets relativ zur Lauflinie

Wendel-Treppe:
- _lauflinie_wendel: 'voll'-Pfeil-Style mit r_inner/r_outer-Spitzen
  relativ zu r_mid (Radial-Offsets)

Trittmass-Lock auf alle Treppen-Arten:
- L: Beide Laeufe proportional skalieren (ratio = N*target_A / (L1+L2))
- Wendel: Sweep-Winkel anpassen (new_delta = sign × N*target_A/r_mid)
- Axis-Geometrie wird in-place via Replace ausgetauscht — Source moves
  fliessen in regulären Regen-Pfad ein
2026-05-28 02:16:57 +02:00
karim 970281e10a Treppen UX-Polish: Start-Z, Trittmass-Lock, Pfeil-Stile, Grips
Properties-Panel:
- Konsistentes 50px/1fr/14px Grid fuer alle Treppen-Rows
- Lage + Unten als Dropdown (lowercase Labels)
- Versatz: Dropdown (Geschoss-OKFF) oder eigenes Z mit Input + x-Button
- Ziel: gleich (Geschoss-Liste oder eigene Hoehe), Geschosse-Filter
  excludes das Start-Geschoss
- Start-Dropdown filtert auf okff < Ziel-Z (kein hoeheres Geschoss als
  Start waehlbar, beachtet auch eigene-Hoehe-Ziel)
- Stufen: Dropdown 2-40 (statt freie Eingabe), mit Lock nur S-konforme
  Werte
- Dropdowns nutzen System-Font (statt mono)
- Ausgrenzung 'Aussenlinie'-Toggle (Aussenlinie immer an)
- Pfeil-Style-Dropdown unter Lauflinie-Checkbox: klassisch / gefuellt
  (Solid-Hatch) / breit / voll (Spitzen bis Treppen-Aussenkanten)

Backend Treppe:
- Start-Z-Override via treppe_uk_over (m Offset relativ zu Geschoss-OKFF)
- 2D-Symbol bleibt auf OKFF (egal ob Versatz) — Symbol klebt am Boden
- Lauflinie-Schaft auf visuellen Treppen-Mittelpunkt versetzt
  (bei Lage=links/rechts), nicht mehr auf der Referenz-Achse
- Trittmass-Lock: treppe_lock_s + target_S/A. Beim Aktivieren werden
  S+A als Ziel gespeichert. Bei H-Change wird N=round(H/target_S)
  recomputed + Axis-Laenge auf N*target_A angepasst (gerade Treppen)
- Bruchsymbol-Toggle aus: ganze Treppe ungesplittet zeichnen
  (eff_cut_h=0 → kein Lower/Upper-Split)
- Treppen-Endpunkt-Marker (treppe_grips.py) — gruene Punkte an Start/
  Ende der Lauflinie, beachtet treppe_art (Wendel: poly[1]/poly[2])

Verdoppelungs-Fix:
- _find_target_volume skipt treppe_2d_symbol explicit (sind 2D-Curves,
  kein Volume). Vorher konnte Replace(curve, brep) fehlschlagen → das
  echte Treppen-Brep blieb stehen + neues kam dazu → Duplikat
- _find_objects_by_wall_id mit HiddenObjects+LockedObjects-Iterator,
  findet auch Objs auf hidden 3D-Layer
- Anti-Dup-Cleanup in _regenerate_element: bei mehreren treppe_volume
  mit gleicher element_id → alle ausser dem ersten loeschen

State-Pipeline:
- geschosse-Liste enthaelt jetzt okff+hoehe (fuer Frontend-Constraints)
- Treppe-State neu: ukOver, arrowStyle, lockS, targetS, targetA
- Hidden-Source-Fallback in _send_state findet auch Treppen wenn der
  3D-Layer aus ist (sodass Properties-Panel angezeigt wird)

Dimensionen-Panel:
- on_select + on_idle skippen waehrend Partnership-Cascade oder
  User-Transform — kein Flicker mehr beim Drag

Andere:
- Wand-Polyline-Vertex-Grips (alle Vertices, nicht nur Enden)
- PopupMenu unterstuetzt _divider + checked-Items
- TREPPEN/RAEUME Layer-Migration auf Capital-Case
- selection-partnership tolerant: hidden Source wird trotzdem in die
  Selection genommen (sonst kann Drag nicht durch Pure-Transform)
2026-05-28 02:09:38 +02:00
karim bcf7d557b1 Treppen 2D-Plansymbol + Pure-Transform fuer hidden Layer
Frontend:
- 2D-Plansymbol pro Treppe (Tritte/Lauflinie/Aussenlinie/Bruchsymbol)
  mit per-Treppe-Toggles in Properties-Panel
- 'Obere Stufen gestrichelt'-Toggle splittet Tritte/Aussenlinie an
  Schnittebene; Lauflinie hat zwei Pfeile bei Bruch
- Wand-Polyline-Grips fuer alle Vertices (nicht nur Enden)
- PopupMenu unterstuetzt Divider + Checkbox-Items

Backend:
- Eigener Layer 41_Treppen_2D fuer Plansymbol, Layer-Default schwarz
- Aussenlinie-Polygone folgen der Bruch-Diagonale (kein Versatz mehr)
- Linetype-Fallback laedt Dashed bei Bedarf nach
- Tritten-immer-an (Toggle entfernt), Z auf Geschoss-OKFF
- TREPPEN/RAEUME Layer-Migration auf Capital-Case (Treppen/Raeume)
- Selection-Partnership: treppe_2d_symbol pairs in axis + volume

Pure-Transform fuer Treppen-Move:
- treppe_2d_symbol + treppe_volume in VOLUME_TYPES → cascade-Support
- Phase 1.5 Volume-only-Detection: wenn Source unbewegt aber Volumes
  uniform translated → synthetisiere canonical aus Avg-Delta der
  bewegten Volumes (unbewegte rausgefiltert sonst Verzerrung)
- Hidden-inclusive ObjectEnumerator in Snapshot + Apply-Loop damit
  hidden treppe_axis auf 40_Treppen mit-transformiert wird
- Properties-Fallback im _send_state findet hidden Sources via
  expliziter Iteration → Panel zeigt Treppe auch bei 3D-Layer aus
- Dimensionen-Panel skipt on_select/idle waehrend UT_ACTIVE oder
  Partnership-Cascade → keine Flicker beim Drag mehr
2026-05-28 00:41:05 +02:00
karim d9589e99f5 Cleanup: gitignore Rhino-Testdateien, Layout-Skip-Versuch zurueck (WebView-Bug) 2026-05-27 20:56:22 +02:00
karim f8d1cfe3fe Splash: borderless+transparent+launcher-dedup, idle-dispatch hide 2026-05-27 20:09:09 +02:00
karim 264327432d Splash + Layout-Skip-Revert
User-Bug: Layout-Skip-Optimierung war zu aggressiv — Mac Rhino haelt die
Panel-Anordnung zwischen Sessions doch nicht im internen State, also
wurden Panels falsch platziert nach Quick-Restart. Skip-Logik raus, der
~3s _-WindowLayout-Apply laeuft wieder jedes Mal. Das ist OK weil der
Splash diese Wartezeit jetzt optisch abdeckt.

Splash verbessert:
- _try_borderless_mac(): direkter NSWindow-Zugriff via Eto.ControlObject
  + ObjC-Methoden (setStyleMask_, setOpaque_, setHasShadow_,
  setBackgroundColor_, setMovableByWindowBackground_) — produziert
  echten borderless Mac-Look wie der Launcher-Splash
- Form-BackgroundColor auf transparent damit das gradient des WebView-
  HTMLs durchscheint (rounded petrol gradient mit weichem Verlauf)
- WebView selber transparenter Hintergrund
- Closeable/Minimizable/Maximizable/Resizable alle False
- [SPLASH] visible log fuer Debug-Sichtbarkeit
2026-05-27 19:36:09 +02:00