Panda3D
|
00001 // Filename: pointerEventList.cxx 00002 // Created by: jyelon (20Sep2007) 00003 // 00004 //////////////////////////////////////////////////////////////////// 00005 // 00006 // PANDA 3D SOFTWARE 00007 // Copyright (c) Carnegie Mellon University. All rights reserved. 00008 // 00009 // All use of this software is subject to the terms of the revised BSD 00010 // license. You should have received a copy of this license along 00011 // with this source code in a file named "LICENSE." 00012 // 00013 //////////////////////////////////////////////////////////////////// 00014 00015 #include "pointerEventList.h" 00016 #include "indent.h" 00017 #include "config_event.h" 00018 #include "clockObject.h" 00019 #include "deg_2_rad.h" 00020 #include "cmath.h" 00021 00022 TypeHandle PointerEventList::_type_handle; 00023 00024 //////////////////////////////////////////////////////////////////// 00025 // Function: delta_angle 00026 // Access: Static, Inline 00027 // Description: Compute the difference between two angles. 00028 // Returns a value in the range -180 to 180. 00029 //////////////////////////////////////////////////////////////////// 00030 INLINE double delta_angle(double angle1, double angle2) { 00031 double deltang = angle2 - angle1; 00032 while (deltang < -180.0) deltang += 360.0; 00033 while (deltang > 180.0) deltang -= 360.0; 00034 return deltang; 00035 } 00036 00037 00038 //////////////////////////////////////////////////////////////////// 00039 // Function: delta_angle 00040 // Access: Static, Inline 00041 // Description: Compute the difference between two angles. 00042 // Returns a value in the range -180 to 180. 00043 //////////////////////////////////////////////////////////////////// 00044 INLINE double normalize_angle(double angle) { 00045 while (angle < 0.0) angle += 360.0; 00046 while (angle > 360.0) angle -= 360.0; 00047 return angle; 00048 } 00049 00050 00051 00052 //////////////////////////////////////////////////////////////////// 00053 // Function: PointerEventList::output 00054 // Access: Public, Virtual 00055 // Description: 00056 //////////////////////////////////////////////////////////////////// 00057 void PointerEventList:: 00058 output(ostream &out) const { 00059 if (_events.empty()) { 00060 out << "(no pointers)"; 00061 } else { 00062 Events::const_iterator ei; 00063 ei = _events.begin(); 00064 out << "(" << (*ei); 00065 ++ei; 00066 while (ei != _events.end()) { 00067 out << " " << (*ei); 00068 ++ei; 00069 } 00070 out << ")"; 00071 } 00072 } 00073 00074 //////////////////////////////////////////////////////////////////// 00075 // Function: PointerEventList::write 00076 // Access: Public 00077 // Description: 00078 //////////////////////////////////////////////////////////////////// 00079 void PointerEventList:: 00080 write(ostream &out, int indent_level) const { 00081 indent(out, indent_level) << _events.size() << " events:\n"; 00082 Events::const_iterator ei; 00083 for (ei = _events.begin(); ei != _events.end(); ++ei) { 00084 indent(out, indent_level + 2) << (*ei) << "\n"; 00085 } 00086 } 00087 00088 //////////////////////////////////////////////////////////////////// 00089 // Function: PointerEventList::add_event 00090 // Access: Published 00091 // Description: Adds a new event to the end of the list. 00092 // Automatically calculates the dx, dy, length, 00093 // direction, and rotation for all but the first event. 00094 //////////////////////////////////////////////////////////////////// 00095 void PointerEventList:: 00096 add_event(bool in_win, int xpos, int ypos, int seq, double time) { 00097 PointerEvent pe; 00098 pe._in_window = in_win; 00099 pe._xpos = xpos; 00100 pe._ypos = ypos; 00101 pe._sequence = seq; 00102 pe._time = time; 00103 if (_events.size() > 0) { 00104 pe._dx = xpos - _events.back()._xpos; 00105 pe._dy = ypos - _events.back()._ypos; 00106 double ddx = pe._dx; 00107 double ddy = pe._dy; 00108 pe._length = csqrt(ddx*ddx + ddy*ddy); 00109 if (pe._length > 0.0) { 00110 pe._direction = normalize_angle(rad_2_deg(catan2(-ddy,ddx))); 00111 } else { 00112 pe._direction = _events.back()._direction; 00113 } 00114 pe._rotation = delta_angle(_events.back()._direction, pe._direction); 00115 } else { 00116 pe._dx = 0; 00117 pe._dy = 0; 00118 pe._length = 0.0; 00119 pe._direction = 0.0; 00120 pe._rotation = 0.0; 00121 } 00122 _events.push_back(pe); 00123 } 00124 00125 //////////////////////////////////////////////////////////////////// 00126 // Function: PointerEventList::encircles 00127 // Access: Published 00128 // Description: Returns true if the trail loops around the 00129 // specified point. 00130 //////////////////////////////////////////////////////////////////// 00131 bool PointerEventList:: 00132 encircles(int x, int y) const { 00133 int tot_events = _events.size(); 00134 if (tot_events < 3) { 00135 return false; 00136 } 00137 int last = tot_events-1; 00138 double dx = _events[last]._xpos - x; 00139 double dy = _events[last]._ypos - y; 00140 double lastang = rad_2_deg(catan2(dy, dx)); 00141 double total = 0.0; 00142 for (int i=last; (i>=0) && (total < 360.0) && (total > -360.0); i--) { 00143 dx = _events[i]._xpos - x; 00144 dy = _events[i]._ypos - y; 00145 if ((dx==0.0)&&(dy==0.0)) { 00146 continue; 00147 } 00148 double angle = rad_2_deg(catan2(dy,dx)); 00149 double deltang = delta_angle(lastang, angle); 00150 if (deltang * total < 0.0) { 00151 total = 0.0; 00152 } 00153 total += deltang; 00154 lastang = angle; 00155 } 00156 return (total > 360.0) || (total < -360.0); 00157 } 00158 00159 //////////////////////////////////////////////////////////////////// 00160 // Function: PointerEventList::total_turns 00161 // Access: Published 00162 // Description: returns the total angular deviation that the trail 00163 // has made in the specified time period. A small 00164 // number means that the trail is moving in a relatively 00165 // straight line, a large number means that the trail 00166 // is zig-zagging or spinning. The result is in degrees. 00167 //////////////////////////////////////////////////////////////////// 00168 double PointerEventList:: 00169 total_turns(double sec) const { 00170 double old = ClockObject::get_global_clock()->get_frame_time() - sec; 00171 int pos = _events.size()-1; 00172 double tot = 0.0; 00173 while ((pos >= 0)&&(_events[pos]._time >= old)) { 00174 double rot = _events[pos]._rotation; 00175 if (rot < 0.0) rot = -rot; 00176 tot += rot; 00177 } 00178 return tot; 00179 } 00180 00181 //////////////////////////////////////////////////////////////////// 00182 // Function: PointerEventList::match_pattern 00183 // Access: Published 00184 // Description: This function is not implemented yet. It is a work 00185 // in progress. The intent is as follows: 00186 // 00187 // Returns a nonzero value if the mouse movements 00188 // match the specified pattern. The higher the value, 00189 // the better the match. The pattern is a sequence 00190 // of compass directions (ie, "E", "NE", etc) separated 00191 // by spaces. If rot is nonzero, then the pattern is 00192 // rotated counterclockwise by the specified amount 00193 // before testing. Seglen is the minimum length a 00194 // mouse movement needs to be in order to be considered 00195 // significant. 00196 //////////////////////////////////////////////////////////////////// 00197 double PointerEventList:: 00198 match_pattern(const string &ascpat, double rot, double seglen) { 00199 // Convert the pattern from ascii to a more usable form. 00200 vector_double pattern; 00201 parse_pattern(ascpat, pattern); 00202 00203 // Apply the rotation to the pattern. 00204 for (size_t i=0; i<pattern.size(); i++) { 00205 pattern[i] = normalize_angle(pattern[i] + rot); 00206 } 00207 00208 return 0.0; 00209 } 00210 00211 //////////////////////////////////////////////////////////////////// 00212 // Function: PointerEventList::parse_pattern 00213 // Access: Private 00214 // Description: Parses a pattern as used by match_pattern. 00215 //////////////////////////////////////////////////////////////////// 00216 void PointerEventList:: 00217 parse_pattern(const string &ascpat, vector_double &pattern) { 00218 int chars = 0; 00219 double dir = 180.0; 00220 for (size_t i=0; i<ascpat.size(); i++) { 00221 char c = ascpat[i]; 00222 double ang = -1.0; 00223 if ((c=='E')||(c=='e')) ang=0.0; 00224 else if ((c=='N')||(c=='n')) ang=90.0; 00225 else if ((c=='W')||(c=='w')) ang=180.0; 00226 else if ((c=='S')||(c=='s')) ang=270.0; 00227 if (ang >= 0.0) { 00228 double offset = delta_angle(dir, ang); 00229 double newang = dir + offset; 00230 dir = normalize_angle((dir * chars + newang) / (chars + 1)); 00231 chars += 1; 00232 } else { 00233 if ((c != ' ')&&(c != '\t')) { 00234 event_cat.warning() << 00235 "Invalid pattern in PointerEventList::match_pattern\n"; 00236 pattern.clear(); 00237 return; 00238 } 00239 if (chars > 0) { 00240 pattern.push_back(dir); 00241 } 00242 chars = 0; 00243 dir = 180.0; 00244 } 00245 } 00246 if (chars > 0) { 00247 pattern.push_back(dir); 00248 } 00249 00250 cerr << "Pattern: "; 00251 for (int i=0; i<(int)pattern.size(); i++) { 00252 cerr << pattern[i] << " "; 00253 } 00254 cerr << "\n"; 00255 }