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 the 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  #ifndef TS5_RASPBERRYPI
134  al_show_mouse_cursor(_ts5_data.display[_ts5_status.active_display]);
135 
136  #endif
137 }
138 
139 
140 ////////////////////////////////////////////////////////////////////////////////
141 /// Make the mouse cursor invisible on the active display.
142 ////////////////////////////////////////////////////////////////////////////////
144 {
145  ts5_check_mouse("ts5_hide_mouse");
146  ts5_log(TS5_LOGLEVEL_5, "ts5_hide_mouse()\n");
147 
148  #ifndef TS5_RASPBERRYPI
149  al_hide_mouse_cursor(_ts5_data.display[_ts5_status.active_display]);
150 
151  #endif
152 }
153 
154 
155 ////////////////////////////////////////////////////////////////////////////////
156 /// Move the mouse pointer to position (x,y).
157 ///
158 /// \param x Horizontal position of the mouse on the active display.
159 /// \param y Vertical position of the mouse on the active display.
160 ////////////////////////////////////////////////////////////////////////////////
161 void ts5_set_mouse_position(double x, double y)
162 {
163  ts5_check_mouse("ts5_set_mouse_position");
164  ts5_log(TS5_LOGLEVEL_5, "ts5_set_mouse_position(%f,%f)\n", x, y);
165 
166  if (_ts5_status.graphics.coordinate_scale
167  == TS5_RELATIVE_COORDINATES) {
170  }
171 
172  if (_ts5_status.graphics.coordinate_system
173  == TS5_CARTESIAN_COORDINATES) {
176  }
177 
178  al_set_mouse_xy(_ts5_data.display[_ts5_status.active_display],
179  (int)x, (int)y);
180 }
181 
182 ////////////////////////////////////////////////////////////////////////////////
183 /// Get the horizontal and vertical position of the mouse pointer
184 ///
185 /// \param x Variable that will store the horizontal position.
186 /// \param y Variable that will store the vertical position.
187 ///
188 /// You can pass NULL for values you are not interested in.
189 ////////////////////////////////////////////////////////////////////////////////
190 void ts5_get_mouse_position(double *x, double *y)
191 {
192  ts5_check_mouse("ts5_get_mouse_position");
193  ts5_log(TS5_LOGLEVEL_6, "ts5_get_mouse_position(%p,%p)\n", x, y);
194 
195  ALLEGRO_MOUSE_STATE status;
196  al_get_mouse_state(&status);
197 
198  double xx, yy;
199 
200  xx = al_get_mouse_state_axis(&status, 0);
201  yy = al_get_mouse_state_axis(&status, 1);
202 
203  #ifdef TS5_RASPBERRYPI
204  #include <allegro5/allegro_primitives.h>
205 
206  // draw mouse
207  al_set_target_backbuffer(_ts5_data.display[_ts5_status.active_display]);
208  al_draw_bitmap(_ts5_data.display_buffer[_ts5_status.active_display], 0.0, 0.0, 0);
209 
210  TS5_COLOR oldcolor = ts5_set_foreground_color(
211  ts5_make_named_color("chartreuse", 1.0));
212 
213  al_draw_line(xx-8.0, yy-8.0, xx+8.0, yy+8.0, _ts5_status.graphics.background_color, 9.0);
214  al_draw_line(xx-8.0, yy+8.0, xx+8.0, yy-8.0, _ts5_status.graphics.background_color, 9.0);
215  al_draw_line(xx-6.0, yy-6.0, xx+6.0, yy+6.0, _ts5_status.graphics.foreground_color, 3.0);
216  al_draw_line(xx-6.0, yy+6.0, xx+6.0, yy-6.0, _ts5_status.graphics.foreground_color, 3.0);
217 
218  ts5_set_foreground_color(oldcolor);
219  al_flip_display();
220 
221  #endif
222 
223  if (_ts5_status.graphics.coordinate_system
224  == TS5_CARTESIAN_COORDINATES) {
227  }
228 
229  if (_ts5_status.graphics.coordinate_scale
230  == TS5_RELATIVE_COORDINATES) {
233  }
234 
235  if (x) {
236  *x = xx;
237  }
238 
239  if (y) {
240  *y = yy;
241  }
242 }
243 
244 
245 ////////////////////////////////////////////////////////////////////////////////
246 /// Get the horizontal position of the mouse pointer
247 ///
248 /// \return The horizontal position of the mouse pointer.
249 ////////////////////////////////////////////////////////////////////////////////
251 {
252  ts5_check_mouse("ts5_get_mouse_x");
253  ts5_log(TS5_LOGLEVEL_6, "ts5_get_mouse_x()\n");
254 
255  double x;
256  ts5_get_mouse_position(&x, NULL);
257 
258  return x;
259 }
260 
261 
262 ////////////////////////////////////////////////////////////////////////////////
263 /// Get the vertical position of the mouse pointer
264 ///
265 /// \return The vertical position of the mouse pointer.
266 ////////////////////////////////////////////////////////////////////////////////
268 {
269  ts5_check_mouse("ts5_get_mouse_y");
270  ts5_log(TS5_LOGLEVEL_6, "ts5_get_mouse_y()\n");
271 
272  double y;
273  ts5_get_mouse_position(NULL, &y);
274 
275  return y;
276 }
277 
278 
279 ////////////////////////////////////////////////////////////////////////////////
280 /// Draw a mouse button and wait for a click.
281 ///
282 /// \param x Horizontal position of the button on the active display.
283 /// \param y Vertical position of the button on the active display.
284 ///
285 /// The button has an ugly green color. This color can not be changed.
286 /// This is not a bug. It is a Deliberately Annoying Feature (DAF).
287 ////////////////////////////////////////////////////////////////////////////////
288 void ts5_draw_mouse_button(double x, double y)
289 {
290  ts5_check_mouse("ts5_draw_mouse_button");
291  ts5_log(TS5_LOGLEVEL_5, "ts5_draw_mouse_button(%f,%f)\n", x, y);
292 
293  // always write to the display
294  ts5_set_active_display(_ts5_status.active_display+1);
295 
296  TS5_BITMAP *oldmap = ts5_set_drawing_target(
297  _ts5_data.display_buffer
298  [_ts5_status.active_display]);
299 
300  TS5_COLOR oldcolor = ts5_set_foreground_color(
301  ts5_make_named_color("chartreuse", 1.0));
302 
303  double oldthick = ts5_set_drawing_thickness(4.0);
304  int oldfill = ts5_set_fill_mode(TS5_FILL_OFF);
305 
306  double w_abs_disp = 40, h_abs_disp = 40;
307  double x1_abs_disp, x2_abs_disp, y1_abs_disp, y2_abs_disp;
308 
309  // covert to absolute scale
310  if (_ts5_status.graphics.coordinate_scale
311  == TS5_RELATIVE_COORDINATES) {
312  x1_abs_disp = ts5_relative_to_absolute_coordinate_x(x);
313  y1_abs_disp = ts5_relative_to_absolute_coordinate_y(y);
314  }
315  else {
316  x1_abs_disp = x;
317  y1_abs_disp = y;
318  }
319 
320  // convert to display coordinates.
321  if (_ts5_status.graphics.coordinate_system
322  == TS5_CARTESIAN_COORDINATES) {
323  x1_abs_disp = ts5_cartesian_to_display_coordinate_x(x1_abs_disp);
324  y1_abs_disp = ts5_cartesian_to_display_coordinate_y(y1_abs_disp);
325 
326  x1_abs_disp -= w_abs_disp/2;
327  y1_abs_disp -= h_abs_disp/2;
328  }
329 
330  x2_abs_disp = x1_abs_disp + w_abs_disp;
331  y2_abs_disp = y1_abs_disp + h_abs_disp;
332 
333  int oldsystem = ts5_set_coordinate_system(TS5_DISPLAY_COORDINATES);
334  int oldscale = ts5_set_coordinate_scale(TS5_ABSOLUTE_COORDINATES);
335 
336  // check if the button will be on the screen
337  double dispw = _ts5_status.display[_ts5_status.active_display].w;
338  double disph = _ts5_status.display[_ts5_status.active_display].h;
339 
340  if (x1_abs_disp < 0.0 || x2_abs_disp > dispw
341  || y1_abs_disp < 0.0 || y2_abs_disp > disph) {
342  ts5_fatal("%s: %s (%f,%f)\n", "ts5_draw_mouse_button",
343  "button will be off screen", x1_abs_disp, y1_abs_disp);
344  }
345 
346  ts5_draw_rounded_rectangle(x1_abs_disp, y1_abs_disp,
347  x2_abs_disp, y2_abs_disp, 3.0, 3.0);
348 
349  ts5_set_fill_mode(TS5_FILL_ON);
350  ts5_draw_triangle(x2_abs_disp - 5.0, (y1_abs_disp+y2_abs_disp)/2.0,
351  x1_abs_disp+5.0, y1_abs_disp+5.0, x1_abs_disp+5.0, y2_abs_disp-5.0);
353 
354  #ifndef TS5_RASPBERRYPI
355  ts5_show_mouse();
356 
357  #endif
358 
359  ALLEGRO_MOUSE_STATE status;
360  int down;
361  int ok = 0;
362  do {
363  double xp, yp;
364  ts5_get_mouse_position(&xp, &yp);
365  al_get_mouse_state(&status);
366  down = al_mouse_button_down(&status, 1);
367  if (down && xp > x1_abs_disp && xp < x2_abs_disp
368  && yp > y1_abs_disp && yp < y2_abs_disp) {
369  ok = 1;
370  }
371  } while (!ok);
372 
374  ts5_draw_triangle(x2_abs_disp - 5, (y1_abs_disp+y2_abs_disp)/2,
375  x1_abs_disp+5, y1_abs_disp+5, x1_abs_disp+5, y2_abs_disp-5);
377 
378  ok = 0;
379  do {
380  al_get_mouse_state(&status);
381  down = al_mouse_button_down(&status, 1);
382  if (!down) {
383  ok = 1;
384  }
385  } while (!ok);
386 
388  ts5_draw_triangle(x2_abs_disp - 5, (y1_abs_disp+y2_abs_disp)/2,
389  x1_abs_disp+5, y1_abs_disp+5, x1_abs_disp+5, y2_abs_disp-5);
391 
392 
393  ts5_set_drawing_target(oldmap);
394  ts5_set_foreground_color(oldcolor);
395  ts5_set_drawing_thickness(oldthick);
396  ts5_set_fill_mode(oldfill);
397  ts5_set_coordinate_system(oldsystem);
398  ts5_set_coordinate_scale(oldscale);
399 }
400 
401 
402 ////////////////////////////////////////////////////////////////////////////////
403 //@}
404 ////////////////////////////////////////////////////////////////////////////////
405 
double ts5_display_to_cartesian_coordinate_y(const double y)
Convert a vertical display coordinate into a vertical Cartisian coordinate.
Definition: graphics.c:396
void ts5_hide_mouse()
Make the mouse cursor invisible on the active display.
Definition: mouse.c:143
TS5_COLOR ts5_make_named_color(const char *name, const double a)
Return a color that corresponds to name.
Definition: graphics.c:549
double ts5_display_to_cartesian_coordinate_x(const double x)
Convert a horizontal display coordinate into a horizontal Cartisian coordinate.
Definition: graphics.c:375
double ts5_flip_display()
Make what has been drawn visible on the screen.
Definition: display.c:525
int ts5_set_active_display(const int display)
Set the active display.
Definition: display.c:601
int ts5_set_fill_mode(const int fill_mode)
Set the fill mode.
Definition: graphics.c:746
void ts5_show_mouse()
Make the mouse cursor visible on the active display.
Definition: mouse.c:128
TS5_COLOR ts5_set_foreground_color(const TS5_COLOR foreground_color)
Set the foreground color.
Definition: graphics.c:607
void ts5_get_mouse_position(double *x, double *y)
Get the horizontal and vertical position of the mouse pointer.
Definition: mouse.c:190
int ts5_set_coordinate_scale(const int coordinate_scale)
Set the coordinate scale.
Definition: graphics.c:147
void ts5_set_mouse_position(double x, double y)
Move the mouse pointer to position (x,y).
Definition: mouse.c:161
TS5_BITMAP * ts5_set_drawing_target(TS5_BITMAP *target)
Set the active drawing target.
Definition: bitmaps.c:243
void ts5_draw_rounded_rectangle(double x1, double y1, double x2, double y2, double rx, double ry)
Draw a rounded rectangle.
Definition: primitives.c:187
int ts5_get_num_mouse_buttons()
Get the number of buttons available on the mouse.
Definition: mouse.c:105
void ts5_draw_mouse_button(double x, double y)
Draw a mouse button and wait for a click.
Definition: mouse.c:288
double ts5_relative_to_absolute_coordinate_x(const double x)
Convert a relative horizontal coordinate into an absolute horizontal coordinate.
Definition: graphics.c:208
double ts5_set_drawing_thickness(double drawing_thickness)
Set the drawing thickness.
Definition: graphics.c:698
int ts5_define_mouse_button(int button)
Define a mouse button as a response button.
Definition: mouse.c:46
void ts5_log(const unsigned int level, const char *format,...)
Send info to a logging window.
Definition: system.c:45
double ts5_cartesian_to_display_coordinate_x(const double x)
Convert a horizontal Cartesian coordinate into a horizontal display coordinate.
Definition: graphics.c:333
double ts5_cartesian_to_display_coordinate_y(const double y)
Convert a vertical Cartesian coordinate into a vertical display coordinate.
Definition: graphics.c:354
void ts5_check_mouse(char *calling_function)
Do some checks at the start of each mouse function.
void ts5_draw_triangle(double x1, double y1, double x2, double y2, double x3, double y3)
Draw a triangle.
Definition: primitives.c:259
double ts5_absolute_to_relative_coordinate_y(const double y)
Convert an absolute vertical coordinate into a relative vertical coordinate.
Definition: graphics.c:302
double ts5_absolute_to_relative_coordinate_x(const double x)
Convert an absolute horizontal coordinate into a relative horizontal coordinate.
Definition: graphics.c:271
void ts5_fatal(const char *format,...)
Exit safely with an error message.
Definition: system.c:529
double ts5_relative_to_absolute_coordinate_y(const double y)
Convert a relative vertical coordinate into an absolute vertical coordinate.
Definition: graphics.c:240
double ts5_get_mouse_x()
Get the horizontal position of the mouse pointer.
Definition: mouse.c:250
int ts5_set_coordinate_system(const int coordinate_system)
Set the coordinate system.
Definition: graphics.c:81
double ts5_get_mouse_y()
Get the vertical position of the mouse pointer.
Definition: mouse.c:267