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