1
Fork 0
This repository has been archived on 2025-04-09. You can view files and clone it, but cannot push or open issues or pull requests.
ctrorganizer/source/main.cpp
2024-01-03 15:59:26 -05:00

326 lines
6.9 KiB
C++

#include <3ds.h>
#include <stdio.h>
#include <dirent.h>
#include <vector>
#include <string>
#include <sstream>
#include <fstream>
#include <algorithm>
#include <citro3d.h>
#include <sstream>
#include <map>
#include <iostream>
#include "browse_entry.h"
#include "vshader_v_shbin.h"
#include "textengine.h"
#include "utility.h"
#include "viewer.h"
#include "textviewer.h"
#include "settingsviewer.h"
enum FileMode {
SELECT,
DELETE,
COPY,
PASTE
}mode;
Viewer* currentViewer;
int currentSelection = 0;
int viewOffset = 0;
std::vector<BrowseEntry*> entries;
std::map<std::string,bool> selectedEntries;
std::string currentPath = "/";
PrintConsole bottomScreen;
u32 kDown;
TextEngine* te;
TextEngine* tb;
void cleanViewer() {
currentViewer->Cleanup();
delete currentViewer;
currentViewer = NULL;
}
void initDirectory() {
currentSelection = 0;
viewOffset = 0;
entries.clear();
DIR *dpdf;
struct dirent *epdf;
dpdf = opendir(currentPath.c_str());
if (dpdf != NULL){
while (epdf = readdir(dpdf)){
BrowseEntry *ent = new BrowseEntry;
ent->name = std::string(epdf->d_name);
if(epdf->d_type == DT_REG) {
ent->isDirectory = false;
} else {
ent->isDirectory = true;
}
entries.push_back(ent);
}
}
//Sort directories first (TODO: sort alphabetically)
std::sort(entries.begin(), entries.end(), [] (BrowseEntry* const& a, BrowseEntry* const& b) {
if(a->isDirectory && !b->isDirectory) {
return true;
} else {
return false;
}
});
}
void OpenDirectory(std::string path, bool isrel) {
if(isrel) {
currentPath += path + "/";
}
initDirectory();
}
//Sometimes going up a directory will permentantly make the directory contents blank, never happened on printf so it's probably a GPU-related issue
void UpDirectory() {
size_t found;
currentPath = currentPath.substr(0, currentPath.length() - 1);
found=currentPath.find_last_of("/\\");
currentPath = currentPath.substr(0, found + 1);
initDirectory();
}
void ViewFile(std::string filename) {
//Re-implement extension checking when we can support something more than plain-text text files
std::string ext = filename.substr(filename.find_last_of(".") + 1);
currentViewer = new TextViewer();
currentViewer->path = currentPath + filename;
currentViewer->Init();
}
std::string GetModeString() {
switch(mode) {
case SELECT:
return "SELECT";
break;
case DELETE:
return "DELETE";
break;
case COPY:
return "COPY";
break;
case PASTE:
return "PASTE";
break;
}
}
void drawFileBrowser() {
te->renderText(8.0f, 8.0f, 0.5f, 0.5f, false, std::string("Current Path:" + currentPath + " View Offset: " + SSTR(viewOffset) + " Cur: " + SSTR(currentSelection) + " Mode: " + GetModeString()).c_str());
for(int i = viewOffset; i < entries.size(); i++) {
if(selectedEntries[(currentPath + entries[i]->name)]) {
te->setTextColor(0x68B0D8FF);
} else {
te->setTextColor(0xFFFFFFFF);
}
if(i == currentSelection) {
if(entries[i]->isDirectory) {
te->renderText(8.0f, (16.0f * i) - (viewOffset * 16.0f) + 16.0f, 0.5f, 0.5f, false, std::string(">[" + Utility::truncate(entries[i]->name, 65, true) + "]").c_str());
} else {
te->renderText(8.0f, (16.0f * i) - (viewOffset * 16.0f) + 16.0f, 0.5f, 0.5f, false, std::string(">" + Utility::truncate(entries[i]->name, 65, true)).c_str());
}
} else {
if(entries[i]->isDirectory) {
te->renderText(8.0f, (16.0f * i) - (viewOffset * 16.0f) + 16.0f, 0.5f, 0.5f, false, std::string("[" + Utility::truncate(entries[i]->name, 65, true) + "]").c_str());
} else {
te->renderText(8.0f, (16.0f * i) - (viewOffset * 16.0f) + 16.0f, 0.5f, 0.5f, false, std::string(Utility::truncate(entries[i]->name, 65, true)).c_str());
}
}
}
if(entries.size() <= 0) {
te->renderText(8.0f, 32.0f, 0.5f, 0.5f, false, "Directory is empty!");
}
}
void updateFilebrowser() {
if(kDown & KEY_SELECT) {
currentViewer = new SettingsViewer();
currentViewer->Init();
}
//Find a better way to cycle through these
if(kDown & KEY_L) {
switch(mode) {
case SELECT:
mode = DELETE;
break;
case DELETE:
mode = COPY;
break;
case COPY:
mode = PASTE;
break;
case PASTE:
mode = SELECT;
break;
}
}
//Mode action
if(kDown & KEY_X) {
switch(mode) {
case SELECT:
{
selectedEntries[(currentPath + entries[currentSelection]->name)] = !selectedEntries[(currentPath + entries[currentSelection]->name)];
printf("Toggled selection for: %s\n", (currentPath + entries[currentSelection]->name).c_str());
}
break;
}
}
if(kDown & KEY_UP) {
//Easy fix until i'm bothered to fix the issue
if(currentSelection < 0 | viewOffset < 0) {
currentSelection = 0;
viewOffset = 0;
}
if(viewOffset != 0) {
viewOffset -= 1;
currentSelection -= 1;
}
if(currentSelection != 0) {
currentSelection -= 1;
}
}
if(kDown & KEY_DOWN) {
//Failsafe to prevent crashing
if(currentSelection > entries.size()) {
currentSelection = 0;
viewOffset = 0;
}
if(currentSelection == 13 + viewOffset) {
viewOffset += 1;
}
if(currentSelection != entries.size() - 1) {
currentSelection += 1;
}
}
if(kDown & KEY_A) {
if(!entries[currentSelection]->isDirectory) {
ViewFile(entries[currentSelection]->name);
} else {
OpenDirectory(entries[currentSelection]->name, true);
}
}
if(kDown & KEY_B) {
if(currentPath != "./")
UpDirectory();
}
}
void update() {
if(currentViewer == NULL) {
updateFilebrowser();
} else {
if(!currentViewer->Update(kDown)) {
cleanViewer();
return;
}
}
}
void drawTopScreen() {
if(currentViewer == NULL) {
drawFileBrowser();
} else {
currentViewer->Draw(te);
}
}
void drawBottomScreen() {
if(currentViewer == NULL) {
tb->renderText(8.0f, 8.0f, 0.5f, 0.5f, false, std::string("A - View file").c_str());
tb->renderText(8.0f, 16.0f, 0.5f, 0.5f, false, std::string("X - Mode action").c_str());
tb->renderText(8.0f, 32.0f, 0.5f, 0.5f, false, std::string("L - Switch mode").c_str());
tb->renderText(8.0f, 50.0f, 0.5f, 0.5f, false, std::string("Start - Exit").c_str());
}
}
void Cleanup() {
te->Cleanup();
entries.clear();
if(currentViewer != NULL) {
cleanViewer();
}
C3D_Fini();
gfxExit();
}
int main(int argc, char **argv)
{
gfxInitDefault();
C3D_Init(C3D_DEFAULT_CMDBUF_SIZE);
te = new TextEngine();
te->Initialize(GFX_TOP);
tb = new TextEngine();
tb->Initialize(GFX_BOTTOM);
//TODO: Thanks to TheCruel (xerpi) for the solution to the GPU freezing issue on cia builds
//aptHook(&apt_hook_cookie, apt_hook_func, NULL);
initDirectory();
while (aptMainLoop())
{
hidScanInput();
kDown = hidKeysDown();
update();
if (kDown & KEY_START)
break;
C3D_FrameBegin(C3D_FRAME_SYNCDRAW);
te->Update();
C3D_FrameDrawOn(te->target);
drawTopScreen();
tb->Update();
C3D_FrameDrawOn(tb->target);
drawBottomScreen();
C3D_FrameEnd(0);
}
Cleanup();
return 0;
}