mirror of
https://github.com/RetroDECK/ES-DE.git
synced 2024-11-21 21:55:38 +00:00
Added black areas around videos with non-standard aspect ratios.
This commit is contained in:
parent
f334eb7037
commit
bbb5575334
1
NEWS.md
1
NEWS.md
|
@ -49,6 +49,7 @@ Many bugs have been fixed, and numerous features that were only partially implem
|
|||
* Improved input device configuration, and default keyboard mappings are now applied if the keyboard has not been configured by the user
|
||||
* GUI-configurable option to sort favorite games above non-favorite games (favorites marked with stars)
|
||||
* GUI-configurable option to sort folders on top of the gamelists
|
||||
* Added the ability to display a black area around videos with non-standard aspect ratios, for example vertical shooters
|
||||
* Added a gamelist info text field displaying the game count, any applied filters as well as an icon if a folder has been entered
|
||||
* Expanded the gamelist filter functionality to include completed and broken games as well as the ability to filter on game names (via free text entry)
|
||||
* Expanded the metadata for folders and made it possible to mark them as favorites
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
#include <SDL2/SDL_timer.h>
|
||||
|
||||
#define SCREENSAVER_FADE_IN_TIME 800
|
||||
#define SCREENSAVER_FADE_IN_TIME 1200
|
||||
|
||||
void VideoComponent::setScreensaverMode(bool isScreensaver)
|
||||
{
|
||||
|
@ -24,24 +24,27 @@ void VideoComponent::setScreensaverMode(bool isScreensaver)
|
|||
}
|
||||
|
||||
VideoComponent::VideoComponent(
|
||||
Window* window)
|
||||
: GuiComponent(window),
|
||||
mWindow(window),
|
||||
mStaticImage(window),
|
||||
mVideoHeight(0),
|
||||
mVideoWidth(0),
|
||||
mStartDelayed(false),
|
||||
mIsPlaying(false),
|
||||
mPause(false),
|
||||
mShowing(false),
|
||||
mDisable(false),
|
||||
mScreensaverActive(false),
|
||||
mScreensaverMode(false),
|
||||
mGameLaunched(false),
|
||||
mBlockPlayer(false),
|
||||
mTargetIsMax(false),
|
||||
mFadeIn(1.0),
|
||||
mTargetSize(0, 0)
|
||||
Window* window)
|
||||
: GuiComponent(window),
|
||||
mWindow(window),
|
||||
mStaticImage(window),
|
||||
mVideoHeight(0),
|
||||
mVideoWidth(0),
|
||||
mStartDelayed(false),
|
||||
mIsPlaying(false),
|
||||
mIsActuallyPlaying(false),
|
||||
mPause(false),
|
||||
mShowing(false),
|
||||
mDisable(false),
|
||||
mScreensaverActive(false),
|
||||
mScreensaverMode(false),
|
||||
mGameLaunched(false),
|
||||
mBlockPlayer(false),
|
||||
mTargetIsMax(false),
|
||||
mFadeIn(1.0),
|
||||
mTargetSize(0, 0),
|
||||
mVideoAreaPos(0, 0),
|
||||
mVideoAreaSize(0, 0)
|
||||
{
|
||||
// Setup the default configuration.
|
||||
mConfig.showSnapshotDelay = false;
|
||||
|
@ -169,10 +172,19 @@ void VideoComponent::applyTheme(const std::shared_ptr<ThemeData>& theme, const s
|
|||
static_cast<float>(Renderer::getScreenHeight()));
|
||||
|
||||
if (properties & ThemeFlags::SIZE) {
|
||||
if (elem->has("size"))
|
||||
if (elem->has("size")) {
|
||||
setResize(elem->get<Vector2f>("size") * scale);
|
||||
else if (elem->has("maxSize"))
|
||||
mVideoAreaSize = elem->get<Vector2f>("size") * scale;
|
||||
}
|
||||
else if (elem->has("maxSize")) {
|
||||
setMaxSize(elem->get<Vector2f>("maxSize") * scale);
|
||||
mVideoAreaSize = elem->get<Vector2f>("maxSize") * scale;
|
||||
}
|
||||
}
|
||||
|
||||
if (properties & ThemeFlags::POSITION) {
|
||||
if (elem->has("pos"))
|
||||
mVideoAreaPos = elem->get<Vector2f>("pos") * scale;
|
||||
}
|
||||
|
||||
if (elem->has("default"))
|
||||
|
@ -258,11 +270,13 @@ void VideoComponent::update(int deltaTime)
|
|||
|
||||
manageState();
|
||||
|
||||
// This is only used to fade in the screensaver, fade-in of the static image is
|
||||
// handled using a lambda animation in VideoGameListView.
|
||||
if (mFadeIn < 1.0f)
|
||||
// Fade in videos, which is handled a bit differently depending on whether it's the
|
||||
// video screensaver that is running, or if it's the video in the gamelist.
|
||||
if (mScreensaverMode && mFadeIn < 1.0f)
|
||||
mFadeIn = Math::clamp(mFadeIn + (deltaTime /
|
||||
static_cast<float>(SCREENSAVER_FADE_IN_TIME)), 0.0, 1.0);
|
||||
else if (mFadeIn < 1.0f)
|
||||
mFadeIn = Math::clamp(mFadeIn + 0.01, 0.0f, 1.0f);
|
||||
|
||||
GuiComponent::update(deltaTime);
|
||||
}
|
||||
|
|
|
@ -104,6 +104,8 @@ protected:
|
|||
unsigned mVideoWidth;
|
||||
unsigned mVideoHeight;
|
||||
Vector2f mTargetSize;
|
||||
Vector2f mVideoAreaPos;
|
||||
Vector2f mVideoAreaSize;
|
||||
std::shared_ptr<TextureResource> mTexture;
|
||||
std::string mStaticImagePath;
|
||||
ImageComponent mStaticImage;
|
||||
|
@ -113,6 +115,7 @@ protected:
|
|||
unsigned mStartTime;
|
||||
bool mStartDelayed;
|
||||
bool mIsPlaying;
|
||||
bool mIsActuallyPlaying;
|
||||
bool mPause;
|
||||
bool mShowing;
|
||||
bool mDisable;
|
||||
|
|
|
@ -150,14 +150,40 @@ void VideoVlcComponent::render(const Transform4x4f& parentTrans)
|
|||
VideoComponent::render(parentTrans);
|
||||
Transform4x4f trans = parentTrans * getTransform();
|
||||
GuiComponent::renderChildren(trans);
|
||||
Renderer::setMatrix(trans);
|
||||
|
||||
if (mIsPlaying && mContext.valid) {
|
||||
// This fade in is only used by the video screensaver.
|
||||
const unsigned int fadeIn = (unsigned int)(Math::clamp(mFadeIn, 0.0f, 1.0f) * 255.0f);
|
||||
const unsigned int color =
|
||||
Renderer::convertColor((fadeIn << 24) | (fadeIn << 16) | (fadeIn << 8) | 255);
|
||||
// Check the actual VLC state, i.e. if the video is really playing rather than
|
||||
// still being opened.
|
||||
if (mMediaPlayer && mIsPlaying && !mIsActuallyPlaying) {
|
||||
libvlc_state_t state;
|
||||
state = libvlc_media_player_get_state(mMediaPlayer);
|
||||
if (state == libvlc_Playing)
|
||||
mIsActuallyPlaying = true;
|
||||
}
|
||||
|
||||
if (!mIsActuallyPlaying && !mStaticImage.isVisible())
|
||||
mStaticImage.setVisible(true);
|
||||
|
||||
if (mIsPlaying && mContext.valid && mIsActuallyPlaying) {
|
||||
unsigned int color;
|
||||
if (mFadeIn < 1) {
|
||||
const unsigned int fadeIn = mFadeIn * 255.0f;
|
||||
color = Renderer::convertColor((fadeIn << 24) | (fadeIn << 16) | (fadeIn << 8) | 255);
|
||||
}
|
||||
else {
|
||||
color = 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
Renderer::Vertex vertices[4];
|
||||
Renderer::setMatrix(parentTrans);
|
||||
|
||||
// Render the black rectangle behind the video.
|
||||
if (mVideoRectangleCoords.size() == 4) {
|
||||
Renderer::drawRect(mVideoRectangleCoords[0], mVideoRectangleCoords[1],
|
||||
mVideoRectangleCoords[2], mVideoRectangleCoords[3],
|
||||
0x000000FF, 0x000000FF);
|
||||
if (mStaticImage.isVisible())
|
||||
mStaticImage.setVisible(false);
|
||||
}
|
||||
|
||||
vertices[0] = { { 0.0f , 0.0f }, { 0.0f, 0.0f }, color };
|
||||
vertices[1] = { { 0.0f , mSize.y() }, { 0.0f, 1.0f }, color };
|
||||
|
@ -175,13 +201,14 @@ void VideoVlcComponent::render(const Transform4x4f& parentTrans)
|
|||
|
||||
#if defined(USE_OPENGL_21)
|
||||
// Render scanlines if this option is enabled. However, if this is the video
|
||||
// screensaver, then skip this as screensaver scanline rendering is handled from
|
||||
// Window.cpp as a postprocessing step.
|
||||
// screensaver, then skip this as screensaver scanline rendering is handled in
|
||||
// SystemScreenSaver as a postprocessing step.
|
||||
if (!mScreensaverMode && Settings::getInstance()->getBool("GamelistVideoScanlines"))
|
||||
vertices[0].shaders = Renderer::SHADER_SCANLINES;
|
||||
#endif
|
||||
|
||||
// Render it.
|
||||
Renderer::setMatrix(trans);
|
||||
Renderer::drawTriangleStrips(&vertices[0], 4, trans);
|
||||
}
|
||||
else {
|
||||
|
@ -292,8 +319,8 @@ void VideoVlcComponent::startVideo()
|
|||
libvlc_event_t vlcEvent;
|
||||
|
||||
// Asynchronous media parsing.
|
||||
libvlc_event_attach(libvlc_media_event_manager(
|
||||
mMedia), libvlc_MediaParsedChanged, VlcMediaParseCallback, 0);
|
||||
libvlc_event_attach(libvlc_media_event_manager(mMedia),
|
||||
libvlc_MediaParsedChanged, VlcMediaParseCallback, 0);
|
||||
parseResult = libvlc_media_parse_with_options(mMedia, libvlc_media_parse_local, -1);
|
||||
|
||||
if (!parseResult) {
|
||||
|
@ -340,6 +367,48 @@ void VideoVlcComponent::startVideo()
|
|||
mIsPlaying = true;
|
||||
mFadeIn = 0.0f;
|
||||
}
|
||||
if (mIsPlaying) {
|
||||
// Create the position and size for the black rectangle that will be
|
||||
// rendered behind videos that are not filling the whole md_video area.
|
||||
if (mVideoAreaPos != 0 && mVideoAreaSize != 0) {
|
||||
mVideoRectangleCoords.clear();
|
||||
float rectHeight;
|
||||
float rectWidth;
|
||||
// Video is in landscape orientation.
|
||||
if (mSize.x() > mSize.y()) {
|
||||
// Checking the Y size should not normally be required as landscape
|
||||
// format should mean the height can't be higher than the max size
|
||||
// defined by the theme. But as the height in mSize is provided by
|
||||
// libVLC in integer format and then scaled, there could be rounding
|
||||
// errors that make the video height slightly higher than allowed.
|
||||
// It's only a pixel or so, but it's still visible for some videos.
|
||||
if (mSize.y() < mVideoAreaSize.y() &&
|
||||
mSize.y() / mVideoAreaSize.y() < 0.97)
|
||||
rectHeight = mVideoAreaSize.y();
|
||||
else
|
||||
rectHeight = mSize.y();
|
||||
// Don't add a black border that is too narrow, that's what the
|
||||
// 0.85 constant takes care of.
|
||||
if (mSize.x() < mVideoAreaSize.x() &&
|
||||
mSize.x() / mVideoAreaSize.x() < 0.85)
|
||||
rectWidth = mVideoAreaSize.x();
|
||||
else
|
||||
rectWidth = mSize.x();
|
||||
}
|
||||
// Video is in portrait orientation (or completely square).
|
||||
else {
|
||||
rectWidth = mVideoAreaSize.x();
|
||||
rectHeight = mSize.y();
|
||||
}
|
||||
// Populate the rectangle coordinates to be used in render().
|
||||
mVideoRectangleCoords.push_back(mVideoAreaPos.x() -
|
||||
rectWidth * mOrigin.x());
|
||||
mVideoRectangleCoords.push_back(mVideoAreaPos.y() -
|
||||
rectHeight * mOrigin.y());
|
||||
mVideoRectangleCoords.push_back(rectWidth);
|
||||
mVideoRectangleCoords.push_back(rectHeight);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -348,6 +417,7 @@ void VideoVlcComponent::startVideo()
|
|||
void VideoVlcComponent::stopVideo()
|
||||
{
|
||||
mIsPlaying = false;
|
||||
mIsActuallyPlaying = false;
|
||||
mStartDelayed = false;
|
||||
mPause = false;
|
||||
// Release the media player so it stops calling back to us.
|
||||
|
|
|
@ -79,6 +79,7 @@ private:
|
|||
libvlc_media_player_t* mMediaPlayer;
|
||||
VideoContext mContext;
|
||||
std::shared_ptr<TextureResource> mTexture;
|
||||
std::vector<float> mVideoRectangleCoords;
|
||||
};
|
||||
|
||||
#endif // ES_CORE_COMPONENTS_VIDEO_VLC_COMPONENT_H
|
||||
|
|
|
@ -284,7 +284,7 @@ based on: 'recalbox-multi' by the Recalbox community
|
|||
<video name="md_video">
|
||||
<origin>0.5 0.5</origin>
|
||||
<pos>0.63 0.45</pos>
|
||||
<maxSize>0.360 0.424</maxSize>
|
||||
<maxSize>0.356 0.424</maxSize>
|
||||
<delay>1.7</delay>
|
||||
<showSnapshotNoVideo>true</showSnapshotNoVideo>
|
||||
<showSnapshotDelay>true</showSnapshotDelay>
|
||||
|
|
Loading…
Reference in a new issue