Scene Lab
An open source project by FPL.
 All Classes Namespaces Files Functions Pages
scene_lab.h
Go to the documentation of this file.
1 // Copyright 2015 Google Inc. All rights reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #ifndef SCENE_LAB_SCENE_LAB_H_
16 #define SCENE_LAB_SCENE_LAB_H_
17 
18 #include <algorithm>
19 #include <map>
20 #include <memory>
21 #include <string>
22 #include <vector>
23 #include "flatui/flatui.h"
24 #include "fplbase/asset_manager.h"
25 #include "fplbase/input.h"
26 #include "fplbase/renderer.h"
27 #include "fplbase/utilities.h"
28 #include "mathfu/vector.h"
30 #include "scene_lab/editor_gui.h"
31 #include "scene_lab/entity_system_adapter.h"
32 #include "scene_lab_config_generated.h"
33 
34 namespace scene_lab {
35 
36 typedef std::function<void(const GenericEntityId& entity)> EntityCallback;
37 typedef std::function<void()> EditorCallback;
38 
39 /// @file
40 class SceneLab {
41  public:
42  /// Initialize Scene Lab once, when starting your game.
43  ///
44  /// Call this function as soon as you have an entity manager and font
45  /// manager. Consider giving Scene Lab a camera via SetCamera() as well.
46  void Initialize(const SceneLabConfig* config,
47  fplbase::AssetManager* asset_manager,
48  fplbase::InputSystem* input, fplbase::Renderer* renderer,
49  flatui::FontManager* font_manager);
50 
51  /// Set which entity system adapter to use.
52  void SetEntitySystemAdapter(std::unique_ptr<EntitySystemAdapter> adapter);
53 
54  /// Accessor for entity system adapter, don't hold onto this pointer.
55  EntitySystemAdapter* entity_system_adapter() const {
56  return entity_system_adapter_.get();
57  }
58 
59  /// While Scene Lab is active, you must call this once a frame, every frame.
60  void AdvanceFrame(double delta_time_seconds);
61 
62  /// Render Scene Lab and its GUI; only call this when Scene Lab is active.
63  ///
64  /// While Scene Lab is running, you are still responsible for rendering your
65  /// own game world. Call GetCamera() to get the camera you should use for
66  /// rendering.
67  ///
68  /// Warning: if you are actively using FlatUI elsewhere in your code while
69  /// Scene Lab is running, you will need to modify this function to not render
70  /// the GUI here, and call EditorGui::StartRender(), EditorGui::DrawGui(), and
71  /// EditorGui::FinishRender() yourself.
72  void Render(fplbase::Renderer* renderer);
73 
74  /// Activate Scene Lab. Once you call this, you should start calling
75  /// AdvanceFrame and Render each frame, and stop calling
76  /// EntityManager::UpdateComponents() yourself.
77  void Activate();
78 
79  /// Immediately deactivate Scene Lab. The preferred way to exit the editor is
80  /// to use RequestExit, however, as that will give the user a chance to save
81  /// their changes to the world.
82  void Deactivate();
83 
84  /// When you activate the editor, you can pass in your game's camera so the
85  /// user can seamlessly be positioned at the same place they were during the
86  /// game. Call this function before Activate().
87  void SetInitialCamera(const GenericCamera& initial_camera);
88 
89  /// Get the Scene Lab camera, so you can render the scene properly
90  /// or change its position.
91  void GetCamera(GenericCamera* camera);
92 
93  /// Highlight the specified entity, so that you can change its properties.
94  void SelectEntity(const GenericEntityId& entity);
95 
96  /// Move the specified entity to directly in front of the camera.
97  void MoveEntityToCamera(const GenericEntityId& entity);
98 
99  /// Save the current positions and properties of all entities.
100  ///
101  /// Returns true if successful or false if it failed.
102  ///
103  /// If `to_disk` is true, save to .bin and .json files and update the entity
104  /// factory's file cache. Otherwise, just update the file cache but don't
105  /// physically save the files to disk.
106  ///
107  /// If you are saving to disk, entities will be saved to the files they were
108  /// initially loaded from.
109  bool SaveScene(bool to_disk);
110 
111  /// Save the current positions and properties to disk.
112  ///
113  /// See SaveScene(bool to_disk) for more details.
114  void SaveScene() { SaveScene(true); }
115 
116  /// Request that Scene Lab exit.
117  ///
118  /// If you haven't saved your changes, it will prompt you to do so, keep them
119  /// in memory, or abandon them. Once Scene Lab decides it's okay to exit,
120  /// IsReadyToExit() will return true.
121  ///
122  /// After you've exited, you can always get back into Scene Lab by calling
123  /// Activate() again.
124  void RequestExit();
125 
126  /// Abort a previously-requested exit, which hides the confirmation dialog.
127  void AbortExit();
128 
129  /// Returns true if we are ready to exit Scene Lab (everything is saved or
130  /// discarded, etc), or false if not. Once it returns true, you can safely
131  /// deactivate the editor.
132  bool IsReadyToExit();
133 
134  /// Externally mark that some entities have been modified.
135  ///
136  /// Generally used by Scene Lab's GUI, but if you change an entity's
137  /// properties some other way, call this function to ensure the user will be
138  /// prompted to save on exiting the editor.
139  void set_entities_modified(bool b) { entities_modified_ = b; }
140 
141  /// Have entities been modified? If so, prompt the user to save before exit.
142  bool entities_modified() const { return entities_modified_; }
143 
144  /// Specify a callback to call when the editor is opened.
145  void AddOnEnterEditorCallback(EditorCallback callback);
146 
147  /// Specify a callback to call when the editor is exited.
148  void AddOnExitEditorCallback(EditorCallback callback);
149 
150  /// Specify a callback to call when an entity is created.
151  void AddOnCreateEntityCallback(EntityCallback callback);
152 
153  /// Specify a callback to call when an entity's data is updated.
154  void AddOnUpdateEntityCallback(EntityCallback callback);
155 
156  /// Specify a callback to call when an entity is deleted.
157  void AddOnDeleteEntityCallback(EntityCallback callback);
158 
159  /// Call all 'EditorEnter' callbacks.
160  void NotifyEnterEditor() const;
161 
162  /// Call all 'EditorExit' callbacks.
163  void NotifyExitEditor() const;
164 
165  /// Call all 'EntityCreated' callbacks.
166  void NotifyCreateEntity(const GenericEntityId& entity) const;
167 
168  /// Call all 'EntityUpdated' callbacks.
169  void NotifyUpdateEntity(const GenericEntityId& entity) const;
170 
171  /// Call all 'EntityDeleted' callbacks.
172  void NotifyDeleteEntity(const GenericEntityId& entity) const;
173 
174  const std::string& version() { return version_; }
175 
176  /// Config accessor, so you can access config options.
177  const SceneLabConfig* config() { return config_; }
178 
179  /// GUI accessor, so you can poke into the EditorGui.
180  EditorGui* gui() { return gui_.get(); }
181 
182  MATHFU_DEFINE_CLASS_SIMD_AWARE_NEW_DELETE
183 
184  private:
185  /// String which identifies the current version of Scene Lab.
186  ///
187  /// kVersion is used by Google developers to identify which applications
188  /// uploaded to Google Play are using this library. This allows the
189  /// development team at Google to determine the popularity of the library.
190  /// How it works: Applications that are uploaded to the Google Play Store are
191  /// scanned for this version string. We track which applications are using it
192  /// to measure popularity. You are free to remove it (of course) but we would
193  /// appreciate if you left it in.
194  static const char kVersion[];
195 
196  enum InputMode { kMoving, kEditing, kDragging };
197  enum MouseMode {
198  kMoveHorizontal, // Move along the ground.
199  kMoveVertical, // Move along a plane perpendicular to the ground and
200  // perpendicular to the camera.
201  kRotateHorizontal, // Rotate horizontally--that is, about an axis
202  // perpendicular to the ground.
203  kRotateVertical, // Rotate vertically--that is, about an axis parallel to
204  // the ground that points back towards the camera.
205  kScaleAll, // Scale on all axes as you drag up and down.
206  kScaleX, // Scale on the X axis as you drag along the ground.
207  kScaleY, // Scale on the Y axis as you drag along the ground.
208  kScaleZ, // Scale on the Z axis as you drag up and down.
209  kMouseModeCount
210  };
211 
212  // return true if we should be moving the camera and objects slowly.
213  bool PreciseMovement() const;
214 
215  // return a global vector from camera coordinates relative to the horizontal
216  // plane.
217  mathfu::vec3 GlobalFromHorizontal(float forward, float right, float up,
218  const mathfu::vec3& plane_normal) const;
219 
220  // get camera movement via W-A-S-D
221  mathfu::vec3 GetMovement() const;
222 
223  // returns true if the transform was modified
224  bool ModifyTransformBasedOnInput(GenericTransform* transform);
225 
226  /// Find the intersection between a ray and a plane.
227  /// Ensure ray_direction and plane_normal are both normalized.
228  /// Returns true if it intersects with the plane, and sets the
229  /// intersection point.
230  static bool IntersectRayToPlane(const mathfu::vec3& ray_origin,
231  const mathfu::vec3& ray_direction,
232  const mathfu::vec3& point_on_plane,
233  const mathfu::vec3& plane_normal,
234  mathfu::vec3* intersection_point);
235 
236  /// Take a point, and project it onto a plane in the direction of the plane
237  /// normal. Ensure plane_normal is normalized. Returns true if was able to
238  /// project the point, false if it wasn't (which would be a weird situation).
239  static bool ProjectPointToPlane(const mathfu::vec3& point_to_project,
240  const mathfu::vec3& point_on_plane,
241  const mathfu::vec3& plane_normal,
242  mathfu::vec3* point_projected);
243 
244  /// Serialize the entities from the given file into the given vector.
245  /// Returns true if it succeeded, false if there was an error.
246  bool SerializeEntitiesFromFile(const std::string& filename,
247  std::vector<uint8_t>* output);
248 
249  /// Load binary and (optionally) text schema files into memory, for
250  /// importing and exporting of entity data.
251  void LoadSchemaFiles();
252 
253  /// Actually write the binary data for a group of entities to the given file.
254  /// Also converts the Flatbuffers data to JSON if possible (i.e. if schemas
255  /// are laoded) and saves to text.
256  ///
257  /// Called by SaveScene() when saving to disk.
258  void WriteEntityFile(const std::string& filename,
259  const std::vector<uint8_t>& data);
260 
261  /// Get a pointer to the file extension to use for binary files. Default is
262  /// ".bin" but can be overridden in the scene lab config. The output does NOT
263  /// include the ".".
264  const char* BinaryEntityFileExtension() const;
265 
266  const SceneLabConfig* config_;
267  std::unique_ptr<EntitySystemAdapter> entity_system_adapter_;
268 
269  fplbase::AssetManager* asset_manager_;
270  fplbase::Renderer* renderer_;
271  fplbase::InputSystem* input_system_;
272  flatui::FontManager* font_manager_;
273  // Which entity are we currently editing?
274  GenericEntityId selected_entity_;
275 
276  InputMode input_mode_;
277  MouseMode mouse_mode_;
278 
279  std::unique_ptr<EditorController> controller_;
280  std::unique_ptr<EditorGui> gui_;
281  GenericCamera initial_camera_;
282 
283  // Camera angles, projected onto the horizontal plane, as defined by the
284  // camera's `up()` direction.
285  mathfu::vec3 horizontal_forward_;
286  mathfu::vec3 horizontal_right_;
287 
288  mathfu::vec3 drag_point_; // Point on the object at which we began dragging.
289  mathfu::vec3 drag_plane_normal_; // Normal of the plane we're dragging along.
290  mathfu::vec3 drag_offset_; // Offset between drag point and object's origin.
291  mathfu::vec3 drag_prev_intersect_; // Previous intersection point
292  mathfu::vec3 drag_orig_scale_; // Object scale when we started dragging.
293 
294  bool initial_camera_set_;
295  bool exit_requested_;
296  bool exit_ready_;
297  bool entities_modified_;
298 
299  // A collection of callbacks that are called when various Scene Lab events
300  // occur that other game systems may want to respond to.
301  std::vector<EditorCallback> on_enter_editor_callbacks_;
302  std::vector<EditorCallback> on_exit_editor_callbacks_;
303  std::vector<EntityCallback> on_create_entity_callbacks_;
304  std::vector<EntityCallback> on_update_entity_callbacks_;
305  std::vector<EntityCallback> on_delete_entity_callbacks_;
306 
307  protected:
308  std::string version_; // Keep a reference to the version string.
309 };
310 
311 } // namespace scene_lab
312 
313 #endif // SCENE_LAB_SCENE_LAB_H_
void GetCamera(GenericCamera *camera)
Get the Scene Lab camera, so you can render the scene properly or change its position.
void SetEntitySystemAdapter(std::unique_ptr< EntitySystemAdapter > adapter)
Set which entity system adapter to use.
Definition: editor_gui.h:38
void AddOnDeleteEntityCallback(EntityCallback callback)
Specify a callback to call when an entity is deleted.
void RequestExit()
Request that Scene Lab exit.
void AddOnUpdateEntityCallback(EntityCallback callback)
Specify a callback to call when an entity's data is updated.
void AbortExit()
Abort a previously-requested exit, which hides the confirmation dialog.
EditorGui is a FlatUI-based GUI overlay for Scene Lab to the edit window and on-screen menu buttons...
void set_entities_modified(bool b)
Externally mark that some entities have been modified.
Definition: scene_lab.h:139
void MoveEntityToCamera(const GenericEntityId &entity)
Move the specified entity to directly in front of the camera.
void Render(fplbase::Renderer *renderer)
Render Scene Lab and its GUI; only call this when Scene Lab is active.
void AddOnEnterEditorCallback(EditorCallback callback)
Specify a callback to call when the editor is opened.
void AddOnExitEditorCallback(EditorCallback callback)
Specify a callback to call when the editor is exited.
void SetInitialCamera(const GenericCamera &initial_camera)
When you activate the editor, you can pass in your game's camera so the user can seamlessly be positi...
void NotifyDeleteEntity(const GenericEntityId &entity) const
Call all 'EntityDeleted' callbacks.
Definition: scene_lab.h:40
void Activate()
Activate Scene Lab.
void SelectEntity(const GenericEntityId &entity)
Highlight the specified entity, so that you can change its properties.
void Initialize(const SceneLabConfig *config, fplbase::AssetManager *asset_manager, fplbase::InputSystem *input, fplbase::Renderer *renderer, flatui::FontManager *font_manager)
Initialize Scene Lab once, when starting your game.
void NotifyCreateEntity(const GenericEntityId &entity) const
Call all 'EntityCreated' callbacks.
Pointer and keyboard controls for Scene Lab.
void Deactivate()
Immediately deactivate Scene Lab.
EditorGui * gui()
GUI accessor, so you can poke into the EditorGui.
Definition: scene_lab.h:180
void NotifyExitEditor() const
Call all 'EditorExit' callbacks.
void AdvanceFrame(double delta_time_seconds)
While Scene Lab is active, you must call this once a frame, every frame.
void SaveScene()
Save the current positions and properties to disk.
Definition: scene_lab.h:114
bool entities_modified() const
Have entities been modified? If so, prompt the user to save before exit.
Definition: scene_lab.h:142
const SceneLabConfig * config()
Config accessor, so you can access config options.
Definition: scene_lab.h:177
bool IsReadyToExit()
Returns true if we are ready to exit Scene Lab (everything is saved or discarded, etc)...
void NotifyEnterEditor() const
Call all 'EditorEnter' callbacks.
void AddOnCreateEntityCallback(EntityCallback callback)
Specify a callback to call when an entity is created.
EntitySystemAdapter * entity_system_adapter() const
Accessor for entity system adapter, don't hold onto this pointer.
Definition: scene_lab.h:55
void NotifyUpdateEntity(const GenericEntityId &entity) const
Call all 'EntityUpdated' callbacks.