File: wlapplication.h

package info (click to toggle)
widelands 1:19+repack-6
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 371,172 kB
  • sloc: cpp: 108,458; ansic: 18,695; python: 5,155; sh: 487; xml: 460; makefile: 229
file content (272 lines) | stat: -rw-r--r-- 9,269 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
/*
 * Copyright (C) 2006-2016 by the Widelands Development Team
 *
 * 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.
 *
 */

#ifndef WL_WLAPPLICATION_H
#define WL_WLAPPLICATION_H

// Workaround for bug http://sourceforge.net/p/mingw/bugs/2152/
#ifdef __MINGW32__
#ifndef _WIN64
#define _USE_32BIT_TIME_T 1
#endif
#endif

#include <cassert>
#include <cstring>
#include <map>
#include <stdexcept>
#include <string>

#include <SDL_events.h>
#include <SDL_keyboard.h>

#include "base/point.h"

namespace Widelands {
class Game;
}

/// Thrown if a commandline parameter is faulty
struct ParameterError : public std::runtime_error {
	explicit ParameterError() : std::runtime_error("") {
	}
	explicit ParameterError(std::string text) : std::runtime_error(text) {
	}
};

// Callbacks input events to the UI. All functions return true when the event
// was handled, false otherwise.
struct InputCallback {
	bool (*mouse_press)(const uint8_t button,  // Button number as #defined in SDL_mouse.h.
	                    int32_t x,
	                    int32_t y);              // The coordinates of the mouse at press time.
	bool (*mouse_release)(const uint8_t button,  // Button number as #defined in SDL_mouse.h.
	                      int32_t x,
	                      int32_t y);  // The coordinates of the mouse at release time.
	bool (*mouse_move)(const uint8_t state, int32_t x, int32_t y, int32_t xdiff, int32_t ydiff);
	bool (*key)(bool down, SDL_Keysym code);
	bool (*textinput)(const std::string& text);
	bool (*mouse_wheel)(uint32_t which, int32_t x, int32_t y);
};

/// You know main functions, of course. This is the main struct.
///
/// The oversimplified version: everything else is either game logic or GUI.
///
/// WLAppplication bundles all initialization and shutdown code in one neat
/// package. It also includes all (well, most) system abstractions, notably
/// i18n, input handling, timing, low level networking and graphics setup (the
/// actual graphics work is done by Graphic).
///
// TODO(bedouin): Is the above part about i18n still true?
//
// Equally important, the main event loop is chugging along in this class.
// [not yet but some time in the future \#bedouin8sep2007]
///
/// \par WLApplication is a singleton
///
/// Because of it's special purpose, having more than one WLApplication is
/// useless. So we implement singleton semantics:
/// \li A private(!) static class variable (--> unique for the whole program,
///     although nobody can get at it) the_singleton holds a pointer to the
///     only instance of WLApplication. It is private because it would not be a
///     struct variable otherwise.
/// \li There is no public constructor. If there was, you would be able to
///     create more WLApplications. So constructor access must be encapsulated
///     too.
/// \li The only way to get at the WLApplication object is to call
///     WLApplication::get(), which is static as well. Because of this, get()
///     can access the_singleton even if no WLApplication object has been
///     instantiated yet. get() will \e always give you a valid WLApplication.
///     If one does not exist yet, it will be created.
/// \li A destructor does not make sense. Just make sure you call
///     shutdown_settings() and shutdown_hardware() when you are done - in a
///     sense, it is a destructor without the destruction part ;-)
///
/// These measures \e guarantee that there are no stray WLApplication objects
/// floating around by accident.
///
/// For testing purposes, we can spawn a second process with widelands running
/// in it (see init_double_game()). The fact that WLApplication is a singleton
/// is not touched by this: the processes start out as a byte exact memory
/// copy, so the two instances ca not know (except for fork()'s return value)
/// that they are (or are not) a primary thread. Each WLApplication singleton
/// really *is* a singleton - inside it's own process.
///
/// Forking does not work on windows, but nobody cares enough to investigate.
/// It is only a debugging convenience anyway.
///
///
/// \par The mouse cursor
///
/// SDL can handle a mouse cursor on its own, but only in black and white. That
/// is not sufficient.
///
/// So Widelands must paint its own cursor and hide the system cursor.
///
/// Ordinarily, relative coordinates break down when the cursor leaves the
/// window. This means we have to grab the mouse, then relative coords are
/// always available.
// TODO(unknown): Actually do grab the mouse when it is locked
// TODO(unknown): Graphics are currently not handled by WLApplication, and it is
// non essential for playback anyway. Additionally, we will want several
// rendering backends (software and OpenGL). Maybe the graphics backend loader
// code should be in System, while the actual graphics work is done elsewhere.
// TODO(unknown): Refactor the mainloop
// TODO(unknown): Sensible use of exceptions (goes for whole game)
// TODO(sirver): this class makes no sense for c++ - most of these should be
// stand alone functions.
struct WLApplication {
	static WLApplication* get(int const argc = 0, char const** argv = nullptr);
	~WLApplication();

