File: mainmenu.cpp

package info (click to toggle)
scummvm 2.9.1%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 450,580 kB
  • sloc: cpp: 4,299,825; asm: 28,322; python: 12,901; sh: 11,302; java: 9,289; xml: 7,895; perl: 2,639; ansic: 2,465; yacc: 1,670; javascript: 1,020; makefile: 933; lex: 578; awk: 275; objc: 82; sed: 11; php: 1
file content (279 lines) | stat: -rw-r--r-- 7,485 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
/* 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 {

MainMenu::~MainMenu() {
	for (auto *button : _buttons) {
		delete button;
	}
}

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");
	}

	for (uint i = 0; i < _menuData->_buttonDests.size(); ++i) {
		_buttons.push_back(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.back()->init();
		_buttons.back()->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);
					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