2004-06-01 19:34:12 +02:00
|
|
|
#include "precompiled.h"
|
2004-05-29 22:56:24 +02:00
|
|
|
|
2005-02-26 16:13:15 +01:00
|
|
|
#include "lib/types.h"
|
2005-08-12 19:06:53 +02:00
|
|
|
#include "lib/res/file/vfs.h"
|
2005-06-20 17:14:36 +02:00
|
|
|
|
2006-06-22 00:37:31 +02:00
|
|
|
#include "Camera.h"
|
|
|
|
#include "LightEnv.h"
|
2005-03-29 22:50:04 +02:00
|
|
|
#include "MapReader.h"
|
2006-06-22 00:37:31 +02:00
|
|
|
#include "MapWriter.h"
|
2004-05-29 22:56:24 +02:00
|
|
|
#include "Model.h"
|
2006-06-22 00:37:31 +02:00
|
|
|
#include "ObjectBase.h"
|
|
|
|
#include "ObjectManager.h"
|
|
|
|
#include "Patch.h"
|
2004-05-29 22:56:24 +02:00
|
|
|
#include "Terrain.h"
|
2005-06-20 17:14:36 +02:00
|
|
|
#include "TextureEntry.h"
|
2006-06-22 00:37:31 +02:00
|
|
|
#include "TextureManager.h"
|
|
|
|
#include "Unit.h"
|
|
|
|
#include "UnitManager.h"
|
|
|
|
|
2006-06-02 04:10:27 +02:00
|
|
|
#include "maths/MathUtil.h"
|
2006-06-22 00:37:31 +02:00
|
|
|
#include "ps/Loader.h"
|
2006-06-09 18:44:16 +02:00
|
|
|
#include "ps/Player.h"
|
2006-06-22 00:37:31 +02:00
|
|
|
#include "ps/VFSUtil.h"
|
2005-08-15 01:50:37 +02:00
|
|
|
#include "ps/XML/XMLWriter.h"
|
2006-06-22 00:37:31 +02:00
|
|
|
#include "renderer/SkyManager.h"
|
|
|
|
#include "renderer/WaterManager.h"
|
2006-07-13 05:29:33 +02:00
|
|
|
#include "simulation/EntityTemplate.h"
|
|
|
|
#include "simulation/EntityTemplateCollection.h"
|
2006-06-22 00:37:31 +02:00
|
|
|
#include "simulation/Entity.h"
|
2005-01-12 15:31:47 +01:00
|
|
|
|
2004-05-29 22:56:24 +02:00
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// CMapWriter constructor: nothing to do at the minute
|
|
|
|
CMapWriter::CMapWriter()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// SaveMap: try to save the current map to the given file
|
2006-06-22 00:37:31 +02:00
|
|
|
void CMapWriter::SaveMap(const char* filename, CTerrain* pTerrain,
|
|
|
|
CUnitManager* pUnitMan, WaterManager* pWaterMan, SkyManager* pSkyMan,
|
|
|
|
CLightEnv* pLightEnv, CCamera* pCamera)
|
2004-05-29 22:56:24 +02:00
|
|
|
{
|
2004-12-15 15:26:21 +01:00
|
|
|
CFilePacker packer(FILE_VERSION, "PSMP");
|
2004-05-29 22:56:24 +02:00
|
|
|
|
|
|
|
// build necessary data
|
2006-06-22 00:37:31 +02:00
|
|
|
PackMap(packer, pTerrain);
|
2004-05-29 22:56:24 +02:00
|
|
|
|
|
|
|
// write it out
|
2004-12-15 15:26:21 +01:00
|
|
|
packer.Write(filename);
|
2005-01-12 15:31:47 +01:00
|
|
|
|
|
|
|
CStr filename_xml (filename);
|
|
|
|
filename_xml = filename_xml.Left(filename_xml.Length()-4) + ".xml";
|
2006-06-22 00:37:31 +02:00
|
|
|
WriteXML(filename_xml, pUnitMan, pWaterMan, pSkyMan, pLightEnv, pCamera);
|
2004-05-29 22:56:24 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// GetHandleIndex: return the index of the given handle in the given list; or 0xffff if
|
|
|
|
// handle isn't in list
|
2006-06-11 09:03:59 +02:00
|
|
|
static u16 GetHandleIndex(const Handle handle, const std::vector<Handle>& handles)
|
2004-05-29 22:56:24 +02:00
|
|
|
{
|
2005-08-09 17:55:44 +02:00
|
|
|
const uint limit = MIN((uint)handles.size(), 0xFFFE); // paranoia
|
|
|
|
for (uint i=0;i<limit;i++) {
|
2004-05-29 22:56:24 +02:00
|
|
|
if (handles[i]==handle) {
|
2005-08-09 17:55:44 +02:00
|
|
|
return (u16)i;
|
2004-05-29 22:56:24 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0xffff;
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// EnumTerrainTextures: build lists of textures used by map, and tile descriptions for
|
|
|
|
// each tile on the terrain
|
2004-07-31 17:57:18 +02:00
|
|
|
void CMapWriter::EnumTerrainTextures(CTerrain *pTerrain,
|
|
|
|
std::vector<CStr>& textures,
|
2004-05-29 22:56:24 +02:00
|
|
|
std::vector<STileDesc>& tiles)
|
|
|
|
{
|
|
|
|
// the list of all handles in use
|
|
|
|
std::vector<Handle> handles;
|
|
|
|
|
|
|
|
// resize tile array to required size
|
2004-07-31 17:57:18 +02:00
|
|
|
tiles.resize(SQR(pTerrain->GetVerticesPerSide()-1));
|
2004-05-29 22:56:24 +02:00
|
|
|
STileDesc* tileptr=&tiles[0];
|
|
|
|
|
|
|
|
// now iterate through all the tiles
|
2004-07-31 17:57:18 +02:00
|
|
|
u32 mapsize=pTerrain->GetPatchesPerSide();
|
2004-05-29 22:56:24 +02:00
|
|
|
for (u32 j=0;j<mapsize;j++) {
|
|
|
|
for (u32 i=0;i<mapsize;i++) {
|
2005-10-07 17:24:29 +02:00
|
|
|
for (u32 m=0;m<(u32)PATCH_SIZE;m++) {
|
|
|
|
for (u32 k=0;k<(u32)PATCH_SIZE;k++) {
|
2004-07-31 17:57:18 +02:00
|
|
|
CMiniPatch& mp=pTerrain->GetPatch(i,j)->m_MiniPatches[m][k];
|
2004-05-29 22:56:24 +02:00
|
|
|
u16 index=u16(GetHandleIndex(mp.Tex1,handles));
|
|
|
|
if (index==0xffff) {
|
2004-06-11 04:14:18 +02:00
|
|
|
index=(u16)handles.size();
|
2004-05-29 22:56:24 +02:00
|
|
|
handles.push_back(mp.Tex1);
|
|
|
|
}
|
|
|
|
|
|
|
|
tileptr->m_Tex1Index=index;
|
|
|
|
tileptr->m_Tex2Index=0xffff;
|
|
|
|
tileptr->m_Priority=mp.Tex1Priority;
|
|
|
|
tileptr++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// now find the texture names for each handle
|
2004-06-11 04:14:18 +02:00
|
|
|
for (uint i=0;i<(uint)handles.size();i++) {
|
2004-05-29 22:56:24 +02:00
|
|
|
CStr texturename;
|
|
|
|
CTextureEntry* texentry=g_TexMan.FindTexture(handles[i]);
|
|
|
|
if (!texentry) {
|
|
|
|
// uh-oh, this shouldn't happen; set texturename to empty string
|
|
|
|
texturename="";
|
|
|
|
} else {
|
2005-06-20 17:14:36 +02:00
|
|
|
texturename=texentry->GetTag();
|
2004-05-29 22:56:24 +02:00
|
|
|
}
|
|
|
|
textures.push_back(texturename);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// PackMap: pack the current world into a raw data stream
|
2006-06-22 00:37:31 +02:00
|
|
|
void CMapWriter::PackMap(CFilePacker& packer, CTerrain* pTerrain)
|
2004-05-29 22:56:24 +02:00
|
|
|
{
|
|
|
|
// now pack everything up
|
2004-07-31 17:57:18 +02:00
|
|
|
PackTerrain(packer, pTerrain);
|
2004-05-29 22:56:24 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// PackTerrain: pack the terrain onto the end of the output data stream
|
|
|
|
// - data: map size, heightmap, list of textures used by map, texture tile assignments
|
2006-06-11 09:03:59 +02:00
|
|
|
void CMapWriter::PackTerrain(CFilePacker& packer, CTerrain* pTerrain)
|
2004-05-29 22:56:24 +02:00
|
|
|
{
|
|
|
|
// pack map size
|
2004-07-31 17:57:18 +02:00
|
|
|
u32 mapsize=pTerrain->GetPatchesPerSide();
|
2004-05-29 22:56:24 +02:00
|
|
|
packer.PackRaw(&mapsize,sizeof(mapsize));
|
|
|
|
|
|
|
|
// pack heightmap
|
2004-07-31 17:57:18 +02:00
|
|
|
packer.PackRaw(pTerrain->GetHeightMap(),sizeof(u16)*SQR(pTerrain->GetVerticesPerSide()));
|
2004-05-29 22:56:24 +02:00
|
|
|
|
|
|
|
// the list of textures used by map
|
|
|
|
std::vector<CStr> terrainTextures;
|
|
|
|
// descriptions of each tile
|
|
|
|
std::vector<STileDesc> tiles;
|
|
|
|
|
|
|
|
// build lists by scanning through the terrain
|
2004-07-31 17:57:18 +02:00
|
|
|
EnumTerrainTextures(pTerrain, terrainTextures, tiles);
|
2004-05-29 22:56:24 +02:00
|
|
|
|
|
|
|
// pack texture names
|
2004-06-11 04:14:18 +02:00
|
|
|
u32 numTextures=(u32)terrainTextures.size();
|
2004-05-29 22:56:24 +02:00
|
|
|
packer.PackRaw(&numTextures,sizeof(numTextures));
|
|
|
|
for (uint i=0;i<numTextures;i++) {
|
|
|
|
packer.PackString(terrainTextures[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
// pack tile data
|
2004-06-11 04:14:18 +02:00
|
|
|
packer.PackRaw(&tiles[0],(u32)(sizeof(STileDesc)*tiles.size()));
|
2004-05-29 22:56:24 +02:00
|
|
|
}
|
|
|
|
|
2005-01-12 15:31:47 +01:00
|
|
|
|
|
|
|
|
2006-06-22 00:37:31 +02:00
|
|
|
void CMapWriter::WriteXML(const char* filename,
|
|
|
|
CUnitManager* pUnitMan, WaterManager* pWaterMan, SkyManager* pSkyMan,
|
|
|
|
CLightEnv* pLightEnv, CCamera* pCamera)
|
2005-01-12 15:31:47 +01:00
|
|
|
{
|
2006-05-17 16:48:18 +02:00
|
|
|
Handle h = vfs_open(filename, FILE_WRITE_TO_TARGET|FILE_NO_AIO);
|
2005-01-12 15:31:47 +01:00
|
|
|
if (h <= 0)
|
|
|
|
{
|
|
|
|
debug_warn("Failed to open map XML file");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
XML_Start("utf-8");
|
|
|
|
|
|
|
|
{
|
|
|
|
XML_Element("Scenario");
|
2005-05-11 05:07:08 +02:00
|
|
|
|
|
|
|
{
|
|
|
|
XML_Element("Environment");
|
|
|
|
|
2006-06-22 00:37:31 +02:00
|
|
|
XML_Setting("SkySet", pSkyMan->GetSkySet());
|
2005-05-11 05:07:08 +02:00
|
|
|
{
|
|
|
|
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);
|
|
|
|
}
|
2006-06-11 09:03:59 +02:00
|
|
|
|
|
|
|
{
|
|
|
|
XML_Element("Water");
|
|
|
|
{
|
|
|
|
XML_Element("WaterBody");
|
|
|
|
XML_Setting("Type", "default");
|
|
|
|
{
|
|
|
|
XML_Element("Colour");
|
|
|
|
XML_Attribute("r", pWaterMan->m_WaterColor.r);
|
|
|
|
XML_Attribute("g", pWaterMan->m_WaterColor.g);
|
|
|
|
XML_Attribute("b", pWaterMan->m_WaterColor.b);
|
|
|
|
}
|
|
|
|
XML_Setting("Height", pWaterMan->m_WaterHeight);
|
|
|
|
XML_Setting("Shininess", pWaterMan->m_Shininess);
|
|
|
|
XML_Setting("Waviness", pWaterMan->m_Waviness);
|
|
|
|
}
|
|
|
|
}
|
2005-05-11 05:07:08 +02:00
|
|
|
}
|
|
|
|
|
2006-03-21 21:55:45 +01:00
|
|
|
{
|
|
|
|
XML_Element("Camera");
|
|
|
|
|
|
|
|
{
|
|
|
|
XML_Element("Position");
|
|
|
|
CVector3D pos = pCamera->m_Orientation.GetTranslation();
|
|
|
|
XML_Attribute("x", pos.X);
|
|
|
|
XML_Attribute("y", pos.Y);
|
|
|
|
XML_Attribute("z", pos.Z);
|
|
|
|
}
|
|
|
|
|
|
|
|
CVector3D in = pCamera->m_Orientation.GetIn();
|
|
|
|
// Convert to spherical coordinates
|
|
|
|
float rotation = atan2(in.X, in.Z);
|
|
|
|
float declination = atan2(sqrt(in.X*in.X + in.Z*in.Z), in.Y) - M_PI_2;
|
|
|
|
|
|
|
|
{
|
|
|
|
XML_Element("Rotation");
|
|
|
|
XML_Attribute("angle", rotation);
|
|
|
|
}
|
|
|
|
{
|
|
|
|
XML_Element("Declination");
|
|
|
|
XML_Attribute("angle", declination);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-01-12 15:31:47 +01:00
|
|
|
{
|
|
|
|
XML_Element("Entities");
|
|
|
|
|
|
|
|
const std::vector<CUnit*>& units = pUnitMan->GetUnits();
|
2005-05-11 05:07:08 +02:00
|
|
|
for (std::vector<CUnit*>::const_iterator unit = units.begin(); unit != units.end(); ++unit)
|
|
|
|
{
|
2005-01-12 15:31:47 +01:00
|
|
|
|
|
|
|
CEntity* entity = (*unit)->GetEntity();
|
|
|
|
|
|
|
|
// Ignore objects that aren't entities
|
|
|
|
if (! entity)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
XML_Element("Entity");
|
|
|
|
|
|
|
|
XML_Setting("Template", entity->m_base->m_Tag);
|
|
|
|
|
2005-02-11 13:57:19 +01:00
|
|
|
XML_Setting("Player", entity->GetPlayer()->GetPlayerID());
|
2005-01-17 00:09:41 +01:00
|
|
|
|
2005-01-12 15:31:47 +01:00
|
|
|
{
|
|
|
|
CVector3D position = entity->m_position;
|
|
|
|
|
|
|
|
XML_Element("Position");
|
|
|
|
XML_Attribute("x", position.X);
|
|
|
|
XML_Attribute("y", position.Y);
|
|
|
|
XML_Attribute("z", position.Z);
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
2006-05-04 06:14:48 +02:00
|
|
|
float angle = entity->m_orientation.Y;
|
2005-01-12 15:31:47 +01:00
|
|
|
|
2005-03-29 22:50:04 +02:00
|
|
|
XML_Element("Orientation");
|
|
|
|
XML_Attribute("angle", angle);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
|
|
|
XML_Element("Nonentities");
|
|
|
|
|
|
|
|
const std::vector<CUnit*>& units = pUnitMan->GetUnits();
|
|
|
|
for (std::vector<CUnit*>::const_iterator unit = units.begin(); unit != units.end(); ++unit) {
|
|
|
|
|
|
|
|
// Ignore objects that are entities
|
|
|
|
if ((*unit)->GetEntity())
|
|
|
|
continue;
|
|
|
|
|
|
|
|
XML_Element("Nonentity");
|
|
|
|
|
|
|
|
XML_Setting("Actor", (*unit)->GetObject()->m_Base->m_Name);
|
|
|
|
|
|
|
|
{
|
|
|
|
CVector3D position = (*unit)->GetModel()->GetTransform().GetTranslation();
|
|
|
|
|
|
|
|
XML_Element("Position");
|
|
|
|
XML_Attribute("x", position.X);
|
|
|
|
XML_Attribute("y", position.Y);
|
|
|
|
XML_Attribute("z", position.Z);
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
CVector3D orient = (*unit)->GetModel()->GetTransform().GetIn();
|
|
|
|
float angle = atan2(-orient.X, -orient.Z);
|
|
|
|
|
2005-01-12 15:31:47 +01:00
|
|
|
XML_Element("Orientation");
|
|
|
|
XML_Attribute("angle", angle);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (! XML_StoreVFS(h))
|
|
|
|
{
|
|
|
|
debug_warn("Failed to write map XML file");
|
|
|
|
}
|
2006-01-24 09:16:29 +01:00
|
|
|
(void)vfs_close(h);
|
2005-01-17 05:52:02 +01:00
|
|
|
}
|
2005-03-29 22:50:04 +02:00
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// RewriteAllMaps
|
2006-06-11 09:03:59 +02:00
|
|
|
void CMapWriter::RewriteAllMaps(CTerrain* pTerrain, CUnitManager* pUnitMan,
|
2006-06-22 00:37:31 +02:00
|
|
|
WaterManager* pWaterMan, SkyManager* pSkyMan,
|
|
|
|
CLightEnv* pLightEnv, CCamera* pCamera)
|
2005-03-29 22:50:04 +02:00
|
|
|
{
|
|
|
|
VFSUtil::FileList files;
|
|
|
|
VFSUtil::FindFiles("maps/scenarios", "*.pmp", files);
|
|
|
|
|
|
|
|
for (VFSUtil::FileList::iterator it = files.begin(); it != files.end(); ++it)
|
|
|
|
{
|
|
|
|
CMapReader* reader = new CMapReader;
|
|
|
|
LDR_BeginRegistering();
|
2006-06-22 00:37:31 +02:00
|
|
|
reader->LoadMap(*it, pTerrain, pUnitMan, pWaterMan, pSkyMan, pLightEnv, pCamera);
|
2005-03-29 22:50:04 +02:00
|
|
|
LDR_EndRegistering();
|
|
|
|
LDR_NonprogressiveLoad();
|
|
|
|
|
|
|
|
CStr n (*it);
|
|
|
|
n.Replace("scenarios/", "scenarios/new/");
|
|
|
|
CMapWriter writer;
|
2006-06-22 00:37:31 +02:00
|
|
|
writer.SaveMap(n, pTerrain, pUnitMan, pWaterMan, pSkyMan, pLightEnv, pCamera);
|
2005-03-29 22:50:04 +02:00
|
|
|
}
|
|
|
|
}
|