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,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 "engines/nancy/nancy.h"
#include "engines/nancy/resource.h"
#include "engines/nancy/graphics.h"
#include "engines/nancy/sound.h"
#include "engines/nancy/input.h"
#include "engines/nancy/cursor.h"
#include "engines/nancy/util.h"
#include "engines/nancy/state/credits.h"
#include "common/events.h"
#include "common/config-manager.h"
namespace Common {
DECLARE_SINGLETON(Nancy::State::Credits);
}
namespace Nancy {
namespace State {
void Credits::process() {
switch (_state) {
case kInit:
init();
// fall through
case kRun:
run();
break;
}
}
void Credits::onStateEnter(const NancyState::NancyState prevState) {
// Handle returning from the GMM
if (prevState == NancyState::kPause) {
g_nancy->_sound->pauseSound(_creditsData->sound, false);
}
}
bool Credits::onStateExit(const NancyState::NancyState nextState) {
// Handle the GMM being called
if (nextState == NancyState::kPause) {
g_nancy->_sound->pauseSound(_creditsData->sound, true);
return false;
} else {
return true;
}
}
void Credits::init() {
_creditsData = GetEngineData(CRED);
assert(_creditsData);
_background.init(_creditsData->imageName);
_textSurface.moveTo(_creditsData->textScreenPosition);
drawTextSurface(0);
_textSurface._drawSurface.create(_fullTextSurface, _textSurface.getBounds());
_textSurface.init();
g_nancy->_sound->stopSound("MSND");
g_nancy->_sound->loadSound(_creditsData->sound);
g_nancy->_sound->playSound(_creditsData->sound);
_background.registerGraphics();
_textSurface.registerGraphics();
g_nancy->setMouseEnabled(false);
_state = kRun;
}
void Credits::run() {
NancyInput input = g_nancy->_input->getInput();
if (input.input & NancyInput::kLeftMouseButtonDown) {
_state = kInit;
g_nancy->_sound->stopSound(_creditsData->sound);
g_nancy->setMouseEnabled(true);
_fullTextSurface.free();
if (!ConfMan.hasKey("original_menus") || ConfMan.getBool("original_menus")) {
g_nancy->setState(NancyState::kMainMenu);
return;
}
Common::Event ev;
ev.type = Common::EVENT_RETURN_TO_LAUNCHER;
g_system->getEventManager()->pushEvent(ev);
return;
}
Time currentTime = g_nancy->getTotalPlayTime();
if (currentTime >= _nextUpdateTime) {
_nextUpdateTime = currentTime + _creditsData->updateTime;
Common::Rect newSrc = _textSurface.getScreenPosition();
newSrc.moveTo(_textSurface._drawSurface.getOffsetFromOwner());
newSrc.translate(0, _creditsData->pixelsToScroll);
if (newSrc.bottom > _fullTextSurface.h) {
newSrc.moveTo(Common::Point());
if (_creditsData->textNames.size() > 1) {
drawTextSurface(_currentTextImage == _creditsData->textNames.size() - 1 ? 0 : _currentTextImage + 1);
}
}
_textSurface._drawSurface.create(_fullTextSurface, newSrc);
_textSurface.setVisible(true);
}
}
void Credits::drawTextSurface(uint id) {
Graphics::ManagedSurface image;
uint surfaceHeight = _textSurface.getBounds().height();
g_nancy->_resource->loadImage(_creditsData->textNames[id], image);
_fullTextSurface.create(image.w, image.h + (surfaceHeight * 2), g_nancy->_graphics->getInputPixelFormat());
_fullTextSurface.setTransparentColor(g_nancy->_graphics->getTransColor());
_fullTextSurface.clear(_fullTextSurface.getTransparentColor());
_fullTextSurface.blitFrom(image, Common::Point(0, surfaceHeight));
if (image.hasPalette()) {
uint8 palette[256 * 3];
image.grabPalette(palette, 0, 256);
_fullTextSurface.setPalette(palette, 0, 256);
}
_currentTextImage = id;
}
} // End of namespace State
} // End of namespace Nancy

View File

