Initial commit

This commit is contained in:
2026-02-02 04:50:13 +01:00
commit 5b11698731
22592 changed files with 7677434 additions and 0 deletions

View File

@@ -0,0 +1,256 @@
/* 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

View File

@@ -0,0 +1,88 @@
/* 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 ULTIMA8_GUMPS_WIDGETS_BUTTONWIDGET_H
#define ULTIMA8_GUMPS_WIDGETS_BUTTONWIDGET_H
#include "ultima/shared/std/string.h"
#include "ultima/ultima8/gumps/gump.h"
#include "ultima/ultima8/gfx/frame_id.h"
#include "ultima/ultima8/misc/classtype.h"
namespace Ultima {
namespace Ultima8 {
class ButtonWidget : public Gump {
public:
// p_dynamic_class stuff
ENABLE_RUNTIME_CLASSTYPE()
ButtonWidget();
ButtonWidget(int x, int y, Std::string txt, bool gamefont, int font,
uint32 mouseOverBlendCol = 0, int width = 0, int height = 0,
int32 layer = LAYER_NORMAL);
ButtonWidget(int x, int y, FrameID frame_up, FrameID frame_down,
bool mouseOver = false, int32 layer = LAYER_NORMAL);
~ButtonWidget() override;
void InitGump(Gump *newparent, bool take_focus = true) override;
uint16 TraceObjId(int32 mx, int32 my) override;
bool PointOnGump(int mx, int my) override;
Gump *onMouseDown(int button, int32 mx, int32 my) override;
void onMouseUp(int button, int32 mx, int32 my) override;
void onMouseClick(int button, int32 mx, int32 my) override;
void onMouseDouble(int button, int32 mx, int32 my) override;
void onMouseOver() override;
void onMouseLeft() override;
//! return the textwidget's vlead, or 0 for an image button
int getVlead();
//void SetShapeDown(Shape *_shape, uint32 frameNum);
//void SetShapeUp(Shape *_shape, uint32 frameNum);
enum Message {
BUTTON_CLICK = 0,
BUTTON_UP = 1,
BUTTON_DOUBLE = 2
};
protected:
Shape *_shapeUp;
uint32 _frameNumUp;
Shape *_shapeDown;
uint32 _frameNumDown;
uint16 _textWidget;
uint32 _mouseOverBlendCol;
bool _mouseOver;
int _origW, _origH;
public:
bool loadData(Common::ReadStream *rs, uint32 version);
void saveData(Common::WriteStream *ws) override;
};
} // End of namespace Ultima8
} // End of namespace Ultima
#endif

View File

@@ -0,0 +1,273 @@
/* 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/edit_widget.h"
#include "ultima/ultima8/gfx/fonts/rendered_text.h"
#include "ultima/ultima8/gfx/render_surface.h"
#include "ultima/ultima8/gfx/fonts/font_manager.h"
#include "common/system.h"
#include "common/events.h"
namespace Ultima {
namespace Ultima8 {
DEFINE_RUNTIME_CLASSTYPE_CODE(EditWidget)
EditWidget::EditWidget(int x, int y, Std::string txt, bool gamefont, int font,
int w, int h, unsigned int maxlength, bool multiline)
: Gump(x, y, w, h), _text(txt), _gameFont(gamefont), _fontNum(font),
_maxLength(maxlength), _multiLine(multiline),
_cursorChanged(0), _cursorVisible(true), _cachedText(nullptr) {
_cursor = _text.size();
}
EditWidget::~EditWidget(void) {
delete _cachedText;
}
// Init the gump, call after construction
void EditWidget::InitGump(Gump *newparent, bool take_focus) {
Gump::InitGump(newparent, take_focus);
Font *font = getFont();
// Y offset is always baseline
_dims.moveTo(0, -font->getBaseline());
if (_gameFont && getFont()->isHighRes()) {
Common::Rect32 rect(_dims);
ScreenSpaceToGumpRect(rect, ROUND_OUTSIDE);
_dims.moveTo(0, rect.top);
}
}
Font *EditWidget::getFont() const {
if (_gameFont)
return FontManager::get_instance()->getGameFont(_fontNum, true);
else
return FontManager::get_instance()->getTTFont(_fontNum);
}
void EditWidget::setText(const Std::string &t) {
_text = t;
_cursor = _text.size();
delete _cachedText;
_cachedText = nullptr;
}
void EditWidget::ensureCursorVisible() {
_cursorVisible = true;
_cursorChanged = g_system->getMillis();
}
bool EditWidget::textFits(Std::string &t) {
Font *font = getFont();
unsigned int remaining;
int32 width, height;
int32 max_width = _multiLine ? _dims.width() : 0;
int32 max_height = _dims.height();
if (_gameFont && font->isHighRes()) {
Common::Rect32 rect(0, 0, max_width, max_height);
GumpRectToScreenSpace(rect, ROUND_INSIDE);
max_width = rect.width();
max_height = rect.height();
}
font->getTextSize(t, width, height, remaining,
max_width, max_height,
Font::TEXT_LEFT, false);
if (_gameFont && font->isHighRes()) {
Common::Rect32 rect(0, 0, width, height);
ScreenSpaceToGumpRect(rect, ROUND_OUTSIDE);
width = rect.width();
height = rect.height();
}
if (_multiLine)
return (remaining >= t.size());
else
return (width <= _dims.width());
}
void EditWidget::renderText() {
bool cv = _cursorVisible;
if (!IsFocus()) {
cv = false;
} else {
uint32 now = g_system->getMillis();
if (now > _cursorChanged + 750) {
cv = !_cursorVisible;
_cursorChanged = now;
}
}
if (cv != _cursorVisible) {
delete _cachedText;
_cachedText = nullptr;
_cursorVisible = cv;
}
if (!_cachedText) {
Font *font = getFont();
int32 max_width = _multiLine ? _dims.width() : 0;
int32 max_height = _dims.height();
if (_gameFont && font->isHighRes()) {
Common::Rect32 rect(0, 0, max_width, max_height);
GumpRectToScreenSpace(rect, ROUND_INSIDE);
max_width = rect.width();
max_height = rect.height();
}
unsigned int remaining;
_cachedText = font->renderText(_text, remaining,
max_width, max_height,
Font::TEXT_LEFT,
false, false,
cv ? _cursor : Std::string::npos);
// Trim text to fit
if (remaining < _text.size()) {
_text.erase(remaining);
_cursor = _text.size();
}
}
}
// Overloadable method to Paint just this Gump (RenderSurface is relative to this)
void EditWidget::PaintThis(RenderSurface *surf, int32 lerp_factor, bool scaled) {
Gump::PaintThis(surf, lerp_factor, scaled);
renderText();
if (scaled && _gameFont && getFont()->isHighRes()) {
return;
}
_cachedText->draw(surf, 0, 0);
}
// Overloadable method to Paint just this gumps unscaled components that require compositing (RenderSurface is relative to parent).
void EditWidget::PaintComposited(RenderSurface *surf, int32 lerp_factor, int32 sx, int32 sy) {
Font *font = getFont();
if (!_gameFont || !font->isHighRes()) return;
int32 x = 0, y = 0;
GumpToScreenSpace(x, y, ROUND_BOTTOMRIGHT);
_cachedText->draw(surf, x, y, true);
Common::Rect32 rect(_dims);
GumpRectToScreenSpace(rect, ROUND_OUTSIDE);
}
// don't handle any mouse motion events, so let parent handle them for us.
Gump *EditWidget::onMouseMotion(int32 mx, int32 my) {
return nullptr;
}
bool EditWidget::OnKeyDown(int key, int mod) {
switch (key) {
case Common::KEYCODE_RETURN:
case Common::KEYCODE_KP_ENTER:
_parent->ChildNotify(this, EDIT_ENTER);
break;
case Common::KEYCODE_ESCAPE:
_parent->ChildNotify(this, EDIT_ESCAPE);
break;
case Common::KEYCODE_BACKSPACE:
if (_cursor > 0) {
_text.erase(--_cursor, 1);
delete _cachedText;
_cachedText = nullptr;
ensureCursorVisible();
}
break;
case Common::KEYCODE_DELETE:
if (_cursor != _text.size()) {
_text.erase(_cursor, 1);
delete _cachedText;
_cachedText = nullptr;
}
break;
case Common::KEYCODE_LEFT:
if (_cursor > 0) {
_cursor--;
delete _cachedText;
_cachedText = nullptr;
ensureCursorVisible();
}
break;
case Common::KEYCODE_RIGHT:
if (_cursor < _text.size()) {
_cursor++;
delete _cachedText;
_cachedText = nullptr;
ensureCursorVisible();
}
break;
default:
break;
}
return true;
}
bool EditWidget::OnKeyUp(int key) {
return true;
}
bool EditWidget::OnTextInput(int unicode) {
if (_maxLength > 0 && _text.size() >= _maxLength)
return true;
char c = 0;
if (unicode >= 0 && unicode < 256)
c = reverse_encoding[unicode];
if (!c) return true;
Std::string newtext = _text;
newtext.insertChar(c, _cursor);
if (textFits(newtext)) {
_text = newtext;
_cursor++;
delete _cachedText;
_cachedText = nullptr;
}
return true;
}
void EditWidget::OnFocus(bool gain) {
g_system->setFeatureState(OSystem::kFeatureVirtualKeyboard, gain);
}
} // End of namespace Ultima8
} // End of namespace Ultima

View File

@@ -0,0 +1,95 @@
/* 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 ULTIMA8_GUMPS_WIDGETS_EDITWIDGET_H
#define ULTIMA8_GUMPS_WIDGETS_EDITWIDGET_H
//
// EditWidget. Widget for text input (single or multi-line)
//
#include "ultima/ultima8/gumps/gump.h"
#include "ultima/ultima8/gfx/fonts/font.h"
#include "ultima/ultima8/misc/classtype.h"
namespace Ultima {
namespace Ultima8 {
class RenderedText;
class EditWidget : public Gump {
public:
ENABLE_RUNTIME_CLASSTYPE()
EditWidget(int x, int y, Std::string txt, bool gamefont, int fontnum,
int width, int height, unsigned int maxlength = 0,
bool multiline = false);
~EditWidget() override;
void InitGump(Gump *newparent, bool take_focus = true) override;
void PaintThis(RenderSurface *, int32 lerp_factor, bool scaled) override;
void PaintComposited(RenderSurface *surf, int32 lerp_factor, int32 sx, int32 sy) override;
Gump *onMouseMotion(int32 mx, int32 my) override;
bool OnKeyDown(int key, int mod) override;
bool OnKeyUp(int key) override;
bool OnTextInput(int unicode) override;
void OnFocus(bool gain) override;
//! get the current text
Std::string getText() const {
return _text;
}
void setText(const Std::string &t);
enum Message {
EDIT_ENTER = 16,
EDIT_ESCAPE = 17
};
protected:
Std::string _text;
Std::string::size_type _cursor;
bool _gameFont;
int _fontNum;
unsigned int _maxLength;
bool _multiLine;
uint32 _cursorChanged;
bool _cursorVisible;
void ensureCursorVisible();
bool textFits(Std::string &t);
void renderText();
Font *getFont() const;
RenderedText *_cachedText;
};
} // End of namespace Ultima8
} // End of namespace Ultima
#endif

View File

@@ -0,0 +1,107 @@
/* 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/sliding_widget.h"
namespace Ultima {
namespace Ultima8 {
DEFINE_RUNTIME_CLASSTYPE_CODE(SlidingWidget)
SlidingWidget::SlidingWidget()
: Gump(), _dragBounds() {
}
SlidingWidget::SlidingWidget(int x, int y, FrameID frame, const Common::Rect32 &dragBounds)
: Gump(x, y, 5, 5, 0, FLAG_DRAGGABLE), _dragBounds(dragBounds) {
SetShape(frame, true);
if (_dragBounds.width() < _dims.width())
_dragBounds.setWidth(_dims.width());
if (_dragBounds.height() < _dims.height())
_dragBounds.setHeight(_dims.height());
}
SlidingWidget::~SlidingWidget() {
}
int SlidingWidget::getValueForRange(int min, int max) {
int val = min;
if (_dragBounds.isValidRect()) {
val = min + (_x - _dragBounds.left) * (max - min) / (_dragBounds.width() - _dims.width());
if (val < min)
val = min;
if (val > max)
val = max;
}
return val;
}
void SlidingWidget::setValueForRange(int value, int min, int max) {
assert(_dragBounds.isValidRect());
_x = _dragBounds.left + (value - min) * (_dragBounds.width() - _dims.width()) / (max - min);
}
void SlidingWidget::InitGump(Gump *newparent, bool take_focus) {
Gump::InitGump(newparent, take_focus);
UpdateDimsFromShape();
}
uint16 SlidingWidget::TraceObjId(int32 mx, int32 my) {
if (PointOnGump(mx, my))
return getObjId();
else
return 0;
}
void SlidingWidget::Move(int32 x, int32 y) {
if (_dragBounds.isValidRect()) {
if (x < _dragBounds.left)
x = _dragBounds.left;
if (x > _dragBounds.right - _dims.width())
x = _dragBounds.right - _dims.width();
if (y < _dragBounds.top)
y = _dragBounds.top;
if (y > _dragBounds.bottom - _dims.height())
y = _dragBounds.bottom - _dims.height();
}
_x = x;
_y = y;
}
void SlidingWidget::onDrag(int32 mx, int32 my) {
Gump::onDrag(mx, my);
_parent->ChildNotify(this, DRAGGING);
}
void SlidingWidget::saveData(Common::WriteStream *ws) {
Gump::saveData(ws);
}
bool SlidingWidget::loadData(Common::ReadStream *rs, uint32 version) {
if (!Gump::loadData(rs, version)) return false;
return true;
}
} // End of namespace Ultima8
} // End of namespace Ultima

View File

@@ -0,0 +1,62 @@
/* 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 ULTIMA8_GUMPS_WIDGETS_SLIDINGWIDGET_H
#define ULTIMA8_GUMPS_WIDGETS_SLIDINGWIDGET_H
#include "ultima/ultima8/gumps/gump.h"
#include "ultima/ultima8/misc/classtype.h"
namespace Ultima {
namespace Ultima8 {
class SlidingWidget : public Gump {
protected:
Common::Rect32 _dragBounds;
public:
ENABLE_RUNTIME_CLASSTYPE()
SlidingWidget();
SlidingWidget(int x, int y, FrameID frame, const Common::Rect32 &dragBounds);
~SlidingWidget() override;
int getValueForRange(int min, int max);
void setValueForRange(int value, int min, int max);
void InitGump(Gump *newparent, bool take_focus = true) override;
uint16 TraceObjId(int32 mx, int32 my) override;
void Move(int32 x, int32 y) override;
void onDrag(int32 mx, int32 my) override;
bool loadData(Common::ReadStream *rs, uint32 version);
void saveData(Common::WriteStream *ws) override;
enum Message {
DRAGGING = 0
};
};
} // End of namespace Ultima8
} // End of namespace Ultima
#endif

View File

@@ -0,0 +1,260 @@
/* 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/text_widget.h"
#include "ultima/ultima8/gfx/fonts/rendered_text.h"
#include "ultima/ultima8/gfx/render_surface.h"
#include "ultima/ultima8/gfx/fonts/font_manager.h"
#include "ultima/ultima8/gumps/bark_gump.h"
#include "ultima/ultima8/gumps/ask_gump.h"
#include "ultima/ultima8/gumps/widgets/button_widget.h"
namespace Ultima {
namespace Ultima8 {
DEFINE_RUNTIME_CLASSTYPE_CODE(TextWidget)
TextWidget::TextWidget() : Gump(), _gameFont(false), _fontNum(0), _blendColour(0),
_tx(0), _ty(0), _currentStart(0), _currentEnd(0), _targetWidth(0), _targetHeight(0),
_cachedText(nullptr), _textAlign(Font::TEXT_LEFT) {
}
TextWidget::TextWidget(int x, int y, const Std::string &txt, bool gamefont, int font,
int w, int h, Font::TextAlign align, bool dopaging) :
Gump(x, y, w, h), _text(txt), _gameFont(gamefont), _fontNum(font),
_blendColour(0), _currentStart(0), _currentEnd(0), _tx(0), _ty(0),
_doPaging(dopaging), _targetWidth(w), _targetHeight(h),
_cachedText(nullptr), _textAlign(align) {
}
TextWidget::~TextWidget(void) {
delete _cachedText;
}
// Init the gump, call after construction
void TextWidget::InitGump(Gump *newparent, bool take_focus) {
Gump::InitGump(newparent, take_focus);
Font *font = getFont();
// Y offset is always baseline
_dims.moveTo(0, -font->getBaseline());
if (_gameFont && getFont()->isHighRes()) {
Common::Rect32 rect(_dims);
ScreenSpaceToGumpRect(rect, ROUND_OUTSIDE);
_dims.moveTo(0, rect.top);
// Note that GumpRectToScreenSpace is guaranteed to keep
// _targetWidth/_targetHeight zero if they already were.
Common::Rect32 target(_dims);
GumpRectToScreenSpace(target, ROUND_OUTSIDE);
_targetWidth = target.width();
_targetHeight = target.height();
Common::Rect32 sr(0, 0, _targetWidth, _targetHeight);
ScreenSpaceToGumpRect(sr, ROUND_OUTSIDE);
_dims.setWidth(sr.width());
_dims.setHeight(sr.height());
}
setupNextText();
}
int TextWidget::getVlead() {
renderText();
assert(_cachedText);
int32 vlead = _cachedText->getVlead();
if (_gameFont && getFont()->isHighRes()) {
Common::Rect32 rect(0, 0, 0, vlead);
ScreenSpaceToGumpRect(rect, ROUND_OUTSIDE);
vlead = rect.height();
}
return vlead;
}
Font *TextWidget::getFont() const {
if (_gameFont)
return FontManager::get_instance()->getGameFont(_fontNum, true);
else
return FontManager::get_instance()->getTTFont(_fontNum);
}
bool TextWidget::setupNextText() {
_currentStart = _currentEnd;
if (_currentStart >= _text.size()) return false;
Font *font = getFont();
unsigned int remaining;
font->getTextSize(_text.substr(_currentStart), _tx, _ty, remaining,
_targetWidth, _targetHeight, _textAlign, true, _doPaging);
_dims.top = -font->getBaseline();
_dims.left = 0;
_dims.setWidth(_tx);
_dims.setHeight(_ty);
_currentEnd = _currentStart + remaining;
delete _cachedText;
_cachedText = nullptr;
if (_gameFont) {
Font *fontP = getFont();
if (fontP->isHighRes()) {
Common::Rect32 sr(0, 0, _dims.width(), _dims.height());
ScreenSpaceToGumpRect(sr, ROUND_OUTSIDE);
_dims.setWidth(sr.width());
_dims.setHeight(sr.height());
}
}
return true;
}
void TextWidget::rewind() {
_currentStart = 0;
_currentEnd = 0;
setupNextText();
}
void TextWidget::renderText() {
if (!_cachedText) {
Font *font = getFont();
unsigned int remaining;
_cachedText = font->renderText(_text.substr(_currentStart,
_currentEnd - _currentStart),
remaining, _targetWidth, _targetHeight,
_textAlign, true, _doPaging);
}
}
// Overloadable method to Paint just this Gump (RenderSurface is relative to this)
void TextWidget::PaintThis(RenderSurface *surf, int32 lerp_factor, bool scaled) {
Gump::PaintThis(surf, lerp_factor, scaled);
renderText();
if (scaled && _gameFont && getFont()->isHighRes()) {
return;
}
if (!_blendColour)
_cachedText->draw(surf, 0, 0);
else
_cachedText->drawBlended(surf, 0, 0, _blendColour);
}
// Overloadable method to Paint just this gumps unscaled components that require compositing (RenderSurface is relative to parent).
void TextWidget::PaintComposited(RenderSurface *surf, int32 lerp_factor, int32 sx, int32 sy) {
Font *font = getFont();
if (!_gameFont || !font->isHighRes()) return;
int32 x = 0, y = 0;
GumpToScreenSpace(x, y, ROUND_BOTTOMRIGHT);
if (!_blendColour)
_cachedText->draw(surf, x, y, true);
else
_cachedText->drawBlended(surf, x, y, _blendColour, true);
if (dynamic_cast<BarkGump *>(_parent))
return;
if (dynamic_cast<ButtonWidget *>(_parent) && dynamic_cast<AskGump *>(_parent->GetParent()))
return;
Common::Rect32 rect(_dims);
GumpRectToScreenSpace(rect, ROUND_OUTSIDE);
}
// don't handle any mouse motion events, so let parent handle them for us.
Gump *TextWidget::onMouseMotion(int32 mx, int32 my) {
return nullptr;
}
void TextWidget::saveData(Common::WriteStream *ws) {
Gump::saveData(ws);
ws->writeByte(_gameFont ? 1 : 0);
ws->writeUint32LE(static_cast<uint32>(_fontNum));
ws->writeUint32LE(_blendColour);
ws->writeUint32LE(static_cast<uint32>(_currentStart));
ws->writeUint32LE(static_cast<uint32>(_currentEnd));
ws->writeUint32LE(static_cast<uint32>(_targetWidth));
ws->writeUint32LE(static_cast<uint32>(_targetHeight));
ws->writeUint16LE(static_cast<uint16>(_textAlign));
ws->writeUint32LE(_text.size());
ws->write(_text.c_str(), _text.size());
}
bool TextWidget::loadData(Common::ReadStream *rs, uint32 version) {
if (!Gump::loadData(rs, version)) return false;
_gameFont = (rs->readByte() != 0);
_fontNum = static_cast<int>(rs->readUint32LE());
_blendColour = rs->readUint32LE();
_currentStart = static_cast<int>(rs->readUint32LE());
_currentEnd = static_cast<int>(rs->readUint32LE());
_targetWidth = static_cast<int>(rs->readUint32LE());
_targetHeight = static_cast<int>(rs->readUint32LE());
_textAlign = static_cast<Font::TextAlign>(rs->readUint16LE());
uint32 slen = rs->readUint32LE();
if (slen > 0) {
char *buf = new char[slen + 1];
rs->read(buf, slen);
buf[slen] = 0;
_text = buf;
delete[] buf;
} else {
_text = "";
}
// HACK ALERT: this is to deal with possibly changing font sizes
// after loading.
Font *font = getFont();
int32 tx, ty;
unsigned int remaining;
font->getTextSize(_text.substr(_currentStart), tx, ty, remaining,
_targetWidth, _targetHeight, _textAlign, true, _doPaging);
// Y offset is always baseline
_dims.top = -font->getBaseline();
_dims.setWidth(tx);
_dims.setHeight(ty);
_currentEnd = _currentStart + remaining;
return true;
}
} // End of namespace Ultima8
} // End of namespace Ultima

View File

@@ -0,0 +1,114 @@
/* 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 ULTIMA8_GUMPS_WIDGETS_TEXTWIDGET_H
#define ULTIMA8_GUMPS_WIDGETS_TEXTWIDGET_H
//
// TextWidget. Displays text in either a fixed-size or a fit-to-text rectangle.
//
#include "ultima/ultima8/gumps/gump.h"
#include "ultima/ultima8/gfx/fonts/font.h"
#include "ultima/ultima8/misc/classtype.h"
namespace Ultima {
namespace Ultima8 {
class RenderedText;
class TextWidget : public Gump {
protected:
Std::string _text;
bool _gameFont;
int _fontNum;
uint32 _blendColour;
int32 _tx, _ty;
bool _doPaging;
unsigned int _currentStart; //!< start of currently displaying text
unsigned int _currentEnd; //!< start of remaining text
int32 _targetWidth, _targetHeight;
RenderedText *_cachedText;
Font::TextAlign _textAlign;
public:
ENABLE_RUNTIME_CLASSTYPE()
TextWidget();
TextWidget(int x, int y, const Std::string &txt, bool gamefont, int fontnum,
int width = 0, int height = 0,
Font::TextAlign align = Font::TEXT_LEFT,
bool dopaging = false);
~TextWidget() override;
// Init the gump, call after construction
void InitGump(Gump *newparent, bool take_focus = true) override;
// Overloadable method to Paint just this Gump (RenderSurface is relative to this)
void PaintThis(RenderSurface *, int32 lerp_factor, bool scaled) override;
void PaintComposited(RenderSurface *surf, int32 lerp_factor, int32 scalex, int32 scaley) override;
Gump *onMouseMotion(int32 mx, int32 my) override;
//! display the next part of the text
//! \return false if there is no more text to display
bool setupNextText();
//! reset the widget to the start of the text
void rewind();
//! get the text that's currently being displayed
//! \param start Returns the start of the text
//! \param end Returns the start of the remaining text
void getCurrentText(unsigned int &start, unsigned int &end) const {
start = _currentStart;
end = _currentEnd;
}
//! set the colour to blend the rendered text with. (0 to disable)
void setBlendColour(uint32 col) {
_blendColour = col;
}
//! get the RenderedText's vlead
int getVlead();
const Std::string &getText() const {
return _text;
}
protected:
void renderText();
Font *getFont() const;
public:
bool loadData(Common::ReadStream *rs, uint32 version);
void saveData(Common::WriteStream *ws) override;
};
} // End of namespace Ultima8
} // End of namespace Ultima
#endif