Tscope5
mouse.c
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////////////
2 //
3 // __ ______
4 // / /_______________ ____ ___ / ____/
5 // / __/ ___/ ___/ __ \/ __ \/ _ \ /___ )
6 // / /_(__ ) /__/ /_/ / /_/ / __/ ____/ /
7 // \__/____/\___/\____/ .___/\___/ /_____/
8 // /_/
9 //
10 /// \file mouse.c
11 /// Definitions of mouse functions
12 /// \example mouse01.c
13 /// \example mouse02.c
14 ////////////////////////////////////////////////////////////////////////////////
15 
16 
17 #include "../include/tscope5/mouse.h"
18 #include "../include/tscope5/timer.h"
19 #include "../include/tscope5/graphics.h"
20 #include "../include/tscope5/bitmaps.h"
21 #include "../include/tscope5/display.h"
22 #include "../include/tscope5/primitives.h"
23 #include "../include/tscope5/mouse_internal.h"
24 #include "../include/tscope5/system_internal.h"
25 #include "../include/tscope5/graphics_internal.h"
26 
27 
28 ////////////////////////////////////////////////////////////////////////////////
29 /// @name Response registration
30 /// The mouse can be used as a response device.
31 /// See timer.c for more information about response registration.
32 //@{
33 ////////////////////////////////////////////////////////////////////////////////
34 
35 
36 ////////////////////////////////////////////////////////////////////////////////
37 /// Define a mouse button as a response button.
38 ///
39 /// \param button Number of the button (buttons are counted from 1).
40 ///
41 /// \return The reponse number associated with the button.
42 ///
43 /// Give a positive number if you want to monitor button press events,
44 /// a negative number if you want to monitor button release events.
45 ////////////////////////////////////////////////////////////////////////////////
46 int ts5_define_mouse_button(int button)
47 {
48  ts5_check_mouse("ts5_define_mouse_button");
49  ts5_log(TS5_LOGLEVEL_3, "ts5_define_mouse_button(%d)\n", button);
50 
51  if (button==0) {
52  ts5_fatal("%s: %s\n", "ts5_define_mouse_button",
53  "button argument is 0, response buttons are numbered from 1");
54  }
55 
56  if (abs(button)>_ts5_status.timer.mouse.num_buttons) {
57  ts5_fatal("%s: %s %d, %s is %d\n", "ts5_define_mouse_button",
58  "button argument is", button,
59  "number of mouse buttons",
60  _ts5_status.timer.mouse.num_buttons);
61  }
62 
63  if (button>0 && _ts5_status.timer.mouse
64  .button_press_defined[button-1]!=0) {
65  ts5_fatal("%s: %s %d %s\n", "ts5_define_mouse_button",
66  "button press", button, "is already defined");
67  }
68 
69  if (button<0 && _ts5_status.timer.mouse
70  .button_release_defined[-button-1]!=0) {
71  ts5_fatal("%s: %s %d %s\n", "ts5_define_mouse_button",
72  "button release", button, "is already defined");
73  }
74 
75  _ts5_status.timer.mouse_is_response_device = 1;
76  _ts5_status.timer.num_defined_buttons++;
77  _ts5_status.timer.num_active_buttons++;
78  _ts5_status.timer.mouse.num_defined_buttons++;
79  _ts5_status.timer.mouse.num_active_buttons++;
80 
81  if (button>0) {
82  _ts5_status.timer.mouse.button_press_defined[button-1] =
83  _ts5_status.timer.num_defined_buttons;
84 
85  _ts5_status.timer.mouse.button_press_active[button-1] =
86  _ts5_status.timer.num_defined_buttons;
87  }
88  else {
89  _ts5_status.timer.mouse.button_release_defined[-button-1] =
90  _ts5_status.timer.num_defined_buttons;
91 
92  _ts5_status.timer.mouse.button_release_active[-button-1] =
93  _ts5_status.timer.num_defined_buttons;
94  }
95 
96  return _ts5_status.timer.num_defined_buttons;
97 }
98 
99 
100 ////////////////////////////////////////////////////////////////////////////////
101 /// Get then number of buttons available on the mouse.
102 ///
103 /// \return The number of buttons on the mouse.
104 ////////////////////////////////////////////////////////////////////////////////
106 {
107  ts5_check_mouse("ts5_get_num_mouse_buttons");
108  ts5_log(TS5_LOGLEVEL_4, "ts5_get_num_mouse_buttons()\n");
109 
110  return _ts5_status.timer.mouse.num_buttons;
111 }
112 
113 
114 ////////////////////////////////////////////////////////////////////////////////
115 //@}
116 ////////////////////////////////////////////////////////////////////////////////
117 
118 
119 ////////////////////////////////////////////////////////////////////////////////
120 /// @name Mouse GUI functions
121 //@{
122 ////////////////////////////////////////////////////////////////////////////////
123 
124 
125 ////////////////////////////////////////////////////////////////////////////////
126 /// Make the mouse cursor visible on the active display.
127 ////////////////////////////////////////////////////////////////////////////////
129 {
130  ts5_check_mouse("ts5_show_mouse");
131  ts5_log(TS5_LOGLEVEL_5, "ts5_show_mouse()\n");
132 
133  al_show_mouse_cursor(_ts5_data.display[_ts5_status.active_display]);
134 }
135 
136 
137 ////////////////////////////////////////////////////////////////////////////////
138 /// Make the mouse cursor invisible on the active display.
139 ////////////////////////////////////////////////////////////////////////////////
141 {
142  ts5_check_mouse("ts5_hide_mouse");
143  ts5_log(TS5_LOGLEVEL_5, "ts5_hide_mouse()\n");
144 
145  al_hide_mouse_cursor(_ts5_data.display[_ts5_status.active_display]);
146 }
147 
148 
149 ////////////////////////////////////////////////////////////////////////////////
150 /// Move the mouse pointer to position (x,y).
151 ///
152 /// \param x Horizontal position of the mouse on the active display.
153 /// \param y Vertical position of the mouse on the active display.
154 ////////////////////////////////////////////////////////////////////////////////
155 void ts5_set_mouse_position(double x, double y)
156 {
157  ts5_check_mouse("ts5_set_mouse_position");
158  ts5_log(TS5_LOGLEVEL_5, "ts5_set_mouse_position(%f,%f)\n", x, y);
159 
160  if (_ts5_status.graphics.coordinate_scale
161  == TS5_RELATIVE_COORDINATES) {
164  }
165 
166  if (_ts5_status.graphics.coordinate_system
167  == TS5_CARTESIAN_COORDINATES) {
170  }
171 
172  al_set_mouse_xy(_ts5_data.display[_ts5_status.active_display],
173  (int)x, (int)y);
174 }
175 
176 ////////////////////////////////////////////////////////////////////////////////
177 /// Get the horizontal and vertical position of the mouse pointer
178 ///
179 /// \param x Variable that will store the horizontal position.
180 /// \param y Variable that will store the vertical position.
181 ///
182 /// You can pass NULL for values you are not interested in.
183 ////////////////////////////////////////////////////////////////////////////////
184 void ts5_get_mouse_position(double *x, double *y)
185 {
186  ts5_check_mouse("ts5_get_mouse_position");
187  ts5_log(TS5_LOGLEVEL_6, "ts5_get_mouse_position(%p,%p)\n", x, y);
188 
189  ALLEGRO_MOUSE_STATE status;
190  al_get_mouse_state(&status);
191 
192  double xx, yy;
193 
194  xx = al_get_mouse_state_axis(&status, 0);
195  yy = al_get_mouse_state_axis(&status, 1);
196 
197  if (_ts5_status.graphics.coordinate_system
198  == TS5_CARTESIAN_COORDINATES) {
201  }
202 
203  if (_ts5_status.graphics.coordinate_scale
204  == TS5_RELATIVE_COORDINATES) {
207  }
208 
209  if (x) {
210  *x = xx;
211  }
212 
213  if (y) {
214  *y = yy;
215  }
216 }
217 
218 
219 ////////////////////////////////////////////////////////////////////////////////
220 /// Get the horizontal position of the mouse pointer
221 ///
222 /// \return The horizontal position of the mouse pointer.
223 ////////////////////////////////////////////////////////////////////////////////
225 {
226  ts5_check_mouse("ts5_get_mouse_x");
227  ts5_log(TS5_LOGLEVEL_6, "ts5_get_mouse_x()\n");
228 
229  double x;
230  ts5_get_mouse_position(&x, NULL);
231 
232  return x;
233 }
234 
235 
236 ////////////////////////////////////////////////////////////////////////////////
237 /// Get the vertical position of the mouse pointer
238 ///
239 /// \return The vertical position of the mouse pointer.
240 ////////////////////////////////////////////////////////////////////////////////
242 {
243  ts5_check_mouse("ts5_get_mouse_y");
244  ts5_log(TS5_LOGLEVEL_6, "ts5_get_mouse_y()\n");
245 
246  double y;
247  ts5_get_mouse_position(NULL, &y);
248 
249  return y;
250 }
251 
252 
253 ////////////////////////////////////////////////////////////////////////////////
254 /// Draw a mouse button and wait for a click.
255 ///
256 /// \param x Horizontal position of the button on the active display.
257 /// \param y Vertical position of the button on the active display.
258 ///
259 /// The button has an ugly green color. This color can not be changed.
260 /// This is not a bug. It is a Deliberately Annoying Feature (DAF).
261 ////////////////////////////////////////////////////////////////////////////////
262 void ts5_draw_mouse_button(double x, double y)
263 {
264  ts5_check_mouse("ts5_draw_mouse_button");
265  ts5_log(TS5_LOGLEVEL_5, "ts5_draw_mouse_button(%f,%f)\n", x, y);
266 
267  // always write to the display
268  ts5_set_active_display(_ts5_status.active_display+1);
269 
270  TS5_BITMAP *oldmap = ts5_set_drawing_target(
271  _ts5_data.display_buffer
272  [_ts5_status.active_display]);
273 
274  TS5_COLOR oldcolor = ts5_set_foreground_color(
275  ts5_make_named_color("chartreuse", 1.0));
276 
277  double oldthick = ts5_set_drawing_thickness(4.0);
278  int oldfill = ts5_set_fill_mode(TS5_FILL_OFF);
279 
280  double w_abs_disp = 40, h_abs_disp = 40;
281  double x1_abs_disp, x2_abs_disp, y1_abs_disp, y2_abs_disp;
282 
283  // covert to absolute scale
284  if (_ts5_status.graphics.coordinate_scale
285  == TS5_RELATIVE_COORDINATES) {
286  x1_abs_disp = ts5_relative_to_absolute_coordinate_x(x);
287  y1_abs_disp = ts5_relative_to_absolute_coordinate_y(y);
288  }
289  else {
290  x1_abs_disp = x;
291  y1_abs_disp = y;
292  }
293 
294  // convert to display coordinates.
295  // for cartesian display coordinates x and y are the center
296  // for display coordinates x and y are
297  if (_ts5_status.graphics.coordinate_system
298  == TS5_CARTESIAN_COORDINATES) {
299  x1_abs_disp = ts5_cartesian_to_display_coordinate_x(x1_abs_disp);
300  y1_abs_disp = ts5_cartesian_to_display_coordinate_y(y1_abs_disp);
301 
302  x1_abs_disp -= w_abs_disp/2;
303  y1_abs_disp -= h_abs_disp/2;
304  }
305 
306  x2_abs_disp = x1_abs_disp + w_abs_disp;
307  y2_abs_disp = y1_abs_disp + h_abs_disp;
308 
309  int oldsystem = ts5_set_coordinate_system(TS5_DISPLAY_COORDINATES);
310  int oldscale = ts5_set_coordinate_scale(TS5_ABSOLUTE_COORDINATES);
311 
312  // check if the button will be on the screen
313  double dispw = _ts5_status.display[_ts5_status.active_display].w;
314  double disph = _ts5_status.display[_ts5_status.active_display].h;
315 
316  if (x1_abs_disp < 0.0 || x2_abs_disp > dispw
317  || y1_abs_disp < 0.0 || y2_abs_disp > disph) {
318  ts5_fatal("%s: %s (%f,%f)\n", "ts5_draw_mouse_button",
319  "button will be off screen", x1_abs_disp, y1_abs_disp);
320  }
321 
322  ts5_draw_rounded_rectangle(x1_abs_disp, y1_abs_disp,
323  x2_abs_disp, y2_abs_disp, 3.0, 3.0);
324 
325  ts5_set_fill_mode(TS5_FILL_ON);
326  ts5_draw_triangle(x2_abs_disp - 5.0, (y1_abs_disp+y2_abs_disp)/2.0,
327  x1_abs_disp+5.0, y1_abs_disp+5.0, x1_abs_disp+5.0, y2_abs_disp-5.0);
329  ts5_show_mouse();
330 
331  ALLEGRO_MOUSE_STATE status;
332  int down;
333  int ok = 0;
334  do {
335  al_rest(0.01);
336  double xp, yp;
337  ts5_get_mouse_position(&xp, &yp);
338  al_get_mouse_state(&status);
339  down = al_mouse_button_down(&status, 1);
340  if (down && xp > x1_abs_disp && xp < x2_abs_disp
341  && yp > y1_abs_disp && yp < y2_abs_disp) {
342  ok = 1;
343  }
344  } while (!ok);
345 
347  ts5_draw_triangle(x2_abs_disp - 5, (y1_abs_disp+y2_abs_disp)/2,
348  x1_abs_disp+5, y1_abs_disp+5, x1_abs_disp+5, y2_abs_disp-5);
350 
351  ok = 0;
352  do {
353  al_rest(0.01);
354  al_get_mouse_state(&status);
355  down = al_mouse_button_down(&status, 1);
356  if (!down) {
357  ok = 1;
358  }
359  } while (!ok);
360 
362  ts5_draw_triangle(x2_abs_disp - 5, (y1_abs_disp+y2_abs_disp)/2,
363  x1_abs_disp+5, y1_abs_disp+5, x1_abs_disp+5, y2_abs_disp-5);
365 
366  ts5_set_drawing_target(oldmap);
367  ts5_set_foreground_color(oldcolor);
368  ts5_set_drawing_thickness(oldthick);
369  ts5_set_fill_mode(oldfill);
370  ts5_set_coordinate_system(oldsystem);
371  ts5_set_coordinate_scale(oldscale);
372 }
373 
374 
375 ////////////////////////////////////////////////////////////////////////////////
376 //@}
377 ////////////////////////////////////////////////////////////////////////////////
378