	enum GameType { NONE, EDITOR, REPLAY, SCENARIO, LOADGAME, NETWORK };

	void run();

	/// \warning true if an external entity wants us to quit
	bool should_die() const {
		return should_die_;
	}

	/// Get the state of the current KeyBoard Button
	/// \warning This function doesn't check for dumbness
	bool get_key_state(SDL_Scancode const key) const {
		return SDL_GetKeyboardState(nullptr)[key];
	}

	// @{
	void warp_mouse(Point);
	void set_input_grab(bool grab);

	/// The mouse's current coordinates
	Point get_mouse_position() const {
		return mouse_position_;
	}
	//
	/// Find out whether the mouse is currently pressed
	bool is_mouse_pressed() const {
		return SDL_GetMouseState(nullptr, nullptr);
	}

	/// Swap left and right mouse key?
	void set_mouse_swap(const bool swap) {
		mouse_swapped_ = swap;
	}

	/// Lock the mouse cursor into place (e.g., for scrolling the map)
	void set_mouse_lock(const bool locked) {
		mouse_locked_ = locked;
	}
	// @}

	// Refresh the graphics settings with the latest options.
	void refresh_graphics();

	// Pump SDL events and dispatch them.
	void handle_input(InputCallback const*);

	void mainmenu();
	void mainmenu_tutorial();
	void mainmenu_singleplayer();
	void mainmenu_multiplayer();
	void mainmenu_editor();

	bool new_game();
	bool load_game();
	bool campaign_game();
	void replay();
	static void emergency_save(Widelands::Game&);

private:
	WLApplication(int argc, char const* const* argv);

	bool poll_event(SDL_Event&);

	bool init_settings();
	void init_language();
	void shutdown_settings();

	void shutdown_hardware();

	void parse_commandline(int argc, char const* const* argv);
	void handle_commandline_parameters();

	void setup_homedir();

	void cleanup_replays();

	bool redirect_output(std::string path = "");

	// Handle the given pressed key. Returns true when key was
	// handled.
	bool handle_key(bool down, const SDL_Keycode& keycode, int modifiers);

	/**
	 * The commandline, conveniently repackaged.
	 */
	std::map<std::string, std::string> commandline_;

	std::string filename_;

	/// Script to be run after the game was started with --editor,
	/// --scenario or --loadgame.
	std::string script_to_run_;

	GameType game_type_;

	/// True if left and right mouse button should be swapped
	bool mouse_swapped_;

	/// When apple is involved, the middle mouse button is sometimes send, even
	/// if it wasn't pressed. We try to revert this and this helps.
	bool faking_middle_mouse_button_;

	/// The current position of the mouse pointer
	Point mouse_position_;

	/// If true, the mouse cursor will \e not move with a mousemotion event:
	/// instead, the map will be scrolled
	bool mouse_locked_;

	/// If the mouse needs to be moved in warp_mouse(), this Point is
	/// used to cancel the resulting SDL_MouseMotionEvent.
	Point mouse_compensate_warp_;

	/// true if an external entity wants us to quit
	bool should_die_;

	std::string homedir_;

	/// flag indicating if stdout and stderr have been redirected
	bool redirected_stdio_;

	/// Absolute path to the data directory.
	std::string datadir_;
	std::string datadir_for_testing_;

	/// Holds this process' one and only instance of WLApplication, if it was
	/// created already. nullptr otherwise.
	/// \note This is private on purpose. Read the class documentation.
	static WLApplication* the_singleton;

	void handle_mousebutton(SDL_Event&, InputCallback const*);
};

#endif  // end of include guard: WL_WLAPPLICATION_H