Skip to content

Commit 0456e35

Browse files
committed
Add support for per-shape physics materials
This lets users override bounce and friction for individual collision shapes instead of using the same properties for the whole body.
1 parent 09fcbb8 commit 0456e35

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+826
-24
lines changed

doc/classes/CollisionShape2D.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@
2727
<member name="one_way_collision_margin" type="float" setter="set_one_way_collision_margin" getter="get_one_way_collision_margin" default="1.0">
2828
The margin used for one-way collision (in pixels). Higher values will make the shape thicker, and work better for colliders that enter the shape at a high velocity.
2929
</member>
30+
<member name="physics_material" type="PhysicsMaterial" setter="set_physics_material" getter="get_physics_material">
31+
The shape's physics material. Setting a physics material lets the body have different parts with different properties, such as the head and handle of a hammer. Physics materials set on a shape take priority over those set on its body.
32+
</member>
3033
<member name="shape" type="Shape2D" setter="set_shape" getter="get_shape">
3134
The actual shape owned by this collision shape.
3235
</member>

doc/classes/CollisionShape3D.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@
3939
<member name="disabled" type="bool" setter="set_disabled" getter="is_disabled" default="false" keywords="enabled">
4040
A disabled collision shape has no effect in the world.
4141
</member>
42+
<member name="physics_material" type="PhysicsMaterial" setter="set_physics_material" getter="get_physics_material">
43+
The shape's physics material. Setting a physics material lets the body have different parts with different properties, such as the head and handle of a hammer. Physics materials set on a shape take priority over those set on its body.
44+
</member>
4245
<member name="shape" type="Shape3D" setter="set_shape" getter="get_shape">
4346
The actual shape owned by this collision shape.
4447
</member>

doc/classes/PhysicsServer2D.xml

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -469,13 +469,29 @@
469469
Returns the [RID] of the shape with the given index in the body's array of shapes.
470470
</description>
471471
</method>
472+
<method name="body_get_shape_bounce_override" qualifiers="const">
473+
<return type="float" />
474+
<param index="0" name="body" type="RID" />
475+
<param index="1" name="shape_idx" type="int" />
476+
<description>
477+
Returns the bounciness override for the shape or [constant @GDScript.NAN] if no override is set.
478+
</description>
479+
</method>
472480
<method name="body_get_shape_count" qualifiers="const">
473481
<return type="int" />
474482
<param index="0" name="body" type="RID" />
475483
<description>
476484
Returns the number of shapes added to the body.
477485
</description>
478486
</method>
487+
<method name="body_get_shape_friction_override" qualifiers="const">
488+
<return type="float" />
489+
<param index="0" name="body" type="RID" />
490+
<param index="1" name="shape_idx" type="int" />
491+
<description>
492+
Returns the friction override for the shape or [constant @GDScript.NAN] if no override is set.
493+
</description>
494+
</method>
479495
<method name="body_get_shape_transform" qualifiers="const">
480496
<return type="Transform2D" />
481497
<param index="0" name="body" type="RID" />
@@ -655,6 +671,16 @@
655671
Sets the one-way collision properties of the body's shape with the given index. If [param enable] is [code]true[/code], the one-way collision direction given by the shape's local upward axis [code]body_get_shape_transform(body, shape_idx).y[/code] will be used to ignore collisions with the shape in the opposite direction, and to ensure depenetration of kinematic bodies happens in this direction.
656672
</description>
657673
</method>
674+
<method name="body_set_shape_bounce_override">
675+
<return type="void" />
676+
<param index="0" name="body" type="RID" />
677+
<param index="1" name="shape_idx" type="int" />
678+
<param index="2" name="enable" type="bool" />
679+
<param index="3" name="bounce" type="float" default="0.0" />
680+
<description>
681+
Sets the bounce for the shape if [param enable] is [code]true[/code], resets to the body's value if [code]false[/code]. A negative value of [param friction] is equivalent to enabling [member PhysicsMaterial.absorbent].
682+
</description>
683+
</method>
658684
<method name="body_set_shape_disabled">
659685
<return type="void" />
660686
<param index="0" name="body" type="RID" />
@@ -664,6 +690,16 @@
664690
Sets the disabled property of the body's shape with the given index. If [param disabled] is [code]true[/code], then the shape will be ignored in all collision detection.
665691
</description>
666692
</method>
693+
<method name="body_set_shape_friction_override">
694+
<return type="void" />
695+
<param index="0" name="body" type="RID" />
696+
<param index="1" name="shape_idx" type="int" />
697+
<param index="2" name="enable" type="bool" />
698+
<param index="3" name="friction" type="float" default="0.0" />
699+
<description>
700+
Sets the friction for the shape if [param enable] is [code]true[/code], resets to the body's value if [code]false[/code]. A negative value of [param friction] is equivalent to enabling [member PhysicsMaterial.rough].
701+
</description>
702+
</method>
667703
<method name="body_set_shape_transform">
668704
<return type="void" />
669705
<param index="0" name="body" type="RID" />

doc/classes/PhysicsServer2DExtension.xml

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -477,13 +477,29 @@
477477
Overridable version of [method PhysicsServer2D.body_get_shape].
478478
</description>
479479
</method>
480+
<method name="_body_get_shape_bounce_override" qualifiers="virtual const">
481+
<return type="float" />
482+
<param index="0" name="body" type="RID" />
483+
<param index="1" name="shape_idx" type="int" />
484+
<description>
485+
Overridable version of [method PhysicsServer2D.body_get_shape_bounce_override].
486+
</description>
487+
</method>
480488
<method name="_body_get_shape_count" qualifiers="virtual const">
481489
<return type="int" />
482490
<param index="0" name="body" type="RID" />
483491
<description>
484492
Overridable version of [method PhysicsServer2D.body_get_shape_count].
485493
</description>
486494
</method>
495+
<method name="_body_get_shape_friction_override" qualifiers="virtual const">
496+
<return type="float" />
497+
<param index="0" name="body" type="RID" />
498+
<param index="1" name="shape_idx" type="int" />
499+
<description>
500+
Overridable version of [method PhysicsServer2D.body_get_shape_friction_override].
501+
</description>
502+
</method>
487503
<method name="_body_get_shape_transform" qualifiers="virtual const">
488504
<return type="Transform2D" />
489505
<param index="0" name="body" type="RID" />
@@ -672,6 +688,16 @@
672688
Overridable version of [method PhysicsServer2D.body_set_shape_as_one_way_collision].
673689
</description>
674690
</method>
691+
<method name="_body_set_shape_bounce_override" qualifiers="virtual">
692+
<return type="void" />
693+
<param index="0" name="body" type="RID" />
694+
<param index="1" name="shape_idx" type="int" />
695+
<param index="2" name="enable" type="bool" />
696+
<param index="3" name="bounce" type="float" />
697+
<description>
698+
Overridable version of [method PhysicsServer2D.body_set_shape_bounce_override].
699+
</description>
700+
</method>
675701
<method name="_body_set_shape_disabled" qualifiers="virtual">
676702
<return type="void" />
677703
<param index="0" name="body" type="RID" />
@@ -681,6 +707,16 @@
681707
Overridable version of [method PhysicsServer2D.body_set_shape_disabled].
682708
</description>
683709
</method>
710+
<method name="_body_set_shape_friction_override" qualifiers="virtual">
711+
<return type="void" />
712+
<param index="0" name="body" type="RID" />
713+
<param index="1" name="shape_idx" type="int" />
714+
<param index="2" name="enable" type="bool" />
715+
<param index="3" name="friction" type="float" />
716+
<description>
717+
Overridable version of [method PhysicsServer2D.body_set_shape_friction_override].
718+
</description>
719+
</method>
684720
<method name="_body_set_shape_transform" qualifiers="virtual">
685721
<return type="void" />
686722
<param index="0" name="body" type="RID" />

