diff options
Diffstat (limited to 'scene/3d/node_3d.h')
-rw-r--r-- | scene/3d/node_3d.h | 31 |
1 files changed, 25 insertions, 6 deletions
diff --git a/scene/3d/node_3d.h b/scene/3d/node_3d.h index 3d561e8620..cfd88585e4 100644 --- a/scene/3d/node_3d.h +++ b/scene/3d/node_3d.h @@ -52,6 +52,9 @@ class Node3D : public Node { GDCLASS(Node3D, Node); public: + // Edit mode for the rotation. + // THIS MODE ONLY AFFECTS HOW DATA IS EDITED AND SAVED + // IT DOES _NOT_ AFFECT THE TRANSFORM LOGIC (see comment in TransformDirty). enum RotationEditMode { ROTATION_EDIT_MODE_EULER, ROTATION_EDIT_MODE_QUATERNION, @@ -68,11 +71,27 @@ public: }; private: + // For the sake of ease of use, Node3D can operate with Transforms (Basis+Origin), Quaterinon/Scale and Euler Rotation/Scale. + // Transform and Quaterinon are stored in data.local_transform Basis (so quaternion is not really stored, but converted back/forth from 3x3 matrix on demand). + // Euler needs to be kept separate because converting to Basis and back may result in a different vector (which is troublesome for users + // editing in the inspector, not only because of the numerical precision loss but because they expect these rotations to be consistent, or support + // "redundant" rotations for animation interpolation, like going from 0 to 720 degrees). + // + // As such, the system works in a way where if the local transform is set (via transform/basis/quaternion), the EULER rotation and scale becomes dirty. + // It will remain dirty until reading back is attempted (for performance reasons). Likewise, if the Euler rotation scale are set, the local transform + // will become dirty (and again, will not become valid again until read). + // + // All this is transparent from outside the Node3D API, which allows everything to works by calling these functions in exchange. + // + // Additionally, setting either transform, quaternion, Euler rotation or scale makes the global transform dirty, which will be updated when read again. + // + // NOTE: Again, RotationEditMode is _independent_ of this mechanism, it is only meant to expose the right set of properties for editing (editor) and saving + // (to scene, in order to keep the same values and avoid data loss on conversions). It has zero influence in the logic described above. enum TransformDirty { DIRTY_NONE = 0, - DIRTY_VECTORS = 1, - DIRTY_LOCAL = 2, - DIRTY_GLOBAL = 4 + DIRTY_EULER_ROTATION_AND_SCALE = 1, + DIRTY_LOCAL_TRANSFORM = 2, + DIRTY_GLOBAL_TRANSFORM = 4 }; mutable SelfList<Node> xform_change; @@ -80,9 +99,8 @@ private: struct Data { mutable Transform3D global_transform; mutable Transform3D local_transform; - mutable Basis::EulerOrder rotation_order = Basis::EULER_ORDER_YXZ; - mutable Quaternion quaternion; - mutable Vector3 rotation; + mutable Basis::EulerOrder euler_rotation_order = Basis::EULER_ORDER_YXZ; + mutable Vector3 euler_rotation; mutable Vector3 scale = Vector3(1, 1, 1); mutable RotationEditMode rotation_edit_mode = ROTATION_EDIT_MODE_EULER; @@ -132,6 +150,7 @@ protected: _FORCE_INLINE_ void set_ignore_transform_notification(bool p_ignore) { data.ignore_notification = p_ignore; } _FORCE_INLINE_ void _update_local_transform() const; + _FORCE_INLINE_ void _update_rotation_and_scale() const; void _notification(int p_what); static void _bind_methods(); |