1508 lines
42 KiB
C
Raw Normal View History

/* RetroArch - A frontend for libretro.
2015-01-07 17:46:50 +01:00
* Copyright (C) 2011-2015 - Daniel De Matteis
* Copyright (C) 2014-2015 - Jean-André Santoni
*
* RetroArch is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with RetroArch.
* If not, see <http://www.gnu.org/licenses/>.
*/
2015-01-26 10:54:13 +01:00
#include <stdint.h>
#include <stdlib.h>
#include <stddef.h>
#include <stdio.h>
#include <string.h>
2015-10-29 02:54:26 +07:00
#include <string/stdstring.h>
#include <limits.h>
#include <retro_log.h>
2015-06-05 18:22:15 +02:00
#include <compat/posix_string.h>
#include <file/file_path.h>
2015-10-03 03:15:47 +02:00
#include "menu_generic.h"
2015-01-10 04:53:37 +01:00
#include "../menu.h"
#include "../menu_driver.h"
2015-09-27 01:10:15 +02:00
#include "../menu_animation.h"
2015-07-09 18:39:40 +02:00
#include "../menu_hash.h"
#include "../menu_display.h"
#include "../../gfx/video_texture.h"
2015-07-09 18:39:40 +02:00
#include "../../runloop_data.h"
enum
{
GLUI_TEXTURE_POINTER = 0,
2015-10-27 22:49:48 +07:00
GLUI_TEXTURE_BACK,
2015-10-28 00:51:22 +07:00
GLUI_TEXTURE_SWITCH_ON,
GLUI_TEXTURE_SWITCH_OFF,
GLUI_TEXTURE_TAB_MAIN_ACTIVE,
GLUI_TEXTURE_TAB_PLAYLISTS_ACTIVE,
GLUI_TEXTURE_TAB_SETTINGS_ACTIVE,
GLUI_TEXTURE_TAB_MAIN_PASSIVE,
GLUI_TEXTURE_TAB_PLAYLISTS_PASSIVE,
GLUI_TEXTURE_TAB_SETTINGS_PASSIVE,
GLUI_TEXTURE_LAST
};
enum
{
GLUI_SYSTEM_TAB_MAIN = 0,
2015-10-29 17:23:04 +07:00
GLUI_SYSTEM_TAB_PLAYLISTS,
GLUI_SYSTEM_TAB_SETTINGS
};
2015-10-29 17:23:04 +07:00
#define GLUI_SYSTEM_TAB_END GLUI_SYSTEM_TAB_SETTINGS
struct glui_texture_item
{
GRuint id;
};
typedef struct glui_handle
{
2015-10-29 02:05:38 +07:00
unsigned tabs_height;
unsigned line_height;
2015-10-27 22:49:48 +07:00
unsigned icon_size;
unsigned margin;
2015-07-16 03:38:07 +02:00
unsigned glyph_width;
char box_message[PATH_MAX_LENGTH];
struct
{
struct
{
float alpha;
} arrow;
struct glui_texture_item bg;
struct glui_texture_item list[GLUI_TEXTURE_LAST];
GRuint white;
} textures;
struct
{
struct
{
unsigned idx;
unsigned idx_old;
} active;
float x_pos;
size_t selection_ptr_old;
size_t selection_ptr;
} categories;
gfx_font_raster_block_t list_block;
} glui_handle_t;
static const GRfloat glui_vertexes[] = {
0, 0,
1, 0,
0, 1,
1, 1
};
static const GRfloat glui_tex_coords[] = {
0, 1,
1, 1,
0, 0,
1, 0
};
static void glui_context_reset_textures(glui_handle_t *glui, const char *iconpath)
{
unsigned i;
for (i = 0; i < GLUI_TEXTURE_LAST; i++)
{
struct texture_image ti = {0};
char path[PATH_MAX_LENGTH] = {0};
switch(i)
{
case GLUI_TEXTURE_POINTER:
fill_pathname_join(path, iconpath, "pointer.png", sizeof(path));
break;
2015-10-27 22:49:48 +07:00
case GLUI_TEXTURE_BACK:
fill_pathname_join(path, iconpath, "back.png", sizeof(path));
break;
2015-10-28 00:51:22 +07:00
case GLUI_TEXTURE_SWITCH_ON:
fill_pathname_join(path, iconpath, "on.png", sizeof(path));
break;
case GLUI_TEXTURE_SWITCH_OFF:
fill_pathname_join(path, iconpath, "off.png", sizeof(path));
break;
case GLUI_TEXTURE_TAB_MAIN_ACTIVE:
fill_pathname_join(path, iconpath, "main_tab_active.png", sizeof(path));
break;
case GLUI_TEXTURE_TAB_PLAYLISTS_ACTIVE:
fill_pathname_join(path, iconpath, "playlists_tab_active.png", sizeof(path));
break;
case GLUI_TEXTURE_TAB_SETTINGS_ACTIVE:
fill_pathname_join(path, iconpath, "settings_tab_active.png", sizeof(path));
break;
case GLUI_TEXTURE_TAB_MAIN_PASSIVE:
fill_pathname_join(path, iconpath, "main_tab_passive.png", sizeof(path));
break;
case GLUI_TEXTURE_TAB_PLAYLISTS_PASSIVE:
fill_pathname_join(path, iconpath, "playlists_tab_passive.png", sizeof(path));
break;
case GLUI_TEXTURE_TAB_SETTINGS_PASSIVE:
fill_pathname_join(path, iconpath, "settings_tab_passive.png", sizeof(path));
break;
}
if (path[0] == '\0' || !path_file_exists(path))
continue;
texture_image_load(&ti, path);
glui->textures.list[i].id = video_texture_load(&ti,
TEXTURE_BACKEND_OPENGL, TEXTURE_FILTER_MIPMAP_LINEAR);
texture_image_free(&ti);
}
}
2015-10-27 22:49:48 +07:00
static void glui_draw_icon(gl_t *gl, glui_handle_t *glui,
GRuint texture,
float x, float y,
unsigned width, unsigned height,
float rotation, float scale_factor,
GRfloat *color)
{
struct gfx_coords coords;
math_matrix_4x4 mymat, mrot, mscal;
2015-11-01 19:28:12 +01:00
menu_display_blend_begin(gl);
2015-10-27 22:49:48 +07:00
matrix_4x4_rotate_z(&mrot, rotation);
matrix_4x4_multiply(&mymat, &mrot, &gl->mvp_no_rot);
matrix_4x4_scale(&mscal, scale_factor, scale_factor, 1);
matrix_4x4_multiply(&mymat, &mscal, &mymat);
coords.vertices = 4;
coords.vertex = glui_vertexes;
2015-10-27 22:49:48 +07:00
coords.tex_coord = glui_tex_coords;
coords.lut_tex_coord = glui_tex_coords;
coords.color = (const float*)color;
menu_display_draw_frame(
x,
height - y - glui->icon_size,
glui->icon_size,
glui->icon_size,
gl->shader, &coords, &mymat, texture, 4,
2015-10-27 22:49:48 +07:00
MENU_DISPLAY_PRIM_TRIANGLESTRIP);
2015-11-01 19:28:12 +01:00
menu_display_blend_end(gl);
2015-10-27 22:49:48 +07:00
}
static void glui_blit_line(float x, float y, unsigned width, unsigned height,
2015-04-21 16:59:02 +02:00
const char *message, uint32_t color, enum text_alignment text_align)
{
2015-09-26 23:37:25 +02:00
int font_size;
void *fb_buf = NULL;
2015-06-12 16:20:45 +02:00
glui_handle_t *glui = NULL;
2015-06-05 18:12:57 +02:00
struct font_params params = {0};
2015-06-12 16:20:45 +02:00
menu_handle_t *menu = menu_driver_get_ptr();
if (!menu)
return;
glui = (glui_handle_t*)menu->userdata;
2015-09-26 23:37:25 +02:00
menu_display_ctl(MENU_DISPLAY_CTL_FONT_SIZE, &font_size);
params.x = x / width;
2015-09-26 23:37:25 +02:00
params.y = 1.0f - (y + glui->line_height / 2 + font_size / 3)
2015-07-08 17:26:51 +02:00
/ height;
2015-01-19 06:44:46 +01:00
params.scale = 1.0;
2015-03-14 19:44:27 -03:00
params.color = color;
params.full_screen = true;
2015-04-04 21:26:11 +02:00
params.text_align = text_align;
2015-01-19 06:44:46 +01:00
menu_display_ctl(MENU_DISPLAY_CTL_FONT_BUF, &fb_buf);
video_driver_set_osd_msg(message, &params, fb_buf);
}
2015-04-04 21:26:11 +02:00
static void glui_render_quad(gl_t *gl, int x, int y, int w, int h,
2015-09-06 20:38:45 +02:00
unsigned width, unsigned height,
2015-09-06 20:36:17 +02:00
GRfloat *coord_color)
2014-10-27 00:55:14 +01:00
{
2015-07-12 03:57:06 +02:00
struct gfx_coords coords;
menu_handle_t *menu = menu_driver_get_ptr();
glui_handle_t *glui = (glui_handle_t*)menu->userdata;
2015-06-30 18:53:57 +02:00
coords.vertices = 4;
coords.vertex = glui_vertexes;
coords.tex_coord = glui_tex_coords;
coords.lut_tex_coord = glui_tex_coords;
2015-09-06 20:36:17 +02:00
coords.color = coord_color;
2014-10-27 00:55:14 +01:00
2015-11-01 19:28:12 +01:00
menu_display_blend_begin(gl);
menu_display_draw_frame(
2015-09-06 18:16:24 +02:00
x,
height - y - h,
w,
h,
gl->shader, &coords,
&gl->mvp_no_rot, glui->textures.white, 4,
2015-10-24 07:51:33 +02:00
MENU_DISPLAY_PRIM_TRIANGLESTRIP );
2014-10-27 00:55:14 +01:00
gl->coords.color = gl->white_color_ptr;
2015-11-01 19:28:12 +01:00
menu_display_blend_end(gl);
2014-10-27 00:55:14 +01:00
}
2015-09-06 20:38:45 +02:00
static void glui_draw_scrollbar(gl_t *gl, unsigned width, unsigned height, GRfloat *coord_color)
2015-04-21 09:47:02 +07:00
{
2015-09-25 21:52:04 +02:00
unsigned header_height;
float content_height, total_height, scrollbar_width, scrollbar_height, y;
2015-06-14 15:34:05 +02:00
glui_handle_t *glui = NULL;
menu_handle_t *menu = menu_driver_get_ptr();
2015-04-21 09:47:02 +07:00
if (!menu)
return;
2015-09-25 21:52:04 +02:00
menu_display_ctl(MENU_DISPLAY_CTL_HEADER_HEIGHT, &header_height);
2015-04-21 16:59:02 +02:00
glui = (glui_handle_t*)menu->userdata;
2015-05-15 00:03:06 +02:00
content_height = menu_entries_get_end() * glui->line_height;
2015-10-29 02:05:38 +07:00
total_height = height - header_height - glui->tabs_height;
scrollbar_height = total_height / (content_height / total_height) - (header_height / 6);
2015-04-21 16:59:02 +02:00
y = total_height * menu->scroll_y / content_height;
2015-04-21 09:47:02 +07:00
if (content_height >= total_height)
2015-09-28 23:00:22 +02:00
{
scrollbar_width = (header_height / 12);
if (scrollbar_height <= header_height / 12)
scrollbar_height = header_height / 12;
2015-09-28 23:00:22 +02:00
glui_render_quad(gl,
width - scrollbar_width - (header_height / 12),
2015-10-29 17:31:13 +07:00
header_height + y + (header_height / 12),
scrollbar_width,
scrollbar_height,
2015-09-06 20:38:45 +02:00
width, height,
2015-09-06 20:36:17 +02:00
coord_color);
2015-09-28 23:00:22 +02:00
}
2015-04-21 09:47:02 +07:00
}
static void glui_get_message(const char *message)
2014-09-15 12:36:52 +02:00
{
glui_handle_t *glui = NULL;
menu_handle_t *menu = menu_driver_get_ptr();
2014-09-15 12:36:52 +02:00
if (!menu)
return;
if (!message || !*message)
2014-09-15 12:36:52 +02:00
return;
glui = (glui_handle_t*)menu->userdata;
2015-02-02 18:51:48 +01:00
if (glui)
strlcpy(glui->box_message, message, sizeof(glui->box_message));
2014-09-15 12:36:52 +02:00
}
static void glui_render_messagebox(const char *message)
{
unsigned i;
unsigned width, height;
2015-03-16 16:57:27 +01:00
uint32_t normal_color;
2015-09-26 23:37:25 +02:00
int x, y, font_size;
struct string_list *list = NULL;
2015-06-05 18:12:57 +02:00
menu_handle_t *menu = menu_driver_get_ptr();
settings_t *settings = config_get_ptr();
2014-09-15 12:36:52 +02:00
if (!menu || !menu->userdata)
return;
list = (struct string_list*)string_split(message, "\n");
2014-09-15 12:36:52 +02:00
if (!list)
return;
2014-09-15 12:36:52 +02:00
if (list->elems == 0)
2015-02-02 18:51:48 +01:00
goto end;
2014-09-15 12:36:52 +02:00
video_driver_get_size(&width, &height);
2015-09-26 23:37:25 +02:00
menu_display_ctl(MENU_DISPLAY_CTL_FONT_SIZE, &font_size);
x = width / 2;
2015-09-26 23:37:25 +02:00
y = height / 2 - list->size * font_size / 2;
2015-03-20 22:22:06 +01:00
normal_color = FONT_COLOR_ARGB_TO_RGBA(settings->menu.entry_normal_color);
2014-09-15 12:36:52 +02:00
for (i = 0; i < list->size; i++)
{
const char *msg = list->elems[i].data;
2015-02-02 18:51:48 +01:00
if (msg)
2015-09-26 23:37:25 +02:00
glui_blit_line(x, y + i * font_size,
width, height,
2015-06-25 08:26:59 +02:00
msg, normal_color, TEXT_ALIGN_CENTER);
2014-09-15 12:36:52 +02:00
}
2015-02-02 18:51:48 +01:00
end:
2014-09-15 12:36:52 +02:00
string_list_free(list);
}
static void glui_render(void)
{
2015-09-25 23:47:01 +02:00
float delta_time, dt;
2015-04-04 21:26:11 +02:00
int bottom;
2015-09-25 21:52:04 +02:00
unsigned width, height, header_height;
glui_handle_t *glui = NULL;
menu_handle_t *menu = menu_driver_get_ptr();
settings_t *settings = config_get_ptr();
2015-05-01 09:35:27 -03:00
if (!menu || !menu->userdata)
return;
video_driver_get_size(&width, &height);
glui = (glui_handle_t*)menu->userdata;
2015-09-25 23:47:01 +02:00
2015-09-25 23:37:02 +02:00
menu_animation_ctl(MENU_ANIMATION_CTL_DELTA_TIME, &delta_time);
2015-09-25 23:47:01 +02:00
dt = delta_time / IDEAL_DT;
menu_animation_ctl(MENU_ANIMATION_CTL_UPDATE, &dt);
2015-04-20 21:22:55 +07:00
menu_display_ctl(MENU_DISPLAY_CTL_SET_WIDTH, &width);
menu_display_ctl(MENU_DISPLAY_CTL_SET_HEIGHT, &height);
2015-09-25 21:52:04 +02:00
menu_display_ctl(MENU_DISPLAY_CTL_HEADER_HEIGHT, &header_height);
2015-04-04 21:26:11 +02:00
if (settings->menu.pointer.enable)
{
int16_t pointer_y = menu_input_pointer_state(MENU_POINTER_Y_AXIS);
float old_accel_val, new_accel_val;
2015-09-24 19:56:53 +02:00
unsigned new_pointer_val =
(pointer_y - glui->line_height + menu->scroll_y - 16)
2015-07-08 17:26:51 +02:00
/ glui->line_height;
2015-04-04 21:26:11 +02:00
2015-09-26 02:52:05 +02:00
menu_input_ctl(MENU_INPUT_CTL_POINTER_ACCEL_READ, &old_accel_val);
menu_input_ctl(MENU_INPUT_CTL_POINTER_PTR, &new_pointer_val);
2015-09-24 19:56:53 +02:00
menu->scroll_y -= old_accel_val / 60.0;
new_accel_val = old_accel_val * 0.96;
2015-09-26 02:52:05 +02:00
menu_input_ctl(MENU_INPUT_CTL_POINTER_ACCEL_WRITE, &new_accel_val);
2015-04-04 21:26:11 +02:00
}
if (settings->menu.mouse.enable)
{
2015-09-24 23:33:41 +02:00
int16_t mouse_y = menu_input_mouse_state(MENU_MOUSE_Y_AXIS);
2015-09-24 17:34:44 +02:00
unsigned new_pointer_val =
(mouse_y - glui->line_height + menu->scroll_y - 16)
/ glui->line_height;
menu_input_ctl(MENU_INPUT_CTL_MOUSE_PTR, &new_pointer_val);
2015-04-04 21:26:11 +02:00
}
2015-04-04 21:26:11 +02:00
if (menu->scroll_y < 0)
menu->scroll_y = 0;
2015-05-15 00:03:06 +02:00
bottom = menu_entries_get_end() * glui->line_height
2015-10-29 02:05:38 +07:00
- height + header_height + glui->tabs_height;
2015-04-04 21:26:11 +02:00
if (menu->scroll_y > bottom)
menu->scroll_y = bottom;
2015-05-15 00:03:06 +02:00
if (menu_entries_get_end() * glui->line_height
2015-10-29 02:05:38 +07:00
< height - header_height - glui->tabs_height)
2015-04-04 21:26:11 +02:00
menu->scroll_y = 0;
2015-07-14 00:38:16 +02:00
if (menu_entries_get_end() < height / glui->line_height)
menu_entries_set_start(0);
else
menu_entries_set_start(menu->scroll_y / glui->line_height);
}
2015-10-28 00:51:22 +07:00
static void glui_render_label_value(glui_handle_t *glui, gl_t *gl,
int y, unsigned width, unsigned height,
2015-10-28 00:51:22 +07:00
uint64_t index, uint32_t color, bool selected, const char *label,
const char *value, GRfloat *pure_white)
{
char label_str[PATH_MAX_LENGTH];
char value_str[PATH_MAX_LENGTH];
int value_len = strlen(value);
2015-07-16 03:38:07 +02:00
int ticker_limit = 0;
2015-09-06 16:20:17 +02:00
size_t usable_width = 0;
2015-10-28 00:51:22 +07:00
GRuint texture_switch = 0;
bool do_draw_text = false;
uint32_t hash_value = 0;
label_str[0] = '\0';
value_str[0] = '\0';
2015-07-16 03:38:07 +02:00
usable_width = width - (glui->margin * 2);
2015-07-16 03:38:07 +02:00
if (value_len * glui->glyph_width > usable_width / 2)
value_len = (usable_width/2) / glui->glyph_width;
ticker_limit = (usable_width / glui->glyph_width) - (value_len + 2);
menu_animation_ticker_str(label_str, ticker_limit, index, label, selected);
menu_animation_ticker_str(value_str, value_len, index, value, selected);
glui_blit_line(glui->margin, y, width, height, label_str, color, TEXT_ALIGN_LEFT);
2015-10-28 00:51:22 +07:00
hash_value = menu_hash_calculate(value);
if (!strcmp(value, "disabled") ||
!strcmp(value, "off"))
2015-10-28 00:51:22 +07:00
{
if (glui->textures.list[GLUI_TEXTURE_SWITCH_OFF].id)
texture_switch = glui->textures.list[GLUI_TEXTURE_SWITCH_OFF].id;
else
do_draw_text = true;
}
else if (!strcmp(value, "enabled") ||
!strcmp(value, "on"))
{
if (glui->textures.list[GLUI_TEXTURE_SWITCH_ON].id)
texture_switch = glui->textures.list[GLUI_TEXTURE_SWITCH_ON].id;
else
2015-10-28 00:51:22 +07:00
do_draw_text = true;
}
else
{
switch (hash_value)
{
case MENU_VALUE_COMP:
break;
case MENU_VALUE_MORE:
break;
case MENU_VALUE_CORE:
break;
case MENU_VALUE_RDB:
break;
case MENU_VALUE_CURSOR:
break;
case MENU_VALUE_FILE:
break;
case MENU_VALUE_DIR:
break;
case MENU_VALUE_MUSIC:
break;
case MENU_VALUE_IMAGE:
break;
case MENU_VALUE_MOVIE:
break;
case MENU_VALUE_ON:
if (glui->textures.list[GLUI_TEXTURE_SWITCH_ON].id)
texture_switch = glui->textures.list[GLUI_TEXTURE_SWITCH_ON].id;
else
do_draw_text = true;
break;
case MENU_VALUE_OFF:
if (glui->textures.list[GLUI_TEXTURE_SWITCH_OFF].id)
texture_switch = glui->textures.list[GLUI_TEXTURE_SWITCH_OFF].id;
else
do_draw_text = true;
break;
default:
do_draw_text = true;
break;
}
2015-10-28 00:51:22 +07:00
}
if (do_draw_text)
glui_blit_line(width - glui->margin, y, width, height, value_str, color, TEXT_ALIGN_RIGHT);
if (texture_switch)
glui_draw_icon(gl, glui, texture_switch,
width - glui->margin - glui->icon_size, y, width, height, 0, 1, &pure_white[0]);
}
2015-10-28 00:51:22 +07:00
static void glui_render_menu_list(glui_handle_t *glui, gl_t *gl,
unsigned width, unsigned height,
2015-05-20 03:09:28 +02:00
menu_handle_t *menu,
2015-05-07 10:15:33 +02:00
uint32_t normal_color,
2015-10-28 00:51:22 +07:00
uint32_t hover_color,
GRfloat *pure_white)
{
2015-09-25 21:52:04 +02:00
unsigned header_height;
2015-07-14 00:38:16 +02:00
size_t i = 0;
2015-08-03 23:01:07 +02:00
uint64_t *frame_count = video_driver_get_frame_count();
2015-07-14 00:38:16 +02:00
size_t end = menu_entries_get_end();
2015-09-25 14:07:01 +02:00
if (!menu_display_ctl(MENU_DISPLAY_CTL_UPDATE_PENDING, NULL))
2015-04-24 22:46:19 +02:00
return;
2015-09-25 21:52:04 +02:00
menu_display_ctl(MENU_DISPLAY_CTL_HEADER_HEIGHT, &header_height);
glui->list_block.carr.coords.vertices = 0;
for (i = menu_entries_get_start(); i < end; i++)
{
2015-09-25 14:57:37 +02:00
int y;
size_t selection;
bool entry_selected;
2015-07-14 00:38:16 +02:00
menu_entry_t entry;
2015-09-25 14:57:37 +02:00
if (!menu_navigation_ctl(MENU_NAVIGATION_CTL_GET_SELECTION, &selection))
continue;
2015-10-29 17:31:13 +07:00
y = header_height - menu->scroll_y + (glui->line_height * i);
2015-11-01 22:20:49 +07:00
if ((y - (int)glui->line_height) > (int)height
|| ((y + (int)glui->line_height) < 0))
continue;
2015-10-27 23:52:20 +01:00
menu_entry_get(&entry, 0, i, NULL, true);
2015-07-14 00:38:16 +02:00
2015-09-25 14:57:37 +02:00
entry_selected = selection == i;
2015-10-28 00:51:22 +07:00
glui_render_label_value(glui, gl, y, width, height, *frame_count / 40,
entry_selected ? hover_color : normal_color, entry_selected,
2015-10-28 00:51:22 +07:00
entry.path, entry.value, pure_white);
}
}
static void glui_draw_cursor(gl_t *gl, glui_handle_t *glui,
GRfloat *color,
float x, float y, unsigned width, unsigned height)
{
struct gfx_coords coords;
math_matrix_4x4 mymat, mrot;
matrix_4x4_rotate_z(&mrot, 0);
matrix_4x4_multiply(&mymat, &mrot, &gl->mvp_no_rot);
coords.vertices = 4;
coords.vertex = glui_vertexes;
coords.tex_coord = glui_tex_coords;
coords.lut_tex_coord = glui_tex_coords;
coords.color = (const float*)color;
2015-11-01 19:28:12 +01:00
menu_display_blend_begin(gl);
2015-11-01 19:26:24 +01:00
menu_display_draw_frame(
x - 32,
height - y - 32,
64,
64,
gl->shader, &coords, &mymat,
glui->textures.list[GLUI_TEXTURE_POINTER].id, 4,
MENU_DISPLAY_PRIM_TRIANGLESTRIP);
2015-11-01 19:26:24 +01:00
2015-11-01 19:28:12 +01:00
menu_display_blend_end(gl);
}
static size_t glui_list_get_size(void *data, menu_list_type_t type)
{
size_t list_size = 0;
switch (type)
{
case MENU_LIST_PLAIN:
list_size = menu_entries_get_stack_size(0);
break;
case MENU_LIST_TABS:
list_size = GLUI_SYSTEM_TAB_END;
break;
default:
break;
}
return list_size;
}
static void glui_frame(void)
{
2015-10-27 13:00:18 +01:00
unsigned header_height;
bool display_kb;
2015-10-27 16:44:56 +07:00
GRfloat black_bg[16] = {
0, 0, 0, 0.75,
0, 0, 0, 0.75,
0, 0, 0, 0.75,
0, 0, 0, 0.75,
};
GRfloat blue_bg[16] = {
0.13, 0.59, 0.95, 1,
0.13, 0.59, 0.95, 1,
0.13, 0.59, 0.95, 1,
0.13, 0.59, 0.95, 1,
};
GRfloat lightblue_bg[16] = {
0.89, 0.95, 0.99, 1.00,
0.89, 0.95, 0.99, 1.00,
0.89, 0.95, 0.99, 1.00,
0.89, 0.95, 0.99, 1.00,
2015-10-27 16:44:56 +07:00
};
2015-10-28 00:51:22 +07:00
GRfloat pure_white[16]= {
1, 1, 1, 1,
1, 1, 1, 1,
1, 1, 1, 1,
1, 1, 1, 1,
};
2015-10-27 16:44:56 +07:00
GRfloat white_bg[16]= {
0.98, 0.98, 0.98, 1,
0.98, 0.98, 0.98, 1,
0.98, 0.98, 0.98, 1,
0.98, 0.98, 0.98, 1,
2015-10-27 16:44:56 +07:00
};
GRfloat white_transp_bg[16]= {
0.98, 0.98, 0.98, 0.90,
0.98, 0.98, 0.98, 0.90,
0.98, 0.98, 0.98, 0.90,
0.98, 0.98, 0.98, 0.90,
2015-10-27 16:44:56 +07:00
};
GRfloat grey_bg[16]= {
0.78, 0.78, 0.78, 1,
0.78, 0.78, 0.78, 1,
0.78, 0.78, 0.78, 1,
0.78, 0.78, 0.78, 1,
2015-10-27 16:44:56 +07:00
};
GRfloat shadow_bg[16]= {
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0.2,
0, 0, 0, 0.2,
};
2015-10-29 02:05:38 +07:00
unsigned width, height, ticker_limit, i, tab_width;
char msg[PATH_MAX_LENGTH];
char title[PATH_MAX_LENGTH];
char title_buf[PATH_MAX_LENGTH];
2015-09-25 14:57:37 +02:00
size_t selection;
2015-10-28 09:54:08 +07:00
size_t title_margin;
2015-06-12 16:20:45 +02:00
gl_t *gl = NULL;
glui_handle_t *glui = NULL;
const struct font_renderer *font_driver = NULL;
2015-06-12 16:20:45 +02:00
driver_t *driver = driver_get_ptr();
menu_handle_t *menu = menu_driver_get_ptr();
settings_t *settings = config_get_ptr();
2015-08-03 23:01:07 +02:00
uint64_t *frame_count = video_driver_get_frame_count();
const uint32_t normal_color = 0x212121ff;
const uint32_t hover_color = 0x212121ff;
2015-10-27 16:44:56 +07:00
const uint32_t title_color = 0xffffffff;
2015-10-29 17:40:06 +07:00
const uint32_t activetab_color = 0x0096f2ff;
const uint32_t passivetab_color = 0x9e9e9eff;
bool background_rendered = false;
bool libretro_running = menu_display_ctl(MENU_DISPLAY_CTL_LIBRETRO_RUNNING, NULL);
2015-10-29 13:32:58 +01:00
(void)passivetab_color;
(void)activetab_color;
2015-05-01 09:35:27 -03:00
if (!menu || !menu->userdata)
return;
gl = (gl_t*)video_driver_get_ptr(NULL);
if (!gl)
return;
glui = (glui_handle_t*)menu->userdata;
msg[0] = '\0';
title[0] = '\0';
title_buf[0] = '\0';
video_driver_get_size(&width, &height);
2015-09-25 13:27:15 +02:00
menu_display_ctl(MENU_DISPLAY_CTL_SET_VIEWPORT, NULL);
2015-09-25 21:52:04 +02:00
menu_display_ctl(MENU_DISPLAY_CTL_HEADER_HEIGHT, &header_height);
2015-11-01 19:49:19 +01:00
if (libretro_running)
{
2015-11-01 19:49:19 +01:00
menu_display_frame_background(menu, settings,
gl, width, height,
glui->textures.white, 0.75f, false,
&white_transp_bg[0], &white_bg[0],
&glui_vertexes[0], &glui_tex_coords[0], 4,
2015-11-01 19:49:19 +01:00
MENU_DISPLAY_PRIM_TRIANGLESTRIP);
}
else
{
menu_display_clear_color(gl, 1.0f, 1.0f, 1.0f, 0.75f);
if (glui->textures.bg.id)
{
background_rendered = true;
2015-11-01 21:02:45 +01:00
/* Set new opacity for transposed white background */
white_transp_bg[3] = 0.30;
white_transp_bg[7] = 0.30;
white_transp_bg[11] = 0.30;
white_transp_bg[15] = 0.30;
menu_display_frame_background(menu, settings,
gl, width, height,
glui->textures.bg.id, 0.75f, true,
&white_transp_bg[0], &white_bg[0],
&glui_vertexes[0], &glui_tex_coords[0], 4,
MENU_DISPLAY_PRIM_TRIANGLESTRIP);
2015-11-01 21:02:45 +01:00
/* Restore opacity of transposed white background */
white_transp_bg[3] = 0.90;
white_transp_bg[7] = 0.90;
white_transp_bg[11] = 0.90;
white_transp_bg[15] = 0.90;
}
}
2015-05-15 00:07:07 +02:00
menu_entries_get_title(title, sizeof(title));
font_driver = driver->font_osd_driver;
2015-04-24 22:46:19 +02:00
2015-09-25 14:57:37 +02:00
if (!menu_navigation_ctl(MENU_NAVIGATION_CTL_GET_SELECTION, &selection))
return;
if (background_rendered || libretro_running)
{
lightblue_bg[3] = 0.75;
lightblue_bg[7] = 0.75;
lightblue_bg[11] = 0.75;
lightblue_bg[15] = 0.75;
}
else
{
lightblue_bg[3] = 1.00;
lightblue_bg[7] = 1.00;
lightblue_bg[11] = 1.00;
lightblue_bg[15] = 1.00;
}
2015-10-28 15:56:45 +01:00
/* highlighted entry */
glui_render_quad(gl, 0,
2015-10-29 17:31:13 +07:00
header_height - menu->scroll_y + glui->line_height *
2015-09-25 14:57:37 +02:00
selection, width, glui->line_height,
2015-09-06 20:38:45 +02:00
width, height,
2015-10-27 16:44:56 +07:00
&lightblue_bg[0]);
menu_display_font_bind_block(menu, font_driver, &glui->list_block);
2015-10-28 00:51:22 +07:00
glui_render_menu_list(glui, gl, width, height, menu, normal_color, hover_color, &pure_white[0]);
2015-10-27 16:44:56 +07:00
menu_display_font_flush_block(menu, font_driver);
2015-09-25 23:42:00 +02:00
menu_animation_ctl(MENU_ANIMATION_CTL_SET_ACTIVE, NULL);
2015-04-04 21:26:11 +02:00
2015-10-28 15:56:45 +01:00
/* header */
glui_render_quad(gl, 0, 0, width,
2015-09-25 21:52:04 +02:00
header_height,
2015-09-06 20:38:45 +02:00
width, height,
2015-10-27 16:44:56 +07:00
&blue_bg[0]);
2015-04-04 21:26:11 +02:00
/* display tabs if depth equal one, if not hide them */
if (glui_list_get_size(menu, MENU_LIST_PLAIN) == 1)
{
float scale_factor;
menu_display_ctl(MENU_DISPLAY_CTL_GET_DPI, &scale_factor);
glui->tabs_height = scale_factor / 3;
/* tabs background */
glui_render_quad(gl, 0, height - glui->tabs_height, width,
glui->tabs_height,
width, height,
&white_bg[0]);
2015-10-29 17:40:06 +07:00
/* tabs separator */
glui_render_quad(gl, 0, height - glui->tabs_height, width,
1,
width, height,
&grey_bg[0]);
2015-10-29 02:05:38 +07:00
for (i = 0; i <= GLUI_SYSTEM_TAB_END; i++)
2015-10-29 02:34:52 +07:00
{
unsigned tab_icon = GLUI_TEXTURE_TAB_MAIN_PASSIVE;
switch (i)
{
case GLUI_SYSTEM_TAB_MAIN:
tab_icon = (i == glui->categories.selection_ptr)
? GLUI_TEXTURE_TAB_MAIN_ACTIVE
: GLUI_TEXTURE_TAB_MAIN_PASSIVE;
break;
case GLUI_SYSTEM_TAB_PLAYLISTS:
tab_icon = (i == glui->categories.selection_ptr)
? GLUI_TEXTURE_TAB_PLAYLISTS_ACTIVE
: GLUI_TEXTURE_TAB_PLAYLISTS_PASSIVE;
break;
case GLUI_SYSTEM_TAB_SETTINGS:
tab_icon = (i == glui->categories.selection_ptr)
? GLUI_TEXTURE_TAB_SETTINGS_ACTIVE
: GLUI_TEXTURE_TAB_SETTINGS_PASSIVE;
break;
}
glui_draw_icon(gl, glui, glui->textures.list[tab_icon].id,
width / (GLUI_SYSTEM_TAB_END+1) * (i+0.5) - glui->icon_size/2,
height - glui->tabs_height,
width, height, 0, 1, &pure_white[0]);
2015-10-29 02:34:52 +07:00
}
/* active tab marker */
tab_width = width / (GLUI_SYSTEM_TAB_END+1);
glui_render_quad(gl, glui->categories.selection_ptr * tab_width,
height - (header_height/16),
tab_width,
header_height/16,
width, height,
&blue_bg[0]);
}
else
{
glui->tabs_height = 0;
2015-10-29 02:05:38 +07:00
}
2015-10-29 17:31:13 +07:00
glui_render_quad(gl, 0, header_height, width,
header_height/12,
width, height,
&shadow_bg[0]);
2015-10-28 09:54:08 +07:00
title_margin = glui->margin;
2015-04-04 21:26:11 +02:00
2015-05-15 00:16:39 +02:00
if (menu_entries_show_back())
2015-10-28 09:54:08 +07:00
{
title_margin = glui->icon_size;
2015-10-27 22:49:48 +07:00
glui_draw_icon(gl, glui, glui->textures.list[GLUI_TEXTURE_BACK].id,
0, 0, width, height, 0, 1, &pure_white[0]);
2015-10-28 09:54:08 +07:00
}
ticker_limit = (width - glui->margin*2) / glui->glyph_width;
menu_animation_ticker_str(title_buf, ticker_limit,
*frame_count / 100, title, true);
2015-10-28 15:56:45 +01:00
/* Title */
2015-10-28 09:54:08 +07:00
glui_blit_line(title_margin, 0, width, height, title_buf,
title_color, TEXT_ALIGN_LEFT);
2015-04-04 21:26:11 +02:00
2015-10-27 16:44:56 +07:00
glui_draw_scrollbar(gl, width, height, &grey_bg[0]);
2015-04-21 09:47:02 +07:00
2015-09-26 02:52:05 +02:00
menu_input_ctl(MENU_INPUT_CTL_KEYBOARD_DISPLAY, &display_kb);
if (display_kb)
{
const char *str = NULL, *label = NULL;
2015-09-26 02:52:05 +02:00
menu_input_ctl(MENU_INPUT_CTL_KEYBOARD_BUFF_PTR, &str);
menu_input_ctl(MENU_INPUT_CTL_KEYBOARD_LABEL, &label);
2015-06-13 00:09:09 +02:00
if (!str)
str = "";
2015-09-06 20:38:45 +02:00
glui_render_quad(gl, 0, 0, width, height, width, height, &black_bg[0]);
snprintf(msg, sizeof(msg), "%s\n%s", label, str);
glui_render_messagebox(msg);
}
if (glui->box_message[0] != '\0')
2014-09-15 12:36:52 +02:00
{
2015-09-06 20:38:45 +02:00
glui_render_quad(gl, 0, 0, width, height, width, height, &black_bg[0]);
glui_render_messagebox(glui->box_message);
glui->box_message[0] = '\0';
2014-09-15 12:36:52 +02:00
}
if (settings->menu.mouse.enable && (settings->video.fullscreen || !video_driver_has_windowed()))
2015-09-24 17:29:46 +02:00
{
int16_t mouse_x = menu_input_mouse_state(MENU_MOUSE_X_AXIS);
int16_t mouse_y = menu_input_mouse_state(MENU_MOUSE_Y_AXIS);
glui_draw_cursor(gl, glui, &white_bg[0], mouse_x, mouse_y, width, height);
2015-09-24 17:29:46 +02:00
}
2015-03-27 16:17:11 -03:00
menu_display_restore_clear_color(gl);
2015-09-25 13:27:15 +02:00
menu_display_ctl(MENU_DISPLAY_CTL_UNSET_VIEWPORT, NULL);
}
static void glui_allocate_white_texture(glui_handle_t *glui)
{
struct texture_image ti;
2015-06-12 16:20:45 +02:00
static const uint8_t white_data[] = { 0xff, 0xff, 0xff, 0xff };
ti.width = 1;
ti.height = 1;
ti.pixels = (uint32_t*)&white_data;
glui->textures.white = video_texture_load(&ti,
TEXTURE_BACKEND_OPENGL, TEXTURE_FILTER_NEAREST);
}
static void glui_font(menu_handle_t *menu)
{
2015-09-26 23:37:25 +02:00
int font_size;
char mediapath[PATH_MAX_LENGTH], fontpath[PATH_MAX_LENGTH];
settings_t *settings = config_get_ptr();
2015-09-26 23:37:25 +02:00
menu_display_ctl(MENU_DISPLAY_CTL_FONT_SIZE, &font_size);
fill_pathname_join(mediapath, settings->assets_directory, "glui", sizeof(mediapath));
fill_pathname_join(fontpath, mediapath, "Roboto-Regular.ttf", sizeof(fontpath));
if (!menu_display_init_main_font(menu, fontpath, font_size))
RARCH_WARN("Failed to load font.");
}
static void glui_layout(menu_handle_t *menu, glui_handle_t *glui)
{
void *fb_buf;
2015-07-16 10:11:28 +02:00
float scale_factor;
2015-09-26 23:37:25 +02:00
int new_font_size;
unsigned width, height, new_header_height;
video_driver_get_size(&width, &height);
2015-07-08 17:26:51 +02:00
/* Mobiles platforms may have very small display metrics coupled to a high
resolution, so we should be dpi aware to ensure the entries hitboxes are big
enough. On desktops, we just care about readability, with every widget size
proportional to the display width. */
2015-09-25 14:03:20 +02:00
menu_display_ctl(MENU_DISPLAY_CTL_GET_DPI, &scale_factor);
2015-09-26 23:37:25 +02:00
new_header_height = scale_factor / 3;
new_font_size = scale_factor / 9;
2015-09-26 23:37:25 +02:00
glui->tabs_height = scale_factor / 3;
glui->line_height = scale_factor / 3;
2015-10-27 22:49:48 +07:00
glui->margin = scale_factor / 9;
2015-10-28 00:51:22 +07:00
glui->icon_size = scale_factor / 3;
2015-09-26 23:37:25 +02:00
menu_display_ctl(MENU_DISPLAY_CTL_SET_HEADER_HEIGHT, &new_header_height);
menu_display_ctl(MENU_DISPLAY_CTL_SET_FONT_SIZE, &new_font_size);
/* we assume the average glyph aspect ratio is close to 3:4 */
2015-09-26 23:37:25 +02:00
glui->glyph_width = new_font_size * 3/4;
glui_font(menu);
menu_display_ctl(MENU_DISPLAY_CTL_FONT_BUF, &fb_buf);
if (fb_buf) /* calculate a more realistic ticker_limit */
{
driver_t *driver = driver_get_ptr();
int m_width = driver->font_osd_driver->get_message_width(fb_buf, "a", 1, 1);
if (m_width)
2015-07-16 03:38:07 +02:00
glui->glyph_width = m_width;
}
}
static void *glui_init(void)
{
2015-04-21 16:59:02 +02:00
glui_handle_t *glui = NULL;
const video_driver_t *video_driver = NULL;
menu_handle_t *menu = NULL;
gl_t *gl = (gl_t*)
video_driver_get_ptr(&video_driver);
if (video_driver != &video_gl || !gl)
2015-09-25 21:52:04 +02:00
goto error;
2015-04-21 16:59:02 +02:00
menu = (menu_handle_t*)calloc(1, sizeof(*menu));
if (!menu)
2015-02-02 18:51:48 +01:00
goto error;
2015-04-21 16:59:02 +02:00
menu->userdata = (glui_handle_t*)calloc(1, sizeof(glui_handle_t));
if (!menu->userdata)
2015-02-02 18:51:48 +01:00
goto error;
2015-06-14 15:34:05 +02:00
glui = (glui_handle_t*)menu->userdata;
glui_layout(menu, glui);
glui_allocate_white_texture(glui);
return menu;
2015-02-02 18:51:48 +01:00
error:
if (menu)
free(menu);
return NULL;
}
static void glui_free(void *data)
{
2015-04-21 16:59:02 +02:00
gl_t *gl = NULL;
const struct font_renderer *font_driver = NULL;
2015-04-21 16:59:02 +02:00
menu_handle_t *menu = (menu_handle_t*)data;
driver_t *driver = driver_get_ptr();
2015-04-21 16:59:02 +02:00
glui_handle_t *glui = (glui_handle_t*)menu->userdata;
2015-04-21 16:59:02 +02:00
if (!glui || !menu)
return;
2015-07-12 05:30:04 +02:00
gfx_coord_array_free(&glui->list_block.carr);
2015-04-21 16:59:02 +02:00
gl = (gl_t*)video_driver_get_ptr(NULL);
2015-03-28 20:50:51 +01:00
font_driver = gl ? (const struct font_renderer*)driver->font_osd_driver : NULL;
2015-04-21 16:59:02 +02:00
2015-04-24 22:17:08 +02:00
if (font_driver && font_driver->bind_block)
font_driver->bind_block(driver->font_osd_data, NULL);
if (menu->userdata)
free(menu->userdata);
2015-06-11 21:12:08 +02:00
menu->userdata = NULL;
}
static void glui_context_bg_destroy(glui_handle_t *glui)
{
2015-10-25 02:33:23 +01:00
if (!glui)
return;
2015-05-11 13:49:46 -03:00
2015-10-25 02:33:23 +01:00
video_texture_unload((uintptr_t*)&glui->textures.bg.id);
video_texture_unload((uintptr_t*)&glui->textures.white);
}
static void glui_context_destroy(void)
{
unsigned i;
2015-05-01 09:02:03 -03:00
glui_handle_t *glui = NULL;
menu_handle_t *menu = menu_driver_get_ptr();
2015-07-08 17:26:51 +02:00
if (!menu || !menu->userdata)
return;
glui = (glui_handle_t*)menu->userdata;
if (!glui)
return;
for (i = 0; i < GLUI_TEXTURE_LAST; i++)
video_texture_unload((uintptr_t*)&glui->textures.list[i].id);
menu_display_free_main_font();
2015-05-01 09:02:03 -03:00
glui_context_bg_destroy(glui);
}
static bool glui_load_image(void *data, menu_image_type_t type)
{
glui_handle_t *glui = NULL;
menu_handle_t *menu = menu_driver_get_ptr();
2015-05-01 09:35:27 -03:00
if (!menu || !menu->userdata)
return false;
2015-07-08 17:26:51 +02:00
glui = (glui_handle_t*)menu->userdata;
switch (type)
{
case MENU_IMAGE_NONE:
break;
case MENU_IMAGE_WALLPAPER:
glui_context_bg_destroy(glui);
glui->textures.bg.id = video_texture_load(data,
TEXTURE_BACKEND_OPENGL, TEXTURE_FILTER_MIPMAP_LINEAR);
glui_allocate_white_texture(glui);
break;
case MENU_IMAGE_BOXART:
break;
}
return true;
}
2015-04-25 00:54:17 +02:00
static float glui_get_scroll(void)
2014-10-27 00:55:14 +01:00
{
2015-09-25 14:57:37 +02:00
size_t selection;
2015-07-13 22:05:14 +02:00
unsigned width, height;
2015-09-25 14:57:37 +02:00
int half = 0;
glui_handle_t *glui = NULL;
menu_handle_t *menu = menu_driver_get_ptr();
2015-09-25 14:57:37 +02:00
if (!menu_navigation_ctl(MENU_NAVIGATION_CTL_GET_SELECTION, &selection))
return 0;
2014-10-27 00:55:14 +01:00
2015-05-01 09:35:27 -03:00
if (!menu || !menu->userdata)
return 0;
2015-04-21 16:59:02 +02:00
2015-07-13 22:05:14 +02:00
video_driver_get_size(&width, &height);
2014-10-27 00:55:14 +01:00
glui = (glui_handle_t*)menu->userdata;
if (glui->line_height)
2015-07-08 17:26:51 +02:00
half = (height / glui->line_height) / 2;
2015-04-04 21:26:11 +02:00
2015-09-05 18:49:48 +02:00
if (selection < (unsigned)half)
return 0;
2015-09-05 18:49:48 +02:00
return ((selection + 2 - half) * glui->line_height);
}
static void glui_navigation_set(bool scroll)
{
menu_handle_t *menu = menu_driver_get_ptr();
2015-09-06 02:10:44 +02:00
float scroll_pos = glui_get_scroll();
2015-04-20 21:22:55 +07:00
if (!menu || !scroll)
return;
2015-09-25 22:24:07 +02:00
menu_animation_push(10, scroll_pos,
2015-07-13 22:05:14 +02:00
&menu->scroll_y, EASING_IN_OUT_QUAD, -1, NULL);
2014-10-27 00:55:14 +01:00
}
static void glui_list_set_selection(file_list_t *list)
{
glui_navigation_set(true);
}
static void glui_navigation_clear(bool pending_push)
{
menu_handle_t *menu = menu_driver_get_ptr();
if (!menu)
return;
menu_entries_set_start(0);
2015-04-21 16:59:02 +02:00
menu->scroll_y = 0;
}
static void glui_navigation_set_last(void)
{
glui_navigation_set(true);
}
2015-06-07 00:48:50 +02:00
static void glui_navigation_alphabet(size_t *unused)
{
glui_navigation_set(true);
}
static void glui_populate_entries(const char *path,
const char *label, unsigned i)
{
menu_handle_t *menu = menu_driver_get_ptr();
if (!menu)
return;
2015-07-13 22:05:14 +02:00
menu->scroll_y = glui_get_scroll();
}
static void glui_context_reset(void)
{
char iconpath[PATH_MAX_LENGTH] = {0};
2015-05-01 09:02:03 -03:00
glui_handle_t *glui = NULL;
menu_handle_t *menu = menu_driver_get_ptr();
settings_t *settings = config_get_ptr();
2015-05-01 09:35:27 -03:00
if (!menu || !menu->userdata || !settings)
return;
2015-04-21 16:59:02 +02:00
2015-05-01 09:35:27 -03:00
glui = (glui_handle_t*)menu->userdata;
if (!glui)
return;
fill_pathname_join(iconpath, settings->assets_directory,
"glui", sizeof(iconpath));
fill_pathname_slash(iconpath, sizeof(iconpath));
glui_layout(menu, glui);
glui_context_bg_destroy(glui);
glui_allocate_white_texture(glui);
glui_context_reset_textures(glui, iconpath);
rarch_main_data_msg_queue_push(DATA_TYPE_IMAGE,
settings->menu.wallpaper, "cb_menu_wallpaper", 0, 1, true);
}
static int glui_environ(menu_environ_cb_t type, void *data)
2015-07-08 00:37:44 +02:00
{
switch (type)
{
2015-07-09 00:24:10 +02:00
case 0:
2015-07-08 00:37:44 +02:00
default:
break;
2015-07-08 00:37:44 +02:00
}
return -1;
2015-07-08 00:37:44 +02:00
}
2015-11-02 01:44:45 +07:00
static void glui_preswitch_tabs(unsigned action)
{
glui_handle_t *glui = NULL;
menu_handle_t *menu = menu_driver_get_ptr();
if (!menu)
return;
glui = (glui_handle_t*)menu->userdata;
if (!glui)
return;
file_list_t *menu_stack = menu_entries_get_menu_stack_ptr(0);
size_t stack_size = menu_stack->size;
if (menu_stack->list[stack_size - 1].label)
free(menu_stack->list[stack_size - 1].label);
menu_stack->list[stack_size - 1].label = NULL;
switch (glui->categories.selection_ptr)
{
case GLUI_SYSTEM_TAB_MAIN:
menu_stack->list[stack_size - 1].label =
strdup(menu_hash_to_str(MENU_VALUE_MAIN_MENU));
menu_stack->list[stack_size - 1].type =
MENU_SETTINGS;
break;
case GLUI_SYSTEM_TAB_PLAYLISTS:
menu_stack->list[stack_size - 1].label =
strdup(menu_hash_to_str(MENU_VALUE_PLAYLISTS_TAB));
menu_stack->list[stack_size - 1].label =
strdup(menu_hash_to_str(MENU_VALUE_PLAYLISTS_TAB));
menu_stack->list[stack_size - 1].type =
MENU_PLAYLISTS_TAB;
break;
case GLUI_SYSTEM_TAB_SETTINGS:
menu_stack->list[stack_size - 1].label =
strdup(menu_hash_to_str(MENU_VALUE_SETTINGS_TAB));
menu_stack->list[stack_size - 1].type =
MENU_SETTINGS;
break;
}
}
static void glui_list_cache(menu_list_type_t type, unsigned action)
{
2015-11-01 21:47:36 +01:00
size_t list_size;
glui_handle_t *glui = NULL;
2015-11-01 21:47:36 +01:00
menu_handle_t *menu = menu_driver_get_ptr();
if (!menu)
return;
glui = (glui_handle_t*)menu->userdata;
if (!glui)
return;
list_size = GLUI_SYSTEM_TAB_END;
switch (type)
{
case MENU_LIST_PLAIN:
break;
case MENU_LIST_HORIZONTAL:
glui->categories.selection_ptr_old = glui->categories.selection_ptr;
switch (action)
{
case MENU_ACTION_LEFT:
if (glui->categories.selection_ptr == 0)
{
glui->categories.selection_ptr = list_size;
glui->categories.active.idx = list_size - 1;
}
else
glui->categories.selection_ptr--;
break;
default:
if (glui->categories.selection_ptr == list_size)
{
glui->categories.selection_ptr = 0;
glui->categories.active.idx = 1;
}
else
glui->categories.selection_ptr++;
break;
}
2015-11-02 01:44:45 +07:00
glui_preswitch_tabs(action);
break;
default:
break;
}
}
2015-10-29 13:35:15 +01:00
static int glui_list_push(menu_displaylist_info_t *info, unsigned type)
{
int ret = -1;
menu_handle_t *menu = menu_driver_get_ptr();
global_t *global = global_get_ptr();
switch (type)
{
case DISPLAYLIST_LOAD_CONTENT_LIST:
menu_entries_clear(info->list);
menu_entries_push(info->list,
menu_hash_to_str(MENU_LABEL_VALUE_LOAD_CONTENT),
menu_hash_to_str(MENU_LABEL_LOAD_CONTENT),
MENU_SETTING_ACTION, 0, 0);
if (core_info_list_num_info_files(global->core_info.list))
{
menu_entries_push(info->list,
menu_hash_to_str(MENU_LABEL_VALUE_DETECT_CORE_LIST),
menu_hash_to_str(MENU_LABEL_DETECT_CORE_LIST),
MENU_SETTING_ACTION, 0, 0);
menu_entries_push(info->list,
menu_hash_to_str(MENU_LABEL_VALUE_DOWNLOADED_FILE_DETECT_CORE_LIST),
menu_hash_to_str(MENU_LABEL_DOWNLOADED_FILE_DETECT_CORE_LIST),
MENU_SETTING_ACTION, 0, 0);
}
info->need_push = true;
info->need_refresh = true;
ret = 0;
break;
2015-10-29 13:35:15 +01:00
case DISPLAYLIST_MAIN_MENU:
menu_entries_clear(info->list);
if (global->inited.main && (global->inited.core.type != CORE_TYPE_DUMMY))
menu_displaylist_parse_settings(menu, info,
menu_hash_to_str(MENU_LABEL_CONTENT_SETTINGS), PARSE_ACTION, false);
#if defined(HAVE_DYNAMIC) || defined(HAVE_LIBRETRO_MANAGEMENT)
menu_displaylist_parse_settings(menu, info,
menu_hash_to_str(MENU_LABEL_CORE_LIST), PARSE_ACTION, false);
#endif
menu_displaylist_parse_settings(menu, info,
menu_hash_to_str(MENU_LABEL_LOAD_CONTENT_LIST), PARSE_ACTION, false);
menu_displaylist_parse_settings(menu, info,
menu_hash_to_str(MENU_LABEL_LOAD_CONTENT_HISTORY), PARSE_ACTION, false);
#if defined(HAVE_NETWORKING)
#if defined(HAVE_LIBRETRODB)
menu_displaylist_parse_settings(menu, info,
menu_hash_to_str(MENU_LABEL_ADD_CONTENT_LIST), PARSE_ACTION, false);
#endif
menu_displaylist_parse_settings(menu, info,
menu_hash_to_str(MENU_LABEL_ONLINE_UPDATER), PARSE_ACTION, false);
#endif
menu_displaylist_parse_settings(menu, info,
menu_hash_to_str(MENU_LABEL_INFORMATION_LIST), PARSE_ACTION, false);
#ifndef HAVE_DYNAMIC
menu_displaylist_parse_settings(menu, info,
menu_hash_to_str(MENU_LABEL_RESTART_RETROARCH), PARSE_ACTION, false);
#endif
menu_displaylist_parse_settings(menu, info,
menu_hash_to_str(MENU_LABEL_CONFIGURATIONS), PARSE_ACTION, false);
menu_displaylist_parse_settings(menu, info,
menu_hash_to_str(MENU_LABEL_SAVE_NEW_CONFIG), PARSE_ACTION, false);
menu_displaylist_parse_settings(menu, info,
menu_hash_to_str(MENU_LABEL_HELP_LIST), PARSE_ACTION, false);
#if !defined(IOS)
menu_displaylist_parse_settings(menu, info,
menu_hash_to_str(MENU_LABEL_QUIT_RETROARCH), PARSE_ACTION, false);
#endif
menu_displaylist_parse_settings(menu, info,
menu_hash_to_str(MENU_LABEL_SHUTDOWN), PARSE_ACTION, false);
info->need_push = true;
ret = 0;
break;
}
return ret;
}
static size_t glui_list_get_selection(void *data)
{
menu_handle_t *menu = (menu_handle_t*)data;
glui_handle_t *glui = menu ? (glui_handle_t*)menu->userdata : NULL;
if (!glui)
return 0;
return glui->categories.selection_ptr;
}
2015-11-01 20:44:04 +01:00
static int glui_pointer_tap(unsigned x, unsigned y,
unsigned ptr, menu_file_list_cbs_t *cbs,
menu_entry_t *entry, unsigned action)
{
size_t selection, idx;
2015-11-02 01:44:45 +07:00
unsigned header_height, width, height, i;
bool scroll = false;
menu_handle_t *menu = menu_driver_get_ptr();
glui_handle_t *glui = menu ? (glui_handle_t*)menu->userdata : NULL;
file_list_t *menu_stack = menu_entries_get_menu_stack_ptr(0);
file_list_t *selection_buf = menu_entries_get_selection_buf_ptr(0);
if (!glui)
return 0;
video_driver_get_size(&width, &height);
menu_navigation_ctl(MENU_NAVIGATION_CTL_GET_SELECTION, &selection);
menu_display_ctl(MENU_DISPLAY_CTL_HEADER_HEIGHT, &header_height);
2015-11-01 20:44:04 +01:00
if (y < header_height)
{
menu_entries_pop_stack(&selection, 0);
menu_navigation_ctl(MENU_NAVIGATION_CTL_SET_SELECTION, &selection);
}
2015-11-01 20:44:04 +01:00
else if (y > height - glui->tabs_height)
2015-11-02 01:44:45 +07:00
{
for (i = 0; i <= GLUI_SYSTEM_TAB_END; i++)
{
unsigned tab_width = width / (GLUI_SYSTEM_TAB_END + 1);
unsigned start = tab_width * i;
2015-11-01 20:44:04 +01:00
if ((x >= start) && (x < (start + tab_width)))
2015-11-02 01:44:45 +07:00
{
glui->categories.selection_ptr = i;
glui_preswitch_tabs(action);
if (cbs && cbs->action_content_list_switch)
return cbs->action_content_list_switch(selection_buf, menu_stack,
"", "", 0);
}
}
}
2015-11-01 20:44:04 +01:00
else if (ptr <= (menu_entries_get_size() - 1))
{
2015-11-01 20:44:04 +01:00
if (ptr == selection && cbs && cbs->action_select)
return menu_entry_action(entry, selection, MENU_ACTION_SELECT);
2015-11-01 20:44:04 +01:00
idx = ptr;
menu_navigation_ctl(MENU_NAVIGATION_CTL_SET_SELECTION, &idx);
menu_navigation_ctl(MENU_NAVIGATION_CTL_SET, &scroll);
}
return 0;
}
2014-09-11 07:06:20 +02:00
menu_ctx_driver_t menu_ctx_glui = {
NULL,
2014-09-15 12:36:52 +02:00
glui_get_message,
generic_menu_iterate,
glui_render,
glui_frame,
glui_init,
glui_free,
glui_context_reset,
glui_context_destroy,
glui_populate_entries,
NULL,
2014-10-27 00:55:14 +01:00
glui_navigation_clear,
NULL,
NULL,
2014-10-27 00:55:14 +01:00
glui_navigation_set,
glui_navigation_set_last,
2015-06-07 00:48:50 +02:00
glui_navigation_alphabet,
glui_navigation_alphabet,
2015-10-03 04:32:38 +02:00
generic_menu_init_list,
NULL,
NULL,
NULL,
glui_list_cache,
2015-10-29 13:35:15 +01:00
glui_list_push,
glui_list_get_selection,
glui_list_get_size,
NULL,
glui_list_set_selection,
2015-06-15 19:00:52 +02:00
NULL,
glui_load_image,
"glui",
2015-08-17 05:05:29 +02:00
MENU_VIDEO_DRIVER_OPENGL,
2015-07-08 00:37:44 +02:00
glui_environ,
glui_pointer_tap,
};