Browse Source

improve tag-based events

David Rose 22 years ago
parent
commit
df1a85e306

+ 142 - 37
panda/src/collide/collisionHandlerEvent.I

@@ -49,12 +49,23 @@ operator = (const CollisionHandlerEvent::SortEntries &) {
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: CollisionHandlerEvent::set_in_pattern
+//     Function: CollisionHandlerEvent::clear_in_patterns
+//       Access: Public
+//  Description: Removes all of the previously-added in patterns.  See
+//               add_in_pattern.
+////////////////////////////////////////////////////////////////////
+INLINE void CollisionHandlerEvent::
+clear_in_patterns() {
+  _in_patterns.clear();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CollisionHandlerEvent::add_in_pattern
 //       Access: Public
-//  Description: Sets the pattern string that indicates how the event
-//               names are generated for each collision detected.
-//               This is a string that may contain any of the
-//               following:
+//  Description: Adds a pattern string to the list of events that will
+//               be generated in response to a collision.  The pattern
+//               string describes how the event name will be composed.
+//               It is a string that may contain any of the following:
 //
 //                  %fn  - the name of the "from" object's node
 //                  %in  - the name of the "into" object's node
@@ -63,15 +74,16 @@ operator = (const CollisionHandlerEvent::SortEntries &) {
 //                  %ig  - 'c' if the collision is into a
 //                          CollisionNode, 'g' if it is a geom.
 //
-//                  %(tag)fh - '1' if "from" has the indicated tag,
-//                          '0' if it does not.
-//                  %(tag)ih - '1' if "into" has the indicated tag,
-//                          '0' if it does not.
-//                  %(tag)iH - '1' if "into" has the indicated net tag,
-//                          '0' if it does not.
+//                  %(tag)fh - generate event only if "from" node has
+//                          the indicated tag.
+//                  %(tag)fx - generate event only if "from" node does 
+//                          not have the indicated tag.
+//                  %(tag)ih - generate event only if "into" node has
+//                          the indicated net tag.
+//                  %(tag)ix - generate event only if "into" node does 
+//                          not have the indicated net tag.
 //                  %(tag)ft - the indicated tag value of the "from" node.
-//                  %(tag)it - the indicated tag value of the "to" node.
-//                  %(tag)iT - the indicated net tag value of the "to" node.
+//                  %(tag)it - the indicated net tag value of the "into" node.
 //
 //               Parentheses in the above are literal and should be
 //               included in the actual pattern.
@@ -89,26 +101,62 @@ operator = (const CollisionHandlerEvent::SortEntries &) {
 //               out_pattern event is thrown.
 ////////////////////////////////////////////////////////////////////
 INLINE void CollisionHandlerEvent::
+add_in_pattern(const string &in_pattern) {
+  _in_patterns.push_back(in_pattern);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CollisionHandlerEvent::set_in_pattern
+//       Access: Public
+//  Description: This method is deprecated; it completely replaces all
+//               the in patterns that have previously been set with
+//               the indicated pattern.
+////////////////////////////////////////////////////////////////////
+INLINE void CollisionHandlerEvent::
 set_in_pattern(const string &in_pattern) {
-  _in_pattern = in_pattern;
+  clear_in_patterns();
+  add_in_pattern(in_pattern);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CollisionHandlerEvent::get_num_in_patterns
+//       Access: Public
+//  Description: Returns the number of in pattern strings that have
+//               been added.
+////////////////////////////////////////////////////////////////////
+INLINE int CollisionHandlerEvent::
+get_num_in_patterns() const {
+  return _in_patterns.size();
 }
 
 ////////////////////////////////////////////////////////////////////
 //     Function: CollisionHandlerEvent::get_in_pattern
 //       Access: Public
-//  Description: Returns the pattern string that indicates how the
+//  Description: Returns the nth pattern string that indicates how the
 //               event names are generated for each collision
-//               detected.  See set_in_pattern().
+//               detected.  See add_in_pattern().
 ////////////////////////////////////////////////////////////////////
 INLINE string CollisionHandlerEvent::
-get_in_pattern() const {
-  return _in_pattern;
+get_in_pattern(int n) const {
+  nassertr(n >= 0 && n < (int)_in_patterns.size(), string());
+  return _in_patterns[n];
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: CollisionHandlerEvent::set_again_pattern
+//     Function: CollisionHandlerEvent::clear_again_patterns
 //       Access: Public
-//  Description: Sets the pattern string that indicates how the event
+//  Description: Removes all of the previously-added in patterns.  See
+//               add_again_pattern.
+////////////////////////////////////////////////////////////////////
+INLINE void CollisionHandlerEvent::
+clear_again_patterns() {
+  _again_patterns.clear();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CollisionHandlerEvent::add_again_pattern
+//       Access: Public
+//  Description: Adds the pattern string that indicates how the event
 //               names are generated when a collision between two
 //               particular nodes is *still* detected.  This event is
 //               thrown each consecutive time a collision between two
@@ -124,28 +172,62 @@ get_in_pattern() const {
 //               out_pattern event is thrown.
 ////////////////////////////////////////////////////////////////////
 INLINE void CollisionHandlerEvent::
+add_again_pattern(const string &again_pattern) {
+  _again_patterns.push_back(again_pattern);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CollisionHandlerEvent::set_again_pattern
+//       Access: Public
+//  Description: This method is deprecated; it completely replaces all
+//               the in patterns that have previously been set with
+//               the indicated pattern.
+////////////////////////////////////////////////////////////////////
+INLINE void CollisionHandlerEvent::
 set_again_pattern(const string &again_pattern) {
-  _again_pattern = again_pattern;
+  clear_again_patterns();
+  add_again_pattern(again_pattern);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CollisionHandlerEvent::get_num_again_patterns
+//       Access: Public
+//  Description: Returns the number of in pattern strings that have
+//               been added.
+////////////////////////////////////////////////////////////////////
+INLINE int CollisionHandlerEvent::
+get_num_again_patterns() const {
+  return _again_patterns.size();
 }
 
 ////////////////////////////////////////////////////////////////////
 //     Function: CollisionHandlerEvent::get_again_pattern
 //       Access: Public
-//  Description: Returns the pattern string that indicates how the
-//               event names are generated when a collision between
-//               two particular nodes is *still* detected.  See
-//               set_again_pattern() and set_in_pattern().
+//  Description: Returns the nth pattern string that indicates how the
+//               event names are generated for each collision
+//               detected.  See add_again_pattern().
 ////////////////////////////////////////////////////////////////////
 INLINE string CollisionHandlerEvent::
-get_again_pattern() const {
-  return _again_pattern;
+get_again_pattern(int n) const {
+  nassertr(n >= 0 && n < (int)_again_patterns.size(), string());
+  return _again_patterns[n];
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: CollisionHandlerEvent::clear_out_patterns
+//       Access: Public
+//  Description: Removes all of the previously-added in patterns.  See
+//               add_out_pattern.
+////////////////////////////////////////////////////////////////////
+INLINE void CollisionHandlerEvent::
+clear_out_patterns() {
+  _out_patterns.clear();
+}
 
 ////////////////////////////////////////////////////////////////////
-//     Function: CollisionHandlerEvent::set_out_pattern
+//     Function: CollisionHandlerEvent::add_out_pattern
 //       Access: Public
-//  Description: Sets the pattern string that indicates how the event
+//  Description: Adds the pattern string that indicates how the event
 //               names are generated when a collision between two
 //               particular nodes is *no longer* detected.
 //
@@ -158,20 +240,43 @@ get_again_pattern() const {
 //               out_pattern event is thrown.
 ////////////////////////////////////////////////////////////////////
 INLINE void CollisionHandlerEvent::
+add_out_pattern(const string &out_pattern) {
+  _out_patterns.push_back(out_pattern);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CollisionHandlerEvent::set_out_pattern
+//       Access: Public
+//  Description: This method is deprecated; it completely replaces all
+//               the in patterns that have previously been set with
+//               the indicated pattern.
+////////////////////////////////////////////////////////////////////
+INLINE void CollisionHandlerEvent::
 set_out_pattern(const string &out_pattern) {
-  _out_pattern = out_pattern;
+  clear_out_patterns();
+  add_out_pattern(out_pattern);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CollisionHandlerEvent::get_num_out_patterns
+//       Access: Public
+//  Description: Returns the number of in pattern strings that have
+//               been added.
+////////////////////////////////////////////////////////////////////
+INLINE int CollisionHandlerEvent::
+get_num_out_patterns() const {
+  return _out_patterns.size();
 }
 
 ////////////////////////////////////////////////////////////////////
 //     Function: CollisionHandlerEvent::get_out_pattern
 //       Access: Public
-//  Description: Returns the pattern string that indicates how the
-//               event names are generated when a collision between
-//               two particular nodes is *no longer* detected.  See
-//               set_out_pattern() and set_in_pattern().
+//  Description: Returns the nth pattern string that indicates how the
+//               event names are generated for each collision
+//               detected.  See add_out_pattern().
 ////////////////////////////////////////////////////////////////////
 INLINE string CollisionHandlerEvent::
-get_out_pattern() const {
-  return _out_pattern;
+get_out_pattern(int n) const {
+  nassertr(n >= 0 && n < (int)_out_patterns.size(), string());
+  return _out_patterns[n];
 }
-

+ 34 - 18
panda/src/collide/collisionHandlerEvent.cxx

@@ -31,7 +31,7 @@ TypeHandle CollisionHandlerEvent::_type_handle;
 //       Access: Public
 //  Description: The default CollisionHandlerEvent will throw no
 //               events.  Its pattern strings must first be set via a
-//               call to set_in_pattern() and/or set_out_pattern().
+//               call to add_in_pattern() and/or add_out_pattern().
 ////////////////////////////////////////////////////////////////////
 CollisionHandlerEvent::
 CollisionHandlerEvent() {
@@ -109,18 +109,18 @@ end_group() {
     if (order(*ca, *cb)) {
       // Here's an element in a but not in b.  That's a newly entered
       // intersection.
-      throw_event_pattern(_in_pattern, *ca);
+      throw_event_for(_in_patterns, *ca);
       ++ca;
 
     } else if (order(*cb, *ca)) {
       // Here's an element in b but not in a.  That's a newly exited
       // intersection.
-      throw_event_pattern(_out_pattern, *cb);
+      throw_event_for(_out_patterns, *cb);
       ++cb;
 
     } else {
       // This element is in both b and a.  It hasn't changed.
-      throw_event_pattern(_again_pattern, *cb);
+      throw_event_for(_again_patterns, *cb);
       ++ca;
       ++cb;
     }
@@ -129,14 +129,14 @@ end_group() {
   while (ca != _current_colliding.end()) {
     // Here's an element in a but not in b.  That's a newly entered
     // intersection.
-    throw_event_pattern(_in_pattern, *ca);
+    throw_event_for(_in_patterns, *ca);
     ++ca;
   }
 
   while (cb != _last_colliding.end()) {
     // Here's an element in b but not in a.  That's a newly exited
     // intersection.
-    throw_event_pattern(_out_pattern, *cb);
+    throw_event_for(_out_patterns, *cb);
     ++cb;
   }
 
@@ -154,7 +154,7 @@ end_group() {
 //               This can be called each frame to defeat the
 //               persistent "in" event mechanism, which prevents the
 //               same "in" event from being thrown repeatedly.
-//               However, also see set_again_pattern(), which can be
+//               However, also see add_again_pattern(), which can be
 //               used to set the event that is thrown when a collision
 //               is detected for two or more consecutive frames.
 ////////////////////////////////////////////////////////////////////
@@ -164,6 +164,20 @@ clear() {
   _current_colliding.clear();
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: CollisionHandlerEvent::throw_event_for
+//       Access: Private
+//  Description: Throws whatever events are suggested by the list of
+//               patterns.
+////////////////////////////////////////////////////////////////////
+void CollisionHandlerEvent::
+throw_event_for(const vector_string &patterns, CollisionEntry *entry) {
+  vector_string::const_iterator pi;
+  for (pi = patterns.begin(); pi != patterns.end(); ++pi) {
+    throw_event_pattern(*pi, entry);
+  }
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: CollisionHandlerEvent::throw_event_pattern
 //       Access: Private
@@ -213,27 +227,29 @@ throw_event_pattern(const string &pattern, CollisionEntry *entry) {
           (entry->has_into() ? 'c' : 'g');
 
       } else if (cmd == "fh") {
-        event += (entry->get_from_node()->has_tag(key) ? '1' : '0');
+        if (!entry->get_from_node()->has_tag(key)) {
+          return;
+        }
+
+      } else if (cmd == "fx") {
+        if (entry->get_from_node()->has_tag(key)) {
+          return;
+        }
 
       } else if (cmd == "ih") {
-        if (entry->has_into()) {
-          event += (entry->get_into_node()->has_tag(key) ? '1' : '0');
+        if (!(entry->has_into() && entry->get_into_node_path().has_net_tag(key))) {
+          return;
         }
 
-      } else if (cmd == "iH") {
-        if (entry->has_into()) {
-          event += (entry->get_into_node_path().has_net_tag(key) ? '1' : '0');
+      } else if (cmd == "ix") {
+        if (entry->has_into() && entry->get_into_node_path().has_net_tag(key)) {
+          return;
         }
 
       } else if (cmd == "ft") {
         event += entry->get_from_node()->get_tag(key);
 
       } else if (cmd == "it") {
-        if (entry->has_into()) {
-          event += entry->get_into_node()->get_tag(key);
-        }
-
-      } else if (cmd == "iT") {
         if (entry->has_into()) {
           event += entry->get_into_node_path().get_net_tag(key);
         }

+ 22 - 9
panda/src/collide/collisionHandlerEvent.h

@@ -25,6 +25,7 @@
 #include "collisionNode.h"
 #include "collisionEntry.h"
 
+#include "vector_string.h"
 #include "pointerTo.h"
 
 ///////////////////////////////////////////////////////////////////
@@ -46,21 +47,33 @@ public:
   virtual bool end_group();
 
 PUBLISHED:
-  INLINE void set_in_pattern(const string &pattern);
-  INLINE string get_in_pattern() const;
-  INLINE void set_again_pattern(const string &pattern);
-  INLINE string get_again_pattern() const;
-  INLINE void set_out_pattern(const string &pattern);
-  INLINE string get_out_pattern() const;
+  INLINE void clear_in_patterns();
+  INLINE void add_in_pattern(const string &in_pattern);
+  INLINE void set_in_pattern(const string &in_pattern);
+  INLINE int get_num_in_patterns() const;
+  INLINE string get_in_pattern(int n) const;
+
+  INLINE void clear_again_patterns();
+  INLINE void add_again_pattern(const string &again_pattern);
+  INLINE void set_again_pattern(const string &again_pattern);
+  INLINE int get_num_again_patterns() const;
+  INLINE string get_again_pattern(int n) const;
+
+  INLINE void clear_out_patterns();
+  INLINE void add_out_pattern(const string &out_pattern);
+  INLINE void set_out_pattern(const string &out_pattern);
+  INLINE int get_num_out_patterns() const;
+  INLINE string get_out_pattern(int n) const;
 
   void clear();
 
 private:
+  void throw_event_for(const vector_string &patterns, CollisionEntry *entry);
   void throw_event_pattern(const string &pattern, CollisionEntry *entry);
 
-  string _in_pattern;
-  string _again_pattern;
-  string _out_pattern;
+  vector_string _in_patterns;
+  vector_string _again_patterns;
+  vector_string _out_patterns;
 
   int _index;