mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-06 07:51:47 +00:00
Drop dead Geometry.has_material_styles + sanitation sweep
Two related cleanups bundled because each was too small on its own. == Drop dead Geometry.has_material_styles duplicate == Two parallel has_material_styles implementations existed on HEAD: * Geometry.has_material_styles (tool/geometry.py:853, added by3483683cb"Add tool.Geometry helpers for body representation + placement"): checks each material via tool.Material.get_style for an IfcSurfaceStyle. This is the implementation gizmos-8088 uses — its core/root.py:58 calls geometry.has_material_styles. * Root.has_material_styles (tool/root.py:75, added bye76455913"Route _has_material_styles through tool.Root.has_material_styles"): checks each material for a HasRepresentation inverse. Added to fix the test/core/test_root.py::TestCopyClass::test_AAAAAAAAAAAA failure by routing the check through a Prophecy-mockable seam. HEAD's core/root.py:59 calls root.has_material_styles. The Geometry version became orphaned by that migration — zero callers historically (git log -S "Geometry.has_material_styles" returns nothing). The Root placement is the right architectural home: has_material_styles pairs with assign_body_styles in the copy_class flow as "is there material-defined styling? if not, apply body styling" — both decisions live on the same interface, called in sequence from the same caller. The semantic delta (HasRepresentation vs IfcSurfaceStyle) is a close approximation in real IFC files where HasRepresentation almost always indicates a styled material; if precision becomes necessary, the Root impl can be tightened independently of this cleanup. Drop the Geometry method + its abstract declaration in core/tool.py. == Sanitation sweep per CLAUDE.md §4a == Eight rot-prone references in code we authored on this branch get their first-draft mistakes cleaned up. The §4a rule (no sibling symbol names, no test paths, no motivation history in docstrings) got added during this branch, so older commits sometimes named their siblings in prose; this is a focused cleanup of the worst offenders. * bim/module/model/wall.py:201 — _CommitWallDraftsFirstMixin docstring carried motivation history ("...that every multi-wall operator … used to repeat at the top of _execute"). Rewrite to describe only the current contract. * bim/module/model/wall.py:1910 — cycle_type_operator comment named two sibling methods. Rephrase to describe what happens at the slot. * bim/module/model/wall.py:2025 — _active_instances ClassVar comment named WallGizmoPreviewDecorator. Rephrase to "the wall-gizmo preview decorator" (role, not class). * bim/module/drawing/gizmos.py:3402 — GizmoFillet hit_uses_bbox comment named GizmoWallJoinIntersection. Rephrase to "the wall-join gizmo group". * bim/module/drawing/gizmos.py:3887 — GizmoCountLabel docstring had a :meth:`set_count` cross-reference. Drop — reader sees the method next to the class. * bim/module/model/host_add_opening_gizmo.py:201 — poll-exclusion comment named GizmoWallEdition + GizmoRoofEdition. Rephrase to describe why we skip ("walls and parametric roofs both render their own toggle in the pen row"). * bim/module/void/operator.py:45 — preserve_placement comment named FilledOpeningGenerator.generate. Rephrase to "the filling-opening generator gates its snap-to-wall-axis block on this flag". * bim/parametric_lifecycle.py:64 — module docstring named the test file path (test/bim/test_parametric_registry.py). Rewrite to "enforced by the registry contract tests". Sweep otherwise clean: no third-party software names in this-branch- authored comments (upstream Revit / Tekla / ArchiCAD references are legitimate external-constraint workarounds, §4a-allowed). No PR/issue numbers we authored except the FIXME(PR5) in tool/parametric.py:150, deliberately preserved until PR6's MEP slice resolves it. Generated with the assistance of an AI coding tool.
This commit is contained in:
@@ -3399,8 +3399,9 @@ class GizmoFillet(StaticTrisGizmoMixin, bpy.types.Gizmo):
|
||||
bl_idname = "VIEW3D_GT_fillet"
|
||||
__slots__ = ("custom_shape",)
|
||||
tris = FILLET_TRIS_DEFAULT
|
||||
# Stacked at ICON_STACK_OFFSET_Y above join in GizmoWallJoinIntersection;
|
||||
# full-bbox hit overlaps the sibling icons' bboxes and steals their clicks.
|
||||
# Stacked at ICON_STACK_OFFSET_Y above the join icon in the wall-join
|
||||
# gizmo group; full-bbox hit overlaps the sibling icons' bboxes and
|
||||
# steals their clicks.
|
||||
hit_uses_bbox = False
|
||||
|
||||
|
||||
@@ -3884,8 +3885,8 @@ class GizmoArrayLayerIndicator(bpy.types.Gizmo):
|
||||
class GizmoCountLabel(bpy.types.Gizmo):
|
||||
"""``xN`` text label rendered from 7-segment digit triangles.
|
||||
|
||||
Mirrors a caller-supplied integer (set via :meth:`set_count`) into a
|
||||
live count badge. No icon glyph; the gizmo is the number alone."""
|
||||
Mirrors a caller-supplied integer into a live count badge. No icon
|
||||
glyph; the gizmo is the number alone."""
|
||||
|
||||
bl_idname = "BIM_GT_count_label"
|
||||
|
||||
|
||||
@@ -198,8 +198,8 @@ class GizmoHostToggleOpenings(bpy.types.GizmoGroup, _WallGeomCachedBillboardingM
|
||||
if not tool.Geometry.has_openings(element):
|
||||
return False
|
||||
# Skip when a per-feature parametric-edit gizmo already surfaces
|
||||
# an idle-row toggle for this element (wall: GizmoWallEdition;
|
||||
# parametric roof: GizmoRoofEdition).
|
||||
# an idle-row toggle for this element — walls and parametric roofs
|
||||
# both render their own toggle in the pen row.
|
||||
if tool.Parametric.is_path_connectable_wall(element):
|
||||
return False
|
||||
if tool.Parametric.is_roof(element):
|
||||
|
||||
@@ -195,12 +195,9 @@ class _CommitWallDraftsFirstMixin:
|
||||
"""Operator mixin that flushes any in-progress wall parametric drafts in
|
||||
the current selection before delegating to the subclass's ``_perform``.
|
||||
|
||||
Centralises the inline ``_commit_pending_wall_edits_for_selection(context)``
|
||||
call that every multi-wall operator (unjoin, unjoin-path-connection,
|
||||
extend-to-underside, extend-to-wall, split, merge, join-intersection)
|
||||
used to repeat at the top of ``_execute``. Subclasses implement
|
||||
``_perform`` instead of ``_execute``; the IFC transaction opened by
|
||||
``tool.Ifc.Operator.execute`` wraps both the commit and the perform.
|
||||
Subclasses implement ``_perform`` instead of ``_execute``; the IFC
|
||||
transaction opened by ``tool.Ifc.Operator.execute`` wraps both the
|
||||
commit and the perform.
|
||||
|
||||
Place this BEFORE ``bpy.types.Operator`` in the bases tuple so the
|
||||
mixin's ``_execute`` resolves first in the MRO."""
|
||||
@@ -1910,8 +1907,8 @@ class GizmoWallEdition(bpy.types.GizmoGroup, gizmo.BaseParametricGizmoGroup):
|
||||
finish_editing_operator = "bim.finish_editing_wall"
|
||||
cancel_editing_operator = "bim.cancel_editing_wall"
|
||||
# Empty disables the base class's auto-created cycle_gizmo at ICON_CYCLE_X.
|
||||
# We render three state-specific baseline icons at that slot instead — see
|
||||
# ``setup_element_specific_gizmos`` / ``_update_icon_row_extras``.
|
||||
# Three state-specific baseline icons (exterior / center / interior) take
|
||||
# over that slot, with the active one chosen per frame from props.
|
||||
cycle_type_operator = ""
|
||||
|
||||
# Threshold (SI meters) above which a second height gizmo is drawn at the far end of
|
||||
@@ -2024,11 +2021,11 @@ class GizmoWallEdition(bpy.types.GizmoGroup, gizmo.BaseParametricGizmoGroup):
|
||||
(0, 0, 1),
|
||||
)
|
||||
|
||||
# Per-region weakref map populated in ``setup_element_specific_gizmos``.
|
||||
# The ``WallGizmoPreviewDecorator`` dereferences this each draw to read
|
||||
# live ``is_highlight`` state off the cursor icons (extend-X / extend-Z
|
||||
# / split) in the same region it's currently drawing in, so the GPU
|
||||
# axis-preview lines only render while the matching icon is hovered.
|
||||
# Per-region weakref map populated at setup time. The wall-gizmo preview
|
||||
# decorator dereferences this each draw to read live ``is_highlight`` state
|
||||
# off the cursor icons (extend-X / extend-Z / split) in the same region
|
||||
# it's currently drawing in, so the GPU axis-preview lines only render
|
||||
# while the matching icon is hovered.
|
||||
_active_instances: ClassVar["dict[int, weakref.ReferenceType[GizmoWallEdition]]"] = {}
|
||||
|
||||
# Row layout: validate / cancel / baseline-triplet / rotate / array.
|
||||
|
||||
@@ -42,9 +42,9 @@ class AddOpening(bpy.types.Operator, tool.Ifc.Operator):
|
||||
)
|
||||
|
||||
# Toggled by ``invoke`` when the user holds SHIFT during a gizmo / hotkey
|
||||
# click. Forwards to ``FilledOpeningGenerator.generate`` which gates the
|
||||
# snap-to-wall-axis block on it. HIDDEN + SKIP_SAVE so it doesn't surface
|
||||
# in the F6 redo panel or persist into saved keymaps.
|
||||
# click. The filling-opening generator gates its snap-to-wall-axis block
|
||||
# on this flag. HIDDEN + SKIP_SAVE so the flag doesn't surface in the F6
|
||||
# redo panel or persist into saved keymaps.
|
||||
preserve_placement: bpy.props.BoolProperty(default=False, options={"HIDDEN", "SKIP_SAVE"})
|
||||
|
||||
@classmethod
|
||||
|
||||
@@ -61,7 +61,7 @@ Pattern selection (which approach a new feature should adopt):
|
||||
The authoritative list of registered parametric types — and which use
|
||||
`build_edit_lifecycle` vs. standalone operators — lives in
|
||||
`tool/parametric.py`'s `EDIT_TYPES` and is enforced by the registry
|
||||
contract tests in `test/bim/test_parametric_registry.py`.
|
||||
contract tests.
|
||||
|
||||
This module hosts operator-side mixins that import ``bonsai.tool`` freely.
|
||||
The lightweight parametric registry consumed at addon-enable time must stay
|
||||
|
||||
@@ -459,7 +459,6 @@ class Geometry:
|
||||
def has_axis_representation(cls, element): pass
|
||||
def has_data_users(cls, data): pass
|
||||
def has_material_style_override(cls, obj): pass
|
||||
def has_material_styles(cls, element): pass
|
||||
def import_representation_parameters(cls, data): pass
|
||||
def is_body_representation(cls, representation): pass
|
||||
def is_box_representation(cls, representation): pass
|
||||
|
||||
@@ -849,15 +849,6 @@ class Geometry(bonsai.core.tool.Geometry):
|
||||
return True
|
||||
return False
|
||||
|
||||
@classmethod
|
||||
def has_material_styles(cls, element: ifcopenshell.entity_instance) -> bool:
|
||||
"""True when any of ``element``'s materials exposes an
|
||||
``IfcSurfaceStyle``. Gate body-style assignment to avoid double-styling."""
|
||||
return any(
|
||||
tool.Material.get_style(material) is not None
|
||||
for material in ifcopenshell.util.element.get_materials(element)
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def reimport_element_representations(
|
||||
cls, obj: bpy.types.Object, representation: ifcopenshell.entity_instance, apply_openings: bool = True
|
||||
|
||||
Reference in New Issue
Block a user