Styles: default pen for new objects + csharp build doc

Gestaltung panel now shows pen controls (color, lineweight, linetype)
when nothing is selected. Settings persist in sticky and are stamped
onto every newly drawn object (curves, text, hatch, dims — not 3D
solids or DOSSIER element geometry) via the existing AddRhinoObject
listener. Active state shown with badge; resets by switching all back
to "Nach Ebene".

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

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-06-07 02:00:47 +02:00
parent e8da519d29
commit d558fac2c3
3 changed files with 243 additions and 11 deletions
+130 -1
View File
@@ -189,6 +189,94 @@ def _hex_to_color(h):
return Drawing.Color.FromArgb(int(h[0:2], 16), int(h[2:4], 16), int(h[4:6], 16))
# Default-Pen ("Stift fuer neue Objekte"): wird in on_add auf frisch
# gezeichnete Kurven gestempelt, solange aktiv. Persistiert in Sticky und
# gilt bis der User wieder auf "Nach Ebene" zurueckstellt. Wird vom selben
# UI-Block gesetzt wie der Selektions-Pen — nur ohne Auswahl (siehe Setter).
_DEFAULT_PEN_KEY = "_dossier_default_pen"
def _default_pen():
p = sc.sticky.get(_DEFAULT_PEN_KEY)
if not isinstance(p, dict):
p = {}
return {
"colorSource": p.get("colorSource", "layer"),
"color": p.get("color"),
"lwSource": p.get("lwSource", "layer"),
"lw": p.get("lw"),
"linetypeSource": p.get("linetypeSource", "layer"),
"linetype": p.get("linetype"),
}
def _set_default_pen(**changes):
p = _default_pen()
p.update(changes)
sc.sticky[_DEFAULT_PEN_KEY] = p
def _default_pen_active(pen=None):
p = pen or _default_pen()
return (p["colorSource"] == "object" or p["lwSource"] == "object"
or p["linetypeSource"] == "object")
def _has_selection(doc):
return bool(list(doc.Objects.GetSelectedObjects(False, False)))
def _apply_pen_to_attrs(doc, a, pen):
"""Stempelt den aktiven Default-Pen auf eine Attribut-Kopie (in-place)."""
if pen["colorSource"] == "object":
a.ColorSource = _FROM_OBJECT
if pen["color"]:
a.ObjectColor = _hex_to_color(pen["color"])
_sync_plot_color_to_display(a)
if pen["lwSource"] == "object" and pen["lw"] is not None:
a.PlotWeightSource = _LW_FROM_OBJECT
try:
import massstab
massstab.write_plotweight(doc, a, float(pen["lw"]))
except Exception:
a.PlotWeight = float(pen["lw"])
if pen["linetypeSource"] == "object" and pen["linetype"]:
idx = -1
try: idx = doc.Linetypes.Find(pen["linetype"], True)
except Exception: idx = -1
if idx >= 0:
a.LinetypeSource = _LT_FROM_OBJECT
a.LinetypeIndex = idx
def _new_object_pen_summary(doc, pen):
"""PenBlock-kompatibles Objekt fuer den leeren Panel-Zustand: zeigt den
aktiven Default-Pen, "Nach Ebene"-Vorschau aus der aktuellen Ebene."""
cur = doc.Layers.CurrentLayer
layer_color = _color_to_hex(cur.Color)
try:
import massstab as _ms
layer_lw = round(_ms.read_plotweight(cur), 4)
except Exception:
layer_lw = round(cur.PlotWeight, 4)
layer_lt = _linetype_name(doc, cur.LinetypeIndex)
return {
"colorSource": pen["colorSource"],
"color": pen["color"] or layer_color,
"layerColor": layer_color,
"lwSource": pen["lwSource"],
"lw": pen["lw"] if pen["lw"] is not None else layer_lw,
"layerLw": layer_lw,
"linetypeSource": pen["linetypeSource"],
"linetype": pen["linetype"] or layer_lt,
"layerLinetype": layer_lt,
"linetypes": _all_linetypes(doc),
"layerName": _safe_layer_label(doc, cur, doc.Layers.CurrentLayerIndex),
"geometryKind": "curveOpen",
"active": _default_pen_active(pen),
}
def _force_load_linetypes(doc):
"""Rhinos Linetype-Tabelle wird lazy initialisiert — wir triggern es."""
# 1) Eingebaute Methode (falls present)
@@ -840,6 +928,7 @@ def _selection_summary(doc):
objs = list(doc.Objects.GetSelectedObjects(False, False))
base = {"count": 0, "linetypes": _all_linetypes(doc), "hatchPatterns": _all_hatch_patterns(doc)}
if not objs:
base["newObjectPen"] = _new_object_pen_summary(doc, _default_pen())
return base
color_sources, colors = set(), set()
@@ -1238,6 +1327,12 @@ class GestaltungBridge(panel_base.BaseBridge):
self._send_selection()
def _set_color_source(self, source, color_hex):
doc = Rhino.RhinoDoc.ActiveDoc
if not _has_selection(doc):
_set_default_pen(colorSource=source,
color=(color_hex if source == "object" else None))
self._send_selection()
return
col = _hex_to_color(color_hex) if (source == "object" and color_hex) else None
def m(a, _obj):
if source == "layer":
@@ -1255,11 +1350,16 @@ class GestaltungBridge(panel_base.BaseBridge):
# Print-Mode-aware: bei aktivem Print-View werden PlotWeights skaliert.
# write_plotweight() kuemmert sich um beides (Original-Speicherung +
# Skalierungs-Multiplier).
doc = Rhino.RhinoDoc.ActiveDoc
if not _has_selection(doc):
_set_default_pen(lwSource=source,
lw=(lw if source == "object" else None))
self._send_selection()
return
try:
import massstab
except Exception:
massstab = None
doc = Rhino.RhinoDoc.ActiveDoc
def m(a, _obj):
if source == "layer":
a.PlotWeightSource = _LW_FROM_LAYER
@@ -1316,6 +1416,11 @@ class GestaltungBridge(panel_base.BaseBridge):
def _set_linetype_source(self, source, name):
doc = Rhino.RhinoDoc.ActiveDoc
if not _has_selection(doc):
_set_default_pen(linetypeSource=source,
linetype=(name if source == "object" else None))
self._send_selection()
return
idx = -1
if source == "object" and name:
try:
@@ -2012,6 +2117,30 @@ def _install_selection_listener(bridge):
# Waehrend Move/Rotate werden Sub-Volumen erzeugt die kein Auto-Fill
# brauchen, und elemente uebernimmt die Coupling.
if sc.sticky.get("_dossier_user_transform_active"): return
# 2b) Default-Pen ("Stift fuer neue Objekte") auf frisch gezeichnete
# 2D-Objekte stempeln (Kurven, Text, Hatch, Bemassung ...), solange
# aktiv. Ausgeschlossen: 3D-Volumen (Pen ist ein 2D-Begriff) und
# DOSSIER-Element-Geometrie (dossier_element_type), die elemente.py setzt.
pen = _default_pen()
g = obj.Geometry
is_3d = isinstance(g, (rg.Brep, rg.Extrusion, rg.Mesh, rg.SubD))
if _default_pen_active(pen) and g is not None and not is_3d:
try: dossier_type = obj.Attributes.GetUserString("dossier_element_type") or ""
except Exception: dossier_type = ""
if not dossier_type:
try:
a = obj.Attributes.Duplicate()
_apply_pen_to_attrs(doc, a, pen)
_processing.add(obj.Id)
try:
doc.Objects.ModifyAttributes(obj, a, True)
finally:
_processing.discard(obj.Id)
doc.Views.Redraw()
except Exception as ex:
print("[STYLES] on_add default-pen:", ex)
try:
ok = _apply_ebene_fill(doc, obj)
except Exception as ex: