mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-10-02 21:12:07 +00:00
bim.add_representation - update occurrences too if there were no representations
and new representation was just added to the type Example - https://imgur.com/a/v6a5kg2
This commit is contained in:
@@ -211,7 +211,7 @@ class AddRepresentation(bpy.types.Operator, Operator):
|
|||||||
if original_data:
|
if original_data:
|
||||||
tool.Geometry.change_object_data(obj, data, is_global=True)
|
tool.Geometry.change_object_data(obj, data, is_global=True)
|
||||||
else:
|
else:
|
||||||
obj = tool.Geometry.recreate_object_with_data(obj, data)
|
obj = tool.Geometry.recreate_object_with_data(obj, data, is_global=True)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
core.add_representation(
|
core.add_representation(
|
||||||
|
|||||||
@@ -690,7 +690,9 @@ class Geometry(blenderbim.core.tool.Geometry):
|
|||||||
obj.name = name
|
obj.name = name
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def recreate_object_with_data(cls, obj: bpy.types.Object, data: Union[bpy.types.ID, None]) -> bpy.types.Object:
|
def recreate_object_with_data(
|
||||||
|
cls, obj: bpy.types.Object, data: Union[bpy.types.ID, None], is_global: bool = False
|
||||||
|
) -> bpy.types.Object:
|
||||||
"""Recreate a Blender object with the provided `data`.
|
"""Recreate a Blender object with the provided `data`.
|
||||||
|
|
||||||
This method is useful when an object should no longer have associated
|
This method is useful when an object should no longer have associated
|
||||||
@@ -703,11 +705,18 @@ class Geometry(blenderbim.core.tool.Geometry):
|
|||||||
Original `obj` is deleted and becomes invalid and should be replaced
|
Original `obj` is deleted and becomes invalid and should be replaced
|
||||||
with an object returned by this method.
|
with an object returned by this method.
|
||||||
|
|
||||||
|
:param is_global: Whether all `obj` occurrences should also be recreated
|
||||||
|
with the provided `data`. Works only if `obj` is an IfcTypeProduct.
|
||||||
:return: The newly recreated object.
|
:return: The newly recreated object.
|
||||||
"""
|
"""
|
||||||
element = tool.Ifc.get_entity(obj)
|
element = tool.Ifc.get_entity(obj)
|
||||||
name = obj.name
|
name = obj.name
|
||||||
if element:
|
if element:
|
||||||
|
if is_global and element.is_a("IfcTypeProduct"):
|
||||||
|
ocurrences = ifcopenshell.util.element.get_types(element)
|
||||||
|
for occurrence in ocurrences:
|
||||||
|
cls.recreate_object_with_data(tool.Ifc.get_object(occurrence), data)
|
||||||
|
|
||||||
tool.Ifc.unlink(element=element)
|
tool.Ifc.unlink(element=element)
|
||||||
|
|
||||||
obj.name = ifcopenshell.guid.new()
|
obj.name = ifcopenshell.guid.new()
|
||||||
|
|||||||
@@ -20,11 +20,13 @@ import bpy
|
|||||||
import math
|
import math
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import ifcopenshell
|
import ifcopenshell
|
||||||
|
import ifcopenshell.api.type
|
||||||
import blenderbim.core.tool
|
import blenderbim.core.tool
|
||||||
import blenderbim.tool as tool
|
import blenderbim.tool as tool
|
||||||
from mathutils import Vector
|
from mathutils import Vector
|
||||||
from test.bim.bootstrap import NewFile
|
from test.bim.bootstrap import NewFile
|
||||||
from blenderbim.tool.geometry import Geometry as subject
|
from blenderbim.tool.geometry import Geometry as subject
|
||||||
|
from typing import Union
|
||||||
|
|
||||||
|
|
||||||
class TestImplementsTool(NewFile):
|
class TestImplementsTool(NewFile):
|
||||||
@@ -375,23 +377,75 @@ class TestRenameObject(NewFile):
|
|||||||
assert obj.name == "name"
|
assert obj.name == "name"
|
||||||
|
|
||||||
|
|
||||||
# TODO: add a test
|
|
||||||
class TestReplaceObjectWithEmpty(NewFile):
|
class TestReplaceObjectWithEmpty(NewFile):
|
||||||
def test_run(self):
|
def validate(
|
||||||
|
self,
|
||||||
|
element: ifcopenshell.entity_instance,
|
||||||
|
obj: bpy.types.Object,
|
||||||
|
new_obj: bpy.types.Object,
|
||||||
|
new_data: Union[bpy.types.Mesh, None],
|
||||||
|
) -> None:
|
||||||
|
assert not tool.Blender.is_valid_data_block(obj)
|
||||||
|
assert new_obj.users_collection[0] == bpy.context.scene.collection
|
||||||
|
assert tool.Ifc.get_entity(new_obj) == element
|
||||||
|
assert tool.Ifc.get_object(element) == new_obj
|
||||||
|
assert new_obj.data is new_data
|
||||||
|
assert new_obj.matrix_world.translation.x == 1
|
||||||
|
|
||||||
|
def create_object(
|
||||||
|
self, name: str, data: Union[bpy.types.Mesh, None], ifc_class: str
|
||||||
|
) -> tuple[bpy.types.Object, ifcopenshell.entity_instance]:
|
||||||
|
ifc = tool.Ifc.get()
|
||||||
|
obj = bpy.data.objects.new(name, data)
|
||||||
|
obj.matrix_world.translation.x = 1
|
||||||
|
bpy.context.scene.collection.objects.link(obj)
|
||||||
|
element = ifc.create_entity(ifc_class)
|
||||||
|
tool.Ifc.link(element, obj)
|
||||||
|
return obj, element
|
||||||
|
|
||||||
|
def run_test_replace_non_global(
|
||||||
|
self, from_data: Union[bpy.types.Mesh, None], to_data: Union[bpy.types.Mesh, None]
|
||||||
|
) -> None:
|
||||||
ifc = ifcopenshell.file()
|
ifc = ifcopenshell.file()
|
||||||
tool.Ifc.set(ifc)
|
tool.Ifc.set(ifc)
|
||||||
obj = bpy.data.objects.new("Object", bpy.data.meshes.new("Mesh"))
|
|
||||||
obj.matrix_world[0][3] = 1
|
obj, element = self.create_object("Object", from_data, "IfcWall")
|
||||||
bpy.context.scene.collection.objects.link(obj)
|
new_obj = subject.recreate_object_with_data(obj, to_data)
|
||||||
element = ifc.createIfcWall()
|
if from_data:
|
||||||
tool.Ifc.link(element, obj)
|
assert tool.Blender.is_valid_data_block(from_data)
|
||||||
subject.recreate_object_with_data(obj, None)
|
self.validate(element, obj, new_obj, to_data)
|
||||||
obj = bpy.data.objects.get("Object")
|
|
||||||
assert obj.users_collection[0] == bpy.context.scene.collection
|
def test_replace_mesh_with_empty(self) -> None:
|
||||||
assert tool.Ifc.get_entity(obj) == element
|
self.run_test_replace_non_global(bpy.data.meshes.new("Mesh"), None)
|
||||||
assert tool.Ifc.get_object(element) == obj
|
|
||||||
assert obj.data is None
|
def test_replace_empty_with_mesh(self) -> None:
|
||||||
assert obj.matrix_world[0][3] == 1
|
self.run_test_replace_non_global(None, bpy.data.meshes.new("New Mesh"))
|
||||||
|
|
||||||
|
def run_test_for_global_argument(
|
||||||
|
self, from_data: Union[bpy.types.Mesh, None], to_data: Union[bpy.types.Mesh, None]
|
||||||
|
) -> None:
|
||||||
|
ifc = ifcopenshell.file()
|
||||||
|
tool.Ifc.set(ifc)
|
||||||
|
|
||||||
|
type_obj, element_type = self.create_object("IfcWallType", from_data, "IfcWallType")
|
||||||
|
obj1, element1 = self.create_object("IfcWall1", from_data, "IfcWall")
|
||||||
|
obj2, element2 = self.create_object("IfcWall2", from_data, "IfcWall")
|
||||||
|
ifcopenshell.api.type.assign_type(ifc, related_objects=[element1, element2], relating_type=element_type)
|
||||||
|
|
||||||
|
to_data = to_data
|
||||||
|
new_obj = subject.recreate_object_with_data(type_obj, to_data, is_global=True)
|
||||||
|
if from_data:
|
||||||
|
assert tool.Blender.is_valid_data_block(from_data)
|
||||||
|
|
||||||
|
self.validate(element_type, type_obj, new_obj, to_data)
|
||||||
|
self.validate(element1, obj1, bpy.data.objects["IfcWall1"], to_data)
|
||||||
|
self.validate(element2, obj2, bpy.data.objects["IfcWall2"], to_data)
|
||||||
|
|
||||||
|
def test_replace_mesh_with_empty_global(self) -> None:
|
||||||
|
self.run_test_for_global_argument(bpy.data.meshes.new("Mesh"), None)
|
||||||
|
|
||||||
|
def test_replace_empty_with_mesh_global(self) -> None:
|
||||||
|
self.run_test_for_global_argument(None, bpy.data.meshes.new("New Mesh"))
|
||||||
|
|
||||||
|
|
||||||
class TestResolveMappedRepresentation(NewFile):
|
class TestResolveMappedRepresentation(NewFile):
|
||||||
|
|||||||
Reference in New Issue
Block a user