doc/classes/PhysicsServer3D.xml

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -437,13 +437,29 @@
437437
Returns the [RID] of the nth shape of a body.
438438
</description>
439439
</method>
440+
<method name="body_get_shape_bounce_override" qualifiers="const">
441+
<return type="float" />
442+
<param index="0" name="body" type="RID" />
443+
<param index="1" name="shape_idx" type="int" />
444+
<description>
445+
Returns the bounciness override for the shape or [constant @GDScript.NAN] if no override is set.
446+
</description>
447+
</method>
440448
<method name="body_get_shape_count" qualifiers="const">
441449
<return type="int" />
442450
<param index="0" name="body" type="RID" />
443451
<description>
444452
Returns the number of shapes assigned to a body.
445453
</description>
446454
</method>
455+
<method name="body_get_shape_friction_override" qualifiers="const">
456+
<return type="float" />
457+
<param index="0" name="body" type="RID" />
458+
<param index="1" name="shape_idx" type="int" />
459+
<description>
460+
Returns the friction override for the shape or [constant @GDScript.NAN] if no override is set.
461+
</description>
462+
</method>
447463
<method name="body_get_shape_transform" qualifiers="const">
448464
<return type="Transform3D" />
449465
<param index="0" name="body" type="RID" />
@@ -644,6 +660,16 @@
644660
Substitutes a given body shape by another. The old shape is selected by its index, the new one by its [RID].
645661
</description>
646662
</method>
663+
<method name="body_set_shape_bounce_override">
664+
<return type="void" />
665+
<param index="0" name="body" type="RID" />
666+
<param index="1" name="shape_idx" type="int" />
667+
<param index="2" name="enable" type="bool" />
668+
<param index="3" name="bounce" type="float" default="0.0" />
669+
<description>
670+
Sets the bounciness for the shape if [param enable] is [code]true[/code], resets to the body's value if [code]false[/code]. A negative value of [param bounce] is equivalent to enabling [member PhysicsMaterial.absorbent].
671+
</description>
672+
</method>
647673
<method name="body_set_shape_disabled">
648674
<return type="void" />
649675
<param index="0" name="body" type="RID" />
@@ -652,6 +678,16 @@
652678
<description>
653679
</description>
654680
</method>
681+
<method name="body_set_shape_friction_override">
682+
<return type="void" />
683+
<param index="0" name="body" type="RID" />
684+
<param index="1" name="shape_idx" type="int" />
685+
<param index="2" name="enable" type="bool" />
686+
<param index="3" name="friction" type="float" default="0.0" />
687+
<description>
688+
Sets the friction for the shape if [param enable] is [code]true[/code], resets to the body's value if [code]false[/code]. A negative value of [param friction] is equivalent to enabling [member PhysicsMaterial.rough].
689+
</description>
690+
</method>
655691
<method name="body_set_shape_transform">
656692
<return type="void" />
657693
<param index="0" name="body" type="RID" />

doc/classes/PhysicsServer3DExtension.xml

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -369,12 +369,28 @@
369369
<description>
370370
</description>
371371
</method>
372+
<method name="_body_get_shape_bounce_override" qualifiers="virtual const">
373+
<return type="float" />
374+
<param index="0" name="body" type="RID" />
375+
<param index="1" name="shape_idx" type="int" />
376+
<description>
377+
Overridable version of [method PhysicsServer3D.body_get_shape_bounce_override].
378+
</description>
379+
</method>
372380
<method name="_body_get_shape_count" qualifiers="virtual const">
373381
<return type="int" />
374382
<param index="0" name="body" type="RID" />
375383
<description>
376384
</description>
377385
</method>
386+
<method name="_body_get_shape_friction_override" qualifiers="virtual const">
387+
<return type="float" />
388+
<param index="0" name="body" type="RID" />
389+
<param index="1" name="shape_idx" type="int" />
390+
<description>
391+
Overridable version of [method PhysicsServer3D.body_get_shape_friction_override].
392+
</description>
393+
</method>
378394
<method name="_body_get_shape_transform" qualifiers="virtual const">
379395
<return type="Transform3D" />
380396
<param index="0" name="body" type="RID" />
@@ -556,6 +572,16 @@
556572
<description>
557573
</description>
558574
</method>
575+
<method name="_body_set_shape_bounce_override" qualifiers="virtual">
576+
<return type="void" />
577+
<param index="0" name="body" type="RID" />
578+
<param index="1" name="shape_idx" type="int" />
579+
<param index="2" name="enable" type="bool" />
580+
<param index="3" name="bounce" type="float" />
581+
<description>
582+
Overridable version of [method PhysicsServer3D.body_set_shape_bounce_override].
583+
</description>
584+
</method>
559585
<method name="_body_set_shape_disabled" qualifiers="virtual">
560586
<return type="void" />
561587
<param index="0" name="body" type="RID" />
@@ -564,6 +590,16 @@
564590
<description>
565591
</description>
566592
</method>
593+
<method name="_body_set_shape_friction_override" qualifiers="virtual">
594+
<return type="void" />
595+
<param index="0" name="body" type="RID" />
596+
<param index="1" name="shape_idx" type="int" />
597+
<param index="2" name="enable" type="bool" />
598+
<param index="3" name="friction" type="float" />
599+
<description>
600+
Overridable version of [method PhysicsServer3D.body_set_shape_friction_override].
601+
</description>
602+
</method>
567603
<method name="_body_set_shape_transform" qualifiers="virtual">
568604
<return type="void" />
569605
<param index="0" name="body" type="RID" />

