mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-10-01 20:49:44 +00:00
Fix failing drawing tool tests. Also consolidate relative paths using tool.Ifc.get_uri.
The same issue of handling relative paths, doing as_posix, checking drives, etc was solved again and again in slightly different ways. This centralises it.
This commit is contained in:
@@ -694,8 +694,8 @@ class CreateDrawing(bpy.types.Operator):
|
|||||||
invalidated_elements = exporter.sync_all_objects()
|
invalidated_elements = exporter.sync_all_objects()
|
||||||
invalidated_elements += exporter.sync_edited_objects()
|
invalidated_elements += exporter.sync_edited_objects()
|
||||||
invalidated_guids = [e.GlobalId for e in invalidated_elements if hasattr(e, "GlobalId")]
|
invalidated_guids = [e.GlobalId for e in invalidated_elements if hasattr(e, "GlobalId")]
|
||||||
cache = IfcStore.get_cache()
|
if cache := IfcStore.get_cache():
|
||||||
[cache.remove(guid) for guid in invalidated_guids]
|
[cache.remove(guid) for guid in invalidated_guids]
|
||||||
|
|
||||||
# If we have already calculated it in the SVG in the past, don't recalculate
|
# If we have already calculated it in the SVG in the past, don't recalculate
|
||||||
edited_guids = set()
|
edited_guids = set()
|
||||||
@@ -1752,7 +1752,7 @@ class CreateSheets(bpy.types.Operator, tool.Ifc.Operator):
|
|||||||
sheet_builder = sheeter.SheetBuilder()
|
sheet_builder = sheeter.SheetBuilder()
|
||||||
|
|
||||||
references = sheet_builder.build(sheet)
|
references = sheet_builder.build(sheet)
|
||||||
raster_references = [tool.Ifc.get_relative_uri(r) for r in references["RASTER"]]
|
raster_references = [tool.Ifc.get_uri(r, use_relative_path=True) for r in references["RASTER"]]
|
||||||
|
|
||||||
# These variables will be made available to the evaluated commands
|
# These variables will be made available to the evaluated commands
|
||||||
svg = references["SHEET"]
|
svg = references["SHEET"]
|
||||||
@@ -1783,7 +1783,7 @@ class CreateSheets(bpy.types.Operator, tool.Ifc.Operator):
|
|||||||
"document.edit_reference",
|
"document.edit_reference",
|
||||||
reference=reference,
|
reference=reference,
|
||||||
attributes=tool.Drawing.generate_reference_attributes(
|
attributes=tool.Drawing.generate_reference_attributes(
|
||||||
reference, Location=tool.Ifc.get_relative_uri(svg), Description="SHEET"
|
reference, Location=tool.Ifc.get_uri(svg, use_relative_path=True), Description="SHEET"
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -1793,7 +1793,9 @@ class CreateSheets(bpy.types.Operator, tool.Ifc.Operator):
|
|||||||
"document.edit_reference",
|
"document.edit_reference",
|
||||||
reference=reference,
|
reference=reference,
|
||||||
attributes=tool.Drawing.generate_reference_attributes(
|
attributes=tool.Drawing.generate_reference_attributes(
|
||||||
reference, Location=tool.Ifc.get_relative_uri(raster_reference), Description="RASTER"
|
reference,
|
||||||
|
Location=tool.Ifc.get_uri(raster_reference, use_relative_path=True),
|
||||||
|
Description="RASTER",
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -2455,21 +2457,8 @@ class AddSchedule(bpy.types.Operator, tool.Ifc.Operator):
|
|||||||
use_relative_path: bpy.props.BoolProperty(name="Use Relative Path", default=True)
|
use_relative_path: bpy.props.BoolProperty(name="Use Relative Path", default=True)
|
||||||
|
|
||||||
def _execute(self, context):
|
def _execute(self, context):
|
||||||
filepath = self.filepath
|
filepath = tool.Ifc.get_uri(self.filepath, use_relative_path=self.use_relative_path)
|
||||||
if self.use_relative_path:
|
core.add_document(tool.Ifc, tool.Drawing, "SCHEDULE", uri=filepath)
|
||||||
ifc_path = tool.Ifc.get_path()
|
|
||||||
if os.path.isfile(ifc_path):
|
|
||||||
ifc_path = os.path.dirname(ifc_path)
|
|
||||||
|
|
||||||
# taking into account different drives on windows
|
|
||||||
if Path(filepath).drive == Path(ifc_path).drive:
|
|
||||||
filepath = os.path.relpath(filepath, ifc_path)
|
|
||||||
core.add_document(
|
|
||||||
tool.Ifc,
|
|
||||||
tool.Drawing,
|
|
||||||
"SCHEDULE",
|
|
||||||
uri=filepath,
|
|
||||||
)
|
|
||||||
|
|
||||||
def invoke(self, context, event):
|
def invoke(self, context, event):
|
||||||
context.window_manager.fileselect_add(self)
|
context.window_manager.fileselect_add(self)
|
||||||
@@ -2653,21 +2642,8 @@ class AddReference(bpy.types.Operator, tool.Ifc.Operator):
|
|||||||
use_relative_path: bpy.props.BoolProperty(name="Use Relative Path", default=True)
|
use_relative_path: bpy.props.BoolProperty(name="Use Relative Path", default=True)
|
||||||
|
|
||||||
def _execute(self, context):
|
def _execute(self, context):
|
||||||
filepath = self.filepath
|
filepath = tool.Ifc.get_uri(self.filepath, use_relative_path=self.use_relative_path)
|
||||||
if self.use_relative_path:
|
core.add_document(tool.Ifc, tool.Drawing, "REFERENCE", uri=filepath)
|
||||||
ifc_path = tool.Ifc.get_path()
|
|
||||||
if os.path.isfile(ifc_path):
|
|
||||||
ifc_path = os.path.dirname(ifc_path)
|
|
||||||
|
|
||||||
# taking into account different drives on windows
|
|
||||||
if Path(filepath).drive == Path(ifc_path).drive:
|
|
||||||
filepath = os.path.relpath(filepath, ifc_path)
|
|
||||||
core.add_document(
|
|
||||||
tool.Ifc,
|
|
||||||
tool.Drawing,
|
|
||||||
"REFERENCE",
|
|
||||||
uri=filepath,
|
|
||||||
)
|
|
||||||
|
|
||||||
def invoke(self, context, event):
|
def invoke(self, context, event):
|
||||||
context.window_manager.fileselect_add(self)
|
context.window_manager.fileselect_add(self)
|
||||||
@@ -3301,11 +3277,8 @@ class AddReferenceImage(bpy.types.Operator, tool.Ifc.Operator):
|
|||||||
return {"RUNNING_MODAL"}
|
return {"RUNNING_MODAL"}
|
||||||
|
|
||||||
def _execute(self, context):
|
def _execute(self, context):
|
||||||
abs_path = Path(self.filepath)
|
abs_path = Path(self.filepath).absolute().resolve()
|
||||||
if self.use_relative_path:
|
image_filepath = Path(tool.Ifc.get_uri(self.filepath, use_relative_path=self.use_relative_path))
|
||||||
image_filepath = abs_path.relative_to(Path(tool.Ifc.get_path()).parent)
|
|
||||||
else:
|
|
||||||
image_filepath = abs_path
|
|
||||||
ifc_file = tool.Ifc.get()
|
ifc_file = tool.Ifc.get()
|
||||||
|
|
||||||
if self.override_existing_image:
|
if self.override_existing_image:
|
||||||
|
|||||||
@@ -1135,17 +1135,12 @@ class LinkIfc(bpy.types.Operator):
|
|||||||
self.report({"INFO"}, "Can't link the current .blend file")
|
self.report({"INFO"}, "Can't link the current .blend file")
|
||||||
continue
|
continue
|
||||||
new = context.scene.BIMProjectProperties.links.add()
|
new = context.scene.BIMProjectProperties.links.add()
|
||||||
if self.use_relative_path and (ifc_filepath := tool.Ifc.get_path()):
|
filepath = tool.Ifc.get_uri(filepath, use_relative_path=self.use_relative_path)
|
||||||
try:
|
new.name = filepath
|
||||||
filepath = filepath.relative_to(Path(ifc_filepath).parent)
|
status = bpy.ops.bim.load_link(filepath=filepath, use_cache=self.use_cache)
|
||||||
except:
|
|
||||||
pass # Perhaps on another drive or something
|
|
||||||
# Store link paths as posix for cross-platform.
|
|
||||||
new.name = filepath.as_posix()
|
|
||||||
status = bpy.ops.bim.load_link(filepath=filepath.as_posix(), use_cache=self.use_cache)
|
|
||||||
if status == {"CANCELLED"}:
|
if status == {"CANCELLED"}:
|
||||||
error_msg = (
|
error_msg = (
|
||||||
f'Error processing IFC file "{filepath.as_posix()}" '
|
f'Error processing IFC file "{filepath}" '
|
||||||
"was critical and blend file either wasn't saved or wasn't updated. "
|
"was critical and blend file either wasn't saved or wasn't updated. "
|
||||||
"See logs above in system console for details."
|
"See logs above in system console for details."
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -387,12 +387,7 @@ class BrowseExternalStyle(bpy.types.Operator):
|
|||||||
|
|
||||||
bpy.data.materials.remove(db["data_block"])
|
bpy.data.materials.remove(db["data_block"])
|
||||||
|
|
||||||
if self.use_relative_path:
|
filepath = tool.Ifc.get_uri(self.filepath, use_relative_path=self.use_relative_path)
|
||||||
filepath = os.path.relpath(self.filepath, Path(tool.Ifc.get_path()).parent)
|
|
||||||
else:
|
|
||||||
filepath = self.filepath
|
|
||||||
filepath = Path(filepath).as_posix()
|
|
||||||
|
|
||||||
attributes = context.scene.BIMStylesProperties.external_style_attributes
|
attributes = context.scene.BIMStylesProperties.external_style_attributes
|
||||||
attributes["Location"].string_value = filepath
|
attributes["Location"].string_value = filepath
|
||||||
attributes["Identification"].string_value = f"{self.data_block_type}/{self.data_block}"
|
attributes["Identification"].string_value = f"{self.data_block_type}/{self.data_block}"
|
||||||
@@ -565,19 +560,9 @@ class ChooseTextureMapPath(bpy.types.Operator):
|
|||||||
self.report({"ERROR"}, "Provide a texture map index")
|
self.report({"ERROR"}, "Provide a texture map index")
|
||||||
return {"CANCELLED"}
|
return {"CANCELLED"}
|
||||||
|
|
||||||
abs_path = Path(self.filepath)
|
filepath = tool.Ifc.get_uri(self.filepath, use_relative_path=self.use_relative_path)
|
||||||
if self.use_relative_path:
|
|
||||||
parent = Path(tool.Ifc.get_path()).parent
|
|
||||||
if abs_path.is_relative_to(parent):
|
|
||||||
image_filepath = abs_path.relative_to(parent)
|
|
||||||
else:
|
|
||||||
self.report({"INFO"}, "Path is not relative to the .ifc file, it will be saved as absolute.")
|
|
||||||
image_filepath = abs_path
|
|
||||||
else:
|
|
||||||
image_filepath = abs_path
|
|
||||||
|
|
||||||
texture = context.scene.BIMStylesProperties.textures[self.texture_map_index]
|
texture = context.scene.BIMStylesProperties.textures[self.texture_map_index]
|
||||||
texture.path = image_filepath.as_posix()
|
texture.path = filepath
|
||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -166,10 +166,7 @@ class SelectURIAttribute(bpy.types.Operator):
|
|||||||
# Do you know a better way?
|
# Do you know a better way?
|
||||||
pass
|
pass
|
||||||
if attribute:
|
if attribute:
|
||||||
filepath = self.filepath
|
attribute.string_value = tool.Ifc.get_uri(self.filepath, use_relative_path=self.use_relative_path)
|
||||||
if self.use_relative_path:
|
|
||||||
filepath = os.path.relpath(filepath, os.path.dirname(tool.Ifc.get_path()))
|
|
||||||
attribute.string_value = filepath
|
|
||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
|
|
||||||
def invoke(self, context, event):
|
def invoke(self, context, event):
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import ifcopenshell.util.schema
|
|||||||
import bonsai.core.tool
|
import bonsai.core.tool
|
||||||
import bonsai.bim.handler
|
import bonsai.bim.handler
|
||||||
import bonsai.tool as tool
|
import bonsai.tool as tool
|
||||||
|
from pathlib import Path
|
||||||
from bonsai.bim.ifc import IfcStore, IFC_CONNECTED_TYPE
|
from bonsai.bim.ifc import IfcStore, IFC_CONNECTED_TYPE
|
||||||
from typing import Optional, Union, Any, final, Literal
|
from typing import Optional, Union, Any, final, Literal
|
||||||
|
|
||||||
@@ -247,13 +248,17 @@ class Ifc(bonsai.core.tool.Ifc):
|
|||||||
return (uri if not uri else os.path.join(ifc_path, uri)).replace("\\", "/")
|
return (uri if not uri else os.path.join(ifc_path, uri)).replace("\\", "/")
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_relative_uri(cls, uri: str) -> str:
|
def get_uri(cls, uri: str | Path, use_relative_path: bool = False) -> str:
|
||||||
if not os.path.isabs(uri):
|
if not use_relative_path:
|
||||||
return uri
|
return Path(uri).absolute().resolve().as_posix()
|
||||||
ifc_path = cls.get_path()
|
uri = Path(uri)
|
||||||
|
if not os.path.isabs(uri) or not (ifc_path := cls.get_path()):
|
||||||
|
return uri.as_posix().replace("\\", "/")
|
||||||
|
if Path(uri).drive != Path(ifc_path).drive:
|
||||||
|
return uri.as_posix().replace("\\", "/")
|
||||||
if os.path.isfile(ifc_path):
|
if os.path.isfile(ifc_path):
|
||||||
ifc_path = os.path.dirname(ifc_path)
|
ifc_path = os.path.dirname(ifc_path)
|
||||||
return os.path.relpath(uri, ifc_path).replace("\\", "/")
|
return Path(os.path.relpath(uri, ifc_path)).as_posix().replace("\\", "/")
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def unlink(
|
def unlink(
|
||||||
|
|||||||
@@ -298,6 +298,7 @@ class Loader(bonsai.core.tool.Loader):
|
|||||||
if is_relative:
|
if is_relative:
|
||||||
ifc_path = Path(tool.Ifc.get_path())
|
ifc_path = Path(tool.Ifc.get_path())
|
||||||
image_url = ifc_path.parent / image_url
|
image_url = ifc_path.parent / image_url
|
||||||
|
image_url = image_url.absolute().resolve()
|
||||||
|
|
||||||
if not image_url.exists():
|
if not image_url.exists():
|
||||||
print(f"WARNING. Couldn't find texture by path {image_url}, it will be skipped.")
|
print(f"WARNING. Couldn't find texture by path {image_url}, it will be skipped.")
|
||||||
|
|||||||
@@ -724,8 +724,8 @@ class TestDrawingMaintainingSheetPosition(NewFile):
|
|||||||
|
|
||||||
# check drawing position on the sheet
|
# check drawing position on the sheet
|
||||||
drawing_data = self.get_sheet_drawing_data(sheet_path)
|
drawing_data = self.get_sheet_drawing_data(sheet_path)
|
||||||
assert drawing_data["foreground"] == (155.0, 155.0, 250.0, 250.0)
|
assert drawing_data["foreground"] == (30.0, 30.0, 500.0, 500.0)
|
||||||
assert drawing_data["view-title"] == (155.0, 410.0, 50.22, 10.0)
|
assert drawing_data["view-title"] == (30.0, 535.0, 50.22, 10.0)
|
||||||
|
|
||||||
|
|
||||||
class TestUpdateTextValue(NewFile):
|
class TestUpdateTextValue(NewFile):
|
||||||
@@ -835,6 +835,9 @@ class TestDrawingStyles(NewFile):
|
|||||||
bpy.ops.bim.add_drawing()
|
bpy.ops.bim.add_drawing()
|
||||||
ifc = tool.Ifc.get()
|
ifc = tool.Ifc.get()
|
||||||
drawing = ifc.by_type("IfcAnnotation")[0]
|
drawing = ifc.by_type("IfcAnnotation")[0]
|
||||||
|
bpy.ops.bim.expand_target_view(target_view="PLAN_VIEW")
|
||||||
|
props = bpy.context.scene.DocProperties
|
||||||
|
props.active_drawing_index = 2
|
||||||
bpy.ops.bim.activate_drawing(drawing=drawing.id())
|
bpy.ops.bim.activate_drawing(drawing=drawing.id())
|
||||||
self.drawing_styles = bpy.context.scene.DocProperties.drawing_styles
|
self.drawing_styles = bpy.context.scene.DocProperties.drawing_styles
|
||||||
|
|
||||||
@@ -857,7 +860,8 @@ class TestAddReferenceImage(NewFile):
|
|||||||
def test_run(self):
|
def test_run(self):
|
||||||
bpy.context.scene.BIMProjectProperties.template_file = "0"
|
bpy.context.scene.BIMProjectProperties.template_file = "0"
|
||||||
bpy.ops.bim.create_project()
|
bpy.ops.bim.create_project()
|
||||||
ifc_file = tool.Ifc.get()
|
ifc_path = Path("test/files/temp/test.ifc").absolute()
|
||||||
|
bpy.ops.bim.save_project(filepath=str(ifc_path), should_save_as=True)
|
||||||
|
|
||||||
filepath = Path("test/files/image.jpg").absolute()
|
filepath = Path("test/files/image.jpg").absolute()
|
||||||
bpy.ops.bim.add_reference_image(filepath=str(filepath))
|
bpy.ops.bim.add_reference_image(filepath=str(filepath))
|
||||||
@@ -870,6 +874,7 @@ class TestAddReferenceImage(NewFile):
|
|||||||
assert material.name == "image"
|
assert material.name == "image"
|
||||||
assert material.BIMStyleProperties.ifc_definition_id != 0
|
assert material.BIMStyleProperties.ifc_definition_id != 0
|
||||||
|
|
||||||
|
ifc_file = tool.Ifc.get()
|
||||||
style = ifc_file.by_id(material.BIMStyleProperties.ifc_definition_id)
|
style = ifc_file.by_id(material.BIMStyleProperties.ifc_definition_id)
|
||||||
styled_items = set(tool.Style.get_styled_items(style))
|
styled_items = set(tool.Style.get_styled_items(style))
|
||||||
representation_items = set(tool.Geometry.get_active_representation(obj).Items)
|
representation_items = set(tool.Geometry.get_active_representation(obj).Items)
|
||||||
|
|||||||
Reference in New Issue
Block a user