mirror of
https://github.com/RetroDECK/ES-DE.git
synced 2024-11-22 14:15: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
|
* 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 favorite games above non-favorite games (favorites marked with stars)
|
||||||
* GUI-configurable option to sort folders on top of the gamelists
|
* 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
|
* 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 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
|
* Expanded the metadata for folders and made it possible to mark them as favorites
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
|
|
||||||
#include <SDL2/SDL_timer.h>
|
#include <SDL2/SDL_timer.h>
|
||||||
|
|
||||||
#define SCREENSAVER_FADE_IN_TIME 800
|
#define SCREENSAVER_FADE_IN_TIME 1200
|
||||||
|
|
||||||
void VideoComponent::setScreensaverMode(bool isScreensaver)
|
void VideoComponent::setScreensaverMode(bool isScreensaver)
|
||||||
{
|
{
|
||||||
|
@ -24,24 +24,27 @@ void VideoComponent::setScreensaverMode(bool isScreensaver)
|
||||||
}
|
}
|
||||||
|
|
||||||
VideoComponent::VideoComponent(
|
VideoComponent::VideoComponent(
|
||||||
Window* window)
|
Window* window)
|
||||||
: GuiComponent(window),
|
: GuiComponent(window),
|
||||||
mWindow(window),
|
mWindow(window),
|
||||||
mStaticImage(window),
|
mStaticImage(window),
|
||||||
mVideoHeight(0),
|
mVideoHeight(0),
|
||||||
mVideoWidth(0),
|
mVideoWidth(0),
|
||||||
mStartDelayed(false),
|
mStartDelayed(false),
|
||||||
mIsPlaying(false),
|
mIsPlaying(false),
|
||||||
mPause(false),
|
mIsActuallyPlaying(false),
|
||||||
mShowing(false),
|
mPause(false),
|
||||||
mDisable(false),
|
mShowing(false),
|
||||||
mScreensaverActive(false),
|
mDisable(false),
|
||||||
mScreensaverMode(false),
|
mScreensaverActive(false),
|
||||||
mGameLaunched(false),
|
mScreensaverMode(false),
|
||||||
mBlockPlayer(false),
|
mGameLaunched(false),
|
||||||
mTargetIsMax(false),
|
mBlockPlayer(false),
|
||||||
mFadeIn(1.0),
|
mTargetIsMax(false),
|
||||||
mTargetSize(0, 0)
|
mFadeIn(1.0),
|
||||||
|
mTargetSize(0, 0),
|
||||||
|
mVideoAreaPos(0, 0),
|
||||||
|
mVideoAreaSize(0, 0)
|
||||||
{
|
{
|
||||||
// Setup the default configuration.
|
// Setup the default configuration.
|
||||||
mConfig.showSnapshotDelay = false;
|
mConfig.showSnapshotDelay = false;
|
||||||
|
@ -169,10 +172,19 @@ void VideoComponent::applyTheme(const std::shared_ptr<ThemeData>& theme, const s
|
||||||
static_cast<float>(Renderer::getScreenHeight()));
|
static_cast<float>(Renderer::getScreenHeight()));
|
||||||
|
|
||||||
if (properties & ThemeFlags::SIZE) {
|
if (properties & ThemeFlags::SIZE) {
|
||||||
if (elem->has("size"))
|
if (elem->has("size")) {
|
||||||
setResize(elem->get<Vector2f>("size") * scale);
|
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);
|
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"))
|
if (elem->has("default"))
|
||||||
|
@ -258,11 +270,13 @@ void VideoComponent::update(int deltaTime)
|
||||||
|
|
||||||
manageState();
|
manageState();
|
||||||
|
|
||||||
// This is only used to fade in the screensaver, fade-in of the static image is
|
// Fade in videos, which is handled a bit differently depending on whether it's the
|
||||||
// handled using a lambda animation in VideoGameListView.
|
// video screensaver that is running, or if it's the video in the gamelist.
|
||||||
if (mFadeIn < 1.0f)
|
if (mScreensaverMode && mFadeIn < 1.0f)
|
||||||
mFadeIn = Math::clamp(mFadeIn + (deltaTime /
|
mFadeIn = Math::clamp(mFadeIn + (deltaTime /
|
||||||
static_cast<float>(SCREENSAVER_FADE_IN_TIME)), 0.0, 1.0);
|
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);
|
GuiComponent::update(deltaTime);
|
||||||
}
|
}
|
||||||
|
|
|
@ -104,6 +104,8 @@ protected:
|
||||||
unsigned mVideoWidth;
|
unsigned mVideoWidth;
|
||||||
unsigned mVideoHeight;
|
unsigned mVideoHeight;
|
||||||
Vector2f mTargetSize;
|
Vector2f mTargetSize;
|
||||||
|
Vector2f mVideoAreaPos;
|
||||||
|
Vector2f mVideoAreaSize;
|
||||||
std::shared_ptr<TextureResource> mTexture;
|
std::shared_ptr<TextureResource> mTexture;
|
||||||
std::string mStaticImagePath;
|
std::string mStaticImagePath;
|
||||||
ImageComponent mStaticImage;
|
ImageComponent mStaticImage;
|
||||||
|
@ -113,6 +115,7 @@ protected:
|
||||||
unsigned mStartTime;
|
unsigned mStartTime;
|
||||||
bool mStartDelayed;
|
bool mStartDelayed;
|
||||||
bool mIsPlaying;
|
bool mIsPlaying;
|
||||||
|
bool mIsActuallyPlaying;
|
||||||
bool mPause;
|
bool mPause;
|
||||||
bool mShowing;
|
bool mShowing;
|
||||||
bool mDisable;
|
bool mDisable;
|
||||||
|
|
|
@ -150,14 +150,40 @@ void VideoVlcComponent::render(const Transform4x4f& parentTrans)
|
||||||
VideoComponent::render(parentTrans);
|
VideoComponent::render(parentTrans);
|
||||||
Transform4x4f trans = parentTrans * getTransform();
|
Transform4x4f trans = parentTrans * getTransform();
|
||||||
GuiComponent::renderChildren(trans);
|
GuiComponent::renderChildren(trans);
|
||||||
Renderer::setMatrix(trans);
|
|
||||||
|
|
||||||
if (mIsPlaying && mContext.valid) {
|
// Check the actual VLC state, i.e. if the video is really playing rather than
|
||||||
// This fade in is only used by the video screensaver.
|
// still being opened.
|
||||||
const unsigned int fadeIn = (unsigned int)(Math::clamp(mFadeIn, 0.0f, 1.0f) * 255.0f);
|
if (mMediaPlayer && mIsPlaying && !mIsActuallyPlaying) {
|
||||||
const unsigned int color =
|
libvlc_state_t state;
|
||||||
Renderer::convertColor((fadeIn << 24) | (fadeIn << 16) | (fadeIn << 8) | 255);
|
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::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[0] = { { 0.0f , 0.0f }, { 0.0f, 0.0f }, color };
|
||||||
vertices[1] = { { 0.0f , mSize.y() }, { 0.0f, 1.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)
|
#if defined(USE_OPENGL_21)
|
||||||
// Render scanlines if this option is enabled. However, if this is the video
|
// Render scanlines if this option is enabled. However, if this is the video
|
||||||
// screensaver, then skip this as screensaver scanline rendering is handled from
|
// screensaver, then skip this as screensaver scanline rendering is handled in
|
||||||
// Window.cpp as a postprocessing step.
|
// SystemScreenSaver as a postprocessing step.
|
||||||
if (!mScreensaverMode && Settings::getInstance()->getBool("GamelistVideoScanlines"))
|
if (!mScreensaverMode && Settings::getInstance()->getBool("GamelistVideoScanlines"))
|
||||||
vertices[0].shaders = Renderer::SHADER_SCANLINES;
|
vertices[0].shaders = Renderer::SHADER_SCANLINES;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Render it.
|
// Render it.
|
||||||
|
Renderer::setMatrix(trans);
|
||||||
Renderer::drawTriangleStrips(&vertices[0], 4, trans);
|
Renderer::drawTriangleStrips(&vertices[0], 4, trans);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -292,8 +319,8 @@ void VideoVlcComponent::startVideo()
|
||||||
libvlc_event_t vlcEvent;
|
libvlc_event_t vlcEvent;
|
||||||
|
|
||||||
// Asynchronous media parsing.
|
// Asynchronous media parsing.
|
||||||
libvlc_event_attach(libvlc_media_event_manager(
|
libvlc_event_attach(libvlc_media_event_manager(mMedia),
|
||||||
mMedia), libvlc_MediaParsedChanged, VlcMediaParseCallback, 0);
|
libvlc_MediaParsedChanged, VlcMediaParseCallback, 0);
|
||||||
parseResult = libvlc_media_parse_with_options(mMedia, libvlc_media_parse_local, -1);
|
parseResult = libvlc_media_parse_with_options(mMedia, libvlc_media_parse_local, -1);
|
||||||
|
|
||||||
if (!parseResult) {
|
if (!parseResult) {
|
||||||
|
@ -340,6 +367,48 @@ void VideoVlcComponent::startVideo()
|
||||||
mIsPlaying = true;
|
mIsPlaying = true;
|
||||||
mFadeIn = 0.0f;
|
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()
|
void VideoVlcComponent::stopVideo()
|
||||||
{
|
{
|
||||||
mIsPlaying = false;
|
mIsPlaying = false;
|
||||||
|
mIsActuallyPlaying = false;
|
||||||
mStartDelayed = false;
|
mStartDelayed = false;
|
||||||
mPause = false;
|
mPause = false;
|
||||||
// Release the media player so it stops calling back to us.
|
// Release the media player so it stops calling back to us.
|
||||||
|
|
|
@ -79,6 +79,7 @@ private:
|
||||||
libvlc_media_player_t* mMediaPlayer;
|
libvlc_media_player_t* mMediaPlayer;
|
||||||
VideoContext mContext;
|
VideoContext mContext;
|
||||||
std::shared_ptr<TextureResource> mTexture;
|
std::shared_ptr<TextureResource> mTexture;
|
||||||
|
std::vector<float> mVideoRectangleCoords;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // ES_CORE_COMPONENTS_VIDEO_VLC_COMPONENT_H
|
#endif // ES_CORE_COMPONENTS_VIDEO_VLC_COMPONENT_H
|
||||||
|
|
|
@ -284,7 +284,7 @@ based on: 'recalbox-multi' by the Recalbox community
|
||||||
<video name="md_video">
|
<video name="md_video">
|
||||||
<origin>0.5 0.5</origin>
|
<origin>0.5 0.5</origin>
|
||||||
<pos>0.63 0.45</pos>
|
<pos>0.63 0.45</pos>
|
||||||
<maxSize>0.360 0.424</maxSize>
|
<maxSize>0.356 0.424</maxSize>
|
||||||
<delay>1.7</delay>
|
<delay>1.7</delay>
|
||||||
<showSnapshotNoVideo>true</showSnapshotNoVideo>
|
<showSnapshotNoVideo>true</showSnapshotNoVideo>
|
||||||
<showSnapshotDelay>true</showSnapshotDelay>
|
<showSnapshotDelay>true</showSnapshotDelay>
|
||||||
|
|
Loading…
Reference in a new issue