*** empty log message ***

This commit is contained in:
David Rose 2001-02-06 19:56:17 +00:00
parent 632c90daac
commit 979b4096e6
54 changed files with 1303 additions and 757 deletions

View File

@ -13,6 +13,7 @@
#include <buttonHandle.h>
#include <buttonEvent.h>
#include <buttonEventDataAttribute.h>
#include <pointerTo.h>
////////////////////////////////////////////////////////////////////
// Class : ClientButtonDevice

View File

@ -18,7 +18,6 @@
////////////////////////////////////////////////////////////////////
TypeHandle MouseAndKeyboard::_type_handle;
TypeHandle MouseAndKeyboard::_mods_type;
TypeHandle MouseAndKeyboard::_pixel_xyz_type;
TypeHandle MouseAndKeyboard::_xyz_type;
TypeHandle MouseAndKeyboard::_button_events_type;
@ -35,17 +34,14 @@ MouseAndKeyboard(GraphicsWindow *window, int device, const string& name) :
_window(window),
_device(device)
{
_mods = new ModifierButtonDataAttribute();
_pixel_xyz = new Vec3DataAttribute(LPoint3f(0, 0, 0));
_xyz = new Vec3DataAttribute(LPoint3f(0, 0, 0));
_button_events = new ButtonEventDataAttribute();
_got_mouse_attrib.set_attribute(_mods_type, _mods);
_got_mouse_attrib.set_attribute(_pixel_xyz_type, _pixel_xyz);
_got_mouse_attrib.set_attribute(_xyz_type, _xyz);
_got_mouse_attrib.set_attribute(_button_events_type, _button_events);
_no_mouse_attrib.set_attribute(_mods_type, _mods);
_no_mouse_attrib.set_attribute(_button_events_type, _button_events);
}
@ -63,9 +59,6 @@ transmit_data(NodeAttributes &data) {
_button_events->push_back(be);
}
// Get modifier buttons
_mods->set_mods(_window->get_modifier_buttons(_device));
if (_window->has_pointer(_device)) {
const MouseData &mdata = _window->get_mouse_data(_device);
@ -105,9 +98,6 @@ init_type() {
register_type(_type_handle, "MouseAndKeyboard",
DataNode::get_class_type());
ModifierButtonDataTransition::init_type();
register_data_transition(_mods_type, "ModifierButtons",
ModifierButtonDataTransition::get_class_type());
Vec3DataTransition::init_type();
register_data_transition(_pixel_xyz_type, "PixelXYZ",
Vec3DataTransition::get_class_type());

View File

@ -12,8 +12,6 @@
#include <pandabase.h>
#include <dataNode.h>
#include <modifierButtonDataTransition.h>
#include <modifierButtonDataAttribute.h>
#include <vec3DataTransition.h>
#include <vec3DataAttribute.h>
#include <buttonEventDataTransition.h>
@ -57,7 +55,6 @@ public:
public:
NodeAttributes _got_mouse_attrib;
NodeAttributes _no_mouse_attrib;
PT(ModifierButtonDataAttribute) _mods;
PT(Vec3DataAttribute) _pixel_xyz;
PT(Vec3DataAttribute) _xyz;
PT(ButtonEventDataAttribute) _button_events;

View File

@ -11,7 +11,9 @@
buttonEventDataAttribute.h buttonEventDataTransition.I \
buttonEventDataTransition.cxx buttonEventDataTransition.h \
config_dgraph.cxx config_dgraph.h dataGraphTraversal.cxx \
dataGraphTraversal.h dataNode.cxx dataNode.h dataRelation.I \
dataGraphTraversal.h \
dataGraphTraverser.I dataGraphTraverser.cxx dataGraphTraverser.h \
dataNode.cxx dataNode.h dataRelation.I \
dataRelation.N dataRelation.cxx dataRelation.h \
describe_data_verbose.cxx describe_data_verbose.h \
doubleDataAttribute.I doubleDataAttribute.cxx doubleDataAttribute.h \
@ -24,9 +26,6 @@
intDataTransition.h matrixDataAttribute.I matrixDataAttribute.cxx \
matrixDataAttribute.h matrixDataTransition.I \
matrixDataTransition.cxx matrixDataTransition.h \
modifierButtonDataAttribute.I modifierButtonDataAttribute.cxx \
modifierButtonDataAttribute.h modifierButtonDataTransition.I \
modifierButtonDataTransition.cxx modifierButtonDataTransition.h \
vec3DataAttribute.I vec3DataAttribute.cxx vec3DataAttribute.h \
vec3DataTransition.I vec3DataTransition.cxx vec3DataTransition.h \
vec4DataAttribute.I vec4DataAttribute.cxx vec4DataAttribute.h \
@ -35,7 +34,8 @@
#define INSTALL_HEADERS \
buttonEventDataAttribute.I buttonEventDataAttribute.h \
buttonEventDataTransition.I buttonEventDataTransition.h \
dataGraphTraversal.h dataNode.h dataRelation.I dataRelation.h \
dataGraphTraversal.h \
dataNode.h dataRelation.I dataRelation.h \
describe_data_verbose.h doubleDataAttribute.I doubleDataAttribute.h \
doubleDataTransition.I doubleDataTransition.h \
doublePtrDataAttribute.I doublePtrDataAttribute.h \
@ -43,8 +43,6 @@
intDataAttribute.I intDataAttribute.h intDataTransition.I \
intDataTransition.h matrixDataAttribute.I matrixDataAttribute.h \
matrixDataTransition.I matrixDataTransition.h \
modifierButtonDataAttribute.I modifierButtonDataAttribute.h \
modifierButtonDataTransition.I modifierButtonDataTransition.h \
numericDataAttribute.I numericDataAttribute.h \
numericDataTransition.I numericDataTransition.h \
pointerDataAttribute.I pointerDataAttribute.h \

View File

@ -7,12 +7,27 @@
#include "buttonEventDataTransition.h"
#include <indent.h>
#include <modifierButtons.h>
#include <algorithm>
TypeHandle ButtonEventDataAttribute::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: ButtonEventDataAttribute::update_mods
// Access: Public
// Description: Updates the indicated ModifierButtons object with all
// of the button up/down transitions indicated in the
// queue.
////////////////////////////////////////////////////////////////////
void ButtonEventDataAttribute::
update_mods(ModifierButtons &mods) const {
Buttons::const_iterator bi;
for (bi = _buttons.begin(); bi != _buttons.end(); ++bi) {
mods.add_event(*bi);
}
}
////////////////////////////////////////////////////////////////////
// Function: ButtonEventDataAttribute::make_copy
// Access: Public, Virtual
@ -43,6 +58,38 @@ get_handle() const {
return ButtonEventDataTransition::get_class_type();
}
////////////////////////////////////////////////////////////////////
// Function: ButtonEventDataAttribute::merge
// Access: Public, Virtual
// Description: Attempts to merge this attribute with the other one,
// if that makes sense to do. Returns a new
// NodeAttribute pointer that represents the merge, or
// if the merge is not possible, returns the "other"
// pointer unchanged (which is the result of the merge).
////////////////////////////////////////////////////////////////////
NodeAttribute *ButtonEventDataAttribute::
merge(const NodeAttribute *other) const {
const ButtonEventDataAttribute *oa;
DCAST_INTO_R(oa, other, NULL);
if (_buttons.empty()) {
return (ButtonEventDataAttribute *)oa;
} else if (oa->_buttons.empty()) {
return (ButtonEventDataAttribute *)this;
} else {
// We have to create a new data attribute that includes both sets
// of buttons.
ButtonEventDataAttribute *new_attrib =
new ButtonEventDataAttribute(*this);
new_attrib->_buttons.insert(new_attrib->_buttons.end(),
oa->_buttons.begin(), oa->_buttons.end());
return new_attrib;
}
}
////////////////////////////////////////////////////////////////////
// Function: ButtonEventDataAttribute::output
// Access: Public, Virtual

View File

@ -14,6 +14,7 @@
#include <vector>
class ButtonEventDataTransition;
class ModifierButtons;
////////////////////////////////////////////////////////////////////
// Class : ButtonEventDataAttribute
@ -42,12 +43,16 @@ public:
INLINE void clear();
INLINE void push_back(const ButtonEvent &event);
void update_mods(ModifierButtons &mods) const;
public:
virtual NodeAttribute *make_copy() const;
virtual NodeAttribute *make_initial() const;
virtual TypeHandle get_handle() const;
virtual NodeAttribute *merge(const NodeAttribute *other) const;
virtual void output(ostream &out) const;
virtual void write(ostream &out, int indent_level = 0) const;

View File

@ -16,9 +16,6 @@
#include "matrixDataAttribute.h"
#include "buttonEventDataTransition.h"
#include "buttonEventDataAttribute.h"
#include "modifierButtonDataTransition.h"
#include "modifierButtonDataAttribute.h"
#include "dataGraphTraversal.h"
#include <dconfig.h>
@ -38,9 +35,6 @@ ConfigureFn(config_dgraph) {
MatrixDataAttribute::init_type();
ButtonEventDataTransition::init_type();
ButtonEventDataAttribute::init_type();
ModifierButtonDataTransition::init_type();
ModifierButtonDataAttribute::init_type();
DataGraphTraversal::init_spam_flag();
DataRelation::register_with_factory();
}

View File

@ -4,82 +4,7 @@
////////////////////////////////////////////////////////////////////
#include "dataGraphTraversal.h"
#include "dataNode.h"
#include "dataRelation.h"
#include "intDataTransition.h"
#include "intDataAttribute.h"
#include "config_dgraph.h"
#include "describe_data_verbose.h"
#include <renderRelation.h>
#include <dftraverser.h>
#include <node.h>
#include <typeHandle.h>
// Here's the static member of DataGraphTraversal.
TypeHandle DataGraphTraversal::_spam_flag_type;
////////////////////////////////////////////////////////////////////
// Function: DataGraphTraversal::init_spam_flag
// Access: Public, Static
// Description: This function is called during static
// initialization and registers a convenient type handle
// for the spam flag.
////////////////////////////////////////////////////////////////////
void DataGraphTraversal::
init_spam_flag() {
// We shouldn't try to call this function more than once. This
// function is only to be called during static initialization.
nassertv(_spam_flag_type == TypeHandle::none());
IntDataTransition::init_type();
register_type(_spam_flag_type, "SpamFlagTransition",
IntDataTransition::get_class_type());
}
////////////////////////////////////////////////////////////////////
// Function: DataGraphVisitor::reached_node
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
bool DataGraphVisitor::
reached_node(Node *node, AllAttributesWrapper &state, NullLevelState &) {
// Is the spam flag set?
bool has_spam_flag =
state.has_attribute(DataGraphTraversal::_spam_flag_type);
if (has_spam_flag && dgraph_cat.is_info()) {
dgraph_cat.info() << "Sending into " << *node << " {\n";
describe_data_verbose(dgraph_cat.info(false), state.get_attributes(), 2);
dgraph_cat.info(false) << "}\n";
}
if (node->is_of_type(DataNode::get_class_type())) {
DataNode *dnode = DCAST(DataNode, node);
// Now let the data node process the data itself.
dnode->transmit_data(state.get_attributes());
if (dnode->get_spam_mode() && !has_spam_flag) {
// If the node we pass through has the spam flag set, then we'll
// set it on our current state, and insist that it gets through
// to all our children.
state.set_attribute(DataGraphTraversal::_spam_flag_type,
new IntDataAttribute);
has_spam_flag = true;
}
}
if (has_spam_flag && !node->_children.empty() &&
dgraph_cat.is_info()) {
dgraph_cat.info() << "Receiving from " << *node << " {\n";
describe_data_verbose(dgraph_cat.info(false), state.get_attributes(), 2);
dgraph_cat.info(false) << "}\n";
}
return true;
}
#include "dataGraphTraverser.h"
////////////////////////////////////////////////////////////////////
@ -90,7 +15,6 @@ reached_node(Node *node, AllAttributesWrapper &state, NullLevelState &) {
// downwards.
////////////////////////////////////////////////////////////////////
void traverse_data_graph(Node *root) {
DataGraphVisitor dgv;
df_traverse(root, dgv, AllAttributesWrapper(),
NullLevelState(), DataRelation::get_class_type());
DataGraphTraverser dgt;
dgt.traverse(root);
}

View File

@ -17,46 +17,12 @@
// This is the main interface to the data graph. Traversing the data
// graph transmits data down the graph--reading data from devices and
// sending it to the DataNodes that want it.
//
////////////////////////////////////////////////////////////////////
#include <pandabase.h>
#include <traverserVisitor.h>
#include <allTransitionsWrapper.h>
#include <allAttributesWrapper.h>
#include <nullLevelState.h>
////////////////////////////////////////////////////////////////////
// Class : DataGraphTraversal
// Description : This is mainly a holder for the static
// _spam_flag_type TypeHandle, which is a registered
// NumericDataAttribute that keeps track of the state of
// the spam flag during data graph traversal. The class
// otherwise doesn't do anything useful, but see the
// traverse_data_graph() function, below.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA DataGraphTraversal {
public:
static void init_spam_flag();
static TypeHandle _spam_flag_type;
};
////////////////////////////////////////////////////////////////////
// Class : DataGraphVisitor
// Description : The TraverserVisitor to handle data graph traversals.
// This manages the spam flag, and may eventually handle
// merging of data from different parents into a single
// node.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA DataGraphVisitor :
public TraverserVisitor<AllTransitionsWrapper, NullLevelState> {
public:
bool reached_node(Node *node, AllAttributesWrapper &state, NullLevelState &);
};
class Node;
////////////////////////////////////////////////////////////////////
// Function: traverse_data_graph

View File

@ -0,0 +1,46 @@
// Filename: dataGraphTraverser.I
// Created by: drose (05Feb01)
//
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: DataGraphTraverser::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE DataGraphTraverser::
DataGraphTraverser() {
}
////////////////////////////////////////////////////////////////////
// Function: DataGraphTraverser::traverse
// Access: Public
// Description: Fires off the traversal, beginning at the indicated
// node.
////////////////////////////////////////////////////////////////////
INLINE void DataGraphTraverser::
traverse(Node *node) {
NodeAttributes empty;
r_traverse(node, empty, false);
resume_all();
}
////////////////////////////////////////////////////////////////////
// Function: DataGraphTraverser::traverse_below
// Access: Public
// Description: Fires off the traversal, beginning *below* the
// indicated node. The transmit_data() function is not
// called on the starting node; instead, the indicated
// data attributes are taken as the output of that node.
//
// If the node defines transmit_data_per_child(), that
// function is still called, once for each child as
// usual.
////////////////////////////////////////////////////////////////////
INLINE void DataGraphTraverser::
traverse_below(Node *node, const NodeAttributes &data) {
NodeAttributes copy = data;
r_traverse_below(node, copy, false);
resume_all();
}

View File

@ -0,0 +1,223 @@
// Filename: dataGraphTraverser.cxx
// Created by: drose (05Feb01)
//
////////////////////////////////////////////////////////////////////
#include "dataGraphTraverser.h"
#include "dataRelation.h"
#include "dataNode.h"
#include "config_dgraph.h"
#include "describe_data_verbose.h"
////////////////////////////////////////////////////////////////////
// Function: DataGraphTraverser::r_traverse
// Access: Private
// Description: The recursive implementation of traverse().
////////////////////////////////////////////////////////////////////
void DataGraphTraverser::
r_traverse(Node *node, NodeAttributes &data, bool has_spam_mode) {
DataNode *data_node = (DataNode *)NULL;
if (node->is_of_type(DataNode::get_class_type())) {
DCAST_INTO_V(data_node, node);
#ifndef NDEBUG
has_spam_mode = has_spam_mode || data_node->get_spam_mode();
#endif
}
int num_parents = node->get_num_parents(DataRelation::get_class_type());
if (num_parents > 1) {
// This node is multiply parented, so we must save it for later.
save(node, data, has_spam_mode, num_parents);
} else {
// Now ask the node to transmit its overall data.
if (data_node != (DataNode *)NULL) {
#ifndef NDEBUG
if (has_spam_mode && dgraph_cat.is_info()) {
dgraph_cat.info() << "Sending into " << *node << " {\n";
describe_data_verbose(dgraph_cat.info(false), data, 2);
dgraph_cat.info(false) << "}\n";
} else if (dgraph_cat.is_spam()) {
dgraph_cat.spam() << "Sending into " << *node << " {\n";
describe_data_verbose(dgraph_cat.spam(false), data, 2);
dgraph_cat.spam(false) << "}\n";
}
#endif
data_node->transmit_data(data);
}
r_traverse_below(node, data, has_spam_mode);
}
}
////////////////////////////////////////////////////////////////////
// Function: DataGraphTraverser::r_traverse_below
// Access: Private
// Description: Resumes the traversal below the indicated node, given
// the output from a previous call to
// Node::transmit_data().
////////////////////////////////////////////////////////////////////
void DataGraphTraverser::
r_traverse_below(Node *node, NodeAttributes &data, bool has_spam_mode) {
DataNode *data_node = (DataNode *)NULL;
if (node->is_of_type(DataNode::get_class_type())) {
DCAST_INTO_V(data_node, node);
#ifndef NDEBUG
has_spam_mode = has_spam_mode || data_node->get_spam_mode();
#endif
}
int num_children = node->get_num_children(DataRelation::get_class_type());
if (num_children > 0) {
// For the first n - 1 children we need to make a copy of our
// NodeAttributes for each one--this allows our children to modify
// the set freely without affecting its siblings.
for (int i = 0; i < num_children - 1; i++) {
NodeAttributes copy = data;
if (data_node != (DataNode *)NULL) {
data_node->transmit_data_per_child(copy, i);
}
NodeRelation *arc =
node->get_child(DataRelation::get_class_type(), i);
r_traverse(arc->get_child(), copy, has_spam_mode);
}
// For the last child, we don't have to bother making a copy since
// no one cares any more. This is a slight optimization.
if (data_node != (DataNode *)NULL) {
data_node->transmit_data_per_child(data, num_children - 1);
}
NodeRelation *arc =
node->get_child(DataRelation::get_class_type(), num_children - 1);
if (dgraph_cat.is_spam()) {
dgraph_cat.spam() << "Traversing " << *arc << "\n";
}
r_traverse(arc->get_child(), data, has_spam_mode);
}
}
////////////////////////////////////////////////////////////////////
// Function: DataGraphTraverser::save
// Access: Private
// Description: Saves the current state for later, until we have
// extracted the data from all the parents of this node.
// When the last parent is accounted for, resumes the
// traversal for this node and removes it from the saved
// queue.
////////////////////////////////////////////////////////////////////
void DataGraphTraverser::
save(Node *node, const NodeAttributes &data, bool has_spam_mode,
int num_parents) {
States::iterator si;
si = _saved_states.find(node);
if (si != _saved_states.end()) {
SavedState &state = (*si).second;
state._data.merge_from(state._data, data);
state._has_spam_mode = state._has_spam_mode || has_spam_mode;
state._num_parents_so_far++;
if (dgraph_cat.is_spam()) {
dgraph_cat.spam()
<< "Encountered " << *node << " with " << num_parents
<< " parents; " << state._num_parents_so_far
<< " processed so far.\n";
}
nassertv(state._num_parents_so_far <= num_parents);
if (state._num_parents_so_far == num_parents) {
// All parents are accounted for, so resume traversal!
resume(node, state);
_saved_states.erase(si);
}
return;
}
// This node has not been encountered before, so save an entry for
// it.
if (dgraph_cat.is_spam()) {
dgraph_cat.spam()
<< "Encountered " << *node << " with " << num_parents
<< " parents.\n";
}
SavedState &state = _saved_states[node];
state._data = data;
state._has_spam_mode = has_spam_mode;
state._num_parents_so_far = 1;
}
////////////////////////////////////////////////////////////////////
// Function: DataGraphTraverser::resume
// Access: Private
// Description: Resumes traversal from a previously-saved state.
////////////////////////////////////////////////////////////////////
void DataGraphTraverser::
resume(Node *node, DataGraphTraverser::SavedState &state) {
DataNode *data_node = (DataNode *)NULL;
if (node->is_of_type(DataNode::get_class_type())) {
DCAST_INTO_V(data_node, node);
#ifndef NDEBUG
if (state._has_spam_mode && dgraph_cat.is_info()) {
dgraph_cat.info() << "Sending into " << *node << " {\n";
describe_data_verbose(dgraph_cat.info(false), state._data, 2);
dgraph_cat.info(false) << "}\n";
} else if (dgraph_cat.is_spam()) {
dgraph_cat.spam() << "Sending into " << *node << " {\n";
describe_data_verbose(dgraph_cat.spam(false), state._data, 2);
dgraph_cat.spam(false) << "}\n";
}
#endif
data_node->transmit_data(state._data);
}
r_traverse_below(node, state._data, state._has_spam_mode);
}
////////////////////////////////////////////////////////////////////
// Function: DataGraphTraverser::resume_all
// Access: Private
// Description: Called after the traversal has completed, this
// resumes all of the unresumed saved states. There
// shouldn't actually be any such things, unless a node
// is multiply parented to a node outside of the data
// graph.
////////////////////////////////////////////////////////////////////
void DataGraphTraverser::
resume_all() {
while (!_saved_states.empty()) {
States::iterator si = _saved_states.begin();
Node *node = (*si).first;
SavedState &state = (*si).second;
dgraph_cat.warning()
<< *node << " is parented both inside and outside of the data graph:\n";
int num_parents = node->get_num_parents(DataRelation::get_class_type());
for (int i = 0; i < num_parents; i++) {
NodeRelation *arc = node->get_parent(DataRelation::get_class_type(), i);
dgraph_cat.warning(false)
<< " " << *arc << "\n";
}
resume(node, state);
_saved_states.erase(si);
}
}

View File

@ -0,0 +1,55 @@
// Filename: dataGraphTraverser.h
// Created by: drose (05Feb01)
//
////////////////////////////////////////////////////////////////////
#ifndef DATAGRAPHTRAVERSER_H
#define DATAGRAPHTRAVERSER_H
#include <pandabase.h>
#include <nodeAttributes.h>
class Node;
////////////////////////////////////////////////////////////////////
// Class : DataGraphTraverser
// Description : This class manages the traversal of the data graph,
// so that all data attributes generated by nodes in the
// graph are transmitted to nodes below them.
//
// A bit of logic is employed to ensure that if a node
// is assigned to two parents, the data from both
// parents is merged before passing it to the child.
//
// This class need not be exported from PANDA.DLL.
////////////////////////////////////////////////////////////////////
class DataGraphTraverser {
public:
INLINE DataGraphTraverser();
INLINE void traverse(Node *node);
INLINE void traverse_below(Node *node, const NodeAttributes &data);
private:
class SavedState {
public:
NodeAttributes _data;
bool _has_spam_mode;
int _num_parents_so_far;
};
void r_traverse(Node *node, NodeAttributes &data, bool has_spam_mode);
void r_traverse_below(Node *node, NodeAttributes &data, bool has_spam_mode);
void save(Node *node, const NodeAttributes &data, bool has_spam_mode,
int num_parents);
void resume(Node *node, SavedState &state);
void resume_all();
typedef map<Node *, SavedState> States;
States _saved_states;
};
#include "dataGraphTraverser.I"
#endif

View File

@ -16,6 +16,23 @@ DataNode::
DataNode(const string &name) : NamedNode(name) {
_spam_mode = false;
}
////////////////////////////////////////////////////////////////////
// Function: DataNode::transmit_data_per_child
// Access: Public, Virtual
// Description: Should be overridden in a derived class that wants to
// send a different data stream to each child.
// Normally, a node only overrides transmit_data(),
// which takes a set of input data attributes and
// generates a set of output data attributes. A node
// may also override transmit_data_per_child(), which is
// called after transmit_data(), once per child; this
// function may be used to send individual data
// attributes to each child.
////////////////////////////////////////////////////////////////////
void DataNode::
transmit_data_per_child(NodeAttributes &, int) {
}
////////////////////////////////////////////////////////////////////
// Function: DataNode::set_spam_mode

View File

@ -70,6 +70,9 @@ public:
virtual void
transmit_data(NodeAttributes &data)=0;
virtual void
transmit_data_per_child(NodeAttributes &data, int child_index);
PUBLISHED:
void set_spam_mode(bool flag);
bool get_spam_mode() const;

View File

@ -26,35 +26,32 @@ describe_data_verbose(ostream &out, const NodeAttributes &state,
NodeAttributes::const_iterator nai;
for (nai = state.begin(); nai != state.end(); ++nai) {
// We'll exclude the spam flag. No one wants to see that.
TypeHandle type = (*nai).first;
if (type != DataGraphTraversal::_spam_flag_type) {
const PT(NodeAttribute) &attrib = (*nai).second;
if (attrib != (NodeAttribute *)NULL) {
// Now extract the type name out of the type flag.
string actual_name = type.get_name();
string::size_type underscore = actual_name.rfind('_');
string name;
if (underscore == string::npos) {
// There was no underscore, so this name wasn't created via
// register_data_transition(). Huh. Well, that's legitimate
// (if unexpected), so just print the whole name.
name = actual_name;
} else {
// Assume that, if the name was created via
// register_data_transition(), the original name was the part
// before the last underscore.
name = actual_name.substr(0, underscore);
}
indent(out, indent_level) << name;
if ((int)name.length() < data_indent_level) {
indent(out, data_indent_level - name.length());
} else {
out << " ";
}
out << *attrib << "\n";
const PT(NodeAttribute) &attrib = (*nai).second;
if (attrib != (NodeAttribute *)NULL) {
// Now extract the type name out of the type flag.
TypeHandle type = (*nai).first;
string actual_name = type.get_name();
string::size_type underscore = actual_name.rfind('_');
string name;
if (underscore == string::npos) {
// There was no underscore, so this name wasn't created via
// register_data_transition(). Huh. Well, that's legitimate
// (if unexpected), so just print the whole name.
name = actual_name;
} else {
// Assume that, if the name was created via
// register_data_transition(), the original name was the part
// before the last underscore.
name = actual_name.substr(0, underscore);
}
indent(out, indent_level) << name;
if ((int)name.length() < data_indent_level) {
indent(out, data_indent_level - name.length());
} else {
out << " ";
}
out << *attrib << "\n";
}
}
}

View File

@ -1,56 +0,0 @@
// Filename: modifierButtonDataAttribute.I
// Created by: drose (27Mar00)
//
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: ModifierButtonDataAttribute::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE ModifierButtonDataAttribute::
ModifierButtonDataAttribute() {
}
////////////////////////////////////////////////////////////////////
// Function: ModifierButtonDataAttribute::Copy Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE ModifierButtonDataAttribute::
ModifierButtonDataAttribute(const ModifierButtonDataAttribute &copy) :
NodeAttribute(copy),
_mods(copy._mods)
{
}
////////////////////////////////////////////////////////////////////
// Function: ModifierButtonDataAttribute::Copy Assignment Operator
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE void ModifierButtonDataAttribute::
operator = (const ModifierButtonDataAttribute &copy) {
NodeAttribute::operator = (copy);
_mods = copy._mods;
}
////////////////////////////////////////////////////////////////////
// Function: ModifierButtonDataAttribute::set_mods
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE void ModifierButtonDataAttribute::
set_mods(const ModifierButtons &mods) {
_mods = mods;
}
////////////////////////////////////////////////////////////////////
// Function: ModifierButtonDataAttribute::set_mods
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE const ModifierButtons &ModifierButtonDataAttribute::
get_mods() const {
return _mods;
}

View File

@ -1,78 +0,0 @@
// Filename: modifierButtonDataAttribute.cxx
// Created by: drose (27Mar00)
//
////////////////////////////////////////////////////////////////////
#include "modifierButtonDataAttribute.h"
#include "modifierButtonDataTransition.h"
#include <indent.h>
TypeHandle ModifierButtonDataAttribute::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: ModifierButtonDataAttribute::make_copy
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
NodeAttribute *ModifierButtonDataAttribute::
make_copy() const {
return new ModifierButtonDataAttribute(*this);
}
////////////////////////////////////////////////////////////////////
// Function: ModifierButtonDataAttribute::make_initial
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
NodeAttribute *ModifierButtonDataAttribute::
make_initial() const {
return new ModifierButtonDataAttribute;
}
////////////////////////////////////////////////////////////////////
// Function: ModifierButtonDataAttribute::get_handle
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
TypeHandle ModifierButtonDataAttribute::
get_handle() const {
return ModifierButtonDataTransition::get_class_type();
}
////////////////////////////////////////////////////////////////////
// Function: ModifierButtonDataAttribute::output
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
void ModifierButtonDataAttribute::
output(ostream &out) const {
out << _mods;
}
////////////////////////////////////////////////////////////////////
// Function: ModifierButtonDataAttribute::write
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
void ModifierButtonDataAttribute::
write(ostream &out, int indent_level) const {
indent(out, indent_level) << _mods << "\n";
}
////////////////////////////////////////////////////////////////////
// Function: ModifierButtonDataAttribute::internal_compare_to
// Access: Protected, Virtual
// Description:
////////////////////////////////////////////////////////////////////
int ModifierButtonDataAttribute::
internal_compare_to(const NodeAttribute *other) const {
const ModifierButtonDataAttribute *ot;
DCAST_INTO_R(ot, other, false);
if (_mods != ot->_mods) {
return (_mods < ot->_mods) ? -1 : 1;
}
return 0;
}

View File

@ -1,68 +0,0 @@
// Filename: modifierButtonDataAttribute.h
// Created by: drose (27Mar00)
//
////////////////////////////////////////////////////////////////////
#ifndef MODIFIERBUTTONDATAATTRIBUTE_H
#define MODIFIERBUTTONDATAATTRIBUTE_H
#include <pandabase.h>
#include <nodeAttribute.h>
#include <modifierButtons.h>
class ModifierButtonDataTransition;
////////////////////////////////////////////////////////////////////
// Class : ModifierButtonDataAttribute
// Description : This data graph attribute stores the current state of
// some various modifier buttons (e.g. shift, control,
// alt, and the mouse buttons), as generated for
// instance by a GraphicsWindow.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA ModifierButtonDataAttribute : public NodeAttribute {
public:
INLINE ModifierButtonDataAttribute();
INLINE ModifierButtonDataAttribute(const ModifierButtonDataAttribute &copy);
INLINE void operator = (const ModifierButtonDataAttribute &copy);
public:
INLINE void set_mods(const ModifierButtons &mods);
INLINE const ModifierButtons &get_mods() const;
virtual NodeAttribute *make_copy() const;
virtual NodeAttribute *make_initial() const;
virtual TypeHandle get_handle() const;
virtual void output(ostream &out) const;
virtual void write(ostream &out, int indent_level = 0) const;
protected:
virtual int internal_compare_to(const NodeAttribute *other) const;
private:
ModifierButtons _mods;
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() {
NodeAttribute::init_type();
register_type(_type_handle, "ModifierButtonDataAttribute",
NodeAttribute::get_class_type());
}
private:
static TypeHandle _type_handle;
friend class ModifierButtonDataTransition;
};
#include "modifierButtonDataAttribute.I"
#endif

View File

@ -1,34 +0,0 @@
// Filename: modifierButtonDataTransition.I
// Created by: drose (27Mar00)
//
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: ModifierButtonDataTransition::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE ModifierButtonDataTransition::
ModifierButtonDataTransition() {
}
////////////////////////////////////////////////////////////////////
// Function: ModifierButtonDataTransition::Copy Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE ModifierButtonDataTransition::
ModifierButtonDataTransition(const ModifierButtonDataTransition &copy) :
NodeTransition(copy)
{
}
////////////////////////////////////////////////////////////////////
// Function: ModifierButtonDataTransition::Copy Assignment Operator
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE void ModifierButtonDataTransition::
operator = (const ModifierButtonDataTransition &copy) {
NodeTransition::operator = (copy);
}

View File

@ -1,80 +0,0 @@
// Filename: modifierButtonDataTransition.cxx
// Created by: drose (01Mar00)
//
////////////////////////////////////////////////////////////////////
#include "modifierButtonDataTransition.h"
#include "modifierButtonDataAttribute.h"
TypeHandle ModifierButtonDataTransition::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: ModifierButtonDataTransition::make_copy
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
NodeTransition *ModifierButtonDataTransition::
make_copy() const {
return new ModifierButtonDataTransition(*this);
}
////////////////////////////////////////////////////////////////////
// Function: ModifierButtonDataTransition::make_attrib
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
NodeAttribute *ModifierButtonDataTransition::
make_attrib() const {
return new ModifierButtonDataAttribute;
}
////////////////////////////////////////////////////////////////////
// Function: ModifierButtonDataTransition::compose
// Access: Public, Virtual
// Description: Returns a new transition that corresponds to the
// composition of this transition with the second
// transition (which must be of an equivalent type).
// This may return the same pointer as either source
// transition. Applying the transition returned from
// this function to an attribute attribute will produce
// the same effect as applying each transition
// separately.
////////////////////////////////////////////////////////////////////
NodeTransition *ModifierButtonDataTransition::
compose(const NodeTransition *) const {
return NULL;
}
////////////////////////////////////////////////////////////////////
// Function: ModifierButtonDataTransition::invert
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
NodeTransition *ModifierButtonDataTransition::
invert() const {
return NULL;
}
////////////////////////////////////////////////////////////////////
// Function: ModifierButtonDataTransition::apply
// Access: Public, Virtual
// Description: Returns a new attribute (or possibly the same
// attribute) that represents the effect of applying this
// indicated transition to the indicated attribute. The
// source attribute may be NULL, indicating the initial
// attribute.
////////////////////////////////////////////////////////////////////
NodeAttribute *ModifierButtonDataTransition::
apply(const NodeAttribute *attrib) const {
return (NodeAttribute *)attrib;
}
////////////////////////////////////////////////////////////////////
// Function: ModifierButtonDataTransition::internal_compare_to
// Access: Protected, Virtual
// Description:
////////////////////////////////////////////////////////////////////
int ModifierButtonDataTransition::
internal_compare_to(const NodeTransition *) const {
return 0;
}

View File

@ -1,54 +0,0 @@
// Filename: modifierButtonDataTransition.h
// Created by: drose (01Mar00)
//
////////////////////////////////////////////////////////////////////
#ifndef MODIFIERBUTTONDATATRANSITION_H
#define MODIFIERBUTTONDATATRANSITION_H
#include <pandabase.h>
#include <nodeTransition.h>
////////////////////////////////////////////////////////////////////
// Class : ModifierButtonDataTransition
// Description :
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA ModifierButtonDataTransition : public NodeTransition {
public:
INLINE ModifierButtonDataTransition();
INLINE ModifierButtonDataTransition(const ModifierButtonDataTransition &copy);
INLINE void operator = (const ModifierButtonDataTransition &copy);
public:
virtual NodeTransition *make_copy() const;
virtual NodeAttribute *make_attrib() const;
virtual NodeTransition *compose(const NodeTransition *other) const;
virtual NodeTransition *invert() const;
virtual NodeAttribute *apply(const NodeAttribute *attrib) const;
protected:
virtual int internal_compare_to(const NodeTransition *other) const;
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() {
NodeTransition::init_type();
register_type(_type_handle, "ModifierButtonDataTransition",
NodeTransition::get_class_type());
}
private:
static TypeHandle _type_handle;
};
#include "modifierButtonDataTransition.I"
#endif

View File

@ -134,34 +134,6 @@ has_keyboard(int device) const {
return _input_devices[device].has_keyboard();
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsWindow::get_modifier_buttons
// Access: Public
// Description: Returns the set of ModifierButtons currently being
// monitored for the nth input device.
////////////////////////////////////////////////////////////////////
INLINE const ModifierButtons &GraphicsWindow::
get_modifier_buttons(int device) const {
nassertr(device >= 0 && device < (int)_input_devices.size(),
*(new ModifierButtons));
return _input_devices[device].get_modifier_buttons();
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsWindow::set_modifier_buttons
// Access: Public
// Description: Changes the set of ModifierButtons that will be
// monitored for the nth input device. It is
// recommended that you first retrieve the existing set
// via get_modifier_buttons(), so that any current
// button state will not be lost.
////////////////////////////////////////////////////////////////////
INLINE void GraphicsWindow::
set_modifier_buttons(int device, const ModifierButtons &mods) {
nassertv(device >= 0 && device < (int)_input_devices.size());
_input_devices[device].set_modifier_buttons(mods);
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsWindow::get_mouse_data
// Access: Public

View File

@ -133,9 +133,6 @@ PUBLISHED:
INLINE bool has_pointer(int device) const;
INLINE bool has_keyboard(int device) const;
INLINE const ModifierButtons &get_modifier_buttons(int device) const;
INLINE void set_modifier_buttons(int device, const ModifierButtons &mods);
public:
INLINE const MouseData &get_mouse_data(int device) const;
INLINE bool has_button_event(int device) const;

View File

@ -44,31 +44,6 @@ get_mouse_data() const {
return _mouse_data;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsWindowInputDevice::get_modifier_buttons
// Access: Public
// Description: Returns the set of ModifierButtons currently being
// monitored for the nth input device.
////////////////////////////////////////////////////////////////////
INLINE const ModifierButtons &GraphicsWindowInputDevice::
get_modifier_buttons() const {
return _mods;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsWindowInputDevice::set_modifier_buttons
// Access: Public
// Description: Changes the set of ModifierButtons that will be
// monitored for the nth input device. It is
// recommended that you first retrieve the existing set
// via get_modifier_buttons(), so that any current
// button state will not be lost.
////////////////////////////////////////////////////////////////////
INLINE void GraphicsWindowInputDevice::
set_modifier_buttons(const ModifierButtons &mods) {
_mods = mods;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsWindowInputDevice::set_pointer_in_window
// Access: Public

View File

@ -29,16 +29,6 @@ GraphicsWindowInputDevice(const string &name, int flags) :
_name(name),
_flags(flags)
{
// We'll define the mouse buttons and the traditional modifier keys
// as the default modifiers. Individual GraphicsWindows can change
// this if they want.
_mods.add_button(MouseButton::one());
_mods.add_button(MouseButton::two());
_mods.add_button(MouseButton::three());
_mods.add_button(KeyboardButton::shift());
_mods.add_button(KeyboardButton::control());
_mods.add_button(KeyboardButton::alt());
}
////////////////////////////////////////////////////////////////////
@ -85,7 +75,6 @@ GraphicsWindowInputDevice(const GraphicsWindowInputDevice &copy) :
_name(copy._name),
_flags(copy._flags),
_mouse_data(copy._mouse_data),
_mods(copy._mods),
_button_events(copy._button_events)
{
}
@ -100,7 +89,6 @@ operator = (const GraphicsWindowInputDevice &copy) {
_name = copy._name;
_flags = copy._flags;
_mouse_data = copy._mouse_data;
_mods = copy._mods;
_button_events = copy._button_events;
}
@ -147,8 +135,7 @@ get_button_event() {
////////////////////////////////////////////////////////////////////
void GraphicsWindowInputDevice::
button_down(ButtonHandle button) {
_button_events.push_back(ButtonEvent(button, true, _mods));
_mods.button_down(button);
_button_events.push_back(ButtonEvent(button, true));
}
////////////////////////////////////////////////////////////////////
@ -158,6 +145,5 @@ button_down(ButtonHandle button) {
////////////////////////////////////////////////////////////////////
void GraphicsWindowInputDevice::
button_up(ButtonHandle button) {
_mods.button_up(button);
_button_events.push_back(ButtonEvent(button, false, _mods));
_button_events.push_back(ButtonEvent(button, false));
}

View File

@ -10,7 +10,6 @@
#include <buttonEvent.h>
#include <mouseData.h>
#include <modifierButtons.h>
#include <deque>
#include <vector>
@ -41,8 +40,6 @@ public:
INLINE bool has_keyboard() const;
INLINE const MouseData &get_mouse_data() const;
INLINE const ModifierButtons &get_modifier_buttons() const;
INLINE void set_modifier_buttons(const ModifierButtons &mods);
bool has_button_event() const;
ButtonEvent get_button_event();
@ -73,7 +70,6 @@ private:
string _name;
int _flags;
MouseData _mouse_data;
ModifierButtons _mods;
ButtonEvents _button_events;
};

View File

@ -1048,7 +1048,10 @@ int framework_main(int argc, char *argv[]) {
PT(Transform2SG) tball2cam = new Transform2SG("tball2cam");
tball2cam->set_arc(arc1);
new DataRelation(trackball, tball2cam);
new DataRelation(drive_interface, tball2cam);
PT(Transform2SG) drive2cam = new Transform2SG("drive2cam");
drive2cam->set_arc(arc1);
new DataRelation(drive_interface, drive2cam);
// Create a ButtonThrower to throw events from the keyboard.
PT(ButtonThrower) et = new ButtonThrower("kb-events");

View File

@ -9,6 +9,20 @@
TypeHandle NodeAttribute::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: NodeAttribute::merge
// Access: Public, Virtual
// Description: Attempts to merge this attribute with the other one,
// if that makes sense to do. Returns a new
// NodeAttribute pointer that represents the merge, or
// if the merge is not possible, returns the "other"
// pointer unchanged (which is the result of the merge).
////////////////////////////////////////////////////////////////////
NodeAttribute *NodeAttribute::
merge(const NodeAttribute *other) const {
return (NodeAttribute *)other;
}
////////////////////////////////////////////////////////////////////
// Function: NodeAttribute::output
// Access: Public, Virtual

View File

@ -66,6 +66,8 @@ public:
virtual TypeHandle get_handle() const=0;
virtual NodeAttribute *merge(const NodeAttribute *other) const;
PUBLISHED:
virtual void output(ostream &out) const;
virtual void write(ostream &out, int indent_level = 0) const;

View File

@ -221,6 +221,35 @@ apply_from(const NodeAttributes &other, const NodeTransitionCache &trans) {
}
}
////////////////////////////////////////////////////////////////////
// Function: NodeAttributes::merge_from
// Access: Public
// Description: Computes the union of the two NodeAttributes sets and
// stores the result in this object (which may be the
// same object as either of the two sources). If a
// given attribute is set in both sources (and cannot be
// union sensibly), the one from the second source
// overrides.
////////////////////////////////////////////////////////////////////
void NodeAttributes::
merge_from(const NodeAttributes &a, const NodeAttributes &b) {
if (&a == this && b.is_empty()) {
// Trivial do-nothing case.
} else if (&b == this && a.is_empty()) {
// Trivial do-nothing case.
} else {
Attributes temp;
tmap_merge_union(a._attributes.begin(), a._attributes.end(),
b._attributes.begin(), b._attributes.end(),
inserter(temp, temp.begin()));
_attributes.swap(temp);
}
}
////////////////////////////////////////////////////////////////////
// Function: NodeAttributes::output

View File

@ -68,7 +68,9 @@ public:
void apply_from(const NodeAttributes &other,
const NodeTransitionCache &trans);
public:
void merge_from(const NodeAttributes &a, const NodeAttributes &b);
PUBLISHED:
void output(ostream &out) const;
void write(ostream &out, int indent_level = 0) const;

View File

@ -252,9 +252,9 @@ store_to(const NodeTransitionCache *a, NodeRelation *arc,
// And now actually add them.
NodeTransitions temp;
tmap_union(nt._transitions.begin(), nt._transitions.end(),
a->_cache.begin(), a->_cache.end(),
inserter(temp._transitions, temp._transitions.begin()));
tmap_override_union(nt._transitions.begin(), nt._transitions.end(),
a->_cache.begin(), a->_cache.end(),
inserter(temp._transitions, temp._transitions.begin()));
nt._transitions.swap(temp._transitions);
}
@ -281,9 +281,9 @@ c_union(const NodeTransitionCache *a, const NodeTransitionCache *b) {
// Neither is empty. Build and return a new list.
NodeTransitionCache *result = new NodeTransitionCache;
tmap_union(a->_cache.begin(), a->_cache.end(),
b->_cache.begin(), b->_cache.end(),
inserter(result->_cache, result->_cache.begin()));
tmap_override_union(a->_cache.begin(), a->_cache.end(),
b->_cache.begin(), b->_cache.end(),
inserter(result->_cache, result->_cache.begin()));
return result;
}

View File

@ -170,9 +170,9 @@ clear() {
void NodeTransitions::
copy_transitions_from(const NodeTransitions &other) {
Transitions temp;
tmap_union(_transitions.begin(), _transitions.end(),
other._transitions.begin(), other._transitions.end(),
inserter(temp, temp.begin()));
tmap_override_union(_transitions.begin(), _transitions.end(),
other._transitions.begin(), other._transitions.end(),
inserter(temp, temp.begin()));
_transitions.swap(temp);
}

View File

@ -37,7 +37,7 @@ tmap_get_interest(InputIterator1 first1, InputIterator1 last1,
}
////////////////////////////////////////////////////////////////////
// Function: tmap_union
// Function: tmap_override_union
// Description: Accepts two NodeTransition or NodeAttribute maps, and
// builds a new map which is the union of the first two.
// If an element appears in both maps, the entry from
@ -45,9 +45,9 @@ tmap_get_interest(InputIterator1 first1, InputIterator1 last1,
////////////////////////////////////////////////////////////////////
template<class InputIterator1, class InputIterator2, class OutputIterator>
OutputIterator
tmap_union(InputIterator1 first1, InputIterator1 last1,
InputIterator2 first2, InputIterator2 last2,
OutputIterator result) {
tmap_override_union(InputIterator1 first1, InputIterator1 last1,
InputIterator2 first2, InputIterator2 last2,
OutputIterator result) {
while (first1 != last1 && first2 != last2) {
if ((*first1).first < (*first2).first) {
*result = *first1;
@ -79,6 +79,50 @@ tmap_union(InputIterator1 first1, InputIterator1 last1,
return result;
}
////////////////////////////////////////////////////////////////////
// Function: tmap_merge_union
// Description: Accepts two NodeAttribute maps, and builds a new map
// which is the union of the first two. If an element
// appears in both maps, the two are merged, preferring
// the second.
////////////////////////////////////////////////////////////////////
template<class InputIterator1, class InputIterator2, class OutputIterator>
OutputIterator
tmap_merge_union(InputIterator1 first1, InputIterator1 last1,
InputIterator2 first2, InputIterator2 last2,
OutputIterator result) {
while (first1 != last1 && first2 != last2) {
if ((*first1).first < (*first2).first) {
*result = *first1;
++first1;
++result;
} else if ((*first2).first < (*first1).first) {
*result = *first2;
++first2;
++result;
} else {
PT(NodeAttribute) c = (*first1).second->merge((*first2).second);
*result = pair<TypeHandle, PT(NodeAttribute)>((*first1).first, c);
++first1;
++first2;
++result;
}
}
while (first1 != last1) {
*result = *first1;
++first1;
++result;
}
while (first2 != last2) {
*result = *first2;
++first2;
++result;
}
return result;
}
////////////////////////////////////////////////////////////////////
// Function: tmap_arc_union
// Description: As above, but updates the transitions on the way to

View File

@ -28,19 +28,6 @@ ButtonEvent(ButtonHandle button, bool down) :
{
}
////////////////////////////////////////////////////////////////////
// Function: ButtonEvent::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE ButtonEvent::
ButtonEvent(ButtonHandle button, bool down, ModifierButtons mods) :
_button(button),
_down(down),
_mods(mods)
{
}
////////////////////////////////////////////////////////////////////
// Function: ButtonEvent::Copy Constructor
// Access: Public
@ -49,8 +36,7 @@ ButtonEvent(ButtonHandle button, bool down, ModifierButtons mods) :
INLINE ButtonEvent::
ButtonEvent(const ButtonEvent &copy) :
_button(copy._button),
_down(copy._down),
_mods(copy._mods)
_down(copy._down)
{
}
@ -63,7 +49,6 @@ INLINE void ButtonEvent::
operator = (const ButtonEvent &copy) {
_button = copy._button;
_down = copy._down;
((ModifierButtons &)_mods) = copy._mods;
}
////////////////////////////////////////////////////////////////////
@ -74,8 +59,7 @@ operator = (const ButtonEvent &copy) {
INLINE bool ButtonEvent::
operator == (const ButtonEvent &other) const {
return (_button == other._button &&
_down == other._down &&
_mods == other._mods);
_down == other._down);
}
////////////////////////////////////////////////////////////////////
@ -99,9 +83,5 @@ operator < (const ButtonEvent &other) const {
return _button < other._button;
}
if (_down != other._down) {
return _down < other._down;
}
return _mods < other._mods;
return _down < other._down;
}

View File

@ -18,5 +18,4 @@ output(ostream &out) const {
} else {
out << " up";
}
out << " with " << _mods;
}

View File

@ -9,19 +9,16 @@
#include <pandabase.h>
#include "buttonHandle.h"
#include "modifierButtons.h"
////////////////////////////////////////////////////////////////////
// Class : ButtonEvent
// Description : Records a transition of one button from up to down or
// vice-versa, as well as an optional recording of some
// ModifierButtons that were being tracked at the time.
// vice-versa.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA ButtonEvent {
public:
INLINE ButtonEvent();
INLINE ButtonEvent(ButtonHandle button, bool down);
INLINE ButtonEvent(ButtonHandle button, bool down, ModifierButtons mods);
INLINE ButtonEvent(const ButtonEvent &copy);
INLINE void operator = (const ButtonEvent &copy);
@ -33,7 +30,6 @@ public:
ButtonHandle _button;
bool _down;
const ModifierButtons _mods;
};
INLINE ostream &operator << (ostream &out, const ButtonEvent &be) {

View File

@ -75,6 +75,21 @@ get_button(int index) const {
return _button_list[index];
}
////////////////////////////////////////////////////////////////////
// Function: ModifierButtons::add_event
// Access: Public
// Description: Calls button_down() or button_up(), as appropriate,
// according to the indicated ButtonEvent.
////////////////////////////////////////////////////////////////////
INLINE bool ModifierButtons::
add_event(const ButtonEvent &event) {
if (event._down) {
return button_down(event._button);
} else {
return button_up(event._button);
}
}
////////////////////////////////////////////////////////////////////
// Function: ModifierButtons::is_down
// Access: Public
@ -86,3 +101,14 @@ is_down(int index) const {
nassertr(index >= 0 && index < (int)_button_list.size(), false);
return ((_state & ((BitmaskType)1 << index)) != 0);
}
////////////////////////////////////////////////////////////////////
// Function: ModifierButtons::is_any_down
// Access: Public
// Description: Returns true if any of the tracked button are known
// to be down, or false if all of them are up.
////////////////////////////////////////////////////////////////////
INLINE bool ModifierButtons::
is_any_down() const {
return _state != 0;
}

View File

@ -129,16 +129,19 @@ remove_button(ButtonHandle button) {
// If the given button is one of the buttons that is
// currently being monitored, this will update the
// internal state appropriately; otherwise, it will do
// nothing.
// nothing. Returns true if the button is one that was
// monitored, or false otherwise.
////////////////////////////////////////////////////////////////////
void ModifierButtons::
bool ModifierButtons::
button_down(ButtonHandle button) {
for (int i = 0; i < (int)_button_list.size(); i++) {
if (button == _button_list[i]) {
_state |= ((BitmaskType)1 << i);
return;
return true;
}
}
return false;
}
////////////////////////////////////////////////////////////////////
@ -148,16 +151,19 @@ button_down(ButtonHandle button) {
// If the given button is one of the buttons that is
// currently being monitored, this will update the
// internal state appropriately; otherwise, it will do
// nothing.
// nothing. Returns true if the button is one that was
// monitored, or false otherwise.
////////////////////////////////////////////////////////////////////
void ModifierButtons::
bool ModifierButtons::
button_up(ButtonHandle button) {
for (int i = 0; i < (int)_button_list.size(); i++) {
if (button == _button_list[i]) {
_state &= ~((BitmaskType)1 << i);
return;
return true;
}
}
return false;
}
////////////////////////////////////////////////////////////////////

View File

@ -10,6 +10,7 @@
#include "buttonHandle.h"
#include "pointerToArray.h"
#include "buttonEvent.h"
////////////////////////////////////////////////////////////////////
// Class : ModifierButtons
@ -18,7 +19,7 @@
// known to be down or up.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA ModifierButtons {
public:
PUBLISHED:
ModifierButtons();
ModifierButtons(const ModifierButtons &copy);
~ModifierButtons();
@ -35,11 +36,13 @@ public:
INLINE int get_num_buttons() const;
INLINE ButtonHandle get_button(int index) const;
void button_down(ButtonHandle button);
void button_up(ButtonHandle button);
bool button_down(ButtonHandle button);
bool button_up(ButtonHandle button);
INLINE bool add_event(const ButtonEvent &event);
bool is_down(ButtonHandle button) const;
INLINE bool is_down(int index) const;
INLINE bool is_any_down() const;
void output(ostream &out) const;
void write(ostream &out) const;

View File

@ -9,6 +9,7 @@
#define SOURCES \
buttonThrower.cxx buttonThrower.h config_tform.cxx config_tform.h \
dataValve.I dataValve.cxx dataValve.h \
driveInterface.cxx driveInterface.h mouseWatcher.I mouseWatcher.cxx \
mouseWatcher.h mouseWatcherRegion.I mouseWatcherRegion.cxx \
mouseWatcherRegion.h planarSlider.cxx planarSlider.h trackball.cxx \
@ -16,7 +17,8 @@
transform2sg.cxx transform2sg.h
#define INSTALL_HEADERS \
buttonThrower.h driveInterface.h mouseWatcher.I mouseWatcher.h \
buttonThrower.h dataValve.I dataValve.h \
driveInterface.h mouseWatcher.I mouseWatcher.h \
mouseWatcherRegion.I mouseWatcherRegion.h planarSlider.h \
trackball.h transform2sg.h

View File

@ -86,9 +86,14 @@ get_modifier_buttons() const {
// be empty, and the ButtonThrower will therefore ignore
// all ModifierButtons attached to the key events, but
// if one or more buttons have been added to this set,
// and those modifier buttons are set on the button
// event, then the event name will be prepended with the
// names of the modifier buttons.
// then the event name will be prepended with the names
// of the modifier buttons.
//
// It is recommended that you change this setting by
// first calling get_modifier_buttons(), making
// adjustments, and passing the new value to
// set_modifier_buttons(). This way the current state
// of the modifier buttons will not be lost.
////////////////////////////////////////////////////////////////////
void ButtonThrower::
set_modifier_buttons(const ModifierButtons &mods) {
@ -110,20 +115,24 @@ transmit_data(NodeAttributes &data) {
for (bi = b->begin(); bi != b->end(); ++bi) {
const ButtonEvent &be = (*bi);
string event_name = _prefix + be._button.get_name();
if (!be._down) {
event_name += "-up";
} else {
// We only prepend modifier names on the button-down events.
string prepend;
for (int i = 0; i < _mods.get_num_buttons(); i++) {
ButtonHandle modifier = _mods.get_button(i);
if (be._mods.is_down(modifier)) {
prepend += modifier.get_name() + "-";
if (be._down) {
if (!_mods.button_down(be._button)) {
// We only prepend modifier names on the button-down events,
// and only for buttons which are not themselves modifiers.
string prepend;
for (int i = 0; i < _mods.get_num_buttons(); i++) {
ButtonHandle modifier = _mods.get_button(i);
if (_mods.is_down(modifier)) {
prepend += modifier.get_name() + "-";
}
}
event_name = prepend + event_name;
}
event_name = prepend + event_name;
} else {
_mods.button_up(be._button);
event_name += "-up";
}
throw_event(event_name);

View File

@ -4,6 +4,8 @@
////////////////////////////////////////////////////////////////////
#include "config_tform.h"
#include "dataValve.h"
#include "driveInterface.h"
#include "buttonThrower.h"
#include "mouseWatcher.h"
@ -30,6 +32,7 @@ const double drive_horizontal_ramp_up_time = config_tform.GetDouble("drive-horiz
const double drive_horizontal_ramp_down_time = config_tform.GetDouble("drive-horizontal-ramp-down-time", 0.0);
ConfigureFn(config_tform) {
DataValve::init_type();
DriveInterface::init_type();
ButtonThrower::init_type();
MouseWatcher::init_type();

126
panda/src/tform/dataValve.I Normal file
View File

@ -0,0 +1,126 @@
// Filename: dataValve.I
// Created by: drose (05Feb01)
//
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: DataValve::Control::Constructor
// Access: Published
// Description: A unique Control can be assigned to each child of the
// DataValve, or the same Control may be shared between
// different children as desired. Each Control may be
// explicitly set on or off to enable or disable all
// data flow to that child, respectively; it may also be
// set to a "buttons" state, in which it enables or
// disables data flow to the child based on the current
// state of the modifier buttons as held by the user.
//
// In addition to being assigned to control all data to
// a particular child, a particular Control may be set
// to control only data of a particular type to a
// particular child. See set_control() and
// set_fine_control() on DataValve.
////////////////////////////////////////////////////////////////////
INLINE DataValve::Control::
Control() {
_state = S_on;
}
////////////////////////////////////////////////////////////////////
// Function: DataValve::Control::set_on
// Access: Published
// Description: Sets the state on this particular Control to be on
// until further notice. Child nodes guarded by this
// Control will receive data.
////////////////////////////////////////////////////////////////////
INLINE void DataValve::Control::
set_on() {
_state = S_on;
}
////////////////////////////////////////////////////////////////////
// Function: DataValve::Control::set_off
// Access: Published
// Description: Sets the state on this particular Control to be off
// until further notice. Child nodes guarded by this
// Control will not receive data.
////////////////////////////////////////////////////////////////////
INLINE void DataValve::Control::
set_off() {
_state = S_off;
}
////////////////////////////////////////////////////////////////////
// Function: DataValve::Control::set_buttons
// Access: Published
// Description: Sets the state on this particular Control to be
// dependent on the current set of buttons being held
// down by the user. The ModifierButtons object here
// must exactly match the ModifierButtons object set on
// the DataValve in order and number of buttons.
//
// The best way to generate the ModifierButtons list is
// to create a new ModifierButtons based on the value
// returned by DataValve::get_modifier_buttons(), then
// explicitly call button_up() and button_down() on each
// button that you want to be up or down.
////////////////////////////////////////////////////////////////////
INLINE void DataValve::Control::
set_buttons(const ModifierButtons &mods) {
_state = S_buttons;
_mods = mods;
}
////////////////////////////////////////////////////////////////////
// Function: DataValve::set_default_control
// Access: Public
// Description: Sets the Control that will apply to each child that
// does not have a particular control set via
// set_control().
////////////////////////////////////////////////////////////////////
INLINE void DataValve::
set_default_control(DataValve::Control *control) {
_default_control = control;
}
////////////////////////////////////////////////////////////////////
// Function: DataValve::get_default_control
// Access: Public
// Description: Returns the Control that will apply to each child
// that does not have a particular control set via
// set_control().
////////////////////////////////////////////////////////////////////
INLINE DataValve::Control *DataValve::
get_default_control() const {
return _default_control;
}
////////////////////////////////////////////////////////////////////
// Function: DataValve::set_modifier_buttons
// Access: Public
// Description: Specifies the set of buttons that the DataValve will
// monitor as modifier buttons. The exact same set of
// ModifierButtons must be specified on the DataValve as
// well as on all of its Controls in order to
// successfully use modifier buttons to switch the
// valves automatically.
//
// This need not match the set of ModifierButtons set on
// the window, but it may be less confusing if it does.
////////////////////////////////////////////////////////////////////
INLINE void DataValve::
set_modifier_buttons(const ModifierButtons &mods) {
_mods = mods;
}
////////////////////////////////////////////////////////////////////
// Function: DataValve::get_modifier_buttons
// Access: Public
// Description: Returns the set of ModifierButtons currently being
// monitored. See set_modifier_buttons().
////////////////////////////////////////////////////////////////////
INLINE const ModifierButtons &DataValve::
get_modifier_buttons() const {
return _mods;
}

View File

@ -0,0 +1,369 @@
// Filename: dataValve.cxx
// Created by: drose (05Feb01)
//
////////////////////////////////////////////////////////////////////
#include "dataValve.h"
#include <dataRelation.h>
#include <buttonEventDataAttribute.h>
#include <buttonEventDataTransition.h>
#include <nodeAttributes.h>
TypeHandle DataValve::_type_handle;
TypeHandle DataValve::_button_events_type;
////////////////////////////////////////////////////////////////////
// Function: DataValve::Control::is_on
// Access: Published
// Description: Returns true if the indicated Control is currently
// on, given the particular DataNode it applies to.
// (The DataNode is necessary to determine the current
// state of the ModiferButtons.
////////////////////////////////////////////////////////////////////
bool DataValve::Control::
is_on(const DataValve &valve) const {
switch (_state) {
case S_on:
return true;
case S_off:
return false;
case S_buttons:
return _mods == valve.get_modifier_buttons();
}
// Invalid state.
nassertr(false, false);
return false;
}
////////////////////////////////////////////////////////////////////
// Function: DataValve::Constructor
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
DataValve::
DataValve(const string &name) : DataNode(name) {
_default_control = new Control;
}
////////////////////////////////////////////////////////////////////
// Function: DataValve::Destructor
// Access: Published, Virtual
// Description:
////////////////////////////////////////////////////////////////////
DataValve::
~DataValve() {
}
////////////////////////////////////////////////////////////////////
// Function: DataValve::set_control
// Access: Published
// Description: Sets an overall Control on the indicated child node.
// The nth child of this node, zero-based, will receive
// data only while the indicated Control is on. This
// affects all types of data that is not specifically
// mentioned by set_fine_control().
////////////////////////////////////////////////////////////////////
void DataValve::
set_control(int child_index, Control *control) {
ensure_child_index(child_index);
nassertv(child_index >= 0 && child_index < (int)_controls.size());
_controls[child_index]._control = control;
}
////////////////////////////////////////////////////////////////////
// Function: DataValve::clear_control
// Access: Published
// Description: Removes the overall Control, as well as all fine
// controls, from the indicated child node. The
// indicated child will now be affected only by the
// default control. See set_control() and
// set_fine_control().
////////////////////////////////////////////////////////////////////
void DataValve::
clear_control(int child_index) {
nassertv(child_index >= 0);
if (child_index < (int)_controls.size()) {
_controls[child_index]._control.clear();
_controls[child_index]._fine_controls.clear();
}
}
////////////////////////////////////////////////////////////////////
// Function: DataValve::has_control
// Access: Published
// Description: Returns true if the indicated child has a particular
// Control set, or if it has *any* fine controls set.
// If this returns false, the child is controlled only
// by the default control. See set_control() and
// set_fine_control().
////////////////////////////////////////////////////////////////////
bool DataValve::
has_control(int child_index) const {
nassertr(child_index >= 0, false);
if (child_index < (int)_controls.size()) {
return
!_controls[child_index]._control.is_null() ||
!_controls[child_index]._fine_controls.empty();
}
return false;
}
////////////////////////////////////////////////////////////////////
// Function: DataValve::get_control
// Access: Published
// Description: Returns the control that has been set for the
// indicated child, or NULL if no control has been set
// (which implies the default control is in affect for
// the indicated child). Note that it is possible for
// this function to return NULL even if has_control(),
// above, returned true, since a fine control may have
// been set without setting a particular general
// control.
////////////////////////////////////////////////////////////////////
DataValve::Control *DataValve::
get_control(int child_index) const {
nassertr(child_index >= 0, NULL);
if (child_index < (int)_controls.size()) {
return _controls[child_index]._control;
}
return NULL;
}
////////////////////////////////////////////////////////////////////
// Function: DataValve::set_fine_control
// Access: Published
// Description: Sets the "fine" control for the indicated child index
// and the indicated data type. This overrides the
// control set by set_control() for this child, but only
// for data of this type. This can be used to send
// data of different types to different children.
////////////////////////////////////////////////////////////////////
void DataValve::
set_fine_control(int child_index, TypeHandle data_type, Control *control) {
ensure_child_index(child_index);
nassertv(child_index >= 0 && child_index < (int)_controls.size());
_controls[child_index]._fine_controls[data_type] = control;
}
////////////////////////////////////////////////////////////////////
// Function: DataValve::clear_fine_control
// Access: Published
// Description: Removes the particular fine control set by
// set_fine_control() for the indicated child index and
// data type. Data of this type will now be controlled
// by the Control indicated by set_control() for this
// child, or by set_default_control() if nothing is
// indicated by set_control().
////////////////////////////////////////////////////////////////////
void DataValve::
clear_fine_control(int child_index, TypeHandle data_type) {
nassertv(child_index >= 0);
if (child_index < (int)_controls.size()) {
_controls[child_index]._fine_controls.erase(data_type);
}
}
////////////////////////////////////////////////////////////////////
// Function: DataValve::has_fine_control
// Access: Published
// Description: Returns true if the indicated child has a particular
// fine control set for the indicated data type, or
// false otherwise.
////////////////////////////////////////////////////////////////////
bool DataValve::
has_fine_control(int child_index, TypeHandle data_type) const {
nassertr(child_index >= 0, false);
if (child_index < (int)_controls.size()) {
return _controls[child_index]._fine_controls.count(data_type) != 0;
}
return false;
}
////////////////////////////////////////////////////////////////////
// Function: DataValve::get_fine_control
// Access: Published
// Description: Returns the fine control that has been set for the
// indicated child and data type, or NULL if no such
// fine control has been set.
////////////////////////////////////////////////////////////////////
DataValve::Control *DataValve::
get_fine_control(int child_index, TypeHandle data_type) const {
nassertr(child_index >= 0, NULL);
if (child_index < (int)_controls.size()) {
FineControls::const_iterator fci =
_controls[child_index]._fine_controls.find(data_type);
if (fci != _controls[child_index]._fine_controls.end()) {
return (*fci).second;
}
}
return NULL;
}
////////////////////////////////////////////////////////////////////
// Function: DataValve::write
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
void DataValve::
write(ostream &out, int indent_level) const {
indent(out, indent_level)
<< "DataValve " << get_name() << ": (default control is "
<< (_default_control->is_on(*this) ? "on" : "off") << ")\n";
size_t i;
for (i = 0; i < _controls.size(); i++) {
if (has_control(i)) {
const Child &child = _controls[i];
indent(out, indent_level + 2)
<< "Child " << i << ": ";
if (child._control.is_null()) {
out << "(default)";
} else {
out << (child._control->is_on(*this) ? "on" : "off");
}
out << "\n";
FineControls::const_iterator fci;
for (fci = child._fine_controls.begin();
fci != child._fine_controls.end();
++fci) {
indent(out, indent_level + 4)
<< (*fci).first << " "
<< ((*fci).second->is_on(*this) ? "on" : "off")
<< "\n";
}
}
}
}
////////////////////////////////////////////////////////////////////
// Function: DataValve::ensure_child_index
// Access: Private
// Description: Guarantees that we have at least enough children in
// the _control vector to describe the indicated
// child_index.
////////////////////////////////////////////////////////////////////
void DataValve::
ensure_child_index(int child_index) {
_controls.reserve(child_index + 1);
while ((int)_controls.size() <= child_index) {
_controls.push_back(Child());
}
}
////////////////////////////////////////////////////////////////////
// Function: DataValve::transmit_data
// Access: Public, Virtual
// Description: Called once before transmit_data_per_child() is
// called for each child, this gives the node a chance
// to process its inputs.
////////////////////////////////////////////////////////////////////
void DataValve::
transmit_data(NodeAttributes &data) {
// Update our modifier buttons during the overall pass.
const ButtonEventDataAttribute *b;
if (get_attribute_into(b, data, _button_events_type)) {
b->update_mods(_mods);
}
}
////////////////////////////////////////////////////////////////////
// Function: DataValve::transmit_data_per_child
// Access: Public, Virtual
// Description: Should be overridden in a derived class that wants to
// send a different data stream to each child.
// Normally, a node only overrides transmit_data(),
// which takes a set of input data attributes and
// generates a set of output data attributes. A node
// may also override transmit_data_per_child(), which is
// called after transmit_data(), once per child; this
// function may be used to send individual data
// attributes to each child.
////////////////////////////////////////////////////////////////////
void DataValve::
transmit_data_per_child(NodeAttributes &data, int child_index) {
// Consider which data this child wants to see.
static const FineControls empty_controls;
Control *control = _default_control;
const FineControls *fine_controls = &empty_controls;
if (child_index < (int)_controls.size()) {
if (!_controls[child_index]._control.is_null()) {
control = _controls[child_index]._control;
}
fine_controls = &_controls[child_index]._fine_controls;
}
if (control->is_on(*this)) {
if (fine_controls->empty()) {
// The control is on, and we have no further fine-tuning. All
// data goes to the indicated node.
return;
} else {
// The control is on, and we have some fine-tuning. Any data
// type explicitly "off" should be yanked.
FineControls::const_iterator fci;
for (fci = fine_controls->begin(); fci != fine_controls->end(); ++fci) {
TypeHandle data_type = (*fci).first;
Control *fcontrol = (*fci).second;
if (!fcontrol->is_on(*this)) {
data.clear_attribute(data_type);
}
}
}
} else {
if (fine_controls->empty()) {
// The control is off, and we have no further fine-tuning. All
// data gets eliminated.
data.clear();
} else {
// The control is off, and we have some fine-tuning. Any data
// type explicitly "on" should be preserved.
NodeAttributes temp;
FineControls::const_iterator fci;
for (fci = fine_controls->begin(); fci != fine_controls->end(); ++fci) {
TypeHandle data_type = (*fci).first;
Control *fcontrol = (*fci).second;
if (fcontrol->is_on(*this)) {
NodeAttribute *attrib = data.get_attribute(data_type);
if (attrib != (NodeAttribute *)NULL) {
temp.set_attribute(data_type, attrib);
}
}
}
data = temp;
}
}
}
////////////////////////////////////////////////////////////////////
// Function: DataValve::init_type
// Access: Public, Static
// Description:
////////////////////////////////////////////////////////////////////
void DataValve::
init_type() {
DataNode::init_type();
register_type(_type_handle, "DataValve",
DataNode::get_class_type());
ButtonEventDataTransition::init_type();
register_data_transition(_button_events_type, "ButtonEvents",
ButtonEventDataTransition::get_class_type());
}

124
panda/src/tform/dataValve.h Normal file
View File

@ -0,0 +1,124 @@
// Filename: dataValve.h
// Created by: drose (05Feb01)
//
////////////////////////////////////////////////////////////////////
#ifndef DATAVALVE_H
#define DATAVALVE_H
#include <pandabase.h>
#include <dataNode.h>
#include <modifierButtons.h>
#include <referenceCount.h>
#include <pointerTo.h>
////////////////////////////////////////////////////////////////////
// Class : DataValve
// Description : This DataNode can be used to selectively control
// which child node or nodes receive certain data graph
// events, based on the type of data and possibly on the
// combination of modifier buttons being held down by
// the user.
//
// It's particularly useful when used in conjunction
// with one or more Trackball interfaces, for instance,
// to move around various different objects according to
// the key combination being held down.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA DataValve : public DataNode {
PUBLISHED:
DataValve(const string &name = "");
virtual ~DataValve();
// The Control is used extensively within the DataValve class to
// manage the data flow; see the comments on the Control
// constructor.
class EXPCL_PANDA Control : public ReferenceCount {
PUBLISHED:
INLINE Control();
INLINE void set_on();
INLINE void set_off();
INLINE void set_buttons(const ModifierButtons &mods);
bool is_on(const DataValve &valve) const;
private:
enum State {
S_on,
S_off,
S_buttons
};
State _state;
ModifierButtons _mods;
};
INLINE void set_default_control(Control *control);
INLINE Control *get_default_control() const;
void set_control(int child_index, Control *control);
void clear_control(int child_index);
bool has_control(int child_index) const;
Control *get_control(int child_index) const;
void set_fine_control(int child_index, TypeHandle data_type, Control *control);
void clear_fine_control(int child_index, TypeHandle data_type);
bool has_fine_control(int child_index, TypeHandle data_type) const;
Control *get_fine_control(int child_index, TypeHandle data_type) const;
INLINE void set_modifier_buttons(const ModifierButtons &mods);
INLINE const ModifierButtons &get_modifier_buttons() const;
public:
virtual void write(ostream &out, int indent_level = 0) const;
private:
void ensure_child_index(int child_index);
ModifierButtons _mods;
PT(Control) _default_control;
typedef map<TypeHandle, PT(Control)> FineControls;
class Child {
public:
PT(Control) _control;
FineControls _fine_controls;
};
typedef vector<Child> Controls;
Controls _controls;
////////////////////////////////////////////////////////////////////
// From parent class DataNode
////////////////////////////////////////////////////////////////////
public:
virtual void
transmit_data(NodeAttributes &data);
virtual void
transmit_data_per_child(NodeAttributes &data, int child_index);
// inputs
static TypeHandle _button_events_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;
};
#include "dataValve.I"
#endif

View File

@ -13,18 +13,14 @@
#include <modifierButtons.h>
#include <buttonEventDataTransition.h>
#include <buttonEventDataAttribute.h>
#include <modifierButtonDataTransition.h>
#include <modifierButtonDataAttribute.h>
#include <keyboardButton.h>
#include <mouseButton.h>
#include <dataGraphTraversal.h>
#include <dataGraphTraverser.h>
#include <allAttributesWrapper.h>
#include <dftraverser.h>
#include <dataRelation.h>
TypeHandle DriveInterface::_type_handle;
TypeHandle DriveInterface::_mods_type;
TypeHandle DriveInterface::_xyz_type;
TypeHandle DriveInterface::_button_events_type;
TypeHandle DriveInterface::_transform_type;
@ -126,6 +122,10 @@ DriveInterface(const string &name) : DataNode(name) {
_cs = default_coordinate_system;
_mods.add_button(MouseButton::one());
_mods.add_button(MouseButton::two());
_mods.add_button(MouseButton::three());
_transform = new MatrixDataAttribute;
_transform->set_value(_mat);
_attrib.set_attribute(_transform_type, _transform);
@ -652,13 +652,9 @@ get_mat() const {
void DriveInterface::
force_dgraph() {
_transform->set_value(_mat);
int num_children = get_num_children(DataRelation::get_class_type());
for (int i = 0; i < num_children; i++) {
DataGraphVisitor dgv;
df_traverse(get_child(DataRelation::get_class_type(), i),
dgv, AllAttributesWrapper(_attrib),
NullLevelState(), DataRelation::get_class_type());
}
DataGraphTraverser dgt;
dgt.traverse_below(this, _attrib);
}
@ -858,6 +854,7 @@ transmit_data(NodeAttributes &data) {
ButtonEventDataAttribute::const_iterator bi;
for (bi = b->begin(); bi != b->end(); ++bi) {
const ButtonEvent &be = (*bi);
_mods.add_event(be);
if (be._button == KeyboardButton::up()) {
_up_arrow.set_key(be._down);
@ -872,7 +869,6 @@ transmit_data(NodeAttributes &data) {
}
// Now look for mouse activity.
bool any_button = false;
double x = 0.0;
double y = 0.0;
@ -881,18 +877,9 @@ transmit_data(NodeAttributes &data) {
LVecBase3f p = xyz->get_value();
x = p[0];
y = p[1];
const ModifierButtonDataAttribute *button;
if (get_attribute_into(button, data, _mods_type)) {
ModifierButtons mods = button->get_mods();
any_button =
mods.is_down(MouseButton::one()) ||
mods.is_down(MouseButton::two()) ||
mods.is_down(MouseButton::three());
}
}
apply(x, y, any_button);
apply(x, y, _mods.is_any_down());
_transform->set_value(_mat);
// Now send our matrix down the pipe.
@ -911,9 +898,6 @@ init_type() {
register_type(_type_handle, "DriveInterface",
DataNode::get_class_type());
ModifierButtonDataTransition::init_type();
register_data_transition(_mods_type, "ModifierButtons",
ModifierButtonDataTransition::get_class_type());
Vec3DataTransition::init_type();
register_data_transition(_xyz_type, "XYZ",
Vec3DataTransition::get_class_type());

View File

@ -14,6 +14,7 @@
#include <matrixDataTransition.h>
#include <matrixDataAttribute.h>
#include <nodeAttributes.h>
#include <modifierButtons.h>
#include <luse.h>
#include <lmatrix.h>
@ -122,6 +123,9 @@ private:
bool _is_force_roll;
CoordinateSystem _cs;
// Remember which mouse buttons are being held down.
ModifierButtons _mods;
// Remember which arrow keys are being held down and which aren't,
// and at what point they last changed state.
class KeyHeld {
@ -152,7 +156,6 @@ public:
PT(MatrixDataAttribute) _transform;
// inputs
static TypeHandle _mods_type;
static TypeHandle _xyz_type;
static TypeHandle _button_events_type;

View File

@ -8,11 +8,8 @@
#include <mouse.h>
#include <mouseData.h>
#include <modifierButtons.h>
#include <buttonEventDataTransition.h>
#include <buttonEventDataAttribute.h>
#include <modifierButtonDataTransition.h>
#include <modifierButtonDataAttribute.h>
#include <keyboardButton.h>
#include <mouseButton.h>
#include <throw_event.h>
@ -21,7 +18,6 @@
TypeHandle MouseWatcher::_type_handle;
TypeHandle MouseWatcher::_mods_type;
TypeHandle MouseWatcher::_xyz_type;
TypeHandle MouseWatcher::_button_events_type;
@ -313,9 +309,6 @@ init_type() {
register_type(_type_handle, "MouseWatcher",
DataNode::get_class_type());
ModifierButtonDataTransition::init_type();
register_data_transition(_mods_type, "ModifierButtons",
ModifierButtonDataTransition::get_class_type());
Vec3DataTransition::init_type();
register_data_transition(_xyz_type, "XYZ",
Vec3DataTransition::get_class_type());

View File

@ -110,7 +110,6 @@ public:
transmit_data(NodeAttributes &data);
// inputs & outputs
static TypeHandle _mods_type;
static TypeHandle _xyz_type;
static TypeHandle _button_events_type;

View File

@ -9,14 +9,15 @@
#include <mouse.h>
#include <mouseData.h>
#include <modifierButtons.h>
#include <modifierButtonDataTransition.h>
#include <buttonEventDataTransition.h>
#include <buttonEventDataAttribute.h>
#include <mouseButton.h>
#include <get_rel_pos.h>
TypeHandle PlanarSlider::_type_handle;
TypeHandle PlanarSlider::_mods_type;
TypeHandle PlanarSlider::_xyz_type;
TypeHandle PlanarSlider::_button_events_type;
TypeHandle PlanarSlider::_transform_type;
@ -34,6 +35,8 @@ PlanarSlider(const string &name) : DataNode(name) {
_transform = new MatrixDataAttribute;
_attrib.set_attribute(_transform_type, _transform);
_mods.add_button(MouseButton::one());
}
@ -146,19 +149,17 @@ get_mouse_pos() const {
////////////////////////////////////////////////////////////////////
void PlanarSlider::
transmit_data(NodeAttributes &data) {
const NodeAttribute *button = data.get_attribute(_mods_type);
// First, update our modifier buttons.
const ButtonEventDataAttribute *b;
if (get_attribute_into(b, data, _button_events_type)) {
b->update_mods(_mods);
}
// Now look for a mouse position.
const NodeAttribute *xyz = data.get_attribute(_xyz_type);
if (xyz != (NodeAttribute *)NULL) {
bool is_down = false;
if (button != (NodeAttribute *)NULL) {
ModifierButtons mods =
DCAST(ModifierButtonDataAttribute, button)->get_mods();
is_down = mods.is_down(MouseButton::one());
}
if (is_down) {
if (_mods.is_any_down()) {
LVecBase3f p = DCAST(Vec3DataAttribute, xyz)->get_value();
set_mouse_pos(LPoint2f(p[0], p[1]));
}
@ -180,13 +181,13 @@ init_type() {
register_type(_type_handle, "PlanarSlider",
DataNode::get_class_type());
ModifierButtonDataTransition::init_type();
register_data_transition(_mods_type, "ModifierButtons",
ModifierButtonDataTransition::get_class_type());
Vec3DataTransition::init_type();
register_data_transition(_xyz_type, "XYZ",
Vec3DataTransition::get_class_type());
MatrixDataTransition::init_type();
register_data_transition(_transform_type, "Transform",
MatrixDataTransition::get_class_type());
ButtonEventDataTransition::init_type();
register_data_transition(_button_events_type, "ButtonEvents",
ButtonEventDataTransition::get_class_type());
}

View File

@ -16,6 +16,7 @@
#include <nodeAttributes.h>
#include <luse.h>
#include <lmatrix.h>
#include <modifierButtons.h>
////////////////////////////////////////////////////////////////////
@ -46,6 +47,7 @@ private:
CoordinateSystem _cs;
LMatrix4f _transform_mat, _inverse_mat;
LPoint2f _mouse_pos;
ModifierButtons _mods;
////////////////////////////////////////////////////////////////////
// From parent class DataNode
@ -59,8 +61,8 @@ public:
PT(MatrixDataAttribute) _transform;
// inputs
static TypeHandle _mods_type;
static TypeHandle _xyz_type;
static TypeHandle _button_events_type;
// outputs
static TypeHandle _transform_type;

View File

@ -10,15 +10,14 @@
#include <mouseData.h>
#include <modifierButtons.h>
#include <buttonEventDataTransition.h>
#include <modifierButtonDataTransition.h>
#include <modifierButtonDataAttribute.h>
#include <buttonEventDataAttribute.h>
#include <mouseButton.h>
#include <get_rel_pos.h>
TypeHandle Trackball::_type_handle;
TypeHandle Trackball::_mods_type;
TypeHandle Trackball::_pixel_xyz_type;
TypeHandle Trackball::_button_events_type;
TypeHandle Trackball::_transform_type;
#define B1_MASK 1
@ -46,6 +45,10 @@ Trackball(const string &name) : DataNode(name) {
_rel_to = NULL;
_cs = default_coordinate_system;
_mods.add_button(MouseButton::one());
_mods.add_button(MouseButton::two());
_mods.add_button(MouseButton::three());
_transform = new MatrixDataAttribute;
_transform->set_value(LMatrix4f::ident_mat());
_attrib.set_attribute(_transform_type, _transform);
@ -471,7 +474,13 @@ recompute() {
////////////////////////////////////////////////////////////////////
void Trackball::
transmit_data(NodeAttributes &data) {
const NodeAttribute *button = data.get_attribute(_mods_type);
// First, update our modifier buttons.
const ButtonEventDataAttribute *b;
if (get_attribute_into(b, data, _button_events_type)) {
b->update_mods(_mods);
}
// Now, check for mouse motion.
const NodeAttribute *pixel_xyz = data.get_attribute(_pixel_xyz_type);
if (pixel_xyz != (NodeAttribute *)NULL) {
@ -480,19 +489,14 @@ transmit_data(NodeAttributes &data) {
float this_y = p[1];
int this_button = 0;
if (button != (NodeAttribute *)NULL) {
ModifierButtons mods =
DCAST(ModifierButtonDataAttribute, button)->get_mods();
if (mods.is_down(MouseButton::one())) {
this_button |= B1_MASK;
}
if (mods.is_down(MouseButton::two())) {
this_button |= B2_MASK;
}
if (mods.is_down(MouseButton::three())) {
this_button |= B3_MASK;
}
if (_mods.is_down(MouseButton::one())) {
this_button |= B1_MASK;
}
if (_mods.is_down(MouseButton::two())) {
this_button |= B2_MASK;
}
if (_mods.is_down(MouseButton::three())) {
this_button |= B3_MASK;
}
float x = this_x - _lastx;
@ -521,12 +525,12 @@ init_type() {
register_type(_type_handle, "Trackball",
DataNode::get_class_type());
ModifierButtonDataTransition::init_type();
register_data_transition(_mods_type, "ModifierButtons",
ModifierButtonDataTransition::get_class_type());
Vec3DataTransition::init_type();
register_data_transition(_pixel_xyz_type, "PixelXYZ",
Vec3DataTransition::get_class_type());
ButtonEventDataTransition::init_type();
register_data_transition(_button_events_type, "ButtonEvents",
ButtonEventDataTransition::get_class_type());
MatrixDataTransition::init_type();
register_data_transition(_transform_type, "Transform",
MatrixDataTransition::get_class_type());

View File

@ -14,6 +14,7 @@
#include <matrixDataTransition.h>
#include <matrixDataAttribute.h>
#include <nodeAttributes.h>
#include <modifierButtons.h>
#include <luse.h>
#include <lmatrix.h>
@ -103,6 +104,9 @@ private:
const Node *_rel_to;
CoordinateSystem _cs;
// Remember which mouse buttons are being held down.
ModifierButtons _mods;
////////////////////////////////////////////////////////////////////
// From parent class DataNode
@ -116,8 +120,8 @@ public:
PT(MatrixDataAttribute) _transform;
// inputs
static TypeHandle _mods_type;
static TypeHandle _pixel_xyz_type;
static TypeHandle _button_events_type;
// outputs
static TypeHandle _transform_type;