1 | /**************************************************************************/ |
2 | /* animated_sprite_2d.cpp */ |
3 | /**************************************************************************/ |
4 | /* This file is part of: */ |
5 | /* GODOT ENGINE */ |
6 | /* https://godotengine.org */ |
7 | /**************************************************************************/ |
8 | /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ |
9 | /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ |
10 | /* */ |
11 | /* Permission is hereby granted, free of charge, to any person obtaining */ |
12 | /* a copy of this software and associated documentation files (the */ |
13 | /* "Software"), to deal in the Software without restriction, including */ |
14 | /* without limitation the rights to use, copy, modify, merge, publish, */ |
15 | /* distribute, sublicense, and/or sell copies of the Software, and to */ |
16 | /* permit persons to whom the Software is furnished to do so, subject to */ |
17 | /* the following conditions: */ |
18 | /* */ |
19 | /* The above copyright notice and this permission notice shall be */ |
20 | /* included in all copies or substantial portions of the Software. */ |
21 | /* */ |
22 | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ |
23 | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ |
24 | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ |
25 | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ |
26 | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ |
27 | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ |
28 | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ |
29 | /**************************************************************************/ |
30 | |
31 | #include "animated_sprite_2d.h" |
32 | |
33 | #include "scene/main/viewport.h" |
34 | #include "scene/scene_string_names.h" |
35 | |
36 | #ifdef TOOLS_ENABLED |
37 | Dictionary AnimatedSprite2D::_edit_get_state() const { |
38 | Dictionary state = Node2D::_edit_get_state(); |
39 | state["offset" ] = offset; |
40 | return state; |
41 | } |
42 | |
43 | void AnimatedSprite2D::_edit_set_state(const Dictionary &p_state) { |
44 | Node2D::_edit_set_state(p_state); |
45 | set_offset(p_state["offset" ]); |
46 | } |
47 | |
48 | void AnimatedSprite2D::_edit_set_pivot(const Point2 &p_pivot) { |
49 | set_offset(get_offset() - p_pivot); |
50 | set_position(get_transform().xform(p_pivot)); |
51 | } |
52 | |
53 | Point2 AnimatedSprite2D::_edit_get_pivot() const { |
54 | return Vector2(); |
55 | } |
56 | |
57 | bool AnimatedSprite2D::_edit_use_pivot() const { |
58 | return true; |
59 | } |
60 | |
61 | Rect2 AnimatedSprite2D::_edit_get_rect() const { |
62 | return _get_rect(); |
63 | } |
64 | |
65 | bool AnimatedSprite2D::_edit_use_rect() const { |
66 | if (frames.is_null() || !frames->has_animation(animation)) { |
67 | return false; |
68 | } |
69 | if (frame < 0 || frame >= frames->get_frame_count(animation)) { |
70 | return false; |
71 | } |
72 | |
73 | Ref<Texture2D> t; |
74 | if (animation) { |
75 | t = frames->get_frame_texture(animation, frame); |
76 | } |
77 | return t.is_valid(); |
78 | } |
79 | #endif |
80 | |
81 | Rect2 AnimatedSprite2D::get_anchorable_rect() const { |
82 | return _get_rect(); |
83 | } |
84 | |
85 | Rect2 AnimatedSprite2D::_get_rect() const { |
86 | if (frames.is_null() || !frames->has_animation(animation)) { |
87 | return Rect2(); |
88 | } |
89 | if (frame < 0 || frame >= frames->get_frame_count(animation)) { |
90 | return Rect2(); |
91 | } |
92 | |
93 | Ref<Texture2D> t; |
94 | if (animation) { |
95 | t = frames->get_frame_texture(animation, frame); |
96 | } |
97 | if (t.is_null()) { |
98 | return Rect2(); |
99 | } |
100 | Size2 s = t->get_size(); |
101 | |
102 | Point2 ofs = offset; |
103 | if (centered) { |
104 | ofs -= s / 2; |
105 | } |
106 | |
107 | if (s == Size2(0, 0)) { |
108 | s = Size2(1, 1); |
109 | } |
110 | |
111 | return Rect2(ofs, s); |
112 | } |
113 | |
114 | void AnimatedSprite2D::_validate_property(PropertyInfo &p_property) const { |
115 | if (!frames.is_valid()) { |
116 | return; |
117 | } |
118 | |
119 | if (p_property.name == "animation" ) { |
120 | List<StringName> names; |
121 | frames->get_animation_list(&names); |
122 | names.sort_custom<StringName::AlphCompare>(); |
123 | |
124 | bool current_found = false; |
125 | bool is_first_element = true; |
126 | |
127 | for (const StringName &E : names) { |
128 | if (!is_first_element) { |
129 | p_property.hint_string += "," ; |
130 | } else { |
131 | is_first_element = false; |
132 | } |
133 | |
134 | p_property.hint_string += String(E); |
135 | if (animation == E) { |
136 | current_found = true; |
137 | } |
138 | } |
139 | |
140 | if (!current_found) { |
141 | if (p_property.hint_string.is_empty()) { |
142 | p_property.hint_string = String(animation); |
143 | } else { |
144 | p_property.hint_string = String(animation) + "," + p_property.hint_string; |
145 | } |
146 | } |
147 | return; |
148 | } |
149 | |
150 | if (p_property.name == "frame" ) { |
151 | if (playing) { |
152 | p_property.usage = PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_READ_ONLY; |
153 | return; |
154 | } |
155 | |
156 | p_property.hint = PROPERTY_HINT_RANGE; |
157 | if (frames->has_animation(animation) && frames->get_frame_count(animation) > 0) { |
158 | p_property.hint_string = "0," + itos(frames->get_frame_count(animation) - 1) + ",1" ; |
159 | } else { |
160 | // Avoid an error, `hint_string` is required for `PROPERTY_HINT_RANGE`. |
161 | p_property.hint_string = "0,0,1" ; |
162 | } |
163 | p_property.usage |= PROPERTY_USAGE_KEYING_INCREMENTS; |
164 | } |
165 | } |
166 | |
167 | void AnimatedSprite2D::_notification(int p_what) { |
168 | switch (p_what) { |
169 | case NOTIFICATION_READY: { |
170 | if (!Engine::get_singleton()->is_editor_hint() && !frames.is_null() && frames->has_animation(autoplay)) { |
171 | play(autoplay); |
172 | } |
173 | } break; |
174 | |
175 | case NOTIFICATION_INTERNAL_PROCESS: { |
176 | if (frames.is_null() || !frames->has_animation(animation)) { |
177 | return; |
178 | } |
179 | |
180 | double remaining = get_process_delta_time(); |
181 | int i = 0; |
182 | while (remaining) { |
183 | // Animation speed may be changed by animation_finished or frame_changed signals. |
184 | double speed = frames->get_animation_speed(animation) * speed_scale * custom_speed_scale * frame_speed_scale; |
185 | double abs_speed = Math::abs(speed); |
186 | |
187 | if (speed == 0) { |
188 | return; // Do nothing. |
189 | } |
190 | |
191 | // Frame count may be changed by animation_finished or frame_changed signals. |
192 | int fc = frames->get_frame_count(animation); |
193 | |
194 | int last_frame = fc - 1; |
195 | if (!signbit(speed)) { |
196 | // Forwards. |
197 | if (frame_progress >= 1.0) { |
198 | if (frame >= last_frame) { |
199 | if (frames->get_animation_loop(animation)) { |
200 | frame = 0; |
201 | emit_signal("animation_looped" ); |
202 | } else { |
203 | frame = last_frame; |
204 | pause(); |
205 | emit_signal(SceneStringNames::get_singleton()->animation_finished); |
206 | return; |
207 | } |
208 | } else { |
209 | frame++; |
210 | } |
211 | _calc_frame_speed_scale(); |
212 | frame_progress = 0.0; |
213 | queue_redraw(); |
214 | emit_signal(SceneStringNames::get_singleton()->frame_changed); |
215 | } |
216 | double to_process = MIN((1.0 - frame_progress) / abs_speed, remaining); |
217 | frame_progress += to_process * abs_speed; |
218 | remaining -= to_process; |
219 | } else { |
220 | // Backwards. |
221 | if (frame_progress <= 0) { |
222 | if (frame <= 0) { |
223 | if (frames->get_animation_loop(animation)) { |
224 | frame = last_frame; |
225 | emit_signal("animation_looped" ); |
226 | } else { |
227 | frame = 0; |
228 | pause(); |
229 | emit_signal(SceneStringNames::get_singleton()->animation_finished); |
230 | return; |
231 | } |
232 | } else { |
233 | frame--; |
234 | } |
235 | _calc_frame_speed_scale(); |
236 | frame_progress = 1.0; |
237 | queue_redraw(); |
238 | emit_signal(SceneStringNames::get_singleton()->frame_changed); |
239 | } |
240 | double to_process = MIN(frame_progress / abs_speed, remaining); |
241 | frame_progress -= to_process * abs_speed; |
242 | remaining -= to_process; |
243 | } |
244 | |
245 | i++; |
246 | if (i > fc) { |
247 | return; // Prevents freezing if to_process is each time much less than remaining. |
248 | } |
249 | } |
250 | } break; |
251 | |
252 | case NOTIFICATION_DRAW: { |
253 | if (frames.is_null() || !frames->has_animation(animation)) { |
254 | return; |
255 | } |
256 | |
257 | Ref<Texture2D> texture = frames->get_frame_texture(animation, frame); |
258 | if (texture.is_null()) { |
259 | return; |
260 | } |
261 | |
262 | RID ci = get_canvas_item(); |
263 | |
264 | Size2 s = texture->get_size(); |
265 | Point2 ofs = offset; |
266 | if (centered) { |
267 | ofs -= s / 2; |
268 | } |
269 | |
270 | if (get_viewport() && get_viewport()->is_snap_2d_transforms_to_pixel_enabled()) { |
271 | ofs = ofs.floor(); |
272 | } |
273 | Rect2 dst_rect(ofs, s); |
274 | |
275 | if (hflip) { |
276 | dst_rect.size.x = -dst_rect.size.x; |
277 | } |
278 | if (vflip) { |
279 | dst_rect.size.y = -dst_rect.size.y; |
280 | } |
281 | |
282 | texture->draw_rect_region(ci, dst_rect, Rect2(Vector2(), texture->get_size()), Color(1, 1, 1), false); |
283 | } break; |
284 | } |
285 | } |
286 | |
287 | void AnimatedSprite2D::set_sprite_frames(const Ref<SpriteFrames> &p_frames) { |
288 | if (frames == p_frames) { |
289 | return; |
290 | } |
291 | |
292 | if (frames.is_valid()) { |
293 | frames->disconnect(SceneStringNames::get_singleton()->changed, callable_mp(this, &AnimatedSprite2D::_res_changed)); |
294 | } |
295 | stop(); |
296 | frames = p_frames; |
297 | if (frames.is_valid()) { |
298 | frames->connect(SceneStringNames::get_singleton()->changed, callable_mp(this, &AnimatedSprite2D::_res_changed)); |
299 | |
300 | List<StringName> al; |
301 | frames->get_animation_list(&al); |
302 | if (al.size() == 0) { |
303 | set_animation(StringName()); |
304 | autoplay = String(); |
305 | } else { |
306 | if (!frames->has_animation(animation)) { |
307 | set_animation(al[0]); |
308 | } |
309 | if (!frames->has_animation(autoplay)) { |
310 | autoplay = String(); |
311 | } |
312 | } |
313 | } |
314 | |
315 | notify_property_list_changed(); |
316 | queue_redraw(); |
317 | update_configuration_warnings(); |
318 | emit_signal("sprite_frames_changed" ); |
319 | } |
320 | |
321 | Ref<SpriteFrames> AnimatedSprite2D::get_sprite_frames() const { |
322 | return frames; |
323 | } |
324 | |
325 | void AnimatedSprite2D::set_frame(int p_frame) { |
326 | set_frame_and_progress(p_frame, signbit(get_playing_speed()) ? 1.0 : 0.0); |
327 | } |
328 | |
329 | int AnimatedSprite2D::get_frame() const { |
330 | return frame; |
331 | } |
332 | |
333 | void AnimatedSprite2D::set_frame_progress(real_t p_progress) { |
334 | frame_progress = p_progress; |
335 | } |
336 | |
337 | real_t AnimatedSprite2D::get_frame_progress() const { |
338 | return frame_progress; |
339 | } |
340 | |
341 | void AnimatedSprite2D::set_frame_and_progress(int p_frame, real_t p_progress) { |
342 | if (frames.is_null()) { |
343 | return; |
344 | } |
345 | |
346 | bool has_animation = frames->has_animation(animation); |
347 | int end_frame = has_animation ? MAX(0, frames->get_frame_count(animation) - 1) : 0; |
348 | bool is_changed = frame != p_frame; |
349 | |
350 | if (p_frame < 0) { |
351 | frame = 0; |
352 | } else if (has_animation && p_frame > end_frame) { |
353 | frame = end_frame; |
354 | } else { |
355 | frame = p_frame; |
356 | } |
357 | |
358 | _calc_frame_speed_scale(); |
359 | frame_progress = p_progress; |
360 | |
361 | if (!is_changed) { |
362 | return; // No change, don't redraw. |
363 | } |
364 | queue_redraw(); |
365 | emit_signal(SceneStringNames::get_singleton()->frame_changed); |
366 | } |
367 | |
368 | void AnimatedSprite2D::set_speed_scale(float p_speed_scale) { |
369 | speed_scale = p_speed_scale; |
370 | } |
371 | |
372 | float AnimatedSprite2D::get_speed_scale() const { |
373 | return speed_scale; |
374 | } |
375 | |
376 | float AnimatedSprite2D::get_playing_speed() const { |
377 | if (!playing) { |
378 | return 0; |
379 | } |
380 | return speed_scale * custom_speed_scale; |
381 | } |
382 | |
383 | void AnimatedSprite2D::set_centered(bool p_center) { |
384 | centered = p_center; |
385 | queue_redraw(); |
386 | item_rect_changed(); |
387 | } |
388 | |
389 | bool AnimatedSprite2D::is_centered() const { |
390 | return centered; |
391 | } |
392 | |
393 | void AnimatedSprite2D::set_offset(const Point2 &p_offset) { |
394 | offset = p_offset; |
395 | queue_redraw(); |
396 | item_rect_changed(); |
397 | } |
398 | |
399 | Point2 AnimatedSprite2D::get_offset() const { |
400 | return offset; |
401 | } |
402 | |
403 | void AnimatedSprite2D::set_flip_h(bool p_flip) { |
404 | hflip = p_flip; |
405 | queue_redraw(); |
406 | } |
407 | |
408 | bool AnimatedSprite2D::is_flipped_h() const { |
409 | return hflip; |
410 | } |
411 | |
412 | void AnimatedSprite2D::set_flip_v(bool p_flip) { |
413 | vflip = p_flip; |
414 | queue_redraw(); |
415 | } |
416 | |
417 | bool AnimatedSprite2D::is_flipped_v() const { |
418 | return vflip; |
419 | } |
420 | |
421 | void AnimatedSprite2D::_res_changed() { |
422 | set_frame_and_progress(frame, frame_progress); |
423 | queue_redraw(); |
424 | notify_property_list_changed(); |
425 | } |
426 | |
427 | bool AnimatedSprite2D::is_playing() const { |
428 | return playing; |
429 | } |
430 | |
431 | void AnimatedSprite2D::set_autoplay(const String &p_name) { |
432 | if (is_inside_tree() && !Engine::get_singleton()->is_editor_hint()) { |
433 | WARN_PRINT("Setting autoplay after the node has been added to the scene has no effect." ); |
434 | } |
435 | |
436 | autoplay = p_name; |
437 | } |
438 | |
439 | String AnimatedSprite2D::get_autoplay() const { |
440 | return autoplay; |
441 | } |
442 | |
443 | void AnimatedSprite2D::play(const StringName &p_name, float p_custom_scale, bool p_from_end) { |
444 | StringName name = p_name; |
445 | |
446 | if (name == StringName()) { |
447 | name = animation; |
448 | } |
449 | |
450 | ERR_FAIL_NULL_MSG(frames, vformat("There is no animation with name '%s'." , name)); |
451 | ERR_FAIL_COND_MSG(!frames->get_animation_names().has(name), vformat("There is no animation with name '%s'." , name)); |
452 | |
453 | if (frames->get_frame_count(name) == 0) { |
454 | return; |
455 | } |
456 | |
457 | playing = true; |
458 | custom_speed_scale = p_custom_scale; |
459 | |
460 | int end_frame = MAX(0, frames->get_frame_count(animation) - 1); |
461 | if (name != animation) { |
462 | animation = name; |
463 | if (p_from_end) { |
464 | set_frame_and_progress(end_frame, 1.0); |
465 | } else { |
466 | set_frame_and_progress(0, 0.0); |
467 | } |
468 | emit_signal("animation_changed" ); |
469 | } else { |
470 | bool is_backward = signbit(speed_scale * custom_speed_scale); |
471 | if (p_from_end && is_backward && frame == 0 && frame_progress <= 0.0) { |
472 | set_frame_and_progress(end_frame, 1.0); |
473 | } else if (!p_from_end && !is_backward && frame == end_frame && frame_progress >= 1.0) { |
474 | set_frame_and_progress(0, 0.0); |
475 | } |
476 | } |
477 | |
478 | set_process_internal(true); |
479 | notify_property_list_changed(); |
480 | queue_redraw(); |
481 | } |
482 | |
483 | void AnimatedSprite2D::play_backwards(const StringName &p_name) { |
484 | play(p_name, -1, true); |
485 | } |
486 | |
487 | void AnimatedSprite2D::_stop_internal(bool p_reset) { |
488 | playing = false; |
489 | if (p_reset) { |
490 | custom_speed_scale = 1.0; |
491 | set_frame_and_progress(0, 0.0); |
492 | } |
493 | notify_property_list_changed(); |
494 | set_process_internal(false); |
495 | } |
496 | |
497 | void AnimatedSprite2D::pause() { |
498 | _stop_internal(false); |
499 | } |
500 | |
501 | void AnimatedSprite2D::stop() { |
502 | _stop_internal(true); |
503 | } |
504 | |
505 | double AnimatedSprite2D::_get_frame_duration() { |
506 | if (frames.is_valid() && frames->has_animation(animation)) { |
507 | return frames->get_frame_duration(animation, frame); |
508 | } |
509 | return 1.0; |
510 | } |
511 | |
512 | void AnimatedSprite2D::_calc_frame_speed_scale() { |
513 | frame_speed_scale = 1.0 / _get_frame_duration(); |
514 | } |
515 | |
516 | void AnimatedSprite2D::set_animation(const StringName &p_name) { |
517 | if (animation == p_name) { |
518 | return; |
519 | } |
520 | |
521 | animation = p_name; |
522 | |
523 | emit_signal("animation_changed" ); |
524 | |
525 | if (frames == nullptr) { |
526 | animation = StringName(); |
527 | stop(); |
528 | ERR_FAIL_MSG(vformat("There is no animation with name '%s'." , p_name)); |
529 | } |
530 | |
531 | int frame_count = frames->get_frame_count(animation); |
532 | if (animation == StringName() || frame_count == 0) { |
533 | stop(); |
534 | return; |
535 | } else if (!frames->get_animation_names().has(animation)) { |
536 | animation = StringName(); |
537 | stop(); |
538 | ERR_FAIL_MSG(vformat("There is no animation with name '%s'." , p_name)); |
539 | } |
540 | |
541 | if (signbit(get_playing_speed())) { |
542 | set_frame_and_progress(frame_count - 1, 1.0); |
543 | } else { |
544 | set_frame_and_progress(0, 0.0); |
545 | } |
546 | |
547 | notify_property_list_changed(); |
548 | queue_redraw(); |
549 | } |
550 | |
551 | StringName AnimatedSprite2D::get_animation() const { |
552 | return animation; |
553 | } |
554 | |
555 | PackedStringArray AnimatedSprite2D::get_configuration_warnings() const { |
556 | PackedStringArray warnings = Node2D::get_configuration_warnings(); |
557 | if (frames.is_null()) { |
558 | warnings.push_back(RTR("A SpriteFrames resource must be created or set in the \"Frames\" property in order for AnimatedSprite2D to display frames." )); |
559 | } |
560 | return warnings; |
561 | } |
562 | |
563 | void AnimatedSprite2D::get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const { |
564 | if (p_idx == 0 && p_function == "play" && frames.is_valid()) { |
565 | List<StringName> al; |
566 | frames->get_animation_list(&al); |
567 | for (const StringName &name : al) { |
568 | r_options->push_back(String(name).quote()); |
569 | } |
570 | } |
571 | Node::get_argument_options(p_function, p_idx, r_options); |
572 | } |
573 | |
574 | #ifndef DISABLE_DEPRECATED |
575 | bool AnimatedSprite2D::_set(const StringName &p_name, const Variant &p_value) { |
576 | if ((p_name == SNAME("frames" ))) { |
577 | set_sprite_frames(p_value); |
578 | return true; |
579 | } |
580 | return false; |
581 | } |
582 | #endif |
583 | void AnimatedSprite2D::_bind_methods() { |
584 | ClassDB::bind_method(D_METHOD("set_sprite_frames" , "sprite_frames" ), &AnimatedSprite2D::set_sprite_frames); |
585 | ClassDB::bind_method(D_METHOD("get_sprite_frames" ), &AnimatedSprite2D::get_sprite_frames); |
586 | |
587 | ClassDB::bind_method(D_METHOD("set_animation" , "name" ), &AnimatedSprite2D::set_animation); |
588 | ClassDB::bind_method(D_METHOD("get_animation" ), &AnimatedSprite2D::get_animation); |
589 | |
590 | ClassDB::bind_method(D_METHOD("set_autoplay" , "name" ), &AnimatedSprite2D::set_autoplay); |
591 | ClassDB::bind_method(D_METHOD("get_autoplay" ), &AnimatedSprite2D::get_autoplay); |
592 | |
593 | ClassDB::bind_method(D_METHOD("is_playing" ), &AnimatedSprite2D::is_playing); |
594 | |
595 | ClassDB::bind_method(D_METHOD("play" , "name" , "custom_speed" , "from_end" ), &AnimatedSprite2D::play, DEFVAL(StringName()), DEFVAL(1.0), DEFVAL(false)); |
596 | ClassDB::bind_method(D_METHOD("play_backwards" , "name" ), &AnimatedSprite2D::play_backwards, DEFVAL(StringName())); |
597 | ClassDB::bind_method(D_METHOD("pause" ), &AnimatedSprite2D::pause); |
598 | ClassDB::bind_method(D_METHOD("stop" ), &AnimatedSprite2D::stop); |
599 | |
600 | ClassDB::bind_method(D_METHOD("set_centered" , "centered" ), &AnimatedSprite2D::set_centered); |
601 | ClassDB::bind_method(D_METHOD("is_centered" ), &AnimatedSprite2D::is_centered); |
602 | |
603 | ClassDB::bind_method(D_METHOD("set_offset" , "offset" ), &AnimatedSprite2D::set_offset); |
604 | ClassDB::bind_method(D_METHOD("get_offset" ), &AnimatedSprite2D::get_offset); |
605 | |
606 | ClassDB::bind_method(D_METHOD("set_flip_h" , "flip_h" ), &AnimatedSprite2D::set_flip_h); |
607 | ClassDB::bind_method(D_METHOD("is_flipped_h" ), &AnimatedSprite2D::is_flipped_h); |
608 | |
609 | ClassDB::bind_method(D_METHOD("set_flip_v" , "flip_v" ), &AnimatedSprite2D::set_flip_v); |
610 | ClassDB::bind_method(D_METHOD("is_flipped_v" ), &AnimatedSprite2D::is_flipped_v); |
611 | |
612 | ClassDB::bind_method(D_METHOD("set_frame" , "frame" ), &AnimatedSprite2D::set_frame); |
613 | ClassDB::bind_method(D_METHOD("get_frame" ), &AnimatedSprite2D::get_frame); |
614 | |
615 | ClassDB::bind_method(D_METHOD("set_frame_progress" , "progress" ), &AnimatedSprite2D::set_frame_progress); |
616 | ClassDB::bind_method(D_METHOD("get_frame_progress" ), &AnimatedSprite2D::get_frame_progress); |
617 | |
618 | ClassDB::bind_method(D_METHOD("set_frame_and_progress" , "frame" , "progress" ), &AnimatedSprite2D::set_frame_and_progress); |
619 | |
620 | ClassDB::bind_method(D_METHOD("set_speed_scale" , "speed_scale" ), &AnimatedSprite2D::set_speed_scale); |
621 | ClassDB::bind_method(D_METHOD("get_speed_scale" ), &AnimatedSprite2D::get_speed_scale); |
622 | ClassDB::bind_method(D_METHOD("get_playing_speed" ), &AnimatedSprite2D::get_playing_speed); |
623 | |
624 | ADD_SIGNAL(MethodInfo("sprite_frames_changed" )); |
625 | ADD_SIGNAL(MethodInfo("animation_changed" )); |
626 | ADD_SIGNAL(MethodInfo("frame_changed" )); |
627 | ADD_SIGNAL(MethodInfo("animation_looped" )); |
628 | ADD_SIGNAL(MethodInfo("animation_finished" )); |
629 | |
630 | ADD_GROUP("Animation" , "" ); |
631 | ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "sprite_frames" , PROPERTY_HINT_RESOURCE_TYPE, "SpriteFrames" ), "set_sprite_frames" , "get_sprite_frames" ); |
632 | ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "animation" , PROPERTY_HINT_ENUM, "" ), "set_animation" , "get_animation" ); |
633 | ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "autoplay" , PROPERTY_HINT_NONE, "" , PROPERTY_USAGE_NO_EDITOR), "set_autoplay" , "get_autoplay" ); |
634 | ADD_PROPERTY(PropertyInfo(Variant::INT, "frame" ), "set_frame" , "get_frame" ); |
635 | ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "frame_progress" , PROPERTY_HINT_NONE, "" , PROPERTY_USAGE_NO_EDITOR), "set_frame_progress" , "get_frame_progress" ); |
636 | ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "speed_scale" ), "set_speed_scale" , "get_speed_scale" ); |
637 | ADD_GROUP("Offset" , "" ); |
638 | ADD_PROPERTY(PropertyInfo(Variant::BOOL, "centered" ), "set_centered" , "is_centered" ); |
639 | ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "offset" , PROPERTY_HINT_NONE, "suffix:px" ), "set_offset" , "get_offset" ); |
640 | ADD_PROPERTY(PropertyInfo(Variant::BOOL, "flip_h" ), "set_flip_h" , "is_flipped_h" ); |
641 | ADD_PROPERTY(PropertyInfo(Variant::BOOL, "flip_v" ), "set_flip_v" , "is_flipped_v" ); |
642 | } |
643 | |
644 | AnimatedSprite2D::AnimatedSprite2D() { |
645 | } |
646 | |