FileMgr.cpp 39 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573
  1. /*
  2. ** Command & Conquer Renegade(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /***********************************************************************************************
  19. *** 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 ***
  20. ***********************************************************************************************
  21. * *
  22. * Project Name : LevelEdit *
  23. * *
  24. * $Archive:: /Commando/Code/Tools/LevelEdit/FileMgr.cpp $*
  25. * *
  26. * Author:: Patrick Smith *
  27. * *
  28. * $Modtime:: 1/29/02 2:59p $*
  29. * *
  30. * $Revision:: 36 $*
  31. * *
  32. *---------------------------------------------------------------------------------------------*
  33. * Functions: *
  34. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  35. #include "stdafx.h"
  36. #include "filemgr.h"
  37. #include "utils.h"
  38. #include "rendobj.h"
  39. #include "matinfo.h"
  40. #include "regkeys.h"
  41. #include "leveledit.h"
  42. #include "_assetmgr.h"
  43. #include "editorassetmgr.h"
  44. #include "updatingdbdialog.h"
  45. #include "uniquelist.h"
  46. #include "part_emt.h"
  47. #include "filelocations.h"
  48. #include "editorini.h"
  49. #include "ffactory.h"
  50. #include "ww3d.h"
  51. #include "node.h"
  52. #include "preset.h"
  53. #include "presetmgr.h"
  54. #include "spawnernode.h"
  55. #include "wwstring.h"
  56. #include "vssclass.h"
  57. #include "assetdatabase.h"
  58. #include "editorbuild.h"
  59. #include "assetpackagemgr.h"
  60. #include "mixfiledatabase.h"
  61. ////////////////////////////////////////////////////////////////////////
  62. // Constants
  63. ////////////////////////////////////////////////////////////////////////
  64. const char *SPECIAL_USER_NAME = "Artist";
  65. const char *SPECIAL_USER_FOLDER = "<Artist Tests>";
  66. const char *PROXY_TESTS_FOLDER = "<Proxy Tests>";
  67. ////////////////////////////////////////////////////////////////////////
  68. // Static member initialization
  69. ////////////////////////////////////////////////////////////////////////
  70. bool FileMgrClass::_bAutoUpdateOn = false;
  71. ////////////////////////////////////////////////////////////////////////
  72. //
  73. // FileMgrClass
  74. //
  75. ////////////////////////////////////////////////////////////////////////
  76. FileMgrClass::FileMgrClass (void)
  77. : m_bVSSInitialized (false),
  78. m_bReadOnlyVSS (true),
  79. m_IsSpecialUser (false)
  80. {
  81. #ifdef PUBLIC_EDITOR_VER
  82. //
  83. // Allocate the database interface layer we'll need to access assets
  84. //
  85. m_DatabaseInterface = new MixFileDatabaseClass;
  86. //
  87. // Get the asset directory from the asset package manager
  88. //
  89. m_BasePath = AssetPackageMgrClass::Get_Current_Package_Path ();
  90. #else
  91. //
  92. // Allocate the database interface layer we'll need to access assets
  93. //
  94. m_DatabaseInterface = new VSSClass;
  95. //
  96. // Read the asset directory from the registry
  97. //
  98. m_BasePath = theApp.GetProfileString (CONFIG_KEY, ASSET_DIR_VALUE);
  99. #endif //PUBLIC_EDITOR_VER
  100. //
  101. // Ensure the base has a directory delimiter on the end
  102. //
  103. if ((m_BasePath.GetLength () > 0) &&
  104. m_BasePath[::lstrlen (m_BasePath) - 1] != '\\')
  105. {
  106. m_BasePath += "\\";
  107. }
  108. //
  109. // The new cache directory is simply a subdirectory of the base
  110. //
  111. m_TextureCachePath = m_BasePath + "EditorCache";
  112. if (::GetFileAttributes (m_TextureCachePath) == 0xFFFFFFFF) {
  113. ::CreateDirectory (m_TextureCachePath, NULL);
  114. }
  115. return ;
  116. }
  117. ////////////////////////////////////////////////////////////////////////
  118. //
  119. // Initialize
  120. //
  121. ////////////////////////////////////////////////////////////////////////
  122. void
  123. FileMgrClass::Initialize (void)
  124. {
  125. Free_Data ();
  126. return ;
  127. }
  128. ////////////////////////////////////////////////////////////////////////
  129. //
  130. // Free_Data
  131. //
  132. ////////////////////////////////////////////////////////////////////////
  133. void
  134. FileMgrClass::Free_Data (void)
  135. {
  136. // Loop through all the files in our array
  137. for (int index = 0; index < m_FileList.Count (); index ++) {
  138. // Free this entry
  139. LevelFileStruct *pentry = m_FileList[index];
  140. SAFE_DELETE (pentry);
  141. }
  142. // Remove all the entries from our list.
  143. m_FileList.Delete_All ();
  144. return ;
  145. }
  146. ////////////////////////////////////////////////////////////////////////
  147. //
  148. // Make_Full_Path
  149. //
  150. ////////////////////////////////////////////////////////////////////////
  151. CString
  152. FileMgrClass::Make_Full_Path (LPCTSTR rel_path)
  153. {
  154. CString full_path = rel_path;
  155. // Is this path really relative?
  156. if (::Is_Path_Relative (rel_path)) {
  157. // Strip of the preceding directory delimiter if there is one.
  158. if ((full_path.GetLength () > 0) && (full_path[0] == '\\')) {
  159. full_path = &(((LPCTSTR)full_path)[1]);
  160. }
  161. // Return the full path
  162. full_path = m_BasePath + rel_path;
  163. // Strip off the last delimiter if necessary
  164. if (full_path[::lstrlen (full_path) - 1] == '\\') {
  165. full_path = full_path.Left (full_path.GetLength () - 1);
  166. }
  167. }
  168. // Return a string which contains the full path to the data file
  169. return full_path;
  170. }
  171. ////////////////////////////////////////////////////////////////////////
  172. //
  173. // Make_Relative_Path
  174. //
  175. ////////////////////////////////////////////////////////////////////////
  176. CString
  177. FileMgrClass::Make_Relative_Path (LPCTSTR full_path)
  178. {
  179. CString base_path = m_BasePath;
  180. CString lower_path = full_path;
  181. lower_path.MakeLower ();
  182. base_path.MakeLower ();
  183. LPCTSTR rel_path = lower_path;
  184. // Is our 'base' part of the full path?
  185. if (::strstr (rel_path, base_path) == rel_path) {
  186. // The relative path is the full path minus the base path
  187. rel_path += m_BasePath.GetLength ();
  188. // Strip of the preceding directory delimiter if there is one.
  189. if (rel_path[0] == '\\') {
  190. rel_path = &(((LPCTSTR)rel_path)[1]);
  191. }
  192. }
  193. // Return a string which contains the relative path to the data file
  194. return CString (rel_path);
  195. }
  196. ////////////////////////////////////////////////////////////////////////
  197. //
  198. // Is_Empty_Path
  199. //
  200. ////////////////////////////////////////////////////////////////////////
  201. bool
  202. FileMgrClass::Is_Empty_Path (LPCTSTR path)
  203. {
  204. bool retval = true;
  205. if (path[0] != 0) {
  206. CString temp1 = path;
  207. CString temp2 = m_BasePath;
  208. ::Delimit_Path (temp1);
  209. ::Delimit_Path (temp2);
  210. retval = bool(::stricmp (temp1, temp2) == 0);
  211. }
  212. return retval;
  213. }
  214. ////////////////////////////////////////////////////////////////////////
  215. //
  216. // Is_Path_Valid
  217. //
  218. ////////////////////////////////////////////////////////////////////////
  219. bool
  220. FileMgrClass::Is_Path_Valid (LPCTSTR path)
  221. {
  222. // The path is valid if its located under the asset tree
  223. return bool(::strnicmp (path, m_BasePath, m_BasePath.GetLength ()) == 0);
  224. }
  225. ////////////////////////////////////////////////////////////////////////
  226. //
  227. // Is_Path_In_Asset_Tree
  228. //
  229. ////////////////////////////////////////////////////////////////////////
  230. bool
  231. FileMgrClass::Is_Path_In_Asset_Tree (LPCTSTR path)
  232. {
  233. CString full_path = Make_Full_Path (path);
  234. return bool(::strnicmp (full_path, m_BasePath, m_BasePath.GetLength ()) == 0);
  235. }
  236. ////////////////////////////////////////////////////////////////////////
  237. //
  238. // Does_File_Exist
  239. //
  240. ////////////////////////////////////////////////////////////////////////
  241. bool
  242. FileMgrClass::Does_File_Exist
  243. (
  244. LPCTSTR filename,
  245. bool update_from_vss
  246. )
  247. {
  248. // Assume it doesn't exist
  249. bool file_exists = false;
  250. // Param valid?
  251. ASSERT (filename != NULL);
  252. if (filename != NULL) {
  253. // Ensure the path is complete
  254. CString path = Make_Full_Path (filename);
  255. file_exists = bool(::GetFileAttributes (path) != 0xFFFFFFFF);
  256. #ifndef PUBLIC_EDITOR_VER
  257. //
  258. // Should we try to get this file from VSS?
  259. //
  260. if (update_from_vss && (file_exists == false)) {
  261. //
  262. // If the file is in VSS, then get it and return the success code
  263. //
  264. if (Is_File_In_VSS (path)) {
  265. file_exists = Update_File (path);
  266. }
  267. }
  268. #endif //!PUBLIC_EDITOR_VER
  269. }
  270. // Return the true/false result code
  271. return file_exists;
  272. }
  273. /////////////////////////////////////////////////////////////////
  274. //
  275. // Find_File
  276. //
  277. /////////////////////////////////////////////////////////////////
  278. int
  279. FileMgrClass::Find_File (LPCTSTR filename) const
  280. {
  281. // Assume failure
  282. int index = -1;
  283. // Can we add another property to our list?
  284. ASSERT (filename != NULL);
  285. if (filename != NULL) {
  286. // Loop through all the files in our array
  287. for (int file_index = 0;
  288. (file_index < m_FileList.Count ()) && (index == -1);
  289. file_index ++) {
  290. // Was this the file we were looking for?
  291. if (::lstrcmpi (m_FileList[file_index]->m_Filename, filename) == 0) {
  292. index = file_index;
  293. }
  294. }
  295. }
  296. // Return the file's index (-1) on error
  297. return index;
  298. }
  299. /////////////////////////////////////////////////////////////////
  300. //
  301. // Remove_File
  302. //
  303. /////////////////////////////////////////////////////////////////
  304. bool
  305. FileMgrClass::Remove_File (int index)
  306. {
  307. // Assume failure
  308. bool retval = false;
  309. // Param valid?
  310. if ((index >= 0) && (index < m_FileList.Count ())) {
  311. // Decrement the ref count on this entry
  312. LevelFileStruct *pentry = m_FileList[index];
  313. pentry->m_RefCount --;
  314. // Do we need to remove this item from the list?
  315. if (pentry->m_RefCount == 0) {
  316. // Free the memory used by this entry and remove it
  317. // from the list
  318. SAFE_DELETE (pentry);
  319. m_FileList.Delete (index);
  320. }
  321. // Success!
  322. retval = true;
  323. }
  324. // Return the true/false result code
  325. return retval;
  326. }
  327. /////////////////////////////////////////////////////////////////
  328. //
  329. // Add_Files_To_Database
  330. //
  331. /////////////////////////////////////////////////////////////////
  332. bool
  333. FileMgrClass::Add_Files_To_Database (LPCTSTR filename)
  334. {
  335. // Assume success
  336. //bool retval = true;
  337. ASSERT (filename != NULL);
  338. m_CurrentFile = filename;
  339. Add_Files_To_Database ();
  340. // Return the true/false success code
  341. return true;
  342. }
  343. /////////////////////////////////////////////////////////////////
  344. //
  345. // Add_File_To_Database
  346. //
  347. /////////////////////////////////////////////////////////////////
  348. bool
  349. FileMgrClass::Add_File_To_Database (LPCTSTR filename)
  350. {
  351. CString path = Make_Full_Path (filename);
  352. if (Does_File_Exist (path) &&
  353. (m_DatabaseInterface->Does_File_Exist (path) == false))
  354. {
  355. m_DatabaseInterface->Add_File (path);
  356. }
  357. return true;
  358. }
  359. /////////////////////////////////////////////////////////////////
  360. //
  361. // Add_Files_To_Database
  362. //
  363. /////////////////////////////////////////////////////////////////
  364. void
  365. FileMgrClass::Add_Files_To_Database (void)
  366. {
  367. // Build a unique list of dependencies on this W3D file
  368. UniqueListClass<CString> unique_list;
  369. //
  370. // If this is a W3D model, enumerate its dependencies, otherwise
  371. // just add it to the list
  372. //
  373. if (::Is_W3D_Filename (m_CurrentFile)) {
  374. Build_Dependency_List (m_CurrentFile, unique_list);
  375. } else {
  376. unique_list.Add (Make_Full_Path (m_CurrentFile));
  377. }
  378. CString current_dir = ::Strip_Filename_From_Path (m_CurrentFile);
  379. current_dir = Make_Full_Path (current_dir);
  380. //
  381. // Now loop through all the files in the unique list and
  382. // add them to VSS.
  383. //
  384. for (int index = 0; index < unique_list.Count (); index ++) {
  385. CString full_path = unique_list[index];
  386. //
  387. // Does this file live outside of our asset tree?
  388. //
  389. if (Is_Path_In_Asset_Tree (full_path) == false) {
  390. CString filename = ::Get_Filename_From_Path (full_path);
  391. CString local_path = ::Make_Path (current_dir, filename);
  392. //
  393. // Copy the file to the asset tree
  394. //
  395. if (::Quick_Compare_Files (full_path, local_path) != 0) {
  396. ::Copy_File (full_path, local_path, FALSE);
  397. }
  398. full_path = local_path;
  399. }
  400. //
  401. // Add this file to VSS (if needs be)
  402. //
  403. if (Does_File_Exist (full_path) &&
  404. (m_DatabaseInterface->Does_File_Exist (full_path) == false))
  405. {
  406. m_DatabaseInterface->Add_File (full_path);
  407. }
  408. }
  409. return ;
  410. }
  411. /////////////////////////////////////////////////////////////////
  412. //
  413. // Add_File
  414. //
  415. /////////////////////////////////////////////////////////////////
  416. int
  417. FileMgrClass::Add_File (LPCTSTR filename, bool subdir_important)
  418. {
  419. // Assume failure
  420. int index = -1;
  421. // Param valid?
  422. ASSERT (filename != NULL);
  423. if ((filename != NULL) && (index == -1)) {
  424. // Ensure the path is complete
  425. CString path = Make_Full_Path (filename);
  426. LevelFileStruct *pentry = NULL;
  427. // Is this file already in the list?
  428. index = Find_File (path);
  429. if (index == -1) {
  430. // Allocate a new entry for our list
  431. pentry = new LevelFileStruct;
  432. ASSERT (pentry != NULL);
  433. // Set the file information
  434. pentry->m_Filename = path;
  435. pentry->m_RefCount = 0;
  436. // Add this entry to the list
  437. m_FileList.Add (pentry);
  438. index = Find_File (path);
  439. } else {
  440. pentry = m_FileList[index];
  441. }
  442. //
  443. // Record whether or not we think the file's subdirectory
  444. // is important.
  445. //
  446. pentry->m_SubdirImportant |= subdir_important;
  447. // Increment the refcount on this entry
  448. pentry->m_RefCount ++;
  449. }
  450. // Return the index of the file
  451. return index;
  452. }
  453. /////////////////////////////////////////////////////////////////
  454. //
  455. // Update_Texture_Cache
  456. //
  457. /////////////////////////////////////////////////////////////////
  458. bool
  459. FileMgrClass::Update_Texture_Cache
  460. (
  461. LPCTSTR start_path,
  462. RenderObjClass *prender_obj
  463. )
  464. {
  465. // Assume failure
  466. bool retval = false;
  467. ASSERT (prender_obj != NULL);
  468. if (prender_obj != NULL) {
  469. // Assume success from here on out
  470. retval = true;
  471. // Generate a list of all the texture files required by this render object
  472. DynamicVectorClass<CString> texture_list;
  473. int count = Build_Texture_List (start_path, prender_obj, texture_list);
  474. // Loop through all the textures in our list and make sure the latest
  475. // version is in the cache directory
  476. for (int texture = 0; texture < count; texture ++) {
  477. // Should we now copy the texture file over?
  478. CString texture_file = texture_list[texture];
  479. if (::GetFileAttributes (texture_file) != 0xFFFFFFFF) {
  480. // Is the texture file newer than the one we have in the cache?
  481. CString cache_path = m_TextureCachePath + CString ("\\") + ::Get_Filename_From_Path (texture_file);
  482. if (::Quick_Compare_Files (texture_file, cache_path) > 0) {
  483. // Everything is in order, so copy the texture file to the cache
  484. retval &= ::Copy_File (texture_file, cache_path, FALSE);
  485. }
  486. }
  487. }
  488. }
  489. // Return the true/false result code
  490. return retval;
  491. }
  492. /////////////////////////////////////////////////////////////////
  493. //
  494. // Build_Texture_List
  495. //
  496. /////////////////////////////////////////////////////////////////
  497. int
  498. FileMgrClass::Build_Texture_List
  499. (
  500. LPCTSTR start_path,
  501. RenderObjClass *prender_obj,
  502. DynamicVectorClass<CString> &texture_list,
  503. bool brecurse
  504. )
  505. {
  506. // Param valid?
  507. ASSERT (prender_obj != NULL);
  508. if (prender_obj) {
  509. CString path = start_path;
  510. ::Delimit_Path (path);
  511. // Get a list of texture files from the render object
  512. DynamicVectorClass<StringClass> dependency_list;
  513. prender_obj->Build_Texture_List (dependency_list);
  514. // Loop through all the texture files and try to assign paths to each one.
  515. for (int index = 0; index < dependency_list.Count (); index ++) {
  516. // Build a full path to the current texture file
  517. const char *filename = dependency_list[index];
  518. CString full_path = path + CString (filename);
  519. full_path = ::Get_File_Mgr ()->Make_Full_Path (full_path);
  520. // Does the texture file exist in this location?
  521. if (Does_File_Exist (full_path) == false) {
  522. // Assume the texture file exists in the parent directory
  523. full_path = ::Up_One_Directory (::Strip_Filename_From_Path (full_path));
  524. ::Delimit_Path (full_path);
  525. full_path += filename;
  526. }
  527. // Add this texture file to the list
  528. texture_list.Add (full_path);
  529. }
  530. dependency_list.Delete_All ();
  531. }
  532. // Return the count of textures in the list
  533. return texture_list.Count ();
  534. }
  535. /////////////////////////////////////////////////////////////////
  536. //
  537. // Determine_File_Location
  538. //
  539. /////////////////////////////////////////////////////////////////
  540. bool
  541. FileMgrClass::Determine_File_Location (LPCTSTR full_path, CString &real_location)
  542. {
  543. bool retval = false;
  544. //
  545. // Does the file exist in this location?
  546. //
  547. if (Does_File_Exist (full_path) == false) {
  548. CString filename = ::Get_Filename_From_Path (full_path);
  549. CString parent_dir = ::Up_One_Directory (::Strip_Filename_From_Path (full_path));
  550. CString parent_path = ::Make_Path (parent_dir, filename);
  551. //
  552. // Does the file exist in the parent directory?
  553. //
  554. if (Does_File_Exist (parent_path) == false) {
  555. if (::Is_Texture_Filename (filename)) {
  556. //
  557. // Does this texture file exist in the global texture directory?
  558. //
  559. CString texture_path = ::Make_Path (GLOBAL_TEXTURE_PATH, filename);
  560. if (Does_File_Exist (texture_path)) {
  561. real_location = texture_path;
  562. retval = true;
  563. }
  564. }
  565. } else {
  566. real_location = parent_path;
  567. retval = true;
  568. }
  569. } else {
  570. real_location = full_path;
  571. retval = true;
  572. }
  573. return retval;
  574. }
  575. /////////////////////////////////////////////////////////////////
  576. //
  577. // Build_File_List
  578. //
  579. /////////////////////////////////////////////////////////////////
  580. void
  581. FileMgrClass::Build_File_List
  582. (
  583. LPCTSTR start_path,
  584. RenderObjClass * render_obj,
  585. FILE_LIST & file_list
  586. )
  587. {
  588. CString path = start_path;
  589. ::Delimit_Path (path);
  590. // Get a list of dependent files from the render object
  591. DynamicVectorClass<StringClass> dependency_list;
  592. render_obj->Build_Dependency_List (dependency_list);
  593. // Loop through all the files and try to assign paths to each one.
  594. for (int index = 0; index < dependency_list.Count (); index ++) {
  595. // Build a full path to the current file
  596. const char *filename = dependency_list[index];
  597. CString full_path = ::Make_Path (path, filename);
  598. full_path = Make_Full_Path (full_path);
  599. //
  600. // Record that the subdir where this file lives is important
  601. // IF the subdir is returned by the render object.
  602. //
  603. bool subdir_important = (::strstr (filename, "+\\") != NULL);
  604. //
  605. // Attempt to find the file
  606. //
  607. CString real_location = full_path;
  608. Determine_File_Location (full_path, real_location);
  609. //
  610. // Add this file to the list
  611. //
  612. file_list.Add (FileInfoStruct (real_location, subdir_important));
  613. }
  614. dependency_list.Delete_All ();
  615. return ;
  616. }
  617. /////////////////////////////////////////////////////////////////
  618. //
  619. // Initialize_VSS
  620. //
  621. /////////////////////////////////////////////////////////////////
  622. bool
  623. FileMgrClass::Initialize_VSS
  624. (
  625. LPCTSTR ini_file_path,
  626. LPCTSTR username,
  627. LPCTSTR password
  628. )
  629. {
  630. // Do we need to initialize the VSS database?
  631. if (m_bVSSInitialized == false) {
  632. // Attempt to open the database
  633. m_bVSSInitialized = m_DatabaseInterface->Open_Database (ini_file_path,
  634. username ? username : "User",
  635. password ? password : "");
  636. m_bReadOnlyVSS = (m_DatabaseInterface->Is_Read_Only () == TRUE);
  637. //
  638. // Is this a special user? A special user is someone who doesn't
  639. // have full write access to the database.
  640. //
  641. if (::lstrcmpi (username, SPECIAL_USER_NAME) == 0) {
  642. m_IsSpecialUser = true;
  643. }
  644. }
  645. // Return the true/false result code
  646. return m_bVSSInitialized;
  647. }
  648. /////////////////////////////////////////////////////////////////
  649. //
  650. // Is_File_In_VSS
  651. //
  652. /////////////////////////////////////////////////////////////////
  653. bool
  654. FileMgrClass::Is_File_In_VSS (LPCTSTR filename)
  655. {
  656. // Assume failure
  657. bool retval = false;
  658. // State OK?
  659. if (m_bVSSInitialized) {
  660. retval = m_DatabaseInterface->Does_File_Exist (filename);
  661. }
  662. // Return the true/false result code
  663. return retval;
  664. }
  665. /////////////////////////////////////////////////////////////////
  666. //
  667. // Build_Update_List
  668. //
  669. /////////////////////////////////////////////////////////////////
  670. int
  671. FileMgrClass::Build_Update_List (DynamicVectorClass<LevelFileStruct *> &update_list)
  672. {
  673. int count = 0;
  674. // State OK?
  675. ASSERT (m_bVSSInitialized);
  676. if (m_bVSSInitialized) {
  677. // Loop through all the files in our array
  678. for (int index = 0;
  679. index < m_FileList.Count ();
  680. index ++) {
  681. // Get a pointer to this entry
  682. LevelFileStruct *pentry = m_FileList[index];
  683. // Ask VSS if we need to update this file.
  684. if (m_DatabaseInterface->Is_File_Different (pentry->m_Filename)) {
  685. update_list.Add (pentry);
  686. }
  687. }
  688. }
  689. // Return the count of items we added to the list
  690. return count;
  691. }
  692. /////////////////////////////////////////////////////////////////
  693. //
  694. // Update_Files
  695. //
  696. /////////////////////////////////////////////////////////////////
  697. bool
  698. FileMgrClass::Update_Files (DynamicVectorClass<LevelFileStruct *> *pupdate_list)
  699. {
  700. // Asssume success
  701. bool retval = true;
  702. ASSERT (m_bVSSInitialized);
  703. // Do we need to build a list of files to generate ourselves?
  704. DynamicVectorClass<LevelFileStruct *> *plist = pupdate_list;
  705. if (plist == NULL) {
  706. // Create a new list object
  707. plist = new DynamicVectorClass<LevelFileStruct *>;
  708. ASSERT (plist != NULL);
  709. // Generate a list of files that need to be updated from VSS
  710. Build_Update_List (*plist);
  711. }
  712. // Loop through all the files in our array
  713. for (int index = 0;
  714. index < plist->Count ();
  715. index ++) {
  716. // Get a pointer to this entry
  717. LevelFileStruct *pentry = (*plist)[index];
  718. //
  719. // Get the latest version from VSS if we don't already have the file
  720. // checked out.
  721. //
  722. if (m_DatabaseInterface->Get_File_Status (pentry->m_Filename) != AssetDatabaseClass::CHECKED_OUT_TO_ME) {
  723. retval &= m_DatabaseInterface->Get (pentry->m_Filename);
  724. }
  725. }
  726. // Free the temporary list if we need to
  727. if (plist != pupdate_list) {
  728. SAFE_DELETE (plist);
  729. }
  730. // Return the true/false result code
  731. return retval;
  732. }
  733. /////////////////////////////////////////////////////////////////
  734. //
  735. // Update_File
  736. //
  737. /////////////////////////////////////////////////////////////////
  738. bool
  739. FileMgrClass::Update_File (int index)
  740. {
  741. // Asssume failure
  742. bool retval = false;
  743. // Param valid?
  744. if ((index >= 0) && (index < m_FileList.Count ())) {
  745. // Update the file using its filename
  746. retval = Update_File (m_FileList[index]->m_Filename);
  747. }
  748. // Return the true/false result code
  749. return retval;
  750. }
  751. /////////////////////////////////////////////////////////////////
  752. //
  753. // Update_File
  754. //
  755. /////////////////////////////////////////////////////////////////
  756. bool
  757. FileMgrClass::Update_File (LPCTSTR filename)
  758. {
  759. // Asssume failure
  760. bool retval = false;
  761. // State valid?
  762. ASSERT (filename != NULL);
  763. ASSERT (m_bVSSInitialized);
  764. if ((filename != NULL) && m_bVSSInitialized) {
  765. // Assume success from here on out
  766. retval = true;
  767. //
  768. // Ensure the path is complete for the file
  769. //
  770. CString path = Make_Full_Path (filename);
  771. //
  772. // Get the latest version from VSS if we don't already have the file
  773. // checked out.
  774. //
  775. if ( ::GetFileAttributes (path) == 0xFFFFFFFF ||
  776. m_DatabaseInterface->Get_File_Status (filename) != AssetDatabaseClass::CHECKED_OUT_TO_ME)
  777. {
  778. retval = m_DatabaseInterface->Get (path);
  779. }
  780. }
  781. // Return the true/false result code
  782. return retval;
  783. }
  784. /////////////////////////////////////////////////////////////////
  785. //
  786. // Update_All_Files
  787. //
  788. /////////////////////////////////////////////////////////////////
  789. bool
  790. FileMgrClass::Update_All_Files (LPCTSTR dest_path, LPCTSTR search_mask)
  791. {
  792. bool retval = false;
  793. // State valid?
  794. ASSERT (dest_path != NULL);
  795. ASSERT (m_bVSSInitialized);
  796. if ((dest_path != NULL) && m_bVSSInitialized) {
  797. //
  798. // Assume success from here on out
  799. //
  800. retval = m_DatabaseInterface->Get_All (dest_path, search_mask);
  801. }
  802. return retval;
  803. }
  804. /////////////////////////////////////////////////////////////////
  805. //
  806. // Get_Subproject
  807. //
  808. /////////////////////////////////////////////////////////////////
  809. bool
  810. FileMgrClass::Get_Subproject (LPCTSTR path)
  811. {
  812. // Asssume failure
  813. bool retval = false;
  814. // State valid?
  815. ASSERT (path != NULL);
  816. ASSERT (m_bVSSInitialized);
  817. if ((path != NULL) && m_bVSSInitialized) {
  818. // Ensure the path is complete for the file
  819. CString full_path = Make_Full_Path (path);
  820. // Get the files from VSS
  821. retval = m_DatabaseInterface->Get (full_path);
  822. }
  823. // Return the true/false result code
  824. return retval;
  825. }
  826. /////////////////////////////////////////////////////////////////
  827. //
  828. // Set_Base_Path
  829. //
  830. /////////////////////////////////////////////////////////////////
  831. void
  832. FileMgrClass::Set_Base_Path (LPCTSTR base)
  833. {
  834. // Store this base both in memory and in the registry
  835. m_BasePath = base;
  836. theApp.WriteProfileString (CONFIG_KEY, ASSET_DIR_VALUE, m_BasePath);
  837. // Ensure the directory is created
  838. if (Does_File_Exist (m_BasePath) == false) {
  839. ::CreateDirectory (base, NULL);
  840. }
  841. // Ensure the new base has a directory delimiter on the end
  842. if (m_BasePath[::lstrlen (m_BasePath) - 1] != '\\') {
  843. m_BasePath += "\\";
  844. }
  845. // The new cache directory is simply a subdirectory of the base
  846. m_TextureCachePath = m_BasePath + "EditorCache";
  847. if (::GetFileAttributes (m_TextureCachePath) == 0xFFFFFFFF) {
  848. ::CreateDirectory (m_TextureCachePath, NULL);
  849. }
  850. //
  851. // Add the texture cache to the search path
  852. //
  853. EditorFileFactoryClass::Add_Search_Path (m_TextureCachePath);
  854. return ;
  855. }
  856. /////////////////////////////////////////////////////////////////
  857. //
  858. // Find_Files
  859. //
  860. /////////////////////////////////////////////////////////////////
  861. void
  862. FileMgrClass::Find_Files
  863. (
  864. LPCTSTR start_path,
  865. LPCTSTR wildcard,
  866. DynamicVectorClass<CString> & file_list,
  867. bool recurse
  868. )
  869. {
  870. CString path = start_path;
  871. if (path[::lstrlen(path)-1] != '\\') {
  872. path += "\\";
  873. }
  874. // Build a file spec from the starting path and the wildcard
  875. CString file_spec = path + wildcard;
  876. // Find all files that match this wildcard
  877. WIN32_FIND_DATA find_info = { 0 };
  878. BOOL bcontinue = TRUE;
  879. for (HANDLE hfile_find = ::FindFirstFile (file_spec, &find_info);
  880. (hfile_find != INVALID_HANDLE_VALUE) && bcontinue;
  881. bcontinue = ::FindNextFile (hfile_find, &find_info)) {
  882. // Is this a file?
  883. if (!(find_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
  884. // Add this file to our list
  885. CString filename = path + find_info.cFileName;
  886. file_list.Add (filename);
  887. }
  888. }
  889. // Close the search handle
  890. ::FindClose (hfile_find);
  891. hfile_find = INVALID_HANDLE_VALUE;
  892. if (recurse) {
  893. // Process all the subdirs
  894. file_spec = path + "*.*";
  895. bcontinue = TRUE;
  896. for (hfile_find = ::FindFirstFile (file_spec, &find_info);
  897. (hfile_find != INVALID_HANDLE_VALUE) && bcontinue;
  898. bcontinue = ::FindNextFile (hfile_find, &find_info)) {
  899. // If this is a subdir, then recursively build the file list
  900. if ((find_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) &&
  901. (find_info.cFileName[0] != '.')){
  902. CString sub_dir = path + find_info.cFileName;
  903. Find_Files (sub_dir, wildcard, file_list, recurse);
  904. }
  905. }
  906. // Close the search handle
  907. ::FindClose (hfile_find);
  908. hfile_find = INVALID_HANDLE_VALUE;
  909. }
  910. return ;
  911. }
  912. /////////////////////////////////////////////////////////////////
  913. //
  914. // Update_Model
  915. //
  916. /////////////////////////////////////////////////////////////////
  917. bool
  918. FileMgrClass::Update_Model
  919. (
  920. LPCTSTR local_path,
  921. LPCTSTR new_filename
  922. )
  923. {
  924. // Assume failure
  925. bool retval = false;
  926. CWaitCursor wait_cursor;
  927. //
  928. // Display a dialog so the user doesn't close down the app
  929. //
  930. HWND hmain_wnd = ::AfxGetMainWnd ()->m_hWnd;
  931. HWND hupdate_dlg = ::Show_VSS_Update_Dialog (hmain_wnd);
  932. CString new_path = ::Strip_Filename_From_Path (new_filename);
  933. CString local_path_temp = local_path;
  934. ::Delimit_Path (local_path_temp);
  935. ::Delimit_Path (new_path);
  936. bool path_different = bool(::lstrcmpi (new_path, local_path_temp) != 0);
  937. //
  938. // Build a unique list of dependencies on this W3D file
  939. //
  940. UniqueListClass<CString> file_list;
  941. Build_Dependency_List (new_filename, file_list);
  942. //
  943. // Loop through all the files in our list
  944. //
  945. for (int index = 0; index < file_list.Count (); index ++) {
  946. // Get the full path, and its 2 components, of the current file.
  947. CString &full_path = file_list[index];
  948. CString path = ::Strip_Filename_From_Path (full_path);
  949. CString filename = ::Get_Filename_From_Path (full_path);
  950. // The local version (in our asset tree) of this file should exist here.
  951. CString local_file = local_path_temp + filename;
  952. //
  953. // Check to see if we need to maintain this file's subdirectory...
  954. //
  955. bool subdir_important = (::strstr (full_path, "+\\") != NULL);
  956. if (subdir_important) {
  957. //
  958. // Ensure the subdirectory exists
  959. //
  960. CString sub_dir = local_path_temp + ::Get_Subdir_From_Full_Path (full_path);
  961. ::Create_Dir_If_Necessary (sub_dir);
  962. //
  963. // Build a path where the destination file lives in the sub-dir
  964. //
  965. local_file = sub_dir + CString ("\\") + filename;
  966. }
  967. //
  968. // Attempt to check out the latest version of this file
  969. //
  970. bool need_checkin = m_DatabaseInterface->Check_Out (local_file, false);
  971. //
  972. // If this file is newer than its local counterpart, copy it!
  973. //
  974. //if (path_different && ::Quick_Compare_Files (full_path, local_file) > 0) {
  975. if (path_different) {
  976. ::Copy_File (full_path, local_file, true);
  977. }
  978. //
  979. // Should we add this file to VSS, or update the existing?
  980. //
  981. if (need_checkin == false) {
  982. m_DatabaseInterface->Add_File (local_file);
  983. } else {
  984. m_DatabaseInterface->Check_In (local_file);
  985. }
  986. }
  987. // Remove the updating dialog
  988. ::Kill_VSS_Update_Dialog (hupdate_dlg);
  989. return retval;
  990. }
  991. /////////////////////////////////////////////////////////////////
  992. //
  993. // Build_Dependency_List
  994. //
  995. /////////////////////////////////////////////////////////////////
  996. void
  997. FileMgrClass::Build_Dependency_List
  998. (
  999. LPCTSTR asset_filename,
  1000. UniqueListClass<CString> & list
  1001. )
  1002. {
  1003. CString full_path = Make_Full_Path (asset_filename);
  1004. CString path = ::Strip_Filename_From_Path (full_path);
  1005. CString filename = ::Get_Filename_From_Path (asset_filename);
  1006. CString asset_name = ::Asset_Name_From_Filename (filename);
  1007. // Create an instance of the model so we can enumerate all the other
  1008. // files this model is dependant on
  1009. _pThe3DAssetManager->Set_Current_Directory (path);
  1010. RenderObjClass *render_obj = _pThe3DAssetManager->Create_Render_Obj (asset_name);
  1011. if (render_obj != NULL) {
  1012. // Build a list of all the files used by this render object
  1013. FILE_LIST file_list;
  1014. Build_File_List (path, render_obj, file_list);
  1015. // Make a unique list out of the file list
  1016. for (int index = 0; index < file_list.Count (); index ++) {
  1017. FileInfoStruct &info = file_list[index];
  1018. list.Add_Unique (info.m_Filename);
  1019. }
  1020. // Free the temporary render object
  1021. MEMBER_RELEASE (render_obj);
  1022. } else {
  1023. //
  1024. // This wasn't a render object file (could of been an animation), so
  1025. // just add the file to the list (no other dependencies).
  1026. //
  1027. list.Add (full_path);
  1028. }
  1029. return ;
  1030. }
  1031. /////////////////////////////////////////////////////////////////
  1032. //
  1033. // Update_Asset_Tree
  1034. //
  1035. /////////////////////////////////////////////////////////////////
  1036. bool
  1037. FileMgrClass::Update_Asset_Tree (void)
  1038. {
  1039. return m_DatabaseInterface->Get_Subproject (m_BasePath);
  1040. }
  1041. /////////////////////////////////////////////////////////////////
  1042. //
  1043. // Build_Global_Include_List
  1044. //
  1045. void
  1046. FileMgrClass::Build_Global_Include_List (void)
  1047. {
  1048. // Ensure we have the latest copy from VSS
  1049. Update_File (ALWAYS_INI_PATH);
  1050. // Build the global include list
  1051. Build_Include_List (ALWAYS_INI_PATH, m_GlobalIncludeFiles);
  1052. return ;
  1053. }
  1054. /////////////////////////////////////////////////////////////////
  1055. //
  1056. // Build_Include_List
  1057. //
  1058. /////////////////////////////////////////////////////////////////
  1059. void
  1060. FileMgrClass::Build_Include_List
  1061. (
  1062. LPCTSTR ini_filename,
  1063. DynamicVectorClass<CString> &list
  1064. )
  1065. {
  1066. // Start with a fresh list of files
  1067. list.Delete_All ();
  1068. // Get a pointer to the INI file from the asset manager
  1069. CString ini_path = Make_Full_Path (ini_filename);
  1070. EditorINIClass *pini = _pThe3DAssetManager->Get_INI (ini_path);
  1071. // Were we successful in getting a pointer to the INI file?
  1072. ASSERT (pini != NULL);
  1073. if (pini != NULL) {
  1074. // Loop through all the assets in the ini file
  1075. int instance_count = pini->Entry_Count ("Assets");
  1076. for (int index = 0; index < instance_count; index ++) {
  1077. // Get the current file spec from the INI
  1078. TCHAR filespec[MAX_PATH];
  1079. pini->Get_String ("Assets",
  1080. pini->Get_Entry ("Assets", index),
  1081. "",
  1082. filespec,
  1083. sizeof (filespec));
  1084. // Add the filespec to our list
  1085. list.Add (filespec);
  1086. }
  1087. // Free the INI object
  1088. SAFE_DELETE (pini);
  1089. }
  1090. return ;
  1091. }
  1092. /////////////////////////////////////////////////////////////////
  1093. //
  1094. // Update_Global_Include_File_List
  1095. //
  1096. /////////////////////////////////////////////////////////////////
  1097. bool
  1098. FileMgrClass::Update_Global_Include_File_List (void)
  1099. {
  1100. bool retval = false;
  1101. // Attempt to checkout the INI file
  1102. CString ini_path = Make_Full_Path (ALWAYS_INI_PATH);
  1103. if (m_DatabaseInterface->Retry_Check_Out (ini_path, 10, 1000)) {
  1104. // Create the INI file from our in-memory list
  1105. EditorINIClass ini_file;
  1106. for (int index = 0; index < m_GlobalIncludeFiles.Count (); index ++) {
  1107. CString index_string;
  1108. index_string.Format ("%d", index + 1);
  1109. ini_file.Put_String ("Assets", index_string, (LPCTSTR)m_GlobalIncludeFiles[index]);
  1110. }
  1111. // Save the INI file
  1112. FileClass * pini_file = _TheFileFactory->Get_File (ini_path);
  1113. if (pini_file) {
  1114. ini_file.Save (*pini_file);
  1115. _TheFileFactory->Return_File (pini_file);
  1116. }
  1117. // Now check the INI file back in
  1118. retval = m_DatabaseInterface->Retry_Check_In (ini_path, 10, 1000);
  1119. }
  1120. // Reutrn the true/false result code
  1121. return retval;
  1122. }
  1123. /////////////////////////////////////////////////////////////////
  1124. //
  1125. // Update
  1126. //
  1127. /////////////////////////////////////////////////////////////////
  1128. void
  1129. FileMgrClass::Update (NodeClass *node, bool add_node)
  1130. {
  1131. //
  1132. // Update the files this preset is dependent on
  1133. //
  1134. PresetClass *preset = node->Get_Preset ();
  1135. if (preset != NULL) {
  1136. Update (preset, add_node);
  1137. }
  1138. //
  1139. // If this is a spawner, then update the files
  1140. // its spawned object is dependent on as well.
  1141. //
  1142. if (node->Get_Type () == NODE_TYPE_SPAWNER) {
  1143. SpawnerDefClass *definition = static_cast<SpawnerDefClass *> (preset->Get_Definition ());
  1144. if (definition != NULL) {
  1145. //
  1146. // Loop over all the possible spawned objects and make sure to load their assets
  1147. //
  1148. const DynamicVectorClass<int> &list = definition->Get_Spawn_Definition_ID_List ();
  1149. for (int index = 0; index < list.Count (); index ++) {
  1150. PresetClass *preset = PresetMgrClass::Find_Preset (list[index]);
  1151. if (preset != NULL) {
  1152. Update (preset, add_node);
  1153. }
  1154. }
  1155. }
  1156. }
  1157. return ;
  1158. }
  1159. /////////////////////////////////////////////////////////////////
  1160. //
  1161. // Update
  1162. //
  1163. /////////////////////////////////////////////////////////////////
  1164. void
  1165. FileMgrClass::Update (PresetClass *preset, bool add_node)
  1166. {
  1167. //
  1168. // Get the list of dependencies from the preset
  1169. //
  1170. STRING_LIST file_list;
  1171. preset->Get_All_Dependencies (file_list);
  1172. //
  1173. // Loop through all the files this preset is dependent on
  1174. //
  1175. for (int index = 0; index < file_list.Count (); index ++) {
  1176. CString filename = file_list[index];
  1177. if (Is_Empty_Path (filename) == false)
  1178. {
  1179. if (add_node) {
  1180. Add_Asset (filename);
  1181. } else {
  1182. Remove_Asset (filename);
  1183. }
  1184. }
  1185. }
  1186. return ;
  1187. }
  1188. /////////////////////////////////////////////////////////////////
  1189. //
  1190. // Add_Asset
  1191. //
  1192. /////////////////////////////////////////////////////////////////
  1193. void
  1194. FileMgrClass::Add_Asset (LPCTSTR filename)
  1195. {
  1196. RenderObjClass *render_obj = NULL;
  1197. //
  1198. // If this is a render object, then build a list of
  1199. // dependencies
  1200. //
  1201. if (::Is_W3D_Filename (filename)) {
  1202. CString asset_name = ::Asset_Name_From_Filename (filename);
  1203. render_obj = ::Create_Render_Obj (asset_name);
  1204. }
  1205. if (render_obj != NULL) {
  1206. //
  1207. // Build a list of all the files used by this render object
  1208. //
  1209. CString full_path = Make_Full_Path (filename);
  1210. CString start_path = ::Strip_Filename_From_Path (full_path);
  1211. FILE_LIST file_list;
  1212. Build_File_List (start_path, render_obj, file_list);
  1213. // Loop through all the files in the list and add them to our internal
  1214. // list (or update its ref count if its already there)
  1215. for (int index = 0; index < file_list.Count (); index ++) {
  1216. FileInfoStruct &info = file_list[index];
  1217. Add_File (Make_Full_Path (info.m_Filename), info.m_SubdirImportant);
  1218. }
  1219. MEMBER_RELEASE (render_obj);
  1220. } else {
  1221. Add_File (Make_Full_Path (filename), false);
  1222. }
  1223. return ;
  1224. }
  1225. /////////////////////////////////////////////////////////////////
  1226. //
  1227. // Remove_Asset
  1228. //
  1229. /////////////////////////////////////////////////////////////////
  1230. void
  1231. FileMgrClass::Remove_Asset (LPCTSTR filename)
  1232. {
  1233. RenderObjClass *render_obj = NULL;
  1234. //
  1235. // If this is a render object, then build a list of
  1236. // dependencies
  1237. //
  1238. if (::Is_W3D_Filename (filename)) {
  1239. CString asset_name = ::Asset_Name_From_Filename (filename);
  1240. render_obj = ::Create_Render_Obj (asset_name);
  1241. }
  1242. if (render_obj != NULL) {
  1243. // Build a list of all the files used by this render object
  1244. CString full_path = Make_Full_Path (filename);
  1245. CString start_path = ::Strip_Filename_From_Path (full_path);
  1246. FILE_LIST file_list;
  1247. Build_File_List (start_path, render_obj, file_list);
  1248. // Loop through all the files in the list and add them to our internal
  1249. // list (or update its ref count if its already there)
  1250. for (int index = 0; index < file_list.Count (); index ++) {
  1251. FileInfoStruct &info = file_list[index];
  1252. Remove_File (Find_File (Make_Full_Path (info.m_Filename)));
  1253. }
  1254. MEMBER_RELEASE (render_obj);
  1255. } else {
  1256. Remove_File (Find_File (Make_Full_Path (filename)));
  1257. }
  1258. return ;
  1259. }
  1260. /////////////////////////////////////////////////////////////////
  1261. //
  1262. // Get_Preset_Library_Path
  1263. //
  1264. /////////////////////////////////////////////////////////////////
  1265. void
  1266. FileMgrClass::Get_Preset_Library_Path (uint32 class_id, bool is_temp, CString &path)
  1267. {
  1268. CString directory = Make_Full_Path (PRESETS_PATH);
  1269. //
  1270. // Build a filename for the presets library
  1271. //
  1272. CString filename;
  1273. if (is_temp == false) {
  1274. filename.Format ("%d.ddb", class_id);
  1275. } else {
  1276. filename = TEMP_DB_FILENAME;
  1277. }
  1278. //
  1279. // Build a fully qualified path from the directory and filename
  1280. //
  1281. path = ::Make_Path (directory, filename);
  1282. return ;
  1283. }