Clean up videos some more, make them skippable

Also, revert a change I made to the button names internally
a long time ago, when the intent behind mkxp-z was possibly going to be
different.
This commit is contained in:
Struma 2022-01-23 01:46:13 -05:00
parent 45c5553619
commit 84f95966ea
7 changed files with 66 additions and 56 deletions

View file

@ -264,14 +264,17 @@ RB_METHOD(graphicsPlayMovie)
{
RB_UNUSED_PARAM;
VALUE filename, volumeArg;
rb_scan_args(argc, argv, "11", &filename, &volumeArg);
VALUE filename, volumeArg, skippable;
rb_scan_args(argc, argv, "12", &filename, &volumeArg, &skippable);
SafeStringValue(filename);
bool skip;
rb_bool_arg(skippable, &skip);
int volume = (volumeArg == Qnil) ? 100 : NUM2INT(volumeArg);
// TODO: Video control inputs (e.g. skip, pause)
GFX_GUARD_EXC(shState->graphics().playMovie(RSTRING_PTR(filename), volume););
GFX_GUARD_EXC(shState->graphics().playMovie(RSTRING_PTR(filename), volume, skip););
return Qnil;
}

View file

@ -367,8 +367,8 @@ struct {
{"LEFT", Input::Left},
{"RIGHT", Input::Right},
{"UP", Input::Up},
{"C", Input::ZL},
{"Z", Input::ZR},
{"C", Input::C},
{"Z", Input::Z},
{"A", Input::A},
{"B", Input::B},
{"X", Input::X},

View file

@ -33,7 +33,7 @@
static const int inputMapRowToCode[] {
Input::Down, Input::Left, Input::Right, Input::Up,
Input::A, Input:: B, Input::ZL, Input::X, Input::Y, Input::ZR,
Input::A, Input:: B, Input::C, Input::X, Input::Y, Input::Z,
Input::L, Input::R
};
@ -280,10 +280,10 @@ s.d.ja.dir = (axis.value >= 0) ? AxisDir::Positive : AxisDir::Negative;
SET_BINDING(Up);
SET_BINDING(A);
SET_BINDING(B);
SET_BINDING_CUSTOM(ZL, "C");
SET_BINDING(C);
SET_BINDING(X);
SET_BINDING(Y);
SET_BINDING_CUSTOM(ZR, "Z");
SET_BINDING(Z);
SET_BINDING(L);
SET_BINDING(R);
@ -292,10 +292,10 @@ if (!data.config.kbActionNames.value.empty()) bindingNames[@(Input::code)] = \
@(data.config.kbActionNames.value.c_str())
SET_BINDING_CONF(A,a);
SET_BINDING_CONF(B,b);
SET_BINDING_CONF(ZL,c);
SET_BINDING_CONF(C,c);
SET_BINDING_CONF(X,x);
SET_BINDING_CONF(Y,y);
SET_BINDING_CONF(ZR,z);
SET_BINDING_CONF(Z,z);
SET_BINDING_CONF(L,l);
SET_BINDING_CONF(R,r);

View file

@ -104,12 +104,13 @@ struct Movie
const THEORAPLAY_VideoFrame *video;
bool hasVideo;
bool hasAudio;
bool skippable;
Bitmap *videoBitmap;
SDL_RWops srcOps;
static float volume;
Movie(int volume_)
: decoder(0), audio(0), video(0)
Movie(int volume_, bool skippable_)
: decoder(0), audio(0), video(0), skippable(skippable_), videoBitmap(0)
{
volume = volume_ * 0.01f;
}
@ -170,7 +171,7 @@ struct Movie
SDL_Delay(VIDEO_DELAY);
}
}
videoBitmap = new Bitmap(video->width, video->height);
movieAudioQueue = NULL;
movieAudioQueueTail = NULL;
@ -284,12 +285,18 @@ struct Movie
void play()
{
// Assuming every frame has the same duration.
Uint32 frameMs = (video->fps == 0.0) ? 0 : ((Uint32) (1000.0 / video->fps));
// Uint32 frameMs = (video->fps == 0.0) ? 0 : ((Uint32) (1000.0 / video->fps));
Uint32 baseTicks = SDL_GetTicks();
bool openedAudio = false;
while (THEORAPLAY_isDecoding(decoder)) {
// Check for reset/shutdown input
if(shState->graphics().updateMovieInput(this)) break;
// Check for attempted skip
if (skippable) {
shState->input().update();
if (shState->input().isTriggered(Input::C) || shState->input().isTriggered(Input::B)) break;
}
const Uint32 now = SDL_GetTicks() - baseTicks;
@ -312,25 +319,12 @@ struct Movie
}
if (video && (video->playms <= now)) {
// Application is too far behind
if (!video) {
Debug() << "WARNING: Video playback cannot keep up!";
break;
}
// Got a video frame, now draw it
videoBitmap->replaceRaw(video->pixels, video->width * video->height * 4);
shState->graphics().update();
THEORAPLAY_freeVideo(video);
video = NULL;
} else {
// Next video frame not yet ready, let the CPU breathe
SDL_Delay(VIDEO_DELAY);
}
// Got a video frame, now draw it
videoBitmap->replaceRaw(video->pixels, video->width * video->height * 4);
shState->graphics().update(false);
THEORAPLAY_freeVideo(video);
video = NULL;
if (openedAudio) {
queueMoreMovieAudio(decoder, now);
}
@ -954,10 +948,13 @@ unsigned long long Graphics::lastUpdate() {
return p->last_update;
}
void Graphics::update() {
void Graphics::update(bool checkForShutdown) {
p->threadData->rqWindowAdjust.wait();
p->last_update = shState->runTime();
p->checkShutDownReset();
if (checkForShutdown)
p->checkShutDownReset();
p->checkSyncLock();
@ -1227,31 +1224,41 @@ bool Graphics::updateMovieInput(Movie *movie) {
return p->threadData->rqTerm || p->threadData->rqReset;
}
void Graphics::playMovie(const char *filename, int volume) {
Movie *movie = new Movie(volume);
void Graphics::playMovie(const char *filename, int volume, bool skippable) {
Movie *movie = new Movie(volume, skippable);
MovieOpenHandler handler(movie->srcOps);
shState->fileSystem().openRead(handler, filename);
if (movie->preparePlayback()) {
int limiterDisabled = p->fpsLimiter.disabled;
p->fpsLimiter.disabled = false;
p->fpsLimiter.setDesiredFPS(movie->video->fps);
int oldFPS = getFrameRate();
setFrameRate(movie->video->fps);
bool oldframeskip = p->useFrameSkip;
p->useFrameSkip = true;
p->useFrameSkip = false;
update();
Sprite movieSprite;
movie->videoBitmap = new Bitmap(movie->video->width, movie->video->height);
// Currently this stretches to fit the screen. VX Ace behavior is to center it and let the edges run off
movieSprite.setBitmap(movie->videoBitmap);
movieSprite.setZoomX((double)width() / movie->video->width);
movieSprite.setZoomY((double)height() / movie->video->height);
double ratio = (double)width() / movie->video->width;
movieSprite.setZoomX(ratio);
movieSprite.setZoomY(ratio);
movieSprite.setY((height() / 2) - (movie->video->height * ratio / 2));
Sprite letterboxSprite;
Bitmap letterbox(width(), height());
letterbox.fillRect(0, 0, width(), height(), Vec4(0,0,0,255));
letterboxSprite.setBitmap(&letterbox);
letterboxSprite.setZ(-1001);
movieSprite.setZ(-1000);
movie->play();
p->fpsLimiter.disabled = limiterDisabled;
p->fpsLimiter.setDesiredFPS(p->frameRate);
setFrameRate(oldFPS);
p->useFrameSkip = oldframeskip;
}

View file

@ -39,7 +39,7 @@ public:
unsigned long long getDelta();
unsigned long long lastUpdate();
void update();
void update(bool checkForShutdown = true);
void freeze();
void transition(int duration = 8,
const char *filename = "",
@ -61,7 +61,7 @@ public:
void resizeScreen(int width, int height);
void drawMovieFrame(const THEORAPLAY_VideoFrame* video, Bitmap *videoBitmap);
bool updateMovieInput(Movie *movie);
void playMovie(const char *filename, int volume);
void playMovie(const char *filename, int volume, bool skippable);
void screenshot(const char *filename);
void reset();

View file

@ -41,8 +41,8 @@ public:
Down = 2, Left = 4, Right = 6, Up = 8,
A = 11, B = 12, ZL = 13,
X = 14, Y = 15, ZR = 16,
A = 11, B = 12, C = 13,
X = 14, Y = 15, Z = 16,
L = 17, R = 18,
Shift = 21, Ctrl = 22, Alt = 23,

View file

@ -72,13 +72,13 @@ static const KbBindingData defaultKbBindings[] =
{ SDL_SCANCODE_UP, Input::Up },
{ SDL_SCANCODE_DOWN, Input::Down },
{ SDL_SCANCODE_SPACE, Input::ZL },
{ SDL_SCANCODE_RETURN, Input::ZL },
{ SDL_SCANCODE_SPACE, Input::C },
{ SDL_SCANCODE_RETURN, Input::C },
{ SDL_SCANCODE_ESCAPE, Input::B },
{ SDL_SCANCODE_KP_0, Input::B },
{ SDL_SCANCODE_LSHIFT, Input::A },
{ SDL_SCANCODE_X, Input::B },
{ SDL_SCANCODE_D, Input::ZR },
{ SDL_SCANCODE_D, Input::Z },
{ SDL_SCANCODE_Q, Input::L },
{ SDL_SCANCODE_W, Input::R },
{ SDL_SCANCODE_A, Input::X },
@ -89,13 +89,13 @@ static const KbBindingData defaultKbBindings[] =
static const KbBindingData defaultKbBindings1[] =
{
{ SDL_SCANCODE_Z, Input::A },
{ SDL_SCANCODE_C, Input::ZL },
{ SDL_SCANCODE_C, Input::C },
};
/* RGSS2 and higher */
static const KbBindingData defaultKbBindings2[] =
{
{ SDL_SCANCODE_Z, Input::ZL }
{ SDL_SCANCODE_Z, Input::C }
};
static elementsN(defaultKbBindings);
@ -106,10 +106,10 @@ static const JsBindingData defaultJsBindings[] =
{
{ 3, Input::A },
{ 0, Input::B },
{ 1, Input::ZL },
{ 1, Input::C },
{ 2, Input::X },
{ 4, Input::Y },
{ 5, Input::ZR },
{ 5, Input::Z },
{ 9, Input::L },
{ 10, Input::R }
};
@ -240,8 +240,8 @@ static bool verifyDesc(const BindingDesc &desc)
{
Input::None,
Input::Down, Input::Left, Input::Right, Input::Up,
Input::A, Input::B, Input::ZL,
Input::X, Input::Y, Input::ZR,
Input::A, Input::B, Input::C,
Input::X, Input::Y, Input::Z,
Input::L, Input::R,
Input::Shift, Input::Ctrl, Input::Alt,
Input::F5, Input::F6, Input::F7, Input::F8, Input::F9