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
->currentConfigId
= 0;
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
->currentConfigId
!= config
->uid
) {
176 mutableText
->currentConfigId
= config
->uid
;
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
);
208 static void initAttributeText(char* themePath
, config_set_t
* themeConfig
, theme_t
* theme
, theme_element_t
* elem
, char* name
,
213 snprintf(elemProp
, 64, "%s_attribute", name
);
214 configGetStr(themeConfig
, elemProp
, &attribute
);
216 elem
->extended
= initMutableText(themePath
, themeConfig
, theme
, name
, TYPE_ATTRIBUTE_TEXT
, elem
, attribute
, NULL
, DISPLAY_ALWAYS
, SIZING_NONE
);
217 elem
->endElem
= &endMutableText
;
218 elem
->drawElem
= &drawAttributeText
;
220 LOG("THEMES AttributeText %s: NO attribute, elem disabled !!\n", name
);
223 // Common functions for Image ///////////////////////////////////////////////////////////////////////////////////////////////
225 static void findDuplicate(theme_element_t
* first
, char* cachePattern
, char* defaultTexture
, char* overlayTexture
, mutable_image_t
* target
) {
226 theme_element_t
* elem
= first
;
228 if ((elem
->type
== TYPE_STATIC_IMAGE
) || (elem
->type
== TYPE_ATTRIBUTE_IMAGE
) || (elem
->type
== TYPE_GAME_IMAGE
) || (elem
->type
== TYPE_BACKGROUND
)) {
229 mutable_image_t
* source
= (mutable_image_t
*) elem
->extended
;
231 if (cachePattern
&& source
->cache
&& !strcmp(cachePattern
, source
->cache
->suffix
)) {
232 target
->cache
= source
->cache
;
233 target
->cacheLinked
= 1;
234 LOG("THEMES Re-using a cache for pattern %s\n", cachePattern
);
237 if (defaultTexture
&& source
->defaultTexture
&& !strcmp(defaultTexture
, source
->defaultTexture
->name
)) {
238 target
->defaultTexture
= source
->defaultTexture
;
239 target
->defaultTextureLinked
= 1;
240 LOG("THEMES Re-using the default texture for %s\n", defaultTexture
);
243 if (overlayTexture
&& source
->overlayTexture
&& !strcmp(overlayTexture
, source
->overlayTexture
->name
)) {
244 target
->overlayTexture
= source
->overlayTexture
;
245 target
->overlayTextureLinked
= 1;
246 LOG("THEMES Re-using the overlay texture for %s\n", overlayTexture
);
254 static void freeImageTexture(image_texture_t
* texture
) {
256 if (texture
->source
.Mem
)
257 free(texture
->source
.Mem
);
265 static image_texture_t
* initImageTexture(char* themePath
, config_set_t
* themeConfig
, char* name
, char* imgName
, int isOverlay
) {
266 image_texture_t
* texture
= (image_texture_t
*) malloc(sizeof(image_texture_t
));
267 texPrepare(&texture
->source
, isOverlay
? GS_PSM_CT32
: GS_PSM_CT24
);
268 texture
->name
= NULL
;
271 snprintf(path
, 255, "%s%s", themePath
, imgName
);
272 if (texDiscoverLoad(&texture
->source
, path
, -1, isOverlay
? GS_PSM_CT32
: GS_PSM_CT24
) >= 0) {
273 int length
= strlen(imgName
) + 1;
274 texture
->name
= (char*) malloc(length
* sizeof(char));
275 memcpy(texture
->name
, imgName
, length
);
280 snprintf(elemProp
, 64, "%s_overlay_ulx", name
);
281 if (configGetInt(themeConfig
, elemProp
, &intValue
))
282 texture
->upperLeft_x
= intValue
;
283 snprintf(elemProp
, 64, "%s_overlay_uly", name
);
284 if (configGetInt(themeConfig
, elemProp
, &intValue
))
285 texture
->upperLeft_y
= intValue
;
286 snprintf(elemProp
, 64, "%s_overlay_urx", name
);
287 if (configGetInt(themeConfig
, elemProp
, &intValue
))
288 texture
->upperRight_x
= intValue
;
289 snprintf(elemProp
, 64, "%s_overlay_ury", name
);
290 if (configGetInt(themeConfig
, elemProp
, &intValue
))
291 texture
->upperRight_y
= intValue
;
292 snprintf(elemProp
, 64, "%s_overlay_llx", name
);
293 if (configGetInt(themeConfig
, elemProp
, &intValue
))
294 texture
->lowerLeft_x
= intValue
;
295 snprintf(elemProp
, 64, "%s_overlay_lly", name
);
296 if (configGetInt(themeConfig
, elemProp
, &intValue
))
297 texture
->lowerLeft_y
= intValue
;
298 snprintf(elemProp
, 64, "%s_overlay_lrx", name
);
299 if (configGetInt(themeConfig
, elemProp
, &intValue
))
300 texture
->lowerRight_x
= intValue
;
301 snprintf(elemProp
, 64, "%s_overlay_lry", name
);
302 if (configGetInt(themeConfig
, elemProp
, &intValue
))
303 texture
->lowerRight_y
= intValue
;
306 freeImageTexture(texture
);
313 static void endMutableImage(struct theme_element
* elem
) {
314 mutable_image_t
* mutableImage
= (mutable_image_t
*) elem
->extended
;
316 if (mutableImage
->cache
&& !mutableImage
->cacheLinked
)
317 cacheDestroyCache(mutableImage
->cache
);
319 if (mutableImage
->defaultTexture
&& !mutableImage
->defaultTextureLinked
)
320 freeImageTexture(mutableImage
->defaultTexture
);
322 if (mutableImage
->overlayTexture
&& !mutableImage
->overlayTextureLinked
)
323 freeImageTexture(mutableImage
->overlayTexture
);
331 static mutable_image_t
* initMutableImage(char* themePath
, config_set_t
* themeConfig
, theme_t
* theme
, char* name
, int type
,
332 char* cachePattern
, int cacheCount
, char* defaultTexture
, char* overlayTexture
) {
334 mutable_image_t
* mutableImage
= (mutable_image_t
*) malloc(sizeof(mutable_image_t
));
335 mutableImage
->currentUid
= -1;
336 mutableImage
->currentConfigId
= 0;
337 mutableImage
->currentValue
= NULL
;
338 mutableImage
->cache
= NULL
;
339 mutableImage
->cacheLinked
= 0;
340 mutableImage
->defaultTexture
= NULL
;
341 mutableImage
->defaultTextureLinked
= 0;
342 mutableImage
->overlayTexture
= NULL
;
343 mutableImage
->overlayTextureLinked
= 0;
347 if (type
== TYPE_ATTRIBUTE_IMAGE
) {
348 snprintf(elemProp
, 64, "%s_attribute", name
);
349 configGetStr(themeConfig
, elemProp
, &cachePattern
);
350 LOG("THEMES MutableImage %s: type: %d using cache pattern: %s\n", name
, type
, cachePattern
);
351 } else if ((type
== TYPE_GAME_IMAGE
) || type
== (TYPE_BACKGROUND
)) {
352 snprintf(elemProp
, 64, "%s_pattern", name
);
353 configGetStr(themeConfig
, elemProp
, &cachePattern
);
354 snprintf(elemProp
, 64, "%s_count", name
);
355 configGetInt(themeConfig
, elemProp
, &cacheCount
);
356 LOG("THEMES MutableImage %s: type: %d using cache pattern: %s\n", name
, type
, cachePattern
);
359 snprintf(elemProp
, 64, "%s_default", name
);
360 configGetStr(themeConfig
, elemProp
, &defaultTexture
);
362 if (type
!= TYPE_BACKGROUND
) {
363 snprintf(elemProp
, 64, "%s_overlay", name
);
364 configGetStr(themeConfig
, elemProp
, &overlayTexture
);
367 findDuplicate(theme
->mainElems
.first
, cachePattern
, defaultTexture
, overlayTexture
, mutableImage
);
368 findDuplicate(theme
->infoElems
.first
, cachePattern
, defaultTexture
, overlayTexture
, mutableImage
);
370 if (cachePattern
&& !mutableImage
->cache
) {
371 if (type
== TYPE_ATTRIBUTE_IMAGE
)
372 mutableImage
->cache
= cacheInitCache(-1, themePath
, 0, cachePattern
, 1);
374 mutableImage
->cache
= cacheInitCache(theme
->gameCacheCount
++, "ART", 1, cachePattern
, cacheCount
);
377 if (defaultTexture
&& !mutableImage
->defaultTexture
)
378 mutableImage
->defaultTexture
= initImageTexture(themePath
, themeConfig
, name
, defaultTexture
, 0);
380 if (overlayTexture
&& !mutableImage
->overlayTexture
)
381 mutableImage
->overlayTexture
= initImageTexture(themePath
, themeConfig
, name
, overlayTexture
, 1);
386 // StaticImage //////////////////////////////////////////////////////////////////////////////////////////////////////////////
388 static void drawStaticImage(struct menu_list
* menu
, struct submenu_list
* item
, config_set_t
* config
, struct theme_element
* elem
) {
389 mutable_image_t
* staticImage
= (mutable_image_t
*) elem
->extended
;
390 if (staticImage
->overlayTexture
) {
391 rmDrawOverlayPixmap(&staticImage
->overlayTexture
->source
, elem
->posX
, elem
->posY
, elem
->aligned
, elem
->width
, elem
->height
, elem
->scaled
, gDefaultCol
,
392 &staticImage
->defaultTexture
->source
, staticImage
->overlayTexture
->upperLeft_x
, staticImage
->overlayTexture
->upperLeft_y
, staticImage
->overlayTexture
->upperRight_x
, staticImage
->overlayTexture
->upperRight_y
,
393 staticImage
->overlayTexture
->lowerLeft_x
, staticImage
->overlayTexture
->lowerLeft_y
, staticImage
->overlayTexture
->lowerRight_x
, staticImage
->overlayTexture
->lowerRight_y
);
395 rmDrawPixmap(&staticImage
->defaultTexture
->source
, elem
->posX
, elem
->posY
, elem
->aligned
, elem
->width
, elem
->height
, elem
->scaled
, gDefaultCol
);
398 static void initStaticImage(char* themePath
, config_set_t
* themeConfig
, theme_t
* theme
, theme_element_t
* elem
, char* name
,
401 mutable_image_t
* mutableImage
= initMutableImage(themePath
, themeConfig
, theme
, name
, elem
->type
, NULL
, 0, imageName
, NULL
);
402 elem
->extended
= mutableImage
;
403 elem
->endElem
= &endMutableImage
;
405 if (mutableImage
->defaultTexture
)
406 elem
->drawElem
= &drawStaticImage
;
408 LOG("THEMES StaticImage %s: NO image name, elem disabled !!\n", name
);
411 // GameImage ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
413 static GSTEXTURE
* getGameImageTexture(image_cache_t
* cache
, void* support
, struct submenu_item
* item
) {
415 item_list_t
* list
= (item_list_t
*) support
;
416 char* startup
= list
->itemGetStartup(item
->id
);
417 return cacheGetTexture(cache
, list
, &item
->cache_id
[cache
->userId
], &item
->cache_uid
[cache
->userId
], startup
);
423 static void drawGameImage(struct menu_list
* menu
, struct submenu_list
* item
, config_set_t
* config
, struct theme_element
* elem
) {
424 mutable_image_t
* gameImage
= (mutable_image_t
*) elem
->extended
;
426 GSTEXTURE
* texture
= getGameImageTexture(gameImage
->cache
, menu
->item
->userdata
, &item
->item
);
427 if (!texture
|| !texture
->Mem
) {
428 if (gameImage
->defaultTexture
)
429 texture
= &gameImage
->defaultTexture
->source
;
431 if (elem
->type
== TYPE_BACKGROUND
)
437 if (gameImage
->overlayTexture
) {
438 rmDrawOverlayPixmap(&gameImage
->overlayTexture
->source
, elem
->posX
, elem
->posY
, elem
->aligned
, elem
->width
, elem
->height
, elem
->scaled
, gDefaultCol
,
439 texture
, gameImage
->overlayTexture
->upperLeft_x
, gameImage
->overlayTexture
->upperLeft_y
, gameImage
->overlayTexture
->upperRight_x
, gameImage
->overlayTexture
->upperRight_y
,
440 gameImage
->overlayTexture
->lowerLeft_x
, gameImage
->overlayTexture
->lowerLeft_y
, gameImage
->overlayTexture
->lowerRight_x
, gameImage
->overlayTexture
->lowerRight_y
);
442 rmDrawPixmap(texture
, elem
->posX
, elem
->posY
, elem
->aligned
, elem
->width
, elem
->height
, elem
->scaled
, gDefaultCol
);
444 } else if (elem
->type
== TYPE_BACKGROUND
) {
445 if (gameImage
->defaultTexture
)
446 rmDrawPixmap(&gameImage
->defaultTexture
->source
, elem
->posX
, elem
->posY
, elem
->aligned
, elem
->width
, elem
->height
, elem
->scaled
, gDefaultCol
);
452 static void initGameImage(char* themePath
, config_set_t
* themeConfig
, theme_t
* theme
, theme_element_t
* elem
, char* name
,
453 char* pattern
, int count
, char* texture
, char* overlay
) {
455 mutable_image_t
* mutableImage
= initMutableImage(themePath
, themeConfig
, theme
, name
, elem
->type
, pattern
, count
, texture
, overlay
);
456 elem
->extended
= mutableImage
;
457 elem
->endElem
= &endMutableImage
;
459 if (mutableImage
->cache
)
460 elem
->drawElem
= &drawGameImage
;
462 LOG("THEMES GameImage %s: NO pattern, elem disabled !!\n", name
);
465 // AttributeImage ///////////////////////////////////////////////////////////////////////////////////////////////////////////
467 static void drawAttributeImage(struct menu_list
* menu
, struct submenu_list
* item
, config_set_t
* config
, struct theme_element
* elem
) {
468 mutable_image_t
* attributeImage
= (mutable_image_t
*) elem
->extended
;
470 if (attributeImage
->currentConfigId
!= config
->uid
) {
472 attributeImage
->currentUid
= -1;
473 attributeImage
->currentConfigId
= config
->uid
;
474 attributeImage
->currentValue
= NULL
;
475 configGetStr(config
, attributeImage
->cache
->suffix
, &attributeImage
->currentValue
);
477 if (attributeImage
->currentValue
) {
479 GSTEXTURE
* texture
= cacheGetTexture(attributeImage
->cache
, menu
->item
->userdata
, &posZ
, &attributeImage
->currentUid
, attributeImage
->currentValue
);
480 if (texture
&& texture
->Mem
) {
481 if (attributeImage
->overlayTexture
) {
482 rmDrawOverlayPixmap(&attributeImage
->overlayTexture
->source
, elem
->posX
, elem
->posY
, elem
->aligned
, elem
->width
, elem
->height
, elem
->scaled
, gDefaultCol
,
483 texture
, attributeImage
->overlayTexture
->upperLeft_x
, attributeImage
->overlayTexture
->upperLeft_y
, attributeImage
->overlayTexture
->upperRight_x
, attributeImage
->overlayTexture
->upperRight_y
,
484 attributeImage
->overlayTexture
->lowerLeft_x
, attributeImage
->overlayTexture
->lowerLeft_y
, attributeImage
->overlayTexture
->lowerRight_x
, attributeImage
->overlayTexture
->lowerRight_y
);
486 rmDrawPixmap(texture
, elem
->posX
, elem
->posY
, elem
->aligned
, elem
->width
, elem
->height
, elem
->scaled
, gDefaultCol
);
492 if (attributeImage
->defaultTexture
)
493 rmDrawPixmap(&attributeImage
->defaultTexture
->source
, elem
->posX
, elem
->posY
, elem
->aligned
, elem
->width
, elem
->height
, elem
->scaled
, gDefaultCol
);
496 static void initAttributeImage(char* themePath
, config_set_t
* themeConfig
, theme_t
* theme
, theme_element_t
* elem
, char* name
) {
497 mutable_image_t
* mutableImage
= initMutableImage(themePath
, themeConfig
, theme
, name
, elem
->type
, NULL
, 1, NULL
, NULL
);
498 elem
->extended
= mutableImage
;
499 elem
->endElem
= &endMutableImage
;
501 if (mutableImage
->cache
)
502 elem
->drawElem
= &drawAttributeImage
;
504 LOG("THEMES AttributeImage %s: NO attribute, elem disabled !!\n", name
);
507 // BasicElement /////////////////////////////////////////////////////////////////////////////////////////////////////////////
509 static void endBasic(theme_element_t
* elem
) {
511 free(elem
->extended
);
516 static theme_element_t
* initBasic(char* themePath
, config_set_t
* themeConfig
, theme_t
* theme
,
517 char* name
, int type
, int x
, int y
, short aligned
, int w
, int h
, short scaled
, u64 color
, int font
) {
520 unsigned char charColor
[3];
524 theme_element_t
* elem
= (theme_element_t
*) malloc(sizeof(theme_element_t
));
527 elem
->extended
= NULL
;
528 elem
->drawElem
= NULL
;
529 elem
->endElem
= &endBasic
;
532 snprintf(elemProp
, 64, "%s_x", name
);
533 if (configGetStr(themeConfig
, elemProp
, &temp
)) {
534 if (!strncmp(temp
, "POS_MID", 7))
535 x
= screenWidth
>> 1;
540 elem
->posX
= screenWidth
+ x
;
544 snprintf(elemProp
, 64, "%s_y", name
);
545 if (configGetStr(themeConfig
, elemProp
, &temp
)) {
546 if (!strncmp(temp
, "POS_MID", 7))
547 y
= screenHeight
>> 1;
552 elem
->posY
= ceil((screenHeight
+ y
) * theme
->usedHeight
/ screenHeight
);
556 snprintf(elemProp
, 64, "%s_width", name
);
557 if (configGetStr(themeConfig
, elemProp
, &temp
)) {
558 if (!strncmp(temp
, "DIM_INF", 7))
559 elem
->width
= screenWidth
;
561 elem
->width
= atoi(temp
);
565 snprintf(elemProp
, 64, "%s_height", name
);
566 if (configGetStr(themeConfig
, elemProp
, &temp
)) {
567 if (!strncmp(temp
, "DIM_INF", 7))
568 elem
->height
= screenHeight
;
570 elem
->height
= atoi(temp
);
574 snprintf(elemProp
, 64, "%s_aligned", name
);
575 if (configGetInt(themeConfig
, elemProp
, &intValue
))
576 elem
->aligned
= intValue
;
578 elem
->aligned
= aligned
;
580 snprintf(elemProp
, 64, "%s_scaled", name
);
581 if (configGetInt(themeConfig
, elemProp
, &intValue
))
582 elem
->scaled
= intValue
;
584 elem
->scaled
= scaled
;
586 snprintf(elemProp
, 64, "%s_color", name
);
587 if (configGetColor(themeConfig
, elemProp
, charColor
))
588 elem
->color
= GS_SETREG_RGBA(charColor
[0], charColor
[1], charColor
[2], 0xff);
592 snprintf(elemProp
, 64, "%s_font", name
);
593 if (configGetInt(themeConfig
, elemProp
, &intValue
))
595 if (font
>= 0 && font
< THM_MAX_FONTS
)
596 elem
->font
= theme
->fonts
[font
];
598 elem
->font
= FNT_DEFAULT
;
603 // Internal elements ////////////////////////////////////////////////////////////////////////////////////////////////////////
605 static void drawBackground(struct menu_list
* menu
, struct submenu_list
* item
, config_set_t
* config
, struct theme_element
* elem
) {
609 static void initBackground(char* themePath
, config_set_t
* themeConfig
, theme_t
* theme
, theme_element_t
* elem
, char* name
,
610 char* pattern
, int count
, char* texture
) {
612 mutable_image_t
* mutableImage
= initMutableImage(themePath
, themeConfig
, theme
, name
, elem
->type
, pattern
, count
, texture
, NULL
);
613 elem
->extended
= mutableImage
;
614 elem
->endElem
= &endMutableImage
;
616 if (mutableImage
->cache
)
617 elem
->drawElem
= &drawGameImage
;
618 else if (mutableImage
->defaultTexture
)
619 elem
->drawElem
= &drawStaticImage
;
621 elem
->drawElem
= &drawBackground
;
624 static void drawMenuIcon(struct menu_list
* menu
, struct submenu_list
* item
, config_set_t
* config
, struct theme_element
* elem
) {
625 GSTEXTURE
* menuIconTex
= thmGetTexture(menu
->item
->icon_id
);
626 if (menuIconTex
&& menuIconTex
->Mem
)
627 rmDrawPixmap(menuIconTex
, elem
->posX
, elem
->posY
, elem
->aligned
, elem
->width
, elem
->height
, elem
->scaled
, gDefaultCol
);
630 static void drawMenuText(struct menu_list
* menu
, struct submenu_list
* item
, config_set_t
* config
, struct theme_element
* elem
) {
631 GSTEXTURE
* leftIconTex
= NULL
, *rightIconTex
= NULL
;
633 leftIconTex
= thmGetTexture(LEFT_ICON
);
635 rightIconTex
= thmGetTexture(RIGHT_ICON
);
638 int offset
= elem
->width
>> 1;
639 if (leftIconTex
&& leftIconTex
->Mem
)
640 rmDrawPixmap(leftIconTex
, elem
->posX
- offset
, elem
->posY
, elem
->aligned
, leftIconTex
->Width
, leftIconTex
->Height
, elem
->scaled
, gDefaultCol
);
641 if (rightIconTex
&& rightIconTex
->Mem
)
642 rmDrawPixmap(rightIconTex
, elem
->posX
+ offset
, elem
->posY
, elem
->aligned
, rightIconTex
->Width
, rightIconTex
->Height
, elem
->scaled
, gDefaultCol
);
645 if (leftIconTex
&& leftIconTex
->Mem
)
646 rmDrawPixmap(leftIconTex
, elem
->posX
- leftIconTex
->Width
, elem
->posY
, elem
->aligned
, leftIconTex
->Width
, leftIconTex
->Height
, elem
->scaled
, gDefaultCol
);
647 if (rightIconTex
&& rightIconTex
->Mem
)
648 rmDrawPixmap(rightIconTex
, elem
->posX
+ elem
->width
, elem
->posY
, elem
->aligned
, rightIconTex
->Width
, rightIconTex
->Height
, elem
->scaled
, gDefaultCol
);
650 fntRenderString(elem
->font
, elem
->posX
, elem
->posY
, elem
->aligned
, 0, 0, menuItemGetText(menu
->item
), elem
->color
);
653 static void drawItemsList(struct menu_list
* menu
, struct submenu_list
* item
, config_set_t
* config
, struct theme_element
* elem
) {
655 items_list_t
* itemsList
= (items_list_t
*) elem
->extended
;
657 int posX
= elem
->posX
, posY
= elem
->posY
;
659 posX
-= elem
->width
>> 1;
660 posY
-= elem
->height
>> 1;
663 submenu_list_t
*ps
= menu
->item
->pagestart
;
666 while (ps
&& (others
++ < itemsList
->displayedItems
)) {
668 color
= gTheme
->selTextColor
;
672 if (itemsList
->decoratorImage
) {
673 GSTEXTURE
* itemIconTex
= getGameImageTexture(itemsList
->decoratorImage
->cache
, menu
->item
->userdata
, &ps
->item
);
674 if (itemIconTex
&& itemIconTex
->Mem
)
675 rmDrawPixmap(itemIconTex
, posX
, posY
, ALIGN_NONE
, DECORATOR_SIZE
, DECORATOR_SIZE
, elem
->scaled
, gDefaultCol
);
677 if (itemsList
->decoratorImage
->defaultTexture
)
678 rmDrawPixmap(&itemsList
->decoratorImage
->defaultTexture
->source
, posX
, posY
, ALIGN_NONE
, DECORATOR_SIZE
, DECORATOR_SIZE
, elem
->scaled
, gDefaultCol
);
680 fntRenderString(elem
->font
, posX
+ DECORATOR_SIZE
, posY
, ALIGN_NONE
, elem
->width
, elem
->height
, submenuItemGetText(&ps
->item
), color
);
682 fntRenderString(elem
->font
, posX
, posY
, ALIGN_NONE
, elem
->width
, elem
->height
, submenuItemGetText(&ps
->item
), color
);
684 posY
+= MENU_ITEM_HEIGHT
;
690 static void initItemsList(char* themePath
, config_set_t
* themeConfig
, theme_t
* theme
, theme_element_t
* elem
, char* name
, char* decorator
) {
693 items_list_t
* itemsList
= (items_list_t
*) malloc(sizeof(items_list_t
));
695 if (elem
->width
== DIM_UNDEF
)
696 elem
->width
= screenWidth
;
698 if (elem
->height
== DIM_UNDEF
)
699 elem
->height
= theme
->usedHeight
- (MENU_POS_V
+ HINT_HEIGHT
);
701 itemsList
->displayedItems
= elem
->height
/ MENU_ITEM_HEIGHT
;
702 LOG("THEMES ItemsList %s: displaying %d elems, item height: %d\n", name
, itemsList
->displayedItems
, elem
->height
);
704 itemsList
->decorator
= NULL
;
705 snprintf(elemProp
, 64, "%s_decorator", name
);
706 configGetStr(themeConfig
, elemProp
, &decorator
);
708 itemsList
->decorator
= decorator
; // Will be used later (thmValidate)
710 itemsList
->decoratorImage
= NULL
;
712 elem
->extended
= itemsList
;
713 // elem->endElem = &endBasic; does the job
715 elem
->drawElem
= &drawItemsList
;
718 static void drawItemText(struct menu_list
* menu
, struct submenu_list
* item
, config_set_t
* config
, struct theme_element
* elem
) {
720 item_list_t
*support
= menu
->item
->userdata
;
721 fntRenderString(elem
->font
, elem
->posX
, elem
->posY
, elem
->aligned
, 0, 0, support
->itemGetStartup(item
->item
.id
), elem
->color
);
725 static void drawHintText(struct menu_list
* menu
, struct submenu_list
* item
, config_set_t
* config
, struct theme_element
* elem
) {
726 menu_hint_item_t
* hint
= menu
->item
->hints
;
730 for (; hint
; hint
= hint
->next
) {
731 x
= guiDrawIconAndText(hint
->icon_id
, hint
->text_id
, elem
->font
, x
, elem
->posY
, elem
->color
);
737 static void drawInfoHintText(struct menu_list
* menu
, struct submenu_list
* item
, config_set_t
* config
, struct theme_element
* elem
) {
739 x
= guiDrawIconAndText(CROSS_ICON
, _STR_RUN
, elem
->font
, x
, elem
->posY
, elem
->color
);
741 x
= guiDrawIconAndText(CIRCLE_ICON
, _STR_O_BACK
, elem
->font
, x
, elem
->posY
, elem
->color
);
744 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
746 static void validateGUIElems(char* themePath
, config_set_t
* themeConfig
, theme_t
* theme
) {
747 // 1. check we have a valid Background elements
748 if ( !theme
->mainElems
.first
|| (theme
->mainElems
.first
->type
!= TYPE_BACKGROUND
) ) {
749 LOG("THEMES No valid background found for main, add default BG_ART\n");
750 theme_element_t
* backgroundElem
= initBasic(themePath
, themeConfig
, theme
, "bg", TYPE_BACKGROUND
, 0, 0, ALIGN_NONE
, screenWidth
, screenHeight
, SCALING_NONE
, gDefaultCol
, FNT_DEFAULT
);
752 initBackground(themePath
, themeConfig
, theme
, backgroundElem
, "bg", "BG", 1, "background");
754 initBackground(themePath
, themeConfig
, theme
, backgroundElem
, "bg", "BG", 1, NULL
);
755 backgroundElem
->next
= theme
->mainElems
.first
;
756 theme
->mainElems
.first
= backgroundElem
;
759 if (theme
->infoElems
.first
) {
760 if (theme
->infoElems
.first
->type
!= TYPE_BACKGROUND
) {
761 LOG("THEMES No valid background found for info, add default BG_ART\n");
762 theme_element_t
* backgroundElem
= initBasic(themePath
, themeConfig
, theme
, "bg", TYPE_BACKGROUND
, 0, 0, ALIGN_NONE
, screenWidth
, screenHeight
, SCALING_NONE
, gDefaultCol
, FNT_DEFAULT
);
764 initBackground(themePath
, themeConfig
, theme
, backgroundElem
, "bg", "BG", 1, "background");
766 initBackground(themePath
, themeConfig
, theme
, backgroundElem
, "bg", "BG", 1, NULL
);
767 backgroundElem
->next
= theme
->infoElems
.first
;
768 theme
->infoElems
.first
= backgroundElem
;
772 // 2. check we have a valid ItemsList element, and link its decorator to the target element
773 if (theme
->itemsList
) {
774 items_list_t
* itemsList
= (items_list_t
*) theme
->itemsList
->extended
;
775 if (itemsList
->decorator
) {
776 // Second pass to find the decorator
777 theme_element_t
* decoratorElem
= theme
->mainElems
.first
;
778 while (decoratorElem
) {
779 if (decoratorElem
->type
== TYPE_GAME_IMAGE
) {
780 mutable_image_t
* gameImage
= (mutable_image_t
*) decoratorElem
->extended
;
781 if (!strcmp(itemsList
->decorator
, gameImage
->cache
->suffix
)) {
782 // if user want to cache less than displayed items, then disable itemslist icons, if not would load constantly
783 if (gameImage
->cache
->count
>= itemsList
->displayedItems
)
784 itemsList
->decoratorImage
= gameImage
;
789 decoratorElem
= decoratorElem
->next
;
791 itemsList
->decorator
= NULL
;
794 LOG("THEMES No itemsList found, adding a default one\n");
795 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
);
796 initItemsList(themePath
, themeConfig
, theme
, theme
->itemsList
, "il", NULL
);
797 theme
->itemsList
->next
= theme
->mainElems
.first
->next
; // Position the itemsList as second element (right after the Background)
798 theme
->mainElems
.first
->next
= theme
->itemsList
;
802 static int addGUIElem(char* themePath
, config_set_t
* themeConfig
, theme_t
* theme
, theme_elems_t
* elems
, char* type
, char* name
) {
806 theme_element_t
* elem
= NULL
;
808 snprintf(elemProp
, 64, "%s_enabled", name
);
809 configGetInt(themeConfig
, elemProp
, &enabled
);
812 snprintf(elemProp
, 64, "%s_type", name
);
813 configGetStr(themeConfig
, elemProp
, &type
);
815 if (!strcmp(elementsType
[TYPE_ATTRIBUTE_TEXT
], type
)) {
816 elem
= initBasic(themePath
, themeConfig
, theme
, name
, TYPE_ATTRIBUTE_TEXT
, 0, 0, ALIGN_CENTER
, DIM_UNDEF
, DIM_UNDEF
, SCALING_RATIO
, theme
->textColor
, FNT_DEFAULT
);
817 initAttributeText(themePath
, themeConfig
, theme
, elem
, name
, NULL
);
818 } else if (!strcmp(elementsType
[TYPE_STATIC_TEXT
], type
)) {
819 elem
= initBasic(themePath
, themeConfig
, theme
, name
, TYPE_STATIC_TEXT
, 0, 0, ALIGN_CENTER
, DIM_UNDEF
, DIM_UNDEF
, SCALING_RATIO
, theme
->textColor
, FNT_DEFAULT
);
820 initStaticText(themePath
, themeConfig
, theme
, elem
, name
, NULL
);
821 } else if (!strcmp(elementsType
[TYPE_ATTRIBUTE_IMAGE
], type
)) {
822 elem
= initBasic(themePath
, themeConfig
, theme
, name
, TYPE_ATTRIBUTE_IMAGE
, 0, 0, ALIGN_CENTER
, DIM_UNDEF
, DIM_UNDEF
, SCALING_RATIO
, gDefaultCol
, FNT_DEFAULT
);
823 initAttributeImage(themePath
, themeConfig
, theme
, elem
, name
);
824 } else if (!strcmp(elementsType
[TYPE_GAME_IMAGE
], type
)) {
825 elem
= initBasic(themePath
, themeConfig
, theme
, name
, TYPE_GAME_IMAGE
, 0, 0, ALIGN_CENTER
, DIM_UNDEF
, DIM_UNDEF
, SCALING_RATIO
, gDefaultCol
, FNT_DEFAULT
);
826 initGameImage(themePath
, themeConfig
, theme
, elem
, name
, NULL
, 1, NULL
, NULL
);
827 } else if (!strcmp(elementsType
[TYPE_STATIC_IMAGE
], type
)) {
828 elem
= initBasic(themePath
, themeConfig
, theme
, name
, TYPE_STATIC_IMAGE
, 0, 0, ALIGN_CENTER
, DIM_UNDEF
, DIM_UNDEF
, SCALING_RATIO
, gDefaultCol
, FNT_DEFAULT
);
829 initStaticImage(themePath
, themeConfig
, theme
, elem
, name
, NULL
);
830 } else if (!strcmp(elementsType
[TYPE_BACKGROUND
], type
)) {
831 if (!elems
->first
) { // Background elem can only be the first one
832 elem
= initBasic(themePath
, themeConfig
, theme
, name
, TYPE_BACKGROUND
, 0, 0, ALIGN_NONE
, screenWidth
, screenHeight
, SCALING_NONE
, gDefaultCol
, FNT_DEFAULT
);
833 initBackground(themePath
, themeConfig
, theme
, elem
, name
, NULL
, 1, NULL
);
835 } else if (!strcmp(elementsType
[TYPE_MENU_ICON
], type
)) {
836 elem
= initBasic(themePath
, themeConfig
, theme
, name
, TYPE_MENU_ICON
, 40, 40, ALIGN_CENTER
, DIM_UNDEF
, DIM_UNDEF
, SCALING_RATIO
, gDefaultCol
, FNT_DEFAULT
);
837 elem
->drawElem
= &drawMenuIcon
;
838 } else if (!strcmp(elementsType
[TYPE_MENU_TEXT
], type
)) {
839 elem
= initBasic(themePath
, themeConfig
, theme
, name
, TYPE_MENU_TEXT
, screenWidth
>> 1, 20, ALIGN_CENTER
, 200, 20, SCALING_RATIO
, theme
->textColor
, FNT_DEFAULT
);
840 elem
->drawElem
= &drawMenuText
;
841 } else if (!strcmp(elementsType
[TYPE_ITEMS_LIST
], type
)) {
842 if (!theme
->itemsList
) {
843 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
);
844 initItemsList(themePath
, themeConfig
, theme
, elem
, name
, NULL
);
845 theme
->itemsList
= elem
;
847 } else if (!strcmp(elementsType
[TYPE_ITEM_ICON
], type
)) {
848 elem
= initBasic(themePath
, themeConfig
, theme
, name
, TYPE_GAME_IMAGE
, 80, theme
->usedHeight
>> 1, ALIGN_CENTER
, DIM_UNDEF
, DIM_UNDEF
, SCALING_RATIO
, gDefaultCol
, FNT_DEFAULT
);
849 initGameImage(themePath
, themeConfig
, theme
, elem
, name
, "ICO", 20, NULL
, NULL
);
850 } else if (!strcmp(elementsType
[TYPE_ITEM_COVER
], type
)) {
851 elem
= initBasic(themePath
, themeConfig
, theme
, name
, TYPE_GAME_IMAGE
, 520, theme
->usedHeight
>> 1, ALIGN_CENTER
, DIM_UNDEF
, DIM_UNDEF
, SCALING_RATIO
, gDefaultCol
, FNT_DEFAULT
);
852 initGameImage(themePath
, themeConfig
, theme
, elem
, name
, "COV", 10, NULL
, NULL
);
853 } else if (!strcmp(elementsType
[TYPE_ITEM_TEXT
], type
)) {
854 elem
= initBasic(themePath
, themeConfig
, theme
, name
, TYPE_ITEM_TEXT
, 520, 370, ALIGN_CENTER
, DIM_UNDEF
, DIM_UNDEF
, SCALING_RATIO
, theme
->textColor
, FNT_DEFAULT
);
855 elem
->drawElem
= &drawItemText
;
856 } else if (!strcmp(elementsType
[TYPE_HINT_TEXT
], type
)) {
857 elem
= initBasic(themePath
, themeConfig
, theme
, name
, TYPE_HINT_TEXT
, 16, -HINT_HEIGHT
, ALIGN_NONE
, 12, 20, SCALING_RATIO
, theme
->textColor
, FNT_DEFAULT
);
858 elem
->drawElem
= &drawHintText
;
859 } else if (!strcmp(elementsType
[TYPE_INFO_HINT_TEXT
], type
)) {
860 elem
= initBasic(themePath
, themeConfig
, theme
, name
, TYPE_INFO_HINT_TEXT
, 16, -HINT_HEIGHT
, ALIGN_NONE
, 12, 20, SCALING_RATIO
, theme
->textColor
, FNT_DEFAULT
);
861 elem
->drawElem
= &drawInfoHintText
;
862 } else if (!strcmp(elementsType
[TYPE_LOADING_ICON
], type
)) {
863 if (!theme
->loadingIcon
)
864 theme
->loadingIcon
= initBasic(themePath
, themeConfig
, theme
, name
, TYPE_LOADING_ICON
, -50, -50, ALIGN_CENTER
, DIM_UNDEF
, DIM_UNDEF
, SCALING_RATIO
, gDefaultCol
, FNT_DEFAULT
);
874 elems
->last
->next
= elem
;
879 return 0; // ends the reading of elements
885 static void freeGUIElems(theme_elems_t
* elems
) {
886 theme_element_t
* elem
= elems
->first
;
888 elems
->first
= elem
->next
;
894 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
895 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
897 GSTEXTURE
* thmGetTexture(unsigned int id
) {
898 if (id
>= TEXTURES_COUNT
)
901 // see if the texture is valid
902 GSTEXTURE
* txt
= &gTheme
->textures
[id
];
911 static void thmFree(theme_t
* theme
) {
914 freeGUIElems(&theme
->mainElems
);
915 freeGUIElems(&theme
->infoElems
);
920 for(; id
< TEXTURES_COUNT
; id
++) {
921 texture
= &theme
->textures
[id
];
922 if (texture
->Mem
!= NULL
) {
929 for (id
= 0; id
< THM_MAX_FONTS
; ++id
) {
930 int fntid
= theme
->fonts
[id
];
932 if (fntid
!= FNT_DEFAULT
)
941 static int thmReadEntry(int index
, char* path
, char* separator
, char* name
, unsigned int mode
) {
942 if (FIO_SO_ISDIR(mode
) && strstr(name
, "thm_")) {
943 theme_file_t
* currTheme
= &themes
[nThemes
+ index
];
945 int length
= strlen(name
) - 4 + 1;
946 currTheme
->name
= (char*) malloc(length
* sizeof(char));
947 memcpy(currTheme
->name
, name
+ 4, length
);
948 currTheme
->name
[length
- 1] = '\0';
950 length
= strlen(path
) + 1 + strlen(name
) + 1 + 1;
951 currTheme
->filePath
= (char*) malloc(length
* sizeof(char));
952 sprintf(currTheme
->filePath
, "%s%s%s%s", path
, separator
, name
, separator
);
954 LOG("THEMES Theme found: %s\n", currTheme
->filePath
);
961 /* themePath must contains the leading separator (as it is dependent of the device, we can't know here) */
962 static int thmLoadResource(int texId
, char* themePath
, short psm
, int useDefault
) {
964 GSTEXTURE
* texture
= &gTheme
->textures
[texId
];
966 if (themePath
!= NULL
)
967 success
= texDiscoverLoad(texture
, themePath
, texId
, psm
); // only set success here
969 if ((success
< 0) && useDefault
)
970 texPngLoad(texture
, NULL
, texId
, psm
); // we don't mind the result of "default"
975 static void thmSetColors(theme_t
* theme
) {
976 memcpy(theme
->bgColor
, gDefaultBgColor
, 3);
977 theme
->textColor
= GS_SETREG_RGBA(gDefaultTextColor
[0], gDefaultTextColor
[1], gDefaultTextColor
[2], 0xff);
978 theme
->uiTextColor
= GS_SETREG_RGBA(gDefaultUITextColor
[0], gDefaultUITextColor
[1], gDefaultUITextColor
[2], 0xff);
979 theme
->selTextColor
= GS_SETREG_RGBA(gDefaultSelTextColor
[0], gDefaultSelTextColor
[1], gDefaultSelTextColor
[2], 0xff);
981 theme_element_t
* elem
= theme
->mainElems
.first
;
983 elem
->color
= theme
->textColor
;
988 static void thmLoadFonts(config_set_t
* themeConfig
, const char* themePath
, theme_t
* theme
) {
989 int fntID
; // theme side font id, not the fntSys handle
990 for (fntID
= -1; fntID
< THM_MAX_FONTS
; ++fntID
) {
991 // does the font by the key exist?
994 // -1 is a placeholder for default font...
996 // Default font handle...
997 theme
->fonts
[fntID
] = FNT_DEFAULT
;
998 snprintf(fntKey
, 16, "font%d", fntID
);
1000 snprintf(fntKey
, 16, "default_font");
1004 int cfgKeyOK
= configGetStr(themeConfig
, fntKey
, &fntFile
);
1005 if (!cfgKeyOK
&& (fntID
>= 0))
1011 // replace the default font
1013 snprintf(fullPath
, 128, "%s%s", themePath
, fntFile
);
1016 void* customFont
= readFile(fullPath
, -1, &size
);
1019 fntReplace(FNT_DEFAULT
, customFont
, size
, 1, 0);
1021 // TODO reload the language font file
1022 fntSetDefault(FNT_DEFAULT
);
1025 snprintf(fullPath
, 128, "%s%s", themePath
, fntFile
);
1026 int fntHandle
= fntLoadFile(fullPath
);
1028 // Do we have a valid font? Assign the font handle to the theme font slot
1029 if (fntHandle
!= FNT_ERROR
)
1030 theme
->fonts
[fntID
] = fntHandle
;
1035 static void thmLoad(char* themePath
) {
1036 LOG("THEMES Load theme path=%s\n", themePath
);
1037 theme_t
* curT
= gTheme
;
1038 theme_t
* newT
= (theme_t
*) malloc(sizeof(theme_t
));
1039 memset(newT
, 0, sizeof(theme_t
));
1041 newT
->useDefault
= 1;
1042 newT
->usedHeight
= 480;
1044 newT
->mainElems
.first
= NULL
;
1045 newT
->mainElems
.last
= NULL
;
1046 newT
->infoElems
.first
= NULL
;
1047 newT
->infoElems
.last
= NULL
;
1048 newT
->gameCacheCount
= 0;
1049 newT
->itemsList
= NULL
;
1050 newT
->loadingIcon
= NULL
;
1051 newT
->loadingIconCount
= LOAD7_ICON
- LOAD0_ICON
+ 1;
1053 config_set_t
* themeConfig
= NULL
;
1055 themeConfig
= configAlloc(0, NULL
, NULL
);
1056 addGUIElem(themePath
, themeConfig
, newT
, &newT
->mainElems
, elementsType
[TYPE_MENU_ICON
], "_");
1057 addGUIElem(themePath
, themeConfig
, newT
, &newT
->mainElems
, elementsType
[TYPE_MENU_TEXT
], "_");
1058 addGUIElem(themePath
, themeConfig
, newT
, &newT
->mainElems
, elementsType
[TYPE_ITEMS_LIST
], "_");
1059 addGUIElem(themePath
, themeConfig
, newT
, &newT
->mainElems
, elementsType
[TYPE_ITEM_ICON
], "_");
1060 addGUIElem(themePath
, themeConfig
, newT
, &newT
->mainElems
, elementsType
[TYPE_ITEM_COVER
], "_");
1061 addGUIElem(themePath
, themeConfig
, newT
, &newT
->mainElems
, elementsType
[TYPE_ITEM_TEXT
], "_");
1062 addGUIElem(themePath
, themeConfig
, newT
, &newT
->mainElems
, elementsType
[TYPE_HINT_TEXT
], "_");
1063 addGUIElem(themePath
, themeConfig
, newT
, &newT
->mainElems
, elementsType
[TYPE_LOADING_ICON
], "_");
1065 // reset the default font to be sure
1066 fntSetDefault(FNT_DEFAULT
);
1069 snprintf(path
, 255, "%sconf_theme.cfg", themePath
);
1070 themeConfig
= configAlloc(0, NULL
, path
);
1071 configRead(themeConfig
); // try to load the theme config file
1074 if (configGetInt(themeConfig
, "use_default", &intValue
))
1075 newT
->useDefault
= intValue
;
1077 if (configGetInt(themeConfig
, "use_real_height", &intValue
)) {
1079 newT
->usedHeight
= screenHeight
;
1082 configGetColor(themeConfig
, "bg_color", newT
->bgColor
);
1084 unsigned char color
[3];
1085 if (configGetColor(themeConfig
, "text_color", color
))
1086 newT
->textColor
= GS_SETREG_RGBA(color
[0], color
[1], color
[2], 0xff);
1088 if (configGetColor(themeConfig
, "ui_text_color", color
))
1089 newT
->uiTextColor
= GS_SETREG_RGBA(color
[0], color
[1], color
[2], 0xff);
1091 if (configGetColor(themeConfig
, "sel_text_color", color
))
1092 newT
->selTextColor
= GS_SETREG_RGBA(color
[0], color
[1], color
[2], 0xff);
1094 // before loading the element definitions, we have to have the fonts prepared
1095 // for that, we load the fonts and a translation table
1096 thmLoadFonts(themeConfig
, themePath
, newT
);
1099 snprintf(path
, 255, "main0");
1100 while (addGUIElem(themePath
, themeConfig
, newT
, &newT
->mainElems
, NULL
, path
))
1101 snprintf(path
, 255, "main%d", i
++);
1104 snprintf(path
, 255, "info0");
1105 while(addGUIElem(themePath
, themeConfig
, newT
, &newT
->infoElems
, NULL
, path
))
1106 snprintf(path
, 255, "info%d", i
++);
1109 validateGUIElems(themePath
, themeConfig
, newT
);
1110 configFree(themeConfig
);
1112 LOG("THEMES Number of cache: %d\n", newT
->gameCacheCount
);
1113 LOG("THEMES Used height: %d\n", newT
->usedHeight
);
1115 /// Now swap theme and start loading textures
1116 if (newT
->usedHeight
== screenHeight
)
1117 rmResetShiftRatio();
1119 rmSetShiftRatio((float) screenHeight
/ newT
->usedHeight
);
1122 // default all to not loaded...
1123 for (i
= 0; i
< TEXTURES_COUNT
; i
++) {
1124 newT
->textures
[i
].Mem
= NULL
;
1127 // LOGO, loaded here to avoid flickering during startup with device in AUTO + theme set
1128 texPngLoad(&newT
->textures
[LOGO_PICTURE
], NULL
, LOGO_PICTURE
, GS_PSM_CT24
);
1133 // First start with busy icon
1134 char* path
= themePath
;
1136 for (i
= LOAD0_ICON
; i
<= LOAD7_ICON
; i
++) {
1137 if (thmLoadResource(i
, path
, GS_PSM_CT32
, gTheme
->useDefault
) >= 0)
1146 gTheme
->loadingIconCount
= i
;
1148 // Customizable icons
1149 for (i
= USB_ICON
; i
<= START_ICON
; i
++)
1150 thmLoadResource(i
, themePath
, GS_PSM_CT32
, gTheme
->useDefault
);
1152 // Not customizable icons
1153 for (i
= L1_ICON
; i
<= R2_ICON
; i
++)
1154 thmLoadResource(i
, NULL
, GS_PSM_CT32
, 1);
1157 static void thmRebuildGuiNames() {
1159 free(guiThemesNames
);
1161 // build the languages name list
1162 guiThemesNames
= (char**) malloc((nThemes
+ 2) * sizeof(char**));
1164 // add default internal
1165 guiThemesNames
[0] = "<OPL>";
1168 for (; i
< nThemes
; i
++) {
1169 guiThemesNames
[i
+ 1] = themes
[i
].name
;
1172 guiThemesNames
[nThemes
+ 1] = NULL
;
1175 void thmAddElements(char* path
, char* separator
, int mode
) {
1176 nThemes
+= listDir(path
, separator
, THM_MAX_FILES
- nThemes
, &thmReadEntry
);
1177 thmRebuildGuiNames();
1180 if (configGetStr(configGetByType(CONFIG_OPL
), "theme", &temp
)) {
1181 LOG("THEMES Trying to set again theme: %s\n", temp
);
1182 if (thmSetGuiValue(thmFindGuiID(temp
), 0))
1183 moduleUpdateMenu(mode
, 1);
1188 LOG("THEMES Init\n");
1191 thmReloadScreenExtents();
1193 // initialize default internal
1196 thmAddElements(gBaseMCDir
, "/", -1);
1199 void thmReinit(char* path
) {
1204 while (i
< nThemes
) {
1205 if (strncmp(themes
[i
].filePath
, path
, strlen(path
)) == 0) {
1206 LOG("THEMES Remove theme: %s\n", themes
[i
].filePath
);
1208 free(themes
[i
].name
);
1209 themes
[i
].name
= themes
[nThemes
].name
;
1210 themes
[nThemes
].name
= NULL
;
1211 free(themes
[i
].filePath
);
1212 themes
[i
].filePath
= themes
[nThemes
].filePath
;
1213 themes
[nThemes
].filePath
= NULL
;
1218 thmRebuildGuiNames();
1221 void thmReloadScreenExtents() {
1222 rmGetScreenExtents(&screenWidth
, &screenHeight
);
1225 char* thmGetValue() {
1226 return guiThemesNames
[guiThemeID
];
1229 int thmSetGuiValue(int themeID
, int reload
) {
1230 if (themeID
!= -1) {
1231 if (guiThemeID
!= themeID
|| reload
) {
1233 thmLoad(themes
[themeID
- 1].filePath
);
1237 guiThemeID
= themeID
;
1238 configSetStr(configGetByType(CONFIG_OPL
), "theme", thmGetValue());
1241 else if (guiThemeID
== 0)
1242 thmSetColors(gTheme
);
1247 int thmGetGuiValue() {
1251 int thmFindGuiID(char* theme
) {
1254 for (; i
< nThemes
; i
++) {
1255 if (stricmp(themes
[i
].name
, theme
) == 0)
1262 char **thmGetGuiList() {
1263 return guiThemesNames
;
1270 for (; i
< nThemes
; i
++) {
1271 free(themes
[i
].name
);
1272 free(themes
[i
].filePath
);
1275 free(guiThemesNames
);