00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #include "mapzone.h"
00036
00037 #include <fstream>
00038
00039 #include "common/wave_ex.h"
00040 #include "typeinst/typeinst.h"
00041 #include "perf/perf.h"
00042 #include "util/file.h"
00043 #include "util/parsing.h"
00044 #include "util/token_stream.h"
00045
00046
00047 namespace mapzone {
00048
00049
00051
00052
00053
00055
00056
00057
00059
00060
00061
00062
00064
00065 class Reader : public aesop::MapFormatReader {
00066 public:
00067 ~Reader(void) throw() { }
00068
00069
00070 const char * getDescription(void);
00071 bool isMyFormat(IN const char * id,
00072 IN const char * path);
00073 smart_ptr<aesop::Map> loadMap(IN const char * id,
00074 IN const char * path);
00075
00076 private:
00077 };
00078
00079
00080 const char *
00081 Reader::getDescription
00082 (
00083 void
00084 )
00085 {
00086 return "Reference format (mapzone library)";
00087 }
00088
00089
00090
00091 bool
00092 Reader::isMyFormat
00093 (
00094 IN const char * id,
00095 IN const char * path
00096 )
00097 {
00098 ASSERT(id, "null");
00099 ASSERT(path, "null");
00100
00101
00102 if (strcmp("map", GetExtension(path))) {
00103 return false;
00104 }
00105
00106
00107 std::ifstream infile(path);
00108 if (!infile.good()) {
00109 WAVE_EX(wex);
00110 wex << "Failed to open map '" << path << "'.";
00111 }
00112
00113 std::string token;
00114 getNextToken(infile, token);
00115 if ("mapFormat" != token) {
00116 return false;
00117 }
00118 getNextToken(infile, token);
00119 if ("mapzone-0.1" != token) {
00120 return false;
00121 }
00122
00123
00124 return true;
00125 }
00126
00127
00128
00129 smart_ptr<aesop::Map>
00130 Reader::loadMap
00131 (
00132 IN const char * id,
00133 IN const char * path
00134 )
00135 {
00136 ASSERT(id, "null");
00137 ASSERT(path, "null");
00138 ASSERT(this->isMyFormat(id, path),
00139 "Not my format? path='%s'", path);
00140
00141 std::ifstream infile(path);
00142 if (!infile.good()) {
00143 WAVE_EX(wex);
00144 wex << "Failed to open map '" << path << "'";
00145 }
00146
00147
00148 expectToken(infile, "mapFormat");
00149 expectToken(infile, "mapzone-0.1");
00150 expectToken(infile, "map");
00151
00152
00153 return mapzone::loadMap(id, infile);
00154 }
00155
00156
00157
00158
00160
00161
00162
00163
00165
00166 class MapImpl : public aesop::Map {
00167 public:
00168
00169 ~MapImpl(void) throw() { }
00170
00171
00172 void initialize(IN const char * id,
00173 IN std::istream& stream);
00174
00175
00176 const char * getId(void) const throw() { return m_id.c_str(); }
00177 aesop::Zone * getRootZone(void) throw();
00178 aesop::Zone * getZone(IN const char * zone_id);
00179 void iterateZones(IN aesop::zone_iteration_fn callback,
00180 IN void * context);
00181 const char * getDefaultStartingPointId(void) const throw()
00182 { return m_defaultStartId.c_str(); }
00183 void getStartingPointIds(OUT VecString& ids) const;
00184 void getStartingPoint(IN const char * id,
00185 OUT aesop::destination_t& start) const;
00186
00187 private:
00188
00189 typedef std::map<std::string, aesop::destination_t> dest_map_t;
00190
00191
00192 void readDestination(IO std::istream& stream,
00193 OUT aesop::destination_t& dest);
00194
00195
00196 std::string m_id;
00197 std::string m_rootZoneId;
00198 std::string m_defaultStartId;
00199 zone_map_t m_zones;
00200 dest_map_t m_startPoints;
00201 };
00202
00203
00204
00205 void
00206 MapImpl::initialize
00207 (
00208 IN const char * id,
00209 IN std::istream& stream
00210 )
00211 {
00212 perf::Timer timer("mapzone::Map::initialize");
00213 ASSERT(id, "null");
00214 ASSERT(stream.good(), "bad?");
00215
00216
00217 m_id = id;
00218 DPRINTF("Map id='%s'", m_id.c_str());
00219
00220
00221 expectToken(stream, "{");
00222
00223
00224 expectToken(stream, "rootZone");
00225 getNextToken(stream, m_rootZoneId);
00226 DPRINTF("Root zone id='%s'", m_rootZoneId.c_str());
00227
00228
00229 expectToken(stream, "defaultStart");
00230 getNextToken(stream, m_defaultStartId);
00231 DPRINTF("Default start id='%s'", m_defaultStartId.c_str());
00232
00233
00234 for (;;) {
00235
00236 std::string token;
00237 getNextToken(stream, token);
00238 if ("}" == token) {
00239 break;
00240 }
00241
00242 aesop::Zone::eType type = aesop::Zone::eType_Invalid;
00243 if ("leafZone" == token) {
00244 type = aesop::Zone::eType_Leaf;
00245 } else if ("parentZone" == token) {
00246 type = aesop::Zone::eType_Parent;
00247 } else if ("virtualLeafZone" == token) {
00248 type = aesop::Zone::eType_VirtualLeaf;
00249 } else if ("start" == token) {
00250 aesop::destination_t d;
00251 this->readDestination(stream, d);
00252 m_startPoints[d.id] = d;
00253 continue;
00254 } else {
00255 WAVE_EX(wex);
00256 wex << "Invalid zone spec: '" << token << "'";
00257 }
00258 smart_ptr<aesop::Zone> zone = loadZone(stream, type);
00259 ASSERT(zone, "Failed to load zone from stream?");
00260
00261 const char * zone_id = zone->getId();
00262 DPRINTF("Just loaded zone '%s'", zone_id);
00263
00264 if (m_zones.end() != m_zones.find(zone_id)) {
00265 WAVE_EX(wex);
00266 wex << "Multiple zones with same ID? id='";
00267 wex << zone_id << "'";
00268 }
00269 m_zones[zone_id] = zone;
00270 ASSERT(2 == zone.get_ref_count(), "bad ref count?");
00271 }
00272 DPRINTF("Loaded %d zones", (int) m_zones.size());
00273
00274
00275 if (m_zones.end() == m_zones.find(m_rootZoneId)) {
00276 WAVE_EX(wex);
00277 wex << "Root zone id='" << m_rootZoneId << "', but no such ";
00278 wex << "zone exists!";
00279 }
00280
00281
00282 for (zone_map_t::iterator i = m_zones.begin(); i != m_zones.end();
00283 ++i) {
00284 aesop::Zone * z = i->second;
00285 ASSERT(z, "null zone in map?");
00286
00287 resolveZoneIds(z, m_zones);
00288 }
00289
00290
00291 for (zone_map_t::iterator i = m_zones.begin(); i != m_zones.end();
00292 ++i) {
00293 aesop::Zone * z = i->second;
00294 ASSERT(z, "null zone in map?");
00295
00296 calcBoundaries(z);
00297
00298
00299 rect3d_t r;
00300 z->getBoundingRect(r);
00301 r.dump(z->getId());
00302 }
00303 }
00304
00305
00306
00307 aesop::Zone *
00308 MapImpl::getRootZone
00309 (
00310 void
00311 )
00312 throw()
00313 {
00314 return this->getZone(m_rootZoneId.c_str());
00315 }
00316
00317
00318
00319 aesop::Zone *
00320 MapImpl::getZone
00321 (
00322 IN const char * zone_id
00323 )
00324 {
00325 ASSERT(zone_id, "null");
00326
00327 zone_map_t::iterator i = m_zones.find(zone_id);
00328 if (m_zones.end() == i) {
00329 WAVE_EX(wex);
00330 wex << "Failed to find zone with id='" << zone_id << "'";
00331 }
00332
00333 return i->second;
00334 }
00335
00336
00337
00338 void
00339 MapImpl::iterateZones
00340 (
00341 IN aesop::zone_iteration_fn callback,
00342 IN void * context
00343 )
00344 {
00345 ASSERT(callback, "null");
00346
00347
00348 for (zone_map_t::iterator i = m_zones.begin(); i != m_zones.end();
00349 ++i) {
00350 aesop::Zone * z = i->second;
00351 ASSERT(z, "null zone in map");
00352
00353
00354 callback(z, context);
00355 }
00356 }
00357
00358
00359
00360 void
00361 MapImpl::getStartingPointIds
00362 (
00363 OUT VecString& ids
00364 )
00365 const
00366 {
00367 ids.clear();
00368
00369 for (dest_map_t::const_iterator i = m_startPoints.begin();
00370 i != m_startPoints.end(); ++i) {
00371 ids.push_back(i->first);
00372 }
00373 }
00374
00375
00376
00377 void
00378 MapImpl::getStartingPoint
00379 (
00380 IN const char * id,
00381 OUT aesop::destination_t& start
00382 )
00383 const
00384 {
00385 ASSERT(id, "null");
00386
00387 dest_map_t::const_iterator i = m_startPoints.find(id);
00388 if (m_startPoints.end() == i) {
00389 WAVE_EX(wex);
00390 wex << "Invalid start point: " << id;
00391 }
00392
00393 start = i->second;
00394 }
00395
00396
00397
00399
00400
00401
00403
00404 void
00405 MapImpl::readDestination
00406 (
00407 IO std::istream& stream,
00408 OUT aesop::destination_t& dest
00409 )
00410 {
00411 ASSERT(stream.good(), "bad?");
00412 dest.clear();
00413
00414 std::string token;
00415
00416
00417 expectToken(stream, "{");
00418 expectToken(stream, "id");
00419 getNextToken(stream, token);
00420 if (token.length() > aesop::eAESOP_MaxIdLength) {
00421 WAVE_EX(wex);
00422 wex << "Invalid id: " << token;
00423 }
00424 strcpy(dest.id, token.c_str());
00425
00426
00427 expectToken(stream, "rect");
00428 token = getNextLineFromStream(stream, eParse_Strip);
00429 parseRect3d(token.c_str(), dest.rect);
00430
00431
00432 expectToken(stream, "}");
00433 }
00434
00435
00436
00438
00439
00440
00442
00443 smart_ptr<aesop::Map>
00444 loadMap
00445 (
00446 IN const char * id,
00447 IN std::istream& stream
00448 )
00449 {
00450 ASSERT(id, "null");
00451 ASSERT(stream.good(), "not good?");
00452
00453 smart_ptr<MapImpl> local = new MapImpl;
00454 ASSERT(local, "out of memory");
00455
00456 local->initialize(id, stream);
00457
00458 return local;
00459 }
00460
00461
00462
00463 smart_ptr<aesop::MapFormatReader>
00464 getMapFormatReader
00465 (
00466 void
00467 )
00468 {
00469 smart_ptr<Reader> local = new Reader;
00470 ASSERT(local, "out of memory");
00471
00472 return local;
00473 }
00474
00475
00476
00477 };
00478