Initial commit
This commit is contained in:
156
engines/nancy/state/credits.cpp
Normal file
156
engines/nancy/state/credits.cpp
Normal 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
|
||||
69
engines/nancy/state/credits.h
Normal file
69
engines/nancy/state/credits.h
Normal 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
|
||||
123
engines/nancy/state/help.cpp
Normal file
123
engines/nancy/state/help.cpp
Normal 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
|
||||
67
engines/nancy/state/help.h
Normal file
67
engines/nancy/state/help.h
Normal 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
|
||||
1407
engines/nancy/state/loadsave.cpp
Normal file
1407
engines/nancy/state/loadsave.cpp
Normal file
File diff suppressed because it is too large
Load Diff
166
engines/nancy/state/loadsave.h
Normal file
166
engines/nancy/state/loadsave.h
Normal 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
|
||||
167
engines/nancy/state/logo.cpp
Normal file
167
engines/nancy/state/logo.cpp
Normal 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
|
||||
74
engines/nancy/state/logo.h
Normal file
74
engines/nancy/state/logo.h
Normal 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
|
||||
278
engines/nancy/state/mainmenu.cpp
Normal file
278
engines/nancy/state/mainmenu.cpp
Normal 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
|
||||
75
engines/nancy/state/mainmenu.h
Normal file
75
engines/nancy/state/mainmenu.h
Normal 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
469
engines/nancy/state/map.cpp
Normal 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
154
engines/nancy/state/map.h
Normal 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
|
||||
134
engines/nancy/state/savedialog.cpp
Normal file
134
engines/nancy/state/savedialog.cpp
Normal 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
|
||||
74
engines/nancy/state/savedialog.h
Normal file
74
engines/nancy/state/savedialog.h
Normal 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
|
||||
1286
engines/nancy/state/scene.cpp
Normal file
1286
engines/nancy/state/scene.cpp
Normal file
File diff suppressed because it is too large
Load Diff
311
engines/nancy/state/scene.h
Normal file
311
engines/nancy/state/scene.h
Normal 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
|
||||
255
engines/nancy/state/setupmenu.cpp
Normal file
255
engines/nancy/state/setupmenu.cpp
Normal 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
|
||||
70
engines/nancy/state/setupmenu.h
Normal file
70
engines/nancy/state/setupmenu.h
Normal 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
|
||||
47
engines/nancy/state/state.h
Normal file
47
engines/nancy/state/state.h
Normal 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
|
||||
Reference in New Issue
Block a user