15 #include "mouseWatcher.h" 16 #include "config_tform.h" 17 #include "dataGraphTraverser.h" 18 #include "mouseWatcherParameter.h" 19 #include "mouseAndKeyboard.h" 20 #include "mouseData.h" 21 #include "buttonEventList.h" 22 #include "mouseButton.h" 23 #include "throw_event.h" 24 #include "eventParameter.h" 25 #include "dataNodeTransmit.h" 26 #include "transformState.h" 27 #include "displayRegion.h" 28 #include "stereoDisplayRegion.h" 29 #include "geomVertexWriter.h" 30 #include "geomLinestrips.h" 31 #include "geomPoints.h" 34 #include "lightMutexHolder.h" 35 #include "nearly_zero.h" 47 MouseWatcher(
const string &name) :
50 _pixel_xy_input = define_input(
"pixel_xy", EventStoreVec2::get_class_type());
51 _pixel_size_input = define_input(
"pixel_size", EventStoreVec2::get_class_type());
52 _xy_input = define_input(
"xy", EventStoreVec2::get_class_type());
53 _button_events_input = define_input(
"button_events", ButtonEventList::get_class_type());
54 _pointer_events_input = define_input(
"pointer_events", PointerEventList::get_class_type());
56 _pixel_xy_output = define_output(
"pixel_xy", EventStoreVec2::get_class_type());
57 _pixel_size_output = define_output(
"pixel_size", EventStoreVec2::get_class_type());
58 _xy_output = define_output(
"xy", EventStoreVec2::get_class_type());
59 _button_events_output = define_output(
"button_events", ButtonEventList::get_class_type());
67 _internal_suppress = 0;
75 _frame.set(-1.0f, 1.0f, -1.0f, 1.0f);
77 _inactivity_timeout = inactivity_timeout;
78 _has_inactivity_timeout = !IS_NEARLY_ZERO(_inactivity_timeout);
80 _num_trail_recent = 0;
81 _trail_log_duration = 0.0;
84 _inactivity_timeout_event =
"inactivity_timeout";
86 _inactivity_state = IS_active;
92 _enter_multiple =
false;
97 _implicit_click =
false;
120 remove_region_from(_current_regions, region);
121 if (region == _preferred_region) {
127 if (region == _preferred_button_down_region) {
131 return MouseWatcherBase::do_remove_region(region);
148 get_over_regions(regions, pos);
149 return get_preferred_region(regions);
174 Groups::const_iterator gi =
175 find(_groups.begin(), _groups.end(), pt);
176 if (gi != _groups.end()) {
182 if (!_show_regions_render2d.
is_empty()) {
183 group->
show_regions(_show_regions_render2d, _show_regions_bin_name,
184 _show_regions_draw_order);
189 _groups.push_back(pt);
206 group->do_sort_regions();
209 intersect_regions(only_a, only_b, both,
210 _current_regions, group->_regions);
211 set_current_regions(only_a);
213 if (has_region_in(both, _preferred_region)) {
219 if (has_region_in(both, _preferred_button_down_region)) {
224 if (!_show_regions_render2d.
is_empty()) {
225 group->do_hide_regions();
231 Groups::iterator gi =
232 find(_groups.begin(), _groups.end(), pt);
233 if (gi != _groups.end()) {
257 if (old_group == new_group) {
267 old_group->do_sort_regions();
268 new_group->do_sort_regions();
271 if (!_show_regions_render2d.
is_empty()) {
272 old_group->do_hide_regions();
273 new_group->do_show_regions(_show_regions_render2d, _show_regions_bin_name,
274 _show_regions_draw_order);
280 intersect_regions(
remove, add, keep,
281 old_group->_regions, new_group->_regions);
284 bool any_new_current_regions =
false;
287 if (!
remove.empty()) {
289 intersect_regions(only_a, only_b, both,
290 _current_regions,
remove);
291 new_current_regions.swap(only_a);
292 any_new_current_regions =
true;
294 if (has_region_in(both, _preferred_region)) {
300 if (has_region_in(both, _preferred_button_down_region)) {
324 if (any_new_current_regions) {
325 set_current_regions(new_current_regions);
330 Groups::iterator gi =
331 find(_groups.begin(), _groups.end(), pt);
332 if (gi == _groups.end()) {
333 _groups.push_back(new_group);
337 if (!_show_regions_render2d.
is_empty()) {
338 new_group->do_update_regions();
344 gi = find(_groups.begin(), _groups.end(), pt);
345 if (gi != _groups.end()) {
364 return _groups.size();
376 nassertr(n >= 0 && n < (
int)_groups.size(), NULL);
390 if (duration < 0.0) {
393 _trail_log_duration = duration;
394 discard_excess_trail_log();
409 discard_excess_trail_log() {
410 if (_trail_log_duration == 0.0) {
413 if (_trail_log->get_num_events() > 2) {
415 while ((_trail_log->get_num_events() > 2)&&
416 (_trail_log->get_time(0) <= old)&&
417 (_trail_log->get_time(1) <= old)) {
418 _trail_log->pop_front();
443 if (_trail_node == 0) {
444 _trail_node =
new GeomNode(
"Mouse Trail Node");
470 update_trail_node() {
471 if (_trail_node == 0) {
474 _trail_node->remove_all_geoms();
476 if (_trail_log->get_num_events() < 2) {
481 (
"mouseTrailSegs", GeomVertexFormat::get_v3(), Geom::UH_static);
487 double xscale = 2.0 / _pixel_size->get_value().get_x();
488 double yscale = 2.0 / _pixel_size->get_value().get_y();
490 for (
int i=0; i<(int)_trail_log->get_num_events(); i++) {
491 double x = (_trail_log->get_xpos(i) * xscale) - 1.0;
492 double y = (_trail_log->get_ypos(i) * yscale) - 1.0;
494 lines->add_vertex(i);
496 lines->close_primitive();
499 l_geom->add_primitive(lines);
500 _trail_node->add_geom(l_geom);
521 switch (_inactivity_state) {
526 _inactivity_state = IS_inactive_to_active;
529 case IS_active_to_inactive:
530 _inactivity_state = IS_active;
533 case IS_inactive_to_active:
545 output(ostream &out)
const {
547 DataNode::output(out);
549 int count = _regions.size();
550 Groups::const_iterator gi;
551 for (gi = _groups.begin(); gi != _groups.end(); ++gi) {
553 count += group->_regions.size();
556 out <<
" (" << count <<
" regions)";
565 write(ostream &out,
int indent_level)
const {
566 indent(out, indent_level)
567 <<
"MouseWatcher " << get_name() <<
":\n";
568 MouseWatcherBase::write(out, indent_level + 2);
571 if (!_groups.empty()) {
572 Groups::const_iterator gi;
573 for (gi = _groups.begin(); gi != _groups.end(); ++gi) {
575 indent(out, indent_level + 2)
577 group->write(out, indent_level + 4);
591 nassertv(_lock.debug_is_locked());
594 PN_stdfloat mx = (pos[0] + 1.0f) * 0.5f * (_frame[1] - _frame[0]) + _frame[0];
595 PN_stdfloat my = (pos[1] + 1.0f) * 0.5f * (_frame[3] - _frame[2]) + _frame[2];
603 Regions::const_iterator ri;
604 for (ri = _regions.begin(); ri != _regions.end(); ++ri) {
606 const LVecBase4 &frame = region->get_frame();
609 mx >= frame[0] && mx <= frame[1] &&
610 my >= frame[2] && my <= frame[3]) {
612 regions.push_back(region);
617 Groups::const_iterator gi;
618 for (gi = _groups.begin(); gi != _groups.end(); ++gi) {
620 for (ri = group->_regions.begin(); ri != group->_regions.end(); ++ri) {
622 const LVecBase4 &frame = region->get_frame();
625 mx >= frame[0] && mx <= frame[1] &&
626 my >= frame[2] && my <= frame[3]) {
628 regions.push_back(region);
636 sort(regions.begin(), regions.end());
650 if (regions.empty()) {
654 Regions::const_iterator ri;
655 ri = regions.begin();
658 while (ri != regions.end()) {
661 if (*region < *preferred) {
682 nassertv(_lock.debug_is_locked());
687 param.set_mouse(_mouse);
690 Regions::const_iterator new_ri = regions.begin();
691 Regions::const_iterator old_ri = _current_regions.begin();
695 vector<MouseWatcherRegion *> new_regions;
697 bool any_changes =
false;
698 while (new_ri != regions.end() && old_ri != _current_regions.end()) {
699 if ((*new_ri) < (*old_ri)) {
702 new_regions.push_back(new_region);
706 }
else if ((*old_ri) < (*new_ri)) {
709 without_region(old_region, param);
720 while (new_ri != regions.end()) {
723 new_regions.push_back(new_region);
728 while (old_ri != _current_regions.end()) {
731 without_region(old_region, param);
739 _current_regions.swap(regions);
742 vector<MouseWatcherRegion *>::const_iterator ri;
743 for (ri = new_regions.begin(); ri != new_regions.end(); ++ri) {
745 within_region(new_region, param);
749 if (!_enter_multiple) {
754 get_preferred_region(_current_regions);
756 if (_button_down && new_preferred_region != _preferred_button_down_region) {
762 if (new_preferred_region != _preferred_region) {
764 exit_region(_preferred_region, param);
766 _preferred_region = new_preferred_region;
768 enter_region(_preferred_region, param);
781 clear_current_regions() {
782 nassertv(_lock.debug_is_locked());
784 if (!_current_regions.empty()) {
790 Regions::const_iterator old_ri = _current_regions.begin();
792 while (old_ri != _current_regions.end()) {
800 _current_regions.clear();
803 _preferred_region->exit_region(param);
818 do_show_regions(
const NodePath &render2d,
const string &bin_name,
820 MouseWatcherBase::do_show_regions(render2d, bin_name, draw_order);
821 _show_regions_render2d = render2d;
822 _show_regions_bin_name = bin_name;
823 _show_regions_draw_order = draw_order;
825 Groups::const_iterator gi;
826 for (gi = _groups.begin(); gi != _groups.end(); ++gi) {
842 MouseWatcherBase::do_hide_regions();
843 _show_regions_render2d =
NodePath();
844 _show_regions_bin_name = string();
845 _show_regions_draw_order = 0;
847 Groups::const_iterator gi;
848 for (gi = _groups.begin(); gi != _groups.end(); ++gi) {
876 Regions::const_iterator a_ri = regions_a.begin();
877 Regions::const_iterator b_ri = regions_b.begin();
879 while (a_ri != regions_a.end() && b_ri != regions_b.end()) {
880 if ((*a_ri) < (*b_ri)) {
882 only_a.push_back(*a_ri);
885 }
else if ((*b_ri) < (*a_ri)) {
887 only_b.push_back(*b_ri);
892 both.push_back(*a_ri);
911 Regions::iterator ri = lower_bound(regions.begin(), regions.end(), ptr);
912 if (ri != regions.end() && (*ri) == ptr) {
931 Regions::const_iterator ri = lower_bound(regions.begin(), regions.end(), ptr);
932 return (ri != regions.end() && (*ri) == ptr);
944 if (pattern.empty()) {
964 for (
size_t p = 0; p < pattern.
size(); ++p) {
965 if (pattern[p] ==
'%') {
966 string cmd = pattern.substr(p + 1, 1);
970 event += region->get_name();
973 }
else if (cmd ==
"b") {
978 <<
"Invalid symbol in event_pattern: %" << cmd <<
"\n";
985 if (!event.empty()) {
1001 nassertv(_lock.debug_is_locked());
1005 param.set_mouse(_mouse);
1008 _preferred_button_down_region->move(param);
1020 nassertv(_lock.debug_is_locked());
1024 param.set_keyrepeat(keyrepeat);
1025 param.set_modifier_buttons(_mods);
1026 param.set_mouse(_mouse);
1031 if (!_button_down) {
1032 _preferred_button_down_region = _preferred_region;
1034 _button_down =
true;
1037 _preferred_button_down_region->press(param);
1039 throw_event_pattern(_button_repeat_pattern,
1040 _preferred_button_down_region, button);
1042 throw_event_pattern(_button_down_pattern,
1043 _preferred_button_down_region, button);
1055 _preferred_region->press(param);
1056 consider_keyboard_suppress(_preferred_region);
1059 if ((_internal_suppress & MouseWatcherRegion::SF_other_button) == 0) {
1063 param.set_outside(
true);
1064 global_keyboard_press(param);
1077 nassertv(_lock.debug_is_locked());
1081 param.set_modifier_buttons(_mods);
1082 param.set_mouse(_mouse);
1092 param.set_outside(_preferred_button_down_region != _preferred_region);
1093 _preferred_button_down_region->release(param);
1094 throw_event_pattern(_button_up_pattern,
1095 _preferred_button_down_region, button);
1098 _button_down =
false;
1106 _preferred_region->
release(param);
1109 param.set_outside(
true);
1110 global_keyboard_release(param);
1121 keystroke(
int keycode) {
1122 nassertv(_lock.debug_is_locked());
1126 param.set_modifier_buttons(_mods);
1127 param.set_mouse(_mouse);
1135 Regions::const_iterator ri;
1136 for (ri = _regions.begin(); ri != _regions.end(); ++ri) {
1140 param.set_outside(region != _preferred_region);
1142 consider_keyboard_suppress(region);
1147 Groups::const_iterator gi;
1148 for (gi = _groups.begin(); gi != _groups.end(); ++gi) {
1150 for (ri = group->_regions.begin(); ri != group->_regions.end(); ++ri) {
1154 param.set_outside(region != _preferred_region);
1156 consider_keyboard_suppress(region);
1169 candidate(
const wstring &candidate_string,
size_t highlight_start,
1170 size_t highlight_end,
size_t cursor_pos) {
1171 nassertv(_lock.debug_is_locked());
1174 param.
set_candidate(candidate_string, highlight_start, highlight_end, cursor_pos);
1175 param.set_modifier_buttons(_mods);
1176 param.set_mouse(_mouse);
1181 Regions::const_iterator ri;
1182 for (ri = _regions.begin(); ri != _regions.end(); ++ri) {
1186 param.set_outside(region != _preferred_region);
1192 Groups::const_iterator gi;
1193 for (gi = _groups.begin(); gi != _groups.end(); ++gi) {
1195 for (ri = group->_regions.begin(); ri != group->_regions.end(); ++ri) {
1199 param.set_outside(region != _preferred_region);
1215 nassertv(_lock.debug_is_locked());
1217 Regions::const_iterator ri;
1218 for (ri = _regions.begin(); ri != _regions.end(); ++ri) {
1221 if (region != _preferred_region && region->
get_keyboard()) {
1222 region->
press(param);
1223 consider_keyboard_suppress(region);
1228 Groups::const_iterator gi;
1229 for (gi = _groups.begin(); gi != _groups.end(); ++gi) {
1231 for (ri = group->_regions.begin(); ri != group->_regions.end(); ++ri) {
1234 if (region != _preferred_region && region->
get_keyboard()) {
1235 region->
press(param);
1236 consider_keyboard_suppress(region);
1250 nassertv(_lock.debug_is_locked());
1252 Regions::const_iterator ri;
1253 for (ri = _regions.begin(); ri != _regions.end(); ++ri) {
1256 if (region != _preferred_region && region->
get_keyboard()) {
1262 Groups::const_iterator gi;
1263 for (gi = _groups.begin(); gi != _groups.end(); ++gi) {
1265 for (ri = group->_regions.begin(); ri != group->_regions.end(); ++ri) {
1268 if (region != _preferred_region && region->
get_keyboard()) {
1283 nassertv(_lock.debug_is_locked());
1287 if (_implicit_click) {
1290 region->
press(param1);
1302 nassertv(_lock.debug_is_locked());
1304 if (_implicit_click) {
1321 nassertv(_lock.debug_is_locked());
1325 if (!_geometry.is_null()) {
1326 _geometry->set_overall_hidden(
true);
1331 clear_current_regions();
1343 nassertv(_lock.debug_is_locked());
1345 if (!_geometry.is_null()) {
1347 _geometry->set_transform(TransformState::make_pos(
LVecBase3(xy[0], 0, xy[1])));
1350 _geometry->set_overall_hidden(
false);
1356 _mouse_pixel = pixel_xy;
1359 get_over_regions(regions, _mouse);
1360 set_current_regions(regions);
1378 _external_suppress |= MouseWatcherRegion::SF_other_button;
1401 bool activity =
false;
1405 _internal_suppress = 0;
1406 _external_suppress = 0;
1410 DCAST_INTO_V(pixel_size, input.
get_data(_pixel_size_input).
get_ptr());
1411 output.
set_data(_pixel_size_output, pixel_size);
1412 _pixel_size = pixel_size;
1424 const LVecBase2 &last_f = _xy->get_value();
1432 if (constrain_display_region(_display_region, f, p, current_thread)) {
1441 _internal_suppress |= MouseWatcherRegion::SF_mouse_button;
1451 _num_trail_recent = 0;
1452 if (input.
has_data(_pointer_events_input) && (_trail_log_duration > 0.0)) {
1454 DCAST_INTO_V(this_pointer_events, input.
get_data(_pointer_events_input).
get_ptr());
1456 for (
int i = 0; i < _num_trail_recent; i++) {
1458 int xpos = this_pointer_events->
get_xpos(i);
1459 int ypos = this_pointer_events->
get_ypos(i);
1461 double time = this_pointer_events->
get_time(i);
1462 _trail_log->add_event(in_win, xpos, ypos, sequence, time);
1465 if (_trail_log->get_num_events() > 0) {
1466 discard_excess_trail_log();
1467 update_trail_node();
1469 if (_num_trail_recent > _trail_log->get_num_events()) {
1470 _num_trail_recent = _trail_log->get_num_events();
1477 _internal_suppress |= _preferred_region->get_suppress_flags();
1483 if (input.
has_data(_button_events_input)) {
1485 DCAST_INTO_V(this_button_events, input.
get_data(_button_events_input).
get_ptr());
1487 for (
int i = 0; i < num_events; i++) {
1492 case ButtonEvent::T_down:
1498 press(be._button,
false);
1505 case ButtonEvent::T_repeat:
1507 press(be._button,
true);
1512 case ButtonEvent::T_up:
1515 release(be._button);
1519 case ButtonEvent::T_keystroke:
1522 keystroke(be._keycode);
1526 case ButtonEvent::T_candidate:
1528 candidate(be._candidate_string, be._highlight_start, be._highlight_end, be._cursor_pos);
1532 case ButtonEvent::T_resume_down:
1539 case ButtonEvent::T_move:
1543 case ButtonEvent::T_raw_down:
1544 case ButtonEvent::T_raw_up:
1561 if (_has_inactivity_timeout) {
1567 double elapsed = now - _last_activity;
1570 if (elapsed > _inactivity_timeout) {
1571 switch (_inactivity_state) {
1573 _inactivity_state = IS_active_to_inactive;
1579 case IS_active_to_inactive:
1582 case IS_inactive_to_active:
1583 _inactivity_state = IS_inactive;
1590 switch (_inactivity_state) {
1595 case IS_active_to_inactive:
1597 if (tform_cat.is_debug()) {
1599 <<
"MouseWatcher detected " << _inactivity_timeout
1600 <<
" seconds of inactivity; releasing held buttons.\n";
1603 for (
int i = 0; i < _current_buttons_down.
get_num_bits(); ++i) {
1604 if (_current_buttons_down.
get_bit(i)) {
1610 _inactivity_state = IS_inactive;
1611 throw_event(_inactivity_timeout_event);
1614 case IS_inactive_to_active:
1617 for (
int i = 0; i < _current_buttons_down.
get_num_bits(); ++i) {
1618 if (_current_buttons_down.
get_bit(i)) {
1624 _inactivity_state = IS_active;
1629 (_internal_suppress & MouseWatcherRegion::SF_mouse_position) == 0) {
1631 _xy->set_value(_mouse);
1633 _pixel_xy->set_value(_mouse_pixel);
1638 int suppress_buttons = ((_internal_suppress | _external_suppress) & MouseWatcherRegion::SF_any_button);
1640 _button_events->clear();
1643 for (
int i = 0; i < num_events; i++) {
1645 bool suppress =
true;
1647 if (be._type != ButtonEvent::T_keystroke &&
1649 suppress = ((suppress_buttons & MouseWatcherRegion::SF_mouse_button) != 0);
1651 suppress = ((suppress_buttons & MouseWatcherRegion::SF_other_button) != 0);
1654 if (!suppress || be._type == ButtonEvent::T_up) {
1656 _button_events->add_event(be);
1660 if (_button_events->get_num_events() != 0) {
1678 Thread *current_thread) {
1679 if (!_button_down) {
1680 _button_down_display_region = NULL;
1682 if (_button_down_display_region != NULL) {
1686 display_region = _button_down_display_region;
1694 DCAST_INTO_R(stereo_display_region, display_region,
false);
1695 return constrain_display_region(stereo_display_region->
get_left_eye(), f, p, current_thread) ||
1696 constrain_display_region(stereo_display_region->
get_right_eye(), f, p, current_thread);
1701 PN_stdfloat left, right, bottom, top;
1702 dr_reader.get_dimensions(left, right, bottom, top);
1705 PN_stdfloat x = (f[0] + 1.0f) / 2.0f;
1706 PN_stdfloat y = (f[1] + 1.0f) / 2.0f;
1708 if (_button_down_display_region == NULL &&
1709 (x < left || x >= right || y < bottom || y >= top)) {
1716 _button_down_display_region = display_region;
1720 PN_stdfloat xp = (x - left) / (right - left);
1722 PN_stdfloat xpp = (xp * 2.0f) - 1.0f;
1724 PN_stdfloat yp = (y - bottom) / (top - bottom);
1725 PN_stdfloat ypp = (yp * 2.0f) - 1.0f;
1728 dr_reader.get_region_pixels_i(xo, yo, w, h);
1731 p.set(p[0] - xo, p[1] - yo);
static ClockObject * get_global_clock()
Returns a pointer to the global ClockObject.
MouseWatcherRegion * get_over_region() const
Returns the smallest region the mouse is currently over, or NULL if it is over no region...
This object provides a high-level interface for quickly writing a sequence of numeric values from a v...
The fundamental type of node for the data graph.
Encapsulates the data from a DisplayRegion, pre-fetched for one stage of the pipeline.
This is the base class for all three-component vectors and points.
int get_num_bits() const
Returns the current number of possibly different bits in this array.
This represents a collection of MouseWatcherRegions that may be managed as a group.
void set_modifier_buttons(const ModifierButtons &mods)
Sets the modifier buttons that were being held while this event was generated.
A class to monitor events from the C++ side of things.
An optional parameter associated with an event.
bool get_bit(int index) const
Returns true if the nth bit is set, false if it is cleared.
virtual void exit_region(const MouseWatcherParameter ¶m)
This is a callback hook function, called whenever the mouse exits the region.
bool is_empty() const
Returns true if the NodePath contains no nodes.
virtual void release(const MouseWatcherParameter ¶m)
This is a callback hook function, called whenever a mouse or keyboard button previously depressed wit...
bool remove_region(MouseWatcherRegion *region)
Removes the indicated region from the group.
void set_trail_log_duration(double duration)
If the duration is nonzero, causes the MouseWatcher to log the mouse's trail.
void set_button(const ButtonHandle &button)
Sets the mouse or keyboard button that generated this event, if any.
int get_suppress_flags() const
Returns the current suppress_flags.
int get_sequence(int n) const
Get the sequence number of the nth event.
virtual void enter_region(const MouseWatcherParameter ¶m)
This is a callback hook function, called whenever the mouse enters the region.
bool test_ref_count_integrity() const
Does some easy checks to make sure that the reference count isn't completely bogus.
int get_xpos(int n) const
Get the x-coordinate of the nth event.
Records a set of pointer events that happened recently.
double get_frame_time(Thread *current_thread=Thread::get_current_thread()) const
Returns the time in seconds as of the last time tick() was called (typically, this will be as of the ...
bool has_data(int index) const
Returns true if the indicated parameter has been stored, false otherwise.
A handy class object for storing simple values (like integers or strings) passed along with an Event ...
void clear_bit(int index)
Sets the nth bit off.
DisplayRegion * get_right_eye()
Returns a pointer to the right DisplayRegion managed by this stereo object.
bool get_keyboard() const
Returns whether the region is interested in global keyboard events; see set_keyboard().
void show_regions(const NodePath &render2d, const string &bin_name, int draw_order)
Enables the visualization of all of the regions handled by this MouseWatcherBase. ...
void hide_regions()
Stops the visualization created by a previous call to show_regions().
virtual void press(const MouseWatcherParameter ¶m)
This is a callback hook function, called whenever a mouse or keyboard button is depressed while the m...
bool get_active() const
Returns whether the region is active or not.
virtual void candidate(const MouseWatcherParameter ¶m)
This is a callback hook function, called whenever an IME candidate is highlighted by the user...
void set_data(int index, const EventParameter &data)
Sets the data for the indicated parameter.
bool get_in_window(int n) const
Get the in-window flag of the nth event.
void set_mouse(const LPoint2 &mouse)
Sets the mouse position that was current at the time the event was generated.
Similar to MutexHolder, but for a light mutex.
This is the class that defines a rectangular region on the screen for the MouseWatcher.
This defines the actual numeric vertex data stored in a Geom, in the structure defined by a particula...
A container for geometry primitives.
Thread * get_current_thread() const
Returns the currently-executing thread object, as passed to the DataGraphTraverser constructor...
void add_data3(PN_stdfloat x, PN_stdfloat y, PN_stdfloat z)
Sets the write row to a particular 3-component value, and advances the write row. ...
This is the base class for all two-component vectors and points.
virtual bool is_stereo() const
Returns true if this is a StereoDisplayRegion, false otherwise.
const Type & get_value() const
Retrieves the value stored in the parameter.
void set_keycode(int keycode)
Sets the keycode associated with this event, if any.
static int size()
Returns 2: the number of components of a LVecBase2.
int get_ypos(int n) const
Get the y-coordinate of the nth event.
TypedWritableReferenceCount * get_ptr() const
Retrieves a pointer to the actual value stored in the parameter.
This is a special DisplayRegion wrapper that actually includes a pair of DisplayRegions internally: t...
This is the base class for all three-component vectors and points.
void set_bit(int index)
Sets the nth bit on.
const EventParameter & get_data(int index) const
Extracts the data for the indicated index, if it has been stored, or the empty parameter if it has no...
bool add_group(MouseWatcherGroup *group)
Adds the indicated group of regions to the set of regions the MouseWatcher will monitor each frame...
int get_num_groups() const
Returns the number of separate groups added to the MouseWatcher via add_group().
virtual void keystroke(const MouseWatcherParameter ¶m)
This is a callback hook function, called whenever a keystroke is generated by the user...
void note_activity()
Can be used in conjunction with the inactivity timeout to inform the MouseWatcher that the user has j...
A thread; that is, a lightweight process.
Defines a series of line strips.
void clear_trail_node()
If you have previously fetched the trail node using get_trail_node, then the MouseWatcher is continua...
A rectangular subregion within a window for rendering into.
bool remove_group(MouseWatcherGroup *group)
Removes the indicated group from the set of extra groups associated with the MouseWatcher.
void set_candidate(const wstring &candidate_string, size_t highlight_start, size_t higlight_end, size_t cursor_pos)
Sets the candidate string associated with this event, if any.
This is a two-component point in space.
double get_time(int n) const
Get the timestamp of the nth event.
TypeHandle is the identifier used to differentiate C++ class types.
DisplayRegion * get_left_eye()
Returns a pointer to the left DisplayRegion managed by this stereo object.
This is sent along as a parameter to most events generated for a region to indicate the mouse and but...
int get_num_events() const
Returns the number of events in the list.
MouseWatcherGroup * get_group(int n) const
Returns the nth group added to the MouseWatcher via add_group().
NodePath is the fundamental system for disambiguating instances, and also provides a higher-level int...
A node that holds Geom objects, renderable pieces of geometry.
Encapsulates the data generated from (or sent into) any particular DataNode.
This object supervises the traversal of the data graph and the moving of data from one DataNode to it...
bool replace_group(MouseWatcherGroup *old_group, MouseWatcherGroup *new_group)
Atomically removes old_group from the MouseWatcher, and replaces it with new_group.