From 459ff06eee40dfa564fd853696d21a7271295190 Mon Sep 17 00:00:00 2001 From: "Zed A. Shaw" Date: Thu, 30 Apr 2026 22:55:11 -0400 Subject: [PATCH] Can now control the slides from the control window...'cause it controls the slides. --- assets/layouts.json | 3 +++ sample/about-bezos.md | 62 +++++++++++++++++++++++++++++++++++-------- src/control_ui.cpp | 55 +++++++++++++++++++++++++++++--------- src/control_ui.hpp | 14 +++++++--- src/main.cpp | 12 ++++----- src/slides_ui.cpp | 62 ++++++++++++++++++++++++++++++------------- src/slides_ui.hpp | 14 +++++++--- 7 files changed, 168 insertions(+), 54 deletions(-) diff --git a/assets/layouts.json b/assets/layouts.json index 6d9e94b..a29f1b0 100644 --- a/assets/layouts.json +++ b/assets/layouts.json @@ -29,6 +29,9 @@ "[_|_|_|_|_]", "[_|_|_|_|_]" ], + "no_title": [ + "[*%(300,600)content]" + ], "centered": [ "[=*%(300,400)title|_|_|_|_]", "[_|_|_]", diff --git a/sample/about-bezos.md b/sample/about-bezos.md index 2017ada..1a12115 100644 --- a/sample/about-bezos.md +++ b/sample/about-bezos.md @@ -1,21 +1,44 @@ { "title": "How to use Bezos", - "description": "A short presentation on Bezos.", + "description": "The PowerPoint killer for PowerPoint haters like Jeff.", "font_file": "assets/bold.otf", "layouts": "assets/layouts.json" } === -# Bezos Loves Slides -* My PowerPoint Killer +{ + "font_size": 120, + "font_centered": false, + "layout": "no_title" +} +Jeff +Bezos +Loves +PowerPoint +--- +# That Fateful Day +* The Deck From Hell +* Jeff Bans PowerPoint +* What Was That Deck? +--- +{ + "font_size": 120, + "font_centered": false +} +Can We Blame Him? +--- +# I Hate PowerPoint Too +* So I made an alternative. * Markdown Format -* Images, Shaders, soon Video? * Hot Reload +* Images, and Shaders. +* Not Much Else --- # Bezos Slide Format * Just markdown separated by --- * Each slide can - have a json header + have a json metadata + header for config --- # Supported Markdown * Simple lists with * @@ -25,7 +48,7 @@ Bare content like this --- # Deck Header -* Right after === +* Right after --- * Use {} to configure * "title" * "description" @@ -33,7 +56,6 @@ Bare content like this * "bg_image": "filepath.jpg" --- { "bg_color": [55, 20, 10, 255] } - # Slide Color * { "bg_color": [r,g,b,a] } * Same as deck header @@ -58,6 +80,7 @@ Bare content like this "bg_color": [10, 10, 25, 255], "font_color": [255, 146, 0, 255], "font_size": 80, + "title_size": 120, "font_padding": 20 } # Font Config @@ -67,11 +90,11 @@ Bare content like this * "X_padding": int --- { - "font_size": 120, - "font_centered": true, - "layout": "centered" + "font_size": 180, + "layout": "no_title" } -One Word +Flexible +Layouts --- # Images !(assets/sample_bg.jpg) @@ -97,3 +120,20 @@ One Word * It watches the file and reloads when it changes --- +# Current Status +* Mostly works for me +* Written in C++ using + my game UI library +* Quick hack POC +* Might Rewrite in Go for + max portability +--- +{ +"font_size": 240, +"layout": "no_title", + "bg_color": [10, 10, 25, 255], + "font_color": [255, 146, 0, 255] +} +Demo +Time +--- diff --git a/src/control_ui.cpp b/src/control_ui.cpp index 61b3bea..4f08622 100644 --- a/src/control_ui.cpp +++ b/src/control_ui.cpp @@ -12,8 +12,10 @@ #include "constants.hpp" #include "control_ui.hpp" -ControlUI::ControlUI(sf::RenderWindow& presenter) : + +ControlUI::ControlUI(sf::RenderWindow& presenter, sf::RenderWindow& controller) : $presenter(presenter), + $controller(controller), $window_size($presenter.getSize()) { $gui.position(0, 0, CONTROL_WIDTH, CONTROL_HEIGHT); @@ -23,29 +25,46 @@ ControlUI::ControlUI(sf::RenderWindow& presenter) : ); } +void ControlUI::config_views(guecs::Entity current, guecs::Entity next) { + // BUG jank ass bullshit, fix this in lel-guecs + auto& cur_cell = $gui.cell_for(current); + $cur_view = std::make_shared($presenter.getSize()); + $cur_sprite = std::make_shared($cur_view->getTexture()); + $cur_sprite->setPosition({float(cur_cell.x), float(cur_cell.y)}); + $cur_sprite->setScale({0.3f, 0.3f}); + + auto& next_cell = $gui.cell_for(next); + $next_view = std::make_shared($presenter.getSize()); + $next_sprite = std::make_shared($next_view->getTexture()); + $next_sprite->setPosition({float(next_cell.x), float(next_cell.y)}); + $next_sprite->setScale({0.3f, 0.3f}); +} + void ControlUI::init() { auto status_id = $gui.entity("status"); $gui.set(status_id, {L""}); auto docs_id = $gui.entity("docs"); $gui.set(docs_id, {L"F: fullscreen\nA: win left\nD: win right\nQ: quit"}); + $gui.init(); auto current = $gui.entity("current"); - $gui.set(current, {}); - $gui.set(current, {L"Current Slide"}); - auto next = $gui.entity("next"); - $gui.set(next, {}); - $gui.set(next, {L"Next Slide"}); - $gui.init(); + config_views(current, next); // warning! must come after init so the thing is there $status = $gui.get_if(status_id); dbc::check($status != nullptr, "failed to setup the status text"); } -void ControlUI::render(sf::RenderWindow& window) { +inline void render_slide(sf::RenderTexture& view, Slide& slide) { + view.clear(); + slide.render(view); + view.display(); +} + +void ControlUI::render(sf::RenderWindow& window, SlideDeck& deck) { dbc::check($status != nullptr, "called render before init?"); auto pos = $presenter.getPosition(); @@ -53,16 +72,24 @@ void ControlUI::render(sf::RenderWindow& window) { $status->update(fmt::format(L"pos={},{}\nsize={},{}", pos.x, pos.y, size.x, size.y)); - window.clear(); + window.clear(); $gui.render(window); + + render_slide(*$cur_view, deck.current_slide()); + window.draw(*$cur_sprite); + + /* + render_slide(*$next_view, deck.preview_slide()); + window.draw(*$next_sprite); + */ } -void ControlUI::handle_events(sf::RenderWindow& controller, const sf::Event& event) { +void ControlUI::handle_events(std::shared_ptr slides, const sf::Event& event) { dbc::check($status != nullptr, "handle_events called before init?!"); if(event.is()) { - controller.close(); + $controller.close(); return; } @@ -80,19 +107,21 @@ void ControlUI::handle_events(sf::RenderWindow& controller, const sf::Event& eve $presenter.setPosition(pos); } break; case KEY::Q: - controller.close(); + $controller.close(); break; case KEY::F: if($full_screen) { $presenter.setSize({$window_size.x/2, $window_size.y/2}); + $presenter.setMouseCursorVisible(true); } else { $presenter.setSize($window_size); + $presenter.setMouseCursorVisible(false); } $full_screen = !$full_screen; break; default: - break; + slides->handle_events($controller, event); } } } diff --git a/src/control_ui.hpp b/src/control_ui.hpp index abed15b..1f23267 100644 --- a/src/control_ui.hpp +++ b/src/control_ui.hpp @@ -9,10 +9,18 @@ struct ControlUI { guecs::UI $gui; guecs::Text* $status; sf::RenderWindow& $presenter; + sf::RenderWindow& $controller; sf::Vector2u $window_size; - ControlUI(sf::RenderWindow& presenter); + std::shared_ptr $cur_view = nullptr; + std::shared_ptr $cur_sprite = nullptr; + + std::shared_ptr $next_view = nullptr; + std::shared_ptr $next_sprite = nullptr; + + ControlUI(sf::RenderWindow& presenter, sf::RenderWindow& controller); void init(); - void render(sf::RenderWindow& window); - void handle_events(sf::RenderWindow& controller, const sf::Event& event); + void render(sf::RenderWindow& window, SlideDeck& deck); + void handle_events(std::shared_ptr slides, const sf::Event& event); + void config_views(guecs::Entity current, guecs::Entity next); }; diff --git a/src/main.cpp b/src/main.cpp index a02768d..9bd0ea9 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -15,14 +15,14 @@ using namespace std::chrono_literals; std::shared_ptr load_slides(const std::string& input_md, std::shared_ptr backend) { try { - auto data = parse_slides(input_md, [&](nlohmann::json& config) { + auto deck = parse_slides(input_md, [&](nlohmann::json& config) { backend->set_font(config["font_file"]); guecs::init(backend.get()); }); fmt::println("FONT FILE: {}", backend->$font_file); - auto slides = std::make_shared(data, sf::Vector2u{WINDOW_WIDTH, WINDOW_HEIGHT}); + auto slides = std::make_shared(deck, sf::Vector2u{WINDOW_WIDTH, WINDOW_HEIGHT}); slides->init(); return slides; @@ -85,7 +85,7 @@ int main(int argc, char *argv[]) { return 1; } - ControlUI control_ui(presenter); + ControlUI control_ui(presenter, controller); control_ui.init(); dbc::check(control_ui.$status != nullptr, "bad ptr"); @@ -99,18 +99,18 @@ int main(int argc, char *argv[]) { } while (const auto event = controller.pollEvent()) { - if(event) control_ui.handle_events(controller, *event); + if(event) control_ui.handle_events(slides, *event); } slides->render(presenter); - control_ui.render(controller); + control_ui.render(controller, *slides->$deck); presenter.display(); controller.display(); if(slides_reloader.changed() || layout_reloader.changed()) { // save the current slide - auto current_slide = slides->$current; + auto current_slide = slides->$deck->current; // load the new one auto new_slides = load_slides(argv[1], backend); diff --git a/src/slides_ui.cpp b/src/slides_ui.cpp index 49e8e50..a8fd29c 100644 --- a/src/slides_ui.cpp +++ b/src/slides_ui.cpp @@ -34,15 +34,19 @@ void Slide::init(lel::Cell& cell, const std::string& layout) { $gui.position(cell.x, cell.y, cell.w, cell.h); $gui.layout(layout); - auto title = $gui.entity("title"); - $gui.set(title, $title_font); + if($gui.contains("title")) { + auto title = $gui.entity("title"); + $gui.set(title, $title_font); + } auto content = $gui.entity("content"); $gui.set(content, $content_font); if($config.contains("image")) { std::string image_name = $config["image"]; + auto at_cell = $config.contains("image_cell") ? $gui.entity($config["image_cell"]) : content; + bool stretched = $config.contains("image_stretch") ? $config["image_stretch"].get() : true; $gui.set(at_cell, {image_name, guecs::THEME.PADDING, stretched}); } @@ -74,6 +78,35 @@ void Slide::render(sf::RenderTarget& view) { // $gui.debug_layout(view); } +void SlideDeck::set_slide(size_t index) { + current = index < slides.size() ? index : 0; +} + +bool SlideDeck::at_end() { + return current >= slides.size() - 1; +} + +Slide& SlideDeck::current_slide() { + return slides.at(current); +} + +Slide& SlideDeck::preview_slide() { + return slides.at(current + 1); +} + +void SlideDeck::next_slide() { + if(current < slides.size() - 1) { + current++; + } +} + +void SlideDeck::prev_slide() { + if(current > 0) { + current--; + } +} + + SlidesUI::SlidesUI(shared_ptr deck, sf::Vector2u size) : $view_texture{size}, $view_sprite($view_texture.getTexture()) @@ -81,7 +114,6 @@ SlidesUI::SlidesUI(shared_ptr deck, sf::Vector2u size) : dbc::check(deck != nullptr, "deck is null"); dbc::check(deck->slides.size() > 0, "slide deck is empy"); $deck = deck; - $current = 0; configure_layouts(); } @@ -113,31 +145,25 @@ void SlidesUI::init() { $gui.init(); } -Slide& SlidesUI::current() { - return $deck->slides.at($current); -} - void SlidesUI::next_slide() { - if($current < $deck->slides.size() - 1) { - $current++; - show_slide(); - } + $deck->next_slide(); + show_slide(); } void SlidesUI::prev_slide() { - if($current > 0) { - $current--; - show_slide(); - } + $deck->prev_slide(); + show_slide(); } void SlidesUI::set_slide(size_t index) { - $current = index < $deck->slides.size() ? index : 0; + $deck->set_slide(index); show_slide(); } void SlidesUI::show_slide() { - auto& slide = current(); + // THIS NEEDS TO BE DONE FOR ALL SLIDES OR CONTROL CAN'T SHOW NEXT SLIDE + // MOVE TO DECK + auto& slide = $deck->current_slide(); // kind of have to set the background for the whole UI using the slide config auto& bg = $gui.get($gui.MAIN); @@ -185,7 +211,7 @@ void SlidesUI::show_slide() { void SlidesUI::render(sf::RenderTarget& window) { $gui.render($view_texture); - auto& slide = current(); + auto& slide = $deck->current_slide(); slide.render($view_texture); $view_texture.display(); diff --git a/src/slides_ui.hpp b/src/slides_ui.hpp index 270b150..712ee4d 100644 --- a/src/slides_ui.hpp +++ b/src/slides_ui.hpp @@ -32,6 +32,14 @@ using SlideSet = std::vector; struct SlideDeck { nlohmann::json config; SlideSet slides; + size_t current = 0; + + bool at_end(); + Slide& current_slide(); + Slide& preview_slide(); + void next_slide(); + void prev_slide(); + void set_slide(size_t index); }; struct SlidesUI { @@ -41,11 +49,11 @@ struct SlidesUI { sf::RenderTexture $view_texture; sf::Sprite $view_sprite; sf::Clock $clock; - size_t $current = 0; - SlidesUI(std::shared_ptr deck, sf::Vector2u size); + SlidesUI(std::shared_ptr deck, sf::Vector2u size); void init(); - Slide& current(); + + Slide& current_slide(); void next_slide(); void prev_slide();