Skip to content

Commit feb4556

Browse files
committed
Add settings related to max_endpoint_distance
Adds properties to determine in which direction the rope should be constrained when exceeding max_endpoint_distance.
1 parent b6874d4 commit feb4556

File tree

5 files changed

+157
-40
lines changed

5 files changed

+157
-40
lines changed

demo/addons/ropesim/Rope.gd

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,18 @@ signal on_point_count_changed()
3030
## Fixed points in between are not taken into account.
3131
@export var max_endpoint_distance: float = -1
3232

33+
## If [member Rope.max_endpoint_distance] is set, contract the rope towards the first point.
34+
## If [member Rope.resolve_to_end] is set as well or if neither is set, the rope gets contracted
35+
## towards the center.
36+
## [member Rope.fixate_begin] will always take precedence over this property.
37+
@export var resolve_to_begin: bool = false
38+
39+
## If [member Rope.max_endpoint_distance] is set, contract the rope towards the last point.
40+
## If [member Rope.resolve_to_begin] is set as well or if neither is set, the rope gets contracted
41+
## towards the center.
42+
## [member Rope.fixate_begin] will always take precedence over this property.
43+
@export var resolve_to_end: bool = false
44+
3345
## (Optional) Allows to distribute the length of rope segment in a non-uniform manner.
3446
## Useful when certain parts of the rope should be more detailed than the rest.
3547
## For example, if it is known that most movement happens at the beginning of the rope, a curve with

demo/project.godot

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ config_version=5
1111
[application]
1212

1313
config/name="ropesim example"
14-
config/features=PackedStringArray("4.2")
14+
config/features=PackedStringArray("4.3")
1515
config/icon="res://rope_examples/icon.svg"
1616

1717
[debug]

demo/rope_examples/rope_properties.tscn

Lines changed: 110 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -63,15 +63,15 @@ metadata/_edit_group_ = true
6363
[node name="RopeHandle" type="Marker2D" parent="Rope15"]
6464
position = Vector2(-106.181, 0)
6565
script = ExtResource("3_mb3ny")
66+
strength = 1.0
6667
rope_path = NodePath("..")
6768
rope_position = 0.0
68-
strength = 1.0
6969

7070
[node name="RopeHandle2" type="Marker2D" parent="Rope15"]
7171
position = Vector2(93.8187, 0)
7272
script = ExtResource("3_mb3ny")
73-
rope_path = NodePath("..")
7473
strength = 1.0
74+
rope_path = NodePath("..")
7575

7676
[node name="Rope16" type="Node2D" parent="."]
7777
position = Vector2(365, 1438)
@@ -85,15 +85,15 @@ metadata/_edit_group_ = true
8585
[node name="RopeHandle" type="Marker2D" parent="Rope16"]
8686
position = Vector2(-106.181, 0)
8787
script = ExtResource("3_mb3ny")
88+
strength = 1.0
8889
rope_path = NodePath("..")
8990
rope_position = 0.0
90-
strength = 1.0
9191

9292
[node name="RopeHandle2" type="Marker2D" parent="Rope16"]
9393
position = Vector2(93.8187, 0)
9494
script = ExtResource("3_mb3ny")
95-
rope_path = NodePath("..")
9695
strength = 1.0
96+
rope_path = NodePath("..")
9797

9898
[node name="Rope17" type="Node2D" parent="."]
9999
position = Vector2(583, 1438)
@@ -106,15 +106,15 @@ metadata/_edit_group_ = true
106106
[node name="RopeHandle" type="Marker2D" parent="Rope17"]
107107
position = Vector2(-106.181, 0)
108108
script = ExtResource("3_mb3ny")
109+
strength = 1.0
109110
rope_path = NodePath("..")
110111
rope_position = 0.0
111-
strength = 1.0
112112

113113
[node name="RopeHandle2" type="Marker2D" parent="Rope17"]
114114
position = Vector2(93.819, 0)
115115
script = ExtResource("3_mb3ny")
116-
rope_path = NodePath("..")
117116
strength = 1.0
117+
rope_path = NodePath("..")
118118

