/// _ /// __ ___ _(_) /// \ \/ / | | | | /// > <| |_| | | /// /_/\_\\__,_|_| /// /// Copyright (c) 1997 - Ognjen 'xolatile' Milan Robovic /// /// xolatile@chud.cyou - xui - Tiny GUI unity header, I'm not sure if it's immediate or not... Probably not. /// /// This program is free software, free as in freedom and as in free beer, you can redistribute it and/or modify it under the terms of the GNU /// General Public License as published by the Free Software Foundation, either version 3 of the License, or any later version if you wish... /// /// This program is distributed in the hope that it will be useful, but it is probably not, and without any warranty, without even the implied /// warranty of merchantability or fitness for a particular purpose, because it is pointless. Please see the GNU (Geenoo) General Public License /// for more details, if you dare, it is a lot of text that nobody wants to read... typedef enum { ui_window_left, ui_window_right, ui_window_upper, ui_window_lower, ui_window_upper_left, ui_window_upper_right, ui_window_lower_left, ui_window_lower_right, ui_frame_left, ui_frame_right, ui_frame_upper, ui_frame_lower, ui_frame_upper_left, ui_frame_upper_right, ui_frame_lower_left, ui_frame_lower_right, ui_status_left, ui_status_right, ui_status_upper, ui_status_lower, ui_status_upper_left, ui_status_upper_right, ui_status_lower_left, ui_status_lower_right, ui_status_middle, ui_menu_left, ui_menu_right, ui_menu_upper, ui_menu_lower, ui_menu_upper_left, ui_menu_upper_right, ui_menu_lower_left, ui_menu_lower_right, ui_menu_middle, ui_button_left, ui_button_right, ui_button_upper, ui_button_lower, ui_button_upper_left, ui_button_upper_right, ui_button_lower_left, ui_button_lower_right, ui_button_middle, ui_fill_bar_left, ui_fill_bar_middle, ui_fill_bar_right, ui_fill_bar_base, ui_tiny_fill_bar_middle, ui_tiny_fill_bar_left, ui_tiny_fill_bar_right, ui_tiny_fill_middle, ui_check_box_off, ui_check_box_on, ui_end_turn_button, ui_icon_frame, ui_overicon_frame, ui_ubericon_frame, ui_scroll_bar_lower, ui_scroll_bar_middle, ui_scroll_bar_upper, ui_scroll_bar_slider, ui_separator_left, ui_separator_middle, ui_separator_right, ui_separator_center, ui_title_bar_left, ui_title_bar_middle, ui_title_bar_right, ui_subcount } ui_subtype; typedef enum { ui_window = ui_window_left, ui_frame = ui_frame_left, ui_status = ui_status_left, ui_menu = ui_menu_left, ui_button = ui_button_left } ui_type; typedef struct { bool freeview; uint ignore; uint camera_x; uint camera_y; char * help_box_none; char * help_box_text; uint help_box_icon; uint side_panel; uint font; uint monofont; uint sprite [ui_subcount]; uint width [ui_subcount]; uint height [ui_subcount]; uint separator_size; uint icon_size; uint overicon_size; uint ubericon_size; uint title_bar_size; uint fill_bar_size; uint scroll_bar_size; uint camera_speed; } ui_structure; static ui_structure * ui_initialize (cross_structure * cross) { char * subtype_file_name [ui_subcount] = { "window_left", "window_right", "window_upper", "window_lower", "window_upper_left", "window_upper_right", "window_lower_left", "window_lower_right", "frame_left", "frame_right", "frame_upper", "frame_lower", "frame_upper_left", "frame_upper_right", "frame_lower_left", "frame_lower_right", "status_left", "status_right", "status_upper", "status_lower", "status_upper_left", "status_upper_right", "status_lower_left", "status_lower_right", "status_middle", "menu_left", "menu_right", "menu_upper", "menu_lower", "menu_upper_left", "menu_upper_right", "menu_lower_left", "menu_lower_right", "menu_middle", "button_left", "button_right", "button_upper", "button_lower", "button_upper_left", "button_upper_right", "button_lower_left", "button_lower_right", "button_middle", "fill_bar_left", "fill_bar_middle", "fill_bar_right", "fill_bar_base", "tiny_fill_bar_left", "tiny_fill_bar_middle", "tiny_fill_bar_right", "tiny_fill_bar_base", "check_box_off", "check_box_on", "end_turn_button", "cursor", "icon_frame", "overicon_frame", "ubericon_frame", "scroll_bar_lower", "scroll_bar_middle", "scroll_bar_upper", "scroll_bar_slider", "separator_left", "separator_middle", "separator_right", "separator_center", "title_bar_left", "title_bar_middle", "title_bar_right" }; ui_structure * ui = allocate (sizeof (* ui)); ui->freeview = false; ui->ignore = ~ 0u; ui->camera_x = 0; ui->camera_y = 0; ui->help_box_none = string_duplicate ("---"); ui->help_box_text = ui->help_box_none; ui->help_box_icon = ui->ignore; ui->side_panel = 400; ui->font = cross_font_import (cross, configuration_format ("xui/regular"), ' ', '~', 0xffee0000u); ui->monofont = cross_font_import (cross, configuration_format ("xui/monospace"), ' ', '~', 0xffeeee00u); for (uint index = 0; index < ui_subcount; ++index) { char * file_name = configuration_format (format ("xui/%s", subtype_file_name [index])); ui->sprite [index] = cross_sprite_import (cross, file_name); ui->width [index] = cross_sprite_width (cross, ui->sprite [index]); ui->height [index] = cross_sprite_height (cross, ui->sprite [index]); } ui->separator_size = ui->height [ui_separator_middle]; ui->icon_size = ui->height [ui_icon_frame]; ui->overicon_size = ui->height [ui_overicon_frame]; ui->ubericon_size = ui->height [ui_ubericon_frame]; ui->title_bar_size = ui->height [ui_title_bar_middle]; ui->fill_bar_size = ui->height [ui_fill_bar_middle]; ui->scroll_bar_size = ui->width [ui_scroll_bar_middle]; print ("[/2Success/-] Initialized UI structure.\n"); return (ui); } static ui_structure * ui_deinitialize (ui_structure * ui) { ui->help_box_none = deallocate (ui->help_box_none); print ("[/2Success/-] Deinitialized UI information.\n"); return (deallocate (ui)); } static int ui_offset_x (cross_structure * cross, ui_structure * ui) { return (ui->camera_x - cross->window_width / 2); } static int ui_offset_y (cross_structure * cross, ui_structure * ui) { return (ui->camera_y - cross->window_height / 2); } static uint ui_side_panel (ui_structure * ui) { return (ui->side_panel); /// MAKE IT WINDOW SIZE DEPENDENT? } static void ui_camera_upper (ui_structure * ui) { ui->freeview = true; ui->camera_y -= ui->camera_speed; } static void ui_camera_lower (ui_structure * ui) { ui->freeview = true; ui->camera_y += ui->camera_speed; } static void ui_camera_left (ui_structure * ui) { ui->freeview = true; ui->camera_x -= ui->camera_speed; } static void ui_camera_right (ui_structure * ui) { ui->freeview = true; ui->camera_x += ui->camera_speed; } static void ui_render (cross_structure * cross, ui_structure * ui, ui_subtype index, int x, int y) { cross_render_sprite (cross, ui->sprite [index], x, y); } static void ui_render_colour (cross_structure * cross, ui_structure * ui, ui_subtype index, uint colour, int x, int y) { cross_render_sprite_colour (cross, ui->sprite [index], colour, x, y); } static void ui_subrender (cross_structure * cross, ui_structure * ui, ui_subtype index, int x, int y, uint u, uint v, uint width, uint height) { cross_render_sprite_crop (cross, ui->sprite [index], x, y, u, v, width, height); } static void ui_subrender_colour (cross_structure * cross, ui_structure * ui, ui_subtype index, uint colour, int x, int y, uint u, uint v, uint width, uint height) { cross_render_sprite_crop_colour (cross, ui->sprite [index], colour, x, y, u, v, width, height); } static void ui_render_horizontal (cross_structure * cross, ui_structure * ui, ui_subtype index, int x, int y, uint width) { int entire = (width / ui->width [index]) * ui->width [index]; for (uint margin = 0; margin < width / ui->width [index]; ++margin) { ui_render (cross, ui, index, x + margin * ui->width [index], y); } if (width % ui->width [index] > 0) { ui_subrender (cross, ui, index, x + entire, y, 0, 0, width % ui->width [index], ui->height [index]); } } static void ui_render_horizontal_colour (cross_structure * cross, ui_structure * ui, ui_subtype index, uint colour, int x, int y, uint width) { int entire = (width / ui->width [index]) * ui->width [index]; for (uint margin = 0; margin < width / ui->width [index]; ++margin) { ui_render_colour (cross, ui, index, colour, x + margin * ui->width [index], y); } if (width % ui->width [index] > 0) { ui_subrender_colour (cross, ui, index, colour, x + entire, y, 0, 0, width % ui->width [index], ui->height [index]); } } static void ui_render_vertical (cross_structure * cross, ui_structure * ui, ui_subtype index, int x, int y, uint height) { int entire = (height / ui->height [index]) * ui->height [index]; for (uint margin = 0; margin < height / ui->height [index]; ++margin) { ui_render (cross, ui, index, x, y + margin * ui->height [index]); } if (height % ui->height [index] > 0) { ui_subrender (cross, ui, index, x, y + entire, 0, 0, ui->width [index], height % ui->height [index]); } } static void ui_render_background (cross_structure * cross, ui_structure * ui, ui_subtype index, int x, int y, uint width, uint height) { uint offset_x = (width / ui->width [index]) * ui->width [index]; uint offset_y = (height / ui->height [index]) * ui->height [index]; uint cutoff_x = width % ui->width [index]; uint cutoff_y = height % ui->height [index]; for (uint vertical = 0; vertical < height / ui->height [index]; ++vertical) { for (uint horizontal = 0; horizontal < width / ui->width [index]; ++horizontal) { ui_render (cross, ui, index, x + horizontal * ui->width [index], y + vertical * ui->height [index]); } if (width % ui->width [index] > 0) { ui_subrender (cross, ui, index, x + offset_x, y + vertical * ui->height [index], 0, 0, cutoff_x, ui->height [index]); } } for (uint horizontal = 0; horizontal < width / ui->width [index]; ++horizontal) { ui_subrender (cross, ui, index, x + horizontal * ui->width [index], y + offset_y, 0, 0, ui->width [index], cutoff_y); } if (width % ui->width [index] > 0) { ui_subrender (cross, ui, index, x + offset_x, y + offset_y, 0, 0, cutoff_x, cutoff_y); } } static void ui_screen_overlay (cross_structure * cross) { cross_render_rectangle_vertical_gradient (cross, 0, 0, cross->window_width, cross->window_height / 2, 0xcc, 0x00); cross_render_rectangle_vertical_gradient (cross, 0, cross->window_height / 2, cross->window_width, cross->window_height / 2, 0x00, 0xcc); } static void ui_render_grid (cross_structure * cross, ui_structure * ui, ui_type element, int x, int y, uint width, uint height, uint margin, bool background) { uint upper_length = width - ui->width [element + 4] - ui->width [element + 5]; uint lower_length = width - ui->width [element + 6] - ui->width [element + 7]; uint left_length = height - ui->height [element + 4] - ui->height [element + 6]; uint right_length = height - ui->height [element + 5] - ui->height [element + 7]; int upper_offset_x = ui->width [element + 4]; int lower_offset_x = ui->width [element + 6]; int lower_offset_y = height - ui->height [element + 3]; int right_offset_x = width - ui->width [element + 1]; int left_offset_y = ui->height [element + 4]; int right_offset_y = ui->height [element + 5]; int upper_right_offset_x = width - ui->width [element + 5]; int lower_right_offset_x = width - ui->width [element + 7]; int lower_left_offset_y = height - ui->height [element + 6]; int lower_right_offset_y = height - ui->height [element + 7]; if ((background == true) && (width > 2 * margin) && (height > 2 * margin)) { ui_render_background (cross, ui, element + 8, x + margin, y + margin, width - 2 * margin, height - 2 * margin); } ui_render_vertical (cross, ui, element + 0, x, y + left_offset_y, left_length); ui_render_vertical (cross, ui, element + 1, x + right_offset_x, y + right_offset_y, right_length); ui_render_horizontal (cross, ui, element + 2, x + upper_offset_x, y, upper_length); ui_render_horizontal (cross, ui, element + 3, x + lower_offset_x, y + lower_offset_y, lower_length); ui_render (cross, ui, element + 4, x, y); ui_render (cross, ui, element + 5, x + upper_right_offset_x, y); ui_render (cross, ui, element + 6, x, y + lower_left_offset_y); ui_render (cross, ui, element + 7, x + lower_right_offset_x, y + lower_right_offset_y); } static void ui_render_window (cross_structure * cross, ui_structure * ui, int x, int y, uint width, uint height) { ui_render_grid (cross, ui, ui_window, x, y, width, height, 0, false); } static void ui_render_frame (cross_structure * cross, ui_structure * ui, int x, int y, uint width, uint height) { ui_render_grid (cross, ui, ui_frame, x, y, width, height, 0, false); } static void ui_render_status (cross_structure * cross, ui_structure * ui, int x, int y, uint width, uint height) { ui_render_grid (cross, ui, ui_status, x, y, width, height, 16, true); } static void ui_render_menu (cross_structure * cross, ui_structure * ui, int x, int y, uint width, uint height) { ui_render_grid (cross, ui, ui_menu, x, y, width, height, 24, true); } static void ui_render_button (cross_structure * cross, ui_structure * ui, int x, int y, uint width, uint height) { ui_render_grid (cross, ui, ui_button, x, y, width, height, 16, true); } static void ui_render_separator (cross_structure * cross, ui_structure * ui, int x, int y, uint width) { uint margin = ui->width [ui_separator_left]; uint length = width - margin - ui->width [ui_separator_right]; ui_render (cross, ui, ui_separator_left, x, y); ui_render_horizontal (cross, ui, ui_separator_middle, x + margin, y, length); ui_render (cross, ui, ui_separator_right, x + margin + length, y); ui_render (cross, ui, ui_separator_center, x + (width - ui->width [ui_separator_center]) / 2, y); } static void ui_render_title_bar (cross_structure * cross, ui_structure * ui, char * title, int x, int y, uint width) { uint margin = ui->width [ui_title_bar_left]; uint length = width - margin - ui->width [ui_title_bar_right]; ui_render (cross, ui, ui_title_bar_left, x, y); ui_render_horizontal (cross, ui, ui_title_bar_middle, x + margin, y, length); ui_render (cross, ui, ui_title_bar_right, x + margin + length, y); cross_render_string (cross, title, ui->font, x + margin + 8, y + 8, 1, 0x112233ff); } static void ui_render_icon_and_text (cross_structure * cross, ui_structure * ui, char * title, uint icon, int x, int y) { cross_render_sprite (cross, icon, x, y); cross_render_string (cross, title, ui->font, x - 2 + ui->icon_size, y + 2, 1, 0x112233ffu); } static void ui_render_scroll_bar (cross_structure * cross, ui_structure * ui, float slider, int x, int y, uint height) { uint margin = ui->height [ui_scroll_bar_upper]; uint length = height - margin - ui->height [ui_scroll_bar_lower]; ui_render (cross, ui, ui_scroll_bar_upper, x, y); ui_render_vertical (cross, ui, ui_scroll_bar_middle, x, y + margin, length); ui_render (cross, ui, ui_scroll_bar_lower, x, y + margin + length); ui_render (cross, ui, ui_scroll_bar_slider, x, y + margin + (uint) (slider * (float) (length - ui->height [ui_scroll_bar_slider]))); } static void ui_render_fill_bar (cross_structure * cross, ui_structure * ui, float fill, uint colour, int x, int y, uint width) { uint margin = ui->width [ui_fill_bar_left]; uint length = width - margin - ui->width [ui_fill_bar_right]; ui_render (cross, ui, ui_fill_bar_left, x, y); ui_render_horizontal (cross, ui, ui_fill_bar_middle, x + margin, y, length); ui_render (cross, ui, ui_fill_bar_right, x + margin + length, y); ui_render_horizontal_colour (cross, ui, ui_fill_bar_base, colour, x + margin, y, (uint) (fill * (float) length)); } static void ui_render_icon (cross_structure * cross, ui_structure * ui, uint icon, int x, int y) { cross_render_sprite (cross, ui->sprite [ui_icon_frame], x, y); if (icon != ui->ignore) { cross_render_sprite (cross, icon, x, y); } } static void ui_render_overicon (cross_structure * cross, ui_structure * ui, uint icon, int x, int y) { if (icon != ui->ignore) { cross_render_sprite (cross, icon, x, y); } cross_render_sprite (cross, ui->sprite [ui_overicon_frame], x, y); } static void ui_render_ubericon (cross_structure * cross, ui_structure * ui, uint icon, int x, int y) { cross_render_sprite (cross, ui->sprite [ui_ubericon_frame], x, y); if (icon != ui->ignore) { cross_render_sprite (cross, icon, x + 16, y + 16); } } static void ui_render_menu_full (cross_structure * cross, ui_structure * ui, char * title, int x, int y, uint width, uint height) { uint margin = 24; ui_screen_overlay (cross); ui_render_menu (cross, ui, x, y, width, height); if (title != null) { ui_render_title_bar (cross, ui, format ("<%s>", title), x + margin, y + margin / 2 - ui->title_bar_size, width - 2 * margin); } }