46 MouseWatcher(
const string &name) :
49 _pixel_xy_input = define_input(
"pixel_xy", EventStoreVec2::get_class_type());
50 _pixel_size_input = define_input(
"pixel_size", EventStoreVec2::get_class_type());
51 _xy_input = define_input(
"xy", EventStoreVec2::get_class_type());
52 _button_events_input = define_input(
"button_events", ButtonEventList::get_class_type());
53 _pointer_events_input = define_input(
"pointer_events", PointerEventList::get_class_type());
55 _pixel_xy_output = define_output(
"pixel_xy", EventStoreVec2::get_class_type());
56 _pixel_size_output = define_output(
"pixel_size", EventStoreVec2::get_class_type());
57 _xy_output = define_output(
"xy", EventStoreVec2::get_class_type());
58 _button_events_output = define_output(
"button_events", ButtonEventList::get_class_type());
66 _internal_suppress = 0;
67 _preferred_region =
nullptr;
68 _preferred_button_down_region =
nullptr;
71 _display_region =
nullptr;
72 _button_down_display_region =
nullptr;
74 _frame.set(-1.0f, 1.0f, -1.0f, 1.0f);
76 _inactivity_timeout = inactivity_timeout;
77 _has_inactivity_timeout = !IS_NEARLY_ZERO(_inactivity_timeout);
79 _num_trail_recent = 0;
80 _trail_log_duration = 0.0;
83 _inactivity_timeout_event =
"inactivity_timeout";
85 _inactivity_state = IS_active;
90 _enter_multiple =
false;
94 _implicit_click =
false;
112 remove_region_from(_current_regions, region);
113 if (region == _preferred_region) {
114 if (_preferred_region !=
nullptr) {
117 _preferred_region =
nullptr;
119 if (region == _preferred_button_down_region) {
120 _preferred_button_down_region =
nullptr;
123 return MouseWatcherBase::do_remove_region(region);
136 get_over_regions(regions, pos);
137 return get_preferred_region(regions);
158 Groups::const_iterator gi =
159 find(_groups.begin(), _groups.end(), pt);
160 if (gi != _groups.end()) {
166 if (!_show_regions_render2d.
is_empty()) {
167 group->
show_regions(_show_regions_render2d, _show_regions_bin_name,
168 _show_regions_draw_order);
173 _groups.push_back(pt);
187 group->do_sort_regions();
190 intersect_regions(only_a, only_b, both,
191 _current_regions, group->_regions);
192 set_current_regions(only_a);
194 if (has_region_in(both, _preferred_region)) {
195 if (_preferred_region !=
nullptr) {
198 _preferred_region =
nullptr;
200 if (has_region_in(both, _preferred_button_down_region)) {
201 _preferred_button_down_region =
nullptr;
205 if (!_show_regions_render2d.
is_empty()) {
206 group->do_hide_regions();
212 Groups::iterator gi =
213 find(_groups.begin(), _groups.end(), pt);
214 if (gi != _groups.end()) {
235 if (old_group == new_group) {
245 old_group->do_sort_regions();
246 new_group->do_sort_regions();
249 if (!_show_regions_render2d.
is_empty()) {
250 old_group->do_hide_regions();
251 new_group->do_show_regions(_show_regions_render2d, _show_regions_bin_name,
252 _show_regions_draw_order);
258 intersect_regions(remove, add, keep,
259 old_group->_regions, new_group->_regions);
262 bool any_new_current_regions =
false;
265 if (!remove.
empty()) {
267 intersect_regions(only_a, only_b, both,
268 _current_regions, remove);
269 new_current_regions.
swap(only_a);
270 any_new_current_regions =
true;
272 if (has_region_in(both, _preferred_region)) {
273 if (_preferred_region !=
nullptr) {
276 _preferred_region =
nullptr;
278 if (has_region_in(both, _preferred_button_down_region)) {
279 _preferred_button_down_region =
nullptr;
301 if (any_new_current_regions) {
302 set_current_regions(new_current_regions);
307 Groups::iterator gi =
308 find(_groups.begin(), _groups.end(), pt);
309 if (gi == _groups.end()) {
310 _groups.push_back(new_group);
314 if (!_show_regions_render2d.
is_empty()) {
315 new_group->do_update_regions();
321 gi = find(_groups.begin(), _groups.end(), pt);
322 if (gi != _groups.end()) {
339 return _groups.size();
348 nassertr(n >= 0 && n < (
int)_groups.size(),
nullptr);
359 if (duration < 0.0) {
362 _trail_log_duration = duration;
363 discard_excess_trail_log();
374 discard_excess_trail_log() {
375 if (_trail_log_duration == 0.0) {
378 if (_trail_log->get_num_events() > 2) {
380 while ((_trail_log->get_num_events() > 2)&&
381 (_trail_log->get_time(0) <= old)&&
382 (_trail_log->get_time(1) <= old)) {
383 _trail_log->pop_front();
402 if (_trail_node ==
nullptr) {
403 _trail_node =
new GeomNode(
"Mouse Trail Node");
417 _trail_node =
nullptr;
424 update_trail_node() {
425 if (_trail_node ==
nullptr) {
428 _trail_node->remove_all_geoms();
430 if (_trail_log->get_num_events() < 2) {
441 double xscale = 2.0 / _pixel_size->get_value().get_x();
442 double yscale = 2.0 / _pixel_size->get_value().get_y();
444 for (
int i=0; i<(int)_trail_log->get_num_events(); i++) {
445 double x = (_trail_log->get_xpos(i) * xscale) - 1.0;
446 double y = (_trail_log->get_ypos(i) * yscale) - 1.0;
447 vertex.add_data3(LVecBase3(x,0.0,-y));
448 lines->add_vertex(i);
450 lines->close_primitive();
453 l_geom->add_primitive(lines);
454 _trail_node->add_geom(l_geom);
470 switch (_inactivity_state) {
475 _inactivity_state = IS_inactive_to_active;
478 case IS_active_to_inactive:
479 _inactivity_state = IS_active;
482 case IS_inactive_to_active:
492 output(std::ostream &out)
const {
494 DataNode::output(out);
500 size_t count = _regions.size();
502 count += group->get_num_regions();
505 out <<
" (" << count <<
" regions)";
512 write(std::ostream &out,
int indent_level)
const {
514 <<
"MouseWatcher " << get_name() <<
":\n";
515 MouseWatcherBase::write(out, indent_level + 2);
519 indent(out, indent_level + 2)
521 group->write(out, indent_level + 4);
531 nassertv(_lock.debug_is_locked());
534 PN_stdfloat mx = (pos[0] + 1.0f) * 0.5f * (_frame[1] - _frame[0]) + _frame[0];
535 PN_stdfloat my = (pos[1] + 1.0f) * 0.5f * (_frame[3] - _frame[2]) + _frame[2];
549 const LVecBase4 &frame = region->get_frame();
551 if (region->get_active() &&
552 mx >= frame[0] && mx <= frame[1] &&
553 my >= frame[2] && my <= frame[3]) {
561 group->sort_regions();
564 const LVecBase4 &frame = region->get_frame();
567 mx >= frame[0] && mx <= frame[1] &&
568 my >= frame[2] && my <= frame[3]) {
578 sort(regions.
begin(), regions.
end());
588 if (regions.
empty()) {
592 Regions::const_iterator ri;
593 ri = regions.
begin();
596 while (ri != regions.
end()) {
599 if (*region < *preferred) {
617 nassertv(_lock.debug_is_locked());
625 Regions::const_iterator new_ri = regions.
begin();
626 Regions::const_iterator old_ri = _current_regions.
begin();
630 std::vector<MouseWatcherRegion *> new_regions;
632 bool any_changes =
false;
633 while (new_ri != regions.
end() && old_ri != _current_regions.
end()) {
634 if ((*new_ri) < (*old_ri)) {
637 new_regions.push_back(new_region);
641 }
else if ((*old_ri) < (*new_ri)) {
644 without_region(old_region, param);
655 while (new_ri != regions.
end()) {
658 new_regions.push_back(new_region);
663 while (old_ri != _current_regions.
end()) {
666 without_region(old_region, param);
674 _current_regions.
swap(regions);
677 std::vector<MouseWatcherRegion *>::const_iterator ri;
678 for (ri = new_regions.begin(); ri != new_regions.end(); ++ri) {
680 within_region(new_region, param);
684 if (!_enter_multiple) {
689 get_preferred_region(_current_regions);
691 if (_button_down && new_preferred_region != _preferred_button_down_region) {
694 new_preferred_region =
nullptr;
697 if (new_preferred_region != _preferred_region) {
698 if (_preferred_region !=
nullptr) {
699 exit_region(_preferred_region, param);
701 _preferred_region = new_preferred_region;
702 if (_preferred_region !=
nullptr) {
703 enter_region(_preferred_region, param);
713 clear_current_regions() {
714 nassertv(_lock.debug_is_locked());
716 if (!_current_regions.
empty()) {
722 Regions::const_iterator old_ri = _current_regions.
begin();
724 while (old_ri != _current_regions.
end()) {
728 throw_event_pattern(_leave_pattern, old_region, ButtonHandle::none());
729 if (_preferred_region == old_region) {
730 _preferred_region =
nullptr;
735 _current_regions.
clear();
737 if (_preferred_region !=
nullptr) {
738 _preferred_region->exit_region(param);
739 throw_event_pattern(_leave_pattern, _preferred_region, ButtonHandle::none());
740 _preferred_region =
nullptr;
750 do_show_regions(
const NodePath &render2d,
const string &bin_name,
753 MouseWatcherBase::do_show_regions(render2d, bin_name, draw_order);
754 _show_regions_render2d = render2d;
755 _show_regions_bin_name = bin_name;
756 _show_regions_draw_order = draw_order;
759 group->show_regions(render2d, bin_name, draw_order);
771 MouseWatcherBase::do_hide_regions();
772 _show_regions_render2d =
NodePath();
773 _show_regions_bin_name = string();
774 _show_regions_draw_order = 0;
777 group->hide_regions();
798 Regions::const_iterator a_ri = regions_a.
begin();
799 Regions::const_iterator b_ri = regions_b.
begin();
801 while (a_ri != regions_a.
end() && b_ri != regions_b.
end()) {
802 if ((*a_ri) < (*b_ri)) {
807 }
else if ((*b_ri) < (*a_ri)) {
830 Regions::iterator ri = lower_bound(regions.
begin(), regions.
end(), ptr);
831 if (ri != regions.
end() && (*ri) == ptr) {
848 Regions::const_iterator ri = lower_bound(regions.
begin(), regions.
end(), ptr);
849 return (ri != regions.
end() && (*ri) == ptr);
859 if (pattern.empty()) {
863 if (region !=
nullptr) {
869 if (button != ButtonHandle::none()) {
879 for (
size_t p = 0; p < pattern.size(); ++p) {
880 if (pattern[p] ==
'%') {
881 string cmd = pattern.substr(p + 1, 1);
884 if (region !=
nullptr) {
885 event += region->get_name();
888 }
else if (cmd ==
"b") {
893 <<
"Invalid symbol in event_pattern: %" << cmd <<
"\n";
900 if (!event.empty()) {
914 nassertv(_lock.debug_is_locked());
920 if (_preferred_button_down_region !=
nullptr) {
921 _preferred_button_down_region->move(param);
930 nassertv(_lock.debug_is_locked());
942 _preferred_button_down_region = _preferred_region;
946 if (_preferred_button_down_region !=
nullptr) {
947 _preferred_button_down_region->press(param);
949 throw_event_pattern(_button_repeat_pattern,
950 _preferred_button_down_region, button);
952 throw_event_pattern(_button_down_pattern,
953 _preferred_button_down_region, button);
960 if (_preferred_region !=
nullptr) {
963 _preferred_region->press(param);
964 consider_keyboard_suppress(_preferred_region);
967 if ((_internal_suppress & MouseWatcherRegion::SF_other_button) == 0) {
972 global_keyboard_press(param);
982 nassertv(_lock.debug_is_locked());
993 if (_preferred_button_down_region !=
nullptr) {
994 param.
set_outside(_preferred_button_down_region != _preferred_region);
995 _preferred_button_down_region->release(param);
996 throw_event_pattern(_button_up_pattern,
997 _preferred_button_down_region, button);
1003 bool has_button =
false;
1004 for (
size_t i = 0; i < MouseButton::num_mouse_buttons; ++i) {
1005 if (MouseButton::_buttons[i] != button &&
1006 _current_buttons_down.
get_bit(MouseButton::_buttons[i].get_index())) {
1013 _button_down =
false;
1014 _preferred_button_down_region =
nullptr;
1020 if (_preferred_region !=
nullptr) {
1021 _preferred_region->release(param);
1025 global_keyboard_release(param);
1033 keystroke(
int keycode) {
1034 nassertv(_lock.debug_is_locked());
1055 consider_keyboard_suppress(region);
1061 group->sort_regions();
1067 consider_keyboard_suppress(region);
1078 candidate(
const std::wstring &candidate_string,
size_t highlight_start,
1079 size_t highlight_end,
size_t cursor_pos) {
1080 nassertv(_lock.debug_is_locked());
1083 param.
set_candidate(candidate_string, highlight_start, highlight_end, cursor_pos);
1104 group->sort_regions();
1122 nassertv(_lock.debug_is_locked());
1130 if (region != _preferred_region && region->
get_keyboard()) {
1131 region->
press(param);
1132 consider_keyboard_suppress(region);
1138 group->sort_regions();
1141 if (region != _preferred_region && region->
get_keyboard()) {
1142 region->
press(param);
1143 consider_keyboard_suppress(region);
1155 nassertv(_lock.debug_is_locked());
1163 if (region != _preferred_region && region->
get_keyboard()) {
1170 group->sort_regions();
1173 if (region != _preferred_region && region->
get_keyboard()) {
1186 nassertv(_lock.debug_is_locked());
1189 throw_event_pattern(_enter_pattern, region, ButtonHandle::none());
1190 if (_implicit_click) {
1193 region->
press(param1);
1203 nassertv(_lock.debug_is_locked());
1205 if (_implicit_click) {
1211 throw_event_pattern(_leave_pattern, region, ButtonHandle::none());
1220 nassertv(_lock.debug_is_locked());
1224 if (!_geometry.is_null()) {
1225 _geometry->set_overall_hidden(
true);
1230 clear_current_regions();
1238 set_mouse(
const LVecBase2 &xy,
const LVecBase2 &pixel_xy) {
1239 nassertv(_lock.debug_is_locked());
1241 if (!_geometry.is_null()) {
1243 _geometry->set_transform(TransformState::make_pos(LVecBase3(xy[0], 0, xy[1])));
1246 _geometry->set_overall_hidden(
false);
1252 _mouse_pixel = pixel_xy;
1255 get_over_regions(regions, _mouse);
1256 set_current_regions(regions);
1270 _external_suppress |= MouseWatcherRegion::SF_other_button;
1288 bool activity =
false;
1292 _internal_suppress = 0;
1293 _external_suppress = 0;
1297 DCAST_INTO_V(pixel_size, input.
get_data(_pixel_size_input).
get_ptr());
1298 output.
set_data(_pixel_size_output, pixel_size);
1299 _pixel_size = pixel_size;
1311 const LVecBase2 &last_f = _xy->get_value();
1317 if (_display_region !=
nullptr) {
1319 if (constrain_display_region(_display_region, f, p, current_thread)) {
1328 _internal_suppress |= MouseWatcherRegion::SF_mouse_button;
1338 _num_trail_recent = 0;
1339 if (input.
has_data(_pointer_events_input) && (_trail_log_duration > 0.0)) {
1341 DCAST_INTO_V(this_pointer_events, input.
get_data(_pointer_events_input).
get_ptr());
1343 for (
size_t i = 0; i < _num_trail_recent; i++) {
1345 int xpos = this_pointer_events->
get_xpos(i);
1346 int ypos = this_pointer_events->
get_ypos(i);
1348 double time = this_pointer_events->
get_time(i);
1349 _trail_log->add_event(in_win, xpos, ypos, sequence, time);
1352 if (_trail_log->get_num_events() > 0) {
1353 discard_excess_trail_log();
1354 update_trail_node();
1356 if (_num_trail_recent > _trail_log->get_num_events()) {
1357 _num_trail_recent = _trail_log->get_num_events();
1363 if (_preferred_region !=
nullptr) {
1364 _internal_suppress |= _preferred_region->get_suppress_flags();
1370 if (input.
has_data(_button_events_input)) {
1372 DCAST_INTO_V(this_button_events, input.
get_data(_button_events_input).
get_ptr());
1374 for (
int i = 0; i < num_events; i++) {
1379 case ButtonEvent::T_down:
1385 press(be._button,
false);
1392 case ButtonEvent::T_repeat:
1394 press(be._button,
true);
1399 case ButtonEvent::T_up:
1402 release(be._button);
1406 case ButtonEvent::T_keystroke:
1409 keystroke(be._keycode);
1413 case ButtonEvent::T_candidate:
1415 candidate(be._candidate_string, be._highlight_start, be._highlight_end, be._cursor_pos);
1419 case ButtonEvent::T_resume_down:
1425 case ButtonEvent::T_move:
1429 case ButtonEvent::T_raw_down:
1430 case ButtonEvent::T_raw_up:
1447 if (_has_inactivity_timeout) {
1453 double elapsed = now - _last_activity;
1456 if (elapsed > _inactivity_timeout) {
1457 switch (_inactivity_state) {
1459 _inactivity_state = IS_active_to_inactive;
1465 case IS_active_to_inactive:
1468 case IS_inactive_to_active:
1469 _inactivity_state = IS_inactive;
1476 switch (_inactivity_state) {
1481 case IS_active_to_inactive:
1483 if (tform_cat.is_debug()) {
1485 <<
"MouseWatcher detected " << _inactivity_timeout
1486 <<
" seconds of inactivity; releasing held buttons.\n";
1489 for (
size_t i = 0; i < _current_buttons_down.
get_num_bits(); ++i) {
1490 if (_current_buttons_down.
get_bit(i)) {
1496 _inactivity_state = IS_inactive;
1497 throw_event(_inactivity_timeout_event);
1500 case IS_inactive_to_active:
1503 for (
size_t i = 0; i < _current_buttons_down.
get_num_bits(); ++i) {
1504 if (_current_buttons_down.
get_bit(i)) {
1510 _inactivity_state = IS_active;
1515 (_internal_suppress & MouseWatcherRegion::SF_mouse_position) == 0) {
1517 _xy->set_value(_mouse);
1519 _pixel_xy->set_value(_mouse_pixel);
1524 int suppress_buttons = ((_internal_suppress | _external_suppress) & MouseWatcherRegion::SF_any_button);
1526 _button_events->clear();
1529 for (
int i = 0; i < num_events; i++) {
1531 bool suppress =
true;
1533 if (be._type != ButtonEvent::T_keystroke &&
1535 suppress = ((suppress_buttons & MouseWatcherRegion::SF_mouse_button) != 0);
1537 suppress = ((suppress_buttons & MouseWatcherRegion::SF_other_button) != 0);
1540 if (!suppress || be._type == ButtonEvent::T_up) {
1542 _button_events->add_event(be);
1546 if (_button_events->get_num_events() != 0) {
1559 LVecBase2 &f, LVecBase2 &p,
1560 Thread *current_thread) {
1561 if (!_button_down) {
1562 _button_down_display_region =
nullptr;
1564 if (_button_down_display_region !=
nullptr) {
1568 display_region = _button_down_display_region;
1575 DCAST_INTO_R(stereo_display_region, display_region,
false);
1576 return constrain_display_region(stereo_display_region->
get_left_eye(), f, p, current_thread) ||
1577 constrain_display_region(stereo_display_region->
get_right_eye(), f, p, current_thread);
1582 PN_stdfloat left, right, bottom, top;
1583 dr_reader.get_dimensions(left, right, bottom, top);
1586 PN_stdfloat x = (f[0] + 1.0f) / 2.0f;
1587 PN_stdfloat y = (f[1] + 1.0f) / 2.0f;
1589 if (_button_down_display_region ==
nullptr &&
1590 (x < left || x >= right || y < bottom || y >= top)) {
1597 _button_down_display_region = display_region;
1601 PN_stdfloat xp = (x - left) / (right - left);
1603 PN_stdfloat xpp = (xp * 2.0f) - 1.0f;
1605 PN_stdfloat yp = (y - bottom) / (top - bottom);
1606 PN_stdfloat ypp = (yp * 2.0f) - 1.0f;
1612 p.set(p[0] - xo, p[1] - yo);
void clear_bit(int index)
Sets the nth bit off.
size_t get_num_bits() const
Returns the current number of possibly different bits in this array.
void set_bit(int index)
Sets the nth bit on.
bool get_bit(int index) const
Returns true if the nth bit is set, false if it is cleared.
get_frame_time
Returns the time in seconds as of the last time tick() was called (typically, this will be as of the ...
static ClockObject * get_global_clock()
Returns a pointer to the global ClockObject.
This object supervises the traversal of the data graph and the moving of data from one DataNode to it...
Thread * get_current_thread() const
Returns the currently-executing thread object, as passed to the DataGraphTraverser constructor.
Encapsulates the data generated from (or sent into) any particular DataNode.
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...
void set_data(int index, const EventParameter &data)
Sets the data for the indicated parameter.
bool has_data(int index) const
Returns true if the indicated parameter has been stored, false otherwise.
The fundamental type of node for the data graph.
Encapsulates the data from a DisplayRegion, pre-fetched for one stage of the pipeline.
A rectangular subregion within a window for rendering into.
is_stereo
Returns true if this is a StereoDisplayRegion, false otherwise.
void get_region_pixels_i(int &xo, int &yo, int &w, int &h) const
Similar to get_region_pixels(), but returns the upper left corner, and the pixel numbers are numbered...
An optional parameter associated with an event.
TypedWritableReferenceCount * get_ptr() const
Retrieves a pointer to the actual value stored in the parameter.
Defines a series of line strips.
A node that holds Geom objects, renderable pieces of geometry.
This defines the actual numeric vertex data stored in a Geom, in the structure defined by a particula...
This object provides a high-level interface for quickly writing a sequence of numeric values from a v...
A container for geometry primitives.
Similar to MutexHolder, but for a light mutex.
void show_regions(const NodePath &render2d, const std::string &bin_name, int draw_order)
Enables the visualization of all of the regions handled by this MouseWatcherBase.
This represents a collection of MouseWatcherRegions that may be managed as a group.
This is sent along as a parameter to most events generated for a region to indicate the mouse and but...
void set_keyrepeat(bool flag)
Sets the state of the "keyrepeat" flag.
void set_mouse(const LPoint2 &mouse)
Sets the mouse position that was current at the time the event was generated.
void set_keycode(int keycode)
Sets the keycode associated with this event, if any.
void set_modifier_buttons(const ModifierButtons &mods)
Sets the modifier buttons that were being held while this event was generated.
void set_candidate(const std::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.
void set_outside(bool flag)
Sets the state of the "outside" flag.
void set_button(const ButtonHandle &button)
Sets the mouse or keyboard button that generated this event, if any.
This is the class that defines a rectangular region on the screen for the MouseWatcher.
virtual void release(const MouseWatcherParameter ¶m)
This is a callback hook function, called whenever a mouse or keyboard button previously depressed wit...
virtual void keystroke(const MouseWatcherParameter ¶m)
This is a callback hook function, called whenever a keystroke is generated by the user.
virtual void exit_region(const MouseWatcherParameter ¶m)
This is a callback hook function, called whenever the mouse exits the region.
virtual void press(const MouseWatcherParameter ¶m)
This is a callback hook function, called whenever a mouse or keyboard button is depressed while the m...
get_active
Returns whether the region is active or not.
get_suppress_flags
Returns the current suppress_flags.
virtual void enter_region(const MouseWatcherParameter ¶m)
This is a callback hook function, called whenever the mouse enters the region.
virtual void candidate(const MouseWatcherParameter ¶m)
This is a callback hook function, called whenever an IME candidate is highlighted by the user.
get_keyboard
Returns whether the region is interested in global keyboard events; see set_keyboard().
This TFormer maintains a list of rectangular regions on the screen that are considered special mouse ...
bool add_group(MouseWatcherGroup *group)
Adds the indicated group of regions to the set of regions the MouseWatcher will monitor each frame.
bool remove_group(MouseWatcherGroup *group)
Removes the indicated group from the set of extra groups associated with the MouseWatcher.
void set_trail_log_duration(double duration)
If the duration is nonzero, causes the MouseWatcher to log the mouse's trail.
get_group
Returns the nth group added to the MouseWatcher via add_group().
bool replace_group(MouseWatcherGroup *old_group, MouseWatcherGroup *new_group)
Atomically removes old_group from the MouseWatcher, and replaces it with new_group.
void clear_trail_node()
If you have previously fetched the trail node using get_trail_node, then the MouseWatcher is continua...
void note_activity()
Can be used in conjunction with the inactivity timeout to inform the MouseWatcher that the user has j...
bool remove_region(MouseWatcherRegion *region)
Removes the indicated region from the group.
MouseWatcherRegion * get_over_region() const
Returns the smallest region the mouse is currently over, or NULL if it is over no region.
get_num_groups
Returns the number of separate groups added to the MouseWatcher via add_group().
NodePath is the fundamental system for disambiguating instances, and also provides a higher-level int...
bool is_empty() const
Returns true if the NodePath contains no nodes.
A handy class object for storing simple values (like integers or strings) passed along with an Event ...
get_value
Retrieves the value stored in the parameter.
Records a set of pointer events that happened recently.
int get_xpos(size_t n) const
Get the x-coordinate of the nth event.
int get_sequence(size_t n) const
Get the sequence number of the nth event.
double get_time(size_t n) const
Get the timestamp of the nth event.
size_t get_num_events() const
Returns the number of events in the list.
int get_ypos(size_t n) const
Get the y-coordinate of the nth event.
bool get_in_window(size_t n) const
Get the in-window flag of the nth event.
bool test_ref_count_integrity() const
Does some easy checks to make sure that the reference count isn't completely bogus.
This is a special DisplayRegion wrapper that actually includes a pair of DisplayRegions internally: t...
get_right_eye
Returns a pointer to the right DisplayRegion managed by this stereo object.
get_left_eye
Returns a pointer to the left DisplayRegion managed by this stereo object.
A thread; that is, a lightweight process.
TypeHandle is the identifier used to differentiate C++ class types.
iterator_0 begin()
Returns the iterator that marks the first element in the ordered vector.
void push_back(const value_type_0 &key)
Adds the new element to the end of the vector without regard for proper sorting.
void swap(ordered_vector< Key, Compare, Vector > &other)
Exchanges the contents of this vector and the other vector, in constant time (e.g....
bool empty() const
Returns true if the ordered vector is empty, false otherwise.
iterator_0 end()
Returns the iterator that marks the end of the ordered vector.
void clear()
Removes all elements from the ordered vector.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
std::ostream & indent(std::ostream &out, int indent_level)
A handy function for doing text formatting.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PT(GeomNode) MouseWatcher
Returns a GeomNode that represents the mouse trail.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.