dialogbutton.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516
  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 : Combat *
  23. * *
  24. * $Archive:: /Commando/Code/wwui/dialogbutton.cpp $*
  25. * *
  26. * Author:: Patrick Smith *
  27. * *
  28. * $Modtime:: 6/11/01 3:58p $*
  29. * *
  30. * $Revision:: 10 $*
  31. * *
  32. *---------------------------------------------------------------------------------------------*
  33. * Functions: *
  34. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  35. #include "dialogbutton.h"
  36. #include "assetmgr.h"
  37. #include "font3d.h"
  38. #include "dialogbase.h"
  39. #include "mousemgr.h"
  40. #include "stylemgr.h"
  41. ////////////////////////////////////////////////////////////////
  42. //
  43. // DialogButtonClass
  44. //
  45. ////////////////////////////////////////////////////////////////
  46. DialogButtonClass::DialogButtonClass (void) :
  47. WasButtonPressedOnMe (false),
  48. IsMouseOverMe (false)
  49. {
  50. //
  51. // Set the font for the text renderer
  52. //
  53. StyleMgrClass::Assign_Font (&TextRenderers[0], StyleMgrClass::FONT_CONTROLS);
  54. StyleMgrClass::Assign_Font (&TextRenderers[1], StyleMgrClass::FONT_CONTROLS);
  55. //
  56. // Configure the renderers
  57. //
  58. //StyleMgrClass::Configure_Renderer (&TextRenderers[0]);
  59. //StyleMgrClass::Configure_Renderer (&TextRenderers[1]);
  60. StyleMgrClass::Configure_Renderer (&ButtonRenderers[0]);
  61. StyleMgrClass::Configure_Renderer (&ButtonRenderers[1]);
  62. return ;
  63. }
  64. ////////////////////////////////////////////////////////////////
  65. //
  66. // Render
  67. //
  68. ////////////////////////////////////////////////////////////////
  69. void
  70. DialogButtonClass::Render (void)
  71. {
  72. //
  73. // Recreate the renderers (if necessary)
  74. //
  75. if (Is_Dirty ()) {
  76. Create_Text_Renderers ();
  77. Create_Component_Button ();
  78. }
  79. if (WasButtonPressedOnMe && IsMouseOverMe) {
  80. //
  81. // Render the button "pressed"
  82. //
  83. ButtonRenderers[DOWN].Render ();
  84. TextRenderers[DOWN].Render ();
  85. } else {
  86. //
  87. // Render the button normally
  88. //
  89. ButtonRenderers[UP].Render ();
  90. TextRenderers[UP].Render ();
  91. }
  92. DialogControlClass::Render ();
  93. return ;
  94. }
  95. ////////////////////////////////////////////////////////////////
  96. //
  97. // On_Create
  98. //
  99. ////////////////////////////////////////////////////////////////
  100. void
  101. DialogButtonClass::On_Create (void)
  102. {
  103. return ;
  104. }
  105. ////////////////////////////////////////////////////////////////
  106. //
  107. // On_LButton_Down
  108. //
  109. ////////////////////////////////////////////////////////////////
  110. void
  111. DialogButtonClass::On_LButton_Down (const Vector2 &mouse_pos)
  112. {
  113. Set_Capture ();
  114. WasButtonPressedOnMe = true;
  115. return ;
  116. }
  117. ////////////////////////////////////////////////////////////////
  118. //
  119. // On_LButton_Up
  120. //
  121. ////////////////////////////////////////////////////////////////
  122. void
  123. DialogButtonClass::On_LButton_Up (const Vector2 &mouse_pos)
  124. {
  125. Release_Capture ();
  126. IsMouseOverMe = Rect.Contains (mouse_pos);
  127. //
  128. // Notify the parent (if necessary)
  129. //
  130. if (WasButtonPressedOnMe && IsMouseOverMe) {
  131. Parent->On_Command (ID, BN_CLICKED, 0);
  132. }
  133. WasButtonPressedOnMe = false;
  134. return ;
  135. }
  136. ////////////////////////////////////////////////////////////////
  137. //
  138. // On_Mouse_Move
  139. //
  140. ////////////////////////////////////////////////////////////////
  141. void
  142. DialogButtonClass::On_Mouse_Move (const Vector2 &mouse_pos)
  143. {
  144. IsMouseOverMe = Rect.Contains (mouse_pos);
  145. return ;
  146. }
  147. ////////////////////////////////////////////////////////////////
  148. //
  149. // Create_Bitmap_Button
  150. //
  151. ////////////////////////////////////////////////////////////////
  152. void
  153. DialogButtonClass::Create_Bitmap_Button (void)
  154. {
  155. ButtonRenderers[0].Reset ();
  156. ButtonRenderers[1].Reset ();
  157. //
  158. // Turn off texturing on the UI background
  159. //
  160. TextureClass *texture = WW3DAssetManager::Get_Instance ()->Get_Texture ("button_test04.tga", TextureClass::MIP_LEVELS_1);
  161. ButtonRenderers[0].Set_Texture (texture);
  162. ButtonRenderers[1].Set_Texture (texture);
  163. texture->Release_Ref();
  164. RectClass uv_rect1 (0, 0, 161.0F / 256.0F, 63.0F / 256.0F);
  165. ButtonRenderers[0].Add_Quad (Rect, uv_rect1);
  166. return ;
  167. }
  168. void
  169. Blit_Section
  170. (
  171. Render2DClass & renderer,
  172. const Vector2 & screen_pos,
  173. const Vector2 & texture_pos,
  174. const Vector2 & pixels,
  175. const Vector2 & texture_dimensions
  176. )
  177. {
  178. RectClass screen_rect;
  179. screen_rect.Left = screen_pos.X;
  180. screen_rect.Top = screen_pos.Y;
  181. screen_rect.Right = screen_rect.Left + pixels.X;
  182. screen_rect.Bottom = screen_rect.Top + pixels.Y;
  183. RectClass uv_rect (texture_pos.X, texture_pos.Y, texture_pos.X + pixels.X, texture_pos.Y + pixels.Y);
  184. uv_rect.Inverse_Scale (Vector2 (texture_dimensions.X - 1, texture_dimensions.Y - 1));
  185. renderer.Add_Quad (screen_rect, uv_rect);
  186. return ;
  187. }
  188. ////////////////////////////////////////////////////////////////
  189. //
  190. // Create_Component_Button
  191. //
  192. ////////////////////////////////////////////////////////////////
  193. void
  194. DialogButtonClass::Create_Component_Button (void)
  195. {
  196. ButtonRenderers[0].Reset ();
  197. ButtonRenderers[1].Reset ();
  198. ButtonRenderers[0].Set_Coordinate_Range (Render2DClass::Get_Screen_Resolution());
  199. ButtonRenderers[1].Set_Coordinate_Range (Render2DClass::Get_Screen_Resolution());
  200. //
  201. // Turn off texturing on the UI background
  202. //
  203. TextureClass *texture = WW3DAssetManager::Get_Instance ()->Get_Texture ("button_test04.tga", TextureClass::MIP_LEVELS_1);
  204. ButtonRenderers[0].Set_Texture (texture);
  205. ButtonRenderers[1].Set_Texture (texture);
  206. texture->Release_Ref();
  207. float height = 15.0F;
  208. float edge_width = 17.0F;
  209. float right = 160.0F;
  210. float bottom = 62.0F;
  211. float dn_start = 63.0F;
  212. //float horz_tile_width = 20.0F;
  213. //float vert_tile_height = 10.0F;
  214. Vector2 texture_dimensions (256.0F, 256.0F);
  215. //
  216. // Upper left
  217. //
  218. ::Blit_Section (ButtonRenderers[0], Vector2 (Rect.Left, Rect.Top), Vector2 (0, 0),
  219. Vector2 (edge_width, height), texture_dimensions);
  220. ::Blit_Section (ButtonRenderers[1], Vector2 (Rect.Left, Rect.Top), Vector2 (0, dn_start),
  221. Vector2 (edge_width, height), texture_dimensions);
  222. //
  223. // Upper right
  224. //
  225. ::Blit_Section (ButtonRenderers[0], Vector2 (Rect.Right - edge_width, Rect.Top), Vector2 (right - edge_width, 0),
  226. Vector2 (edge_width, height), texture_dimensions);
  227. ::Blit_Section (ButtonRenderers[1], Vector2 (Rect.Right - edge_width, Rect.Top), Vector2 (right - edge_width, dn_start),
  228. Vector2 (edge_width, height), texture_dimensions);
  229. //
  230. // Lower left
  231. //
  232. ::Blit_Section (ButtonRenderers[0], Vector2 (Rect.Left, Rect.Bottom - height), Vector2 (0, bottom - height),
  233. Vector2 (edge_width, height), texture_dimensions);
  234. ::Blit_Section (ButtonRenderers[1], Vector2 (Rect.Left, Rect.Bottom - height), Vector2 (0, dn_start + bottom - height),
  235. Vector2 (edge_width, height), texture_dimensions);
  236. //
  237. // Lower right
  238. //
  239. ::Blit_Section (ButtonRenderers[0], Vector2 (Rect.Right - edge_width, Rect.Bottom - height), Vector2 (right - edge_width, bottom - height),
  240. Vector2 (edge_width, height), texture_dimensions);
  241. ::Blit_Section (ButtonRenderers[1], Vector2 (Rect.Right - edge_width, Rect.Bottom - height), Vector2 (right - edge_width, dn_start + bottom - height),
  242. Vector2 (edge_width, height), texture_dimensions);
  243. Vector2 horz_top_pos ((right / 2) - 5, 0);
  244. Vector2 horz_bottom_pos ((right / 2) - 5, bottom - height);
  245. Vector2 horz_size (10, height);
  246. //
  247. // Horizontal tile
  248. //
  249. float remaining_width = Rect.Width () - (edge_width * 2);
  250. float x_pos = Rect.Left + edge_width;
  251. while (remaining_width > 0) {
  252. horz_size.X = min (remaining_width, horz_size.X);
  253. ::Blit_Section (ButtonRenderers[0], Vector2 (x_pos, Rect.Top), horz_top_pos,
  254. horz_size, texture_dimensions);
  255. ::Blit_Section (ButtonRenderers[0], Vector2 (x_pos, Rect.Bottom - height), horz_bottom_pos,
  256. horz_size, texture_dimensions);
  257. ::Blit_Section (ButtonRenderers[1], Vector2 (x_pos, Rect.Top), horz_top_pos + Vector2 (0, dn_start),
  258. horz_size, texture_dimensions);
  259. ::Blit_Section (ButtonRenderers[1], Vector2 (x_pos, Rect.Bottom - height), horz_bottom_pos + Vector2 (0, dn_start),
  260. horz_size, texture_dimensions);
  261. x_pos += horz_size.X;
  262. remaining_width -= horz_size.X;
  263. }
  264. Vector2 vert_left_pos (0, (bottom / 2) - 5);
  265. Vector2 vert_right_pos (right - edge_width, (bottom / 2) - 5);
  266. Vector2 vert_size (edge_width, 10);
  267. //
  268. // Vertical tile
  269. //
  270. float remaining_height = Rect.Height () - (height * 2);
  271. float y_pos = Rect.Top + height;
  272. while (remaining_height > 0) {
  273. vert_size.Y = min (remaining_height, vert_size.Y);
  274. ::Blit_Section (ButtonRenderers[0], Vector2 (Rect.Left, y_pos), vert_left_pos,
  275. vert_size, texture_dimensions);
  276. ::Blit_Section (ButtonRenderers[0], Vector2 (Rect.Right - edge_width, y_pos), vert_right_pos,
  277. vert_size, texture_dimensions);
  278. ::Blit_Section (ButtonRenderers[1], Vector2 (Rect.Left, y_pos), vert_left_pos + Vector2 (0, dn_start),
  279. vert_size, texture_dimensions);
  280. ::Blit_Section (ButtonRenderers[1], Vector2 (Rect.Right - edge_width, y_pos), vert_right_pos + Vector2 (0, dn_start),
  281. vert_size, texture_dimensions);
  282. y_pos += vert_size.Y;
  283. remaining_height -= vert_size.Y;
  284. }
  285. //
  286. // "Patch" fill the interior
  287. //
  288. y_pos = Rect.Top + height;
  289. remaining_height = Rect.Height () - (height * 2);
  290. while (remaining_height > 0) {
  291. x_pos = Rect.Left + edge_width;
  292. remaining_width = Rect.Width () - (edge_width * 2);
  293. while (remaining_width > 0) {
  294. Vector2 size (8, 8);
  295. size.X = min (remaining_width, size.X);
  296. size.Y = min (remaining_height, size.Y);
  297. ::Blit_Section (ButtonRenderers[0], Vector2 (x_pos, y_pos), Vector2 ((right / 2) - 4, (bottom / 2) - 4),
  298. size, texture_dimensions);
  299. ::Blit_Section (ButtonRenderers[1], Vector2 (x_pos, y_pos), Vector2 ((right / 2) - 4, dn_start + (bottom / 2) - 4),
  300. size, texture_dimensions);
  301. remaining_width -= 8;
  302. x_pos += 8;
  303. }
  304. remaining_height -= 8;
  305. y_pos += 8;
  306. }
  307. return ;
  308. }
  309. ////////////////////////////////////////////////////////////////
  310. //
  311. // Create_Component_Button2
  312. //
  313. ////////////////////////////////////////////////////////////////
  314. void
  315. DialogButtonClass::Create_Component_Button2 (void)
  316. {
  317. ButtonRenderers[0].Reset ();
  318. ButtonRenderers[1].Reset ();
  319. ButtonRenderers[0].Set_Coordinate_Range (Render2DClass::Get_Screen_Resolution());
  320. ButtonRenderers[1].Set_Coordinate_Range (Render2DClass::Get_Screen_Resolution());
  321. //
  322. // Turn off texturing on the UI background
  323. //
  324. ButtonRenderers[0].Enable_Texturing (false);
  325. ButtonRenderers[1].Enable_Texturing (false);
  326. const int BLACK = VRGB_TO_INT32 (Vector3 (0, 0, 0));
  327. const int WHITE = VRGB_TO_INT32 (Vector3 (1, 1, 1));
  328. const int DK_GRAY = VRGB_TO_INT32 (Vector3 (0.5F, 0.5F, 0.5F));
  329. const int GRAY = VRGB_TO_INT32 (Vector3 (0.75F, 0.75F, 0.75F));
  330. const int LT_GRAY = VRGB_TO_INT32 (Vector3 (0.9F, 0.9F, 0.9F));
  331. //
  332. // Draw the outside button outline
  333. //
  334. RectClass rect = Rect;
  335. ButtonRenderers[0].Add_Line (Vector2 (rect.Left, rect.Bottom), Vector2 (rect.Left, rect.Top-1), 1, WHITE);
  336. ButtonRenderers[0].Add_Line (Vector2 (rect.Left, rect.Top), Vector2 (rect.Right, rect.Top), 1, WHITE);
  337. ButtonRenderers[0].Add_Line (Vector2 (rect.Right, rect.Top), Vector2 (rect.Right, rect.Bottom), 1, BLACK);
  338. ButtonRenderers[0].Add_Line (Vector2 (rect.Right, rect.Bottom), Vector2 (rect.Left, rect.Bottom), 1, BLACK);
  339. ButtonRenderers[1].Add_Line (Vector2 (rect.Left, rect.Bottom), Vector2 (rect.Left, rect.Top-1), 1, BLACK);
  340. ButtonRenderers[1].Add_Line (Vector2 (rect.Left, rect.Top), Vector2 (rect.Right, rect.Top), 1, BLACK);
  341. ButtonRenderers[1].Add_Line (Vector2 (rect.Right, rect.Top), Vector2 (rect.Right, rect.Bottom), 1, WHITE);
  342. ButtonRenderers[1].Add_Line (Vector2 (rect.Right, rect.Bottom), Vector2 (rect.Left, rect.Bottom), 1, WHITE);
  343. //
  344. // Draw the inside button outline
  345. //
  346. rect.Inflate (Vector2 (-1, -1));
  347. ButtonRenderers[0].Add_Line (Vector2 (rect.Left, rect.Bottom), Vector2 (rect.Left, rect.Top-1), 1, LT_GRAY);
  348. ButtonRenderers[0].Add_Line (Vector2 (rect.Left, rect.Top), Vector2 (rect.Right, rect.Top), 1, LT_GRAY);
  349. ButtonRenderers[0].Add_Line (Vector2 (rect.Right, rect.Top), Vector2 (rect.Right, rect.Bottom), 1, DK_GRAY);
  350. ButtonRenderers[0].Add_Line (Vector2 (rect.Right, rect.Bottom), Vector2 (rect.Left, rect.Bottom), 1, DK_GRAY);
  351. ButtonRenderers[1].Add_Line (Vector2 (rect.Left, rect.Bottom), Vector2 (rect.Left, rect.Top-1), 1, DK_GRAY);
  352. ButtonRenderers[1].Add_Line (Vector2 (rect.Left, rect.Top), Vector2 (rect.Right, rect.Top), 1, DK_GRAY);
  353. //
  354. // Fill the button center
  355. //
  356. rect.Right -= 1;
  357. rect.Bottom -= 1;
  358. ButtonRenderers[0].Add_Quad (rect, GRAY);
  359. ButtonRenderers[1].Add_Quad (rect, GRAY);
  360. return ;
  361. }
  362. ////////////////////////////////////////////////////////////////
  363. //
  364. // Create_Text_Renderers
  365. //
  366. ////////////////////////////////////////////////////////////////
  367. void
  368. DialogButtonClass::Create_Text_Renderers (void)
  369. {
  370. TextRenderers[0].Reset ();
  371. TextRenderers[1].Reset ();
  372. //
  373. // Draw the text
  374. //
  375. StyleMgrClass::Render_Text (Title, &TextRenderers[0], Rect, true, true, StyleMgrClass::CENTER_JUSTIFY);
  376. StyleMgrClass::Render_Text (Title, &TextRenderers[1], Rect, true, true, StyleMgrClass::CENTER_JUSTIFY);
  377. return ;
  378. }
  379. ////////////////////////////////////////////////////////////////
  380. //
  381. // On_Set_Cursor
  382. //
  383. ////////////////////////////////////////////////////////////////
  384. void
  385. DialogButtonClass::On_Set_Cursor (const Vector2 &mouse_pos)
  386. {
  387. //
  388. // Change the mouse cursor if necessary
  389. //
  390. if (ClientRect.Contains (mouse_pos)) {
  391. MouseMgrClass::Set_Cursor (MouseMgrClass::CURSOR_ACTION);
  392. }
  393. return ;
  394. }
  395. ////////////////////////////////////////////////////////////////
  396. //
  397. // On_Kill_Focus
  398. //
  399. ////////////////////////////////////////////////////////////////
  400. void
  401. DialogButtonClass::On_Kill_Focus (DialogControlClass *focus)
  402. {
  403. WasButtonPressedOnMe = false;
  404. IsMouseOverMe = false;
  405. DialogControlClass::On_Kill_Focus (focus);
  406. return ;
  407. }
  408. ////////////////////////////////////////////////////////////////
  409. //
  410. // On_Key_Down
  411. //
  412. ////////////////////////////////////////////////////////////////
  413. void
  414. DialogButtonClass::On_Key_Down (uint32 key_id, uint32 key_data)
  415. {
  416. switch (key_id)
  417. {
  418. case VK_RETURN:
  419. case VK_SPACE:
  420. Parent->On_Command (ID, BN_CLICKED, 0);
  421. break;
  422. }
  423. return ;
  424. }