Merge pull request #412 from Koerty/crop-image-and-minsize

Add cropping and minSize to ImageComponent
This commit is contained in:
John Rassa 2018-04-12 19:15:13 -07:00 committed by GitHub
commit c7c828e47a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 115 additions and 17 deletions

View file

@ -56,7 +56,7 @@ public:
void setRotationOrigin(float originX, float originY);
inline void setRotationOrigin(Vector2f origin) { setRotationOrigin(origin.x(), origin.y()); }
Vector2f getSize() const;
virtual Vector2f getSize() const;
inline void setSize(const Vector2f& size) { setSize(size.x(), size.y()); }
void setSize(float w, float h);
virtual void onSizeChanged() {};

View file

@ -14,9 +14,15 @@ Vector2i ImageComponent::getTextureSize() const
return Vector2i::Zero();
}
Vector2f ImageComponent::getSize() const
{
return GuiComponent::getSize() * (mBottomRightCrop - mTopLeftCrop);
}
ImageComponent::ImageComponent(Window* window, bool forceLoad, bool dynamic) : GuiComponent(window),
mTargetIsMax(false), mFlipX(false), mFlipY(false), mTargetSize(0, 0), mColorShift(0xFFFFFFFF),
mForceLoad(forceLoad), mDynamic(dynamic), mFadeOpacity(0), mFading(false), mRotateByTargetSize(false)
mTargetIsMax(false), mTargetIsMin(false), mFlipX(false), mFlipY(false), mTargetSize(0, 0), mColorShift(0xFFFFFFFF),
mForceLoad(forceLoad), mDynamic(dynamic), mFadeOpacity(0), mFading(false), mRotateByTargetSize(false),
mTopLeftCrop(0.0f, 0.0f), mBottomRightCrop(1.0f, 1.0f)
{
updateColors();
}
@ -63,6 +69,31 @@ void ImageComponent::resize()
mSize[1] = Math::round(mSize[1]);
mSize[0] = (mSize[1] / textureSize.y()) * textureSize.x();
}else if(mTargetIsMin)
{
mSize = textureSize;
Vector2f resizeScale((mTargetSize.x() / mSize.x()), (mTargetSize.y() / mSize.y()));
if(resizeScale.x() > resizeScale.y())
{
mSize[0] *= resizeScale.x();
mSize[1] *= resizeScale.x();
float cropPercent = (mSize.y() - mTargetSize.y()) / (mSize.y() * 2);
crop(0, cropPercent, 0, cropPercent);
}else{
mSize[0] *= resizeScale.y();
mSize[1] *= resizeScale.y();
float cropPercent = (mSize.x() - mTargetSize.x()) / (mSize.x() * 2);
crop(cropPercent, 0, cropPercent, 0);
}
// for SVG rasterization, always calculate width from rounded height (see comment above)
mSize[1] = Math::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
@ -132,6 +163,7 @@ void ImageComponent::setResize(float width, float height)
{
mTargetSize = Vector2f(width, height);
mTargetIsMax = false;
mTargetIsMin = false;
resize();
}
@ -139,6 +171,15 @@ void ImageComponent::setMaxSize(float width, float height)
{
mTargetSize = Vector2f(width, height);
mTargetIsMax = true;
mTargetIsMin = false;
resize();
}
void ImageComponent::setMinSize(float width, float height)
{
mTargetSize = Vector2f(width, height);
mTargetIsMax = false;
mTargetIsMin = true;
resize();
}
@ -152,6 +193,43 @@ void ImageComponent::setRotateByTargetSize(bool rotate)
mRotateByTargetSize = rotate;
}
void ImageComponent::cropLeft(float percent)
{
assert(percent >= 0.0f && percent <= 1.0f);
mTopLeftCrop.x() = percent;
}
void ImageComponent::cropTop(float percent)
{
assert(percent >= 0.0f && percent <= 1.0f);
mTopLeftCrop.y() = percent;
}
void ImageComponent::cropRight(float percent)
{
assert(percent >= 0.0f && percent <= 1.0f);
mBottomRightCrop.x() = 1.0f - percent;
}
void ImageComponent::cropBot(float percent)
{
assert(percent >= 0.0f && percent <= 1.0f);
mBottomRightCrop.y() = 1.0f - percent;
}
void ImageComponent::crop(float left, float top, float right, float bot)
{
cropLeft(left);
cropTop(top);
cropRight(right);
cropBot(bot);
}
void ImageComponent::uncrop()
{
crop(0, 0, 0, 0);
}
void ImageComponent::setFlipX(bool flip)
{
mFlipX = flip;
@ -187,8 +265,9 @@ void ImageComponent::updateVertices()
// we go through this mess to make sure everything is properly rounded
// if we just round vertices at the end, edge cases occur near sizes of 0.5
Vector2f topLeft(0.0, 0.0);
Vector2f bottomRight(Math::round(mSize.x()), Math::round(mSize.y()));
Vector2f size(Math::round(mSize.x()), Math::round(mSize.y()));
Vector2f topLeft(size * mTopLeftCrop);
Vector2f bottomRight(size * mBottomRightCrop);
mVertices[0].pos = Vector2f(topLeft.x(), topLeft.y());
mVertices[1].pos = Vector2f(topLeft.x(), bottomRight.y());
@ -208,23 +287,23 @@ void ImageComponent::updateVertices()
py = 1;
}
mVertices[0].tex = Vector2f(0, py);
mVertices[1].tex = Vector2f(0, 0);
mVertices[2].tex = Vector2f(px, py);
mVertices[0].tex = Vector2f(mTopLeftCrop.x(), py - mTopLeftCrop.y());
mVertices[1].tex = Vector2f(mTopLeftCrop.x(), 1 - mBottomRightCrop.y());
mVertices[2].tex = Vector2f(px * mBottomRightCrop.x(), py - mTopLeftCrop.y());
mVertices[3].tex = Vector2f(px, py);
mVertices[4].tex = Vector2f(0, 0);
mVertices[5].tex = Vector2f(px, 0);
mVertices[3].tex = Vector2f(px * mBottomRightCrop.x(), py - mTopLeftCrop.y());
mVertices[4].tex = Vector2f(mTopLeftCrop.x(), 1 - mBottomRightCrop.y());
mVertices[5].tex = Vector2f(px * mBottomRightCrop.x(), 1 - mBottomRightCrop.y());
if(mFlipX)
{
for(int i = 0; i < 6; i++)
mVertices[i].tex[0] = mVertices[i].tex[0] == px ? 0 : px;
mVertices[i].tex[0] = px - mVertices[i].tex[0];
}
if(mFlipY)
{
for(int i = 0; i < 6; i++)
mVertices[i].tex[1] = mVertices[i].tex[1] == py ? 0 : py;
mVertices[i].tex[1] = py - mVertices[i].tex[1];
}
}
@ -352,6 +431,8 @@ void ImageComponent::applyTheme(const std::shared_ptr<ThemeData>& theme, const s
setResize(elem->get<Vector2f>("size") * scale);
else if(elem->has("maxSize"))
setMaxSize(elem->get<Vector2f>("maxSize") * scale);
else if(elem->has("minSize"))
setMinSize(elem->get<Vector2f>("minSize") * scale);
}
// position + size also implies origin

