Skip to content

Commit

Permalink
Add support for image cropping inside ctrlImageButton
Browse files Browse the repository at this point in the history
  • Loading branch information
tehKaiN committed Sep 21, 2022
1 parent 0537322 commit e16f5f6
Show file tree
Hide file tree
Showing 10 changed files with 113 additions and 25 deletions.
41 changes: 36 additions & 5 deletions libs/s25main/controls/ctrlBaseImage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
6 changes: 4 additions & 2 deletions libs/s25main/controls/ctrlBaseImage.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,10 @@ 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;

/// Draw the image on specified rectangular area. The image is centered inside dstArea and cropped to its size.
void DrawImage(const Rect& dstArea) const;
void DrawImage(const Rect& dstArea, unsigned color) const;

private:
ITexture* img_;
Expand Down
2 changes: 1 addition & 1 deletion libs/s25main/controls/ctrlImage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ ctrlImage::~ctrlImage() = default;
*/
void ctrlImage::Draw_()
{
DrawImage(GetDrawPos());
DrawImage(Rect(GetDrawPos(), GetImageRect().getSize()));
}

bool ctrlImage::Msg_MouseMove(const MouseCoords& mc)
Expand Down
21 changes: 18 additions & 3 deletions libs/s25main/controls/ctrlImageButton.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,26 @@ ctrlImageButton::ctrlImageButton(Window* parent, unsigned id, const DrawPoint& p

void ctrlImageButton::DrawContent() const
{
DrawPoint pos = GetDrawPos() + DrawPoint(GetSize()) / 2;
auto pos = GetDrawPos() - GetImageRect().getOrigin();
auto size = GetSize();

if(hasBorder)
{
// Ensure that 3D border is not drawn on
const unsigned borderThickness = 2;
pos += DrawPoint::all(borderThickness);
size -= Extent::all(2 * borderThickness);
}

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);
}
5 changes: 5 additions & 0 deletions libs/s25main/ogl/ITexture.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#pragma once

#include "Point.h"
#include "Rect.h"

class ITexture
{
Expand All @@ -15,4 +16,8 @@ class ITexture
virtual Position GetOrigin() const = 0;
virtual Extent GetSize() const = 0;
virtual void DrawFull(const Position& dstPos, unsigned color = 0xFFFFFFFFu) = 0;

/// Draws portion of image specified by srcArea on area defined by dstArea.
/// In case of srcArea and dstArea size mismatch, scaling will occur.
virtual void Draw(Rect dstArea, Rect srcArea, unsigned color = 0xFFFFFFFFu) = 0;
};
8 changes: 4 additions & 4 deletions libs/s25main/ogl/glArchivItem_Bitmap.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
};
5 changes: 5 additions & 0 deletions libs/s25main/ogl/glArchivItem_Bitmap_Player.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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*/)
{
Expand Down
1 change: 1 addition & 0 deletions libs/s25main/ogl/glArchivItem_Bitmap_Player.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
46 changes: 36 additions & 10 deletions libs/s25main/ogl/glSmartBitmap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 <glad/glad.h>
#include <cmath>
#include <limits>

namespace {
Expand Down Expand Up @@ -240,12 +242,32 @@ 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)
{
// 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);
}

void glSmartBitmap::drawRect(Rect dstArea, Rect srcArea, unsigned color /*= 0xFFFFFFFF*/, unsigned player_color /*= 0*/)
{
if(!texture)
{
Expand All @@ -255,35 +277,39 @@ 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<Point<GLfloat>, 8> vertices, curTexCoords;
std::array<GL_RGBAColor, 8> colors;

auto drawPt = dstArea.getOrigin();
drawPt -= origin_;
vertices[2] = Point<GLfloat>(drawPt) + size_;
vertices[2] = Point<GLfloat>(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);
colors[0].b = GetBlue(color);
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)
Expand Down
3 changes: 3 additions & 0 deletions libs/s25main/ogl/glSmartBitmap.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down

0 comments on commit e16f5f6

Please sign in to comment.