AGS: Gui controls draw themselves at requested offset

From upstream 9e9c8ffafe465b907ed0d22bcb1ba4df06803b8b
This commit is contained in:
Paul Gilbert 2022-04-29 21:54:19 -07:00
parent 673c8c242e
commit 62ebde86a1
15 changed files with 86 additions and 85 deletions

View File

@ -39,7 +39,7 @@ int GUIInvWindow::GetCharacterId() const {
return CharId;
}
void GUIInvWindow::Draw(Bitmap *ds) {
void GUIInvWindow::Draw(Bitmap *ds, int x, int y) {
const bool enabled = IsGUIEnabled(this);
if (!enabled && (GUI::Options.DisabledStyle == kGuiDis_Blackout))
return;
@ -56,9 +56,9 @@ void GUIInvWindow::Draw(Bitmap *ds) {
TopItem = _GP(play).inv_top;
// draw the items
const int leftmost_x = X;
int at_x = X;
int at_y = Y;
const int leftmost_x = x;
int at_x = x;
int at_y = y;
int lastItem = TopItem + (ColCount * RowCount);
if (lastItem > _G(charextra)[GetCharacterId()].invorder_count)
lastItem = _G(charextra)[GetCharacterId()].invorder_count;
@ -76,10 +76,10 @@ void GUIInvWindow::Draw(Bitmap *ds) {
}
if (!enabled &&
GUI::Options.DisabledStyle == kGuiDis_Greyout &&
_GP(play).inventory_greys_out == 1) {
GUI::Options.DisabledStyle == kGuiDis_Greyout &&
_GP(play).inventory_greys_out == 1) {
// darken the inventory when disabled
GUI::DrawDisabledEffect(ds, RectWH(X, Y, Width, Height));
GUI::DrawDisabledEffect(ds, RectWH(x, y, Width, Height));
}
}

View File

@ -114,12 +114,12 @@ size_t GUILabel::SplitLinesForDrawing(SplitLines &lines) {
return break_up_text_into_lines(_textToDraw.GetCStr(), lines, Width, Font);
}
void GUITextBox::DrawTextBoxContents(Bitmap *ds, color_t text_color) {
wouttext_outline(ds, X + 1 + get_fixed_pixel_size(1), Y + 1 + get_fixed_pixel_size(1), Font, text_color, Text.GetCStr());
void GUITextBox::DrawTextBoxContents(Bitmap *ds, int x, int y, color_t text_color) {
wouttext_outline(ds, x + 1 + get_fixed_pixel_size(1), y + 1 + get_fixed_pixel_size(1), Font, text_color, Text.GetCStr());
if (IsGUIEnabled(this)) {
// draw a cursor
int draw_at_x = get_text_width(Text.GetCStr(), Font) + X + 3;
int draw_at_y = Y + 1 + get_font_height(Font);
int draw_at_x = get_text_width(Text.GetCStr(), Font) + x + 3;
int draw_at_y = y + 1 + get_font_height(Font);
ds->DrawRect(Rect(draw_at_x, draw_at_y, draw_at_x + get_fixed_pixel_size(5), draw_at_y + (get_fixed_pixel_size(1) - 1)), text_color);
}
}

View File

@ -93,7 +93,7 @@ bool GUIButton::IsClippingImage() const {
return (Flags & kGUICtrl_Clip) != 0;
}
void GUIButton::Draw(Bitmap *ds) {
void GUIButton::Draw(Bitmap *ds, int x, int y) {
bool draw_disabled = !IsGUIEnabled(this);
// if it's "Unchanged when disabled" or "GUI Off", don't grey out
@ -111,10 +111,10 @@ void GUIButton::Draw(Bitmap *ds) {
// CHECKME: why testing both CurrentImage and Image?
if (CurrentImage > 0 && IsImageButton())
DrawImageButton(ds, draw_disabled);
DrawImageButton(ds, x, y, draw_disabled);
// CHECKME: why don't draw frame if no Text? this will make button completely invisible!
else if (!_text.IsEmpty())
DrawTextButton(ds, draw_disabled);
DrawTextButton(ds, x, y, draw_disabled);
}
void GUIButton::SetClipImage(bool on) {
@ -282,19 +282,19 @@ void GUIButton::WriteToSavegame(Stream *out) const {
out->WriteInt32(CurrentImage);
}
void GUIButton::DrawImageButton(Bitmap *ds, bool draw_disabled) {
void GUIButton::DrawImageButton(Bitmap *ds, int x, int y, bool draw_disabled) {
// NOTE: the CLIP flag only clips the image, not the text
if (IsClippingImage() && !GUI::Options.ClipControls)
ds->SetClip(RectWH(X, Y, Width, Height));
ds->SetClip(RectWH(x, y, Width, Height));
if (_GP(spriteset)[CurrentImage] != nullptr)
draw_gui_sprite(ds, CurrentImage, X, Y, true);
draw_gui_sprite(ds, CurrentImage, x, y, true);
// Draw active inventory item
if (_placeholder != kButtonPlace_None && _G(gui_inv_pic) >= 0) {
GUIButtonPlaceholder place = _placeholder;
if (place == kButtonPlace_InvItemAuto) {
if ((get_adjusted_spritewidth(_G(gui_inv_pic)) > Width - 6) ||
(get_adjusted_spriteheight(_G(gui_inv_pic)) > Height - 6)) {
(get_adjusted_spriteheight(_G(gui_inv_pic)) > Height - 6)) {
place = kButtonPlace_InvItemStretch;
} else {
place = kButtonPlace_InvItemCenter;
@ -302,38 +302,39 @@ void GUIButton::DrawImageButton(Bitmap *ds, bool draw_disabled) {
}
if (place == kButtonPlace_InvItemStretch) {
ds->StretchBlt(_GP(spriteset)[_G(gui_inv_pic)], RectWH(X + 3, Y + 3, Width - 6, Height - 6), Shared::kBitmap_Transparency);
ds->StretchBlt(_GP(spriteset)[_G(gui_inv_pic)], RectWH(x + 3, y + 3, Width - 6, Height - 6),
kBitmap_Transparency);
} else if (place == kButtonPlace_InvItemCenter) {
draw_gui_sprite(ds, _G(gui_inv_pic),
X + Width / 2 - get_adjusted_spritewidth(_G(gui_inv_pic)) / 2,
Y + Height / 2 - get_adjusted_spriteheight(_G(gui_inv_pic)) / 2,
true);
x + Width / 2 - get_adjusted_spritewidth(_G(gui_inv_pic)) / 2,
y + Height / 2 - get_adjusted_spriteheight(_G(gui_inv_pic)) / 2,
true);
}
}
if ((draw_disabled) && (GUI::Options.DisabledStyle == kGuiDis_Greyout)) {
// darken the button when disabled
GUI::DrawDisabledEffect(ds, RectWH(X, Y,
_GP(spriteset)[CurrentImage]->GetWidth(),
_GP(spriteset)[CurrentImage]->GetHeight()));
GUI::DrawDisabledEffect(ds, RectWH(x, y,
_GP(spriteset)[CurrentImage]->GetWidth(),
_GP(spriteset)[CurrentImage]->GetHeight()));
}
// Don't print Text of (INV) (INVSHR) (INVNS)
if (_placeholder == kButtonPlace_None && !_unnamed)
DrawText(ds, draw_disabled);
DrawText(ds, x, y, draw_disabled);
if (IsClippingImage() && !GUI::Options.ClipControls)
ds->ResetClip();
}
void GUIButton::DrawText(Bitmap *ds, bool draw_disabled) {
void GUIButton::DrawText(Bitmap *ds, int x, int y, bool draw_disabled) {
if (_text.IsEmpty())
return;
// TODO: need to find a way to cache Text prior to drawing;
// but that will require to update all gui controls when translation is changed in game
PrepareTextToDraw();
Rect frame = RectWH(X + 2, Y + 2, Width - 4, Height - 4);
Rect frame = RectWH(x + 2, y + 2, Width - 4, Height - 4);
if (IsPushed && IsMouseOver) {
// move the Text a bit while pushed
frame.Left++;
@ -345,12 +346,12 @@ void GUIButton::DrawText(Bitmap *ds, bool draw_disabled) {
GUI::DrawTextAligned(ds, _textToDraw.GetCStr(), Font, text_color, frame, TextAlignment);
}
void GUIButton::DrawTextButton(Bitmap *ds, bool draw_disabled) {
void GUIButton::DrawTextButton(Bitmap *ds, int x, int y, bool draw_disabled) {
color_t draw_color = ds->GetCompatibleColor(7);
ds->FillRect(Rect(X, Y, X + Width - 1, Y + Height - 1), draw_color);
ds->FillRect(Rect(x, y, x + Width - 1, y + Height - 1), draw_color);
if (Flags & kGUICtrl_Default) {
draw_color = ds->GetCompatibleColor(16);
ds->DrawRect(Rect(X - 1, Y - 1, X + Width, Y + Height), draw_color);
ds->DrawRect(Rect(x - 1, y - 1, x + Width, y + Height), draw_color);
}
// TODO: use color constants instead of literal numbers
@ -359,18 +360,18 @@ void GUIButton::DrawTextButton(Bitmap *ds, bool draw_disabled) {
else
draw_color = ds->GetCompatibleColor(8);
ds->DrawLine(Line(X, Y + Height - 1, X + Width - 1, Y + Height - 1), draw_color);
ds->DrawLine(Line(X + Width - 1, Y, X + Width - 1, Y + Height - 1), draw_color);
ds->DrawLine(Line(x, y + Height - 1, x + Width - 1, y + Height - 1), draw_color);
ds->DrawLine(Line(x + Width - 1, y, x + Width - 1, y + Height - 1), draw_color);
if (draw_disabled || (IsMouseOver && IsPushed))
draw_color = ds->GetCompatibleColor(8);
else
draw_color = ds->GetCompatibleColor(15);
ds->DrawLine(Line(X, Y, X + Width - 1, Y), draw_color);
ds->DrawLine(Line(X, Y, X, Y + Height - 1), draw_color);
ds->DrawLine(Line(x, y, x + Width - 1, y), draw_color);
ds->DrawLine(Line(x, y, x, y + Height - 1), draw_color);
DrawText(ds, draw_disabled);
DrawText(ds, x, y, draw_disabled);
}
} // namespace Shared

View File

@ -67,7 +67,7 @@ public:
bool IsClippingImage() const;
// Operations
void Draw(Bitmap *ds) override;
void Draw(Bitmap *ds, int x = 0, int y = 0) override;
void SetClipImage(bool on);
void SetText(const String &text);
@ -102,9 +102,9 @@ public:
bool IsMouseOver;
private:
void DrawImageButton(Bitmap *ds, bool draw_disabled);
void DrawText(Bitmap *ds, bool draw_disabled);
void DrawTextButton(Bitmap *ds, bool draw_disabled);
void DrawImageButton(Bitmap *ds, int x, int y, bool draw_disabled);
void DrawText(Bitmap *ds, int x, int y, bool draw_disabled);
void DrawTextButton(Bitmap *ds, int x, int y, bool draw_disabled);
void PrepareTextToDraw();
// Defines button placeholder mode; the mode is set

View File

@ -38,7 +38,7 @@ public:
// Operations
// This function has distinct implementations in Engine and Editor
void Draw(Bitmap *ds) override;
void Draw(Bitmap *ds, int x = 0, int y = 0) override;
// Events
void OnMouseEnter() override;

View File

@ -48,7 +48,7 @@ GUILabelMacro GUILabel::GetTextMacros() const {
return _textMacro;
}
void GUILabel::Draw(Shared::Bitmap *ds) {
void GUILabel::Draw(Bitmap *ds, int x, int y) {
// TODO: need to find a way to cache text prior to drawing;
// but that will require to update all gui controls when translation is changed in game
PrepareTextToDraw();
@ -62,12 +62,12 @@ void GUILabel::Draw(Shared::Bitmap *ds) {
get_font_linespacing(Font);
// < 2.72 labels did not limit vertical size of text
const bool limit_by_label_frame = _G(loaded_game_file_version) >= kGameVersion_272;
int at_y = Y;
int at_y = y;
for (size_t i = 0;
i < _GP(Lines).Count() && (!limit_by_label_frame || at_y <= Y + Height);
++i, at_y += linespacing) {
GUI::DrawTextAlignedHor(ds, _GP(Lines)[i].GetCStr(), Font, text_color, X, X + Width - 1, at_y,
(FrameAlignment)TextAlignment);
i < _GP(Lines).Count() && (!limit_by_label_frame || at_y <= y + Height);
++i, at_y += linespacing) {
GUI::DrawTextAlignedHor(ds, _GP(Lines)[i].GetCStr(), Font, text_color, x, x + Width - 1, at_y,
(FrameAlignment)TextAlignment);
}
}

View File

@ -43,7 +43,7 @@ public:
GUILabelMacro GetTextMacros() const;
// Operations
void Draw(Bitmap *ds) override;
void Draw(Bitmap *ds, int x = 0, int y = 0) override;
void SetText(const String &text);
// Serialization

View File

@ -93,7 +93,7 @@ void GUIListBox::Clear() {
NotifyParentChanged();
}
void GUIListBox::Draw(Shared::Bitmap *ds) {
void GUIListBox::Draw(Bitmap *ds, int x, int y) {
const int width = Width - 1;
const int height = Height - 1;
const int pixel_size = get_fixed_pixel_size(1);
@ -101,60 +101,59 @@ void GUIListBox::Draw(Shared::Bitmap *ds) {
color_t text_color = ds->GetCompatibleColor(TextColor);
color_t draw_color = ds->GetCompatibleColor(TextColor);
if (IsBorderShown()) {
ds->DrawRect(Rect(X, Y, X + width + (pixel_size - 1), Y + height + (pixel_size - 1)), draw_color);
ds->DrawRect(Rect(x, y, x + width + (pixel_size - 1), y + height + (pixel_size - 1)), draw_color);
if (pixel_size > 1)
ds->DrawRect(Rect(X + 1, Y + 1, X + width, Y + height), draw_color);
ds->DrawRect(Rect(x + 1, y + 1, x + width, y + height), draw_color);
}
int right_hand_edge = (X + width) - pixel_size - 1;
int right_hand_edge = (x + width) - pixel_size - 1;
// update the RowHeight and VisibleItemCount
// FIXME: find a way to update this whenever relevant things change in the engine
UpdateMetrics();
// draw the scroll bar in if necessary
bool scrollbar = (ItemCount > VisibleItemCount &&IsBorderShown() && AreArrowsShown());
bool scrollbar = (ItemCount > VisibleItemCount) && IsBorderShown() && AreArrowsShown();
if (scrollbar) {
int xstrt, ystrt;
ds->DrawRect(Rect(X + width - get_fixed_pixel_size(7), Y, (X + (pixel_size - 1) + width) - get_fixed_pixel_size(7), Y + height), draw_color);
ds->DrawRect(Rect(X + width - get_fixed_pixel_size(7), Y + height / 2, X + width, Y + height / 2 + (pixel_size - 1)), draw_color);
ds->DrawRect(Rect(x + width - get_fixed_pixel_size(7), y, (x + (pixel_size - 1) + width) - get_fixed_pixel_size(7), y + height), draw_color);
ds->DrawRect(Rect(x + width - get_fixed_pixel_size(7), y + height / 2, x + width, y + height / 2 + (pixel_size - 1)), draw_color);
xstrt = (X + width - get_fixed_pixel_size(6)) + (pixel_size - 1);
ystrt = (Y + height - 3) - get_fixed_pixel_size(5);
xstrt = (x + width - get_fixed_pixel_size(6)) + (pixel_size - 1);
ystrt = (y + height - 3) - get_fixed_pixel_size(5);
draw_color = ds->GetCompatibleColor(TextColor);
ds->DrawTriangle(Triangle(xstrt, ystrt, xstrt + get_fixed_pixel_size(4), ystrt,
xstrt + get_fixed_pixel_size(2),
ystrt + get_fixed_pixel_size(5)), draw_color);
xstrt + get_fixed_pixel_size(2),
ystrt + get_fixed_pixel_size(5)), draw_color);
ystrt = Y + 3;
ystrt = y + 3;
ds->DrawTriangle(Triangle(xstrt, ystrt + get_fixed_pixel_size(5),
xstrt + get_fixed_pixel_size(4),
ystrt + get_fixed_pixel_size(5),
xstrt + get_fixed_pixel_size(2), ystrt), draw_color);
xstrt + get_fixed_pixel_size(4),
ystrt + get_fixed_pixel_size(5),
xstrt + get_fixed_pixel_size(2), ystrt), draw_color);
right_hand_edge -= get_fixed_pixel_size(7);
}
Rect old_clip = ds->GetClip();
if (scrollbar && GUI::Options.ClipControls)
ds->SetClip(Rect(X, Y, right_hand_edge + 1, Y + Height - 1));
ds->SetClip(Rect(x, y, right_hand_edge + 1, y + Height - 1));
for (int item = 0; item < VisibleItemCount; ++item) {
if (item + TopItem >= ItemCount)
break;
int at_y = Y + pixel_size + item * RowHeight;
int at_y = y + pixel_size + item * RowHeight;
if (item + TopItem == SelectedItem) {
text_color = ds->GetCompatibleColor(SelectedTextColor);
if (SelectedBgColor > 0) {
int stretch_to = (X + width) - pixel_size;
int stretch_to = (x + width) - pixel_size;
// draw the SelectedItem item bar (if colour not transparent)
draw_color = ds->GetCompatibleColor(SelectedBgColor);
if ((VisibleItemCount < ItemCount) && IsBorderShown() && AreArrowsShown())
stretch_to -= get_fixed_pixel_size(7);
ds->FillRect(Rect(X + pixel_size, at_y, stretch_to, at_y + RowHeight - pixel_size), draw_color);
ds->FillRect(Rect(x + pixel_size, at_y, stretch_to, at_y + RowHeight - pixel_size), draw_color);
}
} else
text_color = ds->GetCompatibleColor(TextColor);
@ -162,8 +161,8 @@ void GUIListBox::Draw(Shared::Bitmap *ds) {
int item_index = item + TopItem;
PrepareTextToDraw(Items[item_index]);
GUI::DrawTextAlignedHor(ds, _textToDraw.GetCStr(), Font, text_color, X + 1 + pixel_size, right_hand_edge, at_y + 1,
(FrameAlignment)TextAlignment);
GUI::DrawTextAlignedHor(ds, _textToDraw.GetCStr(), Font, text_color, x + 1 + pixel_size, right_hand_edge, at_y + 1,
(FrameAlignment)TextAlignment);
}
ds->SetClip(old_clip);
}

View File

@ -43,7 +43,7 @@ public:
// Operations
int AddItem(const String &text);
void Clear();
void Draw(Bitmap *ds) override;
void Draw(Bitmap *ds, int x = 0, int y = 0) override;
int InsertItem(int index, const String &text);
void RemoveItem(int index);
void SetShowArrows(bool on);

View File

@ -257,7 +257,7 @@ void GUIMain::DrawWithControls(Bitmap *ds) {
ds->SetClip(RectWH(objToDraw->X, objToDraw->Y, objToDraw->Width, objToDraw->Height));
else
ds->ResetClip();
objToDraw->Draw(ds);
objToDraw->Draw(ds, objToDraw->X, objToDraw->Y);
int selectedColour = 14;

View File

@ -64,7 +64,8 @@ public:
virtual bool IsContentClipped() const { return true; }
// Operations
virtual void Draw(Bitmap *) {
virtual void Draw(Bitmap *ds, int x = 0, int y = 0) {
(void)ds; (void)x; (void)y;
}
void SetClickable(bool on);
void SetEnabled(bool on);

View File

@ -56,7 +56,7 @@ bool GUISlider::IsOverControl(int x, int y, int leeway) const {
return _cachedHandle.IsInside(Point(x, y));
}
void GUISlider::Draw(Shared::Bitmap *ds) {
void GUISlider::Draw(Bitmap *ds, int x, int y) {
// Clamp Value
// TODO: this is necessary here because some Slider fields are still public
if (MinValue >= MaxValue)
@ -95,7 +95,7 @@ void GUISlider::Draw(Shared::Bitmap *ds) {
if (IsHorizontal()) // horizontal slider
{
// Value pos is a coordinate corresponding to current slider's value
bar = RectWH(X + 1, Y + Height / 2 - thick_f, Width - 1, bar_thick);
bar = RectWH(x + 1, y + Height / 2 - thick_f, Width - 1, bar_thick);
handle_range = Width - 4;
int value_pos = (int)(((float)(Value - MinValue) * (float)handle_range) / (float)(MaxValue - MinValue));
handle = RectWH((bar.Left + get_fixed_pixel_size(2)) - (handle_sz.Width / 2) + 1 + value_pos - 2,
@ -105,7 +105,7 @@ void GUISlider::Draw(Shared::Bitmap *ds) {
}
// vertical slider
else {
bar = RectWH(X + Width / 2 - thick_f, Y + 1, bar_thick, Height - 1);
bar = RectWH(x + Width / 2 - thick_f, y + 1, bar_thick, Height - 1);
handle_range = Height - 4;
int value_pos = (int)(((float)(MaxValue - Value) * (float)handle_range) / (float)(MaxValue - MinValue));
handle = RectWH(bar.Left + (bar.GetWidth() - handle_sz.Width) / 2,
@ -122,11 +122,11 @@ void GUISlider::Draw(Shared::Bitmap *ds) {
if (IsHorizontal()) {
x_inc = get_adjusted_spritewidth(BgImage);
// centre the image vertically
bar.Top = Y + (Height / 2) - get_adjusted_spriteheight(BgImage) / 2;
bar.Top = y + (Height / 2) - get_adjusted_spriteheight(BgImage) / 2;
} else {
y_inc = get_adjusted_spriteheight(BgImage);
// centre the image horizontally
bar.Left = X + (Width / 2) - get_adjusted_spritewidth(BgImage) / 2;
bar.Left = x + (Width / 2) - get_adjusted_spritewidth(BgImage) / 2;
}
int cx = bar.Left;
int cy = bar.Top;

View File

@ -41,7 +41,7 @@ public:
bool IsOverControl(int x, int y, int leeway) const override;
// Operations
void Draw(Bitmap *ds) override;
void Draw(Bitmap *ds, int x = 0, int y = 0) override;
// Events
bool OnMouseDown() override;

View File

@ -47,16 +47,16 @@ bool GUITextBox::IsBorderShown() const {
return (TextBoxFlags & kTextBox_ShowBorder) != 0;
}
void GUITextBox::Draw(Bitmap *ds) {
void GUITextBox::Draw(Bitmap *ds, int x, int y) {
color_t text_color = ds->GetCompatibleColor(TextColor);
color_t draw_color = ds->GetCompatibleColor(TextColor);
if (IsBorderShown()) {
ds->DrawRect(RectWH(X, Y, Width, Height), draw_color);
ds->DrawRect(RectWH(x, y, Width, Height), draw_color);
if (get_fixed_pixel_size(1) > 1) {
ds->DrawRect(Rect(X + 1, Y + 1, X + Width - get_fixed_pixel_size(1), Y + Height - get_fixed_pixel_size(1)), draw_color);
ds->DrawRect(Rect(x + 1, y + 1, x + Width - get_fixed_pixel_size(1), y + Height - get_fixed_pixel_size(1)), draw_color);
}
}
DrawTextBoxContents(ds, text_color);
DrawTextBoxContents(ds, x, y, text_color);
}
// TODO: a shared utility function

View File

@ -37,7 +37,7 @@ public:
bool IsBorderShown() const;
// Operations
void Draw(Bitmap *ds) override;
void Draw(Bitmap *ds, int x = 0, int y = 0) override;
void SetShowBorder(bool on);
// Events
@ -58,7 +58,7 @@ public:
private:
int32_t TextBoxFlags;
void DrawTextBoxContents(Bitmap *ds, color_t text_color);
void DrawTextBoxContents(Bitmap *ds, int x, int y, color_t text_color);
};
} // namespace Shared