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,66 @@
/* 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/shared/gfx/bitmap.h"
#include "ultima/shared/core/file.h"
#include "common/memstream.h"
#include "graphics/managed_surface.h"
namespace Ultima {
namespace Shared {
namespace Gfx {
void Bitmap::load(const Common::Path &filename) {
File srcFile(filename);
Common::MemoryWriteStreamDynamic decompressedFile(DisposeAfterUse::YES);
decompress(&srcFile, &decompressedFile);
// Set the bitmap size
Common::MemoryReadStream f(decompressedFile.getData(), decompressedFile.size());
int16 xs = f.readSint16LE();
int16 ys = f.readSint16LE();
create(xs, ys);
assert(f.size() == (xs * ys + 4));
Graphics::Surface s = getSubArea(Common::Rect(0, 0, xs, ys));
// Read in the lines
for (int y = 0; y < ys; ++y) {
byte *dest = (byte *)s.getBasePtr(0, y);
f.read(dest, xs);
}
}
void Bitmap::flipHorizontally() {
Graphics::Surface s = getSubArea(Common::Rect(0, 0, this->w, this->h));
for (int y = 0; y < h; ++y) {
byte *lineStart = (byte *)s.getBasePtr(0, y);
byte *lineEnd = (byte *)s.getBasePtr(this->w - 1, y);
for (int x = 0; x < (this->w - 1) / 2; ++x, ++lineStart, --lineEnd)
SWAP(*lineStart, *lineEnd);
}
}
} // End of namespace Gfx
} // End of namespace Shared
} // End of namespace Ultima

View File

@@ -0,0 +1,51 @@
/* 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 ULTIMA_BITMAP_H
#define ULTIMA_BITMAP_H
#include "ultima/shared/core/lzw.h"
#include "common/path.h"
#include "common/stream.h"
#include "graphics/managed_surface.h"
namespace Ultima {
namespace Shared {
namespace Gfx {
class Bitmap : public Graphics::ManagedSurface, public LZW {
public:
/**
* Loads an Ultima 6 bitmap
*/
void load(const Common::Path &filename);
/**
* Flips a bitmap horizontally
*/
void flipHorizontally();
};
} // End of namespace Gfx
} // End of namespace Shared
} // End of namespace Ultima
#endif

View File

@@ -0,0 +1,55 @@
/* 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/shared/gfx/character_input.h"
#include "ultima/shared/gfx/text_cursor.h"
#include "ultima/shared/early/game_base.h"
#include "ultima/shared/engine/messages.h"
namespace Ultima {
namespace Shared {
namespace Gfx {
BEGIN_MESSAGE_MAP(CharacterInput, Popup)
ON_MESSAGE(KeypressMsg)
END_MESSAGE_MAP()
void CharacterInput::show(const Point &pt, byte color, TreeItem *respondTo) {
Popup::show(respondTo);
_color = color;
_bounds = Rect(pt.x, pt.y, pt.x + 8, pt.y + 8);
_game->_textCursor->setPosition(Point(_bounds.left, _bounds.top));
_game->_textCursor->setVisible(true);
}
bool CharacterInput::KeypressMsg(CKeypressMsg *msg) {
hide();
CCharacterInputMsg inputMsg(msg->_keyState);
inputMsg.execute(_respondTo);
return true;
}
} // End of namespace Gfx
} // End of namespace Shared
} // End of namespace Ultima

View File

@@ -0,0 +1,58 @@
/* 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 ULTIMA_GFX_CHARACTER_INPUT_H
#define ULTIMA_GFX_CHARACTER_INPUT_H
#include "ultima/shared/gfx/popup.h"
namespace Ultima {
namespace Shared {
namespace Gfx {
/**
* Text input control
*/
class CharacterInput : public Popup {
DECLARE_MESSAGE_MAP;
bool KeypressMsg(CKeypressMsg *msg);
private:
byte _color;
public:
CLASSDEF;
CharacterInput(GameBase *game) : Popup(game), _color(0) {
}
/**
* Show the character input
* @param pt Position of the input
* @param color Text color
* @param respondTo Where to send response to
* @remarks Generates a TextInputMsg message with the character when pressed
*/
void show(const Point &pt, byte color, TreeItem *respondTo = nullptr);
};
} // End of namespace Gfx
} // End of namespace Shared
} // End of namespace Ultima
#endif

View File

@@ -0,0 +1,195 @@
/* 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/shared/gfx/dungeon_surface.h"
#include "ultima/shared/maps/map.h"
#include "ultima/shared/early/game.h"
namespace Ultima {
namespace Shared {
const byte ARRAY_X[] = { 0, 72, 108, 126, 135, 144 };
const byte ARRAY_Y[] = { 0, 36, 54, 63, 68, 72 };
DungeonSurface::DungeonSurface(const Graphics::ManagedSurface &src, const Rect &bounds, Game *game, DrawWidgetFn widgetFn) :
Gfx::VisualSurface(src, bounds), _widgetFn(widgetFn) {
_edgeColor = game->_edgeColor;
_highlightColor = game->_highlightColor;
_widgetColor = 0;
}
void DungeonSurface::drawWall(uint distance) {
int offsetX = !distance ? 8 : 0, offsetY = !distance ? 8 : 0;
if (distance <= 5) {
hLine(ARRAY_X[distance] + 16 + offsetX, ARRAY_Y[distance] + 8 + offsetY,
303 - ARRAY_X[distance] - offsetX, _edgeColor);
hLine(ARRAY_X[distance] + 16 + offsetX, 151 - ARRAY_Y[distance] - offsetY,
303 - ARRAY_X[distance] - offsetX, _edgeColor);
}
}
void DungeonSurface::drawDoorway(uint distance) {
int offsetY = !distance ? 8 : 0;
byte color = !distance ? 0 : _edgeColor;
if (distance < 5) {
drawWall(distance);
drawLine(ARRAY_X[distance + 1] + 16, 151 - ARRAY_Y[distance] - offsetY,
ARRAY_X[distance + 1] + 16, ARRAY_Y[distance + 1] + 8, _edgeColor);
drawLineTo(303 - ARRAY_X[distance + 1], ARRAY_Y[distance + 1] + 8, _edgeColor);
drawLineTo(303 - ARRAY_X[distance + 1], 151 - ARRAY_Y[distance] - offsetY, _edgeColor);
drawLineTo(ARRAY_X[distance + 1] + 16, 151 - ARRAY_Y[distance] - offsetY, color);
}
}
void DungeonSurface::drawLeftEdge(uint distance) {
if (distance <= 5) {
vLine(ARRAY_X[distance] + 16, ARRAY_Y[distance] + 8, 151 - ARRAY_Y[distance], _edgeColor);
}
}
void DungeonSurface::drawRightEdge(uint distance) {
if (distance <= 5) {
vLine(303 - ARRAY_X[distance], ARRAY_Y[distance] + 8, 151 - ARRAY_Y[distance], _edgeColor);
}
}
void DungeonSurface::drawWidget(uint widgetId, uint distance, byte color) {
_widgetFn(*this, widgetId, distance, color);
}
void DungeonSurface::drawLadderDownFaceOn(uint distance) {
if (distance <= 5) {
drawWidget(27, distance, _edgeColor);
drawWidget(28, distance, _edgeColor);
}
}
void DungeonSurface::drawLadderDownSideOn(uint distance) {
if (distance <= 5) {
drawWidget(27, distance, _edgeColor);
drawWidget(29, distance, _edgeColor);
}
}
void DungeonSurface::drawLadderUpFaceOn(uint distance) {
if (distance <= 5) {
drawWidget(26, distance, _edgeColor);
drawWidget(28, distance, _edgeColor);
}
}
void DungeonSurface::drawLadderUpSideOn(uint distance) {
if (distance <= 5) {
drawWidget(26, distance, _edgeColor);
drawWidget(29, distance, _edgeColor);
}
}
void DungeonSurface::drawLeftDoor(uint distance) {
if (distance <= 5) {
drawLeftWall(distance);
Point p1(ARRAY_X[distance], ARRAY_Y[distance]),
p2(ARRAY_X[distance - 1], ARRAY_Y[distance - 1]);
Point diff = p1 - p2;
diff.x /= 9;
diff.y /= 5;
drawLine(p2.x + diff.x * 2 + 16, 151 - diff.y - p2.y - 1, p2.x + diff.x * 2 + 16,
p1.y + 8 - diff.y, _edgeColor);
drawLineTo(p2.x + diff.x * 6 + 16, p1.y + diff.y + 8, _edgeColor);
drawLineTo(p2.x + diff.x * 6 + 16, 151 - p1.y + diff.y * 2 - (distance == 1 ? 2 : 0), _edgeColor);
}
}
void DungeonSurface::drawLeftWall(uint distance) {
if (distance <= 5) {
Point p1(ARRAY_X[distance], ARRAY_Y[distance]),
p2(ARRAY_X[distance - 1], ARRAY_Y[distance - 1]);
drawLine(p2.x + 16, p2.y + 8, p1.x + 16, p1.y + 8, _edgeColor);
drawLine(p2.x + 16, 151 - p2.y, p1.x + 16, 151 - p1.y, _edgeColor);
}
}
void DungeonSurface::drawLeftBlank(uint distance) {
if (distance <= 5) {
Point p1(ARRAY_X[distance], ARRAY_Y[distance]),
p2(ARRAY_X[distance - 1], ARRAY_Y[distance - 1]);
drawLine(p2.x + 16, p1.y + 8, p1.x + 16, p1.y + 8, _edgeColor);
drawLine(p2.x + 16, 151 - p1.y, p1.x + 16, 151 - p1.y, _edgeColor);
}
}
void DungeonSurface::drawRightDoor(uint distance) {
if (distance <= 5) {
drawRightWall(distance);
Point p1(ARRAY_X[distance], ARRAY_Y[distance]),
p2(ARRAY_X[distance - 1], ARRAY_Y[distance - 1]);
Point diff = p1 - p2;
diff.x /= 9;
diff.y /= 5;
drawLine(303 - (p2.x + diff.x * 2), 151 - diff.y - p2.y - 1, 303 - (p2.x + diff.x * 2),
p1.y + 8 - diff.y, _edgeColor);
drawLineTo(303 - (diff.x * 6 + p2.x), p1.y + 8 + diff.y, _edgeColor);
drawLineTo(303 - (diff.x * 6 + p2.x), 151 - p1.y + diff.y * 2 - (distance == 1 ? 2 : 0), _edgeColor);
}
}
void DungeonSurface::drawRightWall(uint distance) {
if (distance <= 5) {
Point p1(ARRAY_X[distance], ARRAY_Y[distance]),
p2(ARRAY_X[distance - 1], ARRAY_Y[distance - 1]);
drawLine(303 - p2.x, p2.y + 8, 303 - p1.x, p1.y + 8, _edgeColor);
drawLine(303 - p2.x, 151 - p2.y, 303 - p1.x, 151 - p1.y, _edgeColor);
}
}
void DungeonSurface::drawRightBlank(uint distance) {
if (distance <= 5) {
Point p1(ARRAY_X[distance], ARRAY_Y[distance]),
p2(ARRAY_X[distance - 1], ARRAY_Y[distance - 1]);
drawLine(303 - p2.x, p1.y + 8, 303 - p1.x, p1.y + 8, _edgeColor);
drawLine(303 - p2.x, 151 - p1.y, 303 - p1.x, 151 - p1.y, _edgeColor);
}
}
void DungeonSurface::drawBeams(uint distance) {
if (distance <= 5) {
// Figure out the Y difference between each beam
const int Y_START = ARRAY_Y[distance] + 8;
const int Y_END = 151 - ARRAY_Y[distance];
const int HEIGHT = (Y_END - Y_START) / 4;
for (int beamNum = 0; beamNum < 4; ++beamNum) {
const int YP = Y_START + HEIGHT * beamNum + (distance / 2);
drawLine(ARRAY_X[distance] + 16, YP, 303 - ARRAY_X[distance], YP, _highlightColor);
}
}
}
} // End of namespace Shared
} // End of namespace Ultima

View File

@@ -0,0 +1,174 @@
/* 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 ULTIMA_SHARED_GFX_DUNGEON_H
#define ULTIMA_SHARED_GFX_DUNGEON_H
#include "ultima/shared/gfx/visual_surface.h"
namespace Ultima {
namespace Shared {
typedef void(*DrawWidgetFn)(Graphics::ManagedSurface &s, uint widgetId, uint distance, byte color);
class Game;
/**
* Acts as a handy container for the drawing methods for rendering the dungeon view
*/
class DungeonSurface : public Gfx::VisualSurface {
private:
Point _penPos;
byte _edgeColor;
byte _highlightColor;
byte _widgetColor;
DrawWidgetFn _widgetFn;
public:
/**
* Constructor
*/
DungeonSurface(const Graphics::ManagedSurface &src, const Rect &bounds, Game *game, DrawWidgetFn widgetFn);
/**
* Draw a line
*/
void drawLine(int x0, int y0, int x1, int y1, uint32 color) {
Gfx::VisualSurface::drawLine(x0 - 8, y0 - 8, x1 - 8, y1 - 8, color);
_penPos = Point(x1, y1);
}
/**
* Draw a line from a prior line ending point to a new destination pos
*/
void drawLineTo(int x, int y, uint32 color) {
Gfx::VisualSurface::drawLine(_penPos.x - 8, _penPos.y - 8, x - 8, y - 8, color);
_penPos = Point(x, y);
}
/**
* Draw a horizontal line.
*/
void hLine(int x, int y, int x2, uint32 color) {
Gfx::VisualSurface::hLine(x - 8, y - 8, x2 - 8, color);
_penPos = Point(x2, y);
}
/**
* Draw a vertical line.
*/
void vLine(int x, int y, int y2, uint32 color) {
Gfx::VisualSurface::vLine(x - 8, y - 8, y2 - 8, color);
_penPos = Point(x, y2);
}
/**
* Draw a frame around a specified rect.
*/
void frameRect(const Common::Rect &r, uint32 color) {
Gfx::VisualSurface::frameRect(Rect(r.left - 8, r.top - 8, r.right - 8, r.bottom - 8), color);
}
/**
* Draws a wall
*/
void drawWall(uint distance);
/**
* Draws a doorway directly in front of the player
*/
void drawDoorway(uint distance);
/**
* Draws a vertical line forming the edge of cells to the left of the player
*/
void drawLeftEdge(uint distance);
/**
* Draws a vertical line forming the edge of cells to the right of the player
*/
void drawRightEdge(uint distance);
/**
* Draws a monster or item at a given distance from the player
*/
void drawWidget(uint widgetId, uint distance, byte color);
/**
* Draw a ladder down face on
*/
void drawLadderDownFaceOn(uint distance);
/**
* Draw a ladder down side on
*/
void drawLadderDownSideOn(uint distance);
/**
* Draw a ladder down face on
*/
void drawLadderUpFaceOn(uint distance);
/**
* Draw a ladder down side on
*/
void drawLadderUpSideOn(uint distance);
/**
* Draw beams
*/
void drawBeams(uint distance);
/**
* Draws a door on the left hand side
*/
void drawLeftDoor(uint distance);
/**
* Draws a wall on the left-hand side
*/
void drawLeftWall(uint distance);
/**
* Draws the partial wall visible at the back of a corridor leading to the left
*/
void drawLeftBlank(uint distance);
/**
* Draws a door on the right hand side
*/
void drawRightDoor(uint distance);
/**
* Draws a wall on the right-hand side
*/
void drawRightWall(uint distance);
/**
* Draws the partial wall visible at the back of a corridor leading to the right
*/
void drawRightBlank(uint distance);
};
} // End of namespace Shared
} // End of namespace Ultima
#endif

View File

@@ -0,0 +1,83 @@
/* 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/shared/gfx/font.h"
#include "graphics/managed_surface.h"
namespace Ultima {
namespace Shared {
namespace Gfx {
Font::Font(const byte *data, size_t startingChar, size_t charCount) :
_data(data), _startingChar(startingChar), _endingChar(startingChar + charCount - 1) {}
int Font::writeString(Graphics::ManagedSurface &surface, const Common::String &msg, Point &pt,
byte color, byte bgColor) {
int total = 0;
int xs = pt.x;
for (const char *msgP = msg.c_str(); *msgP; ++msgP, total += 8) {
if (*msgP == '\n') {
// Move to next line
pt.x = xs;
pt.y += lineHeight();
} else {
// Write out character
writeChar(surface, (unsigned char)*msgP, pt, color, bgColor);
}
}
return total;
}
void Font::writeChar(Graphics::ManagedSurface &surface, unsigned char c, Point &pt,
byte color, byte bgColor) {
assert(c >= _startingChar && c <= _endingChar);
const byte *charP = _data + (c - _startingChar) * 8;
Graphics::Surface s = surface.getSubArea(Common::Rect(pt.x, pt.y, pt.x + 8, pt.y + 8));
for (int y = 0; y < 8; ++y) {
byte *lineP = (byte *)s.getBasePtr(0, y);
byte lineData = charP[y];
for (int x = 0; x < 8; ++x, lineData <<= 1, ++lineP) {
*lineP = (lineData & 0x80) ? color : bgColor;
}
}
pt.x += charWidth(c);
}
uint Font::charWidth(char c) const {
return 8;
}
uint Font::lineHeight() const {
return 8;
}
uint Font::stringWidth(const Common::String &msg) const {
return msg.size() * 8;
}
} // End of namespace Gfx
} // End of namespace Shared
} // End of namespace Ultima

View File

@@ -0,0 +1,73 @@
/* 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 ULTIMA_SHARED_GFX_FONT_H
#define ULTIMA_SHARED_GFX_FONT_H
#include "common/array.h"
#include "common/stream.h"
#include "graphics/managed_surface.h"
#include "ultima/shared/core/rect.h"
namespace Ultima {
namespace Shared {
namespace Gfx {
class Font {
private:
const byte *_data;
size_t _startingChar, _endingChar;
public:
Font(const byte *data, size_t startingChar = 0, size_t charCount = 256);
/**
* Write out a string
*/
int writeString(Graphics::ManagedSurface &surface, const Common::String &msg,
Point &pt, byte color, byte bgColor = 0);
/**
* Draw a character
*/
void writeChar(Graphics::ManagedSurface &surface, unsigned char c, Point &pt,
byte color, byte bgColor = 0);
/**
* Return the width of a character
*/
uint charWidth(char c) const;
/**
* Return the width of a string
*/
uint stringWidth(const Common::String &msg) const;
/**
* Returns the height of the font
*/
uint lineHeight() const;
};
} // End of namespace Gfx
} // End of namespace Shared
} // End of namespace Ultima
#endif

View File

@@ -0,0 +1,156 @@
/* 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/shared/gfx/info.h"
#include "ultima/shared/early/game.h"
#include "ultima/shared/gfx/text_cursor.h"
#include "ultima/shared/core/str.h"
namespace Ultima {
namespace Shared {
#define PROMPT_CHAR '\x1'
#define SUGGESTED_CR '\r'
BEGIN_MESSAGE_MAP(Info, Shared::Gfx::VisualItem)
ON_MESSAGE(InfoMsg)
ON_MESSAGE(InfoGetCommandKeypress)
ON_MESSAGE(InfoGetKeypress)
ON_MESSAGE(InfoGetInput)
ON_MESSAGE(KeypressMsg)
END_MESSAGE_MAP()
Info::Info(TreeItem *parent, const Rect &bounds) : Gfx::VisualItem("Info", bounds, parent),
_commandRespondTo(nullptr) {
_characterInput = new Gfx::CharacterInput(getGame());
_textInput = new Gfx::TextInput(getGame());
}
Info::~Info() {
delete _characterInput;
delete _textInput;
}
bool Info::InfoMsg(CInfoMsg *msg) {
// Iterate through text, dealing with lines one at a time
StringArray lines = String(msg->_text).split("\r\n");
if (!_lines.empty() && msg->_replaceLine)
_lines.back() = _lines.back().firstChar();
for (uint idx = 0; idx < lines.size(); ++idx) {
if (_lines.empty() || idx > 0)
_lines.push_back(" ");
_lines.back() += lines[idx];
}
// Add newline if necessary
if (msg->_newLine)
_lines.push_back(" ");
setDirty();
// Adding any text hides any visible cursor
_commandRespondTo = nullptr;
Gfx::TextCursor *textCursor = getGame()->_textCursor;
textCursor->setVisible(false);
return true;
}
bool Info::InfoGetCommandKeypress(CInfoGetCommandKeypress *msg) {
if (_lines.empty() || _lines.back() != " ")
_lines.push_back("");
_lines.back() = PROMPT_CHAR;
Gfx::TextCursor *textCursor = getGame()->_textCursor;
textCursor->setVisible(true);
textCursor->setPosition(Point(8, _bounds.bottom - 8));
_commandRespondTo = msg->_responder;
return true;
}
bool Info::InfoGetKeypress(CInfoGetKeypress *msg) {
Game *game = getGame();
Point pt(_bounds.left + _lines.back().size() * 8, _bounds.bottom - 8);
_characterInput->show(pt, game->_textColor, msg->_responder);
return true;
}
bool Info::InfoGetInput(CInfoGetInput *msg) {
Game *game = getGame();
Point pt(_bounds.left + _lines.back().size() * 8, _bounds.bottom - 8);
_textInput->show(pt, msg->_isNumeric, msg->_maxCharacters, game->_textColor, msg->_responder);
return true;
}
bool Info::KeypressMsg(CKeypressMsg *msg) {
// If waiting for a command, dispatch the key to the respond, and hide the cursor
if (_commandRespondTo) {
TreeItem *target = _commandRespondTo;
_commandRespondTo = nullptr;
getGame()->_textCursor->setVisible(false);
CCharacterInputMsg cMsg(msg->_keyState);
cMsg.execute(target);
return true;
}
return true;
}
void Info::draw() {
// Clear the background
Gfx::VisualSurface s = getSurface();
s.clear();
// Get the number og lines to display
uint lineHeight = s.fontHeight();
uint numLines = (s.h + lineHeight - 1) / lineHeight;
// Discard any stored lines beyond the top of the display
while (_lines.size() > numLines)
_lines.remove_at(0);
// Display the lines
int x = 0, y = s.h - _lines.size() * lineHeight;
for (uint idx = 0; idx < _lines.size(); ++idx, x = 0, y += lineHeight) {
// Handle drawing the prompt character at the start of lines if necessary
Common::String line = _lines[idx];
if (!line.empty() && line[0] == PROMPT_CHAR) {
drawPrompt(s, Point(0, y));
x = 8;
line.deleteChar(0);
}
// Write the remainder of the line
s.writeString(line, Point(x, y));
}
_isDirty = false;
}
} // End of namespace Shared
} // End of namespace Ultima

View File

@@ -0,0 +1,80 @@
/* 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 ULTIMA_SHARED_GFX_INFO_H
#define ULTIMA_SHARED_GFX_INFO_H
#include "ultima/shared/gfx/visual_item.h"
#include "ultima/shared/gfx/text_input.h"
#include "ultima/shared/gfx/character_input.h"
#include "common/str-array.h"
namespace Ultima {
namespace Shared {
using Shared::CInfoMsg;
using Shared::CInfoGetCommandKeypress;
using Shared::CInfoGetInput;
using Shared::CKeypressMsg;
/**
* Textual info area, showing what commands area done, and any responses to them
*/
class Info : public Gfx::VisualItem {
DECLARE_MESSAGE_MAP;
bool InfoMsg(CInfoMsg *msg);
bool InfoGetCommandKeypress(CInfoGetCommandKeypress *msg);
bool InfoGetKeypress(CInfoGetKeypress *msg);
bool InfoGetInput(CInfoGetInput *msg);
bool KeypressMsg(CKeypressMsg *msg);
private:
Common::StringArray _lines;
Gfx::TextInput *_textInput;
Gfx::CharacterInput *_characterInput;
TreeItem *_commandRespondTo;
protected:
/**
* Draws a prompt character
*/
virtual void drawPrompt(Gfx::VisualSurface &surf, const Point &pt) = 0;
public:
CLASSDEF;
/**
* Constructor
*/
Info(TreeItem *parent, const Rect &bounds);
/**
* Destructor
*/
~Info() override;
/**
* Draw the contents
*/
void draw() override;
};
} // End of namespace Shared
} // End of namespace Ultima
#endif

