#include "precompiled.h" #include "MapReader.h" #include "lib/types.h" #include "UnitManager.h" #include "Unit.h" #include "Game.h" #include "ObjectManager.h" #include "BaseEntity.h" #include "BaseEntityCollection.h" #include "EntityManager.h" #include "CLogger.h" #include "Model.h" #include "Terrain.h" #include "TextureManager.h" #include "timer.h" #include "Loader.h" #include "LoaderThunks.h" #define LOG_CATEGORY "graphics" CMapReader::CMapReader() : xml_reader(0) { cur_terrain_tex = 0; // important - resets generator state } // LoadMap: try to load the map from given file; reinitialise the scene to new data if successful void CMapReader::LoadMap(const char* filename, CTerrain *pTerrain_, CUnitManager *pUnitMan_, CLightEnv *pLightEnv_) { // latch parameters (held until DelayedLoadFinished) pTerrain = pTerrain_; pUnitMan = pUnitMan_; pLightEnv = pLightEnv_; // [25ms] unpacker.Read(filename,"PSMP"); // check version if (unpacker.GetVersion()=3) { // read the corresponding XML file filename_xml = filename; filename_xml = filename_xml.Left(filename_xml.Length()-4) + ".xml"; RegMemFun(this, &CMapReader::ReadXML, L"CMapReader::ReadXML", 1300); } RegMemFun(this, &CMapReader::DelayLoadFinished, L"CMapReader::DelayLoadFinished", 5); } // UnpackMap: unpack the given data from the raw data stream into local variables int CMapReader::UnpackMap() { // now unpack everything into local data int ret = UnpackTerrain(); if(ret != 0) // failed or timed out return ret; UnpackObjects(); if (unpacker.GetVersion()>=2) { UnpackLightEnv(); } return 0; } // UnpackLightEnv: unpack lighting parameters from input stream void CMapReader::UnpackLightEnv() { unpacker.UnpackRaw(&m_LightEnv.m_SunColor,sizeof(m_LightEnv.m_SunColor)); unpacker.UnpackRaw(&m_LightEnv.m_Elevation,sizeof(m_LightEnv.m_Elevation)); unpacker.UnpackRaw(&m_LightEnv.m_Rotation,sizeof(m_LightEnv.m_Rotation)); unpacker.UnpackRaw(&m_LightEnv.m_TerrainAmbientColor,sizeof(m_LightEnv.m_TerrainAmbientColor)); unpacker.UnpackRaw(&m_LightEnv.m_UnitsAmbientColor,sizeof(m_LightEnv.m_UnitsAmbientColor)); m_LightEnv.CalculateSunDirection(); } // UnpackObjects: unpack world objects from input stream void CMapReader::UnpackObjects() { // unpack object types u32 numObjTypes; unpacker.UnpackRaw(&numObjTypes,sizeof(numObjTypes)); m_ObjectTypes.resize(numObjTypes); for (uint i=0;iGetHandle(); m_TerrainTextures.push_back(handle); cur_terrain_tex++; LDR_CHECK_TIMEOUT(cur_terrain_tex, num_terrain_tex); } // unpack tile data [3ms] u32 tilesPerSide = m_MapSize*PATCH_SIZE; m_Tiles.resize(SQR(tilesPerSide)); unpacker.UnpackRaw(&m_Tiles[0],(u32)(sizeof(STileDesc)*m_Tiles.size())); // reset generator state. cur_terrain_tex = 0; return 0; } // ApplyData: take all the input data, and rebuild the scene from it int CMapReader::ApplyData() { // initialise the terrain pTerrain->Initialize(m_MapSize,&m_Heightmap[0]); // setup the textures on the minipatches STileDesc* tileptr=&m_Tiles[0]; for (u32 j=0;jGetPatch(i,j)->m_MiniPatches[m][k]; mp.Tex1=m_TerrainTextures[tileptr->m_Tex1Index]; mp.Tex1Priority=tileptr->m_Priority; tileptr++; } } } } // delete all existing entities g_EntityManager.deleteAll(); // delete all remaining non-entity units pUnitMan->DeleteAll(); // add new objects for (u32 i=0;iGetIn(); // CVector3D position = ((CMatrix3D*)m_Objects[i].m_Transform)->GetTranslation(); // // g_EntityManager.create(templateObject, position, atan2(-orient.X, -orient.Z)); // // continue; // } } // MT: Testing: if( i == 170 ) { CStrW tom( "dick, harry" ); } CUnit* unit = g_UnitMan.CreateUnit(m_ObjectTypes.at(m_Objects[i].m_ObjectIndex), NULL); if (unit) { CMatrix3D transform; memcpy(&transform._11,m_Objects[i].m_Transform,sizeof(float)*16); unit->GetModel()->SetTransform(transform); } } if (unpacker.GetVersion()>=2) { // copy over the lighting parameters *pLightEnv=m_LightEnv; } return 0; } class CXMLReader { public: CXMLReader(const CStr& xml_filename) { Init(xml_filename); } // return semantics: see Loader.cpp!LoadFunc. int ProgressiveRead(); private: CXeromyces xmb_file; int el_scenario, el_entities, el_entity; int el_template, el_player; int el_position, el_orientation; int el_nonentities, el_nonentity; int el_actor; int at_x, at_y, at_z; int at_angle; XMBElement root; XMBElementList nodes; // children of root XMBElement node; // a child of nodes XMBElementList entities, nonentities; // children of node // loop counters int node_idx; int entity_idx, nonentity_idx; // # entities+nonentities processed and total (for progress calc) int completed_jobs, total_jobs; void Init(const CStr& xml_filename); int ReadEntities(XMBElement& parent, double end_time); int ReadNonEntities(XMBElement& parent, double end_time); }; void CXMLReader::Init(const CStr& xml_filename) { // must only assign once, so do it here node_idx = entity_idx = nonentity_idx = 0; #ifdef SCED // HACK: ScEd uses absolute filenames, not VFS paths. I can't be bothered // to make Xeromyces work with non-VFS, so just cheat: CStr vfs_filename(xml_filename); vfs_filename = vfs_filename.substr(vfs_filename.ReverseFind("\\mods\\official\\") + 15); vfs_filename.Replace("\\", "/"); if (xmb_file.Load(vfs_filename) != PSRETURN_OK) throw CFileUnpacker::CFileReadError(); #else if (xmb_file.Load(xml_filename) != PSRETURN_OK) throw CFileUnpacker::CFileReadError(); #endif // define all the elements and attributes used in the XML file. #define EL(x) el_##x = xmb_file.getElementID(#x) #define AT(x) at_##x = xmb_file.getAttributeID(#x) EL(scenario); EL(entities); EL(entity); EL(template); EL(player); EL(position); EL(orientation); EL(nonentities); EL(nonentity); EL(actor); AT(x); AT(y); AT(z); AT(angle); #undef AT #undef EL root = xmb_file.getRoot(); assert(root.getNodeName() == el_scenario); nodes = root.getChildNodes(); // find out total number of entities+nonentities // (used when calculating progress) completed_jobs = 0; total_jobs = 0; for (int i = 0; i < nodes.Count; i++) { node = nodes.item(i); entities = node.getChildNodes(); total_jobs += entities.Count; } } int CXMLReader::ReadEntities(XMBElement& parent, double end_time) { entities = parent.getChildNodes(); // ok to set more than once while(entity_idx < entities.Count) { // all new state at this scope and below doesn't need to be // wrapped, since we only yield after a complete iteration. XMBElement entity = entities.item(entity_idx++); assert(entity.getNodeName() == el_entity); CStrW TemplateName; int PlayerID; CVector3D Position; float Orientation; XMBElementList children3 = entity.getChildNodes(); for (int k = 0; k < children3.Count; k++) { XMBElement child3 = children3.item(k); int element_name = child3.getNodeName(); //