supertux
editor.hpp
1 // SuperTux
2 // Copyright (C) 2015 Hume2 <teratux.mail@gmail.com>
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
16 
17 #ifndef HEADER_SUPERTUX_EDITOR_EDITOR_HPP
18 #define HEADER_SUPERTUX_EDITOR_EDITOR_HPP
19 
20 #include <functional>
21 #include <vector>
22 #include <string>
23 
24 #include <physfs.h>
25 
26 #include "editor/overlay_widget.hpp"
27 #include "editor/tilebox.hpp"
28 #include "editor/toolbox_widget.hpp"
29 #include "editor/layers_widget.hpp"
30 #include "editor/scroller_widget.hpp"
31 #include "supertux/screen.hpp"
32 #include "supertux/world.hpp"
33 #include "util/currenton.hpp"
34 #include "util/file_system.hpp"
35 #include "util/log.hpp"
36 #include "util/string_util.hpp"
37 #include "video/surface_ptr.hpp"
38 
39 class ButtonWidget;
40 class GameObject;
41 class Level;
42 class ObjectGroup;
43 class Path;
44 class Savegame;
45 class Sector;
46 class TileSet;
47 class World;
48 
49 class Editor final : public Screen,
50  public Currenton<Editor>
51 {
52 public:
53  static bool is_active();
54 
55  static PHYSFS_EnumerateCallbackResult foreach_recurse(void *data,
56  const char *origdir,
57  const char *fname);
58 
59 private:
60  static bool is_autosave_file(const std::string& filename) {
61  return StringUtil::has_suffix(filename, "~");
62  }
63  static std::string get_levelname_from_autosave(const std::string& filename) {
64  return is_autosave_file(filename) ? filename.substr(0, filename.size() - 1) : filename;
65  }
66  static std::string get_autosave_from_levelname(const std::string& filename) {
67  return is_autosave_file(filename) ? filename : filename + "~";
68  }
69 
70 public:
71  static bool s_resaving_in_progress;
72 
73 public:
74  Editor();
75  ~Editor() override;
76 
77  virtual void draw(Compositor&) override;
78  virtual void update(float dt_sec, const Controller& controller) override;
79 
80  virtual void setup() override;
81  virtual void leave() override;
82 
83  virtual IntegrationStatus get_status() const override;
84 
85  void event(const SDL_Event& ev);
86  void resize();
87 
88  void disable_keyboard() { m_enabled = false; }
89 
90  Level* get_level() const { return m_level.get(); }
91 
92  void set_world(std::unique_ptr<World> w);
93  World* get_world() const { return m_world.get(); }
94 
95  TileSet* get_tileset() const { return m_tileset; }
96  TileSelection* get_tiles() const { return m_toolbox_widget->get_tilebox().get_tiles(); }
97  std::string get_tileselect_object() const { return m_toolbox_widget->get_tilebox().get_object(); }
98 
99  EditorTilebox::InputType get_tileselect_input_type() const { return m_toolbox_widget->get_tilebox().get_input_type(); }
100 
101  bool has_active_toolbox_tip() const { return m_toolbox_widget->get_tilebox().has_active_object_tip(); }
102 
103  int get_tileselect_select_mode() const;
104  int get_tileselect_move_mode() const;
105 
106  const std::string& get_levelfile() const { return m_levelfile; }
107 
108  void set_level(const std::string& levelfile_) {
109  m_levelfile = levelfile_;
110  m_reload_request = true;
111  }
112 
113  std::string get_level_directory() const;
114 
115  void open_level_directory();
116 
117  bool is_testing_level() const { return m_leveltested; }
118 
119  void remove_autosave_file();
120 
122  void convert_tiles_by_file(const std::string& file);
123 
124  void check_deprecated_tiles(bool focus = false);
125  bool has_deprecated_tiles() const { return m_has_deprecated_tiles; }
126 
130  void check_save_prerequisites(const std::function<void ()>& callback) const;
131  void check_unsaved_changes(const std::function<void ()>& action);
132 
133  void load_sector(const std::string& name);
134  void delete_current_sector();
135 
136  void update_node_iterators();
137  void esc_press();
138  void delete_markers();
139  void sort_layers();
140 
141  void select_tilegroup(int id);
142  const std::vector<Tilegroup>& get_tilegroups() const;
143  void change_tileset();
144 
145  void select_objectgroup(int id);
146  const std::vector<ObjectGroup>& get_objectgroups() const;
147 
148  void scroll(const Vector& velocity);
149 
150  bool is_level_loaded() const { return m_levelloaded; }
151 
152  void edit_path(PathGameObject* path, GameObject* new_marked_object) {
153  m_overlay_widget->edit_path(path, new_marked_object);
154  }
155 
156  void add_layer(GameObject* layer) { m_layers_widget->add_layer(layer); }
157 
158  TileMap* get_selected_tilemap() const { return m_layers_widget->get_selected_tilemap(); }
159 
160  Sector* get_sector() { return m_sector; }
161 
162  void retoggle_undo_tracking();
163  void undo_stack_cleanup();
164 
165  void undo();
166  void redo();
167 
168  void pack_addon();
169 
170 private:
171  void set_sector(Sector* sector);
172  void set_level(std::unique_ptr<Level> level, bool reset = true);
173  void reload_level();
174  void quit_editor();
181  void save_level(const std::string& filename = "", bool switch_file = false);
182  void test_level(const std::optional<std::pair<std::string, Vector>>& test_pos);
183  void update_keyboard(const Controller& controller);
184 
185  void keep_camera_in_bounds();
186 
187  void post_undo_redo_actions();
188 
189 protected:
190  std::unique_ptr<Level> m_level;
191  std::unique_ptr<World> m_world;
192 
193  std::string m_levelfile;
194  std::string m_autosave_levelfile;
195 
196 public:
197  bool m_quit_request;
198  bool m_newlevel_request;
199  bool m_reload_request;
200  bool m_reactivate_request;
201  bool m_deactivate_request;
202  bool m_save_request;
203  std::string m_save_request_filename;
204  bool m_save_request_switch;
205  bool m_test_request;
206  bool m_particle_editor_request;
207  std::optional<std::pair<std::string, Vector>> m_test_pos;
208 
209  std::string* m_particle_editor_filename;
210 
211 private:
212  Sector* m_sector;
213 
214  bool m_levelloaded;
215  bool m_leveltested;
216  bool m_after_setup; // Set to true after setup function finishes and to false after leave function finishes
217 
218  TileSet* m_tileset;
219  bool m_has_deprecated_tiles;
220 
221  std::vector<std::unique_ptr<Widget> > m_widgets;
222  ButtonWidget* m_undo_widget;
223  ButtonWidget* m_redo_widget;
224  EditorOverlayWidget* m_overlay_widget;
225  EditorToolboxWidget* m_toolbox_widget;
226  EditorLayersWidget* m_layers_widget;
227 
228  bool m_enabled;
229  SurfacePtr m_bgr_surface;
230 
231  float m_time_since_last_save;
232 
233  float m_scroll_speed;
234  float m_new_scale;
235 
236  bool m_ctrl_pressed;
237  Vector m_mouse_pos;
238 
239 private:
240  Editor(const Editor&) = delete;
241  Editor& operator=(const Editor&) = delete;
242 };
243 
244 #endif
245 
246 /* EOF */
Definition: controller.hpp:57
void convert_tiles_by_file(const std::string &file)
Convert tiles on every tilemap in the level, according to a tile conversion file. ...
Definition: editor.cpp:722
Definition: button_widget.hpp:28
The toolbox is on the right side of the screen and allows selection of the current tool and contains ...
Definition: toolbox_widget.hpp:36
Abstract base class for code the MainLoop runs exclusively and full-screen.
Definition: screen.hpp:31
Definition: world.hpp:26
A widget that is drawn on top of the current sector and handles mouse input and tool drawing...
Definition: overlay_widget.hpp:43
void check_save_prerequisites(const std::function< void()> &callback) const
Checks whether the level can be saved and does not contain obvious issues (currently: check if main s...
Definition: editor.cpp:992
Represents one of (potentially) multiple, separate parts of a Level.
Definition: sector.hpp:61
virtual void leave() override
gets called when the current screen is temporarily suspended
Definition: editor.cpp:781
Definition: path.hpp:48
A &#39;Currenton&#39; allows access to the currently active instance of a class via the static current() func...
Definition: currenton.hpp:30
virtual void setup() override
gets called before this screen gets activated (which is at least once before the first draw or update...
Definition: editor.cpp:789
Represents a collection of Sectors running in a single GameSession.
Definition: level.hpp:30
This class is responsible for: Updating and drawing the object.
Definition: game_object.hpp:83
Definition: tile_selection.hpp:24
Definition: compositor.hpp:29
Definition: integration.hpp:26
Definition: savegame.hpp:69
Definition: object_group.hpp:27
Definition: editor.hpp:49
virtual void draw(Compositor &) override
gets called once per frame.
Definition: editor.cpp:151
This class is responsible for managing an array of tiles.
Definition: tilemap.hpp:49
virtual void update(float dt_sec, const Controller &controller) override
gets called for once (per logical) frame.
Definition: editor.cpp:203
Definition: tile_set.hpp:44
Definition: path_gameobject.hpp:32
A widget at the bottom of the screen for switching between tilemap layers and other non-movable GameO...
Definition: layers_widget.hpp:42
virtual IntegrationStatus get_status() const override
Gives details about what the user is doing right now.
Definition: editor.cpp:1105