diff --git a/direct/src/showbase/ShowBase.py b/direct/src/showbase/ShowBase.py index c7edea715e..4d92dbc002 100644 --- a/direct/src/showbase/ShowBase.py +++ b/direct/src/showbase/ShowBase.py @@ -1686,6 +1686,7 @@ class ShowBase(DirectObject.DirectObject): for i in range(win.getNumInputDevices()): name = win.getInputDeviceName(i) mk = self.dataRoot.attachNewNode(MouseAndKeyboard(win, i, name)) + pt = mk.attachNewNode(PointerThrower("pointers%s" % (i))) mw = mk.attachNewNode(MouseWatcher("watcher%s" % (i))) if win.getSideBySideStereo(): diff --git a/panda/src/tform/CMakeLists.txt b/panda/src/tform/CMakeLists.txt index c8da2e176c..9ef9adf9c6 100644 --- a/panda/src/tform/CMakeLists.txt +++ b/panda/src/tform/CMakeLists.txt @@ -9,6 +9,7 @@ set(P3TFORM_HEADERS mouseWatcherGroup.h mouseWatcherParameter.I mouseWatcherParameter.h mouseWatcherRegion.I mouseWatcherRegion.h + pointerThrower.I pointerThrower.h trackball.h transform2sg.h ) @@ -24,6 +25,7 @@ set(P3TFORM_SOURCES mouseWatcherGroup.cxx mouseWatcherParameter.cxx mouseWatcherRegion.cxx + pointerThrower.cxx trackball.cxx transform2sg.cxx ) diff --git a/panda/src/tform/buttonThrower.I b/panda/src/tform/buttonThrower.I index 2e0fc4c57f..83a28220a4 100644 --- a/panda/src/tform/buttonThrower.I +++ b/panda/src/tform/buttonThrower.I @@ -145,6 +145,8 @@ get_candidate_event() const { /** * Specifies the event that is generated (if any) each time the mouse is moved * within the window. + * + * @deprecated Create a PointerThrower object instead. */ INLINE void ButtonThrower:: set_move_event(const std::string &move_event) { @@ -154,6 +156,8 @@ set_move_event(const std::string &move_event) { /** * Returns the move_event that has been set on this ButtonThrower. See * set_move_event(). + * + * @deprecated Create a PointerThrower object instead. */ INLINE const std::string &ButtonThrower:: get_move_event() const { diff --git a/panda/src/tform/config_tform.cxx b/panda/src/tform/config_tform.cxx index 6620e5724c..e6dc47fcbd 100644 --- a/panda/src/tform/config_tform.cxx +++ b/panda/src/tform/config_tform.cxx @@ -20,6 +20,7 @@ #include "mouseWatcherBase.h" #include "mouseWatcherGroup.h" #include "mouseWatcherRegion.h" +#include "pointerThrower.h" #include "trackball.h" #include "transform2sg.h" @@ -74,6 +75,7 @@ ConfigureFn(config_tform) { MouseWatcherBase::init_type(); MouseWatcherGroup::init_type(); MouseWatcherRegion::init_type(); + PointerThrower::init_type(); Trackball::init_type(); Transform2SG::init_type(); } diff --git a/panda/src/tform/p3tform_composite2.cxx b/panda/src/tform/p3tform_composite2.cxx index 862c698071..a8b32a2f5a 100644 --- a/panda/src/tform/p3tform_composite2.cxx +++ b/panda/src/tform/p3tform_composite2.cxx @@ -3,6 +3,7 @@ #include "mouseWatcherGroup.cxx" #include "mouseWatcherParameter.cxx" #include "mouseWatcherRegion.cxx" +#include "pointerThrower.cxx" #include "trackball.cxx" #include "transform2sg.cxx" diff --git a/panda/src/tform/pointerThrower.I b/panda/src/tform/pointerThrower.I new file mode 100644 index 0000000000..5e0838c779 --- /dev/null +++ b/panda/src/tform/pointerThrower.I @@ -0,0 +1,79 @@ +/** + * PANDA 3D SOFTWARE + * Copyright (c) Carnegie Mellon University. All rights reserved. + * + * All use of this software is subject to the terms of the revised BSD + * license. You should have received a copy of this license along + * with this source code in a file named "LICENSE." + * + * @file pointerThrower.I + * @author rdb + * @date 2021-12-22 + */ + +/** + * Specifies the event that is thrown when a pointer enters the active state. + */ +INLINE void PointerThrower:: +set_down_event(const std::string &down_event) { + _down_event = down_event; +} + +/** + * + */ +INLINE const std::string &PointerThrower:: +get_down_event() const { + return _down_event; +} + +/** + * Specifies the event that is thrown when a pointer leaves the active state. + */ +INLINE void PointerThrower:: +set_up_event(const std::string &up_event) { + _up_event = up_event; +} + +/** + * + */ +INLINE const std::string &PointerThrower:: +get_up_event() const { + return _up_event; +} + +/** + * Specifies the event that is thrown when a pointer leaves the active state. + */ +INLINE void PointerThrower:: +set_move_event(const std::string &move_event) { + _move_event = move_event; +} + +/** + * + */ +INLINE const std::string &PointerThrower:: +get_move_event() const { + return _move_event; +} + +/** + * Sets the prefix which is prepended to all specific event names (that is, + * event names generated from the button name itself, as opposed to the + * generic event names like set_down_event) thrown by this object. + */ +INLINE void PointerThrower:: +set_prefix(const std::string &prefix) { + _prefix = prefix; +} + +/** + * Returns the prefix that has been set on this PointerThrower. See + * set_prefix(). + */ +INLINE const std::string &PointerThrower:: +get_prefix() const { + return _prefix; +} diff --git a/panda/src/tform/pointerThrower.cxx b/panda/src/tform/pointerThrower.cxx new file mode 100644 index 0000000000..079afe9dbe --- /dev/null +++ b/panda/src/tform/pointerThrower.cxx @@ -0,0 +1,143 @@ +/** + * PANDA 3D SOFTWARE + * Copyright (c) Carnegie Mellon University. All rights reserved. + * + * All use of this software is subject to the terms of the revised BSD + * license. You should have received a copy of this license along + * with this source code in a file named "LICENSE." + * + * @file pointerThrower.cxx + * @author rdb + * @date 2021-12-22 + */ + +#include "pointerThrower.h" + +#include "pointerEvent.h" +#include "pointerEventList.h" +#include "dataNodeTransmit.h" +#include "throw_event.h" +#include "event.h" +#include "indent.h" +#include "dcast.h" + +using std::string; + +TypeHandle PointerThrower::_type_handle; + +/** + * + */ +PointerThrower:: +PointerThrower(const string &name, const string &prefix) : + DataNode(name), + _down_event(prefix + "pointer-down"), + _up_event(prefix + "pointer-up"), + _move_event(prefix + "pointer-move") +{ + _pointer_events_input = define_input("pointer_events", PointerEventList::get_class_type()); +} + +/** + * + */ +PointerThrower:: +~PointerThrower() { +} + +/** + * Adds the indicated parameter to the list of parameters that will be passed + * with each event generated by this PointerThrower. + */ +void PointerThrower:: +add_parameter(const EventParameter &obj) { + _parameters.push_back(obj); +} + +/** + * Returns the number of parameters that have been added to the list of + * parameters to be passed with each event generated by this PointerThrower. + */ +int PointerThrower:: +get_num_parameters() const { + return _parameters.size(); +} + +/** + * Returns the nth parameter that has been added to the list of parameters + * passed with each event generated by this PointerThrower. + */ +EventParameter PointerThrower:: +get_parameter(size_t n) const { + nassertr(n < _parameters.size(), EventParameter(0)); + return _parameters[n]; +} + +/** + * Throw all events for button events found in the data element. + */ +void PointerThrower:: +write(std::ostream &out, int indent_level) const { + DataNode::write(out, indent_level); +} + +/** + * Generates a pointer event, if one is configured. + */ +void PointerThrower:: +do_general_event(const PointerEvent &pointer_event) { + std::string event_name; + + if (pointer_event._pressure > 0.0) { + if (_active_ids.insert(pointer_event._id).second) { + event_name = _down_event; + } else { + event_name = _move_event; + } + } + else if (_active_ids.erase(pointer_event._id)) { + event_name = _up_event; + } + else { + // Don't generate events for inactive pointers. + return; + } + + if (event_name.empty()) { + return; + } + + PT(Event) event = new Event(event_name); + + //event->add_parameter(new ParamPointerEvent(pointer_event)); + + for (const EventParameter ¶m : _parameters) { + event->add_parameter(param); + } + + throw_event(event); +} + +/** + * The virtual implementation of transmit_data(). This function receives an + * array of input parameters and should generate an array of output + * parameters. The input parameters may be accessed with the index numbers + * returned by the define_input() calls that were made earlier (presumably in + * the constructor); likewise, the output parameters should be set with the + * index numbers returned by the define_output() calls. + */ +void PointerThrower:: +do_transmit_data(DataGraphTraverser *, const DataNodeTransmit &input, + DataNodeTransmit &output) { + + if (input.has_data(_pointer_events_input)) { + const PointerEventList *pointer_events; + DCAST_INTO_V(pointer_events, input.get_data(_pointer_events_input).get_ptr()); + + int num_events = pointer_events->get_num_events(); + for (int i = 0; i < num_events; i++) { + const PointerEvent &pe = pointer_events->get_event(i); + do_general_event(pe); + } + } +} diff --git a/panda/src/tform/pointerThrower.h b/panda/src/tform/pointerThrower.h new file mode 100644 index 0000000000..498c799c58 --- /dev/null +++ b/panda/src/tform/pointerThrower.h @@ -0,0 +1,109 @@ +/** + * PANDA 3D SOFTWARE + * Copyright (c) Carnegie Mellon University. All rights reserved. + * + * All use of this software is subject to the terms of the revised BSD + * license. You should have received a copy of this license along + * with this source code in a file named "LICENSE." + * + * @file pointerThrower.h + * @author rdb + * @date 2021-12-22 + */ + +#ifndef POINTERTHROWER_H +#define POINTERTHROWER_H + +#include "pandabase.h" + +#include "dataNode.h" +#include "modifierButtons.h" +#include "buttonEventList.h" +#include "pvector.h" +#include "pmap.h" +#include "eventParameter.h" + +/** + * Throws pointer events. + * + * This is a DataNode which is intended to be parented to the data graph below + * a device which is generating a sequence of pointer events, like a + * MouseAndKeyboard device. + */ +class EXPCL_PANDA_TFORM PointerThrower : public DataNode { +PUBLISHED: + explicit PointerThrower(const std::string &name, + const std::string &prefix = std::string()); + ~PointerThrower(); + +public: + INLINE void set_down_event(const std::string &pointer_down_event); + INLINE const std::string &get_down_event() const; + INLINE void set_up_event(const std::string &pointer_up_event); + INLINE const std::string &get_up_event() const; + INLINE void set_move_event(const std::string &pointer_move_event); + INLINE const std::string &get_move_event() const; + + INLINE void set_prefix(const std::string &prefix); + INLINE const std::string &get_prefix() const; + + void add_parameter(const EventParameter &obj); + int get_num_parameters() const; + EventParameter get_parameter(size_t n) const; + +PUBLISHED: + MAKE_PROPERTY(down_event, get_down_event, set_down_event); + MAKE_PROPERTY(up_event, get_up_event, set_up_event); + MAKE_PROPERTY(move_event, get_move_event, set_move_event); + + MAKE_PROPERTY(prefix, get_prefix, set_prefix); + MAKE_SEQ_PROPERTY(parameters, get_num_parameters, get_parameter); + +public: + virtual void write(std::ostream &out, int indent_level = 0) const; + +private: + void do_general_event(const PointerEvent &pointer_event); + +private: + std::string _down_event; + std::string _up_event; + std::string _move_event; + std::string _prefix; + + typedef pvector ParameterList; + ParameterList _parameters; + + pset _active_ids; + +protected: + // Inherited from DataNode + virtual void do_transmit_data(DataGraphTraverser *trav, + const DataNodeTransmit &input, + DataNodeTransmit &output); + +private: + // inputs + int _pointer_events_input; + +public: + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + DataNode::init_type(); + register_type(_type_handle, "PointerThrower", + 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 "pointerThrower.I" + +#endif