Gamedev Framework (gf)  0.2.0
A C++11 framework for 2D games
Transformable.h
1 /*
2  * Gamedev Framework (gf)
3  * Copyright (C) 2016 Julien Bernard
4  *
5  * This software is provided 'as-is', without any express or implied
6  * warranty. In no event will the authors be held liable for any damages
7  * arising from the use of this software.
8  *
9  * Permission is granted to anyone to use this software for any purpose,
10  * including commercial applications, and to alter it and redistribute it
11  * freely, subject to the following restrictions:
12  *
13  * 1. The origin of this software must not be misrepresented; you must not
14  * claim that you wrote the original software. If you use this software
15  * in a product, an acknowledgment in the product documentation would be
16  * appreciated but is not required.
17  * 2. Altered source versions must be plainly marked as such, and must not be
18  * misrepresented as being the original software.
19  * 3. This notice may not be removed or altered from any source distribution.
20  *
21  * Part of this file comes from SFML, with the same license:
22  * Copyright (C) 2007-2015 Laurent Gomila (laurent@sfml-dev.org)
23  */
24 #ifndef GF_TRANSFORMABLE_H
25 #define GF_TRANSFORMABLE_H
26 
27 #include "Drawable.h"
28 #include "Matrix.h"
29 #include "Portability.h"
30 #include "Rect.h"
31 #include "Vector.h"
32 
33 namespace gf {
34 #ifndef DOXYGEN_SHOULD_SKIP_THIS
35 inline namespace v1 {
36 #endif
37 
38  /**
39  * @ingroup graphics
40  * @brief The origin anchor of the transformable object
41  *
42  *
43  * @sa Transformable::setOrigin()
44  */
45  enum class Anchor {
46  Center, ///< Center
47  TopLeft, ///< Top-left
48  TopRight, ///< Top-right
49  BottomLeft, ///< Bottom-left
50  BottomRight, ///< Bottom-right
51  };
52 
53  /**
54  * @ingroup graphics
55  * @brief Decomposed transform defined by a position, a rotation and a scale
56  *
57  * gf::Matrix3f, as a low-level class, offers a great level of
58  * flexibility but it is not always convenient to manage. Indeed,
59  * one can easily combine any kind of operation, such as a translation
60  * followed by a rotation followed by a scaling, but once the result
61  * transform is built, there's no way to go backward and, let's say,
62  * change only the rotation without modifying the translation and scaling.
63  * The entire transform must be recomputed, which means that you
64  * need to retrieve the initial translation and scale factors as
65  * well, and combine them the same way you did before updating the
66  * rotation. This is a tedious operation, and it requires to store
67  * all the individual components of the final transform.
68  *
69  * That's exactly what gf::Transformable was written for: it hides
70  * these variables and the composed transform behind an easy to use
71  * interface. You can set or get any of the individual components
72  * without worrying about the others. It also provides the composed
73  * transform (as a gf::Matrix3f), and keeps it up-to-date.
74  *
75  * In addition to the position, rotation and scale, gf::Transformable
76  * provides an "origin" component, which represents the local origin
77  * of the three other components. Let's take an example with a 10x10
78  * pixels sprite. By default, the sprite is positioned/rotated/scaled
79  * relatively to its top-left corner, because it is the local point
80  * @f$(0, 0)@f$. But if we change the origin to be @f$(5, 5)@f$, the
81  * sprite will be positioned/rotated/scaled around its center instead.
82  * And if we set the origin to @f$(10, 10)@f$, it will be transformed
83  * around its bottom-right corner.
84  *
85  * To keep the gf::Transformable class simple, there's only one
86  * origin for all the components. You cannot position the sprite
87  * relatively to its top-left corner while rotating it around its
88  * center, for example. To do such things, use gf::Matrix3f directly.
89  *
90  * gf::Transformable can be used as a base class. That's what
91  * gf's sprites, texts, curves and shapes do.
92  *
93  * ~~~{.cc}
94  * class MyEntity : public gf::Transformable {
95  * virtual void draw(gf::RenderTarget& target, gf::RenderStates states) override {
96  * states.transform *= getTransform();
97  * target.draw(..., states);
98  * }
99  * };
100  *
101  * MyEntity entity;
102  * entity.setPosition(10, 20);
103  * entity.setRotation(45);
104  * renderer.draw(entity);
105  * ~~~
106  *
107  * @sa gf::Matrix3f
108  */
109  class GF_API Transformable : public Drawable {
110  public:
111  /**
112  * @brief Default constructor
113  *
114  * By default:
115  *
116  * - the origin is set to @f$(0,0)@f$
117  * - the position is set to @f$(0,0)@f$
118  * - the rotation is set to @f$ 0 @f$
119  * - the scale is set to @f$(1,1)@f$
120  */
121  Transformable();
122 
123  /**
124  * @brief Set the local origin of the object
125  *
126  * The origin of an object defines the center point for
127  * all transformations (position, scale, rotation).
128  * The coordinates of this point must be relative to the
129  * top-left corner of the object, and ignore all
130  * transformations (position, scale, rotation).
131  *
132  * The default origin of a transformable object is @f$(0, 0)@f$.
133  *
134  * @param origin New origin
135  *
136  * @sa getOrigin()
137  */
138  void setOrigin(Vector2f origin);
139 
140  /**
141  * @brief Get the local origin of the object
142  *
143  * @return Current origin
144  *
145  * @sa setOrigin()
146  */
147  Vector2f getOrigin() const {
148  return m_origin;
149  }
150 
151  /**
152  * @brief Set the position of the object
153  *
154  * This function completely overwrites the previous position.
155  * See the move() function to apply an offset based on the previous
156  * position instead.
157  *
158  * The default position of a transformable object is @f$(0, 0)@f$.
159  *
160  * @param position New position
161  *
162  * @sa move(), getPosition()
163  */
164  void setPosition(Vector2f position);
165 
166  /**
167  * @brief Get the position of the object
168  *
169  * @return Current position
170  *
171  * @sa setPosition
172  */
173  Vector2f getPosition() const {
174  return m_position;
175  }
176 
177  /**
178  * @brief Move the object by a given offset
179  *
180  * This function adds to the current position of the object,
181  * unlike setPosition() which overwrites it.
182  * Thus, it is equivalent to the following code:
183  *
184  * ~~~{.cc}
185  * object.setPosition(object.getPosition() + offset);
186  * ~~~
187  *
188  * @param offset Offset
189  *
190  * @sa setPosition()
191  */
192  void move(Vector2f offset);
193 
194  /**
195  * @brief Set the orientation of the object
196  *
197  * This function completely overwrites the previous rotation.
198  * See the rotate() function to add an angle based on the previous
199  * rotation instead.
200  *
201  * The default rotation of a transformable object is @f$ 0 @f$.
202  *
203  * @param angle New rotation, in radians
204  *
205  * @sa rotate(), getRotation()
206  */
207  void setRotation(float angle);
208 
209  /**
210  * @brief Get the orientation of the object
211  *
212  * @return Current rotation, in radians
213  *
214  * @sa setRotation()
215  */
216  float getRotation() const {
217  return m_rotation;
218  }
219 
220  /**
221  * @brief Rotate the object
222  *
223  * This function adds to the current rotation of the object,
224  * unlike setRotation() which overwrites it.
225  * Thus, it is equivalent to the following code:
226  *
227  * ~~~{.cc}
228  * object.setRotation(object.getRotation() + angle);
229  * ~~~
230  *
231  * @param angle Angle of rotation, in radians
232  */
233  void rotate(float angle);
234 
235  /**
236  * @brief Set the scale factors of the object
237  *
238  * This function completely overwrites the previous scale.
239  * See the scale() function to add a factor based on the previous
240  * scale instead.
241  *
242  * The default scale of a transformable object is @f$(1, 1)@f$.
243  *
244  * @param factors New scale factors
245  *
246  * @sa scale(), getScale()
247  */
248  void setScale(Vector2f factors);
249 
250 
251  /**
252  * @brief Set the scale factor of the object
253  *
254  * This function is a shortcut when the scale factors for @f$ x @f$
255  * and @f$ y @f$ are the same. It is equivalent to:
256  *
257  * ~~~{.cc}
258  * object.setScale({ factor, factor });
259  * ~~~
260  *
261  * @param factor New scale factor
262  *
263  * @sa scale(), getScale()
264  */
265  void setScale(float factor) {
266  setScale({ factor, factor });
267  }
268 
269  /**
270  * @brief Get the current scale of the object
271  *
272  * @return Current scale factors
273  *
274  * @sa setScale()
275  */
276  Vector2f getScale() const {
277  return m_scale;
278  }
279 
280  /**
281  * @brief Scale the object
282  *
283  * This function multiplies the current scale of the object,
284  * unlike setScale() which overwrites it.
285  * Thus, it is equivalent to the following code:
286  *
287  * ~~~{.cc}
288  * object.setScale(object.getScale() * factors);
289  * ~~~
290  *
291  * @param factors Scale factors
292  *
293  * @sa setScale()
294  */
295  void scale(Vector2f factors);
296 
297  /**
298  * @brief Scale the object
299  *
300  * This function is a shortcut when the scale factors for @f$ x @f$
301  * and @f$ y @f$ are the same. It is equivalent to:
302  *
303  * ~~~{.cc}
304  * object.scale({ factor, factor });
305  * ~~~
306  *
307  * @param factor Scale factor
308  *
309  * @sa setScale()
310  */
311  void scale(float factor) {
312  scale({ factor, factor });
313  }
314 
315  /**
316  * @brief Get the combined transform of the object
317  *
318  * The combined transform of the object is (in this order):
319  *
320  * - a translation of -origin
321  * - a scaling of the defined scaling factors
322  * - a rotation of the defined angle
323  * - a translation of the defined position
324  *
325  * @return Transform combining the position/rotation/scale/origin of the object
326  *
327  * @sa getInverseTransform()
328  */
329  Matrix3f getTransform() const;
330 
331  /**
332  * @brief Get the inverse of the combined transform of the object
333  *
334  * @return Inverse of the combined transformations applied to the object
335  *
336  * @sa getTransform()
337  */
338  Matrix3f getInverseTransform() const;
339 
340  protected:
341  /**
342  * @brief Set the origin from an anchor and bounds
343  *
344  * This function can be called from derived classes for setting the origin
345  * properly thanks to an anchor and the bounds they computed.
346  *
347  * @param anchor An anchor
348  * @param bounds The bounds of the entity
349  */
350  void setOriginFromAnchorAndBounds(Anchor anchor, const RectF& bounds);
351 
352  private:
353  Vector2f m_origin;
354  Vector2f m_position;
355  float m_rotation;
356  Vector2f m_scale;
357  };
358 
359 #ifndef DOXYGEN_SHOULD_SKIP_THIS
360 }
361 #endif
362 }
363 
364 #endif // GF_TRANSFORMABLE_H
Decomposed transform defined by a position, a rotation and a scale.
Definition: Transformable.h:109
void scale(float factor)
Scale the object.
Definition: Transformable.h:311
void setPosition(Vector2f position)
Set the position of the object.
Vector2f getPosition() const
Get the position of the object.
Definition: Transformable.h:173
void rotate(float angle)
Rotate the object.
float getRotation() const
Get the orientation of the object.
Definition: Transformable.h:216
void setScale(float factor)
Set the scale factor of the object.
Definition: Transformable.h:265
constexpr Vector(T x, T y)
Constructor that takes 2 components.
Definition: Vector.h:355
void setRotation(float angle)
Set the orientation of the object.
Vector2f getScale() const
Get the current scale of the object.
Definition: Transformable.h:276
void scale(Vector2f factors)
Scale the object.
Abstract base class for objects that can be drawn to a render window.
Definition: Drawable.h:79
void move(Vector2f offset)
Move the object by a given offset.
Transformable()
Default constructor.
Matrix3f getInverseTransform() const
Get the inverse of the combined transform of the object.
Definition: Action.h:34
void setOrigin(Vector2f origin)
Set the local origin of the object.
void setOriginFromAnchorAndBounds(Anchor anchor, const RectF &bounds)
Set the origin from an anchor and bounds.
Anchor
The origin anchor of the transformable object.
Definition: Transformable.h:45
Matrix3f getTransform() const
Get the combined transform of the object.
#define GF_API
Definition: Portability.h:35
Vector2f getOrigin() const
Get the local origin of the object.
Definition: Transformable.h:147
void setScale(Vector2f factors)
Set the scale factors of the object.