diff --git a/src/bonsai/bonsai/bim/helper.py b/src/bonsai/bonsai/bim/helper.py
index 510966e5ef..2dbf5a55ea 100644
--- a/src/bonsai/bonsai/bim/helper.py
+++ b/src/bonsai/bonsai/bim/helper.py
@@ -35,6 +35,7 @@ from typing import Optional, Callable, Any, Union, Iterable, TYPE_CHECKING
if TYPE_CHECKING:
import bonsai.bim.prop
+ from bonsai.bim.prop import Attribute
# ImportCallback return values:
# - None - property should be imported by default workflow
@@ -48,7 +49,7 @@ if TYPE_CHECKING:
def draw_attributes(
- props: list[bonsai.bim.prop.Attribute],
+ props: bpy.types.bpy_prop_collection_idprop[Attribute],
layout: bpy.types.UILayout,
copy_operator: Optional[str] = None,
popup_active_attribute: Optional[bonsai.bim.prop.Attribute] = None,
@@ -117,7 +118,7 @@ def draw_attribute(
def import_attributes(
ifc_class: str,
- props: bpy.types.bpy_prop_collection,
+ props: bpy.types.bpy_prop_collection_idprop[Attribute],
data: dict[str, Any],
callback: Optional[ImportCallback] = None,
) -> None:
@@ -128,7 +129,7 @@ def import_attributes(
# A more elegant attribute importer signature, intended to supersede import_attributes
def import_attributes2(
element: Union[str, ifcopenshell.entity_instance],
- props: bpy.types.bpy_prop_collection,
+ props: bpy.types.bpy_prop_collection_idprop[Attribute],
callback: Optional[ImportCallback] = None,
) -> None:
if isinstance(element, str):
@@ -144,7 +145,7 @@ def import_attributes2(
def import_attribute(
attribute: W.attribute,
- props: bpy.types.bpy_prop_collection,
+ props: bpy.types.bpy_prop_collection_idprop[Attribute],
data: dict[str, Any],
callback: Optional[ImportCallback] = None,
) -> None:
@@ -258,7 +259,7 @@ def add_attribute_description(attribute_blender: bonsai.bim.prop.Attribute, attr
def export_attributes(
- props: bpy.types.bpy_prop_collection,
+ props: bpy.types.bpy_prop_collection_idprop[Attribute],
callback: Optional[ExportCallback] = None,
) -> dict[str, Any]:
attributes: dict[str, Any] = {}
diff --git a/src/bonsai/bonsai/bim/module/project/operator.py b/src/bonsai/bonsai/bim/module/project/operator.py
index 24deefbe2a..9a2c562818 100644
--- a/src/bonsai/bonsai/bim/module/project/operator.py
+++ b/src/bonsai/bonsai/bim/module/project/operator.py
@@ -313,7 +313,7 @@ class RewindLibrary(bpy.types.Operator):
bl_options = {"REGISTER", "UNDO"}
def execute(self, context):
- self.props = context.scene.BIMProjectProperties
+ self.props = tool.Project.get_project_props()
total_breadcrumbs = len(self.props.library_breadcrumb)
if total_breadcrumbs < 2:
bpy.ops.bim.refresh_library()
diff --git a/src/bonsai/bonsai/bim/module/pset/prop.py b/src/bonsai/bonsai/bim/module/pset/prop.py
index 88491bf32a..3f73fa4acd 100644
--- a/src/bonsai/bonsai/bim/module/pset/prop.py
+++ b/src/bonsai/bonsai/bim/module/pset/prop.py
@@ -38,7 +38,7 @@ from bpy.props import (
FloatVectorProperty,
CollectionProperty,
)
-from typing import Union, Literal, TYPE_CHECKING, get_args
+from typing import Union, Literal, TYPE_CHECKING, get_args, Literal
psetnames = {}
qtonames = {}
@@ -259,6 +259,17 @@ class PsetProperties(PropertyGroup):
prop_name: StringProperty(name="Property Name", default="MyProperty")
prop_value: StringProperty(name="Property Value", default="Some Value")
+ if TYPE_CHECKING:
+ active_pset_id: int
+ active_pset_has_template: bool
+ active_pset_name: str
+ active_pset_type: Literal["-", "PSET", "QTO"]
+ properties: bpy.types.bpy_prop_collection_idprop[IfcProperty]
+ pset_name: str
+ qto_name: str
+ prop_name: str
+ prop_value: str
+
class RenameProperties(PropertyGroup):
pset_name: StringProperty(name="Pset")
diff --git a/src/bonsai/bonsai/tool/cost.py b/src/bonsai/bonsai/tool/cost.py
index 3e9f11e17f..164edfe02e 100644
--- a/src/bonsai/bonsai/tool/cost.py
+++ b/src/bonsai/bonsai/tool/cost.py
@@ -248,7 +248,9 @@ class Cost(bonsai.core.tool.Cost):
cls, cost_item: ifcopenshell.entity_instance, related_object_type: RELATED_OBJECT_TYPE
) -> None:
def create_list_items(
- collection: bpy.types.bpy_prop_collection, cost_item: ifcopenshell.entity_instance, is_deep: bool
+ collection: bpy.types.bpy_prop_collection_idprop[bonsai.bim.helper.Attribute],
+ cost_item: ifcopenshell.entity_instance,
+ is_deep: bool,
) -> None:
products = cls.get_cost_item_assignments(cost_item, filter_by_type=related_object_type, is_deep=False)
for product in products:
diff --git a/src/bonsai/bonsai/tool/pset.py b/src/bonsai/bonsai/tool/pset.py
index 7c07010fa8..05dde3c7b3 100644
--- a/src/bonsai/bonsai/tool/pset.py
+++ b/src/bonsai/bonsai/tool/pset.py
@@ -16,6 +16,7 @@
# You should have received a copy of the GNU General Public License
# along with Bonsai. If not, see .
+from __future__ import annotations
import bpy
import ifcopenshell
import ifcopenshell.api.pset
@@ -24,10 +25,14 @@ import ifcopenshell.util.element
import bonsai.core.tool
import bonsai.tool as tool
import bonsai.bim.schema
-from typing import Union, Literal, Any
+from typing import Union, Literal, Any, TYPE_CHECKING
from typing_extensions import assert_never
+if TYPE_CHECKING:
+ from bonsai.bim.module.pset.prop import PsetProperties
+
+
class Pset(bonsai.core.tool.Pset):
PSET_TYPE = Literal["PSET", "QTO"]
@@ -40,7 +45,7 @@ class Pset(bonsai.core.tool.Pset):
return tool.Ifc.get().by_id(pset["id"])
@classmethod
- def get_pset_props(cls, obj: str, obj_type: tool.Ifc.OBJECT_TYPE) -> bpy.types.PropertyGroup:
+ def get_pset_props(cls, obj: str, obj_type: tool.Ifc.OBJECT_TYPE) -> PsetProperties:
if obj_type == "Object":
return bpy.data.objects.get(obj).PsetProperties
elif obj_type == "Material":
diff --git a/src/bonsai/bonsai/tool/search.py b/src/bonsai/bonsai/tool/search.py
index b328016a9c..3b90961559 100644
--- a/src/bonsai/bonsai/tool/search.py
+++ b/src/bonsai/bonsai/tool/search.py
@@ -16,7 +16,7 @@
# You should have received a copy of the GNU General Public License
# along with Bonsai. If not, see .
-
+from __future__ import annotations
import bpy
import json
import lark
@@ -26,7 +26,10 @@ import ifcopenshell.guid
import ifcopenshell.util.selector
from itertools import cycle
from bonsai.bim.prop import BIMFacet
-from typing import Union, Literal
+from typing import Union, Literal, TYPE_CHECKING
+
+if TYPE_CHECKING:
+ from bonsai.bim.prop import BIMFilterGroup
class Search(bonsai.core.tool.Search):
@@ -35,7 +38,7 @@ class Search(bonsai.core.tool.Search):
return json.loads(group.Description)["query"]
@classmethod
- def get_filter_groups(cls, module: str) -> bpy.types.bpy_prop_collection:
+ def get_filter_groups(cls, module: str) -> bpy.types.bpy_prop_collection_idprop[BIMFilterGroup]:
if module == "search":
return bpy.context.scene.BIMSearchProperties.filter_groups
elif module == "csv":
@@ -54,13 +57,15 @@ class Search(bonsai.core.tool.Search):
assert False, f"Unsupported module: {module}"
@classmethod
- def import_filter_query(cls, query: str, filter_groups: bpy.types.bpy_prop_collection) -> None:
+ def import_filter_query(
+ cls, query: str, filter_groups: bpy.types.bpy_prop_collection_idprop[BIMFilterGroup]
+ ) -> None:
filter_groups.clear()
transformer = ImportFilterQueryTransformer(filter_groups)
transformer.transform(ifcopenshell.util.selector.filter_elements_grammar.parse(query))
@classmethod
- def export_filter_query(cls, filter_groups: bpy.types.bpy_prop_collection) -> str:
+ def export_filter_query(cls, filter_groups: bpy.types.bpy_prop_collection_idprop[BIMFilterGroup]) -> str:
query = []
for filter_group in filter_groups:
filter_group_query = []
@@ -300,7 +305,7 @@ class Search(bonsai.core.tool.Search):
class ImportFilterQueryTransformer(lark.Transformer):
- def __init__(self, filter_groups):
+ def __init__(self, filter_groups: bpy.types.bpy_prop_collection_idprop[BIMFilterGroup]):
self.filter_groups = filter_groups
def get_results(self):