1 module armos.app.baseapp;
2 import armos.app.application;
3 import armos.events;
4 import armos.math;
5 import armos.utils.keytype;
6 
7 /++
8 armosの中心となるクラスです.プロジェクトを作成する際はこのクラスを継承して処理を記述していきます.
9 +/
10 class BaseApp: Application{
11     /++
12         事前処理を記述するメンバ関数です.initializerによる初期化が行われた後,一度だけ実行されます.
13     +/
14     void setup(ref SetupEvent arg){
15         this.initHeldKeys;
16         setup();
17     }
18 
19     /++
20         毎フレーム実行されるメンバ関数です.
21     +/
22     void update(ref UpdateEvent arg){
23         update();
24     }
25 
26     /++
27         毎フレーム実行されるメンバ関数です.updateの次に呼ばれます.描画処理を記述します.
28     +/
29     void draw(ref DrawEvent arg){
30         draw();
31         this.updateKeys;
32     }
33 
34     /++
35         事前処理を記述するメンバ関数です.initializerによる初期化が行われた後,一度だけ実行されます.
36     +/
37     void setup(){};
38 
39     /++
40         毎フレーム実行されるメンバ関数です.
41     +/
42     void update(){};
43 
44     /++
45         毎フレーム実行されるメンバ関数です.updateの次に呼ばれます.描画処理を記述します.
46     +/
47     void draw(){};
48 
49 
50     /++
51         終了時に一度だけ呼ばれるメンバ関数です.
52     +/
53     void exit(ref ExitEvent arg){
54         exit();
55     };
56 
57     /++
58         終了時に一度だけ呼ばれるメンバ関数です.
59     +/
60     void exit(){};
61     
62     ///
63     void windowResized(ref WindowResizeEvent message){
64         windowResized(message.w, message.h);
65         windowResized(Vector2i(message.w, message.h));
66         windowResized;
67     }
68     
69     ///
70     void windowResized(){}
71     
72     ///
73     void windowResized(int w, int h){}
74     
75     ///
76     void windowResized(Vector2i size){}
77 
78     /++
79         キーボードを押した際に呼ばれるメンバ関数です.
80         Params:
81         message = キーボードの状態が格納されたメッセージです.
82     +/
83     void keyPressed(ref KeyPressedEvent message){
84         import std.conv;
85         keyPressed(message.key);
86         this.PressKey(message.key);
87     }
88     
89     /++
90         キーボードを押した際に呼ばれるメンバ関数です.
91         Params:
92         key = 押したキーの種類を表すarmos.utils.KeyTypeが格納されています.
93     +/
94     void keyPressed(KeyType key){}
95 
96     /++
97         キーボードを離した際に呼ばれるメンバ関数です.
98         Params:
99         message = キーボードの状態が格納されたメッセージです.
100     +/
101     void keyReleased(ref KeyReleasedEvent message){
102         import std.conv;
103         keyReleased(message.key);
104         this.ReleaseKey(message.key);
105     }
106     
107     /++
108         キーボードを離した際に呼ばれるメンバ関数です.
109         Params: 
110         key = 離したキーの種類を表すarmos.utils.KeyTypeが格納されています.
111     +/
112     void keyReleased(KeyType key){}
113     
114     ///
115     void unicodeInputted(ref UnicodeInputtedEvent message){
116         unicodeInputted(message.key);
117     }
118     
119     ///
120     void unicodeInputted(uint key){}
121 
122     /++
123         マウス位置を表すプロパティです.
124     +/
125     int mouseX, mouseY;
126 
127     /++
128         マウスが動いた際に呼ばれるメンバ関数です.
129         Params:
130         message = マウスの状態が格納されたメッセージです.
131     +/
132     void mouseMoved(ref MouseMovedEvent message){
133         mouseMoved(message.x, message.y, message.button );
134         mouseMoved(Vector2f(message.x, message.y), message.button);
135         mouseMoved(Vector2i(message.x, message.y), message.button);
136         mouseX = message.x;
137         mouseY = message.y;
138     }
139 
140     /++
141         マウスが動いた際に呼ばれるメンバ関数です.
142         Params:
143         x = マウスのX座標です.
144         y = マウスのY座標です.
145     +/
146     void mouseMoved(int x, int y, int button){}
147 
148     /++
149         マウスが動いた際に呼ばれるメンバ関数です.
150         Params:
151         position = マウスの座標を表します.
152     +/
153     void mouseMoved(Vector2f position, int button){}
154 
155     /++
156         マウスが動いた際に呼ばれるメンバ関数です.
157         Params:
158         position = マウスの座標を表します.
159     +/
160     void mouseMoved(Vector2i position, int button){}
161 
162     /++
163         マウスがドラッグされた際に呼ばれるメンバ関数です.
164     +/
165     void mouseDragged(ref MouseDraggedEvent message){
166         mouseDragged(message.x, message.y, message.button );
167         mouseDragged(message.firstX, message.firstY, message.x, message.y, message.button );
168         mouseDragged(Vector2f(message.x, message.y), message.button);
169         mouseDragged(Vector2f(message.firstX, message.firstY), Vector2f(message.x, message.y), message.button);
170         mouseDragged(Vector2i(message.x, message.y), message.button);
171         mouseDragged(Vector2i(message.firstX, message.firstY), Vector2i(message.x, message.y), message.button);
172     }
173 
174     /++
175         マウスがドラッグされた際に呼ばれるメンバ関数です.
176     +/
177     void mouseDragged(int currentX, int currentY, int button){}
178     void mouseDragged(int firstX, int firstY, int currentX, int currentY, int button){}
179 
180     /++
181         マウスがドラッグされた際に呼ばれるメンバ関数です.
182     +/
183     void mouseDragged(Vector2f currentPosition, int button){}
184     void mouseDragged(Vector2f firstPosition, Vector2f currentPosition, int button){}
185 
186     /++
187         マウスがドラッグされた際に呼ばれるメンバ関数です.
188     +/
189     void mouseDragged(Vector2i currentPosition, int button){}
190     void mouseDragged(Vector2i firstPosition, Vector2i currentPosition, int button){}
191 
192 
193     /++
194         マウスのボタンが離れた際に呼ばれるメンバ関数です.
195         Params:
196         message = マウスの状態が格納されたメッセージです.
197     +/
198     void mouseReleased(ref MouseReleasedEvent message){
199         mouseReleased(message.x, message.y, message.button );
200         mouseReleased(Vector2f(message.x, message.y), message.button);
201         mouseReleased(Vector2i(message.x, message.y), message.button);
202     }
203 
204     /++
205         マウスのボタンが離れた際に呼ばれるメンバ関数です.
206         Params:
207         x = マウスのX座標を表します.
208         y = マウスのY座標を表します.
209         button = 離れたマウスのボタンを表します.
210     +/
211     void mouseReleased(int x, int y, int button){}
212 
213     /++
214         マウスのボタンが離れた際に呼ばれるメンバ関数です.
215         Params:
216         position = マウスの座標を表します.
217         button = 離れたマウスのボタンを表します.
218     +/
219     void mouseReleased(Vector2f position, int button){}
220 
221     /++
222         マウスのボタンが離れた際に呼ばれるメンバ関数です.
223         Params:
224         position = マウスの座標を表します.
225         button = 離れたマウスのボタンを表します.
226     +/
227     void mouseReleased(Vector2i position, int button){}
228 
229     /++
230         マウスのボタンが押された際に呼ばれるメンバ関数です.
231         Params:
232         message = マウスの状態が格納されたメッセージです.
233     +/
234     void mousePressed(ref MousePressedEvent message){
235         mousePressed(message.x, message.y, message.button );
236         mousePressed(Vector2f(message.x, message.y), message.button);
237         mousePressed(Vector2i(message.x, message.y), message.button);
238     }
239 
240     /++
241         マウスのボタンが押された際に呼ばれるメンバ関数です.
242         Params:
243         x = マウスのX座標を表します.
244         y = マウスのY座標を表します.
245         button = 押されたマウスのボタンを表します.
246     +/
247     void mousePressed(int x, int y, int button){}
248 
249     /++
250         マウスのボタンが押された際に呼ばれるメンバ関数です.
251         Params:
252         position = マウスの座標を表します.
253         button = 押されたマウスのボタンを表します.
254     +/
255     void mousePressed(Vector2f position, int button){}
256 
257     /++
258         マウスのボタンが押された際に呼ばれるメンバ関数です.
259         Params:
260         position = マウスの座標を表します.
261         button = 押されたマウスのボタンを表します.
262     +/
263     void mousePressed(Vector2i position, int button){}
264 
265     ///
266     void mouseScrolled(ref MouseScrolledEvent message){
267         mouseScrolled(message.xOffset, message.yOffset);
268         mouseScrolled(Vector2f(message.xOffset, message.yOffset));
269         import std.conv:to;
270         mouseScrolled(Vector2i(message.xOffset.to!int, message.yOffset.to!int));
271     }
272 
273     ///
274     // void mouseScrolled(int xOffset, int yOffset){}
275 
276     ///
277     void mouseScrolled(float xOffset, float yOffset){}
278 
279     ///
280     void mouseScrolled(Vector2i position){}
281 
282     ///
283     void mouseScrolled(Vector2f position){}
284     
285     ///
286     bool hasPressedKey(in KeyType key)const{
287         return !_hasHeldKeysPrevious[key] && _hasHeldKeysCurrent[key];
288     }
289     
290     ///
291     bool hasHeldKey(in KeyType key)const{
292         return _hasHeldKeysCurrent[key];
293     }
294     
295     ///
296     bool hasReleasedKey(in KeyType key)const{
297         return _hasHeldKeysPrevious[key] && !_hasHeldKeysCurrent[key];
298     }
299 
300     final void exitApp(){
301         _shouldClose = true;
302     }
303 
304     final bool shouldClose(){
305         return _shouldClose;
306     }
307 
308     
309     private{
310         bool[KeyType] _hasHeldKeysCurrent;
311         bool[KeyType] _hasHeldKeysPrevious;
312         bool _shouldClose = false;
313     }
314 }
315 
316 void initHeldKeys(BaseApp app){
317     import std.traits:EnumMembers;
318     foreach (elem; [EnumMembers!KeyType]) {
319         app._hasHeldKeysCurrent[elem]  = false;
320         app._hasHeldKeysPrevious[elem] = false;
321     }
322 }
323 
324 package void PressKey(BaseApp app, KeyType keyType){
325     app._hasHeldKeysCurrent[keyType] = true;
326 }
327 
328 package void ReleaseKey(BaseApp app, KeyType keyType){
329     app._hasHeldKeysCurrent[keyType] = false;
330 }
331 
332 package BaseApp updateKeys(BaseApp app){
333     import std.traits:EnumMembers;
334     foreach (elem; [EnumMembers!KeyType]) {
335         app._hasHeldKeysPrevious[elem] = app._hasHeldKeysCurrent[elem];
336     }
337     return app;
338 }
339 
340 unittest{
341     auto app = new BaseApp;
342     app.initHeldKeys;
343     
344     assert(!app.hasHeldKey(KeyType.A));
345     assert(!app.hasPressedKey(KeyType.A));
346     assert(!app.hasReleasedKey(KeyType.A));
347     
348     app.updateKeys
349        .PressKey(KeyType.A);
350     
351     assert(app.hasHeldKey(KeyType.A));
352     assert(app.hasPressedKey(KeyType.A));
353     assert(!app.hasReleasedKey(KeyType.A));
354     
355     app.updateKeys;
356     
357     assert(app.hasHeldKey(KeyType.A));
358     assert(!app.hasPressedKey(KeyType.A));
359     assert(!app.hasReleasedKey(KeyType.A));
360     
361     app.updateKeys
362        .ReleaseKey(KeyType.A);
363     
364     assert(!app.hasHeldKey(KeyType.A));
365     assert(!app.hasPressedKey(KeyType.A));
366     assert(app.hasReleasedKey(KeyType.A));
367 }