View File

@@ -0,0 +1,70 @@
/* 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/shared/gfx/popup.h"
#include "ultima/shared/early/game_base.h"
namespace Ultima {
namespace Shared {
namespace Gfx {
BEGIN_MESSAGE_MAP(Popup, VisualItem)
ON_MESSAGE(ShowMsg)
END_MESSAGE_MAP()
Popup::Popup(GameBase *game) : VisualItem(nullptr), _game(game), _respondTo(nullptr), _parentView(nullptr) {
game->addChild(this);
}
Popup::~Popup() {
detach();
}
void Popup::show(TreeItem *respondTo) {
// Save a copy of the view the popup is being shown on, and activate it
_parentView = _game->getView();
_respondTo = respondTo;
if (!_respondTo)
_respondTo = _parentView;
_game->setPopup(this);
setDirty();
}
void Popup::hide() {
CPopupHiddenMsg hiddenMsg(this);
hiddenMsg.execute(_respondTo, nullptr, 0);
// Reset back to the parent view
_game->setView(_parentView);
_parentView->setDirty();
}
bool Popup::ShowMsg(CShowMsg *msg) {
CPopupShownMsg shownMsg(this);
shownMsg.execute(_respondTo, nullptr, 0);
return true;
}
} // End of namespace Gfx
} // End of namespace Shared
} // End of namespace Ultima

View File

@@ -0,0 +1,75 @@
/* 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 ULTIMA_SHARED_GFX_POPUP_H
#define ULTIMA_SHARED_GFX_POPUP_H
#include "ultima/shared/gfx/visual_item.h"
namespace Ultima {
namespace Shared {
class GameBase;
namespace Gfx {
/**
* Base class for graphic elements that "pop up" on top of existing views. This includes things like
* dialogs, text input, etc.
*/
class Popup : public VisualItem {
DECLARE_MESSAGE_MAP;
bool ShowMsg(CShowMsg *msg);
protected:
GameBase *_game;
VisualItem *_parentView;
TreeItem *_respondTo;
public:
CLASSDEF;
/**
* Constructor
*/
Popup(GameBase *game);
/**
* Destructor
*/
~Popup() override;
/**
* Show the popup
* @param respondTo Element to send any response to when the popup closes.
* If not provided, any response goes to the active view
*/
void show(TreeItem *respondTo = nullptr);
/**
* Hide the popup
*/
virtual void hide();
};
} // End of namespace Gfx
} // End of namespace Shared
} // End of namespace Ultima
#endif

View File

@@ -0,0 +1,61 @@
/* 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 "engines/util.h"
#include "ultima/shared/gfx/screen.h"
namespace Ultima {
namespace Shared {
namespace Gfx {
Screen::Screen(): Graphics::Screen(320, 200), _cursor(nullptr), _drawCursor(false) {
initGraphics(320, 200);
}
void Screen::update() {
_drawCursor = false;
if (_cursor) {
// Check whether the area the cursor occupies will be being updated
Common::Rect cursorBounds = _cursor->getBounds();
for (const auto &r : _dirtyRects) {
if (r.intersects(cursorBounds)) {
addDirtyRect(cursorBounds);
_drawCursor = true;
break;
}
}
}
Graphics::Screen::update();
}
void Screen::updateScreen() {
if (_drawCursor)
_cursor->draw();
Graphics::Screen::updateScreen();
}
} // End of namespace Gfx
} // End of namespace Shared
} // 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 ULTIMA_SHARED_GFX_SCREEN_H
#define ULTIMA_SHARED_GFX_SCREEN_H
#include "common/list.h"
#include "ultima/shared/core/rect.h"
#include "graphics/screen.h"
#include "ultima/shared/gfx/font.h"
#include "ultima/shared/engine/messages.h"
namespace Ultima {
namespace Shared {
namespace Gfx {
/**
* Base class for an on-screen cursor. Currently used for text cursor display
*/
class Cursor {
public:
/**
* Destructor
*/
virtual ~Cursor() {}
/**
* Get the bounds of the cursor
*/
virtual Common::Rect getBounds() const = 0;
/**
* Draw the cursor
*/
virtual void draw() = 0;
};
class Screen: public Graphics::Screen {
private:
Cursor *_cursor;
bool _drawCursor;
public:
/**
* Constructor
*/
Screen();
/**
* Updates the screen by copying any affected areas to the system
*/
void update() override;
/**
* Updates the screen at the end of an update call
*/
void updateScreen() override;
/**
* Sets the currently active cursor
*/
void setCursor(Cursor *cursor) { _cursor = cursor; }
};
} // End of namespace Gfx
} // End of namespace Shared
} // End of namespace Ultima
#endif

View File

@@ -0,0 +1,106 @@
/* 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/shared/gfx/sprites.h"
#include "ultima/shared/core/file.h"
namespace Ultima {
namespace Shared {
namespace Gfx {
Sprite::Sprite() {
}
Sprite::Sprite(const Sprite &src) {
_surface.copyFrom(src._surface);
_transSurface.copyFrom(src._transSurface);
}
Sprite::Sprite(const byte *src, uint bpp, uint16 w, uint16 h) {
_surface.create(w, h, Graphics::PixelFormat::createFormatCLUT8());
assert((w % bpp) == 0);
byte v = 0;
for (int y = 0; y < h; ++y) {
byte *destP = (byte *)_surface.getBasePtr(0, y);
for (int x = 0; x < w; ++x, v <<= bpp) {
if ((x % (8 / bpp)) == 0)
v = *src++;
*destP++ = (((uint)v << bpp) & 0xff00) >> 8;
}
}
}
Sprite &Sprite::operator=(const Sprite &src) {
_surface.copyFrom(src._surface);
_transSurface.copyFrom(src._transSurface);
return *this;
}
void Sprite::draw(Graphics::ManagedSurface &dest, const Common::Point &pt) {
// Get area to be drawn on
Graphics::Surface s = dest.getSubArea(Common::Rect(pt.x, pt.y, pt.x + _surface.w, pt.y + _surface.h));
// Draw the sprite
for (uint16 y = 0; y < _surface.h; ++y) {
const byte *srcP = (const byte *)_surface.getBasePtr(0, y);
const byte *transP = (const byte *)_transSurface.getBasePtr(0, y);
byte *destP = (byte *)s.getBasePtr(0, y);
for (uint16 x = 0; x < _surface.w; ++x, ++srcP, ++transP, ++destP) {
if (_transSurface.empty() || *transP)
*destP = *srcP;
}
}
}
/*-------------------------------------------------------------------*/
void Sprites::load(const Common::Path &name, uint bpp, uint16 w, uint16 h) {
_spriteSize = Point(w, h);
// Open the tiles for access
File f(name);
byte *buffer = new byte[w * h];
// Figure out how many tiles the file has
size_t bytesPerTile = (w / (8 / bpp)) * h;
size_t count = f.size() / bytesPerTile;
// Ensure there's enough capacity for the tileset
if (count > size())
_data.resize(count);
// Iterate through loading the tile data and creating sprites for them
for (size_t idx = 0; idx < count; ++idx) {
f.read(buffer, bytesPerTile);
_data[idx] = Sprite(buffer, bpp, w, h);
}
delete[] buffer;
}
} // End of namespace Gfx
} // End of namespace Shared
} // End of namespace Ultima

View File

