257 lines
6.9 KiB
C++
257 lines
6.9 KiB
C++
/* 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 "ultima/ultima8/gumps/widgets/button_widget.h"
|
|
#include "ultima/ultima8/gumps/widgets/text_widget.h"
|
|
#include "ultima/ultima8/games/game_data.h"
|
|
#include "ultima/ultima8/gfx/shape_archive.h"
|
|
#include "ultima/ultima8/gfx/shape.h"
|
|
#include "ultima/ultima8/kernel/mouse.h"
|
|
#include "ultima/ultima8/world/get_object.h"
|
|
|
|
namespace Ultima {
|
|
namespace Ultima8 {
|
|
|
|
// p_dynamic_class stuff
|
|
DEFINE_RUNTIME_CLASSTYPE_CODE(ButtonWidget)
|
|
|
|
ButtonWidget::ButtonWidget() : Gump(), _shapeUp(nullptr), _shapeDown(nullptr),
|
|
_mouseOver(false), _origW(0), _origH(0), _frameNumUp(0),
|
|
_frameNumDown(0), _mouseOverBlendCol(0), _textWidget(0) {
|
|
}
|
|
|
|
ButtonWidget::ButtonWidget(int x, int y, Std::string txt, bool gamefont,
|
|
int font, uint32 mouseOverBlendCol,
|
|
int w, int h, int32 layer) :
|
|
Gump(x, y, w, h, 0, 0, layer), _shapeUp(nullptr), _shapeDown(nullptr),
|
|
_mouseOver(false), _origW(w), _origH(h), _frameNumUp(0), _frameNumDown(0) {
|
|
TextWidget *widget = new TextWidget(0, 0, txt, gamefont, font, w, h);
|
|
// FIXME: Do we ever free this widget?
|
|
_textWidget = widget->getObjId();
|
|
_mouseOverBlendCol = mouseOverBlendCol;
|
|
_mouseOver = (_mouseOverBlendCol != 0);
|
|
}
|
|
|
|
ButtonWidget::ButtonWidget(int x, int y, FrameID frame_up, FrameID frame_down,
|
|
bool mouseOver, int32 layer)
|
|
: Gump(x, y, 5, 5, 0, 0, layer), _textWidget(0), _mouseOver(mouseOver),
|
|
_origW(0), _origH(0), _mouseOverBlendCol(0) {
|
|
_shapeUp = GameData::get_instance()->getShape(frame_up);
|
|
_shapeDown = GameData::get_instance()->getShape(frame_down);
|
|
_frameNumUp = frame_up._frameNum;
|
|
_frameNumDown = frame_down._frameNum;
|
|
}
|
|
|
|
|
|
ButtonWidget::~ButtonWidget(void) {
|
|
}
|
|
|
|
void ButtonWidget::InitGump(Gump *newparent, bool take_focus) {
|
|
Gump::InitGump(newparent, take_focus);
|
|
|
|
if (_textWidget != 0) {
|
|
Gump *widget = getGump(_textWidget);
|
|
assert(widget);
|
|
widget->InitGump(this);
|
|
_dims = widget->getDims(); // transfer child dimension to self
|
|
widget->Move(0, _dims.top); // move it to the correct height
|
|
} else {
|
|
assert(_shapeUp != nullptr);
|
|
assert(_shapeDown != nullptr);
|
|
|
|
SetShape(_shapeUp, _frameNumUp);
|
|
UpdateDimsFromShape();
|
|
}
|
|
}
|
|
|
|
int ButtonWidget::getVlead() {
|
|
if (_textWidget != 0) {
|
|
Gump *widget = getGump(_textWidget);
|
|
TextWidget *txtWidget = dynamic_cast<TextWidget *>(widget);
|
|
assert(txtWidget);
|
|
return txtWidget->getVlead();
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
bool ButtonWidget::PointOnGump(int mx, int my) {
|
|
// CHECKME: this makes the ButtonWidget accept any point in its rectangle,
|
|
// effectively ignoring shape transparency. For some buttons (like those
|
|
// in U8's diary), this is desirable. For others it may not be, so this
|
|
// behaviour may need to be changed. (bool ignoreShapeTransparency or
|
|
// something)
|
|
|
|
int32 gx = mx, gy = my;
|
|
ParentToGump(gx, gy);
|
|
|
|
return _dims.contains(gx, gy);
|
|
}
|
|
|
|
Gump *ButtonWidget::onMouseDown(int button, int32 mx, int32 my) {
|
|
Gump *ret = Gump::onMouseDown(button, mx, my);
|
|
if (ret)
|
|
return ret;
|
|
if (button == Mouse::BUTTON_LEFT) {
|
|
// CHECKME: change dimensions or not?
|
|
if (!_mouseOver) {
|
|
_shape = _shapeDown;
|
|
_frameNum = _frameNumDown;
|
|
}
|
|
return this;
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
uint16 ButtonWidget::TraceObjId(int32 mx, int32 my) {
|
|
if (PointOnGump(mx, my))
|
|
return getObjId();
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
|
|
void ButtonWidget::onMouseUp(int button, int32 mx, int32 my) {
|
|
if (button == Mouse::BUTTON_LEFT) {
|
|
if (!_mouseOver) {
|
|
_shape = _shapeUp;
|
|
_frameNum = _frameNumUp;
|
|
}
|
|
if (PointOnGump(mx, my))
|
|
_parent->ChildNotify(this, BUTTON_UP);
|
|
}
|
|
}
|
|
|
|
void ButtonWidget::onMouseClick(int button, int32 mx, int32 my) {
|
|
if (PointOnGump(mx, my))
|
|
_parent->ChildNotify(this, BUTTON_CLICK);
|
|
}
|
|
|
|
void ButtonWidget::onMouseDouble(int button, int32 mx, int32 my) {
|
|
if (PointOnGump(mx, my))
|
|
_parent->ChildNotify(this, BUTTON_DOUBLE);
|
|
}
|
|
|
|
void ButtonWidget::onMouseOver() {
|
|
if (_mouseOver) {
|
|
if (_textWidget) {
|
|
Gump *widget = getGump(_textWidget);
|
|
TextWidget *txtWidget = dynamic_cast<TextWidget *>(widget);
|
|
assert(txtWidget);
|
|
txtWidget->setBlendColour(_mouseOverBlendCol);
|
|
} else {
|
|
_shape = _shapeDown;
|
|
_frameNum = _frameNumDown;
|
|
}
|
|
}
|
|
}
|
|
|
|
void ButtonWidget::onMouseLeft() {
|
|
if (_mouseOver) {
|
|
if (_textWidget) {
|
|
Gump *widget = getGump(_textWidget);
|
|
TextWidget *txtWidget = dynamic_cast<TextWidget *>(widget);
|
|
assert(txtWidget);
|
|
txtWidget->setBlendColour(0);
|
|
} else {
|
|
_shape = _shapeUp;
|
|
_frameNum = _frameNumUp;
|
|
}
|
|
}
|
|
}
|
|
|
|
void ButtonWidget::saveData(Common::WriteStream *ws) {
|
|
// HACK ALERT
|
|
int w = 0, h = 0;
|
|
if (_textWidget != 0) {
|
|
w = _dims.width();
|
|
h = _dims.height();
|
|
_dims.setWidth(_origW);
|
|
_dims.setHeight(_origH);
|
|
}
|
|
|
|
Gump::saveData(ws);
|
|
|
|
// HACK ALERT
|
|
if (_textWidget != 0) {
|
|
_dims.setWidth(w);
|
|
_dims.setHeight(h);
|
|
}
|
|
|
|
uint16 flex = 0;
|
|
uint32 shapenum = 0;
|
|
if (_shapeUp) {
|
|
_shapeUp->getShapeId(flex, shapenum);
|
|
}
|
|
ws->writeUint16LE(flex);
|
|
ws->writeUint32LE(shapenum);
|
|
ws->writeUint32LE(_frameNumUp);
|
|
|
|
flex = 0;
|
|
shapenum = 0;
|
|
if (_shapeDown) {
|
|
_shapeDown->getShapeId(flex, shapenum);
|
|
}
|
|
ws->writeUint16LE(flex);
|
|
ws->writeUint32LE(shapenum);
|
|
ws->writeUint32LE(_frameNumDown);
|
|
ws->writeUint16LE(_textWidget);
|
|
ws->writeUint32LE(_mouseOverBlendCol);
|
|
|
|
uint8 m = (_mouseOver ? 1 : 0);
|
|
ws->writeByte(m);
|
|
}
|
|
|
|
bool ButtonWidget::loadData(Common::ReadStream *rs, uint32 version) {
|
|
if (!Gump::loadData(rs, version)) return false;
|
|
|
|
_shapeUp = nullptr;
|
|
ShapeArchive *flex = GameData::get_instance()->getShapeFlex(rs->readUint16LE());
|
|
uint32 shapenum = rs->readUint32LE();
|
|
if (flex) {
|
|
_shapeUp = flex->getShape(shapenum);
|
|
}
|
|
_frameNumUp = rs->readUint32LE();
|
|
|
|
_shapeDown = nullptr;
|
|
flex = GameData::get_instance()->getShapeFlex(rs->readUint16LE());
|
|
shapenum = rs->readUint32LE();
|
|
if (flex) {
|
|
_shapeDown = flex->getShape(shapenum);
|
|
}
|
|
_frameNumDown = rs->readUint32LE();
|
|
_textWidget = rs->readUint16LE();
|
|
_mouseOverBlendCol = rs->readUint32LE();
|
|
_mouseOver = (rs->readByte() != 0);
|
|
|
|
// HACK ALERT
|
|
if (_textWidget != 0) {
|
|
Gump *widget = getGump(_textWidget);
|
|
_dims = widget->getDims(); // transfer child dimension to self
|
|
widget->Move(0, _dims.top); // move it to the correct height
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
} // End of namespace Ultima8
|
|
} // End of namespace Ultima
|