1 /*  RetroArch - A frontend for libretro.
2  *  Copyright (C) 2018-2020 - natinusala
3  *  Copyright (C) 2019      - Patrick Scheurenbrand
4  *
5  *  RetroArch is free software: you can redistribute it and/or modify it under the terms
6  *  of the GNU General Public License as published by the Free Software Found-
7  *  ation, either version 3 of the License, or (at your option) any later version.
8  *
9  *  RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
10  *  without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
11  *  PURPOSE.  See the GNU General Public License for more details.
12  *
13  *  You should have received a copy of the GNU General Public License along with RetroArch.
14  *  If not, see <http://www.gnu.org/licenses/>.
15  */
16 
17 #ifndef _OZONE_H
18 #define _OZONE_H
19 
20 typedef struct ozone_handle ozone_handle_t;
21 
22 #include "ozone_theme.h"
23 #include "ozone_sidebar.h"
24 
25 #include <retro_miscellaneous.h>
26 #include <retro_inline.h>
27 
28 #include "../../gfx/gfx_animation.h"
29 #include "../../gfx/gfx_display.h"
30 #include "../../gfx/gfx_thumbnail_path.h"
31 #include "../../gfx/gfx_thumbnail.h"
32 #include "../../menu_screensaver.h"
33 
34 #include "../../configuration.h"
35 
36 #define ANIMATION_PUSH_ENTRY_DURATION  166
37 #define ANIMATION_CURSOR_DURATION      133
38 #define ANIMATION_CURSOR_PULSE         500
39 
40 #define FONT_SIZE_FOOTER            18
41 #define FONT_SIZE_TITLE             36
42 #define FONT_SIZE_TIME              22
43 #define FONT_SIZE_ENTRIES_LABEL     24
44 #define FONT_SIZE_ENTRIES_SUBLABEL  18
45 #define FONT_SIZE_SIDEBAR           24
46 
47 #define HEADER_HEIGHT 87
48 #define FOOTER_HEIGHT 78
49 
50 #define ENTRY_PADDING_HORIZONTAL_HALF  60
51 #define ENTRY_PADDING_HORIZONTAL_FULL  150
52 #define ENTRY_PADDING_VERTICAL         20
53 #define ENTRY_HEIGHT                   50
54 #define ENTRY_SPACING                  8
55 #define ENTRY_ICON_SIZE                46
56 #define ENTRY_ICON_PADDING             15
57 
58 /* > 'SIDEBAR_WIDTH' must be kept in sync with
59  *   menu driver metrics */
60 #define SIDEBAR_WIDTH               408
61 #define SIDEBAR_X_PADDING           40
62 #define SIDEBAR_Y_PADDING           20
63 #define SIDEBAR_ENTRY_HEIGHT        50
64 #define SIDEBAR_ENTRY_Y_PADDING     10
65 #define SIDEBAR_ENTRY_ICON_SIZE     46
66 #define SIDEBAR_ENTRY_ICON_PADDING  15
67 #define SIDEBAR_GRADIENT_HEIGHT     28
68 
69 #define FULLSCREEN_THUMBNAIL_PADDING 48
70 
71 #define CURSOR_SIZE 64
72 /* Cursor becomes active when it moves more
73  * than CURSOR_ACTIVE_DELTA pixels (adjusted
74  * by current scale factor) */
75 #define CURSOR_ACTIVE_DELTA 3
76 
77 #define INTERVAL_OSK_CURSOR            (0.5f * 1000000)
78 
79 #if defined(__APPLE__)
80 /* UTF-8 support is currently broken on Apple devices... */
81 #define OZONE_TICKER_SPACER "   |   "
82 #else
83 /* <EM SPACE><BULLET><EM SPACE>
84  * UCN equivalent: "\u2003\u2022\u2003" */
85 #define OZONE_TICKER_SPACER "\xE2\x80\x83\xE2\x80\xA2\xE2\x80\x83"
86 #endif
87 
88 enum ozone_onscreen_entry_position_type
89 {
90    OZONE_ONSCREEN_ENTRY_FIRST = 0,
91    OZONE_ONSCREEN_ENTRY_LAST,
92    OZONE_ONSCREEN_ENTRY_CENTRE
93 };
94 
95 /* This structure holds all objects + metadata
96  * corresponding to a particular font */
97 typedef struct
98 {
99    font_data_t *font;
100    video_font_raster_block_t raster_block; /* ptr alignment */
101    int glyph_width;
102    int wideglyph_width;
103    int line_height;
104    int line_ascender;
105    int line_centre_offset;
106 } ozone_font_data_t;
107 
108 /* Container for a footer text label */
109 typedef struct
110 {
111    const char *str;
112    int width;
113 } ozone_footer_label_t;
114 
115 struct ozone_handle
116 {
117    menu_input_pointer_t pointer; /* retro_time_t alignment */
118 
119    ozone_theme_t *theme;
120    gfx_thumbnail_path_data_t *thumbnail_path_data;
121    char *pending_message;
122    file_list_t selection_buf_old;                  /* ptr alignment */
123    file_list_t horizontal_list; /* console tabs */ /* ptr alignment */
124    menu_screensaver_t *screensaver;
125 
126    struct
127    {
128       ozone_font_data_t footer;
129       ozone_font_data_t title;
130       ozone_font_data_t time;
131       ozone_font_data_t entries_label;
132       ozone_font_data_t entries_sublabel;
133       ozone_font_data_t sidebar;
134    } fonts;
135 
136    void (*word_wrap)(char *dst, size_t dst_size, const char *src,
137       int line_width, int wideglyph_width, unsigned max_lines);
138 
139    struct
140    {
141       ozone_footer_label_t ok;
142       ozone_footer_label_t back;
143       ozone_footer_label_t search;
144       ozone_footer_label_t fullscreen_thumbs;
145       ozone_footer_label_t metadata_toggle;
146    } footer_labels;
147 
148    struct
149    {
150       gfx_thumbnail_t right;  /* uintptr_t alignment */
151       gfx_thumbnail_t left;   /* uintptr_t alignment */
152    } thumbnails;
153    uintptr_t textures[OZONE_THEME_TEXTURE_LAST];
154    uintptr_t icons_textures[OZONE_ENTRIES_ICONS_TEXTURE_LAST];
155    uintptr_t tab_textures[OZONE_TAB_TEXTURE_LAST];
156 
157    size_t categories_selection_ptr; /* active tab id  */
158    size_t categories_active_idx_old;
159 
160    size_t selection; /* currently selected entry */
161    size_t selection_old; /* previously selected entry (for fancy animation) */
162    size_t selection_old_list;
163    size_t fullscreen_thumbnail_selection;
164    size_t num_search_terms_old;
165    size_t pointer_categories_selection;
166    size_t first_onscreen_entry;
167    size_t last_onscreen_entry;
168    size_t first_onscreen_category;
169    size_t last_onscreen_category;
170 
171    int depth;
172 
173    struct
174    {
175       int header_height;
176       int footer_height;
177 
178       int entry_padding_horizontal_half;
179       int entry_padding_horizontal_full;
180       int entry_padding_vertical;
181       int entry_height;
182       int entry_spacing;
183       int entry_icon_size;
184       int entry_icon_padding;
185 
186       int sidebar_width_normal;
187       int sidebar_width_collapsed;
188 
189       int sidebar_padding_horizontal;
190       int sidebar_padding_vertical;
191       int sidebar_entry_padding_vertical;
192       int sidebar_entry_height;
193       int sidebar_entry_icon_size;
194       int sidebar_entry_icon_padding;
195       int sidebar_gradient_height;
196 
197       int cursor_size;
198 
199       int thumbnail_bar_width;
200       int fullscreen_thumbnail_padding;
201 
202       int spacer_1px;
203       int spacer_2px;
204       int spacer_3px;
205       int spacer_5px;
206    } dimensions;
207 
208    unsigned footer_labels_language;
209    unsigned last_width;
210    unsigned last_height;
211    unsigned entries_height;
212    unsigned theme_dynamic_cursor_state; /* 0 -> 1 -> 0 -> 1 [...] */
213    unsigned selection_core_name_lines;
214    unsigned selection_lastplayed_lines;
215    unsigned old_list_offset_y;
216 
217    float dimensions_sidebar_width; /* animated field */
218    float sidebar_offset;
219    float last_scale_factor;
220    float pure_white[16];
221 
222    struct
223    {
224       float cursor_alpha;
225       float scroll_y;
226       float scroll_y_sidebar;
227 
228       float list_alpha;
229 
230       float messagebox_alpha;
231 
232       float sidebar_text_alpha;
233       float thumbnail_bar_position;
234 
235       float fullscreen_thumbnail_alpha;
236       float left_thumbnail_alpha;
237    } animations;
238 
239    struct
240    {
241       float selection_border[16];
242       float selection[16];
243       float entries_border[16];
244       float entries_icon[16];
245       float entries_checkmark[16];
246       float cursor_alpha[16];
247 
248       float cursor_border[16];
249       float message_background[16];
250    } theme_dynamic;
251 
252    float scroll_old;
253 
254    int16_t pointer_active_delta;
255    int16_t cursor_x_old;
256    int16_t cursor_y_old;
257 
258    uint8_t system_tab_end;
259    uint8_t tabs[OZONE_SYSTEM_TAB_LAST];
260 
261    char title[PATH_MAX_LENGTH];
262 
263    char assets_path[PATH_MAX_LENGTH];
264    char png_path[PATH_MAX_LENGTH];
265    char icons_path[PATH_MAX_LENGTH];
266    char tab_path[PATH_MAX_LENGTH];
267    char fullscreen_thumbnail_label[255];
268 
269    char selection_core_name[255];
270    char selection_playtime[255];
271    char selection_lastplayed[255];
272    char selection_entry_enumeration[255];
273 
274    bool cursor_in_sidebar;
275    bool cursor_in_sidebar_old;
276 
277    bool fade_direction; /* false = left to right, true = right to left */
278 
279    bool draw_sidebar;
280    bool empty_playlist;
281 
282    bool osk_cursor; /* true = display it, false = don't */
283    bool messagebox_state;
284    bool messagebox_state_old;
285    bool should_draw_messagebox;
286 
287    bool need_compute;
288    bool draw_old_list;
289    bool has_all_assets;
290 
291    bool is_playlist;
292    bool is_playlist_old;
293 
294    bool pointer_in_sidebar;
295    bool last_pointer_in_sidebar;
296    bool show_cursor;
297    bool show_screensaver;
298    bool cursor_mode;
299    bool sidebar_collapsed;
300    bool show_thumbnail_bar;
301    bool pending_hide_thumbnail_bar;
302    bool fullscreen_thumbnails_available;
303    bool show_fullscreen_thumbnails;
304    bool selection_core_is_viewer;
305 
306    bool force_metadata_display;
307 
308    bool is_db_manager_list;
309    bool is_file_list;
310    bool is_quick_menu;
311    bool first_frame;
312 
313    struct
314    {
315       retro_time_t start_time;
316       float amplitude;
317       enum menu_action direction;
318       bool wiggling;
319    } cursor_wiggle_state;
320 };
321 
322 /* If you change this struct, also
323    change ozone_alloc_node and
324    ozone_copy_node */
325 typedef struct ozone_node
326 {
327    char *fullpath;            /* Entry fullpath */
328    char *console_name;        /* Console tab name */
329    uintptr_t icon;            /* Console tab icon */
330    uintptr_t content_icon;    /* console content icon */
331    unsigned height;           /* Entry height */
332    unsigned position_y;       /* Entry position Y */
333    unsigned sublabel_lines;   /* Entry sublabel lines */
334    bool wrap;                 /* Wrap entry? */
335 } ozone_node_t;
336 
337 void ozone_draw_entries(
338       ozone_handle_t *ozone,
339       gfx_display_t *p_disp,
340       gfx_animation_t *p_anim,
341       settings_t *settings,
342       void *userdata,
343       unsigned video_width,
344       unsigned video_height,
345       unsigned selection,
346       unsigned selection_old,
347       file_list_t *selection_buf,
348       float alpha,
349       float scroll_y,
350       bool is_playlist);
351 
352 void ozone_draw_sidebar(
353       ozone_handle_t *ozone,
354       gfx_display_t *p_disp,
355       gfx_animation_t *p_anim,
356       settings_t *settings,
357       void *userdata,
358       unsigned video_width,
359       unsigned video_height,
360       bool libretro_running,
361       float menu_framebuffer_opacity
362       );
363 
364 void ozone_change_tab(ozone_handle_t *ozone,
365       enum msg_hash_enums tab,
366       enum menu_settings_type type);
367 
368 void ozone_sidebar_goto(ozone_handle_t *ozone, unsigned new_selection);
369 
370 unsigned ozone_get_sidebar_height(ozone_handle_t *ozone);
371 
372 unsigned ozone_get_selected_sidebar_y_position(ozone_handle_t *ozone);
373 
374 void ozone_leave_sidebar(ozone_handle_t *ozone,
375       settings_t *settings,
376       uintptr_t tag);
377 
378 void ozone_go_to_sidebar(ozone_handle_t *ozone,
379       settings_t *settings,
380       uintptr_t tag);
381 
382 void ozone_refresh_horizontal_list(ozone_handle_t *ozone,
383       settings_t *settings);
384 
385 void ozone_init_horizontal_list(ozone_handle_t *ozone,
386       settings_t *settings);
387 
388 void ozone_context_destroy_horizontal_list(ozone_handle_t *ozone);
389 
390 void ozone_context_reset_horizontal_list(ozone_handle_t *ozone);
391 
392 ozone_node_t *ozone_alloc_node(void);
393 
394 size_t ozone_list_get_size(void *data, enum menu_list_type type);
395 
396 void ozone_free_list_nodes(file_list_t *list, bool actiondata);
397 
398 bool ozone_is_playlist(ozone_handle_t *ozone, bool depth);
399 
400 void ozone_compute_entries_position(
401       ozone_handle_t *ozone,
402       settings_t *settings,
403       size_t entries_end);
404 
405 void ozone_update_scroll(ozone_handle_t *ozone, bool allow_animation, ozone_node_t *node);
406 
407 void ozone_sidebar_update_collapse(
408       ozone_handle_t *ozone,
409       settings_t *settings,
410       bool allow_animation);
411 
412 void ozone_refresh_sidebars(
413       ozone_handle_t *ozone,
414       settings_t *settings,
415       unsigned video_height);
416 
417 void ozone_entries_update_thumbnail_bar(ozone_handle_t *ozone, bool is_playlist, bool allow_animation);
418 
419 void ozone_draw_thumbnail_bar(
420       ozone_handle_t *ozone,
421       gfx_display_t *p_disp,
422       gfx_animation_t *p_anim,
423       settings_t *settings,
424       void *userdata,
425       unsigned video_width,
426       unsigned video_height,
427       bool libretro_running,
428       float menu_framebuffer_opacity);
429 
430 void ozone_hide_fullscreen_thumbnails(ozone_handle_t *ozone, bool animate);
431 void ozone_show_fullscreen_thumbnails(ozone_handle_t *ozone);
432 
ozone_count_lines(const char * str)433 static INLINE unsigned ozone_count_lines(const char *str)
434 {
435    unsigned c     = 0;
436    unsigned lines = 1;
437 
438    for (c = 0; str[c]; c++)
439       lines += (str[c] == '\n');
440    return lines;
441 }
442 
443 void ozone_update_content_metadata(ozone_handle_t *ozone);
444 
445 void ozone_font_flush(
446       unsigned video_width, unsigned video_height,
447       ozone_font_data_t *font_data);
448 
449 void ozone_toggle_metadata_override(ozone_handle_t *ozone);
450 
451 #define OZONE_WIGGLE_DURATION 15
452 
453 /**
454  * Starts the cursor wiggle animation in the given direction
455  * Use ozone_get_cursor_wiggle_offset to read the animation
456  * once it has started
457  */
458 void ozone_start_cursor_wiggle(ozone_handle_t* ozone, enum menu_action direction);
459 
460 /**
461  * Changes x and y to the current offset of the cursor wiggle animation
462  */
463 void ozone_apply_cursor_wiggle_offset(ozone_handle_t* ozone, int* x, size_t* y);
464 
465 void ozone_list_cache(void *data,
466       enum menu_list_type type, unsigned action);
467 
468 #endif
469