mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-04 02:42:49 -04:00
add within/without messages
This commit is contained in:
parent
0ff966d799
commit
7c00e5b6ce
@ -237,6 +237,30 @@ get_exit_prefix() {
|
||||
return "exit-";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PGItem::get_within_prefix
|
||||
// Access: Published, Static
|
||||
// Description: Returns the prefix that is used to define the within
|
||||
// event for all PGItems. The within event is the
|
||||
// concatenation of this string followed by get_id().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE string PGItem::
|
||||
get_within_prefix() {
|
||||
return "within-";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PGItem::get_without_prefix
|
||||
// Access: Published, Static
|
||||
// Description: Returns the prefix that is used to define the without
|
||||
// event for all PGItems. The without event is the
|
||||
// concatenation of this string followed by get_id().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE string PGItem::
|
||||
get_without_prefix() {
|
||||
return "without-";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PGItem::get_focus_in_prefix
|
||||
// Access: Published, Static
|
||||
@ -297,7 +321,8 @@ get_release_prefix() {
|
||||
// Function: PGItem::get_enter_event
|
||||
// Access: Published
|
||||
// Description: Returns the event name that will be thrown when the
|
||||
// item is active and the mouse enters its frame.
|
||||
// item is active and the mouse enters its frame, but
|
||||
// not any nested frames.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE string PGItem::
|
||||
get_enter_event() const {
|
||||
@ -308,13 +333,43 @@ get_enter_event() const {
|
||||
// Function: PGItem::get_exit_event
|
||||
// Access: Published
|
||||
// Description: Returns the event name that will be thrown when the
|
||||
// item is active and the mouse exits its frame.
|
||||
// item is active and the mouse exits its frame, or
|
||||
// enters a nested frame.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE string PGItem::
|
||||
get_exit_event() const {
|
||||
return get_exit_prefix() + get_id();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PGItem::get_within_event
|
||||
// Access: Published
|
||||
// Description: Returns the event name that will be thrown when the
|
||||
// item is active and the mouse moves within the
|
||||
// boundaries of the frame. This is different from the
|
||||
// enter_event in that the mouse is considered within
|
||||
// the frame even if it is also within a nested frame.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE string PGItem::
|
||||
get_within_event() const {
|
||||
return get_within_prefix() + get_id();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PGItem::get_without_event
|
||||
// Access: Published
|
||||
// Description: Returns the event name that will be thrown when the
|
||||
// item is active and the mouse moves completely outside
|
||||
// the boundaries of the frame. This is different from
|
||||
// the exit_event in that the mouse is considered
|
||||
// within the frame even if it is also within a nested
|
||||
// frame.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE string PGItem::
|
||||
get_without_event() const {
|
||||
return get_without_prefix() + get_id();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PGItem::get_focus_in_event
|
||||
// Access: Published
|
||||
|
@ -226,7 +226,10 @@ draw_item(PGTop *top, GraphicsStateGuardian *gsg,
|
||||
// Function: PGItem::enter
|
||||
// Access: Public, Virtual
|
||||
// Description: This is a callback hook function, called whenever the
|
||||
// mouse enters the region.
|
||||
// mouse enters the region. The mouse is only
|
||||
// considered to be "entered" in one region at a time;
|
||||
// in the case of nested regions, it exits the outer
|
||||
// region before entering the inner one.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PGItem::
|
||||
enter(const MouseWatcherParameter ¶m) {
|
||||
@ -240,7 +243,10 @@ enter(const MouseWatcherParameter ¶m) {
|
||||
// Function: PGItem::exit
|
||||
// Access: Public, Virtual
|
||||
// Description: This is a callback hook function, called whenever the
|
||||
// mouse exits the region.
|
||||
// mouse exits the region. The mouse is only considered
|
||||
// to be "entered" in one region at a time; in the case
|
||||
// of nested regions, it exits the outer region before
|
||||
// entering the inner one.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PGItem::
|
||||
exit(const MouseWatcherParameter ¶m) {
|
||||
@ -250,6 +256,39 @@ exit(const MouseWatcherParameter ¶m) {
|
||||
throw_event(event, EventParameter(ep));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PGItem::within
|
||||
// Access: Public, Virtual
|
||||
// Description: This is a callback hook function, called whenever the
|
||||
// mouse moves within the boundaries of the region, even
|
||||
// if it is also within the boundaries of a nested
|
||||
// region. This is different from "enter", which is
|
||||
// only called whenever the mouse is within only that
|
||||
// region.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PGItem::
|
||||
within(const MouseWatcherParameter ¶m) {
|
||||
PGMouseWatcherParameter *ep = new PGMouseWatcherParameter(param);
|
||||
string event = get_within_event();
|
||||
play_sound(event);
|
||||
throw_event(event, EventParameter(ep));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PGItem::without
|
||||
// Access: Public, Virtual
|
||||
// Description: This is a callback hook function, called whenever the
|
||||
// mouse moves completely outside the boundaries of the
|
||||
// region. See within().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PGItem::
|
||||
without(const MouseWatcherParameter ¶m) {
|
||||
PGMouseWatcherParameter *ep = new PGMouseWatcherParameter(param);
|
||||
string event = get_without_event();
|
||||
play_sound(event);
|
||||
throw_event(event, EventParameter(ep));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PGItem::focus_in
|
||||
// Access: Public, Virtual
|
||||
|
@ -75,6 +75,8 @@ public:
|
||||
|
||||
virtual void enter(const MouseWatcherParameter ¶m);
|
||||
virtual void exit(const MouseWatcherParameter ¶m);
|
||||
virtual void within(const MouseWatcherParameter ¶m);
|
||||
virtual void without(const MouseWatcherParameter ¶m);
|
||||
virtual void focus_in();
|
||||
virtual void focus_out();
|
||||
virtual void press(const MouseWatcherParameter ¶m, bool background);
|
||||
@ -119,6 +121,8 @@ PUBLISHED:
|
||||
|
||||
INLINE static string get_enter_prefix();
|
||||
INLINE static string get_exit_prefix();
|
||||
INLINE static string get_within_prefix();
|
||||
INLINE static string get_without_prefix();
|
||||
INLINE static string get_focus_in_prefix();
|
||||
INLINE static string get_focus_out_prefix();
|
||||
INLINE static string get_press_prefix();
|
||||
@ -126,6 +130,8 @@ PUBLISHED:
|
||||
|
||||
INLINE string get_enter_event() const;
|
||||
INLINE string get_exit_event() const;
|
||||
INLINE string get_within_event() const;
|
||||
INLINE string get_without_event() const;
|
||||
INLINE string get_focus_in_event() const;
|
||||
INLINE string get_focus_out_event() const;
|
||||
INLINE string get_press_event(const ButtonHandle &button) const;
|
||||
|
@ -52,7 +52,10 @@ PGMouseWatcherRegion::
|
||||
// Function: PGMouseWatcherRegion::enter
|
||||
// Access: Public, Virtual
|
||||
// Description: This is a callback hook function, called whenever the
|
||||
// mouse enters the region.
|
||||
// mouse enters the region. The mouse is only
|
||||
// considered to be "entered" in one region at a time;
|
||||
// in the case of nested regions, it exits the outer
|
||||
// region before entering the inner one.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PGMouseWatcherRegion::
|
||||
enter(const MouseWatcherParameter ¶m) {
|
||||
@ -65,7 +68,10 @@ enter(const MouseWatcherParameter ¶m) {
|
||||
// Function: PGMouseWatcherRegion::exit
|
||||
// Access: Public, Virtual
|
||||
// Description: This is a callback hook function, called whenever the
|
||||
// mouse exits the region.
|
||||
// mouse exits the region. The mouse is only considered
|
||||
// to be "entered" in one region at a time; in the case
|
||||
// of nested regions, it exits the outer region before
|
||||
// entering the inner one.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PGMouseWatcherRegion::
|
||||
exit(const MouseWatcherParameter ¶m) {
|
||||
@ -74,6 +80,37 @@ exit(const MouseWatcherParameter ¶m) {
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PGMouseWatcherRegion::within
|
||||
// Access: Public, Virtual
|
||||
// Description: This is a callback hook function, called whenever the
|
||||
// mouse moves within the boundaries of the region, even
|
||||
// if it is also within the boundaries of a nested
|
||||
// region. This is different from "enter", which is
|
||||
// only called whenever the mouse is within only that
|
||||
// region.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PGMouseWatcherRegion::
|
||||
within(const MouseWatcherParameter ¶m) {
|
||||
if (_item != (PGItem *)NULL) {
|
||||
_item->within(param);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PGMouseWatcherRegion::without
|
||||
// Access: Public, Virtual
|
||||
// Description: This is a callback hook function, called whenever the
|
||||
// mouse moves completely outside the boundaries of the
|
||||
// region. See within().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PGMouseWatcherRegion::
|
||||
without(const MouseWatcherParameter ¶m) {
|
||||
if (_item != (PGItem *)NULL) {
|
||||
_item->without(param);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PGMouseWatcherRegion::press
|
||||
// Access: Public, Virtual
|
||||
|
@ -39,6 +39,8 @@ public:
|
||||
|
||||
virtual void enter(const MouseWatcherParameter ¶m);
|
||||
virtual void exit(const MouseWatcherParameter ¶m);
|
||||
virtual void within(const MouseWatcherParameter ¶m);
|
||||
virtual void without(const MouseWatcherParameter ¶m);
|
||||
virtual void press(const MouseWatcherParameter ¶m);
|
||||
virtual void release(const MouseWatcherParameter ¶m);
|
||||
|
||||
|
@ -124,7 +124,7 @@ is_over_region(const LPoint2f &pos) const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE MouseWatcherRegion *MouseWatcher::
|
||||
get_over_region() const {
|
||||
return _current_region;
|
||||
return _preferred_region;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -197,8 +197,11 @@ get_button_up_pattern() const {
|
||||
// Function: MouseWatcher::set_enter_pattern
|
||||
// Access: Published
|
||||
// Description: Sets the pattern string that indicates how the event
|
||||
// names are generated when the mouse wanders over a
|
||||
// region. See set_button_down_pattern().
|
||||
// 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) {
|
||||
@ -209,8 +212,10 @@ set_enter_pattern(const string &pattern) {
|
||||
// Function: MouseWatcher::get_enter_pattern
|
||||
// Access: Published
|
||||
// Description: Returns the string that indicates how event names are
|
||||
// generated when the mouse wanders over a region. See
|
||||
// set_button_down_pattern().
|
||||
// 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 {
|
||||
@ -222,7 +227,10 @@ get_enter_pattern() const {
|
||||
// Access: Published
|
||||
// Description: Sets the pattern string that indicates how the event
|
||||
// names are generated when the mouse leaves a region.
|
||||
// See set_button_down_pattern().
|
||||
// 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) {
|
||||
@ -233,14 +241,75 @@ set_leave_pattern(const string &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. See
|
||||
// set_button_down_pattern().
|
||||
// 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
|
||||
|
@ -29,6 +29,8 @@
|
||||
#include "pruneTransition.h"
|
||||
#include "transformTransition.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
TypeHandle MouseWatcher::_type_handle;
|
||||
|
||||
TypeHandle MouseWatcher::_xyz_type;
|
||||
@ -44,8 +46,8 @@ MouseWatcher::
|
||||
MouseWatcher(const string &name) : DataNode(name) {
|
||||
_has_mouse = false;
|
||||
_suppress_flags = 0;
|
||||
_current_region = (MouseWatcherRegion *)NULL;
|
||||
_button_down_region = (MouseWatcherRegion *)NULL;
|
||||
_preferred_region = (MouseWatcherRegion *)NULL;
|
||||
_preferred_button_down_region = (MouseWatcherRegion *)NULL;
|
||||
_button_down = false;
|
||||
_eh = (EventHandler*)0L;
|
||||
}
|
||||
@ -68,12 +70,14 @@ MouseWatcher::
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool MouseWatcher::
|
||||
remove_region(MouseWatcherRegion *region) {
|
||||
if (region == _current_region) {
|
||||
_current_region = (MouseWatcherRegion *)NULL;
|
||||
remove_region_from(_current_regions, region);
|
||||
if (region == _preferred_region) {
|
||||
_preferred_region = (MouseWatcherRegion *)NULL;
|
||||
}
|
||||
if (region == _button_down_region) {
|
||||
_button_down_region = (MouseWatcherRegion *)NULL;
|
||||
if (region == _preferred_button_down_region) {
|
||||
_preferred_button_down_region = (MouseWatcherRegion *)NULL;
|
||||
}
|
||||
|
||||
return MouseWatcherGroup::remove_region(region);
|
||||
}
|
||||
|
||||
@ -88,47 +92,9 @@ remove_region(MouseWatcherRegion *region) {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
MouseWatcherRegion *MouseWatcher::
|
||||
get_over_region(const LPoint2f &pos) const {
|
||||
MouseWatcherRegion *over_region = (MouseWatcherRegion *)NULL;
|
||||
|
||||
Regions::const_iterator ri;
|
||||
for (ri = _regions.begin(); ri != _regions.end(); ++ri) {
|
||||
MouseWatcherRegion *region = (*ri);
|
||||
const LVecBase4f &frame = region->get_frame();
|
||||
|
||||
if (region->get_active() &&
|
||||
pos[0] >= frame[0] && pos[0] <= frame[1] &&
|
||||
pos[1] >= frame[2] && pos[1] <= frame[3]) {
|
||||
|
||||
// We're over this region. Is it preferred to the other one?
|
||||
if (over_region == (MouseWatcherRegion *)NULL ||
|
||||
*region < *over_region) {
|
||||
over_region = region;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Also check all of our sub-groups.
|
||||
Groups::const_iterator gi;
|
||||
for (gi = _groups.begin(); gi != _groups.end(); ++gi) {
|
||||
MouseWatcherGroup *group = (*gi);
|
||||
for (ri = group->_regions.begin(); ri != group->_regions.end(); ++ri) {
|
||||
MouseWatcherRegion *region = (*ri);
|
||||
const LVecBase4f &frame = region->get_frame();
|
||||
|
||||
if (region->get_active() &&
|
||||
pos[0] >= frame[0] && pos[0] <= frame[1] &&
|
||||
pos[1] >= frame[2] && pos[1] <= frame[3]) {
|
||||
|
||||
// We're over this region. Is it preferred to the other one?
|
||||
if (over_region == (MouseWatcherRegion *)NULL ||
|
||||
*region < *over_region) {
|
||||
over_region = region;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return over_region;
|
||||
VRegions regions;
|
||||
get_over_regions(regions, pos);
|
||||
return get_preferred_region(regions);
|
||||
}
|
||||
|
||||
|
||||
@ -140,7 +106,15 @@ get_over_region(const LPoint2f &pos) const {
|
||||
void MouseWatcher::
|
||||
output(ostream &out) const {
|
||||
DataNode::output(out);
|
||||
out << " (" << _regions.size() << " regions)";
|
||||
|
||||
int count = _regions.size();
|
||||
Groups::const_iterator gi;
|
||||
for (gi = _groups.begin(); gi != _groups.end(); ++gi) {
|
||||
MouseWatcherGroup *group = (*gi);
|
||||
count += group->_regions.size();
|
||||
}
|
||||
|
||||
out << " (" << count << " regions)";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -203,44 +177,317 @@ add_group(MouseWatcherGroup *group) {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool MouseWatcher::
|
||||
remove_group(MouseWatcherGroup *group) {
|
||||
if (group->has_region(_current_region)) {
|
||||
_current_region = (MouseWatcherRegion *)NULL;
|
||||
remove_regions_from(_current_regions, group);
|
||||
if (group->has_region(_preferred_region)) {
|
||||
_preferred_region = (MouseWatcherRegion *)NULL;
|
||||
}
|
||||
if (group->has_region(_button_down_region)) {
|
||||
_button_down_region = (MouseWatcherRegion *)NULL;
|
||||
if (group->has_region(_preferred_button_down_region)) {
|
||||
_preferred_button_down_region = (MouseWatcherRegion *)NULL;
|
||||
}
|
||||
|
||||
return _groups.erase(group) != 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MouseWatcher::set_current_region
|
||||
// Function: MouseWatcher::get_over_regions
|
||||
// Access: Private
|
||||
// Description: Changes the "current" region--the one we consider the
|
||||
// mouse to be over--to the indicated one, and throws
|
||||
// whatever events are appropriate because of that.
|
||||
// Description: Fills up the "regions" list with the set of regions
|
||||
// that the indicated point is over, sorted in order by
|
||||
// pointer.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void MouseWatcher::
|
||||
set_current_region(MouseWatcherRegion *region) {
|
||||
#ifndef NDEBUG
|
||||
if (region != (MouseWatcherRegion *)NULL) {
|
||||
region->test_ref_count_integrity();
|
||||
get_over_regions(MouseWatcher::VRegions ®ions, const LPoint2f &pos) const {
|
||||
// Ensure the vector is empty before we begin.
|
||||
regions.clear();
|
||||
|
||||
Regions::const_iterator ri;
|
||||
for (ri = _regions.begin(); ri != _regions.end(); ++ri) {
|
||||
MouseWatcherRegion *region = (*ri);
|
||||
const LVecBase4f &frame = region->get_frame();
|
||||
|
||||
if (region->get_active() &&
|
||||
pos[0] >= frame[0] && pos[0] <= frame[1] &&
|
||||
pos[1] >= frame[2] && pos[1] <= frame[3]) {
|
||||
|
||||
regions.push_back(region);
|
||||
}
|
||||
#endif
|
||||
if (region != _current_region) {
|
||||
}
|
||||
|
||||
// Also check all of our sub-groups.
|
||||
Groups::const_iterator gi;
|
||||
for (gi = _groups.begin(); gi != _groups.end(); ++gi) {
|
||||
MouseWatcherGroup *group = (*gi);
|
||||
for (ri = group->_regions.begin(); ri != group->_regions.end(); ++ri) {
|
||||
MouseWatcherRegion *region = (*ri);
|
||||
const LVecBase4f &frame = region->get_frame();
|
||||
|
||||
if (region->get_active() &&
|
||||
pos[0] >= frame[0] && pos[0] <= frame[1] &&
|
||||
pos[1] >= frame[2] && pos[1] <= frame[3]) {
|
||||
|
||||
regions.push_back(region);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Now sort the regions by pointer. By convention, the Regions
|
||||
// vectors are always kept in order by pointer, so we can do easy
|
||||
// linear comparison and intersection operations.
|
||||
sort(regions.begin(), regions.end());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MouseWatcher::get_preferred_region
|
||||
// Access: Private, Static
|
||||
// Description: Returns the innermost region of all the regions
|
||||
// indicated in the given vector (usually, the regions
|
||||
// the mouse is over). This is the "preferred" region
|
||||
// that gets some special treatment.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
MouseWatcherRegion *MouseWatcher::
|
||||
get_preferred_region(const MouseWatcher::VRegions ®ions) {
|
||||
if (regions.empty()) {
|
||||
return (MouseWatcherRegion *)NULL;
|
||||
}
|
||||
|
||||
VRegions::const_iterator ri;
|
||||
ri = regions.begin();
|
||||
MouseWatcherRegion *preferred = *ri;
|
||||
++ri;
|
||||
while (ri != regions.end()) {
|
||||
MouseWatcherRegion *region = *ri;
|
||||
|
||||
if (*region < *preferred) {
|
||||
preferred = region;
|
||||
}
|
||||
++ri;
|
||||
}
|
||||
|
||||
return preferred;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MouseWatcher::set_current_regions
|
||||
// Access: Private
|
||||
// Description: Changes the "current" regions--the one we consider the
|
||||
// mouse to be over--to the indicated list, and throws
|
||||
// whatever events are appropriate because of that.
|
||||
//
|
||||
// The list passed in is destroyed.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void MouseWatcher::
|
||||
set_current_regions(MouseWatcher::VRegions ®ions) {
|
||||
// Set up a parameter for passing through any change events.
|
||||
MouseWatcherParameter param;
|
||||
param.set_modifier_buttons(_mods);
|
||||
param.set_mouse(_mouse);
|
||||
|
||||
if (_current_region != (MouseWatcherRegion *)NULL) {
|
||||
_current_region->exit(param);
|
||||
throw_event_pattern(_leave_pattern, _current_region, ButtonHandle::none());
|
||||
}
|
||||
_current_region = region;
|
||||
if (_current_region != (MouseWatcherRegion *)NULL) {
|
||||
_current_region->enter(param);
|
||||
throw_event_pattern(_enter_pattern, _current_region, ButtonHandle::none());
|
||||
// Now do a standard sorted comparison between the two vectors.
|
||||
VRegions::const_iterator new_ri = regions.begin();
|
||||
VRegions::const_iterator old_ri = _current_regions.begin();
|
||||
|
||||
bool any_changes = false;
|
||||
while (new_ri != regions.end() && old_ri != _current_regions.end()) {
|
||||
if ((*new_ri) < (*old_ri)) {
|
||||
// Here's a new region that we didn't have last frame.
|
||||
MouseWatcherRegion *new_region = (*new_ri);
|
||||
new_region->within(param);
|
||||
throw_event_pattern(_within_pattern, new_region, ButtonHandle::none());
|
||||
any_changes = true;
|
||||
++new_ri;
|
||||
|
||||
} else if ((*old_ri) < (*new_ri)) {
|
||||
// Here's a region we don't have any more.
|
||||
MouseWatcherRegion *old_region = (*old_ri);
|
||||
old_region->without(param);
|
||||
throw_event_pattern(_without_pattern, old_region, ButtonHandle::none());
|
||||
any_changes = true;
|
||||
++old_ri;
|
||||
|
||||
} else {
|
||||
// Here's a region that hasn't changed.
|
||||
++new_ri;
|
||||
++old_ri;
|
||||
}
|
||||
}
|
||||
|
||||
while (new_ri != regions.end()) {
|
||||
// Here's a new region that we didn't have last frame.
|
||||
MouseWatcherRegion *new_region = (*new_ri);
|
||||
new_region->within(param);
|
||||
throw_event_pattern(_within_pattern, new_region, ButtonHandle::none());
|
||||
any_changes = true;
|
||||
++new_ri;
|
||||
}
|
||||
|
||||
while (old_ri != _current_regions.end()) {
|
||||
// Here's a region we don't have any more.
|
||||
MouseWatcherRegion *old_region = (*old_ri);
|
||||
old_region->without(param);
|
||||
throw_event_pattern(_without_pattern, old_region, ButtonHandle::none());
|
||||
any_changes = true;
|
||||
++old_ri;
|
||||
}
|
||||
|
||||
if (any_changes) {
|
||||
// Now that we've compared the two vectors, simply swap them to set
|
||||
// the new vector.
|
||||
_current_regions.swap(regions);
|
||||
|
||||
// Determine which is the "preferred region", if any. This is the
|
||||
// topmost region that the mouse cursor is over, and the one that
|
||||
// we are considred "entered" into.
|
||||
MouseWatcherRegion *new_preferred_region =
|
||||
get_preferred_region(_current_regions);
|
||||
|
||||
if (_button_down && new_preferred_region != _preferred_button_down_region) {
|
||||
// If the button's being held down, we're only allowed to select
|
||||
// the preferred button down region.
|
||||
new_preferred_region = (MouseWatcherRegion *)NULL;
|
||||
}
|
||||
|
||||
if (new_preferred_region != _preferred_region) {
|
||||
if (_preferred_region != (MouseWatcherRegion *)NULL) {
|
||||
_preferred_region->exit(param);
|
||||
throw_event_pattern(_leave_pattern, _preferred_region, ButtonHandle::none());
|
||||
}
|
||||
_preferred_region = new_preferred_region;
|
||||
if (_preferred_region != (MouseWatcherRegion *)NULL) {
|
||||
_preferred_region->enter(param);
|
||||
throw_event_pattern(_enter_pattern, _preferred_region, ButtonHandle::none());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MouseWatcher::clear_current_regions
|
||||
// Access: Private
|
||||
// Description: Empties the set of current regions.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void MouseWatcher::
|
||||
clear_current_regions() {
|
||||
if (!_current_regions.empty()) {
|
||||
// Set up a parameter for passing through any change events.
|
||||
MouseWatcherParameter param;
|
||||
param.set_modifier_buttons(_mods);
|
||||
param.set_mouse(_mouse);
|
||||
|
||||
VRegions::const_iterator old_ri = _current_regions.begin();
|
||||
|
||||
while (old_ri != _current_regions.end()) {
|
||||
// Here's a region we don't have any more.
|
||||
MouseWatcherRegion *old_region = (*old_ri);
|
||||
old_region->exit(param);
|
||||
throw_event_pattern(_leave_pattern, old_region, ButtonHandle::none());
|
||||
++old_ri;
|
||||
}
|
||||
|
||||
_current_regions.clear();
|
||||
|
||||
if (_preferred_region != (MouseWatcherRegion *)NULL) {
|
||||
_preferred_region->exit(param);
|
||||
throw_event_pattern(_leave_pattern, _preferred_region, ButtonHandle::none());
|
||||
_preferred_region = (MouseWatcherRegion *)NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MouseWatcher::intersect_regions
|
||||
// Access: Private, Static
|
||||
// Description: Sets result to be the intersection of the list of
|
||||
// regions in regions_a and regions_b. It is assumed
|
||||
// that both vectors are already sorted in pointer
|
||||
// order.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void MouseWatcher::
|
||||
intersect_regions(MouseWatcher::VRegions &result,
|
||||
const MouseWatcher::VRegions ®ions_a,
|
||||
const MouseWatcher::VRegions ®ions_b) {
|
||||
// Get a temporary vector for storing the result in. We don't use
|
||||
// result directly, because it might be the same vector as one of a
|
||||
// or b.
|
||||
VRegions temp;
|
||||
|
||||
// Now do a standard sorted intersection between the two vectors.
|
||||
VRegions::const_iterator a_ri = regions_a.begin();
|
||||
VRegions::const_iterator b_ri = regions_b.begin();
|
||||
|
||||
while (a_ri != regions_a.end() && b_ri != regions_b.end()) {
|
||||
if ((*a_ri) < (*b_ri)) {
|
||||
// Here's a region in a, not in b.
|
||||
++a_ri;
|
||||
|
||||
} else if ((*b_ri) < (*a_ri)) {
|
||||
// Here's a region in b, not in a.
|
||||
++b_ri;
|
||||
|
||||
} else {
|
||||
// Here's a region in both vectors.
|
||||
temp.push_back(*a_ri);
|
||||
++a_ri;
|
||||
++b_ri;
|
||||
}
|
||||
}
|
||||
|
||||
// Now store the result!
|
||||
result.swap(temp);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MouseWatcher::remove_region_from
|
||||
// Access: Private, Static
|
||||
// Description: Removes the indicated region from the given vector.
|
||||
// Assumes the vector is sorted in pointer order.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void MouseWatcher::
|
||||
remove_region_from(MouseWatcher::VRegions ®ions,
|
||||
MouseWatcherRegion *region) {
|
||||
VRegions::iterator ri =
|
||||
lower_bound(regions.begin(), regions.end(), region);
|
||||
if (ri != regions.end() && (*ri) == region) {
|
||||
// The region is in the vector. Remove it.
|
||||
regions.erase(ri);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MouseWatcher::remove_regions_from
|
||||
// Access: Private, Static
|
||||
// Description: Removes all the regions in the indicated group from
|
||||
// the given vector. Assumes the vector is sorted in
|
||||
// pointer order.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void MouseWatcher::
|
||||
remove_regions_from(MouseWatcher::VRegions ®ions,
|
||||
MouseWatcherGroup *group) {
|
||||
// Since the group stores a set of regions, which are also sorted in
|
||||
// pointer order, we can just do an intersection operation here.
|
||||
VRegions temp;
|
||||
|
||||
VRegions::const_iterator a_ri = regions.begin();
|
||||
MouseWatcherGroup::Regions::const_iterator b_ri = group->_regions.begin();
|
||||
|
||||
while (a_ri != regions.end() && b_ri != group->_regions.end()) {
|
||||
if ((*a_ri) < (*b_ri)) {
|
||||
// Here's a region in the group, not in regions.
|
||||
++a_ri;
|
||||
|
||||
} else if ((*b_ri) < (*a_ri)) {
|
||||
// Here's a region in regions, not in the group.
|
||||
temp.push_back(*b_ri);
|
||||
++b_ri;
|
||||
|
||||
} else {
|
||||
// Here's a region in the group and in regions.
|
||||
++a_ri;
|
||||
++b_ri;
|
||||
}
|
||||
}
|
||||
|
||||
// Now store the result!
|
||||
regions.swap(temp);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -318,24 +565,25 @@ press(ButtonHandle button) {
|
||||
// Mouse buttons are inextricably linked to the mouse position.
|
||||
|
||||
if (!_button_down) {
|
||||
_button_down_region = _current_region;
|
||||
_preferred_button_down_region = _preferred_region;
|
||||
}
|
||||
_button_down = true;
|
||||
if (_button_down_region != (MouseWatcherRegion *)NULL) {
|
||||
_button_down_region->press(param);
|
||||
throw_event_pattern(_button_down_pattern, _button_down_region,
|
||||
button);
|
||||
|
||||
if (_preferred_button_down_region != (MouseWatcherRegion *)NULL) {
|
||||
_preferred_button_down_region->press(param);
|
||||
throw_event_pattern(_button_down_pattern,
|
||||
_preferred_button_down_region, button);
|
||||
}
|
||||
|
||||
} else {
|
||||
// It's a keyboard button; therefore, send the event to every
|
||||
// region that wants keyboard buttons, regardless of the mouse
|
||||
// position.
|
||||
if (_current_region != (MouseWatcherRegion *)NULL) {
|
||||
if (_preferred_region != (MouseWatcherRegion *)NULL) {
|
||||
// Our current region, the one under the mouse, always get
|
||||
// all the keyboard events, even if it doesn't set its
|
||||
// keyboard flag.
|
||||
_current_region->press(param);
|
||||
_preferred_region->press(param);
|
||||
}
|
||||
|
||||
if ((_suppress_flags & MouseWatcherRegion::SF_other_button) == 0) {
|
||||
@ -362,26 +610,28 @@ release(ButtonHandle button) {
|
||||
param.set_mouse(_mouse);
|
||||
|
||||
if (MouseButton::is_mouse_button(button)) {
|
||||
// Button up. Send the up event associated with the region we
|
||||
// Button up. Send the up event associated with the region(s) we
|
||||
// were over when the button went down.
|
||||
|
||||
// There is some danger of losing button-up events here. If
|
||||
// more than one button goes down together, we won't detect
|
||||
// both of the button-up events properly.
|
||||
if (_button_down_region != (MouseWatcherRegion *)NULL) {
|
||||
param.set_outside(_current_region != _button_down_region);
|
||||
_button_down_region->release(param);
|
||||
throw_event_pattern(_button_up_pattern, _button_down_region,
|
||||
button);
|
||||
if (_preferred_button_down_region != (MouseWatcherRegion *)NULL) {
|
||||
param.set_outside(_preferred_button_down_region != _preferred_region);
|
||||
_preferred_button_down_region->release(param);
|
||||
throw_event_pattern(_button_up_pattern,
|
||||
_preferred_button_down_region, button);
|
||||
}
|
||||
|
||||
_button_down = false;
|
||||
_preferred_button_down_region = (MouseWatcherRegion *)NULL;
|
||||
|
||||
} else {
|
||||
// It's a keyboard button; therefore, send the event to every
|
||||
// region that wants keyboard buttons, regardless of the mouse
|
||||
// position.
|
||||
if (_current_region != (MouseWatcherRegion *)NULL) {
|
||||
_current_region->release(param);
|
||||
if (_preferred_region != (MouseWatcherRegion *)NULL) {
|
||||
_preferred_region->release(param);
|
||||
}
|
||||
|
||||
param.set_outside(true);
|
||||
@ -402,7 +652,7 @@ global_keyboard_press(const MouseWatcherParameter ¶m) {
|
||||
for (ri = _regions.begin(); ri != _regions.end(); ++ri) {
|
||||
MouseWatcherRegion *region = (*ri);
|
||||
|
||||
if (region != _current_region && region->get_keyboard()) {
|
||||
if (region != _preferred_region && region->get_keyboard()) {
|
||||
region->press(param);
|
||||
}
|
||||
}
|
||||
@ -414,7 +664,7 @@ global_keyboard_press(const MouseWatcherParameter ¶m) {
|
||||
for (ri = group->_regions.begin(); ri != group->_regions.end(); ++ri) {
|
||||
MouseWatcherRegion *region = (*ri);
|
||||
|
||||
if (region != _current_region && region->get_keyboard()) {
|
||||
if (region != _preferred_region && region->get_keyboard()) {
|
||||
region->press(param);
|
||||
}
|
||||
}
|
||||
@ -434,7 +684,7 @@ global_keyboard_release(const MouseWatcherParameter ¶m) {
|
||||
for (ri = _regions.begin(); ri != _regions.end(); ++ri) {
|
||||
MouseWatcherRegion *region = (*ri);
|
||||
|
||||
if (region != _current_region && region->get_keyboard()) {
|
||||
if (region != _preferred_region && region->get_keyboard()) {
|
||||
region->release(param);
|
||||
}
|
||||
}
|
||||
@ -446,7 +696,7 @@ global_keyboard_release(const MouseWatcherParameter ¶m) {
|
||||
for (ri = group->_regions.begin(); ri != group->_regions.end(); ++ri) {
|
||||
MouseWatcherRegion *region = (*ri);
|
||||
|
||||
if (region != _current_region && region->get_keyboard()) {
|
||||
if (region != _preferred_region && region->get_keyboard()) {
|
||||
region->release(param);
|
||||
}
|
||||
}
|
||||
@ -473,7 +723,7 @@ transmit_data(AllTransitionsWrapper &data) {
|
||||
_has_mouse = false;
|
||||
// If the mouse is outside the window, do nothing; let all the
|
||||
// events continue down the pipe unmolested.
|
||||
set_current_region(NULL);
|
||||
clear_current_regions();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -492,26 +742,13 @@ transmit_data(AllTransitionsWrapper &data) {
|
||||
|
||||
_has_mouse = true;
|
||||
|
||||
if (!_button_down) {
|
||||
// If the button is not currently being held down, we are free to
|
||||
// set the mouse into whichever region we like.
|
||||
set_current_region(get_over_region(_mouse));
|
||||
|
||||
} else {
|
||||
// If the button *is* currently being held down, we can only move
|
||||
// the mouse into a region if the region is the same region we
|
||||
// started from.
|
||||
MouseWatcherRegion *region = get_over_region(_mouse);
|
||||
if (region == _button_down_region) {
|
||||
set_current_region(region);
|
||||
} else {
|
||||
set_current_region((MouseWatcherRegion *)NULL);
|
||||
}
|
||||
}
|
||||
VRegions regions;
|
||||
get_over_regions(regions, _mouse);
|
||||
set_current_regions(regions);
|
||||
|
||||
_suppress_flags = 0;
|
||||
if (_current_region != (MouseWatcherRegion *)NULL) {
|
||||
_suppress_flags = _current_region->get_suppress_flags();
|
||||
if (_preferred_region != (MouseWatcherRegion *)NULL) {
|
||||
_suppress_flags = _preferred_region->get_suppress_flags();
|
||||
}
|
||||
|
||||
// Look for button events.
|
||||
|
@ -89,6 +89,12 @@ PUBLISHED:
|
||||
INLINE void set_leave_pattern(const string &pattern);
|
||||
INLINE const string &get_leave_pattern() const;
|
||||
|
||||
INLINE void set_within_pattern(const string &pattern);
|
||||
INLINE const string &get_within_pattern() const;
|
||||
|
||||
INLINE void set_without_pattern(const string &pattern);
|
||||
INLINE const string &get_without_pattern() const;
|
||||
|
||||
INLINE void set_geometry(NodeRelation *arc);
|
||||
INLINE bool has_geometry() const;
|
||||
INLINE NodeRelation *get_geometry() const;
|
||||
@ -108,7 +114,21 @@ public:
|
||||
bool remove_group(MouseWatcherGroup *group);
|
||||
|
||||
private:
|
||||
void set_current_region(MouseWatcherRegion *region);
|
||||
typedef pvector< PT(MouseWatcherRegion) > VRegions;
|
||||
void get_over_regions(VRegions ®ions, const LPoint2f &pos) const;
|
||||
static MouseWatcherRegion *get_preferred_region(const VRegions ®ions);
|
||||
|
||||
void set_current_regions(VRegions ®ions);
|
||||
void clear_current_regions();
|
||||
static void intersect_regions(MouseWatcher::VRegions &result,
|
||||
const MouseWatcher::VRegions ®ions_a,
|
||||
const MouseWatcher::VRegions ®ions_b);
|
||||
static void remove_region_from(MouseWatcher::VRegions ®ions,
|
||||
MouseWatcherRegion *region);
|
||||
static void remove_regions_from(MouseWatcher::VRegions ®ions,
|
||||
MouseWatcherGroup *group);
|
||||
|
||||
|
||||
void throw_event_pattern(const string &pattern,
|
||||
const MouseWatcherRegion *region,
|
||||
const ButtonHandle &button);
|
||||
@ -125,14 +145,17 @@ private:
|
||||
int _suppress_flags;
|
||||
LPoint2f _mouse;
|
||||
|
||||
PT(MouseWatcherRegion) _current_region;
|
||||
PT(MouseWatcherRegion) _button_down_region;
|
||||
VRegions _current_regions;
|
||||
PT(MouseWatcherRegion) _preferred_region;
|
||||
PT(MouseWatcherRegion) _preferred_button_down_region;
|
||||
bool _button_down;
|
||||
|
||||
string _button_down_pattern;
|
||||
string _button_up_pattern;
|
||||
string _enter_pattern;
|
||||
string _leave_pattern;
|
||||
string _within_pattern;
|
||||
string _without_pattern;
|
||||
|
||||
PT_NodeRelation _geometry;
|
||||
|
||||
|
@ -47,7 +47,10 @@ write(ostream &out, int indent_level) const {
|
||||
// Function: MouseWatcherRegion::enter
|
||||
// Access: Public, Virtual
|
||||
// Description: This is a callback hook function, called whenever the
|
||||
// mouse enters the region.
|
||||
// mouse enters the region. The mouse is only
|
||||
// considered to be "entered" in one region at a time;
|
||||
// in the case of nested regions, it exits the outer
|
||||
// region before entering the inner one.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void MouseWatcherRegion::
|
||||
enter(const MouseWatcherParameter &) {
|
||||
@ -57,12 +60,40 @@ enter(const MouseWatcherParameter &) {
|
||||
// Function: MouseWatcherRegion::exit
|
||||
// Access: Public, Virtual
|
||||
// Description: This is a callback hook function, called whenever the
|
||||
// mouse exits the region.
|
||||
// mouse exits the region. The mouse is only considered
|
||||
// to be "entered" in one region at a time; in the case
|
||||
// of nested regions, it exits the outer region before
|
||||
// entering the inner one.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void MouseWatcherRegion::
|
||||
exit(const MouseWatcherParameter &) {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MouseWatcherRegion::within
|
||||
// Access: Public, Virtual
|
||||
// Description: This is a callback hook function, called whenever the
|
||||
// mouse moves within the boundaries of the region, even
|
||||
// if it is also within the boundaries of a nested
|
||||
// region. This is different from "enter", which is
|
||||
// only called whenever the mouse is within only that
|
||||
// region.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void MouseWatcherRegion::
|
||||
within(const MouseWatcherParameter &) {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MouseWatcherRegion::without
|
||||
// Access: Public, Virtual
|
||||
// Description: This is a callback hook function, called whenever the
|
||||
// mouse moves completely outside the boundaries of the
|
||||
// region. See within().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void MouseWatcherRegion::
|
||||
without(const MouseWatcherParameter &) {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MouseWatcherRegion::press
|
||||
// Access: Public, Virtual
|
||||
|
@ -72,6 +72,8 @@ public:
|
||||
|
||||
virtual void enter(const MouseWatcherParameter ¶m);
|
||||
virtual void exit(const MouseWatcherParameter ¶m);
|
||||
virtual void within(const MouseWatcherParameter ¶m);
|
||||
virtual void without(const MouseWatcherParameter ¶m);
|
||||
virtual void press(const MouseWatcherParameter ¶m);
|
||||
virtual void release(const MouseWatcherParameter ¶m);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user