// Filename: mouseWatcher.I // Created by: drose (12Mar02) // //////////////////////////////////////////////////////////////////// // // PANDA 3D SOFTWARE // Copyright (c) Carnegie Mellon University. All rights reserved. // // All use of this software is subject to the terms of the revised BSD // license. You should have received a copy of this license along // with this source code in a file named "LICENSE." // //////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////// // Function: MouseWatcher::has_mouse // Access: Published // Description: Returns true if the mouse is anywhere within the // window, false otherwise. Also see is_mouse_open(). //////////////////////////////////////////////////////////////////// INLINE bool MouseWatcher:: has_mouse() const { return _has_mouse; } //////////////////////////////////////////////////////////////////// // Function: MouseWatcher::is_mouse_open // Access: Published // Description: Returns true if the mouse is within the window and // not over some particular MouseWatcherRegion that is // marked to suppress mouse events; that is, that the // mouse is in open space within the window. //////////////////////////////////////////////////////////////////// INLINE bool MouseWatcher:: is_mouse_open() const { return _has_mouse && (_internal_suppress & MouseWatcherRegion::SF_mouse_position) == 0; } //////////////////////////////////////////////////////////////////// // Function: MouseWatcher::get_mouse // Access: Published // Description: It is only valid to call this if has_mouse() returns // true. If so, this returns the current position of // the mouse within the window. //////////////////////////////////////////////////////////////////// INLINE const LPoint2f &MouseWatcher:: get_mouse() const { #ifndef NDEBUG static LPoint2f bogus_mouse(0.0f, 0.0f); nassertr(_has_mouse, bogus_mouse); #endif return _mouse; } //////////////////////////////////////////////////////////////////// // Function: MouseWatcher::get_mouse_x // Access: Published // Description: It is only valid to call this if has_mouse() returns // true. If so, this returns the current X position of // the mouse within the window. //////////////////////////////////////////////////////////////////// INLINE float MouseWatcher:: get_mouse_x() const { nassertr(_has_mouse, 0.0f); return _mouse[0]; } //////////////////////////////////////////////////////////////////// // Function: MouseWatcher::get_mouse_y // Access: Published // Description: It is only valid to call this if has_mouse() returns // true. If so, this returns the current Y position of // the mouse within the window. //////////////////////////////////////////////////////////////////// INLINE float MouseWatcher:: get_mouse_y() const { nassertr(_has_mouse, 0.0f); return _mouse[1]; } //////////////////////////////////////////////////////////////////// // Function: MouseWatcher::set_frame // Access: Published // Description: Sets the frame of the MouseWatcher. See the next // flavor of this method for a more verbose explanation. //////////////////////////////////////////////////////////////////// INLINE void MouseWatcher:: set_frame(float left, float right, float bottom, float top) { set_frame(LVecBase4f(left, right, bottom, top)); } //////////////////////////////////////////////////////////////////// // Function: MouseWatcher::set_frame // Access: Published // Description: Sets the frame of the MouseWatcher. This determines // the coordinate space in which the MouseWatcherRegions // should be expected to live. Normally, this is left // at -1, 1, -1, 1, which is the default setting, and // matches the mouse coordinate range. // // Whatever values you specify here indicate the shape // of the full screen, and the MouseWatcherRegions will // be given in coordinate space matching it. For // instance, if you specify (0, 1, 0, 1), then a // MouseWatcherRegion with the frame (0, 1, 0, .5) will // cover the lower half of the screen. //////////////////////////////////////////////////////////////////// INLINE void MouseWatcher:: set_frame(const LVecBase4f &frame) { _frame = frame; } //////////////////////////////////////////////////////////////////// // Function: MouseWatcher::get_frame // Access: Published // Description: Returns the frame of the MouseWatcher. See // set_frame(). //////////////////////////////////////////////////////////////////// INLINE const LVecBase4f &MouseWatcher:: get_frame() const { return _frame; } //////////////////////////////////////////////////////////////////// // Function: MouseWatcher::is_over_region // Access: Published // Description: Returns true if the mouse is over any rectangular // region, false otherwise. //////////////////////////////////////////////////////////////////// INLINE bool MouseWatcher:: is_over_region() const { return get_over_region() != (MouseWatcherRegion *)NULL; } //////////////////////////////////////////////////////////////////// // Function: MouseWatcher::is_over_region // Access: Published // Description: Returns true if the mouse is over any rectangular // region, false otherwise. //////////////////////////////////////////////////////////////////// INLINE bool MouseWatcher:: is_over_region(float x, float y) const { return get_over_region(x, y) != (MouseWatcherRegion *)NULL; } //////////////////////////////////////////////////////////////////// // Function: MouseWatcher::is_over_region // Access: Published // Description: Returns true if the mouse is over any rectangular // region, false otherwise. //////////////////////////////////////////////////////////////////// INLINE bool MouseWatcher:: is_over_region(const LPoint2f &pos) const { return get_over_region(pos) != (MouseWatcherRegion *)NULL; } //////////////////////////////////////////////////////////////////// // Function: MouseWatcher::get_over_region // Access: Published // Description: Returns the smallest region the mouse is currently // over, or NULL if it is over no region. //////////////////////////////////////////////////////////////////// INLINE MouseWatcherRegion *MouseWatcher:: get_over_region() const { return _preferred_region; } //////////////////////////////////////////////////////////////////// // Function: MouseWatcher::get_over_region // Access: Published // Description: Returns the smallest region the indicated point is // over, or NULL if it is over no region. //////////////////////////////////////////////////////////////////// INLINE MouseWatcherRegion *MouseWatcher:: get_over_region(float x, float y) const { return get_over_region(LPoint2f(x, y)); } //////////////////////////////////////////////////////////////////// // Function: MouseWatcher::is_button_down // Access: Published // Description: Returns true if the indicated button is currently // being held down, false otherwise. //////////////////////////////////////////////////////////////////// INLINE bool MouseWatcher:: is_button_down(ButtonHandle button) const { return _inactivity_state != IS_inactive && _current_buttons_down.get_bit(button.get_index()); } //////////////////////////////////////////////////////////////////// // Function: MouseWatcher::set_button_down_pattern // Access: Published // Description: Sets the pattern string that indicates how the event // names are generated when a button is depressed. This // is a string that may contain any of the following: // // %r - the name of the region the mouse is over // %b - the name of the button pressed. // // The event name will be based on the in_pattern // string specified here, with all occurrences of the // above strings replaced with the corresponding values. //////////////////////////////////////////////////////////////////// INLINE void MouseWatcher:: set_button_down_pattern(const string &pattern) { _button_down_pattern = pattern; } //////////////////////////////////////////////////////////////////// // Function: MouseWatcher::get_button_down_pattern // Access: Published // Description: Returns the string that indicates how event names are // generated when a button is depressed. See // set_button_down_pattern(). //////////////////////////////////////////////////////////////////// INLINE const string &MouseWatcher:: get_button_down_pattern() const { return _button_down_pattern; } //////////////////////////////////////////////////////////////////// // Function: MouseWatcher::set_button_up_pattern // Access: Published // Description: Sets the pattern string that indicates how the event // names are generated when a button is released. See // set_button_down_pattern(). //////////////////////////////////////////////////////////////////// INLINE void MouseWatcher:: set_button_up_pattern(const string &pattern) { _button_up_pattern = pattern; } //////////////////////////////////////////////////////////////////// // Function: MouseWatcher::get_button_up_pattern // Access: Published // Description: Returns the string that indicates how event names are // generated when a button is released. See // set_button_down_pattern(). //////////////////////////////////////////////////////////////////// INLINE const string &MouseWatcher:: get_button_up_pattern() const { return _button_up_pattern; } //////////////////////////////////////////////////////////////////// // Function: MouseWatcher::set_button_repeat_pattern // Access: Published // Description: Sets the pattern string that indicates how the event // names are generated when a button is continuously // held and generates keyrepeat "down" events. This is // a string that may contain any of the following: // // %r - the name of the region the mouse is over // %b - the name of the button pressed. // // The event name will be based on the in_pattern // string specified here, with all occurrences of the // above strings replaced with the corresponding values. //////////////////////////////////////////////////////////////////// INLINE void MouseWatcher:: set_button_repeat_pattern(const string &pattern) { _button_repeat_pattern = pattern; } //////////////////////////////////////////////////////////////////// // Function: MouseWatcher::get_button_repeat_pattern // Access: Published // Description: Returns the string that indicates how event names are // names are generated when a button is continuously // held and generates keyrepeat "down" events. See // set_button_repeat_pattern(). //////////////////////////////////////////////////////////////////// INLINE const string &MouseWatcher:: get_button_repeat_pattern() const { return _button_repeat_pattern; } //////////////////////////////////////////////////////////////////// // Function: MouseWatcher::set_enter_pattern // Access: Published // Description: Sets the pattern string that indicates how the event // names are generated when the mouse enters a region. // This is different from within_pattern, in that a // mouse is only "entered" in the topmost region at a // given time, while it might be "within" multiple // nested regions. //////////////////////////////////////////////////////////////////// INLINE void MouseWatcher:: set_enter_pattern(const string &pattern) { _enter_pattern = pattern; } //////////////////////////////////////////////////////////////////// // Function: MouseWatcher::get_enter_pattern // Access: Published // Description: Returns the string that indicates how event names are // generated when the mouse enters a region. This is // different from within_pattern, in that a mouse is // only "entered" in the topmost region at a given time, // while it might be "within" multiple nested regions. //////////////////////////////////////////////////////////////////// INLINE const string &MouseWatcher:: get_enter_pattern() const { return _enter_pattern; } //////////////////////////////////////////////////////////////////// // Function: MouseWatcher::set_leave_pattern // Access: Published // Description: Sets the pattern string that indicates how the event // names are generated when the mouse leaves a region. // This is different from without_pattern, in that a // mouse is only "entered" in the topmost region at a // given time, while it might be "within" multiple // nested regions. //////////////////////////////////////////////////////////////////// INLINE void MouseWatcher:: set_leave_pattern(const string &pattern) { _leave_pattern = pattern; } //////////////////////////////////////////////////////////////////// // Function: MouseWatcher::get_leave_pattern // Access: Published // Description: Returns the string that indicates how event names are // generated when the mouse leaves a region. This is // different from without_pattern, in that a mouse is // only "entered" in the topmost region at a given time, // while it might be "within" multiple nested regions. //////////////////////////////////////////////////////////////////// INLINE const string &MouseWatcher:: get_leave_pattern() const { return _leave_pattern; } //////////////////////////////////////////////////////////////////// // Function: MouseWatcher::set_within_pattern // Access: Published // Description: Sets the pattern string that indicates how the event // names are generated when the mouse wanders over a // region. This is different from enter_pattern, in // that a mouse is only "entered" in the topmost region // at a given time, while it might be "within" multiple // nested regions. //////////////////////////////////////////////////////////////////// INLINE void MouseWatcher:: set_within_pattern(const string &pattern) { _within_pattern = pattern; } //////////////////////////////////////////////////////////////////// // Function: MouseWatcher::get_within_pattern // Access: Published // Description: Returns the string that indicates how event names are // generated when the mouse wanders over a region. This // is different from enter_pattern, in that a mouse is // only "entered" in the topmost region at a given time, // while it might be "within" multiple nested regions. //////////////////////////////////////////////////////////////////// INLINE const string &MouseWatcher:: get_within_pattern() const { return _within_pattern; } //////////////////////////////////////////////////////////////////// // Function: MouseWatcher::set_without_pattern // Access: Published // Description: Sets the pattern string that indicates how the event // names are generated when the mouse wanders out of a // region. This is different from leave_pattern, in // that a mouse is only "entered" in the topmost region // at a given time, while it might be "within" multiple // nested regions. //////////////////////////////////////////////////////////////////// INLINE void MouseWatcher:: set_without_pattern(const string &pattern) { _without_pattern = pattern; } //////////////////////////////////////////////////////////////////// // Function: MouseWatcher::get_without_pattern // Access: Published // Description: Returns the string that indicates how event names are // generated when the mouse wanders out of a region. // This is different from leave_pattern, in that a mouse // is only "entered" in the topmost region at a given // time, while it might be "within" multiple nested // regions. //////////////////////////////////////////////////////////////////// INLINE const string &MouseWatcher:: get_without_pattern() const { return _without_pattern; } //////////////////////////////////////////////////////////////////// // Function: MouseWatcher::set_geometry // Access: Published // Description: Sets the node that will be transformed each frame by // the mouse's coordinates. It will also be hidden when // the mouse goes outside the window. This can be used // to implement a software mouse pointer for when a // hardware (or system) mouse pointer is unavailable. //////////////////////////////////////////////////////////////////// INLINE void MouseWatcher:: set_geometry(PandaNode *node) { _geometry = node; } //////////////////////////////////////////////////////////////////// // Function: MouseWatcher::has_geometry // Access: Published // Description: Returns true if a software mouse pointer has been // setup via set_geometry(), or false otherwise. See // set_geometry(). //////////////////////////////////////////////////////////////////// INLINE bool MouseWatcher:: has_geometry() const { return !_geometry.is_null(); } //////////////////////////////////////////////////////////////////// // Function: MouseWatcher::get_geometry // Access: Published // Description: Returns the node that has been set as the software // mouse pointer, or NULL if no node has been set. See // has_geometry() and set_geometry(). //////////////////////////////////////////////////////////////////// INLINE PandaNode *MouseWatcher:: get_geometry() const { return _geometry; } //////////////////////////////////////////////////////////////////// // Function: MouseWatcher::clear_geometry // Access: Published // Description: Stops the use of the software cursor set up via // set_geometry(). //////////////////////////////////////////////////////////////////// INLINE void MouseWatcher:: clear_geometry() { _geometry.clear(); } //////////////////////////////////////////////////////////////////// // Function: MouseWatcher::set_extra_handler // Access: Published // Description: As an optimization for the C++ Gui, an extra handler // can be registered with a mouseWatcher so that events // can be dealt with much sooner. //////////////////////////////////////////////////////////////////// INLINE void MouseWatcher:: set_extra_handler(EventHandler *eh) { _eh = eh; } //////////////////////////////////////////////////////////////////// // Function: MouseWatcher::get_extra_handler // Access: Published // Description: As an optimization for the C++ Gui, an extra handler // can be registered with a mouseWatcher so that events // can be dealt with much sooner. //////////////////////////////////////////////////////////////////// INLINE EventHandler *MouseWatcher:: get_extra_handler() const { return _eh; } //////////////////////////////////////////////////////////////////// // Function: MouseWatcher::set_modifier_buttons // Access: Public // Description: Sets the buttons that should be monitored as modifier // buttons for generating events to the // MouseWatcherRegions. //////////////////////////////////////////////////////////////////// INLINE void MouseWatcher:: set_modifier_buttons(const ModifierButtons &mods) { _mods = mods; } //////////////////////////////////////////////////////////////////// // Function: MouseWatcher::get_modifier_buttons // Access: Published // Description: Returns the set of buttons that are being monitored // as modifier buttons, as well as their current state. //////////////////////////////////////////////////////////////////// INLINE ModifierButtons MouseWatcher:: get_modifier_buttons() const { return _mods; } //////////////////////////////////////////////////////////////////// // Function: MouseWatcher::set_display_region // Access: Published // Description: Constrains the MouseWatcher to watching the mouse // within a particular indicated region of the screen. // DataNodes parented under the MouseWatcher will // observe the mouse and keyboard events only when the // mouse is within the indicated region, and the // observed range will be from -1 .. 1 across the // region. // // Do not delete the DisplayRegion while it is owned by // the MouseWatcher. //////////////////////////////////////////////////////////////////// INLINE void MouseWatcher:: set_display_region(DisplayRegion *dr) { _display_region = dr; } //////////////////////////////////////////////////////////////////// // Function: MouseWatcher::clear_display_region // Access: Published // Description: Removes the display region constraint from the // MouseWatcher, and restores it to the default behavior // of watching the whole window. //////////////////////////////////////////////////////////////////// INLINE void MouseWatcher:: clear_display_region() { _display_region = NULL; } //////////////////////////////////////////////////////////////////// // Function: MouseWatcher::get_display_region // Access: Published // Description: Returns the display region the MouseWatcher is // constrained to by set_display_region(), or NULL if it // is not constrained. //////////////////////////////////////////////////////////////////// INLINE DisplayRegion *MouseWatcher:: get_display_region() const { return _display_region; } //////////////////////////////////////////////////////////////////// // Function: MouseWatcher::has_display_region // Access: Published // Description: Returns true if the MouseWatcher has been constrained // to a particular region of the screen via // set_display_region(), or false otherwise. If this // returns true, get_display_region() may be used to // return the particular region. //////////////////////////////////////////////////////////////////// INLINE bool MouseWatcher:: has_display_region() const { return (_display_region != (DisplayRegion *)NULL); } //////////////////////////////////////////////////////////////////// // Function: MouseWatcher::set_inactivity_timeout // Access: Published // Description: Sets an inactivity timeout on the mouse activity. // When this timeout (in seconds) is exceeded with no // keyboard or mouse activity, all currently-held // buttons are automatically released. This is intended // to help protect against people who inadvertently (or // intentionally) leave a keyboard key stuck down and // then wander away from the keyboard. // // Also, when this timeout expires, the event specified // by set_inactivity_timeout_event() will be generated. //////////////////////////////////////////////////////////////////// INLINE void MouseWatcher:: set_inactivity_timeout(double timeout) { _has_inactivity_timeout = true; _inactivity_timeout = timeout; note_activity(); } //////////////////////////////////////////////////////////////////// // Function: MouseWatcher::has_inactivity_timeout // Access: Published // Description: Returns true if an inactivity timeout has been set, // false otherwise. //////////////////////////////////////////////////////////////////// INLINE bool MouseWatcher:: has_inactivity_timeout() const { return _has_inactivity_timeout; } //////////////////////////////////////////////////////////////////// // Function: MouseWatcher::get_inactivity_timeout // Access: Published // Description: Returns the inactivity timeout that has been set. // It is an error to call this if // has_inactivity_timeout() returns false. //////////////////////////////////////////////////////////////////// INLINE double MouseWatcher:: get_inactivity_timeout() const { nassertr(_has_inactivity_timeout, 0.0); return _inactivity_timeout; } //////////////////////////////////////////////////////////////////// // Function: MouseWatcher::clear_inactivity_timeout // Access: Published // Description: Removes the inactivity timeout and restores the // MouseWatcher to its default behavior of allowing a // key to be held indefinitely. //////////////////////////////////////////////////////////////////// INLINE void MouseWatcher:: clear_inactivity_timeout() { _has_inactivity_timeout = false; _inactivity_timeout = 0.0; note_activity(); } //////////////////////////////////////////////////////////////////// // Function: MouseWatcher::set_inactivity_timeout_event // Access: Published // Description: Specifies the event string that will be generated // when the inactivity timeout counter expires. See // set_inactivity_timeout(). //////////////////////////////////////////////////////////////////// INLINE void MouseWatcher:: set_inactivity_timeout_event(const string &event) { _inactivity_timeout_event = event; } //////////////////////////////////////////////////////////////////// // Function: MouseWatcher::get_inactivity_timeout_event // Access: Published // Description: Returns the event string that will be generated // when the inactivity timeout counter expires. See // set_inactivity_timeout(). //////////////////////////////////////////////////////////////////// INLINE const string &MouseWatcher:: get_inactivity_timeout_event() const { return _inactivity_timeout_event; } //////////////////////////////////////////////////////////////////// // Function: MouseWatcher::within_region // Access: Protected // Description: Called internally to indicate the mouse pointer has // moved within the indicated region's boundaries. //////////////////////////////////////////////////////////////////// INLINE void MouseWatcher:: within_region(MouseWatcherRegion *region, const MouseWatcherParameter ¶m) { region->within_region(param); throw_event_pattern(_within_pattern, region, ButtonHandle::none()); if (_enter_multiple) { enter_region(region, param); } } //////////////////////////////////////////////////////////////////// // Function: MouseWatcher::without_region // Access: Protected // Description: Called internally to indicate the mouse pointer has // moved outside of the indicated region's boundaries. //////////////////////////////////////////////////////////////////// INLINE void MouseWatcher:: without_region(MouseWatcherRegion *region, const MouseWatcherParameter ¶m) { if (_enter_multiple) { exit_region(region, param); } region->without_region(param); 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 // Description: Obtain the mouse trail log. This is a PointerEventList. // Does not make a copy, therefore, this PointerEventList // will be updated each time process_events gets called. // // To use trail logging, you need to enable the // generation of pointer events in the // GraphicsWindowInputDevice and set the trail log // duration in the MouseWatcher. Otherwise, the // trail log will be empty. //////////////////////////////////////////////////////////////////// INLINE CPT(PointerEventList) MouseWatcher:: get_trail_log() const { return _trail_log; } //////////////////////////////////////////////////////////////////// // Function: MouseWatcher::num_trail_recent // Access: Published // Description: This counter indicates how many events were added // to the trail log this frame. The trail log is // updated once per frame, during the process_events // operation. //////////////////////////////////////////////////////////////////// INLINE int MouseWatcher:: num_trail_recent() const { return _num_trail_recent; }