1 /* ScummVM - Graphic Adventure Engine
2  *
3  * ScummVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the COPYRIGHT
5  * file distributed with this source distribution.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  */
22 
23 #ifndef TWINE_MENU_H
24 #define TWINE_MENU_H
25 
26 #include "twine/twine.h"
27 #include "twine/text.h"
28 
29 namespace TwinE {
30 
31 #define MAX_BUTTONS 10
32 #define PLASMA_WIDTH 320
33 #define PLASMA_HEIGHT 50
34 #define kQuitEngine 9998
35 
36 class BodyData;
37 class SpriteData;
38 
39 class MenuSettings {
40 private:
41 	enum MenuSettingsType {
42 		// button number
43 		MenuSettings_CurrentLoadedButton = 0,
44 		// is used to calc the height where the first button will appear
45 		MenuSettings_NumberOfButtons = 1,
46 		MenuSettings_ButtonsBoxHeight = 2,
47 		MenuSettings_HeaderEnd = 3, // TODO: unknown
48 		MenuSettings_FirstButtonState = 4,
49 		MenuSettings_FirstButton = 5
50 	};
51 
52 	int16 _settings[4 + MAX_BUTTONS * 2] {0};
53 	Common::String _buttonTexts[MAX_BUTTONS];
54 	int8 _activeButtonIdx = 0;
55 
56 public:
getButtonTextId(int buttonIndex)57 	TextId getButtonTextId(int buttonIndex) const {
58 		return (TextId)_settings[MenuSettings_FirstButton + buttonIndex * 2];
59 	}
60 
reset()61 	void reset() {
62 		for (int32 i = 0; i < MAX_BUTTONS; ++i) {
63 			_buttonTexts[i] = "";
64 		}
65 		_settings[MenuSettings_NumberOfButtons] = 0;
66 		setButtonsBoxHeight(0);
67 		setActiveButton(0);
68 	}
69 
70 	// used to calc the height where the first button will appear
setButtonsBoxHeight(int16 height)71 	void setButtonsBoxHeight(int16 height) {
72 		_settings[MenuSettings_ButtonsBoxHeight] = height;
73 	}
74 
setActiveButton(int16 buttonIdx)75 	void setActiveButton(int16 buttonIdx) {
76 		_activeButtonIdx = buttonIdx;
77 		_settings[MenuSettings_CurrentLoadedButton] = buttonIdx;
78 	}
79 
setActiveButtonTextId(TextId textIndex)80 	void setActiveButtonTextId(TextId textIndex) {
81 		setButtonTextId(getActiveButton(), textIndex);
82 	}
83 
setButtonTextId(int16 buttonIdx,TextId textIndex)84 	void setButtonTextId(int16 buttonIdx, TextId textIndex) {
85 		_settings[MenuSettings_FirstButton + buttonIdx * 2] = (int16)textIndex;
86 		_buttonTexts[buttonIdx].clear();
87 	}
88 
getActiveButtonTextId()89 	TextId getActiveButtonTextId() const {
90 		return getButtonTextId(getActiveButton());
91 	}
92 
getActiveButtonState()93 	int16 getActiveButtonState() const {
94 		return getButtonState(getActiveButton());
95 	}
96 
getButtonState(int buttonIndex)97 	int16 getButtonState(int buttonIndex) const {
98 		return _settings[MenuSettings_FirstButtonState + buttonIndex * 2];
99 	}
100 
101 	const char *getButtonText(Text *text, int buttonIndex);
102 
getActiveButton()103 	int16 getActiveButton() const {
104 		return _activeButtonIdx;
105 	}
106 
getButtonBoxHeight()107 	int16 getButtonBoxHeight() const {
108 		return _settings[MenuSettings_ButtonsBoxHeight];
109 	}
110 
getButtonCount()111 	int16 getButtonCount() const {
112 		return _settings[MenuSettings_NumberOfButtons];
113 	}
114 
setTextBankId(TextBankId textBankIndex)115 	void setTextBankId(TextBankId textBankIndex) {
116 		_settings[MenuSettings_HeaderEnd] = (int16)textBankIndex;
117 	}
118 
119 	void addButton(TextId textId, int16 state = 0) {
120 		const int16 i = _settings[MenuSettings_NumberOfButtons];
121 		_settings[i * 2 + MenuSettings_FirstButtonState] = state;
122 		_settings[i * 2 + MenuSettings_FirstButton] = (int16)textId;
123 		++_settings[MenuSettings_NumberOfButtons];
124 	}
125 
126 	void addButton(const char *text, int16 state = 0) {
127 		const int16 i = _settings[MenuSettings_NumberOfButtons];
128 		_settings[i * 2 + MenuSettings_FirstButtonState] = state;
129 		// will return the button index
130 		_settings[i * 2 + MenuSettings_FirstButton] = i;
131 		_buttonTexts[i] = text;
132 		++_settings[MenuSettings_NumberOfButtons];
133 	}
134 };
135 
136 class Menu {
137 private:
138 	TwinEEngine *_engine;
139 	/** Hero behaviour menu entity */
140 	BodyData *_behaviourEntity = nullptr;
141 	/** Behaviour menu anim state */
142 	uint _behaviourAnimState[4]; // winTab
143 	/** Behaviour menu anim data pointer */
144 	AnimTimerDataStruct _behaviourAnimData[4];
145 
146 	int32 _inventorySelectedColor = COLOR_BLACK;
147 	int32 _inventorySelectedItem = 0; // currentSelectedObjectInInventory
148 
149 	/** Plasma Effect pointer to file content: RESS.HQR:51 */
150 	uint8 *_plasmaEffectPtr = nullptr;
151 
152 	MenuSettings _giveUpMenuWithSaveState;
153 	MenuSettings _volumeMenuState;
154 	MenuSettings _saveManageMenuState;
155 	MenuSettings _giveUpMenuState;
156 	MenuSettings _mainMenuState;
157 	MenuSettings _advOptionsMenuState;
158 	MenuSettings _optionsMenuState;
159 
160 	// objectRotation
161 	int16 _itemAngle[NUM_INVENTORY_ITEMS];
162 	/** Behaviour menu move pointer */
163 	ActorMoveStruct _moveMenu;
164 
165 	/**
166 	 * Draws main menu button
167 	 * @param buttonId current button identification from menu settings
168 	 * @param dialText
169 	 * @param hover flag to know if should draw as a hover button or not
170 	 */
171 	void drawButtonGfx(const MenuSettings *menuSettings, const Common::Rect &rect, int32 buttonId, const char *dialText, bool hover);
172 	void plasmaEffectRenderFrame();
173 	/**
174 	 * Process the menu button draw
175 	 * @param data menu settings array
176 	 * @param mode flag to know if should draw as a hover button or not
177 	 */
178 	int16 drawButtons(MenuSettings *menuSettings, bool hover);
179 	/** Used to run the advanced options menu */
180 	int32 advoptionsMenu();
181 	/** Used to run the volume menu */
182 	int32 volumeMenu();
183 	/** Used to run the save game management menu */
184 	int32 savemanageMenu();
185 	void drawInfoMenu(int16 left, int16 top, int16 width);
186 	Common::Rect calcBehaviourRect(int32 left, int32 top, HeroBehaviourType behaviour) const;
187 	bool isBehaviourHovered(int32 left, int32 top, HeroBehaviourType behaviour) const;
188 	void drawBehaviour(int32 left, int32 top, HeroBehaviourType behaviour, int32 angle, bool cantDrawBox);
189 	void drawInventoryItems(int32 left, int32 top);
190 	void prepareAndDrawBehaviour(int32 left, int32 top, int32 angle, HeroBehaviourType behaviour);
191 	void drawBehaviourMenu(int32 left, int32 top, int32 angle);
192 	void drawItem(int32 left, int32 top, int32 item);
193 
194 	void drawSpriteAndString(int32 left, int32 top, const SpriteData &spriteData, const Common::String &str, int32 color = COLOR_GOLD);
195 
196 public:
197 	Menu(TwinEEngine *engine);
198 	~Menu();
199 
200 	/**
201 	 * Process the plasma effect
202 	 * @param color plasma effect start color
203 	 */
204 	void processPlasmaEffect(const Common::Rect &rect, int32 color);
205 
206 	void drawHealthBar(int32 left, int32 right, int32 top, int32 barLeftPadding, int32 barHeight);
207 	void drawCloverLeafs(int32 newBoxLeft, int32 boxRight, int32 top);
208 	void drawMagicPointsBar(int32 left, int32 right, int32 top, int32 barLeftPadding, int32 barHeight);
209 	void drawCoins(int32 left, int32 top);
210 	void drawKeys(int32 left, int32 top);
211 
212 	/**
213 	 * Draw the rect lines without filling the area
214 	 * @param left start width to draw the button
215 	 * @param top start height to draw the button
216 	 * @param right end width to draw the button
217 	 * @param bottom end height to draw the button
218 	 */
219 	void drawRectBorders(int32 left, int32 top, int32 right, int32 bottom, int32 colorLeftTop = COLOR_79, int32 colorRightBottom = COLOR_73);
220 	void drawRectBorders(const Common::Rect &rect, int32 colorLeftTop = COLOR_79, int32 colorRightBottom = COLOR_73);
221 	/**
222 	 * Where the main menu options are processed
223 	 * @param menuSettings menu settings array with the information to build the menu options
224 	 * @return pressed menu button identification
225 	 */
226 	int32 processMenu(MenuSettings *menuSettings, bool showCredits = true);
227 
228 	bool init();
229 
230 	/** Used to run the main menu */
231 	EngineState run();
232 
233 	/** Used to run the in-game give-up menu */
234 	int32 giveupMenu();
235 
236 	void inGameOptionsMenu();
237 
238 	/** Used to run the options menu */
239 	int32 optionsMenu();
240 
241 	/** Process hero behaviour menu */
242 	void processBehaviourMenu();
243 
244 	/** Process in-game inventory menu */
245 	void processInventoryMenu();
246 };
247 
248 } // namespace TwinE
249 
250 #endif
251