From 1aaccba80368b9907f748172cc69e3a56d6adb85 Mon Sep 17 00:00:00 2001 From: Andrej730 Date: Wed, 22 May 2024 18:44:12 +0500 Subject: [PATCH] simpler way to check if enum property is valid MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Well, it's simpler to use but not really simpler in implementation 😅 Thanks to @Gorgious56 for helping out Hopefully, it's a farewell to those annoying warnings see https://blenderartists.org/t/best-way-to-handle-dynamic-enum-items-without-pyrna-enum-to-py-current-value-matches-no-enum --- .../blenderbim/bim/module/model/data.py | 11 +++--- .../blenderbim/bim/module/model/prop.py | 2 +- src/blenderbim/blenderbim/tool/blender.py | 37 +++++++++++++++---- 3 files changed, 35 insertions(+), 15 deletions(-) diff --git a/src/blenderbim/blenderbim/bim/module/model/data.py b/src/blenderbim/blenderbim/bim/module/model/data.py index 3f3ca4a4bb..7f39a44552 100644 --- a/src/blenderbim/blenderbim/bim/module/model/data.py +++ b/src/blenderbim/blenderbim/bim/module/model/data.py @@ -121,9 +121,10 @@ class AuthoringData: def type_thumbnail(cls): if not cls.data["relating_type_id"]: return 0 - if not tool.Blender.enum_property_has_valid_index(cls.props, "relating_type_id", cls.data["relating_type_id"]): + relating_type_id = tool.Blender.get_enum_safe(cls.props, "relating_type_id") + if relating_type_id is None: return 0 - element = tool.Ifc.get().by_id(int(cls.props.relating_type_id)) + element = tool.Ifc.get().by_id(int(relating_type_id)) return cls.type_thumbnails.get(element.id(), None) or 0 @classmethod @@ -251,10 +252,8 @@ class AuthoringData: @classmethod def predefined_type(cls): - if not tool.Blender.enum_property_has_valid_index(cls.props, "relating_type_id", cls.data["relating_type_id"]): - return - relating_type_id = cls.props.relating_type_id - if not relating_type_id: + relating_type_id = tool.Blender.get_enum_safe(cls.props, "relating_type_id") + if relating_type_id is None: return relating_type = tool.Ifc.get().by_id(int(relating_type_id)) if not hasattr(relating_type, "PredefinedType"): diff --git a/src/blenderbim/blenderbim/bim/module/model/prop.py b/src/blenderbim/blenderbim/bim/module/model/prop.py index 81f763068f..3b55cc945b 100644 --- a/src/blenderbim/blenderbim/bim/module/model/prop.py +++ b/src/blenderbim/blenderbim/bim/module/model/prop.py @@ -60,7 +60,7 @@ def update_ifc_class(self, context): bpy.ops.bim.load_type_thumbnails(ifc_class=self.ifc_class) AuthoringData.data["relating_type_id"] = AuthoringData.relating_type_id() AuthoringData.data["type_thumbnail"] = AuthoringData.type_thumbnail() - if not tool.Blender.enum_property_has_valid_index(self, "relating_type_id", AuthoringData.data["relating_type_id"]): + if tool.Blender.get_enum_safe(self, "relating_type_id") is None: self["relating_type_id"] = 0 diff --git a/src/blenderbim/blenderbim/tool/blender.py b/src/blenderbim/blenderbim/tool/blender.py index af06cb5898..9a102c5399 100644 --- a/src/blenderbim/blenderbim/tool/blender.py +++ b/src/blenderbim/blenderbim/tool/blender.py @@ -468,20 +468,41 @@ class Blender(blenderbim.core.tool.Blender): active_object.select_set(True) @classmethod - def enum_property_has_valid_index(cls, props: bpy.types.PropertyGroup, prop_name: str, enum_items: tuple) -> bool: + def get_enum_safe(cls, props: bpy.types.PropertyGroup, prop_name: str) -> Union[str, None]: """method created for readibility and to avoid console warnings like `pyrna_enum_to_py: current value '17' matches no enum in 'BIMModelProperties', '', 'relating_type_id'` """ - items_amount = len(enum_items) + # Yes, accessing items through annotations is a bit hacky + # but it's the only way to get the dynamic enum items + # besides providing them to get_enum_safe explicitly. + prop_keywords = props.__annotations__[prop_name].keywords + items = prop_keywords.get("items") + if items is None: + return None + if not isinstance(items, (list, tuple)): + # items are retrieved through a callback, not a static list / tuple : + items = items(props, bpy.context) + + items_amount = len(items) # If enum has no items it seems to always produce a warning. # E.g. if you try to get it's value directly: `BIMModelProperties.relating_type_id`. if items_amount == 0: - return False - current_value_index = props.get(prop_name, None) - # assuming the default value is fine - if current_value_index is None: - return True - return current_value_index < items_amount + return None + + index = props.get(prop_name) + # If value was never changed (still default), we can just retrieve it from the enum. + if index is None: + default_value = prop_keywords.get("default") + if isinstance(default_value, int): + index = default_value + else: + # If default value is a string then it's a static enum + # and we can just return it. + return default_value + # Ensure index is valid. + if items_amount > index >= 0: + return items[index][0] + return None @classmethod def append_data_block(cls, filepath: str, data_block_type: str, name: str, link=False, relative=False) -> dict: