Skip to content

Commit 64eb327

Browse files
committed
Add PauseProcess timing
1 parent c83e8c6 commit 64eb327

File tree

7 files changed

+172
-60
lines changed

7 files changed

+172
-60
lines changed

addons/GDTask/Autoload/GDTaskPlayerLoopAutoload.cs

+32-34
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
1-
using System;
2-
using System.Linq;
3-
using Fractural.Tasks.Internal;
4-
using System.Threading;
1+
using Fractural.Tasks.Internal;
52
using Godot;
3+
using System;
64

75
namespace Fractural.Tasks
86
{
@@ -16,31 +14,8 @@ public enum PlayerLoopTiming
1614
{
1715
Process = 0,
1816
PhysicsProcess = 1,
19-
}
20-
21-
[Flags]
22-
public enum InjectPlayerLoopTimings
23-
{
24-
/// <summary>
25-
/// Preset: All loops(default).
26-
/// </summary>
27-
All = Process | PhysicsProcess,
28-
29-
/// <summary>
30-
/// Preset: All without last except LastPostLateUpdate.
31-
/// </summary>
32-
Standard = Process | PhysicsProcess,
33-
34-
/// <summary>
35-
/// Preset: Minimum pattern, Update | PhysicsProcess | LastPostLateUpdate
36-
/// </summary>
37-
Minimum =
38-
Process | PhysicsProcess,
39-
40-
// PlayerLoopTiming
41-
42-
PhysicsProcess = 1,
43-
Process = 2,
17+
PauseProcess = 2,
18+
PausePhysicsProcess = 3,
4419
}
4520

4621
public interface IPlayerLoopItem
@@ -85,7 +60,7 @@ public static GDTaskPlayerLoopAutoload Global
8560
get
8661
{
8762
if (s_Global != null) return s_Global;
88-
63+
8964
var newInstance = new GDTaskPlayerLoopAutoload();
9065
newInstance.Initialize();
9166
var currentScene = ((SceneTree)Engine.GetMainLoop()).CurrentScene;
@@ -104,6 +79,7 @@ public static GDTaskPlayerLoopAutoload Global
10479
private int mainThreadId;
10580
private ContinuationQueue[] yielders;
10681
private PlayerLoopRunner[] runners;
82+
private ProcessListener processListener;
10783

10884
public override void _Ready()
10985
{
@@ -118,15 +94,25 @@ public override void _Ready()
11894

11995
private void Initialize()
12096
{
97+
ProcessMode = ProcessModeEnum.Pausable;
12198
mainThreadId = System.Threading.Thread.CurrentThread.ManagedThreadId;
12299
yielders = new[] {
123100
new ContinuationQueue(PlayerLoopTiming.Process),
124101
new ContinuationQueue(PlayerLoopTiming.PhysicsProcess),
102+
new ContinuationQueue(PlayerLoopTiming.PauseProcess),
103+
new ContinuationQueue(PlayerLoopTiming.PausePhysicsProcess),
125104
};
126105
runners = new[] {
127106
new PlayerLoopRunner(PlayerLoopTiming.Process),
128107
new PlayerLoopRunner(PlayerLoopTiming.PhysicsProcess),
108+
new PlayerLoopRunner(PlayerLoopTiming.PauseProcess),
109+
new PlayerLoopRunner(PlayerLoopTiming.PausePhysicsProcess),
129110
};
111+
processListener = new ProcessListener();
112+
AddChild(processListener);
113+
processListener.ProcessMode = ProcessModeEnum.Always;
114+
processListener.OnProcess += PauseProcess;
115+
processListener.OnPhysicsProcess += PausePhysicsProcess;
130116
}
131117

132118
public override void _Notification(int what)
@@ -147,14 +133,26 @@ public override void _Notification(int what)
147133

148134
public override void _Process(double delta)
149135
{
150-
yielders[(int) PlayerLoopTiming.Process].Run();
151-
runners[(int) PlayerLoopTiming.Process].Run();
136+
yielders[(int)PlayerLoopTiming.Process].Run();
137+
runners[(int)PlayerLoopTiming.Process].Run();
152138
}
153139

154140
public override void _PhysicsProcess(double delta)
155141
{
156-
yielders[(int) PlayerLoopTiming.PhysicsProcess].Run();
157-
runners[(int) PlayerLoopTiming.PhysicsProcess].Run();
142+
yielders[(int)PlayerLoopTiming.PhysicsProcess].Run();
143+
runners[(int)PlayerLoopTiming.PhysicsProcess].Run();
144+
}
145+
146+
private void PauseProcess(double delta)
147+
{
148+
yielders[(int)PlayerLoopTiming.PauseProcess].Run();
149+
runners[(int)PlayerLoopTiming.PauseProcess].Run();
150+
}
151+
152+
private void PausePhysicsProcess(double delta)
153+
{
154+
yielders[(int)PlayerLoopTiming.PausePhysicsProcess].Run();
155+
runners[(int)PlayerLoopTiming.PausePhysicsProcess].Run();
158156
}
159157
}
160158
}
+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
using Godot;
2+
using System;
3+
4+
namespace Fractural.Tasks
5+
{
6+
public partial class ProcessListener : Node
7+
{
8+
public event Action<double> OnProcess;
9+
public event Action<double> OnPhysicsProcess;
10+
11+
public override void _Process(double delta)
12+
{
13+
OnProcess?.Invoke(delta);
14+
}
15+
16+
public override void _PhysicsProcess(double delta)
17+
{
18+
OnPhysicsProcess?.Invoke(delta);
19+
}
20+
}
21+
}

addons/GDTask/GDTask.Delay.cs

+5-7
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
using Fractural.Tasks.Internal;
2+
using Godot;
23
using System;
3-
using System.Collections;
44
using System.Runtime.CompilerServices;
55
using System.Threading;
6-
using Godot;
76

87
namespace Fractural.Tasks
98
{
@@ -82,15 +81,15 @@ public static GDTask WaitForEndOfFrame(CancellationToken cancellationToken)
8281
}
8382

8483
/// <summary>
85-
/// Same as GDTask.Yield(PlayerLoopTiming.LastPhysicsProcess).
84+
/// Same as GDTask.Yield(PlayerLoopTiming.PhysicsProcess).
8685
/// </summary>
8786
public static YieldAwaitable WaitForPhysicsProcess()
8887
{
8988
return GDTask.Yield(PlayerLoopTiming.PhysicsProcess);
9089
}
9190

9291
/// <summary>
93-
/// Same as GDTask.Yield(PlayerLoopTiming.LastPhysicsProcess, cancellationToken).
92+
/// Same as GDTask.Yield(PlayerLoopTiming.PhysicsProcess, cancellationToken).
9493
/// </summary>
9594
public static GDTask WaitForPhysicsProcess(CancellationToken cancellationToken)
9695
{
@@ -138,7 +137,6 @@ public static GDTask WaitForPhysicsProcess(CancellationToken cancellationToken)
138137
delayType = DelayType.Realtime;
139138
}
140139
#endif
141-
142140
switch (delayType)
143141
{
144142
case DelayType.Realtime:
@@ -566,11 +564,11 @@ public bool MoveNext()
566564
}
567565
}
568566

