From 84f95966ead37bce6c8dbeaf3ec08ed949441598 Mon Sep 17 00:00:00 2001 From: Struma Date: Sun, 23 Jan 2022 01:46:13 -0500 Subject: [PATCH] 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. --- binding/graphics-binding.cpp | 9 ++-- binding/input-binding.cpp | 4 +- macos/views/SettingsMenuController.mm | 10 ++-- src/display/graphics.cpp | 73 +++++++++++++++------------ src/display/graphics.h | 4 +- src/input/input.h | 4 +- src/input/keybindings.cpp | 18 +++---- 7 files changed, 66 insertions(+), 56 deletions(-) diff --git a/binding/graphics-binding.cpp b/binding/graphics-binding.cpp index a128f3ea..cce2c7b6 100644 --- a/binding/graphics-binding.cpp +++ b/binding/graphics-binding.cpp @@ -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; } diff --git a/binding/input-binding.cpp b/binding/input-binding.cpp index a40c2cc5..f60d8d28 100644 --- a/binding/input-binding.cpp +++ b/binding/input-binding.cpp @@ -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}, diff --git a/macos/views/SettingsMenuController.mm b/macos/views/SettingsMenuController.mm index 51cb6339..c2f295d5 100644 --- a/macos/views/SettingsMenuController.mm +++ b/macos/views/SettingsMenuController.mm @@ -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); diff --git a/src/display/graphics.cpp b/src/display/graphics.cpp index 6b9947bd..9cbfbfc2 100644 --- a/src/display/graphics.cpp +++ b/src/display/graphics.cpp @@ -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; } diff --git a/src/display/graphics.h b/src/display/graphics.h index 96cbd942..4cf78720 100644 --- a/src/display/graphics.h +++ b/src/display/graphics.h @@ -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(); diff --git a/src/input/input.h b/src/input/input.h index 2cb7e5c8..2d78e804 100644 --- a/src/input/input.h +++ b/src/input/input.h @@ -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, diff --git a/src/input/keybindings.cpp b/src/input/keybindings.cpp index ef1590be..fbe4e38f 100644 --- a/src/input/keybindings.cpp +++ b/src/input/keybindings.cpp @@ -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