diff options
30 files changed, 2020 insertions, 424 deletions
diff --git a/core/object.cpp b/core/object.cpp index 7bdec06c1b..ee4b5e288c 100644 --- a/core/object.cpp +++ b/core/object.cpp @@ -463,6 +463,11 @@ void Object::get_property_list(List<PropertyInfo> *p_list,bool p_reversed) const } } + +void Object::_validate_property(PropertyInfo& property) const { + +} + void Object::get_method_list(List<MethodInfo> *p_list) const { ObjectTypeDB::get_method_list(get_type_name(),p_list); diff --git a/core/object.h b/core/object.h index dcebf9b2a2..c34440100f 100644 --- a/core/object.h +++ b/core/object.h @@ -274,12 +274,12 @@ virtual void _get_property_listv(List<PropertyInfo> *p_list,bool p_reversed) con }\ p_list->push_back( PropertyInfo(Variant::NIL,get_type_static(),PROPERTY_HINT_NONE,String(),PROPERTY_USAGE_CATEGORY));\ if (!_is_gpl_reversed())\ - ObjectTypeDB::get_property_list(#m_type,p_list,true);\ + ObjectTypeDB::get_property_list(#m_type,p_list,true,this);\ if (m_type::_get_get_property_list() != m_inherits::_get_get_property_list()) {\ _get_property_list(p_list);\ }\ if (_is_gpl_reversed())\ - ObjectTypeDB::get_property_list(#m_type,p_list,true);\ + ObjectTypeDB::get_property_list(#m_type,p_list,true,this);\ if (p_reversed) {\ m_inherits::_get_property_listv(p_list,p_reversed);\ }\ @@ -462,6 +462,9 @@ protected: void _clear_internal_resource_paths(const Variant &p_var); +friend class ObjectTypeDB; + virtual void _validate_property(PropertyInfo& property) const; + public: //should be protected, but bug in clang++ static void initialize_type(); _FORCE_INLINE_ static void register_custom_data_to_otdb() {}; diff --git a/core/object_type_db.cpp b/core/object_type_db.cpp index 14b595d61b..5f97df39a6 100644 --- a/core/object_type_db.cpp +++ b/core/object_type_db.cpp @@ -619,14 +619,22 @@ void ObjectTypeDB::add_property(StringName p_type,const PropertyInfo& p_pinfo, c } -void ObjectTypeDB::get_property_list(StringName p_type,List<PropertyInfo> *p_list,bool p_no_inheritance) { +void ObjectTypeDB::get_property_list(StringName p_type, List<PropertyInfo> *p_list, bool p_no_inheritance,const Object *p_validator) { TypeInfo *type=types.getptr(p_type); TypeInfo *check=type; while(check) { for(List<PropertyInfo>::Element *E=type->property_list.front();E;E=E->next()) { - p_list->push_back(E->get()); + + + if (p_validator) { + PropertyInfo pi = E->get(); + p_validator->_validate_property(pi); + p_list->push_back(pi); + } else { + p_list->push_back(E->get()); + } } if (p_no_inheritance) diff --git a/core/object_type_db.h b/core/object_type_db.h index a4896fff81..8313091acd 100644 --- a/core/object_type_db.h +++ b/core/object_type_db.h @@ -456,7 +456,7 @@ public: static void get_signal_list(StringName p_type,List<MethodInfo> *p_signals,bool p_no_inheritance=false); static void add_property(StringName p_type,const PropertyInfo& p_pinfo, const StringName& p_setter, const StringName& p_getter, int p_index=-1); - static void get_property_list(StringName p_type,List<PropertyInfo> *p_list,bool p_no_inheritance=false); + static void get_property_list(StringName p_type, List<PropertyInfo> *p_list, bool p_no_inheritance=false, const Object *p_validator=NULL); static bool set_property(Object* p_object, const StringName& p_property, const Variant& p_value, bool *r_valid=NULL); static bool get_property(Object* p_object,const StringName& p_property, Variant& r_value); static Variant::Type get_property_type(const StringName& p_type, const StringName& p_property,bool *r_is_valid=NULL); diff --git a/scene/2d/animated_sprite.cpp b/scene/2d/animated_sprite.cpp index 1ed508aed3..f482f775c4 100644 --- a/scene/2d/animated_sprite.cpp +++ b/scene/2d/animated_sprite.cpp @@ -29,81 +29,229 @@ #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) { - frames.remove(p_idx); + Map<StringName,Anim>::Element *E=animations.find(p_anim); + ERR_FAIL_COND(!E); + + E->get().frames.remove(p_idx); emit_changed(); } -void SpriteFrames::clear() { +void SpriteFrames::clear(const StringName &p_anim) { + + Map<StringName,Anim>::Element *E=animations.find(p_anim); + ERR_FAIL_COND(!E); - frames.clear(); + 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; + +} + +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{ - Array arr; - arr.resize(frames.size()); - for(int i=0;i<frames.size();i++) - arr[i]=frames[i]; + 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_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","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_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,6 +260,7 @@ void SpriteFrames::_bind_methods() { SpriteFrames::SpriteFrames() { + add_animation(SceneStringNames::get_singleton()->_default); } @@ -120,25 +269,137 @@ SpriteFrames::SpriteFrames() { +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) { + print_line("no draw frame <0"); return; + } - if (frame<0 || frame>=frames->get_frame_count()) + 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,10 +445,14 @@ 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(); } @@ -202,15 +467,23 @@ 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); @@ -281,11 +554,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 +578,92 @@ 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; +} + 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 +688,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 +706,10 @@ AnimatedSprite::AnimatedSprite() { vflip=false; frame=0; - - + playing=false; + animation="default"; modulate=Color(1,1,1,1); + timeout=0; } diff --git a/scene/2d/animated_sprite.h b/scene/2d/animated_sprite.h index da4f1b99af..bbf9c7aafb 100644 --- a/scene/2d/animated_sprite.h +++ b/scene/2d/animated_sprite.h @@ -37,23 +37,69 @@ class SpriteFrames : public Resource { OBJ_TYPE(SpriteFrames,Resource); - Vector< Ref<Texture> > frames; + struct Anim { + + float speed; + bool loop; + Vector< Ref<Texture> > frames; + + Anim() { loop=true; speed=5; } + }; + + Map<StringName,Anim> animations; Array _get_frames() const; void _set_frames(const Array& p_frames); + + Array _get_animations() const; + void _set_animations(const Array& p_animations); + + Vector<String> _get_animation_list() const; + protected: static void _bind_methods(); public: + void add_animation(const StringName& p_anim); + bool has_animation(const StringName& p_anim) const; + void remove_animation(const StringName& p_anim); + void rename_animation(const StringName& p_prev,const StringName& p_next); + + void get_animation_list(List<StringName> *r_animations) const; + + void set_animation_speed(const StringName& p_anim,float p_fps); + float get_animation_speed(const StringName& p_anim) const; + + void set_animation_loop(const StringName& p_anim,bool p_loop); + bool get_animation_loop(const StringName& p_anim) const; + + void add_frame(const StringName& p_anim,const Ref<Texture>& p_frame,int p_at_pos=-1); + int get_frame_count(const StringName& p_anim) const; + _FORCE_INLINE_ Ref<Texture> get_frame(const StringName& p_anim,int p_idx) const { + + const Map<StringName,Anim>::Element *E=animations.find(p_anim); + ERR_FAIL_COND_V(!E,Ref<Texture>()); + ERR_FAIL_COND_V(p_idx<0,Ref<Texture>()); + if (p_idx>=E->get().frames.size()) + return Ref<Texture>(); + + return E->get().frames[p_idx]; + } + + void set_frame(const StringName& p_anim,int p_idx,const Ref<Texture>& p_frame){ + Map<StringName,Anim>::Element *E=animations.find(p_anim); + ERR_FAIL_COND(!E); + ERR_FAIL_COND(p_idx<0); + if (p_idx>=E->get().frames.size()) + return; + E->get().frames[p_idx]=p_frame; + } + void remove_frame(const StringName& p_anim,int p_idx); + void clear(const StringName& p_anim); + void clear_all(); - void add_frame(const Ref<Texture>& p_frame,int p_at_pos=-1); - int get_frame_count() const; - _FORCE_INLINE_ Ref<Texture> get_frame(int p_idx) const { ERR_FAIL_INDEX_V(p_idx,frames.size(),Ref<Texture>()); return frames[p_idx]; } - void set_frame(int p_idx,const Ref<Texture>& p_frame){ ERR_FAIL_INDEX(p_idx,frames.size()); frames[p_idx]=p_frame; } - void remove_frame(int p_idx); - void clear(); SpriteFrames(); @@ -66,21 +112,32 @@ class AnimatedSprite : public Node2D { OBJ_TYPE(AnimatedSprite,Node2D); Ref<SpriteFrames> frames; + bool playing; + StringName animation; int frame; bool centered; Point2 offset; + float timeout; + bool hflip; bool vflip; Color modulate; void _res_changed(); + + void _reset_timeout(); + void _set_playing(bool p_playing); + bool _is_playing() const; + + protected: static void _bind_methods(); void _notification(int p_what); + virtual void _validate_property(PropertyInfo& property) const; public: @@ -92,6 +149,13 @@ public: void set_sprite_frames(const Ref<SpriteFrames> &p_frames); Ref<SpriteFrames> get_sprite_frames() const; + void play(const StringName& p_animation=StringName()); + void stop(); + bool is_playing() const; + + void set_animation(const StringName& p_animation); + StringName get_animation() const; + void set_frame(int p_frame); int get_frame() const; @@ -116,4 +180,5 @@ public: AnimatedSprite(); }; + #endif // ANIMATED_SPRITE_H diff --git a/scene/2d/visibility_notifier_2d.cpp b/scene/2d/visibility_notifier_2d.cpp index 60fa7f69c8..426e86fa13 100644 --- a/scene/2d/visibility_notifier_2d.cpp +++ b/scene/2d/visibility_notifier_2d.cpp @@ -30,6 +30,7 @@ #include "scene/scene_string_names.h" #include "scene/2d/physics_body_2d.h" +#include "scene/2d/animated_sprite.h" #include "scene/animation/animation_player.h" #include "scene/scene_string_names.h" #include "particles_2d.h" @@ -204,6 +205,16 @@ void VisibilityEnabler2D::_find_nodes(Node* p_node) { } + if (enabler[ENABLER_PAUSE_ANIMATED_SPRITES]) { + + AnimatedSprite *as = p_node->cast_to<AnimatedSprite>(); + if (as) { + add=true; + } + + } + + if (enabler[ENABLER_PAUSE_PARTICLES]) { Particles2D *ps = p_node->cast_to<Particles2D>(); @@ -301,6 +312,17 @@ void VisibilityEnabler2D::_change_node_state(Node* p_node,bool p_enabled) { ap->set_active(p_enabled); } } + { + AnimatedSprite *as=p_node->cast_to<AnimatedSprite>(); + + if (as) { + + if (p_enabled) + as->play(); + else + as->stop(); + } + } { Particles2D *ps=p_node->cast_to<Particles2D>(); @@ -333,12 +355,14 @@ void VisibilityEnabler2D::_bind_methods(){ ADD_PROPERTYI( PropertyInfo(Variant::BOOL,"enabler/pause_animations"),_SCS("set_enabler"),_SCS("is_enabler_enabled"), ENABLER_PAUSE_ANIMATIONS ); ADD_PROPERTYI( PropertyInfo(Variant::BOOL,"enabler/freeze_bodies"),_SCS("set_enabler"),_SCS("is_enabler_enabled"), ENABLER_FREEZE_BODIES); ADD_PROPERTYI( PropertyInfo(Variant::BOOL,"enabler/pause_particles"),_SCS("set_enabler"),_SCS("is_enabler_enabled"), ENABLER_PAUSE_PARTICLES); + ADD_PROPERTYI( PropertyInfo(Variant::BOOL,"enabler/pause_animated_sprites"),_SCS("set_enabler"),_SCS("is_enabler_enabled"), ENABLER_PAUSE_ANIMATED_SPRITES); ADD_PROPERTYI( PropertyInfo(Variant::BOOL,"enabler/process_parent"),_SCS("set_enabler"),_SCS("is_enabler_enabled"), ENABLER_PARENT_PROCESS); ADD_PROPERTYI( PropertyInfo(Variant::BOOL,"enabler/fixed_process_parent"),_SCS("set_enabler"),_SCS("is_enabler_enabled"), ENABLER_PARENT_FIXED_PROCESS); BIND_CONSTANT( ENABLER_FREEZE_BODIES ); BIND_CONSTANT( ENABLER_PAUSE_ANIMATIONS ); BIND_CONSTANT( ENABLER_PAUSE_PARTICLES ); + BIND_CONSTANT( ENABLER_PAUSE_ANIMATED_SPRITES ); BIND_CONSTANT( ENABLER_PARENT_PROCESS ); BIND_CONSTANT( ENABLER_PARENT_FIXED_PROCESS ); BIND_CONSTANT( ENABLER_MAX); diff --git a/scene/2d/visibility_notifier_2d.h b/scene/2d/visibility_notifier_2d.h index 6ec24fd4d0..647a5b6e91 100644 --- a/scene/2d/visibility_notifier_2d.h +++ b/scene/2d/visibility_notifier_2d.h @@ -76,6 +76,7 @@ public: ENABLER_PAUSE_PARTICLES, ENABLER_PARENT_PROCESS, ENABLER_PARENT_FIXED_PROCESS, + ENABLER_PAUSE_ANIMATED_SPRITES, ENABLER_MAX }; diff --git a/scene/3d/sprite_3d.cpp b/scene/3d/sprite_3d.cpp index c7d1249a07..da83e9b6d2 100644 --- a/scene/3d/sprite_3d.cpp +++ b/scene/3d/sprite_3d.cpp @@ -606,11 +606,11 @@ void AnimatedSprite3D::_draw() { RID immediate = get_immediate(); VS::get_singleton()->immediate_clear(immediate); - if (!frames.is_valid() || !frames->get_frame_count() || frame<0 || frame>=frames->get_frame_count()) { + if (!frames.is_valid() || !frames->get_frame_count(animation) || frame<0 || frame>=frames->get_frame_count(animation)) { return; } - Ref<Texture> texture = frames->get_frame(frame); + Ref<Texture> texture = frames->get_frame(animation,frame); if (!texture.is_valid()) return; //no texuture no life Vector2 tsize = texture->get_size(); @@ -748,7 +748,7 @@ void AnimatedSprite3D::set_sprite_frames(const Ref<SpriteFrames>& p_sprite_frame if (frames.is_valid()) frames->connect("changed",this,"_queue_update"); - if (!frames.is_valid() || frame >=frames->get_frame_count()) { + if (!frames.is_valid() || frame >=frames->get_frame_count(animation)) { frame=0; } @@ -766,7 +766,7 @@ void AnimatedSprite3D::set_frame(int p_frame){ if (frames.is_null()) return; - ERR_FAIL_INDEX(p_frame,frames->get_frame_count()); + ERR_FAIL_INDEX(p_frame,frames->get_frame_count(animation)); if (frame==p_frame) return; @@ -783,11 +783,11 @@ int AnimatedSprite3D::get_frame() const{ Rect2 AnimatedSprite3D::get_item_rect() const { - if (!frames.is_valid() || !frames->get_frame_count() || frame<0 || frame>=frames->get_frame_count()) { + if (!frames.is_valid() || !frames->get_frame_count(animation) || frame<0 || frame>=frames->get_frame_count(animation)) { return Rect2(0,0,1,1); } - Ref<Texture> t = frames->get_frame(frame); + Ref<Texture> t = frames->get_frame(animation,frame); if (t.is_null()) return Rect2(0,0,1,1); Size2i s = t->get_size(); @@ -806,6 +806,8 @@ Rect2 AnimatedSprite3D::get_item_rect() const { AnimatedSprite3D::AnimatedSprite3D() { + animation="current"; frame=0; } + diff --git a/scene/3d/sprite_3d.h b/scene/3d/sprite_3d.h index fe8e1f6ebf..d8e589556c 100644 --- a/scene/3d/sprite_3d.h +++ b/scene/3d/sprite_3d.h @@ -158,12 +158,14 @@ public: // ~Sprite3D(); }; + class AnimatedSprite3D : public SpriteBase3D { OBJ_TYPE(AnimatedSprite3D,SpriteBase3D); Ref<SpriteFrames> frames; + StringName animation; int frame; protected: @@ -186,6 +188,7 @@ public: // ~AnimatedSprite3D(); }; + VARIANT_ENUM_CAST(SpriteBase3D::DrawFlags); VARIANT_ENUM_CAST(SpriteBase3D::AlphaCutMode); #endif // SPRITE_3D_H diff --git a/scene/gui/item_list.cpp b/scene/gui/item_list.cpp index bf66a770d3..c1a0e43e49 100644 --- a/scene/gui/item_list.cpp +++ b/scene/gui/item_list.cpp @@ -383,6 +383,17 @@ Size2 ItemList::get_min_icon_size() const { return min_icon_size; } + +void ItemList::set_max_icon_size(const Size2& p_size) { + + max_icon_size=p_size; + update(); +} + +Size2 ItemList::get_max_icon_size() const { + + return max_icon_size; +} Size2 ItemList::Item::get_icon_size() const { if (icon.is_null()) @@ -399,16 +410,18 @@ void ItemList::_input_event(const InputEvent& p_event) { defer_select_single=-1; return; } + if (defer_select_single>=0 && p_event.type==InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index==BUTTON_LEFT && !p_event.mouse_button.pressed) { select(defer_select_single,true); + emit_signal("multi_selected",defer_select_single,true); defer_select_single=-1; return; } - if (p_event.type==InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index==BUTTON_LEFT && p_event.mouse_button.pressed) { + if (p_event.type==InputEvent::MOUSE_BUTTON && (p_event.mouse_button.button_index==BUTTON_LEFT || (allow_rmb_select && p_event.mouse_button.button_index==BUTTON_RIGHT)) && p_event.mouse_button.pressed) { const InputEventMouseButton &mb = p_event.mouse_button; @@ -447,6 +460,7 @@ void ItemList::_input_event(const InputEvent& p_event) { if (select_mode==SELECT_MULTI && items[i].selected && mb.mod.command) { unselect(i); emit_signal("multi_selected",i,false); + } else if (select_mode==SELECT_MULTI && mb.mod.shift && current>=0 && current<items.size() && current!=i) { int from = current; @@ -460,29 +474,45 @@ void ItemList::_input_event(const InputEvent& p_event) { if (selected) emit_signal("multi_selected",i,true); } + + if (p_event.mouse_button.button_index==BUTTON_RIGHT) { + + emit_signal("item_rmb_selected",i,Vector2(mb.x,mb.y)); + } } else { - if (!mb.doubleclick && !mb.mod.command && select_mode==SELECT_MULTI && items[i].selectable && items[i].selected) { + if (!mb.doubleclick && !mb.mod.command && select_mode==SELECT_MULTI && items[i].selectable && items[i].selected && p_event.mouse_button.button_index==BUTTON_LEFT) { defer_select_single=i; return; } - bool selected = !items[i].selected; - select(i,select_mode==SELECT_SINGLE || !mb.mod.command); - if (selected) { - if (select_mode==SELECT_SINGLE) { - emit_signal("item_selected",i); - } else - emit_signal("multi_selected",i,true); - } + if (items[i].selected && p_event.mouse_button.button_index==BUTTON_RIGHT) { - if (/*select_mode==SELECT_SINGLE &&*/ mb.doubleclick) { + emit_signal("item_rmb_selected",i,Vector2(mb.x,mb.y)); + } else { + bool selected = !items[i].selected; - emit_signal("item_activated",i); - } + select(i,select_mode==SELECT_SINGLE || !mb.mod.command); + + if (selected) { + if (select_mode==SELECT_SINGLE) { + emit_signal("item_selected",i); + } else + emit_signal("multi_selected",i,true); + + + } + + if (p_event.mouse_button.button_index==BUTTON_RIGHT) { + emit_signal("item_rmb_selected",i,Vector2(mb.x,mb.y)); + } else if (/*select_mode==SELECT_SINGLE &&*/ mb.doubleclick) { + emit_signal("item_activated",i); + + } + } } @@ -690,6 +720,55 @@ void ItemList::ensure_current_is_visible() { update(); } +static Size2 _adjust_to_max_size(Size2 p_size, Size2 p_max_size) { + + if (p_max_size.x<=0) + p_max_size.x=1e20; + if (p_max_size.y<=0) + p_max_size.y=1e20; + + + Size2 new_size; + + if (p_size.x > p_max_size.x) { + + new_size.width=p_max_size.x; + new_size.height=p_size.height * p_max_size.width / p_size.width; + + if (new_size.height > p_max_size.height) { + new_size=Size2(); //invalid + } + } + + + if (p_size.y > p_max_size.y) { + + Size2 new_size2; + new_size2.height=p_max_size.y; + new_size2.width=p_size.width * p_max_size.height / p_size.height; + + if (new_size2.width < p_max_size.width) { + + if (new_size!=Size2()) { + + if (new_size2.x*new_size2.y > new_size.x*new_size.y) { + new_size=new_size2; + } + } else { + new_size=new_size2; + } + } + + } + + if (new_size==Size2()) + return p_size; + else + return new_size; + + +} + void ItemList::_notification(int p_what) { if (p_what==NOTIFICATION_RESIZED) { @@ -752,12 +831,7 @@ void ItemList::_notification(int p_what) { Size2 minsize; if (items[i].icon.is_valid()) { - minsize=items[i].get_icon_size(); - - if (min_icon_size.x!=0) - minsize.x = MAX(minsize.x,min_icon_size.x); - if (min_icon_size.y!=0) - minsize.y = MAX(minsize.y,min_icon_size.y); + minsize=_adjust_to_max_size(items[i].get_icon_size(),max_icon_size); if (items[i].text!="") { if (icon_mode==ICON_MODE_TOP) { @@ -902,7 +976,7 @@ void ItemList::_notification(int p_what) { Vector2 text_ofs; if (items[i].icon.is_valid()) { - Size2 icon_size = items[i].get_icon_size(); + Size2 icon_size = _adjust_to_max_size(items[i].get_icon_size(),max_icon_size); Vector2 icon_ofs; if (min_icon_size!=Vector2()) { @@ -922,7 +996,7 @@ void ItemList::_notification(int p_what) { } if (items[i].icon_region.has_no_area()) - draw_texture(items[i].icon, pos); + draw_texture_rect(items[i].icon, Rect2(pos,icon_size) ); else draw_texture_rect_region(items[i].icon, Rect2(pos, icon_size), items[i].icon_region); @@ -1044,7 +1118,7 @@ void ItemList::_scroll_changed(double) { update(); } -int ItemList::get_item_at_pos(const Point2& p_pos) const { +int ItemList::get_item_at_pos(const Point2& p_pos, bool p_exact) const { Vector2 pos=p_pos; Ref<StyleBox> bg = get_stylebox("bg"); @@ -1067,7 +1141,7 @@ int ItemList::get_item_at_pos(const Point2& p_pos) const { } float dist = rc.distance_to(pos); - if (dist<closest_dist) { + if (!p_exact && dist<closest_dist) { closest=i; closest_dist=dist; } @@ -1117,6 +1191,16 @@ int ItemList::find_metadata(const Variant& p_metadata) const { } + +void ItemList::set_allow_rmb_select(bool p_allow) { + allow_rmb_select=p_allow; +} + +bool ItemList::get_allow_rmb_select() const { + + return allow_rmb_select; +} + void ItemList::_bind_methods(){ ObjectTypeDB::bind_method(_MD("add_item","text","icon:Texture","selectable"),&ItemList::add_item,DEFVAL(Variant()),DEFVAL(true)); @@ -1174,7 +1258,13 @@ void ItemList::_bind_methods(){ ObjectTypeDB::bind_method(_MD("set_min_icon_size","size"),&ItemList::set_min_icon_size); ObjectTypeDB::bind_method(_MD("get_min_icon_size"),&ItemList::get_min_icon_size); - ObjectTypeDB::bind_method(_MD("get_item_at_pos","pos"),&ItemList::get_item_at_pos); + ObjectTypeDB::bind_method(_MD("set_max_icon_size","size"),&ItemList::set_max_icon_size); + ObjectTypeDB::bind_method(_MD("get_max_icon_size"),&ItemList::get_max_icon_size); + + ObjectTypeDB::bind_method(_MD("set_allow_rmb_select","allow"),&ItemList::set_allow_rmb_select); + ObjectTypeDB::bind_method(_MD("get_allow_rmb_select"),&ItemList::get_allow_rmb_select); + + ObjectTypeDB::bind_method(_MD("get_item_at_pos","pos","exact"),&ItemList::get_item_at_pos,DEFVAL(false)); ObjectTypeDB::bind_method(_MD("ensure_current_is_visible"),&ItemList::ensure_current_is_visible); @@ -1187,6 +1277,7 @@ void ItemList::_bind_methods(){ BIND_CONSTANT( SELECT_MULTI ); ADD_SIGNAL( MethodInfo("item_selected",PropertyInfo(Variant::INT,"index"))); + ADD_SIGNAL( MethodInfo("item_rmb_selected",PropertyInfo(Variant::INT,"index"),PropertyInfo(Variant::VECTOR2,"atpos"))); ADD_SIGNAL( MethodInfo("multi_selected",PropertyInfo(Variant::INT,"index"),PropertyInfo(Variant::BOOL,"selected"))); ADD_SIGNAL( MethodInfo("item_activated",PropertyInfo(Variant::INT,"index"))); } @@ -1215,6 +1306,7 @@ ItemList::ItemList() { search_time_msec=0; ensure_selected_visible=false; defer_select_single=-1; + allow_rmb_select=false; } diff --git a/scene/gui/item_list.h b/scene/gui/item_list.h index fcb4dfae5a..59fa1d8270 100644 --- a/scene/gui/item_list.h +++ b/scene/gui/item_list.h @@ -60,9 +60,11 @@ private: int max_text_lines; int max_columns; Size2 min_icon_size; - + Size2 max_icon_size; int defer_select_single; + bool allow_rmb_select; + void _scroll_changed(double); void _input_event(const InputEvent& p_event); protected: @@ -134,13 +136,19 @@ public: void set_min_icon_size(const Size2& p_size); Size2 get_min_icon_size() const; + void set_max_icon_size(const Size2& p_size); + Size2 get_max_icon_size() const; + + void set_allow_rmb_select(bool p_allow); + bool get_allow_rmb_select() const; + void ensure_current_is_visible(); void sort_items_by_text(); int find_metadata(const Variant& p_metadata) const; virtual String get_tooltip(const Point2& p_pos) const; - int get_item_at_pos(const Point2& p_pos) const; + int get_item_at_pos(const Point2& p_pos,bool p_exact=false) const; ItemList(); ~ItemList(); diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp index 062a377cee..9c70785408 100644 --- a/scene/gui/tree.cpp +++ b/scene/gui/tree.cpp @@ -1563,10 +1563,10 @@ int Tree::propagate_mouse_event(const Point2i &p_pos,int x_ofs,int y_ofs,bool p_ col_width-=w+cache.button_margin; } - if (p_button==BUTTON_LEFT) { + if (p_button==BUTTON_LEFT || (p_button==BUTTON_RIGHT && allow_rmb_select)) { /* process selection */ - if (p_doubleclick && (!c.editable || c.mode==TreeItem::CELL_MODE_CUSTOM || c.mode==TreeItem::CELL_MODE_ICON || c.mode==TreeItem::CELL_MODE_CHECK)) { + if (p_doubleclick && (!c.editable || c.mode==TreeItem::CELL_MODE_CUSTOM || c.mode==TreeItem::CELL_MODE_ICON /*|| c.mode==TreeItem::CELL_MODE_CHECK*/)) { //it' s confusing for check emit_signal("item_activated"); return -1; @@ -1574,10 +1574,13 @@ int Tree::propagate_mouse_event(const Point2i &p_pos,int x_ofs,int y_ofs,bool p_ if (select_mode==SELECT_MULTI && p_mod.command && c.selectable) { - if (!c.selected) { + if (!c.selected || p_button==BUTTON_RIGHT) { p_item->select(col); emit_signal("multi_selected",p_item,col,true); + if (p_button==BUTTON_RIGHT) { + emit_signal("item_rmb_selected",get_local_mouse_pos()); + } //p_item->selected_signal.call(col); @@ -1597,15 +1600,25 @@ int Tree::propagate_mouse_event(const Point2i &p_pos,int x_ofs,int y_ofs,bool p_ bool inrange=false; select_single_item( p_item, root, col,selected_item,&inrange ); + if (p_button==BUTTON_RIGHT) { + emit_signal("item_rmb_selected",get_local_mouse_pos()); + } } else { int icount = _count_selected_items(root); - if (select_mode==SELECT_MULTI && icount>1) { + if (select_mode==SELECT_MULTI && icount>1 && p_button!=BUTTON_RIGHT) { single_select_defer=p_item; single_select_defer_column=col; } else { - select_single_item( p_item, root, col ); + + if (p_button!=BUTTON_RIGHT || !c.selected) { + select_single_item( p_item, root, col ); + } + + if (p_button==BUTTON_RIGHT) { + emit_signal("item_rmb_selected",get_local_mouse_pos()); + } } } @@ -1626,7 +1639,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos,int x_ofs,int y_ofs,bool p_ /* editing */ - bool bring_up_editor=c.selected;// && already_selected; + bool bring_up_editor=force_select_on_already_selected ? (c.selected && already_selected) : c.selected; bool bring_up_value_editor=false; String editor_text=c.text; @@ -2348,12 +2361,13 @@ void Tree::_input_event(InputEvent p_event) { } switch(b.button_index) { + case BUTTON_RIGHT: case BUTTON_LEFT: { Ref<StyleBox> bg = cache.bg; Point2 pos = Point2(b.x,b.y) - bg->get_offset(); cache.click_type=Cache::CLICK_NONE; - if (show_column_titles) { + if (show_column_titles && b.button_index==BUTTON_LEFT) { pos.y-=_get_title_button_height(); if (pos.y<0) { @@ -2390,6 +2404,9 @@ void Tree::_input_event(InputEvent p_event) { } + if (b.button_index==BUTTON_RIGHT) + break; + if (drag_touching) { set_fixed_process(false); drag_touching_deaccel=false; @@ -3455,6 +3472,27 @@ int Tree::get_drop_mode_flags() const { return drop_mode_flags; } +void Tree::set_single_select_cell_editing_only_when_already_selected(bool p_enable) { + + force_select_on_already_selected=p_enable; +} + +bool Tree::get_single_select_cell_editing_only_when_already_selected() const { + + return force_select_on_already_selected; +} + + +void Tree::set_allow_rmb_select(bool p_allow) { + + allow_rmb_select=p_allow; +} + +bool Tree::get_allow_rmb_select() const{ + + return allow_rmb_select; +} + void Tree::_bind_methods() { ObjectTypeDB::bind_method(_MD("_range_click_timeout"),&Tree::_range_click_timeout); @@ -3505,8 +3543,15 @@ void Tree::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_drop_mode_flags","flags"),&Tree::set_drop_mode_flags); ObjectTypeDB::bind_method(_MD("get_drop_mode_flags"),&Tree::get_drop_mode_flags); + ObjectTypeDB::bind_method(_MD("set_allow_rmb_select","allow"),&Tree::set_allow_rmb_select); + ObjectTypeDB::bind_method(_MD("get_allow_rmb_select"),&Tree::get_allow_rmb_select); + + + ObjectTypeDB::bind_method(_MD("set_single_select_cell_editing_only_when_already_selected","enable"),&Tree::set_single_select_cell_editing_only_when_already_selected); + ObjectTypeDB::bind_method(_MD("get_single_select_cell_editing_only_when_already_selected"),&Tree::get_single_select_cell_editing_only_when_already_selected); ADD_SIGNAL( MethodInfo("item_selected")); + ADD_SIGNAL( MethodInfo("item_rmb_selected",PropertyInfo(Variant::VECTOR2,"pos"))); ADD_SIGNAL( MethodInfo("cell_selected")); ADD_SIGNAL( MethodInfo("multi_selected",PropertyInfo(Variant::OBJECT,"item"),PropertyInfo(Variant::INT,"column"),PropertyInfo(Variant::BOOL,"selected")) ); ADD_SIGNAL( MethodInfo("item_edited")); @@ -3610,6 +3655,9 @@ Tree::Tree() { drop_mode_over=NULL; drop_mode_section=0; single_select_defer=NULL; + force_select_on_already_selected=false; + + allow_rmb_select=false; } diff --git a/scene/gui/tree.h b/scene/gui/tree.h index 43a913392e..1dad26dffe 100644 --- a/scene/gui/tree.h +++ b/scene/gui/tree.h @@ -438,6 +438,9 @@ friend class TreeItem; bool drag_touching; bool drag_touching_deaccel; bool click_handled; + bool allow_rmb_select; + + bool force_select_on_already_selected; bool hide_folding; @@ -514,6 +517,12 @@ public: void set_drop_mode_flags(int p_flags); int get_drop_mode_flags() const; + void set_single_select_cell_editing_only_when_already_selected(bool p_enable); + bool get_single_select_cell_editing_only_when_already_selected() const; + + void set_allow_rmb_select(bool p_allow); + bool get_allow_rmb_select() const; + void set_value_evaluator(ValueEvaluator *p_evaluator); Tree(); diff --git a/scene/scene_string_names.cpp b/scene/scene_string_names.cpp index 28834c732d..af28feb63d 100644 --- a/scene/scene_string_names.cpp +++ b/scene/scene_string_names.cpp @@ -172,4 +172,6 @@ SceneStringNames::SceneStringNames() { speed=StaticCString::create("speed"); path_pp=NodePath(".."); + + _default=StaticCString::create("default"); } diff --git a/scene/scene_string_names.h b/scene/scene_string_names.h index f85a858423..da5e45172b 100644 --- a/scene/scene_string_names.h +++ b/scene/scene_string_names.h @@ -182,6 +182,7 @@ public: NodePath path_pp; + StringName _default; }; diff --git a/tools/editor/editor_node.cpp b/tools/editor/editor_node.cpp index c9cec3b7f4..bbd2464992 100644 --- a/tools/editor/editor_node.cpp +++ b/tools/editor/editor_node.cpp @@ -2057,8 +2057,9 @@ void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) { case FILE_QUICK_OPEN_FILE: { - quick_open->popup("Resource", false, true); - quick_open->set_title(TTR("Quick Search File..")); + //quick_open->popup("Resource", false, true); + //quick_open->set_title(TTR("Quick Search File..")); + scenes_dock->focus_on_filter(); } break; case FILE_RUN_SCRIPT: { @@ -3942,12 +3943,6 @@ void EditorNode::_update_recent_scenes() { void EditorNode::_quick_opened() { - if (current_option==FILE_QUICK_OPEN_FILE) { - String res_path = quick_open->get_selected(); - - scenes_dock->open(res_path); - return; - } Vector<String> files = quick_open->get_selected_files(); diff --git a/tools/editor/plugins/resource_preloader_editor_plugin.cpp b/tools/editor/plugins/resource_preloader_editor_plugin.cpp index 01bb82834d..cc9aca1a25 100644 --- a/tools/editor/plugins/resource_preloader_editor_plugin.cpp +++ b/tools/editor/plugins/resource_preloader_editor_plugin.cpp @@ -279,6 +279,106 @@ void ResourcePreloaderEditor::edit(ResourcePreloader* p_preloader) { +Variant ResourcePreloaderEditor::get_drag_data_fw(const Point2& p_point,Control* p_from) { + + TreeItem*ti =tree->get_item_at_pos(p_point); + if (!ti) + return Variant(); + + String name = ti->get_metadata(0); + + RES res = preloader->get_resource(name); + if (!res.is_valid()) + return Variant(); + + return EditorNode::get_singleton()->drag_resource(res,p_from); + +} + +bool ResourcePreloaderEditor::can_drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from) const { + + + + Dictionary d = p_data; + + if (!d.has("type")) + return false; + + if (d.has("from") && (Object*)(d["from"])==tree) + return false; + + if (String(d["type"])=="resource" && d.has("resource")) { + RES r=d["resource"]; + + return r.is_valid(); + } + + + if (String(d["type"])=="files") { + + Vector<String> files = d["files"]; + + if (files.size()==0) + return false; + + return true; + + } + return false; +} + +void ResourcePreloaderEditor::drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from) { + + if (!can_drop_data_fw(p_point,p_data,p_from)) + return; + + Dictionary d = p_data; + + if (!d.has("type")) + return; + + + if (String(d["type"])=="resource" && d.has("resource")) { + RES r=d["resource"]; + + if (r.is_valid()) { + + String basename; + if (r->get_name()!="") { + basename=r->get_name(); + } else if (r->get_path().is_resource_file()) { + basename = r->get_path().basename(); + } else { + basename="Resource"; + } + + String name=basename; + int counter=0; + while(preloader->has_resource(name)) { + counter++; + name=basename+"_"+itos(counter); + } + + undo_redo->create_action(TTR("Add Resource")); + undo_redo->add_do_method(preloader,"add_resource",name,r); + undo_redo->add_undo_method(preloader,"remove_resource",name); + undo_redo->add_do_method(this,"_update_library"); + undo_redo->add_undo_method(this,"_update_library"); + undo_redo->commit_action(); + } + } + + + if (String(d["type"])=="files") { + + Vector<String> files = d["files"]; + + _files_load_request(files); + } +} + + + void ResourcePreloaderEditor::_bind_methods() { ObjectTypeDB::bind_method(_MD("_input_event"),&ResourcePreloaderEditor::_input_event); @@ -289,6 +389,13 @@ void ResourcePreloaderEditor::_bind_methods() { ObjectTypeDB::bind_method(_MD("_delete_confirm_pressed"),&ResourcePreloaderEditor::_delete_confirm_pressed); ObjectTypeDB::bind_method(_MD("_files_load_request"),&ResourcePreloaderEditor::_files_load_request); ObjectTypeDB::bind_method(_MD("_update_library"),&ResourcePreloaderEditor::_update_library); + + + ObjectTypeDB::bind_method(_MD("get_drag_data_fw"), &ResourcePreloaderEditor::get_drag_data_fw); + ObjectTypeDB::bind_method(_MD("can_drop_data_fw"), &ResourcePreloaderEditor::can_drop_data_fw); + ObjectTypeDB::bind_method(_MD("drop_data_fw"), &ResourcePreloaderEditor::drop_data_fw); + + } ResourcePreloaderEditor::ResourcePreloaderEditor() { @@ -326,6 +433,7 @@ ResourcePreloaderEditor::ResourcePreloaderEditor() { tree->set_column_expand(1,true); tree->set_v_size_flags(SIZE_EXPAND_FILL); + tree->set_drag_forwarding(this); vbc->add_child(tree); dialog = memnew( AcceptDialog ); diff --git a/tools/editor/plugins/resource_preloader_editor_plugin.h b/tools/editor/plugins/resource_preloader_editor_plugin.h index 0bc94079a5..4f0cb4be37 100644 --- a/tools/editor/plugins/resource_preloader_editor_plugin.h +++ b/tools/editor/plugins/resource_preloader_editor_plugin.h @@ -67,6 +67,11 @@ class ResourcePreloaderEditor : public PanelContainer { UndoRedo *undo_redo; + Variant get_drag_data_fw(const Point2& p_point,Control* p_from); + bool can_drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from) const; + void drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from); + + protected: void _notification(int p_what); void _input_event(InputEvent p_event); diff --git a/tools/editor/plugins/sample_library_editor_plugin.cpp b/tools/editor/plugins/sample_library_editor_plugin.cpp index 0ab45b45c4..8b03c4651d 100644 --- a/tools/editor/plugins/sample_library_editor_plugin.cpp +++ b/tools/editor/plugins/sample_library_editor_plugin.cpp @@ -290,6 +290,123 @@ void SampleLibraryEditor::edit(Ref<SampleLibrary> p_sample_library) { } +Variant SampleLibraryEditor::get_drag_data_fw(const Point2& p_point,Control* p_from) { + + TreeItem*ti =tree->get_item_at_pos(p_point); + if (!ti) + return Variant(); + + String name = ti->get_metadata(0); + + RES res = sample_library->get_sample(name); + if (!res.is_valid()) + return Variant(); + + return EditorNode::get_singleton()->drag_resource(res,p_from); + + +} + +bool SampleLibraryEditor::can_drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from) const { + + + + Dictionary d = p_data; + + if (!d.has("type")) + return false; + + if (d.has("from") && (Object*)(d["from"])==tree) + return false; + + if (String(d["type"])=="resource" && d.has("resource")) { + RES r=d["resource"]; + + Ref<Sample> sample = r; + + if (sample.is_valid()) { + + return true; + } + } + + + if (String(d["type"])=="files") { + + Vector<String> files = d["files"]; + + if (files.size()==0) + return false; + + for(int i=0;i<files.size();i++) { + String file = files[0]; + String ftype = EditorFileSystem::get_singleton()->get_file_type(file); + + if (ftype!="Sample") { + return false; + } + + } + + return true; + + } + return false; +} + +void SampleLibraryEditor::drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from) { + + if (!can_drop_data_fw(p_point,p_data,p_from)) + return; + + Dictionary d = p_data; + + if (!d.has("type")) + return; + + + if (String(d["type"])=="resource" && d.has("resource")) { + RES r=d["resource"]; + + Ref<Sample> sample = r; + + if (sample.is_valid()) { + + String basename; + if (sample->get_name()!="") { + basename=sample->get_name(); + } else if (sample->get_path().is_resource_file()) { + basename = sample->get_path().basename(); + } else { + basename="Sample"; + } + + String name=basename; + int counter=0; + while(sample_library->has_sample(name)) { + counter++; + name=basename+"_"+itos(counter); + } + + undo_redo->create_action(TTR("Add Sample")); + undo_redo->add_do_method(sample_library.operator->(),"add_sample",name,sample); + undo_redo->add_undo_method(sample_library.operator->(),"remove_sample",name); + undo_redo->add_do_method(this,"_update_library"); + undo_redo->add_undo_method(this,"_update_library"); + undo_redo->commit_action(); + } + } + + + if (String(d["type"])=="files") { + + DVector<String> files = d["files"]; + + _file_load_request(files); + + } + +} void SampleLibraryEditor::_bind_methods() { @@ -301,6 +418,11 @@ void SampleLibraryEditor::_bind_methods() { ObjectTypeDB::bind_method(_MD("_file_load_request"),&SampleLibraryEditor::_file_load_request); ObjectTypeDB::bind_method(_MD("_update_library"),&SampleLibraryEditor::_update_library); ObjectTypeDB::bind_method(_MD("_button_pressed"),&SampleLibraryEditor::_button_pressed); + + ObjectTypeDB::bind_method(_MD("get_drag_data_fw"), &SampleLibraryEditor::get_drag_data_fw); + ObjectTypeDB::bind_method(_MD("can_drop_data_fw"), &SampleLibraryEditor::can_drop_data_fw); + ObjectTypeDB::bind_method(_MD("drop_data_fw"), &SampleLibraryEditor::drop_data_fw); + } SampleLibraryEditor::SampleLibraryEditor() { @@ -349,6 +471,8 @@ SampleLibraryEditor::SampleLibraryEditor() { tree->set_column_expand(4,false); tree->set_column_expand(5,false); + tree->set_drag_forwarding(this); + dialog = memnew( ConfirmationDialog ); add_child( dialog ); diff --git a/tools/editor/plugins/sample_library_editor_plugin.h b/tools/editor/plugins/sample_library_editor_plugin.h index b46b9a7f3d..f9fb184b7c 100644 --- a/tools/editor/plugins/sample_library_editor_plugin.h +++ b/tools/editor/plugins/sample_library_editor_plugin.h @@ -68,6 +68,10 @@ class SampleLibraryEditor : public Panel { void _button_pressed(Object *p_item,int p_column, int p_id); + Variant get_drag_data_fw(const Point2& p_point,Control* p_from); + bool can_drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from) const; + void drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from); + protected: void _notification(int p_what); void _input_event(InputEvent p_event); diff --git a/tools/editor/plugins/sprite_frames_editor_plugin.cpp b/tools/editor/plugins/sprite_frames_editor_plugin.cpp index 796fc23d9a..b2f10ccaae 100644 --- a/tools/editor/plugins/sprite_frames_editor_plugin.cpp +++ b/tools/editor/plugins/sprite_frames_editor_plugin.cpp @@ -49,6 +49,9 @@ void SpriteFramesEditor::_notification(int p_what) { if (p_what==NOTIFICATION_ENTER_TREE) { load->set_icon( get_icon("Folder","EditorIcons") ); _delete->set_icon( get_icon("Del","EditorIcons") ); + new_anim->set_icon( get_icon("New","EditorIcons") ); + remove_anim->set_icon( get_icon("Del","EditorIcons") ); + } if (p_what==NOTIFICATION_READY) { @@ -61,8 +64,9 @@ void SpriteFramesEditor::_notification(int p_what) { } } -void SpriteFramesEditor::_file_load_request(const DVector<String>& p_path) { +void SpriteFramesEditor::_file_load_request(const DVector<String>& p_path,int p_at_pos) { + ERR_FAIL_COND(!frames->has_animation(edited_anim)); List< Ref<Texture> > resources; @@ -85,28 +89,32 @@ void SpriteFramesEditor::_file_load_request(const DVector<String>& p_path) { if (resources.empty()) { - print_line("added frames!"); + //print_line("added frames!"); return; } undo_redo->create_action(TTR("Add Frame")); - int fc=frames->get_frame_count(); + int fc=frames->get_frame_count(edited_anim); + + int count=0; for(List< Ref<Texture> >::Element *E=resources.front();E;E=E->next() ) { - undo_redo->add_do_method(frames,"add_frame",E->get()); - undo_redo->add_undo_method(frames,"remove_frame",fc++); + undo_redo->add_do_method(frames,"add_frame",edited_anim,E->get(),p_at_pos==-1?-1:p_at_pos+count); + undo_redo->add_undo_method(frames,"remove_frame",edited_anim,p_at_pos==-1?fc:p_at_pos); + count++; } undo_redo->add_do_method(this,"_update_library"); undo_redo->add_undo_method(this,"_update_library"); undo_redo->commit_action(); - print_line("added frames!"); + //print_line("added frames!"); } void SpriteFramesEditor::_load_pressed() { + ERR_FAIL_COND(!frames->has_animation(edited_anim)); loading_scene=false; file->clear_filters(); @@ -160,19 +168,21 @@ void SpriteFramesEditor::_item_edited() { void SpriteFramesEditor::_delete_confirm_pressed() { - if (!tree->get_selected()) + ERR_FAIL_COND(!frames->has_animation(edited_anim)); + + if (tree->get_current()<0) return; sel-=1; - if (sel<0 && frames->get_frame_count()) + if (sel<0 && frames->get_frame_count(edited_anim)) sel=0; - int to_remove = tree->get_selected()->get_metadata(0); + int to_remove = tree->get_current(); sel=to_remove; - Ref<Texture> r = frames->get_frame(to_remove); + Ref<Texture> r = frames->get_frame(edited_anim,to_remove); undo_redo->create_action(TTR("Delete Resource")); - undo_redo->add_do_method(frames,"remove_frame",to_remove); - undo_redo->add_undo_method(frames,"add_frame",r,to_remove); + undo_redo->add_do_method(frames,"remove_frame",edited_anim,to_remove); + undo_redo->add_undo_method(frames,"add_frame",edited_anim,r,to_remove); undo_redo->add_do_method(this,"_update_library"); undo_redo->add_undo_method(this,"_update_library"); undo_redo->commit_action(); @@ -182,6 +192,8 @@ void SpriteFramesEditor::_delete_confirm_pressed() { void SpriteFramesEditor::_paste_pressed() { + ERR_FAIL_COND(!frames->has_animation(edited_anim)); + Ref<Texture> r=EditorSettings::get_singleton()->get_resource_clipboard(); if (!r.is_valid()) { dialog->set_text(TTR("Resource clipboard is empty or not a texture!")); @@ -194,8 +206,8 @@ void SpriteFramesEditor::_paste_pressed() { undo_redo->create_action(TTR("Paste Frame")); - undo_redo->add_do_method(frames,"add_frame",r); - undo_redo->add_undo_method(frames,"remove_frame",frames->get_frame_count()); + undo_redo->add_do_method(frames,"add_frame",edited_anim,r); + undo_redo->add_undo_method(frames,"remove_frame",edited_anim,frames->get_frame_count(edited_anim)); undo_redo->add_do_method(this,"_update_library"); undo_redo->add_undo_method(this,"_update_library"); undo_redo->commit_action(); @@ -204,16 +216,17 @@ void SpriteFramesEditor::_paste_pressed() { void SpriteFramesEditor::_empty_pressed() { + ERR_FAIL_COND(!frames->has_animation(edited_anim)); int from=-1; - if (tree->get_selected()) { + if (tree->get_current()>=0) { - from = tree->get_selected()->get_metadata(0); + from = tree->get_current(); sel=from; } else { - from=frames->get_frame_count(); + from=frames->get_frame_count(edited_anim); } @@ -221,8 +234,8 @@ void SpriteFramesEditor::_empty_pressed() { Ref<Texture> r; undo_redo->create_action(TTR("Add Empty")); - undo_redo->add_do_method(frames,"add_frame",r,from); - undo_redo->add_undo_method(frames,"remove_frame",from); + undo_redo->add_do_method(frames,"add_frame",edited_anim,r,from); + undo_redo->add_undo_method(frames,"remove_frame",edited_anim,from); undo_redo->add_do_method(this,"_update_library"); undo_redo->add_undo_method(this,"_update_library"); undo_redo->commit_action(); @@ -231,16 +244,17 @@ void SpriteFramesEditor::_empty_pressed() { void SpriteFramesEditor::_empty2_pressed() { + ERR_FAIL_COND(!frames->has_animation(edited_anim)); int from=-1; - if (tree->get_selected()) { + if (tree->get_current()>=0) { - from = tree->get_selected()->get_metadata(0); + from = tree->get_current(); sel=from; } else { - from=frames->get_frame_count(); + from=frames->get_frame_count(edited_anim); } @@ -248,8 +262,8 @@ void SpriteFramesEditor::_empty2_pressed() { Ref<Texture> r; undo_redo->create_action(TTR("Add Empty")); - undo_redo->add_do_method(frames,"add_frame",r,from+1); - undo_redo->add_undo_method(frames,"remove_frame",from+1); + undo_redo->add_do_method(frames,"add_frame",edited_anim,r,from+1); + undo_redo->add_undo_method(frames,"remove_frame",edited_anim,from+1); undo_redo->add_do_method(this,"_update_library"); undo_redo->add_undo_method(this,"_update_library"); undo_redo->commit_action(); @@ -258,21 +272,24 @@ void SpriteFramesEditor::_empty2_pressed() { void SpriteFramesEditor::_up_pressed() { - if (!tree->get_selected()) + ERR_FAIL_COND(!frames->has_animation(edited_anim)); + + if (tree->get_current()<0) return; - int to_move = tree->get_selected()->get_metadata(0); + + int to_move = tree->get_current(); if (to_move<1) return; sel=to_move; sel-=1; - Ref<Texture> r = frames->get_frame(to_move); + Ref<Texture> r = frames->get_frame(edited_anim,to_move); undo_redo->create_action(TTR("Delete Resource")); - undo_redo->add_do_method(frames,"set_frame",to_move,frames->get_frame(to_move-1)); - undo_redo->add_do_method(frames,"set_frame",to_move-1,frames->get_frame(to_move)); - undo_redo->add_undo_method(frames,"set_frame",to_move,frames->get_frame(to_move)); - undo_redo->add_undo_method(frames,"set_frame",to_move-1,frames->get_frame(to_move-1)); + undo_redo->add_do_method(frames,"set_frame",edited_anim,to_move,frames->get_frame(edited_anim,to_move-1)); + undo_redo->add_do_method(frames,"set_frame",edited_anim,to_move-1,frames->get_frame(edited_anim,to_move)); + undo_redo->add_undo_method(frames,"set_frame",edited_anim,to_move,frames->get_frame(edited_anim,to_move)); + undo_redo->add_undo_method(frames,"set_frame",edited_anim,to_move-1,frames->get_frame(edited_anim,to_move-1)); undo_redo->add_do_method(this,"_update_library"); undo_redo->add_undo_method(this,"_update_library"); undo_redo->commit_action(); @@ -281,21 +298,24 @@ void SpriteFramesEditor::_up_pressed() { void SpriteFramesEditor::_down_pressed() { - if (!tree->get_selected()) + ERR_FAIL_COND(!frames->has_animation(edited_anim)); + + if (tree->get_current()<0) return; - int to_move = tree->get_selected()->get_metadata(0); - if (to_move<0 || to_move>=frames->get_frame_count()-1) + + int to_move = tree->get_current(); + if (to_move<0 || to_move>=frames->get_frame_count(edited_anim)-1) return; sel=to_move; sel+=1; - Ref<Texture> r = frames->get_frame(to_move); + Ref<Texture> r = frames->get_frame(edited_anim,to_move); undo_redo->create_action(TTR("Delete Resource")); - undo_redo->add_do_method(frames,"set_frame",to_move,frames->get_frame(to_move+1)); - undo_redo->add_do_method(frames,"set_frame",to_move+1,frames->get_frame(to_move)); - undo_redo->add_undo_method(frames,"set_frame",to_move,frames->get_frame(to_move)); - undo_redo->add_undo_method(frames,"set_frame",to_move+1,frames->get_frame(to_move+1)); + undo_redo->add_do_method(frames,"set_frame",edited_anim,to_move,frames->get_frame(edited_anim,to_move+1)); + undo_redo->add_do_method(frames,"set_frame",edited_anim,to_move+1,frames->get_frame(edited_anim,to_move)); + undo_redo->add_undo_method(frames,"set_frame",edited_anim,to_move,frames->get_frame(edited_anim,to_move)); + undo_redo->add_undo_method(frames,"set_frame",edited_anim,to_move+1,frames->get_frame(edited_anim,to_move+1)); undo_redo->add_do_method(this,"_update_library"); undo_redo->add_undo_method(this,"_update_library"); undo_redo->commit_action(); @@ -308,7 +328,7 @@ void SpriteFramesEditor::_down_pressed() { void SpriteFramesEditor::_delete_pressed() { - if (!tree->get_selected()) + if (tree->get_current()<0) return; _delete_confirm_pressed(); //it has undo.. why bother with a dialog.. @@ -323,39 +343,211 @@ void SpriteFramesEditor::_delete_pressed() { } -void SpriteFramesEditor::_update_library() { +void SpriteFramesEditor::_animation_select() { + + if (updating) + return; + + TreeItem *selected = animations->get_selected(); + ERR_FAIL_COND(!selected); + edited_anim=selected->get_text(0); + _update_library(true); + +} + +void SpriteFramesEditor::_animation_name_edited(){ + + if (updating) + return; + + if (!frames->has_animation(edited_anim)) + return; + + TreeItem *edited = animations->get_edited(); + if (!edited) + return; + + String new_name = edited->get_text(0); + + if (new_name==String(edited_anim)) + return; + + new_name=new_name.replace("/","_").replace(","," "); + + String name=new_name; + int counter=0; + while(frames->has_animation(name)) { + counter++; + name=new_name+" "+itos(counter); + } + + undo_redo->create_action(TTR("Rename Animation")); + undo_redo->add_do_method(frames,"rename_animation",edited_anim,name); + undo_redo->add_undo_method(frames,"rename_animation",name,edited_anim); + undo_redo->add_do_method(this,"_update_library"); + undo_redo->add_undo_method(this,"_update_library"); + + edited_anim=new_name; + + undo_redo->commit_action(); + + + +} +void SpriteFramesEditor::_animation_add(){ + + + String new_name = "New Anim"; + + String name=new_name; + int counter=0; + while(frames->has_animation(name)) { + counter++; + name=new_name+" "+itos(counter); + } + + undo_redo->create_action(TTR("Add Animation")); + undo_redo->add_do_method(frames,"add_animation",name); + undo_redo->add_undo_method(frames,"remove_animation",name); + undo_redo->add_do_method(this,"_update_library"); + undo_redo->add_undo_method(this,"_update_library"); + + edited_anim=new_name; + + undo_redo->commit_action(); + +} +void SpriteFramesEditor::_animation_remove(){ + + //fuck everything + if (updating) + return; + + if (!frames->has_animation(edited_anim)) + return; + + undo_redo->create_action(TTR("Remove Animation")); + undo_redo->add_do_method(frames,"remove_animation",edited_anim); + undo_redo->add_undo_method(frames,"add_animation",edited_anim); + undo_redo->add_undo_method(frames,"set_animation_speed",edited_anim,frames->get_animation_speed(edited_anim)); + undo_redo->add_undo_method(frames,"set_animation_loop",edited_anim,frames->get_animation_loop(edited_anim)); + int fc = frames->get_frame_count(edited_anim); + for(int i=0;i<fc;i++) { + Ref<Texture> frame = frames->get_frame(edited_anim,i); + undo_redo->add_undo_method(frames,"add_frame",edited_anim,frame); + } + undo_redo->add_do_method(this,"_update_library"); + undo_redo->add_undo_method(this,"_update_library"); + + undo_redo->commit_action(); + +} + + +void SpriteFramesEditor::_animation_loop_changed() { + + if (updating) + return; + + undo_redo->create_action(TTR("Change Animation Loop")); + undo_redo->add_do_method(frames,"set_animation_loop",edited_anim,anim_loop->is_pressed()); + undo_redo->add_undo_method(frames,"set_animation_loop",edited_anim,frames->get_animation_loop(edited_anim)); + undo_redo->add_do_method(this,"_update_library",true); + undo_redo->add_undo_method(this,"_update_library",true); + undo_redo->commit_action(); + +} + +void SpriteFramesEditor::_animation_fps_changed(double p_value) { + + if (updating) + return; + + undo_redo->create_action(TTR("Change Animation FPS"),true); + undo_redo->add_do_method(frames,"set_animation_speed",edited_anim,p_value); + undo_redo->add_undo_method(frames,"set_animation_speed",edited_anim,frames->get_animation_speed(edited_anim)); + undo_redo->add_do_method(this,"_update_library",true); + undo_redo->add_undo_method(this,"_update_library",true); + + undo_redo->commit_action(); + +} + +void SpriteFramesEditor::_update_library(bool p_skip_selector) { + + updating=true; + + if (!p_skip_selector) { + animations->clear(); + + TreeItem *anim_root=animations->create_item(); + + List<StringName> anim_names; + + anim_names.sort_custom<StringName::AlphCompare>(); + + frames->get_animation_list(&anim_names); + + anim_names.sort_custom<StringName::AlphCompare>(); + + for(List<StringName>::Element *E=anim_names.front();E;E=E->next()) { + + String name = E->get(); + + TreeItem *it = animations->create_item(anim_root); + + it->set_metadata(0,name); + + it->set_text(0,name); + it->set_editable(0,true); + + if (E->get()==edited_anim) { + it->select(0); + } + } + } + tree->clear(); - tree->set_hide_root(true); - TreeItem *root = tree->create_item(NULL); - if (sel>=frames->get_frame_count()) - sel=frames->get_frame_count()-1; - else if (sel<0 && frames->get_frame_count()) + if (!frames->has_animation(edited_anim)) { + updating=false; + return; + } + + + if (sel>=frames->get_frame_count(edited_anim)) + sel=frames->get_frame_count(edited_anim)-1; + else if (sel<0 && frames->get_frame_count(edited_anim)) sel=0; - for(int i=0;i<frames->get_frame_count();i++) { + for(int i=0;i<frames->get_frame_count(edited_anim);i++) { + + + String name; + Ref<Texture> icon; - TreeItem *ti = tree->create_item(root); - ti->set_cell_mode(0,TreeItem::CELL_MODE_STRING); - ti->set_selectable(0,true); - if (frames->get_frame(i).is_null()) { + if (frames->get_frame(edited_anim,i).is_null()) { - ti->set_text(0,TTR("Frame ")+itos(i)+" (empty)"); + name=itos(i)+TTR(": (empty)"); } else { - ti->set_text(0,TTR("Frame ")+itos(i)+" ("+frames->get_frame(i)->get_name()+")"); - ti->set_icon(0,frames->get_frame(i)); + name=itos(i)+": "+frames->get_frame(edited_anim,i)->get_name(); + icon=frames->get_frame(edited_anim,i); } - if (frames->get_frame(i).is_valid()) - ti->set_tooltip(0,frames->get_frame(i)->get_path()); - ti->set_metadata(0,i); - ti->set_icon_max_width(0,96); + + tree->add_item(name,icon); + if (frames->get_frame(edited_anim,i).is_valid()) + tree->set_item_tooltip(tree->get_item_count()-1,frames->get_frame(edited_anim,i)->get_path()); if (sel==i) - ti->select(0); + tree->select(tree->get_item_count()-1); } + anim_speed->set_val(frames->get_animation_speed(edited_anim)); + anim_loop->set_pressed(frames->get_animation_loop(edited_anim)); + + updating=false; //player->add_resource("default",resource); } @@ -363,10 +555,27 @@ void SpriteFramesEditor::_update_library() { void SpriteFramesEditor::edit(SpriteFrames* p_frames) { + if (frames==p_frames) + return; + frames=p_frames; if (p_frames) { + + if (!p_frames->has_animation(edited_anim)) { + + List<StringName> anim_names; + frames->get_animation_list(&anim_names); + anim_names.sort_custom<StringName::AlphCompare>(); + if (anim_names.size()) { + edited_anim=anim_names.front()->get(); + } else { + edited_anim=StringName(); + } + + } + _update_library(); } else { @@ -377,6 +586,110 @@ void SpriteFramesEditor::edit(SpriteFrames* p_frames) { } +Variant SpriteFramesEditor::get_drag_data_fw(const Point2& p_point,Control* p_from) { + + if (!frames->has_animation(edited_anim)) + return false; + + int idx = tree->get_item_at_pos(p_point,true); + + if (idx<0 || idx>=frames->get_frame_count(edited_anim)) + return Variant(); + + RES frame = frames->get_frame(edited_anim,idx); + + if (frame.is_null()) + return Variant(); + + return EditorNode::get_singleton()->drag_resource(frame,p_from); + + +} + +bool SpriteFramesEditor::can_drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from) const{ + + Dictionary d = p_data; + + if (!d.has("type")) + return false; + + if (d.has("from") && (Object*)(d["from"])==tree) + return false; + + if (String(d["type"])=="resource" && d.has("resource")) { + RES r=d["resource"]; + + Ref<Texture> texture = r; + + if (texture.is_valid()) { + + return true; + } + } + + + if (String(d["type"])=="files") { + + Vector<String> files = d["files"]; + + if (files.size()==0) + return false; + + for(int i=0;i<files.size();i++) { + String file = files[0]; + String ftype = EditorFileSystem::get_singleton()->get_file_type(file); + + if (!ObjectTypeDB::is_type(ftype,"Texture")) { + return false; + } + + } + + return true; + + } + return false; +} + +void SpriteFramesEditor::drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from){ + + if (!can_drop_data_fw(p_point,p_data,p_from)) + return; + + Dictionary d = p_data; + + if (!d.has("type")) + return; + + int at_pos = tree->get_item_at_pos(p_point,true); + + if (String(d["type"])=="resource" && d.has("resource")) { + RES r=d["resource"]; + + Ref<Texture> texture = r; + + if (texture.is_valid()) { + + undo_redo->create_action(TTR("Add Frame")); + undo_redo->add_do_method(frames,"add_frame",edited_anim,texture,at_pos==-1?-1:at_pos); + undo_redo->add_undo_method(frames,"remove_frame",edited_anim,at_pos==-1?frames->get_frame_count(edited_anim):at_pos); + undo_redo->add_do_method(this,"_update_library"); + undo_redo->add_undo_method(this,"_update_library"); + undo_redo->commit_action(); + + } + } + + + if (String(d["type"])=="files") { + + DVector<String> files = d["files"]; + + _file_load_request(files,at_pos); + } + +} + void SpriteFramesEditor::_bind_methods() { @@ -388,29 +701,94 @@ void SpriteFramesEditor::_bind_methods() { ObjectTypeDB::bind_method(_MD("_delete_pressed"),&SpriteFramesEditor::_delete_pressed); ObjectTypeDB::bind_method(_MD("_paste_pressed"),&SpriteFramesEditor::_paste_pressed); ObjectTypeDB::bind_method(_MD("_delete_confirm_pressed"),&SpriteFramesEditor::_delete_confirm_pressed); - ObjectTypeDB::bind_method(_MD("_file_load_request"),&SpriteFramesEditor::_file_load_request); - ObjectTypeDB::bind_method(_MD("_update_library"),&SpriteFramesEditor::_update_library); + ObjectTypeDB::bind_method(_MD("_file_load_request","files","atpos"),&SpriteFramesEditor::_file_load_request,DEFVAL(-1)); + ObjectTypeDB::bind_method(_MD("_update_library","skipsel"),&SpriteFramesEditor::_update_library,DEFVAL(false)); ObjectTypeDB::bind_method(_MD("_up_pressed"),&SpriteFramesEditor::_up_pressed); ObjectTypeDB::bind_method(_MD("_down_pressed"),&SpriteFramesEditor::_down_pressed); + ObjectTypeDB::bind_method(_MD("_animation_select"),&SpriteFramesEditor::_animation_select); + ObjectTypeDB::bind_method(_MD("_animation_name_edited"),&SpriteFramesEditor::_animation_name_edited); + ObjectTypeDB::bind_method(_MD("_animation_add"),&SpriteFramesEditor::_animation_add); + ObjectTypeDB::bind_method(_MD("_animation_remove"),&SpriteFramesEditor::_animation_remove); + ObjectTypeDB::bind_method(_MD("_animation_loop_changed"),&SpriteFramesEditor::_animation_loop_changed); + ObjectTypeDB::bind_method(_MD("_animation_fps_changed"),&SpriteFramesEditor::_animation_fps_changed); + ObjectTypeDB::bind_method(_MD("get_drag_data_fw"), &SpriteFramesEditor::get_drag_data_fw); + ObjectTypeDB::bind_method(_MD("can_drop_data_fw"), &SpriteFramesEditor::can_drop_data_fw); + ObjectTypeDB::bind_method(_MD("drop_data_fw"), &SpriteFramesEditor::drop_data_fw); + + } + SpriteFramesEditor::SpriteFramesEditor() { //add_style_override("panel", get_stylebox("panel","Panel")); + split = memnew( HSplitContainer ); + add_child(split); + + VBoxContainer *vbc_animlist = memnew( VBoxContainer ); + split->add_child(vbc_animlist); + vbc_animlist->set_custom_minimum_size(Size2(150,0)); + //vbc_animlist->set_v_size_flags(SIZE_EXPAND_FILL); + + + VBoxContainer *sub_vb = memnew( VBoxContainer ); + vbc_animlist->add_margin_child(TTR("Animations"),sub_vb,true); + sub_vb->set_v_size_flags(SIZE_EXPAND_FILL); + + HBoxContainer *hbc_animlist = memnew( HBoxContainer ); + sub_vb->add_child(hbc_animlist); + + new_anim = memnew( Button ); + hbc_animlist->add_child(new_anim); + new_anim->connect("pressed",this,"_animation_add"); + + + hbc_animlist->add_spacer(); + + remove_anim = memnew( Button ); + hbc_animlist->add_child(remove_anim); + remove_anim->connect("pressed",this,"_animation_remove"); + + animations = memnew( Tree ); + sub_vb->add_child(animations); + animations->set_v_size_flags(SIZE_EXPAND_FILL); + animations->set_hide_root(true); + animations->connect("cell_selected",this,"_animation_select"); + animations->connect("item_edited",this,"_animation_name_edited"); + animations->set_single_select_cell_editing_only_when_already_selected(true); + + + anim_speed = memnew( SpinBox); + vbc_animlist->add_margin_child(TTR("Speed (FPS):"),anim_speed); + anim_speed->set_min(0); + anim_speed->set_max(100); + anim_speed->set_step(0.01); + anim_speed->connect("value_changed",this,"_animation_fps_changed"); + + anim_loop = memnew( CheckButton ); + anim_loop->set_text(TTR("Loop")); + vbc_animlist->add_child(anim_loop); + anim_loop->connect("pressed",this,"_animation_loop_changed"); + VBoxContainer *vbc = memnew( VBoxContainer ); - add_child(vbc); + split->add_child(vbc); + vbc->set_h_size_flags(SIZE_EXPAND_FILL); + + sub_vb = memnew( VBoxContainer ); + vbc->add_margin_child(TTR("Animation Frames"),sub_vb,true); + HBoxContainer *hbc = memnew( HBoxContainer ); - vbc->add_child(hbc); + sub_vb->add_child(hbc); + + //animations = memnew( ItemList ); + load = memnew( Button ); load->set_tooltip(TTR("Load Resource")); hbc->add_child(load); - - - paste = memnew( Button ); paste->set_text(TTR("Paste")); hbc->add_child(paste); @@ -438,15 +816,22 @@ SpriteFramesEditor::SpriteFramesEditor() { add_child(file); - tree = memnew( Tree ); - tree->set_columns(2); - tree->set_column_min_width(0,3); - tree->set_column_min_width(1,1); - tree->set_column_expand(0,true); - tree->set_column_expand(1,true); + tree = memnew( ItemList ); tree->set_v_size_flags(SIZE_EXPAND_FILL); + tree->set_icon_mode(ItemList::ICON_MODE_TOP); + + int thumbnail_size = 96; + tree->set_max_columns(0); + tree->set_icon_mode(ItemList::ICON_MODE_TOP); + tree->set_fixed_column_width(thumbnail_size*3/2); + tree->set_max_text_lines(2); + tree->set_max_icon_size(Size2(thumbnail_size,thumbnail_size)); + //tree->set_min_icon_size(Size2(thumbnail_size,thumbnail_size)); + tree->set_drag_forwarding(this); + - vbc->add_child(tree); + + sub_vb->add_child(tree); dialog = memnew( AcceptDialog ); add_child( dialog ); @@ -460,10 +845,14 @@ SpriteFramesEditor::SpriteFramesEditor() { move_down->connect("pressed", this,"_down_pressed"); file->connect("files_selected", this,"_file_load_request"); //dialog->connect("confirmed", this,"_delete_confirm_pressed"); - tree->connect("item_edited", this,"_item_edited"); + //tree->connect("item_selected", this,"_item_edited"); loading_scene=false; sel=-1; + updating=false; + + edited_anim="default"; + } diff --git a/tools/editor/plugins/sprite_frames_editor_plugin.h b/tools/editor/plugins/sprite_frames_editor_plugin.h index 5d0a6cb035..f0aa84c23a 100644 --- a/tools/editor/plugins/sprite_frames_editor_plugin.h +++ b/tools/editor/plugins/sprite_frames_editor_plugin.h @@ -36,6 +36,7 @@ #include "scene/2d/animated_sprite.h" #include "scene/gui/file_dialog.h" #include "scene/gui/dialogs.h" +#include "scene/gui/split_container.h" class SpriteFramesEditor : public PanelContainer { @@ -49,10 +50,18 @@ class SpriteFramesEditor : public PanelContainer { Button *empty2; Button *move_up; Button *move_down; - Tree *tree; + ItemList *tree; bool loading_scene; int sel; + HSplitContainer *split; + Button *new_anim; + Button *remove_anim; + + + Tree *animations; + SpinBox *anim_speed; + CheckButton *anim_loop; EditorFileDialog *file; @@ -60,10 +69,11 @@ class SpriteFramesEditor : public PanelContainer { SpriteFrames *frames; + StringName edited_anim; void _load_pressed(); void _load_scene_pressed(); - void _file_load_request(const DVector<String>& p_path); + void _file_load_request(const DVector<String>& p_path, int p_at_pos=-1); void _paste_pressed(); void _empty_pressed(); void _empty2_pressed(); @@ -71,11 +81,27 @@ class SpriteFramesEditor : public PanelContainer { void _delete_confirm_pressed(); void _up_pressed(); void _down_pressed(); - void _update_library(); + void _update_library(bool p_skip_selector=false); void _item_edited(); + + + void _animation_select(); + void _animation_name_edited(); + void _animation_add(); + void _animation_remove(); + void _animation_loop_changed(); + void _animation_fps_changed(double p_value); + + bool updating; + UndoRedo *undo_redo; + bool _is_drop_valid(const Dictionary& p_drag_data, const Dictionary& p_item_data) const; + Variant get_drag_data_fw(const Point2& p_point,Control* p_from); + bool can_drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from) const; + void drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from); + protected: void _notification(int p_what); void _input_event(InputEvent p_event); diff --git a/tools/editor/property_editor.cpp b/tools/editor/property_editor.cpp index 6f80910150..c4f54e04cb 100644 --- a/tools/editor/property_editor.cpp +++ b/tools/editor/property_editor.cpp @@ -2287,6 +2287,7 @@ bool PropertyEditor::_is_drop_valid(const Dictionary& p_drag_data, const Diction } } + if (drag_data.has("type") && String(drag_data["type"])=="files") { Vector<String> files = drag_data["files"]; diff --git a/tools/editor/scene_tree_dock.cpp b/tools/editor/scene_tree_dock.cpp index ce7a0b2911..88bed4c23f 100644 --- a/tools/editor/scene_tree_dock.cpp +++ b/tools/editor/scene_tree_dock.cpp @@ -1681,9 +1681,50 @@ void SceneTreeDock::_nodes_dragged(Array p_nodes,NodePath p_to,int p_type) { } +void SceneTreeDock::_tree_rmb(const Vector2& p_menu_pos) { + + List<Node*> selection = editor_selection->get_selected_node_list(); + + if (selection.size()==0) + return; + menu->clear(); + + + if (selection.size()==1) { + menu->add_item("Add Child Node",TOOL_NEW,KEY_MASK_CMD|KEY_A); + menu->add_item("Instance Child",TOOL_INSTANCE); + menu->add_separator(); + menu->add_item("Change Type",TOOL_REPLACE); + menu->add_separator(); + menu->add_item("Edit Groups",TOOL_GROUP); + menu->add_item("Edit Connections",TOOL_CONNECT); + menu->add_separator(); + menu->add_item("Add Script",TOOL_SCRIPT); + menu->add_separator(); + } + + menu->add_item("Move Up",TOOL_MOVE_UP,KEY_MASK_CMD|KEY_UP); + menu->add_item("Move Down",TOOL_MOVE_DOWN,KEY_MASK_CMD|KEY_DOWN); + menu->add_item("Duplicate",TOOL_DUPLICATE,KEY_MASK_CMD|KEY_D); + menu->add_item("Reparent",TOOL_REPARENT); + + if (selection.size()==1) { + menu->add_separator(); + menu->add_item("Save Branch as Scene",TOOL_NEW_SCENE_FROM); + } + menu->add_separator(); + + menu->add_item("Delete Node(s)",TOOL_ERASE,KEY_DELETE); + + menu->set_size(Size2(1,1)); + menu->set_pos(p_menu_pos); + menu->popup(); + +} + void SceneTreeDock::_bind_methods() { - ObjectTypeDB::bind_method(_MD("_tool_selected"),&SceneTreeDock::_tool_selected); + ObjectTypeDB::bind_method(_MD("_tool_selected"),&SceneTreeDock::_tool_selected,DEFVAL(false)); ObjectTypeDB::bind_method(_MD("_create"),&SceneTreeDock::_create); //ObjectTypeDB::bind_method(_MD("_script_created"),&SceneTreeDock::_script_created); ObjectTypeDB::bind_method(_MD("_node_reparent"),&SceneTreeDock::_node_reparent); @@ -1701,6 +1742,7 @@ void SceneTreeDock::_bind_methods() { ObjectTypeDB::bind_method(_MD("_new_scene_from"),&SceneTreeDock::_new_scene_from); ObjectTypeDB::bind_method(_MD("_nodes_dragged"),&SceneTreeDock::_nodes_dragged); ObjectTypeDB::bind_method(_MD("_files_dropped"),&SceneTreeDock::_files_dropped); + ObjectTypeDB::bind_method(_MD("_tree_rmb"),&SceneTreeDock::_tree_rmb); ObjectTypeDB::bind_method(_MD("instance"),&SceneTreeDock::instance); @@ -1765,6 +1807,7 @@ SceneTreeDock::SceneTreeDock(EditorNode *p_editor,Node *p_scene_root,EditorSelec scene_tree = memnew( SceneTreeEditor(false,true,true )); vbc->add_child(scene_tree); scene_tree->set_v_size_flags(SIZE_EXPAND|SIZE_FILL); + scene_tree->connect("rmb_pressed",this,"_tree_rmb"); scene_tree->connect("node_selected", this,"_node_selected",varray(),CONNECT_DEFERRED); scene_tree->connect("node_renamed", this,"_node_renamed",varray(),CONNECT_DEFERRED); @@ -1869,7 +1912,9 @@ SceneTreeDock::SceneTreeDock(EditorNode *p_editor,Node *p_scene_root,EditorSelec new_scene_from_dialog->connect("file_selected",this,"_new_scene_from"); - + menu = memnew( PopupMenu ); + add_child(menu); + menu->connect("item_pressed",this,"_tool_selected"); first_enter=true; diff --git a/tools/editor/scene_tree_dock.h b/tools/editor/scene_tree_dock.h index 5dc1e3e12e..9b84c4d44d 100644 --- a/tools/editor/scene_tree_dock.h +++ b/tools/editor/scene_tree_dock.h @@ -35,6 +35,7 @@ #include "scene/gui/button.h" #include "scene/gui/tool_button.h" #include "scene/gui/box_container.h" +#include "scene/gui/popup_menu.h" #include "scene_tree_editor.h" #include "create_dialog.h" #include "editor_data.h" @@ -93,6 +94,8 @@ class SceneTreeDock : public VBoxContainer { EditorSubScene *import_subscene_dialog; EditorFileDialog *new_scene_from_dialog; + PopupMenu * menu; + bool first_enter; void _create(); @@ -135,6 +138,8 @@ class SceneTreeDock : public VBoxContainer { void _nodes_dragged(Array p_nodes,NodePath p_to,int p_type); void _files_dropped(Vector<String> p_files,NodePath p_to,int p_type); + void _tree_rmb(const Vector2& p_menu_pos); + protected: void _notification(int p_what); diff --git a/tools/editor/scene_tree_editor.cpp b/tools/editor/scene_tree_editor.cpp index fd79460aa8..8760d21c1c 100644 --- a/tools/editor/scene_tree_editor.cpp +++ b/tools/editor/scene_tree_editor.cpp @@ -908,6 +908,10 @@ void SceneTreeEditor::drop_data_fw(const Point2& p_point,const Variant& p_data,C } +void SceneTreeEditor::_rmb_select(const Vector2& p_pos) { + + emit_signal("rmb_pressed",tree->get_global_transform().xform(p_pos)); +} void SceneTreeEditor::_bind_methods() { @@ -923,6 +927,7 @@ void SceneTreeEditor::_bind_methods() { ObjectTypeDB::bind_method("_cell_button_pressed",&SceneTreeEditor::_cell_button_pressed); ObjectTypeDB::bind_method("_cell_collapsed",&SceneTreeEditor::_cell_collapsed); ObjectTypeDB::bind_method("_subscene_option",&SceneTreeEditor::_subscene_option); + ObjectTypeDB::bind_method("_rmb_select",&SceneTreeEditor::_rmb_select); ObjectTypeDB::bind_method("_node_script_changed",&SceneTreeEditor::_node_script_changed); ObjectTypeDB::bind_method("_node_visibility_changed",&SceneTreeEditor::_node_visibility_changed); @@ -937,6 +942,7 @@ void SceneTreeEditor::_bind_methods() { ADD_SIGNAL( MethodInfo("node_changed") ); ADD_SIGNAL( MethodInfo("nodes_rearranged",PropertyInfo(Variant::ARRAY,"paths"),PropertyInfo(Variant::NODE_PATH,"to_path"),PropertyInfo(Variant::INT,"type") ) ); ADD_SIGNAL( MethodInfo("files_dropped",PropertyInfo(Variant::STRING_ARRAY,"files"),PropertyInfo(Variant::NODE_PATH,"to_path"),PropertyInfo(Variant::INT,"type") ) ); + ADD_SIGNAL( MethodInfo("rmb_pressed",PropertyInfo(Variant::VECTOR2,"pos")) ) ; ADD_SIGNAL( MethodInfo("open") ); ADD_SIGNAL( MethodInfo("open_script") ); @@ -976,6 +982,9 @@ SceneTreeEditor::SceneTreeEditor(bool p_label,bool p_can_rename, bool p_can_open add_child( tree ); tree->set_drag_forwarding(this); + if (p_can_rename) + tree->set_allow_rmb_select(true); + tree->connect("item_rmb_selected",this,"_rmb_select"); tree->connect("cell_selected", this,"_selected_changed"); tree->connect("item_edited", this,"_renamed",varray(),CONNECT_DEFERRED); diff --git a/tools/editor/scene_tree_editor.h b/tools/editor/scene_tree_editor.h index 283db280ed..5529d36a46 100644 --- a/tools/editor/scene_tree_editor.h +++ b/tools/editor/scene_tree_editor.h @@ -112,6 +112,7 @@ class SceneTreeEditor : public Control { void _subscene_option(int p_idx); + void _selection_changed(); Node *get_scene_node(); @@ -119,6 +120,8 @@ class SceneTreeEditor : public Control { bool can_drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from) const; void drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from); + void _rmb_select(const Vector2& p_pos); + public: diff --git a/tools/editor/scenes_dock.cpp b/tools/editor/scenes_dock.cpp index c03142a3e7..e00f470bc4 100644 --- a/tools/editor/scenes_dock.cpp +++ b/tools/editor/scenes_dock.cpp @@ -36,7 +36,7 @@ #include "editor_node.h" #include "editor_settings.h" - +#include "scene/main/viewport.h" bool ScenesDock::_create_tree(TreeItem *p_parent,EditorFileSystemDirectory *p_dir) { @@ -151,6 +151,35 @@ void ScenesDock::_notification(int p_what) { switch(p_what) { + case NOTIFICATION_RESIZED: { + + + bool new_mode = get_size().height < get_viewport_rect().size.height*3/4; + + if (new_mode != split_mode ) { + + split_mode=new_mode; + + //print_line("SPLIT MODE? "+itos(split_mode)); + if (split_mode) { + + file_list_vb->hide(); + tree->set_v_size_flags(SIZE_EXPAND_FILL); + button_back->show(); + } else { + + tree->show(); + file_list_vb->show(); + tree->set_v_size_flags(SIZE_FILL); + button_back->hide(); + if (!EditorFileSystem::get_singleton()->is_scanning()) { + _fs_changed(); + } + } + } + + + } break; case NOTIFICATION_ENTER_TREE: { if (initialized) @@ -163,19 +192,20 @@ void ScenesDock::_notification(int p_what) { button_favorite->set_icon( get_icon("Favorites","EditorIcons")); button_fav_up->set_icon( get_icon("MoveUp","EditorIcons")); button_fav_down->set_icon( get_icon("MoveDown","EditorIcons")); - button_instance->set_icon( get_icon("Add","EditorIcons")); - button_open->set_icon( get_icon("Folder","EditorIcons")); + //button_instance->set_icon( get_icon("Add","EditorIcons")); + //button_open->set_icon( get_icon("Folder","EditorIcons")); button_back->set_icon( get_icon("Filesystem","EditorIcons")); display_mode->set_icon( get_icon("FileList","EditorIcons")); display_mode->connect("pressed",this,"_change_file_display"); - file_options->set_icon( get_icon("Tools","EditorIcons")); + //file_options->set_icon( get_icon("Tools","EditorIcons")); files->connect("item_activated",this,"_select_file"); button_hist_next->connect("pressed",this,"_fw_history"); button_hist_prev->connect("pressed",this,"_bw_history"); + search_button->set_icon( get_icon("Zoom","EditorIcons")); button_hist_next->set_icon( get_icon("Forward","EditorIcons")); button_hist_prev->set_icon( get_icon("Back","EditorIcons")); - file_options->get_popup()->connect("item_pressed",this,"_file_option"); + file_options->connect("item_pressed",this,"_file_option"); button_back->connect("pressed",this,"_go_to_tree",varray(),CONNECT_DEFERRED); @@ -195,6 +225,19 @@ void ScenesDock::_notification(int p_what) { case NOTIFICATION_EXIT_TREE: { } break; + case NOTIFICATION_DRAG_BEGIN: { + + Dictionary dd = get_viewport()->gui_get_drag_data(); + if (tree->is_visible() && dd.has("type") && ( + (String(dd["type"])=="files") || (String(dd["type"])=="files_and_dirs") || (String(dd["type"])=="resource"))) { + tree->set_drop_mode_flags(Tree::DROP_MODE_ON_ITEM); + } + } break; + case NOTIFICATION_DRAG_END: { + + tree->set_drop_mode_flags(0); + + } break; case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: { display_mode->set_pressed(int(EditorSettings::get_singleton()->get("file_dialog/display_mode"))==EditorFileDialog::DISPLAY_LIST); @@ -235,6 +278,11 @@ void ScenesDock::_dir_selected() { button_fav_up->set_disabled(true); button_fav_down->set_disabled(true); + + } + + if (!split_mode) { + _open_pressed(); //go directly to dir } } @@ -355,42 +403,26 @@ String ScenesDock::get_selected_path() const { return "res://"+path; } -void ScenesDock::_instance_pressed() { - if (tree_mode) - { - TreeItem *sel = tree->get_selected(); - if (!sel) - return; - String path = sel->get_metadata(0); - } - else - { - int idx = -1; - for (int i = 0; i<files->get_item_count(); i++) { - if (files->is_selected(i)) - { - idx = i; - break; - } - } +void ScenesDock::_thumbnail_done(const String& p_path,const Ref<Texture>& p_preview, const Variant& p_udata) { - if (idx<0) - return; + bool valid=false; - path = files->get_item_metadata(idx); + if (!search_box->is_hidden()) { + valid=true; + } else { + valid=(path==p_path.get_base_dir()); } - emit_signal("instance",path); -} - -void ScenesDock::_thumbnail_done(const String& p_path,const Ref<Texture>& p_preview, const Variant& p_udata) { - - if (p_preview.is_valid() && path==p_path.get_base_dir()) { + if (p_preview.is_valid() && valid) { - int idx=p_udata; + Array uarr=p_udata; + int idx=uarr[0]; + String file=uarr[1]; if (idx>=files->get_item_count()) return; + if (files->get_item_text(idx)!=file) + return; String fpath = files->get_item_metadata(idx); if (fpath!=p_path) return; @@ -412,6 +444,34 @@ void ScenesDock::_change_file_display() { _update_files(true); } +void ScenesDock::_search(EditorFileSystemDirectory *p_path,List<FileInfo>* matches,int p_max_items) { + + if (matches->size()>p_max_items) + return; + + for(int i=0;i<p_path->get_subdir_count();i++) { + _search(p_path->get_subdir(i),matches,p_max_items); + + } + + String match = search_box->get_text(); + + for(int i=0;i<p_path->get_file_count();i++) { + String file = p_path->get_file(i); + + if (file.find(match)!=-1) { + + FileInfo fi; + fi.name=file; + fi.type=p_path->get_file_type(i); + fi.path=p_path->get_file_path(i); + matches->push_back(fi); + if (matches->size()>p_max_items) + return; + } + } +} + void ScenesDock::_update_files(bool p_keep_selection) { Set<String> cselection; @@ -427,6 +487,9 @@ void ScenesDock::_update_files(bool p_keep_selection) { files->clear(); + current_path->set_text(path); + + EditorFileSystemDirectory *efd = EditorFileSystem::get_singleton()->get_path(path); if (!efd) return; @@ -436,6 +499,7 @@ void ScenesDock::_update_files(bool p_keep_selection) { Ref<Texture> file_thumbnail; bool use_thumbnails=!display_mode->is_pressed(); + bool use_folders = !search_box->is_visible() && split_mode; if (use_thumbnails) { //thumbnails @@ -477,59 +541,90 @@ void ScenesDock::_update_files(bool p_keep_selection) { } + if (use_folders) { - if (path!="res://") { + if (path!="res://") { - if (use_thumbnails) { - files->add_item("..",folder_thumbnail,true); - } else { - files->add_item("..",get_icon("folder","FileDialog"),true); + if (use_thumbnails) { + files->add_item("..",folder_thumbnail,true); + } else { + files->add_item("..",get_icon("folder","FileDialog"),true); + } + + String bd = path.get_base_dir(); + if (bd!="res://" && !bd.ends_with("/")) + bd+="/"; + + files->set_item_metadata(files->get_item_count()-1,bd); } - String bd = path.get_base_dir(); - if (bd!="res://" && !bd.ends_with("/")) - bd+="/"; + for(int i=0;i<efd->get_subdir_count();i++) { + + String dname=efd->get_subdir(i)->get_name(); + + + if (use_thumbnails) { + files->add_item(dname,folder_thumbnail,true); + } else { + files->add_item(dname,get_icon("folder","FileDialog"),true); + } - files->set_item_metadata(files->get_item_count()-1,bd); + files->set_item_metadata(files->get_item_count()-1,path.plus_file(dname)+"/"); + + if (cselection.has(dname)) + files->select(files->get_item_count()-1,false); + } } - for(int i=0;i<efd->get_subdir_count();i++) { - String dname=efd->get_subdir(i)->get_name(); + List<FileInfo> filelist; + if (search_box->is_visible()) { - if (use_thumbnails) { - files->add_item(dname,folder_thumbnail,true); - } else { - files->add_item(dname,get_icon("folder","FileDialog"),true); + if (search_box->get_text().length()>1) { + _search(EditorFileSystem::get_singleton()->get_filesystem(),&filelist,128); } - files->set_item_metadata(files->get_item_count()-1,path.plus_file(dname)+"/"); + filelist.sort(); + } else { - if (cselection.has(dname)) - files->select(files->get_item_count()-1,false); + for(int i=0;i<efd->get_file_count();i++) { + + FileInfo fi; + fi.name=efd->get_file(i); + fi.path=path.plus_file(fi.name); + fi.type=efd->get_file_type(i); + + filelist.push_back(fi); + } } - for(int i=0;i<efd->get_file_count();i++) { + StringName ei="EditorIcons"; //make it faster.. + StringName oi="Object"; - String fname=efd->get_file(i); - String fp = path.plus_file(fname); + for(List<FileInfo>::Element *E=filelist.front();E;E=E->next()) { + String fname=E->get().name; + String fp = E->get().path; + StringName type = E->get().type; - String type = efd->get_file_type(i); Ref<Texture> type_icon; - if (has_icon(type,"EditorIcons")) { - type_icon=get_icon(type,"EditorIcons"); + if (has_icon(type,ei)) { + type_icon=get_icon(type,ei); } else { - type_icon=get_icon("Object","EditorIcons"); + type_icon=get_icon(oi,ei); } if (use_thumbnails) { files->add_item(fname,file_thumbnail,true); files->set_item_metadata(files->get_item_count()-1,fp); files->set_item_tag_icon(files->get_item_count()-1,type_icon); - EditorResourcePreview::get_singleton()->queue_resource_preview(fp,this,"_thumbnail_done",files->get_item_count()-1); + Array udata; + udata.resize(2); + udata[0]=files->get_item_count()-1; + udata[1]=fname; + EditorResourcePreview::get_singleton()->queue_resource_preview(fp,this,"_thumbnail_done",udata); } else { files->add_item(fname,type_icon,true); files->set_item_metadata(files->get_item_count()-1,fp); @@ -547,25 +642,21 @@ void ScenesDock::_update_files(bool p_keep_selection) { void ScenesDock::_select_file(int p_idx) { files->select(p_idx,true); - _open_pressed(); + _file_option(FILE_OPEN); } void ScenesDock::_go_to_tree() { tree->show(); - files->hide(); - path_hb->hide(); + file_list_vb->hide(); _update_tree(); tree->grab_focus(); tree->ensure_cursor_is_visible(); button_favorite->show(); button_fav_up->show(); button_fav_down->show(); - button_open->hide(); - button_instance->hide(); - button_open->hide(); - file_options->hide(); - tree_mode=true; + //button_open->hide(); + //file_options->hide(); } void ScenesDock::_go_to_dir(const String& p_dir){ @@ -585,20 +676,18 @@ void ScenesDock::_fs_changed() { button_hist_prev->set_disabled(history_pos==0); button_hist_next->set_disabled(history_pos+1==history.size()); scanning_vb->hide(); + split_box->show(); - if (tree_mode) { - - tree->show(); + if (!tree->is_hidden()) { button_favorite->show(); button_fav_up->show(); button_fav_down->show(); _update_tree(); - } else { - files->show(); - path_hb->show(); - button_instance->show(); - button_open->show(); - file_options->show(); + + } + + if (!file_list_vb->is_hidden()) { + _update_files(true); } @@ -607,18 +696,10 @@ void ScenesDock::_fs_changed() { void ScenesDock::_set_scannig_mode() { - tree->hide(); - button_favorite->hide(); - button_fav_up->hide(); - button_fav_down->hide(); - button_instance->hide(); - button_open->hide(); - file_options->hide(); + split_box->hide(); button_hist_prev->set_disabled(true); button_hist_next->set_disabled(true); scanning_vb->show(); - path_hb->hide(); - files->hide(); set_process(true); if (EditorFileSystem::get_singleton()->is_scanning()) { scanning_progress->set_val(EditorFileSystem::get_singleton()->get_scanning_progress()*100); @@ -635,11 +716,14 @@ void ScenesDock::_fw_history() { path=history[history_pos]; - if (tree_mode) { + if (!tree->is_hidden()) { _update_tree(); tree->grab_focus(); tree->ensure_cursor_is_visible(); - } else { + + } + + if (!file_list_vb->is_hidden()) { _update_files(false); current_path->set_text(path); } @@ -656,11 +740,14 @@ void ScenesDock::_bw_history() { path=history[history_pos]; - if (tree_mode) { + + if (!tree->is_hidden()) { _update_tree(); tree->grab_focus(); tree->ensure_cursor_is_visible(); - } else { + } + + if (!file_list_vb->is_hidden()) { _update_files(false); current_path->set_text(path); } @@ -829,9 +916,17 @@ void ScenesDock::_move_operation(const String& p_to_path) { for(int i=0;i<move_dirs.size();i++) { - String to = p_to_path.plus_file(move_dirs[i].get_file()); - Error err = da->rename(move_dirs[i],to); - print_line("moving dir "+move_dirs[i]+" to "+to); + String mdir = move_dirs[i]; + if (mdir=="res://") + continue; + + if (mdir.ends_with("/")) { + mdir=mdir.substr(0,mdir.length()-1); + } + + String to = p_to_path.plus_file(mdir.get_file()); + Error err = da->rename(mdir,to); + print_line("moving dir "+mdir+" to "+to); if (err!=OK) { EditorNode::get_singleton()->add_io_error("Error moving dir:\n"+move_dirs[i]+"\n"); } @@ -848,6 +943,52 @@ void ScenesDock::_file_option(int p_option) { switch(p_option) { + + case FILE_OPEN: { + int idx=-1; + for(int i=0;i<files->get_item_count();i++) { + if (files->is_selected(i)) { + idx=i; + break; + } + } + + if (idx<0) + return; + + + + String path = files->get_item_metadata(idx); + + if (path.ends_with("/")) { + if (path!="res://") { + path=path.substr(0,path.length()-1); + } + this->path=path; + _update_files(false); + current_path->set_text(path); + _push_to_history(); + } else { + + if (ResourceLoader::get_resource_type(path)=="PackedScene") { + + editor->open_request(path); + } else { + + editor->load_resource(path); + } + } + } break; + case FILE_INSTANCE: { + + for (int i = 0; i<files->get_item_count(); i++) { + + String path =files->get_item_metadata(i); + if (EditorFileSystem::get_singleton()->get_file_type(path)=="PackedScene") { + emit_signal("instance",path); + } + } + } break; case FILE_DEPENDENCIES: { int idx = files->get_current(); @@ -937,77 +1078,63 @@ void ScenesDock::_file_option(int p_option) { void ScenesDock::_open_pressed(){ - if (tree_mode) { - - TreeItem *sel = tree->get_selected(); - if (!sel) { - return; - } - path = sel->get_metadata(0); - /*if (path!="res://" && path.ends_with("/")) { - path=path.substr(0,path.length()-1); - }*/ + TreeItem *sel = tree->get_selected(); + if (!sel) { + return; + } + path = sel->get_metadata(0); + /*if (path!="res://" && path.ends_with("/")) { + path=path.substr(0,path.length()-1); + }*/ - tree_mode=false; + //tree_mode=false; + if (split_mode) { tree->hide(); - files->show(); - path_hb->show(); + file_list_vb->show(); button_favorite->hide(); button_fav_up->hide(); button_fav_down->hide(); - button_instance->show(); - button_open->show(); - file_options->show(); - - _update_files(false); - - current_path->set_text(path); - - _push_to_history(); + } + //file_options->show(); - } else { - - int idx=-1; - for(int i=0;i<files->get_item_count();i++) { - if (files->is_selected(i)) { - idx=i; - break; - } - } + _update_files(false); + current_path->set_text(path); + _push_to_history(); - if (idx<0) - return; +// emit_signal("open",path); +} +void ScenesDock::_search_toggled(){ - String path = files->get_item_metadata(idx); + if (search_button->is_pressed()) { + //search_box->clear(); + search_box->select_all(); + search_box->show(); + current_path->hide(); + search_box->grab_focus(); - if (path.ends_with("/")) { - if (path!="res://") { - path=path.substr(0,path.length()-1); - } - this->path=path; - _update_files(false); - current_path->set_text(path); - _push_to_history(); - } else { + _update_files(false); + } else { - if (ResourceLoader::get_resource_type(path)=="PackedScene") { + //search_box->clear(); + search_box->hide(); + current_path->show(); - editor->open_request(path); - } else { + _update_files(false); - editor->load_resource(path); - } - } } +} -// emit_signal("open",path); +void ScenesDock::_search_changed(const String& p_text) { -} + if (!search_box->is_visible()) + return; //wtf + _update_files(false); +} void ScenesDock::_rescan() { @@ -1020,51 +1147,8 @@ void ScenesDock::fix_dependencies(const String& p_for_file) { deps_editor->edit(p_for_file); } -void ScenesDock::open(const String& p_path) { - - String npath; - String nfile; - - if (p_path.ends_with("/")) { - - if (p_path!="res://") - npath=p_path.substr(0,p_path.length()-1); - else - npath="res://"; - } else { - nfile=p_path.get_file(); - npath=p_path.get_base_dir(); - } - - path=npath; - - if (tree_mode && nfile=="") { - _update_tree(); - tree->grab_focus(); - tree->call_deferred("ensure_cursor_is_visible"); - _push_to_history(); - return; - } else if (tree_mode){ - _update_tree(); - tree->grab_focus(); - tree->ensure_cursor_is_visible(); - _open_pressed(); - current_path->set_text(path); - } else { - _update_files(false); - _push_to_history(); - } - - for(int i=0;i<files->get_item_count();i++) { - - String md = files->get_item_metadata(i); - if (md==p_path) { - files->select(i,true); - files->ensure_current_is_visible(); - break; - } - } +void ScenesDock::focus_on_filter() { } @@ -1076,6 +1160,23 @@ void ScenesDock::set_use_thumbnails(bool p_use) { Variant ScenesDock::get_drag_data_fw(const Point2& p_point,Control* p_from) { + if (p_from==tree) { + + TreeItem *selected = tree->get_selected(); + if (!selected) + return Variant(); + + String path = selected->get_metadata(0); + if (path==String()) + return Variant(); + if (!path.ends_with("/")) + path=path+"/"; + Vector<String> paths; + paths.push_back(path); + return EditorNode::get_singleton()->drag_files(paths,p_from); + + } + if (p_from==files) { List<int> seldirs; @@ -1150,6 +1251,20 @@ bool ScenesDock::can_drop_data_fw(const Point2& p_point,const Variant& p_data,Co return true; } } + + if (p_from==tree) { + + TreeItem *ti = tree->get_item_at_pos(p_point); + if (!ti) + return false; + String path = ti->get_metadata(0); + + if (path==String()) + return false; + + return true; + } + } return false; @@ -1168,53 +1283,150 @@ void ScenesDock::drop_data_fw(const Point2& p_point,const Variant& p_data,Contro return; } - String save_path=path; - int at_pos = files->get_item_at_pos(p_point); - if (at_pos!=-1) { - String to_dir = files->get_item_metadata(at_pos); - if (to_dir.ends_with("/")) { - save_path=to_dir; - if (save_path!="res://") - save_path=save_path.substr(0,save_path.length()-1); - } + if (p_from==tree) { + + TreeItem *ti = tree->get_item_at_pos(p_point); + if (!ti) + return; + String path = ti->get_metadata(0); + + if (path==String()) + return; + + EditorNode::get_singleton()->save_resource_as(res,path); + return; } - EditorNode::get_singleton()->save_resource_as(res,save_path); - return; + if (p_from==files) { + String save_path=path; + + int at_pos = files->get_item_at_pos(p_point); + if (at_pos!=-1) { + String to_dir = files->get_item_metadata(at_pos); + if (to_dir.ends_with("/")) { + save_path=to_dir; + if (save_path!="res://") + save_path=save_path.substr(0,save_path.length()-1); + } + + } + + EditorNode::get_singleton()->save_resource_as(res,save_path); + return; + } } if (drag_data.has("type") && ( String(drag_data["type"])=="files" || String(drag_data["type"])=="files_and_dirs")) { - int at_pos = files->get_item_at_pos(p_point); - ERR_FAIL_COND(at_pos==-1); - String to_dir = files->get_item_metadata(at_pos); - ERR_FAIL_COND(!to_dir.ends_with("/")); + if (p_from==files || p_from==tree) { - Vector<String> fnames = drag_data["files"]; - move_files.clear(); - move_dirs.clear(); - - for(int i=0;i<fnames.size();i++) { - if (fnames[i].ends_with("/")) - move_dirs.push_back(fnames[i]); - else - move_files.push_back(fnames[i]); - } + String to_dir; + + if (p_from==files) { - _move_operation(to_dir); + int at_pos = files->get_item_at_pos(p_point); + ERR_FAIL_COND(at_pos==-1); + String to_dir = files->get_item_metadata(at_pos); + } else { + TreeItem *ti = tree->get_item_at_pos(p_point); + if (!ti) + return; + to_dir = ti->get_metadata(0); + ERR_FAIL_COND(to_dir==String()); + + } + + if (to_dir!="res://" && to_dir.ends_with("/")) { + to_dir=to_dir.substr(0,to_dir.length()-1); + } + + Vector<String> fnames = drag_data["files"]; + move_files.clear(); + move_dirs.clear(); + + for(int i=0;i<fnames.size();i++) { + if (fnames[i].ends_with("/")) + move_dirs.push_back(fnames[i]); + else + move_files.push_back(fnames[i]); + } + + _move_operation(to_dir); + } } } +void ScenesDock::_files_list_rmb_select(int p_item,const Vector2& p_pos) { + + Vector<String> filenames; + + bool all_scenes=true; + + for(int i=0;i<files->get_item_count();i++) { + + if (!files->is_selected(i)) + continue; + + String path = files->get_item_metadata(i); + + if (files->get_item_text(i)=="..") { + // no operate on .. + return; + } + + if (path.ends_with("/")) { + //no operate on dirs + return; + } + + + filenames.push_back(path); + if (EditorFileSystem::get_singleton()->get_file_type(path)!="PackedScene") + all_scenes=false; + } + + + if (filenames.size()==0) + return; + + file_options->clear(); + file_options->set_size(Size2(1,1)); + + file_options->add_item(TTR("Open"),FILE_OPEN); + if (all_scenes) { + file_options->add_item(TTR("Instance"),FILE_INSTANCE); + } + + file_options->add_separator(); + + if (filenames.size()==1) { + file_options->add_item(TTR("Edit Dependencies.."),FILE_DEPENDENCIES); + file_options->add_item(TTR("View Owners.."),FILE_OWNERS); + file_options->add_separator(); + } + + if (filenames.size()==1) { + file_options->add_item(TTR("Rename or Move.."),FILE_MOVE); + } else { + file_options->add_item(TTR("Move To.."),FILE_MOVE); + } + + file_options->add_item(TTR("Delete"),FILE_REMOVE); + //file_options->add_item(TTR("Info"),FILE_INFO); + file_options->set_pos(files->get_global_pos() + p_pos); + file_options->popup(); + +} void ScenesDock::_bind_methods() { ObjectTypeDB::bind_method(_MD("_update_tree"),&ScenesDock::_update_tree); ObjectTypeDB::bind_method(_MD("_rescan"),&ScenesDock::_rescan); ObjectTypeDB::bind_method(_MD("_favorites_pressed"),&ScenesDock::_favorites_pressed); - ObjectTypeDB::bind_method(_MD("_instance_pressed"),&ScenesDock::_instance_pressed); +// ObjectTypeDB::bind_method(_MD("_instance_pressed"),&ScenesDock::_instance_pressed); ObjectTypeDB::bind_method(_MD("_open_pressed"),&ScenesDock::_open_pressed); ObjectTypeDB::bind_method(_MD("_thumbnail_done"),&ScenesDock::_thumbnail_done); @@ -1231,10 +1443,13 @@ void ScenesDock::_bind_methods() { ObjectTypeDB::bind_method(_MD("_file_option"), &ScenesDock::_file_option); ObjectTypeDB::bind_method(_MD("_move_operation"), &ScenesDock::_move_operation); ObjectTypeDB::bind_method(_MD("_rename_operation"), &ScenesDock::_rename_operation); + ObjectTypeDB::bind_method(_MD("_search_toggled"), &ScenesDock::_search_toggled); + ObjectTypeDB::bind_method(_MD("_search_changed"), &ScenesDock::_search_changed); ObjectTypeDB::bind_method(_MD("get_drag_data_fw"), &ScenesDock::get_drag_data_fw); ObjectTypeDB::bind_method(_MD("can_drop_data_fw"), &ScenesDock::can_drop_data_fw); ObjectTypeDB::bind_method(_MD("drop_data_fw"), &ScenesDock::drop_data_fw); + ObjectTypeDB::bind_method(_MD("_files_list_rmb_select"),&ScenesDock::_files_list_rmb_select); ADD_SIGNAL(MethodInfo("instance")); ADD_SIGNAL(MethodInfo("open")); @@ -1245,6 +1460,7 @@ ScenesDock::ScenesDock(EditorNode *p_editor) { editor=p_editor; + HBoxContainer *toolbar_hbc = memnew( HBoxContainer ); add_child(toolbar_hbc); @@ -1294,7 +1510,7 @@ ScenesDock::ScenesDock(EditorNode *p_editor) { button_fav_up->set_focus_mode(FOCUS_NONE); button_fav_down->set_focus_mode(FOCUS_NONE); - +/* button_open = memnew( Button ); button_open->set_flat(true); button_open->connect("pressed",this,"_open_pressed"); @@ -1312,26 +1528,23 @@ ScenesDock::ScenesDock(EditorNode *p_editor) { button_instance->set_focus_mode(FOCUS_NONE); button_instance->set_tooltip(TTR("Instance the selected scene(s) as child of the selected node.")); +*/ + file_options = memnew( PopupMenu ); + add_child(file_options); - file_options = memnew( MenuButton ); - toolbar_hbc->add_child(file_options); - file_options->get_popup()->add_item(TTR("Rename or Move"),FILE_MOVE); - file_options->get_popup()->add_item(TTR("Delete"),FILE_REMOVE); - file_options->get_popup()->add_separator(); - file_options->get_popup()->add_item(TTR("Edit Dependencies"),FILE_DEPENDENCIES); - file_options->get_popup()->add_item(TTR("View Owners"),FILE_OWNERS); - //file_options->get_popup()->add_item(TTR("Info"),FILE_INFO); - file_options->hide(); - file_options->set_focus_mode(FOCUS_NONE); - file_options->set_tooltip(TTR("Miscenaneous options related to resources on disk.")); + split_box = memnew( VSplitContainer ); + add_child(split_box); + split_box->set_v_size_flags(SIZE_EXPAND_FILL); tree = memnew( Tree ); tree->set_hide_root(true); - add_child(tree); + split_box->add_child(tree); + tree->set_custom_minimum_size(Size2(0,200)); + tree->set_drag_forwarding(this); - tree->set_v_size_flags(SIZE_EXPAND_FILL); + //tree->set_v_size_flags(SIZE_EXPAND_FILL); tree->connect("item_edited",this,"_favorite_toggled"); tree->connect("item_activated",this,"_open_pressed"); tree->connect("cell_selected",this,"_dir_selected"); @@ -1340,22 +1553,40 @@ ScenesDock::ScenesDock(EditorNode *p_editor) { files->set_v_size_flags(SIZE_EXPAND_FILL); files->set_select_mode(ItemList::SELECT_MULTI); files->set_drag_forwarding(this); + files->connect("item_rmb_selected",this,"_files_list_rmb_select"); + files->set_allow_rmb_select(true); + + file_list_vb = memnew( VBoxContainer ); + split_box->add_child(file_list_vb); + file_list_vb->set_v_size_flags(SIZE_EXPAND_FILL); path_hb = memnew( HBoxContainer ); + file_list_vb->add_child(path_hb); + button_back = memnew( ToolButton ); path_hb->add_child(button_back); + button_back->hide(); current_path=memnew( LineEdit ); current_path->set_h_size_flags(SIZE_EXPAND_FILL); path_hb->add_child(current_path); + + search_box = memnew( LineEdit ); + search_box->set_h_size_flags(SIZE_EXPAND_FILL); + path_hb->add_child(search_box); + search_box->hide(); + search_box->connect("text_changed",this,"_search_changed"); + + search_button = memnew( ToolButton ); + path_hb->add_child(search_button); + search_button->set_toggle_mode(true ); + search_button->connect("pressed",this,"_search_toggled"); + display_mode = memnew( ToolButton ); path_hb->add_child(display_mode); display_mode->set_toggle_mode(true); - add_child(path_hb); - path_hb->hide(); + file_list_vb->add_child(files); - add_child(files); - files->hide(); scanning_vb = memnew( VBoxContainer ); Label *slabel = memnew( Label ); @@ -1393,7 +1624,8 @@ ScenesDock::ScenesDock(EditorNode *p_editor) { history.push_back("res://"); history_pos=0; - tree_mode=true; + + split_mode=false; path="res://"; diff --git a/tools/editor/scenes_dock.h b/tools/editor/scenes_dock.h index 86196b7ccd..327e5a25f0 100644 --- a/tools/editor/scenes_dock.h +++ b/tools/editor/scenes_dock.h @@ -39,6 +39,7 @@ #include "scene/gui/menu_button.h" #include "scene/gui/item_list.h" #include "scene/gui/progress_bar.h" +#include "scene/gui/split_container.h" #include "os/dir_access.h" #include "os/thread.h" @@ -54,6 +55,8 @@ class ScenesDock : public VBoxContainer { OBJ_TYPE( ScenesDock, VBoxContainer ); enum FileMenu { + FILE_OPEN, + FILE_INSTANCE, FILE_DEPENDENCIES, FILE_OWNERS, FILE_MOVE, @@ -65,25 +68,28 @@ class ScenesDock : public VBoxContainer { VBoxContainer *scanning_vb; ProgressBar *scanning_progress; + VSplitContainer *split_box; + VBoxContainer *file_list_vb; EditorNode *editor; Set<String> favorites; Button *button_reload; - Button *button_instance; Button *button_favorite; Button *button_fav_up; Button *button_fav_down; - Button *button_open; Button *button_back; Button *display_mode; Button *button_hist_next; Button *button_hist_prev; LineEdit *current_path; + LineEdit *search_box; + Button *search_button; HBoxContainer *path_hb; - MenuButton *file_options; + bool split_mode; + PopupMenu *file_options; DependencyEditor *deps_editor; DependencyEditorOwners *owners_editor; @@ -107,8 +113,6 @@ class ScenesDock : public VBoxContainer { Tree * tree; //directories ItemList *files; - bool tree_mode; - void _go_to_tree(); void _go_to_dir(const String& p_dir); void _select_file(int p_idx); @@ -131,6 +135,7 @@ class ScenesDock : public VBoxContainer { void _bw_history(); void _push_to_history(); + void _fav_up_pressed(); void _fav_down_pressed(); void _dir_selected(); @@ -138,9 +143,27 @@ class ScenesDock : public VBoxContainer { void _rescan(); void _set_scannig_mode(); + void _favorites_pressed(); - void _instance_pressed(); void _open_pressed(); + void _search_toggled(); + void _search_changed(const String& p_text); + + + void _files_list_rmb_select(int p_item,const Vector2& p_pos); + + + struct FileInfo { + String name; + String path; + StringName type; + + bool operator<(const FileInfo& fi) const { + return name < fi.name; + } + }; + + void _search(EditorFileSystemDirectory *p_path, List<FileInfo>* matches, int p_max_items); Variant get_drag_data_fw(const Point2& p_point,Control* p_from); bool can_drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from) const; @@ -152,7 +175,7 @@ protected: public: String get_selected_path() const; - void open(const String& p_path); + void focus_on_filter(); void fix_dependencies(const String& p_for_file); |