Refactor tab visibility to use data cache

Previously calculation of visibility was done on every draw (3x 10tabs x
10 collection items). The data class is intended to calculate UI data
once only which is more efficient. This also removes all helper calls
from the UI.
This commit is contained in:
Dion Moult
2026-01-15 11:30:28 +11:00
parent bb50be389e
commit 26fb6ebd3c
3 changed files with 42 additions and 71 deletions
-16
View File
@@ -830,16 +830,6 @@ def set_tab_visibility(tab_name, visible):
new_tab.is_visible = visible new_tab.is_visible = visible
def get_panel_visibility(panel_id, current_tab=None):
panel_config = get_panel_config(panel_id)
if panel_config:
if current_tab == "BOOKMARK":
return panel_config.is_visible_in_bookmarks
else:
return panel_config.is_visible_in_tab
return True
def get_panel_config(panel_id, create_if_missing=False): def get_panel_config(panel_id, create_if_missing=False):
try: try:
bim_props = tool.Blender.get_bim_props() bim_props = tool.Blender.get_bim_props()
@@ -854,9 +844,6 @@ def get_panel_config(panel_id, create_if_missing=False):
try: try:
prop = bim_props.panel_properties.add() prop = bim_props.panel_properties.add()
prop.name = panel_id prop.name = panel_id
prop.is_visible_in_tab = True
prop.is_visible_in_bookmarks = True
prop.is_bookmarked = False
return prop return prop
except AttributeError: except AttributeError:
pass pass
@@ -918,6 +905,3 @@ def initialize_panel_properties():
prop = bim_props.panel_properties.add() prop = bim_props.panel_properties.add()
prop.name = panel_id prop.name = panel_id
prop.is_visible_in_tab = True
prop.is_visible_in_bookmarks = True
prop.is_bookmarked = False
+5 -1
View File
@@ -60,6 +60,10 @@ def update_tab(self: "BIMAreaProperties", context: bpy.types.Context) -> None:
self.previous_tab = self.tab self.previous_tab = self.tab
def update_is_visible(self: "BIMTabVisibility", context: bpy.types.Context) -> None:
bonsai.bim.handler.refresh_ui_data()
def update_global_tab(self: "BIMTabProperties", context: bpy.types.Context) -> None: def update_global_tab(self: "BIMTabProperties", context: bpy.types.Context) -> None:
tool.Blender.setup_tabs() tool.Blender.setup_tabs()
screen = context.id_data screen = context.id_data
@@ -537,7 +541,7 @@ class BIMTabProperties(PropertyGroup):
class BIMTabVisibility(PropertyGroup): class BIMTabVisibility(PropertyGroup):
name: StringProperty(name="Tab Name") name: StringProperty(name="Tab Name")
is_visible: BoolProperty(name="Is Visible", default=True) is_visible: BoolProperty(name="Is Visible", default=True, update=update_is_visible)
if TYPE_CHECKING: if TYPE_CHECKING:
name: str name: str
+37 -54
View File
@@ -36,18 +36,6 @@ import bonsai.bim
import bonsai.tool as tool import bonsai.tool as tool
from ifcopenshell.util.file import IfcHeaderExtractor from ifcopenshell.util.file import IfcHeaderExtractor
from bonsai.bim.prop import Attribute from bonsai.bim.prop import Attribute
from bonsai.bim.helper import (
get_tab_names,
get_panel_tab_name,
should_show_panel,
get_tab_visibility,
set_tab_visibility,
get_panel_visibility,
get_panel_config,
get_all_tab_panels,
initialize_tab_visibilities,
initialize_panel_properties,
)
from bonsai.bim.module.bsdd.prop import BIMBSDDProperties, BSDDProperty from bonsai.bim.module.bsdd.prop import BIMBSDDProperties, BSDDProperty
from bonsai.bim.module.pset.prop import IfcProperty from bonsai.bim.module.pset.prop import IfcProperty
from bonsai.bim.module.model.prop import ( from bonsai.bim.module.model.prop import (
@@ -998,41 +986,13 @@ class BIM_PT_tabs(Panel):
is_ifc_project = bool(tool.Ifc.get()) is_ifc_project = bool(tool.Ifc.get())
aprops = tool.Blender.get_area_props(context) aprops = tool.Blender.get_area_props(context)
addon_prefs = tool.Blender.get_addon_preferences() addon_prefs = tool.Blender.get_addon_preferences()
ifc_icon = f"{UIData.data['tabs_icon_color_mode']}_ifc"
split = self.layout.split(factor=0.9) split = self.layout.split(factor=0.9)
col_left = split.column(align=True) col_left = split.column(align=True)
row_left = col_left.row(align=True) row_left = col_left.row(align=True)
row_left.alignment = "CENTER" row_left.alignment = "CENTER"
if get_tab_visibility("PROJECT"): for tab in UIData.data["tabs"]:
row_left.operator( self.draw_tab_entry(row_left, tab[1], tab[0], tab[2], aprops.tab == tab[0])
"bim.set_tab",
text="",
emboss=aprops.tab == "PROJECT",
icon_value=bonsai.bim.icons[ifc_icon].icon_id,
).tab = "PROJECT"
if get_tab_visibility("OBJECT"):
self.draw_tab_entry(row_left, "FILE_3D", "OBJECT", is_ifc_project, aprops.tab == "OBJECT")
if get_tab_visibility("GEOMETRY"):
self.draw_tab_entry(row_left, "MATERIAL", "GEOMETRY", is_ifc_project, aprops.tab == "GEOMETRY")
if get_tab_visibility("DRAWINGS"):
self.draw_tab_entry(row_left, "DOCUMENTS", "DRAWINGS", is_ifc_project, aprops.tab == "DRAWINGS")
if get_tab_visibility("SERVICES"):
self.draw_tab_entry(row_left, "NETWORK_DRIVE", "SERVICES", is_ifc_project, aprops.tab == "SERVICES")
if get_tab_visibility("STRUCTURE"):
self.draw_tab_entry(row_left, "EDITMODE_HLT", "STRUCTURE", is_ifc_project, aprops.tab == "STRUCTURE")
if get_tab_visibility("SCHEDULING"):
self.draw_tab_entry(row_left, "NLA", "SCHEDULING", is_ifc_project, aprops.tab == "SCHEDULING")
if get_tab_visibility("FM"):
self.draw_tab_entry(row_left, "PACKAGE", "FM", True, aprops.tab == "FM")
if get_tab_visibility("QUALITY"):
self.draw_tab_entry(row_left, "COMMUNITY", "QUALITY", True, aprops.tab == "QUALITY")
if (
addon_prefs.save_metadata_blend_file
and addon_prefs.user_ui_customization
and get_tab_visibility("BOOKMARK")
):
self.draw_tab_entry(row_left, "SOLO_ON", "BOOKMARK", True, aprops.tab == "BOOKMARK")
row_left.operator("bim.switch_tab", text="", emboss=False, icon="UV_SYNC_SELECT") row_left.operator("bim.switch_tab", text="", emboss=False, icon="UV_SYNC_SELECT")
row_left = col_left.row(align=True) row_left = col_left.row(align=True)
@@ -1043,13 +1003,12 @@ class BIM_PT_tabs(Panel):
if not (addon_prefs.save_metadata_blend_file and addon_prefs.user_ui_customization): if not (addon_prefs.save_metadata_blend_file and addon_prefs.user_ui_customization):
row_left.prop(aprops, "inactive_tab", text="", icon="BLANK1", emboss=False) row_left.prop(aprops, "inactive_tab", text="", icon="BLANK1", emboss=False)
for tab in get_tab_names(): for tab in UIData.data["tabs"]:
# Draw a little underscore below the active tab icon. # Draw a little underscore below the active tab icon.
if get_tab_visibility(tab): if aprops.tab == tab:
if aprops.tab == tab: row_left.prop(aprops, "active_tab", text="", icon="BLANK1")
row_left.prop(aprops, "active_tab", text="", icon="BLANK1") else:
else: row_left.prop(aprops, "inactive_tab", text="", icon="BLANK1", emboss=False)
row_left.prop(aprops, "inactive_tab", text="", icon="BLANK1", emboss=False)
row_left.prop(aprops, "inactive_tab", text="", icon="BLANK1", emboss=False) # space for Switch row_left.prop(aprops, "inactive_tab", text="", icon="BLANK1", emboss=False) # space for Switch
col_right = split.column(align=True) col_right = split.column(align=True)
row_right = col_right.row(align=True) row_right = col_right.row(align=True)
@@ -1062,10 +1021,9 @@ class BIM_PT_tabs(Panel):
row.prop(aprops, "tab", text="") row.prop(aprops, "tab", text="")
if addon_prefs.save_metadata_blend_file and addon_prefs.user_ui_customization: if addon_prefs.save_metadata_blend_file and addon_prefs.user_ui_customization:
for tab in get_tab_names(): for tab in UIData.data["tabs"]:
if get_tab_visibility(tab): if aprops.tab == tab:
if aprops.tab == tab: row.operator("bim.manage_tab_panels", text="", icon="PREFERENCES").tab_name = tab
row.operator("bim.manage_tab_panels", text="", icon="PREFERENCES").tab_name = tab
if bonsai.REINSTALLED_BBIM_VERSION: if bonsai.REINSTALLED_BBIM_VERSION:
box = self.layout.box() box = self.layout.box()
@@ -1132,7 +1090,10 @@ class BIM_PT_tabs(Panel):
def draw_tab_entry(self, row, icon, tab_name, enabled=True, highlight=True): def draw_tab_entry(self, row, icon, tab_name, enabled=True, highlight=True):
tab_entry = row.row(align=True) tab_entry = row.row(align=True)
tab_entry.operator("bim.set_tab", text="", emboss=highlight, icon=icon).tab = tab_name if isinstance(icon, int):
tab_entry.operator("bim.set_tab", text="", emboss=highlight, icon_value=icon).tab = tab_name
else:
tab_entry.operator("bim.set_tab", text="", emboss=highlight, icon=icon).tab = tab_name
tab_entry.enabled = enabled tab_entry.enabled = enabled
@@ -1860,8 +1821,8 @@ class UIData:
def load(cls): def load(cls):
cls.data = { cls.data = {
"version": cls.version(), "version": cls.version(),
"tabs_icon_color_mode": cls.icon_color_mode("user_interface.wcol_regular.text"),
"menu_icon_color_mode": cls.icon_color_mode("user_interface.wcol_menu.text"), "menu_icon_color_mode": cls.icon_color_mode("user_interface.wcol_menu.text"),
"tabs": cls.tabs(),
} }
cls.is_loaded = True cls.is_loaded = True
@@ -1873,6 +1834,28 @@ class UIData:
def icon_color_mode(cls, color_path): def icon_color_mode(cls, color_path):
return tool.Blender.detect_icon_color_mode(color_path) return tool.Blender.detect_icon_color_mode(color_path)
@classmethod
def tabs(cls):
hidden_tabs = [t.name for t in tool.Blender.get_bim_props().tab_visibilities if not t.is_visible]
color_mode = cls.icon_color_mode("user_interface.wcol_regular.text")
is_ifc_project = bool(tool.Ifc.get())
return [
tab
for tab in [
("PROJECT", bonsai.bim.icons[f"{color_mode}_ifc"].icon_id, True),
("OBJECT", "FILE_3D", is_ifc_project),
("GEOMETRY", "MATERIAL", is_ifc_project),
("DRAWINGS", "DOCUMENTS", is_ifc_project),
("SERVICES", "NETWORK_DRIVE", is_ifc_project),
("STRUCTURE", "EDITMODE_HLT", is_ifc_project),
("SCHEDULING", "NLA", is_ifc_project),
("FM", "PACKAGE", True),
("QUALITY", "COMMUNITY", True),
("BOOKMARK", "SOLO_ON", is_ifc_project),
]
if tab[0] not in hidden_tabs
]
def draw_statusbar(self, context): def draw_statusbar(self, context):
if not UIData.is_loaded: if not UIData.is_loaded: