aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
authorPeter Kohaut2018-12-05 18:18:13 +0100
committerPeter Kohaut2018-12-05 18:18:49 +0100
commit1855d1cf13de5c9f4cf84fc07ab4b5053cae5295 (patch)
tree0359b9125083f1fceefa6f121be22299a5ae7859 /engines
parent216d4743489d2284eff6afd7bc7a7e5a92693eea (diff)
downloadscummvm-rg350-1855d1cf13de5c9f4cf84fc07ab4b5053cae5295.tar.gz
scummvm-rg350-1855d1cf13de5c9f4cf84fc07ab4b5053cae5295.tar.bz2
scummvm-rg350-1855d1cf13de5c9f4cf84fc07ab4b5053cae5295.zip
BLADERUNNER: Add in-game saving screen
Diffstat (limited to 'engines')
-rw-r--r--engines/bladerunner/bladerunner.cpp9
-rw-r--r--engines/bladerunner/detection.cpp3
-rw-r--r--engines/bladerunner/module.mk1
-rw-r--r--engines/bladerunner/savefile.cpp15
-rw-r--r--engines/bladerunner/savefile.h7
-rw-r--r--engines/bladerunner/ui/kia.h11
-rw-r--r--engines/bladerunner/ui/kia_section_clues.h8
-rw-r--r--engines/bladerunner/ui/kia_section_load.cpp47
-rw-r--r--engines/bladerunner/ui/kia_section_load.h34
-rw-r--r--engines/bladerunner/ui/kia_section_save.cpp407
-rw-r--r--engines/bladerunner/ui/kia_section_save.h61
-rw-r--r--engines/bladerunner/ui/ui_component.h1
-rw-r--r--engines/bladerunner/ui/ui_container.cpp6
-rw-r--r--engines/bladerunner/ui/ui_container.h1
-rw-r--r--engines/bladerunner/ui/ui_input_box.cpp19
-rw-r--r--engines/bladerunner/ui/ui_input_box.h8
16 files changed, 569 insertions, 69 deletions
diff --git a/engines/bladerunner/bladerunner.cpp b/engines/bladerunner/bladerunner.cpp
index 3d9ba34cb1..61b45e9ada 100644
--- a/engines/bladerunner/bladerunner.cpp
+++ b/engines/bladerunner/bladerunner.cpp
@@ -221,9 +221,7 @@ bool BladeRunnerEngine::canLoadGameStateCurrently() {
}
Common::Error BladeRunnerEngine::loadGameState(int slot) {
- const Common::String saveName = Common::String::format("%s.%03d", _targetName.c_str(), slot);
-
- Common::InSaveFile *saveFile = getSaveFileManager()->openForLoading(saveName);
+ Common::InSaveFile *saveFile = BladeRunner::SaveFileManager::openForLoading(_targetName, slot);
if (saveFile == nullptr || saveFile->err()) {
delete saveFile;
return Common::kReadingFailed;
@@ -253,9 +251,7 @@ bool BladeRunnerEngine::canSaveGameStateCurrently() {
}
Common::Error BladeRunnerEngine::saveGameState(int slot, const Common::String &desc) {
- const Common::String saveName = Common::String::format("%s.%03d", _targetName.c_str(), slot);
-
- Common::OutSaveFile *saveFile = g_system->getSavefileManager()->openForSaving(saveName);
+ Common::OutSaveFile *saveFile = BladeRunner::SaveFileManager::openForSaving(_targetName, slot);
if (saveFile == nullptr || saveFile->err()) {
delete saveFile;
return Common::kReadingFailed;
@@ -1097,6 +1093,7 @@ void BladeRunnerEngine::handleKeyDown(Common::Event &event) {
if (_kia->isOpen()) {
_kia->handleKeyDown(event.kbd);
+ return;
}
if (_spinner->isOpen()) {
diff --git a/engines/bladerunner/detection.cpp b/engines/bladerunner/detection.cpp
index 46285e57bc..5293d76c97 100644
--- a/engines/bladerunner/detection.cpp
+++ b/engines/bladerunner/detection.cpp
@@ -95,8 +95,7 @@ int BladeRunnerMetaEngine::getMaximumSaveSlot() const {
}
void BladeRunnerMetaEngine::removeSaveState(const char *target, int slot) const {
- Common::String filename = Common::String::format("%s.%03d", target, slot);
- g_system->getSavefileManager()->removeSavefile(filename);
+ BladeRunner::SaveFileManager::remove(target, slot);
}
SaveStateDescriptor BladeRunnerMetaEngine::querySaveMetaInfos(const char *target, int slot) const {
diff --git a/engines/bladerunner/module.mk b/engines/bladerunner/module.mk
index 29b6fd2c3a..243f426a44 100644
--- a/engines/bladerunner/module.mk
+++ b/engines/bladerunner/module.mk
@@ -259,6 +259,7 @@ MODULE_OBJS = \
ui/kia_section_help.o \
ui/kia_section_load.o \
ui/kia_section_pogo.o \
+ ui/kia_section_save.o \
ui/kia_section_settings.o \
ui/kia_section_suspects.o \
ui/kia_shapes.o \
diff --git a/engines/bladerunner/savefile.cpp b/engines/bladerunner/savefile.cpp
index fc0073c3ee..55670a1078 100644
--- a/engines/bladerunner/savefile.cpp
+++ b/engines/bladerunner/savefile.cpp
@@ -78,6 +78,21 @@ SaveStateDescriptor SaveFileManager::queryMetaInfos(const Common::String &target
return desc;
}
+Common::InSaveFile *SaveFileManager::openForLoading(const Common::String &target, int slot) {
+ Common::String filename = Common::String::format("%s.%03d", target.c_str(), slot);
+ return g_system->getSavefileManager()->openForLoading(filename);
+}
+
+Common::OutSaveFile *SaveFileManager::openForSaving(const Common::String &target, int slot) {
+ Common::String filename = Common::String::format("%s.%03d", target.c_str(), slot);
+ return g_system->getSavefileManager()->openForSaving(filename);
+}
+
+void SaveFileManager::remove(const Common::String &target, int slot) {
+ Common::String filename = Common::String::format("%s.%03d", target.c_str(), slot);
+ g_system->getSavefileManager()->removeSavefile(filename);
+}
+
bool SaveFileManager::readHeader(Common::SeekableReadStream &in, SaveFileHeader &header, bool skipThumbnail) {
SaveFileReadStream s(in);
diff --git a/engines/bladerunner/savefile.h b/engines/bladerunner/savefile.h
index 64fb0b4999..32b1fc1d49 100644
--- a/engines/bladerunner/savefile.h
+++ b/engines/bladerunner/savefile.h
@@ -25,6 +25,7 @@
#include "common/array.h"
#include "common/memstream.h"
+#include "common/savefile.h"
#include "common/types.h"
#include "graphics/surface.h"
@@ -67,8 +68,14 @@ public:
static SaveStateList list(const Common::String &target);
static SaveStateDescriptor queryMetaInfos(const Common::String &target, int slot);
+ static Common::InSaveFile *openForLoading(const Common::String &target, int slot);
+ static Common::OutSaveFile *openForSaving(const Common::String &target, int slot);
+
+ static void remove(const Common::String &target, int slot);
+
static bool readHeader(Common::SeekableReadStream &in, SaveFileHeader &header, bool skipThumbnail = true);
static bool writeHeader(Common::WriteStream &out, SaveFileHeader &header);
+
};
class SaveFileWriteStream : public Common::WriteStream {
diff --git a/engines/bladerunner/ui/kia.h b/engines/bladerunner/ui/kia.h
index b5be9a7e08..c6d612f0df 100644
--- a/engines/bladerunner/ui/kia.h
+++ b/engines/bladerunner/ui/kia.h
@@ -115,14 +115,15 @@ class KIA {
int _pogoPos;
- Graphics::Surface _thumbnail;
public:
- bool _forceOpen;
+ bool _forceOpen;
- KIALog *_log;
- KIAScript *_script;
- KIAShapes *_shapes;
+ KIALog *_log;
+ KIAScript *_script;
+ KIAShapes *_shapes;
+
+ Graphics::Surface _thumbnail;
public:
KIA(BladeRunnerEngine *vm);
diff --git a/engines/bladerunner/ui/kia_section_clues.h b/engines/bladerunner/ui/kia_section_clues.h
index afd8b67433..1061e637df 100644
--- a/engines/bladerunner/ui/kia_section_clues.h
+++ b/engines/bladerunner/ui/kia_section_clues.h
@@ -45,10 +45,10 @@ class KIASectionClues : public KIASectionBase {
int flags;
};
- UIContainer *_uiContainer;
- UIImagePicker *_buttons;
- UIScrollBox *_cluesScrollBox;
- UIScrollBox *_filterScrollBox;
+ UIContainer *_uiContainer;
+ UIImagePicker *_buttons;
+ UIScrollBox *_cluesScrollBox;
+ UIScrollBox *_filterScrollBox;
bool _isOpen;
bool _debugIntangible;
diff --git a/engines/bladerunner/ui/kia_section_load.cpp b/engines/bladerunner/ui/kia_section_load.cpp
index ba746cab3b..bbc3c74c68 100644
--- a/engines/bladerunner/ui/kia_section_load.cpp
+++ b/engines/bladerunner/ui/kia_section_load.cpp
@@ -35,8 +35,6 @@
#include "common/error.h"
#include "common/system.h"
-#include "engines/savestate.h"
-
namespace BladeRunner {
KIASectionLoad::KIASectionLoad(BladeRunnerEngine *vm) : KIASectionBase(vm) {
@@ -56,34 +54,35 @@ void KIASectionLoad::open() {
_scrollBox->show();
_scrollBox->clearLines();
- SaveStateList saveList = SaveFileManager::list(_vm->getTargetName());
-
- _saveSlotMax = -1;
+ _saveList = SaveFileManager::list(_vm->getTargetName());
- if (!saveList.empty()) {
+ if (!_saveList.empty()) {
_scrollBox->addLine(_vm->_textOptions->getText(36), -1, 4); // Load game:
- for (Common::Array<SaveStateDescriptor>::iterator save = saveList.begin(); save != saveList.end(); save++) {
- _scrollBox->addLine(save->getDescription(), save->getSaveSlot(), 0);
- _saveSlotMax = MAX(_saveSlotMax, save->getSaveSlot());
+ for (uint i = 0; i < _saveList.size(); ++i) {
+ _scrollBox->addLine(_saveList[i].getDescription(), i, 0);
}
_scrollBox->addLine("", -1, 4);
}
+ _newGameEasyLineId = _saveList.size();
+ _newGameMediumLineId = _saveList.size() + 1;
+ _newGameHardLineId = _saveList.size() + 2;
_scrollBox->addLine(_vm->_textOptions->getText(37), -1, 4); // New game:
- _scrollBox->addLine(_vm->_textOptions->getText(20), _saveSlotMax + 1, 0); // Easy
- _scrollBox->addLine(_vm->_textOptions->getText(28), _saveSlotMax + 2, 0); // Medium
- _scrollBox->addLine(_vm->_textOptions->getText(29), _saveSlotMax + 3, 0); // Hard
+ _scrollBox->addLine(_vm->_textOptions->getText(20), _newGameEasyLineId, 0); // Easy
+ _scrollBox->addLine(_vm->_textOptions->getText(28), _newGameMediumLineId, 0); // Medium
+ _scrollBox->addLine(_vm->_textOptions->getText(29), _newGameHardLineId, 0); // Hard
- _hoveredSaveSlot = -1;
+ _hoveredLineId = -1;
_timeLast = _vm->getTotalPlayTime();
_timeLeft = 800;
}
void KIASectionLoad::close() {
_scrollBox->hide();
-
_vm->_kia->playerReset();
+
+ _saveList.clear();
}
void KIASectionLoad::draw(Graphics::Surface &surface){
@@ -91,12 +90,12 @@ void KIASectionLoad::draw(Graphics::Surface &surface){
_uiContainer->draw(surface);
- int selectedSaveSlot = _scrollBox->getSelectedLineData();
+ int selectedLineId = _scrollBox->getSelectedLineData();
- if (_hoveredSaveSlot != selectedSaveSlot) {
- if (selectedSaveSlot >= 0) {
+ if (_hoveredLineId != selectedLineId) {
+ if (selectedLineId >= 0 && selectedLineId < (int)_saveList.size()) {
if (_timeLeft == 0) {
- SaveStateDescriptor desc = SaveFileManager::queryMetaInfos(_vm->getTargetName(), selectedSaveSlot);
+ SaveStateDescriptor desc = SaveFileManager::queryMetaInfos(_vm->getTargetName(), selectedLineId);
const Graphics::Surface *thumbnail = desc.getThumbnail();
if (thumbnail != nullptr) {
_vm->_kia->playImage(*thumbnail);
@@ -106,15 +105,15 @@ void KIASectionLoad::draw(Graphics::Surface &surface){
_vm->_kia->playerReset();
_timeLeft = 800;
}
- _hoveredSaveSlot = selectedSaveSlot;
+ _hoveredLineId = selectedLineId;
}
uint32 now = _vm->getTotalPlayTime();
- if (selectedSaveSlot >= 0) {
+ if (selectedLineId >= 0 && selectedLineId < (int)_saveList.size()) {
if (_timeLeft) {
uint32 timeDiff = now - _timeLast;
if (timeDiff >= _timeLeft) {
- SaveStateDescriptor desc = SaveFileManager::queryMetaInfos(_vm->getTargetName(), selectedSaveSlot);
+ SaveStateDescriptor desc = SaveFileManager::queryMetaInfos(_vm->getTargetName(), _saveList[selectedLineId].getSaveSlot());
const Graphics::Surface *thumbnail = desc.getThumbnail();
if (thumbnail != nullptr) {
_vm->_kia->playImage(*thumbnail);
@@ -144,11 +143,11 @@ void KIASectionLoad::scrollBoxCallback(void *callbackData, void *source, int lin
KIASectionLoad *self = (KIASectionLoad *)callbackData;
if (mouseButton == 0 && source == self->_scrollBox && lineData >= 0) {
- if (lineData == self->_saveSlotMax + 1) {
+ if (lineData == self->_newGameEasyLineId) {
self->_vm->newGame(0);
- } else if (lineData == self->_saveSlotMax + 2) {
+ } else if (lineData == self->_newGameMediumLineId) {
self->_vm->newGame(1);
- } else if (lineData == self->_saveSlotMax + 3) {
+ } else if (lineData == self->_newGameHardLineId) {
self->_vm->newGame(2);
} else {
self->_vm->loadGameState(lineData);
diff --git a/engines/bladerunner/ui/kia_section_load.h b/engines/bladerunner/ui/kia_section_load.h
index 040fc090cc..820b39f5e6 100644
--- a/engines/bladerunner/ui/kia_section_load.h
+++ b/engines/bladerunner/ui/kia_section_load.h
@@ -28,6 +28,8 @@
#include "common/scummsys.h"
#include "common/str.h"
+#include "engines/savestate.h"
+
namespace Graphics {
struct Surface;
}
@@ -38,33 +40,31 @@ class UIContainer;
class UIScrollBox;
class KIASectionLoad : public KIASectionBase {
+ UIContainer *_uiContainer;
+ UIScrollBox *_scrollBox;
- struct Save {
- Common::String name;
- int slotNum;
- };
-
- UIContainer *_uiContainer;
- UIScrollBox *_scrollBox;
+ uint32 _timeLast;
+ uint32 _timeLeft;
- uint32 _timeLast;
- uint32 _timeLeft;
+ SaveStateList _saveList;
- int _hoveredSaveSlot;
- int _saveSlotMax;
+ int _hoveredLineId;
+ int _newGameEasyLineId;
+ int _newGameMediumLineId;
+ int _newGameHardLineId;
public:
KIASectionLoad(BladeRunnerEngine *vm);
~KIASectionLoad();
- void open();
- void close();
+ void open() override;
+ void close() override;
- void draw(Graphics::Surface &surface);
+ void draw(Graphics::Surface &surface) override;
- void handleMouseMove(int mouseX, int mouseY);
- void handleMouseDown(bool mainButton);
- void handleMouseUp(bool mainButton);
+ void handleMouseMove(int mouseX, int mouseY) override;
+ void handleMouseDown(bool mainButton) override;
+ void handleMouseUp(bool mainButton) override;
private:
static void scrollBoxCallback(void *callbackData, void *source, int lineData, int mouseButton);
diff --git a/engines/bladerunner/ui/kia_section_save.cpp b/engines/bladerunner/ui/kia_section_save.cpp
new file mode 100644
index 0000000000..997cb75778
--- /dev/null
+++ b/engines/bladerunner/ui/kia_section_save.cpp
@@ -0,0 +1,407 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "bladerunner/ui/kia_section_save.h"
+
+#include "bladerunner/audio_player.h"
+#include "bladerunner/bladerunner.h"
+#include "bladerunner/font.h"
+#include "bladerunner/game_info.h"
+#include "bladerunner/savefile.h"
+#include "bladerunner/text_resource.h"
+#include "bladerunner/ui/kia.h"
+#include "bladerunner/ui/kia_shapes.h"
+#include "bladerunner/ui/ui_container.h"
+#include "bladerunner/ui/ui_image_picker.h"
+#include "bladerunner/ui/ui_input_box.h"
+#include "bladerunner/ui/ui_scroll_box.h"
+
+#include "common/error.h"
+#include "common/keyboard.h"
+#include "common/system.h"
+
+namespace BladeRunner {
+
+KIASectionSave::KIASectionSave(BladeRunnerEngine *vm) : KIASectionBase(vm) {
+ _uiContainer = new UIContainer(_vm);
+
+ _scrollBox = new UIScrollBox(_vm, scrollBoxCallback, this, 1024, 0, true, Common::Rect(155, 158, 461, 346), Common::Rect(506, 160, 506, 350));
+ _uiContainer->add(_scrollBox);
+
+ _inputBox = new UIInputBox(_vm, inputBoxCallback, this, Common::Rect(155, 367, 461, 376), 41, "");
+ _uiContainer->add(_inputBox);
+ _inputBox->hide();
+
+ _buttons = new UIImagePicker(_vm, 3);
+
+ _mouseX = 0;
+ _mouseY = 0;
+
+ _selectedLineId = -1;
+ _hoveredLineId = -1;
+ _newSaveLineId = -1;
+}
+
+KIASectionSave::~KIASectionSave() {
+ delete _buttons;
+
+ _uiContainer->clear();
+ delete _inputBox;
+ delete _scrollBox;
+ delete _uiContainer;
+}
+
+void KIASectionSave::open() {
+ _scheduledSwitch = false;
+ _state = kStateNormal;
+
+ _buttons->resetImages();
+ _buttons->defineImage(
+ 0,
+ Common::Rect(460, 366, 497, 402),
+ _vm->_kia->_shapes->get(82),
+ _vm->_kia->_shapes->get(83),
+ _vm->_kia->_shapes->get(84),
+ _vm->_textOptions->getText(22) // Save
+ );
+
+ _scrollBox->show();
+
+ _saveList = SaveFileManager::list(_vm->getTargetName());
+
+ bool ableToSaveGame = true;
+
+ _newSaveLineId = _saveList.size();
+
+ if (!_saveList.empty() || ableToSaveGame) {
+
+ _buttons->activate(nullptr, nullptr, nullptr, onButtonPressed, this);
+ _inputBox->show();
+
+ _scrollBox->clearLines();
+
+ if (ableToSaveGame) {
+ _scrollBox->addLine(_vm->_textOptions->getText(23), _newSaveLineId, 0);
+ }
+
+ for (uint i = 0; i < _saveList.size(); ++i) {
+ _scrollBox->addLine(_saveList[i].getDescription(), i, 0);
+ }
+
+ if (ableToSaveGame) {
+ // New save
+ _selectedLineId = _newSaveLineId;
+ _inputBox->setText("");
+ } else {
+ // Overwrite first save
+ _selectedLineId = 0;
+ _inputBox->setText(_saveList[_selectedLineId].getDescription());
+ }
+
+ _scrollBox->setFlags(_selectedLineId, 8);
+ }
+
+ _hoveredLineId = -1;
+ _timeLast = _vm->getTotalPlayTime();
+ _timeLeft = 800;
+}
+
+void KIASectionSave::close() {
+ _inputBox->hide();
+ _scrollBox->hide();
+ _buttons->deactivate();
+
+ _vm->_kia->playerReset();
+
+ _saveList.clear();
+}
+
+void KIASectionSave::draw(Graphics::Surface &surface){
+ _vm->_kia->_shapes->get(69)->draw(surface, 501, 123);
+ _buttons->draw(surface);
+
+ if (_state == kStateNormal) {
+ const char *textChooseSlot = _vm->_textOptions->getText(24); // Choose a slot ...
+ int textChooseSlotWidth = _vm->_mainFont->getTextWidth(textChooseSlot);
+ _vm->_mainFont->drawColor(textChooseSlot, surface, 308 - textChooseSlotWidth / 2, 143, 0x7BB8);
+
+ // Original game shows warnings/error here, but we don't have any
+
+ const char *textTypeName = _vm->_textOptions->getText(24); // Type a name ...
+ int textTypeNameWidth = _vm->_mainFont->getTextWidth(textTypeName);
+ _vm->_mainFont->drawColor(textTypeName, surface, 308 - textTypeNameWidth / 2, 352, 0x7BB8);
+
+ _uiContainer->draw(surface);
+ } else if (_state == kStateOverwrite) {
+ surface.fillRect(Common::Rect(155, 230, 462, 239), 0x28E4);
+
+ const Common::String &saveName = _saveList[_selectedLineId].getDescription();
+ int saveNameWidth = _vm->_mainFont->getTextWidth(saveName);
+ _vm->_mainFont->drawColor(saveName, surface, 308 - saveNameWidth / 2, 230, 0x7751);
+
+ const char *textOverwrite = _vm->_textOptions->getText(35); // Overwrite previously saved game?
+ int textOverwriteWidth = _vm->_mainFont->getTextWidth(textOverwrite);
+ _vm->_mainFont->drawColor(textOverwrite, surface, 308 - textOverwriteWidth / 2, 240, 0x7BB8);
+ } else if (_state == kStateDelete) {
+ surface.fillRect(Common::Rect(155, 230, 462, 239), 0x28E4);
+
+ const Common::String &saveName = _saveList[_selectedLineId].getDescription();
+ int saveNameWidth = _vm->_mainFont->getTextWidth(saveName); // Delete this game?
+ _vm->_mainFont->drawColor(saveName, surface, 308 - saveNameWidth / 2, 230, 0x7751);
+
+ const char *textDelete = _vm->_textOptions->getText(40);
+ int textDeleteWidth = _vm->_mainFont->getTextWidth(textDelete);
+ _vm->_mainFont->drawColor(textDelete, surface, 308 - textDeleteWidth / 2, 240, 0x7BB8);
+ }
+
+ int selectedLineId = _scrollBox->getSelectedLineData();
+
+ if (selectedLineId != _hoveredLineId) {
+ if (selectedLineId >= 0 && selectedLineId < (int)_saveList.size()) {
+ if (_timeLeft == 0) {
+ SaveStateDescriptor desc = SaveFileManager::queryMetaInfos(_vm->getTargetName(), selectedLineId);
+ const Graphics::Surface *thumbnail = desc.getThumbnail();
+ if (thumbnail != nullptr) {
+ _vm->_kia->playImage(*thumbnail);
+ }
+ }
+ } else {
+ _vm->_kia->playerReset();
+ _timeLeft = 800;
+ }
+ _hoveredLineId = selectedLineId;
+ }
+
+ uint32 now = _vm->getTotalPlayTime();
+ if (selectedLineId >= 0 && selectedLineId < (int)_saveList.size()) {
+ if (_timeLeft) {
+ uint32 timeDiff = now - _timeLast;
+ if (timeDiff >= _timeLeft) {
+ SaveStateDescriptor desc = SaveFileManager::queryMetaInfos(_vm->getTargetName(), _saveList[selectedLineId].getSaveSlot());
+ const Graphics::Surface *thumbnail = desc.getThumbnail();
+ if (thumbnail != nullptr) {
+ _vm->_kia->playImage(*thumbnail);
+ }
+ } else {
+ _timeLeft -= timeDiff;
+ }
+ }
+ }
+
+ _timeLast = now;
+ _buttons->drawTooltip(surface, _mouseX, _mouseY);
+}
+
+void KIASectionSave::handleKeyUp(const Common::KeyState &kbd) {
+ if (_state == kStateNormal) {
+ _uiContainer->handleKeyUp(kbd);
+ } else if (_state == kStateOverwrite) {
+ if (kbd.keycode == Common::KEYCODE_RETURN) {
+ save();
+ changeState(kStateNormal);
+ }
+ } else if (_state == kStateDelete) {
+ if (kbd.keycode == Common::KEYCODE_RETURN) {
+ deleteSave();
+ changeState(kStateNormal);
+ }
+ }
+}
+
+void KIASectionSave::handleKeyDown(const Common::KeyState &kbd) {
+ if (_state == kStateNormal) {
+ if (kbd.keycode == Common::KEYCODE_DELETE && _selectedLineId != _newSaveLineId) {
+ changeState(kStateDelete);
+ }
+
+ _uiContainer->handleKeyDown(kbd);
+ }
+}
+
+void KIASectionSave::handleMouseMove(int mouseX, int mouseY) {
+ _mouseX = mouseX;
+ _mouseY = mouseY;
+
+ _buttons->handleMouseAction(_mouseX, _mouseY, false, false, false);
+
+ if (_state == kStateNormal) {
+ _uiContainer->handleMouseMove(_mouseX, _mouseY);
+ }
+}
+
+void KIASectionSave::handleMouseDown(bool mainButton) {
+ if (mainButton) {
+ if (_state == kStateNormal) {
+ _uiContainer->handleMouseDown(false);
+ }
+
+ _buttons->handleMouseAction(_mouseX, _mouseY, true, false, false);
+ }
+}
+
+void KIASectionSave::handleMouseUp(bool mainButton) {
+ if (mainButton) {
+ _buttons->handleMouseAction(_mouseX, _mouseY, false, true, false);
+
+ if (_state == kStateNormal) {
+ _uiContainer->handleMouseUp(false);
+ }
+ }
+}
+
+void KIASectionSave::scrollBoxCallback(void *callbackData, void *source, int lineData, int mouseButton) {
+ KIASectionSave *self = (KIASectionSave *)callbackData;
+
+ if (mouseButton == 0 && source == self->_scrollBox && lineData >= 0 && lineData <= (int)self->_saveList.size()) {
+ self->_scrollBox->resetFlags(self->_selectedLineId, 8);
+ self->_selectedLineId = lineData;
+ self->_scrollBox->setFlags(self->_selectedLineId, 8);
+
+ if (self->_selectedLineId == self->_newSaveLineId) {
+ self->_inputBox->setText("");
+ } else {
+ self->_inputBox->setText(self->_saveList[self->_selectedLineId].getDescription());
+ }
+
+ self->_vm->_audioPlayer->playAud(self->_vm->_gameInfo->getSfxTrack(131), 40, 0, 0, 50, 0);
+ self->_vm->_kia->resume();
+ }
+}
+
+void KIASectionSave::inputBoxCallback(void *callbackData, void *source) {
+ KIASectionSave *self = (KIASectionSave *)callbackData;
+ if (source == self->_inputBox) {
+ if (self->_selectedLineId == self->_newSaveLineId) {
+ self->save();
+ } else {
+ self->changeState(kStateOverwrite);
+ }
+ }
+}
+
+void KIASectionSave::onButtonPressed(int buttonId, void *callbackData) {
+ KIASectionSave *self = (KIASectionSave *)callbackData;
+
+ if (buttonId == 0) {
+ if (self->_selectedLineId == self->_newSaveLineId)
+ {
+ self->save();
+ }
+ else
+ {
+ self->changeState(kStateOverwrite);
+ }
+ } else if (buttonId == 1) {
+ self->changeState(kStateNormal);
+ self->_vm->_audioPlayer->playAud(self->_vm->_gameInfo->getSfxTrack(134), 90, -50, -50, 50, 0);
+ } else if (buttonId == 2) {
+ if (self->_state == kStateOverwrite)
+ {
+ self->save();
+ }
+ else if (self->_state == kStateDelete)
+ {
+ self->deleteSave();
+ }
+ }
+}
+
+void KIASectionSave::changeState(State state) {
+ _state = state;
+ if (state == kStateNormal) {
+ _buttons->resetImages();
+ _buttons->defineImage(
+ 0,
+ Common::Rect(460, 366, 497, 402),
+ _vm->_kia->_shapes->get(82),
+ _vm->_kia->_shapes->get(83),
+ _vm->_kia->_shapes->get(84),
+ _vm->_textOptions->getText(22) // Save
+ );
+ } else {
+ _buttons->resetImages();
+ _buttons->defineImage(
+ 1,
+ Common::Rect(318, 260, 357, 299),
+ _vm->_kia->_shapes->get(126),
+ _vm->_kia->_shapes->get(127),
+ _vm->_kia->_shapes->get(128),
+ _vm->_textOptions->getText(38) // No
+ );
+ _buttons->defineImage(
+ 2,
+ Common::Rect(258, 260, 297, 299),
+ _vm->_kia->_shapes->get(129),
+ _vm->_kia->_shapes->get(130),
+ _vm->_kia->_shapes->get(131),
+ _vm->_textOptions->getText(39) // Yes
+ );
+ _vm->_audioPlayer->playAud(_vm->_gameInfo->getSfxTrack(135), 90, 0, 0, 50, 0);
+ }
+}
+
+void KIASectionSave::save() {
+ int slot = -1;
+
+ if (_selectedLineId < (int)_saveList.size()) {
+ slot = _saveList[_selectedLineId].getSaveSlot();
+ } else {
+ // Find first available save slot
+ for (int i = 0; i < (int)_saveList.size(); ++i) {
+ if (_saveList[i].getSaveSlot() != i) {
+ slot = i;
+ break;
+ }
+ }
+
+ if (slot == -1) {
+ slot = _saveList.size();
+ }
+ }
+
+ Common::OutSaveFile *saveFile = BladeRunner::SaveFileManager::openForSaving(_vm->getTargetName(), slot);
+ if (saveFile == nullptr || saveFile->err()) {
+ delete saveFile;
+ }
+
+ BladeRunner::SaveFileHeader header;
+ header._name = _inputBox->getText();
+
+ BladeRunner::SaveFileManager::writeHeader(*saveFile, header);
+
+ _vm->saveGame(*saveFile, _vm->_kia->_thumbnail);
+
+ saveFile->finalize();
+
+ delete saveFile;
+
+ _vm->_audioPlayer->playAud(_vm->_gameInfo->getSfxTrack(513), 90, 0, 0, 50, 0);
+
+ _scheduledSwitch = true;
+}
+void KIASectionSave::deleteSave() {
+ BladeRunner::SaveFileManager::remove(_vm->getTargetName(), _saveList[_selectedLineId].getSaveSlot());
+ close();
+ open();
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/ui/kia_section_save.h b/engines/bladerunner/ui/kia_section_save.h
index 5e2f5f26ac..d3af65288e 100644
--- a/engines/bladerunner/ui/kia_section_save.h
+++ b/engines/bladerunner/ui/kia_section_save.h
@@ -25,13 +25,72 @@
#include "bladerunner/ui/kia_section_base.h"
+#include "common/scummsys.h"
+#include "common/str.h"
+
+#include "engines/savestate.h"
+
+namespace Graphics {
+struct Surface;
+}
+
namespace BladeRunner {
+class UIContainer;
+class UIScrollBox;
+class UIInputBox;
+class UIImagePicker;
+
class KIASectionSave : public KIASectionBase {
+ enum State {
+ kStateNormal = 0,
+ kStateOverwrite = 1,
+ kStateDelete = 2
+ };
+
+ UIContainer *_uiContainer;
+ UIScrollBox *_scrollBox;
+ UIInputBox *_inputBox;
+ UIImagePicker *_buttons;
+
+ uint32 _timeLast;
+ uint32 _timeLeft;
+
+ SaveStateList _saveList;
+
+ State _state;
+
+ int _mouseX;
+ int _mouseY;
+
+ int _hoveredLineId;
+ int _selectedLineId;
+ int _newSaveLineId;
public:
- KIASectionSave(BladeRunnerEngine *vm): KIASectionBase(vm){}
+ KIASectionSave(BladeRunnerEngine *vm);
+ ~KIASectionSave();
+
+ void open() override;
+ void close() override;
+
+ void draw(Graphics::Surface &surface) override;
+
+ void handleKeyUp(const Common::KeyState &kbd) override;
+ void handleKeyDown(const Common::KeyState &kbd) override;
+ void handleMouseMove(int mouseX, int mouseY) override;
+ void handleMouseDown(bool mainButton) override;
+ void handleMouseUp(bool mainButton) override;
+
+private:
+ static void scrollBoxCallback(void *callbackData, void *source, int lineData, int mouseButton);
+ static void inputBoxCallback(void *callbackData, void *source);
+
+ static void onButtonPressed(int buttonId, void *callbackData);
+ void changeState(State state);
+ void save();
+ void deleteSave();
};
} // End of namespace BladeRunner
diff --git a/engines/bladerunner/ui/ui_component.h b/engines/bladerunner/ui/ui_component.h
index c3a8c21b21..aae944d3ad 100644
--- a/engines/bladerunner/ui/ui_component.h
+++ b/engines/bladerunner/ui/ui_component.h
@@ -54,6 +54,7 @@ public:
virtual void handleMouseDown(bool alternateButton) {}
virtual void handleMouseUp(bool alternateButton) {}
virtual void handleKeyUp(const Common::KeyState &kbd) {}
+ virtual void handleKeyDown(const Common::KeyState &kbd) {}
};
} // End of namespace BladeRunner
diff --git a/engines/bladerunner/ui/ui_container.cpp b/engines/bladerunner/ui/ui_container.cpp
index e84809d379..34a8cecfb1 100644
--- a/engines/bladerunner/ui/ui_container.cpp
+++ b/engines/bladerunner/ui/ui_container.cpp
@@ -56,6 +56,12 @@ void UIContainer::handleKeyUp(const Common::KeyState &kbd) {
}
}
+void UIContainer::handleKeyDown(const Common::KeyState &kbd) {
+ for (Common::Array<UIComponent*>::iterator component = _components.begin(); component != _components.end(); component++) {
+ (*component)->handleKeyDown(kbd);
+ }
+}
+
void UIContainer::add(UIComponent *component) {
_components.push_back(component);
}
diff --git a/engines/bladerunner/ui/ui_container.h b/engines/bladerunner/ui/ui_container.h
index 8e49d36dda..6d5a20765e 100644
--- a/engines/bladerunner/ui/ui_container.h
+++ b/engines/bladerunner/ui/ui_container.h
@@ -43,6 +43,7 @@ public:
void handleMouseDown(bool alternateButton);
void handleMouseUp(bool alternateButton);
void handleKeyUp(const Common::KeyState &kbd);
+ void handleKeyDown(const Common::KeyState &kbd);
void add(UIComponent *component);
void clear();
diff --git a/engines/bladerunner/ui/ui_input_box.cpp b/engines/bladerunner/ui/ui_input_box.cpp
index fb46ec8d34..466238f8d3 100644
--- a/engines/bladerunner/ui/ui_input_box.cpp
+++ b/engines/bladerunner/ui/ui_input_box.cpp
@@ -40,7 +40,6 @@ UIInputBox::UIInputBox(BladeRunnerEngine *vm, UIComponentCallback *valueChangedC
_rect = rect;
_maxLength = maxLength;
- _length = 0;
setText(text);
_cursorIsVisible = false;
@@ -85,11 +84,9 @@ void UIInputBox::hide() {
void UIInputBox::handleKeyUp(const Common::KeyState &kbd) {
if (_isVisible) {
- if (charIsValid(kbd)) {
- _text += kbd.ascii;
- } else if (kbd.keycode == Common::KEYCODE_BACKSPACE) {
- _text.deleteLastChar();
- } else if (kbd.keycode == Common::KEYCODE_RETURN && !_text.empty()) {
+ // Check for "Enter" in keyUp instead of in keyDown as keyDown is repeating characters
+ // and that can screw up UX (which is not great in the original game either).
+ if (kbd.keycode == Common::KEYCODE_RETURN && !_text.empty()) {
if (_valueChangedCallback) {
_valueChangedCallback(_callbackData, this);
}
@@ -97,6 +94,16 @@ void UIInputBox::handleKeyUp(const Common::KeyState &kbd) {
}
}
+void UIInputBox::handleKeyDown(const Common::KeyState &kbd) {
+ if (_isVisible) {
+ if (charIsValid(kbd) && _text.size() < _maxLength) {
+ _text += kbd.ascii;
+ } else if (kbd.keycode == Common::KEYCODE_BACKSPACE) {
+ _text.deleteLastChar();
+ }
+ }
+}
+
bool UIInputBox::charIsValid(const Common::KeyState &kbd) {
return kbd.ascii >= ' '
&& kbd.ascii != '<'
diff --git a/engines/bladerunner/ui/ui_input_box.h b/engines/bladerunner/ui/ui_input_box.h
index 4dfe0785fc..e3aee9996e 100644
--- a/engines/bladerunner/ui/ui_input_box.h
+++ b/engines/bladerunner/ui/ui_input_box.h
@@ -37,8 +37,7 @@ class UIInputBox : public UIComponent {
bool _isVisible;
Common::Rect _rect;
- int _maxLength;
- int _length;
+ uint _maxLength;
Common::String _text;
bool _cursorIsVisible;
@@ -48,7 +47,7 @@ class UIInputBox : public UIComponent {
public:
UIInputBox(BladeRunnerEngine *vm, UIComponentCallback *valueChangedCallback, void *callbackData, Common::Rect rect, int maxLength, const Common::String &text);
- void draw(Graphics::Surface &surface);
+ void draw(Graphics::Surface &surface) override;
void setText(const Common::String &text);
const Common::String &getText();
@@ -56,7 +55,8 @@ public:
void show();
void hide();
- void handleKeyUp(const Common::KeyState &kbd);
+ void handleKeyUp(const Common::KeyState &kbd) override;
+ void handleKeyDown(const Common::KeyState &kbd) override;
private:
bool charIsValid(const Common::KeyState &kbd);