2004-06-01 19:34:12 +02:00
|
|
|
#include "precompiled.h"
|
2004-05-29 22:56:24 +02:00
|
|
|
|
|
|
|
#include "MapReader.h"
|
# Added tool for viewing models and animations outside the game.
Atlas: Added ActorViewer. Moved GL canvas into separate class for shared
use. Disabled message-handling callback while blocked on the game, and
stopped creating dialog boxes inside the game thread in order to avoid
deadlocks (hopefully). Support multiple Views (for independent sets of
camera/update/render code). Recalculate territory boundaries when
necessary. Changed default list of animations to match those currently
used by actors.
# Tidied up more code.
Moved some more #includes out of .h files, to minimise unnecessary
compilation.
MathUtil: Deleted unused/unuseful macros (M_PI (use PI instead), M_PI_2
(use PI/2), MAX3, ABS (use abs)).
ObjectManager: Removed some ScEd-specific things.
Unit: Moved creation out of UnitManager, so units can be created without
adding to the manager. Changed CStr8 to the more conventional CStr.
app_hooks: Removed warning for setting multiple times.
win: Restored SEH catcher.
GameSetup, GameView: Removed RenderNoCull, because it doesn't seem to do
what it says it does ("force renderer to load everything") since we're
loading-on-demand most stuff and it doesn't seem especially useful since
we'd prefer to minimise loading times (but feel free to correct me if
I'm wrong). (And because it crashes when things need to be initialised
in a different order, so it's easier to remove than to understand and
fix it.)
PatchRData, Renderer: Work sensibly when there's no game (hence no LOS
manager, water, etc).
LOSManager: Use entity position instead of actor position when possible.
TerritoryManager: Allow delayed recalculations (so Atlas can issue lots
of move+recalculate commands per frame).
Cinematic: Non-pointer wxTimer, so it doesn't leak and doesn't have to
be deleted manually.
This was SVN commit r4261.
2006-08-28 19:36:42 +02:00
|
|
|
|
|
|
|
#include "graphics/Camera.h"
|
2007-02-10 04:09:52 +01:00
|
|
|
#include "graphics/CinemaTrack.h"
|
# Added tool for viewing models and animations outside the game.
Atlas: Added ActorViewer. Moved GL canvas into separate class for shared
use. Disabled message-handling callback while blocked on the game, and
stopped creating dialog boxes inside the game thread in order to avoid
deadlocks (hopefully). Support multiple Views (for independent sets of
camera/update/render code). Recalculate territory boundaries when
necessary. Changed default list of animations to match those currently
used by actors.
# Tidied up more code.
Moved some more #includes out of .h files, to minimise unnecessary
compilation.
MathUtil: Deleted unused/unuseful macros (M_PI (use PI instead), M_PI_2
(use PI/2), MAX3, ABS (use abs)).
ObjectManager: Removed some ScEd-specific things.
Unit: Moved creation out of UnitManager, so units can be created without
adding to the manager. Changed CStr8 to the more conventional CStr.
app_hooks: Removed warning for setting multiple times.
win: Restored SEH catcher.
GameSetup, GameView: Removed RenderNoCull, because it doesn't seem to do
what it says it does ("force renderer to load everything") since we're
loading-on-demand most stuff and it doesn't seem especially useful since
we'd prefer to minimise loading times (but feel free to correct me if
I'm wrong). (And because it crashes when things need to be initialised
in a different order, so it's easier to remove than to understand and
fix it.)
PatchRData, Renderer: Work sensibly when there's no game (hence no LOS
manager, water, etc).
LOSManager: Use entity position instead of actor position when possible.
TerritoryManager: Allow delayed recalculations (so Atlas can issue lots
of move+recalculate commands per frame).
Cinematic: Non-pointer wxTimer, so it doesn't leak and doesn't have to
be deleted manually.
This was SVN commit r4261.
2006-08-28 19:36:42 +02:00
|
|
|
#include "graphics/GameView.h"
|
|
|
|
#include "graphics/Model.h"
|
|
|
|
#include "graphics/ObjectManager.h"
|
|
|
|
#include "graphics/Patch.h"
|
|
|
|
#include "graphics/Terrain.h"
|
|
|
|
#include "graphics/TextureEntry.h"
|
|
|
|
#include "graphics/TextureManager.h"
|
|
|
|
#include "graphics/Unit.h"
|
|
|
|
#include "graphics/UnitManager.h"
|
|
|
|
#include "lib/timer.h"
|
|
|
|
#include "maths/MathUtil.h"
|
|
|
|
#include "ps/CLogger.h"
|
2006-06-02 04:10:27 +02:00
|
|
|
#include "ps/Game.h"
|
# Added tool for viewing models and animations outside the game.
Atlas: Added ActorViewer. Moved GL canvas into separate class for shared
use. Disabled message-handling callback while blocked on the game, and
stopped creating dialog boxes inside the game thread in order to avoid
deadlocks (hopefully). Support multiple Views (for independent sets of
camera/update/render code). Recalculate territory boundaries when
necessary. Changed default list of animations to match those currently
used by actors.
# Tidied up more code.
Moved some more #includes out of .h files, to minimise unnecessary
compilation.
MathUtil: Deleted unused/unuseful macros (M_PI (use PI instead), M_PI_2
(use PI/2), MAX3, ABS (use abs)).
ObjectManager: Removed some ScEd-specific things.
Unit: Moved creation out of UnitManager, so units can be created without
adding to the manager. Changed CStr8 to the more conventional CStr.
app_hooks: Removed warning for setting multiple times.
win: Restored SEH catcher.
GameSetup, GameView: Removed RenderNoCull, because it doesn't seem to do
what it says it does ("force renderer to load everything") since we're
loading-on-demand most stuff and it doesn't seem especially useful since
we'd prefer to minimise loading times (but feel free to correct me if
I'm wrong). (And because it crashes when things need to be initialised
in a different order, so it's easier to remove than to understand and
fix it.)
PatchRData, Renderer: Work sensibly when there's no game (hence no LOS
manager, water, etc).
LOSManager: Use entity position instead of actor position when possible.
TerritoryManager: Allow delayed recalculations (so Atlas can issue lots
of move+recalculate commands per frame).
Cinematic: Non-pointer wxTimer, so it doesn't leak and doesn't have to
be deleted manually.
This was SVN commit r4261.
2006-08-28 19:36:42 +02:00
|
|
|
#include "ps/Loader.h"
|
|
|
|
#include "ps/LoaderThunks.h"
|
2006-09-15 01:03:16 +02:00
|
|
|
#include "ps/XML/Xeromyces.h"
|
# Added tool for viewing models and animations outside the game.
Atlas: Added ActorViewer. Moved GL canvas into separate class for shared
use. Disabled message-handling callback while blocked on the game, and
stopped creating dialog boxes inside the game thread in order to avoid
deadlocks (hopefully). Support multiple Views (for independent sets of
camera/update/render code). Recalculate territory boundaries when
necessary. Changed default list of animations to match those currently
used by actors.
# Tidied up more code.
Moved some more #includes out of .h files, to minimise unnecessary
compilation.
MathUtil: Deleted unused/unuseful macros (M_PI (use PI instead), M_PI_2
(use PI/2), MAX3, ABS (use abs)).
ObjectManager: Removed some ScEd-specific things.
Unit: Moved creation out of UnitManager, so units can be created without
adding to the manager. Changed CStr8 to the more conventional CStr.
app_hooks: Removed warning for setting multiple times.
win: Restored SEH catcher.
GameSetup, GameView: Removed RenderNoCull, because it doesn't seem to do
what it says it does ("force renderer to load everything") since we're
loading-on-demand most stuff and it doesn't seem especially useful since
we'd prefer to minimise loading times (but feel free to correct me if
I'm wrong). (And because it crashes when things need to be initialised
in a different order, so it's easier to remove than to understand and
fix it.)
PatchRData, Renderer: Work sensibly when there's no game (hence no LOS
manager, water, etc).
LOSManager: Use entity position instead of actor position when possible.
TerritoryManager: Allow delayed recalculations (so Atlas can issue lots
of move+recalculate commands per frame).
Cinematic: Non-pointer wxTimer, so it doesn't leak and doesn't have to
be deleted manually.
This was SVN commit r4261.
2006-08-28 19:36:42 +02:00
|
|
|
#include "renderer/SkyManager.h"
|
|
|
|
#include "renderer/WaterManager.h"
|
2006-06-09 18:44:16 +02:00
|
|
|
#include "simulation/Entity.h"
|
# Added tool for viewing models and animations outside the game.
Atlas: Added ActorViewer. Moved GL canvas into separate class for shared
use. Disabled message-handling callback while blocked on the game, and
stopped creating dialog boxes inside the game thread in order to avoid
deadlocks (hopefully). Support multiple Views (for independent sets of
camera/update/render code). Recalculate territory boundaries when
necessary. Changed default list of animations to match those currently
used by actors.
# Tidied up more code.
Moved some more #includes out of .h files, to minimise unnecessary
compilation.
MathUtil: Deleted unused/unuseful macros (M_PI (use PI instead), M_PI_2
(use PI/2), MAX3, ABS (use abs)).
ObjectManager: Removed some ScEd-specific things.
Unit: Moved creation out of UnitManager, so units can be created without
adding to the manager. Changed CStr8 to the more conventional CStr.
app_hooks: Removed warning for setting multiple times.
win: Restored SEH catcher.
GameSetup, GameView: Removed RenderNoCull, because it doesn't seem to do
what it says it does ("force renderer to load everything") since we're
loading-on-demand most stuff and it doesn't seem especially useful since
we'd prefer to minimise loading times (but feel free to correct me if
I'm wrong). (And because it crashes when things need to be initialised
in a different order, so it's easier to remove than to understand and
fix it.)
PatchRData, Renderer: Work sensibly when there's no game (hence no LOS
manager, water, etc).
LOSManager: Use entity position instead of actor position when possible.
TerritoryManager: Allow delayed recalculations (so Atlas can issue lots
of move+recalculate commands per frame).
Cinematic: Non-pointer wxTimer, so it doesn't leak and doesn't have to
be deleted manually.
This was SVN commit r4261.
2006-08-28 19:36:42 +02:00
|
|
|
#include "simulation/EntityManager.h"
|
2006-11-24 20:45:04 +01:00
|
|
|
#include "simulation/TriggerManager.h"
|
2006-07-13 05:29:33 +02:00
|
|
|
#include "simulation/EntityTemplate.h"
|
|
|
|
#include "simulation/EntityTemplateCollection.h"
|
2005-03-18 23:02:20 +01:00
|
|
|
|
2005-03-29 22:50:04 +02:00
|
|
|
#define LOG_CATEGORY "graphics"
|
|
|
|
|
2004-05-29 22:56:24 +02:00
|
|
|
CMapReader::CMapReader()
|
2005-05-03 23:42:09 +02:00
|
|
|
: xml_reader(0)
|
2004-05-29 22:56:24 +02:00
|
|
|
{
|
2005-05-05 01:12:46 +02:00
|
|
|
cur_terrain_tex = 0; // important - resets generator state
|
2004-05-29 22:56:24 +02:00
|
|
|
}
|
|
|
|
|
2005-03-22 22:00:56 +01:00
|
|
|
|
2004-05-29 22:56:24 +02:00
|
|
|
// LoadMap: try to load the map from given file; reinitialise the scene to new data if successful
|
2006-06-22 00:37:31 +02:00
|
|
|
void CMapReader::LoadMap(const char* filename, CTerrain *pTerrain_,
|
|
|
|
CUnitManager *pUnitMan_, WaterManager* pWaterMan_, SkyManager* pSkyMan_,
|
2006-08-22 04:24:44 +02:00
|
|
|
CLightEnv *pLightEnv_, CCamera *pCamera_, CCinemaManager* pCinema_)
|
2004-05-29 22:56:24 +02:00
|
|
|
{
|
2005-03-22 22:00:56 +01:00
|
|
|
// latch parameters (held until DelayedLoadFinished)
|
|
|
|
pTerrain = pTerrain_;
|
|
|
|
pUnitMan = pUnitMan_;
|
|
|
|
pLightEnv = pLightEnv_;
|
2006-03-21 21:55:45 +01:00
|
|
|
pCamera = pCamera_;
|
2006-06-11 09:03:59 +02:00
|
|
|
pWaterMan = pWaterMan_;
|
2006-06-22 00:37:31 +02:00
|
|
|
pSkyMan = pSkyMan_;
|
2006-08-22 04:24:44 +02:00
|
|
|
pCinema = pCinema_;
|
2005-03-18 23:02:20 +01:00
|
|
|
|
2005-03-22 22:00:56 +01:00
|
|
|
// [25ms]
|
2006-06-11 09:03:59 +02:00
|
|
|
unpacker.Read(filename, "PSMP");
|
2004-05-29 22:56:24 +02:00
|
|
|
|
2006-02-15 01:45:16 +01:00
|
|
|
// check version
|
2005-05-11 05:07:08 +02:00
|
|
|
if (unpacker.GetVersion() < FILE_READ_VERSION) {
|
2006-04-04 06:14:10 +02:00
|
|
|
throw PSERROR_File_InvalidVersion();
|
2004-05-29 22:56:24 +02:00
|
|
|
}
|
|
|
|
|
2005-05-11 05:07:08 +02:00
|
|
|
// delete all existing entities
|
2007-05-02 14:07:08 +02:00
|
|
|
g_EntityManager.DeleteAll();
|
2005-05-11 05:07:08 +02:00
|
|
|
// delete all remaining non-entity units
|
|
|
|
pUnitMan->DeleteAll();
|
2007-01-08 02:56:46 +01:00
|
|
|
pUnitMan->SetNextID(0);
|
2005-05-11 05:07:08 +02:00
|
|
|
|
2004-05-29 22:56:24 +02:00
|
|
|
// unpack the data
|
2006-03-18 22:25:03 +01:00
|
|
|
RegMemFun(this, &CMapReader::UnpackMap, L"CMapReader::UnpackMap", 1200);
|
2004-05-29 22:56:24 +02:00
|
|
|
|
2005-05-11 05:07:08 +02:00
|
|
|
if (unpacker.GetVersion() >= 3) {
|
2005-01-12 15:31:47 +01:00
|
|
|
// read the corresponding XML file
|
2005-03-22 22:00:56 +01:00
|
|
|
filename_xml = filename;
|
2007-02-01 15:46:14 +01:00
|
|
|
filename_xml = filename_xml.Left(filename_xml.length()-4) + ".xml";
|
2006-03-18 22:25:03 +01:00
|
|
|
RegMemFun(this, &CMapReader::ReadXML, L"CMapReader::ReadXML", 5800);
|
2005-01-12 15:31:47 +01:00
|
|
|
}
|
2005-03-22 22:00:56 +01:00
|
|
|
|
2005-05-11 05:07:08 +02:00
|
|
|
// apply data to the world
|
2005-09-21 18:42:56 +02:00
|
|
|
RegMemFun(this, &CMapReader::ApplyData, L"CMapReader::ApplyData", 5);
|
2005-05-11 05:07:08 +02:00
|
|
|
|
2005-05-03 23:42:09 +02:00
|
|
|
RegMemFun(this, &CMapReader::DelayLoadFinished, L"CMapReader::DelayLoadFinished", 5);
|
2004-05-29 22:56:24 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// UnpackMap: unpack the given data from the raw data stream into local variables
|
2005-05-03 23:42:09 +02:00
|
|
|
int CMapReader::UnpackMap()
|
2004-05-29 22:56:24 +02:00
|
|
|
{
|
|
|
|
// now unpack everything into local data
|
2005-05-05 01:12:46 +02:00
|
|
|
int ret = UnpackTerrain();
|
|
|
|
if(ret != 0) // failed or timed out
|
|
|
|
return ret;
|
|
|
|
|
2005-05-11 05:07:08 +02:00
|
|
|
if (unpacker.GetVersion() < 4)
|
|
|
|
UnpackObjects();
|
|
|
|
|
|
|
|
if (unpacker.GetVersion() >= 2 && unpacker.GetVersion() < 4)
|
2005-03-22 22:00:56 +01:00
|
|
|
UnpackLightEnv();
|
2005-05-03 23:42:09 +02:00
|
|
|
|
|
|
|
return 0;
|
2004-05-29 22:56:24 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// UnpackLightEnv: unpack lighting parameters from input stream
|
2005-03-22 22:00:56 +01:00
|
|
|
void CMapReader::UnpackLightEnv()
|
2004-05-29 22:56:24 +02:00
|
|
|
{
|
2005-05-11 05:07:08 +02:00
|
|
|
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();
|
2004-05-29 22:56:24 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// UnpackObjects: unpack world objects from input stream
|
2005-03-22 22:00:56 +01:00
|
|
|
void CMapReader::UnpackObjects()
|
2004-05-29 22:56:24 +02:00
|
|
|
{
|
|
|
|
// unpack object types
|
|
|
|
u32 numObjTypes;
|
2005-05-11 05:07:08 +02:00
|
|
|
unpacker.UnpackRaw(&numObjTypes, sizeof(numObjTypes));
|
2004-05-29 22:56:24 +02:00
|
|
|
m_ObjectTypes.resize(numObjTypes);
|
2005-05-11 05:07:08 +02:00
|
|
|
for (u32 i=0; i<numObjTypes; i++) {
|
2005-03-19 12:55:27 +01:00
|
|
|
unpacker.UnpackString(m_ObjectTypes[i]);
|
2004-05-29 22:56:24 +02:00
|
|
|
}
|
2005-07-30 22:12:41 +02:00
|
|
|
|
2004-05-29 22:56:24 +02:00
|
|
|
// unpack object data
|
|
|
|
u32 numObjects;
|
2005-05-11 05:07:08 +02:00
|
|
|
unpacker.UnpackRaw(&numObjects, sizeof(numObjects));
|
2004-05-29 22:56:24 +02:00
|
|
|
m_Objects.resize(numObjects);
|
2005-07-02 23:42:55 +02:00
|
|
|
if (numObjects)
|
|
|
|
unpacker.UnpackRaw(&m_Objects[0], sizeof(SObjectDesc)*numObjects);
|
2004-05-29 22:56:24 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// UnpackTerrain: unpack the terrain from the end of the input data stream
|
|
|
|
// - data: map size, heightmap, list of textures used by map, texture tile assignments
|
2005-05-05 01:12:46 +02:00
|
|
|
int CMapReader::UnpackTerrain()
|
2004-05-29 22:56:24 +02:00
|
|
|
{
|
2005-10-21 20:01:21 +02:00
|
|
|
// yield after this time is reached. balances increased progress bar
|
|
|
|
// smoothness vs. slowing down loading.
|
2008-01-07 21:03:19 +01:00
|
|
|
const double end_time = timer_Time() + 200e-3;
|
2005-05-05 01:12:46 +02:00
|
|
|
|
|
|
|
// first call to generator (this is skipped after first call,
|
|
|
|
// i.e. when the loop below was interrupted)
|
2005-05-11 05:07:08 +02:00
|
|
|
if (cur_terrain_tex == 0)
|
2005-05-05 01:12:46 +02:00
|
|
|
{
|
|
|
|
// unpack map size
|
2005-05-11 05:07:08 +02:00
|
|
|
unpacker.UnpackRaw(&m_MapSize, sizeof(m_MapSize));
|
2005-05-05 01:12:46 +02:00
|
|
|
|
2005-10-07 23:09:29 +02:00
|
|
|
// unpack heightmap [600us]
|
2005-05-11 05:07:08 +02:00
|
|
|
u32 verticesPerSide = m_MapSize*PATCH_SIZE+1;
|
2005-05-05 01:12:46 +02:00
|
|
|
m_Heightmap.resize(SQR(verticesPerSide));
|
2005-05-11 05:07:08 +02:00
|
|
|
unpacker.UnpackRaw(&m_Heightmap[0], SQR(verticesPerSide)*sizeof(u16));
|
2004-05-29 22:56:24 +02:00
|
|
|
|
2005-05-05 01:12:46 +02:00
|
|
|
// unpack # textures
|
|
|
|
unpacker.UnpackRaw(&num_terrain_tex, sizeof(num_terrain_tex));
|
|
|
|
m_TerrainTextures.reserve(num_terrain_tex);
|
|
|
|
}
|
|
|
|
|
|
|
|
// unpack texture names; find handle for each texture.
|
|
|
|
// interruptible.
|
2005-05-11 05:07:08 +02:00
|
|
|
while (cur_terrain_tex < num_terrain_tex)
|
2005-05-05 01:12:46 +02:00
|
|
|
{
|
2004-05-29 22:56:24 +02:00
|
|
|
CStr texturename;
|
|
|
|
unpacker.UnpackString(texturename);
|
|
|
|
|
|
|
|
Handle handle;
|
2005-05-05 01:12:46 +02:00
|
|
|
CTextureEntry* texentry = g_TexMan.FindTexture(texturename);
|
|
|
|
// mismatch between texture datasets?
|
|
|
|
if (!texentry)
|
|
|
|
handle = 0;
|
|
|
|
else
|
|
|
|
handle = texentry->GetHandle();
|
2004-05-29 22:56:24 +02:00
|
|
|
m_TerrainTextures.push_back(handle);
|
2005-05-05 01:12:46 +02:00
|
|
|
|
|
|
|
cur_terrain_tex++;
|
|
|
|
LDR_CHECK_TIMEOUT(cur_terrain_tex, num_terrain_tex);
|
2004-05-29 22:56:24 +02:00
|
|
|
}
|
2005-05-05 01:12:46 +02:00
|
|
|
|
|
|
|
// unpack tile data [3ms]
|
|
|
|
u32 tilesPerSide = m_MapSize*PATCH_SIZE;
|
2004-05-29 22:56:24 +02:00
|
|
|
m_Tiles.resize(SQR(tilesPerSide));
|
2005-05-11 05:07:08 +02:00
|
|
|
unpacker.UnpackRaw(&m_Tiles[0], (u32)(sizeof(STileDesc)*m_Tiles.size()));
|
2005-05-05 01:12:46 +02:00
|
|
|
|
|
|
|
// reset generator state.
|
|
|
|
cur_terrain_tex = 0;
|
|
|
|
|
|
|
|
return 0;
|
2004-05-29 22:56:24 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// ApplyData: take all the input data, and rebuild the scene from it
|
2005-05-03 23:42:09 +02:00
|
|
|
int CMapReader::ApplyData()
|
2004-05-29 22:56:24 +02:00
|
|
|
{
|
2006-02-15 01:45:16 +01:00
|
|
|
// initialise the terrain
|
|
|
|
pTerrain->Initialize(m_MapSize, &m_Heightmap[0]);
|
2006-05-04 06:14:48 +02:00
|
|
|
|
2004-05-29 22:56:24 +02:00
|
|
|
// setup the textures on the minipatches
|
2005-05-11 05:07:08 +02:00
|
|
|
STileDesc* tileptr = &m_Tiles[0];
|
|
|
|
for (u32 j=0; j<m_MapSize; j++) {
|
|
|
|
for (u32 i=0; i<m_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++) {
|
2005-05-11 05:07:08 +02:00
|
|
|
CMiniPatch& mp = pTerrain->GetPatch(i,j)->m_MiniPatches[m][k];
|
2005-07-30 22:12:41 +02:00
|
|
|
|
2005-05-11 05:07:08 +02:00
|
|
|
mp.Tex1 = m_TerrainTextures[tileptr->m_Tex1Index];
|
|
|
|
mp.Tex1Priority = tileptr->m_Priority;
|
2004-05-29 22:56:24 +02:00
|
|
|
|
|
|
|
tileptr++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// add new objects
|
2005-05-11 05:07:08 +02:00
|
|
|
for (size_t i = 0; i < m_Objects.size(); ++i)
|
|
|
|
{
|
2005-01-12 15:31:47 +01:00
|
|
|
|
2005-05-11 05:07:08 +02:00
|
|
|
if (unpacker.GetVersion() < 3)
|
|
|
|
{
|
2005-03-29 22:50:04 +02:00
|
|
|
debug_warn("Old unsupported map version - objects will be missing");
|
2007-05-02 14:07:08 +02:00
|
|
|
// (GetTemplateByActor doesn't work, since entity templates are now
|
2005-03-29 22:50:04 +02:00
|
|
|
// loaded on demand)
|
2005-03-30 18:14:19 +02:00
|
|
|
}
|
|
|
|
|
2007-01-17 04:25:20 +01:00
|
|
|
std::set<CStr> selections; // TODO: read from file
|
2007-01-08 02:56:46 +01:00
|
|
|
CUnit* unit = pUnitMan->CreateUnit(m_ObjectTypes.at(m_Objects[i].m_ObjectIndex), NULL, selections);
|
2005-03-19 12:55:27 +01:00
|
|
|
|
|
|
|
if (unit)
|
|
|
|
{
|
2005-01-12 15:31:47 +01:00
|
|
|
CMatrix3D transform;
|
2007-04-25 20:19:35 +02:00
|
|
|
cpu_memcpy(&transform._11, m_Objects[i].m_Transform, sizeof(float)*16);
|
2005-01-12 15:31:47 +01:00
|
|
|
unit->GetModel()->SetTransform(transform);
|
2004-05-29 22:56:24 +02:00
|
|
|
}
|
|
|
|
}
|
2006-05-04 06:14:48 +02:00
|
|
|
//Make units start out conforming correctly
|
2007-05-02 14:07:08 +02:00
|
|
|
g_EntityManager.ConformAll();
|
2004-05-29 22:56:24 +02:00
|
|
|
|
2005-05-11 05:07:08 +02:00
|
|
|
if (unpacker.GetVersion() >= 2)
|
|
|
|
{
|
2004-05-29 22:56:24 +02:00
|
|
|
// copy over the lighting parameters
|
2005-05-11 05:07:08 +02:00
|
|
|
*pLightEnv = m_LightEnv;
|
2004-05-29 22:56:24 +02:00
|
|
|
}
|
2005-05-03 23:42:09 +02:00
|
|
|
return 0;
|
2004-05-29 22:56:24 +02:00
|
|
|
}
|
2005-01-12 15:31:47 +01:00
|
|
|
|
|
|
|
|
2005-05-03 23:42:09 +02:00
|
|
|
|
2005-05-11 05:07:08 +02:00
|
|
|
// Holds various state data while reading maps, so that loading can be
|
|
|
|
// interrupted (e.g. to update the progress display) then later resumed.
|
2007-02-01 02:34:17 +01:00
|
|
|
class CXMLReader : boost::noncopyable
|
2005-01-12 15:31:47 +01:00
|
|
|
{
|
2005-05-03 23:42:09 +02:00
|
|
|
public:
|
2005-05-11 05:07:08 +02:00
|
|
|
CXMLReader(const CStr& xml_filename, CMapReader& mapReader)
|
|
|
|
: m_MapReader(mapReader)
|
2005-05-03 23:42:09 +02:00
|
|
|
{
|
|
|
|
Init(xml_filename);
|
|
|
|
}
|
|
|
|
|
|
|
|
// return semantics: see Loader.cpp!LoadFunc.
|
|
|
|
int ProgressiveRead();
|
|
|
|
|
|
|
|
private:
|
|
|
|
CXeromyces xmb_file;
|
|
|
|
|
2005-05-11 05:07:08 +02:00
|
|
|
CMapReader& m_MapReader;
|
|
|
|
|
2005-12-09 02:08:08 +01:00
|
|
|
int el_entity;
|
2006-08-22 04:24:44 +02:00
|
|
|
int el_tracks;
|
2005-05-03 23:42:09 +02:00
|
|
|
int el_template, el_player;
|
|
|
|
int el_position, el_orientation;
|
2005-12-09 02:08:08 +01:00
|
|
|
int el_nonentity;
|
2005-05-03 23:42:09 +02:00
|
|
|
int el_actor;
|
|
|
|
int at_x, at_y, at_z;
|
2007-01-17 00:22:25 +01:00
|
|
|
int at_id;
|
2005-05-03 23:42:09 +02:00
|
|
|
int at_angle;
|
2007-01-17 04:25:20 +01:00
|
|
|
int at_uid;
|
2005-05-03 23:42:09 +02:00
|
|
|
|
2005-05-11 05:07:08 +02:00
|
|
|
XMBElementList nodes; // children of root
|
2005-05-03 23:42:09 +02:00
|
|
|
|
|
|
|
// 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);
|
2005-05-11 05:07:08 +02:00
|
|
|
|
|
|
|
void ReadEnvironment(XMBElement parent);
|
2006-03-21 21:55:45 +01:00
|
|
|
void ReadCamera(XMBElement parent);
|
2006-08-22 04:24:44 +02:00
|
|
|
void ReadCinema(XMBElement parent);
|
2006-11-24 20:45:04 +01:00
|
|
|
void ReadTriggers(XMBElement parent);
|
|
|
|
void ReadTriggerGroup(XMBElement parent, MapTriggerGroup& group);
|
2005-05-11 05:07:08 +02:00
|
|
|
int ReadEntities(XMBElement parent, double end_time);
|
|
|
|
int ReadNonEntities(XMBElement parent, double end_time);
|
2005-05-03 23:42:09 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
void CXMLReader::Init(const CStr& xml_filename)
|
|
|
|
{
|
|
|
|
// must only assign once, so do it here
|
|
|
|
node_idx = entity_idx = nonentity_idx = 0;
|
|
|
|
|
|
|
|
if (xmb_file.Load(xml_filename) != PSRETURN_OK)
|
2006-04-04 06:14:10 +02:00
|
|
|
throw PSERROR_File_ReadFailed();
|
2005-01-12 15:31:47 +01:00
|
|
|
|
2005-12-09 02:08:08 +01:00
|
|
|
// define the elements and attributes that are frequently used in the XML file,
|
|
|
|
// so we don't need to do lots of string construction and comparison when
|
|
|
|
// reading the data.
|
2005-05-11 05:07:08 +02:00
|
|
|
// (Needs to be synchronised with the list in CXMLReader - ugh)
|
2007-05-02 14:07:08 +02:00
|
|
|
#define EL(x) el_##x = xmb_file.GetElementID(#x)
|
|
|
|
#define AT(x) at_##x = xmb_file.GetAttributeID(#x)
|
2005-01-12 15:31:47 +01:00
|
|
|
EL(entity);
|
2006-08-22 04:24:44 +02:00
|
|
|
EL(tracks);
|
2005-01-12 15:31:47 +01:00
|
|
|
EL(template);
|
2005-01-17 00:09:41 +01:00
|
|
|
EL(player);
|
2005-01-12 15:31:47 +01:00
|
|
|
EL(position);
|
|
|
|
EL(orientation);
|
2005-03-29 22:50:04 +02:00
|
|
|
EL(nonentity);
|
|
|
|
EL(actor);
|
2005-05-11 05:07:08 +02:00
|
|
|
AT(x); AT(y); AT(z);
|
2005-01-12 15:31:47 +01:00
|
|
|
AT(angle);
|
2007-01-17 04:25:20 +01:00
|
|
|
AT(uid);
|
2005-01-12 15:31:47 +01:00
|
|
|
#undef AT
|
|
|
|
#undef EL
|
|
|
|
|
2007-05-02 14:07:08 +02:00
|
|
|
XMBElement root = xmb_file.GetRoot();
|
|
|
|
debug_assert(xmb_file.GetElementString(root.GetNodeName()) == "Scenario");
|
|
|
|
nodes = root.GetChildNodes();
|
2005-01-12 15:31:47 +01:00
|
|
|
|
2005-05-03 23:42:09 +02:00
|
|
|
// 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++)
|
2007-05-02 14:07:08 +02:00
|
|
|
total_jobs += nodes.Item(i).GetChildNodes().Count;
|
2005-05-03 23:42:09 +02:00
|
|
|
}
|
2005-01-12 15:31:47 +01:00
|
|
|
|
2005-05-03 23:42:09 +02:00
|
|
|
|
2005-05-11 05:07:08 +02:00
|
|
|
void CXMLReader::ReadEnvironment(XMBElement parent)
|
|
|
|
{
|
2007-05-02 14:07:08 +02:00
|
|
|
#define EL(x) int el_##x = xmb_file.GetElementID(#x)
|
|
|
|
#define AT(x) int at_##x = xmb_file.GetAttributeID(#x)
|
2006-06-22 00:37:31 +02:00
|
|
|
EL(skyset);
|
2005-12-09 02:08:08 +01:00
|
|
|
EL(suncolour);
|
|
|
|
EL(sunelevation);
|
|
|
|
EL(sunrotation);
|
|
|
|
EL(terrainambientcolour);
|
|
|
|
EL(unitsambientcolour);
|
2006-02-15 01:45:16 +01:00
|
|
|
EL(terrainshadowtransparency);
|
2006-06-11 09:03:59 +02:00
|
|
|
EL(water);
|
|
|
|
EL(waterbody);
|
|
|
|
EL(type);
|
|
|
|
EL(colour);
|
|
|
|
EL(height);
|
|
|
|
EL(shininess);
|
|
|
|
EL(waviness);
|
2006-09-18 20:09:07 +02:00
|
|
|
EL(murkiness);
|
|
|
|
EL(tint);
|
|
|
|
EL(reflectiontint);
|
|
|
|
EL(reflectiontintstrength);
|
2005-12-09 02:08:08 +01:00
|
|
|
AT(r); AT(g); AT(b);
|
|
|
|
#undef AT
|
|
|
|
#undef EL
|
|
|
|
|
2005-05-11 05:07:08 +02:00
|
|
|
XERO_ITER_EL(parent, element)
|
|
|
|
{
|
2007-05-02 14:07:08 +02:00
|
|
|
int element_name = element.GetNodeName();
|
2005-07-30 22:12:41 +02:00
|
|
|
|
2007-05-02 14:07:08 +02:00
|
|
|
XMBAttributeList attrs = element.GetAttributes();
|
2006-06-22 00:37:31 +02:00
|
|
|
|
|
|
|
if (element_name == el_skyset)
|
|
|
|
{
|
2007-05-02 14:07:08 +02:00
|
|
|
m_MapReader.pSkyMan->SetSkySet(element.GetText());
|
2006-06-22 00:37:31 +02:00
|
|
|
}
|
|
|
|
else if (element_name == el_suncolour)
|
2005-05-11 05:07:08 +02:00
|
|
|
{
|
|
|
|
m_MapReader.m_LightEnv.m_SunColor = RGBColor(
|
2007-05-02 14:07:08 +02:00
|
|
|
CStr(attrs.GetNamedItem(at_r)).ToFloat(),
|
|
|
|
CStr(attrs.GetNamedItem(at_g)).ToFloat(),
|
|
|
|
CStr(attrs.GetNamedItem(at_b)).ToFloat());
|
2005-05-11 05:07:08 +02:00
|
|
|
}
|
|
|
|
else if (element_name == el_sunelevation)
|
|
|
|
{
|
2007-05-02 14:07:08 +02:00
|
|
|
m_MapReader.m_LightEnv.m_Elevation = CStr(attrs.GetNamedItem(at_angle)).ToFloat();
|
2005-05-11 05:07:08 +02:00
|
|
|
}
|
|
|
|
else if (element_name == el_sunrotation)
|
|
|
|
{
|
2007-05-02 14:07:08 +02:00
|
|
|
m_MapReader.m_LightEnv.m_Rotation = CStr(attrs.GetNamedItem(at_angle)).ToFloat();
|
2005-05-11 05:07:08 +02:00
|
|
|
}
|
|
|
|
else if (element_name == el_terrainambientcolour)
|
|
|
|
{
|
|
|
|
m_MapReader.m_LightEnv.m_TerrainAmbientColor = RGBColor(
|
2007-05-02 14:07:08 +02:00
|
|
|
CStr(attrs.GetNamedItem(at_r)).ToFloat(),
|
|
|
|
CStr(attrs.GetNamedItem(at_g)).ToFloat(),
|
|
|
|
CStr(attrs.GetNamedItem(at_b)).ToFloat());
|
2005-05-11 05:07:08 +02:00
|
|
|
}
|
|
|
|
else if (element_name == el_unitsambientcolour)
|
|
|
|
{
|
|
|
|
m_MapReader.m_LightEnv.m_UnitsAmbientColor = RGBColor(
|
2007-05-02 14:07:08 +02:00
|
|
|
CStr(attrs.GetNamedItem(at_r)).ToFloat(),
|
|
|
|
CStr(attrs.GetNamedItem(at_g)).ToFloat(),
|
|
|
|
CStr(attrs.GetNamedItem(at_b)).ToFloat());
|
2005-05-11 05:07:08 +02:00
|
|
|
}
|
2006-02-15 01:45:16 +01:00
|
|
|
else if (element_name == el_terrainshadowtransparency)
|
|
|
|
{
|
2007-05-02 14:07:08 +02:00
|
|
|
m_MapReader.m_LightEnv.SetTerrainShadowTransparency(CStr(element.GetText()).ToFloat());
|
2006-02-15 01:45:16 +01:00
|
|
|
}
|
2006-06-11 09:03:59 +02:00
|
|
|
else if (element_name == el_water)
|
|
|
|
{
|
|
|
|
XERO_ITER_EL(element, waterbody)
|
|
|
|
{
|
2007-05-02 14:07:08 +02:00
|
|
|
debug_assert(waterbody.GetNodeName() == el_waterbody);
|
2006-06-11 09:03:59 +02:00
|
|
|
XERO_ITER_EL(waterbody, waterelement)
|
|
|
|
{
|
2007-05-02 14:07:08 +02:00
|
|
|
int element_name = waterelement.GetNodeName();
|
2006-06-11 09:03:59 +02:00
|
|
|
if (element_name == el_type)
|
|
|
|
{
|
|
|
|
// TODO: implement this, when WaterManager supports it
|
|
|
|
}
|
2006-09-18 20:09:07 +02:00
|
|
|
|
|
|
|
#define READ_COLOUR(el, out) \
|
|
|
|
else if (element_name == el) \
|
|
|
|
{ \
|
2007-05-02 14:07:08 +02:00
|
|
|
XMBAttributeList attrs = waterelement.GetAttributes(); \
|
2006-09-18 20:09:07 +02:00
|
|
|
out = CColor( \
|
2007-05-02 14:07:08 +02:00
|
|
|
CStr(attrs.GetNamedItem(at_r)).ToFloat(), \
|
|
|
|
CStr(attrs.GetNamedItem(at_g)).ToFloat(), \
|
|
|
|
CStr(attrs.GetNamedItem(at_b)).ToFloat(), \
|
2006-09-18 20:09:07 +02:00
|
|
|
1.f); \
|
2006-06-11 09:03:59 +02:00
|
|
|
}
|
2006-09-18 20:09:07 +02:00
|
|
|
|
|
|
|
#define READ_FLOAT(el, out) \
|
|
|
|
else if (element_name == el) \
|
|
|
|
{ \
|
2007-05-02 14:07:08 +02:00
|
|
|
out = CStr(waterelement.GetText()).ToFloat(); \
|
2006-09-18 20:09:07 +02:00
|
|
|
} \
|
|
|
|
|
|
|
|
READ_COLOUR(el_colour, m_MapReader.pWaterMan->m_WaterColor)
|
|
|
|
READ_FLOAT(el_height, m_MapReader.pWaterMan->m_WaterHeight)
|
|
|
|
READ_FLOAT(el_shininess, m_MapReader.pWaterMan->m_Shininess)
|
|
|
|
READ_FLOAT(el_waviness, m_MapReader.pWaterMan->m_Waviness)
|
|
|
|
READ_FLOAT(el_murkiness, m_MapReader.pWaterMan->m_Murkiness)
|
|
|
|
READ_COLOUR(el_tint, m_MapReader.pWaterMan->m_WaterTint)
|
|
|
|
READ_COLOUR(el_reflectiontint, m_MapReader.pWaterMan->m_ReflectionTint)
|
|
|
|
READ_FLOAT(el_reflectiontintstrength, m_MapReader.pWaterMan->m_ReflectionTintStrength)
|
|
|
|
|
|
|
|
#undef READ_FLOAT
|
|
|
|
#undef READ_COLOUR
|
|
|
|
|
2006-06-11 09:03:59 +02:00
|
|
|
else
|
|
|
|
debug_warn("Invalid map XML data");
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
2005-05-11 05:07:08 +02:00
|
|
|
else
|
2006-03-21 21:55:45 +01:00
|
|
|
debug_warn("Invalid map XML data");
|
2005-05-11 05:07:08 +02:00
|
|
|
}
|
2005-05-05 01:12:46 +02:00
|
|
|
|
2005-05-11 05:07:08 +02:00
|
|
|
m_MapReader.m_LightEnv.CalculateSunDirection();
|
|
|
|
}
|
2005-05-03 23:42:09 +02:00
|
|
|
|
2006-03-21 21:55:45 +01:00
|
|
|
void CXMLReader::ReadCamera(XMBElement parent)
|
|
|
|
{
|
2007-05-02 14:07:08 +02:00
|
|
|
#define EL(x) int el_##x = xmb_file.GetElementID(#x)
|
|
|
|
#define AT(x) int at_##x = xmb_file.GetAttributeID(#x)
|
2006-03-21 21:55:45 +01:00
|
|
|
EL(declination);
|
|
|
|
EL(rotation);
|
|
|
|
EL(position);
|
|
|
|
AT(angle);
|
|
|
|
AT(x); AT(y); AT(z);
|
|
|
|
#undef AT
|
|
|
|
#undef EL
|
|
|
|
|
|
|
|
float declination = DEGTORAD(30.f), rotation = DEGTORAD(-45.f);
|
|
|
|
CVector3D translation = CVector3D(100, 150, -100);
|
|
|
|
|
|
|
|
XERO_ITER_EL(parent, element)
|
|
|
|
{
|
2007-05-02 14:07:08 +02:00
|
|
|
int element_name = element.GetNodeName();
|
2006-03-21 21:55:45 +01:00
|
|
|
|
2007-05-02 14:07:08 +02:00
|
|
|
XMBAttributeList attrs = element.GetAttributes();
|
2006-03-21 21:55:45 +01:00
|
|
|
if (element_name == el_declination)
|
|
|
|
{
|
2007-05-02 14:07:08 +02:00
|
|
|
declination = CStr(attrs.GetNamedItem(at_angle)).ToFloat();
|
2006-03-21 21:55:45 +01:00
|
|
|
}
|
|
|
|
else if (element_name == el_rotation)
|
|
|
|
{
|
2007-05-02 14:07:08 +02:00
|
|
|
rotation = CStr(attrs.GetNamedItem(at_angle)).ToFloat();
|
2006-03-21 21:55:45 +01:00
|
|
|
}
|
|
|
|
else if (element_name == el_position)
|
|
|
|
{
|
|
|
|
translation = CVector3D(
|
2007-05-02 14:07:08 +02:00
|
|
|
CStr(attrs.GetNamedItem(at_x)).ToFloat(),
|
|
|
|
CStr(attrs.GetNamedItem(at_y)).ToFloat(),
|
|
|
|
CStr(attrs.GetNamedItem(at_z)).ToFloat());
|
2006-03-21 21:55:45 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
debug_warn("Invalid map XML data");
|
|
|
|
}
|
|
|
|
|
|
|
|
m_MapReader.pCamera->m_Orientation.SetXRotation(declination);
|
|
|
|
m_MapReader.pCamera->m_Orientation.RotateY(rotation);
|
|
|
|
m_MapReader.pCamera->m_Orientation.Translate(translation);
|
|
|
|
m_MapReader.pCamera->UpdateFrustum();
|
|
|
|
}
|
2006-09-28 04:05:56 +02:00
|
|
|
|
2006-08-22 04:24:44 +02:00
|
|
|
void CXMLReader::ReadCinema(XMBElement parent)
|
|
|
|
{
|
2007-05-02 14:07:08 +02:00
|
|
|
#define EL(x) int el_##x = xmb_file.GetElementID(#x)
|
|
|
|
#define AT(x) int at_##x = xmb_file.GetAttributeID(#x)
|
2006-08-22 04:24:44 +02:00
|
|
|
|
|
|
|
EL(path);
|
|
|
|
EL(rotation);
|
|
|
|
EL(distortion);
|
|
|
|
EL(node);
|
2007-02-27 03:14:18 +01:00
|
|
|
EL(position);
|
|
|
|
EL(time);
|
2006-08-22 04:24:44 +02:00
|
|
|
AT(name);
|
|
|
|
AT(timescale);
|
|
|
|
AT(mode);
|
|
|
|
AT(style);
|
|
|
|
AT(growth);
|
|
|
|
AT(switch);
|
|
|
|
AT(x);
|
|
|
|
AT(y);
|
|
|
|
AT(z);
|
|
|
|
|
|
|
|
#undef EL
|
|
|
|
#undef AT
|
|
|
|
|
2007-02-27 03:14:18 +01:00
|
|
|
std::map<CStrW, CCinemaPath> pathList;
|
2006-08-22 04:24:44 +02:00
|
|
|
XERO_ITER_EL(parent, element)
|
|
|
|
{
|
2007-05-02 14:07:08 +02:00
|
|
|
int elementName = element.GetNodeName();
|
2006-08-22 04:24:44 +02:00
|
|
|
|
2007-02-27 03:14:18 +01:00
|
|
|
if ( elementName == el_path )
|
2006-08-22 04:24:44 +02:00
|
|
|
{
|
2007-05-02 14:07:08 +02:00
|
|
|
XMBAttributeList attrs = element.GetAttributes();
|
|
|
|
CStrW name( CStr(attrs.GetNamedItem(at_name)) );
|
|
|
|
float timescale = CStr(attrs.GetNamedItem(at_timescale)).ToFloat();
|
2007-02-27 03:14:18 +01:00
|
|
|
CCinemaData pathData;
|
|
|
|
pathData.m_Timescale = timescale;
|
|
|
|
TNSpline spline, backwardSpline;
|
2006-08-22 04:24:44 +02:00
|
|
|
|
2007-02-27 03:14:18 +01:00
|
|
|
XERO_ITER_EL(element, pathChild)
|
2006-08-22 04:24:44 +02:00
|
|
|
{
|
2007-05-02 14:07:08 +02:00
|
|
|
elementName = pathChild.GetNodeName();
|
|
|
|
attrs = pathChild.GetAttributes();
|
2006-03-21 21:55:45 +01:00
|
|
|
|
2007-02-27 03:14:18 +01:00
|
|
|
//Load distortion attributes
|
|
|
|
if ( elementName == el_distortion )
|
2006-08-22 04:24:44 +02:00
|
|
|
{
|
2007-05-02 14:07:08 +02:00
|
|
|
pathData.m_Mode = CStr(attrs.GetNamedItem(at_mode)).ToInt();
|
|
|
|
pathData.m_Style = CStr(attrs.GetNamedItem(at_style)).ToInt();
|
|
|
|
pathData.m_Growth = CStr(attrs.GetNamedItem(at_growth)).ToInt();
|
|
|
|
pathData.m_Switch = CStr(attrs.GetNamedItem(at_switch)).ToInt();
|
2006-08-22 04:24:44 +02:00
|
|
|
}
|
2007-02-27 03:14:18 +01:00
|
|
|
|
|
|
|
//Load node data used for spline
|
|
|
|
else if ( elementName == el_node )
|
2006-08-22 04:24:44 +02:00
|
|
|
{
|
2007-02-27 03:14:18 +01:00
|
|
|
SplineData data;
|
|
|
|
XERO_ITER_EL(pathChild, nodeChild)
|
2006-08-22 04:24:44 +02:00
|
|
|
{
|
2007-05-02 14:07:08 +02:00
|
|
|
elementName = nodeChild.GetNodeName();
|
|
|
|
attrs = nodeChild.GetAttributes();
|
2007-02-27 03:14:18 +01:00
|
|
|
|
|
|
|
//Fix?: assumes that time is last element
|
|
|
|
if ( elementName == el_position )
|
2006-08-22 04:24:44 +02:00
|
|
|
{
|
2007-05-02 14:07:08 +02:00
|
|
|
data.Position.X = CStr(attrs.GetNamedItem(at_x)).ToFloat();
|
|
|
|
data.Position.Y = CStr(attrs.GetNamedItem(at_y)).ToFloat();
|
|
|
|
data.Position.Z = CStr(attrs.GetNamedItem(at_z)).ToFloat();
|
2007-02-27 03:14:18 +01:00
|
|
|
continue;
|
2006-08-22 04:24:44 +02:00
|
|
|
}
|
2007-02-27 03:14:18 +01:00
|
|
|
else if ( elementName == el_rotation )
|
|
|
|
{
|
2007-05-02 14:07:08 +02:00
|
|
|
data.Rotation.X = CStr(attrs.GetNamedItem(at_x)).ToFloat();
|
|
|
|
data.Rotation.Y = CStr(attrs.GetNamedItem(at_y)).ToFloat();
|
|
|
|
data.Rotation.Z = CStr(attrs.GetNamedItem(at_z)).ToFloat();
|
2007-02-27 03:14:18 +01:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else if ( elementName == el_time )
|
2007-05-02 14:07:08 +02:00
|
|
|
data.Distance = CStr( nodeChild.GetText() ).ToFloat();
|
2007-02-27 03:14:18 +01:00
|
|
|
else
|
|
|
|
debug_warn("Invalid cinematic element for node child");
|
2006-08-22 04:24:44 +02:00
|
|
|
|
2007-02-27 03:14:18 +01:00
|
|
|
backwardSpline.AddNode(data.Position, data.Rotation, data.Distance);
|
2006-08-22 04:24:44 +02:00
|
|
|
}
|
2007-02-27 03:14:18 +01:00
|
|
|
}
|
2006-08-22 04:24:44 +02:00
|
|
|
else
|
2007-02-27 03:14:18 +01:00
|
|
|
debug_warn("Invalid cinematic element for path child");
|
|
|
|
|
|
|
|
|
2006-08-22 04:24:44 +02:00
|
|
|
}
|
2007-02-27 03:14:18 +01:00
|
|
|
|
|
|
|
//Construct cinema path with data gathered
|
|
|
|
CCinemaPath temp(pathData, backwardSpline);
|
|
|
|
const std::vector<SplineData>& nodes = temp.GetAllNodes();
|
|
|
|
if ( nodes.empty() )
|
|
|
|
{
|
|
|
|
debug_warn("Failure loading cinematics");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
for ( std::vector<SplineData>::const_reverse_iterator it = nodes.rbegin();
|
|
|
|
it != nodes.rend(); ++it )
|
|
|
|
{
|
|
|
|
spline.AddNode(it->Position, it->Rotation, it->Distance);
|
|
|
|
}
|
|
|
|
|
|
|
|
CCinemaPath path(pathData, spline);
|
|
|
|
pathList[name] = path;
|
2006-08-22 04:24:44 +02:00
|
|
|
}
|
2007-02-27 03:14:18 +01:00
|
|
|
else
|
|
|
|
debug_assert("Invalid cinema child");
|
2006-08-22 04:24:44 +02:00
|
|
|
}
|
2007-02-27 03:14:18 +01:00
|
|
|
g_Game->GetView()->GetCinema()->SetAllPaths(pathList);
|
2006-08-22 04:24:44 +02:00
|
|
|
}
|
2005-05-03 23:42:09 +02:00
|
|
|
|
2006-11-24 20:45:04 +01:00
|
|
|
void CXMLReader::ReadTriggers(XMBElement parent)
|
|
|
|
{
|
|
|
|
MapTriggerGroup rootGroup( CStrW(L"Triggers"), CStrW(L"") );
|
|
|
|
g_TriggerManager.DestroyEngineTriggers();
|
|
|
|
ReadTriggerGroup(parent, rootGroup);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CXMLReader::ReadTriggerGroup(XMBElement parent, MapTriggerGroup& group)
|
|
|
|
{
|
2007-05-02 14:07:08 +02:00
|
|
|
#define EL(x) int el_##x = xmb_file.GetElementID(#x)
|
|
|
|
#define AT(x) int at_##x = xmb_file.GetAttributeID(#x)
|
2006-11-24 20:45:04 +01:00
|
|
|
|
|
|
|
EL(group);
|
|
|
|
EL(trigger);
|
|
|
|
EL(active);
|
|
|
|
EL(delay);
|
|
|
|
EL(maxruncount);
|
|
|
|
EL(conditions);
|
|
|
|
EL(logicblock);
|
|
|
|
EL(logicblockend);
|
|
|
|
EL(condition);
|
|
|
|
EL(parameter);
|
|
|
|
EL(linklogic);
|
|
|
|
EL(effects);
|
|
|
|
EL(effect);
|
2007-01-17 00:22:25 +01:00
|
|
|
EL(function);
|
|
|
|
EL(display);
|
2006-11-24 20:45:04 +01:00
|
|
|
|
|
|
|
AT(name);
|
2007-01-29 23:21:25 +01:00
|
|
|
AT(function);
|
|
|
|
AT(display);
|
2006-11-24 20:45:04 +01:00
|
|
|
AT(not);
|
|
|
|
|
|
|
|
#undef EL
|
|
|
|
#undef AT
|
|
|
|
|
2007-05-02 14:07:08 +02:00
|
|
|
CStrW name = parent.GetAttributes().GetNamedItem(at_name), parentName = group.parentName;
|
2006-11-24 20:45:04 +01:00
|
|
|
if ( group.name == L"Triggers" )
|
|
|
|
name = group.name;
|
|
|
|
|
|
|
|
MapTriggerGroup mapGroup(name, parentName);
|
|
|
|
|
|
|
|
XERO_ITER_EL(parent, groupChild)
|
|
|
|
{
|
2007-05-02 14:07:08 +02:00
|
|
|
int elementName = groupChild.GetNodeName();
|
2006-11-24 20:45:04 +01:00
|
|
|
if ( elementName == el_group )
|
|
|
|
ReadTriggerGroup(groupChild, mapGroup);
|
|
|
|
|
|
|
|
else if ( elementName == el_trigger )
|
|
|
|
{
|
|
|
|
MapTrigger mapTrigger;
|
2007-05-02 14:07:08 +02:00
|
|
|
mapTrigger.name = CStrW( groupChild.GetAttributes().GetNamedItem(at_name) );
|
2006-11-24 20:45:04 +01:00
|
|
|
|
|
|
|
//Read everything in this trigger
|
|
|
|
XERO_ITER_EL(groupChild, triggerChild)
|
|
|
|
{
|
2007-05-02 14:07:08 +02:00
|
|
|
elementName = triggerChild.GetNodeName();
|
2006-11-24 20:45:04 +01:00
|
|
|
if ( elementName == el_active )
|
|
|
|
{
|
2007-05-02 14:07:08 +02:00
|
|
|
if ( CStr("false") == CStr( triggerChild.GetText() ) )
|
2006-11-24 20:45:04 +01:00
|
|
|
mapTrigger.active = false;
|
|
|
|
else
|
|
|
|
mapTrigger.active = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
else if ( elementName == el_maxruncount )
|
2007-05-02 14:07:08 +02:00
|
|
|
mapTrigger.maxRunCount = CStr( triggerChild.GetText() ).ToInt();
|
2006-11-24 20:45:04 +01:00
|
|
|
else if ( elementName == el_delay )
|
2007-05-02 14:07:08 +02:00
|
|
|
mapTrigger.timeValue = CStr( triggerChild.GetText() ).ToFloat();
|
2006-11-24 20:45:04 +01:00
|
|
|
|
|
|
|
else if ( elementName == el_conditions )
|
|
|
|
{
|
|
|
|
//Read in all conditions for this trigger
|
|
|
|
XERO_ITER_EL(triggerChild, condition)
|
|
|
|
{
|
2007-05-02 14:07:08 +02:00
|
|
|
elementName = condition.GetNodeName();
|
2006-11-24 20:45:04 +01:00
|
|
|
if ( elementName == el_condition )
|
|
|
|
{
|
|
|
|
MapTriggerCondition mapCondition;
|
2007-05-02 14:07:08 +02:00
|
|
|
mapCondition.name = condition.GetAttributes().GetNamedItem(at_name);
|
|
|
|
mapCondition.functionName = condition.GetAttributes().GetNamedItem(at_function);
|
|
|
|
mapCondition.displayName = condition.GetAttributes().GetNamedItem(at_display);
|
2006-11-24 20:45:04 +01:00
|
|
|
|
2007-05-02 14:07:08 +02:00
|
|
|
CStr notAtt(condition.GetAttributes().GetNamedItem(at_not));
|
2006-11-24 20:45:04 +01:00
|
|
|
if ( notAtt == CStr("true") )
|
2006-11-30 00:37:10 +01:00
|
|
|
mapCondition.negated = true;
|
2006-11-24 20:45:04 +01:00
|
|
|
|
|
|
|
//Read in each condition child
|
|
|
|
XERO_ITER_EL(condition, conditionChild)
|
|
|
|
{
|
2007-05-02 14:07:08 +02:00
|
|
|
elementName = conditionChild.GetNodeName();
|
2006-11-24 20:45:04 +01:00
|
|
|
|
2007-01-17 00:22:25 +01:00
|
|
|
if ( elementName == el_function )
|
2007-05-02 14:07:08 +02:00
|
|
|
mapCondition.functionName = CStrW(conditionChild.GetText());
|
2007-01-17 00:22:25 +01:00
|
|
|
else if ( elementName == el_display )
|
2007-05-02 14:07:08 +02:00
|
|
|
mapCondition.displayName = CStrW(conditionChild.GetText());
|
2007-01-17 00:22:25 +01:00
|
|
|
else if ( elementName == el_parameter )
|
2007-05-02 14:07:08 +02:00
|
|
|
mapCondition.parameters.push_back( conditionChild.GetText() );
|
2006-11-24 20:45:04 +01:00
|
|
|
else if ( elementName == el_linklogic )
|
|
|
|
{
|
2007-05-02 14:07:08 +02:00
|
|
|
CStr logic = conditionChild.GetText();
|
2006-11-24 20:45:04 +01:00
|
|
|
if ( logic == CStr("AND") )
|
|
|
|
mapCondition.linkLogic = 1;
|
|
|
|
else
|
|
|
|
mapCondition.linkLogic = 2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
mapTrigger.conditions.push_back(mapCondition);
|
|
|
|
} //Read all conditions
|
|
|
|
|
|
|
|
else if ( elementName == el_logicblock)
|
|
|
|
{
|
2007-05-02 14:07:08 +02:00
|
|
|
if ( CStr(condition.GetAttributes().GetNamedItem(at_not)) == CStr("true") )
|
2006-11-24 20:45:04 +01:00
|
|
|
mapTrigger.AddLogicBlock(true);
|
|
|
|
else
|
|
|
|
mapTrigger.AddLogicBlock(false);
|
|
|
|
}
|
|
|
|
else if ( elementName == el_logicblockend)
|
|
|
|
mapTrigger.AddLogicBlockEnd();
|
|
|
|
|
|
|
|
} //Read all conditions
|
|
|
|
}
|
|
|
|
|
|
|
|
else if ( elementName == el_effects )
|
|
|
|
{
|
|
|
|
//Read all effects
|
|
|
|
XERO_ITER_EL(triggerChild, effect)
|
|
|
|
{
|
2007-05-02 14:07:08 +02:00
|
|
|
if ( effect.GetNodeName() != el_effect )
|
2006-11-24 20:45:04 +01:00
|
|
|
{
|
|
|
|
debug_warn("Invalid effect tag in trigger XML file");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
MapTriggerEffect mapEffect;
|
2007-05-02 14:07:08 +02:00
|
|
|
mapEffect.name = effect.GetAttributes().GetNamedItem(at_name);
|
2006-11-24 20:45:04 +01:00
|
|
|
|
|
|
|
//Read parameters
|
|
|
|
XERO_ITER_EL(effect, effectChild)
|
|
|
|
{
|
2007-05-02 14:07:08 +02:00
|
|
|
elementName = effectChild.GetNodeName();
|
2007-01-17 00:22:25 +01:00
|
|
|
if ( elementName == el_function )
|
2007-05-02 14:07:08 +02:00
|
|
|
mapEffect.functionName = effectChild.GetText();
|
2007-01-17 00:22:25 +01:00
|
|
|
else if ( elementName == el_display )
|
2007-05-02 14:07:08 +02:00
|
|
|
mapEffect.displayName = effectChild.GetText();
|
2007-01-17 00:22:25 +01:00
|
|
|
else if ( elementName == el_parameter )
|
2007-05-02 14:07:08 +02:00
|
|
|
mapEffect.parameters.push_back( effectChild.GetText() );
|
2007-01-17 00:22:25 +01:00
|
|
|
else
|
2006-11-24 20:45:04 +01:00
|
|
|
{
|
|
|
|
debug_warn("Invalid parameter tag in trigger XML file");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
mapTrigger.effects.push_back(mapEffect);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
debug_warn("Invalid trigger node child in trigger XML file");
|
|
|
|
|
|
|
|
} //Read trigger children
|
|
|
|
g_TriggerManager.AddTrigger(mapGroup, mapTrigger);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
debug_warn("Invalid group node child in XML file");
|
|
|
|
} //Read group children
|
|
|
|
|
|
|
|
g_TriggerManager.AddGroup(mapGroup);
|
|
|
|
}
|
|
|
|
|
2005-05-11 05:07:08 +02:00
|
|
|
int CXMLReader::ReadEntities(XMBElement parent, double end_time)
|
2005-05-03 23:42:09 +02:00
|
|
|
{
|
2007-05-02 14:07:08 +02:00
|
|
|
XMBElementList entities = parent.GetChildNodes();
|
2007-01-17 04:25:20 +01:00
|
|
|
|
|
|
|
// If this is the first time in ReadEntities, find the next free ID number
|
|
|
|
// in case we need to allocate new ones in the future
|
|
|
|
if (entity_idx == 0)
|
2007-01-17 00:22:25 +01:00
|
|
|
{
|
2007-01-17 04:25:20 +01:00
|
|
|
int maxUnitID = -1;
|
2007-01-17 00:22:25 +01:00
|
|
|
|
2007-01-17 04:25:20 +01:00
|
|
|
XERO_ITER_EL(parent, entity)
|
|
|
|
{
|
2007-05-02 14:07:08 +02:00
|
|
|
debug_assert(entity.GetNodeName() == el_entity);
|
2007-01-17 04:25:20 +01:00
|
|
|
|
2007-05-02 14:07:08 +02:00
|
|
|
XMBAttributeList attrs = entity.GetAttributes();
|
|
|
|
utf16string uid = attrs.GetNamedItem(at_uid);
|
2007-01-29 23:21:25 +01:00
|
|
|
int unitId = uid.empty() ? -1 : CStr(uid).ToInt();
|
|
|
|
maxUnitID = std::max(maxUnitID, unitId);
|
2007-01-17 04:25:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
m_MapReader.pUnitMan->SetNextID(maxUnitID + 1);
|
|
|
|
}
|
2007-01-17 00:22:25 +01:00
|
|
|
|
2005-05-11 05:07:08 +02:00
|
|
|
while (entity_idx < entities.Count)
|
2005-01-12 15:31:47 +01:00
|
|
|
{
|
2005-05-03 23:42:09 +02:00
|
|
|
// all new state at this scope and below doesn't need to be
|
|
|
|
// wrapped, since we only yield after a complete iteration.
|
|
|
|
|
2007-05-02 14:07:08 +02:00
|
|
|
XMBElement entity = entities.Item(entity_idx++);
|
|
|
|
debug_assert(entity.GetNodeName() == el_entity);
|
2007-01-17 04:25:20 +01:00
|
|
|
|
2007-05-02 14:07:08 +02:00
|
|
|
XMBAttributeList attrs = entity.GetAttributes();
|
|
|
|
utf16string uid = attrs.GetNamedItem(at_uid);
|
2007-01-29 23:21:25 +01:00
|
|
|
int unitId = uid.empty() ? -1 : CStr(uid).ToInt();
|
2005-05-03 23:42:09 +02:00
|
|
|
|
|
|
|
CStrW TemplateName;
|
2005-07-02 23:42:55 +02:00
|
|
|
int PlayerID = 0;
|
2005-05-03 23:42:09 +02:00
|
|
|
CVector3D Position;
|
2005-07-02 23:42:55 +02:00
|
|
|
float Orientation = 0.f;
|
2005-05-03 23:42:09 +02:00
|
|
|
|
2005-05-11 05:07:08 +02:00
|
|
|
XERO_ITER_EL(entity, setting)
|
2005-01-12 15:31:47 +01:00
|
|
|
{
|
2007-05-02 14:07:08 +02:00
|
|
|
int element_name = setting.GetNodeName();
|
2005-01-12 15:31:47 +01:00
|
|
|
|
2005-05-03 23:42:09 +02:00
|
|
|
// <template>
|
|
|
|
if (element_name == el_template)
|
2005-01-12 15:31:47 +01:00
|
|
|
{
|
2007-05-02 14:07:08 +02:00
|
|
|
TemplateName = setting.GetText();
|
2005-05-03 23:42:09 +02:00
|
|
|
}
|
|
|
|
// <player>
|
|
|
|
else if (element_name == el_player)
|
|
|
|
{
|
2007-05-02 14:07:08 +02:00
|
|
|
PlayerID = CStr(setting.GetText()).ToInt();
|
2005-05-03 23:42:09 +02:00
|
|
|
}
|
|
|
|
// <position>
|
|
|
|
else if (element_name == el_position)
|
|
|
|
{
|
2007-05-02 14:07:08 +02:00
|
|
|
XMBAttributeList attrs = setting.GetAttributes();
|
2005-05-11 05:07:08 +02:00
|
|
|
Position = CVector3D(
|
2007-05-02 14:07:08 +02:00
|
|
|
CStr(attrs.GetNamedItem(at_x)).ToFloat(),
|
|
|
|
CStr(attrs.GetNamedItem(at_y)).ToFloat(),
|
|
|
|
CStr(attrs.GetNamedItem(at_z)).ToFloat());
|
2005-03-29 22:50:04 +02:00
|
|
|
}
|
2005-05-03 23:42:09 +02:00
|
|
|
// <orientation>
|
|
|
|
else if (element_name == el_orientation)
|
|
|
|
{
|
2007-05-02 14:07:08 +02:00
|
|
|
XMBAttributeList attrs = setting.GetAttributes();
|
|
|
|
Orientation = CStr(attrs.GetNamedItem(at_angle)).ToFloat();
|
2005-05-03 23:42:09 +02:00
|
|
|
}
|
|
|
|
else
|
2006-03-21 21:55:45 +01:00
|
|
|
debug_warn("Invalid map XML data");
|
2005-03-29 22:50:04 +02:00
|
|
|
}
|
2005-05-03 23:42:09 +02:00
|
|
|
|
2007-05-02 14:07:08 +02:00
|
|
|
CEntityTemplate* base = g_EntityTemplateCollection.GetTemplate(TemplateName, g_Game->GetPlayer(PlayerID));
|
2005-07-30 22:12:41 +02:00
|
|
|
if (! base)
|
2007-12-29 17:22:23 +01:00
|
|
|
LOG(CLogger::Error, LOG_CATEGORY, "Failed to load entity template '%ls'", TemplateName.c_str());
|
2005-05-03 23:42:09 +02:00
|
|
|
else
|
2005-07-30 22:12:41 +02:00
|
|
|
{
|
2007-01-17 04:25:20 +01:00
|
|
|
std::set<CStr> selections; // TODO: read from file
|
2006-03-17 04:59:49 +01:00
|
|
|
|
2007-05-02 14:07:08 +02:00
|
|
|
HEntity ent = g_EntityManager.Create(base, Position, Orientation, selections);
|
2005-07-30 22:12:41 +02:00
|
|
|
|
|
|
|
if (! ent)
|
2007-12-29 17:22:23 +01:00
|
|
|
LOG(CLogger::Error, LOG_CATEGORY, "Failed to create entity of type '%ls'", TemplateName.c_str());
|
2005-07-30 22:12:41 +02:00
|
|
|
else
|
2005-12-09 04:15:00 +01:00
|
|
|
{
|
2006-09-02 23:20:25 +02:00
|
|
|
ent->m_actor->SetPlayerID(PlayerID);
|
2007-01-17 00:22:25 +01:00
|
|
|
g_EntityManager.AddEntityClassData(ent);
|
2005-12-09 04:15:00 +01:00
|
|
|
|
2007-01-29 23:21:25 +01:00
|
|
|
if (unitId < 0)
|
2007-01-17 00:22:25 +01:00
|
|
|
ent->m_actor->SetID(m_MapReader.pUnitMan->GetNewID());
|
|
|
|
else
|
2007-01-29 23:21:25 +01:00
|
|
|
ent->m_actor->SetID(unitId);
|
2005-12-09 04:15:00 +01:00
|
|
|
}
|
2005-07-30 22:12:41 +02:00
|
|
|
}
|
2005-05-03 23:42:09 +02:00
|
|
|
|
2005-05-05 01:12:46 +02:00
|
|
|
completed_jobs++;
|
|
|
|
LDR_CHECK_TIMEOUT(completed_jobs, total_jobs);
|
2005-05-03 23:42:09 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-05-11 05:07:08 +02:00
|
|
|
int CXMLReader::ReadNonEntities(XMBElement parent, double end_time)
|
2005-05-03 23:42:09 +02:00
|
|
|
{
|
2007-05-02 14:07:08 +02:00
|
|
|
XMBElementList nonentities = parent.GetChildNodes();
|
2005-05-11 05:07:08 +02:00
|
|
|
while (nonentity_idx < nonentities.Count)
|
2005-05-03 23:42:09 +02:00
|
|
|
{
|
|
|
|
// all new state at this scope and below doesn't need to be
|
|
|
|
// wrapped, since we only yield after a complete iteration.
|
|
|
|
|
2007-05-02 14:07:08 +02:00
|
|
|
XMBElement nonentity = nonentities.Item(nonentity_idx++);
|
|
|
|
debug_assert(nonentity.GetNodeName() == el_nonentity);
|
2005-05-03 23:42:09 +02:00
|
|
|
|
|
|
|
CStr ActorName;
|
|
|
|
CVector3D Position;
|
2005-07-02 23:42:55 +02:00
|
|
|
float Orientation = 0.f;
|
2005-05-03 23:42:09 +02:00
|
|
|
|
2005-05-11 05:07:08 +02:00
|
|
|
XERO_ITER_EL(nonentity, setting)
|
2005-03-29 22:50:04 +02:00
|
|
|
{
|
2007-05-02 14:07:08 +02:00
|
|
|
int element_name = setting.GetNodeName();
|
2005-01-18 13:45:56 +01:00
|
|
|
|
2005-05-03 23:42:09 +02:00
|
|
|
// <actor>
|
|
|
|
if (element_name == el_actor)
|
2005-03-29 22:50:04 +02:00
|
|
|
{
|
2007-05-02 14:07:08 +02:00
|
|
|
ActorName = setting.GetText();
|
2005-05-03 23:42:09 +02:00
|
|
|
}
|
|
|
|
// <position>
|
|
|
|
else if (element_name == el_position)
|
|
|
|
{
|
2007-05-02 14:07:08 +02:00
|
|
|
XMBAttributeList attrs = setting.GetAttributes();
|
2007-01-17 04:25:20 +01:00
|
|
|
Position = CVector3D(
|
2007-05-02 14:07:08 +02:00
|
|
|
CStr(attrs.GetNamedItem(at_x)).ToFloat(),
|
|
|
|
CStr(attrs.GetNamedItem(at_y)).ToFloat(),
|
|
|
|
CStr(attrs.GetNamedItem(at_z)).ToFloat());
|
2005-01-12 15:31:47 +01:00
|
|
|
}
|
2005-05-03 23:42:09 +02:00
|
|
|
// <orientation>
|
|
|
|
else if (element_name == el_orientation)
|
|
|
|
{
|
2007-05-02 14:07:08 +02:00
|
|
|
XMBAttributeList attrs = setting.GetAttributes();
|
|
|
|
Orientation = CStr(attrs.GetNamedItem(at_angle)).ToFloat();
|
2005-05-03 23:42:09 +02:00
|
|
|
}
|
|
|
|
else
|
2006-03-21 21:55:45 +01:00
|
|
|
debug_warn("Invalid map XML data");
|
2005-01-12 15:31:47 +01:00
|
|
|
}
|
2005-05-03 23:42:09 +02:00
|
|
|
|
2007-01-17 04:25:20 +01:00
|
|
|
std::set<CStr> selections; // TODO: read from file
|
2006-03-17 04:59:49 +01:00
|
|
|
|
2007-01-08 02:56:46 +01:00
|
|
|
CUnit* unit = m_MapReader.pUnitMan->CreateUnit(ActorName, NULL, selections);
|
2005-05-11 05:07:08 +02:00
|
|
|
|
2005-12-09 04:15:00 +01:00
|
|
|
if (unit)
|
2005-01-12 15:31:47 +01:00
|
|
|
{
|
2005-05-03 23:42:09 +02:00
|
|
|
CMatrix3D m;
|
2007-01-17 04:25:20 +01:00
|
|
|
m.SetYRotation(Orientation + PI);
|
|
|
|
m.Translate(Position);
|
2005-05-03 23:42:09 +02:00
|
|
|
unit->GetModel()->SetTransform(m);
|
2005-12-09 04:15:00 +01:00
|
|
|
|
|
|
|
// TODO: save object IDs in the map file, and load them again,
|
|
|
|
// so that triggers have a persistent identifier for objects
|
2007-01-08 02:56:46 +01:00
|
|
|
unit->SetID(m_MapReader.pUnitMan->GetNewID());
|
2005-01-12 15:31:47 +01:00
|
|
|
}
|
2005-05-03 23:42:09 +02:00
|
|
|
|
2005-05-05 01:12:46 +02:00
|
|
|
completed_jobs++;
|
|
|
|
LDR_CHECK_TIMEOUT(completed_jobs, total_jobs);
|
2005-01-12 15:31:47 +01:00
|
|
|
}
|
2005-05-03 23:42:09 +02:00
|
|
|
|
|
|
|
return 0;
|
2005-01-12 15:31:47 +01:00
|
|
|
}
|
2005-03-22 22:00:56 +01:00
|
|
|
|
|
|
|
|
2005-05-03 23:42:09 +02:00
|
|
|
int CXMLReader::ProgressiveRead()
|
|
|
|
{
|
|
|
|
// yield after this time is reached. balances increased progress bar
|
|
|
|
// smoothness vs. slowing down loading.
|
2008-01-07 21:03:19 +01:00
|
|
|
const double end_time = timer_Time() + 200e-3;
|
2005-05-03 23:42:09 +02:00
|
|
|
|
|
|
|
int ret;
|
|
|
|
|
2005-05-11 05:07:08 +02:00
|
|
|
while (node_idx < nodes.Count)
|
2005-05-03 23:42:09 +02:00
|
|
|
{
|
2007-05-02 14:07:08 +02:00
|
|
|
XMBElement node = nodes.Item(node_idx);
|
|
|
|
CStr name = xmb_file.GetElementString(node.GetNodeName());
|
# Housekeeping and pathfinder enhancements / optimization when dealing with ranged actions.
- Modified Xeromyces to no longer automatically convert element and
attribute names to lowercase, so that we can have camelCase names. We
should now be able to convert all the multi-word entity properties, like
pass_through_allies, to camelCase, like passThroughAllies, which is more
consistent with the rest of our JavaScript naming conventions. To
support the existing code that assumes lowercase element names, I made
the getElementID and getAttributeID methods (used in the EL and AT
macros) ignore case, and I changed any code that directly accessed
element names to use the right case. CEntityTemplate now converts
Names_LikeThis to names_likeThis (changing each separate "word" in the
name to camelCase). Changed the version letter in XMB filenames from A
to B to support this without requiring people to delete old XMBs.
- Enhanced the pathfinder's handling of contact paths, resulting in a
very large speedup for actions like attacking, construction, etc. The
problem was that the pathfinder used to not count a given state as the
goal unless it was exactly coincident with the target location. This is
fine when you order a unit to go exactly to a certain spot, but if
you're ordering a unit to build, gather or attack something, then the
target tile is impassable (because your target is there) and therefore
the pathfinder never declares a state final. As a result, the pathfinder
tries hundreds of extra tiles in case there is a long path that gets to
the goal, and after failing to find any path that reaches the goal, it
gives you one to the closest point it got to. To fix it, I made the
pathfinder take into account a radius around the goal in which it's OK
to be, which depends on the size of the target unit and the range of
your action.
This was SVN commit r4186.
2006-08-01 05:41:21 +02:00
|
|
|
if (name == "Environment")
|
2005-05-11 05:07:08 +02:00
|
|
|
{
|
|
|
|
ReadEnvironment(node);
|
|
|
|
}
|
# Housekeeping and pathfinder enhancements / optimization when dealing with ranged actions.
- Modified Xeromyces to no longer automatically convert element and
attribute names to lowercase, so that we can have camelCase names. We
should now be able to convert all the multi-word entity properties, like
pass_through_allies, to camelCase, like passThroughAllies, which is more
consistent with the rest of our JavaScript naming conventions. To
support the existing code that assumes lowercase element names, I made
the getElementID and getAttributeID methods (used in the EL and AT
macros) ignore case, and I changed any code that directly accessed
element names to use the right case. CEntityTemplate now converts
Names_LikeThis to names_likeThis (changing each separate "word" in the
name to camelCase). Changed the version letter in XMB filenames from A
to B to support this without requiring people to delete old XMBs.
- Enhanced the pathfinder's handling of contact paths, resulting in a
very large speedup for actions like attacking, construction, etc. The
problem was that the pathfinder used to not count a given state as the
goal unless it was exactly coincident with the target location. This is
fine when you order a unit to go exactly to a certain spot, but if
you're ordering a unit to build, gather or attack something, then the
target tile is impassable (because your target is there) and therefore
the pathfinder never declares a state final. As a result, the pathfinder
tries hundreds of extra tiles in case there is a long path that gets to
the goal, and after failing to find any path that reaches the goal, it
gives you one to the closest point it got to. To fix it, I made the
pathfinder take into account a radius around the goal in which it's OK
to be, which depends on the size of the target unit and the range of
your action.
This was SVN commit r4186.
2006-08-01 05:41:21 +02:00
|
|
|
else if (name == "Camera")
|
2006-03-21 21:55:45 +01:00
|
|
|
{
|
|
|
|
ReadCamera(node);
|
|
|
|
}
|
# Housekeeping and pathfinder enhancements / optimization when dealing with ranged actions.
- Modified Xeromyces to no longer automatically convert element and
attribute names to lowercase, so that we can have camelCase names. We
should now be able to convert all the multi-word entity properties, like
pass_through_allies, to camelCase, like passThroughAllies, which is more
consistent with the rest of our JavaScript naming conventions. To
support the existing code that assumes lowercase element names, I made
the getElementID and getAttributeID methods (used in the EL and AT
macros) ignore case, and I changed any code that directly accessed
element names to use the right case. CEntityTemplate now converts
Names_LikeThis to names_likeThis (changing each separate "word" in the
name to camelCase). Changed the version letter in XMB filenames from A
to B to support this without requiring people to delete old XMBs.
- Enhanced the pathfinder's handling of contact paths, resulting in a
very large speedup for actions like attacking, construction, etc. The
problem was that the pathfinder used to not count a given state as the
goal unless it was exactly coincident with the target location. This is
fine when you order a unit to go exactly to a certain spot, but if
you're ordering a unit to build, gather or attack something, then the
target tile is impassable (because your target is there) and therefore
the pathfinder never declares a state final. As a result, the pathfinder
tries hundreds of extra tiles in case there is a long path that gets to
the goal, and after failing to find any path that reaches the goal, it
gives you one to the closest point it got to. To fix it, I made the
pathfinder take into account a radius around the goal in which it's OK
to be, which depends on the size of the target unit and the range of
your action.
This was SVN commit r4186.
2006-08-01 05:41:21 +02:00
|
|
|
else if (name == "Entities")
|
2005-05-03 23:42:09 +02:00
|
|
|
{
|
|
|
|
ret = ReadEntities(node, end_time);
|
2005-05-11 05:07:08 +02:00
|
|
|
if (ret != 0) // error or timed out
|
2005-05-03 23:42:09 +02:00
|
|
|
return ret;
|
|
|
|
}
|
# Housekeeping and pathfinder enhancements / optimization when dealing with ranged actions.
- Modified Xeromyces to no longer automatically convert element and
attribute names to lowercase, so that we can have camelCase names. We
should now be able to convert all the multi-word entity properties, like
pass_through_allies, to camelCase, like passThroughAllies, which is more
consistent with the rest of our JavaScript naming conventions. To
support the existing code that assumes lowercase element names, I made
the getElementID and getAttributeID methods (used in the EL and AT
macros) ignore case, and I changed any code that directly accessed
element names to use the right case. CEntityTemplate now converts
Names_LikeThis to names_likeThis (changing each separate "word" in the
name to camelCase). Changed the version letter in XMB filenames from A
to B to support this without requiring people to delete old XMBs.
- Enhanced the pathfinder's handling of contact paths, resulting in a
very large speedup for actions like attacking, construction, etc. The
problem was that the pathfinder used to not count a given state as the
goal unless it was exactly coincident with the target location. This is
fine when you order a unit to go exactly to a certain spot, but if
you're ordering a unit to build, gather or attack something, then the
target tile is impassable (because your target is there) and therefore
the pathfinder never declares a state final. As a result, the pathfinder
tries hundreds of extra tiles in case there is a long path that gets to
the goal, and after failing to find any path that reaches the goal, it
gives you one to the closest point it got to. To fix it, I made the
pathfinder take into account a radius around the goal in which it's OK
to be, which depends on the size of the target unit and the range of
your action.
This was SVN commit r4186.
2006-08-01 05:41:21 +02:00
|
|
|
else if (name == "Nonentities")
|
2005-05-03 23:42:09 +02:00
|
|
|
{
|
|
|
|
ret = ReadNonEntities(node, end_time);
|
2005-05-11 05:07:08 +02:00
|
|
|
if (ret != 0) // error or timed out
|
2005-05-03 23:42:09 +02:00
|
|
|
return ret;
|
|
|
|
}
|
2007-02-27 03:14:18 +01:00
|
|
|
else if (name == "Paths")
|
2006-08-22 04:24:44 +02:00
|
|
|
{
|
|
|
|
ReadCinema(node);
|
|
|
|
}
|
2006-11-24 20:45:04 +01:00
|
|
|
else if (name == "Triggers")
|
|
|
|
{
|
|
|
|
ReadTriggers(node);
|
|
|
|
}
|
2005-05-03 23:42:09 +02:00
|
|
|
else
|
2007-04-22 03:09:50 +02:00
|
|
|
{
|
|
|
|
debug_printf("Invalid XML element in map file: %s\n", name.c_str());
|
2006-03-21 21:55:45 +01:00
|
|
|
debug_warn("Invalid map XML data");
|
2007-04-22 03:09:50 +02:00
|
|
|
}
|
2005-05-03 23:42:09 +02:00
|
|
|
|
|
|
|
node_idx++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// progressive
|
|
|
|
int CMapReader::ReadXML()
|
|
|
|
{
|
2005-05-11 05:07:08 +02:00
|
|
|
if (!xml_reader)
|
|
|
|
xml_reader = new CXMLReader(filename_xml, *this);
|
2005-05-03 23:42:09 +02:00
|
|
|
|
|
|
|
int ret = xml_reader->ProgressiveRead();
|
2005-05-05 01:12:46 +02:00
|
|
|
// finished or failed
|
2005-05-11 05:07:08 +02:00
|
|
|
if (ret <= 0)
|
2005-05-03 23:42:09 +02:00
|
|
|
{
|
|
|
|
delete xml_reader;
|
|
|
|
xml_reader = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int CMapReader::DelayLoadFinished()
|
2005-03-22 22:00:56 +01:00
|
|
|
{
|
|
|
|
// we were dynamically allocated by CWorld::Initialize
|
|
|
|
delete this;
|
2005-05-03 23:42:09 +02:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|