119119
[node name="Rope18" type="Node2D" parent="."]
120120
position = Vector2(807, 1438)
@@ -128,18 +128,18 @@ metadata/_edit_group_ = true
128128
[node name="RopeHandle" type="Marker2D" parent="Rope18"]
129129
position = Vector2(-106.181, 0)
130130
script = ExtResource("3_mb3ny")
131+
strength = 1.0
131132
rope_path = NodePath("..")
132133
rope_position = 0.0
133-
strength = 1.0
134134

135135
[node name="RopeHandle2" type="Marker2D" parent="Rope18"]
136136
position = Vector2(93.819, 0)
137137
script = ExtResource("3_mb3ny")
138-
rope_path = NodePath("..")
139138
strength = 1.0
139+
rope_path = NodePath("..")
140140

141141
[node name="Node2D2" type="Node2D" parent="."]
142-
position = Vector2(180.7, 124.476)
142+
position = Vector2(146.001, 146.237)
143143

144144
[node name="Rope3" type="Node2D" parent="Node2D2"]
145145
position = Vector2(-88.3748, -22.2188)
@@ -414,13 +414,20 @@ text = "max_endpoint_distance provides an easy way to constraint the rope length
414414

415415
[node name="Label22" type="Label" parent="."]
416416
offset_left = 1267.0
417-
offset_top = 1328.0
417+
offset_top = 1698.0
418418
offset_right = 2007.0
419-
offset_bottom = 1351.0
419+
offset_bottom = 1747.0
420420
text = "max_endpoint_distance only considers the distance between both endpoints.
421421
Does not consider the actual rope length.
422422
"
423423

424+
[node name="Label28" type="Label" parent="."]
425+
offset_left = 1267.0
426+
offset_top = 1364.0
427+
offset_right = 2067.0
428+
offset_bottom = 1387.0
429+
text = "It can be specified how to contract the rope when exceeding max_endpoint_distance."
430+
424431
[node name="Label20" type="Label" parent="."]
425432
offset_left = 1236.0
426433
offset_top = 956.0
@@ -460,7 +467,7 @@ theme_override_styles/separator = SubResource("StyleBoxFlat_f4u3w")
460467
offset_left = 1105.0
461468
offset_top = 854.0
462469
offset_right = 1309.0
463-
offset_bottom = 1771.0
470+
offset_bottom = 2129.0
464471
theme_override_styles/separator = SubResource("StyleBoxFlat_f4u3w")
465472

466473
[node name="Rope" type="Node2D" parent="."]
@@ -470,8 +477,8 @@ script = ExtResource("4_rnvio")
470477
[node name="RopeHandle" type="Marker2D" parent="Rope"]
471478
position = Vector2(136, 257)
472479
script = ExtResource("3_mb3ny")
473-
rope_path = NodePath("..")
474480
strength = 1.0
481+
rope_path = NodePath("..")
475482

476483
[node name="Rope2" type="Node2D" parent="."]
477484
position = Vector2(1697, 992)
@@ -481,54 +488,134 @@ max_endpoint_distance = 100.0
481488
[node name="RopeHandle" type="Marker2D" parent="Rope2"]
482489
position = Vector2(136, 257)
483490
script = ExtResource("3_mb3ny")
484-
rope_path = NodePath("..")
485491
strength = 1.0
492+
rope_path = NodePath("..")
486493

487494
[node name="Label23" type="Label" parent="."]
488495
offset_left = 1236.0
489-
offset_top = 1406.0
496+
offset_top = 1776.0
490497
offset_right = 1460.0
491-
offset_bottom = 1429.0
498+
offset_bottom = 1799.0
492499
text = "max_endpoint_distance = -1"
493500

