Can now control the slides from the control window...'cause it controls the slides.

master
Zed A. Shaw 4 weeks ago
parent 1fb3dea874
commit 459ff06eee
  1. 3
      assets/layouts.json
  2. 62
      sample/about-bezos.md
  3. 55
      src/control_ui.cpp
  4. 14
      src/control_ui.hpp
  5. 12
      src/main.cpp
  6. 62
      src/slides_ui.cpp
  7. 14
      src/slides_ui.hpp

@ -29,6 +29,9 @@
"[_|_|_|_|_]", "[_|_|_|_|_]",
"[_|_|_|_|_]" "[_|_|_|_|_]"
], ],
"no_title": [
"[*%(300,600)content]"
],
"centered": [ "centered": [
"[=*%(300,400)title|_|_|_|_]", "[=*%(300,400)title|_|_|_|_]",
"[_|_|_]", "[_|_|_]",

@ -1,21 +1,44 @@
{ {
"title": "How to use Bezos", "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", "font_file": "assets/bold.otf",
"layouts": "assets/layouts.json" "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 * Markdown Format
* Images, Shaders, soon Video?
* Hot Reload * Hot Reload
* Images, and Shaders.
* Not Much Else
--- ---
# Bezos Slide Format # Bezos Slide Format
* Just markdown * Just markdown
separated by --- separated by ---
* Each slide can * Each slide can
have a json header have a json metadata
header for config
--- ---
# Supported Markdown # Supported Markdown
* Simple lists with * * Simple lists with *
@ -25,7 +48,7 @@
Bare content like this Bare content like this
--- ---
# Deck Header # Deck Header
* Right after === * Right after ---
* Use {} to configure * Use {} to configure
* "title" * "title"
* "description" * "description"
@ -33,7 +56,6 @@ Bare content like this
* "bg_image": "filepath.jpg" * "bg_image": "filepath.jpg"
--- ---
{ "bg_color": [55, 20, 10, 255] } { "bg_color": [55, 20, 10, 255] }
# Slide Color # Slide Color
* { "bg_color": [r,g,b,a] } * { "bg_color": [r,g,b,a] }
* Same as deck header * Same as deck header
@ -58,6 +80,7 @@ Bare content like this
"bg_color": [10, 10, 25, 255], "bg_color": [10, 10, 25, 255],
"font_color": [255, 146, 0, 255], "font_color": [255, 146, 0, 255],
"font_size": 80, "font_size": 80,
"title_size": 120,
"font_padding": 20 "font_padding": 20
} }
# Font Config # Font Config
@ -67,11 +90,11 @@ Bare content like this
* "X_padding": int * "X_padding": int
--- ---
{ {
"font_size": 120, "font_size": 180,
"font_centered": true, "layout": "no_title"
"layout": "centered"
} }
One Word Flexible
Layouts
--- ---
# Images # Images
!(assets/sample_bg.jpg) !(assets/sample_bg.jpg)
@ -97,3 +120,20 @@ One Word
* It watches the file and * It watches the file and
reloads when it changes 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
---

@ -12,8 +12,10 @@
#include "constants.hpp" #include "constants.hpp"
#include "control_ui.hpp" #include "control_ui.hpp"
ControlUI::ControlUI(sf::RenderWindow& presenter) :
ControlUI::ControlUI(sf::RenderWindow& presenter, sf::RenderWindow& controller) :
$presenter(presenter), $presenter(presenter),
$controller(controller),
$window_size($presenter.getSize()) $window_size($presenter.getSize())
{ {
$gui.position(0, 0, CONTROL_WIDTH, CONTROL_HEIGHT); $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<sf::RenderTexture>($presenter.getSize());
$cur_sprite = std::make_shared<sf::Sprite>($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<sf::RenderTexture>($presenter.getSize());
$next_sprite = std::make_shared<sf::Sprite>($next_view->getTexture());
$next_sprite->setPosition({float(next_cell.x), float(next_cell.y)});
$next_sprite->setScale({0.3f, 0.3f});
}
void ControlUI::init() { void ControlUI::init() {
auto status_id = $gui.entity("status"); auto status_id = $gui.entity("status");
$gui.set<guecs::Text>(status_id, {L""}); $gui.set<guecs::Text>(status_id, {L""});
auto docs_id = $gui.entity("docs"); auto docs_id = $gui.entity("docs");
$gui.set<guecs::Text>(docs_id, {L"F: fullscreen\nA: win left\nD: win right\nQ: quit"}); $gui.set<guecs::Text>(docs_id, {L"F: fullscreen\nA: win left\nD: win right\nQ: quit"});
$gui.init();
auto current = $gui.entity("current"); auto current = $gui.entity("current");
$gui.set<guecs::Rectangle>(current, {});
$gui.set<guecs::Text>(current, {L"Current Slide"});
auto next = $gui.entity("next"); auto next = $gui.entity("next");
$gui.set<guecs::Rectangle>(next, {});
$gui.set<guecs::Text>(next, {L"Next Slide"});
$gui.init(); config_views(current, next);
// warning! must come after init so the thing is there // warning! must come after init so the thing is there
$status = $gui.get_if<guecs::Text>(status_id); $status = $gui.get_if<guecs::Text>(status_id);
dbc::check($status != nullptr, "failed to setup the status text"); 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?"); dbc::check($status != nullptr, "called render before init?");
auto pos = $presenter.getPosition(); auto pos = $presenter.getPosition();
@ -53,16 +72,24 @@ void ControlUI::render(sf::RenderWindow& window) {
$status->update(fmt::format(L"pos={},{}\nsize={},{}", $status->update(fmt::format(L"pos={},{}\nsize={},{}",
pos.x, pos.y, size.x, size.y)); pos.x, pos.y, size.x, size.y));
window.clear();
window.clear();
$gui.render(window); $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<SlidesUI> slides, const sf::Event& event) {
dbc::check($status != nullptr, "handle_events called before init?!"); dbc::check($status != nullptr, "handle_events called before init?!");
if(event.is<sf::Event::Closed>()) { if(event.is<sf::Event::Closed>()) {
controller.close(); $controller.close();
return; return;
} }
@ -80,19 +107,21 @@ void ControlUI::handle_events(sf::RenderWindow& controller, const sf::Event& eve
$presenter.setPosition(pos); $presenter.setPosition(pos);
} break; } break;
case KEY::Q: case KEY::Q:
controller.close(); $controller.close();
break; break;
case KEY::F: case KEY::F:
if($full_screen) { if($full_screen) {
$presenter.setSize({$window_size.x/2, $window_size.y/2}); $presenter.setSize({$window_size.x/2, $window_size.y/2});
$presenter.setMouseCursorVisible(true);
} else { } else {
$presenter.setSize($window_size); $presenter.setSize($window_size);
$presenter.setMouseCursorVisible(false);
} }
$full_screen = !$full_screen; $full_screen = !$full_screen;
break; break;
default: default:
break; slides->handle_events($controller, event);
} }
} }
} }

