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_LOADING_ICON 13
40 #define DISPLAY_ALWAYS 0
41 #define DISPLAY_DEFINED 1
42 #define DISPLAY_NEVER 2
44 #define SIZING_NONE -1
48 static char *elementsType
[] = {
65 // Common functions for Text ////////////////////////////////////////////////////////////////////////////////////////////////
67 static void endMutableText(theme_element_t
* elem
) {
68 mutable_text_t
* mutableText
= (mutable_text_t
*) elem
->extended
;
70 if (mutableText
->value
)
71 free(mutableText
->value
);
73 if (mutableText
->alias
)
74 free(mutableText
->alias
);
82 static mutable_text_t
* initMutableText(char* themePath
, config_set_t
* themeConfig
, theme_t
* theme
, char* name
, int type
, struct theme_element
* elem
,
83 char* value
, char* alias
, int displayMode
, int sizingMode
) {
85 mutable_text_t
* mutableText
= (mutable_text_t
*) malloc(sizeof(mutable_text_t
));
86 mutableText
->currentItemId
= -1;
87 mutableText
->currentValue
= NULL
;
88 mutableText
->alias
= NULL
;
92 snprintf(elemProp
, 64, "%s_display", name
);
93 configGetInt(themeConfig
, elemProp
, &displayMode
);
94 mutableText
->displayMode
= displayMode
;
96 int length
= strlen(value
) + 1;
97 mutableText
->value
= (char*) malloc(length
* sizeof(char));
98 memcpy(mutableText
->value
, value
, length
);
100 snprintf(elemProp
, 64, "%s_wrap", name
);
101 if (configGetInt(themeConfig
, elemProp
, &sizingMode
)) {
103 mutableText
->sizingMode
= SIZING_WRAP
;
106 if ((elem
->width
!= DIM_UNDEF
) || (elem
->height
!= DIM_UNDEF
)) {
107 if (sizingMode
== SIZING_NONE
)
108 sizingMode
= SIZING_CLIP
;
110 if (elem
->width
== DIM_UNDEF
)
111 elem
->width
= screenWidth
;
113 if (elem
->height
== DIM_UNDEF
)
114 elem
->height
= screenHeight
;
116 sizingMode
= SIZING_NONE
;
117 mutableText
->sizingMode
= sizingMode
;
119 if (type
== TYPE_ATTRIBUTE_TEXT
) {
120 snprintf(elemProp
, 64, "%s_title", name
);
121 configGetStr(themeConfig
, elemProp
, &alias
);
128 length
= strlen(alias
) + 1 + 3;
129 mutableText
->alias
= (char*) malloc(length
* sizeof(char));
130 if (mutableText
->sizingMode
== SIZING_WRAP
)
131 snprintf(mutableText
->alias
, length
, "%s :\n", alias
);
133 snprintf(mutableText
->alias
, length
, "%s : ", alias
);
135 if (mutableText
->sizingMode
== SIZING_WRAP
)
136 fntFitString(elem
->font
, mutableText
->value
, elem
->width
);
142 // StaticText ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
144 static void drawStaticText(struct menu_list
* menu
, struct submenu_list
* item
, config_set_t
* config
, struct theme_element
* elem
) {
145 mutable_text_t
* mutableText
= (mutable_text_t
*) elem
->extended
;
146 if (mutableText
->sizingMode
== SIZING_NONE
)
147 fntRenderString(elem
->font
, elem
->posX
, elem
->posY
, elem
->aligned
, mutableText
->value
, elem
->color
);
149 fntRenderText(elem
->font
, elem
->posX
, elem
->posY
, elem
->aligned
, elem
->width
, elem
->height
, mutableText
->value
, elem
->color
);
152 static void initStaticText(char* themePath
, config_set_t
* themeConfig
, theme_t
* theme
, theme_element_t
* elem
, char* name
,
157 snprintf(elemProp
, 64, "%s_value", name
);
158 configGetStr(themeConfig
, elemProp
, &value
);
160 elem
->extended
= initMutableText(themePath
, themeConfig
, theme
, name
, TYPE_STATIC_TEXT
, elem
, value
, NULL
, DISPLAY_ALWAYS
, SIZING_NONE
);
161 elem
->endElem
= &endMutableText
;
162 elem
->drawElem
= &drawStaticText
;
164 LOG("elemStaticText %s: NO value, elem disabled !!\n", name
);
167 // AttributeText ////////////////////////////////////////////////////////////////////////////////////////////////////////////
169 static void drawAttributeText(struct menu_list
* menu
, struct submenu_list
* item
, config_set_t
* config
, struct theme_element
* elem
) {
171 mutable_text_t
* mutableText
= (mutable_text_t
*) elem
->extended
;
172 if (mutableText
->currentItemId
!= item
->item
.id
) {
174 mutableText
->currentItemId
= item
->item
.id
;
175 mutableText
->currentValue
= NULL
;
176 if (configGetStr(config
, mutableText
->value
, &mutableText
->currentValue
)) {
177 if (mutableText
->sizingMode
== SIZING_WRAP
)
178 fntFitString(elem
->font
, mutableText
->currentValue
, elem
->width
);
181 if (mutableText
->currentValue
) {
182 if (mutableText
->displayMode
== DISPLAY_NEVER
)
183 if (mutableText
->sizingMode
== SIZING_NONE
)
184 fntRenderString(elem
->font
, elem
->posX
, elem
->posY
, elem
->aligned
, mutableText
->currentValue
, elem
->color
);
186 fntRenderText(elem
->font
, elem
->posX
, elem
->posY
, elem
->aligned
, elem
->width
, elem
->height
, mutableText
->currentValue
, elem
->color
);
189 snprintf(result
, 300, "%s%s", mutableText
->alias
, mutableText
->currentValue
);
190 if (mutableText
->sizingMode
== SIZING_NONE
)
191 fntRenderString(elem
->font
, elem
->posX
, elem
->posY
, elem
->aligned
, result
, elem
->color
);
193 fntRenderText(elem
->font
, elem
->posX
, elem
->posY
, elem
->aligned
, elem
->width
, elem
->height
, result
, elem
->color
);
195 } else if (mutableText
->displayMode
== DISPLAY_ALWAYS
)
196 fntRenderString(elem
->font
, elem
->posX
, elem
->posY
, elem
->aligned
, mutableText
->alias
, elem
->color
);
200 static void initAttributeText(char* themePath
, config_set_t
* themeConfig
, theme_t
* theme
, theme_element_t
* elem
, char* name
,
205 snprintf(elemProp
, 64, "%s_attribute", name
);
206 configGetStr(themeConfig
, elemProp
, &attribute
);
208 elem
->extended
= initMutableText(themePath
, themeConfig
, theme
, name
, TYPE_ATTRIBUTE_TEXT
, elem
, attribute
, NULL
, DISPLAY_ALWAYS
, SIZING_NONE
);
209 elem
->endElem
= &endMutableText
;
210 elem
->drawElem
= &drawAttributeText
;
212 LOG("elemAttributeText %s: NO attribute, elem disabled !!\n", name
);
215 // Common functions for Image ///////////////////////////////////////////////////////////////////////////////////////////////
217 static void findDuplicate(theme_element_t
* first
, char* cachePattern
, char* defaultTexture
, char* overlayTexture
, mutable_image_t
* target
) {
218 theme_element_t
* elem
= first
;
220 if ((elem
->type
== TYPE_STATIC_IMAGE
) || (elem
->type
== TYPE_ATTRIBUTE_IMAGE
) || (elem
->type
== TYPE_GAME_IMAGE
) || (elem
->type
== TYPE_BACKGROUND
)) {
221 mutable_image_t
* source
= (mutable_image_t
*) elem
->extended
;
223 if (cachePattern
&& source
->cache
&& !strcmp(cachePattern
, source
->cache
->suffix
)) {
224 target
->cache
= source
->cache
;
225 target
->cacheLinked
= 1;
226 LOG("Re-using a cache for pattern %s\n", cachePattern
);
229 if (defaultTexture
&& source
->defaultTexture
&& !strcmp(defaultTexture
, source
->defaultTexture
->name
)) {
230 target
->defaultTexture
= source
->defaultTexture
;
231 target
->defaultTextureLinked
= 1;
232 LOG("Re-using the default texture for %s\n", defaultTexture
);
235 if (overlayTexture
&& source
->overlayTexture
&& !strcmp(overlayTexture
, source
->overlayTexture
->name
)) {
236 target
->overlayTexture
= source
->overlayTexture
;
237 target
->overlayTextureLinked
= 1;
238 LOG("Re-using the overlay texture for %s\n", overlayTexture
);
246 static void freeImageTexture(image_texture_t
* texture
) {
248 if (texture
->source
.Mem
)
249 free(texture
->source
.Mem
);
257 static image_texture_t
* initImageTexture(char* themePath
, config_set_t
* themeConfig
, char* name
, char* imgName
, int isOverlay
) {
258 image_texture_t
* texture
= (image_texture_t
*) malloc(sizeof(image_texture_t
));
259 texPrepare(&texture
->source
, isOverlay
? GS_PSM_CT32
: GS_PSM_CT24
);
260 texture
->name
= NULL
;
263 snprintf(path
, 255, "%s%s", themePath
, imgName
);
264 if (texDiscoverLoad(&texture
->source
, path
, -1, isOverlay
? GS_PSM_CT32
: GS_PSM_CT24
) >= 0) {
265 int length
= strlen(imgName
) + 1;
266 texture
->name
= (char*) malloc(length
* sizeof(char));
267 memcpy(texture
->name
, imgName
, length
);
272 snprintf(elemProp
, 64, "%s_overlay_ulx", name
);
273 if (configGetInt(themeConfig
, elemProp
, &intValue
))
274 texture
->upperLeft_x
= intValue
;
275 snprintf(elemProp
, 64, "%s_overlay_uly", name
);
276 if (configGetInt(themeConfig
, elemProp
, &intValue
))
277 texture
->upperLeft_y
= intValue
;
278 snprintf(elemProp
, 64, "%s_overlay_urx", name
);
279 if (configGetInt(themeConfig
, elemProp
, &intValue
))
280 texture
->upperRight_x
= intValue
;
281 snprintf(elemProp
, 64, "%s_overlay_ury", name
);
282 if (configGetInt(themeConfig
, elemProp
, &intValue
))
283 texture
->upperRight_y
= intValue
;
284 snprintf(elemProp
, 64, "%s_overlay_llx", name
);
285 if (configGetInt(themeConfig
, elemProp
, &intValue
))
286 texture
->lowerLeft_x
= intValue
;
287 snprintf(elemProp
, 64, "%s_overlay_lly", name
);
288 if (configGetInt(themeConfig
, elemProp
, &intValue
))
289 texture
->lowerLeft_y
= intValue
;
290 snprintf(elemProp
, 64, "%s_overlay_lrx", name
);
291 if (configGetInt(themeConfig
, elemProp
, &intValue
))
292 texture
->lowerRight_x
= intValue
;
293 snprintf(elemProp
, 64, "%s_overlay_lry", name
);
294 if (configGetInt(themeConfig
, elemProp
, &intValue
))
295 texture
->lowerRight_y
= intValue
;
298 freeImageTexture(texture
);
305 static void endMutableImage(struct theme_element
* elem
) {
306 mutable_image_t
* mutableImage
= (mutable_image_t
*) elem
->extended
;
308 if (mutableImage
->cache
&& !mutableImage
->cacheLinked
)
309 cacheDestroyCache(mutableImage
->cache
);
311 if (mutableImage
->defaultTexture
&& !mutableImage
->defaultTextureLinked
)
312 freeImageTexture(mutableImage
->defaultTexture
);
314 if (mutableImage
->overlayTexture
&& !mutableImage
->overlayTextureLinked
)
315 freeImageTexture(mutableImage
->overlayTexture
);
323 static mutable_image_t
* initMutableImage(char* themePath
, config_set_t
* themeConfig
, theme_t
* theme
, char* name
, int type
,
324 char* cachePattern
, int cacheCount
, char* defaultTexture
, char* overlayTexture
) {
326 mutable_image_t
* mutableImage
= (mutable_image_t
*) malloc(sizeof(mutable_image_t
));
327 mutableImage
->currentUid
= -1;
328 mutableImage
->currentItemId
= -1;
329 mutableImage
->currentValue
= NULL
;
330 mutableImage
->cache
= NULL
;
331 mutableImage
->cacheLinked
= 0;
332 mutableImage
->defaultTexture
= NULL
;
333 mutableImage
->defaultTextureLinked
= 0;
334 mutableImage
->overlayTexture
= NULL
;
335 mutableImage
->overlayTextureLinked
= 0;
339 if (type
== TYPE_ATTRIBUTE_IMAGE
) {
340 snprintf(elemProp
, 64, "%s_attribute", name
);
341 configGetStr(themeConfig
, elemProp
, &cachePattern
);
342 LOG("elemMutableImage %s: type: %d using cache pattern: %s\n", name
, type
, cachePattern
);
343 } else if ((type
== TYPE_GAME_IMAGE
) || type
== (TYPE_BACKGROUND
)) {
344 snprintf(elemProp
, 64, "%s_pattern", name
);
345 configGetStr(themeConfig
, elemProp
, &cachePattern
);
346 snprintf(elemProp
, 64, "%s_count", name
);
347 configGetInt(themeConfig
, elemProp
, &cacheCount
);
348 LOG("elemMutableImage %s: type: %d using cache pattern: %s\n", name
, type
, cachePattern
);
351 snprintf(elemProp
, 64, "%s_default", name
);
352 configGetStr(themeConfig
, elemProp
, &defaultTexture
);
354 if (type
!= TYPE_BACKGROUND
) {
355 snprintf(elemProp
, 64, "%s_overlay", name
);
356 configGetStr(themeConfig
, elemProp
, &overlayTexture
);
359 findDuplicate(theme
->mainElems
.first
, cachePattern
, defaultTexture
, overlayTexture
, mutableImage
);
360 findDuplicate(theme
->infoElems
.first
, cachePattern
, defaultTexture
, overlayTexture
, mutableImage
);
362 if (cachePattern
&& !mutableImage
->cache
) {
363 if (type
== TYPE_ATTRIBUTE_IMAGE
)
364 mutableImage
->cache
= cacheInitCache(-1, themePath
, 0, cachePattern
, 1);
366 mutableImage
->cache
= cacheInitCache(theme
->gameCacheCount
++, "ART", 1, cachePattern
, cacheCount
);
369 if (defaultTexture
&& !mutableImage
->defaultTexture
)
370 mutableImage
->defaultTexture
= initImageTexture(themePath
, themeConfig
, name
, defaultTexture
, 0);
372 if (overlayTexture
&& !mutableImage
->overlayTexture
)
373 mutableImage
->overlayTexture
= initImageTexture(themePath
, themeConfig
, name
, overlayTexture
, 1);
378 // StaticImage //////////////////////////////////////////////////////////////////////////////////////////////////////////////
380 static void drawStaticImage(struct menu_list
* menu
, struct submenu_list
* item
, config_set_t
* config
, struct theme_element
* elem
) {
381 mutable_image_t
* staticImage
= (mutable_image_t
*) elem
->extended
;
382 if (staticImage
->overlayTexture
) {
383 rmDrawOverlayPixmap(&staticImage
->overlayTexture
->source
, elem
->posX
, elem
->posY
, elem
->aligned
, elem
->width
, elem
->height
, elem
->scaled
, gDefaultCol
,
384 &staticImage
->defaultTexture
->source
, staticImage
->overlayTexture
->upperLeft_x
, staticImage
->overlayTexture
->upperLeft_y
, staticImage
->overlayTexture
->upperRight_x
, staticImage
->overlayTexture
->upperRight_y
,
385 staticImage
->overlayTexture
->lowerLeft_x
, staticImage
->overlayTexture
->lowerLeft_y
, staticImage
->overlayTexture
->lowerRight_x
, staticImage
->overlayTexture
->lowerRight_y
);
387 rmDrawPixmap(&staticImage
->defaultTexture
->source
, elem
->posX
, elem
->posY
, elem
->aligned
, elem
->width
, elem
->height
, elem
->scaled
, gDefaultCol
);
390 static void initStaticImage(char* themePath
, config_set_t
* themeConfig
, theme_t
* theme
, theme_element_t
* elem
, char* name
,
393 mutable_image_t
* mutableImage
= initMutableImage(themePath
, themeConfig
, theme
, name
, elem
->type
, NULL
, 0, imageName
, NULL
);
394 elem
->extended
= mutableImage
;
395 elem
->endElem
= &endMutableImage
;
397 if (mutableImage
->defaultTexture
)
398 elem
->drawElem
= &drawStaticImage
;
400 LOG("elemStaticImage %s: NO image name, elem disabled !!\n", name
);
403 // GameImage ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
405 static GSTEXTURE
* getGameImageTexture(image_cache_t
* cache
, void* support
, struct submenu_item
* item
) {
407 item_list_t
* list
= (item_list_t
*) support
;
408 char* startup
= list
->itemGetStartup(item
->id
);
409 //LOG("getGameCachedTex, prefix: %s addsep: %d value: %s suffix: %s\n", cache->prefix, cache->addSeparator, startup, suffix);
410 return cacheGetTexture(cache
, list
, &item
->cache_id
[cache
->userId
], &item
->cache_uid
[cache
->userId
], startup
);
416 static void drawGameImage(struct menu_list
* menu
, struct submenu_list
* item
, config_set_t
* config
, struct theme_element
* elem
) {
417 mutable_image_t
* gameImage
= (mutable_image_t
*) elem
->extended
;
419 GSTEXTURE
* texture
= getGameImageTexture(gameImage
->cache
, menu
->item
->userdata
, &item
->item
);
420 if (!texture
|| !texture
->Mem
) {
421 if (gameImage
->defaultTexture
)
422 texture
= &gameImage
->defaultTexture
->source
;
424 if (elem
->type
== TYPE_BACKGROUND
)
430 if (gameImage
->overlayTexture
) {
431 rmDrawOverlayPixmap(&gameImage
->overlayTexture
->source
, elem
->posX
, elem
->posY
, elem
->aligned
, elem
->width
, elem
->height
, elem
->scaled
, gDefaultCol
,
432 texture
, gameImage
->overlayTexture
->upperLeft_x
, gameImage
->overlayTexture
->upperLeft_y
, gameImage
->overlayTexture
->upperRight_x
, gameImage
->overlayTexture
->upperRight_y
,
433 gameImage
->overlayTexture
->lowerLeft_x
, gameImage
->overlayTexture
->lowerLeft_y
, gameImage
->overlayTexture
->lowerRight_x
, gameImage
->overlayTexture
->lowerRight_y
);
435 rmDrawPixmap(texture
, elem
->posX
, elem
->posY
, elem
->aligned
, elem
->width
, elem
->height
, elem
->scaled
, gDefaultCol
);
437 } else if (elem
->type
== TYPE_BACKGROUND
) {
438 if (gameImage
->defaultTexture
)
439 rmDrawPixmap(&gameImage
->defaultTexture
->source
, elem
->posX
, elem
->posY
, elem
->aligned
, elem
->width
, elem
->height
, elem
->scaled
, gDefaultCol
);
445 static void initGameImage(char* themePath
, config_set_t
* themeConfig
, theme_t
* theme
, theme_element_t
* elem
, char* name
,
446 char* pattern
, int count
, char* texture
, char* overlay
) {
448 mutable_image_t
* mutableImage
= initMutableImage(themePath
, themeConfig
, theme
, name
, elem
->type
, pattern
, count
, texture
, overlay
);
449 elem
->extended
= mutableImage
;
450 elem
->endElem
= &endMutableImage
;
452 if (mutableImage
->cache
)
453 elem
->drawElem
= &drawGameImage
;
455 LOG("elemGameImage %s: NO pattern, elem disabled !!\n", name
);
458 // AttributeImage ///////////////////////////////////////////////////////////////////////////////////////////////////////////
460 static void drawAttributeImage(struct menu_list
* menu
, struct submenu_list
* item
, config_set_t
* config
, struct theme_element
* elem
) {
462 mutable_image_t
* attributeImage
= (mutable_image_t
*) elem
->extended
;
463 if (attributeImage
->currentItemId
!= item
->item
.id
) {
465 attributeImage
->currentUid
= -1;
466 attributeImage
->currentItemId
= item
->item
.id
;
467 attributeImage
->currentValue
= NULL
;
468 configGetStr(config
, attributeImage
->cache
->suffix
, &attributeImage
->currentValue
);
470 if (attributeImage
->currentValue
) {
472 GSTEXTURE
* texture
= cacheGetTexture(attributeImage
->cache
, menu
->item
->userdata
, &posZ
, &attributeImage
->currentUid
, attributeImage
->currentValue
);
473 if (texture
&& texture
->Mem
) {
474 if (attributeImage
->overlayTexture
) {
475 rmDrawOverlayPixmap(&attributeImage
->overlayTexture
->source
, elem
->posX
, elem
->posY
, elem
->aligned
, elem
->width
, elem
->height
, elem
->scaled
, gDefaultCol
,
476 texture
, attributeImage
->overlayTexture
->upperLeft_x
, attributeImage
->overlayTexture
->upperLeft_y
, attributeImage
->overlayTexture
->upperRight_x
, attributeImage
->overlayTexture
->upperRight_y
,
477 attributeImage
->overlayTexture
->lowerLeft_x
, attributeImage
->overlayTexture
->lowerLeft_y
, attributeImage
->overlayTexture
->lowerRight_x
, attributeImage
->overlayTexture
->lowerRight_y
);
479 rmDrawPixmap(texture
, elem
->posX
, elem
->posY
, elem
->aligned
, elem
->width
, elem
->height
, elem
->scaled
, gDefaultCol
);
485 if (attributeImage
->defaultTexture
)
486 rmDrawPixmap(&attributeImage
->defaultTexture
->source
, elem
->posX
, elem
->posY
, elem
->aligned
, elem
->width
, elem
->height
, elem
->scaled
, gDefaultCol
);
490 static void initAttributeImage(char* themePath
, config_set_t
* themeConfig
, theme_t
* theme
, theme_element_t
* elem
, char* name
) {
491 mutable_image_t
* mutableImage
= initMutableImage(themePath
, themeConfig
, theme
, name
, elem
->type
, NULL
, 1, NULL
, NULL
);
492 elem
->extended
= mutableImage
;
493 elem
->endElem
= &endMutableImage
;
495 if (mutableImage
->cache
)
496 elem
->drawElem
= &drawAttributeImage
;
498 LOG("elemAttributeImage %s: NO attribute, elem disabled !!\n", name
);
501 // BasicElement /////////////////////////////////////////////////////////////////////////////////////////////////////////////
503 static void endBasic(theme_element_t
* elem
) {
505 free(elem
->extended
);
510 static theme_element_t
* initBasic(char* themePath
, config_set_t
* themeConfig
, theme_t
* theme
,
511 char* name
, int type
, int x
, int y
, short aligned
, int w
, int h
, short scaled
, u64 color
, int font
) {
514 unsigned char charColor
[3];
518 theme_element_t
* elem
= (theme_element_t
*) malloc(sizeof(theme_element_t
));
521 elem
->extended
= NULL
;
522 elem
->drawElem
= NULL
;
523 elem
->endElem
= &endBasic
;
526 snprintf(elemProp
, 64, "%s_x", name
);
527 if (configGetStr(themeConfig
, elemProp
, &temp
)) {
528 if (!strncmp(temp
, "POS_MID", 7))
529 x
= screenWidth
>> 1;
534 elem
->posX
= screenWidth
+ x
;
538 snprintf(elemProp
, 64, "%s_y", name
);
539 if (configGetStr(themeConfig
, elemProp
, &temp
)) {
540 if (!strncmp(temp
, "POS_MID", 7))
541 y
= screenHeight
>> 1;
546 elem
->posY
= ceil((screenHeight
+ y
) * theme
->usedHeight
/ screenHeight
);
550 snprintf(elemProp
, 64, "%s_width", name
);
551 if (configGetStr(themeConfig
, elemProp
, &temp
)) {
552 if (!strncmp(temp
, "DIM_INF", 7))
553 elem
->width
= screenWidth
;
555 elem
->width
= atoi(temp
);
559 snprintf(elemProp
, 64, "%s_height", name
);
560 if (configGetStr(themeConfig
, elemProp
, &temp
)) {
561 if (!strncmp(temp
, "DIM_INF", 7))
562 elem
->height
= screenHeight
;
564 elem
->height
= atoi(temp
);
568 snprintf(elemProp
, 64, "%s_aligned", name
);
569 if (configGetInt(themeConfig
, elemProp
, &intValue
))
570 elem
->aligned
= intValue
;
572 elem
->aligned
= aligned
;
574 snprintf(elemProp
, 64, "%s_scaled", name
);
575 if (configGetInt(themeConfig
, elemProp
, &intValue
))
576 elem
->scaled
= intValue
;
578 elem
->scaled
= scaled
;
580 snprintf(elemProp
, 64, "%s_color", name
);
581 if (configGetColor(themeConfig
, elemProp
, charColor
))
582 elem
->color
= GS_SETREG_RGBA(charColor
[0], charColor
[1], charColor
[2], 0xff);
586 snprintf(elemProp
, 64, "%s_font", name
);
587 if (configGetInt(themeConfig
, elemProp
, &intValue
))
589 if (font
>= 0 && font
< THM_MAX_FONTS
)
590 elem
->font
= theme
->fonts
[font
];
592 elem
->font
= FNT_DEFAULT
;
597 // Internal elements ////////////////////////////////////////////////////////////////////////////////////////////////////////
599 static void drawBackground(struct menu_list
* menu
, struct submenu_list
* item
, config_set_t
* config
, struct theme_element
* elem
) {
603 static void initBackground(char* themePath
, config_set_t
* themeConfig
, theme_t
* theme
, theme_element_t
* elem
, char* name
,
604 char* pattern
, int count
, char* texture
) {
606 mutable_image_t
* mutableImage
= initMutableImage(themePath
, themeConfig
, theme
, name
, elem
->type
, pattern
, count
, texture
, NULL
);
607 elem
->extended
= mutableImage
;
608 elem
->endElem
= &endMutableImage
;
610 if (mutableImage
->cache
)
611 elem
->drawElem
= &drawGameImage
;
612 else if (mutableImage
->defaultTexture
)
613 elem
->drawElem
= &drawStaticImage
;
615 elem
->drawElem
= &drawBackground
;
618 static void drawMenuIcon(struct menu_list
* menu
, struct submenu_list
* item
, config_set_t
* config
, struct theme_element
* elem
) {
619 GSTEXTURE
* menuIconTex
= thmGetTexture(menu
->item
->icon_id
);
620 if (menuIconTex
&& menuIconTex
->Mem
)
621 rmDrawPixmap(menuIconTex
, elem
->posX
, elem
->posY
, elem
->aligned
, elem
->width
, elem
->height
, elem
->scaled
, gDefaultCol
);
624 static void drawMenuText(struct menu_list
* menu
, struct submenu_list
* item
, config_set_t
* config
, struct theme_element
* elem
) {
625 GSTEXTURE
* leftIconTex
= NULL
, *rightIconTex
= NULL
;
627 leftIconTex
= thmGetTexture(LEFT_ICON
);
629 rightIconTex
= thmGetTexture(RIGHT_ICON
);
632 int offset
= elem
->width
>> 1;
633 if (leftIconTex
&& leftIconTex
->Mem
)
634 rmDrawPixmap(leftIconTex
, elem
->posX
- offset
, elem
->posY
, elem
->aligned
, leftIconTex
->Width
, leftIconTex
->Height
, elem
->scaled
, gDefaultCol
);
635 if (rightIconTex
&& rightIconTex
->Mem
)
636 rmDrawPixmap(rightIconTex
, elem
->posX
+ offset
, elem
->posY
, elem
->aligned
, rightIconTex
->Width
, rightIconTex
->Height
, elem
->scaled
, gDefaultCol
);
639 if (leftIconTex
&& leftIconTex
->Mem
)
640 rmDrawPixmap(leftIconTex
, elem
->posX
- leftIconTex
->Width
, elem
->posY
, elem
->aligned
, leftIconTex
->Width
, leftIconTex
->Height
, elem
->scaled
, gDefaultCol
);
641 if (rightIconTex
&& rightIconTex
->Mem
)
642 rmDrawPixmap(rightIconTex
, elem
->posX
+ elem
->width
, elem
->posY
, elem
->aligned
, rightIconTex
->Width
, rightIconTex
->Height
, elem
->scaled
, gDefaultCol
);
644 fntRenderString(elem
->font
, elem
->posX
, elem
->posY
, elem
->aligned
, menuItemGetText(menu
->item
), elem
->color
);
647 static void drawItemsList(struct menu_list
* menu
, struct submenu_list
* item
, config_set_t
* config
, struct theme_element
* elem
) {
649 items_list_t
* itemsList
= (items_list_t
*) elem
->extended
;
651 int posX
= elem
->posX
, posY
= elem
->posY
;
653 posX
-= elem
->width
>> 1;
654 posY
-= elem
->height
>> 1;
657 submenu_list_t
*ps
= menu
->item
->pagestart
;
660 while (ps
&& (others
++ < itemsList
->displayedItems
)) {
662 color
= gTheme
->selTextColor
;
666 if (itemsList
->decoratorImage
) {
667 GSTEXTURE
* itemIconTex
= getGameImageTexture(itemsList
->decoratorImage
->cache
, menu
->item
->userdata
, &ps
->item
);
668 if (itemIconTex
&& itemIconTex
->Mem
)
669 rmDrawPixmap(itemIconTex
, posX
, posY
, ALIGN_NONE
, DECORATOR_SIZE
, DECORATOR_SIZE
, elem
->scaled
, gDefaultCol
);
671 if (itemsList
->decoratorImage
->defaultTexture
)
672 rmDrawPixmap(&itemsList
->decoratorImage
->defaultTexture
->source
, posX
, posY
, ALIGN_NONE
, DECORATOR_SIZE
, DECORATOR_SIZE
, elem
->scaled
, gDefaultCol
);
674 fntRenderText(elem
->font
, posX
+ DECORATOR_SIZE
, posY
, ALIGN_NONE
, elem
->width
, elem
->height
, submenuItemGetText(&ps
->item
), color
);
676 fntRenderText(elem
->font
, posX
, posY
, ALIGN_NONE
, elem
->width
, elem
->height
, submenuItemGetText(&ps
->item
), color
);
678 posY
+= MENU_ITEM_HEIGHT
;
684 static void initItemsList(char* themePath
, config_set_t
* themeConfig
, theme_t
* theme
, theme_element_t
* elem
, char* name
, char* decorator
) {
687 items_list_t
* itemsList
= (items_list_t
*) malloc(sizeof(items_list_t
));
689 if (elem
->width
== DIM_UNDEF
)
690 elem
->width
= screenWidth
;
692 if (elem
->height
== DIM_UNDEF
)
693 elem
->height
= theme
->usedHeight
- (MENU_POS_V
+ HINT_HEIGHT
);
695 itemsList
->displayedItems
= elem
->height
/ MENU_ITEM_HEIGHT
;
696 LOG("elemItemsList %s: displaying %d elems, item height: %d\n", name
, itemsList
->displayedItems
, elem
->height
);
698 itemsList
->decorator
= NULL
;
699 snprintf(elemProp
, 64, "%s_decorator", name
);
700 configGetStr(themeConfig
, elemProp
, &decorator
);
702 itemsList
->decorator
= decorator
; // Will be used later (thmValidate)
704 itemsList
->decoratorImage
= NULL
;
706 elem
->extended
= itemsList
;
707 // elem->endElem = &endBasic; does the job
709 elem
->drawElem
= &drawItemsList
;
712 static void drawItemText(struct menu_list
* menu
, struct submenu_list
* item
, config_set_t
* config
, struct theme_element
* elem
) {
714 item_list_t
*support
= menu
->item
->userdata
;
715 fntRenderString(elem
->font
, elem
->posX
, elem
->posY
, elem
->aligned
, support
->itemGetStartup(item
->item
.id
), elem
->color
);
719 static void drawHintText(struct menu_list
* menu
, struct submenu_list
* item
, config_set_t
* config
, struct theme_element
* elem
) {
720 menu_hint_item_t
* hint
= menu
->item
->hints
;
724 for (; hint
; hint
= hint
->next
) {
725 x
= guiDrawIconAndText(hint
->icon_id
, hint
->text_id
, elem
->font
, x
, elem
->posY
, elem
->color
);
731 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
733 static void validateGUIElems(char* themePath
, config_set_t
* themeConfig
, theme_t
* theme
) {
734 // 1. check we have a valid Background elements
735 if ( !theme
->mainElems
.first
|| (theme
->mainElems
.first
->type
!= TYPE_BACKGROUND
) ) {
736 LOG("No valid background found for main, add default BG_ART\n");
737 theme_element_t
* backgroundElem
= initBasic(themePath
, themeConfig
, theme
, "bg", TYPE_BACKGROUND
, 0, 0, ALIGN_NONE
, screenWidth
, screenHeight
, SCALING_NONE
, gDefaultCol
, FNT_DEFAULT
);
739 initBackground(themePath
, themeConfig
, theme
, backgroundElem
, "bg", "BG", 1, "background");
741 initBackground(themePath
, themeConfig
, theme
, backgroundElem
, "bg", "BG", 1, NULL
);
742 backgroundElem
->next
= theme
->mainElems
.first
;
743 theme
->mainElems
.first
= backgroundElem
;
746 if (theme
->infoElems
.first
) {
747 if (theme
->infoElems
.first
->type
!= TYPE_BACKGROUND
) {
748 LOG("No valid background found for info, add default BG_ART\n");
749 theme_element_t
* backgroundElem
= initBasic(themePath
, themeConfig
, theme
, "bg", TYPE_BACKGROUND
, 0, 0, ALIGN_NONE
, screenWidth
, screenHeight
, SCALING_NONE
, gDefaultCol
, FNT_DEFAULT
);
751 initBackground(themePath
, themeConfig
, theme
, backgroundElem
, "bg", "BG", 1, "background");
753 initBackground(themePath
, themeConfig
, theme
, backgroundElem
, "bg", "BG", 1, NULL
);
754 backgroundElem
->next
= theme
->infoElems
.first
;
755 theme
->infoElems
.first
= backgroundElem
;
759 // 2. check we have a valid ItemsList element, and link its decorator to the target element
760 if (theme
->itemsList
) {
761 items_list_t
* itemsList
= (items_list_t
*) theme
->itemsList
->extended
;
762 if (itemsList
->decorator
) {
763 // Second pass to find the decorator
764 theme_element_t
* decoratorElem
= theme
->mainElems
.first
;
765 while (decoratorElem
) {
766 if (decoratorElem
->type
== TYPE_GAME_IMAGE
) {
767 mutable_image_t
* gameImage
= (mutable_image_t
*) decoratorElem
->extended
;
768 if (!strcmp(itemsList
->decorator
, gameImage
->cache
->suffix
)) {
769 // if user want to cache less than displayed items, then disable itemslist icons, if not would load constantly
770 if (gameImage
->cache
->count
>= itemsList
->displayedItems
)
771 itemsList
->decoratorImage
= gameImage
;
776 decoratorElem
= decoratorElem
->next
;
778 itemsList
->decorator
= NULL
;
781 LOG("No itemsList found, adding a default one\n");
782 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
);
783 initItemsList(themePath
, themeConfig
, theme
, theme
->itemsList
, "il", NULL
);
784 theme
->itemsList
->next
= theme
->mainElems
.first
->next
; // Position the itemsList as second element (right after the Background)
785 theme
->mainElems
.first
->next
= theme
->itemsList
;
789 static int addGUIElem(char* themePath
, config_set_t
* themeConfig
, theme_t
* theme
, theme_elems_t
* elems
, char* type
, char* name
) {
793 theme_element_t
* elem
= NULL
;
795 snprintf(elemProp
, 64, "%s_enabled", name
);
796 configGetInt(themeConfig
, elemProp
, &enabled
);
799 snprintf(elemProp
, 64, "%s_type", name
);
800 configGetStr(themeConfig
, elemProp
, &type
);
802 if (!strcmp(elementsType
[TYPE_ATTRIBUTE_TEXT
], type
)) {
803 elem
= initBasic(themePath
, themeConfig
, theme
, name
, TYPE_ATTRIBUTE_TEXT
, 0, 0, ALIGN_CENTER
, DIM_UNDEF
, DIM_UNDEF
, SCALING_RATIO
, theme
->textColor
, FNT_DEFAULT
);
804 initAttributeText(themePath
, themeConfig
, theme
, elem
, name
, NULL
);
805 } else if (!strcmp(elementsType
[TYPE_STATIC_TEXT
], type
)) {
806 elem
= initBasic(themePath
, themeConfig
, theme
, name
, TYPE_STATIC_TEXT
, 0, 0, ALIGN_CENTER
, DIM_UNDEF
, DIM_UNDEF
, SCALING_RATIO
, theme
->textColor
, FNT_DEFAULT
);
807 initStaticText(themePath
, themeConfig
, theme
, elem
, name
, NULL
);
808 } else if (!strcmp(elementsType
[TYPE_ATTRIBUTE_IMAGE
], type
)) {
809 elem
= initBasic(themePath
, themeConfig
, theme
, name
, TYPE_ATTRIBUTE_IMAGE
, 0, 0, ALIGN_CENTER
, DIM_UNDEF
, DIM_UNDEF
, SCALING_RATIO
, gDefaultCol
, FNT_DEFAULT
);
810 initAttributeImage(themePath
, themeConfig
, theme
, elem
, name
);
811 } else if (!strcmp(elementsType
[TYPE_GAME_IMAGE
], type
)) {
812 elem
= initBasic(themePath
, themeConfig
, theme
, name
, TYPE_GAME_IMAGE
, 0, 0, ALIGN_CENTER
, DIM_UNDEF
, DIM_UNDEF
, SCALING_RATIO
, gDefaultCol
, FNT_DEFAULT
);
813 initGameImage(themePath
, themeConfig
, theme
, elem
, name
, NULL
, 1, NULL
, NULL
);
814 } else if (!strcmp(elementsType
[TYPE_STATIC_IMAGE
], type
)) {
815 elem
= initBasic(themePath
, themeConfig
, theme
, name
, TYPE_STATIC_IMAGE
, 0, 0, ALIGN_CENTER
, DIM_UNDEF
, DIM_UNDEF
, SCALING_RATIO
, gDefaultCol
, FNT_DEFAULT
);
816 initStaticImage(themePath
, themeConfig
, theme
, elem
, name
, NULL
);
817 } else if (!strcmp(elementsType
[TYPE_BACKGROUND
], type
)) {
818 if (!elems
->first
) { // Background elem can only be the first one
819 elem
= initBasic(themePath
, themeConfig
, theme
, name
, TYPE_BACKGROUND
, 0, 0, ALIGN_NONE
, screenWidth
, screenHeight
, SCALING_NONE
, gDefaultCol
, FNT_DEFAULT
);
820 initBackground(themePath
, themeConfig
, theme
, elem
, name
, NULL
, 1, NULL
);
822 } else if (!strcmp(elementsType
[TYPE_MENU_ICON
], type
)) {
823 elem
= initBasic(themePath
, themeConfig
, theme
, name
, TYPE_MENU_ICON
, 40, 40, ALIGN_CENTER
, DIM_UNDEF
, DIM_UNDEF
, SCALING_RATIO
, gDefaultCol
, FNT_DEFAULT
);
824 elem
->drawElem
= &drawMenuIcon
;
825 } else if (!strcmp(elementsType
[TYPE_MENU_TEXT
], type
)) {
826 elem
= initBasic(themePath
, themeConfig
, theme
, name
, TYPE_MENU_TEXT
, screenWidth
>> 1, 20, ALIGN_CENTER
, 200, 20, SCALING_RATIO
, theme
->textColor
, FNT_DEFAULT
);
827 elem
->drawElem
= &drawMenuText
;
828 } else if (!strcmp(elementsType
[TYPE_ITEMS_LIST
], type
)) {
829 if (!theme
->itemsList
) {
830 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
);
831 initItemsList(themePath
, themeConfig
, theme
, elem
, name
, NULL
);
832 theme
->itemsList
= elem
;
834 } else if (!strcmp(elementsType
[TYPE_ITEM_ICON
], type
)) {
835 elem
= initBasic(themePath
, themeConfig
, theme
, name
, TYPE_GAME_IMAGE
, 80, theme
->usedHeight
>> 1, ALIGN_CENTER
, DIM_UNDEF
, DIM_UNDEF
, SCALING_RATIO
, gDefaultCol
, FNT_DEFAULT
);
836 initGameImage(themePath
, themeConfig
, theme
, elem
, name
, "ICO", 20, NULL
, NULL
);
837 } else if (!strcmp(elementsType
[TYPE_ITEM_COVER
], type
)) {
838 elem
= initBasic(themePath
, themeConfig
, theme
, name
, TYPE_GAME_IMAGE
, 520, theme
->usedHeight
>> 1, ALIGN_CENTER
, DIM_UNDEF
, DIM_UNDEF
, SCALING_RATIO
, gDefaultCol
, FNT_DEFAULT
);
839 initGameImage(themePath
, themeConfig
, theme
, elem
, name
, "COV", 10, NULL
, NULL
);
840 } else if (!strcmp(elementsType
[TYPE_ITEM_TEXT
], type
)) {
841 elem
= initBasic(themePath
, themeConfig
, theme
, name
, TYPE_ITEM_TEXT
, 520, 370, ALIGN_CENTER
, DIM_UNDEF
, DIM_UNDEF
, SCALING_RATIO
, theme
->textColor
, FNT_DEFAULT
);
842 elem
->drawElem
= &drawItemText
;
843 } else if (!strcmp(elementsType
[TYPE_HINT_TEXT
], type
)) {
844 elem
= initBasic(themePath
, themeConfig
, theme
, name
, TYPE_HINT_TEXT
, 16, -HINT_HEIGHT
, ALIGN_NONE
, DIM_UNDEF
, DIM_UNDEF
, SCALING_RATIO
, theme
->textColor
, FNT_DEFAULT
);
845 elem
->drawElem
= &drawHintText
;
846 } else if (!strcmp(elementsType
[TYPE_LOADING_ICON
], type
)) {
847 if (!theme
->loadingIcon
)
848 theme
->loadingIcon
= initBasic(themePath
, themeConfig
, theme
, name
, TYPE_LOADING_ICON
, -50, -50, ALIGN_CENTER
, DIM_UNDEF
, DIM_UNDEF
, SCALING_RATIO
, gDefaultCol
, FNT_DEFAULT
);
858 elems
->last
->next
= elem
;
863 return 0; // ends the reading of elements
869 static void freeGUIElems(theme_elems_t
* elems
) {
870 theme_element_t
* elem
= elems
->first
;
872 elems
->first
= elem
->next
;
878 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
879 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
881 GSTEXTURE
* thmGetTexture(unsigned int id
) {
882 if (id
>= TEXTURES_COUNT
)
885 // see if the texture is valid
886 GSTEXTURE
* txt
= &gTheme
->textures
[id
];
895 static void thmFree(theme_t
* theme
) {
898 freeGUIElems(&theme
->mainElems
);
899 freeGUIElems(&theme
->infoElems
);
904 for(; id
< TEXTURES_COUNT
; id
++) {
905 texture
= &theme
->textures
[id
];
906 if (texture
->Mem
!= NULL
) {
913 for (id
= 0; id
< THM_MAX_FONTS
; ++id
) {
914 int fntid
= theme
->fonts
[id
];
916 if (fntid
!= FNT_DEFAULT
)
925 static int thmReadEntry(int index
, char* path
, char* separator
, char* name
, unsigned int mode
) {
926 LOG("thmReadEntry() path=%s sep=%s name=%s\n", path
, separator
, name
);
927 if (FIO_SO_ISDIR(mode
) && strstr(name
, "thm_")) {
928 theme_file_t
* currTheme
= &themes
[nThemes
+ index
];
930 int length
= strlen(name
) - 4 + 1;
931 currTheme
->name
= (char*) malloc(length
* sizeof(char));
932 memcpy(currTheme
->name
, name
+ 4, length
);
933 currTheme
->name
[length
- 1] = '\0';
935 length
= strlen(path
) + 1 + strlen(name
) + 1 + 1;
936 currTheme
->filePath
= (char*) malloc(length
* sizeof(char));
937 sprintf(currTheme
->filePath
, "%s%s%s%s", path
, separator
, name
, separator
);
939 LOG("Theme found: %s\n", currTheme
->filePath
);
946 /* themePath must contains the leading separator (as it is dependent of the device, we can't know here) */
947 static int thmLoadResource(int texId
, char* themePath
, short psm
, int useDefault
) {
949 GSTEXTURE
* texture
= &gTheme
->textures
[texId
];
951 if (themePath
!= NULL
)
952 success
= texDiscoverLoad(texture
, themePath
, texId
, psm
); // only set success here
954 if ((success
< 0) && useDefault
)
955 texPngLoad(texture
, NULL
, texId
, psm
); // we don't mind the result of "default"
960 static void thmSetColors(theme_t
* theme
) {
961 memcpy(theme
->bgColor
, gDefaultBgColor
, 3);
962 theme
->textColor
= GS_SETREG_RGBA(gDefaultTextColor
[0], gDefaultTextColor
[1], gDefaultTextColor
[2], 0xff);
963 theme
->uiTextColor
= GS_SETREG_RGBA(gDefaultUITextColor
[0], gDefaultUITextColor
[1], gDefaultUITextColor
[2], 0xff);
964 theme
->selTextColor
= GS_SETREG_RGBA(gDefaultSelTextColor
[0], gDefaultSelTextColor
[1], gDefaultSelTextColor
[2], 0xff);
966 theme_element_t
* elem
= theme
->mainElems
.first
;
968 elem
->color
= theme
->textColor
;
973 static void thmLoadFonts(config_set_t
* themeConfig
, const char* themePath
, theme_t
* theme
) {
974 int fntID
; // theme side font id, not the fntSys handle
975 for (fntID
= -1; fntID
< THM_MAX_FONTS
; ++fntID
) {
976 // does the font by the key exist?
979 // -1 is a placeholder for default font...
981 // Default font handle...
982 theme
->fonts
[fntID
] = FNT_DEFAULT
;
983 snprintf(fntKey
, 16, "font%d", fntID
);
985 snprintf(fntKey
, 16, "default_font");
989 int cfgKeyOK
= configGetStr(themeConfig
, fntKey
, &fntFile
);
990 if (!cfgKeyOK
&& (fntID
>= 0))
996 // replace the default font
998 snprintf(fullPath
, 128, "%s%s", themePath
, fntFile
);
1001 void* customFont
= readFile(fullPath
, -1, &size
);
1004 fntReplace(FNT_DEFAULT
, customFont
, size
, 1, 0);
1006 fntSetDefault(FNT_DEFAULT
);
1008 snprintf(fullPath
, 128, "%s%s", themePath
, fntFile
);
1009 int fntHandle
= fntLoadFile(fullPath
);
1011 // Do we have a valid font? Assign the font handle to the theme font slot
1012 if (fntHandle
!= FNT_ERROR
)
1013 theme
->fonts
[fntID
] = fntHandle
;
1018 static void thmLoad(char* themePath
) {
1019 LOG("thmLoad() path=%s\n", themePath
);
1020 theme_t
* curT
= gTheme
;
1021 theme_t
* newT
= (theme_t
*) malloc(sizeof(theme_t
));
1022 memset(newT
, 0, sizeof(theme_t
));
1024 newT
->useDefault
= 1;
1025 newT
->usedHeight
= 480;
1027 newT
->mainElems
.first
= NULL
;
1028 newT
->mainElems
.last
= NULL
;
1029 newT
->infoElems
.first
= NULL
;
1030 newT
->infoElems
.last
= NULL
;
1031 newT
->gameCacheCount
= 0;
1032 newT
->itemsList
= NULL
;
1033 newT
->loadingIcon
= NULL
;
1034 newT
->loadingIconCount
= LOAD7_ICON
- LOAD0_ICON
+ 1;
1036 config_set_t
* themeConfig
= NULL
;
1038 themeConfig
= configAlloc(0, NULL
, NULL
);
1039 addGUIElem(themePath
, themeConfig
, newT
, &newT
->mainElems
, elementsType
[TYPE_MENU_ICON
], "_");
1040 addGUIElem(themePath
, themeConfig
, newT
, &newT
->mainElems
, elementsType
[TYPE_MENU_TEXT
], "_");
1041 addGUIElem(themePath
, themeConfig
, newT
, &newT
->mainElems
, elementsType
[TYPE_ITEMS_LIST
], "_");
1042 addGUIElem(themePath
, themeConfig
, newT
, &newT
->mainElems
, elementsType
[TYPE_ITEM_ICON
], "_");
1043 addGUIElem(themePath
, themeConfig
, newT
, &newT
->mainElems
, elementsType
[TYPE_ITEM_COVER
], "_");
1044 addGUIElem(themePath
, themeConfig
, newT
, &newT
->mainElems
, elementsType
[TYPE_ITEM_TEXT
], "_");
1045 addGUIElem(themePath
, themeConfig
, newT
, &newT
->mainElems
, elementsType
[TYPE_HINT_TEXT
], "_");
1046 addGUIElem(themePath
, themeConfig
, newT
, &newT
->mainElems
, elementsType
[TYPE_LOADING_ICON
], "_");
1048 // reset the default font to be sure
1049 fntSetDefault(FNT_DEFAULT
);
1052 snprintf(path
, 255, "%sconf_theme.cfg", themePath
);
1053 themeConfig
= configAlloc(0, NULL
, path
);
1054 configRead(themeConfig
); // try to load the theme config file
1057 if (configGetInt(themeConfig
, "use_default", &intValue
))
1058 newT
->useDefault
= intValue
;
1060 if (configGetInt(themeConfig
, "use_real_height", &intValue
)) {
1062 newT
->usedHeight
= screenHeight
;
1065 configGetColor(themeConfig
, "bg_color", newT
->bgColor
);
1067 unsigned char color
[3];
1068 if (configGetColor(themeConfig
, "text_color", color
))
1069 newT
->textColor
= GS_SETREG_RGBA(color
[0], color
[1], color
[2], 0xff);
1071 if (configGetColor(themeConfig
, "ui_text_color", color
))
1072 newT
->uiTextColor
= GS_SETREG_RGBA(color
[0], color
[1], color
[2], 0xff);
1074 if (configGetColor(themeConfig
, "sel_text_color", color
))
1075 newT
->selTextColor
= GS_SETREG_RGBA(color
[0], color
[1], color
[2], 0xff);
1077 // before loading the element definitions, we have to have the fonts prepared
1078 // for that, we load the fonts and a translation table
1079 thmLoadFonts(themeConfig
, themePath
, newT
);
1082 snprintf(path
, 255, "main0");
1083 while (addGUIElem(themePath
, themeConfig
, newT
, &newT
->mainElems
, NULL
, path
))
1084 snprintf(path
, 255, "main%d", i
++);
1087 snprintf(path
, 255, "info0");
1088 while(addGUIElem(themePath
, themeConfig
, newT
, &newT
->infoElems
, NULL
, path
))
1089 snprintf(path
, 255, "info%d", i
++);
1092 validateGUIElems(themePath
, themeConfig
, newT
);
1093 configFree(themeConfig
);
1095 LOG("theme loaded, number of cache: %d\n", newT
->gameCacheCount
);
1097 LOG("thmLoad() usedHeight=%d\n", newT
->usedHeight
);
1099 /// Now swap theme and start loading textures
1100 if (newT
->usedHeight
== screenHeight
)
1101 rmResetShiftRatio();
1103 rmSetShiftRatio((float) screenHeight
/ newT
->usedHeight
);
1109 // default all to not loaded...
1110 for (i
= 0; i
< TEXTURES_COUNT
; i
++) {
1111 gTheme
->textures
[i
].Mem
= NULL
;
1114 // First start with busy icon
1115 char* path
= themePath
;
1117 for (i
= LOAD0_ICON
; i
<= LOAD7_ICON
; i
++) {
1118 if (thmLoadResource(i
, path
, GS_PSM_CT32
, gTheme
->useDefault
) >= 0)
1127 gTheme
->loadingIconCount
= i
;
1129 // Customizable icons
1130 for (i
= USB_ICON
; i
<= DOWN_ICON
; i
++)
1131 thmLoadResource(i
, themePath
, GS_PSM_CT32
, gTheme
->useDefault
);
1133 // Not customizable icons
1134 for (i
= L1_ICON
; i
<= START_ICON
; i
++)
1135 thmLoadResource(i
, NULL
, GS_PSM_CT32
, 1);
1137 // LOGO is hardcoded
1138 thmLoadResource(LOGO_PICTURE
, NULL
, GS_PSM_CT24
, 1);
1141 static void thmRebuildGuiNames() {
1143 free(guiThemesNames
);
1145 // build the languages name list
1146 guiThemesNames
= (char**) malloc((nThemes
+ 2) * sizeof(char**));
1148 // add default internal
1149 guiThemesNames
[0] = "<OPL>";
1152 for (; i
< nThemes
; i
++) {
1153 guiThemesNames
[i
+ 1] = themes
[i
].name
;
1156 guiThemesNames
[nThemes
+ 1] = NULL
;
1159 void thmAddElements(char* path
, char* separator
, int mode
) {
1160 LOG("thmAddElements() path=%s sep=%s\n", path
, separator
);
1161 nThemes
+= listDir(path
, separator
, THM_MAX_FILES
- nThemes
, &thmReadEntry
);
1162 LOG("thmAddElements() nThemes=%d\n", nThemes
);
1163 thmRebuildGuiNames();
1166 if (configGetStr(configGetByType(CONFIG_OPL
), "theme", &temp
)) {
1167 LOG("Trying to set again theme: %s\n", temp
);
1168 if (thmSetGuiValue(thmFindGuiID(temp
), 0))
1169 moduleUpdateMenu(mode
, 1);
1177 thmReloadScreenExtents();
1179 // initialize default internal
1182 thmAddElements(gBaseMCDir
, "/", -1);
1185 void thmReloadScreenExtents() {
1186 rmGetScreenExtents(&screenWidth
, &screenHeight
);
1189 char* thmGetValue() {
1190 //LOG("thmGetValue() id=%d name=%s\n", guiThemeID, guiThemesNames[guiThemeID]);
1191 return guiThemesNames
[guiThemeID
];
1194 int thmSetGuiValue(int themeID
, int reload
) {
1195 LOG("thmSetGuiValue() id=%d\n", themeID
);
1196 if (themeID
!= -1) {
1197 if (guiThemeID
!= themeID
|| reload
) {
1199 thmLoad(themes
[themeID
- 1].filePath
);
1203 guiThemeID
= themeID
;
1204 configSetStr(configGetByType(CONFIG_OPL
), "theme", thmGetValue());
1207 else if (guiThemeID
== 0)
1208 thmSetColors(gTheme
);
1213 int thmGetGuiValue() {
1214 //LOG("thmGetGuiValue() id=%d\n", guiThemeID);
1218 int thmFindGuiID(char* theme
) {
1219 LOG("thmFindGuiID() theme=%s\n", theme
);
1222 for (; i
< nThemes
; i
++) {
1223 if (stricmp(themes
[i
].name
, theme
) == 0)
1230 char **thmGetGuiList() {
1231 return guiThemesNames
;
1238 for (; i
< nThemes
; i
++) {
1239 free(themes
[i
].name
);
1240 free(themes
[i
].filePath
);
1243 free(guiThemesNames
);