diff --git a/joomer-ftxui-bsz-browser.cpp b/joomer-ftxui-bsz-browser.cpp index a8291a4..7dde640 100644 --- a/joomer-ftxui-bsz-browser.cpp +++ b/joomer-ftxui-bsz-browser.cpp @@ -1,3 +1,4 @@ +#define _CRT_SECURE_NO_WARNINGS #include #include #include @@ -10,6 +11,7 @@ #include "dl_core/dl_logging.h" // Logging utilities #include // For std::this_thread (C++ standard library) #include // For timing operations (C++ standard library) +#include // For freopen std::string directory_path = "."; int selected_index = -1; // Global variable to hold the selected index @@ -53,8 +55,8 @@ public: // Called when a rendering pass starts void onStarted(dl::String pass) override { - std::cout << "Started pass " << pass.buf() << std::endl; - dl::logInfo("Started pass %s", pass.buf()); + //std::cout << "Started pass " << pass.buf() << std::endl; + // dl::logInfo("Started pass %s", pass.buf()); } // Called to update the current status of rendering @@ -66,9 +68,9 @@ public: // Called to update rendering progress (percentage, time remaining, etc) void onProgress(dl::String pass, dl::bella_sdk::Progress progress) override { - std::cout << progress.toString().buf() << std::endl; + //std::cout << progress.toString().buf() << std::endl; setString(new std::string(progress.toString().buf())); - dl::logInfo("%s [%s]", progress.toString().buf(), pass.buf()); + //dl::logInfo("%s [%s]", progress.toString().buf(), pass.buf()); } //void onImage(String pass, Image image) override @@ -79,13 +81,13 @@ public: // Called when an error occurs during rendering void onError(dl::String pass, dl::String msg) override { - dl::logError("%s [%s]", msg.buf(), pass.buf()); + //dl::logError("%s [%s]", msg.buf(), pass.buf()); } // Called when a rendering pass completes void onStopped(dl::String pass) override { - dl::logInfo("Stopped %s", pass.buf()); + // dl::logInfo("Stopped %s", pass.buf()); std::atomic_bool active_render = false; } @@ -162,9 +164,51 @@ void ReloadDirectory(ftxui::ScreenInteractive& screen, const std::filesystem::pa } } } -// Replace this line in renderImage(): -// engine.render(); +void render_thread(dl::bella_sdk::Engine& engine, MyEngineObserver& engineObserver, std::string selected_name, ftxui::ScreenInteractive& screen) { + // REDIRECT BOTH STDOUT AND STDERR TO NULL + // This stops warnings and logs from breaking the FTXUI layout + /*std::FILE* dummyOut; + std::FILE* dummyErr; + freopen_s(&dummyOut, "NUL", "w", stdout); + freopen_s(&dummyErr, "NUL", "w", stderr);*/ + + // Redirect stdout and stderr to a physical file instead of "NUL" + /*std::FILE* logFile; + if (freopen_s(&logFile, "render_log.txt", "w", stdout) != 0) { + // Optional: Handle redirection failure + } + + // Redirect stderr to the same file (or a different one) + if (freopen_s(&logFile, "render_log.txt", "a", stderr) != 0) { + // Optional: Handle redirection failure + }*/ + + dl::String belPath = dl::String(directory_path.c_str()) + "\\"; + engine.loadScene(belPath + dl::String(selected_name.c_str())); + + if (!engine.scene().read(dl::String(selected_name.c_str()))) return; + + dl::bella_sdk::Node bPass = engine.scene().beautyPass(); + + // Setup the outputImagePath node as we did in the synchronous version + dl::bella_sdk::Node pathNode = engine.scene().createNode("outputImagePath"); + pathNode["dir"] = dl::String(directory_path.c_str()); + pathNode["name"] = "render_result"; + pathNode["ext"] = ".png"; + + bPass["overridePath"] = pathNode; + bPass["timeLimit"] = 30.0f; + + engine.start(); + + // While rendering, sleep and then tell the UI to refresh + while (engine.rendering()) { + std::this_thread::sleep_for(std::chrono::milliseconds(200)); + // This is the key to seeing progress while it's "asynchronous" + screen.PostEvent(ftxui::Event::Custom); + } +} void renderSynchronous(dl::bella_sdk::Engine& engine, MyEngineObserver& engineObserver, std::string selected_name) { dl::String belPath = dl::String(directory_path.c_str()) + "\\"; @@ -193,14 +237,20 @@ void renderSynchronous(dl::bella_sdk::Engine& engine, MyEngineObserver& engineOb } } -int main(int argc, char* argv[]) { +int main(int argc, char* argv[]) { + + // 1. Initialize engine and observer locally within the logic block + dl::bella_sdk::Engine engine; + MyEngineObserver engineObserver; + engine.subscribe(&engineObserver); + // Define a variable to hold the final selection index int final_selected_index = -1; // Use -1 to indicate no selection was made std::vector entries; std::vector clean_names; // New vector for logic std::string current_path = std::filesystem::current_path().string(); - std::filesystem::path start_path = std::filesystem::current_path(); + std::filesystem::path start_path = std::filesystem::current_path(); if (argc > 1) { @@ -287,12 +337,10 @@ int main(int argc, char* argv[]) { { selected_index = selected; // Update global selected index final_selected_index = selected; // Store the final selection index - if (selected_name.substr(selected_name.length() - 3) == "bsz") { - dl::bella_sdk::Engine engine; // The renderer itself - - MyEngineObserver engineObserver; - engine.subscribe(&engineObserver); - renderSynchronous(engine, engineObserver, selected_name); + if (selected_name.substr(selected_name.length() - 3) == "bsz") { + // 2. Start the thread and DETACH it + // Note: We pass 'screen' as a reference so render_thread can call PostEvent + std::thread(render_thread, std::ref(engine), std::ref(engineObserver), selected_name, std::ref(screen)).detach(); } } else @@ -319,6 +367,9 @@ int main(int argc, char* argv[]) { // Create a renderer that defines the layout of your application ftxui::Component main_renderer = ftxui::Renderer(menu_with_event_handler, [&] { + // Get the latest progress string from the observer + std::string current_progress = engineObserver.getProgress(); + return ftxui::vbox({ // Header showing the current directory @@ -326,14 +377,21 @@ int main(int argc, char* argv[]) { ftxui::text(" Current Directory: ") | ftxui::bold, ftxui::text(current_path) | ftxui::color(ftxui::Color::Cyan), }), - ftxui::separator(), + ftxui::separator(), // The menu itself, wrapped in a frame to allow scrolling if the list is long menu_with_event_handler->Render() | ftxui::vscroll_indicator | ftxui::frame, - ftxui::filler(), // Pushes the footer to the bottom - ftxui::separator(), + // Progress Section + ftxui::separator(), + ftxui::hbox({ + ftxui::text(" Render Progress: ") | ftxui::bold, + ftxui::text(current_progress.empty() ? "Idle" : current_progress) + | ftxui::color(ftxui::Color::Green), + }), + + ftxui::separator(), ftxui::hbox({ ftxui::text("Enter folder #: "), ftxui::text(input_buffer), @@ -350,7 +408,7 @@ int main(int argc, char* argv[]) { screen.Loop(main_renderer); // This will print to your terminal AFTER you press 'q' to quit - std::cout << "Final Path on Exit: " << current_path << std::endl; + /* std::cout << "Final Path on Exit: " << current_path << std::endl; // ---------------------------------------------------- // --- OUTPUT AFTER THE LOOP HAS CLEANLY EXITED --- // ---------------------------------------------------- @@ -360,5 +418,5 @@ int main(int argc, char* argv[]) { } else { std::cout << "Selection cancelled or no valid entry selected." << std::endl; } - + */ } \ No newline at end of file