Files
scummvm-cursorfix/engines/stark/ui/menu/locationscreen.cpp
2026-02-02 04:50:13 +01:00

269 lines
6.6 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 "engines/stark/ui/menu/locationscreen.h"
#include "engines/stark/gfx/driver.h"
#include "engines/stark/services/services.h"
#include "engines/stark/services/staticprovider.h"
#include "engines/stark/resources/item.h"
#include "engines/stark/resources/location.h"
#include "engines/stark/resources/sound.h"
#include "engines/stark/ui/cursor.h"
#include "engines/stark/visual/text.h"
#include "audio/mixer.h"
#include "common/system.h"
namespace Stark {
StaticLocationScreen::StaticLocationScreen(Gfx::Driver *gfx, Cursor *cursor,
const char *locationName, Screen::Name screenName) :
SingleWindowScreen(screenName, gfx, cursor),
_locationName(locationName),
_location(nullptr),
_hoveredWidgetIndex(-1) {
_position = Common::Rect(Gfx::Driver::kOriginalWidth, Gfx::Driver::kOriginalHeight);
_visible = true;
}
StaticLocationScreen::~StaticLocationScreen() {
freeWidgets();
}
void StaticLocationScreen::open() {
_location = StarkStaticProvider->loadLocation(_locationName);
}
void StaticLocationScreen::close() {
freeWidgets();
StarkStaticProvider->unloadLocation(_location);
_location = nullptr;
}
void StaticLocationScreen::freeWidgets() {
for (uint i = 0; i < _widgets.size(); i++) {
delete _widgets[i];
}
_widgets.clear();
_hoveredWidgetIndex = -1;
}
void StaticLocationScreen::onGameLoop() {
for (uint i = 0; i < _widgets.size(); i++) {
StaticLocationWidget *widget = _widgets[i];
if (widget->isVisible()) {
widget->onGameLoop();
}
}
}
void StaticLocationScreen::onMouseMove(const Common::Point &pos) {
int newHoveredWidget = -1;
for (uint i = 0; i < _widgets.size(); i++) {
StaticLocationWidget *widget = _widgets[i];
widget->onMouseMove(pos);
if (widget->isVisible() && widget->isMouseInside(pos)) {
newHoveredWidget = i;
}
}
// The first widget is always the background. It is ignored below.
if (newHoveredWidget != _hoveredWidgetIndex) {
if (_hoveredWidgetIndex > 0 && uint(_hoveredWidgetIndex) < _widgets.size()) {
_widgets[_hoveredWidgetIndex]->onMouseLeave();
}
if (newHoveredWidget > 0) {
_widgets[newHoveredWidget]->onMouseEnter();
}
_hoveredWidgetIndex = newHoveredWidget;
}
_cursor->setCursorType(_hoveredWidgetIndex > 0 ? Cursor::kActive : Cursor::kDefault);
}
void StaticLocationScreen::onClick(const Common::Point &pos) {
for (uint i = 1; i < _widgets.size(); i++) {
StaticLocationWidget *widget = _widgets[i];
if (widget->isVisible() && widget->isMouseInside(pos)) {
widget->onClick();
break;
}
}
}
void StaticLocationScreen::onRender() {
for (uint i = 0; i < _widgets.size(); i++) {
if (_widgets[i]->isVisible()) {
_widgets[i]->render();
}
}
}
void StaticLocationScreen::onScreenChanged() {
for (uint i = 0; i < _widgets.size(); i++) {
_widgets[i]->onScreenChanged();
}
}
void StaticLocationScreen::waitForSoundsToComplete() {
while (g_system->getMixer()->hasActiveChannelOfType(Audio::Mixer::kSFXSoundType)) {
StarkGfx->clearScreen();
g_system->delayMillis(10);
StarkGfx->flipBuffer();
}
}
StaticLocationWidget::StaticLocationWidget(const char *renderEntryName, WidgetOnClickCallback *onClickCallback,
WidgetOnMouseMoveCallback *onMouseMoveCallback):
_onClick(onClickCallback),
_onMouseMove(onMouseMoveCallback),
_renderEntry(nullptr),
_item(nullptr),
_soundMouseEnter(nullptr),
_soundMouseClick(nullptr),
_visible(true) {
if (renderEntryName) {
Resources::Location *location = StarkStaticProvider->getLocation();
_renderEntry = location->getRenderEntryByName(renderEntryName);
if (_renderEntry == nullptr) {
debug("Widget disabled: unable to find render entry with name '%s' in location '%s'",
renderEntryName, location->getName().c_str());
setVisible(false);
} else {
_item = _renderEntry->getOwner();
}
}
}
void StaticLocationWidget::render() {
if (_renderEntry) {
_renderEntry->render();
}
}
bool StaticLocationWidget::isVisible() const {
return _visible;
}
void StaticLocationWidget::setVisible(bool visible) {
_visible = visible;
}
bool StaticLocationWidget::isMouseInside(const Common::Point &mousePos) const {
if (!_renderEntry) return false;
Common::Point relativePosition;
return _renderEntry->containsPoint(mousePos, relativePosition, Common::Rect());
}
void StaticLocationWidget::onClick() {
onMouseLeave();
if (_soundMouseClick) {
_soundMouseClick->play();
_soundMouseClick->setStopOnDestroy(false);
}
if (_onClick) {
(*_onClick)();
}
}
void StaticLocationWidget::onGameLoop() {
if (_item) {
_item->onGameLoop();
}
}
void StaticLocationWidget::onMouseEnter() {
if (_soundMouseEnter && !_soundMouseEnter->isPlaying()) {
_soundMouseEnter->play();
}
}
void StaticLocationWidget::onMouseLeave() {
if (_soundMouseEnter) {
_soundMouseEnter->stop();
}
}
void StaticLocationWidget::setupSounds(int16 enterSound, int16 clickSound) {
if (enterSound != -1) {
_soundMouseEnter = StarkStaticProvider->getLocationSound(enterSound);
}
if (clickSound != -1) {
_soundMouseClick = StarkStaticProvider->getLocationSound(clickSound);
}
}
void StaticLocationWidget::setTextColor(const Gfx::Color &textColor) {
if (!_renderEntry) return;
VisualText *text = _renderEntry->getText();
assert(text);
text->setColor(textColor);
}
void StaticLocationWidget::onScreenChanged() {
if (!_renderEntry) return;
VisualText *text = _renderEntry->getText();
if (text) {
text->reset();
}
}
void StaticLocationWidget::onMouseMove(const Common::Point &mousePos) {
if (_onMouseMove) {
(*_onMouseMove)(*this, mousePos);
}
}
Common::Point StaticLocationWidget::getPosition() const {
if (_renderEntry) {
return _renderEntry->getPosition();
}
return Common::Point(0, 0);
}
StaticLocationWidget::~StaticLocationWidget() {
delete _onClick;
delete _onMouseMove;
}
} // End of namespace Stark