modules/godot_physics_2d/godot_body_2d.cpp

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -654,6 +654,56 @@ void GodotBody2D::integrate_velocities(real_t p_step) {
654654
_update_transform_dependent();
655655
}
656656

657+
void GodotBody2D::set_shape_friction(int p_index, real_t p_friction) {
658+
ERR_FAIL_INDEX(p_index, get_shape_count());
659+
660+
int old_size = shape_frictions.size();
661+
if (old_size <= p_index) {
662+
shape_frictions.resize(p_index + 1);
663+
664+
for (int i = old_size; i < p_index; i++) {
665+
shape_frictions[i] = NAN;
666+
}
667+
}
668+
669+
shape_frictions[p_index] = p_friction;
670+
}
671+
672+
void GodotBody2D::set_shape_bounce(int p_index, real_t p_bounce) {
673+
ERR_FAIL_INDEX(p_index, get_shape_count());
674+
675+
int old_size = shape_bounces.size();
676+
if (old_size <= p_index) {
677+
shape_bounces.resize(p_index + 1);
678+
679+
for (int i = old_size; i < p_index; i++) {
680+
shape_bounces[i] = NAN;
681+
}
682+
}
683+
684+
shape_bounces[p_index] = p_bounce;
685+
}
686+
687+
real_t GodotBody2D::get_shape_friction(int p_index) const {
688+
ERR_FAIL_INDEX_V(p_index, get_shape_count(), NAN);
689+
690+
if (static_cast<unsigned int>(p_index) >= shape_frictions.size()) {
691+
return NAN;
692+
}
693+
694+
return shape_frictions[p_index];
695+
}
696+
697+
real_t GodotBody2D::get_shape_bounce(int p_index) const {
698+
ERR_FAIL_INDEX_V(p_index, get_shape_count(), NAN);
699+
700+
if (static_cast<unsigned int>(p_index) >= shape_bounces.size()) {
701+
return NAN;
702+
}
703+
704+
return shape_bounces[p_index];
705+
}
706+
657707
void GodotBody2D::wakeup_neighbours() {
658708
for (const Pair<GodotConstraint2D *, int> &E : constraint_list) {
659709
const GodotConstraint2D *c = E.first;

modules/godot_physics_2d/godot_body_2d.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,9 @@ class GodotBody2D : public GodotCollisionObject2D {
7575
real_t inertia = 0.0;
7676
real_t _inv_inertia = 0.0;
7777

78+
LocalVector<real_t> shape_frictions;
79+
LocalVector<real_t> shape_bounces;
80+
7881
Vector2 center_of_mass_local;
7982
Vector2 center_of_mass;
8083

@@ -331,6 +334,12 @@ class GodotBody2D : public GodotCollisionObject2D {
331334
return Vector2();
332335
}
333336

337+
void set_shape_friction(int p_index, real_t p_friction);
338+
void set_shape_bounce(int p_index, real_t p_bounce);
339+
340+
real_t get_shape_friction(int p_index) const;
341+
real_t get_shape_bounce(int p_index) const;
342+
334343
void call_queries();
335344
void wakeup_neighbours();
336345

0 commit comments

Comments
 (0)