imGui: Switch to SDL2 renderer backend

This commit is contained in:
joel16 2024-05-11 15:17:53 -04:00
parent 3c15a7fff3
commit bed515818f
16 changed files with 675 additions and 960 deletions

View File

@ -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

View File

@ -1,5 +1,13 @@
#pragma once
#include <SDL.h>
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);
}

View File

@ -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);

40
include/tabs.h Normal file
View File

@ -0,0 +1,40 @@
#pragma once
#include <psp2/io/dirent.h>
#include <string>
#include <vector>
#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<SceIoDirent> &loadouts, State &state, int &date_format, std::string &loadout_name);
void Settings(void);
}

View File

@ -1,10 +1,10 @@
#pragma once
#include <vitaGL.h>
#include <SDL.h>
#include <vector>
typedef struct {
GLuint id = 0;
SDL_Texture *ptr = nullptr;
int width = 0;
int height = 0;
} Tex;

View File

@ -1,6 +1,5 @@
#pragma once
#include <psp2/ctrl.h>
#include <psp2/system_param.h>
/// 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);
}

View File

@ -2,66 +2,26 @@
#include <cstdio>
#include <psp2/power.h>
#include <psp2/kernel/clib.h>
#include <vitaGL.h>
#include <SDL.h>
#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<int>(ImGui::GetIO().DisplaySize.x), static_cast<int>(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<SceIoDirent> &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();
}
if (ImGui::BeginTabItem("Sort/Backup")) {
ImGui::Dummy(ImVec2(0.0f, 5.0f)); // Spacing
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);
}
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);
SDL_Renderer *GetRenderer(void) {
return renderer;
}
if (ImGui::Selectable(sort_by[i], is_selected)) {
cfg.sort_by = i;
Config::Save(cfg);
}
SDL_Window *GetWindow(void) {
return window;
}
if (is_selected) {
ImGui::SetItemDefaultFocus();
}
}
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;
}
ImGui::EndCombo();
}
ImGui::PopItemWidth();
ImGui::PopID();
// 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;
}
ImGui::SameLine();
// 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::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);
ImGui_ImplSDL2_InitForSDLRenderer(window, renderer);
ImGui_ImplSDLRenderer2_Init(renderer);
if (ImGui::Selectable(sort_folders[i], is_selected)) {
cfg.sort_folders = i;
Config::Save(cfg);
}
// Build font atlas
unsigned char *pixels = nullptr;
int width = 0, height = 0, bytes_per_pixel = 0;
if (is_selected) {
ImGui::SetItemDefaultFocus();
}
}
ImFontConfig font_config;
font_config.OversampleH = 1;
font_config.OversampleV = 1;
font_config.PixelSnapH = 1;
ImGui::EndCombo();
}
ImGui::PopItemWidth();
ImGui::PopID();
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;
if (ImGui::RadioButton("Default", cfg.sort_mode == SortDefault)) {
cfg.sort_mode = SortDefault;
AppList::Get(entries);
}
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);
ImGui::SameLine();
return 0;
}
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);
}
void Exit(void) {
ImGui_ImplSDLRenderer2_Shutdown();
ImGui_ImplSDL2_Shutdown();
ImGui::DestroyContext();
ImGui::SameLine();
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
}
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<ImTextureID>(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<ImTextureID>(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();
void DisableButtonInit(bool disable) {
if (disable) {
ImGui::PushItemFlag(ImGuiItemFlags_Disabled, true);
ImGui::PushStyleVar(ImGuiStyleVar_Alpha, ImGui::GetStyle().Alpha * 0.5f);
}
}
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;
}
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<ImTextureID>(icons[Page].id), 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<int>(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();
}
}
static void LoadoutsTab(std::vector<SceIoDirent> &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<ImTextureID>(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<SceSystemParamDateFormat>(date_format), loadouts[i].d_stat.st_mtime);
ImGui::Text(date);
ImGui::TableNextColumn();
ImGui::PushID(i);
if (ImGui::ImageButton("", reinterpret_cast<ImTextureID>(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;

View File

@ -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 <math.h>
#include <psp2/kernel/clib.h>
#include <psp2/kernel/processmgr.h>
#include <stdio.h>
#include <stdlib.h>
#include <vitaGL.h>
#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_ImplVitaGL_Data *>(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<float>(w), static_cast<float>(h));
if (w > 0 && h > 0)
io.DisplayFramebufferScale = ImVec2(static_cast<float>(display_w / w),static_cast<float>(display_h) / h);
static uint64_t frequency = 1000000;
uint64_t current_time = sceKernelGetProcessTimeWide();
io.DeltaTime = bd->g_Time > 0 ? static_cast<float>(static_cast<double>((current_time - bd->g_Time)) / frequency) : static_cast<float>(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<GLsizei>(fb_width), static_cast<GLsizei>(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<int>(draw_data->DisplaySize.x * draw_data->FramebufferScale.x);
int fb_height = static_cast<int>(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<const GLvoid *>(reinterpret_cast<const char *>(vtx_buffer) + IM_OFFSETOF(ImDrawVert, pos)));
glTexCoordPointer(2, GL_FLOAT, sizeof(ImDrawVert), reinterpret_cast<const GLvoid *>(reinterpret_cast<const char *>(vtx_buffer) + IM_OFFSETOF(ImDrawVert, uv)));
glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(ImDrawVert), reinterpret_cast<const GLvoid *>(reinterpret_cast<const char *>(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<int>(clip_min.x), static_cast<int>(static_cast<float>(fb_height) - clip_max.y), static_cast<int>(clip_max.x - clip_min.x), static_cast<int>(clip_max.y - clip_min.y));
// Bind texture, Draw
glBindTexture(GL_TEXTURE_2D, reinterpret_cast<GLuint>(pcmd->GetTexID()));
glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(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<GLuint>(last_texture));
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glPopAttrib();
glPolygonMode(GL_FRONT, static_cast<GLenum>(last_polygon_mode[0])); glPolygonMode(GL_BACK, static_cast<GLenum>(last_polygon_mode[1]));
glViewport(last_viewport[0], last_viewport[1], static_cast<GLsizei>(last_viewport[2]), static_cast<GLsizei>(last_viewport[3]));
glScissor(last_scissor_box[0], last_scissor_box[1], static_cast<GLsizei>(last_scissor_box[2]), static_cast<GLsizei>(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<unsigned char **>(&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<ImTextureID>(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();
}

View File

@ -3,8 +3,8 @@
#include <locale>
#include <psp2/kernel/clib.h>
#include <psp2/ime_dialog.h>
#include <vitaGL.h>
#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();
@ -99,7 +98,7 @@ namespace Keyboard {
done = false;
}
vglSwapBuffers(GL_TRUE);
SDL_RenderPresent(GUI::GetRenderer());
} while(!done);
return text;

View File

@ -1,10 +1,8 @@
#include <psp2/sysmodule.h>
#include <vitaGL.h>
#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;

70
source/tabs/loadouts.cpp Normal file
View File

@ -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<SceIoDirent> &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<ImTextureID>(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<SceSystemParamDateFormat>(date_format), loadouts[i].d_stat.st_mtime);
ImGui::Text(date);
ImGui::TableNextColumn();
ImGui::PushID(i);
if (ImGui::ImageButton("", reinterpret_cast<ImTextureID>(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();
}
}
}

76
source/tabs/pages.cpp Normal file
View File

@ -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<ImTextureID>(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<int>(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();
}
}
}

67
source/tabs/settings.cpp Normal file
View File

@ -0,0 +1,67 @@
#include <SDL.h>
#include <string>
#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();
}
}
}

197
source/tabs/sort.cpp Normal file
View File

@ -0,0 +1,197 @@
#include <algorithm>
#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<ImTextureID>(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<ImTextureID>(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();
}
}
}

View File

@ -1,9 +1,8 @@
#include <memory>
#include <png.h>
#include <psp2/kernel/clib.h>
#include <SDL_image.h>
#include <string>
#include "imgui.h"
#include "gui.h"
#include "log.h"
#include "textures.h"
@ -11,68 +10,44 @@ std::vector<Tex> 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);
static bool LoadImage(const std::string &path, Tex &texture) {
texture.ptr = IMG_LoadTexture(GUI::GetRenderer(), path.c_str());
// 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);
if (!texture.ptr) {
Log::Error("Couldn't load %s: %s\n", path.c_str(), SDL_GetError());
return false;
}
// 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);
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<png_byte[]> 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);
}
}
}

View File

@ -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<int *>(&param.enterButtonAssign)))) {
Log::Error("sceAppUtilSystemParamGetInt(SCE_SYSTEM_PARAM_ID_ENTER_BUTTON) failed: 0x%lx\n", ret);
return ret;
}
if (R_FAILED(ret = sceCommonDialogSetConfigParam(&param))) {
Log::Error("sceCommonDialogSetConfigParam failed: 0x%lx\n", ret);
return ret;
@ -57,42 +47,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;