@@ -0,0 +1,69 @@
/* 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 NANCY_STATE_CREDITS_H
#define NANCY_STATE_CREDITS_H
#include "common/singleton.h"
#include "engines/nancy/time.h"
#include "engines/nancy/commontypes.h"
#include "engines/nancy/state/state.h"
#include "engines/nancy/ui/fullscreenimage.h"
namespace Nancy {
namespace State {
class Credits : public State, public Common::Singleton<Credits> {
public:
enum State { kInit, kRun };
Credits() : _state(kInit), _background(), _textSurface(1), _currentTextImage(0), _creditsData(nullptr) {}
// State API
void process() override;
void onStateEnter(const NancyState::NancyState prevState) override;
bool onStateExit(const NancyState::NancyState nextState) override;
protected:
void init();
void run();
void drawTextSurface(uint id);
const CRED *_creditsData;
State _state;
UI::FullScreenImage _background;
RenderObject _textSurface;
Time _nextUpdateTime;
Graphics::ManagedSurface _fullTextSurface;
uint _currentTextImage;
};
#define NancyCreditsState Nancy::State::Credits::instance()
} // End of namespace State
} // End of namespace Nancy
#endif // NANCY_STATE_CREDITS_H

View File

@@ -0,0 +1,123 @@
/* 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/nancy/nancy.h"
#include "engines/nancy/sound.h"
#include "engines/nancy/input.h"
#include "engines/nancy/cursor.h"
#include "engines/nancy/util.h"
#include "engines/nancy/state/help.h"
#include "engines/nancy/ui/button.h"
namespace Common {
DECLARE_SINGLETON(Nancy::State::Help);
}
namespace Nancy {
namespace State {
void Help::process() {
switch (_state) {
case kInit:
init();
// fall through
case kBegin:
begin();
// fall through
case kRun:
run();
break;
case kWait:
wait();
break;
}
}
void Help::onStateEnter(const NancyState::NancyState prevState) {
if (prevState == NancyState::kPause) {
g_nancy->_sound->pauseSound("MSND", false);
}
}
bool Help::onStateExit(const NancyState::NancyState nextState) {
// Handle the GMM being called
if (nextState == NancyState::kPause) {
g_nancy->_sound->pauseSound("MSND", true);
return false;
} else {
return true;
}
}
void Help::init() {
auto *helpData = GetEngineData(HELP);
assert(helpData);
_image.init(helpData->imageName);
_button.reset(new UI::Button(5, _image._drawSurface, helpData->buttonSrc, helpData->buttonDest, helpData->buttonHoverSrc));
_button->init();
_state = kBegin;
}
void Help::begin() {
if (!g_nancy->_sound->isSoundPlaying("MSND")) {
g_nancy->_sound->playSound("MSND");
}
_image.registerGraphics();
_button->registerGraphics();
_image.setVisible(true);
g_nancy->_cursor->setCursorType(CursorManager::kNormalArrow);
_state = kRun;
}
void Help::run() {
NancyInput input = g_nancy->_input->getInput();
_button->handleInput(input);
if (_button->_isClicked) {
auto *bootSummary = GetEngineData(BSUM);
assert(bootSummary);
_button->_isClicked = false;
g_nancy->_sound->playSound("BUOK");
_buttonPressActivationTime = g_system->getMillis() + bootSummary->buttonPressTimeDelay;
_state = kWait;
}
g_nancy->_cursor->setCursorType(CursorManager::kNormalArrow);
}
void Help::wait() {
if (g_system->getMillis() > _buttonPressActivationTime) {
g_nancy->setToPreviousState();
}
}
} // End of namespace State
} // End of namespace Nancy

View File

@@ -0,0 +1,67 @@
/* 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 NANCY_STATE_HELP_H
#define NANCY_STATE_HELP_H
#include "common/ptr.h"
#include "common/singleton.h"
#include "engines/nancy/commontypes.h"
#include "engines/nancy/time.h"
#include "engines/nancy/state/state.h"
#include "engines/nancy/ui/fullscreenimage.h"
namespace Nancy {
namespace UI {
class Button;
}
namespace State {
class Help : public State, public Common::Singleton<Help> {
public:
enum State { kInit, kBegin, kRun, kWait };
// State API
void process() override;
void onStateEnter(const NancyState::NancyState prevState) override;
bool onStateExit(const NancyState::NancyState nextState) override;
private:
void init();
void begin();
void run();
void wait();
State _state = kInit;
UI::FullScreenImage _image;
Common::ScopedPtr<UI::Button> _button;
Time _buttonPressActivationTime;
};
#define NancyHelpState Nancy::State::Help::instance()
} // End of namespace State
} // End of namespace Nancy
#endif // NANCY_STATE_HELP_H

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,166 @@
/* 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 NANCY_STATE_LOADSAVE_H
#define NANCY_STATE_LOADSAVE_H
#include "common/singleton.h"
#include "common/ptr.h"
#include "engines/nancy/state/state.h"
#include "engines/nancy/ui/fullscreenimage.h"
#include "engines/nancy/ui/button.h"
#include "engines/nancy/font.h"
namespace Nancy {
struct LOAD;
namespace State {
class LoadSaveMenu : public State, public Common::Singleton<LoadSaveMenu> {
public:
virtual ~LoadSaveMenu();
protected:
enum State { kInit, kRun, kEnterFilename, kSave, kLoad, kSuccess, kStop };
LoadSaveMenu() :
_blinkingCursorOverlay(6),
_successOverlay(8) {};
virtual void init() = 0;
virtual void run() = 0;
virtual void enterFilename();
virtual bool save();
virtual void load();
virtual void success();
virtual void stop();
virtual int scummVMSaveSlotToLoad() const = 0;
virtual void registerGraphics();
virtual uint16 writeToTextbox(int textboxID, const Common::String &text, const Font *font);
void scummVMSave();
void scummVMLoad();
// State API
void process() override;
void onStateEnter(const NancyState::NancyState prevState) override;
bool onStateExit(const NancyState::NancyState nextState) override;
const Font *_baseFont = nullptr;
const Font *_highlightFont = nullptr;
const Font *_disabledFont = nullptr;
State _state = kInit;
bool _enteringNewState = true;
bool _destroyOnExit = true;
const LOAD *_loadSaveData = nullptr;
int16 _selectedSave = -1;
RenderObject *_textboxReceivingInput = nullptr;
// UI elements common to both menus
Common::Array<Common::ScopedPtr<RenderObject>> _textboxes;
Common::ScopedPtr<UI::Button> _exitButton;
RenderObject _blinkingCursorOverlay;
RenderObject _successOverlay;
uint32 _nextBlink = 0;
Common::String _enteredString;
};
class LoadSaveMenu_V1 : public LoadSaveMenu {
private:
void init() override;
void run() override;
void enterFilename() override;
bool save() override;
virtual int scummVMSaveSlotToLoad() const override;
void registerGraphics() override;
UI::FullScreenImage _background;
Common::Array<Common::String> _filenameStrings;
Common::Array<bool> _saveExists;
Common::Array<Common::ScopedPtr<UI::Button>> _loadButtons;
Common::Array<Common::ScopedPtr<UI::Button>> _saveButtons;
Common::Array<Common::ScopedPtr<RenderObject>> _cancelButtonOverlays;
Common::ScopedPtr<UI::Button> _cancelButton;
};
class LoadSaveMenu_V2 : public LoadSaveMenu {
private:
void init() override;
void run() override;
void enterFilename() override;
bool save() override;
void success() override;
virtual int scummVMSaveSlotToLoad() const override;
void registerGraphics() override;
uint16 writeToTextbox(int textboxID, const Common::String &text, const Font *font) override;
uint16 writeToInputTextbox(const Font *font);
void filterAndSortSaveStates();
void extractSaveNames(uint pageID);
void goToPage(uint pageID);
void reloadSaves();
void setConfig();
UI::FullScreenImage _background1;
UI::FullScreenImage _background2;
Graphics::ManagedSurface _buttonsImage;
Common::Array<Common::String> _filenameStrings;
Common::Array<bool> _saveExists;
Common::ScopedPtr<RenderObject> _inputTextbox;
Common::ScopedPtr<UI::Button> _loadButton;
Common::ScopedPtr<UI::Button> _saveButton;
Common::ScopedPtr<UI::Button> _pageUpButton;
Common::ScopedPtr<UI::Button> _pageDownButton;
int16 _hoveredSave = -1;
uint _currentPage = 0;
SaveStateList _sortedSavesList;
};
} // End of namespace State
} // End of namespace Nancy
namespace Common {
template<>
Nancy::State::LoadSaveMenu *Singleton<Nancy::State::LoadSaveMenu>::makeInstance();
} // End of namespace Common
#endif // NANCY_STATE_LOADSAVE_H

View File

@@ -0,0 +1,167 @@
/* 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 "common/config-manager.h"
#include "engines/nancy/nancy.h"
#include "engines/nancy/sound.h"
#include "engines/nancy/input.h"
#include "engines/nancy/graphics.h"
#include "engines/nancy/state/logo.h"
namespace Common {
DECLARE_SINGLETON(Nancy::State::Logo);
}
namespace Nancy {
namespace State {
void Logo::process() {
switch (_state) {
case kInit:
init();
break;
case kPlayIntroVideo:
playIntroVideo();
break;
case kStartSound:
startSound();
break;
case kRun:
run();
break;
case kStop:
stop();
}
}
void Logo::onStateEnter(const NancyState::NancyState prevState) {
// Handle returning from the GMM
if (prevState == NancyState::kPause) {
if (_state == kPlayIntroVideo) {
_tvdVideoDecoder.pauseVideo(false);
} else if (_state == kRun) {
g_nancy->_sound->pauseSound("MSND", false);
}
}
}
bool Logo::onStateExit(const NancyState::NancyState nextState) {
// Handle the GMM being called
if (nextState == NancyState::kPause) {
if (_state == kPlayIntroVideo) {
_tvdVideoDecoder.pauseVideo(true);
} else if (_state == kRun) {
g_nancy->_sound->pauseSound("MSND", true);
}
return false;
} else {
return true;
}
}
void Logo::init() {
const ImageChunk *lg0 = (const ImageChunk *)g_nancy->getEngineData("LG0");
const ImageChunk *plg0 = (const ImageChunk *)g_nancy->getEngineData("PLG0");
if (!plg0) {
plg0 = (const ImageChunk *)g_nancy->getEngineData("PLGO");
}
assert(lg0);
_logoImage.init(lg0->imageName);
_logoImage.registerGraphics();
if (plg0) {
_partnerLogoImage.init(plg0->imageName);
_partnerLogoImage.registerGraphics();
}
if (g_nancy->getGameType() == kGameTypeVampire && _tvdVideoDecoder.loadFile("VAMPINTR.AVI")) {
_tvdVideoDecoder.start();
_videoObj.moveTo(Common::Rect(0, 0, 640, 480));
_videoObj._drawSurface.create(_tvdVideoDecoder.getWidth(), _tvdVideoDecoder.getHeight(), _tvdVideoDecoder.getPixelFormat());
_videoObj.setPalette(_tvdVideoDecoder.getPalette());
_videoObj.registerGraphics();
_videoObj.setVisible(true);
_state = kPlayIntroVideo;
} else {
_state = kStartSound;
}
}
// The Vampire Diaries originally shipped with a launcher that could either start the game
// or play an introduction video. We don't bother giving the player a choice, and just
// play the video before the game logo
void Logo::playIntroVideo() {
if (_tvdVideoDecoder.needsUpdate()) {
const Graphics::Surface *frame = _tvdVideoDecoder.decodeNextFrame();
if (frame) {
_videoObj._drawSurface.blitFrom(*frame);
_videoObj.setVisible(true);
}
}
if (_tvdVideoDecoder.endOfVideo() || (g_nancy->_input->getInput().input & NancyInput::kLeftMouseButtonDown)) {
_state = kStartSound;
_videoObj.setVisible(false);
_tvdVideoDecoder.close();
}
}
void Logo::startSound() {
g_nancy->_sound->playSound("MSND");
_startTicks = g_nancy->getTotalPlayTime();
_state = kRun;
}
void Logo::run() {
if (g_nancy->getTotalPlayTime() - _startTicks >= g_nancy->getStaticData().logoEndAfter) {
// Display game logo after partner logo
if (!_partnerLogoImage._drawSurface.empty() && _partnerLogoImage.isVisible()) {
_logoImage.setVisible(true);
_partnerLogoImage.setVisible(false);
_startTicks = g_nancy->getTotalPlayTime();
} else {
_state = kStop;
}
}
if (g_nancy->_input->getInput().input & NancyInput::kLeftMouseButtonDown) {
_state = kStop;
}
}
void Logo::stop() {
// The original engine checks for N+D and N+C key combos here.
// For the N+C key combo it looks for some kind of cheat file
// to initialize the game state with.
if (!ConfMan.hasKey("original_menus") || ConfMan.getBool("original_menus")) {
g_nancy->setState(NancyState::kMainMenu);
} else {
g_nancy->setState(NancyState::kScene);
}
}
} // End of namespace State
} // End of namespace Nancy

View File

@@ -0,0 +1,74 @@
/* 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 NANCY_STATE_LOGO_H
#define NANCY_STATE_LOGO_H
#include "common/singleton.h"
#include "video/avi_decoder.h"
#include "engines/nancy/commontypes.h"
#include "engines/nancy/state/state.h"
#include "engines/nancy/ui/fullscreenimage.h"
namespace Nancy {
namespace State {
class Logo : public State, public Common::Singleton<Logo> {
public:
Logo() : _state(kInit), _startTicks(0), _videoObj(1) { }
// State API
void process() override;
void onStateEnter(const NancyState::NancyState prevState) override;
bool onStateExit(const NancyState::NancyState nextState) override;
private:
void init();
void playIntroVideo();
void startSound();
void run();
void stop();
enum State {
kInit,
kPlayIntroVideo,
kStartSound,
kRun,
kStop
};
State _state;
uint _startTicks;
UI::FullScreenImage _logoImage;
UI::FullScreenImage _partnerLogoImage;
SoundDescription _msnd;
Video::AVIDecoder _tvdVideoDecoder;
RenderObject _videoObj;
};
#define NancyLogoState Nancy::State::Logo::instance()
} // end of namespace State
} // End of namespace Nancy
#endif // NANCY_STATE_LOGO_H

View File

@@ -0,0 +1,278 @@
/* 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/nancy/nancy.h"
#include "engines/nancy/cursor.h"
#include "engines/nancy/sound.h"
#include "engines/nancy/input.h"
#include "engines/nancy/util.h"
#include "engines/nancy/graphics.h"
#include "engines/nancy/state/mainmenu.h"
#include "engines/nancy/state/scene.h"
#include "engines/nancy/ui/button.h"
#include "common/config-manager.h"
namespace Common {
DECLARE_SINGLETON(Nancy::State::MainMenu);
}
namespace Nancy {
namespace State {
void MainMenu::process() {
switch (_state) {
case kInit:
init();
// fall through
case kRun:
run();
break;
case kStop:
stop();
break;
}
}
void MainMenu::onStateEnter(const NancyState::NancyState prevState) {
registerGraphics();
}
bool MainMenu::onStateExit(const NancyState::NancyState nextState) {
return _destroyOnExit;
}
void MainMenu::registerGraphics() {
_background.registerGraphics();
for (auto &button : _buttons) {
button->registerGraphics();
}
g_nancy->_graphics->redrawAll();
}
void MainMenu::clearButtonState() {
for (auto &button : _buttons) {
button->_isClicked = false;
}
}
void MainMenu::init() {
_menuData = GetEngineData(MENU);
assert(_menuData);
_background.init(_menuData->_imageName);
_background.registerGraphics();
g_nancy->_cursor->setCursorType(CursorManager::kNormalArrow);
g_nancy->setMouseEnabled(true);
if (!g_nancy->_sound->isSoundPlaying("MSND")) {
g_nancy->_sound->playSound("MSND");
}
_buttons.resize(_menuData->_buttonDests.size());
for (uint i = 0; i < _menuData->_buttonDests.size(); ++i) {
_buttons[i].reset(new UI::Button(5, _background._drawSurface,
_menuData->_buttonDownSrcs[i], _menuData->_buttonDests[i],
_menuData->_buttonHighlightSrcs.size() ? _menuData->_buttonHighlightSrcs[i] : Common::Rect(),
_menuData->_buttonDisabledSrcs.size() ? _menuData->_buttonDisabledSrcs[i] : Common::Rect()));
_buttons[i]->init();
_buttons[i]->setVisible(false);
}
registerGraphics();
// Disable continue if game was just started
// Perhaps could be enabled always, and just load the latest save?
if (!Scene::hasInstance()) {
_buttons[3]->setDisabled(true);
} else {
if (NancySceneState.isRunningAd()) {
// Always destroy current state to make sure music starts again
NancySceneState.destroy();
if (ConfMan.hasKey("restore_after_ad", Common::ConfigManager::kTransientDomain)) {
// Returning to running game, restore second chance
ConfMan.setInt("save_slot", g_nancy->getMetaEngine()->getMaximumSaveSlot(), Common::ConfigManager::kTransientDomain);
} else {
// Not returning to running game, disable Continue button
_buttons[3]->setDisabled(true);
}
}
}
_state = kRun;
}
void MainMenu::run() {
NancyInput input = g_nancy->_input->getInput();
if (_selected != -1) {
input.input &= ~NancyInput::kLeftMouseButtonUp;
}
for (uint i = 0; i < _buttons.size(); ++i) {
auto &button = _buttons[i];
button->handleInput(input);
if (_selected == -1 && button->_isClicked) {
if (button->_isDisabled) {
g_nancy->_sound->playSound("BUDE");
} else {
g_nancy->_sound->playSound("BUOK");
}
_selected = i;
}
}
if (_selected != -1) {
if (!g_nancy->_sound->isSoundPlaying("BUOK") && !g_nancy->_sound->isSoundPlaying("BUDE")) {
if (_buttons[_selected]->_isDisabled) {
_selected = -1;
clearButtonState();
} else {
_state = kStop;
}
}
}
g_nancy->_cursor->setCursorType(CursorManager::kNormalArrow);
}
void MainMenu::stop() {
switch (_selected) {
case 0:
// Credits
g_nancy->setState(NancyState::kCredits);
break;
case 1:
// New Game
if (Scene::hasInstance()) {
NancySceneState.destroy(); // Destroy the existing Scene and create a new one
}
g_nancy->setState(NancyState::kScene);
break;
case 2:
// Load and Save Game, TODO
g_nancy->setState(NancyState::kLoadSave);
break;
case 3:
// Continue
g_nancy->setState(NancyState::kScene);
break;
case 4:
// Second Chance
if (Scene::hasInstance()) {
NancySceneState.destroy(); // Destroy the existing Scene and create a new one
}
ConfMan.setInt("save_slot", g_nancy->getMetaEngine()->getMaximumSaveSlot(), Common::ConfigManager::kTransientDomain);
g_nancy->setState(NancyState::kScene);
break;
case 5:
// Game Setup
g_nancy->setState(NancyState::kSetup);
break;
case 6:
// Exit Game
if (g_nancy->getEngineData("SDLG") && Nancy::State::Scene::hasInstance() && !g_nancy->_hasJustSaved) {
if (!ConfMan.hasKey("sdlg_return", Common::ConfigManager::kTransientDomain)) {
// Request the "Do you want to save before quitting" dialog
ConfMan.setInt("sdlg_id", 0, Common::ConfigManager::kTransientDomain);
_destroyOnExit = false;
g_nancy->setState(NancyState::kSaveDialog);
} else {
// Dialog has returned
_destroyOnExit = true;
g_nancy->_graphics->suppressNextDraw();
uint ret = ConfMan.getInt("sdlg_return", Common::ConfigManager::kTransientDomain);
ConfMan.removeKey("sdlg_return", Common::ConfigManager::kTransientDomain);
switch (ret) {
case 0 :
// "Yes" switches to LoadSave
g_nancy->setState(NancyState::kLoadSave);
if (!ConfMan.getBool("originalsaveload")) {
ConfMan.setBool("sdlg_save_and_quit", true, Common::ConfigManager::kTransientDomain);
}
break;
case 1 :
// "No" quits the game
g_nancy->quitGame();
// fall through
case 2 :
// "Cancel" keeps us in the main menu
_selected = -1;
for (uint i = 0; i < _buttons.size(); ++i) {
_buttons[i]->_isClicked = false;
}
_state = kRun;
break;
default:
break;
}
}
} else {
// Earlier games had no "Do you want to save before quitting" dialog, directly quit
g_nancy->quitGame();
// Fallback for when the ScummVM "Ask for confirmation on exit" option is enabled, and
// the player clicks cancel
_selected = -1;
for (uint i = 0; i < _buttons.size(); ++i) {
_buttons[i]->_isClicked = false;
}
_state = kRun;
break;
}
break;
case 7:
// Help
g_nancy->setState(NancyState::kHelp);
break;
case 8:
// More Nancy Drew!
if (Scene::hasInstance()) {
// The second chance slot is used as temporary save. We make sure not to
// overwrite it when selecting the ad button multiple times in a row.
if (!ConfMan.hasKey("restore_after_ad", Common::ConfigManager::kTransientDomain)) {
g_nancy->secondChance();
}
ConfMan.setBool("restore_after_ad", true, Common::ConfigManager::kTransientDomain);
NancySceneState.destroy();
}
ConfMan.setBool("load_ad", true, Common::ConfigManager::kTransientDomain);
g_nancy->setState(NancyState::kScene);
break;
}
}
} // End of namespace State
} // End of namespace Nancy

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 NANCY_STATE_MAINMENU_H
#define NANCY_STATE_MAINMENU_H
#include "common/ptr.h"
#include "common/singleton.h"
#include "engines/nancy/state/state.h"
#include "engines/nancy/ui/fullscreenimage.h"
namespace Nancy {
struct MENU;
namespace UI {
class Button;
}
namespace State {
class MainMenu : public State, public Common::Singleton<MainMenu> {
public:
MainMenu() : _state(kInit), _selected(-1), _menuData(nullptr) {}
// State API
void process() override;
void onStateEnter(const NancyState::NancyState prevState) override;
bool onStateExit(const NancyState::NancyState nextState) override;
private:
void init();
void run();
void stop();
void registerGraphics();
void clearButtonState();
enum State { kInit, kRun, kStop };
UI::FullScreenImage _background;
State _state;
int16 _selected;
Common::Array<Common::ScopedPtr<UI::Button>> _buttons;
bool _destroyOnExit = true;
const MENU *_menuData;
};
} // End of namespace State
} // End of namespace Nancy
#endif // NANCY_STATE_MAINMENU_H

469
engines/nancy/state/map.cpp Normal file
View File

@@ -0,0 +1,469 @@
/* 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/nancy/nancy.h"
#include "engines/nancy/sound.h"
#include "engines/nancy/input.h"
#include "engines/nancy/cursor.h"
#include "engines/nancy/graphics.h"
#include "engines/nancy/util.h"
#include "engines/nancy/state/map.h"
#include "engines/nancy/state/scene.h"
#include "engines/nancy/ui/button.h"
namespace Common {
DECLARE_SINGLETON(Nancy::State::Map);
template<>
Nancy::State::Map *Singleton<Nancy::State::Map>::makeInstance() {
if (Nancy::g_nancy->getGameType() == Nancy::kGameTypeVampire) {
return new Nancy::State::TVDMap();
} else {
return new Nancy::State::Nancy1Map();
}
}
}
namespace Nancy {
namespace State {
Map::Map() : _state(kInit),
_mapID(0),
_pickedLocationID(-1),
_label(7),
_closedLabel(7),
_background(0) {
_mapData = GetEngineData(MAP);
assert(_mapData);
}
void Map::process() {
switch (_state) {
case kInit:
init();
// fall through
case kLoad:
load();
// fall through
case kRun:
run();
break;
case kExit:
g_nancy->setState(NancyState::kScene);
break;
}
}
void Map::onStateEnter(const NancyState::NancyState prevState) {
// Unpause sound and video when coming back from the GMM
if (prevState == NancyState::kPause) {
g_nancy->_sound->pauseSound(getSound(), false);
if (_viewport._decoder.getFrameCount() > 1) {
_viewport._decoder.pauseVideo(false);
}
}
}
bool Map::onStateExit(const NancyState::NancyState nextState) {
// Only pause when going to the GMM
if (nextState == NancyState::kPause) {
g_nancy->_sound->pauseSound(getSound(), true);
if (_viewport._decoder.getFrameCount() > 1) {
_viewport._decoder.pauseVideo(true);
}
} else {
g_nancy->_graphics->clearObjects();
_viewport.unloadVideo();
_state = kLoad;
}
return false;
}
const SoundDescription &Map::getSound() {
return _mapData->sounds[_mapID];
}
void Map::load() {
// Get a screenshot of the Scene state and set it as the background
// to allow the labels to clear when not hovered
const Graphics::ManagedSurface *screen = g_nancy->_graphics->getScreen();
_background._drawSurface.create(screen->w, screen->h, screen->format);
_background._drawSurface.blitFrom(*screen);
_background.moveTo(_background._drawSurface.getBounds());
_background.setVisible(true);
// The clock may become invisible after the map is opened, resulting in the left half appearing still open
// This is a slightly hacky solution but it works
if (g_nancy->getGameType() == kGameTypeVampire) {
Common::Rect r(52, 100);
_background._drawSurface.blitFrom(NancySceneState.getFrame()._drawSurface, r, r);
}
}
void Map::registerGraphics() {
_background.registerGraphics();
_viewport.registerGraphics();
_label.registerGraphics();
_closedLabel.registerGraphics();
}
void Map::setLabel(int labelID) {
if (labelID == -1) {
_label.setVisible(false);
_closedLabel.setVisible(false);
} else {
_label.moveTo(_locationLabelDests[labelID]);
_label._drawSurface.create(g_nancy->_graphics->_object0, _mapData->locations[labelID].labelSrc);
_label.setVisible(true);
_label.setTransparent(true);
if (!_activeLocations[labelID]) {
_closedLabel.setVisible(true);
}
}
}
void Map::MapViewport::init() {
auto *viewportData = GetEngineData(VIEW);
assert(viewportData);
moveTo(viewportData->screenPosition);
_drawSurface.create(_screenPosition.width(), _screenPosition.height(), g_nancy->_graphics->getInputPixelFormat());
RenderObject::init();
}
void Map::MapViewport::updateGraphics() {
if (_decoder.getFrameCount() > 1) {
if (_decoder.endOfVideo()) {
_decoder.rewind();
}
if (_decoder.needsUpdate()) {
GraphicsManager::copyToManaged(*_decoder.decodeNextFrame(), _drawSurface, g_nancy->getGameType() == kGameTypeVampire);
_needsRedraw = true;
}
}
}
void Map::MapViewport::loadVideo(const Common::Path &filename, const Common::Path &palette) {
if (_decoder.isVideoLoaded()) {
_decoder.close();
}
if (!_decoder.loadFile(filename.append(".avf"))) {
error("Couldn't load video file %s", filename.toString().c_str());
}
if (!palette.empty()) {
setPalette(palette);
}
GraphicsManager::copyToManaged(*_decoder.decodeNextFrame(), _drawSurface, !palette.empty());
_needsRedraw = true;
}
TVDMap::TVDMap() : _ornaments(7), _globe(8, this) {}
void TVDMap::init() {
_viewport.init();
_label.init();
_ornaments.init();
_globe.init();
auto *bootSummary = GetEngineData(BSUM);
assert(bootSummary);
Common::Rect textboxScreenPosition = bootSummary->textboxScreenPosition;
_closedLabel._drawSurface.create(g_nancy->_graphics->_object0, _mapData->closedLabelSrc);
Common::Rect closedScreenRect;
closedScreenRect.left = textboxScreenPosition.left + ((textboxScreenPosition.width() - _mapData->closedLabelSrc.width()) / 2);
closedScreenRect.right = closedScreenRect.left + _mapData->closedLabelSrc.width();
closedScreenRect.bottom = textboxScreenPosition.bottom - 10;
closedScreenRect.top = closedScreenRect.bottom - _mapData->closedLabelSrc.height();
_closedLabel.moveTo(closedScreenRect);
_closedLabel.setTransparent(true);
_activeLocations.resize(7, true);
_locationLabelDests.resize(7);
for (uint i = 0; i < 7; ++i) {
_locationLabelDests[i].left = textboxScreenPosition.left + ((textboxScreenPosition.width() - _mapData->locations[i].labelSrc.width()) / 2);
_locationLabelDests[i].right = _locationLabelDests[i].left + _mapData->locations[i].labelSrc.width();
_locationLabelDests[i].bottom = closedScreenRect.bottom - ((closedScreenRect.bottom - _mapData->locations[i].labelSrc.height() - textboxScreenPosition.top) / 2) - 10;
_locationLabelDests[i].top = _locationLabelDests[i].bottom - _mapData->locations[i].labelSrc.height();
}
_state = kLoad;
}
void TVDMap::load() {
Map::load();
// Determine which version of the map will be shown
if (NancySceneState.getEventFlag(82, g_nancy->_true)) {
_mapID = 3; // Storm
//
} else {
// Determine map based on the in-game time
byte timeOfDay = NancySceneState.getPlayerTOD();
if (timeOfDay == kPlayerDay) {
_mapID = 0; // Day
} else if (timeOfDay == kPlayerNight) {
_mapID = 1; // Night
} else {
_mapID = 2; // Dusk/dawn
}
}
_viewport.loadVideo(_mapData->mapNames[_mapID], _mapData->mapPaletteNames[_mapID]);
g_nancy->_cursor->setCursorItemID(-1);
_viewport.setVisible(false);
_globe.setOpen(true);
_globe.setVisible(true);
if (!g_nancy->_sound->isSoundPlaying(getSound())) {
g_nancy->_sound->loadSound(getSound());
}
g_nancy->_sound->playSound("GLOB");
registerGraphics();
_state = kRun;
}
bool TVDMap::onStateExit(const NancyState::NancyState nextState) {
if (nextState != NancyState::kPause) {
if (_pickedLocationID != -1) {
NancySceneState.changeScene(_mapData->locations[_pickedLocationID].scenes[NancySceneState.getPlayerTOD() == kPlayerDay ? 0 : 1]);
g_nancy->_sound->playSound("BUOK");
} else {
g_nancy->_sound->stopSound(getSound());
}
}
return Map::onStateExit(nextState);
}
void TVDMap::run() {
if (!g_nancy->_sound->isSoundPlaying("GLOB") && !g_nancy->_sound->isSoundPlaying(getSound())) {
g_nancy->_sound->playSound(getSound());
}
setLabel(-1);
g_nancy->_cursor->setCursorType(CursorManager::kNormal);
if (!_globe.isPlaying()) {
NancyInput input = g_nancy->_input->getInput();
_globe.handleInput(input);
for (uint i = 0; i < 7; ++i) {
if (_viewport.convertToScreen(_mapData->locations[i].hotspot).contains(input.mousePos)) {
setLabel(i);
if (_activeLocations[i]){
g_nancy->_cursor->setCursorType(CursorManager::kHotspot);
if (input.input & NancyInput::kLeftMouseButtonUp) {
_pickedLocationID = i;
_globe.setOpen(false);
g_nancy->_sound->playSound("GLOB");
}
}
return;
}
}
}
}
void TVDMap::registerGraphics() {
Map::registerGraphics();
_ornaments.registerGraphics();
_globe.registerGraphics();
}
void TVDMap::MapGlobe::init() {
moveTo(_owner->_mapData->globeDest);
_frameTime = _owner->_mapData->globeFrameTime;
_srcRects = _owner->_mapData->globeSrcs;
_gargoyleEyes._drawSurface.create(g_nancy->_graphics->_object0, _owner->_mapData->globeGargoyleSrc);
_gargoyleEyes.moveTo(_owner->_mapData->globeGargoyleDest);
_gargoyleEyes.setTransparent(true);
_gargoyleEyes.setVisible(false);
_alwaysHighlightCursor = false;
_hotspot = _screenPosition;
AnimatedButton::init();
}
void TVDMap::MapGlobe::registerGraphics() {
AnimatedButton::registerGraphics();
_gargoyleEyes.registerGraphics();
}
void TVDMap::MapGlobe::onClick() {
_gargoyleEyes.setVisible(false);
g_nancy->_sound->playSound("GLOB");
}
void TVDMap::MapGlobe::onTrigger() {
if (_isOpen) {
_gargoyleEyes.setVisible(true);
_owner->_viewport.setVisible(true);
_owner->_viewport.playVideo();
g_nancy->_cursor->warpCursor(_owner->_mapData->cursorPosition);
g_nancy->setMouseEnabled(true);
} else {
_owner->_state = kExit;
_nextFrameTime = 0;
}
}
void Nancy1Map::init() {
_viewport.init();
_label.init();
Common::Rect textboxScreenPosition = NancySceneState.getTextbox().getScreenPosition();
_closedLabel._drawSurface.create(g_nancy->_graphics->_object0, _mapData->closedLabelSrc);
Common::Rect closedScreenRect;
closedScreenRect.left = textboxScreenPosition.left + ((textboxScreenPosition.width() - _mapData->closedLabelSrc.width()) / 2);
closedScreenRect.right = closedScreenRect.left + _mapData->closedLabelSrc.width() - 1;
closedScreenRect.bottom = textboxScreenPosition.bottom - 11;
closedScreenRect.top = closedScreenRect.bottom - _mapData->closedLabelSrc.height() + 1;
_closedLabel.moveTo(closedScreenRect);
_activeLocations.resize(4, true);
_locationLabelDests.resize(4);
for (uint i = 0; i < 4; ++i) {
_locationLabelDests[i].left = textboxScreenPosition.left + ((textboxScreenPosition.width() - _mapData->locations[i].labelSrc.width()) / 2);
_locationLabelDests[i].right = _locationLabelDests[i].left + _mapData->locations[i].labelSrc.width() - 1;
_locationLabelDests[i].bottom = closedScreenRect.bottom - ((closedScreenRect.bottom - _mapData->locations[i].labelSrc.height() - textboxScreenPosition.top) / 2) - 11;
_locationLabelDests[i].top = _locationLabelDests[i].bottom - _mapData->locations[i].labelSrc.height() + 1;
}
_button.reset(new UI::Button(9, g_nancy->_graphics->_object0, _mapData->buttonSrc, _mapData->buttonDest));
_button->init();
_button->setVisible(true);
_state = kLoad;
}
void Nancy1Map::load() {
Map::load();
// Determine which version of the map will be shown
if (NancySceneState.getEventFlag(40, g_nancy->_true) && // Has set up sting
NancySceneState.getEventFlag(95, g_nancy->_true)) { // Connie chickens
_mapID = 1; // Night
_activeLocations[1] = _activeLocations[3] = false;
} else {
_mapID = 0; // Day
}
_viewport.loadVideo(_mapData->mapNames[_mapID]);
setLabel(-1);
g_nancy->_cursor->setCursorItemID(-1);
g_nancy->_cursor->warpCursor(_mapData->cursorPosition);
if (!g_nancy->_sound->isSoundPlaying(getSound())) {
g_nancy->_sound->loadSound(getSound());
}
registerGraphics();
_state = kRun;
}
void Nancy1Map::run() {
if (!g_nancy->_sound->isSoundPlaying("GLOB") && !g_nancy->_sound->isSoundPlaying(getSound())) {
g_nancy->_sound->playSound(getSound());
}
NancyInput input = g_nancy->_input->getInput();
setLabel(-1);
_button->handleInput(input);
if (_button->_isClicked) {
_button->_isClicked = false;
_state = kExit;
return;
}
for (uint i = 0; i < 4; ++i) {
if (_viewport.convertToScreen(_mapData->locations[i].hotspot).contains(input.mousePos)) {
setLabel(i);
if (_activeLocations[i]){
g_nancy->_cursor->setCursorType(CursorManager::kHotspotArrow);
if (input.input & NancyInput::kLeftMouseButtonUp) {
_pickedLocationID = i;
_state = kExit;
}
}
return;
}
}
}
void Nancy1Map::registerGraphics() {
Map::registerGraphics();
_button->registerGraphics();
}
bool Nancy1Map::onStateExit(const NancyState::NancyState nextState) {
if (nextState != NancyState::kPause) {
if (_pickedLocationID != -1) {
NancySceneState.changeScene(_mapData->locations[_pickedLocationID].scenes[_mapID]);
g_nancy->_sound->playSound("BUOK");
}
g_nancy->_sound->stopSound(getSound());
g_nancy->_sound->playSound("GLOB");
}
return Map::onStateExit(nextState);
}
} // End of namespace State
} // End of namespace Nancy

154
engines/nancy/state/map.h Normal file
View File

@@ -0,0 +1,154 @@
/* 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 NANCY_STATE_MAP_H
#define NANCY_STATE_MAP_H
#include "common/ptr.h"
#include "common/singleton.h"
#include "engines/nancy/sound.h"
#include "engines/nancy/video.h"
#include "engines/nancy/state/state.h"
#include "engines/nancy/ui/animatedbutton.h"
#include "engines/nancy/ui/ornaments.h"
namespace Nancy {
class NancyEngine;
namespace UI {
class Button;
}
namespace State {
class Map : public State, public Common::Singleton<Map> {
public:
enum State { kInit, kLoad, kRun, kExit };
Map();
virtual ~Map() = default;
void process() override;
void onStateEnter(const NancyState::NancyState prevState) override;
bool onStateExit(const NancyState::NancyState nextState) override;
const SoundDescription &getSound();
protected:
class MapViewport : public Nancy::RenderObject {
public:
MapViewport() : RenderObject(6) {}
virtual ~MapViewport() = default;
void init() override;
void updateGraphics() override;
void loadVideo(const Common::Path &filename, const Common::Path &palette = Common::Path());
void playVideo() { _decoder.start(); }
void unloadVideo() { _decoder.close(); }
AVFDecoder _decoder;
private:
};
virtual void init() = 0;
virtual void load();
virtual void run() = 0;
virtual void registerGraphics();
void setLabel(int labelID);
const MAP *_mapData;
MapViewport _viewport;
RenderObject _label;
RenderObject _closedLabel;
RenderObject _background;
State _state;
uint16 _mapID;
int16 _pickedLocationID;
Common::Array<bool> _activeLocations;
Common::Array<Common::Rect> _locationLabelDests;
};
class TVDMap : public Map {
friend class MapGlobe;
public:
TVDMap();
virtual ~TVDMap() = default;
private:
class MapGlobe : public Nancy::UI::AnimatedButton {
public:
MapGlobe(uint zOrder, TVDMap *owner) : AnimatedButton(zOrder), _gargoyleEyes(zOrder), _owner(owner) {}
virtual ~MapGlobe() = default;
void init() override;
void registerGraphics() override;
void onClick() override;
void onTrigger() override;
private:
TVDMap *_owner;
RenderObject _gargoyleEyes;
};
void init() override;
void load() override;
void run() override;
void registerGraphics() override;
bool onStateExit(const NancyState::NancyState nextState) override;
MapGlobe _globe;
UI::ViewportOrnaments _ornaments;
};
class Nancy1Map : public Map {
private:
void init() override;
void load() override;
void run() override;
void registerGraphics() override;
bool onStateExit(const NancyState::NancyState next) override;
Common::ScopedPtr<UI::Button> _button;
};
#define NancyMapState Nancy::State::Map::instance()
} // End of namespace State
} // End of namespace Nancy
namespace Common {
template<>
Nancy::State::Map *Singleton<Nancy::State::Map>::makeInstance();
} // End of namespace Common
#endif // NANCY_STATE_MAP_H

View File

@@ -0,0 +1,134 @@
/* 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/nancy/nancy.h"
#include "engines/nancy/cursor.h"
#include "engines/nancy/sound.h"
#include "engines/nancy/input.h"
#include "engines/nancy/util.h"
#include "engines/nancy/state/savedialog.h"
#include "engines/nancy/state/scene.h"
#include "engines/nancy/ui/button.h"
#include "common/config-manager.h"
namespace Common {
DECLARE_SINGLETON(Nancy::State::SaveDialog);
}
namespace Nancy {
namespace State {
void SaveDialog::process() {
if (g_nancy->_sound->isSoundPlaying("BUOK")) {
return;
}
switch (_state) {
case kInit:
init();
// fall through
case kRun:
run();
break;
case kStop:
stop();
break;
}
g_nancy->_cursor->setCursorType(CursorManager::kNormalArrow);
}
void SaveDialog::onStateEnter(const NancyState::NancyState prevState) {
registerGraphics();
}
bool SaveDialog::onStateExit(const NancyState::NancyState nextState) {
return true;
}
void SaveDialog::registerGraphics() {
_background.registerGraphics();
if (_yesButton) {
_yesButton->registerGraphics();
}
if (_noButton) {
_noButton->registerGraphics();
}
if (_cancelButton) {
_cancelButton->registerGraphics();
}
}
void SaveDialog::init() {
auto *sdlg = GetEngineData(SDLG);
assert(sdlg);
_dialogData = &sdlg->dialogs[ConfMan.getInt("sdlg_id", Common::ConfigManager::kTransientDomain)];
ConfMan.removeKey("sdlg_id", Common::ConfigManager::kTransientDomain);
_background.init(_dialogData->imageName);
_yesButton.reset(new UI::Button(1, _background._drawSurface, _dialogData->yesDownSrc, _dialogData->yesDest, _dialogData->yesHighlightSrc));
_noButton.reset(new UI::Button(1, _background._drawSurface, _dialogData->noDownSrc, _dialogData->noDest, _dialogData->noHighlightSrc));
_cancelButton.reset(new UI::Button(1, _background._drawSurface, _dialogData->cancelDownSrc, _dialogData->cancelDest, _dialogData->cancelHighlightSrc));
registerGraphics();
_state = kRun;
}
void SaveDialog::run() {
NancyInput input = g_nancy->_input->getInput();
_yesButton->handleInput(input);
if (_yesButton->_isClicked) {
_selected = 0;
_state = kStop;
g_nancy->_sound->playSound("BUOK");
}
_noButton->handleInput(input);
if (_noButton->_isClicked) {
_selected = 1;
_state = kStop;
g_nancy->_sound->playSound("BUOK");
}
_cancelButton->handleInput(input);
if (_cancelButton->_isClicked) {
_selected = 2;
_state = kStop;
g_nancy->_sound->playSound("BUOK");
}
}
void SaveDialog::stop() {
ConfMan.setInt("sdlg_return", _selected, Common::ConfigManager::kTransientDomain);
g_nancy->setToPreviousState();
}
} // End of namespace State
} // End of namespace Nancy

View File

@@ -0,0 +1,74 @@
/* 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 NANCY_STATE_SAVEDIALOG_H
#define NANCY_STATE_SAVEDIALOG_H
#include "common/ptr.h"
#include "common/singleton.h"
#include "engines/nancy/state/state.h"
#include "engines/nancy/ui/fullscreenimage.h"
namespace Nancy {
struct SDLG;
namespace UI {
class Button;
}
namespace State {
class SaveDialog : public State, public Common::Singleton<SaveDialog> {
public:
SaveDialog() : _state(kInit), _selected(-1), _dialogData(nullptr) {}
// State API
void process() override;
void onStateEnter(const NancyState::NancyState prevState) override;
bool onStateExit(const NancyState::NancyState nextState) override;
private:
void init();
void run();
void stop();
void registerGraphics();
enum State { kInit, kRun, kStop };
UI::FullScreenImage _background;
State _state;
int _selected;
Common::ScopedPtr<UI::Button> _yesButton;
Common::ScopedPtr<UI::Button> _noButton;
Common::ScopedPtr<UI::Button> _cancelButton;
const SDLG::Dialog *_dialogData;
};
} // End of namespace State
} // End of namespace Nancy
#endif // NANCY_STATE_MAINMENU_H

File diff suppressed because it is too large Load Diff

311
engines/nancy/state/scene.h Normal file
View File

@@ -0,0 +1,311 @@
/* 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 NANCY_STATE_SCENE_H
#define NANCY_STATE_SCENE_H
#include "common/singleton.h"
#include "common/queue.h"
#include "engines/nancy/commontypes.h"
#include "engines/nancy/puzzledata.h"
#include "engines/nancy/action/actionmanager.h"
#include "engines/nancy/state/state.h"
#include "engines/nancy/ui/fullscreenimage.h"
#include "engines/nancy/ui/viewport.h"
#include "engines/nancy/ui/textbox.h"
#include "engines/nancy/ui/inventorybox.h"
namespace Common {
class SeekableReadStream;
class Serializer;
}
namespace Nancy {
class NancyEngine;
class NancyConsole;
struct SceneChangeDescription;
namespace Action {
class ConversationSound;
class PlaySecondaryMovie;
}
namespace Misc {
class Lightning;
class SpecialEffect;
}
namespace UI {
class Button;
class ViewportOrnaments;
class TextboxOrnaments;
class InventoryBoxOrnaments;
class Clock;
}
namespace State {
// The game state that handles all of the gameplay
class Scene : public State, public Common::Singleton<Scene> {
friend class Nancy::Action::ActionRecord;
friend class Nancy::Action::ActionManager;
friend class Nancy::NancyConsole;
friend class Nancy::NancyEngine;
public:
struct SceneSummary {
// SSUM and TSUM
// Default values set to match those applied when loading from a TSUM chunk
Common::String description;
Common::Path videoFile;
uint16 videoFormat = kLargeVideoFormat;
Common::Array<Common::Path> palettes;
SoundDescription sound;
byte panningType = kPan360;
uint16 numberOfVideoFrames = 0;
uint16 degreesPerRotation = 18;
uint16 totalViewAngle = 0;
uint16 horizontalScrollDelta = 1;
uint16 verticalScrollDelta = 10;
uint16 horizontalEdgeSize = 15;
uint16 verticalEdgeSize = 15;
Time slowMoveTimeDelta = 400;
Time fastMoveTimeDelta = 66;
// Sound start vectors, used in nancy3 and up
Math::Vector3d listenerPosition;
void read(Common::SeekableReadStream &stream);
void readTerse(Common::SeekableReadStream &stream);
};
Scene();
virtual ~Scene();
// State API
void process() override;
void onStateEnter(const NancyState::NancyState prevState) override;
bool onStateExit(const NancyState::NancyState nextState) override;
// Used when winning/losing game
void setDestroyOnExit() { _destroyOnExit = true; }
bool isRunningAd() const { return _isRunningAd; }
void changeScene(const SceneChangeDescription &sceneDescription);
void pushScene(int16 itemID = -1);
void popScene(bool inventory = false);
void setPlayerTime(Time time, byte relative);
Time getPlayerTime() const { return _timers.playerTime; }
Time getTimerTime() const { return _timers.timerIsActive ? _timers.timerTime : 0; }
byte getPlayerTOD() const;
void addItemToInventory(int16 id);
void removeItemFromInventory(int16 id, bool pickUp = true);
int16 getHeldItem() const { return _flags.heldItem; }
void setHeldItem(int16 id);
void setNoHeldItem();
byte hasItem(int16 id) const;
byte getItemDisabledState(int16 id) const { return _flags.disabledItems[id]; }
void setItemDisabledState(int16 id, byte state) { _flags.disabledItems[id] = state; }
void installInventorySoundOverride(byte command, const SoundDescription &sound, const Common::String &caption, uint16 itemID);
void playItemCantSound(int16 itemID = -1, bool notHoldingSound = false);
void setEventFlag(int16 label, byte flag);
void setEventFlag(FlagDescription eventFlag);
bool getEventFlag(int16 label, byte flag) const;
bool getEventFlag(FlagDescription eventFlag) const;
void setLogicCondition(int16 label, byte flag);
bool getLogicCondition(int16 label, byte flag) const;
void clearLogicConditions();
void setDifficulty(uint difficulty) { _difficulty = difficulty; }
uint16 getDifficulty() const { return _difficulty; }
byte getHintsRemaining() const { return _hintsRemaining[_difficulty]; }
void useHint(uint16 characterID, uint16 hintID);
void requestStateChange(NancyState::NancyState state) { _gameStateRequested = state; }
void resetStateToInit() { _state = kInit; }
void resetAndStartTimer() { _timers.timerIsActive = true; _timers.timerTime = 0; }
void stopTimer() { _timers.timerIsActive = false; _timers.timerTime = 0; }
Time getMovementTimeDelta(bool fast) const { return fast ? _sceneState.summary.fastMoveTimeDelta : _sceneState.summary.slowMoveTimeDelta; }
void registerGraphics();
void synchronize(Common::Serializer &serializer);
UI::FullScreenImage &getFrame() { return _frame; }
UI::Viewport &getViewport() { return _viewport; }
UI::Textbox &getTextbox() { return _textbox; }
UI::InventoryBox &getInventoryBox() { return _inventoryBox; }
UI::Clock *getClock();
Action::ActionManager &getActionManager() { return _actionManager; }
SceneChangeDescription &getSceneInfo() { return _sceneState.currentScene; }
SceneChangeDescription &getNextSceneInfo() { return _sceneState.nextScene; }
const SceneSummary &getSceneSummary() const { return _sceneState.summary; }
void setActiveMovie(Action::PlaySecondaryMovie *activeMovie);
Action::PlaySecondaryMovie *getActiveMovie();
void setActiveConversation(Action::ConversationSound *activeConversation);
Action::ConversationSound *getActiveConversation();
Graphics::ManagedSurface &getLastScreenshot() { return _lastScreenshot; }
// The Vampire Diaries only;
void beginLightning(int16 distance, uint16 pulseTime, int16 rgbPercent);
// Used from nancy2 onwards
void specialEffect(byte type, uint16 fadeToBlackTime, uint16 frameTime);
void specialEffect(byte type, uint16 totalTime, uint16 fadeToBlackTime, Common::Rect rect);
// Get the persistent data for a given puzzle type
PuzzleData *getPuzzleData(const uint32 tag);
private:
void init();
void load(bool fromSaveFile = false);
void run();
void handleInput();
void initStaticData();
void clearSceneData();
void clearPuzzleData();
enum State {
kInit,
kLoad,
kStartSound,
kRun
};
struct SceneState {
SceneSummary summary;
SceneChangeDescription currentScene;
SceneChangeDescription nextScene;
SceneChangeDescription pushedScene;
bool isScenePushed = false;
SceneChangeDescription pushedInvScene;
int16 pushedInvItemID = -1;
bool isInvScenePushed = false;
};
struct Timers {
Time pushedPlayTime;
Time lastTotalTime;
Time sceneTime;
Time timerTime;
bool timerIsActive = false;
Time playerTime; // In-game time of day, adds a minute every 5 seconds
Time playerTimeNextMinute; // Stores the next tick count until we add a minute to playerTime
};
struct PlayFlags {
struct LogicCondition {
LogicCondition();
byte flag;
Time timestamp;
};
LogicCondition logicConditions[30];
Common::Array<byte> eventFlags;
Common::HashMap<uint16, uint16> sceneCounts;
Common::Array<byte> items;
Common::Array<byte> disabledItems;
int16 heldItem = -1;
int16 primaryVideoResponsePicked = -1;
};
struct InventorySoundOverride {
bool isDefault = false; // When true, other fields are ignored
SoundDescription sound;
Common::String caption;
};
// UI
UI::FullScreenImage _frame;
UI::Viewport _viewport;
UI::Textbox _textbox;
UI::InventoryBox _inventoryBox;
UI::Button *_menuButton;
UI::Button *_helpButton;
Time _buttonPressActivationTime;
UI::ViewportOrnaments *_viewportOrnaments;
UI::TextboxOrnaments *_textboxOrnaments;
UI::InventoryBoxOrnaments *_inventoryBoxOrnaments;
RenderObject *_clock;
Common::Rect _mapHotspot;
// General data
SceneState _sceneState;
PlayFlags _flags;
Timers _timers;
uint16 _difficulty;
Common::Array<uint16> _hintsRemaining;
int16 _lastHintCharacter;
int16 _lastHintID;
NancyState::NancyState _gameStateRequested;
Common::HashMap<uint16, InventorySoundOverride> _inventorySoundOverrides;
Misc::Lightning *_lightning;
Common::Queue<Misc::SpecialEffect> _specialEffects;
Common::HashMap<uint32, PuzzleData *> _puzzleData;
Action::ActionManager _actionManager;
Action::PlaySecondaryMovie *_activeMovie;
Action::ConversationSound *_activeConversation;
// Contains a screenshot of the Scene state from the last time it was exited
Graphics::ManagedSurface _lastScreenshot;
RenderObject _hotspotDebug;
bool _destroyOnExit;
bool _isRunningAd;
State _state;
};
#define NancySceneState Nancy::State::Scene::instance()
} // End of namespace State
} // End of namespace Nancy
#endif // NANCY_STATE_SCENE_H

View File

@@ -0,0 +1,255 @@
/* 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/nancy/nancy.h"
#include "engines/nancy/cursor.h"
#include "engines/nancy/sound.h"
#include "engines/nancy/input.h"
#include "engines/nancy/util.h"
#include "engines/nancy/state/setupmenu.h"
#include "engines/nancy/state/scene.h"
#include "engines/nancy/ui/button.h"
#include "engines/nancy/ui/scrollbar.h"
#include "common/config-manager.h"
namespace Common {
DECLARE_SINGLETON(Nancy::State::SetupMenu);
}
namespace Nancy {
namespace State {
void SetupMenu::process() {
switch (_state) {
case kInit:
init();
// fall through
case kRun:
run();
break;
case kStop:
stop();
break;
}
}
void SetupMenu::onStateEnter(const NancyState::NancyState prevState) {
registerGraphics();
}
bool SetupMenu::onStateExit(const NancyState::NancyState nextState) {
return true;
}
void SetupMenu::registerGraphics() {
_background.registerGraphics();
for (auto &tog : _toggles) {
tog->registerGraphics();
}
for (auto &scroll : _scrollbars) {
scroll->registerGraphics();
}
if (_exitButton) {
_exitButton->registerGraphics();
}
}
const Common::String SetupMenu::getToggleConfManKey(uint id) {
GameType gameType = g_nancy->getGameType();
if (gameType == kGameTypeVampire) {
// Note that toggle id 1 (interlaced video) is ignored since we don't support that option
switch (id) {
case 0 :
return "subtitles";
case 2 :
return "player_speech";
case 3 :
return "character_speech";
default:
return "";
}
} else if (gameType <= kGameTypeNancy5) {
switch (id) {
case 0 :
return "subtitles";
case 1 :
return "player_speech";
case 2 :
return "character_speech";
default:
return "";
}
} else {
switch (id) {
case 0 :
return "subtitles";
case 1 :
return "auto_move";
default:
return "";
}
}
}
void SetupMenu::init() {
_setupData = GetEngineData(SET);
assert(_setupData);
if (g_nancy->getGameType() == kGameTypeVampire) {
// There is a setup.bmp an the top directory of the first disk,
// which we need to avoid
_background.init(Common::Path("ART/").joinInPlace(_setupData->_imageName));
} else {
_background.init(_setupData->_imageName);
}
_background.registerGraphics();
g_nancy->_cursor->setCursorType(CursorManager::kNormalArrow);
g_nancy->setMouseEnabled(true);
g_nancy->_sound->stopSound("MSND");
for (uint i = 0; i < _setupData->_sounds.size(); ++i) {
if (!g_nancy->_sound->isSoundPlaying(_setupData->_sounds[i])) {
g_nancy->_sound->loadSound(_setupData->_sounds[i]);
g_nancy->_sound->playSound(_setupData->_sounds[i]);
}
}
_toggles.resize(_setupData->_buttonDests.size() - 1);
for (uint i = 0; i < _setupData->_buttonDests.size() - 1; ++i) {
_toggles[i].reset(new UI::Toggle(5, _background._drawSurface,
_setupData->_buttonDownSrcs[i], _setupData->_buttonDests[i]));
_toggles[i]->init();
}
// Set toggle visibility
for (uint i = 0; i < _toggles.size(); ++i) {
_toggles[i]->setState(ConfMan.getBool(getToggleConfManKey(i), ConfMan.getActiveDomainName()));
}
_scrollbars.resize(_setupData->_scrollbarSrcs.size());
for (uint i = 0; i < _setupData->_scrollbarSrcs.size(); ++i) {
_scrollbars[i].reset(new UI::Scrollbar(7, _setupData->_scrollbarSrcs[i],
_background._drawSurface, Common::Point(_setupData->_scrollbarsCenterXPosL[i] + 1, _setupData->_scrollbarsCenterYPos[i]),
_setupData->_scrollbarsCenterXPosR[i] + 1 - _setupData->_scrollbarsCenterXPosL[i] - 1, false));
_scrollbars[i]->init();
_scrollbars[i]->setVisible(true);
}
// Set scrollbar positions
_scrollbars[0]->setPosition(ConfMan.getInt("speech_volume") / 255.0);
_scrollbars[1]->setPosition(ConfMan.getInt("music_volume") / 255.0);
_scrollbars[2]->setPosition(ConfMan.getInt("sfx_volume") / 255.0);
_exitButton.reset(new UI::Button(5, _background._drawSurface,
_setupData->_buttonDownSrcs.back(), _setupData->_buttonDests.back(),
_setupData->_doneButtonHighlightSrc));
_exitButton->init();
_exitButton->setVisible(false);
registerGraphics();
_state = kRun;
}
void SetupMenu::run() {
NancyInput input = g_nancy->_input->getInput();
for (uint i = 0; i < _scrollbars.size(); ++i) {
auto &scroll = _scrollbars[i];
float startPos = scroll->getPos();
scroll->handleInput(input);
float endPos = scroll->getPos();
if (endPos != startPos) {
Audio::Mixer::SoundType type = Audio::Mixer::SoundType::kSpeechSoundType;
switch (i) {
case 0 :
type = Audio::Mixer::SoundType::kSpeechSoundType;
ConfMan.setInt("speech_volume", endPos * 255, ConfMan.getActiveDomainName());
break;
case 1 :
type = Audio::Mixer::SoundType::kMusicSoundType;
ConfMan.setInt("music_volume", endPos * 255, ConfMan.getActiveDomainName());
break;
case 2 :
type = Audio::Mixer::SoundType::kSFXSoundType;
ConfMan.setInt("sfx_volume", endPos * 255, ConfMan.getActiveDomainName());
break;
default:
break;
}
g_system->getMixer()->setVolumeForSoundType(type, endPos * 255);
}
}
for (uint i = 0; i < _toggles.size(); ++i) {
auto &tog = _toggles[i];
tog->handleInput(input);
if (tog->_stateChanged) {
g_nancy->_sound->playSound("BUOK");
Common::String key = getToggleConfManKey(i);
if (key.size()) {
// Make sure we don't write an empty string as a key in ConfMan
ConfMan.setBool(key, tog->_toggleState, ConfMan.getActiveDomainName());
}
}
}
if (_exitButton) {
_exitButton->handleInput(input);
if (_exitButton->_isClicked) {
g_nancy->_sound->playSound("BUOK");
_state = kStop;
}
}
g_nancy->_cursor->setCursorType(CursorManager::kNormalArrow);
}
void SetupMenu::stop() {
if (g_nancy->_sound->isSoundPlaying("BUOK")) {
return;
}
for (auto &sound : _setupData->_sounds) {
g_nancy->_sound->stopSound(sound);
}
ConfMan.flushToDisk();
g_nancy->setToPreviousState();
}
} // End of namespace State
} // End of namespace Nancy

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/>.
*
*/
#ifndef NANCY_STATE_SETUPMENU_H
#define NANCY_STATE_SETUPMENU_H
#include "common/ptr.h"
#include "common/singleton.h"
#include "engines/nancy/state/state.h"
#include "engines/nancy/ui/fullscreenimage.h"
#include "engines/nancy/ui/scrollbar.h"
#include "engines/nancy/ui/button.h"
namespace Nancy {
struct SET;
namespace State {
class SetupMenu : public State, public Common::Singleton<SetupMenu> {
public:
// State API
void process() override;
void onStateEnter(const NancyState::NancyState prevState) override;
bool onStateExit(const NancyState::NancyState nextState) override;
private:
void init();
void run();
void stop();
void registerGraphics();
const Common::String getToggleConfManKey(uint id);
enum State { kInit, kRun, kStop };
UI::FullScreenImage _background;
State _state = kInit;
Common::Array<Common::ScopedPtr<UI::Toggle>> _toggles;
Common::Array<Common::ScopedPtr<UI::Scrollbar>> _scrollbars;
Common::ScopedPtr<UI::Button> _exitButton;
const SET *_setupData;
};
} // End of namespace State
} // End of namespace Nancy
#endif // NANCY_STATE_SETUPMENU_H

View File

@@ -0,0 +1,47 @@
/* 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 NANCY_STATE_STATE_H
#define NANCY_STATE_STATE_H
#include "engines/nancy/commontypes.h"
#include "common/singleton.h"
namespace Nancy {
namespace State {
// Base class for all states. Provides a simple API for handling state switching
class State {
public:
State() {}
virtual ~State() {};
virtual void process() = 0;
virtual void onStateEnter(const NancyState::NancyState prevState) {}
// Return true when the state needs to be destroyed
virtual bool onStateExit(const NancyState::NancyState nextState) { return false; }
};
} // End of namespace State
} // End of namespace Nancy
#endif // NANCY_STATE_STATE_H