You can now create new projects starting from a template.

This commit is contained in:
Dion Moult
2022-02-03 18:25:03 +11:00
parent 3e99393895
commit 89d5c44855
13 changed files with 466 additions and 73 deletions
@@ -75,7 +75,7 @@ class BIM_PT_aggregate(Panel):
row.operator("bim.add_aggregate", icon="ADD", text="")
row = layout.row(align=True)
parts = AggregateData.data['related_objects_amount']
parts = AggregateData.data["related_objects_amount"]
row.label(text=f"{parts or 'No'} Part{'s' if parts > 1 else ''}", icon="TRIA_DOWN")
if AggregateData.data["has_related_objects"]:
op = row.operator("bim.select_parts", icon="RESTRICT_SELECT_OFF", text="")
@@ -16,6 +16,7 @@
# You should have received a copy of the GNU General Public License
# along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>.
import os
import bpy
import blenderbim.tool as tool
from blenderbim.bim.ifc import IfcStore
@@ -31,9 +32,16 @@ class ProjectData:
@classmethod
def load(cls):
cls.data = {"export_schema": cls.get_export_schema()}
cls.data = {"export_schema": cls.get_export_schema(), "template_file": cls.template_file()}
cls.is_loaded = True
@classmethod
def get_export_schema(cls):
return [(s, s, "") for s in IfcStore.schema_identifiers]
@classmethod
def template_file(cls):
files = os.listdir(os.path.join(bpy.context.scene.BIMProperties.data_dir, "libraries"))
results = [("0", "Blank Project", "")]
results.extend([(f, f.replace(".ifc", ""), "") for f in files if ".ifc" in f])
return results
@@ -27,6 +27,7 @@ import ifcopenshell.util.selector
import ifcopenshell.util.representation
import blenderbim.bim.handler
import blenderbim.tool as tool
import blenderbim.core.project as core
import blenderbim.core.context
import blenderbim.core.owner
from blenderbim.bim.ifc import IfcStore
@@ -45,80 +46,16 @@ class CreateProject(bpy.types.Operator):
def execute(self, context):
IfcStore.begin_transaction(self)
IfcStore.add_transaction_operation(self, rollback=self.rollback, commit=lambda data: True)
result = self._execute(context)
self.transaction_data = {"file": self.file}
self._execute(context)
self.transaction_data = {"file": tool.Ifc.get()}
IfcStore.add_transaction_operation(self, rollback=lambda data: True, commit=self.commit)
IfcStore.end_transaction(self)
return result
def _execute(self, context):
active_object = context.view_layer.objects.active
self.file = IfcStore.get_file()
if self.file:
return {"FINISHED"}
IfcStore.file = ifcopenshell.api.run(
"project.create_file", **{"version": context.scene.BIMProjectProperties.export_schema}
)
self.file = IfcStore.get_file()
if self.file.schema == "IFC2X3":
person = blenderbim.core.owner.add_person(tool.Ifc)
organisation = blenderbim.core.owner.add_organisation(tool.Ifc)
user = blenderbim.core.owner.add_person_and_organisation(tool.Ifc, person=person, organisation=organisation)
blenderbim.core.owner.set_user(tool.Owner, user=user)
project = bpy.data.objects.new(self.get_name("IfcProject", "My Project"), None)
site = bpy.data.objects.new(self.get_name("IfcSite", "My Site"), None)
building = bpy.data.objects.new(self.get_name("IfcBuilding", "My Building"), None)
building_storey = bpy.data.objects.new(self.get_name("IfcBuildingStorey", "My Storey"), None)
bpy.ops.bim.assign_class(obj=project.name, ifc_class="IfcProject")
blenderbim.core.unit.assign_scene_units(tool.Ifc, tool.Unit)
model = blenderbim.core.context.add_context(
tool.Ifc, context_type="Model", context_identifier="", target_view="", parent=0
)
body_context = blenderbim.core.context.add_context(
tool.Ifc, context_type="Model", context_identifier="Body", target_view="MODEL_VIEW", parent=model
)
blenderbim.core.context.add_context(
tool.Ifc, context_type="Model", context_identifier="Box", target_view="MODEL_VIEW", parent=model
)
plan = blenderbim.core.context.add_context(
tool.Ifc, context_type="Plan", context_identifier="", target_view="", parent=0
)
blenderbim.core.context.add_context(
tool.Ifc, context_type="Plan", context_identifier="Annotation", target_view="PLAN_VIEW", parent=plan
)
blenderbim.bim.handler.refresh_ui_data()
context.scene.BIMRootProperties.contexts = str(body_context.id())
bpy.ops.bim.assign_class(obj=site.name, ifc_class="IfcSite")
bpy.ops.bim.assign_class(obj=building.name, ifc_class="IfcBuilding")
bpy.ops.bim.assign_class(obj=building_storey.name, ifc_class="IfcBuildingStorey")
blenderbim.core.aggregate.assign_object(
tool.Ifc, tool.Aggregate, tool.Collector, relating_obj=project, related_obj=site
)
blenderbim.core.aggregate.assign_object(
tool.Ifc, tool.Aggregate, tool.Collector, relating_obj=site, related_obj=building
)
blenderbim.core.aggregate.assign_object(
tool.Ifc, tool.Aggregate, tool.Collector, relating_obj=building, related_obj=building_storey
)
context.view_layer.objects.active = active_object
return {"FINISHED"}
def get_name(self, ifc_class, name):
if not bpy.data.objects.get(f"{ifc_class}/{name}"):
return name
i = 2
while bpy.data.objects.get(f"{ifc_class}/{name} {i}"):
i += 1
return f"{name} {i}"
def _execute(self, context):
props = context.scene.BIMProjectProperties
template = None if props.template_file == "0" else props.template_file
core.create_project(tool.Ifc, tool.Project, schema=props.export_schema, template=template)
def rollback(self, data):
IfcStore.file = None
@@ -373,7 +310,11 @@ class AppendLibraryElement(bpy.types.Operator):
self.import_type_from_ifc(element, context)
elif element.is_a("IfcMaterial"):
self.import_material_from_ifc(element, context)
context.scene.BIMProjectProperties.library_elements[self.prop_index].is_appended = True
try:
context.scene.BIMProjectProperties.library_elements[self.prop_index].is_appended = True
except:
# TODO Remove this terrible code when I refactor this into the core
pass
blenderbim.bim.handler.purge_module_data()
return {"FINISHED"}
@@ -38,6 +38,12 @@ def get_export_schema(self, context):
return ProjectData.data["export_schema"]
def get_template_file(self, context):
if not ProjectData.is_loaded:
ProjectData.load()
return ProjectData.data["template_file"]
def update_filter_mode(self, context):
self.filter_categories.clear()
if self.filter_mode == "NONE":
@@ -132,6 +138,7 @@ class BIMProjectProperties(PropertyGroup):
links: CollectionProperty(name="Links", type=Link)
active_link_index: IntProperty(name="Active Link Index")
export_schema: EnumProperty(items=get_export_schema, name="IFC Schema")
template_file: EnumProperty(items=get_template_file, name="Template File")
def get_library_element_index(self, lib_element):
return next((i for i in range(len(self.library_elements)) if self.library_elements[i] == lib_element))
@@ -156,6 +156,9 @@ class BIM_PT_project(Panel):
row.prop(props, "area_unit", text="Area Unit")
row = self.layout.row()
row.prop(props, "volume_unit", text="Volume Unit")
row = self.layout.row()
row.prop(pprops, "template_file", text="Template")
row = self.layout.row(align=True)
row.operator("bim.create_project")
row.operator("bim.load_project")
+63
View File
@@ -0,0 +1,63 @@
# BlenderBIM Add-on - OpenBIM Blender Add-on
# Copyright (C) 2022 Dion Moult <dion@thinkmoult.com>
#
# This file is part of BlenderBIM Add-on.
#
# BlenderBIM Add-on is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# BlenderBIM Add-on is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>.
def create_project(ifc, project, schema=None, template=None):
if ifc.get():
return
ifc.set(ifc.run("project.create_file", version=schema))
if schema == "IFC2X3":
person = project.run_owner_add_person()
organisation = project.run_owner_add_organisation()
user = project.run_owner_add_person_and_organisation(person=person, organisation=organisation)
project.run_owner_set_user(user=user)
project_obj = project.create_empty("My Project")
site = project.create_empty("My Site")
building = project.create_empty("My Building")
storey = project.create_empty("My Storey")
project.run_root_assign_class(obj=project_obj, ifc_class="IfcProject")
project.run_unit_assign_scene_units()
model = project.run_context_add_context(context_type="Model", context_identifier="", target_view="", parent=0)
body = project.run_context_add_context(
context_type="Model", context_identifier="Body", target_view="MODEL_VIEW", parent=model
)
project.run_context_add_context(
context_type="Model", context_identifier="Box", target_view="MODEL_VIEW", parent=model
)
plan = project.run_context_add_context(context_type="Plan", context_identifier="", target_view="", parent=0)
annotation = project.run_context_add_context(
context_type="Plan", context_identifier="Annotation", target_view="PLAN_VIEW", parent=plan
)
project.run_root_assign_class(obj=site, ifc_class="IfcSite", context=body)
project.run_root_assign_class(obj=building, ifc_class="IfcBuilding", context=body)
project.run_root_assign_class(obj=storey, ifc_class="IfcBuildingStorey", context=body)
project.run_aggregate_assign_object(relating_obj=project_obj, related_obj=site)
project.run_aggregate_assign_object(relating_obj=site, related_obj=building)
project.run_aggregate_assign_object(relating_obj=building, related_obj=storey)
project.set_context(body)
if template:
project.append_all_types_from_template(template)
+16
View File
@@ -215,6 +215,7 @@ class Ifc:
def get_schema(cls): pass
def link(cls, element, obj): pass
def run(cls, command, **kwargs): pass
def set(cls, ifc): pass
def unlink(cls, element=None, obj=None): pass
@@ -292,6 +293,21 @@ class Owner:
def set_user(cls, user): pass
@interface
class Project:
def append_all_types_from_template(cls, template): pass
def create_empty(cls, name): pass
def run_aggregate_assign_object(cls, relating_obj=None, related_obj=None): pass
def run_context_add_context(cls, context_type=None, context_identifier=None, target_view=None, parent=None): pass
def run_owner_add_organisation(cls): pass
def run_owner_add_person(cls): pass
def run_owner_add_person_and_organisation(cls, person=None, organisation=None): pass
def run_owner_set_user(cls, user=None): pass
def run_root_assign_class(cls, obj=None, ifc_class=None, predefined_type=None, should_add_representation=True, context=None, ifc_representation_class=None): pass
def run_unit_assign_scene_units(cls): pass
def set_context(cls, context): pass
@interface
class Pset:
def get_element_pset(cls, element, pset_name): pass
@@ -33,6 +33,7 @@ from blenderbim.tool.misc import Misc
from blenderbim.tool.model import Model
from blenderbim.tool.owner import Owner
from blenderbim.tool.patch import Patch
from blenderbim.tool.project import Project
from blenderbim.tool.pset import Pset
from blenderbim.tool.qto import Qto
from blenderbim.tool.root import Root
+100
View File
@@ -0,0 +1,100 @@
# BlenderBIM Add-on - OpenBIM Blender Add-on
# Copyright (C) 2022 Dion Moult <dion@thinkmoult.com>
#
# This file is part of BlenderBIM Add-on.
#
# BlenderBIM Add-on is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# BlenderBIM Add-on is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>.
import os
import bpy
import blenderbim.core.tool
import blenderbim.tool as tool
from blenderbim.bim.ifc import IfcStore
class Project(blenderbim.core.tool.Project):
@classmethod
def append_all_types_from_template(cls, template):
# TODO refactor
filepath = os.path.join(bpy.context.scene.BIMProperties.data_dir, "libraries", template)
bpy.ops.bim.select_library_file(filepath=filepath)
for element in IfcStore.library_file.by_type("IfcTypeProduct"):
bpy.ops.bim.append_library_element(definition=element.id())
@classmethod
def create_empty(cls, name):
return bpy.data.objects.new(name, None)
@classmethod
def run_aggregate_assign_object(cls, relating_obj=None, related_obj=None):
return blenderbim.core.aggregate.assign_object(
tool.Ifc, tool.Aggregate, tool.Collector, relating_obj=relating_obj, related_obj=related_obj
)
@classmethod
def run_context_add_context(cls, context_type=None, context_identifier=None, target_view=None, parent=None):
return blenderbim.core.context.add_context(
tool.Ifc,
context_type=context_type,
context_identifier=context_identifier,
target_view=target_view,
parent=parent,
)
@classmethod
def run_owner_add_organisation(cls):
return blenderbim.core.owner.add_organisation(tool.Ifc)
@classmethod
def run_owner_add_person(cls):
return blenderbim.core.owner.add_person(tool.Ifc)
@classmethod
def run_owner_add_person_and_organisation(cls, person=None, organisation=None):
return blenderbim.core.owner.add_person_and_organisation(tool.Ifc, person=person, organisation=organisation)
@classmethod
def run_owner_set_user(cls, user=None):
return blenderbim.core.owner.set_user(tool.Owner, user=user)
@classmethod
def run_root_assign_class(
cls,
obj=None,
ifc_class=None,
predefined_type=None,
should_add_representation=True,
context=None,
ifc_representation_class=None,
):
return blenderbim.core.root.assign_class(
tool.Ifc,
tool.Collector,
tool.Root,
obj=obj,
ifc_class=ifc_class,
predefined_type=predefined_type,
should_add_representation=should_add_representation,
context=context,
ifc_representation_class=ifc_representation_class,
)
@classmethod
def run_unit_assign_scene_units(cls):
return blenderbim.core.unit.assign_scene_units(tool.Ifc, tool.Unit)
@classmethod
def set_context(cls, context):
blenderbim.bim.handler.refresh_ui_data()
bpy.context.scene.BIMRootProperties.contexts = str(context.id())
+7
View File
@@ -126,6 +126,13 @@ def patch():
prophet.verify()
@pytest.fixture
def project():
prophet = Prophecy(blenderbim.core.tool.Project)
yield prophet
prophet.verify()
@pytest.fixture
def pset():
prophet = Prophecy(blenderbim.core.tool.Pset)
+156
View File
@@ -0,0 +1,156 @@
# BlenderBIM Add-on - OpenBIM Blender Add-on
# Copyright (C) 2022 Dion Moult <dion@thinkmoult.com>
#
# This file is part of BlenderBIM Add-on.
#
# BlenderBIM Add-on is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# BlenderBIM Add-on is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>.
import blenderbim.core.project as subject
from test.core.bootstrap import ifc, project
class TestCreateProject:
def test_do_nothing_if_a_project_already_exists(self, ifc, project):
ifc.get().should_be_called().will_return("ifc")
subject.create_project(ifc, project, schema="IFC4", template=None)
def test_create_an_ifc4_project(self, ifc, project):
ifc.get().should_be_called().will_return(None)
ifc.run("project.create_file", version="IFC4").should_be_called().will_return("ifc")
ifc.set("ifc").should_be_called()
project.create_empty("My Project").should_be_called().will_return("project")
project.create_empty("My Site").should_be_called().will_return("site")
project.create_empty("My Building").should_be_called().will_return("building")
project.create_empty("My Storey").should_be_called().will_return("storey")
project.run_root_assign_class(obj="project", ifc_class="IfcProject").should_be_called()
project.run_unit_assign_scene_units().should_be_called()
project.run_context_add_context(
context_type="Model", context_identifier="", target_view="", parent=0
).should_be_called().will_return("model")
project.run_context_add_context(
context_type="Model", context_identifier="Body", target_view="MODEL_VIEW", parent="model"
).should_be_called().will_return("body")
project.run_context_add_context(
context_type="Model", context_identifier="Box", target_view="MODEL_VIEW", parent="model"
).should_be_called()
project.run_context_add_context(
context_type="Plan", context_identifier="", target_view="", parent=0
).should_be_called().will_return("plan")
project.run_context_add_context(
context_type="Plan", context_identifier="Annotation", target_view="PLAN_VIEW", parent="plan"
).should_be_called()
project.run_root_assign_class(obj="site", ifc_class="IfcSite", context="body").should_be_called()
project.run_root_assign_class(obj="building", ifc_class="IfcBuilding", context="body").should_be_called()
project.run_root_assign_class(obj="storey", ifc_class="IfcBuildingStorey", context="body").should_be_called()
project.run_aggregate_assign_object(relating_obj="project", related_obj="site").should_be_called()
project.run_aggregate_assign_object(relating_obj="site", related_obj="building").should_be_called()
project.run_aggregate_assign_object(relating_obj="building", related_obj="storey").should_be_called()
project.set_context("body").should_be_called()
subject.create_project(ifc, project, schema="IFC4", template=None)
def test_appending_project_template_types_if_specified(self, ifc, project):
ifc.get().should_be_called().will_return(None)
ifc.run("project.create_file", version="IFC4").should_be_called().will_return("ifc")
ifc.set("ifc").should_be_called()
project.create_empty("My Project").should_be_called().will_return("project")
project.create_empty("My Site").should_be_called().will_return("site")
project.create_empty("My Building").should_be_called().will_return("building")
project.create_empty("My Storey").should_be_called().will_return("storey")
project.run_root_assign_class(obj="project", ifc_class="IfcProject").should_be_called()
project.run_unit_assign_scene_units().should_be_called()
project.run_context_add_context(
context_type="Model", context_identifier="", target_view="", parent=0
).should_be_called().will_return("model")
project.run_context_add_context(
context_type="Model", context_identifier="Body", target_view="MODEL_VIEW", parent="model"
).should_be_called().will_return("body")
project.run_context_add_context(
context_type="Model", context_identifier="Box", target_view="MODEL_VIEW", parent="model"
).should_be_called()
project.run_context_add_context(
context_type="Plan", context_identifier="", target_view="", parent=0
).should_be_called().will_return("plan")
project.run_context_add_context(
context_type="Plan", context_identifier="Annotation", target_view="PLAN_VIEW", parent="plan"
).should_be_called()
project.run_root_assign_class(obj="site", ifc_class="IfcSite", context="body").should_be_called()
project.run_root_assign_class(obj="building", ifc_class="IfcBuilding", context="body").should_be_called()
project.run_root_assign_class(obj="storey", ifc_class="IfcBuildingStorey", context="body").should_be_called()
project.run_aggregate_assign_object(relating_obj="project", related_obj="site").should_be_called()
project.run_aggregate_assign_object(relating_obj="site", related_obj="building").should_be_called()
project.run_aggregate_assign_object(relating_obj="building", related_obj="storey").should_be_called()
project.set_context("body").should_be_called()
project.append_all_types_from_template("template").should_be_called()
subject.create_project(ifc, project, schema="IFC4", template="template")
def test_create_an_ifc2x3_project_with_owner_defaults(self, ifc, project):
ifc.get().should_be_called().will_return(None)
ifc.run("project.create_file", version="IFC2X3").should_be_called().will_return("ifc")
ifc.set("ifc").should_be_called()
project.run_owner_add_person().should_be_called().will_return("person")
project.run_owner_add_organisation().should_be_called().will_return("organisation")
project.run_owner_add_person_and_organisation(
person="person", organisation="organisation"
).should_be_called().will_return("user")
project.run_owner_set_user(user="user").should_be_called()
project.create_empty("My Project").should_be_called().will_return("project")
project.create_empty("My Site").should_be_called().will_return("site")
project.create_empty("My Building").should_be_called().will_return("building")
project.create_empty("My Storey").should_be_called().will_return("storey")
project.run_root_assign_class(obj="project", ifc_class="IfcProject").should_be_called()
project.run_unit_assign_scene_units().should_be_called()
project.run_context_add_context(
context_type="Model", context_identifier="", target_view="", parent=0
).should_be_called().will_return("model")
project.run_context_add_context(
context_type="Model", context_identifier="Body", target_view="MODEL_VIEW", parent="model"
).should_be_called().will_return("body")
project.run_context_add_context(
context_type="Model", context_identifier="Box", target_view="MODEL_VIEW", parent="model"
).should_be_called()
project.run_context_add_context(
context_type="Plan", context_identifier="", target_view="", parent=0
).should_be_called().will_return("plan")
project.run_context_add_context(
context_type="Plan", context_identifier="Annotation", target_view="PLAN_VIEW", parent="plan"
).should_be_called()
project.run_root_assign_class(obj="site", ifc_class="IfcSite", context="body").should_be_called()
project.run_root_assign_class(obj="building", ifc_class="IfcBuilding", context="body").should_be_called()
project.run_root_assign_class(obj="storey", ifc_class="IfcBuildingStorey", context="body").should_be_called()
project.run_aggregate_assign_object(relating_obj="project", related_obj="site").should_be_called()
project.run_aggregate_assign_object(relating_obj="site", related_obj="building").should_be_called()
project.run_aggregate_assign_object(relating_obj="building", related_obj="storey").should_be_called()
project.set_context("body").should_be_called()
subject.create_project(ifc, project, schema="IFC2X3", template=None)
+91
View File
@@ -0,0 +1,91 @@
# BlenderBIM Add-on - OpenBIM Blender Add-on
# Copyright (C) 2021 Dion Moult <dion@thinkmoult.com>
#
# This file is part of BlenderBIM Add-on.
#
# BlenderBIM Add-on is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# BlenderBIM Add-on is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>.
import bpy
import ifcopenshell
import blenderbim.core.tool
import blenderbim.tool as tool
from test.bim.bootstrap import NewFile
from blenderbim.tool.project import Project as subject
class TestImplementsTool(NewFile):
def test_run(self):
assert isinstance(subject(), blenderbim.core.tool.Project)
class TestAppendAllTypesFromTemplate(NewFile):
def test_nothing(self):
# TODO refactor
pass
class TestCreateEmpty(NewFile):
def test_run(self):
subject.create_empty("Foobar")
assert bpy.data.objects.get("Foobar")
assert not bpy.data.objects.get("Foobar").data
class TestRunAggregateAssignObject(NewFile):
def test_nothing(self):
pass
class TestRunContextAddContext(NewFile):
def test_nothing(self):
pass
class TestRunOwnerAddOrganisation(NewFile):
def test_nothing(self):
pass
class TestRunOwnerAddPerson(NewFile):
def test_nothing(self):
pass
class TestRunOwnerAddPersonAndOrganisation(NewFile):
def test_nothing(self):
pass
class TestRunOwnerSetUser(NewFile):
def test_nothing(self):
pass
class TestRunAssignClass(NewFile):
def test_nothing(self):
pass
class TestRunUnitAssignSceneUnits(NewFile):
def test_nothing(self):
pass
class TestSetContext(NewFile):
def test_run(self):
ifc = ifcopenshell.file()
tool.Ifc.set(ifc)
context = ifc.createIfcGeometricRepresentationContext()
subject.set_context(context)
assert bpy.context.scene.BIMRootProperties.contexts == str(context.id())