SphereColorPropPage.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603
  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. // SphereColorPropPage.cpp : implementation file
  19. //
  20. #include "stdafx.h"
  21. #include "w3dview.h"
  22. #include "spherecolorproppage.h"
  23. #include "opacitysettingsdialog.h"
  24. #include "colorutils.h"
  25. #include "utils.h"
  26. #include "opacityvectordialog.h"
  27. #ifdef _DEBUG
  28. #define new DEBUG_NEW
  29. #undef THIS_FILE
  30. static char THIS_FILE[] = __FILE__;
  31. #endif
  32. IMPLEMENT_DYNCREATE(SphereColorPropPageClass, CPropertyPage)
  33. /////////////////////////////////////////////////////////////
  34. //
  35. // SphereColorPropPageClass
  36. //
  37. /////////////////////////////////////////////////////////////
  38. SphereColorPropPageClass::SphereColorPropPageClass (SphereRenderObjClass *sphere)
  39. : m_RenderObj (sphere),
  40. m_bValid (true),
  41. m_ColorBar (NULL),
  42. m_OpacityBar (NULL),
  43. m_EnableOpactiyVector (false),
  44. m_InvertVector (false),
  45. CPropertyPage(SphereColorPropPageClass::IDD)
  46. {
  47. //{{AFX_DATA_INIT(SphereColorPropPageClass)
  48. // NOTE: the ClassWizard will add member initialization here
  49. //}}AFX_DATA_INIT
  50. Initialize ();
  51. return ;
  52. }
  53. /////////////////////////////////////////////////////////////
  54. //
  55. // ~SphereColorPropPageClass
  56. //
  57. /////////////////////////////////////////////////////////////
  58. SphereColorPropPageClass::~SphereColorPropPageClass (void)
  59. {
  60. return ;
  61. }
  62. /////////////////////////////////////////////////////////////
  63. //
  64. // DoDataExchange
  65. //
  66. /////////////////////////////////////////////////////////////
  67. void
  68. SphereColorPropPageClass::DoDataExchange (CDataExchange* pDX)
  69. {
  70. CPropertyPage::DoDataExchange(pDX);
  71. //{{AFX_DATA_MAP(SphereColorPropPageClass)
  72. // NOTE: the ClassWizard will add DDX and DDV calls here
  73. //}}AFX_DATA_MAP
  74. return ;
  75. }
  76. BEGIN_MESSAGE_MAP(SphereColorPropPageClass, CPropertyPage)
  77. //{{AFX_MSG_MAP(SphereColorPropPageClass)
  78. ON_WM_DESTROY()
  79. ON_BN_CLICKED(IDC_OPACITY_VECTOR_CHECK, OnOpacityVectorCheck)
  80. ON_BN_CLICKED(IDC_INVERT_VECTOR_CHECK, OnInvertVectorCheck)
  81. //}}AFX_MSG_MAP
  82. END_MESSAGE_MAP()
  83. /////////////////////////////////////////////////////////////
  84. //
  85. // Initialize
  86. //
  87. /////////////////////////////////////////////////////////////
  88. void
  89. SphereColorPropPageClass::Initialize (void)
  90. {
  91. m_ColorChannel.Reset ();
  92. m_OrigColorChannel.Reset ();
  93. m_AlphaChannel.Reset ();
  94. m_OrigAlphaChannel.Reset ();
  95. m_VectorChannel.Reset ();
  96. m_OrigVectorChannel.Reset ();
  97. if (m_RenderObj != NULL) {
  98. m_ColorChannel = m_RenderObj->Get_Color_Channel ();
  99. m_OrigColorChannel = m_RenderObj->Get_Color_Channel ();
  100. m_AlphaChannel = m_RenderObj->Get_Alpha_Channel ();
  101. m_OrigAlphaChannel = m_RenderObj->Get_Alpha_Channel ();
  102. m_VectorChannel = m_RenderObj->Get_Vector_Channel ();
  103. m_OrigVectorChannel = m_RenderObj->Get_Vector_Channel ();
  104. m_EnableOpactiyVector = (m_RenderObj->Get_Flags () & SphereRenderObjClass::USE_ALPHA_VECTOR) != 0;
  105. m_InvertVector = (m_RenderObj->Get_Flags () & SphereRenderObjClass::USE_INVERSE_ALPHA) != 0;
  106. if (m_ColorChannel.Get_Key_Count () == 0) {
  107. m_ColorChannel.Add_Key (m_RenderObj->Get_Color (), 0);
  108. m_OrigColorChannel.Add_Key (m_RenderObj->Get_Color (), 0);
  109. }
  110. if (m_AlphaChannel.Get_Key_Count () == 0) {
  111. m_AlphaChannel.Add_Key (m_RenderObj->Get_Alpha (), 0);
  112. m_OrigAlphaChannel.Add_Key (m_RenderObj->Get_Alpha(), 0);
  113. }
  114. if (m_VectorChannel.Get_Key_Count () == 0) {
  115. m_VectorChannel.Add_Key (m_RenderObj->Get_Vector (), 0);
  116. m_OrigVectorChannel.Add_Key (m_RenderObj->Get_Vector (), 0);
  117. }
  118. }
  119. return ;
  120. }
  121. /////////////////////////////////////////////////////////////
  122. //
  123. // OnInitDialog
  124. //
  125. /////////////////////////////////////////////////////////////
  126. BOOL
  127. SphereColorPropPageClass::OnInitDialog (void)
  128. {
  129. // Allow the base class to process this message
  130. CPropertyPage::OnInitDialog ();
  131. m_ColorBar = ColorBarClass::Get_Color_Bar (::GetDlgItem (m_hWnd, IDC_COLOR_BAR));
  132. m_OpacityBar = ColorBarClass::Get_Color_Bar (::GetDlgItem (m_hWnd, IDC_OPACITY_BAR));
  133. m_VectorBar = ColorBarClass::Get_Color_Bar (::GetDlgItem (m_hWnd, IDC_VECTOR_BAR));
  134. //
  135. // Setup the color bars
  136. //
  137. m_ColorBar->Set_Range (0, 1);
  138. m_OpacityBar->Set_Range (0, 1);
  139. m_VectorBar->Set_Range (0, 1);
  140. //
  141. // Set-up the color bar
  142. //
  143. for (int index = 0; index < m_OrigColorChannel.Get_Key_Count (); index ++) {
  144. m_ColorBar->Modify_Point ( index,
  145. m_OrigColorChannel[index].Get_Time (),
  146. m_OrigColorChannel[index].Get_Value ().X * 255,
  147. m_OrigColorChannel[index].Get_Value ().Y * 255,
  148. m_OrigColorChannel[index].Get_Value ().Z * 255);
  149. }
  150. //
  151. // Set-up the opacity bar
  152. //
  153. for (index = 0; index < m_OrigAlphaChannel.Get_Key_Count (); index ++) {
  154. m_OpacityBar->Modify_Point ( index,
  155. m_OrigAlphaChannel[index].Get_Time (),
  156. m_OrigAlphaChannel[index].Get_Value () * 255,
  157. m_OrigAlphaChannel[index].Get_Value () * 255,
  158. m_OrigAlphaChannel[index].Get_Value () * 255);
  159. }
  160. //
  161. // Set-up the vector bar
  162. //
  163. for (index = 0; index < m_OrigVectorChannel.Get_Key_Count (); index ++) {
  164. m_VectorBar->Modify_Point (index,
  165. m_OrigVectorChannel[index].Get_Time (),
  166. 128,
  167. 128,
  168. 128);
  169. AlphaVectorStruct *data = new AlphaVectorStruct (m_OrigVectorChannel[index].Get_Value ());
  170. m_VectorBar->Set_User_Data (index, (ULONG)data);
  171. }
  172. //
  173. // Ensure our initial 'current' values are up-to-date
  174. //
  175. Update_Colors ();
  176. Update_Opacities ();
  177. Update_Vectors ();
  178. //
  179. // Ensure the disabled status of the dialog controls is correct
  180. //
  181. CheckDlgButton (IDC_OPACITY_VECTOR_CHECK, (m_RenderObj->Get_Flags () & SphereRenderObjClass::USE_ALPHA_VECTOR) != 0);
  182. CheckDlgButton (IDC_INVERT_VECTOR_CHECK, (m_RenderObj->Get_Flags () & SphereRenderObjClass::USE_INVERSE_ALPHA) != 0);
  183. OnOpacityVectorCheck ();
  184. return TRUE;
  185. }
  186. /////////////////////////////////////////////////////////////
  187. //
  188. // OnApply
  189. //
  190. /////////////////////////////////////////////////////////////
  191. BOOL
  192. SphereColorPropPageClass::OnApply (void)
  193. {
  194. // Allow the base class to process this message
  195. return CPropertyPage::OnApply ();
  196. }
  197. /////////////////////////////////////////////////////////////
  198. //
  199. // OnDestroy
  200. //
  201. /////////////////////////////////////////////////////////////
  202. void
  203. SphereColorPropPageClass::OnDestroy (void)
  204. {
  205. //
  206. // Free the alpha vectors associated with the keys...
  207. //
  208. int count = m_VectorBar->Get_Point_Count ();
  209. for (int index = 0; index < count; index ++) {
  210. AlphaVectorStruct *data = (AlphaVectorStruct *)m_VectorBar->Get_User_Data (index);
  211. if (data != NULL) {
  212. delete data;
  213. m_VectorBar->Set_User_Data (index, 0L);
  214. }
  215. }
  216. CPropertyPage::OnDestroy();
  217. return ;
  218. }
  219. /////////////////////////////////////////////////////////////
  220. //
  221. // OnNotify
  222. //
  223. /////////////////////////////////////////////////////////////
  224. BOOL
  225. SphereColorPropPageClass::OnNotify
  226. (
  227. WPARAM wParam,
  228. LPARAM lParam,
  229. LRESULT *pResult
  230. )
  231. {
  232. CBR_NMHDR *color_bar_hdr = (CBR_NMHDR *)lParam;
  233. //
  234. // Which control sent the notification?
  235. //
  236. switch (color_bar_hdr->hdr.idFrom)
  237. {
  238. case IDC_OPACITY_BAR:
  239. {
  240. if (color_bar_hdr->hdr.code == CBRN_DBLCLK_POINT) {
  241. //
  242. // Allow the user to edit the keyframe
  243. //
  244. OpacitySettingsDialogClass dialog (color_bar_hdr->red / 255, this);
  245. if (dialog.DoModal () == IDOK) {
  246. m_OpacityBar->Modify_Point ( color_bar_hdr->key_index,
  247. color_bar_hdr->position,
  248. dialog.Get_Opacity () * 255,
  249. dialog.Get_Opacity () * 255,
  250. dialog.Get_Opacity () * 255);
  251. //
  252. // Update the object
  253. //
  254. Update_Opacities ();
  255. SetModified ();
  256. }
  257. } else if ((color_bar_hdr->hdr.code == CBRN_MOVING_POINT) ||
  258. (color_bar_hdr->hdr.code == CBRN_DELETED_POINT))
  259. {
  260. //
  261. // Update the object
  262. //
  263. Update_Opacities ();
  264. SetModified ();
  265. }
  266. }
  267. break;
  268. case IDC_COLOR_BAR:
  269. {
  270. if (color_bar_hdr->hdr.code == CBRN_DBLCLK_POINT) {
  271. //
  272. // Allow the user to edit the keyframe
  273. //
  274. int red = (int)color_bar_hdr->red;
  275. int green = (int)color_bar_hdr->green;
  276. int blue = (int)color_bar_hdr->blue;
  277. if (Show_Color_Picker (&red, &green, &blue)) {
  278. m_ColorBar->Modify_Point ( color_bar_hdr->key_index,
  279. color_bar_hdr->position,
  280. red,
  281. green,
  282. blue);
  283. //
  284. // Update the object
  285. //
  286. Update_Colors ();
  287. SetModified ();
  288. }
  289. } else if ((color_bar_hdr->hdr.code == CBRN_MOVING_POINT) ||
  290. (color_bar_hdr->hdr.code == CBRN_DELETED_POINT))
  291. {
  292. //
  293. // Update the object
  294. //
  295. Update_Colors ();
  296. SetModified ();
  297. }
  298. }
  299. break;
  300. case IDC_VECTOR_BAR:
  301. {
  302. bool update = false;
  303. if (color_bar_hdr->hdr.code == CBRN_DBLCLK_POINT) {
  304. AlphaVectorStruct *data = (AlphaVectorStruct *)m_VectorBar->Get_User_Data (color_bar_hdr->key_index);
  305. if (data != NULL) {
  306. //
  307. // Set-up the dialog so the user can edit this keyframe
  308. //
  309. OpacityVectorDialogClass dialog (this);
  310. dialog.Set_Render_Obj (m_RenderObj);
  311. dialog.Set_Vector (*data);
  312. dialog.Set_Key_Index (color_bar_hdr->key_index);
  313. //
  314. // Show the dialog
  315. //
  316. if (dialog.DoModal () == IDOK) {
  317. (*data) = dialog.Get_Vector ();
  318. }
  319. }
  320. } else if ((color_bar_hdr->hdr.code == CBRN_MOVING_POINT) ||
  321. (color_bar_hdr->hdr.code == CBRN_DELETED_POINT))
  322. {
  323. update = true;
  324. } else if (color_bar_hdr->hdr.code == CBRN_DEL_POINT) {
  325. AlphaVectorStruct *data = (AlphaVectorStruct *)m_VectorBar->Get_User_Data (color_bar_hdr->key_index);
  326. SAFE_DELETE (data);
  327. m_VectorBar->Set_User_Data (color_bar_hdr->key_index, 0L);
  328. } else if (color_bar_hdr->hdr.code == CBRN_INSERTED_POINT) {
  329. AlphaVectorStruct *prev_data = (AlphaVectorStruct *)m_VectorBar->Get_User_Data (color_bar_hdr->key_index - 1);
  330. AlphaVectorStruct *next_data = (AlphaVectorStruct *)m_VectorBar->Get_User_Data (color_bar_hdr->key_index + 1);
  331. AlphaVectorStruct *new_data = new AlphaVectorStruct;
  332. if (next_data == NULL) {
  333. (*new_data) = (*prev_data);
  334. } else {
  335. //
  336. // Determine what the new data should be based on its position between
  337. // the prev and next keys.
  338. //
  339. float pos0 = 0;
  340. float pos1 = 0;
  341. float pos2 = 0;
  342. float red = 0;
  343. float green = 0;
  344. float blue = 0;
  345. m_VectorBar->Get_Point (color_bar_hdr->key_index - 1, &pos0, &red, &green, &blue);
  346. m_VectorBar->Get_Point (color_bar_hdr->key_index, &pos1, &red, &green, &blue);
  347. m_VectorBar->Get_Point (color_bar_hdr->key_index + 1, &pos2, &red, &green, &blue);
  348. float percent = (pos1 - pos0) / (pos2 - pos0);
  349. new_data->intensity = prev_data->intensity + ((next_data->intensity - prev_data->intensity) * percent);
  350. ::Slerp (new_data->angle,prev_data->angle, next_data->angle, percent);
  351. }
  352. //
  353. // Associate this data with the new key
  354. //
  355. m_VectorBar->Set_User_Data (color_bar_hdr->key_index, (ULONG)new_data);
  356. update = true;
  357. }
  358. //
  359. // Update the object
  360. //
  361. if (update) {
  362. Update_Vectors ();
  363. SetModified ();
  364. }
  365. }
  366. break;
  367. }
  368. return CPropertyPage::OnNotify (wParam, lParam, pResult);
  369. }
  370. /////////////////////////////////////////////////////////////
  371. //
  372. // OnCancel
  373. //
  374. /////////////////////////////////////////////////////////////
  375. void
  376. SphereColorPropPageClass::OnCancel (void)
  377. {
  378. //
  379. // Reset the object to its original state
  380. //
  381. m_RenderObj->Set_Color_Channel (m_OrigColorChannel);
  382. m_RenderObj->Set_Alpha_Channel (m_OrigAlphaChannel);
  383. m_RenderObj->Set_Vector_Channel (m_OrigVectorChannel);
  384. m_RenderObj->Set_Flag (SphereRenderObjClass::USE_ALPHA_VECTOR, m_EnableOpactiyVector);
  385. m_RenderObj->Set_Flag (SphereRenderObjClass::USE_INVERSE_ALPHA, m_InvertVector);
  386. CPropertyPage::OnCancel ();
  387. return ;
  388. }
  389. /////////////////////////////////////////////////////////////
  390. //
  391. // Update_Opacities
  392. //
  393. /////////////////////////////////////////////////////////////
  394. void
  395. SphereColorPropPageClass::Update_Opacities (void)
  396. {
  397. m_AlphaChannel.Reset ();
  398. float position = 0;
  399. float red = 0;
  400. float green = 0;
  401. float blue = 0;
  402. //
  403. // Build the channel
  404. //
  405. int count = m_OpacityBar->Get_Point_Count ();
  406. for (int index = 0; index < count; index ++) {
  407. m_OpacityBar->Get_Point (index, &position, &red, &green, &blue);
  408. m_AlphaChannel.Add_Key (red / 255, position);
  409. }
  410. //
  411. // Update the object
  412. //
  413. m_RenderObj->Set_Alpha_Channel (m_AlphaChannel);
  414. m_RenderObj->Restart_Animation ();
  415. return ;
  416. }
  417. /////////////////////////////////////////////////////////////
  418. //
  419. // Update_Colors
  420. //
  421. /////////////////////////////////////////////////////////////
  422. void
  423. SphereColorPropPageClass::Update_Colors (void)
  424. {
  425. m_ColorChannel.Reset ();
  426. float position = 0;
  427. float red = 0;
  428. float green = 0;
  429. float blue = 0;
  430. //
  431. // Build the channel
  432. //
  433. int count = m_ColorBar->Get_Point_Count ();
  434. for (int index = 0; index < count; index ++) {
  435. m_ColorBar->Get_Point (index, &position, &red, &green, &blue);
  436. m_ColorChannel.Add_Key (Vector3 (red / 255, green / 255, blue / 255), position);
  437. }
  438. //
  439. // Update the object
  440. //
  441. m_RenderObj->Set_Color_Channel (m_ColorChannel);
  442. m_RenderObj->Restart_Animation ();
  443. return ;
  444. }
  445. /////////////////////////////////////////////////////////////
  446. //
  447. // Update_Vectors
  448. //
  449. /////////////////////////////////////////////////////////////
  450. void
  451. SphereColorPropPageClass::Update_Vectors (void)
  452. {
  453. m_VectorChannel.Reset ();
  454. float position = 0;
  455. float red = 0;
  456. float green = 0;
  457. float blue = 0;
  458. //
  459. // Build the channel
  460. //
  461. int count = m_VectorBar->Get_Point_Count ();
  462. for (int index = 0; index < count; index ++) {
  463. m_VectorBar->Get_Point (index, &position, &red, &green, &blue);
  464. AlphaVectorStruct *data = (AlphaVectorStruct *)m_VectorBar->Get_User_Data (index);
  465. if (data != NULL) {
  466. m_VectorChannel.Add_Key (*data, position);
  467. }
  468. }
  469. //
  470. // Update the object
  471. //
  472. m_RenderObj->Set_Vector_Channel (m_VectorChannel);
  473. m_RenderObj->Restart_Animation ();
  474. return ;
  475. }
  476. /////////////////////////////////////////////////////////////
  477. //
  478. // OnOpacityVectorCheck
  479. //
  480. /////////////////////////////////////////////////////////////
  481. void
  482. SphereColorPropPageClass::OnOpacityVectorCheck (void)
  483. {
  484. bool is_checked = (IsDlgButtonChecked (IDC_OPACITY_VECTOR_CHECK) == 1);
  485. //
  486. // Enable/disable the alpha-vector timeline
  487. //
  488. ::EnableWindow (::GetDlgItem (m_hWnd, IDC_VECTOR_BAR), is_checked);
  489. ::EnableWindow (::GetDlgItem (m_hWnd, IDC_INVERT_VECTOR_CHECK), is_checked);
  490. //
  491. // Update the render object
  492. //
  493. m_RenderObj->Set_Flag (SphereRenderObjClass::USE_ALPHA_VECTOR, is_checked);
  494. SetModified ();
  495. return ;
  496. }
  497. /////////////////////////////////////////////////////////////
  498. //
  499. // OnInvertVectorCheck
  500. //
  501. /////////////////////////////////////////////////////////////
  502. void
  503. SphereColorPropPageClass::OnInvertVectorCheck (void)
  504. {
  505. bool is_checked = (IsDlgButtonChecked (IDC_INVERT_VECTOR_CHECK) == 1);
  506. //
  507. // Invert the effect
  508. //
  509. m_RenderObj->Set_Flag (SphereRenderObjClass::USE_INVERSE_ALPHA, is_checked);
  510. //
  511. // Update the render object
  512. //
  513. m_RenderObj->Set_Flag (SphereRenderObjClass::USE_INVERSE_ALPHA, is_checked);
  514. SetModified ();
  515. return ;
  516. }