32 #include "ext/tinyxml/fife_tinyxml.h"
33 #include "model/model.h"
34 #include "model/structures/layer.h"
35 #include "model/structures/instance.h"
36 #include "model/metamodel/grids/cellgrid.h"
37 #include "model/metamodel/modelcoords.h"
38 #include "model/metamodel/action.h"
39 #include "vfs/fife_boost_filesystem.h"
41 #include "vfs/vfsdirectory.h"
42 #include "vfs/raw/rawdata.h"
43 #include "util/base/exception.h"
44 #include "util/log/logger.h"
45 #include "util/resource/resource.h"
46 #include "util/structures/rect.h"
47 #include "video/imagemanager.h"
48 #include "video/image.h"
49 #include "video/renderbackend.h"
50 #include "view/visual.h"
51 #include "view/camera.h"
52 #include "view/renderers/instancerenderer.h"
53 #include "util/base/stringutils.h"
55 #include "atlasloader.h"
56 #include "maploader.h"
57 #include "animationloader.h"
58 #include "objectloader.h"
61 static Logger _log(LM_NATIVE_LOADERS);
63 MapLoader::MapLoader(Model* model, VFS* vfs, ImageManager* imageManager, RenderBackend* renderBackend)
64 : m_model(model), m_vfs(vfs), m_imageManager(imageManager), m_renderBackend(renderBackend),
65 m_loaderName(
"fife"), m_mapDirectory(
"") {
66 AnimationLoaderPtr animationLoader(
new AnimationLoader(m_vfs, m_imageManager));
67 m_objectLoader.reset(
new ObjectLoader(m_model, m_vfs, m_imageManager, animationLoader));
68 m_atlasLoader.reset(
new AtlasLoader(m_model, m_vfs, m_imageManager));
71 MapLoader::~MapLoader() {
75 Map* MapLoader::load(
const std::string& filename) {
80 m_percentDoneListener.reset();
82 bfs::path mapPath(filename);
93 std::string mapFilename = mapPath.string();
96 RawData* data = m_vfs->open(mapFilename);
99 if (data->getDataLength() != 0) {
100 mapFile.
Parse(data->readString(data->getDataLength()).c_str());
102 if (mapFile.
Error()) {
103 std::ostringstream oss;
104 oss <<
" Failed to load"
107 <<
" [" << __LINE__ <<
"]"
109 FL_ERR(_log, oss.str());
122 FL_ERR(_log, e.what());
136 const std::string* loaderName = root->
Attribute(std::string(
"loaderName"));
139 m_loaderName = *loaderName;
143 int numElementsRetVal = root->QueryValueAttribute(
"elements", &numElements);
144 m_percentDoneListener.setTotalNumberOfElements(numElements);
146 const std::string* mapName = root->
Attribute(std::string(
"id"));
150 map = m_model->createMap(*mapName);
152 catch (NameClash& e) {
153 FL_ERR(_log, e.what());
160 map->setFilename(mapFilename);
164 const std::string* importDir = importElement->Attribute(std::string(
"dir"));
165 const std::string* importFile = importElement->Attribute(std::string(
"file"));
167 std::string directory =
"";
169 directory = *importDir;
172 std::string file =
"";
177 if (importDir && !importFile) {
178 bfs::path fullPath(m_mapDirectory);
179 fullPath /= directory;
180 loadImportDirectory(fullPath.string());
182 else if (importFile) {
183 bfs::path fullFilePath(file);
184 bfs::path fullDirPath(directory);
186 fullDirPath = bfs::path(m_mapDirectory);
187 fullDirPath /= directory;
190 fullFilePath = bfs::path(m_mapDirectory);
191 fullFilePath /= file;
193 loadImportFile(fullFilePath.string(), fullDirPath.string());
200 double xOffset = 0.0;
201 double yOffset = 0.0;
202 double zOffset = 0.0;
205 double rotation = 0.0;
207 int xOffsetRetVal = layerElement->QueryValueAttribute(
"x_offset", &xOffset);
208 int yOffsetRetVal = layerElement->QueryValueAttribute(
"y_offset", &yOffset);
209 int zOffsetRetVal = layerElement->QueryValueAttribute(
"z_offset", &zOffset);
210 int xScaleRetVal = layerElement->QueryValueAttribute(
"x_scale", &xScale);
211 int yScaleRetVal = layerElement->QueryValueAttribute(
"y_scale", &yScale);
212 int rotationRetVal = layerElement->QueryValueAttribute(
"rotation", &rotation);
214 const std::string* layerName = layerElement->Attribute(std::string(
"id"));
215 const std::string* pathing = layerElement->Attribute(std::string(
"pathing"));
216 const std::string* gridType = layerElement->Attribute(std::string(
"grid_type"));
218 if (xOffsetRetVal == TIXML_SUCCESS &&
219 yOffsetRetVal == TIXML_SUCCESS &&
220 xScaleRetVal == TIXML_SUCCESS &&
221 yScaleRetVal == TIXML_SUCCESS &&
222 rotationRetVal == TIXML_SUCCESS &&
228 if (
"cell_edges_and_diagonals" == *pathing) {
229 pathStrategy = CELL_EDGES_AND_DIAGONALS;
231 else if (
"freeform" == *pathing) {
232 pathStrategy = FREEFORM;
235 CellGrid* grid = NULL;
237 grid = m_model->getCellGrid(*gridType);
240 grid = m_model->getCellGrid(
"square");
244 grid->setXShift(xOffset);
245 grid->setXScale(xScale);
246 grid->setYShift(yOffset);
247 grid->setYScale(yScale);
248 grid->setZShift(zOffset);
249 grid->setRotation(rotation);
253 layer = map->createLayer(*layerName, grid);
261 layer->setPathingStrategy(pathStrategy);
274 const std::string* instanceId = instance->Attribute(std::string(
"id"));
275 const std::string* objectId = instance->Attribute(std::string(
"o"));
278 objectId = instance->Attribute(std::string(
"object"));
282 objectId = instance->Attribute(std::string(
"obj"));
285 const std::string* namespaceId = instance->Attribute(std::string(
"ns"));
288 namespaceId = instance->Attribute(std::string(
"namespace"));
291 int xRetVal = instance->QueryValueAttribute(
"x", &x);
292 int yRetVal = instance->QueryValueAttribute(
"y", &y);
293 int zRetVal = instance->QueryValueAttribute(
"z", &z);
294 int rRetVal = instance->QueryValueAttribute(
"r", &r);
296 if (xRetVal == TIXML_SUCCESS) {
303 if (yRetVal == TIXML_SUCCESS) {
310 if (rRetVal != TIXML_SUCCESS) {
311 rRetVal = instance->QueryValueAttribute(
"rotation", &r);
314 int stackRetVal = instance->QueryValueAttribute(
"stackpos", &stackpos);
321 Object*
object = m_model->getObject(*objectId, ns);
324 Instance* inst = NULL;
326 inst = layer->createInstance(
object, ExactModelCoordinate(x,y,z), *instanceId);
329 inst = layer->createInstance(
object, ExactModelCoordinate(x,y,z));
333 if (rRetVal != TIXML_SUCCESS) {
334 ObjectVisual* objVisual =
object->getVisual<ObjectVisual>();
335 std::vector<int> angles;
336 objVisual->getStaticImageAngles(angles);
337 if (!angles.empty()) {
342 inst->setRotation(r);
346 if (instVisual && (stackRetVal == TIXML_SUCCESS)) {
347 instVisual->setStackPosition(stackpos);
350 if (object->getAction(
"default")) {
351 Location target(layer);
353 inst->act(
"default", target,
true);
358 std::ostringstream oss;
359 oss <<
" Failed to create instance of object "
362 <<
" [" << __LINE__ <<
"]"
364 FL_ERR(_log, oss.str());
370 m_percentDoneListener.incrementCount();
378 m_percentDoneListener.incrementCount();
382 const std::string* cameraId = cameraElement->Attribute(std::string(
"id"));
383 const std::string* refLayerId = cameraElement->Attribute(std::string(
"ref_layer_id"));
385 int refCellWidth = 0;
386 int refCellHeight = 0;
387 int success = cameraElement->QueryIntAttribute(
"ref_cell_width", &refCellWidth);
388 success &= cameraElement->QueryIntAttribute(
"ref_cell_height", &refCellHeight);
390 if (cameraId && refLayerId && success == TIXML_SUCCESS) {
393 double rotation = 0.0;
394 cameraElement->QueryDoubleAttribute(
"tilt", &tilt);
395 cameraElement->QueryDoubleAttribute(
"zoom", &zoom);
396 cameraElement->QueryDoubleAttribute(
"rotation", &rotation);
398 const std::string* viewport = cameraElement->Attribute(std::string(
"viewport"));
402 layer = map->getLayer(*refLayerId);
413 IntVector viewportParameters = tokenize(*viewport,
',');
416 if (viewportParameters.size() == 4) {
417 Rect rect(viewportParameters[0], viewportParameters[1],
418 viewportParameters[2], viewportParameters[3]);
421 cam = map->addCamera(*cameraId, layer, rect);
430 Rect rect(0, 0, m_renderBackend->getScreenWidth(), m_renderBackend->getScreenHeight());
433 cam = map->addCamera(*cameraId, layer, rect);
443 cam->setCellImageDimensions(refCellWidth, refCellHeight);
444 cam->setRotation(rotation);
449 InstanceRenderer* instanceRenderer = InstanceRenderer::getInstance(cam);
450 if (instanceRenderer)
452 instanceRenderer->activateAllLayers(map);
458 m_percentDoneListener.incrementCount();
468 assert(objectLoader);
470 m_objectLoader = objectLoader;
475 assert(animationLoader);
477 m_objectLoader->setAnimationLoader(animationLoader);
483 m_atlasLoader = atlasLoader;
486 bool MapLoader::isLoadable(
const std::string& filename)
const {
487 bfs::path mapPath(filename);
491 std::string mapFilename = mapPath.string();
494 RawData* data = m_vfs->open(mapFilename);
497 if (data->getDataLength() != 0) {
498 mapFile.
Parse(data->readString(data->getDataLength()).c_str());
500 if (mapFile.
Error()) {
507 const std::string* loaderName = root->
Attribute(std::string(
"loader"));
513 if (!loaderName || (loaderName && *loaderName == getLoaderName())) {
524 catch (NotFound& e) {
525 FL_ERR(_log, e.what());
533 void MapLoader::loadImportFile(
const std::string& file,
const std::string& directory) {
535 bfs::path importFilePath(directory);
536 importFilePath /= file;
538 std::string importFileString = importFilePath.string();
539 if (m_objectLoader && m_objectLoader->isLoadable(importFileString)) {
540 m_objectLoader->load(importFileString);
542 else if (m_atlasLoader && m_atlasLoader->isLoadable(importFileString)) {
543 m_atlasLoader->load(importFileString);
548 void MapLoader::loadImportDirectory(
const std::string& directory) {
549 if (!directory.empty()) {
550 bfs::path importDirectory(directory);
551 std::string importDirectoryString = importDirectory.string();
553 std::set<std::string> files = m_vfs->listFiles(importDirectoryString);
556 std::set<std::string>::iterator iter;
557 for (iter = files.begin(); iter != files.end(); ++iter) {
560 std::string ext = bfs::extension(*iter);
561 if (ext ==
".xml" || ext ==
".zip") {
562 loadImportFile(*iter, importDirectoryString);
566 std::set<std::string> nestedDirectories = m_vfs->listDirectories(importDirectoryString);
567 for (iter = nestedDirectories.begin(); iter != nestedDirectories.end(); ++iter) {
569 if ((*iter).find(
".svn") == std::string::npos) {
570 loadImportDirectory(importDirectoryString +
"/" + *iter);
576 void MapLoader::addPercentDoneListener(PercentDoneListener* listener) {
577 m_percentDoneListener.addListener(listener);
580 const std::string& MapLoader::getLoaderName()
const {
586 return (
new MapLoader(model, vfs, imageManager, renderBackend));