501+
[node name="Label25" type="Label" parent="."]
502+
offset_left = 1651.0
503+
offset_top = 1497.0
504+
offset_right = 1875.0
505+
offset_bottom = 1520.0
506+
text = "resolve_to_begin = true"
507+
508+
[node name="Label27" type="Label" parent="."]
509+
offset_left = 1650.0
510+
offset_top = 1422.0
511+
offset_right = 1874.0
512+
offset_bottom = 1445.0
513+
text = "default (center)"
514+
515+
[node name="Label26" type="Label" parent="."]
516+
offset_left = 1649.0
517+
offset_top = 1563.0
518+
offset_right = 1873.0
519+
offset_bottom = 1586.0
520+
text = "resolve_to_end = true"
521+
494522
[node name="Label24" type="Label" parent="."]
495523
offset_left = 1609.0
496-
offset_top = 1406.0
524+
offset_top = 1776.0
497525
offset_right = 1837.0
498-
offset_bottom = 1429.0
526+
offset_bottom = 1799.0
499527
text = "max_endpoint_distance = 100"
500528

501529
[node name="Rope4" type="Node2D" parent="."]
502-
position = Vector2(1697, 1442)
530+
position = Vector2(1697, 1812)
503531
script = ExtResource("4_rnvio")
504532
max_endpoint_distance = 100.0
505533

506534
[node name="RopeHandle" type="Marker2D" parent="Rope4"]
507535
position = Vector2(250, 56)
508536
script = ExtResource("3_mb3ny")
537+
strength = 1.0
509538
rope_path = NodePath("..")
510539
rope_position = 0.622
511-
strength = 1.0
512540

513541
[node name="RopeHandle2" type="Marker2D" parent="Rope4"]
514542
position = Vector2(139, 249)
515543
script = ExtResource("3_mb3ny")
516-
rope_path = NodePath("..")
517544
strength = 1.0
545+
rope_path = NodePath("..")
518546

519547
[node name="Rope5" type="Node2D" parent="."]
520-
position = Vector2(1318, 1446)
548+
position = Vector2(1318, 1816)
521549
script = ExtResource("4_rnvio")
522550

523551
[node name="RopeHandle" type="Marker2D" parent="Rope5"]
524552
position = Vector2(250, 56)
525553
script = ExtResource("3_mb3ny")
554+
strength = 1.0
526555
rope_path = NodePath("..")
527556
rope_position = 0.622
528-
strength = 1.0
529557

530558
[node name="RopeHandle2" type="Marker2D" parent="Rope5"]
531559
position = Vector2(139, 249)
532560
script = ExtResource("3_mb3ny")
561+
strength = 1.0
533562
rope_path = NodePath("..")
563+
564+
[node name="Rope6" type="Node2D" parent="."]
565+
position = Vector2(1288, 1431)
566+
script = ExtResource("4_rnvio")
567+
max_endpoint_distance = 150.0
568+
resolve_to_begin = true
569+
fixate_begin = false
570+
571+
[node name="RopeHandle" type="Marker2D" parent="Rope6"]
572+
position = Vector2(-7, 79)
573+
script = ExtResource("3_mb3ny")
574+
strength = 1.0
575+
rope_path = NodePath("..")
576+
rope_position = 0.0
577+
578+
[node name="RopeHandle2" type="Marker2D" parent="Rope6"]
579+
position = Vector2(323, 78)
580+
script = ExtResource("3_mb3ny")
581+
strength = 1.0
582+
rope_path = NodePath("..")
583+
584+
[node name="Rope8" type="Node2D" parent="."]
585+
position = Vector2(1288, 1336)
586+
script = ExtResource("4_rnvio")
587+
max_endpoint_distance = 150.0
588+
fixate_begin = false
589+
590+
[node name="RopeHandle" type="Marker2D" parent="Rope8"]
591+
position = Vector2(-7, 99)
592+
script = ExtResource("3_mb3ny")
593+
strength = 1.0
594+
rope_path = NodePath("..")
595+
rope_position = 0.0
596+
597+
[node name="RopeHandle2" type="Marker2D" parent="Rope8"]
598+
position = Vector2(323, 98)
599+
script = ExtResource("3_mb3ny")
600+
strength = 1.0
601+
rope_path = NodePath("..")
602+
603+
[node name="Rope7" type="Node2D" parent="."]
604+
position = Vector2(1288, 1496)
605+
script = ExtResource("4_rnvio")
606+
max_endpoint_distance = 150.0
607+
resolve_to_end = true
608+
fixate_begin = false
609+
610+
[node name="RopeHandle" type="Marker2D" parent="Rope7"]
611+
position = Vector2(-7, 83)
612+
script = ExtResource("3_mb3ny")
613+
strength = 1.0
614+
rope_path = NodePath("..")
615+
rope_position = 0.0
616+
617+
[node name="RopeHandle2" type="Marker2D" parent="Rope7"]
618+
position = Vector2(323, 82)
619+
script = ExtResource("3_mb3ny")
534620
strength = 1.0
621+
rope_path = NodePath("..")

