1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
|
#ifndef TRANSFORM_H
#define TRANSFORM_H
#include "Runtime/Math/Quaternion.h"
#include "Runtime/BaseClasses/GameObject.h"
#include "Runtime/Utilities/dynamic_array.h"
#include "Runtime/Utilities/EnumFlags.h"
#include "Runtime/Modules/ExportModules.h"
using std::vector; //TODO:refactor
/** Transformcomponent stores rotation and position of objects
* A Transformcomponent can also have child Transformcomponent's,
* which then rotate and translate relative to their father.
* Local space is the space which is relative to its father while world space is an absolute space
* Local and Worldspace is the same if the transformcomponent does not have a father.
* The localspace functions are faster than the worldspace functions
*/
class EXPORT_COREMODULE Transform : public Unity::Component
{
public:
typedef dynamic_array<ImmediatePtr<Transform> > TransformComList;
typedef TransformComList::iterator iterator;
typedef void TransformChangedCallback (Transform* t);
typedef void HierarchyChangedCallback (Transform* t);
typedef void HierarchyChangedCallbackSetParent (Transform* obj, Transform* oldParent, Transform* newParent);
private:
Quaternionf m_LocalRotation;
Vector3f m_LocalPosition;
Vector3f m_LocalScale;
mutable Matrix4x4f m_CachedTransformMatrix;
mutable UInt8 m_CachedTransformType;
mutable UInt8 m_HasCachedTransformMatrix;
mutable UInt8 m_HasChanged;
public:
// This tracks kNoScaleTransform, kUniformScaleTransform and kNonUniformScaleTransform, kHasNegativeScale
UInt8 m_InternalTransformType;
UInt8 m_SupportsTransformChanged;
TransformComList m_Children;
ImmediatePtr<Transform> m_Father;
#if UNITY_EDITOR
#if ENABLE_EDITOR_HIERARCHY_ORDERING
typedef std::pair<std::string, int> VisibleRootSecondaryKey;
typedef std::pair<SInt32, VisibleRootSecondaryKey> VisibleRootKey;
#else
typedef std::pair<std::string, int> VisibleRootKey;
#endif
struct CompareVisibleRoots
{
bool operator() (const VisibleRootKey& lhs, const VisibleRootKey& rhs) const;
};
typedef std::map<VisibleRootKey, Transform*, CompareVisibleRoots> VisibleRootMap;
VisibleRootMap::iterator m_VisibleRootIterator;
bool m_VisibleRootValid;
Vector3f m_LocalEulerAnglesHint;
#endif
#if ENABLE_EDITOR_HIERARCHY_ORDERING
SInt32 m_Order;
#endif
public:
REGISTER_DERIVED_CLASS (Transform, Component)
DECLARE_OBJECT_SERIALIZE (Transform)
Transform (MemLabelId label, ObjectCreationMode mode);
// virtual ~Transform (); declared-by-macro
virtual void AwakeFromLoad (AwakeFromLoadMode awakeMode);
virtual void CheckConsistency ();
virtual void SupportedMessagesDidChange (int mask);
// Tag class as sealed, this makes QueryComponent faster.
static bool IsSealedClass () { return true; }
/// Returns a ptr to the father transformcomponent (NULL if no father)
Transform *GetParent () const { return m_Father; }
/// Returns a reference to the root transform (top most transform with no parent)
Transform& GetRoot ();
/// Finds given transform
iterator Find( const Transform* child );
/// access to the children
int GetChildrenCount ()const { return m_Children.size (); }
Transform &GetChild (int i) const { Assert (i < (int)m_Children.size()); return *m_Children[i]; }
iterator begin () { return m_Children.begin (); }
iterator end () { return m_Children.end (); }
/// Sets the father to p(if p is invalid the Transformcomponent will have no father)
/// Returns false if the father could not be set
/// This happens only if you are trying to set the father to one of its direct/indirect children.
enum SetParentOption { kWorldPositionStays = 1 << 0, kLocalPositionStays = 1 << 1, kAllowParentingFromPrefab = 1 << 2, kDisableTransformMessage = 1 << 3 };
bool SetParent (Transform * parent, SetParentOption options = kWorldPositionStays);
/// Sets the rotation in local space
void SetLocalRotation (const Quaternionf& rotation);
/// Sets the Rotation in world space
void SetRotation (const Quaternionf& rotation);
/// Sets the local euler angles
void SetLocalEulerAngles (const Vector3f& eulerAngles);
/// Sets the position in local space
/// (If the object has no father, localspace is basically the same as world space)
void SetLocalPosition (const Vector3f& inTranslation);
/// Sets the position in world space
void SetPosition (const Vector3f& position);
/// Sets the position - a local space offset will be scaled, rotated and subtracted from the position.
/// Used to set the position For CharacterController and NavMeshAgent that have baseOffset / center.
/// For retreiving the position with a local offset use: TransformPoint (localOffset)
void SetPositionWithLocalOffset (const Vector3f& p, const Vector3f& localOffset);
/// Transforms local space position to world space - while applying an offset which is scaled and rotated accordingly.
Vector3f TransformPointWithLocalOffset (const Vector3f& p, const Vector3f& localOffset) const;
/// Same as above but normalizes the quaternion
void SetLocalRotationSafe (const Quaternionf& rotation);
void SetRotationSafe (const Quaternionf& rotation);
/// Sets the scale in local space
void SetLocalScale (const Vector3f& scale);
/// Sets the scale from a rotation * scale
/// The transform can not hold the full scale if it contains skew
void SetWorldRotationAndScale (const Matrix3x3f& worldRotationAndScale);
/// Sets the world position and rotation
void SetPositionAndRotation (const Vector3f& position, const Quaternionf& rotation);
void SetLocalPositionAndRotation (const Vector3f& position, const Quaternionf& rotation);
/// Return matrix that converts a point from World To Local space
Matrix4x4f GetWorldToLocalMatrix () const;
/// Return matrix that converts a point from Local To World space
Matrix4x4f GetLocalToWorldMatrix () const;
Matrix4x4f GetWorldToLocalMatrixNoScale () const;
const Matrix4x4f& GetWorldToLocalMatrixNoScale (Matrix4x4f& m) const;
Matrix4x4f GetLocalToWorldMatrixNoScale () const;
const Matrix4x4f& GetLocalToWorldMatrixNoScale (Matrix4x4f& m) const;
TransformType CalculateTransformMatrix (Matrix4x4f& matrix) const;
TransformType CalculateTransformMatrixScaleDelta (Matrix4x4f& matrix) const;
TransformType CalculateTransformMatrixDisableNonUniformScale (Matrix4x4f& matrix, Matrix4x4f& scaleOnly, float& scale) const;
TransformType CalculateTransformMatrixDisableScale (Matrix4x4f& matrix) const;
/// Whether the transform has changed since the last time this flag was set to 'false'.
bool GetChangedFlag () { return m_HasChanged; }
/// Sets the flag indicating whether the transform has changed. Most commonly used to simply set it to 'false'.
void SetChangedFlag (bool val) { m_HasChanged = val; }
/// Gets the rotation from local to world space
Quaternionf GetRotation () const;
/// Gets the local rotation
Quaternionf GetLocalRotation () const { return m_LocalRotation; }
/// Gets the local euler angles (in the editor it is first ensures that they are in sync with the local rotation quaternion)
Vector3f GetLocalEulerAngles ();
/// Gets the local position relative to the father
Vector3f GetLocalPosition () const {return m_LocalPosition;}
/// Gets the position in world space
Vector3f GetPosition () const;
/// Returns the local scale
Vector3f GetLocalScale () const { return m_LocalScale; }
/// Returns the world rotation and scale.
/// (It is impossible to return a Vector3 because the scale might be skewed)
Matrix3x3f GetWorldRotationAndScale () const;
Matrix3x3f GetWorldScale () const;
Vector3f GetWorldScaleLossy () const;
/// Rotates the transform around axis by rad
void RotateAroundLocal (const Vector3f& localAxis, float rad);
/// Same, but normalizes the axis for you
void RotateAroundLocalSafe (const Vector3f& localAxis, float rad);
/// Rotates the transform around axis by rad
void RotateAround (const Vector3f& worldAxis, float rad);
/// Same, but normalizes the axis for you
void RotateAroundSafe (const Vector3f& worldAxis, float rad);
/// transforms a point from localspace to worldspace
Vector3f TransformPoint (const Vector3f& inPoint) const;
/// Transforms a direction from localspace to worldspace
/// (Ignores scale)
Vector3f TransformDirection (const Vector3f& inDirection) const;
/// Transforms a point from worldspace to localspace
Vector3f InverseTransformPoint (const Vector3f& inDirection) const;
/// Transforms a direction from worldspace to localspace
/// (Ignores scale)
Vector3f InverseTransformDirection (const Vector3f& inDirection) const;
#if UNITY_EDITOR
/// Register a function which is called whenever a transformcomponent is changed
static void RegisterHierarchyChangedCallback (HierarchyChangedCallback* callback);
static void RegisterHierarchyChangedSetParentCallback (HierarchyChangedCallbackSetParent* callback);
VisibleRootMap::iterator* GetVisibleRootIterator () { return m_VisibleRootValid ? &m_VisibleRootIterator : NULL; }
void SetVisibleRootIterator (const VisibleRootMap::iterator& it) { m_VisibleRootIterator = it; m_VisibleRootValid = true; }
void ClearVisibleRootIterator () { m_VisibleRootValid = false; }
#endif // End UNITY_EDITOR
#if ENABLE_EDITOR_HIERARCHY_ORDERING
static int CompareDepths(Transform* lhs, Transform* rhs);
SInt32 GetOrder () const { return m_Order; }
void SetOrder (SInt32 order);
void OrderChildrenRecursively();
void GetSortedChildList (TransformComList& sortedChildren) const;
#endif
TransformComList& GetChildrenInternal () { return m_Children; }
const TransformComList& GetChildrenInternal () const { return m_Children; }
ImmediatePtr<Transform>& GetParentPtrInternal () { return m_Father; }
/// Reset position&rotation
void Reset ();
/// Sets the world position and rotation without sending out a TransformChanged message to the gameobject and without setting dirty
/// (Not sending TransformChanged will result in the Renderer
/// not updating the AABB to reflect the transform change)
void SetPositionAndRotationWithoutNotification (const Vector3f& position, const Quaternionf& q);
void SetPositionWithoutNotification (const Vector3f& position);
void SetRotationWithoutNotification (const Quaternionf& q);
void SetPositionAndRotationSafeWithoutNotification (const Vector3f& p, const Quaternionf& q);
void SetPositionAndRotationSafe (const Vector3f& p, const Quaternionf& q);
void GetPositionAndRotation (Vector3f& pos, Quaternionf& q)const;
TransformType GetPositionAndRotationWithTransformType (Vector3f& worldPos, Quaternionf& worldRot) const;
/// You seldomly want to call this function yourself.
/// Sends the transform changed message to itself and all children.
/// A bitmask specifies which components have changed!
/// kParentingChanged is also called when SetOrder(SInt32) is called. (Editor Only)
enum { kPositionChanged = 1 << 0, kRotationChanged = 1 << 1, kScaleChanged = 1 << 3, kAnimatePhysics = 1 << 4, kParentingChanged = 1 << 5};
void SendTransformChanged (int mask);
/// private but used by datatemplates
void RemoveFromParent ();
void ClearChildrenParentPointer ();
void ClearChild (Transform* child);
/// Broadcasts a message to this and all child transforms
void BroadcastMessageAny(const MessageIdentifier& message, MessageData& data);
void SetLocalTRS (const Vector3f& pos, const Quaternionf& rot, const Vector3f& scale);
inline void SetLocalRotationWithoutNotification (const Quaternionf& rotation)
{
m_LocalRotation = rotation;
#if UNITY_EDITOR
SyncLocalEulerAnglesHint ();
#endif
}
inline void SetLocalPositionWithoutNotification (const Vector3f& inTranslation)
{
m_LocalPosition = inTranslation;
}
inline void SetLocalScaleWithoutNotification (const Vector3f& scale)
{
m_LocalScale = scale;
RecalculateTransformType ();
}
// For use only by the animation system
void RecalculateTransformType ();
UInt32 CalculateSupportedMessages ();
void MakeEditorValuesLookNice();
private:
friend class AnimationBinder;
friend void SampleAnimation (GameObject& go, class AnimationClip& clip, float inTime, int wrapMode, float deltaTime);
TransformType CalculateLocalTransformMatrix(Matrix4x4f& matrix) const;
TransformType CalculateTransformMatrixIterative (Matrix4x4f& matrix) const;
void SetCacheDirty();
template<bool Safe, bool Notify>
void SetPositionAndRotationInternal( const Vector3f& position, const Quaternionf& rotation );
#if UNITY_EDITOR
/// Makes the local euler angles be in sync with the quaternion rotation
void SyncLocalEulerAnglesHint ();
#endif
};
ENUM_FLAGS(Transform::SetParentOption);
Transform* FindRelativeTransformWithPath (Transform& transform, const char* path);
Transform* FindActiveTransformWithPath (const char* path);
Transform* FindTransformWithName (Transform* root, const char* name);
std::string CalculateTransformPath (const Transform& transform, const Transform* to);
void AppendTransformPath (string& path, const char* appendName);
void AppendTransformPath (UnityStr& path, const char* appendName);
/// Is transform a child of parent? Or is the transform the same.
bool IsChildOrSameTransform(Transform& transform, Transform& parent);
EXPORT_COREMODULE int GetTransformDepth(Transform& transform);
#endif
|