1 module sbylib.graphics.action.sequence;
2 
3 public import std.datetime;
4 
5 import sbylib.graphics.action.action : IAction, ImplAction;
6 import sbylib.graphics.action.animation : Animation;
7 import sbylib.graphics.action.run : RunAction;
8 import sbylib.graphics.action.wait : WaitAction;
9 import sbylib.event : VoidEvent;
10 import std.container : Array;
11 
12 class ActionSequence : IAction {
13 
14     mixin ImplAction;
15 
16     private ActionNode rootAction;
17     private IAction[] actionList;
18 
19     static opCall() {
20         return new typeof(this);
21     }
22 
23     override void start() {
24         rootAction.action.start();
25     }
26 
27     auto animate(string mem,T)(T value) {
28         import std.traits : ReturnType;
29 
30         alias Type = ReturnType!(mixin("value."~mem));
31         auto result = new Animation!Type(
32             () => mixin("value."~mem),
33             (Type v) { mixin("value."~mem) = v; }
34         );
35         add(result);
36         return result;
37     }
38 
39     Animation!T animate(T)(ref T value) {
40         auto result = new Animation!T(value);
41         add(result);
42         return result;
43     }
44 
45     IAction action(IAction action) {
46         add(action);
47         return action;
48     }
49 
50     WaitAction wait(Duration dur) {
51         auto result = new WaitAction(dur);
52         add(result);
53         return result;
54     }
55 
56     RunAction run(void delegate() f) {
57         auto result = new RunAction(f);
58         add(result);
59         return result;
60     }
61 
62     RunAction run(void delegate(void delegate()) f) {
63         auto result = new RunAction(f);
64         add(result);
65         return result;
66     }
67 
68     private void add(IAction action) {
69         if (rootAction is null) {
70             rootAction = new ActionNode(action);
71         } else {
72             rootAction.add(new ActionNode(action));
73         }
74     }
75 
76     private void onFinish() {
77         for (int j = 0; j < callbackList.length; j++) {
78             callbackList[j]();
79         }
80         callbackList.clear();
81     }
82 
83     private class ActionNode {
84         IAction action;
85         ActionNode next;
86 
87         this(IAction action) { 
88             import sbylib.graphics.action.action : when;
89             import sbylib.event.event : then;
90 
91             this.action = action; 
92             when(action.finish).then({
93                 if (next is null) {
94                     onFinish();
95                 } else {
96                     next.action.start();
97                 }
98                 rootAction = next;
99             });
100         }
101 
102         void add(ActionNode node) {
103             if (next is null) {
104                 next = node;
105             } else {
106                 next.add(node);
107             }
108         }
109     }
110 }