ResidualVM logo ResidualVM website - Forums - Contact us BuildBot - Doxygen - Wiki curved edge

saveloadmenu.cpp

Go to the documentation of this file.
00001 /* ResidualVM - A 3D game interpreter
00002  *
00003  * ResidualVM is the legal property of its developers, whose names
00004  * are too numerous to list here. Please refer to the AUTHORS
00005  * file distributed with this source distribution.
00006  *
00007  * This program is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU General Public License
00009  * as published by the Free Software Foundation; either version 2
00010  * of the License, or (at your option) any later version.
00011  *
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00020  *
00021  */
00022 
00023 #include "engines/stark/ui/menu/saveloadmenu.h"
00024 
00025 #include "engines/stark/services/services.h"
00026 #include "engines/stark/services/userinterface.h"
00027 #include "engines/stark/services/stateprovider.h"
00028 #include "engines/stark/services/global.h"
00029 #include "engines/stark/services/settings.h"
00030 #include "engines/stark/services/gamechapter.h"
00031 #include "engines/stark/services/gamemessage.h"
00032 
00033 #include "engines/stark/gfx/driver.h"
00034 #include "engines/stark/gfx/texture.h"
00035 #include "engines/stark/gfx/surfacerenderer.h"
00036 
00037 #include "engines/stark/stark.h"
00038 #include "engines/stark/savemetadata.h"
00039 
00040 #include "engines/engine.h"
00041 
00042 #include "common/config-manager.h"
00043 #include "common/savefile.h"
00044 
00045 #include "gui/message.h"
00046 
00047 namespace Stark {
00048 
00049 const Color SaveDataWidget::_outlineColor = Color(0x1E, 0x1E, 0x96);
00050 const Color SaveDataWidget::_textColor    = Color(0x5C, 0x48, 0x3D);
00051 
00052 SaveLoadMenuScreen::SaveLoadMenuScreen(Gfx::Driver *gfx, Cursor *cursor, Screen::Name screenName) :
00053         StaticLocationScreen(gfx, cursor, "LoadSaveLocation", screenName) {
00054 }
00055 
00056 SaveLoadMenuScreen::~SaveLoadMenuScreen() {
00057 }
00058 
00059 void SaveLoadMenuScreen::open() {
00060     StaticLocationScreen::open();
00061 
00062     _page = StarkSettings->getIntSetting(Settings::kSaveLoadPage);
00063 
00064     _widgets.push_back(new StaticLocationWidget(
00065             "loadsavebg",
00066             nullptr,
00067             nullptr));
00068     
00069     _widgets.push_back(new StaticLocationWidget(
00070             "back to index",
00071             CLICK_HANDLER(SaveLoadMenuScreen, backHandler),
00072             nullptr));
00073     _widgets.back()->setupSounds(0, 1);
00074     
00075     _widgets.push_back(new StaticLocationWidget(
00076             "Cancel",
00077             CLICK_HANDLER(SaveLoadMenuScreen, backHandler),
00078             nullptr));
00079     _widgets.back()->setupSounds(0, 1);
00080     
00081     _widgets.push_back(new StaticLocationWidget(
00082             "SaveText",
00083             nullptr,
00084             nullptr));
00085     
00086     _widgets.push_back(new StaticLocationWidget(
00087             "LoadText",
00088             nullptr,
00089             nullptr));
00090     
00091     _widgets.push_back(new StaticLocationWidget(
00092             "Back",
00093             CLICK_HANDLER(SaveLoadMenuScreen, prevPageHandler),
00094             nullptr));
00095     _widgets.back()->setupSounds(0, 1);
00096     _widgets.back()->setTextColor(Color(0, 0, 0));
00097     _widgets.back()->setVisible(_page > 0);
00098     
00099     _widgets.push_back(new StaticLocationWidget(
00100             "Next",
00101             CLICK_HANDLER(SaveLoadMenuScreen, nextPageHandler),
00102             nullptr));
00103     _widgets.back()->setupSounds(0, 1);
00104     _widgets.back()->setTextColor(Color(0, 0, 0));
00105     _widgets.back()->setVisible(_page < 10);
00106 
00107     loadSaveData(_page);
00108 }
00109 
00110 void SaveLoadMenuScreen::close() {
00111     ConfMan.flushToDisk();
00112     StaticLocationScreen::close();
00113 }
00114 
00115 void SaveLoadMenuScreen::backHandler() {
00116     StarkUserInterface->backPrevScreen();
00117 }
00118 
00119 void SaveLoadMenuScreen::checkError(Common::Error error) {
00120     if (error.getCode() != Common::kNoError) {
00121         GUI::MessageDialog dialog(error.getDesc());
00122         dialog.runModal();
00123     }
00124 }
00125 
00126 void SaveLoadMenuScreen::removeSaveDataWidgets() {
00127     assert(_widgets.size() == 7 + _slotPerPage);
00128 
00129     for (int i = 0; i < _slotPerPage; ++i) {
00130         delete _widgets.back();
00131         _widgets.pop_back();
00132     }
00133 }
00134 
00135 void SaveLoadMenuScreen::loadSaveData(int page) {
00136     for (int i = 0; i < _slotPerPage; ++i) {
00137         _widgets.push_back(new SaveDataWidget(i + page * _slotPerPage, _gfx, this));
00138     }
00139 }
00140 
00141 void SaveLoadMenuScreen::changePage(int page) {
00142     assert(page >= 0 && page <= _maxPage);
00143 
00144     removeSaveDataWidgets();
00145     loadSaveData(page);
00146 
00147     _widgets[kWidgetBack]->setVisible(page > 0);
00148     _widgets[kWidgetNext]->setVisible(page < _maxPage);
00149 
00150     StarkSettings->setIntSetting(Settings::kSaveLoadPage, page);
00151     _page = page;
00152 }
00153 
00154 void SaveMenuScreen::open() {
00155     SaveLoadMenuScreen::open();
00156     _widgets[kWidgetLoadText]->setVisible(false);
00157 }
00158 
00159 void SaveMenuScreen::onWidgetSelected(SaveDataWidget *widget) {
00160     if (widget->hasSave()) {
00161         _slotToSaveAfterConfirm = widget;
00162 
00163         Common::String format = StarkGameMessage->getTextByKey(GameMessage::kOverwriteSave);
00164         Common::String prompt = Common::String::format(format.c_str(), widget->getName().c_str());
00165 
00166         StarkUserInterface->confirm(prompt, this, &SaveMenuScreen::saveConfirmSlot);
00167     } else {
00168         saveGameToSlot(widget);
00169     }
00170 }
00171 
00172 void SaveMenuScreen::saveConfirmSlot() {
00173     assert(_slotToSaveAfterConfirm);
00174 
00175     saveGameToSlot(_slotToSaveAfterConfirm);
00176     _slotToSaveAfterConfirm = nullptr;
00177 }
00178 
00179 void SaveMenuScreen::saveGameToSlot(SaveDataWidget *widget) {
00180     checkError(g_engine->saveGameState(widget->getSlot(), StarkGameChapter->getCurrentChapterTitle()));
00181 
00182     // Freeze the screen for a while to let the user notice the change
00183     widget->loadSaveDataElements();
00184     render();
00185     StarkGfx->flipBuffer();
00186     g_system->delayMillis(100);
00187     render();
00188     StarkGfx->flipBuffer();
00189 
00190     StarkUserInterface->backPrevScreen();
00191 }
00192 
00193 void LoadMenuScreen::open() {
00194     SaveLoadMenuScreen::open();
00195     _widgets[kWidgetSaveText]->setVisible(false);
00196 }
00197 
00198 void LoadMenuScreen::onWidgetSelected(SaveDataWidget *widget) {
00199     if (!StarkGlobal->getCurrent()) {
00200         checkError(g_engine->loadGameState(widget->getSlot()));
00201     } else {
00202         _slotToLoadAfterConfirm = widget->getSlot();
00203         StarkUserInterface->confirm(GameMessage::kEndAndLoad, this, &LoadMenuScreen::loadConfirmSlot);
00204     }
00205 }
00206 
00207 void LoadMenuScreen::loadConfirmSlot() {
00208     assert(_slotToLoadAfterConfirm >= 0);
00209 
00210     checkError(g_engine->loadGameState(_slotToLoadAfterConfirm));
00211     _slotToLoadAfterConfirm = -1;
00212 }
00213 
00214 SaveDataWidget::SaveDataWidget(int slot, Gfx::Driver *gfx, SaveLoadMenuScreen *screen) :
00215         StaticLocationWidget(nullptr, nullptr, nullptr),
00216         _slot(slot),
00217         _screen(screen),
00218         _thumbWidth(StarkUserInterface->kThumbnailWidth),
00219         _thumbHeight(StarkUserInterface->kThumbnailHeight),
00220         _texture(gfx->createTexture()),
00221         _outline(gfx->createTexture()),
00222         _surfaceRenderer(gfx->createSurfaceRenderer()),
00223         _textDesc(gfx),
00224         _textTime(gfx),
00225         _isMouseHovered(false),
00226         _hasSave(false),
00227         _name() {
00228     // Load from the save data
00229     loadSaveDataElements();
00230 
00231     _textDesc.setColor(_textColor);
00232     _textDesc.setFont(FontProvider::kCustomFont, 3);
00233 
00234     _textTime.setColor(_textColor);
00235     _textTime.setFont(FontProvider::kCustomFont, 3);
00236 
00237     Graphics::PixelFormat pixelFormat = Gfx::Driver::getRGBAPixelFormat();
00238     uint32 outlineColor = pixelFormat.ARGBToColor(
00239             _outlineColor.a, _outlineColor.r, _outlineColor.g, _outlineColor.b
00240     );
00241 
00242     // Create the outline texture
00243     Graphics::Surface lineSurface;
00244     lineSurface.create(_thumbWidth, _thumbHeight, pixelFormat);
00245     lineSurface.drawThickLine(0, 0, _thumbWidth - 1, 0, 2, 2, outlineColor);
00246     lineSurface.drawThickLine(0, 0, 0, _thumbHeight - 1, 2, 2, outlineColor);
00247     lineSurface.drawThickLine(_thumbWidth - 2, 0, _thumbWidth - 2, _thumbHeight - 2, 2, 2, outlineColor);
00248     lineSurface.drawThickLine(0, _thumbHeight - 2, _thumbWidth - 2, _thumbHeight - 2, 2, 2, outlineColor);
00249 
00250     _outline->update(&lineSurface);
00251     lineSurface.free();
00252 
00253     // Set the position
00254     _thumbPos.x = 41 + (_slot % SaveLoadMenuScreen::_slotPerRow) * (_thumbWidth + 39);
00255     _thumbPos.y = 61 + (_slot % SaveLoadMenuScreen::_slotPerPage / SaveLoadMenuScreen::_slotPerColumn) * (_thumbHeight + 38);
00256 
00257     _textDescPos.x = _thumbPos.x;
00258     _textDescPos.y = _thumbPos.y + _thumbHeight + 2;
00259 
00260     _textTimePos.x = _thumbPos.x;
00261     _textTimePos.y = _textDescPos.y + 12;
00262 }
00263 
00264 SaveDataWidget::~SaveDataWidget() {
00265     delete _texture;
00266     delete _outline;
00267     delete _surfaceRenderer;
00268 }
00269 
00270 void SaveDataWidget::render() {
00271     _surfaceRenderer->render(_texture, _thumbPos);
00272     _textDesc.render(_textDescPos);
00273     _textTime.render(_textTimePos);
00274     if (_isMouseHovered) {
00275         _surfaceRenderer->render(_outline, _thumbPos);
00276     }
00277 }
00278 
00279 bool SaveDataWidget::isMouseInside(const Common::Point &mousePos) const {
00280     return mousePos.x >= _thumbPos.x && mousePos.x <= _thumbPos.x + _thumbWidth &&
00281            mousePos.y >= _thumbPos.y && mousePos.y <= _thumbPos.y + _thumbHeight;
00282 }
00283 
00284 void SaveDataWidget::onClick() {
00285     StaticLocationWidget::onClick();
00286     _screen->onWidgetSelected(this);
00287 }
00288 
00289 void SaveDataWidget::onMouseMove(const Common::Point &mousePos) {
00290     StaticLocationWidget::onMouseMove(mousePos);
00291     _isMouseHovered = isMouseInside(mousePos);
00292 }
00293 
00294 void SaveDataWidget::onScreenChanged() {
00295     StaticLocationWidget::onScreenChanged();
00296     _textDesc.resetTexture();
00297     _textTime.resetTexture();
00298 }
00299 
00300 void SaveDataWidget::loadSaveDataElements() {
00301     Common::String filename = StarkEngine::formatSaveName(ConfMan.getActiveDomainName().c_str(), _slot);
00302     Common::InSaveFile *save = g_system->getSavefileManager()->openForLoading(filename);
00303     if (save) {
00304         _hasSave = true;
00305 
00306         SaveMetadata metadata;
00307         StateReadStream stream(save);
00308         Common::ErrorCode metadataErrorCode = metadata.read(&stream, filename);
00309         if (metadataErrorCode != Common::kNoError) {
00310             error("Unable to read save metadata with error code %d.", metadataErrorCode);
00311         }
00312 
00313         // Obtain the thumbnail
00314         if (metadata.version >= 9) {
00315             Graphics::Surface *thumb = metadata.readGameScreenThumbnail(&stream);
00316             _texture->update(thumb);
00317             thumb->free();
00318             delete thumb;
00319         }
00320 
00321         // Obtain the text
00322         Common::String desc = metadata.description;
00323         Common::String time = Common::String::format("%02d:%02d:%02d %02d/%02d/%02d",
00324                 metadata.saveHour, metadata.saveMinute, metadata.saveSecond,
00325                 metadata.saveMonth, metadata.saveDay, metadata.saveYear % 100);
00326 
00327         _textDesc.setText(desc);
00328         _textTime.setText(time);
00329         _name = desc + " " + time;
00330     } else {
00331         _hasSave = false;
00332         setVisible(_screen->isSaveMenu());
00333     }
00334 }
00335 
00336 } // End of namespace Stark


Generated on Sat Feb 16 2019 05:01:03 for ResidualVM by doxygen 1.7.1
curved edge   curved edge