initial commit
This commit is contained in:
@@ -0,0 +1,118 @@
|
||||
#pragma once
|
||||
|
||||
#include "fibonacci_line_pattern.h"
|
||||
#include "page.h"
|
||||
#include "scroller_streams.h"
|
||||
|
||||
#include <SDL3/SDL.h>
|
||||
#include <SDL3_ttf/SDL_ttf.h>
|
||||
#include <deque>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
struct AppState;
|
||||
|
||||
// Full-screen page showing proclamation text scrolling vertically using the
|
||||
// Fibonacci line-length pattern, per-frequency color palettes, and crossfaded
|
||||
// solfeggio audio. Proclamation text is never rendered as human-readable type:
|
||||
// every code point is rasterized and permuted into a scrambled glyph tile by
|
||||
// the Fibonacci affine map (see scramble/fibonacci_scrambler.h), and words are
|
||||
// assembled from those tiles. ESC returns to the previous page (Home).
|
||||
class ScrollerPage : public Page {
|
||||
public:
|
||||
void onPush(AppState& state) override;
|
||||
void onResume(AppState& state) override;
|
||||
void onPause(AppState& state) override;
|
||||
void onPop(AppState& state) override;
|
||||
void handleEvent(const SDL_Event& event) override;
|
||||
void update(float dt) override;
|
||||
void render(SDL_Renderer* renderer) override;
|
||||
|
||||
private:
|
||||
struct WordItem {
|
||||
SDL_Texture* texture = nullptr;
|
||||
std::string text;
|
||||
float width = 0;
|
||||
float height = 0;
|
||||
float x = 0; // relative to the line's left edge
|
||||
float y = 0;
|
||||
};
|
||||
|
||||
struct ScrollerLine {
|
||||
std::vector<WordItem> words;
|
||||
float width = 0;
|
||||
uint8_t r = 255;
|
||||
uint8_t g = 255;
|
||||
uint8_t b = 255;
|
||||
};
|
||||
|
||||
struct CachedWord {
|
||||
SDL_Texture* texture = nullptr;
|
||||
float width = 0;
|
||||
float height = 0;
|
||||
};
|
||||
|
||||
// A single glyph's scrambled tile -- [This implementation] rendering
|
||||
// decision: scrambling is per code point so any glyph in the proclamation
|
||||
// set is permuted exactly once per font size, then reused by every word
|
||||
// that contains it.
|
||||
// `surface` is the N x N (N = max(glyphW, glyphH)) RGBA8888 canvas
|
||||
// produced by the Fibonacci affine scrambler. glyphW x glyphH is the
|
||||
// size of the ORIGINAL, unscrambled glyph (the top-left W x H
|
||||
// sub-rectangle of the tile, matching the crop-window display
|
||||
// convention); word assembly blits exactly that crop. `advance` is the
|
||||
// glyph's unmodified TTF advance width, so per-glyph assembly keeps word
|
||||
// layout identical to plain text rendering. Every glyph surface carries
|
||||
// the font's full line height, so crops align on the shared baseline.
|
||||
struct CharEntry {
|
||||
SDL_Surface* surface = nullptr;
|
||||
float glyphW = 0;
|
||||
float glyphH = 0;
|
||||
float advance = 0;
|
||||
};
|
||||
|
||||
void buildStreams(AppState& state);
|
||||
void createFont(AppState& state);
|
||||
void createPatterns();
|
||||
int computePeakWordCount(const std::vector<std::string>& words) const;
|
||||
void destroyResources();
|
||||
void rebuildWordTextures();
|
||||
void prefillLines();
|
||||
void addLineAt(float baseY);
|
||||
void advanceStream();
|
||||
void switchAudioForCurrentStream();
|
||||
void updateAutoVelocity(float dt);
|
||||
void ensureWordTexture(const std::string& word);
|
||||
void ensureCharTexture(const std::string& glyph);
|
||||
void clearCharTextures();
|
||||
float measureWidth(const std::string& text) const;
|
||||
std::string audioFilePath(const std::string& filename) const;
|
||||
|
||||
AppState* state_ = nullptr;
|
||||
|
||||
std::vector<radiantwave::scroller::ProclamationStream> streams_;
|
||||
std::vector<radiantwave::scroller::StreamColor> fallbackPalette_;
|
||||
std::vector<radiantwave::FibonacciLinePattern> patterns_;
|
||||
int streamIndex_ = 0;
|
||||
bool prefilling_ = false;
|
||||
|
||||
TTF_Font* font_ = nullptr;
|
||||
int fontPxSize_ = 32;
|
||||
float lineHeight_ = 0;
|
||||
float spaceWidth_ = 0;
|
||||
float screenW_ = 0;
|
||||
float screenH_ = 0;
|
||||
float maxLineWidth_ = 0;
|
||||
|
||||
std::deque<ScrollerLine> lines_;
|
||||
std::unordered_map<std::string, CachedWord> wordTextures_;
|
||||
std::unordered_map<std::string, CharEntry> charTextures_;
|
||||
|
||||
float scrollOffset_ = 0;
|
||||
float velocity_ = -2750.0f;
|
||||
float velocityStep_ = 100.0f;
|
||||
float velocityDelay_ = 2.5f;
|
||||
int velocityState_ = 0;
|
||||
float velocityTimer_ = 0.0f;
|
||||
};
|
||||
Reference in New Issue
Block a user