diff options
Diffstat (limited to 'scene')
-rw-r--r-- | scene/2d/animated_sprite.cpp | 448 | ||||
-rw-r--r-- | scene/2d/animated_sprite.h | 79 | ||||
-rw-r--r-- | scene/2d/visibility_notifier_2d.cpp | 24 | ||||
-rw-r--r-- | scene/2d/visibility_notifier_2d.h | 1 | ||||
-rw-r--r-- | scene/3d/sprite_3d.cpp | 14 | ||||
-rw-r--r-- | scene/3d/sprite_3d.h | 3 | ||||
-rw-r--r-- | scene/gui/item_list.cpp | 140 | ||||
-rw-r--r-- | scene/gui/item_list.h | 12 | ||||
-rw-r--r-- | scene/gui/line_edit.cpp | 117 | ||||
-rw-r--r-- | scene/gui/line_edit.h | 28 | ||||
-rw-r--r-- | scene/gui/margin_container.cpp | 24 | ||||
-rw-r--r-- | scene/gui/text_edit.cpp | 66 | ||||
-rw-r--r-- | scene/gui/text_edit.h | 18 | ||||
-rw-r--r-- | scene/gui/tree.cpp | 69 | ||||
-rw-r--r-- | scene/gui/tree.h | 9 | ||||
-rw-r--r-- | scene/resources/default_theme/default_theme.cpp | 5 | ||||
-rw-r--r-- | scene/scene_string_names.cpp | 2 | ||||
-rw-r--r-- | scene/scene_string_names.h | 1 |
18 files changed, 932 insertions, 128 deletions
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/line_edit.cpp b/scene/gui/line_edit.cpp index 21dee62b38..14dac454bd 100644 --- a/scene/gui/line_edit.cpp +++ b/scene/gui/line_edit.cpp @@ -41,7 +41,15 @@ void LineEdit::_input_event(InputEvent p_event) { const InputEventMouseButton &b = p_event.mouse_button; - if (b.button_index!=1) + if (b.pressed && b.button_index==BUTTON_RIGHT) { + menu->set_pos(get_global_transform().xform(get_local_mouse_pos())); + menu->set_size(Vector2(1,1)); + menu->popup(); + grab_focus(); + return; + } + + if (b.button_index!=BUTTON_LEFT) break; if (b.pressed) { @@ -143,24 +151,10 @@ void LineEdit::_input_event(InputEvent p_event) { if( k.mod.command && editable) { - int old_cursor_pos = cursor_pos; - text = undo_text; - - Ref<Font> font = get_font("font"); - - cached_width = 0; - for (int i = 0; i<text.length(); i++) - cached_width += font->get_char_size(text[i]).width; + undo(); - if(old_cursor_pos > text.length()) { - set_cursor_pos(text.length()); - } else { - set_cursor_pos(old_cursor_pos); - } } - emit_signal("text_changed",text); - _change_notify("text"); } break; @@ -559,6 +553,28 @@ void LineEdit::paste_text() { } +void LineEdit::undo() { + + int old_cursor_pos = cursor_pos; + text = undo_text; + + Ref<Font> font = get_font("font"); + + cached_width = 0; + for (int i = 0; i<text.length(); i++) + cached_width += font->get_char_size(text[i]).width; + + if(old_cursor_pos > text.length()) { + set_cursor_pos(text.length()); + } else { + set_cursor_pos(old_cursor_pos); + } + + emit_signal("text_changed",text); + _change_notify("text"); + +} + void LineEdit::shift_selection_check_pre(bool p_shift) { if (!selection.old_shift && p_shift) { @@ -669,6 +685,8 @@ void LineEdit::set_text(String p_text) { void LineEdit::clear() { clear_internal(); + emit_signal("text_changed",text); + _change_notify("text"); } String LineEdit::get_text() const { @@ -932,6 +950,39 @@ bool LineEdit::is_text_field() const { return true; } +void LineEdit::menu_option(int p_option) { + + switch(p_option) { + case MENU_CUT: { + cut_text(); + } break; + case MENU_COPY: { + + copy_text(); + } break; + case MENU_PASTE: { + + paste_text(); + } break; + case MENU_CLEAR: { + clear(); + } break; + case MENU_SELECT_ALL: { + select_all(); + } break; + case MENU_UNDO: { + + undo(); + } break; + + } + +} + +PopupMenu *LineEdit::get_menu() const { + return menu; +} + void LineEdit::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_align", "align"), &LineEdit::set_align); @@ -952,6 +1003,8 @@ void LineEdit::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_secret","enabled"),&LineEdit::set_secret); ObjectTypeDB::bind_method(_MD("is_secret"),&LineEdit::is_secret); ObjectTypeDB::bind_method(_MD("select","from","to"),&LineEdit::select,DEFVAL(0),DEFVAL(-1)); + ObjectTypeDB::bind_method(_MD("menu_option","option"),&LineEdit::menu_option); + ObjectTypeDB::bind_method(_MD("get_menu:PopupMenu"),&LineEdit::get_menu); ADD_SIGNAL( MethodInfo("text_changed", PropertyInfo( Variant::STRING, "text" )) ); ADD_SIGNAL( MethodInfo("text_entered", PropertyInfo( Variant::STRING, "text" )) ); @@ -961,11 +1014,21 @@ void LineEdit::_bind_methods() { BIND_CONSTANT(ALIGN_RIGHT); BIND_CONSTANT(ALIGN_FILL); - ADD_PROPERTY( PropertyInfo( Variant::STRING, "text" ), _SCS("set_text"),_SCS("get_text") ); + BIND_CONSTANT( MENU_CUT ); + BIND_CONSTANT( MENU_COPY ); + BIND_CONSTANT( MENU_PASTE ); + BIND_CONSTANT( MENU_CLEAR ); + BIND_CONSTANT( MENU_SELECT_ALL ); + BIND_CONSTANT( MENU_UNDO ); + BIND_CONSTANT( MENU_MAX ); + + ADD_PROPERTYNZ( PropertyInfo( Variant::STRING, "text" ), _SCS("set_text"),_SCS("get_text") ); ADD_PROPERTYNZ(PropertyInfo(Variant::INT, "align", PROPERTY_HINT_ENUM, "Left,Center,Right,Fill"), _SCS("set_align"), _SCS("get_align")); - ADD_PROPERTY( PropertyInfo( Variant::INT, "max_length" ), _SCS("set_max_length"),_SCS("get_max_length") ); - ADD_PROPERTY( PropertyInfo( Variant::BOOL, "editable" ), _SCS("set_editable"),_SCS("is_editable") ); - ADD_PROPERTY( PropertyInfo( Variant::BOOL, "secret" ), _SCS("set_secret"),_SCS("is_secret") ); + ADD_PROPERTYNZ( PropertyInfo( Variant::INT, "max_length" ), _SCS("set_max_length"),_SCS("get_max_length") ); + ADD_PROPERTYNO( PropertyInfo( Variant::BOOL, "editable" ), _SCS("set_editable"),_SCS("is_editable") ); + ADD_PROPERTYNZ( PropertyInfo( Variant::BOOL, "secret" ), _SCS("set_secret"),_SCS("is_secret") ); + + } LineEdit::LineEdit() { @@ -984,6 +1047,20 @@ LineEdit::LineEdit() { set_stop_mouse(true); + menu = memnew( PopupMenu ); + add_child(menu); + menu->add_item(TTR("Cut"),MENU_CUT,KEY_MASK_CMD|KEY_X); + menu->add_item(TTR("Copy"),MENU_COPY,KEY_MASK_CMD|KEY_C); + menu->add_item(TTR("Paste"),MENU_PASTE,KEY_MASK_CMD|KEY_V); + menu->add_separator(); + menu->add_item(TTR("Select All"),MENU_SELECT_ALL,KEY_MASK_CMD|KEY_A); + menu->add_item(TTR("Clear"),MENU_CLEAR); + menu->add_separator(); + menu->add_item(TTR("Undo"),MENU_UNDO,KEY_MASK_CMD|KEY_Z); + menu->connect("item_pressed",this,"menu_option"); + + + } LineEdit::~LineEdit() { diff --git a/scene/gui/line_edit.h b/scene/gui/line_edit.h index 207c6b115b..586a54e950 100644 --- a/scene/gui/line_edit.h +++ b/scene/gui/line_edit.h @@ -30,6 +30,8 @@ #define LINE_EDIT_H #include "scene/gui/control.h" +#include "scene/gui/popup_menu.h" + /** @author Juan Linietsky <reduzio@gmail.com> */ @@ -45,6 +47,18 @@ public: ALIGN_RIGHT, ALIGN_FILL }; + + enum MenuItems { + MENU_CUT, + MENU_COPY, + MENU_PASTE, + MENU_CLEAR, + MENU_SELECT_ALL, + MENU_UNDO, + MENU_MAX + + }; + private: Align align; @@ -54,6 +68,8 @@ private: String undo_text; String text; + PopupMenu *menu; + int cursor_pos; int window_pos; int max_length; // 0 for no maximum @@ -85,14 +101,12 @@ private: void clear_internal(); void changed_internal(); - void copy_text(); - void cut_text(); - void paste_text(); void _input_event(InputEvent p_event); void _notification(int p_what); + protected: static void _bind_methods(); public: @@ -103,6 +117,8 @@ public: virtual bool can_drop_data(const Point2& p_point,const Variant& p_data) const; virtual void drop_data(const Point2& p_point,const Variant& p_data); + void menu_option(int p_option); + PopupMenu *get_menu() const; void select_all(); @@ -116,6 +132,10 @@ public: void append_at_cursor(String p_text); void clear(); + void copy_text(); + void cut_text(); + void paste_text(); + void undo(); void set_editable(bool p_editable); bool is_editable() const; @@ -127,7 +147,7 @@ public: virtual Size2 get_minimum_size() const; - virtual bool is_text_field() const; + virtual bool is_text_field() const; LineEdit(); ~LineEdit(); diff --git a/scene/gui/margin_container.cpp b/scene/gui/margin_container.cpp index fde5df6b72..5f798f445c 100644 --- a/scene/gui/margin_container.cpp +++ b/scene/gui/margin_container.cpp @@ -31,7 +31,10 @@ Size2 MarginContainer::get_minimum_size() const { - int margin = get_constant("margin"); + int margin_left = get_constant("margin_left"); + int margin_top = get_constant("margin_top"); + int margin_right = get_constant("margin_right"); + int margin_bottom = get_constant("margin_bottom"); Size2 max; @@ -52,9 +55,10 @@ Size2 MarginContainer::get_minimum_size() const { max.height = s.height; } - max.width += margin; - return max; + max.width += (margin_left + margin_right); + max.height += (margin_top + margin_bottom); + return max; } @@ -62,7 +66,10 @@ void MarginContainer::_notification(int p_what) { if (p_what==NOTIFICATION_SORT_CHILDREN) { - int margin = get_constant("margin"); + int margin_left = get_constant("margin_left"); + int margin_top = get_constant("margin_top"); + int margin_right = get_constant("margin_right"); + int margin_bottom = get_constant("margin_bottom"); Size2 s = get_size(); @@ -73,13 +80,10 @@ void MarginContainer::_notification(int p_what) { continue; if (c->is_set_as_toplevel()) continue; - int w; - if (c->get_h_size_flags() & Control::SIZE_EXPAND) - w=s.width-margin; - else - w=c->get_combined_minimum_size().width; - fit_child_in_rect(c,Rect2(margin,0,s.width-margin,s.height)); + int w=s.width-margin_left-margin_right; + int h=s.height-margin_top-margin_bottom; + fit_child_in_rect(c,Rect2(margin_left,margin_top,w,h)); } } diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index 8df0c6d254..1ddf614ec4 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -1518,6 +1518,15 @@ void TextEdit::_input_event(const InputEvent& p_input_event) { update(); } + + if (mb.button_index==BUTTON_RIGHT) { + + menu->set_pos(get_global_transform().xform(get_local_mouse_pos())); + menu->set_size(Vector2(1,1)); + menu->popup(); + grab_focus(); + + } } else { if (mb.button_index==BUTTON_LEFT) @@ -4146,6 +4155,38 @@ bool TextEdit::is_text_field() const { return true; } + +void TextEdit::menu_option(int p_option) { + + switch( p_option ) { + case MENU_CUT: { + + cut(); + } break; + case MENU_COPY: { + copy(); + } break; + case MENU_PASTE: { + + paste(); + } break; + case MENU_CLEAR: { + clear(); + } break; + case MENU_SELECT_ALL: { + select_all(); + } break; + case MENU_UNDO: { + undo(); + } break; + + }; +} + +PopupMenu *TextEdit::get_menu() const { + return menu; +} + void TextEdit::_bind_methods() { @@ -4215,6 +4256,8 @@ void TextEdit::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_symbol_color","color"),&TextEdit::set_symbol_color); ObjectTypeDB::bind_method(_MD("set_custom_bg_color","color"),&TextEdit::set_custom_bg_color); ObjectTypeDB::bind_method(_MD("clear_colors"),&TextEdit::clear_colors); + ObjectTypeDB::bind_method(_MD("menu_option"),&TextEdit::menu_option); + ObjectTypeDB::bind_method(_MD("get_menu:PopupMenu"),&TextEdit::get_menu); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "caret/caret_blink"), _SCS("cursor_set_blink_enabled"), _SCS("cursor_get_blink_enabled"));; ADD_PROPERTYNZ(PropertyInfo(Variant::REAL, "caret/caret_blink_speed",PROPERTY_HINT_RANGE,"0.1,10,0.1"), _SCS("cursor_set_blink_speed"),_SCS("cursor_get_blink_speed") ); @@ -4223,6 +4266,15 @@ void TextEdit::_bind_methods() { ADD_SIGNAL(MethodInfo("text_changed")); ADD_SIGNAL(MethodInfo("request_completion")); + BIND_CONSTANT( MENU_CUT ); + BIND_CONSTANT( MENU_COPY ); + BIND_CONSTANT( MENU_PASTE ); + BIND_CONSTANT( MENU_CLEAR ); + BIND_CONSTANT( MENU_SELECT_ALL ); + BIND_CONSTANT( MENU_UNDO ); + BIND_CONSTANT( MENU_MAX ); + + } TextEdit::TextEdit() { @@ -4327,6 +4379,20 @@ TextEdit::TextEdit() { brace_matching_enabled=false; auto_indent=false; insert_mode = false; + + menu = memnew( PopupMenu ); + add_child(menu); + menu->add_item(TTR("Cut"),MENU_CUT,KEY_MASK_CMD|KEY_X); + menu->add_item(TTR("Copy"),MENU_COPY,KEY_MASK_CMD|KEY_C); + menu->add_item(TTR("Paste"),MENU_PASTE,KEY_MASK_CMD|KEY_V); + menu->add_separator(); + menu->add_item(TTR("Select All"),MENU_SELECT_ALL,KEY_MASK_CMD|KEY_A); + menu->add_item(TTR("Clear"),MENU_CLEAR); + menu->add_separator(); + menu->add_item(TTR("Undo"),MENU_UNDO,KEY_MASK_CMD|KEY_Z); + menu->connect("item_pressed",this,"menu_option"); + + } TextEdit::~TextEdit() diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h index ea4f148e91..dbe6293240 100644 --- a/scene/gui/text_edit.h +++ b/scene/gui/text_edit.h @@ -31,6 +31,7 @@ #include "scene/gui/control.h" #include "scene/gui/scroll_bar.h" +#include "scene/gui/popup_menu.h" #include "scene/main/timer.h" @@ -290,6 +291,8 @@ class TextEdit : public Control { DVector<int> _search_bind(const String &p_key,uint32_t p_search_flags, int p_from_line,int p_from_column) const; + PopupMenu *menu; + void _clear(); void _cancel_completion(); void _cancel_code_hint(); @@ -317,6 +320,17 @@ protected: public: + enum MenuItems { + MENU_CUT, + MENU_COPY, + MENU_PASTE, + MENU_CLEAR, + MENU_SELECT_ALL, + MENU_UNDO, + MENU_MAX + + }; + enum SearchFlags { SEARCH_MATCH_CASE=1, @@ -433,6 +447,8 @@ public: uint32_t get_saved_version() const; void tag_saved_version(); + void menu_option(int p_option); + void set_show_line_numbers(bool p_show); void set_tooltip_request_func(Object *p_obj, const StringName& p_function, const Variant& p_udata); @@ -442,6 +458,8 @@ public: void set_code_hint(const String& p_hint); void query_code_comple(); + PopupMenu *get_menu() const; + String get_text_for_completion(); virtual bool is_text_field() const; diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp index 062a377cee..2c39aea08c 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) { @@ -2375,8 +2389,12 @@ void Tree::_input_event(InputEvent p_event) { } } - if (!root) + if (!root || (!root->get_children() && hide_root)) { + if (b.button_index==BUTTON_RIGHT && allow_rmb_select) { + emit_signal("empty_tree_rmb_selected",get_local_mouse_pos()); + } break; + } click_handled=false; pressing_for_editor=false; @@ -2390,6 +2408,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 +3476,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,10 +3547,18 @@ 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("cell_selected")); ADD_SIGNAL( MethodInfo("multi_selected",PropertyInfo(Variant::OBJECT,"item"),PropertyInfo(Variant::INT,"column"),PropertyInfo(Variant::BOOL,"selected")) ); + ADD_SIGNAL( MethodInfo("item_rmb_selected",PropertyInfo(Variant::VECTOR2,"pos"))); + ADD_SIGNAL( MethodInfo("empty_tree_rmb_selected",PropertyInfo(Variant::VECTOR2,"pos"))); ADD_SIGNAL( MethodInfo("item_edited")); ADD_SIGNAL( MethodInfo("item_collapsed",PropertyInfo(Variant::OBJECT,"item"))); //ADD_SIGNAL( MethodInfo("item_doubleclicked" ) ); @@ -3610,6 +3660,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/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp index ade56c4f49..9feadf91cf 100644 --- a/scene/resources/default_theme/default_theme.cpp +++ b/scene/resources/default_theme/default_theme.cpp @@ -837,7 +837,10 @@ void make_default_theme() { t->set_constant("separation","HBoxContainer",4); t->set_constant("separation","VBoxContainer",4); - t->set_constant("margin","MarginContainer",8); + t->set_constant("margin_left","MarginContainer",8); + t->set_constant("margin_top","MarginContainer",0); + t->set_constant("margin_right","MarginContainer",0); + t->set_constant("margin_bottom","MarginContainer",0); t->set_constant("hseparation","GridContainer",4); t->set_constant("vseparation","GridContainer",4); t->set_constant("separation","HSplitContainer",12); 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; }; |