mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-12 14:33:28 +00:00
Reference images attached to the drawings #3447
You can also save them as annotation types. Example - https://imgur.com/a/6trT7SZ
This commit is contained in:
@@ -104,6 +104,9 @@ class AddAnnotationType(bpy.types.Operator, Operator):
|
|||||||
)
|
)
|
||||||
element.ApplicableOccurrence = f"IfcAnnotation/{object_type}"
|
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):
|
class EnableAddAnnotationType(bpy.types.Operator, Operator):
|
||||||
bl_idname = "bim.enable_add_annotation_type"
|
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"
|
"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):
|
def invoke(self, context, event):
|
||||||
context.window_manager.fileselect_add(self)
|
context.window_manager.fileselect_add(self)
|
||||||
@@ -2596,29 +2604,33 @@ class AddReferenceImage(bpy.types.Operator, Operator):
|
|||||||
params = {"check_existing": False}
|
params = {"check_existing": False}
|
||||||
image = load_image(image_filepath.name, image_filepath.parent, **params)
|
image = load_image(image_filepath.name, image_filepath.parent, **params)
|
||||||
|
|
||||||
temp_mesh = bpy.data.meshes.new("temp_mesh")
|
def bm_add_image_plane(mesh):
|
||||||
bm = tool.Blender.get_bmesh_for_mesh(temp_mesh)
|
bm = tool.Blender.get_bmesh_for_mesh(mesh, clean=True)
|
||||||
plane_scale = (Vector(image.size) / min(image.size)).to_3d()
|
plane_scale = (Vector(image.size) / min(image.size)).to_3d()
|
||||||
matrix = Matrix.LocRotScale(None, None, plane_scale)
|
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)
|
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)
|
tool.Blender.apply_bmesh(mesh, bm)
|
||||||
obj = bpy.data.objects.new(image_filepath.stem, temp_mesh)
|
|
||||||
|
|
||||||
# assign to the active collection
|
if self.use_existing_object_by_name:
|
||||||
collection = context.view_layer.active_layer_collection.collection
|
obj = bpy.data.objects[self.use_existing_object_by_name]
|
||||||
collection.objects.link(obj)
|
bm_add_image_plane(obj.data)
|
||||||
|
bpy.ops.bim.update_representation(obj=obj.name, ifc_representation_class="")
|
||||||
tool.Drawing.run_root_assign_class(
|
else:
|
||||||
obj=obj,
|
temp_mesh = bpy.data.meshes.new("temp_mesh")
|
||||||
ifc_class="IfcAnnotation",
|
bm_add_image_plane(temp_mesh)
|
||||||
predefined_type="IMAGE",
|
obj = bpy.data.objects.new(image_filepath.stem, temp_mesh)
|
||||||
should_add_representation=True,
|
tool.Drawing.run_root_assign_class(
|
||||||
context=ifcopenshell.util.representation.get_context(ifc_file, "Model", "Body", "MODEL_VIEW"),
|
obj=obj,
|
||||||
ifc_representation_class=None,
|
ifc_class="IfcAnnotation",
|
||||||
)
|
predefined_type="IMAGE",
|
||||||
tool.Blender.remove_data_block(temp_mesh)
|
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)
|
tool.Blender.set_active_object(obj)
|
||||||
|
|
||||||
material = bpy.data.materials.new(name=image_filepath.stem)
|
material = bpy.data.materials.new(name=image_filepath.stem)
|
||||||
obj.data.materials.append(None) # new slot
|
obj.data.materials.append(None) # new slot
|
||||||
obj.material_slots[0].material = material
|
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)
|
style = ifc_file.by_id(material.BIMMaterialProperties.ifc_style_id)
|
||||||
tool.Style.assign_style_to_object(style, obj)
|
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.diffuse_path = self.filepath
|
||||||
material.BIMStyleProperties.uv_mode = "Generated"
|
material.BIMStyleProperties.uv_mode = "Generated"
|
||||||
bpy.ops.bim.update_style_colours()
|
bpy.ops.bim.update_style_colours()
|
||||||
|
|||||||
@@ -515,6 +515,7 @@ ANNOTATION_TYPES_DATA = {
|
|||||||
"REVISION_CLOUD":("Revision Cloud", "Add revision cloud", "VOLUME_DATA", "mesh"),
|
"REVISION_CLOUD":("Revision Cloud", "Add revision cloud", "VOLUME_DATA", "mesh"),
|
||||||
"FILL_AREA": ("Fill Area", "", "NODE_TEXTURE", "mesh"),
|
"FILL_AREA": ("Fill Area", "", "NODE_TEXTURE", "mesh"),
|
||||||
"FALL": ("Fall", "", "SORT_ASC", "curve"),
|
"FALL": ("Fall", "", "SORT_ASC", "curve"),
|
||||||
|
"IMAGE": ("Image", "Add reference image attached to the drawing", "TEXTURE", "mesh"),
|
||||||
}
|
}
|
||||||
# fmt: on
|
# fmt: on
|
||||||
|
|
||||||
|
|||||||
@@ -186,6 +186,9 @@ def create_annotation_occurrence(context):
|
|||||||
tool.Collector.assign(obj)
|
tool.Collector.assign(obj)
|
||||||
tool.Blender.select_and_activate_single_object(context, 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():
|
def create_annotation():
|
||||||
props = bpy.context.scene.BIMAnnotationProperties
|
props = bpy.context.scene.BIMAnnotationProperties
|
||||||
@@ -194,6 +197,10 @@ def create_annotation():
|
|||||||
else:
|
else:
|
||||||
object_type = props.object_type
|
object_type = props.object_type
|
||||||
bpy.ops.bim.add_annotation(object_type=object_type, data_type=ANNOTATION_TYPES_DATA[object_type][-1])
|
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:
|
class AnnotationToolUI:
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ from test.bim.bootstrap import NewFile
|
|||||||
from blenderbim.tool.drawing import Drawing as subject
|
from blenderbim.tool.drawing import Drawing as subject
|
||||||
from blenderbim.bim.ifc import IfcStore
|
from blenderbim.bim.ifc import IfcStore
|
||||||
from blenderbim.bim.module.drawing.data import DecoratorData
|
from blenderbim.bim.module.drawing.data import DecoratorData
|
||||||
|
from mathutils import Vector
|
||||||
|
|
||||||
import xml.etree.ElementTree as ET
|
import xml.etree.ElementTree as ET
|
||||||
|
|
||||||
@@ -847,3 +848,29 @@ class TestDrawingStyles(NewFile):
|
|||||||
self.setup_project_with_drawing()
|
self.setup_project_with_drawing()
|
||||||
bpy.ops.bim.reload_drawing_styles()
|
bpy.ops.bim.reload_drawing_styles()
|
||||||
assert len(self.drawing_styles) == 3
|
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"
|
||||||
|
|||||||
Reference in New Issue
Block a user