# Design ## Architecture `building.py` will join the bpy-layer feature modules under `blender/osmassets/`. It may import `MeshBatch`, `add_roof`, `add_wall_panel`, and `make_prism` from `osmassets.mesh`, plus `parse_height` from `osmassets.osm`. The module will expose: ```python def assemble(ring, way_id, tag, office_overrides, collection, materials): ... ``` The function returns: ```python (added, industrial_added, ring_pts) ``` This keeps `generate_scene.py`'s count and focus-point handling unchanged while removing building geometry construction from the entry script. ## Boundaries - `generate_scene.py` keeps CLI parsing, OSM way dispatch, material creation, count accumulation, focus-point accumulation, scene custom properties, and stdout markers. - `building.py` owns only building object creation and building-specific facade details for a ring that has already been projected. - `building.py` is a bpy-layer module. It must not be imported by pure Python modules or pure unit tests. - `catalog.py` remains the material declaration source; no material entries or order change in this task. ## Data Flow 1. `generate_scene.py` parses `args["office_overrides"]` into a set. 2. `generate_scene.py` creates `building_mats` from `catalog.MATERIALS`. 3. OSM ways are projected to local-meter rings in `generate_scene.py`. 4. For ways with a `building` tag and at least three ring points, `building.assemble(ring, str(way["id"]), tag, args["office_overrides"], buildings_c, building_mats)` creates the prism, roof, windows, custom properties, and bevel. 5. `generate_scene.py` updates `counts["building_count"]`, `counts["industrial_count"]`, and `focus_points` from the return tuple. ## Compatibility The move must preserve object names, mesh names, material assignments, bevel modifier fields, custom properties, window-band geometry, and return values. Cesium export consumes the resulting `.blend`, so parity should see no non-ignored contract difference. ## Trade-Offs The `office_overrides` set is passed into `building.assemble()` rather than passing the whole `args` dict. This narrows the module contract while preserving behavior. A full feature registry remains deferred until building and roads are both isolated enough to compare safely. ## Rollback Rollback is mechanical: move `assemble()` and its helper back into `generate_scene.py`, restore direct calls, remove the `building.py` import, and delete the module.