Browse Source

Improvements to mouse-trail tracking

Josh Yelon 18 years ago
parent
commit
942769b672

+ 3 - 9
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));
   _pixel_size = new EventStoreVec2(LPoint2f(0.0f, 0.0f));
   _xy = new EventStoreVec2(LPoint2f(0.0f, 0.0f));
   _xy = new EventStoreVec2(LPoint2f(0.0f, 0.0f));
   _button_events = new ButtonEventList;
   _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));
     output.set_data(_button_events_output, EventParameter(_button_events));
   }
   }
   if (_window->has_pointer_event(_device)) {
   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.
   // Get the window size.
   WindowProperties properties = _window->get_properties();
   WindowProperties properties = _window->get_properties();
   if (properties.has_size()) {
   if (properties.has_size()) {

+ 0 - 1
panda/src/device/mouseAndKeyboard.h

@@ -75,7 +75,6 @@ private:
   PT(EventStoreVec2) _pixel_size;
   PT(EventStoreVec2) _pixel_size;
   PT(EventStoreVec2) _xy;
   PT(EventStoreVec2) _xy;
   PT(ButtonEventList) _button_events;
   PT(ButtonEventList) _button_events;
-  PT(PointerEventList) _pointer_events;
 
 
   PT(GraphicsWindow) _window;
   PT(GraphicsWindow) _window;
   int _device;
   int _device;

+ 9 - 9
panda/src/display/graphicsWindow.cxx

@@ -472,7 +472,7 @@ get_button_event(int device) {
 //  Description: Returns true if the indicated device has a pending
 //  Description: Returns true if the indicated device has a pending
 //               pointer event (a mouse movement).  If this returns
 //               pointer event (a mouse movement).  If this returns
 //               true, the particular event may be extracted via
 //               true, the particular event may be extracted via
-//               get_pointer_event().
+//               get_pointer_events().
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 bool GraphicsWindow::
 bool GraphicsWindow::
 has_pointer_event(int device) const {
 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
 //       Access: Public
 //  Description: Assuming a previous call to has_pointer_event()
 //  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);
     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;
   return result;
 }
 }

+ 1 - 1
panda/src/display/graphicsWindow.h

@@ -87,7 +87,7 @@ public:
   bool has_button_event(int device) const;
   bool has_button_event(int device) const;
   ButtonEvent get_button_event(int device);
   ButtonEvent get_button_event(int device);
   bool has_pointer_event(int device) const;
   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);
   virtual int verify_window_sizes(int numsizes, int *dimen);
 
 

+ 18 - 12
panda/src/display/graphicsWindowInputDevice.cxx

@@ -186,20 +186,20 @@ get_button_event() {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 bool GraphicsWindowInputDevice::
 bool GraphicsWindowInputDevice::
 has_pointer_event() const {
 has_pointer_event() const {
-  return !_pointer_events.empty();
+  return (_pointer_events != 0);
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: GraphicsWindowInputDevice::get_pointer_event
+//     Function: GraphicsWindowInputDevice::get_pointer_events
 //       Access: Public
 //       Access: Public
-//  Description: Assuming a previous call to has_pointer_event()
-//               returned true, this returns the pending pointer event.
-////////////////////////////////////////////////////////////////////
-PointerEvent GraphicsWindowInputDevice::
-get_pointer_event() {
-  PointerEvent be = _pointer_events.front();
-  _pointer_events.pop_front();
-  return be;
+//  Description: Returns a PointerEventList containing all the recent
+//               pointer events.
+////////////////////////////////////////////////////////////////////
+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) {
   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);
   }
   }
 }
 }
 
 

+ 3 - 3
panda/src/display/graphicsWindowInputDevice.h

@@ -23,6 +23,7 @@
 
 
 #include "buttonEvent.h"
 #include "buttonEvent.h"
 #include "pointerEvent.h"
 #include "pointerEvent.h"
+#include "pointerEventList.h"
 #include "mouseData.h"
 #include "mouseData.h"
 #include "clockObject.h"
 #include "clockObject.h"
 
 
@@ -69,7 +70,7 @@ public:
   bool has_button_event() const;
   bool has_button_event() const;
   ButtonEvent get_button_event();
   ButtonEvent get_button_event();
   bool has_pointer_event() const;
   bool has_pointer_event() const;
-  PointerEvent get_pointer_event();
+  PT(PointerEventList) get_pointer_events();
 
 
 public:
 public:
   // The following interface is for the various kinds of
   // The following interface is for the various kinds of
@@ -99,7 +100,6 @@ private:
     IDF_has_keyboard   = 0x02
     IDF_has_keyboard   = 0x02
   };
   };
   typedef pdeque<ButtonEvent> ButtonEvents;
   typedef pdeque<ButtonEvent> ButtonEvents;
