*** empty log message ***

This commit is contained in:
David Rose 2001-01-27 01:17:57 +00:00
parent 0ac40455aa
commit fe2f34c925
31 changed files with 938 additions and 261 deletions

View File

@ -13,10 +13,12 @@
clientBase.I clientBase.cxx clientBase.h \
clientButtonDevice.I clientButtonDevice.cxx clientButtonDevice.h \
clientDevice.I clientDevice.cxx clientDevice.h \
clientDialDevice.I clientDialDevice.cxx clientDialDevice.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 \
dialNode.I dialNode.h dialNode.cxx \
mouse.cxx mouse.h \
trackerData.I trackerData.cxx trackerData.h \
trackerNode.I trackerNode.cxx trackerNode.h
#define INSTALL_HEADERS \
@ -26,9 +28,12 @@
clientBase.I clientBase.h \
clientButtonDevice.I clientButtonDevice.h \
clientDevice.I clientDevice.h \
clientDialDevice.I clientDialDevice.h \
clientTrackerDevice.I clientTrackerDevice.h \
config_device.h dialData.I dialData.h mouse.h \
trackerData.I trackerData.h trackerNode.I trackerNode.h
config_device.h mouse.h \
dialNode.I dialNode.h \
trackerData.I trackerData.h \
trackerNode.I trackerNode.h
#define IGATESCAN all

View File

