Initial commit
This commit is contained in:
483
engines/ags/shared/gui/gui_button.cpp
Normal file
483
engines/ags/shared/gui/gui_button.cpp
Normal file
@@ -0,0 +1,483 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ags/shared/ac/sprite_cache.h"
|
||||
#include "ags/shared/ac/game_struct_defines.h"
|
||||
#include "ags/shared/font/fonts.h"
|
||||
#include "ags/shared/gui/gui_button.h"
|
||||
#include "ags/shared/gui/gui_main.h" // TODO: extract helper functions
|
||||
#include "ags/shared/util/stream.h"
|
||||
#include "ags/shared/util/string_utils.h"
|
||||
#include "ags/globals.h"
|
||||
|
||||
namespace AGS3 {
|
||||
namespace AGS {
|
||||
namespace Shared {
|
||||
|
||||
FrameAlignment ConvertLegacyButtonAlignment(LegacyButtonAlignment align) {
|
||||
switch (align) {
|
||||
case kLegacyButtonAlign_TopCenter:
|
||||
return kAlignTopCenter;
|
||||
case kLegacyButtonAlign_TopLeft:
|
||||
return kAlignTopLeft;
|
||||
case kLegacyButtonAlign_TopRight:
|
||||
return kAlignTopRight;
|
||||
case kLegacyButtonAlign_CenterLeft:
|
||||
return kAlignMiddleLeft;
|
||||
case kLegacyButtonAlign_Centered:
|
||||
return kAlignMiddleCenter;
|
||||
case kLegacyButtonAlign_CenterRight:
|
||||
return kAlignMiddleRight;
|
||||
case kLegacyButtonAlign_BottomLeft:
|
||||
return kAlignBottomLeft;
|
||||
case kLegacyButtonAlign_BottomCenter:
|
||||
return kAlignBottomCenter;
|
||||
case kLegacyButtonAlign_BottomRight:
|
||||
return kAlignBottomRight;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return kAlignNone;
|
||||
}
|
||||
|
||||
|
||||
GUIButton::GUIButton() {
|
||||
_image = -1;
|
||||
_mouseOverImage = -1;
|
||||
_pushedImage = -1;
|
||||
_currentImage = -1;
|
||||
Font = 0;
|
||||
TextColor = 0;
|
||||
TextAlignment = kAlignTopCenter;
|
||||
ClickAction[kGUIClickLeft] = kGUIAction_RunScript;
|
||||
ClickAction[kGUIClickRight] = kGUIAction_RunScript;
|
||||
ClickData[kGUIClickLeft] = 0;
|
||||
ClickData[kGUIClickRight] = 0;
|
||||
|
||||
IsPushed = false;
|
||||
IsMouseOver = false;
|
||||
_placeholder = kButtonPlace_None;
|
||||
_unnamed = true;
|
||||
|
||||
_scEventCount = 1;
|
||||
_scEventNames[0] = "Click";
|
||||
_scEventArgs[0] = "GUIControl *control, MouseButton button";
|
||||
}
|
||||
|
||||
bool GUIButton::HasAlphaChannel() const {
|
||||
return ((_currentImage > 0) && is_sprite_alpha(_currentImage)) ||
|
||||
(!_unnamed && is_font_antialiased(Font));
|
||||
}
|
||||
|
||||
int32_t GUIButton::GetCurrentImage() const {
|
||||
return _currentImage;
|
||||
}
|
||||
|
||||
int32_t GUIButton::GetNormalImage() const {
|
||||
return _image;
|
||||
}
|
||||
|
||||
int32_t GUIButton::GetMouseOverImage() const {
|
||||
return _mouseOverImage;
|
||||
}
|
||||
|
||||
int32_t GUIButton::GetPushedImage() const {
|
||||
return _pushedImage;
|
||||
}
|
||||
|
||||
GUIButtonPlaceholder GUIButton::GetPlaceholder() const {
|
||||
return _placeholder;
|
||||
}
|
||||
|
||||
const String &GUIButton::GetText() const {
|
||||
return _text;
|
||||
}
|
||||
|
||||
bool GUIButton::IsImageButton() const {
|
||||
return _image > 0;
|
||||
}
|
||||
|
||||
bool GUIButton::IsClippingImage() const {
|
||||
return (Flags & kGUICtrl_Clip) != 0;
|
||||
}
|
||||
|
||||
Rect GUIButton::CalcGraphicRect(bool clipped) {
|
||||
if (clipped)
|
||||
return RectWH(0, 0, _width, _height);
|
||||
|
||||
// TODO: need to find a way to cache image and text position, or there'll be some repetition
|
||||
Rect rc = RectWH(0, 0, _width, _height);
|
||||
if (IsImageButton()) {
|
||||
if (IsClippingImage())
|
||||
return rc;
|
||||
// Main button graphic
|
||||
if (_currentImage >= 0 && _GP(spriteset).DoesSpriteExist(_currentImage))
|
||||
rc = SumRects(rc, RectWH(0, 0, get_adjusted_spritewidth(_currentImage), get_adjusted_spriteheight(_currentImage)));
|
||||
// Optionally merge with the inventory pic
|
||||
if (_placeholder != kButtonPlace_None && _G(gui_inv_pic) >= 0) {
|
||||
Size inv_sz = Size(get_adjusted_spritewidth(_G(gui_inv_pic)),
|
||||
get_adjusted_spriteheight(_G(gui_inv_pic)));
|
||||
GUIButtonPlaceholder place = _placeholder;
|
||||
if (place == kButtonPlace_InvItemAuto) {
|
||||
place = ((inv_sz.Width > _width - 6) || (inv_sz.Height > _height - 6)) ?
|
||||
kButtonPlace_InvItemStretch : kButtonPlace_InvItemCenter;
|
||||
}
|
||||
|
||||
Rect inv_rc = (place == kButtonPlace_InvItemStretch) ?
|
||||
RectWH(0 + 3, 0 + 3, _width - 6, _height - 6) :
|
||||
RectWH(0 + _width / 2 - inv_sz.Width / 2,
|
||||
0 + _height / 2 - inv_sz.Height / 2,
|
||||
inv_sz.Width, inv_sz.Height);
|
||||
rc = SumRects(rc, inv_rc);
|
||||
}
|
||||
}
|
||||
// Optionally merge with the button text
|
||||
if (!IsImageButton() || ((_placeholder == kButtonPlace_None) && !_unnamed)) {
|
||||
PrepareTextToDraw();
|
||||
Rect frame = RectWH(0 + 2, 0 + 2, _width - 4, _height - 4);
|
||||
if (IsPushed && IsMouseOver) {
|
||||
frame.Left++;
|
||||
frame.Top++;
|
||||
}
|
||||
rc = SumRects(rc, GUI::CalcTextGraphicalRect(_textToDraw.GetCStr(), Font, frame, TextAlignment));
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
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
|
||||
if ((GUI::Options.DisabledStyle == kGuiDis_Unchanged) ||
|
||||
(GUI::Options.DisabledStyle == kGuiDis_Off)) {
|
||||
draw_disabled = false;
|
||||
}
|
||||
// TODO: should only change properties in reaction to particular events
|
||||
if (_currentImage <= 0 || draw_disabled)
|
||||
_currentImage = _image;
|
||||
|
||||
if (draw_disabled && (GUI::Options.DisabledStyle == kGuiDis_Blackout))
|
||||
// buttons off when disabled - no point carrying on
|
||||
return;
|
||||
|
||||
if (IsImageButton())
|
||||
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, x, y, draw_disabled);
|
||||
}
|
||||
|
||||
void GUIButton::SetClipImage(bool on) {
|
||||
if (on != ((Flags & kGUICtrl_Clip) != 0))
|
||||
MarkChanged();
|
||||
if (on)
|
||||
Flags |= kGUICtrl_Clip;
|
||||
else
|
||||
Flags &= ~kGUICtrl_Clip;
|
||||
}
|
||||
|
||||
void GUIButton::SetCurrentImage(int32_t image) {
|
||||
if (_currentImage == image)
|
||||
return;
|
||||
|
||||
_currentImage = image;
|
||||
MarkChanged();
|
||||
}
|
||||
|
||||
void GUIButton::SetMouseOverImage(int32_t image) {
|
||||
if (_mouseOverImage == image)
|
||||
return;
|
||||
|
||||
_mouseOverImage = image;
|
||||
UpdateCurrentImage();
|
||||
}
|
||||
|
||||
void GUIButton::SetNormalImage(int32_t image) {
|
||||
if (_image == image)
|
||||
return;
|
||||
|
||||
_image = image;
|
||||
UpdateCurrentImage();
|
||||
}
|
||||
|
||||
void GUIButton::SetPushedImage(int32_t image) {
|
||||
if (_pushedImage == image)
|
||||
return;
|
||||
|
||||
_pushedImage = image;
|
||||
UpdateCurrentImage();
|
||||
}
|
||||
|
||||
void GUIButton::SetImages(int32_t normal, int32_t over, int32_t pushed) {
|
||||
_image = normal;
|
||||
_mouseOverImage = over;
|
||||
_pushedImage = pushed;
|
||||
UpdateCurrentImage();
|
||||
}
|
||||
|
||||
void GUIButton::SetText(const String &text) {
|
||||
if (_text == text)
|
||||
return;
|
||||
|
||||
_text = text;
|
||||
// Active inventory item placeholders
|
||||
if (_text.CompareNoCase("(INV)") == 0)
|
||||
// Stretch to fit button
|
||||
_placeholder = kButtonPlace_InvItemStretch;
|
||||
else if (_text.CompareNoCase("(INVNS)") == 0)
|
||||
// Draw at actual size
|
||||
_placeholder = kButtonPlace_InvItemCenter;
|
||||
else if (_text.CompareNoCase("(INVSHR)") == 0)
|
||||
// Stretch if too big, actual size if not
|
||||
_placeholder = kButtonPlace_InvItemAuto;
|
||||
else
|
||||
_placeholder = kButtonPlace_None;
|
||||
|
||||
// TODO: find a way to remove this bogus limitation ("New Button" is a valid Text too)
|
||||
_unnamed = _text.IsEmpty() || _text.Compare("New Button") == 0;
|
||||
MarkChanged();
|
||||
}
|
||||
|
||||
bool GUIButton::OnMouseDown() {
|
||||
if (!IsImageButton())
|
||||
MarkChanged();
|
||||
IsPushed = true;
|
||||
UpdateCurrentImage();
|
||||
return false;
|
||||
}
|
||||
|
||||
void GUIButton::OnMouseEnter() {
|
||||
if (IsPushed && !IsImageButton())
|
||||
MarkChanged();
|
||||
IsMouseOver = true;
|
||||
UpdateCurrentImage();
|
||||
}
|
||||
|
||||
void GUIButton::OnMouseLeave() {
|
||||
if (IsPushed && !IsImageButton())
|
||||
MarkChanged();
|
||||
IsMouseOver = false;
|
||||
UpdateCurrentImage();
|
||||
}
|
||||
|
||||
void GUIButton::OnMouseUp() {
|
||||
if (IsMouseOver) {
|
||||
if (IsGUIEnabled(this) && IsClickable())
|
||||
IsActivated = true;
|
||||
}
|
||||
if (IsPushed && !IsImageButton())
|
||||
MarkChanged();
|
||||
IsPushed = false;
|
||||
UpdateCurrentImage();
|
||||
}
|
||||
|
||||
void GUIButton::UpdateCurrentImage() {
|
||||
int new_image = _currentImage;
|
||||
|
||||
if (IsPushed && (_pushedImage > 0)) {
|
||||
new_image = _pushedImage;
|
||||
} else if (IsMouseOver && (_mouseOverImage > 0)) {
|
||||
new_image = _mouseOverImage;
|
||||
} else {
|
||||
new_image = _image;
|
||||
}
|
||||
|
||||
SetCurrentImage(new_image);
|
||||
}
|
||||
|
||||
void GUIButton::WriteToFile(Stream *out) const {
|
||||
GUIObject::WriteToFile(out);
|
||||
|
||||
out->WriteInt32(_image);
|
||||
out->WriteInt32(_mouseOverImage);
|
||||
out->WriteInt32(_pushedImage);
|
||||
out->WriteInt32(Font);
|
||||
out->WriteInt32(TextColor);
|
||||
out->WriteInt32(ClickAction[kGUIClickLeft]);
|
||||
out->WriteInt32(ClickAction[kGUIClickRight]);
|
||||
out->WriteInt32(ClickData[kGUIClickLeft]);
|
||||
out->WriteInt32(ClickData[kGUIClickRight]);
|
||||
|
||||
StrUtil::WriteString(_text, out);
|
||||
out->WriteInt32(TextAlignment);
|
||||
}
|
||||
|
||||
void GUIButton::ReadFromFile(Stream *in, GuiVersion gui_version) {
|
||||
GUIObject::ReadFromFile(in, gui_version);
|
||||
|
||||
_image = in->ReadInt32();
|
||||
_mouseOverImage = in->ReadInt32();
|
||||
_pushedImage = in->ReadInt32();
|
||||
if (gui_version < kGuiVersion_350) { // NOTE: reading into actual variables only for old savegame support
|
||||
_currentImage = in->ReadInt32();
|
||||
IsPushed = in->ReadInt32() != 0;
|
||||
IsMouseOver = in->ReadInt32() != 0;
|
||||
}
|
||||
Font = in->ReadInt32();
|
||||
TextColor = in->ReadInt32();
|
||||
ClickAction[kGUIClickLeft] = (GUIClickAction)in->ReadInt32();
|
||||
ClickAction[kGUIClickRight] = (GUIClickAction)in->ReadInt32();
|
||||
ClickData[kGUIClickLeft] = in->ReadInt32();
|
||||
ClickData[kGUIClickRight] = in->ReadInt32();
|
||||
if (gui_version < kGuiVersion_350)
|
||||
SetText(String::FromStreamCount(in, GUIBUTTON_LEGACY_TEXTLENGTH));
|
||||
else
|
||||
SetText(StrUtil::ReadString(in));
|
||||
|
||||
if (gui_version >= kGuiVersion_272a) {
|
||||
if (gui_version < kGuiVersion_350) {
|
||||
TextAlignment = ConvertLegacyButtonAlignment((LegacyButtonAlignment)in->ReadInt32());
|
||||
in->ReadInt32(); // reserved1
|
||||
} else {
|
||||
TextAlignment = (FrameAlignment)in->ReadInt32();
|
||||
}
|
||||
} else {
|
||||
TextAlignment = kAlignTopCenter;
|
||||
}
|
||||
|
||||
if (TextColor == 0)
|
||||
TextColor = 16;
|
||||
_currentImage = _image;
|
||||
}
|
||||
|
||||
void GUIButton::ReadFromSavegame(Stream *in, GuiSvgVersion svg_ver) {
|
||||
GUIObject::ReadFromSavegame(in, svg_ver);
|
||||
// Properties
|
||||
_image = in->ReadInt32();
|
||||
_mouseOverImage = in->ReadInt32();
|
||||
_pushedImage = in->ReadInt32();
|
||||
Font = in->ReadInt32();
|
||||
TextColor = in->ReadInt32();
|
||||
SetText(StrUtil::ReadString(in));
|
||||
if (svg_ver >= kGuiSvgVersion_350)
|
||||
TextAlignment = (FrameAlignment)in->ReadInt32();
|
||||
// Dynamic state
|
||||
_currentImage = in->ReadInt32();
|
||||
|
||||
// Update current state after reading
|
||||
IsPushed = false;
|
||||
IsMouseOver = false;
|
||||
}
|
||||
|
||||
void GUIButton::WriteToSavegame(Stream *out) const {
|
||||
// Properties
|
||||
GUIObject::WriteToSavegame(out);
|
||||
out->WriteInt32(_image);
|
||||
out->WriteInt32(_mouseOverImage);
|
||||
out->WriteInt32(_pushedImage);
|
||||
out->WriteInt32(Font);
|
||||
out->WriteInt32(TextColor);
|
||||
StrUtil::WriteString(GetText(), out);
|
||||
out->WriteInt32(TextAlignment);
|
||||
// Dynamic state
|
||||
out->WriteInt32(_currentImage);
|
||||
}
|
||||
|
||||
void GUIButton::DrawImageButton(Bitmap *ds, int x, int y, bool draw_disabled) {
|
||||
assert(_currentImage >= 0);
|
||||
// NOTE: the CLIP flag only clips the image, not the text
|
||||
if (IsClippingImage() && !GUI::Options.ClipControls)
|
||||
ds->SetClip(RectWH(x, y, _width, _height));
|
||||
if (_GP(spriteset).DoesSpriteExist(_currentImage))
|
||||
draw_gui_sprite(ds, _currentImage, x, y, true);
|
||||
|
||||
// Draw active inventory item
|
||||
if (_placeholder != kButtonPlace_None && _G(gui_inv_pic) >= 0) {
|
||||
Size inv_sz = Size(get_adjusted_spritewidth(_G(gui_inv_pic)), get_adjusted_spriteheight(_G(gui_inv_pic)));
|
||||
GUIButtonPlaceholder place = _placeholder;
|
||||
if (place == kButtonPlace_InvItemAuto) {
|
||||
place = ((inv_sz.Width > _width - 6) || (inv_sz.Height > _height - 6)) ?
|
||||
kButtonPlace_InvItemStretch : kButtonPlace_InvItemCenter;
|
||||
}
|
||||
|
||||
if (place == kButtonPlace_InvItemStretch) {
|
||||
ds->StretchBlt(_GP(spriteset)[_G(gui_inv_pic)], RectWH(x + 3, y + 3, _width - 6, _height - 6),
|
||||
kBitmap_Transparency);
|
||||
} else {
|
||||
draw_gui_sprite(ds, _G(gui_inv_pic),
|
||||
x + _width / 2 - inv_sz.Width / 2,
|
||||
y + _height / 2 - inv_sz.Height / 2,
|
||||
true);
|
||||
}
|
||||
}
|
||||
|
||||
if ((draw_disabled) && (GUI::Options.DisabledStyle == kGuiDis_Greyout)) {
|
||||
// darken the button when disabled
|
||||
const Size sz = _GP(spriteset).GetSpriteResolution(_currentImage);
|
||||
GUI::DrawDisabledEffect(ds, RectWH(x, y, sz.Width, sz.Height));
|
||||
}
|
||||
|
||||
// Don't print Text of (INV) (INVSHR) (INVNS)
|
||||
if ((_placeholder == kButtonPlace_None) && !_unnamed)
|
||||
DrawText(ds, x, y, draw_disabled);
|
||||
|
||||
if (IsClippingImage() && !GUI::Options.ClipControls)
|
||||
ds->ResetClip();
|
||||
}
|
||||
|
||||
void GUIButton::DrawText(Bitmap *ds, int x, int y, bool draw_disabled) {
|
||||
// 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);
|
||||
if (IsPushed && IsMouseOver) {
|
||||
// move the Text a bit while pushed
|
||||
frame.Left++;
|
||||
frame.Top++;
|
||||
}
|
||||
color_t text_color = ds->GetCompatibleColor(TextColor);
|
||||
if (draw_disabled)
|
||||
text_color = ds->GetCompatibleColor(8);
|
||||
GUI::DrawTextAligned(ds, _textToDraw.GetCStr(), Font, text_color, frame, TextAlignment);
|
||||
}
|
||||
|
||||
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);
|
||||
if (Flags & kGUICtrl_Default) {
|
||||
draw_color = ds->GetCompatibleColor(16);
|
||||
ds->DrawRect(Rect(x - 1, y - 1, x + _width, y + _height), draw_color);
|
||||
}
|
||||
|
||||
// TODO: use color constants instead of literal numbers
|
||||
if (!draw_disabled && IsMouseOver && IsPushed)
|
||||
draw_color = ds->GetCompatibleColor(15);
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
DrawText(ds, x, y, draw_disabled);
|
||||
}
|
||||
|
||||
} // namespace Shared
|
||||
} // namespace AGS
|
||||
} // namespace AGS3
|
||||
150
engines/ags/shared/gui/gui_button.h
Normal file
150
engines/ags/shared/gui/gui_button.h
Normal file
@@ -0,0 +1,150 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AGS_SHARED_GUI_GUI_BUTTON_H
|
||||
#define AGS_SHARED_GUI_GUI_BUTTON_H
|
||||
|
||||
#include "common/std/vector.h"
|
||||
#include "ags/engine/ac/button.h"
|
||||
#include "ags/shared/gui/gui_object.h"
|
||||
#include "ags/shared/util/string.h"
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
#define GUIBUTTON_LEGACY_TEXTLENGTH 50
|
||||
|
||||
namespace AGS {
|
||||
namespace Shared {
|
||||
|
||||
enum GUIClickMouseButton {
|
||||
kGUIClickLeft = 0,
|
||||
kGUIClickRight = 1,
|
||||
kNumGUIClicks
|
||||
};
|
||||
|
||||
enum GUIClickAction {
|
||||
kGUIAction_None = 0,
|
||||
kGUIAction_SetMode = 1,
|
||||
kGUIAction_RunScript = 2,
|
||||
};
|
||||
|
||||
enum LegacyButtonAlignment {
|
||||
kLegacyButtonAlign_TopCenter = 0,
|
||||
kLegacyButtonAlign_TopLeft = 1,
|
||||
kLegacyButtonAlign_TopRight = 2,
|
||||
kLegacyButtonAlign_CenterLeft = 3,
|
||||
kLegacyButtonAlign_Centered = 4,
|
||||
kLegacyButtonAlign_CenterRight = 5,
|
||||
kLegacyButtonAlign_BottomLeft = 6,
|
||||
kLegacyButtonAlign_BottomCenter = 7,
|
||||
kLegacyButtonAlign_BottomRight = 8,
|
||||
};
|
||||
|
||||
// Defines button placeholder mode; the mode is set
|
||||
// depending on special tags found in button text
|
||||
enum GUIButtonPlaceholder {
|
||||
kButtonPlace_None,
|
||||
kButtonPlace_InvItemStretch,
|
||||
kButtonPlace_InvItemCenter,
|
||||
kButtonPlace_InvItemAuto
|
||||
};
|
||||
|
||||
class GUIButton : public GUIObject {
|
||||
public:
|
||||
GUIButton();
|
||||
|
||||
bool HasAlphaChannel() const override;
|
||||
int32_t GetCurrentImage() const;
|
||||
int32_t GetNormalImage() const;
|
||||
int32_t GetMouseOverImage() const;
|
||||
int32_t GetPushedImage() const;
|
||||
GUIButtonPlaceholder GetPlaceholder() const;
|
||||
const String &GetText() const;
|
||||
bool IsImageButton() const;
|
||||
bool IsClippingImage() const;
|
||||
|
||||
// Operations
|
||||
Rect CalcGraphicRect(bool clipped) override;
|
||||
void Draw(Bitmap *ds, int x = 0, int y = 0) override;
|
||||
void SetClipImage(bool on);
|
||||
void SetCurrentImage(int32_t image);
|
||||
void SetMouseOverImage(int32_t image);
|
||||
void SetNormalImage(int32_t image);
|
||||
void SetPushedImage(int32_t image);
|
||||
void SetImages(int32_t normal, int32_t over, int32_t pushed);
|
||||
void SetText(const String &text);
|
||||
|
||||
// Events
|
||||
bool OnMouseDown() override;
|
||||
void OnMouseEnter() override;
|
||||
void OnMouseLeave() override;
|
||||
void OnMouseUp() override;
|
||||
|
||||
// Serialization
|
||||
void ReadFromFile(Stream *in, GuiVersion gui_version) override;
|
||||
void WriteToFile(Stream *out) const override;
|
||||
void ReadFromSavegame(Shared::Stream *in, GuiSvgVersion svg_ver) override;
|
||||
void WriteToSavegame(Shared::Stream *out) const override;
|
||||
|
||||
// TODO: these members are currently public; hide them later
|
||||
public:
|
||||
int32_t Font;
|
||||
color_t TextColor;
|
||||
FrameAlignment TextAlignment;
|
||||
// Click actions for left and right mouse buttons
|
||||
// NOTE: only left click is currently in use
|
||||
GUIClickAction ClickAction[kNumGUIClicks];
|
||||
int32_t ClickData[kNumGUIClicks];
|
||||
|
||||
bool IsPushed;
|
||||
bool IsMouseOver;
|
||||
|
||||
private:
|
||||
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();
|
||||
// Update current image depending on the button's state
|
||||
void UpdateCurrentImage();
|
||||
|
||||
int32_t _image;
|
||||
int32_t _mouseOverImage;
|
||||
int32_t _pushedImage;
|
||||
// Active displayed image
|
||||
int32_t _currentImage;
|
||||
// Text property set by user
|
||||
String _text;
|
||||
// type of content placeholder, if any
|
||||
GUIButtonPlaceholder _placeholder;
|
||||
// A flag indicating unnamed button; this is a convenience trick:
|
||||
// buttons are created named "New Button" in the editor, and users
|
||||
// often do not clear text when they want a graphic button.
|
||||
bool _unnamed;
|
||||
// Prepared text buffer/cache
|
||||
String _textToDraw;
|
||||
};
|
||||
|
||||
} // namespace Shared
|
||||
} // namespace AGS
|
||||
|
||||
} // namespace AGS3
|
||||
|
||||
#endif
|
||||
216
engines/ags/shared/gui/gui_defines.h
Normal file
216
engines/ags/shared/gui/gui_defines.h
Normal file
@@ -0,0 +1,216 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AGS_SHARED_GUI_GUI_DEFINES_H
|
||||
#define AGS_SHARED_GUI_GUI_DEFINES_H
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
#define GUIMAGIC 0xcafebeef
|
||||
#define MAX_GUIOBJ_EVENTS 10
|
||||
#define TEXTWINDOW_PADDING_DEFAULT 3
|
||||
|
||||
// TODO: find out more about gui version history
|
||||
//=============================================================================
|
||||
// GUI Version history
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// 2.1.4..... (100): Introduced Slider gui control. Gui count is now serialized
|
||||
// in game file.
|
||||
// 2.2.2..... (101): Introduced TextBox gui control.
|
||||
// 2.3.0..... (102): Introduced ListBox gui control.
|
||||
// 2.6.0..... (105): GUI custom Z-order support.
|
||||
// 2.7.0..... (110): Added GUI OnClick handler.
|
||||
// 2.7.2.???? (111): Added text alignment property to buttons.
|
||||
// 2.7.2.???? (112): Added text alignment property to list boxes.
|
||||
// 2.7.2.???? (113): Increased permitted length of GUI label text from 200 to
|
||||
// 2048 characters.
|
||||
// 2.7.2.???? (114): Obsoleted savegameindex[] array, and added
|
||||
// ListBox.SaveGameSlots[] array instead.
|
||||
// 2.7.2.???? (115): Added GUI Control z-order support.
|
||||
//
|
||||
// 3.3.0.1132 (116): Added kGUICtrl_Translated flag.
|
||||
// 3.3.1.???? (117): Added padding variable for text window GUIs.
|
||||
// 3.4.0 (118): Removed GUI limits
|
||||
// 3.5.0 (119): Game data contains GUI properties that previously
|
||||
// could be set only at runtime.
|
||||
// Since then format value is defined as AGS version represented as NN,NN,NN,NN
|
||||
//=============================================================================
|
||||
|
||||
enum GuiVersion {
|
||||
// TODO: find out all corresponding engine version numbers
|
||||
kGuiVersion_Initial = 0,
|
||||
kGuiVersion_214 = 100,
|
||||
kGuiVersion_222 = 101,
|
||||
kGuiVersion_230 = 102,
|
||||
kGuiVersion_unkn_103 = 103,
|
||||
kGuiVersion_unkn_104 = 104,
|
||||
kGuiVersion_260 = 105,
|
||||
kGuiVersion_unkn_106 = 106,
|
||||
kGuiVersion_unkn_107 = 107,
|
||||
kGuiVersion_unkn_108 = 108,
|
||||
kGuiVersion_unkn_109 = 109,
|
||||
kGuiVersion_270 = 110,
|
||||
kGuiVersion_272a = 111,
|
||||
kGuiVersion_272b = 112,
|
||||
kGuiVersion_272c = 113,
|
||||
kGuiVersion_272d = 114,
|
||||
kGuiVersion_272e = 115,
|
||||
|
||||
kGuiVersion_330 = 116,
|
||||
kGuiVersion_331 = 117,
|
||||
kGuiVersion_340 = 118,
|
||||
kGuiVersion_350 = 119,
|
||||
kGuiVersion_Current = kGuiVersion_350,
|
||||
};
|
||||
|
||||
namespace AGS {
|
||||
namespace Shared {
|
||||
|
||||
// GUIMain's style and behavior flags
|
||||
enum GUIMainFlags {
|
||||
kGUIMain_Clickable = 0x0001,
|
||||
kGUIMain_TextWindow = 0x0002,
|
||||
kGUIMain_Visible = 0x0004,
|
||||
kGUIMain_Concealed = 0x0008,
|
||||
|
||||
// NOTE: currently default state is Visible to keep this backwards compatible;
|
||||
// check later if this is still a wanted behavior
|
||||
kGUIMain_DefFlags = kGUIMain_Clickable | kGUIMain_Visible,
|
||||
// flags that had inverse meaning in old formats
|
||||
kGUIMain_OldFmtXorMask = kGUIMain_Clickable
|
||||
};
|
||||
|
||||
// GUIMain's legacy flags, now converted to GUIMainFlags on load
|
||||
enum GUIMainLegacyFlags {
|
||||
kGUIMain_LegacyTextWindow = 5
|
||||
};
|
||||
|
||||
// GUIMain's style of getting displayed on screen
|
||||
enum GUIPopupStyle {
|
||||
// Normal GUI
|
||||
kGUIPopupNormal = 0,
|
||||
// Shown when the mouse cursor moves to the top of the screen
|
||||
kGUIPopupMouseY = 1,
|
||||
// Same as Normal, but pauses the game when shown
|
||||
kGUIPopupModal = 2,
|
||||
// Same as Normal, but is not removed when interface is off
|
||||
kGUIPopupNoAutoRemove = 3,
|
||||
// (legacy option) Normal GUI, initially off
|
||||
// converts to kGUIPopupNormal with Visible = false
|
||||
kGUIPopupLegacyNormalOff = 4
|
||||
};
|
||||
|
||||
// The type of GUIControl
|
||||
enum GUIControlType {
|
||||
kGUIControlUndefined = -1,
|
||||
kGUIButton = 1,
|
||||
kGUILabel = 2,
|
||||
kGUIInvWindow = 3,
|
||||
kGUISlider = 4,
|
||||
kGUITextBox = 5,
|
||||
kGUIListBox = 6
|
||||
};
|
||||
|
||||
// GUIControl general style and behavior flags
|
||||
enum GUIControlFlags {
|
||||
kGUICtrl_Default = 0x0001, // only button
|
||||
kGUICtrl_Cancel = 0x0002, // unused
|
||||
kGUICtrl_Enabled = 0x0004,
|
||||
kGUICtrl_TabStop = 0x0008, // unused
|
||||
kGUICtrl_Visible = 0x0010,
|
||||
kGUICtrl_Clip = 0x0020, // only button
|
||||
kGUICtrl_Clickable = 0x0040,
|
||||
kGUICtrl_Translated = 0x0080, // 3.3.0.1132
|
||||
kGUICtrl_Deleted = 0x8000, // unused (probably remains from the old editor?)
|
||||
|
||||
kGUICtrl_DefFlags = kGUICtrl_Enabled | kGUICtrl_Visible | kGUICtrl_Clickable | kGUICtrl_Translated,
|
||||
// flags that had inverse meaning in old formats
|
||||
kGUICtrl_OldFmtXorMask = kGUICtrl_Enabled | kGUICtrl_Visible | kGUICtrl_Clickable
|
||||
};
|
||||
|
||||
// Label macro flags, define which macros are present in the Label's Text
|
||||
enum GUILabelMacro {
|
||||
kLabelMacro_None = 0,
|
||||
kLabelMacro_Gamename = 0x01,
|
||||
kLabelMacro_Overhotspot = 0x02,
|
||||
kLabelMacro_Score = 0x04,
|
||||
kLabelMacro_ScoreText = 0x08,
|
||||
kLabelMacro_TotalScore = 0x10,
|
||||
|
||||
kLabelMacro_AllScore = kLabelMacro_Score | kLabelMacro_ScoreText,
|
||||
kLabelMacro_All = 0xFFFF
|
||||
};
|
||||
|
||||
// GUIListBox style and behavior flags
|
||||
enum GUIListBoxFlags {
|
||||
kListBox_ShowBorder = 0x01,
|
||||
kListBox_ShowArrows = 0x02,
|
||||
kListBox_SvgIndex = 0x04,
|
||||
|
||||
kListBox_DefFlags = kListBox_ShowBorder | kListBox_ShowArrows,
|
||||
// flags that had inverse meaning in old formats
|
||||
kListBox_OldFmtXorMask = kListBox_ShowBorder | kListBox_ShowArrows
|
||||
};
|
||||
|
||||
// GUITextBox style and behavior flags
|
||||
enum GUITextBoxFlags {
|
||||
kTextBox_ShowBorder = 0x0001,
|
||||
|
||||
kTextBox_DefFlags = kTextBox_ShowBorder,
|
||||
// flags that had inverse meaning in old formats
|
||||
kTextBox_OldFmtXorMask = kTextBox_ShowBorder
|
||||
};
|
||||
|
||||
// Savegame data format
|
||||
// TODO: move to the engine code
|
||||
enum GuiSvgVersion {
|
||||
kGuiSvgVersion_Initial = 0,
|
||||
kGuiSvgVersion_350,
|
||||
kGuiSvgVersion_36020,
|
||||
kGuiSvgVersion_36023,
|
||||
kGuiSvgVersion_36025
|
||||
};
|
||||
|
||||
// Style of GUI drawing in disabled state
|
||||
enum GuiDisableStyle {
|
||||
kGuiDis_Undefined = -1, // this is for marking not-disabled state
|
||||
kGuiDis_Greyout = 0, // paint "gisabled" effect over controls
|
||||
kGuiDis_Blackout = 1, // invisible controls (but guis are shown
|
||||
kGuiDis_Unchanged = 2, // no change, display normally
|
||||
kGuiDis_Off = 3 // fully invisible guis
|
||||
};
|
||||
|
||||
// Global GUI options
|
||||
struct GuiOptions {
|
||||
// Clip GUI control's contents to the control's rectangle
|
||||
bool ClipControls = true;
|
||||
// How the GUI controls are drawn when the interface is disabled
|
||||
GuiDisableStyle DisabledStyle = kGuiDis_Unchanged;
|
||||
// Whether to graphically outline GUI controls
|
||||
bool OutlineControls = false;
|
||||
};
|
||||
|
||||
} // namespace Shared
|
||||
} // namespace AGS
|
||||
} // namespace AGS3
|
||||
|
||||
#endif
|
||||
128
engines/ags/shared/gui/gui_inv.cpp
Normal file
128
engines/ags/shared/gui/gui_inv.cpp
Normal file
@@ -0,0 +1,128 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ags/shared/ac/game_version.h"
|
||||
#include "ags/shared/gui/gui_inv.h"
|
||||
#include "ags/shared/gui/gui_main.h"
|
||||
#include "ags/shared/util/stream.h"
|
||||
|
||||
namespace AGS3 {
|
||||
namespace AGS {
|
||||
namespace Shared {
|
||||
|
||||
GUIInvWindow::GUIInvWindow() {
|
||||
IsMouseOver = false;
|
||||
CharId = -1;
|
||||
ItemWidth = 40;
|
||||
ItemHeight = 22;
|
||||
ColCount = 0;
|
||||
RowCount = 0;
|
||||
TopItem = 0;
|
||||
CalculateNumCells();
|
||||
|
||||
_scEventCount = 0;
|
||||
}
|
||||
|
||||
void GUIInvWindow::OnMouseEnter() {
|
||||
IsMouseOver = true;
|
||||
}
|
||||
|
||||
void GUIInvWindow::OnMouseLeave() {
|
||||
IsMouseOver = false;
|
||||
}
|
||||
|
||||
void GUIInvWindow::OnMouseUp() {
|
||||
if (IsMouseOver)
|
||||
IsActivated = true;
|
||||
}
|
||||
|
||||
void GUIInvWindow::OnResized() {
|
||||
CalculateNumCells();
|
||||
MarkChanged();
|
||||
}
|
||||
|
||||
void GUIInvWindow::WriteToFile(Stream *out) const {
|
||||
GUIObject::WriteToFile(out);
|
||||
out->WriteInt32(CharId);
|
||||
out->WriteInt32(ItemWidth);
|
||||
out->WriteInt32(ItemHeight);
|
||||
}
|
||||
|
||||
void GUIInvWindow::ReadFromFile(Stream *in, GuiVersion gui_version) {
|
||||
GUIObject::ReadFromFile(in, gui_version);
|
||||
if (gui_version >= kGuiVersion_unkn_109) {
|
||||
CharId = in->ReadInt32();
|
||||
ItemWidth = in->ReadInt32();
|
||||
ItemHeight = in->ReadInt32();
|
||||
if (gui_version < kGuiVersion_350) { // NOTE: reading into actual variables only for old savegame support
|
||||
TopItem = in->ReadInt32();
|
||||
}
|
||||
} else {
|
||||
CharId = -1;
|
||||
ItemWidth = 40;
|
||||
ItemHeight = 22;
|
||||
TopItem = 0;
|
||||
}
|
||||
|
||||
if (_G(loaded_game_file_version) >= kGameVersion_270) {
|
||||
// ensure that some items are visible
|
||||
if (ItemWidth > _width)
|
||||
ItemWidth = _width;
|
||||
if (ItemHeight > _height)
|
||||
ItemHeight = _height;
|
||||
}
|
||||
|
||||
CalculateNumCells();
|
||||
}
|
||||
|
||||
void GUIInvWindow::ReadFromSavegame(Stream *in, GuiSvgVersion svg_ver) {
|
||||
GUIObject::ReadFromSavegame(in, svg_ver);
|
||||
ItemWidth = in->ReadInt32();
|
||||
ItemHeight = in->ReadInt32();
|
||||
CharId = in->ReadInt32();
|
||||
TopItem = in->ReadInt32();
|
||||
CalculateNumCells();
|
||||
}
|
||||
|
||||
void GUIInvWindow::WriteToSavegame(Stream *out) const {
|
||||
GUIObject::WriteToSavegame(out);
|
||||
out->WriteInt32(ItemWidth);
|
||||
out->WriteInt32(ItemHeight);
|
||||
out->WriteInt32(CharId);
|
||||
out->WriteInt32(TopItem);
|
||||
}
|
||||
|
||||
void GUIInvWindow::CalculateNumCells() {
|
||||
if (ItemWidth <= 0 || ItemHeight <= 0) {
|
||||
ColCount = 0;
|
||||
RowCount = 0;
|
||||
} else if (_G(loaded_game_file_version) >= kGameVersion_270) {
|
||||
ColCount = _width / data_to_game_coord(ItemWidth);
|
||||
RowCount = _height / data_to_game_coord(ItemHeight);
|
||||
} else {
|
||||
ColCount = floor((float)_width / (float)data_to_game_coord(ItemWidth) + 0.5f);
|
||||
RowCount = floor((float)_height / (float)data_to_game_coord(ItemHeight) + 0.5f);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Shared
|
||||
} // namespace AGS
|
||||
} // namespace AGS3
|
||||
74
engines/ags/shared/gui/gui_inv.h
Normal file
74
engines/ags/shared/gui/gui_inv.h
Normal file
@@ -0,0 +1,74 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AGS_SHARED_GUI_GUI_INV_H
|
||||
#define AGS_SHARED_GUI_GUI_INV_H
|
||||
|
||||
#include "common/std/vector.h"
|
||||
#include "ags/shared/gui/gui_object.h"
|
||||
|
||||
namespace AGS3 {
|
||||
namespace AGS {
|
||||
namespace Shared {
|
||||
|
||||
class GUIInvWindow : public GUIObject {
|
||||
public:
|
||||
GUIInvWindow();
|
||||
|
||||
bool HasAlphaChannel() const override;
|
||||
// This function has distinct implementations in Engine and Editor
|
||||
int GetCharacterId() const;
|
||||
|
||||
// Operations
|
||||
// This function has distinct implementations in Engine and Editor
|
||||
void Draw(Bitmap *ds, int x = 0, int y = 0) override;
|
||||
|
||||
// Events
|
||||
void OnMouseEnter() override;
|
||||
void OnMouseLeave() override;
|
||||
void OnMouseUp() override;
|
||||
void OnResized() override;
|
||||
|
||||
// Serialization
|
||||
void ReadFromFile(Stream *in, GuiVersion gui_version) override;
|
||||
void WriteToFile(Stream *out) const override;
|
||||
void ReadFromSavegame(Shared::Stream *in, GuiSvgVersion svg_ver) override;
|
||||
void WriteToSavegame(Shared::Stream *out) const override;
|
||||
|
||||
// TODO: these members are currently public; hide them later
|
||||
public:
|
||||
bool IsMouseOver;
|
||||
int32_t CharId; // whose inventory (-1 = current player)
|
||||
int32_t ItemWidth;
|
||||
int32_t ItemHeight;
|
||||
int32_t ColCount;
|
||||
int32_t RowCount;
|
||||
int32_t TopItem;
|
||||
|
||||
private:
|
||||
void CalculateNumCells();
|
||||
};
|
||||
|
||||
} // namespace Shared
|
||||
} // namespace AGS
|
||||
} // namespace AGS3
|
||||
|
||||
#endif
|
||||
172
engines/ags/shared/gui/gui_label.cpp
Normal file
172
engines/ags/shared/gui/gui_label.cpp
Normal file
@@ -0,0 +1,172 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/std/algorithm.h"
|
||||
#include "ags/shared/ac/game_version.h"
|
||||
#include "ags/shared/font/fonts.h"
|
||||
#include "ags/shared/gui/gui_label.h"
|
||||
#include "ags/shared/gui/gui_main.h"
|
||||
#include "ags/shared/util/stream.h"
|
||||
#include "ags/shared/util/string_utils.h"
|
||||
|
||||
#define GUILABEL_TEXTLENGTH_PRE272 200
|
||||
|
||||
namespace AGS3 {
|
||||
namespace AGS {
|
||||
namespace Shared {
|
||||
|
||||
GUILabel::GUILabel() {
|
||||
Font = 0;
|
||||
TextColor = 0;
|
||||
TextAlignment = kHAlignLeft;
|
||||
|
||||
_scEventCount = 0;
|
||||
}
|
||||
|
||||
bool GUILabel::HasAlphaChannel() const {
|
||||
return is_font_antialiased(Font);
|
||||
}
|
||||
|
||||
String GUILabel::GetText() const {
|
||||
return Text;
|
||||
}
|
||||
|
||||
GUILabelMacro GUILabel::GetTextMacros() const {
|
||||
return _textMacro;
|
||||
}
|
||||
|
||||
Rect GUILabel::CalcGraphicRect(bool clipped) {
|
||||
if (clipped)
|
||||
return RectWH(0, 0, _width, _height);
|
||||
|
||||
// TODO: need to find a way to text position, or there'll be some repetition
|
||||
// have to precache text and size on some events:
|
||||
// - translation change
|
||||
// - macro value change (score, overhotspot etc)
|
||||
Rect rc = RectWH(0, 0, _width, _height);
|
||||
if (PrepareTextToDraw() == 0)
|
||||
return rc;
|
||||
const int linespacing = // Older engine labels used (font height + 1) as linespacing for some reason
|
||||
((_G(loaded_game_file_version) < kGameVersion_360) && (get_font_flags(Font) & FFLG_DEFLINESPACING)) ?
|
||||
(get_font_height(Font) + 1) :
|
||||
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 = 0;
|
||||
Line max_line;
|
||||
for (size_t i = 0;
|
||||
i < _GP(Lines).Count() && (!limit_by_label_frame || at_y <= _height);
|
||||
++i, at_y += linespacing) {
|
||||
Line lpos = GUI::CalcTextPositionHor(_GP(Lines)[i].GetCStr(), Font, 0, 0 + _width - 1, at_y,
|
||||
(FrameAlignment)TextAlignment);
|
||||
max_line.X2 = MAX(max_line.X2, lpos.X2);
|
||||
}
|
||||
// Include font fixes for the first and last text line,
|
||||
// in case graphical height is different, and there's a VerticalOffset
|
||||
Line vextent = GUI::CalcFontGraphicalVExtent(Font);
|
||||
Rect text_rc = RectWH(0, vextent.Y1, max_line.X2 - max_line.X1 + 1, at_y - linespacing + (vextent.Y2 - vextent.Y1));
|
||||
return SumRects(rc, text_rc);
|
||||
}
|
||||
|
||||
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
|
||||
if (PrepareTextToDraw() == 0)
|
||||
return;
|
||||
|
||||
color_t text_color = ds->GetCompatibleColor(TextColor);
|
||||
const int linespacing = // Older engine labels used (font height + 1) as linespacing for some reason
|
||||
((_G(loaded_game_file_version) < kGameVersion_360) && (get_font_flags(Font) & FFLG_DEFLINESPACING)) ?
|
||||
(get_font_height(Font) + 1) :
|
||||
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;
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
void GUILabel::SetText(const String &text) {
|
||||
if (text == Text)
|
||||
return;
|
||||
Text = text;
|
||||
// Check for macros within text
|
||||
_textMacro = GUI::FindLabelMacros(Text);
|
||||
MarkChanged();
|
||||
}
|
||||
|
||||
// TODO: replace string serialization with StrUtil::ReadString and WriteString
|
||||
// methods in the future, to keep this organized.
|
||||
void GUILabel::WriteToFile(Stream *out) const {
|
||||
GUIObject::WriteToFile(out);
|
||||
StrUtil::WriteString(Text, out);
|
||||
out->WriteInt32(Font);
|
||||
out->WriteInt32(TextColor);
|
||||
out->WriteInt32(TextAlignment);
|
||||
}
|
||||
|
||||
void GUILabel::ReadFromFile(Stream *in, GuiVersion gui_version) {
|
||||
GUIObject::ReadFromFile(in, gui_version);
|
||||
|
||||
if (gui_version < kGuiVersion_272c)
|
||||
Text.ReadCount(in, GUILABEL_TEXTLENGTH_PRE272);
|
||||
else
|
||||
Text = StrUtil::ReadString(in);
|
||||
|
||||
Font = in->ReadInt32();
|
||||
TextColor = in->ReadInt32();
|
||||
if (gui_version < kGuiVersion_350)
|
||||
TextAlignment = ConvertLegacyGUIAlignment((LegacyGUIAlignment)in->ReadInt32());
|
||||
else
|
||||
TextAlignment = (HorAlignment)in->ReadInt32();
|
||||
|
||||
if (TextColor == 0)
|
||||
TextColor = 16;
|
||||
|
||||
_textMacro = GUI::FindLabelMacros(Text);
|
||||
}
|
||||
|
||||
void GUILabel::ReadFromSavegame(Stream *in, GuiSvgVersion svg_ver) {
|
||||
GUIObject::ReadFromSavegame(in, svg_ver);
|
||||
Font = in->ReadInt32();
|
||||
TextColor = in->ReadInt32();
|
||||
Text = StrUtil::ReadString(in);
|
||||
if (svg_ver >= kGuiSvgVersion_350)
|
||||
TextAlignment = (HorAlignment)in->ReadInt32();
|
||||
|
||||
_textMacro = GUI::FindLabelMacros(Text);
|
||||
}
|
||||
|
||||
void GUILabel::WriteToSavegame(Stream *out) const {
|
||||
GUIObject::WriteToSavegame(out);
|
||||
out->WriteInt32(Font);
|
||||
out->WriteInt32(TextColor);
|
||||
StrUtil::WriteString(Text, out);
|
||||
out->WriteInt32(TextAlignment);
|
||||
}
|
||||
|
||||
} // namespace Shared
|
||||
} // namespace AGS
|
||||
} // namespace AGS3
|
||||
78
engines/ags/shared/gui/gui_label.h
Normal file
78
engines/ags/shared/gui/gui_label.h
Normal file
@@ -0,0 +1,78 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AGS_SHARED_GUI_GUI_LABEL_H
|
||||
#define AGS_SHARED_GUI_GUI_LABEL_H
|
||||
|
||||
#include "common/std/vector.h"
|
||||
#include "ags/shared/gui/gui_object.h"
|
||||
#include "ags/shared/util/string.h"
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
namespace AGS {
|
||||
namespace Shared {
|
||||
|
||||
class GUILabel : public GUIObject {
|
||||
public:
|
||||
GUILabel();
|
||||
|
||||
bool HasAlphaChannel() const override;
|
||||
// Gets label's text property in original set form (with macros etc)
|
||||
String GetText() const;
|
||||
// Gets which macro are contained within label's text
|
||||
GUILabelMacro GetTextMacros() const;
|
||||
|
||||
// Operations
|
||||
Rect CalcGraphicRect(bool clipped) override;
|
||||
void Draw(Bitmap *ds, int x = 0, int y = 0) override;
|
||||
void SetText(const String &text);
|
||||
|
||||
// Serialization
|
||||
void ReadFromFile(Stream *in, GuiVersion gui_version) override;
|
||||
void WriteToFile(Stream *out) const override;
|
||||
void ReadFromSavegame(Shared::Stream *in, GuiSvgVersion svg_ver) override;
|
||||
void WriteToSavegame(Shared::Stream *out) const override;
|
||||
|
||||
// TODO: these members are currently public; hide them later
|
||||
public:
|
||||
String Text;
|
||||
int32_t Font;
|
||||
color_t TextColor;
|
||||
HorAlignment TextAlignment;
|
||||
|
||||
private:
|
||||
// Transforms the Text property to a drawn text, applies translation,
|
||||
// replaces macros, splits and wraps, etc; returns number of lines.
|
||||
int PrepareTextToDraw();
|
||||
|
||||
// Information on macros contained within Text field
|
||||
GUILabelMacro _textMacro;
|
||||
// prepared text buffer/cache
|
||||
// TODO: cache split lines instead?
|
||||
String _textToDraw;
|
||||
};
|
||||
|
||||
} // namespace Shared
|
||||
} // namespace AGS
|
||||
} // namespace AGS3
|
||||
|
||||
#endif
|
||||
453
engines/ags/shared/gui/gui_listbox.cpp
Normal file
453
engines/ags/shared/gui/gui_listbox.cpp
Normal file
@@ -0,0 +1,453 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/std/algorithm.h"
|
||||
#include "ags/shared/gui/gui_listbox.h"
|
||||
#include "ags/shared/ac/game_version.h"
|
||||
#include "ags/shared/font/fonts.h"
|
||||
#include "ags/shared/gui/gui_main.h"
|
||||
#include "ags/shared/util/stream.h"
|
||||
#include "ags/shared/util/string_utils.h"
|
||||
|
||||
namespace AGS3 {
|
||||
namespace AGS {
|
||||
namespace Shared {
|
||||
|
||||
GUIListBox::GUIListBox() {
|
||||
ItemCount = 0;
|
||||
SelectedItem = 0;
|
||||
TopItem = 0;
|
||||
RowHeight = 0;
|
||||
VisibleItemCount = 0;
|
||||
Font = 0;
|
||||
TextColor = 0;
|
||||
SelectedTextColor = 7;
|
||||
ListBoxFlags = kListBox_DefFlags;
|
||||
SelectedBgColor = 16;
|
||||
TextAlignment = kHAlignLeft;
|
||||
|
||||
_scEventCount = 1;
|
||||
_scEventNames[0] = "SelectionChanged";
|
||||
_scEventArgs[0] = "GUIControl *control";
|
||||
}
|
||||
|
||||
bool GUIListBox::HasAlphaChannel() const {
|
||||
return is_font_antialiased(Font);
|
||||
}
|
||||
|
||||
int GUIListBox::GetItemAt(int x, int y) const {
|
||||
if (RowHeight <= 0 || IsInRightMargin(x))
|
||||
return -1;
|
||||
|
||||
int index = y / RowHeight + TopItem;
|
||||
if (index < 0 || index >= ItemCount)
|
||||
return -1;
|
||||
return index;
|
||||
}
|
||||
|
||||
bool GUIListBox::AreArrowsShown() const {
|
||||
return (ListBoxFlags & kListBox_ShowArrows) != 0;
|
||||
}
|
||||
|
||||
bool GUIListBox::IsBorderShown() const {
|
||||
return (ListBoxFlags & kListBox_ShowBorder) != 0;
|
||||
}
|
||||
|
||||
bool GUIListBox::IsSvgIndex() const {
|
||||
return (ListBoxFlags & kListBox_SvgIndex) != 0;
|
||||
}
|
||||
|
||||
bool GUIListBox::IsInRightMargin(int x) const {
|
||||
if (x >= (_width - get_fixed_pixel_size(6)) && IsBorderShown() && AreArrowsShown())
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
Rect GUIListBox::CalcGraphicRect(bool clipped) {
|
||||
if (clipped)
|
||||
return RectWH(0, 0, _width, _height);
|
||||
|
||||
// TODO: need to find a way to text position, or there'll be some repetition
|
||||
// have to precache text and size on some events:
|
||||
// - translation change
|
||||
// - macro value change (score, overhotspot etc)
|
||||
Rect rc = RectWH(0, 0, _width, _height);
|
||||
UpdateMetrics();
|
||||
const int width = _width - 1;
|
||||
const int pixel_size = get_fixed_pixel_size(1);
|
||||
int right_hand_edge = width - pixel_size - 1;
|
||||
// calculate the scroll bar's width if necessary
|
||||
if (ItemCount > VisibleItemCount &&IsBorderShown() && AreArrowsShown())
|
||||
right_hand_edge -= get_fixed_pixel_size(7);
|
||||
Line max_line;
|
||||
for (int item = 0; (item < VisibleItemCount) && (item + TopItem < ItemCount); ++item) {
|
||||
int at_y = pixel_size + item * RowHeight;
|
||||
int item_index = item + TopItem;
|
||||
PrepareTextToDraw(Items[item_index]);
|
||||
Line lpos = GUI::CalcTextPositionHor(_textToDraw.GetCStr(), Font, 1 + pixel_size, right_hand_edge, at_y + 1,
|
||||
(FrameAlignment)TextAlignment);
|
||||
max_line.X2 = MAX(max_line.X2, lpos.X2);
|
||||
}
|
||||
int last_line_y = pixel_size + 1 + (VisibleItemCount - 1) * RowHeight;
|
||||
// Include font fixes for the first and last text line,
|
||||
// in case graphical height is different, and there's a VerticalOffset
|
||||
Line vextent = GUI::CalcFontGraphicalVExtent(Font);
|
||||
Rect text_rc = RectWH(0, vextent.Y1, max_line.X2 - max_line.X1 + 1, last_line_y + (vextent.Y2 - vextent.Y1));
|
||||
return SumRects(rc, text_rc);
|
||||
}
|
||||
|
||||
int GUIListBox::AddItem(const String &text) {
|
||||
Items.push_back(text);
|
||||
SavedGameIndex.push_back(-1);
|
||||
ItemCount++;
|
||||
MarkChanged();
|
||||
return ItemCount - 1;
|
||||
}
|
||||
|
||||
void GUIListBox::Clear() {
|
||||
if (Items.empty())
|
||||
return;
|
||||
|
||||
Items.clear();
|
||||
SavedGameIndex.clear();
|
||||
ItemCount = 0;
|
||||
SelectedItem = 0;
|
||||
TopItem = 0;
|
||||
MarkChanged();
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
color_t text_color = ds->GetCompatibleColor(TextColor);
|
||||
color_t draw_color = ds->GetCompatibleColor(TextColor);
|
||||
if (IsBorderShown()) {
|
||||
ds->DrawRect(Rect(x, y, x + width, y + height), draw_color);
|
||||
if (pixel_size > 1)
|
||||
ds->DrawRect(Rect(x + 1, y + 1, x + width - 1, y + height - 1), draw_color);
|
||||
}
|
||||
|
||||
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();
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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));
|
||||
for (int item = 0; (item < VisibleItemCount) && (item + TopItem < ItemCount); ++item) {
|
||||
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;
|
||||
// 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);
|
||||
}
|
||||
} else
|
||||
text_color = ds->GetCompatibleColor(TextColor);
|
||||
|
||||
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);
|
||||
}
|
||||
ds->SetClip(old_clip);
|
||||
}
|
||||
|
||||
int GUIListBox::InsertItem(int index, const String &text) {
|
||||
if (index < 0 || index > ItemCount)
|
||||
return -1;
|
||||
|
||||
Items.insert(Items.begin() + index, text);
|
||||
SavedGameIndex.insert(SavedGameIndex.begin() + index, -1);
|
||||
if (SelectedItem >= index)
|
||||
SelectedItem++;
|
||||
|
||||
ItemCount++;
|
||||
MarkChanged();
|
||||
return ItemCount - 1;
|
||||
}
|
||||
|
||||
void GUIListBox::RemoveItem(int index) {
|
||||
if (index < 0 || index >= ItemCount)
|
||||
return;
|
||||
|
||||
Items.erase(Items.begin() + index);
|
||||
SavedGameIndex.erase(SavedGameIndex.begin() + index);
|
||||
ItemCount--;
|
||||
|
||||
if (SelectedItem > index)
|
||||
SelectedItem--;
|
||||
if (SelectedItem >= ItemCount)
|
||||
SelectedItem = -1;
|
||||
MarkChanged();
|
||||
}
|
||||
|
||||
void GUIListBox::SetShowArrows(bool on) {
|
||||
if (on != ((ListBoxFlags & kListBox_ShowArrows) != 0))
|
||||
MarkChanged();
|
||||
if (on)
|
||||
ListBoxFlags |= kListBox_ShowArrows;
|
||||
else
|
||||
ListBoxFlags &= ~kListBox_ShowArrows;
|
||||
}
|
||||
|
||||
void GUIListBox::SetShowBorder(bool on) {
|
||||
if (on != ((ListBoxFlags & kListBox_ShowBorder) != 0))
|
||||
MarkChanged();
|
||||
if (on)
|
||||
ListBoxFlags |= kListBox_ShowBorder;
|
||||
else
|
||||
ListBoxFlags &= ~kListBox_ShowBorder;
|
||||
}
|
||||
|
||||
void GUIListBox::SetSvgIndex(bool on) {
|
||||
if (on)
|
||||
ListBoxFlags |= kListBox_SvgIndex;
|
||||
else
|
||||
ListBoxFlags &= ~kListBox_SvgIndex;
|
||||
}
|
||||
|
||||
void GUIListBox::SetFont(int font) {
|
||||
if (Font == font)
|
||||
return;
|
||||
Font = font;
|
||||
UpdateMetrics();
|
||||
MarkChanged();
|
||||
}
|
||||
|
||||
void GUIListBox::SetItemText(int index, const String &text) {
|
||||
if ((index >= 0) && (index < ItemCount) && (text != Items[index])) {
|
||||
Items[index] = text;
|
||||
MarkChanged();
|
||||
}
|
||||
}
|
||||
|
||||
bool GUIListBox::OnMouseDown() {
|
||||
if (IsInRightMargin(MousePos.X)) {
|
||||
int top_item = TopItem;
|
||||
if (MousePos.Y < _height / 2 && TopItem > 0)
|
||||
top_item = TopItem - 1;
|
||||
if (MousePos.Y >= _height / 2 && ItemCount > TopItem + VisibleItemCount)
|
||||
top_item = TopItem + 1;
|
||||
if (TopItem != top_item) {
|
||||
TopItem = top_item;
|
||||
MarkChanged();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int sel = GetItemAt(MousePos.X, MousePos.Y);
|
||||
if (sel < 0)
|
||||
return false;
|
||||
if (sel != SelectedItem) {
|
||||
SelectedItem = sel;
|
||||
MarkChanged();
|
||||
}
|
||||
IsActivated = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void GUIListBox::OnMouseMove(int x_, int y_) {
|
||||
MousePos.X = x_ - X;
|
||||
MousePos.Y = y_ - Y;
|
||||
}
|
||||
|
||||
void GUIListBox::OnResized() {
|
||||
UpdateMetrics();
|
||||
MarkChanged();
|
||||
}
|
||||
|
||||
void GUIListBox::UpdateMetrics() {
|
||||
int font_height = (_G(loaded_game_file_version) < kGameVersion_360_21) ?
|
||||
get_font_height(Font) : get_font_height_outlined(Font);
|
||||
RowHeight = font_height + get_fixed_pixel_size(2); // +1 top/bottom margin
|
||||
VisibleItemCount = _height / RowHeight;
|
||||
if (ItemCount <= VisibleItemCount)
|
||||
TopItem = 0; // reset scroll if all items are visible
|
||||
}
|
||||
|
||||
// TODO: replace string serialization with StrUtil::ReadString and WriteString
|
||||
// methods in the future, to keep this organized.
|
||||
void GUIListBox::WriteToFile(Stream *out) const {
|
||||
GUIObject::WriteToFile(out);
|
||||
out->WriteInt32(ItemCount);
|
||||
out->WriteInt32(Font);
|
||||
out->WriteInt32(TextColor);
|
||||
out->WriteInt32(SelectedTextColor);
|
||||
out->WriteInt32(ListBoxFlags);
|
||||
out->WriteInt32(TextAlignment);
|
||||
out->WriteInt32(SelectedBgColor);
|
||||
for (int i = 0; i < ItemCount; ++i)
|
||||
Items[i].Write(out);
|
||||
}
|
||||
|
||||
void GUIListBox::ReadFromFile(Stream *in, GuiVersion gui_version) {
|
||||
Clear();
|
||||
|
||||
GUIObject::ReadFromFile(in, gui_version);
|
||||
ItemCount = in->ReadInt32();
|
||||
if (gui_version < kGuiVersion_350) { // NOTE: reading into actual variables only for old savegame support
|
||||
SelectedItem = in->ReadInt32();
|
||||
TopItem = in->ReadInt32();
|
||||
MousePos.X = in->ReadInt32();
|
||||
MousePos.Y = in->ReadInt32();
|
||||
RowHeight = in->ReadInt32();
|
||||
VisibleItemCount = in->ReadInt32();
|
||||
}
|
||||
Font = in->ReadInt32();
|
||||
TextColor = in->ReadInt32();
|
||||
SelectedTextColor = in->ReadInt32();
|
||||
ListBoxFlags = in->ReadInt32();
|
||||
// reverse particular flags from older format
|
||||
if (gui_version < kGuiVersion_350)
|
||||
ListBoxFlags ^= kListBox_OldFmtXorMask;
|
||||
|
||||
if (gui_version >= kGuiVersion_272b) {
|
||||
if (gui_version < kGuiVersion_350) {
|
||||
TextAlignment = ConvertLegacyGUIAlignment((LegacyGUIAlignment)in->ReadInt32());
|
||||
in->ReadInt32(); // reserved1
|
||||
} else {
|
||||
TextAlignment = (HorAlignment)in->ReadInt32();
|
||||
}
|
||||
} else {
|
||||
TextAlignment = kHAlignLeft;
|
||||
}
|
||||
|
||||
if (gui_version >= kGuiVersion_unkn_107) {
|
||||
SelectedBgColor = in->ReadInt32();
|
||||
} else {
|
||||
SelectedBgColor = TextColor;
|
||||
if (SelectedBgColor == 0)
|
||||
SelectedBgColor = 16;
|
||||
}
|
||||
|
||||
// NOTE: we leave items in game data format as a potential support for defining
|
||||
// ListBox contents at design-time, although Editor does not support it as of 3.5.0.
|
||||
Items.resize(ItemCount);
|
||||
SavedGameIndex.resize(ItemCount, -1);
|
||||
for (int i = 0; i < ItemCount; ++i) {
|
||||
Items[i].Read(in);
|
||||
}
|
||||
|
||||
if (gui_version >= kGuiVersion_272d && gui_version < kGuiVersion_350 &&
|
||||
(ListBoxFlags & kListBox_SvgIndex)) { // NOTE: reading into actual variables only for old savegame support
|
||||
for (int i = 0; i < ItemCount; ++i)
|
||||
SavedGameIndex[i] = in->ReadInt16();
|
||||
}
|
||||
|
||||
if (TextColor == 0)
|
||||
TextColor = 16;
|
||||
|
||||
UpdateMetrics();
|
||||
}
|
||||
|
||||
void GUIListBox::ReadFromSavegame(Stream *in, GuiSvgVersion svg_ver) {
|
||||
GUIObject::ReadFromSavegame(in, svg_ver);
|
||||
// Properties
|
||||
ListBoxFlags = in->ReadInt32();
|
||||
Font = in->ReadInt32();
|
||||
if (svg_ver < kGuiSvgVersion_350) {
|
||||
// reverse particular flags from older format
|
||||
ListBoxFlags ^= kListBox_OldFmtXorMask;
|
||||
} else {
|
||||
SelectedBgColor = in->ReadInt32();
|
||||
SelectedTextColor = in->ReadInt32();
|
||||
TextAlignment = (HorAlignment)in->ReadInt32();
|
||||
TextColor = in->ReadInt32();
|
||||
}
|
||||
|
||||
// Items
|
||||
ItemCount = in->ReadInt32();
|
||||
Items.resize(ItemCount);
|
||||
SavedGameIndex.resize(ItemCount);
|
||||
for (int i = 0; i < ItemCount; ++i)
|
||||
Items[i] = StrUtil::ReadString(in);
|
||||
// TODO: investigate this, it might be unreasonable to save and read
|
||||
// savegame index like that because list of savegames may easily change
|
||||
// in between writing and restoring the game. Perhaps clearing and forcing
|
||||
// this list to update on load somehow may make more sense.
|
||||
if (ListBoxFlags & kListBox_SvgIndex)
|
||||
for (int i = 0; i < ItemCount; ++i)
|
||||
SavedGameIndex[i] = in->ReadInt16();
|
||||
TopItem = in->ReadInt32();
|
||||
SelectedItem = in->ReadInt32();
|
||||
|
||||
UpdateMetrics();
|
||||
}
|
||||
|
||||
void GUIListBox::WriteToSavegame(Stream *out) const {
|
||||
GUIObject::WriteToSavegame(out);
|
||||
// Properties
|
||||
out->WriteInt32(ListBoxFlags);
|
||||
out->WriteInt32(Font);
|
||||
out->WriteInt32(SelectedBgColor);
|
||||
out->WriteInt32(SelectedTextColor);
|
||||
out->WriteInt32(TextAlignment);
|
||||
out->WriteInt32(TextColor);
|
||||
|
||||
// Items
|
||||
out->WriteInt32(ItemCount);
|
||||
for (int i = 0; i < ItemCount; ++i)
|
||||
StrUtil::WriteString(Items[i], out);
|
||||
if (ListBoxFlags & kListBox_SvgIndex)
|
||||
for (int i = 0; i < ItemCount; ++i)
|
||||
out->WriteInt16(SavedGameIndex[i]);
|
||||
out->WriteInt32(TopItem);
|
||||
out->WriteInt32(SelectedItem);
|
||||
}
|
||||
|
||||
} // namespace Shared
|
||||
} // namespace AGS
|
||||
} // namespace AGS3
|
||||
103
engines/ags/shared/gui/gui_listbox.h
Normal file
103
engines/ags/shared/gui/gui_listbox.h
Normal file
@@ -0,0 +1,103 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AGS_SHARED_GUI_GUI_LISTBOX_H
|
||||
#define AGS_SHARED_GUI_GUI_LISTBOX_H
|
||||
|
||||
#include "common/std/vector.h"
|
||||
#include "ags/shared/gui/gui_object.h"
|
||||
#include "ags/shared/util/string.h"
|
||||
|
||||
namespace AGS3 {
|
||||
namespace AGS {
|
||||
namespace Shared {
|
||||
|
||||
class GUIListBox : public GUIObject {
|
||||
public:
|
||||
GUIListBox();
|
||||
|
||||
bool HasAlphaChannel() const override;
|
||||
bool AreArrowsShown() const;
|
||||
bool IsBorderShown() const;
|
||||
bool IsSvgIndex() const;
|
||||
bool IsInRightMargin(int x) const;
|
||||
int GetItemAt(int x, int y) const;
|
||||
|
||||
// Operations
|
||||
int AddItem(const String &text);
|
||||
void Clear();
|
||||
Rect CalcGraphicRect(bool clipped) 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);
|
||||
void SetShowBorder(bool on);
|
||||
void SetSvgIndex(bool on); // TODO: work around this
|
||||
void SetFont(int font);
|
||||
void SetItemText(int index, const String &textt);
|
||||
|
||||
// Events
|
||||
bool OnMouseDown() override;
|
||||
void OnMouseMove(int x, int y) override;
|
||||
void OnResized() override;
|
||||
|
||||
// Serialization
|
||||
void ReadFromFile(Stream *in, GuiVersion gui_version) override;
|
||||
void WriteToFile(Stream *out) const override;
|
||||
void ReadFromSavegame(Shared::Stream *in, GuiSvgVersion svg_ver) override;
|
||||
void WriteToSavegame(Shared::Stream *out) const override;
|
||||
|
||||
// TODO: these members are currently public; hide them later
|
||||
public:
|
||||
int32_t Font;
|
||||
color_t TextColor;
|
||||
HorAlignment TextAlignment;
|
||||
color_t SelectedBgColor;
|
||||
color_t SelectedTextColor;
|
||||
int32_t RowHeight;
|
||||
int32_t VisibleItemCount;
|
||||
|
||||
std::vector<String> Items;
|
||||
std::vector<int16_t> SavedGameIndex;
|
||||
int32_t SelectedItem;
|
||||
int32_t TopItem;
|
||||
Point MousePos;
|
||||
|
||||
// TODO: remove these later
|
||||
int32_t ItemCount;
|
||||
|
||||
private:
|
||||
int32_t ListBoxFlags;
|
||||
|
||||
// Updates dynamic metrics such as row height and others
|
||||
void UpdateMetrics();
|
||||
// Applies translation
|
||||
void PrepareTextToDraw(const String &text);
|
||||
|
||||
// prepared text buffer/cache
|
||||
String _textToDraw;
|
||||
};
|
||||
|
||||
} // namespace Shared
|
||||
} // namespace AGS
|
||||
} // namespace AGS3
|
||||
|
||||
#endif
|
||||
1008
engines/ags/shared/gui/gui_main.cpp
Normal file
1008
engines/ags/shared/gui/gui_main.cpp
Normal file
File diff suppressed because it is too large
Load Diff
301
engines/ags/shared/gui/gui_main.h
Normal file
301
engines/ags/shared/gui/gui_main.h
Normal file
@@ -0,0 +1,301 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AGS_SHARED_GUI_GUI_MAIN_H
|
||||
#define AGS_SHARED_GUI_GUI_MAIN_H
|
||||
|
||||
#include "common/std/vector.h"
|
||||
#include "ags/engine/ac/draw.h"
|
||||
#include "ags/shared/ac/common.h"
|
||||
#include "ags/shared/ac/common_defines.h" // TODO: split out gui drawing helpers
|
||||
#include "ags/shared/gfx/gfx_def.h" // TODO: split out gui drawing helpers
|
||||
#include "ags/shared/gui/gui_defines.h"
|
||||
#include "ags/shared/util/error.h"
|
||||
#include "ags/shared/util/geometry.h"
|
||||
#include "ags/shared/util/string.h"
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
// Forward declaration
|
||||
namespace AGS {
|
||||
namespace Shared {
|
||||
class Stream;
|
||||
}
|
||||
}
|
||||
using namespace AGS; // FIXME later
|
||||
|
||||
class SplitLines;
|
||||
|
||||
#define LEGACY_MAX_OBJS_ON_GUI 30
|
||||
|
||||
#define GUIMAIN_LEGACY_RESERVED_INTS 5
|
||||
#define GUIMAIN_LEGACY_NAME_LENGTH 16
|
||||
#define GUIMAIN_LEGACY_EVENTHANDLER_LENGTH 20
|
||||
#define GUIMAIN_LEGACY_TW_FLAGS_SIZE 4
|
||||
|
||||
namespace AGS {
|
||||
namespace Shared {
|
||||
|
||||
// Legacy GUIMain visibility state, which combined Visible property and override factor
|
||||
enum LegacyGUIVisState {
|
||||
kGUIVisibility_LockedOff = -1, // locked hidden (used by PopupMouseY guis)
|
||||
kGUIVisibility_Off = 0, // hidden
|
||||
kGUIVisibility_On = 1 // shown
|
||||
};
|
||||
|
||||
class Bitmap;
|
||||
class GUIObject;
|
||||
|
||||
|
||||
class GUIMain {
|
||||
public:
|
||||
static String FixupGUIName(const String &name);
|
||||
|
||||
public:
|
||||
GUIMain();
|
||||
|
||||
void InitDefaults();
|
||||
|
||||
// Tells if the gui background supports alpha channel
|
||||
bool HasAlphaChannel() const;
|
||||
// Tells if GUI will react on clicking on it
|
||||
bool IsClickable() const { return (_flags & kGUIMain_Clickable) != 0; }
|
||||
// Tells if GUI's visibility is overridden and it won't be displayed on
|
||||
// screen regardless of Visible property (until concealed mode is off).
|
||||
bool IsConcealed() const { return (_flags & kGUIMain_Concealed) != 0; }
|
||||
// Tells if gui is actually meant to be displayed on screen.
|
||||
// Normally Visible property determines whether GUI is allowed to be seen,
|
||||
// but there may be other settings that override it.
|
||||
bool IsDisplayed() const { return IsVisible() && !IsConcealed(); }
|
||||
// Tells if given coordinates are within interactable area of gui
|
||||
// NOTE: this currently tests for actual visibility and Clickable property
|
||||
bool IsInteractableAt(int x, int y) const;
|
||||
// Tells if gui is a text window
|
||||
bool IsTextWindow() const { return (_flags & kGUIMain_TextWindow) != 0; }
|
||||
// Tells if GUI is *allowed* to be displayed and interacted with.
|
||||
// This does not necessarily mean that it is displayed right now, because
|
||||
// GUI may be hidden for other reasons, including overriding behavior.
|
||||
// For example GUI with kGUIPopupMouseY style will not be shown unless
|
||||
// mouse cursor is at certain position on screen.
|
||||
bool IsVisible() const { return (_flags & kGUIMain_Visible) != 0; }
|
||||
|
||||
// Tells if GUI has graphically changed recently
|
||||
bool HasChanged() const { return _hasChanged; }
|
||||
bool HasControlsChanged() const { return _hasControlsChanged; }
|
||||
// Manually marks GUI as graphically changed
|
||||
// NOTE: this only matters if GUI's own graphic changes (content, size etc),
|
||||
// but not its state (visible) or texture drawing mode (transparency, etc).
|
||||
void MarkChanged();
|
||||
// Marks GUI as having any of its controls changed its looks.
|
||||
void MarkControlChanged();
|
||||
// Clears changed flag
|
||||
void ClearChanged();
|
||||
// Notify GUI about any of its controls changing its location.
|
||||
void NotifyControlPosition();
|
||||
// Notify GUI about one of its controls changing its interactive state.
|
||||
void NotifyControlState(int objid, bool mark_changed);
|
||||
// Resets control-under-mouse detection.
|
||||
void ResetOverControl();
|
||||
|
||||
// Finds a control under given screen coordinates, returns control's child ID.
|
||||
// Optionally allows extra leeway (offset in all directions) to let the user grab tiny controls.
|
||||
// Optionally only allows clickable controls, ignoring non-clickable ones.
|
||||
int32_t FindControlAt(int atx, int aty, int leeway = 0, bool must_be_clickable = true) const;
|
||||
// Gets the number of the GUI child controls
|
||||
int32_t GetControlCount() const;
|
||||
// Gets control by its child's index
|
||||
GUIObject *GetControl(int32_t index) const;
|
||||
// Gets child control's type, looks up with child's index
|
||||
GUIControlType GetControlType(int32_t index) const;
|
||||
// Gets child control's global ID, looks up with child's index
|
||||
int32_t GetControlID(int32_t index) const;
|
||||
// Gets an array of child control indexes in the z-order, from bottom to top
|
||||
const std::vector<int> &GetControlsDrawOrder() const;
|
||||
|
||||
// Child control management
|
||||
// Note that currently GUIMain does not own controls (should not delete them)
|
||||
void AddControl(GUIControlType type, int32_t id, GUIObject *control);
|
||||
void RemoveAllControls();
|
||||
|
||||
// Operations
|
||||
bool BringControlToFront(int32_t index);
|
||||
void DrawSelf(Bitmap *ds);
|
||||
void DrawWithControls(Bitmap *ds);
|
||||
// Polls GUI state, providing current cursor (mouse) coordinates
|
||||
void Poll(int mx, int my);
|
||||
HError RebuildArray();
|
||||
void ResortZOrder();
|
||||
bool SendControlToBack(int32_t index);
|
||||
// Sets whether GUI should react to player clicking on it
|
||||
void SetClickable(bool on);
|
||||
// Override GUI visibility; when in concealed mode GUI won't show up
|
||||
// even if Visible = true
|
||||
void SetConceal(bool on);
|
||||
// Attempts to change control's zorder; returns if zorder changed
|
||||
bool SetControlZOrder(int32_t index, int zorder);
|
||||
// Changes GUI style to the text window or back
|
||||
void SetTextWindow(bool on);
|
||||
// Sets GUI transparency as a percentage (0 - 100) where 100 = invisible
|
||||
void SetTransparencyAsPercentage(int percent);
|
||||
// Sets whether GUI is allowed to be displayed on screen
|
||||
void SetVisible(bool on);
|
||||
|
||||
// Events
|
||||
void OnMouseButtonDown(int mx, int my);
|
||||
void OnMouseButtonUp();
|
||||
|
||||
// Serialization
|
||||
void ReadFromFile(Stream *in, GuiVersion gui_version);
|
||||
void WriteToFile(Stream *out) const;
|
||||
// TODO: move to engine, into gui savegame component unit
|
||||
// (should read/write GUI properties accessing them by interface)
|
||||
void ReadFromSavegame(Stream *in, GuiSvgVersion svg_version);
|
||||
void WriteToSavegame(Stream *out) const;
|
||||
|
||||
private:
|
||||
void DrawBlob(Bitmap *ds, int x, int y, color_t draw_color);
|
||||
// Same as FindControlAt but expects local space coordinates
|
||||
int32_t FindControlAtLocal(int atx, int aty, int leeway, bool must_be_clickable) const;
|
||||
|
||||
// TODO: all members are currently public; hide them later
|
||||
public:
|
||||
int32_t ID; // GUI identifier
|
||||
String Name; // the name of the GUI
|
||||
|
||||
int32_t X;
|
||||
int32_t Y;
|
||||
int32_t Width;
|
||||
int32_t Height;
|
||||
color_t BgColor; // background color
|
||||
int32_t BgImage; // background sprite index
|
||||
color_t FgColor; // foreground color (used as border color in normal GUIs,
|
||||
// and text color in text windows)
|
||||
int32_t Padding; // padding surrounding a GUI text window
|
||||
GUIPopupStyle PopupStyle; // GUI popup behavior
|
||||
int32_t PopupAtMouseY; // popup when _G(mousey) < this
|
||||
int32_t Transparency; // "incorrect" alpha (in legacy 255-range units)
|
||||
int32_t ZOrder;
|
||||
|
||||
int32_t FocusCtrl; // which control has the focus
|
||||
int32_t HighlightCtrl; // which control has the bounding selection rect
|
||||
int32_t MouseOverCtrl; // which control has the mouse cursor over it
|
||||
int32_t MouseDownCtrl; // which control has the mouse button pressed on it
|
||||
Point MouseWasAt; // last mouse cursor position
|
||||
|
||||
String OnClickHandler; // script function name
|
||||
|
||||
private:
|
||||
int32_t _flags; // style and behavior flags
|
||||
bool _hasChanged; // flag tells whether GUI has graphically changed recently
|
||||
bool _hasControlsChanged;
|
||||
bool _polling; // inside the polling process
|
||||
|
||||
// Array of types and control indexes in global GUI object arrays;
|
||||
// maps GUI child slots to actual controls and used for rebuilding Controls array
|
||||
typedef std::pair<GUIControlType, int32_t> ControlRef;
|
||||
std::vector<ControlRef> _ctrlRefs;
|
||||
// Array of child control references (not exclusively owned!)
|
||||
std::vector<GUIObject *> _controls;
|
||||
// Sorted array of controls in z-order.
|
||||
std::vector<int> _ctrlDrawOrder;
|
||||
};
|
||||
|
||||
|
||||
namespace GUI {
|
||||
extern GuiVersion GameGuiVersion;
|
||||
extern GuiOptions Options;
|
||||
|
||||
// Applies current text direction setting (may depend on multiple factors)
|
||||
String ApplyTextDirection(const String &text);
|
||||
// Calculates the text's draw position, given the alignment
|
||||
// optionally returns the real graphical rect that the text would occupy
|
||||
Point CalcTextPosition(const char *text, int font, const Rect &frame, FrameAlignment align, Rect *gr_rect = nullptr);
|
||||
// Calculates the text's draw position and horizontal extent,
|
||||
// using strictly horizontal alignment
|
||||
Line CalcTextPositionHor(const char *text, int font, int x1, int x2, int y, FrameAlignment align);
|
||||
// Calculates the graphical rect that the text would occupy
|
||||
// if drawn at the given coordinates
|
||||
Rect CalcTextGraphicalRect(const char *text, int font, const Point &at);
|
||||
// Calculates the graphical rect that the text would occupy
|
||||
// if drawn aligned to the given frame
|
||||
Rect CalcTextGraphicalRect(const char *text, int font, const Rect &frame, FrameAlignment align);
|
||||
// Calculates a vertical graphical extent for a given font,
|
||||
// which is a top and bottom offsets in zero-based coordinates.
|
||||
// NOTE: this applies font size fixups.
|
||||
Line CalcFontGraphicalVExtent(int font);
|
||||
// Draw standart "shading" effect over rectangle
|
||||
void DrawDisabledEffect(Bitmap *ds, const Rect &rc);
|
||||
// Draw text aligned inside rectangle
|
||||
void DrawTextAligned(Bitmap *ds, const char *text, int font, color_t text_color, const Rect &frame, FrameAlignment align);
|
||||
// Draw text aligned horizontally inside given bounds
|
||||
void DrawTextAlignedHor(Bitmap *ds, const char *text, int font, color_t text_color, int x1, int x2, int y, FrameAlignment align);
|
||||
|
||||
// Parses the string and returns combination of label macro flags
|
||||
GUILabelMacro FindLabelMacros(const String &text);
|
||||
// Applies text transformation necessary for rendering, in accordance to the
|
||||
// current game settings, such as right-to-left render, and anything else
|
||||
String TransformTextForDrawing(const String &text, bool translate, bool apply_direction);
|
||||
// Wraps given text to make it fit into width, stores it in the lines;
|
||||
// apply_direction param tells whether text direction setting should be applied
|
||||
size_t SplitLinesForDrawing(const char *text, bool apply_direction, SplitLines &lines, int font, int width, size_t max_lines = -1);
|
||||
|
||||
// Mark all existing GUI for redraw
|
||||
void MarkAllGUIForUpdate(bool redraw, bool reset_over_ctrl);
|
||||
// Mark all translatable GUI controls for redraw
|
||||
void MarkForTranslationUpdate();
|
||||
// Mark all GUI which use the given font for recalculate/redraw;
|
||||
// pass -1 to update all the textual controls together
|
||||
void MarkForFontUpdate(int font);
|
||||
// Mark labels that acts as special text placeholders for redraw
|
||||
void MarkSpecialLabelsForUpdate(GUILabelMacro macro);
|
||||
// Mark inventory windows for redraw, optionally only ones linked to given character;
|
||||
// also marks buttons with inventory icon mode
|
||||
void MarkInventoryForUpdate(int char_id, bool is_player);
|
||||
|
||||
// Reads all GUIs and their controls.
|
||||
// WARNING: the data is read into the global arrays (guis, guibuts, and so on)
|
||||
// TODO: remove is_savegame param after dropping support for old saves
|
||||
// because only they use ReadGUI to read runtime GUI data
|
||||
HError ReadGUI(Stream *in, bool is_savegame = false);
|
||||
// Writes all GUIs and their controls.
|
||||
// WARNING: the data is written from the global arrays (guis, guibuts, and so on)
|
||||
void WriteGUI(Stream *out);
|
||||
// Converts legacy GUIVisibility into appropriate GUIMain properties
|
||||
void ApplyLegacyVisibility(GUIMain &gui, LegacyGUIVisState vis);
|
||||
|
||||
// Rebuilds GUIs, connecting them to the child controls in memory.
|
||||
// WARNING: the data is processed in the global arrays (guis, guibuts, and so on)
|
||||
HError RebuildGUI();
|
||||
}
|
||||
|
||||
} // namespace Shared
|
||||
} // namespace AGS
|
||||
|
||||
extern int get_adjusted_spritewidth(int spr);
|
||||
extern int get_adjusted_spriteheight(int spr);
|
||||
extern bool is_sprite_alpha(int spr);
|
||||
|
||||
extern void set_eip_guiobj(int eip);
|
||||
extern int get_eip_guiobj();
|
||||
|
||||
} // namespace AGS3
|
||||
|
||||
#endif
|
||||
223
engines/ags/shared/gui/gui_object.cpp
Normal file
223
engines/ags/shared/gui/gui_object.cpp
Normal file
@@ -0,0 +1,223 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ags/shared/ac/common.h" // quit
|
||||
#include "ags/shared/gui/gui_main.h"
|
||||
#include "ags/shared/gui/gui_object.h"
|
||||
#include "ags/shared/util/stream.h"
|
||||
|
||||
namespace AGS3 {
|
||||
namespace AGS {
|
||||
namespace Shared {
|
||||
|
||||
GUIObject::GUIObject() {
|
||||
Id = 0;
|
||||
ParentId = 0;
|
||||
Flags = kGUICtrl_DefFlags;
|
||||
X = 0;
|
||||
Y = 0;
|
||||
_width = 0;
|
||||
_height = 0;
|
||||
ZOrder = -1;
|
||||
IsActivated = false;
|
||||
_transparency = 0;
|
||||
_scEventCount = 0;
|
||||
_hasChanged = true;
|
||||
}
|
||||
|
||||
String GUIObject::GetScriptName() const {
|
||||
return Name;
|
||||
}
|
||||
|
||||
int GUIObject::GetEventCount() const {
|
||||
return _scEventCount;
|
||||
}
|
||||
|
||||
String GUIObject::GetEventName(int event) const {
|
||||
if (event < 0 || event >= _scEventCount)
|
||||
return "";
|
||||
return _scEventNames[event];
|
||||
}
|
||||
|
||||
String GUIObject::GetEventArgs(int event) const {
|
||||
if (event < 0 || event >= _scEventCount)
|
||||
return "";
|
||||
return _scEventArgs[event];
|
||||
}
|
||||
|
||||
bool GUIObject::IsOverControl(int x, int y, int leeway) const {
|
||||
return x >= X && y >= Y && x < (X + _width + leeway) && y < (Y + _height + leeway);
|
||||
}
|
||||
|
||||
void GUIObject::SetClickable(bool on) {
|
||||
if (on != ((Flags & kGUICtrl_Clickable) != 0)) {
|
||||
Flags = (Flags & ~kGUICtrl_Clickable) | kGUICtrl_Clickable * on;
|
||||
MarkStateChanged(false, false); // update cursor-over-control only
|
||||
}
|
||||
}
|
||||
|
||||
void GUIObject::SetEnabled(bool on) {
|
||||
if (on != ((Flags & kGUICtrl_Enabled) != 0)) {
|
||||
Flags = (Flags & ~kGUICtrl_Enabled) | kGUICtrl_Enabled * on;
|
||||
MarkStateChanged(true, true); // may change looks, and update cursor-over-control
|
||||
}
|
||||
}
|
||||
|
||||
void GUIObject::SetSize(int width, int height) {
|
||||
if (_width != width || _height != height) {
|
||||
_width = width;
|
||||
_height = height;
|
||||
OnResized();
|
||||
}
|
||||
}
|
||||
|
||||
void GUIObject::SetTranslated(bool on) {
|
||||
if (on != ((Flags & kGUICtrl_Translated) != 0)) {
|
||||
Flags = (Flags & ~kGUICtrl_Translated) | kGUICtrl_Translated * on;
|
||||
MarkChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void GUIObject::SetVisible(bool on) {
|
||||
if (on != ((Flags & kGUICtrl_Visible) != 0)) {
|
||||
Flags = (Flags & ~kGUICtrl_Visible) | kGUICtrl_Visible * on;
|
||||
MarkStateChanged(false, true); // for software mode, and to update cursor-over-control
|
||||
}
|
||||
}
|
||||
|
||||
void GUIObject::SetTransparency(int trans) {
|
||||
if (_transparency != trans) {
|
||||
_transparency = trans;
|
||||
MarkParentChanged(); // for software mode
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: replace string serialization with StrUtil::ReadString and WriteString
|
||||
// methods in the future, to keep this organized.
|
||||
void GUIObject::WriteToFile(Stream *out) const {
|
||||
out->WriteInt32(Flags);
|
||||
out->WriteInt32(X);
|
||||
out->WriteInt32(Y);
|
||||
out->WriteInt32(_width);
|
||||
out->WriteInt32(_height);
|
||||
out->WriteInt32(ZOrder);
|
||||
Name.Write(out);
|
||||
out->WriteInt32(_scEventCount);
|
||||
for (int i = 0; i < _scEventCount; ++i)
|
||||
EventHandlers[i].Write(out);
|
||||
}
|
||||
|
||||
void GUIObject::ReadFromFile(Stream *in, GuiVersion gui_version) {
|
||||
Flags = in->ReadInt32();
|
||||
// reverse particular flags from older format
|
||||
if (gui_version < kGuiVersion_350)
|
||||
Flags ^= kGUICtrl_OldFmtXorMask;
|
||||
X = in->ReadInt32();
|
||||
Y = in->ReadInt32();
|
||||
_width = in->ReadInt32();
|
||||
_height = in->ReadInt32();
|
||||
ZOrder = in->ReadInt32();
|
||||
if (gui_version < kGuiVersion_350) { // NOTE: reading into actual variables only for old savegame support
|
||||
IsActivated = in->ReadInt32() != 0;
|
||||
}
|
||||
|
||||
if (gui_version >= kGuiVersion_unkn_106)
|
||||
Name.Read(in);
|
||||
else
|
||||
Name.Free();
|
||||
|
||||
for (int i = 0; i < _scEventCount; ++i) {
|
||||
EventHandlers[i].Free();
|
||||
}
|
||||
|
||||
if (gui_version >= kGuiVersion_unkn_108) {
|
||||
int evt_count = in->ReadInt32();
|
||||
if (evt_count > _scEventCount)
|
||||
quit("Error: too many control events, need newer version");
|
||||
for (int i = 0; i < evt_count; ++i) {
|
||||
EventHandlers[i].Read(in);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GUIObject::ReadFromSavegame(Stream *in, GuiSvgVersion svg_ver) {
|
||||
// Properties
|
||||
Flags = in->ReadInt32();
|
||||
// reverse particular flags from older format
|
||||
if (svg_ver < kGuiSvgVersion_350)
|
||||
Flags ^= kGUICtrl_OldFmtXorMask;
|
||||
X = in->ReadInt32();
|
||||
Y = in->ReadInt32();
|
||||
_width = in->ReadInt32();
|
||||
_height = in->ReadInt32();
|
||||
ZOrder = in->ReadInt32();
|
||||
// Dynamic state
|
||||
IsActivated = in->ReadBool() ? 1 : 0;
|
||||
if (svg_ver >= kGuiSvgVersion_36023) {
|
||||
_transparency = in->ReadInt32();
|
||||
in->ReadInt32(); // reserve 3 ints
|
||||
in->ReadInt32();
|
||||
in->ReadInt32();
|
||||
}
|
||||
}
|
||||
|
||||
void GUIObject::WriteToSavegame(Stream *out) const {
|
||||
// Properties
|
||||
out->WriteInt32(Flags);
|
||||
out->WriteInt32(X);
|
||||
out->WriteInt32(Y);
|
||||
out->WriteInt32(_width);
|
||||
out->WriteInt32(_height);
|
||||
out->WriteInt32(ZOrder);
|
||||
// Dynamic state
|
||||
out->WriteBool(IsActivated != 0);
|
||||
out->WriteInt32(_transparency);
|
||||
out->WriteInt32(0); // reserve 3 ints
|
||||
out->WriteInt32(0);
|
||||
out->WriteInt32(0);
|
||||
}
|
||||
|
||||
|
||||
HorAlignment ConvertLegacyGUIAlignment(LegacyGUIAlignment align) {
|
||||
switch (align) {
|
||||
case kLegacyGUIAlign_Right:
|
||||
return kHAlignRight;
|
||||
case kLegacyGUIAlign_Center:
|
||||
return kHAlignCenter;
|
||||
default:
|
||||
return kHAlignLeft;
|
||||
}
|
||||
}
|
||||
|
||||
LegacyGUIAlignment GetLegacyGUIAlignment(HorAlignment align) {
|
||||
switch (align) {
|
||||
case kHAlignRight:
|
||||
return kLegacyGUIAlign_Right;
|
||||
case kHAlignCenter:
|
||||
return kLegacyGUIAlign_Center;
|
||||
default:
|
||||
return kLegacyGUIAlign_Left;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Shared
|
||||
} // namespace AGS
|
||||
} // namespace AGS3
|
||||
172
engines/ags/shared/gui/gui_object.h
Normal file
172
engines/ags/shared/gui/gui_object.h
Normal file
@@ -0,0 +1,172 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AGS_SHARED_GUI_GUI_OBJECT_H
|
||||
#define AGS_SHARED_GUI_GUI_OBJECT_H
|
||||
|
||||
#include "ags/shared/core/types.h"
|
||||
#include "ags/shared/gfx/bitmap.h"
|
||||
#include "ags/shared/gui/gui_defines.h"
|
||||
#include "ags/shared/util/string.h"
|
||||
#include "ags/globals.h"
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
struct KeyInput;
|
||||
|
||||
namespace AGS {
|
||||
namespace Shared {
|
||||
|
||||
enum LegacyGUIAlignment {
|
||||
kLegacyGUIAlign_Left = 0,
|
||||
kLegacyGUIAlign_Right = 1,
|
||||
kLegacyGUIAlign_Center = 2
|
||||
};
|
||||
|
||||
class GUIObject {
|
||||
public:
|
||||
GUIObject();
|
||||
virtual ~GUIObject() {}
|
||||
|
||||
String GetScriptName() const;
|
||||
|
||||
String GetEventArgs(int event) const;
|
||||
int GetEventCount() const;
|
||||
String GetEventName(int event) const;
|
||||
bool IsClickable() const { return (Flags & kGUICtrl_Clickable) != 0; }
|
||||
bool IsDeleted() const { return (Flags & kGUICtrl_Deleted) != 0; }
|
||||
bool IsEnabled() const { return (Flags & kGUICtrl_Enabled) != 0; }
|
||||
bool IsTranslated() const { return (Flags & kGUICtrl_Translated) != 0; }
|
||||
bool IsVisible() const { return (Flags & kGUICtrl_Visible) != 0; }
|
||||
// overridable routine to determine whether the mouse is over the control
|
||||
virtual bool IsOverControl(int x, int y, int leeway) const;
|
||||
Size GetSize() const { return Size(_width, _height); }
|
||||
int GetWidth() const { return _width; }
|
||||
int GetHeight() const { return _height; }
|
||||
int GetTransparency() const { return _transparency; }
|
||||
// Compatibility: should the control's graphic be clipped to its x,y,w,h
|
||||
virtual bool IsContentClipped() const { return true; }
|
||||
// Tells if the object image supports alpha channel
|
||||
virtual bool HasAlphaChannel() const { return false; }
|
||||
|
||||
// Operations
|
||||
// Returns the (untransformed!) visual rectangle of this control,
|
||||
// in *relative* coordinates, optionally clipped by the logical size
|
||||
virtual Rect CalcGraphicRect(bool /*clipped*/) {
|
||||
return RectWH(0, 0, _width, _height);
|
||||
}
|
||||
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);
|
||||
void SetSize(int width, int height);
|
||||
inline void SetWidth(int width) { SetSize(width, _height); }
|
||||
inline void SetHeight(int height) { SetSize(_width, height); }
|
||||
void SetTranslated(bool on);
|
||||
void SetVisible(bool on);
|
||||
void SetTransparency(int trans);
|
||||
|
||||
// Events
|
||||
// Key pressed for control
|
||||
virtual void OnKeyPress(const KeyInput &) {}
|
||||
// Mouse button down - return 'True' to lock focus
|
||||
virtual bool OnMouseDown() {
|
||||
return false;
|
||||
}
|
||||
// Mouse moves onto control
|
||||
virtual void OnMouseEnter() {
|
||||
}
|
||||
// Mouse moves off control
|
||||
virtual void OnMouseLeave() {
|
||||
}
|
||||
// Mouse moves over control - x,y relative to gui
|
||||
virtual void OnMouseMove(int /*x*/, int /*y*/) {
|
||||
}
|
||||
// Mouse button up
|
||||
virtual void OnMouseUp() {
|
||||
}
|
||||
// Control was resized
|
||||
virtual void OnResized() { MarkPositionChanged(true); }
|
||||
|
||||
// Serialization
|
||||
virtual void ReadFromFile(Shared::Stream *in, GuiVersion gui_version);
|
||||
virtual void WriteToFile(Shared::Stream *out) const;
|
||||
virtual void ReadFromSavegame(Shared::Stream *in, GuiSvgVersion svg_ver);
|
||||
virtual void WriteToSavegame(Shared::Stream *out) const;
|
||||
|
||||
// TODO: these members are currently public; hide them later
|
||||
public:
|
||||
// Manually marks GUIObject as graphically changed
|
||||
// NOTE: this only matters if control's own graphic changes, but not its
|
||||
// logical (visible, clickable, etc) or visual (e.g. transparency) state.
|
||||
void MarkChanged();
|
||||
// Notifies parent GUI that this control has changed its visual state
|
||||
void MarkParentChanged();
|
||||
// Notifies parent GUI that this control has changed its location (pos, size)
|
||||
void MarkPositionChanged(bool self_changed);
|
||||
// Notifies parent GUI that this control's interactive state has changed
|
||||
void MarkStateChanged(bool self_changed, bool parent_changed);
|
||||
bool HasChanged() const { return _hasChanged; };
|
||||
void ClearChanged();
|
||||
|
||||
int32_t Id; // GUI object's identifier
|
||||
int32_t ParentId; // id of parent GUI
|
||||
String Name; // script name
|
||||
|
||||
int32_t X;
|
||||
int32_t Y;
|
||||
int32_t ZOrder;
|
||||
bool IsActivated; // signals user interaction
|
||||
|
||||
String EventHandlers[MAX_GUIOBJ_EVENTS]; // script function names
|
||||
|
||||
protected:
|
||||
uint32_t Flags; // generic style and behavior flags
|
||||
int32_t _width;
|
||||
int32_t _height;
|
||||
int32_t _transparency; // "incorrect" alpha (in legacy 255-range units)
|
||||
bool _hasChanged;
|
||||
|
||||
// TODO: explicit event names & handlers for every event
|
||||
// FIXME: these must be static!! per type
|
||||
int32_t _scEventCount; // number of supported script events
|
||||
String _scEventNames[MAX_GUIOBJ_EVENTS]; // script event names
|
||||
String _scEventArgs[MAX_GUIOBJ_EVENTS]; // script handler params
|
||||
};
|
||||
|
||||
// Converts legacy alignment type used in GUI Label/ListBox data (only left/right/center)
|
||||
HorAlignment ConvertLegacyGUIAlignment(LegacyGUIAlignment align);
|
||||
LegacyGUIAlignment GetLegacyGUIAlignment(HorAlignment align);
|
||||
|
||||
} // namespace Shared
|
||||
} // namespace AGS
|
||||
|
||||
// Tells if all controls are disabled
|
||||
|
||||
// Tells if the given control is considered enabled, taking global flag into account
|
||||
inline bool IsGUIEnabled(AGS::Shared::GUIObject *g) {
|
||||
return (_G(all_buttons_disabled) < 0) && g->IsEnabled();
|
||||
}
|
||||
|
||||
} // namespace AGS3
|
||||
|
||||
#endif
|
||||
284
engines/ags/shared/gui/gui_slider.cpp
Normal file
284
engines/ags/shared/gui/gui_slider.cpp
Normal file
@@ -0,0 +1,284 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/std/algorithm.h"
|
||||
#include "ags/shared/ac/sprite_cache.h"
|
||||
#include "ags/shared/gui/gui_main.h"
|
||||
#include "ags/shared/gui/gui_slider.h"
|
||||
#include "ags/shared/util/stream.h"
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
namespace AGS {
|
||||
namespace Shared {
|
||||
|
||||
GUISlider::GUISlider() {
|
||||
MinValue = 0;
|
||||
MaxValue = 10;
|
||||
Value = 0;
|
||||
BgImage = 0;
|
||||
HandleImage = 0;
|
||||
HandleOffset = 0;
|
||||
IsMousePressed = false;
|
||||
|
||||
_scEventCount = 1;
|
||||
_scEventNames[0] = "Change";
|
||||
_scEventArgs[0] = "GUIControl *control";
|
||||
_handleRange = 0;
|
||||
}
|
||||
|
||||
bool GUISlider::IsHorizontal() const {
|
||||
return _width > _height;
|
||||
}
|
||||
|
||||
bool GUISlider::HasAlphaChannel() const {
|
||||
return is_sprite_alpha(BgImage) || is_sprite_alpha(HandleImage);
|
||||
}
|
||||
|
||||
bool GUISlider::IsOverControl(int x, int y, int leeway) const {
|
||||
// check the overall boundary
|
||||
if (GUIObject::IsOverControl(x, y, leeway))
|
||||
return true;
|
||||
// now check the handle too
|
||||
return _cachedHandle.IsInside(Point(x - X, y - Y));
|
||||
}
|
||||
|
||||
Rect GUISlider::CalcGraphicRect(bool /*clipped*/) {
|
||||
// Sliders are never clipped as of 3.6.0
|
||||
// TODO: precalculate everything on width/height/graphic change!!
|
||||
UpdateMetrics();
|
||||
Rect logical = RectWH(0, 0, _width, _height);
|
||||
Rect bar = _cachedBar;
|
||||
Rect handle = _cachedHandle;
|
||||
return Rect(
|
||||
MIN(MIN(logical.Left, bar.Left), handle.Left),
|
||||
MIN(MIN(logical.Top, bar.Top), handle.Top),
|
||||
MAX(MAX(logical.Right, bar.Right), handle.Right),
|
||||
MAX(MAX(logical.Bottom, bar.Bottom), handle.Bottom)
|
||||
);
|
||||
}
|
||||
|
||||
void GUISlider::UpdateMetrics() {
|
||||
// Clamp Value
|
||||
// TODO: this is necessary here because some Slider fields are still public
|
||||
if (MinValue >= MaxValue)
|
||||
MaxValue = MinValue + 1;
|
||||
Value = Math::Clamp(Value, MinValue, MaxValue);
|
||||
// Test if sprite is available; // TODO: return a placeholder from spriteset instead!
|
||||
const int handle_im = ((HandleImage > 0) && _GP(spriteset).DoesSpriteExist(HandleImage)) ? HandleImage : 0;
|
||||
|
||||
// Depending on slider's orientation, thickness is either Height or Width
|
||||
const int thickness = IsHorizontal() ? _height : _width;
|
||||
// "thick_f" is the factor for calculating relative element positions
|
||||
const int thick_f = thickness / 3; // one third of the control's thickness
|
||||
// Bar thickness
|
||||
const int bar_thick = thick_f * 2 + 2;
|
||||
|
||||
// Calculate handle size
|
||||
Size handle_sz;
|
||||
if (handle_im > 0) // handle is a sprite
|
||||
{
|
||||
handle_sz = Size(get_adjusted_spritewidth(handle_im),
|
||||
get_adjusted_spriteheight(handle_im));
|
||||
} else // handle is a drawn rectangle
|
||||
{
|
||||
if (IsHorizontal())
|
||||
handle_sz = Size(get_fixed_pixel_size(4) + 1, bar_thick + (thick_f - 1) * 2);
|
||||
else
|
||||
handle_sz = Size(bar_thick + (thick_f - 1) * 2, get_fixed_pixel_size(4) + 1);
|
||||
}
|
||||
|
||||
// Calculate bar and handle positions
|
||||
Rect bar;
|
||||
Rect handle;
|
||||
int handle_range;
|
||||
if (IsHorizontal()) // horizontal slider
|
||||
{
|
||||
// Value pos is a coordinate corresponding to current slider's value
|
||||
bar = RectWH(1, _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,
|
||||
bar.Top + (bar.GetHeight() - handle_sz.Height) / 2,
|
||||
handle_sz.Width, handle_sz.Height);
|
||||
handle.MoveToY(handle.Top + data_to_game_coord(HandleOffset));
|
||||
}
|
||||
// vertical slider
|
||||
else {
|
||||
bar = RectWH(_width / 2 - thick_f, 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,
|
||||
(bar.Top + get_fixed_pixel_size(2)) - (handle_sz.Height / 2) + 1 + value_pos - 2,
|
||||
handle_sz.Width, handle_sz.Height);
|
||||
handle.MoveToX(handle.Left + data_to_game_coord(HandleOffset));
|
||||
}
|
||||
|
||||
_cachedBar = bar;
|
||||
_cachedHandle = handle;
|
||||
_handleRange = MAX(1, handle_range);
|
||||
}
|
||||
|
||||
void GUISlider::Draw(Bitmap *ds, int x, int y) {
|
||||
UpdateMetrics();
|
||||
|
||||
Rect bar = Rect::MoveBy(_cachedBar, x, y);
|
||||
Rect handle = Rect::MoveBy(_cachedHandle, x, y);
|
||||
|
||||
color_t draw_color;
|
||||
if (BgImage > 0) {
|
||||
// tiled image as slider background
|
||||
int x_inc = 0;
|
||||
int y_inc = 0;
|
||||
if (IsHorizontal()) {
|
||||
x_inc = get_adjusted_spritewidth(BgImage);
|
||||
// centre the image vertically
|
||||
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;
|
||||
}
|
||||
int cx = bar.Left;
|
||||
int cy = bar.Top;
|
||||
// draw the tiled background image
|
||||
do {
|
||||
draw_gui_sprite(ds, BgImage, cx, cy, true);
|
||||
cx += x_inc;
|
||||
cy += y_inc;
|
||||
// done as a do..while so that at least one of the image is drawn
|
||||
} while ((cx + x_inc <= bar.Right) && (cy + y_inc <= bar.Bottom));
|
||||
} else {
|
||||
// normal grey background
|
||||
draw_color = ds->GetCompatibleColor(16);
|
||||
ds->FillRect(bar, draw_color);
|
||||
draw_color = ds->GetCompatibleColor(8);
|
||||
ds->DrawLine(Line(bar.Left, bar.Top, bar.Left, bar.Bottom), draw_color);
|
||||
ds->DrawLine(Line(bar.Left, bar.Top, bar.Right, bar.Top), draw_color);
|
||||
draw_color = ds->GetCompatibleColor(15);
|
||||
ds->DrawLine(Line(bar.Right, bar.Top + 1, bar.Right, bar.Bottom), draw_color);
|
||||
ds->DrawLine(Line(bar.Left, bar.Bottom, bar.Right, bar.Bottom), draw_color);
|
||||
}
|
||||
|
||||
// Test if sprite is available; // TODO: return a placeholder from spriteset instead!
|
||||
const int handle_im = ((HandleImage > 0) && _GP(spriteset).DoesSpriteExist(HandleImage)) ? HandleImage : 0;
|
||||
if (handle_im > 0) // handle is a sprite
|
||||
{
|
||||
draw_gui_sprite(ds, handle_im, handle.Left, handle.Top, true);
|
||||
} else // handle is a drawn rectangle
|
||||
{
|
||||
// normal grey tracker handle
|
||||
draw_color = ds->GetCompatibleColor(7);
|
||||
ds->FillRect(handle, draw_color);
|
||||
draw_color = ds->GetCompatibleColor(15);
|
||||
ds->DrawLine(Line(handle.Left, handle.Top, handle.Right, handle.Top), draw_color);
|
||||
ds->DrawLine(Line(handle.Left, handle.Top, handle.Left, handle.Bottom), draw_color);
|
||||
draw_color = ds->GetCompatibleColor(16);
|
||||
ds->DrawLine(Line(handle.Right, handle.Top + 1, handle.Right, handle.Bottom), draw_color);
|
||||
ds->DrawLine(Line(handle.Left + 1, handle.Bottom, handle.Right, handle.Bottom), draw_color);
|
||||
}
|
||||
}
|
||||
|
||||
bool GUISlider::OnMouseDown() {
|
||||
IsMousePressed = true;
|
||||
// lock focus to ourselves
|
||||
return true;
|
||||
}
|
||||
|
||||
void GUISlider::OnMouseMove(int x, int y) {
|
||||
if (!IsMousePressed)
|
||||
return;
|
||||
|
||||
int32_t value;
|
||||
assert(_handleRange > 0);
|
||||
if (IsHorizontal())
|
||||
value = (int)(((float)((x - X) - 2) * (float)(MaxValue - MinValue)) / (float)_handleRange) + MinValue;
|
||||
else
|
||||
value = (int)(((float)(((Y + _height) - y) - 2) * (float)(MaxValue - MinValue)) / (float)_handleRange) + MinValue;
|
||||
|
||||
value = Math::Clamp(value, MinValue, MaxValue);
|
||||
if (value != Value) {
|
||||
Value = value;
|
||||
MarkChanged();
|
||||
}
|
||||
IsActivated = true;
|
||||
}
|
||||
|
||||
void GUISlider::OnMouseUp() {
|
||||
IsMousePressed = false;
|
||||
}
|
||||
|
||||
void GUISlider::ReadFromFile(Stream *in, GuiVersion gui_version) {
|
||||
GUIObject::ReadFromFile(in, gui_version);
|
||||
MinValue = in->ReadInt32();
|
||||
MaxValue = in->ReadInt32();
|
||||
Value = in->ReadInt32();
|
||||
if (gui_version < kGuiVersion_350) { // NOTE: reading into actual variables only for old savegame support
|
||||
IsMousePressed = in->ReadInt32() != 0;
|
||||
}
|
||||
if (gui_version >= kGuiVersion_unkn_104) {
|
||||
HandleImage = in->ReadInt32();
|
||||
HandleOffset = in->ReadInt32();
|
||||
BgImage = in->ReadInt32();
|
||||
} else {
|
||||
HandleImage = -1;
|
||||
HandleOffset = 0;
|
||||
BgImage = 0;
|
||||
}
|
||||
|
||||
UpdateMetrics();
|
||||
}
|
||||
|
||||
void GUISlider::WriteToFile(Stream *out) const {
|
||||
GUIObject::WriteToFile(out);
|
||||
out->WriteInt32(MinValue);
|
||||
out->WriteInt32(MaxValue);
|
||||
out->WriteInt32(Value);
|
||||
out->WriteInt32(HandleImage);
|
||||
out->WriteInt32(HandleOffset);
|
||||
out->WriteInt32(BgImage);
|
||||
}
|
||||
|
||||
void GUISlider::ReadFromSavegame(Stream *in, GuiSvgVersion svg_ver) {
|
||||
GUIObject::ReadFromSavegame(in, svg_ver);
|
||||
BgImage = in->ReadInt32();
|
||||
HandleImage = in->ReadInt32();
|
||||
HandleOffset = in->ReadInt32();
|
||||
MinValue = in->ReadInt32();
|
||||
MaxValue = in->ReadInt32();
|
||||
Value = in->ReadInt32();
|
||||
|
||||
UpdateMetrics();
|
||||
}
|
||||
|
||||
void GUISlider::WriteToSavegame(Stream *out) const {
|
||||
GUIObject::WriteToSavegame(out);
|
||||
out->WriteInt32(BgImage);
|
||||
out->WriteInt32(HandleImage);
|
||||
out->WriteInt32(HandleOffset);
|
||||
out->WriteInt32(MinValue);
|
||||
out->WriteInt32(MaxValue);
|
||||
out->WriteInt32(Value);
|
||||
}
|
||||
|
||||
} // namespace Shared
|
||||
} // namespace AGS
|
||||
} // namespace AGS3
|
||||
85
engines/ags/shared/gui/gui_slider.h
Normal file
85
engines/ags/shared/gui/gui_slider.h
Normal file
@@ -0,0 +1,85 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AGS_SHARED_GUI_GUI_SLIDER_H
|
||||
#define AGS_SHARED_GUI_GUI_SLIDER_H
|
||||
|
||||
#include "common/std/vector.h"
|
||||
#include "ags/shared/gui/gui_object.h"
|
||||
|
||||
namespace AGS3 {
|
||||
namespace AGS {
|
||||
namespace Shared {
|
||||
|
||||
class GUISlider : public GUIObject {
|
||||
public:
|
||||
GUISlider();
|
||||
|
||||
// Tells if the slider is horizontal (otherwise - vertical)
|
||||
bool IsHorizontal() const;
|
||||
bool IsOverControl(int x, int y, int leeway) const override;
|
||||
|
||||
// Compatibility: sliders are not clipped as of 3.6.0
|
||||
bool IsContentClipped() const override { return false; }
|
||||
bool HasAlphaChannel() const override;
|
||||
|
||||
// Operations
|
||||
Rect CalcGraphicRect(bool clipped) override;
|
||||
void Draw(Bitmap *ds, int x = 0, int y = 0) override;
|
||||
|
||||
// Events
|
||||
bool OnMouseDown() override;
|
||||
void OnMouseMove(int xp, int yp) override;
|
||||
void OnMouseUp() override;
|
||||
|
||||
// Serialization
|
||||
void ReadFromFile(Stream *in, GuiVersion gui_version) override;
|
||||
void WriteToFile(Stream *out) const override;
|
||||
void ReadFromSavegame(Stream *in, GuiSvgVersion svg_ver) override;
|
||||
void WriteToSavegame(Stream *out) const override;
|
||||
|
||||
// TODO: these members are currently public; hide them later
|
||||
public:
|
||||
int32_t MinValue;
|
||||
int32_t MaxValue;
|
||||
int32_t Value;
|
||||
int32_t BgImage;
|
||||
int32_t HandleImage;
|
||||
int32_t HandleOffset;
|
||||
bool IsMousePressed;
|
||||
|
||||
private:
|
||||
// Updates dynamic metrics and positions of elements
|
||||
void UpdateMetrics();
|
||||
|
||||
// Cached coordinates of slider bar; in relative coords
|
||||
Rect _cachedBar;
|
||||
// Cached coordinates of slider handle; in relative coords
|
||||
Rect _cachedHandle;
|
||||
// The length of the handle movement range, in pixels
|
||||
int _handleRange;
|
||||
};
|
||||
|
||||
} // namespace Shared
|
||||
} // namespace AGS
|
||||
} // namespace AGS3
|
||||
|
||||
#endif
|
||||
177
engines/ags/shared/gui/gui_textbox.cpp
Normal file
177
engines/ags/shared/gui/gui_textbox.cpp
Normal file
@@ -0,0 +1,177 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ags/shared/ac/keycode.h"
|
||||
#include "ags/shared/font/fonts.h"
|
||||
#include "ags/shared/gui/gui_main.h"
|
||||
#include "ags/shared/gui/gui_textbox.h"
|
||||
#include "ags/shared/util/stream.h"
|
||||
#include "ags/shared/util/string_utils.h"
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
#define GUITEXTBOX_LEGACY_TEXTLEN 200
|
||||
|
||||
namespace AGS {
|
||||
namespace Shared {
|
||||
|
||||
GUITextBox::GUITextBox() {
|
||||
Font = 0;
|
||||
TextColor = 0;
|
||||
TextBoxFlags = kTextBox_DefFlags;
|
||||
|
||||
_scEventCount = 1;
|
||||
_scEventNames[0] = "Activate";
|
||||
_scEventArgs[0] = "GUIControl *control";
|
||||
}
|
||||
|
||||
bool GUITextBox::HasAlphaChannel() const {
|
||||
return is_font_antialiased(Font);
|
||||
}
|
||||
|
||||
bool GUITextBox::IsBorderShown() const {
|
||||
return (TextBoxFlags & kTextBox_ShowBorder) != 0;
|
||||
}
|
||||
|
||||
Rect GUITextBox::CalcGraphicRect(bool clipped) {
|
||||
if (clipped)
|
||||
return RectWH(0, 0, _width, _height);
|
||||
|
||||
// TODO: need to find a way to cache text position, or there'll be some repetition
|
||||
Rect rc = RectWH(0, 0, _width, _height);
|
||||
Point text_at(1 + get_fixed_pixel_size(1), 1 + get_fixed_pixel_size(1));
|
||||
Rect text_rc = GUI::CalcTextGraphicalRect(Text.GetCStr(), Font, text_at);
|
||||
if (IsGUIEnabled(this)) {
|
||||
// add a cursor
|
||||
Rect cur_rc = RectWH(
|
||||
text_rc.Right + 3,
|
||||
1 + get_font_height(Font),
|
||||
get_fixed_pixel_size(5),
|
||||
get_fixed_pixel_size(1) - 1);
|
||||
text_rc = SumRects(text_rc, cur_rc);
|
||||
}
|
||||
return SumRects(rc, text_rc);
|
||||
}
|
||||
|
||||
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);
|
||||
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);
|
||||
}
|
||||
}
|
||||
DrawTextBoxContents(ds, x, y, text_color);
|
||||
}
|
||||
|
||||
// TODO: a shared utility function
|
||||
static void Backspace(String &text) {
|
||||
if (get_uformat() == U_UTF8) {// Find where the last utf8 char begins
|
||||
const char *ptr_end = text.GetCStr() + text.GetLength();
|
||||
const char *ptr = ptr_end - 1;
|
||||
for (; ptr > text.GetCStr() && ((*ptr & 0xC0) == 0x80); --ptr);
|
||||
text.ClipRight(ptr_end - ptr);
|
||||
} else {
|
||||
text.ClipRight(1);
|
||||
}
|
||||
}
|
||||
|
||||
void GUITextBox::OnKeyPress(const KeyInput &ki) {
|
||||
switch (ki.Key) {
|
||||
case eAGSKeyCodeReturn:
|
||||
IsActivated = true;
|
||||
return;
|
||||
case eAGSKeyCodeBackspace:
|
||||
Backspace(Text);
|
||||
MarkChanged();
|
||||
return;
|
||||
default: break;
|
||||
}
|
||||
|
||||
if (ki.UChar == 0)
|
||||
return; // not a textual event
|
||||
if (get_uformat() == U_UTF8)
|
||||
Text.Append(ki.Text); // proper unicode char
|
||||
else if (ki.UChar < 256)
|
||||
Text.AppendChar(static_cast<uint8_t>(ki.UChar)); // ascii/ansi-range char in ascii mode
|
||||
else
|
||||
return; // char from an unsupported range, don't print but still report as handled
|
||||
// if the new string is too long, remove the new character
|
||||
if (get_text_width(Text.GetCStr(), Font) > (_width - (6 + get_fixed_pixel_size(5))))
|
||||
Backspace(Text);
|
||||
MarkChanged();
|
||||
}
|
||||
|
||||
void GUITextBox::SetShowBorder(bool on) {
|
||||
if (on)
|
||||
TextBoxFlags |= kTextBox_ShowBorder;
|
||||
else
|
||||
TextBoxFlags &= ~kTextBox_ShowBorder;
|
||||
}
|
||||
|
||||
// TODO: replace string serialization with StrUtil::ReadString and WriteString
|
||||
// methods in the future, to keep this organized.
|
||||
void GUITextBox::WriteToFile(Stream *out) const {
|
||||
GUIObject::WriteToFile(out);
|
||||
StrUtil::WriteString(Text, out);
|
||||
out->WriteInt32(Font);
|
||||
out->WriteInt32(TextColor);
|
||||
out->WriteInt32(TextBoxFlags);
|
||||
}
|
||||
|
||||
void GUITextBox::ReadFromFile(Stream *in, GuiVersion gui_version) {
|
||||
GUIObject::ReadFromFile(in, gui_version);
|
||||
if (gui_version < kGuiVersion_350)
|
||||
Text.ReadCount(in, GUITEXTBOX_LEGACY_TEXTLEN);
|
||||
else
|
||||
Text = StrUtil::ReadString(in);
|
||||
Font = in->ReadInt32();
|
||||
TextColor = in->ReadInt32();
|
||||
TextBoxFlags = in->ReadInt32();
|
||||
// reverse particular flags from older format
|
||||
if (gui_version < kGuiVersion_350)
|
||||
TextBoxFlags ^= kTextBox_OldFmtXorMask;
|
||||
|
||||
if (TextColor == 0)
|
||||
TextColor = 16;
|
||||
}
|
||||
|
||||
void GUITextBox::ReadFromSavegame(Stream *in, GuiSvgVersion svg_ver) {
|
||||
GUIObject::ReadFromSavegame(in, svg_ver);
|
||||
Font = in->ReadInt32();
|
||||
TextColor = in->ReadInt32();
|
||||
Text = StrUtil::ReadString(in);
|
||||
if (svg_ver >= kGuiSvgVersion_350)
|
||||
TextBoxFlags = in->ReadInt32();
|
||||
}
|
||||
|
||||
void GUITextBox::WriteToSavegame(Stream *out) const {
|
||||
GUIObject::WriteToSavegame(out);
|
||||
out->WriteInt32(Font);
|
||||
out->WriteInt32(TextColor);
|
||||
StrUtil::WriteString(Text, out);
|
||||
out->WriteInt32(TextBoxFlags);
|
||||
}
|
||||
|
||||
} // namespace Shared
|
||||
} // namespace AGS
|
||||
} // namespace AGS3
|
||||
71
engines/ags/shared/gui/gui_textbox.h
Normal file
71
engines/ags/shared/gui/gui_textbox.h
Normal file
@@ -0,0 +1,71 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AGS_SHARED_GUI_GUI_TEXTBOX_H
|
||||
#define AGS_SHARED_GUI_GUI_TEXTBOX_H
|
||||
|
||||
#include "common/std/vector.h"
|
||||
#include "ags/shared/gui/gui_object.h"
|
||||
#include "ags/shared/util/string.h"
|
||||
|
||||
namespace AGS3 {
|
||||
namespace AGS {
|
||||
namespace Shared {
|
||||
|
||||
class GUITextBox : public GUIObject {
|
||||
public:
|
||||
GUITextBox();
|
||||
|
||||
bool HasAlphaChannel() const override;
|
||||
bool IsBorderShown() const;
|
||||
|
||||
// Operations
|
||||
Rect CalcGraphicRect(bool clipped) override;
|
||||
void Draw(Bitmap *ds, int x = 0, int y = 0) override;
|
||||
void SetShowBorder(bool on);
|
||||
|
||||
// Events
|
||||
void OnKeyPress(const KeyInput &ki) override;
|
||||
|
||||
// Serialization
|
||||
void ReadFromFile(Stream *in, GuiVersion gui_version) override;
|
||||
void WriteToFile(Stream *out) const override;
|
||||
void ReadFromSavegame(Stream *in, GuiSvgVersion svg_ver) override;
|
||||
void WriteToSavegame(Stream *out) const override;
|
||||
|
||||
// TODO: these members are currently public; hide them later
|
||||
public:
|
||||
int32_t Font;
|
||||
String Text;
|
||||
color_t TextColor;
|
||||
|
||||
private:
|
||||
int32_t TextBoxFlags;
|
||||
String _textToDraw;
|
||||
|
||||
void DrawTextBoxContents(Bitmap *ds, int x, int y, color_t text_color);
|
||||
};
|
||||
|
||||
} // namespace Shared
|
||||
} // namespace AGS
|
||||
} // namespace AGS3
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user