mirror of
https://github.com/electronicarts/CnC_Renegade.git
synced 2025-12-16 23:51:41 -05:00
Initial commit of Command & Conquer Renegade source code.
This commit is contained in:
856
Code/Tools/LevelEdit/EditorSaveLoad.cpp
Normal file
856
Code/Tools/LevelEdit/EditorSaveLoad.cpp
Normal file
@@ -0,0 +1,856 @@
|
||||
/*
|
||||
** Command & Conquer Renegade(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/***********************************************************************************************
|
||||
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
|
||||
***********************************************************************************************
|
||||
* *
|
||||
* Project Name : LevelEdit *
|
||||
* *
|
||||
* $Archive:: /Commando/Code/Tools/LevelEdit/EditorSaveLoad.cpp $*
|
||||
* *
|
||||
* Author:: Patrick Smith *
|
||||
* *
|
||||
* $Modtime:: 3/05/02 3:30p $*
|
||||
* *
|
||||
* $Revision:: 37 $*
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "leveleditdoc.h"
|
||||
#include "editorsaveload.h"
|
||||
#include "persist.h"
|
||||
#include "persistfactory.h"
|
||||
#include "preset.h"
|
||||
#include "utils.h"
|
||||
#include "definition.h"
|
||||
#include "editorchunkids.h"
|
||||
#include "physstaticsavesystem.h"
|
||||
#include "chunkio.h"
|
||||
#include "cameramgr.h"
|
||||
#include "filemgr.h"
|
||||
#include "matrix3d.h"
|
||||
#include "rawfile.h"
|
||||
#include "nodemgr.h"
|
||||
#include "sceneeditor.h"
|
||||
#include "node.h"
|
||||
#include "lightambientform.h"
|
||||
#include "soundscene.h"
|
||||
#include "backgroundmgr.h"
|
||||
#include "conversationmgr.h"
|
||||
#include "weathermgr.h"
|
||||
#include "combat.h"
|
||||
#include "mapmgr.h"
|
||||
#include "pathfind.h"
|
||||
#include "lightsolvesavesystem.h"
|
||||
#include "heightfieldmgr.h"
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// Global singleton instance
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
EditorSaveLoadClass _TheEditorSaveLoadSubsystem;
|
||||
PathfindImportExportSaveLoadClass _ThePathfindImporterExporter;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// Static member initialization
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
bool EditorSaveLoadClass::m_LoadedValidVis = true;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// Constants
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
enum
|
||||
{
|
||||
CHUNKID_MICRO_CHUNKS = 0x10140738,
|
||||
CHUNKID_OBSOLETE,
|
||||
CHUNKID_PATHFIND_DATA
|
||||
};
|
||||
|
||||
|
||||
enum
|
||||
{
|
||||
VARID_INCLUDE_FILE = 0x01,
|
||||
VARID_CAMERA_TM,
|
||||
VARID_OBSOLETE_0,
|
||||
VARID_BACK_MUSIC,
|
||||
VARID_AMBIENT_LIGHT,
|
||||
VARID_OBSOLETE_1,
|
||||
VARID_OBSOLETE_2,
|
||||
VARID_FAR_CLIP_PLANE_DOUBLE,
|
||||
VARID_FOG_COLOR,
|
||||
VARID_FOG_PLANES,
|
||||
VARID_FOG_ENABLED,
|
||||
VARID_FAR_CLIP_PLANE,
|
||||
VARID_RESTART_SCRIPT_NAME,
|
||||
VARID_RESPAWN_SCRIPT_NAME,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
CHUNKID_LVL_DATA = 304021447,
|
||||
CHUNKID_LIGHT_SOLVE,
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Chunk_ID
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
uint32
|
||||
EditorSaveLoadClass::Chunk_ID (void) const
|
||||
{
|
||||
return CHUNKID_EDITOR_SAVELOAD;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Contains_Data
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
bool
|
||||
EditorSaveLoadClass::Contains_Data (void) const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Save
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
bool
|
||||
EditorSaveLoadClass::Save (ChunkSaveClass &csave)
|
||||
{
|
||||
bool retval = true;
|
||||
int index;
|
||||
|
||||
csave.Begin_Chunk (CHUNKID_MICRO_CHUNKS);
|
||||
|
||||
//
|
||||
// Write the camera transform to the chunk
|
||||
//
|
||||
Matrix3D camera_tm = ::Get_Camera_Mgr ()->Get_Camera ()->Get_Transform ();
|
||||
WRITE_MICRO_CHUNK (csave, VARID_CAMERA_TM, camera_tm);
|
||||
|
||||
//
|
||||
// Write the miscellaneous level settings to the chunk
|
||||
//
|
||||
Vector3 ambient_light = ::Get_Scene_Editor ()->Get_Ambient_Light ();
|
||||
WRITE_MICRO_CHUNK (csave, VARID_AMBIENT_LIGHT, ambient_light);
|
||||
|
||||
//
|
||||
// Save the fog settings
|
||||
//
|
||||
bool fog_enabled = false;
|
||||
struct
|
||||
{
|
||||
float z_near;
|
||||
float z_far;
|
||||
} fog_planes = { 50.0F, 100.0F };
|
||||
|
||||
Vector3 fog_color (0, 0, 0);
|
||||
::Get_Scene_Editor ()->Get_Fog_Range (&fog_planes.z_near, &fog_planes.z_far);
|
||||
fog_color = ::Get_Scene_Editor ()->Get_Fog_Color ();
|
||||
fog_enabled = ::Get_Scene_Editor ()->Get_Fog_Enable ();
|
||||
|
||||
WRITE_MICRO_CHUNK (csave, VARID_FOG_ENABLED, fog_enabled);
|
||||
WRITE_MICRO_CHUNK (csave, VARID_FOG_COLOR, fog_color);
|
||||
WRITE_MICRO_CHUNK (csave, VARID_FOG_PLANES, fog_planes);
|
||||
|
||||
//
|
||||
// Save the restart and respawn script names
|
||||
//
|
||||
StringClass restart_script_name = CombatManager::Get_Start_Script ();
|
||||
StringClass respawn_script_name = CombatManager::Get_Respawn_Script ();
|
||||
WRITE_MICRO_CHUNK_WWSTRING (csave, VARID_RESTART_SCRIPT_NAME, restart_script_name);
|
||||
WRITE_MICRO_CHUNK_WWSTRING (csave, VARID_RESPAWN_SCRIPT_NAME, respawn_script_name);
|
||||
|
||||
//
|
||||
// Save the far clip plane...
|
||||
//
|
||||
float znear = 0;
|
||||
float zfar = 0;
|
||||
::Get_Camera_Mgr ()->Get_Camera ()->Get_Clip_Planes (znear, zfar);
|
||||
WRITE_MICRO_CHUNK (csave, VARID_FAR_CLIP_PLANE, zfar);
|
||||
|
||||
//
|
||||
// Write the background music filename out to the chunk
|
||||
//
|
||||
CString filename = ::Get_Scene_Editor ()->Get_Background_Music_Filename ();
|
||||
CString path = ::Get_File_Mgr ()->Make_Relative_Path (filename);
|
||||
WRITE_MICRO_CHUNK_STRING (csave, VARID_BACK_MUSIC, (LPCTSTR)path);
|
||||
|
||||
//
|
||||
// Write the list of include files for the level to the chunk.
|
||||
//
|
||||
STRING_LIST &include_list = ::Get_File_Mgr ()->Get_Include_File_List ();
|
||||
for (index = 0; index < include_list.Count (); index ++) {
|
||||
StringClass filename = (LPCTSTR)include_list[index];
|
||||
WRITE_MICRO_CHUNK_WWSTRING (csave, VARID_INCLUDE_FILE, filename);
|
||||
}
|
||||
|
||||
csave.End_Chunk ();
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Load
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
bool
|
||||
EditorSaveLoadClass::Load (ChunkLoadClass &cload)
|
||||
{
|
||||
bool retval = true;
|
||||
while (cload.Open_Chunk ()) {
|
||||
switch (cload.Cur_Chunk_ID ()) {
|
||||
|
||||
//
|
||||
// Load all the presets from this chunk
|
||||
//
|
||||
case CHUNKID_MICRO_CHUNKS:
|
||||
retval &= Load_Micro_Chunks (cload);
|
||||
break;
|
||||
}
|
||||
|
||||
cload.Close_Chunk ();
|
||||
}
|
||||
|
||||
SaveLoadSystemClass::Register_Post_Load_Callback (this);
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Load_Micro_Chunks
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
bool
|
||||
EditorSaveLoadClass::Load_Micro_Chunks (ChunkLoadClass &cload)
|
||||
{
|
||||
bool retval = true;
|
||||
|
||||
Vector3 fog_color (0, 0, 0);
|
||||
bool fog_enabled = false;
|
||||
|
||||
StringClass restart_script_name;
|
||||
StringClass respawn_script_name;
|
||||
|
||||
while (cload.Open_Micro_Chunk ()) {
|
||||
switch (cload.Cur_Micro_Chunk_ID ()) {
|
||||
|
||||
//
|
||||
// Read the camera's transformation matrix from the chunk
|
||||
// and pass it onto the camera.
|
||||
//
|
||||
case VARID_CAMERA_TM:
|
||||
{
|
||||
Matrix3D camera_tm;
|
||||
cload.Read(&camera_tm,sizeof (camera_tm));
|
||||
::Get_Camera_Mgr ()->Get_Camera ()->Set_Transform (camera_tm);
|
||||
}
|
||||
break;
|
||||
|
||||
//
|
||||
// Read the include file from the chunk and add it to the list
|
||||
// of level include files.
|
||||
//
|
||||
case VARID_INCLUDE_FILE:
|
||||
{
|
||||
StringClass filename;
|
||||
cload.Read(filename.Get_Buffer(cload.Cur_Micro_Chunk_Length()),cload.Cur_Micro_Chunk_Length());
|
||||
::Get_File_Mgr ()->Get_Include_File_List ().Add ((LPCTSTR)filename);
|
||||
}
|
||||
break;
|
||||
|
||||
case VARID_FAR_CLIP_PLANE_DOUBLE:
|
||||
{
|
||||
float znear = 0;
|
||||
float zfar = 0;
|
||||
::Get_Camera_Mgr ()->Get_Camera ()->Get_Clip_Planes (znear, zfar);
|
||||
|
||||
double double_zfar = 0;
|
||||
cload.Read (&double_zfar, sizeof (double_zfar));
|
||||
zfar = double_zfar;
|
||||
::Get_Camera_Mgr ()->Get_Camera ()->Set_Clip_Planes (znear, zfar);
|
||||
}
|
||||
break;
|
||||
|
||||
case VARID_FAR_CLIP_PLANE:
|
||||
{
|
||||
float znear = 0;
|
||||
float zfar = 0;
|
||||
::Get_Camera_Mgr ()->Get_Camera ()->Get_Clip_Planes (znear, zfar);
|
||||
cload.Read (&zfar, sizeof (zfar));
|
||||
::Get_Camera_Mgr ()->Get_Camera ()->Set_Clip_Planes (znear, zfar);
|
||||
}
|
||||
break;
|
||||
|
||||
case VARID_AMBIENT_LIGHT:
|
||||
{
|
||||
Vector3 ambient_light;
|
||||
cload.Read (&ambient_light, sizeof (ambient_light));
|
||||
::Get_Scene_Editor ()->Set_Ambient_Light (ambient_light);
|
||||
::Get_Scene_Editor ()->Update_Lighting ();
|
||||
|
||||
LightAmbientFormClass *light_form = Get_Ambient_Light_Form ();
|
||||
light_form->Update_Settings ();
|
||||
}
|
||||
break;
|
||||
|
||||
READ_MICRO_CHUNK (cload, VARID_FOG_ENABLED, fog_enabled);
|
||||
READ_MICRO_CHUNK (cload, VARID_FOG_COLOR, fog_color);
|
||||
|
||||
READ_MICRO_CHUNK_WWSTRING (cload, VARID_RESTART_SCRIPT_NAME, restart_script_name);
|
||||
READ_MICRO_CHUNK_WWSTRING (cload, VARID_RESPAWN_SCRIPT_NAME, respawn_script_name);
|
||||
|
||||
case VARID_FOG_PLANES:
|
||||
{
|
||||
struct
|
||||
{
|
||||
float z_near;
|
||||
float z_far;
|
||||
} fog_planes = { 50.0F, 100.0F };
|
||||
|
||||
cload.Read (&fog_planes, sizeof (fog_planes));
|
||||
::Get_Scene_Editor ()->Set_Fog_Range (fog_planes.z_near, fog_planes.z_far);
|
||||
}
|
||||
break;
|
||||
|
||||
case VARID_BACK_MUSIC:
|
||||
{
|
||||
StringClass filename;
|
||||
cload.Read(filename.Get_Buffer(cload.Cur_Micro_Chunk_Length()),cload.Cur_Micro_Chunk_Length());
|
||||
::Get_Scene_Editor ()->Set_Background_Music (filename);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
cload.Close_Micro_Chunk ();
|
||||
}
|
||||
|
||||
//
|
||||
// Apply the script settings
|
||||
//
|
||||
CombatManager::Set_Start_Script (restart_script_name);
|
||||
CombatManager::Set_Respawn_Script (respawn_script_name);
|
||||
|
||||
//
|
||||
// Apply the fog settings
|
||||
//
|
||||
::Get_Scene_Editor ()->Set_Fog_Color (fog_color);
|
||||
::Get_Scene_Editor ()->Set_Fog_Enable (fog_enabled);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Save_Level
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
EditorSaveLoadClass::Save_Level (LPCTSTR filename)
|
||||
{
|
||||
//
|
||||
// Create the file
|
||||
//
|
||||
HANDLE hfile = ::CreateFile (filename,
|
||||
GENERIC_WRITE,
|
||||
0,
|
||||
NULL,
|
||||
CREATE_ALWAYS,
|
||||
0L,
|
||||
NULL);
|
||||
|
||||
ASSERT (hfile != INVALID_HANDLE_VALUE);
|
||||
if (hfile != INVALID_HANDLE_VALUE) {
|
||||
|
||||
RawFileClass file_obj;
|
||||
file_obj.Attach (hfile);
|
||||
ChunkSaveClass chunk_save (&file_obj);
|
||||
|
||||
//
|
||||
// (gth) March 4, 2002 - modifying this function to embed two "save files" into this
|
||||
// file. The first chunk will contain an entire save for the normal level data. The second
|
||||
// chunk will contain the lighting save
|
||||
//
|
||||
chunk_save.Begin_Chunk(CHUNKID_LVL_DATA);
|
||||
Save_Level_Data(chunk_save);
|
||||
chunk_save.End_Chunk();
|
||||
|
||||
chunk_save.Begin_Chunk(CHUNKID_LIGHT_SOLVE);
|
||||
Save_Light_Solve(chunk_save);
|
||||
chunk_save.End_Chunk();
|
||||
|
||||
|
||||
//
|
||||
// Remember that we are now up-to-date
|
||||
//
|
||||
Set_Modified (false);
|
||||
}
|
||||
return ;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Save_Level_Data - saves the level data for an LVL file
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
EditorSaveLoadClass::Save_Level_Data(ChunkSaveClass & chunk_save)
|
||||
{
|
||||
//
|
||||
// Repartition the static culling systems
|
||||
// (gth) can't re-partition the object culling systems or
|
||||
// we'll lose hierarchical vis
|
||||
//
|
||||
::Get_Scene_Editor ()->Re_Partition_Static_Lights ();
|
||||
::Get_Scene_Editor ()->Re_Partition_Audio_System ();
|
||||
|
||||
//
|
||||
// Basically just save the list of nodes and some other
|
||||
// miscellaneous information (camera, sky, etc).
|
||||
//
|
||||
SaveLoadSystemClass::Save (chunk_save, _PhysStaticDataSaveSystem);
|
||||
SaveLoadSystemClass::Save (chunk_save, _TheNodeMgr);
|
||||
SaveLoadSystemClass::Save (chunk_save, _TheEditorSaveLoadSubsystem);
|
||||
SaveLoadSystemClass::Save (chunk_save, _TheBackgroundMgr);
|
||||
SaveLoadSystemClass::Save (chunk_save, _TheWeatherMgr);
|
||||
SaveLoadSystemClass::Save (chunk_save, _TheMapMgrSaveLoadSubsystem);
|
||||
SaveLoadSystemClass::Save (chunk_save, _TheHeightfieldMgrSaveLoadSubsystem);
|
||||
|
||||
//
|
||||
// Save the level-specific conversations
|
||||
//
|
||||
_ConversationMgrSaveLoad.Set_Category_To_Save (ConversationMgrClass::CATEGORY_LEVEL);
|
||||
SaveLoadSystemClass::Save (chunk_save, _ConversationMgrSaveLoad);
|
||||
return ;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Save_Light_Solve - saves the light-solve data for an LVL file
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
void EditorSaveLoadClass::Save_Light_Solve(ChunkSaveClass & chunk_save)
|
||||
{
|
||||
SaveLoadSystemClass::Save( chunk_save, _TheLightSolveSaveSystem);
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Load_Level
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
EditorSaveLoadClass::Load_Level (LPCTSTR filename)
|
||||
{
|
||||
//
|
||||
// Create the file
|
||||
//
|
||||
HANDLE hfile = ::CreateFile (filename,
|
||||
GENERIC_READ,
|
||||
FILE_SHARE_READ,
|
||||
NULL,
|
||||
OPEN_EXISTING,
|
||||
0L,
|
||||
NULL);
|
||||
|
||||
ASSERT (hfile != INVALID_HANDLE_VALUE);
|
||||
if (hfile != INVALID_HANDLE_VALUE) {
|
||||
|
||||
RawFileClass file_obj;
|
||||
file_obj.Attach (hfile);
|
||||
ChunkLoadClass chunk_load (&file_obj);
|
||||
|
||||
SoundSceneClass *sound_scene = WWAudioClass::Get_Instance ()->Get_Sound_Scene ();
|
||||
if (sound_scene != NULL) {
|
||||
sound_scene->Set_Batch_Mode (true);
|
||||
}
|
||||
|
||||
//
|
||||
// Get the save-load subsystem to load
|
||||
//
|
||||
m_LoadedValidVis = true;
|
||||
NodeMgrClass::Free_Nodes ();
|
||||
|
||||
//
|
||||
// (gth) March 4, 2002 - LVL files are now two independent save-load operations,
|
||||
// one for the normal level data and one for the light solve data. Here, we
|
||||
// detect whether we are loading a file that was created before this change.
|
||||
//
|
||||
uint32 id,size;
|
||||
if (chunk_load.Peek_Next_Chunk(&id,&size) && (id == CHUNKID_LVL_DATA)) {
|
||||
|
||||
// Current file format, multiple saves embedded into this file
|
||||
while (chunk_load.Open_Chunk()) {
|
||||
|
||||
switch (chunk_load.Cur_Chunk_ID()) {
|
||||
case CHUNKID_LVL_DATA:
|
||||
case CHUNKID_LIGHT_SOLVE:
|
||||
SaveLoadSystemClass::Load (chunk_load);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
chunk_load.Close_Chunk();
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
// Legacy file format support
|
||||
SaveLoadSystemClass::Load (chunk_load);
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
// Repartition the static culling systems
|
||||
// (gth) can't re-partition the object culling systems or
|
||||
// we'll lose hierarchical vis
|
||||
//
|
||||
::Get_Scene_Editor ()->Re_Partition_Static_Lights ();
|
||||
::Get_Scene_Editor ()->Re_Partition_Audio_System ();
|
||||
|
||||
//
|
||||
// Now create any embedded nodes (nodes that are embedded inside
|
||||
// the preset of any nodes that are currently in the level).
|
||||
//
|
||||
NodeMgrClass::Create_All_Embedded_Nodes ();
|
||||
|
||||
//
|
||||
// Validate VIS information if necessary
|
||||
//
|
||||
if (m_LoadedValidVis) {
|
||||
::Get_Scene_Editor ()->Validate_Vis ();
|
||||
::Get_Scene_Editor ()->Update_Culling_System_Bounding_Boxes ();
|
||||
} else {
|
||||
::MessageBox (NULL, "Static geometry has changed since the last time this level was loaded. All previously generated VIS data has been discarded.", "Vis Discarded", MB_ICONEXCLAMATION | MB_OK);
|
||||
::Get_Scene_Editor ()->Discard_Vis ();
|
||||
}
|
||||
|
||||
if (sound_scene != NULL) {
|
||||
sound_scene->Set_Batch_Mode (false);
|
||||
}
|
||||
|
||||
//
|
||||
// Remember that we are now up-to-date
|
||||
//
|
||||
Set_Modified (false);
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Export_Dynamic_Objects
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
EditorSaveLoadClass::Export_Dynamic_Objects (LPCTSTR filename)
|
||||
{
|
||||
//
|
||||
// Create the file
|
||||
//
|
||||
HANDLE hfile = ::CreateFile (filename,
|
||||
GENERIC_WRITE,
|
||||
0,
|
||||
NULL,
|
||||
CREATE_ALWAYS,
|
||||
0L,
|
||||
NULL);
|
||||
|
||||
ASSERT (hfile != INVALID_HANDLE_VALUE);
|
||||
if (hfile != INVALID_HANDLE_VALUE) {
|
||||
|
||||
RawFileClass file_obj;
|
||||
file_obj.Attach (hfile);
|
||||
ChunkSaveClass chunk_save (&file_obj);
|
||||
|
||||
//
|
||||
// Remove the static objects from the level, save the nodes,
|
||||
// then put the static objects back
|
||||
//
|
||||
NODE_LIST static_obj_list;
|
||||
NodeMgrClass::Remove_Static_Objects (static_obj_list);
|
||||
SaveLoadSystemClass::Save (chunk_save, _TheNodeMgr);
|
||||
NodeMgrClass::Put_Objects_Back (static_obj_list);
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Import_Dynamic_Objects
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
EditorSaveLoadClass::Import_Dynamic_Objects (LPCTSTR filename)
|
||||
{
|
||||
//
|
||||
// Create the file
|
||||
//
|
||||
HANDLE hfile = ::CreateFile (filename,
|
||||
GENERIC_READ,
|
||||
FILE_SHARE_READ,
|
||||
NULL,
|
||||
OPEN_EXISTING,
|
||||
0L,
|
||||
NULL);
|
||||
|
||||
ASSERT (hfile != INVALID_HANDLE_VALUE);
|
||||
if (hfile != INVALID_HANDLE_VALUE) {
|
||||
|
||||
RawFileClass file_obj;
|
||||
file_obj.Attach (hfile);
|
||||
ChunkLoadClass chunk_load (&file_obj);
|
||||
|
||||
//
|
||||
// Find the largest used ID
|
||||
//
|
||||
uint32 start_id = (NodeMgrClass::Get_Max_Used_ID () + 1);
|
||||
|
||||
//
|
||||
// Remove the dynamic objects from the level and load the new objects.
|
||||
//
|
||||
NODE_LIST dynamic_obj_list;
|
||||
NodeMgrClass::Remove_Dynamic_Objects (dynamic_obj_list);
|
||||
SaveLoadSystemClass::Load (chunk_load);
|
||||
|
||||
::Output_Message ("Resetting existing static node IDs.\r\n");
|
||||
|
||||
//
|
||||
// Re-assign IDs to the existing static nodes
|
||||
//
|
||||
for ( NodeClass *node = NodeMgrClass::Get_First ();
|
||||
node != NULL;
|
||||
node = NodeMgrClass::Get_Next (node))
|
||||
{
|
||||
if (node->Is_Static ()) {
|
||||
node->Set_ID (start_id++);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Check all the dynamic objects for ID collision
|
||||
//
|
||||
CString id_collision_msg = "The following dynamic object IDs collided on import:\n\n";
|
||||
bool show_msg = false;
|
||||
DynamicVectorClass<NodeClass *> bad_node_list;
|
||||
for (int index = 0; index < dynamic_obj_list.Count (); index ++) {
|
||||
NodeClass *node = dynamic_obj_list[index];
|
||||
if (NodeMgrClass::Find_Node (node->Get_ID ()) != NULL) {
|
||||
CString entry;
|
||||
entry.Format ("Object %d\n", node->Get_ID ());
|
||||
id_collision_msg += entry;
|
||||
bad_node_list.Add (node);
|
||||
show_msg = true;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Put the original objects back
|
||||
//
|
||||
NodeMgrClass::Put_Objects_Back (dynamic_obj_list);
|
||||
NodeMgrClass::Reset_New_ID ();
|
||||
|
||||
//
|
||||
// Let the user know we had ID collision (if necessary)
|
||||
//
|
||||
if (show_msg) {
|
||||
::MessageBox (NULL, id_collision_msg, "ID Collision", MB_ICONERROR | MB_OK);
|
||||
|
||||
//
|
||||
// Ask the user if we should fix the collisions or not
|
||||
//
|
||||
if (::MessageBox (NULL, "Would you like to repair the newly imported objects with ambiguous IDs?", "ID Collision", MB_ICONQUESTION | MB_YESNO) == IDYES) {
|
||||
|
||||
//
|
||||
// Repair all collisions
|
||||
//
|
||||
for (int index = 0; index < bad_node_list.Count (); index ++) {
|
||||
NodeClass *node = bad_node_list[index];
|
||||
if (node != NULL) {
|
||||
node->Set_ID (NodeMgrClass::Get_Node_ID (node->Get_Type ()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// On_Post_Load
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
EditorSaveLoadClass::On_Post_Load (void)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Export_Pathfind
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
PathfindImportExportSaveLoadClass::Export_Pathfind (LPCTSTR filename)
|
||||
{
|
||||
//
|
||||
// Create the file
|
||||
//
|
||||
HANDLE hfile = ::CreateFile (filename,
|
||||
GENERIC_WRITE,
|
||||
0,
|
||||
NULL,
|
||||
CREATE_ALWAYS,
|
||||
0L,
|
||||
NULL);
|
||||
|
||||
ASSERT (hfile != INVALID_HANDLE_VALUE);
|
||||
if (hfile != INVALID_HANDLE_VALUE) {
|
||||
|
||||
RawFileClass file_obj;
|
||||
file_obj.Attach (hfile);
|
||||
ChunkSaveClass chunk_save (&file_obj);
|
||||
|
||||
//
|
||||
//
|
||||
// Basically just save the list of nodes and some other
|
||||
// miscellaneous information (camera, sky, etc).
|
||||
//
|
||||
SaveLoadSystemClass::Save (chunk_save, _ThePathfindImporterExporter);
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Import_Pathfind
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
PathfindImportExportSaveLoadClass::Import_Pathfind (LPCTSTR filename)
|
||||
{
|
||||
//
|
||||
// Create the file
|
||||
//
|
||||
HANDLE hfile = ::CreateFile (filename,
|
||||
GENERIC_READ,
|
||||
FILE_SHARE_READ,
|
||||
NULL,
|
||||
OPEN_EXISTING,
|
||||
0L,
|
||||
NULL);
|
||||
|
||||
ASSERT (hfile != INVALID_HANDLE_VALUE);
|
||||
if (hfile != INVALID_HANDLE_VALUE) {
|
||||
|
||||
RawFileClass file_obj;
|
||||
file_obj.Attach (hfile);
|
||||
ChunkLoadClass chunk_load (&file_obj);
|
||||
|
||||
//
|
||||
// Get the save-load subsystem to load
|
||||
//
|
||||
SaveLoadSystemClass::Load (chunk_load);
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Save
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
bool
|
||||
PathfindImportExportSaveLoadClass::Save (ChunkSaveClass &csave)
|
||||
{
|
||||
//
|
||||
// Save the pathfind data
|
||||
//
|
||||
csave.Begin_Chunk (CHUNKID_PATHFIND_DATA);
|
||||
PathfindClass::Get_Instance()->Save (csave);
|
||||
csave.End_Chunk ();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Load
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
bool
|
||||
PathfindImportExportSaveLoadClass::Load (ChunkLoadClass &cload)
|
||||
{
|
||||
while (cload.Open_Chunk ()) {
|
||||
switch (cload.Cur_Chunk_ID ()) {
|
||||
|
||||
//
|
||||
// Import the pathfind data...
|
||||
//
|
||||
case CHUNKID_PATHFIND_DATA:
|
||||
PathfindClass::Get_Instance()->Load (cload);
|
||||
break;
|
||||
}
|
||||
|
||||
cload.Close_Chunk ();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
Reference in New Issue
Block a user