track mouse beyond DisplayRegion too

This commit is contained in:
David Rose 2012-02-22 04:23:11 +00:00
parent 5f649a31c1
commit 849f276dd8
3 changed files with 34 additions and 16 deletions

View File

@ -506,6 +506,7 @@ get_modifier_buttons() const {
INLINE void MouseWatcher:: INLINE void MouseWatcher::
set_display_region(DisplayRegion *dr) { set_display_region(DisplayRegion *dr) {
_display_region = dr; _display_region = dr;
_button_down_display_region = NULL;
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -518,6 +519,7 @@ set_display_region(DisplayRegion *dr) {
INLINE void MouseWatcher:: INLINE void MouseWatcher::
clear_display_region() { clear_display_region() {
_display_region = NULL; _display_region = NULL;
_button_down_display_region = NULL;
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////

View File

@ -70,6 +70,7 @@ MouseWatcher(const string &name) :
_button_down = false; _button_down = false;
_eh = (EventHandler *)NULL; _eh = (EventHandler *)NULL;
_display_region = (DisplayRegion *)NULL; _display_region = (DisplayRegion *)NULL;
_button_down_display_region = (DisplayRegion *)NULL;
_frame.set(-1.0f, 1.0f, -1.0f, 1.0f); _frame.set(-1.0f, 1.0f, -1.0f, 1.0f);
@ -1657,7 +1658,7 @@ do_transmit_data(DataGraphTraverser *trav, const DataNodeTransmit &input,
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: MouseWatcher::constrain_display_region // Function: MouseWatcher::constrain_display_region
// Access: Private, Static // Access: Private
// Description: Constrains the mouse coordinates to within the // Description: Constrains the mouse coordinates to within the
// indicated DisplayRegion. If the mouse pointer does // indicated DisplayRegion. If the mouse pointer does
// indeed fall within the DisplayRegion, rescales f and // indeed fall within the DisplayRegion, rescales f and
@ -1669,14 +1670,25 @@ bool MouseWatcher::
constrain_display_region(DisplayRegion *display_region, constrain_display_region(DisplayRegion *display_region,
LVecBase2 &f, LVecBase2 &p, LVecBase2 &f, LVecBase2 &p,
Thread *current_thread) { Thread *current_thread) {
// If it's a stereo DisplayRegion, we should actually call this if (!_button_down) {
// method twice, once for each eye, in case we have side-by-side _button_down_display_region = NULL;
// stereo. }
if (display_region->is_stereo()) { if (_button_down_display_region != NULL) {
StereoDisplayRegion *stereo_display_region; // If the button went down over this DisplayRegion, we consider
DCAST_INTO_R(stereo_display_region, display_region, false); // the button within the same DisplayRegion until it is released
return constrain_display_region(stereo_display_region->get_left_eye(), f, p, current_thread) || // (even if it wanders outside the borders).
constrain_display_region(stereo_display_region->get_right_eye(), f, p, current_thread); display_region = _button_down_display_region;
} else {
// If it's a stereo DisplayRegion, we should actually call this
// method twice, once for each eye, in case we have side-by-side
// stereo.
if (display_region->is_stereo()) {
StereoDisplayRegion *stereo_display_region;
DCAST_INTO_R(stereo_display_region, display_region, false);
return constrain_display_region(stereo_display_region->get_left_eye(), f, p, current_thread) ||
constrain_display_region(stereo_display_region->get_right_eye(), f, p, current_thread);
}
} }
DisplayRegionPipelineReader dr_reader(display_region, current_thread); DisplayRegionPipelineReader dr_reader(display_region, current_thread);
@ -1686,14 +1698,17 @@ constrain_display_region(DisplayRegion *display_region,
// Need to translate this into DisplayRegion [0, 1] space // Need to translate this into DisplayRegion [0, 1] space
PN_stdfloat x = (f[0] + 1.0f) / 2.0f; PN_stdfloat x = (f[0] + 1.0f) / 2.0f;
PN_stdfloat y = (f[1] + 1.0f) / 2.0f; PN_stdfloat y = (f[1] + 1.0f) / 2.0f;
if (x < left || x >= right || if (_button_down_display_region == NULL &&
y < bottom || y >= top) { (x < left || x >= right || y < bottom || y >= top)) {
// The mouse is outside the display region. // The mouse is outside the display region.
return false; return false;
} }
// The mouse is within the display region; rescale it. // The mouse is within the display region; rescale it.
if (_button_down) {
_button_down_display_region = display_region;
}
// Scale in DR space // Scale in DR space
PN_stdfloat xp = (x - left) / (right - left); PN_stdfloat xp = (x - left) / (right - left);

View File

@ -207,9 +207,9 @@ private:
void discard_excess_trail_log(); void discard_excess_trail_log();
void update_trail_node(); void update_trail_node();
static bool constrain_display_region(DisplayRegion *display_region, bool constrain_display_region(DisplayRegion *display_region,
LVecBase2 &f, LVecBase2 &p, LVecBase2 &f, LVecBase2 &p,
Thread *current_thread); Thread *current_thread);
private: private:
// This wants to be a set, but because you cannot export sets across // This wants to be a set, but because you cannot export sets across
@ -252,6 +252,7 @@ private:
EventHandler *_eh; EventHandler *_eh;
ModifierButtons _mods; ModifierButtons _mods;
DisplayRegion *_display_region; DisplayRegion *_display_region;
DisplayRegion *_button_down_display_region;
bool _has_inactivity_timeout; bool _has_inactivity_timeout;
double _inactivity_timeout; double _inactivity_timeout;