diff options
Diffstat (limited to 'scene/gui')
89 files changed, 2765 insertions, 392 deletions
diff --git a/scene/gui/base_button.cpp b/scene/gui/base_button.cpp index bbe15da1cc..965e7f399d 100644 --- a/scene/gui/base_button.cpp +++ b/scene/gui/base_button.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -148,6 +148,7 @@ void BaseButton::_input_event(InputEvent p_event) { update(); } } break; + case InputEvent::ACTION: case InputEvent::JOYSTICK_BUTTON: case InputEvent::KEY: { @@ -389,10 +390,10 @@ void BaseButton::_bind_methods() { ADD_SIGNAL( MethodInfo("pressed" ) ); ADD_SIGNAL( MethodInfo("released" ) ); ADD_SIGNAL( MethodInfo("toggled", PropertyInfo( Variant::BOOL,"pressed") ) ); - ADD_PROPERTY( PropertyInfo( Variant::BOOL, "disabled"), _SCS("set_disabled"), _SCS("is_disabled")); + ADD_PROPERTYNZ( PropertyInfo( Variant::BOOL, "disabled"), _SCS("set_disabled"), _SCS("is_disabled")); ADD_PROPERTY( PropertyInfo( Variant::BOOL, "toggle_mode"), _SCS("set_toggle_mode"), _SCS("is_toggle_mode")); - ADD_PROPERTY( PropertyInfo( Variant::BOOL, "is_pressed"), _SCS("set_pressed"), _SCS("is_pressed")); - ADD_PROPERTY( PropertyInfo( Variant::BOOL, "click_on_press"), _SCS("set_click_on_press"), _SCS("get_click_on_press")); + ADD_PROPERTYNZ( PropertyInfo( Variant::BOOL, "is_pressed"), _SCS("set_pressed"), _SCS("is_pressed")); + ADD_PROPERTYNZ( PropertyInfo( Variant::BOOL, "click_on_press"), _SCS("set_click_on_press"), _SCS("get_click_on_press")); BIND_CONSTANT( DRAW_NORMAL ); diff --git a/scene/gui/base_button.h b/scene/gui/base_button.h index a376591ebb..e187a85eae 100644 --- a/scene/gui/base_button.h +++ b/scene/gui/base_button.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/box_container.cpp b/scene/gui/box_container.cpp index 5ed60e88f8..6489cbccd5 100644 --- a/scene/gui/box_container.cpp +++ b/scene/gui/box_container.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/box_container.h b/scene/gui/box_container.h index fb305f0423..d461b4aebe 100644 --- a/scene/gui/box_container.h +++ b/scene/gui/box_container.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/button.cpp b/scene/gui/button.cpp index 0532ab22da..edeb18bfc1 100644 --- a/scene/gui/button.cpp +++ b/scene/gui/button.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -97,6 +97,13 @@ void Button::_notification(int p_what) { } break; } + + if (has_focus()) { + + Ref<StyleBox> style = get_stylebox("focus"); + style->draw(ci,Rect2(Point2(),size)); + } + Ref<StyleBox> style = get_stylebox("normal" ); Ref<Font> font=get_font("font"); Ref<Texture> _icon; @@ -115,6 +122,8 @@ void Button::_notification(int p_what) { text_ofs.y+=style->get_offset().y; } break; case ALIGN_CENTER: { + if (text_ofs.x<0) + text_ofs.x=0; text_ofs+=icon_ofs; text_ofs+=style->get_offset(); } break; @@ -132,11 +141,7 @@ void Button::_notification(int p_what) { _icon->draw(ci,Point2(style->get_offset().x, Math::floor( (size.height-_icon->get_height())/2.0 ) ),is_disabled()?Color(1,1,1,0.4):Color(1,1,1) ); } - if (has_focus()) { - Ref<StyleBox> style = get_stylebox("focus"); - style->draw(ci,Rect2(Point2(),size)); - } } } @@ -220,11 +225,11 @@ void Button::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_text_align"),&Button::get_text_align); ObjectTypeDB::bind_method(_MD("is_flat"),&Button::is_flat); - ADD_PROPERTY( PropertyInfo( Variant::STRING, "text", PROPERTY_HINT_NONE,"",PROPERTY_USAGE_DEFAULT_INTL ), _SCS("set_text"),_SCS("get_text") ); - ADD_PROPERTY( PropertyInfo( Variant::OBJECT, "icon", PROPERTY_HINT_RESOURCE_TYPE, "Texture" ), _SCS("set_button_icon"),_SCS("get_button_icon") ); + ADD_PROPERTYNZ( PropertyInfo( Variant::STRING, "text", PROPERTY_HINT_NONE,"",PROPERTY_USAGE_DEFAULT_INTL ), _SCS("set_text"),_SCS("get_text") ); + ADD_PROPERTYNZ( PropertyInfo( Variant::OBJECT, "icon", PROPERTY_HINT_RESOURCE_TYPE, "Texture" ), _SCS("set_button_icon"),_SCS("get_button_icon") ); ADD_PROPERTY( PropertyInfo( Variant::BOOL, "flat" ), _SCS("set_flat"),_SCS("is_flat") ); - ADD_PROPERTY( PropertyInfo( Variant::BOOL, "clip_text" ), _SCS("set_clip_text"),_SCS("get_clip_text") ); - ADD_PROPERTY( PropertyInfo( Variant::INT, "align",PROPERTY_HINT_ENUM,"Left,Center,Right" ), _SCS("set_text_align"),_SCS("get_text_align") ); + ADD_PROPERTYNZ( PropertyInfo( Variant::BOOL, "clip_text" ), _SCS("set_clip_text"),_SCS("get_clip_text") ); + ADD_PROPERTYNO( PropertyInfo( Variant::INT, "align",PROPERTY_HINT_ENUM,"Left,Center,Right" ), _SCS("set_text_align"),_SCS("get_text_align") ); } diff --git a/scene/gui/button.h b/scene/gui/button.h index cf79e23579..690179b90c 100644 --- a/scene/gui/button.h +++ b/scene/gui/button.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/button_array.cpp b/scene/gui/button_array.cpp index e3a2b7b290..b86e32dda7 100644 --- a/scene/gui/button_array.cpp +++ b/scene/gui/button_array.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -34,7 +34,7 @@ bool ButtonArray::_set(const StringName& p_name, const Variant& p_value) { String n=String(p_name); if (n.begins_with("button/")) { - String what = n.get_slice("/",1); + String what = n.get_slicec('/',1); if (what=="count") { int new_size=p_value; if (new_size>0 && buttons.size()==0) { @@ -57,7 +57,7 @@ bool ButtonArray::_set(const StringName& p_name, const Variant& p_value) { } else { int idx=what.to_int(); ERR_FAIL_INDEX_V(idx,buttons.size(),false); - String f = n.get_slice("/",2); + String f = n.get_slicec('/',2); if (f=="text") buttons[idx].text=p_value; else if (f=="icon") @@ -80,7 +80,7 @@ bool ButtonArray::_get(const StringName& p_name,Variant &r_ret) const { String n=String(p_name); if (n.begins_with("button/")) { - String what = n.get_slice("/",1); + String what = n.get_slicec('/',1); if (what=="count") { r_ret=buttons.size(); } else if (what=="align") { @@ -92,7 +92,7 @@ bool ButtonArray::_get(const StringName& p_name,Variant &r_ret) const { } else { int idx=what.to_int(); ERR_FAIL_INDEX_V(idx,buttons.size(),false); - String f = n.get_slice("/",2); + String f = n.get_slicec('/',2); if (f=="text") r_ret=buttons[idx].text; else if (f=="icon") diff --git a/scene/gui/button_array.h b/scene/gui/button_array.h index f536040039..ea2c1e4968 100644 --- a/scene/gui/button_array.h +++ b/scene/gui/button_array.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -26,98 +26,98 @@ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef BUTTON_ARRAY_H
-#define BUTTON_ARRAY_H
-
-#include "scene/gui/control.h"
-
-class ButtonArray : public Control {
-
- OBJ_TYPE(ButtonArray, Control);
-public:
- enum Align {
- ALIGN_BEGIN,
- ALIGN_CENTER,
- ALIGN_END,
- ALIGN_FILL,
- ALIGN_EXPAND_FILL
- };
-private:
-
- Orientation orientation;
- Align align;
-
- struct Button {
-
- String text;
- Ref<Texture> icon;
- mutable int _ms_cache;
- mutable int _pos_cache;
- mutable int _size_cache;
- };
-
- int selected;
- int hover;
- double min_button_size;
-
- Vector<Button> buttons;
-protected:
-
- bool _set(const StringName& p_name, const Variant& p_value);
- bool _get(const StringName& p_name,Variant &r_ret) const;
- void _get_property_list( List<PropertyInfo> *p_list) const;
-
- void _notification(int p_what);
- static void _bind_methods();
-
-public:
-
- void _input_event(const InputEvent& p_event);
-
-
- void set_align(Align p_align);
- Align get_align() const;
-
- void add_button(const String& p_button);
- void add_icon_button(const Ref<Texture>& p_icon,const String& p_button="");
-
- void set_button_text(int p_button, const String& p_text);
- void set_button_icon(int p_button, const Ref<Texture>& p_icon);
-
-
- String get_button_text(int p_button) const;
- Ref<Texture> get_button_icon(int p_button) const;
-
- int get_selected() const;
- int get_hovered() const;
- void set_selected(int p_selected);
-
- int get_button_count() const;
-
- void erase_button(int p_button);
- void clear();
-
- virtual Size2 get_minimum_size() const;
-
- virtual void get_translatable_strings(List<String> *p_strings) const;
-
-
- ButtonArray(Orientation p_orientation=HORIZONTAL);
-};
-
-class HButtonArray : public ButtonArray {
- OBJ_TYPE(HButtonArray,ButtonArray);
-public:
-
- HButtonArray() : ButtonArray(HORIZONTAL) {};
-};
-
-class VButtonArray : public ButtonArray {
- OBJ_TYPE(VButtonArray,ButtonArray);
-public:
-
- VButtonArray() : ButtonArray(VERTICAL) {};
-};
-
-
-#endif // BUTTON_ARRAY_H
+#ifndef BUTTON_ARRAY_H +#define BUTTON_ARRAY_H + +#include "scene/gui/control.h" + +class ButtonArray : public Control { + + OBJ_TYPE(ButtonArray, Control); +public: + enum Align { + ALIGN_BEGIN, + ALIGN_CENTER, + ALIGN_END, + ALIGN_FILL, + ALIGN_EXPAND_FILL + }; +private: + + Orientation orientation; + Align align; + + struct Button { + + String text; + Ref<Texture> icon; + mutable int _ms_cache; + mutable int _pos_cache; + mutable int _size_cache; + }; + + int selected; + int hover; + double min_button_size; + + Vector<Button> buttons; +protected: + + bool _set(const StringName& p_name, const Variant& p_value); + bool _get(const StringName& p_name,Variant &r_ret) const; + void _get_property_list( List<PropertyInfo> *p_list) const; + + void _notification(int p_what); + static void _bind_methods(); + +public: + + void _input_event(const InputEvent& p_event); + + + void set_align(Align p_align); + Align get_align() const; + + void add_button(const String& p_button); + void add_icon_button(const Ref<Texture>& p_icon,const String& p_button=""); + + void set_button_text(int p_button, const String& p_text); + void set_button_icon(int p_button, const Ref<Texture>& p_icon); + + + String get_button_text(int p_button) const; + Ref<Texture> get_button_icon(int p_button) const; + + int get_selected() const; + int get_hovered() const; + void set_selected(int p_selected); + + int get_button_count() const; + + void erase_button(int p_button); + void clear(); + + virtual Size2 get_minimum_size() const; + + virtual void get_translatable_strings(List<String> *p_strings) const; + + + ButtonArray(Orientation p_orientation=HORIZONTAL); +}; + +class HButtonArray : public ButtonArray { + OBJ_TYPE(HButtonArray,ButtonArray); +public: + + HButtonArray() : ButtonArray(HORIZONTAL) {}; +}; + +class VButtonArray : public ButtonArray { + OBJ_TYPE(VButtonArray,ButtonArray); +public: + + VButtonArray() : ButtonArray(VERTICAL) {}; +}; + + +#endif // BUTTON_ARRAY_H diff --git a/scene/gui/button_group.cpp b/scene/gui/button_group.cpp index 94cc0a8d51..8d1fa80b84 100644 --- a/scene/gui/button_group.cpp +++ b/scene/gui/button_group.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/button_group.h b/scene/gui/button_group.h index e154f609a8..24edf94994 100644 --- a/scene/gui/button_group.h +++ b/scene/gui/button_group.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/center_container.cpp b/scene/gui/center_container.cpp index 4f8f50781c..8a22a38980 100644 --- a/scene/gui/center_container.cpp +++ b/scene/gui/center_container.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/center_container.h b/scene/gui/center_container.h index 9cd9173fab..4d8d06ac8c 100644 --- a/scene/gui/center_container.h +++ b/scene/gui/center_container.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/check_box.cpp b/scene/gui/check_box.cpp index 309152ba8f..2aa82bc5f5 100644 --- a/scene/gui/check_box.cpp +++ b/scene/gui/check_box.cpp @@ -59,7 +59,7 @@ bool CheckBox::is_radio() Node* parent = this; do { parent = parent->get_parent(); - if (dynamic_cast< ButtonGroup* >(parent)) + if (parent->cast_to<ButtonGroup>()) break; } while (parent); diff --git a/scene/gui/check_button.cpp b/scene/gui/check_button.cpp index 10dca67053..d765aefe5e 100644 --- a/scene/gui/check_button.cpp +++ b/scene/gui/check_button.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/check_button.h b/scene/gui/check_button.h index a4ebe5b8af..b90bb31c2d 100644 --- a/scene/gui/check_button.h +++ b/scene/gui/check_button.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/color_picker.cpp b/scene/gui/color_picker.cpp index d944b804a5..c30d473610 100644 --- a/scene/gui/color_picker.cpp +++ b/scene/gui/color_picker.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/color_picker.h b/scene/gui/color_picker.h index e45b4b131e..0756e88cf2 100644 --- a/scene/gui/color_picker.h +++ b/scene/gui/color_picker.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/color_ramp_edit.cpp b/scene/gui/color_ramp_edit.cpp new file mode 100644 index 0000000000..14a48fe3d3 --- /dev/null +++ b/scene/gui/color_ramp_edit.cpp @@ -0,0 +1,422 @@ +#include "color_ramp_edit.h" +#include "os/keyboard.h" + +ColorRampEdit::ColorRampEdit(){ + grabbed=-1; + grabbing=false; + set_focus_mode(FOCUS_ALL); + + popup = memnew( PopupPanel ); + picker = memnew( ColorPicker ); + popup->add_child(picker); + popup->set_child_rect(picker); + add_child(popup); + + checker = Ref<ImageTexture>(memnew( ImageTexture )); + checker->create_from_image( Image(checker_bg_png),ImageTexture::FLAG_REPEAT ); +} + +int ColorRampEdit::_get_point_from_pos(int x) { + int result = -1; + int total_w = get_size().width-get_size().height-3; + for(int i=0;i<points.size();i++) { + //Check if we clicked at point + if (ABS(x-points[i].offset*total_w+1)<(POINT_WIDTH/2+1)) { + result=i; + } + } + return result; +} + +void ColorRampEdit::_show_color_picker() { + if (grabbed==-1) + return; + Size2 ms = Size2(350, picker->get_combined_minimum_size().height+10); + picker->set_color(points[grabbed].color); + popup->set_pos(get_global_pos()-Vector2(ms.width-get_size().width,ms.height)); + popup->set_size(ms); + popup->popup(); +} + +ColorRampEdit::~ColorRampEdit() { + +} + +void ColorRampEdit::_input_event(const InputEvent& p_event) { + + if (p_event.type==InputEvent::KEY && p_event.key.pressed && p_event.key.scancode==KEY_DELETE && grabbed!=-1) { + + points.remove(grabbed); + grabbed=-1; + grabbing=false; + update(); + emit_signal("ramp_changed"); + accept_event(); + } + + //Show color picker on double click. + if (p_event.type==InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index==1 && p_event.mouse_button.doubleclick && p_event.mouse_button.pressed) { + grabbed=_get_point_from_pos(p_event.mouse_button.x); + _show_color_picker(); + accept_event(); + } + + //Delete point on right click + if (p_event.type==InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index==2 && p_event.mouse_button.pressed) { + grabbed=_get_point_from_pos(p_event.mouse_button.x); + if(grabbed != -1) + { + points.remove(grabbed); + grabbed=-1; + grabbing=false; + update(); + emit_signal("ramp_changed"); + accept_event(); + } + } + + //Hold alt key to duplicate selected color + if (p_event.type==InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index==1 && p_event.mouse_button.pressed && p_event.key.mod.alt ) { + + int x = p_event.mouse_button.x; + grabbed=_get_point_from_pos(x); + + if( grabbed != -1 ) { + int total_w = get_size().width-get_size().height-3; + ColorRamp::Point newPoint = points[grabbed]; + newPoint.offset=CLAMP(x/float(total_w),0,1); + + points.push_back(newPoint); + points.sort(); + for(int i=0;i<points.size();++i) { + if (points[i].offset==newPoint.offset) { + grabbed=i; + break; + } + } + + emit_signal("ramp_changed"); + update(); + } + } + + if (p_event.type==InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index==1 && p_event.mouse_button.pressed) { + + update(); + int x = p_event.mouse_button.x; + int total_w = get_size().width-get_size().height-3; + + //Check if color selector was clicked. + if (x>total_w+3) { + _show_color_picker(); + return; + } + + grabbing=true; + + grabbed=_get_point_from_pos(x); + //grab or select + if (grabbed!=-1) { + return; + } + + //insert + ColorRamp::Point newPoint; + newPoint.offset=CLAMP(x/float(total_w),0,1); + + ColorRamp::Point prev; + ColorRamp::Point next; + + int pos=-1; + for(int i=0;i<points.size();i++) { + if (points[i].offset<newPoint.offset) + pos=i; + } + + if (pos==-1) { + + prev.color=Color(0,0,0); + prev.offset=0; + if (points.size()) { + next=points[0]; + } else { + next.color=Color(1,1,1); + next.offset=1.0; + } + } else { + + if (pos==points.size()-1) { + next.color=Color(1,1,1); + next.offset=1.0; + } else { + next=points[pos+1]; + } + prev=points[pos]; + + } + + newPoint.color=prev.color.linear_interpolate(next.color,(newPoint.offset-prev.offset)/(next.offset-prev.offset)); + + points.push_back(newPoint); + points.sort(); + for(int i=0;i<points.size();i++) { + if (points[i].offset==newPoint.offset) { + grabbed=i; + break; + } + } + + emit_signal("ramp_changed"); + + } + + if (p_event.type==InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index==1 && !p_event.mouse_button.pressed) { + + if (grabbing) { + grabbing=false; + emit_signal("ramp_changed"); + } + update(); + } + + if (p_event.type==InputEvent::MOUSE_MOTION && grabbing) { + + int total_w = get_size().width-get_size().height-3; + + int x = p_event.mouse_motion.x; + float newofs = CLAMP(x/float(total_w),0,1); + + //Snap to nearest point if holding shift + if (p_event.key.mod.shift) { + float snap_treshhold = 0.03; + float smallest_ofs = snap_treshhold; + bool founded = false; + int nearest_point; + for(int i=0;i<points.size();++i) { + if (i != grabbed) { + float temp_ofs = ABS(points[i].offset - newofs); + if (temp_ofs < smallest_ofs) { + smallest_ofs = temp_ofs; + nearest_point = i; + if (founded) + break; + founded = true; + } + } + } + if (founded) { + if (points[nearest_point].offset < newofs) + newofs = points[nearest_point].offset+0.00001; + else + newofs = points[nearest_point].offset-0.00001; + newofs = CLAMP(newofs,0,1); + } + } + + bool valid=true; + for(int i=0;i<points.size();i++) { + + if (points[i].offset==newofs && i!=grabbed) { + valid=false; + } + } + + if (!valid) + return; + + points[grabbed].offset=newofs; + + points.sort(); + for(int i=0;i<points.size();i++) { + if (points[i].offset==newofs) { + grabbed=i; + break; + } + } + + emit_signal("ramp_changed"); + + update(); + } +} + +void ColorRampEdit::_notification(int p_what) { + + if (p_what==NOTIFICATION_ENTER_TREE) { + picker->connect("color_changed",this,"_color_changed"); + } + if (p_what==NOTIFICATION_DRAW) { + + int w = get_size().x; + int h = get_size().y; + + if (w == 0 || h == 0) + return; //Safety check. We have division by 'h'. And in any case there is nothing to draw with such size + + int total_w = get_size().width-get_size().height-3; + + //Draw checker pattern for ramp + _draw_checker(0,0, total_w, h); + + //Draw color ramp + ColorRamp::Point prev; + prev.offset=0; + if(points.size() == 0) + prev.color=Color(0,0,0); //Draw black rectangle if we have no points + else + prev.color = points[0].color; //Extend color of first point to the beginning. + + for(int i=-1;i<points.size();i++) { + + ColorRamp::Point next; + //If there is no next point + if (i+1 == points.size()) { + if(points.size() == 0) + next.color=Color(0,0,0); //Draw black rectangle if we have no points + else + next.color=points[i].color; //Extend color of last point to the end. + next.offset=1; + } else { + next=points[i+1]; + } + + if (prev.offset==next.offset) { + prev=next; + continue; + } + + Vector<Vector2> points; + Vector<Color> colors; + points.push_back(Vector2(prev.offset*total_w,h)); + points.push_back(Vector2(prev.offset*total_w,0)); + points.push_back(Vector2(next.offset*total_w,0)); + points.push_back(Vector2(next.offset*total_w,h)); + colors.push_back(prev.color); + colors.push_back(prev.color); + colors.push_back(next.color); + colors.push_back(next.color); + draw_primitive(points,colors,Vector<Point2>()); + prev=next; + } + + //Draw point markers + for(int i=0;i<points.size();i++) { + + Color col = i==grabbed?Color(1,0.0,0.0,0.9):points[i].color.contrasted(); + col.a = 0.9; + + draw_line(Vector2(points[i].offset*total_w,0),Vector2(points[i].offset*total_w,h/2),col); + draw_rect(Rect2(points[i].offset*total_w-POINT_WIDTH/2, h/2, POINT_WIDTH, h/2), Color(0.6, 0.6, 0.6, i==grabbed?0.9:0.4)); + draw_line(Vector2(points[i].offset*total_w-POINT_WIDTH/2,h/2),Vector2(points[i].offset*total_w-POINT_WIDTH/2,h-1),col); + draw_line(Vector2(points[i].offset*total_w+POINT_WIDTH/2,h/2),Vector2(points[i].offset*total_w+POINT_WIDTH/2,h-1),col); + draw_line(Vector2(points[i].offset*total_w-POINT_WIDTH/2,h/2),Vector2(points[i].offset*total_w+POINT_WIDTH/2,h/2),col); + draw_line(Vector2(points[i].offset*total_w-POINT_WIDTH/2,h-1),Vector2(points[i].offset*total_w+POINT_WIDTH/2,h-1),col); + + } + + + //Draw "button" for color selector + _draw_checker(total_w+3,0, h, h); + if (grabbed!=-1) { + //Draw with selection color + draw_rect(Rect2(total_w+3,0,h,h),points[grabbed].color); + } else { + //if no color selected draw grey color with 'X' on top. + draw_rect(Rect2(total_w+3,0,h,h), Color(0.5, 0.5, 0.5, 1)); + draw_line(Vector2(total_w+3,0),Vector2(total_w+3+h,h),Color(1,1,1,0.6)); + draw_line(Vector2(total_w+3,h),Vector2(total_w+3+h,0),Color(1,1,1,0.6)); + } + + //Draw borders around color ramp if in focus + if (has_focus()) { + + draw_line(Vector2(-1,-1),Vector2(total_w+1,-1),Color(1,1,1,0.6)); + draw_line(Vector2(total_w+1,-1),Vector2(total_w+1,h+1),Color(1,1,1,0.6)); + draw_line(Vector2(total_w+1,h+1),Vector2(-1,h+1),Color(1,1,1,0.6)); + draw_line(Vector2(-1,-1),Vector2(-1,h+1),Color(1,1,1,0.6)); + } + + } +} + +void ColorRampEdit::_draw_checker(int x, int y, int w, int h) { + //Draw it with polygon to insert UVs for scale + Vector<Vector2> backPoints; + backPoints.push_back(Vector2(x, y)); + backPoints.push_back(Vector2(x, y+h)); + backPoints.push_back(Vector2(x+w, y+h)); + backPoints.push_back(Vector2(x+w, y)); + Vector<Color> colorPoints; + colorPoints.push_back(Color(1, 1, 1, 1)); + colorPoints.push_back(Color(1, 1, 1, 1)); + colorPoints.push_back(Color(1, 1, 1, 1)); + colorPoints.push_back(Color(1, 1, 1, 1)); + Vector<Vector2> uvPoints; + //Draw checker pattern pixel-perfect and scale it by 2. + uvPoints.push_back(Vector2(x, y)); + uvPoints.push_back(Vector2(x, y+h*.5f/checker->get_height())); + uvPoints.push_back(Vector2(x+w*.5f/checker->get_width(), y+h*.5f/checker->get_height())); + uvPoints.push_back(Vector2(x+w*.5f/checker->get_width(), y)); + draw_polygon(backPoints, colorPoints, uvPoints, checker); +} + +Size2 ColorRampEdit::get_minimum_size() const { + + return Vector2(0,16); +} + +void ColorRampEdit::_color_changed(const Color& p_color) { + + if (grabbed==-1) + return; + points[grabbed].color=p_color; + update(); + emit_signal("ramp_changed"); + +} + +void ColorRampEdit::set_ramp(const Vector<float>& p_offsets,const Vector<Color>& p_colors) { + + ERR_FAIL_COND(p_offsets.size()!=p_colors.size()); + points.clear(); + for(int i=0;i<p_offsets.size();i++) { + ColorRamp::Point p; + p.offset=p_offsets[i]; + p.color=p_colors[i]; + points.push_back(p); + } + + points.sort(); + update(); +} + +Vector<float> ColorRampEdit::get_offsets() const { + Vector<float> ret; + for(int i=0;i<points.size();i++) + ret.push_back(points[i].offset); + return ret; +} + +Vector<Color> ColorRampEdit::get_colors() const { + Vector<Color> ret; + for(int i=0;i<points.size();i++) + ret.push_back(points[i].color); + return ret; +} + +void ColorRampEdit::set_points(Vector<ColorRamp::Point>& p_points) { + if(points.size() != p_points.size()) + grabbed = -1; + points.clear(); + points = p_points; +} + +Vector<ColorRamp::Point>& ColorRampEdit::get_points() { + return points; +} + +void ColorRampEdit::_bind_methods() { + ObjectTypeDB::bind_method(_MD("_input_event"),&ColorRampEdit::_input_event); + ObjectTypeDB::bind_method(_MD("_color_changed"),&ColorRampEdit::_color_changed); + ADD_SIGNAL(MethodInfo("ramp_changed")); +} diff --git a/scene/gui/color_ramp_edit.h b/scene/gui/color_ramp_edit.h new file mode 100644 index 0000000000..91292eed0d --- /dev/null +++ b/scene/gui/color_ramp_edit.h @@ -0,0 +1,52 @@ +#ifndef SCENE_GUI_COLOR_RAMP_EDIT_H_ +#define SCENE_GUI_COLOR_RAMP_EDIT_H_ + +#include "scene/gui/popup.h" +#include "scene/gui/color_picker.h" +#include "scene/resources/color_ramp.h" +#include "scene/resources/default_theme/theme_data.h" + +#define POINT_WIDTH 8 + +class ColorRampEdit : public Control { + + OBJ_TYPE(ColorRampEdit,Control); + + PopupPanel *popup; + ColorPicker *picker; + + Ref<ImageTexture> checker; + + bool grabbing; + int grabbed; + Vector<ColorRamp::Point> points; + + void _draw_checker(int x, int y, int w, int h); + void _color_changed(const Color& p_color); + int _get_point_from_pos(int x); + void _show_color_picker(); + +protected: + void _input_event(const InputEvent& p_event); + void _notification(int p_what); + static void _bind_methods(); + +public: + void set_ramp(const Vector<float>& p_offsets,const Vector<Color>& p_colors); + Vector<float> get_offsets() const; + Vector<Color> get_colors() const; + void set_points(Vector<ColorRamp::Point>& p_points); + Vector<ColorRamp::Point>& get_points(); + virtual Size2 get_minimum_size() const; + + ColorRampEdit(); + virtual ~ColorRampEdit(); +}; + +/*class ColorRampEditPanel : public Panel +{ + OBJ_TYPE(ColorRampEditPanel, Panel ); +};*/ + + +#endif /* SCENE_GUI_COLOR_RAMP_EDIT_H_ */ diff --git a/scene/gui/container.cpp b/scene/gui/container.cpp index bb61723acf..6c74bc3977 100644 --- a/scene/gui/container.cpp +++ b/scene/gui/container.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/container.h b/scene/gui/container.h index 841244fb9a..ba9bf2d60f 100644 --- a/scene/gui/container.h +++ b/scene/gui/container.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp index c539dc3284..a1c0644650 100644 --- a/scene/gui/control.cpp +++ b/scene/gui/control.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -136,44 +136,54 @@ bool Control::_set(const StringName& p_name, const Variant& p_value) { if (p_value.get_type()==Variant::NIL) { if (name.begins_with("custom_icons/")) { - String dname = name.get_slice("/",1); + String dname = name.get_slicec('/',1); data.icon_override.erase(dname); + notification(NOTIFICATION_THEME_CHANGED); update(); } else if (name.begins_with("custom_styles/")) { - String dname = name.get_slice("/",1); + String dname = name.get_slicec('/',1); data.style_override.erase(dname); + notification(NOTIFICATION_THEME_CHANGED); update(); } else if (name.begins_with("custom_fonts/")) { - String dname = name.get_slice("/",1); + String dname = name.get_slicec('/',1); data.font_override.erase(dname); + notification(NOTIFICATION_THEME_CHANGED); update(); } else if (name.begins_with("custom_colors/")) { - String dname = name.get_slice("/",1); + String dname = name.get_slicec('/',1); data.color_override.erase(dname); + notification(NOTIFICATION_THEME_CHANGED); update(); } else if (name.begins_with("custom_constants/")) { - String dname = name.get_slice("/",1); + String dname = name.get_slicec('/',1); data.constant_override.erase(dname); + notification(NOTIFICATION_THEME_CHANGED); update(); } else return false; } else { if (name.begins_with("custom_icons/")) { - String dname = name.get_slice("/",1); + String dname = name.get_slicec('/',1); + notification(NOTIFICATION_THEME_CHANGED); add_icon_override(dname,p_value); } else if (name.begins_with("custom_styles/")) { - String dname = name.get_slice("/",1); + String dname = name.get_slicec('/',1); add_style_override(dname,p_value); + notification(NOTIFICATION_THEME_CHANGED); } else if (name.begins_with("custom_fonts/")) { - String dname = name.get_slice("/",1); + String dname = name.get_slicec('/',1); add_font_override(dname,p_value); + notification(NOTIFICATION_THEME_CHANGED); } else if (name.begins_with("custom_colors/")) { - String dname = name.get_slice("/",1); + String dname = name.get_slicec('/',1); add_color_override(dname,p_value); + notification(NOTIFICATION_THEME_CHANGED); } else if (name.begins_with("custom_constants/")) { - String dname = name.get_slice("/",1); + String dname = name.get_slicec('/',1); add_constant_override(dname,p_value); + notification(NOTIFICATION_THEME_CHANGED); } else return false; } @@ -207,22 +217,22 @@ bool Control::_get(const StringName& p_name,Variant &r_ret) const { return false; if (sname.begins_with("custom_icons/")) { - String name = sname.get_slice("/",1); + String name = sname.get_slicec('/',1); r_ret= data.icon_override.has(name)?Variant(data.icon_override[name]):Variant(); } else if (sname.begins_with("custom_styles/")) { - String name = sname.get_slice("/",1); + String name = sname.get_slicec('/',1); r_ret= data.style_override.has(name)?Variant(data.style_override[name]):Variant(); } else if (sname.begins_with("custom_fonts/")) { - String name = sname.get_slice("/",1); + String name = sname.get_slicec('/',1); r_ret= data.font_override.has(name)?Variant(data.font_override[name]):Variant(); } else if (sname.begins_with("custom_colors/")) { - String name = sname.get_slice("/",1); + String name = sname.get_slicec('/',1); r_ret= data.color_override.has(name)?Variant(data.color_override[name]):Variant(); } else if (sname.begins_with("custom_constants/")) { - String name = sname.get_slice("/",1); + String name = sname.get_slicec('/',1); r_ret= data.constant_override.has(name)?Variant(data.constant_override[name]):Variant(); } else @@ -514,13 +524,15 @@ void Control::_notification(int p_notification) { if (data.MI) { - data.window->window->modal_stack.erase(data.MI); + if (data.window && data.window->window) + data.window->window->modal_stack.erase(data.MI); data.MI=NULL; } if (data.SI) { //erase from subwindows - data.window->window->subwindows.erase(data.SI); + if (data.window && data.window->window) + data.window->window->subwindows.erase(data.SI); data.SI=NULL; } @@ -536,15 +548,18 @@ void Control::_notification(int p_notification) { Control * parent = get_parent()->cast_to<Control>(); //make children reference them theme - if (parent && data.theme.is_null() && parent->data.theme_owner) + + if (parent && data.theme.is_null() && parent->data.theme_owner) { _propagate_theme_changed(parent->data.theme_owner); + } } break; case NOTIFICATION_UNPARENTED: { //make children unreference the theme - if (data.theme.is_null() && data.theme_owner) + if (data.theme.is_null() && data.theme_owner) { _propagate_theme_changed(NULL); + } } break; case NOTIFICATION_MOVED_IN_PARENT: { @@ -2817,16 +2832,16 @@ void Control::_bind_methods() { ADD_PROPERTYNZ( PropertyInfo(Variant::VECTOR2,"rect/size", PROPERTY_HINT_NONE, "",PROPERTY_USAGE_EDITOR), _SCS("set_size"),_SCS("get_size") ); ADD_PROPERTYNZ( PropertyInfo(Variant::VECTOR2,"rect/min_size"), _SCS("set_custom_minimum_size"),_SCS("get_custom_minimum_size") ); ADD_PROPERTYNZ( PropertyInfo(Variant::STRING,"hint/tooltip", PROPERTY_HINT_MULTILINE_TEXT), _SCS("set_tooltip"),_SCS("_get_tooltip") ); - ADD_PROPERTYI( PropertyInfo(Variant::NODE_PATH,"focus_neighbour/left" ), _SCS("set_focus_neighbour"),_SCS("get_focus_neighbour"),MARGIN_LEFT ); - ADD_PROPERTYI( PropertyInfo(Variant::NODE_PATH,"focus_neighbour/top" ), _SCS("set_focus_neighbour"),_SCS("get_focus_neighbour"),MARGIN_TOP ); - ADD_PROPERTYI( PropertyInfo(Variant::NODE_PATH,"focus_neighbour/right" ), _SCS("set_focus_neighbour"),_SCS("get_focus_neighbour"),MARGIN_RIGHT ); - ADD_PROPERTYI( PropertyInfo(Variant::NODE_PATH,"focus_neighbour/bottom" ), _SCS("set_focus_neighbour"),_SCS("get_focus_neighbour"),MARGIN_BOTTOM ); + ADD_PROPERTYINZ( PropertyInfo(Variant::NODE_PATH,"focus_neighbour/left" ), _SCS("set_focus_neighbour"),_SCS("get_focus_neighbour"),MARGIN_LEFT ); + ADD_PROPERTYINZ( PropertyInfo(Variant::NODE_PATH,"focus_neighbour/top" ), _SCS("set_focus_neighbour"),_SCS("get_focus_neighbour"),MARGIN_TOP ); + ADD_PROPERTYINZ( PropertyInfo(Variant::NODE_PATH,"focus_neighbour/right" ), _SCS("set_focus_neighbour"),_SCS("get_focus_neighbour"),MARGIN_RIGHT ); + ADD_PROPERTYINZ( PropertyInfo(Variant::NODE_PATH,"focus_neighbour/bottom" ), _SCS("set_focus_neighbour"),_SCS("get_focus_neighbour"),MARGIN_BOTTOM ); ADD_PROPERTY( PropertyInfo(Variant::BOOL,"focus/ignore_mouse"), _SCS("set_ignore_mouse"),_SCS("is_ignoring_mouse") ); ADD_PROPERTY( PropertyInfo(Variant::BOOL,"focus/stop_mouse"), _SCS("set_stop_mouse"),_SCS("is_stopping_mouse") ); ADD_PROPERTYNZ( PropertyInfo(Variant::INT,"size_flags/horizontal", PROPERTY_HINT_FLAGS, "Expand,Fill"), _SCS("set_h_size_flags"),_SCS("get_h_size_flags") ); ADD_PROPERTYNZ( PropertyInfo(Variant::INT,"size_flags/vertical", PROPERTY_HINT_FLAGS, "Expand,Fill"), _SCS("set_v_size_flags"),_SCS("get_v_size_flags") ); - ADD_PROPERTY( PropertyInfo(Variant::INT,"size_flags/stretch_ratio", PROPERTY_HINT_RANGE, "1,128,0.01"), _SCS("set_stretch_ratio"),_SCS("get_stretch_ratio") ); + ADD_PROPERTYNO( PropertyInfo(Variant::INT,"size_flags/stretch_ratio", PROPERTY_HINT_RANGE, "1,128,0.01"), _SCS("set_stretch_ratio"),_SCS("get_stretch_ratio") ); ADD_PROPERTYNZ( PropertyInfo(Variant::OBJECT,"theme/theme", PROPERTY_HINT_RESOURCE_TYPE, "Theme"), _SCS("set_theme"),_SCS("get_theme") ); BIND_CONSTANT( ANCHOR_BEGIN ); diff --git a/scene/gui/control.h b/scene/gui/control.h index 7e14bff098..a759fafbc9 100644 --- a/scene/gui/control.h +++ b/scene/gui/control.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/custom_button.cpp b/scene/gui/custom_button.cpp index ed3f01e5fa..53a3bf0914 100644 --- a/scene/gui/custom_button.cpp +++ b/scene/gui/custom_button.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/custom_button.h b/scene/gui/custom_button.h index 1f0f0470ed..49fcf7408f 100644 --- a/scene/gui/custom_button.h +++ b/scene/gui/custom_button.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/dialogs.cpp b/scene/gui/dialogs.cpp index 30e0241f23..3ddf23fc4a 100644 --- a/scene/gui/dialogs.cpp +++ b/scene/gui/dialogs.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/dialogs.h b/scene/gui/dialogs.h index e547d5f2af..67c574a420 100644 --- a/scene/gui/dialogs.h +++ b/scene/gui/dialogs.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/file_dialog.cpp b/scene/gui/file_dialog.cpp index 2e8a84e39b..8e428fd71c 100644 --- a/scene/gui/file_dialog.cpp +++ b/scene/gui/file_dialog.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -92,7 +92,6 @@ void FileDialog::_file_entered(const String& p_file) { } void FileDialog::_save_confirm_pressed() { - String f=dir_access->get_current_dir().plus_file(file->get_text()); emit_signal("file_selected",f); hide(); @@ -609,18 +608,12 @@ void FileDialog::_update_drives() { drives->clear(); drives->show(); - int current=-1; - String abspath = dir_access->get_current_dir(); - for(int i=0;i<dir_access->get_drive_count();i++) { - String d = dir_access->get_drive(i); - if (abspath.begins_with(d)) - current=i; + String d = dir_access->get_drive(i); drives->add_item(dir_access->get_drive(i)); } - if (current!=-1) - drives->select(current); + drives->select(dir_access->get_current_drive()); } } @@ -693,7 +686,7 @@ void FileDialog::set_default_show_hidden_files(bool p_show) { FileDialog::FileDialog() { - show_hidden_files=true; + show_hidden_files=default_show_hidden_files; VBoxContainer *vbc = memnew( VBoxContainer ); add_child(vbc); diff --git a/scene/gui/file_dialog.h b/scene/gui/file_dialog.h index 6b35035829..ec42c7744a 100644 --- a/scene/gui/file_dialog.h +++ b/scene/gui/file_dialog.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/grid_container.cpp b/scene/gui/grid_container.cpp index 582693eb3a..105f66f368 100644 --- a/scene/gui/grid_container.cpp +++ b/scene/gui/grid_container.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -40,7 +40,8 @@ void GridContainer::_notification(int p_what) { Set<int> col_expanded; Set<int> row_expanded; - int sep=get_constant("separation"); + int hsep=get_constant("hseparation"); + int vsep=get_constant("vseparation"); int idx=0; int max_row=0; @@ -69,6 +70,7 @@ void GridContainer::_notification(int p_what) { else row_minh[row]=ms.height; + // print_line("store row "+itos(row)+" mw "+itos(ms.height)); if (c->get_h_size_flags()&SIZE_EXPAND) col_expanded.insert(col); @@ -96,8 +98,8 @@ void GridContainer::_notification(int p_what) { expand_rows++; } - ms.height+=sep*max_row; - ms.width+=sep*max_col; + ms.height+=vsep*max_row; + ms.width+=hsep*max_col; int row_expand = expand_rows?(size.y-ms.y)/expand_rows:0; int col_expand = expand_cols?(size.x-ms.x)/expand_cols:0; @@ -118,29 +120,28 @@ void GridContainer::_notification(int p_what) { if (col==0) { col_ofs=0; if (row>0 && row_minh.has(row-1)) - row_ofs+=row_minh[row-1]+sep+(row_expanded.has(row-1)?row_expand:0); + row_ofs+=row_minh[row-1]+vsep+(row_expanded.has(row-1)?row_expand:0); } - if (c->is_visible()) { - Size2 s; - if (col_minw.has(col)) - s.width=col_minw[col]; - if (row_minh.has(row)) - s.height=row_minh[col]; - - if (row_expanded.has(row)) - s.height+=row_expand; - if (col_expanded.has(col)) - s.width+=col_expand; + Size2 s; + if (col_minw.has(col)) + s.width=col_minw[col]; + if (row_minh.has(row)) + s.height=row_minh[row]; - Point2 p(col_ofs,row_ofs); + if (row_expanded.has(row)) + s.height+=row_expand; + if (col_expanded.has(col)) + s.width+=col_expand; - fit_child_in_rect(c,Rect2(p,s)); + Point2 p(col_ofs,row_ofs); - } +// print_line("col: "+itos(col)+" row: "+itos(row)+" col_ofs: "+itos(col_ofs)+" row_ofs: "+itos(row_ofs)); + fit_child_in_rect(c,Rect2(p,s)); + //print_line("col: "+itos(col)+" row: "+itos(row)+" rect: "+Rect2(p,s)); if (col_minw.has(col)) { - col_ofs+=col_minw[col]+sep+(col_expanded.has(col)?col_expand:0); + col_ofs+=col_minw[col]+hsep+(col_expanded.has(col)?col_expand:0); } idx++; @@ -178,7 +179,8 @@ Size2 GridContainer::get_minimum_size() const { Map<int,int> col_minw; Map<int,int> row_minh; - int sep=get_constant("separation"); + int hsep=get_constant("hseparation"); + int vsep=get_constant("vseparation"); int idx=0; int max_row=0; @@ -216,8 +218,8 @@ Size2 GridContainer::get_minimum_size() const { ms.height+=E->get(); } - ms.height+=sep*max_row; - ms.width+=sep*max_col; + ms.height+=vsep*max_row; + ms.width+=hsep*max_col; return ms; diff --git a/scene/gui/grid_container.h b/scene/gui/grid_container.h index f74ad6c66a..8d8bc27293 100644 --- a/scene/gui/grid_container.h +++ b/scene/gui/grid_container.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/item_list.cpp b/scene/gui/item_list.cpp new file mode 100644 index 0000000000..c29f6625d3 --- /dev/null +++ b/scene/gui/item_list.cpp @@ -0,0 +1,1104 @@ +#include "item_list.h" +#include "os/os.h" +#include "globals.h" + + +void ItemList::add_item(const String& p_item,const Ref<Texture>& p_texture,bool p_selectable) { + + Item item; + item.icon=p_texture; + item.text=p_item; + item.selectable=p_selectable; + item.selected=false; + item.disabled=false; + item.custom_bg=Color(0,0,0,0); + items.push_back(item); + + update(); + shape_changed=true; + +} + +void ItemList::add_icon_item(const Ref<Texture>& p_item,bool p_selectable){ + + Item item; + item.icon=p_item; + //item.text=p_item; + item.selectable=p_selectable; + item.selected=false; + item.disabled=false; + item.custom_bg=Color(0,0,0,0); + items.push_back(item); + + update(); + shape_changed=true; + +} + +void ItemList::set_item_text(int p_idx,const String& p_text){ + + ERR_FAIL_INDEX(p_idx,items.size()); + + items[p_idx].text=p_text; + update(); + shape_changed=true; + +} + +String ItemList::get_item_text(int p_idx) const{ + + ERR_FAIL_INDEX_V(p_idx,items.size(),String()); + return items[p_idx].text; + +} + +void ItemList::set_item_tooltip(int p_idx,const String& p_tooltip){ + + ERR_FAIL_INDEX(p_idx,items.size()); + + items[p_idx].tooltip=p_tooltip; + update(); + shape_changed=true; + +} + +String ItemList::get_item_tooltip(int p_idx) const{ + + ERR_FAIL_INDEX_V(p_idx,items.size(),String()); + return items[p_idx].tooltip; + +} + +void ItemList::set_item_icon(int p_idx,const Ref<Texture>& p_icon){ + + ERR_FAIL_INDEX(p_idx,items.size()); + + items[p_idx].icon=p_icon; + update(); + shape_changed=true; + + +} +Ref<Texture> ItemList::get_item_icon(int p_idx) const{ + + ERR_FAIL_INDEX_V(p_idx,items.size(),Ref<Texture>()); + + return items[p_idx].icon; + +} + +void ItemList::set_item_custom_bg_color(int p_idx,const Color& p_custom_bg_color) { + + ERR_FAIL_INDEX(p_idx,items.size()); + + items[p_idx].custom_bg=p_custom_bg_color; + +} + +Color ItemList::get_item_custom_bg_color(int p_idx) const { + + ERR_FAIL_INDEX_V(p_idx,items.size(),Color()); + + return items[p_idx].custom_bg; + +} + + + +void ItemList::set_item_tag_icon(int p_idx,const Ref<Texture>& p_tag_icon){ + + ERR_FAIL_INDEX(p_idx,items.size()); + + items[p_idx].tag_icon=p_tag_icon; + update(); + shape_changed=true; + + +} +Ref<Texture> ItemList::get_item_tag_icon(int p_idx) const{ + + ERR_FAIL_INDEX_V(p_idx,items.size(),Ref<Texture>()); + + return items[p_idx].tag_icon; + +} + +void ItemList::set_item_selectable(int p_idx,bool p_selectable){ + + ERR_FAIL_INDEX(p_idx,items.size()); + + items[p_idx].selectable=p_selectable; + + +} + + +bool ItemList::is_item_selectable(int p_idx) const{ + + ERR_FAIL_INDEX_V(p_idx,items.size(),false); + return items[p_idx].selectable; +} + +void ItemList::set_item_disabled(int p_idx,bool p_disabled){ + + ERR_FAIL_INDEX(p_idx,items.size()); + + items[p_idx].disabled=p_disabled; + + +} + + +bool ItemList::is_item_disabled(int p_idx) const{ + + ERR_FAIL_INDEX_V(p_idx,items.size(),false); + return items[p_idx].disabled; +} + + +void ItemList::set_item_metadata(int p_idx,const Variant& p_metadata){ + + ERR_FAIL_INDEX(p_idx,items.size()); + + items[p_idx].metadata=p_metadata; + update(); + shape_changed=true; + +} + +Variant ItemList::get_item_metadata(int p_idx) const{ + + ERR_FAIL_INDEX_V(p_idx,items.size(),Variant()); + return items[p_idx].metadata; + +} +void ItemList::select(int p_idx,bool p_single){ + + ERR_FAIL_INDEX(p_idx,items.size()); + + if (p_single || select_mode==SELECT_SINGLE) { + + if (!items[p_idx].selectable) { + return; + } + + for(int i=0;i<items.size();i++) { + items[i].selected=p_idx==i; + } + + current=p_idx; + } else { + + if (items[p_idx].selectable) { + items[p_idx].selected=true; + } + } + update(); + +} +void ItemList::unselect(int p_idx){ + + ERR_FAIL_INDEX(p_idx,items.size()); + + if (select_mode!=SELECT_MULTI) { + items[p_idx].selected=false; + current=-1; + } else { + items[p_idx].selected=false; + } + update(); + +} +bool ItemList::is_selected(int p_idx) const{ + + ERR_FAIL_INDEX_V(p_idx,items.size(),false); + + return items[p_idx].selected; + +} + +void ItemList::set_current(int p_current) { + ERR_FAIL_INDEX(p_current,items.size()); + + if (select_mode==SELECT_SINGLE) + select(p_current,true); + else { + current=p_current; + update(); + } +} + +int ItemList::get_current() const { + + return current; +} + + +int ItemList::get_item_count() const{ + + return items.size(); +} +void ItemList::remove_item(int p_idx){ + + ERR_FAIL_INDEX(p_idx,items.size()); + + items.remove(p_idx); + update(); + shape_changed=true; + +} + +void ItemList::clear(){ + + items.clear(); + current=-1; + update(); + +} + +void ItemList::set_fixed_column_width(int p_size){ + + ERR_FAIL_COND(p_size<0); + fixed_column_width=p_size; + update(); + shape_changed=true; + +} +int ItemList::get_fixed_column_width() const{ + + return fixed_column_width; +} + +void ItemList::set_max_text_lines(int p_lines){ + + ERR_FAIL_COND(p_lines<1); + max_text_lines=p_lines; + update(); + shape_changed=true; + +} +int ItemList::get_max_text_lines() const{ + + return max_text_lines; +} + +void ItemList::set_max_columns(int p_amount){ + + ERR_FAIL_COND(p_amount<0); + max_columns=p_amount; + update(); +} +int ItemList::get_max_columns() const{ + + return max_columns; +} + +void ItemList::set_select_mode(SelectMode p_mode) { + + select_mode=p_mode; + update(); +} + +ItemList::SelectMode ItemList::get_select_mode() const { + + return select_mode; +} + +void ItemList::set_icon_mode(IconMode p_mode){ + + icon_mode=p_mode; + update(); + shape_changed=true; + +} +ItemList::IconMode ItemList::get_icon_mode() const{ + + return icon_mode; +} + +void ItemList::set_min_icon_size(const Size2& p_size) { + + min_icon_size=p_size; + update(); +} + +Size2 ItemList::get_min_icon_size() const { + + return min_icon_size; +} + + + +void ItemList::_input_event(const InputEvent& p_event) { + if (p_event.type==InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index==BUTTON_LEFT && p_event.mouse_button.pressed) { + + const InputEventMouseButton &mb = p_event.mouse_button; + + search_string=""; //any mousepress cancels + Vector2 pos(mb.x,mb.y); + Ref<StyleBox> bg = get_stylebox("bg"); + pos-=bg->get_offset(); + pos.y+=scroll_bar->get_val(); + + int closest = -1; + int closest_dist=0x7FFFFFFF; + + for(int i=0;i<items.size();i++) { + + Rect2 rc = items[i].rect_cache; + if (i%current_columns==current_columns-1) { + rc.size.width=get_size().width; //not right but works + } + + if (rc.has_point(pos)) { + closest=i; + break; + } + + float dist = rc.distance_to(pos); + if (dist<closest_dist) { + closest=i; + closest_dist=dist; + } + } + + if (closest!=-1) { + + int i = closest; + + 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; + int to = i; + if (i<current) { + SWAP(from,to); + } + for(int j=from;j<=to;j++) { + bool selected = !items[j].selected; + select(j,false); + if (selected) + emit_signal("multi_selected",i,true); + } + } else { + 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 (/*select_mode==SELECT_SINGLE &&*/ mb.doubleclick) { + + emit_signal("item_activated",i); + + } + + + } + + + return; + } + } + if (p_event.type==InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index==BUTTON_WHEEL_UP && p_event.mouse_button.pressed) { + + scroll_bar->set_val( scroll_bar->get_val()-scroll_bar->get_page()/8 ); + + } + if (p_event.type==InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index==BUTTON_WHEEL_DOWN && p_event.mouse_button.pressed) { + + scroll_bar->set_val( scroll_bar->get_val()+scroll_bar->get_page()/8 ); + + } + + if (p_event.is_pressed() && items.size()>0) { + if (p_event.is_action("ui_up")) { + + if (search_string!="") { + + uint64_t now = OS::get_singleton()->get_ticks_msec(); + uint64_t diff = now-search_time_msec; + + if (diff<int(Globals::get_singleton()->get("gui/incr_search_max_interval_msec"))*2) { + + for(int i=current-1;i>=0;i--) { + + if (items[i].text.begins_with(search_string)) { + + set_current(i); + ensure_current_is_visible(); + if (select_mode==SELECT_SINGLE) { + emit_signal("item_selected",current); + } + + + break; + } + } + accept_event(); + return; + } + } + + if (current>=current_columns) { + set_current(current-current_columns); + ensure_current_is_visible(); + if (select_mode==SELECT_SINGLE) { + emit_signal("item_selected",current); + } + accept_event(); + } + } else if (p_event.is_action("ui_down")) { + + if (search_string!="") { + + uint64_t now = OS::get_singleton()->get_ticks_msec(); + uint64_t diff = now-search_time_msec; + + if (diff<int(Globals::get_singleton()->get("gui/incr_search_max_interval_msec"))*2) { + + for(int i=current+1;i<items.size();i++) { + + if (items[i].text.begins_with(search_string)) { + + set_current(i); + ensure_current_is_visible(); + if (select_mode==SELECT_SINGLE) { + emit_signal("item_selected",current); + } + break; + } + } + accept_event(); + return; + } + } + + if (current<items.size()-current_columns) { + set_current(current+current_columns); + ensure_current_is_visible(); + if (select_mode==SELECT_SINGLE) { + emit_signal("item_selected",current); + } + accept_event(); + + } + } else if (p_event.is_action("ui_page_up")) { + + search_string=""; //any mousepress cancels + + for(int i=4;i>0;i--) { + if (current-current_columns*i >=0 ) { + set_current( current- current_columns*i); + ensure_current_is_visible(); + if (select_mode==SELECT_SINGLE) { + emit_signal("item_selected",current); + } + accept_event(); + break; + } + } + } else if (p_event.is_action("ui_page_down")) { + + search_string=""; //any mousepress cancels + + for(int i=4;i>0;i--) { + if (current+current_columns*i < items.size() ) { + set_current( current+ current_columns*i); + ensure_current_is_visible(); + if (select_mode==SELECT_SINGLE) { + emit_signal("item_selected",current); + } + accept_event(); + + break; + } + } + } else if (p_event.is_action("ui_left")) { + + search_string=""; //any mousepress cancels + + if (current%current_columns!=0) { + set_current(current-1); + ensure_current_is_visible(); + if (select_mode==SELECT_SINGLE) { + emit_signal("item_selected",current); + } + accept_event(); + + } + } else if (p_event.is_action("ui_right")) { + + search_string=""; //any mousepress cancels + + if (current%current_columns!=(current_columns-1)) { + set_current(current+1); + ensure_current_is_visible(); + if (select_mode==SELECT_SINGLE) { + emit_signal("item_selected",current); + } + accept_event(); + + } + } else if (p_event.is_action("ui_cancel")) { + search_string=""; + } else if (p_event.is_action("ui_select")) { + + + if (select_mode==SELECT_MULTI && current>=0 && current<items.size()) { + if (items[current].selectable && !items[current].selected) { + select(current,false); + emit_signal("multi_selected",current,true); + } else if (items[current].selected) { + unselect(current); + emit_signal("multi_selected",current,false); + } + } + } else if (p_event.is_action("ui_accept")) { + search_string=""; //any mousepress cance + + if (current>=0 && current<items.size()) { + emit_signal("item_activated",current); + } + } else if (p_event.type==InputEvent::KEY) { + + if (p_event.key.unicode) { + + uint64_t now = OS::get_singleton()->get_ticks_msec(); + uint64_t diff = now-search_time_msec; + uint64_t max_interval = uint64_t(GLOBAL_DEF("gui/incr_search_max_interval_msec",2000)); + search_time_msec = now; + + if (diff>max_interval) { + search_string=""; + } + + search_string+=String::chr(p_event.key.unicode); + for(int i=0;i<items.size();i++) { + if (items[i].text.begins_with(search_string)) { + set_current(i); + ensure_current_is_visible(); + if (select_mode==SELECT_SINGLE) { + emit_signal("item_selected",current); + } + break; + } + } + + } + + } + } + + + + +} + +void ItemList::ensure_current_is_visible() { + + if (current>=0 && current <=items.size()) { + + Rect2 r = items[current].rect_cache; + int from = scroll_bar->get_val(); + int to = from + scroll_bar->get_page(); + + if (r.pos.y < from) { + scroll_bar->set_val(r.pos.y); + } else if (r.pos.y+r.size.y > to) { + scroll_bar->set_val(r.pos.y+r.size.y - (to-from)); + } + } +} + +void ItemList::_notification(int p_what) { + + if (p_what==NOTIFICATION_RESIZED) { + shape_changed=true; + update(); + } + + if (p_what==NOTIFICATION_DRAW) { + + VS::get_singleton()->canvas_item_set_clip(get_canvas_item(),true); + Ref<StyleBox> bg = get_stylebox("bg"); + + int mw = scroll_bar->get_minimum_size().x; + scroll_bar->set_anchor_and_margin(MARGIN_LEFT,ANCHOR_END,mw+bg->get_margin(MARGIN_RIGHT)); + scroll_bar->set_anchor_and_margin(MARGIN_RIGHT,ANCHOR_END,bg->get_margin(MARGIN_RIGHT)); + scroll_bar->set_anchor_and_margin(MARGIN_TOP,ANCHOR_BEGIN,bg->get_margin(MARGIN_TOP)); + scroll_bar->set_anchor_and_margin(MARGIN_BOTTOM,ANCHOR_END,bg->get_margin(MARGIN_BOTTOM)); + + + Size2 size = get_size(); + + float page = size.height-bg->get_minimum_size().height; + int width = size.width - mw - bg->get_minimum_size().width; + scroll_bar->set_page(page); + + draw_style_box(bg,Rect2(Point2(),size)); + + int hseparation = get_constant("hseparation"); + int vseparation = get_constant("vseparation"); + int icon_margin = get_constant("icon_margin"); + int line_separation = get_constant("line_separation"); + + Ref<StyleBox> sbsel = has_focus()?get_stylebox("selected_focus"):get_stylebox("selected"); + Ref<StyleBox> cursor = has_focus()?get_stylebox("cursor"):get_stylebox("cursor_unfocused"); + + Ref<Font> font = get_font("font"); + Color guide_color = get_color("guide_color"); + Color font_color = get_color("font_color"); + Color font_color_selected = get_color("font_color_selected"); + int font_height = font->get_height(); + Vector<int> line_size_cache; + Vector<int> line_limit_cache; + + if (max_text_lines) { + line_size_cache.resize(max_text_lines); + line_limit_cache.resize(max_text_lines); + } + + if (has_focus()) { + VisualServer::get_singleton()->canvas_item_add_clip_ignore(get_canvas_item(),true); + draw_style_box(get_stylebox("bg_focus"),Rect2(Point2(),size)); + VisualServer::get_singleton()->canvas_item_add_clip_ignore(get_canvas_item(),false); + } + + if (shape_changed) { + + //1- compute item minimum sizes + for(int i=0;i<items.size();i++) { + + Size2 minsize; + if (items[i].icon.is_valid()) { + minsize=items[i].icon->get_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); + + if (items[i].text!="") { + if (icon_mode==ICON_MODE_TOP) { + minsize.y+=icon_margin; + } else { + minsize.x+=icon_margin; + } + } + } + + if (items[i].text!="") { + + Size2 s = font->get_string_size(items[i].text); + //s.width=MIN(s.width,fixed_column_width); + + + + if (icon_mode==ICON_MODE_TOP) { + minsize.x=MAX(minsize.x,s.width); + if (max_text_lines>0) { + minsize.y+=(font_height+line_separation)*max_text_lines; + } else { + minsize.y+=s.height; + } + + } else { + minsize.y=MAX(minsize.y,s.height); + minsize.x+=s.width; + } + } + + + + items[i].rect_cache.size=minsize; + if (fixed_column_width>0) + items[i].rect_cache.size.x=fixed_column_width; + + } + + int fit_size = size.x - bg->get_minimum_size().width - mw; + + //2-attempt best fit + current_columns = 0x7FFFFFFF; + if (max_columns>0) + current_columns=max_columns; + + + while(true) { + //repeat util all fits + //print_line("try with "+itos(current_columns)); + bool all_fit=true; + Vector2 ofs; + int col=0; + int max_h=0; + separators.clear();; + for(int i=0;i<items.size();i++) { + + if (current_columns>1 && items[i].rect_cache.size.width+ofs.x > fit_size) { + //went past + current_columns=MAX(col,1); + all_fit=false; + break; + } + + items[i].rect_cache.pos=ofs; + max_h=MAX(max_h,items[i].rect_cache.size.y); + ofs.x+=items[i].rect_cache.size.x; + //print_line("item "+itos(i)+" ofs "+rtos(items[i].rect_cache.size.x)); + if (col>0) + ofs.x+=hseparation; + col++; + if (col==current_columns) { + + if (i<items.size()-1) + separators.push_back(ofs.y+max_h+vseparation/2); + ofs.x=0; + ofs.y+=max_h+vseparation; + col=0; + max_h=0; + } + } + + if (all_fit) { + float max = MAX(page,ofs.y+max_h); + scroll_bar->set_max(max); + //print_line("max: "+rtos(max)+" page "+rtos(page)); + if (max<=page) { + scroll_bar->set_val(0); + scroll_bar->hide(); + } else { + scroll_bar->show(); + } + break; + } + } + + + shape_changed=false; + } + + + + Vector2 base_ofs = bg->get_offset(); + base_ofs.y-=int(scroll_bar->get_val()); + + Rect2 clip(Point2(),size-bg->get_minimum_size()+Vector2(0,scroll_bar->get_val())); + + for(int i=0;i<items.size();i++) { + + + Rect2 rcache = items[i].rect_cache; + + if (!clip.intersects(rcache)) + continue; + + + if (current_columns==1) { + rcache.size.width = width-rcache.pos.x; + } + if (items[i].custom_bg.a>0.001) { + Rect2 r=rcache; + r.pos+=base_ofs; + draw_rect(r,items[i].custom_bg); + } + if (items[i].selected) { + Rect2 r=rcache; + r.pos+=base_ofs; + + r.pos.x-=sbsel->get_margin(MARGIN_LEFT); + r.size.x+=sbsel->get_margin(MARGIN_LEFT)+sbsel->get_margin(MARGIN_RIGHT); + r.pos.y-=sbsel->get_margin(MARGIN_TOP); + r.size.y+=sbsel->get_margin(MARGIN_TOP)+sbsel->get_margin(MARGIN_BOTTOM); + + draw_style_box(sbsel,r); + + } + + + Vector2 text_ofs; + if (items[i].icon.is_valid()) { + + Vector2 icon_ofs; + if (min_icon_size!=Vector2()) { + icon_ofs = (min_icon_size - items[i].icon->get_size())/2; + } + + if (icon_mode==ICON_MODE_TOP) { + draw_texture(items[i].icon,icon_ofs+items[i].rect_cache.pos+Vector2(items[i].rect_cache.size.width/2-items[i].icon->get_width()/2,0).floor()+base_ofs); + text_ofs.y = MAX(items[i].icon->get_height(),min_icon_size.y)+icon_margin; + } else { + draw_texture(items[i].icon,icon_ofs+items[i].rect_cache.pos+Vector2(0,items[i].rect_cache.size.height/2-items[i].icon->get_height()/2).floor()+base_ofs); + text_ofs.x = MAX(items[i].icon->get_width(),min_icon_size.x)+icon_margin; + } + } + + if (items[i].tag_icon.is_valid()) { + + draw_texture(items[i].tag_icon,items[i].rect_cache.pos+base_ofs); + } + + if (items[i].text!="") { + + int max_len=-1; + + Vector2 size = font->get_string_size(items[i].text); + if (fixed_column_width) + max_len=fixed_column_width; + else + max_len=size.x; + + if (icon_mode==ICON_MODE_TOP && max_text_lines>0) { + + int ss = items[i].text.length(); + float ofs=0; + int line=0; + for(int j=0;j<=ss;j++) { + + int cs = j<ss?font->get_char_size(items[i].text[j],items[i].text[j+1]).x:0; + if (ofs+cs>max_len || j==ss) { + line_limit_cache[line]=j; + line_size_cache[line]=ofs; + line++; + ofs=0; + if (line>=max_text_lines) + break; + } else { + ofs+=cs; + } + + } + + line=0; + ofs=0; + + text_ofs.y+=font->get_ascent(); + text_ofs=text_ofs.floor(); + text_ofs+=base_ofs; + text_ofs+=items[i].rect_cache.pos; + + for(int j=0;j<ss;j++) { + + if (j==line_limit_cache[line]) { + line++; + ofs=0; + if (line>=max_text_lines) + break; + } + ofs+=font->draw_char(get_canvas_item(),text_ofs+Vector2(ofs+(max_len-line_size_cache[line])/2,line*(font_height+line_separation)).floor(),items[i].text[j],items[i].text[j+1],items[i].selected?font_color_selected:font_color); + } + + //special multiline mode + } else { + + if (fixed_column_width>0) + size.x=MIN(size.x,fixed_column_width); + + if (icon_mode==ICON_MODE_TOP) { + text_ofs.x+=(items[i].rect_cache.size.width-size.x)/2; + } else { + text_ofs.y+=(items[i].rect_cache.size.height-size.y)/2; + } + + text_ofs.y+=font->get_ascent(); + text_ofs=text_ofs.floor(); + text_ofs+=base_ofs; + text_ofs+=items[i].rect_cache.pos; + + draw_string(font,text_ofs,items[i].text,items[i].selected?font_color_selected:font_color,max_len+1); + } + + + } + + if (select_mode==SELECT_MULTI && i==current) { + + Rect2 r=rcache; + r.pos+=base_ofs; + draw_style_box(cursor,r); + + } + } + + for(int i=0;i<separators.size();i++) { + draw_line(Vector2(bg->get_margin(MARGIN_LEFT),base_ofs.y+separators[i]),Vector2(size.width-bg->get_margin(MARGIN_LEFT),base_ofs.y+separators[i]),guide_color); + } + + } +} + +void ItemList::_scroll_changed(double) { + update(); +} + + +String ItemList::get_tooltip(const Point2& p_pos) const { + + Vector2 pos=p_pos; + Ref<StyleBox> bg = get_stylebox("bg"); + pos-=bg->get_offset(); + pos.y+=scroll_bar->get_val(); + + int closest = -1; + int closest_dist=0x7FFFFFFF; + + for(int i=0;i<items.size();i++) { + + Rect2 rc = items[i].rect_cache; + if (i%current_columns==current_columns-1) { + rc.size.width=get_size().width; //not right but works + } + + if (rc.has_point(pos)) { + closest=i; + break; + } + + float dist = rc.distance_to(pos); + if (dist<closest_dist) { + closest=i; + closest_dist=dist; + } + } + + if (closest!=-1) { + if (items[closest].tooltip!="") { + return items[closest].tooltip; + } + if (items[closest].text!="") { + return items[closest].text; + } + } + + return Control::get_tooltip(p_pos); + + +} + +void ItemList::sort_items_by_text() { + items.sort(); + update(); + if (select_mode==SELECT_SINGLE) { + for(int i=0;i<items.size();i++) { + if (items[i].selected) { + select(i); + return; + } + } + } +} + +int ItemList::find_metadata(const Variant& p_metadata) const { + + for(int i=0;i<items.size();i++) { + if (items[i].metadata==p_metadata) { + return i; + } + } + + return -1; + +} + +void ItemList::_bind_methods(){ + + ObjectTypeDB::bind_method(_MD("add_item","text","icon:Texture","selectable"),&ItemList::add_item,DEFVAL(Ref<Texture>()),DEFVAL(true)); + ObjectTypeDB::bind_method(_MD("add_icon_item","icon:Texture","selectable"),&ItemList::add_icon_item,DEFVAL(true)); + + ObjectTypeDB::bind_method(_MD("set_item_text","idx","text"),&ItemList::set_item_text); + ObjectTypeDB::bind_method(_MD("get_item_text","idx"),&ItemList::get_item_text); + + ObjectTypeDB::bind_method(_MD("set_item_icon","idx","icon:Texture"),&ItemList::set_item_icon); + ObjectTypeDB::bind_method(_MD("get_item_icon:Tedture","idx"),&ItemList::get_item_icon); + + ObjectTypeDB::bind_method(_MD("set_item_selectable","idx","selectable"),&ItemList::set_item_selectable); + ObjectTypeDB::bind_method(_MD("is_item_selectable","idx"),&ItemList::is_item_selectable); + + ObjectTypeDB::bind_method(_MD("set_item_disabled","idx","disabled"),&ItemList::set_item_disabled); + ObjectTypeDB::bind_method(_MD("is_item_disabled","idx"),&ItemList::is_item_disabled); + + ObjectTypeDB::bind_method(_MD("set_item_metadata","idx","metadata"),&ItemList::set_item_metadata); + ObjectTypeDB::bind_method(_MD("get_item_metadata","idx"),&ItemList::get_item_metadata); + + ObjectTypeDB::bind_method(_MD("set_item_custom_bg_color","idx","custom_bg_color"),&ItemList::set_item_custom_bg_color); + ObjectTypeDB::bind_method(_MD("get_item_custom_bg_color","idx"),&ItemList::get_item_custom_bg_color); + + ObjectTypeDB::bind_method(_MD("set_item_tooltip","idx","tooltip"),&ItemList::set_item_tooltip); + ObjectTypeDB::bind_method(_MD("get_item_tooltip","idx"),&ItemList::get_item_tooltip); + + ObjectTypeDB::bind_method(_MD("select","idx","single"),&ItemList::select,DEFVAL(true)); + ObjectTypeDB::bind_method(_MD("unselect","idx"),&ItemList::unselect); + ObjectTypeDB::bind_method(_MD("is_selected","idx"),&ItemList::is_selected); + + ObjectTypeDB::bind_method(_MD("get_item_count"),&ItemList::get_item_count); + ObjectTypeDB::bind_method(_MD("remove_item","idx"),&ItemList::remove_item); + + ObjectTypeDB::bind_method(_MD("clear"),&ItemList::clear); + ObjectTypeDB::bind_method(_MD("sort_items_by_text"),&ItemList::clear); + + ObjectTypeDB::bind_method(_MD("set_fixed_column_width","width"),&ItemList::set_fixed_column_width); + ObjectTypeDB::bind_method(_MD("get_fixed_column_width"),&ItemList::get_fixed_column_width); + + ObjectTypeDB::bind_method(_MD("set_max_text_lines","lines"),&ItemList::set_max_text_lines); + ObjectTypeDB::bind_method(_MD("get_max_text_lines"),&ItemList::get_max_text_lines); + + ObjectTypeDB::bind_method(_MD("set_max_columns","amount"),&ItemList::set_max_columns); + ObjectTypeDB::bind_method(_MD("get_max_columns"),&ItemList::get_max_columns); + + ObjectTypeDB::bind_method(_MD("set_select_mode","mode"),&ItemList::set_select_mode); + ObjectTypeDB::bind_method(_MD("get_select_mode"),&ItemList::get_select_mode); + + ObjectTypeDB::bind_method(_MD("set_icon_mode","mode"),&ItemList::set_icon_mode); + ObjectTypeDB::bind_method(_MD("get_icon_mode"),&ItemList::get_icon_mode); + + 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("ensure_current_is_visible"),&ItemList::ensure_current_is_visible); + + ObjectTypeDB::bind_method(_MD("_scroll_changed"),&ItemList::_scroll_changed); + ObjectTypeDB::bind_method(_MD("_input_event"),&ItemList::_input_event); + + BIND_CONSTANT( ICON_MODE_TOP ); + BIND_CONSTANT( ICON_MODE_LEFT ); + BIND_CONSTANT( SELECT_SINGLE ); + BIND_CONSTANT( SELECT_MULTI ); + + ADD_SIGNAL( MethodInfo("item_selected",PropertyInfo(Variant::INT,"index"))); + ADD_SIGNAL( MethodInfo("multi_selected",PropertyInfo(Variant::INT,"index"),PropertyInfo(Variant::BOOL,"selected"))); + ADD_SIGNAL( MethodInfo("item_activated",PropertyInfo(Variant::INT,"index"))); +} + + + +ItemList::ItemList() { + + current=-1; + + select_mode=SELECT_SINGLE; + icon_mode=ICON_MODE_LEFT; + + fixed_column_width=0; + max_text_lines=1; + max_columns=1; + + scroll_bar = memnew( VScrollBar ); + add_child(scroll_bar); + + shape_changed=true; + scroll_bar->connect("value_changed",this,"_scroll_changed"); + + set_focus_mode(FOCUS_ALL); + current_columns=1; + search_time_msec=0; + +} + +ItemList::~ItemList() { + +} + diff --git a/scene/gui/item_list.h b/scene/gui/item_list.h new file mode 100644 index 0000000000..237079c428 --- /dev/null +++ b/scene/gui/item_list.h @@ -0,0 +1,141 @@ +#ifndef ITEMLIST_H +#define ITEMLIST_H + +#include "scene/gui/control.h" +#include "scene/gui/scroll_bar.h" + +class ItemList : public Control { + + OBJ_TYPE( ItemList, Control ); +public: + + enum IconMode { + ICON_MODE_TOP, + ICON_MODE_LEFT + }; + + enum SelectMode { + SELECT_SINGLE, + SELECT_MULTI + }; +private: + struct Item { + + Ref<Texture> icon; + Ref<Texture> tag_icon; + String text; + bool selectable; + bool selected; + bool disabled; + Variant metadata; + String tooltip; + Color custom_bg; + + + Rect2 rect_cache; + + bool operator<(const Item& p_another) const { return text<p_another.text; } + }; + + int current; + + bool shape_changed; + + Vector<Item> items; + Vector<int> separators; + + SelectMode select_mode; + IconMode icon_mode; + VScrollBar *scroll_bar; + + uint64_t search_time_msec; + String search_string; + + int current_columns; + int fixed_column_width; + int max_text_lines; + int max_columns; + Size2 min_icon_size; + + void _scroll_changed(double); + void _input_event(const InputEvent& p_event); +protected: + + void _notification(int p_what); + static void _bind_methods(); +public: + + void add_item(const String& p_item,const Ref<Texture>& p_texture=Ref<Texture>(),bool p_selectable=true); + void add_icon_item(const Ref<Texture>& p_item,bool p_selectable=true); + + void set_item_text(int p_idx,const String& p_text); + String get_item_text(int p_idx) const; + + void set_item_icon(int p_idx,const Ref<Texture>& p_icon); + Ref<Texture> get_item_icon(int p_idx) const; + + void set_item_selectable(int p_idx,bool p_selectable); + bool is_item_selectable(int p_idx) const; + + void set_item_disabled(int p_idx,bool p_disabled); + bool is_item_disabled(int p_idx) const; + + void set_item_metadata(int p_idx,const Variant& p_metadata); + Variant get_item_metadata(int p_idx) const; + + void set_item_tag_icon(int p_idx,const Ref<Texture>& p_tag_icon); + Ref<Texture> get_item_tag_icon(int p_idx) const; + + void set_item_tooltip(int p_idx,const String& p_tooltip); + String get_item_tooltip(int p_idx) const; + + void set_item_custom_bg_color(int p_idx,const Color& p_custom_bg_color); + Color get_item_custom_bg_color(int p_idx) const; + + void select(int p_idx,bool p_single=true); + void unselect(int p_idx); + bool is_selected(int p_idx) const; + + void set_current(int p_current); + int get_current() const; + + + int get_item_count() const; + void remove_item(int p_idx); + + void clear(); + + void set_fixed_column_width(int p_size); + int get_fixed_column_width() const; + + void set_max_text_lines(int p_amount); + int get_max_text_lines() const; + + void set_max_columns(int p_amount); + int get_max_columns() const; + + void set_select_mode(SelectMode p_mode); + SelectMode get_select_mode() const; + + void set_icon_mode(IconMode p_mode); + IconMode get_icon_mode() const; + + void set_min_icon_size(const Size2& p_size); + Size2 get_min_icon_size() 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; + + ItemList(); + ~ItemList(); +}; + +VARIANT_ENUM_CAST(ItemList::SelectMode); +VARIANT_ENUM_CAST(ItemList::IconMode); + + +#endif // ITEMLIST_H diff --git a/scene/gui/label.cpp b/scene/gui/label.cpp index 892e4c9bc7..e7af4fa349 100644 --- a/scene/gui/label.cpp +++ b/scene/gui/label.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -99,7 +99,7 @@ void Label::_notification(int p_what) { int chars_total=0; int vbegin=0,vsep=0; - + if (lines_total && lines_total < lines_visible) { @@ -136,10 +136,9 @@ void Label::_notification(int p_what) { if (!wc) return; - + int c = 0; int line=0; while(wc) { - /* handle lines not meant to be drawn quickly */ if (line>line_to) break; @@ -170,8 +169,8 @@ void Label::_notification(int p_what) { while(to && to->char_pos>=0) { taken+=to->pixel_width; - if (to!=from) { - spaces++; + if (to!=from && to->space_count) { + spaces+=to->space_count; } to=to->next; } @@ -212,15 +211,15 @@ void Label::_notification(int p_what) { ERR_PRINT("BUG"); return; } - if (from!=wc) { + if (from->space_count) { /* spacing */ - x_ofs+=space_w; + x_ofs+=space_w*from->space_count; if (can_fill && align==ALIGN_FILL && spaces) { - + x_ofs+=int((size.width-(taken+space_w*spaces))/spaces); } - - + + } @@ -253,7 +252,7 @@ void Label::_notification(int p_what) { } for (int i=0;i<from->word_len;i++) { - + if (visible_chars < 0 || chars_total<visible_chars) { CharType c = text[i+pos]; CharType n = text[i+pos+1]; @@ -361,11 +360,12 @@ void Label::regenerate_word_cache() { int width=autowrap?get_size().width:get_longest_line_width(); Ref<Font> font = get_font("font"); - + int current_word_size=0; int word_pos=0; int line_width=0; - int last_width=0; + int space_count=0; + int space_width=font->get_char_size(' ').width; line_count=1; total_char_cache=0; @@ -374,16 +374,21 @@ void Label::regenerate_word_cache() { for (int i=0;i<text.size()+1;i++) { CharType current=i<text.length()?text[i]:' '; //always a space at the end, so the algo works - + if (uppercase) current=String::char_uppercase(current); + // ranges taken from http://www.unicodemap.org/ + // if your language is not well supported, consider helping improve + // the unicode support in Godot. + bool separatable = (current>=0x2E08 && current<=0xFAFF) || (current>=0xFE30 && current<=0xFE4F); + //current>=33 && (current < 65||current >90) && (current<97||current>122) && (current<48||current>57); bool insert_newline=false; - + int char_width; + if (current<33) { - + if (current_word_size>0) { - WordCache *wc = memnew( WordCache ); if (word_cache) { last->next=wc; @@ -391,14 +396,16 @@ void Label::regenerate_word_cache() { word_cache=wc; } last=wc; - + wc->pixel_width=current_word_size; wc->char_pos=word_pos; wc->word_len=i-word_pos; + wc->space_count = space_count; current_word_size=0; - + space_count=0; + } - + if (current=='\n') { insert_newline=true; @@ -408,26 +415,49 @@ void Label::regenerate_word_cache() { if (i<text.length() && text[i] == ' ') { total_char_cache--; // do not count spaces + if (line_width > 0 || last==NULL || last->char_pos!=WordCache::CHAR_WRAPLINE) { + space_count++; + line_width+=space_width; + }else { + space_count=0; + } } } else { - + // latin characters if (current_word_size==0) { - if (line_width>0) // add a space before the new word if a word existed before - line_width+=font->get_char_size(' ').width; word_pos=i; } - int char_width=font->get_char_size(current).width; + char_width=font->get_char_size(current).width; current_word_size+=char_width; line_width+=char_width; total_char_cache++; } - - if ((autowrap && line_width>=width && last_width<width) || insert_newline) { - + + if ((autowrap && (line_width >= width) && ((last && last->char_pos >= 0) || separatable)) || insert_newline) { + if (separatable) { + if (current_word_size>0) { + WordCache *wc = memnew( WordCache ); + if (word_cache) { + last->next=wc; + } else { + word_cache=wc; + } + last=wc; + + wc->pixel_width=current_word_size-char_width; + wc->char_pos=word_pos; + wc->word_len=i-word_pos; + wc->space_count = space_count; + current_word_size=char_width; + space_count=0; + word_pos=i; + } + } + WordCache *wc = memnew( WordCache ); if (word_cache) { last->next=wc; @@ -435,18 +465,16 @@ void Label::regenerate_word_cache() { word_cache=wc; } last=wc; - + wc->pixel_width=0; wc->char_pos=insert_newline?WordCache::CHAR_NEWLINE:WordCache::CHAR_WRAPLINE; line_width=current_word_size; line_count++; + space_count=0; - } - last_width=line_width; - } //total_char_cache -= line_count + 1; // do not count new lines (including the first one) @@ -465,7 +493,7 @@ void Label::regenerate_word_cache() { set_max(line_count); word_cache_dirty=false; - + } @@ -585,11 +613,11 @@ void Label::_bind_methods() { BIND_CONSTANT( VALIGN_BOTTOM ); BIND_CONSTANT( VALIGN_FILL ); - ADD_PROPERTY( PropertyInfo( Variant::STRING, "text",PROPERTY_HINT_MULTILINE_TEXT,"",PROPERTY_USAGE_DEFAULT_INTL), _SCS("set_text"),_SCS("get_text") ); - ADD_PROPERTY( PropertyInfo( Variant::INT, "align", PROPERTY_HINT_ENUM,"Left,Center,Right,Fill" ),_SCS("set_align"),_SCS("get_align") ); - ADD_PROPERTY( PropertyInfo( Variant::INT, "valign", PROPERTY_HINT_ENUM,"Top,Center,Bottom,Fill" ),_SCS("set_valign"),_SCS("get_valign") ); - ADD_PROPERTY( PropertyInfo( Variant::BOOL, "autowrap"),_SCS("set_autowrap"),_SCS("has_autowrap") ); - ADD_PROPERTY( PropertyInfo( Variant::BOOL, "uppercase"),_SCS("set_uppercase"),_SCS("is_uppercase") ); + ADD_PROPERTYNZ( PropertyInfo( Variant::STRING, "text",PROPERTY_HINT_MULTILINE_TEXT,"",PROPERTY_USAGE_DEFAULT_INTL), _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_PROPERTYNZ( PropertyInfo( Variant::INT, "valign", PROPERTY_HINT_ENUM,"Top,Center,Bottom,Fill" ),_SCS("set_valign"),_SCS("get_valign") ); + ADD_PROPERTYNZ( PropertyInfo( Variant::BOOL, "autowrap"),_SCS("set_autowrap"),_SCS("has_autowrap") ); + ADD_PROPERTYNZ( PropertyInfo( Variant::BOOL, "uppercase"),_SCS("set_uppercase"),_SCS("is_uppercase") ); ADD_PROPERTY( PropertyInfo( Variant::REAL, "percent_visible", PROPERTY_HINT_RANGE,"0,1,0.001"),_SCS("set_percent_visible"),_SCS("get_percent_visible") ); } diff --git a/scene/gui/label.h b/scene/gui/label.h index 131ee3a944..81e3ab5676 100644 --- a/scene/gui/label.h +++ b/scene/gui/label.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -75,8 +75,9 @@ private: int char_pos; // if -1, then newline int word_len; int pixel_width; + int space_count; WordCache *next; - WordCache() { char_pos=0; word_len=0; pixel_width=0; next=0; } + WordCache() { char_pos=0; word_len=0; pixel_width=0; next=0; space_count=0;} }; bool word_cache_dirty; diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp index 68c990033a..fec9e401f1 100644 --- a/scene/gui/line_edit.cpp +++ b/scene/gui/line_edit.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -272,7 +272,7 @@ void LineEdit::_input_event(InputEvent p_event) { if (editable) { selection_delete(); - CharType ucodestr[2]={k.unicode,0}; + CharType ucodestr[2]={(CharType)k.unicode,0}; append_at_cursor(ucodestr); emit_signal("text_changed",text); _change_notify("text"); diff --git a/scene/gui/line_edit.h b/scene/gui/line_edit.h index 6c18594cda..c19043e826 100644 --- a/scene/gui/line_edit.h +++ b/scene/gui/line_edit.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/margin_container.cpp b/scene/gui/margin_container.cpp index 54373b7592..f10ca6353a 100644 --- a/scene/gui/margin_container.cpp +++ b/scene/gui/margin_container.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/margin_container.h b/scene/gui/margin_container.h index 7f0a1f53e3..56f2344ea7 100644 --- a/scene/gui/margin_container.h +++ b/scene/gui/margin_container.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/menu_button.cpp b/scene/gui/menu_button.cpp index d10ca20fc3..68fcb4bda8 100644 --- a/scene/gui/menu_button.cpp +++ b/scene/gui/menu_button.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/menu_button.h b/scene/gui/menu_button.h index 52c9a9aea5..47e7382d34 100644 --- a/scene/gui/menu_button.h +++ b/scene/gui/menu_button.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/option_button.cpp b/scene/gui/option_button.cpp index 78cc1bcdef..ff94a37be0 100644 --- a/scene/gui/option_button.cpp +++ b/scene/gui/option_button.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/option_button.h b/scene/gui/option_button.h index 295127175d..7d850479aa 100644 --- a/scene/gui/option_button.h +++ b/scene/gui/option_button.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/panel.cpp b/scene/gui/panel.cpp index fd1d5d2de6..d9ba20810b 100644 --- a/scene/gui/panel.cpp +++ b/scene/gui/panel.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/panel.h b/scene/gui/panel.h index 8dab05f1a6..7e6be62923 100644 --- a/scene/gui/panel.h +++ b/scene/gui/panel.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/panel_container.cpp b/scene/gui/panel_container.cpp index 91581ecccd..5ee061356e 100644 --- a/scene/gui/panel_container.cpp +++ b/scene/gui/panel_container.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/panel_container.h b/scene/gui/panel_container.h index ac67b52be8..c09479241c 100644 --- a/scene/gui/panel_container.h +++ b/scene/gui/panel_container.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/popup.cpp b/scene/gui/popup.cpp index d58cb3da79..5ce7e2e0d3 100644 --- a/scene/gui/popup.cpp +++ b/scene/gui/popup.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -84,6 +84,48 @@ void Popup::_fix_size() { } +void Popup::set_as_minsize() { + + Size2 total_minsize; + + for(int i=0;i<get_child_count();i++) { + + Control *c=get_child(i)->cast_to<Control>(); + if (!c) + continue; + if (c->is_hidden()) + continue; + + Size2 minsize = c->get_combined_minimum_size(); + + for(int j=0;j<2;j++) { + + Margin m_beg = Margin(0+j); + Margin m_end = Margin(2+j); + + float margin_begin = c->get_margin(m_beg); + float margin_end = c->get_margin(m_end); + AnchorType anchor_begin = c->get_anchor(m_beg); + AnchorType anchor_end = c->get_anchor(m_end); + + if (anchor_begin == ANCHOR_BEGIN) + minsize[j]+=margin_begin; + if (anchor_end == ANCHOR_END) + minsize[j]+=margin_end; + + } + + print_line(String(c->get_type())+": "+minsize); + + total_minsize.width = MAX( total_minsize.width, minsize.width ); + total_minsize.height = MAX( total_minsize.height, minsize.height ); + } + + set_size(total_minsize); + +} + + void Popup::popup_centered_minsize(const Size2& p_minsize) { diff --git a/scene/gui/popup.h b/scene/gui/popup.h index 072b66c2c7..6c72a3c82b 100644 --- a/scene/gui/popup.h +++ b/scene/gui/popup.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -62,6 +62,7 @@ public: void popup_centered_ratio(float p_screen_ratio=0.75); void popup_centered(const Size2& p_size=Size2()); void popup_centered_minsize(const Size2& p_minsize=Size2()); + void set_as_minsize(); virtual void popup(); diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp index 1fd1d8adc8..e706053592 100644 --- a/scene/gui/popup_menu.cpp +++ b/scene/gui/popup_menu.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/popup_menu.h b/scene/gui/popup_menu.h index d825ea2b68..ed78fe6738 100644 --- a/scene/gui/popup_menu.h +++ b/scene/gui/popup_menu.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/progress_bar.cpp b/scene/gui/progress_bar.cpp index 73fa1fbb98..e7e2c88f4a 100644 --- a/scene/gui/progress_bar.cpp +++ b/scene/gui/progress_bar.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/progress_bar.h b/scene/gui/progress_bar.h index fd34c67fae..33b0d5c185 100644 --- a/scene/gui/progress_bar.h +++ b/scene/gui/progress_bar.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/range.cpp b/scene/gui/range.cpp index 4d0b678925..ad708d16f0 100644 --- a/scene/gui/range.cpp +++ b/scene/gui/range.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/range.h b/scene/gui/range.h index e33a71e6ab..48361ddb0e 100644 --- a/scene/gui/range.h +++ b/scene/gui/range.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/reference_frame.cpp b/scene/gui/reference_frame.cpp index 44ba3a8972..b90ea8292d 100644 --- a/scene/gui/reference_frame.cpp +++ b/scene/gui/reference_frame.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/reference_frame.h b/scene/gui/reference_frame.h index 954b17b5c8..8915b1df0c 100644 --- a/scene/gui/reference_frame.h +++ b/scene/gui/reference_frame.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp index 94df42fc8f..7a607786ee 100644 --- a/scene/gui/rich_text_label.cpp +++ b/scene/gui/rich_text_label.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -58,7 +58,7 @@ RichTextLabel::Item *RichTextLabel::_get_next_item(Item* p_item) { } -void RichTextLabel::_process_line(int &y, int p_width, int p_line, ProcessMode p_mode,const Ref<Font> &p_base_font,const Color &p_base_color,const Point2i& p_click_pos,Item **r_click_item,int *r_click_char,bool *r_outside) { +void RichTextLabel::_process_line(int &y, int p_width, int p_line, ProcessMode p_mode,const Ref<Font> &p_base_font,const Color &p_base_color,const Point2i& p_click_pos,Item **r_click_item,int *r_click_char,bool *r_outside,int p_char_count) { RID ci; if (r_outside) @@ -78,6 +78,8 @@ void RichTextLabel::_process_line(int &y, int p_width, int p_line, ProcessMode p int margin=_find_margin(it,p_base_font); Align align=_find_align(it);; int line=0; + int spaces=0; + if (p_mode!=PROCESS_CACHE) { @@ -85,7 +87,14 @@ void RichTextLabel::_process_line(int &y, int p_width, int p_line, ProcessMode p line_ofs = l.offset_caches[line]; } + if (p_mode==PROCESS_CACHE) { + l.offset_caches.clear(); + l.height_caches.clear(); + l.char_count=0; + } + int wofs=margin; + int spaces_size=0; if (p_mode!=PROCESS_CACHE && align!=ALIGN_FILL) wofs+=line_ofs; @@ -101,7 +110,6 @@ void RichTextLabel::_process_line(int &y, int p_width, int p_line, ProcessMode p Variant meta; - #define NEW_LINE \ {\ if (p_mode!=PROCESS_CACHE) {\ @@ -117,12 +125,15 @@ void RichTextLabel::_process_line(int &y, int p_width, int p_line, ProcessMode p case ALIGN_LEFT: l.offset_caches.push_back(0); break;\ case ALIGN_CENTER: l.offset_caches.push_back(((p_width-margin)-used)/2); break;\ case ALIGN_RIGHT: l.offset_caches.push_back(((p_width-margin)-used)); break;\ - case ALIGN_FILL: l.offset_caches.push_back(p_width-wofs); break;\ + case ALIGN_FILL: l.offset_caches.push_back((p_width-margin)-used+spaces_size); break;\ }\ l.height_caches.push_back(line_height);\ + l.space_caches.push_back(spaces);\ }\ y+=line_height+get_constant(SceneStringNames::get_singleton()->line_separation);\ line_height=0;\ + spaces=0;\ + spaces_size=0;\ wofs=begin;\ if (p_mode!=PROCESS_CACHE) {\ lh=line<l.height_caches.size()?l.height_caches[line]:1;\ @@ -138,6 +149,10 @@ void RichTextLabel::_process_line(int &y, int p_width, int p_line, ProcessMode p #define ENSURE_WIDTH(m_width) \ if (wofs + m_width > p_width) {\ + if (p_mode==PROCESS_CACHE) {\ + if (spaces>0) \ + spaces-=1;\ + }\ if (p_mode==PROCESS_POINTER && r_click_item && p_click_pos.y>=y && p_click_pos.y<=y+lh && p_click_pos.x>wofs) {\ if (r_outside) *r_outside=true; \ *r_click_item=it;\ @@ -203,33 +218,76 @@ if (m_height > line_height) {\ underline=true; } + } else if (p_mode==PROCESS_CACHE) { + l.char_count+=text->text.length(); } rchar=0; + while(*c) { int end=0; int w=0; + int fw=0; lh=0; if (p_mode!=PROCESS_CACHE) { lh=line<l.height_caches.size()?l.height_caches[line]:1; } + bool found_space=false; while (c[end]!=0 && !(end && c[end-1]==' ' && c[end]!=' ')) { + int cw = font->get_char_size(c[end],c[end+1]).width; + if (c[end]=='\t') { + cw=tab_size*font->get_char_size(' ').width; + } w+=cw; - end++; + + if (c[end]==' ') { + + if (p_mode==PROCESS_CACHE) { + fw+=cw; + } else if (align==ALIGN_FILL && line<l.space_caches.size() && l.space_caches[line]>0) { + //print_line(String(c,end)+": "+itos(l.offset_caches[line])+"/"+itos(l.space_caches[line])); + //sub_space=cw; + found_space=true; + } else { + fw+=cw; + } + } else { + fw+=cw; + } + + end++; } - ENSURE_WIDTH(w); + ENSURE_WIDTH(w); + + + //print_line("END: "+String::chr(c[end])+"."); + if (end && c[end-1]==' ') { + spaces++; + if (p_mode==PROCESS_CACHE) { + spaces_size+=font->get_char_size(' ').width; + } + + if (found_space) { + int ln = MIN(l.offset_caches.size()-1,line); + + fw+=l.offset_caches[ln]/l.space_caches[ln]; + } + + } + { int ofs=0; + for(int i=0;i<end;i++) { int pofs=wofs+ofs; @@ -239,7 +297,11 @@ if (m_height > line_height) {\ if (p_mode==PROCESS_POINTER && r_click_char && p_click_pos.y>=y && p_click_pos.y<=y+lh) { //int o = (wofs+w)-p_click_pos.x; + int cw=font->get_char_size(c[i],c[i+1]).x; + if (c[i]=='\t') { + cw=tab_size*font->get_char_size(' ').width; + } if (p_click_pos.x-cw/2>pofs) { @@ -268,22 +330,36 @@ if (m_height > line_height) {\ } } - int cw; + int cw=0; + + bool visible = visible_characters<0 || p_char_count<visible_characters; if (selected) { cw = font->get_char_size(c[i],c[i+1]).x; draw_rect(Rect2(pofs,y,cw,lh),selection_bg); - font->draw_char(ci,Point2(pofs,y+lh-(fh-ascent)),c[i],c[i+1],selection_fg); + if (visible) + font->draw_char(ci,Point2(pofs,y+lh-(fh-ascent)),c[i],c[i+1],selection_fg); } else { - cw=font->draw_char(ci,Point2(pofs,y+lh-(fh-ascent)),c[i],c[i+1],color); + if (visible) + cw=font->draw_char(ci,Point2(pofs,y+lh-(fh-ascent)),c[i],c[i+1],color); + } + + p_char_count++; + if (c[i]=='\t') { + cw=tab_size*font->get_char_size(' ').width; } + + //print_line("draw char: "+String::chr(c[i])); + if (underline) { Color uc=color; - uc.a*=0.3; - VS::get_singleton()->canvas_item_add_line(ci,Point2(pofs,y+ascent+2),Point2(pofs+cw,y+ascent+2),uc); + uc.a*=0.5; + //VS::get_singleton()->canvas_item_add_line(ci,Point2(pofs,y+ascent+2),Point2(pofs+cw,y+ascent+2),uc); + int uy = y+lh-fh+ascent+2; + VS::get_singleton()->canvas_item_add_line(ci,Point2(pofs,uy),Point2(pofs+cw,uy),uc); } ofs+=cw; } @@ -292,7 +368,7 @@ if (m_height > line_height) {\ } - ADVANCE(w); + ADVANCE(fw); CHECK_HEIGHT(fh); //must be done somewhere c=&c[end]; } @@ -304,6 +380,8 @@ if (m_height > line_height) {\ lh=0; if (p_mode!=PROCESS_CACHE) lh = line<l.height_caches.size()?l.height_caches[line]:1; + else + l.char_count+=1; //images count as chars too ItemImage *img = static_cast<ItemImage*>(it); @@ -316,9 +394,12 @@ if (m_height > line_height) {\ ENSURE_WIDTH( img->image->get_width() ); - if (p_mode==PROCESS_DRAW) { + bool visible = visible_characters<0 || p_char_count<visible_characters; + + if (p_mode==PROCESS_DRAW && visible) { img->image->draw(ci,Point2(wofs,y+lh-font->get_descent()-img->image->get_height())); } + p_char_count++; ADVANCE( img->image->get_width() ); CHECK_HEIGHT( (img->image->get_height()+font->get_descent()) ); @@ -450,6 +531,23 @@ void RichTextLabel::_notification(int p_what) { update(); } break; + case NOTIFICATION_ENTER_TREE: { + + if (use_bbcode) + parse_bbcode(bbcode); + first_invalid_line=0; //invalidate ALL + update(); + + } break; + case NOTIFICATION_THEME_CHANGED: { + + if (is_inside_tree() && use_bbcode) { + parse_bbcode(bbcode); + //first_invalid_line=0; //invalidate ALL + //update(); + } + + } break; case NOTIFICATION_DRAW: { _validate_line_caches(); @@ -472,23 +570,26 @@ void RichTextLabel::_notification(int p_what) { //todo, change to binary search int from_line = 0; + int total_chars = 0; while (from_line<lines.size()) { if (lines[from_line].height_accum_cache>=ofs) break; from_line++; + total_chars+=lines[from_line].char_count; } if (from_line>=lines.size()) break; //nothing to draw int y = (lines[from_line].height_accum_cache - lines[from_line].height_cache) - ofs; - Ref<Font> base_font=get_font("default_font"); + Ref<Font> base_font=get_font("normal_font"); Color base_color=get_color("default_color"); while (y<size.height && from_line<lines.size()) { - _process_line(y,size.width-scroll_w,from_line,PROCESS_DRAW,base_font,base_color); + _process_line(y,size.width-scroll_w,from_line,PROCESS_DRAW,base_font,base_color,Point2i(),NULL,NULL,NULL,total_chars); + total_chars+=lines[from_line].char_count; from_line++; } } @@ -521,7 +622,7 @@ void RichTextLabel::_find_click(const Point2i& p_click,Item **r_click_item,int * int y = (lines[from_line].height_accum_cache - lines[from_line].height_cache) - ofs; - Ref<Font> base_font=get_font("default_font"); + Ref<Font> base_font=get_font("normal_font"); Color base_color=get_color("default_color"); @@ -634,12 +735,12 @@ void RichTextLabel::_input_event(InputEvent p_event) { case KEY_UP: { if (vscroll->is_visible()) - vscroll->set_val( vscroll->get_val() - get_font("default_font")->get_height() ); + vscroll->set_val( vscroll->get_val() - get_font("normal_font")->get_height() ); } break; case KEY_DOWN: { if (vscroll->is_visible()) - vscroll->set_val( vscroll->get_val() + get_font("default_font")->get_height() ); + vscroll->set_val( vscroll->get_val() + get_font("normal_font")->get_height() ); } break; case KEY_HOME: { @@ -856,13 +957,12 @@ void RichTextLabel::_validate_line_caches() { //validate invalid lines!s Size2 size = get_size(); - Ref<Font> base_font=get_font("default_font"); + Ref<Font> base_font=get_font("normal_font"); for(int i=first_invalid_line;i<lines.size();i++) { int y=0; _process_line(y,size.width-scroll_w,i,PROCESS_CACHE,base_font,Color()); - lines[i].height_cache=y; lines[i].height_accum_cache=y; @@ -1152,9 +1252,19 @@ Error RichTextLabel::append_bbcode(const String& p_bbcode) { int pos = 0; List<String> tag_stack; - Ref<Font> base_font=get_font("default_font"); + Ref<Font> normal_font=get_font("normal_font"); + Ref<Font> bold_font=get_font("bold_font"); + Ref<Font> italics_font=get_font("italics_font"); + Ref<Font> bold_italics_font=get_font("bold_italics_font"); + Ref<Font> mono_font=get_font("mono_font"); + Color base_color=get_color("default_color"); + int indent_level=0; + + bool in_bold=false; + bool in_italics=false; + while(pos < p_bbcode.length()) { @@ -1182,12 +1292,18 @@ Error RichTextLabel::append_bbcode(const String& p_bbcode) { String tag = p_bbcode.substr(brk_pos+1,brk_end-brk_pos-1); - if (tag.begins_with("/")) { + if (tag.begins_with("/") && tag_stack.size()) { bool tag_ok = tag_stack.size() && tag_stack.front()->get()==tag.substr(1,tag.length()); + if (tag_stack.front()->get()=="b") + in_bold=false; + if (tag_stack.front()->get()=="i") + in_italics=false; + if (tag_stack.front()->get()=="indent") + indent_level--; if (!tag_ok) { @@ -1205,19 +1321,27 @@ Error RichTextLabel::append_bbcode(const String& p_bbcode) { } else if (tag=="b") { //use bold font - push_font(base_font); + in_bold=true; + if (in_italics) + push_font(bold_italics_font); + else + push_font(bold_font); pos=brk_end+1; tag_stack.push_front(tag); } else if (tag=="i") { //use italics font - push_font(base_font); + in_italics=true; + if (in_bold) + push_font(bold_italics_font); + else + push_font(italics_font); pos=brk_end+1; tag_stack.push_front(tag); } else if (tag=="code") { //use monospace font - push_font(base_font); + push_font(mono_font); pos=brk_end+1; tag_stack.push_front(tag); } else if (tag=="u") { @@ -1232,6 +1356,43 @@ Error RichTextLabel::append_bbcode(const String& p_bbcode) { push_underline(); pos=brk_end+1; tag_stack.push_front(tag); + } else if (tag=="center") { + + //use underline + push_align(ALIGN_CENTER); + pos=brk_end+1; + tag_stack.push_front(tag); + } else if (tag=="fill") { + + //use underline + push_align(ALIGN_FILL); + pos=brk_end+1; + tag_stack.push_front(tag); + } else if (tag=="right") { + + //use underline + push_align(ALIGN_RIGHT); + pos=brk_end+1; + tag_stack.push_front(tag); + } else if (tag=="ul") { + + //use underline + push_list(LIST_DOTS); + pos=brk_end+1; + tag_stack.push_front(tag); + } else if (tag=="ol") { + + //use underline + push_list(LIST_NUMBERS); + pos=brk_end+1; + tag_stack.push_front(tag); + } else if (tag=="indent") { + + //use underline + indent_level++; + push_indent(indent_level); + pos=brk_end+1; + tag_stack.push_front(tag); } else if (tag=="url") { @@ -1244,6 +1405,7 @@ Error RichTextLabel::append_bbcode(const String& p_bbcode) { pos=brk_end+1; tag_stack.push_front(tag); + } else if (tag.begins_with("url=")) { String url = tag.substr(4,tag.length()); @@ -1321,7 +1483,7 @@ Error RichTextLabel::append_bbcode(const String& p_bbcode) { if (font.is_valid()) push_font(font); else - push_font(base_font); + push_font(normal_font); pos=brk_end+1; tag_stack.push_front("font"); @@ -1467,7 +1629,7 @@ void RichTextLabel::selection_copy() { if (text!="") { OS::get_singleton()->set_clipboard(text); - print_line("COPY: "+text); + //print_line("COPY: "+text); } } @@ -1477,7 +1639,29 @@ bool RichTextLabel::is_selection_enabled() const { return selection.enabled; } +void RichTextLabel::set_bbcode(const String& p_bbcode) { + bbcode=p_bbcode; + if (is_inside_tree() && use_bbcode) + parse_bbcode(p_bbcode); +} + +String RichTextLabel::get_bbcode() const { + + return bbcode; +} + +void RichTextLabel::set_use_bbcode(bool p_enable) { + if (use_bbcode==p_enable) + return; + use_bbcode=p_enable; + if (is_inside_tree() && use_bbcode) + parse_bbcode(bbcode); +} +bool RichTextLabel::is_using_bbcode() const { + + return use_bbcode; +} void RichTextLabel::_bind_methods() { @@ -1506,15 +1690,32 @@ void RichTextLabel::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_scroll_follow","follow"),&RichTextLabel::set_scroll_follow); ObjectTypeDB::bind_method(_MD("is_scroll_following"),&RichTextLabel::is_scroll_following); + ObjectTypeDB::bind_method(_MD("get_v_scroll"),&RichTextLabel::get_v_scroll); + ObjectTypeDB::bind_method(_MD("set_tab_size","spaces"),&RichTextLabel::set_tab_size); ObjectTypeDB::bind_method(_MD("get_tab_size"),&RichTextLabel::get_tab_size); + ObjectTypeDB::bind_method(_MD("set_selection_enabled","enabled"),&RichTextLabel::set_selection_enabled); ObjectTypeDB::bind_method(_MD("is_selection_enabled"),&RichTextLabel::is_selection_enabled); ObjectTypeDB::bind_method(_MD("parse_bbcode", "bbcode"),&RichTextLabel::parse_bbcode); ObjectTypeDB::bind_method(_MD("append_bbcode", "bbcode"),&RichTextLabel::append_bbcode); + ObjectTypeDB::bind_method(_MD("set_bbcode","text"),&RichTextLabel::set_bbcode); + ObjectTypeDB::bind_method(_MD("get_bbcode"),&RichTextLabel::get_bbcode); + + ObjectTypeDB::bind_method(_MD("set_visible_characters","amount"),&RichTextLabel::set_visible_characters); + ObjectTypeDB::bind_method(_MD("get_visible_characters"),&RichTextLabel::get_visible_characters); + + ObjectTypeDB::bind_method(_MD("get_total_character_count"),&RichTextLabel::get_total_character_count); + + ObjectTypeDB::bind_method(_MD("set_use_bbcode","enable"),&RichTextLabel::set_use_bbcode); + ObjectTypeDB::bind_method(_MD("is_using_bbcode"),&RichTextLabel::is_using_bbcode); + + ADD_PROPERTY(PropertyInfo(Variant::BOOL,"bbcode/enabled"),_SCS("set_use_bbcode"),_SCS("is_using_bbcode")); + ADD_PROPERTY(PropertyInfo(Variant::STRING,"bbcode/bbcode",PROPERTY_HINT_MULTILINE_TEXT),_SCS("set_bbcode"),_SCS("get_bbcode")); + ADD_PROPERTY(PropertyInfo(Variant::INT,"visible_characters",PROPERTY_HINT_RANGE,"-1,128000,1"),_SCS("set_visible_characters"),_SCS("get_visible_characters")); ADD_SIGNAL( MethodInfo("meta_clicked",PropertyInfo(Variant::NIL,"meta"))); @@ -1541,6 +1742,27 @@ void RichTextLabel::_bind_methods() { } + +void RichTextLabel::set_visible_characters(int p_visible) { + + visible_characters=p_visible; + update(); +} + +int RichTextLabel::get_visible_characters() const { + + return visible_characters; +} +int RichTextLabel::get_total_character_count() const { + + int tc=0; + for(int i=0;i<lines.size();i++) + tc+=lines[i].char_count; + + return tc; +} + + RichTextLabel::RichTextLabel() { @@ -1572,11 +1794,14 @@ RichTextLabel::RichTextLabel() { vscroll->set_step(1); vscroll->hide(); current_idx=1; + use_bbcode=false; selection.click=NULL; selection.active=false; selection.enabled=false; + visible_characters=-1; + } RichTextLabel::~RichTextLabel() { diff --git a/scene/gui/rich_text_label.h b/scene/gui/rich_text_label.h index 228d607049..eaa8d5d60a 100644 --- a/scene/gui/rich_text_label.h +++ b/scene/gui/rich_text_label.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -168,10 +168,12 @@ private: Item *from; Vector<int> offset_caches; Vector<int> height_caches; + Vector<int> space_caches; int height_cache; int height_accum_cache; + int char_count; - Line() { from=NULL; } + Line() { from=NULL; char_count=0; } }; @@ -222,10 +224,10 @@ private: Selection selection; + int visible_characters; - - void _process_line(int &y, int p_width, int p_line, ProcessMode p_mode,const Ref<Font> &p_base_font,const Color &p_base_color,const Point2i& p_click_pos=Point2i(),Item **r_click_item=NULL,int *r_click_char=NULL,bool *r_outside=NULL); + void _process_line(int &y, int p_width, int p_line, ProcessMode p_mode,const Ref<Font> &p_base_font,const Color &p_base_color,const Point2i& p_click_pos=Point2i(),Item **r_click_item=NULL,int *r_click_char=NULL,bool *r_outside=NULL,int p_char_count=0); void _find_click(const Point2i& p_click,Item **r_click_item=NULL,int *r_click_char=NULL,bool *r_outside=NULL); @@ -242,6 +244,10 @@ private: void _input_event(InputEvent p_event); Item *_get_next_item(Item* p_item); + bool use_bbcode; + String bbcode; + + protected: void _notification(int p_what); @@ -291,9 +297,20 @@ public: bool is_selection_enabled() const; void selection_copy(); + Error parse_bbcode(const String& p_bbcode); Error append_bbcode(const String& p_bbcode); + void set_use_bbcode(bool p_enable); + bool is_using_bbcode() const; + + void set_bbcode(const String& p_bbcode); + String get_bbcode() const; + + void set_visible_characters(int p_visible); + int get_visible_characters() const; + int get_total_character_count() const; + RichTextLabel(); ~RichTextLabel(); }; diff --git a/scene/gui/scroll_bar.cpp b/scene/gui/scroll_bar.cpp index aaf96114c6..b1fd914fcd 100644 --- a/scene/gui/scroll_bar.cpp +++ b/scene/gui/scroll_bar.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -51,20 +51,20 @@ void ScrollBar::_input_event(InputEvent p_event) { if (b.button_index==5 && b.pressed) { - if (orientation==VERTICAL) - set_val( get_val() + get_page() / 4.0 ); - else - set_val( get_val() + get_page() / 4.0 ); + //if (orientation==VERTICAL) + // set_val( get_val() + get_page() / 4.0 ); + //else + set_val( get_val() + get_page() / 4.0 ); accept_event(); } if (b.button_index==4 && b.pressed) { - if (orientation==HORIZONTAL) - set_val( get_val() - get_page() / 4.0 ); - else - set_val( get_val() - get_page() / 4.0 ); + //if (orientation==HORIZONTAL) + // set_val( get_val() - get_page() / 4.0 ); + //else + set_val( get_val() - get_page() / 4.0 ); accept_event(); } diff --git a/scene/gui/scroll_bar.h b/scene/gui/scroll_bar.h index ad3d1a7f58..367bc3eb53 100644 --- a/scene/gui/scroll_bar.h +++ b/scene/gui/scroll_bar.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/scroll_container.cpp b/scene/gui/scroll_container.cpp index 95354df519..8f753f51bc 100644 --- a/scene/gui/scroll_container.cpp +++ b/scene/gui/scroll_container.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/scroll_container.h b/scene/gui/scroll_container.h index c8b03b3671..b8d37be08c 100644 --- a/scene/gui/scroll_container.h +++ b/scene/gui/scroll_container.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/separator.cpp b/scene/gui/separator.cpp index aac9ac0d03..5e822a10ad 100644 --- a/scene/gui/separator.cpp +++ b/scene/gui/separator.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/separator.h b/scene/gui/separator.h index 177e69cffe..17e9c11e34 100644 --- a/scene/gui/separator.h +++ b/scene/gui/separator.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/slider.cpp b/scene/gui/slider.cpp index 39d0ccfd10..b6292c544b 100644 --- a/scene/gui/slider.cpp +++ b/scene/gui/slider.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/slider.h b/scene/gui/slider.h index d9cb7e754b..5850c48ce3 100644 --- a/scene/gui/slider.h +++ b/scene/gui/slider.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/spin_box.cpp b/scene/gui/spin_box.cpp index 9ac67e92f5..41e775bbff 100644 --- a/scene/gui/spin_box.cpp +++ b/scene/gui/spin_box.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/spin_box.h b/scene/gui/spin_box.h index 70121c9088..6ebe14631e 100644 --- a/scene/gui/spin_box.h +++ b/scene/gui/spin_box.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/split_container.cpp b/scene/gui/split_container.cpp index 49a7957d7c..d7ee7a6b86 100644 --- a/scene/gui/split_container.cpp +++ b/scene/gui/split_container.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -345,6 +345,7 @@ void SplitContainer::_input_event(const InputEvent& p_event) { expand_ofs=drag_ofs+((vertical?mm.y:mm.x)-drag_from); queue_sort(); + emit_signal("dragged",get_split_offset()); } } @@ -431,11 +432,13 @@ void SplitContainer::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_dragger_visible","visible"),&SplitContainer::set_dragger_visible); ObjectTypeDB::bind_method(_MD("is_dragger_visible"),&SplitContainer::is_dragger_visible); + ADD_SIGNAL( MethodInfo("dragged",PropertyInfo(Variant::INT,"offset"))); ADD_PROPERTY( PropertyInfo(Variant::INT,"split/offset"),_SCS("set_split_offset"),_SCS("get_split_offset")); ADD_PROPERTY( PropertyInfo(Variant::INT,"split/collapsed"),_SCS("set_collapsed"),_SCS("is_collapsed")); ADD_PROPERTY( PropertyInfo(Variant::INT,"split/dragger_visible"),_SCS("set_dragger_visible"),_SCS("is_dragger_visible")); + } SplitContainer::SplitContainer(bool p_vertical) { diff --git a/scene/gui/split_container.h b/scene/gui/split_container.h index 4065b7818c..d7f56c6fb4 100644 --- a/scene/gui/split_container.h +++ b/scene/gui/split_container.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/tab_container.cpp b/scene/gui/tab_container.cpp index 12a8a83f26..3ed182c017 100644 --- a/scene/gui/tab_container.cpp +++ b/scene/gui/tab_container.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -88,7 +88,22 @@ void TabContainer::_input_event(const InputEvent& p_event) { Ref<Font> font = get_font("font"); Ref<Texture> incr = get_icon("increment"); Ref<Texture> decr = get_icon("decrement"); + Ref<Texture> menu = get_icon("menu"); + Ref<Texture> menu_hl = get_icon("menu_hl"); + if (popup && pos.x>get_size().width-menu->get_width()) { + + + emit_signal("pre_popup_pressed"); + Vector2 pp_pos = get_global_pos(); + pp_pos.x+=get_size().width; + pp_pos.x-=popup->get_size().width; + pp_pos.y+=menu->get_height(); + + popup->set_global_pos( pp_pos ); + popup->popup();; + return; + } pos.x-=tabs_ofs_cache; int idx=0; @@ -116,17 +131,17 @@ void TabContainer::_input_event(const InputEvent& p_event) { String s = c->has_meta("_tab_name")?String(XL_MESSAGE(String(c->get_meta("_tab_name")))):String(c->get_name()); int tab_width=font->get_string_size(s).width; - if (c->has_meta("_tab_icon")) { - Ref<Texture> icon = c->get_meta("_tab_icon"); - if (icon.is_valid()) { - tab_width+=icon->get_width(); - if (s!="") - tab_width+=get_constant("hseparation"); + if (c->has_meta("_tab_icon")) { + Ref<Texture> icon = c->get_meta("_tab_icon"); + if (icon.is_valid()) { + tab_width+=icon->get_width(); + if (s!="") + tab_width+=get_constant("hseparation"); - } - } + } + } - if (idx==current) { + if (idx==current) { tab_width+=tab_fg->get_minimum_size().width; } else { @@ -163,7 +178,7 @@ void TabContainer::_input_event(const InputEvent& p_event) { if (found!=-1) { - set_current_tab(found); + set_current_tab(found); } } @@ -194,7 +209,9 @@ void TabContainer::_notification(int p_what) { Ref<Texture> incr = get_icon("increment"); Ref<Texture> incr_hl = get_icon("increment_hilite"); Ref<Texture> decr = get_icon("decrement"); - Ref<Texture> decr_hl = get_icon("decrement_hilite"); + Ref<Texture> decr_hl = get_icon("decrement_hilite"); + Ref<Texture> menu = get_icon("menu"); + Ref<Texture> menu_hl = get_icon("menu_hl"); Ref<Font> font = get_font("font"); Color color_fg = get_color("font_color_fg"); Color color_bg = get_color("font_color_bg"); @@ -209,6 +226,7 @@ void TabContainer::_notification(int p_what) { Size2 top_size = Size2( size.width, top_margin ); + int w=0; int idx=0; for(int i=0;i<get_child_count();i++) { @@ -227,7 +245,7 @@ void TabContainer::_notification(int p_what) { if (icon.is_valid()) { w+=icon->get_width(); if (s!="") - w+=get_constant("hseparation"); + w+=get_constant("hseparation"); } } @@ -245,14 +263,18 @@ void TabContainer::_notification(int p_what) { int ofs; int limit=get_size().width; + if (popup) { + top_size.width-=menu->get_width(); + limit-=menu->get_width(); + } - if (w<=get_size().width) { + if (w<=limit) { switch(align) { case ALIGN_LEFT: ofs = side_margin; break; - case ALIGN_CENTER: ofs = (int(top_size.width) - w)/2; break; - case ALIGN_RIGHT: ofs = int(top_size.width) - w - side_margin; break; + case ALIGN_CENTER: ofs = (int(limit) - w)/2; break; + case ALIGN_RIGHT: ofs = int(limit) - w - side_margin; break; }; tab_display_ofs=0; @@ -364,6 +386,15 @@ void TabContainer::_notification(int p_what) { incr->draw(ci,Point2(limit+incr->get_width(),vofs),Color(1,1,1,notdone?1.0:0.5)); } + if (popup) { + int from = get_size().width-menu->get_width(); + + if (mouse_x_cache > from) + menu_hl->draw(get_canvas_item(),Size2(from,0)); + else + menu->draw(get_canvas_item(),Size2(from,0)); + } + panel->draw(ci, Rect2( 0, top_size.height, size.width, size.height-top_size.height)); } break; @@ -465,6 +496,48 @@ int TabContainer::get_current_tab() const { return current; } +Control* TabContainer::get_tab_control(int p_idx) const { + + int idx=0; + + + for(int i=0;i<get_child_count();i++) { + + Control *c = get_child(i)->cast_to<Control>(); + if (!c) + continue; + if (c->is_set_as_toplevel()) + continue; + if (idx==p_idx) { + return c; + + } + idx++; + } + + return NULL; +} +Control* TabContainer::get_current_tab_control() const { + + int idx=0; + + + for(int i=0;i<get_child_count();i++) { + + Control *c = get_child(i)->cast_to<Control>(); + if (!c) + continue; + if (c->is_set_as_toplevel()) + continue; + if (idx==current) { + return c; + + } + idx++; + } + + return NULL; +} void TabContainer::remove_child_notify(Node *p_child) { @@ -635,12 +708,25 @@ Size2 TabContainer::get_minimum_size() const { return ms; } +void TabContainer::set_popup(Node *p_popup) { + ERR_FAIL_NULL(p_popup); + popup=p_popup->cast_to<Popup>(); + update(); +} + +Popup* TabContainer::get_popup() const { + return popup; +} + + void TabContainer::_bind_methods() { ObjectTypeDB::bind_method(_MD("_input_event"),&TabContainer::_input_event); ObjectTypeDB::bind_method(_MD("get_tab_count"),&TabContainer::get_tab_count); ObjectTypeDB::bind_method(_MD("set_current_tab","tab_idx"),&TabContainer::set_current_tab); ObjectTypeDB::bind_method(_MD("get_current_tab"),&TabContainer::get_current_tab); + ObjectTypeDB::bind_method(_MD("get_current_tab_control:Control"),&TabContainer::get_current_tab_control); + ObjectTypeDB::bind_method(_MD("get_tab_control:Control","idx"),&TabContainer::get_tab_control); ObjectTypeDB::bind_method(_MD("set_tab_align","align"),&TabContainer::set_tab_align); ObjectTypeDB::bind_method(_MD("get_tab_align"),&TabContainer::get_tab_align); ObjectTypeDB::bind_method(_MD("set_tabs_visible","visible"),&TabContainer::set_tabs_visible); @@ -649,10 +735,13 @@ void TabContainer::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_tab_title","tab_idx"),&TabContainer::get_tab_title); ObjectTypeDB::bind_method(_MD("set_tab_icon","tab_idx","icon:Texture"),&TabContainer::set_tab_icon); ObjectTypeDB::bind_method(_MD("get_tab_icon:Texture","tab_idx"),&TabContainer::get_tab_icon); + ObjectTypeDB::bind_method(_MD("set_popup","popup:Popup"),&TabContainer::set_popup); + ObjectTypeDB::bind_method(_MD("get_popup:Popup"),&TabContainer::get_popup); ObjectTypeDB::bind_method(_MD("_child_renamed_callback"),&TabContainer::_child_renamed_callback); ADD_SIGNAL(MethodInfo("tab_changed",PropertyInfo(Variant::INT,"tab"))); + ADD_SIGNAL(MethodInfo("pre_popup_pressed")); ADD_PROPERTY( PropertyInfo(Variant::INT, "tab_align", PROPERTY_HINT_ENUM,"Left,Center,Right"), _SCS("set_tab_align"), _SCS("get_tab_align") ); ADD_PROPERTY( PropertyInfo(Variant::INT, "current_tab", PROPERTY_HINT_RANGE,"-1,4096,1",PROPERTY_USAGE_EDITOR), _SCS("set_current_tab"), _SCS("get_current_tab") ); @@ -669,5 +758,6 @@ TabContainer::TabContainer() { mouse_x_cache=0; align=ALIGN_CENTER; tabs_visible=true; + popup=NULL; } diff --git a/scene/gui/tab_container.h b/scene/gui/tab_container.h index df7b03e040..602d248b46 100644 --- a/scene/gui/tab_container.h +++ b/scene/gui/tab_container.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,7 +31,7 @@ #include "scene/gui/control.h" - +#include "scene/gui/popup.h" class TabContainer : public Control { OBJ_TYPE( TabContainer, Control ); @@ -55,6 +55,8 @@ private: TabAlign align; Control *_get_tab(int idx) const; int _get_top_margin() const; + Popup *popup; + protected: @@ -85,10 +87,17 @@ public: void set_current_tab(int p_current); int get_current_tab() const; + Control* get_tab_control(int p_idx) const; + Control* get_current_tab_control() const; + virtual Size2 get_minimum_size() const; virtual void get_translatable_strings(List<String> *p_strings) const; + void set_popup(Node *p_popup); + Popup* get_popup() const; + + TabContainer(); }; diff --git a/scene/gui/tabs.cpp b/scene/gui/tabs.cpp index ae7a4d59a7..a849d3ae72 100644 --- a/scene/gui/tabs.cpp +++ b/scene/gui/tabs.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -56,7 +56,14 @@ Size2 Tabs::get_minimum_size() const { else ms.width+=tab_bg->get_minimum_size().width; + if (tabs[i].right_button.is_valid()) { + Ref<Texture> rb=tabs[i].right_button; + Size2 bms = rb->get_size()+get_stylebox("button")->get_minimum_size(); + bms.width+=get_constant("hseparation"); + ms.width+=bms.width; + ms.height=MAX(bms.height+tab_bg->get_minimum_size().height,ms.height); + } } return ms; @@ -66,6 +73,39 @@ Size2 Tabs::get_minimum_size() const { void Tabs::_input_event(const InputEvent& p_event) { + if (p_event.type==InputEvent::MOUSE_MOTION) { + + Point2 pos( p_event.mouse_motion.x, p_event.mouse_motion.y ); + + int hover=-1; + for(int i=0;i<tabs.size();i++) { + + if (tabs[i].rb_rect.has_point(pos)) { + hover=i; + break; + } + } + + if (hover!=rb_hover) { + rb_hover=hover; + update(); + } + return; + } + + if (rb_pressing && p_event.type==InputEvent::MOUSE_BUTTON && + !p_event.mouse_button.pressed && + p_event.mouse_button.button_index==BUTTON_LEFT) { + + if (rb_hover!=-1) { + //pressed + emit_signal("right_button_pressed",rb_hover); + } + + rb_pressing=false; + update(); + } + if (p_event.type==InputEvent::MOUSE_BUTTON && p_event.mouse_button.pressed && p_event.mouse_button.button_index==BUTTON_LEFT) { @@ -76,9 +116,15 @@ void Tabs::_input_event(const InputEvent& p_event) { int found=-1; for(int i=0;i<tabs.size();i++) { - int ofs=tabs[i].ofs_cache; + if (tabs[i].rb_rect.has_point(pos)) { + rb_pressing=true; + update(); + return; + } - if (pos.x < ofs) { + int ofs=tabs[i].ofs_cache; + int size = tabs[i].ofs_cache; + if (pos.x >=tabs[i].ofs_cache && pos.x<tabs[i].ofs_cache+tabs[i].size_cache) { found=i; break; @@ -89,6 +135,7 @@ void Tabs::_input_event(const InputEvent& p_event) { if (found!=-1) { set_current_tab(found); + emit_signal("tab_changed",found); } } @@ -99,7 +146,10 @@ void Tabs::_notification(int p_what) { switch(p_what) { - + case NOTIFICATION_MOUSE_EXIT: { + rb_hover=-1; + update(); + } break; case NOTIFICATION_DRAW: { RID ci = get_canvas_item(); @@ -117,8 +167,22 @@ void Tabs::_notification(int p_what) { int w=0; + int mw = get_minimum_size().width; + + if (tab_align==ALIGN_CENTER) { + w=(get_size().width-mw)/2; + } else if (tab_align==ALIGN_RIGHT) { + w=get_size().width-mw; + + } + + if (w<0) { + w=0; + } + for(int i=0;i<tabs.size();i++) { + tabs[i].ofs_cache=w; String s = tabs[i].text; int lsize=0; @@ -127,7 +191,7 @@ void Tabs::_notification(int p_what) { Ref<Texture> icon; if (tabs[i].icon.is_valid()) { - Ref<Texture> icon = tabs[i].icon; + icon = tabs[i].icon; if (icon.is_valid()) { lsize+=icon->get_width(); if (s!="") @@ -136,6 +200,16 @@ void Tabs::_notification(int p_what) { } } + if (tabs[i].right_button.is_valid()) { + Ref<StyleBox> style = get_stylebox("button"); + Ref<Texture> rb=tabs[i].right_button; + + lsize+=get_constant("hseparation"); + lsize+=style->get_margin(MARGIN_LEFT); + lsize+=rb->get_width(); + lsize+=style->get_margin(MARGIN_RIGHT); + + } Ref<StyleBox> sb; int va; @@ -169,9 +243,39 @@ void Tabs::_notification(int p_what) { font->draw(ci, Point2i( w, sb->get_margin(MARGIN_TOP)+((sb_rect.size.y-sb_ms.y)-font->get_height())/2+font->get_ascent() ), s, col ); - w+=slen+sb->get_margin(MARGIN_RIGHT); + w+=slen; - tabs[i].ofs_cache=w; + if (tabs[i].right_button.is_valid()) { + Ref<StyleBox> style = get_stylebox("button"); + Ref<Texture> rb=tabs[i].right_button; + + w+=get_constant("hseparation"); + + Rect2 rb_rect; + rb_rect.size=style->get_minimum_size()+rb->get_size(); + rb_rect.pos.x=w; + rb_rect.pos.y=sb->get_margin(MARGIN_TOP)+((sb_rect.size.y-sb_ms.y)-(rb_rect.size.y))/2; + + if (rb_hover==i) { + if (rb_pressing) + get_stylebox("button_pressed")->draw(ci,rb_rect); + else + style->draw(ci,rb_rect); + } + + w+=style->get_margin(MARGIN_LEFT); + + rb->draw(ci,Point2i( w,rb_rect.pos.y+style->get_margin(MARGIN_TOP) )); + w+=rb->get_width(); + w+=style->get_margin(MARGIN_RIGHT); + tabs[i].rb_rect=rb_rect; + + + } + + w+=sb->get_margin(MARGIN_RIGHT); + + tabs[i].size_cache=w-tabs[i].ofs_cache; } @@ -195,7 +299,7 @@ void Tabs::set_current_tab(int p_current) { current=p_current; _change_notify("current_tab"); - emit_signal("tab_changed",current); + //emit_signal("tab_changed",current); update(); } @@ -237,6 +341,23 @@ Ref<Texture> Tabs::get_tab_icon(int p_tab) const{ } + + +void Tabs::set_tab_right_button(int p_tab,const Ref<Texture>& p_right_button){ + + ERR_FAIL_INDEX(p_tab,tabs.size()); + tabs[p_tab].right_button=p_right_button; + update(); + minimum_size_changed(); + +} +Ref<Texture> Tabs::get_tab_right_button(int p_tab) const{ + + ERR_FAIL_INDEX_V(p_tab,tabs.size(),Ref<Texture>()); + return tabs[p_tab].right_button; + +} + void Tabs::add_tab(const String& p_str,const Ref<Texture>& p_icon) { Tab t; @@ -249,6 +370,12 @@ void Tabs::add_tab(const String& p_str,const Ref<Texture>& p_icon) { } +void Tabs::clear_tabs() { + tabs.clear(); + current=0; + update(); +} + void Tabs::remove_tab(int p_idx) { ERR_FAIL_INDEX(p_idx,tabs.size()); @@ -263,8 +390,19 @@ void Tabs::remove_tab(int p_idx) { if (current>=tabs.size()) current=tabs.size()-1; - emit_signal("tab_changed",current); + //emit_signal("tab_changed",current); + +} + +void Tabs::set_tab_align(TabAlign p_align) { + + tab_align=p_align; + update(); +} + +Tabs::TabAlign Tabs::get_tab_align() const { + return tab_align; } @@ -280,15 +418,24 @@ void Tabs::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_tab_icon:Texture","tab_idx"),&Tabs::get_tab_icon); ObjectTypeDB::bind_method(_MD("remove_tab","tab_idx"),&Tabs::remove_tab); ObjectTypeDB::bind_method(_MD("add_tab","title","icon:Texture"),&Tabs::add_tab); + ObjectTypeDB::bind_method(_MD("set_tab_align","align"),&Tabs::set_tab_align); + ObjectTypeDB::bind_method(_MD("get_tab_align"),&Tabs::get_tab_align); ADD_SIGNAL(MethodInfo("tab_changed",PropertyInfo(Variant::INT,"tab"))); + ADD_SIGNAL(MethodInfo("right_button_pressed",PropertyInfo(Variant::INT,"tab"))); ADD_PROPERTY( PropertyInfo(Variant::INT, "current_tab", PROPERTY_HINT_RANGE,"-1,4096,1",PROPERTY_USAGE_EDITOR), _SCS("set_current_tab"), _SCS("get_current_tab") ); + BIND_CONSTANT( ALIGN_LEFT ); + BIND_CONSTANT( ALIGN_CENTER ); + BIND_CONSTANT( ALIGN_RIGHT ); } Tabs::Tabs() { current=0; + tab_align=ALIGN_CENTER; + rb_hover=-1; + rb_pressing=false; } diff --git a/scene/gui/tabs.h b/scene/gui/tabs.h index 72c077a8b0..5cb0d9e916 100644 --- a/scene/gui/tabs.h +++ b/scene/gui/tabs.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -34,6 +34,14 @@ class Tabs : public Control { OBJ_TYPE( Tabs, Control ); +public: + + enum TabAlign { + + ALIGN_LEFT, + ALIGN_CENTER, + ALIGN_RIGHT + }; private: @@ -42,12 +50,18 @@ private: String text; Ref<Texture> icon; int ofs_cache; + int size_cache; + Ref<Texture> right_button; + Rect2 rb_rect; }; Vector<Tab> tabs; int current; Control *_get_tab(int idx) const; int _get_top_margin() const; + TabAlign tab_align; + int rb_hover; + bool rb_pressing; protected: @@ -65,16 +79,25 @@ public: void set_tab_icon(int p_tab,const Ref<Texture>& p_icon); Ref<Texture> get_tab_icon(int p_tab) const; + void set_tab_right_button(int p_tab,const Ref<Texture>& p_right_button); + Ref<Texture> get_tab_right_button(int p_tab) const; + + void set_tab_align(TabAlign p_align); + TabAlign get_tab_align() const; + int get_tab_count() const; void set_current_tab(int p_current); int get_current_tab() const; void remove_tab(int p_idx); + void clear_tabs(); + Size2 get_minimum_size() const; Tabs(); }; +VARIANT_ENUM_CAST(Tabs::TabAlign); #endif // TABS_H diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index b26b55f076..1759f3eb04 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -26,16 +26,6 @@ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -/*****f********************************************/ -/* text_edit.cpp */ -/*************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/*************************************************/ -/* Source code within this file is: */ -/* (c) 2007-2010 Juan Linietsky, Ariel Manzur */ -/* All Rights Reserved. */ -/*************************************************/ #include "text_edit.h" #include "os/keyboard.h" @@ -499,7 +489,7 @@ void TextEdit::_notification(int p_what) { CharType cc = text[i][j]; //ignore any brackets inside a string - if (cc== '"' | cc == '\'') { + if (cc== '"' || cc == '\'') { CharType quotation = cc; do { j++; @@ -570,7 +560,7 @@ void TextEdit::_notification(int p_what) { CharType cc = text[i][j]; //ignore any brackets inside a string - if (cc== '"' | cc == '\'') { + if (cc== '"' || cc == '\'') { CharType quotation = cc; do { j--; @@ -1259,7 +1249,7 @@ void TextEdit::_input_event(const InputEvent& p_input_event) { } - if (!mb.doubleclick && (OS::get_singleton()->get_ticks_msec()-last_dblclk)<600) { + if (!mb.doubleclick && (OS::get_singleton()->get_ticks_msec()-last_dblclk)<600 && cursor.line==prev_line) { //tripleclick select line select(cursor.line,0,cursor.line,text[cursor.line].length()); last_dblclk=0; @@ -1450,7 +1440,7 @@ void TextEdit::_input_event(const InputEvent& p_input_event) { } else { //different char, go back - const CharType chr[2] = {k.unicode, 0}; + const CharType chr[2] = {(CharType)k.unicode, 0}; if(auto_brace_completion_enabled && _is_pair_symbol(chr[0])) { _consume_pair_symbol(chr[0]); } else { @@ -1562,7 +1552,7 @@ void TextEdit::_input_event(const InputEvent& p_input_event) { case KEY_HOME: case KEY_END: // ignore arrows if any modifiers are held (shift = selecting, others may be used for editor hotkeys) - if (k.mod.command || k.mod.shift || k.mod.alt || k.mod.command) + if (k.mod.command || k.mod.shift || k.mod.alt) break; unselect=true; break; @@ -1852,6 +1842,8 @@ void TextEdit::_input_event(const InputEvent& p_input_event) { if (k.mod.shift) _post_shift_selection(); + _cancel_completion(); + completion_hint=""; } break; case KEY_END: { @@ -1865,6 +1857,9 @@ void TextEdit::_input_event(const InputEvent& p_input_event) { if (k.mod.shift) _post_shift_selection(); + + _cancel_completion(); + completion_hint=""; } break; #endif @@ -1877,6 +1872,10 @@ void TextEdit::_input_event(const InputEvent& p_input_event) { if (k.mod.shift) _post_shift_selection(); + + _cancel_completion(); + completion_hint=""; + } break; case KEY_PAGEDOWN: { @@ -1888,6 +1887,10 @@ void TextEdit::_input_event(const InputEvent& p_input_event) { if (k.mod.shift) _post_shift_selection(); + + _cancel_completion(); + completion_hint=""; + } break; case KEY_A: { @@ -1903,7 +1906,7 @@ void TextEdit::_input_event(const InputEvent& p_input_event) { selection.from_line=0; selection.from_column=0; selection.to_line=text.size()-1; - selection.to_column=text[selection.to_line].size(); + selection.to_column=text[selection.to_line].length(); selection.selecting_mode=Selection::MODE_NONE; update(); @@ -2072,8 +2075,11 @@ void TextEdit::_input_event(const InputEvent& p_input_event) { if (readonly) break; - const CharType chr[2] = {k.unicode, 0}; + const CharType chr[2] = {(CharType)k.unicode, 0}; + if (completion_hint!="" && k.unicode==')') { + completion_hint=""; + } if(auto_brace_completion_enabled && _is_pair_symbol(chr[0])) { _consume_pair_symbol(chr[0]); } else { @@ -2596,9 +2602,9 @@ Control::CursorShape TextEdit::get_cursor_shape(const Point2& p_pos) const { void TextEdit::set_text(String p_text){ setting_text=true; - _clear(); + clear(); _insert_text_at_cursor(p_text); - + clear_undo_history(); cursor.column=0; cursor.line=0; cursor.x_ofs=0; @@ -2788,6 +2794,11 @@ void TextEdit::copy() { if (!selection.active) return; + print_line("from line: "+itos(selection.from_line)); + print_line("from column: "+itos(selection.from_column)); + print_line("to line: "+itos(selection.to_line)); + print_line("to column: "+itos(selection.to_column)); + String clipboard = _base_get_text(selection.from_line,selection.from_column,selection.to_line,selection.to_column); OS::get_singleton()->set_clipboard(clipboard); @@ -2819,7 +2830,7 @@ void TextEdit::select_all() { selection.from_line=0; selection.from_column=0; selection.to_line=text.size()-1; - selection.to_column=text[selection.to_line].size(); + selection.to_column=text[selection.to_line].length(); selection.selecting_mode=Selection::MODE_NONE; update(); @@ -3328,9 +3339,32 @@ void TextEdit::_update_completion_candidates() { //look for keywords first - bool pre_keyword=false; + bool inquote=false; + int first_quote=-1; + + int c=cofs-1; + while(c>=0) { + if (l[c]=='"' || l[c]=='\'') { + inquote=!inquote; + if (first_quote==-1) + first_quote=c; + } + c--; + } - if (cofs>0 && l[cofs-1]==' ') { + bool pre_keyword=false; + bool cancel=false; + + //print_line("inquote: "+itos(inquote)+"first quote "+itos(first_quote)+" cofs-1 "+itos(cofs-1)); + if (!inquote && first_quote==cofs-1) { + //no completion here + //print_line("cancel!"); + cancel=true; + } if (inquote && first_quote!=-1) { + + s=l.substr(first_quote,cofs-first_quote); + //print_line("s: 1"+s); + } else if (cofs>0 && l[cofs-1]==' ') { int kofs=cofs-1; String kw; while (kofs>=0 && l[kofs]==' ') @@ -3342,7 +3376,7 @@ void TextEdit::_update_completion_candidates() { } pre_keyword=keywords.has(kw); - print_line("KW "+kw+"? "+itos(pre_keyword)); + //print_line("KW "+kw+"? "+itos(pre_keyword)); } else { @@ -3359,7 +3393,7 @@ void TextEdit::_update_completion_candidates() { update(); - if (!pre_keyword && s=="" && (cofs==0 || !completion_prefixes.has(String::chr(l[cofs-1])))) { + if (cancel || (!pre_keyword && s=="" && (cofs==0 || !completion_prefixes.has(String::chr(l[cofs-1]))))) { //none to complete, cancel _cancel_completion(); return; @@ -3426,7 +3460,16 @@ void TextEdit::query_code_comple() { String l = text[cursor.line]; int ofs = CLAMP(cursor.column,0,l.length()); - if (ofs>0 && (_is_completable(l[ofs-1]) || completion_prefixes.has(String::chr(l[ofs-1])))) + bool inquote=false; + + int c=ofs-1; + while(c>=0) { + if (l[c]=='"' || l[c]=='\'') + inquote=!inquote; + c--; + } + + if (ofs>0 && (inquote || _is_completable(l[ofs-1]) || completion_prefixes.has(String::chr(l[ofs-1])))) emit_signal("request_completion"); } @@ -3504,6 +3547,9 @@ void TextEdit::set_line(int line, String new_text) return; _remove_text(line, 0, line, text[line].length()); _insert_text(line, 0, new_text); + if (cursor.line==line) { + cursor.column=MIN(cursor.column,new_text.length()); + } } void TextEdit::insert_at(const String &p_text, int at) @@ -3603,6 +3649,10 @@ TextEdit::TextEdit() { set_focus_mode(FOCUS_ALL); _update_caches(); cache.size=Size2(1,1); + cache.row_height=1; + cache.line_spacing=1; + cache.line_number_w=1; + tab_size=4; text.set_tab_size(tab_size); text.clear(); diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h index 1d57aef416..1b448bb782 100644 --- a/scene/gui/text_edit.h +++ b/scene/gui/text_edit.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/texture_button.cpp b/scene/gui/texture_button.cpp index 1a7087b7ef..5b2caecb5b 100644 --- a/scene/gui/texture_button.cpp +++ b/scene/gui/texture_button.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -157,14 +157,14 @@ void TextureButton::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_scale"),&TextureButton::get_scale); ObjectTypeDB::bind_method(_MD("get_modulate"),&TextureButton::get_modulate); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT,"textures/normal",PROPERTY_HINT_RESOURCE_TYPE,"Texture"), _SCS("set_normal_texture"), _SCS("get_normal_texture")); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT,"textures/pressed",PROPERTY_HINT_RESOURCE_TYPE,"Texture"), _SCS("set_pressed_texture"), _SCS("get_pressed_texture")); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT,"textures/hover",PROPERTY_HINT_RESOURCE_TYPE,"Texture"), _SCS("set_hover_texture"), _SCS("get_hover_texture")); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT,"textures/disabled",PROPERTY_HINT_RESOURCE_TYPE,"Texture"), _SCS("set_disabled_texture"), _SCS("get_disabled_texture")); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT,"textures/focused",PROPERTY_HINT_RESOURCE_TYPE,"Texture"), _SCS("set_focused_texture"), _SCS("get_focused_texture")); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT,"textures/click_mask",PROPERTY_HINT_RESOURCE_TYPE,"BitMap"), _SCS("set_click_mask"), _SCS("get_click_mask")) ; - ADD_PROPERTY(PropertyInfo(Variant::VECTOR2,"params/scale",PROPERTY_HINT_RANGE,"0.01,1024,0.01"), _SCS("set_scale"), _SCS("get_scale")); - ADD_PROPERTY(PropertyInfo(Variant::COLOR,"params/modulate"), _SCS("set_modulate"), _SCS("get_modulate")); + ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT,"textures/normal",PROPERTY_HINT_RESOURCE_TYPE,"Texture"), _SCS("set_normal_texture"), _SCS("get_normal_texture")); + ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT,"textures/pressed",PROPERTY_HINT_RESOURCE_TYPE,"Texture"), _SCS("set_pressed_texture"), _SCS("get_pressed_texture")); + ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT,"textures/hover",PROPERTY_HINT_RESOURCE_TYPE,"Texture"), _SCS("set_hover_texture"), _SCS("get_hover_texture")); + ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT,"textures/disabled",PROPERTY_HINT_RESOURCE_TYPE,"Texture"), _SCS("set_disabled_texture"), _SCS("get_disabled_texture")); + ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT,"textures/focused",PROPERTY_HINT_RESOURCE_TYPE,"Texture"), _SCS("set_focused_texture"), _SCS("get_focused_texture")); + ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT,"textures/click_mask",PROPERTY_HINT_RESOURCE_TYPE,"BitMap"), _SCS("set_click_mask"), _SCS("get_click_mask")) ; + ADD_PROPERTYNO(PropertyInfo(Variant::VECTOR2,"params/scale",PROPERTY_HINT_RANGE,"0.01,1024,0.01"), _SCS("set_scale"), _SCS("get_scale")); + ADD_PROPERTYNO(PropertyInfo(Variant::COLOR,"params/modulate"), _SCS("set_modulate"), _SCS("get_modulate")); } diff --git a/scene/gui/texture_button.h b/scene/gui/texture_button.h index 94bc53b3ff..01924c1c15 100644 --- a/scene/gui/texture_button.h +++ b/scene/gui/texture_button.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/texture_frame.cpp b/scene/gui/texture_frame.cpp index 26f4d32965..5a6bc86638 100644 --- a/scene/gui/texture_frame.cpp +++ b/scene/gui/texture_frame.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -77,9 +77,9 @@ void TextureFrame::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_expand","enable"), & TextureFrame::set_expand ); ObjectTypeDB::bind_method(_MD("has_expand"), & TextureFrame::has_expand ); - ADD_PROPERTY( PropertyInfo( Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), _SCS("set_texture"),_SCS("get_texture") ); - ADD_PROPERTY( PropertyInfo( Variant::COLOR, "modulate"), _SCS("set_modulate"),_SCS("get_modulate") ); - ADD_PROPERTY( PropertyInfo( Variant::BOOL, "expand" ), _SCS("set_expand"),_SCS("has_expand") ); + ADD_PROPERTYNZ( PropertyInfo( Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), _SCS("set_texture"),_SCS("get_texture") ); + ADD_PROPERTYNO( PropertyInfo( Variant::COLOR, "modulate"), _SCS("set_modulate"),_SCS("get_modulate") ); + ADD_PROPERTYNZ( PropertyInfo( Variant::BOOL, "expand" ), _SCS("set_expand"),_SCS("has_expand") ); } @@ -88,8 +88,8 @@ void TextureFrame::set_texture(const Ref<Texture>& p_tex) { texture=p_tex; update(); - if (texture.is_valid()) - texture->set_flags(texture->get_flags()&(~Texture::FLAG_REPEAT)); //remove repeat from texture, it looks bad in sprites + //if (texture.is_valid()) + // texture->set_flags(texture->get_flags()&(~Texture::FLAG_REPEAT)); //remove repeat from texture, it looks bad in sprites minimum_size_changed(); } diff --git a/scene/gui/texture_frame.h b/scene/gui/texture_frame.h index 9f75e1c2c0..0ccbf5a591 100644 --- a/scene/gui/texture_frame.h +++ b/scene/gui/texture_frame.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/texture_progress.cpp b/scene/gui/texture_progress.cpp index 0ce7df5d20..f61d63e4c3 100644 --- a/scene/gui/texture_progress.cpp +++ b/scene/gui/texture_progress.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/texture_progress.h b/scene/gui/texture_progress.h index 93a0d1046c..d97ebf27f5 100644 --- a/scene/gui/texture_progress.h +++ b/scene/gui/texture_progress.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/tool_button.cpp b/scene/gui/tool_button.cpp index e0ba30a202..d5bcb73476 100644 --- a/scene/gui/tool_button.cpp +++ b/scene/gui/tool_button.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/tool_button.h b/scene/gui/tool_button.h index 9b1664c3fb..648d776b51 100644 --- a/scene/gui/tool_button.h +++ b/scene/gui/tool_button.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp index 035dbb8cc4..6c15f1cae4 100644 --- a/scene/gui/tree.cpp +++ b/scene/gui/tree.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -1106,7 +1106,7 @@ int Tree::draw_item(const Point2i& p_pos,const Point2& p_draw_ofs, const Size2& int option = (int)p_item->cells[i].val; String s = p_item->cells[i].text; - s=s.get_slice(",",option); + s=s.get_slicec(',',option); Ref<Texture> downarrow = cache.select_arrow; @@ -1527,7 +1527,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos,int x_ofs,int y_ofs,bool p_ popup_menu->clear(); for (int i=0;i<c.text.get_slice_count(",");i++) { - String s = c.text.get_slice(",",i); + String s = c.text.get_slicec(',',i); popup_menu->add_item(s,i); } @@ -2234,7 +2234,7 @@ bool Tree::edit_selected() { popup_menu->clear(); for (int i=0;i<c.text.get_slice_count(",");i++) { - String s = c.text.get_slice(",",i); + String s = c.text.get_slicec(',',i); popup_menu->add_item(s,i); } diff --git a/scene/gui/tree.h b/scene/gui/tree.h index 3ffbececb2..8ddddd0630 100644 --- a/scene/gui/tree.h +++ b/scene/gui/tree.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -454,6 +454,8 @@ public: void set_cursor_can_exit_tree(bool p_enable); bool can_cursor_exit_tree() const; + VScrollBar *get_vscroll_bar() { return v_scroll; } + Tree(); ~Tree(); diff --git a/scene/gui/video_player.cpp b/scene/gui/video_player.cpp index 050fd890f4..c0b971cb33 100644 --- a/scene/gui/video_player.cpp +++ b/scene/gui/video_player.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/video_player.h b/scene/gui/video_player.h index 3eb629ced5..2b850ca509 100644 --- a/scene/gui/video_player.h +++ b/scene/gui/video_player.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ |