1 /* RetroArch - A frontend for libretro.
2 * Copyright (C) 2011-2017 - Daniel De Matteis
3 * Copyright (C) 2014-2017 - Jean-André Santoni
4 * Copyright (C) 2016-2019 - Brad Parker
5 * Copyright (C) 2018 - Alfredo Monclús
6 *
7 * RetroArch is free software: you can redistribute it and/or modify it under the terms
8 * of the GNU General Public License as published by the Free Software Found-
9 * ation, either version 3 of the License, or (at your option) any later version.
10 *
11 * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
12 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
13 * PURPOSE. See the GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along with RetroArch.
16 * If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #include <stdlib.h>
20 #include <stddef.h>
21 #include <stdint.h>
22 #include <string.h>
23 #include <limits.h>
24
25 #include <file/file_path.h>
26 #include <compat/posix_string.h>
27 #include <compat/strl.h>
28 #include <formats/image.h>
29 #include <string/stdstring.h>
30 #include <lists/string_list.h>
31 #include <gfx/math/matrix_4x4.h>
32 #include <streams/file_stream.h>
33 #include <encodings/utf.h>
34 #include <features/features_cpu.h>
35
36 #ifdef HAVE_CONFIG_H
37 #include "../../config.h"
38 #endif
39
40 #include "../../frontend/frontend_driver.h"
41
42 #include "../menu_driver.h"
43 #include "../../gfx/gfx_animation.h"
44 #include "../menu_entries.h"
45 #include "../menu_input.h"
46
47 #include "../../core_info.h"
48 #include "../../core.h"
49
50 #include "../../input/input_osk.h"
51
52 #include "../widgets/menu_filebrowser.h"
53
54 #include "../../verbosity.h"
55 #include "../../configuration.h"
56 #include "../../playlist.h"
57 #include "../../retroarch.h"
58
59 #include "../../tasks/tasks_internal.h"
60
61 #ifdef HAVE_CHEEVOS
62 #include "../../cheevos/badges.h"
63 #endif
64
65 #include "../../content.h"
66
67 #define STRIPES_RIBBON_ROWS 64
68 #define STRIPES_RIBBON_COLS 64
69 #define STRIPES_RIBBON_VERTICES 2*STRIPES_RIBBON_COLS*STRIPES_RIBBON_ROWS-2*STRIPES_RIBBON_COLS
70
71 #ifndef STRIPES_DELAY
72 #define STRIPES_DELAY 166
73 #endif
74
75 #define BATTERY_LEVEL_CHECK_INTERVAL (30 * 1000000)
76
77 #if 0
78 #define STRIPES_DEBUG
79 #endif
80
81 /* NOTE: If you change this you HAVE to update
82 * stripes_alloc_node() and stripes_copy_node() */
83 typedef struct
84 {
85 float alpha;
86 float label_alpha;
87 float zoom;
88 float x;
89 float y;
90 float width;
91 uintptr_t icon;
92 uintptr_t content_icon;
93 char *fullpath;
94 } stripes_node_t;
95
96 enum
97 {
98 STRIPES_TEXTURE_MAIN_MENU = 0,
99 STRIPES_TEXTURE_SETTINGS,
100 STRIPES_TEXTURE_HISTORY,
101 STRIPES_TEXTURE_FAVORITES,
102 STRIPES_TEXTURE_MUSICS,
103 #ifdef HAVE_FFMPEG
104 STRIPES_TEXTURE_MOVIES,
105 #endif
106 #ifdef HAVE_NETWORKING
107 STRIPES_TEXTURE_NETPLAY,
108 STRIPES_TEXTURE_ROOM,
109 /* stub these out until we have the icons
110 STRIPES_TEXTURE_ROOM_LAN,
111 STRIPES_TEXTURE_ROOM_MITM,*/
112 #endif
113 #ifdef HAVE_IMAGEVIEWER
114 STRIPES_TEXTURE_IMAGES,
115 #endif
116 STRIPES_TEXTURE_SETTING,
117 STRIPES_TEXTURE_SUBSETTING,
118 STRIPES_TEXTURE_ARROW,
119 STRIPES_TEXTURE_RUN,
120 STRIPES_TEXTURE_CLOSE,
121 STRIPES_TEXTURE_RESUME,
122 STRIPES_TEXTURE_SAVESTATE,
123 STRIPES_TEXTURE_LOADSTATE,
124 STRIPES_TEXTURE_UNDO,
125 STRIPES_TEXTURE_CORE_INFO,
126 STRIPES_TEXTURE_BLUETOOTH,
127 STRIPES_TEXTURE_WIFI,
128 STRIPES_TEXTURE_CORE_OPTIONS,
129 STRIPES_TEXTURE_INPUT_REMAPPING_OPTIONS,
130 STRIPES_TEXTURE_CHEAT_OPTIONS,
131 STRIPES_TEXTURE_DISK_OPTIONS,
132 STRIPES_TEXTURE_SHADER_OPTIONS,
133 STRIPES_TEXTURE_ACHIEVEMENT_LIST,
134 STRIPES_TEXTURE_SCREENSHOT,
135 STRIPES_TEXTURE_RELOAD,
136 STRIPES_TEXTURE_RENAME,
137 STRIPES_TEXTURE_FILE,
138 STRIPES_TEXTURE_FOLDER,
139 STRIPES_TEXTURE_ZIP,
140 STRIPES_TEXTURE_FAVORITE,
141 STRIPES_TEXTURE_ADD_FAVORITE,
142 STRIPES_TEXTURE_MUSIC,
143 STRIPES_TEXTURE_IMAGE,
144 STRIPES_TEXTURE_MOVIE,
145 STRIPES_TEXTURE_CORE,
146 STRIPES_TEXTURE_RDB,
147 STRIPES_TEXTURE_CURSOR,
148 STRIPES_TEXTURE_SWITCH_ON,
149 STRIPES_TEXTURE_SWITCH_OFF,
150 STRIPES_TEXTURE_CLOCK,
151 STRIPES_TEXTURE_BATTERY_FULL,
152 STRIPES_TEXTURE_BATTERY_CHARGING,
153 STRIPES_TEXTURE_POINTER,
154 STRIPES_TEXTURE_ADD,
155 STRIPES_TEXTURE_KEY,
156 STRIPES_TEXTURE_KEY_HOVER,
157 STRIPES_TEXTURE_DIALOG_SLICE,
158 STRIPES_TEXTURE_LAST
159 };
160
161 enum
162 {
163 STRIPES_SYSTEM_TAB_MAIN = 0,
164 STRIPES_SYSTEM_TAB_SETTINGS,
165 STRIPES_SYSTEM_TAB_HISTORY,
166 STRIPES_SYSTEM_TAB_FAVORITES,
167 STRIPES_SYSTEM_TAB_MUSIC,
168 #ifdef HAVE_FFMPEG
169 STRIPES_SYSTEM_TAB_VIDEO,
170 #endif
171 #ifdef HAVE_IMAGEVIEWER
172 STRIPES_SYSTEM_TAB_IMAGES,
173 #endif
174 #ifdef HAVE_NETWORKING
175 STRIPES_SYSTEM_TAB_NETPLAY,
176 #endif
177 STRIPES_SYSTEM_TAB_ADD,
178
179 /* End of this enum - use the last one to determine num of possible tabs */
180 STRIPES_SYSTEM_TAB_MAX_LENGTH
181 };
182
183 typedef struct stripes_handle
184 {
185 bool mouse_show;
186
187 uint8_t system_tab_end;
188 uint8_t tabs[STRIPES_SYSTEM_TAB_MAX_LENGTH];
189
190 int depth;
191 int old_depth;
192 int icon_size;
193 int cursor_size;
194
195 size_t categories_selection_ptr;
196 size_t categories_selection_ptr_old;
197 size_t selection_ptr_old;
198
199 unsigned categories_active_idx;
200 unsigned categories_active_idx_old;
201 uintptr_t thumbnail;
202 uintptr_t left_thumbnail;
203 uintptr_t savestate_thumbnail;
204
205 float x;
206 float alpha;
207 float thumbnail_width;
208 float thumbnail_height;
209 float left_thumbnail_width;
210 float left_thumbnail_height;
211 float savestate_thumbnail_width;
212 float savestate_thumbnail_height;
213 float above_subitem_offset;
214 float above_item_offset;
215 float active_item_factor;
216 float under_item_offset;
217 float shadow_offset;
218 float font_size;
219 float font2_size;
220
221 float margins_screen_left;
222 float margins_screen_top;
223 float margins_setting_left;
224 float margins_title_left;
225 float margins_title_top;
226 float margins_title_bottom;
227 float margins_label_left;
228 float margins_label_top;
229 float icon_spacing_horizontal;
230 float icon_spacing_vertical;
231 float items_active_alpha;
232 float items_active_zoom;
233 float items_passive_alpha;
234 float items_passive_zoom;
235 float margins_dialog;
236 float margins_slice;
237 float textures_arrow_alpha;
238 float categories_x_pos;
239 float categories_angle;
240 float categories_active_y;
241 float categories_before_y;
242 float categories_after_y;
243 float categories_active_x;
244 float categories_before_x;
245 float categories_after_x;
246 float categories_passive_alpha;
247 float categories_passive_zoom;
248 float categories_passive_width;
249 float categories_active_zoom;
250 float categories_active_alpha;
251 float categories_active_width;
252
253 char title_name[255];
254 char *box_message;
255 char *thumbnail_system;
256 char *thumbnail_content;
257 char *savestate_thumbnail_file_path;
258 char *thumbnail_file_path;
259 char *left_thumbnail_file_path;
260 char *bg_file_path;
261
262 file_list_t selection_buf_old; /* ptr alignment */
263 file_list_t horizontal_list; /* ptr alignment */
264
265 struct
266 {
267 uintptr_t bg;
268 uintptr_t list[STRIPES_TEXTURE_LAST];
269 } textures;
270
271 stripes_node_t main_menu_node;
272 #ifdef HAVE_IMAGEVIEWER
273 stripes_node_t images_tab_node;
274 #endif
275 stripes_node_t music_tab_node;
276 #ifdef HAVE_FFMPEG
277 stripes_node_t video_tab_node;
278 #endif
279 stripes_node_t settings_tab_node;
280 stripes_node_t history_tab_node;
281 stripes_node_t favorites_tab_node;
282 stripes_node_t add_tab_node;
283 stripes_node_t netplay_tab_node;
284
285 font_data_t *font;
286 font_data_t *font2;
287 video_font_raster_block_t raster_block;
288 video_font_raster_block_t raster_block2;
289
290 void (*word_wrap)(char *dst, size_t dst_size, const char *src,
291 int line_width, int wideglyph_width, unsigned max_lines);
292 } stripes_handle_t;
293
294 float stripes_scale_mod[8] = {
295 1, 1, 1, 1, 1, 1, 1, 1
296 };
297
298 static float stripes_coord_shadow[] = {
299 0, 0, 0,
300 0, 0, 0,
301 0, 0, 0,
302 0, 0, 0,
303 0, 0, 0, 0
304 };
305
306 static float stripes_coord_black[] = {
307 0, 0, 0,
308 0, 0, 0,
309 0, 0, 0,
310 0, 0, 0,
311 0, 0, 0, 0
312 };
313
314 static float stripes_coord_white[] = {
315 1, 1, 1,
316 1, 1, 1,
317 1, 1, 1,
318 1, 1, 1,
319 1, 1, 1, 1
320 };
321
322 static float stripes_item_color[] = {
323 1, 1, 1,
324 1, 1, 1,
325 1, 1, 1,
326 1, 1, 1,
327 1, 1, 1, 1
328 };
329
HueToRGB(float v1,float v2,float vH)330 static float HueToRGB(float v1, float v2, float vH)
331 {
332 if (vH < 0)
333 vH += 1;
334
335 if (vH > 1)
336 vH -= 1;
337
338 if ((6 * vH) < 1)
339 return (v1 + (v2 - v1) * 6 * vH);
340
341 if ((2 * vH) < 1)
342 return v2;
343
344 if ((3 * vH) < 2)
345 return (v1 + (v2 - v1) * ((2.0f / 3) - vH) * 6);
346
347 return v1;
348 }
349
HSLToRGB(float H,float S,float L,float * rgb)350 static void HSLToRGB(float H, float S, float L, float *rgb) {
351 if (S == 0)
352 rgb[0] = rgb[1] = rgb[2] = L;
353 else
354 {
355 float v1, v2;
356
357 v2 = (L < 0.5) ? (L * (1 + S)) : ((L + S) - (L * S));
358 v1 = 2 * L - v2;
359
360 rgb[0] = HueToRGB(v1, v2, H + (1.0f / 3));
361 rgb[1] = HueToRGB(v1, v2, H);
362 rgb[2] = HueToRGB(v1, v2, H - (1.0f / 3));
363 }
364 }
365
366 static void stripes_calculate_visible_range(const stripes_handle_t *stripes,
367 unsigned height, size_t list_size, unsigned current,
368 unsigned *first, unsigned *last);
369
stripes_theme_ident(void)370 const char* stripes_theme_ident(void)
371 {
372 settings_t *settings = config_get_ptr();
373 switch (settings->uints.menu_xmb_theme)
374 {
375 case XMB_ICON_THEME_FLATUI:
376 return "flatui";
377 case XMB_ICON_THEME_RETROACTIVE:
378 return "retroactive";
379 case XMB_ICON_THEME_RETROSYSTEM:
380 return "retrosystem";
381 case XMB_ICON_THEME_PIXEL:
382 return "pixel";
383 case XMB_ICON_THEME_NEOACTIVE:
384 return "neoactive";
385 case XMB_ICON_THEME_SYSTEMATIC:
386 return "systematic";
387 case XMB_ICON_THEME_DOTART:
388 return "dot-art";
389 case XMB_ICON_THEME_CUSTOM:
390 return "custom";
391 case XMB_ICON_THEME_MONOCHROME_INVERTED:
392 return "monochrome-inverted";
393 case XMB_ICON_THEME_MONOCHROME:
394 default:
395 break;
396 }
397
398 return "monochrome";
399 }
400
401 /* NOTE: This exists because calloc()ing stripes_node_t is expensive
402 * when you can have big lists like MAME and fba playlists */
stripes_alloc_node(void)403 static stripes_node_t *stripes_alloc_node(void)
404 {
405 stripes_node_t *node = (stripes_node_t*)malloc(sizeof(*node));
406
407 node->alpha = node->label_alpha = 0;
408 node->zoom = node->x = node->y = 0;
409 node->icon = node->content_icon = 0;
410 node->fullpath = NULL;
411
412 return node;
413 }
414
stripes_free_node(stripes_node_t * node)415 static void stripes_free_node(stripes_node_t *node)
416 {
417 if (!node)
418 return;
419
420 if (node->fullpath)
421 free(node->fullpath);
422
423 node->fullpath = NULL;
424
425 free(node);
426 }
427
428 /**
429 * @brief frees all stripes_node_t in a file_list_t
430 *
431 * file_list_t asumes userdata holds a simple structure and
432 * free()'s it. Can't change this at the time because other
433 * code depends on this behavior.
434 *
435 * @param list
436 * @param actiondata whether to free actiondata too
437 */
stripes_free_list_nodes(file_list_t * list,bool actiondata)438 static void stripes_free_list_nodes(file_list_t *list, bool actiondata)
439 {
440 unsigned i, size = list ? list->size : 0;
441
442 for (i = 0; i < size; ++i)
443 {
444 stripes_free_node((stripes_node_t*)file_list_get_userdata_at_offset(list, i));
445
446 list->list[i].userdata = NULL;
447
448 if (actiondata)
449 file_list_free_actiondata(list, i);
450 }
451 }
452
stripes_copy_node(const stripes_node_t * old_node)453 static stripes_node_t *stripes_copy_node(const stripes_node_t *old_node)
454 {
455 stripes_node_t *new_node = (stripes_node_t*)malloc(sizeof(*new_node));
456
457 *new_node = *old_node;
458 new_node->fullpath = old_node->fullpath ? strdup(old_node->fullpath) : NULL;
459
460 return new_node;
461 }
462
stripes_thumbnails_ident(char pos)463 static const char *stripes_thumbnails_ident(char pos)
464 {
465 char folder = 0;
466 settings_t *settings = config_get_ptr();
467
468 if (pos == 'R')
469 folder = settings->uints.gfx_thumbnails;
470 if (pos == 'L')
471 folder = settings->uints.menu_left_thumbnails;
472
473 switch (folder)
474 {
475 case 1:
476 return "Named_Snaps";
477 case 2:
478 return "Named_Titles";
479 case 3:
480 return "Named_Boxarts";
481 case 0:
482 default:
483 break;
484 }
485
486 return msg_hash_to_str(MENU_ENUM_LABEL_VALUE_OFF);
487 }
488
stripes_list_get_selection(void * data)489 static size_t stripes_list_get_selection(void *data)
490 {
491 stripes_handle_t *stripes = (stripes_handle_t*)data;
492
493 if (!stripes)
494 return 0;
495
496 return stripes->categories_selection_ptr;
497 }
498
stripes_list_get_size(void * data,enum menu_list_type type)499 static size_t stripes_list_get_size(void *data, enum menu_list_type type)
500 {
501 stripes_handle_t *stripes = (stripes_handle_t*)data;
502
503 switch (type)
504 {
505 case MENU_LIST_PLAIN:
506 return menu_entries_get_stack_size(0);
507 case MENU_LIST_HORIZONTAL:
508 return stripes->horizontal_list.size;
509 case MENU_LIST_TABS:
510 return stripes->system_tab_end;
511 }
512
513 return 0;
514 }
515
stripes_list_get_entry(void * data,enum menu_list_type type,unsigned i)516 static void *stripes_list_get_entry(void *data,
517 enum menu_list_type type, unsigned i)
518 {
519 size_t list_size = 0;
520 stripes_handle_t *stripes = (stripes_handle_t*)data;
521
522 switch (type)
523 {
524 case MENU_LIST_PLAIN:
525 {
526 file_list_t *menu_stack = menu_entries_get_menu_stack_ptr(0);
527 list_size = menu_entries_get_stack_size(0);
528 if (i < list_size)
529 return (void*)&menu_stack->list[i];
530 }
531 break;
532 case MENU_LIST_HORIZONTAL:
533 list_size = stripes->horizontal_list.size;
534 if (i < list_size)
535 return (void*)&stripes->horizontal_list.list[i];
536 break;
537 default:
538 break;
539 }
540
541 return NULL;
542 }
543
stripes_item_y(const stripes_handle_t * stripes,int i,size_t current)544 static INLINE float stripes_item_y(const stripes_handle_t *stripes, int i, size_t current)
545 {
546 float iy = stripes->icon_spacing_vertical;
547
548 if (i < (int)current)
549 if (stripes->depth > 1)
550 iy *= (i - (int)current + stripes->above_subitem_offset);
551 else
552 iy *= (i - (int)current + stripes->above_item_offset);
553 else
554 iy *= (i - (int)current + stripes->under_item_offset);
555
556 if (i == (int)current)
557 iy = stripes->icon_spacing_vertical * stripes->active_item_factor;
558
559 return iy;
560 }
561
stripes_draw_icon(void * userdata,unsigned video_width,unsigned video_height,bool xmb_shadows_enable,int icon_size,math_matrix_4x4 * mymat,uintptr_t texture,float x,float y,unsigned width,unsigned height,float alpha,float rotation,float scale_factor,float * color,float shadow_offset)562 static void stripes_draw_icon(
563 void *userdata,
564 unsigned video_width,
565 unsigned video_height,
566 bool xmb_shadows_enable,
567 int icon_size,
568 math_matrix_4x4 *mymat,
569 uintptr_t texture,
570 float x,
571 float y,
572 unsigned width,
573 unsigned height,
574 float alpha,
575 float rotation,
576 float scale_factor,
577 float *color,
578 float shadow_offset)
579 {
580 gfx_display_ctx_draw_t draw;
581 struct video_coords coords;
582
583 if (
584 (x < (-icon_size / 2.0f)) ||
585 (x > width) ||
586 (y < (icon_size / 2.0f)) ||
587 (y > height + icon_size)
588 )
589 return;
590
591 coords.vertices = 4;
592 coords.vertex = NULL;
593 coords.tex_coord = NULL;
594 coords.lut_tex_coord = NULL;
595
596 draw.width = icon_size;
597 draw.height = icon_size;
598 draw.rotation = rotation;
599 draw.scale_factor = scale_factor;
600 #if defined(VITA) || defined(WIIU)
601 draw.width *= scale_factor;
602 draw.height *= scale_factor;
603 #endif
604 draw.coords = &coords;
605 draw.matrix_data = mymat;
606 draw.texture = texture;
607 draw.prim_type = GFX_DISPLAY_PRIM_TRIANGLESTRIP;
608 draw.pipeline_id = 0;
609
610 if (xmb_shadows_enable)
611 {
612 gfx_display_set_alpha(stripes_coord_shadow, color[3] * 0.35f);
613
614 coords.color = stripes_coord_shadow;
615 draw.x = x + shadow_offset;
616 draw.y = height - y - shadow_offset;
617
618 #if defined(VITA) || defined(WIIU)
619 if (scale_factor < 1)
620 {
621 draw.x = draw.x + (icon_size-draw.width)/2;
622 draw.y = draw.y + (icon_size-draw.width)/2;
623 }
624 #endif
625 if (draw.height > 0 && draw.width > 0)
626 if (dispctx && dispctx->draw)
627 dispctx->draw(&draw, userdata, video_width, video_height);
628 }
629
630 coords.color = (const float*)color;
631 draw.x = x;
632 draw.y = height - y;
633
634 #if defined(VITA) || defined(WIIU)
635 if (scale_factor < 1)
636 {
637 draw.x = draw.x + (icon_size-draw.width)/2;
638 draw.y = draw.y + (icon_size-draw.width)/2;
639 }
640 #endif
641 if (draw.height > 0 && draw.width > 0)
642 if (dispctx && dispctx->draw)
643 dispctx->draw(&draw, userdata, video_width, video_height);
644 }
645
stripes_draw_text(bool xmb_shadows_enable,stripes_handle_t * stripes,const char * str,float x,float y,float scale_factor,float alpha,enum text_alignment text_align,unsigned width,unsigned height,font_data_t * font)646 static void stripes_draw_text(
647 bool xmb_shadows_enable,
648 stripes_handle_t *stripes,
649 const char *str, float x,
650 float y, float scale_factor, float alpha,
651 enum text_alignment text_align,
652 unsigned width, unsigned height, font_data_t* font)
653 {
654 uint32_t color;
655 uint8_t a8;
656 settings_t *settings;
657
658 if (alpha > stripes->alpha)
659 alpha = stripes->alpha;
660
661 a8 = 255 * alpha;
662
663 /* Avoid drawing 100% transparent text */
664 if (a8 == 0)
665 return;
666
667 settings = config_get_ptr();
668 color = FONT_COLOR_RGBA(
669 settings->uints.menu_font_color_red,
670 settings->uints.menu_font_color_green,
671 settings->uints.menu_font_color_blue, a8);
672
673 gfx_display_draw_text(font, str, x, y,
674 width, height, color, text_align, scale_factor,
675 xmb_shadows_enable,
676 stripes->shadow_offset, false);
677 }
678
stripes_messagebox(void * data,const char * message)679 static void stripes_messagebox(void *data, const char *message)
680 {
681 stripes_handle_t *stripes = (stripes_handle_t*)data;
682
683 if (!stripes || string_is_empty(message))
684 return;
685
686 stripes->box_message = strdup(message);
687 }
688
689 /* Returns the OSK key at a given position */
stripes_osk_ptr_at_pos(void * data,int x,int y,unsigned width,unsigned height)690 static int stripes_osk_ptr_at_pos(
691 void *data,
692 int x,
693 int y,
694 unsigned width,
695 unsigned height)
696 {
697 unsigned i;
698 int ptr_width, ptr_height;
699 stripes_handle_t *stripes = (stripes_handle_t*)data;
700
701 if (!stripes)
702 return -1;
703
704 ptr_width = width / 11;
705 ptr_height = height / 10;
706
707 if (ptr_width >= ptr_height)
708 ptr_width = ptr_height;
709
710 for (i = 0; i < 44; i++)
711 {
712 int line_y = (i / 11)*height/10.0;
713 int ptr_x = width/2.0 - (11*ptr_width)/2.0 + (i % 11) * ptr_width;
714 int ptr_y = height/2.0 + ptr_height*1.5 + line_y - ptr_height;
715
716 if (x > ptr_x && x < ptr_x + ptr_width
717 && y > ptr_y && y < ptr_y + ptr_height)
718 return i;
719 }
720
721 return -1;
722 }
723
stripes_render_messagebox_internal(stripes_handle_t * stripes,void * userdata,unsigned video_width,unsigned video_height,const char * message)724 static void stripes_render_messagebox_internal(
725 stripes_handle_t *stripes,
726 void *userdata,
727 unsigned video_width,
728 unsigned video_height,
729 const char *message)
730 {
731 unsigned i, y_position;
732 int x, y, longest = 0, longest_width = 0;
733 float line_height = 0;
734 struct string_list *list = !string_is_empty(message)
735 ? string_split(message, "\n") : NULL;
736 gfx_display_t *p_disp = disp_get_ptr();
737 gfx_display_ctx_driver_t *dispctx = p_disp->dispctx;
738
739 if (!list || !stripes || !stripes->font)
740 {
741 if (list)
742 string_list_free(list);
743 return;
744 }
745
746 if (list->elems == 0)
747 goto end;
748
749 line_height = stripes->font->size * 1.2;
750
751 y_position = video_height / 2;
752 if (menu_input_dialog_get_display_kb())
753 y_position = video_height / 4;
754
755 x = video_width / 2;
756 y = y_position - (list->size-1) * line_height / 2;
757
758 /* find the longest line width */
759 for (i = 0; i < list->size; i++)
760 {
761 const char *msg = list->elems[i].data;
762 int len = (int)utf8len(msg);
763
764 if (len > longest)
765 {
766 longest = len;
767 longest_width = font_driver_get_message_width(
768 stripes->font, msg, strlen(msg), 1);
769 }
770 }
771
772 if (dispctx && dispctx->blend_begin)
773 dispctx->blend_begin(userdata);
774
775 gfx_display_draw_texture_slice(
776 userdata,
777 video_width,
778 video_height,
779 x - longest_width / 2 - stripes->margins_dialog,
780 y + stripes->margins_slice - stripes->margins_dialog,
781 256, 256,
782 longest_width + stripes->margins_dialog * 2,
783 line_height * list->size + stripes->margins_dialog * 2,
784 video_width,
785 video_height,
786 NULL,
787 stripes->margins_slice, 1.0f,
788 stripes->textures.list[STRIPES_TEXTURE_DIALOG_SLICE]);
789
790 for (i = 0; i < list->size; i++)
791 {
792 const char *msg = list->elems[i].data;
793
794 if (msg)
795 gfx_display_draw_text(stripes->font, msg,
796 x - longest_width / 2.0f,
797 y + (i + 0.75f) * line_height,
798 video_width,
799 video_height,
800 0x444444ff,
801 TEXT_ALIGN_LEFT,
802 1.0f, false, 0.0f, false);
803 }
804
805 if (menu_input_dialog_get_display_kb())
806 gfx_display_draw_keyboard(
807 p_disp,
808 userdata,
809 video_width,
810 video_height,
811 stripes->textures.list[STRIPES_TEXTURE_KEY_HOVER],
812 stripes->font,
813 input_event_get_osk_grid(),
814 input_event_get_osk_ptr(),
815 0xffffffff);
816
817 end:
818 string_list_free(list);
819 }
820
stripes_update_thumbnail_path(void * data,unsigned i,char pos)821 static void stripes_update_thumbnail_path(void *data, unsigned i, char pos)
822 {
823 menu_entry_t entry;
824 unsigned entry_type = 0;
825 char new_path[PATH_MAX_LENGTH];
826 settings_t *settings = config_get_ptr();
827 stripes_handle_t *stripes = (stripes_handle_t*)data;
828 playlist_t *playlist = NULL;
829 const char *dir_thumbnails = settings->paths.directory_thumbnails;
830
831 if (!stripes || string_is_empty(dir_thumbnails))
832 goto end;
833
834 new_path[0] = '\0';
835
836 MENU_ENTRY_INIT(entry);
837 menu_entry_get(&entry, 0, i, NULL, true);
838
839 entry_type = entry.type;
840
841 if (entry_type == FILE_TYPE_IMAGEVIEWER || entry_type == FILE_TYPE_IMAGE)
842 {
843 file_list_t *selection_buf = menu_entries_get_selection_buf_ptr(0);
844 stripes_node_t *node = (stripes_node_t*)
845 file_list_get_userdata_at_offset(selection_buf, i);
846
847 if (!string_is_empty(node->fullpath) &&
848 (pos == 'R' || (pos == 'L' && string_is_equal(stripes_thumbnails_ident('R'),
849 msg_hash_to_str(MENU_ENUM_LABEL_VALUE_OFF)))))
850 {
851 if (!string_is_empty(entry.path))
852 fill_pathname_join(
853 new_path,
854 node->fullpath,
855 entry.path,
856 sizeof(new_path));
857
858 goto end;
859 }
860 }
861 else if (filebrowser_get_type() != FILEBROWSER_NONE)
862 {
863 video_driver_texture_unload(&stripes->thumbnail);
864 goto end;
865 }
866
867 playlist = playlist_get_cached();
868
869 if (playlist)
870 {
871 const struct playlist_entry *entry = NULL;
872 playlist_get_index(playlist, i, &entry);
873
874 if (string_is_equal(entry->core_name, "imageviewer"))
875 {
876 if (pos == 'R' || (pos == 'L' && string_is_equal(stripes_thumbnails_ident('R'),
877 msg_hash_to_str(MENU_ENUM_LABEL_VALUE_OFF))))
878 {
879 if (!string_is_empty(entry->label))
880 strlcpy(new_path, entry->label,
881 sizeof(new_path));
882 goto end;
883 }
884 else
885 {
886 video_driver_texture_unload(&stripes->left_thumbnail);
887 goto end;
888 }
889 }
890 }
891
892 /* Append thumbnail system directory */
893 if (!string_is_empty(stripes->thumbnail_system))
894 fill_pathname_join(
895 new_path,
896 dir_thumbnails,
897 stripes->thumbnail_system,
898 sizeof(new_path));
899
900 if (!string_is_empty(new_path))
901 {
902 char tmp_new2[PATH_MAX_LENGTH];
903
904 tmp_new2[0] = '\0';
905
906 /* Append Named_Snaps/Named_Boxarts/Named_Titles */
907 if (pos == 'R')
908 fill_pathname_join(tmp_new2, new_path,
909 stripes_thumbnails_ident('R'), sizeof(tmp_new2));
910 if (pos == 'L')
911 fill_pathname_join(tmp_new2, new_path,
912 stripes_thumbnails_ident('L'), sizeof(tmp_new2));
913
914 strlcpy(new_path, tmp_new2, sizeof(new_path));
915 }
916
917 /* Scrub characters that are not cross-platform and/or violate the
918 * No-Intro filename standard:
919 * http://datomatic.no-intro.org/stuff/The%20Official%20No-Intro%20Convention%20(20071030).zip
920 * Replace these characters in the entry name with underscores.
921 */
922 if (!string_is_empty(stripes->thumbnail_content))
923 {
924 char tmp_new[PATH_MAX_LENGTH];
925 char *scrub_char_pointer = NULL;
926 char *tmp = strdup(stripes->thumbnail_content);
927
928 tmp_new[0] = '\0';
929
930 while ((scrub_char_pointer = strpbrk(tmp, "&*/:`\"<>?\\|")))
931 *scrub_char_pointer = '_';
932
933 /* Look for thumbnail file with this scrubbed filename */
934
935 fill_pathname_join(tmp_new, new_path, tmp, sizeof(tmp_new));
936
937 if (!string_is_empty(tmp_new))
938 strlcpy(new_path,
939 tmp_new, sizeof(new_path));
940
941 free(tmp);
942 }
943
944 /* Append png extension */
945 if (!string_is_empty(new_path))
946 strlcat(new_path, ".png", sizeof(new_path));
947
948 end:
949 if (stripes && !string_is_empty(new_path))
950 {
951 if (pos == 'R')
952 stripes->thumbnail_file_path = strdup(new_path);
953 if (pos == 'L')
954 stripes->left_thumbnail_file_path = strdup(new_path);
955 }
956 }
957
stripes_update_savestate_thumbnail_path(void * data,unsigned i)958 static void stripes_update_savestate_thumbnail_path(void *data, unsigned i)
959 {
960 menu_entry_t entry;
961 settings_t *settings = config_get_ptr();
962 stripes_handle_t *stripes = (stripes_handle_t*)data;
963
964 if (!stripes)
965 return;
966
967 MENU_ENTRY_INIT(entry);
968 menu_entry_get(&entry, 0, i, NULL, true);
969
970 if (!string_is_empty(stripes->savestate_thumbnail_file_path))
971 free(stripes->savestate_thumbnail_file_path);
972 stripes->savestate_thumbnail_file_path = NULL;
973
974 if (!string_is_empty(entry.label))
975 {
976 if ( (settings->bools.savestate_thumbnail_enable)
977 && ((string_is_equal(entry.label, "state_slot"))
978 || (string_is_equal(entry.label, "loadstate"))
979 || (string_is_equal(entry.label, "savestate"))))
980 {
981 char path[8024];
982 global_t *global = global_get_ptr();
983
984 path[0] = '\0';
985
986 if (global)
987 {
988 int state_slot = settings->ints.state_slot;
989
990 if (state_slot > 0)
991 snprintf(path, sizeof(path), "%s%d",
992 global->name.savestate, state_slot);
993 else if (state_slot < 0)
994 fill_pathname_join_delim(path,
995 global->name.savestate, "auto", '.', sizeof(path));
996 else
997 strlcpy(path, global->name.savestate, sizeof(path));
998 }
999
1000 strlcat(path, ".png", sizeof(path));
1001
1002 if (path_is_valid(path))
1003 {
1004 if (!string_is_empty(stripes->savestate_thumbnail_file_path))
1005 free(stripes->savestate_thumbnail_file_path);
1006 stripes->savestate_thumbnail_file_path = strdup(path);
1007 }
1008 }
1009 }
1010 }
1011
stripes_update_thumbnail_image(void * data)1012 static void stripes_update_thumbnail_image(void *data)
1013 {
1014 stripes_handle_t *stripes = (stripes_handle_t*)data;
1015 bool supports_rgba = video_driver_supports_rgba();
1016 if (!stripes)
1017 return;
1018
1019 if (!(string_is_empty(stripes->thumbnail_file_path)))
1020 {
1021 if (path_is_valid(stripes->thumbnail_file_path))
1022 task_push_image_load(stripes->thumbnail_file_path,
1023 supports_rgba, 0,
1024 gfx_display_handle_thumbnail_upload, NULL);
1025 else
1026 video_driver_texture_unload(&stripes->thumbnail);
1027
1028 free(stripes->thumbnail_file_path);
1029 stripes->thumbnail_file_path = NULL;
1030 }
1031
1032 if (!(string_is_empty(stripes->left_thumbnail_file_path)))
1033 {
1034 if (path_is_valid(stripes->left_thumbnail_file_path))
1035 task_push_image_load(stripes->left_thumbnail_file_path,
1036 supports_rgba, 0,
1037 gfx_display_handle_left_thumbnail_upload, NULL);
1038 else
1039 video_driver_texture_unload(&stripes->left_thumbnail);
1040
1041 free(stripes->left_thumbnail_file_path);
1042 stripes->left_thumbnail_file_path = NULL;
1043 }
1044 }
1045
stripes_refresh_thumbnail_image(void * data,unsigned i)1046 static void stripes_refresh_thumbnail_image(void *data, unsigned i)
1047 {
1048 stripes_update_thumbnail_image(data);
1049 }
1050
stripes_set_thumbnail_system(void * data,char * s,size_t len)1051 static void stripes_set_thumbnail_system(void *data, char*s, size_t len)
1052 {
1053 stripes_handle_t *stripes = (stripes_handle_t*)data;
1054 if (!stripes)
1055 return;
1056
1057 if (!string_is_empty(stripes->thumbnail_system))
1058 free(stripes->thumbnail_system);
1059 stripes->thumbnail_system = strdup(s);
1060 }
1061
stripes_get_thumbnail_system(void * data,char * s,size_t len)1062 static void stripes_get_thumbnail_system(void *data, char*s, size_t len)
1063 {
1064 stripes_handle_t *stripes = (stripes_handle_t*)data;
1065 if (!stripes)
1066 return;
1067
1068 if (!string_is_empty(stripes->thumbnail_system))
1069 strlcpy(s, stripes->thumbnail_system, len);
1070 }
1071
stripes_reset_thumbnail_content(void * data)1072 static void stripes_reset_thumbnail_content(void *data)
1073 {
1074 stripes_handle_t *stripes = (stripes_handle_t*)data;
1075 if (!stripes)
1076 return;
1077 if (!string_is_empty(stripes->thumbnail_content))
1078 free(stripes->thumbnail_content);
1079 stripes->thumbnail_content = NULL;
1080 }
1081
stripes_set_thumbnail_content(void * data,char * s,size_t len)1082 static void stripes_set_thumbnail_content(void *data, char *s, size_t len)
1083 {
1084 stripes_handle_t *stripes = (stripes_handle_t*)data;
1085 if (!stripes)
1086 return;
1087 if (!string_is_empty(stripes->thumbnail_content))
1088 free(stripes->thumbnail_content);
1089 stripes->thumbnail_content = strdup(s);
1090 }
1091
stripes_update_savestate_thumbnail_image(void * data)1092 static void stripes_update_savestate_thumbnail_image(void *data)
1093 {
1094 stripes_handle_t *stripes = (stripes_handle_t*)data;
1095 if (!stripes)
1096 return;
1097
1098 if (path_is_valid(stripes->savestate_thumbnail_file_path))
1099 task_push_image_load(stripes->savestate_thumbnail_file_path,
1100 video_driver_supports_rgba(), 0,
1101 gfx_display_handle_savestate_thumbnail_upload, NULL);
1102 else
1103 video_driver_texture_unload(&stripes->savestate_thumbnail);
1104 }
1105
stripes_get_system_tab(stripes_handle_t * stripes,unsigned i)1106 static unsigned stripes_get_system_tab(stripes_handle_t *stripes, unsigned i)
1107 {
1108 if (i <= stripes->system_tab_end)
1109 {
1110 return stripes->tabs[i];
1111 }
1112 return UINT_MAX;
1113 }
1114
stripes_selection_pointer_changed(stripes_handle_t * stripes,bool allow_animations)1115 static void stripes_selection_pointer_changed(
1116 stripes_handle_t *stripes, bool allow_animations)
1117 {
1118 uintptr_t tag;
1119 unsigned i, end, height;
1120 menu_entry_t entry;
1121 size_t num = 0;
1122 int threshold = 0;
1123 file_list_t *selection_buf = menu_entries_get_selection_buf_ptr(0);
1124 size_t selection = menu_navigation_get_selection();
1125 const char *thumb_ident = stripes_thumbnails_ident('R');
1126 const char *lft_thumb_ident= stripes_thumbnails_ident('L');
1127
1128 if (!stripes)
1129 return;
1130
1131 MENU_ENTRY_INIT(entry);
1132 menu_entry_get(&entry, 0, selection, NULL, true);
1133
1134 end = (unsigned)menu_entries_get_size();
1135 threshold = stripes->icon_size * 10;
1136
1137 video_driver_get_size(NULL, &height);
1138
1139 tag = (uintptr_t)selection_buf;
1140
1141 gfx_animation_kill_by_tag(&tag);
1142 menu_entries_ctl(MENU_ENTRIES_CTL_SET_START, &num);
1143
1144 for (i = 0; i < end; i++)
1145 {
1146 float iy, real_iy;
1147 float ia = stripes->items_passive_alpha;
1148 float iz = stripes->items_passive_zoom;
1149 stripes_node_t *node = (stripes_node_t*)
1150 file_list_get_userdata_at_offset(selection_buf, i);
1151
1152 if (!node)
1153 continue;
1154
1155 iy = stripes_item_y(stripes, i, selection);
1156 real_iy = iy + stripes->margins_screen_top;
1157
1158 if ( (!allow_animations)
1159 || (real_iy < -threshold
1160 || real_iy > height+threshold))
1161 {
1162 node->alpha = node->label_alpha = ia;
1163 node->y = iy;
1164 node->zoom = iz;
1165 }
1166 else
1167 {
1168 gfx_animation_ctx_entry_t anim_entry;
1169
1170 anim_entry.duration = STRIPES_DELAY;
1171 anim_entry.target_value = ia;
1172 anim_entry.subject = &node->alpha;
1173 anim_entry.easing_enum = EASING_OUT_QUAD;
1174 anim_entry.tag = tag;
1175 anim_entry.cb = NULL;
1176
1177 gfx_animation_push(&anim_entry);
1178
1179 anim_entry.subject = &node->label_alpha;
1180
1181 gfx_animation_push(&anim_entry);
1182
1183 anim_entry.target_value = iz;
1184 anim_entry.subject = &node->zoom;
1185
1186 gfx_animation_push(&anim_entry);
1187
1188 anim_entry.target_value = iy;
1189 anim_entry.subject = &node->y;
1190
1191 gfx_animation_push(&anim_entry);
1192 }
1193 }
1194 }
1195
stripes_list_open_old(stripes_handle_t * stripes,file_list_t * list,int dir,size_t current)1196 static void stripes_list_open_old(stripes_handle_t *stripes,
1197 file_list_t *list, int dir, size_t current)
1198 {
1199 unsigned i, height = 0;
1200 int threshold = stripes->icon_size * 10;
1201 size_t end = list ? list->size : NULL;
1202
1203 video_driver_get_size(NULL, &height);
1204
1205 for (i = 0; i < end; i++)
1206 {
1207 float ia = 0;
1208 float real_y;
1209 stripes_node_t *node = (stripes_node_t*)
1210 file_list_get_userdata_at_offset(list, i);
1211
1212 if (!node)
1213 continue;
1214
1215 if (i == current)
1216 ia = stripes->items_active_alpha;
1217 if (dir == -1)
1218 ia = 0;
1219
1220 real_y = node->y + stripes->margins_screen_top;
1221
1222 if (real_y < -threshold || real_y > height+threshold)
1223 {
1224 node->alpha = ia;
1225 node->label_alpha = 0;
1226 node->x = stripes->icon_size * dir * -2;
1227 }
1228 else
1229 {
1230 gfx_animation_ctx_entry_t anim_entry;
1231
1232 anim_entry.duration = STRIPES_DELAY;
1233 anim_entry.target_value = ia;
1234 anim_entry.subject = &node->alpha;
1235 anim_entry.easing_enum = EASING_OUT_QUAD;
1236 anim_entry.tag = (uintptr_t)list;
1237 anim_entry.cb = NULL;
1238
1239 gfx_animation_push(&anim_entry);
1240
1241 anim_entry.target_value = 0;
1242 anim_entry.subject = &node->label_alpha;
1243
1244 gfx_animation_push(&anim_entry);
1245
1246 anim_entry.target_value = stripes->icon_size * dir * -2;
1247 anim_entry.subject = &node->x;
1248
1249 gfx_animation_push(&anim_entry);
1250 }
1251 }
1252 }
1253
stripes_list_open_new(stripes_handle_t * stripes,file_list_t * list,int dir,size_t current)1254 static void stripes_list_open_new(stripes_handle_t *stripes,
1255 file_list_t *list, int dir, size_t current)
1256 {
1257 unsigned i, height;
1258 unsigned stripes_system_tab = 0;
1259 size_t skip = 0;
1260 int threshold = stripes->icon_size * 10;
1261 size_t end = list ? list->size : NULL;
1262
1263 video_driver_get_size(NULL, &height);
1264
1265 for (i = 0; i < end; i++)
1266 {
1267 float ia;
1268 float real_y;
1269 stripes_node_t *node = (stripes_node_t*)
1270 file_list_get_userdata_at_offset(list, i);
1271
1272 if (!node)
1273 continue;
1274
1275 if (dir == 1 || (dir == -1 && i != current))
1276 node->alpha = 0;
1277
1278 if (dir == 1 || dir == -1)
1279 node->label_alpha = 0;
1280
1281 node->x = stripes->icon_size * dir * 2;
1282 node->y = stripes_item_y(stripes, i, current);
1283 node->zoom = stripes->categories_passive_zoom;
1284
1285 real_y = node->y + stripes->margins_screen_top;
1286
1287 if (i == current)
1288 node->zoom = stripes->categories_active_zoom;
1289
1290 ia = stripes->items_passive_alpha;
1291 if (i == current)
1292 ia = stripes->items_active_alpha;
1293
1294 if (real_y < -threshold || real_y > height+threshold)
1295 {
1296 node->alpha = node->label_alpha = ia;
1297 node->x = 0;
1298 }
1299 else
1300 {
1301 gfx_animation_ctx_entry_t anim_entry;
1302
1303 anim_entry.duration = STRIPES_DELAY;
1304 anim_entry.target_value = ia;
1305 anim_entry.subject = &node->alpha;
1306 anim_entry.easing_enum = EASING_OUT_QUAD;
1307 anim_entry.tag = (uintptr_t)list;
1308 anim_entry.cb = NULL;
1309
1310 gfx_animation_push(&anim_entry);
1311
1312 anim_entry.subject = &node->label_alpha;
1313
1314 gfx_animation_push(&anim_entry);
1315
1316 anim_entry.target_value = 0;
1317 anim_entry.subject = &node->x;
1318
1319 gfx_animation_push(&anim_entry);
1320 }
1321 }
1322
1323 stripes->old_depth = stripes->depth;
1324 menu_entries_ctl(MENU_ENTRIES_CTL_SET_START, &skip);
1325
1326 stripes_system_tab = stripes_get_system_tab(stripes,
1327 (unsigned)stripes->categories_selection_ptr);
1328
1329 if (stripes_system_tab <= STRIPES_SYSTEM_TAB_SETTINGS)
1330 {
1331 if (stripes->depth < 4)
1332 stripes_reset_thumbnail_content(stripes);
1333 stripes_update_thumbnail_path(stripes, 0, 'R');
1334 stripes_update_thumbnail_image(stripes);
1335 stripes_update_thumbnail_path(stripes, 0, 'L');
1336 stripes_update_thumbnail_image(stripes);
1337 }
1338 }
1339
stripes_node_allocate_userdata(stripes_handle_t * stripes,unsigned i)1340 static stripes_node_t *stripes_node_allocate_userdata(
1341 stripes_handle_t *stripes, unsigned i)
1342 {
1343 stripes_node_t *tmp = NULL;
1344 stripes_node_t *node = stripes_alloc_node();
1345
1346 if (!node)
1347 {
1348 RARCH_ERR("XMB node could not be allocated.\n");
1349 return NULL;
1350 }
1351
1352 node->alpha = stripes->categories_passive_alpha;
1353 node->zoom = stripes->categories_passive_zoom;
1354
1355 if ((i + stripes->system_tab_end) == stripes->categories_active_idx)
1356 {
1357 node->alpha = stripes->categories_active_alpha;
1358 node->zoom = stripes->categories_active_zoom;
1359 }
1360
1361 tmp = (stripes_node_t*)file_list_get_userdata_at_offset(
1362 &stripes->horizontal_list, i);
1363 stripes_free_node(tmp);
1364
1365 stripes->horizontal_list.list[i].userdata = node;
1366
1367 return node;
1368 }
1369
stripes_get_userdata_from_horizontal_list(stripes_handle_t * stripes,unsigned i)1370 static stripes_node_t* stripes_get_userdata_from_horizontal_list(
1371 stripes_handle_t *stripes, unsigned i)
1372 {
1373 return (stripes_node_t*)
1374 file_list_get_userdata_at_offset(&stripes->horizontal_list, i);
1375 }
1376
stripes_push_animations(stripes_node_t * node,uintptr_t tag,float ia,float ix)1377 static void stripes_push_animations(stripes_node_t *node,
1378 uintptr_t tag, float ia, float ix)
1379 {
1380 gfx_animation_ctx_entry_t anim_entry;
1381
1382 anim_entry.duration = STRIPES_DELAY;
1383 anim_entry.target_value = ia;
1384 anim_entry.subject = &node->alpha;
1385 anim_entry.easing_enum = EASING_OUT_QUAD;
1386 anim_entry.tag = tag;
1387 anim_entry.cb = NULL;
1388
1389 gfx_animation_push(&anim_entry);
1390
1391 anim_entry.subject = &node->label_alpha;
1392
1393 gfx_animation_push(&anim_entry);
1394
1395 anim_entry.target_value = ix;
1396 anim_entry.subject = &node->x;
1397
1398 gfx_animation_push(&anim_entry);
1399 }
1400
stripes_list_switch_old(stripes_handle_t * stripes,file_list_t * list,int dir,size_t current)1401 static void stripes_list_switch_old(stripes_handle_t *stripes,
1402 file_list_t *list, int dir, size_t current)
1403 {
1404 unsigned i, first, last, height;
1405 size_t end = list ? list->size : NULL;
1406 float ix = -stripes->icon_spacing_horizontal * dir;
1407 float ia = 0;
1408
1409 first = 0;
1410 last = end > 0 ? end - 1 : 0;
1411
1412 video_driver_get_size(NULL, &height);
1413 stripes_calculate_visible_range(stripes, height, end,
1414 current, &first, &last);
1415
1416 for (i = 0; i < end; i++)
1417 {
1418 stripes_node_t *node = (stripes_node_t*)
1419 file_list_get_userdata_at_offset(list, i);
1420
1421 if (!node)
1422 continue;
1423
1424 if (i >= first && i <= last)
1425 stripes_push_animations(node, (uintptr_t)list, ia, ix);
1426 else
1427 {
1428 node->alpha = node->label_alpha = ia;
1429 node->x = ix;
1430 }
1431 }
1432 }
1433
stripes_list_switch_new(stripes_handle_t * stripes,file_list_t * list,int dir,size_t current)1434 static void stripes_list_switch_new(stripes_handle_t *stripes,
1435 file_list_t *list, int dir, size_t current)
1436 {
1437 unsigned i, first, last, height;
1438 size_t end = 0;
1439 settings_t *settings = config_get_ptr();
1440
1441 if (settings->bools.menu_dynamic_wallpaper_enable)
1442 {
1443 char path[PATH_MAX_LENGTH];
1444 char *tmp = string_replace_substring(stripes->title_name, "/", " ");
1445
1446 path[0] = '\0';
1447
1448 if (tmp)
1449 {
1450 fill_pathname_join_noext(
1451 path,
1452 settings->paths.directory_dynamic_wallpapers,
1453 tmp,
1454 sizeof(path));
1455 free(tmp);
1456 }
1457
1458 strlcat(path, ".png", sizeof(path));
1459
1460 if (!path_is_valid(path))
1461 fill_pathname_application_special(path, sizeof(path),
1462 APPLICATION_SPECIAL_DIRECTORY_ASSETS_XMB_BG);
1463
1464 if (!string_is_equal(path, stripes->bg_file_path))
1465 {
1466 if (path_is_valid(path))
1467 {
1468 task_push_image_load(path,
1469 video_driver_supports_rgba(), 0,
1470 menu_display_handle_wallpaper_upload, NULL);
1471 if (!string_is_empty(stripes->bg_file_path))
1472 free(stripes->bg_file_path);
1473 stripes->bg_file_path = strdup(path);
1474 }
1475 }
1476 }
1477
1478 end = list ? list->size : NULL;
1479 first = 0;
1480 last = end > 0 ? end - 1 : 0;
1481
1482 video_driver_get_size(NULL, &height);
1483 stripes_calculate_visible_range(stripes, height, end, current, &first, &last);
1484
1485 for (i = 0; i < end; i++)
1486 {
1487 stripes_node_t *node = (stripes_node_t*)
1488 file_list_get_userdata_at_offset(list, i);
1489 float ia = stripes->items_passive_alpha;
1490
1491 if (!node)
1492 continue;
1493
1494 node->x = stripes->icon_spacing_horizontal * dir;
1495 node->alpha = 0;
1496 node->label_alpha = 0;
1497
1498 if (i == current)
1499 ia = stripes->items_active_alpha;
1500
1501 if (i >= first && i <= last)
1502 stripes_push_animations(node, (uintptr_t)list, ia, 0);
1503 else
1504 {
1505 node->x = 0;
1506 node->alpha = node->label_alpha = ia;
1507 }
1508 }
1509 }
1510
stripes_set_title(stripes_handle_t * stripes)1511 static void stripes_set_title(stripes_handle_t *stripes)
1512 {
1513 if (stripes->categories_selection_ptr <= stripes->system_tab_end)
1514 {
1515 menu_entries_get_title(stripes->title_name, sizeof(stripes->title_name));
1516 }
1517 else
1518 {
1519 const char *path = stripes->horizontal_list.list[
1520 stripes->categories_selection_ptr - (stripes->system_tab_end + 1)].path;
1521 if (!path)
1522 return;
1523
1524 fill_pathname_base_noext(
1525 stripes->title_name, path, sizeof(stripes->title_name));
1526 }
1527 }
1528
stripes_get_node(stripes_handle_t * stripes,unsigned i)1529 static stripes_node_t* stripes_get_node(stripes_handle_t *stripes, unsigned i)
1530 {
1531 switch (stripes_get_system_tab(stripes, i))
1532 {
1533 case STRIPES_SYSTEM_TAB_SETTINGS:
1534 return &stripes->settings_tab_node;
1535 #ifdef HAVE_IMAGEVIEWER
1536 case STRIPES_SYSTEM_TAB_IMAGES:
1537 return &stripes->images_tab_node;
1538 #endif
1539 case STRIPES_SYSTEM_TAB_MUSIC:
1540 return &stripes->music_tab_node;
1541 #ifdef HAVE_FFMPEG
1542 case STRIPES_SYSTEM_TAB_VIDEO:
1543 return &stripes->video_tab_node;
1544 #endif
1545 case STRIPES_SYSTEM_TAB_HISTORY:
1546 return &stripes->history_tab_node;
1547 case STRIPES_SYSTEM_TAB_FAVORITES:
1548 return &stripes->favorites_tab_node;
1549 #ifdef HAVE_NETWORKING
1550 case STRIPES_SYSTEM_TAB_NETPLAY:
1551 return &stripes->netplay_tab_node;
1552 #endif
1553 case STRIPES_SYSTEM_TAB_ADD:
1554 return &stripes->add_tab_node;
1555 default:
1556 if (i > stripes->system_tab_end)
1557 return stripes_get_userdata_from_horizontal_list(
1558 stripes, i - (stripes->system_tab_end + 1));
1559 }
1560
1561 return &stripes->main_menu_node;
1562 }
1563
stripes_list_switch_horizontal_list(stripes_handle_t * stripes)1564 static void stripes_list_switch_horizontal_list(stripes_handle_t *stripes)
1565 {
1566 unsigned j;
1567 size_t list_size = stripes_list_get_size(stripes, MENU_LIST_HORIZONTAL)
1568 + stripes->system_tab_end;
1569
1570 for (j = 0; j <= list_size; j++)
1571 {
1572 gfx_animation_ctx_entry_t entry;
1573 float ia = stripes->categories_passive_alpha;
1574 float iz = stripes->categories_passive_zoom;
1575 float iw = stripes->categories_passive_width;
1576 float ix = stripes->categories_before_x;
1577 float iy = stripes->categories_before_y;
1578 stripes_node_t *node = stripes_get_node(stripes, j);
1579
1580 if (!node)
1581 continue;
1582
1583 if (j == stripes->categories_active_idx)
1584 {
1585 ia = stripes->categories_active_alpha;
1586 iz = stripes->categories_active_zoom;
1587 iw = stripes->categories_active_width;
1588 ix = stripes->categories_active_x;
1589 iy = stripes->categories_active_y;
1590 }
1591 else if (j < stripes->categories_active_idx)
1592 {
1593 ix = stripes->categories_before_x;
1594 iy = stripes->categories_before_y;
1595 }
1596 else if (j > stripes->categories_active_idx)
1597 {
1598 ix = stripes->categories_after_x;
1599 iy = stripes->categories_after_y;
1600 }
1601
1602 entry.duration = STRIPES_DELAY;
1603 entry.target_value = ia;
1604 entry.subject = &node->alpha;
1605 entry.easing_enum = EASING_OUT_QUAD;
1606 /* TODO/FIXME - integer conversion resulted in change of sign */
1607 entry.tag = -1;
1608 entry.cb = NULL;
1609
1610 gfx_animation_push(&entry);
1611
1612 entry.target_value = iz;
1613 entry.subject = &node->zoom;
1614
1615 gfx_animation_push(&entry);
1616
1617 entry.target_value = iy;
1618 entry.subject = &node->y;
1619
1620 gfx_animation_push(&entry);
1621
1622 entry.target_value = ix;
1623 entry.subject = &node->x;
1624
1625 gfx_animation_push(&entry);
1626
1627 entry.target_value = iw;
1628 entry.subject = &node->width;
1629
1630 gfx_animation_push(&entry);
1631 }
1632 }
1633
stripes_list_switch(stripes_handle_t * stripes)1634 static void stripes_list_switch(stripes_handle_t *stripes)
1635 {
1636 gfx_animation_ctx_entry_t anim_entry;
1637 int dir = -1;
1638 file_list_t *selection_buf = menu_entries_get_selection_buf_ptr(0);
1639 size_t selection = menu_navigation_get_selection();
1640 settings_t *settings = config_get_ptr();
1641
1642 if (stripes->categories_selection_ptr > stripes->categories_selection_ptr_old)
1643 dir = 1;
1644
1645 stripes->categories_active_idx += dir;
1646
1647 stripes_list_switch_horizontal_list(stripes);
1648
1649 anim_entry.duration = STRIPES_DELAY;
1650 anim_entry.target_value = stripes->categories_passive_width
1651 * -(float)stripes->categories_selection_ptr;
1652 anim_entry.subject = &stripes->categories_x_pos;
1653 anim_entry.easing_enum = EASING_OUT_QUAD;
1654 /* TODO/FIXME - integer conversion resulted in change of sign */
1655 anim_entry.tag = -1;
1656 anim_entry.cb = NULL;
1657
1658 if (anim_entry.subject)
1659 gfx_animation_push(&anim_entry);
1660
1661 dir = -1;
1662 if (stripes->categories_selection_ptr > stripes->categories_selection_ptr_old)
1663 dir = 1;
1664
1665 stripes_list_switch_old(stripes,
1666 &stripes->selection_buf_old,
1667 dir, stripes->selection_ptr_old);
1668
1669 /* Check if we are to have horizontal animations. */
1670 if (settings->bools.menu_horizontal_animation)
1671 stripes_list_switch_new(stripes, selection_buf, dir, selection);
1672 stripes->categories_active_idx_old = (unsigned)stripes->categories_selection_ptr;
1673
1674 if (!string_is_equal(stripes_thumbnails_ident('R'),
1675 msg_hash_to_str(MENU_ENUM_LABEL_VALUE_OFF)))
1676 {
1677 menu_entry_t entry;
1678
1679 MENU_ENTRY_INIT(entry);
1680 menu_entry_get(&entry, 0, selection, NULL, true);
1681
1682 if (!string_is_empty(entry.path))
1683 stripes_set_thumbnail_content(stripes, entry.path, 0 /* will be ignored */);
1684
1685 stripes_update_thumbnail_path(stripes, 0, 'R');
1686 stripes_update_thumbnail_image(stripes);
1687 }
1688 if (!string_is_equal(stripes_thumbnails_ident('L'),
1689 msg_hash_to_str(MENU_ENUM_LABEL_VALUE_OFF)))
1690 {
1691 menu_entry_t entry;
1692
1693 MENU_ENTRY_INIT(entry);
1694 menu_entry_get(&entry, 0, selection, NULL, true);
1695
1696 if (!string_is_empty(entry.path))
1697 stripes_set_thumbnail_content(stripes, entry.path, 0 /* will be ignored */);
1698
1699 stripes_update_thumbnail_path(stripes, 0, 'L');
1700 stripes_update_thumbnail_image(stripes);
1701 }
1702 }
1703
stripes_list_open_horizontal_list(stripes_handle_t * stripes)1704 static void stripes_list_open_horizontal_list(stripes_handle_t *stripes)
1705 {
1706 unsigned j;
1707 size_t list_size = stripes_list_get_size(stripes, MENU_LIST_HORIZONTAL)
1708 + stripes->system_tab_end;
1709
1710 for (j = 0; j <= list_size; j++)
1711 {
1712 gfx_animation_ctx_entry_t anim_entry;
1713 float ia = 0;
1714 stripes_node_t *node = stripes_get_node(stripes, j);
1715
1716 if (!node)
1717 continue;
1718
1719 if (j == stripes->categories_active_idx)
1720 ia = stripes->categories_active_alpha;
1721 else if (stripes->depth <= 1)
1722 ia = stripes->categories_passive_alpha;
1723
1724 anim_entry.duration = STRIPES_DELAY;
1725 anim_entry.target_value = ia;
1726 anim_entry.subject = &node->alpha;
1727 anim_entry.easing_enum = EASING_OUT_QUAD;
1728 /* TODO/FIXME - integer conversion resulted in change of sign */
1729 anim_entry.tag = -1;
1730 anim_entry.cb = NULL;
1731
1732 if (anim_entry.subject)
1733 gfx_animation_push(&anim_entry);
1734 }
1735 }
1736
stripes_context_destroy_horizontal_list(stripes_handle_t * stripes)1737 static void stripes_context_destroy_horizontal_list(stripes_handle_t *stripes)
1738 {
1739 unsigned i;
1740 size_t list_size = stripes_list_get_size(stripes, MENU_LIST_HORIZONTAL);
1741
1742 for (i = 0; i < list_size; i++)
1743 {
1744 const char *path = NULL;
1745 stripes_node_t *node = stripes_get_userdata_from_horizontal_list(stripes, i);
1746
1747 if (!node)
1748 continue;
1749
1750 if (!(path = stripes->horizontal_list.list[i].path))
1751 continue;
1752
1753 if (string_ends_with_size(path, ".lpl",
1754 strlen(path), STRLEN_CONST(".lpl")))
1755 {
1756 video_driver_texture_unload(&node->icon);
1757 video_driver_texture_unload(&node->content_icon);
1758 }
1759 }
1760 }
1761
stripes_init_horizontal_list(stripes_handle_t * stripes)1762 static void stripes_init_horizontal_list(stripes_handle_t *stripes)
1763 {
1764 menu_displaylist_info_t info;
1765 settings_t *settings = config_get_ptr();
1766
1767 menu_displaylist_info_init(&info);
1768
1769 info.list = &stripes->horizontal_list;
1770 info.path = strdup(
1771 settings->paths.directory_playlist);
1772 #if 0
1773 /* TODO/FIXME - will need to look what to do here */
1774 info.label = strdup(
1775 msg_hash_to_str(MENU_ENUM_LABEL_CONTENT_COLLECTION_LIST));
1776 info.enum_idx = MENU_ENUM_LABEL_CONTENT_COLLECTION_LIST;
1777 #endif
1778 info.exts = strdup("lpl");
1779 info.type_default = FILE_TYPE_PLAIN;
1780
1781 if (!string_is_empty(info.path))
1782 {
1783 if (menu_displaylist_ctl(DISPLAYLIST_DATABASE_PLAYLISTS_HORIZONTAL, &info,
1784 settings))
1785 {
1786 size_t i;
1787 for (i = 0; i < stripes->horizontal_list.size; i++)
1788 stripes_node_allocate_userdata(stripes, (unsigned)i);
1789 menu_displaylist_process(&info);
1790 }
1791 }
1792
1793 menu_displaylist_info_free(&info);
1794 }
1795
stripes_toggle_horizontal_list(stripes_handle_t * stripes)1796 static void stripes_toggle_horizontal_list(stripes_handle_t *stripes)
1797 {
1798 unsigned i;
1799 size_t list_size = stripes_list_get_size(stripes, MENU_LIST_HORIZONTAL)
1800 + stripes->system_tab_end;
1801
1802 for (i = 0; i <= list_size; i++)
1803 {
1804 stripes_node_t *node = stripes_get_node(stripes, i);
1805
1806 if (!node)
1807 continue;
1808
1809 node->alpha = 0;
1810 node->zoom = stripes->categories_passive_zoom;
1811
1812 if (i == stripes->categories_active_idx)
1813 {
1814 node->alpha = stripes->categories_active_alpha;
1815 node->zoom = stripes->categories_active_zoom;
1816 }
1817 else if (stripes->depth <= 1)
1818 node->alpha = stripes->categories_passive_alpha;
1819 }
1820 }
1821
stripes_context_reset_horizontal_list(stripes_handle_t * stripes)1822 static void stripes_context_reset_horizontal_list(
1823 stripes_handle_t *stripes)
1824 {
1825 unsigned i;
1826 int depth; /* keep this integer */
1827 size_t list_size =
1828 stripes_list_get_size(stripes, MENU_LIST_HORIZONTAL);
1829
1830 stripes->categories_x_pos =
1831 stripes->categories_passive_width *
1832 -(float)stripes->categories_selection_ptr;
1833
1834 depth = (stripes->depth > 1) ? 2 : 1;
1835 stripes->x = stripes->icon_size * -(depth*2-2);
1836
1837 for (i = 0; i < list_size; i++)
1838 {
1839 const char *path = NULL;
1840 stripes_node_t *node =
1841 stripes_get_userdata_from_horizontal_list(stripes, i);
1842
1843 if (!node)
1844 if (!(node = stripes_node_allocate_userdata(stripes, i)))
1845 continue;
1846
1847 if (!(path = stripes->horizontal_list.list[i].path))
1848 continue;
1849 if (string_ends_with_size(path, ".lpl",
1850 strlen(path), STRLEN_CONST(".lpl")))
1851 {
1852 struct texture_image ti;
1853 char sysname[256];
1854 char iconpath[PATH_MAX_LENGTH];
1855 char texturepath[PATH_MAX_LENGTH];
1856 char content_texturepath[PATH_MAX_LENGTH];
1857
1858 iconpath[0] = sysname[0] =
1859 texturepath[0] = content_texturepath[0] = '\0';
1860
1861 fill_pathname_base_noext(sysname, path, sizeof(sysname));
1862
1863 fill_pathname_application_special(iconpath, sizeof(iconpath),
1864 APPLICATION_SPECIAL_DIRECTORY_ASSETS_XMB_ICONS);
1865
1866 fill_pathname_join_concat(texturepath, iconpath, sysname,
1867 ".png", sizeof(texturepath));
1868
1869 ti.width = 0;
1870 ti.height = 0;
1871 ti.pixels = NULL;
1872 ti.supports_rgba = video_driver_supports_rgba();
1873
1874 if (image_texture_load(&ti, texturepath))
1875 {
1876 if (ti.pixels)
1877 {
1878 video_driver_texture_unload(&node->icon);
1879 video_driver_texture_load(&ti,
1880 TEXTURE_FILTER_MIPMAP_LINEAR, &node->icon);
1881 }
1882
1883 image_texture_free(&ti);
1884 }
1885
1886 strlcat(iconpath, sysname, sizeof(iconpath));
1887 fill_pathname_join_delim(content_texturepath, iconpath,
1888 "content.png", '-', sizeof(content_texturepath));
1889
1890 if (image_texture_load(&ti, content_texturepath))
1891 {
1892 if (ti.pixels)
1893 {
1894 video_driver_texture_unload(&node->content_icon);
1895 video_driver_texture_load(&ti,
1896 TEXTURE_FILTER_MIPMAP_LINEAR, &node->content_icon);
1897 }
1898
1899 image_texture_free(&ti);
1900 }
1901 }
1902 }
1903
1904 stripes_toggle_horizontal_list(stripes);
1905 }
1906
stripes_refresh_horizontal_list(stripes_handle_t * stripes)1907 static void stripes_refresh_horizontal_list(stripes_handle_t *stripes)
1908 {
1909 stripes_context_destroy_horizontal_list(stripes);
1910 stripes_free_list_nodes(stripes->horizontal_list, false);
1911 file_list_deinitialize(&stripes->horizontal_list);
1912
1913 menu_driver_ctl(RARCH_MENU_CTL_SET_PREVENT_POPULATE, NULL);
1914
1915 stripes_init_horizontal_list(stripes);
1916
1917 stripes_context_reset_horizontal_list(stripes);
1918 }
1919
stripes_environ(enum menu_environ_cb type,void * data,void * userdata)1920 static int stripes_environ(enum menu_environ_cb type, void *data, void *userdata)
1921 {
1922 stripes_handle_t *stripes = (stripes_handle_t*)userdata;
1923
1924 switch (type)
1925 {
1926 case MENU_ENVIRON_ENABLE_MOUSE_CURSOR:
1927 if (!stripes)
1928 return -1;
1929 stripes->mouse_show = true;
1930 break;
1931 case MENU_ENVIRON_DISABLE_MOUSE_CURSOR:
1932 if (!stripes)
1933 return -1;
1934 stripes->mouse_show = false;
1935 break;
1936 case MENU_ENVIRON_RESET_HORIZONTAL_LIST:
1937 if (!stripes)
1938 return -1;
1939
1940 stripes_refresh_horizontal_list(stripes);
1941 break;
1942 default:
1943 return -1;
1944 }
1945
1946 return 0;
1947 }
1948
stripes_list_open(stripes_handle_t * stripes)1949 static void stripes_list_open(stripes_handle_t *stripes)
1950 {
1951 gfx_animation_ctx_entry_t entry;
1952
1953 int dir = 0;
1954 file_list_t *selection_buf = menu_entries_get_selection_buf_ptr(0);
1955 size_t selection = menu_navigation_get_selection();
1956
1957 stripes->depth = (int)stripes_list_get_size(stripes, MENU_LIST_PLAIN);
1958
1959 if (stripes->depth > stripes->old_depth)
1960 dir = 1;
1961 else if (stripes->depth < stripes->old_depth)
1962 dir = -1;
1963
1964 stripes_list_open_horizontal_list(stripes);
1965
1966 stripes_list_open_old(stripes,
1967 &stripes->selection_buf_old,
1968 dir, stripes->selection_ptr_old);
1969 stripes_list_open_new(stripes, selection_buf,
1970 dir, selection);
1971
1972 entry.duration = STRIPES_DELAY;
1973 entry.target_value = stripes->icon_size * -(stripes->depth*2-2);
1974 entry.subject = &stripes->x;
1975 entry.easing_enum = EASING_OUT_QUAD;
1976 /* TODO/FIXME - integer conversion resulted in change of sign */
1977 entry.tag = -1;
1978 entry.cb = NULL;
1979
1980 switch (stripes->depth)
1981 {
1982 case 1:
1983 gfx_animation_push(&entry);
1984
1985 entry.target_value = 0;
1986 entry.subject = &stripes->textures_arrow_alpha;
1987
1988 gfx_animation_push(&entry);
1989 break;
1990 case 2:
1991 gfx_animation_push(&entry);
1992
1993 entry.target_value = 1;
1994 entry.subject = &stripes->textures_arrow_alpha;
1995
1996 gfx_animation_push(&entry);
1997 break;
1998 }
1999
2000 stripes->old_depth = stripes->depth;
2001 }
2002
stripes_populate_entries(void * data,const char * path,const char * label,unsigned k)2003 static void stripes_populate_entries(void *data,
2004 const char *path,
2005 const char *label, unsigned k)
2006 {
2007 stripes_handle_t *stripes = (stripes_handle_t*)data;
2008
2009 if (!stripes)
2010 return;
2011
2012 if (menu_driver_ctl(RARCH_MENU_CTL_IS_PREVENT_POPULATE, NULL))
2013 {
2014 stripes_selection_pointer_changed(stripes, false);
2015 menu_driver_ctl(RARCH_MENU_CTL_UNSET_PREVENT_POPULATE, NULL);
2016 if (!string_is_equal(stripes_thumbnails_ident('R'),
2017 msg_hash_to_str(MENU_ENUM_LABEL_VALUE_OFF)))
2018 stripes_update_thumbnail_image(stripes);
2019 stripes_update_savestate_thumbnail_image(stripes);
2020 if (!string_is_equal(stripes_thumbnails_ident('L'),
2021 msg_hash_to_str(MENU_ENUM_LABEL_VALUE_OFF)))
2022 stripes_update_thumbnail_image(stripes);
2023 return;
2024 }
2025
2026 stripes_set_title(stripes);
2027
2028 if (stripes->categories_selection_ptr != stripes->categories_active_idx_old)
2029 stripes_list_switch(stripes);
2030 else
2031 stripes_list_open(stripes);
2032 }
2033
stripes_icon_get_id(stripes_handle_t * stripes,stripes_node_t * core_node,stripes_node_t * node,enum msg_hash_enums enum_idx,unsigned type,bool active)2034 static uintptr_t stripes_icon_get_id(stripes_handle_t *stripes,
2035 stripes_node_t *core_node, stripes_node_t *node,
2036 enum msg_hash_enums enum_idx, unsigned type, bool active)
2037 {
2038 switch (enum_idx)
2039 {
2040 case MENU_ENUM_LABEL_CORE_OPTIONS:
2041 case MENU_ENUM_LABEL_NAVIGATION_BROWSER_FILTER_SUPPORTED_EXTENSIONS_ENABLE:
2042 return stripes->textures.list[STRIPES_TEXTURE_CORE_OPTIONS];
2043 case MENU_ENUM_LABEL_CORE_OPTION_OVERRIDE_LIST:
2044 return stripes->textures.list[STRIPES_TEXTURE_SETTING];
2045 case MENU_ENUM_LABEL_ADD_TO_FAVORITES:
2046 case MENU_ENUM_LABEL_ADD_TO_FAVORITES_PLAYLIST:
2047 return stripes->textures.list[STRIPES_TEXTURE_ADD_FAVORITE];
2048 case MENU_ENUM_LABEL_RESET_CORE_ASSOCIATION:
2049 case MENU_ENUM_LABEL_PLAYLIST_MANAGER_RESET_CORES:
2050 return stripes->textures.list[STRIPES_TEXTURE_RENAME];
2051 case MENU_ENUM_LABEL_CORE_INPUT_REMAPPING_OPTIONS:
2052 return stripes->textures.list[STRIPES_TEXTURE_INPUT_REMAPPING_OPTIONS];
2053 case MENU_ENUM_LABEL_CORE_CHEAT_OPTIONS:
2054 return stripes->textures.list[STRIPES_TEXTURE_CHEAT_OPTIONS];
2055 case MENU_ENUM_LABEL_DISK_OPTIONS:
2056 return stripes->textures.list[STRIPES_TEXTURE_DISK_OPTIONS];
2057 case MENU_ENUM_LABEL_SHADER_OPTIONS:
2058 return stripes->textures.list[STRIPES_TEXTURE_SHADER_OPTIONS];
2059 case MENU_ENUM_LABEL_ACHIEVEMENT_LIST:
2060 return stripes->textures.list[STRIPES_TEXTURE_ACHIEVEMENT_LIST];
2061 case MENU_ENUM_LABEL_ACHIEVEMENT_LIST_HARDCORE:
2062 return stripes->textures.list[STRIPES_TEXTURE_ACHIEVEMENT_LIST];
2063 case MENU_ENUM_LABEL_SAVE_STATE:
2064 return stripes->textures.list[STRIPES_TEXTURE_SAVESTATE];
2065 case MENU_ENUM_LABEL_LOAD_STATE:
2066 return stripes->textures.list[STRIPES_TEXTURE_LOADSTATE];
2067 case MENU_ENUM_LABEL_PARENT_DIRECTORY:
2068 case MENU_ENUM_LABEL_UNDO_LOAD_STATE:
2069 case MENU_ENUM_LABEL_UNDO_SAVE_STATE:
2070 return stripes->textures.list[STRIPES_TEXTURE_UNDO];
2071 case MENU_ENUM_LABEL_TAKE_SCREENSHOT:
2072 return stripes->textures.list[STRIPES_TEXTURE_SCREENSHOT];
2073 case MENU_ENUM_LABEL_DELETE_ENTRY:
2074 return stripes->textures.list[STRIPES_TEXTURE_CLOSE];
2075 case MENU_ENUM_LABEL_RESTART_CONTENT:
2076 return stripes->textures.list[STRIPES_TEXTURE_RELOAD];
2077 case MENU_ENUM_LABEL_RENAME_ENTRY:
2078 return stripes->textures.list[STRIPES_TEXTURE_RENAME];
2079 case MENU_ENUM_LABEL_RESUME_CONTENT:
2080 return stripes->textures.list[STRIPES_TEXTURE_RESUME];
2081 case MENU_ENUM_LABEL_SAVE_CURRENT_CONFIG_OVERRIDE_CORE:
2082 case MENU_ENUM_LABEL_SAVE_CURRENT_CONFIG_OVERRIDE_GAME:
2083 return stripes->textures.list[STRIPES_TEXTURE_SAVESTATE];
2084 case MENU_ENUM_LABEL_FAVORITES:
2085 case MENU_ENUM_LABEL_DOWNLOADED_FILE_DETECT_CORE_LIST:
2086 return stripes->textures.list[STRIPES_TEXTURE_FOLDER];
2087 case MENU_ENUM_LABEL_FILE_DETECT_CORE_LIST_PUSH_DIR:
2088 return stripes->textures.list[STRIPES_TEXTURE_RDB];
2089 default:
2090 break;
2091 }
2092
2093 switch(type)
2094 {
2095 case FILE_TYPE_DIRECTORY:
2096 return stripes->textures.list[STRIPES_TEXTURE_FOLDER];
2097 case FILE_TYPE_PLAIN:
2098 case FILE_TYPE_IN_CARCHIVE:
2099 return stripes->textures.list[STRIPES_TEXTURE_FILE];
2100 case FILE_TYPE_RPL_ENTRY:
2101 if (core_node)
2102 return core_node->content_icon;
2103
2104 switch (stripes_get_system_tab(stripes,
2105 (unsigned)stripes->categories_selection_ptr))
2106 {
2107 case STRIPES_SYSTEM_TAB_FAVORITES:
2108 return stripes->textures.list[STRIPES_TEXTURE_FAVORITE];
2109 case STRIPES_SYSTEM_TAB_MUSIC:
2110 return stripes->textures.list[STRIPES_TEXTURE_MUSIC];
2111 #ifdef HAVE_IMAGEVIEWER
2112 case STRIPES_SYSTEM_TAB_IMAGES:
2113 return stripes->textures.list[STRIPES_TEXTURE_IMAGE];
2114 #endif
2115 #ifdef HAVE_FFMPEG
2116 case STRIPES_SYSTEM_TAB_VIDEO:
2117 return stripes->textures.list[STRIPES_TEXTURE_MOVIE];
2118 #endif
2119 default:
2120 break;
2121 }
2122 return stripes->textures.list[STRIPES_TEXTURE_FILE];
2123 case FILE_TYPE_CARCHIVE:
2124 return stripes->textures.list[STRIPES_TEXTURE_ZIP];
2125 case FILE_TYPE_MUSIC:
2126 return stripes->textures.list[STRIPES_TEXTURE_MUSIC];
2127 case FILE_TYPE_IMAGE:
2128 case FILE_TYPE_IMAGEVIEWER:
2129 return stripes->textures.list[STRIPES_TEXTURE_IMAGE];
2130 case FILE_TYPE_MOVIE:
2131 return stripes->textures.list[STRIPES_TEXTURE_MOVIE];
2132 case FILE_TYPE_CORE:
2133 case FILE_TYPE_DIRECT_LOAD:
2134 return stripes->textures.list[STRIPES_TEXTURE_CORE];
2135 case FILE_TYPE_RDB:
2136 return stripes->textures.list[STRIPES_TEXTURE_RDB];
2137 case FILE_TYPE_CURSOR:
2138 return stripes->textures.list[STRIPES_TEXTURE_CURSOR];
2139 case FILE_TYPE_PLAYLIST_ENTRY:
2140 case MENU_SETTING_ACTION_RUN:
2141 return stripes->textures.list[STRIPES_TEXTURE_RUN];
2142 case MENU_SETTING_ACTION_CLOSE:
2143 case MENU_SETTING_ACTION_CLOSE_HORIZONTAL:
2144 return stripes->textures.list[STRIPES_TEXTURE_CLOSE];
2145 case MENU_SETTING_ACTION_SAVESTATE:
2146 return stripes->textures.list[STRIPES_TEXTURE_SAVESTATE];
2147 case MENU_SETTING_ACTION_LOADSTATE:
2148 return stripes->textures.list[STRIPES_TEXTURE_LOADSTATE];
2149 case FILE_TYPE_RDB_ENTRY:
2150 return stripes->textures.list[STRIPES_TEXTURE_CORE_INFO];
2151 case MENU_SETTING_ACTION_CORE_OPTIONS:
2152 case MENU_ENUM_LABEL_SET_CORE_ASSOCIATION:
2153 return stripes->textures.list[STRIPES_TEXTURE_CORE_OPTIONS];
2154 case MENU_SETTING_ACTION_CORE_INPUT_REMAPPING_OPTIONS:
2155 return stripes->textures.list[STRIPES_TEXTURE_INPUT_REMAPPING_OPTIONS];
2156 case MENU_SETTING_ACTION_CORE_CHEAT_OPTIONS:
2157 return stripes->textures.list[STRIPES_TEXTURE_CHEAT_OPTIONS];
2158 case MENU_SETTING_ACTION_CORE_DISK_OPTIONS:
2159 return stripes->textures.list[STRIPES_TEXTURE_DISK_OPTIONS];
2160 case MENU_SETTING_ACTION_CORE_SHADER_OPTIONS:
2161 return stripes->textures.list[STRIPES_TEXTURE_SHADER_OPTIONS];
2162 case MENU_SETTING_ACTION_SCREENSHOT:
2163 return stripes->textures.list[STRIPES_TEXTURE_SCREENSHOT];
2164 case MENU_SETTING_ACTION_DELETE_ENTRY:
2165 return stripes->textures.list[STRIPES_TEXTURE_CLOSE];
2166 case MENU_SETTING_ACTION_RESET:
2167 return stripes->textures.list[STRIPES_TEXTURE_RELOAD];
2168 case MENU_SETTING_ACTION:
2169 if (stripes->depth == 3)
2170 return stripes->textures.list[STRIPES_TEXTURE_SUBSETTING];
2171 return stripes->textures.list[STRIPES_TEXTURE_SETTING];
2172 case MENU_SETTING_GROUP:
2173 return stripes->textures.list[STRIPES_TEXTURE_SETTING];
2174 case MENU_INFO_MESSAGE:
2175 return stripes->textures.list[STRIPES_TEXTURE_CORE_INFO];
2176 case MENU_BLUETOOTH:
2177 return stripes->textures.list[STRIPES_TEXTURE_BLUETOOTH];
2178 case MENU_WIFI:
2179 return stripes->textures.list[STRIPES_TEXTURE_WIFI];
2180 #ifdef HAVE_NETWORKING
2181 case MENU_ROOM:
2182 return stripes->textures.list[STRIPES_TEXTURE_ROOM];
2183 #if 0
2184 /* stub these out until we have the icons */
2185 case MENU_ROOM_LAN:
2186 return stripes->textures.list[STRIPES_TEXTURE_ROOM_LAN];
2187 case MENU_ROOM_MITM:
2188 return stripes->textures.list[STRIPES_TEXTURE_ROOM_MITM];
2189 #endif
2190 #endif
2191 }
2192
2193 #ifdef HAVE_CHEEVOS
2194 if (
2195 (type >= MENU_SETTINGS_CHEEVOS_START) &&
2196 (type < MENU_SETTINGS_NETPLAY_ROOMS_START)
2197 )
2198 {
2199 int index = type - MENU_SETTINGS_CHEEVOS_START;
2200 uintptr_t badge_texture = cheevos_get_menu_badge_texture(index);
2201 if (badge_texture)
2202 return badge_texture;
2203 /* Should be replaced with placeholder badge icon. */
2204 return stripes->textures.list[STRIPES_TEXTURE_SUBSETTING];
2205 }
2206 #endif
2207
2208 return stripes->textures.list[STRIPES_TEXTURE_SUBSETTING];
2209 }
2210
stripes_calculate_visible_range(const stripes_handle_t * stripes,unsigned height,size_t list_size,unsigned current,unsigned * first,unsigned * last)2211 static void stripes_calculate_visible_range(const stripes_handle_t *stripes,
2212 unsigned height, size_t list_size, unsigned current,
2213 unsigned *first, unsigned *last)
2214 {
2215 unsigned j;
2216 float base_y = stripes->margins_screen_top;
2217
2218 *first = 0;
2219 *last = list_size ? list_size - 1 : 0;
2220
2221 if (current)
2222 {
2223 for (j = current; j-- > 0; )
2224 {
2225 float bottom = stripes_item_y(stripes, j, current)
2226 + base_y + stripes->icon_size;
2227
2228 if (bottom < 0)
2229 break;
2230
2231 *first = j;
2232 }
2233 }
2234
2235 for (j = current+1; j < list_size; j++)
2236 {
2237 float top = stripes_item_y(stripes, j, current) + base_y;
2238
2239 if (top > height)
2240 break;
2241
2242 *last = j;
2243 }
2244 }
2245
stripes_draw_item(void * userdata,unsigned video_width,unsigned video_height,bool xmb_shadows_enable,menu_entry_t * entry,math_matrix_4x4 * mymat,stripes_handle_t * stripes,stripes_node_t * core_node,file_list_t * list,float * color,const char * thumb_ident,const char * left_thumb_ident,size_t i,size_t current,unsigned width,unsigned height)2246 static int stripes_draw_item(
2247 void *userdata,
2248 unsigned video_width,
2249 unsigned video_height,
2250 bool xmb_shadows_enable,
2251 menu_entry_t *entry,
2252 math_matrix_4x4 *mymat,
2253 stripes_handle_t *stripes,
2254 stripes_node_t *core_node,
2255 file_list_t *list,
2256 float *color,
2257 const char *thumb_ident,
2258 const char *left_thumb_ident,
2259 size_t i,
2260 size_t current,
2261 unsigned width,
2262 unsigned height
2263 )
2264 {
2265 float icon_x, icon_y, label_offset;
2266 gfx_animation_ctx_ticker_t ticker;
2267 char tmp[255];
2268 const char *ticker_str = NULL;
2269 unsigned entry_type = 0;
2270 const float half_size = stripes->icon_size / 2.0f;
2271 uintptr_t texture_switch = 0;
2272 bool do_draw_text = false;
2273 unsigned ticker_limit = 35 * stripes_scale_mod[0];
2274 stripes_node_t * node = (stripes_node_t*)
2275 file_list_get_userdata_at_offset(list, i);
2276 settings_t *settings = config_get_ptr();
2277 gfx_animation_t *p_anim = anim_get_ptr();
2278
2279 /* Initial ticker configuration */
2280 ticker.type_enum = settings->uints.menu_ticker_type;
2281 ticker.spacer = NULL;
2282
2283 if (!node)
2284 goto iterate;
2285
2286 tmp[0] = '\0';
2287
2288 icon_y = stripes->margins_screen_top + node->y + half_size;
2289
2290 if (icon_y < half_size)
2291 goto iterate;
2292
2293 if (icon_y > height + stripes->icon_size)
2294 goto end;
2295
2296 icon_x = node->x + stripes->margins_screen_left +
2297 stripes->icon_spacing_horizontal - half_size;
2298
2299 if (icon_x < -half_size || icon_x > width)
2300 goto iterate;
2301
2302 entry_type = entry.type;
2303
2304 if (entry_type == FILE_TYPE_CONTENTLIST_ENTRY)
2305 {
2306 char entry_path[PATH_MAX_LENGTH];
2307
2308 entry_path[0] = '\0';
2309 strlcpy(entry_path, entry->path, sizeof(entry_path));
2310
2311 fill_short_pathname_representation(entry_path, entry_path,
2312 sizeof(entry_path));
2313
2314 if (!string_is_empty(entry_path))
2315 {
2316 if (!string_is_empty(entry->path))
2317 free(entry->path);
2318 entry->path = strdup(entry_path);
2319 }
2320 }
2321
2322 if (string_is_equal(entry->value,
2323 msg_hash_to_str(MENU_ENUM_LABEL_DISABLED)) ||
2324 (string_is_equal(entry->value,
2325 msg_hash_to_str(MENU_ENUM_LABEL_VALUE_OFF))))
2326 {
2327 if (stripes->textures.list[STRIPES_TEXTURE_SWITCH_OFF])
2328 texture_switch = stripes->textures.list[STRIPES_TEXTURE_SWITCH_OFF];
2329 else
2330 do_draw_text = true;
2331 }
2332 else if (string_is_equal(entry->value,
2333 msg_hash_to_str(MENU_ENUM_LABEL_ENABLED)) ||
2334 (string_is_equal(entry->value,
2335 msg_hash_to_str(MENU_ENUM_LABEL_VALUE_ON))))
2336 {
2337 if (stripes->textures.list[STRIPES_TEXTURE_SWITCH_ON])
2338 texture_switch = stripes->textures.list[STRIPES_TEXTURE_SWITCH_ON];
2339 else
2340 do_draw_text = true;
2341 }
2342 else
2343 {
2344 if (!string_is_empty(entry->value))
2345 {
2346 if (
2347 string_is_equal(entry->value, "...") ||
2348 string_is_equal(entry->value, "(COMP)") ||
2349 string_is_equal(entry->value, "(CORE)") ||
2350 string_is_equal(entry->value, "(MOVIE)") ||
2351 string_is_equal(entry->value, "(MUSIC)") ||
2352 string_is_equal(entry->value, "(DIR)") ||
2353 string_is_equal(entry->value, "(RDB)") ||
2354 string_is_equal(entry->value, "(CURSOR)")||
2355 string_is_equal(entry->value, "(CFILE)") ||
2356 string_is_equal(entry->value, "(FILE)") ||
2357 string_is_equal(entry->value, "(IMAGE)")
2358 )
2359 {
2360 }
2361 else
2362 do_draw_text = true;
2363 }
2364 else
2365 do_draw_text = true;
2366
2367 }
2368
2369 if (string_is_empty(entry->value))
2370 {
2371 if (stripes->savestate_thumbnail ||
2372 (!string_is_equal
2373 (thumb_ident,
2374 msg_hash_to_str(MENU_ENUM_LABEL_VALUE_OFF))
2375 && stripes->thumbnail) ||
2376 (!string_is_equal
2377 (left_thumb_ident,
2378 msg_hash_to_str(MENU_ENUM_LABEL_VALUE_OFF))
2379 && stripes->left_thumbnail
2380 && settings->bools.menu_xmb_vertical_thumbnails)
2381 )
2382 ticker_limit = 40 * stripes_scale_mod[1];
2383 else
2384 ticker_limit = 70 * stripes_scale_mod[2];
2385 }
2386
2387 if (!string_is_empty(entry->path))
2388 {
2389 if (!string_is_empty(entry.rich_label))
2390 ticker_str = entry.rich_label;
2391 else
2392 ticker_str = entry.path;
2393 }
2394
2395 ticker.s = tmp;
2396 ticker.len = ticker_limit;
2397 ticker.idx = p_anim->ticker_idx;
2398 ticker.str = ticker_str;
2399 ticker.selected = (i == current);
2400
2401 if (ticker.str)
2402 gfx_animation_ticker(&ticker);
2403
2404 label_offset = stripes->margins_label_top;
2405 if (i == current && width > 320 && height > 240
2406 && !string_is_empty(entry->sublabel))
2407 {
2408 char entry_sublabel[MENU_SUBLABEL_MAX_LENGTH] = {0};
2409
2410 label_offset = - stripes->margins_label_top;
2411
2412 (stripes->word_wrap)(entry_sublabel, sizeof(entry_sublabel),
2413 entry->sublabel, 50 * stripes_scale_mod[3], 100, 0);
2414
2415 stripes_draw_text(xmb_shadows_enable, stripes, entry_sublabel,
2416 node->x + stripes->margins_screen_left +
2417 stripes->icon_spacing_horizontal + stripes->margins_label_left,
2418 stripes->margins_screen_top + node->y + stripes->margins_label_top*3.5,
2419 1, node->label_alpha, TEXT_ALIGN_LEFT,
2420 width, height, stripes->font2);
2421 }
2422
2423 stripes_draw_text(xmb_shadows_enable, stripes, tmp,
2424 node->x + stripes->margins_screen_left +
2425 stripes->icon_spacing_horizontal + stripes->margins_label_left,
2426 stripes->margins_screen_top + node->y + label_offset,
2427 1, node->label_alpha, TEXT_ALIGN_LEFT,
2428 width, height, stripes->font);
2429
2430 tmp[0] = '\0';
2431
2432 ticker.s = tmp;
2433 ticker.len = 35 * stripes_scale_mod[7];
2434 ticker.idx = p_anim->ticker_idx;
2435 ticker.selected = (i == current);
2436
2437 if (!string_is_empty(entry->value))
2438 {
2439 ticker.str = entry->value;
2440 gfx_animation_ticker(&ticker);
2441 }
2442
2443 if (do_draw_text)
2444 stripes_draw_text(xmb_shadows_enable, stripes, tmp,
2445 node->x +
2446 + stripes->margins_screen_left
2447 + stripes->icon_spacing_horizontal
2448 + stripes->margins_label_left
2449 + stripes->margins_setting_left,
2450 stripes->margins_screen_top + node->y + stripes->margins_label_top,
2451 1,
2452 node->label_alpha,
2453 TEXT_ALIGN_LEFT,
2454 width, height, stripes->font);
2455
2456 gfx_display_set_alpha(color, MIN(node->alpha, stripes->alpha));
2457
2458 if (color[3] != 0)
2459 {
2460 math_matrix_4x4 mymat_tmp;
2461 gfx_display_ctx_rotate_draw_t rotate_draw;
2462 uintptr_t texture = stripes_icon_get_id(stripes, core_node, node,
2463 entry->enum_idx, entry_type, (i == current));
2464 float x = icon_x;
2465 float y = icon_y;
2466 float rotation = 0;
2467 float scale_factor = node->zoom;
2468
2469 rotate_draw.matrix = &mymat_tmp;
2470 rotate_draw.rotation = rotation;
2471 rotate_draw.scale_x = scale_factor;
2472 rotate_draw.scale_y = scale_factor;
2473 rotate_draw.scale_z = 1;
2474 rotate_draw.scale_enable = true;
2475
2476 gfx_display_rotate_z(p_disp, &rotate_draw, userdata);
2477
2478 stripes_draw_icon(
2479 userdata,
2480 video_width,
2481 video_height,
2482 xmb_shadows_enable,
2483 stripes->icon_size,
2484 &mymat_tmp,
2485 texture,
2486 x,
2487 y,
2488 width,
2489 height,
2490 1.0,
2491 rotation,
2492 scale_factor,
2493 &color[0],
2494 stripes->shadow_offset);
2495 }
2496
2497 gfx_display_set_alpha(color, MIN(node->alpha, stripes->alpha));
2498
2499 if (texture_switch != 0 && color[3] != 0)
2500 stripes_draw_icon(
2501 userdata,
2502 video_width,
2503 video_height,
2504 xmb_shadows_enable,
2505 stripes->icon_size,
2506 mymat,
2507 texture_switch,
2508 node->x + stripes->margins_screen_left
2509 + stripes->icon_spacing_horizontal
2510 + stripes->icon_size / 2.0 + stripes->margins_setting_left,
2511 stripes->margins_screen_top + node->y + stripes->icon_size / 2.0,
2512 width, height,
2513 node->alpha,
2514 0,
2515 1,
2516 &color[0],
2517 stripes->shadow_offset);
2518
2519 iterate:
2520 return 0;
2521
2522 end:
2523 return -1;
2524 }
2525
stripes_draw_items(void * userdata,unsigned video_width,unsigned video_height,bool xmb_shadows_enable,stripes_handle_t * stripes,file_list_t * list,size_t current,size_t cat_selection_ptr,float * color,unsigned width,unsigned height)2526 static void stripes_draw_items(
2527 void *userdata,
2528 unsigned video_width,
2529 unsigned video_height,
2530 bool xmb_shadows_enable,
2531 stripes_handle_t *stripes,
2532 file_list_t *list,
2533 size_t current, size_t cat_selection_ptr, float *color,
2534 unsigned width, unsigned height)
2535 {
2536 size_t i;
2537 unsigned first, last;
2538 math_matrix_4x4 mymat;
2539 gfx_display_ctx_rotate_draw_t rotate_draw;
2540 stripes_node_t *core_node = NULL;
2541 size_t end = 0;
2542 const char *thumb_ident = stripes_thumbnails_ident('R');
2543 const char *left_thumb_ident = stripes_thumbnails_ident('L');
2544 gfx_display_t *p_disp = disp_get_ptr();
2545 gfx_display_ctx_driver_t *dispctx = p_disp->dispctx;
2546
2547 if (!list || !list->size || !stripes)
2548 return;
2549
2550 if (cat_selection_ptr > stripes->system_tab_end)
2551 core_node = stripes_get_userdata_from_horizontal_list(
2552 stripes, (unsigned)(cat_selection_ptr - (stripes->system_tab_end + 1)));
2553
2554 end = list ? list->size : NULL;
2555
2556 rotate_draw.matrix = &mymat;
2557 rotate_draw.rotation = 0;
2558 rotate_draw.scale_x = 1;
2559 rotate_draw.scale_y = 1;
2560 rotate_draw.scale_z = 1;
2561 rotate_draw.scale_enable = true;
2562
2563 gfx_display_rotate_z(p_disp, &rotate_draw, userdata);
2564
2565 menu_entries_ctl(MENU_ENTRIES_CTL_START_GET, &i);
2566
2567 if (list == &stripes->selection_buf_old)
2568 {
2569 stripes_node_t *node = (stripes_node_t*)
2570 file_list_get_userdata_at_offset(list, current);
2571
2572 if (node && (uint8_t)(255 * node->alpha) == 0)
2573 return;
2574
2575 i = 0;
2576 }
2577
2578 first = i;
2579 last = end - 1;
2580
2581 stripes_calculate_visible_range(stripes, height, end, current, &first, &last);
2582
2583 if (dispctx && dispctx->blend_begin)
2584 dispctx->blend_begin(userdata);
2585
2586 for (i = first; i <= last; i++)
2587 {
2588 int ret;
2589 menu_entry_t entry;
2590 MENU_ENTRY_INIT(entry);
2591 menu_entry_get(&entry, 0, i, list, true);
2592 ret = stripes_draw_item(
2593 userdata,
2594 video_width,
2595 video_height,
2596 xmb_shadows_enable,
2597 &entry,
2598 &mymat,
2599 stripes, core_node,
2600 list, color, thumb_ident, left_thumb_ident,
2601 i, current,
2602 width, height);
2603 if (ret == -1)
2604 break;
2605 }
2606
2607 if (dispctx && dispctx->blend_end)
2608 dispctx->blend_end(userdata);
2609 }
2610
stripes_render(void * data,unsigned width,unsigned height,bool is_idle)2611 static void stripes_render(void *data,
2612 unsigned width, unsigned height,
2613 bool is_idle)
2614 {
2615 size_t i;
2616 menu_input_pointer_t pointer;
2617 settings_t *settings = config_get_ptr();
2618 stripes_handle_t *stripes = (stripes_handle_t*)data;
2619 unsigned end = (unsigned)menu_entries_get_size();
2620 gfx_animation_t *p_anim = anim_get_ptr();
2621
2622 if (!stripes)
2623 return;
2624
2625 menu_input_get_pointer_state(&pointer);
2626
2627 if (pointer.type != MENU_POINTER_DISABLED)
2628 {
2629 size_t selection = menu_navigation_get_selection();
2630 int16_t pointer_y = pointer.y;
2631 unsigned first = 0, last = end;
2632
2633 pointer_y = (pointer.type == MENU_POINTER_MOUSE) ?
2634 pointer_y + (stripes->cursor_size/2) : pointer_y;
2635
2636 if (height)
2637 stripes_calculate_visible_range(stripes, height,
2638 end, selection, &first, &last);
2639
2640 for (i = first; i <= last; i++)
2641 {
2642 float item_y1 = stripes->margins_screen_top
2643 + stripes_item_y(stripes, (int)i, selection);
2644 float item_y2 = item_y1 + stripes->icon_size;
2645
2646 if (pointer_y > item_y1 && pointer_y < item_y2)
2647 menu_input_set_pointer_selection(i);
2648 }
2649 }
2650
2651 menu_entries_ctl(MENU_ENTRIES_CTL_START_GET, &i);
2652
2653 if (i >= end)
2654 {
2655 i = 0;
2656 menu_entries_ctl(MENU_ENTRIES_CTL_SET_START, &i);
2657 }
2658
2659 GFX_ANIMATION_CLEAR_ACTIVE(p_anim);
2660 }
2661
stripes_shader_pipeline_active(unsigned menu_shader_pipeline)2662 static bool stripes_shader_pipeline_active(unsigned menu_shader_pipeline)
2663 {
2664 if (string_is_not_equal(menu_driver_ident(), "stripes"))
2665 return false;
2666 if (menu_shader_pipeline == XMB_SHADER_PIPELINE_WALLPAPER)
2667 return false;
2668 return true;
2669 }
2670
stripes_draw_bg(stripes_handle_t * stripes,void * userdata,unsigned video_width,unsigned video_height,unsigned width,unsigned height)2671 static void stripes_draw_bg(
2672 stripes_handle_t *stripes,
2673 void *userdata,
2674 unsigned video_width,
2675 unsigned video_height,
2676 unsigned width,
2677 unsigned height)
2678 {
2679 gfx_display_ctx_draw_t draw;
2680 struct video_coords coords;
2681 float rgb[3];
2682 HSLToRGB(0.0,0.5,0.5, &rgb[0]);
2683 float color[16] = {
2684 rgb[0], rgb[1], rgb[2], 1,
2685 rgb[0], rgb[1], rgb[2], 1,
2686 rgb[0], rgb[1], rgb[2], 1,
2687 rgb[0], rgb[1], rgb[2], 1,
2688 };
2689 gfx_display_t *p_disp = disp_get_ptr();
2690 gfx_display_ctx_driver_t *dispctx = p_disp->dispctx;
2691
2692 coords.vertices = 4;
2693 coords.vertex = NULL;
2694 coords.tex_coord = NULL;
2695 coords.lut_tex_coord = NULL;
2696 coords.color = &color[0];
2697
2698 draw.x = 0;
2699 draw.y = 0;
2700 draw.width = width;
2701 draw.height = height;
2702 draw.coords = &coords;
2703 draw.matrix_data = NULL;
2704 draw.texture = gfx_display_white_texture;
2705 draw.prim_type = GFX_DISPLAY_PRIM_TRIANGLESTRIP;
2706 draw.pipeline_id = 0;
2707
2708 if (dispctx)
2709 {
2710 if (dispctx->blend_begin)
2711 dispctx->blend_begin(userdata);
2712 if (dispctx->draw)
2713 if (draw.height > 0 && draw.width > 0)
2714 dispctx->draw(&draw, userdata, video_width, video_height);
2715 if (dispctx->blend_end)
2716 dispctx->blend_end(userdata);
2717 }
2718 }
2719
stripes_draw_dark_layer(stripes_handle_t * stripes,void * userdata,unsigned video_width,unsigned video_height,unsigned width,unsigned height)2720 static void stripes_draw_dark_layer(
2721 stripes_handle_t *stripes,
2722 void *userdata,
2723 unsigned video_width,
2724 unsigned video_height,
2725 unsigned width,
2726 unsigned height)
2727 {
2728 gfx_display_ctx_draw_t draw;
2729 struct video_coords coords;
2730 float black[16] = {
2731 0, 0, 0, 1,
2732 0, 0, 0, 1,
2733 0, 0, 0, 1,
2734 0, 0, 0, 1,
2735 };
2736 gfx_display_t *p_disp = disp_get_ptr();
2737 gfx_display_ctx_driver_t *dispctx = p_disp->dispctx;
2738
2739 gfx_display_set_alpha(black, MIN(stripes->alpha, 0.75));
2740
2741 coords.vertices = 4;
2742 coords.vertex = NULL;
2743 coords.tex_coord = NULL;
2744 coords.lut_tex_coord = NULL;
2745 coords.color = &black[0];
2746
2747 draw.x = 0;
2748 draw.y = 0;
2749 draw.width = width;
2750 draw.height = height;
2751 draw.coords = &coords;
2752 draw.matrix_data = NULL;
2753 draw.texture = gfx_display_white_texture;
2754 draw.prim_type = GFX_DISPLAY_PRIM_TRIANGLESTRIP;
2755 draw.pipeline_id = 0;
2756
2757 if (dispctx)
2758 {
2759 if (dispctx->blend_begin)
2760 dispctx->blend_begin(userdata);
2761 if (dispctx->draw)
2762 if (draw.height > 0 && draw.width > 0)
2763 dispctx->draw(&draw, userdata, video_width, video_height);
2764 if (dispctx->blend_end)
2765 dispctx->blend_end(userdata);
2766 }
2767 }
2768
stripes_frame(void * data,video_frame_info_t * video_info)2769 static void stripes_frame(void *data, video_frame_info_t *video_info)
2770 {
2771 math_matrix_4x4 mymat;
2772 unsigned i;
2773 gfx_display_ctx_rotate_draw_t rotate_draw;
2774 char msg[1024];
2775 char title_msg[255];
2776 char title_truncated[255];
2777 size_t selection = 0;
2778 size_t percent_width = 0;
2779 const int min_thumb_size = 50;
2780 bool render_background = false;
2781 file_list_t *selection_buf = NULL;
2782 void *userdata = video_info->userdata;
2783 unsigned video_width = video_info->width;
2784 unsigned video_height = video_info->height;
2785 float xmb_alpha_factor = video_info->xmb_alpha_factor;
2786 bool xmb_shadows_enable = video_info->xmb_shadows_enable;
2787 bool video_fullscreen = video_info->fullscreen;
2788 bool mouse_grabbed = video_info->input_driver_grab_mouse_state;
2789 bool menu_mouse_enable = video_info->menu_mouse_enable;
2790 const float under_thumb_margin = 0.96;
2791 float scale_factor = 0.0f;
2792 float pseudo_font_length = 0.0f;
2793 float stack_width = 285;
2794 stripes_handle_t *stripes = (stripes_handle_t*)data;
2795 settings_t *settings = config_get_ptr();
2796 gfx_display_t *p_disp = disp_get_ptr();
2797 gfx_display_ctx_driver_t *dispctx = p_disp->dispctx;
2798
2799 if (!stripes)
2800 return;
2801
2802 scale_factor = (settings->floats.menu_scale_factor * (float)video_width) / 1920.0f;
2803 pseudo_font_length = stripes->icon_spacing_horizontal * 4 - stripes->icon_size / 4;
2804
2805 msg[0] = '\0';
2806 title_msg[0] = '\0';
2807 title_truncated[0] = '\0';
2808
2809 font_driver_bind_block(stripes->font, &stripes->raster_block);
2810 font_driver_bind_block(stripes->font2, &stripes->raster_block2);
2811
2812 stripes->raster_block.carr.coords.vertices = 0;
2813 stripes->raster_block2.carr.coords.vertices = 0;
2814
2815 gfx_display_set_alpha(stripes_coord_black, MIN(
2816 (float)xmb_alpha_factor / 100, stripes->alpha));
2817 gfx_display_set_alpha(stripes_coord_white, stripes->alpha);
2818
2819 stripes_draw_bg(
2820 stripes,
2821 userdata,
2822 video_width,
2823 video_height,
2824 video_width,
2825 video_height);
2826
2827 selection = menu_navigation_get_selection();
2828
2829 rotate_draw.matrix = &mymat;
2830 rotate_draw.rotation = 0;
2831 rotate_draw.scale_x = 1;
2832 rotate_draw.scale_y = 1;
2833 rotate_draw.scale_z = 1;
2834 rotate_draw.scale_enable = true;
2835
2836 gfx_display_rotate_z(p_disp, &rotate_draw, userdata);
2837 if (dispctx && dispctx->blend_begin)
2838 dispctx->blend_begin(userdata);
2839
2840 /* Horizontal stripes */
2841 for (i = 0; i <= stripes_list_get_size(stripes, MENU_LIST_HORIZONTAL)
2842 + stripes->system_tab_end; i++)
2843 {
2844 float color[16];
2845 float rgb[3];
2846 stripes_node_t *node = stripes_get_node(stripes, i);
2847
2848 if (!node)
2849 continue;
2850
2851 HSLToRGB(0.07*(float)i,0.5,0.5, &rgb[0]) ;
2852 color[0] = rgb[0];
2853 color[1] = rgb[1];
2854 color[2] = rgb[2];
2855 color[3] = 0.55;
2856 color[4] = rgb[0];
2857 color[5] = rgb[1];
2858 color[6] = rgb[2];
2859 color[7] = 0.55;
2860 color[8] = rgb[0];
2861 color[9] = rgb[1];
2862 color[10] = rgb[2];
2863 color[11] = 0.55;
2864 color[12] = rgb[0];
2865 color[13] = rgb[1];
2866 color[14] = rgb[2];
2867 color[15] = 0.55;
2868
2869 gfx_display_draw_polygon(
2870 p_disp,
2871 userdata,
2872 video_width,
2873 video_height,
2874 stripes->categories_x_pos + stack_width,
2875 0,
2876 stripes->categories_x_pos + stack_width + node->width,
2877 0,
2878 stripes->categories_x_pos + stack_width + stripes->categories_angle,
2879 video_height,
2880 stripes->categories_x_pos + stack_width + stripes->categories_angle + node->width,
2881 video_height,
2882 video_width, video_height,
2883 &color[0]);
2884
2885 if (dispctx && dispctx->blend_begin)
2886 dispctx->blend_begin(userdata);
2887
2888 stack_width += node->width;
2889 }
2890
2891 stack_width = 285;
2892
2893 /* Horizontal tab icons */
2894 for (i = 0; i <= stripes_list_get_size(stripes, MENU_LIST_HORIZONTAL)
2895 + stripes->system_tab_end; i++)
2896 {
2897 stripes_node_t *node = stripes_get_node(stripes, i);
2898
2899 if (!node)
2900 continue;
2901
2902 gfx_display_set_alpha(stripes_item_color, MIN(node->alpha, stripes->alpha));
2903
2904 if (stripes_item_color[3] != 0)
2905 {
2906 gfx_display_ctx_rotate_draw_t rotate_draw;
2907 math_matrix_4x4 mymat;
2908 uintptr_t texture = node->icon;
2909 float x = stripes->categories_x_pos + stack_width + node->x + node->width / 2.0
2910 - stripes->icon_size / 2.0;
2911 float y = node->y + stripes->icon_size / 2.0;
2912 float rotation = 0;
2913 float scale_factor = node->zoom;
2914
2915 rotate_draw.matrix = &mymat;
2916 rotate_draw.rotation = rotation;
2917 rotate_draw.scale_x = scale_factor;
2918 rotate_draw.scale_y = scale_factor;
2919 rotate_draw.scale_z = 1;
2920 rotate_draw.scale_enable = true;
2921
2922 gfx_display_rotate_z(p_disp, &rotate_draw, userdata);
2923
2924 stripes_draw_icon(
2925 userdata,
2926 video_width,
2927 video_height,
2928 xmb_shadows_enable,
2929 stripes->icon_size,
2930 &mymat,
2931 texture,
2932 x,
2933 y,
2934 video_width,
2935 video_height,
2936 1.0,
2937 rotation,
2938 scale_factor,
2939 &stripes_item_color[0],
2940 stripes->shadow_offset);
2941 }
2942
2943 stack_width += node->width;
2944 }
2945
2946 if (dispctx && dispctx->blend_end)
2947 dispctx->blend_end(userdata);
2948
2949 /* Vertical icons */
2950 #if 0
2951 if (stripes)
2952 stripes_draw_items(
2953 userdata,
2954 video_width,
2955 video_height,
2956 xmb_shadows_enable,
2957 stripes,
2958 &stripes->selection_buf_old,
2959 stripes->selection_ptr_old,
2960 (stripes_list_get_size(stripes, MENU_LIST_PLAIN) > 1)
2961 ? stripes->categories_selection_ptr :
2962 stripes->categories_selection_ptr_old,
2963 &stripes_item_color[0],
2964 video_width,
2965 video_height);
2966
2967 selection_buf = menu_entries_get_selection_buf_ptr(0);
2968
2969 if (stripes)
2970 stripes_draw_items(
2971 userdata,
2972 video_width,
2973 video_height,
2974 xmb_shadows_enable,
2975 stripes,
2976 selection_buf,
2977 selection,
2978 stripes->categories_selection_ptr,
2979 &stripes_item_color[0],
2980 video_width,
2981 video_height);
2982 #endif
2983
2984 font_driver_flush(video_width, video_height, stripes->font);
2985 font_driver_bind_block(stripes->font, NULL);
2986
2987 font_driver_flush(video_width, video_height, stripes->font2);
2988 font_driver_bind_block(stripes->font2, NULL);
2989
2990 if (menu_input_dialog_get_display_kb())
2991 {
2992 const char *str = menu_input_dialog_get_buffer();
2993 const char *label = menu_input_dialog_get_label_buffer();
2994
2995 snprintf(msg, sizeof(msg), "%s\n%s", label, str);
2996 render_background = true;
2997 }
2998
2999 if (!string_is_empty(stripes->box_message))
3000 {
3001 strlcpy(msg, stripes->box_message,
3002 sizeof(msg));
3003 free(stripes->box_message);
3004 stripes->box_message = NULL;
3005 render_background = true;
3006 }
3007
3008 if (render_background)
3009 {
3010 stripes_draw_dark_layer(stripes,
3011 userdata,
3012 video_width,
3013 video_height,
3014 video_width,
3015 video_height);
3016 stripes_render_messagebox_internal(
3017 stripes,
3018 userdata,
3019 video_width,
3020 video_height,
3021 msg);
3022 }
3023
3024 /* Cursor image */
3025 if (stripes->mouse_show)
3026 {
3027 menu_input_pointer_t pointer;
3028 bool cursor_visible = (video_fullscreen || mouse_grabbed) &&
3029 menu_mouse_enable;
3030
3031 menu_input_get_pointer_state(&pointer);
3032
3033 gfx_display_set_alpha(stripes_coord_white, MIN(stripes->alpha, 1.00f));
3034
3035 if (cursor_visible)
3036 gfx_display_draw_cursor(
3037 p_disp,
3038 userdata,
3039 video_width,
3040 video_height,
3041 cursor_visible,
3042 &stripes_coord_white[0],
3043 stripes->cursor_size,
3044 stripes->textures.list[STRIPES_TEXTURE_POINTER],
3045 pointer.x,
3046 pointer.y,
3047 video_width,
3048 video_height);
3049 }
3050
3051 video_driver_set_viewport(video_width, video_height, false, true);
3052 }
3053
stripes_layout_ps3(stripes_handle_t * stripes,int width,int height)3054 static void stripes_layout_ps3(stripes_handle_t *stripes, int width, int height)
3055 {
3056 unsigned new_font_size, new_header_height;
3057 gfx_display_t *p_disp = disp_get_ptr();
3058 settings_t *settings = config_get_ptr();
3059
3060 float scale_factor =
3061 (settings->floats.menu_scale_factor * width) / 1920.0f;
3062
3063 stripes->above_subitem_offset = 1.5;
3064 stripes->above_item_offset = -1.0;
3065 stripes->active_item_factor = 3.0;
3066 stripes->under_item_offset = 5.0;
3067
3068 stripes->categories_active_zoom = 1.0;
3069 stripes->categories_passive_zoom = 0.25;
3070
3071 stripes->categories_angle = 400 * scale_factor;
3072
3073 stripes->categories_active_y = height / 2;
3074 stripes->categories_before_y = 64 * scale_factor;
3075 stripes->categories_after_y = height - 64 * scale_factor;
3076
3077 stripes->categories_active_x = stripes->categories_angle / 2;
3078 stripes->categories_before_x = stripes->categories_angle - 22 * scale_factor;
3079 stripes->categories_after_x = 22 * scale_factor;
3080
3081 stripes->categories_passive_width = 128 * scale_factor;
3082 stripes->categories_active_width = 1200 * scale_factor;
3083
3084 stripes->items_active_zoom = 1.0;
3085 stripes->items_passive_zoom = 0.5;
3086
3087 stripes->categories_active_alpha = 1.0;
3088 stripes->categories_passive_alpha = 1.0;
3089 stripes->items_active_alpha = 1.0;
3090 stripes->items_passive_alpha = 0.85;
3091
3092 stripes->shadow_offset = 2.0;
3093
3094 new_font_size = 32.0 * scale_factor;
3095 stripes->font2_size = 24.0 * scale_factor;
3096 new_header_height = 128.0 * scale_factor;
3097
3098 stripes->thumbnail_width = 1024.0 * scale_factor;
3099 stripes->left_thumbnail_width = 1024.0 * scale_factor;
3100 stripes->savestate_thumbnail_width= 460.0 * scale_factor;
3101 stripes->cursor_size = 64.0 * scale_factor;
3102
3103 stripes->icon_spacing_horizontal = 200.0 * scale_factor;
3104 stripes->icon_spacing_vertical = 64.0 * scale_factor;
3105
3106 stripes->margins_screen_top = (256+32) * scale_factor;
3107 stripes->margins_screen_left = 336.0 * scale_factor;
3108
3109 stripes->margins_title_left = 60 * scale_factor;
3110 stripes->margins_title_top = 60 * scale_factor + new_font_size / 3;
3111 stripes->margins_title_bottom = 60 * scale_factor - new_font_size / 3;
3112
3113 stripes->margins_label_left = 85.0 * scale_factor;
3114 stripes->margins_label_top = new_font_size / 3.0;
3115
3116 stripes->margins_setting_left = 600.0 * scale_factor * stripes_scale_mod[6];
3117 stripes->margins_dialog = 48 * scale_factor;
3118
3119 stripes->margins_slice = 16;
3120
3121 stripes->icon_size = 256.0 * scale_factor;
3122 stripes->font_size = new_font_size;
3123
3124 #ifdef STRIPES_DEBUG
3125 RARCH_LOG("[XMB] margin screen left: %.2f\n", stripes->margins_screen_left);
3126 RARCH_LOG("[XMB] margin screen top: %.2f\n", stripes->margins_screen_top);
3127 RARCH_LOG("[XMB] margin title left: %.2f\n", stripes->margins_title_left);
3128 RARCH_LOG("[XMB] margin title top: %.2f\n", stripes->margins_title_top);
3129 RARCH_LOG("[XMB] margin title bott: %.2f\n", stripes->margins_title_bottom);
3130 RARCH_LOG("[XMB] margin label left: %.2f\n", stripes->margins_label_left);
3131 RARCH_LOG("[XMB] margin label top: %.2f\n", stripes->margins_label_top);
3132 RARCH_LOG("[XMB] margin sett left: %.2f\n", stripes->margins_setting_left);
3133 RARCH_LOG("[XMB] icon spacing hor: %.2f\n", stripes->icon_spacing_horizontal);
3134 RARCH_LOG("[XMB] icon spacing ver: %.2f\n", stripes->icon_spacing_vertical);
3135 RARCH_LOG("[XMB] icon size: %.2f\n", stripes->icon_size);
3136 #endif
3137
3138 p_disp->header_height = new_header_height;
3139 }
3140
stripes_layout_psp(stripes_handle_t * stripes,int width)3141 static void stripes_layout_psp(stripes_handle_t *stripes, int width)
3142 {
3143 unsigned new_font_size, new_header_height;
3144 gfx_display_t *p_disp = disp_get_ptr();
3145 settings_t *settings = config_get_ptr();
3146 float scale_factor =
3147 ((settings->floats.menu_scale_factor * width) / 1920.0) * 1.5;
3148 #ifdef _3DS
3149 scale_factor =
3150 settings->floats.menu_scale_factor / 4.0;
3151 #endif
3152
3153 stripes->above_subitem_offset = 1.5;
3154 stripes->above_item_offset = -1.0;
3155 stripes->active_item_factor = 2.0;
3156 stripes->under_item_offset = 3.0;
3157
3158 stripes->categories_active_zoom = 1.0;
3159 stripes->categories_passive_zoom = 1.0;
3160 stripes->items_active_zoom = 1.0;
3161 stripes->items_passive_zoom = 1.0;
3162
3163 stripes->categories_active_alpha = 1.0;
3164 stripes->categories_passive_alpha = 0.85;
3165 stripes->items_active_alpha = 1.0;
3166 stripes->items_passive_alpha = 0.85;
3167
3168 stripes->shadow_offset = 1.0;
3169
3170 new_font_size = 32.0 * scale_factor;
3171 stripes->font2_size = 24.0 * scale_factor;
3172 new_header_height = 128.0 * scale_factor;
3173 stripes->margins_screen_top = (256+32) * scale_factor;
3174
3175 stripes->thumbnail_width = 460.0 * scale_factor;
3176 stripes->left_thumbnail_width = 400.0 * scale_factor;
3177 stripes->savestate_thumbnail_width= 460.0 * scale_factor;
3178 stripes->cursor_size = 64.0;
3179
3180 stripes->icon_spacing_horizontal = 250.0 * scale_factor;
3181 stripes->icon_spacing_vertical = 108.0 * scale_factor;
3182
3183 stripes->margins_screen_left = 136.0 * scale_factor;
3184 stripes->margins_title_left = 60 * scale_factor;
3185 stripes->margins_title_top = 60 * scale_factor + new_font_size / 3;
3186 stripes->margins_title_bottom = 60 * scale_factor - new_font_size / 3;
3187 stripes->margins_label_left = 85.0 * scale_factor;
3188 stripes->margins_label_top = new_font_size / 3.0;
3189 stripes->margins_setting_left = 600.0 * scale_factor;
3190 stripes->margins_dialog = 48 * scale_factor;
3191 stripes->margins_slice = 16;
3192 stripes->icon_size = 128.0 * scale_factor;
3193 stripes->font_size = new_font_size;
3194
3195 #ifdef STRIPES_DEBUG
3196 RARCH_LOG("[XMB] margin screen left: %.2f\n", stripes->margins_screen_left);
3197 RARCH_LOG("[XMB] margin screen top: %.2f\n", stripes->margins_screen_top);
3198 RARCH_LOG("[XMB] margin title left: %.2f\n", stripes->margins_title_left);
3199 RARCH_LOG("[XMB] margin title top: %.2f\n", stripes->margins_title_top);
3200 RARCH_LOG("[XMB] margin title bott: %.2f\n", stripes->margins_title_bottom);
3201 RARCH_LOG("[XMB] margin label left: %.2f\n", stripes->margins_label_left);
3202 RARCH_LOG("[XMB] margin label top: %.2f\n", stripes->margins_label_top);
3203 RARCH_LOG("[XMB] margin sett left: %.2f\n", stripes->margins_setting_left);
3204 RARCH_LOG("[XMB] icon spacing hor: %.2f\n", stripes->icon_spacing_horizontal);
3205 RARCH_LOG("[XMB] icon spacing ver: %.2f\n", stripes->icon_spacing_vertical);
3206 RARCH_LOG("[XMB] icon size: %.2f\n", stripes->icon_size);
3207 #endif
3208
3209 p_disp->header_height = new_header_height;
3210 }
3211
stripes_layout(stripes_handle_t * stripes)3212 static void stripes_layout(stripes_handle_t *stripes)
3213 {
3214 unsigned width, height, i, current, end;
3215 file_list_t *selection_buf = menu_entries_get_selection_buf_ptr(0);
3216 size_t selection = menu_navigation_get_selection();
3217
3218 video_driver_get_size(&width, &height);
3219
3220 /* Mimic the layout of the PSP instead of the PS3 on tiny screens */
3221 if (width > 320 && height > 240)
3222 stripes_layout_ps3(stripes, width, height);
3223 else
3224 stripes_layout_psp(stripes, width);
3225
3226 current = (unsigned)selection;
3227 end = (unsigned)menu_entries_get_size();
3228
3229 for (i = 0; i < end; i++)
3230 {
3231 float ia = stripes->items_passive_alpha;
3232 float iz = stripes->items_passive_zoom;
3233 stripes_node_t *node = (stripes_node_t*)file_list_get_userdata_at_offset(
3234 selection_buf, i);
3235
3236 if (!node)
3237 continue;
3238
3239 if (i == current)
3240 {
3241 ia = stripes->items_active_alpha;
3242 iz = stripes->items_active_alpha;
3243 }
3244
3245 node->alpha = ia;
3246 node->label_alpha = ia;
3247 node->zoom = iz;
3248 node->y = stripes_item_y(stripes, i, current);
3249 }
3250
3251 if (stripes->depth <= 1)
3252 return;
3253
3254 current = (unsigned)stripes->selection_ptr_old;
3255 end = (unsigned)stripes->selection_buf_old.size;
3256
3257 for (i = 0; i < end; i++)
3258 {
3259 float ia = 0;
3260 float iz = stripes->items_passive_zoom;
3261 stripes_node_t *node = (stripes_node_t*)file_list_get_userdata_at_offset(
3262 &stripes->selection_buf_old, i);
3263
3264 if (!node)
3265 continue;
3266
3267 if (i == current)
3268 {
3269 ia = stripes->items_active_alpha;
3270 iz = stripes->items_active_alpha;
3271 }
3272
3273 node->alpha = ia;
3274 node->label_alpha = 0;
3275 node->zoom = iz;
3276 node->y = stripes_item_y(stripes, i, current);
3277 node->x = stripes->icon_size * 1 * -2;
3278 }
3279 }
3280
stripes_init(void ** userdata,bool video_is_threaded)3281 static void *stripes_init(void **userdata, bool video_is_threaded)
3282 {
3283 unsigned width, height;
3284 int i;
3285 stripes_handle_t *stripes = NULL;
3286 settings_t *settings = config_get_ptr();
3287 menu_handle_t *menu = (menu_handle_t*)calloc(1, sizeof(*menu));
3288 float scale_value = settings->floats.menu_scale_factor * 100.0f;
3289
3290 /* scaling multiplier formulas made from these values: */
3291 /* stripes_scale 50 = {2.5, 2.5, 2, 1.7, 2.5, 4, 2.4, 2.5} */
3292 /* stripes_scale 75 = { 2, 1.6, 1.6, 1.4, 1.5, 2.3, 1.9, 1.3} */
3293 if (scale_value < 100)
3294 {
3295 /* text length & word wrap (base 35 apply to file browser, 1st column) */
3296 stripes_scale_mod[0] = -0.03 * scale_value + 4.083;
3297 /* playlist text length when thumbnail is ON (small, base 40) */
3298 stripes_scale_mod[1] = -0.03 * scale_value + 3.95;
3299 /* playlist text length when thumbnail is OFF (large, base 70) */
3300 stripes_scale_mod[2] = -0.02 * scale_value + 3.033;
3301 /* sub-label length & word wrap */
3302 stripes_scale_mod[3] = -0.014 * scale_value + 2.416;
3303 /* thumbnail size & vertical margin from top */
3304 stripes_scale_mod[4] = -0.03 * scale_value + 3.916;
3305 /* thumbnail horizontal left margin (horizontal positioning) */
3306 stripes_scale_mod[5] = -0.06 * scale_value + 6.933;
3307 /* margin before 2nd column start (shaders parameters, cheats...) */
3308 stripes_scale_mod[6] = -0.028 * scale_value + 3.866;
3309 /* text length & word wrap (base 35 apply to 2nd column in cheats, shaders, etc) */
3310 stripes_scale_mod[7] = 134.179 * pow(scale_value, -1.0778);
3311
3312 for (i = 0; i < 8; i++)
3313 if (stripes_scale_mod[i] < 1)
3314 stripes_scale_mod[i] = 1;
3315 }
3316
3317 if (!menu)
3318 goto error;
3319
3320 video_driver_get_size(&width, &height);
3321
3322 stripes = (stripes_handle_t*)calloc(1, sizeof(stripes_handle_t));
3323
3324 if (!stripes)
3325 goto error;
3326
3327 *userdata = stripes;
3328
3329 if (!file_list_initialize(&stripes->selection_buf_old))
3330 goto error;
3331
3332 stripes->categories_active_idx = 0;
3333 stripes->categories_active_idx_old = 0;
3334 stripes->x = 0;
3335 stripes->categories_x_pos = 0;
3336 stripes->textures_arrow_alpha = 0;
3337 stripes->depth = 1;
3338 stripes->old_depth = 1;
3339 stripes->alpha = 0;
3340
3341 stripes->system_tab_end = 0;
3342 stripes->tabs[stripes->system_tab_end] = STRIPES_SYSTEM_TAB_MAIN;
3343 if (settings->bools.menu_content_show_settings && !settings->bools.kiosk_mode_enable)
3344 stripes->tabs[++stripes->system_tab_end] = STRIPES_SYSTEM_TAB_SETTINGS;
3345 if (settings->bools.menu_content_show_favorites)
3346 stripes->tabs[++stripes->system_tab_end] = STRIPES_SYSTEM_TAB_FAVORITES;
3347 if (settings->bools.menu_content_show_history)
3348 stripes->tabs[++stripes->system_tab_end] = STRIPES_SYSTEM_TAB_HISTORY;
3349 #ifdef HAVE_IMAGEVIEWER
3350 if (settings->bools.menu_content_show_images)
3351 stripes->tabs[++stripes->system_tab_end] = STRIPES_SYSTEM_TAB_IMAGES;
3352 #endif
3353 if (settings->bools.menu_content_show_music)
3354 stripes->tabs[++stripes->system_tab_end] = STRIPES_SYSTEM_TAB_MUSIC;
3355 #ifdef HAVE_FFMPEG
3356 if (settings->bools.menu_content_show_video)
3357 stripes->tabs[++stripes->system_tab_end] = STRIPES_SYSTEM_TAB_VIDEO;
3358 #endif
3359 #ifdef HAVE_NETWORKING
3360 if (settings->bools.menu_content_show_netplay)
3361 stripes->tabs[++stripes->system_tab_end] = STRIPES_SYSTEM_TAB_NETPLAY;
3362 #endif
3363
3364 if (settings->bools.menu_content_show_add && !settings->bools.kiosk_mode_enable)
3365 stripes->tabs[++stripes->system_tab_end] = STRIPES_SYSTEM_TAB_ADD;
3366
3367 menu_driver_ctl(RARCH_MENU_CTL_UNSET_PREVENT_POPULATE, NULL);
3368
3369 /* TODO/FIXME - we don't use framebuffer at all
3370 * for XMB, we should refactor this dependency
3371 * away. */
3372
3373 gfx_display_set_width(width);
3374 gfx_display_set_height(height);
3375
3376 gfx_display_init_white_texture(gfx_display_white_texture);
3377
3378 file_list_initialize(&stripes->horizontal_list);
3379 stripes_init_horizontal_list(stripes);
3380
3381 /* set word_wrap function pointer */
3382 stripes->word_wrap = msg_hash_get_wideglyph_str() ? word_wrap_wideglyph : word_wrap;
3383
3384 return menu;
3385
3386 error:
3387 if (menu)
3388 free(menu);
3389
3390 if (stripes)
3391 {
3392 stripes_free_list_nodes(&stripes->selection_buf_old, false);
3393 stripes_free_list_nodes(&stripes->horizontal_list, false);
3394 file_list_deinitialize(&stripes->selection_buf_old);
3395 file_list_deinitialize(&stripes->horizontal_list);
3396 }
3397 return NULL;
3398 }
3399
stripes_free(void * data)3400 static void stripes_free(void *data)
3401 {
3402 stripes_handle_t *stripes = (stripes_handle_t*)data;
3403
3404 if (stripes)
3405 {
3406 stripes_free_list_nodes(&stripes->selection_buf_old, false);
3407 stripes_free_list_nodes(&stripes->horizontal_list, false);
3408 file_list_deinitialize(&stripes->selection_buf_old);
3409 file_list_deinitialize(&stripes->horizontal_list);
3410
3411 video_coord_array_free(&stripes->raster_block.carr);
3412 video_coord_array_free(&stripes->raster_block2.carr);
3413
3414 if (!string_is_empty(stripes->box_message))
3415 free(stripes->box_message);
3416 if (!string_is_empty(stripes->thumbnail_system))
3417 free(stripes->thumbnail_system);
3418 if (!string_is_empty(stripes->thumbnail_content))
3419 free(stripes->thumbnail_content);
3420 if (!string_is_empty(stripes->savestate_thumbnail_file_path))
3421 free(stripes->savestate_thumbnail_file_path);
3422 if (!string_is_empty(stripes->thumbnail_file_path))
3423 free(stripes->thumbnail_file_path);
3424 if (!string_is_empty(stripes->left_thumbnail_file_path))
3425 free(stripes->left_thumbnail_file_path);
3426 if (!string_is_empty(stripes->bg_file_path))
3427 free(stripes->bg_file_path);
3428 }
3429
3430 if (gfx_display_white_texture)
3431 video_driver_texture_unload(&gfx_display_white_texture);
3432
3433 font_driver_bind_block(NULL, NULL);
3434 }
3435
stripes_context_bg_destroy(stripes_handle_t * stripes)3436 static void stripes_context_bg_destroy(stripes_handle_t *stripes)
3437 {
3438 if (!stripes)
3439 return;
3440 video_driver_texture_unload(&stripes->textures.bg);
3441 video_driver_texture_unload(&gfx_display_white_texture);
3442 }
3443
stripes_load_image(void * userdata,void * data,enum menu_image_type type)3444 static bool stripes_load_image(void *userdata, void *data, enum menu_image_type type)
3445 {
3446 stripes_handle_t *stripes = (stripes_handle_t*)userdata;
3447
3448 if (!stripes || !data)
3449 return false;
3450
3451 switch (type)
3452 {
3453 case MENU_IMAGE_NONE:
3454 break;
3455 case MENU_IMAGE_WALLPAPER:
3456 stripes_context_bg_destroy(stripes);
3457 video_driver_texture_unload(&stripes->textures.bg);
3458 video_driver_texture_load(data,
3459 TEXTURE_FILTER_MIPMAP_LINEAR,
3460 &stripes->textures.bg);
3461 if (gfx_display_white_texture)
3462 video_driver_texture_unload(&gfx_display_white_texture);
3463 gfx_display_init_white_texture(gfx_display_white_texture);
3464 break;
3465 case MENU_IMAGE_THUMBNAIL:
3466 {
3467 struct texture_image *img = (struct texture_image*)data;
3468 stripes->thumbnail_height = stripes->thumbnail_width
3469 * (float)img->height / (float)img->width;
3470 video_driver_texture_unload(&stripes->thumbnail);
3471 video_driver_texture_load(data,
3472 TEXTURE_FILTER_MIPMAP_LINEAR, &stripes->thumbnail);
3473 }
3474 break;
3475 case MENU_IMAGE_LEFT_THUMBNAIL:
3476 {
3477 struct texture_image *img = (struct texture_image*)data;
3478 stripes->left_thumbnail_height = stripes->left_thumbnail_width
3479 * (float)img->height / (float)img->width;
3480 video_driver_texture_unload(&stripes->left_thumbnail);
3481 video_driver_texture_load(data,
3482 TEXTURE_FILTER_MIPMAP_LINEAR, &stripes->left_thumbnail);
3483 }
3484 break;
3485 case MENU_IMAGE_SAVESTATE_THUMBNAIL:
3486 {
3487 struct texture_image *img = (struct texture_image*)data;
3488 stripes->savestate_thumbnail_height = stripes->savestate_thumbnail_width
3489 * (float)img->height / (float)img->width;
3490 video_driver_texture_unload(&stripes->savestate_thumbnail);
3491 video_driver_texture_load(data,
3492 TEXTURE_FILTER_MIPMAP_LINEAR, &stripes->savestate_thumbnail);
3493 }
3494 break;
3495 }
3496
3497 return true;
3498 }
3499
stripes_texture_path(unsigned id)3500 static const char *stripes_texture_path(unsigned id)
3501 {
3502 switch (id)
3503 {
3504 case STRIPES_TEXTURE_MAIN_MENU:
3505 #if defined(HAVE_LAKKA)
3506 return "lakka.png";
3507 #else
3508 return "retroarch.png";
3509 #endif
3510 case STRIPES_TEXTURE_SETTINGS:
3511 return "settings.png";
3512 case STRIPES_TEXTURE_HISTORY:
3513 return "history.png";
3514 case STRIPES_TEXTURE_FAVORITES:
3515 return "favorites.png";
3516 case STRIPES_TEXTURE_ADD_FAVORITE:
3517 return "add-favorite.png";
3518 case STRIPES_TEXTURE_MUSICS:
3519 return "musics.png";
3520 #ifdef HAVE_FFMPEG
3521 case STRIPES_TEXTURE_MOVIES:
3522 return "movies.png";
3523 #endif
3524 #ifdef HAVE_IMAGEVIEWER
3525 case STRIPES_TEXTURE_IMAGES:
3526 return "images.png";
3527 #endif
3528 case STRIPES_TEXTURE_SETTING:
3529 return "setting.png";
3530 case STRIPES_TEXTURE_SUBSETTING:
3531 return "subsetting.png";
3532 case STRIPES_TEXTURE_ARROW:
3533 return "arrow.png";
3534 case STRIPES_TEXTURE_RUN:
3535 return "run.png";
3536 case STRIPES_TEXTURE_CLOSE:
3537 return "close.png";
3538 case STRIPES_TEXTURE_RESUME:
3539 return "resume.png";
3540 case STRIPES_TEXTURE_CLOCK:
3541 return "clock.png";
3542 case STRIPES_TEXTURE_BATTERY_FULL:
3543 return "battery-full.png";
3544 case STRIPES_TEXTURE_BATTERY_CHARGING:
3545 return "battery-charging.png";
3546 case STRIPES_TEXTURE_POINTER:
3547 return "pointer.png";
3548 case STRIPES_TEXTURE_SAVESTATE:
3549 return "savestate.png";
3550 case STRIPES_TEXTURE_LOADSTATE:
3551 return "loadstate.png";
3552 case STRIPES_TEXTURE_UNDO:
3553 return "undo.png";
3554 case STRIPES_TEXTURE_CORE_INFO:
3555 return "core-infos.png";
3556 case STRIPES_TEXTURE_BLUETOOTH:
3557 return "bluetooth.png";
3558 case STRIPES_TEXTURE_WIFI:
3559 return "wifi.png";
3560 case STRIPES_TEXTURE_CORE_OPTIONS:
3561 return "core-options.png";
3562 case STRIPES_TEXTURE_INPUT_REMAPPING_OPTIONS:
3563 return "core-input-remapping-options.png";
3564 case STRIPES_TEXTURE_CHEAT_OPTIONS:
3565 return "core-cheat-options.png";
3566 case STRIPES_TEXTURE_DISK_OPTIONS:
3567 return "core-disk-options.png";
3568 case STRIPES_TEXTURE_SHADER_OPTIONS:
3569 return "core-shader-options.png";
3570 case STRIPES_TEXTURE_ACHIEVEMENT_LIST:
3571 return "achievement-list.png";
3572 case STRIPES_TEXTURE_SCREENSHOT:
3573 return "screenshot.png";
3574 case STRIPES_TEXTURE_RELOAD:
3575 return "reload.png";
3576 case STRIPES_TEXTURE_RENAME:
3577 return "rename.png";
3578 case STRIPES_TEXTURE_FILE:
3579 return "file.png";
3580 case STRIPES_TEXTURE_FOLDER:
3581 return "folder.png";
3582 case STRIPES_TEXTURE_ZIP:
3583 return "zip.png";
3584 case STRIPES_TEXTURE_MUSIC:
3585 return "music.png";
3586 case STRIPES_TEXTURE_FAVORITE:
3587 return "favorites-content.png";
3588 case STRIPES_TEXTURE_IMAGE:
3589 return "image.png";
3590 case STRIPES_TEXTURE_MOVIE:
3591 return "movie.png";
3592 case STRIPES_TEXTURE_CORE:
3593 return "core.png";
3594 case STRIPES_TEXTURE_RDB:
3595 return "database.png";
3596 case STRIPES_TEXTURE_CURSOR:
3597 return "cursor.png";
3598 case STRIPES_TEXTURE_SWITCH_ON:
3599 return "on.png";
3600 case STRIPES_TEXTURE_SWITCH_OFF:
3601 return "off.png";
3602 case STRIPES_TEXTURE_ADD:
3603 return "add.png";
3604 #ifdef HAVE_NETWORKING
3605 case STRIPES_TEXTURE_NETPLAY:
3606 return "netplay.png";
3607 case STRIPES_TEXTURE_ROOM:
3608 return "room.png";
3609 /* stub these out until we have the icons
3610 case STRIPES_TEXTURE_ROOM_LAN:
3611 return "room_lan.png";
3612 case STRIPES_TEXTURE_ROOM_MITM:
3613 return "room_mitm.png";
3614 */
3615 #endif
3616 case STRIPES_TEXTURE_KEY:
3617 return "key.png";
3618 case STRIPES_TEXTURE_KEY_HOVER:
3619 return "key-hover.png";
3620 case STRIPES_TEXTURE_DIALOG_SLICE:
3621 return "dialog-slice.png";
3622
3623 }
3624
3625 return NULL;
3626 }
3627
stripes_context_reset_textures(stripes_handle_t * stripes,const char * iconpath)3628 static void stripes_context_reset_textures(
3629 stripes_handle_t *stripes, const char *iconpath)
3630 {
3631 unsigned i;
3632
3633 for (i = 0; i < STRIPES_TEXTURE_LAST; i++)
3634 gfx_display_reset_textures_list(stripes_texture_path(i), iconpath, &stripes->textures.list[i], TEXTURE_FILTER_MIPMAP_LINEAR, NULL, NULL);
3635
3636 if (gfx_display_white_texture)
3637 video_driver_texture_unload(&gfx_display_white_texture);
3638 gfx_display_init_white_texture(gfx_display_white_texture);
3639
3640 stripes->main_menu_node.icon = stripes->textures.list[STRIPES_TEXTURE_MAIN_MENU];
3641 stripes->main_menu_node.alpha = stripes->categories_active_alpha;
3642 stripes->main_menu_node.zoom = stripes->categories_active_zoom;
3643
3644 stripes->settings_tab_node.icon = stripes->textures.list[STRIPES_TEXTURE_SETTINGS];
3645 stripes->settings_tab_node.alpha = stripes->categories_active_alpha;
3646 stripes->settings_tab_node.zoom = stripes->categories_active_zoom;
3647
3648 stripes->history_tab_node.icon = stripes->textures.list[STRIPES_TEXTURE_HISTORY];
3649 stripes->history_tab_node.alpha = stripes->categories_active_alpha;
3650 stripes->history_tab_node.zoom = stripes->categories_active_zoom;
3651
3652 stripes->favorites_tab_node.icon = stripes->textures.list[STRIPES_TEXTURE_FAVORITES];
3653 stripes->favorites_tab_node.alpha = stripes->categories_active_alpha;
3654 stripes->favorites_tab_node.zoom = stripes->categories_active_zoom;
3655
3656 stripes->music_tab_node.icon = stripes->textures.list[STRIPES_TEXTURE_MUSICS];
3657 stripes->music_tab_node.alpha = stripes->categories_active_alpha;
3658 stripes->music_tab_node.zoom = stripes->categories_active_zoom;
3659
3660 #ifdef HAVE_FFMPEG
3661 stripes->video_tab_node.icon = stripes->textures.list[STRIPES_TEXTURE_MOVIES];
3662 stripes->video_tab_node.alpha = stripes->categories_active_alpha;
3663 stripes->video_tab_node.zoom = stripes->categories_active_zoom;
3664 #endif
3665
3666 #ifdef HAVE_IMAGEVIEWER
3667 stripes->images_tab_node.icon = stripes->textures.list[STRIPES_TEXTURE_IMAGES];
3668 stripes->images_tab_node.alpha = stripes->categories_active_alpha;
3669 stripes->images_tab_node.zoom = stripes->categories_active_zoom;
3670 #endif
3671
3672 stripes->add_tab_node.icon = stripes->textures.list[STRIPES_TEXTURE_ADD];
3673 stripes->add_tab_node.alpha = stripes->categories_active_alpha;
3674 stripes->add_tab_node.zoom = stripes->categories_active_zoom;
3675
3676 #ifdef HAVE_NETWORKING
3677 stripes->netplay_tab_node.icon = stripes->textures.list[STRIPES_TEXTURE_NETPLAY];
3678 stripes->netplay_tab_node.alpha = stripes->categories_active_alpha;
3679 stripes->netplay_tab_node.zoom = stripes->categories_active_zoom;
3680 #endif
3681 }
3682
stripes_context_reset_background(const char * iconpath)3683 static void stripes_context_reset_background(const char *iconpath)
3684 {
3685 char path[PATH_MAX_LENGTH];
3686 settings_t *settings = config_get_ptr();
3687 const char *path_menu_wp = settings->paths.path_menu_wallpaper;
3688
3689 path[0] = '\0';
3690
3691 if (!string_is_empty(path_menu_wp))
3692 strlcpy(path, path_menu_wp, sizeof(path));
3693 else if (!string_is_empty(iconpath))
3694 fill_pathname_join(path, iconpath, "bg.png", sizeof(path));
3695
3696 if (path_is_valid(path))
3697 task_push_image_load(path,
3698 video_driver_supports_rgba(), 0,
3699 menu_display_handle_wallpaper_upload, NULL);
3700 }
3701
stripes_context_reset(void * data,bool is_threaded)3702 static void stripes_context_reset(void *data, bool is_threaded)
3703 {
3704 stripes_handle_t *stripes = (stripes_handle_t*)data;
3705
3706 if (stripes)
3707 {
3708 char iconpath [PATH_MAX_LENGTH];
3709 char bg_file_path[PATH_MAX_LENGTH];
3710 iconpath[0] = bg_file_path[0] = '\0';
3711
3712 fill_pathname_application_special(bg_file_path,
3713 sizeof(bg_file_path), APPLICATION_SPECIAL_DIRECTORY_ASSETS_XMB_BG);
3714
3715 if (!string_is_empty(bg_file_path))
3716 {
3717 if (!string_is_empty(stripes->bg_file_path))
3718 free(stripes->bg_file_path);
3719 stripes->bg_file_path = strdup(bg_file_path);
3720 }
3721
3722 fill_pathname_application_special(iconpath, sizeof(iconpath),
3723 APPLICATION_SPECIAL_DIRECTORY_ASSETS_XMB_ICONS);
3724
3725 stripes_layout(stripes);
3726 stripes->font = gfx_display_font(p_disp, APPLICATION_SPECIAL_DIRECTORY_ASSETS_XMB_FONT,
3727 stripes->font_size,
3728 is_threaded);
3729 stripes->font2 = gfx_display_font(p_disp, APPLICATION_SPECIAL_DIRECTORY_ASSETS_XMB_FONT,
3730 stripes->font2_size,
3731 is_threaded);
3732 stripes_context_reset_textures(stripes, iconpath);
3733 stripes_context_reset_background(iconpath);
3734 stripes_context_reset_horizontal_list(stripes);
3735
3736 if (!string_is_equal(stripes_thumbnails_ident('R'),
3737 msg_hash_to_str(MENU_ENUM_LABEL_VALUE_OFF)))
3738 stripes_update_thumbnail_image(stripes);
3739 if (!string_is_equal(stripes_thumbnails_ident('R'),
3740 msg_hash_to_str(MENU_ENUM_LABEL_VALUE_OFF)))
3741 stripes_update_thumbnail_image(stripes);
3742 stripes_update_savestate_thumbnail_image(stripes);
3743 }
3744 video_driver_monitor_reset();
3745 }
3746
stripes_navigation_clear(void * data,bool pending_push)3747 static void stripes_navigation_clear(void *data, bool pending_push)
3748 {
3749 stripes_handle_t *stripes = (stripes_handle_t*)data;
3750 if (!pending_push)
3751 stripes_selection_pointer_changed(stripes, true);
3752 }
3753
stripes_navigation_pointer_changed(void * data)3754 static void stripes_navigation_pointer_changed(void *data)
3755 {
3756 stripes_handle_t *stripes = (stripes_handle_t*)data;
3757 stripes_selection_pointer_changed(stripes, true);
3758 }
3759
stripes_navigation_set(void * data,bool scroll)3760 static void stripes_navigation_set(void *data, bool scroll)
3761 {
3762 stripes_handle_t *stripes = (stripes_handle_t*)data;
3763 stripes_selection_pointer_changed(stripes, true);
3764 }
3765
stripes_navigation_alphabet(void * data,size_t * unused)3766 static void stripes_navigation_alphabet(void *data, size_t *unused)
3767 {
3768 stripes_handle_t *stripes = (stripes_handle_t*)data;
3769 stripes_selection_pointer_changed(stripes, true);
3770 }
3771
stripes_list_insert(void * userdata,file_list_t * list,const char * path,const char * fullpath,const char * unused,size_t list_size,unsigned entry_type)3772 static void stripes_list_insert(void *userdata,
3773 file_list_t *list,
3774 const char *path,
3775 const char *fullpath,
3776 const char *unused,
3777 size_t list_size,
3778 unsigned entry_type)
3779 {
3780 int current = 0;
3781 int i = (int)list_size;
3782 stripes_node_t *node = NULL;
3783 stripes_handle_t *stripes = (stripes_handle_t*)userdata;
3784 size_t selection = menu_navigation_get_selection();
3785
3786 if (!stripes || !list)
3787 return;
3788
3789 node = (stripes_node_t*)file_list_get_userdata_at_offset(list, i);
3790
3791 if (!node)
3792 node = stripes_alloc_node();
3793
3794 if (!node)
3795 {
3796 RARCH_ERR("XMB node could not be allocated.\n");
3797 return;
3798 }
3799
3800 current = (int)selection;
3801
3802 if (!string_is_empty(fullpath))
3803 {
3804 if (node->fullpath)
3805 free(node->fullpath);
3806
3807 node->fullpath = strdup(fullpath);
3808 }
3809
3810 node->alpha = stripes->items_passive_alpha;
3811 node->zoom = stripes->items_passive_zoom;
3812 node->label_alpha = node->alpha;
3813 node->y = stripes_item_y(stripes, i, current);
3814 node->x = 0;
3815
3816 if (i == current)
3817 {
3818 node->alpha = stripes->items_active_alpha;
3819 node->label_alpha = stripes->items_active_alpha;
3820 node->zoom = stripes->items_active_alpha;
3821 }
3822
3823 list->list[i].userdata = node;
3824 }
3825
stripes_list_clear(file_list_t * list)3826 static void stripes_list_clear(file_list_t *list)
3827 {
3828 uintptr_t tag = (uintptr_t)list;
3829
3830 gfx_animation_kill_by_tag(&tag);
3831
3832 stripes_free_list_nodes(list, false);
3833 }
3834
stripes_list_free(file_list_t * list,size_t a,size_t b)3835 static void stripes_list_free(file_list_t *list, size_t a, size_t b)
3836 {
3837 stripes_list_clear(list);
3838 }
3839
stripes_list_deep_copy(const file_list_t * src,file_list_t * dst,size_t first,size_t last)3840 static void stripes_list_deep_copy(const file_list_t *src, file_list_t *dst,
3841 size_t first, size_t last)
3842 {
3843 size_t i, j = 0;
3844 uintptr_t tag = (uintptr_t)dst;
3845
3846 gfx_animation_kill_by_tag(&tag);
3847
3848 stripes_free_list_nodes(dst, true);
3849
3850 file_list_clear(dst);
3851 file_list_reserve(dst, (last + 1) - first);
3852
3853 for (i = first; i <= last; ++i)
3854 {
3855 struct item_file *d = &dst->list[j];
3856 struct item_file *s = &src->list[i];
3857
3858 void *src_udata = s->userdata;
3859 void *src_adata = s->actiondata;
3860
3861 *d = *s;
3862 d->alt = string_is_empty(d->alt) ? NULL : strdup(d->alt);
3863 d->path = string_is_empty(d->path) ? NULL : strdup(d->path);
3864 d->label = string_is_empty(d->label) ? NULL : strdup(d->label);
3865
3866 if (src_udata)
3867 dst->list[j].userdata = (void*)stripes_copy_node((const stripes_node_t*)src_udata);
3868
3869 if (src_adata)
3870 {
3871 void *data = malloc(sizeof(menu_file_list_cbs_t));
3872 memcpy(data, src_adata, sizeof(menu_file_list_cbs_t));
3873 dst->list[j].actiondata = data;
3874 }
3875
3876 ++j;
3877 }
3878
3879 dst->size = j;
3880 }
3881
stripes_list_cache(void * data,enum menu_list_type type,unsigned action)3882 static void stripes_list_cache(void *data, enum menu_list_type type, unsigned action)
3883 {
3884 size_t stack_size, list_size;
3885 stripes_handle_t *stripes = (stripes_handle_t*)data;
3886 file_list_t *menu_stack = menu_entries_get_menu_stack_ptr(0);
3887 file_list_t *selection_buf = menu_entries_get_selection_buf_ptr(0);
3888 size_t selection = menu_navigation_get_selection();
3889 settings_t *settings = config_get_ptr();
3890
3891 if (!stripes)
3892 return;
3893
3894 /* Check whether to enable the horizontal animation. */
3895 if (settings->bools.menu_horizontal_animation)
3896 {
3897 unsigned first = 0, last = 0;
3898 unsigned height = 0;
3899 video_driver_get_size(NULL, &height);
3900
3901 /* FIXME: this shouldn't be happening at all */
3902 if (selection >= selection_buf->size)
3903 selection = selection_buf->size ? selection_buf->size - 1 : 0;
3904
3905 stripes->selection_ptr_old = selection;
3906
3907 stripes_calculate_visible_range(stripes, height, selection_buf->size,
3908 stripes->selection_ptr_old, &first, &last);
3909
3910 stripes_list_deep_copy(selection_buf,
3911 &stripes->selection_buf_old, first, last);
3912
3913 stripes->selection_ptr_old -= first;
3914 last -= first;
3915 first = 0;
3916 }
3917 else
3918 stripes->selection_ptr_old = 0;
3919
3920 list_size = stripes_list_get_size(stripes, MENU_LIST_HORIZONTAL)
3921 + stripes->system_tab_end;
3922
3923 switch (type)
3924 {
3925 case MENU_LIST_PLAIN:
3926 break;
3927 case MENU_LIST_HORIZONTAL:
3928 stripes->categories_selection_ptr_old = stripes->categories_selection_ptr;
3929
3930 switch (action)
3931 {
3932 case MENU_ACTION_LEFT:
3933 if (stripes->categories_selection_ptr == 0)
3934 {
3935 stripes->categories_selection_ptr = list_size;
3936 stripes->categories_active_idx = (unsigned)(list_size - 1);
3937 }
3938 else
3939 stripes->categories_selection_ptr--;
3940 break;
3941 default:
3942 if (stripes->categories_selection_ptr == list_size)
3943 {
3944 stripes->categories_selection_ptr = 0;
3945 stripes->categories_active_idx = 1;
3946 }
3947 else
3948 stripes->categories_selection_ptr++;
3949 break;
3950 }
3951
3952 stack_size = menu_stack->size;
3953
3954 if (menu_stack->list[stack_size - 1].label)
3955 free(menu_stack->list[stack_size - 1].label);
3956 menu_stack->list[stack_size - 1].label = NULL;
3957
3958 switch (stripes_get_system_tab(stripes, (unsigned)stripes->categories_selection_ptr))
3959 {
3960 case STRIPES_SYSTEM_TAB_MAIN:
3961 menu_stack->list[stack_size - 1].label =
3962 strdup(msg_hash_to_str(MENU_ENUM_LABEL_MAIN_MENU));
3963 menu_stack->list[stack_size - 1].type =
3964 MENU_SETTINGS;
3965 break;
3966 case STRIPES_SYSTEM_TAB_SETTINGS:
3967 menu_stack->list[stack_size - 1].label =
3968 strdup(msg_hash_to_str(MENU_ENUM_LABEL_SETTINGS_TAB));
3969 menu_stack->list[stack_size - 1].type =
3970 MENU_SETTINGS_TAB;
3971 break;
3972 #ifdef HAVE_IMAGEVIEWER
3973 case STRIPES_SYSTEM_TAB_IMAGES:
3974 menu_stack->list[stack_size - 1].label =
3975 strdup(msg_hash_to_str(MENU_ENUM_LABEL_IMAGES_TAB));
3976 menu_stack->list[stack_size - 1].type =
3977 MENU_IMAGES_TAB;
3978 break;
3979 #endif
3980 case STRIPES_SYSTEM_TAB_MUSIC:
3981 menu_stack->list[stack_size - 1].label =
3982 strdup(msg_hash_to_str(MENU_ENUM_LABEL_MUSIC_TAB));
3983 menu_stack->list[stack_size - 1].type =
3984 MENU_MUSIC_TAB;
3985 break;
3986 #ifdef HAVE_FFMPEG
3987 case STRIPES_SYSTEM_TAB_VIDEO:
3988 menu_stack->list[stack_size - 1].label =
3989 strdup(msg_hash_to_str(MENU_ENUM_LABEL_VIDEO_TAB));
3990 menu_stack->list[stack_size - 1].type =
3991 MENU_VIDEO_TAB;
3992 break;
3993 #endif
3994 case STRIPES_SYSTEM_TAB_HISTORY:
3995 menu_stack->list[stack_size - 1].label =
3996 strdup(msg_hash_to_str(MENU_ENUM_LABEL_HISTORY_TAB));
3997 menu_stack->list[stack_size - 1].type =
3998 MENU_HISTORY_TAB;
3999 break;
4000 case STRIPES_SYSTEM_TAB_FAVORITES:
4001 menu_stack->list[stack_size - 1].label =
4002 strdup(msg_hash_to_str(MENU_ENUM_LABEL_FAVORITES_TAB));
4003 menu_stack->list[stack_size - 1].type =
4004 MENU_FAVORITES_TAB;
4005 break;
4006 #ifdef HAVE_NETWORKING
4007 case STRIPES_SYSTEM_TAB_NETPLAY:
4008 menu_stack->list[stack_size - 1].label =
4009 strdup(msg_hash_to_str(MENU_ENUM_LABEL_NETPLAY_TAB));
4010 menu_stack->list[stack_size - 1].type =
4011 MENU_NETPLAY_TAB;
4012 break;
4013 #endif
4014 case STRIPES_SYSTEM_TAB_ADD:
4015 menu_stack->list[stack_size - 1].label =
4016 strdup(msg_hash_to_str(MENU_ENUM_LABEL_ADD_TAB));
4017 menu_stack->list[stack_size - 1].type =
4018 MENU_ADD_TAB;
4019 break;
4020 default:
4021 menu_stack->list[stack_size - 1].label =
4022 strdup(msg_hash_to_str(MENU_ENUM_LABEL_HORIZONTAL_MENU));
4023 menu_stack->list[stack_size - 1].type =
4024 MENU_SETTING_HORIZONTAL_MENU;
4025 break;
4026 }
4027 break;
4028 default:
4029 break;
4030 }
4031 }
4032
stripes_context_destroy(void * data)4033 static void stripes_context_destroy(void *data)
4034 {
4035 unsigned i;
4036 stripes_handle_t *stripes = (stripes_handle_t*)data;
4037
4038 if (!stripes)
4039 return;
4040
4041 for (i = 0; i < STRIPES_TEXTURE_LAST; i++)
4042 video_driver_texture_unload(&stripes->textures.list[i]);
4043
4044 video_driver_texture_unload(&stripes->thumbnail);
4045 video_driver_texture_unload(&stripes->left_thumbnail);
4046 video_driver_texture_unload(&stripes->savestate_thumbnail);
4047
4048 stripes_context_destroy_horizontal_list(stripes);
4049 stripes_context_bg_destroy(stripes);
4050
4051 gfx_display_font_free(stripes->font);
4052 gfx_display_font_free(stripes->font2);
4053
4054 stripes->font = NULL;
4055 stripes->font2 = NULL;
4056 }
4057
stripes_toggle(void * userdata,bool menu_on)4058 static void stripes_toggle(void *userdata, bool menu_on)
4059 {
4060 gfx_animation_ctx_entry_t entry;
4061 bool tmp = false;
4062 stripes_handle_t *stripes = (stripes_handle_t*)userdata;
4063
4064 if (!stripes)
4065 return;
4066
4067 stripes->depth = (int)stripes_list_get_size(stripes, MENU_LIST_PLAIN);
4068
4069 if (!menu_on)
4070 {
4071 stripes->alpha = 0;
4072 return;
4073 }
4074
4075 entry.duration = STRIPES_DELAY * 2;
4076 entry.target_value = 1.0f;
4077 entry.subject = &stripes->alpha;
4078 entry.easing_enum = EASING_OUT_QUAD;
4079 /* TODO/FIXME - integer conversion resulted in change of sign */
4080 entry.tag = -1;
4081 entry.cb = NULL;
4082
4083 gfx_animation_push(&entry);
4084
4085 tmp = !menu_entries_ctl(MENU_ENTRIES_CTL_NEEDS_REFRESH, NULL);
4086
4087 if (tmp)
4088 menu_driver_ctl(RARCH_MENU_CTL_SET_PREVENT_POPULATE, NULL);
4089 else
4090 menu_driver_ctl(RARCH_MENU_CTL_UNSET_PREVENT_POPULATE, NULL);
4091
4092 stripes_toggle_horizontal_list(stripes);
4093 }
4094
stripes_deferred_push_content_actions(menu_displaylist_info_t * info)4095 static int stripes_deferred_push_content_actions(menu_displaylist_info_t *info)
4096 {
4097 settings_t *settings = config_get_ptr();
4098 if (!menu_displaylist_ctl(
4099 DISPLAYLIST_HORIZONTAL_CONTENT_ACTIONS, info, settings))
4100 return -1;
4101 menu_displaylist_process(info);
4102 menu_displaylist_info_free(info);
4103 return 0;
4104 }
4105
stripes_list_bind_init_compare_label(menu_file_list_cbs_t * cbs)4106 static int stripes_list_bind_init_compare_label(menu_file_list_cbs_t *cbs)
4107 {
4108 if (cbs && cbs->enum_idx != MSG_UNKNOWN)
4109 {
4110 switch (cbs->enum_idx)
4111 {
4112 case MENU_ENUM_LABEL_CONTENT_ACTIONS:
4113 cbs->action_deferred_push = stripes_deferred_push_content_actions;
4114 break;
4115 default:
4116 return -1;
4117 }
4118 }
4119
4120 return 0;
4121 }
4122
stripes_list_bind_init(menu_file_list_cbs_t * cbs,const char * path,const char * label,unsigned type,size_t idx)4123 static int stripes_list_bind_init(menu_file_list_cbs_t *cbs,
4124 const char *path, const char *label, unsigned type, size_t idx)
4125 {
4126 if (stripes_list_bind_init_compare_label(cbs) == 0)
4127 return 0;
4128
4129 return -1;
4130 }
4131
stripes_list_push(void * data,void * userdata,menu_displaylist_info_t * info,unsigned type)4132 static int stripes_list_push(void *data, void *userdata,
4133 menu_displaylist_info_t *info, unsigned type)
4134 {
4135 int ret = -1;
4136 int i = 0;
4137 core_info_list_t *list = NULL;
4138
4139 switch (type)
4140 {
4141 case DISPLAYLIST_LOAD_CONTENT_LIST:
4142 {
4143 settings_t *settings = config_get_ptr();
4144
4145 menu_entries_ctl(MENU_ENTRIES_CTL_CLEAR, info->list);
4146
4147 menu_entries_append_enum(info->list,
4148 msg_hash_to_str(MENU_ENUM_LABEL_VALUE_FAVORITES),
4149 msg_hash_to_str(MENU_ENUM_LABEL_FAVORITES),
4150 MENU_ENUM_LABEL_FAVORITES,
4151 MENU_SETTING_ACTION_FAVORITES_DIR, 0, 0);
4152
4153 core_info_get_list(&list);
4154 if (list->info_count > 0)
4155 {
4156 menu_entries_append_enum(info->list,
4157 msg_hash_to_str(MENU_ENUM_LABEL_VALUE_DOWNLOADED_FILE_DETECT_CORE_LIST),
4158 msg_hash_to_str(MENU_ENUM_LABEL_DOWNLOADED_FILE_DETECT_CORE_LIST),
4159 MENU_ENUM_LABEL_DOWNLOADED_FILE_DETECT_CORE_LIST,
4160 MENU_SETTING_ACTION, 0, 0);
4161 }
4162
4163 if (settings->bools.menu_content_show_playlists)
4164 menu_entries_append_enum(info->list,
4165 msg_hash_to_str(MENU_ENUM_LABEL_VALUE_PLAYLISTS_TAB),
4166 msg_hash_to_str(MENU_ENUM_LABEL_PLAYLISTS_TAB),
4167 MENU_ENUM_LABEL_PLAYLISTS_TAB,
4168 MENU_SETTING_ACTION, 0, 0);
4169
4170 if (frontend_driver_parse_drive_list(info->list, true) != 0)
4171 menu_entries_append_enum(info->list, "/",
4172 msg_hash_to_str(MENU_ENUM_LABEL_FILE_DETECT_CORE_LIST_PUSH_DIR),
4173 MENU_ENUM_LABEL_FILE_DETECT_CORE_LIST_PUSH_DIR,
4174 MENU_SETTING_ACTION, 0, 0);
4175
4176 if (!settings->bools.kiosk_mode_enable)
4177 {
4178 menu_entries_append_enum(info->list,
4179 msg_hash_to_str(MENU_ENUM_LABEL_VALUE_MENU_FILE_BROWSER_SETTINGS),
4180 msg_hash_to_str(MENU_ENUM_LABEL_MENU_FILE_BROWSER_SETTINGS),
4181 MENU_ENUM_LABEL_MENU_FILE_BROWSER_SETTINGS,
4182 MENU_SETTING_ACTION, 0, 0);
4183 }
4184
4185 info->need_push = true;
4186 info->need_refresh = true;
4187 ret = 0;
4188 }
4189 break;
4190 case DISPLAYLIST_MAIN_MENU:
4191 {
4192 settings_t *settings = config_get_ptr();
4193 rarch_system_info_t *system = runloop_get_system_info();
4194 menu_entries_ctl(MENU_ENTRIES_CTL_CLEAR, info->list);
4195
4196 entry.data = menu;
4197 entry.info = info;
4198 entry.parse_type = PARSE_ACTION;
4199 entry.add_empty_entry = false;
4200
4201 if (rarch_ctl(RARCH_CTL_CORE_IS_RUNNING, NULL))
4202 {
4203 if (!rarch_ctl(RARCH_CTL_IS_DUMMY_CORE, NULL))
4204 {
4205 MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(
4206 info->list,
4207 MENU_ENUM_LABEL_CONTENT_SETTINGS,
4208 PARSE_ACTION,
4209 false);
4210 }
4211 }
4212 else
4213 {
4214 if (system->load_no_content)
4215 {
4216 MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(
4217 info->list,
4218 MENU_ENUM_LABEL_START_CORE,
4219 PARSE_ACTION,
4220 false);
4221 }
4222
4223 #ifndef HAVE_DYNAMIC
4224 if (frontend_driver_has_fork())
4225 #endif
4226 {
4227 if (settings->bools.menu_show_load_core)
4228 {
4229 MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(
4230 info->list,
4231 MENU_ENUM_LABEL_CORE_LIST,
4232 PARSE_ACTION,
4233 false);
4234 }
4235 }
4236 }
4237
4238 if (settings->bools.menu_show_load_content)
4239 {
4240 MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(
4241 info->list,
4242 MENU_ENUM_LABEL_LOAD_CONTENT_LIST,
4243 PARSE_ACTION,
4244 false);
4245
4246 if (menu_displaylist_has_subsystems())
4247 {
4248 MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(
4249 info->list,
4250 MENU_ENUM_LABEL_SUBSYSTEM_SETTINGS,
4251 PARSE_ACTION,
4252 false);
4253 }
4254 }
4255
4256 MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(
4257 info->list,
4258 MENU_ENUM_LABEL_ADD_CONTENT_LIST,
4259 PARSE_ACTION,
4260 false);
4261 #if defined(HAVE_NETWORKING)
4262 {
4263 settings_t *settings = config_get_ptr();
4264 if (settings->bools.menu_show_online_updater && !settings->bools.kiosk_mode_enable)
4265 {
4266 MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(
4267 info->list,
4268 MENU_ENUM_LABEL_ONLINE_UPDATER,
4269 PARSE_ACTION,
4270 false);
4271 }
4272 }
4273 #endif
4274 if (!settings->bools.menu_content_show_settings && !string_is_empty(settings->paths.menu_content_show_settings_password))
4275 {
4276 MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(
4277 info->list,
4278 MENU_ENUM_LABEL_XMB_MAIN_MENU_ENABLE_SETTINGS,
4279 PARSE_ACTION,
4280 false);
4281 }
4282
4283 if (settings->bools.kiosk_mode_enable && !string_is_empty(settings->paths.kiosk_mode_password))
4284 {
4285 MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(
4286 info->list,
4287 MENU_ENUM_LABEL_MENU_DISABLE_KIOSK_MODE,
4288 PARSE_ACTION,
4289 false);
4290 }
4291
4292 if (settings->bools.menu_show_information)
4293 {
4294 MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(
4295 info->list,
4296 MENU_ENUM_LABEL_INFORMATION_LIST,
4297 PARSE_ACTION,
4298 false);
4299 }
4300
4301 #ifndef HAVE_DYNAMIC
4302 if (settings->bools.menu_show_restart_retroarch)
4303 {
4304 MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(
4305 info->list,
4306 MENU_ENUM_LABEL_RESTART_RETROARCH,
4307 PARSE_ACTION,
4308 false);
4309 }
4310 #endif
4311
4312 if (settings->bools.menu_show_configurations && !settings->bools.kiosk_mode_enable)
4313 {
4314 MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(
4315 info->list,
4316 MENU_ENUM_LABEL_CONFIGURATIONS_LIST,
4317 PARSE_ACTION,
4318 false);
4319 }
4320
4321 if (settings->bools.menu_show_help)
4322 {
4323 MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(
4324 info->list,
4325 MENU_ENUM_LABEL_HELP_LIST,
4326 PARSE_ACTION,
4327 false);
4328 }
4329
4330 #if !defined(IOS)
4331 if (settings->bools.menu_show_quit_retroarch)
4332 {
4333 MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(
4334 info->list,
4335 MENU_ENUM_LABEL_QUIT_RETROARCH,
4336 PARSE_ACTION,
4337 false);
4338 }
4339 #endif
4340
4341 if (settings->bools.menu_show_reboot)
4342 {
4343 MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(
4344 info->list,
4345 MENU_ENUM_LABEL_REBOOT,
4346 PARSE_ACTION,
4347 false);
4348 }
4349
4350 MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(
4351 info->list,
4352 MENU_ENUM_LABEL_SHUTDOWN,
4353 PARSE_ACTION,
4354 false);
4355 info->need_push = true;
4356 ret = 0;
4357 }
4358 break;
4359 }
4360 return ret;
4361 }
4362
stripes_menu_init_list(void * data)4363 static bool stripes_menu_init_list(void *data)
4364 {
4365 menu_displaylist_info_t info;
4366 settings_t *settings = config_get_ptr();
4367
4368 file_list_t *menu_stack = menu_entries_get_menu_stack_ptr(0);
4369 file_list_t *selection_buf = menu_entries_get_selection_buf_ptr(0);
4370
4371 menu_displaylist_info_init(&info);
4372
4373 info.label = strdup(
4374 msg_hash_to_str(MENU_ENUM_LABEL_MAIN_MENU));
4375 info.exts = strdup("lpl");
4376 info.type_default = FILE_TYPE_PLAIN;
4377 info.enum_idx = MENU_ENUM_LABEL_MAIN_MENU;
4378
4379 menu_entries_append_enum(menu_stack, info.path,
4380 info.label,
4381 MENU_ENUM_LABEL_MAIN_MENU,
4382 info.type, info.flags, 0);
4383
4384 info.list = selection_buf;
4385
4386 if (!menu_displaylist_ctl(DISPLAYLIST_MAIN_MENU, &info, settings))
4387 goto error;
4388
4389 info.need_push = true;
4390
4391 if (!menu_displaylist_process(&info))
4392 goto error;
4393
4394 menu_displaylist_info_free(&info);
4395 return true;
4396
4397 error:
4398 menu_displaylist_info_free(&info);
4399 return false;
4400 }
4401
stripes_pointer_up(void * userdata,unsigned x,unsigned y,unsigned ptr,enum menu_input_pointer_gesture gesture,menu_file_list_cbs_t * cbs,menu_entry_t * entry,unsigned action)4402 static int stripes_pointer_up(void *userdata,
4403 unsigned x, unsigned y, unsigned ptr,
4404 enum menu_input_pointer_gesture gesture,
4405 menu_file_list_cbs_t *cbs,
4406 menu_entry_t *entry, unsigned action)
4407 {
4408 stripes_handle_t *stripes = (stripes_handle_t*)userdata;
4409 size_t selection = menu_navigation_get_selection();
4410
4411 switch (gesture)
4412 {
4413 case MENU_INPUT_GESTURE_TAP:
4414 case MENU_INPUT_GESTURE_SHORT_PRESS:
4415 {
4416 /* Normal pointer input */
4417 gfx_display_t *p_disp = disp_get_ptr();
4418 unsigned header_height = p_disp->header_height;
4419
4420 if (y < header_height)
4421 return (unsigned)generic_menu_entry_action(stripes,
4422 entry, selection, MENU_ACTION_CANCEL);
4423 else if (ptr <= (menu_entries_get_size() - 1))
4424 {
4425 if (ptr == selection && cbs && cbs->action_select)
4426 return (unsigned)generic_menu_entry_action(stripes,
4427 entry, selection, MENU_ACTION_SELECT);
4428
4429 menu_navigation_set_selection(ptr);
4430 stripes_navigation_set(stripes, false);
4431 }
4432 }
4433 break;
4434 case MENU_INPUT_GESTURE_LONG_PRESS:
4435 /* 'Reset to default' action */
4436 if ((ptr <= (menu_entries_get_size() - 1)) &&
4437 (ptr == selection))
4438 return generic_menu_entry_action(stripes,
4439 entry, selection, MENU_ACTION_START);
4440 break;
4441 default:
4442 /* Ignore input */
4443 break;
4444 }
4445
4446 return 0;
4447 }
4448
4449 menu_ctx_driver_t menu_ctx_stripes = {
4450 NULL,
4451 stripes_messagebox,
4452 stripes_render,
4453 stripes_frame,
4454 stripes_init,
4455 stripes_free,
4456 stripes_context_reset,
4457 stripes_context_destroy,
4458 stripes_populate_entries,
4459 stripes_toggle,
4460 stripes_navigation_clear,
4461 stripes_navigation_pointer_changed,
4462 stripes_navigation_pointer_changed,
4463 stripes_navigation_set,
4464 stripes_navigation_pointer_changed,
4465 stripes_navigation_alphabet,
4466 stripes_navigation_alphabet,
4467 stripes_menu_init_list,
4468 stripes_list_insert,
4469 NULL,
4470 stripes_list_free,
4471 stripes_list_clear,
4472 stripes_list_cache,
4473 stripes_list_push,
4474 stripes_list_get_selection,
4475 stripes_list_get_size,
4476 stripes_list_get_entry,
4477 NULL,
4478 stripes_list_bind_init,
4479 stripes_load_image,
4480 "stripes",
4481 stripes_environ,
4482 stripes_update_thumbnail_path,
4483 stripes_update_thumbnail_image,
4484 stripes_refresh_thumbnail_image,
4485 stripes_set_thumbnail_system,
4486 stripes_get_thumbnail_system,
4487 stripes_set_thumbnail_content,
4488 stripes_osk_ptr_at_pos,
4489 stripes_update_savestate_thumbnail_path,
4490 stripes_update_savestate_thumbnail_image,
4491 NULL, /* pointer_down */
4492 stripes_pointer_up, /* pointer_up */
4493 generic_menu_entry_action
4494 };
4495