-
-
Notifications
You must be signed in to change notification settings - Fork 98
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
Expose static ScriptPath
for scripts in C# for 4.0
#5238
Comments
Though, the more I think about it, we'd have no way to know about a constant/static property on a class passed into an extension method, unless it was on all Godot.Objects. Perhaps add a static property and just assign it via Source Gen? |
I'm not sure what you mean but this sounds like a bug that should be fixed rather than the intended behavior of instantiating scenes using exports.
You could use source generators yourself to generate a property that is exposed or even create a static class that contains a reference to all the scene paths (instead of the scripts), similar to how the
This would still be the case since
I don't see how having a
The sample you provided is not using reflection so I'm not sure what you mean. However, you could use reflection to access the value of the
You can't access static properties or constants of a class in a generic context, the only way to do this would be using an interface with static virtual methods which is only available in .NET 7.0 (not released yet, will be released in November). Here is another way of doing what you are doing in your sample but using reflection and the using System;
using System.IO;
using System.Reflection;
using Godot;
public static class SceneInstantiater
{
public static T Instantiate<T>() where T : class
{
var type = typeof(T);
var attr = type.GetCustomAttribute<ScriptPathAttribute>();
if (attr == null)
throw new InvalidOperationException($"Type '{type}' does not have a ScriptPathAttribute.");
var path = Path.ChangeExtension(attr.Path, ".tscn");
var scene = GD.Load<PackedScene>(path);
return scene.Instantiate<T>();
}
} To avoid reflection altogether you could, like I mentioned above, implement a source generator that exposes your own Alternatively, you can instead generate something similar to the |
I think this conversation is outside the scope of this proposal, but there are plenty of bugs that can cause it, however the root of it is the design. The editor has access to modify
This is interesting and I haven't learned enough about source generators enough to utilize this, but I'm planning to spend some time this weekend to learn more.
What you're referencing is me talking about a drawback of my current implementation. As you say, scripts and scenes are not 1 to 1, so there is no reliable way for Godot to automatically instance a scene from a script. It has to be up to the user and their personal organization structure to make that connection. As I mentioned, the goal of this proposal is not to enforce a specific way of organizing your scenes/scripts (I think that would be a bad idea), but to allow the user a way to know where the script is, giving them a starting point, so they can make their own implementation and find scenes relative to the script.
In my comment, I realized I hadn't thought this through entirely, unfortunately. I had forgotten that you can't access static methods or properties of a constrained generic type parameter. Looks like another avenue would be necessary.
I didn't realize that
Just to restate: this was just to find a way to expose the script's path in a reliable way without reflection so the user can create their own Instantiate method based around their project organization. Now that I know that I don't really see any other way to be able to make an instantiate method without two references to the class type without having to generate the specific method implementation on every script, which seems like a lot of bloat. I'm going to wait a day and then close this unless anyone has a better solution. |
Describe the project you are working on
A systems test project for Godot 4.0.
Describe the problem or limitation you are having in your project
I was previously looking for a more dynamic way to instantiate scenes in code than using hardcoded strings, and less brittle than editor exports. For my current solution, I added the following static method in my extensions class to get the script's file path, and then modify it to get the scene's file path:
In order for this to work, I need to add this method to every script:
Then I can call it like so:
or even shorter:
Pros:
Cons:
Describe the feature / enhancement and how it helps to overcome the problem or limitation
I noticed awhile ago we added the
ScriptPathAttribute
via Source Generators:godotengine/godot#46713
It seems we already get the file path, but can't access it. If it were able to be generated as a constant or static string on each class, I'd be able to construct the scene's file path:
without magic strings
without adding extra methods to each script
without using exports
without editor setup
without redundant calls
without reflection
If any of this is wrong, please feel free to correct me.
Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams
I'm not the most savvy with Source Generators, but along with the attribute, we'd also just create a static or constant string of the
ScriptPath
.Then anyone would be able to implement their own extension method, to accommodate their personal organization structure, and call it like so:
If this enhancement will not be used often, can it be worked around with a few lines of script?
Unfortunately, it cannot... or at least only with reflection.
Is there a reason why this should be core and not an add-on in the asset library?
I'm not suggesting a full feature, rather just an extra field. I think if this were a full feature to instantiate scenes, requiring a rigid organization structure, this would be better suited as an add-on. I think since this is only exposing one field, it's much more flexible for use in anyone's personal organization system, and possibly for other use cases.
The text was updated successfully, but these errors were encountered: