diff --git a/src/blenderbim/blenderbim/bim/module/drawing/operator.py b/src/blenderbim/blenderbim/bim/module/drawing/operator.py index 63fd5106e2..3bebcdc39f 100644 --- a/src/blenderbim/blenderbim/bim/module/drawing/operator.py +++ b/src/blenderbim/blenderbim/bim/module/drawing/operator.py @@ -104,6 +104,9 @@ class AddAnnotationType(bpy.types.Operator, Operator): ) element.ApplicableOccurrence = f"IfcAnnotation/{object_type}" + if props.create_representation_for_type and object_type == "IMAGE": + bpy.ops.bim.add_reference_image("INVOKE_DEFAULT", use_existing_object_by_name=obj.name) + class EnableAddAnnotationType(bpy.types.Operator, Operator): bl_idname = "bim.enable_add_annotation_type" @@ -2581,6 +2584,11 @@ class AddReferenceImage(bpy.types.Operator, Operator): "Override image if it was previously loaded to Blender. If disabled, will always create a new image" ), ) + use_existing_object_by_name: bpy.props.StringProperty( + name="Use Existing Object By Name", + description="Existing object name to add a style with reference image to. If not provided will create a new object.", + options={"SKIP_SAVE"}, + ) def invoke(self, context, event): context.window_manager.fileselect_add(self) @@ -2596,29 +2604,33 @@ class AddReferenceImage(bpy.types.Operator, Operator): params = {"check_existing": False} image = load_image(image_filepath.name, image_filepath.parent, **params) - temp_mesh = bpy.data.meshes.new("temp_mesh") - bm = tool.Blender.get_bmesh_for_mesh(temp_mesh) - plane_scale = (Vector(image.size) / min(image.size)).to_3d() - matrix = Matrix.LocRotScale(None, None, plane_scale) - bmesh.ops.create_grid(bm, x_segments=1, y_segments=1, size=1, matrix=matrix, calc_uvs=False) - tool.Blender.apply_bmesh(temp_mesh, bm) - obj = bpy.data.objects.new(image_filepath.stem, temp_mesh) + def bm_add_image_plane(mesh): + bm = tool.Blender.get_bmesh_for_mesh(mesh, clean=True) + plane_scale = (Vector(image.size) / min(image.size)).to_3d() + matrix = Matrix.LocRotScale(None, None, plane_scale) + bmesh.ops.create_grid(bm, x_segments=1, y_segments=1, size=1, matrix=matrix, calc_uvs=False) + tool.Blender.apply_bmesh(mesh, bm) - # assign to the active collection - collection = context.view_layer.active_layer_collection.collection - collection.objects.link(obj) - - tool.Drawing.run_root_assign_class( - obj=obj, - ifc_class="IfcAnnotation", - predefined_type="IMAGE", - should_add_representation=True, - context=ifcopenshell.util.representation.get_context(ifc_file, "Model", "Body", "MODEL_VIEW"), - ifc_representation_class=None, - ) - tool.Blender.remove_data_block(temp_mesh) + if self.use_existing_object_by_name: + obj = bpy.data.objects[self.use_existing_object_by_name] + bm_add_image_plane(obj.data) + bpy.ops.bim.update_representation(obj=obj.name, ifc_representation_class="") + else: + temp_mesh = bpy.data.meshes.new("temp_mesh") + bm_add_image_plane(temp_mesh) + obj = bpy.data.objects.new(image_filepath.stem, temp_mesh) + tool.Drawing.run_root_assign_class( + obj=obj, + ifc_class="IfcAnnotation", + predefined_type="IMAGE", + should_add_representation=True, + context=ifcopenshell.util.representation.get_context(ifc_file, "Model", "Body", "MODEL_VIEW"), + ifc_representation_class=None, + ) + tool.Blender.remove_data_block(temp_mesh) tool.Blender.set_active_object(obj) + material = bpy.data.materials.new(name=image_filepath.stem) obj.data.materials.append(None) # new slot obj.material_slots[0].material = material @@ -2626,8 +2638,8 @@ class AddReferenceImage(bpy.types.Operator, Operator): style = ifc_file.by_id(material.BIMMaterialProperties.ifc_style_id) tool.Style.assign_style_to_object(style, obj) + tool.Geometry.record_object_materials(obj) - material.diffuse_color = (0.031379, 0, 0.801157, 1) material.BIMStyleProperties.diffuse_path = self.filepath material.BIMStyleProperties.uv_mode = "Generated" bpy.ops.bim.update_style_colours() diff --git a/src/blenderbim/blenderbim/bim/module/drawing/prop.py b/src/blenderbim/blenderbim/bim/module/drawing/prop.py index c594345bc1..3e4d3e1d03 100644 --- a/src/blenderbim/blenderbim/bim/module/drawing/prop.py +++ b/src/blenderbim/blenderbim/bim/module/drawing/prop.py @@ -515,6 +515,7 @@ ANNOTATION_TYPES_DATA = { "REVISION_CLOUD":("Revision Cloud", "Add revision cloud", "VOLUME_DATA", "mesh"), "FILL_AREA": ("Fill Area", "", "NODE_TEXTURE", "mesh"), "FALL": ("Fall", "", "SORT_ASC", "curve"), + "IMAGE": ("Image", "Add reference image attached to the drawing", "TEXTURE", "mesh"), } # fmt: on diff --git a/src/blenderbim/blenderbim/bim/module/drawing/workspace.py b/src/blenderbim/blenderbim/bim/module/drawing/workspace.py index c7d3337070..4e4b7e4dc6 100644 --- a/src/blenderbim/blenderbim/bim/module/drawing/workspace.py +++ b/src/blenderbim/blenderbim/bim/module/drawing/workspace.py @@ -186,6 +186,9 @@ def create_annotation_occurrence(context): tool.Collector.assign(obj) tool.Blender.select_and_activate_single_object(context, obj) + if relating_type_repr is None and props.object_type == "IMAGE": + bpy.ops.bim.add_reference_image("INVOKE_DEFAULT", use_existing_object_by_name=obj.name) + def create_annotation(): props = bpy.context.scene.BIMAnnotationProperties @@ -194,6 +197,10 @@ def create_annotation(): else: object_type = props.object_type bpy.ops.bim.add_annotation(object_type=object_type, data_type=ANNOTATION_TYPES_DATA[object_type][-1]) + if props.object_type == "IMAGE": + bpy.ops.bim.add_reference_image( + "INVOKE_DEFAULT", use_existing_object_by_name=bpy.context.active_object.name + ) class AnnotationToolUI: diff --git a/src/blenderbim/test/tool/test_drawing.py b/src/blenderbim/test/tool/test_drawing.py index 6fffa5e378..0cce6e1ede 100644 --- a/src/blenderbim/test/tool/test_drawing.py +++ b/src/blenderbim/test/tool/test_drawing.py @@ -27,6 +27,7 @@ from test.bim.bootstrap import NewFile from blenderbim.tool.drawing import Drawing as subject from blenderbim.bim.ifc import IfcStore from blenderbim.bim.module.drawing.data import DecoratorData +from mathutils import Vector import xml.etree.ElementTree as ET @@ -847,3 +848,29 @@ class TestDrawingStyles(NewFile): self.setup_project_with_drawing() bpy.ops.bim.reload_drawing_styles() assert len(self.drawing_styles) == 3 + + +class TestAddReferenceImage(NewFile): + def test_run(self): + bpy.context.scene.BIMProjectProperties.template_file = "0" + bpy.ops.bim.create_project() + ifc_file = tool.Ifc.get() + + filepath = Path("test/files/image.jpg").absolute() + bpy.ops.bim.add_reference_image(filepath=str(filepath)) + + obj = bpy.data.objects["IfcAnnotation/image"] + assert obj is not None + assert tool.Cad.are_vectors_equal(obj.dimensions, Vector((3.53982, 2.0, 0.0))) + + material = obj.active_material + assert material.name == "image" + assert material.BIMMaterialProperties.ifc_style_id != 0 + + style = ifc_file.by_id(material.BIMMaterialProperties.ifc_style_id) + styled_items = set(tool.Style.get_styled_items(style)) + representation_items = set(tool.Geometry.get_active_representation(obj).Items) + assert styled_items == representation_items + + assert Path(material.BIMStyleProperties.diffuse_path) == filepath + assert material.BIMStyleProperties.uv_mode == "Generated"