@ -35,7 +35,10 @@ is_valid() const {
////////////////////////////////////////////////////////////////////
INLINE int AnalogNode::
get_num_controls() const {
return _analog->get_num_controls();
_analog->lock();
int result = _analog->get_num_controls();
_analog->unlock();
return result;
}
////////////////////////////////////////////////////////////////////
@ -48,7 +51,10 @@ get_num_controls() const {
////////////////////////////////////////////////////////////////////
INLINE double AnalogNode::
get_control_state(int index) const {
return _analog->get_control_state(index);
_analog->lock();
double result = _analog->get_control_state(index);
_analog->unlock();
return result;
}
////////////////////////////////////////////////////////////////////
@ -60,7 +66,10 @@ get_control_state(int index) const {
////////////////////////////////////////////////////////////////////
INLINE bool AnalogNode::
is_control_known(int index) const {
return _analog->is_control_known(index);
_analog->lock();
bool result = _analog->is_control_known(index);
_analog->unlock();
return result;
}
////////////////////////////////////////////////////////////////////

View File

@ -67,7 +67,9 @@ write(ostream &out, int indent_level) const {
DataNode::write(out, indent_level);
if (_analog != (ClientAnalogDevice *)NULL) {
_analog->lock();
_analog->write_controls(out, indent_level + 2);
_analog->unlock();
}
}
@ -83,15 +85,18 @@ transmit_data(NodeAttributes &data) {
LPoint3f out(0.0, 0.0, 0.0);
_analog->lock();
for (int i = 0; i < max_outputs; i++) {
if (_outputs[i]._index >= 0 && is_control_known(_outputs[i]._index)) {
if (_outputs[i]._index >= 0 &&
_analog->is_control_known(_outputs[i]._index)) {
if (_outputs[i]._flip) {
out[i] = -get_control_state(_outputs[i]._index);
out[i] = -_analog->get_control_state(_outputs[i]._index);
} else {
out[i] = get_control_state(_outputs[i]._index);
out[i] = _analog->get_control_state(_outputs[i]._index);
}
}
}
_analog->unlock();
_xyz->set_value(out);
}

View File

@ -27,7 +27,10 @@ is_valid() const {
////////////////////////////////////////////////////////////////////
INLINE int ButtonNode::
get_num_buttons() const {
return _button->get_num_buttons();
_button->lock();
int result = _button->get_num_buttons();
_button->unlock();
return result;
}
////////////////////////////////////////////////////////////////////
@ -46,7 +49,9 @@ get_num_buttons() const {
////////////////////////////////////////////////////////////////////
INLINE void ButtonNode::
set_button_map(int index, ButtonHandle button) {
_button->lock();
_button->set_button_map(index, button);
_button->unlock();
}
////////////////////////////////////////////////////////////////////
@ -59,7 +64,10 @@ set_button_map(int index, ButtonHandle button) {
////////////////////////////////////////////////////////////////////
INLINE ButtonHandle ButtonNode::
get_button_map(int index) const {
return _button->get_button_map(index);
_button->lock();
ButtonHandle result = _button->get_button_map(index);
_button->unlock();
return result;
}
////////////////////////////////////////////////////////////////////
@ -71,7 +79,10 @@ get_button_map(int index) const {
////////////////////////////////////////////////////////////////////
INLINE bool ButtonNode::
get_button_state(int index) const {
return _button->get_button_state(index);
_button->lock();
bool result = _button->get_button_state(index);
_button->unlock();
return result;
}
////////////////////////////////////////////////////////////////////
@ -83,5 +94,8 @@ get_button_state(int index) const {
////////////////////////////////////////////////////////////////////
INLINE bool ButtonNode::
is_button_known(int index) const {
return _button->is_button_known(index);
_button->lock();
bool result = _button->is_button_known(index);
_button->unlock();
return result;
}

View File

@ -72,7 +72,9 @@ output(ostream &out) const {
if (_button != (ClientButtonDevice *)NULL) {
out << " (";
_button->lock();
_button->output_buttons(out);
_button->unlock();
out << ")";
}
}
@ -87,7 +89,9 @@ write(ostream &out, int indent_level) const {
DataNode::write(out, indent_level);
if (_button != (ClientButtonDevice *)NULL) {
_button->lock();
_button->write_buttons(out, indent_level + 2);
_button->unlock();
}
}

View File

@ -56,13 +56,18 @@ ClientDevice::
// (and it is probably a mistake to do so); it will
// automatically be called when the ClientDevice object
// destructs.
//
// The lock should *not* be held while this call is
// made; it will explicitly grab the lock itself.
////////////////////////////////////////////////////////////////////
void ClientDevice::
disconnect() {
if (_is_connected) {
lock();
bool disconnected =
_client->disconnect_device(_device_type, _device_name, this);
_is_connected = false;
unlock();
nassertv(disconnected);
}
}

View File

@ -0,0 +1,92 @@
// Filename: clientDialDevice.I
// Created by: drose (26Jan01)
//
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: ClientDialDevice::DialState::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE ClientDialDevice::DialState::
DialState() :
_offset(0.0),
_known(false)
{
}
////////////////////////////////////////////////////////////////////
// Function: ClientDialDevice::Constructor
// Access: Protected
// Description:
////////////////////////////////////////////////////////////////////
INLINE ClientDialDevice::
ClientDialDevice(ClientBase *client, const string &device_name):
ClientDevice(client, get_class_type(), device_name)
{
}
////////////////////////////////////////////////////////////////////
// Function: ClientDialDevice::get_num_dials
// Access: Public
// Description: Returns the number of dial dials known to the
// ClientDialDevice. This number may change as
// more dials are discovered.
////////////////////////////////////////////////////////////////////
INLINE int ClientDialDevice::
get_num_dials() const {
return _dials.size();
}
////////////////////////////////////////////////////////////////////
// Function: ClientDialDevice::push_dial
// Access: Public
// Description: Marks that the dial has been offset by the indicated
// amount. It is the user's responsibility to ensure
// that this call is protected within lock().
////////////////////////////////////////////////////////////////////
INLINE void ClientDialDevice::
push_dial(int index, double offset) {
ensure_dial_index(index);
nassertv(index >= 0 && index < (int)_dials.size());
_dials[index]._offset += offset;
_dials[index]._known = true;
}
////////////////////////////////////////////////////////////////////
// Function: ClientDialDevice::read_dial
// Access: Public
// Description: Returns the number of complete revolutions of the
// dial since the last time read_dial() was called.
// This is a destructive operation; it is not possible
// to read the dial without resetting the counter.
//
// It is the user's responsibility to ensure that this
// call is protected within lock().
////////////////////////////////////////////////////////////////////
INLINE double ClientDialDevice::
read_dial(int index) {
if (index >= 0 && index < (int)_dials.size()) {
double result = _dials[index]._offset;
_dials[index]._offset = 0.0;
return result;
} else {
return 0.0;
}
}
////////////////////////////////////////////////////////////////////
// Function: ClientDialDevice::is_dial_known
// Access: Public
// Description: Returns true if the state of the indicated dial
// dial is known, or false if we have never heard
// anything about this particular dial.
////////////////////////////////////////////////////////////////////
INLINE bool ClientDialDevice::
is_dial_known(int index) const {
if (index >= 0 && index < (int)_dials.size()) {
return _dials[index]._known;
} else {
return false;
}
}

View File

@ -0,0 +1,29 @@
// Filename: clientDialDevice.cxx
// Created by: drose (26Jan01)
//
////////////////////////////////////////////////////////////////////
#include "clientDialDevice.h"
#include <indent.h>
TypeHandle ClientDialDevice::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: ClientDialDevice::ensure_dial_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 ClientDialDevice::
ensure_dial_index(int index) {
nassertv(index >= 0);
_dials.reserve(index + 1);
while ((int)_dials.size() <= index) {
_dials.push_back(DialState());
}
}

View File

@ -0,0 +1,73 @@
// Filename: clientDialDevice.h
// Created by: drose (26Jan01)
//
////////////////////////////////////////////////////////////////////
#ifndef CLIENTDIALDEVICE_H
#define CLIENTDIALDEVICE_H
#include <pandabase.h>
#include "clientDevice.h"
////////////////////////////////////////////////////////////////////
// Class : ClientDialDevice
// Description : A device, attached to the ClientBase by a
// DialNode, that records the data from a single
// named dial device. The named device can contain
// any number of dials, numbered in sequence beginning
// at zero.
//
// A dial is a rotating device that does not have
// stops--it can keep rotating any number of times.
// Therefore it does not have a specific position at any
// given time, unlike an AnalogDevice.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA ClientDialDevice : public ClientDevice {
protected:
INLINE ClientDialDevice(ClientBase *client, const string &device_name);
public:
INLINE int get_num_dials() const;
INLINE void push_dial(int index, double offset);
INLINE double read_dial(int index);
INLINE bool is_dial_known(int index) const;
private:
void ensure_dial_index(int index);
protected:
class DialState {
public:
INLINE DialState();
double _offset;
bool _known;
};
typedef vector<DialState> Dials;
Dials _dials;
public:
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
ClientDevice::init_type();
register_type(_type_handle, "ClientDialDevice",
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 "clientDialDevice.I"
#endif

View File

@ -10,7 +10,9 @@
#include "clientBase.h"
#include "clientButtonDevice.h"
#include "clientDevice.h"
#include "clientDialDevice.h"
#include "clientTrackerDevice.h"
#include "dialNode.h"
#include "mouse.h"
#include "trackerNode.h"
@ -19,7 +21,7 @@
Configure(config_device);
NotifyCategoryDef(device, "");
const bool asynchronous_clients = config_device.GetBool("asynchronous-clients", false);
const bool asynchronous_clients = config_device.GetBool("asynchronous-clients", true);
ConfigureFn(config_device) {
init_libdevice();
@ -47,7 +49,9 @@ init_libdevice() {
ClientBase::init_type();
ClientButtonDevice::init_type();
ClientDevice::init_type();
ClientDialDevice::init_type();
ClientTrackerDevice::init_type();
DialNode::init_type();
MouseAndKeyboard::init_type();
TrackerNode::init_type();
}

View File

@ -1,49 +0,0 @@
// Filename: dialData.I
// Created by: jason (07Aug00)
//
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: DialData::Default Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE DialData::
DialData() :
dtime(0), dial_id(0), change(0)
{
}
////////////////////////////////////////////////////////////////////
// Function: DialData::Copy Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE DialData::
DialData(const DialData &copy) {
(*this) = copy;
}
////////////////////////////////////////////////////////////////////
// Function: DialData::Copy Assignment Operator
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE DialData &DialData::
operator = (const DialData &copy) {
dtime = copy.dtime;
dial_id = copy.dial_id;
change = copy.change;
return *this;
}
////////////////////////////////////////////////////////////////////
// Function: DialData::none
// Access: Public, Static
// Description: Returns an empty DialData object
////////////////////////////////////////////////////////////////////
INLINE const DialData &DialData::
none() {
return _none;
}

View File

@ -1,9 +0,0 @@
// Filename: dialData.cxx
// Created by: jason (04Aug00)
//
////////////////////////////////////////////////////////////////////
#include "dialData.h"
// This is initialized to zero by static initialization.
DialData DialData::_none;

View File

@ -1,29 +0,0 @@
// Filename: dialData.h
// Created by: jason (07Aug00)
//
////////////////////////////////////////////////////////////////////
#ifndef DIAL_DATA
#define DIAL_DATA
#include <pandabase.h>
#include <vector_float.h>
class EXPCL_PANDA DialData {
public:
INLINE DialData();
INLINE DialData(const DialData &copy);
INLINE DialData &operator = (const DialData &copy);
INLINE static const DialData &none();
double dtime;
int dial_id;
float change;
private:
static DialData _none;
};
#include "dialData.I"
#endif

View File

@ -0,0 +1,61 @@
// Filename: dialNode.I
// Created by: drose (26Jan01)
//
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: DialNode::is_valid
// Access: Public
// Description: Returns true if the DialNode is valid and
// connected to a server, false otherwise.
////////////////////////////////////////////////////////////////////
INLINE bool DialNode::
is_valid() const {
return (_dial != (ClientDialDevice *)NULL) && _dial->is_connected();
}
////////////////////////////////////////////////////////////////////
// Function: DialNode::get_num_dials
// Access: Public
// Description: Returns the number of dial dials known to the
// DialNode. This number may change as more dials
// are discovered.
////////////////////////////////////////////////////////////////////
INLINE int DialNode::
get_num_dials() const {
_dial->lock();
int result = _dial->get_num_dials();
_dial->unlock();
return result;
}
////////////////////////////////////////////////////////////////////
// Function: DialNode::read_dial
// Access: Public
// Description: Returns the number of complete revolutions of the
// dial since the last time read_dial() was called.
// This is a destructive operation; it is not possible
// to read the dial without resetting the counter.
////////////////////////////////////////////////////////////////////
INLINE double DialNode::
read_dial(int index) {
_dial->lock();
double result = _dial->read_dial(index);
_dial->unlock();
return result;
}
////////////////////////////////////////////////////////////////////
// Function: DialNode::is_dial_known
// Access: Public
// Description: Returns true if the state of the indicated dial
// dial is known, or false if we have never heard
// anything about this particular dial.
////////////////////////////////////////////////////////////////////
INLINE bool DialNode::
is_dial_known(int index) const {
_dial->lock();
bool result = _dial->is_dial_known(index);
_dial->unlock();
return result;
}

View File

@ -0,0 +1,82 @@
// Filename: dialNode.cxx
// Created by: drose (26Jan01)
//
////////////////////////////////////////////////////////////////////
#include "dialNode.h"
#include "config_device.h"
////////////////////////////////////////////////////////////////////
// Static variables
////////////////////////////////////////////////////////////////////
TypeHandle DialNode::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: DialNode::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
DialNode::
DialNode(ClientBase *client, const string &device_name) :
DataNode(device_name)
{
nassertv(client != (ClientBase *)NULL);
PT(ClientDevice) device =
client->get_device(ClientDialDevice::get_class_type(), device_name);
if (device == (ClientDevice *)NULL) {
device_cat.warning()
<< "Unable to open dial device " << device_name << "\n";
return;
}
if (!device->is_of_type(ClientDialDevice::get_class_type())) {
device_cat.error()
<< "Inappropriate device type " << device->get_type()
<< " created; expected a ClientDialDevice.\n";
return;
}
_dial = DCAST(ClientDialDevice, device);
}
////////////////////////////////////////////////////////////////////
// Function: DialNode::Destructor
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
DialNode::
~DialNode() {
// When the _dial pointer destructs, the ClientDialDevice
// disconnects itself from the ClientBase, and everything that needs
// to get turned off does. Magic.
}
////////////////////////////////////////////////////////////////////
// Function: DialNode::transmit_data
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
void DialNode::
transmit_data(NodeAttributes &data) {
if (is_valid()) {
_dial->poll();
// Not clear yet what we should be transmitting.
}
data = _attrib;
}
////////////////////////////////////////////////////////////////////
// Function: DialNode::init_type
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
void DialNode::
init_type() {
DataNode::init_type();
register_type(_type_handle, "DialNode",
DataNode::get_class_type());
}

View File

@ -0,0 +1,72 @@
// Filename: dialNode.h
// Created by: drose (26Jan01)
//
////////////////////////////////////////////////////////////////////
#ifndef DIALNODE_H
#define DIALNODE_H
#include <pandabase.h>
#include "clientBase.h"
#include "clientDialDevice.h"
#include <dataNode.h>
#include <nodeAttributes.h>
////////////////////////////////////////////////////////////////////
// Class : DialNode
// Description : This is the primary interface to infinite dial type
// devices associated with a ClientBase. This creates a
// node that connects to the named dial device, if it
// exists, and provides hooks to the user to read the
// state of any of the sequentially numbered dial
// controls associated with that device.
//
// A dial is a rotating device that does not have
// stops--it can keep rotating any number of times.
// Therefore it does not have a specific position at any
// given time, unlike an AnalogDevice.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA DialNode : public DataNode {
PUBLISHED:
DialNode(ClientBase *client, const string &device_name);
virtual ~DialNode();
INLINE bool is_valid() const;
INLINE int get_num_dials() const;
INLINE double read_dial(int index);
INLINE bool is_dial_known(int index) const;
////////////////////////////////////////////////////////////////////
// From parent class DataNode
////////////////////////////////////////////////////////////////////
public:
virtual void
transmit_data(NodeAttributes &data);
NodeAttributes _attrib;
private:
PT(ClientDialDevice) _dial;
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 "dialNode.I"
#endif

View File

@ -22,10 +22,11 @@
////////////////////////////////////////////////////////////////////
// Class : TrackerNode
// 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.
// Description : This is the primary interface to a Tracker object
// associated with a ClientBase. It reads the position
// and orientation information from the tracker and
// makes it available as a transformation on the data
// graph.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA TrackerNode : public DataNode {
PUBLISHED:

View File

@ -12,13 +12,13 @@
driveInterface.cxx driveInterface.h mouseWatcher.I mouseWatcher.cxx \
mouseWatcher.h mouseWatcherRegion.I mouseWatcherRegion.cxx \
mouseWatcherRegion.h planarSlider.cxx planarSlider.h trackball.cxx \
trackball.h trackerTransform.cxx trackerTransform.h \
trackball.h \
transform2sg.cxx transform2sg.h
#define INSTALL_HEADERS \
buttonThrower.h driveInterface.h mouseWatcher.I mouseWatcher.h \
mouseWatcherRegion.I mouseWatcherRegion.h planarSlider.h \
trackball.h trackerTransform.h transform2sg.h
trackball.h transform2sg.h
#define IGATESCAN all

View File

@ -11,7 +11,6 @@
#include "planarSlider.h"
#include "trackball.h"
#include "transform2sg.h"
#include "trackerTransform.h"
#include <dconfig.h>
@ -38,5 +37,4 @@ ConfigureFn(config_tform) {
PlanarSlider::init_type();
Trackball::init_type();
Transform2SG::init_type();
TrackerTransform::init_type();
}

View File

@ -1,82 +0,0 @@
// Filename: trackerTransform.cxx
// Created by: jason (08Aug00)
//
////////////////////////////////////////////////////////////////////
#include <pandabase.h>
#include "trackerTransform.h"
#include "config_tform.h"
TypeHandle TrackerTransform::_type_handle;
TypeHandle TrackerTransform::_position_type;
TypeHandle TrackerTransform::_pquat_type;
TypeHandle TrackerTransform::_transform_type;
////////////////////////////////////////////////////////////////////
// Function: TrackerTransform::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
TrackerTransform::
TrackerTransform(const string &name) : DataNode(name) {
_transform = new MatrixDataAttribute;
_transform->set_value(LMatrix4f::ident_mat());
_transform_attrib.set_attribute(_transform_type, _transform);
}
////////////////////////////////////////////////////////////////////
// Function: TrackerTransform::transmit_data
// Access: Public
// Description: Constructs a transformation matrix from tracker data
// and passes it down the line
////////////////////////////////////////////////////////////////////
void TrackerTransform::
transmit_data(NodeAttributes &data) {
const NodeAttribute *position = data.get_attribute(_position_type);
if (tform_cat.is_debug()) {
tform_cat.debug() << "TrackerTransform:transmit_data" << endl;
}
if (position != (NodeAttribute *)NULL) {
LVecBase3f p = DCAST(Vec3DataAttribute, position)->get_value();
LMatrix4f mat = LMatrix4f::translate_mat(p);
if (tform_cat.is_debug()) {
tform_cat.debug() << "Sending down " << mat << endl;
}
_transform->set_value(mat);
}
data = _transform_attrib;
}
////////////////////////////////////////////////////////////////////
// Function: TrackerTransform::init_type
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
void TrackerTransform::
init_type() {
DataNode::init_type();
register_type(_type_handle, "TrackerTransform",
DataNode::get_class_type());
Vec3DataTransition::init_type();
Vec4DataTransition::init_type();
MatrixDataTransition::init_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(_transform_type, "Transform",
MatrixDataTransition::get_class_type());
}

View File

@ -1,68 +0,0 @@
// Filename: trackerTransform.h
// Created by: jason (08Aug00)
//
////////////////////////////////////////////////////////////////////
#ifndef TRACKER_TRANSFORM_H
#define TRACKER_TRANSFORM_H
#include <pandabase.h>
#include <dataNode.h>
#include <doubleDataAttribute.h>
#include <doubleDataTransition.h>
#include <vec3DataAttribute.h>
#include <vec3DataTransition.h>
#include <vec3DataAttribute.h>
#include <vec4DataTransition.h>
#include <vec4DataAttribute.h>
#include <matrixDataTransition.h>
#include <matrixDataAttribute.h>
#include <nodeAttributes.h>
#include <luse.h>
#include <lmatrix.h>
////////////////////////////////////////////////////////////////////
// Class : TrackerTransform
// Description : TrackerTransform reads the data send down the line
// by a TrackerNode and creates a transformation matrix
// from the data and sends that matrix down the line
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA TrackerTransform : public DataNode {
PUBLISHED:
TrackerTransform(const string &name = "");
public:
virtual void transmit_data(NodeAttributes &data);
private:
NodeAttributes _transform_attrib;
PT(MatrixDataAttribute) _transform;
// inputs
static TypeHandle _position_type;
//NOTE!!!
//Currently not being factored into the matrix. Needs to be done
static TypeHandle _pquat_type;
// outputs
static TypeHandle _transform_type;
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

View File

@ -16,6 +16,8 @@
vrpnButton.I vrpnButton.cxx vrpnButton.h \
vrpnButtonDevice.I vrpnButtonDevice.cxx vrpnButtonDevice.h \
vrpnClient.h \
vrpnDial.I vrpnDial.cxx vrpnDial.h \
vrpnDialDevice.I vrpnDialDevice.cxx vrpnDialDevice.h \
vrpnTracker.I vrpnTracker.cxx vrpnTracker.h \
vrpnTrackerDevice.I vrpnTrackerDevice.cxx vrpnTrackerDevice.h \
vrpn_interface.h

View File

@ -7,6 +7,7 @@
#include "vrpnAnalogDevice.h"
#include "vrpnButtonDevice.h"
#include "vrpnClient.h"
#include "vrpnDialDevice.h"
#include "vrpnTrackerDevice.h"
#include <dconfig.h>
@ -19,5 +20,6 @@ ConfigureFn(config_vrpn) {
VrpnAnalogDevice::init_type();
VrpnButtonDevice::init_type();
VrpnClient::init_type();
VrpnDialDevice::init_type();
VrpnTrackerDevice::init_type();
}

View File

@ -10,6 +10,8 @@
#include "vrpnButtonDevice.h"
#include "vrpnAnalog.h"
#include "vrpnAnalogDevice.h"
#include "vrpnDial.h"
#include "vrpnDialDevice.h"
#include "config_vrpn.h"
#include <string_utils.h>
@ -99,6 +101,16 @@ write(ostream &out, int indent_level) const {
vrpn_analog->write(out, indent_level + 4);
}
}
if (!_dials.empty()) {
indent(out, indent_level + 2)
<< _dials.size() << " dials:\n";
Dials::const_iterator di;
for (di = _dials.begin(); di != _dials.end(); ++di) {
VrpnDial *vrpn_dial = (*di).second;
vrpn_dial->write(out, indent_level + 4);
}
}
}
////////////////////////////////////////////////////////////////////
@ -125,6 +137,9 @@ make_device(TypeHandle device_type, const string &device_name) {
} else if (device_type == ClientAnalogDevice::get_class_type()) {
return make_analog_device(device_name);
} else if (device_type == ClientDialDevice::get_class_type()) {
return make_dial_device(device_name);
} else {
return NULL;
}
@ -161,6 +176,9 @@ disconnect_device(TypeHandle device_type, const string &device_name,
} else if (device->is_of_type(VrpnAnalogDevice::get_class_type())) {
disconnect_analog_device(DCAST(VrpnAnalogDevice, device));
} else if (device->is_of_type(VrpnDialDevice::get_class_type())) {
disconnect_dial_device(DCAST(VrpnDialDevice, device));
}
return true;
}
@ -184,7 +202,7 @@ do_poll() {
if (vrpn_cat.is_spam()) {
vrpn_cat.spam()
<< "VrpnClient " << _server_name << " polling "
<< _trackers.size() + _buttons.size() + _analogs.size()
<< _trackers.size() + _buttons.size() + _analogs.size() + _dials.size()
<< " devices.\n";
}
@ -205,6 +223,12 @@ do_poll() {
VrpnAnalog *vrpn_analog = (*ai).second;
vrpn_analog->poll();
}
Dials::iterator di;
for (di = _dials.begin(); di != _dials.end(); ++di) {
VrpnDial *vrpn_dial = (*di).second;
vrpn_dial->poll();
}
}
////////////////////////////////////////////////////////////////////
@ -345,6 +369,33 @@ make_analog_device(const string &device_name) {
return device;
}
////////////////////////////////////////////////////////////////////
// Function: VrpnClient::make_dial_device
// Access: Private
// Description: Creates a new dial device. The device_name is sent
// verbatim to the VRPN library.
////////////////////////////////////////////////////////////////////
PT(ClientDevice) VrpnClient::
make_dial_device(const string &device_name) {
if (vrpn_cat.is_debug()) {
vrpn_cat.debug()
<< "Making dial device for " << device_name << "\n";
}
VrpnDial *dial = get_dial(device_name);
VrpnDialDevice *device =
new VrpnDialDevice(this, device_name, dial);
if (vrpn_cat.is_debug()) {
vrpn_cat.debug()
<< "Creating " << *device << "\n";
}
dial->mark(device);
return device;
}
////////////////////////////////////////////////////////////////////
// Function: VrpnClient::disconnect_tracker_device
// Access: Private
@ -390,6 +441,21 @@ disconnect_analog_device(VrpnAnalogDevice *device) {
}
}
////////////////////////////////////////////////////////////////////
// Function: VrpnClient::disconnect_dial_device
// Access: Private
// Description: Removes the dial device from the list of things to
// be updated.
////////////////////////////////////////////////////////////////////
void VrpnClient::
disconnect_dial_device(VrpnDialDevice *device) {
VrpnDial *vrpn_dial = device->get_vrpn_dial();
vrpn_dial->unmark(device);
if (vrpn_dial->is_empty()) {
free_dial(vrpn_dial);
}
}
////////////////////////////////////////////////////////////////////
// Function: VrpnClient::get_tracker
// Access: Private
@ -543,6 +609,57 @@ free_analog(VrpnAnalog *vrpn_analog) {
delete vrpn_analog;
}
////////////////////////////////////////////////////////////////////
// Function: VrpnClient::get_dial
// Access: Private
// Description: Finds a VrpnDial of the indicated name, and
// returns it if one already exists, or creates a new
// one if it does not.
////////////////////////////////////////////////////////////////////
VrpnDial *VrpnClient::
get_dial(const string &dial_name) {
Dials::iterator di;
di = _dials.find(dial_name);
if (di != _dials.end()) {
return (*di).second;
}
VrpnDial *vrpn_dial = new VrpnDial(dial_name, _connection);
_dials.insert(Dials::value_type(dial_name, vrpn_dial));
if (vrpn_cat.is_debug()) {
vrpn_cat.debug()
<< "Creating dial " << *vrpn_dial << "\n";
}
return vrpn_dial;
}
////////////////////////////////////////////////////////////////////
// Function: VrpnClient::free_dial
// Access: Private
// Description: Removes and deletes the indicated VrpnDial, which
// is no longer referenced by any VrpnDialDevices.
////////////////////////////////////////////////////////////////////
void VrpnClient::
free_dial(VrpnDial *vrpn_dial) {
nassertv(vrpn_dial->is_empty());
if (vrpn_cat.is_debug()) {
vrpn_cat.debug()
<< "Deleting dial " << *vrpn_dial << "\n";
}
Dials::iterator di;
di = _dials.find(vrpn_dial->get_dial_name());
nassertv(di != _dials.end());
nassertv((*di).second == vrpn_dial);
_dials.erase(di);
delete vrpn_dial;
}
#if 0

View File

@ -17,6 +17,8 @@ class VrpnButton;
class VrpnButtonDevice;
class VrpnAnalog;
class VrpnAnalogDevice;
class VrpnDial;
class VrpnDialDevice;
////////////////////////////////////////////////////////////////////
// Class : VrpnClient
@ -52,9 +54,11 @@ private:
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);
PT(ClientDevice) make_dial_device(const string &device_name);
void disconnect_tracker_device(VrpnTrackerDevice *device);
void disconnect_button_device(VrpnButtonDevice *device);
void disconnect_analog_device(VrpnAnalogDevice *device);
void disconnect_dial_device(VrpnDialDevice *device);
VrpnTracker *get_tracker(const string &tracker_name);
void free_tracker(VrpnTracker *vrpn_tracker);
@ -65,6 +69,9 @@ private:
VrpnAnalog *get_analog(const string &analog_name);
void free_analog(VrpnAnalog *vrpn_analog);
VrpnDial *get_dial(const string &dial_name);
void free_dial(VrpnDial *vrpn_dial);
private:
string _server_name;
vrpn_Connection *_connection;
@ -72,10 +79,12 @@ private:
typedef map<string, VrpnTracker *> Trackers;
typedef map<string, VrpnButton *> Buttons;
typedef map<string, VrpnAnalog *> Analogs;
typedef map<string, VrpnDial *> Dials;
Trackers _trackers;
Buttons _buttons;
Analogs _analogs;
Dials _dials;
public:

38
panda/src/vrpn/vrpnDial.I Normal file
View File

@ -0,0 +1,38 @@
// Filename: vrpnDial.I
// Created by: drose (26Jan01)
//
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: VrpnDial::get_dial_name
// Access: Public
// Description: Returns the name of the dial device that was used
// to create this VrpnDial.
////////////////////////////////////////////////////////////////////
INLINE const string &VrpnDial::
get_dial_name() const {
return _dial_name;
}
////////////////////////////////////////////////////////////////////
// Function: VrpnDial::is_empty
// Access: Public
// Description: Returns true if no VrpnDialDevices reference this
// VrpnDial, or false otherwise.
////////////////////////////////////////////////////////////////////
INLINE bool VrpnDial::
is_empty() const {
return _devices.empty();
}
////////////////////////////////////////////////////////////////////
// Function: VrpnDial::poll
// Access: Public
// Description: Polls the connected device. Normally you should not
// call this directly; this will be called by the
// VrpnClient.
////////////////////////////////////////////////////////////////////
INLINE void VrpnDial::
poll() {
_dial->mainloop();
}

118
panda/src/vrpn/vrpnDial.cxx Normal file
View File

@ -0,0 +1,118 @@
// Filename: vrpnDial.cxx
// Created by: drose (26Jan01)
//
////////////////////////////////////////////////////////////////////
#include "vrpnDial.h"
#include "vrpnDialDevice.h"
#include "vrpnClient.h"
#include "config_vrpn.h"
#include <indent.h>
#include <algorithm>
////////////////////////////////////////////////////////////////////
// Function: VrpnDial::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
VrpnDial::
VrpnDial(const string &dial_name, vrpn_Connection *connection) :
_dial_name(dial_name)
{
_dial = new vrpn_Dial_Remote(_dial_name.c_str(), connection);
_dial->register_change_handler((void*)this, &vrpn_dial_callback);
}
////////////////////////////////////////////////////////////////////
// Function: VrpnDial::Destructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
VrpnDial::
~VrpnDial() {
delete _dial;
}
////////////////////////////////////////////////////////////////////
// Function: VrpnDial::mark
// Access: Public
// Description: Adds the indicated VrpnDialDevice to the list of
// devices that are sharing this VrpnDial.
////////////////////////////////////////////////////////////////////
void VrpnDial::
mark(VrpnDialDevice *device) {
if (vrpn_cat.is_debug()) {
vrpn_cat.debug() << *this << " marking " << *device << "\n";
}
_devices.push_back(device);
}
////////////////////////////////////////////////////////////////////
// Function: VrpnDial::unmark
// Access: Public
// Description: Removes the indicated VrpnDialDevice from the list
// of devices that are sharing this VrpnDial.
////////////////////////////////////////////////////////////////////
void VrpnDial::
unmark(VrpnDialDevice *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: VrpnDial::output
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
void VrpnDial::
output(ostream &out) const {
out << _dial_name;
}
////////////////////////////////////////////////////////////////////
// Function: VrpnDial::write
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
void VrpnDial::
write(ostream &out, int indent_level) const {
indent(out, indent_level)
<< get_dial_name() << " ("
<< _devices.size() << " devices)\n";
}
////////////////////////////////////////////////////////////////////
// Function: VrpnDial::vrpn_dial_callback
// Access: Private, Static
// Description: Receives the dial event data from the VRPN
// code and sends it to any interested
// VrpnDialDevices.
////////////////////////////////////////////////////////////////////
void VrpnDial::
vrpn_dial_callback(void *userdata, const vrpn_DIALCB info) {
VrpnDial *self = (VrpnDial *)userdata;
if (vrpn_cat.is_debug()) {
vrpn_cat.debug()
<< *self << " got dial " << info.dial << " = " << info.change << "\n";
}
Devices::iterator di;
for (di = self->_devices.begin(); di != self->_devices.end(); ++di) {
VrpnDialDevice *device = (*di);
device->lock();
device->push_dial(info.dial, info.change);
device->unlock();
}
}

68
panda/src/vrpn/vrpnDial.h Normal file
View File

@ -0,0 +1,68 @@
// Filename: vrpnDial.h
// Created by: drose (26Jan01)
//
////////////////////////////////////////////////////////////////////
#ifndef VRPNDIAL_H
#define VRPNDIAL_H
#include <pandabase.h>
#include "vrpn_interface.h"
#include <vector>
class VrpnDialDevice;
////////////////////////////////////////////////////////////////////
// Class : VrpnDial
// Description : This is the actual interface to a particular VRPN
// dial device, and all of its numbered dials. A
// pointer to this object is stored in the VrpnClient
// class for each differently-named VRPN dial device
// we connect to.
//
// The VRPN callbacks go here, which in turn get
// vectored out to any VrpnDialDevice objects that
// register with this. When the last VrpnDialDevice
// object unregisters, the VrpnDial will be deleted
// by the VrpnClient.
//
// This class does not need to be exported from the DLL.
////////////////////////////////////////////////////////////////////
class VrpnDial {
public:
VrpnDial(const string &dial_name, vrpn_Connection *connection);
~VrpnDial();
INLINE const string &get_dial_name() const;
INLINE bool is_empty() const;
void mark(VrpnDialDevice *device);
void unmark(VrpnDialDevice *device);
INLINE void poll();
void output(ostream &out) const;
void write(ostream &out, int indent_level = 0) const;
private:
static void
vrpn_dial_callback(void *userdata, const vrpn_DIALCB info);
private:
string _dial_name;
vrpn_Dial_Remote *_dial;
typedef vector<VrpnDialDevice *> Devices;
Devices _devices;
};
INLINE ostream &operator << (ostream &out, const VrpnDial &dial) {
dial.output(out);
return out;
}
#include "vrpnDial.I"
#endif

View File

@ -0,0 +1,17 @@
// Filename: vrpnDialDevice.I
// Created by: drose (26Jan01)
//
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: VrpnDialDevice::get_vrpn_dial
// Access: Public
// Description: Returns a pointer to the particular VrpnDial this
// device gets its data from. This pointer may be
// shared with other VrpnDialDevice objects.
////////////////////////////////////////////////////////////////////
INLINE VrpnDial *VrpnDialDevice::
get_vrpn_dial() const {
return _vrpn_dial;
}

View File

@ -0,0 +1,32 @@
// Filename: vrpnDialDevice.cxx
// Created by: drose (26Jan01)
//
////////////////////////////////////////////////////////////////////
#include "vrpnDialDevice.h"
#include "vrpnClient.h"
TypeHandle VrpnDialDevice::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: VrpnDialDevice::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
VrpnDialDevice::
VrpnDialDevice(VrpnClient *client, const string &device_name,
VrpnDial *vrpn_dial) :
ClientDialDevice(client, device_name),
_vrpn_dial(vrpn_dial)
{
}
////////////////////////////////////////////////////////////////////
// Function: VrpnDialDevice::Destructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
VrpnDialDevice::
~VrpnDialDevice() {
disconnect();
}

View File

@ -0,0 +1,57 @@
// Filename: vrpnDialDevice.h
// Created by: drose (26Jan01)
//
////////////////////////////////////////////////////////////////////
#ifndef VRPNDIALDEVICE_H
#define VRPNDIALDEVICE_H
#include <pandabase.h>
#include <clientDialDevice.h>
class VrpnClient;
class VrpnDial;
////////////////////////////////////////////////////////////////////
// Class : VrpnDialDevice
// Description : The Panda interface to a VRPN dial device. This
// object will be returned by VrpnClient::make_device(),
// for attaching to a DialNode.
//
// This class does not need to be exported from the DLL.
////////////////////////////////////////////////////////////////////
class VrpnDialDevice : public ClientDialDevice {
public:
VrpnDialDevice(VrpnClient *client, const string &device_name,
VrpnDial *vrpn_dial);
virtual ~VrpnDialDevice();
INLINE VrpnDial *get_vrpn_dial() const;
private:
VrpnDial *_vrpn_dial;
public:
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
ClientDialDevice::init_type();
register_type(_type_handle, "VrpnDialDevice",
ClientDialDevice::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 VrpnDial;
};
#include "vrpnDialDevice.I"
#endif