Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

panda/src/collide/collisionHandlerEvent.cxx

Go to the documentation of this file.
00001 // Filename: collisionHandlerEvent.cxx
00002 // Created by:  drose (16Mar02)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
00008 //
00009 // All use of this software is subject to the terms of the Panda 3d
00010 // Software license.  You should have received a copy of this license
00011 // along with this source code; you will also find a current copy of
00012 // the license at http://www.panda3d.org/license.txt .
00013 //
00014 // To contact the maintainers of this program write to
00015 // panda3d@yahoogroups.com .
00016 //
00017 ////////////////////////////////////////////////////////////////////
00018 
00019 
00020 #include "collisionHandlerEvent.h"
00021 #include "config_collide.h"
00022 
00023 #include "eventParameter.h"
00024 #include "throw_event.h"
00025 
00026 
00027 TypeHandle CollisionHandlerEvent::_type_handle;
00028 
00029 ////////////////////////////////////////////////////////////////////
00030 //     Function: CollisionHandlerEvent::Constructor
00031 //       Access: Public
00032 //  Description: The default CollisionHandlerEvent will throw no
00033 //               events.  Its pattern strings must first be set via a
00034 //               call to set_in_pattern() and/or set_out_pattern().
00035 ////////////////////////////////////////////////////////////////////
00036 CollisionHandlerEvent::
00037 CollisionHandlerEvent() {
00038 }
00039 
00040 ////////////////////////////////////////////////////////////////////
00041 //     Function: CollisionHandlerEvent::begin_group
00042 //       Access: Public, Virtual
00043 //  Description: Will be called by the CollisionTraverser before a new
00044 //               traversal is begun.  It instructs the handler to
00045 //               reset itself in preparation for a number of
00046 //               CollisionEntries to be sent.
00047 ////////////////////////////////////////////////////////////////////
00048 void CollisionHandlerEvent::
00049 begin_group() {
00050   if (collide_cat.is_spam()) {
00051     collide_cat.spam()
00052       << "begin_group.\n";
00053   }
00054   _last_colliding.swap(_current_colliding);
00055   _current_colliding.clear();
00056 }
00057 
00058 ////////////////////////////////////////////////////////////////////
00059 //     Function: CollisionHandlerEvent::add_entry
00060 //       Access: Public, Virtual
00061 //  Description: Called between a begin_group() .. end_group()
00062 //               sequence for each collision that is detected.
00063 ////////////////////////////////////////////////////////////////////
00064 void CollisionHandlerEvent::
00065 add_entry(CollisionEntry *entry) {
00066   nassertv(entry != (CollisionEntry *)NULL);
00067 
00068   // Record this particular entry for later.  This will keep track of
00069   // all the unique pairs of node/node intersections.
00070   bool inserted = _current_colliding.insert(entry).second;
00071 
00072   if (collide_cat.is_spam()) {
00073     collide_cat.spam()
00074       << "Detected collision from " << (void *)entry->get_from_node()
00075       << " to " << (void *)entry->get_into_node()
00076       << ", inserted = " << inserted << "\n";
00077   }
00078 }
00079 
00080 ////////////////////////////////////////////////////////////////////
00081 //     Function: CollisionHandlerEvent::end_group
00082 //       Access: Public, Virtual
00083 //  Description: Called by the CollisionTraverser at the completion of
00084 //               all collision detections for this traversal.  It
00085 //               should do whatever finalization is required for the
00086 //               handler.
00087 ////////////////////////////////////////////////////////////////////
00088 bool CollisionHandlerEvent::
00089 end_group() {
00090   // Now compare the list of entries we collected this frame with
00091   // those we kept from the last time.  Each new entry represents a
00092   // new 'in' event; each missing entry represents a new 'out' event.
00093 
00094   if (collide_cat.is_spam()) {
00095     collide_cat.spam()
00096       << "end_group.\n"
00097       << "current_colliding has " << _current_colliding.size()
00098       << " entries, last_colliding has " << _last_colliding.size()
00099       << "\n";
00100   }
00101 
00102   Colliding::iterator ca, cb;
00103 
00104   ca = _current_colliding.begin();
00105   cb = _last_colliding.begin();
00106 
00107   SortEntries order;
00108   while (ca != _current_colliding.end() && cb != _last_colliding.end()) {
00109     if (order(*ca, *cb)) {
00110       // Here's an element in a but not in b.  That's a newly entered
00111       // intersection.
00112       throw_event_pattern(_in_pattern, *ca);
00113       ++ca;
00114 
00115     } else if (order(*cb, *ca)) {
00116       // Here's an element in b but not in a.  That's a newly exited
00117       // intersection.
00118       throw_event_pattern(_out_pattern, *cb);
00119       ++cb;
00120 
00121     } else {
00122       // This element is in both b and a.  It hasn't changed.
00123       throw_event_pattern(_again_pattern, *cb);
00124       ++ca;
00125       ++cb;
00126     }
00127   }
00128 
00129   while (ca != _current_colliding.end()) {
00130     // Here's an element in a but not in b.  That's a newly entered
00131     // intersection.
00132     throw_event_pattern(_in_pattern, *ca);
00133     ++ca;
00134   }
00135 
00136   while (cb != _last_colliding.end()) {
00137     // Here's an element in b but not in a.  That's a newly exited
00138     // intersection.
00139     throw_event_pattern(_out_pattern, *cb);
00140     ++cb;
00141   }
00142 
00143   return true;
00144 }
00145 
00146 ////////////////////////////////////////////////////////////////////
00147 //     Function: CollisionHandlerEvent::clear
00148 //       Access: Public
00149 //  Description: Empties the list of elements that all colliders are
00150 //               known to be colliding with.  No "out" events will be
00151 //               thrown; if the same collision is detected next frame,
00152 //               a new "in" event will be thrown for each collision.
00153 //
00154 //               This can be called each frame to defeat the
00155 //               persistent "in" event mechanism, which prevents the
00156 //               same "in" event from being thrown repeatedly.
00157 //               However, also see set_again_pattern(), which can be
00158 //               used to set the event that is thrown when a collision
00159 //               is detected for two or more consecutive frames.
00160 ////////////////////////////////////////////////////////////////////
00161 void CollisionHandlerEvent::
00162 clear() {
00163   _last_colliding.clear();
00164   _current_colliding.clear();
00165 }
00166 
00167 ////////////////////////////////////////////////////////////////////
00168 //     Function: CollisionHandlerEvent::throw_event_pattern
00169 //       Access: Private
00170 //  Description: Throws an event matching the indicated pattern.
00171 ////////////////////////////////////////////////////////////////////
00172 void CollisionHandlerEvent::
00173 throw_event_pattern(const string &pattern, CollisionEntry *entry) {
00174   if (pattern.empty()) {
00175     return;
00176   }
00177 
00178   string event;
00179   for (size_t p = 0; p < pattern.size(); ++p) {
00180     if (pattern[p] == '%') {
00181       string cmd = pattern.substr(p + 1, 2);
00182       p += 2;
00183       if (cmd == "fn") {
00184         event += entry->get_from_node()->get_name();
00185 
00186       } else if (cmd == "in") {
00187         event += entry->get_into_node()->get_name();
00188 
00189       } else if (cmd == "ft") {
00190         event +=
00191           (!entry->get_from()->is_tangible() ? 'i' : 't');
00192 
00193       } else if (cmd == "it") {
00194         event +=
00195           (entry->has_into() && !entry->get_into()->is_tangible() ? 'i' : 't');
00196 
00197       } else if (cmd == "ig") {
00198         event +=
00199           (entry->has_into() ? 'c' : 'g');
00200 
00201       } else {
00202         collide_cat.error()
00203           << "Invalid symbol in event_pattern: %" << cmd << "\n";
00204       }
00205     } else {
00206       event += pattern[p];
00207     }
00208   }
00209 
00210   if (!event.empty()) {
00211     throw_event(event, EventParameter(entry));
00212   }
00213 }

Generated on Fri May 2 00:35:30 2003 for Panda by doxygen1.3