Fix #4176. Bug where tabbed interface didn't work on new or temporary screens.

This commit is contained in:
Dion Moult
2024-01-08 16:03:34 +11:00
parent 02a5b8d997
commit 9093c9d419
6 changed files with 63 additions and 24 deletions
@@ -115,6 +115,7 @@ classes = [
prop.ObjProperty,
prop.Attribute,
prop.BIMAreaProperties,
prop.BIMTabProperties,
prop.BIMProperties,
prop.IfcParameter,
prop.PsetQto,
@@ -206,6 +207,7 @@ def register():
bpy.app.handlers.load_post.append(handler.loadIfcStore)
bpy.types.Scene.BIMProperties = bpy.props.PointerProperty(type=prop.BIMProperties)
bpy.types.Screen.BIMAreaProperties = bpy.props.CollectionProperty(type=prop.BIMAreaProperties)
bpy.types.Screen.BIMTabProperties = bpy.props.PointerProperty(type=prop.BIMTabProperties)
bpy.types.Collection.BIMCollectionProperties = bpy.props.PointerProperty(type=prop.BIMCollectionProperties)
bpy.types.Object.BIMObjectProperties = bpy.props.PointerProperty(type=prop.BIMObjectProperties)
bpy.types.Material.BIMObjectProperties = bpy.props.PointerProperty(type=prop.BIMObjectProperties)
+1 -7
View File
@@ -354,10 +354,4 @@ def load_post(scene):
bpy.utils.register_class(override_panel)
bpy.utils.unregister_class(original_panel)
blenderbim.bim.overridden_scene_panels[panel] = (original_panel, override_panel)
# https://blender.stackexchange.com/questions/140644/how-can-make-the-state-of-a-boolean-property-relative-to-the-3d-view-area
for screen in bpy.data.screens:
if len(screen.BIMAreaProperties) == 20:
continue
screen.BIMAreaProperties.clear()
for i in range(20): # 20 is an arbitrary value of split areas
screen.BIMAreaProperties.add()
tool.Blender.setup_tabs()
+4 -2
View File
@@ -55,7 +55,8 @@ class SetTab(bpy.types.Operator):
def execute(self, context):
if context.area.spaces.active.search_filter:
return {"FINISHED"}
aprops = context.screen.BIMAreaProperties[context.screen.areas[:].index(context.area)]
tool.Blender.setup_tabs()
aprops = tool.Blender.get_area_props(context)
aprops.tab = self.tab
return {"FINISHED"}
@@ -69,7 +70,8 @@ class SwitchTab(bpy.types.Operator):
def execute(self, context):
if context.area.spaces.active.search_filter:
return {"FINISHED"}
aprops = context.screen.BIMAreaProperties[context.screen.areas[:].index(context.area)]
tool.Blender.setup_tabs()
aprops = tool.Blender.get_area_props(context)
aprops.tab = aprops.alt_tab
return {"FINISHED"}
+18
View File
@@ -58,6 +58,13 @@ def update_tab(self, context):
self.previous_tab = self.tab
def update_global_tab(self, context):
tool.Blender.setup_tabs()
screen = tool.Blender.get_screen(context)
aprops = screen.BIMAreaProperties[screen.areas[:].index(context.area)]
aprops.tab = self.tab
# If we don't cache strings, accents get mangled due to a Blender bug
# https://blender.stackexchange.com/questions/216230/is-there-a-workaround-for-the-known-bug-in-dynamic-enumproperty
# https://github.com/IfcOpenShell/IfcOpenShell/pull/1945
@@ -332,6 +339,17 @@ class BIMAreaProperties(PropertyGroup):
inactive_tab: BoolProperty(default=False, name="Inactive Tab")
# BIMAreaProperties exists per area and is setup on load post. However, for new
# or temporary screens, they may not be setup yet, so this global tab
# properties is used as a fallback.
class BIMTabProperties(PropertyGroup):
tab: EnumProperty(default=0, items=get_tab, name="Tab", update=update_global_tab)
previous_tab: StringProperty(default="PROJECT", name="Previous Tab")
alt_tab: StringProperty(default="OBJECT", name="Alt Tab")
active_tab: BoolProperty(default=True, name="Active Tab")
inactive_tab: BoolProperty(default=False, name="Inactive Tab")
class BIMProperties(PropertyGroup):
schema_dir: StringProperty(
default=os.path.join(cwd, "schema") + os.path.sep, name="Schema Directory", update=update_schema_dir
+9 -3
View File
@@ -138,7 +138,11 @@ class BIM_ADDON_preferences(bpy.types.AddonPreferences):
openlca_port: IntProperty(name="OpenLCA IPC Port", default=8080)
should_hide_empty_props: BoolProperty(name="Should Hide Empty Properties", default=True)
should_setup_workspace: BoolProperty(name="Should Setup Workspace Layout for BIM", default=True)
should_setup_toolbar: BoolProperty(name="Always Show Toolbar In 3D Viewport", default=True, description="If disabled, the toolbar will only load when an IFC model is active")
should_setup_toolbar: BoolProperty(
name="Always Show Toolbar In 3D Viewport",
default=True,
description="If disabled, the toolbar will only load when an IFC model is active",
)
should_play_chaching_sound: BoolProperty(
name="Should Make A Cha-Ching Sound When Project Costs Updates", default=False
)
@@ -288,7 +292,10 @@ class BIM_PT_tabs(Panel):
def draw(self, context):
try:
is_ifc_project = bool(tool.Ifc.get())
aprops = context.screen.BIMAreaProperties[context.screen.areas[:].index(context.area)]
aprops = tool.Blender.get_area_props(context)
if not aprops:
# Fallback in case areas aren't setup yet.
aprops = context.screen.BIMTabProperties
row = self.layout.row()
row.operator(
@@ -330,7 +337,6 @@ class BIM_PT_tabs(Panel):
else:
row.prop(aprops, "inactive_tab", text="", icon="BLANK1", emboss=False)
aprops = context.screen.BIMAreaProperties[context.screen.areas[:].index(context.area)]
row = self.layout.row(align=True)
row.prop(aprops, "tab", text="")
except:
+29 -12
View File
@@ -42,26 +42,41 @@ class Blender(blenderbim.core.tool.Blender):
OBJECT_TYPES_THAT_SUPPORT_EDIT_MODE = ("MESH", "CURVE", "SURFACE", "META", "FONT", "LATTICE", "ARMATURE")
OBJECT_TYPES_THAT_SUPPORT_EDIT_GPENCIL_MODE = ("GPENCIL",)
@classmethod
def get_area_props(cls, context):
try:
if context.screen.name.endswith("-nonnormal"): # Ctrl-space temporary fullscreen
screen = bpy.data.screens[context.screen.name[0 : -len("-nonnormal")]]
# The original area object has its type changed to "EMPTY" apparently
index = [a.type for a in screen.areas].index("EMPTY")
return screen.BIMAreaProperties[index]
return context.screen.BIMAreaProperties[context.screen.areas[:].index(context.area)]
except:
return
@classmethod
def set_active_object(cls, obj):
bpy.context.view_layer.objects.active = obj
obj.select_set(True)
@classmethod
def setup_tabs(cls):
# https://blender.stackexchange.com/questions/140644/how-can-make-the-state-of-a-boolean-property-relative-to-the-3d-view-area
for screen in bpy.data.screens:
if len(screen.BIMAreaProperties) == 20:
continue
screen.BIMAreaProperties.clear()
for i in range(20): # 20 is an arbitrary value of split areas
screen.BIMAreaProperties.add()
@classmethod
def is_tab(cls, context, tab):
if not len(context.screen.BIMAreaProperties):
return None
aprops = cls.get_area_props(context)
if not aprops:
return context.screen.BIMTabProperties.tab == tab
if context.area.spaces.active.search_filter:
return True
screen_areas = context.screen.areas[:]
current_area = context.area
# If the user is using the properties panel "Display Filter" search it
# will create a new area that's not present in context.screen.areas for
# all property tabs except for the active property tab.
if current_area not in screen_areas:
current_area = next(a for a in context.screen.areas if a.x == current_area.x and a.y == current_area.y)
area_index = screen_areas.index(current_area)
return context.screen.BIMAreaProperties[area_index].tab == tab
return aprops.tab == tab
@classmethod
def is_default_scene(cls):
@@ -679,7 +694,9 @@ class Blender(blenderbim.core.tool.Blender):
bpy.utils.register_tool(
ws_structural.StructuralTool, after={"bim.spatial_tool"}, separator=False, group=False
)
bpy.utils.register_tool(ws_covering.CoveringTool, after={"bim.structural_tool"}, separator=False, group=False)
bpy.utils.register_tool(
ws_covering.CoveringTool, after={"bim.structural_tool"}, separator=False, group=False
)
except:
pass