mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-11 18:16:40 +00:00
Simplify add reference image size implementation and fix segfaulting tests
Previously, there was a dance between invoke, execute, and draw. This can probably be resolved, but is a high-risk for undo bugs. This simplifies the logic flow to just a traditional _invoke -> _execute. I add a new feature test to at least make sure it does something, and this also fixes the segfault in tool tests as it no longer requires the launching of the file browser.
This commit is contained in:
@@ -3815,91 +3815,14 @@ class AddReferenceImage(bpy.types.Operator, tool.Ifc.Operator, ImportHelper):
|
||||
description="Existing object name to add a style with reference image to. If not provided will create a new object.",
|
||||
options={"SKIP_SAVE"},
|
||||
)
|
||||
|
||||
x_length: bpy.props.FloatProperty(
|
||||
name="X Length",
|
||||
description="Width of the reference image in project units",
|
||||
default=1.0,
|
||||
min=0.001,
|
||||
soft_min=0.01,
|
||||
precision=3,
|
||||
)
|
||||
y_length: bpy.props.FloatProperty(
|
||||
name="Y Length",
|
||||
description="Height of the reference image in project units",
|
||||
default=1.0,
|
||||
min=0.001,
|
||||
soft_min=0.01,
|
||||
precision=3,
|
||||
)
|
||||
|
||||
show_dimensions_dialog: bpy.props.BoolProperty(default=False, options={"HIDDEN", "SKIP_SAVE"})
|
||||
size: bpy.props.FloatProperty(name="Size", description="Size of the reference image", default=1.0, unit="LENGTH")
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
if getattr(self, "show_dimensions_dialog", False):
|
||||
if tool.Ifc.get():
|
||||
length_unit = ifcopenshell.util.unit.get_project_unit(tool.Ifc.get(), "LENGTHUNIT")
|
||||
if length_unit:
|
||||
unit_name = ifcopenshell.util.unit.get_full_unit_name(length_unit).lower()
|
||||
else:
|
||||
unit_name = "project units"
|
||||
layout.label(text=f"Set Reference Image Dimensions (in {unit_name}):")
|
||||
else:
|
||||
layout.label(text="Set Reference Image Dimensions (in project units):")
|
||||
layout.separator()
|
||||
layout.prop(self, "x_length")
|
||||
layout.prop(self, "y_length")
|
||||
else:
|
||||
if Path(tool.Ifc.get_path()).is_file():
|
||||
layout.prop(self, "use_relative_path")
|
||||
else:
|
||||
self.use_relative_path = False
|
||||
layout.label(text="Save the .ifc file first ")
|
||||
layout.label(text="to use relative paths.")
|
||||
layout.prop(self, "override_existing_image")
|
||||
layout.prop(self, "use_existing_object_by_name")
|
||||
|
||||
def invoke(self, context, event):
|
||||
if not getattr(self, "show_dimensions_dialog", False):
|
||||
context.window_manager.fileselect_add(self)
|
||||
return {"RUNNING_MODAL"}
|
||||
else:
|
||||
return context.window_manager.invoke_props_dialog(self)
|
||||
|
||||
def execute(self, context):
|
||||
if not getattr(self, "show_dimensions_dialog", False):
|
||||
abs_path = Path(self.filepath).absolute().resolve()
|
||||
if self.override_existing_image:
|
||||
params = {"check_existing": True, "force_reload": True}
|
||||
else:
|
||||
params = {"check_existing": False}
|
||||
|
||||
try:
|
||||
image = load_image(abs_path.name, str(abs_path.parent), **params)
|
||||
|
||||
image_width_px = image.size[0]
|
||||
image_height_px = image.size[1]
|
||||
aspect_ratio = image_width_px / image_height_px
|
||||
|
||||
if aspect_ratio >= 1.0:
|
||||
self.x_length = 1.0
|
||||
self.y_length = 1.0 / aspect_ratio
|
||||
else:
|
||||
self.x_length = aspect_ratio
|
||||
self.y_length = 1.0
|
||||
|
||||
bpy.data.images.remove(image)
|
||||
|
||||
except Exception as e:
|
||||
self.report({"ERROR"}, f"Failed to load image: {str(e)}")
|
||||
return {"CANCELLED"}
|
||||
|
||||
self.show_dimensions_dialog = True
|
||||
return context.window_manager.invoke_props_dialog(self)
|
||||
|
||||
return self._execute(context)
|
||||
if Path(tool.Ifc.get_path()).is_file():
|
||||
self.layout.prop(self, "use_relative_path")
|
||||
self.layout.prop(self, "override_existing_image")
|
||||
self.layout.prop(self, "use_existing_object_by_name")
|
||||
self.layout.prop(self, "size")
|
||||
|
||||
def _execute(self, context):
|
||||
space = tool.Blender.get_view3d_space()
|
||||
@@ -3920,11 +3843,19 @@ class AddReferenceImage(bpy.types.Operator, tool.Ifc.Operator, ImportHelper):
|
||||
params = {"check_existing": False}
|
||||
image = load_image(abs_path.name, str(abs_path.parent), **params)
|
||||
|
||||
aspect_ratio = image.size[0] / image.size[1]
|
||||
if aspect_ratio >= 1.0: # Landscape
|
||||
x_length = self.size
|
||||
y_length = self.size / aspect_ratio
|
||||
else:
|
||||
x_length = self.size / aspect_ratio
|
||||
y_length = self.size
|
||||
|
||||
def bm_add_image_plane(mesh):
|
||||
bm = tool.Blender.get_bmesh_for_mesh(mesh, clean=True)
|
||||
|
||||
unit_scale = ifcopenshell.util.unit.calculate_unit_scale(ifc_file)
|
||||
plane_scale = Vector((self.x_length * unit_scale / 2.0, self.y_length * unit_scale / 2.0, 1.0))
|
||||
plane_scale = Vector((x_length / 2.0, y_length / 2.0, 1.0))
|
||||
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)
|
||||
|
||||
@@ -4028,8 +3959,6 @@ class AddReferenceImage(bpy.types.Operator, tool.Ifc.Operator, ImportHelper):
|
||||
tool.Style.reload_material_from_ifc(material)
|
||||
tool.Geometry.record_object_materials(obj)
|
||||
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class ConvertSVGToDXF(bpy.types.Operator):
|
||||
bl_idname = "bim.convert_svg_to_dxf"
|
||||
|
||||
@@ -3,12 +3,6 @@ Feature: Drawing
|
||||
|
||||
Scenario: Duplicate drawing
|
||||
Given an empty IFC project
|
||||
And I add a cube
|
||||
And the object "Cube" is selected
|
||||
And I look at the "Class" panel
|
||||
And I set the "Products" property to "IfcElement"
|
||||
And I set the "Class" property to "IfcWall"
|
||||
And I click "Assign IFC Class"
|
||||
And I save IFC project
|
||||
And I look at the "Drawings" panel
|
||||
And I click "IMPORT"
|
||||
@@ -315,3 +309,10 @@ Scenario: Create sheet - with a drawing added to it
|
||||
And I click "IMAGE_PLANE"
|
||||
When I click "OUTPUT"
|
||||
Then the file "{ifc_dir}/sheets/A01 - UNTITLED.svg" should contain "IfcWall"
|
||||
|
||||
Scenario: Add reference image
|
||||
Given an empty IFC project
|
||||
And I save IFC project
|
||||
When I press "bim.add_reference_image(filepath='{cwd}/test/files/image.jpg')"
|
||||
Then the object "IfcAnnotation/image" exists
|
||||
And the object "IfcAnnotation/image" dimensions are "1.0,0.565,0."
|
||||
|
||||
@@ -938,7 +938,7 @@ class TestAddReferenceImage(NewFile):
|
||||
|
||||
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)))
|
||||
assert tool.Cad.are_vectors_equal(obj.dimensions, Vector((1.0, 0.565, 0.0)))
|
||||
|
||||
material = obj.active_material
|
||||
assert material
|
||||
|
||||
Reference in New Issue
Block a user