You've already forked godot
mirror of
https://github.com/godotengine/godot.git
synced 2025-11-05 12:10:55 +00:00
Fix PathFollow3D update issues
- transform is not updated after setting new flags such as `use_model_front` - transform is not updated when the parent Path3D changes - correct_posture() behaves differently when assuming model front - _update_transform() was in immediate mode, could leads to chained calls on scene instantiation.
This commit is contained in:
@@ -165,13 +165,14 @@ void Path3D::_curve_changed() {
|
|||||||
emit_signal(SNAME("curve_changed"));
|
emit_signal(SNAME("curve_changed"));
|
||||||
}
|
}
|
||||||
|
|
||||||
// update the configuration warnings of all children of type PathFollow
|
// Update the configuration warnings of all children of type PathFollow
|
||||||
// previously used for PathFollowOriented (now enforced orientation is done in PathFollow)
|
// previously used for PathFollowOriented (now enforced orientation is done in PathFollow). Also trigger transform update on PathFollow3Ds in deferred mode.
|
||||||
if (is_inside_tree()) {
|
if (is_inside_tree()) {
|
||||||
for (int i = 0; i < get_child_count(); i++) {
|
for (int i = 0; i < get_child_count(); i++) {
|
||||||
PathFollow3D *child = Object::cast_to<PathFollow3D>(get_child(i));
|
PathFollow3D *child = Object::cast_to<PathFollow3D>(get_child(i));
|
||||||
if (child) {
|
if (child) {
|
||||||
child->update_configuration_warnings();
|
child->update_configuration_warnings();
|
||||||
|
child->update_transform();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -207,9 +208,24 @@ void Path3D::_bind_methods() {
|
|||||||
ADD_SIGNAL(MethodInfo("curve_changed"));
|
ADD_SIGNAL(MethodInfo("curve_changed"));
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////
|
// Update transform, in deferred mode by default to avoid superfluity.
|
||||||
|
void PathFollow3D::update_transform(bool p_immediate) {
|
||||||
|
transform_dirty = true;
|
||||||
|
|
||||||
|
if (p_immediate) {
|
||||||
|
_update_transform();
|
||||||
|
} else {
|
||||||
|
callable_mp(this, &PathFollow3D::_update_transform).call_deferred();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update transform immediately .
|
||||||
|
void PathFollow3D::_update_transform() {
|
||||||
|
if (!transform_dirty) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
transform_dirty = false;
|
||||||
|
|
||||||
void PathFollow3D::_update_transform(bool p_update_xyz_rot) {
|
|
||||||
if (!path) {
|
if (!path) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -231,23 +247,25 @@ void PathFollow3D::_update_transform(bool p_update_xyz_rot) {
|
|||||||
t.origin = pos;
|
t.origin = pos;
|
||||||
} else {
|
} else {
|
||||||
t = c->sample_baked_with_rotation(progress, cubic, false);
|
t = c->sample_baked_with_rotation(progress, cubic, false);
|
||||||
|
Vector3 tangent = -t.basis.get_column(2); // Retain tangent for applying tilt.
|
||||||
|
t = PathFollow3D::correct_posture(t, rotation_mode);
|
||||||
|
|
||||||
|
// Switch Z+ and Z- if necessary.
|
||||||
if (use_model_front) {
|
if (use_model_front) {
|
||||||
t.basis *= Basis::from_scale(Vector3(-1.0, 1.0, -1.0));
|
t.basis *= Basis::from_scale(Vector3(-1.0, 1.0, -1.0));
|
||||||
}
|
}
|
||||||
Vector3 forward = t.basis.get_column(2); // Retain tangent for applying tilt
|
|
||||||
t = PathFollow3D::correct_posture(t, rotation_mode);
|
|
||||||
|
|
||||||
// Apply tilt *after* correct_posture
|
// Apply tilt *after* correct_posture().
|
||||||
if (tilt_enabled) {
|
if (tilt_enabled) {
|
||||||
const real_t tilt = c->sample_baked_tilt(progress);
|
const real_t tilt = c->sample_baked_tilt(progress);
|
||||||
|
|
||||||
const Basis twist(forward, tilt);
|
const Basis twist(tangent, tilt);
|
||||||
t.basis = twist * t.basis;
|
t.basis = twist * t.basis;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Apply offset and scale.
|
||||||
Vector3 scale = get_transform().basis.get_scale();
|
Vector3 scale = get_transform().basis.get_scale();
|
||||||
|
|
||||||
t.translate_local(Vector3(h_offset, v_offset, 0));
|
t.translate_local(Vector3(h_offset, v_offset, 0));
|
||||||
t.basis.scale_local(scale);
|
t.basis.scale_local(scale);
|
||||||
|
|
||||||
@@ -261,7 +279,7 @@ void PathFollow3D::_notification(int p_what) {
|
|||||||
if (parent) {
|
if (parent) {
|
||||||
path = Object::cast_to<Path3D>(parent);
|
path = Object::cast_to<Path3D>(parent);
|
||||||
if (path) {
|
if (path) {
|
||||||
_update_transform(false);
|
update_transform();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
@@ -316,11 +334,10 @@ Transform3D PathFollow3D::correct_posture(Transform3D p_transform, PathFollow3D:
|
|||||||
// Clear rotation.
|
// Clear rotation.
|
||||||
t.basis = Basis();
|
t.basis = Basis();
|
||||||
} else if (p_rotation_mode == PathFollow3D::ROTATION_ORIENTED) {
|
} else if (p_rotation_mode == PathFollow3D::ROTATION_ORIENTED) {
|
||||||
// Y-axis always straight up.
|
Vector3 tangent = -t.basis.get_column(2);
|
||||||
Vector3 up(0.0, 1.0, 0.0);
|
|
||||||
Vector3 forward = t.basis.get_column(2);
|
|
||||||
|
|
||||||
t.basis = Basis::looking_at(-forward, up);
|
// Y-axis points up by default.
|
||||||
|
t.basis = Basis::looking_at(tangent);
|
||||||
} else {
|
} else {
|
||||||
// Lock some euler axes.
|
// Lock some euler axes.
|
||||||
Vector3 euler = t.basis.get_euler_normalized(EulerOrder::YXZ);
|
Vector3 euler = t.basis.get_euler_normalized(EulerOrder::YXZ);
|
||||||
@@ -405,14 +422,14 @@ void PathFollow3D::set_progress(real_t p_progress) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_update_transform();
|
update_transform();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PathFollow3D::set_h_offset(real_t p_h_offset) {
|
void PathFollow3D::set_h_offset(real_t p_h_offset) {
|
||||||
h_offset = p_h_offset;
|
h_offset = p_h_offset;
|
||||||
if (path) {
|
if (path) {
|
||||||
_update_transform();
|
update_transform();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -423,7 +440,7 @@ real_t PathFollow3D::get_h_offset() const {
|
|||||||
void PathFollow3D::set_v_offset(real_t p_v_offset) {
|
void PathFollow3D::set_v_offset(real_t p_v_offset) {
|
||||||
v_offset = p_v_offset;
|
v_offset = p_v_offset;
|
||||||
if (path) {
|
if (path) {
|
||||||
_update_transform();
|
update_transform();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -453,7 +470,7 @@ void PathFollow3D::set_rotation_mode(RotationMode p_rotation_mode) {
|
|||||||
rotation_mode = p_rotation_mode;
|
rotation_mode = p_rotation_mode;
|
||||||
|
|
||||||
update_configuration_warnings();
|
update_configuration_warnings();
|
||||||
_update_transform();
|
update_transform();
|
||||||
}
|
}
|
||||||
|
|
||||||
PathFollow3D::RotationMode PathFollow3D::get_rotation_mode() const {
|
PathFollow3D::RotationMode PathFollow3D::get_rotation_mode() const {
|
||||||
@@ -462,6 +479,7 @@ PathFollow3D::RotationMode PathFollow3D::get_rotation_mode() const {
|
|||||||
|
|
||||||
void PathFollow3D::set_use_model_front(bool p_use_model_front) {
|
void PathFollow3D::set_use_model_front(bool p_use_model_front) {
|
||||||
use_model_front = p_use_model_front;
|
use_model_front = p_use_model_front;
|
||||||
|
update_transform();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PathFollow3D::is_using_model_front() const {
|
bool PathFollow3D::is_using_model_front() const {
|
||||||
@@ -470,6 +488,7 @@ bool PathFollow3D::is_using_model_front() const {
|
|||||||
|
|
||||||
void PathFollow3D::set_loop(bool p_loop) {
|
void PathFollow3D::set_loop(bool p_loop) {
|
||||||
loop = p_loop;
|
loop = p_loop;
|
||||||
|
update_transform();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PathFollow3D::has_loop() const {
|
bool PathFollow3D::has_loop() const {
|
||||||
@@ -478,6 +497,7 @@ bool PathFollow3D::has_loop() const {
|
|||||||
|
|
||||||
void PathFollow3D::set_tilt_enabled(bool p_enabled) {
|
void PathFollow3D::set_tilt_enabled(bool p_enabled) {
|
||||||
tilt_enabled = p_enabled;
|
tilt_enabled = p_enabled;
|
||||||
|
update_transform();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PathFollow3D::is_tilt_enabled() const {
|
bool PathFollow3D::is_tilt_enabled() const {
|
||||||
|
|||||||
@@ -72,10 +72,6 @@ public:
|
|||||||
ROTATION_ORIENTED
|
ROTATION_ORIENTED
|
||||||
};
|
};
|
||||||
|
|
||||||
bool use_model_front = false;
|
|
||||||
|
|
||||||
static Transform3D correct_posture(Transform3D p_transform, PathFollow3D::RotationMode p_rotation_mode);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Path3D *path = nullptr;
|
Path3D *path = nullptr;
|
||||||
real_t progress = 0.0;
|
real_t progress = 0.0;
|
||||||
@@ -84,14 +80,16 @@ private:
|
|||||||
bool cubic = true;
|
bool cubic = true;
|
||||||
bool loop = true;
|
bool loop = true;
|
||||||
bool tilt_enabled = true;
|
bool tilt_enabled = true;
|
||||||
|
bool transform_dirty = true;
|
||||||
|
bool use_model_front = false;
|
||||||
RotationMode rotation_mode = ROTATION_XYZ;
|
RotationMode rotation_mode = ROTATION_XYZ;
|
||||||
|
|
||||||
void _update_transform(bool p_update_xyz_rot = true);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void _validate_property(PropertyInfo &p_property) const;
|
void _validate_property(PropertyInfo &p_property) const;
|
||||||
|
|
||||||
void _notification(int p_what);
|
void _notification(int p_what);
|
||||||
|
void _update_transform();
|
||||||
|
|
||||||
static void _bind_methods();
|
static void _bind_methods();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@@ -124,6 +122,10 @@ public:
|
|||||||
|
|
||||||
PackedStringArray get_configuration_warnings() const override;
|
PackedStringArray get_configuration_warnings() const override;
|
||||||
|
|
||||||
|
void update_transform(bool p_immediate = false);
|
||||||
|
|
||||||
|
static Transform3D correct_posture(Transform3D p_transform, PathFollow3D::RotationMode p_rotation_mode);
|
||||||
|
|
||||||
PathFollow3D() {}
|
PathFollow3D() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user