src/NativeRopeContext.cpp

Lines changed: 32 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ void NativeRopeContext::load_context(Node2D* rope)
4444
seg_lengths = rope->call("get_segment_lengths");
4545
simulation_weights = rope->get("_simulation_weights");
4646
fixate_begin = rope->get("fixate_begin");
47+
resolve_to_begin = rope->get("resolve_to_begin");
48+
resolve_to_end = rope->get("resolve_to_end");
4749
}
4850

4951
void NativeRopeContext::simulate(double delta)
@@ -173,29 +175,43 @@ static void constraint_segment(Vector2* point_a, Vector2* point_b, float weight_
173175
void NativeRopeContext::_constraint()
174176
{
175177
const bool use_euclid_constraint = max_endpoint_distance > 0;
176-
Vector2* first_point;
177-
Vector2* last_point;
178-
float euclid_constraint_first_weight;
179-
float max_stretch_length_sqr;
180178

181179
if (use_euclid_constraint)
182180
{
183-
first_point = &points[0];
184-
last_point = &points[(int)points.size() - 1];
185-
euclid_constraint_first_weight = fixate_begin ? 0.0 : 1.0;
186-
max_stretch_length_sqr = max_endpoint_distance * max_endpoint_distance;
187-
}
181+
Vector2* const first_point = &points[0];
182+
Vector2* const last_point = &points[(int)points.size() - 1];
183+
const float max_stretch_length_sqr = max_endpoint_distance * max_endpoint_distance;
184+
const float rope_length_sqr = first_point->distance_squared_to(*last_point);
188185

189-
for (int _ = 0; _ < num_constraint_iterations; ++_)
190-
{
191-
if (use_euclid_constraint)
186+
if (rope_length_sqr > max_stretch_length_sqr)
192187
{
193-
const float rope_length_sqr = first_point->distance_squared_to(*last_point);
194-
195-
if (rope_length_sqr > max_stretch_length_sqr)
196-
constraint_segment(first_point, last_point, euclid_constraint_first_weight, 1.0, max_endpoint_distance);
188+
float weight_a;
189+
float weight_b;
190+
191+
// Always has priority
192+
if (fixate_begin)
193+
{
194+
weight_a = 0.0;
195+
weight_b = 1.0;
196+
}
197+
else if (resolve_to_begin == resolve_to_end)
198+
{
199+
weight_a = 1.0;
200+
weight_b = 1.0;
201+
}
202+
else
203+
{
204+
weight_a = resolve_to_begin ? 0.0 : 1.0;
205+
weight_b = resolve_to_end ? 0.0 : 1.0;
206+
}
207+
208+
constraint_segment(first_point, last_point, weight_a, weight_b, max_endpoint_distance);
197209
}
210+
}
211+
198212

213+
for (int _ = 0; _ < num_constraint_iterations; ++_)
214+
{
199215
for (int i = 0; i < points.size() - 1; ++i)
200216
constraint_segment(&points[i], &points[i + 1], simulation_weights[i], simulation_weights[i + 1], seg_lengths[i]);
201217
}

src/NativeRopeContext.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ namespace godot
3737
int num_constraint_iterations;
3838
Ref<Curve> damping_curve;
3939
bool fixate_begin;
40+
bool resolve_to_begin;
41+
bool resolve_to_end;
4042
};
4143
}
4244

0 commit comments

Comments
 (0)