1 /* RetroArch - A frontend for libretro. 2 * Copyright (C) 2018 - natinusala 3 * 4 * RetroArch is free software: you can redistribute it and/or modify it under the terms 5 * of the GNU General Public License as published by the Free Software Found- 6 * ation, either version 3 of the License, or (at your option) any later version. 7 * 8 * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 9 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 * PURPOSE. See the GNU General Public License for more details. 11 * 12 * You should have received a copy of the GNU General Public License along with RetroArch. 13 * If not, see <http://www.gnu.org/licenses/>. 14 */ 15 16 #ifndef _GFX_WIDGETS_H 17 #define _GFX_WIDGETS_H 18 19 #ifdef HAVE_CONFIG_H 20 #include "../config.h" 21 #endif 22 23 #include <formats/image.h> 24 #include <queues/task_queue.h> 25 #include <queues/message_queue.h> 26 #include <queues/fifo_queue.h> 27 28 #ifdef HAVE_THREADS 29 #include <rthreads/rthreads.h> 30 #endif 31 32 #include "gfx_animation.h" 33 #include "gfx_display.h" 34 35 #define DEFAULT_BACKDROP 0.75f 36 37 #define MSG_QUEUE_PENDING_MAX 32 38 #define MSG_QUEUE_ONSCREEN_MAX 4 39 40 #define MSG_QUEUE_ANIMATION_DURATION 330 41 #define TASK_FINISHED_DURATION 3000 42 #define HOURGLASS_INTERVAL 5000 43 #define HOURGLASS_DURATION 1000 44 45 /* TODO: Colors for warning, error and success */ 46 47 #define TEXT_COLOR_INFO 0xD8EEFFFF 48 #if 0 49 #define TEXT_COLOR_SUCCESS 0x22B14CFF 50 #define TEXT_COLOR_ERROR 0xC23B22FF 51 #endif 52 #define TEXT_COLOR_FAINT 0x878787FF 53 54 enum gfx_widgets_icon 55 { 56 MENU_WIDGETS_ICON_PAUSED = 0, 57 MENU_WIDGETS_ICON_FAST_FORWARD, 58 MENU_WIDGETS_ICON_REWIND, 59 MENU_WIDGETS_ICON_SLOW_MOTION, 60 61 MENU_WIDGETS_ICON_HOURGLASS, 62 MENU_WIDGETS_ICON_CHECK, 63 64 MENU_WIDGETS_ICON_INFO, 65 66 MENU_WIDGETS_ICON_ACHIEVEMENT, 67 68 MENU_WIDGETS_ICON_LAST 69 }; 70 71 enum notification_show_screenshot_duration 72 { 73 NOTIFICATION_SHOW_SCREENSHOT_DURATION_NORMAL = 0, 74 NOTIFICATION_SHOW_SCREENSHOT_DURATION_FAST, 75 NOTIFICATION_SHOW_SCREENSHOT_DURATION_VERY_FAST, 76 NOTIFICATION_SHOW_SCREENSHOT_DURATION_INSTANT, 77 NOTIFICATION_SHOW_SCREENSHOT_DURATION_LAST 78 }; 79 80 enum notification_show_screenshot_flash 81 { 82 NOTIFICATION_SHOW_SCREENSHOT_FLASH_NORMAL = 0, 83 NOTIFICATION_SHOW_SCREENSHOT_FLASH_FAST, 84 NOTIFICATION_SHOW_SCREENSHOT_FLASH_OFF, 85 NOTIFICATION_SHOW_SCREENSHOT_FLASH_LAST 86 }; 87 88 /* This structure holds all objects + metadata 89 * corresponding to a particular font */ 90 typedef struct 91 { 92 font_data_t *font; 93 video_font_raster_block_t raster_block; /* ptr alignment */ 94 size_t usage_count; 95 unsigned glyph_width; 96 float line_height; 97 float line_ascender; 98 float line_descender; 99 float line_centre_offset; 100 } gfx_widget_font_data_t; 101 102 /* Font data */ 103 typedef struct 104 { 105 gfx_widget_font_data_t regular; 106 gfx_widget_font_data_t bold; 107 gfx_widget_font_data_t msg_queue; 108 } gfx_widget_fonts_t; 109 110 typedef struct cheevo_popup 111 { 112 char* title; 113 uintptr_t badge; 114 } cheevo_popup; 115 116 typedef struct disp_widget_msg 117 { 118 char *msg; 119 char *msg_new; 120 retro_task_t *task_ptr; 121 /* Used to detect title change */ 122 char *task_title_ptr; 123 124 uint32_t task_ident; 125 unsigned msg_len; 126 unsigned duration; 127 unsigned text_height; 128 unsigned width; 129 130 float msg_transition_animation; 131 float offset_y; 132 float alpha; 133 float unfold; 134 float hourglass_rotation; 135 gfx_timer_t hourglass_timer; /* float alignment */ 136 gfx_timer_t expiration_timer; /* float alignment */ 137 138 int8_t task_progress; 139 /* How many tasks have used this notification? */ 140 uint8_t task_count; 141 142 bool task_finished; 143 bool task_error; 144 bool task_cancelled; 145 bool expiration_timer_started; 146 /* Is it currently doing the fade out animation ? */ 147 bool dying; 148 /* Has the timer expired ? if so, should be set to dying */ 149 bool expired; 150 /* Unfold animation */ 151 bool unfolded; 152 bool unfolding; 153 } disp_widget_msg_t; 154 155 typedef struct dispgfx_widget 156 { 157 uint64_t gfx_widgets_frame_count; 158 159 #ifdef HAVE_THREADS 160 slock_t* current_msgs_lock; 161 #endif 162 fifo_buffer_t msg_queue; 163 disp_widget_msg_t* current_msgs[MSG_QUEUE_ONSCREEN_MAX]; 164 gfx_widget_fonts_t gfx_widget_fonts; /* ptr alignment */ 165 166 #ifdef HAVE_TRANSLATE 167 uintptr_t ai_service_overlay_texture; 168 #endif 169 uintptr_t msg_queue_icon; 170 uintptr_t msg_queue_icon_outline; 171 uintptr_t msg_queue_icon_rect; 172 uintptr_t gfx_widgets_icons_textures[ 173 MENU_WIDGETS_ICON_LAST]; 174 uintptr_t gfx_widgets_generic_tag; 175 176 size_t current_msgs_size; 177 178 #ifdef HAVE_TRANSLATE 179 int ai_service_overlay_state; 180 #endif 181 182 unsigned last_video_width; 183 unsigned last_video_height; 184 unsigned msg_queue_kill; 185 /* Count of messages bound to a task in current_msgs */ 186 unsigned msg_queue_tasks_count; 187 188 unsigned simple_widget_padding; 189 unsigned simple_widget_height; 190 191 /* Used for both generic and libretro messages */ 192 unsigned generic_message_height; 193 194 unsigned msg_queue_height; 195 unsigned msg_queue_spacing; 196 unsigned msg_queue_rect_start_x; 197 unsigned msg_queue_internal_icon_size; 198 unsigned msg_queue_internal_icon_offset; 199 unsigned msg_queue_icon_size_x; 200 unsigned msg_queue_icon_size_y; 201 unsigned msg_queue_icon_offset_y; 202 unsigned msg_queue_scissor_start_x; 203 unsigned msg_queue_default_rect_width_menu_alive; 204 unsigned msg_queue_default_rect_width; 205 unsigned msg_queue_regular_padding_x; 206 unsigned msg_queue_regular_text_start; 207 unsigned msg_queue_task_text_start_x; 208 unsigned msg_queue_task_rect_start_x; 209 unsigned msg_queue_task_hourglass_x; 210 unsigned divider_width_1px; 211 212 float last_scale_factor; 213 float backdrop_orig[16]; 214 float msg_queue_bg[16]; 215 float pure_white[16]; 216 #ifdef HAVE_TRANSLATE 217 unsigned ai_service_overlay_width; 218 unsigned ai_service_overlay_height; 219 #endif 220 221 char gfx_widgets_status_text[255]; 222 223 /* There can only be one message animation at a time to 224 * avoid confusing users */ 225 bool widgets_moving; 226 bool widgets_inited; 227 bool msg_queue_has_icons; 228 } dispgfx_widget_t; 229 230 231 /* A widget */ 232 /* TODO: cleanup all unused parameters */ 233 struct gfx_widget 234 { 235 /* called when the widgets system is initialized 236 * -> initialize the widget here */ 237 bool (*init)(gfx_display_t *p_disp, 238 gfx_animation_t *p_anim, 239 bool video_is_threaded, bool fullscreen); 240 241 /* called when the widgets system is freed 242 * -> free the widget here */ 243 void (*free)(void); 244 245 /* called when the graphics context is reset 246 * -> (re)load the textures here */ 247 void (*context_reset)(bool is_threaded, 248 unsigned width, unsigned height, bool fullscreen, 249 const char *dir_assets, char *font_path, 250 char* menu_png_path, 251 char* widgets_png_path); 252 253 /* called when the graphics context is destroyed 254 * -> release the textures here */ 255 void (*context_destroy)(void); 256 257 /* called when the window resolution changes 258 * -> (re)layout the widget here */ 259 void (*layout)(void *data, 260 bool is_threaded, const char *dir_assets, char *font_path); 261 262 /* called every frame on the main thread 263 * -> update the widget logic here */ 264 void (*iterate)(void *user_data, 265 unsigned width, unsigned height, bool fullscreen, 266 const char *dir_assets, char *font_path, 267 bool is_threaded); 268 269 /* called every frame 270 * (on the video thread if threaded video is on) 271 * -- data is a video_frame_info_t 272 * -- userdata is a dispgfx_widget_t 273 * -> draw the widget here */ 274 void (*frame)(void* data, void *userdata); 275 }; 276 277 float gfx_widgets_get_thumbnail_scale_factor( 278 const float dst_width, const float dst_height, 279 const float image_width, const float image_height); 280 281 void gfx_widgets_draw_icon( 282 void *userdata, 283 void *data_disp, 284 unsigned video_width, 285 unsigned video_height, 286 unsigned icon_width, 287 unsigned icon_height, 288 uintptr_t texture, 289 float x, float y, 290 float rotation, float scale_factor, 291 float *color); 292 293 void gfx_widgets_draw_text( 294 gfx_widget_font_data_t* font_data, 295 const char *text, 296 float x, float y, 297 int width, int height, 298 uint32_t color, 299 enum text_alignment text_align, 300 bool draw_outside); 301 302 void gfx_widgets_flush_text( 303 unsigned video_width, unsigned video_height, 304 gfx_widget_font_data_t* font_data); 305 306 typedef struct gfx_widget gfx_widget_t; 307 308 bool gfx_widgets_init( 309 void *data, 310 void *data_disp, 311 void *data_anim, 312 void *settings_data, 313 uintptr_t widgets_active_ptr, 314 bool video_is_threaded, 315 unsigned width, unsigned height, bool fullscreen, 316 const char *dir_assets, char *font_path); 317 318 void gfx_widgets_deinit(void *data, bool widgets_persisting); 319 320 void gfx_widgets_msg_queue_push( 321 void *data, 322 retro_task_t *task, const char *msg, 323 unsigned duration, 324 char *title, 325 enum message_queue_icon icon, 326 enum message_queue_category category, 327 unsigned prio, bool flush, 328 bool menu_is_alive); 329 330 void gfx_widget_volume_update_and_show(float new_volume, 331 bool mute); 332 333 void gfx_widgets_iterate( 334 void *data, 335 void *data_disp, 336 void *settings_data, 337 unsigned width, unsigned height, bool fullscreen, 338 const char *dir_assets, char *font_path, 339 bool is_threaded); 340 341 void gfx_widget_screenshot_taken(void *data, 342 const char *shotname, const char *filename); 343 344 /* AI Service functions */ 345 #ifdef HAVE_TRANSLATE 346 bool gfx_widgets_ai_service_overlay_load( 347 dispgfx_widget_t *p_dispwidget, 348 char* buffer, unsigned buffer_len, 349 enum image_type_enum image_type); 350 351 void gfx_widgets_ai_service_overlay_unload(dispgfx_widget_t *p_dispwidget); 352 #endif 353 354 #ifdef HAVE_CHEEVOS 355 void gfx_widgets_push_achievement(const char *title, const char *badge); 356 void gfx_widgets_set_leaderboard_display(unsigned id, const char* value); 357 void gfx_widgets_set_challenge_display(unsigned id, const char* badge); 358 #endif 359 360 /* Warning: not thread safe! */ 361 void gfx_widget_set_generic_message( 362 void *data, 363 const char *message, unsigned duration); 364 365 /* Warning: not thread safe! */ 366 void gfx_widget_set_libretro_message( 367 void *data, 368 const char *message, unsigned duration); 369 370 /* Warning: not thread safe! */ 371 void gfx_widget_set_progress_message(void *data, 372 const char *message, unsigned duration, 373 unsigned priority, int8_t progress); 374 375 /* Warning: not thread safe! */ 376 bool gfx_widget_start_load_content_animation(void); 377 378 /* All the functions below should be called in 379 * the video driver - once they are all added, set 380 * enable_menu_widgets to true for that driver */ 381 void gfx_widgets_frame(void *data); 382 383 void *dispwidget_get_ptr(void); 384 385 extern const gfx_widget_t gfx_widget_screenshot; 386 extern const gfx_widget_t gfx_widget_volume; 387 extern const gfx_widget_t gfx_widget_generic_message; 388 extern const gfx_widget_t gfx_widget_libretro_message; 389 extern const gfx_widget_t gfx_widget_progress_message; 390 extern const gfx_widget_t gfx_widget_load_content_animation; 391 392 #ifdef HAVE_CHEEVOS 393 extern const gfx_widget_t gfx_widget_achievement_popup; 394 extern const gfx_widget_t gfx_widget_leaderboard_display; 395 #endif 396 397 #endif 398