mirror of
https://github.com/nzp-team/quakec.git
synced 2025-01-19 07:40:51 +00:00
MENU: WIP
This commit is contained in:
parent
a9d4c96430
commit
43bd3dfca3
13 changed files with 3599 additions and 0 deletions
25
progs/menu.src
Normal file
25
progs/menu.src
Normal file
|
@ -0,0 +1,25 @@
|
|||
../source/menu/main.qc
|
||||
|
||||
#pragma noref 1
|
||||
#pragma target fte_5768
|
||||
#pragma progs_dat "../build/fte/menu.dat"
|
||||
|
||||
#pragma includedir "../source/menu/"
|
||||
|
||||
#includelist
|
||||
defs/fte.qc
|
||||
defs/custom.qc
|
||||
../client/draw.qc
|
||||
sui_sys.qc
|
||||
m_menu.qc
|
||||
|
||||
menu_main.qc // Main Menu
|
||||
menu_maps.qc // Maps Menu
|
||||
menu_opts.qc // Options Menu
|
||||
menu_vide.qc // Video Menu
|
||||
menu_audi.qc // Audio Menu
|
||||
menu_ctrl.qc // Control Menu
|
||||
menu_gpad.qc // Gamepad Menu
|
||||
|
||||
main.qc
|
||||
#endlist
|
86
source/menu/defs/custom.qc
Normal file
86
source/menu/defs/custom.qc
Normal file
|
@ -0,0 +1,86 @@
|
|||
#define true 1
|
||||
#define false 0
|
||||
|
||||
string build_datetime;
|
||||
float music_duration_time;
|
||||
|
||||
string menu_background;
|
||||
float menu_changetime;
|
||||
|
||||
|
||||
float current_menu;
|
||||
float running_platform;
|
||||
|
||||
enum {
|
||||
PLATFORM_WIN,
|
||||
PLATFORM_MAC,
|
||||
PLATFORM_LIN,
|
||||
PLATFORM_XBX,
|
||||
PLATFORM_AND,
|
||||
PLATFORM_WEB,
|
||||
PLATFORM_BSD,
|
||||
PLATFORM_IOS,
|
||||
PLATFORM_DOS,
|
||||
PLATFORM_UNK
|
||||
};
|
||||
|
||||
enum {
|
||||
MENU_NONE,
|
||||
MENU_MAIN,
|
||||
MENU_SOLO,
|
||||
MENU_SOLOUSER,
|
||||
MENU_OPTIONS,
|
||||
MENU_VIDEO,
|
||||
MENU_AUDIO,
|
||||
MENU_CONTROL,
|
||||
MENU_GAMEPAD,
|
||||
MENU_HELP
|
||||
};
|
||||
|
||||
#define MENU_SND_NAVIGATE 0
|
||||
#define MENU_SND_ENTER 1
|
||||
void(float type) Menu_PlaySound;
|
||||
|
||||
void() Menu_Main;
|
||||
void() Menu_Maps;
|
||||
void() Menu_Options;
|
||||
void() Menu_Video;
|
||||
void() Menu_Audio;
|
||||
void() Menu_Control;
|
||||
void() Menu_Gamepad;
|
||||
|
||||
enum {
|
||||
MAP_SOLOSTOCK,
|
||||
MAP_SOLOUSER,
|
||||
MAP_COOPSTOCK,
|
||||
MAP_COOPUSER
|
||||
};
|
||||
float menu_map_mode;
|
||||
|
||||
// Map content data structure
|
||||
var struct
|
||||
{
|
||||
float occupied;
|
||||
float map_allow_game_settings;
|
||||
float map_use_thumbnail;
|
||||
string map_name;
|
||||
string map_name_pretty;
|
||||
string map_desc[8];
|
||||
string map_author;
|
||||
} user_maps[500];
|
||||
float user_maps_count;
|
||||
float user_maps_page;
|
||||
|
||||
// Built-in (stock) maps, array_index
|
||||
// is populated later.
|
||||
var struct
|
||||
{
|
||||
string bsp_name;
|
||||
float array_index;
|
||||
} stock_maps[] =
|
||||
{
|
||||
{"ndu", 0},
|
||||
{"nzp_warehouse", 0},
|
||||
{"nzp_warehouse2", 0},
|
||||
{"christmas_special", 0}
|
||||
};
|
1051
source/menu/defs/fte.qc
Normal file
1051
source/menu/defs/fte.qc
Normal file
File diff suppressed because it is too large
Load diff
566
source/menu/m_menu.qc
Normal file
566
source/menu/m_menu.qc
Normal file
|
@ -0,0 +1,566 @@
|
|||
vector MENU_BG = '0.2 0.3 0.4';
|
||||
vector MENU_BG_DARK = '0.1 0.15 0.2';
|
||||
vector MENU_BORDER = '0.3 0.4 0.5';
|
||||
vector MENU_BUTTON = '0.3 0.4 0.5';
|
||||
vector MENU_BUTTON_BORDER = '0.35 0.45 0.55';
|
||||
vector MENU_TEXT_1 = '1 1 1';
|
||||
vector MENU_TEXT_2 = '0.7 0.75 0.75';
|
||||
vector MENU_HIGHLIGHT = '1 1 1';
|
||||
vector MENU_DARKEN = '1 1 1';
|
||||
|
||||
vector MENU_TEXT_SUPERSMALL = '10 10 0';
|
||||
vector MENU_TEXT_SMALL = '12 12 0';
|
||||
vector MENU_TEXT_MEDIUM = '14 14 0';
|
||||
vector MENU_TEXT_LARGE = '28 28 0';
|
||||
|
||||
void() input_tester =
|
||||
{
|
||||
float char = 0;
|
||||
float scan = 0;
|
||||
string printme = "";
|
||||
while (sui_get_input(char, scan))
|
||||
{
|
||||
printme = strcat(printme, chr2str(char));
|
||||
}
|
||||
if (printme != "") printf("INPUT: %s\n", printme);
|
||||
};
|
||||
|
||||
void(string id, vector pos, vector size, float maxlen, __inout string text, __inout float cursor) text_input_control =
|
||||
{
|
||||
vector textsize = [size_y - 4, size_y - 4];
|
||||
sui_push_frame(pos, size);
|
||||
vector basecolor = sui_is_hovered(id) ? MENU_BG_DARK + MENU_HIGHLIGHT * 0.08 : MENU_BG_DARK;
|
||||
sui_fill([0, 0], size, basecolor, 0.6, 0);
|
||||
|
||||
sui_text_input(id, [0, 0], size, text, cursor);
|
||||
|
||||
sui_set_align([SUI_ALIGN_START, SUI_ALIGN_CENTER]);
|
||||
float focused = sui_is_last_clicked(id);
|
||||
// Under focus
|
||||
focused ? sui_border_box([0, 0], size, 1, MENU_BORDER, 0.6, 0) : 0;
|
||||
|
||||
sui_push_frame([2, 0], [size_x - 4, size_y - 4]);
|
||||
|
||||
float cursorx;
|
||||
if (stringwidth(text, 1, textsize) > size_x - 4)
|
||||
{
|
||||
sui_clip_to_frame();
|
||||
cursorx = 0;
|
||||
sui_set_align([SUI_ALIGN_END, SUI_ALIGN_CENTER]);
|
||||
sui_text([0, 0], textsize, text, MENU_TEXT_1, 1, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
cursorx = stringwidth(substring(text, 0, cursor), 1, textsize);
|
||||
sui_text([0, 0], textsize, text, MENU_TEXT_1, 1, 0);
|
||||
}
|
||||
if (focused)
|
||||
{
|
||||
sui_fill([cursorx, 0], [2, textsize_y], MENU_TEXT_1, fabs(sin(time * 4)), 0);
|
||||
}
|
||||
sui_reset_clip();
|
||||
sui_pop_frame();
|
||||
|
||||
sui_pop_frame();
|
||||
};
|
||||
|
||||
//
|
||||
// Menu_DrawDivider(order)
|
||||
// Draws a division line between menu
|
||||
// entries.
|
||||
//
|
||||
void(float order) Menu_DrawDivider =
|
||||
{
|
||||
sui_set_align([SUI_ALIGN_START, SUI_ALIGN_START]);
|
||||
|
||||
vector position = [0, 45 + (order * 25)];
|
||||
sui_fill(position, [285, 2], [0.2, 0.2, 0.2], 1, 0);
|
||||
};
|
||||
|
||||
//
|
||||
// Menu_SocialBadge(order, id, text, index)
|
||||
// Displays a social badge with a URL
|
||||
// when hovered over with the mouse.
|
||||
//
|
||||
void(float order, string id, string text, float index) Menu_SocialBadge =
|
||||
{
|
||||
sui_set_align([SUI_ALIGN_END, SUI_ALIGN_END]);
|
||||
|
||||
vector position = [-6, -62 - ((order - 1) * 30)];
|
||||
vector coords_size = [0.5, 0.5];
|
||||
vector coords_pos = [0, 0];
|
||||
|
||||
switch(index) {
|
||||
case 1: coords_pos = [0, 0]; break;
|
||||
case 2: coords_pos = [0.5, 0]; break;
|
||||
case 3: coords_pos = [0, 0.5]; break;
|
||||
case 4: coords_pos = [0.5, 0.5]; break;
|
||||
}
|
||||
|
||||
sui_subpic(position, [28, 28], "gfx/menu/social", [1, 1, 1], coords_pos, coords_size, 1, 0);
|
||||
|
||||
if (sui_is_hovered(id)) {
|
||||
sui_fill(position - [36, 8], [getTextWidth(text, MENU_TEXT_SUPERSMALL_x) + 1, 10], [0, 0, 0], 0.9, 0);
|
||||
sui_text(position - [35, 8], MENU_TEXT_SUPERSMALL, text, [1, 1, 0], 1, 0);
|
||||
}
|
||||
|
||||
sui_action_element(position, [28, 28], id, sui_noop);
|
||||
};
|
||||
|
||||
//
|
||||
// Menu_DrawMapPanel()
|
||||
// Draws a translucent box on the right
|
||||
// side of the window to make map text easier
|
||||
// to read.
|
||||
//
|
||||
void() Menu_DrawMapPanel =
|
||||
{
|
||||
sui_set_align([SUI_ALIGN_START, SUI_ALIGN_START]);
|
||||
sui_fill([300, 55], [sui_current_frame_size()[0], sui_current_frame_size()[1] - 55 - 58], [0, 0, 0], 0.9, 0);
|
||||
sui_fill([300, 55], [3, sui_current_frame_size()[1] - 55 - 58], [1, 1, 0], 0.9, 0);
|
||||
};
|
||||
|
||||
//
|
||||
// Menu_DrawOptionValue(order, value)
|
||||
// Draws the value of the option at a given order.
|
||||
//
|
||||
void(float order, string value) Menu_DrawOptionValue =
|
||||
{
|
||||
sui_set_align([SUI_ALIGN_START, SUI_ALIGN_START]);
|
||||
|
||||
vector position = [320, 50 + (order * 25)];
|
||||
sui_text(position, MENU_TEXT_MEDIUM, value, [1, 1, 1], 1, 0);
|
||||
};
|
||||
|
||||
//
|
||||
// Menu_MapButton(order, id, bsp_name)
|
||||
// Displays a fancy menu option that loads
|
||||
// and draws the details for the given
|
||||
// .BSP.
|
||||
//
|
||||
float(float order, string id, string bsp_name, float usermap_index) Menu_MapButton =
|
||||
{
|
||||
sui_set_align([SUI_ALIGN_START, SUI_ALIGN_START]);
|
||||
|
||||
float is_hovered = sui_is_hovered(id);
|
||||
vector text_color = is_hovered ? [1, 0, 0] : [1, 1, 1];
|
||||
vector position = [6, 50 + (order * 25)];
|
||||
vector bbox_pos = position - [6, 5, 0];
|
||||
vector bbox_size = [290, 22];
|
||||
|
||||
if (is_hovered) {
|
||||
// Background
|
||||
sui_fill(bbox_pos, bbox_size, [0, 0, 0], 0.9, 0);
|
||||
// Top
|
||||
sui_fill(bbox_pos, [bbox_size_x, 2], [0.4, 0, 0], 1, 0);
|
||||
// Bottom
|
||||
sui_fill(bbox_pos + [0, bbox_size_y - 2], [bbox_size_x, 2], [0.4, 0, 0], 1, 0);
|
||||
// Right
|
||||
sui_fill(bbox_pos + [bbox_size_x - 2, 0], [2, bbox_size_y], [0.4, 0, 0], 1, 0);
|
||||
}
|
||||
|
||||
int i;
|
||||
int index = 0;
|
||||
|
||||
// Draw the map data from stock_maps
|
||||
if (usermap_index == -1) {
|
||||
for(i = 0; i < stock_maps.length; i++) {
|
||||
if (stock_maps[i].bsp_name == bsp_name) {
|
||||
index = stock_maps[i].array_index;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
index = usermap_index;
|
||||
}
|
||||
|
||||
// Map title
|
||||
string title = user_maps[index].map_name_pretty;
|
||||
if (!title)
|
||||
title = user_maps[index].map_name;
|
||||
sui_text(position - [getTextWidth(strtoupper(title), MENU_TEXT_MEDIUM_x), 0, 0] + [275, 0, 0], MENU_TEXT_MEDIUM, strtoupper(title), text_color, 1, 0);
|
||||
|
||||
if (is_hovered) {
|
||||
sui_set_align([SUI_ALIGN_CENTER, SUI_ALIGN_CENTER]);
|
||||
|
||||
// Map thumbnail
|
||||
if (user_maps[index].map_use_thumbnail) {
|
||||
sui_fill([150, -70], [302, 174], [0.4, 0.4, 0.4], 1, 0);
|
||||
sui_pic([150, -70], [300, 170], strcat("menu/custom/", user_maps[index].map_name, ".png"), [1, 1, 1], 1, 0);
|
||||
}
|
||||
|
||||
// Map description
|
||||
for(i = 0; i < 8; i++) {
|
||||
sui_text([150, 30 + (i * 14)], MENU_TEXT_SMALL, user_maps[index].map_desc[i], [1, 1, 1], 1, 0);
|
||||
}
|
||||
|
||||
// Author/Description
|
||||
if (user_maps[index].map_author) {
|
||||
sui_set_align([SUI_ALIGN_CENTER, SUI_ALIGN_END]);
|
||||
string author = user_maps[index].map_author;
|
||||
|
||||
sui_text([0, -30], MENU_TEXT_MEDIUM, title, [1, 1, 1], 1, 0);
|
||||
sui_text([0, -15], MENU_TEXT_MEDIUM, author, [1, 1, 0], 1, 0);
|
||||
}
|
||||
|
||||
sui_set_align([SUI_ALIGN_START, SUI_ALIGN_START]);
|
||||
}
|
||||
|
||||
sui_action_element(bbox_pos, bbox_size, id, sui_noop);
|
||||
|
||||
return sui_is_clicked(id);
|
||||
}
|
||||
|
||||
//
|
||||
// Menu_GreyButton(order, title)
|
||||
// Draws Grey (unselect-able text) in place of
|
||||
// menu button.
|
||||
//
|
||||
void(float order, string title) Menu_GreyButton =
|
||||
{
|
||||
vector alignment;
|
||||
|
||||
if (order > 0) alignment = [SUI_ALIGN_START, SUI_ALIGN_START];
|
||||
else alignment = [SUI_ALIGN_START, SUI_ALIGN_END];
|
||||
|
||||
sui_set_align(alignment);
|
||||
|
||||
vector text_color = [0.5, 0.3, 0.3]; // make it kinda red, for flavor.
|
||||
vector position;
|
||||
|
||||
if (order > 0) {
|
||||
position = [6, 50 + (order * 25)];
|
||||
} else {
|
||||
position = [6, -50 + (order * 25)];
|
||||
}
|
||||
|
||||
sui_text(position - [getTextWidth(title, MENU_TEXT_MEDIUM_x), 0, 0] + [275, 0, 0], MENU_TEXT_MEDIUM, title, text_color, 1, 0);
|
||||
};
|
||||
|
||||
//
|
||||
// Menu_Button(order, id, title, description)
|
||||
// Displays a menu option and draws the description
|
||||
// plus flair if selected.
|
||||
//
|
||||
float(float order, string id, string title, string description) Menu_Button =
|
||||
{
|
||||
vector alignment;
|
||||
|
||||
if (order > 0) alignment = [SUI_ALIGN_START, SUI_ALIGN_START];
|
||||
else alignment = [SUI_ALIGN_START, SUI_ALIGN_END];
|
||||
|
||||
sui_set_align(alignment);
|
||||
|
||||
float is_hovered = sui_is_hovered(id);
|
||||
vector text_color = is_hovered ? [1, 0, 0] : [1, 1, 1];
|
||||
vector position, bbox_pos;
|
||||
|
||||
if (order > 0) {
|
||||
position = [6, 50 + (order * 25)];
|
||||
bbox_pos = position - [6, 5, 0];
|
||||
} else {
|
||||
position = [6, -50 + (order * 25)];
|
||||
bbox_pos = position + [-6, 5, 0];
|
||||
}
|
||||
|
||||
vector bbox_size = [290, 22];
|
||||
|
||||
if (is_hovered) {
|
||||
// Description
|
||||
sui_set_align([SUI_ALIGN_CENTER, SUI_ALIGN_END]);
|
||||
sui_text([0, -30], MENU_TEXT_MEDIUM, description, [1, 1, 1], 1, 0);
|
||||
sui_set_align(alignment);
|
||||
|
||||
// Background
|
||||
sui_fill(bbox_pos, bbox_size, [0, 0, 0], 0.9, 0);
|
||||
|
||||
if (order > 0) {
|
||||
// Top
|
||||
sui_fill(bbox_pos, [bbox_size_x, 2], [0.4, 0, 0], 1, 0);
|
||||
// Bottom
|
||||
sui_fill(bbox_pos + [0, bbox_size_y - 2], [bbox_size_x, 2], [0.4, 0, 0], 1, 0);
|
||||
} else {
|
||||
// Top
|
||||
sui_fill(bbox_pos - [0, bbox_size_y], [bbox_size_x, 2], [0.4, 0, 0], 1, 0);
|
||||
// Bottom
|
||||
sui_fill(bbox_pos, [bbox_size_x, 2], [0.4, 0, 0], 1, 0);
|
||||
}
|
||||
|
||||
// Right
|
||||
sui_fill(bbox_pos + [bbox_size_x - 2, 0], [2, bbox_size_y], [0.4, 0, 0], 1, 0);
|
||||
}
|
||||
|
||||
sui_text(position - [getTextWidth(title, MENU_TEXT_MEDIUM_x), 0, 0] + [275, 0, 0], MENU_TEXT_MEDIUM, title, text_color, 1, 0);
|
||||
sui_action_element(bbox_pos, bbox_size, id, sui_noop);
|
||||
|
||||
return sui_is_clicked(id);
|
||||
};
|
||||
|
||||
float(string id, vector pos, vector size, string text) my_button =
|
||||
{
|
||||
sui_push_frame(pos, size);
|
||||
vector basecolor = sui_is_hovered(id) ? MENU_BUTTON + MENU_HIGHLIGHT * 0.1 : MENU_BUTTON;
|
||||
basecolor = sui_is_held(id) ? MENU_BUTTON - MENU_DARKEN * 0.1 : basecolor;
|
||||
sui_fill([0, 0], size, basecolor, 0.6, 0);
|
||||
sui_border_box([0, 0], size, 1, MENU_BUTTON_BORDER, 0.4, 0);
|
||||
|
||||
sui_set_align([SUI_ALIGN_CENTER, SUI_ALIGN_CENTER]);
|
||||
sui_text([0, 0], MENU_TEXT_SMALL, text, MENU_TEXT_1, 1, 0);
|
||||
sui_action_element([0, 0], size, id, sui_noop);
|
||||
sui_pop_frame();
|
||||
|
||||
return sui_is_clicked(id);
|
||||
};
|
||||
|
||||
//
|
||||
// Menu_DrawBuildDate()
|
||||
// Wrapper for drawing the build date
|
||||
// retrieved from nzp/version.txt
|
||||
//
|
||||
void() Menu_DrawBuildDate =
|
||||
{
|
||||
sui_set_align([SUI_ALIGN_END, SUI_ALIGN_START]);
|
||||
sui_text([-6, 8], MENU_TEXT_SMALL, build_datetime, [1, 1, 1], 1, 0);
|
||||
sui_text([-6, 22], MENU_TEXT_SMALL, sprintf("Welcome, %s", cvar_string("name")), [1, 1, 0], 1, 0);
|
||||
};
|
||||
|
||||
//
|
||||
// Menu_DrawBackground()
|
||||
// Wrapper for drawing menu background,
|
||||
// i.e., the Zombie pose with a black
|
||||
// background for readibility, and some
|
||||
// style lines.
|
||||
//
|
||||
string() Menu_PickBackground;
|
||||
void() Menu_DrawBackground =
|
||||
{
|
||||
sui_set_align([SUI_ALIGN_START, SUI_ALIGN_START]);
|
||||
sui_pic([0, 0], sui_current_frame_size(), menu_background, [1, 1, 1], 1, 1);
|
||||
sui_fill([0, 0], sui_current_frame_size(), [0, 0, 0], 0.7, 0);
|
||||
|
||||
// Top Bars
|
||||
sui_fill([0, 0], [sui_current_frame_size()[0], 55], [0, 0, 0], 0.9, 0);
|
||||
sui_fill([0, 52], [sui_current_frame_size()[0], 3], [0.2, 0.2, 0.2], 1, 0);
|
||||
|
||||
// Bottom Bars
|
||||
sui_fill([0, sui_current_frame_size()[1] - 55], [sui_current_frame_size()[0], 55], [0, 0, 0], 0.9, 0);
|
||||
sui_fill([0, sui_current_frame_size()[1] - 58], [sui_current_frame_size()[0], 3], [0.2, 0.2, 0.2], 1, 0);
|
||||
};
|
||||
|
||||
//
|
||||
// Menu_DrawTitle(menu_title)
|
||||
// Wrapper for drawing the current Menu title
|
||||
// in the desired location + at the desired size.
|
||||
//
|
||||
void(string menu_title) Menu_DrawTitle =
|
||||
{
|
||||
sui_set_align([SUI_ALIGN_START, SUI_ALIGN_START]);
|
||||
sui_text([6, 18], MENU_TEXT_LARGE, menu_title, [1, 1, 1], 1, 0);
|
||||
};
|
||||
|
||||
void(string id, vector pos, vector size, vector minmaxsteps, __inout float value) my_slider =
|
||||
{
|
||||
sui_push_frame(pos, size);
|
||||
|
||||
value = sui_slidercontrol(id, [0, 0], size, minmaxsteps, value, sui_slider_noop);
|
||||
float maxval = minmaxsteps[1];
|
||||
float sliderx = (value / maxval) * size_x;
|
||||
sui_fill([0, size_y * 0.25], [size_x, size_y * 0.5], [0.5, 0.1, 0.1], 1.0, 0);
|
||||
sui_fill([sliderx - 2, 0], [4, size_y], [0.6, 0.4, 0.4], 1.0, 0);
|
||||
|
||||
sui_pop_frame();
|
||||
};
|
||||
|
||||
void(vector pos, vector size, vector minmaxsteps, string cvar_s, string name, string format) cvar_slider =
|
||||
{
|
||||
float current = cvar(cvar_s);
|
||||
float old = current;
|
||||
sui_push_frame(pos, [size_x, size_y * 0.5 - 4]);
|
||||
sui_text([0, 0], MENU_TEXT_SMALL, name, MENU_TEXT_1, 1, 0);
|
||||
sui_set_align([SUI_ALIGN_END, SUI_ALIGN_START]);
|
||||
sui_text([0, 0], MENU_TEXT_SMALL, sprintf(format, current), MENU_TEXT_1, 1, 0);
|
||||
sui_pop_frame();
|
||||
my_slider(strcat(cvar_s, "sldr"), [pos_x, pos_y + size_y * 0.5], [size_x, size_y * 0.5], minmaxsteps, current);
|
||||
if (current != old) cvar_set(cvar_s, ftos(current));
|
||||
};
|
||||
|
||||
//
|
||||
// Menu_CvarSlider(order, minmaxsteps, cvar_s, is_int, no_text)
|
||||
// Draws a Slider at the given order position
|
||||
// that controls a cvar.
|
||||
//
|
||||
void(float order, vector minmaxsteps, string cvar_s, float is_int, float no_text) Menu_CvarSlider =
|
||||
{
|
||||
float current = cvar(cvar_s);
|
||||
float old = current;
|
||||
|
||||
vector position = [320, 50 + (order * 25)];
|
||||
vector size = [150, 30];
|
||||
|
||||
my_slider(strcat(cvar_s, "sldr"), [position_x, (position_y - 17) + size_y * 0.5], [size_x, size_y * 0.5], minmaxsteps, current);
|
||||
|
||||
if (current != old) {
|
||||
if (is_int)
|
||||
cvar_set(cvar_s, ftos(rint(current)));
|
||||
else
|
||||
cvar_set(cvar_s, ftos(current));
|
||||
}
|
||||
|
||||
if (!no_text) {
|
||||
if (is_int)
|
||||
sui_text(position + [175, 0, 0], MENU_TEXT_MEDIUM, ftos(rint(current)), [1, 1, 1], 1, 0);
|
||||
else
|
||||
sui_text(position + [175, 0, 0], MENU_TEXT_MEDIUM, ftos(current), [1, 1, 1], 1, 0);
|
||||
}
|
||||
};
|
||||
|
||||
struct name_command {
|
||||
string name;
|
||||
string command;
|
||||
};
|
||||
|
||||
name_command bindlist[] =
|
||||
{
|
||||
{ "Forward", "+forward" },
|
||||
{ "Back", "+back" },
|
||||
{ "Left", "+moveleft" },
|
||||
{ "Right", "+moveright" },
|
||||
{ "Jump", "+jump" }
|
||||
};
|
||||
|
||||
void(string id, vector pos, vector size, string name, string command) bind_button =
|
||||
{
|
||||
sui_push_frame(pos, size);
|
||||
sui_set_align([SUI_ALIGN_START, SUI_ALIGN_CENTER]);
|
||||
string key = sui_binder(id, [0, 0], size, name, command);
|
||||
if (sui_is_hovered(id)) sui_fill([0, 0], size, MENU_HIGHLIGHT, 0.1, 0);
|
||||
sui_text([6, 0], MENU_TEXT_SMALL, name, MENU_TEXT_1, 1, 0);
|
||||
sui_set_align([SUI_ALIGN_END, SUI_ALIGN_CENTER]);
|
||||
sui_text([-6, 0], MENU_TEXT_SMALL, key, MENU_TEXT_1, 1, 0);
|
||||
|
||||
sui_pop_frame();
|
||||
};
|
||||
|
||||
|
||||
void(string id, vector pos, vector size, __inout vector scrollofs) bind_list =
|
||||
{
|
||||
sui_fill(pos, size, MENU_BG_DARK, 0.75, 0);
|
||||
sui_list_view_begin(strcat(id, "scrl"), pos, size, [size_x - 6, 24], bindlist.length, scrollofs, [0, 6]);
|
||||
vector listitem_pos = '0 0 0';
|
||||
for (float index = sui_list_item(listitem_pos); index > -1; index = sui_list_item(listitem_pos))
|
||||
{
|
||||
sui_push_frame(listitem_pos, [size_x - 6, 24]);
|
||||
bind_button(strcat(id, ftos(index)), [0, 0], [size_x - 6, 24], bindlist[index].name, bindlist[index].command);
|
||||
sui_pop_frame();
|
||||
}
|
||||
sui_list_view_end();
|
||||
};
|
||||
|
||||
vector binds_scroll;
|
||||
void() settings_menu =
|
||||
{
|
||||
vector pos = [0, 0];
|
||||
vector size = [360, 280];
|
||||
|
||||
sui_push_frame(pos, size);
|
||||
|
||||
sui_fill([0, 0], size, MENU_BG, 0.75, 0);
|
||||
sui_border_box([0, 0], size, 2, MENU_BORDER, 0.3, 0);
|
||||
|
||||
sui_set_align([SUI_ALIGN_CENTER, SUI_ALIGN_START]);
|
||||
sui_text([0, 4], MENU_TEXT_MEDIUM, "Settings", MENU_TEXT_1, 1, 0);
|
||||
|
||||
|
||||
sui_set_align([SUI_ALIGN_START, SUI_ALIGN_START]);
|
||||
|
||||
float xpos = 8;
|
||||
float ypos = 32;
|
||||
float width = size_x * 0.5 - 8 * 2;
|
||||
sui_text([xpos, ypos], MENU_TEXT_SMALL, "Controls", MENU_TEXT_1, 1, 0);
|
||||
ypos += 16;
|
||||
bind_list("bindlist", [xpos, ypos], [width, 160], binds_scroll);
|
||||
ypos += 160 + 8;
|
||||
|
||||
cvar_slider([xpos, ypos], [width, 32], [0.1, 10], "sensitivity", "Sensitivity", "%.2f");
|
||||
ypos += 32;
|
||||
|
||||
ypos = 32;
|
||||
xpos = 8 + width + 8 + 8;
|
||||
|
||||
cvar_slider([xpos, ypos], [width, 32], [0, 1], "volume", "Volume", "%.2f");
|
||||
ypos += 32 + 4;
|
||||
cvar_slider([xpos, ypos], [width, 32], [0, 1], "musicvolume", "Music Volume", "%.2f");
|
||||
ypos += 32 + 4 + 8;
|
||||
|
||||
sui_text([xpos, ypos], MENU_TEXT_SMALL, "Video", MENU_TEXT_1, 1, 0);
|
||||
ypos += 16;
|
||||
my_button("fs_btn", [xpos, ypos], [width, 20], "Fullscreen") ? localcmd("vid_fullscreen 2; vid_restart\n") : 0;
|
||||
ypos += 24;
|
||||
my_button("wn_btn", [xpos, ypos], [width, 20], "Windowed") ? localcmd("vid_fullscreen 0; vid_width 1024; vid_height 768; vid_restart\n") : 0;
|
||||
ypos += 24;
|
||||
sui_text([xpos, ypos], MENU_TEXT_SMALL, "Window can be resized.", MENU_TEXT_1, 0.8, 0);
|
||||
ypos += 16;
|
||||
sui_set_align([SUI_ALIGN_END, SUI_ALIGN_END]);
|
||||
my_button("stg_back", [-8, -8], [80, 20], "Back") ? current_menu = MENU_MAIN : 0;
|
||||
|
||||
sui_pop_frame();
|
||||
};
|
||||
|
||||
void() help_menu =
|
||||
{
|
||||
vector pos = [0, 0];
|
||||
vector size = [360, 280];
|
||||
|
||||
sui_push_frame(pos, size);
|
||||
|
||||
sui_fill([0, 0], size, MENU_BG, 0.75, 0);
|
||||
sui_border_box([0, 0], size, 2, MENU_BORDER, 0.3, 0);
|
||||
|
||||
sui_set_align([SUI_ALIGN_CENTER, SUI_ALIGN_START]);
|
||||
sui_text([0, 4], MENU_TEXT_MEDIUM, "Help", MENU_TEXT_1, 1, 0);
|
||||
|
||||
float xpos = 0;
|
||||
float ypos = 32;
|
||||
sui_text([xpos, ypos], MENU_TEXT_SMALL, "Bunch of Help and About", MENU_TEXT_1, 1, 0);
|
||||
|
||||
sui_set_align([SUI_ALIGN_END, SUI_ALIGN_END]);
|
||||
my_button("hlp_back", [-8, -8], [80, 20], "Back") ? current_menu = MENU_MAIN : 0;
|
||||
|
||||
sui_pop_frame();
|
||||
};
|
||||
|
||||
void(float type) Menu_PlaySound =
|
||||
{
|
||||
string sound = "";
|
||||
|
||||
if (type == MENU_SND_NAVIGATE) sound = cvar_string("menu_navigatesound");
|
||||
else if (type == MENU_SND_ENTER) sound = cvar_string("menu_entersound");
|
||||
|
||||
localsound(sound, 0, cvar("nzp_uivolume"));
|
||||
};
|
||||
|
||||
float last_menu;
|
||||
void(vector size) root_menu =
|
||||
{
|
||||
sui_set_align([SUI_ALIGN_CENTER, SUI_ALIGN_CENTER]);
|
||||
sui_fill([0, 0], size, '0 0 0', 0.5, 0);
|
||||
switch (current_menu)
|
||||
{
|
||||
case MENU_MAIN: Menu_Main(); break;
|
||||
case MENU_SOLO: menu_map_mode = MAP_SOLOSTOCK; Menu_Maps(); break;
|
||||
case MENU_SOLOUSER: menu_map_mode = MAP_SOLOUSER; Menu_Maps(); break;
|
||||
case MENU_OPTIONS: Menu_Options(); break;
|
||||
case MENU_VIDEO: Menu_Video(); break;
|
||||
case MENU_AUDIO: Menu_Audio(); break;
|
||||
case MENU_CONTROL: Menu_Control(); break;
|
||||
case MENU_GAMEPAD: Menu_Gamepad(); break;
|
||||
case MENU_HELP: help_menu();
|
||||
default: break;
|
||||
}
|
||||
|
||||
// Menu enter sound
|
||||
if (last_menu != current_menu) {
|
||||
Menu_PlaySound(MENU_SND_ENTER);
|
||||
last_menu = current_menu;
|
||||
}
|
||||
};
|
272
source/menu/main.qc
Normal file
272
source/menu/main.qc
Normal file
|
@ -0,0 +1,272 @@
|
|||
|
||||
float menu_active;
|
||||
|
||||
//
|
||||
// Menu_GetBuildDate()
|
||||
// Retrieves build date from version.txt
|
||||
// and stores it into build_datetime string.
|
||||
//
|
||||
void() Menu_GetBuildDate =
|
||||
{
|
||||
float file = fopen("version.txt", FILE_READ);
|
||||
|
||||
if (file != -1) {
|
||||
build_datetime = fgets(file);
|
||||
fclose(file);
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// Menu_PickBackground()
|
||||
// Returns a random image in nzp/gfx/menu/custom
|
||||
// to display in Menu_DrawBackground().
|
||||
//
|
||||
string() Menu_PickBackground =
|
||||
{
|
||||
searchhandle pics;
|
||||
float pic_count;
|
||||
|
||||
pics = search_begin("gfx/menu/custom/*", 0, 0);
|
||||
pic_count = search_getsize(pics);
|
||||
|
||||
string image = "";
|
||||
|
||||
while(TRUE) {
|
||||
float entry = rint(random() * pic_count);
|
||||
string potential_image = search_getfilename(pics, entry);
|
||||
|
||||
string extension = strtolower(substring(potential_image, strlen(potential_image) - 3, strlen(potential_image)));
|
||||
|
||||
if (extension != "tga" && extension != "png" && extension != "jpg")
|
||||
continue;
|
||||
|
||||
if (potential_image != menu_background) {
|
||||
image = potential_image;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return image;
|
||||
};
|
||||
|
||||
//
|
||||
// Menu_MapFinder()
|
||||
// Performs a .BSP search in the maps/
|
||||
// directory and adds them to the custom
|
||||
// map data structure.
|
||||
//
|
||||
string(string s) strip_custominfo =
|
||||
{
|
||||
string s2;
|
||||
s2 = substring(s, 5, strlen(s)); // maps/
|
||||
s2 = substring(s2, 0, strlen(s2) - 4); // .bsp
|
||||
|
||||
return s2;
|
||||
}
|
||||
void() Menu_MapFinder =
|
||||
{
|
||||
searchhandle maps;
|
||||
|
||||
maps = search_begin("maps/*.bsp", 0, 0);
|
||||
user_maps_count = search_getsize(maps);
|
||||
|
||||
//custom_map_pages = ceil(map_count/10);
|
||||
|
||||
//float stock_step_back; // So stock maps aren't appended to user maps..
|
||||
for (float i = 0; i < user_maps_count; i++) {
|
||||
//float index = i - stock_step_back;
|
||||
float index = i;
|
||||
|
||||
user_maps[index].occupied = TRUE;
|
||||
user_maps[index].map_name = strip_custominfo(search_getfilename(maps, i));
|
||||
|
||||
// float is_stock;
|
||||
// for(int j = 0; j < stock_maps.length; j++) {
|
||||
// if (user_maps[index].map_name == stock_maps[j].bsp_name) {
|
||||
// stock_step_back++;
|
||||
// is_stock = true;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
|
||||
// // Don't bother occupying if this map is built in.
|
||||
// if (is_stock)
|
||||
// return;
|
||||
|
||||
float settings = fopen(strcat("maps/", user_maps[index].map_name, ".txt"), FILE_READ);
|
||||
if (settings != -1) {
|
||||
user_maps[index].map_name_pretty = fgets(settings);
|
||||
user_maps[index].map_desc[0] = fgets(settings);
|
||||
user_maps[index].map_desc[1] = fgets(settings);
|
||||
user_maps[index].map_desc[2] = fgets(settings);
|
||||
user_maps[index].map_desc[3] = fgets(settings);
|
||||
user_maps[index].map_desc[4] = fgets(settings);
|
||||
user_maps[index].map_desc[5] = fgets(settings);
|
||||
user_maps[index].map_desc[6] = fgets(settings);
|
||||
user_maps[index].map_desc[7] = fgets(settings);
|
||||
user_maps[index].map_author = fgets(settings);
|
||||
user_maps[index].map_use_thumbnail = stof(fgets(settings));
|
||||
user_maps[index].map_allow_game_settings = stof(fgets(settings));
|
||||
fclose(settings);
|
||||
}
|
||||
|
||||
}
|
||||
//user_maps_count -= stock_step_back;
|
||||
|
||||
search_end(maps);
|
||||
};
|
||||
|
||||
//
|
||||
// Menu_GetPlatform()
|
||||
// Parses sys_platform and returns
|
||||
// a valid platform from the platform
|
||||
// enums.
|
||||
//
|
||||
float() Menu_GetPlatform =
|
||||
{
|
||||
string sys_platform = cvar_string("sys_platform");
|
||||
|
||||
switch(sys_platform) {
|
||||
case "Web":
|
||||
return PLATFORM_WEB;
|
||||
case "WinCE":
|
||||
case "WinRT":
|
||||
case "Win":
|
||||
case "Win16":
|
||||
case "Cygwin":
|
||||
return PLATFORM_WIN;
|
||||
case "Xbox":
|
||||
return PLATFORM_XBX;
|
||||
case "Android":
|
||||
return PLATFORM_AND;
|
||||
case "Linux":
|
||||
return PLATFORM_LIN;
|
||||
case "iOSSim":
|
||||
case "iOS":
|
||||
return PLATFORM_IOS;
|
||||
case "Mac":
|
||||
case "Apple":
|
||||
case "MacOS X":
|
||||
return PLATFORM_MAC;
|
||||
case "FreeBSD":
|
||||
case "OpenBSD":
|
||||
case "NetBSD":
|
||||
case "BSD":
|
||||
return PLATFORM_BSD;
|
||||
case "Dos":
|
||||
return PLATFORM_DOS;
|
||||
default:
|
||||
return PLATFORM_UNK;
|
||||
}
|
||||
|
||||
return PLATFORM_UNK;
|
||||
}
|
||||
|
||||
void() m_init =
|
||||
{
|
||||
registercommand("togglemenu2");
|
||||
setcursormode(TRUE,"gfx/xhair", [16, 16], cvar("vid_conautoscale"));
|
||||
current_menu = last_menu = MENU_MAIN;
|
||||
|
||||
// Cvars for controlable/modifiable menu music
|
||||
autocvar(menu_trackname, "tensioned_by_the_damned");
|
||||
autocvar(menu_tracklength, 490);
|
||||
|
||||
// Same goes for menu nav sounds
|
||||
autocvar(menu_navigatesound, "sounds/menu/navigate.wav");
|
||||
autocvar(menu_entersound, "sounds/menu/enter.wav");
|
||||
|
||||
// Retrieve build date
|
||||
Menu_GetBuildDate();
|
||||
|
||||
// Perform map BSP search
|
||||
Menu_MapFinder();
|
||||
|
||||
// Load the font Kerning Map.
|
||||
InitKerningMap();
|
||||
|
||||
// Get Platform Information
|
||||
running_platform = Menu_GetPlatform();
|
||||
|
||||
// Init Cvars
|
||||
autocvar(cl_cinematic, 0);
|
||||
autocvar(nzp_particles, 1);
|
||||
autocvar(nzp_uivolume, 1);
|
||||
autocvar(nzp_bgmvolume, 1);
|
||||
autocvar(vid_ultrawide_limiter, 0);
|
||||
|
||||
music_duration_time = 0;
|
||||
menu_changetime = 0;
|
||||
};
|
||||
|
||||
void(vector screensize) m_draw =
|
||||
{
|
||||
// Menu Music Playback
|
||||
if (time > music_duration_time) {
|
||||
localsound(sprintf("tracks/%s.ogg", cvar_string("menu_trackname")), 1, cvar("nzp_bgmvolume"));
|
||||
music_duration_time = time + cvar("menu_tracklength");
|
||||
}
|
||||
|
||||
// Menu Background Changing
|
||||
if (time > menu_changetime) {
|
||||
menu_background = Menu_PickBackground();
|
||||
menu_changetime = time + 5;
|
||||
}
|
||||
|
||||
sui_begin(screensize_x, screensize_y);
|
||||
if (menu_active)
|
||||
root_menu(screensize);
|
||||
|
||||
sui_end();
|
||||
};
|
||||
|
||||
void() m_close =
|
||||
{
|
||||
setkeydest(0);
|
||||
menu_active = FALSE;
|
||||
};
|
||||
|
||||
void() m_open =
|
||||
{
|
||||
setkeydest(2);
|
||||
menu_active = TRUE;
|
||||
};
|
||||
|
||||
float(float evtype, float scanx, float chary, float devid) Menu_InputEvent =
|
||||
{
|
||||
float used = sui_input_event(evtype, scanx, chary, devid);
|
||||
|
||||
if (evtype == IE_KEYDOWN && !used)
|
||||
{
|
||||
string cmd = getkeybind(scanx);
|
||||
switch (cmd)
|
||||
{
|
||||
case "togglemenu":
|
||||
m_close();
|
||||
return TRUE;
|
||||
default: return FALSE;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
};
|
||||
|
||||
float(string cmd) m_consolecommand =
|
||||
{
|
||||
tokenize(cmd);
|
||||
switch (argv(0))
|
||||
{
|
||||
default: break;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
};
|
||||
|
||||
void(float wantmode) m_toggle =
|
||||
{
|
||||
if (menu_active) m_close();
|
||||
else m_open();
|
||||
};
|
||||
|
||||
void() m_shutdown =
|
||||
{
|
||||
};
|
27
source/menu/menu_audi.qc
Normal file
27
source/menu/menu_audi.qc
Normal file
|
@ -0,0 +1,27 @@
|
|||
void() Menu_Audio_ApplySettings =
|
||||
{
|
||||
localcmd("vid_reload\nsaveconfig user_settings.cfg\n");
|
||||
music_duration_time = 0;
|
||||
};
|
||||
|
||||
void() Menu_Audio =
|
||||
{
|
||||
Menu_DrawBackground();
|
||||
Menu_DrawTitle("AUDIO OPTIONS");
|
||||
Menu_DrawMapPanel();
|
||||
|
||||
Menu_Button(1, "am_maste", "MASTER VOLUME", "Volume for all Audio.") ? 0 : 0;
|
||||
Menu_CvarSlider(1, [0, 1, 10], "volume", false, true);
|
||||
|
||||
Menu_Button(2, "am_menu", "INTERFACE VOLUME", "Volume for UI/Menus.") ? 0 : 0;
|
||||
Menu_CvarSlider(2, [0, 1, 10], "nzp_uivolume", false, true);
|
||||
|
||||
Menu_Button(3, "am_bgm", "MUSIC VOLUME", "Volume for Background Music.") ? 0 : 0;
|
||||
Menu_CvarSlider(3, [0, 1, 10], "nzp_bgmvolume", false, true);
|
||||
|
||||
Menu_DrawDivider(12.25);
|
||||
Menu_Button(-2, "am_apply", "APPLY", "Save & Apply Settings.") ? Menu_Audio_ApplySettings() : 0;
|
||||
Menu_Button(-1, "am_back", "BACK", "Return to Configuration.") ? current_menu = MENU_OPTIONS : 0;
|
||||
|
||||
sui_pop_frame();
|
||||
};
|
102
source/menu/menu_ctrl.qc
Normal file
102
source/menu/menu_ctrl.qc
Normal file
|
@ -0,0 +1,102 @@
|
|||
float menu_ctrl_init;
|
||||
|
||||
float current_adsmode;
|
||||
float current_invert;
|
||||
|
||||
void() Menu_Control_StoreCurrentSettings =
|
||||
{
|
||||
// Figure out ADS mode.
|
||||
tokenize(findkeysforcommandex("+button8"));
|
||||
string button8_key = strtoupper(argv(0));
|
||||
if (button8_key == "MOUSE2") {
|
||||
current_adsmode = 0;
|
||||
} else {
|
||||
current_adsmode = 1;
|
||||
}
|
||||
|
||||
if (cvar("m_pitch") == 0.022)
|
||||
localcmd("m_pitch -0.022\n");
|
||||
else
|
||||
localcmd("m_pitch 0.022\n");
|
||||
|
||||
current_invert = (cvar("m_pitch") == 0.022);
|
||||
};
|
||||
|
||||
void() Menu_Control_Init =
|
||||
{
|
||||
Menu_Control_StoreCurrentSettings();
|
||||
menu_ctrl_init = true;
|
||||
};
|
||||
|
||||
void() Menu_Control_ApplyADS =
|
||||
{
|
||||
Menu_PlaySound(MENU_SND_ENTER);
|
||||
|
||||
tokenize(findkeysforcommandex("+button8"));
|
||||
string button8_key = strtoupper(argv(0));
|
||||
|
||||
// ADS Mode
|
||||
if (button8_key == "MOUSE2") {
|
||||
localcmd("bind MOUSE2 \"impulse 26\"\n");
|
||||
current_adsmode = 1;
|
||||
} else {
|
||||
localcmd("bind MOUSE2 \"+button8\"\n");
|
||||
current_adsmode = 0;
|
||||
}
|
||||
};
|
||||
|
||||
void() Menu_Control_InvertLook =
|
||||
{
|
||||
Menu_PlaySound(MENU_SND_ENTER);
|
||||
current_invert = !current_invert;
|
||||
|
||||
if (current_invert)
|
||||
localcmd("m_pitch -0.022\n");
|
||||
else
|
||||
localcmd("m_pitch 0.022\n");
|
||||
};
|
||||
|
||||
void() Menu_Control_ApplySettings =
|
||||
{
|
||||
localcmd("vid_reload\nsaveconfig user_settings.cfg\n");
|
||||
music_duration_time = 0;
|
||||
};
|
||||
|
||||
void() Menu_Control =
|
||||
{
|
||||
if (!menu_ctrl_init)
|
||||
Menu_Control_Init();
|
||||
|
||||
Menu_DrawBackground();
|
||||
Menu_DrawTitle("CONTROL OPTIONS");
|
||||
Menu_DrawMapPanel();
|
||||
|
||||
Menu_Button(1, "cm_adsm", "AIM DOWN SIGHT", "Switch between Hold and Toggle ADS Modes.") ? Menu_Control_ApplyADS() : 0;
|
||||
string ads_string = "";
|
||||
switch(current_adsmode) {
|
||||
case 0: ads_string = "HOLD"; break;
|
||||
case 1: ads_string = "TOGGLE"; break;
|
||||
default: break;
|
||||
}
|
||||
Menu_DrawOptionValue(1, ads_string);
|
||||
|
||||
Menu_Button(2, "cm_sens", "SENSITIVITY", "Alter Look Sensitivity.") ? 0 : 0;
|
||||
Menu_CvarSlider(2, [1, 10, 10], "sensitivity", false, false);
|
||||
|
||||
Menu_Button(3, "cm_invs", "INVERT LOOK", "Invert Y-Axis Camera Input.") ? Menu_Control_InvertLook() : 0;
|
||||
string invert_string = "";
|
||||
switch(current_invert) {
|
||||
case 0: invert_string = "ENABLED"; break;
|
||||
case 1: invert_string = "DISABLED"; break;
|
||||
default: break;
|
||||
}
|
||||
Menu_DrawOptionValue(3, invert_string);
|
||||
|
||||
Menu_Button(4, "cm_gpad", "GAMEPAD", "Gamepad specific options.") ? current_menu = MENU_GAMEPAD : 0;
|
||||
|
||||
Menu_DrawDivider(12.25);
|
||||
Menu_Button(-2, "cm_apply", "APPLY", "Save & Apply Settings.") ? Menu_Control_ApplySettings() : 0;
|
||||
Menu_Button(-1, "cm_back", "BACK", "Return to Configuration.") ? current_menu = MENU_OPTIONS : 0;
|
||||
|
||||
sui_pop_frame();
|
||||
};
|
107
source/menu/menu_gpad.qc
Normal file
107
source/menu/menu_gpad.qc
Normal file
|
@ -0,0 +1,107 @@
|
|||
float menu_gpad_init;
|
||||
|
||||
// float current_adsmode;
|
||||
// float current_invert;
|
||||
|
||||
// void() Menu_Control_StoreCurrentSettings =
|
||||
// {
|
||||
// // Figure out ADS mode.
|
||||
// tokenize(findkeysforcommandex("+button8"));
|
||||
// string button8_key = strtoupper(argv(0));
|
||||
// if (button8_key == "MOUSE2") {
|
||||
// current_adsmode = 0;
|
||||
// } else {
|
||||
// current_adsmode = 1;
|
||||
// }
|
||||
|
||||
// if (cvar("m_pitch") == 0.022)
|
||||
// localcmd("m_pitch -0.022\n");
|
||||
// else
|
||||
// localcmd("m_pitch 0.022\n");
|
||||
|
||||
// current_invert = (cvar("m_pitch") == 0.022);
|
||||
// };
|
||||
|
||||
void() Menu_Gamepad_Init =
|
||||
{
|
||||
//Menu_Control_StoreCurrentSettings();
|
||||
menu_gpad_init = true;
|
||||
};
|
||||
|
||||
// void() Menu_Control_ApplyADS =
|
||||
// {
|
||||
// Menu_PlaySound(MENU_SND_ENTER);
|
||||
|
||||
// tokenize(findkeysforcommandex("+button8"));
|
||||
// string button8_key = strtoupper(argv(0));
|
||||
|
||||
// // ADS Mode
|
||||
// if (button8_key == "MOUSE2") {
|
||||
// localcmd("bind MOUSE2 \"impulse 26\"\n");
|
||||
// current_adsmode = 1;
|
||||
// } else {
|
||||
// localcmd("bind MOUSE2 \"+button8\"\n");
|
||||
// current_adsmode = 0;
|
||||
// }
|
||||
// };
|
||||
|
||||
// void() Menu_Control_InvertLook =
|
||||
// {
|
||||
// Menu_PlaySound(MENU_SND_ENTER);
|
||||
// current_invert = !current_invert;
|
||||
|
||||
// if (current_invert)
|
||||
// localcmd("m_pitch -0.022\n");
|
||||
// else
|
||||
// localcmd("m_pitch 0.022\n");
|
||||
// };
|
||||
|
||||
// {[6, 135], "Controller Glyphs", -1, setting_glyph, null, MENU_CONSETTINGS, 0, OPTION_WEB_AND_EXE}, // 67
|
||||
// {[6, 155], "Rumble", -1, settings_rumble, null, MENU_CONSETTINGS, 0, OPTION_WEB_AND_EXE}, // 68
|
||||
// {[6, 175], "Gamepad", -1, settings_gamepad, null, MENU_CONSETTINGS, 0, OPTION_WEB_AND_EXE}, // 69
|
||||
// {[6, 195], "Aim Assist", -1, settings_aimassist, null, MENU_CONSETTINGS, 0, OPTION_WEB_AND_EXE}, // 70
|
||||
|
||||
void() Menu_Gamepad_ApplySettings =
|
||||
{
|
||||
localcmd("vid_reload\nsaveconfig user_settings.cfg\n");
|
||||
music_duration_time = 0;
|
||||
};
|
||||
|
||||
void() Menu_Gamepad =
|
||||
{
|
||||
if (!menu_gpad_init)
|
||||
Menu_Gamepad_Init();
|
||||
|
||||
Menu_DrawBackground();
|
||||
Menu_DrawTitle("GAMEPAD OPTIONS");
|
||||
Menu_DrawMapPanel();
|
||||
|
||||
// Menu_Button(1, "cm_adsm", "AIM DOWN SIGHT", "Switch between Hold and Toggle ADS Modes.") ? Menu_Control_ApplyADS() : 0;
|
||||
// string ads_string = "";
|
||||
// switch(current_adsmode) {
|
||||
// case 0: ads_string = "HOLD"; break;
|
||||
// case 1: ads_string = "TOGGLE"; break;
|
||||
// default: break;
|
||||
// }
|
||||
// Menu_DrawOptionValue(1, ads_string);
|
||||
|
||||
// Menu_Button(2, "cm_sens", "SENSITIVITY", "Alter Look Sensitivity.") ? 0 : 0;
|
||||
// Menu_CvarSlider(2, [1, 10, 10], "sensitivity", false, false);
|
||||
|
||||
// Menu_Button(3, "cm_invs", "INVERT LOOK", "Invert Y-Axis Camera Input.") ? Menu_Control_InvertLook() : 0;
|
||||
// string invert_string = "";
|
||||
// switch(current_invert) {
|
||||
// case 0: invert_string = "ENABLED"; break;
|
||||
// case 1: invert_string = "DISABLED"; break;
|
||||
// default: break;
|
||||
// }
|
||||
// Menu_DrawOptionValue(3, invert_string);
|
||||
|
||||
// Menu_Button(4, "cm_gpad", "GAMEPAD", "Gamepad specific options.") ? current_menu = MENU_GAMEPAD : 0;
|
||||
|
||||
Menu_DrawDivider(12.25);
|
||||
Menu_Button(-2, "gp_apply", "APPLY", "Save & Apply Settings.") ? Menu_Gamepad_ApplySettings() : 0;
|
||||
Menu_Button(-1, "gp_back", "BACK", "Return to Configuration.") ? current_menu = MENU_CONTROL : 0;
|
||||
|
||||
sui_pop_frame();
|
||||
};
|
45
source/menu/menu_main.qc
Normal file
45
source/menu/menu_main.qc
Normal file
|
@ -0,0 +1,45 @@
|
|||
string() Menu_Main_GetDashboardName =
|
||||
{
|
||||
switch(running_platform) {
|
||||
case PLATFORM_WIN: return "Windows";
|
||||
case PLATFORM_MAC: return "MacOS";
|
||||
case PLATFORM_LIN: return "Linux";
|
||||
case PLATFORM_XBX: return "Xbox Dashboard";
|
||||
case PLATFORM_AND: return "Android";
|
||||
case PLATFORM_BSD: return "BSD";
|
||||
case PLATFORM_IOS: return "iOS";
|
||||
case PLATFORM_DOS: return "DOS";
|
||||
default: return "System";
|
||||
}
|
||||
|
||||
return "System";
|
||||
};
|
||||
|
||||
void() Menu_Main =
|
||||
{
|
||||
Menu_DrawBackground();
|
||||
Menu_DrawTitle("MAIN MENU");
|
||||
Menu_DrawBuildDate();
|
||||
|
||||
Menu_Button(1, "mm_start", "SOLO", "Play Solo.") ? current_menu = MENU_SOLO : 0;
|
||||
Menu_Button(2, "mm_coop", "COOPERATIVE", "Play with up to Four Players.") ? localcmd("\n") : 0;
|
||||
Menu_DrawDivider(3);
|
||||
Menu_Button(3.25, "mm_options", "CONFIGURATION", "Tweak Game related Options.") ? current_menu = MENU_OPTIONS : 0;
|
||||
Menu_Button(4.25, "mm_achievements", "ACHIEVEMENTS", "View Achievement Progress.") ? localcmd("\n") : 0;
|
||||
Menu_DrawDivider(5.25);
|
||||
Menu_Button(5.50, "mm_credits", "CREDITS", "NZ:P Team + Special Thanks.") ? localcmd("\n") : 0;
|
||||
|
||||
// Don't have a Quit Game button on WASM
|
||||
if (running_platform != PLATFORM_WEB) {
|
||||
Menu_DrawDivider(6.50);
|
||||
Menu_Button(6.75, "mm_quit", "QUIT GAME", sprintf("Return to %s.", Menu_Main_GetDashboardName())) ? localcmd("quit\n") : 0;
|
||||
}
|
||||
|
||||
|
||||
Menu_SocialBadge(1, "soc_youtube", "youtube.com/@nzpteam", 2);
|
||||
Menu_SocialBadge(2, "soc_mastadon", "FIXME", 3);
|
||||
Menu_SocialBadge(3, "soc_patreon", "patreon.com/cypressimplex", 4);
|
||||
Menu_SocialBadge(4, "soc_matrix", "matrix.nzp.gay", 1);
|
||||
|
||||
sui_pop_frame();
|
||||
};
|
95
source/menu/menu_maps.qc
Normal file
95
source/menu/menu_maps.qc
Normal file
|
@ -0,0 +1,95 @@
|
|||
float menu_maps_init;
|
||||
|
||||
//
|
||||
// Menu_Maps_Init()
|
||||
// Array lookup optimization that stores
|
||||
// the array index of Stock NZ:P maps
|
||||
// from the user_maps struct.
|
||||
//
|
||||
void() Menu_Maps_Init =
|
||||
{
|
||||
menu_maps_init = true;
|
||||
user_maps_page = 0;
|
||||
|
||||
for(int i = 0; i < stock_maps.length; i++) {
|
||||
for(int j = 0; j < user_maps_count; j++) {
|
||||
if (user_maps[j].map_name == stock_maps[i].bsp_name)
|
||||
stock_maps[i].array_index = j;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void() Menu_Maps_NextPage =
|
||||
{
|
||||
Menu_PlaySound(MENU_SND_ENTER);
|
||||
user_maps_page++;
|
||||
}
|
||||
|
||||
void() Menu_Maps_PrevPage =
|
||||
{
|
||||
Menu_PlaySound(MENU_SND_ENTER);
|
||||
user_maps_page--;
|
||||
}
|
||||
|
||||
void() Menu_Maps =
|
||||
{
|
||||
if (!menu_maps_init)
|
||||
Menu_Maps_Init();
|
||||
|
||||
Menu_DrawBackground();
|
||||
|
||||
string back_string = "";
|
||||
float back_menudest = 0;
|
||||
|
||||
switch(menu_map_mode) {
|
||||
case MAP_SOLOSTOCK: Menu_DrawTitle("SELECT MAP: SOLO"); back_string = "Return to Main Menu."; back_menudest = MENU_MAIN; break;
|
||||
case MAP_SOLOUSER: Menu_DrawTitle("USER MAPS: SOLO"); back_string = "Return to Stock Map selection."; back_menudest = MENU_SOLO; break;
|
||||
case MAP_COOPSTOCK: Menu_DrawTitle("SELECT MAP: COOP"); break;
|
||||
case MAP_COOPUSER: Menu_DrawTitle("USER MAPS: COOP"); break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
Menu_DrawMapPanel();
|
||||
|
||||
int i;
|
||||
|
||||
// Stock Maps
|
||||
if (menu_map_mode == MAP_SOLOSTOCK || menu_map_mode == MAP_COOPSTOCK) {
|
||||
for(i = 0; i < stock_maps.length; i++) {
|
||||
Menu_MapButton(i + 1, sprintf("map_%s", stock_maps[i].bsp_name), stock_maps[i].bsp_name, -1) ? localcmd(sprintf("map %s\n", stock_maps[i].bsp_name)) : 0;
|
||||
}
|
||||
Menu_DrawDivider(i + 1.25);
|
||||
Menu_Button(i + 1.5, "map_nzpusermaps", "USER MAPS", "View User-Created Maps.") ? current_menu = MENU_SOLOUSER : 0;
|
||||
} else {
|
||||
// calculate the amount of usermaps we can display on this page.
|
||||
int maps_on_page = 10; // default to 10, all that will fit on the UI.
|
||||
int maps_start_position = (user_maps_page * 10);
|
||||
|
||||
// Not all 10 slots can be filled..
|
||||
if (maps_on_page > user_maps_count - maps_start_position)
|
||||
maps_on_page = user_maps_count - maps_start_position;
|
||||
|
||||
for (i = maps_start_position; i < maps_on_page + maps_start_position; i++) {
|
||||
int menu_position = (i + 1) - (user_maps_page * 10);
|
||||
string bsp_name = user_maps[i].map_name;
|
||||
|
||||
Menu_MapButton(menu_position, sprintf("map_%s", bsp_name), bsp_name, i) ? localcmd(sprintf("map %s\n", bsp_name)) : 0;
|
||||
}
|
||||
|
||||
Menu_DrawDivider(11.25);
|
||||
|
||||
if (maps_on_page + maps_start_position < user_maps_count)
|
||||
Menu_Button(-3, "map_usernext", "NEXT PAGE", "Advance to next User Map page.") ? Menu_Maps_NextPage() : 0;
|
||||
else
|
||||
Menu_GreyButton(-3, "NEXT PAGE");
|
||||
|
||||
if (user_maps_page != 0)
|
||||
Menu_Button(-2, "map_userprev", "PREVIOUS PAGE", "Return to last User Map page.") ? Menu_Maps_PrevPage() : 0;
|
||||
else
|
||||
Menu_GreyButton(-2, "PREVIOUS PAGE");
|
||||
}
|
||||
|
||||
Menu_Button(-1, "map_back", "BACK", back_string) ? current_menu = back_menudest : 0;
|
||||
|
||||
sui_pop_frame();
|
||||
};
|
16
source/menu/menu_opts.qc
Normal file
16
source/menu/menu_opts.qc
Normal file
|
@ -0,0 +1,16 @@
|
|||
void() Menu_Options =
|
||||
{
|
||||
Menu_DrawBackground();
|
||||
Menu_DrawTitle("CONFIGURATION");
|
||||
|
||||
Menu_Button(1, "om_video", "VIDEO", "Visual Fidelity options.") ? current_menu = MENU_VIDEO : 0;
|
||||
Menu_Button(2, "om_audio", "AUDIO", "Volume sliders.") ? current_menu = MENU_AUDIO : 0;
|
||||
Menu_Button(3, "om_binds", "CONTROLS", "Control Options and Bindings.") ? current_menu = MENU_CONTROL : 0;
|
||||
Menu_Button(4, "om_acces", "ACCESSIBILITY", "Light Sensitivity options.") ? 1 : 0;
|
||||
Menu_DrawDivider(5);
|
||||
Menu_Button(5.25, "om_console", "OPEN CONSOLE", "Access the Developer Console.") ? localcmd("toggleconsole\n") : 0;
|
||||
|
||||
Menu_Button(-1, "om_back", "BACK", "Return to Main Menu.") ? current_menu = MENU_MAIN : 0;
|
||||
|
||||
sui_pop_frame();
|
||||
};
|
247
source/menu/menu_vide.qc
Normal file
247
source/menu/menu_vide.qc
Normal file
|
@ -0,0 +1,247 @@
|
|||
float menu_video_init;
|
||||
float menu_video_modes;
|
||||
|
||||
float current_selected_vidmode;
|
||||
float current_fullscreen;
|
||||
float current_showfps;
|
||||
float current_vsync;
|
||||
float current_ultrawide;
|
||||
float current_particles;
|
||||
float current_filter;
|
||||
|
||||
#define MAX_VIDEO_MODES 128 // FIXME: arbitrary.
|
||||
|
||||
var struct
|
||||
{
|
||||
vector size;
|
||||
vector ratio;
|
||||
} video_modes[MAX_VIDEO_MODES];
|
||||
|
||||
float(float a, float b) Menu_Video_GCD =
|
||||
{
|
||||
if (b == 0)
|
||||
return a;
|
||||
else
|
||||
return Menu_Video_GCD(b, a % b);
|
||||
};
|
||||
|
||||
vector(vector resolution) Menu_Video_CalculateAspectRatio =
|
||||
{
|
||||
vector ratio;
|
||||
|
||||
if (resolution_x == resolution_y) {
|
||||
ratio_x = 1;
|
||||
ratio_y = 1;
|
||||
return ratio;
|
||||
}
|
||||
|
||||
float tempf = 0;
|
||||
float width = resolution_x;
|
||||
float height = resolution_y;
|
||||
|
||||
if (width < height) {
|
||||
tempf = width;
|
||||
width = height;
|
||||
height = tempf;
|
||||
}
|
||||
|
||||
float divisor = Menu_Video_GCD(width, height);
|
||||
|
||||
if (!tempf) {
|
||||
ratio_x = rint(width / divisor);
|
||||
ratio_y = rint(height / divisor);
|
||||
} else {
|
||||
ratio_x = rint(height / divisor);
|
||||
ratio_y = rint(width / divisor);
|
||||
}
|
||||
|
||||
return ratio;
|
||||
};
|
||||
|
||||
void() Menu_Video_PrepareVideoModes =
|
||||
{
|
||||
for (float i = 0; i < MAX_VIDEO_MODES; i++)
|
||||
{
|
||||
vector driver_query = getresolution(i);
|
||||
|
||||
if (!driver_query_x || !driver_query_y)
|
||||
break;
|
||||
|
||||
video_modes[i].size = driver_query;
|
||||
video_modes[i].ratio = Menu_Video_CalculateAspectRatio(driver_query);
|
||||
|
||||
menu_video_modes = i;
|
||||
}
|
||||
};
|
||||
|
||||
void() Menu_Video_StoreCurrentSettings =
|
||||
{
|
||||
current_fullscreen = cvar("vid_fullscreen");
|
||||
current_showfps = cvar("show_fps");
|
||||
current_vsync = cvar("vid_vsync");
|
||||
current_ultrawide = cvar("vid_ultrawide_limiter");
|
||||
current_particles = cvar("nzp_particles");
|
||||
current_filter = (substring(strtoupper(cvar_string("gl_texturemode")), 0, 10) == "GL_NEAREST");
|
||||
}
|
||||
|
||||
void() Menu_Video_Init =
|
||||
{
|
||||
Menu_Video_PrepareVideoModes();
|
||||
Menu_Video_StoreCurrentSettings();
|
||||
menu_video_init = true;
|
||||
};
|
||||
|
||||
void() Menu_Video_UpdateParticles =
|
||||
{
|
||||
Menu_PlaySound(MENU_SND_ENTER);
|
||||
current_particles = !current_particles;
|
||||
cvar_set("nzp_particles", ftos(current_particles));
|
||||
};
|
||||
|
||||
void() Menu_Video_UpdateUltrawide =
|
||||
{
|
||||
Menu_PlaySound(MENU_SND_ENTER);
|
||||
current_ultrawide = !current_ultrawide;
|
||||
cvar_set("vid_ultrawide_limiter", ftos(current_ultrawide));
|
||||
};
|
||||
|
||||
void() Menu_Video_UpdateVideoMode =
|
||||
{
|
||||
Menu_PlaySound(MENU_SND_ENTER);
|
||||
current_selected_vidmode++;
|
||||
};
|
||||
|
||||
void() Menu_Video_ApplySettings =
|
||||
{
|
||||
Menu_PlaySound(MENU_SND_ENTER);
|
||||
localcmd(sprintf("vid_width %d\nvid_height %d\nvid_fullscreen %d\nvid_restart\nsaveconfig user_settings.cfg\n",
|
||||
video_modes[current_selected_vidmode].size[0], video_modes[current_selected_vidmode].size[1],
|
||||
current_fullscreen));
|
||||
music_duration_time = 0;
|
||||
};
|
||||
|
||||
void() Menu_Video_UpdateFullscreen =
|
||||
{
|
||||
Menu_PlaySound(MENU_SND_ENTER);
|
||||
current_fullscreen++;
|
||||
if (current_fullscreen > 2) current_fullscreen = 0;
|
||||
};
|
||||
|
||||
void() Menu_Video_UpdateShowFPS =
|
||||
{
|
||||
Menu_PlaySound(MENU_SND_ENTER);
|
||||
current_showfps++;
|
||||
if (current_showfps > 2) current_showfps = 0;
|
||||
localcmd(sprintf("show_fps %d", current_showfps));
|
||||
};
|
||||
|
||||
void() Menu_Video_UpdateVsync =
|
||||
{
|
||||
Menu_PlaySound(MENU_SND_ENTER);
|
||||
current_vsync = !current_vsync;
|
||||
cvar_set("vid_vsync", ftos(current_vsync));
|
||||
};
|
||||
|
||||
void() Menu_Video_UpdateFiltering =
|
||||
{
|
||||
Menu_PlaySound(MENU_SND_ENTER);
|
||||
float is_filter = (substring(strtoupper(cvar_string("gl_texturemode")), 0, 10) == "GL_NEAREST");
|
||||
if (is_filter) {
|
||||
cvar_set("gl_texturemode", "GL_LINEAR_MIPMAP_LINEAR");
|
||||
current_filter = 0;
|
||||
} else {
|
||||
cvar_set("gl_texturemode", "GL_NEAREST_MIPMAP_LINEAR");
|
||||
current_filter = 1;
|
||||
}
|
||||
};
|
||||
|
||||
void() Menu_Video =
|
||||
{
|
||||
if (!menu_video_init)
|
||||
Menu_Video_Init();
|
||||
|
||||
Menu_DrawBackground();
|
||||
Menu_DrawTitle("VIDEO OPTIONS");
|
||||
|
||||
Menu_DrawMapPanel();
|
||||
|
||||
// Resolution
|
||||
Menu_Button(1, "vm_resol", "RESOLUTION", "Window size adjustment.") ? Menu_Video_UpdateVideoMode() : 0;
|
||||
if (current_selected_vidmode > menu_video_modes) current_selected_vidmode = 0;
|
||||
string resolution_string = sprintf("%dx%d (%d:%d)", video_modes[current_selected_vidmode].size[0],
|
||||
video_modes[current_selected_vidmode].size[1], video_modes[current_selected_vidmode].ratio[0],
|
||||
video_modes[current_selected_vidmode].ratio[1]);
|
||||
Menu_DrawOptionValue(1, resolution_string);
|
||||
|
||||
// Fullscreen
|
||||
Menu_Button(2, "vm_fulls", "FULLSCREEN", "Change Fullscreen Mode.") ? Menu_Video_UpdateFullscreen() : 0;
|
||||
string fullscreen_string = "";
|
||||
switch(current_fullscreen) {
|
||||
case 0: fullscreen_string = "DISABLED"; break;
|
||||
case 1: fullscreen_string = "ENABLED"; break;
|
||||
case 2: fullscreen_string = "BORDERLESS"; break;
|
||||
default: break;
|
||||
}
|
||||
Menu_DrawOptionValue(2, fullscreen_string);
|
||||
|
||||
// Show FPS
|
||||
Menu_Button(3, "vm_shfps", "SHOW FPS", "Toggles display of FPS Values.") ? Menu_Video_UpdateShowFPS() : 0;
|
||||
string showfps_string = "";
|
||||
switch(current_showfps) {
|
||||
case 0: showfps_string = "DISABLED"; break;
|
||||
case 1: showfps_string = "ENABLED"; break;
|
||||
case 2: showfps_string = "VERBOSE"; break;
|
||||
default: break;
|
||||
}
|
||||
Menu_DrawOptionValue(3, showfps_string);
|
||||
|
||||
// Max FPS
|
||||
if (cvar("vid_vsync") == 0) {
|
||||
Menu_Button(4, "vm_maxps", "MAX FPS", "Configure Maximum FPS Value.") ? 0 : 0;
|
||||
Menu_CvarSlider(4, [10, 500, 490], "cl_maxfps", true, false);
|
||||
} else {
|
||||
Menu_GreyButton(4, "[VSYNC ON] MAX FPS");
|
||||
}
|
||||
|
||||
// VSync
|
||||
Menu_Button(5, "vm_vsync", "VSYNC", "Sync Framerate with Display.") ? Menu_Video_UpdateVsync() : 0;
|
||||
string vsync_string = "";
|
||||
if (current_vsync) vsync_string = "ENABLED";
|
||||
else vsync_string = "DISABLED";
|
||||
Menu_DrawOptionValue(5, vsync_string);
|
||||
|
||||
// Field of View
|
||||
Menu_Button(6, "vm_fov", "FIELD OF VIEW", "Change Camera Field of View.") ? 0 : 0;
|
||||
Menu_CvarSlider(6, [10, 200, 190], "fov", true, false);
|
||||
|
||||
// Gamma
|
||||
Menu_Button(7, "vm_gamma", "GAMMA", "Adjust game Black Level.") ? 0 : 0;
|
||||
Menu_CvarSlider(7, [0.3, 2, 17], "gamma", false, true);
|
||||
|
||||
// Ultrawide Mode
|
||||
Menu_Button(8, "vm_uwide", "ULTRAWIDE MODE", "Condenses HUD closer to center of Display.") ? Menu_Video_UpdateUltrawide() : 0;
|
||||
string wide_string = "";
|
||||
if (current_ultrawide) wide_string = "ENABLED";
|
||||
else wide_string = "DISABLED";
|
||||
Menu_DrawOptionValue(8, wide_string);
|
||||
|
||||
// Particles
|
||||
Menu_Button(9, "vm_parts", "PARTICLES", "Toggle Particle Effects for Performance.") ? Menu_Video_UpdateParticles() : 0;
|
||||
string part_string = "";
|
||||
if (current_particles) part_string = "ENABLED";
|
||||
else part_string = "DISABLED";
|
||||
Menu_DrawOptionValue(9, part_string);
|
||||
|
||||
// Texture Filtering
|
||||
Menu_Button(10, "vm_filtr", "TEXTURE FILTERING", "Choose 3D Environment Filtering Mode.") ? Menu_Video_UpdateFiltering() : 0;
|
||||
string filt_string = "";
|
||||
if (current_filter) filt_string = "NEAREST";
|
||||
else filt_string = "LINEAR";
|
||||
Menu_DrawOptionValue(10, filt_string);
|
||||
|
||||
Menu_DrawDivider(12.25);
|
||||
Menu_Button(-2, "vm_apply", "APPLY", "Save & Apply Settings.") ? Menu_Video_ApplySettings() : 0;
|
||||
Menu_Button(-1, "vm_back", "BACK", "Return to Configuration Menu.") ? current_menu = MENU_OPTIONS : 0;
|
||||
|
||||
sui_pop_frame();
|
||||
};
|
960
source/menu/sui_sys.qc
Normal file
960
source/menu/sui_sys.qc
Normal file
|
@ -0,0 +1,960 @@
|
|||
// Shpuld's Simple UI lib - sui
|
||||
// Created 11/2018
|
||||
//
|
||||
// sui is a simple QuakeC UI lib for drawing and handling game interfaces.
|
||||
// The API is made simple and easy to build upon, but cuts have been made
|
||||
// to keep complexity low.
|
||||
//
|
||||
|
||||
|
||||
#ifdef MENU
|
||||
const float IE_KEYDOWN = 0; /* Specifies that a key was pressed. Second argument is the scan code. Third argument is the unicode (printable) char value. Fourth argument denotes which keyboard(or mouse, if its a mouse 'scan' key) the event came from. Note that some systems may completely separate scan codes and unicode values, with a 0 value for the unspecified argument. */
|
||||
const float IE_KEYUP = 1; /* Specifies that a key was released. Arguments are the same as IE_KEYDOWN. On some systems, this may be fired instantly after IE_KEYDOWN was fired. */
|
||||
const float IE_MOUSEDELTA = 2; /* Specifies that a mouse was moved (touch screens and tablets typically give IE_MOUSEABS events instead, use _windowed_mouse 0 to test code to cope with either). Second argument is the X displacement, third argument is the Y displacement. Fourth argument is which mouse or touch event triggered the event. */
|
||||
const float IE_MOUSEABS = 3; /* Specifies that a mouse cursor or touch event was moved to a specific location relative to the virtual screen space. Second argument is the new X position, third argument is the new Y position. Fourth argument is which mouse or touch event triggered the event. */
|
||||
const float IE_ACCELEROMETER = 4;
|
||||
const float IE_FOCUS = 5; /* Specifies that input focus was given. parama says mouse focus, paramb says keyboard focus. If either are -1, then it is unchanged. */
|
||||
const float IE_JOYAXIS = 6; /* Specifies that what value a joystick/controller axis currently specifies. x=axis, y=value. Will be called multiple times, once for each axis of each active controller. */
|
||||
|
||||
#define printf(x, ...) print(sprintf(x, __VA_ARGS__))
|
||||
|
||||
#endif
|
||||
float _sui_draw_initialized;
|
||||
|
||||
|
||||
// framing
|
||||
|
||||
// pseudo windowing, sets a new "frame" for whatever we're drawing, instead of
|
||||
// always using screen [0, 0] as min and [screen_width, screen_height] as max.
|
||||
// also allows for aligning content to frame start/end/center on both axis
|
||||
|
||||
struct _frame_t {
|
||||
vector pos;
|
||||
vector size;
|
||||
vector align;
|
||||
};
|
||||
const float MAX_FRAMES = 64;
|
||||
_frame_t _frames[MAX_FRAMES];
|
||||
float _frame_index;
|
||||
|
||||
const float SUI_ALIGN_START = 0;
|
||||
const float SUI_ALIGN_CENTER = 1;
|
||||
const float SUI_ALIGN_END = 2;
|
||||
|
||||
void() sui_reset_align =
|
||||
{
|
||||
_frames[_frame_index].align = [SUI_ALIGN_START, SUI_ALIGN_START];
|
||||
};
|
||||
|
||||
void(float align) sui_set_x_align =
|
||||
{
|
||||
_frames[_frame_index].align.x = align;
|
||||
};
|
||||
|
||||
void(float align) sui_set_y_align =
|
||||
{
|
||||
_frames[_frame_index].align.y = align;
|
||||
};
|
||||
|
||||
void(vector align) sui_set_align =
|
||||
{
|
||||
_frames[_frame_index].align = align;
|
||||
};
|
||||
|
||||
void(__inout vector point) sui_transform_point =
|
||||
{
|
||||
int idx = _frame_index;
|
||||
switch (_frames[idx].align.x)
|
||||
{
|
||||
case SUI_ALIGN_START: point_x += _frames[idx].pos.x; break;
|
||||
case SUI_ALIGN_CENTER: point_x += _frames[idx].pos.x + _frames[idx].size.x * 0.5; break;
|
||||
case SUI_ALIGN_END: point_x += _frames[idx].pos.x + _frames[idx].size.x; break;
|
||||
default: break;
|
||||
}
|
||||
switch (_frames[idx].align.y)
|
||||
{
|
||||
case SUI_ALIGN_START: point_y += _frames[idx].pos.y; break;
|
||||
case SUI_ALIGN_CENTER: point_y += _frames[idx].pos.y + _frames[idx].size.y * 0.5; break;
|
||||
case SUI_ALIGN_END: point_y += _frames[idx].pos.y + _frames[idx].size.y; break;
|
||||
default: break;
|
||||
}
|
||||
};
|
||||
|
||||
void(__inout vector point, vector size) sui_transform_box =
|
||||
{
|
||||
int idx = _frame_index;
|
||||
switch (_frames[idx].align.x)
|
||||
{
|
||||
case SUI_ALIGN_START:
|
||||
point_x += _frames[idx].pos.x;
|
||||
break;
|
||||
case SUI_ALIGN_CENTER:
|
||||
point_x += _frames[idx].pos.x + _frames[idx].size.x * 0.5 - size_x * 0.5;
|
||||
break;
|
||||
case SUI_ALIGN_END:
|
||||
point_x += _frames[idx].pos.x + _frames[idx].size.x - size_x;
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
switch (_frames[idx].align.y)
|
||||
{
|
||||
case SUI_ALIGN_START:
|
||||
point_y += _frames[idx].pos.y;
|
||||
break;
|
||||
case SUI_ALIGN_CENTER:
|
||||
point_y += _frames[idx].pos.y + _frames[idx].size.y * 0.5 - size_y * 0.5;
|
||||
break;
|
||||
case SUI_ALIGN_END:
|
||||
point_y += _frames[idx].pos.y + _frames[idx].size.y - size_y;
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
};
|
||||
|
||||
vector() sui_current_frame_pos =
|
||||
{
|
||||
return _frames[_frame_index].pos;
|
||||
};
|
||||
|
||||
vector() sui_current_frame_size =
|
||||
{
|
||||
return _frames[_frame_index].size;
|
||||
};
|
||||
|
||||
float _sui_is_clipping;
|
||||
vector _sui_clip_area_mins;
|
||||
vector _sui_clip_area_maxs;
|
||||
void() sui_clip_to_frame =
|
||||
{
|
||||
vector pos = _frames[_frame_index].pos;
|
||||
vector size = _frames[_frame_index].size;
|
||||
_sui_is_clipping = TRUE;
|
||||
_sui_clip_area_mins = pos;
|
||||
_sui_clip_area_maxs = pos + size;
|
||||
drawsetcliparea(pos.x, pos.y, size.x, size.y);
|
||||
};
|
||||
|
||||
void() sui_reset_clip =
|
||||
{
|
||||
_sui_is_clipping = FALSE;
|
||||
drawresetcliparea();
|
||||
};
|
||||
|
||||
float() sui_is_clipping =
|
||||
{
|
||||
return _sui_is_clipping;
|
||||
};
|
||||
|
||||
void(vector pos, vector size) sui_push_frame =
|
||||
{
|
||||
sui_transform_box(pos, size);
|
||||
|
||||
_frame_index += 1;
|
||||
if (_frame_index >= MAX_FRAMES)
|
||||
{
|
||||
printf("^3sui warning: amount of frames = %.0f exceeds MAX_FRAMES = %.0f, consider increasing MAX_FRAMES\n", _frame_index, MAX_FRAMES);
|
||||
return;
|
||||
}
|
||||
|
||||
_frames[_frame_index].pos = pos;
|
||||
_frames[_frame_index].size = size;
|
||||
_frames[_frame_index].align = [SUI_ALIGN_START, SUI_ALIGN_START]; // TODO allow customizing this
|
||||
};
|
||||
|
||||
void() sui_pop_frame =
|
||||
{
|
||||
if (_frame_index > 0) _frame_index -= 1;
|
||||
};
|
||||
|
||||
void() sui_reset_frame =
|
||||
{
|
||||
_frame_index = 0;
|
||||
sui_reset_align();
|
||||
};
|
||||
|
||||
|
||||
// actions
|
||||
|
||||
// interaction for sui elements, relies a lot on reading globals to see which
|
||||
// element id is under cursor or held or whatever, not the most elegant
|
||||
// solution but in this highly imperative world of QuakeC we can live with it
|
||||
|
||||
float _holding_click;
|
||||
vector _cursor_click;
|
||||
vector _cursor_position;
|
||||
vector _cursor_relative_click;
|
||||
vector _cursor_relative_hover;
|
||||
struct _action_element_t {
|
||||
vector pos;
|
||||
vector size;
|
||||
string id;
|
||||
void(float index, vector click_ratios) action;
|
||||
};
|
||||
const float MAX_ACTION_ELEMENTS = 256;
|
||||
_action_element_t _action_elements[MAX_ACTION_ELEMENTS];
|
||||
float _action_elements_index;
|
||||
|
||||
|
||||
// TODO better naming
|
||||
float(vector point, vector min, vector max) is_2dpoint_in_bounds =
|
||||
{
|
||||
if (point_x <= min_x || point_y <= min_y) return FALSE;
|
||||
if (point_x > max_x || point_y > max_y) return FALSE;
|
||||
return TRUE;
|
||||
};
|
||||
|
||||
// TODO better naming
|
||||
float(vector point, vector pos, vector size) is_2dpoint_in_bbox =
|
||||
{
|
||||
return is_2dpoint_in_bounds(point, pos, pos + size);
|
||||
};
|
||||
|
||||
void() _action_element_count_sanity =
|
||||
{
|
||||
if (_action_elements_index > MAX_ACTION_ELEMENTS)
|
||||
{
|
||||
// let the user know if they're hitting the bounds
|
||||
printf("^3sui warning: amount of action elements = %.0f exceeds MAX_ACTION_ELEMENTS = %.0f, consider increasing MAX_ACTION_ELEMENTS\n", _action_elements_index, MAX_ACTION_ELEMENTS);
|
||||
}
|
||||
};
|
||||
|
||||
const float MAX_MOUSE_ACTIONS = 16;
|
||||
string _hover_actions[MAX_MOUSE_ACTIONS];
|
||||
string _click_actions[MAX_MOUSE_ACTIONS];
|
||||
string _hold_actions[MAX_MOUSE_ACTIONS];
|
||||
string _release_actions[MAX_MOUSE_ACTIONS];
|
||||
string _last_clicked_actions[MAX_MOUSE_ACTIONS];
|
||||
|
||||
float _hover_action_count;
|
||||
float _click_action_count;
|
||||
float _hold_action_count;
|
||||
float _release_action_count;
|
||||
float _last_clicked_action_count;
|
||||
|
||||
|
||||
// Resets things you might want to persist normally
|
||||
void() sui_reset_actions =
|
||||
{
|
||||
_hover_action_count = 0;
|
||||
_click_action_count = 0;
|
||||
_hold_action_count = 0;
|
||||
_release_action_count = 0;
|
||||
_last_clicked_action_count = 0;
|
||||
_holding_click = FALSE;
|
||||
};
|
||||
|
||||
// Per frame reset?
|
||||
void() sui_reset_click =
|
||||
{
|
||||
_hold_action_count = 0;
|
||||
_click_action_count = 0;
|
||||
_holding_click = FALSE;
|
||||
};
|
||||
|
||||
float() sui_click_held = { return _holding_click; };
|
||||
|
||||
|
||||
// click: on mouse1 button down AND button op, once
|
||||
|
||||
// Returns true if id was the topmost click (what usually is cared about the most)
|
||||
float(string id) sui_is_clicked =
|
||||
{
|
||||
return _click_action_count > 0 && _click_actions[0] == id;
|
||||
};
|
||||
|
||||
// Returns the index of the clicked id, -1 if wasn't hit at all. 0 is topmost
|
||||
float(string id) sui_click_index =
|
||||
{
|
||||
for (int i = 0; i < _click_action_count; i++)
|
||||
{
|
||||
if (_click_actions[i] == id) return i;
|
||||
}
|
||||
return -1;
|
||||
};
|
||||
|
||||
|
||||
// hover: mouse is on top of the action element id
|
||||
|
||||
string last_hovered_id;
|
||||
float(string id) sui_is_hovered =
|
||||
{
|
||||
float is_hovered = _hover_action_count > 0 && _hover_actions[0] == id;
|
||||
|
||||
if (is_hovered && last_hovered_id != id && substring(id, 0, 4) != "soc_") {
|
||||
last_hovered_id = id;
|
||||
Menu_PlaySound(MENU_SND_NAVIGATE);
|
||||
}
|
||||
|
||||
return is_hovered;
|
||||
};
|
||||
|
||||
float(string id) sui_hover_index =
|
||||
{
|
||||
for (int i = 0; i < _hover_action_count; i++)
|
||||
{
|
||||
if (_hover_actions[i] == id) return i;
|
||||
}
|
||||
return -1;
|
||||
};
|
||||
|
||||
|
||||
// hold: mouse button was clicked on top of this id and is held down, but not necessarily over this id anymore
|
||||
|
||||
float(string id) sui_is_held =
|
||||
{
|
||||
return _hold_action_count > 0 && _hold_actions[0] == id;
|
||||
};
|
||||
|
||||
float(string id) sui_hold_index =
|
||||
{
|
||||
for (int i = 0; i < _hold_action_count; i++)
|
||||
{
|
||||
if (_hold_actions[i] == id) return i;
|
||||
}
|
||||
return -1;
|
||||
};
|
||||
|
||||
|
||||
// last clicked: is this the last action element that was clicked, good for focusing on input boxes for example
|
||||
|
||||
float(string id) sui_is_last_clicked =
|
||||
{
|
||||
return _last_clicked_action_count > 0 && _last_clicked_actions[0] == id;
|
||||
};
|
||||
|
||||
float(string id) sui_last_clicked_index =
|
||||
{
|
||||
for (int i = 0; i < _last_clicked_action_count; i++)
|
||||
{
|
||||
if (_last_clicked_actions[i] == id) return i;
|
||||
}
|
||||
return -1;
|
||||
};
|
||||
|
||||
|
||||
// release: a thing was held, but now it was released, once
|
||||
|
||||
float(string id) sui_is_released =
|
||||
{
|
||||
return _release_action_count > 0 && _release_actions[0] == id;
|
||||
};
|
||||
|
||||
float(string id) sui_release_index =
|
||||
{
|
||||
for (int i = 0; i < _release_action_count; i++)
|
||||
{
|
||||
if (_release_actions[i] == id) return i;
|
||||
}
|
||||
return -1;
|
||||
};
|
||||
|
||||
|
||||
float(float num) mouse_action_sanity =
|
||||
{
|
||||
if (num >= MAX_MOUSE_ACTIONS)
|
||||
{
|
||||
printf("^3sui warning: you have exceeded the amount of overlapping action elements with %.0f, MAX_MOUSE_ACTIONS = %.0f\n", num, MAX_MOUSE_ACTIONS);
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
};
|
||||
|
||||
// mouse move, mostly just update hovers
|
||||
|
||||
void(vector pos) _sui_mouse_move =
|
||||
{
|
||||
_cursor_position = pos;
|
||||
_action_element_count_sanity();
|
||||
|
||||
// Reset hover, it'll be back to what it used to be before draw gets called if mouse is still on same element
|
||||
_hover_action_count = 0;
|
||||
|
||||
// Iterate front to back, so topmost element gets the click/hover
|
||||
for (int i = min(MAX_ACTION_ELEMENTS, _action_elements_index) - 1; i >= 0; i--)
|
||||
{
|
||||
if (is_2dpoint_in_bbox(_cursor_position, _action_elements[i].pos, _action_elements[i].size))
|
||||
{
|
||||
if (mouse_action_sanity(_hover_action_count)) break;
|
||||
|
||||
if (_hover_action_count == 0) _cursor_relative_hover = _cursor_position - _action_elements[i].pos;
|
||||
_hover_actions[_hover_action_count] = _action_elements[i].id;
|
||||
_hover_action_count += 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Cypress -- Reset last_hovered if nothing is hovered for menu
|
||||
// navigation sounds
|
||||
if (!_hover_action_count)
|
||||
last_hovered_id = "";
|
||||
};
|
||||
|
||||
// JERK ALERT: hard to pass input params for it without them just being the globals
|
||||
// ... so it just straight up uses the globals... optimization
|
||||
void() _sui_mouse1_down =
|
||||
{
|
||||
// Cheap but it should work...
|
||||
_cursor_click = _cursor_position;
|
||||
_cursor_relative_click = _cursor_relative_hover;
|
||||
for (int i = 0; i < _hover_action_count; i++) _hold_actions[i] = _hover_actions[i];
|
||||
_hold_action_count = _hover_action_count;
|
||||
_holding_click = TRUE;
|
||||
_last_clicked_action_count = 0;
|
||||
};
|
||||
|
||||
void() _sui_mouse1_up =
|
||||
{
|
||||
// Can't be cheap here, we have to get the action fn of the element anyway so..
|
||||
_action_element_count_sanity();
|
||||
|
||||
// Assume we won't hit anything
|
||||
_click_action_count = 0;
|
||||
_last_clicked_action_count = 0;
|
||||
|
||||
// Iterate front to back, so topmost element gets the click/hover
|
||||
for (int i = min(MAX_ACTION_ELEMENTS, _action_elements_index) - 1; i >= 0; i--)
|
||||
{
|
||||
// If the thing wasn't the same thing we started pressing down on, ignore
|
||||
for (int j = 0; j < _hold_action_count; j++)
|
||||
{
|
||||
if (_hold_actions[j] == _action_elements[i].id) // yes this element was held
|
||||
{
|
||||
// Still in bounds?
|
||||
if (is_2dpoint_in_bbox(_cursor_position, _action_elements[i].pos, _action_elements[i].size))
|
||||
{
|
||||
if (mouse_action_sanity(_click_action_count)) break;
|
||||
|
||||
// Register click
|
||||
_click_actions[_click_action_count] = _action_elements[i].id;
|
||||
_last_clicked_actions[_last_clicked_action_count] = _action_elements[i].id;
|
||||
_click_action_count += 1;
|
||||
_last_clicked_action_count += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// In case someone is keeping state on hold and wants to do stuff on release, even if cursor has moved
|
||||
for (int i = 0; i < _hold_action_count; i++) _release_actions[i] = _hold_actions[i];
|
||||
_release_action_count = _hold_action_count;
|
||||
_hold_action_count = 0;
|
||||
_holding_click = FALSE;
|
||||
};
|
||||
|
||||
void(vector pos, vector size, string id, void(float index, vector click_ratios) action) sui_action_element =
|
||||
{
|
||||
if (!_sui_draw_initialized)
|
||||
{
|
||||
print("^1sui error: adding sui elements before sui_pre_draw!\n^1 Always do your sui menus between sui_pre_draw and sui_draw!\n");
|
||||
}
|
||||
if (_action_elements_index >= MAX_ACTION_ELEMENTS)
|
||||
{
|
||||
// Silently fail here, sui will let us know another way, increase the count
|
||||
// so that the error in click/mousemove handlers prints correct numbers.
|
||||
_action_elements_index += 1;
|
||||
return;
|
||||
}
|
||||
|
||||
sui_transform_box(pos, size);
|
||||
|
||||
if (_sui_is_clipping)
|
||||
{
|
||||
vector oldpos = pos;
|
||||
pos_x = max(pos_x, _sui_clip_area_mins_x);
|
||||
pos_y = max(pos_y, _sui_clip_area_mins_y);
|
||||
|
||||
size -= pos - oldpos;
|
||||
|
||||
size_x -= bound(0, (pos_x + size_x - _sui_clip_area_maxs_x), size_x);
|
||||
size_y -= bound(0, (pos_y + size_y - _sui_clip_area_maxs_y), size_y);
|
||||
}
|
||||
|
||||
_action_elements[_action_elements_index].pos = pos;
|
||||
_action_elements[_action_elements_index].size = size;
|
||||
_action_elements[_action_elements_index].id = id;
|
||||
_action_elements[_action_elements_index].action = action;
|
||||
|
||||
_action_elements_index += 1;
|
||||
};
|
||||
|
||||
|
||||
// Input related stuff
|
||||
|
||||
string _sui_binding_command;
|
||||
string _sui_binding_command_name;
|
||||
|
||||
struct _input_t {
|
||||
float char;
|
||||
float scan;
|
||||
};
|
||||
const float MAX_INPUTS = 64;
|
||||
|
||||
_input_t _input_buffer[MAX_INPUTS];
|
||||
float _input_index;
|
||||
float _input_length;
|
||||
|
||||
|
||||
// probably good to use it like while (sui_get_input(char, scan)) { ... };
|
||||
float(__inout float char, __inout float scan) sui_get_input =
|
||||
{
|
||||
if (_input_index >= _input_length) return FALSE;
|
||||
|
||||
char = _input_buffer[_input_index].char;
|
||||
scan = _input_buffer[_input_index].scan;
|
||||
_input_index++;
|
||||
|
||||
return TRUE;
|
||||
};
|
||||
|
||||
// if 2 controls want to read the same input for some reason..
|
||||
void() sui_reread_input =
|
||||
{
|
||||
_input_index = 0;
|
||||
};
|
||||
|
||||
void() sui_clear_input =
|
||||
{
|
||||
_input_length = 0;
|
||||
_input_index = 0;
|
||||
};
|
||||
|
||||
float(float char, float scan) _sui_add_input =
|
||||
{
|
||||
// TODO check if input was listened, return FALSE if not
|
||||
if (_input_length >= MAX_INPUTS)
|
||||
{
|
||||
printf("^3sui warning: exceeded amount of per frame inputs count MAX_INPUTS = %.0f\n"
|
||||
"^3 - make sure sui_input_event isn't being called without sui_draw being called in update loop\n"
|
||||
"^3 - consider increasing MAX_INPUTS\n", MAX_INPUTS);
|
||||
return TRUE;
|
||||
}
|
||||
_input_buffer[_input_length].char = char;
|
||||
_input_buffer[_input_length].scan = scan;
|
||||
_input_length += 1;
|
||||
return TRUE;
|
||||
};
|
||||
|
||||
// Listen to a certain keycode if it was pressed, this way sui know it was requested
|
||||
float(float keycode) sui_listen_keycode_down =
|
||||
{
|
||||
return FALSE;
|
||||
};
|
||||
|
||||
// all text that was input between last and current frame
|
||||
string() sui_listen_text_input =
|
||||
{
|
||||
return "";
|
||||
};
|
||||
|
||||
void(float char, float scan, __inout string text, __inout float cursor) sui_handle_text_input =
|
||||
{
|
||||
float maxlen = 128;
|
||||
|
||||
string prev = text;
|
||||
string pre_cursor, post_cursor;
|
||||
float length = strlen(prev);
|
||||
if (char > 31 && char < 128) //an actual input
|
||||
{
|
||||
if (length >= maxlen) return;
|
||||
pre_cursor = substring(prev, 0, cursor);
|
||||
post_cursor = substring(prev, cursor, length);
|
||||
|
||||
text = sprintf("%s%s%s", pre_cursor, chr2str(char), post_cursor);
|
||||
cursor += 1;
|
||||
}
|
||||
else if (char == 8) // backspace
|
||||
{
|
||||
if (cursor <= 0) return;
|
||||
pre_cursor = substring(prev, 0, cursor - 1);
|
||||
post_cursor = substring(prev, cursor, length);
|
||||
cursor -= 1;
|
||||
cursor = max(0, cursor);
|
||||
text = strcat(pre_cursor, post_cursor);
|
||||
}
|
||||
else if (scan == K_DEL)
|
||||
{
|
||||
if (cursor >= length) return;
|
||||
pre_cursor = substring(prev, 0, cursor);
|
||||
post_cursor = substring(prev, cursor + 1, length);
|
||||
text = strcat(pre_cursor, post_cursor);
|
||||
}
|
||||
else if (char == 13 || char == 27) // enter or escape
|
||||
{
|
||||
// Commit and deselect...
|
||||
// Let's try a hack..
|
||||
_last_clicked_action_count = 0;
|
||||
}
|
||||
else if (scan == K_LEFTARROW)
|
||||
{
|
||||
cursor -= 1;
|
||||
cursor = max(0, cursor);
|
||||
}
|
||||
else if (scan == K_RIGHTARROW)
|
||||
{
|
||||
cursor += 1;
|
||||
cursor = min(strlen(prev), cursor);
|
||||
}
|
||||
};
|
||||
|
||||
void(float maxlen, __inout string text, __inout float cursor) sui_cap_input_length =
|
||||
{
|
||||
if (strlen(text) > maxlen)
|
||||
{
|
||||
text = substring(text, 0, strlen(text));
|
||||
cursor = strlen(text);
|
||||
}
|
||||
};
|
||||
|
||||
void(string command) _sui_unbind =
|
||||
{
|
||||
tokenize(findkeysforcommand(command));
|
||||
string keyname = keynumtostring(stof(argv(0)));
|
||||
string altkeyname = keynumtostring(stof(argv(1)));
|
||||
localcmd(sprintf("unbind %s\n", keyname));
|
||||
localcmd(sprintf("unbind %s\n", altkeyname));
|
||||
};
|
||||
|
||||
void(float scan, string command) _sui_do_keybind =
|
||||
{
|
||||
if (scan == K_ESCAPE)
|
||||
{
|
||||
_sui_binding_command = "";
|
||||
_sui_binding_command_name = "";
|
||||
return;
|
||||
}
|
||||
if (scan == K_BACKSPACE)
|
||||
{
|
||||
_sui_unbind(command);
|
||||
_sui_binding_command = "";
|
||||
_sui_binding_command_name = "";
|
||||
return;
|
||||
}
|
||||
string keyname = keynumtostring(scan);
|
||||
_sui_unbind(command);
|
||||
localcmd(sprintf("bind %s %s\n", keyname, command));
|
||||
_sui_binding_command = "";
|
||||
_sui_binding_command_name = "";
|
||||
};
|
||||
|
||||
void(string command, string command_name) sui_start_bind =
|
||||
{
|
||||
_sui_binding_command = command;
|
||||
_sui_binding_command_name = command_name;
|
||||
};
|
||||
|
||||
// void(float evtype, float scanx, float chary, float devid) sui_input_event
|
||||
// same args is CSQC_InputEvent.
|
||||
// return value tells you if sui used the event or not, in case you want to
|
||||
// not let engine handle it if it was used.
|
||||
// Sets all the internal sui action stuff, call it in CSQC_InputEvent
|
||||
float(float evtype, float scanx, float chary, float devid) sui_input_event =
|
||||
{
|
||||
switch (evtype)
|
||||
{
|
||||
case IE_MOUSEABS:
|
||||
_sui_mouse_move([scanx, chary]);
|
||||
return TRUE;
|
||||
case IE_MOUSEDELTA:
|
||||
// Big question mark...
|
||||
// maybe make our own delta based sui_cursor here..
|
||||
// maybe just ignore delta and let user fake mouseabs with their own
|
||||
// delta cursor by passing different params to this func...?
|
||||
// for MVP let's just use mouseabs only
|
||||
return FALSE;
|
||||
case IE_KEYDOWN:
|
||||
if (_sui_binding_command != "")
|
||||
{
|
||||
// Nothing
|
||||
return TRUE;
|
||||
}
|
||||
else if (scanx == K_MOUSE1)
|
||||
{
|
||||
_sui_mouse1_down();
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((scanx == K_ESCAPE || scanx == K_BACKSPACE) && _sui_binding_command != "")
|
||||
return TRUE;
|
||||
else if (scanx == K_ESCAPE)
|
||||
return FALSE;
|
||||
return _sui_add_input(chary, scanx);
|
||||
}
|
||||
case IE_KEYUP:
|
||||
if (_sui_binding_command != "")
|
||||
{
|
||||
_sui_do_keybind(scanx, _sui_binding_command);
|
||||
return TRUE;
|
||||
}
|
||||
else if (scanx == K_MOUSE1)
|
||||
{
|
||||
_sui_mouse1_up();
|
||||
return TRUE;
|
||||
}
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
};
|
||||
|
||||
|
||||
// void() sui_pre_draw
|
||||
// Resets state for sui actions so that no trouble happens.
|
||||
// Call it before your menu code per frame in your draw/updateview.
|
||||
void(float width, float height) sui_begin =
|
||||
{
|
||||
_action_elements_index = 0;
|
||||
_sui_draw_initialized = TRUE;
|
||||
|
||||
sui_reset_frame();
|
||||
sui_push_frame([0, 0], [width, height]);
|
||||
}
|
||||
|
||||
void() sui_draw_bind_overlay;
|
||||
|
||||
// void() sui_end
|
||||
// Call after your menu code per frame in your draw/updateview.
|
||||
void() sui_end =
|
||||
{
|
||||
// Todo: move overlay drawing elsewhere:
|
||||
sui_draw_bind_overlay();
|
||||
// Dirty part:
|
||||
_sui_draw_initialized = FALSE;
|
||||
// reset "once" type actions
|
||||
_click_action_count = 0;
|
||||
_release_action_count = 0;
|
||||
// empty input buffer
|
||||
sui_clear_input();
|
||||
};
|
||||
|
||||
|
||||
// Different draw components:
|
||||
|
||||
void(vector pos, vector size, vector color, float alpha, float flags) sui_fill =
|
||||
{
|
||||
sui_transform_box(pos, size);
|
||||
|
||||
drawfill(pos, size, color, alpha, flags);
|
||||
};
|
||||
|
||||
void(vector pos, vector size, string pic, vector color, float alpha, float flags) sui_pic =
|
||||
{
|
||||
sui_transform_box(pos, size);
|
||||
|
||||
drawpic(pos, pic, size, color, alpha, flags);
|
||||
};
|
||||
|
||||
void(vector pos, vector size, string pic, vector color, vector source_pos, vector source_size, float alpha, float flags) sui_subpic =
|
||||
{
|
||||
sui_transform_box(pos, size);
|
||||
|
||||
drawsubpic(pos, size, pic, source_pos, source_size, color, alpha, flags);
|
||||
};
|
||||
|
||||
// drawsubpic([g_width - 32, g_height - 32], [28, 28], "gfx/menu/social.tga", [0.5, 0], [0.5, 0.5], [1, 1, 1], 1); // YouTube
|
||||
// drawsubpic([g_width - 32, g_height - 64], [28, 28], "gfx/menu/social.tga", [0, 0.5], [0.5, 0.5], [1, 1, 1], 1); // Twitter
|
||||
// drawsubpic([g_width - 32, g_height - 96], [28, 28], "gfx/menu/social.tga", [0.5, 0.5], [0.5, 0.5], [1, 1, 1], 1); // Patreon
|
||||
|
||||
void(vector pos, vector size, float width, vector color, float alpha, float flags) sui_border_box =
|
||||
{
|
||||
sui_transform_box(pos, size);
|
||||
|
||||
// Top line
|
||||
drawfill(pos, [size_x, width], color, alpha, flags);
|
||||
// Bottom line
|
||||
drawfill([pos_x, pos_y + size_y - width], [size_x, width], color, alpha, flags);
|
||||
// Left line
|
||||
drawfill([pos_x, pos_y + width], [width, size_y - width * 2], color, alpha, flags);
|
||||
// Right line
|
||||
drawfill([pos_x + size_x - width, pos_y + width], [width, size_y - width * 2], color, alpha, flags);
|
||||
};
|
||||
|
||||
|
||||
void(vector pos, vector size, string text, vector color, float alpha, float flags) sui_text =
|
||||
{
|
||||
sui_transform_box(pos, [getTextWidth(text, size_x), size_y]);
|
||||
|
||||
Draw_String(pos, text, size, color, alpha, flags);
|
||||
};
|
||||
|
||||
void(float index, vector click_ratios) sui_noop = {};
|
||||
|
||||
void(float value) sui_slider_noop = {};
|
||||
|
||||
float(string id, vector pos, vector size, vector minmaxsteps, float value, void(float value) action) sui_slidercontrol =
|
||||
{
|
||||
sui_action_element(pos, size, id, sui_noop);
|
||||
float newvalue = value;
|
||||
|
||||
sui_transform_box(pos, size);
|
||||
// user is clicking and holding the slider
|
||||
if (sui_is_held(id))
|
||||
{
|
||||
float min = minmaxsteps[0];
|
||||
float max = minmaxsteps[1];
|
||||
float steps = minmaxsteps[2];
|
||||
float click_ratio = (_cursor_position_x - pos_x) / size_x;
|
||||
click_ratio = bound(0, click_ratio, 1);
|
||||
if (steps > 0) click_ratio = rint(click_ratio * steps) / steps;
|
||||
newvalue = min + click_ratio * (max - min);
|
||||
if (newvalue != value) action(newvalue);
|
||||
}
|
||||
return newvalue;
|
||||
};
|
||||
|
||||
void(string id, vector pos, vector size, __inout string text, __inout float cursor) sui_text_input =
|
||||
{
|
||||
sui_action_element(pos, size, id, sui_noop);
|
||||
if (sui_is_clicked(id)) cursor = strlen(text);
|
||||
if (sui_is_last_clicked(id))
|
||||
{
|
||||
float char = 0;
|
||||
float scan = 0;
|
||||
while(sui_get_input(char, scan)) sui_handle_text_input(char, scan, text, cursor);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
void(string id, vector size, vector contentsize, __inout vector offset, vector scrollbar_widths) sui_scrollbar =
|
||||
{
|
||||
vector maxoffset = contentsize - size;
|
||||
maxoffset_x = max(0, maxoffset_x);
|
||||
maxoffset_y = max(0, maxoffset_y);
|
||||
sui_push_frame([0, 0], size);
|
||||
float ofs;
|
||||
float length;
|
||||
vector barpos, barsize;
|
||||
float scan = 0;
|
||||
float char = 0;
|
||||
string barname;
|
||||
if (maxoffset_y > 0 && contentsize_y > 0)
|
||||
{
|
||||
sui_set_align([SUI_ALIGN_END, SUI_ALIGN_START]);
|
||||
sui_push_frame([0, 0], [scrollbar_widths_y, size_y]);
|
||||
ofs = (offset_y / contentsize_y) * size_y;
|
||||
length = (size_y / contentsize_y) * size_y;
|
||||
barpos = [0, ofs];
|
||||
barsize = [scrollbar_widths_y, length];
|
||||
barname = strcat(id, "vbar");
|
||||
|
||||
if (sui_is_held(barname))
|
||||
{
|
||||
vector anchor = barpos + _cursor_relative_click;
|
||||
sui_transform_point(anchor);
|
||||
float diff = _cursor_position_y - anchor_y;
|
||||
offset_y += (diff * contentsize_y) / size_y; // * contentsize_y; // (size_y / contentsize_y);
|
||||
}
|
||||
|
||||
sui_fill(barpos, barsize, '0.1 0.1 0.1' * (1 - sui_is_hovered(barname)), 0.66, 0);
|
||||
sui_action_element(barpos, barsize, barname, sui_noop);
|
||||
sui_pop_frame();
|
||||
}
|
||||
sui_pop_frame();
|
||||
};
|
||||
|
||||
void(string id, vector pos, vector size, vector contentsize, __inout vector offset, vector scrollbar_widths) sui_scroll_view_begin =
|
||||
{
|
||||
// make space for scrollbars
|
||||
sui_push_frame(pos, size - [scrollbar_widths_y, scrollbar_widths_x]);
|
||||
sui_action_element([0, 0], size, id, sui_noop);
|
||||
|
||||
if (sui_hover_index(id) > -1)
|
||||
{
|
||||
float scrollamount = 0;
|
||||
float char = 0;
|
||||
float scan = 0;
|
||||
sui_reread_input();
|
||||
while (sui_get_input(char, scan))
|
||||
{
|
||||
if (scan == K_MWHEELUP) scrollamount -= 20;
|
||||
if (scan == K_MWHEELDOWN) scrollamount += 20;
|
||||
}
|
||||
offset_y += scrollamount;
|
||||
}
|
||||
|
||||
vector maxoffset = contentsize - size;
|
||||
maxoffset_x = max(0, maxoffset_x);
|
||||
maxoffset_y = max(0, maxoffset_y);
|
||||
offset_x = bound(0, offset_x, maxoffset_x);
|
||||
offset_y = bound(0, offset_y, maxoffset_y);
|
||||
|
||||
sui_scrollbar(id, size, contentsize, offset, scrollbar_widths);
|
||||
|
||||
offset_x = bound(0, offset_x, maxoffset_x);
|
||||
offset_y = bound(0, offset_y, maxoffset_y);
|
||||
|
||||
sui_clip_to_frame();
|
||||
|
||||
|
||||
sui_push_frame(-1 * offset, contentsize);
|
||||
};
|
||||
|
||||
void() sui_scroll_view_end =
|
||||
{
|
||||
sui_pop_frame();
|
||||
sui_reset_clip();
|
||||
sui_pop_frame();
|
||||
};
|
||||
|
||||
float _sui_list_item_height;
|
||||
float _sui_list_first;
|
||||
float _sui_list_last;
|
||||
float _sui_list_pos;
|
||||
int _sui_list_index;
|
||||
void(string id, vector pos, vector size, vector itemsize, float numitems, __inout vector offset, vector scrollbar_widths) sui_list_view_begin =
|
||||
{
|
||||
vector contentsize = [itemsize_x, itemsize_y * numitems];
|
||||
sui_scroll_view_begin(id, pos, size, contentsize, offset, scrollbar_widths);
|
||||
|
||||
_sui_list_item_height = itemsize_y;
|
||||
float hidden_above = floor(offset_y / itemsize_y);
|
||||
_sui_list_first = max(0, hidden_above); // Index of first elem
|
||||
_sui_list_last = min(_sui_list_first + rint(size_y / itemsize_y) + 1, numitems);
|
||||
_sui_list_pos = hidden_above * itemsize_y;
|
||||
_sui_list_index = _sui_list_first;
|
||||
};
|
||||
|
||||
float(__inout vector pos) sui_list_item =
|
||||
{
|
||||
if (_sui_list_index >= _sui_list_last) return -1;
|
||||
pos = _sui_list_index * [0, _sui_list_item_height];
|
||||
_sui_list_index += 1;
|
||||
return _sui_list_index - 1;
|
||||
};
|
||||
|
||||
void() sui_list_view_end =
|
||||
{
|
||||
sui_scroll_view_end();
|
||||
};
|
||||
|
||||
string(string id, vector pos, vector size, string name, string command) sui_binder =
|
||||
{
|
||||
sui_action_element(pos, size, id, sui_noop);
|
||||
if (sui_is_released(id))
|
||||
{
|
||||
sui_start_bind(command, name);
|
||||
}
|
||||
|
||||
tokenize(findkeysforcommand(command));
|
||||
string keyname = keynumtostring(stof(argv(0)));
|
||||
if (keyname == "01") keyname = "unbound";
|
||||
|
||||
return keyname;
|
||||
};
|
||||
|
||||
void() sui_draw_bind_overlay =
|
||||
{
|
||||
if (_sui_binding_command != "")
|
||||
{
|
||||
vector size = sui_current_frame_size();
|
||||
sui_fill([0, 0], size, '0 0 0', 0.5, 0);
|
||||
sui_set_align([SUI_ALIGN_CENTER, SUI_ALIGN_CENTER]);
|
||||
float textsize = 16;
|
||||
sui_text([0, -16], [textsize, textsize], "Press a key for", '1 1 1', 1, 0);
|
||||
sui_text([0, 0], [textsize, textsize], sprintf("'%s'", _sui_binding_command_name), '1 1 1', 1, 0);
|
||||
sui_text([0, 16], [textsize - 4, textsize - 4], "ESC to cancel, BACKSPACE to remove", '1 1 1', 1, 0);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// -------------------- END OF SUI SYSTEM STUFF --------------------
|
Loading…
Reference in a new issue