Three bugs fixed:
1. EditAssignedMaterial was sweeping all slabs that share a layer set
when changing material properties, instead of updating only the
selected element's assigned material.
2. slice_layerset_mesh (loader.py): layer bisect positions were scaled
incorrectly due to a stale unit_scale and a reversed/missing
DirectionSense guard. Now always recalculates unit_scale fresh and
correctly applies sense_factor.
3. change_thickness (slab.py): extrusion depth was computed as
`thickness / cos(obj.rotation_euler.x)`, which incorrectly scaled
ObjectPlacement-rotated slabs (where the extrusion direction is
local Z and no scaling is needed). The correct formula is
`thickness / extrusion_vec.z`, which handles both ObjectPlacement
rotation (extrusion_vec.z ≈ 1.0 → no scale) and ExtrudedDirection
tilts (extrusion_vec.z < 1.0 → scale up) uniformly. The resulting
slab was 1.414× too thick for 45°-rotated slabs, making both
material layers appear fatter than specified.
slice_layerset_mesh retains a depth_scale safety factor
(extrusion_vec.z × ifc_depth / total_layer_thickness) as a
robustness guard for IFC files from other authoring tools where
extrusion depth may not match the sum of LayerThicknesses.
Three related bugs fixed in the slab material layer set workflow:
1. EditAssignedMaterial (operator.py): Applying a custom offset to one slab
instance incorrectly regenerated geometry for ALL slabs sharing the same
IfcMaterialLayerSet. Replaced regenerate_from_layer_set (sweeps all users)
with per-element regenerate_from_occurence for AXIS3 slabs and targeted
recalculate_walls for AXIS2 walls. Each element's IfcMaterialLayerSetUsage
attributes are now updated individually before regeneration.
2. slice_layerset_mesh (loader.py): Loader.unit_scale is a class variable only
set during full file import, so it was stale (= 1) during live geometry
updates on foot-based IFC files. Layer bisect planes were being computed in
IFC feet while the mesh was in Blender metres, placing all cuts completely
outside the mesh. Fixed by computing unit_scale fresh from the IFC file on
each call via ifcopenshell.util.unit.calculate_unit_scale.
3. OffsetFromReferenceLine stale / layer order reversed (slab.py, loader.py):
A guard (and custom_offset is None) in change_thickness prevented writing
the correct OffsetFromReferenceLine (position.z) to the usage when a custom
offset was active. This left the value at 0.0 instead of the actual slab
bottom (e.g. -1.0 IFC units for a TOP-reference slab), so the bisect
starting point co was at the reference plane rather than the slab bottom,
reversing layer assignments or missing layers entirely. Removed the guard —
safe because each element has its own IfcMaterialLayerSetUsage instance.
Reverted the AXIS3 bisect normal back to (0,0,1) (upward from co at slab
bottom) which is correct once OffsetFromReferenceLine is properly set.
Previous logic always skipped the first point. Instead, it should only
skip when actually closing a loop (i.e. >= 3 points).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Since we added more data to debug info in fcf5614 Fatal Error itself started to fail and was never displayed due some props being inaccessible during load, should be fixed now.
Possible error that were fixed:
```
File "\Blender\5.1\extensions\raw_githubusercontent_com\bonsai\__init__.py", line 328, in <module>
print(format_debug_info(get_debug_info()))
~~~~~~~~~~~~~~^^
File "\Blender\5.1\extensions\raw_githubusercontent_com\bonsai\__init__.py", line 117, in get_debug_info
if bpy.data.is_saved:
^^^^^^^^^^^^^^^^^
AttributeError: '_RestrictData' object has no attribute 'is_saved'
Traceback (most recent call last):
File "\Blender\5.1\extensions\raw_githubusercontent_com\bonsai\__init__.py", line 366, in draw
info = get_debug_info()
File "\Blender\5.1\extensions\raw_githubusercontent_com\bonsai\__init__.py", line 152, in get_debug_info
bim_props = tool.Blender.get_bim_props()
^^^^
NameError: name 'tool' is not defined. Did you mean: 'bool'?
Traceback (most recent call last):
File "\Blender\5.1\extensions\raw_githubusercontent_com\bonsai\__init__.py", line 366, in draw
info = get_debug_info()
File "\Blender\5.1\extensions\raw_githubusercontent_com\bonsai\__init__.py", line 141, in get_debug_info
import bonsai.tool as tool
File "\Blender\5.1\extensions\.local\lib\python3.13\site-packages\bonsai\__init__.py", line 355, in <module>
print(format_debug_info(get_debug_info()))
~~~~~~~~~~~~~~^^
File "\Blender\5.1\extensions\.local\lib\python3.13\site-packages\bonsai\__init__.py", line 141, in get_debug_info
import bonsai.tool as tool
File "\Blender\5.1\extensions\.local\lib\python3.13\site-packages\bonsai\tool\__init__.py", line 23, in <module>
from bonsai.tool.attribute import Attribute
File "\Blender\5.1\extensions\.local\lib\python3.13\site-packages\bonsai\tool\attribute.py", line 31, in <module>
import bonsai.bim.helper as helper
File "\Blender\5.1\extensions\.local\lib\python3.13\site-packages\bonsai\bim\__init__.py", line 28, in <module>
from . import handler, operator, prop, ui
File "\Blender\5.1\extensions\.local\lib\python3.13\site-packages\bonsai\bim\handler.py", line 36, in <module>
from bonsai.bim.module.aggregate.decorator import AggregateDecorator
File "\Blender\5.1\extensions\.local\lib\python3.13\site-packages\bonsai\bim\module\aggregate\__init__.py", line 21, in <module>
from . import operator, prop, ui
File "\Blender\5.1\extensions\.local\lib\python3.13\site-packages\bonsai\bim\module\aggregate\operator.py", line 32, in <module>
class BIM_OT_aggregate_assign_object(bpy.types.Operator, tool.Ifc.Operator):
^^^^^^^^
AttributeError: partially initialized module 'bonsai.tool' from '\Blender\5.1\extensions\.local\lib\python3.13\site-packages\bonsai\tool\__init__.py' has no attribute 'Ifc' (most likely due to a circular import)
```
Blender doesn't have it's own quick favorites manager and working with them can be not very flexible - you can add them in context menu and remove them from Quick Favorites menu. But you can't reorder them, you can't rename them and you can't even add a new button to favorites if it's not added by some addon in the UI.
Have been stumbling upon this for awhile and decided to create an experimental manager UI for this. Things it can do:
- help user create a button with any operator in Blender and properties they prefer to then save it Quick Favorites. Which seems can be very useful in Bonsai, since you can create separate buttons for all kinds of selectors expressions, class assignment or other operators.
- it can import quick favorites from user's actual current quick favorites, so they can just modify them a bit, reorder, rename and then add them again.
- Since quick favorites are not exposed to Python API in Blender, we're using a very hacky way to retrieve them from Blender and don't provide our own buttons for adding and removing quick favorites, as it may be dangerous and even more hacky in implementation. So the workflow for user is to either generate some buttons and add them to quick favorites using Manager or to import it's own quick favorites, then change them how they like, then remove quick favorites using usual quick favorites menu and then add new button one by one.
Small demo - https://files.catbox.moe/vyffp6.mp4