Skip to content

Commit a1c1f2f

Browse files
committed
Add option to consider exact positions in RopeAnchor and RopeHandle
1 parent 28d220f commit a1c1f2f

3 files changed

Lines changed: 40 additions & 7 deletions

File tree

demo/addons/ropesim/Rope.gd

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,6 @@ func update_segments():
167167

168168
# Access
169169

170-
171170
func get_num_points() -> int:
172171
return _points.size()
173172

@@ -180,6 +179,16 @@ func get_point_perc(index: int) -> float:
180179
return index / float(_points.size() - 1) if _points.size() > 0 else 0.0
181180

182181

182+
func get_point_interpolate(position_perc: float) -> Vector2:
183+
var idx := get_point_index(position_perc)
184+
if idx == _points.size() - 1:
185+
return _points[idx]
186+
var next := idx + 1
187+
var next_perc := get_point_perc(next)
188+
var perc := get_point_perc(idx)
189+
return lerp(_points[idx], _points[next], (position_perc - perc) / (next_perc - perc))
190+
191+
183192
func get_nearest_point_index(pos: Vector2) -> int:
184193
var min_dist = 1e10
185194
var idx = 0

demo/addons/ropesim/RopeAnchor.gd

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ export var enable: bool = true setget set_enable, get_enable # Enable or disabl
1010
export(NodePath) var rope_path setget set_rope_path # Target rope path.
1111
export(float, 0, 1) var rope_position = 1.0 # Position on the rope between 0 and 1.
1212
export var apply_angle := false # Also apply rotation according to the rope curvature.
13+
## If false, only consider the nearest vertex on the rope. Otherwise, interpolate the position between two relevant points when applicable.
14+
export var precise: bool = false
1315
var _helper: RopeToolHelper
1416

1517

@@ -39,13 +41,18 @@ func set_enable(value: bool):
3941
enable = value
4042
_helper.enable = value
4143

44+
4245
func get_enable() -> bool:
4346
return _helper.enable
4447

4548

4649
func _update() -> void:
4750
var rope: Rope = _helper.target_rope
48-
global_position = rope.get_point(rope.get_point_index(rope_position))
51+
52+
if precise:
53+
global_position = rope.get_point_interpolate(rope_position)
54+
else:
55+
global_position = rope.get_point(rope.get_point_index(rope_position))
4956

5057
if apply_angle:
5158
var a := rope.get_point(rope.get_point_index(rope_position - 0.1))

demo/addons/ropesim/RopeHandle.gd

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ export(NodePath) var rope_path setget set_rope_path # Target rope path
1010
export(float, 0, 1) var rope_position = 1.0 # Position on the rope between 0 and 1.
1111
export var smoothing: bool = false # Whether to smoothly snap to RopeHandle's position instead of instantly.
1212
export var smoothing_speed: float = 0.5 # Smoothing speed
13+
## If false, only affect the nearest vertex on the rope. Otherwise, affect both surrounding points when applicable.
14+
export var precise: bool = false
1315
var _helper: RopeToolHelper
1416

1517

@@ -28,12 +30,27 @@ func _on_pre_update() -> void:
2830
emit_signal("on_before_update")
2931
var rope: Rope = _helper.target_rope
3032
var point_index: int = rope.get_point_index(rope_position)
31-
var new_pos: Vector2
32-
if smoothing:
33-
new_pos = rope.get_point(point_index).linear_interpolate(global_position, get_physics_process_delta_time() * smoothing_speed)
33+
34+
# Only use this method if this is not the last point.
35+
if precise and point_index < rope.get_num_points() - 1:
36+
# TODO: Consider creating a corresponding function in Rope.gd for universal access, e.g. set_point_interpolated().
37+
var point_pos: Vector2 = rope.get_point_interpolate(rope_position)
38+
var diff := global_position - point_pos
39+
var pos_a: Vector2 = rope.get_point(point_index)
40+
var pos_b: Vector2 = rope.get_point(point_index + 1)
41+
var new_pos_a: Vector2 = pos_a + diff
42+
var new_pos_b: Vector2 = pos_b + diff
43+
44+
_move_point(point_index, pos_a, new_pos_a)
45+
_move_point(point_index + 1, pos_b, new_pos_b)
3446
else:
35-
new_pos = global_position
36-
rope.set_point(point_index, new_pos)
47+
_move_point(point_index, rope.get_point(point_index), global_position)
48+
49+
50+
func _move_point(idx: int, from: Vector2, to: Vector2) -> void:
51+
if smoothing:
52+
to = from.linear_interpolate(to, get_physics_process_delta_time() * smoothing_speed)
53+
_helper.target_rope.set_point(idx, to)
3754

3855

3956
func set_rope_path(value: NodePath):

0 commit comments

Comments
 (0)