@ -9,10 +9,18 @@ struct ControlUI {
guecs::UI $gui; guecs::UI $gui;
guecs::Text* $status; guecs::Text* $status;
sf::RenderWindow& $presenter; sf::RenderWindow& $presenter;
sf::RenderWindow& $controller;
sf::Vector2u $window_size; sf::Vector2u $window_size;
ControlUI(sf::RenderWindow& presenter); std::shared_ptr<sf::RenderTexture> $cur_view = nullptr;
std::shared_ptr<sf::Sprite> $cur_sprite = nullptr;
std::shared_ptr<sf::RenderTexture> $next_view = nullptr;
std::shared_ptr<sf::Sprite> $next_sprite = nullptr;
ControlUI(sf::RenderWindow& presenter, sf::RenderWindow& controller);
void init(); void init();
void render(sf::RenderWindow& window); void render(sf::RenderWindow& window, SlideDeck& deck);
void handle_events(sf::RenderWindow& controller, const sf::Event& event); void handle_events(std::shared_ptr<SlidesUI> slides, const sf::Event& event);
void config_views(guecs::Entity current, guecs::Entity next);
}; };

@ -15,14 +15,14 @@ using namespace std::chrono_literals;
std::shared_ptr<SlidesUI> load_slides(const std::string& input_md, std::shared_ptr<gui::Backend> backend) { std::shared_ptr<SlidesUI> load_slides(const std::string& input_md, std::shared_ptr<gui::Backend> backend) {
try { 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"]); backend->set_font(config["font_file"]);
guecs::init(backend.get()); guecs::init(backend.get());
}); });
fmt::println("FONT FILE: {}", backend->$font_file); fmt::println("FONT FILE: {}", backend->$font_file);
auto slides = std::make_shared<SlidesUI>(data, sf::Vector2u{WINDOW_WIDTH, WINDOW_HEIGHT}); auto slides = std::make_shared<SlidesUI>(deck, sf::Vector2u{WINDOW_WIDTH, WINDOW_HEIGHT});
slides->init(); slides->init();
return slides; return slides;
@ -85,7 +85,7 @@ int main(int argc, char *argv[]) {
return 1; return 1;
} }
ControlUI control_ui(presenter); ControlUI control_ui(presenter, controller);
control_ui.init(); control_ui.init();
dbc::check(control_ui.$status != nullptr, "bad ptr"); dbc::check(control_ui.$status != nullptr, "bad ptr");
@ -99,18 +99,18 @@ int main(int argc, char *argv[]) {
} }
while (const auto event = controller.pollEvent()) { 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); slides->render(presenter);
control_ui.render(controller); control_ui.render(controller, *slides->$deck);
presenter.display(); presenter.display();
controller.display(); controller.display();
if(slides_reloader.changed() || layout_reloader.changed()) { if(slides_reloader.changed() || layout_reloader.changed()) {
// save the current slide // save the current slide
auto current_slide = slides->$current; auto current_slide = slides->$deck->current;
// load the new one // load the new one
auto new_slides = load_slides(argv[1], backend); auto new_slides = load_slides(argv[1], backend);

@ -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.position(cell.x, cell.y, cell.w, cell.h);
$gui.layout(layout); $gui.layout(layout);
auto title = $gui.entity("title"); if($gui.contains("title")) {
$gui.set<guecs::Text>(title, $title_font); auto title = $gui.entity("title");
$gui.set<guecs::Text>(title, $title_font);
}
auto content = $gui.entity("content"); auto content = $gui.entity("content");
$gui.set<guecs::Text>(content, $content_font); $gui.set<guecs::Text>(content, $content_font);
if($config.contains("image")) { if($config.contains("image")) {
std::string image_name = $config["image"]; std::string image_name = $config["image"];
auto at_cell = $config.contains("image_cell") ? $gui.entity($config["image_cell"]) : content; auto at_cell = $config.contains("image_cell") ? $gui.entity($config["image_cell"]) : content;
bool stretched = $config.contains("image_stretch") ? $config["image_stretch"].get<bool>() : true; bool stretched = $config.contains("image_stretch") ? $config["image_stretch"].get<bool>() : true;
$gui.set<guecs::Sprite>(at_cell, {image_name, guecs::THEME.PADDING, stretched}); $gui.set<guecs::Sprite>(at_cell, {image_name, guecs::THEME.PADDING, stretched});
} }
@ -74,6 +78,35 @@ void Slide::render(sf::RenderTarget& view) {
// $gui.debug_layout(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<SlideDeck> deck, sf::Vector2u size) : SlidesUI::SlidesUI(shared_ptr<SlideDeck> deck, sf::Vector2u size) :
$view_texture{size}, $view_texture{size},
$view_sprite($view_texture.getTexture()) $view_sprite($view_texture.getTexture())
@ -81,7 +114,6 @@ SlidesUI::SlidesUI(shared_ptr<SlideDeck> deck, sf::Vector2u size) :
dbc::check(deck != nullptr, "deck is null"); dbc::check(deck != nullptr, "deck is null");
dbc::check(deck->slides.size() > 0, "slide deck is empy"); dbc::check(deck->slides.size() > 0, "slide deck is empy");
$deck = deck; $deck = deck;
$current = 0;
configure_layouts(); configure_layouts();
} }
@ -113,31 +145,25 @@ void SlidesUI::init() {
$gui.init(); $gui.init();
} }
Slide& SlidesUI::current() {
return $deck->slides.at($current);
}
void SlidesUI::next_slide() { void SlidesUI::next_slide() {
if($current < $deck->slides.size() - 1) { $deck->next_slide();
$current++; show_slide();
show_slide();
}
} }
void SlidesUI::prev_slide() { void SlidesUI::prev_slide() {
if($current > 0) { $deck->prev_slide();
$current--; show_slide();
show_slide();
}
} }
void SlidesUI::set_slide(size_t index) { void SlidesUI::set_slide(size_t index) {
$current = index < $deck->slides.size() ? index : 0; $deck->set_slide(index);
show_slide(); show_slide();
} }
void SlidesUI::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 // kind of have to set the background for the whole UI using the slide config
auto& bg = $gui.get<guecs::Background>($gui.MAIN); auto& bg = $gui.get<guecs::Background>($gui.MAIN);
@ -185,7 +211,7 @@ void SlidesUI::show_slide() {
void SlidesUI::render(sf::RenderTarget& window) { void SlidesUI::render(sf::RenderTarget& window) {
$gui.render($view_texture); $gui.render($view_texture);
auto& slide = current(); auto& slide = $deck->current_slide();
slide.render($view_texture); slide.render($view_texture);
$view_texture.display(); $view_texture.display();

@ -32,6 +32,14 @@ using SlideSet = std::vector<Slide>;
struct SlideDeck { struct SlideDeck {
nlohmann::json config; nlohmann::json config;
SlideSet slides; 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 { struct SlidesUI {
@ -41,11 +49,11 @@ struct SlidesUI {
sf::RenderTexture $view_texture; sf::RenderTexture $view_texture;
sf::Sprite $view_sprite; sf::Sprite $view_sprite;
sf::Clock $clock; sf::Clock $clock;
size_t $current = 0;
SlidesUI(std::shared_ptr<SlideDeck> deck, sf::Vector2u size); SlidesUI(std::shared_ptr<SlideDeck> deck, sf::Vector2u size);
void init(); void init();
Slide& current();
Slide& current_slide();
void next_slide(); void next_slide();
void prev_slide(); void prev_slide();

Loading…
Cancel
Save