Export ImageTexture node for an image identified in material node tree #39

Merged
Cedric Steiert merged 14 commits from vmarchetti/io_scene_x3d:image-export into main 2024-11-23 03:26:03 +01:00
Collaborator

Re-enables export of an X3D ImageTexture node when an image texture is identified in the material node tree as the base color of a material.

The export routine will also save the image to user disk, even when the image is embedded in blender data as a PackedFile, with no explicit filename

Re-enables export of an X3D ImageTexture node when an image texture is identified in the material node tree as the base color of a material. The export routine will also save the image to user disk, even when the image is embedded in blender data as a PackedFile, with no explicit filename
Vincent Marchetti added 1 commit 2024-11-09 01:35:11 +01:00
properly write the ImageTexture node even when there is no
explicit file name (as the case when image is read from a glTF file)
and save the image file to disk
Author
Collaborator

The attached file earth_textureimage.blend can be used to demonstrate the X3D and image file export.
Load it into Blender, invoke the X3D export with default export options.
A file earth_textureimage.x3d and and image file earth_topo.png will be written to disk.
Results can be viewed in an X3D viewer such as Castle Model Viewer

The attached file earth_textureimage.blend can be used to demonstrate the X3D and image file export. Load it into Blender, invoke the X3D export with default export options. A file earth_textureimage.x3d and and image file earth_topo.png will be written to disk. Results can be viewed in an X3D viewer such as [Castle Model Viewer](https://castle-engine.io/castle-model-viewer)
Collaborator

Thanks for the test file, that seems to be working just fine.
However i caught an edge case which should be handled as well: when the image node inside blender is not yet saved to disk, we get following error:

error msg
Traceback (most recent call last):
  File "__init__.py", line 346, in execute
    return export_x3d.save(context, **keywords)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "export_x3d.py", line 1716, in save
    export(file,
  File "export_x3d.py", line 1656, in export
    image_filepath = os.path.join(base_dst, svRecord.url)
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<frozen ntpath>", line 147, in join
  File "<frozen genericpath>", line 152, in _check_arg_types
TypeError: join() argument must be str, bytes, or os.PathLike object, not 'NoneType'
To replicate, create a new blend file, on the default cube in the shader node editor add a new image texture node and create a new image (press new), don't save to disk. A bit further testing, this seems to be happening to files on disk as well, files need to be packed into the blender file by the user manually (File > External Data > Pack Resources) to work properly. This should be fixed.

To sum up, cases to handle:

  • (done) packed files
  • files on disk
  • files not yet saved
  • image texture node is inside a NodeGroup: currently the image won't get detected. If possible add support for that, if not document as known limitation
  • movie files: Ideally handle them properly or message the user that this ain't supported.

Features i'd wish for to be included, but i'm open for discussion:

  • Path Mode selector in exporter ui (like fbx exporter) to copy image, use absolute/relative path, pack to subdirectory
  • Don't overwrite copied image: Currently the image gets resaved to the output location at each export, i'd suggest to first check if file exists. Additionaly a new ui property "Overwrite/Replace Resource Files" could be exposed. In my opinion that IO operation can get saved, as images usually don't change too often. Alternatively (this is only applicable for files on disk), the modification stamp could get checked first.
Thanks for the test file, that seems to be working just fine. However i caught an edge case which should be handled as well: when the image node inside blender is not yet saved to disk, we get following error: <details> <summary>error msg</summary> ``` Traceback (most recent call last): File "__init__.py", line 346, in execute return export_x3d.save(context, **keywords) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "export_x3d.py", line 1716, in save export(file, File "export_x3d.py", line 1656, in export image_filepath = os.path.join(base_dst, svRecord.url) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "<frozen ntpath>", line 147, in join File "<frozen genericpath>", line 152, in _check_arg_types TypeError: join() argument must be str, bytes, or os.PathLike object, not 'NoneType' ``` </details> To replicate, create a new blend file, on the default cube in the shader node editor add a new image texture node and create a new image (press new), don't save to disk. A bit further testing, this seems to be happening to files on disk as well, files need to be packed into the blender file by the user manually (File > External Data > Pack Resources) to work properly. This should be fixed. **To sum up, cases to handle:** - (done) packed files - files on disk - files not yet saved - image texture node is inside a NodeGroup: currently the image won't get detected. If possible add support for that, if not document as known limitation - movie files: Ideally handle them properly or message the user that this ain't supported. **Features i'd wish for to be included, but i'm open for discussion:** - Path Mode selector in exporter ui (like fbx exporter) to copy image, use absolute/relative path, pack to subdirectory - Don't overwrite copied image: Currently the image gets resaved to the output location at each export, i'd suggest to first check if file exists. Additionaly a new ui property "Overwrite/Replace Resource Files" could be exposed. In my opinion that IO operation can get saved, as images usually don't change too often. Alternatively (this is only applicable for files on disk), the modification stamp could get checked first.
Vincent Marchetti added 1 commit 2024-11-16 00:03:57 +01:00
to be used in the export. For purposes of development the default setting
in the UI is set to COPY, this is contrary to other default value for path_mode.
It may be appropriate to set the default UI setting to AUTO upon merging into
release code.

Added logging messages to export_x3d.py. The intent here is to extend the copy_set
mechanism to handle cases where the image file does not exist on disk at time of
export.
Vincent Marchetti added 5 commits 2024-11-18 21:27:07 +01:00
Vincent Marchetti changed title from WIP: Export ImageTexture node for an image identified in material node tree to Export ImageTexture node for an image identified in material node tree 2024-11-18 21:31:06 +01:00
Author
Collaborator

At commit 832ed4 the code has passed basic testing, including handling the use-case of an image created within blender. The writing of image files has been rewritten to make use of the existing Blender utilities for evaluate file paths according to the path_mode variable, which can now be set by the user.

Image files are written to a new location only when the path_mode is set to 'COPY' upon export. When path_mode is set to COPY, images are written to s "textures" subfolder which is a file system sibling of the exported x3d file.

At commit 832ed4 the code has passed basic testing, including handling the use-case of an image created within blender. The writing of image files has been rewritten to make use of the existing Blender utilities for evaluate file paths according to the path_mode variable, which can now be set by the user. Image files are written to a new location only when the path_mode is set to 'COPY' upon export. When path_mode is set to COPY, images are written to s "textures" subfolder which is a file system sibling of the exported x3d file.
Vincent Marchetti requested review from Cedric Steiert 2024-11-18 23:49:56 +01:00
Cedric Steiert requested changes 2024-11-19 16:58:43 +01:00
Dismissed
Cedric Steiert left a comment
Collaborator

Hi Vincent, thanks for the recent changes. I looked through the code, as far as i can tell it looks good. Few minor typos in docstrings and comments (which also could get simplified).

On testing i found a few minor usage issues, which could get addressed:

  • (edit: seems like an issue with subfolders in freewrl) newly created unsaved image does get saved on export , but not getting displayed.
  • image texture inside a node group still does not get detected and in the code i see no comment declaring it as a technical limitation
  • url is not like setting: example for Filepath Copy url='"textures/Untitled.png" "Untitled.png" "D:/Daten/x3d_test/Untitled.png"' -> copy, strip, absolute combined, should only be copy. This is most likely caused by the legacy algorithm block, as it creates all possible combinations and that full list gets used; from my understanding the filepath_reference should get used
  • despite the export section being named Images and Movies a movie texture gets saved as ImageTexture node instead of MovieTexture. So either warn the user when a movie file gets detected or handle it correctly
Hi Vincent, thanks for the recent changes. I looked through the code, as far as i can tell it looks good. Few minor typos in docstrings and comments (which also could get simplified). On testing i found a few minor usage issues, which could get addressed: - (edit: seems like an issue with subfolders in freewrl) newly created unsaved image does get saved on export , but not getting displayed. - image texture inside a node group still does not get detected and in the code i see no comment declaring it as a technical limitation - url is not like setting: example for Filepath Copy `url='"textures/Untitled.png" "Untitled.png" "D:/Daten/x3d_test/Untitled.png"'` -> copy, strip, absolute combined, should only be copy. This is most likely caused by the legacy algorithm block, as it creates all possible combinations and that full list gets used; from my understanding the filepath_reference should get used - despite the export section being named `Images and Movies` a movie texture gets saved as ImageTexture node instead of MovieTexture. So either warn the user when a movie file gets detected or handle it correctly
@ -259,6 +266,19 @@ def export(file,
# store files to copy
copy_set = set()
# if path_mode is copy, create a temporary folder particular
Collaborator

why is this temporary folder needed? Could you add that to the comment?

why is this temporary folder needed? Could you add that to the comment?
@ -654,3 +622,1 @@
fw(ident_step + 'scale="%.6f %.6f"\n' % (sca_x, sca_y))
fw(ident_step + 'rotation="%.6f"\n' % rot)
fw(ident_step + '/>\n')
# this is a location at which we should
Collaborator

Could you shorten the comment down? For example "Find and write ImageTexture and potentially TextureTransform if present" reads a bit better in my opinion

Could you shorten the comment down? For example "Find and write ImageTexture and potentially TextureTransform if present" reads a bit better in my opinion
@ -1268,2 +1236,3 @@
fw(ident_step + "url='%s'\n" % ' '.join(['"%s"' % escape(f) for f in images]))
if has_packed_file or not imageTextureNode.image.filepath :
# assume that if the data has a packed file or it
Collaborator

comment is a bit tricky to read, maybe simplify: "Write only the filename if image is packed or has no filepath provided"

comment is a bit tricky to read, maybe simplify: "Write only the filename if image is packed or has no filepath provided"
@ -1270,0 +1261,4 @@
image_urls = [filepath_ref]
else:
image_urls = [image_filename]
logger.warn("dangling image url %r" % [image_filename])
Collaborator

warn is deprecated, use warning instead

warn is deprecated, use warning instead
@ -1270,0 +1263,4 @@
image_urls = [image_filename]
logger.warn("dangling image url %r" % [image_filename])
else:
# this is the legacy algorithm for determining
Collaborator

Could also get simplified: "Legacy Algorithm for preparing and normalizing image filepaths: Get the full path, reference path (e.g. relative), filename"

Could also get simplified: "Legacy Algorithm for preparing and normalizing image filepaths: Get the full path, reference path (e.g. relative), filename"
@ -1519,0 +1553,4 @@
# for svRecord in imageInMaterial.imagesToSave():
Collaborator

I personally prefer to not leave dead code in, as it gets outdated quickly and no one remembers what is was used for. So ideally either remove or explain in a short leading comment the purpose of this commented out code block

I personally prefer to not leave dead code in, as it gets outdated quickly and no one remembers what is was used for. So ideally either remove or explain in a short leading comment the purpose of this commented out code block
@ -0,0 +1,114 @@
# SPDX-FileCopyrightText: 2011-2024 Blender Foundation
Collaborator

Not sure about the copyright. Technically this is no longer property of bf, so if you want, you can put in your name (or Web3D Consortium as you're a member there) and current year

Not sure about the copyright. Technically this is no longer property of bf, so if you want, you can put in your name (or Web3D Consortium as you're a member there) and current year
@ -0,0 +30,4 @@
def _find_node_by_idname(nodes, idname):
"""
nodes a sequence of Nodes, idname a string
Collaborator

a few typos here

a few typos here
@ -0,0 +41,4 @@
See https://docs.blender.org/api/current/bpy.types.ShaderNode.html for list of
ShaderNode subclasses
if 0 targets are found, returns None
Collaborator

the output as code is not really needed in the docstring, but if you want simplify: Returns None if no targets are found or returns the first found target

the output as code is not really needed in the docstring, but if you want simplify: Returns None if no targets are found or returns the first found target
@ -0,0 +73,4 @@
bsdf_principled = _find_node_by_idname(
[ndlink.from_node for ndlink in material_output.inputs.get(SURFACE_ATTRIBUTE).links],
_ShaderNodeTypes.BSDF_PRINCIPLED)
if bsdf_principled is None : return None
Collaborator

for better readability put the return into it's own line

for better readability put the return into it's own line
@ -0,0 +79,4 @@
image_texture = _find_node_by_idname(
[ndlink.from_node for ndlink in bsdf_principled.inputs.get(BASE_COLOR_ATTRIBUTE).links],
_ShaderNodeTypes.IMAGE_TEXTURE )
if image_texture is None: return None
Collaborator

for better readability put the return into it's own line

for better readability put the return into it's own line
@ -0,0 +83,4 @@
_logger.debug("located image texture node %r" % image_texture)
return image_texture
## x3d_supported_file_extension = {"PNG" : ".png","JPEG" : ".jpg"}
Collaborator

dead code

dead code
Author
Collaborator

I am not able to reproduce the reported fault:

  • newly created unsaved image does not get saved on export in any mode,

I follow the procedure in the comment above from 9 Nov 2024 10:27 AM EST #39 (comment)
creating a new image on the initial cube; at no point do I save the image to file or try to pack it; the Shader Editor before I export is attached.

Upon export to X3D with Path Mode = COPY an image file is written to textures/florence.png

I am not able to reproduce the reported fault: - newly created unsaved image does not get saved on export in any mode, I follow the procedure in the comment above from 9 Nov 2024 10:27 AM EST https://projects.blender.org/extensions/io_scene_x3d/pulls/39#issuecomment-1335727 creating a new image on the initial cube; at no point do I save the image to file or try to pack it; the Shader Editor before I export is attached. Upon export to X3D with Path Mode = COPY an image file is written to textures/florence.png
Collaborator

Sorry, my bad. Indeed it's working for usnaved textures. The image is in the textures folder and the url correctly set. It's the comparison software "FreeWRL 4.0" that is having issues reading image textures from relative subdfolders as it seems (I'll see if the issue is already reported somewhere then). Thank you for testing and commenting.

Sorry, my bad. Indeed it's working for usnaved textures. The image is in the textures folder and the url correctly set. It's the comparison software "FreeWRL 4.0" that is having issues reading image textures from relative subdfolders as it seems (I'll see if the issue is already reported somewhere then). Thank you for testing and commenting.
Collaborator

By the way, also the current blender x3d importer has trouble with loading images generated by the x3d exporter. Will have to look into it, wether it's the importers fault or the exporter.

By the way, also the current blender x3d importer has trouble with loading images generated by the x3d exporter. Will have to look into it, wether it's the importers fault or the exporter.
Collaborator

Regarding the blender importer: As it seems, it's a format issue. The exporter produces url='"textures\Untitled.png"', the importer expects url="textures\Untitled.png". Should this be fixed in your export script or in the existing import script?

Regarding the blender importer: As it seems, it's a format issue. The exporter produces `url='"textures\Untitled.png"'`, the importer expects `url="textures\Untitled.png"`. Should this be fixed in your export script or in the existing import script?
Author
Collaborator

url='"textures\Untitled.png"' is the correct syntax for this X3D property, which is an MFString type, list of strings. The form expected by the importer is a common mistake. I propose to keep the exported output strictly correct and the import tolerant of the other form. I can submit the issue and prepare the patch

url='"textures\Untitled.png"' is the correct syntax for this X3D property, which is an MFString type, list of strings. The form expected by the importer is a common mistake. I propose to keep the exported output strictly correct and the import tolerant of the other form. I can submit the issue and prepare the patch
Collaborator

Alright, thanks for the feedback. A patch would be greatly appreciated for the import script; a issue is not really needed for that (i usually only create them if it's a backlog task or needs more info). You can push the patch directly to main or include it with this PR.

Alright, thanks for the feedback. A patch would be greatly appreciated for the import script; a issue is not really needed for that (i usually only create them if it's a backlog task or needs more info). You can push the patch directly to main or include it with this PR.
Collaborator

Regarding the issue with freewrl: Dug found out, it's the backslash which caused the issue. Changing it to a foreslash works. Double backslash would also work, but most likely only for certain os/software.

I tested a bit further: Seems like the unsaved image part is broken, as the url of an unsaved image with option copy looks like this url='"textures\Untitled123.png"' but if the image was loaded from disk, it looks like this url='"textures/Untitled123.png"' (i removed the other urls as they shouldn't be there in the first place). Note the difference between backslash (wrong) and foreslash (correct).

Can you replicate and fix this?

Regarding the issue with freewrl: Dug found out, it's the backslash which caused the issue. Changing it to a foreslash works. Double backslash would also work, but most likely only for certain os/software. I tested a bit further: Seems like the unsaved image part is broken, as the url of an unsaved image with option copy looks like this `url='"textures\Untitled123.png"'` but if the image was loaded from disk, it looks like this `url='"textures/Untitled123.png"'` (i removed the other urls as they shouldn't be there in the first place). Note the difference between backslash (wrong) and foreslash (correct). Can you replicate and fix this?
Vincent Marchetti added 5 commits 2024-11-22 05:12:42 +01:00
only include 1 path to  image file in the url attribute of the ImageTexture node, and that path to
an image file is determined by the bpy_extras.io_utils.path_reference utility

configured the Path Mode == COPY case to not write image files to a subdirectory,
copy those image files into the same folder as the export X3D.
until this code implements the export of Movie textures.

The code will output a WARN level logging message if the Blender data contains a
movie file format in an image texture to export.
Author
Collaborator

Recent commits have improved the comments, removed the ashes of dead code.

The file path written to the URL property now follows the logic of the bpy_extras.io_utils.path_reference utility and only one such file path is included. For the Path Mode = COPY case the url and location of copied file are in the same folder as the exported X3D and the url is a relative path to the image.

The limitation that Image Textures defined inside of Node groups are not identified is documented in the docstring to the imageTexture_in_material function

Recent commits have improved the comments, removed the ashes of dead code. The file path written to the URL property now follows the logic of the bpy_extras.io_utils.path_reference utility and only one such file path is included. For the Path Mode = COPY case the url and location of copied file are in the same folder as the exported X3D and the url is a relative path to the image. The limitation that Image Textures defined inside of Node groups are not identified is documented in the docstring to the imageTexture_in_material function
Collaborator

After the backslash issue is fixed (the cases for disk texture auto, absolute, relative path mode are pending), the PR can get merged and a new extension version published after the patch for the MFString is in.

Another minor issue that tickles me, is that an unsaved image gets saved in all modes except copy as url='"."'. This crashes other software like freewrl. The crash of other software is not really our concern, however "." ain't really correct either. Fyi the crash is caused with any ImageTexture node without url values, so full node removal would most likely be best. At current state, i'll count it as known rare issue, thus fixing would not really be mandatory.

After the backslash issue is fixed (the cases for disk texture auto, absolute, relative path mode are pending), the PR can get merged and a new extension version published after the patch for the MFString is in. Another minor issue that tickles me, is that an unsaved image gets saved in all modes except copy as `url='"."'`. This crashes other software like freewrl. The crash of other software is not really our concern, however "." ain't really correct either. Fyi the crash is caused with any ImageTexture node without url values, so full node removal would most likely be best. At current state, i'll count it as known rare issue, thus fixing would not really be mandatory.
Vincent Marchetti added 1 commit 2024-11-22 15:34:04 +01:00
The case of no value for the filepath property can occur in at least two ways
- the user creates the image using Blender UI and does not save it to disk
- the image is imported from a format such as glTF which supports embedded image data
Author
Collaborator

I have added a warning message sent to logging in the case you mentioned of an unsaved image being exported with the Path Mode set to something other than COPY. I agree that it would be best not to include the X3D ImageTexture node at all in this case, and if or when we make the code upgrade to use an xml library, such as xml.etree.ElementTree, to generate the xml output this would be appropriate. In the current code we are sort of streaming the xml text piece by piece and it's awkward to cancel out of a node output.

As for the backslash vs fore slash issue, I propose that the current code that, in COPY mode, refers to the image file as a relatiive file path not in a subdirectory, and the copied image file is saved to the same folder as the exported X3D files, sidesteps the problem by avoiding slashed altogether.

In general, I tried to simplify the X3D export code by relying on the logic of the bpy_extras.io_utils.path_reference utility, code visible at https://projects.blender.org/blender/blender/src/branch/main/scripts/modules/bpy_extras/io_utils.py , to create the file paths according to path_mode. That code uses os.path.join and so the slash/backslash choice will depend on whether the code is being run in Windows OS. Our options for further solving the slash/backslash problem would be

  • modifying the file path after is returned from the path_reference utility, this would then make the X3D export conventions potentially differ from the formats' exports
  • modify the bpy_extras.io_utils.path_reference code , which I do not recommend

The path_reference utility, and the Path Mode concept is, I think, intended for a use case of content creators working within a shared OS and file system. I suggest that the option of using COPY into the same folder as exported X3D gives content creators the basics to deploy their content outside that shared-filesystem framework, probably with a different tool

I have added a warning message sent to logging in the case you mentioned of an unsaved image being exported with the Path Mode set to something other than COPY. I agree that it would be best not to include the X3D ImageTexture node at all in this case, and if or when we make the code upgrade to use an xml library, such as xml.etree.ElementTree, to generate the xml output this would be appropriate. In the current code we are sort of streaming the xml text piece by piece and it's awkward to cancel out of a node output. As for the backslash vs fore slash issue, I propose that the current code that, in COPY mode, refers to the image file as a relatiive file path not in a subdirectory, and the copied image file is saved to the same folder as the exported X3D files, sidesteps the problem by avoiding slashed altogether. In general, I tried to simplify the X3D export code by relying on the logic of the bpy_extras.io_utils.path_reference utility, code visible at https://projects.blender.org/blender/blender/src/branch/main/scripts/modules/bpy_extras/io_utils.py , to create the file paths according to path_mode. That code uses os.path.join and so the slash/backslash choice will depend on whether the code is being run in Windows OS. Our options for further solving the slash/backslash problem would be - modifying the file path after is returned from the path_reference utility, this would then make the X3D export conventions potentially differ from the formats' exports - modify the bpy_extras.io_utils.path_reference code , which I do not recommend The path_reference utility, and the Path Mode concept is, I think, intended for a use case of content creators working within a shared OS and file system. I suggest that the option of using COPY into the same folder as exported X3D gives content creators the basics to deploy their content outside that shared-filesystem framework, probably with a different tool
Collaborator

In the current code we are sort of streaming the xml text piece by piece and it's awkward to cancel out of a node output.

Thus rare known issue. Will fix it if someone complains about it, but i highly doubt this will happen. Another fix despite removing the node would be to fallback to COPY in case the path is empty.
Maybe path mode COPY should even be the default option as files usally get sent elsewhere afterwards?

The path_reference utility, and the Path Mode concept is, I think, intended for a use case of content creators working within a shared OS and file system. I suggest that the option of using COPY into the same folder as exported X3D gives content creators the basics to deploy their content outside that shared-filesystem framework, probably with a different tool

The issue here unfortunately is, that other software (like freewrl) even in windows versions don't handle the regular backslash. Thus the current path output by bpy_extras.io_utils.path_reference is not usable in at least some other x3d software. Foreslash and double backslash would be allowed here. The blender x3d importer can handle all three cases.

As for the backslash vs fore slash issue, I propose that the current code that, in COPY mode, refers to the image file as a relatiive file path not in a subdirectory

I saw that commit already and although it fixes the copy case, the auto(relative)/absolute/relative path options are still affected. For COPY the subdir choice is more or less a individual preference.

modifying the file path after is returned from the path_reference utility

I think this would be the easiest and best option here by simply replacing \ with /.

this would then make the X3D export conventions potentially differ from the formats' exports

If this poses an issue, maybe exposing an option fore-/backslash to the user could help in aiding further issues

> In the current code we are sort of streaming the xml text piece by piece and it's awkward to cancel out of a node output. Thus rare known issue. Will fix it if someone complains about it, but i highly doubt this will happen. Another fix despite removing the node would be to fallback to COPY in case the path is empty. Maybe path mode COPY should even be the default option as files usally get sent elsewhere afterwards? > The path_reference utility, and the Path Mode concept is, I think, intended for a use case of content creators working within a shared OS and file system. I suggest that the option of using COPY into the same folder as exported X3D gives content creators the basics to deploy their content outside that shared-filesystem framework, probably with a different tool The issue here unfortunately is, that other software (like freewrl) even in windows versions don't handle the regular backslash. Thus the current path output by bpy_extras.io_utils.path_reference is not usable in at least some other x3d software. Foreslash and double backslash would be allowed here. The blender x3d importer can handle all three cases. > As for the backslash vs fore slash issue, I propose that the current code that, in COPY mode, refers to the image file as a relatiive file path not in a subdirectory I saw that commit already and although it fixes the copy case, the auto(relative)/absolute/relative path options are still affected. For COPY the subdir choice is more or less a individual preference. > modifying the file path after is returned from the path_reference utility I think this would be the easiest and best option here by simply replacing `\` with `/`. > this would then make the X3D export conventions potentially differ from the formats' exports If this poses an issue, maybe exposing an option fore-/backslash to the user could help in aiding further issues
Vincent Marchetti added 1 commit 2024-11-23 02:18:12 +01:00
to POSIX/Unixy filepath separator in the url property of a
ImageTexture X3D node.
Cedric Steiert approved these changes 2024-11-23 02:59:23 +01:00
Cedric Steiert left a comment
Collaborator

Thanks for the contribution, will merge soon.

Thanks for the contribution, will merge soon.
Cedric Steiert merged commit 4500a03b86 into main 2024-11-23 03:26:03 +01:00
Sign in to join this conversation.
No description provided.