00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <string>
00024 #include <vector>
00025
00026
00027
00028
00029
00030
00031
00032 #include "ext/tinyxml/fife_tinyxml.h"
00033 #include "model/model.h"
00034 #include "model/structures/layer.h"
00035 #include "model/structures/instance.h"
00036 #include "model/metamodel/grids/cellgrid.h"
00037 #include "model/metamodel/modelcoords.h"
00038 #include "model/metamodel/action.h"
00039 #include "vfs/fife_boost_filesystem.h"
00040 #include "vfs/vfs.h"
00041 #include "vfs/vfsdirectory.h"
00042 #include "vfs/raw/rawdata.h"
00043 #include "util/base/exception.h"
00044 #include "util/log/logger.h"
00045 #include "util/resource/resource.h"
00046 #include "util/structures/rect.h"
00047 #include "video/imagemanager.h"
00048 #include "video/image.h"
00049 #include "video/renderbackend.h"
00050 #include "view/visual.h"
00051 #include "view/camera.h"
00052 #include "view/renderers/instancerenderer.h"
00053 #include "util/base/stringutils.h"
00054
00055 #include "atlasloader.h"
00056 #include "maploader.h"
00057 #include "animationloader.h"
00058 #include "objectloader.h"
00059
00060 namespace FIFE {
00061 static Logger _log(LM_NATIVE_LOADERS);
00062
00063 MapLoader::MapLoader(Model* model, VFS* vfs, ImageManager* imageManager, RenderBackend* renderBackend)
00064 : m_model(model), m_vfs(vfs), m_imageManager(imageManager), m_renderBackend(renderBackend),
00065 m_loaderName("fife"), m_mapDirectory("") {
00066 AnimationLoaderPtr animationLoader(new AnimationLoader(m_vfs, m_imageManager));
00067 m_objectLoader.reset(new ObjectLoader(m_model, m_vfs, m_imageManager, animationLoader));
00068 m_atlasLoader.reset(new AtlasLoader(m_model, m_vfs, m_imageManager));
00069 }
00070
00071 MapLoader::~MapLoader() {
00072
00073 }
00074
00075 Map* MapLoader::load(const std::string& filename) {
00076 Map* map = NULL;
00077
00078
00079
00080 m_percentDoneListener.reset();
00081
00082 bfs::path mapPath(filename);
00083
00084 if (HasParentPath(mapPath)) {
00085 if (GetParentPath(mapPath).string() != m_mapDirectory) {
00086
00087 m_mapDirectory = GetParentPath(mapPath).string();
00088 }
00089 }
00090
00091 TiXmlDocument mapFile;
00092
00093 std::string mapFilename = mapPath.string();
00094
00095 try {
00096 RawData* data = m_vfs->open(mapFilename);
00097
00098 if (data) {
00099 if (data->getDataLength() != 0) {
00100 mapFile.Parse(data->readString(data->getDataLength()).c_str());
00101
00102 if (mapFile.Error()) {
00103 std::ostringstream oss;
00104 oss << " Failed to load"
00105 << mapFilename
00106 << " : " << __FILE__
00107 << " [" << __LINE__ << "]"
00108 << std::endl;
00109 FL_ERR(_log, oss.str());
00110
00111 return map;
00112 }
00113 }
00114
00115
00116 delete data;
00117 data = 0;
00118 }
00119 }
00120 catch (NotFound& e)
00121 {
00122 FL_ERR(_log, e.what());
00123
00124
00125
00126
00127
00128 return map;
00129 }
00130
00131
00132
00133 const TiXmlElement* root = mapFile.RootElement();
00134
00135 if (root) {
00136 const std::string* loaderName = root->Attribute(std::string("loaderName"));
00137
00138 if (loaderName) {
00139 m_loaderName = *loaderName;
00140 }
00141
00142 int numElements = 0;
00143 int numElementsRetVal = root->QueryValueAttribute("elements", &numElements);
00144 m_percentDoneListener.setTotalNumberOfElements(numElements);
00145
00146 const std::string* mapName = root->Attribute(std::string("id"));
00147
00148 if (mapName) {
00149 try {
00150 map = m_model->createMap(*mapName);
00151 }
00152 catch (NameClash& e) {
00153 FL_ERR(_log, e.what());
00154
00155
00156 throw;
00157 }
00158
00159 if (map) {
00160 map->setFilename(mapFilename);
00161
00162 std::string ns = "";
00163 for (const TiXmlElement *importElement = root->FirstChildElement("import"); importElement; importElement = importElement->NextSiblingElement("import")) {
00164 const std::string* importDir = importElement->Attribute(std::string("dir"));
00165 const std::string* importFile = importElement->Attribute(std::string("file"));
00166
00167 std::string directory = "";
00168 if (importDir) {
00169 directory = *importDir;
00170 }
00171
00172 std::string file = "";
00173 if (importFile) {
00174 file = *importFile;
00175 }
00176
00177 if (importDir && !importFile) {
00178 bfs::path fullPath(m_mapDirectory);
00179 fullPath /= directory;
00180 loadImportDirectory(fullPath.string());
00181 }
00182 else if (importFile) {
00183 bfs::path fullFilePath(file);
00184 bfs::path fullDirPath(directory);
00185 if (importDir) {
00186 fullDirPath = bfs::path(m_mapDirectory);
00187 fullDirPath /= directory;
00188 }
00189 else {
00190 fullFilePath = bfs::path(m_mapDirectory);
00191 fullFilePath /= file;
00192 }
00193 loadImportFile(fullFilePath.string(), fullDirPath.string());
00194 }
00195 }
00196
00197
00198 for (const TiXmlElement* layerElement = root->FirstChildElement("layer"); layerElement; layerElement = layerElement->NextSiblingElement("layer")) {
00199
00200 double xOffset = 0.0;
00201 double yOffset = 0.0;
00202 double zOffset = 0.0;
00203 double xScale = 1.0;
00204 double yScale = 1.0;
00205 double rotation = 0.0;
00206
00207 int xOffsetRetVal = layerElement->QueryValueAttribute("x_offset", &xOffset);
00208 int yOffsetRetVal = layerElement->QueryValueAttribute("y_offset", &yOffset);
00209 int zOffsetRetVal = layerElement->QueryValueAttribute("z_offset", &zOffset);
00210 int xScaleRetVal = layerElement->QueryValueAttribute("x_scale", &xScale);
00211 int yScaleRetVal = layerElement->QueryValueAttribute("y_scale", &yScale);
00212 int rotationRetVal = layerElement->QueryValueAttribute("rotation", &rotation);
00213
00214 const std::string* layerName = layerElement->Attribute(std::string("id"));
00215 const std::string* pathing = layerElement->Attribute(std::string("pathing"));
00216 const std::string* gridType = layerElement->Attribute(std::string("grid_type"));
00217
00218 if (xOffsetRetVal == TIXML_SUCCESS &&
00219 yOffsetRetVal == TIXML_SUCCESS &&
00220 xScaleRetVal == TIXML_SUCCESS &&
00221 yScaleRetVal == TIXML_SUCCESS &&
00222 rotationRetVal == TIXML_SUCCESS &&
00223 layerName &&
00224 pathing &&
00225 gridType) {
00226 PathingStrategy pathStrategy = CELL_EDGES_ONLY;
00227
00228 if ("cell_edges_and_diagonals" == *pathing) {
00229 pathStrategy = CELL_EDGES_AND_DIAGONALS;
00230 }
00231 else if ("freeform" == *pathing) {
00232 pathStrategy = FREEFORM;
00233 }
00234
00235 CellGrid* grid = NULL;
00236 if (gridType) {
00237 grid = m_model->getCellGrid(*gridType);
00238 }
00239 else {
00240 grid = m_model->getCellGrid("square");
00241 }
00242
00243 if (grid) {
00244 grid->setXShift(xOffset);
00245 grid->setXScale(xScale);
00246 grid->setYShift(yOffset);
00247 grid->setYScale(yScale);
00248 grid->setZShift(zOffset);
00249 grid->setRotation(rotation);
00250 grid->setAllowDiagonals(pathStrategy != CELL_EDGES_ONLY);
00251
00252 Layer *layer = NULL;
00253 try {
00254 layer = map->createLayer(*layerName, grid);
00255 }
00256 catch (NameClash&) {
00257
00258 assert(false);
00259 }
00260
00261 if (layer) {
00262 layer->setPathingStrategy(pathStrategy);
00263
00264 double curr_x = 0;
00265 double curr_y = 0;
00266
00267 for (const TiXmlElement* instances = layerElement->FirstChildElement("instances"); instances; instances = instances->NextSiblingElement("instances")) {
00268 for (const TiXmlElement* instance = instances->FirstChildElement("i"); instance; instance = instance->NextSiblingElement("i")) {
00269 double x = 0;
00270 double y = 0;
00271 double z = 0;
00272 int r = 0;
00273 int stackpos = 0;
00274
00275 const std::string* instanceId = instance->Attribute(std::string("id"));
00276 const std::string* objectId = instance->Attribute(std::string("o"));
00277
00278 if (!objectId) {
00279 objectId = instance->Attribute(std::string("object"));
00280 }
00281
00282 if (!objectId) {
00283 objectId = instance->Attribute(std::string("obj"));
00284 }
00285
00286 const std::string* namespaceId = instance->Attribute(std::string("ns"));
00287
00288 if (!namespaceId) {
00289 namespaceId = instance->Attribute(std::string("namespace"));
00290 }
00291
00292 int xRetVal = instance->QueryValueAttribute("x", &x);
00293 int yRetVal = instance->QueryValueAttribute("y", &y);
00294 int zRetVal = instance->QueryValueAttribute("z", &z);
00295 int rRetVal = instance->QueryValueAttribute("r", &r);
00296
00297 if (xRetVal == TIXML_SUCCESS) {
00298 curr_x = x;
00299 }
00300 else {
00301 x = ++curr_x;
00302 }
00303
00304 if (yRetVal == TIXML_SUCCESS) {
00305 curr_y = y;
00306 }
00307 else {
00308 y = curr_y;
00309 }
00310
00311 if (rRetVal != TIXML_SUCCESS) {
00312 rRetVal = instance->QueryValueAttribute("rotation", &r);
00313 }
00314
00315 int stackRetVal = instance->QueryValueAttribute("stackpos", &stackpos);
00316
00317 if (objectId) {
00318 if (namespaceId) {
00319 ns = *namespaceId;
00320 }
00321
00322 Object* object = m_model->getObject(*objectId, ns);
00323
00324 if (object) {
00325 Instance* inst = NULL;
00326 if (instanceId) {
00327 inst = layer->createInstance(object, ExactModelCoordinate(x,y,z), *instanceId);
00328 }
00329 else {
00330 inst = layer->createInstance(object, ExactModelCoordinate(x,y,z));
00331 }
00332
00333 if (inst) {
00334 if (rRetVal != TIXML_SUCCESS) {
00335 ObjectVisual* objVisual = object->getVisual<ObjectVisual>();
00336 std::vector<int> angles;
00337 objVisual->getStaticImageAngles(angles);
00338 if (!angles.empty()) {
00339 r = angles[0];
00340 }
00341 }
00342
00343 inst->setRotation(r);
00344
00345 InstanceVisual* instVisual = InstanceVisual::create(inst);
00346
00347 if (instVisual && (stackRetVal == TIXML_SUCCESS)) {
00348 instVisual->setStackPosition(stackpos);
00349 }
00350
00351 if (object->getAction("default")) {
00352 Location target(layer);
00353
00354 inst->act("default", target, true);
00355 }
00356 }
00357 else
00358 {
00359 std::ostringstream oss;
00360 oss << " Failed to create instance of object "
00361 << *objectId
00362 << " : " << __FILE__
00363 << " [" << __LINE__ << "]"
00364 << std::endl;
00365 FL_ERR(_log, oss.str());
00366 }
00367 }
00368 }
00369
00370
00371 m_percentDoneListener.incrementCount();
00372 }
00373 }
00374 }
00375 }
00376 }
00377
00378
00379 m_percentDoneListener.incrementCount();
00380 }
00381
00382 for (const TiXmlElement* cameraElement = root->FirstChildElement("camera"); cameraElement; cameraElement = cameraElement->NextSiblingElement("camera")) {
00383 const std::string* cameraId = cameraElement->Attribute(std::string("id"));
00384 const std::string* refLayerId = cameraElement->Attribute(std::string("ref_layer_id"));
00385
00386 int refCellWidth = 0;
00387 int refCellHeight = 0;
00388 int success = cameraElement->QueryIntAttribute("ref_cell_width", &refCellWidth);
00389 success &= cameraElement->QueryIntAttribute("ref_cell_height", &refCellHeight);
00390
00391 if (cameraId && refLayerId && success == TIXML_SUCCESS) {
00392 double tilt = 0.0;
00393 double zoom = 1.0;
00394 double rotation = 0.0;
00395 cameraElement->QueryDoubleAttribute("tilt", &tilt);
00396 cameraElement->QueryDoubleAttribute("zoom", &zoom);
00397 cameraElement->QueryDoubleAttribute("rotation", &rotation);
00398
00399 const std::string* viewport = cameraElement->Attribute(std::string("viewport"));
00400
00401 Layer* layer = NULL;
00402 try {
00403 layer = map->getLayer(*refLayerId);
00404 }
00405 catch (NotFound&) {
00406
00407 assert(false);
00408 }
00409
00410 Camera* cam = NULL;
00411 if (layer) {
00412 if (viewport) {
00413
00414 IntVector viewportParameters = tokenize(*viewport, ',');
00415
00416
00417 if (viewportParameters.size() == 4) {
00418 Rect rect(viewportParameters[0], viewportParameters[1],
00419 viewportParameters[2], viewportParameters[3]);
00420
00421 try {
00422 cam = map->addCamera(*cameraId, layer, rect);
00423 }
00424 catch (NameClash&) {
00425
00426 assert(false);
00427 }
00428 }
00429 }
00430 else {
00431 Rect rect(0, 0, m_renderBackend->getScreenWidth(), m_renderBackend->getScreenHeight());
00432
00433 try {
00434 cam = map->addCamera(*cameraId, layer, rect);
00435 }
00436 catch (NameClash&) {
00437
00438 assert(false);
00439 }
00440 }
00441 }
00442
00443 if (cam) {
00444 cam->setCellImageDimensions(refCellWidth, refCellHeight);
00445 cam->setRotation(rotation);
00446 cam->setTilt(tilt);
00447 cam->setZoom(zoom);
00448
00449
00450 InstanceRenderer* instanceRenderer = InstanceRenderer::getInstance(cam);
00451 if (instanceRenderer)
00452 {
00453 instanceRenderer->activateAllLayers(map);
00454 }
00455 }
00456 }
00457
00458
00459 m_percentDoneListener.incrementCount();
00460 }
00461 }
00462 }
00463 }
00464
00465 return map;
00466 }
00467
00468 void MapLoader::setObjectLoader(const FIFE::ObjectLoaderPtr& objectLoader) {
00469 assert(objectLoader);
00470
00471 m_objectLoader = objectLoader;
00472 }
00473
00474
00475 void MapLoader::setAnimationLoader(const FIFE::AnimationLoaderPtr& animationLoader) {
00476 assert(animationLoader);
00477
00478 m_objectLoader->setAnimationLoader(animationLoader);
00479 }
00480
00481 void MapLoader::setAtlasLoader(const FIFE::AtlasLoaderPtr& atlasLoader) {
00482 assert(atlasLoader);
00483
00484 m_atlasLoader = atlasLoader;
00485 }
00486
00487 bool MapLoader::isLoadable(const std::string& filename) const {
00488 bfs::path mapPath(filename);
00489
00490 TiXmlDocument mapFile;
00491
00492 std::string mapFilename = mapPath.string();
00493
00494 try {
00495 RawData* data = m_vfs->open(mapFilename);
00496
00497 if (data) {
00498 if (data->getDataLength() != 0) {
00499 mapFile.Parse(data->readString(data->getDataLength()).c_str());
00500
00501 if (mapFile.Error()) {
00502 return false;
00503 }
00504
00505 const TiXmlElement* root = mapFile.RootElement();
00506
00507 if (root) {
00508 const std::string* loaderName = root->Attribute(std::string("loader"));
00509
00510
00511
00512
00513
00514 if (!loaderName || (loaderName && *loaderName == getLoaderName())) {
00515 return true;
00516 }
00517 }
00518 }
00519
00520
00521 delete data;
00522 data = 0;
00523 }
00524 }
00525 catch (NotFound& e) {
00526 FL_ERR(_log, e.what());
00527
00528 return false;
00529 }
00530
00531 return false;
00532 }
00533
00534 void MapLoader::loadImportFile(const std::string& file, const std::string& directory) {
00535 if (!file.empty()) {
00536 bfs::path importFilePath(directory);
00537 importFilePath /= file;
00538
00539 std::string importFileString = importFilePath.string();
00540 if (m_objectLoader && m_objectLoader->isLoadable(importFileString)) {
00541 m_objectLoader->load(importFileString);
00542 }
00543 else if (m_atlasLoader && m_atlasLoader->isLoadable(importFileString)) {
00544 m_atlasLoader->load(importFileString);
00545 }
00546 }
00547 }
00548
00549 void MapLoader::loadImportDirectory(const std::string& directory) {
00550 if (!directory.empty()) {
00551 bfs::path importDirectory(directory);
00552 std::string importDirectoryString = importDirectory.string();
00553
00554 std::set<std::string> files = m_vfs->listFiles(importDirectoryString);
00555
00556
00557 std::set<std::string>::iterator iter;
00558 for (iter = files.begin(); iter != files.end(); ++iter) {
00559
00560
00561 std::string ext = bfs::extension(*iter);
00562 if (ext == ".xml" || ext == ".zip") {
00563 loadImportFile(*iter, importDirectoryString);
00564 }
00565 }
00566
00567 std::set<std::string> nestedDirectories = m_vfs->listDirectories(importDirectoryString);
00568 for (iter = nestedDirectories.begin(); iter != nestedDirectories.end(); ++iter) {
00569
00570 if ((*iter).find(".svn") == std::string::npos) {
00571 loadImportDirectory(importDirectoryString + "/" + *iter);
00572 }
00573 }
00574 }
00575 }
00576
00577 void MapLoader::addPercentDoneListener(PercentDoneListener* listener) {
00578 m_percentDoneListener.addListener(listener);
00579 }
00580
00581 const std::string& MapLoader::getLoaderName() const {
00582 return m_loaderName;
00583
00584 }
00585
00586 MapLoader* createDefaultMapLoader(Model* model, VFS* vfs, ImageManager* imageManager, RenderBackend* renderBackend) {
00587 return (new MapLoader(model, vfs, imageManager, renderBackend));
00588 }
00589 }