*** empty log message ***
This commit is contained in:
parent
6fdaa2a31b
commit
867fa370f4
|
|
@ -7,16 +7,30 @@
|
|||
dgraph display gobj sgraph graph gsgbase ipc mathutil linmath putil
|
||||
|
||||
#define SOURCES \
|
||||
adinputNode.cxx adinputNode.h analogData.I analogData.cxx \
|
||||
analogData.h buttonData.I buttonData.cxx buttonData.h \
|
||||
clientBase.cxx clientBase.h config_device.cxx config_device.h \
|
||||
analogData.I analogData.cxx analogData.h \
|
||||
analogNode.I analogNode.cxx analogNode.h \
|
||||
buttonNode.I buttonNode.h buttonNode.cxx \
|
||||
clientAnalogDevice.I clientAnalogDevice.cxx clientAnalogDevice.h \
|
||||
clientBase.I clientBase.cxx clientBase.h \
|
||||
clientButtonDevice.I clientButtonDevice.cxx clientButtonDevice.h \
|
||||
clientDevice.I clientDevice.cxx clientDevice.h \
|
||||
clientTrackerDevice.I clientTrackerDevice.cxx clientTrackerDevice.h \
|
||||
config_device.cxx config_device.h \
|
||||
dialData.I dialData.cxx dialData.h mouse.cxx mouse.h trackerData.I \
|
||||
trackerData.cxx trackerData.h trackerNode.cxx trackerNode.h
|
||||
trackerData.cxx trackerData.h \
|
||||
trackerNode.I trackerNode.cxx trackerNode.h
|
||||
|
||||
#define INSTALL_HEADERS \
|
||||
adinputNode.h analogData.I analogData.h buttonData.I buttonData.h \
|
||||
clientBase.h config_device.h dialData.I dialData.h mouse.h \
|
||||
trackerData.I trackerData.h trackerNode.h
|
||||
analogData.I analogData.h \
|
||||
analogNode.I analogNode.h \
|
||||
buttonNode.I buttonNode.h \
|
||||
clientAnalogDevice.I clientAnalogDevice.h \
|
||||
clientBase.I clientBase.h \
|
||||
clientButtonDevice.I clientButtonDevice.h \
|
||||
clientDevice.I clientDevice.h \
|
||||
clientTrackerDevice.I clientTrackerDevice.h \
|
||||
config_device.h dialData.I dialData.h mouse.h \
|
||||
trackerData.I trackerData.h trackerNode.I trackerNode.h
|
||||
|
||||
#define IGATESCAN all
|
||||
|
||||
|
|
|
|||
|
|
@ -1,124 +0,0 @@
|
|||
// Filename: adinputNode.cxx
|
||||
// Created by: jason (08Aug00)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "adinputNode.h"
|
||||
#include "config_device.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Static variables
|
||||
////////////////////////////////////////////////////////////////////
|
||||
TypeHandle ADInputNode::_type_handle;
|
||||
|
||||
TypeHandle ADInputNode::_dtime_type;
|
||||
TypeHandle ADInputNode::_dial_id_type;
|
||||
TypeHandle ADInputNode::_change_type;
|
||||
|
||||
TypeHandle ADInputNode::_btime_type;
|
||||
TypeHandle ADInputNode::_button_id_type;
|
||||
TypeHandle ADInputNode::_state_type;
|
||||
|
||||
TypeHandle ADInputNode::_atime_type;
|
||||
TypeHandle ADInputNode::_channels_type;
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ADInputNode::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
ADInputNode::
|
||||
ADInputNode(PT(ClientBase) client, const string &adinput) :
|
||||
DataNode(adinput), _client(client), _adinput(adinput)
|
||||
{
|
||||
_client->add_remote_analog(_adinput);
|
||||
_client->add_remote_button(_adinput);
|
||||
_client->add_remote_dial(_adinput);
|
||||
|
||||
_dtime = new DoubleDataAttribute();
|
||||
_dial_id = new IntDataAttribute();
|
||||
_change = new DoubleDataAttribute();
|
||||
|
||||
_btime = new DoubleDataAttribute();
|
||||
_button_id = new IntDataAttribute();
|
||||
_state = new IntDataAttribute();
|
||||
|
||||
_atime = new DoubleDataAttribute();
|
||||
_channels = new DoublePtrDataAttribute();
|
||||
|
||||
_adinput_attrib.set_attribute(_dtime_type, _dtime);
|
||||
_adinput_attrib.set_attribute(_dial_id_type, _dial_id);
|
||||
_adinput_attrib.set_attribute(_change_type, _change);
|
||||
|
||||
_adinput_attrib.set_attribute(_btime_type, _btime);
|
||||
_adinput_attrib.set_attribute(_button_id_type, _button_id);
|
||||
_adinput_attrib.set_attribute(_state_type, _state);
|
||||
|
||||
_adinput_attrib.set_attribute(_atime_type, _atime);
|
||||
_adinput_attrib.set_attribute(_channels_type, _channels);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ADInputNode::transmit_data
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void ADInputNode::
|
||||
transmit_data(NodeAttributes &data) {
|
||||
AnalogData new_analog = _client->get_analog_data(_adinput);
|
||||
ButtonData new_button = _client->get_button_data(_adinput);
|
||||
DialData new_dial = _client->get_dial_data(_adinput);
|
||||
|
||||
_dtime->set_value(new_dial.dtime);
|
||||
_dial_id->set_value(new_dial.dial_id);
|
||||
_change->set_value(new_dial.change);
|
||||
|
||||
_btime->set_value(new_button.btime);
|
||||
_button_id->set_value(new_button.button_id);
|
||||
_state->set_value(new_button.state);
|
||||
|
||||
_atime->set_value(new_analog.atime);
|
||||
_channels->set_value((double*)new_analog.channels);
|
||||
|
||||
data = _adinput_attrib;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ADInputNode::init_type
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void ADInputNode::
|
||||
init_type() {
|
||||
DataNode::init_type();
|
||||
register_type(_type_handle, "ADInputNode",
|
||||
DataNode::get_class_type());
|
||||
|
||||
DoubleDataTransition::init_type();
|
||||
IntDataTransition::init_type();
|
||||
DoublePtrDataTransition::init_type();
|
||||
|
||||
register_data_transition(_dtime_type, "Dial Time",
|
||||
DoubleDataTransition::get_class_type());
|
||||
register_data_transition(_dial_id_type, "Dial ID",
|
||||
IntDataTransition::get_class_type());
|
||||
register_data_transition(_change_type, "Dial Change",
|
||||
DoubleDataTransition::get_class_type());
|
||||
|
||||
register_data_transition(_btime_type, "Button Time",
|
||||
DoubleDataTransition::get_class_type());
|
||||
register_data_transition(_button_id_type, "Button ID",
|
||||
IntDataTransition::get_class_type());
|
||||
register_data_transition(_state_type, "Button State",
|
||||
IntDataTransition::get_class_type());
|
||||
|
||||
register_data_transition(_atime_type, "Analog Time",
|
||||
DoubleDataTransition::get_class_type());
|
||||
register_data_transition(_channels_type, "Analog Channels",
|
||||
DoublePtrDataTransition::get_class_type());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,78 +0,0 @@
|
|||
// Filename: cerealboxNode.h
|
||||
// Created by: jason (08Aug00)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _ADINPUT_NODE
|
||||
#define _ADINPUT_NODE
|
||||
|
||||
#include <pandabase.h>
|
||||
|
||||
#include <dataNode.h>
|
||||
#include <nodeAttributes.h>
|
||||
#include <doubleDataAttribute.h>
|
||||
#include <doubleDataTransition.h>
|
||||
#include <intDataAttribute.h>
|
||||
#include <intDataTransition.h>
|
||||
#include <doublePtrDataAttribute.h>
|
||||
#include <doublePtrDataTransition.h>
|
||||
|
||||
#include <pointerTo.h>
|
||||
#include "clientBase.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : ADInputNode
|
||||
// Description : Reads the analog, buttons and dials from a adinput
|
||||
// and sends it down the DataGraph
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDA ADInputNode : public DataNode {
|
||||
PUBLISHED:
|
||||
ADInputNode(PT(ClientBase) client, const string &adinput);
|
||||
|
||||
public:
|
||||
virtual void transmit_data(NodeAttributes &data);
|
||||
|
||||
public:
|
||||
NodeAttributes _adinput_attrib;
|
||||
|
||||
PT(DoubleDataAttribute) _btime;
|
||||
PT(IntDataAttribute) _button_id;
|
||||
PT(IntDataAttribute) _state;
|
||||
|
||||
PT(DoubleDataAttribute) _dtime;
|
||||
PT(IntDataAttribute) _dial_id;
|
||||
PT(DoubleDataAttribute) _change;
|
||||
|
||||
PT(DoubleDataAttribute) _atime;
|
||||
PT(DoublePtrDataAttribute) _channels;
|
||||
|
||||
static TypeHandle _btime_type;
|
||||
static TypeHandle _button_id_type;
|
||||
static TypeHandle _state_type;
|
||||
|
||||
static TypeHandle _dtime_type;
|
||||
static TypeHandle _dial_id_type;
|
||||
static TypeHandle _change_type;
|
||||
|
||||
static TypeHandle _atime_type;
|
||||
static TypeHandle _channels_type;
|
||||
|
||||
protected:
|
||||
PT(ClientBase) _client;
|
||||
string _adinput;
|
||||
|
||||
public:
|
||||
virtual TypeHandle get_type() const {
|
||||
return get_class_type();
|
||||
}
|
||||
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
}
|
||||
static void init_type();
|
||||
|
||||
private:
|
||||
static TypeHandle _type_handle;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -1,62 +0,0 @@
|
|||
// Filename: analogData.I
|
||||
// Created by: jason (04Aug00)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AnalogData::Default Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE AnalogData::
|
||||
AnalogData() :
|
||||
atime(0)
|
||||
{
|
||||
channels = new vector_double;
|
||||
stored_channels = new vector_double;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AnalogData::Default Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE AnalogData::
|
||||
~AnalogData() {
|
||||
delete channels;
|
||||
delete stored_channels;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AnalogData::Copy Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE AnalogData::
|
||||
AnalogData(const AnalogData ©) {
|
||||
(*this) = copy;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AnalogData::Copy Assignment Operator
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE AnalogData &AnalogData::
|
||||
operator = (const AnalogData ©) {
|
||||
atime = copy.atime;
|
||||
channels = new vector_double(*copy.channels);
|
||||
stored_channels = new vector_double(*copy.stored_channels);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AnalogData::none
|
||||
// Access: Public, Static
|
||||
// Description: Returns an empty AnalogData object
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE const AnalogData &AnalogData::
|
||||
none() {
|
||||
return _none;
|
||||
}
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
// Filename: analogData.cxx
|
||||
// Created by: jason (04Aug00)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "analogData.h"
|
||||
|
||||
// This is initialized to zero by static initialization.
|
||||
AnalogData AnalogData::_none;
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
// Filename: analogData.h
|
||||
// Created by: jason (04Aug00)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef ANALOG_DATA
|
||||
#define ANALOG_DATA
|
||||
|
||||
#include <pandabase.h>
|
||||
#include <vector_double.h>
|
||||
|
||||
class EXPCL_PANDA AnalogData {
|
||||
public:
|
||||
INLINE AnalogData();
|
||||
INLINE ~AnalogData();
|
||||
INLINE AnalogData(const AnalogData ©);
|
||||
INLINE AnalogData &operator = (const AnalogData ©);
|
||||
|
||||
INLINE static const AnalogData &none();
|
||||
|
||||
double atime;
|
||||
//These two pointers are so that we can return a reference to the
|
||||
//current channel values, but not incure the overhead of copying all
|
||||
//those values everywhere. We need two so that we can implement a
|
||||
//rotating pointer scheme to ensure that there are no collisions
|
||||
//between writing and reading.
|
||||
vector_double *channels;
|
||||
private:
|
||||
vector_double *stored_channels;
|
||||
static AnalogData _none;
|
||||
|
||||
friend class ClientBase;
|
||||
};
|
||||
|
||||
#include "analogData.I"
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,119 @@
|
|||
// Filename: analogNode.I
|
||||
// Created by: drose (26Jan01)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AnalogNode::OutputData::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE AnalogNode::OutputData::
|
||||
OutputData() {
|
||||
_index = -1;
|
||||
_flip = false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AnalogNode::is_valid
|
||||
// Access: Public
|
||||
// Description: Returns true if the AnalogNode is valid and
|
||||
// connected to a server, false otherwise.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool AnalogNode::
|
||||
is_valid() const {
|
||||
return (_analog != (ClientAnalogDevice *)NULL) && _analog->is_connected();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AnalogNode::get_num_controls
|
||||
// Access: Public
|
||||
// Description: Returns the number of analog controls known to the
|
||||
// AnalogNode. This number may change as more controls
|
||||
// are discovered.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int AnalogNode::
|
||||
get_num_controls() const {
|
||||
return _analog->get_num_controls();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AnalogNode::get_control_state
|
||||
// Access: Public
|
||||
// Description: Returns the current position of indicated analog
|
||||
// control identified by its index number, or 0.0 if
|
||||
// the control is unknown. The normal range of a single
|
||||
// control is -1.0 to 1.0.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE double AnalogNode::
|
||||
get_control_state(int index) const {
|
||||
return _analog->get_control_state(index);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AnalogNode::is_control_known
|
||||
// Access: Public
|
||||
// Description: Returns true if the state of the indicated analog
|
||||
// control is known, or false if we have never heard
|
||||
// anything about this particular control.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool AnalogNode::
|
||||
is_control_known(int index) const {
|
||||
return _analog->is_control_known(index);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AnalogNode::set_output
|
||||
// Access: Public
|
||||
// Description: Causes a particular analog control to be placed in
|
||||
// the data graph for the indicated channel. Normally,
|
||||
// a mouse uses channels 0 and 1 for the X and Y
|
||||
// information, respectively; channels 0, 1, and 2 are
|
||||
// available. If flip is true, the analog control value
|
||||
// will be reversed before outputting it.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void AnalogNode::
|
||||
set_output(int channel, int index, bool flip) {
|
||||
nassertv(channel >= 0 && channel < max_outputs);
|
||||
_outputs[channel]._index = index;
|
||||
_outputs[channel]._flip = flip;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AnalogNode::clear_output
|
||||
// Access: Public
|
||||
// Description: Removes the output to the data graph associated with
|
||||
// the indicated channel. See set_output().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void AnalogNode::
|
||||
clear_output(int channel) {
|
||||
nassertv(channel >= 0 && channel < max_outputs);
|
||||
_outputs[channel]._index = -1;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AnalogNode::get_output
|
||||
// Access: Public
|
||||
// Description: Returns the analog control index that is output to
|
||||
// the data graph on the indicated channel, or -1 if no
|
||||
// control is output on that channel. See set_output().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int AnalogNode::
|
||||
get_output(int channel) const {
|
||||
nassertr(channel >= 0 && channel < max_outputs, -1);
|
||||
return _outputs[channel]._index;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AnalogNode::is_output_flipped
|
||||
// Access: Public
|
||||
// Description: Returns true if the analog control index that is
|
||||
// output to the data graph on the indicated channel is
|
||||
// flipped. See set_output().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool AnalogNode::
|
||||
is_output_flipped(int channel) const {
|
||||
nassertr(channel >= 0 && channel < max_outputs, false);
|
||||
return _outputs[channel]._flip;
|
||||
}
|
||||
|
|
@ -0,0 +1,116 @@
|
|||
// Filename: analogNode.cxx
|
||||
// Created by: drose (26Jan01)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "analogNode.h"
|
||||
#include "config_device.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Static variables
|
||||
////////////////////////////////////////////////////////////////////
|
||||
TypeHandle AnalogNode::_type_handle;
|
||||
|
||||
TypeHandle AnalogNode::_xyz_type;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AnalogNode::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
AnalogNode::
|
||||
AnalogNode(ClientBase *client, const string &device_name) :
|
||||
DataNode(device_name)
|
||||
{
|
||||
nassertv(client != (ClientBase *)NULL);
|
||||
PT(ClientDevice) device =
|
||||
client->get_device(ClientAnalogDevice::get_class_type(), device_name);
|
||||
|
||||
if (device == (ClientDevice *)NULL) {
|
||||
device_cat.warning()
|
||||
<< "Unable to open analog device " << device_name << "\n";
|
||||
return;
|
||||
}
|
||||
|
||||
if (!device->is_of_type(ClientAnalogDevice::get_class_type())) {
|
||||
device_cat.error()
|
||||
<< "Inappropriate device type " << device->get_type()
|
||||
<< " created; expected a ClientAnalogDevice.\n";
|
||||
return;
|
||||
}
|
||||
|
||||
_analog = DCAST(ClientAnalogDevice, device);
|
||||
|
||||
_xyz = new Vec3DataAttribute(LPoint3f(0, 0, 0));
|
||||
_attrib.set_attribute(_xyz_type, _xyz);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AnalogNode::Destructor
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
AnalogNode::
|
||||
~AnalogNode() {
|
||||
// When the _analog pointer destructs, the ClientAnalogDevice
|
||||
// disconnects itself from the ClientBase, and everything that needs
|
||||
// to get turned off does. Magic.
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AnalogNode::write
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void AnalogNode::
|
||||
write(ostream &out, int indent_level) const {
|
||||
DataNode::write(out, indent_level);
|
||||
|
||||
if (_analog != (ClientAnalogDevice *)NULL) {
|
||||
_analog->write_controls(out, indent_level + 2);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AnalogNode::transmit_data
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void AnalogNode::
|
||||
transmit_data(NodeAttributes &data) {
|
||||
if (is_valid()) {
|
||||
_analog->poll();
|
||||
|
||||
LPoint3f out(0.0, 0.0, 0.0);
|
||||
|
||||
for (int i = 0; i < max_outputs; i++) {
|
||||
if (_outputs[i]._index >= 0 && is_control_known(_outputs[i]._index)) {
|
||||
if (_outputs[i]._flip) {
|
||||
out[i] = -get_control_state(_outputs[i]._index);
|
||||
} else {
|
||||
out[i] = get_control_state(_outputs[i]._index);
|
||||
}
|
||||
}
|
||||
}
|
||||
_xyz->set_value(out);
|
||||
}
|
||||
|
||||
data = _attrib;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AnalogNode::init_type
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void AnalogNode::
|
||||
init_type() {
|
||||
DataNode::init_type();
|
||||
register_type(_type_handle, "AnalogNode",
|
||||
DataNode::get_class_type());
|
||||
|
||||
Vec3DataTransition::init_type();
|
||||
register_data_transition(_xyz_type, "XYZ",
|
||||
Vec3DataTransition::get_class_type());
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,101 @@
|
|||
// Filename: analogNode.h
|
||||
// Created by: drose (26Jan01)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef ANALOGNODE_H
|
||||
#define ANALOGNODE_H
|
||||
|
||||
#include <pandabase.h>
|
||||
|
||||
#include "clientBase.h"
|
||||
#include "clientAnalogDevice.h"
|
||||
|
||||
#include <dataNode.h>
|
||||
#include <nodeAttributes.h>
|
||||
#include <vec3DataTransition.h>
|
||||
#include <vec3DataAttribute.h>
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : AnalogNode
|
||||
// Description : This is the primary interface to analog controls like
|
||||
// sliders and joysticks associated with a ClientBase.
|
||||
// This creates a node that connects to the named analog
|
||||
// device, if it exists, and provides hooks to the user
|
||||
// to read the state of any of the sequentially numbered
|
||||
// controls associated with that device.
|
||||
//
|
||||
// Each control can return a value ranging from -1 to 1,
|
||||
// reflecting the current position of the control within
|
||||
// its total range of motion.
|
||||
//
|
||||
// The user may choose up to three analog controls to
|
||||
// place on the data graph as the three channels of an
|
||||
// XYZ datagram, similarly to the way a mouse places its
|
||||
// position data. In this way, an AnalogNode may be
|
||||
// used in place of a mouse.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDA AnalogNode : public DataNode {
|
||||
PUBLISHED:
|
||||
AnalogNode(ClientBase *client, const string &device_name);
|
||||
virtual ~AnalogNode();
|
||||
|
||||
INLINE bool is_valid() const;
|
||||
|
||||
INLINE int get_num_controls() const;
|
||||
|
||||
INLINE double get_control_state(int index) const;
|
||||
INLINE bool is_control_known(int index) const;
|
||||
|
||||
INLINE void set_output(int channel, int index, bool flip);
|
||||
INLINE void clear_output(int channel);
|
||||
INLINE int get_output(int channel) const;
|
||||
INLINE bool is_output_flipped(int channel) const;
|
||||
|
||||
public:
|
||||
virtual void write(ostream &out, int indent_level = 0) const;
|
||||
|
||||
private:
|
||||
class OutputData {
|
||||
public:
|
||||
INLINE OutputData();
|
||||
int _index;
|
||||
bool _flip;
|
||||
};
|
||||
|
||||
enum { max_outputs = 3 };
|
||||
OutputData _outputs[max_outputs];
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// From parent class DataNode
|
||||
////////////////////////////////////////////////////////////////////
|
||||
public:
|
||||
virtual void
|
||||
transmit_data(NodeAttributes &data);
|
||||
|
||||
NodeAttributes _attrib;
|
||||
PT(Vec3DataAttribute) _xyz;
|
||||
|
||||
static TypeHandle _xyz_type;
|
||||
|
||||
private:
|
||||
PT(ClientAnalogDevice) _analog;
|
||||
|
||||
public:
|
||||
virtual TypeHandle get_type() const {
|
||||
return get_class_type();
|
||||
}
|
||||
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
}
|
||||
static void init_type();
|
||||
|
||||
private:
|
||||
static TypeHandle _type_handle;
|
||||
};
|
||||
|
||||
#include "analogNode.I"
|
||||
|
||||
#endif
|
||||
|
|
@ -1,49 +0,0 @@
|
|||
// Filename: buttonData.I
|
||||
// Created by: jason (07Aug00)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ButtonData::Default Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE ButtonData::
|
||||
ButtonData() :
|
||||
btime(0), button_id(0), state(0)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ButtonData::Copy Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE ButtonData::
|
||||
ButtonData(const ButtonData ©) {
|
||||
(*this) = copy;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ButtonData::Copy Assignment Operator
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE ButtonData &ButtonData::
|
||||
operator = (const ButtonData ©) {
|
||||
btime = copy.btime;
|
||||
button_id = copy.button_id;
|
||||
state = copy.state;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ButtonData::none
|
||||
// Access: Public, Static
|
||||
// Description: Returns an empty ButtonData object
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE const ButtonData &ButtonData::
|
||||
none() {
|
||||
return _none;
|
||||
}
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
// Filename: buttonData.cxx
|
||||
// Created by: jason (04Aug00)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "buttonData.h"
|
||||
|
||||
// This is initialized to zero by static initialization.
|
||||
ButtonData ButtonData::_none;
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
// Filename: buttonData.h
|
||||
// Created by: jason (07Aug00)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BUTTON_DATA
|
||||
#define BUTTON_DATA
|
||||
|
||||
#include <pandabase.h>
|
||||
#include <vector_float.h>
|
||||
|
||||
class EXPCL_PANDA ButtonData {
|
||||
public:
|
||||
INLINE ButtonData();
|
||||
INLINE ButtonData(const ButtonData ©);
|
||||
INLINE ButtonData &operator = (const ButtonData ©);
|
||||
|
||||
INLINE static const ButtonData &none();
|
||||
|
||||
double btime;
|
||||
int button_id;
|
||||
int state;
|
||||
private:
|
||||
static ButtonData _none;
|
||||
};
|
||||
|
||||
#include "buttonData.I"
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,87 @@
|
|||
// Filename: buttonNode.I
|
||||
// Created by: drose (31Dec69)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ButtonNode::is_valid
|
||||
// Access: Public
|
||||
// Description: Returns true if the ButtonNode is valid and
|
||||
// connected to a server, false otherwise.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool ButtonNode::
|
||||
is_valid() const {
|
||||
return (_button != (ClientButtonDevice *)NULL) && _button->is_connected();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ButtonNode::get_num_buttons
|
||||
// Access: Public
|
||||
// Description: Returns the number of buttons known to the
|
||||
// ButtonNode. This includes those buttons whose state
|
||||
// has been seen, as well as buttons that have been
|
||||
// associated with a ButtonHandle even if their state is
|
||||
// unknown. This number may change as more buttons are
|
||||
// discovered.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int ButtonNode::
|
||||
get_num_buttons() const {
|
||||
return _button->get_num_buttons();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ButtonNode::set_button_map
|
||||
// Access: Public
|
||||
// Description: Associates the indicated ButtonHandle with the button
|
||||
// of the indicated index number. When the given button
|
||||
// index changes state, a corresponding ButtonEvent will
|
||||
// be generated with the given ButtonHandle. Pass
|
||||
// ButtonHandle::none() to turn off any association.
|
||||
//
|
||||
// It is not necessary to call this if you simply want
|
||||
// to query the state of the various buttons by index
|
||||
// number; this is only necessary in order to generate
|
||||
// ButtonEvents when the buttons change state.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void ButtonNode::
|
||||
set_button_map(int index, ButtonHandle button) {
|
||||
_button->set_button_map(index, button);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ButtonNode::get_button_map
|
||||
// Access: Public
|
||||
// Description: Returns the ButtonHandle that was previously
|
||||
// associated with the given index number by
|
||||
// a call to set_button_map(), or ButtonHandle::none()
|
||||
// if no button was associated.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE ButtonHandle ButtonNode::
|
||||
get_button_map(int index) const {
|
||||
return _button->get_button_map(index);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ButtonNode::get_button_state
|
||||
// Access: Public
|
||||
// Description: Returns true if the indicated button (identified by
|
||||
// its index number) is currently known to be down, or
|
||||
// false if it is up or unknown.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool ButtonNode::
|
||||
get_button_state(int index) const {
|
||||
return _button->get_button_state(index);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ButtonNode::is_button_known
|
||||
// Access: Public
|
||||
// Description: Returns true if the state of the indicated button is
|
||||
// known, or false if we have never heard anything about
|
||||
// this particular button.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool ButtonNode::
|
||||
is_button_known(int index) const {
|
||||
return _button->is_button_known(index);
|
||||
}
|
||||
|
|
@ -0,0 +1,132 @@
|
|||
// Filename: buttonNode.cxx
|
||||
// Created by: drose (31Dec69)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "buttonNode.h"
|
||||
#include "config_device.h"
|
||||
|
||||
#include <buttonEventDataTransition.h>
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Static variables
|
||||
////////////////////////////////////////////////////////////////////
|
||||
TypeHandle ButtonNode::_type_handle;
|
||||
|
||||
TypeHandle ButtonNode::_button_events_type;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ButtonNode::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
ButtonNode::
|
||||
ButtonNode(ClientBase *client, const string &device_name) :
|
||||
DataNode(device_name)
|
||||
{
|
||||
nassertv(client != (ClientBase *)NULL);
|
||||
PT(ClientDevice) device =
|
||||
client->get_device(ClientButtonDevice::get_class_type(), device_name);
|
||||
|
||||
if (device == (ClientDevice *)NULL) {
|
||||
device_cat.warning()
|
||||
<< "Unable to open button device " << device_name << "\n";
|
||||
return;
|
||||
}
|
||||
|
||||
if (!device->is_of_type(ClientButtonDevice::get_class_type())) {
|
||||
device_cat.error()
|
||||
<< "Inappropriate device type " << device->get_type()
|
||||
<< " created; expected a ClientButtonDevice.\n";
|
||||
return;
|
||||
}
|
||||
|
||||
_button = DCAST(ClientButtonDevice, device);
|
||||
|
||||
if (_button != (ClientButtonDevice *)NULL) {
|
||||
_button_events = new ButtonEventDataAttribute();
|
||||
_attrib.set_attribute(_button_events_type, _button_events);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ButtonNode::Destructor
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
ButtonNode::
|
||||
~ButtonNode() {
|
||||
// When the _button pointer destructs, the ClientButtonDevice
|
||||
// disconnects itself from the ClientBase, and everything that needs
|
||||
// to get turned off does. Magic.
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ButtonNode::output
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void ButtonNode::
|
||||
output(ostream &out) const {
|
||||
DataNode::output(out);
|
||||
|
||||
if (_button != (ClientButtonDevice *)NULL) {
|
||||
out << " (";
|
||||
_button->output_buttons(out);
|
||||
out << ")";
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ButtonNode::write
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void ButtonNode::
|
||||
write(ostream &out, int indent_level) const {
|
||||
DataNode::write(out, indent_level);
|
||||
|
||||
if (_button != (ClientButtonDevice *)NULL) {
|
||||
_button->write_buttons(out, indent_level + 2);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ButtonNode::transmit_data
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void ButtonNode::
|
||||
transmit_data(NodeAttributes &data) {
|
||||
if (is_valid()) {
|
||||
_button->poll();
|
||||
_button->lock();
|
||||
(*_button_events) = (*_button->get_button_events());
|
||||
_button->get_button_events()->clear();
|
||||
_button->unlock();
|
||||
|
||||
if (device_cat.is_debug()) {
|
||||
device_cat.debug() << "ButtonNode:attributes" << endl;
|
||||
_attrib.write(device_cat.debug(false), 3);
|
||||
}
|
||||
}
|
||||
|
||||
data = _attrib;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ButtonNode::init_type
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void ButtonNode::
|
||||
init_type() {
|
||||
DataNode::init_type();
|
||||
register_type(_type_handle, "ButtonNode",
|
||||
DataNode::get_class_type());
|
||||
|
||||
ButtonEventDataTransition::init_type();
|
||||
register_data_transition(_button_events_type, "ButtonEvents",
|
||||
ButtonEventDataTransition::get_class_type());
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,84 @@
|
|||
// Filename: buttonNode.h
|
||||
// Created by: drose (31Dec69)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BUTTONNODE_H
|
||||
#define BUTTONNODE_H
|
||||
|
||||
#include <pandabase.h>
|
||||
|
||||
#include "clientBase.h"
|
||||
#include "clientButtonDevice.h"
|
||||
|
||||
#include <dataNode.h>
|
||||
#include <nodeAttributes.h>
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : ButtonNode
|
||||
// Description : This is the primary interface to on/off button
|
||||
// devices associated with a ClientBase. This creates a
|
||||
// node that connects to the named button device, if it
|
||||
// exists, and provides hooks to the user to read the
|
||||
// state of any of the sequentially numbered buttons
|
||||
// associated with that device.
|
||||
//
|
||||
// It also can associate an arbitrary ButtonHandle with
|
||||
// each button; when buttons are associated with
|
||||
// ButtonHandles, this node will put appropriate up and
|
||||
// down events on the data graph for each button state
|
||||
// change.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDA ButtonNode : public DataNode {
|
||||
PUBLISHED:
|
||||
ButtonNode(ClientBase *client, const string &device_name);
|
||||
virtual ~ButtonNode();
|
||||
|
||||
INLINE bool is_valid() const;
|
||||
|
||||
INLINE int get_num_buttons() const;
|
||||
|
||||
INLINE void set_button_map(int index, ButtonHandle button);
|
||||
INLINE ButtonHandle get_button_map(int index) const;
|
||||
|
||||
INLINE bool get_button_state(int index) const;
|
||||
INLINE bool is_button_known(int index) const;
|
||||
|
||||
public:
|
||||
virtual void output(ostream &out) const;
|
||||
virtual void write(ostream &out, int indent_level = 0) const;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// From parent class DataNode
|
||||
////////////////////////////////////////////////////////////////////
|
||||
public:
|
||||
virtual void
|
||||
transmit_data(NodeAttributes &data);
|
||||
|
||||
NodeAttributes _attrib;
|
||||
PT(ButtonEventDataAttribute) _button_events;
|
||||
|
||||
// outputs
|
||||
static TypeHandle _button_events_type;
|
||||
|
||||
private:
|
||||
PT(ClientButtonDevice) _button;
|
||||
|
||||
public:
|
||||
virtual TypeHandle get_type() const {
|
||||
return get_class_type();
|
||||
}
|
||||
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
}
|
||||
static void init_type();
|
||||
|
||||
private:
|
||||
static TypeHandle _type_handle;
|
||||
};
|
||||
|
||||
#include "buttonNode.I"
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,90 @@
|
|||
// Filename: clientAnalogDevice.I
|
||||
// Created by: drose (26Jan01)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ClientAnalogDevice::AnalogState::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE ClientAnalogDevice::AnalogState::
|
||||
AnalogState() :
|
||||
_state(0.0),
|
||||
_known(false)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ClientAnalogDevice::Constructor
|
||||
// Access: Protected
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE ClientAnalogDevice::
|
||||
ClientAnalogDevice(ClientBase *client, const string &device_name):
|
||||
ClientDevice(client, get_class_type(), device_name)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ClientAnalogDevice::get_num_controls
|
||||
// Access: Public
|
||||
// Description: Returns the number of analog controls known to the
|
||||
// ClientAnalogDevice. This number may change as
|
||||
// more controls are discovered.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int ClientAnalogDevice::
|
||||
get_num_controls() const {
|
||||
return _controls.size();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ClientAnalogDevice::set_control_state
|
||||
// Access: Public
|
||||
// Description: Sets the state of the indicated analog index. The
|
||||
// caller should ensure that lock() 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.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void ClientAnalogDevice::
|
||||
set_control_state(int index, double state) {
|
||||
ensure_control_index(index);
|
||||
nassertv(index >= 0 && index < (int)_controls.size());
|
||||
_controls[index]._state = state;
|
||||
_controls[index]._known = true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ClientAnalogDevice::get_control_state
|
||||
// Access: Public
|
||||
// Description: Returns the current position of indicated analog
|
||||
// control (identified by its index number), or 0.0 if
|
||||
// the control is unknown. The normal range of a single
|
||||
// control is -1.0 to 1.0.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE double ClientAnalogDevice::
|
||||
get_control_state(int index) const {
|
||||
if (index >= 0 && index < (int)_controls.size()) {
|
||||
return _controls[index]._state;
|
||||
} else {
|
||||
return 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ClientAnalogDevice::is_control_known
|
||||
// Access: Public
|
||||
// Description: Returns true if the state of the indicated analog
|
||||
// control is known, or false if we have never heard
|
||||
// anything about this particular control.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool ClientAnalogDevice::
|
||||
is_control_known(int index) const {
|
||||
if (index >= 0 && index < (int)_controls.size()) {
|
||||
return _controls[index]._known;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
// Filename: clientAnalogDevice.cxx
|
||||
// Created by: drose (26Jan01)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "clientAnalogDevice.h"
|
||||
|
||||
#include <indent.h>
|
||||
|
||||
TypeHandle ClientAnalogDevice::_type_handle;
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ClientAnalogDevice::ensure_control_index
|
||||
// Access: Private
|
||||
// Description: Guarantees that there is a slot in the array for the
|
||||
// indicated index number, by filling the array up to
|
||||
// that index if necessary.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void ClientAnalogDevice::
|
||||
ensure_control_index(int index) {
|
||||
nassertv(index >= 0);
|
||||
|
||||
_controls.reserve(index + 1);
|
||||
while ((int)_controls.size() <= index) {
|
||||
_controls.push_back(AnalogState());
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ClientAnalogDevice::write
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void ClientAnalogDevice::
|
||||
write(ostream &out, int indent_level) const {
|
||||
indent(out, indent_level) << get_type() << " " << get_device_name() << ":\n";
|
||||
write_controls(out, indent_level + 2);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ClientAnalogDevice::write_analogs
|
||||
// Access: Public
|
||||
// Description: Writes a multi-line description of the current analog
|
||||
// control states.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void ClientAnalogDevice::
|
||||
write_controls(ostream &out, int indent_level) const {
|
||||
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";
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
// Filename: clientAnalogDevice.h
|
||||
// Created by: drose (26Jan01)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef CLIENTANALOGDEVICE_H
|
||||
#define CLIENTANALOGDEVICE_H
|
||||
|
||||
#include <pandabase.h>
|
||||
|
||||
#include "clientDevice.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : ClientAnalogDevice
|
||||
// Description : A device, attached to the ClientBase by a
|
||||
// AnalogNode, that records the data from a single
|
||||
// named analog device. The named device can contain
|
||||
// any number of analog controls, numbered in
|
||||
// sequence beginning at zero.
|
||||
//
|
||||
// Each analog control returns a value ranging from -1
|
||||
// to 1, reflecting the current position of the control
|
||||
// within its total range of motion.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDA ClientAnalogDevice : public ClientDevice {
|
||||
protected:
|
||||
INLINE ClientAnalogDevice(ClientBase *client, const string &device_name);
|
||||
|
||||
public:
|
||||
INLINE int get_num_controls() const;
|
||||
|
||||
INLINE void set_control_state(int index, double state);
|
||||
INLINE double get_control_state(int index) const;
|
||||
INLINE bool is_control_known(int index) const;
|
||||
|
||||
virtual void write(ostream &out, int indent_level = 0) const;
|
||||
void write_controls(ostream &out, int indent_level) const;
|
||||
|
||||
private:
|
||||
void ensure_control_index(int index);
|
||||
|
||||
protected:
|
||||
class AnalogState {
|
||||
public:
|
||||
INLINE AnalogState();
|
||||
|
||||
double _state;
|
||||
bool _known;
|
||||
};
|
||||
|
||||
typedef vector<AnalogState> Controls;
|
||||
Controls _controls;
|
||||
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
}
|
||||
static void init_type() {
|
||||
ClientDevice::init_type();
|
||||
register_type(_type_handle, "ClientAnalogDevice",
|
||||
ClientDevice::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 "clientAnalogDevice.I"
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
// Filename: clientBase.I
|
||||
// Created by: drose (25Jan01)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ClientBase::is_forked
|
||||
// Access: Public
|
||||
// Description: Returns true if the ClientBase has been forked (and,
|
||||
// therefore, poll() does not need to be called), false
|
||||
// otherwise.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool ClientBase::
|
||||
is_forked() const {
|
||||
return _forked;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ClientBase::poll
|
||||
// Access: Public
|
||||
// Description: Initiates a poll of the client devices, if we are not
|
||||
// forked and if we have not already polled this frame.
|
||||
// Returns true if the poll occurred, or false if it did
|
||||
// not.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool ClientBase::
|
||||
poll() {
|
||||
if (_forked ||
|
||||
_last_poll_frame == ClockObject::get_global_clock()->get_frame_count()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
do_poll();
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ClientBase::get_last_poll_time
|
||||
// Access: Public
|
||||
// Description: Returns the time (according to the global
|
||||
// ClockObject's get_real_time() method) of the last
|
||||
// device poll.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE double ClientBase::
|
||||
get_last_poll_time() const {
|
||||
return _last_poll_time;
|
||||
}
|
||||
|
|
@ -8,18 +8,19 @@
|
|||
|
||||
TypeHandle ClientBase::_type_handle;
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ClientBase::constructor
|
||||
// Access: Public
|
||||
// Access: Protected
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
ClientBase::
|
||||
ClientBase(const string &server) :
|
||||
_sleep_time(1000000/60), _server(server), _forked(false)
|
||||
{
|
||||
ClientBase() {
|
||||
_forked = false;
|
||||
_last_poll_time = 0.0;
|
||||
_last_poll_frame = 0;
|
||||
|
||||
#ifdef HAVE_IPC
|
||||
_client_thread = (thread *)NULL;
|
||||
_shutdown = false;
|
||||
#endif
|
||||
}
|
||||
|
|
@ -31,20 +32,22 @@ ClientBase(const string &server) :
|
|||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
ClientBase::
|
||||
~ClientBase()
|
||||
{
|
||||
#ifdef HAVE_IPC
|
||||
if (asynchronous_clients && _forked == true) {
|
||||
{
|
||||
//Make sure that you grab all locks before setting shutdown to
|
||||
//true. This ensures that all polling actions on the thread
|
||||
//serving the devices have finished before we tell it to
|
||||
//shutdown
|
||||
mutex_lock t_lock(_tracker_lock);
|
||||
mutex_lock a_lock(_analog_lock);
|
||||
mutex_lock b_lock(_button_lock);
|
||||
_shutdown = true;
|
||||
~ClientBase() {
|
||||
// We have to disconnect all of our devices before destructing.
|
||||
Devices::iterator di;
|
||||
Devices devices_copy = _devices;
|
||||
for (di = devices_copy.begin(); di != devices_copy.end(); ++di) {
|
||||
DevicesByName &dbn = (*di).second;
|
||||
DevicesByName::iterator dbni;
|
||||
for (dbni = dbn.begin(); dbni != dbn.end(); ++dbni) {
|
||||
ClientDevice *device = (*dbni).second;
|
||||
device->disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_IPC
|
||||
if (_forked) {
|
||||
_shutdown = true;
|
||||
|
||||
// Join the loader thread - calling process blocks until the loader
|
||||
// thread returns.
|
||||
|
|
@ -53,15 +56,29 @@ ClientBase::
|
|||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ClientBase::fork_asynchronous_thread
|
||||
// Access: Public
|
||||
// Description:
|
||||
// Description: Forks a separate thread to do all the polling of
|
||||
// connected devices. The forked thread will poll after
|
||||
// every poll_time seconds has elapsed. Returns true if
|
||||
// the fork was successful, or false otherwise (for
|
||||
// instance, because we were already forked, or because
|
||||
// asynchronous threads are disabled).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void ClientBase::
|
||||
fork_asynchronous_thread(void) {
|
||||
bool ClientBase::
|
||||
fork_asynchronous_thread(double poll_time) {
|
||||
#ifdef HAVE_IPC
|
||||
if (_forked) {
|
||||
device_cat.error()
|
||||
<< "Attempt to fork client thread twice.\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (asynchronous_clients) {
|
||||
_sleep_time = (int)(1000000 * poll_time);
|
||||
|
||||
_client_thread = thread::create(&st_callback, this);
|
||||
_forked = true;
|
||||
if (device_cat.is_debug()) {
|
||||
|
|
@ -69,22 +86,107 @@ fork_asynchronous_thread(void) {
|
|||
<< "fork_asynchronous_thread() - forking client thread"
|
||||
<< endl;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ClientBase::set_poll_time
|
||||
// Function: ClientBase::get_device
|
||||
// Access: Public
|
||||
// Description: Sets the time between polls. The poll time is assumed
|
||||
// to be in seconds
|
||||
// Description: Returns a ClientDevice pointer that corresponds to
|
||||
// the named device of the indicated device type. The
|
||||
// device_type should be one of ClientTrackerDevice,
|
||||
// ClientAnalogDevice, etc.; the device_name is
|
||||
// implementation defined.
|
||||
//
|
||||
// Normally, the user does not need to call this
|
||||
// function directly; it is called automatically by
|
||||
// creating a TrackerNode or AnalogNode or some such
|
||||
// data graph node.
|
||||
//
|
||||
// The return value is the pointer to the created device
|
||||
// (which might be the same pointer returned by a
|
||||
// previous call to this function with the same
|
||||
// parameters). When the pointer destructs (i.e. its
|
||||
// reference count reaches zero) it will automatically
|
||||
// be disconnected.
|
||||
//
|
||||
// If the named device does not exist or cannot be
|
||||
// connected for some reason, NULL is returned.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PT(ClientDevice) ClientBase::
|
||||
get_device(TypeHandle device_type, const string &device_name) {
|
||||
DevicesByName &dbn = _devices[device_type];
|
||||
|
||||
DevicesByName::iterator dbni;
|
||||
dbni = dbn.find(device_name);
|
||||
if (dbni != dbn.end()) {
|
||||
// This device was previously connected. Return it again.
|
||||
return (*dbni).second;
|
||||
}
|
||||
|
||||
// We need to create a new device for this name.
|
||||
PT(ClientDevice) device = make_device(device_type, device_name);
|
||||
|
||||
if (device != (ClientDevice *)NULL) {
|
||||
dbn.insert(DevicesByName::value_type(device_name, device));
|
||||
device->_is_connected = true;
|
||||
}
|
||||
|
||||
return device;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ClientBase::disconnect_device
|
||||
// Access: Protected, Virtual
|
||||
// Description: Removes the device, which is presumably about to
|
||||
// destruct, from the list of connected devices, and
|
||||
// frees any data required to support it. This device
|
||||
// will no longer receive automatic updates with each
|
||||
// poll.
|
||||
//
|
||||
// The return value is true if the device was
|
||||
// disconnected, or false if it was unknown (e.g. it was
|
||||
// disconnected previously).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool ClientBase::
|
||||
disconnect_device(TypeHandle device_type, const string &device_name,
|
||||
ClientDevice *device) {
|
||||
DevicesByName &dbn = _devices[device_type];
|
||||
|
||||
DevicesByName::iterator dbni;
|
||||
dbni = dbn.find(device_name);
|
||||
if (dbni != dbn.end()) {
|
||||
if ((*dbni).second == device) {
|
||||
// We found it!
|
||||
dbn.erase(dbni);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// The device was unknown.
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ClientBase::do_poll
|
||||
// Access: Protected, Virtual
|
||||
// Description: Implements the polling and updating of connected
|
||||
// devices, if the ClientBase requires this. This may
|
||||
// be called in a sub-thread if
|
||||
// fork_asynchronous_thread() was called; otherwise, it
|
||||
// will be called once per frame.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void ClientBase::
|
||||
set_poll_time(float poll_time) {
|
||||
_sleep_time = (int)(1000000 * poll_time);
|
||||
do_poll() {
|
||||
ClockObject *global_clock = ClockObject::get_global_clock();
|
||||
_last_poll_frame = global_clock->get_frame_count();
|
||||
_last_poll_time = global_clock->get_time();
|
||||
}
|
||||
|
||||
|
||||
#ifdef HAVE_IPC
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ClientBase::st_callback
|
||||
|
|
@ -113,339 +215,13 @@ st_callback(void *arg) {
|
|||
// being watched
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void ClientBase::
|
||||
callback(void) {
|
||||
while(true) {
|
||||
callback() {
|
||||
while (true) {
|
||||
if (_shutdown) {
|
||||
break;
|
||||
}
|
||||
poll_trackers();
|
||||
poll_analogs();
|
||||
poll_buttons();
|
||||
do_poll();
|
||||
ipc_traits::sleep(0, _sleep_time);
|
||||
}
|
||||
}
|
||||
#endif // HAVE_IPC
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ClientBase::get_tracker_data
|
||||
// Access: Public, Virtual
|
||||
// Description: Returns the current data for the sensor of a particular
|
||||
// tracker
|
||||
////////////////////////////////////////////////////////////////////
|
||||
const TrackerData& ClientBase::
|
||||
get_tracker_data(const string &tracker, int sensor) {
|
||||
|
||||
//Very important that this check and associated call are made before
|
||||
//the mutex lock, otherwise if we are not forked and we lock before
|
||||
//doing poll we will get into a deadlock condition when the
|
||||
//associated push for this function is called
|
||||
if (!_forked) {
|
||||
poll_tracker(tracker);
|
||||
}
|
||||
|
||||
//Make sure to prevent simultaneous write and read of device
|
||||
#ifdef HAVE_IPC
|
||||
mutex_lock lock(_tracker_lock);
|
||||
#endif
|
||||
|
||||
if ((find(_trackers.begin(), _trackers.end(), tracker) != _trackers.end()) ||
|
||||
(find(_sensors[tracker].begin(), _sensors[tracker].end(), sensor)
|
||||
!= _sensors[tracker].end())) {
|
||||
if (_tracker_datas.find(tracker) != _tracker_datas.end()) {
|
||||
if (_tracker_datas[tracker].find(sensor) != _tracker_datas[tracker].end()) {
|
||||
return _tracker_datas[tracker][sensor];
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
device_cat.error() << "Request for either unknown sensor " << sensor
|
||||
<< " or unknown tracker " << tracker << " made" << endl;
|
||||
}
|
||||
|
||||
return TrackerData::none();
|
||||
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ClientBase::get_analog_data
|
||||
// Access: Public, Virtual
|
||||
// Description: Returns the current data for the sensor of a particular
|
||||
// analog
|
||||
////////////////////////////////////////////////////////////////////
|
||||
const AnalogData& ClientBase::
|
||||
get_analog_data(const string &analog) {
|
||||
|
||||
//Very important that this check and associated call are made before
|
||||
//the mutex lock, otherwise if we are not forked and we lock before
|
||||
//doing poll we will get into a deadlock condition when the
|
||||
//associated push for this function is called
|
||||
if (!_forked) {
|
||||
poll_analog(analog);
|
||||
}
|
||||
|
||||
//Make sure to prevent simultaneous write and read of device
|
||||
#ifdef HAVE_IPC
|
||||
mutex_lock lock(_analog_lock);
|
||||
#endif
|
||||
|
||||
if (find(_analogs.begin(), _analogs.end(), analog) != _analogs.end()) {
|
||||
if (_analog_datas.find(analog) != _analog_datas.end()) {
|
||||
//Make sure to rotate the arrays to ensure access safety
|
||||
swap(_analog_datas[analog].channels, _analog_datas[analog].stored_channels);
|
||||
return _analog_datas[analog];
|
||||
}
|
||||
}
|
||||
else {
|
||||
device_cat.error() << "Request for unknown analog " << analog << " made" << endl;
|
||||
}
|
||||
|
||||
return AnalogData::none();
|
||||
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ClientBase::get_button_data
|
||||
// Access: Public, Virtual
|
||||
// Description: Returns the current data for the sensor of a particular
|
||||
// button
|
||||
////////////////////////////////////////////////////////////////////
|
||||
const ButtonData& ClientBase::
|
||||
get_button_data(const string &button) {
|
||||
|
||||
//Very important that this check and associated call are made before
|
||||
//the mutex lock, otherwise if we are not forked and we lock before
|
||||
//doing poll we will get into a deadlock condition when the
|
||||
//associated push for this function is called
|
||||
if (!_forked) {
|
||||
poll_button(button);
|
||||
}
|
||||
|
||||
//Make sure to prevent simultaneous write and read of device
|
||||
#ifdef HAVE_IPC
|
||||
mutex_lock lock(_button_lock);
|
||||
#endif
|
||||
|
||||
if (find(_buttons.begin(), _buttons.end(), button) != _buttons.end()) {
|
||||
if (_button_datas.find(button) != _button_datas.end()) {
|
||||
return _button_datas[button];
|
||||
}
|
||||
}
|
||||
else {
|
||||
device_cat.error() << "Request for unknown button " << button << " made" << endl;
|
||||
}
|
||||
|
||||
return ButtonData::none();
|
||||
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ClientBase::get_dial_data
|
||||
// Access: Public, Virtual
|
||||
// Description: Returns the current data for the sensor of a particular
|
||||
// dial
|
||||
////////////////////////////////////////////////////////////////////
|
||||
const DialData& ClientBase::
|
||||
get_dial_data(const string &dial) {
|
||||
|
||||
//Very important that this check and associated call are made before
|
||||
//the mutex lock, otherwise if we are not forked and we lock before
|
||||
//doing poll we will get into a deadlock condition when the
|
||||
//associated push for this function is called
|
||||
if (!_forked) {
|
||||
poll_dial(dial);
|
||||
}
|
||||
|
||||
//Make sure to prevent simultaneous write and read of device
|
||||
#ifdef HAVE_IPC
|
||||
mutex_lock lock(_dial_lock);
|
||||
#endif
|
||||
|
||||
if (find(_dials.begin(), _dials.end(), dial) != _dials.end()) {
|
||||
if (_dial_datas.find(dial) != _dial_datas.end()) {
|
||||
return _dial_datas[dial];
|
||||
}
|
||||
}
|
||||
else {
|
||||
device_cat.error() << "Request for unknown dial " << dial << " made" << endl;
|
||||
}
|
||||
|
||||
return DialData::none();
|
||||
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ClientBase::push_tracker_position
|
||||
// Access: Protected, Virtual
|
||||
// Description: Use this function in the children class to fill in
|
||||
// tracker data
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void ClientBase::
|
||||
push_tracker_position(const string &tracker, const int &sensor, const double &ptime,
|
||||
const LPoint3f &pos, const LVector4f &pquat) {
|
||||
//Make sure to prevent simultaneous write and read of device
|
||||
#ifdef HAVE_IPC
|
||||
mutex_lock lock(_tracker_lock);
|
||||
#endif
|
||||
|
||||
_tracker_datas[tracker][sensor].ptime = ptime;
|
||||
_tracker_datas[tracker][sensor].position = pos;
|
||||
_tracker_datas[tracker][sensor].pquat = pquat;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ClientBase::push_tracker_position
|
||||
// Access: Protected, Virtual
|
||||
// Description: Use this function in the children class to fill in
|
||||
// tracker data
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void ClientBase::
|
||||
push_tracker_velocity(const string &tracker, int sensor, const double &vtime,
|
||||
const LPoint3f &vel, const LVector4f &vquat, const float &dt) {
|
||||
//Make sure to prevent simultaneous write and read of device
|
||||
#ifdef HAVE_IPC
|
||||
mutex_lock lock(_tracker_lock);
|
||||
#endif
|
||||
|
||||
_tracker_datas[tracker][sensor].vtime = vtime;
|
||||
_tracker_datas[tracker][sensor].velocity = vel;
|
||||
_tracker_datas[tracker][sensor].vquat = vquat;
|
||||
_tracker_datas[tracker][sensor].vquat_dt = dt;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ClientBase::push_tracker_position
|
||||
// Access: Protected, Virtual
|
||||
// Description: Use this function in the children class to fill in
|
||||
// tracker data
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void ClientBase::
|
||||
push_tracker_acceleration(const string &tracker, const int &sensor, const double &atime,
|
||||
const LPoint3f &acc, const LVector4f &aquat, const float &dt) {
|
||||
//Make sure to prevent simultaneous write and read of device
|
||||
#ifdef HAVE_IPC
|
||||
mutex_lock lock(_tracker_lock);
|
||||
#endif
|
||||
|
||||
_tracker_datas[tracker][sensor].atime = atime;
|
||||
_tracker_datas[tracker][sensor].acceleration = acc;
|
||||
_tracker_datas[tracker][sensor].aquat = aquat;
|
||||
_tracker_datas[tracker][sensor].aquat_dt = dt;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ClientBase::push_analog
|
||||
// Access: Protected, Virtual
|
||||
// Description: Use this function in the children class to fill in
|
||||
// analog data
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void ClientBase::
|
||||
push_analog(const string &analog, const float &atime,
|
||||
const double *channels, int num_channels) {
|
||||
//Make sure to prevent simultaneous write and read of device
|
||||
#ifdef HAVE_IPC
|
||||
mutex_lock lock(_analog_lock);
|
||||
#endif
|
||||
|
||||
_analog_datas[analog].atime = atime;
|
||||
|
||||
const double *head = channels;
|
||||
const double *end = head + num_channels;
|
||||
_analog_datas[analog].stored_channels->clear();
|
||||
vector_double::iterator start = _analog_datas[analog].stored_channels->begin();
|
||||
_analog_datas[analog].stored_channels->insert(start, head, end);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ClientBase::push_button
|
||||
// Access: Protected, Virtual
|
||||
// Description: Use this function in the children class to fill in
|
||||
// button data
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void ClientBase::
|
||||
push_button(const string &button, const float &btime, const int &button_id,
|
||||
const int &state) {
|
||||
//Make sure to prevent simultaneous write and read of device
|
||||
#ifdef HAVE_IPC
|
||||
mutex_lock lock(_button_lock);
|
||||
#endif
|
||||
|
||||
_button_datas[button].btime = btime;
|
||||
_button_datas[button].button_id = button_id;
|
||||
_button_datas[button].state = state;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ClientBase::push_dial
|
||||
// Access: Protected, Virtual
|
||||
// Description: Use this function in the children class to fill in
|
||||
// dial data
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void ClientBase::
|
||||
push_dial(const string &dial, const float &dtime, const int &dial_id,
|
||||
const float &change) {
|
||||
//Make sure to prevent simultaneous write and read of device
|
||||
#ifdef HAVE_IPC
|
||||
mutex_lock lock(_dial_lock);
|
||||
#endif
|
||||
|
||||
_dial_datas[dial].dtime = dtime;
|
||||
_dial_datas[dial].dial_id = dial_id;
|
||||
_dial_datas[dial].change = change;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ClientBase::poll_trackers()
|
||||
// Access: Private
|
||||
// Description: Polls all current trackers
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void ClientBase::
|
||||
poll_trackers() {
|
||||
Trackers::iterator ti = _trackers.begin();
|
||||
for(; ti != _trackers.end(); ti++) {
|
||||
poll_tracker((*ti));
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ClientBase::poll_analogs()
|
||||
// Access: Private
|
||||
// Description: Polls all current analogs
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void ClientBase::
|
||||
poll_analogs() {
|
||||
Analogs::iterator ti = _analogs.begin();
|
||||
for(; ti != _analogs.end(); ti++) {
|
||||
poll_analog((*ti));
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ClientBase::poll_buttons()
|
||||
// Access: Private
|
||||
// Description: Polls all current buttons
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void ClientBase::
|
||||
poll_buttons() {
|
||||
Buttons::iterator ti = _buttons.begin();
|
||||
for(; ti != _buttons.end(); ti++) {
|
||||
poll_button((*ti));
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ClientBase::poll_dials()
|
||||
// Access: Private
|
||||
// Description: Polls all current dials
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void ClientBase::
|
||||
poll_dials() {
|
||||
Dials::iterator ti = _dials.begin();
|
||||
for(; ti != _dials.end(); ti++) {
|
||||
poll_dial((*ti));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -3,145 +3,102 @@
|
|||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _CLIENT_BASE
|
||||
#define _CLIENT_BASE
|
||||
#ifndef CLIENTBASE_H
|
||||
#define CLIENTBASE_H
|
||||
|
||||
#include <pandabase.h>
|
||||
|
||||
#include "trackerData.h"
|
||||
#include "analogData.h"
|
||||
#include "buttonData.h"
|
||||
#include "dialData.h"
|
||||
#include "clientDevice.h"
|
||||
|
||||
#include <typedReferenceCount.h>
|
||||
#include <luse.h>
|
||||
#include <vector_string.h>
|
||||
#include <vector_int.h>
|
||||
#include <clockObject.h>
|
||||
#include <pointerTo.h>
|
||||
|
||||
#ifdef HAVE_IPC
|
||||
#include <ipc_mutex.h>
|
||||
#include <ipc_condition.h>
|
||||
#include <ipc_thread.h>
|
||||
#endif
|
||||
|
||||
#include <map>
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : ClientBase
|
||||
// Description : An abstract base class for a family of of client
|
||||
// device interfaces--including trackers, buttons,
|
||||
// dials, and other analog inputs.
|
||||
//
|
||||
// This provides a common interface to connect to such
|
||||
// devices and extract their data; it is used by
|
||||
// TrackerNode etc. to put these devices in the data
|
||||
// graph.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDA ClientBase : public TypedReferenceCount {
|
||||
PUBLISHED:
|
||||
ClientBase(const string &server);
|
||||
~ClientBase();
|
||||
void fork_asynchronous_thread(void);
|
||||
void set_poll_time(float poll_time);
|
||||
protected:
|
||||
ClientBase();
|
||||
|
||||
//ADD FUNCTIONS
|
||||
virtual bool add_remote_tracker(const string &tracker, int sensor) = 0;
|
||||
virtual bool add_remote_analog(const string &analog) = 0;
|
||||
virtual bool add_remote_button(const string &button) = 0;
|
||||
virtual bool add_remote_dial(const string &dial) = 0;
|
||||
PUBLISHED:
|
||||
~ClientBase();
|
||||
|
||||
bool fork_asynchronous_thread(double poll_time);
|
||||
INLINE bool is_forked() const;
|
||||
INLINE bool poll();
|
||||
INLINE double get_last_poll_time() const;
|
||||
|
||||
public:
|
||||
//GET FUNCTIONS
|
||||
virtual const TrackerData &get_tracker_data(const string &tracker, int sensor);
|
||||
virtual const AnalogData &get_analog_data(const string &analog);
|
||||
virtual const ButtonData &get_button_data(const string &button);
|
||||
virtual const DialData &get_dial_data(const string &dial);
|
||||
|
||||
PT(ClientDevice) get_device(TypeHandle device_type,
|
||||
const string &device_name);
|
||||
|
||||
protected:
|
||||
void push_tracker_position(const string &tracker, const int &sensor, const double &ptime,
|
||||
const LPoint3f &pos, const LVector4f &pquat);
|
||||
void push_tracker_velocity(const string &tracker, int sensor, const double &vtime,
|
||||
const LPoint3f &vel, const LVector4f &vquat, const float &dt);
|
||||
void push_tracker_acceleration(const string &tracker, const int &sensor, const double &atime,
|
||||
const LPoint3f &acc, const LVector4f &aquat, const float &dt);
|
||||
virtual PT(ClientDevice) make_device(TypeHandle device_type,
|
||||
const string &device_name)=0;
|
||||
|
||||
void push_analog(const string &analog, const float &atime,
|
||||
const double *channels, int num_channels);
|
||||
void push_button(const string &button, const float &btime, const int &button_id,
|
||||
const int &state);
|
||||
void push_dial(const string &dial, const float &dtime, const int &dial_id,
|
||||
const float &change);
|
||||
virtual bool disconnect_device(TypeHandle device_type,
|
||||
const string &device_name,
|
||||
ClientDevice *device);
|
||||
|
||||
virtual void do_poll();
|
||||
|
||||
private:
|
||||
int _sleep_time;
|
||||
const string _server;
|
||||
typedef map<string, ClientDevice *> DevicesByName;
|
||||
typedef map<TypeHandle, DevicesByName> Devices;
|
||||
Devices _devices;
|
||||
|
||||
bool _forked;
|
||||
double _last_poll_time;
|
||||
int _last_poll_frame;
|
||||
|
||||
#ifdef HAVE_IPC
|
||||
//Device locks and conditionals
|
||||
mutex _tracker_lock;
|
||||
mutex _analog_lock;
|
||||
mutex _button_lock;
|
||||
mutex _dial_lock;
|
||||
|
||||
//Thread variables and functions
|
||||
int _sleep_time;
|
||||
thread *_client_thread;
|
||||
bool _shutdown;
|
||||
|
||||
static void* st_callback(void *arg);
|
||||
void callback(void);
|
||||
void callback();
|
||||
#endif
|
||||
|
||||
protected:
|
||||
//Device polling functions
|
||||
void poll_trackers();
|
||||
virtual void poll_tracker(const string &tracker) = 0;
|
||||
|
||||
void poll_analogs();
|
||||
virtual void poll_analog(const string &analog) = 0;
|
||||
virtual int max_analog_channels(void) = 0;
|
||||
|
||||
void poll_buttons();
|
||||
virtual void poll_button(const string &button) = 0;
|
||||
|
||||
void poll_dials();
|
||||
virtual void poll_dial(const string &dial) = 0;
|
||||
|
||||
|
||||
protected:
|
||||
typedef map< int, TrackerData > SensorDatas;
|
||||
typedef map< const string, SensorDatas > TrackerDatas;
|
||||
typedef map< const string, AnalogData > AnalogDatas;
|
||||
typedef map< const string, ButtonData > ButtonDatas;
|
||||
typedef map< const string, DialData > DialDatas;
|
||||
|
||||
typedef vector_string Trackers;
|
||||
typedef vector_int Sensors;
|
||||
typedef map< string, Sensors > TrackerSensors;
|
||||
typedef vector_string Analogs;
|
||||
typedef vector_string Buttons;
|
||||
typedef vector_string Dials;
|
||||
|
||||
TrackerDatas _tracker_datas;
|
||||
Trackers _trackers;
|
||||
TrackerSensors _sensors;
|
||||
|
||||
AnalogDatas _analog_datas;
|
||||
Analogs _analogs;
|
||||
|
||||
ButtonDatas _button_datas;
|
||||
Buttons _buttons;
|
||||
|
||||
DialDatas _dial_datas;
|
||||
Dials _dials;
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type( void ) {
|
||||
return _type_handle;
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
}
|
||||
static void init_type( void ) {
|
||||
static void init_type() {
|
||||
TypedReferenceCount::init_type();
|
||||
register_type( _type_handle, "ClientBase",
|
||||
TypedReferenceCount::get_class_type() );
|
||||
register_type(_type_handle, "ClientBase",
|
||||
TypedReferenceCount::get_class_type());
|
||||
}
|
||||
virtual TypeHandle get_type( void ) const {
|
||||
virtual TypeHandle get_type() const {
|
||||
return get_class_type();
|
||||
}
|
||||
virtual TypeHandle force_init_type() {
|
||||
init_type();
|
||||
return get_class_type();
|
||||
}
|
||||
|
||||
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
|
||||
|
||||
private:
|
||||
static TypeHandle _type_handle;
|
||||
static TypeHandle _type_handle;
|
||||
|
||||
friend class ClientDevice;
|
||||
};
|
||||
|
||||
#include "clientBase.I"
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -0,0 +1,115 @@
|
|||
// Filename: clientButtonDevice.I
|
||||
// Created by: drose (26Jan01)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ClientButtonDevice::ButtonState::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE ClientButtonDevice::ButtonState::
|
||||
ButtonState() :
|
||||
_handle(ButtonHandle::none()),
|
||||
_state(S_unknown)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ClientButtonDevice::get_num_buttons
|
||||
// Access: Public
|
||||
// Description: Returns the number of buttons known to the
|
||||
// ClientButtonDevice. This includes those buttons
|
||||
// whose state has been seen, as well as buttons that
|
||||
// have been associated with a ButtonHandle even if
|
||||
// their state is unknown. This number may change as
|
||||
// more buttons are discovered.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int ClientButtonDevice::
|
||||
get_num_buttons() const {
|
||||
return _buttons.size();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ClientButtonDevice::set_button_map
|
||||
// Access: Public
|
||||
// Description: Associates the indicated ButtonHandle with the button
|
||||
// of the indicated index number. When the given button
|
||||
// index changes state, a corresponding ButtonEvent will
|
||||
// be generated with the given ButtonHandle. Pass
|
||||
// ButtonHandle::none() to turn off any association.
|
||||
//
|
||||
// It is not necessary to call this if you simply want
|
||||
// to query the state of the various buttons by index
|
||||
// number; this is only necessary in order to generate
|
||||
// ButtonEvents when the buttons change state.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void ClientButtonDevice::
|
||||
set_button_map(int index, ButtonHandle button) {
|
||||
ensure_button_index(index);
|
||||
nassertv(index >= 0 && index < (int)_buttons.size());
|
||||
_buttons[index]._handle = button;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ClientButtonDevice::get_button_map
|
||||
// Access: Public
|
||||
// Description: Returns the ButtonHandle that was previously
|
||||
// associated with the given index number by
|
||||
// a call to set_button_map(), or ButtonHandle::none()
|
||||
// if no button was associated.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE ButtonHandle ClientButtonDevice::
|
||||
get_button_map(int index) const {
|
||||
if (index >= 0 && index < (int)_buttons.size()) {
|
||||
return _buttons[index]._handle;
|
||||
} else {
|
||||
return ButtonHandle::none();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ClientButtonDevice::get_button_state
|
||||
// Access: Public
|
||||
// Description: Returns true if the indicated button (identified by
|
||||
// its index number) is currently known to be down, or
|
||||
// false if it is up or unknown.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool ClientButtonDevice::
|
||||
get_button_state(int index) const {
|
||||
if (index >= 0 && index < (int)_buttons.size()) {
|
||||
return (_buttons[index]._state == S_down);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ClientButtonDevice::is_button_known
|
||||
// Access: Public
|
||||
// Description: Returns true if the state of the indicated button is
|
||||
// known, or false if we have never heard anything about
|
||||
// this particular button.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool ClientButtonDevice::
|
||||
is_button_known(int index) const {
|
||||
if (index >= 0 && index < (int)_buttons.size()) {
|
||||
return _buttons[index]._state != S_unknown;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ClientButtonDevice::get_button_events
|
||||
// Access: Public
|
||||
// Description: Returns the list of recently-generated ButtonEvents.
|
||||
// This must be periodically cleared, or the buttons
|
||||
// will accumulate.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE ButtonEventDataAttribute *ClientButtonDevice::
|
||||
get_button_events() const {
|
||||
return _button_events;
|
||||
}
|
||||
|
|
@ -0,0 +1,153 @@
|
|||
// Filename: clientButtonDevice.cxx
|
||||
// Created by: drose (26Jan01)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "clientButtonDevice.h"
|
||||
|
||||
#include <indent.h>
|
||||
|
||||
TypeHandle ClientButtonDevice::_type_handle;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ClientButtonDevice::Constructor
|
||||
// Access: Protected
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
ClientButtonDevice::
|
||||
ClientButtonDevice(ClientBase *client, const string &device_name):
|
||||
ClientDevice(client, get_class_type(), device_name)
|
||||
{
|
||||
_button_events = new ButtonEventDataAttribute();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ClientButtonDevice::set_button_state
|
||||
// Access: Public
|
||||
// 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 lock() is in effect while this call is made.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void ClientButtonDevice::
|
||||
set_button_state(int index, bool down) {
|
||||
ensure_button_index(index);
|
||||
nassertv(index >= 0 && index < (int)_buttons.size());
|
||||
_buttons[index]._state = down ? S_down : S_up;
|
||||
|
||||
ButtonHandle handle = _buttons[index]._handle;
|
||||
if (handle != ButtonHandle::none()) {
|
||||
_button_events->push_back(ButtonEvent(handle, down));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ClientButtonDevice::ensure_button_index
|
||||
// Access: Private
|
||||
// Description: Guarantees that there is a slot in the array for the
|
||||
// indicated index number, by filling the array up to
|
||||
// that index if necessary.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void ClientButtonDevice::
|
||||
ensure_button_index(int index) {
|
||||
nassertv(index >= 0);
|
||||
|
||||
_buttons.reserve(index + 1);
|
||||
while ((int)_buttons.size() <= index) {
|
||||
_buttons.push_back(ButtonState());
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ClientButtonDevice::output
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void ClientButtonDevice::
|
||||
output(ostream &out) const {
|
||||
out << get_type() << " " << get_device_name() << " (";
|
||||
output_buttons(out);
|
||||
out << ")";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ClientButtonDevice::write
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void ClientButtonDevice::
|
||||
write(ostream &out, int indent_level) const {
|
||||
indent(out, indent_level) << get_type() << " " << get_device_name() << ":\n";
|
||||
write_buttons(out, indent_level + 2);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ClientButtonDevice::output_buttons
|
||||
// Access: Public
|
||||
// Description: Writes a one-line string of all of the current button
|
||||
// states.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void ClientButtonDevice::
|
||||
output_buttons(ostream &out) 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) {
|
||||
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: ClientButtonDevice::write_buttons
|
||||
// Access: Public
|
||||
// Description: Writes a multi-line description of the current button
|
||||
// states.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void ClientButtonDevice::
|
||||
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";
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,92 @@
|
|||
// Filename: clientButtonDevice.h
|
||||
// Created by: drose (26Jan01)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef CLIENTBUTTONDEVICE_H
|
||||
#define CLIENTBUTTONDEVICE_H
|
||||
|
||||
#include <pandabase.h>
|
||||
|
||||
#include "clientDevice.h"
|
||||
|
||||
#include <buttonHandle.h>
|
||||
#include <buttonEvent.h>
|
||||
#include <buttonEventDataAttribute.h>
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : ClientButtonDevice
|
||||
// Description : A device, attached to the ClientBase by a
|
||||
// ButtonNode, that records the data from a single
|
||||
// named button device. The named device can contain
|
||||
// any number of up/down style buttons, numbered in
|
||||
// sequence beginning at zero; these are mapped by this
|
||||
// class to a sequence of ButtonHandles specified by the
|
||||
// user.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDA ClientButtonDevice : public ClientDevice {
|
||||
protected:
|
||||
ClientButtonDevice(ClientBase *client, const string &device_name);
|
||||
|
||||
public:
|
||||
INLINE int get_num_buttons() const;
|
||||
|
||||
INLINE void set_button_map(int index, ButtonHandle button);
|
||||
INLINE ButtonHandle get_button_map(int index) const;
|
||||
|
||||
void set_button_state(int index, bool down);
|
||||
INLINE bool get_button_state(int index) const;
|
||||
INLINE bool is_button_known(int index) const;
|
||||
|
||||
INLINE ButtonEventDataAttribute *get_button_events() const;
|
||||
|
||||
virtual void output(ostream &out) const;
|
||||
virtual void write(ostream &out, int indent_level = 0) const;
|
||||
|
||||
void output_buttons(ostream &out) const;
|
||||
void write_buttons(ostream &out, int indent_level) const;
|
||||
|
||||
private:
|
||||
void ensure_button_index(int index);
|
||||
|
||||
protected:
|
||||
enum State {
|
||||
S_unknown,
|
||||
S_up,
|
||||
S_down
|
||||
};
|
||||
|
||||
class ButtonState {
|
||||
public:
|
||||
INLINE ButtonState();
|
||||
|
||||
ButtonHandle _handle;
|
||||
State _state;
|
||||
};
|
||||
|
||||
typedef vector<ButtonState> Buttons;
|
||||
Buttons _buttons;
|
||||
|
||||
PT(ButtonEventDataAttribute) _button_events;
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
}
|
||||
static void init_type() {
|
||||
ClientDevice::init_type();
|
||||
register_type(_type_handle, "ClientButtonDevice",
|
||||
ClientDevice::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 "clientButtonDevice.I"
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
// Filename: clientDevice.I
|
||||
// Created by: drose (25Jan01)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ClientDevice::get_client
|
||||
// Access: Public
|
||||
// Description: Returns the ClientBase this device is associated
|
||||
// with.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE ClientBase *ClientDevice::
|
||||
get_client() const {
|
||||
return _client;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ClientDevice::is_connected
|
||||
// Access: Public
|
||||
// Description: Returns true if the device is still connected to its
|
||||
// ClientBase, false otherwise.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool ClientDevice::
|
||||
is_connected() const {
|
||||
return _is_connected;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ClientDevice::get_device_type
|
||||
// Access: Public
|
||||
// Description: Returns the type of device this is considered to be
|
||||
// to the ClientBase: a ClientTrackerDevice,
|
||||
// ClientAnalogDevice, or what have you. This is not
|
||||
// exactly the same thing as get_type(), because it does
|
||||
// not return the exact type of the ClientDevice
|
||||
// (e.g. it reports ClientTrackerDevice, not
|
||||
// VrpnTrackerDevice).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE TypeHandle ClientDevice::
|
||||
get_device_type() const {
|
||||
return _device_type;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ClientDevice::get_device_name
|
||||
// Access: Public
|
||||
// Description: Returns the device name reported to the ClientBase.
|
||||
// This has some implementation-defined meaning to
|
||||
// identify particular devices.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE const string &ClientDevice::
|
||||
get_device_name() const {
|
||||
return _device_name;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ClientDevice::lock
|
||||
// Access: Public
|
||||
// Description: Grabs the mutex associated with this particular
|
||||
// device. The device will not update asynchronously
|
||||
// while the mutex is held, allowing the user to copy
|
||||
// the data out without fear of getting a partial update
|
||||
// during the copy.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void ClientDevice::
|
||||
lock() {
|
||||
#ifdef HAVE_IPC
|
||||
_lock.lock();
|
||||
#endif
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ClientDevice::unlock
|
||||
// Access: Public
|
||||
// Description: Releases the mutex associated with this particular
|
||||
// device. This should be called after all the data has
|
||||
// been successfully copied out. See lock().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void ClientDevice::
|
||||
unlock() {
|
||||
#ifdef HAVE_IPC
|
||||
_lock.unlock();
|
||||
#endif
|
||||
}
|
||||
|
|
@ -0,0 +1,104 @@
|
|||
// Filename: clientDevice.cxx
|
||||
// Created by: drose (25Jan01)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "clientDevice.h"
|
||||
#include "clientBase.h"
|
||||
|
||||
#include <indent.h>
|
||||
|
||||
TypeHandle ClientDevice::_type_handle;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ClientDevice::Constructor
|
||||
// Access: Protected
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
ClientDevice::
|
||||
ClientDevice(ClientBase *client, TypeHandle device_type,
|
||||
const string &device_name) :
|
||||
_client(client),
|
||||
_device_type(device_type),
|
||||
_device_name(device_name)
|
||||
{
|
||||
// We have to explicitly ref the client pointer, since we can't use
|
||||
// a PT(ClientBase) for circular include reasons.
|
||||
_client->ref();
|
||||
_is_connected = false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ClientDevice::Destructor
|
||||
// Access: Public, Virtual
|
||||
// Description: We don't actually call disconnect() at the
|
||||
// ClientDevice level destructor, because by the time
|
||||
// we get here we're already partly destructed.
|
||||
// Instead, we should call disconnect() from each
|
||||
// specific kind of derived class.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
ClientDevice::
|
||||
~ClientDevice() {
|
||||
nassertv(!_is_connected);
|
||||
|
||||
// And now we explicitly unref the client pointer.
|
||||
unref_delete(_client);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ClientDevice::disconnect
|
||||
// Access: Public
|
||||
// Description: Disconnects the ClientDevice from its ClientBase
|
||||
// object. The device will stop receiving
|
||||
// updates.
|
||||
//
|
||||
// Normally, you should not need to call this explicitly
|
||||
// (and it is probably a mistake to do so); it will
|
||||
// automatically be called when the ClientDevice object
|
||||
// destructs.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void ClientDevice::
|
||||
disconnect() {
|
||||
if (_is_connected) {
|
||||
bool disconnected =
|
||||
_client->disconnect_device(_device_type, _device_name, this);
|
||||
_is_connected = false;
|
||||
nassertv(disconnected);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ClientDevice::poll
|
||||
// Access: Public
|
||||
// Description: Causes the connected ClientBase to poll all of its
|
||||
// clients, if necessary. This will be a no-op if the
|
||||
// client is running in forked mode, or if it has
|
||||
// already polled everything this frame.
|
||||
//
|
||||
// This should generally be called before accessing the
|
||||
// data in this ClientDevice to ensure that it is fresh.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void ClientDevice::
|
||||
poll() {
|
||||
_client->poll();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ClientDevice::output
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void ClientDevice::
|
||||
output(ostream &out) const {
|
||||
out << get_type() << " " << get_device_name();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ClientDevice::write
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void ClientDevice::
|
||||
write(ostream &out, int indent_level) const {
|
||||
indent(out, indent_level) << *this << "\n";
|
||||
}
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
// Filename: clientDevice.h
|
||||
// Created by: drose (25Jan01)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef CLIENTDEVICE_H
|
||||
#define CLIENTDEVICE_H
|
||||
|
||||
#include <pandabase.h>
|
||||
|
||||
#include <typedReferenceCount.h>
|
||||
|
||||
#ifdef HAVE_IPC
|
||||
#include <ipc_mutex.h>
|
||||
#endif
|
||||
|
||||
class ClientBase;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : ClientDevice
|
||||
// Description : Any of a number of different devices that might be
|
||||
// attached to a ClientBase, including trackers, etc.
|
||||
// This is an abstract interface; the actual
|
||||
// implementations are in ClientTrackerDevice, etc.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDA ClientDevice : public TypedReferenceCount {
|
||||
protected:
|
||||
ClientDevice(ClientBase *client, TypeHandle device_type,
|
||||
const string &device_name);
|
||||
|
||||
public:
|
||||
virtual ~ClientDevice();
|
||||
|
||||
INLINE ClientBase *get_client() const;
|
||||
INLINE TypeHandle get_device_type() const;
|
||||
INLINE const string &get_device_name() const;
|
||||
|
||||
INLINE bool is_connected() const;
|
||||
void disconnect();
|
||||
|
||||
void poll();
|
||||
INLINE void lock();
|
||||
INLINE void unlock();
|
||||
|
||||
virtual void output(ostream &out) const;
|
||||
virtual void write(ostream &out, int indent_level = 0) const;
|
||||
|
||||
private:
|
||||
ClientBase *_client;
|
||||
TypeHandle _device_type;
|
||||
string _device_name;
|
||||
bool _is_connected;
|
||||
|
||||
#ifdef HAVE_IPC
|
||||
mutex _lock;
|
||||
#endif
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
}
|
||||
static void init_type() {
|
||||
TypedReferenceCount::init_type();
|
||||
register_type(_type_handle, "ClientDevice",
|
||||
TypedReferenceCount::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;
|
||||
|
||||
friend class ClientBase;
|
||||
};
|
||||
|
||||
INLINE ostream &operator <<(ostream &out, const ClientDevice &device) {
|
||||
device.output(out);
|
||||
return out;
|
||||
}
|
||||
|
||||
#include "clientDevice.I"
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
// Filename: clientTrackerDevice.I
|
||||
// Created by: drose (25Jan01)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ClientTrackerDevice::Constructor
|
||||
// Access: Protected
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE ClientTrackerDevice::
|
||||
ClientTrackerDevice(ClientBase *client, const string &device_name):
|
||||
ClientDevice(client, get_class_type(), device_name)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ClientTrackerDevice::get_data
|
||||
// Access: Public
|
||||
// Description: Returns the TrackerData that this device is
|
||||
// reporting.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE const TrackerData &ClientTrackerDevice::
|
||||
get_data() const {
|
||||
return _data;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
// Filename: clientTrackerDevice.cxx
|
||||
// Created by: drose (25Jan01)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "clientTrackerDevice.h"
|
||||
|
||||
TypeHandle ClientTrackerDevice::_type_handle;
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
// Filename: clientTrackerDevice.h
|
||||
// Created by: drose (25Jan01)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef CLIENTTRACKERDEVICE_H
|
||||
#define CLIENTTRACKERDEVICE_H
|
||||
|
||||
#include <pandabase.h>
|
||||
|
||||
#include "clientDevice.h"
|
||||
#include "trackerData.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : ClientTrackerDevice
|
||||
// Description : A device, attached to the ClientBase by a
|
||||
// TrackerNode, that records the data from a single
|
||||
// tracker device.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDA ClientTrackerDevice : public ClientDevice {
|
||||
protected:
|
||||
INLINE ClientTrackerDevice(ClientBase *client, const string &device_name);
|
||||
|
||||
public:
|
||||
INLINE const TrackerData &get_data() const;
|
||||
|
||||
protected:
|
||||
TrackerData _data;
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
}
|
||||
static void init_type() {
|
||||
ClientDevice::init_type();
|
||||
register_type(_type_handle, "ClientTrackerDevice",
|
||||
ClientDevice::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 "clientTrackerDevice.I"
|
||||
|
||||
#endif
|
||||
|
|
@ -4,10 +4,15 @@
|
|||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "config_device.h"
|
||||
#include "mouse.h"
|
||||
#include "analogNode.h"
|
||||
#include "buttonNode.h"
|
||||
#include "clientAnalogDevice.h"
|
||||
#include "clientBase.h"
|
||||
#include "clientButtonDevice.h"
|
||||
#include "clientDevice.h"
|
||||
#include "clientTrackerDevice.h"
|
||||
#include "mouse.h"
|
||||
#include "trackerNode.h"
|
||||
#include "adinputNode.h"
|
||||
|
||||
#include <dconfig.h>
|
||||
|
||||
|
|
@ -36,8 +41,13 @@ init_libdevice() {
|
|||
}
|
||||
initialized = true;
|
||||
|
||||
AnalogNode::init_type();
|
||||
ButtonNode::init_type();
|
||||
ClientAnalogDevice::init_type();
|
||||
ClientBase::init_type();
|
||||
ClientButtonDevice::init_type();
|
||||
ClientDevice::init_type();
|
||||
ClientTrackerDevice::init_type();
|
||||
MouseAndKeyboard::init_type();
|
||||
TrackerNode::init_type();
|
||||
ADInputNode::init_type();
|
||||
ClientBase::init_type();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
////////////////////////////////////////////////////////////////////
|
||||
INLINE TrackerData::
|
||||
TrackerData() :
|
||||
ptime(0), vtime(0), vquat_dt(0), atime(0), aquat_dt(0)
|
||||
_flags(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -25,35 +25,176 @@ TrackerData(const TrackerData ©) {
|
|||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TrackerData::Copy Assignment Operator
|
||||
// Function: TrackerData::clear
|
||||
// Access: Public
|
||||
// Description:
|
||||
// Description: Removes all data from the structure.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE TrackerData &TrackerData::
|
||||
operator = (const TrackerData ©) {
|
||||
ptime = copy.ptime;
|
||||
position = copy.position;
|
||||
pquat = copy.pquat;
|
||||
|
||||
vtime = copy.vtime;
|
||||
velocity = copy.velocity;
|
||||
vquat = copy.vquat;
|
||||
vquat_dt = copy.vquat_dt;
|
||||
|
||||
atime = copy.atime;
|
||||
acceleration = copy.acceleration;
|
||||
aquat = copy.aquat;
|
||||
aquat_dt = copy.aquat_dt;
|
||||
|
||||
return *this;
|
||||
INLINE void TrackerData::
|
||||
clear() {
|
||||
_flags = 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TrackerData::none
|
||||
// Access: Public, Static
|
||||
// Description: Returns an empty TrackerData object
|
||||
// Function: TrackerData::set_time
|
||||
// Access: Public
|
||||
// Description: Indicates the time at which the position information
|
||||
// (pos and orient) are effective. This is a time
|
||||
// elapsed in seconds since some undefined epoch; it may
|
||||
// or may not correspond to the clock time indicated in
|
||||
// the global ClockObject.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE const TrackerData &TrackerData::
|
||||
none() {
|
||||
return _none;
|
||||
INLINE void TrackerData::
|
||||
set_time(double time) {
|
||||
_time = time;
|
||||
_flags |= F_has_time;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TrackerData::has_time
|
||||
// Access: Public
|
||||
// Description: Returns true if the position information time is
|
||||
// available. See set_time().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool TrackerData::
|
||||
has_time() const {
|
||||
return (_flags & F_has_time) != 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TrackerData::get_time
|
||||
// Access: Public
|
||||
// Description: Returns the time at which the position information
|
||||
// (pos and orient) are effective. It is an error to
|
||||
// call this if has_time() does not return true. See
|
||||
// set_time().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE double TrackerData::
|
||||
get_time() const {
|
||||
nassertr(has_time(), 0.0);
|
||||
return _time;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TrackerData::set_pos
|
||||
// Access: Public
|
||||
// Description: Indicates the current position of the tracker sensor
|
||||
// in space. The coordinate system of this position is
|
||||
// defined by the tracker.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void TrackerData::
|
||||
set_pos(const LPoint3f &pos) {
|
||||
_pos = pos;
|
||||
_flags |= F_has_pos;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TrackerData::has_pos
|
||||
// Access: Public
|
||||
// Description: Returns true if the current position is available.
|
||||
// See set_pos().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool TrackerData::
|
||||
has_pos() const {
|
||||
return (_flags & F_has_pos) != 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TrackerData::get_pos
|
||||
// Access: Public
|
||||
// Description: Returns the current position of the tracker. It is
|
||||
// legal to call this if has_pos() returns false; in
|
||||
// this case, the position will always be (0, 0, 0).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE const LPoint3f &TrackerData::
|
||||
get_pos() const {
|
||||
if (has_pos()) {
|
||||
return _pos;
|
||||
} else {
|
||||
static LPoint3f zero(0.0, 0.0, 0.0);
|
||||
return zero;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TrackerData::set_orient
|
||||
// Access: Public
|
||||
// Description: Indicates the current orientation of the tracker
|
||||
// sensor in space. The coordinate system of this
|
||||
// orientation is defined by the tracker, but should be
|
||||
// the same coordinate system as that reflected by
|
||||
// set_pos().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void TrackerData::
|
||||
set_orient(const LOrientationf &orient) {
|
||||
_orient = orient;
|
||||
_flags |= F_has_orient;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TrackerData::has_orient
|
||||
// Access: Public
|
||||
// Description: Returns true if the current orientation is available.
|
||||
// See set_orient().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool TrackerData::
|
||||
has_orient() const {
|
||||
return (_flags & F_has_orient) != 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TrackerData::get_orient
|
||||
// Access: Public
|
||||
// Description: Returns the current orientation of the tracker. It
|
||||
// is legal to call this if has_orient() returns false;
|
||||
// in this case, the result is always the identity
|
||||
// orientation.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE const LOrientationf &TrackerData::
|
||||
get_orient() const {
|
||||
if (has_orient()) {
|
||||
return _orient;
|
||||
} else {
|
||||
static LOrientationf ident = LOrientationf::ident_quat();
|
||||
return ident;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TrackerData::set_dt
|
||||
// Access: Public
|
||||
// Description: Indicates the amount of elapsed time over which which
|
||||
// the information (pos and orient) were computed. This
|
||||
// only makes sense if the information represents
|
||||
// velocity or acceleration, rather than position. This
|
||||
// is an elapsed time in seconds.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void TrackerData::
|
||||
set_dt(double dt) {
|
||||
_dt = dt;
|
||||
_flags |= F_has_dt;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TrackerData::has_dt
|
||||
// Access: Public
|
||||
// Description: Returns true if the computed elapsed time is
|
||||
// available. See set_dt().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool TrackerData::
|
||||
has_dt() const {
|
||||
return (_flags & F_has_dt) != 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TrackerData::get_dt
|
||||
// Access: Public
|
||||
// Description: Returns the amount of elapsed time over which the
|
||||
// information (pos and orient) were computed. It
|
||||
// is an error to call this if has_dt() does not return
|
||||
// true. See set_dt().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE double TrackerData::
|
||||
get_dt() const {
|
||||
nassertr(has_dt(), 0.0);
|
||||
return _dt;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,5 +5,17 @@
|
|||
|
||||
#include "trackerData.h"
|
||||
|
||||
// This is initialized to zero by static initialization.
|
||||
TrackerData TrackerData::_none;
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TrackerData::Copy Assignment Operator
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void TrackerData::
|
||||
operator = (const TrackerData ©) {
|
||||
_flags = copy._flags;
|
||||
|
||||
_time = copy._time;
|
||||
_pos = copy._pos;
|
||||
_orient = copy._orient;
|
||||
_dt = copy._dt;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,36 +3,54 @@
|
|||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef TRACKER_DATA
|
||||
#define TRACKER_DATA
|
||||
#ifndef TRACKERDATA_H
|
||||
#define TRACKERDATA_H
|
||||
|
||||
#include <pandabase.h>
|
||||
#include <luse.h>
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : TrackerData
|
||||
// Description : Stores the kinds of data that a tracker might output.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDA TrackerData {
|
||||
public:
|
||||
INLINE TrackerData();
|
||||
INLINE TrackerData(const TrackerData ©);
|
||||
INLINE TrackerData &operator = (const TrackerData ©);
|
||||
void operator = (const TrackerData ©);
|
||||
|
||||
INLINE static const TrackerData &none();
|
||||
INLINE void clear();
|
||||
|
||||
double ptime;
|
||||
LPoint3f position;
|
||||
LVector4f pquat;
|
||||
|
||||
double vtime;
|
||||
LVector3f velocity;
|
||||
LVector4f vquat;
|
||||
float vquat_dt;
|
||||
INLINE void set_time(double time);
|
||||
INLINE bool has_time() const;
|
||||
INLINE double get_time() const;
|
||||
|
||||
double atime;
|
||||
LVector3f acceleration;
|
||||
LVector4f aquat;
|
||||
float aquat_dt;
|
||||
INLINE void set_pos(const LPoint3f &pos);
|
||||
INLINE bool has_pos() const;
|
||||
INLINE const LPoint3f &get_pos() const;
|
||||
|
||||
INLINE void set_orient(const LOrientationf &orient);
|
||||
INLINE bool has_orient() const;
|
||||
INLINE const LOrientationf &get_orient() const;
|
||||
|
||||
INLINE void set_dt(double dt);
|
||||
INLINE bool has_dt() const;
|
||||
INLINE double get_dt() const;
|
||||
|
||||
private:
|
||||
static TrackerData _none;
|
||||
enum Flags {
|
||||
F_has_time = 0x0001,
|
||||
F_has_pos = 0x0002,
|
||||
F_has_orient = 0x0004,
|
||||
F_has_dt = 0x0008,
|
||||
};
|
||||
|
||||
int _flags;
|
||||
|
||||
double _time;
|
||||
LPoint3f _pos;
|
||||
LOrientationf _orient;
|
||||
double _dt;
|
||||
};
|
||||
|
||||
#include "trackerData.I"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,51 @@
|
|||
// Filename: trackerNode.I
|
||||
// Created by: drose (25Jan01)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TrackerNode::is_valid
|
||||
// Access: Public
|
||||
// Description: Returns true if the TrackerNode is valid and
|
||||
// connected to a server, false otherwise.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool TrackerNode::
|
||||
is_valid() const {
|
||||
return (_tracker != (ClientTrackerDevice *)NULL) && _tracker->is_connected();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TrackerNode::get_pos
|
||||
// Access: Public
|
||||
// Description: Returns the current position of the tracker, if it is
|
||||
// available.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
const LPoint3f &TrackerNode::
|
||||
get_pos() const {
|
||||
return _data.get_pos();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TrackerNode::get_orient
|
||||
// Access: Public
|
||||
// Description: Returns the current orientation of the tracker, if it
|
||||
// is available.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
const LOrientationf &TrackerNode::
|
||||
get_orient() const {
|
||||
return _data.get_orient();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TrackerNode::get_transform
|
||||
// Access: Public
|
||||
// Description: Returns the current position and orientation of the
|
||||
// tracker, as a combined matrix.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
const LMatrix4f &TrackerNode::
|
||||
get_transform() const {
|
||||
return _transform;
|
||||
}
|
||||
|
||||
|
|
@ -11,19 +11,7 @@
|
|||
////////////////////////////////////////////////////////////////////
|
||||
TypeHandle TrackerNode::_type_handle;
|
||||
|
||||
TypeHandle TrackerNode::_ptime_type;
|
||||
TypeHandle TrackerNode::_position_type;
|
||||
TypeHandle TrackerNode::_pquat_type;
|
||||
|
||||
TypeHandle TrackerNode::_vtime_type;
|
||||
TypeHandle TrackerNode::_velocity_type;
|
||||
TypeHandle TrackerNode::_vquat_type;
|
||||
TypeHandle TrackerNode::_vquat_dt_type;
|
||||
|
||||
TypeHandle TrackerNode::_atime_type;
|
||||
TypeHandle TrackerNode::_acceleration_type;
|
||||
TypeHandle TrackerNode::_aquat_type;
|
||||
TypeHandle TrackerNode::_aquat_dt_type;
|
||||
TypeHandle TrackerNode::_transform_type;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TrackerNode::Constructor
|
||||
|
|
@ -31,39 +19,44 @@ TypeHandle TrackerNode::_aquat_dt_type;
|
|||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
TrackerNode::
|
||||
TrackerNode(PT(ClientBase) client, const string &tracker,
|
||||
int sensor) :
|
||||
DataNode(tracker), _client(client), _tracker(tracker), _sensor(sensor)
|
||||
TrackerNode(ClientBase *client, const string &device_name) :
|
||||
DataNode(device_name)
|
||||
{
|
||||
_client->add_remote_tracker(_tracker, _sensor);
|
||||
|
||||
_ptime = new DoubleDataAttribute();
|
||||
_position = new Vec3DataAttribute(LPoint3f(0,0,0));
|
||||
_pquat = new Vec4DataAttribute(LVector4f(0,0,0,0));
|
||||
nassertv(client != (ClientBase *)NULL);
|
||||
PT(ClientDevice) device =
|
||||
client->get_device(ClientTrackerDevice::get_class_type(), device_name);
|
||||
|
||||
_vtime = new DoubleDataAttribute();
|
||||
_velocity = new Vec3DataAttribute(LPoint3f(0,0,0));
|
||||
_vquat = new Vec4DataAttribute(LVector4f(0,0,0,0));
|
||||
_vquat_dt = new DoubleDataAttribute();
|
||||
if (device == (ClientDevice *)NULL) {
|
||||
device_cat.warning()
|
||||
<< "Unable to open tracker device " << device_name << "\n";
|
||||
return;
|
||||
}
|
||||
|
||||
_atime = new DoubleDataAttribute();
|
||||
_acceleration = new Vec3DataAttribute(LPoint3f(0,0,0));
|
||||
_aquat = new Vec4DataAttribute(LVector4f(0,0,0,0));
|
||||
_aquat_dt = new DoubleDataAttribute();
|
||||
if (!device->is_of_type(ClientTrackerDevice::get_class_type())) {
|
||||
device_cat.error()
|
||||
<< "Inappropriate device type " << device->get_type()
|
||||
<< " created; expected a ClientTrackerDevice.\n";
|
||||
return;
|
||||
}
|
||||
|
||||
_tracker_attrib.set_attribute(_ptime_type, _ptime);
|
||||
_tracker_attrib.set_attribute(_position_type, _position);
|
||||
_tracker_attrib.set_attribute(_pquat_type, _pquat);
|
||||
_tracker = DCAST(ClientTrackerDevice, device);
|
||||
|
||||
_tracker_attrib.set_attribute(_vtime_type, _vtime);
|
||||
_tracker_attrib.set_attribute(_velocity_type, _velocity);
|
||||
_tracker_attrib.set_attribute(_vquat_type, _vquat);
|
||||
_tracker_attrib.set_attribute(_vquat_dt_type, _vquat_dt);
|
||||
if (_tracker != (ClientTrackerDevice *)NULL) {
|
||||
_transform_attrib = new MatrixDataAttribute;
|
||||
_attrib.set_attribute(_transform_type, _transform_attrib);
|
||||
}
|
||||
}
|
||||
|
||||
_tracker_attrib.set_attribute(_atime_type, _atime);
|
||||
_tracker_attrib.set_attribute(_acceleration_type, _acceleration);
|
||||
_tracker_attrib.set_attribute(_aquat_type, _aquat);
|
||||
_tracker_attrib.set_attribute(_aquat_dt_type, _aquat_dt);
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TrackerNode::Destructor
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
TrackerNode::
|
||||
~TrackerNode() {
|
||||
// When the _tracker pointer destructs, the ClientTrackerDevice
|
||||
// disconnects itself from the ClientBase, and everything that needs
|
||||
// to get turned off does. Magic.
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -73,32 +66,24 @@ TrackerNode(PT(ClientBase) client, const string &tracker,
|
|||
////////////////////////////////////////////////////////////////////
|
||||
void TrackerNode::
|
||||
transmit_data(NodeAttributes &data) {
|
||||
TrackerData new_data = _client->get_tracker_data(_tracker, _sensor);
|
||||
if (is_valid()) {
|
||||
_tracker->poll();
|
||||
_tracker->lock();
|
||||
_data = _tracker->get_data();
|
||||
_tracker->unlock();
|
||||
|
||||
if (device_cat.is_debug()) {
|
||||
device_cat.debug() << "TrackerNode:transmit_data" << endl;
|
||||
_data.get_orient().extract_to_matrix(_transform);
|
||||
_transform.set_row(3, _data.get_pos());
|
||||
|
||||
_transform_attrib->set_value(_transform);
|
||||
|
||||
if (device_cat.is_debug()) {
|
||||
device_cat.debug() << "TrackerNode:attributes" << endl;
|
||||
_attrib.write(device_cat.debug(false), 3);
|
||||
}
|
||||
}
|
||||
|
||||
_ptime->set_value(new_data.ptime);
|
||||
_position->set_value(new_data.position);
|
||||
_pquat->set_value(new_data.pquat);
|
||||
|
||||
_vtime->set_value(new_data.vtime);
|
||||
_velocity->set_value(new_data.velocity);
|
||||
_vquat->set_value(new_data.vquat);
|
||||
_vquat_dt->set_value(new_data.vquat_dt);
|
||||
|
||||
_atime->set_value(new_data.atime);
|
||||
_acceleration->set_value(new_data.acceleration);
|
||||
_aquat->set_value(new_data.aquat);
|
||||
_aquat_dt->set_value(new_data.aquat_dt);
|
||||
|
||||
if (device_cat.is_debug()) {
|
||||
device_cat.debug() << "TrackerNode:attributes" << endl;
|
||||
_tracker_attrib.write(device_cat.debug(false), 3);
|
||||
}
|
||||
|
||||
data = _tracker_attrib;
|
||||
data = _attrib;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -112,45 +97,8 @@ init_type() {
|
|||
register_type(_type_handle, "TrackerNode",
|
||||
DataNode::get_class_type());
|
||||
|
||||
DoubleDataTransition::init_type();
|
||||
Vec3DataTransition::init_type();
|
||||
Vec4DataTransition::init_type();
|
||||
|
||||
register_data_transition(_ptime_type, "Position Time",
|
||||
DoubleDataTransition::get_class_type());
|
||||
register_data_transition(_position_type, "Position",
|
||||
Vec3DataTransition::get_class_type());
|
||||
register_data_transition(_pquat_type, "Position Quat",
|
||||
Vec4DataTransition::get_class_type());
|
||||
|
||||
register_data_transition(_vtime_type, "Velocity Time",
|
||||
DoubleDataTransition::get_class_type());
|
||||
register_data_transition(_velocity_type, "Velocity",
|
||||
Vec3DataTransition::get_class_type());
|
||||
register_data_transition(_vquat_type, "Velocity Quat",
|
||||
Vec4DataTransition::get_class_type());
|
||||
register_data_transition(_vquat_dt_type, "Velocity Quat dt",
|
||||
DoubleDataTransition::get_class_type());
|
||||
|
||||
register_data_transition(_atime_type, "Acceleration Time",
|
||||
DoubleDataTransition::get_class_type());
|
||||
register_data_transition(_acceleration_type, "Acceleration",
|
||||
Vec3DataTransition::get_class_type());
|
||||
register_data_transition(_aquat_type, "Acceleration Quat",
|
||||
Vec4DataTransition::get_class_type());
|
||||
register_data_transition(_aquat_dt_type, "Acceleration Quat dt",
|
||||
DoubleDataTransition::get_class_type());
|
||||
MatrixDataTransition::init_type();
|
||||
register_data_transition(_transform_type, "Transform",
|
||||
MatrixDataTransition::get_class_type());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -3,73 +3,59 @@
|
|||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _TRACKER_NODE
|
||||
#define _TRACKER_NODE
|
||||
#ifndef TRACKERNODE_H
|
||||
#define TRACKERNODE_H
|
||||
|
||||
#include <pandabase.h>
|
||||
|
||||
#include <dataNode.h>
|
||||
#include <nodeAttributes.h>
|
||||
#include <doubleDataAttribute.h>
|
||||
#include <doubleDataTransition.h>
|
||||
#include <vec3DataAttribute.h>
|
||||
#include <vec3DataTransition.h>
|
||||
#include <vec3DataAttribute.h>
|
||||
#include <vec4DataTransition.h>
|
||||
#include <vec4DataAttribute.h>
|
||||
|
||||
#include <pointerTo.h>
|
||||
#include "clientBase.h"
|
||||
#include "trackerData.h"
|
||||
#include "clientTrackerDevice.h"
|
||||
|
||||
#include <dataNode.h>
|
||||
#include <matrixDataTransition.h>
|
||||
#include <matrixDataAttribute.h>
|
||||
#include <nodeAttributes.h>
|
||||
#include <luse.h>
|
||||
#include <lmatrix.h>
|
||||
#include <pointerTo.h>
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : TrackerNode
|
||||
// Description : Reads the position, velocity and acceleration
|
||||
// information from one sensor on a tracker and sends it
|
||||
// down the DataGraph
|
||||
// Description : Reads the data associated with a single tracker
|
||||
// sensor accessed on some ClientBase, and makes the
|
||||
// data available to user code. Also places the current
|
||||
// tracker's transform on the data graph.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDA TrackerNode : public DataNode {
|
||||
PUBLISHED:
|
||||
TrackerNode(PT(ClientBase) client, const string &tracker,
|
||||
int sensor);
|
||||
TrackerNode(ClientBase *client, const string &device_name);
|
||||
virtual ~TrackerNode();
|
||||
|
||||
INLINE bool is_valid() const;
|
||||
|
||||
INLINE const LPoint3f &get_pos() const;
|
||||
INLINE const LOrientationf &get_orient() const;
|
||||
INLINE const LMatrix4f &get_transform() const;
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// From parent class DataNode
|
||||
////////////////////////////////////////////////////////////////////
|
||||
public:
|
||||
virtual void transmit_data(NodeAttributes &data);
|
||||
virtual void
|
||||
transmit_data(NodeAttributes &data);
|
||||
|
||||
public:
|
||||
NodeAttributes _tracker_attrib;
|
||||
NodeAttributes _attrib;
|
||||
PT(MatrixDataAttribute) _transform_attrib;
|
||||
|
||||
PT(DoubleDataAttribute) _ptime;
|
||||
PT(Vec3DataAttribute) _position;
|
||||
PT(Vec4DataAttribute) _pquat;
|
||||
|
||||
PT(DoubleDataAttribute) _vtime;
|
||||
PT(Vec3DataAttribute) _velocity;
|
||||
PT(Vec4DataAttribute) _vquat;
|
||||
PT(DoubleDataAttribute) _vquat_dt;
|
||||
// outputs
|
||||
static TypeHandle _transform_type;
|
||||
|
||||
PT(DoubleDataAttribute) _atime;
|
||||
PT(Vec3DataAttribute) _acceleration;
|
||||
PT(Vec4DataAttribute) _aquat;
|
||||
PT(DoubleDataAttribute) _aquat_dt;
|
||||
|
||||
static TypeHandle _ptime_type;
|
||||
static TypeHandle _position_type;
|
||||
static TypeHandle _pquat_type;
|
||||
|
||||
static TypeHandle _vtime_type;
|
||||
static TypeHandle _velocity_type;
|
||||
static TypeHandle _vquat_type;
|
||||
static TypeHandle _vquat_dt_type;
|
||||
|
||||
static TypeHandle _atime_type;
|
||||
static TypeHandle _acceleration_type;
|
||||
static TypeHandle _aquat_type;
|
||||
static TypeHandle _aquat_dt_type;
|
||||
|
||||
protected:
|
||||
PT(ClientBase) _client;
|
||||
string _tracker;
|
||||
int _sensor;
|
||||
private:
|
||||
PT(ClientTrackerDevice) _tracker;
|
||||
TrackerData _data;
|
||||
LMatrix4f _transform;
|
||||
|
||||
public:
|
||||
virtual TypeHandle get_type() const {
|
||||
|
|
@ -85,4 +71,6 @@ private:
|
|||
static TypeHandle _type_handle;
|
||||
};
|
||||
|
||||
#include "trackerNode.I"
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ public:
|
|||
virtual void xform(const LMatrix4f &mat);
|
||||
|
||||
PUBLISHED:
|
||||
void write(ostream &out, int indent_level = 0) const;
|
||||
virtual void write(ostream &out, int indent_level = 0) const;
|
||||
void write_verbose(ostream &out, int indent_level) const;
|
||||
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -76,8 +76,8 @@ PUBLISHED:
|
|||
INLINE NodeRelation *get_geometry() const;
|
||||
INLINE void clear_geometry();
|
||||
|
||||
void output(ostream &out) const;
|
||||
void write(ostream &out, int indent_level = 0) const;
|
||||
virtual void output(ostream &out) const;
|
||||
virtual void write(ostream &out, int indent_level = 0) const;
|
||||
|
||||
private:
|
||||
void set_current_region(MouseWatcherRegion *region);
|
||||
|
|
|
|||
|
|
@ -11,10 +11,18 @@
|
|||
|
||||
#define SOURCES \
|
||||
config_vrpn.cxx config_vrpn.h vrpnClient.I vrpnClient.cxx \
|
||||
vrpnClient.h
|
||||
vrpnAnalog.I vrpnAnalog.cxx vrpnAnalog.h \
|
||||
vrpnAnalogDevice.I vrpnAnalogDevice.cxx vrpnAnalogDevice.h \
|
||||
vrpnButton.I vrpnButton.cxx vrpnButton.h \
|
||||
vrpnButtonDevice.I vrpnButtonDevice.cxx vrpnButtonDevice.h \
|
||||
vrpnClient.h \
|
||||
vrpnTracker.I vrpnTracker.cxx vrpnTracker.h \
|
||||
vrpnTrackerDevice.I vrpnTrackerDevice.cxx vrpnTrackerDevice.h \
|
||||
vrpn_interface.h
|
||||
|
||||
#define INSTALL_HEADERS \
|
||||
config_vrpn.h vrpnClient.I vrpnClient.h
|
||||
config_vrpn.h \
|
||||
vrpnClient.I vrpnClient.h
|
||||
|
||||
#define IGATESCAN all
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,10 @@
|
|||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "config_vrpn.h"
|
||||
#include "vrpnAnalogDevice.h"
|
||||
#include "vrpnButtonDevice.h"
|
||||
#include "vrpnClient.h"
|
||||
#include "vrpnTrackerDevice.h"
|
||||
|
||||
#include <dconfig.h>
|
||||
|
||||
|
|
@ -13,5 +16,8 @@ NotifyCategoryDef(vrpn, "");
|
|||
|
||||
|
||||
ConfigureFn(config_vrpn) {
|
||||
VrpnAnalogDevice::init_type();
|
||||
VrpnButtonDevice::init_type();
|
||||
VrpnClient::init_type();
|
||||
VrpnTrackerDevice::init_type();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,38 @@
|
|||
// Filename: vrpnAnalog.I
|
||||
// Created by: drose (26Jan01)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: VrpnAnalog::get_analog_name
|
||||
// Access: Public
|
||||
// Description: Returns the name of the analog device that was used
|
||||
// to create this VrpnAnalog.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE const string &VrpnAnalog::
|
||||
get_analog_name() const {
|
||||
return _analog_name;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: VrpnAnalog::is_empty
|
||||
// Access: Public
|
||||
// Description: Returns true if no VrpnAnalogDevices reference this
|
||||
// VrpnAnalog, or false otherwise.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool VrpnAnalog::
|
||||
is_empty() const {
|
||||
return _devices.empty();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: VrpnAnalog::poll
|
||||
// Access: Public
|
||||
// Description: Polls the connected device. Normally you should not
|
||||
// call this directly; this will be called by the
|
||||
// VrpnClient.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void VrpnAnalog::
|
||||
poll() {
|
||||
_analog->mainloop();
|
||||
}
|
||||
|
|
@ -0,0 +1,121 @@
|
|||
// Filename: vrpnAnalog.cxx
|
||||
// Created by: drose (26Jan01)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "vrpnAnalog.h"
|
||||
#include "vrpnAnalogDevice.h"
|
||||
#include "vrpnClient.h"
|
||||
#include "config_vrpn.h"
|
||||
|
||||
#include <indent.h>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: VrpnAnalog::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
VrpnAnalog::
|
||||
VrpnAnalog(const string &analog_name, vrpn_Connection *connection) :
|
||||
_analog_name(analog_name)
|
||||
{
|
||||
_analog = new vrpn_Analog_Remote(_analog_name.c_str(), connection);
|
||||
|
||||
_analog->register_change_handler((void*)this, &vrpn_analog_callback);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: VrpnAnalog::Destructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
VrpnAnalog::
|
||||
~VrpnAnalog() {
|
||||
delete _analog;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: VrpnAnalog::mark
|
||||
// Access: Public
|
||||
// Description: Adds the indicated VrpnAnalogDevice to the list of
|
||||
// devices that are sharing this VrpnAnalog.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void VrpnAnalog::
|
||||
mark(VrpnAnalogDevice *device) {
|
||||
if (vrpn_cat.is_debug()) {
|
||||
vrpn_cat.debug() << *this << " marking " << *device << "\n";
|
||||
}
|
||||
_devices.push_back(device);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: VrpnAnalog::unmark
|
||||
// Access: Public
|
||||
// Description: Removes the indicated VrpnAnalogDevice from the list
|
||||
// of devices that are sharing this VrpnAnalog.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void VrpnAnalog::
|
||||
unmark(VrpnAnalogDevice *device) {
|
||||
if (vrpn_cat.is_debug()) {
|
||||
vrpn_cat.debug() << *this << " unmarking " << *device << "\n";
|
||||
}
|
||||
|
||||
Devices::iterator di =
|
||||
find(_devices.begin(), _devices.end(), device);
|
||||
|
||||
if (di != _devices.end()) {
|
||||
_devices.erase(di);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: VrpnAnalog::output
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void VrpnAnalog::
|
||||
output(ostream &out) const {
|
||||
out << _analog_name;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: VrpnAnalog::write
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void VrpnAnalog::
|
||||
write(ostream &out, int indent_level) const {
|
||||
indent(out, indent_level)
|
||||
<< get_analog_name() << " ("
|
||||
<< _devices.size() << " devices)\n";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: VrpnAnalog::vrpn_analog_callback
|
||||
// Access: Private, Static
|
||||
// Description: Receives the analog event data from the VRPN
|
||||
// code and sends it to any interested
|
||||
// VrpnAnalogDevices.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void VrpnAnalog::
|
||||
vrpn_analog_callback(void *userdata, const vrpn_ANALOGCB info) {
|
||||
VrpnAnalog *self = (VrpnAnalog *)userdata;
|
||||
|
||||
Devices::iterator di;
|
||||
for (di = self->_devices.begin(); di != self->_devices.end(); ++di) {
|
||||
VrpnAnalogDevice *device = (*di);
|
||||
device->lock();
|
||||
for (int i = 0; i < info.num_channel; i++) {
|
||||
if (vrpn_cat.is_debug()) {
|
||||
if (device->get_control_state(i) != info.channel[i]) {
|
||||
vrpn_cat.debug()
|
||||
<< *self << " got analog " << i << " = " << info.channel[i] << "\n";
|
||||
}
|
||||
}
|
||||
device->set_control_state(i, info.channel[i]);
|
||||
}
|
||||
device->unlock();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
// Filename: vrpnAnalog.h
|
||||
// Created by: drose (26Jan01)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef VRPNANALOG_H
|
||||
#define VRPNANALOG_H
|
||||
|
||||
#include <pandabase.h>
|
||||
|
||||
#include "vrpn_interface.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
class VrpnAnalogDevice;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : VrpnAnalog
|
||||
// Description : This is the actual interface to a particular VRPN
|
||||
// analog device, and all of its numbered controls. A
|
||||
// pointer to this object is stored in the VrpnClient
|
||||
// class for each differently-named VRPN analog device
|
||||
// we connect to.
|
||||
//
|
||||
// The VRPN callbacks go here, which in turn get
|
||||
// vectored out to any VrpnAnalogDevice objects that
|
||||
// register with this. When the last VrpnAnalogDevice
|
||||
// object unregisters, the VrpnAnalog will be deleted
|
||||
// by the VrpnClient.
|
||||
//
|
||||
// This class does not need to be exported from the DLL.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class VrpnAnalog {
|
||||
public:
|
||||
VrpnAnalog(const string &analog_name, vrpn_Connection *connection);
|
||||
~VrpnAnalog();
|
||||
|
||||
INLINE const string &get_analog_name() const;
|
||||
INLINE bool is_empty() const;
|
||||
|
||||
void mark(VrpnAnalogDevice *device);
|
||||
void unmark(VrpnAnalogDevice *device);
|
||||
|
||||
INLINE void poll();
|
||||
|
||||
void output(ostream &out) const;
|
||||
void write(ostream &out, int indent_level = 0) const;
|
||||
|
||||
private:
|
||||
static void
|
||||
vrpn_analog_callback(void *userdata, const vrpn_ANALOGCB info);
|
||||
|
||||
private:
|
||||
string _analog_name;
|
||||
vrpn_Analog_Remote *_analog;
|
||||
|
||||
typedef vector<VrpnAnalogDevice *> Devices;
|
||||
Devices _devices;
|
||||
};
|
||||
|
||||
INLINE ostream &operator << (ostream &out, const VrpnAnalog &analog) {
|
||||
analog.output(out);
|
||||
return out;
|
||||
}
|
||||
|
||||
#include "vrpnAnalog.I"
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
// Filename: vrpnAnalogDevice.I
|
||||
// Created by: drose (26Jan01)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: VrpnAnalogDevice::get_vrpn_analog
|
||||
// Access: Public
|
||||
// Description: Returns a pointer to the particular VrpnAnalog this
|
||||
// device gets its data from. This pointer may be
|
||||
// shared with other VrpnAnalogDevice objects.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE VrpnAnalog *VrpnAnalogDevice::
|
||||
get_vrpn_analog() const {
|
||||
return _vrpn_analog;
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
// Filename: vrpnAnalogDevice.cxx
|
||||
// Created by: drose (26Jan01)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "vrpnAnalogDevice.h"
|
||||
#include "vrpnClient.h"
|
||||
|
||||
TypeHandle VrpnAnalogDevice::_type_handle;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: VrpnAnalogDevice::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
VrpnAnalogDevice::
|
||||
VrpnAnalogDevice(VrpnClient *client, const string &device_name,
|
||||
VrpnAnalog *vrpn_analog) :
|
||||
ClientAnalogDevice(client, device_name),
|
||||
_vrpn_analog(vrpn_analog)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: VrpnAnalogDevice::Destructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
VrpnAnalogDevice::
|
||||
~VrpnAnalogDevice() {
|
||||
disconnect();
|
||||
}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
// Filename: vrpnAnalogDevice.h
|
||||
// Created by: drose (26Jan01)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef VRPNANALOGDEVICE_H
|
||||
#define VRPNANALOGDEVICE_H
|
||||
|
||||
#include <pandabase.h>
|
||||
|
||||
#include <clientAnalogDevice.h>
|
||||
|
||||
class VrpnClient;
|
||||
class VrpnAnalog;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : VrpnAnalogDevice
|
||||
// Description : The Panda interface to a VRPN analog device. This
|
||||
// object will be returned by VrpnClient::make_device(),
|
||||
// for attaching to a AnalogNode.
|
||||
//
|
||||
// This class does not need to be exported from the DLL.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class VrpnAnalogDevice : public ClientAnalogDevice {
|
||||
public:
|
||||
VrpnAnalogDevice(VrpnClient *client, const string &device_name,
|
||||
VrpnAnalog *vrpn_analog);
|
||||
virtual ~VrpnAnalogDevice();
|
||||
|
||||
INLINE VrpnAnalog *get_vrpn_analog() const;
|
||||
|
||||
private:
|
||||
VrpnAnalog *_vrpn_analog;
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
}
|
||||
static void init_type() {
|
||||
ClientAnalogDevice::init_type();
|
||||
register_type(_type_handle, "VrpnAnalogDevice",
|
||||
ClientAnalogDevice::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;
|
||||
|
||||
friend class VrpnAnalog;
|
||||
};
|
||||
|
||||
#include "vrpnAnalogDevice.I"
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
// Filename: vrpnButton.I
|
||||
// Created by: drose (26Jan01)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: VrpnButton::get_button_name
|
||||
// Access: Public
|
||||
// Description: Returns the name of the button device that was used
|
||||
// to create this VrpnButton.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE const string &VrpnButton::
|
||||
get_button_name() const {
|
||||
return _button_name;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: VrpnButton::is_empty
|
||||
// Access: Public
|
||||
// Description: Returns true if no VrpnButtonDevices reference this
|
||||
// VrpnButton, or false otherwise.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool VrpnButton::
|
||||
is_empty() const {
|
||||
return _devices.empty();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: VrpnButton::poll
|
||||
// Access: Public
|
||||
// Description: Polls the connected device. Normally you should not
|
||||
// call this directly; this will be called by the
|
||||
// VrpnClient.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void VrpnButton::
|
||||
poll() {
|
||||
_button->mainloop();
|
||||
}
|
||||
|
|
@ -0,0 +1,117 @@
|
|||
// Filename: vrpnButton.cxx
|
||||
// Created by: drose (26Jan01)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "vrpnButton.h"
|
||||
#include "vrpnButtonDevice.h"
|
||||
#include "vrpnClient.h"
|
||||
#include "config_vrpn.h"
|
||||
|
||||
#include <indent.h>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: VrpnButton::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
VrpnButton::
|
||||
VrpnButton(const string &button_name, vrpn_Connection *connection) :
|
||||
_button_name(button_name)
|
||||
{
|
||||
_button = new vrpn_Button_Remote(_button_name.c_str(), connection);
|
||||
|
||||
_button->register_change_handler((void*)this, &vrpn_button_callback);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: VrpnButton::Destructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
VrpnButton::
|
||||
~VrpnButton() {
|
||||
delete _button;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: VrpnButton::mark
|
||||
// Access: Public
|
||||
// Description: Adds the indicated VrpnButtonDevice to the list of
|
||||
// devices that are sharing this VrpnButton.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void VrpnButton::
|
||||
mark(VrpnButtonDevice *device) {
|
||||
if (vrpn_cat.is_debug()) {
|
||||
vrpn_cat.debug() << *this << " marking " << *device << "\n";
|
||||
}
|
||||
_devices.push_back(device);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: VrpnButton::unmark
|
||||
// Access: Public
|
||||
// Description: Removes the indicated VrpnButtonDevice from the list
|
||||
// of devices that are sharing this VrpnButton.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void VrpnButton::
|
||||
unmark(VrpnButtonDevice *device) {
|
||||
if (vrpn_cat.is_debug()) {
|
||||
vrpn_cat.debug() << *this << " unmarking " << *device << "\n";
|
||||
}
|
||||
|
||||
Devices::iterator di =
|
||||
find(_devices.begin(), _devices.end(), device);
|
||||
|
||||
if (di != _devices.end()) {
|
||||
_devices.erase(di);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: VrpnButton::output
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void VrpnButton::
|
||||
output(ostream &out) const {
|
||||
out << _button_name;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: VrpnButton::write
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void VrpnButton::
|
||||
write(ostream &out, int indent_level) const {
|
||||
indent(out, indent_level)
|
||||
<< get_button_name() << " ("
|
||||
<< _devices.size() << " devices)\n";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: VrpnButton::vrpn_button_callback
|
||||
// Access: Private, Static
|
||||
// Description: Receives the button event data from the VRPN
|
||||
// code and sends it to any interested
|
||||
// VrpnButtonDevices.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void VrpnButton::
|
||||
vrpn_button_callback(void *userdata, const vrpn_BUTTONCB info) {
|
||||
VrpnButton *self = (VrpnButton *)userdata;
|
||||
if (vrpn_cat.is_debug()) {
|
||||
vrpn_cat.debug()
|
||||
<< *self << " got button " << info.button << " = " << info.state << "\n";
|
||||
}
|
||||
|
||||
Devices::iterator di;
|
||||
for (di = self->_devices.begin(); di != self->_devices.end(); ++di) {
|
||||
VrpnButtonDevice *device = (*di);
|
||||
device->lock();
|
||||
device->set_button_state(info.button, info.state != 0);
|
||||
device->unlock();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
// Filename: vrpnButton.h
|
||||
// Created by: drose (26Jan01)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef VRPNBUTTON_H
|
||||
#define VRPNBUTTON_H
|
||||
|
||||
#include <pandabase.h>
|
||||
|
||||
#include "vrpn_interface.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
class VrpnButtonDevice;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : VrpnButton
|
||||
// Description : This is the actual interface to a particular VRPN
|
||||
// button device, and all of its numbered buttons. A
|
||||
// pointer to this object is stored in the VrpnClient
|
||||
// class for each differently-named VRPN button device
|
||||
// we connect to.
|
||||
//
|
||||
// The VRPN callbacks go here, which in turn get
|
||||
// vectored out to any VrpnButtonDevice objects that
|
||||
// register with this. When the last VrpnButtonDevice
|
||||
// object unregisters, the VrpnButton will be deleted
|
||||
// by the VrpnClient.
|
||||
//
|
||||
// This class does not need to be exported from the DLL.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class VrpnButton {
|
||||
public:
|
||||
VrpnButton(const string &button_name, vrpn_Connection *connection);
|
||||
~VrpnButton();
|
||||
|
||||
INLINE const string &get_button_name() const;
|
||||
INLINE bool is_empty() const;
|
||||
|
||||
void mark(VrpnButtonDevice *device);
|
||||
void unmark(VrpnButtonDevice *device);
|
||||
|
||||
INLINE void poll();
|
||||
|
||||
void output(ostream &out) const;
|
||||
void write(ostream &out, int indent_level = 0) const;
|
||||
|
||||
private:
|
||||
static void
|
||||
vrpn_button_callback(void *userdata, const vrpn_BUTTONCB info);
|
||||
|
||||
private:
|
||||
string _button_name;
|
||||
vrpn_Button_Remote *_button;
|
||||
|
||||
typedef vector<VrpnButtonDevice *> Devices;
|
||||
Devices _devices;
|
||||
};
|
||||
|
||||
INLINE ostream &operator << (ostream &out, const VrpnButton &button) {
|
||||
button.output(out);
|
||||
return out;
|
||||
}
|
||||
|
||||
#include "vrpnButton.I"
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
// Filename: vrpnButtonDevice.I
|
||||
// Created by: drose (26Jan01)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: VrpnButtonDevice::get_vrpn_button
|
||||
// Access: Public
|
||||
// Description: Returns a pointer to the particular VrpnButton this
|
||||
// device gets its data from. This pointer may be
|
||||
// shared with other VrpnButtonDevice objects.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE VrpnButton *VrpnButtonDevice::
|
||||
get_vrpn_button() const {
|
||||
return _vrpn_button;
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
// Filename: vrpnButtonDevice.cxx
|
||||
// Created by: drose (26Jan01)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "vrpnButtonDevice.h"
|
||||
#include "vrpnClient.h"
|
||||
|
||||
TypeHandle VrpnButtonDevice::_type_handle;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: VrpnButtonDevice::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
VrpnButtonDevice::
|
||||
VrpnButtonDevice(VrpnClient *client, const string &device_name,
|
||||
VrpnButton *vrpn_button) :
|
||||
ClientButtonDevice(client, device_name),
|
||||
_vrpn_button(vrpn_button)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: VrpnButtonDevice::Destructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
VrpnButtonDevice::
|
||||
~VrpnButtonDevice() {
|
||||
disconnect();
|
||||
}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
// Filename: vrpnButtonDevice.h
|
||||
// Created by: drose (26Jan01)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef VRPNBUTTONDEVICE_H
|
||||
#define VRPNBUTTONDEVICE_H
|
||||
|
||||
#include <pandabase.h>
|
||||
|
||||
#include <clientButtonDevice.h>
|
||||
|
||||
class VrpnClient;
|
||||
class VrpnButton;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : VrpnButtonDevice
|
||||
// Description : The Panda interface to a VRPN button. This object
|
||||
// will be returned by VrpnClient::make_device(), for
|
||||
// attaching to a ButtonNode.
|
||||
//
|
||||
// This class does not need to be exported from the DLL.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class VrpnButtonDevice : public ClientButtonDevice {
|
||||
public:
|
||||
VrpnButtonDevice(VrpnClient *client, const string &device_name,
|
||||
VrpnButton *vrpn_button);
|
||||
virtual ~VrpnButtonDevice();
|
||||
|
||||
INLINE VrpnButton *get_vrpn_button() const;
|
||||
|
||||
private:
|
||||
VrpnButton *_vrpn_button;
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
}
|
||||
static void init_type() {
|
||||
ClientButtonDevice::init_type();
|
||||
register_type(_type_handle, "VrpnButtonDevice",
|
||||
ClientButtonDevice::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;
|
||||
|
||||
friend class VrpnButton;
|
||||
};
|
||||
|
||||
#include "vrpnButtonDevice.I"
|
||||
|
||||
#endif
|
||||
|
|
@ -5,6 +5,57 @@
|
|||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: VrpnClient::get_server_name
|
||||
// Access: Public
|
||||
// Description: Returns the name of the server as passed to the
|
||||
// VrpnClient constructor.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE const string &VrpnClient::
|
||||
get_server_name() const {
|
||||
return _server_name;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: VrpnClient::is_valid
|
||||
// Access: Public
|
||||
// Description: Returns true if everything seems to be kosher with
|
||||
// the server (even if there is no connection), or false
|
||||
// otherwise.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool VrpnClient::
|
||||
is_valid() const {
|
||||
return _connection->doing_okay();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: VrpnClient::is_connected
|
||||
// Access: Public
|
||||
// Description: Returns true if the connection is established
|
||||
// succesfully, false otherwise.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool VrpnClient::
|
||||
is_connected() const {
|
||||
return _connection->connected();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: VrpnClient::convert_to_secs
|
||||
// Access: Public, Static
|
||||
// Description: Little inline function to convert a struct timeval
|
||||
// to only seconds
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE double VrpnClient::
|
||||
convert_to_secs(struct timeval msg_time) {
|
||||
return (double)(msg_time.tv_sec) + (double)msg_time.tv_usec * 0.000001;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#if 0
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: VrpnClient::constructor
|
||||
// Access: Public
|
||||
|
|
@ -107,12 +158,4 @@ dial(const string &dial, const vrpn_DIALCB info) {
|
|||
push_dial(dial, dtime, info.dial, info.change);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: convert_to_secs
|
||||
// Access: Public
|
||||
// Description: Little inline function to convert a struct timeval
|
||||
// to only seconds
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE double convert_to_secs(struct timeval msg_time) {
|
||||
return (double)(msg_time.tv_sec) + (double)msg_time.tv_usec * 0.000001;
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -4,9 +4,548 @@
|
|||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "vrpnClient.h"
|
||||
#include "vrpnTracker.h"
|
||||
#include "vrpnTrackerDevice.h"
|
||||
#include "vrpnButton.h"
|
||||
#include "vrpnButtonDevice.h"
|
||||
#include "vrpnAnalog.h"
|
||||
#include "vrpnAnalogDevice.h"
|
||||
#include "config_vrpn.h"
|
||||
|
||||
#include <string_utils.h>
|
||||
#include <indent.h>
|
||||
|
||||
TypeHandle VrpnClient::_type_handle;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: VrpnClient::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
VrpnClient::
|
||||
VrpnClient(const string &server_name) :
|
||||
_server_name(server_name)
|
||||
{
|
||||
if (vrpn_cat.is_debug()) {
|
||||
vrpn_cat.debug()
|
||||
<< "Attempting to connect to VRPN server " << _server_name
|
||||
<< "\n";
|
||||
}
|
||||
_connection = vrpn_get_connection_by_name(_server_name.c_str());
|
||||
nassertv(_connection != (vrpn_Connection *)NULL);
|
||||
|
||||
if (!is_valid()) {
|
||||
vrpn_cat.warning()
|
||||
<< "Unable to establish connection to VRPN server " << _server_name
|
||||
<< "\n";
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: VrpnClient::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
VrpnClient::
|
||||
~VrpnClient() {
|
||||
delete _connection;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: VrpnClient::write
|
||||
// Access: Public
|
||||
// Description: Writes a list of the active devices that the
|
||||
// VrpnClient is currently polling each frame.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void VrpnClient::
|
||||
write(ostream &out, int indent_level) const {
|
||||
indent(out, indent_level)
|
||||
<< "VrpnClient, server " << _server_name << "\n";
|
||||
|
||||
if (!is_valid()) {
|
||||
indent(out, indent_level + 2)
|
||||
<< "(error)\n";
|
||||
} else if (!is_connected()) {
|
||||
indent(out, indent_level + 2)
|
||||
<< "(no connection)\n";
|
||||
}
|
||||
|
||||
if (!_trackers.empty()) {
|
||||
indent(out, indent_level + 2)
|
||||
<< _trackers.size() << " trackers:\n";
|
||||
Trackers::const_iterator ti;
|
||||
for (ti = _trackers.begin(); ti != _trackers.end(); ++ti) {
|
||||
VrpnTracker *vrpn_tracker = (*ti).second;
|
||||
vrpn_tracker->write(out, indent_level + 4);
|
||||
}
|
||||
}
|
||||
|
||||
if (!_buttons.empty()) {
|
||||
indent(out, indent_level + 2)
|
||||
<< _buttons.size() << " buttons:\n";
|
||||
Buttons::const_iterator bi;
|
||||
for (bi = _buttons.begin(); bi != _buttons.end(); ++bi) {
|
||||
VrpnButton *vrpn_button = (*bi).second;
|
||||
vrpn_button->write(out, indent_level + 4);
|
||||
}
|
||||
}
|
||||
|
||||
if (!_analogs.empty()) {
|
||||
indent(out, indent_level + 2)
|
||||
<< _analogs.size() << " analogs:\n";
|
||||
Analogs::const_iterator ai;
|
||||
for (ai = _analogs.begin(); ai != _analogs.end(); ++ai) {
|
||||
VrpnAnalog *vrpn_analog = (*ai).second;
|
||||
vrpn_analog->write(out, indent_level + 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: VrpnClient::make_device
|
||||
// Access: Protected, Virtual
|
||||
// Description: Creates and returns a new ClientDevice of the
|
||||
// appropriate type, according to the requested
|
||||
// device_type and device_name. Returns NULL if a
|
||||
// matching device cannot be found.
|
||||
//
|
||||
// This is guaranteed not to be called twice for a given
|
||||
// device_type/device_name combination (unless
|
||||
// disconnect_device() has already been called for the
|
||||
// same device_type/device_name).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PT(ClientDevice) VrpnClient::
|
||||
make_device(TypeHandle device_type, const string &device_name) {
|
||||
if (device_type == ClientTrackerDevice::get_class_type()) {
|
||||
return make_tracker_device(device_name);
|
||||
|
||||
} else if (device_type == ClientButtonDevice::get_class_type()) {
|
||||
return make_button_device(device_name);
|
||||
|
||||
} else if (device_type == ClientAnalogDevice::get_class_type()) {
|
||||
return make_analog_device(device_name);
|
||||
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: VrpnClient::disconnect_device
|
||||
// Access: Protected, Virtual
|
||||
// Description: Removes the device, which is presumably about to
|
||||
// destruct, from the list of connected devices, and
|
||||
// frees any data required to support it. This device
|
||||
// will no longer receive automatic updates with each
|
||||
// poll.
|
||||
//
|
||||
// The return value is true if the device was
|
||||
// disconnected, or false if it was unknown (e.g. it was
|
||||
// disconnected previously).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool VrpnClient::
|
||||
disconnect_device(TypeHandle device_type, const string &device_name,
|
||||
ClientDevice *device) {
|
||||
if (vrpn_cat.is_debug()) {
|
||||
vrpn_cat.debug()
|
||||
<< "Disconnecting device " << *device << "\n";
|
||||
}
|
||||
|
||||
if (ClientBase::disconnect_device(device_type, device_name, device)) {
|
||||
if (device->is_of_type(VrpnTrackerDevice::get_class_type())) {
|
||||
disconnect_tracker_device(DCAST(VrpnTrackerDevice, device));
|
||||
|
||||
} else if (device->is_of_type(VrpnButtonDevice::get_class_type())) {
|
||||
disconnect_button_device(DCAST(VrpnButtonDevice, device));
|
||||
|
||||
} else if (device->is_of_type(VrpnAnalogDevice::get_class_type())) {
|
||||
disconnect_analog_device(DCAST(VrpnAnalogDevice, device));
|
||||
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: VrpnClient::do_poll
|
||||
// Access: Protected, Virtual
|
||||
// Description: Implements the polling and updating of connected
|
||||
// devices, if the ClientBase requires this. This may
|
||||
// be called in a sub-thread if
|
||||
// fork_asynchronous_thread() was called; otherwise, it
|
||||
// will be called once per frame.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void VrpnClient::
|
||||
do_poll() {
|
||||
ClientBase::do_poll();
|
||||
|
||||
if (vrpn_cat.is_spam()) {
|
||||
vrpn_cat.spam()
|
||||
<< "VrpnClient " << _server_name << " polling "
|
||||
<< _trackers.size() + _buttons.size() + _analogs.size()
|
||||
<< " devices.\n";
|
||||
}
|
||||
|
||||
Trackers::iterator ti;
|
||||
for (ti = _trackers.begin(); ti != _trackers.end(); ++ti) {
|
||||
VrpnTracker *vrpn_tracker = (*ti).second;
|
||||
vrpn_tracker->poll();
|
||||
}
|
||||
|
||||
Buttons::iterator bi;
|
||||
for (bi = _buttons.begin(); bi != _buttons.end(); ++bi) {
|
||||
VrpnButton *vrpn_button = (*bi).second;
|
||||
vrpn_button->poll();
|
||||
}
|
||||
|
||||
Analogs::iterator ai;
|
||||
for (ai = _analogs.begin(); ai != _analogs.end(); ++ai) {
|
||||
VrpnAnalog *vrpn_analog = (*ai).second;
|
||||
vrpn_analog->poll();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: VrpnClient::make_tracker_device
|
||||
// Access: Private
|
||||
// Description: Creates a new tracker device. The device_name is
|
||||
// parsed for sensor and data_type information.
|
||||
//
|
||||
// The device_name may be one of the following:
|
||||
//
|
||||
// tracker_name
|
||||
// tracker_name:N
|
||||
// tracker_name:N[pva]
|
||||
//
|
||||
// Where N is an integer sensor number, and [pva] is one
|
||||
// of the lowercase letters p, v, or a.
|
||||
//
|
||||
// In the first form, the device connects to the
|
||||
// indicated tracker, and reports position information
|
||||
// on sensor number 0.
|
||||
//
|
||||
// In the second form, the device connects to the
|
||||
// indicated tracker, and reports position information
|
||||
// on the indicated sensor number.
|
||||
//
|
||||
// In the third form, the device connects to the
|
||||
// indicated tracker, and reports either position,
|
||||
// velocity, or acceleration information on the
|
||||
// indicated sensor number.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PT(ClientDevice) VrpnClient::
|
||||
make_tracker_device(const string &device_name) {
|
||||
if (vrpn_cat.is_debug()) {
|
||||
vrpn_cat.debug()
|
||||
<< "Making tracker device for " << device_name << "\n";
|
||||
}
|
||||
|
||||
string tracker_name = device_name;
|
||||
int sensor = 0;
|
||||
VrpnTrackerDevice::DataType data_type = VrpnTrackerDevice::DT_position;
|
||||
|
||||
size_t colon = device_name.rfind(':');
|
||||
if (colon != string::npos && colon + 1 < device_name.length()) {
|
||||
size_t begin = colon + 1;
|
||||
size_t end = device_name.length();
|
||||
VrpnTrackerDevice::DataType maybe_data_type = data_type;
|
||||
|
||||
switch (device_name[end - 1]) {
|
||||
case 'p':
|
||||
maybe_data_type = VrpnTrackerDevice::DT_position;
|
||||
end--;
|
||||
break;
|
||||
|
||||
case 'v':
|
||||
maybe_data_type = VrpnTrackerDevice::DT_velocity;
|
||||
end--;
|
||||
break;
|
||||
|
||||
case 'a':
|
||||
maybe_data_type = VrpnTrackerDevice::DT_acceleration;
|
||||
end--;
|
||||
break;
|
||||
}
|
||||
int maybe_sensor;
|
||||
if (string_to_int(device_name.substr(begin, end - begin), maybe_sensor)) {
|
||||
// It seems to be a legitimate integer!
|
||||
sensor = maybe_sensor;
|
||||
data_type = maybe_data_type;
|
||||
tracker_name = device_name.substr(0, colon);
|
||||
}
|
||||
}
|
||||
|
||||
VrpnTracker *tracker = get_tracker(tracker_name);
|
||||
|
||||
VrpnTrackerDevice *device =
|
||||
new VrpnTrackerDevice(this, device_name, sensor, data_type, tracker);
|
||||
|
||||
if (vrpn_cat.is_debug()) {
|
||||
vrpn_cat.debug()
|
||||
<< "Creating " << *device << "\n";
|
||||
}
|
||||
|
||||
tracker->mark(device);
|
||||
return device;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: VrpnClient::make_button_device
|
||||
// Access: Private
|
||||
// Description: Creates a new button device. The device_name is sent
|
||||
// verbatim to the VRPN library.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PT(ClientDevice) VrpnClient::
|
||||
make_button_device(const string &device_name) {
|
||||
if (vrpn_cat.is_debug()) {
|
||||
vrpn_cat.debug()
|
||||
<< "Making button device for " << device_name << "\n";
|
||||
}
|
||||
|
||||
VrpnButton *button = get_button(device_name);
|
||||
|
||||
VrpnButtonDevice *device =
|
||||
new VrpnButtonDevice(this, device_name, button);
|
||||
|
||||
if (vrpn_cat.is_debug()) {
|
||||
vrpn_cat.debug()
|
||||
<< "Creating " << *device << "\n";
|
||||
}
|
||||
|
||||
button->mark(device);
|
||||
return device;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: VrpnClient::make_analog_device
|
||||
// Access: Private
|
||||
// Description: Creates a new analog device. The device_name is sent
|
||||
// verbatim to the VRPN library.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PT(ClientDevice) VrpnClient::
|
||||
make_analog_device(const string &device_name) {
|
||||
if (vrpn_cat.is_debug()) {
|
||||
vrpn_cat.debug()
|
||||
<< "Making analog device for " << device_name << "\n";
|
||||
}
|
||||
|
||||
VrpnAnalog *analog = get_analog(device_name);
|
||||
|
||||
VrpnAnalogDevice *device =
|
||||
new VrpnAnalogDevice(this, device_name, analog);
|
||||
|
||||
if (vrpn_cat.is_debug()) {
|
||||
vrpn_cat.debug()
|
||||
<< "Creating " << *device << "\n";
|
||||
}
|
||||
|
||||
analog->mark(device);
|
||||
return device;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: VrpnClient::disconnect_tracker_device
|
||||
// Access: Private
|
||||
// Description: Removes the tracker device from the list of things to
|
||||
// be updated.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void VrpnClient::
|
||||
disconnect_tracker_device(VrpnTrackerDevice *device) {
|
||||
VrpnTracker *vrpn_tracker = device->get_vrpn_tracker();
|
||||
vrpn_tracker->unmark(device);
|
||||
if (vrpn_tracker->is_empty()) {
|
||||
free_tracker(vrpn_tracker);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: VrpnClient::disconnect_button_device
|
||||
// Access: Private
|
||||
// Description: Removes the button device from the list of things to
|
||||
// be updated.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void VrpnClient::
|
||||
disconnect_button_device(VrpnButtonDevice *device) {
|
||||
VrpnButton *vrpn_button = device->get_vrpn_button();
|
||||
vrpn_button->unmark(device);
|
||||
if (vrpn_button->is_empty()) {
|
||||
free_button(vrpn_button);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: VrpnClient::disconnect_analog_device
|
||||
// Access: Private
|
||||
// Description: Removes the analog device from the list of things to
|
||||
// be updated.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void VrpnClient::
|
||||
disconnect_analog_device(VrpnAnalogDevice *device) {
|
||||
VrpnAnalog *vrpn_analog = device->get_vrpn_analog();
|
||||
vrpn_analog->unmark(device);
|
||||
if (vrpn_analog->is_empty()) {
|
||||
free_analog(vrpn_analog);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: VrpnClient::get_tracker
|
||||
// Access: Private
|
||||
// Description: Finds a VrpnTracker of the indicated name, and
|
||||
// returns it if one already exists, or creates a new
|
||||
// one if it does not.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
VrpnTracker *VrpnClient::
|
||||
get_tracker(const string &tracker_name) {
|
||||
Trackers::iterator ti;
|
||||
ti = _trackers.find(tracker_name);
|
||||
|
||||
if (ti != _trackers.end()) {
|
||||
return (*ti).second;
|
||||
}
|
||||
|
||||
VrpnTracker *vrpn_tracker = new VrpnTracker(tracker_name, _connection);
|
||||
_trackers.insert(Trackers::value_type(tracker_name, vrpn_tracker));
|
||||
|
||||
if (vrpn_cat.is_debug()) {
|
||||
vrpn_cat.debug()
|
||||
<< "Creating tracker " << *vrpn_tracker << "\n";
|
||||
}
|
||||
|
||||
return vrpn_tracker;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: VrpnClient::free_tracker
|
||||
// Access: Private
|
||||
// Description: Removes and deletes the indicated VrpnTracker, which
|
||||
// is no longer referenced by any VrpnTrackerDevices.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void VrpnClient::
|
||||
free_tracker(VrpnTracker *vrpn_tracker) {
|
||||
nassertv(vrpn_tracker->is_empty());
|
||||
|
||||
if (vrpn_cat.is_debug()) {
|
||||
vrpn_cat.debug()
|
||||
<< "Deleting tracker " << *vrpn_tracker << "\n";
|
||||
}
|
||||
|
||||
Trackers::iterator ti;
|
||||
ti = _trackers.find(vrpn_tracker->get_tracker_name());
|
||||
nassertv(ti != _trackers.end());
|
||||
nassertv((*ti).second == vrpn_tracker);
|
||||
|
||||
_trackers.erase(ti);
|
||||
delete vrpn_tracker;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: VrpnClient::get_button
|
||||
// Access: Private
|
||||
// Description: Finds a VrpnButton of the indicated name, and
|
||||
// returns it if one already exists, or creates a new
|
||||
// one if it does not.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
VrpnButton *VrpnClient::
|
||||
get_button(const string &button_name) {
|
||||
Buttons::iterator bi;
|
||||
bi = _buttons.find(button_name);
|
||||
|
||||
if (bi != _buttons.end()) {
|
||||
return (*bi).second;
|
||||
}
|
||||
|
||||
VrpnButton *vrpn_button = new VrpnButton(button_name, _connection);
|
||||
_buttons.insert(Buttons::value_type(button_name, vrpn_button));
|
||||
|
||||
if (vrpn_cat.is_debug()) {
|
||||
vrpn_cat.debug()
|
||||
<< "Creating button " << *vrpn_button << "\n";
|
||||
}
|
||||
|
||||
return vrpn_button;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: VrpnClient::free_button
|
||||
// Access: Private
|
||||
// Description: Removes and deletes the indicated VrpnButton, which
|
||||
// is no longer referenced by any VrpnButtonDevices.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void VrpnClient::
|
||||
free_button(VrpnButton *vrpn_button) {
|
||||
nassertv(vrpn_button->is_empty());
|
||||
|
||||
if (vrpn_cat.is_debug()) {
|
||||
vrpn_cat.debug()
|
||||
<< "Deleting button " << *vrpn_button << "\n";
|
||||
}
|
||||
|
||||
Buttons::iterator bi;
|
||||
bi = _buttons.find(vrpn_button->get_button_name());
|
||||
nassertv(bi != _buttons.end());
|
||||
nassertv((*bi).second == vrpn_button);
|
||||
|
||||
_buttons.erase(bi);
|
||||
delete vrpn_button;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: VrpnClient::get_analog
|
||||
// Access: Private
|
||||
// Description: Finds a VrpnAnalog of the indicated name, and
|
||||
// returns it if one already exists, or creates a new
|
||||
// one if it does not.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
VrpnAnalog *VrpnClient::
|
||||
get_analog(const string &analog_name) {
|
||||
Analogs::iterator ai;
|
||||
ai = _analogs.find(analog_name);
|
||||
|
||||
if (ai != _analogs.end()) {
|
||||
return (*ai).second;
|
||||
}
|
||||
|
||||
VrpnAnalog *vrpn_analog = new VrpnAnalog(analog_name, _connection);
|
||||
_analogs.insert(Analogs::value_type(analog_name, vrpn_analog));
|
||||
|
||||
if (vrpn_cat.is_debug()) {
|
||||
vrpn_cat.debug()
|
||||
<< "Creating analog " << *vrpn_analog << "\n";
|
||||
}
|
||||
|
||||
return vrpn_analog;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: VrpnClient::free_analog
|
||||
// Access: Private
|
||||
// Description: Removes and deletes the indicated VrpnAnalog, which
|
||||
// is no longer referenced by any VrpnAnalogDevices.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void VrpnClient::
|
||||
free_analog(VrpnAnalog *vrpn_analog) {
|
||||
nassertv(vrpn_analog->is_empty());
|
||||
|
||||
if (vrpn_cat.is_debug()) {
|
||||
vrpn_cat.debug()
|
||||
<< "Deleting analog " << *vrpn_analog << "\n";
|
||||
}
|
||||
|
||||
Analogs::iterator ai;
|
||||
ai = _analogs.find(vrpn_analog->get_analog_name());
|
||||
nassertv(ai != _analogs.end());
|
||||
nassertv((*ai).second == vrpn_analog);
|
||||
|
||||
_analogs.erase(ai);
|
||||
delete vrpn_analog;
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
|
||||
#include <datagram.h>
|
||||
#include <datagramIterator.h>
|
||||
|
||||
|
|
@ -261,3 +800,5 @@ st_dial(void *userdata, const vrpn_DIALCB info) {
|
|||
VrpnClientInfo *data = (VrpnClientInfo *)userdata;
|
||||
((VrpnClient *)data->self)->dial(data->device_name, info);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -3,110 +3,99 @@
|
|||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef VRPN_CLIENT
|
||||
#define VRPN_CLIENT
|
||||
#ifndef VRPNCLIENT_H
|
||||
#define VRPNCLIENT_H
|
||||
|
||||
#include <pandabase.h>
|
||||
#include <clientBase.h>
|
||||
|
||||
#ifdef CPPPARSER
|
||||
// For correct interrogate parsing of UNC's vrpn library.
|
||||
#ifdef WIN32_VC
|
||||
#define _WIN32
|
||||
#define SOCKET int
|
||||
#else
|
||||
#define linux
|
||||
typedef struct timeval timeval;
|
||||
#endif
|
||||
#endif
|
||||
#include "vrpn_interface.h"
|
||||
|
||||
#include <vrpn_Connection.h>
|
||||
#include <vrpn_Tracker.h>
|
||||
#include <vrpn_Analog.h>
|
||||
#include <vrpn_Button.h>
|
||||
#include <vrpn_Dial.h>
|
||||
class VrpnTracker;
|
||||
class VrpnTrackerDevice;
|
||||
class VrpnButton;
|
||||
class VrpnButtonDevice;
|
||||
class VrpnAnalog;
|
||||
class VrpnAnalogDevice;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : VrpnClient
|
||||
// Description : A specific ClientBase that connects to a VRPN server
|
||||
// and records information on the connected VRPN
|
||||
// devices.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDA VrpnClient : public ClientBase {
|
||||
PUBLISHED:
|
||||
INLINE VrpnClient(const string &server);
|
||||
VrpnClient(const string &server_name);
|
||||
~VrpnClient();
|
||||
|
||||
INLINE const string &get_server_name() const;
|
||||
INLINE bool is_valid() const;
|
||||
INLINE bool is_connected() const;
|
||||
|
||||
void write(ostream &out, int indent_level = 0) const;
|
||||
|
||||
public:
|
||||
//ADD FUNCTIONS
|
||||
virtual bool add_remote_tracker(const string &tracker, int sensor);
|
||||
virtual bool add_remote_analog(const string &analog);
|
||||
virtual bool add_remote_button(const string &button);
|
||||
virtual bool add_remote_dial(const string &dial);
|
||||
|
||||
INLINE static double convert_to_secs(struct timeval msg_time);
|
||||
|
||||
protected:
|
||||
virtual int max_analog_channels();
|
||||
virtual PT(ClientDevice) make_device(TypeHandle device_type,
|
||||
const string &device_name);
|
||||
|
||||
//Device polling functions
|
||||
virtual void poll_tracker(const string &tracker);
|
||||
virtual void poll_analog(const string &analog);
|
||||
virtual void poll_button(const string &button);
|
||||
virtual void poll_dial(const string &dial);
|
||||
virtual bool disconnect_device(TypeHandle device_type,
|
||||
const string &device_name,
|
||||
ClientDevice *device);
|
||||
|
||||
virtual void do_poll();
|
||||
|
||||
private:
|
||||
//Private VRPN objects
|
||||
typedef map <string, vrpn_Tracker*> VrpnTrackers;
|
||||
typedef map <string, vrpn_Analog*> VrpnAnalogs;
|
||||
typedef map <string, vrpn_Button*> VrpnButtons;
|
||||
typedef map <string, vrpn_Dial*> VrpnDials;
|
||||
PT(ClientDevice) make_tracker_device(const string &device_name);
|
||||
PT(ClientDevice) make_button_device(const string &device_name);
|
||||
PT(ClientDevice) make_analog_device(const string &device_name);
|
||||
void disconnect_tracker_device(VrpnTrackerDevice *device);
|
||||
void disconnect_button_device(VrpnButtonDevice *device);
|
||||
void disconnect_analog_device(VrpnAnalogDevice *device);
|
||||
|
||||
VrpnTracker *get_tracker(const string &tracker_name);
|
||||
void free_tracker(VrpnTracker *vrpn_tracker);
|
||||
|
||||
VrpnButton *get_button(const string &button_name);
|
||||
void free_button(VrpnButton *vrpn_button);
|
||||
|
||||
VrpnAnalog *get_analog(const string &analog_name);
|
||||
void free_analog(VrpnAnalog *vrpn_analog);
|
||||
|
||||
private:
|
||||
string _server_name;
|
||||
vrpn_Connection *_connection;
|
||||
VrpnTrackers _vrpn_trackers;
|
||||
VrpnAnalogs _vrpn_analogs;
|
||||
VrpnButtons _vrpn_buttons;
|
||||
VrpnDials _vrpn_dials;
|
||||
|
||||
//VRPN Callback functions. Each callback actually needs to be a
|
||||
//pair of two functions, one a static and one not. The static is
|
||||
//needed because we can't set member functions as callbacks (due to
|
||||
//the implicity this pointer) and the non-static function is needed
|
||||
//so that we can set the non-static data storage variables
|
||||
//appropriately
|
||||
private:
|
||||
static void st_tracker_position(void *userdata, const vrpn_TRACKERCB info);
|
||||
INLINE void tracker_position(const string &tracker, const vrpn_TRACKERCB info);
|
||||
typedef map<string, VrpnTracker *> Trackers;
|
||||
typedef map<string, VrpnButton *> Buttons;
|
||||
typedef map<string, VrpnAnalog *> Analogs;
|
||||
|
||||
static void st_tracker_velocity(void *userdata, const vrpn_TRACKERVELCB info);
|
||||
INLINE void tracker_velocity(const string &tracker, const vrpn_TRACKERVELCB info);
|
||||
Trackers _trackers;
|
||||
Buttons _buttons;
|
||||
Analogs _analogs;
|
||||
|
||||
static void st_tracker_acceleration(void *userdata, const vrpn_TRACKERACCCB info);
|
||||
INLINE void tracker_acceleration(const string &tracker, const vrpn_TRACKERACCCB info);
|
||||
|
||||
static void st_analog(void *userdata, const vrpn_ANALOGCB info);
|
||||
INLINE void analog(const string &analog, const vrpn_ANALOGCB info);
|
||||
|
||||
static void st_button(void *userdata, const vrpn_BUTTONCB info);
|
||||
INLINE void button(const string &button, const vrpn_BUTTONCB info);
|
||||
|
||||
static void st_dial(void *userdata, const vrpn_DIALCB info);
|
||||
INLINE void dial(const string &dial, const vrpn_DIALCB info);
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type( void ) {
|
||||
return _type_handle;
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
}
|
||||
static void init_type( void ) {
|
||||
static void init_type() {
|
||||
ClientBase::init_type();
|
||||
register_type( _type_handle, "VrpnClient",
|
||||
ClientBase::get_class_type() );
|
||||
register_type(_type_handle, "VrpnClient",
|
||||
ClientBase::get_class_type());
|
||||
}
|
||||
virtual TypeHandle get_type( void ) const {
|
||||
virtual TypeHandle get_type() const {
|
||||
return get_class_type();
|
||||
}
|
||||
virtual TypeHandle force_init_type() {
|
||||
init_type();
|
||||
return get_class_type();
|
||||
}
|
||||
|
||||
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
|
||||
|
||||
private:
|
||||
static TypeHandle _type_handle;
|
||||
static TypeHandle _type_handle;
|
||||
};
|
||||
|
||||
INLINE double convert_to_secs(struct timeval msg_time);
|
||||
|
||||
#include "vrpnClient.I"
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -0,0 +1,38 @@
|
|||
// Filename: vrpnTracker.I
|
||||
// Created by: drose (25Jan01)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: VrpnTracker::get_tracker_name
|
||||
// Access: Public
|
||||
// Description: Returns the name of the tracker device that was used
|
||||
// to create this VrpnTracker.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE const string &VrpnTracker::
|
||||
get_tracker_name() const {
|
||||
return _tracker_name;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: VrpnTracker::is_empty
|
||||
// Access: Public
|
||||
// Description: Returns true if no VrpnTrackerDevices reference this
|
||||
// VrpnTracker, or false otherwise.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool VrpnTracker::
|
||||
is_empty() const {
|
||||
return _devices.empty();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: VrpnTracker::poll
|
||||
// Access: Public
|
||||
// Description: Polls the connected device. Normally you should not
|
||||
// call this directly; this will be called by the
|
||||
// VrpnClient.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void VrpnTracker::
|
||||
poll() {
|
||||
_tracker->mainloop();
|
||||
}
|
||||
|
|
@ -0,0 +1,186 @@
|
|||
// Filename: vrpnTracker.cxx
|
||||
// Created by: drose (25Jan01)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "vrpnTracker.h"
|
||||
#include "vrpnTrackerDevice.h"
|
||||
#include "vrpnClient.h"
|
||||
#include "config_vrpn.h"
|
||||
|
||||
#include <indent.h>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: VrpnTracker::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
VrpnTracker::
|
||||
VrpnTracker(const string &tracker_name, vrpn_Connection *connection) :
|
||||
_tracker_name(tracker_name)
|
||||
{
|
||||
_tracker = new vrpn_Tracker_Remote(_tracker_name.c_str(), connection);
|
||||
|
||||
_tracker->register_change_handler((void*)this, &vrpn_position_callback);
|
||||
_tracker->register_change_handler((void*)this, &vrpn_velocity_callback);
|
||||
_tracker->register_change_handler((void*)this, &vrpn_acceleration_callback);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: VrpnTracker::Destructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
VrpnTracker::
|
||||
~VrpnTracker() {
|
||||
delete _tracker;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: VrpnTracker::mark
|
||||
// Access: Public
|
||||
// Description: Adds the indicated VrpnTrackerDevice to the list of
|
||||
// devices that are sharing this VrpnTracker.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void VrpnTracker::
|
||||
mark(VrpnTrackerDevice *device) {
|
||||
if (vrpn_cat.is_debug()) {
|
||||
vrpn_cat.debug() << *this << " marking " << *device << "\n";
|
||||
}
|
||||
_devices.push_back(device);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: VrpnTracker::unmark
|
||||
// Access: Public
|
||||
// Description: Removes the indicated VrpnTrackerDevice from the list
|
||||
// of devices that are sharing this VrpnTracker.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void VrpnTracker::
|
||||
unmark(VrpnTrackerDevice *device) {
|
||||
if (vrpn_cat.is_debug()) {
|
||||
vrpn_cat.debug() << *this << " unmarking " << *device << "\n";
|
||||
}
|
||||
|
||||
Devices::iterator di =
|
||||
find(_devices.begin(), _devices.end(), device);
|
||||
|
||||
if (di != _devices.end()) {
|
||||
_devices.erase(di);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: VrpnTracker::output
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void VrpnTracker::
|
||||
output(ostream &out) const {
|
||||
out << _tracker_name;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: VrpnTracker::write
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void VrpnTracker::
|
||||
write(ostream &out, int indent_level) const {
|
||||
indent(out, indent_level)
|
||||
<< get_tracker_name() << " ("
|
||||
<< _devices.size() << " devices)\n";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: VrpnTracker::vrpn_position_callback
|
||||
// Access: Private, Static
|
||||
// Description: Receives the tracker positional data from the VRPN
|
||||
// code and sends it to any interested
|
||||
// VrpnTrackerDevices.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void VrpnTracker::
|
||||
vrpn_position_callback(void *userdata, const vrpn_TRACKERCB info) {
|
||||
VrpnTracker *self = (VrpnTracker *)userdata;
|
||||
if (vrpn_cat.is_spam()) {
|
||||
vrpn_cat.spam()
|
||||
<< *self << " position_callback\n";
|
||||
}
|
||||
|
||||
Devices::iterator di;
|
||||
for (di = self->_devices.begin(); di != self->_devices.end(); ++di) {
|
||||
VrpnTrackerDevice *device = (*di);
|
||||
if (device->get_sensor() == info.sensor &&
|
||||
device->get_data_type() == VrpnTrackerDevice::DT_position) {
|
||||
device->lock();
|
||||
device->_data.set_time(VrpnClient::convert_to_secs(info.msg_time));
|
||||
device->_data.set_pos(LPoint3f(info.pos[0], info.pos[1], info.pos[2]));
|
||||
device->_data.set_orient(LOrientationf(info.quat[0], info.quat[1], info.quat[2], info.quat[3]));
|
||||
device->unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: VrpnTracker::vrpn_velocity_callback
|
||||
// Access: Private, Static
|
||||
// Description: Receives the tracker velocity data from the VRPN
|
||||
// code and sends it to any interested
|
||||
// VrpnTrackerDevices.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void VrpnTracker::
|
||||
vrpn_velocity_callback(void *userdata, const vrpn_TRACKERVELCB info) {
|
||||
VrpnTracker *self = (VrpnTracker *)userdata;
|
||||
if (vrpn_cat.is_spam()) {
|
||||
vrpn_cat.spam()
|
||||
<< *self << " velocity_callback\n";
|
||||
}
|
||||
|
||||
Devices::iterator di;
|
||||
for (di = self->_devices.begin(); di != self->_devices.end(); ++di) {
|
||||
VrpnTrackerDevice *device = (*di);
|
||||
if (device->get_sensor() == info.sensor &&
|
||||
device->get_data_type() == VrpnTrackerDevice::DT_velocity) {
|
||||
device->lock();
|
||||
device->_data.set_time(VrpnClient::convert_to_secs(info.msg_time));
|
||||
device->_data.set_pos(LPoint3f(info.vel[0], info.vel[1], info.vel[2]));
|
||||
device->_data.set_orient(LOrientationf(info.vel_quat[0], info.vel_quat[1],
|
||||
info.vel_quat[2], info.vel_quat[3]));
|
||||
device->_data.set_dt(info.vel_quat_dt);
|
||||
device->unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: VrpnTracker::vrpn_acceleration_callback
|
||||
// Access: Private, Static
|
||||
// Description: Receives the tracker acceleration data from the VRPN
|
||||
// code and sends it to any interested
|
||||
// VrpnTrackerDevices.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void VrpnTracker::
|
||||
vrpn_acceleration_callback(void *userdata, const vrpn_TRACKERACCCB info) {
|
||||
VrpnTracker *self = (VrpnTracker *)userdata;
|
||||
if (vrpn_cat.is_spam()) {
|
||||
vrpn_cat.spam()
|
||||
<< *self << " acceleration_callback\n";
|
||||
}
|
||||
|
||||
Devices::iterator di;
|
||||
for (di = self->_devices.begin(); di != self->_devices.end(); ++di) {
|
||||
VrpnTrackerDevice *device = (*di);
|
||||
if (device->get_sensor() == info.sensor &&
|
||||
device->get_data_type() == VrpnTrackerDevice::DT_acceleration) {
|
||||
device->lock();
|
||||
device->_data.set_time(VrpnClient::convert_to_secs(info.msg_time));
|
||||
device->_data.set_pos(LPoint3f(info.acc[0], info.acc[1], info.acc[2]));
|
||||
device->_data.set_orient(LOrientationf(info.acc_quat[0], info.acc_quat[1],
|
||||
info.acc_quat[2], info.acc_quat[3]));
|
||||
device->_data.set_dt(info.acc_quat_dt);
|
||||
device->unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
// Filename: vrpnTracker.h
|
||||
// Created by: drose (25Jan01)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef VRPNTRACKER_H
|
||||
#define VRPNTRACKER_H
|
||||
|
||||
#include <pandabase.h>
|
||||
|
||||
#include "vrpn_interface.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
class VrpnTrackerDevice;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : VrpnTracker
|
||||
// Description : This is the actual interface to a particular VRPN
|
||||
// tracker object, and all of its sensors. A pointer to
|
||||
// this object is stored in the VrpnClient class for
|
||||
// each differently-named VRPN tracker we connect to.
|
||||
//
|
||||
// The VRPN callbacks go here, which in turn get
|
||||
// vectored out to any VrpnTrackerDevice objects that
|
||||
// register with this. When the last VrpnTrackerDevice
|
||||
// object unregisters, the VrpnTracker will be deleted
|
||||
// by the VrpnClient.
|
||||
//
|
||||
// This class does not need to be exported from the DLL.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class VrpnTracker {
|
||||
public:
|
||||
VrpnTracker(const string &tracker_name, vrpn_Connection *connection);
|
||||
~VrpnTracker();
|
||||
|
||||
INLINE const string &get_tracker_name() const;
|
||||
INLINE bool is_empty() const;
|
||||
|
||||
void mark(VrpnTrackerDevice *device);
|
||||
void unmark(VrpnTrackerDevice *device);
|
||||
|
||||
INLINE void poll();
|
||||
|
||||
void output(ostream &out) const;
|
||||
void write(ostream &out, int indent_level = 0) const;
|
||||
|
||||
private:
|
||||
static void
|
||||
vrpn_position_callback(void *userdata, const vrpn_TRACKERCB info);
|
||||
static void
|
||||
vrpn_velocity_callback(void *userdata, const vrpn_TRACKERVELCB info);
|
||||
static void
|
||||
vrpn_acceleration_callback(void *userdata, const vrpn_TRACKERACCCB info);
|
||||
|
||||
private:
|
||||
string _tracker_name;
|
||||
vrpn_Tracker_Remote *_tracker;
|
||||
|
||||
typedef vector<VrpnTrackerDevice *> Devices;
|
||||
Devices _devices;
|
||||
};
|
||||
|
||||
INLINE ostream &operator << (ostream &out, const VrpnTracker &tracker) {
|
||||
tracker.output(out);
|
||||
return out;
|
||||
}
|
||||
|
||||
#include "vrpnTracker.I"
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
// Filename: vrpnTrackerDevice.I
|
||||
// Created by: drose (25Jan01)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: VrpnTrackerDevice::get_sensor
|
||||
// Access: Public
|
||||
// Description: Returns the particular sensor index that this device
|
||||
// wants to hear about from the VrpnTracker.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int VrpnTrackerDevice::
|
||||
get_sensor() const {
|
||||
return _sensor;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: VrpnTrackerDevice::get_data_type
|
||||
// Access: Public
|
||||
// Description: Returns the type of data this device represents from
|
||||
// the VrpnTracker. This may be position, velocity, or
|
||||
// acceleration.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE VrpnTrackerDevice::DataType VrpnTrackerDevice::
|
||||
get_data_type() const {
|
||||
return _data_type;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: VrpnTrackerDevice::get_vrpn_tracker
|
||||
// Access: Public
|
||||
// Description: Returns a pointer to the particular VrpnTracker this
|
||||
// device gets its data from. This pointer may be
|
||||
// shared with other VrpnTrackerDevice objects (each
|
||||
// representing a different portion of the tracker
|
||||
// data).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE VrpnTracker *VrpnTrackerDevice::
|
||||
get_vrpn_tracker() const {
|
||||
return _vrpn_tracker;
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
// Filename: vrpnTrackerDevice.cxx
|
||||
// Created by: drose (25Jan01)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "vrpnTrackerDevice.h"
|
||||
#include "vrpnClient.h"
|
||||
|
||||
TypeHandle VrpnTrackerDevice::_type_handle;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: VrpnTrackerDevice::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
VrpnTrackerDevice::
|
||||
VrpnTrackerDevice(VrpnClient *client, const string &device_name,
|
||||
int sensor, VrpnTrackerDevice::DataType data_type,
|
||||
VrpnTracker *vrpn_tracker) :
|
||||
ClientTrackerDevice(client, device_name),
|
||||
_sensor(sensor),
|
||||
_data_type(data_type),
|
||||
_vrpn_tracker(vrpn_tracker)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: VrpnTrackerDevice::Destructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
VrpnTrackerDevice::
|
||||
~VrpnTrackerDevice() {
|
||||
disconnect();
|
||||
}
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
// Filename: vrpnTrackerDevice.h
|
||||
// Created by: drose (25Jan01)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef VRPNTRACKERDEVICE_H
|
||||
#define VRPNTRACKERDEVICE_H
|
||||
|
||||
#include <pandabase.h>
|
||||
|
||||
#include <clientTrackerDevice.h>
|
||||
|
||||
class VrpnClient;
|
||||
class VrpnTracker;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : VrpnTrackerDevice
|
||||
// Description : The Panda interface to a VRPN tracker. This object
|
||||
// will be returned by VrpnClient::make_device(), for
|
||||
// attaching to a TrackerNode.
|
||||
//
|
||||
// It represents the data from just one particular
|
||||
// sensor of a named VRPN tracker, and may reflect
|
||||
// either the sensor's position, its velocity, or its
|
||||
// acceleration.
|
||||
//
|
||||
// This class does not need to be exported from the DLL.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class VrpnTrackerDevice : public ClientTrackerDevice {
|
||||
public:
|
||||
enum DataType {
|
||||
DT_position,
|
||||
DT_velocity,
|
||||
DT_acceleration
|
||||
};
|
||||
|
||||
VrpnTrackerDevice(VrpnClient *client, const string &device_name,
|
||||
int sensor, DataType data_type,
|
||||
VrpnTracker *vrpn_tracker);
|
||||
virtual ~VrpnTrackerDevice();
|
||||
|
||||
INLINE int get_sensor() const;
|
||||
INLINE DataType get_data_type() const;
|
||||
INLINE VrpnTracker *get_vrpn_tracker() const;
|
||||
|
||||
private:
|
||||
int _sensor;
|
||||
DataType _data_type;
|
||||
VrpnTracker *_vrpn_tracker;
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
}
|
||||
static void init_type() {
|
||||
ClientTrackerDevice::init_type();
|
||||
register_type(_type_handle, "VrpnTrackerDevice",
|
||||
ClientTrackerDevice::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;
|
||||
|
||||
friend class VrpnTracker;
|
||||
};
|
||||
|
||||
#include "vrpnTrackerDevice.I"
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
// Filename: vrpn_interface.h
|
||||
// Created by: drose (25Jan01)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef VRPN_INTERFACE_H
|
||||
#define VRPN_INTERFACE_H
|
||||
|
||||
#include <pandabase.h>
|
||||
|
||||
#ifdef CPPPARSER
|
||||
// For correct interrogate parsing of UNC's vrpn library.
|
||||
#ifdef WIN32_VC
|
||||
#define _WIN32
|
||||
#define SOCKET int
|
||||
#else
|
||||
#define linux
|
||||
typedef struct timeval timeval;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <vrpn_Connection.h>
|
||||
#include <vrpn_Tracker.h>
|
||||
#include <vrpn_Analog.h>
|
||||
#include <vrpn_Button.h>
|
||||
#include <vrpn_Dial.h>
|
||||
|
||||
#endif
|
||||
Loading…
Reference in New Issue