View file

@ -40,8 +40,20 @@ public:
void setMaxSize(float width, float height);
inline void setMaxSize(const Vector2f& size) { setMaxSize(size.x(), size.y()); }
void setMinSize(float width, float height);
inline void setMinSize(const Vector2f& size) { setMinSize(size.x(), size.y()); }
Vector2f getRotationSize() const override;
// Applied AFTER image positioning and sizing
// cropTop(0.2) will crop 20% of the top of the image.
void cropLeft(float percent);
void cropTop(float percent);
void cropRight(float percent);
void cropBot(float percent);
void crop(float left, float top, float right, float bot);
void uncrop();
// Multiply all pixels in the image by this color when rendering.
void setColorShift(unsigned int color);
@ -53,6 +65,8 @@ public:
// Returns the size of the current texture, or (0, 0) if none is loaded. May be different than drawn size (use getSize() for that).
Vector2i getTextureSize() const;
Vector2f getSize() const override;
bool hasImage();
void render(const Transform4x4f& parentTrans) override;
@ -63,7 +77,7 @@ public:
private:
Vector2f mTargetSize;
bool mFlipX, mFlipY, mTargetIsMax;
bool mFlipX, mFlipY, mTargetIsMax, mTargetIsMin;
// Calculates the correct mSize from our resizing information (set by setResize/setMaxSize).
// Used internally whenever the resizing parameters or texture change.
@ -86,11 +100,14 @@ private:
std::string mDefaultPath;
std::shared_ptr<TextureResource> mTexture;
unsigned char mFadeOpacity;
bool mFading;
bool mForceLoad;
unsigned char mFadeOpacity;
bool mFading;
bool mForceLoad;
bool mDynamic;
bool mRotateByTargetSize;
Vector2f mTopLeftCrop;
Vector2f mBottomRightCrop;
};
#endif // ES_CORE_COMPONENTS_IMAGE_COMPONENT_H