@@ -0,0 +1,138 @@
/* 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 ULTIMA_SPRITES_H
#define ULTIMA_SPRITES_H
#include "common/array.h"
#include "common/path.h"
#include "graphics/managed_surface.h"
#include "ultima/shared/core/rect.h"
namespace Ultima {
namespace Shared {
namespace Gfx {
class Sprite {
private:
Graphics::ManagedSurface _surface;
Graphics::ManagedSurface _transSurface;
public:
/**
* Constructor
*/
Sprite();
/**
* Constructor, copying from another sprite
*/
Sprite(const Sprite &src);
/**
* Constructor, loading a sprite from passed data
* @param src Source data
* @param bpp The bits per pixel for tiles in the file
* @param w Width of tiles
* @param h Height of files
*/
Sprite(const byte *src, uint bpp, uint16 w = 16, uint16 h = 16);
/**
* Copy assignment operator
*/
Sprite &operator=(const Sprite &src);
/**
* Draw a tile onto a passed surface
*/
void draw(Graphics::ManagedSurface &dest, const Common::Point &pt);
/**
* Return the width of the sprite
*/
uint16 w() const { return _surface.w; }
/**
* Return the height of the sprite
*/
uint16 h() const { return _surface.h; }
/**
* Get a reference to the sprite surface
*/
byte *getPixels() { return (byte *)_surface.getPixels(); }
/**
* Get a reference to a specified position within the sprite
*/
byte *getBasePtr(int16 x, int16 y) { return (byte *)_surface.getBasePtr(x, y); }
/**
* Get a reference to a specified position within the sprite
*/
const byte *getBasePtr(int16 x, int16 y) const { return (const byte *)_surface.getBasePtr(x, y); }
};
class Sprites {
protected:
Common::Array<Sprite> _data;
Point _spriteSize; // Size of individual sprites
protected:
/**
* Load a raw data file containing sprite pixels
* @param name Filename
* @param bpp The bits per pixel for tiles in the file
* @param w Width of tiles
* @param h Height of files
*/
void load(const Common::Path &name, uint bpp, uint16 w = 16, uint16 h = 16);
public:
/**
* Destructor
*/
virtual ~Sprites() {}
/**
* Return the default dimensions for tiles
*/
Point getSpriteSize() const { return _spriteSize; }
/**
* Return the size of the sprites list
*/
size_t size() const { return _data.size(); }
/**
* Returns true if the sprites list is empty
*/
bool empty() const { return size() == 0; }
/**
* Return a specific sprite
*/
virtual Sprite &operator[](uint idx) { return _data[idx]; }
};
} // End of namespace Gfx
} // End of namespace Shared
} // End of namespace Ultima
#endif

View File

@@ -0,0 +1,35 @@
/* 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/shared/gfx/text_cursor.h"
#include "ultima/shared/early/ultima_early.h"
namespace Ultima {
namespace Shared {
namespace Gfx {
void TextCursor::markAsDirty() {
g_vm->_screen->getSubArea(_bounds);
}
} // End of namespace Gfx
} // End of namespace Shared
} // 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 ULTIMA_SHARED_GFX_TEXT_CURSOR_H
#define ULTIMA_SHARED_GFX_TEXT_CURSOR_H
#include "ultima/shared/core/rect.h"
#include "ultima/shared/gfx/screen.h"
namespace Ultima {
namespace Shared {
namespace Gfx {
/**
* Base class for text cursors, and is used by those games that don't have a visible cursor
*/
class TextCursor : public Cursor {
protected:
bool _visible;
Common::Rect _bounds;
protected:
/**
* Marks the area of the screen the cursor covers as dirty
*/
void markAsDirty();
public:
TextCursor() : _visible(false) {
}
~TextCursor() override {
}
/**
* Returns true if the cursor is visible
*/
bool isVisible() const {
return _visible;
}
/**
* Sets the visibility of the cursor
*/
virtual void setVisible(bool isVis) {
_visible = isVis;
markAsDirty();
}
/**
* Get the bounds of the cursor
*/
Common::Rect getBounds() const override { return _bounds; }
/**
* Returns the position of the cursor
*/
Point getPosition() const { return Point(_bounds.left, _bounds.top); }
/**
* Sets the position of the cursor
*/
void setPosition(const Point &pt) {
bool vis = _visible;
setVisible(false);
_bounds.moveTo(pt);
setVisible(vis);
}
/**
* Update the cursor
*/
virtual void update() = 0;
};
} // End of namespace Gfx
} // End of namespace Shared
} // End of namespace Ultima
#endif

View File

@@ -0,0 +1,96 @@
/* 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/shared/gfx/text_input.h"
#include "ultima/shared/gfx/text_cursor.h"
#include "ultima/shared/early/game_base.h"
#include "ultima/shared/engine/messages.h"
namespace Ultima {
namespace Shared {
namespace Gfx {
BEGIN_MESSAGE_MAP(TextInput, Popup)
ON_MESSAGE(KeypressMsg)
END_MESSAGE_MAP()
void TextInput::show(const Point &pt, bool isNumeric, size_t maxCharacters, byte color, TreeItem *respondTo) {
Popup::show(respondTo);
_isNumeric = isNumeric;
_maxCharacters = maxCharacters;
_color = color;
_bounds = Rect(pt.x, pt.y, pt.x + 8 * (maxCharacters + 1), pt.y + 8);
_text = "";
_game->_textCursor->setPosition(Point(_bounds.left, _bounds.top));
_game->_textCursor->setVisible(true);
}
void TextInput::draw() {
Popup::draw();
VisualSurface s = getSurface();
// Ensure the cursor is at the right position
_game->_textCursor->setPosition(Point(_bounds.left + _text.size() * 8, _bounds.top));
// Display the text
Common::String text = _text;
while (text.size() < _maxCharacters)
text += ' ';
s.writeString(text, TextPoint(0, 0), _color);
}
bool TextInput::KeypressMsg(CKeypressMsg *msg) {
uint16 c = msg->_keyState.ascii;
//TreeItem *respondTo = _respondTo;
if (c >= ' ' && c <= 0x7f) {
// Printable character
if (_text.size() < _maxCharacters && (!_isNumeric || (c >= '0' && c <= '9'))) {
_text += msg->_keyState.ascii;
setDirty();
}
} else if (msg->_keyState.keycode == Common::KEYCODE_BACKSPACE || msg->_keyState.keycode == Common::KEYCODE_LEFT) {
if (!_text.empty()) {
_text.deleteLastChar();
setDirty();
}
} else if (msg->_keyState.keycode == Common::KEYCODE_RETURN || msg->_keyState.keycode == Common::KEYCODE_KP_ENTER) {
_game->_textCursor->setVisible(false);
hide();
CTextInputMsg inputMsg(_text, false);
inputMsg.execute(_respondTo);
} else if (msg->_keyState.keycode == Common::KEYCODE_ESCAPE) {
_game->_textCursor->setVisible(false);
hide();
CTextInputMsg inputMsg("", true);
inputMsg.execute(_respondTo);
}
return true;
}
} // End of namespace Gfx
} // End of namespace Shared
} // End of namespace Ultima

View File

@@ -0,0 +1,68 @@
/* 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 ULTIMA_GFX_TEXT_INPUT_H
#define ULTIMA_GFX_TEXT_INPUT_H
#include "ultima/shared/gfx/popup.h"
namespace Ultima {
namespace Shared {
namespace Gfx {
/**
* Text input control
*/
class TextInput : public Popup {
DECLARE_MESSAGE_MAP;
bool KeypressMsg(CKeypressMsg *msg);
private:
bool _isNumeric;
size_t _maxCharacters;
Common::String _text;
byte _color;
public:
CLASSDEF;
TextInput(GameBase *game) : Popup(game), _isNumeric(false), _maxCharacters(0), _color(0) {}
/**
* Draws the visual item on the screen
*/
void draw() override;
/**
* Show the text input
* @param pt Position of the input
* @param maxCharacters Maximum length of input
* @param color Text color
* @param respondTo Element to send any response to when the popup closes.
* If not provided, any response goes to the active view
* @remarks Generates a TextInputMsg message with the text when Enter or escape is pressed
*/
void show(const Point &pt, bool isNumeric, size_t maxCharacters, byte color,
TreeItem *respondTo = nullptr);
};
} // End of namespace Gfx
} // End of namespace Shared
} // End of namespace Ultima
#endif

View File

@@ -0,0 +1,267 @@
/* 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/shared/gfx/viewport_dungeon.h"
#include "ultima/shared/maps/dungeon_widget.h"
#include "ultima/shared/maps/dungeon_creature.h"
#include "ultima/shared/maps/map_widget.h"
#include "ultima/shared/maps/map.h"
#include "ultima/shared/early/game.h"
namespace Ultima {
namespace Shared {
EMPTY_MESSAGE_MAP(ViewportDungeon, Shared::Gfx::VisualItem);
void ViewportDungeon::draw() {
// Get a surface reference and clear it's contents
DungeonSurface s = getSurface();
s.clear();
// Get the position delta for the facing direction, and the cells to the left and right of that
Maps::Map *map = getGame()->getMap();
Point delta = map->getDirectionDelta();
Point leftDelta, rightDelta;
switch (map->getDirection()) {
case Maps::DIR_LEFT:
leftDelta.y = 1;
rightDelta.y = -1;
break;
case Maps::DIR_RIGHT:
leftDelta.y = -1;
rightDelta.y = 1;
break;
case Maps::DIR_UP:
leftDelta.x = -1;
rightDelta.x = 1;
break;
case Maps::DIR_DOWN:
leftDelta.x = 1;
rightDelta.x = -1;
break;
default:
break;
}
Maps::MapTile tile, deltaTile, leftTile, rightTile, backTile;
Point currentPos = map->getPosition();
map->getTileAt(currentPos, &tile);
map->getTileAt(currentPos + delta, &deltaTile);
bool isDoor = tile.isDoor();
bool isWall = tile.isWallOrSecretDoor();
int distance = distanceToOccupiedCell(delta);
// If stuck in a wall, draw it and exit
if (isWall) {
s.drawWall(0);
return;
}
Point backDelta(delta.x * distance, delta.y * distance),
currDelta(delta.x * distance, delta.y * distance);
if (isDoor && deltaTile.isWallOrDoorway()) {
s.drawWall(0);
} else {
if (isDoor)
s.drawDoorway(0);
// These are essentially boolean flags with an extra 'initial' state
byte endingLeft = 100, endingRight = 100;
byte leftFlag = 100, rightFlag = 100;
byte priorLeftFlag = 100, priorRightFlag = 100;
for (int index = distance; index; --index) {
currDelta -= delta;
Point pt = currentPos + currDelta;
if (!isDoor || index > 1) {
map->getTileAt(pt + leftDelta, &leftTile);
map->getTileAt(pt + rightDelta, &rightTile);
leftFlag = leftTile.isSolid();
rightFlag = rightTile.isSolid();
if (index == distance) {
endingLeft = leftFlag;
endingRight = rightFlag;
} else {
if (leftFlag != priorLeftFlag)
s.drawLeftEdge(index);
if (rightFlag != priorRightFlag)
s.drawRightEdge(index);
}
drawLeftCell(index, leftTile);
drawRightCell(index, rightTile);
}
drawCell(index, pt + delta);
priorLeftFlag = leftFlag;
priorRightFlag = rightFlag;
}
if (!isDoor)
drawCell(0, currentPos);
map->getTileAt(currentPos + delta, &backTile);
if (distance < 5 && isMonsterBlocking(currentPos + backDelta) && backTile.isDoor()) {
map->getTileAt(currentPos + leftDelta, &leftTile);
map->getTileAt(currentPos + rightDelta, &rightTile);
drawLeftCell(distance + 1, leftTile);
drawRightCell(distance + 1, rightTile);
map->getTileAt(currentPos + leftDelta, &leftTile);
if (!leftTile.isSolid())
s.drawLeftEdge(distance);
if (!rightTile.isSolid())
s.drawRightEdge(distance);
} else {
if (endingLeft)
s.drawLeftEdge(distance);
if (endingRight)
s.drawRightEdge(distance);
}
}
Maps::DungeonWidget *widget = dynamic_cast<Maps::DungeonWidget *>(tile._widget);
if (isDoor && widget) {
widget->draw(s, 0);
}
}
uint ViewportDungeon::distanceToOccupiedCell(const Point &delta) {
Point d = delta;
uint distance;
for (distance = 1; !isCellOccupied(d); ++distance, d.x += delta.x, d.y += delta.y) {}
return MIN(distance, (uint)5);
}
bool ViewportDungeon::isCellOccupied(const Point &delta) {
Maps::Map *map = getGame()->getMap();
Point pt = map->getPosition() + delta;
Maps::MapTile tile;
map->getTileAt(pt, &tile);
if (tile.isWallOrDoorway())
return true;
return isMonsterBlocking(pt);
}
bool ViewportDungeon::isMonsterBlocking(const Point &pt) {
Maps::MapTile tile;
getGame()->getMap()->getTileAt(pt, &tile);
Maps::DungeonCreature *monster = dynamic_cast<Maps::DungeonCreature *>(tile._widget);
return monster != nullptr && monster->isBlockingView();
}
void ViewportDungeon::drawCell(uint distance, const Point &pt) {
Game *game = getGame();
DungeonSurface s = getSurface();
Maps::Map *map = game->getMap();
Maps::MapTile tile;
map->getTileAt(pt, &tile);
// TODO: This currently contains dungeon cell types specific to Ultima 1
Maps::DungeonCreature *monster = dynamic_cast<Maps::DungeonCreature *>(tile._widget);
if (monster) {
// Draw a monster
if (tile.isWallOrDoorway())
s.drawWall(distance);
if (tile._tileId == 7)
// Ladder down
s.drawWidget(27, distance + 1, game->_edgeColor);
if (tile._tileId == 6)
// Ladder up
s.drawWidget(26, distance + 1, game->_edgeColor);
monster->draw(s, distance);
} else {
switch (tile._tileId) {
case 1:
case 2:
// Wall or secret door
s.drawWall(distance);
break;
case 3:
// Doorway
s.drawDoorway(distance);
break;
case 6:
// Ladder down
if (map->getDirection() == Maps::DIR_UP || map->getDirection() == Maps::DIR_DOWN) {
s.drawLadderDownFaceOn(distance + 1);
} else {
s.drawLadderDownSideOn(distance + 1);
}
break;
case 7:
// Ladder up
if (map->getDirection() == Maps::DIR_UP || map->getDirection() == Maps::DIR_DOWN) {
s.drawLadderUpFaceOn(distance + 1);
} else {
s.drawLadderUpSideOn(distance + 1);
}
break;
case 8:
// Beams
s.drawBeams(distance);
break;
default:
break;
}
}
// Draw any item at that distance
Maps::DungeonWidget *widget = dynamic_cast<Maps::DungeonWidget *>(tile._widget);
if (widget)
widget->draw(s, distance);
}
void ViewportDungeon::drawLeftCell(uint distance, const Maps::MapTile &tile) {
DungeonSurface s = getSurface();
if (tile.isDoor())
s.drawLeftDoor(distance);
else if (tile.isWallOrSecretDoor())
s.drawLeftWall(distance);
else
s.drawLeftBlank(distance);
}
void ViewportDungeon::drawRightCell(uint distance, const Maps::MapTile &tile) {
DungeonSurface s = getSurface();
if (tile.isDoor())
s.drawRightDoor(distance);
else if (tile.isWallOrSecretDoor())
s.drawRightWall(distance);
else
s.drawRightBlank(distance);
}
} // End of namespace Shared
} // End of namespace Ultima

View File

@@ -0,0 +1,83 @@
/* 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 ULTIMA_SHARED_GFX_VIEWPORT_DUNGEON_H
#define ULTIMA_SHARED_GFX_VIEWPORT_DUNGEON_H
#include "ultima/shared/gfx/visual_item.h"
#include "ultima/shared/gfx/dungeon_surface.h"
#include "ultima/shared/maps/map_tile.h"
namespace Ultima {
namespace Shared {
class ViewportDungeon : public Gfx::VisualItem {
DECLARE_MESSAGE_MAP;
private:
/**
* Returns the distance to an occupied cell, if any
*/
uint distanceToOccupiedCell(const Point &delta);
/**
* Returns if a cell at a given delta to the player is occupied
*/
bool isCellOccupied(const Point &delta);
/**
* Returns true if a monster is at a given position, and it has the blocking attribute
*/
bool isMonsterBlocking(const Point &pt);
/**
* Draw a monster or, failing that, the given tile at a given cell and distance
*/
void drawCell(uint distance, const Point &pt);
/**
* Draw a cell to the left
*/
void drawLeftCell(uint distance, const Maps::MapTile &tile);
/**
* Draw a cell to the left
*/
void drawRightCell(uint distance, const Maps::MapTile &tile);
protected:
/**
* Returns the surface for rendering the dungeon
*/
virtual DungeonSurface getSurface() = 0;
public:
CLASSDEF;
ViewportDungeon(TreeItem *parent) : Gfx::VisualItem("ViewportDungeon", Rect(8, 8, 312, 152), parent) {}
~ViewportDungeon() override {}
/**
* Draws the dungeon
*/
void draw() override;
};
} // End of namespace Shared
} // End of namespace Ultima
#endif

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/>.
*
*/
#include "ultima/shared/gfx/viewport_map.h"
#include "ultima/shared/maps/map.h"
#include "ultima/shared/early/game.h"
namespace Ultima {
namespace Shared {
EMPTY_MESSAGE_MAP(ViewportMap, Gfx::VisualItem);
void ViewportMap::draw() {
// Get a surface reference and clear it's contents
Gfx::VisualSurface s = getSurface();
s.clear();
// Figure out how many tiles can fit into the display
const Point spriteSize = _sprites->getSpriteSize();
const Point visibleTiles(_bounds.width() / spriteSize.x, _bounds.height() / spriteSize.y);
// Get a reference to the map and get the starting tile position
Maps::Map *map = getGame()->getMap();
const Point topLeft = map->getViewportPosition(visibleTiles);
// Iterate through drawing the map
Maps::MapTile tile;
for (int y = 0; y < visibleTiles.y; ++y) {
for (int x = 0; x < visibleTiles.x; ++x) {
Point drawPos(x * spriteSize.x, y * spriteSize.y);
// Get the next tile to display and draw it
map->getTileAt(Point(topLeft.x + x, topLeft.y + y), &tile);
(*_sprites)[tile._tileDisplayNum].draw(s, drawPos);
// Draw any widgets on the tile
for (uint idx = 0; idx < tile._widgets.size(); ++idx)
(*_sprites)[tile._widgets[idx]->getTileNum()].draw(s, drawPos);
}
}
}
} // End of namespace Shared
} // End of namespace Ultima

