fixing onscreen button position
[drnoksnes] / platform / sdli.cpp
1 #include <SDL.h>
2 #include <math.h>
3
4 #include "platform.h"
5 #include "snes9x.h"
6 #include "display.h"
7
8 struct TouchButton {
9         unsigned short mask;
10         unsigned short x, y;
11         unsigned short x2, y2;
12         float fx, fy;
13         float fw, fh;
14 };
15
16 #define TOUCH_BUTTON_INITIALIZER(name, x, y, w, h) \
17         {SNES_##name##_MASK, 0, 0, 0, 0, x, y, w, h}
18
19 static TouchButton touchbuttons[] = {
20         TOUCH_BUTTON_INITIALIZER(TL, 0, 0, 0.375, 0.0833),
21         TOUCH_BUTTON_INITIALIZER(TR, 0.625, 0, 0.375, 0.0833),
22         TOUCH_BUTTON_INITIALIZER(UP, 0.125, 0.0833, 0.125, 0.2777), //2
23         TOUCH_BUTTON_INITIALIZER(LEFT, 0.0, 0.3611, 0.125, 0.2777), //3
24         TOUCH_BUTTON_INITIALIZER(RIGHT, 0.25, 0.3611, 0.125, 0.2777), //4
25         TOUCH_BUTTON_INITIALIZER(DOWN, 0.125, 0.6388, 0.125, 0.2777), //5
26         TOUCH_BUTTON_INITIALIZER(START, 0, 0.9166, 0.375, 0.0833),
27         TOUCH_BUTTON_INITIALIZER(Y, 0.75, 0.0833, 0.125, 0.2777),
28         TOUCH_BUTTON_INITIALIZER(X, 0.625, 0.3611, 0.125, 0.2777),
29         TOUCH_BUTTON_INITIALIZER(A, 0.875, 0.3611, 0.125, 0.2777),
30         TOUCH_BUTTON_INITIALIZER(B, 0.75, 0.6388, 0.125, 0.2777),
31         TOUCH_BUTTON_INITIALIZER(SELECT, 0.625, 0.9166, 0.375, 0.0833),
32 };
33
34 static TouchButton* current = 0;
35
36 static uint32 joypads[2];
37 static struct {
38         unsigned x;
39         unsigned y;
40         bool enabled, pressed;
41 } mouse;
42
43 static TouchButton* getButtonFor(unsigned int x, unsigned int y) {
44         unsigned int i;
45
46         for (i = 0; i < sizeof(touchbuttons)/sizeof(TouchButton); i++) {
47                 if (x > touchbuttons[i].x && x < touchbuttons[i].x2 &&
48                         y > touchbuttons[i].y && y < touchbuttons[i].y2) {
49
50                         return &touchbuttons[i];
51                 }
52         }
53
54         return 0;
55 }
56
57 static inline void unpress(TouchButton* b) {
58         joypads[0] &= ~b->mask;
59 }
60 static inline void press(TouchButton* b) {
61         joypads[0] |= b->mask;
62 }
63
64 static void processMouse(unsigned int x, unsigned int y, int pressed = 0)
65 {
66         if (Config.touchscreenInput) {
67                 if (pressed < 0) {
68                         // Button up.
69                         if (current) {
70                                 // Leaving button
71                                 unpress(current);
72                                 current = 0;
73                         }
74                 } else {
75                         // Button down, or mouse motion.
76                         TouchButton* b = getButtonFor(x, y);
77                         if (current && b && current != b) {
78                                 // Moving from button to button
79                                 unpress(current);
80                                 current = b;
81                                 press(current);
82                         } else if (current && !b) {
83                                 // Leaving button
84                                 unpress(current);
85                                 current = 0;
86                         } else if (!current && b) {
87                                 // Entering button
88                                 current = b;
89                                 press(current);
90                         }
91                 }
92         } else if (mouse.enabled) {
93                 // TODO Review this
94                 mouse.x = x;
95                 mouse.y = y;
96                 if (Config.xsp) {
97                         mouse.x /= 2;
98                         mouse.y /= 2;
99                 }
100                 if (pressed > 0)
101                         mouse.pressed = true;
102                 else if (pressed < 0)
103                         mouse.pressed = false;
104         }
105 }
106
107 static void processEvent(const SDL_Event& event)
108 {
109         switch (event.type) 
110         {
111         case SDL_KEYDOWN:
112                 if (Config.action[event.key.keysym.scancode]) 
113                         S9xDoAction(Config.action[event.key.keysym.scancode]);
114                 joypads[0] |= Config.joypad1Mapping[event.key.keysym.scancode];
115                 break;
116         case SDL_KEYUP:
117                 joypads[0] &= ~Config.joypad1Mapping[event.key.keysym.scancode];
118                 break;
119         case SDL_MOUSEBUTTONUP:
120         case SDL_MOUSEBUTTONDOWN:
121                 processMouse(event.button.x, event.button.y,
122                                 (event.button.state == SDL_PRESSED) ? 1 : - 1);
123                 break;
124         case SDL_MOUSEMOTION:
125                 processMouse(event.motion.x, event.motion.y);
126                 break;
127         case SDL_QUIT:
128                 Config.quitting = true;
129                 break;
130         }
131 }
132
133 uint32 S9xReadJoypad (int which)
134 {
135         if (which < 0 || which > 2) {
136                 return 0;
137         }
138
139         return joypads[which];
140 }
141
142 bool8 S9xReadMousePosition(int which1, int& x, int& y, uint32& buttons)
143 {
144         if (which1 != 0) return FALSE;
145
146         x = mouse.x;
147         y = mouse.y;
148         buttons = mouse.pressed ? 1 : 0;
149
150         return TRUE;
151 }
152
153 bool8 S9xReadSuperScopePosition(int& x, int& y, uint32& buttons)
154 {
155         x = mouse.x;
156         y = mouse.y;
157         buttons = mouse.pressed ? 8 : 0;
158
159         return TRUE;
160 }
161
162 void S9xProcessEvents(bool8_32 block)
163 {
164         SDL_Event event;
165
166         if (block) {
167                 SDL_WaitEvent(&event);
168                 processEvent(event);
169         } else {
170                 while(SDL_PollEvent(&event)) 
171                 {      
172                         processEvent(event);
173                 }
174         }
175 }
176
177 void S9xInitInputDevices()
178 {
179         joypads[0] = 0;
180         joypads[1] = 0;
181
182         switch (Settings.ControllerOption) {
183                 case SNES_JOYPAD:
184                         joypads[0] = 0x80000000UL;
185                         printf("Input: 1 joypad, keyboard only\n");
186                         break;
187                 case SNES_MOUSE:
188                         joypads[0] = 0x80000000UL;
189                         mouse.enabled = true;
190                         printf("Input: 1 joypad + mouse\n");
191                         break;
192                 case SNES_MOUSE_SWAPPED:
193                         printf("Input: mouse\n");
194                         mouse.enabled = true;
195                         break;
196                 case SNES_SUPERSCOPE:
197                         joypads[0] = 0x80000000UL;
198                         mouse.enabled = true;
199                         printf("Input: 1 joypad + superscope\n");
200                         break;
201                 default:
202                         printf("Input: unknown\n");
203                         break;
204         }
205
206         S9xInputScreenChanged();
207 }
208
209 void S9xDeinitInputDevices()
210 {
211
212 }
213
214 void S9xInputScreenChanged()
215 {
216         unsigned int i = 0, w = 0, h = 0;
217         S9xVideoGetWindowSize(&w, &h);
218         for (i = 0; i < sizeof(touchbuttons)/sizeof(TouchButton); i++) {
219                 touchbuttons[i].x = (unsigned)round(touchbuttons[i].fx * w);
220                 touchbuttons[i].y = (unsigned)round(touchbuttons[i].fy * h);
221                 touchbuttons[i].x2 = (unsigned)round(touchbuttons[i].x + touchbuttons[i].fw * w);
222                 touchbuttons[i].y2 = (unsigned)round(touchbuttons[i].y + touchbuttons[i].fh * h);
223         }
224 }
225