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

View File

@ -5,7 +5,7 @@ class CMapIO
{
public:
// 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
enum { FILE_READ_VERSION = 1 };
@ -31,5 +31,3 @@ public:
};
#endif

View File

@ -40,23 +40,28 @@ void CMapReader::LoadMap(const char* filename, CTerrain *pTerrain_, CUnitManager
unpacker.Read(filename,"PSMP");
// check version
if (unpacker.GetVersion()<FILE_READ_VERSION) {
if (unpacker.GetVersion() < FILE_READ_VERSION) {
throw CFileUnpacker::CFileVersionError();
}
// delete all existing entities
g_EntityManager.deleteAll();
// delete all remaining non-entity units
pUnitMan->DeleteAll();
// unpack the data
RegMemFun(this, &CMapReader::UnpackMap, L"CMapReader::UnpackMap", 1900);
// apply data to the world
RegMemFun(this, &CMapReader::ApplyData, L"CMapReader::ApplyData", 20);
if (unpacker.GetVersion()>=3) {
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);
}
// apply data to the world
RegMemFun(this, &CMapReader::ApplyData, L"CMapReader::ApplyData", 20);
RegMemFun(this, &CMapReader::DelayLoadFinished, L"CMapReader::DelayLoadFinished", 5);
}
@ -68,10 +73,11 @@ int CMapReader::UnpackMap()
if(ret != 0) // failed or timed out
return ret;
UnpackObjects();
if (unpacker.GetVersion()>=2) {
if (unpacker.GetVersion() < 4)
UnpackObjects();
if (unpacker.GetVersion() >= 2 && unpacker.GetVersion() < 4)
UnpackLightEnv();
}
return 0;
}
@ -79,12 +85,12 @@ int CMapReader::UnpackMap()
// 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();
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
@ -92,17 +98,17 @@ void CMapReader::UnpackObjects()
{
// unpack object types
u32 numObjTypes;
unpacker.UnpackRaw(&numObjTypes,sizeof(numObjTypes));
unpacker.UnpackRaw(&numObjTypes, sizeof(numObjTypes));
m_ObjectTypes.resize(numObjTypes);
for (uint i=0;i<numObjTypes;i++) {
for (u32 i=0; i<numObjTypes; i++) {
unpacker.UnpackString(m_ObjectTypes[i]);
}
// unpack object data
u32 numObjects;
unpacker.UnpackRaw(&numObjects,sizeof(numObjects));
unpacker.UnpackRaw(&numObjects, sizeof(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
@ -113,15 +119,15 @@ int CMapReader::UnpackTerrain()
// first call to generator (this is skipped after first call,
// i.e. when the loop below was interrupted)
if(cur_terrain_tex == 0)
if (cur_terrain_tex == 0)
{
// unpack map size
unpacker.UnpackRaw(&m_MapSize,sizeof(m_MapSize));
unpacker.UnpackRaw(&m_MapSize, sizeof(m_MapSize));
// unpack heightmap [600µs]
u32 verticesPerSide=m_MapSize*PATCH_SIZE+1;
u32 verticesPerSide = m_MapSize*PATCH_SIZE+1;
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
unpacker.UnpackRaw(&num_terrain_tex, sizeof(num_terrain_tex));
@ -130,7 +136,7 @@ int CMapReader::UnpackTerrain()
// unpack texture names; find handle for each texture.
// interruptible.
while(cur_terrain_tex < num_terrain_tex)
while (cur_terrain_tex < num_terrain_tex)
{
CStr texturename;
unpacker.UnpackString(texturename);
@ -151,7 +157,7 @@ int CMapReader::UnpackTerrain()
// 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()));
unpacker.UnpackRaw(&m_Tiles[0], (u32)(sizeof(STileDesc)*m_Tiles.size()));
// reset generator state.
cur_terrain_tex = 0;
@ -163,18 +169,18 @@ int CMapReader::UnpackTerrain()
int CMapReader::ApplyData()
{
// initialise the terrain
pTerrain->Initialize(m_MapSize,&m_Heightmap[0]);
pTerrain->Initialize(m_MapSize, &m_Heightmap[0]);
// setup the textures on the minipatches
STileDesc* tileptr=&m_Tiles[0];
for (u32 j=0;j<m_MapSize;j++) {
for (u32 i=0;i<m_MapSize;i++) {
for (u32 m=0;m<PATCH_SIZE;m++) {
for (u32 k=0;k<PATCH_SIZE;k++) {
CMiniPatch& mp=pTerrain->GetPatch(i,j)->m_MiniPatches[m][k];
STileDesc* tileptr = &m_Tiles[0];
for (u32 j=0; j<m_MapSize; j++) {
for (u32 i=0; i<m_MapSize; i++) {
for (u32 m=0; m<PATCH_SIZE; m++) {
for (u32 k=0; k<PATCH_SIZE; k++) {
CMiniPatch& mp = pTerrain->GetPatch(i,j)->m_MiniPatches[m][k];
mp.Tex1=m_TerrainTextures[tileptr->m_Tex1Index];
mp.Tex1Priority=tileptr->m_Priority;
mp.Tex1 = m_TerrainTextures[tileptr->m_Tex1Index];
mp.Tex1Priority = tileptr->m_Priority;
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
for (u32 i=0;i<m_Objects.size();i++) {
if (unpacker.GetVersion() < 3) {
for (size_t i = 0; i < m_Objects.size(); ++i)
{
if (unpacker.GetVersion() < 3)
{
debug_warn("Old unsupported map version - objects will be missing");
// (getTemplateByActor doesn't work, since entity templates are now
// 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);
@ -223,14 +204,15 @@ int CMapReader::ApplyData()
if (unit)
{
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);
}
}
if (unpacker.GetVersion()>=2) {
if (unpacker.GetVersion() >= 2)
{
// copy over the lighting parameters
*pLightEnv=m_LightEnv;
*pLightEnv = m_LightEnv;
}
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
{
public:
CXMLReader(const CStr& xml_filename)
CXMLReader(const CStr& xml_filename, CMapReader& mapReader)
: m_MapReader(mapReader)
{
Init(xml_filename);
}
@ -253,18 +237,20 @@ public:
private:
CXeromyces xmb_file;
CMapReader& m_MapReader;
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 el_environment, el_suncolour, el_sunelevation, el_sunrotation;
int el_terrainambientcolour, el_unitsambientcolour;
int at_x, at_y, at_z;
int at_r, at_g, at_b;
int at_angle;
XMBElement root;
XMBElementList nodes; // children of root
XMBElement node; // a child of nodes
XMBElementList entities, nonentities; // children of node
XMBElementList nodes; // children of root
// loop counters
int node_idx;
@ -275,8 +261,10 @@ private:
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
// 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 AT(x) at_##x = xmb_file.getAttributeID(#x)
EL(scenario);
@ -311,14 +300,19 @@ void CXMLReader::Init(const CStr& xml_filename)
EL(nonentities);
EL(nonentity);
EL(actor);
AT(x);
AT(y);
AT(z);
EL(environment);
EL(suncolour);
EL(sunelevation);
EL(sunrotation);
EL(terrainambientcolour);
EL(unitsambientcolour);
AT(x); AT(y); AT(z);
AT(r); AT(g); AT(b);
AT(angle);
#undef AT
#undef EL
root = xmb_file.getRoot();
XMBElement root = xmb_file.getRoot();
assert(root.getNodeName() == el_scenario);
nodes = root.getChildNodes();
@ -327,21 +321,58 @@ void CXMLReader::Init(const CStr& xml_filename)
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;
}
total_jobs += nodes.item(i).getChildNodes().Count;
}
int CXMLReader::ReadEntities(XMBElement& parent, double end_time)
void CXMLReader::ReadEnvironment(XMBElement parent)
{
entities = parent.getChildNodes(); // ok to set more than once
while(entity_idx < entities.Count)
XERO_ITER_EL(parent, element)
{
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
// wrapped, since we only yield after a complete iteration.
@ -354,34 +385,33 @@ int CXMLReader::ReadEntities(XMBElement& parent, double end_time)
CVector3D Position;
float Orientation;
XMBElementList children3 = entity.getChildNodes();
for (int k = 0; k < children3.Count; k++)
XERO_ITER_EL(entity, setting)
{
XMBElement child3 = children3.item(k);
int element_name = child3.getNodeName();
int element_name = setting.getNodeName();
// <template>
if (element_name == el_template)
{
TemplateName = child3.getText();
TemplateName = setting.getText();
}
// <player>
else if (element_name == el_player)
{
PlayerID = CStr(child3.getText()).ToInt();
PlayerID = CStr(setting.getText()).ToInt();
}
// <position>
else if (element_name == el_position)
{
XMBAttributeList attrs = child3.getAttributes();
Position = CVector3D(CStr(attrs.getNamedItem(at_x)).ToFloat(),
CStr(attrs.getNamedItem(at_y)).ToFloat(),
CStr(attrs.getNamedItem(at_z)).ToFloat());
XMBAttributeList attrs = setting.getAttributes();
Position = CVector3D(
CStr(attrs.getNamedItem(at_x)).ToFloat(),
CStr(attrs.getNamedItem(at_y)).ToFloat(),
CStr(attrs.getNamedItem(at_z)).ToFloat());
}
// <orientation>
else if (element_name == el_orientation)
{
XMBAttributeList attrs = child3.getAttributes();
XMBAttributeList attrs = setting.getAttributes();
Orientation = CStr(attrs.getNamedItem(at_angle)).ToFloat();
}
else
@ -389,6 +419,7 @@ int CXMLReader::ReadEntities(XMBElement& parent, double end_time)
}
HEntity ent = g_EntityManager.create(g_EntityTemplateCollection.getTemplate(TemplateName), Position, Orientation);
if (! ent)
LOG(ERROR, LOG_CATEGORY, "Failed to create entity '%ls'", TemplateName.c_str());
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
while(nonentity_idx < nonentities.Count)
XMBElementList nonentities = parent.getChildNodes();
while (nonentity_idx < nonentities.Count)
{
// all new state at this scope and below doesn't need to be
// wrapped, since we only yield after a complete iteration.
@ -417,21 +448,19 @@ int CXMLReader::ReadNonEntities(XMBElement& parent, double end_time)
CVector3D Position;
float Orientation;
XMBElementList children3 = nonentity.getChildNodes();
for (int k = 0; k < children3.Count; k++)
XERO_ITER_EL(nonentity, setting)
{
XMBElement child3 = children3.item(k);
int element_name = child3.getNodeName();
int element_name = setting.getNodeName();
// <actor>
if (element_name == el_actor)
{
ActorName = child3.getText();
ActorName = setting.getText();
}
// <position>
else if (element_name == el_position)
{
XMBAttributeList attrs = child3.getAttributes();
XMBAttributeList attrs = setting.getAttributes();
Position = CVector3D(CStr(attrs.getNamedItem(at_x)).ToFloat(),
CStr(attrs.getNamedItem(at_y)).ToFloat(),
CStr(attrs.getNamedItem(at_z)).ToFloat());
@ -439,7 +468,7 @@ int CXMLReader::ReadNonEntities(XMBElement& parent, double end_time)
// <orientation>
else if (element_name == el_orientation)
{
XMBAttributeList attrs = child3.getAttributes();
XMBAttributeList attrs = setting.getAttributes();
Orientation = CStr(attrs.getNamedItem(at_angle)).ToFloat();
}
else
@ -447,16 +476,17 @@ int CXMLReader::ReadNonEntities(XMBElement& parent, double end_time)
}
CUnit* unit = g_UnitMan.CreateUnit(ActorName, NULL);
if (unit && unit->GetModel())
{
// Copied from CEntity::updateActorTransforms():
float s = sin( Orientation );
float c = cos( Orientation );
float s = sin(Orientation);
float c = cos(Orientation);
CMatrix3D m;
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._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._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._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;
unit->GetModel()->SetTransform(m);
}
@ -476,19 +506,23 @@ int CXMLReader::ProgressiveRead()
int ret;
while(node_idx < nodes.Count)
while (node_idx < nodes.Count)
{
node = nodes.item(node_idx);
if (node.getNodeName() == el_entities)
XMBElement node = nodes.item(node_idx);
if (node.getNodeName() == el_environment)
{
ReadEnvironment(node);
}
else if (node.getNodeName() == el_entities)
{
ret = ReadEntities(node, end_time);
if(ret != 0) // error or timed out
if (ret != 0) // error or timed out
return ret;
}
else if (node.getNodeName() == el_nonentities)
{
ret = ReadNonEntities(node, end_time);
if(ret != 0) // error or timed out
if (ret != 0) // error or timed out
return ret;
}
else
@ -504,12 +538,12 @@ int CXMLReader::ProgressiveRead()
// progressive
int CMapReader::ReadXML()
{
if(!xml_reader)
xml_reader = new CXMLReader(filename_xml);
if (!xml_reader)
xml_reader = new CXMLReader(filename_xml, *this);
int ret = xml_reader->ProgressiveRead();
// finished or failed
if(ret <= 0)
if (ret <= 0)
{
delete xml_reader;
xml_reader = 0;

View File

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

View File

@ -40,7 +40,7 @@ void CMapWriter::SaveMap(const char* filename, CTerrain *pTerrain, CLightEnv *pL
CStr filename_xml (filename);
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
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
#ifdef SCED
@ -192,15 +168,55 @@ void CMapWriter::WriteXML(const char* filename, CUnitManager* pUnitMan)
#endif
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("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");
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();

View File

@ -27,10 +27,6 @@ private:
void PackMap(CFilePacker& packer, CTerrain *pTerr, CLightEnv *pLightEnv, CUnitManager *pUnitMan);
// PackTerrain: pack the terrain onto the end of the data stream
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
// for each tile on the terrain
@ -38,7 +34,7 @@ private:
std::vector<STileDesc>& tileIndices);
// 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

View File

@ -250,7 +250,7 @@ int LDR_ProgressiveLoad(double time_budget, wchar_t* description,
double current_estimate = estimated_duration_tally;
// 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.
if(ret > 0)
{
@ -261,6 +261,10 @@ int LDR_ProgressiveLoad(double time_budget, wchar_t* description,
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
// continue when we're called in the next iteration of the main loop.
// rationale: bail immediately instead of remembering the first error