3
3
extends Node
4
4
class_name AnimatedShape2D
5
5
6
- # _ _ _ _____ _
7
- # /\ (_) | | | |/ ____| |
8
- # / \ _ __ _ _ __ ___ __ _| |_ ___ __| | (___ | |__ __ _ _ __ ___
9
- # / /\ \ | '_ \| | '_ ` _ \ / _` | __/ _ \/ _` |\___ \| '_ \ / _` | '_ \ / _ \
10
- # / ____ \| | | | | | | | | | (_| | || __/ (_| |____) | | | | (_| | |_) | __/
11
- # /_/ \_\_| |_|_|_| |_| |_|\__,_|\__\___|\__,_|_____/|_| |_|\__,_| .__/ \___|
12
- # | |
13
- # v0.1.3-20231231 |_|
14
6
## Animates a CollisionShape2D for each frame of an AnimatedSprite2D.
15
7
## You can put this pretty much anywhere you want in your scene.
16
8
@@ -49,6 +41,19 @@ class_name AnimatedShape2D
49
41
@export var handle_flip_h := true
50
42
51
43
44
+ enum SHAPE_UPDATE_MODE {
45
+ ## Update the existing shape resource properties in the CollisionShape2D,
46
+ ## but only if shape types are compatible.
47
+ UPDATE ,
48
+ ## Always replace the existing shape resource in the CollisionShape2D.
49
+ ## This may trigger additional [code]entered[/code] signals.
50
+ REPLACE ,
51
+ }
52
+
53
+ ## How the Shape2D resource is updated between frames.
54
+ @export var update_shape_mode := SHAPE_UPDATE_MODE .UPDATE
55
+
56
+
52
57
var fallback_shape : Shape2D
53
58
var fallback_position : Vector2
54
59
var fallback_disabled : bool
@@ -76,12 +81,16 @@ func setup():
76
81
if self .collision_shape == null :
77
82
return
78
83
self .fallback_shape = self .collision_shape .shape
84
+ if self .update_shape_mode == SHAPE_UPDATE_MODE .UPDATE :
85
+ # We're going to update the original collision shape's shape, so we copy
86
+ self .fallback_shape = self .collision_shape .shape .duplicate (true )
79
87
self .fallback_position = self .collision_shape .position
80
88
self .fallback_disabled = self .collision_shape .disabled
81
89
self .collision_shape_parent = self .collision_shape .get_parent ()
82
90
if self .collision_shape_parent != null :
83
91
self .initial_scale = self .collision_shape_parent .scale
84
92
93
+ self .animated_sprite .animation_changed .connect (update_shape )
85
94
self .animated_sprite .frame_changed .connect (update_shape )
86
95
87
96
@@ -106,7 +115,7 @@ func update_shape():
106
115
position = self .fallback_position
107
116
disabled = self .fallback_disabled
108
117
109
- self . collision_shape . shape = shape
118
+ update_collision_shape_shape ( shape )
110
119
self .collision_shape .position = position
111
120
self .collision_shape .disabled = disabled
112
121
if self .handle_flip_h and is_collision_shape_parent_flippable ():
@@ -117,6 +126,68 @@ func update_shape():
117
126
self .collision_shape_parent .scale .x = self .initial_scale .x
118
127
119
128
129
+ func update_collision_shape_shape (new_shape : Shape2D ):
130
+ if new_shape == self .collision_shape .shape :
131
+ return
132
+
133
+ if (
134
+ self .update_shape_mode == SHAPE_UPDATE_MODE .UPDATE
135
+ and
136
+ self .collision_shape .shape != null
137
+ and
138
+ new_shape != null
139
+ ):
140
+ if (
141
+ (self .collision_shape .shape is RectangleShape2D )
142
+ and
143
+ (new_shape is RectangleShape2D )
144
+ ):
145
+ self .collision_shape .shape .size = new_shape .size
146
+ return
147
+
148
+ if (
149
+ (self .collision_shape .shape is CircleShape2D )
150
+ and
151
+ (new_shape is CircleShape2D )
152
+ ):
153
+ self .collision_shape .shape .radius = new_shape .radius
154
+ return
155
+
156
+ if (
157
+ (self .collision_shape .shape is CapsuleShape2D )
158
+ and
159
+ (new_shape is CapsuleShape2D )
160
+ ):
161
+ self .collision_shape .shape .height = new_shape .height
162
+ self .collision_shape .shape .radius = new_shape .radius
163
+ return
164
+
165
+ if (
166
+ (self .collision_shape .shape is SegmentShape2D )
167
+ and
168
+ (new_shape is SegmentShape2D )
169
+ ):
170
+ self .collision_shape .shape .a = new_shape .a
171
+ self .collision_shape .shape .b = new_shape .b
172
+ return
173
+
174
+ if (
175
+ (self .collision_shape .shape is WorldBoundaryShape2D )
176
+ and
177
+ (new_shape is WorldBoundaryShape2D )
178
+ ):
179
+ self .collision_shape .shape .distance = new_shape .distance
180
+ self .collision_shape .shape .normal = new_shape .normal
181
+ return
182
+
183
+ # If the update cannot be done, we want to duplicate the shape
184
+ # because we might update it later on.
185
+ self .collision_shape .shape = new_shape .duplicate (true )
186
+ return
187
+
188
+ self .collision_shape .shape = new_shape
189
+
190
+
120
191
## We don't want to flip PhysicsBodies because it creates odd behaviors.
121
192
## Override this method if that's what you want for some reason.
122
193
func is_collision_shape_parent_flippable () -> bool :
0 commit comments