Prototype game engine for Heroes of Might & Magic, featuring a gameplay plot-twist...
Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

767 linhas
37KB

  1. -- Copyright (c) 2024 - Ognjen 'xolatile' Milan Robovic
  2. --
  3. -- GNU General Public Licence (version 3 or later)
  4. with core;
  5. with ada.strings.unbounded;
  6. use type core.cursor_code;
  7. use type ada.strings.unbounded.unbounded_string;
  8. package body ui is
  9. ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  10. type element is (
  11. none,
  12. main_background,
  13. --
  14. corner_upper_left, border_upper, corner_upper_right,
  15. border_left, border_right,
  16. corner_lower_left, border_lower, corner_lower_right,
  17. --
  18. tiny_corner_upper_left, tiny_border_upper, tiny_corner_upper_right,
  19. tiny_border_left, tiny_border_right,
  20. tiny_corner_lower_left, tiny_border_lower, tiny_corner_lower_right,
  21. --
  22. frame_upper_left, frame_upper, frame_upper_right,
  23. frame_left, frame_middle, frame_right,
  24. frame_lower_left, frame_lower, frame_lower_right,
  25. --
  26. icon_upper_left, icon_upper, icon_upper_right,
  27. icon_left, icon_right,
  28. icon_lower_left, icon_lower, icon_lower_right,
  29. --
  30. text_upper_left, text_upper, text_upper_right,
  31. text_left, text_middle, text_right,
  32. text_lower_left, text_lower, text_lower_right,
  33. --
  34. cursor, icon, overicon, icon_selected,
  35. --
  36. fill_bar_left, fill_bar_horizontal, fill_bar_right, fill_horizontal,
  37. tiny_fill_bar_left, tiny_fill_bar_horizontal, tiny_fill_bar_right, tiny_fill_horizontal,
  38. --
  39. scroll_bar_lower, scroll_bar_middle, scroll_bar_upper,
  40. --
  41. title_bar_left, title_bar_middle, title_bar_right,
  42. --
  43. check_box_on, check_box_off,
  44. --
  45. end_turn_button
  46. );
  47. ------------------------------------------------------------------------------------------
  48. type rectangle is record
  49. x, y, width, height : integer;
  50. end record;
  51. ------------------------------------------------------------------------------------------
  52. structure_limit : constant natural := 12;
  53. font_tint : array (style) of core.colour := (
  54. main => (127, 127, 127, 255),
  55. fairy => ( 0, 127, 255, 255),
  56. dwarf => (127, 255, 255, 255),
  57. gnoll => (255, 255, 0, 255),
  58. kobold => (255, 127, 255, 255),
  59. goblin => ( 0, 255, 127, 255),
  60. imp => (255, 127, 0, 255)
  61. );
  62. sprite : array (style, element) of core.sprite;
  63. font : array (style) of core.font;
  64. structure_array : array (0 .. structure_limit) of structure;
  65. structure_count : natural := 0;
  66. monospace : core.font;
  67. console_message_limit : constant natural := 6;
  68. console_message_count : natural := 0;
  69. --
  70. console_message_array : array (0 .. console_message_limit - 1) of ada.strings.unbounded.unbounded_string;
  71. ------------------------------------------------------------------------------------------
  72. procedure draw (index : in element := none;
  73. x : in integer := 0;
  74. y : in integer := 0;
  75. width : in integer := 0;
  76. height : in integer := 0) is
  77. begin
  78. core.draw (sprite (active, index), x, y, 0, 0, width, height, factor => 1);
  79. end draw;
  80. ------------------------------------------------------------------------------------------
  81. procedure draw_horizontally (index : in element; x, y, width : in integer; action : core.pointer := core.idle_skip'access; tint : in core.colour := (others => 255)) is
  82. begin
  83. core.draw_horizontally (sprite (active, index), x, y, width, 1, tint);
  84. end draw_horizontally;
  85. ------------------------------------------------------------------------------------------
  86. procedure draw_vertically (index : in element; x, y, height : in integer; action : core.pointer := core.idle_skip'access; tint : in core.colour := (others => 255)) is
  87. begin
  88. core.draw_vertically (sprite (active, index), x, y, height, 1, tint);
  89. end draw_vertically;
  90. ------------------------------------------------------------------------------------------
  91. procedure draw_background (index : in element; x, y, width, height : in integer; action : core.pointer := core.idle_skip'access) is
  92. base_width : integer := sprite (active, index).width;
  93. base_height : integer := sprite (active, index).height;
  94. crop_width : integer := width mod base_width;
  95. crop_height : integer := height mod base_height;
  96. begin
  97. for move_y in 0 .. height / base_height - 1 loop
  98. for move_x in 0 .. width / base_width - 1 loop
  99. draw (index, x + move_x * base_width, y + move_y * base_height);
  100. end loop;
  101. --
  102. if width mod base_width > 0 then
  103. draw (index, x + width - crop_width, y + move_y * base_height, crop_width, base_height);
  104. end if;
  105. end loop;
  106. --
  107. for move_x in 0 .. width / base_width - 1 loop
  108. if height mod base_height > 0 then
  109. draw (index, x + move_x * base_width, y + height - crop_height, base_width, crop_height);
  110. end if;
  111. end loop;
  112. --
  113. if width mod base_width > 0 and height mod base_height > 0 then
  114. draw (index, x + width - crop_width, y + height - crop_height, crop_width, crop_height);
  115. end if;
  116. end draw_background;
  117. ------------------------------------------------------------------------------------------
  118. procedure draw_popup_box is
  119. width : constant integer := 320;
  120. height : constant integer := core.icon;
  121. middle : constant integer := sprite (active, text_middle).width;
  122. offset : constant integer := 16;
  123. begin
  124. draw_background (text_middle, core.cursor.x + middle + offset, core.cursor.y + middle + offset, width - 2 * middle, height - 2 * middle);
  125. --
  126. draw_horizontally (text_upper, core.cursor.x + middle + offset, core.cursor.y + offset, width - 2 * middle);
  127. draw_horizontally (text_lower, core.cursor.x + middle + offset, core.cursor.y + height - middle + offset, width - 2 * middle);
  128. draw_vertically (text_left, core.cursor.x + offset, core.cursor.y + middle + offset, height - 2 * middle);
  129. draw_vertically (text_right, core.cursor.x + width - middle + offset, core.cursor.y + middle + offset, height - 2 * middle);
  130. --
  131. draw (text_upper_left, core.cursor.x + offset, core.cursor.y + offset);
  132. draw (text_upper_right, core.cursor.x + width - middle + offset, core.cursor.y + offset);
  133. draw (text_lower_left, core.cursor.x + offset, core.cursor.y + height - middle + offset);
  134. draw (text_lower_right, core.cursor.x + width - middle + offset, core.cursor.y + height - middle + offset);
  135. --
  136. ui.write (core.read_text_box, core.cursor.x + 4 + offset, core.cursor.y + 6 + offset);
  137. end draw_popup_box;
  138. ------------------------------------------------------------------------------------------
  139. procedure draw_structure (data : in structure) is
  140. offset : constant integer := core.icon / 4;
  141. orients : natural := 0;
  142. --
  143. frame_data : rectangle := (others => 0);
  144. button_data : rectangle := (others => 0);
  145. begin
  146. for index in 0 .. data.gui_n - 1 loop
  147. if data.gui_list (index).kind = gui_orient then
  148. orients := orients + 1;
  149. end if;
  150. end loop;
  151. --
  152. frame_data.width := (if data.resize then 320 else data.width) * (orients + 1) - offset * orients;
  153. frame_data.height := (if data.resize then data.gui_n * (core.icon + 2 * offset) + 2 * core.icon else data.height) / (orients + 1) + offset * orients;
  154. frame_data.x := (if data.center then (core.window_width - frame_data.width) / 2 else data.x);
  155. frame_data.y := (if data.center then (core.window_height - frame_data.height) / 2 else data.y);
  156. button_data.width := frame_data.width / (orients + 1) - 2 * core.icon;
  157. button_data.height := core.icon + 2 * offset;
  158. button_data.x := frame_data.x + core.icon;
  159. button_data.y := frame_data.y + core.icon;
  160. --
  161. draw_tiny_menu (frame_data.x, frame_data.y, frame_data.width, frame_data.height);
  162. draw_title_bar (frame_data.x, frame_data.y, frame_data.width, data.title);
  163. --
  164. for x in 0 .. data.gui_n - 1 loop
  165. case data.gui_list (x).kind is
  166. when gui_button =>
  167. draw_button (text => -(data.gui_list (x).text),
  168. description => -(data.gui_list (x).info),
  169. icon => data.gui_list (x).image,
  170. x => button_data.x,
  171. y => button_data.y,
  172. width => button_data.width,
  173. height => button_data.height);
  174. --
  175. button_data.y := button_data.y + button_data.height;
  176. when gui_orient =>
  177. button_data.x := button_data.x + frame_data.width / (orients + 1) - 2 * core.icon + offset;
  178. button_data.y := frame_data.y + core.icon;
  179. when others => null;
  180. end case;
  181. end loop;
  182. --
  183. if orients > 0 then
  184. draw_scroll_bar (frame_data.x + frame_data.width - 2 * core.icon, frame_data.y + core.icon, frame_data.height - 2 * core.icon, 4);
  185. end if;
  186. end draw_structure;
  187. ------------------------------------------------------------------------------------------
  188. procedure configure is
  189. procedure load_ui (index : in style; folder_path : in string) is
  190. begin
  191. font (index) := core.import_font (core.folder & "/ui/" & folder_path & "/font.png", 24, 0);
  192. --
  193. for this in element loop
  194. sprite (index, this) := core.import_sprite (core.folder & "/ui/" & folder_path & "/" & core.lowercase (element'image (this)) & ".png", 1, 1);
  195. end loop;
  196. end load_ui;
  197. begin
  198. monospace := core.import_font (core.folder & "/ui/monospace.png", 15, 0);
  199. --
  200. core.echo (core.comment, "Configuring UI components...");
  201. --
  202. for index in style loop
  203. load_ui (index, core.lowercase (style'image (index)));
  204. end loop;
  205. end configure;
  206. ------------------------------------------------------------------------------------------
  207. procedure synchronize is
  208. use core;
  209. begin
  210. prioritize := false;
  211. --
  212. for index in 0 .. structure_count - 1 loop
  213. if signal_mode = structure_array (index).toggle then
  214. structure_array (index).show := not structure_array (index).show;
  215. end if;
  216. --
  217. if structure_array (index).show then
  218. draw_structure (structure_array (index));
  219. --
  220. prioritize := true;
  221. end if;
  222. end loop;
  223. --
  224. draw (cursor, core.cursor.x, core.cursor.y);
  225. --
  226. if read_text_box /= "--" then
  227. draw_popup_box;
  228. end if;
  229. --
  230. core.write_text_box ("--");
  231. end synchronize;
  232. ------------------------------------------------------------------------------------------
  233. procedure echo (message : in string) is
  234. begin
  235. console_message_array (console_message_count) := ada.strings.unbounded.to_unbounded_string (message);
  236. --
  237. console_message_count := (console_message_count + 1) mod console_message_limit;
  238. end echo;
  239. ------------------------------------------------------------------------------------------
  240. procedure write (text : in string; x, y : in integer; tint : in core.colour := (others => 255); size : in natural := 15; code : in boolean := false) is
  241. begin
  242. core.write (text, x, y, tint, (if code then 15 else font (active).scale), (if code then monospace else font (active)));
  243. end write;
  244. ------------------------------------------------------------------------------------------
  245. procedure draw_icon (data : in core.sprite; text : in string; x, y : in integer; action : core.pointer := core.idle_skip'access) is
  246. begin
  247. draw (icon, x, y);
  248. --
  249. core.draw (data, x, y, factor => 1);
  250. --
  251. if core.cursor_inside (x, y, core.icon / core.zoom, core.icon / core.zoom) then
  252. prioritize := true;
  253. --
  254. draw (icon_selected, x, y);
  255. --
  256. core.write_help_box (text);
  257. --
  258. if core.cursor_mode = core.cursor_left then
  259. action.all;
  260. core.cursor_mode := core.cursor_none;
  261. end if;
  262. end if;
  263. end draw_icon;
  264. ------------------------------------------------------------------------------------------
  265. procedure draw_overicon (data : in core.sprite; text : in string; x, y : in integer; action : core.pointer := core.idle_skip'access) is
  266. begin
  267. core.draw (data, x, y, factor => 1);
  268. --
  269. draw (overicon, x, y);
  270. end draw_overicon;
  271. ------------------------------------------------------------------------------------------
  272. procedure draw_sprite (data : in core.sprite; text : in string; x, y, offset : in integer; action : core.pointer := core.idle_skip'access) is
  273. begin
  274. core.draw (data, x + offset, y + offset, factor => 1);
  275. --
  276. draw_icon_menu (x, y, data.width + 2 * offset, data.height + 2 * offset);
  277. --
  278. if core.cursor_inside (x, y, (data.width + 2 * offset) / core.zoom, (data.height + 2 * offset) / core.zoom) then
  279. prioritize := true;
  280. --
  281. core.write_help_box (text);
  282. --
  283. if core.cursor_mode = core.cursor_left then
  284. action.all;
  285. core.cursor_mode := core.cursor_none;
  286. end if;
  287. end if;
  288. end draw_sprite;
  289. ------------------------------------------------------------------------------------------
  290. procedure draw_text_box (x, y, width, height : in integer) is
  291. middle : constant integer := sprite (active, text_middle).width;
  292. begin
  293. draw_background (text_middle, x + middle, y + middle, width - 2 * middle, height - 2 * middle);
  294. --
  295. draw_horizontally (text_upper, x + middle, y, width - 2 * middle);
  296. draw_horizontally (text_lower, x + middle, y + height - middle, width - 2 * middle);
  297. draw_vertically (text_left, x, y + middle, height - 2 * middle);
  298. draw_vertically (text_right, x + width - middle, y + middle, height - 2 * middle);
  299. --
  300. draw (text_upper_left, x, y);
  301. draw (text_upper_right, x + width - middle, y);
  302. draw (text_lower_left, x, y + height - middle);
  303. draw (text_lower_right, x + width - middle, y + height - middle);
  304. end draw_text_box;
  305. ------------------------------------------------------------------------------------------
  306. procedure draw_help_box (x, y, width, height : in integer; action : core.pointer := core.idle_skip'access) is
  307. offset : constant integer := sprite (active, text_middle).width;
  308. begin
  309. if core.cursor_inside (x, y, width, height) then
  310. prioritize := true;
  311. end if;
  312. --
  313. draw_background (text_middle, x + offset, y + offset, width - 2 * offset, height - 2 * offset);
  314. --
  315. draw_horizontally (text_upper, x + offset, y, width - 2 * offset);
  316. draw_horizontally (text_lower, x + offset, y + height - offset, width - 2 * offset);
  317. draw_vertically (text_left, x, y + offset, height - 2 * offset);
  318. draw_vertically (text_right, x + width - offset, y + offset, height - 2 * offset);
  319. --
  320. draw (text_upper_left, x, y);
  321. draw (text_upper_right, x + width - offset, y);
  322. draw (text_lower_left, x, y + height - offset);
  323. draw (text_lower_right, x + width - offset, y + height - offset);
  324. --
  325. ui.write (core.read_help_box, (core.icon - font (active).scale) / 2 + x + 4, (core.icon - font (active).scale) / 2 + y);
  326. --
  327. core.write_help_box ("--");
  328. end draw_help_box;
  329. ------------------------------------------------------------------------------------------
  330. procedure draw_frame (description : in string; x, y, width, height : in integer; action : core.pointer := core.idle_skip'access) is
  331. offset_x : constant integer := sprite (active, frame_middle).width;
  332. offset_y : constant integer := sprite (active, frame_middle).height;
  333. begin
  334. if height < core.icon or width < core.icon then
  335. return;
  336. end if;
  337. --
  338. draw_background (frame_middle, x + offset_x, y + offset_y, width - 2 * offset_x, height - 2 * offset_y);
  339. --
  340. draw_horizontally (frame_upper, x + offset_x, y, width - 2 * offset_x);
  341. draw_horizontally (frame_lower, x + offset_x, y + height - offset_y, width - 2 * offset_x);
  342. draw_vertically (frame_left, x, y + offset_y, height - 2 * offset_y);
  343. draw_vertically (frame_right, x + width - offset_x, y + offset_y, height - 2 * offset_y);
  344. --
  345. draw (frame_upper_left, x, y);
  346. draw (frame_upper_right, x + width - sprite (active, frame_upper_right).width, y);
  347. draw (frame_lower_left, x, y + height - sprite (active, frame_lower_left).height);
  348. draw (frame_lower_right, x + width - sprite (active, frame_lower_right).width, y + height - sprite (active, frame_lower_right).height);
  349. --
  350. if core.cursor_inside (x, y, width / core.zoom, height / core.zoom) then
  351. prioritize := true;
  352. --
  353. core.write_help_box (description);
  354. --
  355. if core.cursor_mode = core.cursor_left then
  356. action.all;
  357. core.cursor_mode := core.cursor_none;
  358. end if;
  359. end if;
  360. end draw_frame;
  361. ------------------------------------------------------------------------------------------
  362. procedure draw_button (text, description : in string; icon : in core.sprite; x, y, width, height : in integer; action : core.pointer := core.idle_skip'access) is
  363. offset : constant integer := core.icon / 4;
  364. begin
  365. draw_frame (description, x, y, width, height);
  366. draw_icon (icon, description, x + offset, y + offset);
  367. --
  368. ui.write (text,
  369. x + offset + (core.icon - font (active).scale) / 2 + core.icon,
  370. y + offset + (core.icon - font (active).scale) / 2,
  371. (if core.cursor_inside (x, y, width / core.zoom, height / core.zoom) then font_tint (active) else (others => 255)));
  372. --
  373. if core.cursor_inside (x, y, width / core.zoom, height / core.zoom) then
  374. prioritize := true;
  375. --
  376. if core.cursor_mode = core.cursor_left then
  377. action.all;
  378. core.cursor_mode := core.cursor_none;
  379. end if;
  380. end if;
  381. end draw_button;
  382. ------------------------------------------------------------------------------------------
  383. procedure draw_check_box (x, y : in integer; on : in out boolean; text : in string) is
  384. begin
  385. draw ((if on then check_box_on else check_box_off), x, y);
  386. --
  387. ui.write (text, x + sprite (active, check_box_on).width, y);
  388. --
  389. if core.cursor_mode = core.cursor_left
  390. and core.cursor_inside (x, y, sprite (active, check_box_on).width / core.zoom, sprite (active, check_box_on).height / core.zoom) then
  391. on := not on;
  392. core.cursor_mode := core.cursor_none;
  393. end if;
  394. end draw_check_box;
  395. ------------------------------------------------------------------------------------------
  396. procedure draw_title_bar (x, y, width : in integer; title : in string) is
  397. middle_width : constant integer := width - sprite (active, title_bar_left).width - sprite (active, title_bar_right).width;
  398. offset : constant integer := (sprite (active, title_bar_middle).height - font (active).scale) / 2;
  399. begin
  400. if core.cursor_inside (x, y, width / core.zoom, sprite (active, title_bar_left).height / core.zoom) then
  401. prioritize := true;
  402. end if;
  403. --
  404. draw (title_bar_left, x, y - sprite (active, title_bar_left).height);
  405. draw (title_bar_right, x + middle_width + sprite (active, title_bar_left).width, y - sprite (active, title_bar_right).height);
  406. --
  407. draw_horizontally (title_bar_middle, x + sprite (active, title_bar_left).width, y - sprite (active, title_bar_middle).height, middle_width);
  408. --
  409. ui.write (title, x + sprite (active, title_bar_left).width, y - font (active).scale - 4, tint => font_tint (active));
  410. end draw_title_bar;
  411. ------------------------------------------------------------------------------------------
  412. procedure draw_fill_bar (x, y, width : in integer; fill : in float) is
  413. middle_width : constant integer := width - sprite (active, fill_bar_left).width - sprite (active, fill_bar_right).width;
  414. fill_width : constant integer := integer (float (middle_width) * fill);
  415. begin
  416. draw (fill_bar_left, x, y - sprite (active, fill_bar_left).height);
  417. draw (fill_bar_right, x + middle_width + sprite (active, fill_bar_left).width, y - sprite (active, fill_bar_right).height);
  418. --
  419. draw_horizontally (fill_bar_horizontal, x + sprite (active, fill_bar_left).width, y - sprite (active, fill_bar_horizontal).height, middle_width);
  420. draw_horizontally (fill_horizontal, x + sprite (active, fill_bar_left).width, y - sprite (active, fill_bar_horizontal).height, fill_width);
  421. end draw_fill_bar;
  422. ------------------------------------------------------------------------------------------
  423. procedure draw_tiny_fill_bar (x, y, width : in integer; fill : in float; tint : in core.colour) is
  424. middle_width : constant integer := width - sprite (active, tiny_fill_bar_left).width - sprite (active, tiny_fill_bar_right).width;
  425. fill_width : constant integer := integer (float (middle_width) * fill);
  426. begin
  427. draw (tiny_fill_bar_left, x, y - sprite (active, tiny_fill_bar_left).height);
  428. draw (tiny_fill_bar_right, x + middle_width + sprite (active, tiny_fill_bar_left).width, y - sprite (active, tiny_fill_bar_left).height);
  429. --
  430. draw_horizontally (tiny_fill_bar_horizontal, x + sprite (active, tiny_fill_bar_left).width, y - sprite (active, tiny_fill_bar_horizontal).height, middle_width);
  431. --
  432. draw_horizontally (index => tiny_fill_horizontal,
  433. x => x + sprite (active, tiny_fill_bar_left).width,
  434. y => y - sprite (active, tiny_fill_bar_horizontal).height,
  435. width => fill_width,
  436. tint => tint);
  437. end draw_tiny_fill_bar;
  438. ------------------------------------------------------------------------------------------
  439. procedure draw_scroll_bar (x, y, height, offset : in integer) is
  440. middle_height : constant integer := height - sprite (active, scroll_bar_upper).height - sprite (active, scroll_bar_lower).height;
  441. begin
  442. draw (scroll_bar_upper, x, y);
  443. draw (scroll_bar_lower, x, y + middle_height + sprite (active, scroll_bar_upper).height);
  444. --
  445. draw_vertically (scroll_bar_middle, x, y + sprite (active, scroll_bar_upper).height, middle_height);
  446. end draw_scroll_bar;
  447. ------------------------------------------------------------------------------------------
  448. procedure draw_menu (x, y, width, height : in integer) is
  449. offset : constant integer := sprite (active, none).width;
  450. begin
  451. if core.cursor_inside (x, y, width / core.zoom, height / core.zoom) then
  452. prioritize := true;
  453. end if;
  454. --
  455. declare upper : constant integer := width - sprite (active, corner_upper_left).width - sprite (active, corner_upper_right).width;
  456. lower : constant integer := width - sprite (active, corner_lower_left).width - sprite (active, corner_lower_right).width;
  457. left : constant integer := height - sprite (active, corner_upper_left).height - sprite (active, corner_lower_left).height;
  458. right : constant integer := height - sprite (active, corner_upper_right).height - sprite (active, corner_lower_right).height;
  459. begin
  460. draw_horizontally (border_upper, x + sprite (active, corner_upper_left).width, y, upper);
  461. draw_horizontally (border_lower, x + sprite (active, corner_lower_left).width, y + height - sprite (active, border_lower).height, lower);
  462. draw_vertically (border_left, x, y + sprite (active, corner_upper_left).height, left);
  463. draw_vertically (border_right, x + width - sprite (active, border_right).width, y + sprite (active, corner_upper_right).height, right);
  464. end;
  465. --
  466. draw (corner_upper_left, x, y);
  467. draw (corner_upper_right, x + width - sprite (active, corner_upper_right).width, y);
  468. draw (corner_lower_left, x, y + height - sprite (active, corner_lower_left).height);
  469. draw (corner_lower_right, x + width - sprite (active, corner_lower_right).width, y + height - sprite (active, corner_lower_right).height);
  470. end draw_menu;
  471. ------------------------------------------------------------------------------------------
  472. procedure draw_tiny_menu (x, y, width, height : in integer) is
  473. offset : constant integer := sprite (active, none).width;
  474. begin
  475. if core.cursor_inside (x, y, width / core.zoom, height / core.zoom) then
  476. prioritize := true;
  477. end if;
  478. --
  479. draw_background (main_background, x + offset, y + offset, width - 2 * offset, height - 2 * offset);
  480. --
  481. declare upper : constant integer := width - sprite (active, tiny_corner_upper_left).width - sprite (active, tiny_corner_upper_right).width;
  482. lower : constant integer := width - sprite (active, tiny_corner_lower_left).width - sprite (active, tiny_corner_lower_right).width;
  483. left : constant integer := height - sprite (active, tiny_corner_upper_left).height - sprite (active, tiny_corner_lower_left).height;
  484. right : constant integer := height - sprite (active, tiny_corner_upper_right).height - sprite (active, tiny_corner_lower_right).height;
  485. begin
  486. draw_horizontally (tiny_border_upper, x + sprite (active, tiny_corner_upper_left).width, y, upper);
  487. draw_horizontally (tiny_border_lower, x + sprite (active, tiny_corner_lower_left).width, y + height - sprite (active, tiny_border_lower).height, lower);
  488. draw_vertically (tiny_border_left, x, y + sprite (active, tiny_corner_upper_left).height, left);
  489. draw_vertically (tiny_border_right, x + width - sprite (active, tiny_border_right).width, y + sprite (active, tiny_corner_upper_right).height, right);
  490. end;
  491. --
  492. draw (tiny_corner_upper_left, x, y);
  493. draw (tiny_corner_upper_right, x + width - sprite (active, tiny_corner_upper_right).width, y);
  494. draw (tiny_corner_lower_left, x, y + height - sprite (active, tiny_corner_lower_left).height);
  495. draw (tiny_corner_lower_right, x + width - sprite (active, tiny_corner_lower_right).width, y + height - sprite (active, tiny_corner_lower_right).height);
  496. end draw_tiny_menu;
  497. ------------------------------------------------------------------------------------------
  498. procedure draw_icon_menu (x, y, width, height : in integer) is
  499. offset_x : constant integer := sprite (active, icon_upper_left).width;
  500. offset_y : constant integer := sprite (active, icon_upper_left).height;
  501. begin
  502. if core.cursor_inside (x, y, width / core.zoom, height / core.zoom) then
  503. prioritize := true;
  504. end if;
  505. --
  506. if height < 2 * sprite (active, icon_upper_left).height
  507. or width < 2 * sprite (active, icon_upper_left).width then
  508. return;
  509. end if;
  510. --
  511. draw_horizontally (icon_upper, x + offset_x, y, width - 2 * offset_x);
  512. draw_horizontally (icon_lower, x + offset_x, y + height - offset_y, width - 2 * offset_x);
  513. draw_vertically (icon_left, x, y + offset_y, height - 2 * offset_y);
  514. draw_vertically (icon_right, x + width - offset_x, y + offset_y, height - 2 * offset_y);
  515. --
  516. draw (icon_upper_left, x, y);
  517. draw (icon_upper_right, x + width - sprite (active, icon_upper_right).width, y);
  518. draw (icon_lower_left, x, y + height - sprite (active, icon_lower_left).height);
  519. draw (icon_lower_right, x + width - sprite (active, icon_lower_right).width, y + height - sprite (active, icon_lower_right).height);
  520. end draw_icon_menu;
  521. ------------------------------------------------------------------------------------------
  522. procedure draw_end_turn_button (x, y : in integer) is
  523. begin
  524. draw (end_turn_button, x, y);
  525. --
  526. if core.cursor_inside (x, y, sprite (active, end_turn_button).width, sprite (active, end_turn_button).height) and core.cursor_mode = core.cursor_left then
  527. core.end_turn := true;
  528. core.cursor_mode := core.cursor_none;
  529. --
  530. echo ("-- Turn --");
  531. end if;
  532. end draw_end_turn_button;
  533. ------------------------------------------------------------------------------------------
  534. procedure draw_state_box (x, y : in integer) is
  535. begin
  536. ui.write ("Cursor X:" & core.cursor.x'image, x, y + 0);
  537. ui.write ("Cursor Y:" & core.cursor.y'image, x, y + 32);
  538. ui.write ("Cursor Mode:" & core.cursor_mode'image, x, y + 64);
  539. ui.write ("Camera X:" & core.camera.x'image, x, y + 96);
  540. ui.write ("Camera Y:" & core.camera.y'image, x, y + 128);
  541. ui.write ("Global Time:" & core.global_time'image, x, y + 160);
  542. ui.write ("Gameplay Time:" & core.gameplay_time'image, x, y + 192);
  543. ui.write ("Animation Time:" & core.animation_time'image, x, y + 224);
  544. ui.write ("Framerate:" & core.framerate'image, x, y + 256);
  545. end draw_state_box;
  546. ------------------------------------------------------------------------------------------
  547. procedure draw_console_box (x, y, width, height : in integer) is
  548. offset : constant integer := 8;
  549. font_width : constant integer := 9;
  550. font_height : constant integer := 15;
  551. characters_per_width : constant integer := width / font_width;
  552. characters_per_height : constant integer := height / font_height;
  553. begin
  554. draw_text_box (x, y, width, height);
  555. --
  556. for index in 0 .. console_message_limit - 1 loop
  557. ui.write (text => ada.strings.unbounded.to_string (console_message_array ((index + console_message_count) mod console_message_limit)),
  558. x => x + offset,
  559. y => y + offset + index * font_height,
  560. size => 15,
  561. code => true);
  562. end loop;
  563. end draw_console_box;
  564. ------------------------------------------------------------------------------------------
  565. procedure add_structure (data : in structure) is
  566. begin
  567. structure_array (structure_count) := data;
  568. structure_array (structure_count).gui_list := new gui_array (0 .. structure_array (structure_count).gui_n - 1);
  569. structure_array (structure_count).gui_n := 0;
  570. --
  571. core.increment (structure_count);
  572. end add_structure;
  573. ------------------------------------------------------------------------------------------
  574. procedure add_structure_button (icon : in core.sprite; name : in core.unstring; text : in core.unstring) is
  575. index : natural renames structure_array (structure_count - 1).gui_n;
  576. begin
  577. structure_array (structure_count - 1).gui_list (index).kind := gui_button;
  578. structure_array (structure_count - 1).gui_list (index).text := name;
  579. structure_array (structure_count - 1).gui_list (index).info := text;
  580. structure_array (structure_count - 1).gui_list (index).number := 0;
  581. structure_array (structure_count - 1).gui_list (index).image := icon;
  582. --
  583. core.increment (index);
  584. end add_structure_button;
  585. ------------------------------------------------------------------------------------------
  586. procedure add_structure_orient is
  587. index : natural renames structure_array (structure_count - 1).gui_n;
  588. begin
  589. structure_array (structure_count - 1).gui_list (index).kind := gui_orient;
  590. --
  591. core.increment (index);
  592. end add_structure_orient;
  593. ------------------------------------------------------------------------------------------
  594. procedure write_ada_code (text : in core.string_box_data; x, y : in integer) is
  595. word : ada.strings.unbounded.unbounded_string := ada.strings.unbounded.to_unbounded_string ("");
  596. --
  597. buffer : character := ' ';
  598. width : constant integer := 9;
  599. height : constant integer := 15;
  600. length : natural := 1;
  601. offset : core.vector := (x, y);
  602. subset : natural := 0;
  603. begin
  604. loop
  605. buffer := ada.strings.unbounded.element (text.text, length);
  606. offset.x := offset.x + width;
  607. --
  608. exit when buffer = character'val (0);
  609. --
  610. case buffer is
  611. when character'val (9) => offset.x := offset.x + 2 * width;
  612. when character'val (10) => offset.y := offset.y + 1 * height; offset.x := x;
  613. when ':' | ';' | '.' | ',' | '=' | '<' | '>' =>
  614. ui.write (buffer & "", offset.x, offset.y, (63, 127, 255, 255), height, code => true);
  615. when '+' | '*' | '/' | '|' | '&' =>
  616. ui.write (buffer & "", offset.x, offset.y, (63, 63, 255, 255), height, code => true);
  617. when '(' | ')' | ''' =>
  618. ui.write (buffer & "", offset.x, offset.y, (63, 255, 255, 255), height, code => true);
  619. when '"' =>
  620. ui.write (buffer & "", offset.x, offset.y, (127, 63, 127, 255), height, code => true);
  621. offset.x := offset.x + width;
  622. loop
  623. core.increment (length);
  624. buffer := ada.strings.unbounded.element (text.text, length);
  625. ui.write (buffer & "", offset.x, offset.y, (127, 63, 127, 255), height, code => true);
  626. offset.x := offset.x + width;
  627. exit when buffer = '"';
  628. end loop;
  629. offset.x := offset.x - width;
  630. when '-' =>
  631. if ada.strings.unbounded.element (text.text, length + 1) = '-' then
  632. ui.write (buffer & "", offset.x, offset.y, (127, 127, 127, 255), height, code => true);
  633. offset.x := offset.x + width;
  634. loop
  635. core.increment (length);
  636. buffer := ada.strings.unbounded.element (text.text, length);
  637. ui.write (buffer & "", offset.x, offset.y, (127, 127, 127, 255), height, code => true);
  638. offset.x := offset.x + width;
  639. exit when buffer = character'val (10);
  640. end loop;
  641. core.decrement (length);
  642. else
  643. ui.write (buffer & "", offset.x, offset.y, (63, 63, 255, 255), height, code => true);
  644. end if;
  645. when '0' .. '9' =>
  646. loop
  647. ui.write (buffer & "", offset.x, offset.y, (127, 63, 255, 255), height, code => true);
  648. core.increment (length);
  649. buffer := ada.strings.unbounded.element (text.text, length);
  650. exit when buffer = ' ' or buffer = ';' or buffer = ')' or buffer = ',';
  651. offset.x := offset.x + width;
  652. end loop;
  653. core.decrement (length);
  654. when 'a' .. 'z' | 'A' .. 'Z' =>
  655. word := ada.strings.unbounded.to_unbounded_string (buffer & "");
  656. subset := 1;
  657. loop
  658. buffer := ada.strings.unbounded.element (text.text, length + subset);
  659. exit when buffer = ' ' or buffer = '.' or buffer = '(' or buffer = ')' or buffer = ',' or buffer = ';' or buffer = '''
  660. or buffer = character'val (9) or buffer = character'val (10);
  661. word := word & ada.strings.unbounded.to_unbounded_string (buffer & "");
  662. core.increment (subset);
  663. end loop;
  664. if word = "type" or word = "begin" or word = "end" or word = "when" or word = "others" or word = "procedure" or word = "function"
  665. or word = "package" or word = "body" or word = "if" or word = "then" or word = "else" or word = "elsif" or word = "case" or word = "is"
  666. or word = "and" or word = "or" or word = "xor" or word = "exit" or word = "constant" or word = "access" or word = "range"
  667. or word = "subtype" or word = "array" or word = "in" or word = "out" or word = "return" or word = "for" or word = "with"
  668. or word = "loop" or word = "while" or word = "of" or word = "null" or word = "record" or word = "use" or word = "mod" or word = "new"
  669. or word = "aliased" or word = "all" then
  670. ui.write (ada.strings.unbounded.to_string (word), offset.x, offset.y, (255, 255, 0, 255), height, code => true);
  671. else
  672. ui.write (ada.strings.unbounded.to_string (word), offset.x, offset.y, (others => 255), height, code => true);
  673. end if;
  674. offset.x := offset.x + (subset - 1) * width;
  675. length := length + subset - 1;
  676. when others =>
  677. ui.write (buffer & "", offset.x, offset.y, (others => 255), height, code => true);
  678. end case;
  679. --
  680. core.increment (length);
  681. end loop;
  682. end write_ada_code;
  683. ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  684. end ui;