From 02a00a9b4a0c3d2e601885060d0508c72d97f0b5 Mon Sep 17 00:00:00 2001 From: karim Date: Tue, 26 May 2026 18:26:49 +0200 Subject: [PATCH] Display-Modes: 3D-Template + Auto-Assign + Material/Raytracing-Slots MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Neues Template rhino/templates/dossier_3d.ini fuer perspektivische Views - Registry-Loop in oberleiste.py generalisiert (Plan + 3D + Material + Raytracing) — Material/Raytracing skippen wenn kein Template vorhanden, um Cycles-Pipeline-Clone-Crash zu vermeiden - Guid-Replace praezisiert: nur Section-Header-Guid, nie PipelineId - Plan-spezifische ini-Patches auf target_name=="Dossier Plan" gegated - Auto-Assign in startup.py: Parallel-Viewports -> Plan, Perspective -> 3D, einmal-pro-Doc via doc.Strings-Flag (User-Overrides bleiben) - schnitte.activate_schnitt setzt Dossier Plan explizit (Hatches auch in Schnittperspektive sichtbar) - GestaltungApp Section-Block neu strukturiert: PenBlock fuer 3D als 'Fill' innerhalb der Section, Solid-Fill-Toggle entfernt (war Duplikat) --- rhino/oberleiste.py | 114 ++++++++---- rhino/schnitte.py | 11 ++ rhino/startup.py | 71 ++++++++ rhino/templates/dossier_3d.ini | 323 +++++++++++++++++++++++++++++++++ src/GestaltungApp.jsx | 37 ++-- 5 files changed, 497 insertions(+), 59 deletions(-) create mode 100644 rhino/templates/dossier_3d.ini diff --git a/rhino/oberleiste.py b/rhino/oberleiste.py index 6ea55fc..9c95408 100644 --- a/rhino/oberleiste.py +++ b/rhino/oberleiste.py @@ -185,9 +185,23 @@ def _import_display_modes(paths): return count -# Fest-Guid fuer 'Dossier Plan' damit Re-Imports denselben Slot +# Fest-Guids fuer die Dossier-Display-Modes damit Re-Imports denselben Slot # wiederverwenden statt Duplikate zu erzeugen. -_DOSSIER_PLAN_GUID = "d0551e72-7e72-4170-b1a4-d0551e72d055" +_DOSSIER_PLAN_GUID = "d0551e72-7e72-4170-b1a4-d0551e72d055" +_DOSSIER_3D_GUID = "d0551e72-7e72-4170-b1a4-3d3d3d3d3d3d" +_DOSSIER_MATERIAL_GUID = "d0551e72-7e72-4170-b1a4-555555555555" +_DOSSIER_RAYTRACING_GUID = "d0551e72-7e72-4170-b1a4-666666666666" + +# Registrierte Dossier-Display-Modes: (name, guid, template_basename, default_pipeline_fallback) +# Material + Raytracing haben (noch) kein Template — werden vom Fallback-Base +# (Rendered / Raytraced) geklont. User kann sie in Rhino anpassen und spaeter +# als Template exportieren. +_DOSSIER_DISPLAY_MODES = ( + ("Dossier Plan", _DOSSIER_PLAN_GUID, "dossier_plan.ini", "Technical"), + ("Dossier 3D", _DOSSIER_3D_GUID, "dossier_3d.ini", "Shaded"), + ("Dossier Material", _DOSSIER_MATERIAL_GUID, "dossier_material.ini", "Rendered"), + ("Dossier Raytracing", _DOSSIER_RAYTRACING_GUID, "dossier_raytracing.ini", "Raytraced"), +) def _apply_dossier_plan_attrs(dmd): """Wendet die Dossier-Plan-Visual-Settings auf einen DisplayMode an. @@ -303,38 +317,54 @@ def _apply_dossier_plan_attrs(dmd): print("[OBERLEISTE] Plan-Mode update:", ex) -_TEMPLATE_INI_PATH = os.path.join(_HERE, "templates", "dossier_plan.ini") +_TEMPLATES_DIR = os.path.join(_HERE, "templates") -def _ensure_dossier_plan_display_mode(): - """Stellt sicher dass der 'Dossier Plan' Display-Mode existiert. +def _ensure_dossier_display_mode(target_name, target_guid, template_basename, + fallback_base_name): + """Stellt sicher dass ein Dossier-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. + (rhino/templates/), laden wir die. Sonst Fallback auf + Clone-eines-Built-in-Mode + ini-Patch. Template ist die bevorzugte + Methode weil sich Mac-Rhino-Display-Mode-Properties via Python-API + unzuverlaessig setzen lassen. + + Args: + target_name: 'Dossier Plan' / 'Dossier 3D' / ... + target_guid: Fix-Guid die wir fuer Re-Imports wiederverwenden + template_basename: 'dossier_plan.ini' / 'dossier_3d.ini' + fallback_base_name: 'Technical' / 'Shaded' — Mode zum Klonen """ - print("[OBERLEISTE] Plan-Mode: check...") + print("[OBERLEISTE] {}: check...".format(target_name)) try: from Rhino.Display import DisplayModeDescription except Exception as ex: - print("[OBERLEISTE] Plan-Mode: DMD nicht verfuegbar:", ex) + print("[OBERLEISTE] {}: DMD nicht verfuegbar: {}".format(target_name, ex)) return False - import re # fuer ini-checks unten - target_name = "Dossier Plan" + import re + template_ini_path = os.path.join(_TEMPLATES_DIR, template_basename) try: import System - target_guid_obj = System.Guid(_DOSSIER_PLAN_GUID) + target_guid_obj = System.Guid(target_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")) + template_exists = os.path.isfile(template_ini_path) + print("[OBERLEISTE] {} template: {}".format(target_name, + "found at " + template_ini_path if template_exists else "missing")) + # Fallback-Clone nur fuer "Dossier Plan" erlauben. Bei anderen Modes + # ohne Template skippen — sonst klonen wir z.B. den Raytraced-Mode mit + # Cycles-PipelineId, was Rhinos Display-Mode-State auf Mac korrumpieren + # und ALLE Modes nach Restart verschwinden lassen kann. User soll den + # Mode in Rhino bauen + per "Save As" -> templates/ exportieren. + if not template_exists and target_name != "Dossier Plan": + print("[OBERLEISTE] {}: kein Template → skip (in Rhino bauen, " + "Display-Mode -> Save As -> {})".format( + target_name, template_ini_path)) + return False # Schon registriert? try: existing = None @@ -385,23 +415,24 @@ def _ensure_dossier_plan_display_mode(): # exportiert) — sonst Fallback auf Technical-Clone. # ---------------------------------------------------------------- import tempfile - tmp_path = os.path.join(tempfile.gettempdir(), "dossier_plan.ini") + tmp_path = os.path.join(tempfile.gettempdir(), template_basename) 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: + 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))) + print("[OBERLEISTE] {}: Template geladen ({} bytes)".format( + target_name, len(content))) except Exception as ex: - print("[OBERLEISTE] Plan-Mode Template read:", ex) + print("[OBERLEISTE] {} Template read: {}".format(target_name, ex)) return False else: - # Fallback: Technical exportieren + patchen + # Fallback: einen Base-Mode exportieren + patchen try: all_modes = list(DisplayModeDescription.GetDisplayModes()) except Exception: all_modes = [] - for prefer in ("Technical", "Pen", "Shaded"): + for prefer in (fallback_base_name, "Technical", "Pen", "Shaded"): for dm in all_modes: try: if dm.EnglishName == prefer: @@ -434,18 +465,24 @@ def _ensure_dossier_plan_display_mode(): r'(?i)^(\s*Name\s*=\s*)(.*)$', r'\1' + target_name, content, count=1, flags=re.MULTILINE) except Exception: pass - # Guid (im ini meist als [] Section-Header oder als "id="-Feld) + # Mode-Guid PRAEZISE per Section-Header finden — nicht irgendeine + # Guid im ini erwischen (PipelineId etc. sind eigene Guids die wir + # NICHT anfassen duerfen, sonst geht die Pipeline-Referenz kaputt + # und Rhino verliert den Mode bzw. crasht beim Klick). 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})', + r'\[DisplayMode\\([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, target_guid) content = content.replace(old_guid.upper(), - _DOSSIER_PLAN_GUID.upper()) - except Exception: pass + target_guid.upper()) + else: + print("[OBERLEISTE] {}: kein DisplayMode-Section-Header " + "gefunden — Mode-Guid nicht ersetzt".format(target_name)) + except Exception as ex: + print("[OBERLEISTE] {} Guid-Replace: {}".format(target_name, ex)) # Plan-Mode-Settings in der ini patchen — Rhino-DisplayMode-ini hat # nested Sections wie [DisplayMode\\Objects\Surfaces]. Wir # patchen nur EXISTIERENDE Keys (Rhino's Parser stripped unbekannte @@ -460,8 +497,12 @@ def _ensure_dossier_plan_display_mode(): # 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: + # Bei Fallback-Pfad fuer Dossier Plan (Technical-Clone): die Plan- + # spezifischen Settings forcen. Andere Modes (Material/Raytracing) + # uebernehmen den Fallback-Base 1:1 — sonst wuerden Plan-Settings + # wie TechnicalMask in eine Rendered/Raytraced-ini gequetscht und + # alles zerschiessen. + if not template_exists and target_name == "Dossier Plan": for key, val in ( ("ClipSectionUsage", "1"), ("TechnicalMask", "15"), @@ -2092,9 +2133,12 @@ def _bridge_factory(): # 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) +# Alle Dossier-Display-Modes registrieren (Plan, 3D, ...) +for _name, _guid, _tmpl, _fallback in _DOSSIER_DISPLAY_MODES: + try: + _ensure_dossier_display_mode(_name, _guid, _tmpl, _fallback) + except Exception as _ex: + print("[OBERLEISTE] ensure {}: {}".format(_name, _ex)) panel_base.register_and_open("oberleiste", "Oberleiste", PANEL_GUID_STR, _bridge_factory, diff --git a/rhino/schnitte.py b/rhino/schnitte.py index 51f32e1..e08c2cd 100644 --- a/rhino/schnitte.py +++ b/rhino/schnitte.py @@ -293,6 +293,17 @@ def activate_schnitt(doc, z, skip_view=False): vp.ChangeToParallelProjection(True) vp.SetCameraLocations(target, cam_pos) vp.CameraUp = rg.Vector3d(0, 0, 1) + # Display-Mode auf 'Dossier Plan' — auch bei Perspektive, damit + # die Section-Hatches sichtbar sind. User kann manuell wechseln. + try: + from Rhino.Display import DisplayModeDescription + for dm in DisplayModeDescription.GetDisplayModes(): + try: + if dm.EnglishName == "Dossier Plan": + vp.DisplayMode = dm + break + except Exception: pass + except Exception: pass # Zoom auf Schnitt-BoundingBox + etwas Rand. Bei Perspektive # macht ZoomBoundingBox auch Sinn — Rhino passt das FOV-Frame # entsprechend an. diff --git a/rhino/startup.py b/rhino/startup.py index 6813192..c6de017 100644 --- a/rhino/startup.py +++ b/rhino/startup.py @@ -76,6 +76,71 @@ def _migrate_active_doc(*_): print("[STARTUP] Migration:", ex) +_DOC_FLAG_VIEW_MODES = "dossier_view_modes_initialized" + + +def _assign_default_display_modes(doc): + """Setzt einmalig pro Doc die Display-Modes auf die Dossier-Defaults: + - Parallel-Projektionen (Top/Front/Right/Schnitt-parallel) -> 'Dossier Plan' + - Perspektive (Perspective/Schnittperspektive) -> 'Dossier 3D' + Persistiert einen Flag in doc.Strings → laeuft nur EINMAL pro Doc. + User-Overrides (manuelles Wechseln) bleiben damit erhalten. + """ + if doc is None: return + try: + if doc.Strings.GetValue(_DOC_FLAG_VIEW_MODES) == "1": + return # schon initialisiert + except Exception: pass + + try: + from Rhino.Display import DisplayModeDescription + except Exception as ex: + print("[STARTUP] view-modes: DMD nicht verfuegbar:", ex); return + + # Mode-Lookup per Name + mode_plan = mode_3d = None + try: + for dm in DisplayModeDescription.GetDisplayModes(): + try: + n = dm.EnglishName + if n == "Dossier Plan": mode_plan = dm + elif n == "Dossier 3D": mode_3d = dm + except Exception: pass + except Exception as ex: + print("[STARTUP] view-modes: Mode-List:", ex); return + + if mode_plan is None and mode_3d is None: + print("[STARTUP] view-modes: keine Dossier-Modes registriert — skip") + return + + n_set = 0 + try: + for view in doc.Views: + try: + vp = view.ActiveViewport + if vp is None: continue + is_par = bool(vp.IsParallelProjection) + target = mode_plan if is_par else mode_3d + if target is None: continue + try: + vp.DisplayMode = target + n_set += 1 + except Exception as ex: + print("[STARTUP] view-modes set ({}): {}".format( + vp.Name, ex)) + except Exception: pass + try: + doc.Views.Redraw() + except Exception: pass + except Exception as ex: + print("[STARTUP] view-modes iterate:", ex) + + try: + doc.Strings.SetString(_DOC_FLAG_VIEW_MODES, "1") + except Exception: pass + print("[STARTUP] view-modes: {} Viewport(s) gesetzt".format(n_set)) + + def _on_doc_opened(sender, e): """Greift bei jedem geoeffneten Doc nach Rhino-Start. Migration ist idempotent (Flag in doc.Strings).""" @@ -83,6 +148,7 @@ def _on_doc_opened(sender, e): doc = e.Document if hasattr(e, "Document") else Rhino.RhinoDoc.ActiveDoc import panel_base panel_base.migrate_to_dossier(doc) + _assign_default_display_modes(doc) except Exception as ex: print("[STARTUP] _on_doc_opened:", ex) @@ -141,6 +207,11 @@ def _load_all(sender, e): text_editor._ensure_double_click_hook() except Exception as ex: print("[STARTUP] text_editor hook:", ex) + # Display-Modes auf Default fuer aktives Doc setzen (einmalig) + try: + _assign_default_display_modes(Rhino.RhinoDoc.ActiveDoc) + except Exception as ex: + print("[STARTUP] view-modes assign:", ex) # DOSSIERUI Window-Layout — Hinweis fuer manuelles Laden _hint_dossier_ui() # Startup-Timing-Summary 3 Sekunden spaeter (nachdem alle async Idle- diff --git a/rhino/templates/dossier_3d.ini b/rhino/templates/dossier_3d.ini new file mode 100644 index 0000000..da3b3ec --- /dev/null +++ b/rhino/templates/dossier_3d.ini @@ -0,0 +1,323 @@ +[DisplayMode\d0551e72-7e72-4170-b1a4-3d3d3d3d3d3d] +PipelineId=e1eb7363-87f2-4a2b-a861-256e77835369 +SupportsShading=y +SupportsStereo=y +AddToMenu=y +AllowObjectAssignment=y +ShadedPipelineRequired=y +WireframePipelineRequired=y +PipelineLocked=y +Order=-5 +DerivedFrom=00000000-0000-0000-0000-000000000000 +Name=Dossier 3D +XrayAllObjects=n +IgnoreHighlights=n +DisableConduits=n +DisableTransparency=n +BBoxMode=0 +RealtimeDisplayId=00000000-0000-0000-0000-000000000000 +SupportsShadeCmd=y +[DisplayMode\d0551e72-7e72-4170-b1a4-3d3d3d3d3d3d\Lighting] +ShadowIntensity=40 +ShadowClippingRadius=0 +ShadowClippingUsage=0 +PerPixelLighting=n +TransparencyTolerance=40 +ShadowBlur=0 +ShadowBias=10,12,0 +ShowLights=n +UseHiddenLights=n +UseLightColor=n +LightingScheme=2 +Luminosity=0 +AmbientColor=0,0,0 +LightCount=0 +CastShadows=y +ShadowMapSize=2048 +SkylightShadowQuality=4 +NumSamples=4 +ShadowMapType=2 +ShadowBitDepth=32 +ShadowColor=0,0,0 +[DisplayMode\d0551e72-7e72-4170-b1a4-3d3d3d3d3d3d\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-3d3d3d3d3d3d\Objects\Annotations] +DotBorderColor=-1 +ShowText=y +ShowAnnotations=y +DotTextColor=-1 +[DisplayMode\d0551e72-7e72-4170-b1a4-3d3d3d3d3d3d\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-3d3d3d3d3d3d\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-3d3d3d3d3d3d\Objects\Points] +PCSize=2 +ShowPoints=y +PointStyle=51 +PointSize=3 +PCGripStyle=102 +PCGripSize=2 +PCStyle=50 +ShowPointClouds=y +[DisplayMode\d0551e72-7e72-4170-b1a4-3d3d3d3d3d3d\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-3d3d3d3d3d3d\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-3d3d3d3d3d3d\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-3d3d3d3d3d3d\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-3d3d3d3d3d3d\Shading\Material] +BackIsCustom=y +FrontIsCustom=n +UseBackMaterial=y +[DisplayMode\d0551e72-7e72-4170-b1a4-3d3d3d3d3d3d\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-3d3d3d3d3d3d\Shading\Material\Back Material\BitmapTexture] += +[DisplayMode\d0551e72-7e72-4170-b1a4-3d3d3d3d3d3d\Shading\Material\Back Material\EmapTexture] += +[DisplayMode\d0551e72-7e72-4170-b1a4-3d3d3d3d3d3d\Shading\Material\Back Material\TransparencyTexture] += +[DisplayMode\d0551e72-7e72-4170-b1a4-3d3d3d3d3d3d\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-3d3d3d3d3d3d\Shading\Material\Front Material\BitmapTexture] += +[DisplayMode\d0551e72-7e72-4170-b1a4-3d3d3d3d3d3d\Shading\Material\Front Material\EmapTexture] += +[DisplayMode\d0551e72-7e72-4170-b1a4-3d3d3d3d3d3d\Shading\Material\Front Material\TransparencyTexture] += +[DisplayMode\d0551e72-7e72-4170-b1a4-3d3d3d3d3d3d\View settings] +ShowClippingPlanes=n +FlipGlasses=n +AGViewingMode=0 +AGColorMode=0 +StereoParallax=1 +StereoSeparation=1 +StereoModeEnabled=0 +BackgroundBitmap= +GradBotRight=210,210,210 +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=240,240,240 +GradBotLeft=210,210,210 +GradTopLeft=240,240,240 +SolidColor=250,250,250 +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 diff --git a/src/GestaltungApp.jsx b/src/GestaltungApp.jsx index 1b514dd..4a63de1 100644 --- a/src/GestaltungApp.jsx +++ b/src/GestaltungApp.jsx @@ -485,28 +485,10 @@ function SectionBlock({ sel }) { setter={setSectionStyle} /> - {/* Hintergrund (Solid-Fill hinter dem Hatch-Pattern) */} - {!isLayerSource && enabled && ( - <> - -
-
- callSetter({ - backgroundColor: backgroundColor ? null : '#ffffff' - })} /> -
- {backgroundColor && ( - callSetter({ backgroundColor: c })} - /> - )} -
- - )} + {/* Fill — Objekt-Pen (Color/LW/Linetype) als 'Fill' weil dessen + Color in Plan-Mode visuell die Schnittflaeche fuellt. */} + + } @@ -565,8 +547,15 @@ export default function GestaltungApp() { )} - - + {/* PenBlock fuer 2D/Curves oben, fuer 3D innerhalb der + SectionBlock als 'Fill' weiter unten (User-Erfahrung: + ObjektFarbe fuehlt sich wie Section-Fill an). */} + {kind !== '3d' && ( + <> + + + + )} {showSection && (