change .poll for overridden panels instead of creating new classes

Needed to avoid errors disabling addons that have overridden panels
This commit is contained in:
Andrej730
2024-04-03 15:42:23 +05:00
parent c462fc9337
commit 5ac96cb5b9
3 changed files with 34 additions and 35 deletions
+14 -6
View File
@@ -23,6 +23,7 @@ import bpy.utils.previews
import blenderbim
import importlib
from . import handler, ui, prop, operator, helper
from typing import Callable, Union
try:
from blenderbim.translations import translations_dict
@@ -187,7 +188,7 @@ addon_keymaps = []
icons = None
is_registering = False
last_commit_hash = "8888888"
overridden_scene_panels = dict()
original_scene_panels_polls: dict[bpy.types.Panel, Union[Callable, None]] = dict()
def on_register(scene):
@@ -295,10 +296,17 @@ def unregister():
km.keymap_items.remove(kmi)
addon_keymaps.clear()
for panel in tuple(overridden_scene_panels.keys()):
original_panel, override_panel = overridden_scene_panels[panel]
bpy.utils.unregister_class(override_panel)
bpy.utils.register_class(original_panel)
del overridden_scene_panels[panel]
for panel, poll in tuple(original_scene_panels_polls.items()):
if poll is None:
del panel.poll
else:
panel.poll = poll
# panel might be already unregisterd during blender exit
# or if it's addon was disabled
if panel.is_registered:
# reregister to activate new poll
bpy.utils.unregister_class(panel)
bpy.utils.register_class(panel)
del original_scene_panels_polls[panel]
bpy.app.translations.unregister("blenderbim")
+14 -27
View File
@@ -260,34 +260,25 @@ def poll_check_blender_tab(cls, context):
return tool.Blender.is_tab(context, "BLENDER")
def get_override_scene_panel(panel_name):
original_panel = getattr(bpy.types, panel_name)
override_panel = type(f"Override_{panel_name}", (original_panel,), {})
override_panel.bl_idname = f"{panel_name}_override"
# some blender panel depend on other and register_class will throw an error
# if we won't override their `bl_parent_id`
bl_parent_id = getattr(override_panel, "bl_parent_id", None)
if bl_parent_id is not None:
override_panel.bl_parent_id = f"{bl_parent_id}_override"
def override_scene_panel(original_panel: bpy.types.Panel) -> None:
polls = blenderbim.bim.original_scene_panels_polls
# override poll method
poll = getattr(override_panel, "poll", None)
if poll is None:
override_panel.poll = poll_check_blender_tab
if not hasattr(original_panel, "poll"):
polls[original_panel] = None
original_panel.poll = poll_check_blender_tab
else:
polls[original_panel] = original_panel.poll
@classmethod
def wrapped_poll(cls, context):
return super(override_panel, cls).poll(context) and poll_check_blender_tab.__func__(cls, context)
return polls[cls](context) and poll_check_blender_tab.__func__(cls, context)
override_panel.poll = wrapped_poll
original_panel.poll = wrapped_poll
return override_panel
OVERRIDE_SCENE_PANELS = tool.Blender.get_scene_panels_list()
# reregister to activate new poll
bpy.utils.unregister_class(original_panel)
bpy.utils.register_class(original_panel)
@persistent
@@ -328,12 +319,8 @@ def load_post(scene):
# To improve usability for new users, we hijack the scene properties
# tab. We override default scene properties panels with our own poll
# to hide them unless the user has chosen to view Blender properties.
for panel in OVERRIDE_SCENE_PANELS:
if panel in blenderbim.bim.overridden_scene_panels:
for panel in tool.Blender.get_scene_panels_list():
if panel in blenderbim.bim.original_scene_panels_polls:
continue
override_panel = get_override_scene_panel(panel)
original_panel = getattr(bpy.types, panel)
bpy.utils.register_class(override_panel)
bpy.utils.unregister_class(original_panel)
blenderbim.bim.overridden_scene_panels[panel] = (original_panel, override_panel)
override_scene_panel(panel)
tool.Blender.setup_tabs()
+6 -2
View File
@@ -877,7 +877,7 @@ class Blender(blenderbim.core.tool.Blender):
pass
@classmethod
def get_scene_panels_list(cls) -> tuple[str, ...]:
def get_scene_panels_list(cls) -> tuple[bpy.types.Panel, ...]:
# example default blender scene panels can be found in
# https://projects.blender.org/blender/blender/src/branch/main/scripts/startup/bl_ui/properties_scene.py#L421
scene_panels: list[str] = []
@@ -887,6 +887,9 @@ class Blender(blenderbim.core.tool.Blender):
# filter only panels
if not hasattr(item, "bl_rna") or not isinstance(item.bl_rna, bpy.types.Panel):
continue
# ignore bbim panels
if item.__module__.startswith("blenderbim"):
continue
# filter scene panels
if getattr(item, "bl_context", None) != "scene":
continue
@@ -896,7 +899,8 @@ class Blender(blenderbim.core.tool.Blender):
panels_to_parents[item_name] = parent_panel
scene_panels = cls.sort_panels_for_register(scene_panels, panels_to_parents)
return tuple(scene_panels)
final_panels = [getattr(bpy.types, p) for p in scene_panels]
return tuple(final_panels)
@classmethod
def sort_panels_for_register(cls, items: list[str], items_to_parents: dict[str, str]) -> list[str]: