PresetExport.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847
  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/PresetExport.cpp $*
  25. * *
  26. * Author:: Patrick Smith *
  27. * *
  28. * $Modtime:: 4/02/01 11:32a $*
  29. * *
  30. * $Revision:: 4 $*
  31. * *
  32. *---------------------------------------------------------------------------------------------*
  33. * Functions: *
  34. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  35. #include "stdafx.h"
  36. #include "presetexport.h"
  37. #include "preset.h"
  38. #include "presetmgr.h"
  39. #include "textfile.h"
  40. #include "utils.h"
  41. #include "parameter.h"
  42. #include "simpleparameter.h"
  43. #include "presetslibform.h"
  44. ///////////////////////////////////////////////////////////////////////
  45. //
  46. // Import
  47. //
  48. ///////////////////////////////////////////////////////////////////////
  49. void
  50. PresetExportClass::Import (const char *filename)
  51. {
  52. //
  53. // Try to open the log file
  54. //
  55. TextFileClass file (filename);
  56. if (file.Open ()) {
  57. //
  58. // Lookup the class ID in the header of the text file
  59. //
  60. bool is_valid_file = false;
  61. int class_id = Find_Header (file);
  62. if (class_id != 0) {
  63. //
  64. // Read the column headers from disk
  65. //
  66. DynamicVectorClass<StringClass> column_headers;
  67. if ( Read_Column_Headers (file, column_headers) &&
  68. Validate_Columns (class_id, column_headers))
  69. {
  70. //
  71. // Try to check-out the preset database we will be modifying
  72. //
  73. bool should_undo_on_err = false;
  74. if (PresetMgrClass::Check_Out_Database (class_id, &should_undo_on_err)) {
  75. //
  76. // Turn off immediate check in mode so we can make bulk changes to the
  77. // preset library
  78. //
  79. bool old_check_in_mode = PresetMgrClass::Get_Immediate_Check_In_Mode ();
  80. PresetMgrClass::Set_Immediate_Check_In_Mode (false);
  81. //
  82. // Import the new settings
  83. //
  84. if (Import_Presets (file, class_id, column_headers)) {
  85. is_valid_file = true;
  86. //
  87. // Save the preset changes to disk
  88. //
  89. ::Get_Presets_Form ()->Save_Global_Presets (class_id);
  90. if (old_check_in_mode) {
  91. PresetMgrClass::Check_In_Presets ();
  92. }
  93. }
  94. //
  95. // Restore the old check-in mode
  96. //
  97. PresetMgrClass::Set_Immediate_Check_In_Mode (old_check_in_mode);
  98. }
  99. }
  100. }
  101. //
  102. // Warn the user that the file did not appear to be valid
  103. //
  104. if (is_valid_file == false) {
  105. CString message;
  106. message.Format ("%s does not appear to be a valid preset export text file or there was an error parsing the data.\nDue to the severe side-effects of improperly importing preset settings, all changes were ignored.", filename);
  107. ::MessageBox (::AfxGetMainWnd ()->m_hWnd, message, "Invalid Data", MB_ICONERROR | MB_OK);
  108. }
  109. //
  110. // Close the file
  111. //
  112. file.Close ();
  113. }
  114. return ;
  115. }
  116. ///////////////////////////////////////////////////////////////////////
  117. //
  118. // Read_Column_Headers
  119. //
  120. ///////////////////////////////////////////////////////////////////////
  121. bool
  122. PresetExportClass::Read_Column_Headers
  123. (
  124. TextFileClass & file,
  125. DynamicVectorClass<StringClass> & column_headers
  126. )
  127. {
  128. bool retval = false;
  129. //
  130. // Keep reading lines of text from the file until we've
  131. // found the column headers
  132. //
  133. StringClass line;
  134. while (file.Read_Line (line)) {
  135. //
  136. // Check to see if this is the column header
  137. //
  138. const char * COL_HEADER_TEXT = "Name\tPreset ID\t";
  139. int header_len = ::lstrlen (COL_HEADER_TEXT);
  140. if (::strnicmp (line, COL_HEADER_TEXT, header_len) == 0) {
  141. //
  142. // Build a list from the column header string
  143. //
  144. CString *temp_string_list = NULL;
  145. int count = ::Build_List_From_String (line, "\t", &temp_string_list);
  146. if (count > 0) {
  147. //
  148. // Add the entries from our temp list to the list the
  149. // caller supplied. Also check for NULL entries
  150. //
  151. for (int index = 0; index < count; index ++) {
  152. if (temp_string_list[index].IsEmpty () == false) {
  153. column_headers.Add ((const char *)temp_string_list[index]);
  154. }
  155. }
  156. SAFE_DELETE_ARRAY (temp_string_list);
  157. retval = true;
  158. }
  159. break;
  160. }
  161. }
  162. return retval;
  163. }
  164. ///////////////////////////////////////////////////////////////////////
  165. //
  166. // Validate_Columns
  167. //
  168. ///////////////////////////////////////////////////////////////////////
  169. bool
  170. PresetExportClass::Validate_Columns
  171. (
  172. int class_id,
  173. DynamicVectorClass<StringClass> & column_headers
  174. )
  175. {
  176. bool retval = false;
  177. //
  178. // Lookup the first preset of the given class
  179. //
  180. PresetClass *first_preset = PresetMgrClass::Get_First (class_id, PresetMgrClass::ID_CLASS);
  181. if (first_preset != NULL) {
  182. //
  183. // Assume success from here on out
  184. //
  185. retval = true;
  186. //
  187. // Try to match each column header with a parameter of the class
  188. //
  189. for (int col_index = 2; col_index < column_headers.Count (); col_index ++) {
  190. //
  191. // Loop over all the parameters for this definition type
  192. //
  193. DefinitionClass *definition = first_preset->Get_Definition ();
  194. int count = definition->Get_Parameter_Count ();
  195. bool found = false;
  196. for (int index = 0; !found && index < count; index ++) {
  197. ParameterClass *parameter = definition->Lock_Parameter (index);
  198. //
  199. // Is this the parameter we are looking for?
  200. //
  201. if (::lstrcmpi (column_headers[col_index], parameter->Get_Name ()) == 0) {
  202. //
  203. // Is this a parameter type that we are likely to have exported?
  204. //
  205. if (Can_Export_Parameter (parameter)) {
  206. found = true;
  207. }
  208. }
  209. definition->Unlock_Parameter (index);
  210. }
  211. //
  212. // Kick out of the loop if we can't match even one of the presets
  213. //
  214. if (found == false) {
  215. retval = false;
  216. break;
  217. }
  218. }
  219. }
  220. return retval;
  221. }
  222. ///////////////////////////////////////////////////////////////////////
  223. //
  224. // Import_Presets
  225. //
  226. ///////////////////////////////////////////////////////////////////////
  227. bool
  228. PresetExportClass::Import_Presets
  229. (
  230. TextFileClass & file,
  231. int class_id,
  232. DynamicVectorClass<StringClass> & column_headers
  233. )
  234. {
  235. bool retval = true;
  236. //
  237. // Keep reading preset values until we've exhausted the file's contents
  238. //
  239. StringClass line;
  240. while (retval && file.Read_Line (line)) {
  241. //
  242. // Build a list of values from the string
  243. //
  244. CString *value_list = NULL;
  245. int count = ::Build_List_From_String (line, "\t", &value_list);
  246. //
  247. // Exit early if the count of values does not match the count
  248. // of expected values.
  249. //
  250. if (count != column_headers.Count ()) {
  251. retval = false;
  252. } else {
  253. //
  254. // Get the ID of the preset
  255. //
  256. int preset_id = ::atoi (value_list[1]);
  257. PresetClass *preset = NULL;
  258. if (preset_id == 0) {
  259. //
  260. // Create a new preset...
  261. //
  262. preset = PresetMgrClass::Create_Preset (class_id, value_list[0], false);
  263. if (preset != NULL) {
  264. //
  265. // Add this preset to the framework
  266. //
  267. ::Get_Presets_Form ()->Add_Preset (preset);
  268. PresetMgrClass::Add_Preset (preset);
  269. DefinitionMgrClass::Register_Definition (preset->Get_Definition ());
  270. }
  271. } else {
  272. //
  273. // Lookup the preset based on its ID
  274. //
  275. preset = PresetMgrClass::Find_Preset (preset_id);
  276. }
  277. //
  278. // Did we find the preset and does its name match?
  279. //
  280. if (preset != NULL && ::lstrcmpi (preset->Get_Name (), value_list[0]) == 0) {
  281. //
  282. // Import the remainder of the parameter values
  283. //
  284. for (int index = 2; retval && index < count; index ++) {
  285. ParameterClass *parameter = Find_Parameter (preset, column_headers[index]);
  286. if (parameter != NULL) {
  287. //
  288. // Store the change in the preset
  289. //
  290. retval = Import_Setting (preset, parameter, value_list[index]);
  291. } else {
  292. retval = false;
  293. }
  294. }
  295. //
  296. // Register this preset for updating...
  297. //
  298. if (retval) {
  299. PresetMgrClass::Add_Dirty_Preset (preset_id);
  300. }
  301. }
  302. }
  303. SAFE_DELETE_ARRAY (value_list);
  304. }
  305. //
  306. // Force the imported presets to be sorted
  307. //
  308. ::Get_Presets_Form ()->Sort_Items (class_id);
  309. return retval;
  310. }
  311. ///////////////////////////////////////////////////////////////////////
  312. //
  313. // Import_Setting
  314. //
  315. ///////////////////////////////////////////////////////////////////////
  316. bool
  317. PresetExportClass::Import_Setting
  318. (
  319. PresetClass * preset,
  320. ParameterClass * parameter,
  321. const char * value
  322. )
  323. {
  324. bool retval = true;
  325. //
  326. // Handle each type differently
  327. //
  328. switch (parameter->Get_Type ())
  329. {
  330. case ParameterClass::TYPE_INT:
  331. {
  332. //
  333. // Convert the string to its native type
  334. //
  335. int param_value = 0;
  336. ::sscanf (value, "%d", &param_value);
  337. //
  338. // Pass the new value onto the parameter
  339. //
  340. ((IntParameterClass *)parameter)->Set_Value (param_value);
  341. }
  342. break;
  343. case ParameterClass::TYPE_FLOAT:
  344. {
  345. //
  346. // Convert the string to its native type
  347. //
  348. float param_value = 0;
  349. ::sscanf (value, "%f", &param_value);
  350. //
  351. // Pass the new value onto the parameter
  352. //
  353. ((FloatParameterClass *)parameter)->Set_Value (param_value);
  354. }
  355. break;
  356. case ParameterClass::TYPE_FILENAME:
  357. case ParameterClass::TYPE_SOUND_FILENAME:
  358. case ParameterClass::TYPE_STRING:
  359. {
  360. //
  361. // Pass the new value onto the parameter
  362. //
  363. ((StringParameterClass *)parameter)->Set_String (value);
  364. }
  365. break;
  366. case ParameterClass::TYPE_VECTOR3:
  367. {
  368. //
  369. // Convert the string to its native type
  370. //
  371. Vector3 param_value (0, 0, 0);
  372. ::sscanf (value, "\"%f, %f, %f\"", &param_value.X, &param_value.Y, &param_value.Z);
  373. //
  374. // Pass the new value onto the parameter
  375. //
  376. ((Vector3ParameterClass *)parameter)->Set_Value (param_value);
  377. }
  378. break;
  379. case ParameterClass::TYPE_BOOL:
  380. {
  381. //
  382. // Convert the string to its native type
  383. //
  384. int param_value = 0;
  385. ::sscanf (value, "%d", &param_value);
  386. //
  387. // Pass the new value onto the parameter
  388. //
  389. ((BoolParameterClass *)parameter)->Set_Value (bool(param_value == 1));
  390. }
  391. break;
  392. case ParameterClass::TYPE_ENUM:
  393. {
  394. //
  395. // Convert the string to its native type
  396. //
  397. int param_value = 0;
  398. ::sscanf (value, "%d", &param_value);
  399. //
  400. // Pass the new value onto the parameter
  401. //
  402. ((EnumParameterClass *)parameter)->Set_Selected_Value (param_value);
  403. }
  404. break;
  405. case ParameterClass::TYPE_ANGLE:
  406. {
  407. //
  408. // Convert the string to its native type
  409. //
  410. float param_value = 0;
  411. ::sscanf (value, "%f", &param_value);
  412. //
  413. // Pass the new value onto the parameter
  414. //
  415. ((AngleParameterClass *)parameter)->Set_Value (param_value);
  416. }
  417. break;
  418. default:
  419. retval = false;
  420. break;
  421. }
  422. return retval;
  423. }
  424. ///////////////////////////////////////////////////////////////////////
  425. //
  426. // Find_Parameter
  427. //
  428. ///////////////////////////////////////////////////////////////////////
  429. ParameterClass *
  430. PresetExportClass::Find_Parameter (PresetClass *preset, const char *parameter_name)
  431. {
  432. ParameterClass *parameter = NULL;
  433. DefinitionClass *definition = preset->Get_Definition ();
  434. int count = definition->Get_Parameter_Count ();
  435. bool found = false;
  436. for (int index = 0; !found && index < count; index ++) {
  437. ParameterClass *curr_parameter = definition->Lock_Parameter (index);
  438. //
  439. // Is this the parameter we are looking for?
  440. //
  441. if ( ::lstrcmpi (parameter_name, curr_parameter->Get_Name ()) == 0 &&
  442. Can_Export_Parameter (curr_parameter))
  443. {
  444. parameter = curr_parameter;
  445. found = true;
  446. }
  447. }
  448. return parameter;
  449. }
  450. ///////////////////////////////////////////////////////////////////////
  451. //
  452. // Find_Header
  453. //
  454. ///////////////////////////////////////////////////////////////////////
  455. int
  456. PresetExportClass::Find_Header (TextFileClass &file)
  457. {
  458. int class_id = 0;
  459. StringClass line;
  460. //
  461. // Keep reading lines of text from the file until we've
  462. // found the header
  463. //
  464. while (file.Read_Line (line)) {
  465. //
  466. // Check to see if this is the header
  467. //
  468. const char * HEADER_TEXT = "Level Edit Preset Export. Class ID: ";
  469. int header_len = ::lstrlen (HEADER_TEXT);
  470. if (::strnicmp (line, HEADER_TEXT, header_len) == 0) {
  471. //
  472. // Convert the remaining characters to a class ID
  473. //
  474. class_id = ::atoi (((const char *)line) + header_len);
  475. break;
  476. }
  477. }
  478. return class_id;
  479. }
  480. ///////////////////////////////////////////////////////////////////////
  481. //
  482. // Export
  483. //
  484. ///////////////////////////////////////////////////////////////////////
  485. void
  486. PresetExportClass::Export (uint32 class_id, const char *filename)
  487. {
  488. //
  489. // Try to open the log file
  490. //
  491. TextFileClass file (filename);
  492. if (file.Open (RawFileClass::WRITE)) {
  493. //
  494. // Write a header to the file
  495. //
  496. StringClass header;
  497. header.Format ("Level Edit Preset Export. Class ID: %d", class_id);
  498. file.Write_Line (header);
  499. file.Write_Line ("");
  500. file.Write_Line ("");
  501. //
  502. // Write a tab-delimited list of the parameter names we are going to
  503. // export
  504. //
  505. Write_Column_Headers (class_id, file);
  506. //
  507. // Export each preset
  508. //
  509. PresetClass *preset = NULL;
  510. for ( preset = PresetMgrClass::Get_First (class_id, PresetMgrClass::ID_CLASS);
  511. preset != NULL;
  512. preset = PresetMgrClass::Get_Next (preset, class_id, PresetMgrClass::ID_CLASS))
  513. {
  514. Export_Preset (file, preset);
  515. }
  516. //
  517. // Close the file
  518. //
  519. file.Close ();
  520. }
  521. return ;
  522. }
  523. ///////////////////////////////////////////////////////////////////////
  524. //
  525. // Can_Export_Parameter
  526. //
  527. ///////////////////////////////////////////////////////////////////////
  528. bool
  529. PresetExportClass::Can_Export_Parameter (ParameterClass *parameter)
  530. {
  531. bool retval = false;
  532. //
  533. // We can only export simple parameter types
  534. //
  535. if ( parameter->Get_Type () == ParameterClass::TYPE_INT ||
  536. parameter->Get_Type () == ParameterClass::TYPE_FLOAT ||
  537. parameter->Get_Type () == ParameterClass::TYPE_STRING ||
  538. parameter->Get_Type () == ParameterClass::TYPE_VECTOR3 ||
  539. parameter->Get_Type () == ParameterClass::TYPE_BOOL ||
  540. parameter->Get_Type () == ParameterClass::TYPE_FILENAME ||
  541. parameter->Get_Type () == ParameterClass::TYPE_ENUM ||
  542. parameter->Get_Type () == ParameterClass::TYPE_SOUND_FILENAME ||
  543. parameter->Get_Type () == ParameterClass::TYPE_ANGLE )
  544. {
  545. retval = true;
  546. }
  547. return retval;
  548. }
  549. ///////////////////////////////////////////////////////////////////////
  550. //
  551. // Write_Column_Headers
  552. //
  553. ///////////////////////////////////////////////////////////////////////
  554. void
  555. PresetExportClass::Write_Column_Headers (uint32 class_id, TextFileClass &file)
  556. {
  557. //
  558. // Write the column headers
  559. //
  560. PresetClass *first_preset = PresetMgrClass::Get_First (class_id, PresetMgrClass::ID_CLASS);
  561. if (first_preset != NULL) {
  562. StringClass column_headers = "Name\tPreset ID\t";
  563. //
  564. // Loop over all the parameters for this definition type
  565. //
  566. DefinitionClass *definition = first_preset->Get_Definition ();
  567. int count = definition->Get_Parameter_Count ();
  568. for (int index = 0; index < count; index ++) {
  569. ParameterClass *parameter = definition->Lock_Parameter (index);
  570. //
  571. // Check to ensure we can export this type of parameter
  572. //
  573. if (Can_Export_Parameter (parameter)) {
  574. column_headers += parameter->Get_Name ();
  575. column_headers += "\t";
  576. }
  577. definition->Unlock_Parameter (index);
  578. }
  579. //
  580. // Write the column headers to the file
  581. //
  582. file.Write_Line (column_headers);
  583. }
  584. return ;
  585. }
  586. ///////////////////////////////////////////////////////////////////////
  587. //
  588. // Export_Preset
  589. //
  590. ///////////////////////////////////////////////////////////////////////
  591. void
  592. PresetExportClass::Export_Preset (TextFileClass &file, PresetClass *preset)
  593. {
  594. //
  595. // Start the entry by filling in the preset's name and ID
  596. //
  597. StringClass settings = preset->Get_Name ();
  598. settings += "\t";
  599. StringClass id_string;
  600. id_string.Format ("%d", preset->Get_ID ());
  601. settings += id_string;
  602. settings += "\t";
  603. //
  604. // Loop over all the parameters for this definition type
  605. //
  606. DefinitionClass *definition = preset->Get_Definition ();
  607. int count = definition->Get_Parameter_Count ();
  608. for (int index = 0; index < count; index ++) {
  609. ParameterClass *parameter = definition->Lock_Parameter (index);
  610. //
  611. // Handle each type differently
  612. //
  613. switch (parameter->Get_Type ())
  614. {
  615. case ParameterClass::TYPE_INT:
  616. {
  617. //
  618. // Format the parameter value into a string
  619. //
  620. int param_value = ((IntParameterClass *)parameter)->Get_Value ();
  621. StringClass string_value;
  622. string_value.Format ("%d", param_value);
  623. //
  624. // Add this string to the end of the entry
  625. //
  626. settings += string_value;
  627. settings += "\t";
  628. }
  629. break;
  630. case ParameterClass::TYPE_FLOAT:
  631. {
  632. //
  633. // Format the parameter value into a string
  634. //
  635. float param_value = ((FloatParameterClass *)parameter)->Get_Value ();
  636. StringClass string_value;
  637. string_value.Format ("%f", param_value);
  638. //
  639. // Add this string to the end of the entry
  640. //
  641. settings += string_value;
  642. settings += "\t";
  643. }
  644. break;
  645. case ParameterClass::TYPE_FILENAME:
  646. case ParameterClass::TYPE_SOUND_FILENAME:
  647. case ParameterClass::TYPE_STRING:
  648. {
  649. //
  650. // Format the parameter value into a string
  651. //
  652. const char *param_value = ((StringParameterClass *)parameter)->Get_String ();
  653. //
  654. // Add this string to the end of the entry
  655. //
  656. settings += param_value;
  657. settings += "\t";
  658. }
  659. break;
  660. case ParameterClass::TYPE_VECTOR3:
  661. {
  662. //
  663. // Format the parameter value into a string
  664. //
  665. const Vector3 &param_value = ((Vector3ParameterClass *)parameter)->Get_Value ();
  666. StringClass string_value;
  667. string_value.Format ("\"%f, %f, %f\"", param_value.X, param_value.Y, param_value.Z);
  668. //
  669. // Add this string to the end of the entry
  670. //
  671. settings += string_value;
  672. settings += "\t";
  673. }
  674. break;
  675. case ParameterClass::TYPE_BOOL:
  676. {
  677. //
  678. // Format the parameter value into a string
  679. //
  680. int param_value = ((BoolParameterClass *)parameter)->Get_Value ();
  681. StringClass string_value;
  682. string_value.Format ("%d", param_value);
  683. //
  684. // Add this string to the end of the entry
  685. //
  686. settings += string_value;
  687. settings += "\t";
  688. }
  689. break;
  690. case ParameterClass::TYPE_ENUM:
  691. {
  692. //
  693. // Format the parameter value into a string
  694. //
  695. int param_value = ((EnumParameterClass *)parameter)->Get_Selected_Value ();
  696. StringClass string_value;
  697. string_value.Format ("%d", param_value);
  698. //
  699. // Add this string to the end of the entry
  700. //
  701. settings += string_value;
  702. settings += "\t";
  703. }
  704. break;
  705. case ParameterClass::TYPE_ANGLE:
  706. {
  707. //
  708. // Format the parameter value into a string
  709. //
  710. float param_value = ((AngleParameterClass *)parameter)->Get_Value ();
  711. StringClass string_value;
  712. string_value.Format ("%f", param_value);
  713. //
  714. // Add this string to the end of the entry
  715. //
  716. settings += string_value;
  717. settings += "\t";
  718. }
  719. break;
  720. }
  721. definition->Unlock_Parameter (index);
  722. }
  723. //
  724. // Write the settings to the file
  725. //
  726. file.Write_Line (settings);
  727. return ;
  728. }