From bed515818f5f6192c1c64b13a0428a2851762459 Mon Sep 17 00:00:00 2001 From: joel16 Date: Sat, 11 May 2024 15:17:53 -0400 Subject: [PATCH] imGui: Switch to SDL2 renderer backend --- CMakeLists.txt | 34 +- include/gui.h | 8 + include/imgui_impl_vitagl.h | 30 -- include/tabs.h | 40 +++ include/textures.h | 4 +- include/utils.h | 7 - source/gui.cpp | 596 ++++++++++------------------------- source/imgui_impl_vitagl.cpp | 300 ------------------ source/keyboard.cpp | 9 +- source/main.cpp | 80 +---- source/tabs/loadouts.cpp | 70 ++++ source/tabs/pages.cpp | 76 +++++ source/tabs/settings.cpp | 67 ++++ source/tabs/sort.cpp | 197 ++++++++++++ source/textures.cpp | 71 ++--- source/utils.cpp | 46 --- 16 files changed, 675 insertions(+), 960 deletions(-) delete mode 100644 include/imgui_impl_vitagl.h create mode 100644 include/tabs.h delete mode 100644 source/imgui_impl_vitagl.cpp create mode 100644 source/tabs/loadouts.cpp create mode 100644 source/tabs/pages.cpp create mode 100644 source/tabs/settings.cpp create mode 100644 source/tabs/sort.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 5c72101..e613619 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -28,10 +28,17 @@ add_definitions( set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3 -ffast-math -mtune=cortex-a9 -mfpu=neon -Wall -Wno-psabi -fno-rtti -std=gnu++17") set(VITA_MKSFOEX_FLAGS "${VITA_MKSFOEX_FLAGS} -d PARENTAL_LEVEL=1") +find_package(SDL2 REQUIRED) +find_package(SDL2_image REQUIRED) + include_directories( ${VITASDK}/arm-vita-eabi/include/freetype2/ + ${SDL2_INCLUDE_DIR} + ${SDL2_IMAGE_INCLUDE_DIRS} libs/imgui + libs/imgui/backends libs/sqlite3 + libs include ) @@ -45,13 +52,18 @@ add_executable(${PROJECT_NAME} libs/imgui/imgui_draw.cpp libs/imgui/imgui_tables.cpp libs/imgui/imgui_widgets.cpp + libs/imgui/backends/imgui_impl_sdl2.cpp + libs/imgui/backends/imgui_impl_sdlrenderer2.cpp libs/imgui/misc/freetype/imgui_freetype.cpp libs/sqlite3/sqlite3.c + source/tabs/loadouts.cpp + source/tabs/pages.cpp + source/tabs/settings.cpp + source/tabs/sort.cpp source/applist.cpp source/config.cpp source/fs.cpp source/gui.cpp - source/imgui_impl_vitagl.cpp source/keyboard.cpp source/loadouts.cpp source/log.cpp @@ -66,27 +78,11 @@ target_link_libraries(${PROJECT_NAME} freetype png pthread - lzma bz2 z - vitaGL - vitashark - mathneon - SceAppMgr_stub - SceAppUtil_stub - SceCommonDialog_stub - SceCtrl_stub - SceDisplay_stub - SceGxm_stub - SceKernelDmacMgr_stub + SDL2_image + SDL2::SDL2 SceLibJson_stub - SceLibKernel_stub - ScePower_stub - SceShaccCg_stub - SceShaccCgExt - SceSysmodule_stub - SceTouch_stub - taihen_stub ) ## Create Vita files diff --git a/include/gui.h b/include/gui.h index 2810ca9..eaf98a1 100644 --- a/include/gui.h +++ b/include/gui.h @@ -1,5 +1,13 @@ #pragma once +#include + namespace GUI { + SDL_Renderer *GetRenderer(void); + SDL_Window *GetWindow(void); + int Init(void); + void Exit(void); + void DisableButtonInit(bool disable); + void DisableButtonExit(bool disable); int RenderLoop(void); } diff --git a/include/imgui_impl_vitagl.h b/include/imgui_impl_vitagl.h deleted file mode 100644 index a16628f..0000000 --- a/include/imgui_impl_vitagl.h +++ /dev/null @@ -1,30 +0,0 @@ -// dear imgui: Renderer Backend for OpenGL2 (legacy OpenGL, fixed pipeline) -// This needs to be used along with a Platform Backend (e.g. GLFW, SDL, Win32, custom..) - -// Implemented features: -// [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID! - -// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. -// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. -// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp. -// Read online: https://github.com/ocornut/imgui/tree/master/docs - -// **DO NOT USE THIS CODE IF YOUR CODE/ENGINE IS USING MODERN OPENGL (SHADERS, VBO, VAO, etc.)** -// **Prefer using the code in imgui_impl_opengl3.cpp** -// This code is mostly provided as a reference to learn how ImGui integration works, because it is shorter to read. -// If your code is using GL3+ context or any semi modern OpenGL calls, using this is likely to make everything more -// complicated, will require your code to reset every single OpenGL attributes to their initial state, and might -// confuse your GPU driver. -// The GL2 code is unable to reset attributes or even call e.g. "glUseProgram(0)" because they don't exist in that API. - -#pragma once -#include "imgui.h" // IMGUI_IMPL_API - -IMGUI_API bool ImGui_ImplVitaGL_Init(void); -IMGUI_API void ImGui_ImplVitaGL_Shutdown(void); -IMGUI_API void ImGui_ImplVitaGL_NewFrame(void); -IMGUI_API void ImGui_ImplVitaGL_RenderDrawData(ImDrawData* draw_data); - -// Use if you want to reset your rendering device without losing ImGui state. -IMGUI_API bool ImGui_ImplVitaGL_CreateDeviceObjects(void); -IMGUI_API void ImGui_ImplVitaGL_DestroyDeviceObjects(void); diff --git a/include/tabs.h b/include/tabs.h new file mode 100644 index 0000000..82105ca --- /dev/null +++ b/include/tabs.h @@ -0,0 +1,40 @@ +#pragma once + +#include +#include +#include + +#include "applist.h" + +enum IconType { + App, + DB, + Folder, + Page, + Trash +}; + +enum SortMode { + SortDefault, + SortAsc, + SortDesc +}; + +enum State { + StateNone, + StateConfirmSort, + StateConfirmSwap, + StateRestore, + StateLoadoutRestore, + StateWarning, + StateDone, + StateDelete, + StateError +}; + +namespace Tabs { + void Sort(AppEntries &entries, State &state, bool &backupExists); + void Pages(AppEntries &entries, State &state, bool &backupExists); + void Loadouts(std::vector &loadouts, State &state, int &date_format, std::string &loadout_name); + void Settings(void); +} diff --git a/include/textures.h b/include/textures.h index ab2783a..878f18c 100644 --- a/include/textures.h +++ b/include/textures.h @@ -1,10 +1,10 @@ #pragma once -#include +#include #include typedef struct { - GLuint id = 0; + SDL_Texture *ptr = nullptr; int width = 0; int height = 0; } Tex; diff --git a/include/utils.h b/include/utils.h index 1082b46..970fb2a 100644 --- a/include/utils.h +++ b/include/utils.h @@ -1,6 +1,5 @@ #pragma once -#include #include /// Checks whether a result code indicates success. @@ -9,17 +8,11 @@ #define R_FAILED(res) ((res)<0) /// Returns the level of a result code. -extern int SCE_CTRL_ENTER, SCE_CTRL_CANCEL; -extern unsigned int pressed; - constexpr char db_path[] = "ur0:shell/db/app.db"; namespace Utils { int InitAppUtil(void); int EndAppUtil(void); - SceCtrlData ReadControls(void); - int GetEnterButton(void); - int GetCancelButton(void); int GetDateFormat(void); void GetDateString(char string[24], SceSystemParamDateFormat format, SceDateTime &time); } diff --git a/source/gui.cpp b/source/gui.cpp index 82ec024..1b7d578 100644 --- a/source/gui.cpp +++ b/source/gui.cpp @@ -2,66 +2,26 @@ #include #include #include -#include +#include #include "applist.h" #include "config.h" #include "fs.h" #define IMGUI_DEFINE_MATH_OPERATORS -#include "imgui_impl_vitagl.h" +#include "imgui_impl_sdl2.h" +#include "imgui_impl_sdlrenderer2.h" #include "imgui_internal.h" +#include "log.h" #include "loadouts.h" -#include "sqlite3.h" -#include "textures.h" +#include "tabs.h" #include "utils.h" -namespace Renderer { - static void End(bool clear, ImVec4 clear_color) { - glViewport(0, 0, static_cast(ImGui::GetIO().DisplaySize.x), static_cast(ImGui::GetIO().DisplaySize.y)); - - if (clear) { - glClearColor(clear_color.x, clear_color.y, clear_color.z, clear_color.w); - glClear(GL_COLOR_BUFFER_BIT); - } - - ImGui::Render(); - ImGui_ImplVitaGL_RenderDrawData(ImGui::GetDrawData()); - vglSwapBuffers(GL_TRUE); - } -} - namespace GUI { - enum State { - StateNone, - StateConfirmSort, - StateConfirmSwap, - StateRestore, - StateLoadoutRestore, - StateWarning, - StateDone, - StateDelete, - StateError - }; - - enum SortMode { - SortDefault, - SortAsc, - SortDesc - }; - - enum IconType { - App, - DB, - Folder, - Page, - Trash - }; - static bool backupExists = false; static const ImVec2 tex_size = ImVec2(20, 20); - static const char *sort_by[] = {"Title", "Title ID"}; - static const char *sort_folders[] = {"Both", "Apps only", "Folders only"}; - static int old_page_id = -1; + + static SDL_Window *window; + static SDL_Renderer *renderer; static void SetupPopup(const char *id) { ImGui::OpenPopup(id); @@ -85,23 +45,10 @@ namespace GUI { ImGui::PopStyleVar(); }; - static void DisableButtonInit(bool disable) { - if (disable) { - ImGui::PushItemFlag(ImGuiItemFlags_Disabled, true); - ImGui::PushStyleVar(ImGuiStyleVar_Alpha, ImGui::GetStyle().Alpha * 0.5f); - } - } - - static void DisableButtonExit(bool disable) { - if (disable) { - ImGui::PopItemFlag(); - ImGui::PopStyleVar(); - } - } - static void Prompt(State &state, AppEntries &entries, std::vector &loadouts, const std::string &db_name) { - if (state == StateNone) + if (state == StateNone) { return; + } std::string title, prompt; @@ -243,371 +190,153 @@ namespace GUI { GUI::ExitPopup(); } - static void SortTab(AppEntries &entries, State &state) { - ImGuiTableFlags tableFlags = ImGuiTableFlags_Resizable | ImGuiTableFlags_BordersInner | ImGuiTableFlags_BordersOuter | - ImGuiTableFlags_SizingStretchProp | ImGuiTableFlags_ScrollY; + static void Begin(void) { + ImGui_ImplSDLRenderer2_NewFrame(); + ImGui_ImplSDL2_NewFrame(); + ImGui::NewFrame(); + } + + static void End(ImGuiIO &io, ImVec4 clear_color, SDL_Renderer *renderer) { + ImGui::Render(); + SDL_RenderSetScale(renderer, io.DisplayFramebufferScale.x, io.DisplayFramebufferScale.y); + SDL_SetRenderDrawColor(renderer, (Uint8)(clear_color.x * 255), (Uint8)(clear_color.y * 255), (Uint8)(clear_color.z * 255), (Uint8)(clear_color.w * 255)); + SDL_RenderClear(renderer); + ImGui_ImplSDLRenderer2_RenderDrawData(ImGui::GetDrawData()); + SDL_RenderPresent(renderer); + } + + SDL_Renderer *GetRenderer(void) { + return renderer; + } + + SDL_Window *GetWindow(void) { + return window; + } + + int Init(void) { + if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_GAMECONTROLLER) != 0) { + Log::Error("SDL_Init failed: %s\n", SDL_GetError()); + return -1; + } - if (ImGui::BeginTabItem("Sort/Backup")) { - ImGui::Dummy(ImVec2(0.0f, 5.0f)); // Spacing - - ImGui::PushID("sort_by"); - ImGui::PushItemWidth(100.f); - if (ImGui::BeginCombo("", sort_by[cfg.sort_by])) { - for (int i = 0; i < IM_ARRAYSIZE(sort_by); i++) { - const bool is_selected = (cfg.sort_by == i); - - if (ImGui::Selectable(sort_by[i], is_selected)) { - cfg.sort_by = i; - Config::Save(cfg); - } - - if (is_selected) { - ImGui::SetItemDefaultFocus(); - } - } - - ImGui::EndCombo(); - } - ImGui::PopItemWidth(); - ImGui::PopID(); - - ImGui::SameLine(); - - ImGui::PushID("sort_folders"); - ImGui::PushItemWidth(150.f); - if (ImGui::BeginCombo("", sort_folders[cfg.sort_folders])) { - for (int i = 0; i < IM_ARRAYSIZE(sort_folders); i++) { - const bool is_selected = (cfg.sort_folders == i); - - if (ImGui::Selectable(sort_folders[i], is_selected)) { - cfg.sort_folders = i; - Config::Save(cfg); - } - - if (is_selected) { - ImGui::SetItemDefaultFocus(); - } - } - - ImGui::EndCombo(); - } - ImGui::PopItemWidth(); - ImGui::PopID(); - - ImGui::SameLine(); - - if (ImGui::RadioButton("Default", cfg.sort_mode == SortDefault)) { - cfg.sort_mode = SortDefault; - AppList::Get(entries); - } - - ImGui::SameLine(); - - if (ImGui::RadioButton("Asc", cfg.sort_mode == SortAsc)) { - cfg.sort_mode = SortAsc; - AppList::Get(entries); - std::sort(entries.icons.begin(), entries.icons.end(), AppList::SortAppAsc); - std::sort(entries.child_apps.begin(), entries.child_apps.end(), AppList::SortChildAppAsc); - AppList::Sort(entries); - } - - ImGui::SameLine(); - - if (ImGui::RadioButton("Desc", cfg.sort_mode == SortDesc)) { - cfg.sort_mode = SortDesc; - AppList::Get(entries); - std::sort(entries.icons.begin(), entries.icons.end(), AppList::SortAppDesc); - std::sort(entries.child_apps.begin(), entries.child_apps.end(), AppList::SortChildAppDesc); - AppList::Sort(entries); - } - - ImGui::SameLine(); - - GUI::DisableButtonInit(cfg.sort_mode == SortDefault); - if (ImGui::Button("Apply Sort", ImVec2(ImGui::GetContentRegionAvail().x * 0.5f, 0.0f))) { - state = StateConfirmSort; - } - GUI::DisableButtonExit(cfg.sort_mode == SortDefault); - - ImGui::SameLine(); - - GUI::DisableButtonInit(!backupExists); - if (ImGui::Button("Restore Backup", ImVec2(ImGui::GetContentRegionAvail().x * 1.0f, 0.0f))) { - state = StateRestore; - } - GUI::DisableButtonExit(!backupExists); - - ImGui::Dummy(ImVec2(0.0f, 5.0f)); // Spacing - - if (ImGui::BeginTable("AppList", 5, tableFlags)) { - ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthFixed); - ImGui::TableSetupColumn("Title"); - ImGui::TableSetupColumn("Page ID", ImGuiTableColumnFlags_WidthFixed); - ImGui::TableSetupColumn("Page No", ImGuiTableColumnFlags_WidthFixed); - ImGui::TableSetupColumn("Pos", ImGuiTableColumnFlags_WidthFixed); - ImGui::TableHeadersRow(); - - for (unsigned int i = 0, counter = 0; i < entries.icons.size(); i++) { - if (entries.icons[i].icon0Type == 7) { - ImGui::TableNextRow(); - - ImGui::TableNextColumn(); - ImGui::Image(reinterpret_cast(icons[Folder].id), tex_size); - - ImGui::TableNextColumn(); - std::string title = std::to_string(counter) + ") "; - title.append(entries.icons[i].title); - bool open = ImGui::TreeNodeEx(title.c_str(), ImGuiTreeNodeFlags_SpanFullWidth); - - ImGui::TableNextColumn(); - ImGui::Text("%d", entries.icons[i].pageId); - - ImGui::TableNextColumn(); - ImGui::Text("%d", entries.icons[i].pageNo); - - ImGui::TableNextColumn(); - ImGui::Text("%d", entries.icons[i].pos); - - if (open) { - ImGuiTreeNodeFlags flags = ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_Bullet | ImGuiTreeNodeFlags_NoTreePushOnOpen | ImGuiTreeNodeFlags_SpanFullWidth; - int reserved01 = std::stoi(std::string(entries.icons[i].reserved01)); - - for (unsigned int j = 0; j < entries.child_apps.size(); j++) { - if (entries.child_apps[j].pageNo == reserved01) { - ImGui::TableNextRow(); - ImGui::TableNextColumn(); - - ImGui::TableNextColumn(); - ImGui::TreeNodeEx(entries.child_apps[j].title, flags); - - ImGui::TableNextColumn(); - ImGui::Text("%d", entries.child_apps[j].pageId); - - ImGui::TableNextColumn(); - ImGui::Text("-"); - - ImGui::TableNextColumn(); - ImGui::Text("%d", entries.child_apps[j].pos); - } - } - - ImGui::TreePop(); - } - - counter++; - } - else if (entries.icons[i].pageNo >= 0) { - ImGui::TableNextRow(); - - ImGui::TableNextColumn(); - ImGui::Image(reinterpret_cast(icons[App].id), tex_size); - - ImGui::TableNextColumn(); - std::string title = std::to_string(counter) + ") "; - title.append(entries.icons[i].title); - ImGui::Selectable(title.c_str(), false, ImGuiSelectableFlags_SpanAllColumns); - - ImGui::TableNextColumn(); - ImGui::Text("%d", entries.icons[i].pageId); - - ImGui::TableNextColumn(); - ImGui::Text("%d", entries.icons[i].pageNo); - - ImGui::TableNextColumn(); - ImGui::Text("%d", entries.icons[i].pos); - - counter++; - } - } - - ImGui::EndTable(); - } - - ImGui::EndTabItem(); + // Create window with SDL_Renderer graphics context + SDL_WindowFlags window_flags = (SDL_WindowFlags)(SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI); + window = SDL_CreateWindow("VITA Customizer", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 960, 544, window_flags); + renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_ACCELERATED); + if (renderer == nullptr) { + Log::Error("SDL_CreateRenderer failed: %s\n", SDL_GetError()); + return 0; } - } - - static void PagesTab(AppEntries &entries, State &state) { - ImGuiTableFlags tableFlags = ImGuiTableFlags_Resizable | ImGuiTableFlags_BordersInner | ImGuiTableFlags_BordersOuter; - if (ImGui::BeginTabItem("Pages")) { - ImGui::Dummy(ImVec2(0.0f, 5.0f)); // Spacing - - if (ImGui::Button("Reset", ImVec2(ImGui::GetContentRegionAvail().x * 0.33f, 0.0f))) { - AppList::Get(entries); - old_page_id = -1; - } + // Setup Dear ImGui context + IMGUI_CHECKVERSION(); + ImGui::CreateContext(); + ImGuiIO& io = ImGui::GetIO(); (void)io; + io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls + io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls + io.IniFilename = nullptr; - ImGui::SameLine(); + ImGui_ImplSDL2_InitForSDLRenderer(window, renderer); + ImGui_ImplSDLRenderer2_Init(renderer); - if (ImGui::Button("Apply Changes", ImVec2(ImGui::GetContentRegionAvail().x * 0.5f, 0.0f))) { - state = StateConfirmSwap; - } + // Build font atlas + unsigned char *pixels = nullptr; + int width = 0, height = 0, bytes_per_pixel = 0; + + ImFontConfig font_config; + font_config.OversampleH = 1; + font_config.OversampleV = 1; + font_config.PixelSnapH = 1; + + io.Fonts->AddFontFromFileTTF("sa0:/data/font/pvf/jpn0.pvf", 20.0f, std::addressof(font_config), io.Fonts->GetGlyphRangesJapanese()); + io.Fonts->GetTexDataAsAlpha8(std::addressof(pixels), std::addressof(width), std::addressof(height), std::addressof(bytes_per_pixel)); + io.Fonts->Build(); - ImGui::SameLine(); + // Set theme/style + ImGui::GetStyle().FrameRounding = 4.0f; + ImGui::GetStyle().GrabRounding = 4.0f; + + ImVec4 *colors = ImGui::GetStyle().Colors; + colors[ImGuiCol_Text] = ImVec4(0.85f, 0.85f, 0.85f, 1.00f); + colors[ImGuiCol_TextDisabled] = ImVec4(0.36f, 0.42f, 0.47f, 1.00f); + colors[ImGuiCol_WindowBg] = ImVec4(0.05f, 0.07f, 0.13f, 1.00f); + colors[ImGuiCol_ChildBg] = ImVec4(0.15f, 0.18f, 0.22f, 1.00f); + colors[ImGuiCol_PopupBg] = ImVec4(0.08f, 0.08f, 0.08f, 0.94f); + colors[ImGuiCol_Border] = ImVec4(0.65f, 0.16f, 0.31f, 1.0f); + colors[ImGuiCol_BorderShadow] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f); + colors[ImGuiCol_FrameBg] = ImVec4(0.20f, 0.25f, 0.29f, 1.00f); + colors[ImGuiCol_FrameBgHovered] = ImVec4(0.12f, 0.20f, 0.28f, 1.00f); + colors[ImGuiCol_FrameBgActive] = ImVec4(0.09f, 0.12f, 0.14f, 1.00f); + colors[ImGuiCol_TitleBg] = ImVec4(0.09f, 0.12f, 0.14f, 0.65f); + colors[ImGuiCol_TitleBgActive] = ImVec4(0.65f, 0.16f, 0.31f, 1.0f); + colors[ImGuiCol_TitleBgCollapsed] = ImVec4(0.00f, 0.00f, 0.00f, 0.51f); + colors[ImGuiCol_MenuBarBg] = ImVec4(0.15f, 0.18f, 0.22f, 1.00f); + colors[ImGuiCol_ScrollbarBg] = ImVec4(0.02f, 0.02f, 0.02f, 0.39f); + colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.65f, 0.16f, 0.31f, 1.0f); + colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.18f, 0.22f, 0.25f, 1.00f); + colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.09f, 0.21f, 0.31f, 1.00f); + colors[ImGuiCol_CheckMark] = ImVec4(0.65f, 0.16f, 0.31f, 1.0f); + colors[ImGuiCol_SliderGrab] = ImVec4(0.28f, 0.56f, 1.00f, 1.00f); + colors[ImGuiCol_SliderGrabActive] = ImVec4(0.37f, 0.61f, 1.00f, 1.00f); + colors[ImGuiCol_Button] = ImVec4(0.20f, 0.25f, 0.29f, 1.00f); + colors[ImGuiCol_ButtonHovered] = ImVec4(0.65f, 0.16f, 0.31f, 1.0f); + colors[ImGuiCol_ButtonActive] = ImVec4(0.65f, 0.16f, 0.31f, 1.0f); + colors[ImGuiCol_Header] = ImVec4(0.20f, 0.25f, 0.29f, 0.55f); + colors[ImGuiCol_HeaderHovered] = ImVec4(0.65f, 0.16f, 0.31f, 1.0f); + colors[ImGuiCol_HeaderActive] = ImVec4(0.65f, 0.16f, 0.31f, 1.0f); + colors[ImGuiCol_Separator] = ImVec4(0.20f, 0.25f, 0.29f, 1.00f); + colors[ImGuiCol_SeparatorHovered] = ImVec4(0.10f, 0.40f, 0.75f, 0.78f); + colors[ImGuiCol_SeparatorActive] = ImVec4(0.10f, 0.40f, 0.75f, 1.00f); + colors[ImGuiCol_ResizeGrip] = ImVec4(0.26f, 0.59f, 0.98f, 0.25f); + colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.26f, 0.59f, 0.98f, 0.67f); + colors[ImGuiCol_ResizeGripActive] = ImVec4(0.26f, 0.59f, 0.98f, 0.95f); + colors[ImGuiCol_Tab] = ImVec4(0.11f, 0.15f, 0.17f, 1.00f); + colors[ImGuiCol_TabHovered] = ImVec4(0.65f, 0.16f, 0.31f, 1.0f); + colors[ImGuiCol_TabActive] = ImVec4(0.65f, 0.16f, 0.31f, 1.0f); + colors[ImGuiCol_TabUnfocused] = ImVec4(0.11f, 0.15f, 0.17f, 1.00f); + colors[ImGuiCol_TabUnfocusedActive] = ImVec4(0.11f, 0.15f, 0.17f, 1.00f); + colors[ImGuiCol_PlotLines] = ImVec4(0.65f, 0.16f, 0.31f, 1.0f); + colors[ImGuiCol_PlotLinesHovered] = ImVec4(1.00f, 0.43f, 0.35f, 1.00f); + colors[ImGuiCol_PlotHistogram] = ImVec4(0.65f, 0.16f, 0.31f, 1.0f); + colors[ImGuiCol_PlotHistogramHovered] = ImVec4(1.00f, 0.60f, 0.00f, 1.00f); + colors[ImGuiCol_TextSelectedBg] = ImVec4(0.26f, 0.59f, 0.98f, 0.35f); + colors[ImGuiCol_DragDropTarget] = ImVec4(1.00f, 1.00f, 0.00f, 0.90f); + colors[ImGuiCol_NavHighlight] = ImVec4(0.65f, 0.16f, 0.31f, 1.0f); + colors[ImGuiCol_NavWindowingHighlight] = ImVec4(1.00f, 1.00f, 1.00f, 0.70f); + colors[ImGuiCol_NavWindowingDimBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.20f); + colors[ImGuiCol_ModalWindowDimBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.35f); - GUI::DisableButtonInit(!backupExists); - if (ImGui::Button("Restore Backup", ImVec2(ImGui::GetContentRegionAvail().x * 1.0f, 0.0f))) { - state = StateRestore; - } - GUI::DisableButtonExit(!backupExists); - - ImGui::Dummy(ImVec2(0.0f, 5.0f)); // Spacing - - if (ImGui::BeginTable("PagesList", 3, tableFlags)) { - ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthFixed); - ImGui::TableSetupColumn("pageId"); - ImGui::TableSetupColumn("pageNo"); - ImGui::TableHeadersRow(); - - for (unsigned int i = 0; i < entries.pages.size(); i++) { - ImGui::TableNextRow(); - - ImGui::TableNextColumn(); - ImGui::Image(reinterpret_cast(icons[Page].id), tex_size); - - ImGui::TableNextColumn(); - ImGui::Text("%d", entries.pages[i].pageId); + return 0; + } - ImGui::TableNextColumn(); - std::string pageNo = std::to_string(entries.pages[i].pageNo); - const bool is_selected = (old_page_id == static_cast(i)); - if (ImGui::Selectable(pageNo.c_str(), is_selected)) { - if (old_page_id == -1) { - old_page_id = i; - } - else { - int temp = entries.pages[i].pageNo; - entries.pages[i].pageNo = entries.pages[old_page_id].pageNo; - entries.pages[old_page_id].pageNo = temp; - old_page_id = -1; - ImGui::ClearActiveID(); - } - } - } + void Exit(void) { + ImGui_ImplSDLRenderer2_Shutdown(); + ImGui_ImplSDL2_Shutdown(); + ImGui::DestroyContext(); + + SDL_DestroyRenderer(renderer); + SDL_DestroyWindow(window); + SDL_Quit(); + } - ImGui::EndTable(); - } - - ImGui::EndTabItem(); + void DisableButtonInit(bool disable) { + if (disable) { + ImGui::PushItemFlag(ImGuiItemFlags_Disabled, true); + ImGui::PushStyleVar(ImGuiStyleVar_Alpha, ImGui::GetStyle().Alpha * 0.5f); } } - static void LoadoutsTab(std::vector &loadouts, State &state, int &date_format, std::string &loadout_name) { - ImGuiTableFlags tableFlags = ImGuiTableFlags_Resizable | ImGuiTableFlags_BordersInner | ImGuiTableFlags_BordersOuter | - ImGuiTableFlags_SizingStretchProp | ImGuiTableFlags_ScrollY; - - if (ImGui::BeginTabItem("Loadouts")) { - ImGui::Dummy(ImVec2(0.0f, 5.0f)); // Spacing - - if (ImGui::Button("Backup current loadout", ImVec2(ImGui::GetContentRegionAvail().x * 1.0f, 0.0f))) { - if (R_SUCCEEDED(Loadouts::Backup())) { - FS::GetDirList("ux0:data/VITAHomebrewSorter/loadouts", loadouts); - } - } - - ImGui::Dummy(ImVec2(0.0f, 5.0f)); // Spacing - - if (ImGui::BeginTable("LoadoutList", 4, tableFlags)) { - if (loadouts.empty()) { - ImGui::Text("No loadouts found"); - } - else { - ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthFixed); - ImGui::TableSetupColumn("Title"); - ImGui::TableSetupColumn("Date", ImGuiTableColumnFlags_WidthFixed); - ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthFixed); - ImGui::TableHeadersRow(); - - for (unsigned int i = 0; i < loadouts.size(); i++) { - ImGui::TableNextRow(); - - ImGui::TableNextColumn(); - ImGui::Image(reinterpret_cast(icons[DB].id), tex_size); - - ImGui::TableNextColumn(); - if (ImGui::Selectable(loadouts[i].d_name, false)) { - loadout_name = loadouts[i].d_name; - state = StateLoadoutRestore; - } - - ImGui::TableNextColumn(); - char date[16]; - Utils::GetDateString(date, static_cast(date_format), loadouts[i].d_stat.st_mtime); - ImGui::Text(date); - - ImGui::TableNextColumn(); - ImGui::PushID(i); - if (ImGui::ImageButton("", reinterpret_cast(icons[Trash].id), tex_size, ImVec2(0, 0), ImVec2(1, 1), ImVec4(0.0f, 0.0f, 0.0f, 1.0f), ImVec4(1.0f, 1.0f, 1.0f, 1.0f))) { - loadout_name = loadouts[i].d_name; - state = StateDelete; - } - ImGui::PopID(); - } - } - - ImGui::EndTable(); - } - - ImGui::EndTabItem(); - } - } - - static void SettingsTab(void) { - if (ImGui::BeginTabItem("Settings")) { - ImGui::Dummy(ImVec2(0.0f, 5.0f)); // Spacing - - ImGui::Indent(5.f); - ImGui::TextColored(ImVec4(0.70f, 0.16f, 0.31f, 1.0f), "Beta features:"); - ImGui::Indent(15.f); - - if (ImGui::RadioButton("Enabled", cfg.beta_features == true)) { - cfg.beta_features = true; - Config::Save(cfg); - } - - ImGui::SameLine(); - - if (ImGui::RadioButton("Disabled", cfg.beta_features == false)) { - cfg.beta_features = false; - Config::Save(cfg); - } - - ImGui::Dummy(ImVec2(0.0f, 10.0f)); // Spacing - ImGui::Unindent(); - - ImGui::Indent(5.f); - ImGui::TextColored(ImVec4(0.70f, 0.16f, 0.31f, 1.0f), "App Info:"); - ImGui::Indent(15.f); - std::string version = APP_VERSION; - version.erase(0, std::min(version.find_first_not_of('0'), version.size() - 1)); - ImGui::Text("App version: %s", version.c_str()); - ImGui::Text("Author: Joel16"); - ImGui::Text("Assets: PreetiSketch"); - ImGui::Text("Dear imGui version: %s", ImGui::GetVersion()); - ImGui::Text("SQLite 3 version: %s", sqlite3_libversion()); - - ImGui::Dummy(ImVec2(0.0f, 10.0f)); // Spacing - ImGui::Unindent(); - - ImGui::Indent(5.f); - ImGui::TextColored(ImVec4(0.70f, 0.16f, 0.31f, 1.0f), "Usage:"); - ImGui::Indent(15.f); - std::string usage = std::string("VITA Homebrew Sorter is a basic PS VITA homebrew application that sorts the application database in your LiveArea.") - + " The application sorts apps and games that are inside folders as well. This applications also allows you to backup your current 'loadout' that " - + " you can switch into as you wish. A backup will be made before any changes are applied to the application database." - + " This backup is overwritten each time you use the sort option. You can find the backup in ux0:/data/VITAHomebrewSorter/backups/app.db." - + " \n\nIt is always recommended to restart your vita so that it can refresh your livearea/app.db for any changes (deleted icons, new folders, etc.)" - + " before you run this application."; - ImGui::TextWrapped(usage.c_str()); - ImGui::Unindent(); - - ImGui::EndTabItem(); + void DisableButtonExit(bool disable) { + if (disable) { + ImGui::PopItemFlag(); + ImGui::PopStyleVar(); } } int RenderLoop(void) { bool done = false; + ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f); + backupExists = (FS::FileExists("ux0:/data/VITAHomebrewSorter/backup/app.db") || FS::FileExists("ux0:/data/VITAHomebrewSorter/backup/app.db.bkp")); AppEntries entries; @@ -624,34 +353,51 @@ namespace GUI { std::string loadout_name; State state = StateNone; - SceCtrlData pad = { 0 }; + + ImGuiIO& io = ImGui::GetIO(); (void)io; while (!done) { - ImGui_ImplVitaGL_NewFrame(); - ImGui::NewFrame(); + SDL_Event event; + while (SDL_PollEvent(&event)) { + ImGui_ImplSDL2_ProcessEvent(&event); + + switch (event.type) { + case SDL_QUIT: + done = true; + break; + + case SDL_WINDOWEVENT: + if (event.window.event == SDL_WINDOWEVENT_CLOSE && event.window.windowID == SDL_GetWindowID(window)) { + done = true; + } + break; + + case SDL_CONTROLLERBUTTONDOWN: + if (event.cbutton.button == SDL_CONTROLLER_BUTTON_START) { + done = true; + } + break; + } + } + + GUI::Begin(); GUI::SetupWindow(); if (ImGui::Begin("VITA Homebrew Sorter", nullptr, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse)) { if (ImGui::BeginTabBar("VITA Homebrew Sorter tabs")) { - GUI::SortTab(entries, state); - GUI::PagesTab(entries, state); + Tabs::Sort(entries, state, backupExists); + Tabs::Pages(entries, state, backupExists); GUI::DisableButtonInit(!cfg.beta_features); - GUI::LoadoutsTab(loadouts, state, date_format, loadout_name); + Tabs::Loadouts(loadouts, state, date_format, loadout_name); GUI::DisableButtonExit(!cfg.beta_features); - GUI::SettingsTab(); + Tabs::Settings(); ImGui::EndTabBar(); } } GUI::ExitWindow(); GUI::Prompt(state, entries, loadouts, loadout_name.c_str()); - Renderer::End(true, ImVec4(0.45f, 0.55f, 0.60f, 1.00f)); - - pad = Utils::ReadControls(); - - if (pressed & SCE_CTRL_START) { - done = true; - } + GUI::End(io, clear_color, renderer); } return 0; diff --git a/source/imgui_impl_vitagl.cpp b/source/imgui_impl_vitagl.cpp deleted file mode 100644 index f9b9e0d..0000000 --- a/source/imgui_impl_vitagl.cpp +++ /dev/null @@ -1,300 +0,0 @@ -// Implemented features: -// [X] User texture binding. Cast 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. - -#include -#include -#include -#include -#include -#include - -#include "imgui.h" -#include "imgui_impl_vitagl.h" -#include "utils.h" - -#define lerp(value, from_max, to_max) ((((value * 10) * (to_max * 10)) / (from_max * 10)) / 10) - -struct ImGui_ImplVitaGL_Data { - GLuint FontTexture = 0; - uint64_t g_Time = 0; - ImGui_ImplVitaGL_Data(void) { - sceClibMemset(this, 0, sizeof(*this)); - } -}; - -// Backend data stored in io.BackendRendererUserData to allow support for multiple Dear ImGui contexts -// It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts. -static ImGui_ImplVitaGL_Data *ImGui_ImplVitaGL_GetBackendData(void) { - return ImGui::GetCurrentContext() ? static_cast(ImGui::GetIO().BackendRendererUserData) : nullptr; -} - -bool ImGui_ImplVitaGL_Init(void) { - sceCtrlSetSamplingMode(SCE_CTRL_MODE_ANALOG_WIDE); - ImGuiIO& io = ImGui::GetIO(); - IM_ASSERT(io.BackendRendererUserData == nullptr && "Already initialized a renderer backend!"); - - // Setup backend capabilities flags - ImGui_ImplVitaGL_Data *bd = IM_NEW(ImGui_ImplVitaGL_Data)(); - io.BackendRendererUserData = (void *)bd; - io.BackendRendererName = "imgui_impl_vitagl"; - - return true; -} - -void ImGui_ImplVitaGL_Shutdown(void) { - ImGui_ImplVitaGL_Data *bd = ImGui_ImplVitaGL_GetBackendData(); - IM_ASSERT(bd != NULL && "No renderer backend to shutdown, or already shutdown?"); - ImGuiIO& io = ImGui::GetIO(); - - ImGui_ImplVitaGL_DestroyDeviceObjects(); - io.BackendRendererName = nullptr; - io.BackendRendererUserData = nullptr; - IM_DELETE(bd); -} - -static void ImGui_ImplVitaGL_UpdateGamepads(void) { - ImGuiIO& io = ImGui::GetIO(); - if ((io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) == 0) - return; - - // Get gamepad - io.BackendFlags &= ~ImGuiBackendFlags_HasGamepad; - - SceCtrlData pad; - sceCtrlPeekBufferPositive(0, &pad, 1); - - io.BackendFlags |= ImGuiBackendFlags_HasGamepad; - - int rstick_x = (pad.rx - 127) * 256; - int rstick_y = (pad.ry - 127) * 256; - - // Update gamepad inputs - #define IM_SATURATE(V) (V < 0.0f ? 0.0f : V > 1.0f ? 1.0f : V) - #define MAP_BUTTON(KEY_NO, BUTTON_NO) { io.AddKeyEvent(KEY_NO, (pad.buttons & BUTTON_NO)); } - #define MAP_ANALOG(KEY_NO, AXIS_NO, V0, V1) { float vn = (float)(AXIS_NO - V0) / (float)(V1 - V0); vn = IM_SATURATE(vn); io.AddKeyAnalogEvent(KEY_NO, vn > 0.1f, vn); } - const int thumb_dead_zone = 8000; // SDL_gamecontroller.h suggests using this value. - MAP_BUTTON(ImGuiKey_GamepadStart, SCE_CTRL_ENTER); - MAP_BUTTON(ImGuiKey_GamepadBack, SCE_CTRL_CANCEL); - MAP_BUTTON(ImGuiKey_GamepadFaceDown, SCE_CTRL_ENTER); - MAP_BUTTON(ImGuiKey_GamepadFaceRight, SCE_CTRL_CANCEL); - MAP_BUTTON(ImGuiKey_GamepadFaceLeft, SCE_CTRL_SQUARE); - MAP_BUTTON(ImGuiKey_GamepadFaceUp, SCE_CTRL_TRIANGLE); - MAP_BUTTON(ImGuiKey_GamepadDpadLeft, SCE_CTRL_LEFT); - MAP_BUTTON(ImGuiKey_GamepadDpadRight, SCE_CTRL_RIGHT); - MAP_BUTTON(ImGuiKey_GamepadDpadUp, SCE_CTRL_UP); - MAP_BUTTON(ImGuiKey_GamepadDpadDown, SCE_CTRL_DOWN); - MAP_BUTTON(ImGuiKey_GamepadL1, SCE_CTRL_LTRIGGER); - MAP_BUTTON(ImGuiKey_GamepadR1, SCE_CTRL_RTRIGGER); - MAP_ANALOG(ImGuiKey_GamepadLStickLeft, rstick_x, -thumb_dead_zone, -32768); - MAP_ANALOG(ImGuiKey_GamepadLStickRight, rstick_x, +thumb_dead_zone, +32767); - MAP_ANALOG(ImGuiKey_GamepadLStickUp, rstick_y, -thumb_dead_zone, -32767); - MAP_ANALOG(ImGuiKey_GamepadLStickDown, rstick_y, +thumb_dead_zone, +32767); - #undef MAP_BUTTON - #undef MAP_ANALOG -} - -void ImGui_ImplVitaGL_NewFrame(void) { - ImGui_ImplVitaGL_Data *bd = ImGui_ImplVitaGL_GetBackendData(); - IM_ASSERT(bd != nullptr && "Did you call ImGui_ImplVitaGL_Init()?"); - - if (!bd->FontTexture) - ImGui_ImplVitaGL_CreateDeviceObjects(); - - ImGuiIO& io = ImGui::GetIO(); - - // Setup display size (every frame to accommodate for window resizing) - int w = 0, h = 0; - int display_w = 0, display_h = 0; - - GLint viewport[4]; - glGetIntegerv(GL_VIEWPORT, viewport); - - w = display_w = viewport[2]; - h = display_h = viewport[3]; - - io.DisplaySize = ImVec2(static_cast(w), static_cast(h)); - - if (w > 0 && h > 0) - io.DisplayFramebufferScale = ImVec2(static_cast(display_w / w),static_cast(display_h) / h); - - static uint64_t frequency = 1000000; - uint64_t current_time = sceKernelGetProcessTimeWide(); - io.DeltaTime = bd->g_Time > 0 ? static_cast(static_cast((current_time - bd->g_Time)) / frequency) : static_cast(1.0f / 60.0f); - bd->g_Time = current_time; - - ImGui_ImplVitaGL_UpdateGamepads(); -} - -static void ImGui_ImplVitaGL_SetupRenderState(ImDrawData *draw_data, int fb_width, int fb_height) { - // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, vertex/texcoord/color pointers, polygon fill. - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - //glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); // In order to composite our output buffer we need to preserve alpha - glDisable(GL_CULL_FACE); - glDisable(GL_DEPTH_TEST); - glDisable(GL_STENCIL_TEST); - glDisable(GL_LIGHTING); - glDisable(GL_COLOR_MATERIAL); - glEnable(GL_SCISSOR_TEST); - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - glEnableClientState(GL_COLOR_ARRAY); - glDisableClientState(GL_NORMAL_ARRAY); - glEnable(GL_TEXTURE_2D); - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - glShadeModel(GL_SMOOTH); - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - - // If you are using this code with non-legacy OpenGL header/contexts (which you should not, prefer using imgui_impl_opengl3.cpp!!), - // you may need to backup/reset/restore other state, e.g. for current shader using the commented lines below. - // (DO NOT MODIFY THIS FILE! Add the code in your calling function) - // GLint last_program; - // glGetIntegerv(GL_CURRENT_PROGRAM, &last_program); - // glUseProgram(0); - // ImGui_ImplVitaGL_RenderDrawData(...); - // glUseProgram(last_program) - // There are potentially many more states you could need to clear/setup that we can't access from default headers. - // e.g. glBindBuffer(GL_ARRAY_BUFFER, 0), glDisable(GL_TEXTURE_CUBE_MAP). - - // Setup viewport, orthographic projection matrix - // Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayPos is (0,0) for single viewport apps. - glViewport(0, 0, static_cast(fb_width), static_cast(fb_height)); - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glLoadIdentity(); - glOrtho(draw_data->DisplayPos.x, draw_data->DisplayPos.x + draw_data->DisplaySize.x, draw_data->DisplayPos.y + draw_data->DisplaySize.y, draw_data->DisplayPos.y, -1.0f, +1.0f); - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glLoadIdentity(); -} - -// OpenGL2 Render function. -// Note that this implementation is little overcomplicated because we are saving/setting up/restoring every OpenGL state explicitly. -// This is in order to be able to run within an OpenGL engine that doesn't do so. -void ImGui_ImplVitaGL_RenderDrawData(ImDrawData *draw_data) { - // Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates) - int fb_width = static_cast(draw_data->DisplaySize.x * draw_data->FramebufferScale.x); - int fb_height = static_cast(draw_data->DisplaySize.y * draw_data->FramebufferScale.y); - if (fb_width == 0 || fb_height == 0) - return; - - // Backup GL state - GLint last_texture; glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); - GLint last_polygon_mode[2]; glGetIntegerv(GL_POLYGON_MODE, last_polygon_mode); - GLint last_viewport[4]; glGetIntegerv(GL_VIEWPORT, last_viewport); - GLint last_scissor_box[4]; glGetIntegerv(GL_SCISSOR_BOX, last_scissor_box); - //GLint last_shade_model; glGetIntegerv(GL_SHADE_MODEL, &last_shade_model); - GLint last_tex_env_mode; glGetTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &last_tex_env_mode); - glPushAttrib(GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT | GL_TRANSFORM_BIT); - - // Setup desired GL state - ImGui_ImplVitaGL_SetupRenderState(draw_data, fb_width, fb_height); - - // Will project scissor/clipping rectangles into framebuffer space - ImVec2 clip_off = draw_data->DisplayPos; // (0,0) unless using multi-viewports - ImVec2 clip_scale = draw_data->FramebufferScale; // (1,1) unless using retina display which are often (2,2) - - // Render command lists - for (int n = 0; n < draw_data->CmdListsCount; n++) { - const ImDrawList *cmd_list = draw_data->CmdLists[n]; - const ImDrawVert *vtx_buffer = cmd_list->VtxBuffer.Data; - const ImDrawIdx *idx_buffer = cmd_list->IdxBuffer.Data; - glVertexPointer(2, GL_FLOAT, sizeof(ImDrawVert), reinterpret_cast(reinterpret_cast(vtx_buffer) + IM_OFFSETOF(ImDrawVert, pos))); - glTexCoordPointer(2, GL_FLOAT, sizeof(ImDrawVert), reinterpret_cast(reinterpret_cast(vtx_buffer) + IM_OFFSETOF(ImDrawVert, uv))); - glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(ImDrawVert), reinterpret_cast(reinterpret_cast(vtx_buffer) + IM_OFFSETOF(ImDrawVert, col))); - - for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++) { - const ImDrawCmd *pcmd = &cmd_list->CmdBuffer[cmd_i]; - if (pcmd->UserCallback) { - // User callback, registered via ImDrawList::AddCallback() - // (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.) - if (pcmd->UserCallback == ImDrawCallback_ResetRenderState) - ImGui_ImplVitaGL_SetupRenderState(draw_data, fb_width, fb_height); - else - pcmd->UserCallback(cmd_list, pcmd); - } - else { - // Project scissor/clipping rectangles into framebuffer space - ImVec2 clip_min((pcmd->ClipRect.x - clip_off.x) * clip_scale.x, (pcmd->ClipRect.y - clip_off.y) * clip_scale.y); - ImVec2 clip_max((pcmd->ClipRect.z - clip_off.x) * clip_scale.x, (pcmd->ClipRect.w - clip_off.y) * clip_scale.y); - if (clip_max.x <= clip_min.x || clip_max.y <= clip_min.y) - continue; - - // Apply scissor/clipping rectangle (Y is inverted in OpenGL) - glScissor(static_cast(clip_min.x), static_cast(static_cast(fb_height) - clip_max.y), static_cast(clip_max.x - clip_min.x), static_cast(clip_max.y - clip_min.y)); - - // Bind texture, Draw - glBindTexture(GL_TEXTURE_2D, reinterpret_cast(pcmd->GetTexID())); - glDrawElements(GL_TRIANGLES, static_cast(pcmd->ElemCount), sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer + pcmd->IdxOffset); - } - } - } - - // Restore modified GL state - glDisableClientState(GL_COLOR_ARRAY); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - glDisableClientState(GL_VERTEX_ARRAY); - glBindTexture(GL_TEXTURE_2D, static_cast(last_texture)); - glMatrixMode(GL_MODELVIEW); - glPopMatrix(); - glMatrixMode(GL_PROJECTION); - glPopMatrix(); - glPopAttrib(); - glPolygonMode(GL_FRONT, static_cast(last_polygon_mode[0])); glPolygonMode(GL_BACK, static_cast(last_polygon_mode[1])); - glViewport(last_viewport[0], last_viewport[1], static_cast(last_viewport[2]), static_cast(last_viewport[3])); - glScissor(last_scissor_box[0], last_scissor_box[1], static_cast(last_scissor_box[2]), static_cast(last_scissor_box[3])); - //glShadeModel(last_shade_model); - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, last_tex_env_mode); -} - -bool ImGui_ImplVitaGL_CreateFontsTexture(void) { - // Build texture atlas - ImGuiIO& io = ImGui::GetIO(); - ImGui_ImplVitaGL_Data *bd = ImGui_ImplVitaGL_GetBackendData(); - unsigned char *pixels = nullptr; - int width = 0, height = 0; - - ImFontConfig font_config; - font_config.OversampleH = 1; - font_config.OversampleV = 1; - font_config.PixelSnapH = 1; - - io.Fonts->AddFontFromFileTTF("sa0:/data/font/pvf/jpn0.pvf", 20.0f, &font_config, io.Fonts->GetGlyphRangesJapanese()); - io.Fonts->GetTexDataAsRGBA32(static_cast(&pixels), &width, &height); - - // Upload texture to graphics system - GLint last_texture; - glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); - glGenTextures(1, &bd->FontTexture); - glBindTexture(GL_TEXTURE_2D, bd->FontTexture); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); - - // Store our identifier - io.Fonts->SetTexID(reinterpret_cast(bd->FontTexture)); - - // Restore state - glBindTexture(GL_TEXTURE_2D, last_texture); - return true; -} - -void ImGui_ImplVitaGL_DestroyFontsTexture(void) { - ImGuiIO& io = ImGui::GetIO(); - ImGui_ImplVitaGL_Data *bd = ImGui_ImplVitaGL_GetBackendData(); - - if (bd->FontTexture) { - glDeleteTextures(1, &bd->FontTexture); - io.Fonts->SetTexID(0); - bd->FontTexture = 0; - } -} - -bool ImGui_ImplVitaGL_CreateDeviceObjects(void) { - return ImGui_ImplVitaGL_CreateFontsTexture(); -} - -void ImGui_ImplVitaGL_DestroyDeviceObjects(void) { - ImGui_ImplVitaGL_DestroyFontsTexture(); -} diff --git a/source/keyboard.cpp b/source/keyboard.cpp index cbbc37e..056cbf3 100644 --- a/source/keyboard.cpp +++ b/source/keyboard.cpp @@ -3,8 +3,8 @@ #include #include #include -#include +#include "gui.h" #include "keyboard.h" #include "log.h" #include "utils.h" @@ -87,8 +87,7 @@ namespace Keyboard { bool done = false; do { - glClear(GL_COLOR_BUFFER_BIT); - glClearColor(0, 0, 0, 1); + SDL_RenderClear(GUI::GetRenderer()); SceCommonDialogStatus status = Keyboard::Update(); @@ -98,8 +97,8 @@ namespace Keyboard { else if (status != SCE_COMMON_DIALOG_STATUS_CANCELLED) { done = false; } - - vglSwapBuffers(GL_TRUE); + + SDL_RenderPresent(GUI::GetRenderer()); } while(!done); return text; diff --git a/source/main.cpp b/source/main.cpp index 6c0d5ac..a7e50f3 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -1,10 +1,8 @@ #include -#include #include "config.h" #include "fs.h" #include "gui.h" -#include "imgui_impl_vitagl.h" #include "log.h" #include "power.h" #include "textures.h" @@ -13,79 +11,9 @@ int _newlib_heap_size_user = 192 * 1024 * 1024; namespace Services { - void SetDefaultTheme(void) { - ImGui::GetStyle().FrameRounding = 4.0f; - ImGui::GetStyle().GrabRounding = 4.0f; - - ImVec4 *colors = ImGui::GetStyle().Colors; - colors[ImGuiCol_Text] = ImVec4(0.85f, 0.85f, 0.85f, 1.00f); - colors[ImGuiCol_TextDisabled] = ImVec4(0.36f, 0.42f, 0.47f, 1.00f); - colors[ImGuiCol_WindowBg] = ImVec4(0.05f, 0.07f, 0.13f, 1.00f); - colors[ImGuiCol_ChildBg] = ImVec4(0.15f, 0.18f, 0.22f, 1.00f); - colors[ImGuiCol_PopupBg] = ImVec4(0.08f, 0.08f, 0.08f, 0.94f); - colors[ImGuiCol_Border] = ImVec4(0.65f, 0.16f, 0.31f, 1.0f); - colors[ImGuiCol_BorderShadow] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f); - colors[ImGuiCol_FrameBg] = ImVec4(0.20f, 0.25f, 0.29f, 1.00f); - colors[ImGuiCol_FrameBgHovered] = ImVec4(0.12f, 0.20f, 0.28f, 1.00f); - colors[ImGuiCol_FrameBgActive] = ImVec4(0.09f, 0.12f, 0.14f, 1.00f); - colors[ImGuiCol_TitleBg] = ImVec4(0.09f, 0.12f, 0.14f, 0.65f); - colors[ImGuiCol_TitleBgActive] = ImVec4(0.65f, 0.16f, 0.31f, 1.0f); - colors[ImGuiCol_TitleBgCollapsed] = ImVec4(0.00f, 0.00f, 0.00f, 0.51f); - colors[ImGuiCol_MenuBarBg] = ImVec4(0.15f, 0.18f, 0.22f, 1.00f); - colors[ImGuiCol_ScrollbarBg] = ImVec4(0.02f, 0.02f, 0.02f, 0.39f); - colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.65f, 0.16f, 0.31f, 1.0f); - colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.18f, 0.22f, 0.25f, 1.00f); - colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.09f, 0.21f, 0.31f, 1.00f); - colors[ImGuiCol_CheckMark] = ImVec4(0.65f, 0.16f, 0.31f, 1.0f); - colors[ImGuiCol_SliderGrab] = ImVec4(0.28f, 0.56f, 1.00f, 1.00f); - colors[ImGuiCol_SliderGrabActive] = ImVec4(0.37f, 0.61f, 1.00f, 1.00f); - colors[ImGuiCol_Button] = ImVec4(0.20f, 0.25f, 0.29f, 1.00f); - colors[ImGuiCol_ButtonHovered] = ImVec4(0.65f, 0.16f, 0.31f, 1.0f); - colors[ImGuiCol_ButtonActive] = ImVec4(0.65f, 0.16f, 0.31f, 1.0f); - colors[ImGuiCol_Header] = ImVec4(0.20f, 0.25f, 0.29f, 0.55f); - colors[ImGuiCol_HeaderHovered] = ImVec4(0.65f, 0.16f, 0.31f, 1.0f); - colors[ImGuiCol_HeaderActive] = ImVec4(0.65f, 0.16f, 0.31f, 1.0f); - colors[ImGuiCol_Separator] = ImVec4(0.20f, 0.25f, 0.29f, 1.00f); - colors[ImGuiCol_SeparatorHovered] = ImVec4(0.10f, 0.40f, 0.75f, 0.78f); - colors[ImGuiCol_SeparatorActive] = ImVec4(0.10f, 0.40f, 0.75f, 1.00f); - colors[ImGuiCol_ResizeGrip] = ImVec4(0.26f, 0.59f, 0.98f, 0.25f); - colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.26f, 0.59f, 0.98f, 0.67f); - colors[ImGuiCol_ResizeGripActive] = ImVec4(0.26f, 0.59f, 0.98f, 0.95f); - colors[ImGuiCol_Tab] = ImVec4(0.11f, 0.15f, 0.17f, 1.00f); - colors[ImGuiCol_TabHovered] = ImVec4(0.65f, 0.16f, 0.31f, 1.0f); - colors[ImGuiCol_TabActive] = ImVec4(0.65f, 0.16f, 0.31f, 1.0f); - colors[ImGuiCol_TabUnfocused] = ImVec4(0.11f, 0.15f, 0.17f, 1.00f); - colors[ImGuiCol_TabUnfocusedActive] = ImVec4(0.11f, 0.15f, 0.17f, 1.00f); - colors[ImGuiCol_PlotLines] = ImVec4(0.65f, 0.16f, 0.31f, 1.0f); - colors[ImGuiCol_PlotLinesHovered] = ImVec4(1.00f, 0.43f, 0.35f, 1.00f); - colors[ImGuiCol_PlotHistogram] = ImVec4(0.65f, 0.16f, 0.31f, 1.0f); - colors[ImGuiCol_PlotHistogramHovered] = ImVec4(1.00f, 0.60f, 0.00f, 1.00f); - colors[ImGuiCol_TextSelectedBg] = ImVec4(0.26f, 0.59f, 0.98f, 0.35f); - colors[ImGuiCol_DragDropTarget] = ImVec4(1.00f, 1.00f, 0.00f, 0.90f); - colors[ImGuiCol_NavHighlight] = ImVec4(0.65f, 0.16f, 0.31f, 1.0f); - colors[ImGuiCol_NavWindowingHighlight] = ImVec4(1.00f, 1.00f, 1.00f, 0.70f); - colors[ImGuiCol_NavWindowingDimBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.20f); - colors[ImGuiCol_ModalWindowDimBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.35f); - - ImGuiIO& io = ImGui::GetIO(); (void)io; - io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; - io.IniFilename = nullptr; - } - void Init(void) { - // Initalize vitaGL and imGui contexts - vglInitExtended(0, 960, 544, 0x800000, SCE_GXM_MULTISAMPLE_4X); - vglUseVram(GL_TRUE); - ImGui::CreateContext(); - ImGui_ImplVitaGL_Init(); - - // Setup style - ImGui::StyleColorsDark(); - + GUI::Init(); Utils::InitAppUtil(); - SCE_CTRL_ENTER = Utils::GetEnterButton(); - SCE_CTRL_CANCEL = Utils::GetCancelButton(); - sceSysmoduleLoadModule(SCE_SYSMODULE_JSON); if (!FS::DirExists("ux0:data/VITAHomebrewSorter/backup")) { @@ -103,20 +31,16 @@ namespace Services { } void Exit(void) { - // Clean up Textures::Exit(); Log::Exit(); sceSysmoduleUnloadModule(SCE_SYSMODULE_JSON); Utils::EndAppUtil(); - ImGui_ImplVitaGL_Shutdown(); - ImGui::DestroyContext(); - vglEnd(); + GUI::Exit(); } } int main(int argc, char *argv[]) { Services::Init(); - Services::SetDefaultTheme(); GUI::RenderLoop(); Services::Exit(); return 0; diff --git a/source/tabs/loadouts.cpp b/source/tabs/loadouts.cpp new file mode 100644 index 0000000..656cd90 --- /dev/null +++ b/source/tabs/loadouts.cpp @@ -0,0 +1,70 @@ +#include "fs.h" +#include "imgui.h" +#include "loadouts.h" +#include "tabs.h" +#include "textures.h" +#include "utils.h" + +namespace Tabs { + static const ImVec2 tex_size = ImVec2(20, 20); + + void Loadouts(std::vector &loadouts, State &state, int &date_format, std::string &loadout_name) { + ImGuiTableFlags tableFlags = ImGuiTableFlags_Resizable | ImGuiTableFlags_BordersInner | ImGuiTableFlags_BordersOuter | + ImGuiTableFlags_SizingStretchProp | ImGuiTableFlags_ScrollY; + + if (ImGui::BeginTabItem("Loadouts")) { + ImGui::Dummy(ImVec2(0.0f, 5.0f)); // Spacing + + if (ImGui::Button("Backup current loadout", ImVec2(ImGui::GetContentRegionAvail().x * 1.0f, 0.0f))) { + if (R_SUCCEEDED(Loadouts::Backup())) { + FS::GetDirList("ux0:data/VITAHomebrewSorter/loadouts", loadouts); + } + } + + ImGui::Dummy(ImVec2(0.0f, 5.0f)); // Spacing + + if (ImGui::BeginTable("LoadoutList", 4, tableFlags)) { + if (loadouts.empty()) { + ImGui::Text("No loadouts found"); + } + else { + ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthFixed); + ImGui::TableSetupColumn("Title"); + ImGui::TableSetupColumn("Date", ImGuiTableColumnFlags_WidthFixed); + ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthFixed); + ImGui::TableHeadersRow(); + + for (unsigned int i = 0; i < loadouts.size(); i++) { + ImGui::TableNextRow(); + + ImGui::TableNextColumn(); + ImGui::Image(reinterpret_cast(icons[DB].ptr), tex_size); + + ImGui::TableNextColumn(); + if (ImGui::Selectable(loadouts[i].d_name, false)) { + loadout_name = loadouts[i].d_name; + state = StateLoadoutRestore; + } + + ImGui::TableNextColumn(); + char date[16]; + Utils::GetDateString(date, static_cast(date_format), loadouts[i].d_stat.st_mtime); + ImGui::Text(date); + + ImGui::TableNextColumn(); + ImGui::PushID(i); + if (ImGui::ImageButton("", reinterpret_cast(icons[Trash].ptr), tex_size, ImVec2(0, 0), ImVec2(1, 1), ImVec4(0.0f, 0.0f, 0.0f, 1.0f), ImVec4(1.0f, 1.0f, 1.0f, 1.0f))) { + loadout_name = loadouts[i].d_name; + state = StateDelete; + } + ImGui::PopID(); + } + } + + ImGui::EndTable(); + } + + ImGui::EndTabItem(); + } + } +} diff --git a/source/tabs/pages.cpp b/source/tabs/pages.cpp new file mode 100644 index 0000000..a3e6299 --- /dev/null +++ b/source/tabs/pages.cpp @@ -0,0 +1,76 @@ +#include "gui.h" +#include "imgui.h" +#include "imgui_internal.h" +#include "tabs.h" +#include "textures.h" + +namespace Tabs { + static int old_page_id = -1; + static const ImVec2 tex_size = ImVec2(20, 20); + + void Pages(AppEntries &entries, State &state, bool &backupExists) { + ImGuiTableFlags tableFlags = ImGuiTableFlags_Resizable | ImGuiTableFlags_BordersInner | ImGuiTableFlags_BordersOuter; + + if (ImGui::BeginTabItem("Pages")) { + ImGui::Dummy(ImVec2(0.0f, 5.0f)); // Spacing + + if (ImGui::Button("Reset", ImVec2(ImGui::GetContentRegionAvail().x * 0.33f, 0.0f))) { + AppList::Get(entries); + old_page_id = -1; + } + + ImGui::SameLine(); + + if (ImGui::Button("Apply Changes", ImVec2(ImGui::GetContentRegionAvail().x * 0.5f, 0.0f))) { + state = StateConfirmSwap; + } + + ImGui::SameLine(); + + GUI::DisableButtonInit(!backupExists); + if (ImGui::Button("Restore Backup", ImVec2(ImGui::GetContentRegionAvail().x * 1.0f, 0.0f))) { + state = StateRestore; + } + GUI::DisableButtonExit(!backupExists); + + ImGui::Dummy(ImVec2(0.0f, 5.0f)); // Spacing + + if (ImGui::BeginTable("PagesList", 3, tableFlags)) { + ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthFixed); + ImGui::TableSetupColumn("pageId"); + ImGui::TableSetupColumn("pageNo"); + ImGui::TableHeadersRow(); + + for (unsigned int i = 0; i < entries.pages.size(); i++) { + ImGui::TableNextRow(); + + ImGui::TableNextColumn(); + ImGui::Image(reinterpret_cast(icons[Page].ptr), tex_size); + + ImGui::TableNextColumn(); + ImGui::Text("%d", entries.pages[i].pageId); + + ImGui::TableNextColumn(); + std::string pageNo = std::to_string(entries.pages[i].pageNo); + const bool is_selected = (old_page_id == static_cast(i)); + if (ImGui::Selectable(pageNo.c_str(), is_selected)) { + if (old_page_id == -1) { + old_page_id = i; + } + else { + int temp = entries.pages[i].pageNo; + entries.pages[i].pageNo = entries.pages[old_page_id].pageNo; + entries.pages[old_page_id].pageNo = temp; + old_page_id = -1; + ImGui::ClearActiveID(); + } + } + } + + ImGui::EndTable(); + } + + ImGui::EndTabItem(); + } + } +} diff --git a/source/tabs/settings.cpp b/source/tabs/settings.cpp new file mode 100644 index 0000000..77a91b1 --- /dev/null +++ b/source/tabs/settings.cpp @@ -0,0 +1,67 @@ +#include +#include + +#include "config.h" +#include "imgui.h" +#include "sqlite3.h" + +namespace Tabs { + static SDL_version sdlVersion; + + void Settings(void) { + if (ImGui::BeginTabItem("Settings")) { + ImGui::Dummy(ImVec2(0.0f, 5.0f)); // Spacing + + ImGui::Indent(5.f); + ImGui::TextColored(ImVec4(0.70f, 0.16f, 0.31f, 1.0f), "Beta features:"); + ImGui::Indent(15.f); + + if (ImGui::RadioButton("Enabled", cfg.beta_features == true)) { + cfg.beta_features = true; + Config::Save(cfg); + } + + ImGui::SameLine(); + + if (ImGui::RadioButton("Disabled", cfg.beta_features == false)) { + cfg.beta_features = false; + Config::Save(cfg); + } + + ImGui::Dummy(ImVec2(0.0f, 10.0f)); // Spacing + ImGui::Unindent(); + + ImGui::Indent(5.f); + ImGui::TextColored(ImVec4(0.70f, 0.16f, 0.31f, 1.0f), "App Info:"); + ImGui::Indent(15.f); + std::string version = APP_VERSION; + version.erase(0, std::min(version.find_first_not_of('0'), version.size() - 1)); + ImGui::Text("App version: %s", version.c_str()); + ImGui::Text("Author: Joel16"); + ImGui::Text("Assets: PreetiSketch"); + ImGui::Text("Dear imGui version: %s", ImGui::GetVersion()); + + SDL_GetVersion(&sdlVersion); + ImGui::Text("SDL2 version: %u.%u.%u", sdlVersion.major, sdlVersion.minor, sdlVersion.patch); + + ImGui::Text("SQLite 3 version: %s", sqlite3_libversion()); + + ImGui::Dummy(ImVec2(0.0f, 10.0f)); // Spacing + ImGui::Unindent(); + + ImGui::Indent(5.f); + ImGui::TextColored(ImVec4(0.70f, 0.16f, 0.31f, 1.0f), "Usage:"); + ImGui::Indent(15.f); + std::string usage = std::string("VITA Homebrew Sorter is a basic PS VITA homebrew application that sorts the application database in your LiveArea.") + + " The application sorts apps and games that are inside folders as well. This applications also allows you to backup your current 'loadout' that " + + " you can switch into as you wish. A backup will be made before any changes are applied to the application database." + + " This backup is overwritten each time you use the sort option. You can find the backup in ux0:/data/VITAHomebrewSorter/backups/app.db." + + " \n\nIt is always recommended to restart your vita so that it can refresh your livearea/app.db for any changes (deleted icons, new folders, etc.)" + + " before you run this application."; + ImGui::TextWrapped(usage.c_str()); + ImGui::Unindent(); + + ImGui::EndTabItem(); + } + } +} diff --git a/source/tabs/sort.cpp b/source/tabs/sort.cpp new file mode 100644 index 0000000..53e9c6d --- /dev/null +++ b/source/tabs/sort.cpp @@ -0,0 +1,197 @@ +#include + +#include "config.h" +#include "gui.h" +#include "imgui.h" +#include "tabs.h" +#include "textures.h" + +namespace Tabs { + static const ImVec2 tex_size = ImVec2(20, 20); + static const char *sort_by[] = {"Title", "Title ID"}; + static const char *sort_folders[] = {"Both", "Apps only", "Folders only"}; + + void Sort(AppEntries &entries, State &state, bool &backupExists) { + ImGuiTableFlags tableFlags = ImGuiTableFlags_Resizable | ImGuiTableFlags_BordersInner | ImGuiTableFlags_BordersOuter | + ImGuiTableFlags_SizingStretchProp | ImGuiTableFlags_ScrollY; + + if (ImGui::BeginTabItem("Sort/Backup")) { + ImGui::Dummy(ImVec2(0.0f, 5.0f)); // Spacing + + ImGui::PushID("sort_by"); + ImGui::PushItemWidth(100.f); + if (ImGui::BeginCombo("", sort_by[cfg.sort_by])) { + for (int i = 0; i < IM_ARRAYSIZE(sort_by); i++) { + const bool is_selected = (cfg.sort_by == i); + + if (ImGui::Selectable(sort_by[i], is_selected)) { + cfg.sort_by = i; + Config::Save(cfg); + } + + if (is_selected) { + ImGui::SetItemDefaultFocus(); + } + } + + ImGui::EndCombo(); + } + ImGui::PopItemWidth(); + ImGui::PopID(); + + ImGui::SameLine(); + + ImGui::PushID("sort_folders"); + ImGui::PushItemWidth(150.f); + if (ImGui::BeginCombo("", sort_folders[cfg.sort_folders])) { + for (int i = 0; i < IM_ARRAYSIZE(sort_folders); i++) { + const bool is_selected = (cfg.sort_folders == i); + + if (ImGui::Selectable(sort_folders[i], is_selected)) { + cfg.sort_folders = i; + Config::Save(cfg); + } + + if (is_selected) { + ImGui::SetItemDefaultFocus(); + } + } + + ImGui::EndCombo(); + } + ImGui::PopItemWidth(); + ImGui::PopID(); + + ImGui::SameLine(); + + if (ImGui::RadioButton("Default", cfg.sort_mode == SortDefault)) { + cfg.sort_mode = SortDefault; + AppList::Get(entries); + } + + ImGui::SameLine(); + + if (ImGui::RadioButton("Asc", cfg.sort_mode == SortAsc)) { + cfg.sort_mode = SortAsc; + AppList::Get(entries); + std::sort(entries.icons.begin(), entries.icons.end(), AppList::SortAppAsc); + std::sort(entries.child_apps.begin(), entries.child_apps.end(), AppList::SortChildAppAsc); + AppList::Sort(entries); + } + + ImGui::SameLine(); + + if (ImGui::RadioButton("Desc", cfg.sort_mode == SortDesc)) { + cfg.sort_mode = SortDesc; + AppList::Get(entries); + std::sort(entries.icons.begin(), entries.icons.end(), AppList::SortAppDesc); + std::sort(entries.child_apps.begin(), entries.child_apps.end(), AppList::SortChildAppDesc); + AppList::Sort(entries); + } + + ImGui::SameLine(); + + GUI::DisableButtonInit(cfg.sort_mode == SortDefault); + if (ImGui::Button("Apply Sort", ImVec2(ImGui::GetContentRegionAvail().x * 0.5f, 0.0f))) { + state = StateConfirmSort; + } + GUI::DisableButtonExit(cfg.sort_mode == SortDefault); + + ImGui::SameLine(); + + GUI::DisableButtonInit(!backupExists); + if (ImGui::Button("Restore Backup", ImVec2(ImGui::GetContentRegionAvail().x * 1.0f, 0.0f))) { + state = StateRestore; + } + GUI::DisableButtonExit(!backupExists); + + ImGui::Dummy(ImVec2(0.0f, 5.0f)); // Spacing + + if (ImGui::BeginTable("AppList", 5, tableFlags)) { + ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthFixed); + ImGui::TableSetupColumn("Title"); + ImGui::TableSetupColumn("Page ID", ImGuiTableColumnFlags_WidthFixed); + ImGui::TableSetupColumn("Page No", ImGuiTableColumnFlags_WidthFixed); + ImGui::TableSetupColumn("Pos", ImGuiTableColumnFlags_WidthFixed); + ImGui::TableHeadersRow(); + + for (unsigned int i = 0, counter = 0; i < entries.icons.size(); i++) { + if (entries.icons[i].icon0Type == 7) { + ImGui::TableNextRow(); + + ImGui::TableNextColumn(); + ImGui::Image(reinterpret_cast(icons[Folder].ptr), tex_size); + + ImGui::TableNextColumn(); + std::string title = std::to_string(counter) + ") "; + title.append(entries.icons[i].title); + bool open = ImGui::TreeNodeEx(title.c_str(), ImGuiTreeNodeFlags_SpanFullWidth); + + ImGui::TableNextColumn(); + ImGui::Text("%d", entries.icons[i].pageId); + + ImGui::TableNextColumn(); + ImGui::Text("%d", entries.icons[i].pageNo); + + ImGui::TableNextColumn(); + ImGui::Text("%d", entries.icons[i].pos); + + if (open) { + ImGuiTreeNodeFlags flags = ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_Bullet | ImGuiTreeNodeFlags_NoTreePushOnOpen | ImGuiTreeNodeFlags_SpanFullWidth; + int reserved01 = std::stoi(std::string(entries.icons[i].reserved01)); + + for (unsigned int j = 0; j < entries.child_apps.size(); j++) { + if (entries.child_apps[j].pageNo == reserved01) { + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + + ImGui::TableNextColumn(); + ImGui::TreeNodeEx(entries.child_apps[j].title, flags); + + ImGui::TableNextColumn(); + ImGui::Text("%d", entries.child_apps[j].pageId); + + ImGui::TableNextColumn(); + ImGui::Text("-"); + + ImGui::TableNextColumn(); + ImGui::Text("%d", entries.child_apps[j].pos); + } + } + + ImGui::TreePop(); + } + + counter++; + } + else if (entries.icons[i].pageNo >= 0) { + ImGui::TableNextRow(); + + ImGui::TableNextColumn(); + ImGui::Image(reinterpret_cast(icons[App].ptr), tex_size); + + ImGui::TableNextColumn(); + std::string title = std::to_string(counter) + ") "; + title.append(entries.icons[i].title); + ImGui::Selectable(title.c_str(), false, ImGuiSelectableFlags_SpanAllColumns); + + ImGui::TableNextColumn(); + ImGui::Text("%d", entries.icons[i].pageId); + + ImGui::TableNextColumn(); + ImGui::Text("%d", entries.icons[i].pageNo); + + ImGui::TableNextColumn(); + ImGui::Text("%d", entries.icons[i].pos); + + counter++; + } + } + + ImGui::EndTable(); + } + + ImGui::EndTabItem(); + } + } +} \ No newline at end of file diff --git a/source/textures.cpp b/source/textures.cpp index 03361de..2d66b3a 100644 --- a/source/textures.cpp +++ b/source/textures.cpp @@ -1,9 +1,8 @@ -#include -#include -#include +#include #include #include "imgui.h" +#include "gui.h" #include "log.h" #include "textures.h" @@ -11,68 +10,44 @@ std::vector icons; namespace Textures { constexpr int max_textures = 7; + int GL_RGB = 3, GL_RGBA = 4; - static bool Create(unsigned char *data, GLint format, Tex &texture) { - // Create a OpenGL texture identifier - glGenTextures(1, &texture.id); - glBindTexture(GL_TEXTURE_2D, texture.id); - - // Setup filtering parameters for display - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - - // Upload pixels into texture -#if defined(GL_UNPACK_ROW_LENGTH) && !defined(__EMSCRIPTEN__) - glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); -#endif - glTexImage2D(GL_TEXTURE_2D, 0, format, texture.width, texture.height, 0, format, GL_UNSIGNED_BYTE, data); + static bool LoadImage(const std::string &path, Tex &texture) { + texture.ptr = IMG_LoadTexture(GUI::GetRenderer(), path.c_str()); + + if (!texture.ptr) { + Log::Error("Couldn't load %s: %s\n", path.c_str(), SDL_GetError()); + return false; + } + + SDL_QueryTexture(texture.ptr, nullptr, nullptr, &texture.width, &texture.height); return true; } - static bool LoadImagePNG(const std::string &path, Tex &texture) { - bool ret = false; - png_image image; - sceClibMemset(&image, 0, (sizeof image)); - image.version = PNG_IMAGE_VERSION; - - if (png_image_begin_read_from_file(&image, path.c_str()) != 0) { - image.format = PNG_FORMAT_RGBA; - std::unique_ptr buffer(new png_byte[PNG_IMAGE_SIZE(image)]); - - if (png_image_finish_read(&image, nullptr, buffer.get(), 0, nullptr) != 0) { - texture.width = image.width; - texture.height = image.height; - ret = Textures::Create(buffer.get(), GL_RGBA, texture); - png_image_free(&image); - } - else { - Log::Error("png_image_finish_read failed: %s\n", image.message); - png_image_free(&image); - } + void Free(SDL_Texture *texture) { + if (texture) { + SDL_DestroyTexture(texture); + texture = nullptr; } - else { - Log::Error("png_image_begin_read_from_memory failed: %s\n", image.message); - } - - return ret; } bool Init(void) { - icons.resize(max_textures); - const std::string paths[max_textures] { "app0:res/app.png", "app0:res/db.png", "app0:res/folder.png", "app0:res/page.png", + "app0:res/trash.png", "app0:res/checked.png", - "app0:res/unchecked.png", - "app0:res/trash.png" + "app0:res/unchecked.png" }; for (int i = 0; i < max_textures; i++) { - bool ret = Textures::LoadImagePNG(paths[i], icons[i]); + Tex texture; + bool ret = Textures::LoadImage(paths[i], texture); IM_ASSERT(ret); + + icons.push_back(texture); } return 0; @@ -80,7 +55,7 @@ namespace Textures { void Exit(void) { for (int i = 0; i < max_textures; i++) { - glDeleteTextures(1, &icons[i].id); + Textures::Free(icons[i].ptr); } } } diff --git a/source/utils.cpp b/source/utils.cpp index e4512c0..45cebb9 100644 --- a/source/utils.cpp +++ b/source/utils.cpp @@ -6,12 +6,7 @@ #include "log.h" #include "utils.h" -int SCE_CTRL_ENTER = 0, SCE_CTRL_CANCEL = 0; -unsigned int pressed = 0; - namespace Utils { - static SceCtrlData pad, old_pad; - int InitAppUtil(void) { SceAppUtilInitParam init; SceAppUtilBootParam boot; @@ -33,11 +28,6 @@ namespace Utils { return ret; } - if (R_FAILED(ret = sceAppUtilSystemParamGetInt(SCE_SYSTEM_PARAM_ID_ENTER_BUTTON, reinterpret_cast(¶m.enterButtonAssign)))) { - Log::Error("sceAppUtilSystemParamGetInt(SCE_SYSTEM_PARAM_ID_ENTER_BUTTON) failed: 0x%lx\n", ret); - return ret; - } - if (R_FAILED(ret = sceCommonDialogSetConfigParam(¶m))) { Log::Error("sceCommonDialogSetConfigParam failed: 0x%lx\n", ret); return ret; @@ -56,42 +46,6 @@ namespace Utils { return 0; } - - SceCtrlData ReadControls(void) { - sceClibMemset(&pad, 0, sizeof(SceCtrlData)); - sceCtrlPeekBufferPositive(0, &pad, 1); - pressed = pad.buttons & ~old_pad.buttons; - old_pad = pad; - return pad; - } - - int GetEnterButton(void) { - int button = 0, ret = 0; - if (R_FAILED(ret = sceAppUtilSystemParamGetInt(SCE_SYSTEM_PARAM_ID_ENTER_BUTTON, &button))) { - Log::Error("sceAppUtilSystemParamGetInt(SCE_SYSTEM_PARAM_ID_ENTER_BUTTON) failed: 0x%lx\n", ret); - return ret; - } - - if (button == SCE_SYSTEM_PARAM_ENTER_BUTTON_CIRCLE) { - return SCE_CTRL_CIRCLE; - } - - return SCE_CTRL_CROSS; - } - - int GetCancelButton(void) { - int button = 0, ret = 0; - if (R_FAILED(ret = sceAppUtilSystemParamGetInt(SCE_SYSTEM_PARAM_ID_ENTER_BUTTON, &button))) { - Log::Error("sceAppUtilSystemParamGetInt(SCE_SYSTEM_PARAM_ID_ENTER_BUTTON) failed: 0x%lx\n", ret); - return ret; - } - - if (button == SCE_SYSTEM_PARAM_ENTER_BUTTON_CIRCLE) { - return SCE_CTRL_CROSS; - } - - return SCE_CTRL_CIRCLE; - } int GetDateFormat(void) { int format = 0, ret = 0;