1
0
forked from 0ad/0ad

Updated map format, to store lighting information in XML. Also, vital whitespace consistency improvements.

This was SVN commit r2276.
This commit is contained in:
Ykkrosh 2005-05-11 03:07:08 +00:00
parent ee1ff55046
commit ab980c1a31
7 changed files with 234 additions and 183 deletions

View File

@ -31,6 +31,7 @@ class CLightEnv
{ {
friend class CMapWriter; friend class CMapWriter;
friend class CMapReader; friend class CMapReader;
friend class CXMLReader;
friend class CEditorData; friend class CEditorData;
friend class CMainFrame; friend class CMainFrame;
friend class CLightSettingsDlg; friend class CLightSettingsDlg;
@ -43,7 +44,7 @@ private:
public: public:
RGBColor m_TerrainAmbientColor; RGBColor m_TerrainAmbientColor;
RGBColor m_UnitsAmbientColor; RGBColor m_UnitsAmbientColor;
CVector3D m_SunDir; CVector3D m_SunDir;
// get sun direction from a rotation and elevation; defined such that: // get sun direction from a rotation and elevation; defined such that:
// 0 rotation = (0,0,1) // 0 rotation = (0,0,1)
@ -51,29 +52,29 @@ public:
// 0 elevation = (0,0,0) // 0 elevation = (0,0,0)
// PI/2 elevation = (0,-1,0) // PI/2 elevation = (0,-1,0)
float GetElevation() { return m_Elevation; } float GetElevation() { return m_Elevation; }
float GetRotation() { return m_Rotation; } float GetRotation() { return m_Rotation; }
void SetElevation(float f) void SetElevation(float f)
{ {
m_Elevation = f; m_Elevation = f;
CalculateSunDirection(); CalculateSunDirection();
} }
void SetRotation(float f) void SetRotation(float f)
{ {
m_Rotation = f; m_Rotation = f;
CalculateSunDirection(); CalculateSunDirection();
} }
void CalculateSunDirection() void CalculateSunDirection()
{ {
m_SunDir.Y=-float(sin(m_Elevation)); m_SunDir.Y=-float(sin(m_Elevation));
float scale=1+m_SunDir.Y; float scale=1+m_SunDir.Y;
m_SunDir.X=scale*float(sin(m_Rotation)); m_SunDir.X=scale*float(sin(m_Rotation));
m_SunDir.Z=scale*float(cos(m_Rotation)); m_SunDir.Z=scale*float(cos(m_Rotation));
m_SunDir.Normalize(); m_SunDir.Normalize();
} }
}; };
#endif #endif

View File

@ -5,7 +5,7 @@ class CMapIO
{ {
public: public:
// current file version given to saved maps // current file version given to saved maps
enum { FILE_VERSION = 3 }; enum { FILE_VERSION = 4 };
// supported file read version - file with version less than this will be reject // supported file read version - file with version less than this will be reject
enum { FILE_READ_VERSION = 1 }; enum { FILE_READ_VERSION = 1 };
@ -31,5 +31,3 @@ public:
}; };
#endif #endif

View File

