Skip to content
This repository has been archived by the owner on Sep 16, 2024. It is now read-only.

Commit

Permalink
filepicker
Browse files Browse the repository at this point in the history
  • Loading branch information
OFFTKP committed Jan 11, 2024
1 parent 4c4440a commit ac79932
Show file tree
Hide file tree
Showing 42 changed files with 5,380 additions and 80 deletions.
28 changes: 21 additions & 7 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ set(BUILD_SHARED_LIBS OFF)
set(BUILD_STATIC_LIBS ON)
set(DPP_BUILD_TEST OFF)

if (WIN32)
if(WIN32)
set(HYDRA_DEFINITIONS ${HYDRA_DEFINITIONS} HYDRA_WINDOWS WIN32_LEAN_AND_MEAN NOMINMAX)
set(HYDRA_WINDOWS 1)
elseif(APPLE)
Expand Down Expand Up @@ -84,7 +84,7 @@ else()
endif()

# Thanks SkyEmu for most of these configurations
if (MSVC)
if(MSVC)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /MT /Ox /Ob2 /Oi /Ot /GT /GF /GS- /fp:fast /fp:except- /MP /sdl- /EHsc /D_SECURE_SCL=0 /D_SCL_SECURE_NO_WARNINGS /D_ITERATOR_DEBUG_LEVEL=0 /D_HAS_ITERATOR_DEBUGGING=0")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MT /Ox /Ob2 /Oi /Ot /GT /GF /GS- /fp:fast /fp:except- /MP /sdl- /EHsc /D_SECURE_SCL=0 /D_SCL_SECURE_NO_WARNINGS /D_ITERATOR_DEBUG_LEVEL=0 /D_HAS_ITERATOR_DEBUGGING=0")
else()
Expand Down Expand Up @@ -112,6 +112,11 @@ set_property(TARGET ssl PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded")
set_property(TARGET crypto PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded")
set(HYDRA_LIBRARIES ${HYDRA_LIBRARIES} ssl crypto)

if(HYDRA_LINUX OR HYDRA_FREEBSD OR HYDRA_MACOS OR HYDRA_WINDOWS)
set(HYDRA_DESKTOP 1)
set(HYDRA_DEFINITIONS ${HYDRA_DEFINITIONS} HYDRA_DESKTOP)
endif()

if(NOT HYDRA_WEB)
set(CURL_USE_LIBSSH2 OFF)
set(CURL_USE_LIBPSL OFF)
Expand All @@ -121,7 +126,7 @@ if(NOT HYDRA_WEB)
set(CURL_ENABLE_EXPORT_TARGET OFF)
set(BUILD_TESTING OFF)
set(BUILD_CURL_EXE OFF)
if (WIN32)
if(WIN32)
set(CURL_STATIC_CRT ON)
endif()
add_definitions(-DCURL_STATICLIB)
Expand All @@ -137,6 +142,14 @@ if(HYDRA_LINUX OR HYDRA_FREEBSD OR HYDRA_WINDOWS)
find_package(OpenGL REQUIRED)
endif()

if(HYDRA_DESKTOP)
add_subdirectory(vendored/nativefiledialog)
set(HYDRA_INCLUDES ${HYDRA_INCLUDES}
vendored/nativefiledialog/src/include
)
set(HYDRA_LIBRARIES ${HYDRA_LIBRARIES} nfd)
endif()

if(HYDRA_MACOS OR HYDRA_IOS)
set_target_properties(hydra PROPERTIES
MACOSX_BUNDLE ON
Expand All @@ -162,6 +175,7 @@ set(HYDRA_IMGUI_FILES
src/app.cxx
src/gamewindow.cxx
src/mainwindow.cxx
src/filepicker.cxx
vendored/imgui/backends/imgui_impl_sdl3.cpp
vendored/imgui/backends/imgui_impl_opengl3.cpp
vendored/imgui/imgui.cpp
Expand Down Expand Up @@ -214,7 +228,7 @@ cmrc_add_resource_library(hydra_data ALIAS hydra::data NAMESPACE hydra

set(HYDRA_LIBRARIES ${HYDRA_LIBRARIES} hydra::data)

if (BUILD_QT)
if(BUILD_QT)
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
Expand All @@ -224,14 +238,14 @@ if (BUILD_QT)
set(HYDRA_SOURCES ${HYDRA_SOURCES} ${HYDRA_QT_FILES})
endif()

if (BUILD_DISCORD_BOT)
if(BUILD_DISCORD_BOT)
add_subdirectory(vendored/DPP)
add_definitions(-DHYDRA_DISCORD_BOT)
set(HYDRA_SOURCES ${HYDRA_SOURCES} ${HYDRA_BOT_FILES})
set(HYDRA_LIBRARIES ${HYDRA_LIBRARIES} dpp)
endif()

if (BUILD_LUA)
if(BUILD_LUA)
find_package(Lua REQUIRED)
set(HYDRA_INCLUDES
${HYDRA_INCLUDES}
Expand Down Expand Up @@ -266,6 +280,6 @@ target_include_directories(hydra PRIVATE ${HYDRA_INCLUDES})
target_compile_definitions(hydra PRIVATE HYDRA_VERSION="${PROJECT_VERSION}")
target_compile_definitions(hydra PRIVATE ${HYDRA_DEFINITIONS})

if (HYDRA_LINUX OR HYDRA_FREEBSD OR HYDRA_MACOS OR HYDRA_ANDROID OR HYDRA_WEB)
if(HYDRA_LINUX OR HYDRA_FREEBSD OR HYDRA_MACOS OR HYDRA_ANDROID OR HYDRA_WEB)
target_compile_definitions(hydra PRIVATE HYDRA_LIBDL)
endif()
5 changes: 4 additions & 1 deletion VENDORED.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
### Hydra vendored libraries
- [OpenSSL 1.1.1w](https://github.com/janbar/openssl-cmake)
- [CURL 8.5.0](https://github.com/curl/curl)
- [DPP](https://github.com/brainboxdotcc/DPP)
- [sol 3.2.3](https://github.com/ThePhD/sol2)
- [miniaudio 0.11.21](https://github.com/mackron/miniaudio)
- [stb_image 2.28](https://github.com/nothings/stb)
Expand All @@ -10,4 +11,6 @@
- [SDL3 2.28.5](https://github.com/libsdl-org/SDL)
- [glad gl=4.6, gles1=1.0, gles2=3.2](https://github.com/Dav1dde/glad)
- [miniz 3.0.0](https://github.com/richgel999/miniz)
- [fmt](https://github.com/fmtlib/fmt/)
- [fmt](https://github.com/fmtlib/fmt/)
- [nativefiledialog 1.1.1](https://github.com/btzy/nativefiledialog-extended)
- [toml11 3.8.1](https://github.com/ToruNiina/toml11)
14 changes: 11 additions & 3 deletions include/compatibility.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include <cstdint>
#include <filesystem>
#include <functional>
#include <log.hxx>
#include <span>
#include <sstream>
Expand All @@ -12,16 +13,23 @@
#include <emscripten.h>
#endif

static void sync_fs()
static void sync_fs(std::function<void()> callback = nullptr)
{
#ifdef HYDRA_WEB
EM_ASM(
std::function<void()>* func = nullptr;
if (callback)
{
func = new std::function<void()>(callback);
}
EM_ASM({
FS.syncfs(false, function (err) {
if (err) {
console.log("Failed to sync FS: " + err);
} else {
Module.ccall('callback_wrapper', null, ['number'], [$0]);
}
});
);
}, func);
#endif
}

Expand Down
29 changes: 29 additions & 0 deletions include/filepicker.hxx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#pragma once

#include <functional>
#include <imgui/imgui.h>
#include <string>
#include <utility>
#include <vector>

using FilePickerFilters = std::vector<std::pair<std::string, std::string>>;

class FilePicker
{
public:
FilePicker(const std::string& id, const std::string& name, const std::string& default_path,
const FilePickerFilters& filters, std::function<void(const char*)> callback);
~FilePicker();
void update(ImVec2 start, ImVec2 end);

private:
std::string id;
std::string imgui_id;
std::string name;
std::function<void(const char*)> callback;
FilePickerFilters filters;

#ifdef HYDRA_WEB
std::string html_id;
#endif
};
5 changes: 4 additions & 1 deletion include/mainwindow.hxx
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
#pragma once

#include "filepicker.hxx"
#include "gamewindow.hxx"
#include "imgui.h"
#include <array>
#include <filesystem>
#include <functional>
#include <imgui/imgui.h>
#include <string>
#include <unordered_map>
#include <vector>
Expand Down Expand Up @@ -44,4 +45,6 @@ private:
size_t open_core_settings = -1;
std::unordered_map<std::string, std::vector<std::function<void()>>> settings_functions;
std::unique_ptr<GameWindow> game_window;

FilePicker rom_picker;
};
21 changes: 14 additions & 7 deletions src/app.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -60,21 +60,28 @@ extern "C" void hydra_drop_file(const char* name, void* data, size_t size)
std::filesystem::path out_path = cores / file;
std::ofstream ofs(out_path, std::ios_base::binary | std::ios_base::out);
ofs.write((const char*)data, size);
sync_fs();
Settings::ReinitCoreInfo();
sync_fs([] { Settings::ReinitCoreInfo(); });
}
else
{
std::filesystem::path cache = Settings::GetCachePath();
std::filesystem::path out_path = cache / file;
std::ofstream ofs(out_path, std::ios_base::binary | std::ios_base::out);
ofs.write((const char*)data, size);
sync_fs();
hydra::fwrite(out_path, std::span<uint8_t>((uint8_t*)data, size));
}
}

extern "C" void callback_wrapper(void* callback)
{
if (callback)
{
std::function<void()>* func = (std::function<void()>*)callback;
(*func)();
delete func;
}
}

#ifdef HYDRA_WEB
EM_JS(void, add_drag_drop_listeners, (), {
EM_JS(void, hydra_web_initialize, (), {
var canvas = document.getElementById("canvas");
canvas.addEventListener(
"dragenter",
Expand Down Expand Up @@ -186,7 +193,7 @@ int imgui_main(int argc, char* argv[])
#endif

#ifdef HYDRA_WEB
add_drag_drop_listeners();
hydra_web_initialize();
#endif

IMGUI_CHECKVERSION();
Expand Down
74 changes: 74 additions & 0 deletions src/filepicker.cxx
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
#include <filepicker.hxx>
#include <imgui/imgui.h>
#include <nfd.h>

#ifdef HYDRA_WEB
int html_id_last = 0;
#include <emscripten.h>
#endif

FilePicker::FilePicker(const std::string& id, const std::string& name,
const std::string& default_path, const FilePickerFilters& filters,
std::function<void(const char*)> callback)
: id(id), name(name), filters(filters), callback(callback)
{
imgui_id = this->name + "##" + this->id;
#ifdef HYDRA_WEB
html_id = "filepicker_" + std::to_string(html_id_last++);
EM_ASM({
var input = document.createElement('input');
input.type = 'file';
input.id = $0;
input.value = '';
document.body.appendChild(input);
input.onmousemove = input.onmouseover = function(e) {
const mouseMoveEvent = new MouseEvent('mousemove', {
bubbles: true,
cancelable: true,
clientX: event.clientX,
clientY: event.clientY
});
document.getElementById('canvas').dispatchEvent(mouseMoveEvent);
};
}, html_id.c_str());
#endif
}

FilePicker::~FilePicker()
{
#ifdef HYDRA_WEB
EM_ASM({
var element = document.getElementById($0);
element.parentNode.removeChild(element);
}, html_id.c_str());
#endif
}

void FilePicker::update(ImVec2 start, ImVec2 end)
{
bool hovered = ImGui::IsMouseHoveringRect(start, end);
if (hovered && ImGui::IsMouseClicked(0))
{
#ifdef HYDRA_DESKTOP
NFD_Init();
nfdchar_t* path = nullptr;
nfdfilteritem_t* filter = new nfdfilteritem_t[filters.size()];
for (size_t i = 0; i < filters.size(); ++i)
{
filter[i].name = filters[i].first.c_str();
filter[i].spec = filters[i].second.c_str();
}
nfdresult_t result = NFD_OpenDialog(&path, filter, filters.size(), NULL);
if (result == NFD_OKAY)
{
callback(path);
NFD_FreePath(path);
}
else if (result != NFD_CANCEL)
{
printf("Error: %s\n", NFD_GetError());
}
NFD_Quit();
#endif
}
}
32 changes: 23 additions & 9 deletions src/mainwindow.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ constexpr const char* icons[tab_count] = {ICON_MD_GAMES, ICON_MD_MEMORY, ICON_MD
ICON_MD_INFO};

MainWindow::MainWindow()
: rom_picker("rom_picker", "Load ROM", "", {}, [this](const char* path) { loadRom(path); })
{
selected_y = ImGui::GetStyle().WindowPadding.y + ImGui::GetStyle().ItemSpacing.y;
core_directory.resize(4096);
Expand Down Expand Up @@ -149,20 +150,33 @@ void MainWindow::update()
}
}

void MainWindow::loadRom(const std::filesystem::path& path) {}
void MainWindow::loadRom(const std::filesystem::path& path)
{
game_window = std::make_unique<GameWindow>("/hydra/cores/libNanoBoyAdvance-hydra.wasm",
"/hydra/cache/emerald.gba");
if (!game_window->isLoaded())
{
game_window.reset();
}
}

void MainWindow::draw_games()
{
if (ImGui::Button(ICON_MD_FOLDER " Load ROM"))
ImDrawList* draw_list = ImGui::GetWindowDrawList();
ImVec2 min = ImGui::GetCursorPos();
ImVec2 max = ImVec2(ImGui::GetCursorPos().x + ImGui::GetContentRegionAvail().x,
ImGui::GetCursorPos().y + ImGui::GetContentRegionAvail().y * 0.1f);
uint32_t color = ImGui::GetColorU32(ImGuiCol_Button);
if (ImGui::IsMouseHoveringRect(min, max))
{
Settings::Set("NanoBoyAdvance_bios", "/hydra/cache/gba_bios.bin");
game_window = std::make_unique<GameWindow>("/hydra/cores/libNanoBoyAdvance-hydra.wasm",
"/hydra/cache/emerald.gba");
if (!game_window->isLoaded())
{
game_window.reset();
}
color = ImGui::GetColorU32(ImGuiCol_ButtonHovered);
}
draw_list->AddRectFilled(min, max, color, 0, 0);
rom_picker.update(min, max);
min.x += ImGui::GetStyle().ItemSpacing.x;
min.y += ImGui::GetContentRegionAvail().y * 0.05f - hydra::ImGuiHelper::TextHeight() * 0.5f;
ImGui::SetCursorPos(min);
ImGui::Text(ICON_MD_FOLDER " Load ROM");
}

void MainWindow::draw_cores()
Expand Down
11 changes: 11 additions & 0 deletions vendored/nativefiledialog/.clang-format
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
BasedOnStyle: Chromium
IndentWidth: 4
BinPackArguments: false
ColumnLimit: 100
AllowShortIfStatementsOnASingleLine: WithoutElse
AllowShortLoopsOnASingleLine: true
---
Language: Cpp
---
Language: ObjC
Loading

0 comments on commit ac79932

Please sign in to comment.