569-
if (timing == PlayerLoopTiming.Process)
567+
if (timing == PlayerLoopTiming.Process || timing == PlayerLoopTiming.PauseProcess)
570568
elapsed += GDTaskPlayerLoopAutoload.Global.DeltaTime;
571569
else
572570
elapsed += GDTaskPlayerLoopAutoload.Global.PhysicsDeltaTime;
573-
571+
574572
if (elapsed >= delayTimeSpan)
575573
{
576574
core.TrySetResult(null);

addons/GDTask/Internal/ContinuationQueue.cs

+7-1
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,11 @@ public void Run()
9595
case PlayerLoopTiming.Process:
9696
Process();
9797
break;
98-
default:
98+
case PlayerLoopTiming.PausePhysicsProcess:
99+
PausePhysicsProcess();
100+
break;
101+
case PlayerLoopTiming.PauseProcess:
102+
PauseProcess();
99103
break;
100104
}
101105
#else
@@ -105,6 +109,8 @@ public void Run()
105109

106110
void PhysicsProcess() => RunCore();
107111
void Process() => RunCore();
112+
void PausePhysicsProcess() => RunCore();
113+
void PauseProcess() => RunCore();
108114

109115
[System.Diagnostics.DebuggerHidden]
110116
void RunCore()

addons/GDTask/Internal/PlayerLoopRunner.cs

