mirror of
https://github.com/RetroDECK/ES-DE.git
synced 2024-11-29 09:35:39 +00:00
implement maxSize for videos
implement maxSize for videos
This commit is contained in:
parent
e95eb4eea6
commit
44f886c961
|
@ -86,6 +86,7 @@ std::map< std::string, ElementMapType > ThemeData::sElementMap = boost::assign::
|
||||||
("video", makeMap(boost::assign::map_list_of
|
("video", makeMap(boost::assign::map_list_of
|
||||||
("pos", NORMALIZED_PAIR)
|
("pos", NORMALIZED_PAIR)
|
||||||
("size", NORMALIZED_PAIR)
|
("size", NORMALIZED_PAIR)
|
||||||
|
("maxSize", NORMALIZED_PAIR)
|
||||||
("origin", NORMALIZED_PAIR)
|
("origin", NORMALIZED_PAIR)
|
||||||
("default", PATH)
|
("default", PATH)
|
||||||
("delay", FLOAT)
|
("delay", FLOAT)
|
||||||
|
|
|
@ -39,7 +39,10 @@ VideoComponent::VideoComponent(Window* window) :
|
||||||
mVideoWidth(0),
|
mVideoWidth(0),
|
||||||
mStartDelayed(false),
|
mStartDelayed(false),
|
||||||
mIsPlaying(false),
|
mIsPlaying(false),
|
||||||
mShowing(false)
|
mShowing(false),
|
||||||
|
mTargetIsMax(false),
|
||||||
|
mOrigin(0, 0),
|
||||||
|
mTargetSize(0, 0)
|
||||||
{
|
{
|
||||||
memset(&mContext, 0, sizeof(mContext));
|
memset(&mContext, 0, sizeof(mContext));
|
||||||
|
|
||||||
|
@ -69,12 +72,89 @@ void VideoComponent::setOrigin(float originX, float originY)
|
||||||
mStaticImage.setOrigin(originX, originY);
|
mStaticImage.setOrigin(originX, originY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VideoComponent::setResize(float width, float height)
|
||||||
|
{
|
||||||
|
mTargetSize << width, height;
|
||||||
|
mTargetIsMax = false;
|
||||||
|
mStaticImage.setResize(width, height);
|
||||||
|
resize();
|
||||||
|
}
|
||||||
|
|
||||||
|
void VideoComponent::setMaxSize(float width, float height)
|
||||||
|
{
|
||||||
|
mTargetSize << width, height;
|
||||||
|
mTargetIsMax = true;
|
||||||
|
mStaticImage.setMaxSize(width, height);
|
||||||
|
resize();
|
||||||
|
}
|
||||||
|
|
||||||
Eigen::Vector2f VideoComponent::getCenter() const
|
Eigen::Vector2f VideoComponent::getCenter() const
|
||||||
{
|
{
|
||||||
return Eigen::Vector2f(mPosition.x() - (getSize().x() * mOrigin.x()) + getSize().x() / 2,
|
return Eigen::Vector2f(mPosition.x() - (getSize().x() * mOrigin.x()) + getSize().x() / 2,
|
||||||
mPosition.y() - (getSize().y() * mOrigin.y()) + getSize().y() / 2);
|
mPosition.y() - (getSize().y() * mOrigin.y()) + getSize().y() / 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VideoComponent::resize()
|
||||||
|
{
|
||||||
|
if(!mTexture)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const Eigen::Vector2f textureSize(mVideoWidth, mVideoHeight);
|
||||||
|
|
||||||
|
if(textureSize.isZero())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// SVG rasterization is determined by height (see SVGResource.cpp), and rasterization is done in terms of pixels
|
||||||
|
// if rounding is off enough in the rasterization step (for images with extreme aspect ratios), it can cause cutoff when the aspect ratio breaks
|
||||||
|
// so, we always make sure the resultant height is an integer to make sure cutoff doesn't happen, and scale width from that
|
||||||
|
// (you'll see this scattered throughout the function)
|
||||||
|
// this is probably not the best way, so if you're familiar with this problem and have a better solution, please make a pull request!
|
||||||
|
|
||||||
|
if(mTargetIsMax)
|
||||||
|
{
|
||||||
|
|
||||||
|
mSize = textureSize;
|
||||||
|
|
||||||
|
Eigen::Vector2f resizeScale((mTargetSize.x() / mSize.x()), (mTargetSize.y() / mSize.y()));
|
||||||
|
|
||||||
|
if(resizeScale.x() < resizeScale.y())
|
||||||
|
{
|
||||||
|
mSize[0] *= resizeScale.x();
|
||||||
|
mSize[1] *= resizeScale.x();
|
||||||
|
}else{
|
||||||
|
mSize[0] *= resizeScale.y();
|
||||||
|
mSize[1] *= resizeScale.y();
|
||||||
|
}
|
||||||
|
|
||||||
|
// for SVG rasterization, always calculate width from rounded height (see comment above)
|
||||||
|
mSize[1] = round(mSize[1]);
|
||||||
|
mSize[0] = (mSize[1] / textureSize.y()) * textureSize.x();
|
||||||
|
|
||||||
|
}else{
|
||||||
|
// if both components are set, we just stretch
|
||||||
|
// if no components are set, we don't resize at all
|
||||||
|
mSize = mTargetSize.isZero() ? textureSize : mTargetSize;
|
||||||
|
|
||||||
|
// if only one component is set, we resize in a way that maintains aspect ratio
|
||||||
|
// for SVG rasterization, we always calculate width from rounded height (see comment above)
|
||||||
|
if(!mTargetSize.x() && mTargetSize.y())
|
||||||
|
{
|
||||||
|
mSize[1] = round(mTargetSize.y());
|
||||||
|
mSize[0] = (mSize.y() / textureSize.y()) * textureSize.x();
|
||||||
|
}else if(mTargetSize.x() && !mTargetSize.y())
|
||||||
|
{
|
||||||
|
mSize[1] = round((mTargetSize.x() / textureSize.x()) * textureSize.y());
|
||||||
|
mSize[0] = (mSize.y() / textureSize.y()) * textureSize.x();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// mSize.y() should already be rounded
|
||||||
|
mTexture->rasterizeAt((int)round(mSize.x()), (int)round(mSize.y()));
|
||||||
|
|
||||||
|
onSizeChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void VideoComponent::onSizeChanged()
|
void VideoComponent::onSizeChanged()
|
||||||
{
|
{
|
||||||
// Update the embeded static image
|
// Update the embeded static image
|
||||||
|
@ -111,8 +191,6 @@ void VideoComponent::setImage(std::string path)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
mStaticImage.setImage(path);
|
mStaticImage.setImage(path);
|
||||||
// Make the image stretch to fill the video region
|
|
||||||
mStaticImage.setSize(getSize());
|
|
||||||
mFadeIn = 0.0f;
|
mFadeIn = 0.0f;
|
||||||
mStaticImagePath = path;
|
mStaticImagePath = path;
|
||||||
}
|
}
|
||||||
|
@ -243,11 +321,15 @@ void VideoComponent::applyTheme(const std::shared_ptr<ThemeData>& theme, const s
|
||||||
{
|
{
|
||||||
Eigen::Vector2f denormalized = elem->get<Eigen::Vector2f>("pos").cwiseProduct(scale);
|
Eigen::Vector2f denormalized = elem->get<Eigen::Vector2f>("pos").cwiseProduct(scale);
|
||||||
setPosition(Eigen::Vector3f(denormalized.x(), denormalized.y(), 0));
|
setPosition(Eigen::Vector3f(denormalized.x(), denormalized.y(), 0));
|
||||||
|
mStaticImage.setPosition(Eigen::Vector3f(denormalized.x(), denormalized.y(), 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((properties & ThemeFlags::SIZE) && elem->has("size"))
|
if(properties & ThemeFlags::SIZE)
|
||||||
{
|
{
|
||||||
setSize(elem->get<Eigen::Vector2f>("size").cwiseProduct(scale));
|
if(elem->has("size"))
|
||||||
|
setResize(elem->get<Eigen::Vector2f>("size").cwiseProduct(scale));
|
||||||
|
else if(elem->has("maxSize"))
|
||||||
|
setMaxSize(elem->get<Eigen::Vector2f>("maxSize").cwiseProduct(scale));
|
||||||
}
|
}
|
||||||
|
|
||||||
// position + size also implies origin
|
// position + size also implies origin
|
||||||
|
@ -265,11 +347,6 @@ void VideoComponent::applyTheme(const std::shared_ptr<ThemeData>& theme, const s
|
||||||
|
|
||||||
if (elem->has("showSnapshotDelay"))
|
if (elem->has("showSnapshotDelay"))
|
||||||
mConfig.showSnapshotDelay = elem->get<bool>("showSnapshotDelay");
|
mConfig.showSnapshotDelay = elem->get<bool>("showSnapshotDelay");
|
||||||
|
|
||||||
// Update the embeded static image
|
|
||||||
mStaticImage.setPosition(getPosition());
|
|
||||||
mStaticImage.setMaxSize(getSize());
|
|
||||||
mStaticImage.setSize(getSize());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<HelpPrompt> VideoComponent::getHelpPrompts()
|
std::vector<HelpPrompt> VideoComponent::getHelpPrompts()
|
||||||
|
@ -287,6 +364,7 @@ void VideoComponent::setupContext()
|
||||||
mContext.surface = SDL_CreateRGBSurface(SDL_SWSURFACE, (int)mVideoWidth, (int)mVideoHeight, 32, 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff);
|
mContext.surface = SDL_CreateRGBSurface(SDL_SWSURFACE, (int)mVideoWidth, (int)mVideoHeight, 32, 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff);
|
||||||
mContext.mutex = SDL_CreateMutex();
|
mContext.mutex = SDL_CreateMutex();
|
||||||
mContext.valid = true;
|
mContext.valid = true;
|
||||||
|
resize();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -55,6 +55,19 @@ public:
|
||||||
void onSizeChanged() override;
|
void onSizeChanged() override;
|
||||||
void setOpacity(unsigned char opacity) override;
|
void setOpacity(unsigned char opacity) override;
|
||||||
|
|
||||||
|
// Resize the video to fit this size. If one axis is zero, scale that axis to maintain aspect ratio.
|
||||||
|
// If both are non-zero, potentially break the aspect ratio. If both are zero, no resizing.
|
||||||
|
// Can be set before or after a video is loaded.
|
||||||
|
// setMaxSize() and setResize() are mutually exclusive.
|
||||||
|
void setResize(float width, float height);
|
||||||
|
inline void setResize(const Eigen::Vector2f& size) { setResize(size.x(), size.y()); }
|
||||||
|
|
||||||
|
// Resize the video to be as large as possible but fit within a box of this size.
|
||||||
|
// Can be set before or after a video is loaded.
|
||||||
|
// Never breaks the aspect ratio. setMaxSize() and setResize() are mutually exclusive.
|
||||||
|
void setMaxSize(float width, float height);
|
||||||
|
inline void setMaxSize(const Eigen::Vector2f& size) { setMaxSize(size.x(), size.y()); }
|
||||||
|
|
||||||
void render(const Eigen::Affine3f& parentTrans) override;
|
void render(const Eigen::Affine3f& parentTrans) override;
|
||||||
|
|
||||||
virtual void applyTheme(const std::shared_ptr<ThemeData>& theme, const std::string& view, const std::string& element, unsigned int properties) override;
|
virtual void applyTheme(const std::shared_ptr<ThemeData>& theme, const std::string& view, const std::string& element, unsigned int properties) override;
|
||||||
|
@ -67,6 +80,10 @@ public:
|
||||||
virtual void update(int deltaTime);
|
virtual void update(int deltaTime);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
// Calculates the correct mSize from our resizing information (set by setResize/setMaxSize).
|
||||||
|
// Used internally whenever the resizing parameters or texture change.
|
||||||
|
void resize();
|
||||||
|
|
||||||
// Start the video Immediately
|
// Start the video Immediately
|
||||||
void startVideo();
|
void startVideo();
|
||||||
// Start the video after any configured delay
|
// Start the video after any configured delay
|
||||||
|
@ -94,6 +111,7 @@ private:
|
||||||
unsigned mVideoWidth;
|
unsigned mVideoWidth;
|
||||||
unsigned mVideoHeight;
|
unsigned mVideoHeight;
|
||||||
Eigen::Vector2f mOrigin;
|
Eigen::Vector2f mOrigin;
|
||||||
|
Eigen::Vector2f mTargetSize;
|
||||||
std::shared_ptr<TextureResource> mTexture;
|
std::shared_ptr<TextureResource> mTexture;
|
||||||
float mFadeIn;
|
float mFadeIn;
|
||||||
std::string mStaticImagePath;
|
std::string mStaticImagePath;
|
||||||
|
@ -105,6 +123,7 @@ private:
|
||||||
unsigned mStartTime;
|
unsigned mStartTime;
|
||||||
bool mIsPlaying;
|
bool mIsPlaying;
|
||||||
bool mShowing;
|
bool mShowing;
|
||||||
|
bool mTargetIsMax;
|
||||||
|
|
||||||
Configuration mConfig;
|
Configuration mConfig;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue