1 /// Event processor definitions
2 module des.app.evproc;
3 
4 import std.conv : to;
5 
6 import des.util.arch;
7 import derelict.sdl2.sdl;
8 
9 import des.util.logsys;
10 import des.util.stdext..string;
11 
12 public import des.app.event;
13 
14 /// 
15 interface SDLEventProcessor : DesBase
16 {
17     /++ process SDL event
18      + Returns:
19      + `true` if processed
20      + `false` otherwise
21      +/
22     bool procSDLEvent( in SDL_Event ev );
23 }
24 
25 ///
26 abstract class BaseSDLEventProcessor : SDLEventProcessor
27 {
28     mixin DES;
29     this() { prepareDES(); }
30 }
31 
32 ///
33 class MouseEventProcessor : BaseSDLEventProcessor
34 {
35     mixin DES;
36 protected:
37     MouseEvent main_event;
38 
39 public:
40     ///
41     Signal!( in_MouseEvent ) signal;
42 
43     ///
44     alias signal this;
45 
46     ///
47     MouseEvent lastState() const @property { return main_event; }
48 
49     bool procSDLEvent( in SDL_Event ev )
50     {
51         switch( ev.type )
52         {
53             case SDL_MOUSEMOTION:
54                 auto e = ev.motion;
55                 main_event.type = MouseEvent.Type.MOTION;
56                 main_event.btn = MouseEvent.Button.NONE;
57                 main_event.pos = ivec2( e.x, e.y );
58                 main_event.rel = ivec2( e.xrel, e.yrel );
59 
60                 foreach( i, btn; [EnumMembers!(MouseEvent.Button)][1..$] )
61                 {
62                     if( binHas( main_event.mask, btn ) )
63                         main_event.relPress[i] = main_event.pos - main_event.posPress[i];
64                     else
65                     {
66                         main_event.posPress[i] = main_event.pos;
67                         main_event.relPress[i] = ivec2(0,0);
68                     }
69                 }
70                 signal( main_event );
71                 return true;
72             case SDL_MOUSEBUTTONDOWN:
73             case SDL_MOUSEBUTTONUP:
74                 auto e = ev.button;
75                 main_event.btn = cast(MouseEvent.Button)SDL_BUTTON(e.button);
76                 if( e.state == SDL_PRESSED )
77                 {
78                     main_event.type = MouseEvent.Type.PRESSED;
79                     main_event.appendButton( SDL_BUTTON(e.button) );
80                     main_event.posPress[main_event.buttonIndex(main_event.btn)] = main_event.pos;
81                 }
82                 else
83                 {
84                     main_event.type = MouseEvent.Type.RELEASED;
85                     main_event.removeButton( SDL_BUTTON(e.button) );
86                 }
87                 signal( main_event );
88                 return true;
89             case SDL_MOUSEWHEEL:
90                 auto e = ev.wheel;
91                 main_event.type = MouseEvent.Type.WHEEL;
92                 main_event.btn = MouseEvent.Button.NONE;
93                 main_event.whe = ivec2( e.x, e.y );
94                 signal( main_event );
95                 return true;
96             default: return false;
97         }
98     }
99 }
100 
101 ///
102 class WindowEventProcessor : BaseSDLEventProcessor
103 {
104     mixin DES;
105     ///
106     Signal!() shown;
107     ///
108     Signal!() hidden;
109     ///
110     Signal!() exposed;
111     ///
112     Signal!(ivec2) moved;
113     ///
114     Signal!(ivec2) resized;
115     ///
116     Signal!() minimized;
117     ///
118     Signal!() maximized;
119     ///
120     Signal!() restored;
121     ///
122     Signal!() enter;
123     ///
124     Signal!() leave;
125     ///
126     Signal!() focusGained;
127     ///
128     Signal!() focusLost;
129     ///
130     Signal!() close;
131     
132     bool procSDLEvent( in SDL_Event ev )
133     {
134         if( ev.type != SDL_WINDOWEVENT ) return false;
135         auto wID = ev.window.windowID;
136         auto data = ivec2( ev.window.data1, ev.window.data2 );
137 
138         switch(ev.window.event)
139         {
140             case SDL_WINDOWEVENT_SHOWN:        shown();         break;
141             case SDL_WINDOWEVENT_HIDDEN:       hidden();        break;
142             case SDL_WINDOWEVENT_EXPOSED:      exposed();       break;
143             case SDL_WINDOWEVENT_MOVED:        moved( data );   break;
144             case SDL_WINDOWEVENT_RESIZED:      resized( data ); break;
145             case SDL_WINDOWEVENT_MINIMIZED:    minimized();     break;
146             case SDL_WINDOWEVENT_MAXIMIZED:    maximized();     break;
147             case SDL_WINDOWEVENT_RESTORED:     restored();      break;
148             case SDL_WINDOWEVENT_ENTER:        enter();         break;
149             case SDL_WINDOWEVENT_LEAVE:        leave();         break;
150             case SDL_WINDOWEVENT_FOCUS_GAINED: focusGained();   break;
151             case SDL_WINDOWEVENT_FOCUS_LOST:   focusLost();     break;
152             case SDL_WINDOWEVENT_CLOSE:        close();         break;
153             default: return false;
154         }
155         return true;
156     }
157 }
158 
159 ///
160 class KeyboardEventProcessor : BaseSDLEventProcessor
161 {
162     mixin DES;
163     ///
164     Signal!( in_KeyboardEvent ) signal;
165 
166     ///
167     alias signal this;
168 
169     bool procSDLEvent( in SDL_Event ev )
170     {
171         switch( ev.type )
172         {
173             case SDL_KEYUP:
174             case SDL_KEYDOWN:
175                 with( ev.key )
176                 {
177                     auto rep = cast(bool)repeat;
178                     auto pre = cast(bool)state;
179                     auto cod = cast(KeyboardEvent.Scan)keysym.scancode;
180                     auto sym = keysym.sym;
181                     auto mod = cast(KeyboardEvent.Mod)keysym.mod;
182                     signal( KeyboardEvent( pre, rep, cod, sym, mod ) );
183                 }
184                 return true;
185             default: return false;
186         }
187     }
188 }
189 
190 ///
191 class TextEventProcessor : BaseSDLEventProcessor
192 {
193     mixin DES;
194     ///
195     Signal!( dstring ) input;
196     ///
197     Signal!( dstring, int, int ) edit;
198 
199     bool procSDLEvent( in SDL_Event ev )
200     {
201         switch( ev.type )
202         {
203             case SDL_TEXTINPUT:
204                 with( ev.text )
205                     input( to!dstring( text.toDStringFix ) );
206                 return true;
207             case SDL_TEXTEDITING:
208                 with( ev.edit )
209                     edit( to!dstring( text.toDStringFix ), start, length );
210                 return true;
211             default: return false;
212         }
213     }
214 }