From 081122fe3bbafeb0124bf1516748249c9823317d Mon Sep 17 00:00:00 2001 From: David Rose Date: Sat, 12 Jun 2004 02:12:16 +0000 Subject: [PATCH] define mouseInterfaceNode --- panda/src/putil/modifierButtons.I | 33 ++++++ panda/src/putil/modifierButtons.cxx | 93 ++++++++++++++- panda/src/putil/modifierButtons.h | 8 ++ panda/src/tform/Sources.pp | 3 + panda/src/tform/config_tform.cxx | 1 + panda/src/tform/driveInterface.cxx | 33 ++---- panda/src/tform/driveInterface.h | 11 +- panda/src/tform/mouseInterfaceNode.I | 30 +++++ panda/src/tform/mouseInterfaceNode.cxx | 155 +++++++++++++++++++++++++ panda/src/tform/mouseInterfaceNode.h | 84 ++++++++++++++ panda/src/tform/tform_composite1.cxx | 2 + panda/src/tform/trackball.cxx | 33 +++--- panda/src/tform/trackball.h | 15 +-- 13 files changed, 441 insertions(+), 60 deletions(-) create mode 100644 panda/src/tform/mouseInterfaceNode.I create mode 100644 panda/src/tform/mouseInterfaceNode.cxx create mode 100644 panda/src/tform/mouseInterfaceNode.h diff --git a/panda/src/putil/modifierButtons.I b/panda/src/putil/modifierButtons.I index f7e7ff563c..72723d95b4 100644 --- a/panda/src/putil/modifierButtons.I +++ b/panda/src/putil/modifierButtons.I @@ -66,6 +66,39 @@ operator < (const ModifierButtons &other) const { return _state < other._state; } +//////////////////////////////////////////////////////////////////// +// Function: ModifierButtons::operator & +// Access: Published +// Description: Returns a new ModifierButtons object for which +// is_down() will be true only if it is true on both +// source objects. The set of buttons reported by +// has_button() is not completely defined if both source +// objects have a different set. +//////////////////////////////////////////////////////////////////// +INLINE ModifierButtons ModifierButtons:: +operator & (const ModifierButtons &other) const { + ModifierButtons result = *this; + result &= other; + return result; +} + + +//////////////////////////////////////////////////////////////////// +// Function: ModifierButtons::operator | +// Access: Published +// Description: Returns a new ModifierButtons object for which +// is_down() will be true if it is true on either of the +// source objects. The set of buttons reported by +// has_button() is not completely defined if both source +// objects have a different set. +//////////////////////////////////////////////////////////////////// +INLINE ModifierButtons ModifierButtons:: +operator | (const ModifierButtons &other) const { + ModifierButtons result = *this; + result |= other; + return result; +} + //////////////////////////////////////////////////////////////////// // Function: ModifierButtons::get_num_buttons // Access: Published diff --git a/panda/src/putil/modifierButtons.cxx b/panda/src/putil/modifierButtons.cxx index c5d352d086..1cbdf72777 100644 --- a/panda/src/putil/modifierButtons.cxx +++ b/panda/src/putil/modifierButtons.cxx @@ -29,7 +29,7 @@ ModifierButtons:: ModifierButtons() : _state(0) { - _button_list= PTA(ButtonHandle)::empty_array(0); + _button_list = PTA(ButtonHandle)::empty_array(0); } //////////////////////////////////////////////////////////////////// @@ -53,6 +53,97 @@ ModifierButtons:: ~ModifierButtons() { } +//////////////////////////////////////////////////////////////////// +// Function: ModifierButtons::operator &= +// Access: Published +// Description: Sets is_down() true for any button that is already +// true for this object and the other object. +//////////////////////////////////////////////////////////////////// +void ModifierButtons:: +operator &= (const ModifierButtons &other) { + if (_button_list == other._button_list) { + // Trivially easy case: if the button lists are the same, we can + // do this using a bitmask operation. + _state &= other._state; + + } else { + // More complicated case: if the button lists are different, we + // have to iterate through the buttons and compare them + // case-by-case. This becomes an n^2 operation, but fortunately + // there won't be more than a handful of buttons. + int num_buttons = get_num_buttons(); + for (int i = 0; i < num_buttons; i++) { + if (is_down(i) && !other.is_down(get_button(i))) { + _state &= ~((BitmaskType)1 << i); + } + } + } +} + +//////////////////////////////////////////////////////////////////// +// Function: ModifierButtons::operator |= +// Access: Published +// Description: Sets is_down() true for any button that is already +// true for this object and the other object. Adds +// whatever buttons are necessary to the list to make +// this so +//////////////////////////////////////////////////////////////////// +void ModifierButtons:: +operator |= (const ModifierButtons &other) { + if (_button_list == other._button_list) { + // Trivially easy case: if the button lists are the same, we can + // do this using a bitmask operation. + _state |= other._state; + + } else { + // More complicated case: if the button lists are different, we + // have to iterate through the buttons and compare them + // case-by-case. This becomes an n^2 operation, but fortunately + // there won't be more than a handful of buttons. + int num_buttons = other.get_num_buttons(); + for (int i = 0; i < num_buttons; i++) { + if (other.is_down(i)) { + add_button(other.get_button(i)); + button_down(other.get_button(i)); + } + } + } +} + +//////////////////////////////////////////////////////////////////// +// Function: ModifierButtons::set_button_list +// Access: Published +// Description: Sets the list of buttons to watch to be the same as +// that of the other ModifierButtons object. This makes +// the lists pointer equivalent (until one or the other +// is later modified). +// +// This will preserve the state of any button that was +// on the original list and is also on the new lists. +// Any other buttons will get reset to the default state +// of "up". +//////////////////////////////////////////////////////////////////// +void ModifierButtons:: +set_button_list(const ModifierButtons &other) { + if (_button_list != other._button_list) { + if (_state != 0) { + // If we have some buttons already down, we have to copy them to + // the new state. + BitmaskType new_state = 0; + int num_buttons = other.get_num_buttons(); + for (int i = 0; i < num_buttons; i++) { + if (is_down(other.get_button(i))) { + new_state |= ((BitmaskType)1 << i); + } + } + + _state = new_state; + } + + _button_list = other._button_list; + } +} + //////////////////////////////////////////////////////////////////// // Function: ModifierButtons::matches // Access: Published diff --git a/panda/src/putil/modifierButtons.h b/panda/src/putil/modifierButtons.h index 14cd1e86b3..7c9bcc15e6 100644 --- a/panda/src/putil/modifierButtons.h +++ b/panda/src/putil/modifierButtons.h @@ -41,6 +41,14 @@ PUBLISHED: INLINE bool operator != (const ModifierButtons &other) const; INLINE bool operator < (const ModifierButtons &other) const; + INLINE ModifierButtons operator & (const ModifierButtons &other) const; + INLINE ModifierButtons operator | (const ModifierButtons &other) const; + + void operator &= (const ModifierButtons &other); + void operator |= (const ModifierButtons &other); + + void set_button_list(const ModifierButtons &other); + bool matches(const ModifierButtons &other) const; bool add_button(ButtonHandle button); diff --git a/panda/src/tform/Sources.pp b/panda/src/tform/Sources.pp index 441d5e324c..b6a5774255 100644 --- a/panda/src/tform/Sources.pp +++ b/panda/src/tform/Sources.pp @@ -13,6 +13,7 @@ buttonThrower.I buttonThrower.h \ config_tform.h \ driveInterface.I driveInterface.h \ + mouseInterfaceNode.I mouseInterfaceNode.h \ mouseWatcher.I mouseWatcher.h \ mouseWatcherGroup.h \ mouseWatcherParameter.I mouseWatcherParameter.h \ @@ -24,6 +25,7 @@ buttonThrower.cxx \ config_tform.cxx \ driveInterface.cxx \ + mouseInterfaceNode.cxx \ mouseWatcher.cxx \ mouseWatcherGroup.cxx \ mouseWatcherParameter.cxx mouseWatcherRegion.cxx \ @@ -33,6 +35,7 @@ #define INSTALL_HEADERS \ buttonThrower.I buttonThrower.h \ driveInterface.I driveInterface.h \ + mouseInterfaceNode.I mouseInterfaceNode.h \ mouseWatcher.I mouseWatcher.h \ mouseWatcherGroup.h \ mouseWatcherParameter.I mouseWatcherParameter.h \ diff --git a/panda/src/tform/config_tform.cxx b/panda/src/tform/config_tform.cxx index 86f30edbdd..57979bd9b7 100644 --- a/panda/src/tform/config_tform.cxx +++ b/panda/src/tform/config_tform.cxx @@ -46,6 +46,7 @@ const double drive_horizontal_ramp_down_time = config_tform.GetDouble("drive-hor ConfigureFn(config_tform) { DriveInterface::init_type(); ButtonThrower::init_type(); + MouseInterfaceNode::init_type(); MouseWatcher::init_type(); MouseWatcherGroup::init_type(); MouseWatcherRegion::init_type(); diff --git a/panda/src/tform/driveInterface.cxx b/panda/src/tform/driveInterface.cxx index 55a461876e..34f4899bfc 100644 --- a/panda/src/tform/driveInterface.cxx +++ b/panda/src/tform/driveInterface.cxx @@ -104,7 +104,7 @@ operator < (const DriveInterface::KeyHeld &other) const { //////////////////////////////////////////////////////////////////// DriveInterface:: DriveInterface(const string &name) : - DataNode(name) + MouseInterfaceNode(name) { _xy_input = define_input("xy", EventStoreVec2::get_class_type()); _button_events_input = define_input("button_events", ButtonEventList::get_class_type()); @@ -138,9 +138,7 @@ DriveInterface(const string &name) : _force_mouse = false; _stop_this_frame = false; - _mods.add_button(MouseButton::one()); - _mods.add_button(MouseButton::two()); - _mods.add_button(MouseButton::three()); + watch_button(MouseButton::one()); } @@ -168,8 +166,6 @@ reset() { _down_arrow.clear(); _left_arrow.clear(); _right_arrow.clear(); - - _mods.all_buttons_up(); } @@ -398,13 +394,17 @@ apply(double x, double y, bool any_button) { //////////////////////////////////////////////////////////////////// void DriveInterface:: do_transmit_data(const DataNodeTransmit &input, DataNodeTransmit &output) { + // First, update our modifier buttons. + bool required_buttons_match; + const ButtonEventList *button_events = check_button_events(input, required_buttons_match); + // Look for mouse activity. double x = 0.0f; double y = 0.0f; bool got_mouse = false; - if (input.has_data(_xy_input)) { + if (required_buttons_match && input.has_data(_xy_input)) { const EventStoreVec2 *xy; DCAST_INTO_V(xy, input.get_data(_xy_input).get_ptr()); const LVecBase2f &p = xy->get_value(); @@ -415,28 +415,13 @@ do_transmit_data(const DataNodeTransmit &input, DataNodeTransmit &output) { } // Look for keyboard events. - if (input.has_data(_button_events_input)) { - const ButtonEventList *button_events; - DCAST_INTO_V(button_events, input.get_data(_button_events_input).get_ptr()); + if (required_buttons_match && button_events != (const ButtonEventList *)NULL) { int num_events = button_events->get_num_events(); for (int i = 0; i < num_events; i++) { const ButtonEvent &be = button_events->get_event(i); if (be._type != ButtonEvent::T_keystroke) { bool down = (be._type == ButtonEvent::T_down); - - if (down) { - // We only trap button down events if (a) the mouse is in the - // window, and (b) we aren't set to ignore the mouse. - if (got_mouse && !_ignore_mouse) { - be.update_mods(_mods); - } - } else { - // However, we always trap button up events, so we don't get - // confused and believe a button is still being held down when - // it is not. - be.update_mods(_mods); - } if (be._button == KeyboardButton::up()) { _up_arrow.set_key(down); @@ -451,7 +436,7 @@ do_transmit_data(const DataNodeTransmit &input, DataNodeTransmit &output) { } } - apply(x, y, _mods.is_any_down()); + apply(x, y, !_ignore_mouse && is_down(MouseButton::one())); _transform = TransformState::make_pos_hpr(_xyz, _hpr); _velocity->set_value(_vel); output.set_data(_transform_output, EventParameter(_transform)); diff --git a/panda/src/tform/driveInterface.h b/panda/src/tform/driveInterface.h index ed8b7fe76f..df7cb9b674 100644 --- a/panda/src/tform/driveInterface.h +++ b/panda/src/tform/driveInterface.h @@ -21,7 +21,7 @@ #include "pandabase.h" -#include "dataNode.h" +#include "mouseInterfaceNode.h" #include "modifierButtons.h" #include "luse.h" #include "linmath_events.h" @@ -35,7 +35,7 @@ // The basic motion is on a horizontal plane, as if // driving a vehicle. //////////////////////////////////////////////////////////////////// -class EXPCL_PANDA DriveInterface : public DataNode { +class EXPCL_PANDA DriveInterface : public MouseInterfaceNode { PUBLISHED: DriveInterface(const string &name = ""); ~DriveInterface(); @@ -136,9 +136,6 @@ private: // This is only used to return a temporary value in get_mat(). LMatrix4f _mat; - // Remember which mouse buttons are being held down. - ModifierButtons _mods; - // Remember which arrow keys are being held down and which aren't, // and at what point they last changed state. class KeyHeld { @@ -187,9 +184,9 @@ public: return _type_handle; } static void init_type() { - DataNode::init_type(); + MouseInterfaceNode::init_type(); register_type(_type_handle, "DriveInterface", - DataNode::get_class_type()); + MouseInterfaceNode::get_class_type()); } virtual TypeHandle get_type() const { return get_class_type(); diff --git a/panda/src/tform/mouseInterfaceNode.I b/panda/src/tform/mouseInterfaceNode.I new file mode 100644 index 0000000000..cfff5aad3d --- /dev/null +++ b/panda/src/tform/mouseInterfaceNode.I @@ -0,0 +1,30 @@ +// Filename: mouseInterfaceNode.I +// Created by: drose (11Jun04) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////// +// Function: MouseInterfaceNode::is_down +// Access: Protected +// Description: Returns true if the indicated button (which must have +// been specified in a previous call to watch_button()) +// is known to be held down, false otherwise. +//////////////////////////////////////////////////////////////////// +INLINE bool MouseInterfaceNode:: +is_down(ButtonHandle button) const { + return _current_button_state.is_down(button); +} diff --git a/panda/src/tform/mouseInterfaceNode.cxx b/panda/src/tform/mouseInterfaceNode.cxx new file mode 100644 index 0000000000..2fd5ce0d1a --- /dev/null +++ b/panda/src/tform/mouseInterfaceNode.cxx @@ -0,0 +1,155 @@ +// Filename: mouseInterfaceNode.cxx +// Created by: drose (11Jun04) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + + +#include "trackball.h" +#include "buttonEvent.h" +#include "buttonEventList.h" +#include "dataNodeTransmit.h" +#include "mouseData.h" + +TypeHandle MouseInterfaceNode::_type_handle; + +//////////////////////////////////////////////////////////////////// +// Function: MouseInterfaceNode::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +MouseInterfaceNode:: +MouseInterfaceNode(const string &name) : + DataNode(name) +{ + _button_events_input = define_input("button_events", ButtonEventList::get_class_type()); +} + +//////////////////////////////////////////////////////////////////// +// Function: MouseInterfaceNode::Destructor +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +MouseInterfaceNode:: +~MouseInterfaceNode() { +} + +//////////////////////////////////////////////////////////////////// +// Function: MouseInterfaceNode::require_button +// Access: Published +// Description: Indicates that the indicated button must be in the +// required state (either up or down) in order for this +// particular MouseInterfaceNode to do anything. For +// instance, this may be called to make a Trackball +// object respect mouse input only when the control key +// is held down. +//////////////////////////////////////////////////////////////////// +void MouseInterfaceNode:: +require_button(const ButtonHandle &button, bool is_down) { + _required_buttons_mask.add_button(button); + _required_buttons_state.set_button_list(_required_buttons_mask); + _current_button_state.set_button_list(_required_buttons_mask); + + _required_buttons_mask.button_down(button); + if (is_down) { + _required_buttons_state.button_down(button); + } else { + _required_buttons_state.button_up(button); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: MouseInterfaceNode::clear_button +// Access: Published +// Description: Removes any requirement on the indicated button set +// by an earlier call to require_button(). +//////////////////////////////////////////////////////////////////// +void MouseInterfaceNode:: +clear_button(const ButtonHandle &button) { + _required_buttons_mask.button_up(button); + _required_buttons_state.button_up(button); + + // The _required_buttons_mask and state must always keep the buttons + // that are listed in _watched_buttons. + + if (!_watched_buttons.has_button(button)) { + _required_buttons_mask.remove_button(button); + _required_buttons_state.set_button_list(_required_buttons_mask); + _current_button_state.set_button_list(_required_buttons_mask); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: MouseInterfaceNode::clear_all_button +// Access: Published +// Description: Removes all requirements on buttons set by an earlier +// call to require_button(). +//////////////////////////////////////////////////////////////////// +void MouseInterfaceNode:: +clear_all_buttons() { + _required_buttons_mask.all_buttons_up(); + _required_buttons_state.all_buttons_up(); + + _required_buttons_mask.set_button_list(_watched_buttons); + _required_buttons_state.set_button_list(_watched_buttons); + _current_button_state.set_button_list(_watched_buttons); +} + +//////////////////////////////////////////////////////////////////// +// Function: MouseInterfaceNode::watch_button +// Access: Protected +// Description: Indicates that the derived class would like to know +// the state of the given button. +//////////////////////////////////////////////////////////////////// +void MouseInterfaceNode:: +watch_button(const ButtonHandle &button) { + _watched_buttons.add_button(button); + + // We also add the button to _required_buttons_mask and + // _required_buttons_state, but it's left 'up' in these two. + _required_buttons_mask.add_button(button); + _required_buttons_state.set_button_list(_required_buttons_mask); + _current_button_state.set_button_list(_required_buttons_mask); +} + +//////////////////////////////////////////////////////////////////// +// Function: MouseInterfaceNode::check_button_events +// Access: Protected +// Description: Gets the button events from the data graph and +// updates the ModifierButtons objects appropriately. +// +// Sets required_buttons_match to true if the required +// combination of buttons are being held down, or false +// otherwise. +// +// The return value is the list of button events +// processed this frame, or NULL if there are no button +// events. +//////////////////////////////////////////////////////////////////// +const ButtonEventList *MouseInterfaceNode:: +check_button_events(const DataNodeTransmit &input, + bool &required_buttons_match) { + const ButtonEventList *button_events = NULL; + + if (input.has_data(_button_events_input)) { + DCAST_INTO_R(button_events, input.get_data(_button_events_input).get_ptr(), false); + button_events->update_mods(_current_button_state); + } + + required_buttons_match = + (_current_button_state & _required_buttons_mask) == _required_buttons_state; + + return button_events; +} diff --git a/panda/src/tform/mouseInterfaceNode.h b/panda/src/tform/mouseInterfaceNode.h new file mode 100644 index 0000000000..c5704ae325 --- /dev/null +++ b/panda/src/tform/mouseInterfaceNode.h @@ -0,0 +1,84 @@ +// Filename: mouseInterfaceNode.h +// Created by: drose (11Jun04) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + +#ifndef MOUSEINTERFACENODE_H +#define MOUSEINTERFACENODE_H + +#include "pandabase.h" + +#include "dataNode.h" +#include "modifierButtons.h" + +class ButtonEventList; + +//////////////////////////////////////////////////////////////////// +// Class : MouseInterfaceNode +// Description : This is the base class for some classes that monitor +// the mouse and keyboard input and perform some action +// due to their state. +// +// It collects together some common interface; in +// particular, the require_button() and related methods. +//////////////////////////////////////////////////////////////////// +class EXPCL_PANDA MouseInterfaceNode : public DataNode { +public: + MouseInterfaceNode(const string &name); + virtual ~MouseInterfaceNode(); + +PUBLISHED: + void require_button(const ButtonHandle &button, bool is_down); + void clear_button(const ButtonHandle &button); + void clear_all_buttons(); + +protected: + void watch_button(const ButtonHandle &button); + const ButtonEventList *check_button_events(const DataNodeTransmit &input, + bool &required_buttons_match); + + INLINE bool is_down(ButtonHandle button) const; + +private: + ModifierButtons _current_button_state; + ModifierButtons _watched_buttons; + ModifierButtons _required_buttons_mask; + ModifierButtons _required_buttons_state; + +private: + int _button_events_input; + +public: + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + DataNode::init_type(); + register_type(_type_handle, "MouseInterfaceNode", + DataNode::get_class_type()); + } + virtual TypeHandle get_type() const { + return get_class_type(); + } + virtual TypeHandle force_init_type() {init_type(); return get_class_type();} + +private: + static TypeHandle _type_handle; +}; + +#include "mouseInterfaceNode.I" + +#endif diff --git a/panda/src/tform/tform_composite1.cxx b/panda/src/tform/tform_composite1.cxx index ff5fd652ab..ecd32e43b2 100644 --- a/panda/src/tform/tform_composite1.cxx +++ b/panda/src/tform/tform_composite1.cxx @@ -1,4 +1,6 @@ #include "buttonThrower.cxx" #include "config_tform.cxx" #include "driveInterface.cxx" +#include "mouseInterfaceNode.cxx" + diff --git a/panda/src/tform/trackball.cxx b/panda/src/tform/trackball.cxx index 445513c18a..843ef16d06 100644 --- a/panda/src/tform/trackball.cxx +++ b/panda/src/tform/trackball.cxx @@ -38,10 +38,9 @@ TypeHandle Trackball::_type_handle; //////////////////////////////////////////////////////////////////// Trackball:: Trackball(const string &name) : - DataNode(name) + MouseInterfaceNode(name) { _pixel_xy_input = define_input("pixel_xy", EventStoreVec2::get_class_type()); - _button_events_input = define_input("button_events", ButtonEventList::get_class_type()); _transform_output = define_output("transform", TransformState::get_class_type()); @@ -59,9 +58,10 @@ Trackball(const string &name) : _invert = true; _cs = default_coordinate_system; - _mods.add_button(MouseButton::one()); - _mods.add_button(MouseButton::two()); - _mods.add_button(MouseButton::three()); + // We want to track the state of these buttons. + watch_button(MouseButton::one()); + watch_button(MouseButton::two()); + watch_button(MouseButton::three()); } //////////////////////////////////////////////////////////////////// @@ -535,36 +535,33 @@ recompute() { void Trackball:: do_transmit_data(const DataNodeTransmit &input, DataNodeTransmit &output) { // First, update our modifier buttons. - if (input.has_data(_button_events_input)) { - const ButtonEventList *button_events; - DCAST_INTO_V(button_events, input.get_data(_button_events_input).get_ptr()); - button_events->update_mods(_mods); - } + bool required_buttons_match; + check_button_events(input, required_buttons_match); // Now, check for mouse motion. - if (input.has_data(_pixel_xy_input)) { + if (required_buttons_match && input.has_data(_pixel_xy_input)) { const EventStoreVec2 *pixel_xy; DCAST_INTO_V(pixel_xy, input.get_data(_pixel_xy_input).get_ptr()); const LVecBase2f &p = pixel_xy->get_value(); float this_x = p[0]; float this_y = p[1]; int this_button = 0; - - if (_mods.is_down(MouseButton::one())) { + + if (is_down(MouseButton::one())) { this_button |= B1_MASK; } - if (_mods.is_down(MouseButton::two())) { + if (is_down(MouseButton::two())) { this_button |= B2_MASK; } - if (_mods.is_down(MouseButton::three())) { + if (is_down(MouseButton::three())) { this_button |= B3_MASK; } - + float x = this_x - _lastx; float y = this_y - _lasty; - + apply(x, y, this_button); - + _lastx = this_x; _lasty = this_y; } diff --git a/panda/src/tform/trackball.h b/panda/src/tform/trackball.h index 63aaac4801..0322ef7b1c 100644 --- a/panda/src/tform/trackball.h +++ b/panda/src/tform/trackball.h @@ -21,7 +21,7 @@ #include "pandabase.h" -#include "dataNode.h" +#include "mouseInterfaceNode.h" #include "nodePath.h" #include "modifierButtons.h" #include "luse.h" @@ -41,7 +41,7 @@ // it to actually transform objects (or cameras) in the // world. //////////////////////////////////////////////////////////////////// -class EXPCL_PANDA Trackball : public DataNode { +class EXPCL_PANDA Trackball : public MouseInterfaceNode { PUBLISHED: Trackball(const string &name); ~Trackball(); @@ -88,7 +88,7 @@ PUBLISHED: void set_invert(bool flag); bool get_invert() const; - void set_rel_to(const NodePath &_rel_to); + void set_rel_to(const NodePath &rel_to); const NodePath &get_rel_to() const; void set_coordinate_system(CoordinateSystem cs); @@ -118,10 +118,6 @@ private: NodePath _rel_to; CoordinateSystem _cs; - // Remember which mouse buttons are being held down. - ModifierButtons _mods; - - protected: // Inherited from DataNode virtual void do_transmit_data(const DataNodeTransmit &input, @@ -130,7 +126,6 @@ protected: private: // inputs int _pixel_xy_input; - int _button_events_input; // outputs int _transform_output; @@ -142,9 +137,9 @@ public: return _type_handle; } static void init_type() { - DataNode::init_type(); + MouseInterfaceNode::init_type(); register_type(_type_handle, "Trackball", - DataNode::get_class_type()); + MouseInterfaceNode::get_class_type()); } virtual TypeHandle get_type() const { return get_class_type();