Skip to content

Commit

Permalink
feat(tesseratos): add file selector plugin
Browse files Browse the repository at this point in the history
  • Loading branch information
Scarface1809 committed Oct 11, 2024
1 parent ff78548 commit a47cace
Show file tree
Hide file tree
Showing 4 changed files with 221 additions and 0 deletions.
1 change: 1 addition & 0 deletions tools/tesseratos/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ set(TESSERATOS_SOURCE
"src/tesseratos/scene_editor/plugin.cpp"
"src/tesseratos/voxel_palette_editor/plugin.cpp"
"src/tesseratos/importer/plugin.cpp"
"src/tesseratos/file_selector/plugin.cpp"
)

add_executable(tesseratos ${TESSERATOS_SOURCE})
Expand Down
193 changes: 193 additions & 0 deletions tools/tesseratos/src/tesseratos/file_selector/plugin.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
#include "plugin.hpp"
#include <filesystem>

#include <imgui.h>

#include <cubos/core/data/fs/file_system.hpp>
#include <cubos/core/memory/standard_stream.hpp>

#include <cubos/engine/imgui/plugin.hpp>

using cubos::core::data::FileSystem;
using cubos::engine::Cubos;

namespace fs = std::filesystem;

using namespace tesseratos;

namespace
{
struct FileSelectorState
{
CUBOS_ANONYMOUS_REFLECT(FileSelectorState);

// Absolute path to the current directory (for the filesystem not for the virtual filesystem)
std::string currentPath =
(fs::current_path().parent_path().parent_path() / "tools" / "tesseratos" / "assets").string();
// bool isLocal = true to use the virtual filesystem
bool isLocal = true;
bool isGridMode = true;
bool showFileSelector = false;
std::string selectedFile;
};
} // namespace

static std::optional<std::string> showFileSelector(FileSelectorState& state)
{
if (!state.showFileSelector)
{
return std::nullopt;
}

ImGui::Begin("File Selector");

// Absolue path for the virtual filesystem
std::string relativePath =
fs::relative(state.currentPath, fs::current_path().parent_path().parent_path() / "tools" / "tesseratos")
.string();

std::replace(relativePath.begin(), relativePath.end(), '\\', '/');

ImGui::Text("Current Path: %s", state.isLocal ? std::string(relativePath).c_str() : state.currentPath.c_str());

ImGui::Separator();

// Search bar
static char searchBuffer[256] = "";
ImGui::InputTextWithHint("##search", "Search...", searchBuffer, sizeof(searchBuffer));

ImGui::SameLine();

// Parent directory button
if (!(state.isLocal && relativePath == "assets"))
{
if (ImGui::Button("Up"))
{
state.currentPath = fs::path(state.currentPath).parent_path().string();
}
}

ImGui::SameLine();

// View mode toggle
if (ImGui::RadioButton("Grid", state.isGridMode))
{
state.isGridMode = true;
}

ImGui::SameLine();

if (ImGui::RadioButton("List", !state.isGridMode))
{
state.isGridMode = false;
}

ImGui::Separator();

float cellSize = 100.0F; // Size of each grid cell
float padding = 10.0F; // Padding between cells

if (state.isGridMode)
{
// Calculate number of columns for grid layout
float panelWidth = ImGui::GetContentRegionAvail().x;
int columns = (int)(panelWidth / (cellSize + padding));
if (columns < 1)
{
columns = 1;
}
ImGui::Columns(columns, nullptr, false);
}

for (const auto& entry : fs::directory_iterator(state.currentPath))
{
// Filter files and directories based on search query
std::string fileName = entry.path().filename().string();
if (strlen(searchBuffer) > 0 && fileName.find(searchBuffer) == std::string::npos)
continue;

if (entry.is_directory())
{
// Directories
if (ImGui::Button((fileName + "/").c_str(), state.isGridMode ? ImVec2(cellSize, cellSize) : ImVec2(0, 0)))
{
state.currentPath = entry.path().string();
}
}
else if (entry.is_regular_file())
{
// Files
if (ImGui::Selectable(fileName.c_str(), state.selectedFile == entry.path().string(), 0,
state.isGridMode ? ImVec2(cellSize, cellSize) : ImVec2(0, 0)))
{
std::string selectedFilePath = entry.path().string();
if (state.isLocal)
{
selectedFilePath = fs::relative(selectedFilePath, fs::current_path().parent_path().parent_path() /
"tools" / "tesseratos")
.string();
std::replace(selectedFilePath.begin(), selectedFilePath.end(), '\\', '/');
state.selectedFile = selectedFilePath;
}
else
{
state.selectedFile = selectedFilePath;
}
}
}

if (state.isGridMode)
ImGui::NextColumn(); // Move to next column in grid layout
}

if (state.isGridMode)
ImGui::Columns(1); // End grid layout

ImGui::Separator();

// Display selected file
if (!state.selectedFile.empty())
{
ImGui::Text("Selected File: %s", state.selectedFile.c_str());

// Confirm button
if (ImGui::Button("Select"))
{
ImGui::End();
std::string selectedFile = state.selectedFile;
state.selectedFile.clear();
state.showFileSelector = false;
return selectedFile;
}
}
else
{
ImGui::Text("No file selected.");
}

ImGui::End();
return std::nullopt;
}

static std::optional<std::string> createFileSelectorButton(FileSelectorState& state, const char* label)
{
if (ImGui::Button(label))
{
state.showFileSelector = true;
}

auto selectedFile = showFileSelector(state);
return selectedFile;
}

void tesseratos::fileSelectorPlugin(Cubos& cubos)
{
cubos.depends(cubos::engine::imguiPlugin);
cubos.resource<FileSelectorState>();

cubos.system("show File Selector UI").tagged(cubos::engine::imguiTag).call([](FileSelectorState& state) {
ImGui::Begin("File Selector");
createFileSelectorButton(state, "Open File Selector");
ImGui::End();
});
}
25 changes: 25 additions & 0 deletions tools/tesseratos/src/tesseratos/file_selector/plugin.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/// @dir
/// @brief @ref tesseratos-file-selector-plugin plugin directory.

/// @file
/// @brief Plugin entry point.
/// @ingroup tesseratos-file-selector-plugin

#pragma once

#include <cubos/engine/prelude.hpp>

namespace tesseratos
{
/// @defgroup tesseratos-file-selector-plugin Asset explorer
/// @ingroup tesseratos
/// @brief Allows selecting files in the filesystem
///
/// ## Dependencies
/// - @ref imgui-plugin

/// @brief Plugin entry function.
/// @param cubos @b Cubos main class
/// @ingroup tesseratos-file-selector-plugin
void fileSelectorPlugin(cubos::engine::Cubos& cubos);
} // namespace tesseratos
2 changes: 2 additions & 0 deletions tools/tesseratos/src/tesseratos/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

#include "asset_explorer/plugin.hpp"
#include "debugger/plugin.hpp"
#include "file_selector/plugin.hpp"
#include "importer/plugin.hpp"
#include "scene_editor/plugin.hpp"
#include "voxel_palette_editor/plugin.hpp"
Expand Down Expand Up @@ -38,6 +39,7 @@ int main(int argc, char** argv)
cubos.plugin(sceneEditorPlugin);
cubos.plugin(voxelPaletteEditorPlugin);
cubos.plugin(importerPlugin);
cubos.plugin(fileSelectorPlugin);

cubos.startupSystem("configure Assets plugin").tagged(cubos::engine::settingsTag).call([](Settings& settings) {
settings.setString("assets.io.path", TESSERATOS_ASSETS_FOLDER);
Expand Down

0 comments on commit a47cace

Please sign in to comment.