1 #include "include/usbld.h"
2 #include "include/themes.h"
3 #include "include/util.h"
4 #include "include/gui.h"
5 #include "include/renderman.h"
6 #include "include/textures.h"
7 #include "include/ioman.h"
8 #include "include/fntsys.h"
9 #include "include/lang.h"
12 #define HINT_HEIGHT 32
13 #define DECORATOR_SIZE 20
17 static int screenWidth
;
18 static int screenHeight
;
19 static int guiThemeID
= 0;
21 static int nThemes
= 0;
22 static theme_file_t themes
[THM_MAX_FILES
];
23 static char **guiThemesNames
= NULL
;
25 #define TYPE_ATTRIBUTE_TEXT 0
26 #define TYPE_STATIC_TEXT 1
27 #define TYPE_ATTRIBUTE_IMAGE 2
28 #define TYPE_GAME_IMAGE 3
29 #define TYPE_STATIC_IMAGE 4
30 #define TYPE_BACKGROUND 5
31 #define TYPE_MENU_ICON 6
32 #define TYPE_MENU_TEXT 7
33 #define TYPE_ITEMS_LIST 8
34 #define TYPE_ITEM_ICON 9
35 #define TYPE_ITEM_COVER 10
36 #define TYPE_ITEM_TEXT 11
37 #define TYPE_HINT_TEXT 12
38 #define TYPE_INFO_HINT_TEXT 13
39 #define TYPE_LOADING_ICON 14
41 #define DISPLAY_ALWAYS 0
42 #define DISPLAY_DEFINED 1
43 #define DISPLAY_NEVER 2
45 #define SIZING_NONE -1
49 static char *elementsType
[] = {
67 // Common functions for Text ////////////////////////////////////////////////////////////////////////////////////////////////
69 static void endMutableText(theme_element_t
* elem
) {
70 mutable_text_t
* mutableText
= (mutable_text_t
*) elem
->extended
;
72 if (mutableText
->value
)
73 free(mutableText
->value
);
75 if (mutableText
->alias
)
76 free(mutableText
->alias
);
84 static mutable_text_t
* initMutableText(char* themePath
, config_set_t
* themeConfig
, theme_t
* theme
, char* name
, int type
, struct theme_element
* elem
,
85 char* value
, char* alias
, int displayMode
, int sizingMode
) {
87 mutable_text_t
* mutableText
= (mutable_text_t
*) malloc(sizeof(mutable_text_t
));
88 mutableText
->currentItemId
= -1;
89 mutableText
->currentValue
= NULL
;
90 mutableText
->alias
= NULL
;
94 snprintf(elemProp
, 64, "%s_display", name
);
95 configGetInt(themeConfig
, elemProp
, &displayMode
);
96 mutableText
->displayMode
= displayMode
;
98 int length
= strlen(value
) + 1;
99 mutableText
->value
= (char*) malloc(length
* sizeof(char));
100 memcpy(mutableText
->value
, value
, length
);
102 snprintf(elemProp
, 64, "%s_wrap", name
);
103 if (configGetInt(themeConfig
, elemProp
, &sizingMode
)) {
105 mutableText
->sizingMode
= SIZING_WRAP
;
108 if ((elem
->width
!= DIM_UNDEF
) || (elem
->height
!= DIM_UNDEF
)) {
109 if (sizingMode
== SIZING_NONE
)
110 sizingMode
= SIZING_CLIP
;
112 if (elem
->width
== DIM_UNDEF
)
113 elem
->width
= screenWidth
;
115 if (elem
->height
== DIM_UNDEF
)
116 elem
->height
= screenHeight
;
118 sizingMode
= SIZING_NONE
;
119 mutableText
->sizingMode
= sizingMode
;
121 if (type
== TYPE_ATTRIBUTE_TEXT
) {
122 snprintf(elemProp
, 64, "%s_title", name
);
123 configGetStr(themeConfig
, elemProp
, &alias
);
130 length
= strlen(alias
) + 1 + 3;
131 mutableText
->alias
= (char*) malloc(length
* sizeof(char));
132 if (mutableText
->sizingMode
== SIZING_WRAP
)
133 snprintf(mutableText
->alias
, length
, "%s :\n", alias
);
135 snprintf(mutableText
->alias
, length
, "%s : ", alias
);
137 if (mutableText
->sizingMode
== SIZING_WRAP
)
138 fntFitString(elem
->font
, mutableText
->value
, elem
->width
);
144 // StaticText ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
146 static void drawStaticText(struct menu_list
* menu
, struct submenu_list
* item
, config_set_t
* config
, struct theme_element
* elem
) {
147 mutable_text_t
* mutableText
= (mutable_text_t
*) elem
->extended
;
148 if (mutableText
->sizingMode
== SIZING_NONE
)
149 fntRenderString(elem
->font
, elem
->posX
, elem
->posY
, elem
->aligned
, 0, 0, mutableText
->value
, elem
->color
);
151 fntRenderString(elem
->font
, elem
->posX
, elem
->posY
, elem
->aligned
, elem
->width
, elem
->height
, mutableText
->value
, elem
->color
);
154 static void initStaticText(char* themePath
, config_set_t
* themeConfig
, theme_t
* theme
, theme_element_t
* elem
, char* name
,
159 snprintf(elemProp
, 64, "%s_value", name
);
160 configGetStr(themeConfig
, elemProp
, &value
);
162 elem
->extended
= initMutableText(themePath
, themeConfig
, theme
, name
, TYPE_STATIC_TEXT
, elem
, value
, NULL
, DISPLAY_ALWAYS
, SIZING_NONE
);
163 elem
->endElem
= &endMutableText
;
164 elem
->drawElem
= &drawStaticText
;
166 LOG("elemStaticText %s: NO value, elem disabled !!\n", name
);
169 // AttributeText ////////////////////////////////////////////////////////////////////////////////////////////////////////////
171 static void drawAttributeText(struct menu_list
* menu
, struct submenu_list
* item
, config_set_t
* config
, struct theme_element
* elem
) {
172 mutable_text_t
* mutableText
= (mutable_text_t
*) elem
->extended
;
174 if (mutableText
->currentItemId
!= item
->item
.id
) {
176 mutableText
->currentItemId
= item
->item
.id
;
177 mutableText
->currentValue
= NULL
;
178 if (configGetStr(config
, mutableText
->value
, &mutableText
->currentValue
)) {
179 if (mutableText
->sizingMode
== SIZING_WRAP
)
180 fntFitString(elem
->font
, mutableText
->currentValue
, elem
->width
);
183 if (mutableText
->currentValue
) {
184 if (mutableText
->displayMode
== DISPLAY_NEVER
)
185 if (mutableText
->sizingMode
== SIZING_NONE
)
186 fntRenderString(elem
->font
, elem
->posX
, elem
->posY
, elem
->aligned
, 0, 0, mutableText
->currentValue
, elem
->color
);
188 fntRenderString(elem
->font
, elem
->posX
, elem
->posY
, elem
->aligned
, elem
->width
, elem
->height
, mutableText
->currentValue
, elem
->color
);
191 snprintf(result
, 300, "%s%s", mutableText
->alias
, mutableText
->currentValue
);
192 if (mutableText
->sizingMode
== SIZING_NONE
)
193 fntRenderString(elem
->font
, elem
->posX
, elem
->posY
, elem
->aligned
, 0, 0, result
, elem
->color
);
195 fntRenderString(elem
->font
, elem
->posX
, elem
->posY
, elem
->aligned
, elem
->width
, elem
->height
, result
, elem
->color
);
200 if (mutableText
->displayMode
== DISPLAY_ALWAYS
)
201 fntRenderString(elem
->font
, elem
->posX
, elem
->posY
, elem
->aligned
, 0, 0, mutableText
->alias
, elem
->color
);
204 static void initAttributeText(char* themePath
, config_set_t
* themeConfig
, theme_t
* theme
, theme_element_t
* elem
, char* name
,
209 snprintf(elemProp
, 64, "%s_attribute", name
);
210 configGetStr(themeConfig
, elemProp
, &attribute
);
212 elem
->extended
= initMutableText(themePath
, themeConfig
, theme
, name
, TYPE_ATTRIBUTE_TEXT
, elem
, attribute
, NULL
, DISPLAY_ALWAYS
, SIZING_NONE
);
213 elem
->endElem
= &endMutableText
;
214 elem
->drawElem
= &drawAttributeText
;
216 LOG("elemAttributeText %s: NO attribute, elem disabled !!\n", name
);
219 // Common functions for Image ///////////////////////////////////////////////////////////////////////////////////////////////
221 static void findDuplicate(theme_element_t
* first
, char* cachePattern
, char* defaultTexture
, char* overlayTexture
, mutable_image_t
* target
) {
222 theme_element_t
* elem
= first
;
224 if ((elem
->type
== TYPE_STATIC_IMAGE
) || (elem
->type
== TYPE_ATTRIBUTE_IMAGE
) || (elem
->type
== TYPE_GAME_IMAGE
) || (elem
->type
== TYPE_BACKGROUND
)) {
225 mutable_image_t
* source
= (mutable_image_t
*) elem
->extended
;
227 if (cachePattern
&& source
->cache
&& !strcmp(cachePattern
, source
->cache
->suffix
)) {
228 target
->cache
= source
->cache
;
229 target
->cacheLinked
= 1;
230 LOG("Re-using a cache for pattern %s\n", cachePattern
);
233 if (defaultTexture
&& source
->defaultTexture
&& !strcmp(defaultTexture
, source
->defaultTexture
->name
)) {
234 target
->defaultTexture
= source
->defaultTexture
;
235 target
->defaultTextureLinked
= 1;
236 LOG("Re-using the default texture for %s\n", defaultTexture
);
239 if (overlayTexture
&& source
->overlayTexture
&& !strcmp(overlayTexture
, source
->overlayTexture
->name
)) {
240 target
->overlayTexture
= source
->overlayTexture
;
241 target
->overlayTextureLinked
= 1;
242 LOG("Re-using the overlay texture for %s\n", overlayTexture
);
250 static void freeImageTexture(image_texture_t
* texture
) {
252 if (texture
->source
.Mem
)
253 free(texture
->source
.Mem
);
261 static image_texture_t
* initImageTexture(char* themePath
, config_set_t
* themeConfig
, char* name
, char* imgName
, int isOverlay
) {
262 image_texture_t
* texture
= (image_texture_t
*) malloc(sizeof(image_texture_t
));
263 texPrepare(&texture
->source
, isOverlay
? GS_PSM_CT32
: GS_PSM_CT24
);
264 texture
->name
= NULL
;
267 snprintf(path
, 255, "%s%s", themePath
, imgName
);
268 if (texDiscoverLoad(&texture
->source
, path
, -1, isOverlay
? GS_PSM_CT32
: GS_PSM_CT24
) >= 0) {
269 int length
= strlen(imgName
) + 1;
270 texture
->name
= (char*) malloc(length
* sizeof(char));
271 memcpy(texture
->name
, imgName
, length
);
276 snprintf(elemProp
, 64, "%s_overlay_ulx", name
);
277 if (configGetInt(themeConfig
, elemProp
, &intValue
))
278 texture
->upperLeft_x
= intValue
;
279 snprintf(elemProp
, 64, "%s_overlay_uly", name
);
280 if (configGetInt(themeConfig
, elemProp
, &intValue
))
281 texture
->upperLeft_y
= intValue
;
282 snprintf(elemProp
, 64, "%s_overlay_urx", name
);
283 if (configGetInt(themeConfig
, elemProp
, &intValue
))
284 texture
->upperRight_x
= intValue
;
285 snprintf(elemProp
, 64, "%s_overlay_ury", name
);
286 if (configGetInt(themeConfig
, elemProp
, &intValue
))
287 texture
->upperRight_y
= intValue
;
288 snprintf(elemProp
, 64, "%s_overlay_llx", name
);
289 if (configGetInt(themeConfig
, elemProp
, &intValue
))
290 texture
->lowerLeft_x
= intValue
;
291 snprintf(elemProp
, 64, "%s_overlay_lly", name
);
292 if (configGetInt(themeConfig
, elemProp
, &intValue
))
293 texture
->lowerLeft_y
= intValue
;
294 snprintf(elemProp
, 64, "%s_overlay_lrx", name
);
295 if (configGetInt(themeConfig
, elemProp
, &intValue
))
296 texture
->lowerRight_x
= intValue
;
297 snprintf(elemProp
, 64, "%s_overlay_lry", name
);
298 if (configGetInt(themeConfig
, elemProp
, &intValue
))
299 texture
->lowerRight_y
= intValue
;
302 freeImageTexture(texture
);
309 static void endMutableImage(struct theme_element
* elem
) {
310 mutable_image_t
* mutableImage
= (mutable_image_t
*) elem
->extended
;
312 if (mutableImage
->cache
&& !mutableImage
->cacheLinked
)
313 cacheDestroyCache(mutableImage
->cache
);
315 if (mutableImage
->defaultTexture
&& !mutableImage
->defaultTextureLinked
)
316 freeImageTexture(mutableImage
->defaultTexture
);
318 if (mutableImage
->overlayTexture
&& !mutableImage
->overlayTextureLinked
)
319 freeImageTexture(mutableImage
->overlayTexture
);
327 static mutable_image_t
* initMutableImage(char* themePath
, config_set_t
* themeConfig
, theme_t
* theme
, char* name
, int type
,
328 char* cachePattern
, int cacheCount
, char* defaultTexture
, char* overlayTexture
) {
330 mutable_image_t
* mutableImage
= (mutable_image_t
*) malloc(sizeof(mutable_image_t
));
331 mutableImage
->currentUid
= -1;
332 mutableImage
->currentItemId
= -1;
333 mutableImage
->currentValue
= NULL
;
334 mutableImage
->cache
= NULL
;
335 mutableImage
->cacheLinked
= 0;
336 mutableImage
->defaultTexture
= NULL
;
337 mutableImage
->defaultTextureLinked
= 0;
338 mutableImage
->overlayTexture
= NULL
;
339 mutableImage
->overlayTextureLinked
= 0;
343 if (type
== TYPE_ATTRIBUTE_IMAGE
) {
344 snprintf(elemProp
, 64, "%s_attribute", name
);
345 configGetStr(themeConfig
, elemProp
, &cachePattern
);
346 LOG("elemMutableImage %s: type: %d using cache pattern: %s\n", name
, type
, cachePattern
);
347 } else if ((type
== TYPE_GAME_IMAGE
) || type
== (TYPE_BACKGROUND
)) {
348 snprintf(elemProp
, 64, "%s_pattern", name
);
349 configGetStr(themeConfig
, elemProp
, &cachePattern
);
350 snprintf(elemProp
, 64, "%s_count", name
);
351 configGetInt(themeConfig
, elemProp
, &cacheCount
);
352 LOG("elemMutableImage %s: type: %d using cache pattern: %s\n", name
, type
, cachePattern
);
355 snprintf(elemProp
, 64, "%s_default", name
);
356 configGetStr(themeConfig
, elemProp
, &defaultTexture
);
358 if (type
!= TYPE_BACKGROUND
) {
359 snprintf(elemProp
, 64, "%s_overlay", name
);
360 configGetStr(themeConfig
, elemProp
, &overlayTexture
);
363 findDuplicate(theme
->mainElems
.first
, cachePattern
, defaultTexture
, overlayTexture
, mutableImage
);
364 findDuplicate(theme
->infoElems
.first
, cachePattern
, defaultTexture
, overlayTexture
, mutableImage
);
366 if (cachePattern
&& !mutableImage
->cache
) {
367 if (type
== TYPE_ATTRIBUTE_IMAGE
)
368 mutableImage
->cache
= cacheInitCache(-1, themePath
, 0, cachePattern
, 1);
370 mutableImage
->cache
= cacheInitCache(theme
->gameCacheCount
++, "ART", 1, cachePattern
, cacheCount
);
373 if (defaultTexture
&& !mutableImage
->defaultTexture
)
374 mutableImage
->defaultTexture
= initImageTexture(themePath
, themeConfig
, name
, defaultTexture
, 0);
376 if (overlayTexture
&& !mutableImage
->overlayTexture
)
377 mutableImage
->overlayTexture
= initImageTexture(themePath
, themeConfig
, name
, overlayTexture
, 1);
382 // StaticImage //////////////////////////////////////////////////////////////////////////////////////////////////////////////
384 static void drawStaticImage(struct menu_list
* menu
, struct submenu_list
* item
, config_set_t
* config
, struct theme_element
* elem
) {
385 mutable_image_t
* staticImage
= (mutable_image_t
*) elem
->extended
;
386 if (staticImage
->overlayTexture
) {
387 rmDrawOverlayPixmap(&staticImage
->overlayTexture
->source
, elem
->posX
, elem
->posY
, elem
->aligned
, elem
->width
, elem
->height
, elem
->scaled
, gDefaultCol
,
388 &staticImage
->defaultTexture
->source
, staticImage
->overlayTexture
->upperLeft_x
, staticImage
->overlayTexture
->upperLeft_y
, staticImage
->overlayTexture
->upperRight_x
, staticImage
->overlayTexture
->upperRight_y
,
389 staticImage
->overlayTexture
->lowerLeft_x
, staticImage
->overlayTexture
->lowerLeft_y
, staticImage
->overlayTexture
->lowerRight_x
, staticImage
->overlayTexture
->lowerRight_y
);
391 rmDrawPixmap(&staticImage
->defaultTexture
->source
, elem
->posX
, elem
->posY
, elem
->aligned
, elem
->width
, elem
->height
, elem
->scaled
, gDefaultCol
);
394 static void initStaticImage(char* themePath
, config_set_t
* themeConfig
, theme_t
* theme
, theme_element_t
* elem
, char* name
,
397 mutable_image_t
* mutableImage
= initMutableImage(themePath
, themeConfig
, theme
, name
, elem
->type
, NULL
, 0, imageName
, NULL
);
398 elem
->extended
= mutableImage
;
399 elem
->endElem
= &endMutableImage
;
401 if (mutableImage
->defaultTexture
)
402 elem
->drawElem
= &drawStaticImage
;
404 LOG("elemStaticImage %s: NO image name, elem disabled !!\n", name
);
407 // GameImage ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
409 static GSTEXTURE
* getGameImageTexture(image_cache_t
* cache
, void* support
, struct submenu_item
* item
) {
411 item_list_t
* list
= (item_list_t
*) support
;
412 char* startup
= list
->itemGetStartup(item
->id
);
413 //LOG("getGameCachedTex, prefix: %s addsep: %d value: %s suffix: %s\n", cache->prefix, cache->addSeparator, startup, suffix);
414 return cacheGetTexture(cache
, list
, &item
->cache_id
[cache
->userId
], &item
->cache_uid
[cache
->userId
], startup
);
420 static void drawGameImage(struct menu_list
* menu
, struct submenu_list
* item
, config_set_t
* config
, struct theme_element
* elem
) {
421 mutable_image_t
* gameImage
= (mutable_image_t
*) elem
->extended
;
423 GSTEXTURE
* texture
= getGameImageTexture(gameImage
->cache
, menu
->item
->userdata
, &item
->item
);
424 if (!texture
|| !texture
->Mem
) {
425 if (gameImage
->defaultTexture
)
426 texture
= &gameImage
->defaultTexture
->source
;
428 if (elem
->type
== TYPE_BACKGROUND
)
434 if (gameImage
->overlayTexture
) {
435 rmDrawOverlayPixmap(&gameImage
->overlayTexture
->source
, elem
->posX
, elem
->posY
, elem
->aligned
, elem
->width
, elem
->height
, elem
->scaled
, gDefaultCol
,
436 texture
, gameImage
->overlayTexture
->upperLeft_x
, gameImage
->overlayTexture
->upperLeft_y
, gameImage
->overlayTexture
->upperRight_x
, gameImage
->overlayTexture
->upperRight_y
,
437 gameImage
->overlayTexture
->lowerLeft_x
, gameImage
->overlayTexture
->lowerLeft_y
, gameImage
->overlayTexture
->lowerRight_x
, gameImage
->overlayTexture
->lowerRight_y
);
439 rmDrawPixmap(texture
, elem
->posX
, elem
->posY
, elem
->aligned
, elem
->width
, elem
->height
, elem
->scaled
, gDefaultCol
);
441 } else if (elem
->type
== TYPE_BACKGROUND
) {
442 if (gameImage
->defaultTexture
)
443 rmDrawPixmap(&gameImage
->defaultTexture
->source
, elem
->posX
, elem
->posY
, elem
->aligned
, elem
->width
, elem
->height
, elem
->scaled
, gDefaultCol
);
449 static void initGameImage(char* themePath
, config_set_t
* themeConfig
, theme_t
* theme
, theme_element_t
* elem
, char* name
,
450 char* pattern
, int count
, char* texture
, char* overlay
) {
452 mutable_image_t
* mutableImage
= initMutableImage(themePath
, themeConfig
, theme
, name
, elem
->type
, pattern
, count
, texture
, overlay
);
453 elem
->extended
= mutableImage
;
454 elem
->endElem
= &endMutableImage
;
456 if (mutableImage
->cache
)
457 elem
->drawElem
= &drawGameImage
;
459 LOG("elemGameImage %s: NO pattern, elem disabled !!\n", name
);
462 // AttributeImage ///////////////////////////////////////////////////////////////////////////////////////////////////////////
464 static void drawAttributeImage(struct menu_list
* menu
, struct submenu_list
* item
, config_set_t
* config
, struct theme_element
* elem
) {
465 mutable_image_t
* attributeImage
= (mutable_image_t
*) elem
->extended
;
467 if (attributeImage
->currentItemId
!= item
->item
.id
) {
469 attributeImage
->currentUid
= -1;
470 attributeImage
->currentItemId
= item
->item
.id
;
471 attributeImage
->currentValue
= NULL
;
472 configGetStr(config
, attributeImage
->cache
->suffix
, &attributeImage
->currentValue
);
474 if (attributeImage
->currentValue
) {
476 GSTEXTURE
* texture
= cacheGetTexture(attributeImage
->cache
, menu
->item
->userdata
, &posZ
, &attributeImage
->currentUid
, attributeImage
->currentValue
);
477 if (texture
&& texture
->Mem
) {
478 if (attributeImage
->overlayTexture
) {
479 rmDrawOverlayPixmap(&attributeImage
->overlayTexture
->source
, elem
->posX
, elem
->posY
, elem
->aligned
, elem
->width
, elem
->height
, elem
->scaled
, gDefaultCol
,
480 texture
, attributeImage
->overlayTexture
->upperLeft_x
, attributeImage
->overlayTexture
->upperLeft_y
, attributeImage
->overlayTexture
->upperRight_x
, attributeImage
->overlayTexture
->upperRight_y
,
481 attributeImage
->overlayTexture
->lowerLeft_x
, attributeImage
->overlayTexture
->lowerLeft_y
, attributeImage
->overlayTexture
->lowerRight_x
, attributeImage
->overlayTexture
->lowerRight_y
);
483 rmDrawPixmap(texture
, elem
->posX
, elem
->posY
, elem
->aligned
, elem
->width
, elem
->height
, elem
->scaled
, gDefaultCol
);
489 if (attributeImage
->defaultTexture
)
490 rmDrawPixmap(&attributeImage
->defaultTexture
->source
, elem
->posX
, elem
->posY
, elem
->aligned
, elem
->width
, elem
->height
, elem
->scaled
, gDefaultCol
);
493 static void initAttributeImage(char* themePath
, config_set_t
* themeConfig
, theme_t
* theme
, theme_element_t
* elem
, char* name
) {
494 mutable_image_t
* mutableImage
= initMutableImage(themePath
, themeConfig
, theme
, name
, elem
->type
, NULL
, 1, NULL
, NULL
);
495 elem
->extended
= mutableImage
;
496 elem
->endElem
= &endMutableImage
;
498 if (mutableImage
->cache
)
499 elem
->drawElem
= &drawAttributeImage
;
501 LOG("elemAttributeImage %s: NO attribute, elem disabled !!\n", name
);
504 // BasicElement /////////////////////////////////////////////////////////////////////////////////////////////////////////////
506 static void endBasic(theme_element_t
* elem
) {
508 free(elem
->extended
);
513 static theme_element_t
* initBasic(char* themePath
, config_set_t
* themeConfig
, theme_t
* theme
,
514 char* name
, int type
, int x
, int y
, short aligned
, int w
, int h
, short scaled
, u64 color
, int font
) {
517 unsigned char charColor
[3];
521 theme_element_t
* elem
= (theme_element_t
*) malloc(sizeof(theme_element_t
));
524 elem
->extended
= NULL
;
525 elem
->drawElem
= NULL
;
526 elem
->endElem
= &endBasic
;
529 snprintf(elemProp
, 64, "%s_x", name
);
530 if (configGetStr(themeConfig
, elemProp
, &temp
)) {
531 if (!strncmp(temp
, "POS_MID", 7))
532 x
= screenWidth
>> 1;
537 elem
->posX
= screenWidth
+ x
;
541 snprintf(elemProp
, 64, "%s_y", name
);
542 if (configGetStr(themeConfig
, elemProp
, &temp
)) {
543 if (!strncmp(temp
, "POS_MID", 7))
544 y
= screenHeight
>> 1;
549 elem
->posY
= ceil((screenHeight
+ y
) * theme
->usedHeight
/ screenHeight
);
553 snprintf(elemProp
, 64, "%s_width", name
);
554 if (configGetStr(themeConfig
, elemProp
, &temp
)) {
555 if (!strncmp(temp
, "DIM_INF", 7))
556 elem
->width
= screenWidth
;
558 elem
->width
= atoi(temp
);
562 snprintf(elemProp
, 64, "%s_height", name
);
563 if (configGetStr(themeConfig
, elemProp
, &temp
)) {
564 if (!strncmp(temp
, "DIM_INF", 7))
565 elem
->height
= screenHeight
;
567 elem
->height
= atoi(temp
);
571 snprintf(elemProp
, 64, "%s_aligned", name
);
572 if (configGetInt(themeConfig
, elemProp
, &intValue
))
573 elem
->aligned
= intValue
;
575 elem
->aligned
= aligned
;
577 snprintf(elemProp
, 64, "%s_scaled", name
);
578 if (configGetInt(themeConfig
, elemProp
, &intValue
))
579 elem
->scaled
= intValue
;
581 elem
->scaled
= scaled
;
583 snprintf(elemProp
, 64, "%s_color", name
);
584 if (configGetColor(themeConfig
, elemProp
, charColor
))
585 elem
->color
= GS_SETREG_RGBA(charColor
[0], charColor
[1], charColor
[2], 0xff);
589 snprintf(elemProp
, 64, "%s_font", name
);
590 if (configGetInt(themeConfig
, elemProp
, &intValue
))
592 if (font
>= 0 && font
< THM_MAX_FONTS
)
593 elem
->font
= theme
->fonts
[font
];
595 elem
->font
= FNT_DEFAULT
;
600 // Internal elements ////////////////////////////////////////////////////////////////////////////////////////////////////////
602 static void drawBackground(struct menu_list
* menu
, struct submenu_list
* item
, config_set_t
* config
, struct theme_element
* elem
) {
606 static void initBackground(char* themePath
, config_set_t
* themeConfig
, theme_t
* theme
, theme_element_t
* elem
, char* name
,
607 char* pattern
, int count
, char* texture
) {
609 mutable_image_t
* mutableImage
= initMutableImage(themePath
, themeConfig
, theme
, name
, elem
->type
, pattern
, count
, texture
, NULL
);
610 elem
->extended
= mutableImage
;
611 elem
->endElem
= &endMutableImage
;
613 if (mutableImage
->cache
)
614 elem
->drawElem
= &drawGameImage
;
615 else if (mutableImage
->defaultTexture
)
616 elem
->drawElem
= &drawStaticImage
;
618 elem
->drawElem
= &drawBackground
;
621 static void drawMenuIcon(struct menu_list
* menu
, struct submenu_list
* item
, config_set_t
* config
, struct theme_element
* elem
) {
622 GSTEXTURE
* menuIconTex
= thmGetTexture(menu
->item
->icon_id
);
623 if (menuIconTex
&& menuIconTex
->Mem
)
624 rmDrawPixmap(menuIconTex
, elem
->posX
, elem
->posY
, elem
->aligned
, elem
->width
, elem
->height
, elem
->scaled
, gDefaultCol
);
627 static void drawMenuText(struct menu_list
* menu
, struct submenu_list
* item
, config_set_t
* config
, struct theme_element
* elem
) {
628 GSTEXTURE
* leftIconTex
= NULL
, *rightIconTex
= NULL
;
630 leftIconTex
= thmGetTexture(LEFT_ICON
);
632 rightIconTex
= thmGetTexture(RIGHT_ICON
);
635 int offset
= elem
->width
>> 1;
636 if (leftIconTex
&& leftIconTex
->Mem
)
637 rmDrawPixmap(leftIconTex
, elem
->posX
- offset
, elem
->posY
, elem
->aligned
, leftIconTex
->Width
, leftIconTex
->Height
, elem
->scaled
, gDefaultCol
);
638 if (rightIconTex
&& rightIconTex
->Mem
)
639 rmDrawPixmap(rightIconTex
, elem
->posX
+ offset
, elem
->posY
, elem
->aligned
, rightIconTex
->Width
, rightIconTex
->Height
, elem
->scaled
, gDefaultCol
);
642 if (leftIconTex
&& leftIconTex
->Mem
)
643 rmDrawPixmap(leftIconTex
, elem
->posX
- leftIconTex
->Width
, elem
->posY
, elem
->aligned
, leftIconTex
->Width
, leftIconTex
->Height
, elem
->scaled
, gDefaultCol
);
644 if (rightIconTex
&& rightIconTex
->Mem
)
645 rmDrawPixmap(rightIconTex
, elem
->posX
+ elem
->width
, elem
->posY
, elem
->aligned
, rightIconTex
->Width
, rightIconTex
->Height
, elem
->scaled
, gDefaultCol
);
647 fntRenderString(elem
->font
, elem
->posX
, elem
->posY
, elem
->aligned
, 0, 0, menuItemGetText(menu
->item
), elem
->color
);
650 static void drawItemsList(struct menu_list
* menu
, struct submenu_list
* item
, config_set_t
* config
, struct theme_element
* elem
) {
652 items_list_t
* itemsList
= (items_list_t
*) elem
->extended
;
654 int posX
= elem
->posX
, posY
= elem
->posY
;
656 posX
-= elem
->width
>> 1;
657 posY
-= elem
->height
>> 1;
660 submenu_list_t
*ps
= menu
->item
->pagestart
;
663 while (ps
&& (others
++ < itemsList
->displayedItems
)) {
665 color
= gTheme
->selTextColor
;
669 if (itemsList
->decoratorImage
) {
670 GSTEXTURE
* itemIconTex
= getGameImageTexture(itemsList
->decoratorImage
->cache
, menu
->item
->userdata
, &ps
->item
);
671 if (itemIconTex
&& itemIconTex
->Mem
)
672 rmDrawPixmap(itemIconTex
, posX
, posY
, ALIGN_NONE
, DECORATOR_SIZE
, DECORATOR_SIZE
, elem
->scaled
, gDefaultCol
);
674 if (itemsList
->decoratorImage
->defaultTexture
)
675 rmDrawPixmap(&itemsList
->decoratorImage
->defaultTexture
->source
, posX
, posY
, ALIGN_NONE
, DECORATOR_SIZE
, DECORATOR_SIZE
, elem
->scaled
, gDefaultCol
);
677 fntRenderString(elem
->font
, posX
+ DECORATOR_SIZE
, posY
, ALIGN_NONE
, elem
->width
, elem
->height
, submenuItemGetText(&ps
->item
), color
);
679 fntRenderString(elem
->font
, posX
, posY
, ALIGN_NONE
, elem
->width
, elem
->height
, submenuItemGetText(&ps
->item
), color
);
681 posY
+= MENU_ITEM_HEIGHT
;
687 static void initItemsList(char* themePath
, config_set_t
* themeConfig
, theme_t
* theme
, theme_element_t
* elem
, char* name
, char* decorator
) {
690 items_list_t
* itemsList
= (items_list_t
*) malloc(sizeof(items_list_t
));
692 if (elem
->width
== DIM_UNDEF
)
693 elem
->width
= screenWidth
;
695 if (elem
->height
== DIM_UNDEF
)
696 elem
->height
= theme
->usedHeight
- (MENU_POS_V
+ HINT_HEIGHT
);
698 itemsList
->displayedItems
= elem
->height
/ MENU_ITEM_HEIGHT
;
699 LOG("elemItemsList %s: displaying %d elems, item height: %d\n", name
, itemsList
->displayedItems
, elem
->height
);
701 itemsList
->decorator
= NULL
;
702 snprintf(elemProp
, 64, "%s_decorator", name
);
703 configGetStr(themeConfig
, elemProp
, &decorator
);
705 itemsList
->decorator
= decorator
; // Will be used later (thmValidate)
707 itemsList
->decoratorImage
= NULL
;
709 elem
->extended
= itemsList
;
710 // elem->endElem = &endBasic; does the job
712 elem
->drawElem
= &drawItemsList
;
715 static void drawItemText(struct menu_list
* menu
, struct submenu_list
* item
, config_set_t
* config
, struct theme_element
* elem
) {
717 item_list_t
*support
= menu
->item
->userdata
;
718 fntRenderString(elem
->font
, elem
->posX
, elem
->posY
, elem
->aligned
, 0, 0, support
->itemGetStartup(item
->item
.id
), elem
->color
);
722 static void drawHintText(struct menu_list
* menu
, struct submenu_list
* item
, config_set_t
* config
, struct theme_element
* elem
) {
723 menu_hint_item_t
* hint
= menu
->item
->hints
;
727 for (; hint
; hint
= hint
->next
) {
728 x
= guiDrawIconAndText(hint
->icon_id
, hint
->text_id
, elem
->font
, x
, elem
->posY
, elem
->color
);
734 static void drawInfoHintText(struct menu_list
* menu
, struct submenu_list
* item
, config_set_t
* config
, struct theme_element
* elem
) {
736 x
= guiDrawIconAndText(CROSS_ICON
, _STR_RUN
, elem
->font
, x
, elem
->posY
, elem
->color
);
738 x
= guiDrawIconAndText(CIRCLE_ICON
, _STR_O_BACK
, elem
->font
, x
, elem
->posY
, elem
->color
);
741 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
743 static void validateGUIElems(char* themePath
, config_set_t
* themeConfig
, theme_t
* theme
) {
744 // 1. check we have a valid Background elements
745 if ( !theme
->mainElems
.first
|| (theme
->mainElems
.first
->type
!= TYPE_BACKGROUND
) ) {
746 LOG("No valid background found for main, add default BG_ART\n");
747 theme_element_t
* backgroundElem
= initBasic(themePath
, themeConfig
, theme
, "bg", TYPE_BACKGROUND
, 0, 0, ALIGN_NONE
, screenWidth
, screenHeight
, SCALING_NONE
, gDefaultCol
, FNT_DEFAULT
);
749 initBackground(themePath
, themeConfig
, theme
, backgroundElem
, "bg", "BG", 1, "background");
751 initBackground(themePath
, themeConfig
, theme
, backgroundElem
, "bg", "BG", 1, NULL
);
752 backgroundElem
->next
= theme
->mainElems
.first
;
753 theme
->mainElems
.first
= backgroundElem
;
756 if (theme
->infoElems
.first
) {
757 if (theme
->infoElems
.first
->type
!= TYPE_BACKGROUND
) {
758 LOG("No valid background found for info, add default BG_ART\n");
759 theme_element_t
* backgroundElem
= initBasic(themePath
, themeConfig
, theme
, "bg", TYPE_BACKGROUND
, 0, 0, ALIGN_NONE
, screenWidth
, screenHeight
, SCALING_NONE
, gDefaultCol
, FNT_DEFAULT
);
761 initBackground(themePath
, themeConfig
, theme
, backgroundElem
, "bg", "BG", 1, "background");
763 initBackground(themePath
, themeConfig
, theme
, backgroundElem
, "bg", "BG", 1, NULL
);
764 backgroundElem
->next
= theme
->infoElems
.first
;
765 theme
->infoElems
.first
= backgroundElem
;
769 // 2. check we have a valid ItemsList element, and link its decorator to the target element
770 if (theme
->itemsList
) {
771 items_list_t
* itemsList
= (items_list_t
*) theme
->itemsList
->extended
;
772 if (itemsList
->decorator
) {
773 // Second pass to find the decorator
774 theme_element_t
* decoratorElem
= theme
->mainElems
.first
;
775 while (decoratorElem
) {
776 if (decoratorElem
->type
== TYPE_GAME_IMAGE
) {
777 mutable_image_t
* gameImage
= (mutable_image_t
*) decoratorElem
->extended
;
778 if (!strcmp(itemsList
->decorator
, gameImage
->cache
->suffix
)) {
779 // if user want to cache less than displayed items, then disable itemslist icons, if not would load constantly
780 if (gameImage
->cache
->count
>= itemsList
->displayedItems
)
781 itemsList
->decoratorImage
= gameImage
;
786 decoratorElem
= decoratorElem
->next
;
788 itemsList
->decorator
= NULL
;
791 LOG("No itemsList found, adding a default one\n");
792 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
);
793 initItemsList(themePath
, themeConfig
, theme
, theme
->itemsList
, "il", NULL
);
794 theme
->itemsList
->next
= theme
->mainElems
.first
->next
; // Position the itemsList as second element (right after the Background)
795 theme
->mainElems
.first
->next
= theme
->itemsList
;
799 static int addGUIElem(char* themePath
, config_set_t
* themeConfig
, theme_t
* theme
, theme_elems_t
* elems
, char* type
, char* name
) {
803 theme_element_t
* elem
= NULL
;
805 snprintf(elemProp
, 64, "%s_enabled", name
);
806 configGetInt(themeConfig
, elemProp
, &enabled
);
809 snprintf(elemProp
, 64, "%s_type", name
);
810 configGetStr(themeConfig
, elemProp
, &type
);
812 if (!strcmp(elementsType
[TYPE_ATTRIBUTE_TEXT
], type
)) {
813 elem
= initBasic(themePath
, themeConfig
, theme
, name
, TYPE_ATTRIBUTE_TEXT
, 0, 0, ALIGN_CENTER
, DIM_UNDEF
, DIM_UNDEF
, SCALING_RATIO
, theme
->textColor
, FNT_DEFAULT
);
814 initAttributeText(themePath
, themeConfig
, theme
, elem
, name
, NULL
);
815 } else if (!strcmp(elementsType
[TYPE_STATIC_TEXT
], type
)) {
816 elem
= initBasic(themePath
, themeConfig
, theme
, name
, TYPE_STATIC_TEXT
, 0, 0, ALIGN_CENTER
, DIM_UNDEF
, DIM_UNDEF
, SCALING_RATIO
, theme
->textColor
, FNT_DEFAULT
);
817 initStaticText(themePath
, themeConfig
, theme
, elem
, name
, NULL
);
818 } else if (!strcmp(elementsType
[TYPE_ATTRIBUTE_IMAGE
], type
)) {
819 elem
= initBasic(themePath
, themeConfig
, theme
, name
, TYPE_ATTRIBUTE_IMAGE
, 0, 0, ALIGN_CENTER
, DIM_UNDEF
, DIM_UNDEF
, SCALING_RATIO
, gDefaultCol
, FNT_DEFAULT
);
820 initAttributeImage(themePath
, themeConfig
, theme
, elem
, name
);
821 } else if (!strcmp(elementsType
[TYPE_GAME_IMAGE
], type
)) {
822 elem
= initBasic(themePath
, themeConfig
, theme
, name
, TYPE_GAME_IMAGE
, 0, 0, ALIGN_CENTER
, DIM_UNDEF
, DIM_UNDEF
, SCALING_RATIO
, gDefaultCol
, FNT_DEFAULT
);
823 initGameImage(themePath
, themeConfig
, theme
, elem
, name
, NULL
, 1, NULL
, NULL
);
824 } else if (!strcmp(elementsType
[TYPE_STATIC_IMAGE
], type
)) {
825 elem
= initBasic(themePath
, themeConfig
, theme
, name
, TYPE_STATIC_IMAGE
, 0, 0, ALIGN_CENTER
, DIM_UNDEF
, DIM_UNDEF
, SCALING_RATIO
, gDefaultCol
, FNT_DEFAULT
);
826 initStaticImage(themePath
, themeConfig
, theme
, elem
, name
, NULL
);
827 } else if (!strcmp(elementsType
[TYPE_BACKGROUND
], type
)) {
828 if (!elems
->first
) { // Background elem can only be the first one
829 elem
= initBasic(themePath
, themeConfig
, theme
, name
, TYPE_BACKGROUND
, 0, 0, ALIGN_NONE
, screenWidth
, screenHeight
, SCALING_NONE
, gDefaultCol
, FNT_DEFAULT
);
830 initBackground(themePath
, themeConfig
, theme
, elem
, name
, NULL
, 1, NULL
);
832 } else if (!strcmp(elementsType
[TYPE_MENU_ICON
], type
)) {
833 elem
= initBasic(themePath
, themeConfig
, theme
, name
, TYPE_MENU_ICON
, 40, 40, ALIGN_CENTER
, DIM_UNDEF
, DIM_UNDEF
, SCALING_RATIO
, gDefaultCol
, FNT_DEFAULT
);
834 elem
->drawElem
= &drawMenuIcon
;
835 } else if (!strcmp(elementsType
[TYPE_MENU_TEXT
], type
)) {
836 elem
= initBasic(themePath
, themeConfig
, theme
, name
, TYPE_MENU_TEXT
, screenWidth
>> 1, 20, ALIGN_CENTER
, 200, 20, SCALING_RATIO
, theme
->textColor
, FNT_DEFAULT
);
837 elem
->drawElem
= &drawMenuText
;
838 } else if (!strcmp(elementsType
[TYPE_ITEMS_LIST
], type
)) {
839 if (!theme
->itemsList
) {
840 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
);
841 initItemsList(themePath
, themeConfig
, theme
, elem
, name
, NULL
);
842 theme
->itemsList
= elem
;
844 } else if (!strcmp(elementsType
[TYPE_ITEM_ICON
], type
)) {
845 elem
= initBasic(themePath
, themeConfig
, theme
, name
, TYPE_GAME_IMAGE
, 80, theme
->usedHeight
>> 1, ALIGN_CENTER
, DIM_UNDEF
, DIM_UNDEF
, SCALING_RATIO
, gDefaultCol
, FNT_DEFAULT
);
846 initGameImage(themePath
, themeConfig
, theme
, elem
, name
, "ICO", 20, NULL
, NULL
);
847 } else if (!strcmp(elementsType
[TYPE_ITEM_COVER
], type
)) {
848 elem
= initBasic(themePath
, themeConfig
, theme
, name
, TYPE_GAME_IMAGE
, 520, theme
->usedHeight
>> 1, ALIGN_CENTER
, DIM_UNDEF
, DIM_UNDEF
, SCALING_RATIO
, gDefaultCol
, FNT_DEFAULT
);
849 initGameImage(themePath
, themeConfig
, theme
, elem
, name
, "COV", 10, NULL
, NULL
);
850 } else if (!strcmp(elementsType
[TYPE_ITEM_TEXT
], type
)) {
851 elem
= initBasic(themePath
, themeConfig
, theme
, name
, TYPE_ITEM_TEXT
, 520, 370, ALIGN_CENTER
, DIM_UNDEF
, DIM_UNDEF
, SCALING_RATIO
, theme
->textColor
, FNT_DEFAULT
);
852 elem
->drawElem
= &drawItemText
;
853 } else if (!strcmp(elementsType
[TYPE_HINT_TEXT
], type
)) {
854 elem
= initBasic(themePath
, themeConfig
, theme
, name
, TYPE_HINT_TEXT
, 16, -HINT_HEIGHT
, ALIGN_NONE
, 12, 20, SCALING_RATIO
, theme
->textColor
, FNT_DEFAULT
);
855 elem
->drawElem
= &drawHintText
;
856 } else if (!strcmp(elementsType
[TYPE_INFO_HINT_TEXT
], type
)) {
857 elem
= initBasic(themePath
, themeConfig
, theme
, name
, TYPE_INFO_HINT_TEXT
, 16, -HINT_HEIGHT
, ALIGN_NONE
, 12, 20, SCALING_RATIO
, theme
->textColor
, FNT_DEFAULT
);
858 elem
->drawElem
= &drawInfoHintText
;
859 } else if (!strcmp(elementsType
[TYPE_LOADING_ICON
], type
)) {
860 if (!theme
->loadingIcon
)
861 theme
->loadingIcon
= initBasic(themePath
, themeConfig
, theme
, name
, TYPE_LOADING_ICON
, -50, -50, ALIGN_CENTER
, DIM_UNDEF
, DIM_UNDEF
, SCALING_RATIO
, gDefaultCol
, FNT_DEFAULT
);
871 elems
->last
->next
= elem
;
876 return 0; // ends the reading of elements
882 static void freeGUIElems(theme_elems_t
* elems
) {
883 theme_element_t
* elem
= elems
->first
;
885 elems
->first
= elem
->next
;
891 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
892 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
894 GSTEXTURE
* thmGetTexture(unsigned int id
) {
895 if (id
>= TEXTURES_COUNT
)
898 // see if the texture is valid
899 GSTEXTURE
* txt
= &gTheme
->textures
[id
];
908 static void thmFree(theme_t
* theme
) {
911 freeGUIElems(&theme
->mainElems
);
912 freeGUIElems(&theme
->infoElems
);
917 for(; id
< TEXTURES_COUNT
; id
++) {
918 texture
= &theme
->textures
[id
];
919 if (texture
->Mem
!= NULL
) {
926 for (id
= 0; id
< THM_MAX_FONTS
; ++id
) {
927 int fntid
= theme
->fonts
[id
];
929 if (fntid
!= FNT_DEFAULT
)
938 static int thmReadEntry(int index
, char* path
, char* separator
, char* name
, unsigned int mode
) {
939 if (FIO_SO_ISDIR(mode
) && strstr(name
, "thm_")) {
940 LOG("thmReadEntry() path=%s sep=%s name=%s\n", path
, separator
, name
);
941 theme_file_t
* currTheme
= &themes
[nThemes
+ index
];
943 int length
= strlen(name
) - 4 + 1;
944 currTheme
->name
= (char*) malloc(length
* sizeof(char));
945 memcpy(currTheme
->name
, name
+ 4, length
);
946 currTheme
->name
[length
- 1] = '\0';
948 length
= strlen(path
) + 1 + strlen(name
) + 1 + 1;
949 currTheme
->filePath
= (char*) malloc(length
* sizeof(char));
950 sprintf(currTheme
->filePath
, "%s%s%s%s", path
, separator
, name
, separator
);
952 LOG("Theme found: %s\n", currTheme
->filePath
);
959 /* themePath must contains the leading separator (as it is dependent of the device, we can't know here) */
960 static int thmLoadResource(int texId
, char* themePath
, short psm
, int useDefault
) {
962 GSTEXTURE
* texture
= &gTheme
->textures
[texId
];
964 if (themePath
!= NULL
)
965 success
= texDiscoverLoad(texture
, themePath
, texId
, psm
); // only set success here
967 if ((success
< 0) && useDefault
)
968 texPngLoad(texture
, NULL
, texId
, psm
); // we don't mind the result of "default"
973 static void thmSetColors(theme_t
* theme
) {
974 memcpy(theme
->bgColor
, gDefaultBgColor
, 3);
975 theme
->textColor
= GS_SETREG_RGBA(gDefaultTextColor
[0], gDefaultTextColor
[1], gDefaultTextColor
[2], 0xff);
976 theme
->uiTextColor
= GS_SETREG_RGBA(gDefaultUITextColor
[0], gDefaultUITextColor
[1], gDefaultUITextColor
[2], 0xff);
977 theme
->selTextColor
= GS_SETREG_RGBA(gDefaultSelTextColor
[0], gDefaultSelTextColor
[1], gDefaultSelTextColor
[2], 0xff);
979 theme_element_t
* elem
= theme
->mainElems
.first
;
981 elem
->color
= theme
->textColor
;
986 static void thmLoadFonts(config_set_t
* themeConfig
, const char* themePath
, theme_t
* theme
) {
987 int fntID
; // theme side font id, not the fntSys handle
988 for (fntID
= -1; fntID
< THM_MAX_FONTS
; ++fntID
) {
989 // does the font by the key exist?
992 // -1 is a placeholder for default font...
994 // Default font handle...
995 theme
->fonts
[fntID
] = FNT_DEFAULT
;
996 snprintf(fntKey
, 16, "font%d", fntID
);
998 snprintf(fntKey
, 16, "default_font");
1002 int cfgKeyOK
= configGetStr(themeConfig
, fntKey
, &fntFile
);
1003 if (!cfgKeyOK
&& (fntID
>= 0))
1009 // replace the default font
1011 snprintf(fullPath
, 128, "%s%s", themePath
, fntFile
);
1014 void* customFont
= readFile(fullPath
, -1, &size
);
1017 fntReplace(FNT_DEFAULT
, customFont
, size
, 1, 0);
1019 fntSetDefault(FNT_DEFAULT
);
1021 snprintf(fullPath
, 128, "%s%s", themePath
, fntFile
);
1022 int fntHandle
= fntLoadFile(fullPath
);
1024 // Do we have a valid font? Assign the font handle to the theme font slot
1025 if (fntHandle
!= FNT_ERROR
)
1026 theme
->fonts
[fntID
] = fntHandle
;
1031 static void thmLoad(char* themePath
) {
1032 LOG("thmLoad() path=%s\n", themePath
);
1033 theme_t
* curT
= gTheme
;
1034 theme_t
* newT
= (theme_t
*) malloc(sizeof(theme_t
));
1035 memset(newT
, 0, sizeof(theme_t
));
1037 newT
->useDefault
= 1;
1038 newT
->usedHeight
= 480;
1040 newT
->mainElems
.first
= NULL
;
1041 newT
->mainElems
.last
= NULL
;
1042 newT
->infoElems
.first
= NULL
;
1043 newT
->infoElems
.last
= NULL
;
1044 newT
->gameCacheCount
= 0;
1045 newT
->itemsList
= NULL
;
1046 newT
->loadingIcon
= NULL
;
1047 newT
->loadingIconCount
= LOAD7_ICON
- LOAD0_ICON
+ 1;
1049 config_set_t
* themeConfig
= NULL
;
1051 themeConfig
= configAlloc(0, NULL
, NULL
);
1052 addGUIElem(themePath
, themeConfig
, newT
, &newT
->mainElems
, elementsType
[TYPE_MENU_ICON
], "_");
1053 addGUIElem(themePath
, themeConfig
, newT
, &newT
->mainElems
, elementsType
[TYPE_MENU_TEXT
], "_");
1054 addGUIElem(themePath
, themeConfig
, newT
, &newT
->mainElems
, elementsType
[TYPE_ITEMS_LIST
], "_");
1055 addGUIElem(themePath
, themeConfig
, newT
, &newT
->mainElems
, elementsType
[TYPE_ITEM_ICON
], "_");
1056 addGUIElem(themePath
, themeConfig
, newT
, &newT
->mainElems
, elementsType
[TYPE_ITEM_COVER
], "_");
1057 addGUIElem(themePath
, themeConfig
, newT
, &newT
->mainElems
, elementsType
[TYPE_ITEM_TEXT
], "_");
1058 addGUIElem(themePath
, themeConfig
, newT
, &newT
->mainElems
, elementsType
[TYPE_HINT_TEXT
], "_");
1059 addGUIElem(themePath
, themeConfig
, newT
, &newT
->mainElems
, elementsType
[TYPE_LOADING_ICON
], "_");
1061 // reset the default font to be sure
1062 fntSetDefault(FNT_DEFAULT
);
1065 snprintf(path
, 255, "%sconf_theme.cfg", themePath
);
1066 themeConfig
= configAlloc(0, NULL
, path
);
1067 configRead(themeConfig
); // try to load the theme config file
1070 if (configGetInt(themeConfig
, "use_default", &intValue
))
1071 newT
->useDefault
= intValue
;
1073 if (configGetInt(themeConfig
, "use_real_height", &intValue
)) {
1075 newT
->usedHeight
= screenHeight
;
1078 configGetColor(themeConfig
, "bg_color", newT
->bgColor
);
1080 unsigned char color
[3];
1081 if (configGetColor(themeConfig
, "text_color", color
))
1082 newT
->textColor
= GS_SETREG_RGBA(color
[0], color
[1], color
[2], 0xff);
1084 if (configGetColor(themeConfig
, "ui_text_color", color
))
1085 newT
->uiTextColor
= GS_SETREG_RGBA(color
[0], color
[1], color
[2], 0xff);
1087 if (configGetColor(themeConfig
, "sel_text_color", color
))
1088 newT
->selTextColor
= GS_SETREG_RGBA(color
[0], color
[1], color
[2], 0xff);
1090 // before loading the element definitions, we have to have the fonts prepared
1091 // for that, we load the fonts and a translation table
1092 thmLoadFonts(themeConfig
, themePath
, newT
);
1095 snprintf(path
, 255, "main0");
1096 while (addGUIElem(themePath
, themeConfig
, newT
, &newT
->mainElems
, NULL
, path
))
1097 snprintf(path
, 255, "main%d", i
++);
1100 snprintf(path
, 255, "info0");
1101 while(addGUIElem(themePath
, themeConfig
, newT
, &newT
->infoElems
, NULL
, path
))
1102 snprintf(path
, 255, "info%d", i
++);
1105 validateGUIElems(themePath
, themeConfig
, newT
);
1106 configFree(themeConfig
);
1108 LOG("theme loaded, number of cache: %d\n", newT
->gameCacheCount
);
1110 LOG("thmLoad() usedHeight=%d\n", newT
->usedHeight
);
1112 /// Now swap theme and start loading textures
1113 if (newT
->usedHeight
== screenHeight
)
1114 rmResetShiftRatio();
1116 rmSetShiftRatio((float) screenHeight
/ newT
->usedHeight
);
1119 // default all to not loaded...
1120 for (i
= 0; i
< TEXTURES_COUNT
; i
++) {
1121 newT
->textures
[i
].Mem
= NULL
;
1124 // LOGO, loaded here to avoid flickering during startup with device in AUTO + theme set
1125 texPngLoad(&newT
->textures
[LOGO_PICTURE
], NULL
, LOGO_PICTURE
, GS_PSM_CT24
);
1130 // First start with busy icon
1131 char* path
= themePath
;
1133 for (i
= LOAD0_ICON
; i
<= LOAD7_ICON
; i
++) {
1134 if (thmLoadResource(i
, path
, GS_PSM_CT32
, gTheme
->useDefault
) >= 0)
1143 gTheme
->loadingIconCount
= i
;
1145 // Customizable icons
1146 for (i
= USB_ICON
; i
<= DOWN_ICON
; i
++)
1147 thmLoadResource(i
, themePath
, GS_PSM_CT32
, gTheme
->useDefault
);
1149 // Not customizable icons
1150 for (i
= L1_ICON
; i
<= START_ICON
; i
++)
1151 thmLoadResource(i
, NULL
, GS_PSM_CT32
, 1);
1154 static void thmRebuildGuiNames() {
1156 free(guiThemesNames
);
1158 // build the languages name list
1159 guiThemesNames
= (char**) malloc((nThemes
+ 2) * sizeof(char**));
1161 // add default internal
1162 guiThemesNames
[0] = "<OPL>";
1165 for (; i
< nThemes
; i
++) {
1166 guiThemesNames
[i
+ 1] = themes
[i
].name
;
1169 guiThemesNames
[nThemes
+ 1] = NULL
;
1172 void thmAddElements(char* path
, char* separator
, int mode
) {
1173 LOG("thmAddElements() path=%s sep=%s\n", path
, separator
);
1174 nThemes
+= listDir(path
, separator
, THM_MAX_FILES
- nThemes
, &thmReadEntry
);
1175 LOG("thmAddElements() nThemes=%d\n", nThemes
);
1176 thmRebuildGuiNames();
1179 if (configGetStr(configGetByType(CONFIG_OPL
), "theme", &temp
)) {
1180 LOG("Trying to set again theme: %s\n", temp
);
1181 if (thmSetGuiValue(thmFindGuiID(temp
), 0))
1182 moduleUpdateMenu(mode
, 1);
1190 thmReloadScreenExtents();
1192 // initialize default internal
1195 thmAddElements(gBaseMCDir
, "/", -1);
1198 void thmReloadScreenExtents() {
1199 rmGetScreenExtents(&screenWidth
, &screenHeight
);
1202 char* thmGetValue() {
1203 //LOG("thmGetValue() id=%d name=%s\n", guiThemeID, guiThemesNames[guiThemeID]);
1204 return guiThemesNames
[guiThemeID
];
1207 int thmSetGuiValue(int themeID
, int reload
) {
1208 LOG("thmSetGuiValue() id=%d\n", themeID
);
1209 if (themeID
!= -1) {
1210 if (guiThemeID
!= themeID
|| reload
) {
1212 thmLoad(themes
[themeID
- 1].filePath
);
1216 guiThemeID
= themeID
;
1217 configSetStr(configGetByType(CONFIG_OPL
), "theme", thmGetValue());
1220 else if (guiThemeID
== 0)
1221 thmSetColors(gTheme
);
1226 int thmGetGuiValue() {
1227 //LOG("thmGetGuiValue() id=%d\n", guiThemeID);
1231 int thmFindGuiID(char* theme
) {
1232 LOG("thmFindGuiID() theme=%s\n", theme
);
1235 for (; i
< nThemes
; i
++) {
1236 if (stricmp(themes
[i
].name
, theme
) == 0)
1243 char **thmGetGuiList() {
1244 return guiThemesNames
;
1251 for (; i
< nThemes
; i
++) {
1252 free(themes
[i
].name
);
1253 free(themes
[i
].filePath
);
1256 free(guiThemesNames
);