Skip to content

Commit 73e5985

Browse files
committed
bcf + bbim - set/get selected/visible elements #4857
1) added more high level api for getting/setting selected/visible elements in bcf 2) in bbim when you add a new viewpoint it will remember currently selected and visible objects: https://imgur.com/a/2pZ79Z2
1 parent de14e92 commit 73e5985

File tree

3 files changed

+217
-5
lines changed

3 files changed

+217
-5
lines changed

src/bcf/bcf/v2/visinfo.py

Lines changed: 100 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import uuid
22
import zipfile
3-
from typing import Any, Iterable, Optional
3+
from typing import Any, Iterable, Optional, Literal, Union
44

55
import numpy as np
66
from ifcopenshell import entity_instance
@@ -204,6 +204,104 @@ def create_from_point_and_guids(
204204
visualization_info=build_viewpoint_from_position_and_guids(position, *guids), xml_handler=xml_handler
205205
)
206206

207+
def get_selected_guids(self) -> Union[list[str], None]:
208+
"""
209+
Return viewpoint selected elements IFC guids.
210+
211+
Returns:
212+
If viewpoint has no selection settings, return `None`.
213+
Otherwise return a list of selected elements IFC guids.
214+
"""
215+
visualization_info = self.visualization_info
216+
components = visualization_info.components
217+
if not components:
218+
return None
219+
220+
selection = components.selection
221+
if not selection:
222+
return None
223+
return [guid for c in selection.component if (guid := c.ifc_guid)]
224+
225+
def set_selected_elements(self, elements: list[ifcopenshell.entity_instance]) -> None:
226+
visualization_info = self.visualization_info
227+
228+
guids = [e.GlobalId for e in elements]
229+
components = visualization_info.components
230+
if not components:
231+
visibility = mdl.ComponentVisibility(default_visibility=True)
232+
components = mdl.Components(visibility=visibility)
233+
visualization_info.components = components
234+
235+
selection = components.selection
236+
components_list = [mdl.Component(ifc_guid=guid) for guid in guids]
237+
if not selection:
238+
selection = mdl.ComponentSelection()
239+
components.selection = selection
240+
selection.component = components_list
241+
242+
def set_visible_elements(self, elements: list[ifcopenshell.entity_instance]) -> None:
243+
self.set_visibility(elements, elements_visibility="VISIBLE")
244+
245+
def set_hidden_elements(self, elements: list[ifcopenshell.entity_instance]) -> None:
246+
self.set_visibility(elements, elements_visibility="HIDDEN")
247+
248+
def set_visibility(
249+
self, elements: list[ifcopenshell.entity_instance], elements_visibility: Literal["VISIBLE", "HIDDEN"]
250+
) -> None:
251+
visualization_info = self.visualization_info
252+
default_visibility = elements_visibility == "HIDDEN"
253+
254+
guids = [e.GlobalId for e in elements]
255+
components_list = [mdl.Component(ifc_guid=guid) for guid in guids]
256+
components = visualization_info.components
257+
if not components:
258+
visibility = mdl.ComponentVisibility(default_visibility=default_visibility)
259+
components = mdl.Components(visibility=visibility)
260+
visualization_info.components = components
261+
262+
visibility = components.visibility
263+
if not visibility:
264+
visibility = mdl.ComponentVisibility(default_visibility=default_visibility)
265+
components.visibility = visibility
266+
elif visibility.default_visibility != default_visibility:
267+
visibility.default_visibility = default_visibility
268+
269+
exceptions = visibility.exceptions
270+
if not exceptions:
271+
exceptions = mdl.ComponentVisibilityExceptions()
272+
visibility.exceptions = exceptions
273+
exceptions.component = components_list
274+
275+
def get_elements_visibility(self) -> Union[tuple[bool, list[str]], None]:
276+
"""
277+
Return viewpoint elements visibility settings.
278+
279+
Returns:
280+
If viewpoint has no visibility settings, return `None`.
281+
Otherwise return a tuple containing the default visibility
282+
and a list of IFC element GUIDs listed as exceptions.
283+
284+
If default visibility is `True`, all elements are visible except the exceptions.
285+
286+
If default visibility is `False`, all elements are hidden except the exceptions.
287+
"""
288+
289+
visualization_info = self.visualization_info
290+
components = visualization_info.components
291+
if not components:
292+
return None
293+
294+
visibility = components.visibility
295+
if not visibility:
296+
return None
297+
default_visibility = visibility.default_visibility or False
298+
299+
exceptions = visibility.exceptions
300+
if not exceptions:
301+
return default_visibility, []
302+
guids = [guid for c in exceptions.component if (guid := c.ifc_guid)]
303+
return default_visibility, guids
304+
207305

