mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-18 12:43:44 -04:00
539 lines
16 KiB
C++
539 lines
16 KiB
C++
// Filename: inputDevice.cxx
|
|
// Created by: drose (24May00)
|
|
//
|
|
////////////////////////////////////////////////////////////////////
|
|
//
|
|
// 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."
|
|
//
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
#include "inputDevice.h"
|
|
|
|
TypeHandle InputDevice::_type_handle;
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: InputDevice::Constructor
|
|
// Access: Private
|
|
// Description: Defines a new InputDevice for the window. Most
|
|
// windows will have exactly one InputDevice: a
|
|
// keyboard/mouse pair. Some may also add joystick
|
|
// data, or additional mice or something.
|
|
//
|
|
// This private constructor is only used internally by
|
|
// the named constructors, below.
|
|
////////////////////////////////////////////////////////////////////
|
|
InputDevice::
|
|
InputDevice(const string &name, DeviceClass dev_class, int flags) :
|
|
_name(name),
|
|
_flags(flags),
|
|
_device_class(dev_class),
|
|
_vendor_id(0),
|
|
_product_id(0),
|
|
_is_connected(true),
|
|
_event_sequence(0),
|
|
_enable_pointer_events(false),
|
|
_battery_level(-1),
|
|
_max_battery_level(-1)
|
|
{
|
|
_button_events = new ButtonEventList;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: InputDevice::Copy Constructor
|
|
// Access: Public
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
InputDevice::
|
|
InputDevice(const InputDevice ©) {
|
|
nassertv(false);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: InputDevice::Copy Assignment Operator
|
|
// Access: Public
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
void InputDevice::
|
|
operator = (const InputDevice ©) {
|
|
nassertv(false);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: InputDevice::Destructor
|
|
// Access: Public
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
InputDevice::
|
|
~InputDevice() {
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: InputDevice::poll
|
|
// Access: Public, Virtual
|
|
// Description: Polls the input device for new activity, to ensure
|
|
// it contains the latest events. This will only have
|
|
// any effect for some types of input devices; others
|
|
// may be updated automatically, and this method will
|
|
// be a no-op.
|
|
////////////////////////////////////////////////////////////////////
|
|
void InputDevice::
|
|
poll() {
|
|
LightMutexHolder holder(_lock);
|
|
do_poll();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: InputDevice::has_button_event
|
|
// Access: Public
|
|
// Description: Returns true if this device has a pending button
|
|
// event (a mouse button or keyboard button down/up),
|
|
// false otherwise. If this returns true, the
|
|
// particular event may be extracted via
|
|
// get_button_event().
|
|
////////////////////////////////////////////////////////////////////
|
|
bool InputDevice::
|
|
has_button_event() const {
|
|
LightMutexHolder holder(_lock);
|
|
return !_button_events.is_null() && _button_events->get_num_events() > 0;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: InputDevice::get_button_events
|
|
// Access: Public
|
|
// Description: Returns the list of recently-generated ButtonEvents.
|
|
// The list is also cleared.
|
|
////////////////////////////////////////////////////////////////////
|
|
PT(ButtonEventList) InputDevice::
|
|
get_button_events() {
|
|
LightMutexHolder holder(_lock);
|
|
PT(ButtonEventList) result = new ButtonEventList;
|
|
swap(_button_events, result);
|
|
return result;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: InputDevice::has_pointer_event
|
|
// Access: Public
|
|
// Description: Returns true if this device has a pending pointer
|
|
// event (a mouse movement), or false otherwise. If
|
|
// this returns true, the particular event may be
|
|
// extracted via get_pointer_event().
|
|
////////////////////////////////////////////////////////////////////
|
|
bool InputDevice::
|
|
has_pointer_event() const {
|
|
LightMutexHolder holder(_lock);
|
|
return (_pointer_events != 0);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: InputDevice::get_pointer_events
|
|
// Access: Public
|
|
// Description: Returns a PointerEventList containing all the recent
|
|
// pointer events. Clears the list.
|
|
////////////////////////////////////////////////////////////////////
|
|
PT(PointerEventList) InputDevice::
|
|
get_pointer_events() {
|
|
LightMutexHolder holder(_lock);
|
|
PT(PointerEventList) result = _pointer_events;
|
|
_pointer_events.clear();
|
|
return result;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: InputDevice::set_pointer
|
|
// Access: Protected
|
|
// Description: Records that a mouse movement has taken place.
|
|
////////////////////////////////////////////////////////////////////
|
|
void InputDevice::
|
|
set_pointer(bool inwin, double x, double y, double time) {
|
|
nassertv(_lock.debug_is_locked());
|
|
_pointer_data._in_window = inwin;
|
|
_pointer_data._xpos = x;
|
|
_pointer_data._ypos = y;
|
|
|
|
if (_enable_pointer_events) {
|
|
int seq = _event_sequence++;
|
|
if (_pointer_events.is_null()) {
|
|
_pointer_events = new PointerEventList();
|
|
}
|
|
_pointer_events->add_event(_pointer_data._in_window,
|
|
_pointer_data._xpos,
|
|
_pointer_data._ypos,
|
|
seq, time);
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: InputDevice::set_pointer_out_of_window
|
|
// Access: Protected
|
|
// Description: Records that the mouse pointer has left the window.
|
|
////////////////////////////////////////////////////////////////////
|
|
void InputDevice::
|
|
set_pointer_out_of_window(double time) {
|
|
nassertv(_lock.debug_is_locked());
|
|
_pointer_data._in_window = false;
|
|
|
|
if (_enable_pointer_events) {
|
|
int seq = _event_sequence++;
|
|
if (_pointer_events.is_null()) {
|
|
_pointer_events = new PointerEventList();
|
|
}
|
|
_pointer_events->add_event(_pointer_data._in_window,
|
|
_pointer_data._xpos,
|
|
_pointer_data._ypos,
|
|
seq, time);
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: InputDevice::set_button_state
|
|
// Access: Protected
|
|
// Description: Sets the state of the indicated button index, where
|
|
// true indicates down, and false indicates up. This
|
|
// may generate a ButtonEvent if the button has an
|
|
// associated ButtonHandle. The caller should ensure
|
|
// that acquire() is in effect while this call is made.
|
|
////////////////////////////////////////////////////////////////////
|
|
void InputDevice::
|
|
set_button_state(int index, bool down) {
|
|
nassertv(_lock.debug_is_locked());
|
|
nassertv(index >= 0);
|
|
if (index >= (int)_buttons.size()) {
|
|
_buttons.resize(index + 1, ButtonState());
|
|
}
|
|
|
|
_buttons[index]._state = down ? S_down : S_up;
|
|
|
|
ButtonHandle handle = _buttons[index]._handle;
|
|
if (handle != ButtonHandle::none()) {
|
|
_button_events->add_event(ButtonEvent(handle, down ? ButtonEvent::T_down : ButtonEvent::T_up));
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: InputDevice::set_control_state
|
|
// Access: Protected
|
|
// Description: Sets the state of the indicated analog index. The
|
|
// caller should ensure that acquire() is in effect while
|
|
// this call is made. This should be a number in the
|
|
// range -1.0 to 1.0, representing the current position
|
|
// of the control within its total range of movement.
|
|
////////////////////////////////////////////////////////////////////
|
|
void InputDevice::
|
|
set_control_state(int index, double state) {
|
|
nassertv(_lock.debug_is_locked());
|
|
nassertv(index >= 0);
|
|
if (index >= (int)_controls.size()) {
|
|
_controls.resize(index + 1, AnalogState());
|
|
}
|
|
|
|
if (device_cat.is_spam()) {
|
|
device_cat.spam()
|
|
<< "Changed control " << index;
|
|
|
|
if (_controls[index]._axis != C_none) {
|
|
device_cat.spam(false) << " (" << _controls[index]._axis << ")";
|
|
}
|
|
|
|
device_cat.spam(false) << " to " << state << "\n";
|
|
}
|
|
|
|
_controls[index]._state = state;
|
|
_controls[index]._known = true;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: InputDevice::set_tracker
|
|
// Access: Protected
|
|
// Description: Records that a tracker movement has taken place.
|
|
////////////////////////////////////////////////////////////////////
|
|
void InputDevice::
|
|
set_tracker(const LPoint3 &pos, const LOrientation &orient, double time) {
|
|
nassertv(_lock.debug_is_locked());
|
|
|
|
_tracker_data.set_pos(pos);
|
|
_tracker_data.set_orient(orient);
|
|
_tracker_data.set_time(time);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: InputDevice::output
|
|
// Access: Public
|
|
// Description: Writes a one-line string describing the device.
|
|
////////////////////////////////////////////////////////////////////
|
|
void InputDevice::
|
|
output(ostream &out) const {
|
|
LightMutexHolder holder(_lock);
|
|
|
|
out << _name << " (";
|
|
|
|
if (!_is_connected) {
|
|
out << "dis";
|
|
}
|
|
|
|
out << "connected)";
|
|
|
|
if (_device_class != DC_unknown) {
|
|
out << ", " << _device_class;
|
|
}
|
|
|
|
if (_buttons.size() > 0) {
|
|
out << ", " << _buttons.size() << " button";
|
|
if (_buttons.size() != 1) {
|
|
out.put('s');
|
|
}
|
|
}
|
|
|
|
if (_controls.size() > 0) {
|
|
out << ", " << _controls.size() << " control";
|
|
if (_controls.size() != 1) {
|
|
out.put('s');
|
|
}
|
|
}
|
|
|
|
if (_flags & IDF_has_pointer) {
|
|
out << ", pointer";
|
|
}
|
|
if (_flags & IDF_has_keyboard) {
|
|
out << ", keyboard";
|
|
}
|
|
if (_flags & IDF_has_tracker) {
|
|
out << ", tracker";
|
|
}
|
|
if (_flags & IDF_has_vibration) {
|
|
out << ", vibration";
|
|
}
|
|
if (_flags & IDF_has_battery) {
|
|
out << ", battery";
|
|
|
|
if (_battery_level > 0 && _max_battery_level > 0) {
|
|
out << " [";
|
|
short i = 0;
|
|
for (; i < _battery_level; ++i) {
|
|
out << '=';
|
|
}
|
|
for (; i < _max_battery_level; ++i) {
|
|
out << ' ';
|
|
}
|
|
out << ']';
|
|
}
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: InputDevice::output_buttons
|
|
// Access: Public
|
|
// Description: Writes a one-line string of all of the current button
|
|
// states.
|
|
////////////////////////////////////////////////////////////////////
|
|
void InputDevice::
|
|
output_buttons(ostream &out) const {
|
|
LightMutexHolder holder(_lock);
|
|
|
|
bool any_buttons = false;
|
|
Buttons::const_iterator bi;
|
|
for (bi = _buttons.begin(); bi != _buttons.end(); ++bi) {
|
|
const ButtonState &state = (*bi);
|
|
if (state._state != S_unknown) {
|
|
if (any_buttons) {
|
|
out << ", ";
|
|
}
|
|
any_buttons = true;
|
|
out << (int)(bi - _buttons.begin()) << "=";
|
|
if (state._state == S_up) {
|
|
out << "up";
|
|
} else {
|
|
out << "down";
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!any_buttons) {
|
|
out << "no known buttons";
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: InputDevice::write_buttons
|
|
// Access: Public
|
|
// Description: Writes a multi-line description of the current button
|
|
// states.
|
|
////////////////////////////////////////////////////////////////////
|
|
void InputDevice::
|
|
write_buttons(ostream &out, int indent_level) const {
|
|
bool any_buttons = false;
|
|
Buttons::const_iterator bi;
|
|
for (bi = _buttons.begin(); bi != _buttons.end(); ++bi) {
|
|
const ButtonState &state = (*bi);
|
|
if (state._state != S_unknown) {
|
|
any_buttons = true;
|
|
|
|
indent(out, indent_level)
|
|
<< (int)(bi - _buttons.begin()) << ". ";
|
|
|
|
if (state._handle != ButtonHandle::none()) {
|
|
out << "(" << state._handle << ") ";
|
|
}
|
|
|
|
if (state._state == S_up) {
|
|
out << "up";
|
|
} else {
|
|
out << "down";
|
|
}
|
|
out << "\n";
|
|
}
|
|
}
|
|
|
|
if (!any_buttons) {
|
|
indent(out, indent_level)
|
|
<< "(no known buttons)\n";
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: InputDevice::write_controls
|
|
// Access: Public
|
|
// Description: Writes a multi-line description of the current analog
|
|
// control states.
|
|
////////////////////////////////////////////////////////////////////
|
|
void InputDevice::
|
|
write_controls(ostream &out, int indent_level) const {
|
|
LightMutexHolder holder(_lock);
|
|
|
|
bool any_controls = false;
|
|
Controls::const_iterator ai;
|
|
for (ai = _controls.begin(); ai != _controls.end(); ++ai) {
|
|
const AnalogState &state = (*ai);
|
|
if (state._known) {
|
|
any_controls = true;
|
|
|
|
indent(out, indent_level)
|
|
<< (int)(ai - _controls.begin()) << ". " << state._state << "\n";
|
|
}
|
|
}
|
|
|
|
if (!any_controls) {
|
|
indent(out, indent_level)
|
|
<< "(no known analog controls)\n";
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: InputDevice::do_set_vibration
|
|
// Access: Private, Virtual
|
|
// Description: Sets the vibration strength. The first argument
|
|
// controls a low-frequency motor, if present, and
|
|
// the latter controls a high-frequency motor. The
|
|
// values are within the 0-1 range.
|
|
////////////////////////////////////////////////////////////////////
|
|
void InputDevice::
|
|
do_set_vibration(double strong, double weak) {
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: InputDevice::do_poll
|
|
// Access: Protected, Virtual
|
|
// Description: Polls the input device for new activity, to ensure
|
|
// it contains the latest events. This will only have
|
|
// any effect for some types of input devices; others
|
|
// may be updated automatically, and this method will
|
|
// be a no-op.
|
|
////////////////////////////////////////////////////////////////////
|
|
void InputDevice::
|
|
do_poll() {
|
|
}
|
|
|
|
ostream &
|
|
operator << (ostream &out, InputDevice::DeviceClass dc) {
|
|
switch (dc) {
|
|
case InputDevice::DC_unknown:
|
|
out << "unknown";
|
|
break;
|
|
|
|
case InputDevice::DC_virtual:
|
|
out << "virtual";
|
|
break;
|
|
|
|
case InputDevice::DC_keyboard:
|
|
out << "keyboard";
|
|
break;
|
|
|
|
case InputDevice::DC_mouse:
|
|
out << "mouse";
|
|
break;
|
|
|
|
case InputDevice::DC_touch:
|
|
out << "touch";
|
|
break;
|
|
|
|
case InputDevice::DC_gamepad:
|
|
out << "gamepad";
|
|
break;
|
|
|
|
case InputDevice::DC_flight_stick:
|
|
out << "flight_stick";
|
|
break;
|
|
|
|
case InputDevice::DC_steering_wheel:
|
|
out << "steering_wheel";
|
|
break;
|
|
}
|
|
return out;
|
|
}
|
|
|
|
ostream &
|
|
operator << (ostream &out, InputDevice::ControlAxis axis) {
|
|
switch (axis) {
|
|
case InputDevice::C_none:
|
|
out << "none";
|
|
break;
|
|
|
|
case InputDevice::C_left_x:
|
|
out << "left_x";
|
|
break;
|
|
|
|
case InputDevice::C_left_y:
|
|
out << "left_y";
|
|
break;
|
|
|
|
case InputDevice::C_left_trigger:
|
|
out << "left_trigger";
|
|
break;
|
|
|
|
case InputDevice::C_right_x:
|
|
out << "right_x";
|
|
break;
|
|
|
|
case InputDevice::C_right_y:
|
|
out << "right_y";
|
|
break;
|
|
|
|
case InputDevice::C_right_trigger:
|
|
out << "right_trigger";
|
|
break;
|
|
|
|
case InputDevice::C_x:
|
|
out << "x";
|
|
break;
|
|
|
|
case InputDevice::C_y:
|
|
out << "y";
|
|
break;
|
|
|
|
case InputDevice::C_trigger:
|
|
out << "trigger";
|
|
break;
|
|
|
|
case InputDevice::C_throttle:
|
|
out << "throttle";
|
|
break;
|
|
}
|
|
|
|
return out;
|
|
}
|