Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Clarify what an imported resource really is and how to load external files (png, jpg, ogg, wav...) #2148

Open
mrcdk opened this issue Jan 18, 2019 · 13 comments
Labels
area:manual Issues and PRs related to the Manual/Tutorials section of the documentation enhancement

Comments

@mrcdk
Copy link
Contributor

mrcdk commented Jan 18, 2019

it's not the first time (and won't be the last) where an user tries to load an external file (a file that has not been imported) with load() or ResourceLoader.load() and gets confused because it doesn't load or it fails.

We need to explain them that those functions only work with imported files and what they should do to load external files. I think we need to specify somewhere that imported resources aren't the same as files and how to load external files but I have no idea where.

I'll try to explain it and hope that someone can unmess the mess I write 😅

In godot, imported resources aren't the same as files.

Explanation on what godot does when you import a file here https://docs.godotengine.org/en/latest/getting_started/workflow/assets/import_process.html

So a resource links a file with one or more converted files. For example, the path res://icon.png doesn't point to the file my_project/icon.png but it will read the icon.png.import file and this file will contain the path to the converted files something like my_project/.import/icon-47---.stex and my_project/.import/icon-12---.stex which are the files that the engine has created from your file and they are the ones that it will use at runtime.

When you export your project my_project/icon.png won't be in exported into the pck file but only the icon.png.import file pointing to those converted files.

And some examples to load different files:

Load an ogg file:

func play_external_file(path):
	var ogg = AudioStreamOGGVorbis.new()
	var file = File.new()	
	file.open(path, File.READ)
	ogg.data = file.get_buffer(file.get_len())
	file.close()
	$AudioStreamPlayer.stream = ogg
	$AudioStreamPlayer.play()

Load a png file:

func get_external_texture(path):
    var img = Image.new()
    img.load(path)
    var texture = ImageTexture.new()
    texture.create_from_image(img)
    return texture
@cbscribe
Copy link
Contributor

Good one. This probably belongs in the "I/O" section of Tutorials.

@mrcdk
Copy link
Contributor Author

mrcdk commented Jan 20, 2019

Updated the load an image example. Image already has a load() function that will do all the work for us (reading the file and using the correct loader to load the image)

@pwab
Copy link

pwab commented Apr 2, 2020

it's not the first time (and won't be the last) ...

Damn right. I also stepped into that hell of confusion and so I want to ping this issue (or just mark it as a reminder for myself).

As discussed in the referenced issue of the godot repository there are currently a few file formats which can be loaded at runtime:

By a combination of gdscript functions:

Or by using a plugin:

A simple page in the I/O section of the docs which sums this up and collects the mentioned code snippets that were posted in those related issues would be of great benefit.

@bitdom8

This comment was marked as off-topic.

@golddotasksquestions
Copy link
Contributor

golddotasksquestions commented Oct 4, 2020

func get_external_texture(path):
var img = Image.new()
img.load(path)
var texture = ImageTexture.new()
texture.create_from_image(img)
return texture

This does not work for me on Android
I get the following errors:

E 0:00:00.266 load_image: Error opening file '/storage/emulated/0/Pictures/cardgame/00000001.jpg'.
<C++ Source> core/io/image_loader.cpp:56 @ load_image()
E 0:00:00.266 texture_set_data: Condition "!read.ptr()" is true.
<C++ Source> drivers/gles3/rasterizer_storage_gles3.cpp:836 @ texture_set_data()
E 0:00:24.465 load_source_code: Condition "err" is true. Returned: err
<C++ Source> modules/gdscript/gdscript.cpp:829 @ load_source_code()

It does work fine on Windows though.
I had the same issues on Android with the same errors with this this answer from Zylann:
https://godotengine.org/qa/50876/load-texture-from-file-and-assign-to-texture

Any help how to load external image data as a sprite texture on Android would be greatly appreciated!

Edit: Ok so after a hole day of painful trail and error, I figured out I apparently I have to check "Media Content Control", "Read External Storage", "Write External Storage", and call

OS.request_permissions()
print(OS.get_granted_permissions())

Any single one of those options won't do.
With that the errors are gone, however the image is still not shown. I do see a black rectangle in the exact size of my texture at the exact location of my sprite, but unlike in Windows where the texture shows, on Android it does not.
What else is there to do?
I really wish those error messages would be more useful and this process was documented somewhere.

@RockyMadio
Copy link

it's not the first time (and won't be the last) where an user tries to load an external file (a file that has not been imported) with load() or ResourceLoader.load() and gets confused because it doesn't load or it fails.

We need to explain them that those functions only work with imported files and what they should do to load external files. I think we need to specify somewhere that imported resources aren't the same as files and how to load external files but I have no idea where.

I'll try to explain it and hope that someone can unmess the mess I write 😅

