[OnInstantiate] does not search all project scene files
My project is setup so scripts are separate from scene files
I have always organized my project by having a res://Scenes folder for all .tscn files and a res://Scripts folder for all .cs files. I'm not sure how I feel about keeping the .tscn files next to the .cs files. I might just refactor my entire projects file structure just to use this attribute.
The Issue
I get the following error when I try to use [OnInstantiate] in UIOptions.cs. This is because there is no UIOptions.tscn file in this path as its located under res://Scenes not res://Scripts.
Error: Cannot open file 'res://Template/Scripts/UI/Options/UIOptions.tscn'.
Actual Scene Path: res://Scenes/Prefabs/UI/options.tscn
Actual Script Path: res://Template/Scripts/UI/Options/UIOptions.cs
I've made the decision to refactor my project to make it so all scripts are right next to their respective scene files.
Yes, true. I have an alternate path for tscn parsing on SceneTree, but not for any other attribute. It would suck having to specify an alternative for all these attribute-based generators, so unfortunately this paradigm does tend to lend itself to grouping scene files with source code.
If it helps, I nest my tscn/tres files under my cs files in Visual Studio: https://github.com/Cat-Lips/F00F (see .filenesting.json)
(Of course, also open to any ideas about how to better support separation of scenes and source if that's what is preferred...)
You could tell users to include the following in their main Godot .csproj file.
<ItemGroup>
<AdditionalFiles Include="**\*.tscn" />
</ItemGroup>
And then you could loop through each .tscn file in your source generator and parse it.
[Generator]
public class SourceGen: ISourceGenerator
{
public void Execute(GeneratorExecutionContext context)
{
// Get all additional text files
IEnumerable<AdditionalText> tscnFiles = context.AdditionalFiles
.Where(file => Path.GetExtension(file.Path)
.Equals(".tscn", StringComparison.OrdinalIgnoreCase));
// Do something with tscnFiles here
}
}
Ok, great. By providing the additional files to a source generator, it can find the matching tscn. But in your case, I've just realised that the names are different (options.tscn/UIOptions.cs), so even if they were in the same folder or using an additional files lookup, we'd probably still need to use an attribute property...
If the name and path is the same, it's easy to replace the extension to get the scene file, eg:
public static T GetScene<T>() where T : GodotObject
=> LoadScene<T>().Instantiate<T>();
public static PackedScene LoadScene<T>() where T : GodotObject
=> GD.Load<PackedScene>(GetScriptPath<T>().Replace(".cs", ".tscn"));
public static string GetScriptPath<T>() where T : GodotObject
=> typeof(T).GetCustomAttribute<ScriptPathAttribute>(false).Path;
(https://github.com/Cat-Lips/F00F.Core/blob/main/addons/F00F.Core/Utilities/Utils.cs)
Anyway, I'll see what I can do to fix this for you.
But in your case, I've just realised that the names are different (options.tscn/UIOptions.cs), so even if they were in the same folder or using an additional files lookup, we'd probably still need to use an attribute property...
Or... could parse tscn files to get cs path and create a static lookup
Hi Valk. You happy for me to close this issue?
I've gotten use to putting my scripts next to scene files.
Thanks bud