208306
def build_viewpoint(element: entity_instance) -> mdl.VisualizationInfo:
209307
"""
@@ -256,7 +354,7 @@ def build_components(*guids: str) -> mdl.Components:
256354
Return the BCF components from an IFC element GUID.
257355
258356
Args:
259-
*guids: One or more IFC element GUID.
357+
*guids: One or more selected IFC element GUID.
260358
261359
Returns:
262360
The BCF components definition.

src/bcf/bcf/v3/visinfo.py

Lines changed: 100 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import uuid
22
import zipfile
3-
from typing import Any, Iterable, Optional
3+
from typing import Any, Iterable, Optional, Literal, Union
44

55
import numpy as np
66
from ifcopenshell import entity_instance
@@ -204,6 +204,104 @@ def create_from_point_and_guids(
204204
visualization_info=build_viewpoint_from_position_and_guids(position, *guids), xml_handler=xml_handler
205205
)
206206

207+
def get_selected_guids(self) -> Union[list[str], None]:
208+
"""
209+
Return viewpoint selected elements IFC guids.
210+
211+
Returns:
212+
If viewpoint has no selection settings, return `None`.
213+
Otherwise return a list of selected elements IFC guids.
214+
"""
215+
visualization_info = self.visualization_info
216+
components = visualization_info.components
217+
if not components:
218+
return None
219+
220+
selection = components.selection
221+
if not selection:
222+
return None
223+
return [guid for c in selection.component if (guid := c.ifc_guid)]
224+
225+
def set_selected_elements(self, elements: list[ifcopenshell.entity_instance]) -> None:
226+
visualization_info = self.visualization_info
227+
228+
guids = [e.GlobalId for e in elements]
229+
components = visualization_info.components
230+
if not components:
231+
visibility = mdl.ComponentVisibility(default_visibility=True)
232+
components = mdl.Components(visibility=visibility)
233+
visualization_info.components = components
234+
235+
selection = components.selection
236+
components_list = [mdl.Component(ifc_guid=guid) for guid in guids]
237+
if not selection:
238+
selection = mdl.ComponentSelection()
239+
components.selection = selection
240+
selection.component = components_list
241+
242+
def set_visible_elements(self, elements: list[ifcopenshell.entity_instance]) -> None:
243+
self.set_visibility(elements, elements_visibility="VISIBLE")
244+
245+
def set_hidden_elements(self, elements: list[ifcopenshell.entity_instance]) -> None:
246+
self.set_visibility(elements, elements_visibility="HIDDEN")
247+
248+
def set_visibility(
249+
self, elements: list[ifcopenshell.entity_instance], elements_visibility: Literal["VISIBLE", "HIDDEN"]
250+
) -> None:
251+
visualization_info = self.visualization_info
252+
default_visibility = elements_visibility == "HIDDEN"
253+
254+
guids = [e.GlobalId for e in elements]
255+
components_list = [mdl.Component(ifc_guid=guid) for guid in guids]
256+
components = visualization_info.components
257+
if not components:
258+
visibility = mdl.ComponentVisibility(default_visibility=default_visibility)
259+
components = mdl.Components(visibility=visibility)
260+
visualization_info.components = components
261+
262+
visibility = components.visibility
263+
if not visibility:
264+
visibility = mdl.ComponentVisibility(default_visibility=default_visibility)
265+
components.visibility = visibility
266+
elif visibility.default_visibility != default_visibility:
267+
visibility.default_visibility = default_visibility
268+
269+
exceptions = visibility.exceptions
270+
if not exceptions:
271+
exceptions = mdl.ComponentVisibilityExceptions()
272+
visibility.exceptions = exceptions
273+
exceptions.component = components_list
274+
275+
def get_elements_visibility(self) -> Union[tuple[bool, list[str]], None]:
276+
"""
277+
Return viewpoint elements visibility settings.
278+
279+
Returns:
280+
If viewpoint has no visibility settings, return `None`.
281+
Otherwise return a tuple containing the default visibility
282+
and a list of IFC element GUIDs listed as exceptions.
283+
284+
If default visibility is `True`, all elements are visible except the exceptions.
285+
286+
If default visibility is `False`, all elements are hidden except the exceptions.
287+
"""
288+
289+
visualization_info = self.visualization_info
290+
components = visualization_info.components
291+
if not components:
292+
return None
293+
294+
visibility = components.visibility
295+
if not visibility:
296+
return None
297+
default_visibility = visibility.default_visibility or False
298+
299+
exceptions = visibility.exceptions
300+
if not exceptions:
301+
return default_visibility, []
302+
guids = [guid for c in exceptions.component if (guid := c.ifc_guid)]
303+
return default_visibility, guids
304+
207305

208306
def build_viewpoint(element: entity_instance) -> mdl.VisualizationInfo:
209307
"""
@@ -256,7 +354,7 @@ def build_components(*guids: str) -> mdl.Components:
256354
Return the BCF components from an IFC element GUID.
257355
258356
Args:
259-
*guids: One or more IFC element GUID.
357+
*guids: One or more selected IFC element GUID.
260358
261359
Returns:
262360
The BCF components definition.

