# Bonsai Add-on Source Code Structure - In-Depth Analysis **Date:** February 16, 2026 **Scope:** Complete architectural analysis of the Bonsai (formerly BlenderBIM) Blender add-on source code --- ## Executive Summary Bonsai is a comprehensive Blender add-on that transforms Blender into a native IFC authoring platform for Building Information Modeling. The codebase is structured as a highly modular Python application with clear separation between Blender-agnostic core logic, Blender-specific implementation, and UI components. The source code follows a domain-driven design with over 50+ specialized modules covering all aspects of BIM workflows. --- ## 1. Top-Level Directory Structure ### 1.1 Root Organization ``` src/bonsai/ ├── bonsai/ # Main add-on package │ ├── __init__.py # Blender add-on entry point and registration │ ├── core/ # Blender-agnostic core logic │ ├── tool/ # Blender-specific shared functionality │ ├── bim/ # Blender-specific UI and operators │ ├── libs/ # Static assets and auxiliary libraries │ ├── wheels/ # Python dependencies (bundled) │ └── schema/ # IFC schema definitions (EXPRESS) ├── docs/ # Sphinx documentation ├── test/ # Test suite └── Makefile # Build and packaging scripts ``` ### 1.2 Key Characteristics - **Location:** Distributed as add-on in Blender's add-ons directory - **Size:** ~50+ modules, thousands of files - **Language:** Pure Python (no compilation required) - **Blender Version Support:** 3.6, 4.0, 4.1, 4.2+ (rolling support) - **Python Version:** 3.9, 3.10, 3.11, 3.12 (matches Blender's Python) --- ## 2. Core Architecture Layers ### 2.1 Three-Tier Architecture ``` ┌─────────────────────────────────────────────────┐ │ bim/ (UI Layer) │ │ - Operators (user actions) │ │ - UI panels and properties │ │ - Blender event handlers │ └─────────────────────────────────────────────────┘ ↓↑ ┌─────────────────────────────────────────────────┐ │ tool/ (Integration Layer) │ │ - Blender API wrappers │ │ - State management │ │ - Blender-IFC bridge │ └─────────────────────────────────────────────────┘ ↓↑ ┌─────────────────────────────────────────────────┐ │ core/ (Business Logic) │ │ - Pure IFC operations │ │ - Domain logic (Blender-independent) │ │ - Uses ifcopenshell API directly │ └─────────────────────────────────────────────────┘ ``` **Design Philosophy:** - **core/**: Can be unit tested without Blender - **tool/**: Provides abstraction over Blender's complex APIs - **bim/**: Handles all Blender-specific UI and registration --- ## 3. The core/ Directory - Business Logic Layer ### 3.1 Purpose and Structure The `core/` directory contains Blender-agnostic business logic. Each module typically implements IFC operations that could theoretically run without Blender. **Key Principle:** Functions in `core/` take IFC entities and parameters as input, perform operations using `ifcopenshell`, and return results. They should not import `bpy` (Blender Python API). ### 3.2 Example Core Modules ``` core/ ├── aggregate.py # Aggregate/decomposition relationships ├── attribute.py # IFC attribute manipulation ├── bcf.py # BCF (BIM Collaboration Format) operations ├── boundary.py # Space boundary calculations ├── classification.py # Classification system assignments ├── context.py # Representation context management ├── document.py # Document reference handling ├── drawing.py # 2D drawing generation logic ├── geometry.py # Geometric operations and transformations ├── group.py # IFC group operations ├── material.py # Material and material layer management ├── owner.py # Ownership history tracking ├── pset.py # Property set operations ├── qto.py # Quantity take-off calculations ├── root.py # Root entity creation (walls, slabs, etc.) ├── spatial.py # Spatial decomposition tree operations ├── structural.py # Structural analysis model operations ├── style.py # Visual styling operations ├── type.py # Type/occurrence relationships ├── unit.py # Unit system handling └── void.py # Opening and void operations ``` ### 3.3 Core Module Pattern **Typical Function Signature:** ```python # In core/root.py def create_entity( file: ifcopenshell.file, ifc_class: str, predefined_type: Optional[str] = None, name: Optional[str] = None ) -> ifcopenshell.entity_instance: """ Create a new IFC entity of the specified class. Pure business logic - no Blender dependencies. """ # IFC operations using ifcopenshell entity = file.create_entity(ifc_class) if name: entity.Name = name if predefined_type: entity.PredefinedType = predefined_type return entity ``` **Characteristics:** - Functions are pure or have minimal side effects - Take `ifcopenshell.file` as parameter (not global state) - Return IFC entities or primitive types - Testable without Blender running --- ## 4. The tool/ Directory - Integration Layer ### 4.1 Purpose and Structure The `tool/` directory provides Blender-specific implementations that bridge between Blender and IFC. These are concrete implementations of abstract tool interfaces. **Key Principle:** Tools wrap Blender API complexity and provide clean interfaces to the `bim/` layer. ### 4.2 Tool Modules ``` tool/ ├── __init__.py # Tool registration and factory ├── aggregate.py # Blender collection aggregation ├── blender.py # General Blender utilities ├── boundary.py # Space boundary visualization ├── brick.py # Brick schema integration ├── cad.py # CAD import/export helpers ├── collector.py # Element collection utilities ├── context.py # Blender context helpers ├── debug.py # Debugging utilities ├── diff.py # Model comparison visualization ├── document.py # Document handling in Blender ├── drawing.py # Drawing generation with Blender ├── geometry.py # Geometry creation/manipulation in Blender ├── georeference.py # Georeferencing tools ├── ifc.py # Core IFC file management ├── loader.py # IFC model loading ├── material.py # Material creation in Blender ├── mesh.py # Mesh manipulation ├── model.py # Model state management ├── owner.py # Ownership tracking in Blender ├── profile.py # Profile management ├── project.py # Project setup and management ├── pset.py # Property set UI helpers ├── qto.py # Quantity visualization ├── root.py # Root element creation in Blender ├── search.py # Search and filter functionality ├── selector.py # IFC selector query execution ├── spatial.py # Spatial tree management in Blender ├── style.py # Visual style application ├── structural.py # Structural element visualization ├── surveyor.py # Survey and measurement tools ├── system.py # MEP system management ├── type.py # Type management in Blender └── voider.py # Opening/void creation ``` ### 4.3 Tool Implementation Pattern **Tool Singleton Pattern:** ```python # In tool/ifc.py class Ifc: """Singleton tool for IFC file management.""" @classmethod def get(cls) -> Optional[ifcopenshell.file]: """Get the currently active IFC file.""" # Access IfcStore which maintains the Blender<->IFC link return IfcStore.get_file() @classmethod get_entity(cls, obj: bpy.types.Object) -> Optional[ifcopenshell.entity_instance]: """Get IFC entity associated with Blender object.""" if not obj: return None return IfcStore.get_file().by_id(obj.BIMObjectProperties.ifc_definition_id) @classmethod def get_object(cls, entity: ifcopenshell.entity_instance) -> Optional[bpy.types.Object]: """Get Blender object associated with IFC entity.""" return IfcStore.get_element(entity.id()) ``` **Usage in Operators:** ```python # In bim/module/root/operator.py import bonsai.tool as tool class MyOperator(bpy.types.Operator): def execute(self, context): ifc_file = tool.Ifc.get() # Get IFC file via tool obj = context.active_object element = tool.Ifc.get_entity(obj) # Get IFC entity # ... operate on element ``` ### 4.4 The IfcStore - Central State Manager Located in `bonsai/bim/ifc.py`, the `IfcStore` is the critical singleton that maintains: ```python class IfcStore: """ Central store maintaining the link between Blender and IFC. Singleton pattern - one per Blender session. """ # The active IFC file file: Optional[ifcopenshell.file] = None # Schema being used schema: Optional[ifcopenshell.ifcopenshell_wrapper.schema_definition] = None # Bidirectional mapping: IFC ID <-> Blender Object id_map: Dict[int, bpy.types.Object] = {} guid_map: Dict[str, bpy.types.Object] = {} # Edited objects (for incremental saves) edited_objs: Set[bpy.types.Object] = set() # Session-wide settings last_saved_file: Optional[str] = None last_transaction: Optional[int] = None ``` **Critical Functions:** - `get_file()`: Returns active IFC file - `link_element(element, obj)`: Links IFC entity to Blender object - `unlink_element(element)`: Breaks the link - `get_element(ifc_id)`: Gets Blender object from IFC ID - `execute_ifc_operator(operator)`: Transaction wrapper for IFC operations --- ## 5. The bim/ Directory - UI and Operator Layer ### 5.1 Overall Structure The `bim/` directory is the largest and most complex, containing all Blender-specific UI and operator code. ``` bim/ ├── __init__.py # Module registration ├── ifc.py # IfcStore and core utilities ├── handler.py # Blender event handlers ├── module/ # Feature modules (50+ modules) │ ├── aggregate/ │ ├── boundary/ │ ├── brick/ │ ├── clash/ │ ├── classification/ │ ├── context/ │ ├── cost/ │ ├── document/ │ ├── drawing/ │ ├── geometry/ │ ├── material/ │ ├── model/ │ ├── project/ │ ├── pset/ │ ├── qto/ │ ├── root/ │ ├── sequence/ │ ├── spatial/ │ ├── structural/ │ ├── style/ │ ├── system/ │ ├── type/ │ └── ... (50+ total) ├── data/ # Static data files │ ├── pset/ # Property set templates │ ├── class/ # Classification systems (Uniclass, Omniclass) │ ├── qto/ # Quantity templates │ └── libraries/ # IFC type libraries └── helper.py # UI helper functions ``` ### 5.2 Module Internal Structure Each module follows a consistent internal pattern: ``` bim/module// ├── __init__.py # Module registration ├── operator.py # Blender operators (actions) ├── ui.py # Blender UI panels ├── prop.py # Blender properties (data storage) ├── data.py # Data loading and caching └── workspace.py # (Optional) Workspace-specific UI ``` **Example: The 'root' module** ``` bim/module/root/ ├── __init__.py # Registers operators, UI, properties ├── operator.py # CreateEntity, CopyClass, etc. ├── ui.py # BIM_PT_root panel ├── prop.py # BIMRootProperties └── data.py # RootData class for UI data ``` --- ## 6. Module-by-Module Breakdown ### 6.1 Core Spatial and Structural Modules #### **project** - Project Setup and Management ``` bim/module/project/ ├── operator.py │ - CreateProject: Initialize new IFC project │ - AppendLibraryElement: Add library elements │ - LinkIfc: Link external IFC files │ - UnlinkIfc: Unlink external references │ - LoadProject: Load IFC file into Blender │ - UnloadProject: Close IFC project ├── ui.py │ - BIM_PT_project_info: Project information panel │ - BIM_PT_links: Linked models panel ├── prop.py │ - BIMProjectProperties: Project-level settings └── data.py - ProjectData: Load project information for UI ``` **Key Responsibilities:** - IFC project initialization (IfcProject, IfcSite, IfcBuilding, IfcBuildingStorey hierarchy) - File I/O (open, save, save-as) - External model linking - Project-level metadata --- #### **spatial** - Spatial Decomposition Tree ``` bim/module/spatial/ ├── operator.py │ - AssignContainer: Assign element to spatial container │ - EnableEditingContainer: Edit mode for containers │ - DisableEditingContainer: Exit edit mode │ - CopyToContainer: Copy elements to container │ - SelectContainer: Select all in container │ - SelectSimilarContainer: Select similar elements │ - AddSpace: Add IfcSpace │ - GenerateSpace: Auto-generate spaces │ - ToggleHideSpaces: Show/hide space volumes ├── ui.py │ - BIM_PT_spatial_container: Spatial tree panel │ - BIM_PT_spatial_decomposition: Decomposition panel │ - BIM_UL_spaces: Space list UI ├── prop.py │ - BIMSpatialProperties: Spatial tree settings └── data.py - SpatialData: Load spatial hierarchy for UI ``` **Key Responsibilities:** - Managing the IFC spatial tree (Project > Site > Building > Storey > Space) - Element containment relationships (IfcRelContainedInSpatialStructure) - Space/room generation and management - Spatial filtering and selection **Architecture Note:** Previously used Blender collections directly mapped to IFC spatial tree. Recent refactoring (v0.8+) decoupled collections from spatial tree to improve performance and fix sync bugs. --- #### **root** - Element Creation ``` bim/module/root/ ├── operator.py │ - AssignClass: Assign IFC class to object │ - UnassignClass: Remove IFC class │ - CopyClass: Duplicate IFC element │ - AddInstanceToType: Instance from type │ - EnableEditingType: Edit type definition │ - DisableEditingType: Exit type edit mode ├── ui.py │ - BIM_PT_object_metadata: Object IFC metadata panel │ - BIM_PT_class: IFC class panel ├── prop.py │ - BIMRootProperties: Root element properties └── data.py - RootData: Load root element data ``` **Key Responsibilities:** - Creating IFC entities (IfcWall, IfcSlab, IfcColumn, etc.) - Managing IFC class assignments - Type/occurrence pattern implementation - Entity copying and instancing --- #### **type** - Type Management ``` bim/module/type/ ├── operator.py │ - AssignType: Assign type to occurrence │ - UnassignType: Remove type assignment │ - SelectSimilarType: Select all of same type │ - SelectType: Select type definition │ - DuplicateType: Create new type variant │ - EnableEditingType: Edit type properties ├── ui.py │ - BIM_PT_type: Type management panel │ - BIM_UL_types: Type list UI └── prop.py - BIMTypeProperties: Type-related settings ``` **Key Responsibilities:** - IfcTypeObject management - Type-occurrence relationships - Type library management - Parametric type definitions --- ### 6.2 Geometry and Material Modules #### **geometry** - Geometry Management ``` bim/module/geometry/ ├── operator.py │ - AddRepresentation: Add geometry representation │ - SwitchRepresentation: Change active representation │ - RemoveRepresentation: Delete representation │ - UpdateRepresentation: Sync geometry changes │ - UpdateParametricRepresentation: Update parametric geometry │ - EditObjectPlacement: Transform objects │ - DeriveObjectPlacement: Inherit placement ├── ui.py │ - BIM_PT_geometry: Geometry panel │ - BIM_PT_representations: Representations list │ - BIM_PT_mesh: Mesh editing tools ├── prop.py │ - BIMGeometryProperties: Geometry settings │ - BIMMeshProperties: Mesh-specific properties └── data.py - GeometryData: Load geometry info for UI ``` **Key Responsibilities:** - IFC geometry representation management (Body, Axis, Box, etc.) - Representation context handling (Model, Plan) - Geometric placement (ObjectPlacement, LocalPlacement) - Parametric geometry updates - Mesh <-> IFC geometry synchronization **Architecture Note:** Geometry is bidirectionally synced. Changes in Blender mesh trigger IFC update, and IFC changes update Blender mesh. --- #### **material** - Material Assignment ``` bim/module/material/ ├── operator.py │ - AddMaterial: Create IFC material │ - AssignMaterial: Assign material to element │ - UnassignMaterial: Remove material assignment │ - AddLayer: Add material layer │ - AddProfile: Add material profile │ - AddConstituent: Add material constituent │ - EnableEditingMaterialSetUsage: Edit mode ├── ui.py │ - BIM_PT_materials: Materials panel │ - BIM_PT_material_sets: Material sets (layers/profiles) │ - BIM_UL_materials: Material list ├── prop.py │ - BIMMaterialProperties: Material properties └── data.py - MaterialData: Load material data ``` **Key Responsibilities:** - IfcMaterial creation and management - Material sets (layer sets, profile sets, constituent sets) - Material assignment to elements - Material usage (offsets, directions) - Material styles (surface styles, rendering) --- #### **style** - Visual Styling ``` bim/module/style/ ├── operator.py │ - AddPresentationStyle: Add surface style │ - EditPresentationStyle: Modify style │ - RemovePresentationStyle: Delete style │ - AssignPresentationStyle: Apply to material │ - UnassignPresentationStyle: Remove style ├── ui.py │ - BIM_PT_styles: Styles panel │ - BIM_PT_style_textures: Texture mapping └── prop.py - BIMStyleProperties: Style settings ``` **Key Responsibilities:** - IfcSurfaceStyle creation - Color and texture management - Presentation layer styling - Blender material <-> IFC style synchronization --- ### 6.3 Documentation Modules #### **drawing** - 2D Documentation ``` bim/module/drawing/ ├── operator.py │ - CreateDrawing: Create drawing view │ - CreateSheet: Create sheet │ - ActivateDrawing: Switch to drawing view │ - OpenDrawing: Open in image editor │ - GenerateDrawing: Render drawing │ - AddDrawingStyle: Add drawing style │ - AddAnnotation: Add text/dimension │ - EditText: Modify text annotation ├── ui.py │ - BIM_PT_drawings: Drawings panel │ - BIM_PT_sheets: Sheets panel │ - BIM_PT_schedules: Schedule tables │ - BIM_PT_references: Reference drawings ├── prop.py │ - BIMDrawingProperties: Drawing settings │ - BIMAnnotationProperties: Annotation settings └── data.py - DrawingData: Load drawing information ``` **Key Responsibilities:** - 2D drawing view creation (plans, sections, elevations) - Sheet layout and title blocks - Annotations (text, dimensions, leaders, tags) - Drawing generation (SVG output with semantic IFC data) - Schedule generation from IFC data - Cut plane management - Drawing styles and line weights **Technical Implementation:** - Uses Blender camera as cut plane - Projects 3D geometry to 2D - Exports to SVG with embedded IFC metadata - Supports multiple representation contexts (PLAN_VIEW, SECTION_VIEW, etc.) --- #### **document** - Document Management ``` bim/module/document/ ├── operator.py │ - AddDocument: Add document reference │ - EditDocument: Modify document info │ - RemoveDocument: Delete reference │ - AssignDocument: Link document to element │ - UnassignDocument: Remove link │ - OpenDocumentUri: Open external file ├── ui.py │ - BIM_PT_documents: Documents panel │ - BIM_UL_documents: Document list └── prop.py - BIMDocumentProperties: Document settings ``` **Key Responsibilities:** - IfcDocumentInformation management - Document references (PDFs, drawings, specs) - Document assignments to elements - URI handling for external documents --- ### 6.4 Data and Properties Modules #### **pset** - Property Sets ``` bim/module/pset/ ├── operator.py │ - AddPset: Add property set │ - RemovePset: Delete property set │ - EditPset: Enable edit mode │ - EnablePsetEditing: Edit properties │ - DisablePsetEditing: Exit edit mode │ - AddQto: Add quantity set │ - CopyPropertyToSelection: Bulk edit │ - GuessQuantity: Auto-calculate quantities ├── ui.py │ - BIM_PT_object_psets: Property sets panel │ - BIM_PT_object_qtos: Quantities panel │ - BIM_UL_psets: Property set list ├── prop.py │ - BIMPsetProperties: Pset settings └── data.py - PsetData: Load property data - MaterialPsetsData: Material properties - ProfilePsetsData: Profile properties ``` **Key Responsibilities:** - Property set (Pset) management - Quantity set (Qto) management - Property templates (PsetTemplate) - Bulk property editing - Property inheritance from types **Architecture Note:** Property data is lazily loaded and cached in `data.py` classes for performance. --- #### **qto** - Quantity Take-Off ``` bim/module/qto/ ├── calculator.py # Quantity calculation algorithms ├── operator.py │ - CalculateEdgeLengths: Compute edge lengths │ - CalculateFaceAreas: Compute surface areas │ - CalculateObjectVolumes: Compute volumes │ - CalculateAllQuantities: Full QTO │ - AssignQuantity: Manual quantity input ├── ui.py │ - BIM_PT_qto: QTO panel │ - BIM_PT_quantity_calculator: Calculator tools └── prop.py - BIMQtoProperties: QTO settings ``` **Key Responsibilities:** - Geometric quantity calculation (length, area, volume) - Opening area calculation - Space boundary calculations - Gross/net area computations - Advanced geometric calculations (footprint, side area) **Technical Implementation:** - Uses Blender's mathutils and BVHTree for geometric operations - Handles opening subtraction - Considers material layers - Supports angle-based filtering for specific surfaces --- #### **classification** - Classification Systems ``` bim/module/classification/ ├── operator.py │ - LoadClassificationLibrary: Load system (Uniclass, Omniclass) │ - AddClassification: Add classification │ - RemoveClassification: Remove classification │ - EnableEditingClassification: Edit mode ├── ui.py │ - BIM_PT_classification: Classification panel │ - BIM_UL_classifications: Classification list └── prop.py - BIMClassificationProperties: Classification settings ``` **Key Responsibilities:** - Classification system management - Classification assignment to elements - Support for multiple classification systems - Classification hierarchy browsing --- ### 6.5 4D/5D BIM Modules #### **sequence** - 4D Construction Scheduling ``` bim/module/sequence/ ├── operator.py │ - AddWorkPlan: Create work plan │ - AddWorkSchedule: Create schedule │ - AddTask: Add task to schedule │ - AssignSequence: Link task to element │ - UnassignSequence: Remove link │ - CalculateCriticalPath: CPM analysis │ - VisualiseWorkSchedule: 4D animation │ - ImportP6: Import Primavera P6 │ - ImportMSP: Import MS Project │ - ExportMSP: Export to MS Project ├── ui.py │ - BIM_PT_work_plans: Work plans panel │ - BIM_PT_work_schedules: Schedules panel │ - BIM_PT_tasks: Task tree panel │ - BIM_PT_task_calendar: Calendar panel └── prop.py - BIMWorkPlanProperties: Work plan settings - BIMWorkScheduleProperties: Schedule settings ``` **Key Responsibilities:** - Work plan and schedule creation - Task hierarchy (WBS - Work Breakdown Structure) - Task sequences and dependencies - Construction simulation (4D BIM) - Critical path analysis - P6/MSP import/export - Task-element relationships --- #### **cost** - 5D Cost Management ``` bim/module/cost/ ├── operator.py │ - AddCostSchedule: Create cost schedule │ - AddCostItem: Add cost item │ - AssignCostValue: Assign cost to element │ - CalculateCostSchedule: Compute totals │ - ImportCostSchedule: Import BC3/budget │ - ExportCostSchedule: Export BC3 │ - CopySchedule: Duplicate schedule ├── ui.py │ - BIM_PT_cost_schedules: Cost schedules panel │ - BIM_PT_cost_items: Cost breakdown panel │ - BIM_UL_cost_items: Cost tree └── prop.py - BIMCostProperties: Cost settings ``` **Key Responsibilities:** - Cost schedule creation - Cost breakdown structure (CBS) - Cost item hierarchy - Quantity-cost relationships - Formula-based calculations - BC3 format support (Spanish construction standard) - Budget export and reporting --- ### 6.6 MEP and Systems Modules #### **system** - Distribution Systems ``` bim/module/system/ ├── operator.py │ - AddSystem: Create distribution system │ - AssignSystem: Assign element to system │ - UnassignSystem: Remove from system │ - SelectSystemElements: Select all in system │ - ShowPorts: Visualize connection ports │ - ConnectPort: Connect two ports │ - DisconnectPort: Disconnect ports ├── ui.py │ - BIM_PT_systems: Systems panel │ - BIM_UL_systems: System list └── prop.py - BIMSystemProperties: System settings ``` **Key Responsibilities:** - IfcSystem creation (electrical, HVAC, plumbing) - Element-to-system assignment - Port and connectivity management - System flow analysis - MEP network visualization --- ### 6.7 Analysis and Coordination Modules #### **clash** - Clash Detection ``` bim/module/clash/ ├── operator.py │ - AddClashSource: Add clash source │ - SelectClashSource: Select source elements │ - ExecuteIfcClash: Run clash detection │ - SelectClashResults: Select clashing elements │ - ImportBCF: Import clash report │ - ExportBCF: Export clash report ├── ui.py │ - BIM_PT_clash_manager: Clash manager panel │ - BIM_UL_clash_sets: Clash sets list └── prop.py - BIMClashProperties: Clash detection settings ``` **Key Responsibilities:** - Clash detection setup - Clash source/target definition - Integration with IfcClash library - Clash visualization in 3D viewport - BCF integration for clash reporting --- #### **bcf** - BIM Collaboration Format ``` bim/module/bcf/ ├── operator.py │ - NewBCFProject: Create BCF project │ - LoadBCFProject: Load BCF file │ - AddBCFTopic: Add issue topic │ - EditBCFTopic: Modify topic │ - AddBCFViewpoint: Capture viewpoint │ - GoToBCFViewpoint: Navigate to viewpoint │ - ActivateBCFViewpoint: Apply camera/visibility ├── ui.py │ - BIM_PT_bcf: BCF panel │ - BIM_UL_topics: Topic list └── prop.py - BCFProperties: BCF settings ``` **Key Responsibilities:** - BCF XML/BCFzip file handling - Issue/topic management - Viewpoint capture and navigation - Comment threading - Integration with external BCF managers --- #### **structural** - Structural Analysis ``` bim/module/structural/ ├── operator.py │ - AddStructuralAnalysisModel: Create analysis model │ - EnableEditingStructuralAnalysisModels: Edit mode │ - AssignStructuralAnalysisMember: Assign member │ - AddStructuralMemberConnection: Add connection │ - AddStructuralLoad: Define load │ - VisualizeStructuralLoad: Show loads │ - CalculateStructuralAnalysis: Run analysis ├── ui.py │ - BIM_PT_structural_analysis: Analysis panel │ - BIM_PT_structural_loads: Loads panel └── prop.py - BIMStructuralProperties: Structural settings ``` **Key Responsibilities:** - IfcStructuralAnalysisModel creation - Structural member definitions - Load case and combination management - Load visualization (arrows, colors) - Connection and boundary conditions - Results visualization --- ### 6.8 Specialized Domain Modules #### **brick** - Brick Schema Integration ``` bim/module/brick/ ├── operator.py │ - LoadBrickProject: Load Brick model │ - NewBrickFile: Create Brick file │ - AddBrick: Add Brick entity │ - AssignBrickReference: Link IFC to Brick ├── ui.py │ - BIM_PT_brick: Brick panel └── prop.py - BrickProperties: Brick settings ``` **Key Responsibilities:** - Brick schema integration (IoT/smart building metadata) - IFC-Brick relationship mapping - Brick namespace management --- #### **fm** - Facility Management ``` bim/module/fm/ ├── operator.py │ - AddAsset: Create asset │ - ExportFMData: Export FM database │ - ImportCOBie: Import COBie spreadsheet │ - ExportCOBie: Export COBie ├── ui.py │ - BIM_PT_fm: FM panel └── prop.py - BIMFMProperties: FM settings ``` **Key Responsibilities:** - Asset and equipment management - COBie (Construction Operations Building Information Exchange) support - Maintenance schedule data - Warranty and document tracking --- ### 6.9 Advanced Geometry Modules #### **model** - Advanced Modeling Tools ``` bim/module/model/ ├── operator.py │ - AddWall: Wall modeling tool │ - AddSlab: Slab modeling tool │ - AddDoor: Door placement tool │ - AddWindow: Window placement tool │ - AddStair: Parametric stair generator │ - AddRoof: Parametric roof generator │ - JoinWalls: Wall joining │ - AlignWall: Wall alignment │ - FlipWall: Flip wall direction │ - SplitWall: Split at point ├── ui.py │ - BIM_PT_wall_tool: Wall tool panel │ - BIM_PT_slab_tool: Slab tool panel │ - Various tool panels └── prop.py - BIMModelProperties: Modeling settings - BIMWallProperties: Wall tool settings - BIMSlabProperties: Slab tool settings ``` **Key Responsibilities:** - Interactive modeling tools with real-time preview - Parametric element generation - Snap and alignment features - Polyline drawing - Angle and axis constraints - Parametric stairs, roofs, railings **Technical Implementation:** - Modal operators with draw handlers - Real-time viewport feedback - Snapping to grid, objects, axes - Preview geometry generation --- #### **void** - Openings and Voids ``` bim/module/void/ ├── operator.py │ - AddFilling: Add door/window to opening │ - AddOpening: Create opening in wall │ - EditOpening: Modify opening │ - RemoveOpening: Delete opening │ - CloneOpening: Duplicate opening │ - FlipFill: Flip door/window direction ├── ui.py │ - BIM_PT_voiding: Voiding panel └── prop.py - BIMVoidProperties: Void settings ``` **Key Responsibilities:** - IfcOpeningElement creation - Void-element relationships (IfcRelVoidsElement) - Filling relationships (IfcRelFillsElement) - Opening propagation through layers - Parametric opening adjustments --- ### 6.10 Utility and Helper Modules #### **search** - Search and Filter ``` bim/module/search/ ├── operator.py │ - ActivateSearch: Open search interface │ - ColourByProperty: Color-code by property │ - SelectByProperty: Filter selection │ - SelectGlobalId: Find by GUID │ - SelectAttribute: Select by attribute value │ - SelectPset: Select by property value │ - FilterModelElements: Advanced filtering ├── ui.py │ - BIM_PT_search: Search panel └── prop.py - BIMSearchProperties: Search settings ``` **Key Responsibilities:** - IFC selector query language - Property-based filtering - Color-coding by attributes - Bulk selection tools - GUID search - Spatial filtering **Selector Syntax Examples:** ``` .IfcWall # All walls .IfcWall[Name*="External"] # Walls with "External" in name .IfcWall .IfcWindow # All windows in walls .IfcWall[IsExternal=TRUE] # External walls #12345 # By IFC ID {ABC123...} # By GUID ``` --- #### **debug** - Development Tools ``` bim/module/debug/ ├── operator.py │ - PrintIfcFile: Print IFC to console │ - ValidateIfcFile: Run IFC validation │ - SelectHighPolygonMeshes: Performance check │ - RewindInspector: Inspect undo history │ - InspectPurge: See purgeable data ├── ui.py │ - BIM_PT_debug: Debug panel └── prop.py - BIMDebugProperties: Debug settings ``` **Key Responsibilities:** - Development and debugging utilities - Performance profiling - IFC validation - Undo/redo inspection - Memory analysis --- ## 7. Property System Architecture ### 7.1 Blender Property Groups Each module defines property groups to store UI state and settings: ```python # In bim/module/root/prop.py class BIMRootProperties(PropertyGroup): """Properties stored per scene for root module.""" ifc_class: EnumProperty( items=get_ifc_class_items, name="IFC Class", description="The IFC class to assign" ) ifc_predefined_type: EnumProperty( items=get_predefined_type_items, name="Predefined Type" ) relating_type: PointerProperty( type=bpy.types.Object, name="Type", description="The type definition" ) ``` **Storage Locations:** - `Scene.BIMRootProperties`: Scene-level settings - `Object.BIMObjectProperties`: Per-object IFC data - `Material.BIMMaterialProperties`: Per-material IFC data - `Camera.BIMCameraProperties`: Per-camera settings ### 7.2 The Critical BIMObjectProperties Every Blender object linked to IFC has these properties: ```python class BIMObjectProperties(PropertyGroup): """Core properties linking Blender object to IFC entity.""" ifc_definition_id: IntProperty( name="IFC Definition ID", description="The ID of the IFC entity" ) is_reassigning_class: BoolProperty( name="Is Reassigning Class", description="Flag for class reassignment operation" ) has_box_representation: BoolProperty( name="Has Box Representation" ) material_type: EnumProperty( name="Material Type", items=[ ('IfcMaterial', 'IfcMaterial', ''), ('IfcMaterialLayerSet', 'Layer Set', ''), ('IfcMaterialProfileSet', 'Profile Set', ''), ] ) ``` **Critical Field:** `ifc_definition_id` is the primary key linking Blender object to IFC entity. --- ## 8. Operator Architecture ### 8.1 Operator Pattern All operators follow Blender's operator pattern: ```python # In bim/module/root/operator.py class AssignClass(bpy.types.Operator, tool.Ifc.Operator): """Assign IFC Class""" bl_idname = "bim.assign_class" bl_label = "Assign IFC Class" bl_options = {"REGISTER", "UNDO"} obj: StringProperty() # Optional parameter ifc_class: StringProperty() predefined_type: StringProperty() should_add_representation: BoolProperty(default=True) def _execute(self, context): """ Implementation method called by tool.Ifc.Operator wrapper. Automatically wrapped in IFC transaction. """ # Get parameters from UI or operator properties obj = bpy.data.objects.get(self.obj) or context.active_object ifc_class = self.ifc_class or context.scene.BIMRootProperties.ifc_class # Call core business logic core.assign_class( tool.Ifc, tool.Collector, tool.Root, obj=obj, ifc_class=ifc_class, predefined_type=self.predefined_type, should_add_representation=self.should_add_representation, context=context ) return {"FINISHED"} ``` ### 8.2 The tool.Ifc.Operator Base Class Provides transaction wrapping: ```python class Operator: """ Base class for IFC operators. Provides automatic transaction handling and error recovery. """ def execute(self, context): # Start IFC transaction IfcStore.begin_transaction(self) # Mark edited objects for incremental save self.transaction_data = {"edited_objs": set()} try: result = self._execute(context) if result == {"FINISHED"}: IfcStore.commit_transaction(self) else: IfcStore.rollback_transaction(self) return result except Exception as e: IfcStore.rollback_transaction(self) import traceback traceback.print_exc() self.report({"ERROR"}, str(e)) return {"CANCELLED"} def _execute(self, context): """Override this method in subclasses.""" raise NotImplementedError ``` --- ## 9. UI Architecture ### 9.1 Panel System UI panels are organized by workspace and context: ```python # In bim/module/root/ui.py class BIM_PT_object_metadata(Panel): """Panel shown in Properties > Object tab""" bl_label = "IFC Object Metadata" bl_idname = "BIM_PT_object_metadata" bl_space_type = "PROPERTIES" bl_region_type = "WINDOW" bl_context = "object" @classmethod def poll(cls, context): """Show panel only if object has IFC data.""" return context.active_object and \ context.active_object.BIMObjectProperties.ifc_definition_id def draw(self, context): """Draw panel UI.""" layout = self.layout obj = context.active_object props = context.scene.BIMRootProperties # Load data lazily if not RootData.is_loaded: RootData.load() # Draw UI elements row = layout.row() row.prop(props, "ifc_class") row = layout.row() row.operator("bim.assign_class") ``` ### 9.2 The Data Loading Pattern To avoid performance issues, UI data is lazily loaded and cached: ```python # In bim/module/root/data.py class RootData: """Cache for UI data to avoid recomputing on every draw.""" data = {} is_loaded = False @classmethod def load(cls): """Load data needed for UI.""" cls.data = { "ifc_classes": cls.get_ifc_classes(), "predefined_types": cls.get_predefined_types(), "total_elements": cls.count_elements(), } cls.is_loaded = True @classmethod def get_ifc_classes(cls): """Get list of available IFC classes.""" schema = tool.Ifc.schema() return [d.name() for d in schema.declarations() if hasattr(d, 'name')] ``` --- ## 10. Event Handler System ### 10.1 Blender Event Handlers Located in `bim/handler.py`, event handlers respond to Blender events: ```python # In bim/handler.py @persistent def load_post(dummy): """Called after loading a .blend file.""" # Check if file has IFC project if bpy.context.scene.BIMProperties.ifc_file: # Reload IFC file IfcStore.file = ifcopenshell.open(bpy.context.scene.BIMProperties.ifc_file) # Rebuild object links tool.Ifc.link_elements() @persistent def save_pre(dummy): """Called before saving .blend file.""" # If linked to IFC, save IFC changes if tool.Ifc.get() and IfcStore.edited_objs: tool.Ifc.write(IfcStore.last_saved_file) @persistent def depsgraph_update_post(scene, depsgraph): """Called after scene updates (object moved, modified, etc.).""" # Track geometry changes for update in depsgraph.updates: if isinstance(update.id, bpy.types.Object): obj = update.id if obj.BIMObjectProperties.ifc_definition_id: # Mark for geometry update IfcStore.edited_objs.add(obj) def register(): """Register handlers on add-on enable.""" bpy.app.handlers.load_post.append(load_post) bpy.app.handlers.save_pre.append(save_pre) bpy.app.handlers.depsgraph_update_post.append(depsgraph_update_post) ``` ### 10.2 Real-Time Geometry Sync Bonsai monitors Blender's dependency graph to detect geometry changes: 1. User moves/edits object in Blender 2. `depsgraph_update_post` handler detects change 3. Object added to `IfcStore.edited_objs` 4. On next IFC operation or save, geometry is synced to IFC --- ## 11. Data Directory Structure ### 11.1 Static Data Assets ``` bim/data/ ├── pset/ # Property set templates │ ├── Pset_*.xml # Standard IFC property sets │ └── Qto_*.xml # Standard quantity templates ├── class/ # Classification systems │ ├── classifications.csv # Available systems │ ├── Uniclass2015.csv # Uniclass hierarchy │ └── OmniClass.csv # OmniClass hierarchy ├── qto/ # Quantity templates │ └── *.xml ├── libraries/ # IFC type libraries │ ├── IFC4_library.ifc # Standard types │ └── profiles.json # Steel profiles database ├── fonts/ # Fonts for annotations ├── icons/ # UI icons └── templates/ # Project templates ``` ### 11.2 Schema Directory ``` schema/ ├── IFC2X3.exp # IFC2X3 EXPRESS schema ├── IFC4.exp # IFC4 EXPRESS schema ├── IFC4X3_ADD2.exp # IFC4X3 EXPRESS schema └── *.xml # Property set definitions ``` --- ## 12. External Dependencies ### 12.1 Python Dependencies (wheels/) When packaged, Bonsai bundles these dependencies: ``` wheels/ ├── ifcopenshell-*.whl # Core IFC library ├── ifcopenshell_wrapper.*.so # C++ bindings ├── bcf-*.whl # BCF library ├── brickschema-*.whl # Brick schema ├── deepdiff-*.whl # Model comparison ├── ifc4d-*.whl # 4D scheduling ├── ifc5d-*.whl # 5D costing ├── ifcclash-*.whl # Clash detection ├── ifcdiff-*.whl # Model diff ├── ifcfm-*.whl # Facility management ├── ifcjson-*.whl # JSON serialization ├── ifcpatch-*.whl # Model patching ├── ifcsverchok-*.whl # Sverchok integration ├── ifctester-*.whl # IDS validation ├── lark-*.whl # Parser for selectors ├── odfpy-*.whl # ODS spreadsheet ├── openpyxl-*.whl # Excel support ├── pyparsing-*.whl # Parsing library ├── pyproj-*.whl # Coordinate systems ├── rdflib-*.whl # RDF for Brick ├── shapely-*.whl # Geometric operations ├── svgwrite-*.whl # SVG generation └── xmlschema-*.whl # XML validation ``` **Platform-Specific:** - Linux: `*-linux_x86_64.whl` - Windows: `*-win_amd64.whl` - macOS Intel: `*-macosx_x86_64.whl` - macOS ARM: `*-macosx_arm64.whl` --- ## 13. Build and Packaging System ### 13.1 Makefile Targets The `Makefile` handles packaging: ```makefile PLATFORM := linux # or win, macos, macosm1 PYVERSION := py311 # or py39, py310, py312 dist: # 1. Create clean directory rm -rf dist/bonsai mkdir -p dist/bonsai # 2. Copy source code cp -r bonsai/* dist/bonsai/ # 3. Download/copy platform-specific wheels # (from IfcOpenBot builds or local builds) mkdir -p dist/bonsai/libs/site/packages pip download -d dist/bonsai/libs/site/packages \ --platform $(PLATFORM) \ --python-version $(PYVERSION) \ ifcopenshell bcf ifc4d ifc5d ... # 4. Extract wheels cd dist/bonsai/libs/site/packages && \ for f in *.whl; do unzip -o $f; done # 5. Clean up rm dist/bonsai/libs/site/packages/*.whl rm -rf dist/bonsai/libs/site/packages/*.dist-info # 6. Create zipfile cd dist && zip -r bonsai-$(VERSION)-$(PLATFORM)-$(PYVERSION).zip bonsai/ ``` ### 13.2 Blender Add-on Structure Packaged as standard Blender add-on: ``` bonsai.zip └── bonsai/ ├── __init__.py # bl_info and register() ├── core/ ├── tool/ ├── bim/ ├── libs/ │ └── site/ │ └── packages/ # Dependencies ├── wheels/ # (empty in distribution) └── schema/ ``` **Installation:** Extract to Blender's add-ons directory or install via Blender UI. --- ## 14. Code Organization Principles ### 14.1 Separation of Concerns **Strict Layering:** 1. `core/` - Business logic (Blender-agnostic) 2. `tool/` - Blender integration 3. `bim/` - UI and user interaction **Benefits:** - Core logic is unit-testable without Blender - Tool layer provides stable API for operators - UI can change without affecting business logic ### 14.2 Module Independence Each `bim/module/*` is designed to be relatively independent: - Has its own operators, UI, properties - Communicates with other modules via `tool.*` interfaces - Can be disabled/enabled individually (though not currently implemented) ### 14.3 Lazy Loading Pattern UI data is loaded on-demand: - Avoid loading all data on startup - Cache data after first load - Invalidate cache when IFC changes **Example:** ```python class MyData: data = {} is_loaded = False @classmethod def load(cls): if not cls.is_loaded: cls.data = expensive_computation() cls.is_loaded = True @classmethod def clear(cls): cls.is_loaded = False ``` --- ## 15. Transaction System ### 15.1 IFC Transaction Architecture All IFC modifications are wrapped in transactions: ```python class IfcStore: history = [] # Stack of transactions future = [] # Redo stack @staticmethod def begin_transaction(operator): """Start new transaction.""" transaction = { "operations": [], "objects_created": [], "objects_deleted": [], "state_before": snapshot_ifc_state() } IfcStore.history.append(transaction) @staticmethod def commit_transaction(operator): """Commit changes.""" transaction = IfcStore.history[-1] transaction["state_after"] = snapshot_ifc_state() # Transaction is complete @staticmethod def rollback_transaction(operator): """Undo changes.""" transaction = IfcStore.history.pop() restore_ifc_state(transaction["state_before"]) ``` ### 15.2 Undo/Redo Support Blender's undo system is integrated: - Each IFC operation is a Blender undo step - Undo restores both Blender objects and IFC state - Redo re-applies operations --- ## 16. Performance Optimizations ### 16.1 Geometry Processing **Multi-core Support:** - IfcOpenShell's geometry iterator can run in parallel - Bonsai spawns worker processes for large model loads - Uses Blender's job system **Caching:** - Representation shapes are cached - Mesh data reused where possible - HDF5 cache for geometry (optional) ### 16.2 UI Performance **Lazy UI Updates:** - Data classes avoid recomputation - UI only updates on actual changes - Batch operations minimize redraws **Collection Optimization:** - Recent refactoring decoupled Blender collections from IFC spatial tree - Improves load/save performance - Reduces sync bugs ### 16.3 Large Model Handling **Selective Loading:** - Load only visible elements - Option to load without geometry - Level-of-detail (LOD) support **Streaming:** - Progressive loading of large files - Background geometry processing - Viewport culling --- ## 17. Testing Architecture ### 17.1 Test Structure ``` test/ ├── bim/ # BIM module tests │ ├── core/ # Core logic unit tests │ └── module/ # Module-specific tests ├── files/ # Test IFC files └── conftest.py # Pytest configuration ``` ### 17.2 Testing Strategy **Unit Tests (core/):** ```python # test/bim/core/test_root.py def test_create_entity(): """Test entity creation without Blender.""" file = ifcopenshell.file() entity = root.create_entity( file, ifc_class="IfcWall", name="Test Wall" ) assert entity.is_a("IfcWall") assert entity.Name == "Test Wall" ``` **Integration Tests (with Blender):** - Require Blender to be running - Test operator execution - Verify UI behavior --- ## 18. Documentation Generation ### 18.1 Sphinx Documentation Located in `docs/`: ``` docs/ ├── conf.py # Sphinx configuration ├── index.rst # Documentation home ├── quickstart/ # Getting started guides ├── guides/ # User guides ├── reference/ # API reference ├── tutorials/ # Step-by-step tutorials ├── _static/ # Images, CSS └── _build/ # Generated HTML ``` **Build Command:** ```bash cd docs make html # Output in _build/html/ ``` ### 18.2 API Documentation Generated from docstrings: - Core modules documented with detailed docstrings - Operator descriptions become Blender's built-in help - Property descriptions show as tooltips --- ## 19. Workflow Examples ### 19.1 Creating a Wall - Full Stack **User Action:** Click "Create Wall" tool **Execution Flow:** ``` 1. UI (bim/module/model/ui.py) └─> User clicks button in workspace 2. Operator (bim/module/model/operator.py) └─> AddWall.invoke() - starts modal mode └─> AddWall.modal() - handles mouse/keyboard └─> Draw handler shows preview geometry 3. On confirmation, operator calls core logic: 4. Core (bonsai/core/root.py) └─> create_entity() - Creates IfcWall in IFC file - Sets properties (Name, PredefinedType) - Assigns spatial container 5. Core (bonsai/core/geometry.py) └─> add_representation() - Creates IfcProductDefinitionShape - Adds body representation - Links to representation context 6. Tool (bonsai/tool/geometry.py) └─> create_blender_object() - Creates Blender mesh - Assigns materials - Links to scene collection 7. Tool (bonsai/tool/ifc.py) └─> link_element() - Stores IFC ID in object properties - Registers in IfcStore.id_map 8. Result: Wall exists in both IFC and Blender ``` ### 19.2 Editing Properties **User Action:** Change property value in UI **Execution Flow:** ``` 1. UI (bim/module/pset/ui.py) └─> BIM_PT_object_psets panel displays properties └─> User edits EnumProperty 2. Operator (bim/module/pset/operator.py) └─> EditPset.execute() 3. Core (bonsai/core/pset.py) └─> edit_pset() - Gets IFC property set - Updates property value - Validates against schema 4. Transaction committed └─> IfcStore marks object as edited └─> Change saved on next IFC write ``` --- ## 20. Development Workflow ### 20.1 Setting Up Development Environment **Clone Repository:** ```bash git clone https://github.com/IfcOpenShell/IfcOpenShell.git cd IfcOpenShell/src/bonsai ``` **Install in Blender:** ```bash # Create symlink in Blender add-ons directory ln -s $(pwd)/bonsai ~/.config/blender/4.2/scripts/addons/bonsai # Or set BLENDER_USER_SCRIPTS environment variable export BLENDER_USER_SCRIPTS=/path/to/IfcOpenShell/src ``` **Install Dependencies:** ```bash # Get ifcopenshell and dependencies # Option 1: Use pre-built wheels from IfcOpenBot # Option 2: Build from source (see IfcOpenShell build docs) pip install ifcopenshell --target bonsai/libs/site/packages ``` ### 20.2 Development Tools **VSCode/VSCodium Setup:** - Python extension - Blender Development extension - Debugger configuration **Debugging:** ```json // .vscode/launch.json { "version": "0.2.0", "configurations": [ { "name": "Blender", "type": "python", "request": "attach", "port": 3000, "host": "localhost" } ] } ``` **Code Formatting:** ```bash # Black formatter black src/bonsai # Ruff linter ruff check src/bonsai ``` --- ## 21. Extension Points and Customization ### 21.1 Adding New Modules To add a new feature module: 1. Create module directory: ``` bim/module/myfeature/ ├── __init__.py ├── operator.py ├── ui.py ├── prop.py └── data.py ``` 2. Implement operators, UI, properties 3. Register in `bim/__init__.py`: ```python from . module.myfeature import register as register_myfeature def register(): register_myfeature() ``` ### 21.2 Custom Operators ```python # In bim/module/myfeature/operator.py class MyOperator(bpy.types.Operator, tool.Ifc.Operator): bl_idname = "bim.my_operator" bl_label = "My Custom Operation" bl_options = {"REGISTER", "UNDO"} def _execute(self, context): # Your implementation file = tool.Ifc.get() # ... IFC operations return {"FINISHED"} def register(): bpy.utils.register_class(MyOperator) ``` ### 21.3 Custom Tools ```python # In tool/myfeature.py class MyFeature: @classmethod def my_helper(cls, param): """Custom tool method.""" # Implementation pass ``` --- ## 22. Architecture Strengths ### 22.1 Modularity - Clear separation of concerns - Independent modules - Pluggable architecture ### 22.2 Maintainability - Consistent patterns across modules - Well-defined interfaces (tool layer) - Centralized state management (IfcStore) ### 22.3 Extensibility - Easy to add new modules - Tool system provides stable API - Core logic reusable outside Blender ### 22.4 Performance - Lazy loading - Caching strategies - Multi-core geometry processing - Transaction batching ### 22.5 Robustness - Transaction system with undo - Error handling in operators - Validation at multiple layers --- ## 23. Architecture Challenges ### 23.1 Complexity - Large codebase (50+ modules) - Steep learning curve for contributors - Many interdependencies ### 23.2 Blender API Changes - Must track Blender API changes - Version compatibility maintenance - Deprecation handling ### 23.3 Performance at Scale - Very large models (10,000+ elements) can be slow - Geometry synchronization overhead - Collection system limitations ### 23.4 Testing Challenges - Requires Blender for integration tests - Hard to test UI interactions - Long test execution times --- ## 24. Future Architecture Directions ### 24.1 Planned Improvements **Better Abstraction:** - Further decouple from Blender specifics - More reusable core logic - Potential for other frontend (Qt, web?) **Performance:** - Continued optimization of loading - Better streaming for large models - GPU-accelerated operations **Modularity:** - Plugin system for third-party extensions - Selective module loading - Reduced memory footprint ### 24.2 Emerging Features **AI Integration:** - MCP4IFC framework - LLM-driven authoring - Intelligent validation **Web Technologies:** - WebAssembly builds - Cloud collaboration - Browser-based viewers --- ## 25. Conclusion ### 25.1 Summary Bonsai represents a sophisticated, well-architected Blender add-on that transforms Blender into a native IFC authoring platform. The architecture is characterized by: - **Three-tier design:** Core logic, integration tools, UI layer - **50+ specialized modules:** Covering all BIM workflows - **Robust state management:** IfcStore singleton with transactions - **Performance optimizations:** Lazy loading, caching, multi-core processing - **Clean separation of concerns:** Blender-agnostic core, Blender-specific implementation ### 25.2 Key Takeaways **Architectural Principles:** 1. Separation of business logic from UI 2. Tool layer provides stable abstractions 3. Transaction system ensures data integrity 4. Modular design enables independent features 5. Lazy loading optimizes performance **Code Organization:** - Consistent patterns across all modules - Clear file structure (operator, ui, prop, data) - Centralized state (IfcStore) - Event-driven synchronization **Development Philosophy:** - Native IFC (not import/export) - Direct manipulation of IFC entities - Bidirectional Blender-IFC sync - Comprehensive BIM workflow support - Open-source and community-driven ### 25.3 For Developers **Getting Started:** 1. Understand the three-tier architecture 2. Study a simple module (e.g., `root`) 3. Learn the tool layer interfaces 4. Follow operator patterns 5. Contribute incrementally **Best Practices:** - Keep core logic Blender-agnostic - Use tool layer for Blender operations - Follow transaction pattern for IFC modifications - Implement lazy loading for UI data - Write descriptive docstrings --- ## Appendix: File Count and Statistics **Estimated Statistics (as of v0.8):** - **Total Python Files:** ~800+ - **Lines of Code:** ~200,000+ - **Modules:** 50+ - **Operators:** 500+ - **UI Panels:** 200+ - **Property Groups:** 50+ - **Test Files:** 100+ **Module Distribution:** - `core/`: ~30 modules - `tool/`: ~30 modules - `bim/module/`: ~50 modules - `bim/data/`: Static assets --- **Document Version:** 1.0 **Last Updated:** February 16, 2026 **Repository:** https://github.com/IfcOpenShell/IfcOpenShell/tree/v0.8.0/src/bonsai