Files
2026-02-02 04:50:13 +01:00

180 lines
4.7 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 "mm/mm1/views_enh/interactions/interaction.h"
#include "mm/mm1/globals.h"
#include "mm/mm1/mm1.h"
#include "mm/mm1/sound.h"
#include "mm/shared/utils/strings.h"
namespace MM {
namespace MM1 {
namespace ViewsEnh {
namespace Interactions {
#define BTN_SIZE 10
Interaction::Interaction(const Common::String &name, int portrait) : PartyView(name) {
_bounds = Common::Rect(8, 8, 224, 140);
if (portrait != -1) {
_frame.load("frame.fac");
_portrait.load(Common::Path(Common::String::format("face%02d.fac", portrait)));
}
}
void Interaction::addText(const Common::String &str) {
setReduced(false);
_lines = splitLines(searchAndReplace(str, "\n", " "));
}
bool Interaction::msgGame(const GameMessage &msg) {
if (msg._name == "DISPLAY") {
addView(this);
return true;
}
return PartyView::msgGame(msg);
}
bool Interaction::msgUnfocus(const UnfocusMessage &msg) {
PartyView::msgUnfocus(msg);
return true;
}
void Interaction::draw() {
PartyView::draw();
Graphics::ManagedSurface s = getSurface();
if (!_frame.empty()) {
_frame.draw(&s, 0, Common::Point(8, 8));
_portrait.draw(&s, _portraitFrameNum, Common::Point(15, 14));
}
setReduced(false);
if (!_title.empty()) {
size_t strWidth = getStringWidth(_title);
writeString(125 - strWidth / 2, 20, _title);
}
// Write any text lines
for (uint i = 0; i < _lines.size(); ++i) {
writeString(0, (6 + i) * 9 - 5, _lines[i], ALIGN_MIDDLE);
}
// Write out any buttons
if (!_buttons.empty()) {
_textPos = Common::Point(0, (6 + _lines.size()) * 9);
setReduced(true);
// Create a blank button
Graphics::ManagedSurface btnSmall(BTN_SIZE, BTN_SIZE);
btnSmall.blitFrom(g_globals->_blankButton, Common::Rect(0, 0, 20, 20),
Common::Rect(0, 0, BTN_SIZE, BTN_SIZE));
for (uint i = 0; i < _buttons.size(); ++i, _textPos.x += 10) {
InteractionButton &btn = _buttons[i];
int itemWidth = BTN_SIZE + 5 + getStringWidth(_buttons[i]._text);
if ((_textPos.x + itemWidth) > _innerBounds.width()) {
_textPos.x = 0;
_textPos.y += BTN_SIZE + 2;
}
Common::Point pt = _textPos;
// Display button and write character in the middle
s.blitFrom(btnSmall, Common::Point(pt.x + _bounds.borderSize(),
pt.y + _bounds.borderSize()));
writeString(pt.x + (BTN_SIZE / 2) + 1, pt.y,
Common::String::format("%c", _buttons[i]._c), ALIGN_MIDDLE);
// Write text to the right of the button
writeString(pt.x + BTN_SIZE + 5, pt.y, _buttons[i]._text);
// Set up bounds for the area covered by the button & text
btn._bounds = Common::Rect(pt.x, pt.y,
pt.x + BTN_SIZE + 5 + itemWidth, pt.y + BTN_SIZE);
btn._bounds.translate(_innerBounds.left, _innerBounds.top);
}
}
}
bool Interaction::tick() {
if (_animated && ++_tickCtr >= 10) {
_tickCtr = 0;
_portraitFrameNum = g_engine->getRandomNumber(0, 2);
redraw();
}
return PartyView::tick();
}
void Interaction::leave() {
if (g_events->focusedView() == this)
close();
g_maps->turnAround();
g_events->redraw();
}
bool Interaction::msgKeypress(const KeypressMessage &msg) {
viewAction();
return true;
}
bool Interaction::msgAction(const ActionMessage &msg) {
if (msg._action == KEYBIND_ESCAPE) {
leave();
} else if (!PartyView::msgAction(msg)) {
viewAction();
}
return true;
}
bool Interaction::msgMouseDown(const MouseDownMessage &msg) {
if (!PartyView::msgMouseDown(msg)) {
// Check if a button was pressed
for (uint i = 0; i < _buttons.size(); ++i) {
const auto &btn = _buttons[i];
if (_buttons[i]._bounds.contains(msg._pos)) {
msgKeypress(KeypressMessage(Common::KeyState(
(Common::KeyCode)(Common::KEYCODE_a + btn._c - 'A'), btn._c
)));
return true;
}
}
// Fall back on treating click as a standard acknowledgement
viewAction();
}
return true;
}
} // namespace Interactions
} // namespace ViewsEnh
} // namespace MM1
} // namespace MM