Files
scummvm-cursorfix/engines/illusions/bbdou/bbdou_credits.cpp
2026-02-02 04:50:13 +01:00

245 lines
6.4 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 "illusions/bbdou/illusions_bbdou.h"
#include "illusions/bbdou/bbdou_credits.h"
#include "illusions/actor.h"
#include "illusions/dictionary.h"
#include "illusions/textdrawer.h"
#include "illusions/time.h"
#include "illusions/resources/scriptresource.h"
namespace Illusions {
BbdouCredits::BbdouCredits(IllusionsEngine_BBDOU *vm)
: _vm(vm) {
}
BbdouCredits::~BbdouCredits() {
}
void BbdouCredits::start(uint32 endSignalPropertyId, float speedModifier) {
_endSignalPropertyId = endSignalPropertyId;
_currFontId = 0x120004;
_currLineIndex = 1;
_split = false;
// convertTextData();
initCreditsItems();
createCreditsThread(speedModifier);
}
void BbdouCredits::stop() {
freeCreditsItems();
}
void BbdouCredits::drawNextLine() {
uint leftIndex, rightIndex;
if (!readNextLine(leftIndex, rightIndex)) {
_vm->_scriptResource->_properties.set(_endSignalPropertyId, true);
return;
}
if (leftIndex) {
const char *leftText = getText(leftIndex);
if (leftText && strlen(leftText) != 0) {
uint32 objectId = getNextFreeObjectId();
int alignment = rightIndex ? 1 : 2;
drawTextToControl(objectId, leftText, alignment);
}
}
if (rightIndex) {
const char *rightText = getText(rightIndex);
if (rightText && strlen(rightText) != 0) {
uint32 objectId = getNextFreeObjectId();
drawTextToControl(objectId, rightText, 4);
}
}
}
void charToWChar(const char *text, uint16 *wtext, uint size) {
while (*text != 0 && size > 1) {
*wtext++ = (byte)*text++;
/*
byte c = (byte)*text++;
if (c > 127) c = 32;
*wtext = c;
debug("%04X", *wtext);
++wtext;
*/
--size;
}
*wtext++ = 0;
}
void BbdouCredits::drawTextToControl(uint32 objectId, const char *text, uint alignment) {
uint16 wtext[128];
charToWChar(text, wtext, ARRAYSIZE(wtext));
Control *control = _vm->getObjectControl(objectId);
FontResource *font = _vm->_dict->findFont(_currFontId);
TextDrawer textDrawer;
WidthHeight dimensions;
uint16 *outText;
control->getActorFrameDimensions(dimensions);
control->fillActor(0);
textDrawer.wrapText(font, wtext, &dimensions, Common::Point(0, 0), alignment, outText);
textDrawer.drawText(_vm->_screen, control->_actor->_surface, 0, 0);
control->_actor->_flags |= Illusions::ACTOR_FLAG_4000;
}
bool BbdouCredits::readNextLine(uint &leftIndex, uint &rightIndex) {
bool done = false;
int textLines = 0;
leftIndex = 0;
rightIndex = 0;
do {
uint lineIndex = _currLineIndex++;
const char *text = getText(lineIndex);
if (text[0] == '@') {
const char *command = text + 1;
if (!strcmp(command, "end"))
done = true;
if (!strcmp(command, "bold"))
_currFontId = 0x120005;
else if (!strcmp(command, "normal"))
_currFontId = 0x120004;
else if (!strcmp(command, "center"))
_split = false;
else if (!strcmp(command, "split"))
_split = true;
else
done = true;
} else {
++textLines;
if (!_split) {
leftIndex = lineIndex;
done = true;
} else if (textLines > 1) {
rightIndex = lineIndex;
done = true;
} else {
leftIndex = lineIndex;
}
}
} while (!done);
return textLines > 0;
}
void BbdouCredits::initCreditsItems() {
for (uint i = 0; i < kCreditsItemsCount; ++i) {
uint32 objectId = _vm->_controls->newTempObjectId();
_vm->_controls->placeActor(0x00050188, Common::Point(320, 480), 0x00060BE1, objectId, 0);
Control *control = _vm->_dict->getObjectControl(objectId);
control->startSequenceActor(0x60BE2, 2, 0);
_items[i].isUsed = false;
_items[i].objectId = objectId;
}
}
void BbdouCredits::freeCreditsItems() {
for (uint i = 0; i < kCreditsItemsCount; ++i) {
Control *control = _vm->_dict->getObjectControl(_items[i].objectId);
control->disappearActor();
}
}
uint32 BbdouCredits::getNextFreeObjectId() {
for (uint i = 0; i < kCreditsItemsCount; ++i) {
if (!_items[i].isUsed) {
_items[i].isUsed = true;
return _items[i].objectId;
}
}
return 0;
}
void BbdouCredits::removeText(uint32 objectId) {
for (uint i = 0; i < kCreditsItemsCount; ++i) {
if (_items[i].objectId == objectId) {
_items[i].isUsed = false;
resetObjectPos(objectId);
}
}
}
void BbdouCredits::resetObjectPos(uint32 objectId) {
Control *control = _vm->_dict->getObjectControl(objectId);
control->setActorPosition(Common::Point(320, 480));
}
void BbdouCredits::createCreditsThread(float speedModifier) {
uint32 tempThreadId = _vm->newTempThreadId();
CreditsThread *creditsThread = new CreditsThread(_vm, this, tempThreadId, speedModifier);
_vm->_threads->startThread(creditsThread);
}
void BbdouCredits::updateTexts(int yIncr) {
for (uint i = 0; i < kCreditsItemsCount; ++i) {
if (_items[i].isUsed) {
Control *control = _vm->_dict->getObjectControl(_items[i].objectId);
Common::Point pt = control->getActorPosition();
pt.y += yIncr;
control->setActorPosition(pt);
if (pt.y <= 0)
removeText(_items[i].objectId);
}
}
}
// CreditsThread
CreditsThread::CreditsThread(IllusionsEngine_BBDOU *vm, BbdouCredits *credits, uint32 threadId, float speedModifier)
: Thread(vm, threadId, 0, 0), _speedModifier(speedModifier), _lastFraction(0.0), _credits(credits) {
_type = kTTSpecialThread;
_lastUpdateTime = getCurrentTime();
}
int CreditsThread::onUpdate() {
uint32 currTime = getCurrentTime();
float fltDelta = (currTime - _lastUpdateTime) * _speedModifier + _lastFraction;
int delta = (int)fltDelta;
_lastFraction = fltDelta - delta;
if (delta != 0)
_credits->updateTexts(-delta);
_lastUpdateTime = currTime;
return 2;
}
void CreditsThread::onNotify() {
_lastUpdateTime = getCurrentTime();
}
void CreditsThread::onResume() {
onNotify();
}
void CreditsThread::onTerminated() {
_credits->stop();
}
} // End of namespace Illusions