Fix registration bug that created hundreds of workspaces due to continuous triggering of the depsgraph_update.

Use an is_registering check to only run the on_register once.

Rename setDefaultProperties to load_post to better reflect what handler it is.

Unregister our custom scene panels upon addon activation.

Move aprops getting to tool.Blender because it is a bit complex. Also, aprops may not be setup until load_post is called, so the len() check protects against that.
This commit is contained in:
Dion Moult
2023-07-11 17:40:13 +10:00
parent 86dd79daa6
commit 8689164769
6 changed files with 66 additions and 52 deletions
+24 -3
View File
@@ -149,12 +149,19 @@ for mod in modules.values():
addon_keymaps = [] addon_keymaps = []
icons = None icons = None
is_registering = False
def on_register(scene): def on_register(scene):
handler.setDefaultProperties(scene) global is_registering
if is_registering:
return
is_registering = True
handler.load_post(scene)
if not bpy.app.background: if not bpy.app.background:
bpy.app.handlers.depsgraph_update_post.remove(on_register) bpy.app.handlers.depsgraph_update_post.remove(on_register)
is_registering = False
def register(): def register():
@@ -165,7 +172,7 @@ def register():
bpy.app.handlers.undo_post.append(handler.undo_post) bpy.app.handlers.undo_post.append(handler.undo_post)
bpy.app.handlers.redo_pre.append(handler.redo_pre) bpy.app.handlers.redo_pre.append(handler.redo_pre)
bpy.app.handlers.redo_post.append(handler.redo_post) bpy.app.handlers.redo_post.append(handler.redo_post)
bpy.app.handlers.load_post.append(handler.setDefaultProperties) bpy.app.handlers.load_post.append(handler.load_post)
bpy.app.handlers.load_post.append(handler.loadIfcStore) bpy.app.handlers.load_post.append(handler.loadIfcStore)
bpy.app.handlers.save_post.append(handler.ensureIfcExported) bpy.app.handlers.save_post.append(handler.ensureIfcExported)
bpy.types.Scene.BIMProperties = bpy.props.PointerProperty(type=prop.BIMProperties) bpy.types.Scene.BIMProperties = bpy.props.PointerProperty(type=prop.BIMProperties)
@@ -215,7 +222,7 @@ def unregister():
elif cls.is_registered: elif cls.is_registered:
bpy.utils.unregister_class(cls) bpy.utils.unregister_class(cls)
bpy.app.handlers.load_post.remove(handler.setDefaultProperties) bpy.app.handlers.load_post.remove(handler.load_post)
bpy.app.handlers.load_post.remove(handler.loadIfcStore) bpy.app.handlers.load_post.remove(handler.loadIfcStore)
bpy.app.handlers.save_post.remove(handler.ensureIfcExported) bpy.app.handlers.save_post.remove(handler.ensureIfcExported)
del bpy.types.Scene.BIMProperties del bpy.types.Scene.BIMProperties
@@ -240,3 +247,17 @@ def unregister():
for km, kmi in addon_keymaps: for km, kmi in addon_keymaps:
km.keymap_items.remove(kmi) km.keymap_items.remove(kmi)
addon_keymaps.clear() addon_keymaps.clear()
for panel in [
"SCENE_PT_scene",
"SCENE_PT_unit",
"SCENE_PT_physics",
"SCENE_PT_rigid_body_world",
"SCENE_PT_audio",
"SCENE_PT_keying_sets",
"SCENE_PT_custom_props",
]:
try:
bpy.utils.unregister_class(getattr(handler, f"Override_{panel}"))
except:
pass
+1 -1
View File
@@ -351,7 +351,7 @@ if getattr(bpy.types, "SCENE_PT_custom_props"):
@persistent @persistent
def setDefaultProperties(scene): def load_post(scene):
global global_subscription_owner global global_subscription_owner
active_object_key = bpy.types.LayerObjects, "active" active_object_key = bpy.types.LayerObjects, "active"
bpy.msgbus.subscribe_rna( bpy.msgbus.subscribe_rna(
@@ -22,6 +22,7 @@ from blenderbim.bim.helper import prop_with_search
from blenderbim.bim.module.brick.data import BrickschemaData, BrickschemaReferencesData from blenderbim.bim.module.brick.data import BrickschemaData, BrickschemaReferencesData
from blenderbim.tool.brick import BrickStore from blenderbim.tool.brick import BrickStore
class BIM_PT_brickschema(Panel): class BIM_PT_brickschema(Panel):
bl_label = "Brickschema Project" bl_label = "Brickschema Project"
bl_idname = "BIM_PT_brickschema" bl_idname = "BIM_PT_brickschema"
@@ -32,8 +33,7 @@ class BIM_PT_brickschema(Panel):
@classmethod @classmethod
def poll(cls, context): def poll(cls, context):
aprops = tool.Blender.get_area_properties(context) return tool.Blender.is_tab(context, "OTHER")
return aprops.tab == "OTHER" or context.area.spaces.active.search_filter
def draw(self, context): def draw(self, context):
if not BrickschemaData.is_loaded: if not BrickschemaData.is_loaded:
@@ -48,7 +48,7 @@ class BIM_PT_brickschema(Panel):
if BrickStore.path: if BrickStore.path:
row = self.layout.row(align=True) row = self.layout.row(align=True)
row.label(text=BrickStore.path, icon='FILEBROWSER') row.label(text=BrickStore.path, icon="FILEBROWSER")
row = self.layout.row(align=True) row = self.layout.row(align=True)
if len(self.props.brick_breadcrumbs): if len(self.props.brick_breadcrumbs):
@@ -70,7 +70,7 @@ class BIM_PT_brickschema(Panel):
row.prop(data=self.props, property="new_brick_namespace_alias", text="") row.prop(data=self.props, property="new_brick_namespace_alias", text="")
col = row.column() col = row.column()
col.alignment = "CENTER" col.alignment = "CENTER"
col.scale_x = 1.1 col.scale_x = 1.1
col.label(text=":") col.label(text=":")
row.prop(data=self.props, property="new_brick_namespace_uri", text="") row.prop(data=self.props, property="new_brick_namespace_uri", text="")
row.operator("bim.add_brick_namespace", text="", icon="ADD") row.operator("bim.add_brick_namespace", text="", icon="ADD")
@@ -167,8 +167,7 @@ class BIM_PT_drawings(Panel):
@classmethod @classmethod
def poll(cls, context): def poll(cls, context):
aprops = tool.Blender.get_area_properties(context) return tool.Blender.is_tab(context, "DRAWINGS") and tool.Ifc.get()
return (aprops.tab == "DRAWINGS" or context.area.spaces.active.search_filter) and tool.Ifc.get()
def draw(self, context): def draw(self, context):
if not DrawingsData.is_loaded: if not DrawingsData.is_loaded:
@@ -236,8 +235,7 @@ class BIM_PT_schedules(Panel):
@classmethod @classmethod
def poll(cls, context): def poll(cls, context):
aprops = tool.Blender.get_area_properties(context) return tool.Blender.is_tab(context, "DRAWINGS") and tool.Ifc.get()
return (aprops.tab == "DRAWINGS" or context.area.spaces.active.search_filter) and tool.Ifc.get()
def draw(self, context): def draw(self, context):
if not DocumentsData.is_loaded: if not DocumentsData.is_loaded:
@@ -292,8 +290,7 @@ class BIM_PT_references(Panel):
@classmethod @classmethod
def poll(cls, context): def poll(cls, context):
aprops = tool.Blender.get_area_properties(context) return tool.Blender.is_tab(context, "DRAWINGS") and tool.Ifc.get()
return (aprops.tab == "DRAWINGS" or context.area.spaces.active.search_filter) and tool.Ifc.get()
def draw(self, context): def draw(self, context):
if not DocumentsData.is_loaded: if not DocumentsData.is_loaded:
@@ -337,8 +334,7 @@ class BIM_PT_sheets(Panel):
@classmethod @classmethod
def poll(cls, context): def poll(cls, context):
aprops = tool.Blender.get_area_properties(context) return tool.Blender.is_tab(context, "DRAWINGS") and tool.Ifc.get()
return (aprops.tab == "DRAWINGS" or context.area.spaces.active.search_filter) and tool.Ifc.get()
def draw(self, context): def draw(self, context):
if not SheetsData.is_loaded: if not SheetsData.is_loaded:
+17 -24
View File
@@ -278,10 +278,13 @@ class BIM_PT_root(Panel):
bl_options = {"HIDE_HEADER"} bl_options = {"HIDE_HEADER"}
def draw(self, context): def draw(self, context):
aprops = tool.Blender.get_area_properties(context) try:
row = self.layout.row(align=True) aprops = context.screen.BIMAreaProperties[context.screen.areas[:].index(context.area)]
row.prop(aprops, "tab", text="") row = self.layout.row(align=True)
row.operator("bim.switch_tab", text="", icon="UV_SYNC_SELECT") row.prop(aprops, "tab", text="")
row.operator("bim.switch_tab", text="", icon="UV_SYNC_SELECT")
except:
pass # Prior to load_post, we may not have any area properties setup
class BIM_PT_project_info(Panel): class BIM_PT_project_info(Panel):
@@ -292,8 +295,7 @@ class BIM_PT_project_info(Panel):
@classmethod @classmethod
def poll(cls, context): def poll(cls, context):
aprops = tool.Blender.get_area_properties(context) return tool.Blender.is_tab(context, "PROJECT")
return aprops.tab == "PROJECT" or context.area.spaces.active.search_filter
def draw(self, context): def draw(self, context):
pass pass
@@ -308,8 +310,7 @@ class BIM_PT_project_setup(Panel):
@classmethod @classmethod
def poll(cls, context): def poll(cls, context):
aprops = tool.Blender.get_area_properties(context) return tool.Blender.is_tab(context, "PROJECT")
return aprops.tab == "PROJECT" or context.area.spaces.active.search_filter
def draw(self, context): def draw(self, context):
pass pass
@@ -324,8 +325,7 @@ class BIM_PT_collaboration(Panel):
@classmethod @classmethod
def poll(cls, context): def poll(cls, context):
aprops = tool.Blender.get_area_properties(context) return tool.Blender.is_tab(context, "OTHER")
return aprops.tab == "OTHER" or context.area.spaces.active.search_filter
def draw(self, context): def draw(self, context):
pass pass
@@ -340,8 +340,7 @@ class BIM_PT_selection(Panel):
@classmethod @classmethod
def poll(cls, context): def poll(cls, context):
aprops = tool.Blender.get_area_properties(context) return tool.Blender.is_tab(context, "PROJECT") and tool.Ifc.get()
return (aprops.tab == "PROJECT" or context.area.spaces.active.search_filter) and tool.Ifc.get()
def draw(self, context): def draw(self, context):
pass pass
@@ -356,8 +355,7 @@ class BIM_PT_geometry(Panel):
@classmethod @classmethod
def poll(cls, context): def poll(cls, context):
aprops = tool.Blender.get_area_properties(context) return tool.Blender.is_tab(context, "PROJECT") and tool.Ifc.get()
return (aprops.tab == "PROJECT" or context.area.spaces.active.search_filter) and tool.Ifc.get()
def draw(self, context): def draw(self, context):
pass pass
@@ -372,8 +370,7 @@ class BIM_PT_4D5D(Panel):
@classmethod @classmethod
def poll(cls, context): def poll(cls, context):
aprops = tool.Blender.get_area_properties(context) return tool.Blender.is_tab(context, "SCHEDULING") and tool.Ifc.get()
return (aprops.tab == "SCHEDULING" or context.area.spaces.active.search_filter) and tool.Ifc.get()
def draw(self, context): def draw(self, context):
pass pass
@@ -388,8 +385,7 @@ class BIM_PT_structural(Panel):
@classmethod @classmethod
def poll(cls, context): def poll(cls, context):
aprops = tool.Blender.get_area_properties(context) return tool.Blender.is_tab(context, "STRUCTURE") and tool.Ifc.get()
return (aprops.tab == "STRUCTURE" or context.area.spaces.active.search_filter) and tool.Ifc.get()
def draw(self, context): def draw(self, context):
pass pass
@@ -404,8 +400,7 @@ class BIM_PT_services(Panel):
@classmethod @classmethod
def poll(cls, context): def poll(cls, context):
aprops = tool.Blender.get_area_properties(context) return tool.Blender.is_tab(context, "SERVICES") and tool.Ifc.get()
return (aprops.tab == "SERVICES" or context.area.spaces.active.search_filter) and tool.Ifc.get()
def draw(self, context): def draw(self, context):
pass pass
@@ -420,8 +415,7 @@ class BIM_PT_quality_control(Panel):
@classmethod @classmethod
def poll(cls, context): def poll(cls, context):
aprops = tool.Blender.get_area_properties(context) return tool.Blender.is_tab(context, "OTHER")
return aprops.tab == "OTHER" or context.area.spaces.active.search_filter
def draw(self, context): def draw(self, context):
pass pass
@@ -436,8 +430,7 @@ class BIM_PT_integrations(Panel):
@classmethod @classmethod
def poll(cls, context): def poll(cls, context):
aprops = tool.Blender.get_area_properties(context) return tool.Blender.is_tab(context, "OTHER")
return aprops.tab == "OTHER" or context.area.spaces.active.search_filter
def draw(self, context): def draw(self, context):
pass pass
+16 -12
View File
@@ -41,6 +41,22 @@ class Blender:
bpy.context.view_layer.objects.active = obj bpy.context.view_layer.objects.active = obj
obj.select_set(True) obj.select_set(True)
@classmethod
def is_tab(cls, context, tab):
if not len(context.screen.BIMAreaProperties):
return None
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
@classmethod @classmethod
def get_name(cls, ifc_class, name): def get_name(cls, ifc_class, name):
if not bpy.data.objects.get(f"{ifc_class}/{name}"): if not bpy.data.objects.get(f"{ifc_class}/{name}"):
@@ -151,18 +167,6 @@ class Blender:
for attr in VIEWPORT_ATTRIBUTES: for attr in VIEWPORT_ATTRIBUTES:
setattr(region_3d, attr, data[attr]) setattr(region_3d, attr, data[attr])
@classmethod
def get_area_properties(cls, context):
areas = context.screen.areas[:]
current_area = context.area
# if user is using search from different properties tab (not SCENE)
# it will create new area that's not present in context.screen.areas
if current_area not in areas:
current_area = next(a for a in context.screen.areas if a.x == current_area.x and a.y == current_area.y)
area_i = areas.index(current_area)
return context.screen.BIMAreaProperties[area_i]
@classmethod @classmethod
def get_shader_editor_context(cls): def get_shader_editor_context(cls):
for screen in bpy.data.screens: for screen in bpy.data.screens: