Merge pull request #64804 from Mickeon/rename-path-progress

This commit is contained in:
Rémi Verschelde 2022-08-25 18:35:48 +02:00 committed by GitHub
commit 88145e81e2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 177 additions and 167 deletions

View file

@ -5,7 +5,7 @@
</brief_description>
<description>
This node takes its parent [Path2D], and returns the coordinates of a point within it, given a distance from the first vertex.
It is useful for making other nodes follow a path, without coding the movement pattern. For that, the nodes must be children of this node. The descendant nodes will then move accordingly when setting an offset in this node.
It is useful for making other nodes follow a path, without coding the movement pattern. For that, the nodes must be children of this node. The descendant nodes will then move accordingly when setting the [member progress] in this node.
</description>
<tutorials>
</tutorials>
@ -24,15 +24,15 @@
<member name="loop" type="bool" setter="set_loop" getter="has_loop" default="true">
If [code]true[/code], any offset outside the path's length will wrap around, instead of stopping at the ends. Use it for cyclic paths.
</member>
<member name="offset" type="float" setter="set_offset" getter="get_offset" default="0.0">
The distance along the path in pixels.
<member name="progress" type="float" setter="set_progress" getter="get_progress" default="0.0">
The distance along the path, in pixels. Changing this value sets this node's position to a point within the path.
</member>
<member name="progress_ratio" type="float" setter="set_progress_ratio" getter="get_progress_ratio" default="0.0">
The distance along the path as a number in the range 0.0 (for the first vertex) to 1.0 (for the last). This is just another way of expressing the progress within the path, as the offset supplied is multiplied internally by the path's length.
</member>
<member name="rotates" type="bool" setter="set_rotates" getter="is_rotating" default="true">
If [code]true[/code], this node rotates to follow the path, with the +X direction facing forward on the path.
</member>
<member name="unit_offset" type="float" setter="set_unit_offset" getter="get_unit_offset" default="0.0">
The distance along the path as a number in the range 0.0 (for the first vertex) to 1.0 (for the last). This is just another way of expressing the offset within the path, as the offset supplied is multiplied internally by the path's length.
</member>
<member name="v_offset" type="float" setter="set_v_offset" getter="get_v_offset" default="0.0">
The node's offset perpendicular to the curve.
</member>

View file

@ -5,7 +5,7 @@
</brief_description>
<description>
This node takes its parent [Path3D], and returns the coordinates of a point within it, given a distance from the first vertex.
It is useful for making other nodes follow a path, without coding the movement pattern. For that, the nodes must be children of this node. The descendant nodes will then move accordingly when setting an offset in this node.
It is useful for making other nodes follow a path, without coding the movement pattern. For that, the nodes must be children of this node. The descendant nodes will then move accordingly when setting the [member progress] in this node.
</description>
<tutorials>
</tutorials>
@ -21,15 +21,15 @@
<member name="loop" type="bool" setter="set_loop" getter="has_loop" default="true">
If [code]true[/code], any offset outside the path's length will wrap around, instead of stopping at the ends. Use it for cyclic paths.
</member>
<member name="offset" type="float" setter="set_offset" getter="get_offset" default="0.0">
The distance from the first vertex, measured in 3D units along the path. This sets this node's position to a point within the path.
<member name="progress" type="float" setter="set_progress" getter="get_progress" default="0.0">
The distance from the first vertex, measured in 3D units along the path. Changing this value sets this node's position to a point within the path.
</member>
<member name="progress_ratio" type="float" setter="set_progress_ratio" getter="get_progress_ratio" default="0.0">
The distance from the first vertex, considering 0.0 as the first vertex and 1.0 as the last. This is just another way of expressing the progress within the path, as the progress supplied is multiplied internally by the path's length.
</member>
<member name="rotation_mode" type="int" setter="set_rotation_mode" getter="get_rotation_mode" enum="PathFollow3D.RotationMode" default="3">
Allows or forbids rotation on one or more axes, depending on the [enum RotationMode] constants being used.
</member>
<member name="unit_offset" type="float" setter="set_unit_offset" getter="get_unit_offset" default="0.0">
The distance from the first vertex, considering 0.0 as the first vertex and 1.0 as the last. This is just another way of expressing the offset within the path, as the offset supplied is multiplied internally by the path's length.
</member>
<member name="v_offset" type="float" setter="set_v_offset" getter="get_v_offset" default="0.0">
The node's offset perpendicular to the curve.
</member>

View file

@ -206,6 +206,7 @@ static const char *gdscript_function_renames[][2] = {
// { "set_margin", "set_offset" }, // Control broke Shape3D, AtlasTexture
// { "set_mode", "set_mode_file_mode" }, // FileDialog broke Panel, Shader, CSGPolygon, Tilemap
// { "set_normal", "surface_set_normal"}, // ImmediateGeometry broke SurfaceTool, WorldMarginShape2D
// { "set_offset", "set_progress" }, // PathFollow2D, PathFollow3D - Too common
// { "set_process_mode", "set_process_callback" }, // AnimationTree broke Node, Tween, Sky
// { "set_refuse_new_network_connections", "set_refuse_new_connections"}, // MultiplayerAPI broke SceneTree
// { "set_uv", "surface_set_uv" }, // ImmediateMesh broke Polygon2D
@ -371,6 +372,7 @@ static const char *gdscript_function_renames[][2] = {
{ "get_theme_item_types", "get_theme_item_type_list" }, // Theme
{ "get_timer_process_mode", "get_timer_process_callback" }, // Timer
{ "get_translation", "get_position" }, // Node3D broke GLTFNode which is used rarely
{ "get_unit_offset", "get_progress_ratio" }, // PathFollow2D, PathFollow3D
{ "get_use_in_baked_light", "is_baking_navigation" }, // GridMap
{ "get_used_cells_by_id", "get_used_cells" }, // TileMap
{ "get_v_scrollbar", "get_v_scroll_bar" }, //ScrollContainer
@ -532,6 +534,7 @@ static const char *gdscript_function_renames[][2] = {
{ "set_timer_process_mode", "set_timer_process_callback" }, // Timer
{ "set_tonemap_auto_exposure", "set_tonemap_auto_exposure_enabled" }, // Environment
{ "set_translation", "set_position" }, // Node3D - this broke GLTFNode which is used rarely
{ "set_unit_offset", "set_progress_ratio" }, // PathFollow2D, PathFollow3D
{ "set_uv2", "surface_set_uv2" }, // ImmediateMesh broke Surffacetool
{ "set_v_drag_enabled", "set_drag_vertical_enabled" }, // Camera2D
{ "set_valign", "set_vertical_alignment" }, // Label
@ -612,6 +615,7 @@ static const char *csharp_function_renames[][2] = {
// { "SetMargin", "SetOffset" }, // Control broke Shape3D, AtlasTexture
// { "SetMode", "SetModeFileMode" }, // FileDialog broke Panel, Shader, CSGPolygon, Tilemap
// { "SetNormal", "SurfaceSetNormal"}, // ImmediateGeometry broke SurfaceTool, WorldMarginShape2D
// { "SetOffset", "SetProgress" }, // PathFollow2D, PathFollow3D - Too common
// { "SetProcessMode", "SetProcessCallback" }, // AnimationTree broke Node, Tween, Sky
// { "SetRefuseNewNetworkConnections", "SetRefuseNewConnections"}, // MultiplayerAPI broke SceneTree
// { "SetUv", "SurfaceSetUv" }, // ImmediateMesh broke Polygon2D
@ -767,6 +771,7 @@ static const char *csharp_function_renames[][2] = {
{ "GetThemeItemTypes", "GetThemeItemTypeList" }, // Theme
{ "GetTimerProcessMode", "GetTimerProcessCallback" }, // Timer
{ "GetTranslation", "GetPosition" }, // Node3D broke GLTFNode which is used rarely
{ "GetUnitOffset", "GetProgressRatio" }, // PathFollow2D, PathFollow3D
{ "GetUseInBakedLight", "IsBakingNavigation" }, // GridMap
{ "GetUsedCellsById", "GetUsedCells" }, // TileMap
{ "GetVScrollbar", "GetVScrollBar" }, //ScrollContainer
@ -918,6 +923,7 @@ static const char *csharp_function_renames[][2] = {
{ "SetTimerProcessMode", "SetTimerProcessCallback" }, // Timer
{ "SetTonemapAutoExposure", "SetTonemapAutoExposureEnabled" }, // Environment
{ "SetTranslation", "SetPosition" }, // Node3D - this broke GLTFNode which is used rarely
{ "SetUnitOffset", "SetProgressRatio" }, // PathFollow2D, PathFollow3D
{ "SetUv2", "SurfaceSetUv2" }, // ImmediateMesh broke Surffacetool
{ "SetVDragEnabled", "SetDragVerticalEnabled" }, // Camera2D
{ "SetValign", "SetVerticalAlignment" }, // Label
@ -969,6 +975,7 @@ static const char *gdscript_properties_renames[][2] = {
// // {"meta","meta_pressed"},// This may broke a lot of comments and user variables
// // {"pause_mode","process_mode"}, // Node - Cyclic rename, look for others
// // {"rotate","rotates"}, // PathFollow2D - probably function exists with same name
// // {"offset","progress"}, // PathFollow2D, PathFollow3D - Name is way too vague
// // {"shift","shift_pressed"},// This may broke a lot of comments and user variables
// { "autowrap", "autowrap_mode" }, // Label
// { "cast_to", "target_position" }, // RayCast2D, RayCast3D
@ -1038,6 +1045,7 @@ static const char *gdscript_properties_renames[][2] = {
{ "table_hseparation", "table_h_separation" }, // Theme
{ "table_vseparation", "table_v_separation" }, // Theme
{ "translation", "position" }, // Node3D - broke GLTFNode
{ "unit_offset", "progress_ratio" }, // PathFollow2D, PathFollow3D
{ "vseparation", "v_separation" }, // Theme
{ nullptr, nullptr },
@ -1053,6 +1061,7 @@ static const char *csharp_properties_renames[][2] = {
// // {"Meta","MetaPressed"},// This may broke a lot of comments and user variables
// // {"PauseMode","ProcessMode"}, // Node - Cyclic rename, look for others
// // {"Rotate","Rotates"}, // PathFollow2D - probably function exists with same name
// // {"Offset","Progress"}, // PathFollow2D, PathFollow3D - Name is way too vague
// // {"Shift","ShiftPressed"},// This may broke a lot of comments and user variables
// { "Autowrap", "AutowrapMode" }, // Label
// { "CastTo", "TargetPosition" }, // RayCast2D, RayCast3D
@ -1120,6 +1129,7 @@ static const char *csharp_properties_renames[][2] = {
{ "TableHseparation", "TableHSeparation" }, // Theme
{ "TableVseparation", "TableVSeparation" }, // Theme
{ "Translation", "Position" }, // Node3D - broke GLTFNode
{ "UnitOffset", "ProgressRatio" }, // PathFollow2D, PathFollow3D
{ "Vseparation", "VSeparation" }, // Theme
{ nullptr, nullptr },

View file

@ -175,10 +175,10 @@ void PathFollow2D::_update_transform() {
if (path_length == 0) {
return;
}
Vector2 pos = c->interpolate_baked(offset, cubic);
Vector2 pos = c->interpolate_baked(progress, cubic);
if (rotates) {
real_t ahead = offset + lookahead;
real_t ahead = progress + lookahead;
if (loop && ahead >= path_length) {
// If our lookahead will loop, we need to check if the path is closed.
@ -202,7 +202,7 @@ void PathFollow2D::_update_transform() {
// This will happen at the end of non-looping or non-closed paths.
// We'll try a look behind instead, in order to get a meaningful angle.
tangent_to_curve =
(pos - c->interpolate_baked(offset - lookahead, cubic)).normalized();
(pos - c->interpolate_baked(progress - lookahead, cubic)).normalized();
} else {
tangent_to_curve = (ahead_pos - pos).normalized();
}
@ -269,8 +269,8 @@ TypedArray<String> PathFollow2D::get_configuration_warnings() const {
}
void PathFollow2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_offset", "offset"), &PathFollow2D::set_offset);
ClassDB::bind_method(D_METHOD("get_offset"), &PathFollow2D::get_offset);
ClassDB::bind_method(D_METHOD("set_progress", "progress"), &PathFollow2D::set_progress);
ClassDB::bind_method(D_METHOD("get_progress"), &PathFollow2D::get_progress);
ClassDB::bind_method(D_METHOD("set_h_offset", "h_offset"), &PathFollow2D::set_h_offset);
ClassDB::bind_method(D_METHOD("get_h_offset"), &PathFollow2D::get_h_offset);
@ -278,8 +278,8 @@ void PathFollow2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_v_offset", "v_offset"), &PathFollow2D::set_v_offset);
ClassDB::bind_method(D_METHOD("get_v_offset"), &PathFollow2D::get_v_offset);
ClassDB::bind_method(D_METHOD("set_unit_offset", "unit_offset"), &PathFollow2D::set_unit_offset);
ClassDB::bind_method(D_METHOD("get_unit_offset"), &PathFollow2D::get_unit_offset);
ClassDB::bind_method(D_METHOD("set_progress_ratio", "ratio"), &PathFollow2D::set_progress_ratio);
ClassDB::bind_method(D_METHOD("get_progress_ratio"), &PathFollow2D::get_progress_ratio);
ClassDB::bind_method(D_METHOD("set_rotates", "enable"), &PathFollow2D::set_rotates);
ClassDB::bind_method(D_METHOD("is_rotating"), &PathFollow2D::is_rotating);
@ -293,8 +293,8 @@ void PathFollow2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_lookahead", "lookahead"), &PathFollow2D::set_lookahead);
ClassDB::bind_method(D_METHOD("get_lookahead"), &PathFollow2D::get_lookahead);
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "offset", PROPERTY_HINT_RANGE, "0,10000,0.01,or_lesser,or_greater,suffix:px"), "set_offset", "get_offset");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "unit_offset", PROPERTY_HINT_RANGE, "0,1,0.0001,or_lesser,or_greater", PROPERTY_USAGE_EDITOR), "set_unit_offset", "get_unit_offset");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "progress", PROPERTY_HINT_RANGE, "0,10000,0.01,or_lesser,or_greater,suffix:px"), "set_progress", "get_progress");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "progress_ratio", PROPERTY_HINT_RANGE, "0,1,0.0001,or_lesser,or_greater", PROPERTY_USAGE_EDITOR), "set_progress_ratio", "get_progress_ratio");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "h_offset"), "set_h_offset", "get_h_offset");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "v_offset"), "set_v_offset", "get_v_offset");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "rotates"), "set_rotates", "is_rotating");
@ -303,20 +303,20 @@ void PathFollow2D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "lookahead", PROPERTY_HINT_RANGE, "0.001,1024.0,0.001"), "set_lookahead", "get_lookahead");
}
void PathFollow2D::set_offset(real_t p_offset) {
ERR_FAIL_COND(!isfinite(p_offset));
offset = p_offset;
void PathFollow2D::set_progress(real_t p_progress) {
ERR_FAIL_COND(!isfinite(p_progress));
progress = p_progress;
if (path) {
if (path->get_curve().is_valid()) {
real_t path_length = path->get_curve()->get_baked_length();
if (loop && path_length) {
offset = Math::fposmod(offset, path_length);
if (!Math::is_zero_approx(p_offset) && Math::is_zero_approx(offset)) {
offset = path_length;
progress = Math::fposmod(progress, path_length);
if (!Math::is_zero_approx(p_progress) && Math::is_zero_approx(progress)) {
progress = path_length;
}
} else {
offset = CLAMP(offset, 0, path_length);
progress = CLAMP(progress, 0, path_length);
}
}
@ -346,19 +346,19 @@ real_t PathFollow2D::get_v_offset() const {
return v_offset;
}
real_t PathFollow2D::get_offset() const {
return offset;
real_t PathFollow2D::get_progress() const {
return progress;
}
void PathFollow2D::set_unit_offset(real_t p_unit_offset) {
void PathFollow2D::set_progress_ratio(real_t p_ratio) {
if (path && path->get_curve().is_valid() && path->get_curve()->get_baked_length()) {
set_offset(p_unit_offset * path->get_curve()->get_baked_length());
set_progress(p_ratio * path->get_curve()->get_baked_length());
}
}
real_t PathFollow2D::get_unit_offset() const {
real_t PathFollow2D::get_progress_ratio() const {
if (path && path->get_curve().is_valid() && path->get_curve()->get_baked_length()) {
return get_offset() / path->get_curve()->get_baked_length();
return get_progress() / path->get_curve()->get_baked_length();
} else {
return 0;
}

View file

@ -65,7 +65,7 @@ class PathFollow2D : public Node2D {
public:
private:
Path2D *path = nullptr;
real_t offset = 0.0;
real_t progress = 0.0;
real_t h_offset = 0.0;
real_t v_offset = 0.0;
real_t lookahead = 4.0;
@ -82,8 +82,8 @@ protected:
static void _bind_methods();
public:
void set_offset(real_t p_offset);
real_t get_offset() const;
void set_progress(real_t p_progress);
real_t get_progress() const;
void set_h_offset(real_t p_h_offset);
real_t get_h_offset() const;
@ -91,8 +91,8 @@ public:
void set_v_offset(real_t p_v_offset);
real_t get_v_offset() const;
void set_unit_offset(real_t p_unit_offset);
real_t get_unit_offset() const;
void set_progress_ratio(real_t p_ratio);
real_t get_progress_ratio() const;
void set_lookahead(real_t p_lookahead);
real_t get_lookahead() const;

View file

@ -183,8 +183,8 @@ void PathFollow3D::_update_transform(bool p_update_xyz_rot) {
return;
}
real_t bi = c->get_bake_interval();
real_t o_next = offset + bi;
real_t o_prev = offset - bi;
real_t o_next = progress + bi;
real_t o_prev = progress - bi;
if (loop) {
o_next = Math::fposmod(o_next, bl);
@ -198,7 +198,7 @@ void PathFollow3D::_update_transform(bool p_update_xyz_rot) {
}
}
Vector3 pos = c->interpolate_baked(offset, cubic);
Vector3 pos = c->interpolate_baked(progress, cubic);
Transform3D t = get_transform();
// Vector3 pos_offset = Vector3(h_offset, v_offset, 0); not used in all cases
// will be replaced by "Vector3(h_offset, v_offset, 0)" where it was formerly used
@ -217,9 +217,9 @@ void PathFollow3D::_update_transform(bool p_update_xyz_rot) {
forward.normalize();
}
Vector3 up = c->interpolate_baked_up_vector(offset, true);
Vector3 up = c->interpolate_baked_up_vector(progress, true);
if (o_next < offset) {
if (o_next < progress) {
Vector3 up1 = c->interpolate_baked_up_vector(o_next, true);
Vector3 axis = up.cross(up1);
@ -247,12 +247,12 @@ void PathFollow3D::_update_transform(bool p_update_xyz_rot) {
// for a discussion about why not Frenet frame.
t.origin = pos;
if (p_update_xyz_rot && prev_offset != offset) { // Only update rotation if some parameter has changed - i.e. not on addition to scene tree.
if (p_update_xyz_rot && prev_offset != progress) { // Only update rotation if some parameter has changed - i.e. not on addition to scene tree.
real_t sample_distance = bi * 0.01;
Vector3 t_prev_pos_a = c->interpolate_baked(prev_offset - sample_distance, cubic);
Vector3 t_prev_pos_b = c->interpolate_baked(prev_offset + sample_distance, cubic);
Vector3 t_cur_pos_a = c->interpolate_baked(offset - sample_distance, cubic);
Vector3 t_cur_pos_b = c->interpolate_baked(offset + sample_distance, cubic);
Vector3 t_cur_pos_a = c->interpolate_baked(progress - sample_distance, cubic);
Vector3 t_cur_pos_b = c->interpolate_baked(progress + sample_distance, cubic);
Vector3 t_prev = (t_prev_pos_a - t_prev_pos_b).normalized();
Vector3 t_cur = (t_cur_pos_a - t_cur_pos_b).normalized();
@ -277,7 +277,7 @@ void PathFollow3D::_update_transform(bool p_update_xyz_rot) {
}
// do the additional tilting
real_t tilt_angle = c->interpolate_baked_tilt(offset);
real_t tilt_angle = c->interpolate_baked_tilt(progress);
Vector3 tilt_axis = t_cur; // not sure what tilt is supposed to do, is this correct??
if (likely(!Math::is_zero_approx(Math::abs(tilt_angle)))) {
@ -359,8 +359,8 @@ TypedArray<String> PathFollow3D::get_configuration_warnings() const {
}
void PathFollow3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_offset", "offset"), &PathFollow3D::set_offset);
ClassDB::bind_method(D_METHOD("get_offset"), &PathFollow3D::get_offset);
ClassDB::bind_method(D_METHOD("set_progress", "progress"), &PathFollow3D::set_progress);
ClassDB::bind_method(D_METHOD("get_progress"), &PathFollow3D::get_progress);
ClassDB::bind_method(D_METHOD("set_h_offset", "h_offset"), &PathFollow3D::set_h_offset);
ClassDB::bind_method(D_METHOD("get_h_offset"), &PathFollow3D::get_h_offset);
@ -368,8 +368,8 @@ void PathFollow3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_v_offset", "v_offset"), &PathFollow3D::set_v_offset);
ClassDB::bind_method(D_METHOD("get_v_offset"), &PathFollow3D::get_v_offset);
ClassDB::bind_method(D_METHOD("set_unit_offset", "unit_offset"), &PathFollow3D::set_unit_offset);
ClassDB::bind_method(D_METHOD("get_unit_offset"), &PathFollow3D::get_unit_offset);
ClassDB::bind_method(D_METHOD("set_progress_ratio", "ratio"), &PathFollow3D::set_progress_ratio);
ClassDB::bind_method(D_METHOD("get_progress_ratio"), &PathFollow3D::get_progress_ratio);
ClassDB::bind_method(D_METHOD("set_rotation_mode", "rotation_mode"), &PathFollow3D::set_rotation_mode);
ClassDB::bind_method(D_METHOD("get_rotation_mode"), &PathFollow3D::get_rotation_mode);
@ -380,8 +380,8 @@ void PathFollow3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_loop", "loop"), &PathFollow3D::set_loop);
ClassDB::bind_method(D_METHOD("has_loop"), &PathFollow3D::has_loop);
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "offset", PROPERTY_HINT_RANGE, "0,10000,0.01,or_lesser,or_greater,suffix:m"), "set_offset", "get_offset");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "unit_offset", PROPERTY_HINT_RANGE, "0,1,0.0001,or_lesser,or_greater", PROPERTY_USAGE_EDITOR), "set_unit_offset", "get_unit_offset");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "progress", PROPERTY_HINT_RANGE, "0,10000,0.01,or_lesser,or_greater,suffix:m"), "set_progress", "get_progress");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "progress_ratio", PROPERTY_HINT_RANGE, "0,1,0.0001,or_lesser,or_greater", PROPERTY_USAGE_EDITOR), "set_progress_ratio", "get_progress_ratio");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "h_offset", PROPERTY_HINT_NONE, "suffix:m"), "set_h_offset", "get_h_offset");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "v_offset", PROPERTY_HINT_NONE, "suffix:m"), "set_v_offset", "get_v_offset");
ADD_PROPERTY(PropertyInfo(Variant::INT, "rotation_mode", PROPERTY_HINT_ENUM, "None,Y,XY,XYZ,Oriented"), "set_rotation_mode", "get_rotation_mode");
@ -395,22 +395,22 @@ void PathFollow3D::_bind_methods() {
BIND_ENUM_CONSTANT(ROTATION_ORIENTED);
}
void PathFollow3D::set_offset(real_t p_offset) {
ERR_FAIL_COND(!isfinite(p_offset));
prev_offset = offset;
offset = p_offset;
void PathFollow3D::set_progress(real_t p_progress) {
ERR_FAIL_COND(!isfinite(p_progress));
prev_offset = progress;
progress = p_progress;
if (path) {
if (path->get_curve().is_valid()) {
real_t path_length = path->get_curve()->get_baked_length();
if (loop && path_length) {
offset = Math::fposmod(offset, path_length);
if (!Math::is_zero_approx(p_offset) && Math::is_zero_approx(offset)) {
offset = path_length;
progress = Math::fposmod(progress, path_length);
if (!Math::is_zero_approx(p_progress) && Math::is_zero_approx(progress)) {
progress = path_length;
}
} else {
offset = CLAMP(offset, 0, path_length);
progress = CLAMP(progress, 0, path_length);
}
}
@ -440,19 +440,19 @@ real_t PathFollow3D::get_v_offset() const {
return v_offset;
}
real_t PathFollow3D::get_offset() const {
return offset;
real_t PathFollow3D::get_progress() const {
return progress;
}
void PathFollow3D::set_unit_offset(real_t p_unit_offset) {
void PathFollow3D::set_progress_ratio(real_t p_ratio) {
if (path && path->get_curve().is_valid() && path->get_curve()->get_baked_length()) {
set_offset(p_unit_offset * path->get_curve()->get_baked_length());
set_progress(p_ratio * path->get_curve()->get_baked_length());
}
}
real_t PathFollow3D::get_unit_offset() const {
real_t PathFollow3D::get_progress_ratio() const {
if (path && path->get_curve().is_valid() && path->get_curve()->get_baked_length()) {
return get_offset() / path->get_curve()->get_baked_length();
return get_progress() / path->get_curve()->get_baked_length();
} else {
return 0;
}

View file

@ -75,7 +75,7 @@ public:
private:
Path3D *path = nullptr;
real_t prev_offset = 0.0; // Offset during the last _update_transform.
real_t offset = 0.0;
real_t progress = 0.0;
real_t h_offset = 0.0;
real_t v_offset = 0.0;
bool cubic = true;
@ -91,8 +91,8 @@ protected:
static void _bind_methods();
public:
void set_offset(real_t p_offset);
real_t get_offset() const;
void set_progress(real_t p_progress);
real_t get_progress() const;
void set_h_offset(real_t p_h_offset);
real_t get_h_offset() const;
@ -100,8 +100,8 @@ public:
void set_v_offset(real_t p_v_offset);
real_t get_v_offset() const;
void set_unit_offset(real_t p_unit_offset);
real_t get_unit_offset() const;
void set_progress_ratio(real_t p_ratio);
real_t get_progress_ratio() const;
void set_loop(bool p_loop);
bool has_loop() const;

View file

@ -37,7 +37,7 @@
namespace TestPathFollow2D {
TEST_CASE("[PathFollow2D] Sampling with unit offset") {
TEST_CASE("[PathFollow2D] Sampling with progress ratio") {
const Ref<Curve2D> &curve = memnew(Curve2D());
curve->add_point(Vector2(0, 0));
curve->add_point(Vector2(100, 0));
@ -49,37 +49,37 @@ TEST_CASE("[PathFollow2D] Sampling with unit offset") {
const PathFollow2D *path_follow_2d = memnew(PathFollow2D);
path->add_child(path_follow_2d);
path_follow_2d->set_unit_offset(0);
path_follow_2d->set_progress_ratio(0);
CHECK(path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(0, 0)));
path_follow_2d->set_unit_offset(0.125);
path_follow_2d->set_progress_ratio(0.125);
CHECK(path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(50, 0)));
path_follow_2d->set_unit_offset(0.25);
path_follow_2d->set_progress_ratio(0.25);
CHECK(path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(100, 0)));
path_follow_2d->set_unit_offset(0.375);
path_follow_2d->set_progress_ratio(0.375);
CHECK(path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(100, 50)));
path_follow_2d->set_unit_offset(0.5);
path_follow_2d->set_progress_ratio(0.5);
CHECK(path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(100, 100)));
path_follow_2d->set_unit_offset(0.625);
path_follow_2d->set_progress_ratio(0.625);
CHECK(path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(50, 100)));
path_follow_2d->set_unit_offset(0.75);
path_follow_2d->set_progress_ratio(0.75);
CHECK(path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(0, 100)));
path_follow_2d->set_unit_offset(0.875);
path_follow_2d->set_progress_ratio(0.875);
CHECK(path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(0, 50)));
path_follow_2d->set_unit_offset(1);
path_follow_2d->set_progress_ratio(1);
CHECK(path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(0, 0)));
memdelete(path);
}
TEST_CASE("[PathFollow2D] Sampling with offset") {
TEST_CASE("[PathFollow2D] Sampling with progress") {
const Ref<Curve2D> &curve = memnew(Curve2D());
curve->add_point(Vector2(0, 0));
curve->add_point(Vector2(100, 0));
@ -91,31 +91,31 @@ TEST_CASE("[PathFollow2D] Sampling with offset") {
const PathFollow2D *path_follow_2d = memnew(PathFollow2D);
path->add_child(path_follow_2d);
path_follow_2d->set_offset(0);
path_follow_2d->set_progress(0);
CHECK(path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(0, 0)));
path_follow_2d->set_offset(50);
path_follow_2d->set_progress(50);
CHECK(path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(50, 0)));
path_follow_2d->set_offset(100);
path_follow_2d->set_progress(100);
CHECK(path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(100, 0)));
path_follow_2d->set_offset(150);
path_follow_2d->set_progress(150);
CHECK(path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(100, 50)));
path_follow_2d->set_offset(200);
path_follow_2d->set_progress(200);
CHECK(path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(100, 100)));
path_follow_2d->set_offset(250);
path_follow_2d->set_progress(250);
CHECK(path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(50, 100)));
path_follow_2d->set_offset(300);
path_follow_2d->set_progress(300);
CHECK(path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(0, 100)));
path_follow_2d->set_offset(350);
path_follow_2d->set_progress(350);
CHECK(path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(0, 50)));
path_follow_2d->set_offset(400);
path_follow_2d->set_progress(400);
CHECK(path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(0, 0)));
memdelete(path);
@ -131,7 +131,7 @@ TEST_CASE("[PathFollow2D] Removal of a point in curve") {
const PathFollow2D *path_follow_2d = memnew(PathFollow2D);
path->add_child(path_follow_2d);
path_follow_2d->set_unit_offset(0.5);
path_follow_2d->set_progress_ratio(0.5);
CHECK(path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(100, 0)));
curve->remove_point(1);
@ -152,7 +152,7 @@ TEST_CASE("[PathFollow2D] Setting h_offset and v_offset") {
const PathFollow2D *path_follow_2d = memnew(PathFollow2D);
path->add_child(path_follow_2d);
path_follow_2d->set_unit_offset(0.5);
path_follow_2d->set_progress_ratio(0.5);
CHECK(path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(50, 0)));
path_follow_2d->set_h_offset(25);
@ -175,32 +175,32 @@ TEST_CASE("[PathFollow2D] Unit offset out of range") {
path_follow_2d->set_loop(true);
path_follow_2d->set_unit_offset(-0.3);
path_follow_2d->set_progress_ratio(-0.3);
CHECK_MESSAGE(
path_follow_2d->get_unit_offset() == 0.7,
"Unit Offset should loop back from the end in the opposite direction");
path_follow_2d->get_progress_ratio() == 0.7,
"Progress Ratio should loop back from the end in the opposite direction");
path_follow_2d->set_unit_offset(1.3);
path_follow_2d->set_progress_ratio(1.3);
CHECK_MESSAGE(
path_follow_2d->get_unit_offset() == 0.3,
"Unit Offset should loop back from the end in the opposite direction");
path_follow_2d->get_progress_ratio() == 0.3,
"Progress Ratio should loop back from the end in the opposite direction");
path_follow_2d->set_loop(false);
path_follow_2d->set_unit_offset(-0.3);
path_follow_2d->set_progress_ratio(-0.3);
CHECK_MESSAGE(
path_follow_2d->get_unit_offset() == 0,
"Unit Offset should be clamped at 0");
path_follow_2d->get_progress_ratio() == 0,
"Progress Ratio should be clamped at 0");
path_follow_2d->set_unit_offset(1.3);
path_follow_2d->set_progress_ratio(1.3);
CHECK_MESSAGE(
path_follow_2d->get_unit_offset() == 1,
"Unit Offset should be clamped at 1");
path_follow_2d->get_progress_ratio() == 1,
"Progress Ratio should be clamped at 1");
memdelete(path);
}
TEST_CASE("[PathFollow2D] Offset out of range") {
TEST_CASE("[PathFollow2D] Progress out of range") {
const Ref<Curve2D> &curve = memnew(Curve2D());
curve->add_point(Vector2(0, 0));
curve->add_point(Vector2(100, 0));
@ -211,27 +211,27 @@ TEST_CASE("[PathFollow2D] Offset out of range") {
path_follow_2d->set_loop(true);
path_follow_2d->set_offset(-50);
path_follow_2d->set_progress(-50);
CHECK_MESSAGE(
path_follow_2d->get_offset() == 50,
"Offset should loop back from the end in the opposite direction");
path_follow_2d->get_progress() == 50,
"Progress should loop back from the end in the opposite direction");
path_follow_2d->set_offset(150);
path_follow_2d->set_progress(150);
CHECK_MESSAGE(
path_follow_2d->get_offset() == 50,
"Offset should loop back from the end in the opposite direction");
path_follow_2d->get_progress() == 50,
"Progress should loop back from the end in the opposite direction");
path_follow_2d->set_loop(false);
path_follow_2d->set_offset(-50);
path_follow_2d->set_progress(-50);
CHECK_MESSAGE(
path_follow_2d->get_offset() == 0,
"Offset should be clamped at 0");
path_follow_2d->get_progress() == 0,
"Progress should be clamped at 0");
path_follow_2d->set_offset(150);
path_follow_2d->set_progress(150);
CHECK_MESSAGE(
path_follow_2d->get_offset() == 100,
"Offset should be clamped at 1");
path_follow_2d->get_progress() == 100,
"Progress should be clamped at 1");
memdelete(path);
}

