mirror of
https://github.com/libretro/RetroArch.git
synced 2024-11-24 08:30:16 +00:00
Merge pull request #10240 from natinusala/split-widgets
gfx_widgets: start moving widgets into their own file
This commit is contained in:
commit
adfef2a503
@ -840,7 +840,8 @@ endif
|
||||
OBJ += input/input_osk.o
|
||||
|
||||
ifeq ($(HAVE_GFX_WIDGETS), 1)
|
||||
OBJ += gfx/gfx_widgets.o
|
||||
OBJ += gfx/gfx_widgets.o \
|
||||
gfx/widgets/gfx_widget_screenshot.o
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_OVERLAY), 1)
|
||||
|
@ -24,6 +24,8 @@
|
||||
|
||||
#include "../retroarch.h"
|
||||
|
||||
#include "video_defines.h"
|
||||
|
||||
RETRO_BEGIN_DECLS
|
||||
|
||||
/* All coordinates and offsets are top-left oriented.
|
||||
|
@ -1,7 +1,7 @@
|
||||
/* RetroArch - A frontend for libretro.
|
||||
* Copyright (C) 2014-2017 - Jean-André Santoni
|
||||
* Copyright (C) 2015-2018 - Andre Leiradella
|
||||
* Copyright (C) 2018-2019 - natinusala
|
||||
* Copyright (C) 2018-2020 - natinusala
|
||||
*
|
||||
* 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-
|
||||
@ -35,7 +35,6 @@
|
||||
|
||||
#include "gfx_widgets.h"
|
||||
|
||||
#include "gfx_animation.h"
|
||||
#include "gfx_display.h"
|
||||
#include "font_driver.h"
|
||||
|
||||
@ -61,13 +60,6 @@ static float msg_queue_task_progress_2[16] = COLOR_HEX_TO_FLOAT(0x317198, 1.0f);
|
||||
static float color_task_progress_bar[16] = COLOR_HEX_TO_FLOAT(0x22B14C, 1.0f);
|
||||
#endif
|
||||
|
||||
#define TEXT_COLOR_INFO 0xD8EEFFFF
|
||||
#if 0
|
||||
#define TEXT_COLOR_SUCCESS 0x22B14CFF
|
||||
#define TEXT_COLOR_ERROR 0xC23B22FF
|
||||
#endif
|
||||
#define TEXT_COLOR_FAINT 0x878787FF
|
||||
|
||||
static float volume_bar_background[16] = COLOR_HEX_TO_FLOAT(0x1A1A1A, 1.0f);
|
||||
static float volume_bar_normal[16] = COLOR_HEX_TO_FLOAT(0x198AC6, 1.0f);
|
||||
static float volume_bar_loud[16] = COLOR_HEX_TO_FLOAT(0xF5DD19, 1.0f);
|
||||
@ -79,6 +71,16 @@ static uint64_t gfx_widgets_frame_count = 0;
|
||||
static font_data_t *font_regular = NULL;
|
||||
static font_data_t *font_bold = NULL;
|
||||
|
||||
font_data_t* gfx_widgets_get_font_regular()
|
||||
{
|
||||
return font_regular;
|
||||
}
|
||||
|
||||
font_data_t* gfx_widgets_get_font_bold()
|
||||
{
|
||||
return font_bold;
|
||||
}
|
||||
|
||||
static video_font_raster_block_t font_raster_regular;
|
||||
static video_font_raster_block_t font_raster_bold;
|
||||
|
||||
@ -89,6 +91,11 @@ static float gfx_widgets_pure_white[16] = {
|
||||
1.00, 1.00, 1.00, 1.00,
|
||||
};
|
||||
|
||||
float* gfx_widgets_get_pure_white(void)
|
||||
{
|
||||
return gfx_widgets_pure_white;
|
||||
}
|
||||
|
||||
/* FPS */
|
||||
static char gfx_widgets_fps_text[255] = {0};
|
||||
|
||||
@ -150,6 +157,11 @@ static float gfx_widgets_backdrop_orig[16] = {
|
||||
0.00, 0.00, 0.00, 0.75,
|
||||
};
|
||||
|
||||
float* gfx_widgets_get_backdrop_orig(void)
|
||||
{
|
||||
return gfx_widgets_backdrop_orig;
|
||||
}
|
||||
|
||||
static float gfx_widgets_backdrop[16] = {
|
||||
0.00, 0.00, 0.00, 0.75,
|
||||
0.00, 0.00, 0.00, 0.75,
|
||||
@ -216,8 +228,12 @@ static uintptr_t msg_queue_icon_outline = 0;
|
||||
static uintptr_t msg_queue_icon_rect = 0;
|
||||
static bool msg_queue_has_icons = false;
|
||||
|
||||
extern gfx_animation_ctx_tag
|
||||
gfx_widgets_generic_tag;
|
||||
extern gfx_animation_ctx_tag gfx_widgets_generic_tag;
|
||||
|
||||
gfx_animation_ctx_tag gfx_widgets_get_generic_tag(void)
|
||||
{
|
||||
return gfx_widgets_generic_tag;
|
||||
}
|
||||
|
||||
/* There can only be one message animation at a time to
|
||||
* avoid confusing users */
|
||||
@ -279,25 +295,6 @@ static gfx_animation_ctx_tag volume_tag = (uintptr_t) &volume_alpha;
|
||||
static bool volume_mute = false;
|
||||
|
||||
|
||||
/* Screenshot */
|
||||
static float screenshot_alpha = 0.0f;
|
||||
static uintptr_t screenshot_texture = 0;
|
||||
static unsigned screenshot_texture_width = 0;
|
||||
static unsigned screenshot_texture_height = 0;
|
||||
static char screenshot_shotname[256] = {0};
|
||||
static char screenshot_filename[256] = {0};
|
||||
static bool screenshot_loaded = false;
|
||||
|
||||
static float screenshot_scale_factor = 0.0f;
|
||||
static float screenshot_y = 0.0f;
|
||||
static unsigned screenshot_height = 0;
|
||||
static unsigned screenshot_width = 0;
|
||||
static unsigned screenshot_thumbnail_width = 0;
|
||||
static unsigned screenshot_thumbnail_height = 0;
|
||||
static gfx_timer_t screenshot_timer;
|
||||
|
||||
static unsigned screenshot_shotname_length = 0;
|
||||
|
||||
#ifdef HAVE_TRANSLATE
|
||||
/* AI Service Overlay */
|
||||
static int ai_service_overlay_state = 0;
|
||||
@ -325,10 +322,30 @@ static float last_scale_factor = 0.0f;
|
||||
static float msg_queue_text_scale_factor = 0.0f;
|
||||
static float widget_font_size = 0.0f;
|
||||
|
||||
float gfx_widgets_get_font_size(void)
|
||||
{
|
||||
return widget_font_size;
|
||||
}
|
||||
|
||||
static unsigned simple_widget_padding = 0;
|
||||
static unsigned simple_widget_height = 0;
|
||||
static unsigned glyph_width = 0;
|
||||
|
||||
unsigned gfx_widgets_get_padding(void)
|
||||
{
|
||||
return simple_widget_padding;
|
||||
}
|
||||
|
||||
unsigned gfx_widgets_get_height(void)
|
||||
{
|
||||
return simple_widget_height;
|
||||
}
|
||||
|
||||
unsigned gfx_widgets_get_glyph_width(void)
|
||||
{
|
||||
return glyph_width;
|
||||
}
|
||||
|
||||
static unsigned libretro_message_width = 0;
|
||||
|
||||
static unsigned msg_queue_height;
|
||||
@ -361,6 +378,13 @@ static unsigned divider_width_1px = 1;
|
||||
static unsigned last_video_width = 0;
|
||||
static unsigned last_video_height = 0;
|
||||
|
||||
/* Widgets list */
|
||||
const static gfx_widget_t* const widgets[] = {
|
||||
&gfx_widget_screenshot
|
||||
};
|
||||
|
||||
static const size_t widgets_len = sizeof(widgets) / sizeof(widgets[0]);
|
||||
|
||||
static void msg_widget_msg_transition_animation_done(void *userdata)
|
||||
{
|
||||
menu_widget_msg_t *msg = (menu_widget_msg_t*)userdata;
|
||||
@ -734,7 +758,7 @@ static void gfx_widgets_msg_queue_kill(unsigned idx)
|
||||
gfx_widgets_msg_queue_move();
|
||||
}
|
||||
|
||||
static void gfx_widgets_draw_icon(
|
||||
void gfx_widgets_draw_icon(
|
||||
void *userdata,
|
||||
unsigned video_width,
|
||||
unsigned video_height,
|
||||
@ -838,7 +862,7 @@ static void gfx_widgets_draw_icon_blend(
|
||||
}
|
||||
#endif
|
||||
|
||||
static float gfx_widgets_get_thumbnail_scale_factor(
|
||||
float gfx_widgets_get_thumbnail_scale_factor(
|
||||
const float dst_width, const float dst_height,
|
||||
const float image_width, const float image_height)
|
||||
{
|
||||
@ -850,28 +874,6 @@ static float gfx_widgets_get_thumbnail_scale_factor(
|
||||
return (dst_width / image_width);
|
||||
}
|
||||
|
||||
static void gfx_widgets_screenshot_dispose(void *userdata)
|
||||
{
|
||||
screenshot_loaded = false;
|
||||
video_driver_texture_unload(&screenshot_texture);
|
||||
screenshot_texture = 0;
|
||||
}
|
||||
|
||||
static void gfx_widgets_screenshot_end(void *userdata)
|
||||
{
|
||||
gfx_animation_ctx_entry_t entry;
|
||||
|
||||
entry.cb = gfx_widgets_screenshot_dispose;
|
||||
entry.duration = MSG_QUEUE_ANIMATION_DURATION;
|
||||
entry.easing_enum = EASING_OUT_QUAD;
|
||||
entry.subject = &screenshot_y;
|
||||
entry.tag = gfx_widgets_generic_tag;
|
||||
entry.target_value = -((float)screenshot_height);
|
||||
entry.userdata = NULL;
|
||||
|
||||
gfx_animation_push(&entry);
|
||||
}
|
||||
|
||||
static void gfx_widgets_start_msg_expiration_timer(menu_widget_msg_t *msg_widget, unsigned duration)
|
||||
{
|
||||
gfx_timer_ctx_entry_t timer;
|
||||
@ -955,6 +957,14 @@ void gfx_widgets_iterate(
|
||||
video_driver_monitor_reset();
|
||||
}
|
||||
|
||||
for (i = 0; i < widgets_len; i++)
|
||||
{
|
||||
const gfx_widget_t* widget = widgets[i];
|
||||
|
||||
if (widget->iterate)
|
||||
widget->iterate(width, height, fullscreen, dir_assets, font_path, is_threaded);
|
||||
}
|
||||
|
||||
/* Messages queue */
|
||||
|
||||
/* Consume one message if available */
|
||||
@ -1032,44 +1042,6 @@ void gfx_widgets_iterate(
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Load screenshot and start its animation */
|
||||
if (screenshot_filename[0] != '\0')
|
||||
{
|
||||
gfx_timer_ctx_entry_t timer;
|
||||
|
||||
video_driver_texture_unload(&screenshot_texture);
|
||||
|
||||
screenshot_texture = 0;
|
||||
|
||||
gfx_display_reset_textures_list(screenshot_filename,
|
||||
"", &screenshot_texture, TEXTURE_FILTER_MIPMAP_LINEAR,
|
||||
&screenshot_texture_width, &screenshot_texture_height);
|
||||
|
||||
screenshot_height = widget_font_size * 4;
|
||||
screenshot_width = width;
|
||||
|
||||
screenshot_scale_factor = gfx_widgets_get_thumbnail_scale_factor(
|
||||
width, screenshot_height,
|
||||
screenshot_texture_width, screenshot_texture_height
|
||||
);
|
||||
|
||||
screenshot_thumbnail_width = screenshot_texture_width * screenshot_scale_factor;
|
||||
screenshot_thumbnail_height = screenshot_texture_height * screenshot_scale_factor;
|
||||
|
||||
screenshot_shotname_length = (width - screenshot_thumbnail_width - simple_widget_padding*2) / glyph_width;
|
||||
|
||||
screenshot_y = 0.0f;
|
||||
|
||||
timer.cb = gfx_widgets_screenshot_end;
|
||||
timer.duration = SCREENSHOT_NOTIFICATION_DURATION;
|
||||
timer.userdata = NULL;
|
||||
|
||||
gfx_timer_start(&screenshot_timer, &timer);
|
||||
|
||||
screenshot_loaded = true;
|
||||
screenshot_filename[0] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
static int gfx_widgets_draw_indicator(
|
||||
@ -1630,62 +1602,6 @@ void gfx_widgets_frame(void *data)
|
||||
1, false, 0, false);
|
||||
}
|
||||
|
||||
/* Screenshot */
|
||||
if (screenshot_loaded)
|
||||
{
|
||||
char shotname[256];
|
||||
gfx_animation_ctx_ticker_t ticker;
|
||||
|
||||
gfx_display_set_alpha(gfx_widgets_backdrop_orig, DEFAULT_BACKDROP);
|
||||
|
||||
gfx_display_draw_quad(userdata,
|
||||
video_width, video_height,
|
||||
0, screenshot_y,
|
||||
screenshot_width, screenshot_height,
|
||||
video_width, video_height,
|
||||
gfx_widgets_backdrop_orig
|
||||
);
|
||||
|
||||
gfx_display_set_alpha(gfx_widgets_pure_white, 1.0f);
|
||||
gfx_widgets_draw_icon(
|
||||
userdata,
|
||||
video_width,
|
||||
video_height,
|
||||
screenshot_thumbnail_width,
|
||||
screenshot_thumbnail_height,
|
||||
screenshot_texture,
|
||||
0, screenshot_y,
|
||||
video_width, video_height,
|
||||
0, 1, gfx_widgets_pure_white
|
||||
);
|
||||
|
||||
gfx_display_draw_text(font_regular,
|
||||
msg_hash_to_str(MSG_SCREENSHOT_SAVED),
|
||||
screenshot_thumbnail_width + simple_widget_padding, widget_font_size * 1.9f + screenshot_y,
|
||||
video_width, video_height,
|
||||
TEXT_COLOR_FAINT,
|
||||
TEXT_ALIGN_LEFT,
|
||||
1, false, 0, true
|
||||
);
|
||||
|
||||
ticker.idx = gfx_animation_get_ticker_idx();
|
||||
ticker.len = screenshot_shotname_length;
|
||||
ticker.s = shotname;
|
||||
ticker.selected = true;
|
||||
ticker.str = screenshot_shotname;
|
||||
|
||||
gfx_animation_ticker(&ticker);
|
||||
|
||||
gfx_display_draw_text(font_regular,
|
||||
shotname,
|
||||
screenshot_thumbnail_width + simple_widget_padding, widget_font_size * 2.9f + screenshot_y,
|
||||
video_width, video_height,
|
||||
TEXT_COLOR_INFO,
|
||||
TEXT_ALIGN_LEFT,
|
||||
1, false, 0, true
|
||||
);
|
||||
}
|
||||
|
||||
#ifdef HAVE_CHEEVOS
|
||||
/* Achievement notification */
|
||||
if (cheevo_popup_queue_read_index >= 0 && cheevo_popup_queue[cheevo_popup_queue_read_index].title)
|
||||
@ -2032,18 +1948,12 @@ void gfx_widgets_frame(void *data)
|
||||
gfx_widgets_icons_textures[MENU_WIDGETS_ICON_SLOW_MOTION], (fps_show ? simple_widget_height : 0), top_right_x_advance,
|
||||
MSG_SLOW_MOTION);
|
||||
|
||||
/* Screenshot */
|
||||
if (screenshot_alpha > 0.0f)
|
||||
for (i = 0; i < widgets_len; i++)
|
||||
{
|
||||
gfx_display_set_alpha(gfx_widgets_pure_white, screenshot_alpha);
|
||||
gfx_display_draw_quad(userdata,
|
||||
video_width,
|
||||
video_height,
|
||||
0, 0,
|
||||
video_width, video_height,
|
||||
video_width, video_height,
|
||||
gfx_widgets_pure_white
|
||||
);
|
||||
const gfx_widget_t* widget = widgets[i];
|
||||
|
||||
if (widget->frame)
|
||||
widget->frame(data);
|
||||
}
|
||||
|
||||
#ifdef HAVE_MENU
|
||||
@ -2066,11 +1976,21 @@ void gfx_widgets_frame(void *data)
|
||||
|
||||
bool gfx_widgets_init(bool video_is_threaded, bool fullscreen)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (!gfx_display_init_first_driver(video_is_threaded))
|
||||
goto error;
|
||||
|
||||
gfx_widgets_frame_count = 0;
|
||||
|
||||
for (i = 0; i < widgets_len; i++)
|
||||
{
|
||||
const gfx_widget_t* widget = widgets[i];
|
||||
|
||||
if (widget->init)
|
||||
widget->init(video_is_threaded, fullscreen);
|
||||
}
|
||||
|
||||
msg_queue = fifo_new(MSG_QUEUE_PENDING_MAX * sizeof(menu_widget_msg_t*));
|
||||
|
||||
if (!msg_queue)
|
||||
@ -2103,6 +2023,7 @@ error:
|
||||
static void gfx_widgets_layout(
|
||||
bool is_threaded, const char *dir_assets, char *font_path)
|
||||
{
|
||||
size_t i;
|
||||
int font_height = 0;
|
||||
|
||||
/* Base font size must be determined first
|
||||
@ -2225,13 +2146,21 @@ static void gfx_widgets_layout(
|
||||
divider_width_1px = 1;
|
||||
if (last_scale_factor > 1.0f)
|
||||
divider_width_1px = (unsigned)(last_scale_factor + 0.5f);
|
||||
|
||||
for (i = 0; i < widgets_len; i++)
|
||||
{
|
||||
const gfx_widget_t* widget = widgets[i];
|
||||
|
||||
if (widget->layout)
|
||||
widget->layout(is_threaded, dir_assets, font_path);
|
||||
}
|
||||
}
|
||||
|
||||
void gfx_widgets_context_reset(bool is_threaded,
|
||||
unsigned width, unsigned height, bool fullscreen,
|
||||
const char *dir_assets, char *font_path)
|
||||
{
|
||||
int i;
|
||||
size_t i;
|
||||
char xmb_path[PATH_MAX_LENGTH];
|
||||
char monochrome_png_path[PATH_MAX_LENGTH];
|
||||
char gfx_widgets_path[PATH_MAX_LENGTH];
|
||||
@ -2286,6 +2215,14 @@ void gfx_widgets_context_reset(bool is_threaded,
|
||||
|
||||
msg_queue_has_icons = msg_queue_icon && msg_queue_icon_outline && msg_queue_icon_rect;
|
||||
|
||||
for (i = 0; i < widgets_len; i++)
|
||||
{
|
||||
const gfx_widget_t* widget = widgets[i];
|
||||
|
||||
if (widget->context_reset)
|
||||
widget->context_reset(is_threaded, width, height, fullscreen, dir_assets, font_path);
|
||||
}
|
||||
|
||||
/* Update scaling/dimensions */
|
||||
last_video_width = width;
|
||||
last_video_height = height;
|
||||
@ -2299,7 +2236,15 @@ void gfx_widgets_context_reset(bool is_threaded,
|
||||
|
||||
static void gfx_widgets_context_destroy(void)
|
||||
{
|
||||
unsigned i;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < widgets_len; i++)
|
||||
{
|
||||
const gfx_widget_t* widget = widgets[i];
|
||||
|
||||
if (widget->context_destroy)
|
||||
widget->context_destroy();
|
||||
}
|
||||
|
||||
/* TODO: Dismiss onscreen notifications that have been freed */
|
||||
|
||||
@ -2364,6 +2309,14 @@ void gfx_widgets_free(void)
|
||||
|
||||
gfx_widgets_context_destroy();
|
||||
|
||||
for (i = 0; i < widgets_len; i++)
|
||||
{
|
||||
const gfx_widget_t* widget = widgets[i];
|
||||
|
||||
if (widget->free)
|
||||
widget->free();
|
||||
}
|
||||
|
||||
/* Kill any pending animation */
|
||||
gfx_animation_kill_by_tag(&volume_tag);
|
||||
gfx_animation_kill_by_tag(&gfx_widgets_generic_tag);
|
||||
@ -2435,10 +2388,6 @@ void gfx_widgets_free(void)
|
||||
|
||||
/* Volume */
|
||||
volume_alpha = 0.0f;
|
||||
|
||||
/* Screenshot */
|
||||
screenshot_alpha = 0.0f;
|
||||
gfx_widgets_screenshot_dispose(NULL);
|
||||
}
|
||||
|
||||
static void gfx_widgets_volume_timer_end(void *userdata)
|
||||
@ -2527,43 +2476,6 @@ void gfx_widgets_ai_service_overlay_unload(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
static void gfx_widgets_screenshot_fadeout(void *userdata)
|
||||
{
|
||||
gfx_animation_ctx_entry_t entry;
|
||||
|
||||
entry.cb = NULL;
|
||||
entry.duration = SCREENSHOT_DURATION_OUT;
|
||||
entry.easing_enum = EASING_OUT_QUAD;
|
||||
entry.subject = &screenshot_alpha;
|
||||
entry.tag = gfx_widgets_generic_tag;
|
||||
entry.target_value = 0.0f;
|
||||
entry.userdata = NULL;
|
||||
|
||||
gfx_animation_push(&entry);
|
||||
}
|
||||
|
||||
static void gfx_widgets_play_screenshot_flash(void)
|
||||
{
|
||||
gfx_animation_ctx_entry_t entry;
|
||||
|
||||
entry.cb = gfx_widgets_screenshot_fadeout;
|
||||
entry.duration = SCREENSHOT_DURATION_IN;
|
||||
entry.easing_enum = EASING_IN_QUAD;
|
||||
entry.subject = &screenshot_alpha;
|
||||
entry.tag = gfx_widgets_generic_tag;
|
||||
entry.target_value = 1.0f;
|
||||
entry.userdata = NULL;
|
||||
|
||||
gfx_animation_push(&entry);
|
||||
}
|
||||
|
||||
void gfx_widgets_screenshot_taken(const char *shotname, const char *filename)
|
||||
{
|
||||
gfx_widgets_play_screenshot_flash();
|
||||
strlcpy(screenshot_filename, filename, sizeof(screenshot_filename));
|
||||
strlcpy(screenshot_shotname, shotname, sizeof(screenshot_shotname));
|
||||
}
|
||||
|
||||
static void gfx_widgets_end_load_content_animation(void *userdata)
|
||||
{
|
||||
#if 0
|
||||
|
@ -24,6 +24,8 @@
|
||||
#include <queues/task_queue.h>
|
||||
#include <queues/message_queue.h>
|
||||
|
||||
#include "gfx_animation.h"
|
||||
|
||||
#define DEFAULT_BACKDROP 0.75f
|
||||
|
||||
#define MSG_QUEUE_PENDING_MAX 32
|
||||
@ -31,15 +33,88 @@
|
||||
|
||||
#define MSG_QUEUE_ANIMATION_DURATION 330
|
||||
#define VOLUME_DURATION 3000
|
||||
#define SCREENSHOT_DURATION_IN 66
|
||||
#define SCREENSHOT_DURATION_OUT SCREENSHOT_DURATION_IN*10
|
||||
#define SCREENSHOT_NOTIFICATION_DURATION 6000
|
||||
#define CHEEVO_NOTIFICATION_DURATION 4000
|
||||
#define TASK_FINISHED_DURATION 3000
|
||||
#define HOURGLASS_INTERVAL 5000
|
||||
#define HOURGLASS_DURATION 1000
|
||||
#define GENERIC_MESSAGE_DURATION 3000
|
||||
|
||||
#define TEXT_COLOR_INFO 0xD8EEFFFF
|
||||
#if 0
|
||||
#define TEXT_COLOR_SUCCESS 0x22B14CFF
|
||||
#define TEXT_COLOR_ERROR 0xC23B22FF
|
||||
#endif
|
||||
#define TEXT_COLOR_FAINT 0x878787FF
|
||||
|
||||
/* A widget */
|
||||
/* TODO: cleanup all unused parameters */
|
||||
struct gfx_widget
|
||||
{
|
||||
/* called when the widgets system is initialized
|
||||
* -> initialize the widget here */
|
||||
bool (*init)(bool video_is_threaded, bool fullscreen);
|
||||
|
||||
/* called when the widgets system is freed
|
||||
* -> free the widget here */
|
||||
void (*free)(void);
|
||||
|
||||
/* called when the graphics context is reset
|
||||
* -> (re)load the textures here */
|
||||
void (*context_reset)(bool is_threaded,
|
||||
unsigned width, unsigned height, bool fullscreen,
|
||||
const char *dir_assets, char *font_path);
|
||||
|
||||
/* called when the graphics context is destroyed
|
||||
* -> release the textures here */
|
||||
void (*context_destroy)(void);
|
||||
|
||||
/* called when the window resolution changes
|
||||
* -> (re)layout the widget here */
|
||||
void (*layout)(bool is_threaded, const char *dir_assets, char *font_path);
|
||||
|
||||
/* called every frame on the main thread
|
||||
* -> update the widget logic here */
|
||||
void (*iterate)(
|
||||
unsigned width, unsigned height, bool fullscreen,
|
||||
const char *dir_assets, char *font_path,
|
||||
bool is_threaded);
|
||||
|
||||
/* called every frame
|
||||
* (on the video thread if threaded video is on)
|
||||
* -> draw the widget here */
|
||||
void (*frame)(void* data);
|
||||
};
|
||||
|
||||
gfx_animation_ctx_tag gfx_widgets_get_generic_tag(void);
|
||||
float* gfx_widgets_get_pure_white(void);
|
||||
unsigned gfx_widgets_get_padding(void);
|
||||
unsigned gfx_widgets_get_height(void);
|
||||
unsigned gfx_widgets_get_glyph_width(void);
|
||||
float gfx_widgets_get_font_size(void);
|
||||
font_data_t* gfx_widgets_get_font_regular(void);
|
||||
font_data_t* gfx_widgets_get_font_bold(void);
|
||||
float* gfx_widgets_get_backdrop_orig(void);
|
||||
|
||||
float gfx_widgets_get_thumbnail_scale_factor(
|
||||
const float dst_width, const float dst_height,
|
||||
const float image_width, const float image_height);
|
||||
|
||||
void gfx_widgets_draw_icon(
|
||||
void *userdata,
|
||||
unsigned video_width,
|
||||
unsigned video_height,
|
||||
unsigned icon_width,
|
||||
unsigned icon_height,
|
||||
uintptr_t texture,
|
||||
float x, float y,
|
||||
unsigned width, unsigned height,
|
||||
float rotation, float scale_factor,
|
||||
float *color);
|
||||
|
||||
typedef struct gfx_widget gfx_widget_t;
|
||||
|
||||
extern const gfx_widget_t gfx_widget_screenshot;
|
||||
|
||||
bool gfx_widgets_init(bool video_is_threaded, bool fullscreen);
|
||||
|
||||
void gfx_widgets_free(void);
|
||||
|
290
gfx/widgets/gfx_widget_screenshot.c
Normal file
290
gfx/widgets/gfx_widget_screenshot.c
Normal file
@ -0,0 +1,290 @@
|
||||
/* RetroArch - A frontend for libretro.
|
||||
* Copyright (C) 2014-2017 - Jean-André Santoni
|
||||
* Copyright (C) 2015-2018 - Andre Leiradella
|
||||
* Copyright (C) 2018-2020 - natinusala
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#include "../gfx_widgets.h"
|
||||
#include "../gfx_animation.h"
|
||||
#include "../gfx_display.h"
|
||||
#include "../../retroarch.h"
|
||||
|
||||
#define SCREENSHOT_DURATION_IN 66
|
||||
#define SCREENSHOT_DURATION_OUT SCREENSHOT_DURATION_IN*10
|
||||
#define SCREENSHOT_NOTIFICATION_DURATION 6000
|
||||
|
||||
struct gfx_widget_screenshot_state
|
||||
{
|
||||
float alpha;
|
||||
uintptr_t texture;
|
||||
unsigned texture_width;
|
||||
unsigned texture_height;
|
||||
char shotname[256];
|
||||
char filename[256];
|
||||
bool loaded;
|
||||
|
||||
float scale_factor;
|
||||
float y;
|
||||
unsigned height;
|
||||
unsigned width;
|
||||
unsigned thumbnail_width;
|
||||
unsigned thumbnail_height;
|
||||
gfx_timer_t timer;
|
||||
|
||||
unsigned shotname_length;
|
||||
};
|
||||
|
||||
typedef struct gfx_widget_screenshot_state gfx_widget_screenshot_state_t;
|
||||
|
||||
static gfx_widget_screenshot_state_t p_state = {
|
||||
0.0f,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
{0},
|
||||
{0},
|
||||
false,
|
||||
|
||||
0.0f,
|
||||
0.0f,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0.0f,
|
||||
|
||||
0
|
||||
};
|
||||
|
||||
static gfx_widget_screenshot_state_t* gfx_widget_screenshot_get_ptr(void)
|
||||
{
|
||||
return &p_state;
|
||||
}
|
||||
|
||||
static void gfx_widgets_screenshot_fadeout(void *userdata)
|
||||
{
|
||||
gfx_widget_screenshot_state_t* state = gfx_widget_screenshot_get_ptr();
|
||||
gfx_animation_ctx_entry_t entry;
|
||||
|
||||
entry.cb = NULL;
|
||||
entry.duration = SCREENSHOT_DURATION_OUT;
|
||||
entry.easing_enum = EASING_OUT_QUAD;
|
||||
entry.subject = &state->alpha;
|
||||
entry.tag = gfx_widgets_get_generic_tag();
|
||||
entry.target_value = 0.0f;
|
||||
entry.userdata = NULL;
|
||||
|
||||
gfx_animation_push(&entry);
|
||||
}
|
||||
|
||||
static void gfx_widgets_play_screenshot_flash(void)
|
||||
{
|
||||
gfx_widget_screenshot_state_t* state = gfx_widget_screenshot_get_ptr();
|
||||
gfx_animation_ctx_entry_t entry;
|
||||
|
||||
entry.cb = gfx_widgets_screenshot_fadeout;
|
||||
entry.duration = SCREENSHOT_DURATION_IN;
|
||||
entry.easing_enum = EASING_IN_QUAD;
|
||||
entry.subject = &state->alpha;
|
||||
entry.tag = gfx_widgets_get_generic_tag();
|
||||
entry.target_value = 1.0f;
|
||||
entry.userdata = NULL;
|
||||
|
||||
gfx_animation_push(&entry);
|
||||
}
|
||||
|
||||
void gfx_widgets_screenshot_taken(const char *shotname, const char *filename)
|
||||
{
|
||||
gfx_widget_screenshot_state_t* state = gfx_widget_screenshot_get_ptr();
|
||||
gfx_widgets_play_screenshot_flash();
|
||||
strlcpy(state->filename, filename, sizeof(state->filename));
|
||||
strlcpy(state->shotname, shotname, sizeof(state->shotname));
|
||||
}
|
||||
|
||||
static void gfx_widgets_screenshot_dispose(void *userdata)
|
||||
{
|
||||
gfx_widget_screenshot_state_t* state = gfx_widget_screenshot_get_ptr();
|
||||
state->loaded = false;
|
||||
video_driver_texture_unload(&state->texture);
|
||||
state->texture = 0;
|
||||
}
|
||||
|
||||
static void gfx_widgets_screenshot_end(void *userdata)
|
||||
{
|
||||
gfx_widget_screenshot_state_t* state = gfx_widget_screenshot_get_ptr();
|
||||
gfx_animation_ctx_entry_t entry;
|
||||
|
||||
entry.cb = gfx_widgets_screenshot_dispose;
|
||||
entry.duration = MSG_QUEUE_ANIMATION_DURATION;
|
||||
entry.easing_enum = EASING_OUT_QUAD;
|
||||
entry.subject = &state->y;
|
||||
entry.tag = gfx_widgets_get_generic_tag();
|
||||
entry.target_value = -((float)state->height);
|
||||
entry.userdata = NULL;
|
||||
|
||||
gfx_animation_push(&entry);
|
||||
}
|
||||
|
||||
static void gfx_widget_screenshot_free(void)
|
||||
{
|
||||
gfx_widget_screenshot_state_t* state = gfx_widget_screenshot_get_ptr();
|
||||
state->alpha = 0.0f;
|
||||
gfx_widgets_screenshot_dispose(NULL);
|
||||
}
|
||||
|
||||
static void gfx_widget_screenshot_frame(void* data)
|
||||
{
|
||||
video_frame_info_t *video_info = (video_frame_info_t*)data;
|
||||
void *userdata = video_info->userdata;
|
||||
unsigned video_width = video_info->width;
|
||||
unsigned video_height = video_info->height;
|
||||
|
||||
unsigned padding = gfx_widgets_get_padding();
|
||||
float font_size = gfx_widgets_get_font_size();
|
||||
|
||||
font_data_t* font_regular = gfx_widgets_get_font_regular();
|
||||
|
||||
float* pure_white = gfx_widgets_get_pure_white();
|
||||
|
||||
gfx_widget_screenshot_state_t* state = gfx_widget_screenshot_get_ptr();
|
||||
|
||||
/* Screenshot */
|
||||
if (state->loaded)
|
||||
{
|
||||
char shotname[256];
|
||||
gfx_animation_ctx_ticker_t ticker;
|
||||
|
||||
gfx_display_set_alpha(gfx_widgets_get_backdrop_orig(), DEFAULT_BACKDROP);
|
||||
|
||||
gfx_display_draw_quad(userdata,
|
||||
video_width, video_height,
|
||||
0, state->y,
|
||||
state->width, state->height,
|
||||
video_width, video_height,
|
||||
gfx_widgets_get_backdrop_orig()
|
||||
);
|
||||
|
||||
gfx_display_set_alpha(pure_white, 1.0f);
|
||||
gfx_widgets_draw_icon(
|
||||
userdata,
|
||||
video_width,
|
||||
video_height,
|
||||
state->thumbnail_width,
|
||||
state->thumbnail_height,
|
||||
state->texture,
|
||||
0, state->y,
|
||||
video_width, video_height,
|
||||
0, 1, pure_white
|
||||
);
|
||||
|
||||
gfx_display_draw_text(font_regular,
|
||||
msg_hash_to_str(MSG_SCREENSHOT_SAVED),
|
||||
state->thumbnail_width + padding, font_size * 1.9f + state->y,
|
||||
video_width, video_height,
|
||||
TEXT_COLOR_FAINT,
|
||||
TEXT_ALIGN_LEFT,
|
||||
1, false, 0, true
|
||||
);
|
||||
|
||||
ticker.idx = gfx_animation_get_ticker_idx();
|
||||
ticker.len = state->shotname_length;
|
||||
ticker.s = shotname;
|
||||
ticker.selected = true;
|
||||
ticker.str = state->shotname;
|
||||
|
||||
gfx_animation_ticker(&ticker);
|
||||
|
||||
gfx_display_draw_text(font_regular,
|
||||
shotname,
|
||||
state->thumbnail_width + padding, font_size * 2.9f + state->y,
|
||||
video_width, video_height,
|
||||
TEXT_COLOR_INFO,
|
||||
TEXT_ALIGN_LEFT,
|
||||
1, false, 0, true
|
||||
);
|
||||
}
|
||||
|
||||
/* Flash effect */
|
||||
if (state->alpha > 0.0f)
|
||||
{
|
||||
gfx_display_set_alpha(pure_white, state->alpha);
|
||||
gfx_display_draw_quad(userdata,
|
||||
video_width,
|
||||
video_height,
|
||||
0, 0,
|
||||
video_width, video_height,
|
||||
video_width, video_height,
|
||||
pure_white
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
static void gfx_widget_screenshot_iterate(unsigned width, unsigned height, bool fullscreen,
|
||||
const char *dir_assets, char *font_path,
|
||||
bool is_threaded)
|
||||
{
|
||||
gfx_widget_screenshot_state_t* state = gfx_widget_screenshot_get_ptr();
|
||||
|
||||
float font_size = gfx_widgets_get_font_size();
|
||||
unsigned padding = gfx_widgets_get_padding();
|
||||
unsigned glyph_width = gfx_widgets_get_glyph_width();
|
||||
|
||||
/* Load screenshot and start its animation */
|
||||
if (state->filename[0] != '\0')
|
||||
{
|
||||
gfx_timer_ctx_entry_t timer;
|
||||
|
||||
video_driver_texture_unload(&state->texture);
|
||||
|
||||
state->texture = 0;
|
||||
|
||||
gfx_display_reset_textures_list(state->filename,
|
||||
"", &state->texture, TEXTURE_FILTER_MIPMAP_LINEAR,
|
||||
&state->texture_width, &state->texture_height);
|
||||
|
||||
state->height = font_size * 4;
|
||||
state->width = width;
|
||||
|
||||
state->scale_factor = gfx_widgets_get_thumbnail_scale_factor(
|
||||
width, state->height,
|
||||
state->texture_width, state->texture_height
|
||||
);
|
||||
|
||||
state->thumbnail_width = state->texture_width * state->scale_factor;
|
||||
state->thumbnail_height = state->texture_height * state->scale_factor;
|
||||
|
||||
state->shotname_length = (width - state->thumbnail_width - padding*2) / glyph_width;
|
||||
|
||||
state->y = 0.0f;
|
||||
|
||||
timer.cb = gfx_widgets_screenshot_end;
|
||||
timer.duration = SCREENSHOT_NOTIFICATION_DURATION;
|
||||
timer.userdata = NULL;
|
||||
|
||||
gfx_timer_start(&state->timer, &timer);
|
||||
|
||||
state->loaded = true;
|
||||
state->filename[0] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
const gfx_widget_t gfx_widget_screenshot = {
|
||||
NULL, /* init */
|
||||
gfx_widget_screenshot_free,
|
||||
NULL, /* context_reset*/
|
||||
NULL, /* context_destroy */
|
||||
NULL, /* layout */
|
||||
gfx_widget_screenshot_iterate,
|
||||
gfx_widget_screenshot_frame
|
||||
};
|
@ -1261,6 +1261,7 @@ MENU
|
||||
|
||||
#ifdef HAVE_GFX_WIDGETS
|
||||
#include "../gfx/gfx_widgets.c"
|
||||
#include "../gfx/widgets/gfx_widget_screenshot.c"
|
||||
#endif
|
||||
|
||||
#include "../input/input_osk.c"
|
||||
|
Loading…
Reference in New Issue
Block a user