mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-09 09:21:46 +00:00
move scene panels from different addons to "Blender Properties"
now we also automatically get list of default blender scene panels instead of hardcoding them
This commit is contained in:
@@ -31,6 +31,7 @@ from blenderbim.bim.module.model.data import AuthoringData
|
||||
from blenderbim.bim.module.model.workspace import LIST_OF_TOOLS, TOOLS_TO_CLASSES_MAP
|
||||
from mathutils import Vector
|
||||
from math import cos, degrees
|
||||
from typing import Union
|
||||
|
||||
|
||||
cwd = os.path.dirname(os.path.realpath(__file__))
|
||||
@@ -286,26 +287,7 @@ def get_override_scene_panel(panel_name):
|
||||
return override_panel
|
||||
|
||||
|
||||
# TODO: possibly override scene panels from other addons too?
|
||||
# list can be updated from
|
||||
# https://projects.blender.org/blender/blender/src/branch/main/scripts/startup/bl_ui/properties_scene.py#L421
|
||||
OVERRIDE_SCENE_PANELS = (
|
||||
"SCENE_PT_scene",
|
||||
"SCENE_PT_unit",
|
||||
"SCENE_PT_physics",
|
||||
"SCENE_PT_rigid_body_world",
|
||||
"SCENE_PT_rigid_body_world_settings",
|
||||
"SCENE_PT_rigid_body_cache",
|
||||
"SCENE_PT_rigid_body_field_weights",
|
||||
"SCENE_PT_audio",
|
||||
"SCENE_PT_keying_sets",
|
||||
"SCENE_PT_custom_props",
|
||||
# after SCENE_PT_keying_sets
|
||||
"SCENE_PT_keying_set_paths",
|
||||
"SCENE_PT_keyframing_settings",
|
||||
)
|
||||
if bpy.app.version >= (4, 0):
|
||||
OVERRIDE_SCENE_PANELS += ("SCENE_PT_simulation",)
|
||||
OVERRIDE_SCENE_PANELS = tool.Blender.get_scene_panels_list()
|
||||
|
||||
|
||||
@persistent
|
||||
|
||||
@@ -875,3 +875,58 @@ class Blender(blenderbim.core.tool.Blender):
|
||||
bpy.utils.unregister_tool(ws_covering.CoveringTool)
|
||||
except:
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
def get_scene_panels_list(cls) -> tuple[str, ...]:
|
||||
# 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] = []
|
||||
panels_to_parents: dict[str, str] = dict()
|
||||
for item_name in dir(bpy.types):
|
||||
item = getattr(bpy.types, item_name)
|
||||
# filter only panels
|
||||
if not hasattr(item, "bl_rna") or not isinstance(item.bl_rna, bpy.types.Panel):
|
||||
continue
|
||||
# filter scene panels
|
||||
if getattr(item, "bl_context", None) != "scene":
|
||||
continue
|
||||
scene_panels.append(item_name)
|
||||
parent_panel = getattr(item, "bl_parent_id", None)
|
||||
if parent_panel is not None:
|
||||
panels_to_parents[item_name] = parent_panel
|
||||
|
||||
scene_panels = cls.sort_panels_for_register(scene_panels, panels_to_parents)
|
||||
return tuple(scene_panels)
|
||||
|
||||
@classmethod
|
||||
def sort_panels_for_register(cls, items: list[str], items_to_parents: dict[str, str]) -> list[str]:
|
||||
"""sort panels ensuring parents panels will be registered first
|
||||
as otherwise we'll get errors unregistering them all and registering child panel"""
|
||||
final_items = []
|
||||
unsorted = items.copy()
|
||||
|
||||
# first, add items without parents
|
||||
for item in unsorted[:]:
|
||||
if item not in items_to_parents:
|
||||
final_items.append(item)
|
||||
unsorted.remove(item)
|
||||
|
||||
# store children for each parent
|
||||
children: dict[str, list[str]] = dict()
|
||||
for item in items_to_parents:
|
||||
children.setdefault(items_to_parents[item], []).append(item)
|
||||
|
||||
# add children recursively, ensuring parents are added first
|
||||
keep_looking = True
|
||||
while keep_looking:
|
||||
keep_looking = False
|
||||
for item in list(children.keys()):
|
||||
# check if parent panel was already added
|
||||
if item not in final_items:
|
||||
continue
|
||||
final_items.extend(children[item])
|
||||
del children[item]
|
||||
keep_looking = True
|
||||
|
||||
assert set(items) == set(final_items), "Sorted list doesn't match original"
|
||||
return final_items
|
||||
|
||||
@@ -20,6 +20,7 @@ import bpy
|
||||
import ifcopenshell
|
||||
import blenderbim.core.tool
|
||||
import blenderbim.tool as tool
|
||||
import pytest
|
||||
from test.bim.bootstrap import NewFile
|
||||
from blenderbim.tool.blender import Blender as subject
|
||||
|
||||
@@ -44,3 +45,17 @@ class TestCopyNodeGraph(NewFile):
|
||||
|
||||
subject.copy_node_graph(material_to, material_from)
|
||||
assert len(material_to_nodes) == 2
|
||||
|
||||
|
||||
class TestSortPanelsForRegister(NewFile):
|
||||
def test_run(self):
|
||||
items = ["A", "B", "C", "D"]
|
||||
items_to_parents = {"A": "D", "D": "C", "C": "B"}
|
||||
sorted_items = subject.sort_panels_for_register(items, items_to_parents)
|
||||
assert tuple(sorted_items) == ("B", "C", "D", "A")
|
||||
|
||||
with pytest.raises(AssertionError):
|
||||
subject.sort_panels_for_register(items, {"A": "K"})
|
||||
|
||||
with pytest.raises(AssertionError):
|
||||
subject.sort_panels_for_register(items, {"J": "A"})
|
||||
|
||||
Reference in New Issue
Block a user