raycaster/storyboard/ui.cpp
2025-11-12 11:48:24 -05:00

114 lines
2.8 KiB
C++

#include "storyboard/ui.hpp"
#include "components.hpp"
#include "animation.hpp"
#include "sound.hpp"
#include "config.hpp"
#include <chrono>
#include <iostream>
#include <locale>
#include <sstream>
namespace storyboard {
UI::UI(const std::string& story_name) :
$view_texture({SCREEN_WIDTH, SCREEN_HEIGHT}),
$view_sprite($view_texture.getTexture()),
$audio(sound::get_sound_pair("ambient_1").sound)
{
$view_sprite.setPosition({0, 0});
auto config = settings::get("stories");
$story = components::convert<components::Storyboard>(config[story_name]);
}
void UI::init() {
$ui.position(0,0, SCREEN_WIDTH, SCREEN_HEIGHT);
$ui.set<guecs::Background>($ui.MAIN, {$ui.$parser, guecs::THEME.TRANSPARENT});
auto& background = $ui.get<guecs::Background>($ui.MAIN);
background.set_sprite($story.image, true);
for(auto& line : $story.layout) {
$layout.append(line);
}
$ui.layout($layout);
sound::play($story.audio, true);
}
void UI::render(sf::RenderWindow &window) {
track_audio();
$view_texture.clear();
$camera.render($view_texture);
$ui.render($view_texture);
$ui.debug_layout($view_texture);
$view_texture.display();
window.draw($view_sprite);
}
sf::Time parse_time_code(const std::string& time) {
std::chrono::seconds out{};
std::istringstream is{time};
is >> std::chrono::parse("%M:%S", out);
dbc::check(!is.fail(), fmt::format("Time parse failed: {}", time));
return sf::Time(out);
}
void UI::track_audio() {
auto& beat = $story.beats[cur_beat % $story.beats.size()];
auto track_head = $audio->getPlayingOffset();
auto next_beat = parse_time_code(beat[0]);
if(track_head >= next_beat) {
if($moving) return;
$moving = true; // prevent motion until next tick
// get the original zoom target as from
auto& cell = $ui.cell_for($zoom_target);
$camera.position(cell.mid_x, cell.mid_y);
$zoom_target = beat[1];
$camera.style(beat[2]);
// get the new target from the cell names
zoom($zoom_target);
$camera.play();
cur_beat++;
} else {
$moving = false;
}
}
bool UI::mouse(float x, float y, guecs::Modifiers mods) {
auto& cell = $ui.cell_for($zoom_target);
$zoom_target = *$ui.$parser.hit(x, y);
if($zoom_target == "a") {
reset();
} else {
$camera.position(cell.mid_x, cell.mid_y);
zoom($zoom_target);
$camera.play();
}
return $ui.mouse(x, y, mods);
}
void UI::zoom(const std::string &cell_name) {
auto& cell = $ui.cell_for(cell_name);
$camera.resize(float(cell.w), float(cell.h));
$camera.move(float(cell.mid_x), float(cell.mid_y));
}
void UI::reset() {
sf::FloatRect where{{0,0},{SCREEN_WIDTH, SCREEN_HEIGHT}};
sf::View view{where};
$view_texture.setView(view);
}
}