PresetTransitionTab.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549
  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. // PresetGeneralTab.cpp : implementation file
  19. //
  20. #include "stdafx.h"
  21. #include "leveledit.h"
  22. #include "PresetTransitionTab.h"
  23. #include "definition.h"
  24. #include "preset.h"
  25. #include "utils.h"
  26. #include "TransitionEditDialog.h"
  27. #include "objectnode.h"
  28. #include "rendobj.h"
  29. #include "SceneEditor.h"
  30. #include "decophys.h"
  31. #include "CollisionGroups.h"
  32. #include "staticphys.h"
  33. #include "transition.h"
  34. #include "wheelvehicle.h"
  35. #include "cameramgr.h"
  36. #include "hlod.h"
  37. #include "rinfo.h"
  38. #ifdef _DEBUG
  39. #define new DEBUG_NEW
  40. #undef THIS_FILE
  41. static char THIS_FILE[] = __FILE__;
  42. #endif
  43. /////////////////////////////////////////////////////////////////////////////
  44. //
  45. // Constants
  46. //
  47. /////////////////////////////////////////////////////////////////////////////
  48. const float DROP_POS = 1000.0F;
  49. const float DROP_HEIGHT = 5.0F;
  50. const int COL_NAME = 0;
  51. const int COL_ANIMATION = 1;
  52. /////////////////////////////////////////////////////////////////////////////
  53. //
  54. // PresetTransitionTabClass
  55. //
  56. /////////////////////////////////////////////////////////////////////////////
  57. PresetTransitionTabClass::PresetTransitionTabClass (PresetClass *preset)
  58. : m_Preset (preset),
  59. m_Height (0),
  60. m_RenderObj (NULL),
  61. m_TransitionList (NULL),
  62. DockableFormClass(PresetTransitionTabClass::IDD)
  63. {
  64. //{{AFX_DATA_INIT(PresetTransitionTabClass)
  65. // NOTE: the ClassWizard will add member initialization here
  66. //}}AFX_DATA_INIT
  67. return ;
  68. }
  69. /////////////////////////////////////////////////////////////////////////////
  70. //
  71. // ~PresetTransitionTabClass
  72. //
  73. /////////////////////////////////////////////////////////////////////////////
  74. PresetTransitionTabClass::~PresetTransitionTabClass (void)
  75. {
  76. MEMBER_RELEASE (m_RenderObj);
  77. return ;
  78. }
  79. /////////////////////////////////////////////////////////////////////////////
  80. //
  81. // DoDataExchange
  82. //
  83. /////////////////////////////////////////////////////////////////////////////
  84. void
  85. PresetTransitionTabClass::DoDataExchange (CDataExchange *pDX)
  86. {
  87. DockableFormClass::DoDataExchange(pDX);
  88. //{{AFX_DATA_MAP(PresetTransitionTabClass)
  89. DDX_Control(pDX, IDC_TRANSITION_LIST, m_ListCtrl);
  90. //}}AFX_DATA_MAP
  91. return ;
  92. }
  93. BEGIN_MESSAGE_MAP(PresetTransitionTabClass, DockableFormClass)
  94. //{{AFX_MSG_MAP(PresetTransitionTabClass)
  95. ON_NOTIFY(LVN_ITEMCHANGED, IDC_TRANSITION_LIST, OnItemChangedTransitionList)
  96. ON_BN_CLICKED(IDC_ADD_BUTTON, OnAddButton)
  97. ON_BN_CLICKED(IDC_DELETE_BUTTON, OnDeleteButton)
  98. ON_BN_CLICKED(IDC_MODIFY_BUTTON, OnModifyButton)
  99. ON_NOTIFY(LVN_DELETEITEM, IDC_TRANSITION_LIST, OnDeleteitemTransitionList)
  100. ON_NOTIFY(NM_DBLCLK, IDC_TRANSITION_LIST, OnDblclkTransitionList)
  101. //}}AFX_MSG_MAP
  102. END_MESSAGE_MAP()
  103. #ifdef _DEBUG
  104. void PresetTransitionTabClass::AssertValid() const
  105. {
  106. DockableFormClass::AssertValid();
  107. }
  108. void PresetTransitionTabClass::Dump(CDumpContext& dc) const
  109. {
  110. DockableFormClass::Dump(dc);
  111. }
  112. #endif //_DEBUG
  113. /////////////////////////////////////////////////////////////////////////////
  114. //
  115. // HandleInitDialog
  116. //
  117. /////////////////////////////////////////////////////////////////////////////
  118. void
  119. PresetTransitionTabClass::HandleInitDialog (void)
  120. {
  121. ASSERT (m_Preset != NULL);
  122. m_ListCtrl.InsertColumn (COL_NAME, "Name");
  123. m_ListCtrl.InsertColumn (COL_ANIMATION, "Animation");
  124. //
  125. // Add the transitions to the list ctrl
  126. //
  127. int count = m_TransitionList->Count ();
  128. for (int index = 0; index < count; index ++) {
  129. //
  130. // Insert this transition into the control
  131. //
  132. TransitionDataClass *transition = (*m_TransitionList)[index];
  133. if (transition != NULL) {
  134. TransitionDataClass *our_copy = new TransitionDataClass;
  135. (*our_copy) = (*transition);
  136. Insert_Transition (our_copy);
  137. }
  138. }
  139. //
  140. // Size the columns
  141. //
  142. CRect rect;
  143. m_ListCtrl.GetWindowRect (&rect);
  144. m_ListCtrl.SetColumnWidth (COL_NAME, (rect.Width () >> 1) - 2);
  145. m_ListCtrl.SetColumnWidth (COL_ANIMATION, (rect.Width () >> 1) - 2);
  146. m_ListCtrl.SetFocus ();
  147. return ;
  148. }
  149. /////////////////////////////////////////////////////////////////////////////
  150. //
  151. // Apply_Changes
  152. //
  153. /////////////////////////////////////////////////////////////////////////////
  154. bool
  155. PresetTransitionTabClass::Apply_Changes (void)
  156. {
  157. // Assume success
  158. bool retval = true;
  159. //
  160. // Free the old transitions
  161. //
  162. int count = m_TransitionList->Count ();
  163. for (int index = 0; index < count; index ++) {
  164. TransitionDataClass *transition = (*m_TransitionList)[index];
  165. SAFE_DELETE (transition);
  166. }
  167. m_TransitionList->Delete_All ();
  168. //
  169. // Now, take all the transitions from the list control and add
  170. // the to the vector.
  171. //
  172. count = m_ListCtrl.GetItemCount ();
  173. for (index = 0; index < count; index ++) {
  174. TransitionDataClass *transition = (TransitionDataClass *)m_ListCtrl.GetItemData (index);
  175. if (transition != NULL) {
  176. m_TransitionList->Add (transition);
  177. m_ListCtrl.SetItemData (index, NULL);
  178. }
  179. }
  180. // Return true to allow the dialog to close
  181. return retval;
  182. }
  183. /////////////////////////////////////////////////////////////////////////////
  184. //
  185. // Insert_Transition
  186. //
  187. /////////////////////////////////////////////////////////////////////////////
  188. void
  189. PresetTransitionTabClass::Insert_Transition (TransitionDataClass *transition)
  190. {
  191. LPCTSTR name = transition->Get_Type_Name (transition->Get_Type ());
  192. int index = m_ListCtrl.InsertItem (0xFF, name);
  193. if (index >= 0) {
  194. m_ListCtrl.SetItemText (index, COL_ANIMATION, transition->Get_Animation_Name ());
  195. m_ListCtrl.SetItemData (index, (ULONG)transition);
  196. }
  197. return ;
  198. }
  199. /////////////////////////////////////////////////////////////////////////////
  200. //
  201. // OnAddButton
  202. //
  203. /////////////////////////////////////////////////////////////////////////////
  204. void
  205. PresetTransitionTabClass::OnAddButton (void)
  206. {
  207. Create_Render_Obj ();
  208. //
  209. // Show the transition editor
  210. //
  211. if (m_RenderObj != NULL) {
  212. //
  213. // Create a new transition
  214. //
  215. TransitionDataClass *transition = new TransitionDataClass;
  216. transition->Set_Type ((TransitionDataClass::StyleType)0);
  217. //
  218. // Give the transition a starting position and size
  219. //
  220. AABoxClass box = m_RenderObj->Get_Bounding_Box ();
  221. OBBoxClass zone (Vector3 (0, -(box.Extent.Y+0.5F), 0.5F), Vector3 (1, 1, 1));
  222. transition->Set_Zone (zone);
  223. transition->Set_Ending_TM (Matrix3D (zone.Center-Vector3 (0, 0, 0.5F)));
  224. //
  225. // Show the transition edit dialog
  226. //
  227. TransitionEditDialogClass dialog (this);
  228. dialog.Set_Render_Obj (m_RenderObj);
  229. dialog.Set_Start_Height (m_Height);
  230. dialog.Set_Transition (transition);
  231. if (dialog.DoModal () == IDOK) {
  232. //
  233. // Update the list ctrl
  234. //
  235. Insert_Transition (transition);
  236. } else {
  237. SAFE_DELETE (transition);
  238. }
  239. }
  240. return ;
  241. }
  242. /////////////////////////////////////////////////////////////////////////////
  243. //
  244. // OnDeleteButton
  245. //
  246. /////////////////////////////////////////////////////////////////////////////
  247. void
  248. PresetTransitionTabClass::OnDeleteButton (void)
  249. {
  250. //
  251. // Get the currently selected item
  252. //
  253. int index = m_ListCtrl.GetNextItem (-1, LVNI_ALL | LVNI_SELECTED);
  254. if (index >= 0) {
  255. //
  256. // Delete the transition and remove it from the UI
  257. //
  258. TransitionDataClass *transition = (TransitionDataClass *)m_ListCtrl.GetItemData (index);
  259. if (transition != NULL) {
  260. SAFE_DELETE (transition);
  261. m_ListCtrl.SetItemData (index, NULL);
  262. }
  263. m_ListCtrl.DeleteItem (index);
  264. }
  265. return ;
  266. }
  267. /////////////////////////////////////////////////////////////////////////////
  268. //
  269. // OnModifyButton
  270. //
  271. /////////////////////////////////////////////////////////////////////////////
  272. void
  273. PresetTransitionTabClass::OnModifyButton (void)
  274. {
  275. Create_Render_Obj ();
  276. if (m_RenderObj != NULL) {
  277. //
  278. // Get the currently selected item
  279. //
  280. int index = m_ListCtrl.GetNextItem (-1, LVNI_ALL | LVNI_SELECTED);
  281. if (index >= 0) {
  282. //
  283. // Delete the transition and remove it from the UI
  284. //
  285. TransitionDataClass *transition = (TransitionDataClass *)m_ListCtrl.GetItemData (index);
  286. if (transition != NULL) {
  287. //
  288. // Show the transition edit dialog
  289. //
  290. TransitionEditDialogClass dialog (this);
  291. dialog.Set_Render_Obj (m_RenderObj);
  292. dialog.Set_Start_Height (m_Height);
  293. dialog.Set_Transition (transition);
  294. if (dialog.DoModal () == IDOK) {
  295. //
  296. // Update the list ctrl
  297. //
  298. LPCTSTR name = transition->Get_Type_Name (transition->Get_Type ());
  299. m_ListCtrl.SetItemText (index, COL_NAME, name);
  300. m_ListCtrl.SetItemText (index, COL_ANIMATION, transition->Get_Animation_Name ());
  301. }
  302. }
  303. }
  304. }
  305. return ;
  306. }
  307. /////////////////////////////////////////////////////////////////////////////
  308. //
  309. // OnItemChangedTransitionList
  310. //
  311. /////////////////////////////////////////////////////////////////////////////
  312. void
  313. PresetTransitionTabClass::OnItemChangedTransitionList
  314. (
  315. NMHDR * pNMHDR,
  316. LRESULT* pResult
  317. )
  318. {
  319. NM_LISTVIEW *pNMListView = (NM_LISTVIEW *)pNMHDR;
  320. (*pResult) = 0;
  321. int index = m_ListCtrl.GetNextItem (-1, LVNI_ALL | LVNI_SELECTED);
  322. if (index >= 0) {
  323. ::EnableWindow (::GetDlgItem (m_hWnd, IDC_MODIFY_BUTTON), true);
  324. ::EnableWindow (::GetDlgItem (m_hWnd, IDC_DELETE_BUTTON), true);
  325. } else {
  326. ::EnableWindow (::GetDlgItem (m_hWnd, IDC_MODIFY_BUTTON), false);
  327. ::EnableWindow (::GetDlgItem (m_hWnd, IDC_DELETE_BUTTON), false);
  328. }
  329. return ;
  330. }
  331. /////////////////////////////////////////////////////////////////////////////
  332. //
  333. // Create_Render_Obj
  334. //
  335. /////////////////////////////////////////////////////////////////////////////
  336. void
  337. PresetTransitionTabClass::Create_Render_Obj (void)
  338. {
  339. CWaitCursor wait_cursor;
  340. if (m_RenderObj == NULL && m_Preset != NULL) {
  341. //
  342. // Instantiate the node
  343. //
  344. NodeClass *node = (NodeClass *)m_Preset->Create ();
  345. ASSERT (node != NULL);
  346. if (node != NULL) {
  347. //
  348. // Initialize the game object and get its render object pointer
  349. //
  350. node->Initialize ();
  351. RenderObjClass *render_obj = node->Peek_Render_Obj ();
  352. ASSERT (render_obj != NULL);
  353. if (render_obj != NULL) {
  354. PhysClass *phys_obj = node->Peek_Physics_Obj ();
  355. if (phys_obj != NULL && phys_obj->As_DecorationPhysClass () == NULL) {
  356. SceneEditorClass *scene = ::Get_Scene_Editor ();
  357. //
  358. // Create a 'floor' which we can drop the object onto
  359. //
  360. PhysClass *phys_obj = node->Peek_Physics_Obj ();
  361. RenderObjClass *floor = ::Create_Render_Obj ("GRID");
  362. if (floor != NULL) {
  363. phys_obj->Set_Transform (Matrix3D (Vector3(0, 0, DROP_POS)));
  364. //
  365. // Determine what height we should drop the object from
  366. //
  367. float drop_height = DROP_HEIGHT;
  368. if (phys_obj->Peek_Model () != NULL) {
  369. drop_height = (phys_obj->Peek_Model ()->Get_Bounding_Box ().Extent.Z * 2.0F);
  370. }
  371. //
  372. // Create the floor
  373. //
  374. StaticPhysClass *floor_phys = new StaticPhysClass;
  375. floor_phys->Set_Model (floor);
  376. floor_phys->Set_Transform (Matrix3D (Vector3(0, 0, DROP_POS-drop_height)));
  377. floor_phys->Set_Collision_Group (MOUSE_CLICK_COLLISION_GROUP);
  378. scene->Add_Static_Object (floor_phys);
  379. scene->Validate_Vis ();
  380. /*Matrix3D tm;
  381. tm.Look_At (Vector3 (0, -12, DROP_POS-drop_height+2), Vector3 (0, 0, DROP_POS-drop_height), 0);
  382. ::Get_Camera_Mgr ()->Get_Camera ()->Set_Transform (tm);
  383. scene->Add_Dynamic_Object (phys_obj);*/
  384. //
  385. // Drop the object onto the floor
  386. //
  387. for (int index = 0; index < 50; index ++) {
  388. phys_obj->Timestep (0.05F);
  389. if (phys_obj->As_VehiclePhysClass () != NULL) {
  390. phys_obj->As_VehiclePhysClass ()->Update_Wheels ();
  391. }
  392. //::Refresh_Main_View ();
  393. }
  394. //
  395. // Determine how high the object sits ontop of the ground
  396. //
  397. m_Height = phys_obj->Get_Transform ().Get_Translation ().Z - (DROP_POS - drop_height);
  398. if (WWMath::Is_Valid_Float (m_Height) == false || WWMath::Fabs (m_Height) > 4.0F) {
  399. m_Height = 0.5F;
  400. }
  401. //
  402. // Cleanup
  403. //
  404. //scene->Remove_Object (phys_obj);
  405. scene->Remove_Object (floor_phys);
  406. scene->Validate_Vis ();
  407. floor_phys->Release_Ref ();
  408. floor->Release_Ref ();
  409. }
  410. }
  411. //
  412. // Keep a copy of the render object for our own uses.
  413. //
  414. m_RenderObj = render_obj->Clone ();
  415. //
  416. // Force the object to use its highest LOD
  417. //
  418. if (m_RenderObj->Class_ID () == RenderObjClass::CLASSID_HLOD) {
  419. HLodClass *lod_obj = (HLodClass *)m_RenderObj;
  420. lod_obj->Set_LOD_Level (lod_obj->Get_LOD_Count () - 1);
  421. }
  422. }
  423. MEMBER_RELEASE (node);
  424. } else {
  425. ::Message_Box (m_hWnd, IDS_CANT_CREATE_OBJECT_MSG, IDS_CANT_CREATE_OBJECT_TITLE);
  426. }
  427. }
  428. return ;
  429. }
  430. /////////////////////////////////////////////////////////////////////////////
  431. //
  432. // OnDeleteitemTransitionList
  433. //
  434. /////////////////////////////////////////////////////////////////////////////
  435. void
  436. PresetTransitionTabClass::OnDeleteitemTransitionList
  437. (
  438. NMHDR * pNMHDR,
  439. LRESULT * pResult
  440. )
  441. {
  442. NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
  443. (*pResult) = 0;
  444. //
  445. // Delete the transition pointer
  446. //
  447. TransitionDataClass *transition = (TransitionDataClass *)m_ListCtrl.GetItemData (pNMListView->iItem);
  448. if (transition != NULL) {
  449. SAFE_DELETE (transition);
  450. m_ListCtrl.SetItemData (pNMListView->iItem, NULL);
  451. }
  452. return ;
  453. }
  454. /////////////////////////////////////////////////////////////////////////////
  455. //
  456. // OnDeleteitemTransitionList
  457. //
  458. /////////////////////////////////////////////////////////////////////////////
  459. void
  460. PresetTransitionTabClass::OnDblclkTransitionList
  461. (
  462. NMHDR * pNMHDR,
  463. LRESULT *pResult
  464. )
  465. {
  466. (*pResult) = 0;
  467. OnModifyButton ();
  468. return ;
  469. }