View File

@@ -0,0 +1,57 @@
/* 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 ULTIMA_SHARED_GFX_VIEWPORT_MAP_H
#define ULTIMA_SHARED_GFX_VIEWPORT_MAP_H
#include "ultima/shared/gfx/visual_item.h"
#include "ultima/shared/gfx/sprites.h"
namespace Ultima {
namespace Shared {
class ViewportMap : public Gfx::VisualItem {
DECLARE_MESSAGE_MAP;
protected:
Gfx::Sprites *_sprites;
public:
CLASSDEF;
/**
* Constructor
*/
ViewportMap(TreeItem *parent) : Gfx::VisualItem("ViewportMap", Rect(8, 8, 312, 152), parent), _sprites(nullptr) {}
/**
* Destructor
*/
~ViewportMap() override {}
/**
* Draws the map
*/
void draw() override;
};
} // End of namespace Shared
} // End of namespace Ultima
#endif

View File

@@ -0,0 +1,140 @@
/* 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/shared/gfx/visual_container.h"
namespace Ultima {
namespace Shared {
namespace Gfx {
BEGIN_MESSAGE_MAP(VisualContainer, VisualItem)
ON_MESSAGE(MouseButtonDownMsg)
ON_MESSAGE(MouseButtonUpMsg)
ON_MESSAGE(MouseMoveMsg)
ON_MESSAGE(MouseDoubleClickMsg)
ON_MESSAGE(MouseWheelMsg)
END_MESSAGE_MAP()
bool VisualContainer::MouseButtonDownMsg(CMouseButtonDownMsg *msg) {
if (msg->_buttons & MB_LEFT) {
_mouseFocusItem = handleMouseMsg(msg);
return _mouseFocusItem != nullptr;
}
return false;
}
bool VisualContainer::MouseButtonUpMsg(CMouseButtonUpMsg *msg) {
if (msg->_buttons & MB_LEFT) {
bool result = handleMouseMsg(msg) != nullptr;
_mouseFocusItem = nullptr;
return result;
}
return false;
}
bool VisualContainer::MouseDoubleClickMsg(CMouseDoubleClickMsg *msg) {
if (msg->_buttons & MB_LEFT)
return handleMouseMsg(msg);
return false;
}
bool VisualContainer::MouseWheelMsg(CMouseWheelMsg *msg) {
return handleMouseMsg(msg);
}
bool VisualContainer::MouseMoveMsg(CMouseMoveMsg *msg) {
if (msg->_buttons & MB_LEFT)
return handleMouseMsg(msg);
return false;
}
bool VisualContainer::MouseDragMsg(CMouseDragMsg *msg) {
return handleMouseMsg(msg);
}
VisualItem *VisualContainer::handleMouseMsg(CMouseMsg *msg) {
if (_mouseFocusItem) {
// An item currently has focus, so pass all events directly to
// it, irrespective of whether the mouse is still in it or not
msg->execute(_mouseFocusItem);
return _mouseFocusItem;
} else {
// Iterate through each child and pass the message to the first
// immediate child the mouse position falls within
for (TreeItem *child = getFirstChild(); child; child = child->getNextSibling()) {
VisualItem *item = dynamic_cast<VisualItem *>(child);
if (item && item->getBounds().contains(msg->_mousePos)) {
if (msg->execute(item))
return item;
}
}
return nullptr;
}
}
void VisualContainer::draw() {
// If the overall container is dirty, clear it
if (_isDirty)
getSurface().clear();
// Iterate through each child and draw any dirty visual items
for (TreeItem *child = getFirstChild(); child; child = child->getNextSibling()) {
VisualItem *item = dynamic_cast<VisualItem *>(child);
if (item && item->isDirty())
item->draw();
}
_isDirty = false;
}
void VisualContainer::setDirty(bool dirty) {
for (TreeItem *child = getFirstChild(); child; child = child->getNextSibling()) {
VisualItem *item = dynamic_cast<VisualItem *>(child);
if (item)
item->setDirty(dirty);
}
VisualItem::setDirty(dirty);
}
bool VisualContainer::isDirty() const {
if (_isDirty)
return true;
for (TreeItem *child = getFirstChild(); child; child = child->getNextSibling()) {
VisualItem *item = dynamic_cast<VisualItem *>(child);
if (item && item->isDirty())
return true;
}
return false;
}
} // End of namespace Gfx
} // End of namespace Shared
} // End of namespace Ultima

View 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 ULTIMA_SHARED_GFX_VISUAL_CONTAINER_H
#define ULTIMA_SHARED_GFX_VISUAL_CONTAINER_H
#include "ultima/shared/gfx/visual_item.h"
#include "ultima/shared/core/message_target.h"
namespace Ultima {
namespace Shared {
namespace Gfx {
class VisualContainer : public VisualItem {
DECLARE_MESSAGE_MAP;
bool MouseButtonDownMsg(CMouseButtonDownMsg *msg);
bool MouseButtonUpMsg(CMouseButtonUpMsg *msg);
bool MouseMoveMsg(CMouseMoveMsg *msg);
bool MouseDoubleClickMsg(CMouseDoubleClickMsg *msg);
bool MouseWheelMsg(CMouseWheelMsg *msg);
bool MouseDragMsg(CMouseDragMsg *msg);
private:
VisualItem *_mouseFocusItem;
private:
/**
* Called to handle mouse messagaes on the view
*/
VisualItem *handleMouseMsg(CMouseMsg *msg);
public:
CLASSDEF;
VisualContainer(TreeItem *parent = nullptr) : VisualItem(parent), _mouseFocusItem(nullptr) {}
VisualContainer(const Rect &r, TreeItem *parent = nullptr) :
VisualItem(r, parent), _mouseFocusItem(nullptr) {}
VisualContainer(const Common::String &name, TreeItem *parent = nullptr) :
VisualItem(name, parent), _mouseFocusItem(nullptr) {}
VisualContainer(const Common::String &name, const Rect &r, TreeItem *parent = nullptr) :
VisualItem(name, r, parent), _mouseFocusItem(nullptr) {}
~VisualContainer() override {}
/**
* Draws the container by iterating through each child and letting it draw
*/
void draw() override;
/**
* Flags the item as being changed, requiring a redraw
*/
void setDirty(bool dirty = true) override;
/**
* Returns true if the item is dirty, requiring a redraw
*/
bool isDirty() const override;
};
} // End of namespace Gfx
} // End of namespace Shared
} // End of namespace Ultima
#endif

View File

