Prototype game engine for Heroes of Might & Magic, featuring a gameplay plot-twist...
Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

327 рядки
17KB

  1. -- Copyright (c) 2024 - Ognjen 'xolatile' Milan Robovic
  2. --
  3. -- GNU General Public Licence (version 3 or later)
  4. with core, ui;
  5. package body ui is
  6. ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  7. sprite : array (style, enumeration) of core.sprite;
  8. glyphs : array (style) of core.font;
  9. ------------------------------------------------------------------------------------------
  10. procedure select_text_box (text : in string; x, y, width, height : in integer) is
  11. begin
  12. if core.cursor.x > x and core.cursor.x < x + width
  13. and core.cursor.y > y and core.cursor.y < y + height then
  14. core.write_text_box (text);
  15. end if;
  16. end select_text_box;
  17. ------------------------------------------------------------------------------------------
  18. procedure draw (index : in enumeration; x, y : in integer) is
  19. begin
  20. core.zoom := 1;
  21. core.draw (sprite (active, index), x, y);
  22. core.zoom := 2;
  23. end draw;
  24. ------------------------------------------------------------------------------------------
  25. procedure crop (index : in enumeration; x, y, u, v, width, height : in integer) is
  26. begin
  27. core.zoom := 1;
  28. core.draw (sprite (active, index), x, y, u, v, width, height);
  29. core.zoom := 2;
  30. end crop;
  31. ------------------------------------------------------------------------------------------
  32. procedure draw_horizontally (index : in enumeration; x, y, width : in integer) is
  33. base : constant integer := sprite (active, index).width;
  34. begin
  35. for move in 0 .. width / base - 1
  36. loop
  37. draw (index, x + move * base, y);
  38. end loop;
  39. --
  40. crop (index, x + (width / base) * base, y, 0, 0, width mod base, sprite (active, index).height);
  41. end draw_horizontally;
  42. ------------------------------------------------------------------------------------------
  43. procedure draw_vertically (index : in enumeration; x, y, height : in integer) is
  44. base : constant integer := sprite (active, index).height;
  45. begin
  46. for move in 0 .. height / base - 1
  47. loop
  48. draw (index, x, y + move * base);
  49. end loop;
  50. --
  51. crop (index, x, y + (height / base) * base, 0, 0, sprite (active, index).width, height mod base);
  52. end draw_vertically;
  53. ------------------------------------------------------------------------------------------
  54. procedure draw_background (index : in enumeration; x, y, width, height : in integer) is
  55. base_width : integer := sprite (active, index).width;
  56. base_height : integer := sprite (active, index).height;
  57. crop_width : integer := width mod base_width;
  58. crop_height : integer := height mod base_height;
  59. begin
  60. for move_y in 0 .. height / base_height - 1
  61. loop
  62. for move_x in 0 .. width / base_width - 1
  63. loop
  64. draw (index, x + move_x * base_width, y + move_y * base_height);
  65. end loop;
  66. --
  67. crop (index, x + width - crop_width, y + move_y * base_height, 0, 0, crop_width, base_height);
  68. end loop;
  69. --
  70. for move_x in 0 .. width / base_width - 1
  71. loop
  72. crop (index, x + move_x * base_width, y + height - crop_height, 0, 0, base_width, crop_height);
  73. end loop;
  74. --
  75. crop (index, x + width - crop_width, y + height - crop_height, 0, 0, crop_width, crop_height);
  76. end draw_background;
  77. ------------------------------------------------------------------------------------------
  78. procedure configure is
  79. procedure load_ui (index : in style; folder_path : in string) is
  80. begin
  81. glyphs (index) := core.import_font ("./sprite/ui/" & folder_path & "/font.png", (if index = default then 16 else 24), 0);
  82. --
  83. for this in enumeration
  84. loop
  85. sprite (index, this) := core.import_sprite ("./sprite/ui/" & folder_path & core.lowercase (enumeration'image (this)) & ".png", 1, 1);
  86. end loop;
  87. end load_ui;
  88. begin
  89. core.echo (core.comment, "Configuring UI components...");
  90. --
  91. load_ui (default, "default/");
  92. load_ui (steam, "steam/");
  93. end configure;
  94. ------------------------------------------------------------------------------------------
  95. procedure draw_icon (data : in core.sprite; description : in string; x, y : in integer) is
  96. begin
  97. draw (icon, x, y);
  98. select_text_box (description, x, y, core.icon, core.icon);
  99. --
  100. core.zoom := 1;
  101. core.draw (data, x, y);
  102. core.zoom := 2;
  103. --
  104. end draw_icon;
  105. ------------------------------------------------------------------------------------------
  106. procedure draw_overicon (description : in string; x, y : in integer) is
  107. begin
  108. draw (overicon, x, y);
  109. select_text_box (description, x, y, core.icon, core.icon);
  110. end draw_overicon;
  111. ------------------------------------------------------------------------------------------
  112. procedure draw_text_box (x, y, width, height : in integer) is
  113. offset : constant integer := sprite (active, text_middle).width;
  114. begin
  115. draw_background (text_middle, x + offset, y + offset, width - 2 * offset, height - 2 * offset);
  116. --
  117. draw_horizontally (text_upper, x + offset, y, width - 2 * offset);
  118. draw_horizontally (text_lower, x + offset, y + height - offset, width - 2 * offset);
  119. draw_vertically (text_left, x, y + offset, height - 2 * offset);
  120. draw_vertically (text_right, x + width - offset, y + offset, height - 2 * offset);
  121. --
  122. draw (text_upper_left, x, y);
  123. draw (text_upper_right, x + width - offset, y);
  124. draw (text_lower_left, x, y + height - offset);
  125. draw (text_lower_right, x + width - offset, y + height - offset);
  126. --
  127. core.write (core.read_text_box, x, y, glyphs (active));
  128. --
  129. select_text_box ("", x, y, width, height);
  130. end draw_text_box;
  131. ------------------------------------------------------------------------------------------
  132. procedure draw_frame (description : in string; x, y, width, height : in integer) is
  133. offset_x : constant integer := sprite (active, frame_middle).width;
  134. offset_y : constant integer := sprite (active, frame_middle).height;
  135. begin
  136. if height < core.icon or width < core.icon then
  137. return;
  138. end if;
  139. --
  140. draw_background (frame_middle, x + offset_x, y + offset_y, width - 2 * offset_x, height - 2 * offset_y);
  141. --
  142. draw_horizontally (frame_upper, x + offset_x, y, width - 2 * offset_x);
  143. draw_horizontally (frame_lower, x + offset_x, y + height - offset_y, width - 2 * offset_x);
  144. draw_vertically (frame_left, x, y + offset_y, height - 2 * offset_y);
  145. draw_vertically (frame_right, x + width - offset_x, y + offset_y, height - 2 * offset_y);
  146. --
  147. draw (frame_upper_left, x, y);
  148. draw (frame_upper_right, x + width - sprite (active, frame_upper_right).width, y);
  149. draw (frame_lower_left, x, y + height - sprite (active, frame_lower_left).height);
  150. draw (frame_lower_right, x + width - sprite (active, frame_lower_right).width, y + height - sprite (active, frame_lower_right).height);
  151. --
  152. select_text_box (description, x, y, width, height);
  153. end draw_frame;
  154. ------------------------------------------------------------------------------------------
  155. procedure draw_title_bar (x, y, width : in integer; title : in string) is
  156. middle_width : constant integer := width - sprite (active, title_bar_left).width - sprite (active, title_bar_right).width;
  157. begin
  158. draw (title_bar_left, x, y - sprite (active, title_bar_left).height);
  159. draw (title_bar_right, x + middle_width + sprite (active, title_bar_left).width, y - sprite (active, title_bar_right).height);
  160. --
  161. draw_horizontally (title_bar_middle, x + sprite (active, title_bar_left).width, y - sprite (active, title_bar_middle).height, middle_width);
  162. --
  163. core.write (title, x + sprite (active, title_bar_left).width / 2, y - sprite (active, title_bar_middle).height / 2 - 4, glyphs (active));
  164. --
  165. select_text_box ("", x, y - sprite (active, title_bar_middle).height, width, sprite (active, title_bar_middle).height);
  166. end draw_title_bar;
  167. ------------------------------------------------------------------------------------------
  168. procedure draw_scroll_bar (x, y, height : in integer; offset : in integer) is
  169. middle_height : constant integer := height - sprite (active, scroll_bar_upper).height - sprite (active, scroll_bar_lower).height;
  170. begin
  171. draw (scroll_bar_upper, x, y);
  172. draw (scroll_bar_lower, x, y + middle_height + sprite (active, scroll_bar_upper).height);
  173. --
  174. draw_vertically (scroll_bar_middle, x, y + sprite (active, scroll_bar_upper).height, middle_height);
  175. end draw_scroll_bar;
  176. ------------------------------------------------------------------------------------------
  177. procedure draw_menu (x, y, width, height : in integer; background : in boolean) is
  178. offset : constant integer := sprite (active, none).width;
  179. begin
  180. if width < sprite (active, corner_upper_left).width + sprite (active, corner_upper_right).width
  181. or width < sprite (active, corner_lower_left).width + sprite (active, corner_lower_right).width
  182. or height < sprite (active, corner_upper_left).height + sprite (active, corner_lower_left).height
  183. or height < sprite (active, corner_upper_right).height + sprite (active, corner_lower_right).height
  184. then return;
  185. end if;
  186. --
  187. if background then
  188. draw_background (main_background, x + offset, y + offset, width - 2 * offset, height - 2 * offset);
  189. end if;
  190. --
  191. declare
  192. upper : constant integer := width - sprite (active, corner_upper_left).width - sprite (active, corner_upper_right).width;
  193. lower : constant integer := width - sprite (active, corner_lower_left).width - sprite (active, corner_lower_right).width;
  194. left : constant integer := height - sprite (active, corner_upper_left).height - sprite (active, corner_lower_left).height;
  195. right : constant integer := height - sprite (active, corner_upper_right).height - sprite (active, corner_lower_right).height;
  196. begin
  197. draw_horizontally (border_upper, x + sprite (active, corner_upper_left).width, y, upper);
  198. draw_horizontally (border_lower, x + sprite (active, corner_lower_left).width, y + height - sprite (active, border_lower).height, lower);
  199. draw_vertically (border_left, x, y + sprite (active, corner_upper_left).height, left);
  200. draw_vertically (border_right, x + width - sprite (active, border_right).width, y + sprite (active, corner_upper_right).height, right);
  201. end;
  202. --
  203. draw (corner_upper_left, x, y);
  204. draw (corner_upper_right, x + width - sprite (active, corner_upper_right).width, y);
  205. draw (corner_lower_left, x, y + height - sprite (active, corner_lower_left).height);
  206. draw (corner_lower_right, x + width - sprite (active, corner_lower_right).width, y + height - sprite (active, corner_lower_right).height);
  207. --
  208. select_text_box ("", x, y, width, height);
  209. end draw_menu;
  210. ------------------------------------------------------------------------------------------
  211. procedure draw_tiny_menu (x, y, width, height : in integer; background : in boolean) is
  212. offset : constant integer := sprite (active, none).width;
  213. begin
  214. if width < sprite (active, tiny_corner_upper_left).width + sprite (active, tiny_corner_upper_right).width
  215. or width < sprite (active, tiny_corner_lower_left).width + sprite (active, tiny_corner_lower_right).width
  216. or height < sprite (active, tiny_corner_upper_left).height + sprite (active, tiny_corner_lower_left).height
  217. or height < sprite (active, tiny_corner_upper_right).height + sprite (active, tiny_corner_lower_right).height
  218. then return;
  219. end if;
  220. --
  221. if background then
  222. draw_background (main_background, x + offset, y + offset, width - 2 * offset, height - 2 * offset);
  223. end if;
  224. --
  225. declare
  226. upper : constant integer := width - sprite (active, tiny_corner_upper_left).width - sprite (active, tiny_corner_upper_right).width;
  227. lower : constant integer := width - sprite (active, tiny_corner_lower_left).width - sprite (active, tiny_corner_lower_right).width;
  228. left : constant integer := height - sprite (active, tiny_corner_upper_left).height - sprite (active, tiny_corner_lower_left).height;
  229. right : constant integer := height - sprite (active, tiny_corner_upper_right).height - sprite (active, tiny_corner_lower_right).height;
  230. begin
  231. draw_horizontally (tiny_border_upper, x + sprite (active, tiny_corner_upper_left).width, y, upper);
  232. draw_horizontally (tiny_border_lower, x + sprite (active, tiny_corner_lower_left).width, y + height - sprite (active, tiny_border_lower).height, lower);
  233. draw_vertically (tiny_border_left, x, y + sprite (active, tiny_corner_upper_left).height, left);
  234. draw_vertically (tiny_border_right, x + width - sprite (active, tiny_border_right).width, y + sprite (active, tiny_corner_upper_right).height, right);
  235. end;
  236. --
  237. draw (tiny_corner_upper_left, x, y);
  238. draw (tiny_corner_upper_right, x + width - sprite (active, tiny_corner_upper_right).width, y);
  239. draw (tiny_corner_lower_left, x, y + height - sprite (active, tiny_corner_lower_left).height);
  240. draw (tiny_corner_lower_right, x + width - sprite (active, tiny_corner_lower_right).width, y + height - sprite (active, tiny_corner_lower_right).height);
  241. --
  242. select_text_box ("", x, y, width, height);
  243. end draw_tiny_menu;
  244. ------------------------------------------------------------------------------------------
  245. procedure draw_icon_menu (description : in string; x, y, width, height : in integer) is
  246. offset_x : constant integer := sprite (active, icon_upper_left).width;
  247. offset_y : constant integer := sprite (active, icon_upper_left).height;
  248. begin
  249. if height < 2 * sprite (active, icon_upper_left).height or width < 2 * sprite (active, icon_upper_left).width then
  250. return;
  251. end if;
  252. --
  253. draw_horizontally (icon_upper, x + offset_x, y, width - 2 * offset_x);
  254. draw_horizontally (icon_lower, x + offset_x, y + height - offset_y, width - 2 * offset_x);
  255. draw_vertically (icon_left, x, y + offset_y, height - 2 * offset_y);
  256. draw_vertically (icon_right, x + width - offset_x, y + offset_y, height - 2 * offset_y);
  257. --
  258. draw (icon_upper_left, x, y);
  259. draw (icon_upper_right, x + width - sprite (active, icon_upper_right).width, y);
  260. draw (icon_lower_left, x, y + height - sprite (active, icon_lower_left).height);
  261. draw (icon_lower_right, x + width - sprite (active, icon_lower_right).width, y + height - sprite (active, icon_lower_right).height);
  262. --
  263. select_text_box (description, x, y, width, height);
  264. end draw_icon_menu;
  265. ------------------------------------------------------------------------------------------
  266. procedure draw_state_box (x, y : in integer) is
  267. begin
  268. ui.write ("Cursor X :" & core.cursor.x'image, x, y + 0);
  269. ui.write ("Cursor Y :" & core.cursor.y'image, x, y + 32);
  270. ui.write ("Cursor Mode :" & core.cursor_mode'image, x, y + 64);
  271. ui.write ("Camera X :" & core.camera.x'image, x, y + 96);
  272. ui.write ("Camera Y :" & core.camera.y'image, x, y + 128);
  273. ui.write ("Global Time :" & core.global_time'image, x, y + 160);
  274. ui.write ("Gameplay Time :" & core.gameplay_time'image, x, y + 192);
  275. ui.write ("Animation Time :" & core.animation_time'image, x, y + 224);
  276. ui.write ("Framerate :" & core.framerate'image, x, y + 256);
  277. end draw_state_box;
  278. ------------------------------------------------------------------------------------------
  279. procedure write (text : in string; x, y : in integer) is
  280. begin
  281. core.write (text, x, y, glyphs (active));
  282. end write;
  283. ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  284. end ui;