SDL 3 + curl thread download manager

This commit is contained in:
Anthony 2024-04-01 15:29:00 +02:00
parent 001034db61
commit 42c3d9d215
11 changed files with 313 additions and 145 deletions

View file

@ -12,9 +12,16 @@ LibraryManager::LibraryManager() {}
void LibraryManager::Initialize(const std::string &library_path)
{
m_library_path = library_path;
CheckDirectories();
Scan();
}
void LibraryManager::CheckDirectories()
{
std::filesystem::path dlDir = std::filesystem::path(m_library_path) / "store";
std::filesystem::create_directories(dlDir);
}
void LibraryManager::Scan()
{
std::filesystem::path directoryPath(m_library_path);

View file

@ -24,12 +24,17 @@ public:
void Scan();
std::shared_ptr<StoryProject> NewProject();
void CheckDirectories();
std::shared_ptr<StoryProject> GetStory(const std::string &uuid);
void SetStoreUrl(const std::string &store_url) { m_storeUrl = store_url; }
std::string GetStoreUrl() const { return m_storeUrl; }
private:
std::string m_library_path;
std::vector<std::shared_ptr<StoryProject>> m_projectsList;
std::string m_storeUrl;
};
#endif // LIBRARYMANAGER_H

View file

@ -60,24 +60,36 @@ add_compile_definitions(IMGUI_INCLUDE="imgui.h")
add_subdirectory(libs/ImGuiFileDialog)
# =========================================================================================================================
# SDL
# SDL2
# =========================================================================================================================
Set(FETCHCONTENT_QUIET FALSE)
# FetchContent_Declare(
# sdl2
# GIT_REPOSITORY https://github.com/libsdl-org/SDL.git
# GIT_TAG origin/SDL2
# GIT_SHALLOW TRUE
# GIT_PROGRESS TRUE
# )
# set(BUILD_SHARED_LIBS TRUE)
# set(SDL_STATIC TRUE)
# FetchContent_MakeAvailable(sdl2)
# =========================================================================================================================
# SDL3
# =========================================================================================================================
FetchContent_Declare(
sdl2
sdl3
GIT_REPOSITORY https://github.com/libsdl-org/SDL.git
GIT_TAG origin/SDL2
GIT_TAG prerelease-3.1.0
GIT_SHALLOW TRUE
GIT_PROGRESS TRUE
)
set(BUILD_SHARED_LIBS TRUE)
set(SDL_STATIC TRUE)
FetchContent_MakeAvailable(sdl2)
# add_subdirectory(libs/SDL)
# include_directories(libs/SDL/include)
FetchContent_MakeAvailable(sdl3)
include_directories(${sdl3_SOURCE_DIR}/include)
# =========================================================================================================================
# SDL3-Image
@ -155,8 +167,8 @@ set(SRCS
libs/imgui-node-editor/crude_json.cpp
libs/ImGuiFileDialog/ImGuiFileDialog.cpp
${imgui_SOURCE_DIR}/backends/imgui_impl_sdl2.cpp
${imgui_SOURCE_DIR}/backends/imgui_impl_sdlrenderer2.cpp
${imgui_SOURCE_DIR}/backends/imgui_impl_sdl3.cpp
${imgui_SOURCE_DIR}/backends/imgui_impl_sdlrenderer3.cpp
${imgui_SOURCE_DIR}/backends/imgui_impl_opengl3.cpp
${imgui_SOURCE_DIR}/imgui.cpp
${imgui_SOURCE_DIR}/imgui_widgets.cpp
@ -243,16 +255,17 @@ target_compile_definitions(${STORY_EDITOR_PROJECT} PUBLIC cimg_display=0)
target_compile_definitions(${STORY_EDITOR_PROJECT} PUBLIC "$<$<CONFIG:DEBUG>:DEBUG>")
target_link_directories(${STORY_EDITOR_PROJECT} PUBLIC ${sdl2_BINARY_DIR} ${curl_BINARY_DIR})
message(${sdl2_BINARY_DIR})
set(SDL2_BIN_DIR ${sdl2_BINARY_DIR})
target_link_directories(${STORY_EDITOR_PROJECT} PUBLIC ${sdl3_BINARY_DIR} ${curl_BINARY_DIR})
set(SDL2_BIN_DIR ${sdl3_BINARY_DIR})
if(UNIX)
target_link_libraries(${STORY_EDITOR_PROJECT}
pthread
OpenGL::GL
dl
SDL2
SDL3
libcurl_static
OpenSSL::SSL OpenSSL::Crypto
)

View file

@ -11,23 +11,34 @@ your use of the corresponding standard functions.
#include <iostream>
#include <filesystem>
#include "imgui_impl_sdl2.h"
#include "imgui_impl_sdlrenderer2.h"
#include <stdio.h>
#include <SDL2/SDL.h>
#include "imgui_internal.h"
// SDL2 ---------------------------------
// #include "imgui_impl_sdl2.h"
// #include "imgui_impl_sdlrenderer2.h"
// #include <SDL2/SDL.h>
// #if defined(IMGUI_IMPL_OPENGL_ES2)
// #include <SDL2/SDL_opengles2.h>
// #else
// #include <SDL2/SDL_opengl.h>
//#endif
// SDL3 ---------------------------------
#include "imgui_impl_sdl3.h"
#include "imgui_impl_sdlrenderer3.h"
#include <SDL3/SDL.h>
#if defined(IMGUI_IMPL_OPENGL_ES2)
#include <SDL2/SDL_opengles2.h>
#include <SDL3/SDL_opengles2.h>
#else
#include <SDL2/SDL_opengl.h>
#include <SDL3/SDL_opengl.h>
#endif
#include "IconsMaterialDesignIcons.h"
#include "IconsFontAwesome5_c.h"
#include "qoi.h"
#include "platform_folders.h"
static void glfw_error_callback(int error, const char* description)
{
fprintf(stderr, "GLFW Error %d: %s\n", error, description);
@ -50,8 +61,6 @@ static std::string GetFileExtension(const std::string &fileName)
// Simple helper function to load an image into a OpenGL texture with common settings
bool LoadTextureFromFile(const char* filename, Gui::Image &img)
{
std::string ext = GetFileExtension(filename);
SDL_Surface* surface = nullptr;
@ -64,8 +73,12 @@ bool LoadTextureFromFile(const char* filename, Gui::Image &img)
img.w = desc.width;
img.h = desc.height;
surface = SDL_CreateRGBSurfaceFrom((void*)pixels, img.w, img.h, channels * 8, channels * img.w,
0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000);
// SDL3
surface = SDL_CreateSurfaceFrom((void*)pixels, img.w, img.h, 4 * img.w, SDL_PIXELFORMAT_RGBA8888);
// SDL2
// surface = SDL_CreateRGBSurfaceFrom((void*)pixels, img.w, img.h, channels * 8, channels * img.w,
// 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000);
if (pixels != NULL)
{
@ -84,12 +97,12 @@ bool LoadTextureFromFile(const char* filename, Gui::Image &img)
}
// SDL3
// SDL_Surface* surface = SDL_CreateSurfaceFrom((void*)data, img.w, img.h, 4 * img.w, SDL_PIXELFORMAT_RGBA8888);
//SDL3
surface = SDL_CreateSurfaceFrom((void*)data, img.w, img.h, 4 * img.w, SDL_PIXELFORMAT_RGBA32);
// SDL2
surface = SDL_CreateRGBSurfaceFrom((void*)data, img.w, img.h, channels * 8, channels * img.w,
0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000);
// surface = SDL_CreateRGBSurfaceFrom((void*)data, img.w, img.h, channels * 8, channels * img.w,
// 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000);
stbi_image_free(data);
}
@ -105,8 +118,8 @@ bool LoadTextureFromFile(const char* filename, Gui::Image &img)
fprintf(stderr, "Failed to create SDL texture: %s\n", SDL_GetError());
}
// SDL_DestroySurface(surface); // SDL3
SDL_FreeSurface(surface); // SDL2
SDL_DestroySurface(surface); // SDL3
// SDL_FreeSurface(surface); // SDL2
return true;
@ -129,8 +142,11 @@ Gui::Gui()
bool Gui::Initialize()
{
// Setup SDL
if (SDL_Init(SDL_INIT_EVERYTHING) != 0)
// Setup SDL2
// if (SDL_Init(SDL_INIT_EVERYTHING) != 0)
// Setup SDL3
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_GAMEPAD) != 0)
{
printf("Error: SDL_Init(): %s\n", SDL_GetError());
return -1;
@ -143,17 +159,17 @@ bool Gui::Initialize()
SDL_WindowFlags window_flags = (SDL_WindowFlags)(SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIDDEN);
// SDL3
//window = SDL_CreateWindow("Dear ImGui SDL3+SDL_Renderer example", 1280, 720, window_flags);
window = SDL_CreateWindow("Story Editor", 1280, 720, window_flags);
// SDL2
window = SDL_CreateWindow("Story Editor", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, window_flags);
// window = SDL_CreateWindow("Story Editor", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, window_flags);
if (window == nullptr)
{
printf("Error: SDL_CreateWindow(): %s\n", SDL_GetError());
return -1;
}
renderer = SDL_CreateRenderer(window, 0, SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_ACCELERATED);
renderer = SDL_CreateRenderer(window, nullptr, SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_ACCELERATED);
if (renderer == nullptr)
{
SDL_Log("Error: SDL_CreateRenderer(): %s\n", SDL_GetError());
@ -170,6 +186,7 @@ bool Gui::Initialize()
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;
io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable;
io.Fonts->AddFontFromFileTTF( std::string(m_executablePath + "/fonts/roboto.ttf").c_str(), 20);
@ -201,13 +218,12 @@ bool Gui::Initialize()
// Setup Platform/Renderer backends
// SDL3
// ImGui_ImplSDL3_InitForSDLRenderer(window, renderer);
// ImGui_ImplSDLRenderer3_Init(renderer);
ImGui_ImplSDL3_InitForSDLRenderer(window, renderer);
ImGui_ImplSDLRenderer3_Init(renderer);
// SDL2
ImGui_ImplSDL2_InitForSDLRenderer(window, renderer);
ImGui_ImplSDLRenderer2_Init(renderer);
// ImGui_ImplSDL2_InitForSDLRenderer(window, renderer);
// ImGui_ImplSDLRenderer2_Init(renderer);
// Load Fonts
// - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
@ -237,20 +253,19 @@ bool Gui::PollEvent()
while (SDL_PollEvent(&event))
{
// SDL3
/*
ImGui_ImplSDL3_ProcessEvent(&event);
if (event.type == SDL_EVENT_QUIT)
done = true;
if (event.type == SDL_EVENT_WINDOW_CLOSE_REQUESTED && event.window.windowID == SDL_GetWindowID(window))
done = true;
*/
// SLD2
ImGui_ImplSDL2_ProcessEvent(&event);
if (event.type == SDL_QUIT)
done = true;
if (event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_CLOSE && event.window.windowID == SDL_GetWindowID(window))
done = true;
// ImGui_ImplSDL2_ProcessEvent(&event);
// if (event.type == SDL_QUIT)
// done = true;
// if (event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_CLOSE && event.window.windowID == SDL_GetWindowID(window))
// done = true;
}
return done;
@ -262,12 +277,12 @@ void Gui::StartFrame()
// Start the Dear ImGui frame
// SDL3
// ImGui_ImplSDLRenderer3_NewFrame();
// ImGui_ImplSDL3_NewFrame();
ImGui_ImplSDLRenderer3_NewFrame();
ImGui_ImplSDL3_NewFrame();
// SDL2
ImGui_ImplSDLRenderer2_NewFrame();
ImGui_ImplSDL2_NewFrame();
// ImGui_ImplSDLRenderer2_NewFrame();
// ImGui_ImplSDL2_NewFrame();
ImGui::NewFrame();
}
@ -284,8 +299,8 @@ void Gui::EndFrame()
ImGui::Render();
//ImGui_ImplSDLRenderer3_RenderDrawData(ImGui::GetDrawData()); // SDL3
ImGui_ImplSDLRenderer2_RenderDrawData(ImGui::GetDrawData()); // SDL2
ImGui_ImplSDLRenderer3_RenderDrawData(ImGui::GetDrawData()); // SDL3
// ImGui_ImplSDLRenderer2_RenderDrawData(ImGui::GetDrawData()); // SDL2
SDL_RenderPresent(renderer);
}
@ -295,12 +310,12 @@ void Gui::Destroy()
// Cleanup
// SDL3
// ImGui_ImplSDLRenderer3_Shutdown();
// ImGui_ImplSDL3_Shutdown();
ImGui_ImplSDLRenderer3_Shutdown();
ImGui_ImplSDL3_Shutdown();
// SDL2
ImGui_ImplSDLRenderer2_Shutdown();
ImGui_ImplSDL2_Shutdown();
// ImGui_ImplSDLRenderer2_Shutdown();
// ImGui_ImplSDL2_Shutdown();
ImGui::DestroyContext();
@ -495,7 +510,7 @@ void Gui::ApplyTheme()
#include "imgui_internal.h"
namespace ImGui {
void LoadingIndicatorCircle(const char* label, const float indicator_radius,
const ImVec4& main_color, const ImVec4& backdrop_color,

View file

@ -53,10 +53,10 @@ private:
std::string m_executablePath;
};
namespace ImGui {
void LoadingIndicatorCircle(const char* label, const float indicator_radius,
const ImVec4& main_color, const ImVec4& backdrop_color,
const int circle_count, const float speed);
}
// namespace ImGui {
// void LoadingIndicatorCircle(const char* label, const float indicator_radius,
// const ImVec4& main_color, const ImVec4& backdrop_color,
// const int circle_count, const float speed);
// }
#endif // GUI_H

View file

@ -5,10 +5,26 @@
#include <string>
#include <memory>
#include <list>
#include <functional>
#include "resource.h"
#include "connection.h"
template <typename T>
struct Callback;
template <typename Ret, typename... Params>
struct Callback<Ret(Params...)> {
template <typename... Args>
static Ret callback(Args... args) {
return func(args...);
}
static std::function<Ret(Params...)> func;
};
template <typename Ret, typename... Params>
std::function<Ret(Params...)> Callback<Ret(Params...)>::func;
class IStoryManager
{
public:
@ -36,8 +52,6 @@ public:
virtual void Pause() = 0;
virtual void Next() = 0;
virtual void Previous() = 0;
};
#endif // I_STORY_MANAGER_H

View file

@ -3,61 +3,44 @@
#include "ImGuiFileDialog.h"
#include <filesystem>
#include "IconsMaterialDesignIcons.h"
#include "i_story_manager.h"
#include <functional>
#define CPPHTTPLIB_OPENSSL_SUPPORT
#include "httplib.h"
#define CA_CERT_FILE "./ca-bundle.crt"
typedef int (*xfer_callback_t)(void *clientp, curl_off_t dltotal, curl_off_t dlnow,
curl_off_t ultotal, curl_off_t ulnow);
#include <curl/curl.h>
int xfer_callback(void *clientp, curl_off_t dltotal, curl_off_t dlnow,
curl_off_t ultotal, curl_off_t ulnow)
void download_file(CURL *curl,
const std::string &url,
const std::string &output_file,
std::function<void(bool)> finished_callback)
{
return 0;
}
void download_file(const std::string &output_file = "pi.txt")
{
CURL *curl_download;
FILE *fp;
CURLcode res;
std::string url = "http://www.gecif.net/articles/mathematiques/pi/pi_1_million.txt";
curl_download = curl_easy_init();
if (curl_download)
if (curl)
{
//SetConsoleTextAttribute(hConsole, 11);
fp = fopen(output_file.c_str(),"wb");
curl_easy_setopt(curl_download, CURLOPT_URL, url.c_str());
curl_easy_setopt(curl_download, CURLOPT_WRITEFUNCTION, NULL);
curl_easy_setopt(curl_download, CURLOPT_WRITEDATA, fp);
curl_easy_setopt(curl_download, CURLOPT_NOPROGRESS, 0);
//progress_bar : the fonction for the progress bar
curl_easy_setopt(curl_download, CURLOPT_XFERINFOFUNCTION, xfer_callback);
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
std::cout<<" Start download"<<std::endl<<std::endl;
res = curl_easy_perform(curl_download);
res = curl_easy_perform(curl);
fclose(fp);
if(res == CURLE_OK)
{
std::cout<< std::endl<< std::endl<<" The file was download with succes"<< std::endl;
}
else
{
std::cout<< std::endl << std::endl<<" Error"<< std::endl;
}
curl_easy_cleanup(curl_download);
finished_callback(res == CURLE_OK);
}
}
@ -66,36 +49,78 @@ LibraryWindow::LibraryWindow(IStoryManager &project, LibraryManager &library)
, m_storyManager(project)
, m_libraryManager(library)
{
m_downloadThread = std::thread( std::bind(&LibraryWindow::DownloadThread, this) );
download_file();
m_store_url[0] = 0;
}
httplib::SSLClient cli("gist.githubusercontent.com", 443);
cli.set_ca_cert_path(CA_CERT_FILE);
cli.enable_server_certificate_verification(false);
LibraryWindow::~LibraryWindow()
{
// Cancel any pending download
if (auto res = cli.Get("/UnofficialStories/32702fb104aebfe650d4ef8d440092c1/raw/luniicreations.json")) {
std::cout << res->status << std::endl;
std::cout << res->get_header_value("Content-Type") << std::endl;
m_storeRawJson = res->body;
ParseStoreData();
//std::cout << res->body << std::endl;
} else {
std::cout << "error code: " << res.error() << std::endl;
auto result = cli.get_openssl_verify_result();
if (result) {
std::cout << "verify error: " << X509_verify_cert_error_string(result) <<std:: endl;
}
if (m_curl)
{
m_downloadMutex.lock();
m_cancel = true;
m_downloadMutex.unlock();
}
// Quit download thread
m_downloadQueue.push({"quit", ""});
if (m_downloadThread.joinable())
{
m_downloadThread.join();
}
curl_global_cleanup();
}
void LibraryWindow::ParseStoreData()
void LibraryWindow::DownloadThread()
{
for (;;)
{
auto cmd = m_downloadQueue.front();
m_downloadQueue.pop();
if (cmd.order == "quit")
{
curl_easy_cleanup(m_curl);
return;
}
else if (cmd.order == "dl")
{
download_file(m_curl, cmd.url, cmd.filename, cmd.finished_callback);
}
}
}
int LibraryWindow::TransferCallback(void *clientp, curl_off_t dltotal, curl_off_t dlnow,
curl_off_t ultotal, curl_off_t ulnow)
{
std::cout << "DL total: " << dltotal << ", now: " << dlnow << std::endl;
m_downloadMutex.lock();
bool cancel = m_cancel;
m_downloadMutex.unlock();
if (cancel)
{
return 1; // Annuler la requête curl
}
m_transferProgress.push(TransferProgress(dltotal, dlnow));
return 0;
}
void LibraryWindow::ParseStoreData(bool success)
{
try {
nlohmann::json j = nlohmann::json::parse(m_storeRawJson);
std::ifstream f(m_storeIndexFilename);
nlohmann::json j = nlohmann::json::parse(f);
m_store.clear();
for (const auto &obj : j)
@ -116,11 +141,28 @@ void LibraryWindow::ParseStoreData()
void LibraryWindow::Initialize()
{
// Try to download the store index file
m_curl = curl_easy_init();
if (m_curl)
{
curl_easy_setopt(m_curl, CURLOPT_WRITEFUNCTION, NULL);
curl_easy_setopt(m_curl, CURLOPT_NOPROGRESS, 0);
//progress_bar : the fonction for the progress bar
Callback<int(void *, curl_off_t, curl_off_t, curl_off_t, curl_off_t)>::func = std::bind(
&LibraryWindow::TransferCallback,
this,
std::placeholders::_1,
std::placeholders::_2,
std::placeholders::_3,
std::placeholders::_4,
std::placeholders::_5);
curl_easy_setopt(m_curl, CURLOPT_XFERINFOFUNCTION, static_cast<xfer_callback_t>(Callback<int(void *, curl_off_t, curl_off_t, curl_off_t, curl_off_t)>::callback));
}
}
static bool canValidateDialog = false;
inline void InfosPane(const char *vFilter, IGFDUserDatas vUserDatas, bool *vCantContinue) // if vCantContinue is false, the user cant validate the dialog
{
@ -131,6 +173,14 @@ inline void InfosPane(const char *vFilter, IGFDUserDatas vUserDatas, bool *vCant
*vCantContinue = canValidateDialog;
}
std::string LibraryWindow::ToLocalStoreFile(const std::string &url)
{
auto filename = StoryProject::GetFileName(m_store_url);
filename = m_libraryManager.LibraryPath() + "/store/" + filename;
std::cout << "Store file: " << filename << std::endl;
return filename;
}
void LibraryWindow::Draw()
{
@ -178,8 +228,6 @@ void LibraryWindow::Draw()
// ============================================================================
if (ImGui::BeginTabItem("Local library ##LocalTabBar", nullptr, ImGuiTabItemFlags_None))
{
if (ImGui::Button("Scan library"))
{
m_libraryManager.Scan();
@ -228,10 +276,45 @@ void LibraryWindow::Draw()
}
// ============================================================================
// LOCAL TABLE
// STORE STORY LIST
// ============================================================================
if (ImGui::BeginTabItem("Remote Store##StoreTabBar", nullptr, ImGuiTabItemFlags_None))
{
ImGui::InputTextWithHint("##store_url", "Store URL", m_store_url, IM_ARRAYSIZE(m_store_url));
ImGui::SameLine();
if (ImGui::Button("Load"))
{
m_storeIndexFilename = ToLocalStoreFile(m_store_url);
m_downloadQueue.push({
"dl",
m_store_url,
m_storeIndexFilename,
std::bind(&LibraryWindow::ParseStoreData, this, std::placeholders::_1)
});
}
static TransferProgress progressItem;
static std::string currentDownload;
static float progress = 0.0f;
if (m_transferProgress.try_pop(progressItem))
{
if (progressItem.total > 0)
{
// currentDownload = ""
progress += (progressItem.current / progressItem.total);
}
else
{
progress = 0.0;
}
}
// Typically we would use ImVec2(-1.0f,0.0f) or ImVec2(-FLT_MIN,0.0f) to use all available width,
// or ImVec2(width,0.0f) for a specified width. ImVec2(0.0f,0.0f) uses ItemWidth.
ImGui::ProgressBar(progress, ImVec2(0.0f, 0.0f));
// ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
// ImGui::Text("Current download: ");
if (ImGui::BeginTable("store_table", 3, tableFlags))
{
ImGui::TableSetupColumn("Title", ImGuiTableColumnFlags_WidthFixed);

View file

@ -1,14 +1,41 @@
#pragma once
#include <thread>
#include "window_base.h"
#include "library_manager.h"
#include "i_story_manager.h"
#include "thread_safe_queue.h"
#include <curl/curl.h>
struct StoryInf {
int age;
std::string title;
};
struct DownloadCommand {
std::string order;
std::string url;
std::string filename;
std::function<void(bool)> finished_callback;
};
struct TransferProgress {
long total;
long current;
TransferProgress() {
total = 0;
current = 0;
}
TransferProgress(int t, int c) {
total = t;
current = c;
}
};
class LibraryWindow : public WindowBase
{
public:
@ -17,13 +44,27 @@ public:
void Initialize();
virtual void Draw() override;
~LibraryWindow();
private:
IStoryManager &m_storyManager;
LibraryManager &m_libraryManager;
CURL *m_curl;
char m_store_url[1024];
std::thread m_downloadThread;
ThreadSafeQueue<DownloadCommand> m_downloadQueue;
ThreadSafeQueue<TransferProgress> m_transferProgress;
std::mutex m_downloadMutex;
bool m_cancel{false};
std::vector<StoryInf> m_store;
std::string m_storeIndexFilename;
std::string m_storeRawJson;
void ParseStoreData();
void ParseStoreData(bool success);
void DownloadThread();
int TransferCallback(void *clientp, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow);
std::string ToLocalStoreFile(const std::string &url);
};

View file

@ -1,6 +1,6 @@
#include "main_window.h"
#include <filesystem>
#include <SDL.h>
#include <SDL3/SDL.h>
#include "platform_folders.h"
#include "media_converter.h"
@ -372,6 +372,8 @@ void MainWindow::DrawMainMenuBar()
void MainWindow::Initialize()
{
LoadParams();
// GUI Init
m_gui.Initialize();
// gui.ApplyTheme();
@ -380,8 +382,9 @@ void MainWindow::Initialize()
m_emulatorWindow.Initialize();
m_nodeEditorWindow.Initialize();
m_PropertiesWindow.Initialize();
m_libraryWindow.Initialize();
LoadParams();
}
@ -979,6 +982,9 @@ void MainWindow::LoadParams()
m_libraryManager.Initialize(library_path);
}
nlohmann::json store_url = j["store_url"];
m_libraryManager.SetStoreUrl(store_url);
}
catch(std::exception &e)
{

View file

@ -63,24 +63,6 @@ struct DebugContext
};
template <typename T>
struct Callback;
template <typename Ret, typename... Params>
struct Callback<Ret(Params...)> {
template <typename... Args>
static Ret callback(Args... args) {
return func(args...);
}
static std::function<Ret(Params...)> func;
};
template <typename Ret, typename... Params>
std::function<Ret(Params...)> Callback<Ret(Params...)>::func;
class MainWindow : public IStoryManager, public IAudioEvent
{
public:

View file

@ -1,4 +1,6 @@
#include "node_editor_window.h"
#include "imgui.h"
#include "imgui_internal.h"
#include <iostream>