@ -40,23 +40,28 @@ void CMapReader::LoadMap(const char* filename, CTerrain *pTerrain_, CUnitManager
unpacker.Read(filename,"PSMP"); unpacker.Read(filename,"PSMP");
// check version // check version
if (unpacker.GetVersion()<FILE_READ_VERSION) { if (unpacker.GetVersion() < FILE_READ_VERSION) {
throw CFileUnpacker::CFileVersionError(); throw CFileUnpacker::CFileVersionError();
} }
// delete all existing entities
g_EntityManager.deleteAll();
// delete all remaining non-entity units
pUnitMan->DeleteAll();
// unpack the data // unpack the data
RegMemFun(this, &CMapReader::UnpackMap, L"CMapReader::UnpackMap", 1900); RegMemFun(this, &CMapReader::UnpackMap, L"CMapReader::UnpackMap", 1900);
// apply data to the world if (unpacker.GetVersion() >= 3) {
RegMemFun(this, &CMapReader::ApplyData, L"CMapReader::ApplyData", 20);
if (unpacker.GetVersion()>=3) {
// read the corresponding XML file // read the corresponding XML file
filename_xml = filename; filename_xml = filename;
filename_xml = filename_xml.Left(filename_xml.Length()-4) + ".xml"; filename_xml = filename_xml.Left(filename_xml.Length()-4) + ".xml";
RegMemFun(this, &CMapReader::ReadXML, L"CMapReader::ReadXML", 1300); RegMemFun(this, &CMapReader::ReadXML, L"CMapReader::ReadXML", 1300);
} }
// apply data to the world
RegMemFun(this, &CMapReader::ApplyData, L"CMapReader::ApplyData", 20);
RegMemFun(this, &CMapReader::DelayLoadFinished, L"CMapReader::DelayLoadFinished", 5); RegMemFun(this, &CMapReader::DelayLoadFinished, L"CMapReader::DelayLoadFinished", 5);
} }
@ -68,10 +73,11 @@ int CMapReader::UnpackMap()
if(ret != 0) // failed or timed out if(ret != 0) // failed or timed out
return ret; return ret;
UnpackObjects(); if (unpacker.GetVersion() < 4)
if (unpacker.GetVersion()>=2) { UnpackObjects();
if (unpacker.GetVersion() >= 2 && unpacker.GetVersion() < 4)
UnpackLightEnv(); UnpackLightEnv();
}
return 0; return 0;
} }
@ -79,12 +85,12 @@ int CMapReader::UnpackMap()
// UnpackLightEnv: unpack lighting parameters from input stream // UnpackLightEnv: unpack lighting parameters from input stream
void CMapReader::UnpackLightEnv() void CMapReader::UnpackLightEnv()
{ {
unpacker.UnpackRaw(&m_LightEnv.m_SunColor,sizeof(m_LightEnv.m_SunColor)); 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_Elevation, sizeof(m_LightEnv.m_Elevation));
unpacker.UnpackRaw(&m_LightEnv.m_Rotation,sizeof(m_LightEnv.m_Rotation)); 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_TerrainAmbientColor, sizeof(m_LightEnv.m_TerrainAmbientColor));
unpacker.UnpackRaw(&m_LightEnv.m_UnitsAmbientColor,sizeof(m_LightEnv.m_UnitsAmbientColor)); unpacker.UnpackRaw(&m_LightEnv.m_UnitsAmbientColor, sizeof(m_LightEnv.m_UnitsAmbientColor));
m_LightEnv.CalculateSunDirection(); m_LightEnv.CalculateSunDirection();
} }
// UnpackObjects: unpack world objects from input stream // UnpackObjects: unpack world objects from input stream
@ -92,17 +98,17 @@ void CMapReader::UnpackObjects()
{ {
// unpack object types // unpack object types
u32 numObjTypes; u32 numObjTypes;
unpacker.UnpackRaw(&numObjTypes,sizeof(numObjTypes)); unpacker.UnpackRaw(&numObjTypes, sizeof(numObjTypes));
m_ObjectTypes.resize(numObjTypes); m_ObjectTypes.resize(numObjTypes);
for (uint i=0;i<numObjTypes;i++) { for (u32 i=0; i<numObjTypes; i++) {
unpacker.UnpackString(m_ObjectTypes[i]); unpacker.UnpackString(m_ObjectTypes[i]);
} }
// unpack object data // unpack object data
u32 numObjects; u32 numObjects;
unpacker.UnpackRaw(&numObjects,sizeof(numObjects)); unpacker.UnpackRaw(&numObjects, sizeof(numObjects));
m_Objects.resize(numObjects); m_Objects.resize(numObjects);
unpacker.UnpackRaw(&m_Objects[0],sizeof(SObjectDesc)*numObjects); unpacker.UnpackRaw(&m_Objects[0], sizeof(SObjectDesc)*numObjects);
} }
// UnpackTerrain: unpack the terrain from the end of the input data stream // UnpackTerrain: unpack the terrain from the end of the input data stream
@ -113,15 +119,15 @@ int CMapReader::UnpackTerrain()
// first call to generator (this is skipped after first call, // first call to generator (this is skipped after first call,
// i.e. when the loop below was interrupted) // i.e. when the loop below was interrupted)
if(cur_terrain_tex == 0) if (cur_terrain_tex == 0)
{ {
// unpack map size // unpack map size
unpacker.UnpackRaw(&m_MapSize,sizeof(m_MapSize)); unpacker.UnpackRaw(&m_MapSize, sizeof(m_MapSize));
// unpack heightmap [600µs] // unpack heightmap [600µs]
u32 verticesPerSide=m_MapSize*PATCH_SIZE+1; u32 verticesPerSide = m_MapSize*PATCH_SIZE+1;
m_Heightmap.resize(SQR(verticesPerSide)); m_Heightmap.resize(SQR(verticesPerSide));
unpacker.UnpackRaw(&m_Heightmap[0],SQR(verticesPerSide)*sizeof(u16)); unpacker.UnpackRaw(&m_Heightmap[0], SQR(verticesPerSide)*sizeof(u16));
// unpack # textures // unpack # textures
unpacker.UnpackRaw(&num_terrain_tex, sizeof(num_terrain_tex)); unpacker.UnpackRaw(&num_terrain_tex, sizeof(num_terrain_tex));
@ -130,7 +136,7 @@ int CMapReader::UnpackTerrain()
// unpack texture names; find handle for each texture. // unpack texture names; find handle for each texture.
// interruptible. // interruptible.
while(cur_terrain_tex < num_terrain_tex) while (cur_terrain_tex < num_terrain_tex)
{ {
CStr texturename; CStr texturename;
unpacker.UnpackString(texturename); unpacker.UnpackString(texturename);
@ -151,7 +157,7 @@ int CMapReader::UnpackTerrain()
// unpack tile data [3ms] // unpack tile data [3ms]
u32 tilesPerSide = m_MapSize*PATCH_SIZE; u32 tilesPerSide = m_MapSize*PATCH_SIZE;
m_Tiles.resize(SQR(tilesPerSide)); m_Tiles.resize(SQR(tilesPerSide));
unpacker.UnpackRaw(&m_Tiles[0],(u32)(sizeof(STileDesc)*m_Tiles.size())); unpacker.UnpackRaw(&m_Tiles[0], (u32)(sizeof(STileDesc)*m_Tiles.size()));
// reset generator state. // reset generator state.
cur_terrain_tex = 0; cur_terrain_tex = 0;
@ -163,18 +169,18 @@ int CMapReader::UnpackTerrain()
int CMapReader::ApplyData() int CMapReader::ApplyData()
{ {
// initialise the terrain // initialise the terrain
pTerrain->Initialize(m_MapSize,&m_Heightmap[0]); pTerrain->Initialize(m_MapSize, &m_Heightmap[0]);
// setup the textures on the minipatches // setup the textures on the minipatches
STileDesc* tileptr=&m_Tiles[0]; STileDesc* tileptr = &m_Tiles[0];
for (u32 j=0;j<m_MapSize;j++) { for (u32 j=0; j<m_MapSize; j++) {
for (u32 i=0;i<m_MapSize;i++) { for (u32 i=0; i<m_MapSize; i++) {
for (u32 m=0;m<PATCH_SIZE;m++) { for (u32 m=0; m<PATCH_SIZE; m++) {
for (u32 k=0;k<PATCH_SIZE;k++) { for (u32 k=0; k<PATCH_SIZE; k++) {
CMiniPatch& mp=pTerrain->GetPatch(i,j)->m_MiniPatches[m][k]; CMiniPatch& mp = pTerrain->GetPatch(i,j)->m_MiniPatches[m][k];
mp.Tex1=m_TerrainTextures[tileptr->m_Tex1Index]; mp.Tex1 = m_TerrainTextures[tileptr->m_Tex1Index];
mp.Tex1Priority=tileptr->m_Priority; mp.Tex1Priority = tileptr->m_Priority;
tileptr++; tileptr++;
} }
@ -182,40 +188,15 @@ int CMapReader::ApplyData()
} }
} }
// delete all existing entities
g_EntityManager.deleteAll();
// delete all remaining non-entity units
pUnitMan->DeleteAll();
// add new objects // add new objects
for (u32 i=0;i<m_Objects.size();i++) { for (size_t i = 0; i < m_Objects.size(); ++i)
{
if (unpacker.GetVersion() < 3) {
if (unpacker.GetVersion() < 3)
{
debug_warn("Old unsupported map version - objects will be missing"); debug_warn("Old unsupported map version - objects will be missing");
// (getTemplateByActor doesn't work, since entity templates are now // (getTemplateByActor doesn't work, since entity templates are now
// loaded on demand) // loaded on demand)
// // Hijack the standard actor instantiation for actors that correspond to entities.
// // Not an ideal solution; we'll have to figure out a map format that can define entities separately or somesuch.
//
// CBaseEntity* templateObject = g_EntityTemplateCollection.getTemplateByActor(m_ObjectTypes.at(m_Objects[i].m_ObjectIndex));
//
// if (templateObject)
// {
// CVector3D orient = ((CMatrix3D*)m_Objects[i].m_Transform)->GetIn();
// 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); CUnit* unit = g_UnitMan.CreateUnit(m_ObjectTypes.at(m_Objects[i].m_ObjectIndex), NULL);
@ -223,14 +204,15 @@ int CMapReader::ApplyData()
if (unit) if (unit)
{ {
CMatrix3D transform; CMatrix3D transform;
memcpy(&transform._11,m_Objects[i].m_Transform,sizeof(float)*16); memcpy(&transform._11, m_Objects[i].m_Transform, sizeof(float)*16);
unit->GetModel()->SetTransform(transform); unit->GetModel()->SetTransform(transform);
} }
} }
if (unpacker.GetVersion()>=2) { if (unpacker.GetVersion() >= 2)
{
// copy over the lighting parameters // copy over the lighting parameters
*pLightEnv=m_LightEnv; *pLightEnv = m_LightEnv;
} }
return 0; return 0;
@ -238,11 +220,13 @@ int CMapReader::ApplyData()
// Holds various state data while reading maps, so that loading can be
// interrupted (e.g. to update the progress display) then later resumed.
class CXMLReader class CXMLReader
{ {
public: public:
CXMLReader(const CStr& xml_filename) CXMLReader(const CStr& xml_filename, CMapReader& mapReader)
: m_MapReader(mapReader)
{ {
Init(xml_filename); Init(xml_filename);
} }
@ -253,18 +237,20 @@ public:
private: private:
CXeromyces xmb_file; CXeromyces xmb_file;
CMapReader& m_MapReader;
int el_scenario, el_entities, el_entity; int el_scenario, el_entities, el_entity;
int el_template, el_player; int el_template, el_player;
int el_position, el_orientation; int el_position, el_orientation;
int el_nonentities, el_nonentity; int el_nonentities, el_nonentity;
int el_actor; int el_actor;
int el_environment, el_suncolour, el_sunelevation, el_sunrotation;
int el_terrainambientcolour, el_unitsambientcolour;
int at_x, at_y, at_z; int at_x, at_y, at_z;
int at_r, at_g, at_b;
int at_angle; int at_angle;
XMBElement root; XMBElementList nodes; // children of root
XMBElementList nodes; // children of root
XMBElement node; // a child of nodes
XMBElementList entities, nonentities; // children of node
// loop counters // loop counters
int node_idx; int node_idx;
@ -275,8 +261,10 @@ private:
void Init(const CStr& xml_filename); void Init(const CStr& xml_filename);
int ReadEntities(XMBElement& parent, double end_time);
int ReadNonEntities(XMBElement& parent, double end_time); void ReadEnvironment(XMBElement parent);
int ReadEntities(XMBElement parent, double end_time);
int ReadNonEntities(XMBElement parent, double end_time);
}; };
@ -299,6 +287,7 @@ void CXMLReader::Init(const CStr& xml_filename)
#endif #endif
// define all the elements and attributes used in the XML file. // define all the elements and attributes used in the XML file.
// (Needs to be synchronised with the list in CXMLReader - ugh)
#define EL(x) el_##x = xmb_file.getElementID(#x) #define EL(x) el_##x = xmb_file.getElementID(#x)
#define AT(x) at_##x = xmb_file.getAttributeID(#x) #define AT(x) at_##x = xmb_file.getAttributeID(#x)
EL(scenario); EL(scenario);
@ -311,14 +300,19 @@ void CXMLReader::Init(const CStr& xml_filename)
EL(nonentities); EL(nonentities);
EL(nonentity); EL(nonentity);
EL(actor); EL(actor);
AT(x); EL(environment);
AT(y); EL(suncolour);
AT(z); EL(sunelevation);
EL(sunrotation);
EL(terrainambientcolour);
EL(unitsambientcolour);
AT(x); AT(y); AT(z);
AT(r); AT(g); AT(b);
AT(angle); AT(angle);
#undef AT #undef AT
#undef EL #undef EL
root = xmb_file.getRoot(); XMBElement root = xmb_file.getRoot();
assert(root.getNodeName() == el_scenario); assert(root.getNodeName() == el_scenario);
nodes = root.getChildNodes(); nodes = root.getChildNodes();
@ -327,21 +321,58 @@ void CXMLReader::Init(const CStr& xml_filename)
completed_jobs = 0; completed_jobs = 0;
total_jobs = 0; total_jobs = 0;
for (int i = 0; i < nodes.Count; i++) for (int i = 0; i < nodes.Count; i++)
{ total_jobs += nodes.item(i).getChildNodes().Count;
node = nodes.item(i);
entities = node.getChildNodes();
total_jobs += entities.Count;
}
} }
void CXMLReader::ReadEnvironment(XMBElement parent)
int CXMLReader::ReadEntities(XMBElement& parent, double end_time)
{ {
entities = parent.getChildNodes(); // ok to set more than once XERO_ITER_EL(parent, element)
while(entity_idx < entities.Count) {
int element_name = element.getNodeName();
XMBAttributeList attrs = element.getAttributes();
if (element_name == el_suncolour)
{
m_MapReader.m_LightEnv.m_SunColor = RGBColor(
CStr(attrs.getNamedItem(at_r)).ToFloat(),
CStr(attrs.getNamedItem(at_g)).ToFloat(),
CStr(attrs.getNamedItem(at_b)).ToFloat());
}
else if (element_name == el_sunelevation)
{
m_MapReader.m_LightEnv.m_Elevation = CStr(attrs.getNamedItem(at_angle)).ToFloat();
}
else if (element_name == el_sunrotation)
{
m_MapReader.m_LightEnv.m_Rotation = CStr(attrs.getNamedItem(at_angle)).ToFloat();
}
else if (element_name == el_terrainambientcolour)
{
m_MapReader.m_LightEnv.m_TerrainAmbientColor = RGBColor(
CStr(attrs.getNamedItem(at_r)).ToFloat(),
CStr(attrs.getNamedItem(at_g)).ToFloat(),
CStr(attrs.getNamedItem(at_b)).ToFloat());
}
else if (element_name == el_unitsambientcolour)
{
m_MapReader.m_LightEnv.m_UnitsAmbientColor = RGBColor(
CStr(attrs.getNamedItem(at_r)).ToFloat(),
CStr(attrs.getNamedItem(at_g)).ToFloat(),
CStr(attrs.getNamedItem(at_b)).ToFloat());
}
else
debug_warn("Invalid XML data - DTD shouldn't allow this");
}
m_MapReader.m_LightEnv.CalculateSunDirection();
}
int CXMLReader::ReadEntities(XMBElement parent, double end_time)
{
XMBElementList entities = parent.getChildNodes();
while (entity_idx < entities.Count)
{ {
// all new state at this scope and below doesn't need to be // all new state at this scope and below doesn't need to be
// wrapped, since we only yield after a complete iteration. // wrapped, since we only yield after a complete iteration.
@ -354,34 +385,33 @@ int CXMLReader::ReadEntities(XMBElement& parent, double end_time)
CVector3D Position; CVector3D Position;
float Orientation; float Orientation;
XMBElementList children3 = entity.getChildNodes(); XERO_ITER_EL(entity, setting)
for (int k = 0; k < children3.Count; k++)
{ {
XMBElement child3 = children3.item(k); int element_name = setting.getNodeName();
int element_name = child3.getNodeName();
// <template> // <template>
if (element_name == el_template) if (element_name == el_template)
{ {
TemplateName = child3.getText(); TemplateName = setting.getText();
} }
// <player> // <player>
else if (element_name == el_player) else if (element_name == el_player)
{ {
PlayerID = CStr(child3.getText()).ToInt(); PlayerID = CStr(setting.getText()).ToInt();
} }
// <position> // <position>
else if (element_name == el_position) else if (element_name == el_position)
{ {
XMBAttributeList attrs = child3.getAttributes(); XMBAttributeList attrs = setting.getAttributes();
Position = CVector3D(CStr(attrs.getNamedItem(at_x)).ToFloat(), Position = CVector3D(
CStr(attrs.getNamedItem(at_y)).ToFloat(), CStr(attrs.getNamedItem(at_x)).ToFloat(),
CStr(attrs.getNamedItem(at_z)).ToFloat()); CStr(attrs.getNamedItem(at_y)).ToFloat(),
CStr(attrs.getNamedItem(at_z)).ToFloat());
} }
// <orientation> // <orientation>
else if (element_name == el_orientation) else if (element_name == el_orientation)
{ {
XMBAttributeList attrs = child3.getAttributes(); XMBAttributeList attrs = setting.getAttributes();
Orientation = CStr(attrs.getNamedItem(at_angle)).ToFloat(); Orientation = CStr(attrs.getNamedItem(at_angle)).ToFloat();
} }
else else
@ -389,6 +419,7 @@ int CXMLReader::ReadEntities(XMBElement& parent, double end_time)
} }
HEntity ent = g_EntityManager.create(g_EntityTemplateCollection.getTemplate(TemplateName), Position, Orientation); HEntity ent = g_EntityManager.create(g_EntityTemplateCollection.getTemplate(TemplateName), Position, Orientation);
if (! ent) if (! ent)
LOG(ERROR, LOG_CATEGORY, "Failed to create entity '%ls'", TemplateName.c_str()); LOG(ERROR, LOG_CATEGORY, "Failed to create entity '%ls'", TemplateName.c_str());
else else
@ -402,10 +433,10 @@ int CXMLReader::ReadEntities(XMBElement& parent, double end_time)
} }
int CXMLReader::ReadNonEntities(XMBElement& parent, double end_time) int CXMLReader::ReadNonEntities(XMBElement parent, double end_time)
{ {
nonentities = parent.getChildNodes(); // ok to set more than once XMBElementList nonentities = parent.getChildNodes();
while(nonentity_idx < nonentities.Count) while (nonentity_idx < nonentities.Count)
{ {
// all new state at this scope and below doesn't need to be // all new state at this scope and below doesn't need to be
// wrapped, since we only yield after a complete iteration. // wrapped, since we only yield after a complete iteration.
@ -417,21 +448,19 @@ int CXMLReader::ReadNonEntities(XMBElement& parent, double end_time)
CVector3D Position; CVector3D Position;
float Orientation; float Orientation;
XMBElementList children3 = nonentity.getChildNodes(); XERO_ITER_EL(nonentity, setting)
for (int k = 0; k < children3.Count; k++)
{ {
XMBElement child3 = children3.item(k); int element_name = setting.getNodeName();
int element_name = child3.getNodeName();
// <actor> // <actor>
if (element_name == el_actor) if (element_name == el_actor)
{ {
ActorName = child3.getText(); ActorName = setting.getText();
} }
// <position> // <position>
else if (element_name == el_position) else if (element_name == el_position)
{ {
XMBAttributeList attrs = child3.getAttributes(); XMBAttributeList attrs = setting.getAttributes();
Position = CVector3D(CStr(attrs.getNamedItem(at_x)).ToFloat(), Position = CVector3D(CStr(attrs.getNamedItem(at_x)).ToFloat(),
CStr(attrs.getNamedItem(at_y)).ToFloat(), CStr(attrs.getNamedItem(at_y)).ToFloat(),
CStr(attrs.getNamedItem(at_z)).ToFloat()); CStr(attrs.getNamedItem(at_z)).ToFloat());
@ -439,7 +468,7 @@ int CXMLReader::ReadNonEntities(XMBElement& parent, double end_time)
// <orientation> // <orientation>
else if (element_name == el_orientation) else if (element_name == el_orientation)
{ {
XMBAttributeList attrs = child3.getAttributes(); XMBAttributeList attrs = setting.getAttributes();
Orientation = CStr(attrs.getNamedItem(at_angle)).ToFloat(); Orientation = CStr(attrs.getNamedItem(at_angle)).ToFloat();
} }
else else
@ -447,16 +476,17 @@ int CXMLReader::ReadNonEntities(XMBElement& parent, double end_time)
} }
CUnit* unit = g_UnitMan.CreateUnit(ActorName, NULL); CUnit* unit = g_UnitMan.CreateUnit(ActorName, NULL);
if (unit && unit->GetModel()) if (unit && unit->GetModel())
{ {
// Copied from CEntity::updateActorTransforms(): // Copied from CEntity::updateActorTransforms():
float s = sin( Orientation ); float s = sin(Orientation);
float c = cos( Orientation ); float c = cos(Orientation);
CMatrix3D m; CMatrix3D m;
m._11 = -c; m._12 = 0.0f; m._13 = -s; m._14 = Position.X; m._11 = -c; m._12 = 0.0f; m._13 = -s; m._14 = Position.X;
m._21 = 0.0f; m._22 = 1.0f; m._23 = 0.0f; m._24 = Position.Y; m._21 = 0.0f; m._22 = 1.0f; m._23 = 0.0f; m._24 = Position.Y;
m._31 = s; m._32 = 0.0f; m._33 = -c; m._34 = Position.Z; m._31 = s; m._32 = 0.0f; m._33 = -c; m._34 = Position.Z;
m._41 = 0.0f; m._42 = 0.0f; m._43 = 0.0f; m._44 = 1.0f; m._41 = 0.0f; m._42 = 0.0f; m._43 = 0.0f; m._44 = 1.0f;
unit->GetModel()->SetTransform(m); unit->GetModel()->SetTransform(m);
} }
@ -476,19 +506,23 @@ int CXMLReader::ProgressiveRead()
int ret; int ret;
while(node_idx < nodes.Count) while (node_idx < nodes.Count)
{ {
node = nodes.item(node_idx); XMBElement node = nodes.item(node_idx);
if (node.getNodeName() == el_entities) if (node.getNodeName() == el_environment)
{
ReadEnvironment(node);
}
else if (node.getNodeName() == el_entities)
{ {
ret = ReadEntities(node, end_time); ret = ReadEntities(node, end_time);
if(ret != 0) // error or timed out if (ret != 0) // error or timed out
return ret; return ret;
} }
else if (node.getNodeName() == el_nonentities) else if (node.getNodeName() == el_nonentities)
{ {
ret = ReadNonEntities(node, end_time); ret = ReadNonEntities(node, end_time);
if(ret != 0) // error or timed out if (ret != 0) // error or timed out
return ret; return ret;
} }
else else
@ -504,12 +538,12 @@ int CXMLReader::ProgressiveRead()
// progressive // progressive
int CMapReader::ReadXML() int CMapReader::ReadXML()
{ {
if(!xml_reader) if (!xml_reader)
xml_reader = new CXMLReader(filename_xml); xml_reader = new CXMLReader(filename_xml, *this);
int ret = xml_reader->ProgressiveRead(); int ret = xml_reader->ProgressiveRead();
// finished or failed // finished or failed
if(ret <= 0) if (ret <= 0)
{ {
delete xml_reader; delete xml_reader;
xml_reader = 0; xml_reader = 0;

View File

@ -16,6 +16,8 @@ class CXMLReader;
class CMapReader : public CMapIO class CMapReader : public CMapIO
{ {
friend class CXMLReader;
public: public:
// constructor // constructor
CMapReader(); CMapReader();
@ -65,8 +67,8 @@ private:
CStr filename_xml; CStr filename_xml;
// UnpackTerrain generator state // UnpackTerrain generator state
int cur_terrain_tex; u32 cur_terrain_tex;
int num_terrain_tex; u32 num_terrain_tex;
CXMLReader* xml_reader; CXMLReader* xml_reader;
}; };

View File

@ -40,7 +40,7 @@ void CMapWriter::SaveMap(const char* filename, CTerrain *pTerrain, CLightEnv *pL
CStr filename_xml (filename); CStr filename_xml (filename);
filename_xml = filename_xml.Left(filename_xml.Length()-4) + ".xml"; filename_xml = filename_xml.Left(filename_xml.Length()-4) + ".xml";
WriteXML(filename_xml, pUnitMan); WriteXML(filename_xml, pUnitMan, pLightEnv);
} }
/////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////
@ -113,30 +113,6 @@ void CMapWriter::PackMap(CFilePacker& packer, CTerrain *pTerrain, CLightEnv *pLi
{ {
// now pack everything up // now pack everything up
PackTerrain(packer, pTerrain); PackTerrain(packer, pTerrain);
PackObjects(packer, pUnitMan);
PackLightEnv(packer, pLightEnv);
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// PackLightEnv: pack lighting parameters onto the end of the output data stream
void CMapWriter::PackLightEnv(CFilePacker& packer, CLightEnv *pLightEnv)
{
packer.PackRaw(&pLightEnv->m_SunColor,sizeof(pLightEnv->m_SunColor));
packer.PackRaw(&pLightEnv->m_Elevation,sizeof(pLightEnv->m_Elevation));
packer.PackRaw(&pLightEnv->m_Rotation,sizeof(pLightEnv->m_Rotation));
packer.PackRaw(&pLightEnv->m_TerrainAmbientColor,sizeof(pLightEnv->m_TerrainAmbientColor));
packer.PackRaw(&pLightEnv->m_UnitsAmbientColor,sizeof(pLightEnv->m_UnitsAmbientColor));
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// PackObjects: pack world objects onto the end of the output data stream
// - data: list of objects types used by map, list of object descriptions
void CMapWriter::PackObjects(CFilePacker& packer, CUnitManager *pUnitMan)
{
// (These are now handled by XML, so this function is fairly uninteresting)
u32 zero = 0;
packer.PackRaw(&zero,sizeof(zero)); // numObjTypes
packer.PackRaw(&zero,sizeof(zero)); // numObjects
} }
/////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////
@ -172,7 +148,7 @@ void CMapWriter::PackTerrain(CFilePacker& packer, CTerrain *pTerrain)
void CMapWriter::WriteXML(const char* filename, CUnitManager* pUnitMan) void CMapWriter::WriteXML(const char* filename, CUnitManager* pUnitMan, CLightEnv *pLightEnv)
{ {
// HACK: ScEd uses non-VFS filenames, so just use fopen instead of vfs_open // HACK: ScEd uses non-VFS filenames, so just use fopen instead of vfs_open
#ifdef SCED #ifdef SCED
@ -192,15 +168,55 @@ void CMapWriter::WriteXML(const char* filename, CUnitManager* pUnitMan)
#endif #endif
XML_Start("utf-8"); XML_Start("utf-8");
XML_Doctype("Scenario", "/maps/scenario.dtd"); // DTDs are rather annoying. They ought to be strict in what they accept,
// else they serve no purpose (given that the only purpose is complaining
// nicely when someone provides invalid input). But then it can't be
// backwards-compatible, because the old data files don't follow the new
// format, and there's no way we're going to rebuild all the old data
// files. So, just create an entirely new DTD for each revision of the
// format:
XML_Doctype("Scenario", "/maps/scenario_v4.dtd");
{ {
XML_Element("Scenario"); XML_Element("Scenario");
{
XML_Element("Environment");
{
XML_Element("SunColour");
XML_Attribute("r", pLightEnv->m_SunColor.X); // yes, it's X/Y/Z...
XML_Attribute("g", pLightEnv->m_SunColor.Y);
XML_Attribute("b", pLightEnv->m_SunColor.Z);
}
{
XML_Element("SunElevation");
XML_Attribute("angle", pLightEnv->m_Elevation);
}
{
XML_Element("SunRotation");
XML_Attribute("angle", pLightEnv->m_Rotation);
}
{
XML_Element("TerrainAmbientColour");
XML_Attribute("r", pLightEnv->m_TerrainAmbientColor.X);
XML_Attribute("g", pLightEnv->m_TerrainAmbientColor.Y);
XML_Attribute("b", pLightEnv->m_TerrainAmbientColor.Z);
}
{
XML_Element("UnitsAmbientColour");
XML_Attribute("r", pLightEnv->m_UnitsAmbientColor.X);
XML_Attribute("g", pLightEnv->m_UnitsAmbientColor.Y);
XML_Attribute("b", pLightEnv->m_UnitsAmbientColor.Z);
}
}
{ {
XML_Element("Entities"); XML_Element("Entities");
const std::vector<CUnit*>& units = pUnitMan->GetUnits(); const std::vector<CUnit*>& units = pUnitMan->GetUnits();
for (std::vector<CUnit*>::const_iterator unit = units.begin(); unit != units.end(); ++unit) { for (std::vector<CUnit*>::const_iterator unit = units.begin(); unit != units.end(); ++unit)
{
CEntity* entity = (*unit)->GetEntity(); CEntity* entity = (*unit)->GetEntity();

View File

@ -27,10 +27,6 @@ private:
void PackMap(CFilePacker& packer, CTerrain *pTerr, CLightEnv *pLightEnv, CUnitManager *pUnitMan); void PackMap(CFilePacker& packer, CTerrain *pTerr, CLightEnv *pLightEnv, CUnitManager *pUnitMan);
// PackTerrain: pack the terrain onto the end of the data stream // PackTerrain: pack the terrain onto the end of the data stream
void PackTerrain(CFilePacker& packer, CTerrain *pTerrain); void PackTerrain(CFilePacker& packer, CTerrain *pTerrain);
// PackObjects: pack world objects onto the end of the output data stream
void PackObjects(CFilePacker& packer, CUnitManager *pUnitMan);
// PackLightEnv: pack lighting parameters onto the end of the output data stream
void PackLightEnv(CFilePacker& packer, CLightEnv *pLightEnv);
// EnumTerrainTextures: build lists of textures used by map, and indices into this list // EnumTerrainTextures: build lists of textures used by map, and indices into this list
// for each tile on the terrain // for each tile on the terrain
@ -38,7 +34,7 @@ private:
std::vector<STileDesc>& tileIndices); std::vector<STileDesc>& tileIndices);
// WriteXML: output some other data (entities, etc) in XML format // WriteXML: output some other data (entities, etc) in XML format
void WriteXML(const char* filename, CUnitManager* pUnitMan); void WriteXML(const char* filename, CUnitManager* pUnitMan, CLightEnv *pLightEnv);
}; };
#endif #endif

View File

@ -250,7 +250,7 @@ int LDR_ProgressiveLoad(double time_budget, wchar_t* description,
double current_estimate = estimated_duration_tally; double current_estimate = estimated_duration_tally;
// function interrupted itself; add its estimated progress. // function interrupted itself; add its estimated progress.
// note: monoticity is guaranteed since we never add more than // note: monotonicity is guaranteed since we never add more than
// its estimated_duration_ms. // its estimated_duration_ms.
if(ret > 0) if(ret > 0)
{ {
@ -261,6 +261,10 @@ int LDR_ProgressiveLoad(double time_budget, wchar_t* description,
progress = current_estimate / total_estimated_duration; progress = current_estimate / total_estimated_duration;
} }
// function interrupted itself; need to return ERR_TIMED_OUT
if(ret > 0)
ret = ERR_TIMED_OUT;
// failed or timed out => abort immediately; loading will // failed or timed out => abort immediately; loading will
// continue when we're called in the next iteration of the main loop. // continue when we're called in the next iteration of the main loop.
// rationale: bail immediately instead of remembering the first error // rationale: bail immediately instead of remembering the first error