Files
wc3re/game/GSMvePlay.cc

126 lines
3.0 KiB
C++

#include "MveDecoder.hh"
#include "GSMvePlay.hh"
#include "render/Overlay.hh"
#include "render/Renderer.hh"
#include "render/AudioStream.hh"
namespace game {
GSMvePlay::GSMvePlay(render::Renderer& renderer, MveDecoder::Movie& movie)
: GameState(renderer), movie_(movie),
overlay_(nullptr), delta_(0),
nextFT_(1000/15.0f), frameRGBA_(), decoded_(false), firstFrame_(true)
{
int scrWidth = renderer_.getWidth(), scrHeight = renderer_.getHeight();
const float mvePAR = 1.2f;
int mveWidth = movie_.getWidth(), mveHeight = movie_.getHeight();
int top = 0, left = 0;
if ((static_cast<float>(mveWidth)/(mveHeight*mvePAR)) > (static_cast<float>(scrWidth)/scrHeight)) {
// letterbox
int newScrHeight = scrWidth/(static_cast<float>(mveWidth)/(mveHeight*mvePAR));
top = (scrHeight-newScrHeight)/2;
scrHeight = newScrHeight;
} else {
// pillarbox
int newScrWidth = scrHeight*(static_cast<float>(mveWidth)/(mveHeight*mvePAR));
left = (scrWidth-newScrWidth)/2;
scrWidth = newScrWidth;
}
overlay_ = std::make_unique<render::Overlay>(renderer_, scrWidth, scrHeight, left, top,
mveWidth, mveHeight);
audio_ = std::make_unique<render::AudioStream>();
frameRGBA_.resize(mveWidth*mveHeight*4);
decode_();
overlay_->setContentBGRA8(frameRGBA_.data());
decode_();
}
GSMvePlay::~GSMvePlay()
{
}
void GSMvePlay::decode_()
{
if (movie_.hasAudio()) {
auto samples = movie_.getNextAudio();
audio_->queueSamples(1, 22050, samples.data(), samples.size()*2);
}
if (movie_.hasNext()) {
auto dec = movie_.decodeNext();
auto& frame = std::get<0>(dec);
auto& palette = std::get<1>(dec);
size_t i = 0;
auto height = movie_.getHeight(), width = movie_.getWidth();
for (unsigned y = 0;y < height;++y) {
for (unsigned x = 0;x < width;++x) {
auto idx = frame[y*width+x];
frameRGBA_[i] = palette[idx*3+2];
frameRGBA_[i+1] = palette[idx*3+1];
frameRGBA_[i+2] = palette[idx*3];
frameRGBA_[i+3] = 255u;
i += 4;
}
}
} else
frameRGBA_.resize(0);
}
bool GSMvePlay::handleEvent(SDL_Event& event)
{
switch (event.type) {
case SDL_KEYDOWN:
if (event.key.keysym.sym == SDLK_ESCAPE) {
renderer_.popGS();
return true;
}
break;
}
return false;
}
void GSMvePlay::draw(unsigned delta_ms)
{
const float frameTime = 1000/15.0f;
if (firstFrame_) {
firstFrame_ = false;
audio_->play();
}
delta_ += delta_ms;
if (delta_ >= nextFT_) {
if (!decoded_)
decode_();
if (!frameRGBA_.size()) {
renderer_.popGS();
return;
}
if (delta_-nextFT_ <= frameTime)
nextFT_ = frameTime-(delta_-nextFT_);
else
nextFT_ = frameTime;
delta_ = 0;
overlay_->setContentBGRA8(frameRGBA_.data());
decoded_ = false;
} else if (!decoded_) {
decode_();
decoded_ = true;
}
overlay_->draw();
}
}