1 //  SuperTuxKart - a fun racing game with go-kart
2 //
3 //  Copyright (C) 2013-2015 Joerg Henrichs, Marianne Gagnon
4 //
5 //  This program is free software; you can redistribute it and/or
6 //  modify it under the terms of the GNU General Public License
7 //  as published by the Free Software Foundation; either version 3
8 //  of the License, or (at your option) any later version.
9 //
10 //  This program 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 General Public License for more details.
14 //
15 //  You should have received a copy of the GNU General Public License
16 //  along with this program; if not, write to the Free Software
17 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18 
19 
20 #ifndef HEADER_TRACK_OBJECT_PRESENTATION_HPP
21 #define HEADER_TRACK_OBJECT_PRESENTATION_HPP
22 
23 #include "graphics/lod_node.hpp"
24 #include "utils/cpp2011.hpp"
25 #include "utils/no_copy.hpp"
26 #include "utils/log.hpp"
27 #include "utils/leak_check.hpp"
28 #include "utils/time.hpp"
29 #include "utils/vec3.hpp"
30 
31 #include <vector3d.h>
32 #include <IAnimatedMeshSceneNode.h>
33 
34 #include <memory>
35 #include <limits>
36 #include <string>
37 
38 class SFXBase;
39 class ParticleEmitter;
40 class PhysicalObject;
41 class ThreeDAnimation;
42 class ModelDefinitionLoader;
43 class RenderInfo;
44 class STKInstancedSceneNode;
45 class XMLNode;
46 class TrackObject;
47 
48 namespace irr
49 {
50     namespace scene { class IAnimatedMesh; class IMeshSceneNode; class ISceneNode; }
51 }
52 using namespace irr;
53 
54 /** \ingroup tracks
55  *  Base class for all track object presentation classes.
56  */
57 class TrackObjectPresentation
58 {
59 protected:
60     /** The initial XYZ position of the object. */
61     core::vector3df                m_init_xyz;
62 
63     /** The initial hpr of the object. */
64     core::vector3df                m_init_hpr;
65 
66     /** The initial scale of the object. */
67     core::vector3df                m_init_scale;
68 
69 
70 public:
71 
72     TrackObjectPresentation(const XMLNode& xml_node);
73 
TrackObjectPresentation(const core::vector3df & xyz,const core::vector3df & hpr=core::vector3df (0,0,0),const core::vector3df & scale=core::vector3df (0,0,0))74     TrackObjectPresentation(const core::vector3df& xyz,
75                             const core::vector3df& hpr = core::vector3df(0,0,0),
76                             const core::vector3df& scale = core::vector3df(0,0,0))
77     {
78         m_init_xyz = xyz;
79         m_init_hpr = hpr;
80         m_init_scale = scale;
81     }   // TrackObjectPresentation
82 
83     // ------------------------------------------------------------------------
~TrackObjectPresentation()84     virtual ~TrackObjectPresentation() {}
85     // ------------------------------------------------------------------------
86 
reset()87     virtual void reset() {}
setEnable(bool enabled)88     virtual void setEnable(bool enabled)
89     {
90         Log::warn("TrackObjectPresentation", "setEnable unimplemented for this presentation type");
91     }
updateGraphics(float dt)92     virtual void updateGraphics(float dt) {}
update(float dt)93     virtual void update(float dt) {}
move(const core::vector3df & xyz,const core::vector3df & hpr,const core::vector3df & scale,bool isAbsoluteCoord)94     virtual void move(const core::vector3df& xyz, const core::vector3df& hpr,
95         const core::vector3df& scale, bool isAbsoluteCoord) {}
96 
97     // ------------------------------------------------------------------------
98     /** Returns the position of this TrackObjectPresentation. */
getPosition() const99     virtual const core::vector3df& getPosition() const { return m_init_xyz; }
100     // ------------------------------------------------------------------------
101     /** Returns a copy of the initial position. Note this function does not
102      *  return a const reference, since some classes overwrite it this way. */
getAbsolutePosition() const103     virtual const core::vector3df getAbsolutePosition() const
104     {
105         return m_init_xyz;
106     }   // getAbsolutePosition
107     // ------------------------------------------------------------------------
getAbsoluteCenterPosition() const108     virtual const core::vector3df getAbsoluteCenterPosition() const
109     {
110         return m_init_xyz;
111     }
112     // ------------------------------------------------------------------------
113     /** Returns the initial rotation. */
getRotation() const114     virtual const core::vector3df& getRotation() const { return m_init_hpr; }
115     // ------------------------------------------------------------------------
116     /** Returns the initial scale. */
getScale() const117     virtual const core::vector3df& getScale() const { return m_init_scale; }
118 
119     LEAK_CHECK()
120 };
121 
122 // ============================================================================
123 /** \ingroup tracks
124  *  Base class for all track object presentation classes using a scene node
125  *  as presentation
126  */
127 class TrackObjectPresentationSceneNode : public TrackObjectPresentation
128 {
129 protected:
130     /** A pointer to the scene node of this object. */
131     scene::ISceneNode* m_node;
132 
133     bool m_force_always_hidden;
134 public:
135 
136     /** Constructor based on data from xml. */
TrackObjectPresentationSceneNode(const XMLNode & xml_node)137     TrackObjectPresentationSceneNode(const XMLNode& xml_node) :
138         TrackObjectPresentation(xml_node)
139     {
140         m_node = NULL;
141         m_force_always_hidden = false;
142     }   // TrackObjectPresentationSceneNode
143     // ------------------------------------------------------------------------
144     /** Constructor based on a transform. */
TrackObjectPresentationSceneNode(const core::vector3df & xyz,const core::vector3df & hpr,const core::vector3df & scale,scene::ISceneNode * node=NULL)145     TrackObjectPresentationSceneNode(const core::vector3df& xyz,
146                                      const core::vector3df& hpr,
147                                      const core::vector3df& scale,
148                                      scene::ISceneNode* node = NULL) :
149         TrackObjectPresentation(xyz, hpr, scale)
150     {
151         m_node = node;
152         m_force_always_hidden = false;
153     }   // TrackObjectPresentationSceneNode
154 
155     // ------------------------------------------------------------------------
156     virtual const core::vector3df& getPosition() const OVERRIDE;
157     virtual const core::vector3df  getAbsolutePosition() const OVERRIDE;
158     virtual const core::vector3df getAbsoluteCenterPosition() const OVERRIDE;
159     virtual const core::vector3df& getRotation() const OVERRIDE;
160     virtual const core::vector3df& getScale() const OVERRIDE;
161     virtual void move(const core::vector3df& xyz, const core::vector3df& hpr,
162         const core::vector3df& scale, bool isAbsoluteCoord) OVERRIDE;
163     virtual void setEnable(bool enabled) OVERRIDE;
164     virtual void reset() OVERRIDE;
165 
166     // ------------------------------------------------------------------------
167     /** Returns a pointer to the scene node. */
getNode()168     scene::ISceneNode* getNode() { return m_node; }
169     // ------------------------------------------------------------------------
170     /** Returns a pointer to the scene node, const version. */
getNode() const171     const scene::ISceneNode* getNode() const { return m_node; }
172     // ------------------------------------------------------------------------
isAlwaysHidden() const173     bool isAlwaysHidden() const { return m_force_always_hidden; }
174 };   // class TrackObjectPresentationSceneNode
175 
176 // ============================================================================
177 /** \ingroup tracks
178  *  A track object representation that is invisible and only consists of a
179  *  location, rotation and scale.
180  */
181 class TrackObjectPresentationEmpty : public TrackObjectPresentationSceneNode
182 {
183 public:
184     TrackObjectPresentationEmpty(const XMLNode& xml_node);
185     virtual ~TrackObjectPresentationEmpty();
186 };   // class TrackObjectPresentationEmpty
187 
188 // ============================================================================
189 /** \ingroup tracks
190  *  A track object representation that is a library node
191  */
192 class TrackObjectPresentationLibraryNode : public TrackObjectPresentationSceneNode
193 {
194     TrackObject* m_parent;
195     using TrackObjectPresentationSceneNode::move;
196     std::string m_name;
197     bool m_start_executed, m_reset_executed;
198 public:
199     TrackObjectPresentationLibraryNode(TrackObject* parent,
200         const XMLNode& xml_node,
201         ModelDefinitionLoader& model_def_loader);
202     virtual ~TrackObjectPresentationLibraryNode();
203     virtual void update(float dt) OVERRIDE;
reset()204     virtual void reset() OVERRIDE
205     {
206         m_reset_executed = false;
207         TrackObjectPresentationSceneNode::reset();
208     }
209     virtual void move(const core::vector3df& xyz, const core::vector3df& hpr,
210         const core::vector3df& scale, bool isAbsoluteCoord) OVERRIDE;
211 };   // TrackObjectPresentationLibraryNode
212 
213 // ============================================================================
214 /** \ingroup tracks
215  *  A track object representation that consists of a level-of-detail scene node
216  */
217 class TrackObjectPresentationLOD : public TrackObjectPresentationSceneNode
218 {
219 public:
220 
221     TrackObjectPresentationLOD(const XMLNode& xml_node,
222                                scene::ISceneNode* parent,
223                                ModelDefinitionLoader& model_def_loader,
224                                std::shared_ptr<RenderInfo> ri);
225     virtual ~TrackObjectPresentationLOD();
226     virtual void reset() OVERRIDE;
227 };
228 
229 // ============================================================================
230 /** \ingroup tracks
231  *  A track object representation that consists of a mesh scene node.
232  */
233 class TrackObjectPresentationMesh : public TrackObjectPresentationSceneNode
234 {
235 private:
236     /** The mesh used here. It needs to be stored so that it can be
237      *  removed from irrlicht's mesh cache when it is deleted. */
238     scene::IMesh                  *m_mesh;
239 
240     /** True if it is a looped animation. */
241     bool                    m_is_looped;
242 
243     /** True if the object is in the skybox */
244     bool                    m_is_in_skybox;
245 
246     std::string             m_model_file;
247 
248     std::shared_ptr<RenderInfo> m_render_info;
249 
250     void init(const XMLNode* xml_node, scene::ISceneNode* parent, bool enabled);
251 
252 public:
253     TrackObjectPresentationMesh(const XMLNode& xml_node, bool enabled,
254                                 scene::ISceneNode* parent,
255                                 std::shared_ptr<RenderInfo> render_info);
256 
257     TrackObjectPresentationMesh(const std::string& model_file,
258                                 const core::vector3df& xyz,
259                                 const core::vector3df& hpr,
260                                 const core::vector3df& scale);
261     TrackObjectPresentationMesh(scene::IAnimatedMesh* mesh,
262                                 const core::vector3df& xyz,
263                                 const core::vector3df& hpr,
264                                 const core::vector3df& scale);
265     virtual ~TrackObjectPresentationMesh();
266     virtual void reset() OVERRIDE;
267     // ------------------------------------------------------------------------
268     /** Returns the mode file name. */
getModelFile() const269     const std::string& getModelFile() const { return m_model_file; }
270 };   // class TrackObjectPresentationMesh
271 
272 // ============================================================================
273 /** \ingroup tracks
274  *  A track object representation that consists of a sound emitter
275  */
276 class TrackObjectPresentationSound : public TrackObjectPresentation
277 {
278 private:
279 
280     /** If a sound is attached to this object and/or this is a sound emitter
281      *  object */
282     SFXBase* m_sound;
283 
284     /** Currently used for sound effects only, in cutscenes only atm */
285     std::string  m_trigger_condition;
286 
287     core::vector3df m_xyz;
288 
289     bool m_enabled;
290 
291 public:
292 
293     TrackObjectPresentationSound(const XMLNode& xml_node,
294                                  scene::ISceneNode* parent,
295                                  bool disable_for_multiplayer);
296     virtual ~TrackObjectPresentationSound();
297     void onTriggerItemApproached(int kart_id);
298     virtual void updateGraphics(float dt) OVERRIDE;
299     virtual void move(const core::vector3df& xyz, const core::vector3df& hpr,
300         const core::vector3df& scale, bool isAbsoluteCoord) OVERRIDE;
301     void triggerSound(bool loop);
302     void stopSound();
303 
304     virtual void setEnable(bool enabled) OVERRIDE;
305 
306     // ------------------------------------------------------------------------
307     /** Currently used for sound effects only, in cutscenes only atm */
getTriggerCondition() const308     const std::string& getTriggerCondition() const { return m_trigger_condition; }
309 };   // TrackObjectPresentationSound
310 
311 // ============================================================================
312 /** \ingroup tracks
313  *  A track object representation that consists of a billboard scene node.
314  */
315 class TrackObjectPresentationBillboard : public TrackObjectPresentationSceneNode
316 {
317     /** To make the billboard disappear when close to the camera. Useful for
318      *  light halos: instead of "colliding" with the camera and suddenly
319      *  disappearing when clipped by frustum culling, it will gently fade out.
320      */
321     bool m_fade_out_when_close;
322     float m_fade_out_start;
323     float m_fade_out_end;
324 public:
325     TrackObjectPresentationBillboard(const XMLNode& xml_node,
326                                      scene::ISceneNode* parent);
327     virtual ~TrackObjectPresentationBillboard();
328     virtual void updateGraphics(float dt) OVERRIDE;
329 };   // TrackObjectPresentationBillboard
330 
331 
332 // ============================================================================
333 /** \ingroup tracks
334  *  A track object representation that consists of a particle emitter
335  */
336 class TrackObjectPresentationParticles : public TrackObjectPresentationSceneNode
337 {
338 private:
339     ParticleEmitter* m_emitter;
340     LODNode* m_lod_emitter_node;
341     std::string m_trigger_condition;
342     bool m_delayed_stop;
343     double m_delayed_stop_time;
344 
345 public:
346     TrackObjectPresentationParticles(const XMLNode& xml_node,
347                                      scene::ISceneNode* parent);
348     virtual ~TrackObjectPresentationParticles();
349 
350     virtual void updateGraphics(float dt) OVERRIDE;
351     void triggerParticles();
352     void stop();
353     void stopIn(double delay);
354     void setRate(float rate);
355     // ------------------------------------------------------------------------
356     /** Returns the trigger condition for this object. */
getTriggerCondition()357     std::string& getTriggerCondition() { return m_trigger_condition; }
358 };   // TrackObjectPresentationParticles
359 
360 // ============================================================================
361 /** \ingroup tracks
362  *  A track object representation that consists of a light emitter
363  */
364 class TrackObjectPresentationLight : public TrackObjectPresentationSceneNode
365 {
366 private:
367     video::SColor m_color;
368     float m_distance;
369     float m_energy;
370 public:
371     TrackObjectPresentationLight(const XMLNode& xml_node,
372                                  scene::ISceneNode* parent);
373     virtual ~TrackObjectPresentationLight();
getEnergy() const374     float getEnergy() const { return m_energy; }
375     virtual void setEnable(bool enabled) OVERRIDE;
376     void setEnergy(float energy);
377 };   // TrackObjectPresentationLight
378 
379 // ============================================================================
380 
381 enum ActionTriggerType
382 {
383     TRIGGER_TYPE_POINT = 0,
384     TRIGGER_TYPE_CYLINDER = 1
385 };
386 
387 /** \ingroup tracks
388  *  A track object representation that consists of an action trigger
389  */
390 class TrackObjectPresentationActionTrigger : public TrackObjectPresentation
391 {
392 private:
393     /** For action trigger objects */
394     std::string m_action, m_library_id, m_triggered_object, m_library_name;
395 
396     float m_xml_reenable_timeout;
397 
398     uint64_t m_reenable_timeout;
399 
400     ActionTriggerType m_type;
401 
402 public:
403     TrackObjectPresentationActionTrigger(const XMLNode& xml_node,
404                                          TrackObject* parent);
405     TrackObjectPresentationActionTrigger(const core::vector3df& xyz,
406                                          const std::string& scriptname,
407                                          float distance);
408 
~TrackObjectPresentationActionTrigger()409     virtual ~TrackObjectPresentationActionTrigger() {}
410 
411     void onTriggerItemApproached(int kart_id);
412     // ------------------------------------------------------------------------
413     /** Reset the trigger (i.e. sets it to active again). */
reset()414     virtual void reset() OVERRIDE
415                              { m_reenable_timeout = StkTime::getMonoTimeMs(); }
416     // ------------------------------------------------------------------------
417     /** Sets the trigger to be enabled or disabled. getMonoTimeMs is used to
418      *  to avoid called update which duplicated in network rewinding. */
setEnable(bool status)419     virtual void setEnable(bool status) OVERRIDE
420     {
421         m_reenable_timeout = status ? StkTime::getMonoTimeMs() :
422             std::numeric_limits<uint64_t>::max();
423     }
424     // ------------------------------------------------------------------------
setReenableTimeout(float time)425     void setReenableTimeout(float time)
426     {
427         m_reenable_timeout =
428             StkTime::getMonoTimeMs() + (uint64_t)(time * 1000.0f);
429     }
430 };   // class TrackObjectPresentationActionTrigger
431 
432 
433 #endif // TRACKOBJECTPRESENTATION_HPP
434 
435