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 EventArg arg){
15         this.initHeldKeys;
16         setup();
17     }
18 
19     /++
20         毎フレーム実行されるメンバ関数です.
21     +/
22     void update(ref EventArg arg){
23         update();
24     }
25 
26     /++
27         毎フレーム実行されるメンバ関数です.updateの次に呼ばれます.描画処理を記述します.
28     +/
29     void draw(ref EventArg 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 EventArg arg){
54         exit();
55     };
56 
57     /++
58         終了時に一度だけ呼ばれるメンバ関数です.
59     +/
60     void exit(){};
61     
62     ///
63     void windowResized(ref WindowResizeEventArg 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 KeyPressedEventArg 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 KeyReleasedEventArg 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 UnicodeInputtedEventArg 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 MouseMovedEventArg 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         Deprecated: 現在動作しません.
165     +/
166     void mouseDragged(ref MouseDraggedEventArg message){
167         mouseDragged(message.x, message.y, message.button );
168         mouseDragged(Vector2f(message.x, message.y), message.button);
169         mouseDragged(Vector2i(message.x, message.y), message.button);
170     }
171 
172     /++
173         マウスがドラッグされた際に呼ばれるメンバ関数です.
174         Deprecated: 現在動作しません.
175     +/
176     void mouseDragged(int x, int y, int button){}
177 
178     /++
179         マウスがドラッグされた際に呼ばれるメンバ関数です.
180         Deprecated: 現在動作しません.
181     +/
182     void mouseDragged(Vector2f position, int button){}
183 
184     /++
185         マウスがドラッグされた際に呼ばれるメンバ関数です.
186         Deprecated: 現在動作しません.
187     +/
188     void mouseDragged(Vector2i position, int button){}
189 
190 
191     /++
192         マウスのボタンが離れた際に呼ばれるメンバ関数です.
193         Params:
194         message = マウスの状態が格納されたメッセージです.
195     +/
196     void mouseReleased(ref MouseReleasedEventArg message){
197         mouseReleased(message.x, message.y, message.button );
198         mouseReleased(Vector2f(message.x, message.y), message.button);
199         mouseReleased(Vector2i(message.x, message.y), message.button);
200     }
201 
202     /++
203         マウスのボタンが離れた際に呼ばれるメンバ関数です.
204         Params:
205         x = マウスのX座標を表します.
206         y = マウスのY座標を表します.
207         button = 離れたマウスのボタンを表します.
208     +/
209     void mouseReleased(int x, int y, int button){}
210 
211     /++
212         マウスのボタンが離れた際に呼ばれるメンバ関数です.
213         Params:
214         position = マウスの座標を表します.
215         button = 離れたマウスのボタンを表します.
216     +/
217     void mouseReleased(Vector2f position, int button){}
218 
219     /++
220         マウスのボタンが離れた際に呼ばれるメンバ関数です.
221         Params:
222         position = マウスの座標を表します.
223         button = 離れたマウスのボタンを表します.
224     +/
225     void mouseReleased(Vector2i position, int button){}
226 
227     /++
228         マウスのボタンが押された際に呼ばれるメンバ関数です.
229         Params:
230         message = マウスの状態が格納されたメッセージです.
231     +/
232     void mousePressed(ref MousePressedEventArg message){
233         mousePressed(message.x, message.y, message.button );
234         mousePressed(Vector2f(message.x, message.y), message.button);
235         mousePressed(Vector2i(message.x, message.y), message.button);
236     }
237 
238     /++
239         マウスのボタンが押された際に呼ばれるメンバ関数です.
240         Params:
241         x = マウスのX座標を表します.
242         y = マウスのY座標を表します.
243         button = 押されたマウスのボタンを表します.
244     +/
245     void mousePressed(int x, int y, int button){}
246 
247     /++
248         マウスのボタンが押された際に呼ばれるメンバ関数です.
249         Params:
250         position = マウスの座標を表します.
251         button = 押されたマウスのボタンを表します.
252     +/
253     void mousePressed(Vector2f position, int button){}
254 
255     /++
256         マウスのボタンが押された際に呼ばれるメンバ関数です.
257         Params:
258         position = マウスの座標を表します.
259         button = 押されたマウスのボタンを表します.
260     +/
261     void mousePressed(Vector2i position, int button){}
262     
263     ///
264     bool hasPressedKey(in KeyType key)const{
265         return !_hasHeldKeysPrevious[key] && _hasHeldKeysCurrent[key];
266     }
267     
268     ///
269     bool hasHeldKey(in KeyType key)const{
270         return _hasHeldKeysCurrent[key];
271     }
272     
273     ///
274     bool hasReleasedKey(in KeyType key)const{
275         return _hasHeldKeysPrevious[key] && !_hasHeldKeysCurrent[key];
276     }
277 
278     final void exitApp(){
279         _shouldClose = true;
280     }
281 
282     final bool shouldClose(){
283         return _shouldClose;
284     }
285 
286     
287     private{
288         bool[KeyType] _hasHeldKeysCurrent;
289         bool[KeyType] _hasHeldKeysPrevious;
290         bool _shouldClose = false;
291     }
292 }
293 
294 void initHeldKeys(BaseApp app){
295     import std.traits:EnumMembers;
296     foreach (elem; [EnumMembers!KeyType]) {
297         app._hasHeldKeysCurrent[elem]  = false;
298         app._hasHeldKeysPrevious[elem] = false;
299     }
300 }
301 
302 package void PressKey(BaseApp app, KeyType keyType){
303     app._hasHeldKeysCurrent[keyType] = true;
304 }
305 
306 package void ReleaseKey(BaseApp app, KeyType keyType){
307     app._hasHeldKeysCurrent[keyType] = false;
308 }
309 
310 package BaseApp updateKeys(BaseApp app){
311     import std.traits:EnumMembers;
312     foreach (elem; [EnumMembers!KeyType]) {
313         app._hasHeldKeysPrevious[elem] = app._hasHeldKeysCurrent[elem];
314     }
315     return app;
316 }
317 
318 unittest{
319     auto app = new BaseApp;
320     app.initHeldKeys;
321     
322     assert(!app.hasHeldKey(KeyType.A));
323     assert(!app.hasPressedKey(KeyType.A));
324     assert(!app.hasReleasedKey(KeyType.A));
325     
326     app.updateKeys
327        .PressKey(KeyType.A);
328     
329     assert(app.hasHeldKey(KeyType.A));
330     assert(app.hasPressedKey(KeyType.A));
331     assert(!app.hasReleasedKey(KeyType.A));
332     
333     app.updateKeys;
334     
335     assert(app.hasHeldKey(KeyType.A));
336     assert(!app.hasPressedKey(KeyType.A));
337     assert(!app.hasReleasedKey(KeyType.A));
338     
339     app.updateKeys
340        .ReleaseKey(KeyType.A);
341     
342     assert(!app.hasHeldKey(KeyType.A));
343     assert(!app.hasPressedKey(KeyType.A));
344     assert(app.hasReleasedKey(KeyType.A));
345 }