| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573 |
- /*
- ** 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/FileMgr.cpp $*
- * *
- * Author:: Patrick Smith *
- * *
- * $Modtime:: 1/29/02 2:59p $*
- * *
- * $Revision:: 36 $*
- * *
- *---------------------------------------------------------------------------------------------*
- * Functions: *
- * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
- #include "stdafx.h"
- #include "filemgr.h"
- #include "utils.h"
- #include "rendobj.h"
- #include "matinfo.h"
- #include "regkeys.h"
- #include "leveledit.h"
- #include "_assetmgr.h"
- #include "editorassetmgr.h"
- #include "updatingdbdialog.h"
- #include "uniquelist.h"
- #include "part_emt.h"
- #include "filelocations.h"
- #include "editorini.h"
- #include "ffactory.h"
- #include "ww3d.h"
- #include "node.h"
- #include "preset.h"
- #include "presetmgr.h"
- #include "spawnernode.h"
- #include "wwstring.h"
- #include "vssclass.h"
- #include "assetdatabase.h"
- #include "editorbuild.h"
- #include "assetpackagemgr.h"
- #include "mixfiledatabase.h"
- ////////////////////////////////////////////////////////////////////////
- // Constants
- ////////////////////////////////////////////////////////////////////////
- const char *SPECIAL_USER_NAME = "Artist";
- const char *SPECIAL_USER_FOLDER = "<Artist Tests>";
- const char *PROXY_TESTS_FOLDER = "<Proxy Tests>";
- ////////////////////////////////////////////////////////////////////////
- // Static member initialization
- ////////////////////////////////////////////////////////////////////////
- bool FileMgrClass::_bAutoUpdateOn = false;
- ////////////////////////////////////////////////////////////////////////
- //
- // FileMgrClass
- //
- ////////////////////////////////////////////////////////////////////////
- FileMgrClass::FileMgrClass (void)
- : m_bVSSInitialized (false),
- m_bReadOnlyVSS (true),
- m_IsSpecialUser (false)
- {
- #ifdef PUBLIC_EDITOR_VER
- //
- // Allocate the database interface layer we'll need to access assets
- //
- m_DatabaseInterface = new MixFileDatabaseClass;
- //
- // Get the asset directory from the asset package manager
- //
- m_BasePath = AssetPackageMgrClass::Get_Current_Package_Path ();
- #else
-
- //
- // Allocate the database interface layer we'll need to access assets
- //
- m_DatabaseInterface = new VSSClass;
- //
- // Read the asset directory from the registry
- //
- m_BasePath = theApp.GetProfileString (CONFIG_KEY, ASSET_DIR_VALUE);
- #endif //PUBLIC_EDITOR_VER
- //
- // Ensure the base has a directory delimiter on the end
- //
- if ((m_BasePath.GetLength () > 0) &&
- m_BasePath[::lstrlen (m_BasePath) - 1] != '\\')
- {
- m_BasePath += "\\";
- }
- //
- // The new cache directory is simply a subdirectory of the base
- //
- m_TextureCachePath = m_BasePath + "EditorCache";
- if (::GetFileAttributes (m_TextureCachePath) == 0xFFFFFFFF) {
- ::CreateDirectory (m_TextureCachePath, NULL);
- }
- return ;
- }
- ////////////////////////////////////////////////////////////////////////
- //
- // Initialize
- //
- ////////////////////////////////////////////////////////////////////////
- void
- FileMgrClass::Initialize (void)
- {
- Free_Data ();
- return ;
- }
- ////////////////////////////////////////////////////////////////////////
- //
- // Free_Data
- //
- ////////////////////////////////////////////////////////////////////////
- void
- FileMgrClass::Free_Data (void)
- {
- // Loop through all the files in our array
- for (int index = 0; index < m_FileList.Count (); index ++) {
-
- // Free this entry
- LevelFileStruct *pentry = m_FileList[index];
- SAFE_DELETE (pentry);
- }
-
- // Remove all the entries from our list.
- m_FileList.Delete_All ();
- return ;
- }
- ////////////////////////////////////////////////////////////////////////
- //
- // Make_Full_Path
- //
- ////////////////////////////////////////////////////////////////////////
- CString
- FileMgrClass::Make_Full_Path (LPCTSTR rel_path)
- {
- CString full_path = rel_path;
- // Is this path really relative?
- if (::Is_Path_Relative (rel_path)) {
-
- // Strip of the preceding directory delimiter if there is one.
- if ((full_path.GetLength () > 0) && (full_path[0] == '\\')) {
- full_path = &(((LPCTSTR)full_path)[1]);
- }
- // Return the full path
- full_path = m_BasePath + rel_path;
-
- // Strip off the last delimiter if necessary
- if (full_path[::lstrlen (full_path) - 1] == '\\') {
- full_path = full_path.Left (full_path.GetLength () - 1);
- }
- }
- // Return a string which contains the full path to the data file
- return full_path;
- }
- ////////////////////////////////////////////////////////////////////////
- //
- // Make_Relative_Path
- //
- ////////////////////////////////////////////////////////////////////////
- CString
- FileMgrClass::Make_Relative_Path (LPCTSTR full_path)
- {
- CString base_path = m_BasePath;
- CString lower_path = full_path;
- lower_path.MakeLower ();
- base_path.MakeLower ();
- LPCTSTR rel_path = lower_path;
- // Is our 'base' part of the full path?
- if (::strstr (rel_path, base_path) == rel_path) {
- // The relative path is the full path minus the base path
- rel_path += m_BasePath.GetLength ();
-
- // Strip of the preceding directory delimiter if there is one.
- if (rel_path[0] == '\\') {
- rel_path = &(((LPCTSTR)rel_path)[1]);
- }
- }
- // Return a string which contains the relative path to the data file
- return CString (rel_path);
- }
- ////////////////////////////////////////////////////////////////////////
- //
- // Is_Empty_Path
- //
- ////////////////////////////////////////////////////////////////////////
- bool
- FileMgrClass::Is_Empty_Path (LPCTSTR path)
- {
- bool retval = true;
- if (path[0] != 0) {
- CString temp1 = path;
- CString temp2 = m_BasePath;
- ::Delimit_Path (temp1);
- ::Delimit_Path (temp2);
- retval = bool(::stricmp (temp1, temp2) == 0);
- }
- return retval;
- }
- ////////////////////////////////////////////////////////////////////////
- //
- // Is_Path_Valid
- //
- ////////////////////////////////////////////////////////////////////////
- bool
- FileMgrClass::Is_Path_Valid (LPCTSTR path)
- {
- // The path is valid if its located under the asset tree
- return bool(::strnicmp (path, m_BasePath, m_BasePath.GetLength ()) == 0);
- }
- ////////////////////////////////////////////////////////////////////////
- //
- // Is_Path_In_Asset_Tree
- //
- ////////////////////////////////////////////////////////////////////////
- bool
- FileMgrClass::Is_Path_In_Asset_Tree (LPCTSTR path)
- {
- CString full_path = Make_Full_Path (path);
- return bool(::strnicmp (full_path, m_BasePath, m_BasePath.GetLength ()) == 0);
- }
- ////////////////////////////////////////////////////////////////////////
- //
- // Does_File_Exist
- //
- ////////////////////////////////////////////////////////////////////////
- bool
- FileMgrClass::Does_File_Exist
- (
- LPCTSTR filename,
- bool update_from_vss
- )
- {
- // Assume it doesn't exist
- bool file_exists = false;
- // Param valid?
- ASSERT (filename != NULL);
- if (filename != NULL) {
- // Ensure the path is complete
- CString path = Make_Full_Path (filename);
- file_exists = bool(::GetFileAttributes (path) != 0xFFFFFFFF);
- #ifndef PUBLIC_EDITOR_VER
- //
- // Should we try to get this file from VSS?
- //
- if (update_from_vss && (file_exists == false)) {
-
- //
- // If the file is in VSS, then get it and return the success code
- //
- if (Is_File_In_VSS (path)) {
- file_exists = Update_File (path);
- }
- }
- #endif //!PUBLIC_EDITOR_VER
- }
- // Return the true/false result code
- return file_exists;
- }
- /////////////////////////////////////////////////////////////////
- //
- // Find_File
- //
- /////////////////////////////////////////////////////////////////
- int
- FileMgrClass::Find_File (LPCTSTR filename) const
- {
- // Assume failure
- int index = -1;
- // Can we add another property to our list?
- ASSERT (filename != NULL);
- if (filename != NULL) {
- // Loop through all the files in our array
- for (int file_index = 0;
- (file_index < m_FileList.Count ()) && (index == -1);
- file_index ++) {
- // Was this the file we were looking for?
- if (::lstrcmpi (m_FileList[file_index]->m_Filename, filename) == 0) {
- index = file_index;
- }
- }
- }
- // Return the file's index (-1) on error
- return index;
- }
- /////////////////////////////////////////////////////////////////
- //
- // Remove_File
- //
- /////////////////////////////////////////////////////////////////
- bool
- FileMgrClass::Remove_File (int index)
- {
- // Assume failure
- bool retval = false;
- // Param valid?
- if ((index >= 0) && (index < m_FileList.Count ())) {
-
- // Decrement the ref count on this entry
- LevelFileStruct *pentry = m_FileList[index];
- pentry->m_RefCount --;
- // Do we need to remove this item from the list?
- if (pentry->m_RefCount == 0) {
-
- // Free the memory used by this entry and remove it
- // from the list
- SAFE_DELETE (pentry);
- m_FileList.Delete (index);
- }
- // Success!
- retval = true;
- }
- // Return the true/false result code
- return retval;
- }
- /////////////////////////////////////////////////////////////////
- //
- // Add_Files_To_Database
- //
- /////////////////////////////////////////////////////////////////
- bool
- FileMgrClass::Add_Files_To_Database (LPCTSTR filename)
- {
- // Assume success
- //bool retval = true;
- ASSERT (filename != NULL);
- m_CurrentFile = filename;
- Add_Files_To_Database ();
- // Return the true/false success code
- return true;
- }
- /////////////////////////////////////////////////////////////////
- //
- // Add_File_To_Database
- //
- /////////////////////////////////////////////////////////////////
- bool
- FileMgrClass::Add_File_To_Database (LPCTSTR filename)
- {
- CString path = Make_Full_Path (filename);
- if (Does_File_Exist (path) &&
- (m_DatabaseInterface->Does_File_Exist (path) == false))
- {
- m_DatabaseInterface->Add_File (path);
- }
- return true;
- }
- /////////////////////////////////////////////////////////////////
- //
- // Add_Files_To_Database
- //
- /////////////////////////////////////////////////////////////////
- void
- FileMgrClass::Add_Files_To_Database (void)
- {
- // Build a unique list of dependencies on this W3D file
- UniqueListClass<CString> unique_list;
- //
- // If this is a W3D model, enumerate its dependencies, otherwise
- // just add it to the list
- //
- if (::Is_W3D_Filename (m_CurrentFile)) {
- Build_Dependency_List (m_CurrentFile, unique_list);
- } else {
- unique_list.Add (Make_Full_Path (m_CurrentFile));
- }
- CString current_dir = ::Strip_Filename_From_Path (m_CurrentFile);
- current_dir = Make_Full_Path (current_dir);
-
- //
- // Now loop through all the files in the unique list and
- // add them to VSS.
- //
- for (int index = 0; index < unique_list.Count (); index ++) {
- CString full_path = unique_list[index];
-
- //
- // Does this file live outside of our asset tree?
- //
- if (Is_Path_In_Asset_Tree (full_path) == false) {
-
- CString filename = ::Get_Filename_From_Path (full_path);
- CString local_path = ::Make_Path (current_dir, filename);
- //
- // Copy the file to the asset tree
- //
- if (::Quick_Compare_Files (full_path, local_path) != 0) {
- ::Copy_File (full_path, local_path, FALSE);
- }
-
- full_path = local_path;
- }
-
- //
- // Add this file to VSS (if needs be)
- //
- if (Does_File_Exist (full_path) &&
- (m_DatabaseInterface->Does_File_Exist (full_path) == false))
- {
- m_DatabaseInterface->Add_File (full_path);
- }
- }
- return ;
- }
- /////////////////////////////////////////////////////////////////
- //
- // Add_File
- //
- /////////////////////////////////////////////////////////////////
- int
- FileMgrClass::Add_File (LPCTSTR filename, bool subdir_important)
- {
- // Assume failure
- int index = -1;
- // Param valid?
- ASSERT (filename != NULL);
- if ((filename != NULL) && (index == -1)) {
- // Ensure the path is complete
- CString path = Make_Full_Path (filename);
- LevelFileStruct *pentry = NULL;
- // Is this file already in the list?
- index = Find_File (path);
- if (index == -1) {
-
- // Allocate a new entry for our list
- pentry = new LevelFileStruct;
- ASSERT (pentry != NULL);
- // Set the file information
- pentry->m_Filename = path;
- pentry->m_RefCount = 0;
-
- // Add this entry to the list
- m_FileList.Add (pentry);
- index = Find_File (path);
- } else {
- pentry = m_FileList[index];
- }
- //
- // Record whether or not we think the file's subdirectory
- // is important.
- //
- pentry->m_SubdirImportant |= subdir_important;
- // Increment the refcount on this entry
- pentry->m_RefCount ++;
- }
- // Return the index of the file
- return index;
- }
- /////////////////////////////////////////////////////////////////
- //
- // Update_Texture_Cache
- //
- /////////////////////////////////////////////////////////////////
- bool
- FileMgrClass::Update_Texture_Cache
- (
- LPCTSTR start_path,
- RenderObjClass *prender_obj
- )
- {
- // Assume failure
- bool retval = false;
- ASSERT (prender_obj != NULL);
- if (prender_obj != NULL) {
-
- // Assume success from here on out
- retval = true;
- // Generate a list of all the texture files required by this render object
- DynamicVectorClass<CString> texture_list;
- int count = Build_Texture_List (start_path, prender_obj, texture_list);
- // Loop through all the textures in our list and make sure the latest
- // version is in the cache directory
- for (int texture = 0; texture < count; texture ++) {
-
- // Should we now copy the texture file over?
- CString texture_file = texture_list[texture];
- if (::GetFileAttributes (texture_file) != 0xFFFFFFFF) {
-
- // Is the texture file newer than the one we have in the cache?
- CString cache_path = m_TextureCachePath + CString ("\\") + ::Get_Filename_From_Path (texture_file);
- if (::Quick_Compare_Files (texture_file, cache_path) > 0) {
-
- // Everything is in order, so copy the texture file to the cache
- retval &= ::Copy_File (texture_file, cache_path, FALSE);
- }
- }
- }
- }
-
- // Return the true/false result code
- return retval;
- }
- /////////////////////////////////////////////////////////////////
- //
- // Build_Texture_List
- //
- /////////////////////////////////////////////////////////////////
- int
- FileMgrClass::Build_Texture_List
- (
- LPCTSTR start_path,
- RenderObjClass *prender_obj,
- DynamicVectorClass<CString> &texture_list,
- bool brecurse
- )
- {
- // Param valid?
- ASSERT (prender_obj != NULL);
- if (prender_obj) {
- CString path = start_path;
- ::Delimit_Path (path);
- // Get a list of texture files from the render object
- DynamicVectorClass<StringClass> dependency_list;
- prender_obj->Build_Texture_List (dependency_list);
- // Loop through all the texture files and try to assign paths to each one.
- for (int index = 0; index < dependency_list.Count (); index ++) {
-
- // Build a full path to the current texture file
- const char *filename = dependency_list[index];
- CString full_path = path + CString (filename);
- full_path = ::Get_File_Mgr ()->Make_Full_Path (full_path);
- // Does the texture file exist in this location?
- if (Does_File_Exist (full_path) == false) {
- // Assume the texture file exists in the parent directory
- full_path = ::Up_One_Directory (::Strip_Filename_From_Path (full_path));
- ::Delimit_Path (full_path);
- full_path += filename;
- }
- // Add this texture file to the list
- texture_list.Add (full_path);
- }
- dependency_list.Delete_All ();
- }
- // Return the count of textures in the list
- return texture_list.Count ();
- }
- /////////////////////////////////////////////////////////////////
- //
- // Determine_File_Location
- //
- /////////////////////////////////////////////////////////////////
- bool
- FileMgrClass::Determine_File_Location (LPCTSTR full_path, CString &real_location)
- {
- bool retval = false;
- //
- // Does the file exist in this location?
- //
- if (Does_File_Exist (full_path) == false) {
- CString filename = ::Get_Filename_From_Path (full_path);
- CString parent_dir = ::Up_One_Directory (::Strip_Filename_From_Path (full_path));
- CString parent_path = ::Make_Path (parent_dir, filename);
- //
- // Does the file exist in the parent directory?
- //
- if (Does_File_Exist (parent_path) == false) {
-
- if (::Is_Texture_Filename (filename)) {
-
- //
- // Does this texture file exist in the global texture directory?
- //
- CString texture_path = ::Make_Path (GLOBAL_TEXTURE_PATH, filename);
- if (Does_File_Exist (texture_path)) {
- real_location = texture_path;
- retval = true;
- }
- }
- } else {
- real_location = parent_path;
- retval = true;
- }
- } else {
- real_location = full_path;
- retval = true;
- }
-
- return retval;
- }
- /////////////////////////////////////////////////////////////////
- //
- // Build_File_List
- //
- /////////////////////////////////////////////////////////////////
- void
- FileMgrClass::Build_File_List
- (
- LPCTSTR start_path,
- RenderObjClass * render_obj,
- FILE_LIST & file_list
- )
- {
- CString path = start_path;
- ::Delimit_Path (path);
- // Get a list of dependent files from the render object
- DynamicVectorClass<StringClass> dependency_list;
- render_obj->Build_Dependency_List (dependency_list);
- // Loop through all the files and try to assign paths to each one.
- for (int index = 0; index < dependency_list.Count (); index ++) {
-
- // Build a full path to the current file
- const char *filename = dependency_list[index];
- CString full_path = ::Make_Path (path, filename);
- full_path = Make_Full_Path (full_path);
- //
- // Record that the subdir where this file lives is important
- // IF the subdir is returned by the render object.
- //
- bool subdir_important = (::strstr (filename, "+\\") != NULL);
- //
- // Attempt to find the file
- //
- CString real_location = full_path;
- Determine_File_Location (full_path, real_location);
- //
- // Add this file to the list
- //
- file_list.Add (FileInfoStruct (real_location, subdir_important));
- }
- dependency_list.Delete_All ();
- return ;
- }
- /////////////////////////////////////////////////////////////////
- //
- // Initialize_VSS
- //
- /////////////////////////////////////////////////////////////////
- bool
- FileMgrClass::Initialize_VSS
- (
- LPCTSTR ini_file_path,
- LPCTSTR username,
- LPCTSTR password
- )
- {
- // Do we need to initialize the VSS database?
- if (m_bVSSInitialized == false) {
- // Attempt to open the database
- m_bVSSInitialized = m_DatabaseInterface->Open_Database (ini_file_path,
- username ? username : "User",
- password ? password : "");
-
- m_bReadOnlyVSS = (m_DatabaseInterface->Is_Read_Only () == TRUE);
- //
- // Is this a special user? A special user is someone who doesn't
- // have full write access to the database.
- //
- if (::lstrcmpi (username, SPECIAL_USER_NAME) == 0) {
- m_IsSpecialUser = true;
- }
- }
- // Return the true/false result code
- return m_bVSSInitialized;
- }
- /////////////////////////////////////////////////////////////////
- //
- // Is_File_In_VSS
- //
- /////////////////////////////////////////////////////////////////
- bool
- FileMgrClass::Is_File_In_VSS (LPCTSTR filename)
- {
- // Assume failure
- bool retval = false;
- // State OK?
- if (m_bVSSInitialized) {
- retval = m_DatabaseInterface->Does_File_Exist (filename);
- }
- // Return the true/false result code
- return retval;
- }
- /////////////////////////////////////////////////////////////////
- //
- // Build_Update_List
- //
- /////////////////////////////////////////////////////////////////
- int
- FileMgrClass::Build_Update_List (DynamicVectorClass<LevelFileStruct *> &update_list)
- {
- int count = 0;
- // State OK?
- ASSERT (m_bVSSInitialized);
- if (m_bVSSInitialized) {
- // Loop through all the files in our array
- for (int index = 0;
- index < m_FileList.Count ();
- index ++) {
-
- // Get a pointer to this entry
- LevelFileStruct *pentry = m_FileList[index];
-
- // Ask VSS if we need to update this file.
- if (m_DatabaseInterface->Is_File_Different (pentry->m_Filename)) {
- update_list.Add (pentry);
- }
- }
- }
- // Return the count of items we added to the list
- return count;
- }
- /////////////////////////////////////////////////////////////////
- //
- // Update_Files
- //
- /////////////////////////////////////////////////////////////////
- bool
- FileMgrClass::Update_Files (DynamicVectorClass<LevelFileStruct *> *pupdate_list)
- {
- // Asssume success
- bool retval = true;
- ASSERT (m_bVSSInitialized);
- // Do we need to build a list of files to generate ourselves?
- DynamicVectorClass<LevelFileStruct *> *plist = pupdate_list;
- if (plist == NULL) {
-
- // Create a new list object
- plist = new DynamicVectorClass<LevelFileStruct *>;
- ASSERT (plist != NULL);
- // Generate a list of files that need to be updated from VSS
- Build_Update_List (*plist);
- }
- // Loop through all the files in our array
- for (int index = 0;
- index < plist->Count ();
- index ++) {
-
- // Get a pointer to this entry
- LevelFileStruct *pentry = (*plist)[index];
-
- //
- // Get the latest version from VSS if we don't already have the file
- // checked out.
- //
- if (m_DatabaseInterface->Get_File_Status (pentry->m_Filename) != AssetDatabaseClass::CHECKED_OUT_TO_ME) {
- retval &= m_DatabaseInterface->Get (pentry->m_Filename);
- }
- }
- // Free the temporary list if we need to
- if (plist != pupdate_list) {
- SAFE_DELETE (plist);
- }
- // Return the true/false result code
- return retval;
- }
- /////////////////////////////////////////////////////////////////
- //
- // Update_File
- //
- /////////////////////////////////////////////////////////////////
- bool
- FileMgrClass::Update_File (int index)
- {
- // Asssume failure
- bool retval = false;
- // Param valid?
- if ((index >= 0) && (index < m_FileList.Count ())) {
-
- // Update the file using its filename
- retval = Update_File (m_FileList[index]->m_Filename);
- }
-
- // Return the true/false result code
- return retval;
- }
- /////////////////////////////////////////////////////////////////
- //
- // Update_File
- //
- /////////////////////////////////////////////////////////////////
- bool
- FileMgrClass::Update_File (LPCTSTR filename)
- {
- // Asssume failure
- bool retval = false;
- // State valid?
- ASSERT (filename != NULL);
- ASSERT (m_bVSSInitialized);
- if ((filename != NULL) && m_bVSSInitialized) {
-
- // Assume success from here on out
- retval = true;
- //
- // Ensure the path is complete for the file
- //
- CString path = Make_Full_Path (filename);
- //
- // Get the latest version from VSS if we don't already have the file
- // checked out.
- //
- if ( ::GetFileAttributes (path) == 0xFFFFFFFF ||
- m_DatabaseInterface->Get_File_Status (filename) != AssetDatabaseClass::CHECKED_OUT_TO_ME)
- {
- retval = m_DatabaseInterface->Get (path);
- }
- }
-
- // Return the true/false result code
- return retval;
- }
- /////////////////////////////////////////////////////////////////
- //
- // Update_All_Files
- //
- /////////////////////////////////////////////////////////////////
- bool
- FileMgrClass::Update_All_Files (LPCTSTR dest_path, LPCTSTR search_mask)
- {
- bool retval = false;
- // State valid?
- ASSERT (dest_path != NULL);
- ASSERT (m_bVSSInitialized);
- if ((dest_path != NULL) && m_bVSSInitialized) {
-
- //
- // Assume success from here on out
- //
- retval = m_DatabaseInterface->Get_All (dest_path, search_mask);
- }
-
- return retval;
- }
- /////////////////////////////////////////////////////////////////
- //
- // Get_Subproject
- //
- /////////////////////////////////////////////////////////////////
- bool
- FileMgrClass::Get_Subproject (LPCTSTR path)
- {
- // Asssume failure
- bool retval = false;
- // State valid?
- ASSERT (path != NULL);
- ASSERT (m_bVSSInitialized);
- if ((path != NULL) && m_bVSSInitialized) {
- // Ensure the path is complete for the file
- CString full_path = Make_Full_Path (path);
- // Get the files from VSS
- retval = m_DatabaseInterface->Get (full_path);
- }
- // Return the true/false result code
- return retval;
- }
- /////////////////////////////////////////////////////////////////
- //
- // Set_Base_Path
- //
- /////////////////////////////////////////////////////////////////
- void
- FileMgrClass::Set_Base_Path (LPCTSTR base)
- {
- // Store this base both in memory and in the registry
- m_BasePath = base;
- theApp.WriteProfileString (CONFIG_KEY, ASSET_DIR_VALUE, m_BasePath);
-
- // Ensure the directory is created
- if (Does_File_Exist (m_BasePath) == false) {
- ::CreateDirectory (base, NULL);
- }
- // Ensure the new base has a directory delimiter on the end
- if (m_BasePath[::lstrlen (m_BasePath) - 1] != '\\') {
- m_BasePath += "\\";
- }
- // The new cache directory is simply a subdirectory of the base
- m_TextureCachePath = m_BasePath + "EditorCache";
- if (::GetFileAttributes (m_TextureCachePath) == 0xFFFFFFFF) {
- ::CreateDirectory (m_TextureCachePath, NULL);
- }
- //
- // Add the texture cache to the search path
- //
- EditorFileFactoryClass::Add_Search_Path (m_TextureCachePath);
- return ;
- }
- /////////////////////////////////////////////////////////////////
- //
- // Find_Files
- //
- /////////////////////////////////////////////////////////////////
- void
- FileMgrClass::Find_Files
- (
- LPCTSTR start_path,
- LPCTSTR wildcard,
- DynamicVectorClass<CString> & file_list,
- bool recurse
- )
- {
- CString path = start_path;
- if (path[::lstrlen(path)-1] != '\\') {
- path += "\\";
- }
- // Build a file spec from the starting path and the wildcard
- CString file_spec = path + wildcard;
- // Find all files that match this wildcard
- WIN32_FIND_DATA find_info = { 0 };
- BOOL bcontinue = TRUE;
- for (HANDLE hfile_find = ::FindFirstFile (file_spec, &find_info);
- (hfile_find != INVALID_HANDLE_VALUE) && bcontinue;
- bcontinue = ::FindNextFile (hfile_find, &find_info)) {
- // Is this a file?
- if (!(find_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
-
- // Add this file to our list
- CString filename = path + find_info.cFileName;
- file_list.Add (filename);
- }
- }
-
- // Close the search handle
- ::FindClose (hfile_find);
- hfile_find = INVALID_HANDLE_VALUE;
- if (recurse) {
-
- // Process all the subdirs
- file_spec = path + "*.*";
- bcontinue = TRUE;
- for (hfile_find = ::FindFirstFile (file_spec, &find_info);
- (hfile_find != INVALID_HANDLE_VALUE) && bcontinue;
- bcontinue = ::FindNextFile (hfile_find, &find_info)) {
- // If this is a subdir, then recursively build the file list
- if ((find_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) &&
- (find_info.cFileName[0] != '.')){
- CString sub_dir = path + find_info.cFileName;
- Find_Files (sub_dir, wildcard, file_list, recurse);
- }
- }
- // Close the search handle
- ::FindClose (hfile_find);
- hfile_find = INVALID_HANDLE_VALUE;
- }
-
- return ;
- }
- /////////////////////////////////////////////////////////////////
- //
- // Update_Model
- //
- /////////////////////////////////////////////////////////////////
- bool
- FileMgrClass::Update_Model
- (
- LPCTSTR local_path,
- LPCTSTR new_filename
- )
- {
- // Assume failure
- bool retval = false;
- CWaitCursor wait_cursor;
- //
- // Display a dialog so the user doesn't close down the app
- //
- HWND hmain_wnd = ::AfxGetMainWnd ()->m_hWnd;
- HWND hupdate_dlg = ::Show_VSS_Update_Dialog (hmain_wnd);
- CString new_path = ::Strip_Filename_From_Path (new_filename);
- CString local_path_temp = local_path;
- ::Delimit_Path (local_path_temp);
- ::Delimit_Path (new_path);
- bool path_different = bool(::lstrcmpi (new_path, local_path_temp) != 0);
- //
- // Build a unique list of dependencies on this W3D file
- //
- UniqueListClass<CString> file_list;
- Build_Dependency_List (new_filename, file_list);
- //
- // Loop through all the files in our list
- //
- for (int index = 0; index < file_list.Count (); index ++) {
-
- // Get the full path, and its 2 components, of the current file.
- CString &full_path = file_list[index];
- CString path = ::Strip_Filename_From_Path (full_path);
- CString filename = ::Get_Filename_From_Path (full_path);
- // The local version (in our asset tree) of this file should exist here.
- CString local_file = local_path_temp + filename;
- //
- // Check to see if we need to maintain this file's subdirectory...
- //
- bool subdir_important = (::strstr (full_path, "+\\") != NULL);
- if (subdir_important) {
- //
- // Ensure the subdirectory exists
- //
- CString sub_dir = local_path_temp + ::Get_Subdir_From_Full_Path (full_path);
- ::Create_Dir_If_Necessary (sub_dir);
- //
- // Build a path where the destination file lives in the sub-dir
- //
- local_file = sub_dir + CString ("\\") + filename;
- }
-
- //
- // Attempt to check out the latest version of this file
- //
- bool need_checkin = m_DatabaseInterface->Check_Out (local_file, false);
- //
- // If this file is newer than its local counterpart, copy it!
- //
- //if (path_different && ::Quick_Compare_Files (full_path, local_file) > 0) {
- if (path_different) {
- ::Copy_File (full_path, local_file, true);
- }
- //
- // Should we add this file to VSS, or update the existing?
- //
- if (need_checkin == false) {
- m_DatabaseInterface->Add_File (local_file);
- } else {
- m_DatabaseInterface->Check_In (local_file);
- }
- }
- // Remove the updating dialog
- ::Kill_VSS_Update_Dialog (hupdate_dlg);
- return retval;
- }
- /////////////////////////////////////////////////////////////////
- //
- // Build_Dependency_List
- //
- /////////////////////////////////////////////////////////////////
- void
- FileMgrClass::Build_Dependency_List
- (
- LPCTSTR asset_filename,
- UniqueListClass<CString> & list
- )
- {
- CString full_path = Make_Full_Path (asset_filename);
- CString path = ::Strip_Filename_From_Path (full_path);
- CString filename = ::Get_Filename_From_Path (asset_filename);
- CString asset_name = ::Asset_Name_From_Filename (filename);
- // Create an instance of the model so we can enumerate all the other
- // files this model is dependant on
- _pThe3DAssetManager->Set_Current_Directory (path);
- RenderObjClass *render_obj = _pThe3DAssetManager->Create_Render_Obj (asset_name);
- if (render_obj != NULL) {
- // Build a list of all the files used by this render object
- FILE_LIST file_list;
- Build_File_List (path, render_obj, file_list);
- // Make a unique list out of the file list
- for (int index = 0; index < file_list.Count (); index ++) {
- FileInfoStruct &info = file_list[index];
- list.Add_Unique (info.m_Filename);
- }
- // Free the temporary render object
- MEMBER_RELEASE (render_obj);
- } else {
-
- //
- // This wasn't a render object file (could of been an animation), so
- // just add the file to the list (no other dependencies).
- //
- list.Add (full_path);
- }
- return ;
- }
- /////////////////////////////////////////////////////////////////
- //
- // Update_Asset_Tree
- //
- /////////////////////////////////////////////////////////////////
- bool
- FileMgrClass::Update_Asset_Tree (void)
- {
- return m_DatabaseInterface->Get_Subproject (m_BasePath);
- }
- /////////////////////////////////////////////////////////////////
- //
- // Build_Global_Include_List
- //
- void
- FileMgrClass::Build_Global_Include_List (void)
- {
- // Ensure we have the latest copy from VSS
- Update_File (ALWAYS_INI_PATH);
- // Build the global include list
- Build_Include_List (ALWAYS_INI_PATH, m_GlobalIncludeFiles);
- return ;
- }
- /////////////////////////////////////////////////////////////////
- //
- // Build_Include_List
- //
- /////////////////////////////////////////////////////////////////
- void
- FileMgrClass::Build_Include_List
- (
- LPCTSTR ini_filename,
- DynamicVectorClass<CString> &list
- )
- {
- // Start with a fresh list of files
- list.Delete_All ();
- // Get a pointer to the INI file from the asset manager
- CString ini_path = Make_Full_Path (ini_filename);
- EditorINIClass *pini = _pThe3DAssetManager->Get_INI (ini_path);
-
- // Were we successful in getting a pointer to the INI file?
- ASSERT (pini != NULL);
- if (pini != NULL) {
- // Loop through all the assets in the ini file
- int instance_count = pini->Entry_Count ("Assets");
- for (int index = 0; index < instance_count; index ++) {
-
- // Get the current file spec from the INI
- TCHAR filespec[MAX_PATH];
- pini->Get_String ("Assets",
- pini->Get_Entry ("Assets", index),
- "",
- filespec,
- sizeof (filespec));
- // Add the filespec to our list
- list.Add (filespec);
- }
-
- // Free the INI object
- SAFE_DELETE (pini);
- }
-
- return ;
- }
- /////////////////////////////////////////////////////////////////
- //
- // Update_Global_Include_File_List
- //
- /////////////////////////////////////////////////////////////////
- bool
- FileMgrClass::Update_Global_Include_File_List (void)
- {
- bool retval = false;
- // Attempt to checkout the INI file
- CString ini_path = Make_Full_Path (ALWAYS_INI_PATH);
- if (m_DatabaseInterface->Retry_Check_Out (ini_path, 10, 1000)) {
- // Create the INI file from our in-memory list
- EditorINIClass ini_file;
- for (int index = 0; index < m_GlobalIncludeFiles.Count (); index ++) {
- CString index_string;
- index_string.Format ("%d", index + 1);
- ini_file.Put_String ("Assets", index_string, (LPCTSTR)m_GlobalIncludeFiles[index]);
- }
- // Save the INI file
- FileClass * pini_file = _TheFileFactory->Get_File (ini_path);
- if (pini_file) {
- ini_file.Save (*pini_file);
- _TheFileFactory->Return_File (pini_file);
- }
- // Now check the INI file back in
- retval = m_DatabaseInterface->Retry_Check_In (ini_path, 10, 1000);
- }
- // Reutrn the true/false result code
- return retval;
- }
- /////////////////////////////////////////////////////////////////
- //
- // Update
- //
- /////////////////////////////////////////////////////////////////
- void
- FileMgrClass::Update (NodeClass *node, bool add_node)
- {
- //
- // Update the files this preset is dependent on
- //
- PresetClass *preset = node->Get_Preset ();
- if (preset != NULL) {
- Update (preset, add_node);
- }
- //
- // If this is a spawner, then update the files
- // its spawned object is dependent on as well.
- //
- if (node->Get_Type () == NODE_TYPE_SPAWNER) {
- SpawnerDefClass *definition = static_cast<SpawnerDefClass *> (preset->Get_Definition ());
- if (definition != NULL) {
- //
- // Loop over all the possible spawned objects and make sure to load their assets
- //
- const DynamicVectorClass<int> &list = definition->Get_Spawn_Definition_ID_List ();
- for (int index = 0; index < list.Count (); index ++) {
- PresetClass *preset = PresetMgrClass::Find_Preset (list[index]);
- if (preset != NULL) {
- Update (preset, add_node);
- }
- }
- }
- }
- return ;
- }
- /////////////////////////////////////////////////////////////////
- //
- // Update
- //
- /////////////////////////////////////////////////////////////////
- void
- FileMgrClass::Update (PresetClass *preset, bool add_node)
- {
- //
- // Get the list of dependencies from the preset
- //
- STRING_LIST file_list;
- preset->Get_All_Dependencies (file_list);
-
- //
- // Loop through all the files this preset is dependent on
- //
- for (int index = 0; index < file_list.Count (); index ++) {
- CString filename = file_list[index];
-
- if (Is_Empty_Path (filename) == false)
- {
- if (add_node) {
- Add_Asset (filename);
- } else {
- Remove_Asset (filename);
- }
- }
- }
- return ;
- }
- /////////////////////////////////////////////////////////////////
- //
- // Add_Asset
- //
- /////////////////////////////////////////////////////////////////
- void
- FileMgrClass::Add_Asset (LPCTSTR filename)
- {
- RenderObjClass *render_obj = NULL;
- //
- // If this is a render object, then build a list of
- // dependencies
- //
- if (::Is_W3D_Filename (filename)) {
- CString asset_name = ::Asset_Name_From_Filename (filename);
- render_obj = ::Create_Render_Obj (asset_name);
- }
- if (render_obj != NULL) {
- //
- // Build a list of all the files used by this render object
- //
- CString full_path = Make_Full_Path (filename);
- CString start_path = ::Strip_Filename_From_Path (full_path);
- FILE_LIST file_list;
- Build_File_List (start_path, render_obj, file_list);
- // Loop through all the files in the list and add them to our internal
- // list (or update its ref count if its already there)
- for (int index = 0; index < file_list.Count (); index ++) {
- FileInfoStruct &info = file_list[index];
- Add_File (Make_Full_Path (info.m_Filename), info.m_SubdirImportant);
- }
- MEMBER_RELEASE (render_obj);
- } else {
- Add_File (Make_Full_Path (filename), false);
- }
- return ;
- }
- /////////////////////////////////////////////////////////////////
- //
- // Remove_Asset
- //
- /////////////////////////////////////////////////////////////////
- void
- FileMgrClass::Remove_Asset (LPCTSTR filename)
- {
- RenderObjClass *render_obj = NULL;
- //
- // If this is a render object, then build a list of
- // dependencies
- //
- if (::Is_W3D_Filename (filename)) {
- CString asset_name = ::Asset_Name_From_Filename (filename);
- render_obj = ::Create_Render_Obj (asset_name);
- }
- if (render_obj != NULL) {
- // Build a list of all the files used by this render object
- CString full_path = Make_Full_Path (filename);
- CString start_path = ::Strip_Filename_From_Path (full_path);
- FILE_LIST file_list;
- Build_File_List (start_path, render_obj, file_list);
- // Loop through all the files in the list and add them to our internal
- // list (or update its ref count if its already there)
- for (int index = 0; index < file_list.Count (); index ++) {
- FileInfoStruct &info = file_list[index];
- Remove_File (Find_File (Make_Full_Path (info.m_Filename)));
- }
- MEMBER_RELEASE (render_obj);
- } else {
- Remove_File (Find_File (Make_Full_Path (filename)));
- }
- return ;
- }
- /////////////////////////////////////////////////////////////////
- //
- // Get_Preset_Library_Path
- //
- /////////////////////////////////////////////////////////////////
- void
- FileMgrClass::Get_Preset_Library_Path (uint32 class_id, bool is_temp, CString &path)
- {
- CString directory = Make_Full_Path (PRESETS_PATH);
-
- //
- // Build a filename for the presets library
- //
- CString filename;
- if (is_temp == false) {
- filename.Format ("%d.ddb", class_id);
- } else {
- filename = TEMP_DB_FILENAME;
- }
-
- //
- // Build a fully qualified path from the directory and filename
- //
- path = ::Make_Path (directory, filename);
- return ;
- }
|