1 // Copyright © 2008-2021 Pioneer Developers. See AUTHORS.txt for details
2 // Licensed under the terms of the GPL v3. See licenses/GPL-3.txt
3 
4 #ifndef _PI_H
5 #define _PI_H
6 
7 #include "JobQueue.h"
8 #include "Random.h"
9 #include "core/GuiApplication.h"
10 #include "gameconsts.h"
11 #include "libs.h"
12 
13 #include "SDL_keyboard.h"
14 #include <sigc++/sigc++.h>
15 #include <map>
16 #include <string>
17 #include <vector>
18 
19 namespace Input {
20 	class Manager;
21 } //namespace Input
22 
23 namespace PiGui {
24 	class Instance;
25 } //namespace PiGui
26 
27 class Game;
28 
29 class GameConfig;
30 class Intro;
31 class LuaConsole;
32 class LuaNameGen;
33 class LuaTimer;
34 class ModelCache;
35 class ObjectViewerView;
36 class Player;
37 class SystemPath;
38 class TransferPlanner;
39 class View;
40 class SDLGraphics;
41 class LuaSerializer;
42 
43 #if ENABLE_SERVER_AGENT
44 class ServerAgent;
45 #endif
46 
47 namespace Graphics {
48 	class Renderer;
49 	class Texture;
50 	class RenderState;
51 	class RenderTarget;
52 	namespace Drawables {
53 		class TexturedQuad;
54 	}
55 } // namespace Graphics
56 
57 namespace SceneGraph {
58 	class Model;
59 }
60 
61 namespace Sound {
62 	class MusicPlayer;
63 }
64 
65 class DetailLevel {
66 public:
DetailLevel()67 	DetailLevel() :
68 		planets(0),
69 		cities(0) {}
70 	int planets;
71 	int cities;
72 };
73 
74 class Pi {
75 public:
76 	Pi() = delete;
77 
78 	class App final : public GuiApplication {
79 	public:
80 		// TODO: headless mode should be part of a different, process-wide inter
HeadlessMode()81 		bool HeadlessMode() { return m_noGui; }
82 
83 		void SetStartPath(const SystemPath &startPath);
84 
85 		// Returns a pointer to the async JobSet for the current startup loading step.
86 		// The current load step will not complete until all ordered jobs have finished.
87 		// NOTE: this queue runs on a different thread.
88 		JobSet *GetCurrentLoadStepQueue() const;
89 
90 		// Returns a pointer to the async JobSet for the entire startup loading screen.
91 		// Loading will not finish until all ordered jobs have finished.
92 		// NOTE: this queue runs on a different thread.
93 		JobSet *GetAsyncStartupQueue() const;
94 
95 	protected:
96 		// for compatibility, while we're moving Pi's internals into App
97 		friend class Pi;
98 
99 		// Pi-internal lifecycle classes
100 		friend class MainMenu;
101 		friend class GameLoop;
102 		friend class TombstoneLoop;
103 
App()104 		App() :
105 			GuiApplication("Pioneer") {}
106 
107 		void Startup() override;
108 		void Shutdown() override;
109 
110 		void PreUpdate() override;
111 		void PostUpdate() override;
112 
113 		void RunJobs();
114 
115 		void HandleRequests();
116 		bool HandleEvent(SDL_Event &ev) override;
117 
118 	private:
119 		// msgs/requests that can be posted which the game processes at the end of a game loop in HandleRequests
120 		enum class InternalRequests {
121 			END_GAME = 0,
122 			QUIT_GAME,
123 		};
124 
125 		std::vector<InternalRequests> internalRequests;
126 
127 		bool m_noGui;
128 
129 		std::shared_ptr<Lifecycle> m_loader;
130 		std::shared_ptr<Lifecycle> m_mainMenu;
131 		std::shared_ptr<Lifecycle> m_gameLoop;
132 	};
133 
134 public:
135 	static void Init(const std::map<std::string, std::string> &options, bool no_gui = false);
136 
137 	static void StartGame(Game *game);
138 
139 	static void RequestEndGame(); // request that the game is ended as soon as safely possible
140 	static void RequestQuit();
141 
142 	static void OnChangeDetailLevel();
GetFrameTime()143 	static float GetFrameTime() { return frameTime; }
GetGameTickAlpha()144 	static float GetGameTickAlpha() { return gameTickAlpha; }
145 	// for internal use, don't modify unless you know what you're doing
SetGameTickAlpha(float alpha)146 	static void SetGameTickAlpha(float alpha) { gameTickAlpha = alpha; }
147 
SetShowDebugInfo(bool enabled)148 	static void SetShowDebugInfo(bool enabled) { showDebugInfo = enabled; };
ToggleShowDebugInfo()149 	static void ToggleShowDebugInfo() { showDebugInfo = !showDebugInfo; };
150 
151 	// FIXME: hacked-in singleton pattern, find a better way to locate the application
GetApp()152 	static App *GetApp() { return m_instance; }
153 
IsNavTunnelDisplayed()154 	static bool IsNavTunnelDisplayed() { return navTunnelDisplayed; }
SetNavTunnelDisplayed(bool state)155 	static void SetNavTunnelDisplayed(bool state) { navTunnelDisplayed = state; }
AreSpeedLinesDisplayed()156 	static bool AreSpeedLinesDisplayed() { return speedLinesDisplayed; }
SetSpeedLinesDisplayed(bool state)157 	static void SetSpeedLinesDisplayed(bool state) { speedLinesDisplayed = state; }
AreHudTrailsDisplayed()158 	static bool AreHudTrailsDisplayed() { return hudTrailsDisplayed; }
SetHudTrailsDisplayed(bool state)159 	static void SetHudTrailsDisplayed(bool state) { hudTrailsDisplayed = state; }
160 
161 	static void SetMouseGrab(bool on);
DoingMouseGrab()162 	static bool DoingMouseGrab() { return doingMouseGrab; }
163 
164 	// Get the default speed modifier to apply to movement (scrolling, zooming...), depending on the "shift" keys.
165 	// This is a default value only, centralized here to promote uniform user expericience.
166 	static float GetMoveSpeedShiftModifier();
167 
168 	static std::string GetSaveDir();
169 	static SceneGraph::Model *FindModel(const std::string &, bool allowPlaceholder = true);
170 
171 	static const char SAVE_DIR_NAME[];
172 
173 	static LuaSerializer *luaSerializer;
174 	static LuaTimer *luaTimer;
175 
176 	static LuaNameGen *luaNameGen;
177 
178 #if ENABLE_SERVER_AGENT
179 	static ServerAgent *serverAgent;
180 #endif
181 
182 	static PiGui::Instance *pigui;
183 
184 	static Random rng;
185 	static int statSceneTris;
186 	static int statNumPatches;
187 
188 	static void SetView(View *v);
GetView()189 	static View *GetView() { return currentView; }
190 
SetAmountBackgroundStars(const float pc)191 	static void SetAmountBackgroundStars(const float pc)
192 	{
193 		amountOfBackgroundStarsDisplayed = Clamp(pc, 0.0f, 1.0f);
194 		bRefreshBackgroundStars = true;
195 	}
GetAmountBackgroundStars()196 	static float GetAmountBackgroundStars() { return amountOfBackgroundStarsDisplayed; }
MustRefreshBackgroundClearFlag()197 	static bool MustRefreshBackgroundClearFlag()
198 	{
199 		const bool bRet = bRefreshBackgroundStars;
200 		bRefreshBackgroundStars = false;
201 		return bRet;
202 	}
203 
204 	/* Only use #if WITH_DEVKEYS */
205 	static bool showDebugInfo;
206 
207 	static Input::Manager *input;
208 	static Player *player;
209 	static TransferPlanner *planner;
210 	static std::unique_ptr<LuaConsole> luaConsole;
GetMusicPlayer()211 	static Sound::MusicPlayer &GetMusicPlayer() { return musicPlayer; }
212 	static Graphics::Renderer *renderer;
213 	static ModelCache *modelCache;
214 	static Intro *intro;
215 	static SDLGraphics *sdl;
216 
217 	static Game *game;
218 
219 	static DetailLevel detail;
220 	static GameConfig *config;
221 
GetAsyncJobQueue()222 	static JobQueue *GetAsyncJobQueue() { return asyncJobQueue.get(); }
GetSyncJobQueue()223 	static JobQueue *GetSyncJobQueue() { return syncJobQueue.get(); }
224 
225 	static bool DrawGUI;
226 
227 private:
228 	static void HandleKeyDown(SDL_Keysym *key);
229 
230 	// private members
231 	static const Uint32 SYNC_JOBS_PER_LOOP = 1;
232 	static std::unique_ptr<AsyncJobQueue> asyncJobQueue;
233 	static std::unique_ptr<SyncJobQueue> syncJobQueue;
234 
235 	static bool menuDone;
236 
237 	static View *currentView;
238 
239 	/** So, the game physics rate (50Hz) can run slower
240 	  * than the frame rate. gameTickAlpha is the interpolation
241 	  * factor between one physics tick and another [0.0-1.0]
242 	  */
243 	static float gameTickAlpha;
244 	static float frameTime;
245 
246 	static Sound::MusicPlayer musicPlayer;
247 
248 	static bool navTunnelDisplayed;
249 	static bool speedLinesDisplayed;
250 	static bool hudTrailsDisplayed;
251 	static bool bRefreshBackgroundStars;
252 	static float amountOfBackgroundStarsDisplayed;
253 
254 	static Graphics::RenderTarget *renderTarget;
255 	static RefCountedPtr<Graphics::Texture> renderTexture;
256 	static std::unique_ptr<Graphics::Drawables::TexturedQuad> renderQuad;
257 	static Graphics::RenderState *quadRenderState;
258 
259 	static bool doingMouseGrab;
260 
261 	static bool isRecordingVideo;
262 	static FILE *ffmpegFile;
263 
264 private:
265 	// for compatibility, while we're moving Pi's internals into App
266 	friend class App;
267 
268 	static App *m_instance;
269 };
270 
271 #endif /* _PI_H */
272