diff options
Diffstat (limited to 'scene/2d/animated_sprite.cpp')
-rw-r--r-- | scene/2d/animated_sprite.cpp | 460 |
1 files changed, 413 insertions, 47 deletions
diff --git a/scene/2d/animated_sprite.cpp b/scene/2d/animated_sprite.cpp index 1ed508aed3..c062a6d1fc 100644 --- a/scene/2d/animated_sprite.cpp +++ b/scene/2d/animated_sprite.cpp @@ -29,81 +29,227 @@ #include "animated_sprite.h" #include "scene/scene_string_names.h" #include "os/os.h" +#include "scene/scene_string_names.h" -void AnimatedSprite::edit_set_pivot(const Point2& p_pivot) { - set_offset(p_pivot); -} -Point2 AnimatedSprite::edit_get_pivot() const { - return get_offset(); -} -bool AnimatedSprite::edit_has_pivot() const { +//////////////////////////// + - return true; -} +void SpriteFrames::add_frame(const StringName &p_anim, const Ref<Texture>& p_frame, int p_at_pos) { -void SpriteFrames::add_frame(const Ref<Texture>& p_frame,int p_at_pos) { + Map<StringName,Anim>::Element *E=animations.find(p_anim); + ERR_FAIL_COND(!E); - if (p_at_pos>=0 && p_at_pos<frames.size()) - frames.insert(p_at_pos,p_frame); + if (p_at_pos>=0 && p_at_pos<E->get().frames.size()) + E->get().frames.insert(p_at_pos,p_frame); else - frames.push_back(p_frame); + E->get().frames.push_back(p_frame); emit_changed(); } -int SpriteFrames::get_frame_count() const { +int SpriteFrames::get_frame_count(const StringName &p_anim) const { + const Map<StringName,Anim>::Element *E=animations.find(p_anim); + ERR_FAIL_COND_V(!E,0); - return frames.size(); + return E->get().frames.size(); } -void SpriteFrames::remove_frame(int p_idx) { +void SpriteFrames::remove_frame(const StringName &p_anim, int p_idx) { + + Map<StringName,Anim>::Element *E=animations.find(p_anim); + ERR_FAIL_COND(!E); - frames.remove(p_idx); + E->get().frames.remove(p_idx); emit_changed(); } -void SpriteFrames::clear() { +void SpriteFrames::clear(const StringName &p_anim) { - frames.clear(); + Map<StringName,Anim>::Element *E=animations.find(p_anim); + ERR_FAIL_COND(!E); + + E->get().frames.clear(); emit_changed(); } +void SpriteFrames::clear_all() { -Array SpriteFrames::_get_frames() const { + animations.clear(); + add_animation("default"); +} + + + +void SpriteFrames::add_animation(const StringName& p_anim) { + + ERR_FAIL_COND(animations.has(p_anim)); + + animations[p_anim]=Anim(); +} + +bool SpriteFrames::has_animation(const StringName& p_anim) const{ + + return animations.has(p_anim); +} +void SpriteFrames::remove_animation(const StringName& p_anim){ + + animations.erase(p_anim); +} + +void SpriteFrames::rename_animation(const StringName& p_prev,const StringName& p_next) { + + ERR_FAIL_COND(!animations.has(p_prev)); + ERR_FAIL_COND(animations.has(p_next)); + + Anim anim = animations[p_prev]; + animations.erase(p_prev); + animations[p_next]=anim; - Array arr; - arr.resize(frames.size()); - for(int i=0;i<frames.size();i++) - arr[i]=frames[i]; +} + +Vector<String> SpriteFrames::_get_animation_list() const { + + Vector<String> ret; + List<StringName> al; + get_animation_list(&al); + for(List<StringName>::Element *E=al.front();E;E=E->next()) { + + ret.push_back(E->get()); + } + + return ret; +} + +void SpriteFrames::get_animation_list(List<StringName> *r_animations) const{ + + for (const Map<StringName,Anim>::Element *E=animations.front();E;E=E->next()) { + r_animations->push_back(E->key()); + } +} + +void SpriteFrames::set_animation_speed(const StringName& p_anim,float p_fps){ + + ERR_FAIL_COND(p_fps<0); + Map<StringName,Anim>::Element *E=animations.find(p_anim); + ERR_FAIL_COND(!E); + E->get().speed=p_fps; +} +float SpriteFrames::get_animation_speed(const StringName& p_anim) const{ + + const Map<StringName,Anim>::Element *E=animations.find(p_anim); + ERR_FAIL_COND_V(!E,0); + return E->get().speed; +} + +void SpriteFrames::set_animation_loop(const StringName& p_anim,bool p_loop){ + Map<StringName,Anim>::Element *E=animations.find(p_anim); + ERR_FAIL_COND(!E); + E->get().loop=p_loop; +} +bool SpriteFrames::get_animation_loop(const StringName& p_anim) const{ + const Map<StringName,Anim>::Element *E=animations.find(p_anim); + ERR_FAIL_COND_V(!E,false); + return E->get().loop; - return arr; } void SpriteFrames::_set_frames(const Array& p_frames) { - frames.resize(p_frames.size()); - for(int i=0;i<frames.size();i++) - frames[i]=p_frames[i]; + clear_all(); + Map<StringName,Anim>::Element *E=animations.find(SceneStringNames::get_singleton()->_default); + ERR_FAIL_COND(!E); + + E->get().frames.resize(p_frames.size()); + for(int i=0;i<E->get().frames.size();i++) + E->get().frames[i]=p_frames[i]; + +} +Array SpriteFrames::_get_frames() const { + + return Array(); +} + +Array SpriteFrames::_get_animations() const { + + Array anims; + for (Map<StringName,Anim>::Element *E=animations.front();E;E=E->next()) { + Dictionary d; + d["name"]=E->key(); + d["speed"]=E->get().speed; + d["loop"]=E->get().loop; + Array frames; + for(int i=0;i<E->get().frames.size();i++) { + frames.push_back(E->get().frames[i]); + } + d["frames"]=frames; + anims.push_back(d); + } + return anims; +} +void SpriteFrames::_set_animations(const Array& p_animations) { + + animations.clear(); + for(int i=0;i<p_animations.size();i++) { + + Dictionary d=p_animations[i]; + + ERR_CONTINUE(!d.has("name")); + ERR_CONTINUE(!d.has("speed")); + ERR_CONTINUE(!d.has("loop")); + ERR_CONTINUE(!d.has("frames")); + + Anim anim; + anim.speed=d["speed"]; + anim.loop=d["loop"]; + Array frames=d["frames"]; + for(int i=0;i<frames.size();i++) { + + RES res = frames[i]; + anim.frames.push_back(res); + } + + animations[d["name"]]=anim; + + + } } void SpriteFrames::_bind_methods() { - ObjectTypeDB::bind_method(_MD("add_frame","frame","atpos"),&SpriteFrames::add_frame,DEFVAL(-1)); - ObjectTypeDB::bind_method(_MD("get_frame_count"),&SpriteFrames::get_frame_count); - ObjectTypeDB::bind_method(_MD("get_frame","idx"),&SpriteFrames::get_frame); - ObjectTypeDB::bind_method(_MD("set_frame","idx","txt"),&SpriteFrames::set_frame); - ObjectTypeDB::bind_method(_MD("remove_frame","idx"),&SpriteFrames::remove_frame); - ObjectTypeDB::bind_method(_MD("clear"),&SpriteFrames::clear); + + ObjectTypeDB::bind_method(_MD("add_animation","anim"),&SpriteFrames::add_animation); + ObjectTypeDB::bind_method(_MD("has_animation","anim"),&SpriteFrames::has_animation); + ObjectTypeDB::bind_method(_MD("remove_animation","anim"),&SpriteFrames::remove_animation); + ObjectTypeDB::bind_method(_MD("rename_animation","anim","newname"),&SpriteFrames::rename_animation); + + ObjectTypeDB::bind_method(_MD("set_animation_speed","anim","speed"),&SpriteFrames::set_animation_speed); + ObjectTypeDB::bind_method(_MD("get_animation_speed","anim"),&SpriteFrames::get_animation_speed); + + ObjectTypeDB::bind_method(_MD("set_animation_loop","anim","loop"),&SpriteFrames::set_animation_loop); + ObjectTypeDB::bind_method(_MD("get_animation_loop","anim"),&SpriteFrames::get_animation_loop); + + ObjectTypeDB::bind_method(_MD("add_frame","anim","frame","atpos"),&SpriteFrames::add_frame,DEFVAL(-1)); + ObjectTypeDB::bind_method(_MD("get_frame_count","anim"),&SpriteFrames::get_frame_count); + ObjectTypeDB::bind_method(_MD("get_frame","anim","idx"),&SpriteFrames::get_frame); + ObjectTypeDB::bind_method(_MD("set_frame","anim","idx","txt"),&SpriteFrames::set_frame); + ObjectTypeDB::bind_method(_MD("remove_frame","anim","idx"),&SpriteFrames::remove_frame); + ObjectTypeDB::bind_method(_MD("clear","anim"),&SpriteFrames::clear); + ObjectTypeDB::bind_method(_MD("clear_all"),&SpriteFrames::clear_all); ObjectTypeDB::bind_method(_MD("_set_frames"),&SpriteFrames::_set_frames); ObjectTypeDB::bind_method(_MD("_get_frames"),&SpriteFrames::_get_frames); - ADD_PROPERTYNZ( PropertyInfo(Variant::ARRAY,"frames",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("_set_frames"),_SCS("_get_frames")); + ADD_PROPERTYNZ( PropertyInfo(Variant::ARRAY,"frames",PROPERTY_HINT_NONE,"",0),_SCS("_set_frames"),_SCS("_get_frames")); //compatibility + + ObjectTypeDB::bind_method(_MD("_set_animations"),&SpriteFrames::_set_animations); + ObjectTypeDB::bind_method(_MD("_get_animations"),&SpriteFrames::_get_animations); + + ADD_PROPERTYNZ( PropertyInfo(Variant::ARRAY,"animations",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("_set_animations"),_SCS("_get_animations")); //compatibility } @@ -112,33 +258,146 @@ void SpriteFrames::_bind_methods() { SpriteFrames::SpriteFrames() { + add_animation(SceneStringNames::get_singleton()->_default); + +} + + + + + + +void AnimatedSprite::edit_set_pivot(const Point2& p_pivot) { + set_offset(p_pivot); } +Point2 AnimatedSprite::edit_get_pivot() const { + return get_offset(); +} +bool AnimatedSprite::edit_has_pivot() const { + return true; +} +void AnimatedSprite::_validate_property(PropertyInfo& property) const { + if (!frames.is_valid()) + return; + if (property.name=="animation") { -////////////////////////// + property.hint=PROPERTY_HINT_ENUM; + List<StringName> names; + frames->get_animation_list(&names); + names.sort_custom<StringName::AlphCompare>(); + bool current_found=false; + + for (List<StringName>::Element *E=names.front();E;E=E->next()) { + if (E->prev()) { + property.hint_string+=","; + } + + property.hint_string+=String(E->get()); + if (animation==E->get()) { + current_found=true; + } + } + + if (!current_found) { + if (property.hint_string==String()) { + property.hint_string=String(animation); + } else { + property.hint_string=String(animation)+","+property.hint_string; + } + } + } + + + if (property.name=="frame") { + + property.hint=PROPERTY_HINT_RANGE; + + if (frames->has_animation(animation)) { + property.hint_string="0,"+itos(frames->get_frame_count(animation)-1)+",1"; + } else { + property.hint_string="0,0,0"; + } + } + +} void AnimatedSprite::_notification(int p_what) { switch(p_what) { + case NOTIFICATION_PROCESS: { + + if (frames.is_null()) + return; + if (!frames->has_animation(animation)) + return; + if (frame<0) + return; + + float speed = frames->get_animation_speed(animation); + if (speed==0) + return; //do nothing + + float remaining = get_process_delta_time(); + + while(remaining) { + + if (timeout<=0) { + + timeout=1.0/speed; + + int fc = frames->get_frame_count(animation); + if (frame>=fc-1) { + if (frames->get_animation_loop(animation)) { + frame=0; + } else { + frame=fc-1; + } + } else { + frame++; + } + + update(); + _change_notify("frame"); + } + + float to_process = MIN(timeout,remaining); + remaining-=to_process; + timeout-=to_process; + } + } break; case NOTIFICATION_DRAW: { - if (frames.is_null()) + if (frames.is_null()) { + print_line("no draw no faemos"); return; + } - if (frame<0 || frame>=frames->get_frame_count()) + if (frame<0) { + print_line("no draw frame <0"); return; + } + + if (!frames->has_animation(animation)) { + print_line("no draw no anim: "+String(animation)); + return; + } + + - Ref<Texture> texture = frames->get_frame(frame); - if (texture.is_null()) + Ref<Texture> texture = frames->get_frame(animation,frame); + if (texture.is_null()) { + print_line("no draw texture is null"); return; + } //print_line("DECIDED TO DRAW"); @@ -184,11 +443,16 @@ void AnimatedSprite::set_sprite_frames(const Ref<SpriteFrames> &p_frames) { if (!frames.is_valid()) { frame=0; - } else { set_frame(frame); } + + + + _change_notify(); + _reset_timeout(); update(); + update_configuration_warning(); } @@ -202,19 +466,29 @@ void AnimatedSprite::set_frame(int p_frame) { if (!frames.is_valid()) { return; } - if (p_frame>=frames->get_frame_count()) - p_frame=frames->get_frame_count()-1; + + if (frames->has_animation(animation)) { + int limit = frames->get_frame_count(animation); + if (p_frame>=limit) + p_frame=limit-1; + + } + if (p_frame<0) p_frame=0; + if (frame==p_frame) return; frame=p_frame; + _reset_timeout(); update(); _change_notify("frame"); emit_signal(SceneStringNames::get_singleton()->frame_changed); + + } int AnimatedSprite::get_frame() const { @@ -281,11 +555,13 @@ Color AnimatedSprite::get_modulate() const{ Rect2 AnimatedSprite::get_item_rect() const { - if (!frames.is_valid() || !frames->get_frame_count() || frame<0 || frame>=frames->get_frame_count()) { + if (!frames.is_valid() || !frames->has_animation(animation) || frame<0 || frame>=frames->get_frame_count(animation)) { return Node2D::get_item_rect(); } - Ref<Texture> t = frames->get_frame(frame); + Ref<Texture> t; + if (animation) + t = frames->get_frame(animation,frame); if (t.is_null()) return Node2D::get_item_rect(); Size2i s = t->get_size(); @@ -303,14 +579,101 @@ Rect2 AnimatedSprite::get_item_rect() const { void AnimatedSprite::_res_changed() { set_frame(frame); + _change_notify("frame"); + _change_notify("animation"); update(); } +void AnimatedSprite::_set_playing(bool p_playing) { + + if (playing==p_playing) + return; + playing=p_playing; + _reset_timeout(); + set_process(playing); +} + +bool AnimatedSprite::_is_playing() const { + + return playing; +} + +void AnimatedSprite::play(const StringName& p_animation) { + + if (p_animation) + set_animation(p_animation); + _set_playing(true); +} + +void AnimatedSprite::stop(){ + + _set_playing(false); +} + +bool AnimatedSprite::is_playing() const { + + return is_processing(); +} + +void AnimatedSprite::_reset_timeout() { + + if (!playing) + return; + + if (frames.is_valid() && frames->has_animation(animation)) { + float speed = frames->get_animation_speed(animation); + if (speed>0) { + timeout=1.0/speed; + } else { + timeout=0; + } + } else { + timeout=0; + } + +} + +void AnimatedSprite::set_animation(const StringName& p_animation){ + + if (animation==p_animation) + return; + + animation=p_animation; + _reset_timeout(); + set_frame(0); + _change_notify(); + update(); +} +StringName AnimatedSprite::get_animation() const{ + + return animation; +} + +String AnimatedSprite::get_configuration_warning() const { + + if (frames.is_null()) { + return TTR("A SpriteFrames resource must be created or set in the 'Frames' property in order for AnimatedSprite to display frames."); + } + + return String(); +} + void AnimatedSprite::_bind_methods() { + ObjectTypeDB::bind_method(_MD("set_sprite_frames","sprite_frames:SpriteFrames"),&AnimatedSprite::set_sprite_frames); ObjectTypeDB::bind_method(_MD("get_sprite_frames:SpriteFrames"),&AnimatedSprite::get_sprite_frames); + ObjectTypeDB::bind_method(_MD("set_animation","animation"),&AnimatedSprite::set_animation); + ObjectTypeDB::bind_method(_MD("get_animation"),&AnimatedSprite::get_animation); + + ObjectTypeDB::bind_method(_MD("_set_playing","playing"),&AnimatedSprite::_set_playing); + ObjectTypeDB::bind_method(_MD("_is_playing"),&AnimatedSprite::_is_playing); + + ObjectTypeDB::bind_method(_MD("play","anim"),&AnimatedSprite::play,DEFVAL(StringName())); + ObjectTypeDB::bind_method(_MD("stop"),&AnimatedSprite::stop); + ObjectTypeDB::bind_method(_MD("is_playing"),&AnimatedSprite::is_playing); + ObjectTypeDB::bind_method(_MD("set_centered","centered"),&AnimatedSprite::set_centered); ObjectTypeDB::bind_method(_MD("is_centered"),&AnimatedSprite::is_centered); @@ -335,7 +698,9 @@ void AnimatedSprite::_bind_methods() { ADD_SIGNAL(MethodInfo("frame_changed")); ADD_PROPERTYNZ( PropertyInfo( Variant::OBJECT, "frames",PROPERTY_HINT_RESOURCE_TYPE,"SpriteFrames"), _SCS("set_sprite_frames"),_SCS("get_sprite_frames")); + ADD_PROPERTY( PropertyInfo( Variant::STRING, "animation"), _SCS("set_animation"),_SCS("get_animation")); ADD_PROPERTYNZ( PropertyInfo( Variant::INT, "frame",PROPERTY_HINT_SPRITE_FRAME), _SCS("set_frame"),_SCS("get_frame")); + ADD_PROPERTYNZ( PropertyInfo( Variant::BOOL, "playing"), _SCS("_set_playing"),_SCS("_is_playing")); ADD_PROPERTYNO( PropertyInfo( Variant::BOOL, "centered"), _SCS("set_centered"),_SCS("is_centered")); ADD_PROPERTYNZ( PropertyInfo( Variant::VECTOR2, "offset"), _SCS("set_offset"),_SCS("get_offset")); ADD_PROPERTYNZ( PropertyInfo( Variant::BOOL, "flip_h"), _SCS("set_flip_h"),_SCS("is_flipped_h")); @@ -351,9 +716,10 @@ AnimatedSprite::AnimatedSprite() { vflip=false; frame=0; - - + playing=false; + animation="default"; modulate=Color(1,1,1,1); + timeout=0; } |