1 #include "include/usbld.h"
2 #include "include/themes.h"
3 #include "include/util.h"
4 #include "include/gui.h"
5 #include "include/renderman.h"
6 #include "include/textures.h"
7 #include "include/ioman.h"
8 #include "include/fntsys.h"
9 #include "include/lang.h"
12 #define HINT_HEIGHT 32
13 #define DECORATOR_SIZE 20
17 static int screenWidth
;
18 static int screenHeight
;
19 static int guiThemeID
= 0;
21 static int nThemes
= 0;
22 static theme_file_t themes
[THM_MAX_FILES
];
23 static char **guiThemesNames
= NULL
;
25 #define TYPE_ATTRIBUTE_TEXT 0
26 #define TYPE_STATIC_TEXT 1
27 #define TYPE_ATTRIBUTE_IMAGE 2
28 #define TYPE_GAME_IMAGE 3
29 #define TYPE_STATIC_IMAGE 4
30 #define TYPE_BACKGROUND 5
31 #define TYPE_MENU_ICON 6
32 #define TYPE_MENU_TEXT 7
33 #define TYPE_ITEMS_LIST 8
34 #define TYPE_ITEM_ICON 9
35 #define TYPE_ITEM_COVER 10
36 #define TYPE_ITEM_TEXT 11
37 #define TYPE_HINT_TEXT 12
38 #define TYPE_INFO_HINT_TEXT 13
39 #define TYPE_LOADING_ICON 14
41 #define DISPLAY_ALWAYS 0
42 #define DISPLAY_DEFINED 1
43 #define DISPLAY_NEVER 2
45 #define SIZING_NONE -1
49 static char *elementsType
[] = {
67 // Common functions for Text ////////////////////////////////////////////////////////////////////////////////////////////////
69 static void endMutableText(theme_element_t
* elem
) {
70 mutable_text_t
* mutableText
= (mutable_text_t
*) elem
->extended
;
72 if (mutableText
->value
)
73 free(mutableText
->value
);
75 if (mutableText
->alias
)
76 free(mutableText
->alias
);
84 static mutable_text_t
* initMutableText(char* themePath
, config_set_t
* themeConfig
, theme_t
* theme
, char* name
, int type
, struct theme_element
* elem
,
85 char* value
, char* alias
, int displayMode
, int sizingMode
) {
87 mutable_text_t
* mutableText
= (mutable_text_t
*) malloc(sizeof(mutable_text_t
));
88 mutableText
->currentItemId
= -1;
89 mutableText
->currentValue
= NULL
;
90 mutableText
->alias
= NULL
;
94 snprintf(elemProp
, 64, "%s_display", name
);
95 configGetInt(themeConfig
, elemProp
, &displayMode
);
96 mutableText
->displayMode
= displayMode
;
98 int length
= strlen(value
) + 1;
99 mutableText
->value
= (char*) malloc(length
* sizeof(char));
100 memcpy(mutableText
->value
, value
, length
);
102 snprintf(elemProp
, 64, "%s_wrap", name
);
103 if (configGetInt(themeConfig
, elemProp
, &sizingMode
)) {
105 mutableText
->sizingMode
= SIZING_WRAP
;
108 if ((elem
->width
!= DIM_UNDEF
) || (elem
->height
!= DIM_UNDEF
)) {
109 if (sizingMode
== SIZING_NONE
)
110 sizingMode
= SIZING_CLIP
;
112 if (elem
->width
== DIM_UNDEF
)
113 elem
->width
= screenWidth
;
115 if (elem
->height
== DIM_UNDEF
)
116 elem
->height
= screenHeight
;
118 sizingMode
= SIZING_NONE
;
119 mutableText
->sizingMode
= sizingMode
;
121 if (type
== TYPE_ATTRIBUTE_TEXT
) {
122 snprintf(elemProp
, 64, "%s_title", name
);
123 configGetStr(themeConfig
, elemProp
, &alias
);
130 length
= strlen(alias
) + 1 + 3;
131 mutableText
->alias
= (char*) malloc(length
* sizeof(char));
132 if (mutableText
->sizingMode
== SIZING_WRAP
)
133 snprintf(mutableText
->alias
, length
, "%s :\n", alias
);
135 snprintf(mutableText
->alias
, length
, "%s : ", alias
);
137 if (mutableText
->sizingMode
== SIZING_WRAP
)
138 fntFitString(elem
->font
, mutableText
->value
, elem
->width
);
144 // StaticText ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
146 static void drawStaticText(struct menu_list
* menu
, struct submenu_list
* item
, config_set_t
* config
, struct theme_element
* elem
) {
147 mutable_text_t
* mutableText
= (mutable_text_t
*) elem
->extended
;
148 if (mutableText
->sizingMode
== SIZING_NONE
)
149 fntRenderString(elem
->font
, elem
->posX
, elem
->posY
, elem
->aligned
, 0, 0, mutableText
->value
, elem
->color
);
151 fntRenderString(elem
->font
, elem
->posX
, elem
->posY
, elem
->aligned
, elem
->width
, elem
->height
, mutableText
->value
, elem
->color
);
154 static void initStaticText(char* themePath
, config_set_t
* themeConfig
, theme_t
* theme
, theme_element_t
* elem
, char* name
,
159 snprintf(elemProp
, 64, "%s_value", name
);
160 configGetStr(themeConfig
, elemProp
, &value
);
162 elem
->extended
= initMutableText(themePath
, themeConfig
, theme
, name
, TYPE_STATIC_TEXT
, elem
, value
, NULL
, DISPLAY_ALWAYS
, SIZING_NONE
);
163 elem
->endElem
= &endMutableText
;
164 elem
->drawElem
= &drawStaticText
;
166 LOG("THEMES StaticText %s: NO value, elem disabled !!\n", name
);
169 // AttributeText ////////////////////////////////////////////////////////////////////////////////////////////////////////////
171 static void drawAttributeText(struct menu_list
* menu
, struct submenu_list
* item
, config_set_t
* config
, struct theme_element
* elem
) {
172 mutable_text_t
* mutableText
= (mutable_text_t
*) elem
->extended
;
174 if (mutableText
->currentItemId
!= item
->item
.id
) {
176 mutableText
->currentItemId
= item
->item
.id
;
177 mutableText
->currentValue
= NULL
;
178 if (configGetStr(config
, mutableText
->value
, &mutableText
->currentValue
)) {
179 if (mutableText
->sizingMode
== SIZING_WRAP
)
180 fntFitString(elem
->font
, mutableText
->currentValue
, elem
->width
);
183 if (mutableText
->currentValue
) {
184 if (mutableText
->displayMode
== DISPLAY_NEVER
)
185 if (mutableText
->sizingMode
== SIZING_NONE
)
186 fntRenderString(elem
->font
, elem
->posX
, elem
->posY
, elem
->aligned
, 0, 0, mutableText
->currentValue
, elem
->color
);
188 fntRenderString(elem
->font
, elem
->posX
, elem
->posY
, elem
->aligned
, elem
->width
, elem
->height
, mutableText
->currentValue
, elem
->color
);
191 snprintf(result
, 300, "%s%s", mutableText
->alias
, mutableText
->currentValue
);
192 if (mutableText
->sizingMode
== SIZING_NONE
)
193 fntRenderString(elem
->font
, elem
->posX
, elem
->posY
, elem
->aligned
, 0, 0, result
, elem
->color
);
195 fntRenderString(elem
->font
, elem
->posX
, elem
->posY
, elem
->aligned
, elem
->width
, elem
->height
, result
, elem
->color
);
200 if (mutableText
->displayMode
== DISPLAY_ALWAYS
)
201 if (mutableText
->sizingMode
== SIZING_NONE
)
202 fntRenderString(elem
->font
, elem
->posX
, elem
->posY
, elem
->aligned
, 0, 0, mutableText
->alias
, elem
->color
);
204 fntRenderString(elem
->font
, elem
->posX
, elem
->posY
, elem
->aligned
, elem
->width
, elem
->height
, mutableText
->alias
, elem
->color
);
207 static void initAttributeText(char* themePath
, config_set_t
* themeConfig
, theme_t
* theme
, theme_element_t
* elem
, char* name
,
212 snprintf(elemProp
, 64, "%s_attribute", name
);
213 configGetStr(themeConfig
, elemProp
, &attribute
);
215 elem
->extended
= initMutableText(themePath
, themeConfig
, theme
, name
, TYPE_ATTRIBUTE_TEXT
, elem
, attribute
, NULL
, DISPLAY_ALWAYS
, SIZING_NONE
);
216 elem
->endElem
= &endMutableText
;
217 elem
->drawElem
= &drawAttributeText
;
219 LOG("THEMES AttributeText %s: NO attribute, elem disabled !!\n", name
);
222 // Common functions for Image ///////////////////////////////////////////////////////////////////////////////////////////////
224 static void findDuplicate(theme_element_t
* first
, char* cachePattern
, char* defaultTexture
, char* overlayTexture
, mutable_image_t
* target
) {
225 theme_element_t
* elem
= first
;
227 if ((elem
->type
== TYPE_STATIC_IMAGE
) || (elem
->type
== TYPE_ATTRIBUTE_IMAGE
) || (elem
->type
== TYPE_GAME_IMAGE
) || (elem
->type
== TYPE_BACKGROUND
)) {
228 mutable_image_t
* source
= (mutable_image_t
*) elem
->extended
;
230 if (cachePattern
&& source
->cache
&& !strcmp(cachePattern
, source
->cache
->suffix
)) {
231 target
->cache
= source
->cache
;
232 target
->cacheLinked
= 1;
233 LOG("THEMES Re-using a cache for pattern %s\n", cachePattern
);
236 if (defaultTexture
&& source
->defaultTexture
&& !strcmp(defaultTexture
, source
->defaultTexture
->name
)) {
237 target
->defaultTexture
= source
->defaultTexture
;
238 target
->defaultTextureLinked
= 1;
239 LOG("THEMES Re-using the default texture for %s\n", defaultTexture
);
242 if (overlayTexture
&& source
->overlayTexture
&& !strcmp(overlayTexture
, source
->overlayTexture
->name
)) {
243 target
->overlayTexture
= source
->overlayTexture
;
244 target
->overlayTextureLinked
= 1;
245 LOG("THEMES Re-using the overlay texture for %s\n", overlayTexture
);
253 static void freeImageTexture(image_texture_t
* texture
) {
255 if (texture
->source
.Mem
)
256 free(texture
->source
.Mem
);
264 static image_texture_t
* initImageTexture(char* themePath
, config_set_t
* themeConfig
, char* name
, char* imgName
, int isOverlay
) {
265 image_texture_t
* texture
= (image_texture_t
*) malloc(sizeof(image_texture_t
));
266 texPrepare(&texture
->source
, isOverlay
? GS_PSM_CT32
: GS_PSM_CT24
);
267 texture
->name
= NULL
;
270 snprintf(path
, 255, "%s%s", themePath
, imgName
);
271 if (texDiscoverLoad(&texture
->source
, path
, -1, isOverlay
? GS_PSM_CT32
: GS_PSM_CT24
) >= 0) {
272 int length
= strlen(imgName
) + 1;
273 texture
->name
= (char*) malloc(length
* sizeof(char));
274 memcpy(texture
->name
, imgName
, length
);
279 snprintf(elemProp
, 64, "%s_overlay_ulx", name
);
280 if (configGetInt(themeConfig
, elemProp
, &intValue
))
281 texture
->upperLeft_x
= intValue
;
282 snprintf(elemProp
, 64, "%s_overlay_uly", name
);
283 if (configGetInt(themeConfig
, elemProp
, &intValue
))
284 texture
->upperLeft_y
= intValue
;
285 snprintf(elemProp
, 64, "%s_overlay_urx", name
);
286 if (configGetInt(themeConfig
, elemProp
, &intValue
))
287 texture
->upperRight_x
= intValue
;
288 snprintf(elemProp
, 64, "%s_overlay_ury", name
);
289 if (configGetInt(themeConfig
, elemProp
, &intValue
))
290 texture
->upperRight_y
= intValue
;
291 snprintf(elemProp
, 64, "%s_overlay_llx", name
);
292 if (configGetInt(themeConfig
, elemProp
, &intValue
))
293 texture
->lowerLeft_x
= intValue
;
294 snprintf(elemProp
, 64, "%s_overlay_lly", name
);
295 if (configGetInt(themeConfig
, elemProp
, &intValue
))
296 texture
->lowerLeft_y
= intValue
;
297 snprintf(elemProp
, 64, "%s_overlay_lrx", name
);
298 if (configGetInt(themeConfig
, elemProp
, &intValue
))
299 texture
->lowerRight_x
= intValue
;
300 snprintf(elemProp
, 64, "%s_overlay_lry", name
);
301 if (configGetInt(themeConfig
, elemProp
, &intValue
))
302 texture
->lowerRight_y
= intValue
;
305 freeImageTexture(texture
);
312 static void endMutableImage(struct theme_element
* elem
) {
313 mutable_image_t
* mutableImage
= (mutable_image_t
*) elem
->extended
;
315 if (mutableImage
->cache
&& !mutableImage
->cacheLinked
)
316 cacheDestroyCache(mutableImage
->cache
);
318 if (mutableImage
->defaultTexture
&& !mutableImage
->defaultTextureLinked
)
319 freeImageTexture(mutableImage
->defaultTexture
);
321 if (mutableImage
->overlayTexture
&& !mutableImage
->overlayTextureLinked
)
322 freeImageTexture(mutableImage
->overlayTexture
);
330 static mutable_image_t
* initMutableImage(char* themePath
, config_set_t
* themeConfig
, theme_t
* theme
, char* name
, int type
,
331 char* cachePattern
, int cacheCount
, char* defaultTexture
, char* overlayTexture
) {
333 mutable_image_t
* mutableImage
= (mutable_image_t
*) malloc(sizeof(mutable_image_t
));
334 mutableImage
->currentUid
= -1;
335 mutableImage
->currentItemId
= -1;
336 mutableImage
->currentValue
= NULL
;
337 mutableImage
->cache
= NULL
;
338 mutableImage
->cacheLinked
= 0;
339 mutableImage
->defaultTexture
= NULL
;
340 mutableImage
->defaultTextureLinked
= 0;
341 mutableImage
->overlayTexture
= NULL
;
342 mutableImage
->overlayTextureLinked
= 0;
346 if (type
== TYPE_ATTRIBUTE_IMAGE
) {
347 snprintf(elemProp
, 64, "%s_attribute", name
);
348 configGetStr(themeConfig
, elemProp
, &cachePattern
);
349 LOG("THEMES MutableImage %s: type: %d using cache pattern: %s\n", name
, type
, cachePattern
);
350 } else if ((type
== TYPE_GAME_IMAGE
) || type
== (TYPE_BACKGROUND
)) {
351 snprintf(elemProp
, 64, "%s_pattern", name
);
352 configGetStr(themeConfig
, elemProp
, &cachePattern
);
353 snprintf(elemProp
, 64, "%s_count", name
);
354 configGetInt(themeConfig
, elemProp
, &cacheCount
);
355 LOG("THEMES MutableImage %s: type: %d using cache pattern: %s\n", name
, type
, cachePattern
);
358 snprintf(elemProp
, 64, "%s_default", name
);
359 configGetStr(themeConfig
, elemProp
, &defaultTexture
);
361 if (type
!= TYPE_BACKGROUND
) {
362 snprintf(elemProp
, 64, "%s_overlay", name
);
363 configGetStr(themeConfig
, elemProp
, &overlayTexture
);
366 findDuplicate(theme
->mainElems
.first
, cachePattern
, defaultTexture
, overlayTexture
, mutableImage
);
367 findDuplicate(theme
->infoElems
.first
, cachePattern
, defaultTexture
, overlayTexture
, mutableImage
);
369 if (cachePattern
&& !mutableImage
->cache
) {
370 if (type
== TYPE_ATTRIBUTE_IMAGE
)
371 mutableImage
->cache
= cacheInitCache(-1, themePath
, 0, cachePattern
, 1);
373 mutableImage
->cache
= cacheInitCache(theme
->gameCacheCount
++, "ART", 1, cachePattern
, cacheCount
);
376 if (defaultTexture
&& !mutableImage
->defaultTexture
)
377 mutableImage
->defaultTexture
= initImageTexture(themePath
, themeConfig
, name
, defaultTexture
, 0);
379 if (overlayTexture
&& !mutableImage
->overlayTexture
)
380 mutableImage
->overlayTexture
= initImageTexture(themePath
, themeConfig
, name
, overlayTexture
, 1);
385 // StaticImage //////////////////////////////////////////////////////////////////////////////////////////////////////////////
387 static void drawStaticImage(struct menu_list
* menu
, struct submenu_list
* item
, config_set_t
* config
, struct theme_element
* elem
) {
388 mutable_image_t
* staticImage
= (mutable_image_t
*) elem
->extended
;
389 if (staticImage
->overlayTexture
) {
390 rmDrawOverlayPixmap(&staticImage
->overlayTexture
->source
, elem
->posX
, elem
->posY
, elem
->aligned
, elem
->width
, elem
->height
, elem
->scaled
, gDefaultCol
,
391 &staticImage
->defaultTexture
->source
, staticImage
->overlayTexture
->upperLeft_x
, staticImage
->overlayTexture
->upperLeft_y
, staticImage
->overlayTexture
->upperRight_x
, staticImage
->overlayTexture
->upperRight_y
,
392 staticImage
->overlayTexture
->lowerLeft_x
, staticImage
->overlayTexture
->lowerLeft_y
, staticImage
->overlayTexture
->lowerRight_x
, staticImage
->overlayTexture
->lowerRight_y
);
394 rmDrawPixmap(&staticImage
->defaultTexture
->source
, elem
->posX
, elem
->posY
, elem
->aligned
, elem
->width
, elem
->height
, elem
->scaled
, gDefaultCol
);
397 static void initStaticImage(char* themePath
, config_set_t
* themeConfig
, theme_t
* theme
, theme_element_t
* elem
, char* name
,
400 mutable_image_t
* mutableImage
= initMutableImage(themePath
, themeConfig
, theme
, name
, elem
->type
, NULL
, 0, imageName
, NULL
);
401 elem
->extended
= mutableImage
;
402 elem
->endElem
= &endMutableImage
;
404 if (mutableImage
->defaultTexture
)
405 elem
->drawElem
= &drawStaticImage
;
407 LOG("THEMES StaticImage %s: NO image name, elem disabled !!\n", name
);
410 // GameImage ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
412 static GSTEXTURE
* getGameImageTexture(image_cache_t
* cache
, void* support
, struct submenu_item
* item
) {
414 item_list_t
* list
= (item_list_t
*) support
;
415 char* startup
= list
->itemGetStartup(item
->id
);
416 return cacheGetTexture(cache
, list
, &item
->cache_id
[cache
->userId
], &item
->cache_uid
[cache
->userId
], startup
);
422 static void drawGameImage(struct menu_list
* menu
, struct submenu_list
* item
, config_set_t
* config
, struct theme_element
* elem
) {
423 mutable_image_t
* gameImage
= (mutable_image_t
*) elem
->extended
;
425 GSTEXTURE
* texture
= getGameImageTexture(gameImage
->cache
, menu
->item
->userdata
, &item
->item
);
426 if (!texture
|| !texture
->Mem
) {
427 if (gameImage
->defaultTexture
)
428 texture
= &gameImage
->defaultTexture
->source
;
430 if (elem
->type
== TYPE_BACKGROUND
)
436 if (gameImage
->overlayTexture
) {
437 rmDrawOverlayPixmap(&gameImage
->overlayTexture
->source
, elem
->posX
, elem
->posY
, elem
->aligned
, elem
->width
, elem
->height
, elem
->scaled
, gDefaultCol
,
438 texture
, gameImage
->overlayTexture
->upperLeft_x
, gameImage
->overlayTexture
->upperLeft_y
, gameImage
->overlayTexture
->upperRight_x
, gameImage
->overlayTexture
->upperRight_y
,
439 gameImage
->overlayTexture
->lowerLeft_x
, gameImage
->overlayTexture
->lowerLeft_y
, gameImage
->overlayTexture
->lowerRight_x
, gameImage
->overlayTexture
->lowerRight_y
);
441 rmDrawPixmap(texture
, elem
->posX
, elem
->posY
, elem
->aligned
, elem
->width
, elem
->height
, elem
->scaled
, gDefaultCol
);
443 } else if (elem
->type
== TYPE_BACKGROUND
) {
444 if (gameImage
->defaultTexture
)
445 rmDrawPixmap(&gameImage
->defaultTexture
->source
, elem
->posX
, elem
->posY
, elem
->aligned
, elem
->width
, elem
->height
, elem
->scaled
, gDefaultCol
);
451 static void initGameImage(char* themePath
, config_set_t
* themeConfig
, theme_t
* theme
, theme_element_t
* elem
, char* name
,
452 char* pattern
, int count
, char* texture
, char* overlay
) {
454 mutable_image_t
* mutableImage
= initMutableImage(themePath
, themeConfig
, theme
, name
, elem
->type
, pattern
, count
, texture
, overlay
);
455 elem
->extended
= mutableImage
;
456 elem
->endElem
= &endMutableImage
;
458 if (mutableImage
->cache
)
459 elem
->drawElem
= &drawGameImage
;
461 LOG("THEMES GameImage %s: NO pattern, elem disabled !!\n", name
);
464 // AttributeImage ///////////////////////////////////////////////////////////////////////////////////////////////////////////
466 static void drawAttributeImage(struct menu_list
* menu
, struct submenu_list
* item
, config_set_t
* config
, struct theme_element
* elem
) {
467 mutable_image_t
* attributeImage
= (mutable_image_t
*) elem
->extended
;
469 if (attributeImage
->currentItemId
!= item
->item
.id
) {
471 attributeImage
->currentUid
= -1;
472 attributeImage
->currentItemId
= item
->item
.id
;
473 attributeImage
->currentValue
= NULL
;
474 configGetStr(config
, attributeImage
->cache
->suffix
, &attributeImage
->currentValue
);
476 if (attributeImage
->currentValue
) {
478 GSTEXTURE
* texture
= cacheGetTexture(attributeImage
->cache
, menu
->item
->userdata
, &posZ
, &attributeImage
->currentUid
, attributeImage
->currentValue
);
479 if (texture
&& texture
->Mem
) {
480 if (attributeImage
->overlayTexture
) {
481 rmDrawOverlayPixmap(&attributeImage
->overlayTexture
->source
, elem
->posX
, elem
->posY
, elem
->aligned
, elem
->width
, elem
->height
, elem
->scaled
, gDefaultCol
,
482 texture
, attributeImage
->overlayTexture
->upperLeft_x
, attributeImage
->overlayTexture
->upperLeft_y
, attributeImage
->overlayTexture
->upperRight_x
, attributeImage
->overlayTexture
->upperRight_y
,
483 attributeImage
->overlayTexture
->lowerLeft_x
, attributeImage
->overlayTexture
->lowerLeft_y
, attributeImage
->overlayTexture
->lowerRight_x
, attributeImage
->overlayTexture
->lowerRight_y
);
485 rmDrawPixmap(texture
, elem
->posX
, elem
->posY
, elem
->aligned
, elem
->width
, elem
->height
, elem
->scaled
, gDefaultCol
);
491 if (attributeImage
->defaultTexture
)
492 rmDrawPixmap(&attributeImage
->defaultTexture
->source
, elem
->posX
, elem
->posY
, elem
->aligned
, elem
->width
, elem
->height
, elem
->scaled
, gDefaultCol
);
495 static void initAttributeImage(char* themePath
, config_set_t
* themeConfig
, theme_t
* theme
, theme_element_t
* elem
, char* name
) {
496 mutable_image_t
* mutableImage
= initMutableImage(themePath
, themeConfig
, theme
, name
, elem
->type
, NULL
, 1, NULL
, NULL
);
497 elem
->extended
= mutableImage
;
498 elem
->endElem
= &endMutableImage
;
500 if (mutableImage
->cache
)
501 elem
->drawElem
= &drawAttributeImage
;
503 LOG("THEMES AttributeImage %s: NO attribute, elem disabled !!\n", name
);
506 // BasicElement /////////////////////////////////////////////////////////////////////////////////////////////////////////////
508 static void endBasic(theme_element_t
* elem
) {
510 free(elem
->extended
);
515 static theme_element_t
* initBasic(char* themePath
, config_set_t
* themeConfig
, theme_t
* theme
,
516 char* name
, int type
, int x
, int y
, short aligned
, int w
, int h
, short scaled
, u64 color
, int font
) {
519 unsigned char charColor
[3];
523 theme_element_t
* elem
= (theme_element_t
*) malloc(sizeof(theme_element_t
));
526 elem
->extended
= NULL
;
527 elem
->drawElem
= NULL
;
528 elem
->endElem
= &endBasic
;
531 snprintf(elemProp
, 64, "%s_x", name
);
532 if (configGetStr(themeConfig
, elemProp
, &temp
)) {
533 if (!strncmp(temp
, "POS_MID", 7))
534 x
= screenWidth
>> 1;
539 elem
->posX
= screenWidth
+ x
;
543 snprintf(elemProp
, 64, "%s_y", name
);
544 if (configGetStr(themeConfig
, elemProp
, &temp
)) {
545 if (!strncmp(temp
, "POS_MID", 7))
546 y
= screenHeight
>> 1;
551 elem
->posY
= ceil((screenHeight
+ y
) * theme
->usedHeight
/ screenHeight
);
555 snprintf(elemProp
, 64, "%s_width", name
);
556 if (configGetStr(themeConfig
, elemProp
, &temp
)) {
557 if (!strncmp(temp
, "DIM_INF", 7))
558 elem
->width
= screenWidth
;
560 elem
->width
= atoi(temp
);
564 snprintf(elemProp
, 64, "%s_height", name
);
565 if (configGetStr(themeConfig
, elemProp
, &temp
)) {
566 if (!strncmp(temp
, "DIM_INF", 7))
567 elem
->height
= screenHeight
;
569 elem
->height
= atoi(temp
);
573 snprintf(elemProp
, 64, "%s_aligned", name
);
574 if (configGetInt(themeConfig
, elemProp
, &intValue
))
575 elem
->aligned
= intValue
;
577 elem
->aligned
= aligned
;
579 snprintf(elemProp
, 64, "%s_scaled", name
);
580 if (configGetInt(themeConfig
, elemProp
, &intValue
))
581 elem
->scaled
= intValue
;
583 elem
->scaled
= scaled
;
585 snprintf(elemProp
, 64, "%s_color", name
);
586 if (configGetColor(themeConfig
, elemProp
, charColor
))
587 elem
->color
= GS_SETREG_RGBA(charColor
[0], charColor
[1], charColor
[2], 0xff);
591 snprintf(elemProp
, 64, "%s_font", name
);
592 if (configGetInt(themeConfig
, elemProp
, &intValue
))
594 if (font
>= 0 && font
< THM_MAX_FONTS
)
595 elem
->font
= theme
->fonts
[font
];
597 elem
->font
= FNT_DEFAULT
;
602 // Internal elements ////////////////////////////////////////////////////////////////////////////////////////////////////////
604 static void drawBackground(struct menu_list
* menu
, struct submenu_list
* item
, config_set_t
* config
, struct theme_element
* elem
) {
608 static void initBackground(char* themePath
, config_set_t
* themeConfig
, theme_t
* theme
, theme_element_t
* elem
, char* name
,
609 char* pattern
, int count
, char* texture
) {
611 mutable_image_t
* mutableImage
= initMutableImage(themePath
, themeConfig
, theme
, name
, elem
->type
, pattern
, count
, texture
, NULL
);
612 elem
->extended
= mutableImage
;
613 elem
->endElem
= &endMutableImage
;
615 if (mutableImage
->cache
)
616 elem
->drawElem
= &drawGameImage
;
617 else if (mutableImage
->defaultTexture
)
618 elem
->drawElem
= &drawStaticImage
;
620 elem
->drawElem
= &drawBackground
;
623 static void drawMenuIcon(struct menu_list
* menu
, struct submenu_list
* item
, config_set_t
* config
, struct theme_element
* elem
) {
624 GSTEXTURE
* menuIconTex
= thmGetTexture(menu
->item
->icon_id
);
625 if (menuIconTex
&& menuIconTex
->Mem
)
626 rmDrawPixmap(menuIconTex
, elem
->posX
, elem
->posY
, elem
->aligned
, elem
->width
, elem
->height
, elem
->scaled
, gDefaultCol
);
629 static void drawMenuText(struct menu_list
* menu
, struct submenu_list
* item
, config_set_t
* config
, struct theme_element
* elem
) {
630 GSTEXTURE
* leftIconTex
= NULL
, *rightIconTex
= NULL
;
632 leftIconTex
= thmGetTexture(LEFT_ICON
);
634 rightIconTex
= thmGetTexture(RIGHT_ICON
);
637 int offset
= elem
->width
>> 1;
638 if (leftIconTex
&& leftIconTex
->Mem
)
639 rmDrawPixmap(leftIconTex
, elem
->posX
- offset
, elem
->posY
, elem
->aligned
, leftIconTex
->Width
, leftIconTex
->Height
, elem
->scaled
, gDefaultCol
);
640 if (rightIconTex
&& rightIconTex
->Mem
)
641 rmDrawPixmap(rightIconTex
, elem
->posX
+ offset
, elem
->posY
, elem
->aligned
, rightIconTex
->Width
, rightIconTex
->Height
, elem
->scaled
, gDefaultCol
);
644 if (leftIconTex
&& leftIconTex
->Mem
)
645 rmDrawPixmap(leftIconTex
, elem
->posX
- leftIconTex
->Width
, elem
->posY
, elem
->aligned
, leftIconTex
->Width
, leftIconTex
->Height
, elem
->scaled
, gDefaultCol
);
646 if (rightIconTex
&& rightIconTex
->Mem
)
647 rmDrawPixmap(rightIconTex
, elem
->posX
+ elem
->width
, elem
->posY
, elem
->aligned
, rightIconTex
->Width
, rightIconTex
->Height
, elem
->scaled
, gDefaultCol
);
649 fntRenderString(elem
->font
, elem
->posX
, elem
->posY
, elem
->aligned
, 0, 0, menuItemGetText(menu
->item
), elem
->color
);
652 static void drawItemsList(struct menu_list
* menu
, struct submenu_list
* item
, config_set_t
* config
, struct theme_element
* elem
) {
654 items_list_t
* itemsList
= (items_list_t
*) elem
->extended
;
656 int posX
= elem
->posX
, posY
= elem
->posY
;
658 posX
-= elem
->width
>> 1;
659 posY
-= elem
->height
>> 1;
662 submenu_list_t
*ps
= menu
->item
->pagestart
;
665 while (ps
&& (others
++ < itemsList
->displayedItems
)) {
667 color
= gTheme
->selTextColor
;
671 if (itemsList
->decoratorImage
) {
672 GSTEXTURE
* itemIconTex
= getGameImageTexture(itemsList
->decoratorImage
->cache
, menu
->item
->userdata
, &ps
->item
);
673 if (itemIconTex
&& itemIconTex
->Mem
)
674 rmDrawPixmap(itemIconTex
, posX
, posY
, ALIGN_NONE
, DECORATOR_SIZE
, DECORATOR_SIZE
, elem
->scaled
, gDefaultCol
);
676 if (itemsList
->decoratorImage
->defaultTexture
)
677 rmDrawPixmap(&itemsList
->decoratorImage
->defaultTexture
->source
, posX
, posY
, ALIGN_NONE
, DECORATOR_SIZE
, DECORATOR_SIZE
, elem
->scaled
, gDefaultCol
);
679 fntRenderString(elem
->font
, posX
+ DECORATOR_SIZE
, posY
, ALIGN_NONE
, elem
->width
, elem
->height
, submenuItemGetText(&ps
->item
), color
);
681 fntRenderString(elem
->font
, posX
, posY
, ALIGN_NONE
, elem
->width
, elem
->height
, submenuItemGetText(&ps
->item
), color
);
683 posY
+= MENU_ITEM_HEIGHT
;
689 static void initItemsList(char* themePath
, config_set_t
* themeConfig
, theme_t
* theme
, theme_element_t
* elem
, char* name
, char* decorator
) {
692 items_list_t
* itemsList
= (items_list_t
*) malloc(sizeof(items_list_t
));
694 if (elem
->width
== DIM_UNDEF
)
695 elem
->width
= screenWidth
;
697 if (elem
->height
== DIM_UNDEF
)
698 elem
->height
= theme
->usedHeight
- (MENU_POS_V
+ HINT_HEIGHT
);
700 itemsList
->displayedItems
= elem
->height
/ MENU_ITEM_HEIGHT
;
701 LOG("THEMES ItemsList %s: displaying %d elems, item height: %d\n", name
, itemsList
->displayedItems
, elem
->height
);
703 itemsList
->decorator
= NULL
;
704 snprintf(elemProp
, 64, "%s_decorator", name
);
705 configGetStr(themeConfig
, elemProp
, &decorator
);
707 itemsList
->decorator
= decorator
; // Will be used later (thmValidate)
709 itemsList
->decoratorImage
= NULL
;
711 elem
->extended
= itemsList
;
712 // elem->endElem = &endBasic; does the job
714 elem
->drawElem
= &drawItemsList
;
717 static void drawItemText(struct menu_list
* menu
, struct submenu_list
* item
, config_set_t
* config
, struct theme_element
* elem
) {
719 item_list_t
*support
= menu
->item
->userdata
;
720 fntRenderString(elem
->font
, elem
->posX
, elem
->posY
, elem
->aligned
, 0, 0, support
->itemGetStartup(item
->item
.id
), elem
->color
);
724 static void drawHintText(struct menu_list
* menu
, struct submenu_list
* item
, config_set_t
* config
, struct theme_element
* elem
) {
725 menu_hint_item_t
* hint
= menu
->item
->hints
;
729 for (; hint
; hint
= hint
->next
) {
730 x
= guiDrawIconAndText(hint
->icon_id
, hint
->text_id
, elem
->font
, x
, elem
->posY
, elem
->color
);
736 static void drawInfoHintText(struct menu_list
* menu
, struct submenu_list
* item
, config_set_t
* config
, struct theme_element
* elem
) {
738 x
= guiDrawIconAndText(CROSS_ICON
, _STR_RUN
, elem
->font
, x
, elem
->posY
, elem
->color
);
740 x
= guiDrawIconAndText(CIRCLE_ICON
, _STR_O_BACK
, elem
->font
, x
, elem
->posY
, elem
->color
);
743 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
745 static void validateGUIElems(char* themePath
, config_set_t
* themeConfig
, theme_t
* theme
) {
746 // 1. check we have a valid Background elements
747 if ( !theme
->mainElems
.first
|| (theme
->mainElems
.first
->type
!= TYPE_BACKGROUND
) ) {
748 LOG("THEMES No valid background found for main, add default BG_ART\n");
749 theme_element_t
* backgroundElem
= initBasic(themePath
, themeConfig
, theme
, "bg", TYPE_BACKGROUND
, 0, 0, ALIGN_NONE
, screenWidth
, screenHeight
, SCALING_NONE
, gDefaultCol
, FNT_DEFAULT
);
751 initBackground(themePath
, themeConfig
, theme
, backgroundElem
, "bg", "BG", 1, "background");
753 initBackground(themePath
, themeConfig
, theme
, backgroundElem
, "bg", "BG", 1, NULL
);
754 backgroundElem
->next
= theme
->mainElems
.first
;
755 theme
->mainElems
.first
= backgroundElem
;
758 if (theme
->infoElems
.first
) {
759 if (theme
->infoElems
.first
->type
!= TYPE_BACKGROUND
) {
760 LOG("THEMES No valid background found for info, add default BG_ART\n");
761 theme_element_t
* backgroundElem
= initBasic(themePath
, themeConfig
, theme
, "bg", TYPE_BACKGROUND
, 0, 0, ALIGN_NONE
, screenWidth
, screenHeight
, SCALING_NONE
, gDefaultCol
, FNT_DEFAULT
);
763 initBackground(themePath
, themeConfig
, theme
, backgroundElem
, "bg", "BG", 1, "background");
765 initBackground(themePath
, themeConfig
, theme
, backgroundElem
, "bg", "BG", 1, NULL
);
766 backgroundElem
->next
= theme
->infoElems
.first
;
767 theme
->infoElems
.first
= backgroundElem
;
771 // 2. check we have a valid ItemsList element, and link its decorator to the target element
772 if (theme
->itemsList
) {
773 items_list_t
* itemsList
= (items_list_t
*) theme
->itemsList
->extended
;
774 if (itemsList
->decorator
) {
775 // Second pass to find the decorator
776 theme_element_t
* decoratorElem
= theme
->mainElems
.first
;
777 while (decoratorElem
) {
778 if (decoratorElem
->type
== TYPE_GAME_IMAGE
) {
779 mutable_image_t
* gameImage
= (mutable_image_t
*) decoratorElem
->extended
;
780 if (!strcmp(itemsList
->decorator
, gameImage
->cache
->suffix
)) {
781 // if user want to cache less than displayed items, then disable itemslist icons, if not would load constantly
782 if (gameImage
->cache
->count
>= itemsList
->displayedItems
)
783 itemsList
->decoratorImage
= gameImage
;
788 decoratorElem
= decoratorElem
->next
;
790 itemsList
->decorator
= NULL
;
793 LOG("THEMES No itemsList found, adding a default one\n");
794 theme
->itemsList
= initBasic(themePath
, themeConfig
, theme
, "il", TYPE_ITEMS_LIST
, 150, MENU_POS_V
, ALIGN_NONE
, DIM_UNDEF
, DIM_UNDEF
, SCALING_RATIO
, theme
->textColor
, FNT_DEFAULT
);
795 initItemsList(themePath
, themeConfig
, theme
, theme
->itemsList
, "il", NULL
);
796 theme
->itemsList
->next
= theme
->mainElems
.first
->next
; // Position the itemsList as second element (right after the Background)
797 theme
->mainElems
.first
->next
= theme
->itemsList
;
801 static int addGUIElem(char* themePath
, config_set_t
* themeConfig
, theme_t
* theme
, theme_elems_t
* elems
, char* type
, char* name
) {
805 theme_element_t
* elem
= NULL
;
807 snprintf(elemProp
, 64, "%s_enabled", name
);
808 configGetInt(themeConfig
, elemProp
, &enabled
);
811 snprintf(elemProp
, 64, "%s_type", name
);
812 configGetStr(themeConfig
, elemProp
, &type
);
814 if (!strcmp(elementsType
[TYPE_ATTRIBUTE_TEXT
], type
)) {
815 elem
= initBasic(themePath
, themeConfig
, theme
, name
, TYPE_ATTRIBUTE_TEXT
, 0, 0, ALIGN_CENTER
, DIM_UNDEF
, DIM_UNDEF
, SCALING_RATIO
, theme
->textColor
, FNT_DEFAULT
);
816 initAttributeText(themePath
, themeConfig
, theme
, elem
, name
, NULL
);
817 } else if (!strcmp(elementsType
[TYPE_STATIC_TEXT
], type
)) {
818 elem
= initBasic(themePath
, themeConfig
, theme
, name
, TYPE_STATIC_TEXT
, 0, 0, ALIGN_CENTER
, DIM_UNDEF
, DIM_UNDEF
, SCALING_RATIO
, theme
->textColor
, FNT_DEFAULT
);
819 initStaticText(themePath
, themeConfig
, theme
, elem
, name
, NULL
);
820 } else if (!strcmp(elementsType
[TYPE_ATTRIBUTE_IMAGE
], type
)) {
821 elem
= initBasic(themePath
, themeConfig
, theme
, name
, TYPE_ATTRIBUTE_IMAGE
, 0, 0, ALIGN_CENTER
, DIM_UNDEF
, DIM_UNDEF
, SCALING_RATIO
, gDefaultCol
, FNT_DEFAULT
);
822 initAttributeImage(themePath
, themeConfig
, theme
, elem
, name
);
823 } else if (!strcmp(elementsType
[TYPE_GAME_IMAGE
], type
)) {
824 elem
= initBasic(themePath
, themeConfig
, theme
, name
, TYPE_GAME_IMAGE
, 0, 0, ALIGN_CENTER
, DIM_UNDEF
, DIM_UNDEF
, SCALING_RATIO
, gDefaultCol
, FNT_DEFAULT
);
825 initGameImage(themePath
, themeConfig
, theme
, elem
, name
, NULL
, 1, NULL
, NULL
);
826 } else if (!strcmp(elementsType
[TYPE_STATIC_IMAGE
], type
)) {
827 elem
= initBasic(themePath
, themeConfig
, theme
, name
, TYPE_STATIC_IMAGE
, 0, 0, ALIGN_CENTER
, DIM_UNDEF
, DIM_UNDEF
, SCALING_RATIO
, gDefaultCol
, FNT_DEFAULT
);
828 initStaticImage(themePath
, themeConfig
, theme
, elem
, name
, NULL
);
829 } else if (!strcmp(elementsType
[TYPE_BACKGROUND
], type
)) {
830 if (!elems
->first
) { // Background elem can only be the first one
831 elem
= initBasic(themePath
, themeConfig
, theme
, name
, TYPE_BACKGROUND
, 0, 0, ALIGN_NONE
, screenWidth
, screenHeight
, SCALING_NONE
, gDefaultCol
, FNT_DEFAULT
);
832 initBackground(themePath
, themeConfig
, theme
, elem
, name
, NULL
, 1, NULL
);
834 } else if (!strcmp(elementsType
[TYPE_MENU_ICON
], type
)) {
835 elem
= initBasic(themePath
, themeConfig
, theme
, name
, TYPE_MENU_ICON
, 40, 40, ALIGN_CENTER
, DIM_UNDEF
, DIM_UNDEF
, SCALING_RATIO
, gDefaultCol
, FNT_DEFAULT
);
836 elem
->drawElem
= &drawMenuIcon
;
837 } else if (!strcmp(elementsType
[TYPE_MENU_TEXT
], type
)) {
838 elem
= initBasic(themePath
, themeConfig
, theme
, name
, TYPE_MENU_TEXT
, screenWidth
>> 1, 20, ALIGN_CENTER
, 200, 20, SCALING_RATIO
, theme
->textColor
, FNT_DEFAULT
);
839 elem
->drawElem
= &drawMenuText
;
840 } else if (!strcmp(elementsType
[TYPE_ITEMS_LIST
], type
)) {
841 if (!theme
->itemsList
) {
842 elem
= initBasic(themePath
, themeConfig
, theme
, name
, TYPE_ITEMS_LIST
, 150, MENU_POS_V
, ALIGN_NONE
, DIM_UNDEF
, DIM_UNDEF
, SCALING_RATIO
, theme
->textColor
, FNT_DEFAULT
);
843 initItemsList(themePath
, themeConfig
, theme
, elem
, name
, NULL
);
844 theme
->itemsList
= elem
;
846 } else if (!strcmp(elementsType
[TYPE_ITEM_ICON
], type
)) {
847 elem
= initBasic(themePath
, themeConfig
, theme
, name
, TYPE_GAME_IMAGE
, 80, theme
->usedHeight
>> 1, ALIGN_CENTER
, DIM_UNDEF
, DIM_UNDEF
, SCALING_RATIO
, gDefaultCol
, FNT_DEFAULT
);
848 initGameImage(themePath
, themeConfig
, theme
, elem
, name
, "ICO", 20, NULL
, NULL
);
849 } else if (!strcmp(elementsType
[TYPE_ITEM_COVER
], type
)) {
850 elem
= initBasic(themePath
, themeConfig
, theme
, name
, TYPE_GAME_IMAGE
, 520, theme
->usedHeight
>> 1, ALIGN_CENTER
, DIM_UNDEF
, DIM_UNDEF
, SCALING_RATIO
, gDefaultCol
, FNT_DEFAULT
);
851 initGameImage(themePath
, themeConfig
, theme
, elem
, name
, "COV", 10, NULL
, NULL
);
852 } else if (!strcmp(elementsType
[TYPE_ITEM_TEXT
], type
)) {
853 elem
= initBasic(themePath
, themeConfig
, theme
, name
, TYPE_ITEM_TEXT
, 520, 370, ALIGN_CENTER
, DIM_UNDEF
, DIM_UNDEF
, SCALING_RATIO
, theme
->textColor
, FNT_DEFAULT
);
854 elem
->drawElem
= &drawItemText
;
855 } else if (!strcmp(elementsType
[TYPE_HINT_TEXT
], type
)) {
856 elem
= initBasic(themePath
, themeConfig
, theme
, name
, TYPE_HINT_TEXT
, 16, -HINT_HEIGHT
, ALIGN_NONE
, 12, 20, SCALING_RATIO
, theme
->textColor
, FNT_DEFAULT
);
857 elem
->drawElem
= &drawHintText
;
858 } else if (!strcmp(elementsType
[TYPE_INFO_HINT_TEXT
], type
)) {
859 elem
= initBasic(themePath
, themeConfig
, theme
, name
, TYPE_INFO_HINT_TEXT
, 16, -HINT_HEIGHT
, ALIGN_NONE
, 12, 20, SCALING_RATIO
, theme
->textColor
, FNT_DEFAULT
);
860 elem
->drawElem
= &drawInfoHintText
;
861 } else if (!strcmp(elementsType
[TYPE_LOADING_ICON
], type
)) {
862 if (!theme
->loadingIcon
)
863 theme
->loadingIcon
= initBasic(themePath
, themeConfig
, theme
, name
, TYPE_LOADING_ICON
, -50, -50, ALIGN_CENTER
, DIM_UNDEF
, DIM_UNDEF
, SCALING_RATIO
, gDefaultCol
, FNT_DEFAULT
);
873 elems
->last
->next
= elem
;
878 return 0; // ends the reading of elements
884 static void freeGUIElems(theme_elems_t
* elems
) {
885 theme_element_t
* elem
= elems
->first
;
887 elems
->first
= elem
->next
;
893 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
894 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
896 GSTEXTURE
* thmGetTexture(unsigned int id
) {
897 if (id
>= TEXTURES_COUNT
)
900 // see if the texture is valid
901 GSTEXTURE
* txt
= &gTheme
->textures
[id
];
910 static void thmFree(theme_t
* theme
) {
913 freeGUIElems(&theme
->mainElems
);
914 freeGUIElems(&theme
->infoElems
);
919 for(; id
< TEXTURES_COUNT
; id
++) {
920 texture
= &theme
->textures
[id
];
921 if (texture
->Mem
!= NULL
) {
928 for (id
= 0; id
< THM_MAX_FONTS
; ++id
) {
929 int fntid
= theme
->fonts
[id
];
931 if (fntid
!= FNT_DEFAULT
)
940 static int thmReadEntry(int index
, char* path
, char* separator
, char* name
, unsigned int mode
) {
941 if (FIO_SO_ISDIR(mode
) && strstr(name
, "thm_")) {
942 theme_file_t
* currTheme
= &themes
[nThemes
+ index
];
944 int length
= strlen(name
) - 4 + 1;
945 currTheme
->name
= (char*) malloc(length
* sizeof(char));
946 memcpy(currTheme
->name
, name
+ 4, length
);
947 currTheme
->name
[length
- 1] = '\0';
949 length
= strlen(path
) + 1 + strlen(name
) + 1 + 1;
950 currTheme
->filePath
= (char*) malloc(length
* sizeof(char));
951 sprintf(currTheme
->filePath
, "%s%s%s%s", path
, separator
, name
, separator
);
953 LOG("THEMES Theme found: %s\n", currTheme
->filePath
);
960 /* themePath must contains the leading separator (as it is dependent of the device, we can't know here) */
961 static int thmLoadResource(int texId
, char* themePath
, short psm
, int useDefault
) {
963 GSTEXTURE
* texture
= &gTheme
->textures
[texId
];
965 if (themePath
!= NULL
)
966 success
= texDiscoverLoad(texture
, themePath
, texId
, psm
); // only set success here
968 if ((success
< 0) && useDefault
)
969 texPngLoad(texture
, NULL
, texId
, psm
); // we don't mind the result of "default"
974 static void thmSetColors(theme_t
* theme
) {
975 memcpy(theme
->bgColor
, gDefaultBgColor
, 3);
976 theme
->textColor
= GS_SETREG_RGBA(gDefaultTextColor
[0], gDefaultTextColor
[1], gDefaultTextColor
[2], 0xff);
977 theme
->uiTextColor
= GS_SETREG_RGBA(gDefaultUITextColor
[0], gDefaultUITextColor
[1], gDefaultUITextColor
[2], 0xff);
978 theme
->selTextColor
= GS_SETREG_RGBA(gDefaultSelTextColor
[0], gDefaultSelTextColor
[1], gDefaultSelTextColor
[2], 0xff);
980 theme_element_t
* elem
= theme
->mainElems
.first
;
982 elem
->color
= theme
->textColor
;
987 static void thmLoadFonts(config_set_t
* themeConfig
, const char* themePath
, theme_t
* theme
) {
988 int fntID
; // theme side font id, not the fntSys handle
989 for (fntID
= -1; fntID
< THM_MAX_FONTS
; ++fntID
) {
990 // does the font by the key exist?
993 // -1 is a placeholder for default font...
995 // Default font handle...
996 theme
->fonts
[fntID
] = FNT_DEFAULT
;
997 snprintf(fntKey
, 16, "font%d", fntID
);
999 snprintf(fntKey
, 16, "default_font");
1003 int cfgKeyOK
= configGetStr(themeConfig
, fntKey
, &fntFile
);
1004 if (!cfgKeyOK
&& (fntID
>= 0))
1010 // replace the default font
1012 snprintf(fullPath
, 128, "%s%s", themePath
, fntFile
);
1015 void* customFont
= readFile(fullPath
, -1, &size
);
1018 fntReplace(FNT_DEFAULT
, customFont
, size
, 1, 0);
1020 fntSetDefault(FNT_DEFAULT
);
1022 snprintf(fullPath
, 128, "%s%s", themePath
, fntFile
);
1023 int fntHandle
= fntLoadFile(fullPath
);
1025 // Do we have a valid font? Assign the font handle to the theme font slot
1026 if (fntHandle
!= FNT_ERROR
)
1027 theme
->fonts
[fntID
] = fntHandle
;
1032 static void thmLoad(char* themePath
) {
1033 LOG("THEMES Load theme path=%s\n", themePath
);
1034 theme_t
* curT
= gTheme
;
1035 theme_t
* newT
= (theme_t
*) malloc(sizeof(theme_t
));
1036 memset(newT
, 0, sizeof(theme_t
));
1038 newT
->useDefault
= 1;
1039 newT
->usedHeight
= 480;
1041 newT
->mainElems
.first
= NULL
;
1042 newT
->mainElems
.last
= NULL
;
1043 newT
->infoElems
.first
= NULL
;
1044 newT
->infoElems
.last
= NULL
;
1045 newT
->gameCacheCount
= 0;
1046 newT
->itemsList
= NULL
;
1047 newT
->loadingIcon
= NULL
;
1048 newT
->loadingIconCount
= LOAD7_ICON
- LOAD0_ICON
+ 1;
1050 config_set_t
* themeConfig
= NULL
;
1052 themeConfig
= configAlloc(0, NULL
, NULL
);
1053 addGUIElem(themePath
, themeConfig
, newT
, &newT
->mainElems
, elementsType
[TYPE_MENU_ICON
], "_");
1054 addGUIElem(themePath
, themeConfig
, newT
, &newT
->mainElems
, elementsType
[TYPE_MENU_TEXT
], "_");
1055 addGUIElem(themePath
, themeConfig
, newT
, &newT
->mainElems
, elementsType
[TYPE_ITEMS_LIST
], "_");
1056 addGUIElem(themePath
, themeConfig
, newT
, &newT
->mainElems
, elementsType
[TYPE_ITEM_ICON
], "_");
1057 addGUIElem(themePath
, themeConfig
, newT
, &newT
->mainElems
, elementsType
[TYPE_ITEM_COVER
], "_");
1058 addGUIElem(themePath
, themeConfig
, newT
, &newT
->mainElems
, elementsType
[TYPE_ITEM_TEXT
], "_");
1059 addGUIElem(themePath
, themeConfig
, newT
, &newT
->mainElems
, elementsType
[TYPE_HINT_TEXT
], "_");
1060 addGUIElem(themePath
, themeConfig
, newT
, &newT
->mainElems
, elementsType
[TYPE_LOADING_ICON
], "_");
1062 // reset the default font to be sure
1063 fntSetDefault(FNT_DEFAULT
);
1066 snprintf(path
, 255, "%sconf_theme.cfg", themePath
);
1067 themeConfig
= configAlloc(0, NULL
, path
);
1068 configRead(themeConfig
); // try to load the theme config file
1071 if (configGetInt(themeConfig
, "use_default", &intValue
))
1072 newT
->useDefault
= intValue
;
1074 if (configGetInt(themeConfig
, "use_real_height", &intValue
)) {
1076 newT
->usedHeight
= screenHeight
;
1079 configGetColor(themeConfig
, "bg_color", newT
->bgColor
);
1081 unsigned char color
[3];
1082 if (configGetColor(themeConfig
, "text_color", color
))
1083 newT
->textColor
= GS_SETREG_RGBA(color
[0], color
[1], color
[2], 0xff);
1085 if (configGetColor(themeConfig
, "ui_text_color", color
))
1086 newT
->uiTextColor
= GS_SETREG_RGBA(color
[0], color
[1], color
[2], 0xff);
1088 if (configGetColor(themeConfig
, "sel_text_color", color
))
1089 newT
->selTextColor
= GS_SETREG_RGBA(color
[0], color
[1], color
[2], 0xff);
1091 // before loading the element definitions, we have to have the fonts prepared
1092 // for that, we load the fonts and a translation table
1093 thmLoadFonts(themeConfig
, themePath
, newT
);
1096 snprintf(path
, 255, "main0");
1097 while (addGUIElem(themePath
, themeConfig
, newT
, &newT
->mainElems
, NULL
, path
))
1098 snprintf(path
, 255, "main%d", i
++);
1101 snprintf(path
, 255, "info0");
1102 while(addGUIElem(themePath
, themeConfig
, newT
, &newT
->infoElems
, NULL
, path
))
1103 snprintf(path
, 255, "info%d", i
++);
1106 validateGUIElems(themePath
, themeConfig
, newT
);
1107 configFree(themeConfig
);
1109 LOG("THEMES Number of cache: %d\n", newT
->gameCacheCount
);
1110 LOG("THEMES Used height: %d\n", newT
->usedHeight
);
1112 /// Now swap theme and start loading textures
1113 if (newT
->usedHeight
== screenHeight
)
1114 rmResetShiftRatio();
1116 rmSetShiftRatio((float) screenHeight
/ newT
->usedHeight
);
1119 // default all to not loaded...
1120 for (i
= 0; i
< TEXTURES_COUNT
; i
++) {
1121 newT
->textures
[i
].Mem
= NULL
;
1124 // LOGO, loaded here to avoid flickering during startup with device in AUTO + theme set
1125 texPngLoad(&newT
->textures
[LOGO_PICTURE
], NULL
, LOGO_PICTURE
, GS_PSM_CT24
);
1130 // First start with busy icon
1131 char* path
= themePath
;
1133 for (i
= LOAD0_ICON
; i
<= LOAD7_ICON
; i
++) {
1134 if (thmLoadResource(i
, path
, GS_PSM_CT32
, gTheme
->useDefault
) >= 0)
1143 gTheme
->loadingIconCount
= i
;
1145 // Customizable icons
1146 for (i
= USB_ICON
; i
<= START_ICON
; i
++)
1147 thmLoadResource(i
, themePath
, GS_PSM_CT32
, gTheme
->useDefault
);
1149 // Not customizable icons
1150 for (i
= L1_ICON
; i
<= R2_ICON
; i
++)
1151 thmLoadResource(i
, NULL
, GS_PSM_CT32
, 1);
1154 static void thmRebuildGuiNames() {
1156 free(guiThemesNames
);
1158 // build the languages name list
1159 guiThemesNames
= (char**) malloc((nThemes
+ 2) * sizeof(char**));
1161 // add default internal
1162 guiThemesNames
[0] = "<OPL>";
1165 for (; i
< nThemes
; i
++) {
1166 guiThemesNames
[i
+ 1] = themes
[i
].name
;
1169 guiThemesNames
[nThemes
+ 1] = NULL
;
1172 void thmAddElements(char* path
, char* separator
, int mode
) {
1173 nThemes
+= listDir(path
, separator
, THM_MAX_FILES
- nThemes
, &thmReadEntry
);
1174 thmRebuildGuiNames();
1177 if (configGetStr(configGetByType(CONFIG_OPL
), "theme", &temp
)) {
1178 LOG("THEMES Trying to set again theme: %s\n", temp
);
1179 if (thmSetGuiValue(thmFindGuiID(temp
), 0))
1180 moduleUpdateMenu(mode
, 1);
1185 LOG("THEMES Init\n");
1188 thmReloadScreenExtents();
1190 // initialize default internal
1193 thmAddElements(gBaseMCDir
, "/", -1);
1196 void thmReinit(char* path
) {
1201 while (i
< nThemes
) {
1202 if (strncmp(themes
[i
].filePath
, path
, strlen(path
)) == 0) {
1203 LOG("THEMES Remove theme: %s\n", themes
[i
].filePath
);
1205 free(themes
[i
].name
);
1206 themes
[i
].name
= themes
[nThemes
].name
;
1207 themes
[nThemes
].name
= NULL
;
1208 free(themes
[i
].filePath
);
1209 themes
[i
].filePath
= themes
[nThemes
].filePath
;
1210 themes
[nThemes
].filePath
= NULL
;
1215 thmRebuildGuiNames();
1218 void thmReloadScreenExtents() {
1219 rmGetScreenExtents(&screenWidth
, &screenHeight
);
1222 char* thmGetValue() {
1223 return guiThemesNames
[guiThemeID
];
1226 int thmSetGuiValue(int themeID
, int reload
) {
1227 if (themeID
!= -1) {
1228 if (guiThemeID
!= themeID
|| reload
) {
1230 thmLoad(themes
[themeID
- 1].filePath
);
1234 guiThemeID
= themeID
;
1235 configSetStr(configGetByType(CONFIG_OPL
), "theme", thmGetValue());
1238 else if (guiThemeID
== 0)
1239 thmSetColors(gTheme
);
1244 int thmGetGuiValue() {
1248 int thmFindGuiID(char* theme
) {
1251 for (; i
< nThemes
; i
++) {
1252 if (stricmp(themes
[i
].name
, theme
) == 0)
1259 char **thmGetGuiList() {
1260 return guiThemesNames
;
1267 for (; i
< nThemes
; i
++) {
1268 free(themes
[i
].name
);
1269 free(themes
[i
].filePath
);
1272 free(guiThemesNames
);