From d844bdbbbc1096a330abd4a8ecf2cb0c5e99dcc7 Mon Sep 17 00:00:00 2001 From: VargaDot Date: Mon, 3 Feb 2025 15:31:11 +0100 Subject: [PATCH] c-sharp Co-Authored-By: SP4R0W --- Composer/Composer.cs | 182 ++++++++++++++++++++++++++++++++++++++++++ ComposerRevamp.csproj | 8 ++ ComposerRevamp.sln | 19 +++++ project.godot | 4 + 4 files changed, 213 insertions(+) create mode 100644 Composer/Composer.cs create mode 100644 ComposerRevamp.csproj create mode 100644 ComposerRevamp.sln diff --git a/Composer/Composer.cs b/Composer/Composer.cs new file mode 100644 index 0000000..c4971c2 --- /dev/null +++ b/Composer/Composer.cs @@ -0,0 +1,182 @@ +using Godot; +using System.Threading.Tasks; +using Array = Godot.Collections.Array; + +public partial class Composer : Node +{ + [Signal] + public delegate void FinishedInitializingEventHandler(); + + [Signal] + public delegate void InvalidSceneEventHandler(string path); + + [Signal] + public delegate void FailedLoadingEventHandler(string path); + + [Signal] + public delegate void UpdatedLoadingEventHandler(string path, int progress); + + [Signal] + public delegate void FinishedLoadingEventHandler(Node scene); + + [Signal] + public delegate void LoadingActivatedEventHandler(); + + private bool _hasInitialized = false; + public bool HasInitialized { + get => _hasInitialized; + private set + { + _hasInitialized = value; + if (_hasInitialized) + EmitSignal(SignalName.FinishedInitializing); + } + } + + public bool IsUsingSubthreads {get; set;} = false; + public ResourceLoader.CacheMode CacheMode {get; set;} = ResourceLoader.CacheMode.Reuse; + + private float _loadingTimerDelay = 0.1f; + public float LoadingTimerDelay { + get => _loadingTimerDelay; + set + { + _loadingTimerDelay = value; + if (LoadingTimer != null) + LoadingTimer.WaitTime = _loadingTimerDelay; + } + } + + public Node Root {get; set;} + + private bool IsLoading = false; + private bool HasLoadingScreen = false; + private Timer LoadingTimer; + private string CurrentLoadingPath = ""; + private Node CurrentLoadScreen = null; + private Node CurrentScene = null; + + public override void _EnterTree() + { + InvalidScene += OnInvalidScene; + FailedLoading += OnFailedLoading; + FinishedLoading += OnFinishedLoading; + + Root = GetTree().Root; + SetupTimer(); + } + + public async void LoadScene(string path) + { + if (IsLoading) + return; + + if (!HasInitialized) + await ToSignal(this, SignalName.FinishedInitializing); + + Error loader = ResourceLoader.LoadThreadedRequest(path, "", IsUsingSubthreads, CacheMode); + if (!ResourceLoader.Exists(path) || loader != Error.Ok) + { + EmitSignal(SignalName.InvalidScene, path); + return; + } + + IsLoading = true; + + if (CurrentScene != null) + { + CurrentScene.QueueFree(); + CurrentScene = null; + } + + CurrentLoadingPath = path; + LoadingTimer.Start(); + } + + public Node SetupLoadScreen(string path) + { + if (HasLoadingScreen) + return CurrentLoadScreen; + + HasLoadingScreen = true; + CurrentLoadScreen = GD.Load(path).Instantiate(); + + Root.CallDeferred(MethodName.AddChild, CurrentLoadScreen); + Root.CallDeferred(MethodName.MoveChild, CurrentLoadScreen, Root.GetChildCount()-1); + + return CurrentLoadScreen; + } + + public void ClearLoadScreen() + { + CurrentLoadScreen.QueueFree(); + CurrentLoadScreen = null; + HasLoadingScreen = false; + } + + private void CheckLoadingStatus() + { + Array loadProgress = new(); + ResourceLoader.ThreadLoadStatus LoadStatus = ResourceLoader.LoadThreadedGetStatus(CurrentLoadingPath, loadProgress); + + switch (LoadStatus) + { + case ResourceLoader.ThreadLoadStatus.InvalidResource: + { + EmitSignal(SignalName.InvalidScene, CurrentLoadingPath); + LoadingTimer.Stop(); + break; + } + case ResourceLoader.ThreadLoadStatus.Failed: + { + EmitSignal(SignalName.FailedLoading, CurrentLoadingPath); + LoadingTimer.Stop(); + break; + } + case ResourceLoader.ThreadLoadStatus.InProgress: + { + EmitSignal(SignalName.UpdatedLoading, (int)loadProgress[0] * 100); + break; + } + case ResourceLoader.ThreadLoadStatus.Loaded: + { + LoadingTimer.Stop(); + EmitSignal(SignalName.FinishedLoading, ((PackedScene)ResourceLoader.LoadThreadedGet(CurrentLoadingPath)).Instantiate()); + break; + } + } + } + + private async Task SetupTimer() + { + LoadingTimer = new(); + LoadingTimer.Name = "LoadingTimer"; + LoadingTimer.WaitTime = LoadingTimerDelay; + LoadingTimer.Timeout += CheckLoadingStatus; + Root.CallDeferred(MethodName.AddChild, LoadingTimer); + + await ToSignal(LoadingTimer, Timer.SignalName.Ready); + + HasInitialized = true; + } + + private void OnFinishedLoading(Node scene) + { + Root.CallDeferred(MethodName.AddChild, scene); + CurrentScene = scene; + + CurrentLoadingPath = ""; + IsLoading = false; + } + + private void OnInvalidScene(string path) + { + GD.PrintErr($"Invalid resource: {path}"); + } + + private void OnFailedLoading(string path) + { + GD.PrintErr($"Failed to load resource: {path}"); + } +} + diff --git a/ComposerRevamp.csproj b/ComposerRevamp.csproj new file mode 100644 index 0000000..53cc1f1 --- /dev/null +++ b/ComposerRevamp.csproj @@ -0,0 +1,8 @@ + + + net6.0 + net7.0 + net8.0 + true + + \ No newline at end of file diff --git a/ComposerRevamp.sln b/ComposerRevamp.sln new file mode 100644 index 0000000..28e3ab1 --- /dev/null +++ b/ComposerRevamp.sln @@ -0,0 +1,19 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2012 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ComposerRevamp", "ComposerRevamp.csproj", "{E0E27FFE-5D97-46B3-BF50-BA399E9FC468}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + ExportDebug|Any CPU = ExportDebug|Any CPU + ExportRelease|Any CPU = ExportRelease|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {E0E27FFE-5D97-46B3-BF50-BA399E9FC468}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E0E27FFE-5D97-46B3-BF50-BA399E9FC468}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E0E27FFE-5D97-46B3-BF50-BA399E9FC468}.ExportDebug|Any CPU.ActiveCfg = ExportDebug|Any CPU + {E0E27FFE-5D97-46B3-BF50-BA399E9FC468}.ExportDebug|Any CPU.Build.0 = ExportDebug|Any CPU + {E0E27FFE-5D97-46B3-BF50-BA399E9FC468}.ExportRelease|Any CPU.ActiveCfg = ExportRelease|Any CPU + {E0E27FFE-5D97-46B3-BF50-BA399E9FC468}.ExportRelease|Any CPU.Build.0 = ExportRelease|Any CPU + EndGlobalSection +EndGlobal diff --git a/project.godot b/project.godot index 00319d9..cb041ee 100644 --- a/project.godot +++ b/project.godot @@ -23,6 +23,10 @@ Composer="*res://Composer/Composer.gd" gdscript/warnings/untyped_declaration=2 +[dotnet] + +project/assembly_name="ComposerRevamp" + [input] activate={