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

Cannot import any resource from any folder other than res:// #17848

Open
TwistedTwigleg opened this issue Mar 29, 2018 · 12 comments
Open

Cannot import any resource from any folder other than res:// #17848

TwistedTwigleg opened this issue Mar 29, 2018 · 12 comments
Assignees
Milestone

Comments

@TwistedTwigleg
Copy link
Contributor

@TwistedTwigleg TwistedTwigleg commented Mar 29, 2018

Godot version:
3.0.2

OS/device including version:
Windows 10, 64 bit

Issue description:
There does not seem to be any way to import/load any resource file outside of res://

I've tried importing files with various methods (see the example project for three methods for importing texture files). I've tried importing .png, .jpg, .dae, and .obj files from user:// and other folders (not in res://) with no avail.

According to the docs, the host file system can be used, but I've had no luck.

(Not sure if this is needed, but I'll explain anyway)
The reason I want to load textures/models from folders outside of res:// is to make a PBR texture creation tool similar to Surforge. I did some initial tests and it seems it's possible to make such a system in Godot (at least a simple version), and having the ability to load textures/models would be extremely helpful.

Steps to reproduce:
Try to load any resource outside of res://

Minimal reproduction project:
LoadFileExample.zip

@LinuxUserGD

This comment has been minimized.

Copy link
Contributor

@LinuxUserGD LinuxUserGD commented Mar 29, 2018

Could be the new issue for #17748 (exactly 100 issues before)

@TwistedTwigleg

This comment has been minimized.

Copy link
Contributor Author

@TwistedTwigleg TwistedTwigleg commented Mar 29, 2018

I looked at that, but even in user:// it was not working for .png, dae, or .obj files.

I just tried with the example project, and it doesn't load images from user://, even with code similar ot that posed in issue #17748 (the code changed slightly to work with images).


Kinda off topic, but...

Is there a way to load meshes like in the issue linked above? I looked but I didn't see anything for loading meshes from code.

@LinuxUserGD

This comment has been minimized.

Copy link
Contributor

@LinuxUserGD LinuxUserGD commented Mar 31, 2018

It seems like the .data property doesn't exist in VideoStreamWebm and I don't know any replacement.

@TwistedTwigleg

This comment has been minimized.

Copy link
Contributor Author

@TwistedTwigleg TwistedTwigleg commented Mar 31, 2018

No worries! I found a way around the issue for my project.

@LinuxUserGD

This comment has been minimized.

Copy link
Contributor

@LinuxUserGD LinuxUserGD commented Mar 31, 2018

So it's possible to load videos that are not packaged? Or do you mean a way around in general?

@TwistedTwigleg

This comment has been minimized.

Copy link
Contributor Author

@TwistedTwigleg TwistedTwigleg commented Apr 1, 2018

I mean in general. In the end I decided to split my model viewer into it's own project, where I dump the textures/models/scenes/others I want to load into that project's resource folder.

Sorry. I wish I had a better solution to offer.

@TwistedTwigleg

This comment has been minimized.

Copy link
Contributor Author

@TwistedTwigleg TwistedTwigleg commented Sep 23, 2018

Well, I found a interesting way around the problem, it is just a bit more involved.
You can convert files into something that is readable in Godot by using the get_var and store_var functions provided in the File class.

All it requires is placing the image in a Godot project, and then saving it out using get_var into a custom file. Then you can load it from anywhere and in any project. Here is the code I used to save and load image files:

# You can use this function in any Godot project, as long as it has a image file.
func create_file_selected(filepath):
	var image_file = load("res://test_image.jpg");
	image_file = image_file.get_data();
	
	var new_file = File.new();
	new_file.open(filepath, new_file.WRITE);
	new_file.store_var(image_file);
	new_file.close();

# Now delete test_image.jpg, it's .import file, and it's files in the .import folder!
# Then you can load and use the image from anywhere in the file system using the following code:
# (It can even be a completely different project!)

func load_file_selected(filepath):
	var GImage_File = File.new();
	
	if (GImage_File.file_exists(filepath)):
		GImage_File.open(filepath, GImage_File.READ);
		
		var g_texture = GImage_File.get_var();
		var new_img = ImageTexture.new();
		new_img.create_from_image(g_texture);
		
		GImage_File.close();
		
		get_node("Sprite").texture = new_img;

I can provide a test project if you guys want. I think you can use the same method to save almost any resource in Godot. I've tried saving meshes this way, but I haven't quite figured out how to do it.

This is probably more trouble than it's worth, but for anyone looking for a way to load files from anywhere in the file system, this method seems to work nicely.

@TwistedTwigleg

This comment has been minimized.

Copy link
Contributor Author

@TwistedTwigleg TwistedTwigleg commented Sep 28, 2018

I know this is totally off topic from this issue, and I promise this is the last off-topic post I'll make on this issue. I just wanted to share an update for anyone trying to load files outside a project, as I found it interesting and it may help others with similar interests/problems


Since I last posted, I figured out how to save and load meshes. Turns out it works almost exactly the same as saving images. You just need to use file.store_var(mesh_instance.mesh) to save meshes, and mesh_instance.mesh = file.get_var() to load meshes using the File class.

So, after figuring this out, I decided to take a small detour and see if I can save/load entire scenes using the File class. Turns out, you can!

You can save ANY node to a file using store_var and retrieve it using get_var. Just to be safe, I duplicate the nodes using node.duplicate(true) just to make sure I am not editing the nodes actually in the scene, but I do not think that it is necessary per say (though I have not tested either!)

All of the properties from the node will be saved, with only resources being lost on export. You can get around this by saving the resources as well (like Image resources on Sprite nodes) and then reassigning them once you have loaded the file.

One interesting thing to note is that nodes will forget their name when they are stored using get_var. This means you will need to store the names of all the nodes in the scene somewhere so you can reassign them once you have loaded the nodes using get_var.

Another interesting problem to work around is rebuilding the scene tree. I found a way around this by storing a JSON dictionary with the names of the children for each node in the scene. Then it is just a matter rebuilding the node tree using the JSON dictionary and a depth-first algorithm.


So after a few days of tinkering, I have successfully made a editor plugin that saves and loads .dscn (Deep-Copy Scene) files to and from the editor. (Made entirely in GDScript!)

Right now the plugin only has resource support for Sprites and Polygon2D nodes, but some nodes already work without needing resource support. (Like AnimationPlayer nodes).

In theory I should be able to support most, if not all, of the default nodes Godot provides, as only a few nodes need custom resource support.

Using .dscn files (or files made using the same method), you should be able to do the following, which I think is not currently doable using normal .tscn or .scn files:

  • Open scene files anywhere on the file system.
    • .tscn and .scn files can only be opened in res:// and user://. Because .dscn files use the File class, you can load scenes anywhere the File class can access.
    • In theory you may be able to send and receive .dscn files using the high level networking API, which would allow for easy sharing of .dscn files, but I'm not 100% sure if this will work or not.
  • Save and load user made scene files (from anywhere File can access) while the game is running.
    • This allows for super easy mod support!
  • Easily change/patch scene files without having to export a new .pkg file.
    • Users just have to download a new .dscn file and replace the old .dscn file to use the patch.

The one big downside with .dscn files is they are a tad more heavy when it comes to data storage. A simple .tscn scene is 3kb, while the same scene as is 22kb as a .dscn files. Most of the added size comes from embedding resources, like images, into the .dscn file, and from data that has to be stored to parse the .dscn file.

A minor downside is that in order to make a .dscn file, you have to use File, which means you have to have whatever you want to save in a Godot project. This means you cannot load image files without first converting them to .dscn files in a Godot project. This is not a huge issue for me, but it's worth mentioning.

So if anyone is looking to load scene files from anywhere in the file system, I have a plugin that (hopefully) will do exactly that. Right now the code messy, poorly documented, and there are still a lot of nodes missing resource support. I do not really know when I will be able to release it, but I'm hoping for sooner rather than later.

Right now I am struggling to get scripts from nodes in the open scene in the editor. It seems get_script() does not work with nodes in the editor, or I am going about it the wrong way. If anyone knows how to get scripts from nodes using a EditorPlugin, please let me know, as it would be awesome to be able to save/load scripts as well!

@KoBeWi

This comment has been minimized.

Copy link
Contributor

@KoBeWi KoBeWi commented May 5, 2019

Related: #14879

@akien-mga akien-mga modified the milestones: 3.2, 4.0 Nov 14, 2019
@bitdom8

This comment has been minimized.

Copy link

@bitdom8 bitdom8 commented Jan 18, 2020

https://github.com/TwistedTwigleg Is the solution you find eligible also for windows?

@TwistedTwigleg

This comment has been minimized.

Copy link
Contributor Author

@TwistedTwigleg TwistedTwigleg commented Jan 18, 2020

@bitdom8 It should work on Windows. It utilizes Godot’s File class, so as long as the File class works the same across all platforms, it should work.

Here is a link to the repository, if you want to try it: https://github.com/TwistedTwigleg/DSCN_Plugin

@bitdom8

This comment has been minimized.

Copy link

@bitdom8 bitdom8 commented Jan 18, 2020

@TwistedTwigleg Thanks, I just want to make my filedialog available for users to import from windows file system. DSCN not needed I guess

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
6 participants
You can’t perform that action at this time.