@@ -0,0 +1,90 @@
/* 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/shared/gfx/visual_item.h"
#include "ultima/shared/early/ultima_early.h"
#include "ultima/shared/early/game.h"
namespace Ultima {
namespace Shared {
namespace Gfx {
BEGIN_MESSAGE_MAP(VisualItem, NamedItem)
ON_MESSAGE(ShowMsg)
ON_MESSAGE(HideMsg)
END_MESSAGE_MAP()
void VisualItem::init(TreeItem *parent) {
_isDirty = true;
if (parent != nullptr)
addUnder(parent);
}
bool VisualItem::ShowMsg(CShowMsg *msg) {
// When a view is shown, mark it to be redrawn
_isDirty = true;
// Font *font = Font::getActiveFont();
// _fontDetails._fontNumber = font ? font->_fontNumber : 1;
return false;
}
bool VisualItem::HideMsg(CHideMsg *msg) {
// When view is hidden, mark it as not dirty
_isDirty = false;
return false;
}
VisualSurface VisualItem::getSurface() {
Graphics::ManagedSurface src(*g_vm->_screen, _bounds);
return VisualSurface(src, _bounds, getGame());
}
void VisualItem::setBounds(const Rect &r) {
_bounds = r;
setDirty();
}
void VisualItem::setPosition(const Point &pt) {
_bounds.moveTo(pt);
setDirty();
}
void VisualItem::setDirty(bool dirty) {
// Flag the item as dirty
_isDirty = dirty;
}
void VisualItem::setView(const Common::String &viewName) {
getGame()->setView(viewName);
}
void VisualItem::setPopup(Gfx::Popup *popup) {
getGame()->setPopup(popup);
}
void VisualItem::setView() {
getGame()->setView(this);
}
} // End of namespace Gfx
} // End of namespace Shaerd
} // End of namespace Ultima

View 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/>.
*
*/
#ifndef ULTIMA_SHARED_GFX_VISUAL_ITEM_H
#define ULTIMA_SHARED_GFX_VISUAL_ITEM_H
#include "graphics/managed_surface.h"
#include "ultima/shared/core/named_item.h"
#include "ultima/shared/gfx/screen.h"
#include "ultima/shared/gfx/visual_surface.h"
namespace Ultima {
namespace Shared {
namespace Gfx {
class Popup;
/**
* Acts as the base class for all classes that have a visual representation on the screen
*/
class VisualItem : public NamedItem {
friend class VisualSurface;
DECLARE_MESSAGE_MAP;
bool ShowMsg(CShowMsg *msg);
bool HideMsg(CHideMsg *msg);
private:
/**
* Common initialization method used by the constructors
*/
void init(TreeItem *parent = nullptr);
protected:
Rect _bounds;
bool _isDirty;
public:
CLASSDEF;
VisualItem(TreeItem *parent = nullptr) { init(parent); }
VisualItem(const Rect &r, TreeItem *parent = nullptr) : _bounds(r) { init(parent); }
VisualItem(const Common::String &name, TreeItem *parent = nullptr) : NamedItem(name) { init(parent); }
VisualItem(const Common::String &name, const Rect &r, TreeItem *parent = nullptr) : NamedItem(name),
_bounds(r) { init(parent); }
~VisualItem() override {
}
/**
* Draws the visual item on the screen
*/
virtual void draw() {
_isDirty = false;
}
/**
* Gets a managed surface representing the portion of the screen defined by _bounds.
* This allows drawing to be done without worrying about offsets or clipping
*/
VisualSurface getSurface();
/**
* Gets the bounds for the item
*/
const Rect &getBounds() { return _bounds; }
/**
* Sets the bounds for the item
* @remarks Does not erase the item if it's already been drawn
*/
void setBounds(const Rect &r);
/**
* Set the position for the item
* @remarks Does not erase the item if it's already been drawn
*/
void setPosition(const Point &pt);
/**
* Flags the item as being changed, requiring a redraw
*/
virtual void setDirty(bool dirty = true);
/**
* Clears the dirty flag
*/
void clearDirty() { setDirty(false); }
/**
* Returns true if the item is dirty, requiring a redraw
*/
virtual bool isDirty() const { return _isDirty; }
/**
* Helper function to switch to a different visual item
*/
void setView(const Common::String &viewName);
/**
* Helper function to switch to an on-screen popup
*/
void setPopup(Gfx::Popup *popup);
/**
* Helper function to switch the item to be the current view
*/
void setView();
};
} // End of namespace Gfx
} // End of namespace Shared
} // End of namespace Ultima
#endif

View File

@@ -0,0 +1,72 @@
/* 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/shared/gfx/visual_surface.h"
#include "ultima/shared/early/ultima_early.h"
#include "ultima/shared/early/game.h"
#include "ultima/shared/gfx/font.h"
namespace Ultima {
namespace Shared {
namespace Gfx {
VisualSurface::VisualSurface(const Graphics::ManagedSurface &src, const Rect &bounds, GameBase *game) :
_bounds(bounds), _textColor(255), _bgColor(0) {
copyFrom(src);
Shared::Game *sharedGame = dynamic_cast<Shared::Game *>(game);
if (sharedGame) {
_textColor = sharedGame->_textColor;
_bgColor = sharedGame->_bgColor;
}
}
void VisualSurface::drawPoint(const Point &pt, byte color) {
fillRect(Rect(pt.x, pt.y, pt.x + 1, pt.y + 1), color);
}
void VisualSurface::writeString(const Common::String &msg, const Point &pt, int color, int bgColor) {
_textPos = pt;
writeString(msg, color == -1 ? _textColor : color, bgColor == -1 ? _bgColor : bgColor);
}
void VisualSurface::writeString(const Common::String &msg, int color, int bgColor) {
Gfx::Font *font = g_vm->_game->getFont();
font->writeString(*this, msg, _textPos, color == -1 ? _textColor : color, bgColor == -1 ? _bgColor : bgColor);
}
void VisualSurface::writeChar(unsigned char c, const Point &pt, int color, int bgColor) {
_textPos = pt;
writeChar(c, color == -1 ? _textColor : color, bgColor == -1 ? _bgColor : bgColor);
}
void VisualSurface::writeChar(unsigned char c, int color, int bgColor) {
Gfx::Font *font = g_vm->_game->getFont();
font->writeChar(*this, c, _textPos, color == -1 ? _textColor : color, bgColor == -1 ? _bgColor : bgColor);
}
size_t VisualSurface::fontHeight() {
Gfx::Font *font = g_vm->_game->getFont();
return font->lineHeight();
}
} // End of namespace Gfx
} // End of namespace Shared
} // End of namespace Ultima

View File

@@ -0,0 +1,91 @@
/* 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 ULTIMA_SHARED_GFX_VISUAL_SURFACE_H
#define ULTIMA_SHARED_GFX_VISUAL_SURFACE_H
#include "graphics/managed_surface.h"
#include "ultima/shared/core/named_item.h"
#include "ultima/shared/core/rect.h"
#include "ultima/shared/gfx/screen.h"
namespace Ultima {
namespace Shared {
class GameBase;
namespace Gfx {
class Font;
class VisualSurface : public Graphics::ManagedSurface {
private:
Rect _bounds;
Point _textPos;
byte _textColor;
byte _bgColor;
public:
/**
* Constructor
*/
VisualSurface(const Graphics::ManagedSurface &src, const Rect &bounds, GameBase *game = nullptr);
/**
* Draws a point on the surface
*/
void drawPoint(const Point &pt, byte color);
/**
* Set the position for writing text to
*/
void setTextPos(const Point &pt) { _textPos = pt; }
/**
* Write out a string
*/
void writeString(const Common::String &msg, const Point &pt, int color = -1, int bgColor = -1);
/**
* Write out a string
*/
void writeString(const Common::String &msg, int color = -1, int bgColor = -1);
/**
* Draw a character
*/
void writeChar(unsigned char c, const Point &pt, int color = -1, int bgColor = -1);
/**
* Draw a character
*/
void writeChar(unsigned char c, int color = -1, int bgColor = -1);
/**
* Get the current font height
*/
size_t fontHeight();
};
} // End of namespace Gfx
} // End of namespace Shared
} // End of namespace Ultima
#endif