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:
+130
-1
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user