dlgevaviewertab.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489
  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 : Combat *
  23. * *
  24. * $Archive:: /Commando/Code/commando/dlgevaviewertab.cpp $*
  25. * *
  26. * Author:: Patrick Smith *
  27. * *
  28. * $Modtime:: 1/07/02 6:12p $*
  29. * *
  30. * $Revision:: 17 $*
  31. * *
  32. *---------------------------------------------------------------------------------------------*
  33. * Functions: *
  34. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  35. #include "dlgevaviewertab.h"
  36. #include "resource.h"
  37. #include "mapctrl.h"
  38. #include "combat.h"
  39. #include "soldier.h"
  40. #include "objectives.h"
  41. #include "translatedb.h"
  42. #include "translateobj.h"
  43. #include "listctrl.h"
  44. #include "dialogtext.h"
  45. #include "assets.h"
  46. #include "ini.h"
  47. #include "inisup.h"
  48. #include "listnode.h"
  49. #include "viewerctrl.h"
  50. #include "rendobj.h"
  51. #include "wheelvehicle.h"
  52. #include "string_ids.h"
  53. ////////////////////////////////////////////////////////////////
  54. //
  55. // EvaViewerTabClass
  56. //
  57. ////////////////////////////////////////////////////////////////
  58. EvaViewerTabClass::EvaViewerTabClass (int resource_id) :
  59. ListCtrl (NULL),
  60. DescriptionCtrl (NULL),
  61. AffiliationCtrl (NULL),
  62. ViewerCtrl (NULL),
  63. EncyclopediaType (EncyclopediaMgrClass::TYPE_CHARACTER),
  64. ChildDialogClass (resource_id)
  65. {
  66. return ;
  67. }
  68. ////////////////////////////////////////////////////////////////
  69. //
  70. // On_Init_Dialog
  71. //
  72. ////////////////////////////////////////////////////////////////
  73. void
  74. EvaViewerTabClass::On_Init_Dialog (void)
  75. {
  76. //
  77. // Generate a set of data to display to the user (from an INI)
  78. //
  79. Build_Object_List ();
  80. //
  81. // Configure the list control
  82. //
  83. ListCtrl->Add_Column (TRANSLATE (IDS_MENU_NAME), 1.0F, Vector3 (1, 1, 1));
  84. //
  85. // Add this data to the list control
  86. //
  87. int total_obj_count = 0;
  88. for (int index = 0; index < ObjectList.Count (); index ++) {
  89. EvaViewerObjectClass &object = ObjectList[index];
  90. //
  91. // Check to see if this entry should be displayed
  92. //
  93. if (EncyclopediaMgrClass::Is_Object_Revealed (EncyclopediaType, object.Get_ID ())) {
  94. //
  95. // Add an entry to the list control for this object
  96. //
  97. int item_index = ListCtrl->Insert_Entry (index, object.Get_Name ());
  98. if (item_index >= 0) {
  99. ListCtrl->Set_Entry_Data (item_index, 0, (uint32)&object);
  100. //
  101. // Colorize the entry
  102. //
  103. Vector3 color (1.0F, 1.0F, 1.0F);
  104. if (object.Get_Player_Type () == PLAYERTYPE_GDI) {
  105. color.Set (1.0F, 0.832F, 0.156F);
  106. } else if (object.Get_Player_Type () == PLAYERTYPE_NOD) {
  107. color.Set (1.0F, 0.0F, 0.0F);
  108. }
  109. ListCtrl->Set_Entry_Color (item_index, 0, color);
  110. total_obj_count ++;
  111. }
  112. }
  113. }
  114. //
  115. // Now, sort the players by rank
  116. //
  117. ListCtrl->Sort (ListSortCallback, 0);
  118. //
  119. // Select and view the first entry by default
  120. //
  121. if (total_obj_count > 0) {
  122. ListCtrl->Set_Curr_Sel (0);
  123. View_Entry (0);
  124. } else {
  125. if (AffiliationCtrl != NULL) {
  126. AffiliationCtrl->Set_Text (L"");
  127. }
  128. }
  129. ChildDialogClass::On_Init_Dialog ();
  130. return ;
  131. }
  132. ////////////////////////////////////////////////////////////////
  133. //
  134. // On_Destroy_Dialog
  135. //
  136. ////////////////////////////////////////////////////////////////
  137. void
  138. EvaViewerTabClass::On_Destroy_Dialog (void)
  139. {
  140. if (ViewerCtrl != NULL) {
  141. ViewerCtrl->Set_Model ((RenderObjClass *)NULL);
  142. }
  143. return ;
  144. }
  145. ////////////////////////////////////////////////////////////////
  146. //
  147. // Build_Object_List
  148. //
  149. ////////////////////////////////////////////////////////////////
  150. void
  151. EvaViewerTabClass::Build_Object_List (void)
  152. {
  153. ObjectList.Delete_All ();
  154. //
  155. // Get the INI file which contains the data for this viewer
  156. //
  157. INIClass *ini_file = ::Get_INI (INIFilename);
  158. if (ini_file != NULL) {
  159. //
  160. // Loop over all the sections in the INI
  161. //
  162. List<INISection *> &section_list = ini_file->Get_Section_List ();
  163. for ( INISection *section = section_list.First ();
  164. section != NULL;
  165. section = section->Next_Valid ())
  166. {
  167. //
  168. // Read this object's data from the INI file
  169. //
  170. StringClass name_id (0, true);
  171. StringClass description_id (0, true);
  172. StringClass affiliation_id (0, true);
  173. StringClass model_name (0, true);
  174. StringClass anim_name (0, true);
  175. StringClass definition_name (0, true);
  176. StringClass player_type_str (0, true);
  177. ini_file->Get_String (name_id, section->Section, "NameID");
  178. ini_file->Get_String (description_id, section->Section, "DescriptionID");
  179. ini_file->Get_String (affiliation_id, section->Section, "AffiliationID");
  180. ini_file->Get_String (model_name, section->Section, "Model");
  181. ini_file->Get_String (anim_name, section->Section, "Anim");
  182. ini_file->Get_String (definition_name, section->Section, "DefinitionName");
  183. ini_file->Get_String (player_type_str, section->Section, "PlayerType");
  184. int id = ini_file->Get_Int (section->Section, "ID");
  185. float min_dist = ini_file->Get_Float (section->Section, "MinDist");
  186. //
  187. // Determine the player type
  188. //
  189. int player_type = PLAYERTYPE_NEUTRAL;
  190. if (player_type_str.Compare_No_Case ("GDI") == 0) {
  191. player_type = PLAYERTYPE_GDI;
  192. } else if (player_type_str.Compare_No_Case ("NOD") == 0) {
  193. player_type = PLAYERTYPE_NOD;
  194. }
  195. //
  196. // Translate the data
  197. //
  198. const WCHAR *name = TRANSLATE_BY_DESC(name_id);
  199. const WCHAR *description = TRANSLATE_BY_DESC(description_id);
  200. const WCHAR *affiliation = TRANSLATE_BY_DESC(affiliation_id);
  201. //
  202. // Configure an object that will hold this data for us
  203. //
  204. EvaViewerObjectClass object;
  205. object.Set_ID (id);
  206. object.Set_Name (name);
  207. object.Set_Description (description);
  208. object.Set_Affiliation (affiliation);
  209. object.Set_Model_Name (model_name);
  210. object.Set_Anim_Name (anim_name);
  211. object.Set_Definition_Name (definition_name);
  212. object.Set_Min_Distance (min_dist);
  213. object.Set_Player_Type (player_type);
  214. //
  215. // Add this object to the list
  216. //
  217. ObjectList.Add (object);
  218. }
  219. delete ini_file;
  220. }
  221. return ;
  222. }
  223. ////////////////////////////////////////////////////////////////
  224. //
  225. // On_ListCtrl_Sel_Change
  226. //
  227. ////////////////////////////////////////////////////////////////
  228. void
  229. EvaViewerTabClass::On_ListCtrl_Sel_Change
  230. (
  231. ListCtrlClass * list_ctrl,
  232. int ctrl_id,
  233. int old_index,
  234. int new_index
  235. )
  236. {
  237. View_Entry (new_index);
  238. return ;
  239. }
  240. ////////////////////////////////////////////////////////////////
  241. //
  242. // View_Entry
  243. //
  244. ////////////////////////////////////////////////////////////////
  245. void
  246. EvaViewerTabClass::View_Entry (int entry_index)
  247. {
  248. WideStringClass name;
  249. WideStringClass description;
  250. WideStringClass affiliation;
  251. StringClass model_name;
  252. StringClass anim_name;
  253. StringClass definition_name;
  254. float min_dist = 0.0F;
  255. //
  256. // Is there new data to display?
  257. //
  258. if (entry_index >= 0) {
  259. //
  260. // Load the data for this selection
  261. //
  262. EvaViewerObjectClass *object = (EvaViewerObjectClass *)ListCtrl->Get_Entry_Data (entry_index, 0);
  263. name = object->Get_Name ();
  264. description = object->Get_Description ();
  265. affiliation = object->Get_Affiliation ();
  266. model_name = object->Get_Model_Name ();
  267. anim_name = object->Get_Anim_Name ();
  268. min_dist = object->Get_Min_Distance ();
  269. definition_name = object->Get_Definition_Name ();
  270. }
  271. //
  272. // Display the data
  273. //
  274. if (DescriptionCtrl != NULL) {
  275. DescriptionCtrl->Set_Text (description);
  276. }
  277. if (AffiliationCtrl != NULL) {
  278. AffiliationCtrl->Set_Text (affiliation);
  279. }
  280. if (ViewerCtrl != NULL) {
  281. ViewerCtrl->Set_Camera_Min_Dist (min_dist);
  282. //
  283. // Special-case vehicles so we can get the wheels to "drop"
  284. //
  285. if (EncyclopediaType == EncyclopediaMgrClass::TYPE_VEHICLE) {
  286. RenderObjClass *new_model = NULL;
  287. //
  288. // Try to find the definition that this vehicle is defined by
  289. //
  290. DefinitionClass *definition = DefinitionMgrClass::Find_Typed_Definition (definition_name, CLASSID_GAME_OBJECTS);
  291. if (definition != NULL) {
  292. PhysicalGameObj *game_obj = (PhysicalGameObj *)definition->Create ();
  293. if (game_obj != NULL) {
  294. //
  295. // Is the physics object associated with this game object a vehicle?
  296. //
  297. PhysClass *phys_obj = game_obj->Peek_Physical_Object ();
  298. if (phys_obj != NULL && phys_obj->As_VehiclePhysClass () != NULL) {
  299. //
  300. // Drop the wheels on this object and clone its model
  301. //
  302. phys_obj->As_VehiclePhysClass ()->Non_Physical_Wheel_Update (0.7F, 0);
  303. new_model = phys_obj->Peek_Model ()->Clone ();
  304. }
  305. //
  306. // Delete the game object
  307. //
  308. game_obj->Set_Delete_Pending ();
  309. }
  310. }
  311. //
  312. // Set the model we dug out of the definition, or
  313. // simply create the object from its W3D
  314. //
  315. if (new_model != NULL) {
  316. ViewerCtrl->Set_Model (new_model);
  317. } else {
  318. ViewerCtrl->Set_Model (model_name);
  319. }
  320. } else {
  321. ViewerCtrl->Set_Model (model_name);
  322. }
  323. //
  324. // Play the animation on the object
  325. //
  326. ViewerCtrl->Set_Animation (anim_name);
  327. }
  328. return ;
  329. }
  330. ////////////////////////////////////////////////////////////////
  331. //
  332. // On_ViewerCtrl_Model_Loaded
  333. //
  334. ////////////////////////////////////////////////////////////////
  335. void
  336. EvaViewerTabClass::On_ViewerCtrl_Model_Loaded
  337. (
  338. ViewerCtrlClass * viewer_ctrl,
  339. int ctrl_id,
  340. RenderObjClass * model
  341. )
  342. {
  343. if (model != NULL) {
  344. Prepare_Model (model);
  345. //
  346. // Start the image rotating again...
  347. //
  348. ViewerCtrl->Set_Interface_Mode (ViewerCtrlClass::Z_ROTATION, 45.0F);
  349. }
  350. return ;
  351. }
  352. ////////////////////////////////////////////////////////////////
  353. //
  354. // Prepare_Model
  355. //
  356. ////////////////////////////////////////////////////////////////
  357. void
  358. EvaViewerTabClass::Prepare_Model (RenderObjClass *model)
  359. {
  360. if (model != NULL) {
  361. //
  362. // Attempt to hide the muzzle flashes
  363. //
  364. for (int index = 0; index < model->Get_Num_Sub_Objects(); index ++) {
  365. RenderObjClass *sub_obj = model->Get_Sub_Object (index);
  366. //
  367. // Hide the muzzle flash (if necessary)
  368. //
  369. if (::strstr (sub_obj->Get_Name (),"MUZZLEFLASH") != NULL) {
  370. sub_obj->Set_Hidden (true);
  371. }
  372. //
  373. // Recurse into this sub-object
  374. //
  375. Prepare_Model (sub_obj);
  376. REF_PTR_RELEASE (sub_obj);
  377. }
  378. }
  379. return ;
  380. }
  381. ////////////////////////////////////////////////////////////////
  382. //
  383. // ListSortCallback
  384. //
  385. ////////////////////////////////////////////////////////////////
  386. int CALLBACK
  387. EvaViewerTabClass::ListSortCallback
  388. (
  389. ListCtrlClass * list_ctrl,
  390. int item_index1,
  391. int item_index2,
  392. uint32 user_param
  393. )
  394. {
  395. //
  396. // Lookup the data associated with these entries
  397. //
  398. EvaViewerObjectClass *object1 = (EvaViewerObjectClass *)list_ctrl->Get_Entry_Data (item_index1, 0);
  399. EvaViewerObjectClass *object2 = (EvaViewerObjectClass *)list_ctrl->Get_Entry_Data (item_index2, 0);
  400. int player_type1 = object1->Get_Player_Type ();
  401. int player_type2 = object2->Get_Player_Type ();
  402. int result = 0;
  403. //
  404. // Sort alphatically if the types are the same
  405. //
  406. if (player_type1 == player_type2) {
  407. result = ::wcsicmp (object1->Get_Name (), object2->Get_Name ());
  408. } else {
  409. //
  410. // Sort by type...
  411. //
  412. if (player_type1 == PLAYERTYPE_NEUTRAL) {
  413. result = -1;
  414. } else if (player_type2 == PLAYERTYPE_NEUTRAL) {
  415. result = 1;
  416. } else if (player_type1 == PLAYERTYPE_GDI) {
  417. result = -1;
  418. } else if (player_type2 == PLAYERTYPE_GDI) {
  419. result = 1;
  420. }
  421. }
  422. return result;
  423. }