1// SuperTux
2// Copyright (C) 2006 Matthias Braun <matze@braunis.de>
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_SUPERTUX_GAME_OBJECT_HPP
18#define HEADER_SUPERTUX_SUPERTUX_GAME_OBJECT_HPP
19
20#include <algorithm>
21#include <string>
22
23#include "editor/object_settings.hpp"
24#include "supertux/game_object_component.hpp"
25#include "util/gettext.hpp"
26#include "util/uid.hpp"
27
28class DrawingContext;
29class GameObjectComponent;
30class ObjectRemoveListener;
31class ReaderMapping;
32class Writer;
33
34/**
35 Base class for all the things that make up Levels' Sectors.
36
37 Each sector of a level will hold a list of active GameObject while the
38 game is played.
39
40 This class is responsible for:
41 - Updating and Drawing the object. This should happen in the update() and
42 draw() functions. Both are called once per frame.
43 - Providing a safe way to remove the object by calling the remove_me
44 functions.
45*/
46class GameObject
47{
48 friend class GameObjectManager;
49
50public:
51 GameObject();
52 GameObject(const std::string& name);
53 GameObject(const ReaderMapping& reader);
54 virtual ~GameObject();
55
56 /** Called after all objects have been added to the Sector and the
57 Sector is fully constructed. If objects refer to other objects
58 by name, those connection can be resolved here. */
59 virtual void finish_construction() {}
60
61 UID get_uid() const { return m_uid; }
62
63 /** This function is called once per frame and allows the object to
64 update it's state. The dt_sec is the time that has passed since
65 the last frame in seconds and should be the base for all timed
66 calculations (don't use SDL_GetTicks directly as this will fail
67 in pause mode). This function is not called in the Editor. */
68 virtual void update(float dt_sec) = 0;
69
70 /** The GameObject should draw itself onto the provided
71 DrawingContext if this function is called. */
72 virtual void draw(DrawingContext& context) = 0;
73
74 /** This function saves the object. Editor will use that. */
75 void save(Writer& writer);
76 virtual std::string get_class() const { return "game-object"; }
77 virtual std::string get_display_name() const { return _("Unknown object"); }
78
79 /** If true only a single object of this type is allowed in a
80 given GameObjectManager */
81 virtual bool is_singleton() const { return false; }
82
83 /** Does this object have variable size
84 (secret area trigger, wind, etc.) */
85 virtual bool has_variable_size() const { return false; }
86
87 /** Indicates if the object will be saved. If false, the object will
88 be skipped on saving and can't be cloned in the editor. */
89 virtual bool is_saveable() const { return true; }
90
91 /** Indicates if get_settings() is implemented. If true the editor
92 will display Tip and ObjectMenu. */
93 virtual bool has_settings() const { return is_saveable(); }
94 virtual ObjectSettings get_settings();
95
96 virtual void after_editor_set() {}
97
98 /** returns true if the object is not scheduled to be removed yet */
99 bool is_valid() const { return !m_scheduled_for_removal; }
100
101 /** schedules this object to be removed at the end of the frame */
102 void remove_me() { m_scheduled_for_removal = true; }
103
104 /** registers a remove listener which will be called if the object
105 gets removed/destroyed */
106 void add_remove_listener(ObjectRemoveListener* listener);
107
108 /** unregisters a remove listener, so it will no longer be called if
109 the object gets removed/destroyed */
110 void del_remove_listener(ObjectRemoveListener* listener);
111
112 void set_name(const std::string& name) { m_name = name; }
113 const std::string& get_name() const { return m_name; }
114
115 virtual const std::string get_icon_path() const {
116 return "images/tiles/auxiliary/notile.png";
117 }
118
119 /** stops all looping sounds */
120 virtual void stop_looping_sounds() {}
121
122 /** continues all looping sounds */
123 virtual void play_looping_sounds() {}
124
125 template<typename T>
126 T* get_component() {
127 for(auto& component : m_components) {
128 if (T* result = dynamic_cast<T*>(component.get())) {
129 return result;
130 }
131 }
132 return nullptr;
133 }
134
135 void add_component(std::unique_ptr<GameObjectComponent> component) {
136 m_components.emplace_back(std::move(component));
137 }
138
139 void remove_component(GameObjectComponent* component) {
140 auto it = std::find_if(m_components.begin(), m_components.end(),
141 [component](const std::unique_ptr<GameObjectComponent>& lhs){
142 return lhs.get() == component;
143 });
144 if (it != m_components.end()) {
145 m_components.erase(it);
146 }
147 }
148
149 /** The editor requested the deletion of the object */
150 virtual void editor_delete() { remove_me(); }
151
152 /** The user clicked on the object in the editor and selected it*/
153 virtual void editor_select() {}
154
155 /** The object got deselected */
156 virtual void editor_deselect() {}
157
158 /** Called each frame in the editor, used to keep linked objects
159 together (e.g. platform on a path) */
160 virtual void editor_update() {}
161
162private:
163 void set_uid(const UID& uid) { m_uid = uid; }
164
165protected:
166 /** a name for the gameobject, this is mostly a hint for scripts and
167 for debugging, don't rely on names being set or being unique */
168 std::string m_name;
169
170private:
171 /** A unique id for the object to safely refer to it. This will be
172 set by the GameObjectManager. */
173 UID m_uid;
174
175 /** this flag indicates if the object should be removed at the end of the frame */
176 bool m_scheduled_for_removal;
177
178 std::vector<std::unique_ptr<GameObjectComponent> > m_components;
179
180 std::vector<ObjectRemoveListener*> m_remove_listeners;
181
182private:
183 GameObject(const GameObject&) = delete;
184 GameObject& operator=(const GameObject&) = delete;
185};
186
187#endif
188
189/* EOF */
190