PositionPage.cpp 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361
  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. // PositionPage.cpp : implementation file
  19. //
  20. #include "stdafx.h"
  21. #include "leveledit.h"
  22. #include "positionpage.h"
  23. #include "node.h"
  24. #include "utils.h"
  25. #include "sceneeditor.h"
  26. #include "mover.h"
  27. #ifdef _DEBUG
  28. #define new DEBUG_NEW
  29. #undef THIS_FILE
  30. static char THIS_FILE[] = __FILE__;
  31. #endif
  32. /////////////////////////////////////////////////////////////////////////////
  33. //
  34. // PositionPageClass
  35. //
  36. /////////////////////////////////////////////////////////////////////////////
  37. PositionPageClass::PositionPageClass (void)
  38. : m_pNode (NULL),
  39. m_bInclueRotation (false),
  40. DockableFormClass (PositionPageClass::IDD)
  41. {
  42. return ;
  43. }
  44. /////////////////////////////////////////////////////////////////////////////
  45. //
  46. // PositionPageClass
  47. //
  48. /////////////////////////////////////////////////////////////////////////////
  49. PositionPageClass::PositionPageClass (NodeClass *node)
  50. : m_pNode (node),
  51. m_bInclueRotation (false),
  52. DockableFormClass (PositionPageClass::IDD)
  53. {
  54. //{{AFX_DATA_INIT(PositionPageClass)
  55. // NOTE: the ClassWizard will add member initialization here
  56. //}}AFX_DATA_INIT
  57. return ;
  58. }
  59. /////////////////////////////////////////////////////////////////////////////
  60. //
  61. // ~PositionPageClass
  62. //
  63. /////////////////////////////////////////////////////////////////////////////
  64. PositionPageClass::~PositionPageClass (void)
  65. {
  66. return ;
  67. }
  68. /////////////////////////////////////////////////////////////////////////////
  69. //
  70. // DoDataExchange
  71. //
  72. /////////////////////////////////////////////////////////////////////////////
  73. void
  74. PositionPageClass::DoDataExchange (CDataExchange* pDX)
  75. {
  76. DockableFormClass::DoDataExchange(pDX);
  77. //{{AFX_DATA_MAP(PositionPageClass)
  78. // NOTE: the ClassWizard will add DDX and DDV calls here
  79. //}}AFX_DATA_MAP
  80. return ;
  81. }
  82. BEGIN_MESSAGE_MAP(PositionPageClass, DockableFormClass)
  83. //{{AFX_MSG_MAP(PositionPageClass)
  84. ON_NOTIFY(UDN_DELTAPOS, IDC_XPOS_SPIN, OnDeltaPosXPosSpin)
  85. ON_NOTIFY(UDN_DELTAPOS, IDC_XROT_SPIN, OnDeltaPosXRotSpin)
  86. ON_NOTIFY(UDN_DELTAPOS, IDC_YPOS_SPIN, OnDeltaPosYPosSpin)
  87. ON_NOTIFY(UDN_DELTAPOS, IDC_YROT_SPIN, OnDeltaPosYRotSpin)
  88. ON_NOTIFY(UDN_DELTAPOS, IDC_ZPOS_SPIN, OnDeltaPosZPosSpin)
  89. ON_NOTIFY(UDN_DELTAPOS, IDC_ZROT_SPIN, OnDeltaPosZRotSpin)
  90. ON_EN_CHANGE(IDC_ZROT_EDIT, OnChangeZRotEdit)
  91. //}}AFX_MSG_MAP
  92. END_MESSAGE_MAP()
  93. /////////////////////////////////////////////////////////////////////////////
  94. // PositionPageClass diagnostics
  95. #ifdef _DEBUG
  96. void PositionPageClass::AssertValid() const
  97. {
  98. DockableFormClass::AssertValid();
  99. }
  100. void PositionPageClass::Dump(CDumpContext& dc) const
  101. {
  102. DockableFormClass::Dump(dc);
  103. }
  104. #endif //_DEBUG
  105. /////////////////////////////////////////////////////////////////////////////
  106. //
  107. // HandleInitDialog
  108. //
  109. /////////////////////////////////////////////////////////////////////////////
  110. void
  111. PositionPageClass::HandleInitDialog (void)
  112. {
  113. ASSERT (m_pNode != NULL);
  114. // Get the node's position
  115. Matrix3D transform = m_pNode->Get_Transform ();
  116. Vector3 translation = transform.Get_Translation ();
  117. // Fill the position controls
  118. ::SetDlgItemFloat (m_hWnd, IDC_XPOS_EDIT, translation.X);
  119. ::SetDlgItemFloat (m_hWnd, IDC_YPOS_EDIT, translation.Y);
  120. ::SetDlgItemFloat (m_hWnd, IDC_ZPOS_EDIT, translation.Z);
  121. // Fill the rotation controls
  122. ::SetDlgItemFloat (m_hWnd, IDC_XROT_EDIT, RAD_TO_DEG (transform.Get_X_Rotation ()));
  123. ::SetDlgItemFloat (m_hWnd, IDC_YROT_EDIT, RAD_TO_DEG (transform.Get_Y_Rotation ()));
  124. ::SetDlgItemFloat (m_hWnd, IDC_ZROT_EDIT, RAD_TO_DEG (transform.Get_Z_Rotation ()));
  125. // Enable/disable the 'restrict rotation' checkbox, and set its check state
  126. ::EnableWindow (::GetDlgItem (m_hWnd, IDC_RESTRICT_CHECK), m_pNode->Can_Be_Rotated_Freely ());
  127. SendDlgItemMessage (IDC_RESTRICT_CHECK, BM_SETCHECK, (WPARAM)m_pNode->Is_Rotation_Restricted ());
  128. // Set the ranges for the spin controls
  129. SendDlgItemMessage (IDC_XPOS_SPIN, UDM_SETRANGE, (WPARAM)0, MAKELPARAM (UD_MAXVAL, UD_MINVAL));
  130. SendDlgItemMessage (IDC_YPOS_SPIN, UDM_SETRANGE, (WPARAM)0, MAKELPARAM (UD_MAXVAL, UD_MINVAL));
  131. SendDlgItemMessage (IDC_ZPOS_SPIN, UDM_SETRANGE, (WPARAM)0, MAKELPARAM (UD_MAXVAL, UD_MINVAL));
  132. SendDlgItemMessage (IDC_ZROT_SPIN, UDM_SETRANGE, (WPARAM)0, MAKELPARAM (UD_MAXVAL, UD_MINVAL));
  133. // Assume we aren't messing with the rotation
  134. m_bInclueRotation = false;
  135. return ;
  136. }
  137. /////////////////////////////////////////////////////////////////////////////
  138. //
  139. // Apply_Changes
  140. //
  141. /////////////////////////////////////////////////////////////////////////////
  142. bool
  143. PositionPageClass::Apply_Changes (void)
  144. {
  145. Matrix3D transform (1);
  146. Vector3 translation (0, 0, 0);
  147. // Get the rotation angle
  148. if (m_bInclueRotation) {
  149. float zrot = ::GetDlgItemFloat (m_hWnd, IDC_ZROT_EDIT);
  150. transform.Rotate_Z (DEG_TO_RAD (zrot));
  151. } else {
  152. transform = m_pNode->Get_Transform ();
  153. }
  154. // Pass the translation onto the transform
  155. translation.X = ::GetDlgItemFloat (m_hWnd, IDC_XPOS_EDIT);
  156. translation.Y = ::GetDlgItemFloat (m_hWnd, IDC_YPOS_EDIT);
  157. translation.Z = ::GetDlgItemFloat (m_hWnd, IDC_ZPOS_EDIT);
  158. transform.Set_Translation (translation);
  159. // Pass the newly constructed transform directly to the node
  160. MoverClass::Transform_Node (m_pNode, transform);
  161. // Pass the rotation restriction onto the node (if necessary)
  162. if (m_pNode->Can_Be_Rotated_Freely ()) {
  163. m_pNode->Restrict_Rotation (bool(SendDlgItemMessage (IDC_RESTRICT_CHECK, BM_GETCHECK) == 1));
  164. }
  165. // Return true to allow the dialog to close
  166. return true;
  167. }
  168. /////////////////////////////////////////////////////////////////////////////
  169. //
  170. // OnDeltaPosXPosSpin
  171. //
  172. /////////////////////////////////////////////////////////////////////////////
  173. void
  174. PositionPageClass::OnDeltaPosXPosSpin
  175. (
  176. NMHDR* pNMHDR,
  177. LRESULT* pResult
  178. )
  179. {
  180. NM_UPDOWN* pNMUpDown = (NM_UPDOWN*)pNMHDR;
  181. // Get the current value, increment it, and put it back into the control
  182. float xpos = ::GetDlgItemFloat (m_hWnd, IDC_XPOS_EDIT);
  183. xpos += (((float)pNMUpDown->iDelta) / 100.0F);
  184. ::SetDlgItemFloat (m_hWnd, IDC_XPOS_EDIT, xpos);
  185. (*pResult) = 0;
  186. return ;
  187. }
  188. /////////////////////////////////////////////////////////////////////////////
  189. //
  190. // OnDeltaPosXRotSpin
  191. //
  192. /////////////////////////////////////////////////////////////////////////////
  193. void
  194. PositionPageClass::OnDeltaPosXRotSpin
  195. (
  196. NMHDR* pNMHDR,
  197. LRESULT* pResult
  198. )
  199. {
  200. NM_UPDOWN* pNMUpDown = (NM_UPDOWN*)pNMHDR;
  201. // Get the current value, increment it, and put it back into the control
  202. float xrot = ::GetDlgItemFloat (m_hWnd, IDC_XROT_EDIT);
  203. xrot += (((float)pNMUpDown->iDelta) / 100.0F);
  204. ::SetDlgItemFloat (m_hWnd, IDC_XROT_EDIT, xrot);
  205. (*pResult) = 0;
  206. return ;
  207. }
  208. /////////////////////////////////////////////////////////////////////////////
  209. //
  210. // OnDeltaPosYPosSpin
  211. //
  212. /////////////////////////////////////////////////////////////////////////////
  213. void
  214. PositionPageClass::OnDeltaPosYPosSpin
  215. (
  216. NMHDR* pNMHDR,
  217. LRESULT* pResult
  218. )
  219. {
  220. NM_UPDOWN* pNMUpDown = (NM_UPDOWN*)pNMHDR;
  221. // Get the current value, increment it, and put it back into the control
  222. float ypos = ::GetDlgItemFloat (m_hWnd, IDC_YPOS_EDIT);
  223. ypos += (((float)pNMUpDown->iDelta) / 100.0F);
  224. ::SetDlgItemFloat (m_hWnd, IDC_YPOS_EDIT, ypos);
  225. (*pResult) = 0;
  226. return ;
  227. }
  228. /////////////////////////////////////////////////////////////////////////////
  229. //
  230. // OnDeltaPosYRotSpin
  231. //
  232. /////////////////////////////////////////////////////////////////////////////
  233. void
  234. PositionPageClass::OnDeltaPosYRotSpin
  235. (
  236. NMHDR* pNMHDR,
  237. LRESULT* pResult
  238. )
  239. {
  240. NM_UPDOWN* pNMUpDown = (NM_UPDOWN*)pNMHDR;
  241. // Get the current value, increment it, and put it back into the control
  242. float yrot = ::GetDlgItemFloat (m_hWnd, IDC_YROT_EDIT);
  243. yrot += (((float)pNMUpDown->iDelta) / 100.0F);
  244. ::SetDlgItemFloat (m_hWnd, IDC_YROT_EDIT, yrot);
  245. (*pResult) = 0;
  246. return ;
  247. }
  248. /////////////////////////////////////////////////////////////////////////////
  249. //
  250. // OnDeltaPosZPosSpin
  251. //
  252. /////////////////////////////////////////////////////////////////////////////
  253. void
  254. PositionPageClass::OnDeltaPosZPosSpin
  255. (
  256. NMHDR* pNMHDR,
  257. LRESULT* pResult
  258. )
  259. {
  260. NM_UPDOWN* pNMUpDown = (NM_UPDOWN*)pNMHDR;
  261. // Get the current value, increment it, and put it back into the control
  262. float zpos = ::GetDlgItemFloat (m_hWnd, IDC_ZPOS_EDIT);
  263. zpos += (((float)pNMUpDown->iDelta) / 100.0F);
  264. ::SetDlgItemFloat (m_hWnd, IDC_ZPOS_EDIT, zpos);
  265. (*pResult) = 0;
  266. return ;
  267. }
  268. /////////////////////////////////////////////////////////////////////////////
  269. //
  270. // OnDeltaPosZRotSpin
  271. //
  272. /////////////////////////////////////////////////////////////////////////////
  273. void
  274. PositionPageClass::OnDeltaPosZRotSpin
  275. (
  276. NMHDR* pNMHDR,
  277. LRESULT* pResult
  278. )
  279. {
  280. NM_UPDOWN* pNMUpDown = (NM_UPDOWN*)pNMHDR;
  281. // Get the current value, increment it, and put it back into the control
  282. float zrot = ::GetDlgItemFloat (m_hWnd, IDC_ZROT_EDIT);
  283. zrot += (((float)pNMUpDown->iDelta) / 100.0F);
  284. ::SetDlgItemFloat (m_hWnd, IDC_ZROT_EDIT, zrot);
  285. // Modify the transform's rotation on exit
  286. m_bInclueRotation = true;
  287. (*pResult) = 0;
  288. return ;
  289. }
  290. /////////////////////////////////////////////////////////////////////////////
  291. //
  292. // OnChangeZRotEdit
  293. //
  294. /////////////////////////////////////////////////////////////////////////////
  295. void
  296. PositionPageClass::OnChangeZRotEdit (void)
  297. {
  298. // Modify the transform's rotation on exit
  299. m_bInclueRotation = true;
  300. return ;
  301. }