View file

@ -37,7 +37,7 @@
namespace TestPathFollow3D {
TEST_CASE("[PathFollow3D] Sampling with unit offset") {
TEST_CASE("[PathFollow3D] Sampling with progress ratio") {
const Ref<Curve3D> &curve = memnew(Curve3D());
curve->add_point(Vector3(0, 0, 0));
curve->add_point(Vector3(100, 0, 0));
@ -49,37 +49,37 @@ TEST_CASE("[PathFollow3D] Sampling with unit offset") {
const PathFollow3D *path_follow_3d = memnew(PathFollow3D);
path->add_child(path_follow_3d);
path_follow_3d->set_unit_offset(0);
path_follow_3d->set_progress_ratio(0);
CHECK(path_follow_3d->get_transform().get_origin().is_equal_approx(Vector3(0, 0, 0));
path_follow_3d->set_unit_offset(0.125);
path_follow_3d->set_progress_ratio(0.125);
CHECK(path_follow_3d->get_transform().get_origin().is_equal_approx(Vector3(50, 0, 0));
path_follow_3d->set_unit_offset(0.25);
path_follow_3d->set_progress_ratio(0.25);
CHECK(path_follow_3d->get_transform().get_origin().is_equal_approx(Vector3(100, 0, 0);
path_follow_3d->set_unit_offset(0.375);
path_follow_3d->set_progress_ratio(0.375);
CHECK(path_follow_3d->get_transform().get_origin().is_equal_approx(Vector3(100, 50, 0)));
path_follow_3d->set_unit_offset(0.5);
path_follow_3d->set_progress_ratio(0.5);
CHECK(path_follow_3d->get_transform().get_origin().is_equal_approx(Vector3(100, 100, 0)));
path_follow_3d->set_unit_offset(0.625);
path_follow_3d->set_progress_ratio(0.625);
CHECK(path_follow_3d->get_transform().get_origin().is_equal_approx(Vector3(100, 100, 50)));
path_follow_3d->set_unit_offset(0.75);
path_follow_3d->set_progress_ratio(0.75);
CHECK(path_follow_3d->get_transform().get_origin().is_equal_approx(Vector3(100, 100, 100)));
path_follow_3d->set_unit_offset(0.875);
path_follow_3d->set_progress_ratio(0.875);
CHECK(path_follow_3d->get_transform().get_origin().is_equal_approx(Vector3(100, 50, 100)));
path_follow_3d->set_unit_offset(1);
path_follow_3d->set_progress_ratio(1);
CHECK(path_follow_3d->get_transform().get_origin().is_equal_approx(Vector3(100, 0, 100)));
memdelete(path);
}
TEST_CASE("[PathFollow3D] Sampling with offset") {
TEST_CASE("[PathFollow3D] Sampling with progress") {
const Ref<Curve3D> &curve = memnew(Curve3D());
curve->add_point(Vector3(0, 0, 0));
curve->add_point(Vector3(100, 0, 0));
@ -91,31 +91,31 @@ TEST_CASE("[PathFollow3D] Sampling with offset") {
const PathFollow3D *path_follow_3d = memnew(PathFollow3D);
path->add_child(path_follow_3d);
path_follow_3d->set_offset(0);
path_follow_3d->set_progress(0);
CHECK(path_follow_3d->get_transform().get_origin().is_equal_approx(Vector3(0, 0, 0));
path_follow_3d->set_offset(50);
path_follow_3d->set_progress(50);
CHECK(path_follow_3d->get_transform().get_origin().is_equal_approx(Vector3(50, 0, 0));
path_follow_3d->set_offset(100);
path_follow_3d->set_progress(100);
CHECK(path_follow_3d->get_transform().get_origin().is_equal_approx(Vector3(100, 0, 0);
path_follow_3d->set_offset(150);
path_follow_3d->set_progress(150);
CHECK(path_follow_3d->get_transform().get_origin().is_equal_approx(Vector3(100, 50, 0)));
path_follow_3d->set_offset(200);
path_follow_3d->set_progress(200);
CHECK(path_follow_3d->get_transform().get_origin().is_equal_approx(Vector3(100, 100, 0)));
path_follow_3d->set_offset(250);
path_follow_3d->set_progress(250);
CHECK(path_follow_3d->get_transform().get_origin().is_equal_approx(Vector3(100, 100, 50)));
path_follow_3d->set_offset(300);
path_follow_3d->set_progress(300);
CHECK(path_follow_3d->get_transform().get_origin().is_equal_approx(Vector3(100, 100, 100)));
path_follow_3d->set_offset(350);
path_follow_3d->set_progress(350);
CHECK(path_follow_3d->get_transform().get_origin().is_equal_approx(Vector3(100, 50, 100)));
path_follow_3d->set_offset(400);
path_follow_3d->set_progress(400);
CHECK(path_follow_3d->get_transform().get_origin().is_equal_approx(Vector3(100, 0, 100)));
memdelete(path);
@ -131,7 +131,7 @@ TEST_CASE("[PathFollow3D] Removal of a point in curve") {
const PathFollow3D *path_follow_3d = memnew(PathFollow3D);
path->add_child(path_follow_3d);
path_follow_3d->set_unit_offset(0.5);
path_follow_3d->set_progress_ratio(0.5);
CHECK(path_follow_3d->get_transform().get_origin().is_equal_approx(Vector2(100, 0, 0)));
curve->remove_point(1);
@ -143,7 +143,7 @@ TEST_CASE("[PathFollow3D] Removal of a point in curve") {
memdelete(path);
}
TEST_CASE("[PathFollow3D] Unit offset out of range") {
TEST_CASE("[PathFollow3D] Progress ratio out of range") {
const Ref<Curve3D> &curve = memnew(Curve3D());
curve->add_point(Vector3(0, 0, 0));
curve->add_point(Vector3(100, 0, 0));
@ -154,32 +154,32 @@ TEST_CASE("[PathFollow3D] Unit offset out of range") {
path_follow_3d->set_loop(true);
path_follow_3d->set_unit_offset(-0.3);
path_follow_3d->set_progress_ratio(-0.3);
CHECK_MESSAGE(
path_follow_3d->get_unit_offset() == 0.7,
"Unit Offset should loop back from the end in the opposite direction");
path_follow_3d->get_progress_ratio() == 0.7,
"Progress Ratio should loop back from the end in the opposite direction");
path_follow_3d->set_unit_offset(1.3);
path_follow_3d->set_progress_ratio(1.3);
CHECK_MESSAGE(
path_follow_3d->get_unit_offset() == 0.3,
"Unit Offset should loop back from the end in the opposite direction");
path_follow_3d->get_progress_ratio() == 0.3,
"Progress Ratio should loop back from the end in the opposite direction");
path_follow_3d->set_loop(false);
path_follow_3d->set_unit_offset(-0.3);
path_follow_3d->set_progress_ratio(-0.3);
CHECK_MESSAGE(
path_follow_3d->get_unit_offset() == 0,
"Unit Offset should be clamped at 0");
path_follow_3d->get_progress_ratio() == 0,
"Progress Ratio should be clamped at 0");
path_follow_3d->set_unit_offset(1.3);
path_follow_3d->set_progress_ratio(1.3);
CHECK_MESSAGE(
path_follow_3d->get_unit_offset() == 1,
"Unit Offset should be clamped at 1");
path_follow_3d->get_progress_ratio() == 1,
"Progress Ratio should be clamped at 1");
memdelete(path);
}
TEST_CASE("[PathFollow3D] Offset out of range") {
TEST_CASE("[PathFollow3D] Progress out of range") {
const Ref<Curve3D> &curve = memnew(Curve3D());
curve->add_point(Vector3(0, 0, 0));
curve->add_point(Vector3(100, 0, 0));
@ -190,27 +190,27 @@ TEST_CASE("[PathFollow3D] Offset out of range") {
path_follow_3d->set_loop(true);
path_follow_3d->set_offset(-50);
path_follow_3d->set_progress(-50);
CHECK_MESSAGE(
path_follow_3d->get_offset() == 50,
"Offset should loop back from the end in the opposite direction");
path_follow_3d->get_progress() == 50,
"Progress should loop back from the end in the opposite direction");
path_follow_3d->set_offset(150);
path_follow_3d->set_progress(150);
CHECK_MESSAGE(
path_follow_3d->get_offset() == 50,
"Offset should loop back from the end in the opposite direction");
path_follow_3d->get_progress() == 50,
"Progress should loop back from the end in the opposite direction");
path_follow_3d->set_loop(false);
path_follow_3d->set_offset(-50);
path_follow_3d->set_progress(-50);
CHECK_MESSAGE(
path_follow_3d->get_offset() == 0,
"Offset should be clamped at 0");
path_follow_3d->get_progress() == 0,
"Progress should be clamped at 0");
path_follow_3d->set_offset(150);
path_follow_3d->set_progress(150);
CHECK_MESSAGE(
path_follow_3d->get_offset() == 100,
"Offset should be clamped at max value of curve");
path_follow_3d->get_progress() == 100,
"Progress should be clamped at max value of curve");
memdelete(path);
}