src/blenderbim/blenderbim/bim/module/bcf/operator.py

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
import ifcopenshell
3232
import ifcopenshell.util.geolocation
3333
import ifcopenshell.util.unit
34+
import blenderbim.tool as tool
3435
import blenderbim.bim.module.bcf.prop as bcf_prop
3536
import blenderbim.bim.module.bcf.bcfstore as bcfstore
3637
from pathlib import Path
@@ -453,6 +454,7 @@ def poll(cls, context):
453454
def execute(self, context):
454455
bcfxml = bcfstore.BcfStore.get_bcfxml()
455456
blender_camera = context.scene.camera
457+
assert blender_camera
456458
props = context.scene.BCFProperties
457459
blender_topic = props.active_topic
458460
topic = bcfxml.topics[blender_topic.name]
@@ -495,13 +497,27 @@ def execute(self, context):
495497
snapshot = f.read()
496498
# viewpoint.snapshot = blender_render.filepath
497499

498-
# TODO we should handle selection and visibility state
499500
vizinfo = bcf.v2.visinfo.VisualizationInfoHandler(visualization_info=visualization_info, snapshot=snapshot)
500501
topic.viewpoints[vizinfo.guid + ".bcfv"] = vizinfo
501502
topic.markup.viewpoints.append(
502503
bcf.v2.model.ViewPoint(viewpoint=vizinfo.guid + ".bcfv", guid=vizinfo.guid, snapshot=vizinfo.guid + ".png")
503504
)
504505

506+
def get_ifc_elements(objs: list[bpy.types.Object]) -> list[ifcopenshell.entity_instance]:
507+
elements = []
508+
for obj in objs:
509+
if e := tool.Ifc.get_entity(obj):
510+
elements.append(e)
511+
return elements
512+
513+
selected_elements = get_ifc_elements(context.selected_objects)
514+
if selected_elements:
515+
vizinfo.set_selected_elements(selected_elements)
516+
517+
visible_elements = get_ifc_elements(context.visible_objects)
518+
if visible_elements:
519+
vizinfo.set_visible_elements(visible_elements)
520+
505521
blender_render.filepath = old_filepath
506522
blender_render.image_settings.file_format = old_file_format
507523
props.refresh_topic(context)

0 commit comments

Comments
 (0)