mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-08 17:01:40 +00:00
Fix Image empty interpreted as Mesh #5194
Apparently we can't trust `obj.data == None` to identify empties since in Blender there are empties that can use `bpy.types.Image` as their `obj.data`.
This commit is contained in:
@@ -364,7 +364,8 @@ class UpdateRepresentation(bpy.types.Operator, tool.Ifc.Operator):
|
||||
# TODO: write unit tests to see how this bulk operation handles
|
||||
# contradictory ifc_representation_class values and when
|
||||
# ifc_representation_class is IfcTextLiteral
|
||||
if not obj.data:
|
||||
data = obj.data
|
||||
if not tool.Geometry.is_data_supported_for_adding_representation(data):
|
||||
continue
|
||||
self.update_obj_mesh_representation(context, obj)
|
||||
tool.Ifc.finish_edit(obj)
|
||||
|
||||
@@ -172,7 +172,13 @@ class AssignClass(bpy.types.Operator, tool.Ifc.Operator):
|
||||
|
||||
def _execute(self, context):
|
||||
props = context.scene.BIMRootProperties
|
||||
objects = [bpy.data.objects.get(self.obj)] if self.obj else context.selected_objects or [context.active_object]
|
||||
objects: list[bpy.types.Object] = []
|
||||
if self.obj:
|
||||
objects = [bpy.data.objects[self.obj]]
|
||||
elif objects := context.selected_objects:
|
||||
pass
|
||||
elif obj := context.active_object:
|
||||
objects = [obj]
|
||||
|
||||
if not objects:
|
||||
self.report({"INFO"}, "No objects selected.")
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from __future__ import annotations
|
||||
from typing import TYPE_CHECKING, Optional, Sequence
|
||||
from typing import TYPE_CHECKING, Optional, Sequence, Union
|
||||
|
||||
if TYPE_CHECKING:
|
||||
import bpy
|
||||
@@ -47,7 +47,8 @@ def add_representation(
|
||||
context: ifcopenshell.entity_instance,
|
||||
ifc_representation_class: Optional[str] = None,
|
||||
profile_set_usage: Optional[ifcopenshell.entity_instance] = None,
|
||||
) -> ifcopenshell.entity_instance:
|
||||
) -> Union[ifcopenshell.entity_instance, None]:
|
||||
"""Add IFC representation based on object `.data`."""
|
||||
element = ifc.get_entity(obj)
|
||||
if not element:
|
||||
return
|
||||
@@ -55,7 +56,7 @@ def add_representation(
|
||||
edit_object_placement(ifc, geometry, surveyor, obj=obj)
|
||||
data = geometry.get_object_data(obj)
|
||||
|
||||
if not data and ifc_representation_class != "IfcTextLiteral":
|
||||
if not geometry.is_data_supported_for_adding_representation(data) and ifc_representation_class != "IfcTextLiteral":
|
||||
return
|
||||
|
||||
representation = ifc.run(
|
||||
|
||||
@@ -407,6 +407,7 @@ class Geometry:
|
||||
def import_representation_parameters(cls, data): pass
|
||||
def is_body_representation(cls, representation): pass
|
||||
def is_box_representation(cls, representation): pass
|
||||
def is_data_supported_for_adding_representation(cls, data): pass
|
||||
def is_edited(cls, obj): pass
|
||||
def is_mapped_representation(cls, representation): pass
|
||||
def is_type_product(cls, element): pass
|
||||
|
||||
@@ -41,8 +41,8 @@ from collections import defaultdict
|
||||
from math import radians, pi
|
||||
from mathutils import Vector, Matrix
|
||||
from bonsai.bim.ifc import IfcStore
|
||||
from typing import Union, Iterable, Optional, Literal
|
||||
from typing import Iterator
|
||||
from typing import Union, Iterable, Optional, Literal, Iterator
|
||||
from typing_extensions import TypeIs
|
||||
|
||||
|
||||
class Geometry(bonsai.core.tool.Geometry):
|
||||
@@ -477,7 +477,7 @@ class Geometry(bonsai.core.tool.Geometry):
|
||||
return hasher.hexdigest()
|
||||
|
||||
@classmethod
|
||||
def get_object_data(cls, obj: bpy.types.Object) -> bpy.types.ID:
|
||||
def get_object_data(cls, obj: bpy.types.Object) -> Union[bpy.types.ID, None]:
|
||||
return obj.data
|
||||
|
||||
@classmethod
|
||||
@@ -646,6 +646,21 @@ class Geometry(bonsai.core.tool.Geometry):
|
||||
def is_box_representation(cls, representation: ifcopenshell.entity_instance) -> bool:
|
||||
return representation.ContextOfItems.ContextIdentifier == "Box"
|
||||
|
||||
@classmethod
|
||||
def is_data_supported_for_adding_representation(cls, data: Union[bpy.types.ID, None]) -> TypeIs[
|
||||
Union[
|
||||
bpy.types.Mesh,
|
||||
bpy.types.Curve,
|
||||
]
|
||||
]:
|
||||
supported_types = (
|
||||
bpy.types.Mesh,
|
||||
bpy.types.Curve,
|
||||
)
|
||||
if not data:
|
||||
return False
|
||||
return isinstance(data, supported_types)
|
||||
|
||||
@classmethod
|
||||
def is_edited(cls, obj: bpy.types.Object) -> bool:
|
||||
return not all([tool.Cad.is_x(o, 1.0) for o in obj.scale]) or obj in IfcStore.edited_objs
|
||||
|
||||
@@ -42,6 +42,7 @@ class TestAddRepresentation:
|
||||
|
||||
# Add representation
|
||||
geometry.get_object_data("obj").should_be_called().will_return("data")
|
||||
geometry.is_data_supported_for_adding_representation("data").should_be_called().will_return(True)
|
||||
geometry.get_cartesian_point_coordinate_offset("obj").should_be_called().will_return("coordinate_offset")
|
||||
geometry.get_total_representation_items("obj").should_be_called().will_return(1)
|
||||
geometry.should_force_faceted_brep().should_be_called().will_return(False)
|
||||
@@ -108,6 +109,7 @@ class TestAddRepresentation:
|
||||
|
||||
# Add representation
|
||||
geometry.get_object_data("obj").should_be_called().will_return("data")
|
||||
geometry.is_data_supported_for_adding_representation("data").should_be_called().will_return(True)
|
||||
geometry.get_cartesian_point_coordinate_offset("obj").should_be_called().will_return("coordinate_offset")
|
||||
geometry.get_total_representation_items("obj").should_be_called().will_return(1)
|
||||
geometry.should_force_faceted_brep().should_be_called().will_return(False)
|
||||
@@ -158,7 +160,8 @@ class TestAddRepresentation:
|
||||
TestEditObjectPlacement.predict(self, ifc, geometry, surveyor)
|
||||
|
||||
# Add representation
|
||||
geometry.get_object_data("obj").should_be_called().will_return(None)
|
||||
geometry.get_object_data("obj").should_be_called().will_return("data")
|
||||
geometry.is_data_supported_for_adding_representation("data").should_be_called().will_return(False)
|
||||
assert (
|
||||
subject.add_representation(
|
||||
ifc,
|
||||
|
||||
Reference in New Issue
Block a user