PresetRemapDialog.cpp 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315
  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. // PresetRemapDialog.cpp : implementation file
  19. //
  20. #include "stdafx.h"
  21. #include "leveledit.h"
  22. #include "leveleditdoc.h"
  23. #include "presetremapdialog.h"
  24. #include "selectpresetdialog.h"
  25. #include "node.h"
  26. #include "nodemgr.h"
  27. #include "presetmgr.h"
  28. #ifdef _DEBUG
  29. #define new DEBUG_NEW
  30. #undef THIS_FILE
  31. static char THIS_FILE[] = __FILE__;
  32. #endif
  33. enum
  34. {
  35. COL_OBJECT = 0,
  36. COL_PRESET
  37. };
  38. /////////////////////////////////////////////////////////////////////////////
  39. // NODE_PRESET_INFO
  40. /////////////////////////////////////////////////////////////////////////////
  41. /*typedef struct _NODE_PRESET_INFO
  42. {
  43. PresetClass * preset;
  44. NodeClass * node;
  45. } NODE_PRESET_INFO;*/
  46. /////////////////////////////////////////////////////////////////////////////
  47. //
  48. // PresetRemapDialogClass
  49. //
  50. /////////////////////////////////////////////////////////////////////////////
  51. PresetRemapDialogClass::PresetRemapDialogClass (CWnd* pParent /*=NULL*/)
  52. : CDialog(PresetRemapDialogClass::IDD, pParent)
  53. {
  54. //{{AFX_DATA_INIT(PresetRemapDialogClass)
  55. // NOTE: the ClassWizard will add member initialization here
  56. //}}AFX_DATA_INIT
  57. return ;
  58. }
  59. /////////////////////////////////////////////////////////////////////////////
  60. //
  61. // DoDataExchange
  62. //
  63. /////////////////////////////////////////////////////////////////////////////
  64. void
  65. PresetRemapDialogClass::DoDataExchange (CDataExchange* pDX)
  66. {
  67. CDialog::DoDataExchange(pDX);
  68. //{{AFX_DATA_MAP(PresetRemapDialogClass)
  69. DDX_Control(pDX, IDC_LIST_CTRL, m_ListCtrl);
  70. //}}AFX_DATA_MAP
  71. return ;
  72. }
  73. BEGIN_MESSAGE_MAP(PresetRemapDialogClass, CDialog)
  74. //{{AFX_MSG_MAP(PresetRemapDialogClass)
  75. ON_NOTIFY(NM_DBLCLK, IDC_LIST_CTRL, OnDblclkListCtrl)
  76. ON_NOTIFY(LVN_DELETEITEM, IDC_LIST_CTRL, OnDeleteitemListCtrl)
  77. //}}AFX_MSG_MAP
  78. END_MESSAGE_MAP()
  79. /////////////////////////////////////////////////////////////////////////////
  80. //
  81. // OnInitDialog
  82. //
  83. /////////////////////////////////////////////////////////////////////////////
  84. BOOL
  85. PresetRemapDialogClass::OnInitDialog (void)
  86. {
  87. CDialog::OnInitDialog ();
  88. //
  89. // Configure the columns
  90. //
  91. m_ListCtrl.InsertColumn (COL_OBJECT, "Object");
  92. m_ListCtrl.InsertColumn (COL_PRESET, "Preset");
  93. m_ListCtrl.SetExtendedStyle (m_ListCtrl.GetExtendedStyle () | LVS_EX_FULLROWSELECT);
  94. //
  95. // Choose an appropriate size for the columns
  96. //
  97. CRect rect;
  98. m_ListCtrl.GetClientRect (&rect);
  99. rect.right -= ::GetSystemMetrics (SM_CXVSCROLL) + 2;
  100. m_ListCtrl.SetColumnWidth (COL_OBJECT, rect.Width () / 2);
  101. m_ListCtrl.SetColumnWidth (COL_PRESET, rect.Width () / 2);
  102. if (CLevelEditDoc::Is_Batch_Export_Mode ()) {
  103. //
  104. // Simply log the errors if we're in batch export mode
  105. //
  106. for (int index = 0; index < NodeList.Count (); index ++) {
  107. NodeClass *node = NodeList[index];
  108. if (node != NULL) {
  109. StringClass name = node->Get_Name ();
  110. WWDEBUG_SAY (("Unable to find preset for node: %s\n", (const char *)name));
  111. }
  112. }
  113. //
  114. // Close the dialog
  115. //
  116. EndDialog (IDOK);
  117. } else {
  118. //
  119. // Add the node's into the list control
  120. //
  121. for (int index = 0; index < NodeList.Count (); index ++) {
  122. NodeClass *node = NodeList[index];
  123. if (node != NULL) {
  124. StringClass name = node->Get_Name ();
  125. //
  126. // Add this object to the list control
  127. //
  128. int item_index = m_ListCtrl.InsertItem (0xFF, name);
  129. if (item_index >= 0) {
  130. m_ListCtrl.SetItemData (item_index, (DWORD)node);
  131. //
  132. // Take a best guess at a preset name for the object
  133. //
  134. char *separator = ::strchr (name, '.');
  135. if (separator != NULL) {
  136. separator[0] = 0;
  137. const char *candidate_preset_name = name;
  138. PresetClass *candidate_preset = PresetMgrClass::Find_Preset (candidate_preset_name);
  139. if (candidate_preset != NULL) {
  140. //
  141. // Associate the preset with the object
  142. //
  143. node->Set_Preset (candidate_preset);
  144. m_ListCtrl.SetItemText (item_index, COL_PRESET, candidate_preset->Get_Name ());
  145. }
  146. }
  147. }
  148. }
  149. }
  150. }
  151. return TRUE;
  152. }
  153. /////////////////////////////////////////////////////////////////////////////
  154. //
  155. // OnDblclkListCtrl
  156. //
  157. /////////////////////////////////////////////////////////////////////////////
  158. void
  159. PresetRemapDialogClass::OnDblclkListCtrl
  160. (
  161. NMHDR * pNMHDR,
  162. LRESULT * pResult
  163. )
  164. {
  165. (*pResult) = 0;
  166. //
  167. // Get the selected item
  168. //
  169. int item_index = m_ListCtrl.GetNextItem (-1, LVNI_SELECTED | LVNI_ALL);
  170. if (item_index >= 0) {
  171. //
  172. // Get the node from this item
  173. //
  174. NodeClass *node = (NodeClass *)m_ListCtrl.GetItemData (item_index);
  175. if (node != NULL) {
  176. //
  177. // Show a dialog to the user that will enable them to
  178. // select a new preset
  179. //
  180. SelectPresetDialogClass dialog (this);
  181. dialog.Set_Preset (node->Get_Preset ());
  182. if (dialog.DoModal () == IDOK) {
  183. //
  184. // Get the new preset from the dialog
  185. //
  186. PresetClass *preset = dialog.Get_Selection ();
  187. CString preset_name = preset->Get_Name ();
  188. //
  189. // Ask the user if they want to make this change to all the nodes
  190. //
  191. if (MessageBox ("Would you like to propagate this preset to all other nodes of the same original preset?", "Propagate", MB_YESNO | MB_ICONQUESTION)) {
  192. uint32 preset_id_to_change = node->Get_Preset_ID ();
  193. int count = m_ListCtrl.GetItemCount ();
  194. //
  195. // Loop over all the nodes in the list
  196. //
  197. for (int index = 0; index < count; index ++) {
  198. NodeClass *curr_node = (NodeClass *)m_ListCtrl.GetItemData (index);
  199. if (curr_node != NULL && curr_node->Get_Preset_ID () == preset_id_to_change) {
  200. //
  201. // Associate the preset with the object
  202. //
  203. curr_node->Set_Preset (preset);
  204. m_ListCtrl.SetItemText (index, COL_PRESET, preset_name);
  205. }
  206. }
  207. } else {
  208. //
  209. // Associate the preset with the object
  210. //
  211. node->Set_Preset (preset);
  212. m_ListCtrl.SetItemText (item_index, COL_PRESET, preset_name);
  213. }
  214. }
  215. }
  216. }
  217. return ;
  218. }
  219. /////////////////////////////////////////////////////////////////////////////
  220. //
  221. // OnDeleteitemListCtrl
  222. //
  223. /////////////////////////////////////////////////////////////////////////////
  224. void
  225. PresetRemapDialogClass::OnDeleteitemListCtrl
  226. (
  227. NMHDR * pNMHDR,
  228. LRESULT* pResult
  229. )
  230. {
  231. NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
  232. (*pResult) = 0;
  233. //
  234. // Free our hold on this node
  235. //
  236. NodeClass *node = (NodeClass *)m_ListCtrl.GetItemData (pNMListView->iItem);
  237. REF_PTR_RELEASE (node);
  238. m_ListCtrl.SetItemData (pNMListView->iItem, 0);
  239. return ;
  240. }
  241. /////////////////////////////////////////////////////////////////////////////
  242. //
  243. // OnOK
  244. //
  245. /////////////////////////////////////////////////////////////////////////////
  246. void
  247. PresetRemapDialogClass::OnOK (void)
  248. {
  249. CWaitCursor wait_cursor;
  250. //
  251. // Loop over all the nodes in the list
  252. //
  253. int count = m_ListCtrl.GetItemCount ();
  254. for (int index = 0; index < count; index ++) {
  255. NodeClass *curr_node = (NodeClass *)m_ListCtrl.GetItemData (index);
  256. if (curr_node->Get_Preset () != NULL) {
  257. //
  258. // Add this node to the world
  259. //
  260. curr_node->Initialize ();
  261. NodeMgrClass::Add_Node (curr_node);
  262. }
  263. }
  264. CDialog::OnOK ();
  265. return ;
  266. }