Simulant  21.12-349
A portable game engine for Windows, OSX, Linux, Dreamcast, and PSP
window.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 SIMULANT_WINDOW_BASE_H
20 #define SIMULANT_WINDOW_BASE_H
21 
22 #include <memory>
23 
24 #include "logging.h"
25 
26 #include "generic/property.h"
27 #include "generic/object_manager.h"
28 #include "generic/data_carrier.h"
29 
30 #include "input/input_state.h"
31 #include "types.h"
32 #include "loader.h"
33 #include "event_listener.h"
34 #include "stats_recorder.h"
35 #include "screen.h"
36 
37 namespace smlt {
38 
39 class AssetManager;
40 class InputManager;
41 
42 namespace ui {
43  class Interface;
44 }
45 
46 namespace scenes {
47  class Loading;
48 }
49 
50 class Application;
51 class InputState;
52 class Compositor;
53 class SceneImpl;
54 class Renderer;
55 class Panel;
56 class SoundDriver;
57 class StageNode;
58 
59 typedef sig::signal<void (std::string, Screen*)> ScreenAddedSignal;
60 typedef sig::signal<void (std::string, Screen*)> ScreenRemovedSignal;
61 
62 class Window :
63  public Loadable,
64  public RenderTarget,
65  public EventListenerManager {
66 
67  DEFINE_SIGNAL(ScreenAddedSignal, signal_screen_added);
68  DEFINE_SIGNAL(ScreenRemovedSignal, signal_screen_removed);
69 
70  friend class Screen; /* Screen needs to call render_screen */
71  friend class Application; /* ContextLock stuff */
72 public:
73  typedef std::shared_ptr<Window> ptr;
74 
75  template<typename T>
76  static std::shared_ptr<Window> create(Application* app) {
77  auto window = std::make_shared<T>();
78  window->set_application(app);
79  return window;
80  }
81 
82  virtual ~Window();
83 
84  virtual bool create_window(
85  uint16_t width,
86  uint16_t height,
87  uint8_t bpp,
88  bool fullscreen,
89  bool enable_vsync
90  );
91 
92  virtual void set_title(const std::string& title) = 0;
93  virtual void cursor_position(int32_t& mouse_x, int32_t& mouse_y) = 0;
94  virtual void show_cursor(bool cursor_shown=true) = 0;
95  virtual void lock_cursor(bool cursor_locked=true) = 0;
96 
97  virtual void check_events() = 0;
98  virtual void swap_buffers() = 0;
99 
100  uint16_t width() const override { return width_; }
101  uint16_t height() const override { return height_; }
102  bool is_fullscreen() const { return fullscreen_; }
103  bool vsync_enabled() const { return vsync_enabled_; }
104 
105  float aspect_ratio() const;
106  void set_logging_level(LogLevel level);
107 
108  void reset();
109 
110  Vec2 coordinate_from_normalized(Ratio rx, Ratio ry) {
111  return Vec2(
112  uint16_t(float(width()) * rx),
113  uint16_t(float(height()) * ry)
114  );
115  }
116 
117  void on_finger_down(
118  TouchPointID touch_id,
119  float normalized_x, float normalized_y, float pressure=1.0
120  );
121 
122  void on_finger_up(
123  TouchPointID touch_id,
124  float normalized_x, float normalized_y
125  );
126 
127  void on_finger_motion(
128  TouchPointID touch_id,
129  float normalized_x, float normalized_y,
130  float dx, float dy // Between -1.0 and +1.0
131  );
132 
133  void on_key_down(KeyboardCode code, ModifierKeyState modifiers);
134  void on_key_up(KeyboardCode code, ModifierKeyState modifiers);
135 
136  void on_game_controller_button_down(GameControllerIndex index, JoystickButton button);
137  void on_game_controller_button_up(GameControllerIndex index, JoystickButton button);
138 
139  /* Return the number of screens connected */
140  std::size_t screen_count() const;
141 
142  /* Return a specific screen given its name */
143  Screen* screen(const std::string& name) const;
144 
145  void each_screen(std::function<void (std::string, Screen*)> callback);
146 
147  /* Private API for Window subclasses (public for testing)
148  don't call this directly
149  */
150  Screen* _create_screen(
151  const std::string& name,
152  uint16_t width,
153  uint16_t height,
154  ScreenFormat format,
155  uint16_t refresh_rate);
156 
157  void _destroy_screen(const std::string& name);
158 
159  /* Creates the window, but doesn't do any context initialisation */
160  virtual bool _init_window() = 0;
161 
162  /* Initialises any renderer context */
163  virtual bool _init_renderer(Renderer* renderer) = 0;
164 
165  bool initialize_assets_and_devices();
166  void _clean_up();
167 
168  /* Audio listener stuff */
169 
170  /* Returns the current audio listener, or NULL if there
171  * is no explicit audio listener set, and there are no current
172  * render pipelines.
173  *
174  * Behaviour is:
175  *
176  * - Explictly set listener
177  * - Or, First camera of first render pipeline
178  * - Or, NULL
179  */
180  StageNode* audio_listener();
181 
182  /* Sets a stage node explicitly as the audio listener */
183  void set_audio_listener(StageNode* node);
184 
185  /* Returns true if an explicit audio listener is being used */
186  bool has_explicit_audio_listener() const;
187 
189  bool has_context() const { return has_context_; }
190 
192  bool has_focus() const { return has_focus_; }
193 
196  void set_has_focus(bool v=true) {
197  has_focus_ = v;
198  }
199 
201  void create_panels();
202 
204  void destroy_panels();
205 protected:
206  std::shared_ptr<Renderer> renderer_;
207 
208  void set_vsync_enabled(bool vsync) {
209  vsync_enabled_ = vsync;
210  }
211 
212  void set_width(uint16_t width) {
213  width_ = width;
214  }
215 
216  void set_height(uint16_t height) {
217  height_ = height;
218  }
219 
220  void set_bpp(uint16_t bpp) {
221  bpp_ = bpp;
222  }
223 
224  void set_fullscreen(bool val) {
225  fullscreen_ = val;
226  }
227 
228  virtual void destroy_window() = 0;
229 
230  Window();
231 
232  void set_has_context(bool value=true);
233  thread::Mutex& context_lock() { return context_lock_; }
234 
235  void set_application(Application* app) { application_ = app; }
236 
237  void update_screens(float dt);
238  sig::Connection update_conn_;
239 public:
240  void set_escape_to_quit(bool value=true) { escape_to_quit_ = value; }
241  bool escape_to_quit_enabled() const { return escape_to_quit_; }
242 
243  // Panels
244  void register_panel(uint8_t function_key, std::shared_ptr<Panel> panel);
245  void unregister_panel(uint8_t function_key);
246  void toggle_panel(uint8_t id);
247  void activate_panel(uint8_t id);
248  void deactivate_panel(uint8_t id);
249  bool panel_is_active(uint8_t id);
250 private:
251  Application* application_ = nullptr;
252 
253  void create_defaults();
254  virtual void initialize_input_controller(InputState& controller) = 0;
255 
256  bool can_attach_sound_by_id() const { return false; }
257 
258  bool initialized_;
259 
260  uint16_t width_ = 0;
261  uint16_t height_ = 0;
262  uint16_t bpp_ = 0;
263  bool fullscreen_ = false;
264  bool vsync_enabled_ = false;
265 
266  bool escape_to_quit_ = true;
267 
268  bool has_context_ = false;
269  bool has_focus_ = false;
270 
271  struct PanelEntry {
272  std::shared_ptr<Panel> panel;
273  };
274 
275  std::unordered_map<uint8_t, PanelEntry> panels_;
276 
277  /*
278  * Sometimes we need to destroy or recreate the GL context, if that happens while we are rendering in the
279  * main thread, then bad things happen. This lock exists so that we don't destroy the context while we are rendering.
280  * We obtain the lock before rendering, and release it after. Likewise we obtain the lock while destroying the context
281  * (we can use has_context to make sure we don't start rendering when there is no context) */
282  thread::Mutex context_lock_;
283 
284  void destroy() {}
285 
286  std::shared_ptr<smlt::Compositor> compositor_;
287  generic::DataCarrier data_carrier_;
288 
289  virtual std::shared_ptr<SoundDriver> create_sound_driver(const std::string& from_config) = 0;
290 
291  std::shared_ptr<InputState> input_state_;
292  std::shared_ptr<InputManager> input_manager_;
293 
294  std::unordered_map<std::string, Screen::ptr> screens_;
295 
296  /* This is called by Screens to render themselves to devices. Default behaviour is a no-op */
297  virtual void render_screen(Screen* screen, const uint8_t* data, int row_stride) {
298  _S_UNUSED(screen);
299  _S_UNUSED(data);
300  _S_UNUSED(row_stride);
301  }
302 
303  /* To be overridden by subclasses if external screens need some kind of initialization/clean_up */
304  virtual bool initialize_screen(Screen* screen) {
305  _S_UNUSED(screen);
306  return true;
307  }
308 
309  virtual void shutdown_screen(Screen* screen) {
310  _S_UNUSED(screen);
311  }
312 
313  StageNode* audio_listener_ = nullptr;
314 protected:
315  friend class GameController;
316 
317  InputState* _input_state() const { return input_state_.get(); }
318 
319  virtual void game_controller_start_rumble(GameController *controller, RangeValue<0, 1> low_rumble, RangeValue<0, 1> high_rumble, const smlt::Seconds& duration) {
320  _S_UNUSED(controller);
321  _S_UNUSED(low_rumble);
322  _S_UNUSED(high_rumble);
323  _S_UNUSED(duration);
324  }
325 
326  virtual void game_controller_stop_rumble(GameController *controller) {
327  _S_UNUSED(controller);
328  }
329 
330 public:
331  //Read only properties
332  S_DEFINE_PROPERTY(application, &Window::application_);
333  S_DEFINE_PROPERTY(renderer, &Window::renderer_);
334  S_DEFINE_PROPERTY(data, &Window::data_carrier_);
335  S_DEFINE_PROPERTY(input, &Window::input_manager_);
336  S_DEFINE_PROPERTY(input_state, &Window::input_state_);
337  S_DEFINE_PROPERTY(compositor, &Window::compositor_);
338 };
339 
340 }
341 
342 #endif
smlt::Application
Definition: application.h:157
smlt
Definition: animation.cpp:25
smlt::Window
Definition: window.h:65
smlt::Window::reset
void reset()
Window::reset.
Definition: window.cpp:275
smlt::Window::set_has_focus
void set_has_focus(bool v=true)
Definition: window.h:196
smlt::RenderTarget
Definition: interfaces.h:27
smlt::Window::has_context
bool has_context() const
Definition: window.h:189
smlt::Loadable
Definition: loadable.h:26
smlt::ModifierKeyState
Definition: event_listener.h:40
smlt::StageNode
Definition: stage_node.h:61
smlt::Screen
Definition: screen.h:20
smlt::Seconds
Definition: types.h:55
smlt::Renderer
Definition: renderer.h:40
smlt::Window::create_panels
void create_panels()
Definition: window.cpp:253
smlt::Window::destroy_panels
void destroy_panels()
Definition: window.cpp:261
smlt::EventListenerManager
Definition: event_listener.h:126
smlt::Window::has_focus
bool has_focus() const
Definition: window.h:192
smlt::Vec2
Definition: vec2.h:13
smlt::sig::signal
Definition: signal.h:319