Bladeren bron

insist on same graph for colliders

David Rose 22 jaren geleden
bovenliggende
commit
8a45c38537

+ 26 - 17
panda/src/collide/collisionTraverser.cxx

@@ -265,7 +265,7 @@ traverse(const NodePath &root) {
 #endif  // DO_COLLISION_RECORDING
 
   CollisionLevelState level_state(root);
-  prepare_colliders(level_state);
+  prepare_colliders(level_state, root);
 
   Handlers::iterator hi;
   for (hi = _handlers.begin(); hi != _handlers.end(); ++hi) {
@@ -399,29 +399,38 @@ write(ostream &out, int indent_level) const {
 //  Description:
 ////////////////////////////////////////////////////////////////////
 void CollisionTraverser::
-prepare_colliders(CollisionLevelState &level_state) {
+prepare_colliders(CollisionLevelState &level_state, const NodePath &root) {
   level_state.clear();
   level_state.reserve(_colliders.size());
 
   int i = 0;
   while (i < (int)_ordered_colliders.size()) {
     NodePath cnode_path = _ordered_colliders[i];
-    if (!cnode_path.is_empty() && 
-        cnode_path.node()->is_of_type(CollisionNode::get_class_type())) {
-      CollisionNode *cnode = DCAST(CollisionNode, cnode_path.node());
-
-      CollisionLevelState::ColliderDef def;
-      def._node = cnode;
-      def._node_path = cnode_path;
-      
-      int num_solids = cnode->get_num_solids();
-      for (int s = 0; s < num_solids; s++) {
-        CollisionSolid *collider = cnode->get_solid(s);
-        def._collider = collider;
-        level_state.prepare_collider(def);
+#ifndef NDEBUG
+    if (!cnode_path.is_same_graph(root)) {
+      collide_cat.error()
+        << "Collider " << cnode_path
+        << " is not in scene graph.  Dropping from traverser.\n";
+      // This is safe to do while traversing the list of colliders,
+      // because we do not increment i in this case.
+      remove_collider(cnode_path);
+    } else
+#endif
+      {
+        CollisionNode *cnode = DCAST(CollisionNode, cnode_path.node());
+        
+        CollisionLevelState::ColliderDef def;
+        def._node = cnode;
+        def._node_path = cnode_path;
+        
+        int num_solids = cnode->get_num_solids();
+        for (int s = 0; s < num_solids; s++) {
+          CollisionSolid *collider = cnode->get_solid(s);
+          def._collider = collider;
+          level_state.prepare_collider(def);
+        }
+        i++;
       }
-      i++;
-    }
   }
 }
 

+ 1 - 1
panda/src/collide/collisionTraverser.h

@@ -83,7 +83,7 @@ PUBLISHED:
   void write(ostream &out, int indent_level) const;
 
 private:
-  void prepare_colliders(CollisionLevelState &state);
+  void prepare_colliders(CollisionLevelState &state, const NodePath &root);
 
   void r_traverse(CollisionLevelState &level_state);
 

+ 21 - 7
panda/src/pgraph/nodePath.I

@@ -262,13 +262,6 @@ node() const {
 //               given key will never be reused for a different
 //               instance (unless the app has been running long enough
 //               that we overflow the integer key value).
-//
-//               There are a few special case circumstances that can
-//               cause the key for a particular instance to be
-//               changed.  These all involve different instances being
-//               collapsed into the same instance by some scene graph
-//               operation (for instance, detaching a node below an
-//               instanced node).
 ////////////////////////////////////////////////////////////////////
 INLINE int NodePath::
 get_key() const {
@@ -278,6 +271,27 @@ get_key() const {
   return _head->get_key();
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: NodePath::is_same_graph
+//       Access: Published
+//  Description: Returns true if the node represented by this NodePath
+//               is parented within the same graph as that of the
+//               other NodePath.  This is essentially the same thing
+//               as asking whether the top node of both NodePaths is
+//               the same (e.g., both "render").
+////////////////////////////////////////////////////////////////////
+INLINE bool NodePath::
+is_same_graph(const NodePath &other) const {
+  // Actually, it's possible for the top nodes to be the same, but the
+  // NodePaths still to be considered in different graphs.  This will
+  // happen if one of the top nodes is considered a different
+  // instance--for instance, render.instance_to(NodePath()) returns a
+  // different instance of render that appears to have the same top
+  // node.  But this is a very rare thing to do.
+  int a_count, b_count;
+  return (find_common_ancestor(*this, other, a_count, b_count) != (NodePathComponent *)NULL);
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: NodePath::get_num_children
 //       Access: Published

+ 2 - 0
panda/src/pgraph/nodePath.h

@@ -179,6 +179,8 @@ PUBLISHED:
 
   INLINE int get_key() const;
 
+  INLINE bool is_same_graph(const NodePath &other) const;
+
   // Methods that return collections of NodePaths derived from or
   // related to this one.