+8
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,12 @@ public void Run()
8282
case PlayerLoopTiming.Process:
8383
Process();
8484
break;
85+
case PlayerLoopTiming.PausePhysicsProcess:
86+
PausePhysicsProcess();
87+
break;
88+
case PlayerLoopTiming.PauseProcess:
89+
PauseProcess();
90+
break;
8591
}
8692
#else
8793
RunCore();
@@ -90,6 +96,8 @@ public void Run()
9096

9197
void PhysicsProcess() => RunCore();
9298
void Process() => RunCore();
99+
void PausePhysicsProcess() => RunCore();
100+
void PauseProcess() => RunCore();
93101

94102

95103
[System.Diagnostics.DebuggerHidden]

tests/manual/Test.cs

+74-14
Original file line numberDiff line numberDiff line change
@@ -5,56 +5,69 @@
55

66
namespace Tests.Manual
77
{
8-
public partial class Test : Node2D
8+
public partial class Test : Node
99
{
1010
[Export]
1111
private bool runTestOnReady;
1212
[Export]
1313
private NodePath spritePath;
14+
[Export]
15+
private Label pauseLabel;
1416
public Sprite2D sprite;
1517

1618
public override void _Ready()
1719
{
1820
sprite = GetNode<Sprite2D>(spritePath);
1921
if (runTestOnReady)
2022
Run().Forget();
23+
ProcessMode = ProcessModeEnum.Always;
24+
pauseLabel.Text = GetTree().Paused ? "Paused" : "Unpaused";
2125
}
2226

2327
public override void _Input(InputEvent @event)
2428
{
25-
if (@event.IsActionReleased("ui_select"))
29+
if (@event.IsActionReleased("ui_left"))
2630
{
2731
Run().Forget();
2832
}
33+
else if (@event.IsActionReleased("ui_right"))
34+
{
35+
RunPause().Forget();
36+
}
37+
else if (@event.IsActionReleased("ui_up"))
38+
{
39+
GetTree().Paused = !GetTree().Paused;
40+
pauseLabel.Text = GetTree().Paused ? "Paused" : "Unpaused";
41+
}
2942
}
3043

3144
private async GDTaskVoid Run()
3245
{
33-
GD.Print("Pre delay");
46+
GD.Print("Run: Pre delay");
3447
sprite.Visible = false;
3548
await GDTask.Delay(TimeSpan.FromSeconds(3));
3649
sprite.Visible = true;
37-
GD.Print("Post delay after 3 seconds");
50+
GD.Print("Run: Post delay after 3 seconds");
3851

39-
GD.Print("Pre RunWithResult");
52+
GD.Print("Run: Pre RunWithResult");
4053
string result = await RunWithResult();
41-
GD.Print($"Post got result: {result}");
54+
GD.Print($"Run: Post got result: {result}");
4255

43-
GD.Print("LongTask started");
56+
GD.Print("Run: LongTask started");
4457
var cts = new CancellationTokenSource();
4558

4659
CancellableReallyLongTask(cts.Token).Forget();
4760

4861
await GDTask.Delay(TimeSpan.FromSeconds(3));
4962
cts.Cancel();
50-
GD.Print("LongTask cancelled");
63+
GD.Print("Run: LongTask cancelled");
5164

5265
await GDTask.WaitForEndOfFrame();
53-
GD.Print("WaitForEndOfFrame");
66+
GD.Print("Run: WaitForEndOfFrame");
5467
await GDTask.WaitForPhysicsProcess();
55-
GD.Print("WaitForPhysicsProcess");
68+
GD.Print("Run: WaitForPhysicsProcess");
5669
await GDTask.NextFrame();
57-
GD.Print("NextFrame");
70+
GD.Print("Run: NextFrame");
5871
}
5972

6073
private async GDTask<string> RunWithResult()
@@ -66,13 +79,60 @@ private async GDTask<string> RunWithResult()
6679
private async GDTaskVoid CancellableReallyLongTask(CancellationToken cancellationToken)
6780
{
6881
int seconds = 10;
69-
GD.Print($"Starting long task ({seconds} seconds long).");
82+
GD.Print($"Run: Starting long task ({seconds} seconds long).");
7083
for (int i = 0; i < seconds; i++)
7184
{
72-
GD.Print($"Working on long task for {i} seconds...");
85+
GD.Print($"Run: Working on long task for {i} seconds...");
7386
await GDTask.Delay(TimeSpan.FromSeconds(1), cancellationToken: cancellationToken);
7487
}
75-
GD.Print("Finished long task.");
88+
GD.Print("Run: Finished long task.");
89+
}
90+
91+
private async GDTaskVoid RunPause()
92+
{
93+
GD.Print("RunPause: Pre delay");
94+
sprite.Visible = false;
95+
await GDTask.Delay(TimeSpan.FromSeconds(3), PlayerLoopTiming.PauseProcess);
96+
sprite.Visible = true;
97+
GD.Print("RunPause: Post delay after 3 seconds");
98+
99+
GD.Print("RunPause: Pre RunWithResult");
100+
string result = await RunWithResultPause();
101+
GD.Print($"RunPause: Post got result: {result}");
102+
103+
GD.Print("RunPause: LongTask started");
104+
var cts = new CancellationTokenSource();
105+
106+
CancellableReallyLongTaskPause(cts.Token).Forget();
107+
108+
await GDTask.Delay(TimeSpan.FromSeconds(3), PlayerLoopTiming.PauseProcess);
109+
cts.Cancel();
110+
GD.Print("RunPause: LongTask cancelled");
111+
112+
await GDTask.Yield(PlayerLoopTiming.PauseProcess);
113+
GD.Print("RunPause: Yield(PlayerLoopTiming.PauseProcess)");
114+
await GDTask.Yield(PlayerLoopTiming.PausePhysicsProcess);
115+
GD.Print("RunPause: Yield(PlayerLoopTiming.PausePhysicsProcess)");
116+
await GDTask.NextFrame(PlayerLoopTiming.PauseProcess);
117+
GD.Print("RunPause: NextFrame");
118+
}
119+
120+
private async GDTask<string> RunWithResultPause()
121+
{
122+
await GDTask.Delay(TimeSpan.FromSeconds(2), PlayerLoopTiming.PauseProcess);
123+
return "Hello";
124+
}
125+
126+
private async GDTaskVoid CancellableReallyLongTaskPause(CancellationToken cancellationToken)
127+
{
128+
int seconds = 10;
129+
GD.Print($"RunPause: Starting long task ({seconds} seconds long).");
130+
for (int i = 0; i < seconds; i++)
131+
{
132+
GD.Print($"RunPause: Working on long task for {i} seconds...");
133+
await GDTask.Delay(TimeSpan.FromSeconds(1), PlayerLoopTiming.PauseProcess, cancellationToken);
134+
}
135+
GD.Print("RunPause: Finished long task.");
76136
}
77137
}
78138
}

0 commit comments

Comments
 (0)