1 /*
2 	C-Dogs SDL
3 	A port of the legendary (and fun) action/arcade cdogs.
4 	Copyright (C) 1995 Ronny Wester
5 	Copyright (C) 2003 Jeremy Chin
6 	Copyright (C) 2003-2007 Lucas Martin-King
7 
8 	This program is free software; you can redistribute it and/or modify
9 	it under the terms of the GNU General Public License as published by
10 	the Free Software Foundation; either version 2 of the License, or
11 	(at your option) any later version.
12 
13 	This program is distributed in the hope that it will be useful,
14 	but WITHOUT ANY WARRANTY; without even the implied warranty of
15 	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 	GNU General Public License for more details.
17 
18 	You should have received a copy of the GNU General Public License
19 	along with this program; if not, write to the Free Software
20 	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21 
22 	This file incorporates work covered by the following copyright and
23 	permission notice:
24 
25 	Copyright (c) 2013-2018, 2020-2021 Cong Xu
26 	All rights reserved.
27 
28 	Redistribution and use in source and binary forms, with or without
29 	modification, are permitted provided that the following conditions are met:
30 
31 	Redistributions of source code must retain the above copyright notice, this
32 	list of conditions and the following disclaimer.
33 	Redistributions in binary form must reproduce the above copyright notice,
34 	this list of conditions and the following disclaimer in the documentation
35 	and/or other materials provided with the distribution.
36 
37 	THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
38 	AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
39 	IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
40 	ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
41 	LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
42 	CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
43 	SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
44 	INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
45 	CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
46 	ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
47 	POSSIBILITY OF SUCH DAMAGE.
48 */
49 #pragma once
50 
51 #include <cdogs/c_array.h>
52 #include <cdogs/campaigns.h>
53 #include <cdogs/events.h>
54 #include <cdogs/gamedata.h>
55 #include <cdogs/grafx.h>
56 
57 #include "credits.h"
58 #include "game_loop.h"
59 
60 typedef enum
61 {
62 	MENU_TYPE_NORMAL,  // normal menu with items, up/down/left/right moves
63 					   // cursor
64 	MENU_TYPE_OPTIONS, // menu with items, only up/down moves
65 	MENU_TYPE_BASIC,   // no items, does nothing (use custom callbacks)
66 	MENU_TYPE_SET_OPTION_TOGGLE, // no items, sets option on/off
67 	MENU_TYPE_SET_OPTION_RANGE,	 // no items, sets option range low-high
68 	MENU_TYPE_SET_OPTION_SEED,	 // set random seed
69 	MENU_TYPE_SET_OPTION_UP_DOWN_VOID_FUNC_VOID, // set option using up/down
70 												 // functions
71 	MENU_TYPE_SET_OPTION_RANGE_GET_SET, // set option range low-high using
72 										// get/set functions
73 	MENU_TYPE_SET_OPTION_CHANGE_KEY,	// redefine key
74 	MENU_TYPE_VOID_FUNC,				// call a void (*f)(void *) function
75 	MENU_TYPE_BACK,
76 	MENU_TYPE_QUIT,
77 	MENU_TYPE_RETURN, // Return with a code
78 	MENU_TYPE_CUSTOM  // use custom callbacks for input and drawing
79 } menu_type_e;
80 
81 typedef enum
82 {
83 	MENU_OPTION_DISPLAY_STYLE_NONE,
84 	MENU_OPTION_DISPLAY_STYLE_STR_FUNC, // use a function that returns string
85 	MENU_OPTION_DISPLAY_STYLE_INT_TO_STR_FUNC, // function that converts int to
86 											   // string
87 } menu_option_display_style_e;
88 
89 typedef enum
90 {
91 	MENU_DISPLAY_ITEMS_CREDITS = 0x01,
92 	MENU_DISPLAY_ITEMS_AUTHORS = 0x02
93 } menu_display_items_e;
94 
95 typedef struct menu menu_t;
96 
97 // Callback for drawing custom menu
98 // menu, graphics, pos, size, data
99 typedef void (*MenuDisplayFunc)(
100 	const menu_t *, GraphicsDevice *, const struct vec2i, const struct vec2i,
101 	const void *);
102 // Callback for handling user input
103 // cmd, data
104 // returns: 0 if stay on menu, 1 if exit from menu
105 typedef int (*MenuInputFunc)(int, void *);
106 // Callback for processing custom function on menu
107 typedef void (*MenuFunc)(menu_t *, void *);
108 // Callback for processing custom menu function post input
109 // menu, cmd, data
110 typedef void (*MenuPostInputFunc)(menu_t *, int cmd, void *);
111 
112 typedef enum
113 {
114 	MENU_ALIGN_CENTER,
115 	MENU_ALIGN_LEFT
116 } MenuAlignStyle;
117 
118 typedef enum
119 {
120 	MENU_SOUND_ENTER,
121 	MENU_SOUND_BACK,
122 	MENU_SOUND_SWITCH,
123 	MENU_SOUND_START,
124 	MENU_SOUND_ERROR
125 } MenuSound;
126 
127 struct menu
128 {
129 	char *name;
130 	menu_type_e type;
131 	struct menu *parentMenu;
132 	bool isDisabled;
133 	color_t color;
134 	MenuFunc customPostEnterFunc;
135 	void *customPostEnterData;
136 	bool isCustomPostEnterDataDynamic;
137 	MenuFunc customPostUpdateFunc;
138 	void *customPostUpdateData;
139 	bool isCustomPostUpdateDataDynamic;
140 	MenuPostInputFunc customPostInputFunc;
141 	void *customPostInputData;
142 	MenuDisplayFunc customDisplayFunc;
143 	const void *customDisplayData;
144 	MenuSound enterSound;
145 	union {
146 		// normal menu, with sub menus
147 		struct
148 		{
149 			char title[64];
150 			CArray subMenus; // of menu_t
151 			// whether to use alternate control to enter submenus
152 			bool isSubmenusAlt;
153 			int index;
154 			int scroll;
155 			int maxItems; // 0 means unlimited
156 			MenuAlignStyle align;
157 			int quitMenuIndex;
158 			int displayItems;
159 			int setOptions;
160 			struct menu
161 				*changeKeyMenu; // if in change key mode, and which item
162 		} normal;
163 		// menu item only
164 		struct
165 		{
166 			union {
167 				bool *optionToggle;
168 				struct
169 				{
170 					int *option;
171 					int low;
172 					int high;
173 					int increment;
174 				} optionRange;
175 				unsigned int *seed;
176 				// function to call
177 				struct
178 				{
179 					void (*upFunc)(void);
180 					void (*downFunc)(void);
181 				} upDownFuncs;
182 				struct
183 				{
184 					int (*getFunc)(void);
185 					void (*setFunc)(int);
186 					int low;
187 					int high;
188 					int increment;
189 				} optionRangeGetSet;
190 				struct
191 				{
192 					void (*func)(void *);
193 					void *data;
194 				} voidFunc;
195 				struct
196 				{
197 					input_device_e *device0;
198 					input_device_e *device1;
199 				} changeControl;
200 			} uHook;
201 			menu_option_display_style_e displayStyle;
202 			union {
203 				char *(*str)(void);
204 				const char *(*intToStr)(int);
205 			} uFunc;
206 		} option;
207 		// change key
208 		struct
209 		{
210 			key_code_e code;
211 			int playerIndex;
212 			// If key is optional, allow it to be unset
213 			bool isOptional;
214 		} changeKey;
215 		int returnCode;
216 		struct
217 		{
218 			MenuDisplayFunc displayFunc;
219 			MenuInputFunc inputFunc;
220 			void *data;
221 		} customData;
222 	} u;
223 };
224 
225 typedef struct
226 {
227 	MenuDisplayFunc Func;
228 	void *Data;
229 } MenuCustomDisplayFunc;
230 typedef struct
231 {
232 	menu_t *root;
233 	menu_t *current;
234 	CArray exitTypes; // of menu_type_e
235 	credits_displayer_t *creditsDisplayer;
236 	EventHandlers *handlers;
237 	GraphicsDevice *graphics;
238 	struct vec2i pos;
239 	struct vec2i size;
240 	MenuAlignStyle align;
241 	bool allowAborts;
242 	bool hasAbort;
243 	CArray customDisplayFuncs; // of MenuCustomDisplayFunc
244 } MenuSystem;
245 
246 void MenuSystemInit(
247 	MenuSystem *ms, EventHandlers *handlers, GraphicsDevice *graphics,
248 	struct vec2i pos, struct vec2i size);
249 void MenuSystemTerminate(MenuSystem *ms);
250 void MenuSetCreditsDisplayer(
251 	MenuSystem *menu, credits_displayer_t *creditsDisplayer);
252 void MenuAddExitType(MenuSystem *menu, menu_type_e exitType);
253 void MenuSystemAddCustomDisplay(
254 	MenuSystem *ms, MenuDisplayFunc func, void *data);
255 int MenuIsExit(MenuSystem *ms);
256 GameLoopData *MenuLoop(MenuSystem *menu);
257 GameLoopResult MenuUpdate(MenuSystem *ms);
258 void MenuDraw(const MenuSystem *ms);
259 void MenuDisplay(const MenuSystem *ms);
260 void MenuProcessCmd(MenuSystem *ms, int cmd);
261 void MenuReset(MenuSystem *menu);
262 void MenuDisableSubmenu(menu_t *menu, int index);
263 void MenuEnableSubmenu(menu_t *menu, int index);
264 void MenuSetDisabled(menu_t *menu, const bool isDisabled);
265 menu_t *MenuGetSubmenuByName(menu_t *menu, const char *name);
266 int MenuGetNumMenuItemsShown(const menu_t *menu);
267 
268 void ShowControls(void);
269 struct vec2i DisplayMenuItem(
270 	GraphicsDevice *g, const Rect2i bounds, const char *s, const bool selected,
271 	const bool isDisabled, const color_t color);
272 
273 menu_t *MenuCreate(const char *name, menu_type_e type);
274 menu_t *MenuCreateNormal(
275 	const char *name, const char *title, menu_type_e type, int displayItems);
276 menu_t *MenuAddSubmenu(menu_t *menu, menu_t *subMenu);
277 void MenuSetPostEnterFunc(
278 	menu_t *menu, MenuFunc func, void *data, const bool isDynamicData);
279 void MenuSetPostUpdateFunc(
280 	menu_t *menu, MenuFunc func, void *data, const bool isDynamicData);
281 void MenuSetPostInputFunc(menu_t *menu, MenuPostInputFunc func, void *data);
282 void MenuSetCustomDisplay(
283 	menu_t *menu, MenuDisplayFunc func, const void *data);
284 
285 void MenuAddConfigOptionsItem(menu_t *menu, Config *c);
286 menu_t *MenuCreateOptionToggle(const char *name, bool *config);
287 menu_t *MenuCreateOptionRange(
288 	const char *name, int *config, int low, int high, int increment,
289 	menu_option_display_style_e style, void (*func)(void));
290 menu_t *MenuCreateOptionSeed(const char *name, unsigned int *seed);
291 menu_t *MenuCreateOptionUpDownFunc(
292 	const char *name, void (*upFunc)(void), void (*downFunc)(void),
293 	menu_option_display_style_e style, char *(*strFunc)(void));
294 menu_t *MenuCreateVoidFunc(const char *name, void (*func)(void *), void *data);
295 menu_t *MenuCreateOptionRangeGetSet(
296 	const char *name, int (*getFunc)(void), void (*setFunc)(int), int low,
297 	int high, int increment, menu_option_display_style_e style,
298 	void (*func)(void));
299 menu_t *MenuCreateSeparator(const char *name);
300 menu_t *MenuCreateBack(const char *name);
301 // Create a menu entry that exits the menu while setting a return code
302 // The return code can be retrieved from the menu system via
303 // ms.current->u.returnCode
304 menu_t *MenuCreateReturn(const char *name, int returnCode);
305 menu_t *MenuCreateCustom(
306 	const char *name, MenuDisplayFunc displayFunc, MenuInputFunc inputFunc,
307 	void *data);
308 
309 void MenuPlaySound(MenuSound s);
310 
311 void MenuClearSubmenus(menu_t *menu);
312