Skip to content
5 changes: 5 additions & 0 deletions libs/common/include/Point.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,11 @@ using Position = Point<int>;
/// Type for describing an extent/size etc. (unsigned type)
using Extent = Point<unsigned>;
using PointF = Point<float>;
/// Type for describing limiting scaling factors for GUI elements (unsigned type)
/// Limits scaling from Base Resolution 800x600 to fit screen size in a granularity of 10
/// Valid range is from 1 up to 10, values outside the range don't impose any limiting
/// e. g. Value 1: scales 1/10 of the difference between screensize and Base Resolution
using LimitFactors = Point<unsigned>;
//-V:all:810

//////////////////////////////////////////////////////////////////////////
Expand Down
38 changes: 29 additions & 9 deletions libs/s25main/RescaleWindowProp.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ struct ScaleWindowPropUp
ScaleWindowPropUp(const Extent& size) : size(size) {}

template<typename T_Pt>
static T_Pt scale(const T_Pt& value, const Extent& size);
static T_Pt scale(const T_Pt& value, const Extent& size, const LimitFactors& limfactors);
template<typename T_Pt>
T_Pt operator()(const T_Pt& value) const;
};
Expand All @@ -24,30 +24,50 @@ struct RescaleWindowProp
RescaleWindowProp(Extent oldSize, Extent newSize) : oldSize(oldSize), newSize(newSize) {}
/// Scale the point or size from beeing relative to the oldSize to relative to the newSize
template<typename T_Pt>
T_Pt operator()(const T_Pt& oldValue) const;
T_Pt operator()(const T_Pt& oldValue, const LimitFactors& limfactors) const;
};

template<typename T_Pt>
inline T_Pt ScaleWindowPropUp::scale(const T_Pt& value, const Extent& sizeToScale)
inline T_Pt ScaleWindowPropUp::scale(const T_Pt& value, const Extent& sizeToScale, const LimitFactors& limfactors)
{
return T_Pt(value * sizeToScale / Extent(800, 600));
if(limfactors.x > 0 && limfactors.x < 11 && limfactors.y > 0 && limfactors.y < 11)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we (should) try to avoid magic numbers, make the 11 a constant please,

also if using a std::optional, the test would be much simpler (is set & assertion for >0 only)

{
T_Pt diff(sizeToScale - Extent(800, 600));
T_Pt limScaledValue(value * (sizeToScale - diff * limfactors / 10) / Extent(800, 600));
return limScaledValue;
} else
{
T_Pt scaledValue(value * sizeToScale / Extent(800, 600));
return scaledValue;
}
}

template<typename T_Pt>
inline T_Pt ScaleWindowPropUp::operator()(const T_Pt& value) const
{
return scale(value, size);
return scale(value, size, LimitFactors(0, 0));
}

template<typename T_Pt>
inline T_Pt RescaleWindowProp::operator()(const T_Pt& oldValue) const
inline T_Pt RescaleWindowProp::operator()(const T_Pt& oldValue, const LimitFactors& limfactors) const
{
T_Pt realValue(oldValue.x * 800 / oldSize.x, oldValue.y * 600 / oldSize.y);
T_Pt realValue;
if(limfactors.x > 0 && limfactors.x < 11 && limfactors.y > 0 && limfactors.y < 11)
{
T_Pt diff(oldSize - Extent(800, 600));
T_Pt limUnscaleValue(oldValue.x * 800 / (oldSize.x - (diff.x * limfactors.x / 10)),
oldValue.y * 600 / (oldSize.y - (diff.y * limfactors.y / 10)));
realValue = limUnscaleValue;
} else
{
T_Pt unscaleValue(oldValue.x * 800 / oldSize.x, oldValue.y * 600 / oldSize.y);
realValue = unscaleValue;
}
// Check for rounding errors
T_Pt checkValue = ScaleWindowPropUp::scale(realValue, oldSize);
T_Pt checkValue = ScaleWindowPropUp::scale(realValue, oldSize, limfactors);
if(checkValue.x < oldValue.x)
realValue.x++;
if(checkValue.y < oldValue.y)
realValue.y++;
return ScaleWindowPropUp::scale(realValue, newSize);
return ScaleWindowPropUp::scale(realValue, newSize, limfactors);
}
37 changes: 28 additions & 9 deletions libs/s25main/Window.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@
#include <boost/range/adaptor/reversed.hpp>
#include <cstdarg>

Window::Window(Window* parent, unsigned id, const DrawPoint& pos, const Extent& size)
: parent_(parent), id_(id), pos_(pos), size_(size), active_(false), visible_(true), scale_(false),
isInMouseRelay(false), animations_(this)
Window::Window(Window* parent, unsigned id, const DrawPoint& pos, const LimitFactors& size)
: parent_(parent), id_(id), pos_(pos), size_(size), limitFactors_(LimitFactors(0, 0)), active_(false),
visible_(true), scale_(false), isInMouseRelay(false), animations_(this)
{}