-  typedef pdeque<PointerEvent> PointerEvents;
   
   
   GraphicsWindow *_host;
   GraphicsWindow *_host;
   
   
@@ -117,7 +117,7 @@ private:
   MouseData _mouse_data;
   MouseData _mouse_data;
   MouseData _true_mouse_data;
   MouseData _true_mouse_data;
   ButtonEvents _button_events;
   ButtonEvents _button_events;
-  PointerEvents _pointer_events;
+  PT(PointerEventList) _pointer_events;
 };
 };
 
 
 #include "graphicsWindowInputDevice.I"
 #include "graphicsWindowInputDevice.I"

+ 1 - 0
panda/src/event/config_event.cxx

@@ -33,6 +33,7 @@ ConfigureFn(config_event) {
   AsyncTask::init_type();
   AsyncTask::init_type();
   AsyncTaskManager::init_type();
   AsyncTaskManager::init_type();
   ButtonEventList::init_type();
   ButtonEventList::init_type();
+  PointerEventList::init_type();
   Event::init_type();
   Event::init_type();
   EventHandler::init_type();
   EventHandler::init_type();
   EventStoreValueBase::init_type();
   EventStoreValueBase::init_type();

+ 52 - 31
panda/src/event/pointerEvent.I

@@ -24,26 +24,19 @@
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE PointerEvent::
 INLINE PointerEvent::
 PointerEvent() :
 PointerEvent() :
-  _device(-1),
+  _in_window(false),
+  _xpos(0),
+  _ypos(0),
+  _dx(0),
+  _dy(0),
   _sequence(0),
   _sequence(0),
+  _length(0.0),
+  _direction(0.0),
+  _rotation(0.0),
   _time(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
 //     Function: PointerEvent::Copy Constructor
 //       Access: Public
 //       Access: Public
@@ -51,9 +44,15 @@ PointerEvent(int dev, const MouseData &data, int seq, double time) :
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE PointerEvent::
 INLINE PointerEvent::
 PointerEvent(const PointerEvent &copy) :
 PointerEvent(const PointerEvent &copy) :
-  _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),
   _sequence(copy._sequence),
+  _length(copy._length),
+  _direction(copy._direction),
+  _rotation(copy._rotation),
   _time(copy._time)
   _time(copy._time)
 {
 {
 }
 }
@@ -65,9 +64,15 @@ PointerEvent(const PointerEvent &copy) :
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE void PointerEvent::
 INLINE void PointerEvent::
 operator = (const PointerEvent &copy) {
 operator = (const PointerEvent &copy) {
-  _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;
   _sequence = copy._sequence;
+  _length = copy._length;
+  _direction = copy._direction;
+  _rotation = copy._rotation;
   _time = copy._time;
   _time = copy._time;
 }
 }
 
 
@@ -79,11 +84,15 @@ operator = (const PointerEvent &copy) {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE bool PointerEvent::
 INLINE bool PointerEvent::
 operator == (const PointerEvent &other) const {
 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 &&
           _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::
 INLINE bool PointerEvent::
 operator < (const PointerEvent &other) const {
 operator < (const PointerEvent &other) const {
-  if (_device != other._device) {
-    return _device < other._device;
-  }
   if (_sequence != other._sequence) {
   if (_sequence != other._sequence) {
     return _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 (_ypos != other._ypos) {
+    return _ypos < other._ypos;
+  }
+  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 (_data._ypos != other._data._ypos) {
-    return _data._ypos < other._data._ypos;
+  if (_rotation != other._rotation) {
+    return _rotation < other._rotation;
   }
   }
-  return _data._in_window < other._data._in_window;
+  return _in_window < other._in_window;
 }
 }
 
 

+ 4 - 13
panda/src/event/pointerEvent.cxx

@@ -27,8 +27,8 @@
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void PointerEvent::
 void PointerEvent::
 output(ostream &out) const {
 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::
 void PointerEvent::
 write_datagram(Datagram &dg) const {
 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::
 void PointerEvent::
 read_datagram(DatagramIterator &scan) {
 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.");
 }
 }

+ 8 - 3
panda/src/event/pointerEvent.h

@@ -34,7 +34,6 @@ public:
 
 
   INLINE PointerEvent();
   INLINE PointerEvent();
   INLINE PointerEvent(const PointerEvent &copy);
   INLINE PointerEvent(const PointerEvent &copy);
-  INLINE PointerEvent(int dev, const MouseData &data, int seq, double time);
   INLINE void operator = (const PointerEvent &copy);
   INLINE void operator = (const PointerEvent &copy);
 
 
   INLINE bool operator == (const PointerEvent &other) const;
   INLINE bool operator == (const PointerEvent &other) const;
@@ -47,8 +46,14 @@ public:
   void read_datagram(DatagramIterator &scan);
   void read_datagram(DatagramIterator &scan);
 
 
 public:
 public:
-  int       _device;
-  MouseData _data;
+  bool      _in_window;
+  int       _xpos;
+  int       _ypos;
+  int       _dx;
+  int       _dy;
+  double    _length;
+  double    _direction;
+  double    _rotation;
   int       _sequence;
   int       _sequence;
   double    _time;
   double    _time;
 };
 };

+ 66 - 38
panda/src/event/pointerEventList.I

@@ -47,16 +47,6 @@ operator = (const PointerEventList &copy) {
   _events = copy._events;
   _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
 //     Function: PointerEventList::get_num_events
 //       Access: Published
 //       Access: Published
@@ -68,36 +58,91 @@ get_num_events() const {
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: PointerEventList::get_x
+//     Function: PointerEventList::get_in_window
+//       Access: Published
+//  Description: Get the in-window flag of the nth event.
+////////////////////////////////////////////////////////////////////
+INLINE bool PointerEventList::
+get_in_window(int evt) const {
+  nassertr((evt >= 0) && (evt < (int)_events.size()), 0);
+  return _events[evt]._in_window;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PointerEventList::get_xpos
 //       Access: Published
 //       Access: Published
 //  Description: Get the x-coordinate of the nth event.
 //  Description: Get the x-coordinate of the nth event.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE int PointerEventList::
 INLINE int PointerEventList::
-get_x(int evt) const {
+get_xpos(int evt) const {
   nassertr((evt >= 0) && (evt < (int)_events.size()), 0);
   nassertr((evt >= 0) && (evt < (int)_events.size()), 0);
-  return _events[evt]._data._xpos;
+  return _events[evt]._xpos;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: PointerEventList::get_y
+//     Function: PointerEventList::get_ypos
 //       Access: Published
 //       Access: Published
 //  Description: Get the y-coordinate of the nth event.
 //  Description: Get the y-coordinate of the nth event.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE int PointerEventList::
 INLINE int PointerEventList::
-get_y(int evt) const {
+get_ypos(int evt) const {
   nassertr((evt >= 0) && (evt < (int)_events.size()), 0);
   nassertr((evt >= 0) && (evt < (int)_events.size()), 0);
-  return _events[evt]._data._ypos;
+  return _events[evt]._ypos;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: PointerEventList::get_in_window
+//     Function: PointerEventList::get_dx
 //       Access: Published
 //       Access: Published
-//  Description: Get the in-window flag of the nth event.
+//  Description: Get the x-coordinate of the nth event.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-INLINE bool PointerEventList::
-get_in_window(int evt) const {
+INLINE int PointerEventList::
+get_dx(int evt) const {
   nassertr((evt >= 0) && (evt < (int)_events.size()), 0);
   nassertr((evt >= 0) && (evt < (int)_events.size()), 0);
-  return _events[evt]._data._in_window;
+  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;
   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
 //     Function: PointerEventList::clear
 //       Access: Public
 //       Access: Public

+ 89 - 76
panda/src/event/pointerEventList.cxx

@@ -18,23 +18,12 @@
 
 
 #include "pointerEventList.h"
 #include "pointerEventList.h"
 #include "indent.h"
 #include "indent.h"
+#include "clockObject.h"
+#define _USE_MATH_DEFINES
+#include <math.h>
 
 
 TypeHandle PointerEventList::_type_handle;
 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
 //     Function: PointerEventList::output
 //       Access: Public, Virtual
 //       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.
-////////////////////////////////////////////////////////////////////
-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);
+//     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.
+////////////////////////////////////////////////////////////////////
+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 &params) {
-  PointerEventList *list = new PointerEventList;
-  DatagramIterator scan;
-  BamReader *manager;
-
-  parse_params(params, scan, manager);
-  list->fillin(scan, manager);
-
-  return list;
+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<tot_events) && (total < 360.0) && (total > -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::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);
+//     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;
 }
 }

+ 16 - 19
panda/src/event/pointerEventList.h

@@ -40,25 +40,32 @@ class DatagramIterator;
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 class EXPCL_PANDA_EVENT PointerEventList : public EventStoreValueBase {
 class EXPCL_PANDA_EVENT PointerEventList : public EventStoreValueBase {
 PUBLISHED:
 PUBLISHED:
+  INLINE PointerEventList();
+
   INLINE int get_num_events() const;
   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 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 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 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:
 public:
-  INLINE PointerEventList();
   INLINE PointerEventList(const PointerEventList &copy);
   INLINE PointerEventList(const PointerEventList &copy);
   INLINE void operator = (const PointerEventList &copy);
   INLINE void operator = (const PointerEventList &copy);
 
 
-  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;
   virtual void output(ostream &out) const;
   void write(ostream &out, int indent_level = 0) const;
   void write(ostream &out, int indent_level = 0) const;
 
 
@@ -66,16 +73,6 @@ private:
   typedef pdeque<PointerEvent> Events;
   typedef pdeque<PointerEvent> Events;
   Events _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 &params);
-
-public:
-  void fillin(DatagramIterator &scan, BamReader *manager);
-  
 public:
 public:
   static TypeHandle get_class_type() {
   static TypeHandle get_class_type() {
     return _type_handle;
     return _type_handle;

+ 11 - 0
panda/src/tform/mouseWatcher.I

@@ -620,6 +620,17 @@ without_region(MouseWatcherRegion *region, const MouseWatcherParameter &param) {
   throw_event_pattern(_without_pattern, region, ButtonHandle::none());
   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
 //     Function: MouseWatcher::get_trail_log
 //       Access: Published
 //       Access: Published

+ 12 - 6
panda/src/tform/mouseWatcher.cxx

@@ -377,7 +377,8 @@ set_trail_log_duration(double duration) {
 //               desired log duration.  Keeps one event that is beyond
 //               desired log duration.  Keeps one event that is beyond
 //               the specified age, because otherwise, it is not always
 //               the specified age, because otherwise, it is not always
 //               possible to determine where the mouse was for the
 //               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.
 //               method discards all trail events.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void MouseWatcher::
 void MouseWatcher::
@@ -385,9 +386,9 @@ discard_excess_trail_log() {
   if (_trail_log_duration == 0.0) {
   if (_trail_log_duration == 0.0) {
     _trail_log->clear();
     _trail_log->clear();
   } else {
   } 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;
       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(0) <= old)&&
              (_trail_log->get_time(1) <= old)) {
              (_trail_log->get_time(1) <= old)) {
         _trail_log->pop_front();
         _trail_log->pop_front();
@@ -463,8 +464,8 @@ update_trail_node() {
   double yscale = 2.0 / _pixel_size->get_value().get_y();
   double yscale = 2.0 / _pixel_size->get_value().get_y();
   
   
   for (int i=0; i<(int)_trail_log->get_num_events(); i++) {
   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));
     vertex.add_data3f(LVecBase3f(x,0.0,-y));
     lines->add_vertex(i);
     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());
     DCAST_INTO_V(this_pointer_events, input.get_data(_pointer_events_input).get_ptr());
     _num_trail_recent = this_pointer_events->get_num_events();
     _num_trail_recent = this_pointer_events->get_num_events();
     for (int i = 0; i < _num_trail_recent; i++) {
     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) {
   if (_trail_log->get_num_events() > 0) {

+ 1 - 0
panda/src/tform/mouseWatcher.h

@@ -148,6 +148,7 @@ PUBLISHED:
   void         set_trail_log_duration(double duration);
   void         set_trail_log_duration(double duration);
   PT(GeomNode) get_trail_node();
   PT(GeomNode) get_trail_node();
   void         clear_trail_node();
   void         clear_trail_node();
+  INLINE void  clear_trail_log();
   
   
   void note_activity();
   void note_activity();