From 942769b67240a6aac66fd738c5bc489bcc7acbfd Mon Sep 17 00:00:00 2001 From: Josh Yelon Date: Mon, 1 Oct 2007 19:47:19 +0000 Subject: [PATCH] Improvements to mouse-trail tracking --- panda/src/device/mouseAndKeyboard.cxx | 12 +- panda/src/device/mouseAndKeyboard.h | 1 - panda/src/display/graphicsWindow.cxx | 18 +- panda/src/display/graphicsWindow.h | 2 +- .../src/display/graphicsWindowInputDevice.cxx | 28 +-- panda/src/display/graphicsWindowInputDevice.h | 6 +- panda/src/event/config_event.cxx | 1 + panda/src/event/pointerEvent.I | 83 +++++---- panda/src/event/pointerEvent.cxx | 17 +- panda/src/event/pointerEvent.h | 11 +- panda/src/event/pointerEventList.I | 128 +++++++------ panda/src/event/pointerEventList.cxx | 169 ++++++++++-------- panda/src/event/pointerEventList.h | 35 ++-- panda/src/tform/mouseWatcher.I | 11 ++ panda/src/tform/mouseWatcher.cxx | 18 +- panda/src/tform/mouseWatcher.h | 1 + 16 files changed, 307 insertions(+), 234 deletions(-) diff --git a/panda/src/device/mouseAndKeyboard.cxx b/panda/src/device/mouseAndKeyboard.cxx index ba51b5d8f6..27987e131a 100644 --- a/panda/src/device/mouseAndKeyboard.cxx +++ b/panda/src/device/mouseAndKeyboard.cxx @@ -46,7 +46,6 @@ MouseAndKeyboard(GraphicsWindow *window, int device, const string &name) : _pixel_size = new EventStoreVec2(LPoint2f(0.0f, 0.0f)); _xy = new EventStoreVec2(LPoint2f(0.0f, 0.0f)); _button_events = new ButtonEventList; - _pointer_events = new PointerEventList; } //////////////////////////////////////////////////////////////////// @@ -108,15 +107,10 @@ do_transmit_data(DataGraphTraverser *, const DataNodeTransmit &, output.set_data(_button_events_output, EventParameter(_button_events)); } if (_window->has_pointer_event(_device)) { - // Fill up the pointer events. - _pointer_events->clear(); - while (_window->has_pointer_event(_device)) { - PointerEvent be = _window->get_pointer_event(_device); - _pointer_events->add_event(be); - } - output.set_data(_pointer_events_output, EventParameter(_pointer_events)); + PT(PointerEventList) pel = _window->get_pointer_events(_device); + output.set_data(_pointer_events_output, EventParameter(pel)); } - + // Get the window size. WindowProperties properties = _window->get_properties(); if (properties.has_size()) { diff --git a/panda/src/device/mouseAndKeyboard.h b/panda/src/device/mouseAndKeyboard.h index 2402d6dc4f..f2550f840b 100644 --- a/panda/src/device/mouseAndKeyboard.h +++ b/panda/src/device/mouseAndKeyboard.h @@ -75,7 +75,6 @@ private: PT(EventStoreVec2) _pixel_size; PT(EventStoreVec2) _xy; PT(ButtonEventList) _button_events; - PT(PointerEventList) _pointer_events; PT(GraphicsWindow) _window; int _device; diff --git a/panda/src/display/graphicsWindow.cxx b/panda/src/display/graphicsWindow.cxx index b693fcee81..b336ec8042 100644 --- a/panda/src/display/graphicsWindow.cxx +++ b/panda/src/display/graphicsWindow.cxx @@ -472,7 +472,7 @@ get_button_event(int device) { // Description: Returns true if the indicated device has a pending // pointer event (a mouse movement). If this returns // true, the particular event may be extracted via -// get_pointer_event(). +// get_pointer_events(). //////////////////////////////////////////////////////////////////// bool GraphicsWindow:: has_pointer_event(int device) const { @@ -486,19 +486,19 @@ has_pointer_event(int device) const { } //////////////////////////////////////////////////////////////////// -// Function: GraphicsWindow::get_pointer_event +// Function: GraphicsWindow::get_pointer_events // Access: Public // Description: Assuming a previous call to has_pointer_event() -// returned true, this returns the pending pointer event. +// returned true, this returns the pending pointer event list. //////////////////////////////////////////////////////////////////// -PointerEvent GraphicsWindow:: -get_pointer_event(int device) { - PointerEvent result; +PT(PointerEventList) GraphicsWindow:: +get_pointer_events(int device) { + PT(PointerEventList) result; { MutexHolder holder(_input_lock); - nassertr(device >= 0 && device < (int)_input_devices.size(), PointerEvent()); - nassertr(_input_devices[device].has_pointer_event(), PointerEvent()); - result = _input_devices[device].get_pointer_event(); + nassertr(device >= 0 && device < (int)_input_devices.size(), NULL); + nassertr(_input_devices[device].has_pointer_event(), NULL); + result = _input_devices[device].get_pointer_events(); } return result; } diff --git a/panda/src/display/graphicsWindow.h b/panda/src/display/graphicsWindow.h index 0547fff55d..0544458fd0 100644 --- a/panda/src/display/graphicsWindow.h +++ b/panda/src/display/graphicsWindow.h @@ -87,7 +87,7 @@ public: bool has_button_event(int device) const; ButtonEvent get_button_event(int device); bool has_pointer_event(int device) const; - PointerEvent get_pointer_event(int device); + PT(PointerEventList) get_pointer_events(int device); virtual int verify_window_sizes(int numsizes, int *dimen); diff --git a/panda/src/display/graphicsWindowInputDevice.cxx b/panda/src/display/graphicsWindowInputDevice.cxx index 21e79ceeb4..93325e499f 100644 --- a/panda/src/display/graphicsWindowInputDevice.cxx +++ b/panda/src/display/graphicsWindowInputDevice.cxx @@ -186,20 +186,20 @@ get_button_event() { //////////////////////////////////////////////////////////////////// bool GraphicsWindowInputDevice:: has_pointer_event() const { - return !_pointer_events.empty(); + return (_pointer_events != 0); } //////////////////////////////////////////////////////////////////// -// Function: GraphicsWindowInputDevice::get_pointer_event +// Function: GraphicsWindowInputDevice::get_pointer_events // Access: Public -// Description: Assuming a previous call to has_pointer_event() -// returned true, this returns the pending pointer event. +// Description: Returns a PointerEventList containing all the recent +// pointer events. //////////////////////////////////////////////////////////////////// -PointerEvent GraphicsWindowInputDevice:: -get_pointer_event() { - PointerEvent be = _pointer_events.front(); - _pointer_events.pop_front(); - return be; +PT(PointerEventList) GraphicsWindowInputDevice:: +get_pointer_events() { + PT(PointerEventList) result = _pointer_events; + _pointer_events = 0; + return result; } //////////////////////////////////////////////////////////////////// @@ -277,8 +277,14 @@ set_pointer(bool inwin, int x, int y, double time) { } if (_enable_pointer_events) { - int seq = _event_sequence ++; - _pointer_events.push_back(PointerEvent(_device_index, _mouse_data, seq, time)); + int seq = _event_sequence++; + if (_pointer_events == 0) { + _pointer_events = new PointerEventList(); + } + _pointer_events->add_event(_mouse_data._in_window, + _mouse_data._xpos, + _mouse_data._ypos, + seq, time); } } diff --git a/panda/src/display/graphicsWindowInputDevice.h b/panda/src/display/graphicsWindowInputDevice.h index c07e6c623a..3d2bf2e422 100644 --- a/panda/src/display/graphicsWindowInputDevice.h +++ b/panda/src/display/graphicsWindowInputDevice.h @@ -23,6 +23,7 @@ #include "buttonEvent.h" #include "pointerEvent.h" +#include "pointerEventList.h" #include "mouseData.h" #include "clockObject.h" @@ -69,7 +70,7 @@ public: bool has_button_event() const; ButtonEvent get_button_event(); bool has_pointer_event() const; - PointerEvent get_pointer_event(); + PT(PointerEventList) get_pointer_events(); public: // The following interface is for the various kinds of @@ -99,7 +100,6 @@ private: IDF_has_keyboard = 0x02 }; typedef pdeque ButtonEvents; - typedef pdeque PointerEvents; GraphicsWindow *_host; @@ -117,7 +117,7 @@ private: MouseData _mouse_data; MouseData _true_mouse_data; ButtonEvents _button_events; - PointerEvents _pointer_events; + PT(PointerEventList) _pointer_events; }; #include "graphicsWindowInputDevice.I" diff --git a/panda/src/event/config_event.cxx b/panda/src/event/config_event.cxx index 19e5c58e3b..1f4c363ec7 100644 --- a/panda/src/event/config_event.cxx +++ b/panda/src/event/config_event.cxx @@ -33,6 +33,7 @@ ConfigureFn(config_event) { AsyncTask::init_type(); AsyncTaskManager::init_type(); ButtonEventList::init_type(); + PointerEventList::init_type(); Event::init_type(); EventHandler::init_type(); EventStoreValueBase::init_type(); diff --git a/panda/src/event/pointerEvent.I b/panda/src/event/pointerEvent.I index 05dd326aee..89a5d5a305 100644 --- a/panda/src/event/pointerEvent.I +++ b/panda/src/event/pointerEvent.I @@ -24,26 +24,19 @@ //////////////////////////////////////////////////////////////////// INLINE PointerEvent:: PointerEvent() : - _device(-1), + _in_window(false), + _xpos(0), + _ypos(0), + _dx(0), + _dy(0), _sequence(0), + _length(0.0), + _direction(0.0), + _rotation(0.0), _time(0.0) { } -//////////////////////////////////////////////////////////////////// -// Function: PointerEvent::Constructor -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -INLINE PointerEvent:: -PointerEvent(int dev, const MouseData &data, int seq, double time) : - _device(dev), - _data(data), - _sequence(seq), - _time(time) -{ -} - //////////////////////////////////////////////////////////////////// // Function: PointerEvent::Copy Constructor // Access: Public @@ -51,9 +44,15 @@ PointerEvent(int dev, const MouseData &data, int seq, double time) : //////////////////////////////////////////////////////////////////// INLINE PointerEvent:: PointerEvent(const PointerEvent ©) : - _device(copy._device), - _data(copy._data), + _in_window(copy._in_window), + _xpos(copy._xpos), + _ypos(copy._ypos), + _dx(copy._dx), + _dy(copy._dy), _sequence(copy._sequence), + _length(copy._length), + _direction(copy._direction), + _rotation(copy._rotation), _time(copy._time) { } @@ -65,9 +64,15 @@ PointerEvent(const PointerEvent ©) : //////////////////////////////////////////////////////////////////// INLINE void PointerEvent:: operator = (const PointerEvent ©) { - _device = copy._device; - _data = copy._data; + _in_window = copy._in_window; + _xpos = copy._xpos; + _ypos = copy._ypos; + _dx = copy._dx; + _dy = copy._dy; _sequence = copy._sequence; + _length = copy._length; + _direction = copy._direction; + _rotation = copy._rotation; _time = copy._time; } @@ -79,11 +84,15 @@ operator = (const PointerEvent ©) { //////////////////////////////////////////////////////////////////// INLINE bool PointerEvent:: operator == (const PointerEvent &other) const { - return (_device == other._device && - _data._xpos == other._data._xpos && - _data._ypos == other._data._ypos && + return (_in_window == other._in_window && + _xpos == other._xpos && + _ypos == other._ypos && + _dx == other._dx && + _dy == other._dy && _sequence == other._sequence && - _data._in_window == other._data._in_window); + _length == other._length && + _direction == other._direction && + _rotation == other._rotation); } //////////////////////////////////////////////////////////////////// @@ -103,18 +112,30 @@ operator != (const PointerEvent &other) const { //////////////////////////////////////////////////////////////////// INLINE bool PointerEvent:: operator < (const PointerEvent &other) const { - if (_device != other._device) { - return _device < other._device; - } if (_sequence != other._sequence) { return _sequence < other._sequence; } - if (_data._xpos != other._data._xpos) { - return _data._xpos < other._data._xpos; + if (_xpos != other._xpos) { + return _xpos < other._xpos; } - if (_data._ypos != other._data._ypos) { - return _data._ypos < other._data._ypos; + if (_ypos != other._ypos) { + return _ypos < other._ypos; } - return _data._in_window < other._data._in_window; + if (_dx != other._dx) { + return _dx < other._dx; + } + if (_dy != other._dy) { + return _dy < other._dy; + } + if (_length != other._length) { + return _length < other._length; + } + if (_direction != other._direction) { + return _direction < other._direction; + } + if (_rotation != other._rotation) { + return _rotation < other._rotation; + } + return _in_window < other._in_window; } diff --git a/panda/src/event/pointerEvent.cxx b/panda/src/event/pointerEvent.cxx index c70d16dc3c..8efb5962db 100644 --- a/panda/src/event/pointerEvent.cxx +++ b/panda/src/event/pointerEvent.cxx @@ -27,8 +27,8 @@ //////////////////////////////////////////////////////////////////// void PointerEvent:: output(ostream &out) const { - out << (_data._in_window ? "In@" : "Out@") - << _data._xpos << "," << _data._ypos << " "; + out << (_in_window ? "In@" : "Out@") + << _xpos << "," << _ypos << " "; } //////////////////////////////////////////////////////////////////// @@ -38,11 +38,7 @@ output(ostream &out) const { //////////////////////////////////////////////////////////////////// void PointerEvent:: write_datagram(Datagram &dg) const { - dg.add_int8(_device); - dg.add_bool(_data._in_window); - dg.add_int32(_data._xpos); - dg.add_int32(_data._ypos); - dg.add_int32(_sequence); + nassertv(false && "This function not implemented yet."); } //////////////////////////////////////////////////////////////////// @@ -52,10 +48,5 @@ write_datagram(Datagram &dg) const { //////////////////////////////////////////////////////////////////// void PointerEvent:: read_datagram(DatagramIterator &scan) { - _device = scan.get_int8(); - _data._in_window = scan.get_bool(); - _data._xpos = scan.get_int32(); - _data._ypos = scan.get_int32(); - _sequence = scan.get_int32(); - _time = 0.0; + nassertv(false && "This function not implemented yet."); } diff --git a/panda/src/event/pointerEvent.h b/panda/src/event/pointerEvent.h index 7c208c1323..ef78bdcf2b 100644 --- a/panda/src/event/pointerEvent.h +++ b/panda/src/event/pointerEvent.h @@ -34,7 +34,6 @@ public: INLINE PointerEvent(); INLINE PointerEvent(const PointerEvent ©); - INLINE PointerEvent(int dev, const MouseData &data, int seq, double time); INLINE void operator = (const PointerEvent ©); INLINE bool operator == (const PointerEvent &other) const; @@ -47,8 +46,14 @@ public: void read_datagram(DatagramIterator &scan); public: - int _device; - MouseData _data; + bool _in_window; + int _xpos; + int _ypos; + int _dx; + int _dy; + double _length; + double _direction; + double _rotation; int _sequence; double _time; }; diff --git a/panda/src/event/pointerEventList.I b/panda/src/event/pointerEventList.I index 61a229cf24..f63ab83e16 100644 --- a/panda/src/event/pointerEventList.I +++ b/panda/src/event/pointerEventList.I @@ -47,16 +47,6 @@ operator = (const PointerEventList ©) { _events = copy._events; } -//////////////////////////////////////////////////////////////////// -// Function: PointerEventList::add_event -// Access: Public -// Description: Adds a new event to the end of the list. -//////////////////////////////////////////////////////////////////// -INLINE void PointerEventList:: -add_event(const PointerEvent &event) { - _events.push_back(event); -} - //////////////////////////////////////////////////////////////////// // Function: PointerEventList::get_num_events // Access: Published @@ -67,28 +57,6 @@ get_num_events() const { return _events.size(); } -//////////////////////////////////////////////////////////////////// -// Function: PointerEventList::get_x -// Access: Published -// Description: Get the x-coordinate of the nth event. -//////////////////////////////////////////////////////////////////// -INLINE int PointerEventList:: -get_x(int evt) const { - nassertr((evt >= 0) && (evt < (int)_events.size()), 0); - return _events[evt]._data._xpos; -} - -//////////////////////////////////////////////////////////////////// -// Function: PointerEventList::get_y -// Access: Published -// Description: Get the y-coordinate of the nth event. -//////////////////////////////////////////////////////////////////// -INLINE int PointerEventList:: -get_y(int evt) const { - nassertr((evt >= 0) && (evt < (int)_events.size()), 0); - return _events[evt]._data._ypos; -} - //////////////////////////////////////////////////////////////////// // Function: PointerEventList::get_in_window // Access: Published @@ -97,7 +65,84 @@ get_y(int evt) const { INLINE bool PointerEventList:: get_in_window(int evt) const { nassertr((evt >= 0) && (evt < (int)_events.size()), 0); - return _events[evt]._data._in_window; + return _events[evt]._in_window; +} + +//////////////////////////////////////////////////////////////////// +// Function: PointerEventList::get_xpos +// Access: Published +// Description: Get the x-coordinate of the nth event. +//////////////////////////////////////////////////////////////////// +INLINE int PointerEventList:: +get_xpos(int evt) const { + nassertr((evt >= 0) && (evt < (int)_events.size()), 0); + return _events[evt]._xpos; +} + +//////////////////////////////////////////////////////////////////// +// Function: PointerEventList::get_ypos +// Access: Published +// Description: Get the y-coordinate of the nth event. +//////////////////////////////////////////////////////////////////// +INLINE int PointerEventList:: +get_ypos(int evt) const { + nassertr((evt >= 0) && (evt < (int)_events.size()), 0); + return _events[evt]._ypos; +} + +//////////////////////////////////////////////////////////////////// +// Function: PointerEventList::get_dx +// Access: Published +// Description: Get the x-coordinate of the nth event. +//////////////////////////////////////////////////////////////////// +INLINE int PointerEventList:: +get_dx(int evt) const { + nassertr((evt >= 0) && (evt < (int)_events.size()), 0); + return _events[evt]._dx; +} + +//////////////////////////////////////////////////////////////////// +// Function: PointerEventList::get_dy +// Access: Published +// Description: Get the y-coordinate of the nth event. +//////////////////////////////////////////////////////////////////// +INLINE int PointerEventList:: +get_dy(int evt) const { + nassertr((evt >= 0) && (evt < (int)_events.size()), 0); + return _events[evt]._dy; +} + +//////////////////////////////////////////////////////////////////// +// Function: PointerEventList::get_length +// Access: Published +// Description: Get the length of the nth event. +//////////////////////////////////////////////////////////////////// +INLINE double PointerEventList:: +get_length(int evt) const { + nassertr((evt >= 0) && (evt < (int)_events.size()), 0); + return _events[evt]._length; +} + +//////////////////////////////////////////////////////////////////// +// Function: PointerEventList::get_direction +// Access: Published +// Description: Get the direction of the nth event. +//////////////////////////////////////////////////////////////////// +INLINE double PointerEventList:: +get_direction(int evt) const { + nassertr((evt >= 0) && (evt < (int)_events.size()), 0); + return _events[evt]._direction; +} + +//////////////////////////////////////////////////////////////////// +// Function: PointerEventList::get_rotation +// Access: Published +// Description: Get the rotation of the nth event. +//////////////////////////////////////////////////////////////////// +INLINE double PointerEventList:: +get_rotation(int evt) const { + nassertr((evt >= 0) && (evt < (int)_events.size()), 0); + return _events[evt]._rotation; } //////////////////////////////////////////////////////////////////// @@ -122,23 +167,6 @@ get_time(int evt) const { return _events[evt]._time; } -//////////////////////////////////////////////////////////////////// -// Function: PointerEventList::get_event -// Access: Public -// Description: Returns the nth event in the list. This does not -// remove the event from the list; the only way to -// remove events is to empty the whole list with -// clear(). -//////////////////////////////////////////////////////////////////// -INLINE const PointerEvent &PointerEventList:: -get_event(int n) const { -#ifndef NDEBUG - static PointerEvent empty_event; - nassertr(n >= 0 && n < (int)_events.size(), empty_event); -#endif // NDEBUG - return _events[n]; -} - //////////////////////////////////////////////////////////////////// // Function: PointerEventList::clear // Access: Public diff --git a/panda/src/event/pointerEventList.cxx b/panda/src/event/pointerEventList.cxx index 392cfaae6f..529006dc64 100644 --- a/panda/src/event/pointerEventList.cxx +++ b/panda/src/event/pointerEventList.cxx @@ -18,23 +18,12 @@ #include "pointerEventList.h" #include "indent.h" +#include "clockObject.h" +#define _USE_MATH_DEFINES +#include TypeHandle PointerEventList::_type_handle; -//////////////////////////////////////////////////////////////////// -// Function: PointerEventList::add_events -// Access: Public -// Description: Appends the events from the other list onto the end -// of this one. -//////////////////////////////////////////////////////////////////// -void PointerEventList:: -add_events(const PointerEventList &other) { - Events::const_iterator ei; - for (ei = other._events.begin(); ei != other._events.end(); ++ei) { - _events.push_back(*ei); - } -} - //////////////////////////////////////////////////////////////////// // Function: PointerEventList::output // Access: Public, Virtual @@ -72,74 +61,98 @@ write(ostream &out, int indent_level) const { } //////////////////////////////////////////////////////////////////// -// Function: PointerEventList::register_with_read_factory -// Access: Public, Static -// Description: Tells the BamReader how to create objects of type -// Lens. +// Function: PointerEventList::add_event +// Access: Published +// Description: Adds a new event to the end of the list. +// Automatically calculates the dx, dy, length, +// direction, and rotation for all but the first event. //////////////////////////////////////////////////////////////////// -void PointerEventList:: -register_with_read_factory() { - BamReader::get_factory()->register_factory(get_class_type(), make_from_bam); -} - -//////////////////////////////////////////////////////////////////// -// Function: PointerEventList::write_datagram -// Access: Public, Virtual -// Description: Writes the contents of this object to the datagram -// for shipping out to a Bam file. -//////////////////////////////////////////////////////////////////// -void PointerEventList:: -write_datagram(BamWriter *manager, Datagram &dg) { - TypedWritable::write_datagram(manager, dg); - - dg.add_uint16(_events.size()); - Events::const_iterator ei; - for (ei = _events.begin(); ei != _events.end(); ++ei) { - (*ei).write_datagram(dg); +INLINE void PointerEventList:: +add_event(bool in_win, int xpos, int ypos, int seq, double time) { + PointerEvent pe; + pe._in_window = in_win; + pe._xpos = xpos; + pe._ypos = ypos; + pe._sequence = seq; + pe._time = time; + if (_events.size() > 0) { + pe._dx = xpos - _events.back()._xpos; + pe._dy = ypos - _events.back()._ypos; + double ddx = pe._dx; + double ddy = pe._dy; + pe._length = sqrt(ddx*ddx + ddy*ddy); + if (pe._length > 0.0) { + pe._direction = atan2(-ddy,ddx) * (180.0 / M_PI); + if (pe._direction < 0.0) pe._direction += 360.0; + } else { + pe._direction = _events.back()._direction; + } + pe._rotation = pe._direction - _events.back()._direction; + if (pe._rotation > 180.0) pe._rotation -= 360.0; + if (pe._rotation < -180.0) pe._rotation += 360.0; + } else { + pe._dx = 0; + pe._dy = 0; + pe._length = 0.0; + pe._direction = 0.0; + pe._rotation = 0.0; } -} + _events.push_back(pe); +} //////////////////////////////////////////////////////////////////// -// Function: PointerEventList::make_from_bam -// Access: Protected, Static -// Description: This function is called by the BamReader's factory -// when a new object of type Lens is encountered -// in the Bam file. It should create the Lens -// and extract its information from the file. +// Function: PointerEventList::encircles +// Access: Published +// Description: Returns true if the trail loops around the +// specified point. //////////////////////////////////////////////////////////////////// -TypedWritable *PointerEventList:: -make_from_bam(const FactoryParams ¶ms) { - PointerEventList *list = new PointerEventList; - DatagramIterator scan; - BamReader *manager; - - parse_params(params, scan, manager); - list->fillin(scan, manager); - - return list; -} - -//////////////////////////////////////////////////////////////////// -// Function: PointerEventList::fillin -// Access: Public -// Description: This internal function is called by make_from_bam to -// read in all of the relevant data from the BamFile for -// the new PointerEventList. -// -// This function is normally protected, but it is -// declared public in this case so that MouseRecorder -// may call it to read a PointerEventList from the middle -// of a datagram. -//////////////////////////////////////////////////////////////////// -void PointerEventList:: -fillin(DatagramIterator &scan, BamReader *manager) { - TypedWritable::fillin(scan, manager); - - int num_events = scan.get_uint16(); - _events.clear(); - for (int i = 0; i < num_events; i++) { - PointerEvent event; - event.read_datagram(scan); - _events.push_back(event); +bool PointerEventList:: +encircles(int x, int y) const { + int tot_events = _events.size(); + if (tot_events < 3) { + return false; } + double dx = _events[0]._xpos - x; + double dy = _events[0]._ypos - y; + double lastang = atan2(dy, dx) * (180.0/M_PI); + double total = 0.0; + for (int i=1; (i -360.0); i++) { + dx = _events[i]._xpos - x; + dy = _events[i]._ypos - y; + if ((dx==0.0)&&(dy==0.0)) { + continue; + } + double angle = atan2(dy,dx) * (180.0/M_PI); + double deltang = angle - lastang; + if (deltang < -180.0) deltang += 360.0; + if (deltang > 180.0) deltang -= 360.0; + if (deltang * total < 0.0) { + total = 0.0; + } + total += deltang; + lastang = angle; + } + return (total > 360.0) || (total < -360.0); +} + +//////////////////////////////////////////////////////////////////// +// Function: PointerEventList::total_turns +// Access: Published +// Description: returns the total angular deviation that the trail +// has made in the specified time period. A small +// number means that the trail is moving in a relatively +// straight line, a large number means that the trail +// is zig-zagging or spinning. The result is in degrees. +//////////////////////////////////////////////////////////////////// +double PointerEventList:: +total_turns(double sec) const { + double old = ClockObject::get_global_clock()->get_frame_time() - sec; + int pos = _events.size()-1; + double tot = 0.0; + while ((pos >= 0)&&(_events[pos]._time >= old)) { + double rot = _events[pos]._rotation; + if (rot < 0.0) rot = -rot; + tot += rot; + } + return tot; } diff --git a/panda/src/event/pointerEventList.h b/panda/src/event/pointerEventList.h index fd04de15d0..253b02ef50 100644 --- a/panda/src/event/pointerEventList.h +++ b/panda/src/event/pointerEventList.h @@ -40,25 +40,32 @@ class DatagramIterator; //////////////////////////////////////////////////////////////////// class EXPCL_PANDA_EVENT PointerEventList : public EventStoreValueBase { PUBLISHED: + INLINE PointerEventList(); + INLINE int get_num_events() const; - INLINE int get_x(int n) const; - INLINE int get_y(int n) const; INLINE bool get_in_window(int n) const; + INLINE int get_xpos(int n) const; + INLINE int get_ypos(int n) const; + INLINE int get_dx(int n) const; + INLINE int get_dy(int n) const; INLINE int get_sequence(int n) const; + INLINE double get_length(int n) const; + INLINE double get_direction(int n) const; + INLINE double get_rotation(int n) const; INLINE double get_time(int n) const; + + INLINE void clear(); + INLINE void pop_front(); + INLINE void add_event(bool in_win, int xpos, int ypos, int seq, double time); + + INLINE bool encircles(int x, int y) const; + INLINE double total_turns(double sec) const; public: - INLINE PointerEventList(); INLINE PointerEventList(const PointerEventList ©); INLINE void operator = (const PointerEventList ©); - INLINE void add_event(const PointerEvent &event); - INLINE const PointerEvent &get_event(int n) const; - INLINE void clear(); - INLINE void pop_front(); - void add_events(const PointerEventList &other); - virtual void output(ostream &out) const; void write(ostream &out, int indent_level = 0) const; @@ -66,16 +73,6 @@ private: typedef pdeque Events; Events _events; -public: - static void register_with_read_factory(); - virtual void write_datagram(BamWriter *manager, Datagram &dg); - -protected: - static TypedWritable *make_from_bam(const FactoryParams ¶ms); - -public: - void fillin(DatagramIterator &scan, BamReader *manager); - public: static TypeHandle get_class_type() { return _type_handle; diff --git a/panda/src/tform/mouseWatcher.I b/panda/src/tform/mouseWatcher.I index 3108bf61e7..9f82d2413f 100644 --- a/panda/src/tform/mouseWatcher.I +++ b/panda/src/tform/mouseWatcher.I @@ -620,6 +620,17 @@ without_region(MouseWatcherRegion *region, const MouseWatcherParameter ¶m) { throw_event_pattern(_without_pattern, region, ButtonHandle::none()); } +//////////////////////////////////////////////////////////////////// +// Function: MouseWatcher::clear_trail_log +// Access: Published +// Description: Clears the mouse trail log. This does not prevent +// further accumulation of the log given future events. +//////////////////////////////////////////////////////////////////// +INLINE void MouseWatcher:: +clear_trail_log() { + _trail_log->clear(); +} + //////////////////////////////////////////////////////////////////// // Function: MouseWatcher::get_trail_log // Access: Published diff --git a/panda/src/tform/mouseWatcher.cxx b/panda/src/tform/mouseWatcher.cxx index fe4ca15500..a92f94cbbf 100644 --- a/panda/src/tform/mouseWatcher.cxx +++ b/panda/src/tform/mouseWatcher.cxx @@ -377,7 +377,8 @@ set_trail_log_duration(double duration) { // desired log duration. Keeps one event that is beyond // the specified age, because otherwise, it is not always // possible to determine where the mouse was for the -// full logging duration. If the duration is zero, this +// full logging duration. Also, keeps a minimum of two +// events in the queue. If the duration is zero, this // method discards all trail events. //////////////////////////////////////////////////////////////////// void MouseWatcher:: @@ -385,9 +386,9 @@ discard_excess_trail_log() { if (_trail_log_duration == 0.0) { _trail_log->clear(); } else { - if (_trail_log->get_num_events() >= 2) { + if (_trail_log->get_num_events() > 2) { double old = ClockObject::get_global_clock()->get_frame_time() - _trail_log_duration; - while ((_trail_log->get_num_events() >= 2)&& + while ((_trail_log->get_num_events() > 2)&& (_trail_log->get_time(0) <= old)&& (_trail_log->get_time(1) <= old)) { _trail_log->pop_front(); @@ -463,8 +464,8 @@ update_trail_node() { double yscale = 2.0 / _pixel_size->get_value().get_y(); for (int i=0; i<(int)_trail_log->get_num_events(); i++) { - double x = (_trail_log->get_x(i) * xscale) - 1.0; - double y = (_trail_log->get_y(i) * yscale) - 1.0; + double x = (_trail_log->get_xpos(i) * xscale) - 1.0; + double y = (_trail_log->get_ypos(i) * yscale) - 1.0; vertex.add_data3f(LVecBase3f(x,0.0,-y)); lines->add_vertex(i); } @@ -1449,7 +1450,12 @@ do_transmit_data(DataGraphTraverser *trav, const DataNodeTransmit &input, DCAST_INTO_V(this_pointer_events, input.get_data(_pointer_events_input).get_ptr()); _num_trail_recent = this_pointer_events->get_num_events(); for (int i = 0; i < _num_trail_recent; i++) { - _trail_log->add_event(this_pointer_events->get_event(i)); + bool in_win = this_pointer_events->get_in_window(i); + int xpos = this_pointer_events->get_xpos(i); + int ypos = this_pointer_events->get_ypos(i); + int sequence = this_pointer_events->get_sequence(i); + double time = this_pointer_events->get_time(i); + _trail_log->add_event(in_win, xpos, ypos, sequence, time); } } if (_trail_log->get_num_events() > 0) { diff --git a/panda/src/tform/mouseWatcher.h b/panda/src/tform/mouseWatcher.h index 82bc5898d5..1f792caaf5 100644 --- a/panda/src/tform/mouseWatcher.h +++ b/panda/src/tform/mouseWatcher.h @@ -148,6 +148,7 @@ PUBLISHED: void set_trail_log_duration(double duration); PT(GeomNode) get_trail_node(); void clear_trail_node(); + INLINE void clear_trail_log(); void note_activity();