Window::~Window()
Expand Down Expand Up @@ -65,6 +65,16 @@ Extent Window::GetSize() const
return size_;
}

LimitFactors Window::GetLimitFactors() const
{
return limitFactors_;
}

void Window::SetLimitFactors(LimitFactors limitFactors)
{
limitFactors_ = limitFactors;
}

Rect Window::GetDrawRect() const
{
return Rect(GetDrawPos(), GetSize());
Expand Down Expand Up @@ -220,7 +230,7 @@ ctrlBuildingIcon* Window::AddBuildingIcon(unsigned id, const DrawPoint& pos, Bui
ctrlButton* Window::AddTextButton(unsigned id, const DrawPoint& pos, const Extent& size, const TextureColor tc,
const std::string& text, const glFont* font, const std::string& tooltip)
{
return AddCtrl(new ctrlTextButton(this, id, ScaleIf(pos), ScaleIf(size), tc, text, font, tooltip));
return AddCtrl(new ctrlTextButton(this, id, pos, size, tc, text, font, tooltip, LimitFactors(7, 5)));
}

ctrlButton* Window::AddColorButton(unsigned id, const DrawPoint& pos, const Extent& size, const TextureColor tc,
Expand Down Expand Up @@ -540,24 +550,33 @@ void Window::Msg_ScreenResize(const ScreenResizeEvent& sr)
if(!ctrl)
continue;
// Save new size (could otherwise be changed(?) in Msg_ScreenResize)
Extent newSize = rescale(ctrl->GetSize());
ctrl->SetPos(rescale(ctrl->GetPos()));
Extent newSize = rescale(ctrl->GetSize(), ctrl->GetLimitFactors());
ctrl->SetPos(rescale(ctrl->GetPos(), LimitFactors(0, 0)));
ctrl->Msg_ScreenResize(sr);
ctrl->Resize(newSize);
}
animations_.onRescale(sr);
}

template<class T_Pt>
T_Pt Window::Scale(const T_Pt& pt)
T_Pt Window::Scale(const T_Pt& pt, const LimitFactors& limfactors)
{
return ScaleWindowPropUp::scale(pt, VIDEODRIVER.GetRenderSize());
return ScaleWindowPropUp::scale(pt, VIDEODRIVER.GetRenderSize(), limfactors);
}

void Window::ScaleByFactor()
{
if(scale_)
{
pos_ = ScaleWindowPropUp::scale(pos_, VIDEODRIVER.GetRenderSize(), LimitFactors(0, 0));
size_ = ScaleWindowPropUp::scale(size_, VIDEODRIVER.GetRenderSize(), limitFactors_);
}
}

template<class T_Pt>
T_Pt Window::ScaleIf(const T_Pt& pt) const
{
return scale_ ? Scale(pt) : pt;
return scale_ ? Scale(pt, LimitFactors(0, 0)) : pt;
}

// Inlining removes those. so add it here
Expand Down
27 changes: 18 additions & 9 deletions libs/s25main/Window.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ class Window
DrawPoint GetDrawPos() const;
/// Get the size of the window
Extent GetSize() const;
/// Get the Limit Factors for scaling
LimitFactors GetLimitFactors() const;
/// gets the extent of the window in absolute coordinates
Rect GetDrawRect() const;
/// Get the actual extents of the rect (might be different to the draw rect if the window resizes according to
Expand All @@ -86,6 +88,8 @@ class Window
void SetWidth(unsigned width) { Resize(Extent(width, size_.y)); }
/// setzt die Höhe des Fensters
void SetHeight(unsigned height) { Resize(Extent(size_.x, height)); }
/// Set the Limit Factors for scaling
void SetLimitFactors(LimitFactors limitFactors);
/// Sendet eine Tastaturnachricht an die Steuerelemente.
bool RelayKeyboardMessage(KeyboardMsgHandler msg, const KeyEvent& ke);
/// Sendet eine Mausnachricht weiter an alle Steuerelemente
Expand Down Expand Up @@ -286,9 +290,11 @@ class Window
friend constexpr auto maxEnumValue(ButtonState) { return ButtonState::Pressed; }
using ControlMap = std::map<unsigned, Window*>;

/// scales X- und Y values to fit the screen
/// scales X- and Y values to fit the screen, additionally considering a limiting factor for size
template<class T_Pt>
static T_Pt Scale(const T_Pt& pt);
static T_Pt Scale(const T_Pt& pt, const LimitFactors& limfactors);
/// scales X- and Y values of pos_ and size_, additionally considering limitFactors_ for size_ scaling
void ScaleByFactor();
/// Scales the value when scale_ is true, else returns the value
template<class T_Pt>
T_Pt ScaleIf(const T_Pt& pt) const;
Expand All @@ -300,13 +306,14 @@ class Window
virtual bool IsMessageRelayAllowed() const;

private:
Window* const parent_; /// Handle auf das Parentfenster.
unsigned id_; /// ID des Fensters.
DrawPoint pos_; /// Position des Fensters.
Extent size_; /// Höhe des Fensters.
bool active_; /// Fenster aktiv?
bool visible_; /// Fenster sichtbar?
bool scale_; /// Sollen Controls an Fenstergröße angepasst werden?
Window* const parent_; /// Handle auf das Parentfenster.
unsigned id_; /// ID des Fensters.
DrawPoint pos_; /// Position des Fensters.
Extent size_; /// Höhe des Fensters.
LimitFactors limitFactors_; /// X and Y scaling limiting factors
bool active_; /// Fenster aktiv?
bool visible_; /// Fenster sichtbar?
bool scale_; /// Sollen Controls an Fenstergröße angepasst werden?

std::map<Window*, Rect> lockedAreas_; /// gesperrte Regionen des Fensters.
std::vector<Window*> tofreeAreas_;
Expand All @@ -322,6 +329,8 @@ inline T* Window::AddCtrl(T* ctrl)
childIdToWnd_.insert(std::make_pair(ctrl->GetID(), ctrl));

ctrl->scale_ = scale_;
if(ctrl->limitFactors_ != LimitFactors(0, 0))
ctrl->ScaleByFactor();
ctrl->SetActive(active_);

return ctrl;
Expand Down
4 changes: 2 additions & 2 deletions libs/s25main/animation/MoveAnimation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ MoveAnimation::MoveAnimation(Window* element, DrawPoint newPos, unsigned animTim
void MoveAnimation::onRescale(const ScreenResizeEvent& rs)
{
RescaleWindowProp rescale(rs.oldSize, rs.newSize);
origPos_ = rescale(origPos_);
newPos_ = rescale(newPos_);
origPos_ = rescale(origPos_, LimitFactors(0, 0));
newPos_ = rescale(newPos_, LimitFactors(0, 0));
}

void MoveAnimation::doUpdate(Window* element, double nextFramepartTime)
Expand Down
6 changes: 4 additions & 2 deletions libs/s25main/controls/ctrlTextButton.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,11 @@ static constexpr unsigned contentOffset = 2;

ctrlTextButton::ctrlTextButton(Window* parent, unsigned id, const DrawPoint& pos, const Extent& size,
const TextureColor tc, const std::string& text, const glFont* font,
const std::string& tooltip)
const std::string& tooltip, const LimitFactors& limitFactors)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what about making it std::optional?

: ctrlButton(parent, id, pos, size, tc, tooltip), ctrlBaseText(text, COLOR_YELLOW, font)
{}
{
Window::SetLimitFactors(limitFactors);
}

void ctrlTextButton::ResizeForMaxChars(unsigned numChars)
{
Expand Down
3 changes: 2 additions & 1 deletion libs/s25main/controls/ctrlTextButton.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ class ctrlTextButton : public ctrlButton, public ctrlBaseText
{
public:
ctrlTextButton(Window* parent, unsigned id, const DrawPoint& pos, const Extent& size, TextureColor tc,
const std::string& text, const glFont* font, const std::string& tooltip);
const std::string& text, const glFont* font, const std::string& tooltip,
const LimitFactors& limitFactors);

/// Changes width so at most this many chars can be shown
void ResizeForMaxChars(unsigned numChars);
Expand Down
4 changes: 2 additions & 2 deletions tests/s25Main/UI/testControls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ BOOST_FIXTURE_TEST_CASE(MouseOver, uiHelper::Fixture)
const auto pos = rttr::test::randomPoint<DrawPoint>();
const auto size = rttr::test::randomPoint<Extent>(10);
const auto font = createMockFont({'H', 'e', 'l', 'o', '?'});
ctrlTextButton bt(nullptr, 1, pos, size, TextureColor::Bricks, "Hello", font.get(), "");
ctrlTextButton bt(nullptr, 1, pos, size, TextureColor::Bricks, "Hello", font.get(), "", LimitFactors(0, 0));
BOOST_TEST(bt.IsMouseOver(pos));
BOOST_TEST(!bt.IsMouseOver(pos - DrawPoint(1, 0)));
BOOST_TEST(!bt.IsMouseOver(pos - DrawPoint(0, 1)));
Expand Down Expand Up @@ -251,7 +251,7 @@ BOOST_AUTO_TEST_CASE(AdjustWidthForMaxChars_SetsCorrectSize)
}
{
ctrlTextButton txt(nullptr, 1, rttr::test::randomPoint<DrawPoint>(), rttr::test::randomPoint<Extent>(),
TextureColor::Green1, "foo", font.get(), "tooltip");
TextureColor::Green1, "foo", font.get(), "tooltip", LimitFactors(0, 0));
const Extent sizeBefore = txt.GetSize();
// Don't assume size, so get size for 0 chars
txt.ResizeForMaxChars(0);
Expand Down
Loading