diff --git a/panda/src/collide/collisionHandler.h b/panda/src/collide/collisionHandler.h index ed19710621..345c57c45c 100644 --- a/panda/src/collide/collisionHandler.h +++ b/panda/src/collide/collisionHandler.h @@ -27,10 +27,12 @@ public: virtual void end_group(); -public: +PUBLISHED: static TypeHandle get_class_type() { return _type_handle; } + +public: static void init_type() { TypedReferenceCount::init_type(); register_type(_type_handle, "CollisionHandler", diff --git a/panda/src/collide/collisionHandlerPhysical.cxx b/panda/src/collide/collisionHandlerPhysical.cxx index 6739461458..720784ad37 100644 --- a/panda/src/collide/collisionHandlerPhysical.cxx +++ b/panda/src/collide/collisionHandlerPhysical.cxx @@ -50,6 +50,7 @@ set_mat(const LMatrix4f &mat) const { } else if (_drive_interface != (DriveInterface *)NULL) { _drive_interface->set_mat(mat); + _drive_interface->force_dgraph(); } else { collide_cat.error() diff --git a/panda/src/collide/collisionTraverser.cxx b/panda/src/collide/collisionTraverser.cxx index 761b415485..aaccc9b642 100644 --- a/panda/src/collide/collisionTraverser.cxx +++ b/panda/src/collide/collisionTraverser.cxx @@ -57,6 +57,7 @@ CollisionTraverser:: //////////////////////////////////////////////////////////////////// void CollisionTraverser:: add_collider(CollisionNode *node, CollisionHandler *handler) { + nassertv(_ordered_colliders.size() == _colliders.size()); nassertv(node != (CollisionNode *)NULL); nassertv(handler != (CollisionHandler *)NULL); @@ -88,6 +89,7 @@ add_collider(CollisionNode *node, CollisionHandler *handler) { } else { // We hadn't already known about this collider. _colliders.insert(Colliders::value_type(node, handler)); + _ordered_colliders.push_back(node); Handlers::iterator hi = _handlers.find(handler); if (hi == _handlers.end()) { @@ -96,6 +98,8 @@ add_collider(CollisionNode *node, CollisionHandler *handler) { (*hi).second++; } } + + nassertv(_ordered_colliders.size() == _colliders.size()); } //////////////////////////////////////////////////////////////////// @@ -109,6 +113,8 @@ add_collider(CollisionNode *node, CollisionHandler *handler) { //////////////////////////////////////////////////////////////////// bool CollisionTraverser:: remove_collider(CollisionNode *node) { + nassertr(_ordered_colliders.size() == _colliders.size(), false); + Colliders::iterator ci = _colliders.find(node); if (ci == _colliders.end()) { // We didn't know about this node. @@ -127,6 +133,13 @@ remove_collider(CollisionNode *node) { } _colliders.erase(ci); + + OrderedColliders::iterator oci = + find(_ordered_colliders.begin(), _ordered_colliders.end(), node); + nassertr(oci != _ordered_colliders.end(), false); + _ordered_colliders.erase(oci); + + nassertr(_ordered_colliders.size() == _colliders.size(), false); return true; } @@ -143,6 +156,31 @@ has_collider(CollisionNode *node) const { return (ci != _colliders.end()); } +//////////////////////////////////////////////////////////////////// +// Function: CollisionTraverser::get_num_colliders +// Access: Public +// Description: Returns the number of CollisionNodes that have been +// added to the traverser via add_collider(). +//////////////////////////////////////////////////////////////////// +int CollisionTraverser:: +get_num_colliders() const { + nassertr(_ordered_colliders.size() == _colliders.size(), 0); + return _ordered_colliders.size(); +} + +//////////////////////////////////////////////////////////////////// +// Function: CollisionTraverser::get_collider +// Access: Public +// Description: Returns the nth CollisionNode that has been +// added to the traverser via add_collider(). +//////////////////////////////////////////////////////////////////// +CollisionNode *CollisionTraverser:: +get_collider(int n) const { + nassertr(_ordered_colliders.size() == _colliders.size(), NULL); + nassertr(n >= 0 && n < (int)_ordered_colliders.size(), NULL); + return _ordered_colliders[n]; +} + //////////////////////////////////////////////////////////////////// // Function: CollisionTraverser::get_handler // Access: Public @@ -168,6 +206,7 @@ get_handler(CollisionNode *node) const { void CollisionTraverser:: clear_colliders() { _colliders.clear(); + _ordered_colliders.clear(); } @@ -245,10 +284,9 @@ prepare_colliders(CollisionLevelState &level_state) { level_state.clear(); level_state.reserve(_colliders.size()); - Colliders::iterator ci = _colliders.begin(); - while (ci != _colliders.end()) { - CollisionNode *cnode = (*ci).first; - ++ci; + int i = 0; + while (i < (int)_ordered_colliders.size()) { + CollisionNode *cnode = _ordered_colliders[i]; CollisionLevelState::ColliderDef def; def._node = cnode; @@ -261,7 +299,7 @@ prepare_colliders(CollisionLevelState &level_state) { << "Collider " << *cnode << " has become NaN. Dropping from traverser.\n"; // This is safe to do while traversing the list of colliders, - // because we have already incremented ci, above. + // because we do not increment i in this case. remove_collider(cnode); } else #endif @@ -272,6 +310,7 @@ prepare_colliders(CollisionLevelState &level_state) { def._collider = collider; level_state.prepare_collider(def); } + i++; } } } diff --git a/panda/src/collide/collisionTraverser.h b/panda/src/collide/collisionTraverser.h index db17138f3b..6dedeb398a 100644 --- a/panda/src/collide/collisionTraverser.h +++ b/panda/src/collide/collisionTraverser.h @@ -37,6 +37,8 @@ PUBLISHED: void add_collider(CollisionNode *node, CollisionHandler *handler); bool remove_collider(CollisionNode *node); bool has_collider(CollisionNode *node) const; + int get_num_colliders() const; + CollisionNode *get_collider(int n) const; CollisionHandler *get_handler(CollisionNode *node) const; void clear_colliders(); @@ -79,6 +81,8 @@ private: typedef map Colliders; Colliders _colliders; + typedef vector OrderedColliders; + OrderedColliders _ordered_colliders; typedef map Handlers; Handlers _handlers; diff --git a/panda/src/dgraph/dataGraphTraversal.cxx b/panda/src/dgraph/dataGraphTraversal.cxx index 053b8510ab..78b9ae22b5 100644 --- a/panda/src/dgraph/dataGraphTraversal.cxx +++ b/panda/src/dgraph/dataGraphTraversal.cxx @@ -91,9 +91,6 @@ reached_node(Node *node, AllAttributesWrapper &state, NullLevelState &) { //////////////////////////////////////////////////////////////////// void traverse_data_graph(Node *root) { DataGraphVisitor dgv; - df_traverse(root, dgv, AllAttributesWrapper(), - NullLevelState(), RenderRelation::get_class_type()); - df_traverse(root, dgv, AllAttributesWrapper(), NullLevelState(), DataRelation::get_class_type()); } diff --git a/panda/src/tform/driveInterface.cxx b/panda/src/tform/driveInterface.cxx index e641d79488..119d76d14b 100644 --- a/panda/src/tform/driveInterface.cxx +++ b/panda/src/tform/driveInterface.cxx @@ -17,6 +17,10 @@ #include #include #include +#include +#include +#include +#include TypeHandle DriveInterface::_type_handle; @@ -577,6 +581,27 @@ get_mat() const { return _mat; } +//////////////////////////////////////////////////////////////////// +// Function: DriveInterface::force_dgraph +// Access: Public +// Description: This is a special kludge for DriveInterface to allow +// us to avoid the one-frame latency after a collision. +// It forces an immediate partial data flow for all data +// graph nodes below this node, causing all data nodes +// that depend on this matrix to be updated immediately. +//////////////////////////////////////////////////////////////////// +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()); + } +} + //////////////////////////////////////////////////////////////////// // Function: DriveInterface::apply diff --git a/panda/src/tform/driveInterface.h b/panda/src/tform/driveInterface.h index 73764373b8..7fae14e291 100644 --- a/panda/src/tform/driveInterface.h +++ b/panda/src/tform/driveInterface.h @@ -85,6 +85,7 @@ PUBLISHED: void set_mat(const LMatrix4f &mat); const LMatrix4f &get_mat() const; + void force_dgraph(); private: void apply(double x, double y, bool any_button);