In godot, imported resources aren't the same as files.
Explanation on what godot does when you import a file here https://docs.godotengine.org/en/latest/getting_started/workflow/assets/import_process.html
So a resource links a file with one or more converted files. For example, the path res://icon.png doesn't point to the file my_project/icon.png but it will read the icon.png.import file and this file will contain the path to the converted files something like my_project/.import/icon-47---.stex and my_project/.import/icon-12---.stex which are the files that the engine has created from your file and they are the ones that it will use at runtime.
When you export your project my_project/icon.png won't be in exported into the pck file but only the icon.png.import file pointing to those converted files.

And some examples to load different files:

Load an ogg file:

func play_external_file(path):
	var ogg = AudioStreamOGGVorbis.new()
	var file = File.new()	
	file.open(path, File.READ)
	ogg.data = file.get_buffer(file.get_len())
	file.close()
	$AudioStreamPlayer.stream = ogg
	$AudioStreamPlayer.play()

Load a png file:

func get_external_texture(path):
    var img = Image.new()
    img.load(path)
    var texture = ImageTexture.new()
    texture.create_from_image(img)
    return texture

Thank you for sharing, how would you load a wav file?

@pwab
Copy link

pwab commented Sep 9, 2021

Thank you for sharing, how would you load a wav file?

As stated in my last comment you could use https://github.com/Gianclgar/GDScriptAudioImport. The code for loading a wav-file can be found on line 61. (But there are problems with specific files)

@SylvanSign
Copy link
Contributor

@mrcdk thank you so much for this thread! I was just struggling with this over the last couple days...

And I came across this Q&A page for the exact same issue, so I just submitted an answer that links back to this thread 😄
https://godotengine.org/qa/126162/cannot-load-texture-from-pck-file-created-using-pckpacker

@skyace65 skyace65 added the area:manual Issues and PRs related to the Manual/Tutorials section of the documentation label Dec 28, 2022
@SteveSmith16384
Copy link

Another aspect to this which I don't think has been mentioned is when loading a texture for a sprite in a tool script (i.e. design time). If I add the texture via the editor or use load(), it links the texture file as an "ext_resource". However, if I use the code get_external_texture() as above, it adds the texture data directly to the tscn file, making for potentially very large files.

@pwab
Copy link

pwab commented Jul 20, 2023

Unfortunately my comment above is quite outdated. As I wanted to update my knowledge for Godot 4.x, I stumbled across two new methods coming with Godot 4.2 🎉:

For the sake of completeness (and because I wondered why it hadn't been linked yet), here's the supplemental proposal:
godotengine/godot-proposals#1632

@FrasherGray
Copy link

it's not the first time (and won't be the last) ...

Damn right. I also stepped into that hell of confusion and so I want to ping this issue (or just mark it as a reminder for myself).

As discussed in the referenced issue of the godot repository there are currently a few file formats which can be loaded at runtime:

By a combination of gdscript functions:

* [jpg/png](https://github.com/godotengine/godot/issues/18367#issuecomment-383521520) ([or see here](https://github.com/godotengine/godot/issues/17848#issuecomment-607438775))

* [ogg](https://github.com/godotengine/godot/issues/17748#issuecomment-376320424)

Or by using a plugin:

* [wav/ogg/mp3](https://github.com/Gianclgar/GDScriptAudioImport)

* [obj](https://github.com/Ezcha/gd-obj)

* [dscn](https://github.com/TwistedTwigleg/DSCN_Plugin)

A simple page in the I/O section of the docs which sums this up and collects the mentioned code snippets that were posted in those related issues would be of great benefit.

Are there any alternative obj loaders? The one linked doesn't work without mtl.

@pwab
Copy link

pwab commented Jul 22, 2024

Hey @FrasherGray thanks to your comment I stumbled upon the docs page Runtime file loading and saving introduced by @Calinou in #8363 (and there is also a corresponding demo added in godotengine/godot-demo-projects#993). So there is actually a pretty current documentation about file loading and you should ignore old comments and scripts that were posted before.

The question arises if this issue here is still relevant now that the page exist. It wasn't linked in the PR so I guess @Calinou wasn't aware of this discussion.


Anyway regarding your question:
The addon you linked was rewritten for Godot 4 and updated a year ago. Not sure if it still works but according to the Readme loading a obj-file without a mtl-file is possible:

The second argument path_to_mtl is optional. When excluded the parser will check if a materials file is specified in the .obj data and will automatically load it if valid.

The issue talking about it not being able to do so seems to be quite old. Have you tested it yourself?

The only alternative I see right now is using Godots ability of loading a GLTF file at runtime. So you could convert any obj-file into a glb-file first and then load those. There is still an open issue about it #6385 that you should read if you consider using this workaround.

@FrasherGray
Copy link

@pwab I got it to work by commenting out the entire "use-mtl" case where the issue was arising. Since I will always be assigning materials within the project and not with blender, it works fine for me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area:manual Issues and PRs related to the Manual/Tutorials section of the documentation enhancement
Projects
None yet
Development

No branches or pull requests