OverlapPage.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466
  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/OverlapPage.cpp $*
  25. * *
  26. * Author:: Patrick Smith *
  27. * *
  28. * $Modtime:: 4/11/00 5:48p $*
  29. * *
  30. * $Revision:: 3 $*
  31. * *
  32. *---------------------------------------------------------------------------------------------*
  33. * Functions: *
  34. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  35. #include "stdafx.h"
  36. #include "leveledit.h"
  37. #include "OverlapPage.h"
  38. #include "nodemgr.h"
  39. #include "node.h"
  40. #include "coltest.h"
  41. #include "icons.h"
  42. #include "cameramgr.h"
  43. #ifdef _DEBUG
  44. #define new DEBUG_NEW
  45. #undef THIS_FILE
  46. static char THIS_FILE[] = __FILE__;
  47. #endif
  48. /////////////////////////////////////////////////////////////////////////////
  49. // Local constants
  50. /////////////////////////////////////////////////////////////////////////////
  51. static const int TOOLBAR_HEIGHT = 25;
  52. static const int TOOLBAR_V_SPACING = 5;
  53. static const int TOOLBAR_V_BORDER = TOOLBAR_V_SPACING * 2;
  54. static const int TOOLBAR_H_SPACING = 5;
  55. static const int TOOLBAR_H_BORDER = TOOLBAR_H_SPACING * 2;
  56. /////////////////////////////////////////////////////////////////////////////
  57. //
  58. // OverlapPageClass
  59. //
  60. /////////////////////////////////////////////////////////////////////////////
  61. OverlapPageClass::OverlapPageClass(CWnd* pParent /*=NULL*/)
  62. : CDialog(OverlapPageClass::IDD, pParent),
  63. m_SoundsRoot (NULL),
  64. m_LightsRoot (NULL)
  65. {
  66. //{{AFX_DATA_INIT(OverlapPageClass)
  67. // NOTE: the ClassWizard will add member initialization here
  68. //}}AFX_DATA_INIT
  69. Create (OverlapPageClass::IDD, pParent);
  70. return ;
  71. }
  72. /////////////////////////////////////////////////////////////////////////////
  73. //
  74. // ~OverlapPageClass
  75. //
  76. /////////////////////////////////////////////////////////////////////////////
  77. OverlapPageClass::~OverlapPageClass (void)
  78. {
  79. return ;
  80. }
  81. /////////////////////////////////////////////////////////////////////////////
  82. //
  83. // DoDataExchange
  84. //
  85. /////////////////////////////////////////////////////////////////////////////
  86. void
  87. OverlapPageClass::DoDataExchange (CDataExchange *pDX)
  88. {
  89. CDialog::DoDataExchange(pDX);
  90. //{{AFX_DATA_MAP(OverlapPageClass)
  91. DDX_Control(pDX, IDC_OVERLAP_TREE, m_TreeCtrl);
  92. //}}AFX_DATA_MAP
  93. return ;
  94. }
  95. BEGIN_MESSAGE_MAP(OverlapPageClass, CDialog)
  96. //{{AFX_MSG_MAP(OverlapPageClass)
  97. ON_NOTIFY(TVN_DELETEITEM, IDC_OVERLAP_TREE, OnDeleteitemOverlapTree)
  98. ON_WM_SIZE()
  99. ON_WM_DESTROY()
  100. ON_COMMAND(IDC_REFRESH, OnRefresh)
  101. ON_NOTIFY(NM_DBLCLK, IDC_OVERLAP_TREE, OnDblclkOverlapTree)
  102. ON_NOTIFY(TVN_ITEMEXPANDED, IDC_OVERLAP_TREE, OnItemexpandedOverlapTree)
  103. //}}AFX_MSG_MAP
  104. END_MESSAGE_MAP()
  105. /////////////////////////////////////////////////////////////////////////////
  106. //
  107. // OnSize
  108. //
  109. /////////////////////////////////////////////////////////////////////////////
  110. void
  111. OverlapPageClass::OnSize
  112. (
  113. UINT nType,
  114. int cx,
  115. int cy
  116. )
  117. {
  118. // Allow the base class to process this message
  119. CDialog::OnSize (nType, cx, cy);
  120. if (::IsWindow (m_TreeCtrl) && (cx > 0) && (cy > 0)) {
  121. // Get the bounding rectangle of the form window
  122. CRect parentrect;
  123. GetWindowRect (&parentrect);
  124. // Get the bounding rectangle of the toolbar
  125. CRect toolbar_rect;
  126. m_Toolbar.GetWindowRect (&toolbar_rect);
  127. ScreenToClient (&toolbar_rect);
  128. // Move the toolbar so it is in its correct position
  129. m_Toolbar.SetWindowPos (NULL,
  130. TOOLBAR_H_SPACING,
  131. (cy - TOOLBAR_V_SPACING) - toolbar_rect.Height (),
  132. cx - TOOLBAR_H_BORDER,
  133. toolbar_rect.Height (),
  134. SWP_NOZORDER);
  135. // Get the bounding rectnagle of the list ctrl
  136. RECT list_rect;
  137. m_TreeCtrl.GetWindowRect (&list_rect);
  138. CRect client_rect = list_rect;
  139. ScreenToClient (&client_rect);
  140. int list_height = ((cy - TOOLBAR_V_BORDER) - toolbar_rect.Height ()) - client_rect.top;
  141. // Resize the tab control to fill the entire contents of the client area
  142. m_TreeCtrl.SetWindowPos ( NULL,
  143. 0,
  144. 0,
  145. cx-((list_rect.left - parentrect.left) << 1),
  146. list_height,
  147. SWP_NOZORDER | SWP_NOMOVE);
  148. }
  149. return ;
  150. }
  151. /////////////////////////////////////////////////////////////////////////////
  152. //
  153. // OnDestroy
  154. //
  155. /////////////////////////////////////////////////////////////////////////////
  156. void
  157. OverlapPageClass::OnDestroy (void)
  158. {
  159. // Free the state image list we associated with the control
  160. CImageList *imagelist = m_TreeCtrl.GetImageList (TVSIL_STATE);
  161. m_TreeCtrl.SetImageList (NULL, TVSIL_STATE);
  162. SAFE_DELETE (imagelist);
  163. // Remove the main image list we associated with the control
  164. m_TreeCtrl.SetImageList (NULL, TVSIL_NORMAL);
  165. m_TreeCtrl.DeleteAllItems ();
  166. ::RemoveProp (m_TreeCtrl, "TRANS_ACCS");
  167. ::RemoveProp (m_hWnd, "TRANS_ACCS");
  168. // Allow the base class to process this message
  169. CDialog::OnDestroy ();
  170. return ;
  171. }
  172. ////////////////////////////////////////////////////////////////////////////
  173. //
  174. // OnInitDialog
  175. //
  176. ////////////////////////////////////////////////////////////////////////////
  177. BOOL
  178. OverlapPageClass::OnInitDialog (void)
  179. {
  180. CDialog::OnInitDialog ();
  181. m_Toolbar.CreateEx (this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_ALIGN_TOP, CRect(0, 0, 0, 0), 101);
  182. m_Toolbar.SetOwner (this);
  183. m_Toolbar.LoadToolBar (IDR_OVERLAP_TOOLBAR);
  184. m_Toolbar.SetBarStyle (m_Toolbar.GetBarStyle () | CBRS_TOOLTIPS | CBRS_FLYBY);
  185. //
  186. // Size the toolbar
  187. //
  188. CRect parentrect;
  189. GetWindowRect (&parentrect);
  190. m_Toolbar.SetWindowPos (NULL, 0, 0, parentrect.Width () - TOOLBAR_H_BORDER, TOOLBAR_HEIGHT, SWP_NOZORDER | SWP_NOMOVE);
  191. //
  192. // Pass the general use imagelist onto the tree control
  193. //
  194. m_TreeCtrl.SetImageList (::Get_Global_Image_List (), TVSIL_NORMAL);
  195. SetProp (m_TreeCtrl, "TRANS_ACCS", (HANDLE)1);
  196. SetProp (m_hWnd, "TRANS_ACCS", (HANDLE)1);
  197. Reset_Tree ();
  198. return TRUE;
  199. }
  200. /////////////////////////////////////////////////////////////////////////////
  201. //
  202. // OnDeleteitemOverlapTree
  203. //
  204. /////////////////////////////////////////////////////////////////////////////
  205. void
  206. OverlapPageClass::OnDeleteitemOverlapTree
  207. (
  208. NMHDR * pNMHDR,
  209. LRESULT *pResult
  210. )
  211. {
  212. NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
  213. (*pResult) = 0;
  214. return ;
  215. }
  216. /////////////////////////////////////////////////////////////////////////////
  217. //
  218. // Build_Tree
  219. //
  220. /////////////////////////////////////////////////////////////////////////////
  221. void
  222. OverlapPageClass::Build_Tree (void)
  223. {
  224. Reset_Tree ();
  225. //
  226. // Fill the sub-nodes
  227. //
  228. Detect_Overlaps (m_SoundsRoot, NODE_TYPE_SOUND);
  229. Detect_Overlaps (m_LightsRoot, NODE_TYPE_LIGHT);
  230. return ;
  231. }
  232. /////////////////////////////////////////////////////////////////////////////
  233. //
  234. // Reset_Tree
  235. //
  236. /////////////////////////////////////////////////////////////////////////////
  237. void
  238. OverlapPageClass::Reset_Tree (void)
  239. {
  240. m_TreeCtrl.DeleteAllItems ();
  241. //
  242. // Insert the root nodes
  243. //
  244. m_SoundsRoot = m_TreeCtrl.InsertItem ("Sounds", FOLDER_ICON, FOLDER_ICON);
  245. m_LightsRoot = m_TreeCtrl.InsertItem ("Lights", FOLDER_ICON, FOLDER_ICON);
  246. return ;
  247. }
  248. /////////////////////////////////////////////////////////////////////////////
  249. //
  250. // Detect_Overlaps
  251. //
  252. /////////////////////////////////////////////////////////////////////////////
  253. void
  254. OverlapPageClass::Detect_Overlaps (HTREEITEM root_item, NODE_TYPE node_type)
  255. {
  256. //
  257. // Loop over each node (of the given type) in the world
  258. //
  259. NodeClass *node1 = NULL;
  260. for ( node1 = NodeMgrClass::Get_First (node_type);
  261. node1 != NULL;
  262. node1 = NodeMgrClass::Get_Next (node1, node_type))
  263. {
  264. //
  265. // Check this node against every other node (of the sametype) in the world
  266. //
  267. HTREEITEM tree_item = NULL;
  268. NodeClass *node2 = NULL;
  269. for ( node2 = NodeMgrClass::Get_First (node_type);
  270. node2 != NULL;
  271. node2 = NodeMgrClass::Get_Next (node2, node_type))
  272. {
  273. if (node1 != node2) {
  274. SphereClass sphere1 (node1->Get_Position (), node1->Get_Attenuation_Radius ());
  275. SphereClass sphere2 (node2->Get_Position (), node2->Get_Attenuation_Radius ());
  276. //
  277. // Do these spheres intersect?
  278. //
  279. if (CollisionMath::Overlap_Test (sphere1, sphere2) != CollisionMath::OUTSIDE) {
  280. //
  281. // Add a tree entry for this node (if necessary)
  282. //
  283. if (tree_item == NULL) {
  284. tree_item = Insert_Node (root_item, node1);
  285. }
  286. //
  287. // Add this node as a sub-entry under the tree
  288. //
  289. Insert_Node (tree_item, node2);
  290. }
  291. }
  292. }
  293. }
  294. return ;
  295. }
  296. /////////////////////////////////////////////////////////////////////////////
  297. //
  298. // Insert_Node
  299. //
  300. /////////////////////////////////////////////////////////////////////////////
  301. HTREEITEM
  302. OverlapPageClass::Insert_Node (HTREEITEM parent_item, NodeClass *node)
  303. {
  304. //
  305. // Add this node to the tree
  306. //
  307. int icon_index = node->Get_Icon_Index ();
  308. HTREEITEM tree_item = m_TreeCtrl.InsertItem ( node->Get_Name (),
  309. icon_index,
  310. icon_index,
  311. parent_item);
  312. //
  313. // Save the node's ID with the tree entry so we can look it up later...
  314. //
  315. if (tree_item != NULL) {
  316. m_TreeCtrl.SetItemData (tree_item, node->Get_ID ());
  317. }
  318. return tree_item;
  319. }
  320. /////////////////////////////////////////////////////////////////////////////
  321. //
  322. // OnRefresh
  323. //
  324. /////////////////////////////////////////////////////////////////////////////
  325. void
  326. OverlapPageClass::OnRefresh (void)
  327. {
  328. Build_Tree ();
  329. return ;
  330. }
  331. ////////////////////////////////////////////////////////////////////////////
  332. //
  333. // OnDblclkOverlapTree
  334. //
  335. ////////////////////////////////////////////////////////////////////////////
  336. void
  337. OverlapPageClass::OnDblclkOverlapTree
  338. (
  339. NMHDR * pNMHDR,
  340. LRESULT * pResult
  341. )
  342. {
  343. //
  344. // Determine what client-coord location was double-clicked on
  345. //
  346. DWORD mouse_pos = ::GetMessagePos ();
  347. POINT hit_point = { GET_X_LPARAM (mouse_pos), GET_Y_LPARAM (mouse_pos) };
  348. m_TreeCtrl.ScreenToClient (&hit_point);
  349. //
  350. // Goto the node that was double-clicked on (if possible)
  351. //
  352. UINT flags = 0;
  353. HTREEITEM tree_item = m_TreeCtrl.HitTest (hit_point, &flags);
  354. if (tree_item != NULL && flags & TVHT_ONITEMLABEL) {
  355. //
  356. // Lookup the node from its ID
  357. //
  358. int node_id = m_TreeCtrl.GetItemData (tree_item);
  359. NodeClass *node = NodeMgrClass::Find_Node (node_id);
  360. if (node != NULL) {
  361. //
  362. // Reposition the camera so its looking at the node
  363. //
  364. ::Get_Camera_Mgr ()->Goto_Node (node);
  365. }
  366. }
  367. (*pResult) = 0;
  368. return ;
  369. }
  370. ////////////////////////////////////////////////////////////////////////////
  371. //
  372. // OnItemexpandedOverlapTree
  373. //
  374. ////////////////////////////////////////////////////////////////////////////
  375. void
  376. OverlapPageClass::OnItemexpandedOverlapTree
  377. (
  378. NMHDR * pNMHDR,
  379. LRESULT * pResult
  380. )
  381. {
  382. NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
  383. //
  384. // If this is a folder, then change its image based
  385. // on its expanded state.
  386. //
  387. uint32 node_id = m_TreeCtrl.GetItemData (pNMTreeView->itemNew.hItem);
  388. if (node_id == 0) {
  389. if (pNMTreeView->itemNew.state & TVIS_EXPANDED) {
  390. m_TreeCtrl.SetItemImage (pNMTreeView->itemNew.hItem, OPEN_FOLDER_ICON, OPEN_FOLDER_ICON);
  391. } else {
  392. m_TreeCtrl.SetItemImage (pNMTreeView->itemNew.hItem, FOLDER_ICON, FOLDER_ICON);
  393. }
  394. }
  395. (*pResult) = 0;
  396. return ;
  397. }