1 module caLib_util.Controller;
2 
3 import caLib_abstract.lattice : isLattice;
4 import caLib_abstract.rule : isRule, isReversibleRule;
5 import caLib_abstract.renderer : isRenderer;
6 import derelict.sdl2.sdl;
7 import std.stdio: writeln;
8 import std.exception : Exception;
9 
10 
11 
12 auto create_Controller(Lt, Rt, REt)(Lt* lattice, Rt* rule, REt* renderer)
13 {
14     return new Controller!(Lt, Rt, REt)(lattice, rule, renderer);
15 }
16 
17 
18 
19 class Controller(Lt, Rt, REt)
20 {
21 
22 private:
23 
24     Lt* lattice;
25     Rt* rule;
26     REt* renderer;
27 
28     void delegate() task;
29     bool running;
30     bool recording;
31 
32     static if(isReversibleRule!Rt)
33     {
34         bool reverse;
35     }
36 
37 public:
38 
39     this(Lt* lattice, Rt* rule, REt* renderer)
40     {
41         this.lattice = lattice;
42         this.rule = rule;
43         this.renderer = renderer;
44 
45         this.task = null;
46         this.running = false;
47         this.recording = false;
48 
49         static if(isReversibleRule!Rt)
50         {
51             bool reverse = false;
52         }
53     }
54 
55     void start()
56     {
57         renderer.render();
58 
59         task = &this.pause;
60 
61         while(true)
62         {
63             SDL_Event events;
64             while(SDL_PollEvent(&events))
65             {
66                 if(events.type == SDL_QUIT)
67                 {
68                     return;
69                 }
70                 else if(events.type == SDL_KEYDOWN)
71                 {
72                     if(events.key.keysym.sym == SDLK_SPACE)
73                     {
74                         if(running)
75                         {
76                             task = &this.pause;
77                             running = false;
78                         }
79                         else
80                         {
81                             task = &this.run;
82                             running = true;
83                         }
84                     }
85                     else if(events.key.keysym.sym == SDLK_d)
86                     {
87                         run();
88                         task = &this.pause;
89                         running = false;
90                     }
91                     else if(events.key.keysym.sym == SDLK_s)
92                     {
93                         screenshot();
94                     }
95                     else if(events.key.keysym.sym == SDLK_r)
96                     {
97                         record();
98                     }
99                     static if(isReversibleRule!Rt)
100                     {
101                         if(events.key.keysym.sym == SDLK_a)
102                         {
103                             reverse = !reverse;
104                             writeln("running reverse");
105                         }
106                     }
107                 }
108             }
109 
110             task();
111         }
112     }
113 
114     void pause() {}
115 
116     void run()
117     {
118         static if(isReversibleRule!Rt)
119         {
120             if(!reverse)
121                 rule.applyRule();
122             else
123                 rule.applyRuleReverse();
124         }
125         else
126         {
127             rule.applyRule();
128         }
129         renderer.render();
130     }
131 
132     void screenshot()
133     {
134         writeln("screenshoting. The programm might seem unresponsive");
135         try
136         {
137             renderer.screenshot("screenshot.png");
138             writeln("done screenshoting");
139         }
140         catch(Exception e)
141         {
142             writeln("could not screenshot. Error message:\n    ", e.msg);
143         }
144     }
145 
146     void record()
147     {
148         if(recording)
149         {
150             scope(exit) recording = false;
151             try
152             {
153                 renderer.stopRecording();
154                 writeln("done recording");
155             }
156             catch(Exception e)
157             {
158                 writeln("could not complete recording. Error message:\n    ",
159                     e.msg);
160             }
161         }
162         else
163         {
164             try
165             {
166                 renderer.startRecording("recording.mp4", 10);
167                 writeln("recording.. Press r to stop recording");
168                 recording = true;
169             }
170             catch(Exception e)
171             {
172                 writeln("could not start recording. Error message:\n    ",
173                     e.msg);
174 
175                 recording = false;
176             }
177         }
178     }
179 }