From a86456392b635a893deb3737fb88486f269573dd Mon Sep 17 00:00:00 2001 From: Andrej730 Date: Fri, 30 Jun 2023 17:57:23 +0500 Subject: [PATCH] improved relative path handling for textures #3365 now we're going to store all texture paths in .ifc as posix to keep them working if .ifc moved from one platform to another previously it was saving all paths as absolute --- src/blenderbim/blenderbim/tool/blender.py | 15 ++++++++++++ src/blenderbim/blenderbim/tool/loader.py | 23 ++++++++++++++----- src/blenderbim/blenderbim/tool/style.py | 5 +--- .../api/style/add_surface_textures.py | 4 +++- 4 files changed, 36 insertions(+), 11 deletions(-) diff --git a/src/blenderbim/blenderbim/tool/blender.py b/src/blenderbim/blenderbim/tool/blender.py index 1648c4bca0..0410a2daf2 100644 --- a/src/blenderbim/blenderbim/tool/blender.py +++ b/src/blenderbim/blenderbim/tool/blender.py @@ -215,6 +215,21 @@ class Blender: return current_iteration return cls.ensure_unique_name(name, objects, iteration + 1) + @classmethod + def blender_path_to_posix(cls, blender_path): + """Process blender path to be saved as posix. + + If path is relative the method will keep it relative to .ifc file + """ + if blender_path.startswith("//"): # detect relative blender path + ifc_path = Path(tool.Ifc.get_path()) + abs_path = Path(bpy.path.abspath(blender_path)) + path = abs_path.relative_to(ifc_path.parent) + else: + path = Path(blender_path) + + return path.as_posix() + @classmethod def get_default_selection_keypmap(cls): """keymap to replicate default blender selection behaviour with click and box selection""" diff --git a/src/blenderbim/blenderbim/tool/loader.py b/src/blenderbim/blenderbim/tool/loader.py index 0020cf39f8..e695ebafbb 100644 --- a/src/blenderbim/blenderbim/tool/loader.py +++ b/src/blenderbim/blenderbim/tool/loader.py @@ -191,16 +191,27 @@ class Loader(blenderbim.core.tool.Loader): mode = texture.get("Mode", None) node = None - if texture["type"] == "IfcImageTexture": - image_url = texture["URLReference"] - ifc_path = tool.Ifc.get_path() - if ifc_path: - image_url = bpy.path.abspath(image_url, start=Path(ifc_path).parent) + if texture["type"] != "IfcImageTexture": + print(f"WARNING. Texture of type {texture['type']} is not currently supported, it will be skipped.") + continue - if not os.path.exists(image_url): + original_image_url = texture["URLReference"] + is_relative = not os.path.isabs(original_image_url) + image_url = Path(original_image_url) + if is_relative: + ifc_path = Path(tool.Ifc.get_path()) + image_url = ifc_path.parent / image_url + + # import pdb; pdb.set_trace() + if not image_url.exists(): print(f"WARNING. Couldn't find texture by path {image_url}, it will be skipped.") continue + # keep url relative if it was before + image_url = str(image_url) + if is_relative and bpy.data.filepath: + image_url = bpy.path.relpath(image_url) + if reflectance_method in ["PHYSICAL", "NOTDEFINED"]: bsdf = tool.Blender.get_material_node(blender_material, "BSDF_PRINCIPLED") if mode == "NORMAL": diff --git a/src/blenderbim/blenderbim/tool/style.py b/src/blenderbim/blenderbim/tool/style.py index 980269b729..6ae871ace7 100644 --- a/src/blenderbim/blenderbim/tool/style.py +++ b/src/blenderbim/blenderbim/tool/style.py @@ -143,13 +143,10 @@ class Style(blenderbim.core.tool.Style): path = getattr(props, prop_name) if not path: continue - if not os.path.abspath(path) and tool.Ifc.get_path(): - path = os.path.join(os.path.dirname(tool.Ifc.get_path()), path) - texture_data = { "Mode": prop_mode, "type": "IfcImageTexture", - "URLReference": path, + "URLReference": tool.Blender.blender_path_to_posix(path), } textures.append(texture_data) diff --git a/src/ifcopenshell-python/ifcopenshell/api/style/add_surface_textures.py b/src/ifcopenshell-python/ifcopenshell/api/style/add_surface_textures.py index 3218b9e54b..e11650e2bd 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/style/add_surface_textures.py +++ b/src/ifcopenshell-python/ifcopenshell/api/style/add_surface_textures.py @@ -130,12 +130,14 @@ class Usecase: return self.create_surface_texture(links[0].from_node, "DIFFUSE") def create_surface_texture(self, node, mode): + import blenderbim.tool as tool + texture = self.file.create_entity( "IfcImageTexture", RepeatS=node.extension == "REPEAT", RepeatT=node.extension == "REPEAT", Mode=mode, - URLReference=node.image.filepath, + URLReference=tool.Blender.blender_path_to_posix(node.image.filepath), ) self.textures.append(texture) self.process_texture_coordinates(node, texture)