-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathCoroutineExample.cs
More file actions
105 lines (93 loc) · 3.48 KB
/
CoroutineExample.cs
File metadata and controls
105 lines (93 loc) · 3.48 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
namespace Pollus.Examples;
using System.Collections;
using Pollus.Coroutine;
using Pollus.Debugging;
using Pollus.ECS;
using Pollus.Engine;
using Pollus.Input;
public partial class CoroutineExample : IExample
{
public string Name => "coroutine";
IApplication? app;
enum TestState
{
First,
Second,
}
public void Run() => (app = Application.Builder
.AddPlugins([
new InputPlugin(),
new StatePlugin<TestState>(TestState.Second),
])
.AddSystemSet<CoroutineSystemSet>()
.AddSystems(CoreStage.Update, Coroutine.Create(new("TestCoroutine")
{
Locals = [Local.From(1f)],
},
static (param) =>
{
return Routine();
static IEnumerable<Yield> Routine()
{
yield return Yield.WaitForSeconds(1f);
Log.Info("Coroutine Tick, Press Space to enter First State");
yield return Coroutine.WaitForEnterState(TestState.First);
Log.Info("Entered First State, Press Space to exit First State");
yield return Coroutine.WaitForExitState(TestState.First);
Log.Info("Exited First State");
}
}))
.AddSystems(CoreStage.Update, FnSystem.Create("Input", static (ButtonInput<Key> keyboard, State<TestState> state) =>
{
if (keyboard.JustPressed(Key.Space))
{
state.Set(state.Current switch
{
TestState.First => TestState.Second,
TestState.Second => TestState.First,
_ => throw new NotImplementedException(),
});
}
}))
.Build())
.Run();
public void Stop()
{
app?.Shutdown();
}
[SystemSet]
public partial class CoroutineSystemSet
{
[Coroutine(nameof(Routine))]
static readonly SystemBuilderDescriptor RoutineDescriptor = new()
{
Stage = CoreStage.Update,
};
static IEnumerable<Yield> Routine(Time time)
{
var frames = int.Min((int)(1f / time.DeltaTimeF), 100_000);
if (time.FrameCount < 10) frames = 10;
yield return CustomYields.WaitForFrames(frames);
Log.Info($"WaitForFrames custom yield, waited for {frames} frames, frameCount: {time.FrameCount}");
}
}
static class CustomYields
{
struct WaitForFramesData
{
public required int FrameCount { get; init; }
int current { get; set; }
public static bool WaitForNFramesHandler(scoped ref Yield yield, scoped in Param<World> param)
{
ref var data = ref yield.GetCustomData<WaitForFramesData>();
if (++data.current >= data.FrameCount) return true;
return false;
}
}
public static Yield WaitForFrames(int frameCount)
{
YieldCustomInstructionHandler<Param<World>>.AddHandler<WaitForFramesData>(WaitForFramesData.WaitForNFramesHandler, []);
return Yield.Custom(new WaitForFramesData { FrameCount = frameCount });
}
}
}