xolatilization/xui.h

521 lines
26 KiB
C
Executable File

/// _
/// __ ___ _(_)
/// \ \/ / | | | |
/// > <| |_| | |
/// /_/\_\\__,_|_|
///
/// 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_left, ui_tiny_fill_bar_middle, ui_tiny_fill_bar_right, ui_tiny_fill_bar_base,
ui_check_box_off, ui_check_box_on,
ui_cursor,
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_enumeration;
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_enumeration;
typedef struct {
natural count;
natural limit;
natural active;
natural ignore;
natural help_box_icon;
character * help_box_none;
character * help_box_text;
character * * folder;
natural * * sprite;
natural * * width;
natural * * height;
natural * font;
natural * monofont;
natural * separator_size;
natural * icon_size;
natural * overicon_size;
natural * ubericon_size;
natural * title_bar_size;
natural * fill_bar_size;
natural * tiny_fill_bar_size;
natural * scroll_bar_size;
} ui_structure;
static character * ui_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",
"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"
};
static ui_structure * ui_initialize (cross_structure * cross, natural limit) {
ui_structure * ui = allocate (sizeof (* ui));
ui->limit = limit;
ui->ignore = ~ 0u;
ui->help_box_none = string_duplicate ("---");
ui->help_box_text = ui->help_box_none;
ui->help_box_icon = ui->ignore;
ui->folder = allocate (limit * sizeof (* ui->folder));
ui->sprite = allocate (limit * sizeof (* ui->sprite));
ui->width = allocate (limit * sizeof (* ui->width));
ui->height = allocate (limit * sizeof (* ui->height));
ui->font = allocate (limit * sizeof (* ui->font));
ui->monofont = allocate (limit * sizeof (* ui->monofont));
ui->separator_size = allocate (limit * sizeof (* ui->separator_size));
ui->icon_size = allocate (limit * sizeof (* ui->icon_size));
ui->overicon_size = allocate (limit * sizeof (* ui->overicon_size));
ui->ubericon_size = allocate (limit * sizeof (* ui->ubericon_size));
ui->title_bar_size = allocate (limit * sizeof (* ui->title_bar_size));
ui->fill_bar_size = allocate (limit * sizeof (* ui->fill_bar_size));
ui->tiny_fill_bar_size = allocate (limit * sizeof (* ui->tiny_fill_bar_size));
ui->scroll_bar_size = allocate (limit * sizeof (* ui->scroll_bar_size));
for (natural index = 0; index < limit; ++index) {
ui->sprite [index] = allocate (ui_subcount * sizeof (* * ui->sprite));
ui->width [index] = allocate (ui_subcount * sizeof (* * ui->width));
ui->height [index] = allocate (ui_subcount * sizeof (* * ui->height));
}
print ("/s Initialized UI structure.\n");
return (ui);
}
static ui_structure * ui_deinitialize (ui_structure * ui) {
for (natural index = 0; index < ui->limit; ++index) {
ui->sprite [index] = deallocate (ui->sprite [index]);
ui->width [index] = deallocate (ui->width [index]);
ui->height [index] = deallocate (ui->height [index]);
if (ui->folder [index] != null) {
ui->folder [index] = deallocate (ui->folder [index]);
}
}
ui->folder = deallocate (ui->folder);
ui->sprite = deallocate (ui->sprite);
ui->width = deallocate (ui->width);
ui->height = deallocate (ui->height);
ui->font = deallocate (ui->font);
ui->monofont = deallocate (ui->monofont);
ui->separator_size = deallocate (ui->separator_size);
ui->icon_size = deallocate (ui->icon_size);
ui->overicon_size = deallocate (ui->overicon_size);
ui->ubericon_size = deallocate (ui->ubericon_size);
ui->title_bar_size = deallocate (ui->title_bar_size);
ui->fill_bar_size = deallocate (ui->fill_bar_size);
ui->tiny_fill_bar_size = deallocate (ui->tiny_fill_bar_size);
ui->scroll_bar_size = deallocate (ui->scroll_bar_size);
ui->help_box_none = deallocate (ui->help_box_none);
print ("/s Deinitialized UI structure.\n");
return (deallocate (ui));
}
static boolean ui_validate_dimensions (ui_structure * ui, ui_subtype_enumeration subtype) {
if (ui->width [ui->active] [subtype] != ui->height [ui->active] [subtype]) {
print ("/w Mismatching sizes for sprite '%s', in UI '%s'.\n", ui_subtype_file_name [subtype], ui->folder [ui->active]);
}
}
static boolean ui_validate_width_dimensions (ui_structure * ui, ui_subtype_enumeration begin, ui_subtype_enumeration end) {
for (ui_subtype_enumeration index = begin; index <= end; ++index) {
if (ui->width [ui->active] [index] != ui->width [ui->active] [begin]) {
print ("/w Mismatching width for sprite '%s', in UI '%s'.\n", ui_subtype_file_name [index], ui->folder [ui->active]);
}
}
}
static boolean ui_validate_height_dimensions (ui_structure * ui, ui_subtype_enumeration begin, ui_subtype_enumeration end) {
for (ui_subtype_enumeration index = begin; index <= end; ++index) {
if (ui->height [ui->active] [index] != ui->height [ui->active] [begin]) {
print ("/w Mismatching height for sprite '%s', in UI '%s'.\n", ui_subtype_file_name [index], ui->folder [ui->active]);
}
}
}
static boolean ui_validate_grid_dimensions (ui_structure * ui, ui_subtype_enumeration begin, ui_subtype_enumeration end) {
for (ui_subtype_enumeration index = begin; index <= end; ++index) {
if ((ui->width [ui->active] [index] != ui->width [ui->active] [begin])
|| (ui->height [ui->active] [index] != ui->height [ui->active] [begin])) {
print ("/w Mismatching grid for sprite '%s', in UI '%s'.\n", ui_subtype_file_name [index], ui->folder [ui->active]);
}
}
}
static procedure ui_configure (cross_structure * cross, ui_structure * ui, character * folder) {
if (ui->count >= ui->limit) {
print ("/w You are trying to configure more UIs than you set the limit to.\n");
return;
}
natural current = ui->active = ++ui->count - 1;
if (cross->very_verbose_spam == true) {
print ("/c Importing UI sprites from '%s' at index %i...\n", folder, current);
}
if (folder != null) {
ui->folder [current] = string_duplicate (folder);
}
ui->font [current] = cross_font_import (cross, (folder == null)
? configuration_format ("xui/regular")
: format ("%s/regular", folder), ' ', '~' + 0, 0);
ui->monofont [current] = cross_font_import (cross, (folder == null)
? configuration_format ("xui/monospace")
: format ("%s/monospace", folder), ' ', '~' + 1, 0);
for (natural index = 0; index < ui_subcount; ++index) {
character * file_name = (folder == null)
? configuration_format (format ("xui/%s", ui_subtype_file_name [index]))
: format ("%s/%s", folder, ui_subtype_file_name [index]);
ui->sprite [current] [index] = cross_sprite_import (cross, file_name);
ui->width [current] [index] = cross_sprite_width (cross, ui->sprite [current] [index]);
ui->height [current] [index] = cross_sprite_height (cross, ui->sprite [current] [index]);
if ((ui->width [current] [index] == 0) || (ui->height [current] [index] == 0)) {
print ("/f UI sprite '%s' has width or height zero.\n", file_name);
exit (log_failure);
}
}
ui_validate_dimensions (ui, ui_cursor);
ui_validate_dimensions (ui, ui_icon_frame);
ui_validate_dimensions (ui, ui_overicon_frame);
ui_validate_dimensions (ui, ui_ubericon_frame);
ui_validate_grid_dimensions (ui, ui_status_left, ui_status_lower_right);
ui_validate_grid_dimensions (ui, ui_menu_left, ui_menu_lower_right);
ui_validate_grid_dimensions (ui, ui_button_left, ui_button_lower_right);
ui_validate_width_dimensions (ui, ui_scroll_bar_lower, ui_scroll_bar_slider);
ui_validate_height_dimensions (ui, ui_fill_bar_left, ui_fill_bar_base);
ui_validate_height_dimensions (ui, ui_tiny_fill_bar_left, ui_tiny_fill_bar_base);
ui_validate_height_dimensions (ui, ui_separator_left, ui_separator_center);
ui_validate_height_dimensions (ui, ui_title_bar_left, ui_title_bar_right);
ui->separator_size [current] = ui->height [current] [ui_separator_middle];
ui->icon_size [current] = ui->height [current] [ui_icon_frame];
ui->overicon_size [current] = ui->height [current] [ui_overicon_frame];
ui->ubericon_size [current] = ui->height [current] [ui_ubericon_frame];
ui->title_bar_size [current] = ui->height [current] [ui_title_bar_middle];
ui->fill_bar_size [current] = ui->height [current] [ui_fill_bar_middle];
ui->tiny_fill_bar_size [current] = ui->height [current] [ui_tiny_fill_bar_middle];
ui->scroll_bar_size [current] = ui->width [current] [ui_scroll_bar_middle];
if (cross->very_verbose_spam == true) {
print ("/c Imported UI sprites from '%s' at index %i.\n", folder, ui->count);
}
}
static procedure ui_render (cross_structure * cross, ui_structure * ui, ui_subtype_enumeration index, integer x, integer y) {
cross_render_sprite (cross, ui->sprite [ui->active] [index], x, y);
}
static procedure ui_render_colour (cross_structure * cross, ui_structure * ui, ui_subtype_enumeration index, natural colour, integer x, integer y) {
cross_render_sprite_colour (cross, ui->sprite [ui->active] [index], colour, x, y);
}
static procedure ui_subrender (cross_structure * cross, ui_structure * ui, ui_subtype_enumeration index, integer x, integer y, natural u, natural v,
natural width, natural height) {
cross_render_sprite_crop (cross, ui->sprite [ui->active] [index], x, y, u, v, width, height);
}
static procedure ui_subrender_colour (cross_structure * cross, ui_structure * ui, ui_subtype_enumeration index, natural colour, integer x, integer y,
natural u, natural v, natural width, natural height) {
cross_render_sprite_crop_colour (cross, ui->sprite [ui->active] [index], colour, x, y, u, v, width, height);
}
static procedure ui_render_horizontal (cross_structure * cross, ui_structure * ui, ui_subtype_enumeration index, integer x, integer y, natural width) {
integer entire = (width / ui->width [ui->active] [index]) * ui->width [ui->active] [index];
for (natural margin = 0; margin < width / ui->width [ui->active] [index]; ++margin) {
ui_render (cross, ui, index, x + margin * ui->width [ui->active] [index], y);
}
if (width % ui->width [ui->active] [index] > 0) {
ui_subrender (cross, ui, index, x + entire, y, 0, 0, width % ui->width [ui->active] [index], ui->height [ui->active] [index]);
}
}
static procedure ui_render_horizontal_colour (cross_structure * cross, ui_structure * ui, ui_subtype_enumeration index, natural colour,
integer x, integer y, natural width) {
//~natural width_divisor = width / ui->width [ui->active] [index];
//~natural width_remainder = width % ui->width [ui->active] [index];
//~for (natural offset = 0; offset < width_divisor; ++offset) {
//~ui_render_colour (cross, ui, index, colour, x + offset * ui->width [ui->active] [index], y);
//~}
//~if (width_remainder > 0) {
//~ui_subrender_colour (cross, ui, index, colour, x + width - width_remainder, y, 0, 0, width_remainder, ui->height [ui->active] [index]);
//~}
integer entire = (width / ui->width [ui->active] [index]) * ui->width [ui->active] [index];
for (natural margin = 0; margin < width / ui->width [ui->active] [index]; ++margin) {
ui_render (cross, ui, index, x + margin * ui->width [ui->active] [index], y);
}
if (width % ui->width [ui->active] [index] > 0) {
ui_subrender (cross, ui, index, x + entire, y, 0, 0, width % ui->width [ui->active] [index], ui->height [ui->active] [index]);
}
}
static procedure ui_render_vertical (cross_structure * cross, ui_structure * ui, ui_subtype_enumeration index, integer x, integer y, natural height) {
integer entire = (height / ui->height [ui->active] [index]) * ui->height [ui->active] [index];
for (natural margin = 0; margin < height / ui->height [ui->active] [index]; ++margin) {
ui_render (cross, ui, index, x, y + margin * ui->height [ui->active] [index]);
}
if (height % ui->height [ui->active] [index] > 0) {
ui_subrender (cross, ui, index, x, y + entire, 0, 0, ui->width [ui->active] [index], height % ui->height [ui->active] [index]);
}
}
static procedure ui_render_background (cross_structure * cross, ui_structure * ui, ui_subtype_enumeration index, integer x, integer y, natural width, natural height) {
natural offset_x = (width / ui->width [ui->active] [index]) * ui->width [ui->active] [index];
natural offset_y = (height / ui->height [ui->active] [index]) * ui->height [ui->active] [index];
natural cutoff_x = width % ui->width [ui->active] [index];
natural cutoff_y = height % ui->height [ui->active] [index];
for (natural vertical = 0; vertical < height / ui->height [ui->active] [index]; ++vertical) {
for (natural horizontal = 0; horizontal < width / ui->width [ui->active] [index]; ++horizontal) {
ui_render (cross, ui, index, x + horizontal * ui->width [ui->active] [index], y + vertical * ui->height [ui->active] [index]);
}
if (width % ui->width [ui->active] [index] > 0) {
ui_subrender (cross, ui, index, x + offset_x, y + vertical * ui->height [ui->active] [index], 0, 0, cutoff_x, ui->height [ui->active] [index]);
}
}
for (natural horizontal = 0; horizontal < width / ui->width [ui->active] [index]; ++horizontal) {
ui_subrender (cross, ui, index, x + horizontal * ui->width [ui->active] [index], y + offset_y, 0, 0, ui->width [ui->active] [index], cutoff_y);
}
if (width % ui->width [ui->active] [index] > 0) {
ui_subrender (cross, ui, index, x + offset_x, y + offset_y, 0, 0, cutoff_x, cutoff_y);
}
}
static procedure ui_screen_overlay (cross_structure * cross, natural colour) {
cross_render_rectangle (cross, 0, 0, cross->window_width, cross->window_height, colour);
}
static procedure ui_render_grid (cross_structure * cross, ui_structure * ui, ui_type_enumeration element, integer x, integer y, natural width,
natural height, boolean background) {
if ((width < ui->width [ui->active] [element + 4] + ui->width [ui->active] [element + 5] + ui->width [ui->active] [element + 2]) ||
(height < ui->height [ui->active] [element + 4] + ui->height [ui->active] [element + 6] + ui->height [ui->active] [element + 0])) {
return;
}
natural upper_length = width - ui->width [ui->active] [element + 4] - ui->width [ui->active] [element + 5];
natural lower_length = width - ui->width [ui->active] [element + 6] - ui->width [ui->active] [element + 7];
natural left_length = height - ui->height [ui->active] [element + 4] - ui->height [ui->active] [element + 6];
natural right_length = height - ui->height [ui->active] [element + 5] - ui->height [ui->active] [element + 7];
integer upper_offset_x = ui->width [ui->active] [element + 4];
integer lower_offset_x = ui->width [ui->active] [element + 6];
integer lower_offset_y = height - ui->height [ui->active] [element + 3];
integer right_offset_x = width - ui->width [ui->active] [element + 1];
integer left_offset_y = ui->height [ui->active] [element + 4];
integer right_offset_y = ui->height [ui->active] [element + 5];
integer upper_right_offset_x = width - ui->width [ui->active] [element + 5];
integer lower_right_offset_x = width - ui->width [ui->active] [element + 7];
integer lower_left_offset_y = height - ui->height [ui->active] [element + 6];
integer lower_right_offset_y = height - ui->height [ui->active] [element + 7];
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);
if (background == true) {
ui_render_background (cross, ui, element + 8, x + upper_offset_x, y + left_offset_y, upper_length, left_length);
}
}
static procedure ui_render_window (cross_structure * cross, ui_structure * ui, integer x, integer y, natural width, natural height) {
ui_render_grid (cross, ui, ui_window, x, y, width, height, false);
}
static procedure ui_render_frame (cross_structure * cross, ui_structure * ui, integer x, integer y, natural width, natural height) {
ui_render_grid (cross, ui, ui_frame, x, y, width, height, false);
}
static procedure ui_render_status (cross_structure * cross, ui_structure * ui, integer x, integer y, natural width, natural height) {
ui_render_grid (cross, ui, ui_status, x, y, width, height, true);
}
static procedure ui_render_menu (cross_structure * cross, ui_structure * ui, integer x, integer y, natural width, natural height) {
ui_render_grid (cross, ui, ui_menu, x, y, width, height, true);
}
static procedure ui_render_button (cross_structure * cross, ui_structure * ui, integer x, integer y, natural width, natural height) {
ui_render_grid (cross, ui, ui_button, x, y, width, height, true);
}
static procedure ui_render_separator (cross_structure * cross, ui_structure * ui, integer x, integer y, natural width) {
natural margin = ui->width [ui->active] [ui_separator_left];
natural length = width - margin - ui->width [ui->active] [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->active] [ui_separator_center]) / 2, y);
}
static procedure ui_render_title_bar (cross_structure * cross, ui_structure * ui, character * title, integer x, integer y, natural width) {
natural margin = ui->width [ui->active] [ui_title_bar_left];
natural length = width - margin - ui->width [ui->active] [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 [ui->active], x + margin + 8, y + 8, 1, 0x112233ff);
}
static procedure ui_render_icon_and_text (cross_structure * cross, ui_structure * ui, character * title, natural icon, integer x, integer y,
natural colour) {
cross_render_sprite (cross, icon, x, y);
//////////////////////////////////////////
cross_render_string (cross, title, ui->font [ui->active], x - 2 + ui->icon_size [ui->active], y + 2, 1.0f, colour);
}
static procedure ui_render_scroll_bar (cross_structure * cross, ui_structure * ui, real slider, integer x, integer y, natural height) {
natural margin = ui->height [ui->active] [ui_scroll_bar_upper];
natural length = height - margin - ui->height [ui->active] [ui_scroll_bar_lower];
real slider_offset = slider * (real) (length - ui->height [ui->active] [ui_scroll_bar_slider]);
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 + (natural) slider_offset);
}
static procedure ui_render_fill_bar (cross_structure * cross, ui_structure * ui, real fill, natural colour, integer x, integer y, natural width) {
natural margin = ui->width [ui->active] [ui_fill_bar_left];
natural length = width - margin - ui->width [ui->active] [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, (natural) (fill * (real) length));
}
static procedure ui_render_icon (cross_structure * cross, ui_structure * ui, natural icon, integer x, integer y) {
cross_render_sprite (cross, ui->sprite [ui->active] [ui_icon_frame], x, y);
if (icon != ui->ignore) {
cross_render_sprite (cross, icon, x, y);
}
}
static procedure ui_render_overicon (cross_structure * cross, ui_structure * ui, natural icon, integer x, integer y) {
if (icon != ui->ignore) {
cross_render_sprite (cross, icon, x, y);
}
cross_render_sprite (cross, ui->sprite [ui->active] [ui_overicon_frame], x, y);
}
static procedure ui_render_ubericon (cross_structure * cross, ui_structure * ui, natural icon, integer x, integer y, natural offset) {
cross_render_sprite (cross, ui->sprite [ui->active] [ui_ubericon_frame], x, y);
if (icon != ui->ignore) {
cross_render_sprite (cross, icon, x + offset, y + offset);
}
}
static procedure ui_render_menu_full (cross_structure * cross, ui_structure * ui, character * title, integer x, integer y, natural width,
natural height, natural overlay_colour, natural margin) {
if (overlay_colour != 0x00000000u) {
ui_screen_overlay (cross, overlay_colour);
}
ui_render_menu (cross, ui, x, y, width, height);
if (title != null) {
ui_render_title_bar (cross, ui, title, x + margin, y + margin / 2 - ui->title_bar_size [ui->active], width - 2 * margin);
}
}