pointerEventList.cxx 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. // Filename: pointerEventList.cxx
  2. // Created by: jyelon (20Sep2007)
  3. //
  4. ////////////////////////////////////////////////////////////////////
  5. //
  6. // PANDA 3D SOFTWARE
  7. // Copyright (c) Carnegie Mellon University. All rights reserved.
  8. //
  9. // All use of this software is subject to the terms of the revised BSD
  10. // license. You should have received a copy of this license along
  11. // with this source code in a file named "LICENSE."
  12. //
  13. ////////////////////////////////////////////////////////////////////
  14. #include "pointerEventList.h"
  15. #include "indent.h"
  16. #include "config_event.h"
  17. #include "clockObject.h"
  18. #include "mathNumbers.h"
  19. #include <math.h>
  20. TypeHandle PointerEventList::_type_handle;
  21. ////////////////////////////////////////////////////////////////////
  22. // Function: delta_angle
  23. // Access: Static, Inline
  24. // Description: Compute the difference between two angles.
  25. // Returns a value in the range -180 to 180.
  26. ////////////////////////////////////////////////////////////////////
  27. INLINE double delta_angle(double angle1, double angle2) {
  28. double deltang = angle2 - angle1;
  29. while (deltang < -180.0) deltang += 360.0;
  30. while (deltang > 180.0) deltang -= 360.0;
  31. return deltang;
  32. }
  33. ////////////////////////////////////////////////////////////////////
  34. // Function: delta_angle
  35. // Access: Static, Inline
  36. // Description: Compute the difference between two angles.
  37. // Returns a value in the range -180 to 180.
  38. ////////////////////////////////////////////////////////////////////
  39. INLINE double normalize_angle(double angle) {
  40. while (angle < 0.0) angle += 360.0;
  41. while (angle > 360.0) angle -= 360.0;
  42. return angle;
  43. }
  44. ////////////////////////////////////////////////////////////////////
  45. // Function: PointerEventList::output
  46. // Access: Public, Virtual
  47. // Description:
  48. ////////////////////////////////////////////////////////////////////
  49. void PointerEventList::
  50. output(ostream &out) const {
  51. if (_events.empty()) {
  52. out << "(no pointers)";
  53. } else {
  54. Events::const_iterator ei;
  55. ei = _events.begin();
  56. out << "(" << (*ei);
  57. ++ei;
  58. while (ei != _events.end()) {
  59. out << " " << (*ei);
  60. ++ei;
  61. }
  62. out << ")";
  63. }
  64. }
  65. ////////////////////////////////////////////////////////////////////
  66. // Function: PointerEventList::write
  67. // Access: Public
  68. // Description:
  69. ////////////////////////////////////////////////////////////////////
  70. void PointerEventList::
  71. write(ostream &out, int indent_level) const {
  72. indent(out, indent_level) << _events.size() << " events:\n";
  73. Events::const_iterator ei;
  74. for (ei = _events.begin(); ei != _events.end(); ++ei) {
  75. indent(out, indent_level + 2) << (*ei) << "\n";
  76. }
  77. }
  78. ////////////////////////////////////////////////////////////////////
  79. // Function: PointerEventList::add_event
  80. // Access: Published
  81. // Description: Adds a new event to the end of the list.
  82. // Automatically calculates the dx, dy, length,
  83. // direction, and rotation for all but the first event.
  84. ////////////////////////////////////////////////////////////////////
  85. void PointerEventList::
  86. add_event(bool in_win, int xpos, int ypos, int seq, double time) {
  87. PointerEvent pe;
  88. pe._in_window = in_win;
  89. pe._xpos = xpos;
  90. pe._ypos = ypos;
  91. pe._sequence = seq;
  92. pe._time = time;
  93. if (_events.size() > 0) {
  94. pe._dx = xpos - _events.back()._xpos;
  95. pe._dy = ypos - _events.back()._ypos;
  96. double ddx = pe._dx;
  97. double ddy = pe._dy;
  98. pe._length = sqrt(ddx*ddx + ddy*ddy);
  99. if (pe._length > 0.0) {
  100. pe._direction = normalize_angle(atan2(-ddy,ddx) * (180.0 / MathNumbers::pi));
  101. } else {
  102. pe._direction = _events.back()._direction;
  103. }
  104. pe._rotation = delta_angle(_events.back()._direction, pe._direction);
  105. } else {
  106. pe._dx = 0;
  107. pe._dy = 0;
  108. pe._length = 0.0;
  109. pe._direction = 0.0;
  110. pe._rotation = 0.0;
  111. }
  112. _events.push_back(pe);
  113. }
  114. ////////////////////////////////////////////////////////////////////
  115. // Function: PointerEventList::encircles
  116. // Access: Published
  117. // Description: Returns true if the trail loops around the
  118. // specified point.
  119. ////////////////////////////////////////////////////////////////////
  120. bool PointerEventList::
  121. encircles(int x, int y) const {
  122. int tot_events = _events.size();
  123. if (tot_events < 3) {
  124. return false;
  125. }
  126. int last = tot_events-1;
  127. double dx = _events[last]._xpos - x;
  128. double dy = _events[last]._ypos - y;
  129. double lastang = atan2(dy, dx) * (180.0/MathNumbers::pi);
  130. double total = 0.0;
  131. for (int i=last; (i>=0) && (total < 360.0) && (total > -360.0); i--) {
  132. dx = _events[i]._xpos - x;
  133. dy = _events[i]._ypos - y;
  134. if ((dx==0.0)&&(dy==0.0)) {
  135. continue;
  136. }
  137. double angle = atan2(dy,dx) * (180.0/MathNumbers::pi);
  138. double deltang = delta_angle(lastang, angle);
  139. if (deltang * total < 0.0) {
  140. total = 0.0;
  141. }
  142. total += deltang;
  143. lastang = angle;
  144. }
  145. return (total > 360.0) || (total < -360.0);
  146. }
  147. ////////////////////////////////////////////////////////////////////
  148. // Function: PointerEventList::total_turns
  149. // Access: Published
  150. // Description: returns the total angular deviation that the trail
  151. // has made in the specified time period. A small
  152. // number means that the trail is moving in a relatively
  153. // straight line, a large number means that the trail
  154. // is zig-zagging or spinning. The result is in degrees.
  155. ////////////////////////////////////////////////////////////////////
  156. double PointerEventList::
  157. total_turns(double sec) const {
  158. double old = ClockObject::get_global_clock()->get_frame_time() - sec;
  159. int pos = _events.size()-1;
  160. double tot = 0.0;
  161. while ((pos >= 0)&&(_events[pos]._time >= old)) {
  162. double rot = _events[pos]._rotation;
  163. if (rot < 0.0) rot = -rot;
  164. tot += rot;
  165. }
  166. return tot;
  167. }
  168. ////////////////////////////////////////////////////////////////////
  169. // Function: PointerEventList::match_pattern
  170. // Access: Published
  171. // Description: This function is not implemented yet. It is a work
  172. // in progress. The intent is as follows:
  173. //
  174. // Returns a nonzero value if the mouse movements
  175. // match the specified pattern. The higher the value,
  176. // the better the match. The pattern is a sequence
  177. // of compass directions (ie, "E", "NE", etc) separated
  178. // by spaces. If rot is nonzero, then the pattern is
  179. // rotated counterclockwise by the specified amount
  180. // before testing. Seglen is the minimum length a
  181. // mouse movement needs to be in order to be considered
  182. // significant.
  183. ////////////////////////////////////////////////////////////////////
  184. double PointerEventList::
  185. match_pattern(const string &ascpat, double rot, double seglen) {
  186. // Convert the pattern from ascii to a more usable form.
  187. pvector <double> pattern;
  188. parse_pattern(ascpat, pattern);
  189. // Apply the rotation to the pattern.
  190. for (size_t i=0; i<pattern.size(); i++) {
  191. pattern[i] = normalize_angle(pattern[i] + rot);
  192. }
  193. return 0.0;
  194. }
  195. ////////////////////////////////////////////////////////////////////
  196. // Function: PointerEventList::parse_pattern
  197. // Access: Private
  198. // Description: Parses a pattern as used by match_pattern.
  199. ////////////////////////////////////////////////////////////////////
  200. void PointerEventList::
  201. parse_pattern(const string &ascpat, pvector <double> &pattern) {
  202. int chars = 0;
  203. double dir = 180.0;
  204. for (size_t i=0; i<ascpat.size(); i++) {
  205. char c = ascpat[i];
  206. double ang = -1.0;
  207. if ((c=='E')||(c=='e')) ang=0.0;
  208. else if ((c=='N')||(c=='n')) ang=90.0;
  209. else if ((c=='W')||(c=='w')) ang=180.0;
  210. else if ((c=='S')||(c=='s')) ang=270.0;
  211. if (ang >= 0.0) {
  212. double offset = delta_angle(dir, ang);
  213. double newang = dir + offset;
  214. dir = normalize_angle((dir * chars + newang) / (chars + 1));
  215. chars += 1;
  216. } else {
  217. if ((c != ' ')&&(c != '\t')) {
  218. event_cat.warning() <<
  219. "Invalid pattern in PointerEventList::match_pattern\n";
  220. pattern.clear();
  221. return;
  222. }
  223. if (chars > 0) {
  224. pattern.push_back(dir);
  225. }
  226. chars = 0;
  227. dir = 180.0;
  228. }
  229. }
  230. if (chars > 0) {
  231. pattern.push_back(dir);
  232. }
  233. cerr << "Pattern: ";
  234. for (int i=0; i<(int)pattern.size(); i++) {
  235. cerr << pattern[i] << " ";
  236. }
  237. cerr << "\n";
  238. }