AGPL-3.0 Dual-Lizenz + Pill-Stil-UI + Section-Style-Overhaul + Plan-Mode-Template
Lizenz: - AGPL-3.0 LICENSE-File im Repo-Root (GNU Volltext) - SPDX-Header + Copyright in allen Source-Files (Python/JSX/JS/Rust) - license-Feld in package.json + Cargo.toml - About-App komplett neu: Dual-Lizenz-Block (AGPL + Commercial), openbureau-Branding, Version-Pills, made-in-Switzerland-Footer UI-Restyle (3 Wellen) — alle Dialoge + Satellites + Panel-Sidebars auf gemeinsamen Pill-Stil aus BarControls (BarToggle/BarButton/BarCombo): - Welle 1: GeschossDialog/Settings, AusschnittSettings, LayoutDialog - Welle 2: ConfirmDeleteEbene, Kamera, MasseSettings, Osm, Swisstopo, TextEditor, AusschnittLayerDialog, LayerCombinations - Welle 3: LayoutsApp, MassstabApp, WerkzeugeApp, OverridesApp, ZeichnungsebenenApp; Werkzeuge mit ElementeApp-PillGroup-Layout GeschossDialog Header-Refactor: +Geschoss/+Zeichnung in Toolbar oben, move-Pfeile-Spalte breiter (kein Overlap mit G-Haken) Ausschnitte Rows als Pills, kein Outer-Border ums Suchfeld Section-Style komplett neu (gestaltung.py + GestaltungApp.jsx): - ObjectSectionAttributesSource.FromObject (richtiger Enum-Name fuer Mac) - HatchPatternPrintColor + BoundaryPrintColor mit-setzen (Display = Print) - BoundaryColor nur bei explizitem User-Override, sonst Rhino-Default - background_color_hex Parameter (BackgroundFillMode=SolidColor) - Readback aus GetCustomSectionStyle statt direkt aus Attributes - UI: Schnittkante > Section Style > Solid-Fill mit proper SectionHead - 'Boundary' (3D Pen) -> 'Background' weil sich's wie Section-Hintergrund verhaelt Plan-Mode 'Dossier Plan' via Template: - rhino/templates/dossier_plan.ini wird direkt geladen - Fallback auf Technical-Clone + ini-Patch wenn Template fehlt - Auto-Cleanup von Orphan-Modes vor Import (Name- oder Guid-Match) - ClipSectionUsage=1 + TechnicalMask=15 als bekannte Soll-Werte - Bei Template-Pfad keine ini-Patches (1:1 wie User exportiert) - Sanity-Print listet alle registrierten Modes nach Anlegen Bridge-Unification: 4 Settings-Apps (Ebenen/Project/Geschoss*Dialog) benutzen jetzt chunkende send() statt eigene bridgeSend ohne Chunk- Logik -> grosse Payloads (Hatch-Refs etc.) kommen nicht mehr truncated bei Python an (loeste 'JSON-Fehler char 990'-Regression in Ebenen- Settings) Library-Imports robust: 'import library' jetzt Top-Level in elemente.py + rhinopanel.py (statt Lazy in Methoden) -> 'No module named library'- Crashes weg auch wenn sys.path zwischendurch resettet wird Tools fuer Display-Mode-Maintenance: - _clean_display_modes.py (loescht alle Custom-Modes, Built-ins bleiben) - _inspect_plan_mode.py / _inspect_obj_section.py / _inspect_obj_boundary.py (Diagnose-Skripte fuer SectionStyle-Property-Reverse-Engineering) - _reset_rhino_settings.sh (Backup + Nuke der Rhino-Settings als letzte Bastion gegen korrupte Display-Modes)
This commit is contained in:
@@ -0,0 +1,66 @@
|
||||
#! python3
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
# Copyright (C) 2026 Karim Gabriele Varano
|
||||
"""Loescht ALLE Custom-Display-Modes (User-erstellte) — laesst die Rhino-
|
||||
Built-ins (Wireframe, Shaded, Rendered, Ghosted, XRay, Technical, Artistic,
|
||||
Pen, Monochrome, Arctic, Raytraced) in Ruhe.
|
||||
|
||||
Loescht auch Orphan-Modes ohne Namen (die manchmal bei abgebrochenen
|
||||
Imports hierbleiben und Rhino zum Crash bringen wenn man sie anklickt).
|
||||
|
||||
Vorgehen:
|
||||
_RunPythonScript /Users/karim/STUDIO/DOSSIER/rhino/_clean_display_modes.py
|
||||
"""
|
||||
from Rhino.Display import DisplayModeDescription
|
||||
|
||||
BUILTIN_NAMES = {
|
||||
"Wireframe", "Shaded", "Rendered", "Ghosted",
|
||||
"X-Ray", "XRay", "X Ray",
|
||||
"Technical", "Artistic", "Pen", "Monochrome",
|
||||
"Arctic", "Raytraced",
|
||||
}
|
||||
|
||||
deleted = []
|
||||
kept = []
|
||||
errors = []
|
||||
|
||||
for dm in list(DisplayModeDescription.GetDisplayModes()):
|
||||
name_en = name_local = None
|
||||
try: name_en = dm.EnglishName
|
||||
except Exception: pass
|
||||
try: name_local = dm.LocalName
|
||||
except Exception: pass
|
||||
name_display = name_en or name_local or "(Orphan, kein Name)"
|
||||
is_builtin = (name_en in BUILTIN_NAMES) or (name_local in BUILTIN_NAMES)
|
||||
|
||||
if is_builtin:
|
||||
kept.append(name_display)
|
||||
continue
|
||||
|
||||
# Custom oder Orphan → loeschen
|
||||
try:
|
||||
dm_id = dm.Id
|
||||
ok = DisplayModeDescription.DeleteDisplayMode(dm_id)
|
||||
if ok:
|
||||
deleted.append("{} ({})".format(name_display, dm_id))
|
||||
else:
|
||||
errors.append("{} → DeleteDisplayMode returned False".format(name_display))
|
||||
except Exception as ex:
|
||||
errors.append("{} → {}".format(name_display, ex))
|
||||
|
||||
print("[CLEAN] Display-Modes gesaeubert.")
|
||||
print("[CLEAN] Built-ins behalten ({}):".format(len(kept)))
|
||||
for n in kept:
|
||||
print(" ✓ {}".format(n))
|
||||
print("")
|
||||
print("[CLEAN] Geloescht ({}):".format(len(deleted)))
|
||||
for n in deleted:
|
||||
print(" × {}".format(n))
|
||||
if errors:
|
||||
print("")
|
||||
print("[CLEAN] Fehler ({}):".format(len(errors)))
|
||||
for e in errors:
|
||||
print(" ! {}".format(e))
|
||||
print("")
|
||||
print("[CLEAN] Fertig. Jetzt _reset_panels.py laufen lassen damit der")
|
||||
print("[CLEAN] Plugin den 'Dossier Plan' aus dem Template neu importiert.")
|
||||
@@ -0,0 +1,67 @@
|
||||
#! python3
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
# Copyright (C) 2026 Karim Gabriele Varano
|
||||
"""Boundary/Hatch-Inspector — zeigt was Rhino setzt wenn du via
|
||||
Properties-Panel die Section-Boundary aenderst.
|
||||
|
||||
Vorgehen:
|
||||
1. Objekt selektieren
|
||||
2. In Rhinos Properties → Section Style → Custom → Boundary verstellen
|
||||
(Farbe ändern, Visible toggeln, Width setzen)
|
||||
3. _RunPythonScript /Users/karim/STUDIO/DOSSIER/rhino/_inspect_obj_boundary.py
|
||||
4. Output schicken — speziell die Boundary-Properties
|
||||
"""
|
||||
import Rhino
|
||||
|
||||
doc = Rhino.RhinoDoc.ActiveDoc
|
||||
objs = list(doc.Objects.GetSelectedObjects(False, False))
|
||||
if not objs:
|
||||
print("[INSPECT] Bitte Objekt selektieren")
|
||||
else:
|
||||
obj = objs[0]
|
||||
a = obj.Attributes
|
||||
print("[INSPECT] Object {}".format(str(obj.Id)[:8]))
|
||||
print("")
|
||||
print("=== Attributes.SectionAttributesSource ===")
|
||||
try: print(" =", a.SectionAttributesSource)
|
||||
except Exception as ex: print(" err:", ex)
|
||||
print("")
|
||||
print("=== Attributes.GetCustomSectionStyle() — alle Props ===")
|
||||
try:
|
||||
css = a.GetCustomSectionStyle()
|
||||
if css is None:
|
||||
print(" None (kein Custom-SectionStyle)")
|
||||
else:
|
||||
for n in sorted(dir(css)):
|
||||
if n.startswith("_"): continue
|
||||
try:
|
||||
v = getattr(css, n)
|
||||
if callable(v): continue
|
||||
sv = str(v)
|
||||
if len(sv) > 80: sv = sv[:77] + "..."
|
||||
print(" {} = {}".format(n, sv))
|
||||
except Exception as ex:
|
||||
print(" {} <unreadable: {}>".format(n, ex))
|
||||
except Exception as ex:
|
||||
print(" err:", ex)
|
||||
print("")
|
||||
print("=== Layer.GetCustomSectionStyle (Layer-Default) ===")
|
||||
try:
|
||||
lyr = doc.Layers[a.LayerIndex]
|
||||
print(" Layer:", lyr.FullPath)
|
||||
if hasattr(lyr, "GetCustomSectionStyle"):
|
||||
css = lyr.GetCustomSectionStyle()
|
||||
if css is None:
|
||||
print(" Layer hat KEIN Custom-SectionStyle")
|
||||
else:
|
||||
for n in sorted(dir(css)):
|
||||
if n.startswith("_"): continue
|
||||
try:
|
||||
v = getattr(css, n)
|
||||
if callable(v): continue
|
||||
sv = str(v)
|
||||
if len(sv) > 80: sv = sv[:77] + "..."
|
||||
print(" {} = {}".format(n, sv))
|
||||
except Exception: pass
|
||||
except Exception as ex:
|
||||
print(" err:", ex)
|
||||
@@ -0,0 +1,112 @@
|
||||
#! python3
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
# Copyright (C) 2026 Karim Gabriele Varano
|
||||
"""Dumpt ALLE Section-/Hatch-relevanten Properties des selektierten Objekts.
|
||||
So sehen wir was Rhino's eigene Section-Style-UI tatsaechlich setzt vs.
|
||||
was unser Plugin-Code setzt.
|
||||
|
||||
Vorgehen:
|
||||
1. Ein 3D-Objekt selektieren (Wand, Box, ...)
|
||||
2. In Rhinos Properties-Panel manuell SectionStyle → Custom mit spezifischen
|
||||
Werten setzen (z.B. Pattern Color=Gruen, Pattern Rotation=20, Pattern
|
||||
Scale=2.4, Boundary Color=Rot, Boundary Width Scale=6) → Apply
|
||||
3. _RunPythonScript /Users/karim/STUDIO/DOSSIER/rhino/_inspect_obj_section.py
|
||||
4. Output an Claude
|
||||
"""
|
||||
import Rhino
|
||||
|
||||
|
||||
def _fmt(v):
|
||||
if v is None: return "None"
|
||||
s = str(v)
|
||||
if len(s) > 80: s = s[:77] + "..."
|
||||
return s
|
||||
|
||||
|
||||
def _dump_group(css, prefix, title):
|
||||
"""Dumpt Properties auf css deren Name mit `prefix` (case-insens) anfaengt."""
|
||||
print("--- {} ---".format(title))
|
||||
p_lower = prefix.lower()
|
||||
found = False
|
||||
for n in sorted(dir(css)):
|
||||
if n.startswith("_"): continue
|
||||
if p_lower not in n.lower(): continue
|
||||
try:
|
||||
v = getattr(css, n)
|
||||
if callable(v): continue
|
||||
found = True
|
||||
print(" {:32s} = {}".format(n, _fmt(v)))
|
||||
except Exception as ex:
|
||||
print(" {:32s} = <unreadable: {}>".format(n, ex))
|
||||
if not found:
|
||||
print(" (nichts)")
|
||||
|
||||
|
||||
doc = Rhino.RhinoDoc.ActiveDoc
|
||||
objs = list(doc.Objects.GetSelectedObjects(False, False))
|
||||
if not objs:
|
||||
print("[INSPECT] Bitte ein Objekt selektieren")
|
||||
else:
|
||||
obj = objs[0]
|
||||
a = obj.Attributes
|
||||
print("[INSPECT] Object: {} (Id={})".format(type(obj).__name__, obj.Id))
|
||||
|
||||
# SectionAttributesSource (FromLayer / FromObject)
|
||||
print("")
|
||||
print("=== Attributes ===")
|
||||
try:
|
||||
print(" SectionAttributesSource =", a.SectionAttributesSource)
|
||||
except Exception as ex:
|
||||
print(" SectionAttributesSource err:", ex)
|
||||
try:
|
||||
print(" HatchBackgroundFillColor =", a.HatchBackgroundFillColor)
|
||||
except Exception: pass
|
||||
try:
|
||||
print(" HatchBoundaryVisible =", a.HatchBoundaryVisible)
|
||||
except Exception: pass
|
||||
|
||||
# Custom SectionStyle aus Object
|
||||
print("")
|
||||
print("=== Object.GetCustomSectionStyle() ===")
|
||||
css = None
|
||||
if hasattr(a, "GetCustomSectionStyle"):
|
||||
try:
|
||||
css = a.GetCustomSectionStyle()
|
||||
except Exception as ex:
|
||||
print(" err:", ex)
|
||||
|
||||
if css is None:
|
||||
print(" None (kein Custom-SectionStyle gesetzt)")
|
||||
else:
|
||||
print(" Type:", type(css).__name__)
|
||||
print("")
|
||||
# Gruppierte Property-Dumps damit Mapping zu Rhino-UI klar wird
|
||||
_dump_group(css, "Hatch", "Hatch (Pattern, Color, Scale, Rotation)")
|
||||
print("")
|
||||
_dump_group(css, "Boundary", "Boundary (Visible, Color, Width)")
|
||||
print("")
|
||||
_dump_group(css, "Background", "Background (FillColor, FillMode)")
|
||||
print("")
|
||||
# Section-spezifisch (SectionFillRule etc.)
|
||||
print("--- Misc Section ---")
|
||||
for n in ("SectionFillRule", "Name", "Id", "HasUserData", "Index"):
|
||||
if hasattr(css, n):
|
||||
try: print(" {:32s} = {}".format(n, _fmt(getattr(css, n))))
|
||||
except Exception: pass
|
||||
|
||||
# Layer-Default SectionStyle als Vergleich
|
||||
print("")
|
||||
print("=== Layer.GetCustomSectionStyle (Layer-Default) ===")
|
||||
try:
|
||||
lyr = doc.Layers[a.LayerIndex]
|
||||
print(" Layer:", lyr.FullPath, "Color:", lyr.Color)
|
||||
if hasattr(lyr, "GetCustomSectionStyle"):
|
||||
l_css = lyr.GetCustomSectionStyle()
|
||||
if l_css is None:
|
||||
print(" Layer hat KEIN Custom-SectionStyle")
|
||||
else:
|
||||
_dump_group(l_css, "Hatch", "Layer.Hatch")
|
||||
_dump_group(l_css, "Boundary", "Layer.Boundary")
|
||||
_dump_group(l_css, "Background", "Layer.Background")
|
||||
except Exception as ex:
|
||||
print(" err:", ex)
|
||||
@@ -0,0 +1,96 @@
|
||||
#! python3
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
# Copyright (C) 2026 Karim Gabriele Varano
|
||||
"""One-Shot-Diagnose: dumpt alle Properties + Werte des 'Dossier Plan'
|
||||
Display-Modes und exportiert ihn als ini neben dem Skript.
|
||||
|
||||
Vorgehen:
|
||||
1. In Rhinos Display-Mode-Editor: 'Show HiddenLines' AUS schalten +
|
||||
Apply
|
||||
2. _RunPythonScript /Users/karim/STUDIO/DOSSIER/rhino/_inspect_plan_mode.py
|
||||
3. Resultat: zeigt alle Hidden/Tangent/Silhouette-Properties +
|
||||
/tmp/dossier_plan_inspect.ini
|
||||
|
||||
So koennen wir sehen welche Property-Namen Mac Rhino tatsaechlich hat.
|
||||
"""
|
||||
import os
|
||||
from Rhino.Display import DisplayModeDescription
|
||||
|
||||
target_name = "Dossier Plan"
|
||||
dmd = None
|
||||
for dm in DisplayModeDescription.GetDisplayModes():
|
||||
if dm.EnglishName == target_name or dm.LocalName == target_name:
|
||||
dmd = dm; break
|
||||
|
||||
if dmd is None:
|
||||
print("[INSPECT] 'Dossier Plan' nicht gefunden")
|
||||
else:
|
||||
attrs = dmd.DisplayAttributes
|
||||
print("[INSPECT] Mode gefunden: {} (Id={})".format(dmd.EnglishName, dmd.Id))
|
||||
print("")
|
||||
print("=== ALLE DisplayAttributes Properties mit Werten ===")
|
||||
for n in sorted(dir(attrs)):
|
||||
if n.startswith("_"): continue
|
||||
try:
|
||||
v = getattr(attrs, n)
|
||||
if callable(v): continue
|
||||
sv = str(v)
|
||||
if len(sv) > 80: sv = sv[:77] + "..."
|
||||
print(" {} = {}".format(n, sv))
|
||||
except Exception as ex:
|
||||
print(" {} = <unreadable: {}>".format(n, ex))
|
||||
|
||||
print("")
|
||||
print("=== Sub-Objekt Properties (ALLE) ===")
|
||||
# Erst alle Sub-Objekt-Properties autodetect (anything mit "+" im String)
|
||||
sub_names = set()
|
||||
for n in dir(attrs):
|
||||
if n.startswith("_"): continue
|
||||
try:
|
||||
v = getattr(attrs, n)
|
||||
if callable(v): continue
|
||||
if "DisplayPipelineAttributes+" in str(v):
|
||||
sub_names.add(n)
|
||||
except Exception: pass
|
||||
# Plus die expliziten Kandidaten
|
||||
for hard in ("CurveSettings", "ObjectSettings", "ShadingSettings",
|
||||
"MeshSpecificAttributes", "SubObjectDisplayMode",
|
||||
"ViewSpecificAttributes"):
|
||||
if hasattr(attrs, hard): sub_names.add(hard)
|
||||
|
||||
for sub_name in sorted(sub_names):
|
||||
try:
|
||||
sub = getattr(attrs, sub_name)
|
||||
print(" --- {} ---".format(sub_name))
|
||||
for n in sorted(dir(sub)):
|
||||
if n.startswith("_"): continue
|
||||
try:
|
||||
v = getattr(sub, n)
|
||||
if callable(v): continue
|
||||
sv = str(v)
|
||||
if len(sv) > 80: sv = sv[:77] + "..."
|
||||
print(" {} = {}".format(n, sv))
|
||||
except Exception as ex:
|
||||
print(" {} = <unreadable: {}>".format(n, ex))
|
||||
except Exception as ex:
|
||||
print(" {} couldn't be inspected: {}".format(sub_name, ex))
|
||||
|
||||
print("")
|
||||
print("=== ini-Export ===")
|
||||
# In den Desktop schreiben damit der User die Datei einfach manuell
|
||||
# oeffnen + mir den Inhalt schicken kann (in /tmp gehts manchmal verloren).
|
||||
ini_path = os.path.expanduser("~/Desktop/dossier_plan_inspect.ini")
|
||||
try:
|
||||
ok = DisplayModeDescription.ExportToFile(dmd, ini_path)
|
||||
print(" Export OK: {} → {}".format(ok, ini_path))
|
||||
if ok and os.path.exists(ini_path):
|
||||
with open(ini_path, "r", encoding="utf-8", errors="ignore") as f:
|
||||
content = f.read()
|
||||
print(" ini-Inhalt ({} chars) — siehe Datei auf dem Desktop.".format(len(content)))
|
||||
# Falls Rhinos Log das Print durchlaesst, hier ueberhaupt rein
|
||||
print("===INI-START===")
|
||||
for line in content.split("\n"):
|
||||
print(line)
|
||||
print("===INI-END===")
|
||||
except Exception as ex:
|
||||
print(" Export-Fehler:", ex)
|
||||
@@ -1,5 +1,7 @@
|
||||
#! python 3
|
||||
# -*- coding: utf-8 -*-
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
# Copyright (C) 2026 Karim Gabriele Varano
|
||||
"""Hilfsscript: alle Dossier-Panel-Registrierungs-Flags clearen + Module
|
||||
neu laden. Nuetzlich nach Icon-/Layout-Aenderungen. ABER: Rhinos
|
||||
Panel-Manager cached die Icon-Bindung pro GUID — fuer NEUE Icons hilft
|
||||
|
||||
Executable
+52
@@ -0,0 +1,52 @@
|
||||
#!/usr/bin/env bash
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
# Copyright (C) 2026 Karim Gabriele Varano
|
||||
#
|
||||
# Nuke + Reset Rhino-8 Settings (Mac). Backupt vorher in einen Ordner mit
|
||||
# Zeitstempel — verlorene Settings koennen daraus rekonstruiert werden.
|
||||
#
|
||||
# Was geht VERLOREN:
|
||||
# - Alle Custom-Display-Modes (Dossier Plan, DOSSIER2D, etc.)
|
||||
# - Window-Layouts, Toolbar-Customizations
|
||||
# - Custom-Keyboard-Shortcuts
|
||||
# - Tab-Panel-Positions
|
||||
#
|
||||
# Was bleibt:
|
||||
# - Lizenz (License Manager Ordner wird NICHT angefasst)
|
||||
# - .3dm Templates
|
||||
# - Scripts unter scripts/
|
||||
# - Plugin-Einstellungen (in Plug-ins/-Unterordnern)
|
||||
#
|
||||
# Vorgehen:
|
||||
# 1. Rhino komplett quitten (Cmd+Q)
|
||||
# 2. ./rhino/_reset_rhino_settings.sh
|
||||
# 3. Rhino neu starten
|
||||
# 4. _RunPythonScript .../_reset_panels.py → Plan-Mode aus Template
|
||||
|
||||
set -e
|
||||
|
||||
SETTINGS_DIR="$HOME/Library/Application Support/McNeel/Rhinoceros/8.0/settings"
|
||||
TIMESTAMP="$(date +%Y%m%d-%H%M%S)"
|
||||
BACKUP="$SETTINGS_DIR.backup-$TIMESTAMP"
|
||||
|
||||
if [ ! -d "$SETTINGS_DIR" ]; then
|
||||
echo "[RESET] Settings-Ordner nicht gefunden: $SETTINGS_DIR"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check ob Rhino läuft
|
||||
if pgrep -x "Rhinoceros" > /dev/null; then
|
||||
echo "[RESET] FEHLER: Rhino läuft noch. Bitte erst Cmd+Q drücken."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "[RESET] Backup → $BACKUP"
|
||||
mv "$SETTINGS_DIR" "$BACKUP"
|
||||
echo "[RESET] Settings nun zurückgesetzt."
|
||||
echo "[RESET] Beim nächsten Rhino-Start werden Defaults regeneriert."
|
||||
echo "[RESET] Backup liegt unter: $BACKUP"
|
||||
echo ""
|
||||
echo "[RESET] Nächste Schritte:"
|
||||
echo " 1. Rhino starten"
|
||||
echo " 2. _RunPythonScript /Users/karim/STUDIO/DOSSIER/rhino/_reset_panels.py"
|
||||
echo " → Dossier-Plan wird aus Template neu erstellt"
|
||||
@@ -1,5 +1,7 @@
|
||||
#! python 3
|
||||
# -*- coding: utf-8 -*-
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
# Copyright (C) 2026 Karim Gabriele Varano
|
||||
"""
|
||||
about.py
|
||||
About-Dialog als Eto-Form + WebView. Vom DOSSIER-Logo-Klick in der
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#! python 3
|
||||
# -*- coding: utf-8 -*-
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
# Copyright (C) 2026 Karim Gabriele Varano
|
||||
"""
|
||||
ausschnitte.py
|
||||
AUSSCHNITTE-Panel: speichert Viewport-Ausschnitte mit Kamera, Display-Mode,
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
#! python 3
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
# Copyright (C) 2026 Karim Gabriele Varano
|
||||
"""
|
||||
clean.py
|
||||
Loescht ALLE sticky-Eintraege der DOSSIER-Panels, damit der naechste
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
#! python 3
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
# Copyright (C) 2026 Karim Gabriele Varano
|
||||
"""
|
||||
clean_layers.py
|
||||
Loescht Rhino-Standardlayer (Default, Layer 01-05 usw.)
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#! python 3
|
||||
# -*- coding: utf-8 -*-
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
# Copyright (C) 2026 Karim Gabriele Varano
|
||||
"""
|
||||
dimensionen.py
|
||||
DIMENSIONEN-Panel: Object Info Palette nach Vectorworks-Vorbild.
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#! python 3
|
||||
# -*- coding: utf-8 -*-
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
# Copyright (C) 2026 Karim Gabriele Varano
|
||||
"""
|
||||
elemente.py
|
||||
ELEMENTE-Panel: Smart Architektur-Elemente.
|
||||
@@ -22,6 +24,7 @@ if _HERE not in sys.path:
|
||||
|
||||
import panel_base
|
||||
import mass_style
|
||||
import library
|
||||
|
||||
PANEL_GUID_STR = "5a6b7c8d-9e0f-4a1b-c2d3-e4f5061728e0"
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#! python 3
|
||||
# -*- coding: utf-8 -*-
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
# Copyright (C) 2026 Karim Gabriele Varano
|
||||
"""
|
||||
elemente_properties.py
|
||||
Properties-Satellite-Window. Zeigt die Property-Forms (WallProperties,
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#! python 3
|
||||
# -*- coding: utf-8 -*-
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
# Copyright (C) 2026 Karim Gabriele Varano
|
||||
"""
|
||||
elemente_uebersicht.py
|
||||
BIM-artiger Project Browser: alle Smart-Elemente in einem Tree
|
||||
|
||||
+275
-69
@@ -1,5 +1,7 @@
|
||||
#! python 3
|
||||
# -*- coding: utf-8 -*-
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
# Copyright (C) 2026 Karim Gabriele Varano
|
||||
"""
|
||||
gestaltung.py
|
||||
GESTALTUNG-Panel: Attribute der Selektion (Farbe, Stiftdicke, Linientyp,
|
||||
@@ -860,6 +862,11 @@ def _selection_summary(doc):
|
||||
sec_patterns = set()
|
||||
sec_scales = set()
|
||||
sec_rots = set()
|
||||
# Boundary-Subsettings (Schnittkante)
|
||||
sec_bdy_visible = set()
|
||||
sec_bdy_colors = set()
|
||||
sec_bdy_widths = set()
|
||||
sec_bg_colors = set() # Background-Fill (None wenn FillMode != SolidColor)
|
||||
# Geometry-Kind-Klassifikation: 'curve' (closed planar 2D), 'curveOpen'
|
||||
# (offene Kurve), '3d' (Brep/Extrusion/Mesh — Volumen mit Schnittflaeche),
|
||||
# 'other'. Aggregiert ueber alle Selektions-Objekte zu kind=
|
||||
@@ -926,52 +933,93 @@ def _selection_summary(doc):
|
||||
else:
|
||||
geometry_kinds.add('other')
|
||||
|
||||
# Section-Style aus Object-Attributes lesen (Rhino 8, mit Fallbacks
|
||||
# fuer Property-Namen die je nach Build variieren).
|
||||
# Section-Style aus Object-Attributes lesen — Rhino 8 Mac packt die
|
||||
# Settings in ein SectionStyle-Objekt (via GetCustomSectionStyle),
|
||||
# NICHT in direkte Attribute-Properties wie das alte API.
|
||||
if is_3d:
|
||||
src_attr = None
|
||||
try:
|
||||
src_attr = getattr(a, "SectionAttributesSource", None)
|
||||
except Exception: src_attr = None
|
||||
src_is_object = False
|
||||
if src_attr is not None:
|
||||
try:
|
||||
src_name = str(src_attr).lower()
|
||||
if "layer" in src_name: sec_sources.add("layer")
|
||||
elif "object" in src_name: sec_sources.add("object")
|
||||
if "object" in src_name:
|
||||
sec_sources.add("object"); src_is_object = True
|
||||
elif "layer" in src_name:
|
||||
sec_sources.add("layer")
|
||||
except Exception: pass
|
||||
# Hatch-Index/Scale/Rotation
|
||||
hidx = None
|
||||
for n in ("SectionHatchIndex", "HatchPatternIndex"):
|
||||
if hasattr(a, n):
|
||||
|
||||
# Wenn Source=FromObject: aus dem Custom-SectionStyle lesen.
|
||||
# Sonst (FromLayer): vom Layer.GetCustomSectionStyle() lesen damit
|
||||
# die UI auch im Layer-Modus den effektiven Hatch zeigt.
|
||||
css = None
|
||||
try:
|
||||
if src_is_object and hasattr(a, "GetCustomSectionStyle"):
|
||||
css = a.GetCustomSectionStyle()
|
||||
if css is None:
|
||||
# Fallback: Layer-SectionStyle
|
||||
try:
|
||||
v = getattr(a, n)
|
||||
if v is not None: hidx = int(v); break
|
||||
lyr = doc.Layers[obj.Attributes.LayerIndex]
|
||||
if hasattr(lyr, "GetCustomSectionStyle"):
|
||||
css = lyr.GetCustomSectionStyle()
|
||||
except Exception: pass
|
||||
if hidx is not None and hidx >= 0 and hidx < doc.HatchPatterns.Count:
|
||||
sec_enabled.add(True)
|
||||
try: sec_patterns.add(doc.HatchPatterns[hidx].Name)
|
||||
except Exception: pass
|
||||
elif hidx == -1:
|
||||
sec_enabled.add(False)
|
||||
for n, target in (
|
||||
(("SectionHatchScale", "HatchPatternScale"), sec_scales),
|
||||
(("SectionHatchRotation", "HatchPatternRotation"), sec_rots),
|
||||
):
|
||||
for nn in n:
|
||||
if hasattr(a, nn):
|
||||
except Exception: pass
|
||||
|
||||
if css is not None:
|
||||
# HatchIndex
|
||||
hidx = None
|
||||
for n in ("HatchIndex", "HatchPatternIndex"):
|
||||
if hasattr(css, n):
|
||||
try:
|
||||
v = float(getattr(a, nn))
|
||||
target.add(round(v, 4)
|
||||
if target is sec_scales
|
||||
else round(math.degrees(v), 2))
|
||||
break
|
||||
v = getattr(css, n)
|
||||
if v is not None: hidx = int(v); break
|
||||
except Exception: pass
|
||||
for n in ("SectionFillColor", "SectionHatchColor", "HatchColor"):
|
||||
if hasattr(a, n):
|
||||
try:
|
||||
c = _color_to_hex(getattr(a, n))
|
||||
if c: sec_colors.add(c); break
|
||||
if hidx is not None and hidx >= 0 and hidx < doc.HatchPatterns.Count:
|
||||
sec_enabled.add(True)
|
||||
try: sec_patterns.add(doc.HatchPatterns[hidx].Name)
|
||||
except Exception: pass
|
||||
elif hidx == -1:
|
||||
sec_enabled.add(False)
|
||||
# Scale
|
||||
for n in ("HatchScale", "HatchPatternScale"):
|
||||
if hasattr(css, n):
|
||||
try: sec_scales.add(round(float(getattr(css, n)), 4)); break
|
||||
except Exception: pass
|
||||
# Rotation (rad → deg)
|
||||
for n in ("HatchRotationRadians", "HatchRotation", "HatchAngle"):
|
||||
if hasattr(css, n):
|
||||
try: sec_rots.add(round(math.degrees(float(getattr(css, n))), 2)); break
|
||||
except Exception: pass
|
||||
# Color
|
||||
for n in ("HatchPatternColor", "HatchColor", "FillColor"):
|
||||
if hasattr(css, n):
|
||||
try:
|
||||
c = _color_to_hex(getattr(css, n))
|
||||
if c: sec_colors.add(c); break
|
||||
except Exception: pass
|
||||
# Boundary-Settings auslesen
|
||||
if hasattr(css, "BoundaryVisible"):
|
||||
try: sec_bdy_visible.add(bool(css.BoundaryVisible))
|
||||
except Exception: pass
|
||||
if hasattr(css, "BoundaryColor"):
|
||||
try:
|
||||
c = _color_to_hex(css.BoundaryColor)
|
||||
if c: sec_bdy_colors.add(c)
|
||||
except Exception: pass
|
||||
if hasattr(css, "BoundaryWidthScale"):
|
||||
try: sec_bdy_widths.add(round(float(css.BoundaryWidthScale), 2))
|
||||
except Exception: pass
|
||||
# Background nur lesen wenn FillMode != Viewport (sonst transparent)
|
||||
try:
|
||||
mode = getattr(css, "BackgroundFillMode", None)
|
||||
if mode is not None and "viewport" not in str(mode).lower():
|
||||
c = _color_to_hex(css.BackgroundFillColor)
|
||||
if c: sec_bg_colors.add(c)
|
||||
except Exception: pass
|
||||
else:
|
||||
sec_enabled.add(False)
|
||||
|
||||
# Fuellung
|
||||
if _is_closed_planar_curve(obj.Geometry):
|
||||
@@ -1072,6 +1120,10 @@ def _selection_summary(doc):
|
||||
"sectionPattern": single(sec_patterns),
|
||||
"sectionScale": single(sec_scales),
|
||||
"sectionRotation": single(sec_rots),
|
||||
"sectionBoundaryVisible": single(sec_bdy_visible),
|
||||
"sectionBoundaryColor": single(sec_bdy_colors),
|
||||
"sectionBoundaryWidthScale": single(sec_bdy_widths),
|
||||
"sectionBackgroundColor": single(sec_bg_colors),
|
||||
# geometryKind: 'curve' | 'curveOpen' | '3d' | 'mixed' | 'other'
|
||||
"geometryKind": (
|
||||
'mixed' if len(geometry_kinds & {'curve', 'curveOpen', '3d'}) > 1
|
||||
@@ -1159,6 +1211,10 @@ class GestaltungBridge(panel_base.BaseBridge):
|
||||
p.get("pattern"),
|
||||
p.get("scale"),
|
||||
p.get("rotation"),
|
||||
boundary_visible=p.get("boundaryVisible", True),
|
||||
boundary_width_scale=p.get("boundaryWidthScale", 1.0),
|
||||
boundary_color_hex=p.get("boundaryColor"),
|
||||
background_color_hex=p.get("backgroundColor"),
|
||||
)
|
||||
|
||||
def _send_selection(self):
|
||||
@@ -1478,71 +1534,221 @@ class GestaltungBridge(panel_base.BaseBridge):
|
||||
# ---- SectionStyle (per-Object, Rhino 8) -------------------------------
|
||||
|
||||
def _set_section_style(self, enabled, source, color_hex,
|
||||
pattern_name=None, scale=None, rotation_deg=None):
|
||||
"""Setzt Per-Object SectionStyle-Properties auf die selektierten
|
||||
3D-Objekte. Rhino 8 expone diese Properties auf ObjectAttributes
|
||||
unter teils variierenden Namen — wir versuchen die bekannten."""
|
||||
pattern_name=None, scale=None, rotation_deg=None,
|
||||
boundary_visible=True, boundary_width_scale=1.0,
|
||||
boundary_color_hex=None,
|
||||
background_color_hex=None):
|
||||
"""Setzt einen Per-Object SectionStyle ueber die Rhino-8 API
|
||||
(analog zu Layer.SetCustomSectionStyle). source='layer' entfernt
|
||||
den Custom-Style → Layer-Default greift. source='object' setzt
|
||||
einen frischen SectionStyle pro Objekt."""
|
||||
doc = Rhino.RhinoDoc.ActiveDoc
|
||||
objs = list(doc.Objects.GetSelectedObjects(False, False))
|
||||
is_layer_source = (source == "layer")
|
||||
print("[GESTALTUNG] _set_section_style: source={} enabled={} pattern={}".format(
|
||||
source, enabled, pattern_name))
|
||||
|
||||
# SectionStyle-Klasse + Source-Enum holen.
|
||||
# Mac Rhino 8: Enum heisst ObjectSectionAttributesSource (mit
|
||||
# "Object"-Prefix) — per Inspektion verifiziert. Ohne explizites
|
||||
# Setzen von Attributes.SectionAttributesSource = FromObject wird
|
||||
# der Custom-SectionStyle zwar persistiert, aber visuell ignoriert
|
||||
# weil der Default-Wert FromLayer bleibt.
|
||||
try:
|
||||
SS = Rhino.DocObjects.SectionStyle
|
||||
except Exception as ex:
|
||||
print("[GESTALTUNG] SectionStyle-Klasse fehlt:", ex)
|
||||
return
|
||||
SAS = None
|
||||
for cls_name in ("ObjectSectionAttributesSource", "SectionAttributesSource"):
|
||||
try:
|
||||
SAS = getattr(Rhino.DocObjects, cls_name)
|
||||
if SAS is not None:
|
||||
print("[GESTALTUNG] Source-Enum: Rhino.DocObjects.{}".format(cls_name))
|
||||
break
|
||||
except Exception: pass
|
||||
if SAS is None:
|
||||
print("[GESTALTUNG] WARNUNG: kein Source-Enum gefunden")
|
||||
if objs and not getattr(self, "_ss_api_logged", False):
|
||||
o = objs[0]
|
||||
for meth in ("SetCustomSectionStyle", "RemoveCustomSectionStyle",
|
||||
"HasCustomSectionStyle", "GetCustomSectionStyle"):
|
||||
print("[GESTALTUNG] RhinoObject.{}: {}".format(
|
||||
meth, hasattr(o, meth)))
|
||||
try:
|
||||
a = o.Attributes
|
||||
for meth in ("SetCustomSectionStyle", "RemoveCustomSectionStyle"):
|
||||
print("[GESTALTUNG] Attributes.{}: {}".format(
|
||||
meth, hasattr(a, meth)))
|
||||
except Exception: pass
|
||||
self._ss_api_logged = True
|
||||
|
||||
# Hatch-Pattern-Index ermitteln
|
||||
pat_idx = -1
|
||||
if pattern_name and pattern_name not in ("None", ""):
|
||||
try: pat_idx = doc.HatchPatterns.Find(pattern_name, True)
|
||||
except Exception: pat_idx = -1
|
||||
if pat_idx < 0 and pattern_name not in ("None", ""):
|
||||
try: pat_idx = doc.HatchPatterns.Find("Solid", True)
|
||||
except Exception: pat_idx = -1
|
||||
|
||||
col = _hex_to_color(color_hex) if color_hex else None
|
||||
scale_v = float(scale) if scale is not None else 1.0
|
||||
rot_rad = math.radians(float(rotation_deg)) if rotation_deg is not None else 0.0
|
||||
|
||||
def _try_set_attr(a, names, value):
|
||||
def _try_set(target, names, value):
|
||||
for n in names:
|
||||
if hasattr(a, n):
|
||||
if hasattr(target, n):
|
||||
try:
|
||||
setattr(a, n, value)
|
||||
setattr(target, n, value)
|
||||
return n
|
||||
except Exception: pass
|
||||
return None
|
||||
|
||||
def _apply_custom(obj, style):
|
||||
"""Setzt Custom-SectionStyle + schaltet SectionAttributesSource
|
||||
auf FromObject. Beides muss persistiert sein damit Rhino den
|
||||
Custom-Style auch tatsaechlich rendert."""
|
||||
try:
|
||||
a = obj.Attributes.Duplicate()
|
||||
if hasattr(a, "SetCustomSectionStyle"):
|
||||
a.SetCustomSectionStyle(style)
|
||||
# KRITISCH: Source auf FromObject — ohne das ignoriert Rhino
|
||||
# den Custom-Style und nutzt weiter den Layer-Style.
|
||||
if SAS is not None and hasattr(a, "SectionAttributesSource"):
|
||||
try:
|
||||
a.SectionAttributesSource = SAS.FromObject
|
||||
except Exception as ex:
|
||||
print("[GESTALTUNG] set Source.FromObject fail:", ex)
|
||||
ok_modify = doc.Objects.ModifyAttributes(obj, a, True)
|
||||
_log_post(obj, "Attributes.SetCustomSectionStyle+FromObject",
|
||||
ok_modify)
|
||||
return "Attributes.SetCustomSectionStyle"
|
||||
except Exception as ex:
|
||||
print("[GESTALTUNG] attr.SetCustomSectionStyle fail:", ex)
|
||||
return None
|
||||
|
||||
def _log_post(obj, via, ok_modify=None):
|
||||
"""Nach SetCustom: pruefen ob Rhino den Style auch behalten hat."""
|
||||
try:
|
||||
ob = doc.Objects.FindId(obj.Id) if hasattr(obj, "Id") else obj
|
||||
if ob is None: ob = obj
|
||||
a = ob.Attributes
|
||||
src = "n/a"
|
||||
if hasattr(a, "SectionAttributesSource"):
|
||||
try: src = str(a.SectionAttributesSource)
|
||||
except Exception: pass
|
||||
got = None
|
||||
if hasattr(a, "GetCustomSectionStyle"):
|
||||
try:
|
||||
css = a.GetCustomSectionStyle()
|
||||
if css is not None:
|
||||
got = "HatchIndex={}".format(getattr(css, "HatchIndex", "?"))
|
||||
except Exception as ex:
|
||||
got = "get-err: {}".format(ex)
|
||||
print("[GESTALTUNG] post via {} (modify_ok={}): Source={} Got={}".format(
|
||||
via, ok_modify, src, got))
|
||||
except Exception as ex:
|
||||
print("[GESTALTUNG] post-check:", ex)
|
||||
|
||||
def _remove_custom(obj):
|
||||
"""Entfernt Custom-SectionStyle + schaltet Source auf FromLayer
|
||||
zurueck. Damit greift wieder der Layer-Default-SectionStyle."""
|
||||
try:
|
||||
a = obj.Attributes.Duplicate()
|
||||
if hasattr(a, "RemoveCustomSectionStyle"):
|
||||
a.RemoveCustomSectionStyle()
|
||||
if SAS is not None and hasattr(a, "SectionAttributesSource"):
|
||||
try:
|
||||
a.SectionAttributesSource = SAS.FromLayer
|
||||
except Exception as ex:
|
||||
print("[GESTALTUNG] set Source.FromLayer fail:", ex)
|
||||
doc.Objects.ModifyAttributes(obj, a, True)
|
||||
return "Attributes.RemoveCustomSectionStyle+FromLayer"
|
||||
except Exception as ex:
|
||||
print("[GESTALTUNG] attr.RemoveCustomSectionStyle fail:", ex)
|
||||
return None
|
||||
|
||||
n_ok = 0
|
||||
for obj in objs:
|
||||
geom = obj.Geometry
|
||||
if not isinstance(geom, (rg.Brep, rg.Extrusion, rg.Mesh, rg.SubD)):
|
||||
continue
|
||||
a = obj.Attributes.Duplicate()
|
||||
|
||||
# Source: FromLayer vs FromObject — verschiedene Enum-Namen
|
||||
if is_layer_source:
|
||||
# Versuche SectionAttributesSource auf FromLayer
|
||||
_try_set_attr(a, ("SectionAttributesSource",),
|
||||
Rhino.DocObjects.SectionAttributesSource.FromLayer
|
||||
if hasattr(Rhino.DocObjects, "SectionAttributesSource") else 0)
|
||||
# Custom entfernen → Layer-SectionStyle wird wirksam
|
||||
via = _remove_custom(obj)
|
||||
print("[GESTALTUNG] obj {}: remove custom via {}".format(
|
||||
str(obj.Id)[:8], via))
|
||||
if via: n_ok += 1
|
||||
continue
|
||||
# Default-Farbe = Layer-Farbe wenn der User keine Override-Farbe
|
||||
# gewaehlt hat. Section-Style hat keine "ByLayer"-Source-Option,
|
||||
# also setzen wir die echte Layer-Farbe explizit auf den Style.
|
||||
obj_col = col
|
||||
obj_col_src = "user-override" if col is not None else "n/a"
|
||||
if obj_col is None:
|
||||
try:
|
||||
lyr = doc.Layers[obj.Attributes.LayerIndex]
|
||||
obj_col = lyr.Color
|
||||
obj_col_src = "layer({})".format(lyr.FullPath)
|
||||
except Exception as ex:
|
||||
obj_col = None
|
||||
obj_col_src = "fail:{}".format(ex)
|
||||
print("[GESTALTUNG] obj {} color src={} val={}".format(
|
||||
str(obj.Id)[:8], obj_col_src, obj_col))
|
||||
# Per-Object: frischen SectionStyle bauen wie in layer_builder
|
||||
style = SS()
|
||||
if pattern_name == "None" or not enabled:
|
||||
_try_set(style, ("HatchIndex", "HatchPatternIndex"), -1)
|
||||
else:
|
||||
_try_set_attr(a, ("SectionAttributesSource",),
|
||||
Rhino.DocObjects.SectionAttributesSource.FromObject
|
||||
if hasattr(Rhino.DocObjects, "SectionAttributesSource") else 1)
|
||||
|
||||
if not enabled or pattern_name == "None":
|
||||
# Hatch-Index auf -1 = keine Fuellung
|
||||
_try_set_attr(a, ("SectionHatchIndex", "HatchPatternIndex"), -1)
|
||||
else:
|
||||
if pat_idx >= 0:
|
||||
_try_set_attr(a, ("SectionHatchIndex", "HatchPatternIndex"), pat_idx)
|
||||
_try_set_attr(a, ("SectionHatchScale", "HatchPatternScale"), scale_v)
|
||||
_try_set_attr(a, ("SectionHatchRotation", "HatchPatternRotation"), rot_rad)
|
||||
if col is not None:
|
||||
_try_set_attr(a, ("SectionFillColor", "SectionHatchColor",
|
||||
"HatchColor"), col)
|
||||
|
||||
if pat_idx >= 0:
|
||||
_try_set(style, ("HatchIndex", "HatchPatternIndex"), pat_idx)
|
||||
_try_set(style, ("HatchScale", "HatchPatternScale"), scale_v)
|
||||
_try_set(style, ("HatchRotationRadians", "HatchRotation",
|
||||
"HatchAngle"), rot_rad)
|
||||
if obj_col is not None:
|
||||
# Display- UND Print-Color setzen damit beide matchen
|
||||
_try_set(style, ("HatchPatternColor", "HatchColor",
|
||||
"FillColor"), obj_col)
|
||||
_try_set(style, ("HatchPatternPrintColor",), obj_col)
|
||||
_try_set(style, ("BoundaryVisible",), bool(boundary_visible))
|
||||
try:
|
||||
doc.Objects.ModifyAttributes(obj, a, True)
|
||||
n_ok += 1
|
||||
except Exception as ex:
|
||||
print("[GESTALTUNG] SectionStyle ModifyAttributes:", ex)
|
||||
_try_set(style, ("BoundaryWidthScale",),
|
||||
float(boundary_width_scale))
|
||||
except Exception: pass
|
||||
# Boundary-Farbe: NUR setzen wenn User explizit eine Override-Farbe
|
||||
# gewaehlt hat. Sonst lassen wir Rhinos Default (schwarz) greifen
|
||||
# damit Boundary visuell unterscheidbar von der Hatch-Pattern-Farbe
|
||||
# bleibt. (Sonst wuerde HatchPatternColor=Layer + BoundaryColor=Layer
|
||||
# die Schnittflaeche als einfarbige Flaeche erscheinen lassen.)
|
||||
bcol = None
|
||||
if boundary_color_hex:
|
||||
try: bcol = _hex_to_color(boundary_color_hex)
|
||||
except Exception: bcol = None
|
||||
if bcol is not None:
|
||||
_try_set(style, ("BoundaryColor",), bcol)
|
||||
_try_set(style, ("BoundaryPrintColor",), bcol)
|
||||
# Background-Fill: User-Override (hex) → SolidColor-Mode + Farbe
|
||||
# Sonst Transparent (Viewport-Mode, Default)
|
||||
if background_color_hex:
|
||||
try:
|
||||
bgcol = _hex_to_color(background_color_hex)
|
||||
except Exception:
|
||||
bgcol = None
|
||||
if bgcol is not None:
|
||||
_try_set(style, ("BackgroundFillColor",), bgcol)
|
||||
_try_set(style, ("BackgroundFillPrintColor",), bgcol)
|
||||
# FillMode auf SolidColor via Enum (mehrere Namens-Varianten)
|
||||
for en_cls in ("SectionBackgroundFillMode",
|
||||
"BackgroundFillMode"):
|
||||
try:
|
||||
E = getattr(Rhino.DocObjects, en_cls, None)
|
||||
if E is not None:
|
||||
_try_set(style, ("BackgroundFillMode",),
|
||||
E.SolidColor)
|
||||
break
|
||||
except Exception: pass
|
||||
via = _apply_custom(obj, style)
|
||||
print("[GESTALTUNG] obj {}: set custom via {} (hatch_idx={})".format(
|
||||
str(obj.Id)[:8], via, pat_idx))
|
||||
if via: n_ok += 1
|
||||
|
||||
print("[GESTALTUNG] SectionStyle auf {} Objekt(e) appliziert".format(n_ok))
|
||||
doc.Views.Redraw()
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
#! python 3
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
# Copyright (C) 2026 Karim Gabriele Varano
|
||||
"""
|
||||
inspect_section.py
|
||||
Schreibt ALLE Eigenschaften der SectionStyle der aktuellen Ebene ins Log,
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#! python 3
|
||||
# -*- coding: utf-8 -*-
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
# Copyright (C) 2026 Karim Gabriele Varano
|
||||
"""
|
||||
kamera.py
|
||||
Kamera-Panel: liest/setzt Viewport-Kamera (Position, Target, Projektion,
|
||||
|
||||
+25
-19
@@ -1,5 +1,7 @@
|
||||
#! python 3
|
||||
# -*- coding: utf-8 -*-
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
# Copyright (C) 2026 Karim Gabriele Varano
|
||||
"""
|
||||
layer_builder.py
|
||||
Layer-Struktur:
|
||||
@@ -157,6 +159,9 @@ def _apply_section_style(doc, layer, section_cfg, layer_color):
|
||||
pat = (section_cfg.get("hatchPattern") or "None").strip()
|
||||
show = bool(section_cfg.get("boundaryShow", True))
|
||||
diag = "[SS:{}]".format(layer.Name if layer else "?")
|
||||
# DEBUG: zeigt was an section_cfg ankommt (zur Diagnose des Hatch-Bugs)
|
||||
print(diag, "section_cfg.hatchPattern='{}' scale={} rot={}".format(
|
||||
pat, section_cfg.get("hatchScale"), section_cfg.get("hatchRotation")))
|
||||
|
||||
# Wenn weder Hatch noch Boundary → Custom-Style entfernen
|
||||
if pat == "None" and not show:
|
||||
@@ -194,17 +199,20 @@ def _apply_section_style(doc, layer, section_cfg, layer_color):
|
||||
rot_deg = float(section_cfg.get("hatchRotation") or 0)
|
||||
_try_set(style, ("HatchRotation", "HatchAngle"), math.radians(rot_deg))
|
||||
|
||||
# Hatch-Color: explizit ColorFromObject setzen damit der eigene Wert greift
|
||||
# Hatch-Color: explizit setzen — wenn User keine Override-Farbe angegeben
|
||||
# hat, nehmen wir die Layer-Farbe als Default (sonst rendert Rhino sonst
|
||||
# schwarz). Section-Style hat keine ByLayer-Option, also Farbwert
|
||||
# explizit reinkopieren.
|
||||
hatch_color = section_cfg.get("hatchColor")
|
||||
if hatch_color:
|
||||
col = _color(hatch_color)
|
||||
set_color = _try_set(style, ("HatchColor", "FillColor"), col)
|
||||
# Source auf "FromObject" — sonst nutzt Rhino den Layer-Color
|
||||
src_from_object = _enum_int(
|
||||
(("DocObjects", "ObjectColorSource"), "ColorFromObject"))
|
||||
if src_from_object is not None:
|
||||
_try_set(style, ("HatchColorSource", "FillColorSource"), src_from_object)
|
||||
print(diag, "HatchColor via {}".format(set_color))
|
||||
elif layer_color is not None:
|
||||
col = _color(layer_color) if isinstance(layer_color, str) else layer_color
|
||||
else:
|
||||
col = None
|
||||
if col is not None:
|
||||
set_color = _try_set(style, ("HatchPatternColor", "HatchColor", "FillColor"), col)
|
||||
print(diag, "HatchColor via {} (default=layer)".format(set_color))
|
||||
|
||||
# Background (viewport=0/transparent vs object=1)
|
||||
bg = section_cfg.get("background")
|
||||
@@ -226,20 +234,18 @@ def _apply_section_style(doc, layer, section_cfg, layer_color):
|
||||
print(diag, "BoundaryVisible={} via {}".format(show, set_show))
|
||||
|
||||
if show:
|
||||
# Boundary-Color: setze Color + Source auf FromObject
|
||||
# Boundary-Color: User-Override oder Layer-Farbe als Default
|
||||
bc = section_cfg.get("boundaryColor")
|
||||
if bc:
|
||||
col = _color(bc)
|
||||
bcol = _color(bc)
|
||||
elif layer_color is not None:
|
||||
bcol = _color(layer_color) if isinstance(layer_color, str) else layer_color
|
||||
else:
|
||||
bcol = None
|
||||
if bcol is not None:
|
||||
set_to = _try_set(style,
|
||||
("BoundaryColor", "OutlineColor", "EdgeColor"), col)
|
||||
src_from_object = _enum_int(
|
||||
(("DocObjects", "ObjectColorSource"), "ColorFromObject"))
|
||||
if src_from_object is not None:
|
||||
_try_set(style,
|
||||
("BoundaryColorSource", "OutlineColorSource",
|
||||
"EdgeColorSource"),
|
||||
src_from_object)
|
||||
print(diag, "BoundaryColor={} via {}".format(bc, set_to))
|
||||
("BoundaryColor", "OutlineColor", "EdgeColor"), bcol)
|
||||
print(diag, "BoundaryColor via {} (default=layer)".format(set_to))
|
||||
|
||||
# Width-Scale auf PlotWeight uebertragen (RW8 hat keine WidthScale direkt;
|
||||
# alternative Property-Namen probieren)
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#! python 3
|
||||
# -*- coding: utf-8 -*-
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
# Copyright (C) 2026 Karim Gabriele Varano
|
||||
"""
|
||||
layouts.py
|
||||
LAYOUTS-Panel: Layout-Pages erstellen + Details mit Ausschnitten bestuecken.
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#! python3
|
||||
# -*- coding: utf-8 -*-
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
# Copyright (C) 2026 Karim Gabriele Varano
|
||||
"""
|
||||
library.py — Dossier-Library (Phase A: lokal, read-only)
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#! python 3
|
||||
# -*- coding: utf-8 -*-
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
# Copyright (C) 2026 Karim Gabriele Varano
|
||||
"""
|
||||
mass_style.py
|
||||
Globale Mass-Stil-Presets fuer Dossier — speichert pro Dokument benannte
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#! python 3
|
||||
# -*- coding: utf-8 -*-
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
# Copyright (C) 2026 Karim Gabriele Varano
|
||||
"""
|
||||
masse_settings.py
|
||||
Satellite-Fenster fuer das Bearbeiten der Masse-Presets
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#! python 3
|
||||
# -*- coding: utf-8 -*-
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
# Copyright (C) 2026 Karim Gabriele Varano
|
||||
"""
|
||||
massstab.py
|
||||
MASSSTAB-Panel: zeigt + setzt den aktuellen Massstab des aktiven Viewports.
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#! python 3
|
||||
# -*- coding: utf-8 -*-
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
# Copyright (C) 2026 Karim Gabriele Varano
|
||||
"""
|
||||
oberleiste.py
|
||||
OBERLEISTE-Panel: horizontale Top-Bar mit Architektur-Kontext-Controls.
|
||||
@@ -183,6 +185,363 @@ def _import_display_modes(paths):
|
||||
return count
|
||||
|
||||
|
||||
# Fest-Guid fuer 'Dossier Plan' damit Re-Imports denselben Slot
|
||||
# wiederverwenden statt Duplikate zu erzeugen.
|
||||
_DOSSIER_PLAN_GUID = "d0551e72-7e72-4170-b1a4-d0551e72d055"
|
||||
|
||||
def _apply_dossier_plan_attrs(dmd):
|
||||
"""Wendet die Dossier-Plan-Visual-Settings auf einen DisplayMode an.
|
||||
Wird sowohl beim Erstanlegen als auch bei jedem Reload aufgerufen —
|
||||
so propagieren Attribut-Aenderungen aus dem Code automatisch."""
|
||||
try:
|
||||
from Rhino.Display import DisplayModeDescription
|
||||
except Exception:
|
||||
return
|
||||
attrs = dmd.DisplayAttributes
|
||||
# DEBUG: einmal pro Session alle relevanten Property-Namen loggen damit
|
||||
# wir sehen welche tatsaechlich existieren (Mac vs Win Rhino unterscheidet
|
||||
# sich) — sonst werden Set-Attempts still verschluckt.
|
||||
if not getattr(_apply_dossier_plan_attrs, "_props_logged", False):
|
||||
try:
|
||||
relevant = sorted([n for n in dir(attrs)
|
||||
if not n.startswith("_")
|
||||
and ("idden" in n or "ngent" in n or "ilho" in n
|
||||
or "ire" in n or "soc" in n or "dge" in n
|
||||
or "ech" in n or "hade" in n or "ection" in n)])
|
||||
print("[OBERLEISTE] Plan-Mode Attrs-Inventar:", ", ".join(relevant))
|
||||
# Sub-Objekt-Settings sind in Rhino 8 oft eigene Klassen
|
||||
for sub in ("CurveSettings", "ObjectSettings", "ShadingSettings",
|
||||
"MeshSpecificAttributes"):
|
||||
if hasattr(attrs, sub):
|
||||
obj = getattr(attrs, sub)
|
||||
sub_props = sorted([n for n in dir(obj)
|
||||
if not n.startswith("_")
|
||||
and ("idden" in n or "ngent" in n
|
||||
or "soc" in n or "ire" in n
|
||||
or "dge" in n)])
|
||||
if sub_props:
|
||||
print("[OBERLEISTE] Plan-Mode {}:".format(sub),
|
||||
", ".join(sub_props))
|
||||
except Exception as ex:
|
||||
print("[OBERLEISTE] Plan-Mode inspect:", ex)
|
||||
_apply_dossier_plan_attrs._props_logged = True
|
||||
# Surfaces gefuellt + weiss + kein Shading
|
||||
try: attrs.ShadingEnabled = False
|
||||
except Exception: pass
|
||||
try: import System.Drawing as SD
|
||||
except Exception: SD = None
|
||||
if SD:
|
||||
try:
|
||||
white = SD.Color.FromArgb(255, 255, 255, 255)
|
||||
try: attrs.ShadeSurfaceColor = white
|
||||
except Exception: pass
|
||||
try: attrs.BackgroundColor = white
|
||||
except Exception: pass
|
||||
try: attrs.BackgroundColorTop = white
|
||||
except Exception: pass
|
||||
try: attrs.BackgroundColorBottom = white
|
||||
except Exception: pass
|
||||
except Exception: pass
|
||||
# Wires + Isocurves AUS — sonst Plan-Linien-Noise.
|
||||
# Property-Namen wie sie auf Mac Rhino 8 tatsaechlich existieren
|
||||
# (per Inspektion verifiziert — frueher hatten wir falsche Schreibweisen
|
||||
# die das try/except still verschluckt hat).
|
||||
try: attrs.ShowIsoCurves = False # NICHT ShowIsocurves!
|
||||
except Exception: pass
|
||||
try: attrs.SurfaceIsoThicknessUsed = False
|
||||
except Exception: pass
|
||||
try: attrs.SurfaceIsoColorsUsed = False
|
||||
except Exception: pass
|
||||
try: attrs.ShowTangentEdges = False
|
||||
except Exception: pass
|
||||
try: attrs.ShowTangentSeams = False
|
||||
except Exception: pass
|
||||
try: attrs.ShowSurfaceEdges = True
|
||||
except Exception: pass
|
||||
try: attrs.ShowSurfaceEdge = True # Singular existiert auch
|
||||
except Exception: pass
|
||||
# Mesh-Wires AUS — die liegen auf dem Sub-Objekt MeshSpecificAttributes,
|
||||
# nicht direkt auf attrs. Das sind in Top-Views haeufig die "feinen
|
||||
# Punkte" auf Brep-Wand-Volumen (Rhino mesht intern fuer Display).
|
||||
try:
|
||||
if hasattr(attrs, "MeshSpecificAttributes"):
|
||||
attrs.MeshSpecificAttributes.ShowMeshWires = False
|
||||
attrs.MeshSpecificAttributes.ShowMeshVertices = False
|
||||
except Exception as ex:
|
||||
print("[OBERLEISTE] Plan-Mode MeshSpecificAttributes:", ex)
|
||||
# Section-Styles MUESSEN aktiv sein damit Custom-Section-Styles
|
||||
# (per-Layer oder per-Object) tatsaechlich gerendert werden. Default
|
||||
# ist False — d.h. Section-Hatches werden zugewiesen aber nicht angezeigt.
|
||||
# Diagnose: vorher + nachher loggen weil auf Mac Rhino set+UpdateDisplayMode
|
||||
# diesen Wert manchmal nicht persistiert (wir patchen darum auch direkt
|
||||
# die ini beim Erstanlegen).
|
||||
pre_uss = None
|
||||
try: pre_uss = bool(attrs.UseSectionStyles)
|
||||
except Exception: pass
|
||||
try: attrs.UseSectionStyles = True
|
||||
except Exception as ex:
|
||||
print("[OBERLEISTE] Plan-Mode UseSectionStyles set:", ex)
|
||||
try: post_uss = bool(attrs.UseSectionStyles)
|
||||
except Exception: post_uss = None
|
||||
print("[OBERLEISTE] Plan-Mode UseSectionStyles pre={} post={}".format(
|
||||
pre_uss, post_uss))
|
||||
# Clipping-Edges + Fills sichtbar
|
||||
try: attrs.ShowClippingEdges = True
|
||||
except Exception: pass
|
||||
try: attrs.ShowClippingFills = True
|
||||
except Exception: pass
|
||||
try: attrs.ShowClipIntersectionEdges = True
|
||||
except Exception: pass
|
||||
try: attrs.ShowClipIntersectionSurfaces = True
|
||||
except Exception: pass
|
||||
# Linewidths an — Lineweights-Toggle wirkt
|
||||
try: attrs.ShowLineWidths = True
|
||||
except Exception: pass
|
||||
try:
|
||||
DisplayModeDescription.UpdateDisplayMode(dmd)
|
||||
except Exception as ex:
|
||||
print("[OBERLEISTE] Plan-Mode update:", ex)
|
||||
|
||||
|
||||
_TEMPLATE_INI_PATH = os.path.join(_HERE, "templates", "dossier_plan.ini")
|
||||
|
||||
|
||||
def _ensure_dossier_plan_display_mode():
|
||||
"""Stellt sicher dass der 'Dossier Plan' Display-Mode existiert.
|
||||
|
||||
Strategie: wenn eine Template-ini im Repo existiert
|
||||
(rhino/templates/dossier_plan.ini), laden wir die. Sonst Fallback auf
|
||||
Clone-Technical + ini-Patch. Template ist die bevorzugte Methode weil
|
||||
sich Mac-Rhino-Display-Mode-Properties via Python-API unzuverlaessig
|
||||
setzen lassen — der User baut den Mode einmal manuell perfekt zusammen
|
||||
und exportiert ihn dort hin.
|
||||
"""
|
||||
print("[OBERLEISTE] Plan-Mode: check...")
|
||||
try:
|
||||
from Rhino.Display import DisplayModeDescription
|
||||
except Exception as ex:
|
||||
print("[OBERLEISTE] Plan-Mode: DMD nicht verfuegbar:", ex)
|
||||
return False
|
||||
import re # fuer ini-checks unten
|
||||
target_name = "Dossier Plan"
|
||||
try:
|
||||
import System
|
||||
target_guid_obj = System.Guid(_DOSSIER_PLAN_GUID)
|
||||
except Exception:
|
||||
target_guid_obj = None
|
||||
# Template-Datei vorhanden? Wenn ja, Hash davon als "version key"
|
||||
# benutzen — wir nur neu importieren wenn sich die Template-Datei
|
||||
# geaendert hat.
|
||||
template_exists = os.path.isfile(_TEMPLATE_INI_PATH)
|
||||
print("[OBERLEISTE] Plan-Mode template: {}".format(
|
||||
"found at " + _TEMPLATE_INI_PATH if template_exists else "missing → fallback"))
|
||||
# Schon registriert?
|
||||
try:
|
||||
existing = None
|
||||
for dm in DisplayModeDescription.GetDisplayModes():
|
||||
try:
|
||||
if dm.EnglishName == target_name or dm.LocalName == target_name:
|
||||
existing = dm; break
|
||||
if target_guid_obj is not None and dm.Id == target_guid_obj:
|
||||
existing = dm; break
|
||||
except Exception: pass
|
||||
if existing is not None:
|
||||
# Mode existiert bereits — in Ruhe lassen. User kann manuell
|
||||
# loeschen + reloaden wenn er das Template neu laden will.
|
||||
# Vermeidet delete-loop wenn das Template ini-Werte hat die mein
|
||||
# alter check als "falsch" einstufte.
|
||||
print("[OBERLEISTE] Plan-Mode: existing gefunden, keine Aktion (manuell loeschen fuer Refresh)")
|
||||
return True
|
||||
# Sonst kein existing → vor dem Import alle Orphan-Modes mit unserer
|
||||
# Guid ODER Namen "Dossier Plan" wegputzen (alte kaputte Versionen
|
||||
# ohne Namen sind zuvor manchmal liegen geblieben → Duplikate +
|
||||
# Rhino-Crashes beim Klick).
|
||||
try:
|
||||
cleanup_count = 0
|
||||
for dm in list(DisplayModeDescription.GetDisplayModes()):
|
||||
should_delete = False
|
||||
try:
|
||||
if dm.EnglishName == target_name or dm.LocalName == target_name:
|
||||
should_delete = True
|
||||
elif target_guid_obj is not None and dm.Id == target_guid_obj:
|
||||
should_delete = True
|
||||
except Exception: pass
|
||||
if should_delete:
|
||||
try:
|
||||
DisplayModeDescription.DeleteDisplayMode(dm.Id)
|
||||
cleanup_count += 1
|
||||
except Exception as ex:
|
||||
print("[OBERLEISTE] Plan-Mode cleanup delete fail:", ex)
|
||||
if cleanup_count > 0:
|
||||
print("[OBERLEISTE] Plan-Mode: {} Orphan-Mode(s) entfernt vor Import".format(
|
||||
cleanup_count))
|
||||
except Exception as ex:
|
||||
print("[OBERLEISTE] Plan-Mode cleanup:", ex)
|
||||
except Exception as ex:
|
||||
print("[OBERLEISTE] Plan-Mode list:", ex)
|
||||
return False
|
||||
# ----------------------------------------------------------------
|
||||
# SOURCE: Template-ini bevorzugt (User hat den Mode manuell gebaut +
|
||||
# exportiert) — sonst Fallback auf Technical-Clone.
|
||||
# ----------------------------------------------------------------
|
||||
import tempfile
|
||||
tmp_path = os.path.join(tempfile.gettempdir(), "dossier_plan.ini")
|
||||
base = None
|
||||
if template_exists:
|
||||
# Template-ini lesen + ueberschreiben den tmp_path
|
||||
try:
|
||||
with open(_TEMPLATE_INI_PATH, "r", encoding="utf-8", errors="ignore") as f:
|
||||
content = f.read()
|
||||
print("[OBERLEISTE] Plan-Mode: Template geladen ({} bytes)".format(len(content)))
|
||||
except Exception as ex:
|
||||
print("[OBERLEISTE] Plan-Mode Template read:", ex)
|
||||
return False
|
||||
else:
|
||||
# Fallback: Technical exportieren + patchen
|
||||
try:
|
||||
all_modes = list(DisplayModeDescription.GetDisplayModes())
|
||||
except Exception: all_modes = []
|
||||
for prefer in ("Technical", "Pen", "Shaded"):
|
||||
for dm in all_modes:
|
||||
try:
|
||||
if dm.EnglishName == prefer:
|
||||
base = dm; break
|
||||
except Exception: pass
|
||||
if base is not None: break
|
||||
if base is None:
|
||||
print("[OBERLEISTE] Plan-Mode: kein Basis-Modus gefunden")
|
||||
return False
|
||||
try:
|
||||
ok_export = False
|
||||
try:
|
||||
ok_export = bool(DisplayModeDescription.ExportToFile(base, tmp_path))
|
||||
except Exception as ex:
|
||||
print("[OBERLEISTE] Plan-Mode ExportToFile:", ex)
|
||||
if not ok_export:
|
||||
print("[OBERLEISTE] Plan-Mode: ExportToFile failed")
|
||||
return False
|
||||
with open(tmp_path, "r", encoding="utf-8", errors="ignore") as f:
|
||||
content = f.read()
|
||||
except Exception as ex:
|
||||
print("[OBERLEISTE] Plan-Mode fallback read ini:", ex)
|
||||
return False
|
||||
|
||||
try:
|
||||
# Name-Feld ersetzen (verschiedene moegliche Keys)
|
||||
import re
|
||||
try:
|
||||
content = re.sub(
|
||||
r'(?i)^(\s*Name\s*=\s*)(.*)$',
|
||||
r'\1' + target_name, content, count=1, flags=re.MULTILINE)
|
||||
except Exception: pass
|
||||
# Guid (im ini meist als [<guid>] Section-Header oder als "id="-Feld)
|
||||
try:
|
||||
# Bestehende Guid aus dem File extrahieren + ueberall ersetzen
|
||||
old_guid_match = re.search(
|
||||
r'([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})',
|
||||
content)
|
||||
if old_guid_match:
|
||||
old_guid = old_guid_match.group(1)
|
||||
content = content.replace(old_guid, _DOSSIER_PLAN_GUID)
|
||||
content = content.replace(old_guid.upper(),
|
||||
_DOSSIER_PLAN_GUID.upper())
|
||||
except Exception: pass
|
||||
# Plan-Mode-Settings in der ini patchen — Rhino-DisplayMode-ini hat
|
||||
# nested Sections wie [DisplayMode\<guid>\Objects\Surfaces]. Wir
|
||||
# patchen nur EXISTIERENDE Keys (Rhino's Parser stripped unbekannte
|
||||
# Keys beim Re-Import wieder).
|
||||
def _ini_replace(content, key, value):
|
||||
"""Ersetzt erstes Vorkommen von key=... mit key=value (case-insens).
|
||||
Liefert (content, found_bool)."""
|
||||
pat = r'(?im)^(\s*' + re.escape(key) + r'\s*=\s*)(.*)$'
|
||||
new_content, n = re.subn(pat, r'\g<1>' + str(value),
|
||||
content, count=1)
|
||||
return new_content, (n > 0)
|
||||
|
||||
# Bei Template-Pfad: NUR Name+Guid normalisieren, KEINE inhaltlichen
|
||||
# Patches (User hat das Template bewusst so konfiguriert).
|
||||
# Bei Fallback-Pfad (Technical-Clone): die bekannten Settings forcen.
|
||||
if not template_exists:
|
||||
for key, val in (
|
||||
("ClipSectionUsage", "1"),
|
||||
("TechnicalMask", "15"),
|
||||
("ShowIsocurves", "n"),
|
||||
("ShowTangentEdges", "n"),
|
||||
("ShowTangentSeams", "n"),
|
||||
("ShowMeshWires", "n"),
|
||||
("ShowMeshEdges", "n"),
|
||||
("ShadeSurface", "n"),
|
||||
("ClippingShowXEdges", "y"),
|
||||
("ClippingShowXSurface", "y"),
|
||||
):
|
||||
try:
|
||||
content, found = _ini_replace(content, key, val)
|
||||
if found:
|
||||
print("[OBERLEISTE] Plan-Mode ini {}={}".format(key, val))
|
||||
except Exception as ex:
|
||||
print("[OBERLEISTE] Plan-Mode ini-set {}={} fail: {}".format(
|
||||
key, val, ex))
|
||||
try:
|
||||
with open(tmp_path, "w", encoding="utf-8") as f:
|
||||
f.write(content)
|
||||
except Exception as ex:
|
||||
print("[OBERLEISTE] Plan-Mode write ini:", ex)
|
||||
return False
|
||||
# Import
|
||||
try:
|
||||
ok_import = bool(DisplayModeDescription.ImportFromFile(tmp_path))
|
||||
except Exception as ex:
|
||||
print("[OBERLEISTE] Plan-Mode ImportFromFile:", ex)
|
||||
return False
|
||||
if not ok_import:
|
||||
print("[OBERLEISTE] Plan-Mode: ImportFromFile gab False")
|
||||
return False
|
||||
except Exception as ex:
|
||||
print("[OBERLEISTE] Plan-Mode clone:", ex)
|
||||
return False
|
||||
# Neu importierten Mode holen + tweaken
|
||||
try:
|
||||
dmd = None
|
||||
if target_guid_obj is not None:
|
||||
try: dmd = DisplayModeDescription.GetDisplayMode(target_guid_obj)
|
||||
except Exception: pass
|
||||
if dmd is None:
|
||||
for dm in DisplayModeDescription.GetDisplayModes():
|
||||
try:
|
||||
if dm.EnglishName == target_name or dm.LocalName == target_name:
|
||||
dmd = dm; break
|
||||
except Exception: pass
|
||||
if dmd is None:
|
||||
print("[OBERLEISTE] Plan-Mode: nach Import nicht gefunden")
|
||||
return False
|
||||
# KEIN _apply_dossier_plan_attrs() hier — der wuerde
|
||||
# UpdateDisplayMode() aufrufen und die ini-Werte (ClipSectionUsage,
|
||||
# TechnicalMask) mit den Python-Default-Attrs ueberschreiben.
|
||||
# Die ini hat schon alle richtigen Werte.
|
||||
src = "Template" if template_exists else (base.EnglishName if base else "?")
|
||||
print("[OBERLEISTE] Display-Mode 'Dossier Plan' angelegt (Basis: {})".format(src))
|
||||
# Sanity-Check: liste alle Display-Modes auf damit wir sehen ob unser
|
||||
# Mode wirklich registriert ist (und mit welchem Namen).
|
||||
try:
|
||||
names = []
|
||||
for dm_check in DisplayModeDescription.GetDisplayModes():
|
||||
try:
|
||||
names.append(dm_check.EnglishName)
|
||||
except Exception: pass
|
||||
print("[OBERLEISTE] Plan-Mode: alle registrierten Modes: {}".format(
|
||||
", ".join(names)))
|
||||
except Exception: pass
|
||||
# Cache invalidieren damit das Dropdown ihn sieht
|
||||
try:
|
||||
global _display_modes_cache
|
||||
_display_modes_cache = None
|
||||
except Exception: pass
|
||||
return True
|
||||
except Exception as ex:
|
||||
print("[OBERLEISTE] Plan-Mode tweak:", ex)
|
||||
return False
|
||||
|
||||
|
||||
_THUMB_SIZE = (480, 320) # 3:2 — kompakt fuer Launcher-Cards
|
||||
|
||||
|
||||
@@ -1730,5 +2089,13 @@ def _bridge_factory():
|
||||
return b
|
||||
|
||||
|
||||
# Custom Display-Mode 'Dossier Plan' beim Modul-Load registrieren — laeuft
|
||||
# bei jedem startup.py oder _reset_panels.py, unabhaengig davon ob das
|
||||
# Panel jemals geoeffnet wird. Funktion ist idempotent.
|
||||
try: _ensure_dossier_plan_display_mode()
|
||||
except Exception as ex:
|
||||
print("[OBERLEISTE] ensure_dossier_plan_display_mode:", ex)
|
||||
|
||||
|
||||
panel_base.register_and_open("oberleiste", "Oberleiste", PANEL_GUID_STR, _bridge_factory,
|
||||
icon_spec=("menu", "#2f5d54"))
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#! python3
|
||||
# -*- coding: utf-8 -*-
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
# Copyright (C) 2026 Karim Gabriele Varano
|
||||
"""
|
||||
OSM-Importer fuer Dossier — holt OpenStreetMap-Daten via Overpass-API als
|
||||
Polylinien (Strassen, Gebaeudeumrisse, Wasser, Gruenflaechen, Wege).
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#! python 3
|
||||
# -*- coding: utf-8 -*-
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
# Copyright (C) 2026 Karim Gabriele Varano
|
||||
"""
|
||||
overrides.py
|
||||
Engine fuer regelbasierte grafische Overrides (ArchiCAD Graphical Overrides /
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#! python 3
|
||||
# -*- coding: utf-8 -*-
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
# Copyright (C) 2026 Karim Gabriele Varano
|
||||
"""
|
||||
overrides_panel.py
|
||||
OVERRIDES-Panel: Rule-Editor fuer grafische Overrides.
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#! python 3
|
||||
# -*- coding: utf-8 -*-
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
# Copyright (C) 2026 Karim Gabriele Varano
|
||||
"""
|
||||
panel_base.py
|
||||
Geteilte Infrastruktur fuer dockbare Rhino-Panels mit React-WebView.
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#! python 3
|
||||
# -*- coding: utf-8 -*-
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
# Copyright (C) 2026 Karim Gabriele Varano
|
||||
"""
|
||||
rhinopanel.py
|
||||
Oeffnet das EBENEN-Panel (Zeichnungsebenen + globale Ebenen).
|
||||
@@ -16,6 +18,7 @@ if _HERE not in sys.path:
|
||||
|
||||
import panel_base
|
||||
import layer_builder
|
||||
import library
|
||||
|
||||
PANEL_GUID_STR = "3a7f2e1d-4b8c-4d9e-a1b2-c3d4e5f60718"
|
||||
# Zweites Panel fuer Zeichnungsebenen (Geschoss-Liste + Clipping). UX-Split
|
||||
@@ -1609,6 +1612,10 @@ class EbenenBridge(panel_base.BaseBridge):
|
||||
updated = p.get("ebene") or {}
|
||||
orig_code = p.get("originalCode") or updated.get("code")
|
||||
if not (isinstance(updated, dict) and updated.get("code")): return
|
||||
# DEBUG: zeigt was tatsaechlich vom Frontend ankommt
|
||||
_sec = updated.get("section") or {}
|
||||
print("[EBENEN-SETTINGS] _persist code={} sec.hatch={} sec.color={}".format(
|
||||
updated.get("code"), _sec.get("hatchPattern"), _sec.get("hatchColor")))
|
||||
e_raw = doc.Strings.GetValue("dossier_ebenen")
|
||||
if not e_raw: return
|
||||
try: e_list = json.loads(e_raw)
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#! python3
|
||||
# -*- coding: utf-8 -*-
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
# Copyright (C) 2026 Karim Gabriele Varano
|
||||
"""
|
||||
schnitt_grips.py
|
||||
Endpoint-Grips fuer Schnitt/Ansicht-Symbole im Plan.
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#! python3
|
||||
# -*- coding: utf-8 -*-
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
# Copyright (C) 2026 Karim Gabriele Varano
|
||||
"""
|
||||
schnitte.py
|
||||
Schnitte + Ansichten als Zeichnungsebenen-Typ.
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#! python 3
|
||||
# -*- coding: utf-8 -*-
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
# Copyright (C) 2026 Karim Gabriele Varano
|
||||
"""
|
||||
startup.py
|
||||
Laedt DOSSIER-Panels beim Rhino-Start. Liest pro geoeffnetem Dokument eine
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#! python 3
|
||||
# -*- coding: utf-8 -*-
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
# Copyright (C) 2026 Karim Gabriele Varano
|
||||
"""
|
||||
swisstopo.py
|
||||
STAC-API-Client + GeoTIFF/XYZ-Parser + Mesh-Builder fuer swisstopo-Daten.
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
# Display-Mode-Templates
|
||||
|
||||
## dossier_plan.ini — was wir wollen
|
||||
|
||||
Das Plugin liest **`dossier_plan.ini`** aus diesem Ordner und lädt den
|
||||
Dossier-Plan-Display-Mode daraus. So fügst du den Mode hinzu:
|
||||
|
||||
1. In Rhino: Display-Mode-Editor öffnen (Settings → View → Display Modes)
|
||||
2. „Dossier Plan" auswählen (oder einen neuen Mode anlegen + benennen)
|
||||
3. Settings so einstellen wie du sie haben willst:
|
||||
- General → Visibility → „Show HiddenLines" **AUS**
|
||||
- Clipping plane objects → „Use section styles" **AN**
|
||||
- Curves, Mesh-Wires, Iso-Curves: alles aus
|
||||
- Hintergrund weiss
|
||||
- Was auch immer du brauchst…
|
||||
4. Apply + OK
|
||||
5. Display-Mode-Editor: rechts-klick auf „Dossier Plan" → **Export…**
|
||||
6. Datei speichern als: `~/STUDIO/DOSSIER/rhino/templates/dossier_plan.ini`
|
||||
|
||||
Beim nächsten Reload (`_RunPythonScript /…/_reset_panels.py`) lädt das
|
||||
Plugin den Mode aus dieser ini direkt. Name + Guid werden automatisch
|
||||
auf „Dossier Plan" + `d0551e72-7e72-4170-b1a4-d0551e72d055` umgesetzt, alles
|
||||
andere bleibt 1:1 wie du's exportiert hast.
|
||||
|
||||
## Fallback wenn keine ini da
|
||||
|
||||
Wenn `dossier_plan.ini` nicht existiert, klont das Plugin den
|
||||
**Technical**-Mode und patcht ihn programmatisch (mit den paar Settings
|
||||
die wir kennen). Funktioniert aber nicht so robust — Template ist
|
||||
sauberer.
|
||||
@@ -0,0 +1,323 @@
|
||||
[DisplayMode\d0551e72-7e72-4170-b1a4-d0551e72d055]
|
||||
PipelineId=e1eb7363-87f2-4a2b-a861-256e77835369
|
||||
SupportsShading=y
|
||||
SupportsStereo=y
|
||||
AddToMenu=y
|
||||
AllowObjectAssignment=y
|
||||
ShadedPipelineRequired=y
|
||||
WireframePipelineRequired=y
|
||||
PipelineLocked=y
|
||||
Order=-6
|
||||
DerivedFrom=00000000-0000-0000-0000-000000000000
|
||||
Name=Dossier Plan
|
||||
XrayAllObjects=n
|
||||
IgnoreHighlights=n
|
||||
DisableConduits=n
|
||||
DisableTransparency=n
|
||||
BBoxMode=0
|
||||
RealtimeDisplayId=00000000-0000-0000-0000-000000000000
|
||||
SupportsShadeCmd=y
|
||||
[DisplayMode\d0551e72-7e72-4170-b1a4-d0551e72d055\Lighting]
|
||||
ShadowIntensity=100
|
||||
ShadowClippingRadius=0
|
||||
ShadowClippingUsage=0
|
||||
PerPixelLighting=n
|
||||
TransparencyTolerance=40
|
||||
ShadowBlur=0
|
||||
ShadowBias=10,12,0
|
||||
ShowLights=n
|
||||
UseHiddenLights=n
|
||||
UseLightColor=n
|
||||
LightingScheme=0
|
||||
Luminosity=0
|
||||
AmbientColor=0,0,0
|
||||
LightCount=0
|
||||
CastShadows=n
|
||||
ShadowMapSize=2048
|
||||
SkylightShadowQuality=4
|
||||
NumSamples=4
|
||||
ShadowMapType=2
|
||||
ShadowBitDepth=32
|
||||
ShadowColor=0,0,0
|
||||
[DisplayMode\d0551e72-7e72-4170-b1a4-d0551e72d055\Objects]
|
||||
CPHidePoints=n
|
||||
CPHighlight=y
|
||||
CPHidden=n
|
||||
nCPWireThickness=1
|
||||
LockedUsage=2
|
||||
LockedTrans=50
|
||||
GhostLockedObjects=n
|
||||
ClipSectionUsage=0
|
||||
CPColor=0,0,0
|
||||
eCVStyle=102
|
||||
nCVSize=3
|
||||
LayersFollowLockUsage=n
|
||||
LockedObjectsBehind=n
|
||||
LockedColor=100,100,100
|
||||
CPSolidLines=n
|
||||
CPSingleColor=n
|
||||
CPHideSurface=n
|
||||
[DisplayMode\d0551e72-7e72-4170-b1a4-d0551e72d055\Objects\Annotations]
|
||||
DotBorderColor=-1
|
||||
ShowText=y
|
||||
ShowAnnotations=y
|
||||
DotTextColor=-1
|
||||
[DisplayMode\d0551e72-7e72-4170-b1a4-d0551e72d055\Objects\Curves]
|
||||
ShowCurves=y
|
||||
CurveThicknessUsage=0
|
||||
LineJoinStyle=0
|
||||
LineEndCapStyle=0
|
||||
CurvePattern=-1
|
||||
CurveTrans=0
|
||||
CurveThickness=1
|
||||
CurveColor=0,0,0
|
||||
SingleCurveColor=n
|
||||
ShowCurvatureHair=n
|
||||
CurveThicknessScale=1
|
||||
[DisplayMode\d0551e72-7e72-4170-b1a4-d0551e72d055\Objects\Meshes]
|
||||
ShowMeshNakedEdges=n
|
||||
MeshNonmanifoldEdgeColor=0,0,0
|
||||
MeshNakedEdgeColor=0,0,0
|
||||
MeshEdgeColor=0,0,0
|
||||
MeshNonmanifoldEdgeColorReduction=0
|
||||
MeshNakedEdgeColorReduction=0
|
||||
MeshEdgeColorReduction=0
|
||||
MeshNonmanifoldEdgeThickness=0
|
||||
MeshNakedEdgeThickness=2
|
||||
MeshEdgeThickness=2
|
||||
ShowMeshNonmanifoldEdges=n
|
||||
ShowMeshEdges=n
|
||||
MeshVertexSize=0
|
||||
ShowMeshVertices=n
|
||||
ShowMeshWires=n
|
||||
MeshWirePattern=-1
|
||||
MeshWireThickness=1
|
||||
MeshWireColor=0,0,0
|
||||
SingleMeshWireColor=n
|
||||
HighlightMeshes=n
|
||||
[DisplayMode\d0551e72-7e72-4170-b1a4-d0551e72d055\Objects\Points]
|
||||
PCSize=2
|
||||
ShowPoints=y
|
||||
PointStyle=51
|
||||
PointSize=3
|
||||
PCGripStyle=102
|
||||
PCGripSize=2
|
||||
PCStyle=50
|
||||
ShowPointClouds=y
|
||||
[DisplayMode\d0551e72-7e72-4170-b1a4-d0551e72d055\Objects\SubD]
|
||||
CreaseVisible=n
|
||||
CreaseUsage=0
|
||||
CreaseColor=255,255,255
|
||||
CreaseColorReduction=0
|
||||
CreaseThickness=2
|
||||
CreaseThicknessScale=1
|
||||
CreaseApplyPattern=y
|
||||
NonmanifoldVisible=n
|
||||
NonmanifoldUsage=0
|
||||
NonmanifoldColor=255,255,255
|
||||
NonmanifoldColorReduction=0
|
||||
NonmanifoldThickness=1
|
||||
NonmanifoldThicknessScale=1
|
||||
NonmanifoldApplyPattern=y
|
||||
BoundaryVisible=n
|
||||
BoundaryUsage=0
|
||||
BoundaryColor=255,255,255
|
||||
SmoothColorReduction=0
|
||||
SmoothColor=255,255,255
|
||||
ShowSymmetryAxis=y
|
||||
SmoothVisible=n
|
||||
SubDThicknessUsage=0
|
||||
BoundaryColorReduction=0
|
||||
BoundaryThickness=2
|
||||
SmoothThickness=1
|
||||
BoundaryThicknessScale=2
|
||||
BoundaryApplyPattern=y
|
||||
ShowReflectedPlane=y
|
||||
SmoothUsage=0
|
||||
PlaneColorUsage=2
|
||||
SymmetryAxisThickness=0.02500000037252903
|
||||
ReflectedColor=64,64,64
|
||||
ColorPercentage=30
|
||||
AxisColor=255,0,0
|
||||
SmoothThicknessScale=1
|
||||
SmoothApplyPattern=y
|
||||
[DisplayMode\d0551e72-7e72-4170-b1a4-d0551e72d055\Objects\Surfaces]
|
||||
EdgeColorReduction=0
|
||||
SurfaceKappaHair=n
|
||||
HighlightSurfaces=n
|
||||
ShowIsocurves=n
|
||||
IsoThicknessUsed=n
|
||||
IsocurveThickness=1
|
||||
IsoUThickness=1
|
||||
IsoVThickness=1
|
||||
IsoWThickness=1
|
||||
SingleIsoColor=n
|
||||
IsoColor=0,0,0
|
||||
IsoColorsUsed=n
|
||||
IsoUColor=0,0,0
|
||||
IsoVColor=0,0,0
|
||||
IsoWColor=0,0,0
|
||||
IsoPatternUsed=n
|
||||
IsocurvePattern=-1
|
||||
IsoUPattern=-1
|
||||
IsoVPattern=-1
|
||||
IsoWPattern=-1
|
||||
ShowEdges=y
|
||||
ShowNakedEdges=n
|
||||
ShowTangentEdges=n
|
||||
ShowTangentSeams=n
|
||||
ShowNonmanifoldEdges=n
|
||||
ShowEdgeEndpoints=n
|
||||
EdgeThickness=1
|
||||
EdgeColorUsage=0
|
||||
NakedEdgeThickness=2
|
||||
NakedEdgeColorUsage=0
|
||||
NakedEdgeColorReduction=0
|
||||
EdgeColor=0,0,0
|
||||
NakedEdgeColor=0,0,0
|
||||
NonmanifoldEdgeColor=0,0,0
|
||||
EdgePattern=-1
|
||||
NakedEdgePattern=-1
|
||||
NonmanifoldEdgePattern=-1
|
||||
SurfaceThicknessUsage=0
|
||||
SurfaceEdgeThicknessScale=2
|
||||
SurfaceEdgeApplyPattern=y
|
||||
SurfaceNakedEdgeUseNormalEdgeThickness=y
|
||||
SurfaceNakedEdgeThicknessScale=2
|
||||
SurfaceNakedEdgeApplyPattern=y
|
||||
SurfaceIsoUThicknessScale=1
|
||||
SurfaceIsoVThicknessScale=1
|
||||
SurfaceIsoWThicknessScale=1
|
||||
SurfaceIsoUApplyPattern=y
|
||||
SurfaceIsoVApplyPattern=y
|
||||
SurfaceIsoWApplyPattern=y
|
||||
ShowFlatSurfaceIsos=n
|
||||
[DisplayMode\d0551e72-7e72-4170-b1a4-d0551e72d055\Objects\Technical]
|
||||
TEThickness=1
|
||||
TCThickness=1
|
||||
TSThickness=1
|
||||
TIThickness=1
|
||||
THColor=0,0,0
|
||||
TEColor=0,0,0
|
||||
TSiColor=0,0,0
|
||||
TCColor=0,0,0
|
||||
TSColor=0,0,0
|
||||
TIColor=0,0,0
|
||||
TechnicalMask=14
|
||||
TechnicalUsageMask=0
|
||||
THThickness=1
|
||||
TSiThickness=1
|
||||
[DisplayMode\d0551e72-7e72-4170-b1a4-d0551e72d055\Shading]
|
||||
ParallelLineRotation=0
|
||||
CullBackfaces=n
|
||||
ShadeVertexColors=n
|
||||
SingleWireColor=n
|
||||
WireColor=0,0,0
|
||||
ShadeSurface=y
|
||||
UseObjectMaterial=n
|
||||
UseObjectBFMaterial=n
|
||||
BakeTextures=y
|
||||
ShowDecals=y
|
||||
SurfaceColorWriting=y
|
||||
ShadingEffect=0
|
||||
ParallelLineWidth=2
|
||||
ParallelLineSeparation=3
|
||||
[DisplayMode\d0551e72-7e72-4170-b1a4-d0551e72d055\Shading\Material]
|
||||
BackIsCustom=y
|
||||
FrontIsCustom=n
|
||||
UseBackMaterial=y
|
||||
[DisplayMode\d0551e72-7e72-4170-b1a4-d0551e72d055\Shading\Material\Back Material]
|
||||
ShineIntensity=100
|
||||
Luminosity=0
|
||||
Reflectivity=0
|
||||
Transparency=0
|
||||
Specular=255,255,255
|
||||
Shine=0
|
||||
Diffuse=126,126,126
|
||||
OverrideObjectReflectivity=y
|
||||
OverrideObjectTransparency=y
|
||||
OverrideObjectColor=n
|
||||
FlatShaded=n
|
||||
[DisplayMode\d0551e72-7e72-4170-b1a4-d0551e72d055\Shading\Material\Back Material\BitmapTexture]
|
||||
=
|
||||
[DisplayMode\d0551e72-7e72-4170-b1a4-d0551e72d055\Shading\Material\Back Material\EmapTexture]
|
||||
=
|
||||
[DisplayMode\d0551e72-7e72-4170-b1a4-d0551e72d055\Shading\Material\Back Material\TransparencyTexture]
|
||||
=
|
||||
[DisplayMode\d0551e72-7e72-4170-b1a4-d0551e72d055\Shading\Material\Front Material]
|
||||
Diffuse=126,126,126
|
||||
Specular=255,255,255
|
||||
Shine=128
|
||||
ShineIntensity=100
|
||||
Reflectivity=0
|
||||
Transparency=0
|
||||
FlatShaded=y
|
||||
OverrideObjectColor=n
|
||||
OverrideObjectTransparency=y
|
||||
OverrideObjectReflectivity=y
|
||||
Luminosity=0
|
||||
[DisplayMode\d0551e72-7e72-4170-b1a4-d0551e72d055\Shading\Material\Front Material\BitmapTexture]
|
||||
=
|
||||
[DisplayMode\d0551e72-7e72-4170-b1a4-d0551e72d055\Shading\Material\Front Material\EmapTexture]
|
||||
=
|
||||
[DisplayMode\d0551e72-7e72-4170-b1a4-d0551e72d055\Shading\Material\Front Material\TransparencyTexture]
|
||||
=
|
||||
[DisplayMode\d0551e72-7e72-4170-b1a4-d0551e72d055\View settings]
|
||||
ShowClippingPlanes=n
|
||||
FlipGlasses=n
|
||||
AGViewingMode=0
|
||||
AGColorMode=0
|
||||
StereoParallax=1
|
||||
StereoSeparation=1
|
||||
StereoModeEnabled=0
|
||||
BackgroundBitmap=
|
||||
GradBotRight=140,140,140
|
||||
WzColor=0,0,150
|
||||
GridTrans=60
|
||||
WyColor=75,150,75
|
||||
WxColor=150,75,75
|
||||
WorldAxesColor=0
|
||||
GridPlaneColor=0,0,0
|
||||
PlaneUsesGridColor=n
|
||||
AxesPercentage=100
|
||||
PlaneVisibility=0
|
||||
GridPlaneTrans=90
|
||||
DrawTransGridPlane=n
|
||||
GradTopRight=200,200,200
|
||||
GradBotLeft=140,140,140
|
||||
GradTopLeft=200,200,200
|
||||
SolidColor=230,230,230
|
||||
FillMode=2
|
||||
CustomLinearWorkflowPostProcessGamma=2.200000047683716
|
||||
CustomLinearWorkflowPreProcessGamma=2.200000047683716
|
||||
CustomLinearWorkflowPostProcessFrameBuffer=n
|
||||
CustomLinearWorkflowPreProcessTextures=y
|
||||
CustomLinearWorkflowPreProcessColors=y
|
||||
LinearWorkflowUsage=0
|
||||
CustomGroundPlaneShadowOnly=y
|
||||
CustomGroundPlaneAutomaticAltitude=y
|
||||
CustomGroundPlaneAltitude=0
|
||||
CustomGroundPlaneShow=y
|
||||
GroundPlaneUsage=1
|
||||
UseDocumentGrid=n
|
||||
DrawGrid=n
|
||||
DrawAxes=n
|
||||
DrawZAxis=n
|
||||
DrawWorldAxes=n
|
||||
ShowGridOnTop=n
|
||||
ShowTransGrid=n
|
||||
BlendGrid=n
|
||||
VertScale=1
|
||||
HorzScale=1
|
||||
ClippingCPColor=255,255,255
|
||||
ClippingEdgeColor=0,0,0
|
||||
ClippingSurfaceColor=128,128,128
|
||||
ClippingEdgeThickness=3
|
||||
ClippingCPTrans=95
|
||||
ClippingCPUsage=0
|
||||
ClippingEdgesUsage=2
|
||||
ClippingSurfaceUsage=0
|
||||
ClippingShowCP=n
|
||||
ClippingClipSelected=y
|
||||
ClippingShowXEdges=y
|
||||
ClippingShowXSurface=y
|
||||
@@ -1,5 +1,7 @@
|
||||
#! python 3
|
||||
# -*- coding: utf-8 -*-
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
# Copyright (C) 2026 Karim Gabriele Varano
|
||||
"""
|
||||
text_create.py
|
||||
Text-Erstellungs-Workflow mit Floating-Input-Box statt Rhino-Dialog.
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#! python 3
|
||||
# -*- coding: utf-8 -*-
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
# Copyright (C) 2026 Karim Gabriele Varano
|
||||
"""
|
||||
text_editor.py
|
||||
React-WYSIWYG-Editor in Satellite-WebView (Topmost). User picked Frame
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#! python3
|
||||
# -*- coding: utf-8 -*-
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
# Copyright (C) 2026 Karim Gabriele Varano
|
||||
"""
|
||||
wand_grips.py
|
||||
Custom Endpoint-Grips fuer Waende — Display-Conduit + MouseCallback Overlay.
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#! python 3
|
||||
# -*- coding: utf-8 -*-
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
# Copyright (C) 2026 Karim Gabriele Varano
|
||||
"""
|
||||
werkzeuge.py
|
||||
WERKZEUGE-Panel: Architektur-orientierte Toolbar als React-WebView.
|
||||
|
||||
Reference in New Issue
Block a user