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: %s using cache pattern: %s\n", name
, elementsType
[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: %s using cache pattern: %s count: %d\n", name
, elementsType
[type
], cachePattern
, cacheCount
);
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);
593 snprintf(elemProp
, 64, "%s_font", name
);
594 if (configGetInt(themeConfig
, elemProp
, &intValue
)) {
595 if (intValue
> 0 && intValue
< THM_MAX_FONTS
)
596 elem
->font
= theme
->fonts
[intValue
];
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
, theme
->fonts
[0]);
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
, theme
->fonts
[0]);
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
, theme
->fonts
[0]);
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
, theme
->fonts
[0]);
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
, theme
->fonts
[0]);
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
, theme
->fonts
[0]);
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
, theme
->fonts
[0]);
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
, theme
->fonts
[0]);
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
, theme
->fonts
[0]);
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
, theme
->fonts
[0]);
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
, theme
->fonts
[0]);
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
, theme
->fonts
[0]);
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
, theme
->fonts
[0]);
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
, theme
->fonts
[0]);
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
, theme
->fonts
[0]);
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
, theme
->fonts
[0]);
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
, theme
->fonts
[0]);
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
, -40, -60, ALIGN_CENTER
, DIM_UNDEF
, DIM_UNDEF
, SCALING_RATIO
, gDefaultCol
, theme
->fonts
[0]);
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 fntRelease(theme
->fonts
[id
]);
936 static int thmReadEntry(int index
, char* path
, char* separator
, char* name
, unsigned int mode
) {
937 if (FIO_SO_ISDIR(mode
) && strstr(name
, "thm_")) {
938 theme_file_t
* currTheme
= &themes
[nThemes
+ index
];
940 int length
= strlen(name
) - 4 + 1;
941 currTheme
->name
= (char*) malloc(length
* sizeof(char));
942 memcpy(currTheme
->name
, name
+ 4, length
);
943 currTheme
->name
[length
- 1] = '\0';
945 length
= strlen(path
) + 1 + strlen(name
) + 1 + 1;
946 currTheme
->filePath
= (char*) malloc(length
* sizeof(char));
947 sprintf(currTheme
->filePath
, "%s%s%s%s", path
, separator
, name
, separator
);
949 LOG("THEMES Theme found: %s\n", currTheme
->filePath
);
956 /* themePath must contains the leading separator (as it is dependent of the device, we can't know here) */
957 static int thmLoadResource(int texId
, char* themePath
, short psm
, int useDefault
) {
959 GSTEXTURE
* texture
= &gTheme
->textures
[texId
];
961 if (themePath
!= NULL
)
962 success
= texDiscoverLoad(texture
, themePath
, texId
, psm
); // only set success here
964 if ((success
< 0) && useDefault
)
965 texPngLoad(texture
, NULL
, texId
, psm
); // we don't mind the result of "default"
970 static void thmSetColors(theme_t
* theme
) {
971 memcpy(theme
->bgColor
, gDefaultBgColor
, 3);
972 theme
->textColor
= GS_SETREG_RGBA(gDefaultTextColor
[0], gDefaultTextColor
[1], gDefaultTextColor
[2], 0xff);
973 theme
->uiTextColor
= GS_SETREG_RGBA(gDefaultUITextColor
[0], gDefaultUITextColor
[1], gDefaultUITextColor
[2], 0xff);
974 theme
->selTextColor
= GS_SETREG_RGBA(gDefaultSelTextColor
[0], gDefaultSelTextColor
[1], gDefaultSelTextColor
[2], 0xff);
976 theme_element_t
* elem
= theme
->mainElems
.first
;
978 elem
->color
= theme
->textColor
;
983 static void thmLoadFonts(config_set_t
* themeConfig
, const char* themePath
, theme_t
* theme
) {
984 int fntID
; // theme side font id, not the fntSys handle
985 for (fntID
= 0; fntID
< THM_MAX_FONTS
; ++fntID
) {
986 // does the font by the key exist?
990 snprintf(fntKey
, 16, "default_font");
991 theme
->fonts
[0] = FNT_DEFAULT
;
993 snprintf(fntKey
, 16, "font%d", fntID
);
994 theme
->fonts
[fntID
] = theme
->fonts
[0];
999 if (configGetStr(themeConfig
, fntKey
, &fntFile
)) {
1000 snprintf(fullPath
, 128, "%s%s", themePath
, fntFile
);
1001 int fntHandle
= fntLoadFile(fullPath
);
1003 // Do we have a valid font? Assign the font handle to the theme font slot
1004 if (fntHandle
!= FNT_ERROR
)
1005 theme
->fonts
[fntID
] = fntHandle
;
1010 static void thmLoad(char* themePath
) {
1011 LOG("THEMES Load theme path=%s\n", themePath
);
1012 theme_t
* curT
= gTheme
;
1013 theme_t
* newT
= (theme_t
*) malloc(sizeof(theme_t
));
1014 memset(newT
, 0, sizeof(theme_t
));
1016 newT
->useDefault
= 1;
1017 newT
->usedHeight
= 480;
1019 newT
->mainElems
.first
= NULL
;
1020 newT
->mainElems
.last
= NULL
;
1021 newT
->infoElems
.first
= NULL
;
1022 newT
->infoElems
.last
= NULL
;
1023 newT
->gameCacheCount
= 0;
1024 newT
->itemsList
= NULL
;
1025 newT
->loadingIcon
= NULL
;
1026 newT
->loadingIconCount
= LOAD7_ICON
- LOAD0_ICON
+ 1;
1028 config_set_t
* themeConfig
= NULL
;
1030 themeConfig
= configAlloc(0, NULL
, NULL
);
1031 addGUIElem(themePath
, themeConfig
, newT
, &newT
->mainElems
, elementsType
[TYPE_MENU_ICON
], "_");
1032 addGUIElem(themePath
, themeConfig
, newT
, &newT
->mainElems
, elementsType
[TYPE_MENU_TEXT
], "_");
1033 addGUIElem(themePath
, themeConfig
, newT
, &newT
->mainElems
, elementsType
[TYPE_ITEMS_LIST
], "_");
1034 addGUIElem(themePath
, themeConfig
, newT
, &newT
->mainElems
, elementsType
[TYPE_ITEM_ICON
], "_");
1035 addGUIElem(themePath
, themeConfig
, newT
, &newT
->mainElems
, elementsType
[TYPE_ITEM_COVER
], "_");
1036 addGUIElem(themePath
, themeConfig
, newT
, &newT
->mainElems
, elementsType
[TYPE_ITEM_TEXT
], "_");
1037 addGUIElem(themePath
, themeConfig
, newT
, &newT
->mainElems
, elementsType
[TYPE_HINT_TEXT
], "_");
1038 addGUIElem(themePath
, themeConfig
, newT
, &newT
->mainElems
, elementsType
[TYPE_LOADING_ICON
], "_");
1041 snprintf(path
, 255, "%sconf_theme.cfg", themePath
);
1042 themeConfig
= configAlloc(0, NULL
, path
);
1043 configRead(themeConfig
); // try to load the theme config file
1046 if (configGetInt(themeConfig
, "use_default", &intValue
))
1047 newT
->useDefault
= intValue
;
1049 if (configGetInt(themeConfig
, "use_real_height", &intValue
)) {
1051 newT
->usedHeight
= screenHeight
;
1054 configGetColor(themeConfig
, "bg_color", newT
->bgColor
);
1056 unsigned char color
[3];
1057 if (configGetColor(themeConfig
, "text_color", color
))
1058 newT
->textColor
= GS_SETREG_RGBA(color
[0], color
[1], color
[2], 0xff);
1060 if (configGetColor(themeConfig
, "ui_text_color", color
))
1061 newT
->uiTextColor
= GS_SETREG_RGBA(color
[0], color
[1], color
[2], 0xff);
1063 if (configGetColor(themeConfig
, "sel_text_color", color
))
1064 newT
->selTextColor
= GS_SETREG_RGBA(color
[0], color
[1], color
[2], 0xff);
1066 // before loading the element definitions, we have to have the fonts prepared
1067 // for that, we load the fonts and a translation table
1068 thmLoadFonts(themeConfig
, themePath
, newT
);
1071 snprintf(path
, 255, "main0");
1072 while (addGUIElem(themePath
, themeConfig
, newT
, &newT
->mainElems
, NULL
, path
))
1073 snprintf(path
, 255, "main%d", i
++);
1076 snprintf(path
, 255, "info0");
1077 while(addGUIElem(themePath
, themeConfig
, newT
, &newT
->infoElems
, NULL
, path
))
1078 snprintf(path
, 255, "info%d", i
++);
1081 validateGUIElems(themePath
, themeConfig
, newT
);
1082 configFree(themeConfig
);
1084 LOG("THEMES Number of cache: %d\n", newT
->gameCacheCount
);
1085 LOG("THEMES Used height: %d\n", newT
->usedHeight
);
1087 /// Now swap theme and start loading textures
1088 if (newT
->usedHeight
== screenHeight
)
1089 rmResetShiftRatio();
1091 rmSetShiftRatio((float) screenHeight
/ newT
->usedHeight
);
1094 // default all to not loaded...
1095 for (i
= 0; i
< TEXTURES_COUNT
; i
++) {
1096 newT
->textures
[i
].Mem
= NULL
;
1099 // LOGO, loaded here to avoid flickering during startup with device in AUTO + theme set
1100 texPngLoad(&newT
->textures
[LOGO_PICTURE
], NULL
, LOGO_PICTURE
, GS_PSM_CT24
);
1105 // First start with busy icon
1106 char* path
= themePath
;
1108 for (i
= LOAD0_ICON
; i
<= LOAD7_ICON
; i
++) {
1109 if (thmLoadResource(i
, path
, GS_PSM_CT32
, gTheme
->useDefault
) >= 0)
1118 gTheme
->loadingIconCount
= i
;
1120 // Customizable icons
1121 for (i
= USB_ICON
; i
<= START_ICON
; i
++)
1122 thmLoadResource(i
, themePath
, GS_PSM_CT32
, gTheme
->useDefault
);
1124 // Not customizable icons
1125 for (i
= L1_ICON
; i
<= R2_ICON
; i
++)
1126 thmLoadResource(i
, NULL
, GS_PSM_CT32
, 1);
1129 static void thmRebuildGuiNames() {
1131 free(guiThemesNames
);
1133 // build the languages name list
1134 guiThemesNames
= (char**) malloc((nThemes
+ 2) * sizeof(char**));
1136 // add default internal
1137 guiThemesNames
[0] = "<OPL>";
1140 for (; i
< nThemes
; i
++) {
1141 guiThemesNames
[i
+ 1] = themes
[i
].name
;
1144 guiThemesNames
[nThemes
+ 1] = NULL
;
1147 void thmAddElements(char* path
, char* separator
, int mode
) {
1148 nThemes
+= listDir(path
, separator
, THM_MAX_FILES
- nThemes
, &thmReadEntry
);
1149 thmRebuildGuiNames();
1152 if (configGetStr(configGetByType(CONFIG_OPL
), "theme", &temp
)) {
1153 LOG("THEMES Trying to set again theme: %s\n", temp
);
1154 if (thmSetGuiValue(thmFindGuiID(temp
), 0))
1155 moduleUpdateMenu(mode
, 1);
1160 LOG("THEMES Init\n");
1163 thmReloadScreenExtents();
1165 // initialize default internal
1168 thmAddElements(gBaseMCDir
, "/", -1);
1171 void thmReinit(char* path
) {
1176 while (i
< nThemes
) {
1177 if (strncmp(themes
[i
].filePath
, path
, strlen(path
)) == 0) {
1178 LOG("THEMES Remove theme: %s\n", themes
[i
].filePath
);
1180 free(themes
[i
].name
);
1181 themes
[i
].name
= themes
[nThemes
].name
;
1182 themes
[nThemes
].name
= NULL
;
1183 free(themes
[i
].filePath
);
1184 themes
[i
].filePath
= themes
[nThemes
].filePath
;
1185 themes
[nThemes
].filePath
= NULL
;
1190 thmRebuildGuiNames();
1193 void thmReloadScreenExtents() {
1194 rmGetScreenExtents(&screenWidth
, &screenHeight
);
1197 char* thmGetValue() {
1198 return guiThemesNames
[guiThemeID
];
1201 int thmSetGuiValue(int themeID
, int reload
) {
1202 if (themeID
!= -1) {
1203 if (guiThemeID
!= themeID
|| reload
) {
1205 thmLoad(themes
[themeID
- 1].filePath
);
1209 guiThemeID
= themeID
;
1210 configSetStr(configGetByType(CONFIG_OPL
), "theme", thmGetValue());
1213 else if (guiThemeID
== 0)
1214 thmSetColors(gTheme
);
1219 int thmGetGuiValue() {
1223 int thmFindGuiID(char* theme
) {
1226 for (; i
< nThemes
; i
++) {
1227 if (stricmp(themes
[i
].name
, theme
) == 0)
1234 char **thmGetGuiList() {
1235 return guiThemesNames
;
1242 for (; i
< nThemes
; i
++) {
1243 free(themes
[i
].name
);
1244 free(themes
[i
].filePath
);
1247 free(guiThemesNames
);