Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Class Members | File Members | Related Pages

ScenerySet.cpp

Go to the documentation of this file.
00001 /*
00002  * ScenerySet.cpp
00003  *
00004  * Part of Fly! Legacy project
00005  *
00006  * Copyright 2004 Chris Wallace
00007  *
00008  * Fly! Legacy is free software; you can redistribute it and/or modify
00009  *   it under the terms of the GNU General Public License as published by
00010  *   the Free Software Foundation; either version 2 of the License, or
00011  *   (at your option) any later version.
00012  *
00013  * Fly! Legacy is distributed in the hope that it will be useful,
00014  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  *   GNU General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU General Public License
00019  *   along with Fly! Legacy; if not, write to the Free Software
00020  *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00021  *
00022  */
00023 
00028 #include "../Include/FlyLegacy.h"
00029 #include "../Include/Globals.h"
00030 #include "../Include/Ui.h"
00031 #include "../Include/Terrain.h"
00032 
00033 using namespace std;
00034 
00035 CScenerySet::CScenerySet (const char* baseFolder,
00036                           const char* scfFolder,
00037                           const char* scfFilename)
00038 {
00039   char fullname[1024];
00040   strcpy (fullname, scfFolder);
00041   strcat (fullname, "\\");
00042   strcat (fullname, scfFilename);
00043 
00044   // Attempt to open scenery file stream
00045   SStream *s = new SStream;
00046   strcpy (s->filename, fullname);
00047   strcpy (s->mode, "r");
00048   if (OpenStream (s)) {
00049     ReadFrom (this, s);
00050     CloseStream (s);
00051   }
00052   delete s;
00053 
00054   // Save base pathname, SCF pathname and SCF filename
00055   strcpy (this->baseFolder, baseFolder);
00056   strcpy (this->scfFolder, scfFolder);
00057   strcpy (this->scfFilename, scfFilename);
00058 
00059   // Default state is unloaded
00060   refCount = 0;
00061   loaded = false;
00062   pfs = NULL;
00063 }
00064 
00065 CScenerySet::~CScenerySet (void)
00066 {
00067   // Ensure scenery set is unloaded
00068   if (loaded) Unload ();
00069 }
00070 
00071 int CScenerySet::Read (SStream *stream, Tag tag)
00072 {
00073   int rc = TAG_IGNORED;
00074 
00075   char file[64];
00076 
00077   switch (tag) {
00078   case 'call':
00079     ReadLatLon (&call, stream);
00080     rc = TAG_READ;
00081     break;
00082   case 'caur':
00083     ReadLatLon (&caur, stream);
00084     rc = TAG_READ;
00085     break;
00086   case 'ldll':
00087     ReadLatLon (&ldll, stream);
00088     rc = TAG_READ;
00089     break;
00090   case 'ldur':
00091     ReadLatLon (&ldur, stream);
00092     rc = TAG_READ;
00093     break;
00094   case 'file':
00095     {
00096       ReadString (file, 64, stream);
00097       podList.push_back (file);
00098     }
00099     rc = TAG_READ;
00100     break;
00101   }
00102 
00103   return rc;
00104 }
00105 
00106 //
00107 // Check whether the given position is within the lower-left (SW) and upper-right (NE)
00108 //   boundaries of the load area
00109 //
00110 bool CScenerySet::InLoadRange (SPosition pos)
00111 {
00112   return ((pos.lat >= ldll.lat) && (pos.lat <= ldur.lat) &&
00113           (pos.lon >= ldll.lon) && (pos.lon <= ldur.lon));
00114 }
00115 
00116 //
00117 // Check whether the given position is within the lower-left (SW) and upper-right (NE)
00118 //   boundaries of the coverage
00119 //
00120 bool CScenerySet::InCoverageRange (SPosition pos)
00121 {
00122   return ((pos.lat >= call.lat) && (pos.lat <= caur.lat) &&
00123           (pos.lon >= call.lon) && (pos.lon <= caur.lon));
00124 }
00125 
00126 bool CScenerySet::IsLoaded (void)
00127 {
00128   return loaded;
00129 }
00130 
00131 int  CScenerySet::GetRefCount (void)
00132 {
00133   return refCount;
00134 }
00135 
00136 void CScenerySet::IncRefCount (void)
00137 {
00138   refCount++;
00139 }
00140 
00141 void CScenerySet::DecRefCount (void)
00142 {
00143   --refCount;
00144 }
00145 
00146 void CScenerySet::Load (void)
00147 {
00148   IncRefCount();
00149 
00150   // Check if set is already loaded
00151   if (!IsLoaded()) {
00152     // Add individual pods to the filesystem
00153     vector<string>::iterator i;
00154     for (i=podList.begin(); i!=podList.end(); i++) {
00155       char podName[1024];
00156       strcpy (podName, scfFolder);
00157       strcat (podName, "\\");
00158       strcat (podName, i->c_str());
00159       paddpod (&globals->pfs, podName);
00160     }
00161 
00162     // Set loaded flag
00163     loaded = true;
00164 
00165     // Debug
00166     char debug[80];
00167     sprintf (debug, "Loaded scenery set : %s", scfFilename);
00168     DrawNoticeToUser (debug, 5);
00169   }
00170 
00171   DEBUGLOG ("Load scenery set %s, ref count = %d", scfFilename, refCount);
00172 }
00173 
00174 void CScenerySet::Unload (void)
00175 {
00176   if (IsLoaded()) {
00177     // Decrement reference count and unload if necessary
00178     DecRefCount();
00179     if (GetRefCount() <= 0) {
00180       // Remove individual pods from the scenery filesystem
00181       vector<string>::iterator i;
00182       for (i=podList.begin(); i!=podList.end(); i++) {
00183         premovepod (&globals->pfs, i->c_str());
00184       }
00185   
00186       // Clear loaded flag
00187       loaded = false;
00188 
00189       DEBUGLOG ("Unload scenery set %s, ref count = %d", scfFilename, refCount);
00190     }
00191   }
00192 }
00193 
00194 CScenerySetDatabase *ssdb;
00195 
00196 //
00197 // CScenerySetDatabase
00198 //
00199 
00200 CScenerySetDatabase::CScenerySetDatabase (void)
00201 {
00202   Init ();
00203 }
00204 
00205 CScenerySetDatabase::~CScenerySetDatabase (void)
00206 {
00207   Purge ();
00208 }
00209 
00210 //
00211 // Unload and delete all scenery sets
00212 //
00213 void CScenerySetDatabase::Purge (void)
00214 {
00215   set<CScenerySet*>::iterator i;
00216   for (i=setActive.begin(); i!=setActive.end(); i++) delete *i;
00217   setActive.empty();
00218 
00219   for (i=setInactive.begin(); i!=setInactive.end(); i++) delete *i;
00220   setInactive.empty();
00221 }
00222 
00223 //
00224 // Search a directory for any scenery control files
00225 //
00226 void CScenerySetDatabase::LoadInFolder (const char* base, const char *path)
00227 {
00228   char fullpath[1024];
00229   strcpy (fullpath, base);
00230   strcat (fullpath, "\\");
00231   strcat (fullpath, path);
00232 
00233   // Iterate over all files in this folder.  Sub-folders are ignored
00234   ulDir* dirp = ulOpenDir (fullpath);
00235   if (dirp != NULL) {
00236     ulDirEnt* dp;
00237     while ((dp = ulReadDir(dirp)) != NULL ) {
00238       if (dp->d_isdir) {
00239         // This is a sub-folder, ignore it
00240         continue;
00241       } else {
00242         // Check for file extension .SCF
00243         char *c = strrchr (dp->d_name, '.');
00244         if (stricmp (c, ".SCF") == 0) {
00245           CScenerySet *set = new CScenerySet (base, path, dp->d_name);
00246           setInactive.insert (set);
00247         }
00248       }
00249     }
00250     ulCloseDir(dirp);
00251   }
00252 }
00253 
00254 //
00255 // Search for any scenery files that describe sliced scenery areas.
00256 // Scenery files are stream files with no extension that reside in
00257 //   a sub-directory from the \Scenery folder.
00258 //
00259 
00261 
00262 void CScenerySetDatabase::Init (void)
00263 {
00264   char base[1024];
00265   strcpy (base, "");
00266   GetIniString ("UI", "flyRootFolder", base, 1024);
00267   if (strlen (base) == 0) {
00268     strcpy (base, "C:\\Program Files\\Terminal Reality\\Fly! II");
00269   }
00270 
00271   // Search the Scenery folder for any sub-directories, which are individually
00272   //   searched for SCF files
00273   char searchPath[1024];
00274   strcpy (searchPath, base);
00275   strcat (searchPath, "\\Scenery");
00276   ulDir* dirp = ulOpenDir (searchPath);
00277   if (dirp != NULL) {
00278     ulDirEnt* dp;
00279     while ((dp = ulReadDir(dirp)) != NULL )
00280     {
00281       if (dp->d_isdir &&
00282           (strcmp (dp->d_name, ".") != 0) &&
00283           (strcmp (dp->d_name, "..") != 0))
00284       {
00285         // This is a sub-folder, attempt to load scenery files in it
00286         char path[1024];
00287         strcpy (path, "Scenery\\");
00288         strcat (path, dp->d_name);
00289         LoadInFolder (base, path);
00290       }
00291     }
00292     ulCloseDir(dirp);
00293   }
00294 }
00295 
00296 //
00297 //  Registration of a position is the trigger for loading of available
00298 //    scenery sets.
00299 //    1. Check the position against the load area boundaries for every
00300 //         scenery set in the inactive set.  If a match is found, move
00301 //         the scenery set to the active set with ref counter of 1.
00302 //    2. Check the position against the load area boundaries of every
00303 //         scenery set in the active set.  If a match is found, increment
00304 //         the ref counter.
00305 //
00306 void CScenerySetDatabase::Register (SPosition pos)
00307 {
00308   // Search inactive set list
00309   set<CScenerySet*>::iterator i;
00310   for (i=setInactive.begin(); i!=setInactive.end(); i++) {
00311     CScenerySet *cset = *i;
00312     if (cset->InLoadRange (pos)) {
00313       // Position is in the load region; move this set from the inactive
00314       //   to the active list and ensure it is loaded
00315       setInactive.erase(cset);
00316       setActive.insert(cset);
00317       cset->Load();
00318     }
00319   }
00320   
00321   // Search active set list
00322   for (i=setActive.begin(); i!=setActive.end(); i++) {
00323     CScenerySet *cset = *i;
00324     if (cset->InLoadRange (pos)) {
00325       // Position is in the load region for the set; the Load() method
00326       //   will ensure the set is loaded, or increment the ref count
00327       cset->Load();
00328     }
00329   }
00330 }
00331 
00332 //
00333 //  Deregistration of a position is the trigger for unloading scenery sets.
00334 //    1. Check the position against the load area boundaries for every
00335 //         scenery set in the active set.  If a match is found, decrement
00336 //         the ref counter.  If the counter is zero, unload the set and
00337 //         move it to the inactive set.
00338 //
00339 void CScenerySetDatabase::Deregister (SPosition pos)
00340 {
00341   // Search active set list
00342   set<CScenerySet*>::iterator i;
00343   for (i=setActive.begin(); i!=setActive.end(); i++) {
00344     CScenerySet *cset = *i;
00345     if (!(cset->InLoadRange (pos))) {
00346       // Position is not in the load region for the set; the Unload() method
00347       //   decrement the ref count and unload the set when ref count reaches 0
00348       cset->Unload();
00349       if (cset->GetRefCount() <= 0) {
00350         // Move the set from the active to inactive lists
00351         setActive.erase(cset);
00352         setInactive.insert(cset);
00353       }
00354     }
00355   }
00356 }
00357 
SourceForge.net Logo Documentation generated by doxygen