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