Use parallel transport in PathFollow2D.

Fixes #12995.
This commit is contained in:
Ferenc Arn 2017-11-19 14:26:55 -05:00
parent f0795ae2fe
commit 4e87f471d7
2 changed files with 22 additions and 29 deletions

View File

@ -107,28 +107,39 @@ void PathFollow2D::_update_transform() {
if (!c.is_valid()) if (!c.is_valid())
return; return;
if (delta_offset == 0) {
return;
}
float o = offset; float o = offset;
if (loop) if (loop)
o = Math::fposmod(o, c->get_baked_length()); o = Math::fposmod(o, c->get_baked_length());
Vector2 pos = c->interpolate_baked(o, cubic); Vector2 pos = c->interpolate_baked(o, cubic);
Vector2 offset = Vector2(h_offset, v_offset);
Transform2D t = get_transform();
t.set_origin(pos);
if (rotate) { if (rotate) {
Vector2 n = (c->interpolate_baked(o + lookahead, cubic) - pos).normalized(); Vector2 t_prev = (pos - c->interpolate_baked(o - delta_offset, cubic)).normalized();
Vector2 t = -n.tangent(); Vector2 t_cur = (c->interpolate_baked(o + delta_offset, cubic) - pos).normalized();
pos += n * h_offset;
pos += t * v_offset;
set_rotation(t.angle()); float dot = t_prev.dot(t_cur);
float angle = Math::acos(CLAMP(dot, -1, 1));
t.rotate(angle);
t.translate(offset);
} else { } else {
pos.x += h_offset; t.set_origin(t.get_origin() + offset);
pos.y += v_offset;
} }
set_position(pos); set_transform(t);
} }
void PathFollow2D::_notification(int p_what) { void PathFollow2D::_notification(int p_what) {
@ -176,8 +187,6 @@ bool PathFollow2D::_set(const StringName &p_name, const Variant &p_value) {
set_cubic_interpolation(p_value); set_cubic_interpolation(p_value);
} else if (String(p_name) == "loop") { } else if (String(p_name) == "loop") {
set_loop(p_value); set_loop(p_value);
} else if (String(p_name) == "lookahead") {
set_lookahead(p_value);
} else } else
return false; return false;
@ -200,8 +209,6 @@ bool PathFollow2D::_get(const StringName &p_name, Variant &r_ret) const {
r_ret = cubic; r_ret = cubic;
} else if (String(p_name) == "loop") { } else if (String(p_name) == "loop") {
r_ret = loop; r_ret = loop;
} else if (String(p_name) == "lookahead") {
r_ret = lookahead;
} else } else
return false; return false;
@ -219,7 +226,6 @@ void PathFollow2D::_get_property_list(List<PropertyInfo> *p_list) const {
p_list->push_back(PropertyInfo(Variant::BOOL, "rotate")); p_list->push_back(PropertyInfo(Variant::BOOL, "rotate"));
p_list->push_back(PropertyInfo(Variant::BOOL, "cubic_interp")); p_list->push_back(PropertyInfo(Variant::BOOL, "cubic_interp"));
p_list->push_back(PropertyInfo(Variant::BOOL, "loop")); p_list->push_back(PropertyInfo(Variant::BOOL, "loop"));
p_list->push_back(PropertyInfo(Variant::REAL, "lookahead", PROPERTY_HINT_RANGE, "0.001,1024.0,0.001"));
} }
String PathFollow2D::get_configuration_warning() const { String PathFollow2D::get_configuration_warning() const {
@ -259,7 +265,7 @@ void PathFollow2D::_bind_methods() {
} }
void PathFollow2D::set_offset(float p_offset) { void PathFollow2D::set_offset(float p_offset) {
delta_offset = p_offset - offset;
offset = p_offset; offset = p_offset;
if (path) if (path)
_update_transform(); _update_transform();
@ -310,16 +316,6 @@ float PathFollow2D::get_unit_offset() const {
return 0; return 0;
} }
void PathFollow2D::set_lookahead(float p_lookahead) {
lookahead = p_lookahead;
}
float PathFollow2D::get_lookahead() const {
return lookahead;
}
void PathFollow2D::set_rotate(bool p_rotate) { void PathFollow2D::set_rotate(bool p_rotate) {
rotate = p_rotate; rotate = p_rotate;
@ -344,11 +340,11 @@ bool PathFollow2D::has_loop() const {
PathFollow2D::PathFollow2D() { PathFollow2D::PathFollow2D() {
offset = 0; offset = 0;
delta_offset = 0;
h_offset = 0; h_offset = 0;
v_offset = 0; v_offset = 0;
path = NULL; path = NULL;
rotate = true; rotate = true;
cubic = true; cubic = true;
loop = true; loop = true;
lookahead = 4;
} }

View File

@ -60,9 +60,9 @@ public:
private: private:
Path2D *path; Path2D *path;
real_t offset; real_t offset;
real_t delta_offset; // change in offset since last _update_transform
real_t h_offset; real_t h_offset;
real_t v_offset; real_t v_offset;
real_t lookahead;
bool cubic; bool cubic;
bool loop; bool loop;
bool rotate; bool rotate;
@ -90,9 +90,6 @@ public:
void set_unit_offset(float p_unit_offset); void set_unit_offset(float p_unit_offset);
float get_unit_offset() const; float get_unit_offset() const;
void set_lookahead(float p_lookahead);
float get_lookahead() const;
void set_loop(bool p_loop); void set_loop(bool p_loop);
bool has_loop() const; bool has_loop() const;