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

Fix GDScript load with relative path #66550

Closed
wants to merge 1 commit into from

Conversation

RedMser
Copy link
Contributor

@RedMser RedMser commented Sep 28, 2022

Supersedes #37324
Fixes #35832

First time touching GDScript internals, hope I didn't mess anything up!

As suggested in a comment in the previous PR, all utility function calls now pass the script reference, which is used for figuring out the absolute path.
Also by using get_path() instead of path, this PR supports built-in scripts as well.

Open Question:
I'm currently passing the analyzer a nullptr script reference. While ResourceLoader::load(parser->script_path, "Script") is possible, I don't understand yet what the "benefits" are, since I don't understand the analyzer's purpose beyond type checking.

@RedMser RedMser requested a review from a team as a code owner September 28, 2022 15:06
@Chaosus Chaosus added this to the 4.0 milestone Sep 28, 2022
@akien-mga akien-mga modified the milestones: 4.0, 4.x Feb 12, 2023
@YuriSizov YuriSizov modified the milestones: 4.x, 4.1 Feb 12, 2023
@RedMser RedMser force-pushed the gd-load-relative-path branch from 9a5c3e3 to fb90101 Compare April 28, 2023 18:28
@adamscott
Copy link
Member

Could you add a unit test to the PR? I would hope to merge this PR for the 4.1 release, but time is running out.
If you need more info, don't hesitate to chat us in #gdscript.

Passes the script reference to all gdscript utility function calls.
@RedMser RedMser force-pushed the gd-load-relative-path branch from fb90101 to 209842c Compare June 18, 2023 16:36
@RedMser
Copy link
Contributor Author

RedMser commented Jun 18, 2023

@adamscott Added some tests. It seems like type inference does not work, since it's emitting warnings. Probably due to me leaving out the analyzer.

I don't really have time to figure this stuff out, so if you or another GDScript dev knows more about this, please fix up my commit or attach a diff that fixes this part, if it's urgent to land it.


EDIT: I confused load with preload - the former always returns Resource so I assume this is OK. I also realize that ResourceLoader::load(parser->script_path, "Script") would be possible, but I have no idea if this is correct -or- what is even the reason I'd want to do this 🙃

Copy link
Member

@adamscott adamscott left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PR seems good to me. OK for 4.1!

@@ -229,19 +229,24 @@ struct GDScriptUtilityFunctionsDefinitions {
}
}

static inline void load(Variant *r_ret, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) {
static inline void load(Variant *r_ret, const Variant **p_args, int p_arg_count, const Ref<GDScript> p_script, Callable::CallError &r_error) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We usually do const Ref<T> & where suitable, would that work here?

@dalexeev
Copy link
Member

Might it be better to resolve this in the compiler and VM (with a separate opcode to convert relative paths, if the argument is unknown at compile time) than to construct a Ref<GDScript> on each utility function call? I do not think that your option is significantly more expensive, just mention an alternative solution.

@akien-mga akien-mga modified the milestones: 4.1, 4.2 Jun 21, 2023
@adamscott
Copy link
Member

Added the PR to the PRs to review by the GDScript team.

@vnen
Copy link
Member

vnen commented Jul 24, 2023

I do think this is overkill to solve this particular issue. Adding an argument to every function just because one needs it looks like too much.

We can discuss other solutions to this.

For instance, we could have a second, optional argument to load that works as the base for relative paths and at compile time we can insert this (if not explicitly set). So relative paths would work even if generated dynamically in the user script.

If dynamic is not a necessity, we could detect relative paths at runtime and prepend the script's base directory to it so it becomes an absolute path.

I think an opcode as @dalexeev suggested is also too much, but we could generate the logic with a combination of opcodes (it does increase the overhead of calling load though).

In any case, I do believe we can find a more localized solution rather than changing all utility functions.

@dalexeev
Copy link
Member

I think an opcode as @dalexeev suggested is also too much, but we could generate the logic with a combination of opcodes (it does increase the overhead of calling load though).

Note that if the load() argument is a constant expression, then the path is resolved in the compiler and the opcode is not generated. (Which is quite common in my opinion, users may still use load() instead of preload(), even for constant expressions.)

This only affects variable expressions such as load("path/" + file) or load("path/%s" % file). In theory, we could optimize some of these cases too, as long as the prefix is known at compile time.

@RedMser
Copy link
Contributor Author

RedMser commented Jul 24, 2023

I'll leave a more optimized implementation to someone who has more experience with GDScript internals. Thanks for the feedback!

@dalexeev
Copy link
Member

@RedMser Thanks for your contribution nonetheless!

@YuriSizov YuriSizov removed this from the 4.2 milestone Jul 31, 2023
@dalexeev dalexeev mentioned this pull request Jan 24, 2024
3 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

load doesn't work for relative paths that go back a folder without "res://"
7 participants