From 5f8fc67cf651665cc0af0b6f8f95dfd4114be678 Mon Sep 17 00:00:00 2001 From: KaiN Date: Tue, 20 Sep 2022 17:44:17 +0200 Subject: [PATCH] Add support for image cropping inside ctrlImageButton --- libs/s25main/controls/ctrlBaseImage.cpp | 41 ++++++++++++++-- libs/s25main/controls/ctrlBaseImage.h | 4 +- libs/s25main/controls/ctrlImage.cpp | 2 +- libs/s25main/controls/ctrlImageButton.cpp | 13 +++-- libs/s25main/ogl/ITexture.h | 2 + libs/s25main/ogl/glArchivItem_Bitmap.h | 8 ++-- .../ogl/glArchivItem_Bitmap_Player.cpp | 5 ++ libs/s25main/ogl/glArchivItem_Bitmap_Player.h | 1 + libs/s25main/ogl/glSmartBitmap.cpp | 48 ++++++++++++++----- libs/s25main/ogl/glSmartBitmap.h | 3 ++ 10 files changed, 101 insertions(+), 26 deletions(-) diff --git a/libs/s25main/controls/ctrlBaseImage.cpp b/libs/s25main/controls/ctrlBaseImage.cpp index 8be298836..dc31e6db2 100644 --- a/libs/s25main/controls/ctrlBaseImage.cpp +++ b/libs/s25main/controls/ctrlBaseImage.cpp @@ -20,13 +20,44 @@ Rect ctrlBaseImage::GetImageRect() const return Rect(-img_->GetOrigin(), img_->GetSize()); } -void ctrlBaseImage::DrawImage(const DrawPoint& pos) const +void ctrlBaseImage::DrawImage(const Rect& dstArea) const { - DrawImage(pos, modulationColor_); + DrawImage(dstArea, modulationColor_); } -void ctrlBaseImage::DrawImage(const DrawPoint& pos, unsigned color) const +void ctrlBaseImage::DrawImage(const Rect& dstArea, unsigned color) const { - if(img_) - img_->DrawFull(pos, color); + if(img_ == nullptr) + return; + + auto dst = dstArea; + auto imageSize = img_->GetSize(); + auto dstSize = dstArea.getSize(); + Rect srcArea = Rect(DrawPoint::all(0), imageSize); + + if(imageSize.x > dstSize.x) + { + auto halfDelta = (imageSize.x - dstSize.x) / 2; + srcArea.left += halfDelta; + srcArea.right -= halfDelta; + } else if(imageSize.x < dstSize.x) + { + auto halfDelta = (dstSize.x - imageSize.x) / 2; + dst.left += halfDelta; + dst.right -= halfDelta; + } + + if(imageSize.y > dstSize.y) + { + auto halfDelta = (imageSize.y - dstSize.y) / 2; + srcArea.top += halfDelta; + srcArea.bottom -= halfDelta; + } else if(imageSize.y < dstSize.y) + { + auto halfDelta = (dstSize.y - imageSize.y) / 2; + dst.top += halfDelta; + dst.bottom -= halfDelta; + } + + img_->Draw(dst, srcArea, color); } diff --git a/libs/s25main/controls/ctrlBaseImage.h b/libs/s25main/controls/ctrlBaseImage.h index 55d919139..ef3e167af 100644 --- a/libs/s25main/controls/ctrlBaseImage.h +++ b/libs/s25main/controls/ctrlBaseImage.h @@ -24,8 +24,8 @@ class ctrlBaseImage /// Swap the images of those controls void SwapImage(ctrlBaseImage& other); Rect GetImageRect() const; - void DrawImage(const DrawPoint& pos) const; - void DrawImage(const DrawPoint& pos, unsigned color) const; + void DrawImage(const Rect& dstArea) const; + void DrawImage(const Rect& dstArea, unsigned color) const; private: ITexture* img_; diff --git a/libs/s25main/controls/ctrlImage.cpp b/libs/s25main/controls/ctrlImage.cpp index c87d4a1a5..8b9cefe6b 100644 --- a/libs/s25main/controls/ctrlImage.cpp +++ b/libs/s25main/controls/ctrlImage.cpp @@ -17,7 +17,7 @@ ctrlImage::~ctrlImage() = default; */ void ctrlImage::Draw_() { - DrawImage(GetDrawPos()); + DrawImage(Rect(GetDrawPos(), GetImageRect().getSize())); } bool ctrlImage::Msg_MouseMove(const MouseCoords& mc) diff --git a/libs/s25main/controls/ctrlImageButton.cpp b/libs/s25main/controls/ctrlImageButton.cpp index f4a0639df..e03726a4b 100644 --- a/libs/s25main/controls/ctrlImageButton.cpp +++ b/libs/s25main/controls/ctrlImageButton.cpp @@ -11,11 +11,18 @@ ctrlImageButton::ctrlImageButton(Window* parent, unsigned id, const DrawPoint& p void ctrlImageButton::DrawContent() const { - DrawPoint pos = GetDrawPos() + DrawPoint(GetSize()) / 2; + DrawPoint pos = GetDrawPos() - GetImageRect().getOrigin() + DrawPoint::all(2); + Extent size = GetSize() - Extent::all(4); + if((state == ButtonState::Pressed || isChecked) && isEnabled) + { pos += DrawPoint::all(2); + size -= Extent::all(2); + } + + Rect drawRect(pos, size); if(!isEnabled && GetModulationColor() == COLOR_WHITE) - DrawImage(pos, 0xFF555555); + DrawImage(drawRect, 0xFF555555); else - DrawImage(pos); + DrawImage(drawRect); } diff --git a/libs/s25main/ogl/ITexture.h b/libs/s25main/ogl/ITexture.h index 256797ca6..529cbdb0a 100644 --- a/libs/s25main/ogl/ITexture.h +++ b/libs/s25main/ogl/ITexture.h @@ -5,6 +5,7 @@ #pragma once #include "Point.h" +#include "Rect.h" class ITexture { @@ -15,4 +16,5 @@ class ITexture virtual Position GetOrigin() const = 0; virtual Extent GetSize() const = 0; virtual void DrawFull(const Position& dstPos, unsigned color = 0xFFFFFFFFu) = 0; + virtual void Draw(Rect dstArea, Rect srcArea, unsigned color = 0xFFFFFFFFu) = 0; }; diff --git a/libs/s25main/ogl/glArchivItem_Bitmap.h b/libs/s25main/ogl/glArchivItem_Bitmap.h index b78353964..21d95b29a 100644 --- a/libs/s25main/ogl/glArchivItem_Bitmap.h +++ b/libs/s25main/ogl/glArchivItem_Bitmap.h @@ -26,14 +26,14 @@ class glArchivItem_Bitmap : public virtual libsiedler2::baseArchivItem_Bitmap, p void DrawPart(const Rect& destArea, const DrawPoint& offset, unsigned color = COLOR_WHITE); /// Draw a rectangular part of the texture from the origin of it void DrawPart(const Rect& destArea, unsigned color = COLOR_WHITE); - /// Draw only percent% of the height of the image + /// Draw only percent% of the height of the image, counting from the bottom of the image void DrawPercent(const DrawPoint& dstPos, unsigned percent, unsigned color = COLOR_WHITE); - -protected: /// Draw the texture. /// src_w/h default to the full bitmap size /// dst_w/h default the src_w/h - void Draw(Rect dstArea, Rect srcArea, unsigned color = COLOR_WHITE); + void Draw(Rect dstArea, Rect srcArea, unsigned color = COLOR_WHITE) override; + +protected: void FillTexture() override; Extent CalcTextureSize() const override; }; diff --git a/libs/s25main/ogl/glArchivItem_Bitmap_Player.cpp b/libs/s25main/ogl/glArchivItem_Bitmap_Player.cpp index b60261fe9..f064e28a9 100644 --- a/libs/s25main/ogl/glArchivItem_Bitmap_Player.cpp +++ b/libs/s25main/ogl/glArchivItem_Bitmap_Player.cpp @@ -42,6 +42,11 @@ void glArchivItem_Bitmap_Player::drawForPlayer(const DrawPoint& dst, unsigned pl DrawFull(dst, COLOR_WHITE, playerColor); } +void glArchivItem_Bitmap_Player::Draw(Rect dstArea, Rect srcArea, unsigned color /*= COLOR_WHITE*/) +{ + Draw(dstArea, srcArea, color, COLOR_WHITE); +} + void glArchivItem_Bitmap_Player::Draw(Rect dstArea, Rect srcArea, unsigned color /*= COLOR_WHITE*/, unsigned player_color /*= COLOR_WHITE*/) { diff --git a/libs/s25main/ogl/glArchivItem_Bitmap_Player.h b/libs/s25main/ogl/glArchivItem_Bitmap_Player.h index ec04a9bcb..2ab87505b 100644 --- a/libs/s25main/ogl/glArchivItem_Bitmap_Player.h +++ b/libs/s25main/ogl/glArchivItem_Bitmap_Player.h @@ -29,6 +29,7 @@ class glArchivItem_Bitmap_Player : public libsiedler2::ArchivItem_Bitmap_Player, virtual void DrawFull(const Position& dstPos, unsigned color = COLOR_WHITE) override; /// Draw in player colors void drawForPlayer(const DrawPoint& dst, unsigned playerColor); + void Draw(Rect dstArea, Rect srcArea, unsigned color = COLOR_WHITE) override; protected: void Draw(Rect dstArea, Rect srcArea, unsigned color = COLOR_WHITE, unsigned player_color = COLOR_WHITE); diff --git a/libs/s25main/ogl/glSmartBitmap.cpp b/libs/s25main/ogl/glSmartBitmap.cpp index 29d12ae1f..bae24759a 100644 --- a/libs/s25main/ogl/glSmartBitmap.cpp +++ b/libs/s25main/ogl/glSmartBitmap.cpp @@ -5,12 +5,14 @@ #include "glSmartBitmap.h" #include "Loader.h" #include "drivers/VideoDriverWrapper.h" +#include "helpers/mathFuncs.h" #include "ogl/glBitmapItem.h" #include "libsiedler2/ArchivItem_Bitmap.h" #include "libsiedler2/ArchivItem_Bitmap_Player.h" #include "libsiedler2/PixelBufferBGRA.h" #include "s25util/colors.h" #include +#include #include namespace { @@ -240,12 +242,17 @@ void glSmartBitmap::generateTexture() } } +void glSmartBitmap::Draw(Rect dstArea, Rect srcArea, unsigned color /*= 0xFFFFFFFF*/) +{ + drawRect(dstArea, srcArea, color); +} + void glSmartBitmap::draw(DrawPoint drawPt, unsigned color, unsigned player_color) { drawPercent(drawPt, 100, color, player_color); } -void glSmartBitmap::drawPercent(DrawPoint drawPt, unsigned percent, unsigned color, unsigned player_color) +void glSmartBitmap::drawRect(Rect dstArea, Rect srcArea, unsigned color /*= 0xFFFFFFFF*/, unsigned player_color /*= 0*/) { if(!texture) { @@ -255,23 +262,18 @@ void glSmartBitmap::drawPercent(DrawPoint drawPt, unsigned percent, unsigned col return; } - // nothing to draw? - if(!percent) - return; - RTTR_Assert(percent <= 100); - - const float partDrawn = percent / 100.f; std::array, 8> vertices, curTexCoords; std::array colors; + auto drawPt = dstArea.getOrigin(); drawPt -= origin_; - vertices[2] = Point(drawPt) + size_; + vertices[2] = Point(dstArea.getEndPt() - origin_); // destination bottom vertices[0].x = vertices[1].x = GLfloat(drawPt.x); vertices[3].x = vertices[2].x; - vertices[0].y = vertices[3].y = GLfloat(drawPt.y + size_.y * (1.f - partDrawn)); - vertices[1].y = vertices[2].y; + vertices[0].y = vertices[3].y = GLfloat(drawPt.y); // destination top + vertices[1].y = vertices[2].y; // destination bottom colors[0].r = GetRed(color); colors[0].g = GetGreen(color); @@ -279,11 +281,20 @@ void glSmartBitmap::drawPercent(DrawPoint drawPt, unsigned percent, unsigned col colors[0].a = GetAlpha(color); colors[3] = colors[2] = colors[1] = colors[0]; + // vertical coords curTexCoords[0] = texCoords[0]; curTexCoords[1] = texCoords[1]; curTexCoords[2] = texCoords[2]; curTexCoords[3] = texCoords[3]; - curTexCoords[0].y = curTexCoords[3].y = curTexCoords[1].y - (curTexCoords[1].y - curTexCoords[0].y) * partDrawn; + curTexCoords[0].y = curTexCoords[3].y = helpers::lerp( + texCoords[0].y, texCoords[1].y, helpers::inverseLerp(.0f, float(size_.y), float(srcArea.getOrigin().y))); + curTexCoords[1].y = curTexCoords[2].y = helpers::lerp( + texCoords[0].y, texCoords[1].y, helpers::inverseLerp(.0f, float(size_.y), float(srcArea.getEndPt().y))); + // horizontal coords + curTexCoords[0].x = curTexCoords[1].x = helpers::lerp( + texCoords[0].x, texCoords[3].x, helpers::inverseLerp(.0f, float(size_.x), float(srcArea.getOrigin().x))); + curTexCoords[2].x = curTexCoords[3].x = helpers::lerp( + texCoords[0].x, texCoords[3].x, helpers::inverseLerp(.0f, float(size_.x), float(srcArea.getEndPt().x))); int numQuads; if(player_color && hasPlayer) @@ -314,3 +325,18 @@ void glSmartBitmap::drawPercent(DrawPoint drawPt, unsigned percent, unsigned col glDrawArrays(GL_QUADS, 0, numQuads); glDisableClientState(GL_COLOR_ARRAY); } + +void glSmartBitmap::drawPercent(DrawPoint drawPt, unsigned percent, unsigned color, unsigned player_color) +{ + // nothing to draw? + if(!percent) + return; + RTTR_Assert(percent <= 100); + + const float partDrawn = percent / 100.f; + auto startY = int(std::floor(size_.y * (1 - partDrawn))); + auto endY = int(std::ceil(size_.y * partDrawn)); + Rect dstArea(drawPt.x, drawPt.y + startY, size_.x, endY); + Rect srcArea(0, startY, size_.x, endY); + drawRect(dstArea, srcArea, color, player_color); +} diff --git a/libs/s25main/ogl/glSmartBitmap.h b/libs/s25main/ogl/glSmartBitmap.h index 7fd6c6323..27201fc12 100644 --- a/libs/s25main/ogl/glSmartBitmap.h +++ b/libs/s25main/ogl/glSmartBitmap.h @@ -59,8 +59,11 @@ class glSmartBitmap : public ITexture void generateTexture(); void DrawFull(const Position& dstPos, unsigned color = 0xFFFFFFFF) override { draw(dstPos, color); } + void Draw(Rect dstArea, Rect srcArea, unsigned color = 0xFFFFFFFF) override; + void drawRect(Rect dstArea, Rect srcArea, unsigned color = 0xFFFFFFFF, unsigned player_color = 0); void draw(DrawPoint drawPt, unsigned color = 0xFFFFFFFF, unsigned player_color = 0); void drawForPlayer(DrawPoint drawPt, unsigned player_color) { draw(drawPt, 0xFFFFFFFF, player_color); } + /// Draw only percent% of the height of the image, counting from the bottom of the image void drawPercent(DrawPoint drawPt, unsigned percent, unsigned color = 0xFFFFFFFF, unsigned player_color = 0); /// Draw the bitmap(s) to the specified buffer at the position starting at bufOffset (must be positive) void drawTo(libsiedler2::PixelBufferBGRA& buffer, const Extent& bufOffset = Extent(0, 0)) const;