This repository has been archived on 2025-02-27. You can view files and clone it, but cannot push or open issues or pull requests.
CnC_Renegade/Code/Tools/LevelEdit/Export.cpp

1015 lines
26 KiB
C++

/*
** 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/Export.cpp $*
* *
* Author:: Patrick Smith *
* *
* $Modtime:: 6/26/02 2:13p $*
* *
* $Revision:: 34 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "stdafx.h"
#include "leveledit.h"
#include "leveleditdoc.h"
#include "export.h"
#include "editorini.h"
#include "utils.h"
#include "resource.h"
#include "nodemgr.h"
#include "vector3.h"
#include "matrix3d.h"
#include "ffactory.h"
#include "filemgr.h"
#include "_assetmgr.h"
#include "editorassetmgr.h"
#include "..\..\commando\lev_file.h"
#include "chunkio.h"
#include "sceneeditor.h"
#include "filelocations.h"
#include "inisections.h"
#include "hlod.h"
#include "w3derr.h"
#include "saveload.h"
#include "physstaticsavesystem.h"
#include "physdynamicsavesystem.h"
#include "combatsaveload.h"
#include "terrainnode.h"
#include "staticphys.h"
#include "savegame.h"
#include "regkeys.h"
#include "combat.h"
#include "assetdep.h"
#include "presetslibform.h"
#include "pathfind.h"
#include "gameobjmanager.h"
#include "stringsmgr.h"
#include "assetpackagemgr.h"
#include "presetmgr.h"
/////////////////////////////////////////////////////////
// Local constants
/////////////////////////////////////////////////////////
const TCHAR * const STATIC_EXTENSION = TEXT (".lsd");
const TCHAR * const DYNAMIC_EXTENSION = TEXT (".ldd");
const TCHAR * const MIX_EXTENSION = TEXT (".mix");
const TCHAR * const ALWAYS_ROOT_NAME = TEXT ("always");
const TCHAR * const ALWAYS_DATA_FILENAME = TEXT ("always.dat");
const TCHAR * const ALWAYS_DB_FILENAME = TEXT ("always.dbs");
/////////////////////////////////////////////////////////
//
// Export_Level
//
/////////////////////////////////////////////////////////
void
ExporterClass::Export_Level (LPCTSTR filename)
{
CWaitCursor wait_cursor;
m_AssetList.Delete_All ();
//
// Prepare the level for exporting...
//
DynamicVectorClass<NodeClass *> node_list;
Pre_Level_Export (node_list);
//
// Get the base destination path
//
Path = ::Strip_Filename_From_Path (filename);
//
// Strip the path and extension from the filename to give
// us a base for use with other filenames
//
FilenameBase = ::Get_Filename_From_Path (filename);
int extension_index = FilenameBase.ReverseFind ('.');
if (extension_index != -1) {
FilenameBase = FilenameBase.Left (extension_index);
}
//
// Setup the temporary directory
//
Make_Temp_Directory ();
//
// Export the level files
//
Export_Level_File ();
Export_Level_Data ();
Export_Dependency_File ();
Export_Definition_Databases (false);
//
// Now build the mix file...
//
MixFileCreator.Generate_Mix_File (filename);
//
// Cleanup any temp files we needed
//
Delete_Temp_Directory ();
//
// Resetore the level after exporting
//
Post_Level_Export (node_list);
//
// Cache the directory path we just exported into
//
theApp.WriteProfileString (CONFIG_KEY, LAST_EXPORT_DIR_VALUE, Path);
return ;
}
/////////////////////////////////////////////////////////
//
// Make_Temp_Directory
//
/////////////////////////////////////////////////////////
void
ExporterClass::Make_Temp_Directory (void)
{
//
// Get the path of the temp directory
//
char temp_dir[MAX_PATH] = { 0 };
::GetTempPath (sizeof (temp_dir), temp_dir);
CString temp_path = ::Make_Path (temp_dir, FilenameBase);
//
// Try to find a unique temp directory to store our data
//
int index = 0;
do {
TempDirectory.Format ("%s%.2d.DIR", (const char *)temp_path, index++);
} while (GetFileAttributes (TempDirectory) != 0xFFFFFFFF);
//
// Create the directory
//
::CreateDirectory (TempDirectory, NULL);
::Set_Current_Directory (TempDirectory);
::SetCurrentDirectory (TempDirectory);
return ;
}
/////////////////////////////////////////////////////////
//
// Delete_Temp_Directory
//
/////////////////////////////////////////////////////////
void
ExporterClass::Delete_Temp_Directory (void)
{
//
// Change the current directory so we can remove the temporary one
//
::Set_Current_Directory (Path);
::SetCurrentDirectory (Path);
//
// Remove the temporary directory
//
Clean_Directory (TempDirectory);
::RemoveDirectory (TempDirectory);
return ;
}
/////////////////////////////////////////////////////////
//
// Export_Dependency_File
//
/////////////////////////////////////////////////////////
void
ExporterClass::Export_Dependency_File (void)
{
//
// Make a file that contains a list of all the W3D files that
// were part of this export
//
StringClass dep_filename = FilenameBase + ".dep";
StringClass dep_path = ::Make_Path (TempDirectory, dep_filename);
AssetDependencyManager::Save_Level_Dependencies (dep_path, m_AssetList);
//
// Add this file to the mix
//
MixFileCreator.Add_File (dep_path, ::Get_Filename_From_Path (dep_path));
return ;
}
/////////////////////////////////////////////////////////
//
// Export_Level_File
//
/////////////////////////////////////////////////////////
bool
ExporterClass::Export_Level_File (void)
{
//
// Create filenames for both the static and dynamic data
//
CString ldd_filename = FilenameBase + DYNAMIC_EXTENSION;
CString lsd_filename = FilenameBase + STATIC_EXTENSION;
//
// Save the LSD and LDD files to a temporary directory
//
SaveGameManager::Set_Map_Filename (lsd_filename);
SaveGameManager::Save_Level ();
SaveGameManager::Save_Game (ldd_filename, NULL);
//
// Now add these files to the mix file
//
CString lsd_path = Make_Path (TempDirectory, lsd_filename);
CString ldd_path = Make_Path (TempDirectory, ldd_filename);
MixFileCreator.Add_File (lsd_path, lsd_filename);
MixFileCreator.Add_File (ldd_path, ldd_filename);
return true;
}
/////////////////////////////////////////////////////////
//
// Export_Always_Files
//
/////////////////////////////////////////////////////////
void
ExporterClass::Export_Always_Files (LPCTSTR path)
{
CWaitCursor wait_cursor;
m_AssetList.Delete_All ();
//
// Does the path exist?
//
if (::GetFileAttributes (path) != 0xFFFFFFFF) {
//
// Get the base destination path
//
Path = path;
FilenameBase = ALWAYS_ROOT_NAME;
//
// Setup the temporary directory
//
Make_Temp_Directory ();
//
// Copy all the files used by the framework to the directory
//
STRING_LIST &global_list = ::Get_File_Mgr ()->Get_Global_Include_File_List ();
Process_Include_Files (global_list);
//
// Get the always dependency search list
//
STRING_LIST search_list;
CString always_dep_search_ini = ::Get_File_Mgr ()->Make_Full_Path (ALWAYS_DEP_INI_PATH);
::Get_File_Mgr ()->Build_Include_List (always_dep_search_ini, search_list);
//
// Find all the files in the search list and add them to a list
//
STRING_LIST file_list;
Build_File_List (search_list, file_list);
//
// Now add all the W3D files from the list to another list. *sigh*
//
DynamicVectorClass<StringClass> dep_list;
for (int index = 0; index < file_list.Count (); index ++) {
CString &filename = file_list[index];
if (::Is_W3D_Filename (filename)) {
dep_list.Add ((LPCTSTR)::Get_Filename_From_Path (filename));
}
}
//
// Make a file that contains a list of all these W3D files
//
AssetDependencyManager::Save_Always_Dependencies (TempDirectory, dep_list);
CString dep_file_path = Make_Path (TempDirectory, "always.dep");
MixFileCreator.Add_File (dep_file_path, "always.dep");
//
// Now build the mix file...
//
CString mix_filename = Make_Path (Path, ALWAYS_DATA_FILENAME);
MixFileCreator.Generate_Mix_File (mix_filename);
//
// Cleanup any temp files we needed
//
Delete_Temp_Directory ();
} else {
//
// Invalid file, let the user know
//
::Message_Box (::AfxGetMainWnd ()->m_hWnd, IDS_CANT_EXPORT_MSG, IDS_CANT_EXPORT_TITLE, MB_ICONERROR | MB_OK);
}
return ;
}
/////////////////////////////////////////////////////////
//
// Export_Level_Data
//
/////////////////////////////////////////////////////////
bool
ExporterClass::Export_Level_Data (void)
{
bool retval = true;
//
// Loop through all the files used by this level and copy them
// to the same directory that the level definition was saved in.
//
int count = ::Get_File_Mgr ()->Get_File_Count ();
for (int file_index = 0; file_index < count; file_index ++) {
//
// Build the complete paths of both the original file location and the new file location
//
CString file_path = ::Get_File_Mgr ()->Get_File_Name (file_index);
CString entry_name;
//
// Is this file's subdirectory important?
//
bool path_important = ::Get_File_Mgr ()->Is_File_Path_Important (file_index);
if (path_important) {
//
// Pre-pend the subdirectory name to form the entry name
//
CString sub_dir = ::Get_Subdir_From_Full_Path (file_path);
entry_name = Make_Path (sub_dir, ::Get_Filename_From_Path (file_path));
} else {
entry_name = ::Get_Filename_From_Path (file_path);
}
//
// Add this file to the mix file with the given name
//
MixFileCreator.Add_File (file_path, entry_name);
//
// Add this file to the level-asset list if its a W3D file
//
if (::Is_W3D_Filename (entry_name)) {
m_AssetList.Add ((LPCTSTR)::Get_Filename_From_Path (entry_name));
}
}
//
// Add the temp definition database
//
CString temp_db_filename = ::Get_File_Mgr ()->Make_Full_Path (TEMP_DB_PATH);
CString temp_db_name = FilenameBase + ".ddb";
MixFileCreator.Add_File (temp_db_filename, temp_db_name);
//
// Copy all the files used by the framework to the directory
//
STRING_LIST &level_list = ::Get_File_Mgr ()->Get_Include_File_List ();
Process_Include_Files (level_list);
return retval;
}
/////////////////////////////////////////////////////////
//
// Export_Database_Mix
//
/////////////////////////////////////////////////////////
void
ExporterClass::Export_Database_Mix (LPCTSTR path)
{
CWaitCursor wait_cursor;
m_AssetList.Delete_All ();
Path = path;
FilenameBase = "always.dbs";
//
// Setup the temporary directory
//
Make_Temp_Directory ();
//
// Export the definition databases
//
Export_Definition_Databases (true);
//
// Cleanup any temp files we needed
//
Delete_Temp_Directory ();
return ;
}
/////////////////////////////////////////////////////////
//
// Export_Definition_Databases
//
/////////////////////////////////////////////////////////
bool
ExporterClass::Export_Definition_Databases (bool use_temp_strings_library)
{
EditorMixFileCreator always_db_mix_creator;
//
// Save the preset library to the temp directory
//
PresetsFormClass *presets_form = ::Get_Presets_Form ();
if (presets_form != NULL) {
CString path = ::Make_Path (TempDirectory, "objects.ddb");
presets_form->Save_Presets (path, 0, false, false);
always_db_mix_creator.Add_File (path, ::Get_Filename_From_Path (path));
}
//
// Add the strings table
//
if (use_temp_strings_library == false) {
CString filename = ::Get_File_Mgr ()->Make_Full_Path (STRINGS_DB_PATH);
always_db_mix_creator.Add_File (filename, ::Get_Filename_From_Path (filename));
} else {
//
// Save the strings table to the temporary directory, then
// add it to the mix file
//
CString path = ::Make_Path (TempDirectory, STRINGS_DB_NAME);
StringsMgrClass::Save_Translation_Database (path);
always_db_mix_creator.Add_File (path, STRINGS_DB_NAME);
}
//
// Add the global conversation database
//
CString filename = ::Get_File_Mgr ()->Make_Full_Path (CONV_DB_PATH);
always_db_mix_creator.Add_File (filename, ::Get_Filename_From_Path (filename));
//
// Now generate the definition databases mix file
//
CString mix_filename = ::Make_Path (Path, ALWAYS_DB_FILENAME);
always_db_mix_creator.Generate_Mix_File (mix_filename);
return true;
}
/////////////////////////////////////////////////////////
//
// Build_File_List
//
/////////////////////////////////////////////////////////
bool
ExporterClass::Build_File_List (const STRING_LIST &search_list, STRING_LIST &file_list)
{
bool retval = true;
//
// Loop through all the files in our include list
//
for (int index = 0; index < search_list.Count (); index ++) {
CString wildcard = search_list[index];
CString search = ::Get_File_Mgr ()->Make_Full_Path (wildcard);
//
// Make sure we have all the assets for this always group
//
if (DontGetVersionsFromVSS == false) {
::Get_File_Mgr ()->Get_Subproject (::Strip_Filename_From_Path (wildcard));
}
//
// Add the all the files that match the search mask to this list
//
Find_Files (search, file_list);
}
return retval;
}
/////////////////////////////////////////////////////////
//
// Find_Files
//
/////////////////////////////////////////////////////////
void
ExporterClass::Find_Files (const char *search_mask, STRING_LIST &file_list)
{
//
// Get the directory where we'll be copying the files from
//
CString directory = ::Strip_Filename_From_Path (search_mask);
CString mask = ::Get_Filename_From_Path (search_mask);
//
// Find all files that match this wildcard
//
WIN32_FIND_DATA find_info = { 0 };
BOOL keep_going = TRUE;
for (HANDLE hfile_find = ::FindFirstFile (search_mask, &find_info);
(hfile_find != INVALID_HANDLE_VALUE) && keep_going;
keep_going = ::FindNextFile (hfile_find, &find_info))
{
//
// Don't do this if its a directory
//
if (!(find_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
//
// Add this file to the list
//
CString full_path = Make_Path (directory, ::Get_Filename_From_Path (find_info.cFileName));
file_list.Add (full_path);
}
}
if (hfile_find != INVALID_HANDLE_VALUE) {
::FindClose (hfile_find);
}
CString full_search_mask = Make_Path (directory, "*.*");
//
// Now recurse into any sub-directories
//
keep_going = TRUE;
for (hfile_find = ::FindFirstFile (full_search_mask, &find_info);
(hfile_find != INVALID_HANDLE_VALUE) && keep_going;
keep_going = ::FindNextFile (hfile_find, &find_info))
{
//
// Don't do this if its a directory
//
if ((find_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && (find_info.cFileName[0] != '.')) {
//
// Build a search mask for this sub-directory
//
CString full_path = Make_Path (directory, ::Get_Filename_From_Path (find_info.cFileName));
full_path = Make_Path (full_path, mask);
//
// Recurse into this sub-directory
//
Find_Files (full_path, file_list);
}
}
if (hfile_find != INVALID_HANDLE_VALUE) {
::FindClose (hfile_find);
}
return ;
}
/////////////////////////////////////////////////////////
//
// Process_Include_Files
//
/////////////////////////////////////////////////////////
void
ExporterClass::Process_Include_Files (const STRING_LIST &search_list)
{
STRING_LIST file_list;
Build_File_List (search_list, file_list);
Export_Include_Files (file_list);
return ;
}
/////////////////////////////////////////////////////////
//
// Export_Include_Files
//
/////////////////////////////////////////////////////////
bool
ExporterClass::Export_Include_Files (const STRING_LIST &file_list)
{
//
// Add all the files from the list
//
for (int index = 0; index < file_list.Count (); index ++) {
const CString &full_path = file_list[index];
//
// Add this file to the mix file
//
MixFileCreator.Add_File (full_path, ::Get_Filename_From_Path (full_path));
//
// Add this file to the level-asset list if its a W3D file
//
if (::Is_W3D_Filename (full_path)) {
m_AssetList.Add ((LPCTSTR)::Get_Filename_From_Path (full_path));
}
}
return true;
}
////////////////////////////////////////////////////////////////////////////
//
// Delete_File
//
////////////////////////////////////////////////////////////////////////////
bool
ExporterClass::Delete_File (LPCTSTR filename)
{
bool retval = false;
ASSERT (filename != NULL);
if (filename != NULL) {
//
// Strip the readonly bit off if necessary
//
DWORD attributes = ::GetFileAttributes (filename);
if ((attributes != 0xFFFFFFFF) &&
((attributes & FILE_ATTRIBUTE_READONLY) == FILE_ATTRIBUTE_READONLY))
{
::SetFileAttributes (filename, attributes & (~FILE_ATTRIBUTE_READONLY));
}
//
// Perform the delete operation!
//
if ((attributes != 0xFFFFFFFF) &&
((attributes & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY))
{
retval = (::RemoveDirectory (filename) == TRUE);
} else {
retval = (::DeleteFile (filename) == TRUE);
}
}
return retval;
}
//////////////////////////////////////////////////////////////////////////////////
//
// Clean_Directory
//
//////////////////////////////////////////////////////////////////////////////////
bool
ExporterClass::Clean_Directory (LPCTSTR local_dir)
{
bool retval = true;
//
// Build a search mask from the directory
//
CString search_mask = CString (local_dir) + "\\*.*";
//
// Loop through all the files in this directory and add them
// to our list
//
DynamicVectorClass<CString> file_list;
BOOL keep_going = TRUE;
WIN32_FIND_DATA find_info = { 0 };
for (HANDLE hfind = ::FindFirstFile (search_mask, &find_info);
(hfind != INVALID_HANDLE_VALUE) && keep_going;
keep_going = ::FindNextFile (hfind, &find_info))
{
//
// If this file isn't a directory, add it to the list
//
if (!(find_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
CString filename = find_info.cFileName;
file_list.Add (filename);
} else if (find_info.cFileName[0] != '.') {
//
// Recurse into this subdirectory
//
CString full_path = local_dir;
::Delimit_Path (full_path);
full_path += find_info.cFileName;
Clean_Directory (full_path);
//
// Add this directory to the list so it will get
// deleted with the files...
//
CString filename = find_info.cFileName;
file_list.Add (filename);
}
}
//
// Close the search handle
//
if (hfind != NULL) {
::FindClose (hfind);
}
//
// Now loop through all the files and delete them
//
for (int index = 0; index < file_list.Count (); index ++) {
CString &filename = file_list[index];
CString full_path = ::Make_Path (local_dir, filename);
Delete_File (full_path);
}
return retval;
}
//////////////////////////////////////////////////////////////////////////////////
//
// Pre_Level_Export
//
//////////////////////////////////////////////////////////////////////////////////
void
ExporterClass::Pre_Level_Export (DynamicVectorClass<NodeClass *> &node_list)
{
//
// Force static anim phys to be displayed
//
::Get_Scene_Editor ()->Display_Static_Anim_Phys (true);
::Get_Scene_Editor ()->Display_Editor_Objects (true);
//
// Make sure the scenes are repartitioned
// (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 ();
::Get_Scene_Editor ()->Set_Selection (NULL);
::Get_Scene_Editor ()->Display_Vis_Points (false);
//
// Make sure the buildings are in a good state
//
GameObjManager::Update_Building_Collection_Spheres ();
GameObjManager::Init_Buildings ();
//
// Let the nodes know we are about to start exporting them.
// This way they can remove any 'editor-only' artifacts from
// the system.
//
NodeMgrClass::Build_Full_Node_List (node_list);
for (int index = 0; index < node_list.Count (); index ++) {
node_list[index]->Pre_Export ();
}
//
// Force the pathfind system to use any available waypath data
// in its evaluation
//
PathfindClass::Get_Instance ()->Generate_Waypath_Sectors_And_Portals ();
return ;
}
//////////////////////////////////////////////////////////////////////////////////
//
// Post_Level_Export
//
//////////////////////////////////////////////////////////////////////////////////
void
ExporterClass::Post_Level_Export (DynamicVectorClass<NodeClass *> &node_list)
{
//
// Let the nodes know we're done exporting
//
for (int index = 0; index < node_list.Count (); index ++) {
NodeClass *node = node_list[index];
node->Post_Export ();
}
return ;
}
/////////////////////////////////////////////////////////
//
// Export_Package
//
/////////////////////////////////////////////////////////
void
ExporterClass::Export_Package (LPCTSTR full_path)
{
CWaitCursor wait_cursor;
//
// Save the preset changes to disk as necessary
//
if (PresetMgrClass::Are_Presets_Dirty ()) {
PresetMgrClass::Check_In_Presets ();
}
//
// Get the base destination path
//
Path = ::Strip_Filename_From_Path (full_path);
//
// Strip the path and extension from the filename to give
// us a base for use with other filenames
//
FilenameBase = ::Get_Filename_From_Path (full_path);
int extension_index = FilenameBase.ReverseFind ('.');
if (extension_index != -1) {
FilenameBase = FilenameBase.Left (extension_index);
}
//
// Add all the files from our asset tree to this package
//
Add_Files_To_Mod_Package (AssetPackageMgrClass::Get_Current_Package_Path ());
//
// Create the mix file...
//
MixFileCreator.Generate_Mix_File (full_path);
//
// Cache the directory path we just exported into
//
theApp.WriteProfileString (CONFIG_KEY, LAST_EXPORT_DIR_VALUE, Path);
return ;
}
/////////////////////////////////////////////////////////
//
// Add_Files_To_Mod_Package
//
/////////////////////////////////////////////////////////
void
ExporterClass::Add_Files_To_Mod_Package (LPCTSTR full_path)
{
//
// Build a search path for all the files in this directory
//
CString search_path = ::Make_Path (full_path, "*.*");
//
// Search for all the files in this directory
//
WIN32_FIND_DATA find_info = { 0 };
BOOL keep_going = TRUE;
HANDLE file_find = NULL;
for (file_find = ::FindFirstFile (search_path, &find_info);
(file_find != INVALID_HANDLE_VALUE) && keep_going;
keep_going = ::FindNextFile (file_find, &find_info))
{
if (find_info.cFileName[0] != '.') {
if ((find_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY) {
//
// Recurse into this sub-directory
//
CString subdir_path = ::Make_Path (full_path, find_info.cFileName);
Add_Files_To_Mod_Package (subdir_path);
} else {
//
// Skip all lvl files
//
if (::strstr (find_info.cFileName, ".lvl") == NULL) {
//
// Simply add this file to the mix
//
CString file_path = ::Make_Path (full_path, find_info.cFileName);
MixFileCreator.Add_File (file_path, find_info.cFileName);
}
}
}
}
//
// Close the search handle
//
if (file_find != INVALID_HANDLE_VALUE) {
::FindClose (file_find);
}
return ;
}
/////////////////////////////////////////////////////////
//
// Export_Level_Only
//
/////////////////////////////////////////////////////////
void
ExporterClass::Export_Level_Only (LPCTSTR path)
{
CWaitCursor wait_cursor;
m_AssetList.Delete_All ();
//
// Prepare the level for exporting...
//
DynamicVectorClass<NodeClass *> node_list;
Pre_Level_Export (node_list);
//
// Get the base destination path
//
Path = ::Strip_Filename_From_Path (path);
TempDirectory = Path;
::Set_Current_Directory (TempDirectory);
::SetCurrentDirectory (TempDirectory);
//
// Strip the path and extension from the filename to give
// us a base for use with other filenames
//
FilenameBase = ::Get_Filename_From_Path (path);
int extension_index = FilenameBase.ReverseFind ('.');
if (extension_index != -1) {
FilenameBase = FilenameBase.Left (extension_index);
}
//
// Export the level in game format
//
Export_Level_File ();
//
// Add the temp definition database
//
CString temp_db_source = ::Get_File_Mgr ()->Make_Full_Path (TEMP_DB_PATH);
CString temp_db_dest = ::Make_Path(Path,FilenameBase + ".ddb");
::CopyFile(temp_db_source,temp_db_dest,false);
//
// Resetore the level after exporting
//
Post_Level_Export (node_list);
//
// Cache the directory path we just exported into
//
theApp.WriteProfileString (CONFIG_KEY, LAST_EXPORT_DIR_VALUE, Path);
return ;
}