AreaManager.cpp

Go to the documentation of this file.
00001 /*
00002 SagaEngine library
00003 Copyright (c) 2002-2006 Skalden Studio AS
00004 
00005 This software is provided 'as-is', without any express or implied 
00006 warranty. In no event will the authors be held liable for any 
00007 damages arising from the use of this software.
00008 
00009 Permission is granted to distribute the library under the terms of the 
00010 Q Public License version 1.0. Be sure to read and understand the license
00011 before using the library. It should be included here, or you may read it
00012 at http://www.trolltech.com/products/qt/licenses/licensing/qpl
00013 
00014 The original version of this library can be located at:
00015 http://www.sagaengine.com/
00016 
00017 Rune Myrland
00018 rune@skalden.com
00019 */
00020 
00021 
00022 #include "AreaManager.hpp"
00023 #include "Area.hpp"
00024 #include "AreaFactory.hpp"
00025 #include "util/error/Log.hpp"
00026 #include "sim/schema/SimSchema.hpp"
00027 #include "comp/schema/CompSchema.hpp"
00028 #include "sim/zone/ZoneAreaComponent.hpp"
00029 #include <cstring>
00030 #include <cstdio>
00031 
00032 
00033 namespace se_core {
00034 
00035     AreaManager
00036     ::AreaManager() 
00037             : areaCount_(0), factoryCount_(0), activeCount_(0)
00038             , maxWidth_(0), maxHeight_(0) {
00039         areas_ = new Area*[ MAX_ELEMENTS ];
00040         factories_ = new const AreaFactory*[ MAX_FACTORIES ];
00041         active_ = new Area*[ MAX_ACTIVE ];
00042         shouldKeep_ = new bool[ MAX_ACTIVE ];
00043         LogDetail("Creating AreaManager");
00044     }
00045 
00046 
00047     AreaManager
00048     ::~AreaManager() {
00049         resetAll();
00050         delete[] areas_;
00051         delete[] active_;
00052         delete[] factories_;
00053         delete[] shouldKeep_;
00054         LogDetail("Destroying AreaManager");
00055     }
00056 
00057 
00058     void AreaManager
00059     ::addArea(Area* area) {
00060         Assert(areaCount_ < MAX_ELEMENTS && "Too many elements. Adjust MAX_ELEMENTS.");
00061 
00062         if(area->width() > maxWidth_)
00063             maxWidth_ = area->width();
00064         if(area->height() > maxHeight_)
00065             maxHeight_ = area->height();
00066 
00067 
00068         // Init neighbours
00069         for(int i = 0; i < areaCount_; ++i) {
00070             if(areas_[i]->isNeighbour( *area )) {
00071                 areas_[i]->addNeighbour( area );
00072             }
00073 
00074             if(area->isNeighbour( *areas_[i] )) {
00075                 area->addNeighbour(areas_[i]);
00076             }
00077         }
00078 
00079         // Add area to repository
00080         areas_[ areaCount_++ ] = area;
00081     }
00082 
00083 
00084     Area* AreaManager
00085     ::area(const char* name) {
00086         for(int i = 0; i < areaCount_; ++i) {
00087             if(strcmp(areas_[ i ]->name(), name) == 0) {
00088                 return areas_[ i ];
00089             }
00090         }
00091         LogFatal("Couldn't find area: " << name);
00092         return 0;
00093     }
00094 
00095 
00096     int AreaManager
00097     ::areasByFactory(const char* name, Area** dest, int maxCount) {
00098         int c = 0;
00099         for(int i = 0; i < areaCount_; ++i) {
00100             Assert(areas_[ i ]->owner()->factory());
00101             Assert(areas_[ i ]->owner()->factory()->name());
00102             if(strcmp(areas_[ i ]->owner()->factory()->name(), name) == 0) {
00103                 dest[ c++ ] = areas_[ i ];
00104                 if(c >= maxCount)
00105                     break;
00106             }
00107         }
00108         return c;
00109     }
00110 
00111 
00112     bool AreaManager
00113     ::hasArea(const char* name) {
00114         for(int i = 0; i < areaCount_; ++i) {
00115             if(strcmp(areas_[ i ]->name(), name) == 0) {
00116                 return true;
00117             }
00118         }
00119         return false;
00120     }
00121 
00122 
00123     Area* AreaManager
00124     ::areaById(Composite::id_type id) {
00125         for(int i = 0; i < areaCount_; ++i) {
00126             if(areas_[ i ]->owner()->id() == id) {
00127                 return areas_[ i ];
00128             }
00129         }
00130         LogFatal("Couldn't find area");
00131         return 0;
00132     }
00133 
00134 
00135     Area* AreaManager
00136     ::active(int index) {
00137         Assert(index >= 0 && index < areaCount_);
00138         return active_[ index ];
00139     }
00140 
00141 
00142     void AreaManager
00143     ::setActive(Area* area) {
00144         for(int i = 0; i < activeCount_; ++i) {
00145             if(area == active_[i]) {
00146                 shouldKeep_[i] = true;
00147                 return;
00148             }
00149         }
00150 
00151         active_[ activeCount_ ] = area;
00152         active_[ activeCount_ ]->owner()->setParent(CompSchema::activeRoot());
00153         shouldKeep_[ activeCount_ ] = true;
00154         ++activeCount_;
00155 
00156         DebugExec(integrity());
00157     }
00158 
00159 
00160     void AreaManager
00161     ::setActive(Area* area, int pages) {
00162         for(int i = 0; i < activeCount_; ++i)
00163             shouldKeep_[i] = false;
00164 
00165         setActive(area);
00166         if(pages > 0) {
00167             _setActive(area, pages);
00168         }
00169 
00170         /*
00171         for(short relZ = -pages; relZ <= pages; ++relZ) {
00172             for(short relX = -pages; relX <= pages; ++relX) {
00173                 Area* a = area->neighbour(relX, 0, relZ);
00174                 if(!a) continue;
00175                 
00176                 // Already active?
00177                 int index = -1;
00178                 for(int i = 0; i < activeCount_; ++i) {
00179                     if(a == active_[i]) {
00180                         index = i;
00181                         break;
00182                     }
00183                 }
00184 
00185 
00186                 // Nope?
00187                 if(index < 0) {
00188                     // Make it active
00189                     index = activeCount_;
00190                     active_[ index ] = a;
00191                     a->setParent(CompSchema::activeRoot());
00192                     ++activeCount_;
00193                 }
00194                 
00195                 // Should keep it as active
00196                 shouldKeep_[ index ] = true;
00197             }
00198         }
00199         */
00200 
00201         DebugExec(integrity());
00202 
00203         // Remove inactive
00204         for(int i = 0; i < activeCount_; ++i) {
00205             Assert(active_[i]);
00206             if(!shouldKeep_[i]) {
00207                 Area* a = active_[i];
00208                 Assert(a);
00209                 a->owner()->setParent(CompSchema::inactiveRoot());
00210 
00211                 // Delete current by moving last to here
00212                 --activeCount_;
00213                 active_[ i ] = active_[ activeCount_ ];
00214                 shouldKeep_[ i ] = shouldKeep_[ activeCount_ ];
00215                 active_[ activeCount_ ] = 0;
00216 
00217                 // Do this index again, as it now contains new area
00218                 --i;
00219             }
00220         }
00221 
00222         DebugExec(integrity());
00223     }
00224 
00225 
00226     void AreaManager
00227     ::_setActive(Area* area, int pages) {
00228         ZoneAreaComponent::Ptr aZone(*area);
00229         ComponentList::Iterator it(aZone->links());
00230         while(it.hasNext()) {
00231             Area::Ptr a(it.next());
00232             // Already did self
00233             if(a->owner() == area->owner())
00234                 continue;
00235 
00236             // Already active?
00237             int index = -1;
00238             for(int i = 0; i < activeCount_; ++i) {
00239                 if(a->owner() == active_[i]->owner()) {
00240                     index = i;
00241                     break;
00242                 }
00243             }
00244 
00245             // Nope?
00246             if(index < 0) {
00247                 // Make it active
00248                 index = activeCount_;
00249                 active_[ index ] = a;
00250                 a->owner()->setParent(CompSchema::activeRoot());
00251                 ++activeCount_;
00252             }
00253             
00254             // Should keep it as active
00255             shouldKeep_[ index ] = true;
00256 
00257             if(pages > 1) {
00258                 _setActive(a, pages - 1);
00259             }
00260 
00261         }
00262     }
00263 
00264 
00265     void AreaManager
00266     ::setInactive(Area* area) {
00267         for(int i = 0; i < activeCount_; ++i) {
00268             if(area == active_[i]) {
00269                 area->owner()->setParent(CompSchema::inactiveRoot());
00270 
00271                 --activeCount_;
00272                 active_[ i ] = active_[ activeCount_ ];
00273                 active_[ activeCount_ ] = 0;
00274             }
00275         }
00276 
00277         DebugExec(integrity());
00278     }
00279 
00280 
00281 
00282     void AreaManager
00283     ::resetActive() {
00284         while(activeCount_ > 0) {
00285             setInactive(active_[0]);
00286         }
00287 
00288         DebugExec(integrity());
00289     }
00290 
00291     void AreaManager
00292     ::addFactory(const AreaFactory* f) {
00293         factories_[ factoryCount_++ ] = f;
00294     }
00295 
00296 
00297     const AreaFactory* AreaManager
00298     ::factory(const char* name) const {
00299         for(int i = 0; i < factoryCount_; ++i) {
00300             if(strcmp(factories_[ i ]->name(), name) == 0) {
00301                 return factories_[i];
00302             }
00303         }
00304         LogFatal("AreaFactory '" << name << "' does not exist.");
00305         return 0;
00306     }
00307 
00308 
00309     Area* AreaManager
00310     ::createArea(const char* areaName, const char* factoryName, int pageX, int pageY, int pageZ, int gridId) {
00311         char* name = new char[strlen(areaName) + 1];
00312         strcpy(name, areaName);
00313         //LogDetail("Created area: " << name);
00314 
00315         const AreaFactory* f = factory(factoryName);
00316         Composite* a = f->create(new String(name), pageX, pageY, pageZ, gridId);
00317         // Needed for proper destruction
00318         a->setFactory(f);
00319 
00320 
00321         PosComponent::Ptr aPos(*a);
00322 
00323         // Update world coordinate
00324         aPos->updateWorldViewPoint();
00325 
00326         // Make sure both nextPos() and pos() are good
00327         aPos->flip();
00328 
00329 
00330         // Store it away
00331         Area::Ptr area(a);
00332         addArea(area);
00333 
00334         return area;
00335     }
00336 
00337 
00338     void AreaManager
00339     ::resetThings() {
00340         for(int i = 0; i < areaCount_; ++i) {
00341             areas_[ i ]->reset();
00342             areas_[ i ]->owner()->cleanup();
00343         }
00344         LogDetail("Destoryed things");
00345     }
00346 
00347 
00348     void AreaManager
00349     ::resetAll() {
00350         resetActive();
00351         resetThings();
00352 
00353         for(int i = 0; i < areaCount_; ++i) {
00354             if(areas_[i]->owner()->factory())
00355                 areas_[i]->owner()->factory()->release(areas_[i]->owner());
00356             else
00357                 delete areas_[ i ]->owner();
00358         }
00359         areaCount_ = 0;
00360         LogDetail("Destroyed areas");
00361 
00362         for(int i = 0; i < factoryCount_; ++i) {
00363             delete factories_[i];
00364         }
00365         factoryCount_ = 0;
00366         LogDetail("Destroyed area factories");
00367     }
00368 
00369 
00370     void AreaManager
00371 	::dump() {
00372         puts("Dumping repository...");
00373         for(int i = 0; i < areaCount_; ++i) {
00374             printf("%d - %s\n", (size_t)areas_[i]->owner()->id(), areas_[i]->owner()->name());
00375         }
00376     }
00377 
00378 
00379     void AreaManager
00380     ::integrity() {
00381         for(int i = 0; i < activeCount_ - 1; ++i) {
00382             for(int j = i + 1; j < activeCount_; ++j) {
00383                 if(active_[i] == active_[j]) {
00384                     LogFatal(i << " == " << j);
00385                 }
00386             }
00387         }
00388     }
00389 
00390 
00391 }

Home Page | SagaEngine trunk (updated nightly) reference generated Sun Dec 2 20:06:11 2007 by Doxygen version 1.3.9.1.

SourceForge.net Logo