diff --git a/assets/star_off.bin b/assets/star_off.bin new file mode 100644 index 0000000..20b455c Binary files /dev/null and b/assets/star_off.bin differ diff --git a/assets/star_on.bin b/assets/star_on.bin new file mode 100644 index 0000000..2922b05 Binary files /dev/null and b/assets/star_on.bin differ diff --git a/assets/star_small.bin b/assets/star_small.bin new file mode 100644 index 0000000..dbec733 Binary files /dev/null and b/assets/star_small.bin differ diff --git a/common/assets.c b/common/assets.c index e3cc541..8680ca3 100644 --- a/common/assets.c +++ b/common/assets.c @@ -27,6 +27,9 @@ assetsDataEntry g_assetsDataList[AssetId_Max] = { GENASSET("wifi3_icon.bin"), GENASSET("eth_icon.bin"), GENASSET("eth_none_icon.bin"), + GENASSET("star_small.bin"), + GENASSET("star_on.bin"), + GENASSET("star_off.bin"), }; static void assetsClearEntry(assetsDataEntry *entry) { diff --git a/common/assets.h b/common/assets.h index 6eb23e2..fed4a66 100644 --- a/common/assets.h +++ b/common/assets.h @@ -17,6 +17,9 @@ typedef enum { AssetId_wifi3_icon, AssetId_eth_icon, AssetId_eth_none_icon, + AssetId_star_small, + AssetId_star_on, + AssetId_star_off, AssetId_Max } AssetId; diff --git a/common/language.c b/common/language.c index e634e02..f8a95bb 100644 --- a/common/language.c +++ b/common/language.c @@ -1,4 +1,4 @@ -#include "language.h" +#include "language.h" #ifdef __SWITCH__ #define STR_JP(_str) [SetLanguage_JA] = _str @@ -331,6 +331,28 @@ const char* const g_strings[StrId_Max][16] = STR_TW("应用"), }, + [StrId_Actions_Star] = + { + STR_EN("Star"), + STR_FR("Star"), + STR_DE("Star"), + STR_ES("Star"), + STR_JP("Star"), + STR_KO("Star"), + STR_TW("Star"), + }, + + [StrId_Actions_UnStar] = + { + STR_EN("UnStar"), + STR_FR("UnStar"), + STR_DE("UnStar"), + STR_ES("UnStar"), + STR_JP("UnStar"), + STR_KO("UnStar"), + STR_TW("UnStar"), + }, + [StrId_ThemeMenu] = { STR_EN("Theme Menu"), diff --git a/common/language.h b/common/language.h index d76839c..8bf1f34 100644 --- a/common/language.h +++ b/common/language.h @@ -23,6 +23,8 @@ typedef enum StrId_Actions_Open, StrId_Actions_Back, StrId_Actions_Apply, + StrId_Actions_Star, + StrId_Actions_UnStar, StrId_MsgBox_OK, diff --git a/common/menu-entry.c b/common/menu-entry.c index ed90336..9f17974 100644 --- a/common/menu-entry.c +++ b/common/menu-entry.c @@ -490,6 +490,13 @@ bool menuEntryLoad(menuEntry_s* me, const char* name, bool shortcut) { return false; } + //check for .filename.star in same path + strptr = getSlash(me->path); + if (strptr[0] == '/') strptr++; + snprintf(tempbuf, sizeof(tempbuf)-1, "%.*s.%.*s.star", (int)((strlen(me->path)) - (strlen(strptr))), me->path, (int)(strlen(strptr)), strptr); + strcpy(me->starpath, tempbuf); + me->starred = fileExists(me->starpath); + return true; } diff --git a/common/menu-list.c b/common/menu-list.c index d693f54..1073622 100644 --- a/common/menu-list.c +++ b/common/menu-list.c @@ -96,20 +96,32 @@ static void menuSort(void) { menu_s* m = &s_menu[!s_curMenu]; int nEntries = m->nEntries; if (nEntries==0) return; + int nEntriesStar = 0, nEntriesNoStar = 0; menuEntry_s** list = (menuEntry_s**)calloc(nEntries, sizeof(menuEntry_s*)); if(list == NULL) return; + menuEntry_s** listStar = (menuEntry_s**)calloc(nEntries, sizeof(menuEntry_s*)); + if(listStar == NULL) return; menuEntry_s* p = m->firstEntry; for(i = 0; i < nEntries; ++i) { - list[i] = p; + if (p->starred) { + listStar[nEntriesStar++] = p; + } else { + list[nEntriesNoStar++] = p; + } p = p->next; } - qsort(list, nEntries, sizeof(menuEntry_s*), menuEntryCmp); + qsort(listStar, nEntriesStar, sizeof(menuEntry_s*), menuEntryCmp); + qsort(list, nEntriesNoStar, sizeof(menuEntry_s*), menuEntryCmp); menuEntry_s** pp = &m->firstEntry; - for(i = 0; i < nEntries; ++i) { + for(i = 0; i < nEntriesStar; ++i) { + *pp = listStar[i]; + pp = &(*pp)->next; + } + for(i = 0; i < nEntriesNoStar; ++i) { *pp = list[i]; pp = &(*pp)->next; } @@ -117,6 +129,14 @@ static void menuSort(void) { *pp = NULL; free(list); + free(listStar); +} + +void menuReSort (void) { + s_curMenu = !s_curMenu; + menuSort(); + s_curMenu = !s_curMenu; + menuClear(); } int menuScan(const char* target) { diff --git a/common/menu.c b/common/menu.c index 3643763..9201ad4 100644 --- a/common/menu.c +++ b/common/menu.c @@ -1,6 +1,7 @@ #include #include "common.h" #include "netloader.h" +#include #ifndef __SWITCH__ #include "switch/runtime/nxlink.h" @@ -29,6 +30,39 @@ void launchMenuEntryTask(menuEntry_s* arg) { launchMenuEntry(me); } +void toggleStarState(menuEntry_s* arg) { + menuEntry_s* me = arg; + if (me->starred) + { + if (fileExists(me->starpath)) + remove(me->starpath); + } else { + if (!fileExists(me->starpath)) + { + int fd = open(me->starpath,O_CREAT|O_WRONLY, ACCESSPERMS); + close(fd); + } + } + me->starred = fileExists(me->starpath); + //todo: error handling/message? + + menuReSort(); + menu_s* menu = menuGetCurrent(); + menuEntry_s* meSearch = menu->firstEntry; + menu->curEntry = -1; + int i = 0; + while (menu->curEntry == -1) + { + if (me == meSearch) + { + menu->curEntry = i; + } else { + meSearch = meSearch->next; + i++; + } + } +} + static enum { HBMENU_DEFAULT, @@ -73,6 +107,19 @@ void menuHandleAButton(void) { } } +void menuHandleXButton(void) { + menu_s* menu = menuGetCurrent(); + + if (menu->nEntries > 0 && hbmenu_state == HBMENU_DEFAULT) + { + int i; + menuEntry_s* me; + for (i = 0, me = menu->firstEntry; i != menu->curEntry; i ++, me = me->next); + toggleStarState(me); + } +} + + void launchApplyThemeTask(menuEntry_s* arg) { const char* themePath = arg->path; SetThemePathToConfig(themePath); @@ -246,6 +293,8 @@ static void drawEntry(menuEntry_s* me, int off_x, int is_active) { if (smallimg) { drawImage(start_x, start_y + 32, 140, 140, smallimg, IMAGE_MODE_RGB24); + if (me->starred) + drawImage(start_x + 105 + 12, start_y - 12, 35, 33, themeCurrent.starSmallImage, IMAGE_MODE_RGBA32); } if (is_active && largeimg) { @@ -283,6 +332,14 @@ static void drawEntry(menuEntry_s* me, int off_x, int is_active) { snprintf(tmpstr, sizeof(tmpstr)-1, "%s: %s", textGetString(StrId_AppInfo_Version), me->version); DrawText(interuiregular14, start_x, start_y + 28 + 30 + 18 + 6 + 18, themeCurrent.textColor, tmpstr); } + + if (me->starred) + { + drawImage(start_x - 64, 100, 64, 61, themeCurrent.starOnImage, IMAGE_MODE_RGBA32); + } else { + if (smallimg != theme_icon_small)//if (me->type != ENTRY_TYPE_THEME) <- why this crash? + drawImage(start_x - 64, 100, 64, 61, themeCurrent.starOffImage, IMAGE_MODE_RGBA32); + } } } @@ -666,6 +723,18 @@ void menuLoop(void) { } drawButtons(menu, false, &menupath_x_endpos); + + if(active_entry != NULL && active_entry->type != ENTRY_TYPE_THEME) { + getX = GetTextXCoordinate(interuiregular18, menupath_x_endpos - 32, textGetString(StrId_Actions_UnStar), 'r'); + DrawText(fontscale7, getX - 36, 720 - 47 + 24, themeCurrent.textColor, themeCurrent.buttonXText); + if (active_entry->starred) { + DrawText(interuiregular18, getX, 720 - 47 + 24, themeCurrent.textColor, textGetString(StrId_Actions_UnStar)); + } else { + DrawText(interuiregular18, getX, 720 - 47 + 24, themeCurrent.textColor, textGetString(StrId_Actions_Star)); + } + menupath_x_endpos = getX - 36 - 40; + } + } DrawTextTruncate(interuiregular18, 40, 720 - 47 + 24, themeCurrent.textColor, menu->dirname, menupath_x_endpos - 40, "..."); diff --git a/common/menu.h b/common/menu.h index bd7894f..2208d59 100644 --- a/common/menu.h +++ b/common/menu.h @@ -51,6 +51,7 @@ struct menuEntry_s_tag MenuEntryType type; char path[PATH_MAX+8]; + char starpath[PATH_MAX+8]; argData_s args; bool fileassoc_type;//0=file_extension, 1 = filename @@ -64,6 +65,8 @@ struct menuEntry_s_tag size_t icon_size; uint8_t *icon_gfx; uint8_t *icon_gfx_small; + + bool starred; NacpStruct *nacp; }; @@ -97,11 +100,13 @@ void menuDeleteEntry(menuEntry_s* me, bool skip_icongfx); menu_s* menuGetCurrent(void); menu_s* menuFileassocGetCurrent(void); +void menuReSort (void); int menuScan(const char* target); int themeMenuScan(const char* target); int menuFileassocScan(const char* target); void launchMenuEntryTask(menuEntry_s* arg); +void toggleStarState(menuEntry_s* arg); void launchApplyThemeTask(menuEntry_s* arg); void launchMenuBackTask(); void launchMenuNetloaderTask(); @@ -109,6 +114,7 @@ char *menuGetRootPath(void); char *menuGetRootBasePath(void); void menuHandleAButton(void); +void menuHandleXButton(void); bool menuIsNetloaderActive(void); diff --git a/common/theme.c b/common/theme.c index c18853b..7b0bfd7 100644 --- a/common/theme.c +++ b/common/theme.c @@ -26,10 +26,14 @@ void themeStartup(ThemePreset preset) { .enableWaveBlending = 0, .buttonAText = "\uE0E0", .buttonBText = "\uE0E1", + .buttonXText = "\uE0E2", .buttonYText = "\uE0E3", .buttonPText = "\uE0EF", .buttonMText = "\uE0F0", - .hbmenuLogoImage = assetsGetDataBuffer(AssetId_hbmenu_logo_light) + .hbmenuLogoImage = assetsGetDataBuffer(AssetId_hbmenu_logo_light), + .starSmallImage = assetsGetDataBuffer(AssetId_star_small), + .starOnImage = assetsGetDataBuffer(AssetId_star_on), + .starOffImage = assetsGetDataBuffer(AssetId_star_off) }; theme_t themeDark = (theme_t) { @@ -46,10 +50,14 @@ void themeStartup(ThemePreset preset) { .enableWaveBlending = 0, .buttonAText = "\uE0A0", .buttonBText = "\uE0A1", + .buttonXText = "\uE0A2", .buttonYText = "\uE0A3", .buttonPText = "\uE0B3", .buttonMText = "\uE0B4", - .hbmenuLogoImage = assetsGetDataBuffer(AssetId_hbmenu_logo_dark) + .hbmenuLogoImage = assetsGetDataBuffer(AssetId_hbmenu_logo_dark), + .starSmallImage = assetsGetDataBuffer(AssetId_star_small), + .starOnImage = assetsGetDataBuffer(AssetId_star_on), + .starOffImage = assetsGetDataBuffer(AssetId_star_off) }; char themePath[PATH_MAX] = {0}; @@ -61,7 +69,7 @@ void themeStartup(ThemePreset preset) { config_setting_t *theme = NULL; color_t text, frontWave, middleWave, backWave, background, highlight, separator, borderColor, borderTextColor, progressBarColor; int waveBlending; - const char *AText, *BText, *YText, *PText, *MText; + const char *AText, *BText, *XText, *YText, *PText, *MText; bool good_cfg = false; if(themePath[0]!=0) @@ -110,6 +118,8 @@ void themeStartup(ThemePreset preset) { AText = themeDefault->buttonAText; if (!config_setting_lookup_string(theme, "buttonBText", &BText)) BText = themeDefault->buttonBText; + if (!config_setting_lookup_string(theme, "buttonXText", &XText)) + XText = themeDefault->buttonXText; if (!config_setting_lookup_string(theme, "buttonYText", &YText)) YText = themeDefault->buttonYText; if (!config_setting_lookup_string(theme, "buttonPText", &PText)) @@ -132,6 +142,7 @@ void themeStartup(ThemePreset preset) { }; strncpy(themeCurrent.buttonAText, AText, sizeof(themeCurrent.buttonAText)-1); strncpy(themeCurrent.buttonBText, BText, sizeof(themeCurrent.buttonBText)-1); + strncpy(themeCurrent.buttonXText, XText, sizeof(themeCurrent.buttonXText)-1); strncpy(themeCurrent.buttonYText, YText, sizeof(themeCurrent.buttonYText)-1); strncpy(themeCurrent.buttonPText, PText, sizeof(themeCurrent.buttonPText)-1); strncpy(themeCurrent.buttonMText, MText, sizeof(themeCurrent.buttonMText)-1); diff --git a/common/theme.h b/common/theme.h index 65ef7d4..5869f4a 100644 --- a/common/theme.h +++ b/common/theme.h @@ -18,10 +18,14 @@ typedef struct bool enableWaveBlending; char buttonAText[32]; char buttonBText[32]; + char buttonXText[32]; char buttonYText[32]; char buttonPText[32]; char buttonMText[32]; const uint8_t *hbmenuLogoImage; + const uint8_t *starSmallImage; + const uint8_t *starOnImage; + const uint8_t *starOffImage; } theme_t; typedef enum diff --git a/nx_main/main.c b/nx_main/main.c index b968e7e..4b2a2c4 100644 --- a/nx_main/main.c +++ b/nx_main/main.c @@ -204,6 +204,10 @@ bool menuUpdate(void) { { launchMenuNetloaderTask(); } + else if (down & KEY_X) + { + menuHandleXButton(); + } else if (down & KEY_A) { menuHandleAButton(); diff --git a/nx_main/nx_touch.c b/nx_main/nx_touch.c index 1584033..593997b 100644 --- a/nx_main/nx_touch.c +++ b/nx_main/nx_touch.c @@ -13,6 +13,11 @@ #define BACK_BUTTON_END_X 1048 #define LAUNCH_BUTTON_START_X 1092 #define LAUNCH_BUTTON_END_X 1200 +#define STAR_BUTTON_START_X 426 +#define STAR_BUTTON_END_X 490 +#define STAR_BUTTON_START_Y 100 +#define STAR_BUTTON_END_Y 161 + #define distance(x1, y1, x2, y2) (int) sqrt(((x2 - x1) * (x2 - x1)) + ((y2 - y1) * (y2 - y1))) @@ -127,6 +132,16 @@ void handleTouch(menu_s* menu) { } } } + // Star + else { + int i; + menuEntry_s* me; + for (i = 0, me = menu->firstEntry; i != menu->curEntry; i ++, me = me->next); + if (me->type != ENTRY_TYPE_THEME && x1 > STAR_BUTTON_START_X && x1 < STAR_BUTTON_END_X + && y1 > STAR_BUTTON_START_Y && y1 < STAR_BUTTON_END_Y) { + menuHandleXButton(); + } + } } // Vertical Swipe else if (abs(x1 - x2) < VERTICAL_SWIPE_HORIZONTAL_PLAY && distance(x1, y1, x2, y2) > VERTICAL_SWIPE_MINIMUM_DISTANCE) { diff --git a/pc_main/main.cpp b/pc_main/main.cpp index f038dc7..dd1b574 100644 --- a/pc_main/main.cpp +++ b/pc_main/main.cpp @@ -74,6 +74,8 @@ extern "C" bool menuUpdate(void) { int new_esc_state = sf::Keyboard::isKeyPressed(sf::Keyboard::Escape); static int return_state = 0; int new_return_state = sf::Keyboard::isKeyPressed(sf::Keyboard::Return); + static int x_state = 0; + int new_x_state = sf::Keyboard::isKeyPressed(sf::Keyboard::X); static int y_state = 0; int new_y_state = sf::Keyboard::isKeyPressed(sf::Keyboard::Y); static int t_state = 0; @@ -85,6 +87,12 @@ extern "C" bool menuUpdate(void) { } + if(!new_x_state && x_state) + { + menuHandleXButton(); + + } + if (!new_esc_state && esc_state) { launchMenuBackTask(); diff --git a/resources/star_off.png b/resources/star_off.png new file mode 100644 index 0000000..e52b4e1 Binary files /dev/null and b/resources/star_off.png differ diff --git a/resources/star_on.png b/resources/star_on.png new file mode 100644 index 0000000..d1788c7 Binary files /dev/null and b/resources/star_on.png differ diff --git a/resources/star_small.png b/resources/star_small.png new file mode 100644 index 0000000..40523bb Binary files /dev/null and b/resources/star_small.png differ