mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-14 05:38:56 +00:00
573 lines
17 KiB
C++
573 lines
17 KiB
C++
/* ScummVM - Graphic Adventure Engine
|
|
*
|
|
* ScummVM is the legal property of its developers, whose names
|
|
* are too numerous to list here. Please refer to the COPYRIGHT
|
|
* file distributed with this source distribution.
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
*/
|
|
|
|
#include "mohawk/cstime_game.h" // debugging..
|
|
#include "mohawk/cstime_ui.h"
|
|
#include "mohawk/cstime_view.h"
|
|
#include "mohawk/resource.h"
|
|
#include "mohawk/cursors.h"
|
|
|
|
#include "common/events.h"
|
|
#include "common/system.h"
|
|
#include "common/textconsole.h"
|
|
|
|
namespace Mohawk {
|
|
|
|
CSTimeView::CSTimeView(MohawkEngine_CSTime *vm) : View(vm) {
|
|
_timeVm = vm;
|
|
_gfx = vm->_gfx;
|
|
_bitmapCursorId = 0;
|
|
}
|
|
|
|
uint32 CSTimeView::getTime() {
|
|
return _vm->_system->getMillis();
|
|
}
|
|
|
|
void CSTimeView::setupView() {
|
|
_rootNode = new NewFeature(this);
|
|
_cursorNode = new NewFeature(this);
|
|
_rootNode->setNodeDefaults(nullptr, _cursorNode);
|
|
_rootNode->_id = 1; // TODO: 10 in new?
|
|
_rootNode->_data.enabled = 0;
|
|
_rootNode->_flags = kFeatureSortBackground;
|
|
_rootNode->_moveProc = nullptr;
|
|
_rootNode->_drawProc = nullptr;
|
|
_rootNode->_timeProc = nullptr;
|
|
_cursorNode->setNodeDefaults(_rootNode, nullptr);
|
|
_cursorNode->_id = 0xffff; // TODO: 1 in new?
|
|
_cursorNode->_data.enabled = 0;
|
|
_cursorNode->_flags = kFeatureOldSortForeground; // TODO: 0x4000 in new..
|
|
_cursorNode->_moveProc = (Module::FeatureProc)&CSTimeModule::cursorMoveProc;
|
|
_cursorNode->_drawProc = (Module::FeatureProc)&CSTimeModule::cursorDrawProc;
|
|
_cursorNode->_timeProc = nullptr;
|
|
}
|
|
|
|
Feature *CSTimeView::installViewFeature(uint16 scrbId, uint32 flags, Common::Point *pos) {
|
|
Feature *node = _rootNode;
|
|
// FIXME: find the right node to insert under
|
|
while (node) {
|
|
if (node->_next && (node->_next->_id == 0xffff || ((flags & 0x8000) && !(node->_next->_flags & 0x8000))))
|
|
break;
|
|
node = node->_next;
|
|
}
|
|
if (!node)
|
|
error("failed to install view feature");
|
|
|
|
NewFeature *feature = new NewFeature(this);
|
|
feature->setNodeDefaults(node, node->_next);
|
|
|
|
feature->_moveProc = (Module::FeatureProc)&CSTimeModule::defaultMoveProc;
|
|
feature->_drawProc = (Module::FeatureProc)&CSTimeModule::defaultDrawProc;
|
|
feature->_timeProc = (Module::BooleanProc)&CSTimeModule::defaultTimeProc;
|
|
feature->_pickupProc = (Module::PickupProc)&CSTimeModule::defaultPickupProc;
|
|
feature->_dropProc = (Module::FeatureProc)&CSTimeModule::defaultDropProc;
|
|
feature->_dragMoveProc = (Module::FeatureProc)&CSTimeModule::defaultDragMoveProc;
|
|
feature->_oldMoveProc = nullptr;
|
|
feature->_dragFlags = 0x8000;
|
|
|
|
feature->_id = getNewFeatureId();
|
|
node->_next = feature;
|
|
feature->_next->_prev = feature;
|
|
if (pos) {
|
|
feature->_data.currentPos = *pos;
|
|
feature->_unknown168 = 1;
|
|
} else {
|
|
feature->_data.currentPos = Common::Point();
|
|
feature->_unknown168 = 0x7FFFFFFF;
|
|
}
|
|
feature->_data.nextPos = Common::Point();
|
|
feature->_scrbId = scrbId;
|
|
feature->_flags = flags;
|
|
feature->_delayTime = 100;
|
|
return feature;
|
|
}
|
|
|
|
void CSTimeView::installGroup(uint16 resourceId, uint size, uint count, bool regs, uint16 baseId) {
|
|
// TODO: make sure this is in sync!
|
|
assert(_numSCRBGroups < 14);
|
|
installFeatureShapes(regs, _numSCRBGroups, resourceId);
|
|
if (baseId == 0xffff)
|
|
baseId = resourceId;
|
|
_SCRBGroupResources[_numSCRBGroups] = resourceId; // TODO: Meh. This needs some rethinking.
|
|
installGroupOfSCRBs(false, baseId, size, count);
|
|
}
|
|
|
|
void CSTimeView::removeGroup(uint16 resourceId) {
|
|
// FIXME: deal with zero resourceId
|
|
if (resourceId == 0)
|
|
error("removeGroup got zero resourceId");
|
|
|
|
uint16 groupId = getGroupFromBaseId(resourceId);
|
|
if (groupId == 0xffff)
|
|
return;
|
|
|
|
removeObjectsUsingBaseId(resourceId);
|
|
freeShapesUsingResourceId(resourceId);
|
|
freeScriptsUsingResourceId(resourceId);
|
|
// adjustShapeGroups(groupId); - TODO: unnecessary?
|
|
}
|
|
|
|
void CSTimeView::removeObjectsUsingBaseId(uint16 baseId) {
|
|
uint16 groupId = getGroupFromBaseId(baseId);
|
|
|
|
Feature *node = _rootNode->_next;
|
|
while (node->_next) {
|
|
Feature *curr = node;
|
|
node = node->_next;
|
|
if (curr->_data.compoundSHAPIndex == groupId) {
|
|
removeFeature(curr, true);
|
|
}
|
|
}
|
|
}
|
|
|
|
void CSTimeView::freeShapesUsingResourceId(uint16 resourceId) {
|
|
// TODO: Meh. This needs some rethinking.
|
|
for (int i = _numSCRBGroups - 1; i >= 0; i--) {
|
|
if (_SCRBGroupResources[i] != resourceId)
|
|
continue;
|
|
for (uint j = i; j < 13; j++)
|
|
_compoundSHAPGroups[j] = _compoundSHAPGroups[j + 1];
|
|
_compoundSHAPGroups[13] = 0;
|
|
// TODO: deal with REGS
|
|
}
|
|
}
|
|
|
|
void CSTimeView::freeScriptsUsingResourceId(uint16 resourceId) {
|
|
// TODO: Meh. This needs some rethinking.
|
|
for (int i = _numSCRBGroups - 1; i >= 0; i--) {
|
|
if (_SCRBGroupResources[i] == resourceId)
|
|
groupFreeScript(i);
|
|
}
|
|
}
|
|
|
|
void CSTimeView::groupFreeScript(uint index) {
|
|
uint count = _SCRBGroupSizes[index];
|
|
_numSCRBGroups--;
|
|
for (uint i = index; i < _numSCRBGroups; i++) {
|
|
_SCRBGroupBases[i] = _SCRBGroupBases[i + 1];
|
|
_SCRBGroupSizes[i] = _SCRBGroupSizes[i + 1];
|
|
_SCRBGroupResources[i] = _SCRBGroupResources[i + 1]; // TODO: Meh. This needs some rethinking.
|
|
}
|
|
uint base = 0;
|
|
for (uint i = 0; i < index; i++)
|
|
base += _SCRBGroupSizes[i];
|
|
for (uint i = 0; i < count; i++)
|
|
_SCRBEntries.remove_at(base);
|
|
// TODO: kill any actual scripts
|
|
groupAdjustView(index, count);
|
|
}
|
|
|
|
void CSTimeView::groupAdjustView(uint index, uint count) {
|
|
for (Feature *node = _rootNode->_next; node->_next; node = node->_next) {
|
|
if (node->_data.compoundSHAPIndex < index)
|
|
continue;
|
|
node->_data.compoundSHAPIndex--;
|
|
node->_data.scrbIndex -= count;
|
|
}
|
|
}
|
|
|
|
void CSTimeView::loadBitmapCursors(uint16 baseId) {
|
|
// TODO
|
|
}
|
|
|
|
void CSTimeView::setBitmapCursor(uint16 id) {
|
|
if (_bitmapCursorId == id)
|
|
return;
|
|
|
|
if (!id) {
|
|
_vm->_cursor->showCursor();
|
|
} else {
|
|
_vm->_cursor->hideCursor();
|
|
}
|
|
|
|
_bitmapCursorId = id;
|
|
}
|
|
|
|
void CSTimeView::dragFeature(NewFeature *feature, Common::Point pos, uint mode, uint32 flags, Common::Rect *rect) {
|
|
feature->_data.hidden = 0;
|
|
|
|
if (mode == 2) {
|
|
if (feature->_dragFlags & 0x800000) {
|
|
feature->_dragFlags = flags | 0x8000;
|
|
if (!(flags & 1))
|
|
(_currentModule->*(feature->_dropProc))(feature);
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (feature->_dragFlags & 0x800000)
|
|
(_currentModule->*(feature->_dropProc))(feature);
|
|
else
|
|
(_currentModule->*(feature->_pickupProc))(feature, pos, flags, rect);
|
|
}
|
|
|
|
void CSTimeView::finishDraw() {
|
|
// TODO: This is a kinda stupid hack, here just for debugging.
|
|
((MohawkEngine_CSTime *)_vm)->getCase()->getCurrScene()->drawHotspots();
|
|
}
|
|
|
|
CSTimeModule::CSTimeModule(MohawkEngine_CSTime *vm) : _vm(vm) {
|
|
}
|
|
|
|
void CSTimeModule::defaultMoveProc(Feature *feature) {
|
|
if (feature->_data.paused > 0)
|
|
return;
|
|
|
|
if (!feature->_data.enabled)
|
|
return;
|
|
|
|
if (feature->_timeProc && !(this->*(feature->_timeProc))(feature))
|
|
return;
|
|
|
|
if (feature->_needsReset) {
|
|
feature->resetFeatureScript(1, feature->_scrbId);
|
|
if ((feature->_flags & kFeatureNewDisable) || (feature->_flags & kFeatureNewDisableOnReset)) {
|
|
feature->_data.enabled = 0;
|
|
}
|
|
feature->_dirty = true;
|
|
if (feature->_flags & kFeatureInternalRegion) {
|
|
// TODO: create region [+140] (if not already done)
|
|
}
|
|
} else {
|
|
if (!(feature->_flags & kFeatureNewClip)) {
|
|
if (feature->_data.useClipRect) {
|
|
// TODO: or clip with _unknown228
|
|
} else if (feature->_region) {
|
|
// TODO: or clip with region
|
|
} else {
|
|
// TODO: or clip with bounds
|
|
}
|
|
}
|
|
feature->_dirty = true;
|
|
if (feature->_flags & kFeatureNewInternalTiming) {
|
|
feature->_nextTime += feature->_delayTime;
|
|
} else {
|
|
feature->_nextTime = _vm->getView()->_lastIdleTime + feature->_delayTime;
|
|
}
|
|
if (feature->_done) {
|
|
if (feature->_flags & kFeatureNewNoLoop) {
|
|
// FIXME: sync channel reset
|
|
uint16 unknown184 = 1, unknown186 = 1; // FIXME: XXX
|
|
if (feature->_flags & kFeatureDisableOnEnd || (unknown184 != 0 && unknown186 != 0)) { // FIXME: XXX
|
|
feature->_data.enabled = 0;
|
|
if (feature->_doneProc) {
|
|
(this->*(feature->_doneProc))(feature); // TODO: with -2
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
feature->_data.currOffset = 26;
|
|
feature->_done = false;
|
|
}
|
|
if (feature->_flags & kFeatureNewDisable)
|
|
feature->_data.enabled = 0;
|
|
}
|
|
|
|
int xOffset = feature->_data.currentPos.x + feature->_data.nextPos.x;
|
|
int yOffset = feature->_data.currentPos.y + feature->_data.nextPos.y;
|
|
|
|
Common::SeekableReadStream *ourSCRB = _vm->getView()->getSCRB(feature->_data.scrbIndex);
|
|
ourSCRB->seek(feature->_data.currOffset);
|
|
|
|
bool setBitmap = false;
|
|
uint bitmapId = 0;
|
|
bool done = false;
|
|
while (!done) {
|
|
byte opcode = ourSCRB->readByte();
|
|
byte size = ourSCRB->readByte();
|
|
switch (opcode) {
|
|
case 1:
|
|
ourSCRB->skip(size - 2);
|
|
opcode = ourSCRB->readByte();
|
|
size = ourSCRB->readByte();
|
|
if (opcode != 0) {
|
|
ourSCRB->seek(-2, SEEK_CUR);
|
|
done = true;
|
|
break;
|
|
}
|
|
// fall through
|
|
// FIXME: Unclear if fall through is intentional...
|
|
case 0:
|
|
// TODO: set ptr +176 to 1
|
|
feature->_done = true;
|
|
if (feature->_doneProc) {
|
|
(this->*(feature->_doneProc))(feature); // TODO: with -1
|
|
}
|
|
done = true;
|
|
break;
|
|
|
|
case 3:
|
|
{
|
|
int32 pos = ourSCRB->pos();
|
|
ourSCRB->seek(2);
|
|
uint16 base = ourSCRB->readUint16BE();
|
|
ourSCRB->seek(pos);
|
|
base += ourSCRB->readUint16BE();
|
|
if (base) {
|
|
// FIXME: sound?
|
|
}
|
|
ourSCRB->skip(size - 4);
|
|
}
|
|
warning("saw feature opcode 0x3 (size %d)", size);
|
|
break;
|
|
|
|
case 4:
|
|
// FIXME
|
|
if (false /* TODO: !+72 */) {
|
|
ourSCRB->skip(size - 2);
|
|
} else {
|
|
uint16 time = ourSCRB->readUint16BE();
|
|
// FIXME: not right
|
|
feature->_delayTime = time;
|
|
ourSCRB->skip(size - 4);
|
|
}
|
|
warning("saw feature opcode 0x4 (size %d)", size);
|
|
break;
|
|
|
|
case 9:
|
|
// FIXME
|
|
ourSCRB->skip(size - 2);
|
|
warning("ignoring feature opcode 0x9 (size %d)", size);
|
|
break;
|
|
|
|
case 0xf:
|
|
// FIXME
|
|
ourSCRB->skip(size - 2);
|
|
warning("ignoring feature opcode 0xf (size %d)", size);
|
|
break;
|
|
|
|
case 0x10:
|
|
while (bitmapId < 48) {
|
|
if (!size)
|
|
break;
|
|
size--;
|
|
feature->_data.bitmapIds[bitmapId] = ourSCRB->readUint16BE() & 0xFFF;
|
|
feature->_data.bitmapPos[bitmapId].x = ourSCRB->readUint16BE() + xOffset;
|
|
feature->_data.bitmapPos[bitmapId].y = ourSCRB->readUint16BE() + yOffset;
|
|
bitmapId++;
|
|
}
|
|
feature->_data.bitmapIds[bitmapId] = 0;
|
|
setBitmap = true;
|
|
break;
|
|
|
|
default:
|
|
warning("unknown new feature opcode %d", opcode);
|
|
ourSCRB->skip(size - 2);
|
|
break;
|
|
}
|
|
}
|
|
|
|
feature->_data.currOffset = ourSCRB->pos();
|
|
if (!setBitmap) {
|
|
// TODO: set fail flag
|
|
return;
|
|
}
|
|
if (feature->_frameProc) {
|
|
(this->*(feature->_frameProc))(feature);
|
|
}
|
|
// TODO: set palette if needed
|
|
|
|
// TODO: adjust for regs if needed
|
|
Common::Array<int16> regsX, regsY;
|
|
Common::SeekableReadStream *regsStream;
|
|
uint16 compoundSHAPIndex = _vm->getView()->getCompoundSHAPId(feature->_data.compoundSHAPIndex);
|
|
regsStream = _vm->getResource(ID_REGS, compoundSHAPIndex);
|
|
while (regsStream->pos() != regsStream->size())
|
|
regsX.push_back(regsStream->readSint16BE());
|
|
delete regsStream;
|
|
regsStream = _vm->getResource(ID_REGS, compoundSHAPIndex + 1);
|
|
while (regsStream->pos() != regsStream->size())
|
|
regsY.push_back(regsStream->readSint16BE());
|
|
delete regsStream;
|
|
for (uint i = 0; i < 48; i++) {
|
|
uint16 thisBitmapId = feature->_data.bitmapIds[i];
|
|
if (!thisBitmapId)
|
|
break;
|
|
feature->_data.bitmapPos[i].x -= regsX[thisBitmapId];
|
|
feature->_data.bitmapPos[i].y -= regsY[thisBitmapId];
|
|
}
|
|
|
|
// TODO: set bounds
|
|
// TODO: unset fail flag
|
|
}
|
|
|
|
void CSTimeModule::defaultDrawProc(Feature *feature) {
|
|
if (feature->_data.hidden > 0)
|
|
return;
|
|
|
|
feature->defaultDraw();
|
|
}
|
|
|
|
bool CSTimeModule::defaultTimeProc(Feature *feature) {
|
|
return (feature->_nextTime <= _vm->getView()->getTime());
|
|
}
|
|
|
|
void CSTimeModule::defaultPickupProc(NewFeature *feature, Common::Point pos, uint32 flags, Common::Rect *rect) {
|
|
_vm->getView()->removeFeature(feature, false);
|
|
|
|
feature->_dragFlags |= flags | 0x800000;
|
|
feature->_oldFlags = feature->_flags;
|
|
feature->_data.useClipRect = 0;
|
|
// TODO: these flags are weird/different
|
|
feature->_flags = (feature->_flags & ~kFeatureSortBackground) | kFeatureOldSortForeground | kFeatureSortStatic | 0x2000;
|
|
_vm->getView()->insertUnderCursor(feature);
|
|
|
|
feature->_nextTime = 0;
|
|
// FIXME: preserve old delayTime (see also script op 4)
|
|
feature->_delayTime = 50;
|
|
|
|
feature->_oldPos = feature->_data.currentPos;
|
|
|
|
feature->_posDiff.x = pos.x - feature->_data.currentPos.x;
|
|
feature->_posDiff.y = pos.y - feature->_data.currentPos.y;
|
|
debug("defaultPickupProc: diff is %d, %d", feature->_posDiff.x, feature->_posDiff.y);
|
|
|
|
feature->_oldMoveProc = feature->_moveProc;
|
|
feature->_moveProc = feature->_dragMoveProc;
|
|
|
|
// FIXME: deal with rect
|
|
if (rect)
|
|
error("defaultPickupProc doesn't handle rect yet");
|
|
}
|
|
|
|
void CSTimeModule::defaultDropProc(NewFeature *feature) {
|
|
// FIXME: invalidation
|
|
|
|
feature->_flags = feature->_oldFlags;
|
|
// FIXME: restore old delayTime
|
|
feature->_dragFlags &= ~0x800000;
|
|
|
|
if (feature->_dragFlags & 0x800)
|
|
feature->moveAndUpdate(feature->_oldPos);
|
|
if (feature->_dragFlags & 0x200)
|
|
feature->hide(true);
|
|
feature->_moveProc = feature->_oldMoveProc;
|
|
}
|
|
|
|
void CSTimeModule::defaultDragMoveProc(NewFeature *feature) {
|
|
// FIXME
|
|
|
|
if (feature->_dragFlags & 0x8000)
|
|
feature->_currDragPos = _vm->getEventManager()->getMousePos();
|
|
|
|
Common::Point pos = feature->_currDragPos;
|
|
pos.x -= feature->_posDiff.x;
|
|
pos.y -= feature->_posDiff.y;
|
|
|
|
if (feature->_dragFlags & 0x80) {
|
|
// FIXME: handle 0x80 case
|
|
error("encountered 0x80 case in defaultDragMoveProc");
|
|
}
|
|
|
|
feature->moveAndUpdate(pos);
|
|
|
|
(this->*(feature->_oldMoveProc))(feature);
|
|
}
|
|
|
|
void CSTimeModule::cursorMoveProc(Feature *feature) {
|
|
uint16 cursor = _vm->getView()->getBitmapCursor();
|
|
if (!cursor)
|
|
return;
|
|
|
|
Common::Point pos = _vm->getEventManager()->getMousePos();
|
|
|
|
// FIXME: shouldn't be hardcoded
|
|
uint16 compoundSHAPIndex = 200;
|
|
// FIXME: stupid REGS stuff..
|
|
Common::SeekableReadStream *regsStream = _vm->getResource(ID_REGS, compoundSHAPIndex);
|
|
regsStream->seek(cursor * 2);
|
|
feature->_data.bounds.left = pos.x - regsStream->readSint16BE();
|
|
delete regsStream;
|
|
regsStream = _vm->getResource(ID_REGS, compoundSHAPIndex + 1);
|
|
regsStream->seek(cursor * 2);
|
|
feature->_data.bounds.top = pos.y - regsStream->readSint16BE();
|
|
delete regsStream;
|
|
}
|
|
|
|
void CSTimeModule::cursorDrawProc(Feature *feature) {
|
|
uint16 cursor = _vm->getView()->getBitmapCursor();
|
|
if (!cursor)
|
|
return;
|
|
// FIXME: shouldn't be hardcoded
|
|
uint16 compoundSHAPIndex = 200;
|
|
_vm->getView()->getGfx()->copyAnimSubImageToScreen(compoundSHAPIndex, cursor - 1, feature->_data.bounds.left, feature->_data.bounds.top);
|
|
}
|
|
|
|
void CSTimeModule::rolloverTextMoveProc(Feature *feature) {
|
|
// Should OR the whole bounds into the dirty region, if the text changed.
|
|
}
|
|
|
|
void CSTimeModule::rolloverTextDrawProc(Feature *feature) {
|
|
// TODO: if timeBook->getState() is 2, return
|
|
const Common::String &text = _vm->getInterface()->getRolloverText();
|
|
if (!text.empty()) {
|
|
Common::Rect &rect = feature->_data.bounds;
|
|
Graphics::Surface *screen = g_system->lockScreen();
|
|
_vm->getInterface()->getRolloverFont().drawString(screen, text, rect.left, rect.top, rect.width(), 32, Graphics::kTextAlignCenter);
|
|
g_system->unlockScreen();
|
|
}
|
|
// TODO: some special case about dragging in case 1, scene 4 (torch?)
|
|
// TODO: unset text changed flag
|
|
}
|
|
|
|
void CSTimeModule::dialogTextMoveProc(Feature *feature) {
|
|
// FIXME
|
|
}
|
|
|
|
void CSTimeModule::dialogTextDrawProc(Feature *feature) {
|
|
const Common::Array<Common::String> &lines = _vm->getInterface()->getDialogLines();
|
|
const Common::Array<byte> &colors = _vm->getInterface()->getDialogLineColors();
|
|
const Common::Rect &bounds = feature->_data.bounds;
|
|
const Graphics::Font &font = _vm->getInterface()->getDialogFont();
|
|
|
|
Graphics::Surface *screen = _vm->_system->lockScreen();
|
|
for (uint i = 0; i < lines.size(); i++)
|
|
font.drawString(screen, lines[i], bounds.left, bounds.top + 1 + i*15, bounds.width(), colors[i], Graphics::kTextAlignCenter);
|
|
_vm->_system->unlockScreen();
|
|
// FIXME
|
|
}
|
|
|
|
void CSTimeModule::bubbleTextMoveProc(Feature *feature) {
|
|
// FIXME
|
|
}
|
|
|
|
void CSTimeModule::bubbleTextDrawProc(Feature *feature) {
|
|
Common::Rect bounds = feature->_data.bounds;
|
|
bounds.grow(-5);
|
|
const Graphics::Font &font = _vm->getInterface()->getDialogFont();
|
|
uint height = font.getFontHeight();
|
|
|
|
Common::Array<Common::String> lines;
|
|
font.wordWrapText(_vm->getInterface()->getCurrBubbleText(), bounds.width(), lines);
|
|
|
|
Graphics::Surface *screen = _vm->_system->lockScreen();
|
|
for (int x = -2; x < 2; x++)
|
|
for (int y = -1; y < 3; y++)
|
|
for (uint i = 0; i < lines.size(); i++)
|
|
font.drawString(screen, lines[i], bounds.left + x, bounds.top + y + i*height, bounds.width(), 241, Graphics::kTextAlignCenter);
|
|
for (uint i = 0; i < lines.size(); i++)
|
|
font.drawString(screen, lines[i], bounds.left, bounds.top + i*height, bounds.width(), 32, Graphics::kTextAlignCenter);
|
|
_vm->_system->unlockScreen();
|
|
}
|
|
|
|
} // End of namespace Mohawk
|