diff --git a/Makefile b/Makefile index f29c44a..849ad3b 100644 --- a/Makefile +++ b/Makefile @@ -32,9 +32,9 @@ include $(DEVKITPRO)/libnx/switch_rules #--------------------------------------------------------------------------------- TARGET := JKSV BUILD := build -SOURCES := src src/ui src/fs +SOURCES := src src/ui src/fs src/gfx DATA := data -INCLUDES := inc inc/ui inc/fs +INCLUDES := inc inc/ui inc/fs inc/gfx EXEFS_SRC := exefs_src APP_TITLE := JKSV APP_AUTHOR := JK diff --git a/inc/gfx.h b/inc/gfx.h index 2a9c75b..94be689 100644 --- a/inc/gfx.h +++ b/inc/gfx.h @@ -1,18 +1,17 @@ #pragma once #include +#include "textureMgr.h" namespace gfx { extern SDL_Renderer *render; + extern gfx::textureMgr *texMgr; void init(); void exit(); void present(); - SDL_Texture *loadJPEGMem(const void *jpegData, size_t jpegSize); - SDL_Texture *loadImageFile(const char *file); - void drawTextf(SDL_Texture *target, int fontSize, int x, int y, const SDL_Color *c, const char *fmt, ...); void drawTextfWrap(SDL_Texture *target, int fontSize, int x, int y, int maxWidth, const SDL_Color* c, const char *fmt, ...); size_t getTextWidth(const char *str, int fontSize); diff --git a/inc/gfx/textureMgr.h b/inc/gfx/textureMgr.h new file mode 100644 index 0000000..08820dc --- /dev/null +++ b/inc/gfx/textureMgr.h @@ -0,0 +1,32 @@ +#pragma once + +#include +#include + +/*Texture manager class +Keeps pointers to ALL textures so it is not possible to forget to free them. Also keeps code a little easier to read. A little.*/ + +typedef enum +{ + IMG_FMT_PNG, + IMG_FMT_JPG, + IMG_FMT_BMP +} imgTypes; + +namespace gfx +{ + class textureMgr + { + public: + textureMgr() = default; + ~textureMgr(); + + void textureAdd(SDL_Texture *_tex); + SDL_Texture *textureCreate(int _w, int _h); + SDL_Texture *textureLoadFromFile(const char *_path); + SDL_Texture *textureLoadFromMem(imgTypes _type, const void *_dat, size_t _datSize); + + private: + std::vector textures; + }; +} diff --git a/src/cfg.cpp b/src/cfg.cpp index a77879f..8074a59 100644 --- a/src/cfg.cpp +++ b/src/cfg.cpp @@ -155,6 +155,7 @@ void cfg::resetConfig() cfg::config["autoName"] = false; cfg::sortType = cfg::ALPHA; ui::animScale = 3.0f; + cfg::config["autoUpload"] = false; } static inline bool textToBool(const std::string& _txt) @@ -437,6 +438,10 @@ void cfg::loadConfig() cfg::driveRefreshToken = cfgRead.getNextValueStr(); break; + case 20: + cfg::config["autoUpload"] = textToBool(cfgRead.getNextValueStr()); + break; + default: break; } @@ -474,6 +479,7 @@ void cfg::saveConfig() fprintf(cfgOut, "enableTrashBin = %s\n", boolToText(cfg::config["trashBin"]).c_str()); fprintf(cfgOut, "titleSortType = %s\n", sortTypeText().c_str()); fprintf(cfgOut, "animationScale = %f\n", ui::animScale); + fprintf(cfgOut, "autoUpload = %s\n", boolToText(cfg::config["autoUpload"]).c_str()); if(!cfg::driveRefreshToken.empty()) fprintf(cfgOut, "driveRefreshToken = %s\n", cfg::driveRefreshToken.c_str()); diff --git a/src/data.cpp b/src/data.cpp index fe37927..7bab6de 100644 --- a/src/data.cpp +++ b/src/data.cpp @@ -130,7 +130,7 @@ static inline void addTitleToList(const uint64_t& tid) if(cfg::isFavorite(tid)) data::titles[tid].fav = true; - data::titles[tid].icon = gfx::loadJPEGMem(ctrlData->icon, iconSize); + data::titles[tid].icon = gfx::texMgr->textureLoadFromMem(IMG_FMT_JPG, ctrlData->icon, iconSize); if(!data::titles[tid].icon) data::titles[tid].icon = util::createIconGeneric(util::getIDStrLower(tid).c_str(), 32, true); } @@ -215,7 +215,7 @@ static void importSVIs() data::titles[tid].fav = true; if(!data::titles[tid].icon && iconSize > 0) - data::titles[tid].icon = gfx::loadJPEGMem(iconBuffer, iconSize); + data::titles[tid].icon = gfx::texMgr->textureLoadFromMem(IMG_FMT_JPG, iconBuffer, iconSize); else if(!data::titles[tid].icon && iconSize == 0) data::titles[tid].icon = util::createIconGeneric(util::getIDStrLower(tid).c_str(), 32, true); } @@ -450,7 +450,7 @@ data::user::user(const AccountUid& _id, const std::string& _backupName, const st accountProfileGetImageSize(&prof, &jpgSize); uint8_t *jpegData = new uint8_t[jpgSize]; accountProfileLoadImage(&prof, jpegData, jpgSize, &jpgSize); - userIcon = gfx::loadJPEGMem(jpegData, jpgSize); + userIcon = gfx::texMgr->textureLoadFromMem(IMG_FMT_JPG, jpegData, jpgSize); delete[] jpegData; accountProfileClose(&prof); diff --git a/src/gfx.cpp b/src/gfx.cpp index 7f5e7ae..330fb42 100644 --- a/src/gfx.cpp +++ b/src/gfx.cpp @@ -13,6 +13,7 @@ static SDL_Window *wind; SDL_Renderer *gfx::render; +gfx::textureMgr *gfx::texMgr; static FT_Library lib; static FT_Face face[6]; @@ -102,6 +103,8 @@ void gfx::init() SDL_SetRenderDrawBlendMode(render, SDL_BLENDMODE_BLEND); + gfx::texMgr = new gfx::textureMgr; + loadSystemFont(); } @@ -110,9 +113,7 @@ void gfx::exit() IMG_Quit(); SDL_Quit(); freeSystemFont(); - - for(auto c : glyphCache) - SDL_DestroyTexture(c.second.tex); + delete gfx::texMgr; } void gfx::present() @@ -120,37 +121,6 @@ void gfx::present() SDL_RenderPresent(render); } -SDL_Texture *gfx::loadJPEGMem(const void *jpegData, size_t jpegsize) -{ - SDL_Texture *ret = NULL; - SDL_RWops *jpeg = SDL_RWFromConstMem(jpegData, jpegsize); - SDL_Surface *tmpSurf = IMG_LoadJPG_RW(jpeg); - if(tmpSurf) - { - ret = SDL_CreateTextureFromSurface(render, tmpSurf); - SDL_FreeSurface(tmpSurf); - } - SDL_RWclose(jpeg); - - SDL_SetTextureBlendMode(ret, SDL_BLENDMODE_BLEND); - - return ret; -} - -SDL_Texture *gfx::loadImageFile(const char *file) -{ - SDL_Texture *ret = NULL; - SDL_Surface *tmpSurf = IMG_Load(file); - if(tmpSurf) - { - ret = SDL_CreateTextureFromSurface(render, tmpSurf); - SDL_FreeSurface(tmpSurf); - } - SDL_SetTextureBlendMode(ret, SDL_BLENDMODE_BLEND); - - return ret; -} - static inline void resizeFont(int sz) { for(int i = 0; i < totalFonts; i++) @@ -197,6 +167,9 @@ static glyphData *getGlyph(uint32_t chr, int size) SDL_FreeSurface(tmpSurf); free(tmpBuff); + //Add it to texture manager so textures are freed on exit + gfx::texMgr->textureAdd(tex); + //Add it to cache map glyphCache[std::make_pair(chr, size)] = {(uint16_t)bmp.width, (uint16_t)bmp.rows, (int)glyph->advance.x >> 6, glyph->bitmap_top, glyph->bitmap_left, tex}; diff --git a/src/gfx/textureMgr.cpp b/src/gfx/textureMgr.cpp new file mode 100644 index 0000000..fcb975c --- /dev/null +++ b/src/gfx/textureMgr.cpp @@ -0,0 +1,108 @@ +#include +#include +#include + +#include "gfx.h" + +gfx::textureMgr::~textureMgr() +{ + for(auto tex : textures) + SDL_DestroyTexture(tex); +} + +void gfx::textureMgr::textureAdd(SDL_Texture *_tex) +{ + textures.push_back(_tex); +} + +SDL_Texture *gfx::textureMgr::textureCreate(int _w, int _h) +{ + SDL_Texture *ret = NULL; + ret = SDL_CreateTexture(gfx::render, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STATIC, _w, _h); + if(ret) + textures.push_back(ret); + return ret; +} + +SDL_Texture *gfx::textureMgr::textureLoadFromFile(const char *_path) +{ + SDL_Texture *ret = NULL; + SDL_Surface *tmp = IMG_Load(_path); + if(tmp) + { + ret = SDL_CreateTextureFromSurface(gfx::render, tmp); + textures.push_back(ret); + SDL_FreeSurface(tmp); + SDL_SetTextureBlendMode(ret, SDL_BLENDMODE_BLEND); + } + return ret; +} + +static SDL_Texture *loadPNGMem(const void *_dat, size_t _datSize) +{ + SDL_Texture *ret = NULL; + SDL_RWops *pngData = SDL_RWFromConstMem(_dat, _datSize); + SDL_Surface *tmp = IMG_LoadPNG_RW(pngData); + if(tmp) + { + ret = SDL_CreateTextureFromSurface(gfx::render, tmp); + SDL_FreeSurface(tmp); + SDL_SetTextureBlendMode(ret, SDL_BLENDMODE_BLEND); + } + SDL_RWclose(pngData); + return ret; +} + +static SDL_Texture *loadJPEGMem(const void *_dat, size_t _datSize) +{ + SDL_Texture *ret = NULL; + SDL_RWops *jpegData = SDL_RWFromConstMem(_dat, _datSize); + SDL_Surface *tmp = IMG_LoadJPG_RW(jpegData); + if(tmp) + { + ret = SDL_CreateTextureFromSurface(gfx::render, tmp); + SDL_FreeSurface(tmp); + SDL_SetTextureBlendMode(ret, SDL_BLENDMODE_BLEND); + } + SDL_RWclose(jpegData); + return ret; +} + +static SDL_Texture *loadBMPMem(const void *_dat, size_t _datSize) +{ + SDL_Texture *ret = NULL; + SDL_RWops *bmpData = SDL_RWFromConstMem(_dat, _datSize); + SDL_Surface *tmp = IMG_LoadBMP_RW(bmpData); + if(tmp) + { + ret = SDL_CreateTextureFromSurface(gfx::render, tmp); + SDL_FreeSurface(tmp); + SDL_SetTextureBlendMode(ret, SDL_BLENDMODE_BLEND); + } + SDL_RWclose(bmpData); + return ret; +} + +SDL_Texture *gfx::textureMgr::textureLoadFromMem(imgTypes _type, const void *_dat, size_t _datSize) +{ + SDL_Texture *ret = NULL; + switch (_type) + { + case IMG_FMT_PNG: + ret = loadPNGMem(_dat, _datSize); + break; + + case IMG_FMT_JPG: + ret = loadJPEGMem(_dat, _datSize); + break; + + case IMG_FMT_BMP: + ret = loadBMPMem(_dat, _datSize); + break; + } + + if(ret) + textures.push_back(ret); + + return ret; +} \ No newline at end of file diff --git a/src/ui.cpp b/src/ui.cpp index 12b544b..4a34d79 100644 --- a/src/ui.cpp +++ b/src/ui.cpp @@ -102,10 +102,10 @@ void ui::initTheme() void ui::init() { - mnuTopLeft = gfx::loadImageFile("romfs:/img/fb/menuTopLeft.png"); - mnuTopRight = gfx::loadImageFile("romfs:/img/fb/menuTopRight.png"); - mnuBotLeft = gfx::loadImageFile("romfs:/img/fb/menuBotLeft.png"); - mnuBotRight = gfx::loadImageFile("romfs:/img/fb/menuBotRight.png"); + mnuTopLeft = gfx::texMgr->textureLoadFromFile("romfs:/img/fb/menuTopLeft.png"); + mnuTopRight = gfx::texMgr->textureLoadFromFile("romfs:/img/fb/menuTopRight.png"); + mnuBotLeft = gfx::texMgr->textureLoadFromFile("romfs:/img/fb/menuBotLeft.png"); + mnuBotRight = gfx::texMgr->textureLoadFromFile("romfs:/img/fb/menuBotRight.png"); corePanel = SDL_CreateTexture(gfx::render, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET | SDL_TEXTUREACCESS_STATIC, 1220, 559); SDL_SetTextureBlendMode(corePanel, SDL_BLENDMODE_BLEND); @@ -114,26 +114,26 @@ void ui::init() { case ColorSetId_Light: //Dark corners - cornerTopLeft = gfx::loadImageFile("romfs:/img/tboxLght/tboxCornerTopLeft.png"); - cornerTopRight = gfx::loadImageFile("romfs:/img/tboxLght/tboxCornerTopRight.png"); - cornerBottomLeft = gfx::loadImageFile("romfs:/img/tboxLght/tboxCornerBotLeft.png"); - cornerBottomRight = gfx::loadImageFile("romfs:/img/tboxLght/tboxCornerBotRight.png"); - progCovLeft = gfx::loadImageFile("romfs:/img/tboxDrk/progBarCoverLeftDrk.png"); - progCovRight = gfx::loadImageFile("romfs:/img/tboxDrk/progBarCoverRightDrk.png"); - icn = gfx::loadImageFile("romfs:/img/icn/icnDrk.png"); - sideBar = gfx::loadImageFile("romfs:/img/fb/lLight.png"); + cornerTopLeft = gfx::texMgr->textureLoadFromFile("romfs:/img/tboxLght/tboxCornerTopLeft.png"); + cornerTopRight = gfx::texMgr->textureLoadFromFile("romfs:/img/tboxLght/tboxCornerTopRight.png"); + cornerBottomLeft = gfx::texMgr->textureLoadFromFile("romfs:/img/tboxLght/tboxCornerBotLeft.png"); + cornerBottomRight = gfx::texMgr->textureLoadFromFile("romfs:/img/tboxLght/tboxCornerBotRight.png"); + progCovLeft = gfx::texMgr->textureLoadFromFile("romfs:/img/tboxDrk/progBarCoverLeftDrk.png"); + progCovRight = gfx::texMgr->textureLoadFromFile("romfs:/img/tboxDrk/progBarCoverRightDrk.png"); + icn = gfx::texMgr->textureLoadFromFile("romfs:/img/icn/icnDrk.png"); + sideBar = gfx::texMgr->textureLoadFromFile("romfs:/img/fb/lLight.png"); break; default: //Light corners - cornerTopLeft = gfx::loadImageFile("romfs:/img/tboxDrk/tboxCornerTopLeft.png"); - cornerTopRight = gfx::loadImageFile("romfs:/img/tboxDrk/tboxCornerTopRight.png"); - cornerBottomLeft = gfx::loadImageFile("romfs:/img/tboxDrk/tboxCornerBotLeft.png"); - cornerBottomRight = gfx::loadImageFile("romfs:/img/tboxDrk/tboxCornerBotRight.png"); - progCovLeft = gfx::loadImageFile("romfs:/img/tboxLght/progBarCoverLeftLight.png"); - progCovRight = gfx::loadImageFile("romfs:/img/tboxLght/progBarCoverRightLight.png"); - icn = gfx::loadImageFile("romfs:/img/icn/icnLght.png"); - sideBar = gfx::loadImageFile("romfs:/img/fb/lDark.png"); + cornerTopLeft = gfx::texMgr->textureLoadFromFile("romfs:/img/tboxDrk/tboxCornerTopLeft.png"); + cornerTopRight = gfx::texMgr->textureLoadFromFile("romfs:/img/tboxDrk/tboxCornerTopRight.png"); + cornerBottomLeft = gfx::texMgr->textureLoadFromFile("romfs:/img/tboxDrk/tboxCornerBotLeft.png"); + cornerBottomRight = gfx::texMgr->textureLoadFromFile("romfs:/img/tboxDrk/tboxCornerBotRight.png"); + progCovLeft = gfx::texMgr->textureLoadFromFile("romfs:/img/tboxLght/progBarCoverLeftLight.png"); + progCovRight = gfx::texMgr->textureLoadFromFile("romfs:/img/tboxLght/progBarCoverRightLight.png"); + icn = gfx::texMgr->textureLoadFromFile("romfs:/img/icn/icnLght.png"); + sideBar = gfx::texMgr->textureLoadFromFile("romfs:/img/fb/lDark.png"); break; } @@ -166,22 +166,6 @@ void ui::exit() delete popMessages; delete threadMngr; - - SDL_DestroyTexture(cornerTopLeft); - SDL_DestroyTexture(cornerTopRight); - SDL_DestroyTexture(cornerBottomLeft); - SDL_DestroyTexture(cornerBottomRight); - SDL_DestroyTexture(progCovLeft); - SDL_DestroyTexture(progCovRight); - - SDL_DestroyTexture(mnuTopLeft); - SDL_DestroyTexture(mnuTopRight); - SDL_DestroyTexture(mnuBotLeft); - SDL_DestroyTexture(mnuBotRight); - - SDL_DestroyTexture(corePanel); - - SDL_DestroyTexture(icn); } int ui::registerPanel(slideOutPanel *sop) @@ -197,12 +181,11 @@ threadInfo *ui::newThread(ThreadFunc func, void *args, funcPtr _drawFunc) void ui::showLoadScreen() { - SDL_Texture *icon = gfx::loadImageFile("romfs:/icon.png"); + SDL_Texture *icon = gfx::texMgr->textureLoadFromFile("romfs:/icon.png"); gfx::clearTarget(NULL, &ui::clearClr); gfx::texDraw(NULL, icon, 512, 232); gfx::drawTextf(NULL, 16, 1100, 673, &ui::txtCont, ui::getUICString("loadingStartPage", 0)); gfx::present(); - SDL_DestroyTexture(icon); } void ui::drawUI() diff --git a/src/ui/fld.cpp b/src/ui/fld.cpp index 11bed8c..2751486 100644 --- a/src/ui/fld.cpp +++ b/src/ui/fld.cpp @@ -184,7 +184,7 @@ static void fldFuncDownload_t(void *a) dlFile.path = targetPath; dlFile.size = in->size; dlFile.o = &cpy->offset; - + fs::gDrive->downloadFile(in->id, &dlFile); //fclose(dlFile.f); diff --git a/src/ui/sett.cpp b/src/ui/sett.cpp index 2872c9d..f63915c 100644 --- a/src/ui/sett.cpp +++ b/src/ui/sett.cpp @@ -227,6 +227,10 @@ static void toggleOpt(void *a) if(ui::animScale > 8) ui::animScale = 1; break; + + case 21: + toggleBool(cfg::config["autoUpload"]); + break; } } @@ -251,6 +255,7 @@ static void updateMenuText() char tmp[16]; sprintf(tmp, "%.1f", ui::animScale); ui::settMenu->editOpt(20, NULL, ui::getUIString(settMenuStr, 20) + std::string(tmp)); + ui::settMenu->editOpt(21, NULL, ui::getUIString(settMenuStr, 21) + getBoolText(cfg::config["autoUpload"])); } void ui::settInit() @@ -267,7 +272,7 @@ void ui::settInit() optHelpX = 1220 - gfx::getTextWidth(ui::getUICString("helpSettings", 0), 18); - for(unsigned i = 0; i < 21; i++) + for(unsigned i = 0; i < 22; i++) { ui::settMenu->addOpt(NULL, ui::getUIString("settingsMenu", i)); ui::settMenu->optAddButtonEvent(i, HidNpadButton_A, toggleOpt, NULL); diff --git a/src/ui/uistr.cpp b/src/ui/uistr.cpp index 3672e03..1e75991 100644 --- a/src/ui/uistr.cpp +++ b/src/ui/uistr.cpp @@ -203,6 +203,7 @@ void ui::initStrings() addUIString("settingsMenu", 18, "Enable Trash Bin: "); addUIString("settingsMenu", 19, "Title Sorting Type: "); addUIString("settingsMenu", 20, "Animation Scale: "); + addUIString("settingsMenu", 21, "Auto-upload to Drive: "); //Main menu addUIString("mainMenuSettings", 0, "Settings");