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.