Simulant  21.12-1292
A portable game engine for Windows, OSX, Linux, Dreamcast, and PSP
application.h
1 /* * Copyright (c) 2011-2017 Luke Benstead https://simulant-engine.appspot.com
2  *
3  * This file is part of Simulant.
4  *
5  * Simulant is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU Lesser General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * Simulant is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public License
16  * along with Simulant. If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 #ifndef APPLICATION_H
20 #define APPLICATION_H
21 
22 #include <cstdint>
23 #include <memory>
24 #include <list>
25 #include <iosfwd>
26 
27 #include "arg_parser.h"
28 #include "keycodes.h"
29 #include "utils/deprecated.h"
30 #include "types.h"
31 #include "utils/unicode.h"
32 #include "scenes/scene_manager.h"
33 #include "generic/property.h"
34 #include "generic/data_carrier.h"
35 #include "scenes/scene_manager.h"
36 #include "screen.h"
37 #include "logging.h"
38 #include "path.h"
39 #include "loader.h"
40 
41 #define DEFAULT_LANGUAGE_CODE "en-us"
42 
43 
44 namespace smlt {
45 
46 class Window;
47 class Stage;
48 class SharedAssetManager;
49 class TimeKeeper;
50 class StatsRecorder;
51 class VirtualFileSystem;
52 class SoundDriver;
53 
54 class BackgroundLoadException : public std::runtime_error {
55 public:
57  std::runtime_error("An error occurred while running a background task") {}
58 };
59 
60 struct AppConfig {
61  unicode title = _u("Simulant Application");
62  uint32_t width = 0;
63  uint32_t height = 0;
64  uint32_t bpp = 0;
65  bool fullscreen = true;
66 
67  /* This is the frame limit; set to 0 to disable */
68  uint16_t target_frame_rate = 60;
69 
70  /* This is how many fixed updates should happen per second */
71  uint16_t target_fixed_step_rate = 60;
72 
73  /* Whether to enable vsync or not */
74  bool enable_vsync = false;
75 
76  // Additional paths for asset loading
77  std::vector<Path> search_paths;
78 
79  // Program arguments
80  std::vector<unicode> arguments;
81 
82  smlt::LogLevel log_level = smlt::LOG_LEVEL_INFO;
83 
84  /* If set to true, the mouse cursor will not be hidden by default */
85  bool show_cursor = false;
86 
87  std::string source_language_code = DEFAULT_LANGUAGE_CODE;
88 
89  struct General {
90  uint32_t stage_node_pool_size = 64;
91  } general;
92 
93  struct UI {
96  std::vector<Path> font_directories = {};
97 
99  std::string font_family = "Orbitron";
100 
103  uint16_t font_size = 18;
104  } ui;
105 
106  struct Desktop {
107  bool enable_virtual_screen = false;
108  ScreenFormat virtual_screen_format = SCREEN_FORMAT_G1;
109  uint16_t virtual_screen_width = 48;
110  uint16_t virtual_screen_height = 32;
111  uint16_t virtual_screen_integer_scale = 1;
112  } desktop;
113 
114  struct Development {
115  /* If set to true, profiling mode will be enabled
116  * regardless of the SIMULANT_PROFILE environment variable.
117  *
118  * When profiling mode is enabled, the frame limit is uncapped
119  * and on some platforms a profiler is enabled.
120  */
121 #ifdef SIMULANT_PROFILE
122  bool force_profiling = true;
123 #else
124  bool force_profiling = false;
125 #endif
126  /*
127  * Set to gl1x or gl2x to force that renderer if available
128  FIXME: Not yet working
129  */
130  std::string force_renderer = "";
131  std::string force_sound_driver = "";
132 
133  /* If not empty, logging entries will be written to this
134  * file as well as stdout */
135  std::string log_file = "";
136 
137  /* Additional memory debug logging. If set to true information
138  about scene memory usage will be logged at INFO level */
139  bool additional_memory_logging = true;
140  } development;
141 };
142 
143 class Loader;
144 class LoaderType;
145 
146 typedef std::shared_ptr<Loader> LoaderPtr;
147 typedef std::shared_ptr<LoaderType> LoaderTypePtr;
148 
149 typedef sig::signal<void ()> FrameStartedSignal;
150 typedef sig::signal<void ()> FrameFinishedSignal;
151 typedef sig::signal<void ()> PreSwapSignal;
152 typedef sig::signal<void ()> PostCoroutinesSignal;
153 
154 typedef sig::signal<void (float)> FixedUpdateSignal;
155 typedef sig::signal<void (float)> UpdateSignal;
156 typedef sig::signal<void (float)> LateUpdateSignal;
157 typedef sig::signal<void ()> PostLateUpdateSignal;
158 typedef sig::signal<void ()> ShutdownSignal;
159 
160 class Application {
161  friend class Window;
162 
163  DEFINE_SIGNAL(PreSwapSignal, signal_pre_swap);
164  DEFINE_SIGNAL(PostCoroutinesSignal, signal_post_coroutines);
165  DEFINE_SIGNAL(FixedUpdateSignal, signal_fixed_update);
166  DEFINE_SIGNAL(UpdateSignal, signal_update);
167  DEFINE_SIGNAL(LateUpdateSignal, signal_late_update);
168  DEFINE_SIGNAL(PostLateUpdateSignal, signal_post_late_update);
169  DEFINE_SIGNAL(ShutdownSignal, signal_shutdown);
170 
171  DEFINE_SIGNAL(FrameStartedSignal, signal_frame_started);
172  DEFINE_SIGNAL(FrameFinishedSignal, signal_frame_finished);
173 
174 public:
175  Application(const AppConfig& config, void* platform_state=nullptr);
176  virtual ~Application();
177 
178  bool profiling_enabled() const;
179 
180  //Create the window, start do_initialization in a thread, show the loading scene
181  //when thread completes, hide the loading scene and run the main loop
182  int32_t run();
183  int32_t run(int argc, char* argv[]);
184 
185  bool initialized() const { return initialized_; }
186 
189  ProcessID process_id() const;
190 
192  smlt::thread::ThreadID thread_id() const;
193 
197  int64_t ram_usage_in_bytes() const;
198 
201  bool run_frame();
202 
205  void run_update(float dt);
206 
208  void run_fixed_updates();
209 
212  void request_frame_time(float ms);
213 
214  /* Coroutines */
215  void start_coroutine(std::function<void ()> func);
216  void update_coroutines();
217  void stop_all_coroutines();
218 
220  void stop_running();
221 
223  bool is_shutting_down() const;
224 
225  void shutdown();
226 
227  /* Loader things */
228  LoaderPtr loader_for(const Path &filename, LoaderHint hint=LOADER_HINT_NONE);
229  LoaderPtr loader_for(const std::string& loader_name, const Path& filename);
230  LoaderTypePtr loader_type(const std::string& loader_name) const;
231 
232  void register_loader(LoaderTypePtr loader_type);
233 
239  bool activate_language(const std::string& language_code);
240 
241 
246  bool activate_language_from_arb_data(const uint8_t* data, std::size_t byte_size);
247 
248 
250  std::string active_language() const {
251  return active_language_;
252  }
253 
260  unicode translated_text(const unicode& source_text) {
261  auto it = active_translations_.find(source_text);
262  if(it == active_translations_.end()) {
263  return source_text;
264  } else {
265  return it->second;
266  }
267  }
268 
269  void* platform_state() {
270  return platform_state_;
271  }
272 
273 protected:
274  bool _call_init();
275 
276  virtual std::shared_ptr<Window> instantiate_window();
277 
278 private:
279  void* platform_state_ = nullptr;
280  friend void cr_run_main(std::function<void ()> func);
281  std::function<void ()> cr_synced_function_;
282 
283  void run_coroutines_and_late_update();
284 
285  thread::ThreadID main_thread_id_;
286  bool has_shutdown_ = false;
287 
288  std::shared_ptr<Window> window_;
289  std::shared_ptr<SceneManager> scene_manager_;
290  std::shared_ptr<SharedAssetManager> asset_manager_;
291  std::shared_ptr<TimeKeeper> time_keeper_;
292  std::shared_ptr<StatsRecorder> stats_;
293  std::shared_ptr<VirtualFileSystem> vfs_;
294  std::shared_ptr<SoundDriver> sound_driver_;
295  std::shared_ptr<MaterialValuePool> pool_;
296  std::vector<LoaderTypePtr> loaders_;
297 
298  bool initialized_ = false;
299  bool is_running_ = true;
300 
301  float frame_counter_time_ = 0.0f;
302  int32_t frame_counter_frames_ = 0;
303  float frame_time_in_milliseconds_ = 0.0f;
304 
305  void _call_fixed_update(float dt) {
306  fixed_update(dt);
307  }
308 
309  void _call_clean_up();
310 
311  void _call_update(float dt) {
312  update(dt);
313  }
314 
315  void _call_late_update(float dt) {
316  late_update(dt);
317  }
318 
319  virtual bool init() = 0;
320 
329  virtual bool pre_init() { return true; }
330 
331  virtual void fixed_update(float dt) {
332  _S_UNUSED(dt);
333  }
334 
335  virtual void update(float dt) {
336  _S_UNUSED(dt);
337  }
338 
339  virtual void late_update(float dt) {
340  _S_UNUSED(dt);
341  }
342 
343  virtual void clean_up() {}
344 
345  generic::DataCarrier data_carrier_;
346 
347  AppConfig config_;
348 
349  bool construct_window(const AppConfig& config);
350 
351  ArgParser args_;
352 
353  void await_frame_time();
354  uint64_t last_frame_time_us_ = 0;
355  float requested_frame_time_ms_ = 0;
356 
357  std::list<cort::CoroutineID> coroutines_;
358  void preload_default_font();
359 
360  std::string active_language_ = DEFAULT_LANGUAGE_CODE;
361  std::map<unicode, unicode> active_translations_;
362 
363  std::shared_ptr<Scene> overlay_scene_;
364 public:
365  S_DEFINE_PROPERTY(window, &Application::window_);
366  S_DEFINE_PROPERTY(data, &Application::data_carrier_);
367  S_DEFINE_PROPERTY(scenes, &Application::scene_manager_);
368  S_DEFINE_PROPERTY(args, &Application::args_);
369  S_DEFINE_PROPERTY(config, &Application::config_);
370  S_DEFINE_PROPERTY(shared_assets, &Application::asset_manager_);
371  S_DEFINE_PROPERTY(time_keeper, &Application::time_keeper_);
372  S_DEFINE_PROPERTY(stats, &Application::stats_);
373  S_DEFINE_PROPERTY(vfs, &Application::vfs_);
374  S_DEFINE_PROPERTY(sound_driver, &Application::sound_driver_);
375  S_DEFINE_PROPERTY(material_value_pool, &Application::pool_);
376 
380  S_DEFINE_PROPERTY(overlay, &Application::overlay_scene_);
381 
382 private:
383  friend Application* get_app();
384  static Application* global_app;
385 
386  mutable thread::Mutex running_lock_;
387 
388  std::vector<std::string> generate_potential_codes(const std::string& language_code);
389  bool load_arb(std::shared_ptr<std::istream> stream, std::string* language_code = nullptr);
390  bool load_arb_from_file(const smlt::Path& filename);
391 
392 
393  /* A number of steps in the application initialization depend on a
394  * viable GL context. Some platforms (cough, Android) won't have a
395  * native window at boot time, and will get one later on. This function
396  * is called by the Window when set_has_context(true) happens */
397  void on_render_context_created();
398 
399  void on_render_context_destroyed();
400 };
401 
402 Application* get_app();
403 
404 }
405 
406 #define _T(text) \
407  smlt::get_app()->translated_text((text))
408 
409 #endif // APPLICATION_H
smlt::Application::run_update
void run_update(float dt)
Definition: application.cpp:440
smlt::Application::S_DEFINE_PROPERTY
S_DEFINE_PROPERTY(overlay, &Application::overlay_scene_)
smlt::AppConfig::Desktop
Definition: application.h:106
smlt::Application::activate_language_from_arb_data
bool activate_language_from_arb_data(const uint8_t *data, std::size_t byte_size)
Definition: application.cpp:895
smlt::Application::process_id
ProcessID process_id() const
Definition: application.cpp:650
smlt::Application
Definition: application.h:160
smlt::Application::stop_running
void stop_running()
Definition: application.cpp:711
smlt
Definition: animation.cpp:25
smlt::LoaderType
Definition: loader.h:111
smlt::Window
Definition: window.h:68
smlt::Loader
Definition: loader.h:66
smlt::AppConfig::UI
Definition: application.h:93
smlt::BackgroundLoadException
Definition: application.h:54
smlt::Application::active_language
std::string active_language() const
Definition: application.h:250
smlt::Application::translated_text
unicode translated_text(const unicode &source_text)
Definition: application.h:260
smlt::AppConfig::UI::font_family
std::string font_family
Definition: application.h:99
smlt::Application::run_fixed_updates
void run_fixed_updates()
Definition: application.cpp:463
smlt::Application::thread_id
smlt::thread::ThreadID thread_id() const
Definition: application.cpp:660
smlt::AppConfig::UI::font_size
uint16_t font_size
Definition: application.h:103
smlt::Path
Definition: path.h:7
smlt::AppConfig
Definition: application.h:60
unicode
Definition: unicode.h:36
smlt::AppConfig::General
Definition: application.h:89
smlt::Application::ram_usage_in_bytes
int64_t ram_usage_in_bytes() const
Definition: application.cpp:664
smlt::Application::request_frame_time
void request_frame_time(float ms)
Definition: application.cpp:423
smlt::thread::Mutex
Definition: mutex.h:35
smlt::Application::run_frame
bool run_frame()
Definition: application.cpp:478
smlt::AppConfig::UI::font_directories
std::vector< Path > font_directories
Definition: application.h:96
smlt::sig::signal
Definition: signal.h:330
smlt::Application::is_shutting_down
bool is_shutting_down() const
Definition: application.cpp:716
smlt::Application::activate_language
bool activate_language(const std::string &language_code)
Definition: application.cpp:907
smlt::AppConfig::Development
Definition: application.h:114