codepad
[
create a new paste
]
login
|
about
Language:
C
C++
D
Haskell
Lua
OCaml
PHP
Perl
Plain Text
Python
Ruby
Scheme
Tcl
#include "MapLoader.hpp" using namespace std; using namespace Dodge; //=========================================== // MapLoader::refCountTable_t::erase //=========================================== void MapLoader::refCountTable_t::erase(id_t id) { auto i = m_byId.find(id); if (i != m_byId.end()) { m_byRefCount.erase(make_pair(i->second.first, make_pair(i->second.second, id))); m_byId.erase(i); } assert(m_byRefCount.size() == m_byId.size()); } //=========================================== // MapLoader::refCountTable_t::insert //=========================================== void MapLoader::refCountTable_t::insert(id_t id, refCount_t refCount, time_t time) { m_byRefCount.insert(make_pair(refCount, make_pair(time, id))); m_byId[id] = make_pair(refCount, time); assert(m_byRefCount.size() == m_byId.size()); } //=========================================== // MapLoader::refCountTable_t::incrRefCount //=========================================== void MapLoader::refCountTable_t::incrRefCount(id_t id) { auto i = m_byId.find(id); if (i != m_byId.end()) { m_byRefCount.erase(make_pair(i->second.first, make_pair(i->second.second, id))); ++i->second.first; i->second.second = -m_timer.getTime(); m_byRefCount.insert(make_pair(i->second.first, make_pair(i->second.second, id))); } else { insert(id, 1, m_timer.getTime()); } assert(m_byRefCount.size() == m_byId.size()); } //=========================================== // MapLoader::refCountTable_t::getBestCandidateForDeletion //=========================================== MapLoader::refCountTable_t::id_t MapLoader::refCountTable_t::getBestCandidateForDeletion() const { auto i = m_byRefCount.begin(); return i->first == 0 ? i->second.second : -1; } //=========================================== // MapLoader::refCountTable_t::decrRefCount //=========================================== void MapLoader::refCountTable_t::decrRefCount(id_t id) { auto i = m_byId.find(id); if (i != m_byId.end() && i->second.first > 0) { m_byRefCount.erase(make_pair(i->second.first, make_pair(i->second.second, id))); --i->second.first; m_byRefCount.insert(make_pair(i->second.first, make_pair(i->second.second, id))); } assert(m_byRefCount.size() == m_byId.size()); } //=========================================== // MapLoader::loadAssets // // Loads assets from <assets> tag. //=========================================== void MapLoader::loadAssets(const XmlNode data, mapSegment_t* segment) { try { XML_NODE_CHECK(data, assets); XmlNode node = data.firstChild(); while (!node.isNull() && node.name() == "asset") { XmlAttribute attr = node.firstAttribute(); XML_ATTR_CHECK(attr, id); long id = attr.getLong(); // If asset is not already loaded if (!m_assetManager.getAssetPointer(id)) { boost::shared_ptr<Asset> asset = m_factoryFunc(node.firstChild()); m_assetManager.addAsset(id, asset); m_currentMemUsage += asset->getSize(); } if (segment) segment->assetIds.push_back(id); m_refCountTable.incrRefCount(id); node = node.nextSibling(); } } catch (XmlException& e) { e.prepend("Error loading assets from XML file; "); throw; } } //=========================================== // MapLoader::getMemoryUsage //=========================================== size_t MapLoader::getMemoryUsage() const { size_t total = 0; for (auto i = m_assetManager.begin(); i != m_assetManager.end(); ++i) total += i->second->getSize(); return total; } //=========================================== // MapLoader::parseAssetsFile_r //=========================================== void MapLoader::parseAssetsFile_r(const string& path, mapSegment_t* segment) { try { XmlDocument doc; XmlNode decl = doc.parse(path); if (decl.isNull()) throw XmlException("Expected XML declaration", __FILE__, __LINE__); XmlNode node = decl.nextSibling(); XML_NODE_CHECK(node, ASSETFILE); node = node.firstChild(); if (node.isNull()) throw XmlException("Expected 'using' or 'assets' tag", __FILE__, __LINE__); if (node.name() == "using") { XmlNode node_ = node.firstChild(); while (!node_.isNull() && node_.name() == "file") { parseAssetsFile_r(node_.getString(), segment); node_ = node_.nextSibling(); } node = node.nextSibling(); } XML_NODE_CHECK(node, assets); loadAssets(node, segment); } catch (XmlException& e) { e.prepend("Error loading assets from XML file; "); throw; } } //=========================================== // MapLoader::loadMapSettings //=========================================== void MapLoader::loadMapSettings(const XmlNode data) { try { XML_NODE_CHECK(data, settings); XmlNode node = data.firstChild(); XML_NODE_CHECK(node, boundary); m_mapBoundary = Range(node.firstChild()); node = node.nextSibling(); XML_NODE_CHECK(node, numSegments); Vec2i nSegs(node.firstChild()); node = node.nextSibling(); XML_NODE_CHECK(node, segmentSize); m_segmentSize = Vec2f(node.firstChild()); node = node.nextSibling(); XML_NODE_CHECK(node, segmentsDir); string dir = node.getString(); for (int i = 0; i < nSegs.x; ++i) { m_segments.push_back(vector<mapSegment_t>()); for (int j = 0; j < nSegs.y; ++j) { mapSegment_t seg; stringstream path; path << dir << "/" << i << j << ".xml"; seg.filePath = path.str(); m_segments[i].push_back(seg); } } } catch (XmlException& e) { e.prepend("Error loading map settings; "); throw; } } //=========================================== // MapLoader::parseMapFile //=========================================== void MapLoader::parseMapFile(const std::string& file) { m_segments.clear(); m_centreSegment = Vec2i(-1, -1); try { XmlDocument doc; XmlNode decl = doc.parse(file); if (decl.isNull()) throw XmlException("Expected XML declaration", __FILE__, __LINE__); XmlNode node = decl.nextSibling(); XML_NODE_CHECK(node, MAPFILE); node = node.firstChild(); if (!node.isNull() && node.name() == "customSettings") { m_setMapSettingsFunc(node); node = node.nextSibling(); } loadMapSettings(node); node = node.nextSibling(); if (!node.isNull() && node.name() == "using") { XmlNode node_ = node.firstChild(); while (!node_.isNull() && node_.name() == "file") { parseAssetsFile_r(node_.getString(), NULL); node_ = node_.nextSibling(); } node = node.nextSibling(); } if (!node.isNull() && node.name() == "assets") loadAssets(node, NULL); } catch (XmlException& e) { e.prepend("Error loading map; "); throw; } } //=========================================== // MapLoader::unloadRefCountZeroAssets //=========================================== void MapLoader::unloadRefCountZeroAssets() { while (m_currentMemUsage > m_targetMemUsage) { long id = m_refCountTable.getBestCandidateForDeletion(); if (id != -1) { pAsset_t asset = m_assetManager.getAssetPointer(id); if (asset) { m_currentMemUsage -= asset->getSize(); m_deleteAssetFunc(asset); m_assetManager.freeAsset(id); m_refCountTable.erase(id); } } else break; } } //=========================================== // MapLoader::unloadSegment // // Decrement ref. counts for assets used by segment //=========================================== void MapLoader::unloadSegment(const Vec2i& indices) { if (indices.x < 0 || indices.x >= static_cast<int>(m_segments.size()) || indices.y < 0 || indices.y >= static_cast<int>(m_segments[indices.x].size())) return; mapSegment_t& seg = m_segments[indices.x][indices.y]; for (uint_t i = 0; i < seg.assetIds.size(); ++i) m_refCountTable.decrRefCount(seg.assetIds[i]); seg.loaded = false; } //=========================================== // MapLoader::loadSegment //=========================================== void MapLoader::loadSegment(const Vec2i& indices) { if (indices.x < 0 || indices.x >= static_cast<int>(m_segments.size()) || indices.y < 0 || indices.y >= static_cast<int>(m_segments[indices.x].size())) return; mapSegment_t& seg = m_segments[indices.x][indices.y]; if (!seg.loaded) { seg.assetIds.clear(); parseAssetsFile_r(seg.filePath, &seg); seg.loaded = true; } } //=========================================== // MapLoader::update //=========================================== void MapLoader::update(const Vec2f& viewPos) { Vec2i current = getSegment(viewPos); if (current == Vec2i(-1, -1)) return; // If map segments are not loaded if (m_centreSegment == Vec2i(-1, -1)) { loadSegment(current + Vec2i(-1, -1)); loadSegment(current + Vec2i(-1, 0)); loadSegment(current + Vec2i(-1, 1)); loadSegment(current + Vec2i(0, -1)); loadSegment(current + Vec2i(0, 0)); loadSegment(current + Vec2i(0, 1)); loadSegment(current + Vec2i(1, -1)); loadSegment(current + Vec2i(1, 0)); loadSegment(current + Vec2i(1, 1)); m_currentMemUsage = getMemoryUsage(); } else { // If camera has moved if (current != m_centreSegment) { set<pair<int, int> > prvSegs; prvSegs.insert(pair<int, int>(m_centreSegment.x - 1, m_centreSegment.y - 1)); prvSegs.insert(pair<int, int>(m_centreSegment.x - 1, m_centreSegment.y + 0)); prvSegs.insert(pair<int, int>(m_centreSegment.x - 1, m_centreSegment.y + 1)); prvSegs.insert(pair<int, int>(m_centreSegment.x + 0, m_centreSegment.y - 1)); prvSegs.insert(pair<int, int>(m_centreSegment.x + 0, m_centreSegment.y + 0)); prvSegs.insert(pair<int, int>(m_centreSegment.x + 0, m_centreSegment.y + 1)); prvSegs.insert(pair<int, int>(m_centreSegment.x + 1, m_centreSegment.y - 1)); prvSegs.insert(pair<int, int>(m_centreSegment.x + 1, m_centreSegment.y + 0)); prvSegs.insert(pair<int, int>(m_centreSegment.x + 1, m_centreSegment.y + 1)); set<pair<int, int> > curSegs; curSegs.insert(pair<int, int>(current.x - 1, current.y - 1)); curSegs.insert(pair<int, int>(current.x - 1, current.y + 0)); curSegs.insert(pair<int, int>(current.x - 1, current.y + 1)); curSegs.insert(pair<int, int>(current.x + 0, current.y - 1)); curSegs.insert(pair<int, int>(current.x + 0, current.y + 0)); curSegs.insert(pair<int, int>(current.x + 0, current.y + 1)); curSegs.insert(pair<int, int>(current.x + 1, current.y - 1)); curSegs.insert(pair<int, int>(current.x + 1, current.y + 0)); curSegs.insert(pair<int, int>(current.x + 1, current.y + 1)); for (auto i = prvSegs.begin(); i != prvSegs.end(); ++i) { if (curSegs.find(*i) == curSegs.end()) unloadSegment(Vec2i(i->first, i->second)); } for (auto i = curSegs.begin(); i != curSegs.end(); ++i) { if (prvSegs.find(*i) == prvSegs.end()) loadSegment(Vec2i(i->first, i->second)); } unloadRefCountZeroAssets(); } } m_centreSegment = current; } //=========================================== // MapLoader::getSegmentRange // // Returns the range spanned by the map segment at position 'indices' in the m_segments array. //=========================================== void MapLoader::getSegmentRange(const Vec2i& indices, Range* range) const { if (indices.x < 0 || indices.x >= static_cast<int>(m_segments.size()) || indices.y < 0 || indices.y >= static_cast<int>(m_segments[indices.x].size())) { throw Exception("Cannot retrieve map segment; Index out of range", __FILE__, __LINE__); } const Vec2f& mapPos = m_mapBoundary.getPosition(); Vec2f pos(mapPos.x + static_cast<float32_t>(indices.x) * m_segmentSize.x, mapPos.y + static_cast<float32_t>(indices.y) * m_segmentSize.y); range->setPosition(pos); range->setSize(m_segmentSize); } //=========================================== // MapLoader::getSegment // // Returns (-1, -1) if pos is not inside any segment. //=========================================== Vec2i MapLoader::getSegment(const Vec2f& pos) const { Vec2f tmp = pos - m_mapBoundary.getPosition(); Vec2i indices(floor(tmp.x / m_segmentSize.x), floor(tmp.y / m_segmentSize.y)); if (indices.x < 0 || indices.x > static_cast<int>(m_segments.size()) || indices.y < 0 || indices.y > static_cast<int>(m_segments[indices.x].size())) { return Vec2i(-1, -1); } return indices; }
Private
[
?
]
Run code
Submit