tqueue.cc

Go to the documentation of this file.
00001 /*
00002  *  tqueue.cc - A queue of time-based events for animation.
00003  *
00004  *  Copyright (C) 2000-2001  The Exult Team
00005  *
00006  *  This program is free software; you can redistribute it and/or modify
00007  *  it under the terms of the GNU General Public License as published by
00008  *  the Free Software Foundation; either version 2 of the License, or
00009  *  (at your option) any later version.
00010  *
00011  *  This program is distributed in the hope that it will be useful,
00012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  *  GNU General Public License for more details.
00015  *
00016  *  You should have received a copy of the GNU General Public License
00017  *  along with this program; if not, write to the Free Software
00018  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00019  */
00020 
00021 #ifdef HAVE_CONFIG_H
00022 #  include <config.h>
00023 #endif
00024 
00025 #include "tqueue.h"
00026 #include <algorithm>
00027 #include <SDL_timer.h>
00028 
00029 /*
00030  *  Be sure no copies are still in queue when deleted.
00031  */
00032 
00033 Time_sensitive::~Time_sensitive
00034   (
00035   )
00036   {
00037 #if 0 /*+++++++For finding bugs. */
00038   if (queue_cnt > 0)
00039     {
00040     char *p = 0;
00041     char c = *p;    // Force crash.
00042     }
00043 #endif
00044   }
00045 
00046 /*
00047  *  Remove all entries.
00048  */
00049 
00050 void Time_queue::clear
00051   (
00052   )
00053   {
00054   Temporal_sequence::iterator it;
00055   while ((it=data.begin()) != data.end())
00056     {
00057     Queue_entry ent = *it;
00058     Time_sensitive *obj = ent.handler;
00059     data.erase(it);
00060     obj->queue_cnt--;
00061     }
00062   }
00063 
00064 /*
00065  *  Add an entry to the queue.
00066  */
00067 
00068 void Time_queue::add
00069   (
00070   uint32 t,   // When entry is to be activated.
00071   Time_sensitive *obj,    // Object to be added.
00072   long ud       // User data.
00073   )
00074   {
00075   obj->queue_cnt++;   // It's going in, no matter what.
00076   Queue_entry newent;
00077   if (paused && !obj->always) // Paused?
00078           // Messy, but we need to fix time.
00079     t -= SDL_GetTicks() - pause_time;
00080   newent.set(t,obj,ud);
00081   if(!data.size())
00082     {
00083     data.push_back(newent);
00084     return;
00085     }
00086   for(Temporal_sequence::iterator it=data.begin();
00087     it!=data.end(); ++it)
00088     {
00089     if(newent<*it)
00090       {
00091       data.insert(it,newent);
00092       return;
00093       }
00094     }
00095   data.push_back(newent);
00096   }
00097 
00098 bool    operator <(const Queue_entry &q1,const Queue_entry &q2)
00099 {
00100         if(q1.time<q2.time)
00101                 return true;
00102         return false;
00103 }
00104 
00105 /*
00106  *  Remove first entry containing a given object.
00107  *
00108  *  Output: 1 if found, else 0.
00109  */
00110 
00111 int Time_queue::remove
00112   (
00113   Time_sensitive *obj
00114   )
00115   {
00116   if(data.size()==0)
00117     return 0;
00118   for(Temporal_sequence::iterator it=data.begin();
00119     it!=data.end(); ++it)
00120     {
00121     if(it->handler==obj)
00122       {
00123       obj->queue_cnt--;
00124       data.erase(it);
00125       return 1;
00126       }
00127     }
00128   return (0);     // Not found.
00129   }
00130 
00131 /*
00132  *  Remove first entry containing a given object and data.
00133  *
00134  *  Output: 1 if found, else 0.
00135  */
00136 
00137 int Time_queue::remove
00138   (
00139   Time_sensitive *obj,
00140   long udata
00141   )
00142   {
00143   if(data.size()==0)
00144     return 0;
00145   for(Temporal_sequence::iterator it=data.begin();
00146     it!=data.end(); ++it)
00147     {
00148     if(it->handler==obj && it->udata == udata)
00149       {
00150       obj->queue_cnt--;
00151       data.erase(it);
00152       return 1;
00153       }
00154     }
00155   return (0);     // Not found.
00156   }
00157 
00158 /*
00159  *  See if a given entry is in the queue.
00160  *
00161  *  Output: 1 if found, else 0.
00162  */
00163 
00164 int Time_queue::find
00165   (
00166   Time_sensitive *obj
00167   )
00168   {
00169   if(data.size()==0)
00170     return 0;
00171   for(Temporal_sequence::iterator it=data.begin();
00172     it!=data.end(); ++it)
00173     {
00174     if(it->handler==obj)
00175       return 1;
00176     }
00177   return 0;
00178   }
00179 
00180 /*
00181  *  Find when an entry is due.
00182  *
00183  *  Output: delay in msecs. when due, or -1 if not in queue.
00184  */
00185 
00186 long Time_queue::find_delay
00187   (
00188   Time_sensitive *obj,
00189   uint32 curtime
00190   )
00191   {
00192   if(data.size()==0)
00193     return -1;
00194   for(Temporal_sequence::iterator it=data.begin();
00195     it!=data.end(); ++it)
00196     {
00197     if(it->handler==obj)
00198       {
00199       if (pause_time) // Watch for case when paused.
00200         curtime = pause_time;
00201       long delay = it->time - curtime;
00202       return delay >= 0 ? delay : 0;
00203       }
00204     }
00205   return -1;
00206   }
00207 
00208 /*
00209  *  Remove & activate entries that are due, starting with head (already
00210  *  known to be due).
00211  */
00212 
00213 void Time_queue::activate0
00214   (
00215   uint32 curtime    // Current time.
00216   )
00217   {
00218   if(data.size()==0)
00219     return;
00220   Queue_entry ent;
00221   do
00222     {
00223     ent=data.front();
00224     Time_sensitive *obj = ent.handler;
00225     long udata = ent.udata;
00226     data.pop_front(); // Remove from chain.
00227     obj->queue_cnt--;
00228     obj->handle_event(curtime, udata);
00229     }
00230   while (data.size() && !(curtime < data.front().time));
00231   }
00232 
00233 /*
00234  *  Remove & activate entries marked 'always'.  This is called when
00235  *  the queue is paused.
00236  */
00237 
00238 void Time_queue::activate_always
00239   (
00240   uint32 curtime    // Current time.
00241   )
00242   {
00243   if(data.size()==0)
00244     return;
00245   Queue_entry ent;
00246   for(Temporal_sequence::iterator it=data.begin();
00247     it!=data.end() && !(curtime < (*it).time); )
00248     {
00249     Temporal_sequence::iterator next = it;
00250     ++next;     // Get ->next in case we erase.
00251     ent = *it;
00252     Time_sensitive *obj = ent.handler;
00253     if (obj->always)
00254       {
00255       obj->queue_cnt--;
00256       long udata = ent.udata;
00257       data.erase(it);
00258       obj->handle_event(curtime, udata);
00259       }
00260     it = next;
00261     }
00262   }
00263 
00264 /*
00265  *  Resume after a pause.
00266  */
00267 
00268 void Time_queue::resume
00269   (
00270   uint32 curtime
00271   )
00272   {
00273   if (!paused || --paused > 0)  // Only unpause when stack empty.
00274     return;     // Not paused.
00275   int diff = curtime - pause_time;
00276   pause_time = 0;
00277   if (diff < 0)     // Should not happen.
00278     return;
00279   for(Temporal_sequence::iterator it=data.begin();
00280     it!=data.end(); ++it)
00281     {
00282     if (!(*it).handler->always)
00283       it->time += diff; // Push entries ahead.
00284     }
00285   }
00286 
00287 /*
00288  *  Get next element in queue.
00289  */
00290 
00291 int Time_queue_iterator::operator()
00292   (
00293   Time_sensitive *& obj,    // Main object.
00294   long& data      // Data that was added with it.
00295   )
00296   {
00297   while (iter != tqueue->data.end() && this_obj &&
00298             (*iter).handler != this_obj)
00299     ++iter;
00300   if (iter == tqueue->data.end())
00301     return (0);
00302   obj = (*iter).handler;    // Return fields.
00303   data = (*iter).udata;
00304   ++iter;       // On to the next.
00305   return (1);
00306   }
00307 

Generated on Mon Jul 9 14:42:51 2007 for ExultEngine by  doxygen 1.5.1