132 lines
4.6 KiB
C++
132 lines
4.6 KiB
C++
#pragma once
|
|
#include <Common.h>
|
|
#include <Environment.h>
|
|
#include "Graphics.h"
|
|
|
|
namespace ADVect {
|
|
template <typename T>
|
|
struct Varying {
|
|
u64 begin = 0, duration = 0;
|
|
std::function<T(f32)> interp;
|
|
bool done = true;
|
|
|
|
T get(u64 current_time) const {
|
|
if (done)
|
|
return interp(1.f);
|
|
else
|
|
return interp((current_time - begin) / static_cast<f32>(duration));
|
|
}
|
|
void kickoff(u64 current_time, u64 dur, const std::function<T(f32)>& f = [](f32 x) { return static_cast<T>(x); }) {
|
|
begin = current_time;
|
|
done = false;
|
|
duration = dur;
|
|
interp = f;
|
|
}
|
|
bool check(u64 current_time) {
|
|
if (done) return true;
|
|
else if (current_time >= begin + duration) {
|
|
done = true;
|
|
return true;
|
|
}
|
|
else return false;
|
|
}
|
|
};
|
|
|
|
template <typename T, bool UsePointer, bool IsNamed, bool IsVisual, bool IsVisualFill, bool HasTransition>
|
|
struct Track {
|
|
std::conditional_t<UsePointer, T*, T> current{};
|
|
[[no_unique_address]] std::conditional_t<IsNamed, std::string, std::monostate> name{};
|
|
|
|
// Visual
|
|
[[no_unique_address]] std::conditional_t<IsVisual, i32, std::monostate> pos_x{}, pos_y{};
|
|
[[no_unique_address]] std::conditional_t<IsVisual, u32, std::monostate> w{}, h{};
|
|
[[no_unique_address]] std::conditional_t<IsVisual, f32, std::monostate> opacity{};
|
|
// TODO other transforms
|
|
|
|
// Fill
|
|
static_assert(IsVisual || !IsVisualFill, "Track cannot have fill unless visual");
|
|
[[no_unique_address]] std::conditional_t<IsVisualFill, u32, std::monostate> fill{};
|
|
|
|
// Transition, with assumption that we need to access the original when transition is underway
|
|
[[no_unique_address]] std::conditional_t<HasTransition, std::conditional_t<UsePointer, T*, T>, std::monostate> next{};
|
|
[[no_unique_address]] std::conditional_t<HasTransition, Varying<f32>, std::monostate> transition{};
|
|
void check(u64 current_time) requires HasTransition {
|
|
if constexpr (UsePointer) {
|
|
if (next != nullptr && transition.check(current_time)) {
|
|
current = next;
|
|
next = nullptr;
|
|
}
|
|
}
|
|
else {
|
|
if (transition.check(current_time))
|
|
current = next;
|
|
}
|
|
}
|
|
void change(u64 current_time, const std::conditional_t<UsePointer, T*, T> n, u64 dur, const std::function<f32(f32)>& f = [](f32 x) { return x; }) requires HasTransition {
|
|
if constexpr (UsePointer) {
|
|
if (current == nullptr)
|
|
current = n;
|
|
else if (n == nullptr) current = n;
|
|
else {
|
|
next = n;
|
|
transition.kickoff(current_time, dur, f);
|
|
}
|
|
}
|
|
else {
|
|
next = n;
|
|
transition.kickoff(current_time, dur, f);
|
|
}
|
|
}
|
|
};
|
|
|
|
template<typename T, bool UsePointer>
|
|
using VisualTrack = Track<T, UsePointer, false, true, false, false>;
|
|
template<typename T, bool UsePointer>
|
|
using VisualTransitionTrack = Track<T, UsePointer, false, true, false, true>;
|
|
|
|
template<typename T, bool UsePointer>
|
|
using FillVisualTrack = Track<T, UsePointer, false, true, true, false>;
|
|
template<typename T, bool UsePointer>
|
|
using FillVisualTransitionTrack = Track<T, UsePointer, false, true, true, true>;
|
|
|
|
/* TODO impl
|
|
struct AudioTrack {};
|
|
*/
|
|
|
|
using TextTrack = FillVisualTrack<NVL::String, false>;
|
|
using MarkupTextTrack = FillVisualTrack<NVL::Environment::MarkupString, false>;
|
|
using MarkupTextTransitionTrack = FillVisualTransitionTrack<NVL::Environment::MarkupString, false>;
|
|
using ImageTrack = VisualTrack<ADVect::Graphics::ImageTexture, true>;
|
|
using ImageTransitionTrack = VisualTransitionTrack<ADVect::Graphics::ImageTexture, true>;
|
|
/* TODO VideoTrack */
|
|
|
|
void draw_typewriter(u64 current_time, const MarkupTextTransitionTrack& t) {
|
|
if (t.transition.done)
|
|
ADVect::Graphics::RenderSubstringMarkupBox(t.current, t.pos_x, t.pos_y, t.w, t.fill);
|
|
else
|
|
ADVect::Graphics::RenderSubstringMarkupBox(t.next, t.pos_x, t.pos_y, t.w, t.fill, t.transition.get(current_time));
|
|
}
|
|
|
|
void draw_image_transition_fade(u64 current_time, const ImageTransitionTrack& t) {
|
|
if (t.current != nullptr) {
|
|
if (t.next != nullptr) {
|
|
ADVect::Graphics::DrawTextureImage(*t.current, t.pos_x, t.pos_y);
|
|
ADVect::Graphics::DrawTextureImageAlpha(*t.next, t.pos_x, t.pos_y, t.transition.get(current_time));
|
|
}
|
|
else {
|
|
ADVect::Graphics::DrawTextureImage(*t.current, t.pos_x, t.pos_y);
|
|
}
|
|
}
|
|
}
|
|
void draw_image_transition_crossfade(u64 current_time, const ImageTransitionTrack& t) {
|
|
if (t.current != nullptr) {
|
|
if (t.next != nullptr) {
|
|
ADVect::Graphics::DrawTextureImageAlpha(*t.current, t.pos_x, t.pos_y, 1.0f - t.transition.get(current_time));
|
|
ADVect::Graphics::DrawTextureImageAlpha(*t.next, t.pos_x, t.pos_y, t.transition.get(current_time));
|
|
}
|
|
else {
|
|
ADVect::Graphics::DrawTextureImage(*t.current, t.pos_x, t.pos_y);
|
|
}
|
|
}
|
|
}
|
|
}
|