From 696c6b09b0cb336780905e0723186eec0c655004 Mon Sep 17 00:00:00 2001 From: Andrej730 Date: Fri, 31 May 2024 16:19:18 +0500 Subject: [PATCH] materials ui - preserve selected category on expanding/contracting all categories --- src/blenderbim/blenderbim/tool/material.py | 33 +++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/src/blenderbim/blenderbim/tool/material.py b/src/blenderbim/blenderbim/tool/material.py index e52b7abbf0..a927e99bd6 100644 --- a/src/blenderbim/blenderbim/tool/material.py +++ b/src/blenderbim/blenderbim/tool/material.py @@ -16,6 +16,7 @@ # You should have received a copy of the GNU General Public License # along with BlenderBIM Add-on. If not, see . +from __future__ import annotations import bpy import ifcopenshell import blenderbim.core.tool @@ -25,7 +26,11 @@ import blenderbim.bim.helper import ifcopenshell.util.unit import ifcopenshell.util.element from collections import defaultdict -from typing import Union, Any +from typing import Union, Any, TYPE_CHECKING + +if TYPE_CHECKING: + # Avoid circular imports. + from blenderbim.bim.module.material.prop import Material as MaterialItem class Material(blenderbim.core.tool.Material): @@ -57,9 +62,25 @@ class Material(blenderbim.core.tool.Material): def get_name(cls, obj: bpy.types.Material) -> str: return obj.name + @classmethod + def get_active_material_item(cls) -> Union[MaterialItem, None]: + """Get active material props item if index is valid, otherwise, return None.""" + props = bpy.context.scene.BIMMaterialProperties + if 0 <= props.active_material_index < len(props.materials): + return props.materials[props.active_material_index] + return None + @classmethod def import_material_definitions(cls, material_type: str) -> None: props = bpy.context.scene.BIMMaterialProperties + + # Store active category name to reselect it later. + # Occurs when we expand/contract all categories. + active_item = cls.get_active_material_item() + previously_selected_category = None + if active_item and active_item.is_category: + previously_selected_category = active_item.name + expanded_categories = {m.name for m in props.materials if m.is_category and m.is_expanded} props.materials.clear() get_name = lambda x: x.Name or "Unnamed" @@ -70,16 +91,23 @@ class Material(blenderbim.core.tool.Material): materials = sorted(tool.Ifc.get().by_type(material_type), key=get_name) categories = defaultdict(list) if material_type == "IfcMaterial": + category_index_to_reselect = None + for m in materials: # IfcMaterial has Category since IFC4. category = getattr(m, "Category", None) category = category or "Uncategorised" categories[category].append(m) + for category, mats in categories.items(): cat = props.materials.add() cat.name = category cat.is_category = True cat.is_expanded = cat.name in expanded_categories + + if previously_selected_category == category: + category_index_to_reselect = len(props.materials) - 1 + for material in mats if cat.is_expanded else []: new = props.materials.add() new.ifc_definition_id = material.id() @@ -88,6 +116,9 @@ class Material(blenderbim.core.tool.Material): ifcopenshell.util.element.get_elements_by_material(tool.Ifc.get(), material) ) new.has_style = bool(material.HasRepresentation) + + if category_index_to_reselect is not None: + props.active_material_index = category_index_to_reselect return for material in materials: new = props.materials.add()