diff options
Diffstat (limited to 'scene/gui')
105 files changed, 5994 insertions, 2977 deletions
diff --git a/scene/gui/SCsub b/scene/gui/SCsub index bbe59b3054..bf9125be7f 100644 --- a/scene/gui/SCsub +++ b/scene/gui/SCsub @@ -1,5 +1,7 @@ +#!/usr/bin/env python + Import('env') -env.add_source_files(env.scene_sources,"*.cpp") +env.add_source_files(env.scene_sources, "*.cpp") Export('env') diff --git a/scene/gui/base_button.cpp b/scene/gui/base_button.cpp index 3bcc60b86a..0b40983ddf 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-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 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 */ @@ -29,10 +29,24 @@ #include "base_button.h" #include "os/keyboard.h" #include "print_string.h" -#include "button_group.h" #include "scene/scene_string_names.h" +#include "scene/main/viewport.h" -void BaseButton::_input_event(InputEvent p_event) { + +void BaseButton::_unpress_group() { + + if (!button_group.is_valid()) + return; + + for (Set<BaseButton*>::Element *E=button_group->buttons.front();E;E=E->next()) { + if (E->get()==this) + continue; + + E->get()->set_pressed(false); + } +} + +void BaseButton::_gui_input(InputEvent p_event) { if (status.disabled) // no interaction with disabled button @@ -50,10 +64,12 @@ void BaseButton::_input_event(InputEvent p_event) { if (status.pressing_button) break; - if (status.click_on_press) { + if (action_mode==ACTION_MODE_BUTTON_PRESS) { if (b.pressed) { + emit_signal("button_down"); + if (!toggle_mode) { //mouse press attempt status.press_attempt=true; @@ -66,6 +82,8 @@ void BaseButton::_input_event(InputEvent p_event) { } emit_signal("pressed"); + _unpress_group(); + } else { @@ -76,6 +94,8 @@ void BaseButton::_input_event(InputEvent p_event) { get_script_instance()->call(SceneStringNames::get_singleton()->_pressed,NULL,0,ce); } emit_signal("pressed"); + _unpress_group(); + toggled(status.pressed); emit_signal("toggled",status.pressed); @@ -85,10 +105,13 @@ void BaseButton::_input_event(InputEvent p_event) { } else { - if (status.press_attempt && status.pressing_inside) { -// released(); + emit_signal("button_up"); + +/* this is pointless if (status.press_attempt && status.pressing_inside) { + //released(); emit_signal("released"); } +*/ status.press_attempt=false; } update(); @@ -99,9 +122,11 @@ void BaseButton::_input_event(InputEvent p_event) { status.press_attempt=true; status.pressing_inside=true; + emit_signal("button_down"); } else { + emit_signal("button_up"); if (status.press_attempt &&status.pressing_inside) { @@ -131,6 +156,9 @@ void BaseButton::_input_event(InputEvent p_event) { } + _unpress_group(); + + } status.press_attempt=false; @@ -149,7 +177,7 @@ void BaseButton::_input_event(InputEvent p_event) { } } break; case InputEvent::ACTION: - case InputEvent::JOYSTICK_BUTTON: + case InputEvent::JOYPAD_BUTTON: case InputEvent::KEY: { @@ -172,6 +200,7 @@ void BaseButton::_input_event(InputEvent p_event) { status.pressing_button++; status.press_attempt=true; status.pressing_inside=true; + emit_signal("button_down"); } else if (status.press_attempt) { @@ -184,6 +213,8 @@ void BaseButton::_input_event(InputEvent p_event) { status.press_attempt=false; status.pressing_inside=false; + emit_signal("button_up"); + if (!toggle_mode) { //mouse press attempt pressed(); @@ -201,6 +232,9 @@ void BaseButton::_input_event(InputEvent p_event) { } emit_signal("toggled",status.pressed); } + + _unpress_group(); + } accept_event(); @@ -225,37 +259,45 @@ void BaseButton::_notification(int p_what) { status.hovering=false; update(); } + if (p_what==NOTIFICATION_DRAG_BEGIN) { + + if (status.press_attempt) { + status.press_attempt=false; + status.pressing_button=0; + update(); + } + } + + if (p_what==NOTIFICATION_FOCUS_ENTER) { + + status.hovering=true; + update(); + } + if (p_what==NOTIFICATION_FOCUS_EXIT) { if (status.pressing_button && status.press_attempt) { status.press_attempt=false; status.pressing_button=0; + status.hovering=false; + update(); + } else if (status.hovering) { + status.hovering=false; + update(); } } if (p_what==NOTIFICATION_ENTER_TREE) { - CanvasItem *ci=this; - while(ci) { - - ButtonGroup *bg = ci->cast_to<ButtonGroup>(); - if (bg) { - group=bg; - group->_add_button(this); - } - - ci=ci->get_parent_item(); - } } if (p_what==NOTIFICATION_EXIT_TREE) { - if (group) - group->_remove_button(this); + } - if (p_what==NOTIFICATION_VISIBILITY_CHANGED && !is_visible()) { + if (p_what==NOTIFICATION_VISIBILITY_CHANGED && !is_visible_in_tree()) { if (!toggle_mode) { status.pressed = false; @@ -275,8 +317,9 @@ void BaseButton::pressed() { void BaseButton::toggled(bool p_pressed) { - if (get_script_instance()) + if (get_script_instance()) { get_script_instance()->call("toggled",p_pressed); + } } @@ -289,7 +332,7 @@ void BaseButton::set_disabled(bool p_disabled) { if (p_disabled) set_focus_mode(FOCUS_NONE); else - set_focus_mode(FOCUS_ALL); + set_focus_mode(enabled_focus_mode); } bool BaseButton::is_disabled() const { @@ -305,6 +348,11 @@ void BaseButton::set_pressed(bool p_pressed) { return; _change_notify("pressed"); status.pressed=p_pressed; + + if (p_pressed) { + _unpress_group(); + + } update(); } @@ -367,43 +415,131 @@ bool BaseButton::is_toggle_mode() const { return toggle_mode; } -void BaseButton::set_click_on_press(bool p_click_on_press) { +void BaseButton::set_action_mode(ActionMode p_mode) { + + action_mode=p_mode; +} + +BaseButton::ActionMode BaseButton::get_action_mode() const { + + return action_mode; +} + +void BaseButton::set_enabled_focus_mode(FocusMode p_mode) { + + enabled_focus_mode = p_mode; + if (!status.disabled) { + set_focus_mode( p_mode ); + } +} + +Control::FocusMode BaseButton::get_enabled_focus_mode() const { - status.click_on_press=p_click_on_press; + return enabled_focus_mode; } -bool BaseButton::get_click_on_press() const { +void BaseButton::set_shortcut(const Ref<ShortCut>& p_shortcut) { + + if (shortcut.is_null() == p_shortcut.is_null()) + return; - return status.click_on_press; + shortcut=p_shortcut; + set_process_unhandled_input(shortcut.is_valid()); } +Ref<ShortCut> BaseButton:: get_shortcut() const { + return shortcut; +} +void BaseButton::_unhandled_input(InputEvent p_event) { + + if (!is_disabled() && is_visible_in_tree() && p_event.is_pressed() && !p_event.is_echo() && shortcut.is_valid() && shortcut->is_shortcut(p_event)) { + + if (get_viewport()->get_modal_stack_top() && !get_viewport()->get_modal_stack_top()->is_a_parent_of(this)) + return; //ignore because of modal window + + if (is_toggle_mode()) { + set_pressed(!is_pressed()); + emit_signal("toggled",is_pressed()); + } + + emit_signal("pressed"); + } +} + +String BaseButton::get_tooltip(const Point2& p_pos) const { + + String tooltip=Control::get_tooltip(p_pos); + if (shortcut.is_valid() && shortcut->is_valid()) { + if (tooltip.find("$sc")!=-1) { + tooltip=tooltip.replace_first("$sc","("+shortcut->get_as_text()+")"); + } else { + tooltip+=" ("+shortcut->get_as_text()+")"; + } + } + return tooltip; +} + + +void BaseButton::set_button_group(const Ref<ButtonGroup>& p_group) { + + if (button_group.is_valid()) { + button_group->buttons.erase(this); + } + + button_group=p_group; + + if (button_group.is_valid()) { + button_group->buttons.insert(this); + } + + update(); //checkbox changes to radio if set a buttongroup + +} + +Ref<ButtonGroup> BaseButton::get_button_group() const { + + return button_group; +} void BaseButton::_bind_methods() { - ObjectTypeDB::bind_method(_MD("_input_event"),&BaseButton::_input_event); - ObjectTypeDB::bind_method(_MD("set_pressed","pressed"),&BaseButton::set_pressed); - ObjectTypeDB::bind_method(_MD("is_pressed"),&BaseButton::is_pressed); - ObjectTypeDB::bind_method(_MD("is_hovered"),&BaseButton::is_hovered); - ObjectTypeDB::bind_method(_MD("set_toggle_mode","enabled"),&BaseButton::set_toggle_mode); - ObjectTypeDB::bind_method(_MD("is_toggle_mode"),&BaseButton::is_toggle_mode); - ObjectTypeDB::bind_method(_MD("set_disabled","disabled"),&BaseButton::set_disabled); - ObjectTypeDB::bind_method(_MD("is_disabled"),&BaseButton::is_disabled); - ObjectTypeDB::bind_method(_MD("set_click_on_press","enable"),&BaseButton::set_click_on_press); - ObjectTypeDB::bind_method(_MD("get_click_on_press"),&BaseButton::get_click_on_press); - ObjectTypeDB::bind_method(_MD("get_draw_mode"),&BaseButton::get_draw_mode); + ClassDB::bind_method(_MD("_gui_input"),&BaseButton::_gui_input); + ClassDB::bind_method(_MD("_unhandled_input"),&BaseButton::_unhandled_input); + ClassDB::bind_method(_MD("set_pressed","pressed"),&BaseButton::set_pressed); + ClassDB::bind_method(_MD("is_pressed"),&BaseButton::is_pressed); + ClassDB::bind_method(_MD("is_hovered"),&BaseButton::is_hovered); + ClassDB::bind_method(_MD("set_toggle_mode","enabled"),&BaseButton::set_toggle_mode); + ClassDB::bind_method(_MD("is_toggle_mode"),&BaseButton::is_toggle_mode); + ClassDB::bind_method(_MD("set_disabled","disabled"),&BaseButton::set_disabled); + ClassDB::bind_method(_MD("is_disabled"),&BaseButton::is_disabled); + ClassDB::bind_method(_MD("set_action_mode","mode"),&BaseButton::set_action_mode); + ClassDB::bind_method(_MD("get_action_mode"),&BaseButton::get_action_mode); + ClassDB::bind_method(_MD("get_draw_mode"),&BaseButton::get_draw_mode); + ClassDB::bind_method(_MD("set_enabled_focus_mode","mode"),&BaseButton::set_enabled_focus_mode); + ClassDB::bind_method(_MD("get_enabled_focus_mode"),&BaseButton::get_enabled_focus_mode); + + ClassDB::bind_method(_MD("set_shortcut","shortcut"),&BaseButton::set_shortcut); + ClassDB::bind_method(_MD("get_shortcut"),&BaseButton::get_shortcut); + + ClassDB::bind_method(_MD("set_button_group","button_group"),&BaseButton::set_button_group); + ClassDB::bind_method(_MD("get_button_group"),&BaseButton::get_button_group); BIND_VMETHOD(MethodInfo("_pressed")); BIND_VMETHOD(MethodInfo("_toggled",PropertyInfo(Variant::BOOL,"pressed"))); ADD_SIGNAL( MethodInfo("pressed" ) ); - ADD_SIGNAL( MethodInfo("released" ) ); + ADD_SIGNAL( MethodInfo("button_up") ); + ADD_SIGNAL( MethodInfo("button_down") ); ADD_SIGNAL( MethodInfo("toggled", PropertyInfo( Variant::BOOL,"pressed") ) ); 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_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")); + ADD_PROPERTYNO( PropertyInfo( Variant::INT, "action_mode",PROPERTY_HINT_ENUM,"Button Press,Button Release"), _SCS("set_action_mode"), _SCS("get_action_mode")); + ADD_PROPERTY( PropertyInfo( Variant::INT,"enabled_focus_mode", PROPERTY_HINT_ENUM, "None,Click,All" ), _SCS("set_enabled_focus_mode"), _SCS("get_enabled_focus_mode") ); + ADD_PROPERTY( PropertyInfo( Variant::OBJECT, "shortcut",PROPERTY_HINT_RESOURCE_TYPE,"ShortCut"), _SCS("set_shortcut"), _SCS("get_shortcut")); + ADD_PROPERTY( PropertyInfo( Variant::OBJECT, "group",PROPERTY_HINT_RESOURCE_TYPE,"ButtonGroup"), _SCS("set_button_group"), _SCS("get_button_group")); BIND_CONSTANT( DRAW_NORMAL ); @@ -411,6 +547,10 @@ void BaseButton::_bind_methods() { BIND_CONSTANT( DRAW_HOVER ); BIND_CONSTANT( DRAW_DISABLED ); + BIND_CONSTANT( ACTION_MODE_BUTTON_PRESS ); + BIND_CONSTANT( ACTION_MODE_BUTTON_RELEASE ); + + } BaseButton::BaseButton() { @@ -421,10 +561,15 @@ BaseButton::BaseButton() { status.hovering=false; status.pressing_inside=false; status.disabled = false; - status.click_on_press=false; status.pressing_button=0; set_focus_mode( FOCUS_ALL ); - group=NULL; + enabled_focus_mode = FOCUS_ALL; + action_mode=ACTION_MODE_BUTTON_RELEASE; + + + if (button_group.is_valid()) { + button_group->buttons.erase(this); + } } @@ -433,4 +578,30 @@ BaseButton::~BaseButton() { } +void ButtonGroup::get_buttons(List<BaseButton*> *r_buttons) { + + for (Set<BaseButton*>::Element *E=buttons.front();E;E=E->next()) { + r_buttons->push_back(E->get()); + } +} + +BaseButton* ButtonGroup::get_pressed_button() { + + for (Set<BaseButton*>::Element *E=buttons.front();E;E=E->next()) { + if (E->get()->is_pressed()) + return E->get(); + } + + return NULL; + +} + +void ButtonGroup::_bind_methods() { + + ClassDB::bind_method(_MD("get_pressed_button:BaseButton"),&ButtonGroup::get_pressed_button); +} + +ButtonGroup::ButtonGroup() { + set_local_to_scene(true); +} diff --git a/scene/gui/base_button.h b/scene/gui/base_button.h index 9a5213d971..def4ff7536 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-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 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 */ @@ -39,10 +39,21 @@ class ButtonGroup; class BaseButton : public Control { - OBJ_TYPE( BaseButton, Control ); + GDCLASS( BaseButton, Control ); +public: + + enum ActionMode { + ACTION_MODE_BUTTON_PRESS, + ACTION_MODE_BUTTON_RELEASE, + }; + +private: bool toggle_mode; + FocusMode enabled_focus_mode; + Ref<ShortCut> shortcut; + ActionMode action_mode; struct Status { bool pressed; @@ -51,14 +62,16 @@ class BaseButton : public Control { bool pressing_inside; bool disabled; - bool click_on_press; int pressing_button; } status; - ButtonGroup *group; + + Ref<ButtonGroup> button_group; + void _unpress_group(); + protected: @@ -67,7 +80,8 @@ protected: virtual void pressed(); virtual void toggled(bool p_pressed); static void _bind_methods(); - virtual void _input_event(InputEvent p_event); + virtual void _gui_input(InputEvent p_event); + virtual void _unhandled_input(InputEvent p_event); void _notification(int p_what); public: @@ -94,15 +108,42 @@ public: void set_disabled(bool p_disabled); bool is_disabled() const; - void set_click_on_press(bool p_click_on_press); - bool get_click_on_press() const; + void set_action_mode(ActionMode p_mode); + ActionMode get_action_mode() const; + + void set_enabled_focus_mode(FocusMode p_mode); + FocusMode get_enabled_focus_mode() const; + + void set_shortcut(const Ref<ShortCut>& p_shortcut); + Ref<ShortCut> get_shortcut() const; + + virtual String get_tooltip(const Point2& p_pos) const; + void set_button_group(const Ref<ButtonGroup>& p_group); + Ref<ButtonGroup> get_button_group() const; BaseButton(); ~BaseButton(); }; -VARIANT_ENUM_CAST( BaseButton::DrawMode ); +VARIANT_ENUM_CAST( BaseButton::DrawMode ) +VARIANT_ENUM_CAST( BaseButton::ActionMode ) + + + +class ButtonGroup : public Resource { + + GDCLASS(ButtonGroup,Resource) +friend class BaseButton; + Set<BaseButton*> buttons; +protected: + static void _bind_methods(); +public: + + BaseButton* get_pressed_button(); + void get_buttons(List<BaseButton*> *r_buttons); + ButtonGroup(); +}; #endif diff --git a/scene/gui/box_container.cpp b/scene/gui/box_container.cpp index a6ffc30a83..7ca44ac27b 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-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 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 */ @@ -55,7 +55,7 @@ void BoxContainer::_resort() { for(int i=0;i<get_child_count();i++) { Control *c=get_child(i)->cast_to<Control>(); - if (!c || !c->is_visible()) + if (!c || !c->is_visible_in_tree()) continue; if (c->is_set_as_toplevel()) continue; @@ -108,7 +108,7 @@ void BoxContainer::_resort() { for(int i=0;i<get_child_count();i++) { Control *c=get_child(i)->cast_to<Control>(); - if (!c || !c->is_visible()) + if (!c || !c->is_visible_in_tree()) continue; if (c->is_set_as_toplevel()) continue; @@ -164,7 +164,7 @@ void BoxContainer::_resort() { for(int i=0;i<get_child_count();i++) { Control *c=get_child(i)->cast_to<Control>(); - if (!c || !c->is_visible()) + if (!c || !c->is_visible_in_tree()) continue; if (c->is_set_as_toplevel()) continue; @@ -227,7 +227,7 @@ Size2 BoxContainer::get_minimum_size() const { if (c->is_set_as_toplevel()) continue; - if (c->is_hidden()) { + if (!c->is_visible()) { continue; } @@ -280,7 +280,8 @@ BoxContainer::AlignMode BoxContainer::get_alignment() const { void BoxContainer::add_spacer(bool p_begin) { Control *c = memnew( Control ); - c->set_stop_mouse(false); + c->set_mouse_filter(MOUSE_FILTER_PASS); //allow spacer to pass mouse events + if (vertical) c->set_v_size_flags(SIZE_EXPAND_FILL); else @@ -295,15 +296,15 @@ BoxContainer::BoxContainer(bool p_vertical) { vertical=p_vertical; align = ALIGN_BEGIN; -// set_ignore_mouse(true); - set_stop_mouse(false); + //set_ignore_mouse(true); + set_mouse_filter(MOUSE_FILTER_PASS); } void BoxContainer::_bind_methods() { - ObjectTypeDB::bind_method(_MD("add_spacer","begin"),&BoxContainer::add_spacer); - ObjectTypeDB::bind_method(_MD("get_alignment"),&BoxContainer::get_alignment); - ObjectTypeDB::bind_method(_MD("set_alignment","alignment"),&BoxContainer::set_alignment); + ClassDB::bind_method(_MD("add_spacer","begin"),&BoxContainer::add_spacer); + ClassDB::bind_method(_MD("get_alignment"),&BoxContainer::get_alignment); + ClassDB::bind_method(_MD("set_alignment","alignment"),&BoxContainer::set_alignment); BIND_CONSTANT( ALIGN_BEGIN ); BIND_CONSTANT( ALIGN_CENTER ); diff --git a/scene/gui/box_container.h b/scene/gui/box_container.h index 6e63e8bdac..c428ec132c 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-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 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 */ @@ -33,7 +33,7 @@ class BoxContainer : public Container { - OBJ_TYPE(BoxContainer,Container); + GDCLASS(BoxContainer,Container); public: @@ -68,7 +68,7 @@ public: class HBoxContainer : public BoxContainer { - OBJ_TYPE(HBoxContainer,BoxContainer); + GDCLASS(HBoxContainer,BoxContainer); public: @@ -79,7 +79,7 @@ public: class MarginContainer; class VBoxContainer : public BoxContainer { - OBJ_TYPE(VBoxContainer,BoxContainer); + GDCLASS(VBoxContainer,BoxContainer); public: diff --git a/scene/gui/button.cpp b/scene/gui/button.cpp index 0f1622a838..f28595b622 100644 --- a/scene/gui/button.cpp +++ b/scene/gui/button.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 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 @@ Size2 Button::get_minimum_size() const { - Size2 minsize=get_font("font")->get_string_size( text ); + Size2 minsize=get_font("font")->get_string_size( xl_text ); if (clip_text) minsize.width=0; @@ -48,7 +48,7 @@ Size2 Button::get_minimum_size() const { minsize.height=MAX( minsize.height, _icon->get_height() ); minsize.width+=_icon->get_width(); - if (text!="") + if (xl_text!="") minsize.width+=get_constant("hseparation"); } @@ -59,6 +59,13 @@ Size2 Button::get_minimum_size() const { void Button::_notification(int p_what) { + if (p_what==NOTIFICATION_TRANSLATION_CHANGED) { + + xl_text=XL_MESSAGE(text); + minimum_size_changed(); + update(); + } + if (p_what==NOTIFICATION_DRAW) { RID ci = get_canvas_item(); @@ -114,7 +121,7 @@ void Button::_notification(int p_what) { Point2 icon_ofs = (!_icon.is_null())?Point2( _icon->get_width() + get_constant("hseparation"), 0):Point2(); int text_clip=size.width - style->get_minimum_size().width - icon_ofs.width; - Point2 text_ofs = (size - style->get_minimum_size() - icon_ofs - font->get_string_size( text ) )/2.0; + Point2 text_ofs = (size - style->get_minimum_size() - icon_ofs - font->get_string_size( xl_text ) )/2.0; switch(align) { case ALIGN_LEFT: { @@ -128,14 +135,14 @@ void Button::_notification(int p_what) { text_ofs+=style->get_offset(); } break; case ALIGN_RIGHT: { - text_ofs.x=size.x - style->get_margin(MARGIN_RIGHT) - font->get_string_size( text ).x; + text_ofs.x=size.x - style->get_margin(MARGIN_RIGHT) - font->get_string_size( xl_text ).x; text_ofs.y+=style->get_offset().y; } break; } text_ofs.y+=font->get_ascent(); - font->draw( ci, text_ofs.floor(), text, color,clip_text?text_clip:-1); + font->draw( ci, text_ofs.floor(), xl_text, color,clip_text?text_clip:-1); if (!_icon.is_null()) { int valign = size.height-style->get_minimum_size().y; @@ -152,7 +159,8 @@ void Button::set_text(const String& p_text) { if (text==p_text) return; - text=XL_MESSAGE(p_text); + text=p_text; + xl_text=XL_MESSAGE(p_text); update(); _change_notify("text"); minimum_size_changed(); @@ -213,19 +221,18 @@ Button::TextAlign Button::get_text_align() const { return align; } - void Button::_bind_methods() { - ObjectTypeDB::bind_method(_MD("set_text","text"),&Button::set_text); - ObjectTypeDB::bind_method(_MD("get_text"),&Button::get_text); - ObjectTypeDB::bind_method(_MD("set_button_icon","texture:Texture"),&Button::set_icon); - ObjectTypeDB::bind_method(_MD("get_button_icon:Texture"),&Button::get_icon); - ObjectTypeDB::bind_method(_MD("set_flat","enabled"),&Button::set_flat); - ObjectTypeDB::bind_method(_MD("set_clip_text","enabled"),&Button::set_clip_text); - ObjectTypeDB::bind_method(_MD("get_clip_text"),&Button::get_clip_text); - ObjectTypeDB::bind_method(_MD("set_text_align","align"),&Button::set_text_align); - ObjectTypeDB::bind_method(_MD("get_text_align"),&Button::get_text_align); - ObjectTypeDB::bind_method(_MD("is_flat"),&Button::is_flat); + ClassDB::bind_method(_MD("set_text","text"),&Button::set_text); + ClassDB::bind_method(_MD("get_text"),&Button::get_text); + ClassDB::bind_method(_MD("set_button_icon","texture:Texture"),&Button::set_icon); + ClassDB::bind_method(_MD("get_button_icon:Texture"),&Button::get_icon); + ClassDB::bind_method(_MD("set_flat","enabled"),&Button::set_flat); + ClassDB::bind_method(_MD("set_clip_text","enabled"),&Button::set_clip_text); + ClassDB::bind_method(_MD("get_clip_text"),&Button::get_clip_text); + ClassDB::bind_method(_MD("set_text_align","align"),&Button::set_text_align); + ClassDB::bind_method(_MD("get_text_align"),&Button::get_text_align); + ClassDB::bind_method(_MD("is_flat"),&Button::is_flat); BIND_CONSTANT( ALIGN_LEFT ); BIND_CONSTANT( ALIGN_CENTER ); @@ -243,7 +250,7 @@ Button::Button(const String &p_text) { flat=false; clip_text=false; - set_stop_mouse(true); + set_mouse_filter(MOUSE_FILTER_STOP); set_text(p_text); align=ALIGN_CENTER; } diff --git a/scene/gui/button.h b/scene/gui/button.h index 8a17a164a0..2fd3a0cace 100644 --- a/scene/gui/button.h +++ b/scene/gui/button.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 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 */ @@ -33,9 +33,12 @@ /** @author Juan Linietsky <reduzio@gmail.com> */ + + + class Button : public BaseButton { - OBJ_TYPE( Button, BaseButton ); + GDCLASS( Button, BaseButton ); public: @@ -49,12 +52,12 @@ private: bool flat; String text; + String xl_text; Ref<Texture> icon; bool clip_text; TextAlign align; - protected: virtual Size2 get_minimum_size() const; @@ -62,6 +65,8 @@ protected: static void _bind_methods(); public: // + + void set_text(const String& p_text); String get_text() const; @@ -77,6 +82,7 @@ public: void set_text_align(TextAlign p_align); TextAlign get_text_align() const; + Button(const String& p_text=String()); ~Button(); diff --git a/scene/gui/button_array.cpp b/scene/gui/button_array.cpp index be48296110..3d7c0e2825 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-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 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 */ @@ -60,6 +60,8 @@ bool ButtonArray::_set(const StringName& p_name, const Variant& p_value) { String f = n.get_slicec('/',2); if (f=="text") buttons[idx].text=p_value; + else if (f=="tooltip") + buttons[idx].tooltip=p_value; else if (f=="icon") buttons[idx].icon=p_value; else @@ -95,6 +97,8 @@ bool ButtonArray::_get(const StringName& p_name,Variant &r_ret) const { String f = n.get_slicec('/',2); if (f=="text") r_ret=buttons[idx].text; + else if (f=="tooltip") + r_ret=buttons[idx].tooltip; else if (f=="icon") r_ret=buttons[idx].icon; else @@ -115,6 +119,7 @@ void ButtonArray::_get_property_list( List<PropertyInfo> *p_list) const { for(int i=0;i<buttons.size();i++) { String base="button/"+itos(i)+"/"; p_list->push_back( PropertyInfo( Variant::STRING, base+"text")); + p_list->push_back( PropertyInfo( Variant::STRING, base+"tooltip")); p_list->push_back( PropertyInfo( Variant::OBJECT, base+"icon",PROPERTY_HINT_RESOURCE_TYPE,"Texture")); } if (buttons.size()>0) { @@ -168,8 +173,12 @@ Size2 ButtonArray::get_minimum_size() const { void ButtonArray::_notification(int p_what) { switch(p_what) { + case NOTIFICATION_MOUSE_EXIT:{ + hover=-1; + update(); + }break; case NOTIFICATION_READY:{ - MethodInfo mi; + MethodInfo mi; mi.name="mouse_sub_enter"; add_user_signal(mi); @@ -245,8 +254,12 @@ void ButtonArray::_notification(int p_what) { Ref<Font> f; Color c; + Point2 sbsize; + Point2 sbofs; if (i==selected) { draw_style_box(style_selected,r); + sbsize=style_selected->get_minimum_size(); + sbofs=style_selected->get_offset(); f=font_selected; c=color_selected; if (has_focus()) @@ -254,8 +267,10 @@ void ButtonArray::_notification(int p_what) { } else { if (hover==i) draw_style_box(style_hover,r); - else + else if (!flat) draw_style_box(style_normal,r); + sbsize=style_normal->get_minimum_size(); + sbofs=style_normal->get_offset(); f=font_normal; c=color_normal; } @@ -265,7 +280,7 @@ void ButtonArray::_notification(int p_what) { ssize.x+=buttons[i].icon->get_width(); } - Point2 text_ofs=((r.size-ssize)/2.0+Point2(0,f->get_ascent())).floor(); + Point2 text_ofs=((r.size-ssize-sbsize)/2.0+Point2(0,f->get_ascent())).floor()+sbofs; if (buttons[i].icon.is_valid()) { draw_texture(buttons[i].icon,r.pos+Point2(text_ofs.x,Math::floor((r.size.height-buttons[i].icon->get_height())/2.0))); @@ -285,7 +300,7 @@ void ButtonArray::_notification(int p_what) { } -void ButtonArray::_input_event(const InputEvent& p_event) { +void ButtonArray::_gui_input(const InputEvent& p_event) { if ( ( (orientation==HORIZONTAL && p_event.is_action("ui_left") ) || @@ -349,6 +364,18 @@ void ButtonArray::_input_event(const InputEvent& p_event) { } +String ButtonArray::get_tooltip(const Point2& p_pos) const { + + int ofs = orientation==HORIZONTAL ? p_pos.x: p_pos.y; + for(int i=0;i<buttons.size();i++) { + + if (ofs>=buttons[i]._pos_cache && ofs<buttons[i]._pos_cache+buttons[i]._size_cache) + return buttons[i].tooltip; + + } + return Control::get_tooltip(p_pos); +} + void ButtonArray::set_align(Align p_align) { align=p_align; @@ -361,11 +388,23 @@ ButtonArray::Align ButtonArray::get_align() const { return align; } +void ButtonArray::set_flat(bool p_flat) { + + flat=p_flat; + update(); +} + +bool ButtonArray::is_flat() const { + + return flat; +} + -void ButtonArray::add_button(const String& p_text) { +void ButtonArray::add_button(const String& p_text,const String& p_tooltip) { Button button; button.text=p_text; + button.tooltip=p_tooltip; buttons.push_back(button); update(); @@ -375,11 +414,12 @@ void ButtonArray::add_button(const String& p_text) { minimum_size_changed(); } -void ButtonArray::add_icon_button(const Ref<Texture>& p_icon,const String& p_text) { +void ButtonArray::add_icon_button(const Ref<Texture>& p_icon,const String& p_text,const String& p_tooltip) { Button button; button.text=p_text; button.icon=p_icon; + button.tooltip=p_tooltip; buttons.push_back(button); if (selected==-1) selected=0; @@ -397,6 +437,13 @@ void ButtonArray::set_button_text(int p_button, const String& p_text) { } +void ButtonArray::set_button_tooltip(int p_button, const String& p_text) { + + ERR_FAIL_INDEX(p_button,buttons.size()); + buttons[p_button].tooltip=p_text; + +} + void ButtonArray::set_button_icon(int p_button, const Ref<Texture>& p_icon) { ERR_FAIL_INDEX(p_button,buttons.size()); @@ -411,6 +458,12 @@ String ButtonArray::get_button_text(int p_button) const { return buttons[p_button].text; } +String ButtonArray::get_button_tooltip(int p_button) const { + + ERR_FAIL_INDEX_V(p_button,buttons.size(),""); + return buttons[p_button].tooltip; +} + Ref<Texture> ButtonArray::get_button_icon(int p_button) const { ERR_FAIL_INDEX_V(p_button,buttons.size(),Ref<Texture>()); @@ -465,27 +518,33 @@ int ButtonArray::get_button_count() const { void ButtonArray::get_translatable_strings(List<String> *p_strings) const { - for(int i=0;i<buttons.size();i++) + for(int i=0;i<buttons.size();i++) { p_strings->push_back(buttons[i].text); + p_strings->push_back(buttons[i].tooltip); + } } void ButtonArray::_bind_methods() { - ObjectTypeDB::bind_method(_MD("add_button","text"),&ButtonArray::add_button); - ObjectTypeDB::bind_method(_MD("add_icon_button","icon:Texture","text"),&ButtonArray::add_icon_button,DEFVAL("")); - ObjectTypeDB::bind_method(_MD("set_button_text","button_idx","text"),&ButtonArray::set_button_text); - ObjectTypeDB::bind_method(_MD("set_button_icon","button_idx","icon:Texture"),&ButtonArray::set_button_icon); - ObjectTypeDB::bind_method(_MD("get_button_text","button_idx"),&ButtonArray::get_button_text); - ObjectTypeDB::bind_method(_MD("get_button_icon:Texture","button_idx"),&ButtonArray::get_button_icon); - ObjectTypeDB::bind_method(_MD("get_button_count"),&ButtonArray::get_button_count); - ObjectTypeDB::bind_method(_MD("get_selected"),&ButtonArray::get_selected); - ObjectTypeDB::bind_method(_MD("get_hovered"),&ButtonArray::get_hovered); - ObjectTypeDB::bind_method(_MD("set_selected","button_idx"),&ButtonArray::set_selected); - ObjectTypeDB::bind_method(_MD("erase_button","button_idx"),&ButtonArray::erase_button); - ObjectTypeDB::bind_method(_MD("clear"),&ButtonArray::clear); - - ObjectTypeDB::bind_method(_MD("_input_event"),&ButtonArray::_input_event); + ClassDB::bind_method(_MD("add_button","text","tooltip"),&ButtonArray::add_button,DEFVAL("")); + ClassDB::bind_method(_MD("add_icon_button","icon:Texture","text","tooltip"),&ButtonArray::add_icon_button,DEFVAL(""),DEFVAL("")); + ClassDB::bind_method(_MD("set_button_text","button_idx","text"),&ButtonArray::set_button_text); + ClassDB::bind_method(_MD("set_button_tooltip","button_idx","text"),&ButtonArray::set_button_tooltip); + ClassDB::bind_method(_MD("set_button_icon","button_idx","icon:Texture"),&ButtonArray::set_button_icon); + ClassDB::bind_method(_MD("get_button_text","button_idx"),&ButtonArray::get_button_text); + ClassDB::bind_method(_MD("get_button_tooltip","button_idx"),&ButtonArray::get_button_tooltip); + ClassDB::bind_method(_MD("get_button_icon:Texture","button_idx"),&ButtonArray::get_button_icon); + ClassDB::bind_method(_MD("get_button_count"),&ButtonArray::get_button_count); + ClassDB::bind_method(_MD("set_flat","enabled"),&ButtonArray::set_flat); + ClassDB::bind_method(_MD("is_flat"),&ButtonArray::is_flat); + ClassDB::bind_method(_MD("get_selected"),&ButtonArray::get_selected); + ClassDB::bind_method(_MD("get_hovered"),&ButtonArray::get_hovered); + ClassDB::bind_method(_MD("set_selected","button_idx"),&ButtonArray::set_selected); + ClassDB::bind_method(_MD("erase_button","button_idx"),&ButtonArray::erase_button); + ClassDB::bind_method(_MD("clear"),&ButtonArray::clear); + + ClassDB::bind_method(_MD("_gui_input"),&ButtonArray::_gui_input); BIND_CONSTANT( ALIGN_BEGIN ); BIND_CONSTANT( ALIGN_CENTER ); @@ -493,6 +552,8 @@ void ButtonArray::_bind_methods() { BIND_CONSTANT( ALIGN_FILL ); BIND_CONSTANT( ALIGN_EXPAND_FILL ); + ADD_PROPERTY( PropertyInfo( Variant::BOOL, "flat" ), _SCS("set_flat"),_SCS("is_flat") ); + ADD_SIGNAL( MethodInfo("button_selected",PropertyInfo(Variant::INT,"button_idx"))); } @@ -503,5 +564,6 @@ ButtonArray::ButtonArray(Orientation p_orientation) { selected=-1; set_focus_mode(FOCUS_ALL); hover=-1; + flat=false; min_button_size = -1; } diff --git a/scene/gui/button_array.h b/scene/gui/button_array.h index c4b9b0c9e3..37533695c9 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-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 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 */ @@ -33,7 +33,7 @@ class ButtonArray : public Control { - OBJ_TYPE(ButtonArray, Control); + GDCLASS(ButtonArray, Control); public: enum Align { ALIGN_BEGIN, @@ -50,6 +50,7 @@ private: struct Button { String text; + String tooltip; Ref<Texture> icon; mutable int _ms_cache; mutable int _pos_cache; @@ -58,6 +59,7 @@ private: int selected; int hover; + bool flat; double min_button_size; Vector<Button> buttons; @@ -72,20 +74,25 @@ protected: public: - void _input_event(const InputEvent& p_event); + void _gui_input(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_flat(bool p_flat); + bool is_flat() const; + + void add_button(const String& p_button,const String& p_tooltip=""); + void add_icon_button(const Ref<Texture>& p_icon,const String& p_button="",const String& p_tooltip=""); void set_button_text(int p_button, const String& p_text); + void set_button_tooltip(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; + String get_button_tooltip(int p_button) const; Ref<Texture> get_button_icon(int p_button) const; int get_selected() const; @@ -100,20 +107,21 @@ public: virtual Size2 get_minimum_size() const; virtual void get_translatable_strings(List<String> *p_strings) const; + virtual String get_tooltip(const Point2& p_pos) const; ButtonArray(Orientation p_orientation=HORIZONTAL); }; class HButtonArray : public ButtonArray { - OBJ_TYPE(HButtonArray,ButtonArray); + GDCLASS(HButtonArray,ButtonArray); public: HButtonArray() : ButtonArray(HORIZONTAL) {}; }; class VButtonArray : public ButtonArray { - OBJ_TYPE(VButtonArray,ButtonArray); + GDCLASS(VButtonArray,ButtonArray); public: VButtonArray() : ButtonArray(VERTICAL) {}; diff --git a/scene/gui/button_group.cpp b/scene/gui/button_group.cpp index 04ba5fc06d..01a3f633c3 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-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 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 */ @@ -27,6 +27,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ #include "button_group.h" + +#if 0 #include "base_button.h" void ButtonGroup::_add_button(BaseButton *p_button) { @@ -60,6 +62,9 @@ void ButtonGroup::_pressed(Object *p_button) { BaseButton *bb=E->get(); bb->set_pressed( b==bb ); + if (b==bb){ + emit_signal("button_selected", b); + } } } @@ -146,15 +151,17 @@ int ButtonGroup::get_pressed_button_index() const { void ButtonGroup::_bind_methods() { - ObjectTypeDB::bind_method(_MD("get_pressed_button:BaseButton"),&ButtonGroup::get_pressed_button); - ObjectTypeDB::bind_method(_MD("get_pressed_button_index"),&ButtonGroup::get_pressed_button_index); - ObjectTypeDB::bind_method(_MD("get_focused_button:BaseButton"),&ButtonGroup::get_focused_button); - ObjectTypeDB::bind_method(_MD("get_button_list"),&ButtonGroup::_get_button_list); - ObjectTypeDB::bind_method(_MD("_pressed"),&ButtonGroup::_pressed); - ObjectTypeDB::bind_method(_MD("set_pressed_button","button:BaseButton"),&ButtonGroup::_pressed); + ClassDB::bind_method(_MD("get_pressed_button:BaseButton"),&ButtonGroup::get_pressed_button); + ClassDB::bind_method(_MD("get_pressed_button_index"),&ButtonGroup::get_pressed_button_index); + ClassDB::bind_method(_MD("get_focused_button:BaseButton"),&ButtonGroup::get_focused_button); + ClassDB::bind_method(_MD("get_button_list"),&ButtonGroup::_get_button_list); + ClassDB::bind_method(_MD("_pressed"),&ButtonGroup::_pressed); + ClassDB::bind_method(_MD("set_pressed_button","button:BaseButton"),&ButtonGroup::_pressed); + ADD_SIGNAL( MethodInfo("button_selected",PropertyInfo(Variant::OBJECT,"button",PROPERTY_HINT_RESOURCE_TYPE,"BaseButton"))); } ButtonGroup::ButtonGroup() : BoxContainer(true) { } +#endif diff --git a/scene/gui/button_group.h b/scene/gui/button_group.h index 4afba22228..38acd06984 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-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 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,12 +31,12 @@ #include "scene/gui/box_container.h" - +#if 0 class BaseButton; class ButtonGroup : public BoxContainer { - OBJ_TYPE(ButtonGroup,BoxContainer); + GDCLASS(ButtonGroup,BoxContainer); Set<BaseButton*> buttons; @@ -63,4 +63,5 @@ public: ButtonGroup(); }; +#endif #endif // BUTTON_GROUP_H diff --git a/scene/gui/center_container.cpp b/scene/gui/center_container.cpp index 844175e4c1..4d4abb6484 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-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 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 */ @@ -42,7 +42,7 @@ Size2 CenterContainer::get_minimum_size() const { continue; if (c->is_set_as_toplevel()) continue; - if (c->is_hidden()) + if (!c->is_visible()) continue; Size2 minsize = c->get_combined_minimum_size(); ms.width = MAX(ms.width , minsize.width); @@ -92,8 +92,8 @@ void CenterContainer::_notification(int p_what) { void CenterContainer::_bind_methods() { - ObjectTypeDB::bind_method(_MD("set_use_top_left","enable"),&CenterContainer::set_use_top_left); - ObjectTypeDB::bind_method(_MD("is_using_top_left"),&CenterContainer::is_using_top_left); + ClassDB::bind_method(_MD("set_use_top_left","enable"),&CenterContainer::set_use_top_left); + ClassDB::bind_method(_MD("is_using_top_left"),&CenterContainer::is_using_top_left); ADD_PROPERTY( PropertyInfo(Variant::BOOL,"use_top_left"),_SCS("set_use_top_left"),_SCS("is_using_top_left")); } diff --git a/scene/gui/center_container.h b/scene/gui/center_container.h index dc95533525..7acc14de19 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-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 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 @@ class CenterContainer : public Container { - OBJ_TYPE( CenterContainer, Container ); + GDCLASS( CenterContainer, Container ); bool use_top_left; protected: diff --git a/scene/gui/check_box.cpp b/scene/gui/check_box.cpp index 1381d6eb60..c9803bc654 100644 --- a/scene/gui/check_box.cpp +++ b/scene/gui/check_box.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 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,14 +56,8 @@ void CheckBox::_notification(int p_what) { bool CheckBox::is_radio() { - Node* parent = this; - do { - parent = parent->get_parent(); - if (parent->cast_to<ButtonGroup>()) - break; - } while (parent); - return (parent != 0); + return get_button_group().is_valid(); } CheckBox::CheckBox(const String &p_text): diff --git a/scene/gui/check_box.h b/scene/gui/check_box.h index 95dd4891d4..6a4893936f 100644 --- a/scene/gui/check_box.h +++ b/scene/gui/check_box.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 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 */ @@ -36,7 +36,7 @@ */ class CheckBox : public Button { - OBJ_TYPE( CheckBox, Button ); + GDCLASS( CheckBox, Button ); protected: diff --git a/scene/gui/check_button.cpp b/scene/gui/check_button.cpp index f8c0c6b208..6404f066e8 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-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 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 a1ed4c1896..1c5440a25d 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-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 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 */ @@ -36,7 +36,7 @@ */ class CheckButton : public Button { - OBJ_TYPE( CheckButton, Button ); + GDCLASS( CheckButton, Button ); protected: diff --git a/scene/gui/color_picker.cpp b/scene/gui/color_picker.cpp index bd24b43761..da2fb1bc91 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-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 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,51 +34,33 @@ #include "os/input.h" #include "os/keyboard.h" -void update_material(Ref<CanvasItemMaterial>mat,const Color& p_color,float h,float s,float v) { - if (!mat.is_valid()) - return; - Ref<Shader> sdr = mat->get_shader(); - if (!sdr.is_valid()) - return; - - mat->set_shader_param("R",p_color.r); - mat->set_shader_param("G",p_color.g); - mat->set_shader_param("B",p_color.b); - mat->set_shader_param("H",h); - mat->set_shader_param("S",s); - mat->set_shader_param("V",v); - mat->set_shader_param("A",p_color.a); -} void ColorPicker::_notification(int p_what) { switch(p_what) { case NOTIFICATION_THEME_CHANGED: { - uv_material->set_shader(get_shader("uv_editor")); - w_material->set_shader(get_shader("w_editor")); - update_material(uv_material,color,h,s,v); - update_material(w_material,color,h,s,v); + //sample->set_texture(get_icon("color_sample")); + _update_controls(); } break; case NOTIFICATION_ENTER_TREE: { btn_pick->set_icon(get_icon("screen_picker", "ColorPicker")); - update_material(uv_material, color,h,s,v); - update_material(w_material, color,h,s,v); - uv_edit->get_child(0)->cast_to<Control>()->update(); - w_edit->get_child(0)->cast_to<Control>()->update(); _update_color(); } - case NOTIFICATION_VISIBILITY_CHANGED: { - c_text->call_deferred("grab_focus"); - c_text->call_deferred("select"); - } break; + } } +void ColorPicker::set_focus_on_line_edit() { + + c_text->grab_focus(); + c_text->select(); +} + void ColorPicker::_update_controls() { if (edit_alpha) { @@ -93,7 +75,7 @@ void ColorPicker::_update_controls() { } -void ColorPicker::set_color(const Color& p_color) { +void ColorPicker::set_pick_color(const Color& p_color) { color=p_color; if (color != last_hsv) { @@ -106,9 +88,7 @@ void ColorPicker::set_color(const Color& p_color) { if (!is_inside_tree()) return; - update_material(uv_material, color,h,s,v); - update_material(w_material, color,h,s,v); - + return; //it crashes, so returning uv_edit->get_child(0)->cast_to<Control>()->update(); w_edit->get_child(0)->cast_to<Control>()->update(); _update_color(); @@ -137,14 +117,13 @@ void ColorPicker::_value_changed(double) { if (updating) return; - for(int i=0;i<3;i++) { - color.components[i] = scroll[i]->get_val()/(raw_mode_enabled?1.0:255.0); + for(int i=0;i<4;i++) { + color.components[i] = scroll[i]->get_value()/(raw_mode_enabled?1.0:255.0); } - color.components[3] = scroll[3]->get_val()/255.0; - set_color(color); + set_pick_color(color); - c_text->set_text(color.to_html(edit_alpha && color.a<1)); + _update_text_value(); emit_signal("color_changed",color); @@ -160,7 +139,7 @@ void ColorPicker::_html_entered(const String& p_html) { if (!is_inside_tree()) return; - _update_color(); + set_pick_color(color); emit_signal("color_changed",color); } @@ -171,22 +150,16 @@ void ColorPicker::_update_color() { for(int i=0;i<4;i++) { scroll[i]->set_max(255); scroll[i]->set_step(0.01); - if (raw_mode_enabled && i != 3) - scroll[i]->set_val(color.components[i]); - else - scroll[i]->set_val(color.components[i]*255); + if (raw_mode_enabled) { + if (i == 3) + scroll[i]->set_max(1); + scroll[i]->set_value(color.components[i]); + } else { + scroll[i]->set_value(color.components[i] * 255); + } } - if (text_is_constructor) { - String t = "Color("+String::num(color.r)+","+String::num(color.g)+","+String::num(color.b); - if (edit_alpha && color.a<1) - t+=(","+String::num(color.a)+")") ; - else - t+=")"; - c_text->set_text(t); - } else { - c_text->set_text(color.to_html(edit_alpha && color.a<1)); - } + _update_text_value(); sample->update(); updating=false; @@ -196,10 +169,24 @@ void ColorPicker::_update_presets() { Size2 size=bt_add_preset->get_size(); preset->set_custom_minimum_size(Size2(size.width*presets.size(),size.height)); - Image i(size.x*presets.size(),size.y, false, Image::FORMAT_RGB); - for (int y=0;y<size.y;y++) - for (int x=0;x<size.x*presets.size();x++) - i.put_pixel(x,y,presets[(int)x/size.x]); + + PoolVector<uint8_t> img; + img.resize(size.x*presets.size()*size.y*3); + + { + PoolVector<uint8_t>::Write w=img.write(); + for (int y=0;y<size.y;y++) { + for (int x=0;x<size.x*presets.size();x++) { + int ofs = (y*(size.x*presets.size())+x)*3; + w[ofs+0]=uint8_t(CLAMP(presets[(int)x/size.x].r*255.0,0,255)); + w[ofs+1]=uint8_t(CLAMP(presets[(int)x/size.x].g*255.0,0,255)); + w[ofs+2]=uint8_t(CLAMP(presets[(int)x/size.x].b*255.0,0,255)); + } + } + } + + Image i(size.x*presets.size(),size.y, false, Image::FORMAT_RGB8,img); + Ref<ImageTexture> t; t.instance(); t->create_from_image(i); @@ -221,7 +208,7 @@ void ColorPicker::_text_type_toggled() _update_color(); } -Color ColorPicker::get_color() const { +Color ColorPicker::get_pick_color() const { return color; } @@ -259,6 +246,20 @@ bool ColorPicker::is_raw_mode() const { return raw_mode_enabled; } + +void ColorPicker::_update_text_value() { + if (text_is_constructor) { + String t = "Color("+String::num(color.r)+","+String::num(color.g)+","+String::num(color.b); + if (edit_alpha && color.a<1) + t+=(","+String::num(color.a)+")") ; + else + t+=")"; + c_text->set_text(t); + } else { + c_text->set_text(color.to_html(edit_alpha && color.a<1)); + } +} + void ColorPicker::_sample_draw() { sample->draw_rect(Rect2(Point2(),Size2(256,20)),color); } @@ -268,14 +269,39 @@ void ColorPicker::_hsv_draw(int p_wich,Control* c) if (!c) return; if (p_wich==0) { - int x=c->get_size().x*s; - int y=c->get_size().y-c->get_size().y*v; + Vector<Point2> points; + points.push_back(Vector2()); + points.push_back(Vector2(c->get_size().x,0)); + points.push_back(c->get_size()); + points.push_back(Vector2(0,c->get_size().y)); + Vector<Color> colors; + colors.push_back(Color(1,1,1)); + colors.push_back(Color(1,1,1)); + colors.push_back(Color()); + colors.push_back(Color()); + c->draw_polygon(points,colors); + Vector<Color> colors2; Color col = color; + col.set_hsv(color.get_h(),1,1); + col.a = 0; + colors2.push_back(col); + col.a = 1; + colors2.push_back(col); + col.set_hsv(color.get_h(),1,0); + colors2.push_back(col); + col.a = 0; + colors2.push_back(col); + c->draw_polygon(points,colors); + int x = CLAMP(c->get_size().x * s, 0, c->get_size().x); + int y = CLAMP(c->get_size().y-c->get_size().y * v, 0, c->get_size().y); + col = color; col.a=1; c->draw_line(Point2(x,0),Point2(x,c->get_size().y),col.inverted()); - c->draw_line(Point2(0,y),Point2(c->get_size().x,y),col.inverted()); + c->draw_line(Point2(0, y),Point2(c->get_size().x, y),col.inverted()); c->draw_line(Point2(x,y),Point2(x,y),Color(1,1,1),2); } else if (p_wich==1) { + Ref<Texture> hue = get_icon("color_hue","ColorPicker"); + c->draw_texture_rect(hue,Rect2(Point2(),c->get_size())); int y=c->get_size().y-c->get_size().y*h; Color col=Color(); col.set_hsv(h,1,1); @@ -286,7 +312,7 @@ void ColorPicker::_hsv_draw(int p_wich,Control* c) void ColorPicker::_uv_input(const InputEvent &ev) { if (ev.type == InputEvent::MOUSE_BUTTON) { const InputEventMouseButton &bev = ev.mouse_button; - if (bev.pressed) { + if (bev.pressed && bev.button_index==BUTTON_LEFT) { changing_color = true; float x = CLAMP((float)bev.x,0,256); float y = CLAMP((float)bev.y,0,256); @@ -294,7 +320,7 @@ void ColorPicker::_uv_input(const InputEvent &ev) { v=1.0-y/256.0; color.set_hsv(h,s,v,color.a); last_hsv = color; - set_color(color); + set_pick_color(color); _update_color(); emit_signal("color_changed", color); } else { @@ -310,7 +336,7 @@ void ColorPicker::_uv_input(const InputEvent &ev) { v=1.0-y/256.0; color.set_hsv(h,s,v,color.a); last_hsv = color; - set_color(color); + set_pick_color(color); _update_color(); emit_signal("color_changed", color); } @@ -319,7 +345,7 @@ void ColorPicker::_uv_input(const InputEvent &ev) { void ColorPicker::_w_input(const InputEvent &ev) { if (ev.type == InputEvent::MOUSE_BUTTON) { const InputEventMouseButton &bev = ev.mouse_button; - if (bev.pressed) { + if (bev.pressed && bev.button_index==BUTTON_LEFT) { changing_color = true; h=1-((float)bev.y)/256.0; @@ -328,7 +354,7 @@ void ColorPicker::_w_input(const InputEvent &ev) { } color.set_hsv(h,s,v,color.a); last_hsv = color; - set_color(color); + set_pick_color(color); _update_color(); emit_signal("color_changed", color); } else if (ev.type == InputEvent::MOUSE_MOTION) { @@ -339,7 +365,7 @@ void ColorPicker::_w_input(const InputEvent &ev) { h=1.0-y/256.0; color.set_hsv(h,s,v,color.a); last_hsv = color; - set_color(color); + set_pick_color(color); _update_color(); emit_signal("color_changed", color); } @@ -350,7 +376,7 @@ void ColorPicker::_preset_input(const InputEvent &ev) { const InputEventMouseButton &bev = ev.mouse_button; if (bev.pressed && bev.button_index==BUTTON_LEFT) { int index = bev.x/(preset->get_size().x/presets.size()); - set_color(presets[index]); + set_pick_color(presets[index]); } else if (bev.pressed && bev.button_index==BUTTON_RIGHT) { int index = bev.x/(preset->get_size().x/presets.size()); presets.erase(presets[index]); @@ -384,14 +410,23 @@ void ColorPicker::_screen_input(const InputEvent &ev) } else if (ev.type==InputEvent::MOUSE_MOTION) { const InputEventMouse &mev = ev.mouse_motion; Viewport *r=get_tree()->get_root(); - if (!r->get_rect().has_point(Point2(mev.global_x,mev.global_y))) + if (!r->get_visible_rect().has_point(Point2(mev.global_x,mev.global_y))) return; Image img =r->get_screen_capture(); - if (!img.empty()) + if (!img.empty()) { last_capture=img; r->queue_screen_capture(); - if (!last_capture.empty()) - set_color(last_capture.get_pixel(mev.global_x,mev.global_y)); + } + if (!last_capture.empty()) { + int pw = last_capture.get_format()==Image::FORMAT_RGBA8?4:3; + int ofs = (mev.global_y*last_capture.get_width()+mev.global_x)*pw; + + PoolVector<uint8_t>::Read r = last_capture.get_data().read(); + + Color c( r[ofs+0]/255.0, r[ofs+1]/255.0, r[ofs+2]/255.0 ); + + set_pick_color(c); + } } } @@ -405,34 +440,35 @@ void ColorPicker::_screen_pick_pressed() if (!screen) { screen=memnew( Control ); r->add_child(screen); + screen->set_as_toplevel(true); screen->set_area_as_parent_rect(); - screen->connect("input_event",this,"_screen_input"); + screen->connect("gui_input",this,"_screen_input"); } screen->raise(); - screen->show(); + screen->show_modal(); r->queue_screen_capture(); } void ColorPicker::_bind_methods() { - ObjectTypeDB::bind_method(_MD("set_color","color"),&ColorPicker::set_color); - ObjectTypeDB::bind_method(_MD("get_color"),&ColorPicker::get_color); - ObjectTypeDB::bind_method(_MD("set_raw_mode","mode"),&ColorPicker::set_raw_mode); - ObjectTypeDB::bind_method(_MD("is_raw_mode"),&ColorPicker::is_raw_mode); - ObjectTypeDB::bind_method(_MD("set_edit_alpha","show"),&ColorPicker::set_edit_alpha); - ObjectTypeDB::bind_method(_MD("is_editing_alpha"),&ColorPicker::is_editing_alpha); - ObjectTypeDB::bind_method(_MD("add_preset"), &ColorPicker::add_preset); - ObjectTypeDB::bind_method(_MD("_value_changed"),&ColorPicker::_value_changed); - ObjectTypeDB::bind_method(_MD("_html_entered"),&ColorPicker::_html_entered); - ObjectTypeDB::bind_method(_MD("_text_type_toggled"),&ColorPicker::_text_type_toggled); - ObjectTypeDB::bind_method(_MD("_add_preset_pressed"), &ColorPicker::_add_preset_pressed); - ObjectTypeDB::bind_method(_MD("_screen_pick_pressed"), &ColorPicker::_screen_pick_pressed); - ObjectTypeDB::bind_method(_MD("_sample_draw"),&ColorPicker::_sample_draw); - ObjectTypeDB::bind_method(_MD("_hsv_draw"),&ColorPicker::_hsv_draw); - ObjectTypeDB::bind_method(_MD("_uv_input"),&ColorPicker::_uv_input); - ObjectTypeDB::bind_method(_MD("_w_input"),&ColorPicker::_w_input); - ObjectTypeDB::bind_method(_MD("_preset_input"),&ColorPicker::_preset_input); - ObjectTypeDB::bind_method(_MD("_screen_input"),&ColorPicker::_screen_input); + ClassDB::bind_method(_MD("set_pick_color","color"),&ColorPicker::set_pick_color); + ClassDB::bind_method(_MD("get_pick_color"),&ColorPicker::get_pick_color); + ClassDB::bind_method(_MD("set_raw_mode","mode"),&ColorPicker::set_raw_mode); + ClassDB::bind_method(_MD("is_raw_mode"),&ColorPicker::is_raw_mode); + ClassDB::bind_method(_MD("set_edit_alpha","show"),&ColorPicker::set_edit_alpha); + ClassDB::bind_method(_MD("is_editing_alpha"),&ColorPicker::is_editing_alpha); + ClassDB::bind_method(_MD("add_preset"), &ColorPicker::add_preset); + ClassDB::bind_method(_MD("_value_changed"),&ColorPicker::_value_changed); + ClassDB::bind_method(_MD("_html_entered"),&ColorPicker::_html_entered); + ClassDB::bind_method(_MD("_text_type_toggled"),&ColorPicker::_text_type_toggled); + ClassDB::bind_method(_MD("_add_preset_pressed"), &ColorPicker::_add_preset_pressed); + ClassDB::bind_method(_MD("_screen_pick_pressed"), &ColorPicker::_screen_pick_pressed); + ClassDB::bind_method(_MD("_sample_draw"),&ColorPicker::_sample_draw); + ClassDB::bind_method(_MD("_hsv_draw"),&ColorPicker::_hsv_draw); + ClassDB::bind_method(_MD("_uv_input"),&ColorPicker::_uv_input); + ClassDB::bind_method(_MD("_w_input"),&ColorPicker::_w_input); + ClassDB::bind_method(_MD("_preset_input"),&ColorPicker::_preset_input); + ClassDB::bind_method(_MD("_screen_input"),&ColorPicker::_screen_input); ADD_SIGNAL( MethodInfo("color_changed",PropertyInfo(Variant::COLOR,"color"))); } @@ -451,7 +487,7 @@ ColorPicker::ColorPicker() : btn_pick = memnew( ToolButton ); btn_pick->connect("pressed",this,"_screen_pick_pressed"); - sample = memnew( TextureFrame ); + sample = memnew( TextureRect ); sample->set_h_size_flags(SIZE_EXPAND_FILL); sample->connect("draw",this,"_sample_draw"); @@ -461,50 +497,30 @@ ColorPicker::ColorPicker() : HBoxContainer *hb_edit = memnew( HBoxContainer ); - uv_edit= memnew ( TextureFrame ); - Image i(256, 256, false, Image::FORMAT_RGB); - for (int y=0;y<256;y++) - for (int x=0;x<256;x++) - i.put_pixel(x,y,Color()); - Ref<ImageTexture> t; - t.instance(); - t->create_from_image(i); - uv_edit->set_texture(t); - uv_edit->set_ignore_mouse(false); - uv_edit->set_custom_minimum_size(Size2(256,256)); - uv_edit->connect("input_event", this, "_uv_input"); - Control *c= memnew( Control ); - uv_edit->add_child(c); - c->set_area_as_parent_rect(); - c->set_stop_mouse(false); - c->set_material(memnew ( CanvasItemMaterial )); + uv_edit= memnew ( Control ); + + + + + uv_edit->connect("gui_input", this, "_uv_input"); + uv_edit->set_mouse_filter(MOUSE_FILTER_PASS); + uv_edit->set_custom_minimum_size(Size2 (256,256)); Vector<Variant> args=Vector<Variant>(); args.push_back(0); - args.push_back(c); - c->connect("draw",this,"_hsv_draw",args); + args.push_back(uv_edit); + uv_edit->connect("draw",this,"_hsv_draw",args); add_child(hb_edit); - w_edit= memnew( TextureFrame ); - i = Image(15, 256, false, Image::FORMAT_RGB); - for (int y=0;y<256;y++) - for (int x=0;x<15;x++) - i.put_pixel(x,y,Color()); - Ref<ImageTexture> tw; - tw.instance(); - tw->create_from_image(i); - w_edit->set_texture(tw); - w_edit->set_ignore_mouse(false); - w_edit->set_custom_minimum_size(Size2(15,256)); - w_edit->connect("input_event", this, "_w_input"); - c= memnew( Control ); - w_edit->add_child(c); - c->set_area_as_parent_rect(); - c->set_stop_mouse(false); - c->set_material(memnew ( CanvasItemMaterial )); + + w_edit= memnew( Control ); + //w_edit->set_ignore_mouse(false); + w_edit->set_custom_minimum_size(Size2(30,256)); + w_edit->connect("gui_input", this, "_w_input"); args.clear(); args.push_back(1); - args.push_back(c); - c->connect("draw",this,"_hsv_draw",args); + args.push_back(w_edit); + w_edit->connect("draw",this,"_hsv_draw",args); + hb_edit->add_child(uv_edit); hb_edit->add_child(memnew( VSeparator )); @@ -568,39 +584,16 @@ ColorPicker::ColorPicker() : //_update_color(); updating=false; - uv_material.instance(); - Ref<Shader> s_uv = get_shader("uv_editor"); - uv_material->set_shader(s_uv); + set_pick_color(Color(1,1,1)); - w_material.instance(); - - Ref<Shader> s_w = get_shader("w_editor"); - w_material->set_shader(s_w); - - uv_edit->set_material(uv_material); - w_edit->set_material(w_material); - - set_color(Color(1,1,1)); - - i.create(256,20,false,Image::FORMAT_RGB); - for (int y=0;y<20;y++) - for(int x=0;x<256;x++) - if ((x/4+y/4)%2) - i.put_pixel(x,y,Color(1,1,1)); - else - i.put_pixel(x,y,Color(0.6,0.6,0.6)); - Ref<ImageTexture> t_smpl; - t_smpl.instance(); - t_smpl->create_from_image(i); - sample->set_texture(t_smpl); HBoxContainer *bbc = memnew( HBoxContainer ); add_child(bbc); - preset = memnew( TextureFrame ); + preset = memnew( TextureRect ); bbc->add_child(preset); - preset->set_ignore_mouse(false); - preset->connect("input_event", this, "_preset_input"); + //preset->set_ignore_mouse(false); + preset->connect("gui_input", this, "_preset_input"); bt_add_preset = memnew ( Button ); bt_add_preset->set_icon(get_icon("add_preset")); @@ -628,6 +621,7 @@ void ColorPickerButton::pressed() { popup->set_pos(get_global_pos()-Size2(0,ms.height)); popup->set_size(ms); popup->popup(); + picker->set_focus_on_line_edit(); } @@ -638,19 +632,20 @@ void ColorPickerButton::_notification(int p_what) { if (p_what==NOTIFICATION_DRAW) { Ref<StyleBox> normal = get_stylebox("normal" ); - draw_rect(Rect2(normal->get_offset(),get_size()-normal->get_minimum_size()),picker->get_color()); + draw_rect(Rect2(normal->get_offset(),get_size()-normal->get_minimum_size()),picker->get_pick_color()); } } -void ColorPickerButton::set_color(const Color& p_color){ +void ColorPickerButton::set_pick_color(const Color& p_color){ - picker->set_color(p_color); + picker->set_pick_color(p_color); update(); + emit_signal("color_changed",p_color); } -Color ColorPickerButton::get_color() const{ +Color ColorPickerButton::get_pick_color() const{ - return picker->get_color(); + return picker->get_pick_color(); } void ColorPickerButton::set_edit_alpha(bool p_show) { @@ -664,16 +659,21 @@ bool ColorPickerButton::is_editing_alpha() const{ } +ColorPicker *ColorPickerButton::get_picker() { + return picker; +} + void ColorPickerButton::_bind_methods(){ - ObjectTypeDB::bind_method(_MD("set_color","color"),&ColorPickerButton::set_color); - ObjectTypeDB::bind_method(_MD("get_color"),&ColorPickerButton::get_color); - ObjectTypeDB::bind_method(_MD("set_edit_alpha","show"),&ColorPickerButton::set_edit_alpha); - ObjectTypeDB::bind_method(_MD("is_editing_alpha"),&ColorPickerButton::is_editing_alpha); - ObjectTypeDB::bind_method(_MD("_color_changed"),&ColorPickerButton::_color_changed); + ClassDB::bind_method(_MD("set_pick_color","color"),&ColorPickerButton::set_pick_color); + ClassDB::bind_method(_MD("get_pick_color"),&ColorPickerButton::get_pick_color); + ClassDB::bind_method(_MD("get_picker:ColorPicker"),&ColorPickerButton::get_picker); + ClassDB::bind_method(_MD("set_edit_alpha","show"),&ColorPickerButton::set_edit_alpha); + ClassDB::bind_method(_MD("is_editing_alpha"),&ColorPickerButton::is_editing_alpha); + ClassDB::bind_method(_MD("_color_changed"),&ColorPickerButton::_color_changed); ADD_SIGNAL( MethodInfo("color_changed",PropertyInfo(Variant::COLOR,"color"))); - ADD_PROPERTY( PropertyInfo(Variant::COLOR,"color"),_SCS("set_color"),_SCS("get_color") ); + ADD_PROPERTY( PropertyInfo(Variant::COLOR,"color"),_SCS("set_pick_color"),_SCS("get_pick_color") ); ADD_PROPERTY( PropertyInfo(Variant::BOOL,"edit_alpha"),_SCS("set_edit_alpha"),_SCS("is_editing_alpha") ); } @@ -683,7 +683,7 @@ ColorPickerButton::ColorPickerButton() { popup = memnew( PopupPanel ); picker = memnew( ColorPicker ); popup->add_child(picker); - popup->set_child_rect(picker); + picker->connect("color_changed",this,"_color_changed"); add_child(popup); } diff --git a/scene/gui/color_picker.h b/scene/gui/color_picker.h index 4559bc7391..d9db9c89f7 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-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 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 */ @@ -36,29 +36,26 @@ #include "scene/gui/button.h" #include "scene/gui/popup.h" #include "scene/gui/box_container.h" -#include "scene/gui/texture_frame.h" +#include "scene/gui/texture_rect.h" #include "scene/gui/tool_button.h" #include "scene/gui/check_button.h" -#include "scene/resources/material.h" class ColorPicker : public BoxContainer { - OBJ_TYPE(ColorPicker,BoxContainer); + GDCLASS(ColorPicker,BoxContainer); private: Control *screen; Image last_capture; - TextureFrame *uv_edit; - TextureFrame *w_edit; - TextureFrame *sample; - TextureFrame *preset; + Control *uv_edit; + Control *w_edit; + TextureRect *sample; + TextureRect *preset; Button *bt_add_preset; List<Color> presets; ToolButton *btn_pick; CheckButton *btn_mode; - Ref<CanvasItemMaterial> uv_material; - Ref<CanvasItemMaterial> w_material; HSlider *scroll[4]; SpinBox *values[4]; Label *labels[4]; @@ -80,6 +77,7 @@ private: void _update_controls(); void _update_color(); void _update_presets(); + void _update_text_value(); void _text_type_toggled(); void _sample_draw(); void _hsv_draw(int p_wich,Control *c); @@ -100,20 +98,21 @@ public: void set_edit_alpha(bool p_show); bool is_editing_alpha() const; - void set_color(const Color& p_color); - Color get_color() const; + void set_pick_color(const Color& p_color); + Color get_pick_color() const; void add_preset(const Color& p_color); void set_raw_mode(bool p_enabled); bool is_raw_mode() const; + void set_focus_on_line_edit(); ColorPicker(); }; class ColorPickerButton : public Button { - OBJ_TYPE(ColorPickerButton,Button); + GDCLASS(ColorPickerButton,Button); PopupPanel *popup; ColorPicker *picker; @@ -127,12 +126,14 @@ protected: static void _bind_methods(); public: - void set_color(const Color& p_color); - Color get_color() const; + void set_pick_color(const Color& p_color); + Color get_pick_color() const; void set_edit_alpha(bool p_show); bool is_editing_alpha() const; + ColorPicker *get_picker(); + ColorPickerButton(); }; diff --git a/scene/gui/color_ramp_edit.cpp b/scene/gui/color_ramp_edit.cpp index 2ab004e04b..5d5d6c31a2 100644 --- a/scene/gui/color_ramp_edit.cpp +++ b/scene/gui/color_ramp_edit.cpp @@ -1,3 +1,31 @@ +/*************************************************************************/ +/* color_ramp_edit.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2017 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 */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ #include "color_ramp_edit.h" #include "os/keyboard.h" @@ -9,7 +37,7 @@ ColorRampEdit::ColorRampEdit(){ popup = memnew( PopupPanel ); picker = memnew( ColorPicker ); popup->add_child(picker); - popup->set_child_rect(picker); + add_child(popup); checker = Ref<ImageTexture>(memnew( ImageTexture )); @@ -32,7 +60,7 @@ 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); + picker->set_pick_color(points[grabbed].color); popup->set_pos(get_global_pos()-Vector2(ms.width-get_size().width,ms.height)); popup->set_size(ms); popup->popup(); @@ -42,7 +70,7 @@ ColorRampEdit::~ColorRampEdit() { } -void ColorRampEdit::_input_event(const InputEvent& p_event) { +void ColorRampEdit::_gui_input(const InputEvent& p_event) { if (p_event.type==InputEvent::KEY && p_event.key.pressed && p_event.key.scancode==KEY_DELETE && grabbed!=-1) { @@ -243,7 +271,9 @@ void ColorRampEdit::_input_event(const InputEvent& p_event) { void ColorRampEdit::_notification(int p_what) { if (p_what==NOTIFICATION_ENTER_TREE) { - picker->connect("color_changed",this,"_color_changed"); + if (!picker->is_connected("color_changed",this,"_color_changed")) { + picker->connect("color_changed",this,"_color_changed"); + } } if (p_what==NOTIFICATION_DRAW) { @@ -416,7 +446,7 @@ Vector<ColorRamp::Point>& ColorRampEdit::get_points() { } void ColorRampEdit::_bind_methods() { - ObjectTypeDB::bind_method(_MD("_input_event"),&ColorRampEdit::_input_event); - ObjectTypeDB::bind_method(_MD("_color_changed"),&ColorRampEdit::_color_changed); + ClassDB::bind_method(_MD("_gui_input"),&ColorRampEdit::_gui_input); + ClassDB::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 index 91292eed0d..c6a20a539d 100644 --- a/scene/gui/color_ramp_edit.h +++ b/scene/gui/color_ramp_edit.h @@ -1,3 +1,31 @@ +/*************************************************************************/ +/* color_ramp_edit.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2017 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 */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ #ifndef SCENE_GUI_COLOR_RAMP_EDIT_H_ #define SCENE_GUI_COLOR_RAMP_EDIT_H_ @@ -10,7 +38,7 @@ class ColorRampEdit : public Control { - OBJ_TYPE(ColorRampEdit,Control); + GDCLASS(ColorRampEdit,Control); PopupPanel *popup; ColorPicker *picker; @@ -27,7 +55,7 @@ class ColorRampEdit : public Control { void _show_color_picker(); protected: - void _input_event(const InputEvent& p_event); + void _gui_input(const InputEvent& p_event); void _notification(int p_what); static void _bind_methods(); @@ -45,7 +73,7 @@ public: /*class ColorRampEditPanel : public Panel { - OBJ_TYPE(ColorRampEditPanel, Panel ); + GDCLASS(ColorRampEditPanel, Panel ); };*/ diff --git a/scene/gui/custom_button.cpp b/scene/gui/color_rect.cpp index a70af05418..99797aa9c1 100644 --- a/scene/gui/custom_button.cpp +++ b/scene/gui/color_rect.cpp @@ -1,11 +1,11 @@ /*************************************************************************/ -/* custom_button.cpp */ +/* color_rect.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 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,15 +26,36 @@ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "custom_button.h" +#include "color_rect.h" -CustomButton::CustomButton() -{ + +void ColorRect::set_frame_color(const Color& p_color) { + + color=p_color; + update(); +} + +Color ColorRect::get_frame_color() const{ + + return color; } +void ColorRect::_notification(int p_what) { -CustomButton::~CustomButton() -{ + if (p_what==NOTIFICATION_DRAW) { + draw_rect(Rect2(Point2(),get_size()),color); + } } +void ColorRect::_bind_methods() { + ClassDB::bind_method(_MD("set_frame_color","color"),&ColorRect::set_frame_color); + ClassDB::bind_method(_MD("get_frame_color"),&ColorRect::get_frame_color); + + ADD_PROPERTY(PropertyInfo(Variant::COLOR,"color"),_SCS("set_frame_color"),_SCS("get_frame_color") ); +} + +ColorRect::ColorRect() { + + color=Color(1,1,1); +} diff --git a/scene/gui/custom_button.h b/scene/gui/color_rect.h index 2492750489..55e413ce27 100644 --- a/scene/gui/custom_button.h +++ b/scene/gui/color_rect.h @@ -1,11 +1,11 @@ /*************************************************************************/ -/* custom_button.h */ +/* color_rect.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 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,18 +26,25 @@ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef CUSTOM_BUTTON_H -#define CUSTOM_BUTTON_H +#ifndef COLOR_RECT_H +#define COLOR_RECT_H -/** - @author Juan Linietsky <reduzio@gmail.com> -*/ -class CustomButton{ +#include "scene/gui/control.h" + +class ColorRect : public Control { + GDCLASS(ColorRect,Control) + + Color color; +protected: + + void _notification(int p_what); + static void _bind_methods(); public: - CustomButton(); - ~CustomButton(); + void set_frame_color(const Color& p_color); + Color get_frame_color() const; + ColorRect(); }; -#endif +#endif // COLOR_RECT_H diff --git a/scene/gui/container.cpp b/scene/gui/container.cpp index 920c6bf1e6..de5f35933c 100644 --- a/scene/gui/container.cpp +++ b/scene/gui/container.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 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 */ @@ -41,6 +41,8 @@ void Container::_child_minsize_changed() { void Container::add_child_notify(Node *p_child) { + Control::add_child_notify(p_child); + Control *control = p_child->cast_to<Control>(); if (!control) return; @@ -50,18 +52,24 @@ void Container::add_child_notify(Node *p_child) { control->connect("visibility_changed",this,"_child_minsize_changed"); queue_sort(); + } void Container::move_child_notify(Node *p_child) { + Control::move_child_notify(p_child); + if (!p_child->cast_to<Control>()) return; queue_sort(); + + } void Container::remove_child_notify(Node *p_child) { + Control::remove_child_notify(p_child); Control *control = p_child->cast_to<Control>(); if (!control) @@ -139,7 +147,7 @@ void Container::_notification(int p_what) { } break; case NOTIFICATION_VISIBILITY_CHANGED: { - if (is_visible()) { + if (is_visible_in_tree()) { queue_sort(); } } break; @@ -148,11 +156,11 @@ void Container::_notification(int p_what) { void Container::_bind_methods() { - ObjectTypeDB::bind_method(_MD("_sort_children"),&Container::_sort_children); - ObjectTypeDB::bind_method(_MD("_child_minsize_changed"),&Container::_child_minsize_changed); + ClassDB::bind_method(_MD("_sort_children"),&Container::_sort_children); + ClassDB::bind_method(_MD("_child_minsize_changed"),&Container::_child_minsize_changed); - ObjectTypeDB::bind_method(_MD("queue_sort"),&Container::queue_sort); - ObjectTypeDB::bind_method(_MD("fit_child_in_rect","child:Control","rect"),&Container::fit_child_in_rect); + ClassDB::bind_method(_MD("queue_sort"),&Container::queue_sort); + ClassDB::bind_method(_MD("fit_child_in_rect","child:Control","rect"),&Container::fit_child_in_rect); BIND_CONSTANT( NOTIFICATION_SORT_CHILDREN ); ADD_SIGNAL(MethodInfo("sort_children")); diff --git a/scene/gui/container.h b/scene/gui/container.h index 1c7587c155..bb47524972 100644 --- a/scene/gui/container.h +++ b/scene/gui/container.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 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 */ @@ -33,7 +33,7 @@ class Container : public Control { - OBJ_TYPE(Container,Control); + GDCLASS(Container,Control); bool pending_sort; void _sort_children(); diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp index 73e7237058..533d24f998 100644 --- a/scene/gui/control.cpp +++ b/scene/gui/control.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 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 */ @@ -49,14 +49,22 @@ Variant Control::edit_get_state() const { - return get_rect(); + Dictionary s; + s["rect"]=get_rect(); + s["rot"]=get_rotation(); + s["scale"]=get_scale(); + return s; } void Control::edit_set_state(const Variant& p_state) { - Rect2 state=p_state; + Dictionary s=p_state; + + Rect2 state=s["rect"]; set_pos(state.pos); set_size(state.size); + set_rotation(s["rot"]); + set_scale(s["scale"]); } void Control::set_custom_minimum_size(const Size2& p_custom) { @@ -88,7 +96,7 @@ Size2 Control::edit_get_minimum_size() const { void Control::edit_set_rect(const Rect2& p_edit_rect) { - Matrix32 postxf; + Transform2D postxf; postxf.set_rotation_and_scale(data.rotation,data.scale); Vector2 new_pos = postxf.xform(p_edit_rect.pos); @@ -108,30 +116,7 @@ bool Control::_set(const StringName& p_name, const Variant& p_value) { String name= p_name; if (!name.begins_with("custom")) { - if (name.begins_with("margin/")) { - String dname = name.get_slicec('/', 1); - if (dname == "left") { - set_margin(MARGIN_LEFT, p_value); - return true; - } - else if (dname == "top") { - set_margin(MARGIN_TOP, p_value); - return true; - } - else if (dname == "right") { - set_margin(MARGIN_RIGHT, p_value); - return true; - } - else if (dname == "bottom") { - set_margin(MARGIN_BOTTOM, p_value); - return true; - } - else { - return false; - } - } else { - return false; - } + return false; } if (p_value.get_type()==Variant::NIL) { @@ -153,6 +138,9 @@ bool Control::_set(const StringName& p_name, const Variant& p_value) { update(); } else if (name.begins_with("custom_fonts/")) { String dname = name.get_slicec('/',1); + if (data.font_override.has(dname)) { + _unref_font(data.font_override[dname]); + } data.font_override.erase(dname); notification(NOTIFICATION_THEME_CHANGED); update(); @@ -223,31 +211,10 @@ bool Control::_get(const StringName& p_name,Variant &r_ret) const { String sname=p_name; - if (!sname.begins_with("custom")) - if (sname.begins_with("margin/")) { - String dname = sname.get_slicec('/', 1); - if (dname == "left") { - r_ret = get_margin(MARGIN_LEFT); - return true; - } - else if (dname == "top") { - r_ret = get_margin(MARGIN_TOP); - return true; - } - else if (dname == "right") { - r_ret = get_margin(MARGIN_RIGHT); - return true; - } - else if (dname == "bottom") { - r_ret = get_margin(MARGIN_BOTTOM); - return true; - } - else { - return false; - } - } else { - return false; - } + if (!sname.begins_with("custom")) { + return false; + + } if (sname.begins_with("custom_icons/")) { String name = sname.get_slicec('/',1); @@ -283,36 +250,6 @@ bool Control::_get(const StringName& p_name,Variant &r_ret) const { } void Control::_get_property_list( List<PropertyInfo> *p_list) const { - { - if (get_anchor(MARGIN_LEFT) == ANCHOR_RATIO) { - p_list->push_back(PropertyInfo(Variant::REAL, "margin/left", PROPERTY_HINT_RANGE, "-4096,4096,0.001")); - } - else { - p_list->push_back(PropertyInfo(Variant::INT, "margin/left", PROPERTY_HINT_RANGE, "-4096,4096")); - } - - if (get_anchor(MARGIN_TOP) == ANCHOR_RATIO) { - p_list->push_back(PropertyInfo(Variant::REAL, "margin/top", PROPERTY_HINT_RANGE, "-4096,4096,0.001")); - } - else { - p_list->push_back(PropertyInfo(Variant::INT, "margin/top", PROPERTY_HINT_RANGE, "-4096,4096")); - } - - if (get_anchor(MARGIN_RIGHT) == ANCHOR_RATIO) { - p_list->push_back(PropertyInfo(Variant::REAL, "margin/right", PROPERTY_HINT_RANGE, "-4096,4096,0.001")); - } - else { - p_list->push_back(PropertyInfo(Variant::INT, "margin/right", PROPERTY_HINT_RANGE, "-4096,4096")); - } - - if (get_anchor(MARGIN_BOTTOM) == ANCHOR_RATIO) { - p_list->push_back(PropertyInfo(Variant::REAL, "margin/bottom", PROPERTY_HINT_RANGE, "-4096,4096,0.001")); - } - else { - p_list->push_back(PropertyInfo(Variant::INT, "margin/bottom", PROPERTY_HINT_RANGE, "-4096,4096")); - } - } - Ref<Theme> theme; if (data.theme.is_valid()) { @@ -324,7 +261,7 @@ void Control::_get_property_list( List<PropertyInfo> *p_list) const { { List<StringName> names; - theme->get_icon_list(get_type_name(),&names); + theme->get_icon_list(get_class_name(),&names); for(List<StringName>::Element *E=names.front();E;E=E->next()) { uint32_t hint= PROPERTY_USAGE_EDITOR|PROPERTY_USAGE_CHECKABLE; @@ -336,7 +273,7 @@ void Control::_get_property_list( List<PropertyInfo> *p_list) const { } { List<StringName> names; - theme->get_shader_list(get_type_name(),&names); + theme->get_shader_list(get_class_name(),&names); for(List<StringName>::Element *E=names.front();E;E=E->next()) { uint32_t hint= PROPERTY_USAGE_EDITOR|PROPERTY_USAGE_CHECKABLE; @@ -348,7 +285,7 @@ void Control::_get_property_list( List<PropertyInfo> *p_list) const { } { List<StringName> names; - theme->get_stylebox_list(get_type_name(),&names); + theme->get_stylebox_list(get_class_name(),&names); for(List<StringName>::Element *E=names.front();E;E=E->next()) { uint32_t hint= PROPERTY_USAGE_EDITOR|PROPERTY_USAGE_CHECKABLE; @@ -360,7 +297,7 @@ void Control::_get_property_list( List<PropertyInfo> *p_list) const { } { List<StringName> names; - theme->get_font_list(get_type_name(),&names); + theme->get_font_list(get_class_name(),&names); for(List<StringName>::Element *E=names.front();E;E=E->next()) { uint32_t hint= PROPERTY_USAGE_EDITOR|PROPERTY_USAGE_CHECKABLE; @@ -372,7 +309,7 @@ void Control::_get_property_list( List<PropertyInfo> *p_list) const { } { List<StringName> names; - theme->get_color_list(get_type_name(),&names); + theme->get_color_list(get_class_name(),&names); for(List<StringName>::Element *E=names.front();E;E=E->next()) { uint32_t hint= PROPERTY_USAGE_EDITOR|PROPERTY_USAGE_CHECKABLE; @@ -384,7 +321,7 @@ void Control::_get_property_list( List<PropertyInfo> *p_list) const { } { List<StringName> names; - theme->get_constant_list(get_type_name(),&names); + theme->get_constant_list(get_class_name(),&names); for(List<StringName>::Element *E=names.front();E;E=E->next()) { uint32_t hint= PROPERTY_USAGE_EDITOR|PROPERTY_USAGE_CHECKABLE; @@ -410,7 +347,38 @@ void Control::_resize(const Size2& p_size) { _size_changed(); } +//moved theme configuration here, so controls can set up even if still not inside active scene + +void Control::add_child_notify(Node *p_child) { + + Control *child_c=p_child->cast_to<Control>(); + if (!child_c) + return; + + if (child_c->data.theme.is_null() && data.theme_owner) { + _propagate_theme_changed(child_c,data.theme_owner); //need to propagate here, since many controls may require setting up stuff + } +} + +void Control::remove_child_notify(Node *p_child) { + + Control *child_c=p_child->cast_to<Control>(); + if (!child_c) + return; + + if (child_c->data.theme_owner && child_c->data.theme.is_null()) { + _propagate_theme_changed(child_c,NULL); + } + +} + +void Control::_update_canvas_item_transform() { + Transform2D xform=Transform2D(data.rotation,get_pos()); + xform.scale_basis(data.scale); + VisualServer::get_singleton()->canvas_item_set_transform(get_canvas_item(),xform); + +} void Control::_notification(int p_notification) { @@ -436,11 +404,17 @@ void Control::_notification(int p_notification) { if (is_set_as_toplevel()) { data.SI=get_viewport()->_gui_add_subwindow_control(this); + + if (data.theme.is_null() && data.parent && data.parent->data.theme_owner) { + data.theme_owner=data.parent->data.theme_owner; + notification(NOTIFICATION_THEME_CHANGED); + } + } else { Node *parent=this; //meh - Node *parent_control=NULL; + Control *parent_control=NULL; bool subwindow=false; while(parent) { @@ -456,8 +430,9 @@ void Control::_notification(int p_notification) { break; } - if (parent->cast_to<Control>()) { - parent_control=parent->cast_to<Control>(); + parent_control=parent->cast_to<Control>(); + + if (parent_control) { break; } else if (ci) { @@ -469,6 +444,10 @@ void Control::_notification(int p_notification) { if (parent_control) { //do nothing, has a parent control + if (data.theme.is_null() && parent_control->data.theme_owner) { + data.theme_owner=parent_control->data.theme_owner; + notification(NOTIFICATION_THEME_CHANGED); + } } else if (subwindow) { //is a subwindow (process input before other controls for that canvas) data.SI=get_viewport()->_gui_add_subwindow_control(this); @@ -489,6 +468,12 @@ void Control::_notification(int p_notification) { } + /* + if (data.theme.is_null() && data.parent && data.parent->data.theme_owner) { + data.theme_owner=data.parent->data.theme_owner; + notification(NOTIFICATION_THEME_CHANGED); + } + */ } break; case NOTIFICATION_EXIT_CANVAS: { @@ -520,27 +505,12 @@ void Control::_notification(int p_notification) { data.parent=NULL; data.parent_canvas_item=NULL; - - } break; - - - case NOTIFICATION_PARENTED: { - - Control * parent = get_parent()->cast_to<Control>(); - - //make children reference them theme - - 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) { - _propagate_theme_changed(NULL); + /* + if (data.theme_owner && data.theme.is_null()) { + data.theme_owner=NULL; + notification(NOTIFICATION_THEME_CHANGED); } + */ } break; case NOTIFICATION_MOVED_IN_PARENT: { @@ -564,29 +534,28 @@ void Control::_notification(int p_notification) { } break; case NOTIFICATION_DRAW: { - Matrix32 xform=Matrix32(data.rotation,get_pos()); - xform.scale_basis(data.scale); - VisualServer::get_singleton()->canvas_item_set_transform(get_canvas_item(),xform); - VisualServer::get_singleton()->canvas_item_set_custom_rect( get_canvas_item(),true, Rect2(Point2(),get_size())); + _update_canvas_item_transform(); + VisualServer::get_singleton()->canvas_item_set_custom_rect( get_canvas_item(),!data.disable_visibility_clip, Rect2(Point2(),get_size())); + VisualServer::get_singleton()->canvas_item_set_clip( get_canvas_item(), data.clip_contents ); //emit_signal(SceneStringNames::get_singleton()->draw); } break; case NOTIFICATION_MOUSE_ENTER: { - emit_signal(SceneStringNames::get_singleton()->mouse_enter); + emit_signal(SceneStringNames::get_singleton()->mouse_entered); } break; case NOTIFICATION_MOUSE_EXIT: { - emit_signal(SceneStringNames::get_singleton()->mouse_exit); + emit_signal(SceneStringNames::get_singleton()->mouse_exited); } break; case NOTIFICATION_FOCUS_ENTER: { - emit_signal(SceneStringNames::get_singleton()->focus_enter); + emit_signal(SceneStringNames::get_singleton()->focus_entered); update(); } break; case NOTIFICATION_FOCUS_EXIT: { - emit_signal(SceneStringNames::get_singleton()->focus_exit); + emit_signal(SceneStringNames::get_singleton()->focus_exited); update(); } break; @@ -596,11 +565,11 @@ void Control::_notification(int p_notification) { } break; case NOTIFICATION_MODAL_CLOSE: { - emit_signal("modal_close"); + emit_signal("modal_closed"); } break; case NOTIFICATION_VISIBILITY_CHANGED: { - if (!is_visible()) { + if (!is_visible_in_tree()) { if(get_viewport() != NULL) get_viewport()->_gui_hid_control(this); @@ -752,6 +721,11 @@ bool Control::is_window_modal_on_top() const { return get_viewport()->_gui_is_modal_on_top(this); } +uint64_t Control::get_modal_frame() const { + + return data.modal_frame; +} + Size2 Control::get_minimum_size() const { @@ -770,22 +744,30 @@ Size2 Control::get_minimum_size() const { Ref<Texture> Control::get_icon(const StringName& p_name,const StringName& p_type) const { - if (p_type==StringName()) { + if (p_type==StringName() || p_type=="") { const Ref<Texture>* tex = data.icon_override.getptr(p_name); if (tex) return *tex; } - StringName type = p_type?p_type:get_type_name(); + StringName type = p_type?p_type:get_class_name(); // try with custom themes Control *theme_owner = data.theme_owner; while(theme_owner) { - if (theme_owner->data.theme->has_icon(p_name, type ) ) - return data.theme_owner->data.theme->get_icon(p_name, type ); + StringName class_name = type; + + while(class_name!=StringName()) { + if (theme_owner->data.theme->has_icon(p_name, class_name ) ) { + return theme_owner->data.theme->get_icon(p_name, class_name ); + } + + class_name = ClassDB::get_parent_class_nocheck(class_name); + } + Control *parent = theme_owner->get_parent()?theme_owner->get_parent()->cast_to<Control>():NULL; if (parent) @@ -800,22 +782,30 @@ Ref<Texture> Control::get_icon(const StringName& p_name,const StringName& p_type } Ref<Shader> Control::get_shader(const StringName& p_name,const StringName& p_type) const { - if (p_type==StringName()) { + if (p_type==StringName() || p_type=="") { const Ref<Shader>* sdr = data.shader_override.getptr(p_name); if (sdr) return *sdr; } - StringName type = p_type?p_type:get_type_name(); + StringName type = p_type?p_type:get_class_name(); // try with custom themes Control *theme_owner = data.theme_owner; while(theme_owner) { - if (theme_owner->data.theme->has_shader(p_name, type)) - return data.theme_owner->data.theme->get_shader(p_name, type ); + StringName class_name = type; + + while(class_name!=StringName()) { + if (theme_owner->data.theme->has_shader(p_name, class_name ) ) { + return theme_owner->data.theme->get_shader(p_name, class_name ); + } + + class_name = ClassDB::get_parent_class_nocheck(class_name); + } + Control *parent = theme_owner->get_parent()?theme_owner->get_parent()->cast_to<Control>():NULL; if (parent) @@ -830,21 +820,29 @@ Ref<Shader> Control::get_shader(const StringName& p_name,const StringName& p_typ Ref<StyleBox> Control::get_stylebox(const StringName& p_name,const StringName& p_type) const { - if (p_type==StringName()) { + if (p_type==StringName() || p_type=="") { const Ref<StyleBox>* style = data.style_override.getptr(p_name); if (style) return *style; } - StringName type = p_type?p_type:get_type_name(); + StringName type = p_type?p_type:get_class_name(); // try with custom themes Control *theme_owner = data.theme_owner; while(theme_owner) { - if (theme_owner->data.theme->has_stylebox(p_name, type ) ) - return data.theme_owner->data.theme->get_stylebox(p_name, type ); + StringName class_name = type; + + while(class_name!=StringName()) { + if (theme_owner->data.theme->has_stylebox(p_name, class_name ) ) { + return theme_owner->data.theme->get_stylebox(p_name, class_name ); + } + + class_name = ClassDB::get_parent_class_nocheck(class_name); + } + Control *parent = theme_owner->get_parent()?theme_owner->get_parent()->cast_to<Control>():NULL; if (parent) @@ -858,21 +856,29 @@ Ref<StyleBox> Control::get_stylebox(const StringName& p_name,const StringName& p } Ref<Font> Control::get_font(const StringName& p_name,const StringName& p_type) const { - if (p_type==StringName()) { + if (p_type==StringName() || p_type=="") { const Ref<Font>* font = data.font_override.getptr(p_name); if (font) return *font; } - StringName type = p_type?p_type:get_type_name(); + StringName type = p_type?p_type:get_class_name(); // try with custom themes Control *theme_owner = data.theme_owner; while(theme_owner) { - if (theme_owner->data.theme->has_font(p_name, type ) ) - return data.theme_owner->data.theme->get_font(p_name, type ); + StringName class_name = type; + + while(class_name!=StringName()) { + if (theme_owner->data.theme->has_font(p_name, class_name ) ) { + return theme_owner->data.theme->get_font(p_name, class_name ); + } + + class_name = ClassDB::get_parent_class_nocheck(class_name); + } + if (theme_owner->data.theme->get_default_theme_font().is_valid()) return theme_owner->data.theme->get_default_theme_font(); Control *parent = theme_owner->get_parent()?theme_owner->get_parent()->cast_to<Control>():NULL; @@ -889,20 +895,28 @@ Ref<Font> Control::get_font(const StringName& p_name,const StringName& p_type) c } Color Control::get_color(const StringName& p_name,const StringName& p_type) const { - if (p_type==StringName()) { + if (p_type==StringName() || p_type=="") { const Color* color = data.color_override.getptr(p_name); if (color) return *color; } - StringName type = p_type?p_type:get_type_name(); + StringName type = p_type?p_type:get_class_name(); // try with custom themes Control *theme_owner = data.theme_owner; while(theme_owner) { - if (theme_owner->data.theme->has_color(p_name, type ) ) - return data.theme_owner->data.theme->get_color(p_name, type ); + StringName class_name = type; + + while(class_name!=StringName()) { + if (theme_owner->data.theme->has_color(p_name, class_name ) ) { + return theme_owner->data.theme->get_color(p_name, class_name ); + } + + class_name = ClassDB::get_parent_class_nocheck(class_name); + } + Control *parent = theme_owner->get_parent()?theme_owner->get_parent()->cast_to<Control>():NULL; if (parent) @@ -918,20 +932,28 @@ Color Control::get_color(const StringName& p_name,const StringName& p_type) cons int Control::get_constant(const StringName& p_name,const StringName& p_type) const { - if (p_type==StringName()) { + if (p_type==StringName() || p_type=="") { const int* constant = data.constant_override.getptr(p_name); if (constant) return *constant; } - StringName type = p_type?p_type:get_type_name(); + StringName type = p_type?p_type:get_class_name(); // try with custom themes Control *theme_owner = data.theme_owner; while(theme_owner) { - if (theme_owner->data.theme->has_constant(p_name, type ) ) - return data.theme_owner->data.theme->get_constant(p_name, type ); + StringName class_name = type; + + while(class_name!=StringName()) { + if (theme_owner->data.theme->has_constant(p_name, class_name ) ) { + return theme_owner->data.theme->get_constant(p_name, class_name ); + } + + class_name = ClassDB::get_parent_class_nocheck(class_name); + } + Control *parent = theme_owner->get_parent()?theme_owner->get_parent()->cast_to<Control>():NULL; if (parent) @@ -946,24 +968,83 @@ int Control::get_constant(const StringName& p_name,const StringName& p_type) con } +bool Control::has_icon_override(const StringName& p_name) const { + + const Ref<Texture>* tex = data.icon_override.getptr(p_name); + if (tex) + return true; + else + return false; +} + +bool Control::has_shader_override(const StringName &p_name) const { + + const Ref<Shader>* sdr = data.shader_override.getptr(p_name); + if (sdr) + return true; + else + return false; +} + +bool Control::has_stylebox_override(const StringName& p_name) const { + + const Ref<StyleBox>* style = data.style_override.getptr(p_name); + if (style) + return true; + else + return false; +} + +bool Control::has_font_override(const StringName& p_name) const { + + const Ref<Font>* font = data.font_override.getptr(p_name); + if (font) + return true; + else + return false; +} + +bool Control::has_color_override(const StringName& p_name) const { + + const Color* color = data.color_override.getptr(p_name); + if (color) + return true; + else + return false; +} + +bool Control::has_constant_override(const StringName& p_name) const { + + const int* constant = data.constant_override.getptr(p_name); + if (constant) + return true; + else + return false; +} bool Control::has_icon(const StringName& p_name,const StringName& p_type) const { - if (p_type==StringName()) { - const Ref<Texture>* tex = data.icon_override.getptr(p_name); - if (tex) + if (p_type==StringName() || p_type=="") { + if (has_icon_override(p_name) == true) return true; } - StringName type = p_type?p_type:get_type_name(); + StringName type = p_type?p_type:get_class_name(); // try with custom themes Control *theme_owner = data.theme_owner; while(theme_owner) { - if (theme_owner->data.theme->has_icon(p_name, type ) ) - return true; + StringName class_name = type; + + while(class_name!=StringName()) { + if (theme_owner->data.theme->has_icon(p_name, class_name ) ) { + return true; + } + class_name = ClassDB::get_parent_class_nocheck(class_name); + } + Control *parent = theme_owner->get_parent()?theme_owner->get_parent()->cast_to<Control>():NULL; if (parent) @@ -977,23 +1058,29 @@ bool Control::has_icon(const StringName& p_name,const StringName& p_type) const } -bool Control::has_shader(const StringName &p_name, const StringName &p_type) const -{ - if (p_type==StringName()) { - const Ref<Shader>* sdr = data.shader_override.getptr(p_name); - if (sdr) +bool Control::has_shader(const StringName &p_name, const StringName &p_type) const { + + if (p_type==StringName() || p_type=="") { + if (has_shader_override(p_name)==true) return true; } - StringName type = p_type?p_type:get_type_name(); + StringName type = p_type?p_type:get_class_name(); // try with custom themes Control *theme_owner = data.theme_owner; while(theme_owner) { - if (theme_owner->data.theme->has_shader(p_name, type)) - return true; + StringName class_name = type; + + while(class_name!=StringName()) { + if (theme_owner->data.theme->has_shader(p_name, class_name ) ) { + return true; + } + class_name = ClassDB::get_parent_class_nocheck(class_name); + } + Control *parent = theme_owner->get_parent()?theme_owner->get_parent()->cast_to<Control>():NULL; if (parent) @@ -1008,22 +1095,27 @@ bool Control::has_shader(const StringName &p_name, const StringName &p_type) con } bool Control::has_stylebox(const StringName& p_name,const StringName& p_type) const { - if (p_type==StringName()) { - const Ref<StyleBox>* style = data.style_override.getptr(p_name); - - if (style) + if (p_type==StringName() || p_type=="") { + if (has_stylebox_override(p_name)==true) return true; } - StringName type = p_type?p_type:get_type_name(); + StringName type = p_type?p_type:get_class_name(); // try with custom themes Control *theme_owner = data.theme_owner; while(theme_owner) { - if (theme_owner->data.theme->has_stylebox(p_name, type ) ) - return true; + StringName class_name = type; + + while(class_name!=StringName()) { + if (theme_owner->data.theme->has_stylebox(p_name, class_name ) ) { + return true; + } + class_name = ClassDB::get_parent_class_nocheck(class_name); + } + Control *parent = theme_owner->get_parent()?theme_owner->get_parent()->cast_to<Control>():NULL; if (parent) @@ -1038,22 +1130,28 @@ bool Control::has_stylebox(const StringName& p_name,const StringName& p_type) co } bool Control::has_font(const StringName& p_name,const StringName& p_type) const { - if (p_type==StringName()) { - const Ref<Font>* font = data.font_override.getptr(p_name); - if (font) + if (p_type==StringName() || p_type=="") { + if (has_font_override(p_name)==true) return true; } - StringName type = p_type?p_type:get_type_name(); + StringName type = p_type?p_type:get_class_name(); // try with custom themes Control *theme_owner = data.theme_owner; while(theme_owner) { - if (theme_owner->data.theme->has_font(p_name, type ) ) - return true; + StringName class_name = type; + + while(class_name!=StringName()) { + if (theme_owner->data.theme->has_font(p_name, class_name ) ) { + return true; + } + class_name = ClassDB::get_parent_class_nocheck(class_name); + } + Control *parent = theme_owner->get_parent()?theme_owner->get_parent()->cast_to<Control>():NULL; if (parent) @@ -1066,23 +1164,30 @@ bool Control::has_font(const StringName& p_name,const StringName& p_type) const return Theme::get_default()->has_font( p_name, type ); } -bool Control::has_color(const StringName& p_name,const StringName& p_type) const { - if (p_type==StringName()) { - const Color* color = data.color_override.getptr(p_name); - if (color) +bool Control::has_color(const StringName& p_name, const StringName& p_type) const { + + if (p_type==StringName() || p_type=="") { + if (has_color_override(p_name)==true) return true; } - StringName type = p_type?p_type:get_type_name(); + StringName type = p_type?p_type:get_class_name(); // try with custom themes Control *theme_owner = data.theme_owner; while(theme_owner) { - if (theme_owner->data.theme->has_color(p_name, type ) ) - return true; + StringName class_name = type; + + while(class_name!=StringName()) { + if (theme_owner->data.theme->has_color(p_name, class_name ) ) { + return true; + } + class_name = ClassDB::get_parent_class_nocheck(class_name); + } + Control *parent = theme_owner->get_parent()?theme_owner->get_parent()->cast_to<Control>():NULL; if (parent) @@ -1098,23 +1203,28 @@ bool Control::has_color(const StringName& p_name,const StringName& p_type) const bool Control::has_constant(const StringName& p_name,const StringName& p_type) const { - if (p_type==StringName()) { - - const int* constant = data.constant_override.getptr(p_name); - if (constant) + if (p_type==StringName() || p_type=="") { + if (has_constant_override(p_name) == true) return true; } - StringName type = p_type?p_type:get_type_name(); + StringName type = p_type?p_type:get_class_name(); // try with custom themes Control *theme_owner = data.theme_owner; while(theme_owner) { - if (theme_owner->data.theme->has_constant(p_name, type ) ) - return true; + StringName class_name = type; + + while(class_name!=StringName()) { + if (theme_owner->data.theme->has_constant(p_name, class_name ) ) { + return true; + } + class_name = ClassDB::get_parent_class_nocheck(class_name); + } + Control *parent = theme_owner->get_parent()?theme_owner->get_parent()->cast_to<Control>():NULL; if (parent) @@ -1166,14 +1276,10 @@ void Control::_size_changed() { margin_pos[i]=area-data.margin[i]; } break; - case ANCHOR_RATIO: { + case ANCHOR_CENTER: { - margin_pos[i]=area*data.margin[i]; + margin_pos[i]=(area/2)-data.margin[i]; } break; - case ANCHOR_CENTER: { - - margin_pos[i]=(area/2)-data.margin[i]; - } break; } } @@ -1184,17 +1290,24 @@ void Control::_size_changed() { new_size_cache.x = MAX( minimum_size.x, new_size_cache.x ); new_size_cache.y = MAX( minimum_size.y, new_size_cache.y ); - - if (new_pos_cache == data.pos_cache && new_size_cache == data.size_cache) - return; // did not change, don't emit signal + bool pos_changed = new_pos_cache != data.pos_cache; + bool size_changed = new_size_cache != data.size_cache; data.pos_cache=new_pos_cache; data.size_cache=new_size_cache; - notification(NOTIFICATION_RESIZED); - item_rect_changed(); - _change_notify_margins(); - _notify_transform(); + if (size_changed) { + notification(NOTIFICATION_RESIZED); + } + if (pos_changed || size_changed) { + item_rect_changed(size_changed); + _change_notify_margins(); + _notify_transform(); + } + + if (pos_changed && !size_changed) { + _update_canvas_item_transform(); //move because it won't be updated + } } float Control::_get_parent_range(int p_idx) const { @@ -1235,12 +1348,9 @@ float Control::_s2a(float p_val, AnchorType p_anchor,float p_range) const { case ANCHOR_END: { return p_range-p_val; } break; - case ANCHOR_RATIO: { - return p_val/p_range; + case ANCHOR_CENTER: { + return (p_range/2)-p_val; } break; - case ANCHOR_CENTER: { - return (p_range/2)-p_val; - } break; } return 0; @@ -1257,11 +1367,8 @@ float Control::_a2s(float p_val, AnchorType p_anchor,float p_range) const { case ANCHOR_END: { return Math::floor(p_range-p_val); } break; - case ANCHOR_RATIO: { - return Math::floor(p_range*p_val); - } break; case ANCHOR_CENTER: { - return Math::floor((p_range/2)-p_val); + return Math::floor((p_range/2)-p_val); } break; } return 0; @@ -1288,7 +1395,7 @@ void Control::set_anchor(Margin p_margin,AnchorType p_anchor, bool p_keep_margin void Control::_set_anchor(Margin p_margin,AnchorType p_anchor) { #ifdef TOOLS_ENABLED if (is_inside_tree() && get_tree()->is_editor_hint()) { - set_anchor(p_margin, p_anchor, EDITOR_DEF("2d_editor/keep_margins_when_changing_anchors", false)); + set_anchor(p_margin, p_anchor, EDITOR_DEF("editors/2d/keep_margins_when_changing_anchors", false)); } else { set_anchor(p_margin, p_anchor, false); } @@ -1368,7 +1475,7 @@ Point2 Control::get_global_pos() const { void Control::set_global_pos(const Point2& p_point) { - Matrix32 inv; + Transform2D inv; if (data.parent_canvas_item) { @@ -1505,7 +1612,15 @@ void Control::add_style_override(const StringName& p_name, const Ref<StyleBox>& void Control::add_font_override(const StringName& p_name, const Ref<Font>& p_font) { ERR_FAIL_COND(p_font.is_null()); + if (data.font_override.has(p_name)) { + _unref_font(data.font_override[p_name]); + } data.font_override[p_name]=p_font; + + if (p_font.is_valid()) { + _ref_font(p_font); + } + notification(NOTIFICATION_THEME_CHANGED); update(); } @@ -1549,7 +1664,7 @@ static Control *_next_control(Control *p_from) { for(int i=(next+1);i<parent->get_child_count();i++) { Control *c = parent->get_child(i)->cast_to<Control>(); - if (!c || !c->is_visible() || c->is_set_as_toplevel()) + if (!c || !c->is_visible_in_tree() || c->is_set_as_toplevel()) continue; return c; @@ -1574,7 +1689,7 @@ Control *Control::find_next_valid_focus() const { for(int i=0;i<from->get_child_count();i++) { Control *c = from->get_child(i)->cast_to<Control>(); - if (!c || !c->is_visible() || c->is_set_as_toplevel()) { + if (!c || !c->is_visible_in_tree() || c->is_set_as_toplevel()) { continue; } @@ -1618,11 +1733,11 @@ Control *Control::find_next_valid_focus() const { if (next_child==this) // no next control-> return (get_focus_mode()==FOCUS_ALL)?next_child:NULL; - - if (next_child->get_focus_mode()==FOCUS_ALL) - return next_child; - - from = next_child; + if (next_child) { + if (next_child->get_focus_mode()==FOCUS_ALL) + return next_child; + from = next_child; + } else break; } return NULL; @@ -1640,7 +1755,7 @@ static Control *_prev_control(Control *p_from) { for(int i=p_from->get_child_count()-1;i>=0;i--) { Control *c = p_from->get_child(i)->cast_to<Control>(); - if (!c || !c->is_visible() || c->is_set_as_toplevel()) + if (!c || !c->is_visible_in_tree() || c->is_set_as_toplevel()) continue; child=c; @@ -1680,7 +1795,7 @@ Control *Control::find_prev_valid_focus() const { Control *c = from->get_parent()->get_child(i)->cast_to<Control>(); - if (!c || !c->is_visible() || c->is_set_as_toplevel()) { + if (!c || !c->is_visible_in_tree() || c->is_set_as_toplevel()) { continue; } @@ -1764,7 +1879,7 @@ void Control::show_modal(bool p_exclusive) { ERR_FAIL_COND(!is_inside_tree()); ERR_FAIL_COND(!data.SI); - if (is_visible()) + if (is_visible_in_tree()) hide(); ERR_FAIL_COND( data.MI!=NULL ); @@ -1772,6 +1887,7 @@ void Control::show_modal(bool p_exclusive) { raise(); data.modal_exclusive=p_exclusive; data.MI=get_viewport()->_gui_show_modal(this); + data.modal_frame=Engine::get_singleton()->get_frames_drawn(); } @@ -1794,38 +1910,68 @@ void Control::_modal_stack_remove() { } -void Control::_propagate_theme_changed(Control *p_owner) { +void Control::_propagate_theme_changed(CanvasItem *p_at,Control *p_owner,bool p_assign) { + + Control *c = p_at->cast_to<Control>(); + + if (c && c!=p_owner && c->data.theme.is_valid()) // has a theme, this can't be propagated + return; + + for(int i=0;i<p_at->get_child_count();i++) { + + CanvasItem *child = p_at->get_child(i)->cast_to<CanvasItem>(); + if (child) { + _propagate_theme_changed(child,p_owner,p_assign); + } + + } - for(int i=0;i<get_child_count();i++) { - Control *child = get_child(i)->cast_to<Control>(); - if (child && child->data.theme.is_null()) //has no theme, propagate - child->_propagate_theme_changed(p_owner); + if (c) { + + if (p_assign) { + c->data.theme_owner=p_owner; + } + c->notification(NOTIFICATION_THEME_CHANGED); + c->update(); } +} - data.theme_owner=p_owner; - _notification(NOTIFICATION_THEME_CHANGED); - update(); + +void Control::_theme_changed() { + + _propagate_theme_changed(this,this,false); } void Control::set_theme(const Ref<Theme>& p_theme) { + + if (data.theme==p_theme) + return; + + if (data.theme.is_valid()) { + data.theme->disconnect("changed",this,"_theme_changed"); + } + data.theme=p_theme; if (!p_theme.is_null()) { - _propagate_theme_changed(this); + _propagate_theme_changed(this,this); } else { Control *parent = get_parent()?get_parent()->cast_to<Control>():NULL; if (parent && parent->data.theme_owner) { - _propagate_theme_changed(parent->data.theme_owner); + _propagate_theme_changed(this,parent->data.theme_owner); } else { - _propagate_theme_changed(NULL); + _propagate_theme_changed(this,NULL); } } + if (data.theme.is_valid()) { + data.theme->connect("changed",this,"_theme_changed"); + } } @@ -1865,9 +2011,9 @@ Control::CursorShape Control::get_cursor_shape(const Point2& p_pos) const { return data.default_cursor; } -Matrix32 Control::get_transform() const { +Transform2D Control::get_transform() const { - Matrix32 xform=Matrix32(data.rotation,get_pos()); + Transform2D xform=Transform2D(data.rotation,get_pos()); xform.scale_basis(data.scale); return xform; } @@ -1911,7 +2057,7 @@ Control *Control::_get_focus_neighbour(Margin p_margin,int p_count) { return NULL; } bool valid=true; - if (c->is_hidden()) + if (!c->is_visible()) valid=false; if (c->get_focus_mode()==FOCUS_NONE) valid=false; @@ -1928,7 +2074,7 @@ Control *Control::_get_focus_neighbour(Margin p_margin,int p_count) { Point2 points[4]; - Matrix32 xform = get_global_transform(); + Transform2D xform = get_global_transform(); Rect2 rect = get_item_rect(); points[0]=xform.xform(rect.pos); @@ -1984,11 +2130,11 @@ void Control::_window_find_focus_neighbour(const Vector2& p_dir, Node *p_at,cons Control *c = p_at->cast_to<Control>(); - if (c && c !=this && c->get_focus_mode()==FOCUS_ALL && c->is_visible()) { + if (c && c !=this && c->get_focus_mode()==FOCUS_ALL && c->is_visible_in_tree()) { Point2 points[4]; - Matrix32 xform = c->get_global_transform(); + Transform2D xform = c->get_global_transform(); Rect2 rect = c->get_item_rect(); points[0]=xform.xform(rect.pos); @@ -2087,7 +2233,7 @@ void Control::grab_click_focus() { void Control::minimum_size_changed() { - if (!is_inside_tree()) + if (!is_inside_tree() || data.block_minimum_size_adjust) return; if (data.pending_min_size_update) @@ -2108,25 +2254,17 @@ int Control::get_v_size_flags() const{ return data.v_size_flags; } -void Control::set_ignore_mouse(bool p_ignore) { +void Control::set_mouse_filter(MouseFilter p_filter) { - data.ignore_mouse=p_ignore; + ERR_FAIL_INDEX(p_filter,3); + data.mouse_filter=p_filter; } -bool Control::is_ignoring_mouse() const { +Control::MouseFilter Control::get_mouse_filter() const{ - return data.ignore_mouse; + return data.mouse_filter; } -void Control::set_stop_mouse(bool p_stop) { - - data.stop_mouse=p_stop; -} - -bool Control::is_stopping_mouse() const { - - return data.stop_mouse; -} Control *Control::get_focus_owner() const { @@ -2161,6 +2299,7 @@ void Control::set_rotation(float p_radians) { data.rotation=p_radians; update(); _notify_transform(); + _change_notify("rect/rotation"); } float Control::get_rotation() const{ @@ -2186,6 +2325,33 @@ float Control::_get_rotation_deg() const { WARN_PRINT("Deprecated method Control._get_rotation_deg(): This method was renamed to get_rotation_deg. Please adapt your code accordingly, as the old method will be obsoleted."); return get_rotation_deg(); } +//needed to update the control if the font changes.. +void Control::_ref_font( Ref<Font> p_sc) { + + if (!data.font_refcount.has(p_sc)) { + data.font_refcount[p_sc]=1; + p_sc->connect("changed",this,"_font_changed"); + } else { + data.font_refcount[p_sc]+=1; + } +} + +void Control::_unref_font(Ref<Font> p_sc) { + + ERR_FAIL_COND(!data.font_refcount.has(p_sc)); + data.font_refcount[p_sc]--; + if (data.font_refcount[p_sc]==0) { + p_sc->disconnect("changed",this,"_font_changed"); + data.font_refcount.erase(p_sc); + } +} + +void Control::_font_changed(){ + + update(); + notification(NOTIFICATION_THEME_CHANGED); + minimum_size_changed(); //fonts affect minimum size pretty much almost always +} void Control::set_scale(const Vector2& p_scale){ @@ -2219,144 +2385,238 @@ Control *Control::get_root_parent_control() const { return const_cast<Control*>(root); } +void Control::set_block_minimum_size_adjust(bool p_block) { + data.block_minimum_size_adjust=p_block; +} + +bool Control::is_minimum_size_adjust_blocked() const { + + return data.block_minimum_size_adjust; +} + + +void Control::set_disable_visibility_clip(bool p_ignore) { + + data.disable_visibility_clip=p_ignore; + update(); +} + +bool Control::is_visibility_clip_disabled() const { + + return data.disable_visibility_clip; +} + +void Control::get_argument_options(const StringName& p_function,int p_idx,List<String>*r_options) const { + + Node::get_argument_options(p_function,p_idx,r_options); + + if (p_idx==0) { + List<StringName> sn; + String pf = p_function; + if (pf=="add_color_override" || pf=="has_color" || pf=="has_color_override" || pf=="get_color") { + Theme::get_default()->get_color_list(get_class(),&sn); + } else if (pf=="add_style_override" || pf=="has_style" || pf=="has_style_override" || pf=="get_style") { + Theme::get_default()->get_stylebox_list(get_class(),&sn); + } else if (pf=="add_font_override" || pf=="has_font" || pf=="has_font_override" || pf=="get_font") { + Theme::get_default()->get_font_list(get_class(),&sn); + } else if (pf=="add_constant_override" || pf=="has_constant" || pf=="has_constant_override" || pf=="get_constant") { + Theme::get_default()->get_constant_list(get_class(),&sn); + } else if (pf=="add_color_override" || pf=="has_color" || pf=="has_color_override" || pf=="get_color") { + Theme::get_default()->get_color_list(get_class(),&sn); + } + + sn.sort_custom<StringName::AlphCompare>(); + for (List<StringName>::Element *E=sn.front();E;E=E->next()) { + r_options->push_back("\""+E->get()+"\""); + } + } + + +} +void Control::set_clip_contents(bool p_clip) { + + data.clip_contents=p_clip; + update(); +} + +bool Control::is_clipping_contents() { + + return data.clip_contents; +} void Control::_bind_methods() { -// ObjectTypeDB::bind_method(_MD("_window_resize_event"),&Control::_window_resize_event); - ObjectTypeDB::bind_method(_MD("_size_changed"),&Control::_size_changed); - ObjectTypeDB::bind_method(_MD("_update_minimum_size"),&Control::_update_minimum_size); - - ObjectTypeDB::bind_method(_MD("accept_event"),&Control::accept_event); - ObjectTypeDB::bind_method(_MD("get_minimum_size"),&Control::get_minimum_size); - ObjectTypeDB::bind_method(_MD("get_combined_minimum_size"),&Control::get_combined_minimum_size); - ObjectTypeDB::bind_method(_MD("set_anchor","margin","anchor_mode","keep_margin"),&Control::set_anchor,DEFVAL(false)); - ObjectTypeDB::bind_method(_MD("_set_anchor","margin","anchor_mode"),&Control::_set_anchor); - ObjectTypeDB::bind_method(_MD("get_anchor","margin"),&Control::get_anchor); - ObjectTypeDB::bind_method(_MD("set_margin","margin","offset"),&Control::set_margin); - ObjectTypeDB::bind_method(_MD("set_anchor_and_margin","margin","anchor_mode","offset"),&Control::set_anchor_and_margin); - ObjectTypeDB::bind_method(_MD("set_begin","pos"),&Control::set_begin); - ObjectTypeDB::bind_method(_MD("set_end","pos"),&Control::set_end); - ObjectTypeDB::bind_method(_MD("set_pos","pos"),&Control::set_pos); - ObjectTypeDB::bind_method(_MD("set_size","size"),&Control::set_size); - ObjectTypeDB::bind_method(_MD("set_custom_minimum_size","size"),&Control::set_custom_minimum_size); - ObjectTypeDB::bind_method(_MD("set_global_pos","pos"),&Control::set_global_pos); - ObjectTypeDB::bind_method(_MD("set_rotation","radians"),&Control::set_rotation); - ObjectTypeDB::bind_method(_MD("set_rotation_deg","degrees"),&Control::set_rotation_deg); + //ClassDB::bind_method(_MD("_window_resize_event"),&Control::_window_resize_event); + ClassDB::bind_method(_MD("_size_changed"),&Control::_size_changed); + ClassDB::bind_method(_MD("_update_minimum_size"),&Control::_update_minimum_size); + + ClassDB::bind_method(_MD("accept_event"),&Control::accept_event); + ClassDB::bind_method(_MD("get_minimum_size"),&Control::get_minimum_size); + ClassDB::bind_method(_MD("get_combined_minimum_size"),&Control::get_combined_minimum_size); + ClassDB::bind_method(_MD("set_anchor","margin","anchor_mode","keep_margin"),&Control::set_anchor,DEFVAL(false)); + ClassDB::bind_method(_MD("_set_anchor","margin","anchor_mode"),&Control::_set_anchor); + ClassDB::bind_method(_MD("get_anchor","margin"),&Control::get_anchor); + ClassDB::bind_method(_MD("set_margin","margin","offset"),&Control::set_margin); + ClassDB::bind_method(_MD("set_anchor_and_margin","margin","anchor_mode","offset"),&Control::set_anchor_and_margin); + ClassDB::bind_method(_MD("set_begin","pos"),&Control::set_begin); + ClassDB::bind_method(_MD("set_end","pos"),&Control::set_end); + ClassDB::bind_method(_MD("set_pos","pos"),&Control::set_pos); + ClassDB::bind_method(_MD("set_size","size"),&Control::set_size); + ClassDB::bind_method(_MD("set_custom_minimum_size","size"),&Control::set_custom_minimum_size); + ClassDB::bind_method(_MD("set_global_pos","pos"),&Control::set_global_pos); + ClassDB::bind_method(_MD("set_rotation","radians"),&Control::set_rotation); + ClassDB::bind_method(_MD("set_rotation_deg","degrees"),&Control::set_rotation_deg); // TODO: Obsolete this method (old name) properly (GH-4397) - ObjectTypeDB::bind_method(_MD("_set_rotation_deg","degrees"),&Control::_set_rotation_deg); - ObjectTypeDB::bind_method(_MD("set_scale","scale"),&Control::set_scale); - ObjectTypeDB::bind_method(_MD("get_margin","margin"),&Control::get_margin); - ObjectTypeDB::bind_method(_MD("get_begin"),&Control::get_begin); - ObjectTypeDB::bind_method(_MD("get_end"),&Control::get_end); - ObjectTypeDB::bind_method(_MD("get_pos"),&Control::get_pos); - ObjectTypeDB::bind_method(_MD("get_size"),&Control::get_size); - ObjectTypeDB::bind_method(_MD("get_rotation"),&Control::get_rotation); - ObjectTypeDB::bind_method(_MD("get_rotation_deg"),&Control::get_rotation_deg); + ClassDB::bind_method(_MD("_set_rotation_deg","degrees"),&Control::_set_rotation_deg); + ClassDB::bind_method(_MD("set_scale","scale"),&Control::set_scale); + ClassDB::bind_method(_MD("get_margin","margin"),&Control::get_margin); + ClassDB::bind_method(_MD("get_begin"),&Control::get_begin); + ClassDB::bind_method(_MD("get_end"),&Control::get_end); + ClassDB::bind_method(_MD("get_pos"),&Control::get_pos); + ClassDB::bind_method(_MD("get_size"),&Control::get_size); + ClassDB::bind_method(_MD("get_rotation"),&Control::get_rotation); + ClassDB::bind_method(_MD("get_rotation_deg"),&Control::get_rotation_deg); // TODO: Obsolete this method (old name) properly (GH-4397) - ObjectTypeDB::bind_method(_MD("_get_rotation_deg"),&Control::_get_rotation_deg); - ObjectTypeDB::bind_method(_MD("get_scale"),&Control::get_scale); - ObjectTypeDB::bind_method(_MD("get_custom_minimum_size"),&Control::get_custom_minimum_size); - ObjectTypeDB::bind_method(_MD("get_parent_area_size"),&Control::get_size); - ObjectTypeDB::bind_method(_MD("get_global_pos"),&Control::get_global_pos); - ObjectTypeDB::bind_method(_MD("get_rect"),&Control::get_rect); - ObjectTypeDB::bind_method(_MD("get_global_rect"),&Control::get_global_rect); - ObjectTypeDB::bind_method(_MD("set_area_as_parent_rect","margin"),&Control::set_area_as_parent_rect,DEFVAL(0)); - ObjectTypeDB::bind_method(_MD("show_modal","exclusive"),&Control::show_modal,DEFVAL(false)); - ObjectTypeDB::bind_method(_MD("set_focus_mode","mode"),&Control::set_focus_mode); - ObjectTypeDB::bind_method(_MD("has_focus"),&Control::has_focus); - ObjectTypeDB::bind_method(_MD("grab_focus"),&Control::grab_focus); - ObjectTypeDB::bind_method(_MD("release_focus"),&Control::release_focus); - ObjectTypeDB::bind_method(_MD("get_focus_owner:Control"),&Control::get_focus_owner); + ClassDB::bind_method(_MD("_get_rotation_deg"),&Control::_get_rotation_deg); + ClassDB::bind_method(_MD("get_scale"),&Control::get_scale); + ClassDB::bind_method(_MD("get_custom_minimum_size"),&Control::get_custom_minimum_size); + ClassDB::bind_method(_MD("get_parent_area_size"),&Control::get_size); + ClassDB::bind_method(_MD("get_global_pos"),&Control::get_global_pos); + ClassDB::bind_method(_MD("get_rect"),&Control::get_rect); + ClassDB::bind_method(_MD("get_global_rect"),&Control::get_global_rect); + ClassDB::bind_method(_MD("set_area_as_parent_rect","margin"),&Control::set_area_as_parent_rect,DEFVAL(0)); + ClassDB::bind_method(_MD("show_modal","exclusive"),&Control::show_modal,DEFVAL(false)); + ClassDB::bind_method(_MD("set_focus_mode","mode"),&Control::set_focus_mode); + ClassDB::bind_method(_MD("get_focus_mode"),&Control::get_focus_mode); + ClassDB::bind_method(_MD("has_focus"),&Control::has_focus); + ClassDB::bind_method(_MD("grab_focus"),&Control::grab_focus); + ClassDB::bind_method(_MD("release_focus"),&Control::release_focus); + ClassDB::bind_method(_MD("get_focus_owner:Control"),&Control::get_focus_owner); + + ClassDB::bind_method(_MD("set_h_size_flags","flags"),&Control::set_h_size_flags); + ClassDB::bind_method(_MD("get_h_size_flags"),&Control::get_h_size_flags); + + ClassDB::bind_method(_MD("set_stretch_ratio","ratio"),&Control::set_stretch_ratio); + ClassDB::bind_method(_MD("get_stretch_ratio"),&Control::get_stretch_ratio); + + ClassDB::bind_method(_MD("set_v_size_flags","flags"),&Control::set_v_size_flags); + ClassDB::bind_method(_MD("get_v_size_flags"),&Control::get_v_size_flags); + + ClassDB::bind_method(_MD("set_theme","theme:Theme"),&Control::set_theme); + ClassDB::bind_method(_MD("get_theme:Theme"),&Control::get_theme); - ObjectTypeDB::bind_method(_MD("set_h_size_flags","flags"),&Control::set_h_size_flags); - ObjectTypeDB::bind_method(_MD("get_h_size_flags"),&Control::get_h_size_flags); + ClassDB::bind_method(_MD("add_icon_override","name","texture:Texture"),&Control::add_icon_override); + ClassDB::bind_method(_MD("add_shader_override","name","shader:Shader"),&Control::add_shader_override); + ClassDB::bind_method(_MD("add_style_override","name","stylebox:StyleBox"),&Control::add_style_override); + ClassDB::bind_method(_MD("add_font_override","name","font:Font"),&Control::add_font_override); + ClassDB::bind_method(_MD("add_color_override","name","color"),&Control::add_color_override); + ClassDB::bind_method(_MD("add_constant_override","name","constant"),&Control::add_constant_override); - ObjectTypeDB::bind_method(_MD("set_stretch_ratio","ratio"),&Control::set_stretch_ratio); - ObjectTypeDB::bind_method(_MD("get_stretch_ratio"),&Control::get_stretch_ratio); + ClassDB::bind_method(_MD("get_icon:Texture","name","type"),&Control::get_icon,DEFVAL("")); + ClassDB::bind_method(_MD("get_stylebox:StyleBox","name","type"),&Control::get_stylebox,DEFVAL("")); + ClassDB::bind_method(_MD("get_font:Font","name","type"),&Control::get_font,DEFVAL("")); + ClassDB::bind_method(_MD("get_color","name","type"),&Control::get_color,DEFVAL("")); + ClassDB::bind_method(_MD("get_constant","name","type"),&Control::get_constant,DEFVAL("")); - ObjectTypeDB::bind_method(_MD("set_v_size_flags","flags"),&Control::set_v_size_flags); - ObjectTypeDB::bind_method(_MD("get_v_size_flags"),&Control::get_v_size_flags); + ClassDB::bind_method(_MD("has_icon_override", "name"), &Control::has_icon_override); + ClassDB::bind_method(_MD("has_stylebox_override", "name"), &Control::has_stylebox_override); + ClassDB::bind_method(_MD("has_font_override", "name"), &Control::has_font_override); + ClassDB::bind_method(_MD("has_color_override", "name"), &Control::has_color_override); + ClassDB::bind_method(_MD("has_constant_override", "name"), &Control::has_constant_override); - ObjectTypeDB::bind_method(_MD("set_theme","theme:Theme"),&Control::set_theme); - ObjectTypeDB::bind_method(_MD("get_theme:Theme"),&Control::get_theme); + ClassDB::bind_method(_MD("has_icon", "name", "type"), &Control::has_icon, DEFVAL("")); + ClassDB::bind_method(_MD("has_stylebox", "name", "type"), &Control::has_stylebox, DEFVAL("")); + ClassDB::bind_method(_MD("has_font", "name", "type"), &Control::has_font, DEFVAL("")); + ClassDB::bind_method(_MD("has_color", "name", "type"), &Control::has_color, DEFVAL("")); + ClassDB::bind_method(_MD("has_constant", "name", "type"), &Control::has_constant, DEFVAL("")); - ObjectTypeDB::bind_method(_MD("add_icon_override","name","texture:Texture"),&Control::add_icon_override); - ObjectTypeDB::bind_method(_MD("add_shader_override","name","shader:Shader"),&Control::add_shader_override); - ObjectTypeDB::bind_method(_MD("add_style_override","name","stylebox:StyleBox"),&Control::add_style_override); - ObjectTypeDB::bind_method(_MD("add_font_override","name","font:Font"),&Control::add_font_override); - ObjectTypeDB::bind_method(_MD("add_color_override","name","color"),&Control::add_color_override); - ObjectTypeDB::bind_method(_MD("add_constant_override","name","constant"),&Control::add_constant_override); + ClassDB::bind_method(_MD("get_parent_control:Control"),&Control::get_parent_control); - ObjectTypeDB::bind_method(_MD("get_icon:Texture","name","type"),&Control::get_icon,DEFVAL("")); - ObjectTypeDB::bind_method(_MD("get_stylebox:StyleBox","name","type"),&Control::get_stylebox,DEFVAL("")); - ObjectTypeDB::bind_method(_MD("get_font:Font","name","type"),&Control::get_font,DEFVAL("")); - ObjectTypeDB::bind_method(_MD("get_color","name","type"),&Control::get_color,DEFVAL("")); - ObjectTypeDB::bind_method(_MD("get_constant","name","type"),&Control::get_constant,DEFVAL("")); + ClassDB::bind_method(_MD("set_tooltip","tooltip"),&Control::set_tooltip); + ClassDB::bind_method(_MD("get_tooltip","atpos"),&Control::get_tooltip,DEFVAL(Point2())); + ClassDB::bind_method(_MD("_get_tooltip"),&Control::_get_tooltip); + ClassDB::bind_method(_MD("set_default_cursor_shape","shape"),&Control::set_default_cursor_shape); + ClassDB::bind_method(_MD("get_default_cursor_shape"),&Control::get_default_cursor_shape); + ClassDB::bind_method(_MD("get_cursor_shape","pos"),&Control::get_cursor_shape,DEFVAL(Point2())); - ObjectTypeDB::bind_method(_MD("get_parent_control:Control"),&Control::get_parent_control); + ClassDB::bind_method(_MD("set_focus_neighbour","margin","neighbour"),&Control::set_focus_neighbour); + ClassDB::bind_method(_MD("get_focus_neighbour","margin"),&Control::get_focus_neighbour); - ObjectTypeDB::bind_method(_MD("set_tooltip","tooltip"),&Control::set_tooltip); - ObjectTypeDB::bind_method(_MD("get_tooltip","atpos"),&Control::get_tooltip,DEFVAL(Point2())); - ObjectTypeDB::bind_method(_MD("_get_tooltip"),&Control::_get_tooltip); + ClassDB::bind_method(_MD("force_drag","data","preview"),&Control::force_drag); - ObjectTypeDB::bind_method(_MD("set_default_cursor_shape","shape"),&Control::set_default_cursor_shape); - ObjectTypeDB::bind_method(_MD("get_default_cursor_shape"),&Control::get_default_cursor_shape); - ObjectTypeDB::bind_method(_MD("get_cursor_shape","pos"),&Control::get_cursor_shape,DEFVAL(Point2())); + ClassDB::bind_method(_MD("set_mouse_filter","filter"),&Control::set_mouse_filter); + ClassDB::bind_method(_MD("get_mouse_filter"),&Control::get_mouse_filter); - ObjectTypeDB::bind_method(_MD("set_focus_neighbour","margin","neighbour"),&Control::set_focus_neighbour); - ObjectTypeDB::bind_method(_MD("get_focus_neighbour","margin"),&Control::get_focus_neighbour); + ClassDB::bind_method(_MD("set_clip_contents","enable"),&Control::set_clip_contents); + ClassDB::bind_method(_MD("is_clipping_contents"),&Control::is_clipping_contents); - ObjectTypeDB::bind_method(_MD("set_ignore_mouse","ignore"),&Control::set_ignore_mouse); - ObjectTypeDB::bind_method(_MD("is_ignoring_mouse"),&Control::is_ignoring_mouse); + ClassDB::bind_method(_MD("grab_click_focus"),&Control::grab_click_focus); - ObjectTypeDB::bind_method(_MD("force_drag","data","preview"),&Control::force_drag); + ClassDB::bind_method(_MD("set_drag_forwarding","target:Control"),&Control::set_drag_forwarding); + ClassDB::bind_method(_MD("set_drag_preview","control:Control"),&Control::set_drag_preview); - ObjectTypeDB::bind_method(_MD("set_stop_mouse","stop"),&Control::set_stop_mouse); - ObjectTypeDB::bind_method(_MD("is_stopping_mouse"),&Control::is_stopping_mouse); + ClassDB::bind_method(_MD("warp_mouse","to_pos"),&Control::warp_mouse); - ObjectTypeDB::bind_method(_MD("grab_click_focus"),&Control::grab_click_focus); + ClassDB::bind_method(_MD("minimum_size_changed"), &Control::minimum_size_changed); - ObjectTypeDB::bind_method(_MD("set_drag_forwarding","target:Control"),&Control::set_drag_forwarding); - ObjectTypeDB::bind_method(_MD("set_drag_preview","control:Control"),&Control::set_drag_preview); + ClassDB::bind_method(_MD("_theme_changed"), &Control::_theme_changed); - ObjectTypeDB::bind_method(_MD("warp_mouse","to_pos"),&Control::warp_mouse); - BIND_VMETHOD(MethodInfo("_input_event",PropertyInfo(Variant::INPUT_EVENT,"event"))); + ClassDB::bind_method(_MD("_font_changed"), &Control::_font_changed); + + BIND_VMETHOD(MethodInfo("_gui_input",PropertyInfo(Variant::INPUT_EVENT,"event"))); BIND_VMETHOD(MethodInfo(Variant::VECTOR2,"get_minimum_size")); BIND_VMETHOD(MethodInfo(Variant::OBJECT,"get_drag_data",PropertyInfo(Variant::VECTOR2,"pos"))); BIND_VMETHOD(MethodInfo(Variant::BOOL,"can_drop_data",PropertyInfo(Variant::VECTOR2,"pos"),PropertyInfo(Variant::NIL,"data"))); BIND_VMETHOD(MethodInfo("drop_data",PropertyInfo(Variant::VECTOR2,"pos"),PropertyInfo(Variant::NIL,"data"))); - ADD_PROPERTYINZ( PropertyInfo(Variant::INT,"anchor/left", PROPERTY_HINT_ENUM, "Begin,End,Ratio,Center"), _SCS("_set_anchor"),_SCS("get_anchor"), MARGIN_LEFT ); - ADD_PROPERTYINZ( PropertyInfo(Variant::INT,"anchor/top", PROPERTY_HINT_ENUM, "Begin,End,Ratio,Center"), _SCS("_set_anchor"),_SCS("get_anchor"), MARGIN_TOP ); - ADD_PROPERTYINZ( PropertyInfo(Variant::INT,"anchor/right", PROPERTY_HINT_ENUM, "Begin,End,Ratio,Center"), _SCS("_set_anchor"),_SCS("get_anchor"), MARGIN_RIGHT ); - ADD_PROPERTYINZ( PropertyInfo(Variant::INT,"anchor/bottom", PROPERTY_HINT_ENUM, "Begin,End,Ratio,Center"), _SCS("_set_anchor"),_SCS("get_anchor"), MARGIN_BOTTOM ); - - ADD_PROPERTYNZ( PropertyInfo(Variant::VECTOR2,"rect/pos", PROPERTY_HINT_NONE, "",PROPERTY_USAGE_EDITOR), _SCS("set_pos"),_SCS("get_pos") ); - 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::REAL,"rect/rotation",PROPERTY_HINT_RANGE,"-1080,1080,0.01"), _SCS("set_rotation_deg"),_SCS("get_rotation_deg") ); - ADD_PROPERTYNO( PropertyInfo(Variant::VECTOR2,"rect/scale"), _SCS("set_scale"),_SCS("get_scale") ); - ADD_PROPERTYNZ( PropertyInfo(Variant::STRING,"hint/tooltip", PROPERTY_HINT_MULTILINE_TEXT), _SCS("set_tooltip"),_SCS("_get_tooltip") ); - 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_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") ); + ADD_GROUP("Anchor","anchor_"); + ADD_PROPERTYINZ( PropertyInfo(Variant::INT,"anchor_left", PROPERTY_HINT_ENUM, "Begin,End,Center"), _SCS("_set_anchor"),_SCS("get_anchor"), MARGIN_LEFT ); + ADD_PROPERTYINZ( PropertyInfo(Variant::INT,"anchor_top", PROPERTY_HINT_ENUM, "Begin,End,Center"), _SCS("_set_anchor"),_SCS("get_anchor"), MARGIN_TOP ); + ADD_PROPERTYINZ( PropertyInfo(Variant::INT,"anchor_right", PROPERTY_HINT_ENUM, "Begin,End,Center"), _SCS("_set_anchor"),_SCS("get_anchor"), MARGIN_RIGHT ); + ADD_PROPERTYINZ( PropertyInfo(Variant::INT,"anchor_bottom", PROPERTY_HINT_ENUM, "Begin,End,Center"), _SCS("_set_anchor"),_SCS("get_anchor"), MARGIN_BOTTOM ); + + ADD_GROUP("Margin","margin_"); + ADD_PROPERTYINZ( PropertyInfo(Variant::INT,"margin_left", PROPERTY_HINT_RANGE, "-4096,4096"), _SCS("set_margin"),_SCS("get_margin"),MARGIN_LEFT ); + ADD_PROPERTYINZ( PropertyInfo(Variant::INT,"margin_top", PROPERTY_HINT_RANGE, "-4096,4096"), _SCS("set_margin"),_SCS("get_margin"),MARGIN_TOP ); + ADD_PROPERTYINZ( PropertyInfo(Variant::INT,"margin_right", PROPERTY_HINT_RANGE, "-4096,4096"), _SCS("set_margin"),_SCS("get_margin"),MARGIN_RIGHT ); + ADD_PROPERTYINZ( PropertyInfo(Variant::INT,"margin_bottom", PROPERTY_HINT_RANGE, "-4096,4096"), _SCS("set_margin"),_SCS("get_margin"),MARGIN_BOTTOM ); + + ADD_GROUP("Rect","rect_"); + ADD_PROPERTYNZ( PropertyInfo(Variant::VECTOR2,"rect_pos", PROPERTY_HINT_NONE, "",PROPERTY_USAGE_EDITOR), _SCS("set_pos"),_SCS("get_pos") ); + 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::REAL,"rect_rotation",PROPERTY_HINT_RANGE,"-1080,1080,0.01"), _SCS("set_rotation_deg"),_SCS("get_rotation_deg") ); + ADD_PROPERTYNO( PropertyInfo(Variant::VECTOR2,"rect_scale"), _SCS("set_scale"),_SCS("get_scale") ); + ADD_PROPERTYNO( PropertyInfo(Variant::BOOL,"rect_clip_content"), _SCS("set_clip_contents"),_SCS("is_clipping_contents") ); + + + ADD_GROUP("Hint","hint_"); + ADD_PROPERTYNZ( PropertyInfo(Variant::STRING,"hint_tooltip", PROPERTY_HINT_MULTILINE_TEXT), _SCS("set_tooltip"),_SCS("_get_tooltip") ); + + ADD_GROUP("Focus","focus_"); + 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_GROUP("Mouse","mouse_"); + ADD_PROPERTY( PropertyInfo(Variant::INT,"mouse_filter",PROPERTY_HINT_ENUM,"Stop,Pass,Ignore"), _SCS("set_mouse_filter"),_SCS("get_mouse_filter") ); + + ADD_GROUP("Size Flags","size_flags_"); + ADD_PROPERTYNO( PropertyInfo(Variant::INT,"size_flags_horizontal", PROPERTY_HINT_FLAGS, "Fill,Expand"), _SCS("set_h_size_flags"),_SCS("get_h_size_flags") ); + ADD_PROPERTYNO( PropertyInfo(Variant::INT,"size_flags_vertical", PROPERTY_HINT_FLAGS, "Fill,Expand"), _SCS("set_v_size_flags"),_SCS("get_v_size_flags") ); + 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_GROUP("Theme",""); + ADD_PROPERTYNZ( PropertyInfo(Variant::OBJECT,"theme", PROPERTY_HINT_RESOURCE_TYPE, "Theme"), _SCS("set_theme"),_SCS("get_theme") ); + ADD_GROUP("",""); BIND_CONSTANT( ANCHOR_BEGIN ); BIND_CONSTANT( ANCHOR_END ); - BIND_CONSTANT( ANCHOR_RATIO ); BIND_CONSTANT( ANCHOR_CENTER ); BIND_CONSTANT( FOCUS_NONE ); BIND_CONSTANT( FOCUS_CLICK ); @@ -2393,15 +2653,19 @@ void Control::_bind_methods() { BIND_CONSTANT( SIZE_FILL ); BIND_CONSTANT( SIZE_EXPAND_FILL ); + BIND_CONSTANT( MOUSE_FILTER_STOP ); + BIND_CONSTANT( MOUSE_FILTER_PASS ); + BIND_CONSTANT( MOUSE_FILTER_IGNORE ); + ADD_SIGNAL( MethodInfo("resized") ); - ADD_SIGNAL( MethodInfo("input_event",PropertyInfo(Variant::INPUT_EVENT,"ev")) ); - ADD_SIGNAL( MethodInfo("mouse_enter") ); - ADD_SIGNAL( MethodInfo("mouse_exit") ); - ADD_SIGNAL( MethodInfo("focus_enter") ); - ADD_SIGNAL( MethodInfo("focus_exit") ); + ADD_SIGNAL( MethodInfo("gui_input",PropertyInfo(Variant::INPUT_EVENT,"ev")) ); + ADD_SIGNAL( MethodInfo("mouse_entered") ); + ADD_SIGNAL( MethodInfo("mouse_exited") ); + ADD_SIGNAL( MethodInfo("focus_entered") ); + ADD_SIGNAL( MethodInfo("focus_exited") ); ADD_SIGNAL( MethodInfo("size_flags_changed") ); ADD_SIGNAL( MethodInfo("minimum_size_changed") ); - ADD_SIGNAL( MethodInfo("modal_close") ); + ADD_SIGNAL( MethodInfo("modal_closed") ); } @@ -2409,9 +2673,7 @@ Control::Control() { data.parent=NULL; - data.ignore_mouse=false; - data.stop_mouse=true; - + data.mouse_filter=MOUSE_FILTER_STOP; data.SI=NULL; data.MI=NULL; @@ -2428,8 +2690,11 @@ Control::Control() { data.parent_canvas_item=NULL; data.scale=Vector2(1,1); data.drag_owner=0; + data.modal_frame=0; + data.block_minimum_size_adjust=false; + data.disable_visibility_clip=false; - + data.clip_contents=false; for (int i=0;i<4;i++) { data.anchor[i]=ANCHOR_BEGIN; data.margin[i]=0; diff --git a/scene/gui/control.h b/scene/gui/control.h index f720185c9d..68795b054c 100644 --- a/scene/gui/control.h +++ b/scene/gui/control.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 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 */ @@ -35,7 +35,7 @@ #include "scene/2d/canvas_item.h" #include "math_2d.h" #include "rid.h" - +#include "scene/gui/input_action.h" /** @author Juan Linietsky <reduzio@gmail.com> */ @@ -46,7 +46,7 @@ class Panel; class Control : public CanvasItem { - OBJ_TYPE( Control, CanvasItem ); + GDCLASS( Control, CanvasItem ); OBJ_CATEGORY("GUI Nodes"); public: @@ -54,7 +54,6 @@ public: enum AnchorType { ANCHOR_BEGIN, ANCHOR_END, - ANCHOR_RATIO, ANCHOR_CENTER, }; @@ -66,12 +65,18 @@ public: enum SizeFlags { - SIZE_EXPAND=1, - SIZE_FILL=2, + SIZE_FILL=1, + SIZE_EXPAND=2, SIZE_EXPAND_FILL=SIZE_EXPAND|SIZE_FILL }; + enum MouseFilter { + MOUSE_FILTER_STOP, + MOUSE_FILTER_PASS, + MOUSE_FILTER_IGNORE + }; + enum CursorShape { CURSOR_ARROW, CURSOR_IBEAM, @@ -125,13 +130,18 @@ private: bool pending_min_size_update; Point2 custom_minimum_size; - bool ignore_mouse; - bool stop_mouse; + MouseFilter mouse_filter; + + bool clip_contents; + + bool block_minimum_size_adjust; + bool disable_visibility_clip; Control *parent; ObjectID drag_owner; bool modal; bool modal_exclusive; + uint64_t modal_frame; //frame used to put something as modal Ref<Theme> theme; Control *theme_owner; String tooltip; @@ -153,10 +163,12 @@ private: HashMap<StringName, Ref<Font>, StringNameHasher > font_override; HashMap<StringName, Color, StringNameHasher > color_override; HashMap<StringName, int, StringNameHasher > constant_override; + Map< Ref<Font>, int> font_refcount; + } data; // used internally - Control* _find_control_at_pos(CanvasItem* p_node,const Point2& p_pos,const Matrix32& p_xform,Matrix32& r_inv_xform); + Control* _find_control_at_pos(CanvasItem* p_node,const Point2& p_pos,const Transform2D& p_xform,Transform2D& r_inv_xform); void _window_find_focus_neighbour(const Vector2& p_dir, Node *p_at, const Point2* p_points ,float p_min,float &r_closest_dist,Control **r_closest); @@ -169,7 +181,9 @@ private: float _get_range(int p_idx) const; float _s2a(float p_val, AnchorType p_anchor,float p_range) const; float _a2s(float p_val, AnchorType p_anchor,float p_range) const; - void _propagate_theme_changed(Control *p_owner); + void _propagate_theme_changed(CanvasItem *p_at, Control *p_owner, bool p_assign=true); + void _theme_changed(); + void _change_notify_margins(); void _update_minimum_size(); @@ -184,13 +198,23 @@ private: void _set_rotation_deg(float p_degrees); float _get_rotation_deg() const; + void _ref_font(Ref<Font> p_sc); + void _unref_font( Ref<Font> p_sc); + void _font_changed(); + + void _update_canvas_item_transform(); + + friend class Viewport; void _modal_stack_remove(); void _modal_set_prev_focus_owner(ObjectID p_prev); protected: - //virtual void _window_input_event(InputEvent p_event); + virtual void add_child_notify(Node *p_child); + virtual void remove_child_notify(Node *p_child); + + //virtual void _window_gui_input(InputEvent p_event); bool _set(const StringName& p_name, const Variant& p_value); bool _get(const StringName& p_name,Variant &r_ret) const; @@ -242,6 +266,7 @@ public: Size2 get_custom_minimum_size() const; bool is_window_modal_on_top() const; + uint64_t get_modal_frame() const; //frame in which this was made modal Control *get_parent_control() const; @@ -319,11 +344,8 @@ public: Control *get_focus_owner() const; - void set_ignore_mouse(bool p_ignore); - bool is_ignoring_mouse() const; - - void set_stop_mouse(bool p_stop); - bool is_stopping_mouse() const; + void set_mouse_filter(MouseFilter p_filter); + MouseFilter get_mouse_filter() const; /* SKINNING */ @@ -341,6 +363,13 @@ public: Color get_color(const StringName& p_name,const StringName& p_type=StringName()) const; int get_constant(const StringName& p_name,const StringName& p_type=StringName()) const; + bool has_icon_override(const StringName& p_name) const; + bool has_shader_override(const StringName& p_name) const; + bool has_stylebox_override(const StringName& p_name) const; + bool has_font_override(const StringName& p_name) const; + bool has_color_override(const StringName& p_name) const; + bool has_constant_override(const StringName& p_name) const; + bool has_icon(const StringName& p_name,const StringName& p_type=StringName()) const; bool has_shader(const StringName& p_name,const StringName& p_type=StringName()) const; bool has_stylebox(const StringName& p_name,const StringName& p_type=StringName()) const; @@ -360,7 +389,7 @@ public: virtual CursorShape get_cursor_shape(const Point2& p_pos=Point2i()) const; virtual Rect2 get_item_rect() const; - virtual Matrix32 get_transform() const; + virtual Transform2D get_transform() const; bool is_toplevel_control() const; @@ -374,6 +403,17 @@ public: Control *get_root_parent_control() const; + void set_clip_contents(bool p_clip); + bool is_clipping_contents(); + + void set_block_minimum_size_adjust(bool p_block); + bool is_minimum_size_adjust_blocked() const; + + void set_disable_visibility_clip(bool p_ignore); + bool is_visibility_clip_disabled() const; + + virtual void get_argument_options(const StringName& p_function,int p_idx,List<String>*r_options) const; + Control(); ~Control(); @@ -383,5 +423,6 @@ VARIANT_ENUM_CAST(Control::AnchorType); VARIANT_ENUM_CAST(Control::FocusMode); VARIANT_ENUM_CAST(Control::SizeFlags); VARIANT_ENUM_CAST(Control::CursorShape); +VARIANT_ENUM_CAST(Control::MouseFilter); #endif diff --git a/scene/gui/dialogs.cpp b/scene/gui/dialogs.cpp index e7a84d1146..cc6fe7cae8 100644 --- a/scene/gui/dialogs.cpp +++ b/scene/gui/dialogs.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 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 */ @@ -47,7 +47,7 @@ bool WindowDialog::has_point(const Point2& p_point) const { } -void WindowDialog::_input_event(const InputEvent& p_event) { +void WindowDialog::_gui_input(const InputEvent& p_event) { if (p_event.type == InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index==BUTTON_LEFT) { @@ -62,7 +62,6 @@ void WindowDialog::_input_event(const InputEvent& p_event) { Point2 rel( p_event.mouse_motion.relative_x, p_event.mouse_motion.relative_y ); Point2 pos = get_pos(); - Size2 size = get_size(); pos+=rel; @@ -142,13 +141,13 @@ TextureButton *WindowDialog::get_close_button() { void WindowDialog::_bind_methods() { - ObjectTypeDB::bind_method( _MD("_input_event"),&WindowDialog::_input_event); - ObjectTypeDB::bind_method( _MD("set_title","title"),&WindowDialog::set_title); - ObjectTypeDB::bind_method( _MD("get_title"),&WindowDialog::get_title); - ObjectTypeDB::bind_method( _MD("_closed"),&WindowDialog::_closed); - ObjectTypeDB::bind_method( _MD("get_close_button:TextureButton"),&WindowDialog::get_close_button); + ClassDB::bind_method( _MD("_gui_input"),&WindowDialog::_gui_input); + ClassDB::bind_method( _MD("set_title","title"),&WindowDialog::set_title); + ClassDB::bind_method( _MD("get_title"),&WindowDialog::get_title); + ClassDB::bind_method( _MD("_closed"),&WindowDialog::_closed); + ClassDB::bind_method( _MD("get_close_button:TextureButton"),&WindowDialog::get_close_button); - ADD_PROPERTY( PropertyInfo(Variant::STRING,"window/title",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_DEFAULT_INTL),_SCS("set_title"),_SCS("get_title")); + ADD_PROPERTY( PropertyInfo(Variant::STRING,"window_title",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_DEFAULT_INTL),_SCS("set_title"),_SCS("get_title")); } WindowDialog::WindowDialog() { @@ -204,7 +203,7 @@ void AcceptDialog::_notification(int p_what) { cancel_pressed(); } if (p_what==NOTIFICATION_RESIZED) { - _update_child_rect(); + _update_child_rects(); } } @@ -233,6 +232,8 @@ String AcceptDialog::get_text() const { void AcceptDialog::set_text(String p_text) { label->set_text(p_text); + minimum_size_changed(); + _update_child_rects(); } void AcceptDialog::set_hide_on_ok(bool p_hide) { @@ -252,21 +253,31 @@ void AcceptDialog::register_text_enter(Node *p_line_edit) { p_line_edit->connect("text_entered", this,"_builtin_text_entered"); } -void AcceptDialog::_update_child_rect() { +void AcceptDialog::_update_child_rects() { + + Size2 label_size=label->get_minimum_size(); + if (label->get_text().empty()) { + label_size.height = 0; + } int margin = get_constant("margin","Dialogs"); Size2 size = get_size(); Size2 hminsize = hbc->get_combined_minimum_size(); - Vector2 cpos(margin,margin); - Vector2 csize(size.x-margin*2,size.y-margin*3-hminsize.y); - label->set_pos(cpos); - label->set_size(csize); + Vector2 cpos(margin,margin+label_size.height); + Vector2 csize(size.x-margin*2,size.y-margin*3-hminsize.y-label_size.height); + + for(int i=0;i<get_child_count();i++) { + Control *c = get_child(i)->cast_to<Control>(); + if (!c) + continue; + + if (c==hbc || c==label || c==get_close_button()) + continue; - if (child) { + c->set_pos(cpos); + c->set_size(csize); - child->set_pos(cpos); - child->set_size(csize); } cpos.y+=csize.y+margin; @@ -281,13 +292,23 @@ Size2 AcceptDialog::get_minimum_size() const { int margin = get_constant("margin","Dialogs"); Size2 minsize = label->get_combined_minimum_size(); - if (child) { - Size2 cminsize = child->get_combined_minimum_size(); + + for(int i=0;i<get_child_count();i++) { + Control *c = get_child(i)->cast_to<Control>(); + if (!c) + continue; + + if (c==hbc || c==label || c==const_cast<AcceptDialog*>(this)->get_close_button()) + continue; + + Size2 cminsize = c->get_combined_minimum_size(); minsize.x=MAX(cminsize.x,minsize.x); minsize.y=MAX(cminsize.y,minsize.y); + } + Size2 hminsize = hbc->get_combined_minimum_size(); minsize.x = MAX(hminsize.x,minsize.x); minsize.y+=hminsize.y; @@ -300,23 +321,6 @@ Size2 AcceptDialog::get_minimum_size() const { } -void AcceptDialog::set_child_rect(Control *p_child) { - - ERR_FAIL_COND(p_child->get_parent()!=this); - - //p_child->set_area_as_parent_rect(get_constant("margin","Dialogs")); - child=p_child; - minimum_size_changed(); - _update_child_rect(); -} - -void AcceptDialog::remove_child_notify(Node *p_child) { - - if (p_child==child) { - child=NULL; - } -} - void AcceptDialog::_custom_action(const String& p_action) { emit_signal("custom_action",p_action); @@ -349,7 +353,7 @@ Button* AcceptDialog::add_cancel(const String &p_cancel) { String c = p_cancel; if (p_cancel=="") - c="Cancel"; + c=RTR("Cancel"); Button *b = swap_ok_cancel ? add_button(c,true) : add_button(c); b->connect("pressed",this,"_closed"); return b; @@ -357,24 +361,25 @@ Button* AcceptDialog::add_cancel(const String &p_cancel) { void AcceptDialog::_bind_methods() { - ObjectTypeDB::bind_method(_MD("_ok"),&AcceptDialog::_ok_pressed); - ObjectTypeDB::bind_method(_MD("get_ok"),&AcceptDialog::get_ok); - ObjectTypeDB::bind_method(_MD("get_label"),&AcceptDialog::get_label); - ObjectTypeDB::bind_method(_MD("set_hide_on_ok","enabled"),&AcceptDialog::set_hide_on_ok); - ObjectTypeDB::bind_method(_MD("get_hide_on_ok"),&AcceptDialog::get_hide_on_ok); - ObjectTypeDB::bind_method(_MD("add_button:Button","text","right","action"),&AcceptDialog::add_button,DEFVAL(false),DEFVAL("")); - ObjectTypeDB::bind_method(_MD("add_cancel:Button","name"),&AcceptDialog::add_cancel); - ObjectTypeDB::bind_method(_MD("_builtin_text_entered"),&AcceptDialog::_builtin_text_entered); - ObjectTypeDB::bind_method(_MD("register_text_enter:LineEdit","line_edit"),&AcceptDialog::register_text_enter); - ObjectTypeDB::bind_method(_MD("_custom_action"),&AcceptDialog::_custom_action); - ObjectTypeDB::bind_method(_MD("set_text","text"),&AcceptDialog::set_text); - ObjectTypeDB::bind_method(_MD("get_text"),&AcceptDialog::get_text); + ClassDB::bind_method(_MD("_ok"),&AcceptDialog::_ok_pressed); + ClassDB::bind_method(_MD("get_ok"),&AcceptDialog::get_ok); + ClassDB::bind_method(_MD("get_label"),&AcceptDialog::get_label); + ClassDB::bind_method(_MD("set_hide_on_ok","enabled"),&AcceptDialog::set_hide_on_ok); + ClassDB::bind_method(_MD("get_hide_on_ok"),&AcceptDialog::get_hide_on_ok); + ClassDB::bind_method(_MD("add_button:Button","text","right","action"),&AcceptDialog::add_button,DEFVAL(false),DEFVAL("")); + ClassDB::bind_method(_MD("add_cancel:Button","name"),&AcceptDialog::add_cancel); + ClassDB::bind_method(_MD("_builtin_text_entered"),&AcceptDialog::_builtin_text_entered); + ClassDB::bind_method(_MD("register_text_enter:LineEdit","line_edit"),&AcceptDialog::register_text_enter); + ClassDB::bind_method(_MD("_custom_action"),&AcceptDialog::_custom_action); + ClassDB::bind_method(_MD("set_text","text"),&AcceptDialog::set_text); + ClassDB::bind_method(_MD("get_text"),&AcceptDialog::get_text); ADD_SIGNAL( MethodInfo("confirmed") ); ADD_SIGNAL( MethodInfo("custom_action",PropertyInfo(Variant::STRING,"action")) ); - ADD_PROPERTYNZ( PropertyInfo(Variant::STRING,"dialog/text",PROPERTY_HINT_MULTILINE_TEXT,"",PROPERTY_USAGE_DEFAULT_INTL),_SCS("set_text"),_SCS("get_text")); - ADD_PROPERTY( PropertyInfo(Variant::BOOL, "dialog/hide_on_ok"),_SCS("set_hide_on_ok"),_SCS("get_hide_on_ok") ); + ADD_GROUP("Dialog","dialog"); + ADD_PROPERTYNZ( PropertyInfo(Variant::STRING,"dialog_text",PROPERTY_HINT_MULTILINE_TEXT,"",PROPERTY_USAGE_DEFAULT_INTL),_SCS("set_text"),_SCS("get_text")); + ADD_PROPERTY( PropertyInfo(Variant::BOOL, "dialog_hide_on_ok"),_SCS("set_hide_on_ok"),_SCS("get_hide_on_ok") ); } @@ -400,25 +405,20 @@ AcceptDialog::AcceptDialog() { add_child(label); hbc = memnew( HBoxContainer ); - hbc->set_area_as_parent_rect(margin); - hbc->set_anchor_and_margin(MARGIN_TOP,ANCHOR_END,button_margin); add_child(hbc); hbc->add_spacer(); ok = memnew( Button ); - ok->set_text("OK"); + ok->set_text(RTR("OK")); hbc->add_child(ok); hbc->add_spacer(); - //add_child(ok); ok->connect("pressed", this,"_ok"); set_as_toplevel(true); hide_on_ok=true; - set_title("Alert!"); - - child=NULL; + set_title(RTR("Alert!")); } @@ -429,7 +429,7 @@ AcceptDialog::~AcceptDialog() void ConfirmationDialog::_bind_methods() { - ObjectTypeDB::bind_method(_MD("get_cancel:Button"),&ConfirmationDialog::get_cancel); + ClassDB::bind_method(_MD("get_cancel:Button"),&ConfirmationDialog::get_cancel); } Button *ConfirmationDialog::get_cancel() { @@ -439,6 +439,6 @@ Button *ConfirmationDialog::get_cancel() { ConfirmationDialog::ConfirmationDialog() { - set_title("Please Confirm..."); + set_title(RTR("Please Confirm...")); cancel = add_cancel(); } diff --git a/scene/gui/dialogs.h b/scene/gui/dialogs.h index d00bb41ff6..6650c5eb5d 100644 --- a/scene/gui/dialogs.h +++ b/scene/gui/dialogs.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 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 */ @@ -42,13 +42,13 @@ class WindowDialog : public Popup { - OBJ_TYPE(WindowDialog,Popup); + GDCLASS(WindowDialog,Popup); TextureButton *close_button; String title; bool dragging; - void _input_event(const InputEvent& p_event); + void _gui_input(const InputEvent& p_event); void _closed(); protected: virtual void _post_popup(); @@ -73,7 +73,7 @@ public: class PopupDialog : public Popup { - OBJ_TYPE(PopupDialog,Popup); + GDCLASS(PopupDialog,Popup); protected: void _notification(int p_what); @@ -89,13 +89,12 @@ class LineEdit; class AcceptDialog : public WindowDialog { - OBJ_TYPE(AcceptDialog,WindowDialog); + GDCLASS(AcceptDialog,WindowDialog); - Control *child; HBoxContainer *hbc; Label *label; Button *ok; -// Button *cancel; no more cancel (there is X on tht titlebar) + //Button *cancel; no more cancel (there is X on tht titlebar) bool hide_on_ok; @@ -103,13 +102,11 @@ class AcceptDialog : public WindowDialog { void _ok_pressed(); void _close_pressed(); void _builtin_text_entered(const String& p_text); - void _update_child_rect(); + void _update_child_rects(); static bool swap_ok_cancel; - virtual void remove_child_notify(Node *p_child); - protected: @@ -140,8 +137,6 @@ public: void set_text(String p_text); String get_text() const; - void set_child_rect(Control *p_child); - AcceptDialog(); ~AcceptDialog(); @@ -150,7 +145,7 @@ public: class ConfirmationDialog : public AcceptDialog { - OBJ_TYPE(ConfirmationDialog,AcceptDialog); + GDCLASS(ConfirmationDialog,AcceptDialog); Button *cancel; protected: static void _bind_methods(); diff --git a/scene/gui/file_dialog.cpp b/scene/gui/file_dialog.cpp index 705ce55d42..393f14bee2 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-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 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 */ @@ -164,7 +164,7 @@ void FileDialog::_action_pressed() { TreeItem *ti=tree->get_next_selected(NULL); String fbase=dir_access->get_current_dir(); - DVector<String> files; + PoolVector<String> files; while(ti) { files.push_back( fbase.plus_file(ti->get_text(0)) ); @@ -186,15 +186,17 @@ void FileDialog::_action_pressed() { hide(); }else if (mode==MODE_OPEN_ANY || mode==MODE_OPEN_DIR) { - String path=dir_access->get_current_dir(); - /*if (tree->get_selected()) { - Dictionary d = tree->get_selected()->get_metadata(0); + + path=path.replace("\\","/"); + + if (TreeItem* item = tree->get_selected()) { + Dictionary d = item->get_metadata(0); if (d["dir"]) { - path=path+"/"+String(d["name"]); + path=path.plus_file(d["name"]); } - }*/ - path=path.replace("\\","/"); + } + emit_signal("dir_selected",path); hide(); } @@ -258,7 +260,7 @@ void FileDialog::_action_pressed() { } if (dir_access->file_exists(f)) { - confirm_save->set_text("File Exists, Overwrite?"); + confirm_save->set_text(RTR("File Exists, Overwrite?")); confirm_save->popup_centered(Size2(200,80)); } else { @@ -339,22 +341,27 @@ void FileDialog::update_file_list() { } } + if (dirs.find("..")==NULL) { + //may happen if lacking permissions + dirs.push_back(".."); + } + dirs.sort_custom<NoCaseComparator>(); files.sort_custom<NoCaseComparator>(); while(!dirs.empty()) { + String& dir_name = dirs.front()->get(); + TreeItem *ti=tree->create_item(root); + ti->set_text(0,dir_name+"/"); + ti->set_icon(0,folder); - if (dirs.front()->get()!=".") { - TreeItem *ti=tree->create_item(root); - ti->set_text(0,dirs.front()->get()+"/"); - ti->set_icon(0,folder); - Dictionary d; - d["name"]=dirs.front()->get(); - d["dir"]=true; - ti->set_metadata(0,d); - } - dirs.pop_front(); + Dictionary d; + d["name"]=dir_name; + d["dir"]=true; + + ti->set_metadata(0,d); + dirs.pop_front(); } dirs.clear(); @@ -396,11 +403,12 @@ void FileDialog::update_file_list() { while(!files.empty()) { bool match=patterns.empty(); + String match_str; for(List<String>::Element *E=patterns.front();E;E=E->next()) { if (files.front()->get().matchn(E->get())) { - + match_str=E->get(); match=true; break; } @@ -425,14 +433,14 @@ void FileDialog::update_file_list() { d["dir"]=false; ti->set_metadata(0,d); - if (file->get_text()==files.front()->get()) + if (file->get_text()==files.front()->get() || match_str==files.front()->get()) ti->select(0); } files.pop_front(); } - if (tree->get_root() && tree->get_root()->get_children()) + if (tree->get_root() && tree->get_root()->get_children() && tree->get_selected()==NULL) tree->get_root()->get_children()->select(0); files.clear(); @@ -463,19 +471,19 @@ void FileDialog::update_filters() { if (max_filters<filters.size()) all_filters+=", ..."; - filter->add_item("All Recognized ( "+all_filters+" )"); + filter->add_item(RTR("All Recognized")+" ( "+all_filters+" )"); } for(int i=0;i<filters.size();i++) { String flt=filters[i].get_slice(";",0).strip_edges(); String desc=filters[i].get_slice(";",1).strip_edges(); if (desc.length()) - filter->add_item(desc+" ( "+flt+" )"); + filter->add_item(String(XL_MESSAGE(desc))+" ( "+flt+" )"); else filter->add_item("( "+flt+" )"); } - filter->add_item("All Files (*)"); + filter->add_item(RTR("All Files (*)")); } @@ -493,6 +501,16 @@ void FileDialog::add_filter(const String& p_filter) { } +void FileDialog::set_filters(const Vector<String>& p_filters){ + filters=p_filters; + update_filters(); + invalidate(); +} + +Vector<String> FileDialog::get_filters() const{ + return filters; +} + String FileDialog::get_current_dir() const { return dir->get_text(); @@ -548,11 +566,11 @@ void FileDialog::set_mode(Mode p_mode) { mode=p_mode; switch(mode) { - case MODE_OPEN_FILE: get_ok()->set_text("Open"); set_title("Open a File"); makedir->hide(); break; - case MODE_OPEN_FILES: get_ok()->set_text("Open"); set_title("Open File(s)"); makedir->hide(); break; - case MODE_OPEN_DIR: get_ok()->set_text("Open"); set_title("Open a Directory"); makedir->show(); break; - case MODE_OPEN_ANY: get_ok()->set_text("Open"); set_title("Open a File or Directory"); makedir->show(); break; - case MODE_SAVE_FILE: get_ok()->set_text("Save"); set_title("Save a File"); makedir->show(); break; + case MODE_OPEN_FILE: get_ok()->set_text(RTR("Open")); set_title(RTR("Open a File")); makedir->hide(); break; + case MODE_OPEN_FILES: get_ok()->set_text(RTR("Open")); set_title(RTR("Open File(s)")); makedir->hide(); break; + case MODE_OPEN_DIR: get_ok()->set_text(RTR("Open")); set_title(RTR("Open a Directory")); makedir->show(); break; + case MODE_OPEN_ANY: get_ok()->set_text(RTR("Open")); set_title(RTR("Open a File or Directory")); makedir->show(); break; + case MODE_SAVE_FILE: get_ok()->set_text(RTR("Save")); set_title(RTR("Save a File")); makedir->show(); break; } if (mode==MODE_OPEN_FILES) { @@ -597,7 +615,7 @@ void FileDialog::set_access(Access p_access) { void FileDialog::invalidate() { - if (is_visible()) { + if (is_visible_in_tree()) { update_file_list(); invalidated=false; } else { @@ -668,42 +686,44 @@ bool FileDialog::default_show_hidden_files=false; void FileDialog::_bind_methods() { - ObjectTypeDB::bind_method(_MD("_unhandled_input"),&FileDialog::_unhandled_input); - - ObjectTypeDB::bind_method(_MD("_tree_selected"),&FileDialog::_tree_selected); - ObjectTypeDB::bind_method(_MD("_tree_db_selected"),&FileDialog::_tree_dc_selected); - ObjectTypeDB::bind_method(_MD("_dir_entered"),&FileDialog::_dir_entered); - ObjectTypeDB::bind_method(_MD("_file_entered"),&FileDialog::_file_entered); - ObjectTypeDB::bind_method(_MD("_action_pressed"),&FileDialog::_action_pressed); - ObjectTypeDB::bind_method(_MD("_cancel_pressed"),&FileDialog::_cancel_pressed); - ObjectTypeDB::bind_method(_MD("_filter_selected"),&FileDialog::_filter_selected); - ObjectTypeDB::bind_method(_MD("_save_confirm_pressed"),&FileDialog::_save_confirm_pressed); - - ObjectTypeDB::bind_method(_MD("clear_filters"),&FileDialog::clear_filters); - ObjectTypeDB::bind_method(_MD("add_filter","filter"),&FileDialog::add_filter); - ObjectTypeDB::bind_method(_MD("get_current_dir"),&FileDialog::get_current_dir); - ObjectTypeDB::bind_method(_MD("get_current_file"),&FileDialog::get_current_file); - ObjectTypeDB::bind_method(_MD("get_current_path"),&FileDialog::get_current_path); - ObjectTypeDB::bind_method(_MD("set_current_dir","dir"),&FileDialog::set_current_dir); - ObjectTypeDB::bind_method(_MD("set_current_file","file"),&FileDialog::set_current_file); - ObjectTypeDB::bind_method(_MD("set_current_path","path"),&FileDialog::set_current_path); - ObjectTypeDB::bind_method(_MD("set_mode","mode"),&FileDialog::set_mode); - ObjectTypeDB::bind_method(_MD("get_mode"),&FileDialog::get_mode); - ObjectTypeDB::bind_method(_MD("get_vbox:VBoxContainer"),&FileDialog::get_vbox); - ObjectTypeDB::bind_method(_MD("set_access","access"),&FileDialog::set_access); - ObjectTypeDB::bind_method(_MD("get_access"),&FileDialog::get_access); - ObjectTypeDB::bind_method(_MD("set_show_hidden_files","show"),&FileDialog::set_show_hidden_files); - ObjectTypeDB::bind_method(_MD("is_showing_hidden_files"),&FileDialog::is_showing_hidden_files); - ObjectTypeDB::bind_method(_MD("_select_drive"),&FileDialog::_select_drive); - ObjectTypeDB::bind_method(_MD("_make_dir"),&FileDialog::_make_dir); - ObjectTypeDB::bind_method(_MD("_make_dir_confirm"),&FileDialog::_make_dir_confirm); - ObjectTypeDB::bind_method(_MD("_update_file_list"),&FileDialog::update_file_list); - ObjectTypeDB::bind_method(_MD("_update_dir"),&FileDialog::update_dir); - - ObjectTypeDB::bind_method(_MD("invalidate"),&FileDialog::invalidate); + ClassDB::bind_method(_MD("_unhandled_input"),&FileDialog::_unhandled_input); + + ClassDB::bind_method(_MD("_tree_selected"),&FileDialog::_tree_selected); + ClassDB::bind_method(_MD("_tree_db_selected"),&FileDialog::_tree_dc_selected); + ClassDB::bind_method(_MD("_dir_entered"),&FileDialog::_dir_entered); + ClassDB::bind_method(_MD("_file_entered"),&FileDialog::_file_entered); + ClassDB::bind_method(_MD("_action_pressed"),&FileDialog::_action_pressed); + ClassDB::bind_method(_MD("_cancel_pressed"),&FileDialog::_cancel_pressed); + ClassDB::bind_method(_MD("_filter_selected"),&FileDialog::_filter_selected); + ClassDB::bind_method(_MD("_save_confirm_pressed"),&FileDialog::_save_confirm_pressed); + + ClassDB::bind_method(_MD("clear_filters"),&FileDialog::clear_filters); + ClassDB::bind_method(_MD("add_filter","filter"),&FileDialog::add_filter); + ClassDB::bind_method(_MD("set_filters","filters"),&FileDialog::set_filters); + ClassDB::bind_method(_MD("get_filters"),&FileDialog::get_filters); + ClassDB::bind_method(_MD("get_current_dir"),&FileDialog::get_current_dir); + ClassDB::bind_method(_MD("get_current_file"),&FileDialog::get_current_file); + ClassDB::bind_method(_MD("get_current_path"),&FileDialog::get_current_path); + ClassDB::bind_method(_MD("set_current_dir","dir"),&FileDialog::set_current_dir); + ClassDB::bind_method(_MD("set_current_file","file"),&FileDialog::set_current_file); + ClassDB::bind_method(_MD("set_current_path","path"),&FileDialog::set_current_path); + ClassDB::bind_method(_MD("set_mode","mode"),&FileDialog::set_mode); + ClassDB::bind_method(_MD("get_mode"),&FileDialog::get_mode); + ClassDB::bind_method(_MD("get_vbox:VBoxContainer"),&FileDialog::get_vbox); + ClassDB::bind_method(_MD("set_access","access"),&FileDialog::set_access); + ClassDB::bind_method(_MD("get_access"),&FileDialog::get_access); + ClassDB::bind_method(_MD("set_show_hidden_files","show"),&FileDialog::set_show_hidden_files); + ClassDB::bind_method(_MD("is_showing_hidden_files"),&FileDialog::is_showing_hidden_files); + ClassDB::bind_method(_MD("_select_drive"),&FileDialog::_select_drive); + ClassDB::bind_method(_MD("_make_dir"),&FileDialog::_make_dir); + ClassDB::bind_method(_MD("_make_dir_confirm"),&FileDialog::_make_dir_confirm); + ClassDB::bind_method(_MD("_update_file_list"),&FileDialog::update_file_list); + ClassDB::bind_method(_MD("_update_dir"),&FileDialog::update_dir); + + ClassDB::bind_method(_MD("invalidate"),&FileDialog::invalidate); ADD_SIGNAL(MethodInfo("file_selected",PropertyInfo( Variant::STRING,"path"))); - ADD_SIGNAL(MethodInfo("files_selected",PropertyInfo( Variant::STRING_ARRAY,"paths"))); + ADD_SIGNAL(MethodInfo("files_selected",PropertyInfo( Variant::POOL_STRING_ARRAY,"paths"))); ADD_SIGNAL(MethodInfo("dir_selected",PropertyInfo( Variant::STRING,"dir"))); BIND_CONSTANT( MODE_OPEN_FILE ); @@ -717,6 +737,11 @@ void FileDialog::_bind_methods() { BIND_CONSTANT( ACCESS_USERDATA ); BIND_CONSTANT( ACCESS_FILESYSTEM ); + ADD_PROPERTY( PropertyInfo(Variant::INT, "mode", PROPERTY_HINT_ENUM, "Open one,Open many,Open folder,Open any,Save"),_SCS("set_mode"),_SCS("get_mode") ); + ADD_PROPERTY( PropertyInfo(Variant::INT, "access", PROPERTY_HINT_ENUM, "Resources,User data,File system"),_SCS("set_access"),_SCS("get_access") ); + ADD_PROPERTY( PropertyInfo(Variant::POOL_STRING_ARRAY, "filters"),_SCS("set_filters"),_SCS("get_filters") ); + ADD_PROPERTY( PropertyInfo(Variant::BOOL, "show_hidden_files"),_SCS("set_show_hidden_files"),_SCS("is_showing_hidden_files") ); + } @@ -739,10 +764,10 @@ FileDialog::FileDialog() { VBoxContainer *vbc = memnew( VBoxContainer ); add_child(vbc); - set_child_rect(vbc); + mode=MODE_SAVE_FILE; - set_title("Save a File"); + set_title(RTR("Save a File")); dir = memnew(LineEdit); HBoxContainer *pathhb = memnew( HBoxContainer ); @@ -758,24 +783,24 @@ FileDialog::FileDialog() { drives->connect("item_selected",this,"_select_drive"); makedir = memnew( Button ); - makedir->set_text("Create Folder"); + makedir->set_text(RTR("Create Folder")); makedir->connect("pressed",this,"_make_dir"); pathhb->add_child(makedir); - vbc->add_margin_child("Path:",pathhb); + vbc->add_margin_child(RTR("Path:"),pathhb); tree = memnew(Tree); tree->set_hide_root(true); - vbc->add_margin_child("Directories & Files:",tree,true); + vbc->add_margin_child(RTR("Directories & Files:"),tree,true); file = memnew(LineEdit); //add_child(file); - vbc->add_margin_child("File:",file); + vbc->add_margin_child(RTR("File:"),file); filter = memnew( OptionButton ); //add_child(filter); - vbc->add_margin_child("Filter:",filter); + vbc->add_margin_child(RTR("Filter:"),filter); filter->set_clip_text(true);//too many extensions overflow it dir_access = DirAccess::create(DirAccess::ACCESS_RESOURCES); @@ -800,21 +825,21 @@ FileDialog::FileDialog() { confirm_save->connect("confirmed", this,"_save_confirm_pressed"); makedialog = memnew( ConfirmationDialog ); - makedialog->set_title("Create Folder"); + makedialog->set_title(RTR("Create Folder")); VBoxContainer *makevb= memnew( VBoxContainer ); makedialog->add_child(makevb); - makedialog->set_child_rect(makevb); + makedirname = memnew( LineEdit ); - makevb->add_margin_child("Name:",makedirname); + makevb->add_margin_child(RTR("Name:"),makedirname); add_child(makedialog); makedialog->register_text_enter(makedirname); makedialog->connect("confirmed",this,"_make_dir_confirm"); mkdirerr = memnew( AcceptDialog ); - mkdirerr->set_text("Could not create folder."); + mkdirerr->set_text(RTR("Could not create folder.")); add_child(mkdirerr); exterr = memnew( AcceptDialog ); - exterr->set_text("Must use a valid extension."); + exterr->set_text(RTR("Must use a valid extension.")); add_child(exterr); @@ -843,11 +868,11 @@ FileDialog::~FileDialog() { void LineEditFileChooser::_bind_methods() { - ObjectTypeDB::bind_method(_MD("_browse"),&LineEditFileChooser::_browse); - ObjectTypeDB::bind_method(_MD("_chosen"),&LineEditFileChooser::_chosen); - ObjectTypeDB::bind_method(_MD("get_button:Button"),&LineEditFileChooser::get_button); - ObjectTypeDB::bind_method(_MD("get_line_edit:LineEdit"),&LineEditFileChooser::get_line_edit); - ObjectTypeDB::bind_method(_MD("get_file_dialog:FileDialog"),&LineEditFileChooser::get_file_dialog); + ClassDB::bind_method(_MD("_browse"),&LineEditFileChooser::_browse); + ClassDB::bind_method(_MD("_chosen"),&LineEditFileChooser::_chosen); + ClassDB::bind_method(_MD("get_button:Button"),&LineEditFileChooser::get_button); + ClassDB::bind_method(_MD("get_line_edit:LineEdit"),&LineEditFileChooser::get_line_edit); + ClassDB::bind_method(_MD("get_file_dialog:FileDialog"),&LineEditFileChooser::get_file_dialog); } diff --git a/scene/gui/file_dialog.h b/scene/gui/file_dialog.h index 1fcf8387ce..653b38e40d 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-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 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 */ @@ -42,7 +42,7 @@ */ class FileDialog : public ConfirmationDialog { - OBJ_TYPE( FileDialog, ConfirmationDialog ); + GDCLASS( FileDialog, ConfirmationDialog ); public: @@ -131,6 +131,8 @@ public: void clear_filters(); void add_filter(const String& p_filter); + void set_filters(const Vector<String>& p_filters); + Vector<String> get_filters() const; void set_enable_multiple_selection(bool p_enable); Vector<String> get_selected_files() const; @@ -165,7 +167,7 @@ public: class LineEditFileChooser : public HBoxContainer { - OBJ_TYPE( LineEditFileChooser, HBoxContainer ); + GDCLASS( LineEditFileChooser, HBoxContainer ); Button *button; LineEdit *line_edit; FileDialog *dialog; diff --git a/scene/gui/graph_edit.cpp b/scene/gui/graph_edit.cpp index 9123194589..ba1ab1afa8 100644 --- a/scene/gui/graph_edit.cpp +++ b/scene/gui/graph_edit.cpp @@ -1,3 +1,31 @@ +/*************************************************************************/ +/* graph_edit.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2017 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 */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ #include "graph_edit.h" #include "os/input.h" #include "os/keyboard.h" @@ -33,6 +61,8 @@ Error GraphEdit::connect_node(const StringName& p_from, int p_from_port,const St c.to_port=p_to_port; connections.push_back(c); top_layer->update(); + update(); + connections_layer->update(); return OK; } @@ -57,6 +87,8 @@ void GraphEdit::disconnect_node(const StringName& p_from, int p_from_port,const connections.erase(E); top_layer->update(); + update(); + connections_layer->update(); return; } } @@ -72,19 +104,39 @@ void GraphEdit::get_connection_list(List<Connection> *r_connections) const { *r_connections=connections; } +void GraphEdit::set_scroll_ofs(const Vector2& p_ofs) { + + setting_scroll_ofs=true; + h_scroll->set_value(p_ofs.x); + v_scroll->set_value(p_ofs.y); + _update_scroll(); + setting_scroll_ofs=false; +} + Vector2 GraphEdit::get_scroll_ofs() const{ - return Vector2(h_scroll->get_val(),v_scroll->get_val()); + return Vector2(h_scroll->get_value(),v_scroll->get_value()); } void GraphEdit::_scroll_moved(double) { - _update_scroll_offset(); + + if (!awaiting_scroll_offset_update) { + call_deferred("_update_scroll_offset"); + awaiting_scroll_offset_update=true; + } top_layer->update(); + update(); + + if (!setting_scroll_ofs) {//in godot, signals on change value are avoided as a convention + emit_signal("scroll_offset_changed",get_scroll_ofs()); + } } void GraphEdit::_update_scroll_offset() { + set_block_minimum_size_adjust(true); + for(int i=0;i<get_child_count();i++) { GraphNode *gn=get_child(i)->cast_to<GraphNode>(); @@ -92,11 +144,17 @@ void GraphEdit::_update_scroll_offset() { continue; Point2 pos=gn->get_offset()*zoom; - pos-=Point2(h_scroll->get_val(),v_scroll->get_val()); + pos-=Point2(h_scroll->get_value(),v_scroll->get_value()); gn->set_pos(pos); - gn->set_scale(Vector2(zoom,zoom)); + if (gn->get_scale()!=Vector2(zoom,zoom)) { + gn->set_scale(Vector2(zoom,zoom)); + } } + connections_layer->set_pos(-Point2(h_scroll->get_value(),v_scroll->get_value())); + set_block_minimum_size_adjust(false); + awaiting_scroll_offset_update=false; + } void GraphEdit::_update_scroll() { @@ -105,6 +163,9 @@ void GraphEdit::_update_scroll() { return; updating=true; + + set_block_minimum_size_adjust(true); + Rect2 screen; for(int i=0;i<get_child_count();i++) { @@ -139,7 +200,13 @@ void GraphEdit::_update_scroll() { else v_scroll->show(); - _update_scroll_offset(); + set_block_minimum_size_adjust(false); + + if (!awaiting_scroll_offset_update) { + call_deferred("_update_scroll_offset"); + awaiting_scroll_offset_update=true; + } + updating=false; } @@ -149,7 +216,21 @@ void GraphEdit::_graph_node_raised(Node* p_gn) { GraphNode *gn=p_gn->cast_to<GraphNode>(); ERR_FAIL_COND(!gn); gn->raise(); + if (gn->is_comment()) { + move_child(gn,0); + } + int first_not_comment=0; + for(int i=0;i<get_child_count();i++) { + GraphNode *gn=get_child(i)->cast_to<GraphNode>(); + if (gn && !gn->is_comment()) { + first_not_comment=i; + break; + } + } + + move_child(connections_layer,first_not_comment); top_layer->raise(); + emit_signal("node_selected",p_gn); } @@ -159,23 +240,32 @@ void GraphEdit::_graph_node_moved(Node *p_gn) { GraphNode *gn=p_gn->cast_to<GraphNode>(); ERR_FAIL_COND(!gn); top_layer->update(); + update(); + connections_layer->update(); } void GraphEdit::add_child_notify(Node *p_child) { + Control::add_child_notify(p_child); + top_layer->call_deferred("raise"); //top layer always on top! GraphNode *gn = p_child->cast_to<GraphNode>(); if (gn) { gn->set_scale(Vector2(zoom,zoom)); gn->connect("offset_changed",this,"_graph_node_moved",varray(gn)); gn->connect("raise_request",this,"_graph_node_raised",varray(gn)); + gn->connect("item_rect_changed",connections_layer,"update"); _graph_node_moved(gn); - gn->set_stop_mouse(false); + gn->set_mouse_filter(MOUSE_FILTER_PASS); } + + } void GraphEdit::remove_child_notify(Node *p_child) { + Control::remove_child_notify(p_child); + top_layer->call_deferred("raise"); //top layer always on top! GraphNode *gn = p_child->cast_to<GraphNode>(); if (gn) { @@ -200,18 +290,69 @@ void GraphEdit::_notification(int p_what) { h_scroll->set_anchor_and_margin(MARGIN_TOP,ANCHOR_END,hmin.height); h_scroll->set_anchor_and_margin(MARGIN_BOTTOM,ANCHOR_END,0); -// zoom_icon->set_texture( get_icon("Zoom", "EditorIcons")); + + zoom_minus->set_icon(get_icon("minus")); + zoom_reset->set_icon(get_icon("reset")); + zoom_plus->set_icon(get_icon("more")); + snap_button->set_icon(get_icon("snap")); + //zoom_icon->set_texture( get_icon("Zoom", "EditorIcons")); } if (p_what==NOTIFICATION_DRAW) { + + draw_style_box( get_stylebox("bg"),Rect2(Point2(),get_size()) ); - VS::get_singleton()->canvas_item_set_clip(get_canvas_item(),true); + + if (is_using_snap()) { + //draw grid + + int snap = get_snap(); + + Vector2 offset = get_scroll_ofs()/zoom; + Size2 size = get_size()/zoom; + + Point2i from = (offset/float(snap)).floor(); + Point2i len = (size/float(snap)).floor()+Vector2(1,1); + + Color grid_minor = get_color("grid_minor"); + Color grid_major = get_color("grid_major"); + + for(int i=from.x;i<from.x+len.x;i++) { + + Color color; + + if (ABS(i)%10==0) + color=grid_major; + else + color=grid_minor; + + float base_ofs = i*snap*zoom - offset.x*zoom; + draw_line(Vector2(base_ofs,0),Vector2(base_ofs,get_size().height),color); + } + + for(int i=from.y;i<from.y+len.y;i++) { + + Color color; + + if (ABS(i)%10==0) + color=grid_major; + else + color=grid_minor; + + float base_ofs = i*snap*zoom - offset.y*zoom; + draw_line(Vector2(0,base_ofs),Vector2(get_size().width,base_ofs),color); + } + + } + + } if (p_what==NOTIFICATION_RESIZED) { _update_scroll(); top_layer->update(); + } } @@ -219,7 +360,8 @@ bool GraphEdit::_filter_input(const Point2& p_point) { Ref<Texture> port =get_icon("port","GraphNode"); - float grab_r=port->get_width()*0.5; + float grab_r_extend = 2.0; + float grab_r=port->get_width()*0.5*grab_r_extend; for(int i=get_child_count()-1;i>=0;i--) { GraphNode *gn=get_child(i)->cast_to<GraphNode>(); @@ -238,8 +380,9 @@ bool GraphEdit::_filter_input(const Point2& p_point) { for(int j=0;j<gn->get_connection_input_count();j++) { Vector2 pos = gn->get_connection_input_pos(j)+gn->get_pos(); - if (pos.distance_to(p_point)<grab_r) + if (pos.distance_to(p_point)<grab_r) { return true; + } } @@ -251,11 +394,13 @@ bool GraphEdit::_filter_input(const Point2& p_point) { void GraphEdit::_top_layer_input(const InputEvent& p_ev) { + + float grab_r_extend = 2.0; if (p_ev.type==InputEvent::MOUSE_BUTTON && p_ev.mouse_button.button_index==BUTTON_LEFT && p_ev.mouse_button.pressed) { Ref<Texture> port =get_icon("port","GraphNode"); Vector2 mpos(p_ev.mouse_button.x,p_ev.mouse_button.y); - float grab_r=port->get_width()*0.5; + float grab_r=port->get_width()*0.5*grab_r_extend; for(int i=get_child_count()-1;i>=0;i--) { GraphNode *gn=get_child(i)->cast_to<GraphNode>(); @@ -267,6 +412,37 @@ void GraphEdit::_top_layer_input(const InputEvent& p_ev) { Vector2 pos = gn->get_connection_output_pos(j)+gn->get_pos(); if (pos.distance_to(mpos)<grab_r) { + + if (valid_left_disconnect_types.has(gn->get_connection_output_type(j))) { + //check disconnect + for (List<Connection>::Element*E=connections.front();E;E=E->next()) { + + if (E->get().from==gn->get_name() && E->get().from_port==j) { + + Node*to = get_node(String(E->get().to)); + if (to && to->cast_to<GraphNode>()) { + + connecting_from=E->get().to; + connecting_index=E->get().to_port; + connecting_out=false; + connecting_type=to->cast_to<GraphNode>()->get_connection_input_type(E->get().to_port); + connecting_color=to->cast_to<GraphNode>()->get_connection_input_color(E->get().to_port); + connecting_target=false; + connecting_to=pos; + just_disconected=true; + + emit_signal("disconnection_request",E->get().from,E->get().from_port,E->get().to,E->get().to_port); + to = get_node(String(connecting_from)); //maybe it was erased + if (to && to->cast_to<GraphNode>()) { + connecting=true; + } + return; + } + + } + } + } + connecting=true; connecting_from=gn->get_name(); connecting_index=j; @@ -275,6 +451,7 @@ void GraphEdit::_top_layer_input(const InputEvent& p_ev) { connecting_color=gn->get_connection_output_color(j); connecting_target=false; connecting_to=pos; + just_disconected=false; return; } @@ -287,7 +464,7 @@ void GraphEdit::_top_layer_input(const InputEvent& p_ev) { if (pos.distance_to(mpos)<grab_r) { - if (right_disconnects) { + if (right_disconnects || valid_right_disconnect_types.has(gn->get_connection_input_type(j))) { //check disconnect for (List<Connection>::Element*E=connections.front();E;E=E->next()) { @@ -303,6 +480,7 @@ void GraphEdit::_top_layer_input(const InputEvent& p_ev) { connecting_color=fr->cast_to<GraphNode>()->get_connection_output_color(E->get().from_port); connecting_target=false; connecting_to=pos; + just_disconected=true; emit_signal("disconnection_request",E->get().from,E->get().from_port,E->get().to,E->get().to_port); fr = get_node(String(connecting_from)); //maybe it was erased @@ -325,6 +503,8 @@ void GraphEdit::_top_layer_input(const InputEvent& p_ev) { connecting_color=gn->get_connection_input_color(j); connecting_target=false; connecting_to=pos; + just_disconected=true; + return; } @@ -337,11 +517,11 @@ void GraphEdit::_top_layer_input(const InputEvent& p_ev) { connecting_to=Vector2(p_ev.mouse_motion.x,p_ev.mouse_motion.y); connecting_target=false; - top_layer->update(); + top_layer->update(); Ref<Texture> port =get_icon("port","GraphNode"); Vector2 mpos(p_ev.mouse_button.x,p_ev.mouse_button.y); - float grab_r=port->get_width()*0.5; + float grab_r=port->get_width()*0.5*grab_r_extend; for(int i=get_child_count()-1;i>=0;i--) { GraphNode *gn=get_child(i)->cast_to<GraphNode>(); @@ -353,7 +533,7 @@ void GraphEdit::_top_layer_input(const InputEvent& p_ev) { Vector2 pos = gn->get_connection_output_pos(j)+gn->get_pos(); int type =gn->get_connection_output_type(j); - if (type==connecting_type && pos.distance_to(mpos)<grab_r) { + if ((type==connecting_type ||valid_connection_types.has(ConnType(type,connecting_type))) && pos.distance_to(mpos)<grab_r) { connecting_target=true; connecting_to=pos; @@ -370,7 +550,7 @@ void GraphEdit::_top_layer_input(const InputEvent& p_ev) { Vector2 pos = gn->get_connection_input_pos(j)+gn->get_pos(); int type =gn->get_connection_input_type(j); - if (type==connecting_type && pos.distance_to(mpos)<grab_r) { + if ((type==connecting_type ||valid_connection_types.has(ConnType(type,connecting_type))) && pos.distance_to(mpos)<grab_r) { connecting_target=true; connecting_to=pos; connecting_target_to=gn->get_name(); @@ -397,18 +577,91 @@ void GraphEdit::_top_layer_input(const InputEvent& p_ev) { } emit_signal("connection_request",from,from_slot,to,to_slot); + } else if (!just_disconected) { + String from = connecting_from; + int from_slot = connecting_index; + Vector2 ofs = Vector2(p_ev.mouse_button.x,p_ev.mouse_button.y); + emit_signal("connection_to_empty",from,from_slot,ofs); } connecting=false; top_layer->update(); + update(); + connections_layer->update(); } } -void GraphEdit::_draw_cos_line(const Vector2& p_from, const Vector2& p_to,const Color& p_color) { + +template<class Vector2> +static _FORCE_INLINE_ Vector2 _bezier_interp(real_t t, Vector2 start, Vector2 control_1, Vector2 control_2, Vector2 end) { + /* Formula from Wikipedia article on Bezier curves. */ + real_t omt = (1.0 - t); + real_t omt2 = omt*omt; + real_t omt3 = omt2*omt; + real_t t2 = t*t; + real_t t3 = t2*t; + + return start * omt3 + + control_1 * omt2 * t * 3.0 + + control_2 * omt * t2 * 3.0 + + end * t3; +} + + +void GraphEdit::_bake_segment2d(CanvasItem* p_where,float p_begin, float p_end,const Vector2& p_a,const Vector2& p_out,const Vector2& p_b, const Vector2& p_in,int p_depth,int p_min_depth,int p_max_depth,float p_tol,const Color& p_color,const Color& p_to_color,int &lines) const { + + float mp = p_begin+(p_end-p_begin)*0.5; + Vector2 beg = _bezier_interp(p_begin,p_a,p_a+p_out,p_b+p_in,p_b); + Vector2 mid = _bezier_interp(mp,p_a,p_a+p_out,p_b+p_in,p_b); + Vector2 end = _bezier_interp(p_end,p_a,p_a+p_out,p_b+p_in,p_b); + + Vector2 na = (mid-beg).normalized(); + Vector2 nb = (end-mid).normalized(); + float dp = Math::rad2deg(Math::acos(na.dot(nb))); + + if (p_depth>=p_min_depth && ( dp<p_tol || p_depth>=p_max_depth)) { + + + + p_where->draw_line(beg,end,p_color.linear_interpolate(p_to_color,mp),2,true); + lines++; + } else { + _bake_segment2d(p_where,p_begin,mp,p_a,p_out,p_b,p_in,p_depth+1,p_min_depth,p_max_depth,p_tol,p_color,p_to_color,lines); + _bake_segment2d(p_where,mp,p_end,p_a,p_out,p_b,p_in,p_depth+1,p_min_depth,p_max_depth,p_tol,p_color,p_to_color,lines); + } +} + + +void GraphEdit::_draw_cos_line(CanvasItem* p_where,const Vector2& p_from, const Vector2& p_to,const Color& p_color,const Color& p_to_color) { + + +#if 1 + + //cubic bezier code + float diff = p_to.x-p_from.x; + float cp_offset; + int cp_len = get_constant("bezier_len_pos"); + int cp_neg_len = get_constant("bezier_len_neg"); + + if (diff>0) { + cp_offset=MAX(cp_len,diff*0.5); + } else { + cp_offset=MAX(MIN(cp_len-diff,cp_neg_len),-diff*0.5); + } + + Vector2 c1 = Vector2(cp_offset*zoom,0); + Vector2 c2 = Vector2(-cp_offset*zoom,0); + + int lines=0; + _bake_segment2d(p_where,0,1,p_from,c1,p_to,c2,0,3,9,8,p_color,p_to_color,lines); + + +#else static const int steps = 20; + //old cosine code Rect2 r; r.pos=p_from; r.expand_to(p_to); @@ -418,6 +671,7 @@ void GraphEdit::_draw_cos_line(const Vector2& p_from, const Vector2& p_to,const Vector2 prev; for(int i=0;i<=steps;i++) { + float d = i/float(steps); float c=-Math::cos(d*Math_PI) * 0.5+0.5; if (flip) @@ -426,11 +680,65 @@ void GraphEdit::_draw_cos_line(const Vector2& p_from, const Vector2& p_to,const if (i>0) { - top_layer->draw_line(prev,p,p_color,2); + p_where->draw_line(prev,p,p_color.linear_interpolate(p_to_color,d),2); } prev=p; } +#endif +} + + +void GraphEdit::_connections_layer_draw() { + + + { + //draw connections + List<List<Connection>::Element* > to_erase; + for(List<Connection>::Element *E=connections.front();E;E=E->next()) { + + NodePath fromnp(E->get().from); + + Node * from = get_node(fromnp); + if (!from) { + to_erase.push_back(E); + continue; + } + + GraphNode *gfrom = from->cast_to<GraphNode>(); + + if (!gfrom) { + to_erase.push_back(E); + continue; + } + + NodePath tonp(E->get().to); + Node * to = get_node(tonp); + if (!to) { + to_erase.push_back(E); + continue; + } + + GraphNode *gto = to->cast_to<GraphNode>(); + + if (!gto) { + to_erase.push_back(E); + continue; + } + + Vector2 frompos=gfrom->get_connection_output_pos(E->get().from_port)+gfrom->get_offset()*zoom; + Color color = gfrom->get_connection_output_color(E->get().from_port); + Vector2 topos=gto->get_connection_input_pos(E->get().to_port)+gto->get_offset()*zoom; + Color tocolor = gto->get_connection_input_color(E->get().to_port); + _draw_cos_line(connections_layer,frompos,topos,color,tocolor); + + } + + while(to_erase.size()) { + connections.erase(to_erase.front()->get()); + to_erase.pop_front(); + } + } } void GraphEdit::_top_layer_draw() { @@ -460,71 +768,55 @@ void GraphEdit::_top_layer_draw() { col.g+=0.4; col.b+=0.4; } - _draw_cos_line(pos,topos,col); - } - - List<List<Connection>::Element* > to_erase; - for(List<Connection>::Element *E=connections.front();E;E=E->next()) { - - NodePath fromnp(E->get().from); - Node * from = get_node(fromnp); - if (!from) { - to_erase.push_back(E); - continue; + if (!connecting_out) { + SWAP(pos,topos); } + _draw_cos_line(top_layer,pos,topos,col,col); + } - GraphNode *gfrom = from->cast_to<GraphNode>(); - if (!gfrom) { - to_erase.push_back(E); - continue; - } + if (box_selecting) + top_layer->draw_rect(box_selecting_rect,Color(0.7,0.7,1.0,0.3)); +} - NodePath tonp(E->get().to); - Node * to = get_node(tonp); - if (!to) { - to_erase.push_back(E); - continue; - } +void GraphEdit::set_selected(Node* p_child) { - GraphNode *gto = to->cast_to<GraphNode>(); + for(int i=get_child_count()-1;i>=0;i--) { - if (!gto) { - to_erase.push_back(E); + GraphNode *gn=get_child(i)->cast_to<GraphNode>(); + if (!gn) continue; - } - - Vector2 frompos=gfrom->get_connection_output_pos(E->get().from_port)+gfrom->get_pos(); - Color color = gfrom->get_connection_output_color(E->get().from_port); - Vector2 topos=gto->get_connection_input_pos(E->get().to_port)+gto->get_pos(); - _draw_cos_line(frompos,topos,color); + gn->set_selected(gn==p_child); } - - while(to_erase.size()) { - connections.erase(to_erase.front()->get()); - to_erase.pop_front(); - } - if (box_selecting) - top_layer->draw_rect(box_selecting_rect,Color(0.7,0.7,1.0,0.3)); } -void GraphEdit::_input_event(const InputEvent& p_ev) { +void GraphEdit::_gui_input(const InputEvent& p_ev) { if (p_ev.type==InputEvent::MOUSE_MOTION && (p_ev.mouse_motion.button_mask&BUTTON_MASK_MIDDLE || (p_ev.mouse_motion.button_mask&BUTTON_MASK_LEFT && Input::get_singleton()->is_key_pressed(KEY_SPACE)))) { - h_scroll->set_val( h_scroll->get_val() - p_ev.mouse_motion.relative_x ); - v_scroll->set_val( v_scroll->get_val() - p_ev.mouse_motion.relative_y ); + h_scroll->set_value( h_scroll->get_value() - p_ev.mouse_motion.relative_x ); + v_scroll->set_value( v_scroll->get_value() - p_ev.mouse_motion.relative_y ); } if (p_ev.type==InputEvent::MOUSE_MOTION && dragging) { just_selected=true; - drag_accum+=Vector2(p_ev.mouse_motion.relative_x,p_ev.mouse_motion.relative_y); + // TODO: Remove local mouse pos hack if/when InputEventMouseMotion is fixed to support floats + //drag_accum+=Vector2(p_ev.mouse_motion.relative_x,p_ev.mouse_motion.relative_y); + drag_accum = get_local_mouse_pos() - drag_origin; for(int i=get_child_count()-1;i>=0;i--) { GraphNode *gn=get_child(i)->cast_to<GraphNode>(); - if (gn && gn->is_selected()) - gn->set_offset((gn->get_drag_from()*zoom+drag_accum)/zoom); + if (gn && gn->is_selected()) { + + Vector2 pos = (gn->get_drag_from()*zoom+drag_accum)/zoom; + if (is_using_snap()) { + int snap = get_snap(); + pos = pos.snapped(Vector2(snap,snap)); + } + + gn->set_offset(pos); + } } } @@ -613,19 +905,27 @@ void GraphEdit::_input_event(const InputEvent& p_ev) { dragging = false; top_layer->update(); + update(); + connections_layer->update(); } if (b.button_index==BUTTON_LEFT && b.pressed) { GraphNode *gn = NULL; + GraphNode *gn_selected = NULL; for(int i=get_child_count()-1;i>=0;i--) { - gn=get_child(i)->cast_to<GraphNode>(); + gn_selected=get_child(i)->cast_to<GraphNode>(); + + if (gn_selected) { - if (gn) { - Rect2 r = gn->get_rect(); + if (gn_selected->is_resizing()) + continue; + + Rect2 r = gn_selected->get_rect(); r.size*=zoom; if (r.has_point(get_local_mouse_pos())) + gn = gn_selected; break; } } @@ -637,6 +937,7 @@ void GraphEdit::_input_event(const InputEvent& p_ev) { dragging = true; drag_accum = Vector2(); + drag_origin = get_local_mouse_pos(); just_selected = !gn->is_selected(); if(!gn->is_selected() && !Input::get_singleton()->is_key_pressed(KEY_CONTROL)) { for (int i = 0; i < get_child_count(); i++) { @@ -733,6 +1034,7 @@ void GraphEdit::clear_connections() { connections.clear(); update(); + connections_layer->update(); } void GraphEdit::set_zoom(float p_zoom) { @@ -744,19 +1046,19 @@ void GraphEdit::set_zoom(float p_zoom) { zoom_minus->set_disabled(zoom==MIN_ZOOM); zoom_plus->set_disabled(zoom==MAX_ZOOM); - Vector2 sbofs = (Vector2( h_scroll->get_val(), v_scroll->get_val() ) + get_size()/2)/zoom; + Vector2 sbofs = (Vector2( h_scroll->get_value(), v_scroll->get_value() ) + get_size()/2)/zoom; - float prev_zoom = zoom; zoom = p_zoom; top_layer->update(); _update_scroll(); + connections_layer->update(); - if (is_visible()) { + if (is_visible_in_tree()) { Vector2 ofs = sbofs*zoom - get_size()/2; - h_scroll->set_val( ofs.x ); - v_scroll->set_val( ofs.y ); + h_scroll->set_value( ofs.x ); + v_scroll->set_value( ofs.y ); } @@ -777,6 +1079,29 @@ bool GraphEdit::is_right_disconnects_enabled() const{ return right_disconnects; } +void GraphEdit::add_valid_right_disconnect_type(int p_type) { + + valid_right_disconnect_types.insert(p_type); +} + +void GraphEdit::remove_valid_right_disconnect_type(int p_type){ + + valid_right_disconnect_types.erase(p_type); + +} + +void GraphEdit::add_valid_left_disconnect_type(int p_type){ + + valid_left_disconnect_types.insert(p_type); + +} + +void GraphEdit::remove_valid_left_disconnect_type(int p_type){ + + valid_left_disconnect_types.erase(p_type); + +} + Array GraphEdit::_get_connection_list() const { List<Connection> conns; @@ -811,40 +1136,120 @@ void GraphEdit::_zoom_plus() { set_zoom(zoom*ZOOM_SCALE); } +void GraphEdit::add_valid_connection_type(int p_type,int p_with_type) { + + ConnType ct; + ct.type_a=p_type; + ct.type_b=p_with_type; + + valid_connection_types.insert(ct); +} + +void GraphEdit::remove_valid_connection_type(int p_type,int p_with_type) { + + ConnType ct; + ct.type_a=p_type; + ct.type_b=p_with_type; + + valid_connection_types.erase(ct); + +} + +bool GraphEdit::is_valid_connection_type(int p_type,int p_with_type) const { + + ConnType ct; + ct.type_a=p_type; + ct.type_b=p_with_type; + + return valid_connection_types.has(ct); + +} + +void GraphEdit::set_use_snap(bool p_enable) { + + snap_button->set_pressed(p_enable); + update(); + +} + +bool GraphEdit::is_using_snap() const{ + + return snap_button->is_pressed(); + +} + +int GraphEdit::get_snap() const{ + + return snap_amount->get_value(); +} + +void GraphEdit::set_snap(int p_snap) { + + ERR_FAIL_COND(p_snap<5); + snap_amount->set_value(p_snap); + update(); +} +void GraphEdit::_snap_toggled() { + update(); +} + +void GraphEdit::_snap_value_changed(double) { + + update(); +} + void GraphEdit::_bind_methods() { - ObjectTypeDB::bind_method(_MD("connect_node:Error","from","from_port","to","to_port"),&GraphEdit::connect_node); - ObjectTypeDB::bind_method(_MD("is_node_connected","from","from_port","to","to_port"),&GraphEdit::is_node_connected); - ObjectTypeDB::bind_method(_MD("disconnect_node","from","from_port","to","to_port"),&GraphEdit::disconnect_node); - ObjectTypeDB::bind_method(_MD("get_connection_list"),&GraphEdit::_get_connection_list); - ObjectTypeDB::bind_method(_MD("get_scroll_ofs"),&GraphEdit::get_scroll_ofs); + ClassDB::bind_method(_MD("connect_node:Error","from","from_port","to","to_port"),&GraphEdit::connect_node); + ClassDB::bind_method(_MD("is_node_connected","from","from_port","to","to_port"),&GraphEdit::is_node_connected); + ClassDB::bind_method(_MD("disconnect_node","from","from_port","to","to_port"),&GraphEdit::disconnect_node); + ClassDB::bind_method(_MD("get_connection_list"),&GraphEdit::_get_connection_list); + ClassDB::bind_method(_MD("get_scroll_ofs"),&GraphEdit::get_scroll_ofs); + ClassDB::bind_method(_MD("set_scroll_ofs","ofs"),&GraphEdit::set_scroll_ofs); + + ClassDB::bind_method(_MD("set_zoom","p_zoom"),&GraphEdit::set_zoom); + ClassDB::bind_method(_MD("get_zoom"),&GraphEdit::get_zoom); + + ClassDB::bind_method(_MD("set_snap","pixels"),&GraphEdit::set_snap); + ClassDB::bind_method(_MD("get_snap"),&GraphEdit::get_snap); - ObjectTypeDB::bind_method(_MD("set_zoom","p_zoom"),&GraphEdit::set_zoom); - ObjectTypeDB::bind_method(_MD("get_zoom"),&GraphEdit::get_zoom); + ClassDB::bind_method(_MD("set_use_snap","enable"),&GraphEdit::set_use_snap); + ClassDB::bind_method(_MD("is_using_snap"),&GraphEdit::is_using_snap); - ObjectTypeDB::bind_method(_MD("set_right_disconnects","enable"),&GraphEdit::set_right_disconnects); - ObjectTypeDB::bind_method(_MD("is_right_disconnects_enabled"),&GraphEdit::is_right_disconnects_enabled); + ClassDB::bind_method(_MD("set_right_disconnects","enable"),&GraphEdit::set_right_disconnects); + ClassDB::bind_method(_MD("is_right_disconnects_enabled"),&GraphEdit::is_right_disconnects_enabled); - ObjectTypeDB::bind_method(_MD("_graph_node_moved"),&GraphEdit::_graph_node_moved); - ObjectTypeDB::bind_method(_MD("_graph_node_raised"),&GraphEdit::_graph_node_raised); + ClassDB::bind_method(_MD("_graph_node_moved"),&GraphEdit::_graph_node_moved); + ClassDB::bind_method(_MD("_graph_node_raised"),&GraphEdit::_graph_node_raised); - ObjectTypeDB::bind_method(_MD("_top_layer_input"),&GraphEdit::_top_layer_input); - ObjectTypeDB::bind_method(_MD("_top_layer_draw"),&GraphEdit::_top_layer_draw); - ObjectTypeDB::bind_method(_MD("_scroll_moved"),&GraphEdit::_scroll_moved); - ObjectTypeDB::bind_method(_MD("_zoom_minus"),&GraphEdit::_zoom_minus); - ObjectTypeDB::bind_method(_MD("_zoom_reset"),&GraphEdit::_zoom_reset); - ObjectTypeDB::bind_method(_MD("_zoom_plus"),&GraphEdit::_zoom_plus); + ClassDB::bind_method(_MD("_top_layer_input"),&GraphEdit::_top_layer_input); + ClassDB::bind_method(_MD("_top_layer_draw"),&GraphEdit::_top_layer_draw); + ClassDB::bind_method(_MD("_scroll_moved"),&GraphEdit::_scroll_moved); + ClassDB::bind_method(_MD("_zoom_minus"),&GraphEdit::_zoom_minus); + ClassDB::bind_method(_MD("_zoom_reset"),&GraphEdit::_zoom_reset); + ClassDB::bind_method(_MD("_zoom_plus"),&GraphEdit::_zoom_plus); + ClassDB::bind_method(_MD("_snap_toggled"),&GraphEdit::_snap_toggled); + ClassDB::bind_method(_MD("_snap_value_changed"),&GraphEdit::_snap_value_changed); - ObjectTypeDB::bind_method(_MD("_input_event"),&GraphEdit::_input_event); + ClassDB::bind_method(_MD("_gui_input"),&GraphEdit::_gui_input); + ClassDB::bind_method(_MD("_update_scroll_offset"),&GraphEdit::_update_scroll_offset); + ClassDB::bind_method(_MD("_connections_layer_draw"),&GraphEdit::_connections_layer_draw); + + + + ClassDB::bind_method(_MD("set_selected","node"),&GraphEdit::set_selected); ADD_SIGNAL(MethodInfo("connection_request",PropertyInfo(Variant::STRING,"from"),PropertyInfo(Variant::INT,"from_slot"),PropertyInfo(Variant::STRING,"to"),PropertyInfo(Variant::INT,"to_slot"))); ADD_SIGNAL(MethodInfo("disconnection_request",PropertyInfo(Variant::STRING,"from"),PropertyInfo(Variant::INT,"from_slot"),PropertyInfo(Variant::STRING,"to"),PropertyInfo(Variant::INT,"to_slot"))); ADD_SIGNAL(MethodInfo("popup_request", PropertyInfo(Variant::VECTOR2,"p_position"))); ADD_SIGNAL(MethodInfo("duplicate_nodes_request")); + ADD_SIGNAL(MethodInfo("node_selected",PropertyInfo(Variant::OBJECT,"node"))); + ADD_SIGNAL(MethodInfo("connection_to_empty",PropertyInfo(Variant::STRING,"from"),PropertyInfo(Variant::INT,"from_slot"),PropertyInfo(Variant::VECTOR2,"release_pos"))); ADD_SIGNAL(MethodInfo("delete_nodes_request")); ADD_SIGNAL(MethodInfo("_begin_node_move")); ADD_SIGNAL(MethodInfo("_end_node_move")); + ADD_SIGNAL(MethodInfo("scroll_offset_changed",PropertyInfo(Variant::VECTOR2,"ofs"))); } @@ -852,14 +1257,21 @@ void GraphEdit::_bind_methods() { GraphEdit::GraphEdit() { set_focus_mode(FOCUS_ALL); + awaiting_scroll_offset_update=false; top_layer=NULL; top_layer=memnew(GraphEditFilter(this)); add_child(top_layer); - top_layer->set_stop_mouse(false); + top_layer->set_mouse_filter(MOUSE_FILTER_PASS); top_layer->set_area_as_parent_rect(); top_layer->connect("draw",this,"_top_layer_draw"); - top_layer->set_stop_mouse(false); - top_layer->connect("input_event",this,"_top_layer_input"); + top_layer->set_mouse_filter(MOUSE_FILTER_PASS); + top_layer->connect("gui_input",this,"_top_layer_input"); + + connections_layer = memnew( Control ); + add_child(connections_layer); + connections_layer->connect("draw",this,"_connections_layer_draw"); + connections_layer->set_name("CLAYER"); + connections_layer->set_disable_visibility_clip(true); // so it can draw freely and be offseted h_scroll = memnew(HScrollBar); h_scroll->set_name("_h_scroll"); @@ -875,6 +1287,13 @@ GraphEdit::GraphEdit() { box_selecting = false; dragging = false; + //set large minmax so it can scroll even if not resized yet + h_scroll->set_min(-10000); + h_scroll->set_max(10000); + + v_scroll->set_min(-10000); + v_scroll->set_max(10000); + h_scroll->connect("value_changed", this,"_scroll_moved"); v_scroll->connect("value_changed", this,"_scroll_moved"); @@ -888,17 +1307,36 @@ GraphEdit::GraphEdit() { zoom_minus = memnew( ToolButton ); zoom_hb->add_child(zoom_minus); zoom_minus->connect("pressed",this,"_zoom_minus"); - zoom_minus->set_icon(get_icon("minus")); + zoom_minus->set_focus_mode(FOCUS_NONE); zoom_reset = memnew( ToolButton ); zoom_hb->add_child(zoom_reset); zoom_reset->connect("pressed",this,"_zoom_reset"); - zoom_reset->set_icon(get_icon("reset")); + zoom_reset->set_focus_mode(FOCUS_NONE); zoom_plus = memnew( ToolButton ); zoom_hb->add_child(zoom_plus); zoom_plus->connect("pressed",this,"_zoom_plus"); - zoom_plus->set_icon(get_icon("more")); + zoom_plus->set_focus_mode(FOCUS_NONE); + + snap_button = memnew( ToolButton ); + snap_button->set_toggle_mode(true); + snap_button->connect("pressed",this,"_snap_toggled"); + snap_button->set_pressed(true); + snap_button->set_focus_mode(FOCUS_NONE); + zoom_hb->add_child(snap_button); + + snap_amount = memnew( SpinBox ); + snap_amount->set_min(5); + snap_amount->set_max(100); + snap_amount->set_step(1); + snap_amount->set_value(20); + snap_amount->connect("value_changed",this,"_snap_value_changed"); + zoom_hb->add_child(snap_amount); + + setting_scroll_ofs=false; + just_disconected=false; + set_clip_contents(true); } diff --git a/scene/gui/graph_edit.h b/scene/gui/graph_edit.h index 8a7721b9b5..3e9944332f 100644 --- a/scene/gui/graph_edit.h +++ b/scene/gui/graph_edit.h @@ -1,3 +1,31 @@ +/*************************************************************************/ +/* graph_edit.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2017 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 */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ #ifndef GRAPH_EDIT_H #define GRAPH_EDIT_H @@ -5,13 +33,14 @@ #include "scene/gui/scroll_bar.h" #include "scene/gui/slider.h" #include "scene/gui/tool_button.h" -#include "texture_frame.h" +#include "scene/gui/spin_box.h" +#include "scene/gui/texture_rect.h" class GraphEdit; class GraphEditFilter : public Control { - OBJ_TYPE(GraphEditFilter,Control); + GDCLASS(GraphEditFilter,Control); friend class GraphEdit; GraphEdit *ge; @@ -25,7 +54,7 @@ public: class GraphEdit : public Control { - OBJ_TYPE(GraphEdit,Control); + GDCLASS(GraphEdit,Control); public: struct Connection { @@ -42,6 +71,9 @@ private: ToolButton *zoom_reset; ToolButton *zoom_plus; + ToolButton *snap_button; + SpinBox *snap_amount; + void _zoom_minus(); void _zoom_reset(); void _zoom_plus(); @@ -60,10 +92,12 @@ private: Vector2 connecting_to; String connecting_target_to; int connecting_target_index; + bool just_disconected; bool dragging; bool just_selected; Vector2 drag_accum; + Point2 drag_origin; // Workaround for GH-5907 float zoom; @@ -74,28 +108,64 @@ private: Rect2 box_selecting_rect; List<GraphNode*> previus_selected; + bool setting_scroll_ofs; bool right_disconnects; bool updating; + bool awaiting_scroll_offset_update; List<Connection> connections; - void _draw_cos_line(const Vector2& p_from, const Vector2& p_to,const Color& p_color); + void _bake_segment2d(CanvasItem* p_where,float p_begin, float p_end, const Vector2& p_a, const Vector2& p_out, const Vector2& p_b, const Vector2& p_in, int p_depth, int p_min_depth, int p_max_depth, float p_tol, const Color& p_color, const Color& p_to_color, int &lines) const; + + void _draw_cos_line(CanvasItem* p_where,const Vector2& p_from, const Vector2& p_to, const Color& p_color, const Color &p_to_color); void _graph_node_raised(Node* p_gn); void _graph_node_moved(Node *p_gn); void _update_scroll(); void _scroll_moved(double); - void _input_event(const InputEvent& p_ev); + void _gui_input(const InputEvent& p_ev); + Control *connections_layer; GraphEditFilter *top_layer; void _top_layer_input(const InputEvent& p_ev); void _top_layer_draw(); + void _connections_layer_draw(); void _update_scroll_offset(); Array _get_connection_list() const; + bool lines_on_bg; + + + + struct ConnType { + + union { + struct { + uint32_t type_a; + uint32_t type_b; + }; + uint64_t key; + }; + + bool operator<(const ConnType& p_type) const { + return key<p_type.key; + } + + ConnType(uint32_t a=0, uint32_t b=0) { + type_a=a; + type_b=b; + } + }; + + Set<ConnType> valid_connection_types; + Set<int> valid_left_disconnect_types; + Set<int> valid_right_disconnect_types; + friend class GraphEditFilter; bool _filter_input(const Point2& p_point); + void _snap_toggled(); + void _snap_value_changed(double); protected: static void _bind_methods(); @@ -110,6 +180,10 @@ public: void disconnect_node(const StringName& p_from, int p_from_port,const StringName& p_to,int p_to_port); void clear_connections(); + void add_valid_connection_type(int p_type,int p_with_type); + void remove_valid_connection_type(int p_type,int p_with_type); + bool is_valid_connection_type(int p_type,int p_with_type) const; + void set_zoom(float p_zoom); float get_zoom() const; @@ -119,8 +193,23 @@ public: void set_right_disconnects(bool p_enable); bool is_right_disconnects_enabled() const; + void add_valid_right_disconnect_type(int p_type); + void remove_valid_right_disconnect_type(int p_type); + + void add_valid_left_disconnect_type(int p_type); + void remove_valid_left_disconnect_type(int p_type); + + void set_scroll_ofs(const Vector2& p_ofs); Vector2 get_scroll_ofs() const; + void set_selected(Node* p_child); + + void set_use_snap(bool p_enable); + bool is_using_snap() const; + + int get_snap() const; + void set_snap(int p_snap); + GraphEdit(); }; diff --git a/scene/gui/graph_node.cpp b/scene/gui/graph_node.cpp index eef1bf79c4..aa8c875f40 100644 --- a/scene/gui/graph_node.cpp +++ b/scene/gui/graph_node.cpp @@ -1,3 +1,31 @@ +/*************************************************************************/ +/* graph_node.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2017 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 */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ #include "graph_node.h" #include "method_bind_ext.inc" @@ -155,14 +183,45 @@ void GraphNode::_resort() { } +bool GraphNode::has_point(const Point2& p_point) const { + + if (comment) { + Ref<StyleBox> comment = get_stylebox("comment"); + Ref<Texture> resizer =get_icon("resizer"); + + if (Rect2(get_size()-resizer->get_size(), resizer->get_size()).has_point(p_point)) { + return true; + } + if (Rect2(0,0,get_size().width,comment->get_margin(MARGIN_TOP)).has_point(p_point)) { + return true; + } + + return false; + + } else { + return Control::has_point(p_point); + } +} void GraphNode::_notification(int p_what) { if (p_what==NOTIFICATION_DRAW) { - Ref<StyleBox> sb=get_stylebox(selected ? "selectedframe" : "frame"); + Ref<StyleBox> sb; + + if (comment) { + sb = get_stylebox( selected? "commentfocus" : "comment"); + + } else { + + sb = get_stylebox( selected ? "selectedframe" : "frame"); + } + + //sb=sb->duplicate(); + //sb->call("set_modulate",modulate); Ref<Texture> port =get_icon("port"); Ref<Texture> close =get_icon("close"); + Ref<Texture> resizer =get_icon("resizer"); int close_offset = get_constant("close_offset"); Ref<Font> title_font = get_font("title_font"); int title_offset = get_constant("title_offset"); @@ -170,8 +229,25 @@ void GraphNode::_notification(int p_what) { Point2i icofs = -port->get_size()*0.5; int edgeofs=get_constant("port_offset"); icofs.y+=sb->get_margin(MARGIN_TOP); + + + draw_style_box(sb,Rect2(Point2(),get_size())); + switch(overlay) { + case OVERLAY_DISABLED: { + + } break; + case OVERLAY_BREAKPOINT: { + + draw_style_box(get_stylebox("breakpoint"),Rect2(Point2(),get_size())); + } break; + case OVERLAY_POSITION: { + draw_style_box(get_stylebox("position"),Rect2(Point2(),get_size())); + + } break; + } + int w = get_size().width-sb->get_minimum_size().x; if (show_close) @@ -195,12 +271,27 @@ void GraphNode::_notification(int p_what) { continue; const Slot &s=slot_info[E->key()]; //left - if (s.enable_left) - port->draw(get_canvas_item(),icofs+Point2(edgeofs,cache_y[E->key()]),s.color_left); - if (s.enable_right) - port->draw(get_canvas_item(),icofs+Point2(get_size().x-edgeofs,cache_y[E->key()]),s.color_right); + if (s.enable_left) { + Ref<Texture> p = port; + if (s.custom_slot_left.is_valid()) { + p=s.custom_slot_left; + } + p->draw(get_canvas_item(),icofs+Point2(edgeofs,cache_y[E->key()]),s.color_left); + } + if (s.enable_right) { + Ref<Texture> p = port; + if (s.custom_slot_right.is_valid()) { + p=s.custom_slot_right; + } + p->draw(get_canvas_item(),icofs+Point2(get_size().x-edgeofs,cache_y[E->key()]),s.color_right); + } } + + + if (resizeable) { + draw_texture(resizer,get_size()-resizer->get_size()); + } } if (p_what==NOTIFICATION_SORT_CHILDREN) { @@ -211,7 +302,7 @@ void GraphNode::_notification(int p_what) { } -void GraphNode::set_slot(int p_idx,bool p_enable_left,int p_type_left,const Color& p_color_left, bool p_enable_right,int p_type_right,const Color& p_color_right) { +void GraphNode::set_slot(int p_idx,bool p_enable_left,int p_type_left,const Color& p_color_left, bool p_enable_right,int p_type_right,const Color& p_color_right,const Ref<Texture>& p_custom_left,const Ref<Texture>& p_custom_right) { ERR_FAIL_COND(p_idx<0); @@ -227,6 +318,8 @@ void GraphNode::set_slot(int p_idx,bool p_enable_left,int p_type_left,const Colo s.enable_right=p_enable_right; s.type_right=p_type_right; s.color_right=p_color_right; + s.custom_slot_left=p_custom_left; + s.custom_slot_right=p_custom_right; slot_info[p_idx]=s; update(); connpos_dirty=true; @@ -528,68 +621,162 @@ Color GraphNode::get_connection_output_color(int p_idx) { return conn_output_cache[p_idx].color; } -void GraphNode::_input_event(const InputEvent& p_ev) { +void GraphNode::_gui_input(const InputEvent& p_ev) { if (p_ev.type==InputEvent::MOUSE_BUTTON) { - get_parent_control()->grab_focus(); + + ERR_EXPLAIN("GraphNode must be the child of a GraphEdit node."); + ERR_FAIL_COND(get_parent_control() == NULL); + + print_line("INPUT EVENT BUTTON"); + if(p_ev.mouse_button.pressed && p_ev.mouse_button.button_index==BUTTON_LEFT) { Vector2 mpos = Vector2(p_ev.mouse_button.x,p_ev.mouse_button.y); if (close_rect.size!=Size2() && close_rect.has_point(mpos)) { emit_signal("close_request"); + accept_event(); return; } + + Ref<Texture> resizer =get_icon("resizer"); + + if (resizeable && mpos.x > get_size().x-resizer->get_width() && mpos.y > get_size().y-resizer->get_height()) { + + resizing=true; + resizing_from=mpos; + resizing_from_size=get_size(); + accept_event(); + return; + } + + //send focus to parent emit_signal("raise_request"); + get_parent_control()->grab_focus(); + } + + if(!p_ev.mouse_button.pressed && p_ev.mouse_button.button_index==BUTTON_LEFT) { + resizing=false; + } + + } + + + if (resizing && p_ev.type==InputEvent::MOUSE_MOTION) { + Vector2 mpos = Vector2(p_ev.mouse_motion.x,p_ev.mouse_motion.y); + + Vector2 diff = mpos - resizing_from; + + emit_signal("resize_request",resizing_from_size+diff); + } + +} + +void GraphNode::set_overlay(Overlay p_overlay) { + + overlay=p_overlay; + update(); +} + +GraphNode::Overlay GraphNode::get_overlay() const{ + + return overlay; +} + +void GraphNode::set_comment(bool p_enable) { + + comment=p_enable; + update(); +} + +bool GraphNode::is_comment() const{ + + return comment; +} + + +void GraphNode::set_resizeable(bool p_enable) { + + resizeable=p_enable; + update(); +} + +bool GraphNode::is_resizeable() const{ + + return resizeable; } void GraphNode::_bind_methods() { - ObjectTypeDB::bind_method(_MD("set_title","title"),&GraphNode::set_title); - ObjectTypeDB::bind_method(_MD("get_title"),&GraphNode::get_title); - ObjectTypeDB::bind_method(_MD("_input_event"),&GraphNode::_input_event); + ClassDB::bind_method(_MD("set_title","title"),&GraphNode::set_title); + ClassDB::bind_method(_MD("get_title"),&GraphNode::get_title); + ClassDB::bind_method(_MD("_gui_input"),&GraphNode::_gui_input); + + ClassDB::bind_method(_MD("set_slot","idx","enable_left","type_left","color_left","enable_right","type_right","color_right","custom_left","custom_right"),&GraphNode::set_slot,DEFVAL(Ref<Texture>()),DEFVAL(Ref<Texture>())); + ClassDB::bind_method(_MD("clear_slot","idx"),&GraphNode::clear_slot); + ClassDB::bind_method(_MD("clear_all_slots","idx"),&GraphNode::clear_all_slots); + ClassDB::bind_method(_MD("is_slot_enabled_left","idx"),&GraphNode::is_slot_enabled_left); + ClassDB::bind_method(_MD("get_slot_type_left","idx"),&GraphNode::get_slot_type_left); + ClassDB::bind_method(_MD("get_slot_color_left","idx"),&GraphNode::get_slot_color_left); + ClassDB::bind_method(_MD("is_slot_enabled_right","idx"),&GraphNode::is_slot_enabled_right); + ClassDB::bind_method(_MD("get_slot_type_right","idx"),&GraphNode::get_slot_type_right); + ClassDB::bind_method(_MD("get_slot_color_right","idx"),&GraphNode::get_slot_color_right); - ObjectTypeDB::bind_method(_MD("set_slot","idx","enable_left","type_left","color_left","enable_right","type_right","color_right"),&GraphNode::set_slot); - ObjectTypeDB::bind_method(_MD("clear_slot","idx"),&GraphNode::clear_slot); - ObjectTypeDB::bind_method(_MD("clear_all_slots","idx"),&GraphNode::clear_all_slots); - ObjectTypeDB::bind_method(_MD("is_slot_enabled_left","idx"),&GraphNode::is_slot_enabled_left); - ObjectTypeDB::bind_method(_MD("get_slot_type_left","idx"),&GraphNode::get_slot_type_left); - ObjectTypeDB::bind_method(_MD("get_slot_color_left","idx"),&GraphNode::get_slot_color_left); - ObjectTypeDB::bind_method(_MD("is_slot_enabled_right","idx"),&GraphNode::is_slot_enabled_right); - ObjectTypeDB::bind_method(_MD("get_slot_type_right","idx"),&GraphNode::get_slot_type_right); - ObjectTypeDB::bind_method(_MD("get_slot_color_right","idx"),&GraphNode::get_slot_color_right); + ClassDB::bind_method(_MD("set_offset","offset"),&GraphNode::set_offset); + ClassDB::bind_method(_MD("get_offset"),&GraphNode::get_offset); - ObjectTypeDB::bind_method(_MD("set_offset","offset"),&GraphNode::set_offset); - ObjectTypeDB::bind_method(_MD("get_offset"),&GraphNode::get_offset); + ClassDB::bind_method(_MD("set_comment","comment"),&GraphNode::set_comment); + ClassDB::bind_method(_MD("is_comment"),&GraphNode::is_comment); - ObjectTypeDB::bind_method(_MD("get_connection_output_count"),&GraphNode::get_connection_output_count); - ObjectTypeDB::bind_method(_MD("get_connection_input_count"),&GraphNode::get_connection_input_count); + ClassDB::bind_method(_MD("set_resizeable","resizeable"),&GraphNode::set_resizeable); + ClassDB::bind_method(_MD("is_resizeable"),&GraphNode::is_resizeable); - ObjectTypeDB::bind_method(_MD("get_connection_output_pos","idx"),&GraphNode::get_connection_output_pos); - ObjectTypeDB::bind_method(_MD("get_connection_output_type","idx"),&GraphNode::get_connection_output_type); - ObjectTypeDB::bind_method(_MD("get_connection_output_color","idx"),&GraphNode::get_connection_output_color); - ObjectTypeDB::bind_method(_MD("get_connection_input_pos","idx"),&GraphNode::get_connection_input_pos); - ObjectTypeDB::bind_method(_MD("get_connection_input_type","idx"),&GraphNode::get_connection_input_type); - ObjectTypeDB::bind_method(_MD("get_connection_input_color","idx"),&GraphNode::get_connection_input_color); + ClassDB::bind_method(_MD("set_selected","selected"),&GraphNode::set_selected); + ClassDB::bind_method(_MD("is_selected"),&GraphNode::is_selected); + ClassDB::bind_method(_MD("get_connection_output_count"),&GraphNode::get_connection_output_count); + ClassDB::bind_method(_MD("get_connection_input_count"),&GraphNode::get_connection_input_count); - ObjectTypeDB::bind_method(_MD("set_show_close_button","show"),&GraphNode::set_show_close_button); - ObjectTypeDB::bind_method(_MD("is_close_button_visible"),&GraphNode::is_close_button_visible); + ClassDB::bind_method(_MD("get_connection_output_pos","idx"),&GraphNode::get_connection_output_pos); + ClassDB::bind_method(_MD("get_connection_output_type","idx"),&GraphNode::get_connection_output_type); + ClassDB::bind_method(_MD("get_connection_output_color","idx"),&GraphNode::get_connection_output_color); + ClassDB::bind_method(_MD("get_connection_input_pos","idx"),&GraphNode::get_connection_input_pos); + ClassDB::bind_method(_MD("get_connection_input_type","idx"),&GraphNode::get_connection_input_type); + ClassDB::bind_method(_MD("get_connection_input_color","idx"),&GraphNode::get_connection_input_color); + + ClassDB::bind_method(_MD("set_show_close_button","show"),&GraphNode::set_show_close_button); + ClassDB::bind_method(_MD("is_close_button_visible"),&GraphNode::is_close_button_visible); + + ClassDB::bind_method(_MD("set_overlay","overlay"),&GraphNode::set_overlay); + ClassDB::bind_method(_MD("get_overlay"),&GraphNode::get_overlay); ADD_PROPERTY( PropertyInfo(Variant::STRING,"title"),_SCS("set_title"),_SCS("get_title")); ADD_PROPERTY( PropertyInfo(Variant::BOOL,"show_close"),_SCS("set_show_close_button"),_SCS("is_close_button_visible")); + ADD_PROPERTY( PropertyInfo(Variant::BOOL,"resizeable"),_SCS("set_resizeable"),_SCS("is_resizeable")); ADD_SIGNAL(MethodInfo("offset_changed")); ADD_SIGNAL(MethodInfo("dragged",PropertyInfo(Variant::VECTOR2,"from"),PropertyInfo(Variant::VECTOR2,"to"))); ADD_SIGNAL(MethodInfo("raise_request")); ADD_SIGNAL(MethodInfo("close_request")); + ADD_SIGNAL(MethodInfo("resize_request",PropertyInfo(Variant::VECTOR2,"new_minsize"))); + + BIND_CONSTANT( OVERLAY_DISABLED ); + BIND_CONSTANT( OVERLAY_BREAKPOINT ); + BIND_CONSTANT( OVERLAY_POSITION ); } GraphNode::GraphNode() { + + overlay=OVERLAY_DISABLED; show_close=false; connpos_dirty=true; - set_stop_mouse(false); + set_mouse_filter(MOUSE_FILTER_PASS); + comment=false; + resizeable=false; + resizing=false; + selected=false; } diff --git a/scene/gui/graph_node.h b/scene/gui/graph_node.h index dc407a6809..9cb46fc49c 100644 --- a/scene/gui/graph_node.h +++ b/scene/gui/graph_node.h @@ -1,3 +1,31 @@ +/*************************************************************************/ +/* graph_node.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2017 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 */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ #ifndef GRAPH_NODE_H #define GRAPH_NODE_H @@ -5,9 +33,15 @@ class GraphNode : public Container { - OBJ_TYPE(GraphNode,Container); - + GDCLASS(GraphNode,Container); +public: + enum Overlay { + OVERLAY_DISABLED, + OVERLAY_BREAKPOINT, + OVERLAY_POSITION + }; +private: struct Slot { bool enable_left; @@ -16,6 +50,8 @@ class GraphNode : public Container { bool enable_right; int type_right; Color color_right; + Ref<Texture> custom_slot_left; + Ref<Texture> custom_slot_right; Slot() { enable_left=false; type_left=0; color_left=Color(1,1,1,1); enable_right=false; type_right=0; color_right=Color(1,1,1,1); } @@ -24,6 +60,12 @@ class GraphNode : public Container { String title; bool show_close; Vector2 offset; + bool comment; + bool resizeable; + + bool resizing; + Vector2 resizing_from; + Vector2 resizing_from_size; Rect2 close_rect; @@ -47,10 +89,15 @@ class GraphNode : public Container { Vector2 drag_from; bool selected; + + Overlay overlay; + + bool has_point(const Point2& p_point) const; + protected: - void _input_event(const InputEvent& p_ev); + void _gui_input(const InputEvent& p_ev); void _notification(int p_what); static void _bind_methods(); @@ -63,7 +110,7 @@ public: - void set_slot(int p_idx,bool p_enable_left,int p_type_left,const Color& p_color_left, bool p_enable_right,int p_type_right,const Color& p_color_right); + void set_slot(int p_idx,bool p_enable_left,int p_type_left,const Color& p_color_left, bool p_enable_right,int p_type_right,const Color& p_color_right,const Ref<Texture>& p_custom_left=Ref<Texture>(),const Ref<Texture>& p_custom_right=Ref<Texture>()); void clear_slot(int p_idx); void clear_all_slots(); bool is_slot_enabled_left(int p_idx) const; @@ -98,10 +145,22 @@ public: Color get_connection_output_color(int p_idx); + void set_overlay(Overlay p_overlay); + Overlay get_overlay() const; + + void set_comment(bool p_enable); + bool is_comment() const; + + void set_resizeable(bool p_enable); + bool is_resizeable() const; + virtual Size2 get_minimum_size() const; + bool is_resizing() const { return resizing; } + GraphNode(); }; +VARIANT_ENUM_CAST( GraphNode::Overlay ) #endif // GRAPH_NODE_H diff --git a/scene/gui/grid_container.cpp b/scene/gui/grid_container.cpp index a514f1b3d7..597169ca83 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-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 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 */ @@ -53,7 +53,7 @@ void GridContainer::_notification(int p_what) { for(int i=0;i<get_child_count();i++) { Control *c = get_child(i)->cast_to<Control>(); - if (!c || !c->is_visible()) + if (!c || !c->is_visible_in_tree()) continue; int row = idx / columns; @@ -70,7 +70,7 @@ void GridContainer::_notification(int p_what) { else row_minh[row]=ms.height; - // print_line("store row "+itos(row)+" mw "+itos(ms.height)); + //print_line("store row "+itos(row)+" mw "+itos(ms.height)); if (c->get_h_size_flags()&SIZE_EXPAND) col_expanded.insert(col); @@ -112,7 +112,7 @@ void GridContainer::_notification(int p_what) { for(int i=0;i<get_child_count();i++) { Control *c = get_child(i)->cast_to<Control>(); - if (!c || !c->is_visible()) + if (!c || !c->is_visible_in_tree()) continue; int row = idx / columns; int col = idx % columns; @@ -136,7 +136,7 @@ void GridContainer::_notification(int p_what) { Point2 p(col_ofs,row_ofs); -// print_line("col: "+itos(col)+" row: "+itos(row)+" col_ofs: "+itos(col_ofs)+" row_ofs: "+itos(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)); @@ -156,8 +156,10 @@ void GridContainer::_notification(int p_what) { void GridContainer::set_columns(int p_columns) { + ERR_FAIL_COND(p_columns<1); columns=p_columns; queue_sort(); + minimum_size_changed(); } @@ -168,8 +170,8 @@ int GridContainer::get_columns() const{ void GridContainer::_bind_methods(){ - ObjectTypeDB::bind_method(_MD("set_columns","columns"),&GridContainer::set_columns); - ObjectTypeDB::bind_method(_MD("get_columns"),&GridContainer::get_columns); + ClassDB::bind_method(_MD("set_columns","columns"),&GridContainer::set_columns); + ClassDB::bind_method(_MD("get_columns"),&GridContainer::get_columns); ADD_PROPERTY( PropertyInfo(Variant::INT,"columns",PROPERTY_HINT_RANGE,"1,1024,1"),_SCS("set_columns"),_SCS("get_columns")); } @@ -189,7 +191,7 @@ Size2 GridContainer::get_minimum_size() const { for(int i=0;i<get_child_count();i++) { Control *c = get_child(i)->cast_to<Control>(); - if (!c || !c->is_visible()) + if (!c || !c->is_visible_in_tree()) continue; int row = idx / columns; int col = idx % columns; @@ -228,6 +230,6 @@ Size2 GridContainer::get_minimum_size() const { GridContainer::GridContainer() { - set_stop_mouse(false); + set_mouse_filter(MOUSE_FILTER_PASS); columns=1; } diff --git a/scene/gui/grid_container.h b/scene/gui/grid_container.h index 588bb17fa1..cc1d04cdb2 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-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 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 */ @@ -33,7 +33,7 @@ class GridContainer : public Container { - OBJ_TYPE(GridContainer,Container); + GDCLASS(GridContainer,Container); int columns; protected: diff --git a/scene/gui/input_action.cpp b/scene/gui/input_action.cpp new file mode 100644 index 0000000000..77026dfdb1 --- /dev/null +++ b/scene/gui/input_action.cpp @@ -0,0 +1,125 @@ +#include "input_action.h" +#include "os/keyboard.h" + +void ShortCut::set_shortcut(const InputEvent& p_shortcut){ + + shortcut=p_shortcut; + emit_changed(); +} + +InputEvent ShortCut::get_shortcut() const{ + + return shortcut; +} + +bool ShortCut::is_shortcut(const InputEvent& p_event) const { + + bool same=false; + + + switch(p_event.type) { + + case InputEvent::KEY: { + + same=(shortcut.key.scancode==p_event.key.scancode && shortcut.key.mod == p_event.key.mod); + + } break; + case InputEvent::JOYPAD_BUTTON: { + + same=(shortcut.joy_button.button_index==p_event.joy_button.button_index); + + } break; + case InputEvent::MOUSE_BUTTON: { + + same=(shortcut.mouse_button.button_index==p_event.mouse_button.button_index); + + } break; + case InputEvent::JOYPAD_MOTION: { + + same=(shortcut.joy_motion.axis==p_event.joy_motion.axis && (shortcut.joy_motion.axis_value < 0) == (p_event.joy_motion.axis_value < 0)); + + } break; + default: {}; + } + + return same; +} + +String ShortCut::get_as_text() const { + + switch(shortcut.type) { + + case InputEvent::NONE: { + + return "None"; + } break; + case InputEvent::KEY: { + + String str; + if (shortcut.key.mod.shift) + str+=RTR("Shift+"); + if (shortcut.key.mod.alt) + str+=RTR("Alt+"); + if (shortcut.key.mod.control) + str+=RTR("Ctrl+"); + if (shortcut.key.mod.meta) + str+=RTR("Meta+"); + + str+=keycode_get_string(shortcut.key.scancode).capitalize(); + + return str; + } break; + case InputEvent::JOYPAD_BUTTON: { + + String str = RTR("Device")+" "+itos(shortcut.device)+", "+RTR("Button")+" "+itos(shortcut.joy_button.button_index); + str+="."; + + return str; + } break; + case InputEvent::MOUSE_BUTTON: { + + String str = RTR("Device")+" "+itos(shortcut.device)+", "; + switch (shortcut.mouse_button.button_index) { + case BUTTON_LEFT: str+=RTR("Left Button."); break; + case BUTTON_RIGHT: str+=RTR("Right Button."); break; + case BUTTON_MIDDLE: str+=RTR("Middle Button."); break; + case BUTTON_WHEEL_UP: str+=RTR("Wheel Up."); break; + case BUTTON_WHEEL_DOWN: str+=RTR("Wheel Down."); break; + default: str+=RTR("Button")+" "+itos(shortcut.mouse_button.button_index)+"."; + } + + return str; + } break; + case InputEvent::JOYPAD_MOTION: { + + int ax = shortcut.joy_motion.axis; + String str = RTR("Device")+" "+itos(shortcut.device)+", "+RTR("Axis")+" "+itos(ax)+"."; + + return str; + } break; + } + + return ""; +} + +bool ShortCut::is_valid() const { + + return shortcut.type!=InputEvent::NONE; +} + +void ShortCut::_bind_methods() { + + ClassDB::bind_method(_MD("set_shortcut","event"),&ShortCut::set_shortcut); + ClassDB::bind_method(_MD("get_shortcut"),&ShortCut::get_shortcut); + + ClassDB::bind_method(_MD("is_valid"),&ShortCut::is_valid); + + ClassDB::bind_method(_MD("is_shortcut","event"),&ShortCut::is_shortcut); + ClassDB::bind_method(_MD("get_as_text"),&ShortCut::get_as_text); + + ADD_PROPERTY(PropertyInfo(Variant::INPUT_EVENT,"shortcut"),_SCS("set_shortcut"),_SCS("get_shortcut")); +} + +ShortCut::ShortCut(){ + +} diff --git a/scene/gui/input_action.h b/scene/gui/input_action.h new file mode 100644 index 0000000000..a83b3a70cd --- /dev/null +++ b/scene/gui/input_action.h @@ -0,0 +1,26 @@ +#ifndef INPUTACTION_H +#define INPUTACTION_H + +#include "resource.h" + +class ShortCut : public Resource { + + GDCLASS(ShortCut,Resource); + + InputEvent shortcut; +protected: + + static void _bind_methods(); +public: + + void set_shortcut(const InputEvent& p_shortcut); + InputEvent get_shortcut() const; + bool is_shortcut(const InputEvent& p_Event) const; + bool is_valid() const; + + String get_as_text() const; + + ShortCut(); +}; + +#endif // INPUTACTION_H diff --git a/scene/gui/item_list.cpp b/scene/gui/item_list.cpp index fc4ab5f8ca..a3ed0a91cf 100644 --- a/scene/gui/item_list.cpp +++ b/scene/gui/item_list.cpp @@ -1,3 +1,31 @@ +/*************************************************************************/ +/* item_list.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2017 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 */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ #include "item_list.h" #include "os/os.h" #include "globals.h" @@ -12,6 +40,7 @@ void ItemList::add_item(const String& p_item,const Ref<Texture>& p_texture,bool item.selectable=p_selectable; item.selected=false; item.disabled=false; + item.tooltip_enabled=true; item.custom_bg=Color(0,0,0,0); items.push_back(item); @@ -29,6 +58,7 @@ void ItemList::add_icon_item(const Ref<Texture>& p_item,bool p_selectable){ item.selectable=p_selectable; item.selected=false; item.disabled=false; + item.tooltip_enabled=true; item.custom_bg=Color(0,0,0,0); items.push_back(item); @@ -54,6 +84,16 @@ String ItemList::get_item_text(int p_idx) const{ } +void ItemList::set_item_tooltip_enabled(int p_idx, const bool p_enabled) { + ERR_FAIL_INDEX(p_idx,items.size()); + items[p_idx].tooltip_enabled = p_enabled; +} + +bool ItemList::is_item_tooltip_enabled(int p_idx) const { + ERR_FAIL_INDEX_V(p_idx,items.size(), false); + return items[p_idx].tooltip_enabled; +} + void ItemList::set_item_tooltip(int p_idx,const String& p_tooltip){ ERR_FAIL_INDEX(p_idx,items.size()); @@ -163,7 +203,7 @@ void ItemList::set_item_disabled(int p_idx,bool p_disabled){ ERR_FAIL_INDEX(p_idx,items.size()); items[p_idx].disabled=p_disabled; - + update(); } @@ -197,7 +237,7 @@ void ItemList::select(int p_idx,bool p_single){ if (p_single || select_mode==SELECT_SINGLE) { - if (!items[p_idx].selectable) { + if (!items[p_idx].selectable || items[p_idx].disabled) { return; } @@ -209,7 +249,7 @@ void ItemList::select(int p_idx,bool p_single){ ensure_selected_visible=false; } else { - if (items[p_idx].selectable) { + if (items[p_idx].selectable && !items[p_idx].disabled) { items[p_idx].selected=true; } } @@ -308,6 +348,7 @@ void ItemList::clear(){ current=-1; ensure_selected_visible=false; update(); + shape_changed=true; defer_select_single=-1; } @@ -384,27 +425,16 @@ 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::set_max_icon_size(const Size2& p_size) { +void ItemList::set_fixed_icon_size(const Size2& p_size) { - max_icon_size=p_size; + fixed_icon_size=p_size; update(); } -Size2 ItemList::get_max_icon_size() const { +Size2 ItemList::get_fixed_icon_size() const { - return max_icon_size; + return fixed_icon_size; } Size2 ItemList::Item::get_icon_size() const { @@ -416,7 +446,7 @@ Size2 ItemList::Item::get_icon_size() const { return icon_region.size; } -void ItemList::_input_event(const InputEvent& p_event) { +void ItemList::_gui_input(const InputEvent& p_event) { if (defer_select_single>=0 && p_event.type==InputEvent::MOUSE_MOTION) { defer_select_single=-1; @@ -441,10 +471,9 @@ void ItemList::_input_event(const InputEvent& p_event) { Vector2 pos(mb.x,mb.y); Ref<StyleBox> bg = get_stylebox("bg"); pos-=bg->get_offset(); - pos.y+=scroll_bar->get_val(); + pos.y+=scroll_bar->get_value(); int closest = -1; - int closest_dist=0x7FFFFFFF; for(int i=0;i<items.size();i++) { @@ -457,12 +486,6 @@ void ItemList::_input_event(const InputEvent& p_event) { closest=i; break; } - - float dist = rc.distance_to(pos); - if (dist<closest_dist) { - closest=i; - closest_dist=dist; - } } if (closest!=-1) { @@ -493,7 +516,7 @@ void ItemList::_input_event(const InputEvent& p_event) { } } else { - if (!mb.doubleclick && !mb.mod.command && select_mode==SELECT_MULTI && items[i].selectable && items[i].selected && p_event.mouse_button.button_index==BUTTON_LEFT) { + if (!mb.doubleclick && !mb.mod.command && select_mode==SELECT_MULTI && items[i].selectable && !items[i].disabled && items[i].selected && p_event.mouse_button.button_index==BUTTON_LEFT) { defer_select_single=i; return; } @@ -529,16 +552,21 @@ void ItemList::_input_event(const InputEvent& p_event) { return; + } else { + Vector<int> sItems = get_selected_items(); + for(int i = 0; i < sItems.size(); i++) { + unselect(sItems[i]); + } } } 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 ); + scroll_bar->set_value( scroll_bar->get_value()-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 ); + scroll_bar->set_value( scroll_bar->get_value()+scroll_bar->get_page()/8 ); } @@ -550,7 +578,7 @@ void ItemList::_input_event(const InputEvent& p_event) { 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) { + if (diff<int(GlobalConfig::get_singleton()->get("gui/timers/incremental_search_max_interval_msec"))*2) { for(int i=current-1;i>=0;i--) { @@ -586,7 +614,7 @@ void ItemList::_input_event(const InputEvent& p_event) { 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) { + if (diff<int(GlobalConfig::get_singleton()->get("gui/timers/incremental_search_max_interval_msec"))*2) { for(int i=current+1;i<items.size();i++) { @@ -677,7 +705,7 @@ void ItemList::_input_event(const InputEvent& p_event) { if (select_mode==SELECT_MULTI && current>=0 && current<items.size()) { - if (items[current].selectable && !items[current].selected) { + if (items[current].selectable && !items[current].disabled && !items[current].selected) { select(current,false); emit_signal("multi_selected",current,true); } else if (items[current].selected) { @@ -697,7 +725,7 @@ void ItemList::_input_event(const InputEvent& p_event) { 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)); + uint64_t max_interval = uint64_t(GLOBAL_DEF("gui/timers/incremental_search_max_interval_msec",2000)); search_time_msec = now; if (diff>max_interval) { @@ -732,51 +760,21 @@ void ItemList::ensure_current_is_visible() { update(); } -static Size2 _adjust_to_max_size(Size2 p_size, Size2 p_max_size) { - - if (p_max_size.x<=0) - p_max_size.x=1e20; - if (p_max_size.y<=0) - p_max_size.y=1e20; - +static Rect2 _adjust_to_max_size(Size2 p_size, Size2 p_max_size) { - Size2 new_size; + Size2 size=p_max_size; + int tex_width = p_size.width * size.height / p_size.height; + int tex_height = size.height; - if (p_size.x > p_max_size.x) { - - new_size.width=p_max_size.x; - new_size.height=p_size.height * p_max_size.width / p_size.width; - - if (new_size.height > p_max_size.height) { - new_size=Size2(); //invalid - } + if (tex_width>size.width) { + tex_width=size.width; + tex_height=p_size.height * tex_width / p_size.width; } + int ofs_x=(size.width - tex_width)/2; + int ofs_y=(size.height - tex_height)/2; - if (p_size.y > p_max_size.y) { - - Size2 new_size2; - new_size2.height=p_max_size.y; - new_size2.width=p_size.width * p_max_size.height / p_size.height; - - if (new_size2.width < p_max_size.width) { - - if (new_size!=Size2()) { - - if (new_size2.x*new_size2.y > new_size.x*new_size.y) { - new_size=new_size2; - } - } else { - new_size=new_size2; - } - } - - } - - if (new_size==Size2()) - return p_size; - else - return new_size; + return Rect2(ofs_x,ofs_y,tex_width,tex_height); } @@ -790,7 +788,6 @@ void ItemList::_notification(int p_what) { 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; @@ -803,7 +800,10 @@ void ItemList::_notification(int p_what) { Size2 size = get_size(); float page = size.height-bg->get_minimum_size().height; - int width = size.width - mw - bg->get_minimum_size().width; + int width = size.width-bg->get_minimum_size().width; + if (scroll_bar->is_visible()){ + width-=mw+bg->get_margin(MARGIN_RIGHT); + } scroll_bar->set_page(page); draw_style_box(bg,Rect2(Point2(),size)); @@ -836,7 +836,7 @@ void ItemList::_notification(int p_what) { } if (shape_changed) { - + float max_column_width = 0; //1- compute item minimum sizes @@ -845,7 +845,11 @@ void ItemList::_notification(int p_what) { Size2 minsize; if (items[i].icon.is_valid()) { - minsize=_adjust_to_max_size(items[i].get_icon_size(),max_icon_size) * icon_scale; + if (fixed_icon_size.x>0 && fixed_icon_size.y>0) { + minsize=fixed_icon_size* icon_scale; + } else { + minsize=items[i].get_icon_size() *icon_scale; + } if (items[i].text!="") { if (icon_mode==ICON_MODE_TOP) { @@ -923,11 +927,11 @@ void ItemList::_notification(int p_what) { if (i<items.size()-1) separators.push_back(ofs.y+max_h+vseparation/2); - + for(int j=i;j>=0 && col>0;j--, col--) { items[j].rect_cache.size.y = max_h; } - + ofs.x=0; ofs.y+=max_h+vseparation; col=0; @@ -944,7 +948,7 @@ void ItemList::_notification(int p_what) { scroll_bar->set_max(max); //print_line("max: "+rtos(max)+" page "+rtos(page)); if (max<=page) { - scroll_bar->set_val(0); + scroll_bar->set_value(0); scroll_bar->hide(); } else { scroll_bar->show(); @@ -957,12 +961,28 @@ void ItemList::_notification(int p_what) { shape_changed=false; } + //ensure_selected_visible needs to be checked before we draw the list. + if (ensure_selected_visible && current>=0 && current <=items.size()) { + + Rect2 r = items[current].rect_cache; + int from = scroll_bar->get_value(); + int to = from + scroll_bar->get_page(); + + if (r.pos.y < from) { + scroll_bar->set_value(r.pos.y); + } else if (r.pos.y+r.size.y > to) { + scroll_bar->set_value(r.pos.y+r.size.y - (to-from)); + } + + } + + ensure_selected_visible=false; Vector2 base_ofs = bg->get_offset(); - base_ofs.y-=int(scroll_bar->get_val()); + base_ofs.y-=int(scroll_bar->get_value()); - Rect2 clip(Point2(),size-bg->get_minimum_size()+Vector2(0,scroll_bar->get_val())); + Rect2 clip(Point2(),size-bg->get_minimum_size()+Vector2(0,scroll_bar->get_value())); for(int i=0;i<items.size();i++) { @@ -1001,13 +1021,18 @@ void ItemList::_notification(int p_what) { Vector2 text_ofs; if (items[i].icon.is_valid()) { - Size2 icon_size = _adjust_to_max_size(items[i].get_icon_size(),max_icon_size) * icon_scale; + Size2 icon_size; + //= _adjust_to_max_size(items[i].get_icon_size(),fixed_icon_size) * icon_scale; + + if (fixed_icon_size.x>0 && fixed_icon_size.y>0) { + icon_size=fixed_icon_size* icon_scale; + } else { + icon_size=items[i].get_icon_size() *icon_scale; - Vector2 icon_ofs; - if (min_icon_size!=Vector2()) { - icon_ofs = (min_icon_size - icon_size)/2; } + Vector2 icon_ofs; + Point2 pos = items[i].rect_cache.pos + icon_ofs + base_ofs; if (icon_mode==ICON_MODE_TOP) { @@ -1017,18 +1042,30 @@ void ItemList::_notification(int p_what) { Math::floor((items[i].rect_cache.size.height - icon_size.height)/2), items[i].rect_cache.size.height - items[i].min_rect_cache.size.height ); - text_ofs.y = MAX(icon_size.height, min_icon_size.y) + icon_margin; + text_ofs.y = icon_size.height + icon_margin; text_ofs.y += items[i].rect_cache.size.height - items[i].min_rect_cache.size.height; } else { pos.y += Math::floor((items[i].rect_cache.size.height - icon_size.height)/2); - text_ofs.x = MAX(icon_size.width, min_icon_size.x) + icon_margin; + text_ofs.x = icon_size.width + icon_margin; + } + + Rect2 draw_rect=Rect2(pos,icon_size); + + if (fixed_icon_size.x>0 && fixed_icon_size.y>0) { + Rect2 adj = _adjust_to_max_size(items[i].get_icon_size() * icon_scale,icon_size); + draw_rect.pos+=adj.pos; + draw_rect.size=adj.size; } + Color modulate=Color(1,1,1,1); + if (items[i].disabled) + modulate.a*=0.5; + if (items[i].icon_region.has_no_area()) - draw_texture_rect(items[i].icon, Rect2(pos,icon_size) ); + draw_texture_rect(items[i].icon, draw_rect,false,modulate ); else - draw_texture_rect_region(items[i].icon, Rect2(pos, icon_size), items[i].icon_region); + draw_texture_rect_region(items[i].icon, draw_rect, items[i].icon_region,modulate); } @@ -1049,6 +1086,10 @@ void ItemList::_notification(int p_what) { else max_len=size.x; + Color modulate=items[i].selected?font_color_selected:font_color; + if (items[i].disabled) + modulate.a*=0.5; + if (icon_mode==ICON_MODE_TOP && max_text_lines>0) { int ss = items[i].text.length(); @@ -1086,7 +1127,7 @@ void ItemList::_notification(int p_what) { 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); + 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],modulate); } //special multiline mode @@ -1106,7 +1147,7 @@ void ItemList::_notification(int p_what) { 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); + draw_string(font,text_ofs,items[i].text,modulate,max_len+1); } @@ -1124,25 +1165,6 @@ void ItemList::_notification(int p_what) { 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); } - - - if (ensure_selected_visible && 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)); - } - - - } - - ensure_selected_visible=false; - } } @@ -1155,7 +1177,7 @@ int ItemList::get_item_at_pos(const Point2& p_pos, bool p_exact) const { Vector2 pos=p_pos; Ref<StyleBox> bg = get_stylebox("bg"); pos-=bg->get_offset(); - pos.y+=scroll_bar->get_val(); + pos.y+=scroll_bar->get_value(); int closest = -1; int closest_dist=0x7FFFFFFF; @@ -1187,6 +1209,9 @@ String ItemList::get_tooltip(const Point2& p_pos) const { int closest = get_item_at_pos(p_pos); if (closest!=-1) { + if (!items[closest].tooltip_enabled) { + return ""; + } if (items[closest].tooltip!="") { return items[closest].tooltip; } @@ -1199,8 +1224,11 @@ String ItemList::get_tooltip(const Point2& p_pos) const { } void ItemList::sort_items_by_text() { + items.sort(); update(); + shape_changed=true; + if (select_mode==SELECT_SINGLE) { for(int i=0;i<items.size();i++) { if (items[i].selected) { @@ -1241,81 +1269,98 @@ real_t ItemList::get_icon_scale() const { return icon_scale; } +Vector<int> ItemList::get_selected_items() { + Vector<int> selected; + for (int i = 0; i < items.size(); i++) { + if (items[i].selected) { + selected.push_back(i); + if (this->select_mode == SELECT_SINGLE) { + break; + } + } + } + return selected; +} + void ItemList::_bind_methods(){ - ObjectTypeDB::bind_method(_MD("add_item","text","icon:Texture","selectable"),&ItemList::add_item,DEFVAL(Variant()),DEFVAL(true)); - ObjectTypeDB::bind_method(_MD("add_icon_item","icon:Texture","selectable"),&ItemList::add_icon_item,DEFVAL(true)); + ClassDB::bind_method(_MD("add_item","text","icon:Texture","selectable"),&ItemList::add_item,DEFVAL(Variant()),DEFVAL(true)); + ClassDB::bind_method(_MD("add_icon_item","icon:Texture","selectable"),&ItemList::add_icon_item,DEFVAL(true)); + + ClassDB::bind_method(_MD("set_item_text","idx","text"),&ItemList::set_item_text); + ClassDB::bind_method(_MD("get_item_text","idx"),&ItemList::get_item_text); - 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); + ClassDB::bind_method(_MD("set_item_icon","idx","icon:Texture"),&ItemList::set_item_icon); + ClassDB::bind_method(_MD("get_item_icon:Texture","idx"),&ItemList::get_item_icon); - ObjectTypeDB::bind_method(_MD("set_item_icon","idx","icon:Texture"),&ItemList::set_item_icon); - ObjectTypeDB::bind_method(_MD("get_item_icon:Texture","idx"),&ItemList::get_item_icon); + ClassDB::bind_method(_MD("set_item_icon_region","idx","rect"),&ItemList::set_item_icon_region); + ClassDB::bind_method(_MD("get_item_icon_region","idx"),&ItemList::get_item_icon_region); - ObjectTypeDB::bind_method(_MD("set_item_icon_region","idx","rect"),&ItemList::set_item_icon_region); - ObjectTypeDB::bind_method(_MD("get_item_icon_region","idx"),&ItemList::get_item_icon_region); + ClassDB::bind_method(_MD("set_item_selectable","idx","selectable"),&ItemList::set_item_selectable); + ClassDB::bind_method(_MD("is_item_selectable","idx"),&ItemList::is_item_selectable); - 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); + ClassDB::bind_method(_MD("set_item_disabled","idx","disabled"),&ItemList::set_item_disabled); + ClassDB::bind_method(_MD("is_item_disabled","idx"),&ItemList::is_item_disabled); - 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); + ClassDB::bind_method(_MD("set_item_metadata","idx","metadata"),&ItemList::set_item_metadata); + ClassDB::bind_method(_MD("get_item_metadata","idx"),&ItemList::get_item_metadata); - 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); + ClassDB::bind_method(_MD("set_item_custom_bg_color","idx","custom_bg_color"),&ItemList::set_item_custom_bg_color); + ClassDB::bind_method(_MD("get_item_custom_bg_color","idx"),&ItemList::get_item_custom_bg_color); - 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); + ClassDB::bind_method(_MD("set_item_tooltip_enabled","idx","enable"),&ItemList::set_item_tooltip_enabled); + ClassDB::bind_method(_MD("is_item_tooltip_enabled","idx"),&ItemList::is_item_tooltip_enabled); - 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); + ClassDB::bind_method(_MD("set_item_tooltip","idx","tooltip"),&ItemList::set_item_tooltip); + ClassDB::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); + ClassDB::bind_method(_MD("select","idx","single"),&ItemList::select,DEFVAL(true)); + ClassDB::bind_method(_MD("unselect","idx"),&ItemList::unselect); + ClassDB::bind_method(_MD("is_selected","idx"),&ItemList::is_selected); + ClassDB::bind_method(_MD("get_selected_items"),&ItemList::get_selected_items); - ObjectTypeDB::bind_method(_MD("get_item_count"),&ItemList::get_item_count); - ObjectTypeDB::bind_method(_MD("remove_item","idx"),&ItemList::remove_item); + ClassDB::bind_method(_MD("get_item_count"),&ItemList::get_item_count); + ClassDB::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); + ClassDB::bind_method(_MD("clear"),&ItemList::clear); + ClassDB::bind_method(_MD("sort_items_by_text"),&ItemList::sort_items_by_text); - 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); + ClassDB::bind_method(_MD("set_fixed_column_width","width"),&ItemList::set_fixed_column_width); + ClassDB::bind_method(_MD("get_fixed_column_width"),&ItemList::get_fixed_column_width); - ObjectTypeDB::bind_method(_MD("set_same_column_width","enable"),&ItemList::set_same_column_width); - ObjectTypeDB::bind_method(_MD("is_same_column_width"),&ItemList::is_same_column_width); + ClassDB::bind_method(_MD("set_same_column_width","enable"),&ItemList::set_same_column_width); + ClassDB::bind_method(_MD("is_same_column_width"),&ItemList::is_same_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); + ClassDB::bind_method(_MD("set_max_text_lines","lines"),&ItemList::set_max_text_lines); + ClassDB::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); + ClassDB::bind_method(_MD("set_max_columns","amount"),&ItemList::set_max_columns); + ClassDB::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); + ClassDB::bind_method(_MD("set_select_mode","mode"),&ItemList::set_select_mode); + ClassDB::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); + ClassDB::bind_method(_MD("set_icon_mode","mode"),&ItemList::set_icon_mode); + ClassDB::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("set_max_icon_size","size"),&ItemList::set_max_icon_size); - ObjectTypeDB::bind_method(_MD("get_max_icon_size"),&ItemList::get_max_icon_size); + ClassDB::bind_method(_MD("set_fixed_icon_size","size"),&ItemList::set_fixed_icon_size); + ClassDB::bind_method(_MD("get_fixed_icon_size"),&ItemList::get_fixed_icon_size); - ObjectTypeDB::bind_method(_MD("set_icon_scale","scale"),&ItemList::set_icon_scale); - ObjectTypeDB::bind_method(_MD("get_icon_scale"),&ItemList::get_icon_scale); + ClassDB::bind_method(_MD("set_icon_scale","scale"),&ItemList::set_icon_scale); + ClassDB::bind_method(_MD("get_icon_scale"),&ItemList::get_icon_scale); - ObjectTypeDB::bind_method(_MD("set_allow_rmb_select","allow"),&ItemList::set_allow_rmb_select); - ObjectTypeDB::bind_method(_MD("get_allow_rmb_select"),&ItemList::get_allow_rmb_select); + ClassDB::bind_method(_MD("set_allow_rmb_select","allow"),&ItemList::set_allow_rmb_select); + ClassDB::bind_method(_MD("get_allow_rmb_select"),&ItemList::get_allow_rmb_select); - ObjectTypeDB::bind_method(_MD("get_item_at_pos","pos","exact"),&ItemList::get_item_at_pos,DEFVAL(false)); + ClassDB::bind_method(_MD("get_item_at_pos","pos","exact"),&ItemList::get_item_at_pos,DEFVAL(false)); - ObjectTypeDB::bind_method(_MD("ensure_current_is_visible"),&ItemList::ensure_current_is_visible); + ClassDB::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); + ClassDB::bind_method(_MD("get_v_scroll"),&ItemList::get_v_scroll); + + ClassDB::bind_method(_MD("_scroll_changed"),&ItemList::_scroll_changed); + ClassDB::bind_method(_MD("_gui_input"),&ItemList::_gui_input); BIND_CONSTANT( ICON_MODE_TOP ); BIND_CONSTANT( ICON_MODE_LEFT ); @@ -1326,9 +1371,9 @@ void ItemList::_bind_methods(){ ADD_SIGNAL( MethodInfo("item_rmb_selected",PropertyInfo(Variant::INT,"index"),PropertyInfo(Variant::VECTOR2,"atpos"))); ADD_SIGNAL( MethodInfo("multi_selected",PropertyInfo(Variant::INT,"index"),PropertyInfo(Variant::BOOL,"selected"))); ADD_SIGNAL( MethodInfo("item_activated",PropertyInfo(Variant::INT,"index"))); -} - + GLOBAL_DEF("gui/timers/incremental_search_max_interval_msec",2000); +} ItemList::ItemList() { @@ -1356,9 +1401,9 @@ ItemList::ItemList() { allow_rmb_select=false; icon_scale = 1.0f; + set_clip_contents(true); } ItemList::~ItemList() { } - diff --git a/scene/gui/item_list.h b/scene/gui/item_list.h index 087c585128..f4a864c782 100644 --- a/scene/gui/item_list.h +++ b/scene/gui/item_list.h @@ -1,3 +1,31 @@ +/*************************************************************************/ +/* item_list.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2017 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 */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ #ifndef ITEMLIST_H #define ITEMLIST_H @@ -6,7 +34,7 @@ class ItemList : public Control { - OBJ_TYPE( ItemList, Control ); + GDCLASS( ItemList, Control ); public: enum IconMode { @@ -28,6 +56,7 @@ private: bool selectable; bool selected; bool disabled; + bool tooltip_enabled; Variant metadata; String tooltip; Color custom_bg; @@ -62,8 +91,7 @@ private: int max_text_lines; int max_columns; - Size2 min_icon_size; - Size2 max_icon_size; + Size2 fixed_icon_size; Size2 max_item_size_cache; @@ -74,7 +102,9 @@ private: real_t icon_scale; void _scroll_changed(double); - void _input_event(const InputEvent& p_event); + void _gui_input(const InputEvent& p_event); + + protected: void _notification(int p_what); @@ -106,6 +136,9 @@ public: 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_enabled(int p_idx, const bool p_enabled); + bool is_item_tooltip_enabled(int p_idx) const; + void set_item_tooltip(int p_idx,const String& p_tooltip); String get_item_tooltip(int p_idx) const; @@ -115,6 +148,7 @@ public: void select(int p_idx,bool p_single=true); void unselect(int p_idx); bool is_selected(int p_idx) const; + Vector<int> get_selected_items(); void set_current(int p_current); int get_current() const; @@ -144,11 +178,8 @@ public: 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 set_max_icon_size(const Size2& p_size); - Size2 get_max_icon_size() const; + void set_fixed_icon_size(const Size2& p_size); + Size2 get_fixed_icon_size() const; void set_allow_rmb_select(bool p_allow); bool get_allow_rmb_select() const; @@ -164,6 +195,8 @@ public: void set_icon_scale(real_t p_scale); real_t get_icon_scale() const; + VScrollBar *get_v_scroll() { return scroll_bar; } + ItemList(); ~ItemList(); }; diff --git a/scene/gui/label.cpp b/scene/gui/label.cpp index 09c6a77b42..cd500a62bc 100644 --- a/scene/gui/label.cpp +++ b/scene/gui/label.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 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 */ @@ -68,10 +68,18 @@ int Label::get_line_height() const { void Label::_notification(int p_what) { + if (p_what==NOTIFICATION_TRANSLATION_CHANGED) { + + xl_text=XL_MESSAGE(text); + minimum_size_changed(); + update(); + } + if (p_what==NOTIFICATION_DRAW) { - if (clip || autowrap) + if (clip || autowrap) { VisualServer::get_singleton()->canvas_item_set_clip(get_canvas_item(),true); + } if (word_cache_dirty) regenerate_word_cache(); @@ -85,14 +93,16 @@ void Label::_notification(int p_what) { Ref<Font> font = get_font("font"); Color font_color = get_color("font_color"); Color font_color_shadow = get_color("font_color_shadow"); - bool use_outlinde = get_constant("shadow_as_outline"); + bool use_outline = get_constant("shadow_as_outline"); Point2 shadow_ofs(get_constant("shadow_offset_x"),get_constant("shadow_offset_y")); int line_spacing = get_constant("line_spacing"); VisualServer::get_singleton()->canvas_item_set_distance_field_mode(get_canvas_item(),font.is_valid() && font->is_distance_field_hint()); int font_h = font->get_height()+line_spacing; - int lines_visible = size.y/font_h; + + int lines_visible = (size.y+line_spacing)/font_h; + int space_w=font->get_char_size(' ').width; int chars_total=0; @@ -116,19 +126,19 @@ void Label::_notification(int p_what) { //nothing } break; case VALIGN_CENTER: { - vbegin=(size.y - lines_visible * font_h) / 2; + vbegin=(size.y - (lines_visible * font_h - line_spacing)) / 2; vsep=0; } break; case VALIGN_BOTTOM: { - vbegin=size.y - lines_visible * font_h; + vbegin=size.y - (lines_visible * font_h - line_spacing); vsep=0; } break; case VALIGN_FILL: { vbegin=0; if (lines_visible>1) { - vsep=(size.y - lines_visible * font_h) / (lines_visible - 1); + vsep=(size.y - (lines_visible * font_h - line_spacing)) / (lines_visible - 1); } else { vsep=0; } @@ -142,7 +152,6 @@ void Label::_notification(int p_what) { if (!wc) return; - int c = 0; int line=0; int line_to=lines_skipped + (lines_visible>0?lines_visible:1); while(wc) { @@ -238,15 +247,15 @@ void Label::_notification(int p_what) { for (int i=0;i<from->word_len;i++) { if (visible_chars < 0 || chars_total_shadow<visible_chars) { - CharType c = text[i+pos]; - CharType n = text[i+pos+1]; + CharType c = xl_text[i+pos]; + CharType n = xl_text[i+pos+1]; if (uppercase) { c=String::char_uppercase(c); n=String::char_uppercase(c); } float move=font->draw_char(ci, Point2( x_ofs_shadow, y_ofs )+shadow_ofs, c, n,font_color_shadow ); - if (use_outlinde) { + if (use_outline) { font->draw_char(ci, Point2( x_ofs_shadow, y_ofs )+Vector2(-shadow_ofs.x,shadow_ofs.y), c, n,font_color_shadow ); font->draw_char(ci, Point2( x_ofs_shadow, y_ofs )+Vector2(shadow_ofs.x,-shadow_ofs.y), c, n,font_color_shadow ); font->draw_char(ci, Point2( x_ofs_shadow, y_ofs )+Vector2(-shadow_ofs.x,-shadow_ofs.y), c, n,font_color_shadow ); @@ -261,8 +270,8 @@ 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]; + CharType c = xl_text[i+pos]; + CharType n = xl_text[i+pos+1]; if (uppercase) { c=String::char_uppercase(c); n=String::char_uppercase(c); @@ -317,9 +326,9 @@ int Label::get_longest_line_width() const { int max_line_width=0; int line_width=0; - for (int i=0;i<text.size();i++) { + for (int i=0;i<xl_text.size();i++) { - CharType current=text[i]; + CharType current=xl_text[i]; if (uppercase) current=String::char_uppercase(current); @@ -333,7 +342,7 @@ int Label::get_longest_line_width() const { } } else { - int char_width=font->get_char_size(current).width; + int char_width=font->get_char_size(current,xl_text[i+1]).width; line_width+=char_width; } @@ -355,6 +364,21 @@ int Label::get_line_count() const { return line_count; } +int Label::get_visible_line_count() const { + + int line_spacing = get_constant("line_spacing"); + int font_h = get_font("font")->get_height()+line_spacing; + int lines_visible = (get_size().y+line_spacing)/font_h; + + if (lines_visible > line_count) + lines_visible = line_count; + + if (max_lines_visible >= 0 && lines_visible > max_lines_visible) + lines_visible = max_lines_visible; + + return lines_visible; +} + void Label::regenerate_word_cache() { while (word_cache) { @@ -379,9 +403,9 @@ void Label::regenerate_word_cache() { WordCache *last=NULL; - for (int i=0;i<text.size()+1;i++) { + for (int i=0;i<xl_text.size()+1;i++) { - CharType current=i<text.length()?text[i]:' '; //always a space at the end, so the algo works + CharType current=i<xl_text.length()?xl_text[i]:' '; //always a space at the end, so the algo works if (uppercase) current=String::char_uppercase(current); @@ -421,7 +445,7 @@ void Label::regenerate_word_cache() { total_char_cache++; } - if (i<text.length() && text[i] == ' ') { + if (i<xl_text.length() && xl_text[i] == ' ') { total_char_cache--; // do not count spaces if (line_width > 0 || last==NULL || last->char_pos!=WordCache::CHAR_WRAPLINE) { space_count++; @@ -438,7 +462,7 @@ void Label::regenerate_word_cache() { word_pos=i; } - char_width=font->get_char_size(current).width; + char_width=font->get_char_size(current,xl_text[i+1]).width; current_word_size+=char_width; line_width+=char_width; total_char_cache++; @@ -488,9 +512,9 @@ void Label::regenerate_word_cache() { if (!autowrap) { minsize.width=width; if (max_lines_visible > 0 && line_count > max_lines_visible) { - minsize.height=(font->get_height()+line_spacing)*max_lines_visible; + minsize.height=(font->get_height() * max_lines_visible) + (line_spacing * (max_lines_visible - 1)); } else { - minsize.height=(font->get_height()+line_spacing)*line_count; + minsize.height=(font->get_height() * line_count)+(line_spacing * (line_count - 1)); } } @@ -524,17 +548,18 @@ Label::VAlign Label::get_valign() const{ void Label::set_text(const String& p_string) { - String str = XL_MESSAGE(p_string); - if (text==str) + if (text==p_string) return; - - text=str; + text=p_string; + xl_text=XL_MESSAGE(p_string); word_cache_dirty=true; if (percent_visible<1) visible_chars=get_total_character_count()*percent_visible; update(); - minimum_size_changed(); + if (!autowrap) { + minimum_size_changed(); + } } @@ -623,29 +648,30 @@ int Label::get_total_character_count() const { void Label::_bind_methods() { - ObjectTypeDB::bind_method(_MD("set_align","align"),&Label::set_align); - ObjectTypeDB::bind_method(_MD("get_align"),&Label::get_align); - ObjectTypeDB::bind_method(_MD("set_valign","valign"),&Label::set_valign); - ObjectTypeDB::bind_method(_MD("get_valign"),&Label::get_valign); - ObjectTypeDB::bind_method(_MD("set_text","text"),&Label::set_text); - ObjectTypeDB::bind_method(_MD("get_text"),&Label::get_text); - ObjectTypeDB::bind_method(_MD("set_autowrap","enable"),&Label::set_autowrap); - ObjectTypeDB::bind_method(_MD("has_autowrap"),&Label::has_autowrap); - ObjectTypeDB::bind_method(_MD("set_clip_text","enable"),&Label::set_clip_text); - ObjectTypeDB::bind_method(_MD("is_clipping_text"),&Label::is_clipping_text); - ObjectTypeDB::bind_method(_MD("set_uppercase","enable"),&Label::set_uppercase); - ObjectTypeDB::bind_method(_MD("is_uppercase"),&Label::is_uppercase); - ObjectTypeDB::bind_method(_MD("get_line_height"),&Label::get_line_height); - ObjectTypeDB::bind_method(_MD("get_line_count"),&Label::get_line_count); - ObjectTypeDB::bind_method(_MD("get_total_character_count"),&Label::get_total_character_count); - ObjectTypeDB::bind_method(_MD("set_visible_characters","amount"),&Label::set_visible_characters); - ObjectTypeDB::bind_method(_MD("get_visible_characters"),&Label::get_visible_characters); - ObjectTypeDB::bind_method(_MD("set_percent_visible","percent_visible"),&Label::set_percent_visible); - ObjectTypeDB::bind_method(_MD("get_percent_visible"),&Label::get_percent_visible); - ObjectTypeDB::bind_method(_MD("set_lines_skipped","lines_skipped"),&Label::set_lines_skipped); - ObjectTypeDB::bind_method(_MD("get_lines_skipped"),&Label::get_lines_skipped); - ObjectTypeDB::bind_method(_MD("set_max_lines_visible","lines_visible"),&Label::set_max_lines_visible); - ObjectTypeDB::bind_method(_MD("get_max_lines_visible"),&Label::get_max_lines_visible); + ClassDB::bind_method(_MD("set_align","align"),&Label::set_align); + ClassDB::bind_method(_MD("get_align"),&Label::get_align); + ClassDB::bind_method(_MD("set_valign","valign"),&Label::set_valign); + ClassDB::bind_method(_MD("get_valign"),&Label::get_valign); + ClassDB::bind_method(_MD("set_text","text"),&Label::set_text); + ClassDB::bind_method(_MD("get_text"),&Label::get_text); + ClassDB::bind_method(_MD("set_autowrap","enable"),&Label::set_autowrap); + ClassDB::bind_method(_MD("has_autowrap"),&Label::has_autowrap); + ClassDB::bind_method(_MD("set_clip_text","enable"),&Label::set_clip_text); + ClassDB::bind_method(_MD("is_clipping_text"),&Label::is_clipping_text); + ClassDB::bind_method(_MD("set_uppercase","enable"),&Label::set_uppercase); + ClassDB::bind_method(_MD("is_uppercase"),&Label::is_uppercase); + ClassDB::bind_method(_MD("get_line_height"),&Label::get_line_height); + ClassDB::bind_method(_MD("get_line_count"),&Label::get_line_count); + ClassDB::bind_method(_MD("get_visible_line_count"),&Label::get_visible_line_count); + ClassDB::bind_method(_MD("get_total_character_count"),&Label::get_total_character_count); + ClassDB::bind_method(_MD("set_visible_characters","amount"),&Label::set_visible_characters); + ClassDB::bind_method(_MD("get_visible_characters"),&Label::get_visible_characters); + ClassDB::bind_method(_MD("set_percent_visible","percent_visible"),&Label::set_percent_visible); + ClassDB::bind_method(_MD("get_percent_visible"),&Label::get_percent_visible); + ClassDB::bind_method(_MD("set_lines_skipped","lines_skipped"),&Label::set_lines_skipped); + ClassDB::bind_method(_MD("get_lines_skipped"),&Label::get_lines_skipped); + ClassDB::bind_method(_MD("set_max_lines_visible","lines_visible"),&Label::set_max_lines_visible); + ClassDB::bind_method(_MD("get_max_lines_visible"),&Label::get_max_lines_visible); BIND_CONSTANT( ALIGN_LEFT ); BIND_CONSTANT( ALIGN_CENTER ); @@ -673,14 +699,14 @@ Label::Label(const String &p_text) { align=ALIGN_LEFT; valign=VALIGN_TOP; - text=""; + xl_text=""; word_cache=NULL; word_cache_dirty=true; autowrap=false; line_count=0; set_v_size_flags(0); clip=false; - set_ignore_mouse(true); + set_mouse_filter(MOUSE_FILTER_IGNORE); total_char_cache=0; visible_chars=-1; percent_visible=1; diff --git a/scene/gui/label.h b/scene/gui/label.h index 3c14add60d..80e4c970f6 100644 --- a/scene/gui/label.h +++ b/scene/gui/label.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 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 */ @@ -35,7 +35,7 @@ */ class Label : public Control { - OBJ_TYPE( Label, Control ); + GDCLASS( Label, Control ); public: enum Align { @@ -58,6 +58,7 @@ private: Align align; VAlign valign; String text; + String xl_text; bool autowrap; bool clip; Size2 minsize; @@ -132,6 +133,7 @@ public: int get_line_height() const; int get_line_count() const; + int get_visible_line_count() const; Label(const String& p_text=String()); ~Label(); diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp index 14dac454bd..3a72e0e445 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-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 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,8 +31,17 @@ #include "os/os.h" #include "print_string.h" #include "label.h" +#include "translation.h" +#ifdef TOOLS_ENABLED +#include "tools/editor/editor_settings.h" +#endif -void LineEdit::_input_event(InputEvent p_event) { +static bool _is_text_char(CharType c) { + + return (c>='a' && c<='z') || (c>='A' && c<='Z') || (c>='0' && c<='9') || c=='_'; +} + +void LineEdit::_gui_input(InputEvent p_event) { switch(p_event.type) { @@ -52,32 +61,41 @@ void LineEdit::_input_event(InputEvent p_event) { if (b.button_index!=BUTTON_LEFT) break; + _reset_caret_blink_timer(); if (b.pressed) { + shift_selection_check_pre(b.mod.shift); + set_cursor_at_pixel_pos(b.x); - if (b.doubleclick) { + if (b.mod.shift) { - selection.enabled=true; - selection.begin=0; - selection.end=text.length(); - selection.doubleclick=true; - } + selection_fill_at_cursor(); + selection.creating=true; - selection.drag_attempt=false; + } else { - if ((cursor_pos<selection.begin) || (cursor_pos>selection.end) || !selection.enabled) { + if (b.doubleclick) { - selection_clear(); - selection.cursor_start=cursor_pos; - selection.creating=true; - } else if (selection.enabled) { + selection.enabled=true; + selection.begin=0; + selection.end=text.length(); + selection.doubleclick=true; + } + + selection.drag_attempt=false; + + if ((cursor_pos<selection.begin) || (cursor_pos>selection.end) || !selection.enabled) { - selection.drag_attempt=true; + selection_clear(); + selection.cursor_start=cursor_pos; + selection.creating=true; + } else if (selection.enabled) { + + selection.drag_attempt=true; + } } - // if (!editable) - // non_editable_clicked_signal.call(); update(); } else { @@ -89,7 +107,7 @@ void LineEdit::_input_event(InputEvent p_event) { selection.doubleclick=false; if (OS::get_singleton()->has_virtual_keyboard()) - OS::get_singleton()->show_virtual_keyboard(get_text(),get_global_rect()); + OS::get_singleton()->show_virtual_keyboard(text,get_global_rect()); } update(); @@ -98,7 +116,7 @@ void LineEdit::_input_event(InputEvent p_event) { const InputEventMouseMotion& m=p_event.mouse_motion; - if (m.button_mask&1) { + if (m.button_mask&BUTTON_LEFT) { if (selection.creating) { set_cursor_at_pixel_pos(m.x); @@ -124,7 +142,7 @@ void LineEdit::_input_event(InputEvent p_event) { case (KEY_X): { // CUT - if(k.mod.command && editable) { + if(editable) { cut_text(); } @@ -132,15 +150,13 @@ void LineEdit::_input_event(InputEvent p_event) { case (KEY_C): { // COPY - if(k.mod.command) { - copy_text(); - } + copy_text(); } break; case (KEY_V): { // PASTE - if(k.mod.command && editable) { + if(editable) { paste_text(); } @@ -149,7 +165,7 @@ void LineEdit::_input_event(InputEvent p_event) { case (KEY_Z): { // Simple One level undo - if( k.mod.command && editable) { + if(editable) { undo(); @@ -160,7 +176,7 @@ void LineEdit::_input_event(InputEvent p_event) { case (KEY_U): { // Delete from start to cursor - if( k.mod.command && editable) { + if(editable) { selection_clear(); undo_text = text; @@ -175,8 +191,8 @@ void LineEdit::_input_event(InputEvent p_event) { } set_cursor_pos(0); - emit_signal("text_changed",text); - _change_notify("text"); + _text_changed(); + } @@ -184,7 +200,7 @@ void LineEdit::_input_event(InputEvent p_event) { case (KEY_Y): { // PASTE (Yank for unix users) - if(k.mod.command && editable) { + if(editable) { paste_text(); } @@ -192,13 +208,12 @@ void LineEdit::_input_event(InputEvent p_event) { } break; case (KEY_K): { // Delete from cursor_pos to end - if(k.mod.command && editable) { + if(editable) { selection_clear(); undo_text = text; text = text.substr(0,cursor_pos); - emit_signal("text_changed",text); - _change_notify("text"); + _text_changed(); } } break; @@ -214,8 +229,8 @@ void LineEdit::_input_event(InputEvent p_event) { } } - - if (!k.mod.alt && !k.mod.meta && !k.mod.command) { + _reset_caret_blink_timer(); + if (!k.mod.meta) { bool handled=true; switch (code) { @@ -232,13 +247,45 @@ void LineEdit::_input_event(InputEvent p_event) { case KEY_BACKSPACE: { - if (editable) { - undo_text = text; - if (selection.enabled) - selection_delete(); - else - delete_char(); + if (!editable) + break; + + if (selection.enabled) { + undo_text=text; + selection_delete(); + break; + } + +#ifdef APPLE_STYLE_KEYS + if (k.mod.alt) { +#else + if (k.mod.alt) { + handled=false; + break; + } else if (k.mod.command) { +#endif + int cc=cursor_pos; + bool prev_char=false; + + while (cc>0) { + bool ischar=_is_text_char(text[cc-1]); + + if (prev_char && !ischar) + break; + + prev_char=ischar; + cc--; + } + + delete_text(cc, cursor_pos); + + set_cursor_pos(cc); + + } else { + undo_text=text; + delete_char(); } + } break; case KEY_KP_4: { if (k.unicode != 0) { @@ -248,8 +295,42 @@ void LineEdit::_input_event(InputEvent p_event) { // numlock disabled. fallthrough to key_left } case KEY_LEFT: { + +#ifndef APPLE_STYLE_KEYS + if (!k.mod.alt) +#endif shift_selection_check_pre(k.mod.shift); - set_cursor_pos(get_cursor_pos()-1); + +#ifdef APPLE_STYLE_KEYS + if (k.mod.command) { + set_cursor_pos(0); + } else if (k.mod.alt) { + +#else + if (k.mod.alt) { + handled=false; + break; + } else if (k.mod.command) { +#endif + bool prev_char=false; + int cc=cursor_pos; + + while (cc>0) { + bool ischar=_is_text_char(text[cc-1]); + + if (prev_char && !ischar) + break; + + prev_char=ischar; + cc--; + } + + set_cursor_pos(cc); + + } else { + set_cursor_pos(get_cursor_pos()-1); + } + shift_selection_check_post(k.mod.shift); } break; @@ -263,25 +344,88 @@ void LineEdit::_input_event(InputEvent p_event) { case KEY_RIGHT: { shift_selection_check_pre(k.mod.shift); - set_cursor_pos(get_cursor_pos()+1); + +#ifdef APPLE_STYLE_KEYS + if (k.mod.command) { + set_cursor_pos(text.length()); + } else if (k.mod.alt) { +#else + if (k.mod.alt) { + handled=false; + break; + } else if (k.mod.command) { +#endif + bool prev_char=false; + int cc=cursor_pos; + + while (cc<text.length()) { + bool ischar=_is_text_char(text[cc]); + + if (prev_char && !ischar) + break; + + prev_char=ischar; + cc++; + } + + set_cursor_pos(cc); + + } else { + set_cursor_pos(get_cursor_pos()+1); + } + shift_selection_check_post(k.mod.shift); + } break; case KEY_DELETE: { - if (k.mod.shift && !k.mod.command && !k.mod.alt && editable) { + if (!editable) + break; + + if (k.mod.shift && !k.mod.command && !k.mod.alt) { cut_text(); break; } - if (editable) { - undo_text = text; - if (selection.enabled) - selection_delete(); - else if (cursor_pos<text.length()) { + if (selection.enabled) { + undo_text=text; + selection_delete(); + break; + } + + int text_len = text.length(); + + if (cursor_pos==text_len) + break; // nothing to do + +#ifdef APPLE_STYLE_KEYS + if (k.mod.alt) { +#else + if (k.mod.alt) { + handled=false; + break; + } else if (k.mod.command) { +#endif + int cc=cursor_pos; + + bool prev_char=false; + + while (cc<text.length()) { - set_cursor_pos(get_cursor_pos()+1); - delete_char(); + bool ischar=_is_text_char(text[cc]); + + if (prev_char && !ischar) + break; + prev_char=ischar; + cc++; } + + delete_text(cursor_pos,cc); + + } else { + undo_text=text; + set_cursor_pos(cursor_pos+1); + delete_char(); } } break; @@ -321,16 +465,14 @@ void LineEdit::_input_event(InputEvent p_event) { if (handled) { accept_event(); - } else { + } else if (!k.mod.alt && !k.mod.command) { if (k.unicode>=32 && k.scancode!=KEY_DELETE) { if (editable) { selection_delete(); CharType ucodestr[2]={(CharType)k.unicode,0}; append_at_cursor(ucodestr); - emit_signal("text_changed",text); - _change_notify("text"); - + _text_changed(); accept_event(); } @@ -339,8 +481,6 @@ void LineEdit::_input_event(InputEvent p_event) { } } - - selection.old_shift=k.mod.shift; update(); } @@ -406,14 +546,39 @@ void LineEdit::drop_data(const Point2& p_point,const Variant& p_data){ void LineEdit::_notification(int p_what) { switch(p_what) { - +#ifdef TOOLS_ENABLED + case NOTIFICATION_ENTER_TREE: { + if (get_tree()->is_editor_hint()) { + cursor_set_blink_enabled(EDITOR_DEF("text_editor/cursor/caret_blink", false)); + cursor_set_blink_speed(EDITOR_DEF("text_editor/cursor/caret_blink_speed", 0.65)); + + if (!EditorSettings::get_singleton()->is_connected("settings_changed",this,"_editor_settings_changed")) { + EditorSettings::get_singleton()->connect("settings_changed",this,"_editor_settings_changed"); + } + } + } break; +#endif case NOTIFICATION_RESIZED: { set_cursor_pos( get_cursor_pos() ); } break; + case MainLoop::NOTIFICATION_WM_FOCUS_IN: { + window_has_focus = true; + draw_caret = true; + update(); + } break; + case MainLoop::NOTIFICATION_WM_FOCUS_OUT: { + window_has_focus = false; + draw_caret = false; + update(); + } break; case NOTIFICATION_DRAW: { + if ((!has_focus() && !menu->has_focus()) || !window_has_focus) { + draw_caret = false; + } + int width,height; Size2 size=get_size(); @@ -446,11 +611,11 @@ void LineEdit::_notification(int p_what) { } break; case ALIGN_CENTER: { - x_ofs=x_ofs=int(size.width-(cached_width))/2; + x_ofs=int(size.width-(cached_width))/2; } break; case ALIGN_RIGHT: { - x_ofs=x_ofs=int(size.width-style->get_offset().x-(cached_width)); + x_ofs=int(size.width-style->get_offset().x-(cached_width)); } break; } @@ -467,14 +632,20 @@ void LineEdit::_notification(int p_what) { Color font_color_selected=get_color("font_color_selected"); Color cursor_color=get_color("cursor_color"); + const String& t = text.empty() ? placeholder : text; + // draw placeholder color + if(text.empty()) + font_color.a *= placeholder_alpha; + + int caret_height = font->get_height() > y_area ? y_area : font->get_height(); while(true) { //end of string, break! - if (char_ofs>=text.length()) + if (char_ofs>=t.length()) break; - CharType cchar=pass?'*':text[char_ofs]; - CharType next=pass?'*':text[char_ofs+1]; + CharType cchar=pass?'*':t[char_ofs]; + CharType next=pass?'*':t[char_ofs+1]; int char_width=font->get_char_size( cchar,next ).width; // end of widget, break! @@ -485,28 +656,33 @@ void LineEdit::_notification(int p_what) { bool selected=selection.enabled && char_ofs>=selection.begin && char_ofs<selection.end; if (selected) - VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2(x_ofs, y_ofs), Size2(char_width, y_area)), selection_color); + VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2(x_ofs, y_ofs), Size2(char_width, caret_height)), selection_color); font->draw_char(ci, Point2(x_ofs, y_ofs + font_ascent), cchar, next, selected ? font_color_selected : font_color); - if (char_ofs==cursor_pos && has_focus()) + if (char_ofs==cursor_pos && draw_caret) { VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2( - Point2( x_ofs , y_ofs ), Size2( 1, y_area ) ), cursor_color ); + Point2( x_ofs , y_ofs ), Size2( 1, caret_height ) ), cursor_color ); + } x_ofs+=char_width; char_ofs++; } - if (char_ofs==cursor_pos && has_focus()) //may be at the end + if (char_ofs==cursor_pos && draw_caret) {//may be at the end VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2( - Point2( x_ofs , y_ofs ), Size2( 1, y_area ) ), cursor_color ); - + Point2( x_ofs , y_ofs ), Size2( 1, caret_height ) ), cursor_color ); + } } break; case NOTIFICATION_FOCUS_ENTER: { + if (!caret_blink_enabled) { + draw_caret = true; + } + if (OS::get_singleton()->has_virtual_keyboard()) - OS::get_singleton()->show_virtual_keyboard(get_text(),get_global_rect()); + OS::get_singleton()->show_virtual_keyboard(text,get_global_rect()); } break; case NOTIFICATION_FOCUS_EXIT: { @@ -545,8 +721,7 @@ void LineEdit::paste_text() { if(selection.enabled) selection_delete(); append_at_cursor(paste_buffer); - emit_signal("text_changed",text); - _change_notify("text"); + _text_changed(); } @@ -570,14 +745,12 @@ void LineEdit::undo() { set_cursor_pos(old_cursor_pos); } - emit_signal("text_changed",text); - _change_notify("text"); - + _text_changed(); } void LineEdit::shift_selection_check_pre(bool p_shift) { - if (!selection.old_shift && p_shift) { + if (!selection.enabled && p_shift) { selection.cursor_start=cursor_pos; } if (!p_shift) @@ -626,13 +799,6 @@ void LineEdit::set_cursor_at_pixel_pos(int p_x) { pixel_ofs+=char_w; if (pixel_ofs > p_x) { //found what we look for - - - if ( (pixel_ofs-p_x) < (char_w >> 1 ) ) { - - ofs+=1; - } - break; } @@ -651,6 +817,45 @@ void LineEdit::set_cursor_at_pixel_pos(int p_x) { } +bool LineEdit::cursor_get_blink_enabled() const { + return caret_blink_enabled; +} + +void LineEdit::cursor_set_blink_enabled(const bool p_enabled) { + caret_blink_enabled = p_enabled; + if (p_enabled) { + caret_blink_timer->start(); + } else { + caret_blink_timer->stop(); + } + draw_caret = true; +} + +float LineEdit::cursor_get_blink_speed() const { + return caret_blink_timer->get_wait_time(); +} + +void LineEdit::cursor_set_blink_speed(const float p_speed) { + ERR_FAIL_COND(p_speed <= 0); + caret_blink_timer->set_wait_time(p_speed); +} + +void LineEdit::_reset_caret_blink_timer() { + if (caret_blink_enabled) { + caret_blink_timer->stop(); + caret_blink_timer->start(); + draw_caret = true; + update(); + } + } + +void LineEdit::_toggle_draw_caret() { + draw_caret = !draw_caret; + if (is_visible_in_tree() && has_focus() && window_has_focus) { + update(); + } +} + void LineEdit::delete_char() { if ((text.length()<=0) || (cursor_pos==0)) return; @@ -666,11 +871,42 @@ void LineEdit::delete_char() { if (cursor_pos==window_pos) { - // set_window_pos(cursor_pos-get_window_length()); + //set_window_pos(cursor_pos-get_window_length()); } - emit_signal("text_changed",text); - _change_notify("text"); + _text_changed(); +} + +void LineEdit::delete_text(int p_from_column, int p_to_column) { + + undo_text = text; + + if (text.size() > 0) + { + Ref<Font> font = get_font("font"); + if (font != NULL) { + for (int i = p_from_column; i < p_to_column; i++) + cached_width -= font->get_char_size(text[i]).width; + } + } + else + { + cached_width = 0; + } + + text.erase(p_from_column,p_to_column-p_from_column); + cursor_pos-=CLAMP( cursor_pos-p_from_column, 0, p_to_column-p_from_column); + + if (cursor_pos>=text.length()) { + + cursor_pos=text.length(); + } + if (window_pos>cursor_pos) { + + window_pos=cursor_pos; + } + + _text_changed(); } void LineEdit::set_text(String p_text) { @@ -680,13 +916,13 @@ void LineEdit::set_text(String p_text) { update(); cursor_pos=0; window_pos=0; + _text_changed(); } void LineEdit::clear() { clear_internal(); - emit_signal("text_changed",text); - _change_notify("text"); + _text_changed(); } String LineEdit::get_text() const { @@ -694,6 +930,29 @@ String LineEdit::get_text() const { return text; } +void LineEdit::set_placeholder(String p_text) { + + placeholder = XL_MESSAGE(p_text); + update(); +} + +String LineEdit::get_placeholder() const { + + return placeholder; +} + + +void LineEdit::set_placeholder_alpha(float p_alpha) { + + placeholder_alpha = p_alpha; + update(); +} + +float LineEdit::get_placeholder_alpha() const { + + return placeholder_alpha; +} + void LineEdit::set_cursor_pos(int p_pos) { if (p_pos>(int)text.length()) @@ -706,10 +965,6 @@ void LineEdit::set_cursor_pos(int p_pos) { cursor_pos=p_pos; -// if (cursor_pos>(window_pos+get_window_length())) { -// set_window_pos(cursor_pos-get_window_lengt//h()); -// } - if (!is_inside_tree()) { window_pos=cursor_pos; @@ -728,17 +983,23 @@ void LineEdit::set_cursor_pos(int p_pos) { if (window_width<0) return; - int width_to_cursor=0; int wp=window_pos; - if (font != NULL) { - for (int i=window_pos;i<cursor_pos;i++) - width_to_cursor+=font->get_char_size( text[i] ).width; + if (font.is_valid()) { + + int accum_width=0; + + for(int i=cursor_pos;i>=window_pos;i--) { - while (width_to_cursor >= window_width && wp < text.length()) { + if (i>=text.length()) { + accum_width=font->get_char_size(' ').width; //anything should do + } else { + accum_width+=font->get_char_size(text[i],i+1<text.length()?text[i+1]:0).width; //anything should do + } + if (accum_width>=window_width) + break; - width_to_cursor -= font->get_char_size(text[wp]).width; - wp++; + wp=i; } } @@ -800,7 +1061,16 @@ Size2 LineEdit::get_minimum_size() const { Size2 min=style->get_minimum_size(); min.height+=font->get_height(); - min.width+=get_constant("minimum_spaces")*font->get_char_size(' ').x; + + //minimum size of text + int space_size = font->get_char_size(' ').x; + int mstext = get_constant("minimum_spaces")*space_size; + + if (expand_to_text_length) { + mstext=MAX(mstext,font->get_string_size(text).x+space_size); //add a spce because some fonts are too exact + } + + min.width+=mstext; return min; } @@ -814,46 +1084,14 @@ void LineEdit::selection_clear() { selection.cursor_start=0; selection.enabled=false; selection.creating=false; - selection.old_shift=false; selection.doubleclick=false; update(); } - void LineEdit::selection_delete() { - if (selection.enabled) { - - undo_text = text; - - if (text.size() > 0) - { - Ref<Font> font = get_font("font"); - if (font != NULL) { - for (int i = selection.begin; i < selection.end; i++) - cached_width -= font->get_char_size(text[i]).width; - } - } - else - { - cached_width = 0; - } - - text.erase(selection.begin,selection.end-selection.begin); - cursor_pos-=CLAMP( cursor_pos-selection.begin, 0, selection.end-selection.begin); - - if (cursor_pos>=text.length()) { - - cursor_pos=text.length(); - } - if (window_pos>cursor_pos) { - - window_pos=cursor_pos; - } - - emit_signal("text_changed",text); - _change_notify("text"); - }; + if (selection.enabled) + delete_text(selection.begin,selection.end); selection_clear(); } @@ -940,7 +1178,6 @@ void LineEdit::select(int p_from, int p_to) { selection.begin=p_from; selection.end=p_to; selection.creating=false; - selection.old_shift=false; selection.doubleclick=false; update(); } @@ -954,24 +1191,28 @@ void LineEdit::menu_option(int p_option) { switch(p_option) { case MENU_CUT: { - cut_text(); + if (editable) { + cut_text(); + } } break; case MENU_COPY: { copy_text(); } break; case MENU_PASTE: { - - paste_text(); + if (editable) { + paste_text(); + } } break; case MENU_CLEAR: { - clear(); + if (editable) { + clear(); + } } break; case MENU_SELECT_ALL: { select_all(); } break; case MENU_UNDO: { - undo(); } break; @@ -983,28 +1224,74 @@ PopupMenu *LineEdit::get_menu() const { return menu; } +#ifdef TOOLS_ENABLED + void LineEdit::_editor_settings_changed() { + cursor_set_blink_enabled(EDITOR_DEF("text_editor/cursor/caret_blink", false)); + cursor_set_blink_speed(EDITOR_DEF("text_editor/cursor/caret_blink_speed", 0.65)); + } +#endif + + +void LineEdit::set_expand_to_text_length(bool p_enabled) { + + expand_to_text_length = p_enabled; + minimum_size_changed(); +} + +bool LineEdit::get_expand_to_text_length() const{ + + return expand_to_text_length; +} + + +void LineEdit::_text_changed() { + + if (expand_to_text_length) + minimum_size_changed(); + + emit_signal("text_changed",text); + _change_notify("text"); + +} + void LineEdit::_bind_methods() { - ObjectTypeDB::bind_method(_MD("set_align", "align"), &LineEdit::set_align); - ObjectTypeDB::bind_method(_MD("get_align"), &LineEdit::get_align); - - ObjectTypeDB::bind_method(_MD("_input_event"),&LineEdit::_input_event); - ObjectTypeDB::bind_method(_MD("clear"),&LineEdit::clear); - ObjectTypeDB::bind_method(_MD("select_all"),&LineEdit::select_all); - ObjectTypeDB::bind_method(_MD("set_text","text"),&LineEdit::set_text); - ObjectTypeDB::bind_method(_MD("get_text"),&LineEdit::get_text); - ObjectTypeDB::bind_method(_MD("set_cursor_pos","pos"),&LineEdit::set_cursor_pos); - ObjectTypeDB::bind_method(_MD("get_cursor_pos"),&LineEdit::get_cursor_pos); - ObjectTypeDB::bind_method(_MD("set_max_length","chars"),&LineEdit::set_max_length); - ObjectTypeDB::bind_method(_MD("get_max_length"),&LineEdit::get_max_length); - ObjectTypeDB::bind_method(_MD("append_at_cursor","text"),&LineEdit::append_at_cursor); - ObjectTypeDB::bind_method(_MD("set_editable","enabled"),&LineEdit::set_editable); - ObjectTypeDB::bind_method(_MD("is_editable"),&LineEdit::is_editable); - ObjectTypeDB::bind_method(_MD("set_secret","enabled"),&LineEdit::set_secret); - ObjectTypeDB::bind_method(_MD("is_secret"),&LineEdit::is_secret); - ObjectTypeDB::bind_method(_MD("select","from","to"),&LineEdit::select,DEFVAL(0),DEFVAL(-1)); - ObjectTypeDB::bind_method(_MD("menu_option","option"),&LineEdit::menu_option); - ObjectTypeDB::bind_method(_MD("get_menu:PopupMenu"),&LineEdit::get_menu); + ClassDB::bind_method(_MD("_toggle_draw_caret"),&LineEdit::_toggle_draw_caret); + +#ifdef TOOLS_ENABLED + ClassDB::bind_method("_editor_settings_changed",&LineEdit::_editor_settings_changed); +#endif + + ClassDB::bind_method(_MD("set_align", "align"), &LineEdit::set_align); + ClassDB::bind_method(_MD("get_align"), &LineEdit::get_align); + + ClassDB::bind_method(_MD("_gui_input"),&LineEdit::_gui_input); + ClassDB::bind_method(_MD("clear"),&LineEdit::clear); + ClassDB::bind_method(_MD("select_all"),&LineEdit::select_all); + ClassDB::bind_method(_MD("set_text","text"),&LineEdit::set_text); + ClassDB::bind_method(_MD("get_text"),&LineEdit::get_text); + ClassDB::bind_method(_MD("set_placeholder","text"),&LineEdit::set_placeholder); + ClassDB::bind_method(_MD("get_placeholder"),&LineEdit::get_placeholder); + ClassDB::bind_method(_MD("set_placeholder_alpha","alpha"),&LineEdit::set_placeholder_alpha); + ClassDB::bind_method(_MD("get_placeholder_alpha"),&LineEdit::get_placeholder_alpha); + ClassDB::bind_method(_MD("set_cursor_pos","pos"),&LineEdit::set_cursor_pos); + ClassDB::bind_method(_MD("get_cursor_pos"),&LineEdit::get_cursor_pos); + ClassDB::bind_method(_MD("set_expand_to_text_length","enabled"),&LineEdit::set_expand_to_text_length); + ClassDB::bind_method(_MD("get_expand_to_text_length"),&LineEdit::get_expand_to_text_length); + ClassDB::bind_method(_MD("cursor_set_blink_enabled", "enabled"),&LineEdit::cursor_set_blink_enabled); + ClassDB::bind_method(_MD("cursor_get_blink_enabled"),&LineEdit::cursor_get_blink_enabled); + ClassDB::bind_method(_MD("cursor_set_blink_speed", "blink_speed"),&LineEdit::cursor_set_blink_speed); + ClassDB::bind_method(_MD("cursor_get_blink_speed"),&LineEdit::cursor_get_blink_speed); + ClassDB::bind_method(_MD("set_max_length","chars"),&LineEdit::set_max_length); + ClassDB::bind_method(_MD("get_max_length"),&LineEdit::get_max_length); + ClassDB::bind_method(_MD("append_at_cursor","text"),&LineEdit::append_at_cursor); + ClassDB::bind_method(_MD("set_editable","enabled"),&LineEdit::set_editable); + ClassDB::bind_method(_MD("is_editable"),&LineEdit::is_editable); + ClassDB::bind_method(_MD("set_secret","enabled"),&LineEdit::set_secret); + ClassDB::bind_method(_MD("is_secret"),&LineEdit::is_secret); + ClassDB::bind_method(_MD("select","from","to"),&LineEdit::select,DEFVAL(0),DEFVAL(-1)); + ClassDB::bind_method(_MD("menu_option","option"),&LineEdit::menu_option); + ClassDB::bind_method(_MD("get_menu:PopupMenu"),&LineEdit::get_menu); ADD_SIGNAL( MethodInfo("text_changed", PropertyInfo( Variant::STRING, "text" )) ); ADD_SIGNAL( MethodInfo("text_entered", PropertyInfo( Variant::STRING, "text" )) ); @@ -1027,8 +1314,14 @@ void LineEdit::_bind_methods() { ADD_PROPERTYNZ( PropertyInfo( Variant::INT, "max_length" ), _SCS("set_max_length"),_SCS("get_max_length") ); ADD_PROPERTYNO( PropertyInfo( Variant::BOOL, "editable" ), _SCS("set_editable"),_SCS("is_editable") ); ADD_PROPERTYNZ( PropertyInfo( Variant::BOOL, "secret" ), _SCS("set_secret"),_SCS("is_secret") ); - - + ADD_PROPERTYNO( PropertyInfo( Variant::BOOL, "expand_to_len" ), _SCS("set_expand_to_text_length"),_SCS("get_expand_to_text_length") ); + ADD_PROPERTY( PropertyInfo( Variant::INT,"focus_mode", PROPERTY_HINT_ENUM, "None,Click,All" ), _SCS("set_focus_mode"), _SCS("get_focus_mode") ); + ADD_GROUP("Placeholder","placeholder_"); + ADD_PROPERTYNZ( PropertyInfo( Variant::STRING, "placeholder_text" ), _SCS("set_placeholder"),_SCS("get_placeholder") ); + ADD_PROPERTYNZ( PropertyInfo( Variant::REAL, "placeholder_alpha",PROPERTY_HINT_RANGE,"0,1,0.001" ), _SCS("set_placeholder_alpha"),_SCS("get_placeholder_alpha") ); + ADD_GROUP("Caret","caret_"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "caret_blink"), _SCS("cursor_set_blink_enabled"), _SCS("cursor_get_blink_enabled"));; + ADD_PROPERTYNZ(PropertyInfo(Variant::REAL, "caret_blink_speed",PROPERTY_HINT_RANGE,"0.1,10,0.1"), _SCS("cursor_set_blink_speed"),_SCS("cursor_get_blink_speed") ); } LineEdit::LineEdit() { @@ -1037,15 +1330,24 @@ LineEdit::LineEdit() { cached_width = 0; cursor_pos=0; window_pos=0; + window_has_focus=true; max_length = 0; pass=false; + placeholder_alpha=0.6; selection_clear(); set_focus_mode( FOCUS_ALL ); editable=true; set_default_cursor_shape(CURSOR_IBEAM); - set_stop_mouse(true); + set_mouse_filter(MOUSE_FILTER_STOP); + draw_caret=true; + caret_blink_enabled=false; + caret_blink_timer = memnew(Timer); + add_child(caret_blink_timer); + caret_blink_timer->set_wait_time(0.65); + caret_blink_timer->connect("timeout", this,"_toggle_draw_caret"); + cursor_set_blink_enabled(false); menu = memnew( PopupMenu ); add_child(menu); @@ -1057,8 +1359,8 @@ LineEdit::LineEdit() { menu->add_item(TTR("Clear"),MENU_CLEAR); menu->add_separator(); menu->add_item(TTR("Undo"),MENU_UNDO,KEY_MASK_CMD|KEY_Z); - menu->connect("item_pressed",this,"menu_option"); - + menu->connect("id_pressed",this,"menu_option"); + expand_to_text_length=false; } diff --git a/scene/gui/line_edit.h b/scene/gui/line_edit.h index 586a54e950..64c37861d0 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-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 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 */ @@ -37,7 +37,7 @@ */ class LineEdit : public Control { - OBJ_TYPE( LineEdit, Control ); + GDCLASS( LineEdit, Control ); public: enum Align { @@ -67,6 +67,8 @@ private: String undo_text; String text; + String placeholder; + float placeholder_alpha; PopupMenu *menu; @@ -83,11 +85,20 @@ private: int cursor_start; bool enabled; bool creating; - bool old_shift; bool doubleclick; bool drag_attempt; } selection; + Timer *caret_blink_timer; + + + void _text_changed(); + bool expand_to_text_length; + + bool caret_blink_enabled; + bool draw_caret; + bool window_has_focus; + void shift_selection_check_pre(bool); void shift_selection_check_post(bool); @@ -98,12 +109,17 @@ private: void set_cursor_at_pixel_pos(int p_x); + void _reset_caret_blink_timer(); + void _toggle_draw_caret(); + void clear_internal(); void changed_internal(); +#ifdef TOOLS_ENABLED + void _editor_settings_changed(); +#endif - - void _input_event(InputEvent p_event); + void _gui_input(InputEvent p_event); void _notification(int p_what); @@ -123,8 +139,13 @@ public: void select_all(); void delete_char(); + void delete_text(int p_from_column, int p_to_column); void set_text(String p_text); String get_text() const; + void set_placeholder(String p_text); + String get_placeholder() const; + void set_placeholder_alpha(float p_alpha); + float get_placeholder_alpha() const; void set_cursor_pos(int p_pos); int get_cursor_pos() const; void set_max_length(int p_max_length); @@ -132,6 +153,12 @@ public: void append_at_cursor(String p_text); void clear(); + bool cursor_get_blink_enabled() const; + void cursor_set_blink_enabled(const bool p_enabled); + + float cursor_get_blink_speed() const; + void cursor_set_blink_speed(const float p_speed); + void copy_text(); void cut_text(); void paste_text(); @@ -147,6 +174,9 @@ public: virtual Size2 get_minimum_size() const; + void set_expand_to_text_length(bool p_len); + bool get_expand_to_text_length() const; + virtual bool is_text_field() const; LineEdit(); ~LineEdit(); diff --git a/scene/gui/link_button.cpp b/scene/gui/link_button.cpp index 007d0a709e..5b791064a8 100644 --- a/scene/gui/link_button.cpp +++ b/scene/gui/link_button.cpp @@ -1,3 +1,31 @@ +/*************************************************************************/ +/* link_button.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2017 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 */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ #include "link_button.h" @@ -59,13 +87,13 @@ void LinkButton::_notification(int p_what) { else color=get_color("font_color"); - do_underline=true; + do_underline=underline_mode!=UNDERLINE_MODE_NEVER; } break; case DRAW_HOVER: { color=get_color("font_color_hover"); - do_underline=true; + do_underline=underline_mode!=UNDERLINE_MODE_NEVER; } break; case DRAW_DISABLED: { @@ -102,23 +130,24 @@ void LinkButton::_notification(int p_what) { void LinkButton::_bind_methods() { - ObjectTypeDB::bind_method(_MD("set_text","text"),&LinkButton::set_text); - ObjectTypeDB::bind_method(_MD("get_text"),&LinkButton::get_text); + ClassDB::bind_method(_MD("set_text","text"),&LinkButton::set_text); + ClassDB::bind_method(_MD("get_text"),&LinkButton::get_text); - ObjectTypeDB::bind_method(_MD("set_underline_mode","underline_mode"),&LinkButton::set_underline_mode); - ObjectTypeDB::bind_method(_MD("get_underline_mode"),&LinkButton::get_underline_mode); + ClassDB::bind_method(_MD("set_underline_mode","underline_mode"),&LinkButton::set_underline_mode); + ClassDB::bind_method(_MD("get_underline_mode"),&LinkButton::get_underline_mode); BIND_CONSTANT( UNDERLINE_MODE_ALWAYS ); BIND_CONSTANT( UNDERLINE_MODE_ON_HOVER ); + BIND_CONSTANT( UNDERLINE_MODE_NEVER ); ADD_PROPERTYNZ(PropertyInfo(Variant::STRING,"text"), _SCS("set_text"), _SCS("get_text")); - ADD_PROPERTYNZ(PropertyInfo(Variant::INT,"underline",PROPERTY_HINT_ENUM,"Always,On Hover"), _SCS("set_underline_mode"), _SCS("get_underline_mode")); + ADD_PROPERTYNZ(PropertyInfo(Variant::INT,"underline",PROPERTY_HINT_ENUM,"Always,On Hover,Never"), _SCS("set_underline_mode"), _SCS("get_underline_mode")); } LinkButton::LinkButton() { underline_mode=UNDERLINE_MODE_ALWAYS; - set_focus_mode(FOCUS_NONE); + set_enabled_focus_mode(FOCUS_NONE); set_default_cursor_shape(CURSOR_POINTING_HAND); } diff --git a/scene/gui/link_button.h b/scene/gui/link_button.h index d218482337..42d7c05cff 100644 --- a/scene/gui/link_button.h +++ b/scene/gui/link_button.h @@ -1,3 +1,31 @@ +/*************************************************************************/ +/* link_button.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2017 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 */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ #ifndef LINKBUTTON_H #define LINKBUTTON_H @@ -7,12 +35,13 @@ class LinkButton : public BaseButton { - OBJ_TYPE( LinkButton, BaseButton ); + GDCLASS( LinkButton, BaseButton ); public: enum UnderlineMode { UNDERLINE_MODE_ALWAYS, - UNDERLINE_MODE_ON_HOVER + UNDERLINE_MODE_ON_HOVER, + UNDERLINE_MODE_NEVER }; private: String text; diff --git a/scene/gui/margin_container.cpp b/scene/gui/margin_container.cpp index 5f798f445c..be27c40117 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-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 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 */ @@ -45,7 +45,7 @@ Size2 MarginContainer::get_minimum_size() const { continue; if (c->is_set_as_toplevel()) continue; - if (c->is_hidden()) + if (!c->is_visible()) continue; Size2 s = c->get_combined_minimum_size(); diff --git a/scene/gui/margin_container.h b/scene/gui/margin_container.h index df9a5c9361..542578dd01 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-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 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 */ @@ -32,7 +32,7 @@ #include "scene/gui/container.h" class MarginContainer : public Container { - OBJ_TYPE(MarginContainer,Container); + GDCLASS(MarginContainer,Container); protected: void _notification(int p_what); diff --git a/scene/gui/menu_button.cpp b/scene/gui/menu_button.cpp index 0f415f013d..4a366c55c6 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-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 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 */ @@ -28,34 +28,22 @@ /*************************************************************************/ #include "menu_button.h" #include "os/keyboard.h" +#include "scene/main/viewport.h" void MenuButton::_unhandled_key_input(InputEvent p_event) { - //check accelerators - if (p_event.type==InputEvent::KEY && p_event.key.pressed) { + if (p_event.is_pressed() && !p_event.is_echo() && (p_event.type==InputEvent::KEY || p_event.type==InputEvent::ACTION || p_event.type==InputEvent::JOYPAD_BUTTON)) { - if (!get_parent() || !is_visible() || is_disabled()) + if (!get_parent() || !is_visible_in_tree() || is_disabled()) return; - uint32_t code=p_event.key.scancode; - if (code==0) - code=p_event.key.unicode; + bool global_only = (get_viewport()->get_modal_stack_top() && !get_viewport()->get_modal_stack_top()->is_a_parent_of(this)); - if (p_event.key.mod.control) - code|=KEY_MASK_CTRL; - if (p_event.key.mod.alt) - code|=KEY_MASK_ALT; - if (p_event.key.mod.meta) - code|=KEY_MASK_META; - if (p_event.key.mod.shift) - code|=KEY_MASK_SHIFT; - - - int item = popup->activate_item_by_accelerator(code); + if (popup->activate_item_by_event(p_event,global_only)) + accept_event(); } - } @@ -74,12 +62,12 @@ void MenuButton::pressed() { } -void MenuButton::_input_event(InputEvent p_event) { +void MenuButton::_gui_input(InputEvent p_event) { /*if (p_event.type==InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index==BUTTON_LEFT) { clicked=p_event.mouse_button.pressed; } - if (clicked && p_event.type==InputEvent::MOUSE_MOTION && popup->is_visible()) { + if (clicked && p_event.type==InputEvent::MOUSE_MOTION && popup->is_visible_in_tree()) { Point2 gt = Point2(p_event.mouse_motion.x,p_event.mouse_motion.y); gt = get_global_transform().xform(gt); @@ -91,7 +79,7 @@ void MenuButton::_input_event(InputEvent p_event) { }*/ - BaseButton::_input_event(p_event); + BaseButton::_gui_input(p_event); } PopupMenu *MenuButton::get_popup() { @@ -110,10 +98,10 @@ void MenuButton::_set_items(const Array& p_items) { void MenuButton::_bind_methods() { - ObjectTypeDB::bind_method(_MD("get_popup:PopupMenu"),&MenuButton::get_popup); - ObjectTypeDB::bind_method(_MD("_unhandled_key_input"),&MenuButton::_unhandled_key_input); - ObjectTypeDB::bind_method(_MD("_set_items"),&MenuButton::_set_items); - ObjectTypeDB::bind_method(_MD("_get_items"),&MenuButton::_get_items); + ClassDB::bind_method(_MD("get_popup:PopupMenu"),&MenuButton::get_popup); + ClassDB::bind_method(_MD("_unhandled_key_input"),&MenuButton::_unhandled_key_input); + ClassDB::bind_method(_MD("_set_items"),&MenuButton::_set_items); + ClassDB::bind_method(_MD("_get_items"),&MenuButton::_get_items); ADD_PROPERTY( PropertyInfo(Variant::ARRAY,"items",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR), _SCS("_set_items"),_SCS("_get_items") ); @@ -123,13 +111,13 @@ MenuButton::MenuButton() { set_flat(true); - set_focus_mode(FOCUS_NONE); + set_enabled_focus_mode(FOCUS_NONE); popup = memnew( PopupMenu ); popup->hide(); add_child(popup); popup->set_as_toplevel(true); set_process_unhandled_key_input(true); - set_click_on_press(true); + set_action_mode(ACTION_MODE_BUTTON_PRESS); } diff --git a/scene/gui/menu_button.h b/scene/gui/menu_button.h index 650e4aba5c..5b5573456f 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-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 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 */ @@ -36,7 +36,7 @@ */ class MenuButton : public Button { - OBJ_TYPE( MenuButton, Button ); + GDCLASS( MenuButton, Button ); bool clicked; PopupMenu *popup; @@ -46,7 +46,7 @@ class MenuButton : public Button { Array _get_items() const; void _set_items(const Array& p_items); - void _input_event(InputEvent p_event); + void _gui_input(InputEvent p_event); protected: diff --git a/scene/gui/option_button.cpp b/scene/gui/option_button.cpp index 587a68ae37..1b5b21ae92 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-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 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 */ @@ -287,32 +287,32 @@ void OptionButton::get_translatable_strings(List<String> *p_strings) const { void OptionButton::_bind_methods() { - ObjectTypeDB::bind_method(_MD("_selected"),&OptionButton::_selected); - - ObjectTypeDB::bind_method(_MD("add_item","label","id"),&OptionButton::add_item,DEFVAL(-1)); - ObjectTypeDB::bind_method(_MD("add_icon_item","texture:Texture","label","id"),&OptionButton::add_icon_item); - ObjectTypeDB::bind_method(_MD("set_item_text","idx","text"),&OptionButton::set_item_text); - ObjectTypeDB::bind_method(_MD("set_item_icon","idx","texture:Texture"),&OptionButton::set_item_icon); - ObjectTypeDB::bind_method(_MD("set_item_disabled","idx","disabled"),&OptionButton::set_item_disabled); - ObjectTypeDB::bind_method(_MD("set_item_ID","idx","id"),&OptionButton::set_item_ID); - ObjectTypeDB::bind_method(_MD("set_item_metadata","idx","metadata"),&OptionButton::set_item_metadata); - ObjectTypeDB::bind_method(_MD("get_item_text","idx"),&OptionButton::get_item_text); - ObjectTypeDB::bind_method(_MD("get_item_icon:Texture","idx"),&OptionButton::get_item_icon); - ObjectTypeDB::bind_method(_MD("get_item_ID","idx"),&OptionButton::get_item_ID); - ObjectTypeDB::bind_method(_MD("get_item_metadata","idx"),&OptionButton::get_item_metadata); - ObjectTypeDB::bind_method(_MD("is_item_disabled","idx"),&OptionButton::is_item_disabled); - ObjectTypeDB::bind_method(_MD("get_item_count"),&OptionButton::get_item_count); - ObjectTypeDB::bind_method(_MD("add_separator"),&OptionButton::add_separator); - ObjectTypeDB::bind_method(_MD("clear"),&OptionButton::clear); - ObjectTypeDB::bind_method(_MD("select","idx"),&OptionButton::select); - ObjectTypeDB::bind_method(_MD("get_selected"),&OptionButton::get_selected); - ObjectTypeDB::bind_method(_MD("get_selected_ID"),&OptionButton::get_selected_ID); - ObjectTypeDB::bind_method(_MD("get_selected_metadata"),&OptionButton::get_selected_metadata); - ObjectTypeDB::bind_method(_MD("remove_item","idx"),&OptionButton::remove_item); - ObjectTypeDB::bind_method(_MD("_select_int"),&OptionButton::_select_int); - - ObjectTypeDB::bind_method(_MD("_set_items"),&OptionButton::_set_items); - ObjectTypeDB::bind_method(_MD("_get_items"),&OptionButton::_get_items); + ClassDB::bind_method(_MD("_selected"),&OptionButton::_selected); + + ClassDB::bind_method(_MD("add_item","label","id"),&OptionButton::add_item,DEFVAL(-1)); + ClassDB::bind_method(_MD("add_icon_item","texture:Texture","label","id"),&OptionButton::add_icon_item); + ClassDB::bind_method(_MD("set_item_text","idx","text"),&OptionButton::set_item_text); + ClassDB::bind_method(_MD("set_item_icon","idx","texture:Texture"),&OptionButton::set_item_icon); + ClassDB::bind_method(_MD("set_item_disabled","idx","disabled"),&OptionButton::set_item_disabled); + ClassDB::bind_method(_MD("set_item_ID","idx","id"),&OptionButton::set_item_ID); + ClassDB::bind_method(_MD("set_item_metadata","idx","metadata"),&OptionButton::set_item_metadata); + ClassDB::bind_method(_MD("get_item_text","idx"),&OptionButton::get_item_text); + ClassDB::bind_method(_MD("get_item_icon:Texture","idx"),&OptionButton::get_item_icon); + ClassDB::bind_method(_MD("get_item_ID","idx"),&OptionButton::get_item_ID); + ClassDB::bind_method(_MD("get_item_metadata","idx"),&OptionButton::get_item_metadata); + ClassDB::bind_method(_MD("is_item_disabled","idx"),&OptionButton::is_item_disabled); + ClassDB::bind_method(_MD("get_item_count"),&OptionButton::get_item_count); + ClassDB::bind_method(_MD("add_separator"),&OptionButton::add_separator); + ClassDB::bind_method(_MD("clear"),&OptionButton::clear); + ClassDB::bind_method(_MD("select","idx"),&OptionButton::select); + ClassDB::bind_method(_MD("get_selected"),&OptionButton::get_selected); + ClassDB::bind_method(_MD("get_selected_ID"),&OptionButton::get_selected_ID); + ClassDB::bind_method(_MD("get_selected_metadata"),&OptionButton::get_selected_metadata); + ClassDB::bind_method(_MD("remove_item","idx"),&OptionButton::remove_item); + ClassDB::bind_method(_MD("_select_int"),&OptionButton::_select_int); + + ClassDB::bind_method(_MD("_set_items"),&OptionButton::_set_items); + ClassDB::bind_method(_MD("_get_items"),&OptionButton::_get_items); ADD_PROPERTY( PropertyInfo(Variant::INT,"selected"), _SCS("_select_int"),_SCS("get_selected") ); ADD_PROPERTY( PropertyInfo(Variant::ARRAY,"items",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR), _SCS("_set_items"),_SCS("_get_items") ); @@ -326,7 +326,7 @@ OptionButton::OptionButton() { popup->hide(); popup->set_as_toplevel(true); add_child(popup); - popup->connect("item_pressed", this,"_selected"); + popup->connect("id_pressed", this,"_selected"); current=-1; set_text_align(ALIGN_LEFT); diff --git a/scene/gui/option_button.h b/scene/gui/option_button.h index 70ebc66a46..681cb5a088 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-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 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 */ @@ -36,7 +36,7 @@ */ class OptionButton : public Button { - OBJ_TYPE( OptionButton, Button ); + GDCLASS( OptionButton, Button ); PopupMenu *popup; int current; diff --git a/scene/gui/panel.cpp b/scene/gui/panel.cpp index 682ea5b92c..c4b7199c3e 100644 --- a/scene/gui/panel.cpp +++ b/scene/gui/panel.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 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 */ @@ -41,7 +41,7 @@ void Panel::_notification(int p_what) { Panel::Panel() { - set_stop_mouse(true); + set_mouse_filter(MOUSE_FILTER_STOP); } diff --git a/scene/gui/panel.h b/scene/gui/panel.h index efa9ebcaa0..34c73960e7 100644 --- a/scene/gui/panel.h +++ b/scene/gui/panel.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 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 */ @@ -35,7 +35,7 @@ */ class Panel : public Control{ - OBJ_TYPE(Panel,Control); + GDCLASS(Panel,Control); protected: void _notification(int p_what); @@ -45,4 +45,6 @@ public: }; + + #endif diff --git a/scene/gui/panel_container.cpp b/scene/gui/panel_container.cpp index b5e3ef8c7b..48270d12c7 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-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 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 */ @@ -43,7 +43,7 @@ Size2 PanelContainer::get_minimum_size() const { for(int i=0;i<get_child_count();i++) { Control *c = get_child(i)->cast_to<Control>(); - if (!c || !c->is_visible()) + if (!c || !c->is_visible_in_tree()) continue; if (c->is_set_as_toplevel()) continue; @@ -98,7 +98,7 @@ void PanelContainer::_notification(int p_what) { for(int i=0;i<get_child_count();i++) { Control *c = get_child(i)->cast_to<Control>(); - if (!c || !c->is_visible()) + if (!c || !c->is_visible_in_tree()) continue; if (c->is_set_as_toplevel()) continue; diff --git a/scene/gui/panel_container.h b/scene/gui/panel_container.h index a40519c9f2..86f390fdf3 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-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 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 */ @@ -33,7 +33,7 @@ class PanelContainer : public Container { - OBJ_TYPE( PanelContainer, Container ); + GDCLASS( PanelContainer, Container ); protected: diff --git a/scene/gui/patch_9_frame.cpp b/scene/gui/patch_9_frame.cpp deleted file mode 100644 index b6e261714c..0000000000 --- a/scene/gui/patch_9_frame.cpp +++ /dev/null @@ -1,132 +0,0 @@ -#include "patch_9_frame.h" - -#include "servers/visual_server.h" - -void Patch9Frame::_notification(int p_what) { - - if (p_what==NOTIFICATION_DRAW) { - - if (texture.is_null()) - return; - - - Size2 s=get_size(); - RID ci = get_canvas_item(); - VS::get_singleton()->canvas_item_add_style_box(ci,Rect2(Point2(),s),texture->get_rid(),Vector2(margin[MARGIN_LEFT],margin[MARGIN_TOP]),Vector2(margin[MARGIN_RIGHT],margin[MARGIN_BOTTOM]),draw_center,modulate); -// draw_texture_rect(texture,Rect2(Point2(),s),false,modulate); - -/* - Vector<Point2> points; - points.resize(4); - points[0]=Point2(0,0); - points[1]=Point2(s.x,0); - points[2]=Point2(s.x,s.y); - points[3]=Point2(0,s.y); - Vector<Point2> uvs; - uvs.resize(4); - uvs[0]=Point2(0,0); - uvs[1]=Point2(1,0); - uvs[2]=Point2(1,1); - uvs[3]=Point2(0,1); - - VisualServer::get_singleton()->canvas_item_add_primitive(ci,points,Vector<Color>(),uvs,texture->get_rid()); -*/ - } -} - -Size2 Patch9Frame::get_minimum_size() const { - - return Size2(margin[MARGIN_LEFT]+margin[MARGIN_RIGHT],margin[MARGIN_TOP]+margin[MARGIN_BOTTOM]); -} -void Patch9Frame::_bind_methods() { - - - ObjectTypeDB::bind_method(_MD("set_texture","texture"), & Patch9Frame::set_texture ); - ObjectTypeDB::bind_method(_MD("get_texture"), & Patch9Frame::get_texture ); - ObjectTypeDB::bind_method(_MD("set_modulate","modulate"), & Patch9Frame::set_modulate ); - ObjectTypeDB::bind_method(_MD("get_modulate"), & Patch9Frame::get_modulate ); - ObjectTypeDB::bind_method(_MD("set_patch_margin","margin","value"), & Patch9Frame::set_patch_margin ); - ObjectTypeDB::bind_method(_MD("get_patch_margin","margin"), & Patch9Frame::get_patch_margin ); - ObjectTypeDB::bind_method(_MD("set_draw_center","draw_center"), & Patch9Frame::set_draw_center ); - ObjectTypeDB::bind_method(_MD("get_draw_center"), & Patch9Frame::get_draw_center ); - - 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_PROPERTYNO( PropertyInfo( Variant::BOOL, "draw_center"), _SCS("set_draw_center"),_SCS("get_draw_center") ); - ADD_PROPERTYINZ( PropertyInfo( Variant::INT, "patch_margin/left",PROPERTY_HINT_RANGE,"0,16384,1"), _SCS("set_patch_margin"),_SCS("get_patch_margin"),MARGIN_LEFT ); - ADD_PROPERTYINZ( PropertyInfo( Variant::INT, "patch_margin/top",PROPERTY_HINT_RANGE,"0,16384,1"), _SCS("set_patch_margin"),_SCS("get_patch_margin"),MARGIN_TOP ); - ADD_PROPERTYINZ( PropertyInfo( Variant::INT, "patch_margin/right",PROPERTY_HINT_RANGE,"0,16384,1"), _SCS("set_patch_margin"),_SCS("get_patch_margin"),MARGIN_RIGHT ); - ADD_PROPERTYINZ( PropertyInfo( Variant::INT, "patch_margin/bottom",PROPERTY_HINT_RANGE,"0,16384,1"), _SCS("set_patch_margin"),_SCS("get_patch_margin"),MARGIN_BOTTOM ); - -} - - -void Patch9Frame::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 - minimum_size_changed(); -} - -Ref<Texture> Patch9Frame::get_texture() const { - - return texture; -} - -void Patch9Frame::set_modulate(const Color& p_tex) { - - modulate=p_tex; - update(); -} - -Color Patch9Frame::get_modulate() const{ - - return modulate; -} - - -void Patch9Frame::set_patch_margin(Margin p_margin,int p_size) { - - ERR_FAIL_INDEX(p_margin,4); - margin[p_margin]=p_size; - update(); - minimum_size_changed(); -} - -int Patch9Frame::get_patch_margin(Margin p_margin) const{ - - ERR_FAIL_INDEX_V(p_margin,4,0); - return margin[p_margin]; -} - -void Patch9Frame::set_draw_center(bool p_draw) { - - draw_center=p_draw; - update(); -} - -bool Patch9Frame::get_draw_center() const{ - - return draw_center; -} - -Patch9Frame::Patch9Frame() { - - - margin[MARGIN_LEFT]=0; - margin[MARGIN_RIGHT]=0; - margin[MARGIN_BOTTOM]=0; - margin[MARGIN_TOP]=0; - modulate=Color(1,1,1,1); - set_ignore_mouse(true); - draw_center=true; -} - - -Patch9Frame::~Patch9Frame() -{ -} - - diff --git a/scene/gui/patch_9_frame.h b/scene/gui/patch_9_frame.h deleted file mode 100644 index 562a5b1d77..0000000000 --- a/scene/gui/patch_9_frame.h +++ /dev/null @@ -1,40 +0,0 @@ -#ifndef PATCH_9_FRAME_H -#define PATCH_9_FRAME_H - -#include "scene/gui/control.h" -/** - @author Juan Linietsky <reduzio@gmail.com> -*/ -class Patch9Frame : public Control { - - OBJ_TYPE(Patch9Frame,Control); - - bool draw_center; - int margin[4]; - Color modulate; - Ref<Texture> texture; -protected: - - void _notification(int p_what); - virtual Size2 get_minimum_size() const; - static void _bind_methods(); - -public: - - void set_texture(const Ref<Texture>& p_tex); - Ref<Texture> get_texture() const; - - void set_modulate(const Color& p_tex); - Color get_modulate() const; - - void set_patch_margin(Margin p_margin,int p_size); - int get_patch_margin(Margin p_margin) const; - - void set_draw_center(bool p_enable); - bool get_draw_center() const; - - Patch9Frame(); - ~Patch9Frame(); - -}; -#endif // PATCH_9_FRAME_H diff --git a/scene/gui/patch_9_rect.cpp b/scene/gui/patch_9_rect.cpp new file mode 100644 index 0000000000..4e1856778e --- /dev/null +++ b/scene/gui/patch_9_rect.cpp @@ -0,0 +1,186 @@ +/*************************************************************************/ +/* patch_9_rect.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2017 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 */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#include "patch_9_rect.h" + +#include "servers/visual_server.h" + +void NinePatchRect::_notification(int p_what) { + + if (p_what==NOTIFICATION_DRAW) { + + if (texture.is_null()) + return; + + Size2 s=get_size(); + RID ci = get_canvas_item(); + VS::get_singleton()->canvas_item_add_nine_patch(ci,Rect2(Point2(),s),region_rect,texture->get_rid(),Vector2(margin[MARGIN_LEFT],margin[MARGIN_TOP]),Vector2(margin[MARGIN_RIGHT],margin[MARGIN_BOTTOM]),VS::NINE_PATCH_STRETCH,VS::NINE_PATCH_STRETCH,draw_center); + //draw_texture_rect(texture,Rect2(Point2(),s),false,modulate); + +/* + Vector<Point2> points; + points.resize(4); + points[0]=Point2(0,0); + points[1]=Point2(s.x,0); + points[2]=Point2(s.x,s.y); + points[3]=Point2(0,s.y); + Vector<Point2> uvs; + uvs.resize(4); + uvs[0]=Point2(0,0); + uvs[1]=Point2(1,0); + uvs[2]=Point2(1,1); + uvs[3]=Point2(0,1); + + VisualServer::get_singleton()->canvas_item_add_primitive(ci,points,Vector<Color>(),uvs,texture->get_rid()); +*/ + } +} + +Size2 NinePatchRect::get_minimum_size() const { + + return Size2(margin[MARGIN_LEFT]+margin[MARGIN_RIGHT],margin[MARGIN_TOP]+margin[MARGIN_BOTTOM]); +} +void NinePatchRect::_bind_methods() { + + + ClassDB::bind_method(_MD("set_texture","texture"), & NinePatchRect::set_texture ); + ClassDB::bind_method(_MD("get_texture"), & NinePatchRect::get_texture ); + ClassDB::bind_method(_MD("set_patch_margin","margin","value"), & NinePatchRect::set_patch_margin ); + ClassDB::bind_method(_MD("get_patch_margin","margin"), & NinePatchRect::get_patch_margin ); + ClassDB::bind_method(_MD("set_region_rect","rect"),&NinePatchRect::set_region_rect); + ClassDB::bind_method(_MD("get_region_rect"),&NinePatchRect::get_region_rect); + ClassDB::bind_method(_MD("set_draw_center","draw_center"), & NinePatchRect::set_draw_center ); + ClassDB::bind_method(_MD("get_draw_center"), & NinePatchRect::get_draw_center ); + + ADD_SIGNAL(MethodInfo("texture_changed")); + + ADD_PROPERTYNZ( PropertyInfo( Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), _SCS("set_texture"),_SCS("get_texture") ); + ADD_PROPERTYNO( PropertyInfo( Variant::BOOL, "draw_center"), _SCS("set_draw_center"),_SCS("get_draw_center") ); + ADD_PROPERTYNZ( PropertyInfo( Variant::RECT2, "region_rect"), _SCS("set_region_rect"),_SCS("get_region_rect")); + + ADD_GROUP("Patch Margin","patch_margin_"); + ADD_PROPERTYINZ( PropertyInfo( Variant::INT, "patch_margin_left",PROPERTY_HINT_RANGE,"0,16384,1"), _SCS("set_patch_margin"),_SCS("get_patch_margin"),MARGIN_LEFT ); + ADD_PROPERTYINZ( PropertyInfo( Variant::INT, "patch_margin_top",PROPERTY_HINT_RANGE,"0,16384,1"), _SCS("set_patch_margin"),_SCS("get_patch_margin"),MARGIN_TOP ); + ADD_PROPERTYINZ( PropertyInfo( Variant::INT, "patch_margin_right",PROPERTY_HINT_RANGE,"0,16384,1"), _SCS("set_patch_margin"),_SCS("get_patch_margin"),MARGIN_RIGHT ); + ADD_PROPERTYINZ( PropertyInfo( Variant::INT, "patch_margin_bottom",PROPERTY_HINT_RANGE,"0,16384,1"), _SCS("set_patch_margin"),_SCS("get_patch_margin"),MARGIN_BOTTOM ); + +} + + +void NinePatchRect::set_texture(const Ref<Texture>& p_tex) { + + if (texture==p_tex) + return; + 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 + */ + minimum_size_changed(); + emit_signal("texture_changed"); +} + +Ref<Texture> NinePatchRect::get_texture() const { + + return texture; +} + + + +void NinePatchRect::set_patch_margin(Margin p_margin,int p_size) { + + ERR_FAIL_INDEX(p_margin,4); + margin[p_margin]=p_size; + update(); + minimum_size_changed(); + switch (p_margin) { + case MARGIN_LEFT: + _change_notify("patch_margin/left"); + break; + case MARGIN_TOP: + _change_notify("patch_margin/top"); + break; + case MARGIN_RIGHT: + _change_notify("patch_margin/right"); + break; + case MARGIN_BOTTOM: + _change_notify("patch_margin/bottom"); + break; + } +} + +int NinePatchRect::get_patch_margin(Margin p_margin) const{ + + ERR_FAIL_INDEX_V(p_margin,4,0); + return margin[p_margin]; +} + +void NinePatchRect::set_region_rect(const Rect2& p_region_rect) { + + if (region_rect==p_region_rect) + return; + + region_rect=p_region_rect; + + item_rect_changed(); + _change_notify("region_rect"); +} + +Rect2 NinePatchRect::get_region_rect() const { + + return region_rect; +} + +void NinePatchRect::set_draw_center(bool p_draw) { + + draw_center=p_draw; + update(); +} + +bool NinePatchRect::get_draw_center() const{ + + return draw_center; +} + +NinePatchRect::NinePatchRect() { + + + margin[MARGIN_LEFT]=0; + margin[MARGIN_RIGHT]=0; + margin[MARGIN_BOTTOM]=0; + margin[MARGIN_TOP]=0; + + set_mouse_filter(MOUSE_FILTER_IGNORE); + draw_center=true; +} + + +NinePatchRect::~NinePatchRect() +{ +} diff --git a/scene/gui/patch_9_rect.h b/scene/gui/patch_9_rect.h new file mode 100644 index 0000000000..b87f2f64ec --- /dev/null +++ b/scene/gui/patch_9_rect.h @@ -0,0 +1,68 @@ +/*************************************************************************/ +/* patch_9_rect.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2017 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 */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#ifndef PATCH_9_FRAME_H +#define PATCH_9_FRAME_H + +#include "scene/gui/control.h" +/** + @author Juan Linietsky <reduzio@gmail.com> +*/ +class NinePatchRect : public Control { + + GDCLASS(NinePatchRect,Control); + + bool draw_center; + int margin[4]; + Rect2 region_rect; + Ref<Texture> texture; +protected: + + void _notification(int p_what); + virtual Size2 get_minimum_size() const; + static void _bind_methods(); + +public: + + void set_texture(const Ref<Texture>& p_tex); + Ref<Texture> get_texture() const; + + void set_patch_margin(Margin p_margin,int p_size); + int get_patch_margin(Margin p_margin) const; + + void set_region_rect(const Rect2& p_region_rect); + Rect2 get_region_rect() const; + + void set_draw_center(bool p_enable); + bool get_draw_center() const; + + NinePatchRect(); + ~NinePatchRect(); + +}; +#endif // PATCH_9_FRAME_H diff --git a/scene/gui/popup.cpp b/scene/gui/popup.cpp index 8d02d0e4e5..3f0f76f184 100644 --- a/scene/gui/popup.cpp +++ b/scene/gui/popup.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 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 @@ -void Popup::_input_event(InputEvent p_event) { +void Popup::_gui_input(InputEvent p_event) { } @@ -39,7 +39,7 @@ void Popup::_input_event(InputEvent p_event) { void Popup::_notification(int p_what) { if (p_what==NOTIFICATION_VISIBILITY_CHANGED) { - if (popped_up && !is_visible()) { + if (popped_up && !is_visible_in_tree()) { popped_up=false; notification(NOTIFICATION_POPUP_HIDE); emit_signal("popup_hide"); @@ -103,7 +103,7 @@ void Popup::set_as_minsize() { Control *c=get_child(i)->cast_to<Control>(); if (!c) continue; - if (c->is_hidden()) + if (!c->is_visible()) continue; Size2 minsize = c->get_combined_minimum_size(); @@ -125,8 +125,6 @@ void Popup::set_as_minsize() { } - 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 ); } @@ -146,7 +144,7 @@ void Popup::popup_centered_minsize(const Size2& p_minsize) { Control *c=get_child(i)->cast_to<Control>(); if (!c) continue; - if (c->is_hidden()) + if (!c->is_visible()) continue; Size2 minsize = c->get_combined_minimum_size(); @@ -168,8 +166,6 @@ void Popup::popup_centered_minsize(const Size2& p_minsize) { } - 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 ); } @@ -261,15 +257,16 @@ bool Popup::is_exclusive() const { void Popup::_bind_methods() { - ObjectTypeDB::bind_method(_MD("popup_centered","size"),&Popup::popup_centered,DEFVAL(Size2())); - ObjectTypeDB::bind_method(_MD("popup_centered_ratio","ratio"),&Popup::popup_centered_ratio,DEFVAL(0.75)); - ObjectTypeDB::bind_method(_MD("popup_centered_minsize","minsize"),&Popup::popup_centered_minsize,DEFVAL(Size2())); - ObjectTypeDB::bind_method(_MD("popup"),&Popup::popup); - ObjectTypeDB::bind_method(_MD("set_exclusive","enable"),&Popup::set_exclusive); - ObjectTypeDB::bind_method(_MD("is_exclusive"),&Popup::is_exclusive); + ClassDB::bind_method(_MD("popup_centered","size"),&Popup::popup_centered,DEFVAL(Size2())); + ClassDB::bind_method(_MD("popup_centered_ratio","ratio"),&Popup::popup_centered_ratio,DEFVAL(0.75)); + ClassDB::bind_method(_MD("popup_centered_minsize","minsize"),&Popup::popup_centered_minsize,DEFVAL(Size2())); + ClassDB::bind_method(_MD("popup"),&Popup::popup); + ClassDB::bind_method(_MD("set_exclusive","enable"),&Popup::set_exclusive); + ClassDB::bind_method(_MD("is_exclusive"),&Popup::is_exclusive); ADD_SIGNAL( MethodInfo("about_to_show") ); ADD_SIGNAL( MethodInfo("popup_hide") ); - ADD_PROPERTY( PropertyInfo( Variant::BOOL, "popup/exclusive"), _SCS("set_exclusive"),_SCS("is_exclusive") ); + ADD_GROUP("Popup","popup_"); + ADD_PROPERTY( PropertyInfo( Variant::BOOL, "popup_exclusive"), _SCS("set_exclusive"),_SCS("is_exclusive") ); BIND_CONSTANT(NOTIFICATION_POST_POPUP); BIND_CONSTANT(NOTIFICATION_POPUP_HIDE); @@ -286,7 +283,7 @@ Popup::Popup() { String Popup::get_configuration_warning() const { - if (is_visible()) { + if (is_visible_in_tree()) { return TTR("Popups will hide by default unless you call popup() or any of the popup*() functions. Making them visible for editing is fine though, but they will hide upon running."); } diff --git a/scene/gui/popup.h b/scene/gui/popup.h index dccaf2ae69..17ae4a938a 100644 --- a/scene/gui/popup.h +++ b/scene/gui/popup.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 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 */ @@ -36,7 +36,7 @@ */ class Popup : public Control { - OBJ_TYPE( Popup, Control ); + GDCLASS( Popup, Control ); bool exclusive; bool popped_up; @@ -45,7 +45,7 @@ protected: virtual void _post_popup() {} - void _input_event(InputEvent p_event); + void _gui_input(InputEvent p_event); void _notification(int p_what); void _fix_size(); static void _bind_methods(); @@ -74,7 +74,7 @@ public: class PopupPanel : public Popup { - OBJ_TYPE(PopupPanel,Popup); + GDCLASS(PopupPanel,Popup); protected: diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp index 819885809b..65e7c3ab39 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-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 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 */ @@ -32,9 +32,16 @@ #include "translation.h" #include "os/input.h" -String PopupMenu::_get_accel_text(uint32_t p_accel) const { +String PopupMenu::_get_accel_text(int p_item) const { + + ERR_FAIL_INDEX_V(p_item,items.size(),String()); + + if (items[p_item].shortcut.is_valid()) + return items[p_item].shortcut->get_as_text(); + else if (items[p_item].accel) + return keycode_get_string(items[p_item].accel); + return String(); - return keycode_get_string(p_accel); /* String atxt; if (p_accel&KEY_MASK_SHIFT) @@ -82,22 +89,26 @@ Size2 PopupMenu::get_minimum_size() const { size.height=font_h; } + size.width+=items[i].h_ofs; + if (items[i].checkable) { size.width+=check_w+hseparation; } - size.width+=font->get_string_size(items[i].text).width; + String text = items[i].shortcut.is_valid() ? String(tr(items[i].shortcut->get_name())) : items[i].xl_text; + size.width+=font->get_string_size(text).width; if (i>0) size.height+=vseparation; - if (items[i].accel) { + if (items[i].accel || (items[i].shortcut.is_valid() && items[i].shortcut->is_valid())) { int accel_w = hseparation*2; - accel_w+=font->get_string_size(_get_accel_text(items[i].accel)).width; + accel_w+=font->get_string_size(_get_accel_text(i)).width; accel_max_w = MAX( accel_w, accel_max_w ); } + minsize.height+=size.height; max_w = MAX( max_w, size.width ); @@ -125,7 +136,7 @@ int PopupMenu::_get_mouse_over(const Point2& p_over) const { Ref<Font> font = get_font("font"); int vseparation = get_constant("vseparation"); -// int hseparation = get_constant("hseparation"); + //int hseparation = get_constant("hseparation"); float font_h=font->get_height(); @@ -163,7 +174,7 @@ void PopupMenu::_activate_submenu(int over) { Popup *pm = n->cast_to<Popup>(); ERR_EXPLAIN("item subnode is not a Popup: "+items[over].submenu); ERR_FAIL_COND(!pm); - if (pm->is_visible()) + if (pm->is_visible_in_tree()) return; //already visible! @@ -204,7 +215,7 @@ void PopupMenu::_submenu_timeout() { } -void PopupMenu::_input_event(const InputEvent &p_event) { +void PopupMenu::_gui_input(const InputEvent &p_event) { switch( p_event.type) { @@ -297,7 +308,7 @@ void PopupMenu::_input_event(const InputEvent &p_event) { ie.type=InputEvent::MOUSE_MOTION; ie.mouse_motion.x=b.x; ie.mouse_motion.y=b.y+s; - _input_event(ie); + _gui_input(ie); } } break; case BUTTON_WHEEL_UP: { @@ -317,7 +328,7 @@ void PopupMenu::_input_event(const InputEvent &p_event) { ie.type=InputEvent::MOUSE_MOTION; ie.mouse_motion.x=b.x; ie.mouse_motion.y=b.y-s; - _input_event(ie); + _gui_input(ie); } @@ -410,7 +421,16 @@ void PopupMenu::_notification(int p_what) { switch(p_what) { + case NOTIFICATION_TRANSLATION_CHANGED: { + for(int i=0;i<items.size();i++) { + items[i].xl_text=XL_MESSAGE(items[i].text); + } + + minimum_size_changed(); + update(); + + } break; case NOTIFICATION_DRAW: { RID ci = get_canvas_item(); @@ -442,6 +462,7 @@ void PopupMenu::_notification(int p_what) { float h; Size2 icon_size; + item_ofs.x+=items[i].h_ofs; if (!items[i].icon.is_null()) { icon_size = items[i].icon->get_size(); @@ -453,13 +474,13 @@ void PopupMenu::_notification(int p_what) { if (i==mouse_over) { - hover->draw(ci, Rect2( ofs+Point2(-hseparation,-vseparation), Size2( get_size().width - style->get_minimum_size().width + hseparation*2, h+vseparation*2 ) )); + hover->draw(ci, Rect2( item_ofs+Point2(-hseparation,-vseparation), Size2( get_size().width - style->get_minimum_size().width + hseparation*2, h+vseparation*2 ) )); } if (items[i].separator) { int sep_h=separator->get_center_size().height+separator->get_minimum_size().height; - separator->draw(ci, Rect2( ofs+Point2(0,Math::floor((h-sep_h)/2.0)), Size2( get_size().width - style->get_minimum_size().width , sep_h ) )); + separator->draw(ci, Rect2( item_ofs+Point2(0,Math::floor((h-sep_h)/2.0)), Size2( get_size().width - style->get_minimum_size().width , sep_h ) )); } @@ -484,13 +505,15 @@ void PopupMenu::_notification(int p_what) { } item_ofs.y+=font->get_ascent(); - if (!items[i].separator) - font->draw(ci,item_ofs+Point2(0,Math::floor((h-font_h)/2.0)),items[i].text,items[i].disabled?font_color_disabled:(i==mouse_over?font_color_hover:font_color)); + String text = items[i].shortcut.is_valid() ? String(tr(items[i].shortcut->get_name())) : items[i].xl_text; + if (!items[i].separator) { + font->draw(ci,item_ofs+Point2(0,Math::floor((h-font_h)/2.0)),text,items[i].disabled?font_color_disabled:(i==mouse_over?font_color_hover:font_color)); + } - if (items[i].accel) { + if (items[i].accel || (items[i].shortcut.is_valid() && items[i].shortcut->is_valid())) { //accelerator - String text = _get_accel_text(items[i].accel); + String text = _get_accel_text(i); item_ofs.x=size.width-style->get_margin(MARGIN_RIGHT)-font->get_string_size(text).width; font->draw(ci,item_ofs+Point2(0,Math::floor((h-font_h)/2.0)),text,i==mouse_over?font_color_hover:font_color_accel); @@ -523,6 +546,7 @@ void PopupMenu::add_icon_item(const Ref<Texture>& p_icon,const String& p_label,i Item item; item.icon=p_icon; item.text=p_label; + item.xl_text=XL_MESSAGE(p_label); item.accel=p_accel; item.ID=p_ID; items.push_back(item); @@ -531,7 +555,8 @@ void PopupMenu::add_icon_item(const Ref<Texture>& p_icon,const String& p_label,i void PopupMenu::add_item(const String& p_label,int p_ID,uint32_t p_accel) { Item item; - item.text=XL_MESSAGE(p_label); + item.text=p_label; + item.xl_text=XL_MESSAGE(p_label); item.accel=p_accel; item.ID=p_ID; items.push_back(item); @@ -541,7 +566,8 @@ void PopupMenu::add_item(const String& p_label,int p_ID,uint32_t p_accel) { void PopupMenu::add_submenu_item(const String& p_label, const String& p_submenu,int p_ID){ Item item; - item.text=XL_MESSAGE(p_label); + item.text=p_label; + item.xl_text=XL_MESSAGE(p_label); item.ID=p_ID; item.submenu=p_submenu; items.push_back(item); @@ -552,7 +578,8 @@ void PopupMenu::add_icon_check_item(const Ref<Texture>& p_icon,const String& p_l Item item; item.icon=p_icon; - item.text=XL_MESSAGE(p_label); + item.text=p_label; + item.xl_text=XL_MESSAGE(p_label); item.accel=p_accel; item.ID=p_ID; item.checkable=true; @@ -562,7 +589,8 @@ void PopupMenu::add_icon_check_item(const Ref<Texture>& p_icon,const String& p_l void PopupMenu::add_check_item(const String& p_label,int p_ID,uint32_t p_accel) { Item item; - item.text=XL_MESSAGE(p_label); + item.text=p_label; + item.xl_text=XL_MESSAGE(p_label); item.accel=p_accel; item.ID=p_ID; item.checkable=true; @@ -570,10 +598,73 @@ void PopupMenu::add_check_item(const String& p_label,int p_ID,uint32_t p_accel) update(); } + +void PopupMenu::add_icon_shortcut(const Ref<Texture>& p_icon, const Ref<ShortCut>& p_shortcut, int p_ID, bool p_global) { + + ERR_FAIL_COND(p_shortcut.is_null()); + + _ref_shortcut(p_shortcut); + + Item item; + item.ID=p_ID; + item.icon=p_icon; + item.shortcut=p_shortcut; + item.shortcut_is_global=p_global; + items.push_back(item); + update(); + +} + +void PopupMenu::add_shortcut(const Ref<ShortCut>& p_shortcut, int p_ID, bool p_global){ + + ERR_FAIL_COND(p_shortcut.is_null()); + + _ref_shortcut(p_shortcut); + + Item item; + item.ID=p_ID; + item.shortcut=p_shortcut; + item.shortcut_is_global=p_global; + items.push_back(item); + update(); + +} +void PopupMenu::add_icon_check_shortcut(const Ref<Texture>& p_icon, const Ref<ShortCut>& p_shortcut, int p_ID, bool p_global){ + + ERR_FAIL_COND(p_shortcut.is_null()); + + _ref_shortcut(p_shortcut); + + Item item; + item.ID=p_ID; + item.shortcut=p_shortcut; + item.checkable=true; + item.icon=p_icon; + item.shortcut_is_global=p_global; + items.push_back(item); + update(); +} + +void PopupMenu::add_check_shortcut(const Ref<ShortCut>& p_shortcut, int p_ID, bool p_global){ + + ERR_FAIL_COND(p_shortcut.is_null()); + + _ref_shortcut(p_shortcut); + + Item item; + item.ID=p_ID; + item.shortcut=p_shortcut; + item.shortcut_is_global=p_global; + item.checkable=true; + items.push_back(item); + update(); +} + void PopupMenu::set_item_text(int p_idx,const String& p_text) { ERR_FAIL_INDEX(p_idx,items.size()); - items[p_idx].text=XL_MESSAGE(p_text); + items[p_idx].text=p_text; + items[p_idx].xl_text=XL_MESSAGE(p_text); update(); @@ -633,6 +724,13 @@ void PopupMenu::set_item_submenu(int p_idx, const String& p_submenu) { update(); } +void PopupMenu::toggle_item_checked(int p_idx) { + + ERR_FAIL_INDEX(p_idx,items.size()); + items[p_idx].checked = !items[p_idx].checked; + update(); +} + String PopupMenu::get_item_text(int p_idx) const { ERR_FAIL_INDEX_V(p_idx,items.size(),""); @@ -701,6 +799,12 @@ String PopupMenu::get_item_tooltip(int p_idx) const { return items[p_idx].tooltip; } +Ref<ShortCut> PopupMenu::get_item_shortcut(int p_idx) const { + + ERR_FAIL_INDEX_V(p_idx,items.size(),Ref<ShortCut>()); + return items[p_idx].shortcut; +} + void PopupMenu::set_item_as_separator(int p_idx, bool p_separator) { ERR_FAIL_INDEX(p_idx,items.size()); @@ -730,6 +834,32 @@ void PopupMenu::set_item_tooltip(int p_idx,const String& p_tooltip) { update(); } +void PopupMenu::set_item_shortcut(int p_idx, const Ref<ShortCut>& p_shortcut, bool p_global) { + ERR_FAIL_INDEX(p_idx,items.size()); + if (items[p_idx].shortcut.is_valid()) { + _unref_shortcut(items[p_idx].shortcut); + } + items[p_idx].shortcut=p_shortcut; + items[p_idx].shortcut_is_global=p_global; + + + if (items[p_idx].shortcut.is_valid()) { + _ref_shortcut(items[p_idx].shortcut); + } + + + update(); +} + +void PopupMenu::set_item_h_offset(int p_idx, int p_offset) { + + ERR_FAIL_INDEX(p_idx,items.size()); + items[p_idx].h_ofs=p_offset; + update(); + +} + + bool PopupMenu::is_item_checkable(int p_idx) const { ERR_FAIL_INDEX_V(p_idx,items.size(),false); return items[p_idx].checkable; @@ -740,14 +870,36 @@ int PopupMenu::get_item_count() const { return items.size(); } -bool PopupMenu::activate_item_by_accelerator(uint32_t p_accel) { +bool PopupMenu::activate_item_by_event(const InputEvent& p_event, bool p_for_global_only) { + + uint32_t code=0; + if (p_event.type==InputEvent::KEY) { + code=p_event.key.scancode; + if (code==0) + code=p_event.key.unicode; + if (p_event.key.mod.control) + code|=KEY_MASK_CTRL; + if (p_event.key.mod.alt) + code|=KEY_MASK_ALT; + if (p_event.key.mod.meta) + code|=KEY_MASK_META; + if (p_event.key.mod.shift) + code|=KEY_MASK_SHIFT; + } + int il=items.size(); for(int i=0;i<il;i++) { if (is_item_disabled(i)) continue; - if (items[i].accel==p_accel) { + + if (items[i].shortcut.is_valid() && items[i].shortcut->is_shortcut(p_event) && (items[i].shortcut_is_global || !p_for_global_only)) { + activate_item(i); + return true; + } + + if (code!=0 && items[i].accel==code) { activate_item(i); return true; } @@ -761,7 +913,7 @@ bool PopupMenu::activate_item_by_accelerator(uint32_t p_accel) { if(!pm) continue; - if(pm->activate_item_by_accelerator(p_accel)) { + if(pm->activate_item_by_event(p_event,p_for_global_only)) { return true; } } @@ -775,22 +927,42 @@ void PopupMenu::activate_item(int p_item) { ERR_FAIL_INDEX(p_item,items.size()); ERR_FAIL_COND(items[p_item].separator); int id = items[p_item].ID>=0?items[p_item].ID:p_item; - emit_signal("item_pressed",id); + emit_signal("id_pressed",id); + emit_signal("index_pressed",p_item); //hide all parent PopupMenue's Node *next = get_parent(); PopupMenu *pop = next->cast_to<PopupMenu>(); while (pop) { - pop->hide(); - next = next->get_parent(); - pop = next->cast_to<PopupMenu>(); + // We close all parents that are chained together, + // with hide_on_item_selection enabled + if(hide_on_item_selection && pop->is_hide_on_item_selection()) { + pop->hide(); + next = next->get_parent(); + pop = next->cast_to<PopupMenu>(); + } + else { + // Break out of loop when the next parent has + // hide_on_item_selection disabled + break; + } + } + // Hides popup by default; unless otherwise specified + // by using set_hide_on_item_selection + if (hide_on_item_selection) { + hide(); } - hide(); } void PopupMenu::remove_item(int p_idx) { + ERR_FAIL_INDEX(p_idx,items.size()); + + if (items[p_idx].shortcut.is_valid()) { + _unref_shortcut(items[p_idx].shortcut); + } + items.remove(p_idx); update(); } @@ -806,6 +978,11 @@ void PopupMenu::add_separator() { void PopupMenu::clear() { + for(int i=0;i<items.size();i++) { + if (items[i].shortcut.is_valid()) { + _unref_shortcut(items[i].shortcut); + } + } items.clear(); mouse_over=-1; update(); @@ -834,6 +1011,27 @@ Array PopupMenu::_get_items() const { return items; } + +void PopupMenu::_ref_shortcut( Ref<ShortCut> p_sc) { + + if (!shortcut_refcount.has(p_sc)) { + shortcut_refcount[p_sc]=1; + p_sc->connect("changed",this,"update"); + } else { + shortcut_refcount[p_sc]+=1; + } +} + +void PopupMenu::_unref_shortcut(Ref<ShortCut> p_sc) { + + ERR_FAIL_COND(!shortcut_refcount.has(p_sc)); + shortcut_refcount[p_sc]--; + if (shortcut_refcount[p_sc]==0) { + p_sc->disconnect("changed",this,"update"); + shortcut_refcount.erase(p_sc); + } +} + void PopupMenu::_set_items(const Array& p_items){ ERR_FAIL_COND(p_items.size() % 10); @@ -869,6 +1067,16 @@ void PopupMenu::_set_items(const Array& p_items){ } +// Hide on item selection determines whether or not the popup will close after item selection +void PopupMenu::set_hide_on_item_selection(bool p_enabled) { + + hide_on_item_selection=p_enabled; +} + +bool PopupMenu::is_hide_on_item_selection() { + + return hide_on_item_selection; +} String PopupMenu::get_tooltip(const Point2& p_pos) const { @@ -889,8 +1097,8 @@ void PopupMenu::get_translatable_strings(List<String> *p_strings) const { for(int i=0;i<items.size();i++) { - if (items[i].text!="") - p_strings->push_back(items[i].text); + if (items[i].xl_text!="") + p_strings->push_back(items[i].xl_text); } } @@ -906,46 +1114,67 @@ void PopupMenu::clear_autohide_areas(){ void PopupMenu::_bind_methods() { - ObjectTypeDB::bind_method(_MD("_input_event"),&PopupMenu::_input_event); - ObjectTypeDB::bind_method(_MD("add_icon_item","texture","label","id","accel"),&PopupMenu::add_icon_item,DEFVAL(-1),DEFVAL(0)); - ObjectTypeDB::bind_method(_MD("add_item","label","id","accel"),&PopupMenu::add_item,DEFVAL(-1),DEFVAL(0)); - ObjectTypeDB::bind_method(_MD("add_icon_check_item","texture","label","id","accel"),&PopupMenu::add_icon_check_item,DEFVAL(-1),DEFVAL(0)); - ObjectTypeDB::bind_method(_MD("add_check_item","label","id","accel"),&PopupMenu::add_check_item,DEFVAL(-1),DEFVAL(0)); - ObjectTypeDB::bind_method(_MD("add_submenu_item","label","submenu","id"),&PopupMenu::add_submenu_item,DEFVAL(-1)); - ObjectTypeDB::bind_method(_MD("set_item_text","idx","text"),&PopupMenu::set_item_text); - ObjectTypeDB::bind_method(_MD("set_item_icon","idx","icon"),&PopupMenu::set_item_icon); - ObjectTypeDB::bind_method(_MD("set_item_accelerator","idx","accel"),&PopupMenu::set_item_accelerator); - ObjectTypeDB::bind_method(_MD("set_item_metadata","idx","metadata"),&PopupMenu::set_item_metadata); - ObjectTypeDB::bind_method(_MD("set_item_checked","idx","checked"),&PopupMenu::set_item_checked); - ObjectTypeDB::bind_method(_MD("set_item_disabled","idx","disabled"),&PopupMenu::set_item_disabled); - ObjectTypeDB::bind_method(_MD("set_item_submenu","idx","submenu"),&PopupMenu::set_item_submenu); - ObjectTypeDB::bind_method(_MD("set_item_as_separator","idx","enable"),&PopupMenu::set_item_as_separator); - ObjectTypeDB::bind_method(_MD("set_item_as_checkable","idx","enable"),&PopupMenu::set_item_as_checkable); - ObjectTypeDB::bind_method(_MD("set_item_ID","idx","id"),&PopupMenu::set_item_ID); - ObjectTypeDB::bind_method(_MD("get_item_text","idx"),&PopupMenu::get_item_text); - ObjectTypeDB::bind_method(_MD("get_item_icon","idx"),&PopupMenu::get_item_icon); - ObjectTypeDB::bind_method(_MD("get_item_metadata","idx"),&PopupMenu::get_item_metadata); - ObjectTypeDB::bind_method(_MD("get_item_accelerator","idx"),&PopupMenu::get_item_accelerator); - ObjectTypeDB::bind_method(_MD("get_item_submenu","idx"),&PopupMenu::get_item_submenu); - ObjectTypeDB::bind_method(_MD("is_item_separator","idx"),&PopupMenu::is_item_separator); - ObjectTypeDB::bind_method(_MD("is_item_checkable","idx"),&PopupMenu::is_item_checkable); - ObjectTypeDB::bind_method(_MD("is_item_checked","idx"),&PopupMenu::is_item_checked); - ObjectTypeDB::bind_method(_MD("is_item_disabled","idx"),&PopupMenu::is_item_disabled); - ObjectTypeDB::bind_method(_MD("get_item_ID","idx"),&PopupMenu::get_item_ID); - ObjectTypeDB::bind_method(_MD("get_item_index","id"),&PopupMenu::get_item_index); - ObjectTypeDB::bind_method(_MD("get_item_count"),&PopupMenu::get_item_count); - ObjectTypeDB::bind_method(_MD("add_separator"),&PopupMenu::add_separator); - ObjectTypeDB::bind_method(_MD("remove_item","idx"),&PopupMenu::remove_item); - ObjectTypeDB::bind_method(_MD("clear"),&PopupMenu::clear); - - ObjectTypeDB::bind_method(_MD("_set_items"),&PopupMenu::_set_items); - ObjectTypeDB::bind_method(_MD("_get_items"),&PopupMenu::_get_items); - - ObjectTypeDB::bind_method(_MD("_submenu_timeout"),&PopupMenu::_submenu_timeout); + ClassDB::bind_method(_MD("_gui_input"),&PopupMenu::_gui_input); + ClassDB::bind_method(_MD("add_icon_item","texture","label","id","accel"),&PopupMenu::add_icon_item,DEFVAL(-1),DEFVAL(0)); + ClassDB::bind_method(_MD("add_item","label","id","accel"),&PopupMenu::add_item,DEFVAL(-1),DEFVAL(0)); + ClassDB::bind_method(_MD("add_icon_check_item","texture","label","id","accel"),&PopupMenu::add_icon_check_item,DEFVAL(-1),DEFVAL(0)); + ClassDB::bind_method(_MD("add_check_item","label","id","accel"),&PopupMenu::add_check_item,DEFVAL(-1),DEFVAL(0)); + ClassDB::bind_method(_MD("add_submenu_item","label","submenu","id"),&PopupMenu::add_submenu_item,DEFVAL(-1)); + + ClassDB::bind_method(_MD("add_icon_shortcut","texture","shortcut:ShortCut","id","global"),&PopupMenu::add_icon_shortcut,DEFVAL(-1),DEFVAL(false)); + ClassDB::bind_method(_MD("add_shortcut","shortcut:ShortCut","id","global"),&PopupMenu::add_shortcut,DEFVAL(-1),DEFVAL(false)); + ClassDB::bind_method(_MD("add_icon_check_shortcut","texture","shortcut:ShortCut","id","global"),&PopupMenu::add_icon_check_shortcut,DEFVAL(-1),DEFVAL(false)); + ClassDB::bind_method(_MD("add_check_shortcut","shortcut:ShortCut","id","global"),&PopupMenu::add_check_shortcut,DEFVAL(-1),DEFVAL(false)); + + ClassDB::bind_method(_MD("set_item_text","idx","text"),&PopupMenu::set_item_text); + ClassDB::bind_method(_MD("set_item_icon","idx","icon"),&PopupMenu::set_item_icon); + ClassDB::bind_method(_MD("set_item_checked","idx","checked"),&PopupMenu::set_item_checked); + ClassDB::bind_method(_MD("set_item_ID","idx","id"),&PopupMenu::set_item_ID); + ClassDB::bind_method(_MD("set_item_accelerator","idx","accel"),&PopupMenu::set_item_accelerator); + ClassDB::bind_method(_MD("set_item_metadata","idx","metadata"),&PopupMenu::set_item_metadata); + ClassDB::bind_method(_MD("set_item_disabled","idx","disabled"),&PopupMenu::set_item_disabled); + ClassDB::bind_method(_MD("set_item_submenu","idx","submenu"),&PopupMenu::set_item_submenu); + ClassDB::bind_method(_MD("set_item_as_separator","idx","enable"),&PopupMenu::set_item_as_separator); + ClassDB::bind_method(_MD("set_item_as_checkable","idx","enable"),&PopupMenu::set_item_as_checkable); + ClassDB::bind_method(_MD("set_item_tooltip","idx","tooltip"),&PopupMenu::set_item_tooltip); + ClassDB::bind_method(_MD("set_item_shortcut","idx","shortcut:ShortCut","global"),&PopupMenu::set_item_shortcut,DEFVAL(false)); + + ClassDB::bind_method(_MD("toggle_item_checked","idx"), &PopupMenu::toggle_item_checked); + + ClassDB::bind_method(_MD("get_item_text","idx"),&PopupMenu::get_item_text); + ClassDB::bind_method(_MD("get_item_icon","idx"),&PopupMenu::get_item_icon); + ClassDB::bind_method(_MD("is_item_checked","idx"),&PopupMenu::is_item_checked); + ClassDB::bind_method(_MD("get_item_ID","idx"),&PopupMenu::get_item_ID); + ClassDB::bind_method(_MD("get_item_index","id"),&PopupMenu::get_item_index); + ClassDB::bind_method(_MD("get_item_accelerator","idx"),&PopupMenu::get_item_accelerator); + ClassDB::bind_method(_MD("get_item_metadata","idx"),&PopupMenu::get_item_metadata); + ClassDB::bind_method(_MD("is_item_disabled","idx"),&PopupMenu::is_item_disabled); + ClassDB::bind_method(_MD("get_item_submenu","idx"),&PopupMenu::get_item_submenu); + ClassDB::bind_method(_MD("is_item_separator","idx"),&PopupMenu::is_item_separator); + ClassDB::bind_method(_MD("is_item_checkable","idx"),&PopupMenu::is_item_checkable); + ClassDB::bind_method(_MD("get_item_tooltip","idx"),&PopupMenu::get_item_tooltip); + ClassDB::bind_method(_MD("get_item_shortcut:ShortCut","idx"),&PopupMenu::get_item_shortcut); + + ClassDB::bind_method(_MD("get_item_count"),&PopupMenu::get_item_count); + + ClassDB::bind_method(_MD("remove_item","idx"),&PopupMenu::remove_item); + + ClassDB::bind_method(_MD("add_separator"),&PopupMenu::add_separator); + ClassDB::bind_method(_MD("clear"),&PopupMenu::clear); + + ClassDB::bind_method(_MD("_set_items"),&PopupMenu::_set_items); + ClassDB::bind_method(_MD("_get_items"),&PopupMenu::_get_items); + + ClassDB::bind_method(_MD("set_hide_on_item_selection","enable"),&PopupMenu::set_hide_on_item_selection); + ClassDB::bind_method(_MD("is_hide_on_item_selection"),&PopupMenu::is_hide_on_item_selection); + + ClassDB::bind_method(_MD("_submenu_timeout"),&PopupMenu::_submenu_timeout); ADD_PROPERTY( PropertyInfo(Variant::ARRAY,"items",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR), _SCS("_set_items"),_SCS("_get_items") ); + ADD_PROPERTYNO( PropertyInfo(Variant::BOOL, "hide_on_item_selection" ), _SCS("set_hide_on_item_selection"), _SCS("is_hide_on_item_selection") ); - ADD_SIGNAL( MethodInfo("item_pressed", PropertyInfo( Variant::INT,"ID") ) ); + ADD_SIGNAL( MethodInfo("id_pressed", PropertyInfo( Variant::INT,"ID") ) ); + ADD_SIGNAL( MethodInfo("index_pressed", PropertyInfo( Variant::INT,"index") ) ); } @@ -962,6 +1191,7 @@ PopupMenu::PopupMenu() { set_focus_mode(FOCUS_ALL); set_as_toplevel(true); + set_hide_on_item_selection(true); submenu_timer = memnew( Timer ); submenu_timer->set_wait_time(0.3); @@ -973,5 +1203,3 @@ PopupMenu::PopupMenu() { PopupMenu::~PopupMenu() { } - - diff --git a/scene/gui/popup_menu.h b/scene/gui/popup_menu.h index 0e98765dc4..b5fca9a451 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-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 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,13 +34,17 @@ /** @author Juan Linietsky <reduzio@gmail.com> */ + + + class PopupMenu : public Popup { - OBJ_TYPE(PopupMenu, Popup ); + GDCLASS(PopupMenu, Popup ); struct Item { Ref<Texture> icon; String text; + String xl_text; bool checked; bool checkable; bool separator; @@ -51,8 +55,11 @@ class PopupMenu : public Popup { String tooltip; uint32_t accel; int _ofs_cache; + int h_ofs; + Ref<ShortCut> shortcut; + bool shortcut_is_global; - Item() { checked=false; checkable=false; separator=false; accel=0; disabled=false; _ofs_cache=0; } + Item() { checked=false; checkable=false; separator=false; accel=0; disabled=false; _ofs_cache=0; h_ofs=0; shortcut_is_global=false; } }; @@ -62,19 +69,24 @@ class PopupMenu : public Popup { int mouse_over; int submenu_over; Rect2 parent_rect; - String _get_accel_text(uint32_t p_accel) const; + String _get_accel_text(int p_item) const; int _get_mouse_over(const Point2& p_over) const; virtual Size2 get_minimum_size() const; - void _input_event(const InputEvent &p_event); + void _gui_input(const InputEvent &p_event); void _activate_submenu(int over); void _submenu_timeout(); bool invalidated_click; + bool hide_on_item_selection; Vector2 moved; Array _get_items() const; void _set_items(const Array& p_items); + Map< Ref<ShortCut>, int> shortcut_refcount; + + void _ref_shortcut(Ref<ShortCut> p_sc); + void _unref_shortcut( Ref<ShortCut> p_sc); protected: virtual bool has_point(const Point2& p_point) const; @@ -90,6 +102,11 @@ public: void add_check_item(const String& p_label,int p_ID=-1,uint32_t p_accel=0); void add_submenu_item(const String& p_label,const String& p_submenu, int p_ID=-1); + void add_icon_shortcut(const Ref<Texture>& p_icon,const Ref<ShortCut>& p_shortcut,int p_ID=-1,bool p_global=false); + void add_shortcut(const Ref<ShortCut>& p_shortcut,int p_ID=-1,bool p_global=false); + void add_icon_check_shortcut(const Ref<Texture>& p_icon,const Ref<ShortCut>& p_shortcut,int p_ID=-1,bool p_global=false); + void add_check_shortcut(const Ref<ShortCut>& p_shortcut,int p_ID=-1,bool p_global=false); + void set_item_text(int p_idx,const String& p_text); void set_item_icon(int p_idx,const Ref<Texture>& p_icon); void set_item_checked(int p_idx,bool p_checked); @@ -101,6 +118,10 @@ public: void set_item_as_separator(int p_idx, bool p_separator); void set_item_as_checkable(int p_idx, bool p_checkable); void set_item_tooltip(int p_idx,const String& p_tooltip); + void set_item_shortcut(int p_idx, const Ref<ShortCut>& p_shortcut,bool p_global=false); + void set_item_h_offset(int p_idx, int p_offset); + + void toggle_item_checked(int p_idx); String get_item_text(int p_idx) const; Ref<Texture> get_item_icon(int p_idx) const; @@ -114,10 +135,11 @@ public: bool is_item_separator(int p_idx) const; bool is_item_checkable(int p_idx) const; String get_item_tooltip(int p_idx) const; + Ref<ShortCut> get_item_shortcut(int p_idx) const; int get_item_count() const; - bool activate_item_by_accelerator(uint32_t p_accel); + bool activate_item_by_event(const InputEvent& p_event,bool p_for_global_only=false); void activate_item(int p_item); void remove_item(int p_idx); @@ -136,6 +158,8 @@ public: void clear_autohide_areas(); void set_invalidate_click_until_motion(); + void set_hide_on_item_selection(bool p_enabled); + bool is_hide_on_item_selection(); PopupMenu(); ~PopupMenu(); diff --git a/scene/gui/progress_bar.cpp b/scene/gui/progress_bar.cpp index 02da8ff27e..0f99d4f19e 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-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 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,10 +51,9 @@ void ProgressBar::_notification(int p_what) { Ref<StyleBox> fg = get_stylebox("fg"); Ref<Font> font = get_font("font"); Color font_color=get_color("font_color"); - Color font_color_shadow=get_color("font_color_shadow"); draw_style_box(bg,Rect2(Point2(),get_size())); - float r = get_unit_value(); + float r = get_as_ratio(); int mp = fg->get_minimum_size().width; int p = r*get_size().width-mp; if (p>0) { @@ -63,8 +62,7 @@ void ProgressBar::_notification(int p_what) { } if (percent_visible) { - int fh=font->get_height(); - String txt=itos(int(get_unit_value()*100))+"%"; + String txt=itos(int(get_as_ratio()*100))+"%"; font->draw_halign(get_canvas_item(),Point2(0,font->get_ascent()+(get_size().height-font->get_height())/2),HALIGN_CENTER,get_size().width,txt,font_color); } } @@ -84,9 +82,10 @@ bool ProgressBar::is_percent_visible() const{ void ProgressBar::_bind_methods() { - ObjectTypeDB::bind_method(_MD("set_percent_visible","visible"),&ProgressBar::set_percent_visible); - ObjectTypeDB::bind_method(_MD("is_percent_visible"),&ProgressBar::is_percent_visible); - ADD_PROPERTY(PropertyInfo(Variant::BOOL,"percent/visible"),_SCS("set_percent_visible"),_SCS("is_percent_visible")); + ClassDB::bind_method(_MD("set_percent_visible","visible"),&ProgressBar::set_percent_visible); + ClassDB::bind_method(_MD("is_percent_visible"),&ProgressBar::is_percent_visible); + ADD_GROUP("Percent","percent_"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL,"percent_visible"),_SCS("set_percent_visible"),_SCS("is_percent_visible")); } ProgressBar::ProgressBar() { diff --git a/scene/gui/progress_bar.h b/scene/gui/progress_bar.h index f50df346ac..01306a2ac4 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-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 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 */ @@ -33,7 +33,7 @@ class ProgressBar : public Range { - OBJ_TYPE( ProgressBar, Range ); + GDCLASS( ProgressBar, Range ); bool percent_visible; protected: diff --git a/scene/gui/range.cpp b/scene/gui/range.cpp index e056c55f71..d5c1034c9c 100644 --- a/scene/gui/range.cpp +++ b/scene/gui/range.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 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 */ @@ -66,7 +66,7 @@ void Range::Shared::emit_changed(const char *p_what) { } -void Range::set_val(double p_val) { +void Range::set_value(double p_val) { if(_rounded_values){ p_val = Math::round(p_val); @@ -88,14 +88,14 @@ void Range::set_val(double p_val) { void Range::set_min(double p_min) { shared->min=p_min; - set_val(shared->val); + set_value(shared->val); shared->emit_changed("range/min"); } void Range::set_max(double p_max) { shared->max=p_max; - set_val(shared->val); + set_value(shared->val); shared->emit_changed("range/max"); @@ -109,12 +109,12 @@ void Range::set_step(double p_step) { void Range::set_page(double p_page) { shared->page=p_page; - set_val(shared->val); + set_value(shared->val); shared->emit_changed("range/page"); } -double Range::get_val() const { +double Range::get_value() const { return shared->val; } @@ -135,31 +135,40 @@ double Range::get_page() const { return shared->page; } -void Range::set_unit_value(double p_value) { - if (shared->exp_unit_value && get_min()>0) { +void Range::set_as_ratio(double p_value) { + + double v; + + if (shared->exp_ratio && get_min()>0) { double exp_min = Math::log(get_min())/Math::log(2); double exp_max = Math::log(get_max())/Math::log(2); - double v = Math::pow(2,exp_min+(exp_max-exp_min)*p_value); - - set_val( v ); + v = Math::pow(2,exp_min+(exp_max-exp_min)*p_value); } else { - set_val( (get_max() - get_min()) * p_value + get_min() ); + + double percent = (get_max() - get_min()) * p_value; + if (get_step() > 0) { + double steps = round(percent / get_step()); + v = steps * get_step() + get_min(); + } else { + v = percent + get_min(); + } } + set_value( v ); } -double Range::get_unit_value() const { +double Range::get_as_ratio() const { - if (shared->exp_unit_value && get_min()>0) { + if (shared->exp_ratio && get_min()>0) { double exp_min = Math::log(get_min())/Math::log(2); double exp_max = Math::log(get_max())/Math::log(2); - double v = Math::log(get_val())/Math::log(2); + double v = Math::log(get_value())/Math::log(2); return (v - exp_min) / (exp_max - exp_min); } else { - return (get_val() - get_min()) / (get_max() - get_min()); + return (get_value() - get_min()) / (get_max() - get_min()); } } @@ -213,59 +222,57 @@ void Range::_unref_shared() { void Range::_bind_methods() { - ObjectTypeDB::bind_method(_MD("get_val"),&Range::get_val); - ObjectTypeDB::bind_method(_MD("get_value"),&Range::get_val); - ObjectTypeDB::bind_method(_MD("get_min"),&Range::get_min); - ObjectTypeDB::bind_method(_MD("get_max"),&Range::get_max); - ObjectTypeDB::bind_method(_MD("get_step"),&Range::get_step); - ObjectTypeDB::bind_method(_MD("get_page"),&Range::get_page); - ObjectTypeDB::bind_method(_MD("get_unit_value"),&Range::get_unit_value); - ObjectTypeDB::bind_method(_MD("set_val","value"),&Range::set_val); - ObjectTypeDB::bind_method(_MD("set_value","value"),&Range::set_val); - ObjectTypeDB::bind_method(_MD("set_min","minimum"),&Range::set_min); - ObjectTypeDB::bind_method(_MD("set_max","maximum"),&Range::set_max); - ObjectTypeDB::bind_method(_MD("set_step","step"),&Range::set_step); - ObjectTypeDB::bind_method(_MD("set_page","pagesize"),&Range::set_page); - ObjectTypeDB::bind_method(_MD("set_unit_value","value"),&Range::set_unit_value); - ObjectTypeDB::bind_method(_MD("set_rounded_values","enabled"),&Range::set_rounded_values); - ObjectTypeDB::bind_method(_MD("is_rounded_values"),&Range::is_rounded_values); - ObjectTypeDB::bind_method(_MD("set_exp_unit_value","enabled"),&Range::set_exp_unit_value); - ObjectTypeDB::bind_method(_MD("is_unit_value_exp"),&Range::is_unit_value_exp); - - ObjectTypeDB::bind_method(_MD("share","with"),&Range::_share); - ObjectTypeDB::bind_method(_MD("unshare"),&Range::unshare); + ClassDB::bind_method(_MD("get_value"),&Range::get_value); + ClassDB::bind_method(_MD("get_min"),&Range::get_min); + ClassDB::bind_method(_MD("get_max"),&Range::get_max); + ClassDB::bind_method(_MD("get_step"),&Range::get_step); + ClassDB::bind_method(_MD("get_page"),&Range::get_page); + ClassDB::bind_method(_MD("get_as_ratio"),&Range::get_as_ratio); + ClassDB::bind_method(_MD("set_value","value"),&Range::set_value); + ClassDB::bind_method(_MD("set_min","minimum"),&Range::set_min); + ClassDB::bind_method(_MD("set_max","maximum"),&Range::set_max); + ClassDB::bind_method(_MD("set_step","step"),&Range::set_step); + ClassDB::bind_method(_MD("set_page","pagesize"),&Range::set_page); + ClassDB::bind_method(_MD("set_as_ratio","value"),&Range::set_as_ratio); + ClassDB::bind_method(_MD("set_use_rounded_values","enabled"),&Range::set_use_rounded_values); + ClassDB::bind_method(_MD("is_using_rounded_values"),&Range::is_using_rounded_values); + ClassDB::bind_method(_MD("set_exp_ratio","enabled"),&Range::set_exp_ratio); + ClassDB::bind_method(_MD("is_ratio_exp"),&Range::is_ratio_exp); + + ClassDB::bind_method(_MD("share","with"),&Range::_share); + ClassDB::bind_method(_MD("unshare"),&Range::unshare); ADD_SIGNAL( MethodInfo("value_changed", PropertyInfo(Variant::REAL,"value"))); ADD_SIGNAL( MethodInfo("changed")); - ADD_PROPERTY( PropertyInfo( Variant::REAL, "range/min" ), _SCS("set_min"), _SCS("get_min") ); - ADD_PROPERTY( PropertyInfo( Variant::REAL, "range/max" ), _SCS("set_max"), _SCS("get_max") ); - ADD_PROPERTY( PropertyInfo( Variant::REAL, "range/step" ), _SCS("set_step"), _SCS("get_step") ); - ADD_PROPERTY( PropertyInfo( Variant::REAL, "range/page" ), _SCS("set_page"), _SCS("get_page") ); - ADD_PROPERTY( PropertyInfo( Variant::REAL, "range/value" ), _SCS("set_val"), _SCS("get_val") ); - ADD_PROPERTY( PropertyInfo( Variant::BOOL, "range/exp_edit" ), _SCS("set_exp_unit_value"), _SCS("is_unit_value_exp") ); - ADD_PROPERTY( PropertyInfo( Variant::BOOL, "range/rounded" ), _SCS("set_rounded_values"), _SCS("is_rounded_values") ); + ADD_PROPERTY( PropertyInfo( Variant::REAL, "min_value" ), _SCS("set_min"), _SCS("get_min") ); + ADD_PROPERTY( PropertyInfo( Variant::REAL, "max_value" ), _SCS("set_max"), _SCS("get_max") ); + ADD_PROPERTY( PropertyInfo( Variant::REAL, "step" ), _SCS("set_step"), _SCS("get_step") ); + ADD_PROPERTY( PropertyInfo( Variant::REAL, "page" ), _SCS("set_page"), _SCS("get_page") ); + ADD_PROPERTY( PropertyInfo( Variant::REAL, "value" ), _SCS("set_value"), _SCS("get_value") ); + ADD_PROPERTY( PropertyInfo( Variant::BOOL, "exp_edit" ), _SCS("set_exp_ratio"), _SCS("is_ratio_exp") ); + ADD_PROPERTY( PropertyInfo( Variant::BOOL, "rounded" ), _SCS("set_use_rounded_values"), _SCS("is_using_rounded_values") ); } -void Range::set_rounded_values(bool p_enable) { +void Range::set_use_rounded_values(bool p_enable) { _rounded_values = p_enable; } -bool Range::is_rounded_values() const { +bool Range::is_using_rounded_values() const { return _rounded_values; } -void Range::set_exp_unit_value(bool p_enable) { +void Range::set_exp_ratio(bool p_enable) { - shared->exp_unit_value=p_enable; + shared->exp_ratio=p_enable; } -bool Range::is_unit_value_exp() const { +bool Range::is_ratio_exp() const { - return shared->exp_unit_value; + return shared->exp_ratio; } @@ -278,7 +285,7 @@ Range::Range() shared->step=1; shared->page=0; shared->owners.insert(this); - shared->exp_unit_value=false; + shared->exp_ratio=false; _rounded_values = false; } diff --git a/scene/gui/range.h b/scene/gui/range.h index 85c3687b7d..5f274a6901 100644 --- a/scene/gui/range.h +++ b/scene/gui/range.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 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 */ @@ -35,13 +35,13 @@ */ class Range : public Control { - OBJ_TYPE( Range, Control ); + GDCLASS( Range, Control ); struct Shared { double val,min,max; double step,page; - bool exp_unit_value; + bool exp_ratio; Set<Range*> owners; void emit_value_changed(); void emit_changed(const char *p_what=""); @@ -66,25 +66,25 @@ protected: bool _rounded_values; public: - void set_val(double p_val); + void set_value(double p_val); void set_min(double p_min); void set_max(double p_max); void set_step(double p_step); void set_page(double p_page); - void set_unit_value(double p_value); + void set_as_ratio(double p_value); - double get_val() const; + double get_value() const; double get_min() const; double get_max() const; double get_step() const; double get_page() const; - double get_unit_value() const; + double get_as_ratio() const; - void set_rounded_values(bool p_enable); - bool is_rounded_values() const; + void set_use_rounded_values(bool p_enable); + bool is_using_rounded_values() const; - void set_exp_unit_value(bool p_enable); - bool is_unit_value_exp() const; + void set_exp_ratio(bool p_enable); + bool is_ratio_exp() const; void share(Range *p_range); void unshare(); diff --git a/scene/gui/reference_frame.cpp b/scene/gui/reference_rect.cpp index d037664a62..ff4cdf04fd 100644 --- a/scene/gui/reference_frame.cpp +++ b/scene/gui/reference_rect.cpp @@ -1,11 +1,11 @@ /*************************************************************************/ -/* reference_frame.cpp */ +/* reference_rect.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 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,9 +26,9 @@ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "reference_frame.h" +#include "reference_rect.h" -void ReferenceFrame::_notification(int p_what) { +void ReferenceRect::_notification(int p_what) { if (p_what==NOTIFICATION_DRAW) { @@ -39,6 +39,6 @@ void ReferenceFrame::_notification(int p_what) { } } -ReferenceFrame::ReferenceFrame() +ReferenceRect::ReferenceRect() { } diff --git a/scene/gui/reference_frame.h b/scene/gui/reference_rect.h index 5d3694e6e8..be493f346c 100644 --- a/scene/gui/reference_frame.h +++ b/scene/gui/reference_rect.h @@ -1,11 +1,11 @@ /*************************************************************************/ -/* reference_frame.h */ +/* reference_rect.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 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,20 +26,20 @@ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef REFERENCE_FRAME_H -#define REFERENCE_FRAME_H +#ifndef REFERENCE_RECT_H +#define REFERENCE_RECT_H #include "scene/gui/control.h" -class ReferenceFrame : public Control { +class ReferenceRect : public Control { - OBJ_TYPE( ReferenceFrame, Control); + GDCLASS( ReferenceRect, Control); protected: void _notification(int p_what); public: - ReferenceFrame(); + ReferenceRect(); }; -#endif // REFERENCE_FRAME_H +#endif // REFERENCE_RECT_H diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp index 98bc0b9434..434fb36e24 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-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 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 */ @@ -270,7 +270,6 @@ if (m_height > line_height) {\ 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]!=' ')) { @@ -278,31 +277,19 @@ if (m_height > line_height) {\ if (c[end]=='\t') { cw=tab_size*font->get_char_size(' ').width; } - w+=cw; - if (c[end]==' ') { - - fw+=cw; - /* - 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; + if (end>0 && w+cw+begin > p_width ) { + break; //don't allow lines longer than assigned width } + w+=cw; + fw+=cw; + end++; } ENSURE_WIDTH(w); - //print_line("END: "+String::chr(c[end])+"."); if (end && c[end-1]==' ') { if (p_mode==PROCESS_CACHE) { spaces_size+=font->get_char_size(' ').width; @@ -314,48 +301,31 @@ if (m_height > line_height) {\ } spaces++; - /* - 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; - - if (p_mode==PROCESS_POINTER && r_click_char && p_click_pos.y>=p_ofs.y+y && p_click_pos.y<=p_ofs.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>p_ofs.x+align_ofs+pofs) { rchar=int((&c[i])-cf); - //print_line("GOT: "+itos(rchar)); - - - //if (i==end-1 && p_click_pos.x+cw/2 > pofs) - // rchar++; - //int o = (wofs+w)-p_click_pos.x; - - // if (o>cw/2) - // rchar++; } @@ -374,6 +344,8 @@ if (m_height > line_height) {\ int cw=0; bool visible = visible_characters<0 || p_char_count<visible_characters; + if (c[i]=='\t') + visible=false; if (selected) { @@ -393,12 +365,9 @@ if (m_height > line_height) {\ } - //print_line("draw char: "+String::chr(c[i])); - if (underline) { Color uc=color; 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,p_ofs+Point2(align_ofs+pofs,uy),p_ofs+Point2(align_ofs+pofs+cw,uy),uc); } @@ -453,28 +422,6 @@ if (m_height > line_height) {\ if (p_mode!=PROCESS_CACHE) lh = line<l.height_caches.size()?l.height_caches[line]:1; - -#if 0 - if (p_mode==PROCESS_POINTER && r_click_item ) { - //previous last "wrapped" line - int pl = line-1; - if (pl<0 || lines[pl].height_caches.size()==0) - break; - int py=lines[pl].offset_caches[ lines[pl].offset_caches.size() -1 ]; - int ph=lines[pl].height_caches[ lines[pl].height_caches.size() -1 ]; - print_line("py: "+itos(py)); - print_line("ph: "+itos(ph)); - - rchar=0; - if (p_click_pos.y>=py && p_click_pos.y<=py+ph) { - if (r_outside) *r_outside=true; - *r_click_item=it; - *r_click_char=rchar; - return; - } - } - -#endif } break; case ITEM_TABLE: { @@ -484,7 +431,6 @@ if (m_height > line_height) {\ int vseparation=get_constant("table_vseparation"); Color ccolor = _find_color(table,p_base_color); Vector2 draw_ofs = Point2(wofs,y); - int max_y=get_size().height; if (p_mode==PROCESS_CACHE) { @@ -664,7 +610,7 @@ void RichTextLabel::_scroll_changed(double) { if (updating_scroll) return; - if (scroll_follow && vscroll->get_val()>=(vscroll->get_max()-vscroll->get_page())) + if (scroll_follow && vscroll->get_value()>=(vscroll->get_max()-vscroll->get_page())) scroll_following=true; else scroll_following=false; @@ -716,8 +662,9 @@ void RichTextLabel::_notification(int p_what) { } break; case NOTIFICATION_ENTER_TREE: { - if (use_bbcode) - parse_bbcode(bbcode); + if (bbcode != "") + set_bbcode(bbcode); + main->first_invalid_line=0; //invalidate ALL update(); @@ -740,15 +687,13 @@ void RichTextLabel::_notification(int p_what) { RID ci=get_canvas_item(); Size2 size = get_size(); - VisualServer::get_singleton()->canvas_item_set_clip(ci,true); - if (has_focus()) { VisualServer::get_singleton()->canvas_item_add_clip_ignore(ci,true); draw_style_box(get_stylebox("focus"),Rect2(Point2(),size)); VisualServer::get_singleton()->canvas_item_add_clip_ignore(ci,false); } - int ofs = vscroll->get_val(); + int ofs = vscroll->get_value(); //todo, change to binary search @@ -787,7 +732,7 @@ void RichTextLabel::_find_click(ItemFrame* p_frame,const Point2i& p_click,Item * Size2 size = get_size(); - int ofs = vscroll->get_val(); + int ofs = vscroll->get_value(); //todo, change to binary search int from_line = 0; @@ -842,7 +787,7 @@ Control::CursorShape RichTextLabel::get_cursor_shape(const Point2& p_pos) const } -void RichTextLabel::_input_event(InputEvent p_event) { +void RichTextLabel::_gui_input(InputEvent p_event) { switch(p_event.type) { @@ -891,12 +836,12 @@ void RichTextLabel::_input_event(InputEvent p_event) { if (b.button_index==BUTTON_WHEEL_UP) { if (scroll_active) - vscroll->set_val( vscroll->get_val()-vscroll->get_page()/8 ); + vscroll->set_value( vscroll->get_value()-vscroll->get_page()/8 ); } if (b.button_index==BUTTON_WHEEL_DOWN) { if (scroll_active) - vscroll->set_val( vscroll->get_val()+vscroll->get_page()/8 ); + vscroll->set_value( vscroll->get_value()+vscroll->get_page()/8 ); } } break; case InputEvent::KEY: { @@ -907,33 +852,33 @@ void RichTextLabel::_input_event(InputEvent p_event) { switch(k.scancode) { case KEY_PAGEUP: { - if (vscroll->is_visible()) - vscroll->set_val( vscroll->get_val() - vscroll->get_page() ); + if (vscroll->is_visible_in_tree()) + vscroll->set_value( vscroll->get_value() - vscroll->get_page() ); } break; case KEY_PAGEDOWN: { - if (vscroll->is_visible()) - vscroll->set_val( vscroll->get_val() + vscroll->get_page() ); + if (vscroll->is_visible_in_tree()) + vscroll->set_value( vscroll->get_value() + vscroll->get_page() ); } break; case KEY_UP: { - if (vscroll->is_visible()) - vscroll->set_val( vscroll->get_val() - get_font("normal_font")->get_height() ); + if (vscroll->is_visible_in_tree()) + vscroll->set_value( vscroll->get_value() - get_font("normal_font")->get_height() ); } break; case KEY_DOWN: { - if (vscroll->is_visible()) - vscroll->set_val( vscroll->get_val() + get_font("normal_font")->get_height() ); + if (vscroll->is_visible_in_tree()) + vscroll->set_value( vscroll->get_value() + get_font("normal_font")->get_height() ); } break; case KEY_HOME: { - if (vscroll->is_visible()) - vscroll->set_val( 0 ); + if (vscroll->is_visible_in_tree()) + vscroll->set_value( 0 ); } break; case KEY_END: { - if (vscroll->is_visible()) - vscroll->set_val( vscroll->get_max() ); + if (vscroll->is_visible_in_tree()) + vscroll->set_value( vscroll->get_max() ); } break; case KEY_INSERT: case KEY_C: { @@ -1166,7 +1111,7 @@ void RichTextLabel::_validate_line_caches(ItemFrame* p_frame) { vscroll->set_max(total_height); vscroll->set_page(size.height); if (scroll_follow && scroll_following) - vscroll->set_val(total_height-size.height); + vscroll->set_value(total_height-size.height); updating_scroll=false; @@ -1232,7 +1177,8 @@ void RichTextLabel::add_text(const String& p_text) { item->line=current_frame->lines.size(); _add_item(item,false); current_frame->lines.resize(current_frame->lines.size()+1); - current_frame->lines[current_frame->lines.size()-1].from=item; + if (item->type!=ITEM_NEWLINE) + current_frame->lines[current_frame->lines.size()-1].from=item; _invalidate_current_line(current_frame); } @@ -1463,7 +1409,7 @@ bool RichTextLabel::is_meta_underlined() const { void RichTextLabel::set_offset(int p_pixel) { - vscroll->set_val(p_pixel); + vscroll->set_value(p_pixel); } void RichTextLabel::set_scroll_active(bool p_active) { @@ -1483,7 +1429,7 @@ bool RichTextLabel::is_scroll_active() const { void RichTextLabel::set_scroll_follow(bool p_follow) { scroll_follow=p_follow; - if (!vscroll->is_visible() || vscroll->get_val()>=(vscroll->get_max()-vscroll->get_page())) + if (!vscroll->is_visible_in_tree() || vscroll->get_value()>=(vscroll->get_max()-vscroll->get_page())) scroll_following=true; } @@ -1494,7 +1440,6 @@ bool RichTextLabel::is_scroll_following() const { Error RichTextLabel::parse_bbcode(const String& p_bbcode) { - clear(); return append_bbcode(p_bbcode); } @@ -1781,7 +1726,7 @@ void RichTextLabel::scroll_to_line(int p_line) { ERR_FAIL_INDEX(p_line,main->lines.size()); _validate_line_caches(main); - vscroll->set_val(main->lines[p_line].height_accum_cache-main->lines[p_line].height_cache); + vscroll->set_value(main->lines[p_line].height_accum_cache-main->lines[p_line].height_cache); } @@ -1816,7 +1761,6 @@ bool RichTextLabel::search(const String& p_string,bool p_from_selection) { charidx=selection.to_char+1; } - int line=-1; while(it) { if (it->type==ITEM_TEXT) { @@ -1849,7 +1793,7 @@ bool RichTextLabel::search(const String& p_string,bool p_from_selection) { } item=item->parent; } - vscroll->set_val(offset-fh); + vscroll->set_value(offset-fh); return true; } @@ -1913,6 +1857,10 @@ void RichTextLabel::set_bbcode(const String& p_bbcode) { bbcode=p_bbcode; if (is_inside_tree() && use_bbcode) parse_bbcode(p_bbcode); + else { // raw text + clear(); + add_text(p_bbcode); + } } String RichTextLabel::get_bbcode() const { @@ -1924,71 +1872,90 @@ 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); + set_bbcode(bbcode); } bool RichTextLabel::is_using_bbcode() const { return use_bbcode; } + +String RichTextLabel::get_text() { + String text = ""; + Item *it = main; + while (it) { + if (it->type == ITEM_TEXT) { + ItemText *t = static_cast<ItemText*>(it); + text += t->text; + } else if (it->type == ITEM_NEWLINE) { + text += "\n"; + } else if (it->type == ITEM_INDENT) { + text += "\t"; + } + it=_get_next_item(it,true); + } + return text; +} + void RichTextLabel::_bind_methods() { - ObjectTypeDB::bind_method(_MD("_input_event"),&RichTextLabel::_input_event); - ObjectTypeDB::bind_method(_MD("_scroll_changed"),&RichTextLabel::_scroll_changed); - ObjectTypeDB::bind_method(_MD("add_text","text"),&RichTextLabel::add_text); - ObjectTypeDB::bind_method(_MD("add_image","image:Texture"),&RichTextLabel::add_image); - ObjectTypeDB::bind_method(_MD("newline"),&RichTextLabel::add_newline); - ObjectTypeDB::bind_method(_MD("push_font","font"),&RichTextLabel::push_font); - ObjectTypeDB::bind_method(_MD("push_color","color"),&RichTextLabel::push_color); - ObjectTypeDB::bind_method(_MD("push_align","align"),&RichTextLabel::push_align); - ObjectTypeDB::bind_method(_MD("push_indent","level"),&RichTextLabel::push_indent); - ObjectTypeDB::bind_method(_MD("push_list","type"),&RichTextLabel::push_list); - ObjectTypeDB::bind_method(_MD("push_meta","data"),&RichTextLabel::push_meta); - ObjectTypeDB::bind_method(_MD("push_underline"),&RichTextLabel::push_underline); - ObjectTypeDB::bind_method(_MD("push_table","columns"),&RichTextLabel::push_table); - ObjectTypeDB::bind_method(_MD("set_table_column_expand","column","expand","ratio"),&RichTextLabel::set_table_column_expand); - ObjectTypeDB::bind_method(_MD("push_cell"),&RichTextLabel::push_cell); - ObjectTypeDB::bind_method(_MD("pop"),&RichTextLabel::pop); + ClassDB::bind_method(_MD("_gui_input"),&RichTextLabel::_gui_input); + ClassDB::bind_method(_MD("_scroll_changed"),&RichTextLabel::_scroll_changed); + ClassDB::bind_method(_MD("get_text"),&RichTextLabel::get_text); + ClassDB::bind_method(_MD("add_text","text"),&RichTextLabel::add_text); + ClassDB::bind_method(_MD("add_image","image:Texture"),&RichTextLabel::add_image); + ClassDB::bind_method(_MD("newline"),&RichTextLabel::add_newline); + ClassDB::bind_method(_MD("push_font","font"),&RichTextLabel::push_font); + ClassDB::bind_method(_MD("push_color","color"),&RichTextLabel::push_color); + ClassDB::bind_method(_MD("push_align","align"),&RichTextLabel::push_align); + ClassDB::bind_method(_MD("push_indent","level"),&RichTextLabel::push_indent); + ClassDB::bind_method(_MD("push_list","type"),&RichTextLabel::push_list); + ClassDB::bind_method(_MD("push_meta","data"),&RichTextLabel::push_meta); + ClassDB::bind_method(_MD("push_underline"),&RichTextLabel::push_underline); + ClassDB::bind_method(_MD("push_table","columns"),&RichTextLabel::push_table); + ClassDB::bind_method(_MD("set_table_column_expand","column","expand","ratio"),&RichTextLabel::set_table_column_expand); + ClassDB::bind_method(_MD("push_cell"),&RichTextLabel::push_cell); + ClassDB::bind_method(_MD("pop"),&RichTextLabel::pop); - ObjectTypeDB::bind_method(_MD("clear"),&RichTextLabel::clear); + ClassDB::bind_method(_MD("clear"),&RichTextLabel::clear); - ObjectTypeDB::bind_method(_MD("set_meta_underline","enable"),&RichTextLabel::set_meta_underline); - ObjectTypeDB::bind_method(_MD("is_meta_underlined"),&RichTextLabel::is_meta_underlined); + ClassDB::bind_method(_MD("set_meta_underline","enable"),&RichTextLabel::set_meta_underline); + ClassDB::bind_method(_MD("is_meta_underlined"),&RichTextLabel::is_meta_underlined); - ObjectTypeDB::bind_method(_MD("set_scroll_active","active"),&RichTextLabel::set_scroll_active); - ObjectTypeDB::bind_method(_MD("is_scroll_active"),&RichTextLabel::is_scroll_active); + ClassDB::bind_method(_MD("set_scroll_active","active"),&RichTextLabel::set_scroll_active); + ClassDB::bind_method(_MD("is_scroll_active"),&RichTextLabel::is_scroll_active); - ObjectTypeDB::bind_method(_MD("set_scroll_follow","follow"),&RichTextLabel::set_scroll_follow); - ObjectTypeDB::bind_method(_MD("is_scroll_following"),&RichTextLabel::is_scroll_following); + ClassDB::bind_method(_MD("set_scroll_follow","follow"),&RichTextLabel::set_scroll_follow); + ClassDB::bind_method(_MD("is_scroll_following"),&RichTextLabel::is_scroll_following); - ObjectTypeDB::bind_method(_MD("get_v_scroll"),&RichTextLabel::get_v_scroll); + ClassDB::bind_method(_MD("get_v_scroll"),&RichTextLabel::get_v_scroll); - ObjectTypeDB::bind_method(_MD("scroll_to_line","line"),&RichTextLabel::scroll_to_line); + ClassDB::bind_method(_MD("scroll_to_line","line"),&RichTextLabel::scroll_to_line); - ObjectTypeDB::bind_method(_MD("set_tab_size","spaces"),&RichTextLabel::set_tab_size); - ObjectTypeDB::bind_method(_MD("get_tab_size"),&RichTextLabel::get_tab_size); + ClassDB::bind_method(_MD("set_tab_size","spaces"),&RichTextLabel::set_tab_size); + ClassDB::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); + ClassDB::bind_method(_MD("set_selection_enabled","enabled"),&RichTextLabel::set_selection_enabled); + ClassDB::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); + ClassDB::bind_method(_MD("parse_bbcode", "bbcode"),&RichTextLabel::parse_bbcode); + ClassDB::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); + ClassDB::bind_method(_MD("set_bbcode","text"),&RichTextLabel::set_bbcode); + ClassDB::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); + ClassDB::bind_method(_MD("set_visible_characters","amount"),&RichTextLabel::set_visible_characters); + ClassDB::bind_method(_MD("get_visible_characters"),&RichTextLabel::get_visible_characters); - ObjectTypeDB::bind_method(_MD("get_total_character_count"),&RichTextLabel::get_total_character_count); + ClassDB::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); + ClassDB::bind_method(_MD("set_use_bbcode","enable"),&RichTextLabel::set_use_bbcode); + ClassDB::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_GROUP("BBCode","bbcode_"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL,"bbcode_enabled"),_SCS("set_use_bbcode"),_SCS("is_using_bbcode")); + ADD_PROPERTY(PropertyInfo(Variant::STRING,"bbcode_text",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"))); @@ -2077,6 +2044,7 @@ RichTextLabel::RichTextLabel() { visible_characters=-1; + set_clip_contents(true); } RichTextLabel::~RichTextLabel() { diff --git a/scene/gui/rich_text_label.h b/scene/gui/rich_text_label.h index 635fe87ad4..39032185f8 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-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 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 @@ class RichTextLabel : public Control { - OBJ_TYPE( RichTextLabel, Control ); + GDCLASS( RichTextLabel, Control ); public: enum Align { @@ -267,7 +267,7 @@ private: void _update_scroll(); void _scroll_changed(double); - void _input_event(InputEvent p_event); + void _gui_input(InputEvent p_event); Item *_get_next_item(Item* p_item, bool p_free=false); bool use_bbcode; @@ -280,6 +280,7 @@ protected: public: + String get_text(); void add_text(const String& p_text); void add_image(const Ref<Texture>& p_image); void add_newline(); diff --git a/scene/gui/scroll_bar.cpp b/scene/gui/scroll_bar.cpp index d8365feb24..fc406ff0f5 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-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 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 */ @@ -39,7 +39,7 @@ void ScrollBar::set_can_focus_by_default(bool p_can_focus) { focus_by_default=p_can_focus; } -void ScrollBar::_input_event(InputEvent p_event) { +void ScrollBar::_gui_input(InputEvent p_event) { switch(p_event.type) { @@ -51,20 +51,24 @@ 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_value( get_value() + 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_value( get_value() - get_page() / 4.0 ); accept_event(); } @@ -87,13 +91,13 @@ void ScrollBar::_input_event(InputEvent p_event) { if (ofs < decr_size ) { - set_val( get_val() - (custom_step>=0?custom_step:get_step()) ); + set_value( get_value() - (custom_step>=0?custom_step:get_step()) ); break; } if (ofs > total-incr_size ) { - set_val( get_val() + (custom_step>=0?custom_step:get_step()) ); + set_value( get_value() + (custom_step>=0?custom_step:get_step()) ); break; } @@ -101,7 +105,7 @@ void ScrollBar::_input_event(InputEvent p_event) { if ( ofs < grabber_ofs ) { - set_val( get_val() - get_page() ); + set_value( get_value() - get_page() ); break; } @@ -112,12 +116,12 @@ void ScrollBar::_input_event(InputEvent p_event) { drag.active=true; drag.pos_at_click=grabber_ofs+ofs; - drag.value_at_click=get_unit_value(); + drag.value_at_click=get_as_ratio(); update(); } else { - set_val( get_val() + get_page() ); + set_value( get_value() + get_page() ); } @@ -145,7 +149,7 @@ void ScrollBar::_input_event(InputEvent p_event) { double diff = (ofs-drag.pos_at_click) / get_area_size(); - set_unit_value( drag.value_at_click + diff ); + set_as_ratio( drag.value_at_click + diff ); } else { @@ -194,14 +198,14 @@ void ScrollBar::_input_event(InputEvent p_event) { if (orientation!=HORIZONTAL) return; - set_val( get_val() - (custom_step>=0?custom_step:get_step()) ); + set_value( get_value() - (custom_step>=0?custom_step:get_step()) ); } break; case KEY_RIGHT: { if (orientation!=HORIZONTAL) return; - set_val( get_val() + (custom_step>=0?custom_step:get_step()) ); + set_value( get_value() + (custom_step>=0?custom_step:get_step()) ); } break; case KEY_UP: { @@ -209,7 +213,7 @@ void ScrollBar::_input_event(InputEvent p_event) { if (orientation!=VERTICAL) return; - set_val( get_val() - (custom_step>=0?custom_step:get_step()) ); + set_value( get_value() - (custom_step>=0?custom_step:get_step()) ); } break; @@ -217,17 +221,17 @@ void ScrollBar::_input_event(InputEvent p_event) { if (orientation!=VERTICAL) return; - set_val( get_val() + (custom_step>=0?custom_step:get_step()) ); + set_value( get_value() + (custom_step>=0?custom_step:get_step()) ); } break; case KEY_HOME: { - set_val( get_min() ); + set_value( get_min() ); } break; case KEY_END: { - set_val( get_max() ); + set_value( get_max() ); } break; @@ -302,8 +306,8 @@ void ScrollBar::_notification(int p_what) { } if (drag_slave) { - drag_slave->connect("input_event",this,"_drag_slave_input"); - drag_slave->connect("exit_tree",this,"_drag_slave_exit",varray(),CONNECT_ONESHOT); + drag_slave->connect("gui_input",this,"_drag_slave_input"); + drag_slave->connect("tree_exited",this,"_drag_slave_exit",varray(),CONNECT_ONESHOT); } @@ -311,8 +315,8 @@ void ScrollBar::_notification(int p_what) { if (p_what==NOTIFICATION_EXIT_TREE) { if (drag_slave) { - drag_slave->disconnect("input_event",this,"_drag_slave_input"); - drag_slave->disconnect("exit_tree",this,"_drag_slave_exit"); + drag_slave->disconnect("gui_input",this,"_drag_slave_input"); + drag_slave->disconnect("tree_exited",this,"_drag_slave_exit"); } drag_slave=NULL; @@ -325,7 +329,7 @@ void ScrollBar::_notification(int p_what) { if (drag_slave_touching_deaccel) { - Vector2 pos = Vector2(orientation==HORIZONTAL?get_val():0,orientation==VERTICAL?get_val():0); + Vector2 pos = Vector2(orientation==HORIZONTAL?get_value():0,orientation==VERTICAL?get_value():0); pos+=drag_slave_speed*get_fixed_process_delta_time(); bool turnoff=false; @@ -342,7 +346,7 @@ void ScrollBar::_notification(int p_what) { turnoff=true; } - set_val(pos.x); + set_value(pos.x); float sgn_x = drag_slave_speed.x<0? -1 : 1; float val_x = Math::abs(drag_slave_speed.x); @@ -367,7 +371,7 @@ void ScrollBar::_notification(int p_what) { turnoff=true; } - set_val(pos.y); + set_value(pos.y); float sgn_y = drag_slave_speed.y<0? -1 : 1; float val_y = Math::abs(drag_slave_speed.y); @@ -425,8 +429,10 @@ double ScrollBar::get_grabber_size() const { return 0; float page = (get_page()>0)? get_page() : 0; -// if (grabber_range < get_step()) -// grabber_range=get_step(); + /* + if (grabber_range < get_step()) + grabber_range=get_step(); + */ double area_size=get_area_size(); double grabber_size = page / range * area_size; @@ -497,7 +503,7 @@ double ScrollBar::get_click_pos(const Point2& p_pos) const { double ScrollBar::get_grabber_offset() const { - return (get_area_size()) * get_unit_value(); + return (get_area_size()) * get_as_ratio(); } @@ -546,7 +552,7 @@ float ScrollBar::get_custom_step() const { void ScrollBar::_drag_slave_exit() { if (drag_slave) { - drag_slave->disconnect("input_event",this,"_drag_slave_input"); + drag_slave->disconnect("gui_input",this,"_drag_slave_input"); } drag_slave=NULL; } @@ -580,7 +586,7 @@ void ScrollBar::_drag_slave_input(const InputEvent& p_input) { drag_slave_accum=Vector2(); last_drag_slave_accum=Vector2(); //drag_slave_from=Vector2(h_scroll->get_val(),v_scroll->get_val()); - drag_slave_from= Vector2(orientation==HORIZONTAL?get_val():0,orientation==VERTICAL?get_val():0); + drag_slave_from= Vector2(orientation==HORIZONTAL?get_value():0,orientation==VERTICAL?get_value():0); drag_slave_touching=OS::get_singleton()->has_touchscreen_ui_hint(); drag_slave_touching_deaccel=false; @@ -619,13 +625,17 @@ void ScrollBar::_drag_slave_input(const InputEvent& p_input) { Vector2 diff = drag_slave_from+drag_slave_accum; if (orientation==HORIZONTAL) - set_val(diff.x); - //else - // drag_slave_accum.x=0; + set_value(diff.x); + /* + else + drag_slave_accum.x=0; + */ if (orientation==VERTICAL) - set_val(diff.y); - //else - // drag_slave_accum.y=0; + set_value(diff.y); + /* + else + drag_slave_accum.y=0; + */ time_since_motion=0; } @@ -638,8 +648,8 @@ void ScrollBar::set_drag_slave(const NodePath& p_path) { if (is_inside_tree()) { if (drag_slave) { - drag_slave->disconnect("input_event",this,"_drag_slave_input"); - drag_slave->disconnect("exit_tree",this,"_drag_slave_exit"); + drag_slave->disconnect("gui_input",this,"_drag_slave_input"); + drag_slave->disconnect("tree_exited",this,"_drag_slave_exit"); } } @@ -654,8 +664,8 @@ void ScrollBar::set_drag_slave(const NodePath& p_path) { } if (drag_slave) { - drag_slave->connect("input_event",this,"_drag_slave_input"); - drag_slave->connect("exit_tree",this,"_drag_slave_exit",varray(),CONNECT_ONESHOT); + drag_slave->connect("gui_input",this,"_drag_slave_input"); + drag_slave->connect("tree_exited",this,"_drag_slave_exit",varray(),CONNECT_ONESHOT); } } } @@ -804,11 +814,11 @@ bool ScrollBar::key(unsigned long p_unicode, unsigned long p_scan_code,bool b.pr void ScrollBar::_bind_methods() { - ObjectTypeDB::bind_method(_MD("_input_event"),&ScrollBar::_input_event); - ObjectTypeDB::bind_method(_MD("set_custom_step","step"),&ScrollBar::set_custom_step); - ObjectTypeDB::bind_method(_MD("get_custom_step"),&ScrollBar::get_custom_step); - ObjectTypeDB::bind_method(_MD("_drag_slave_input"),&ScrollBar::_drag_slave_input); - ObjectTypeDB::bind_method(_MD("_drag_slave_exit"),&ScrollBar::_drag_slave_exit); + ClassDB::bind_method(_MD("_gui_input"),&ScrollBar::_gui_input); + ClassDB::bind_method(_MD("set_custom_step","step"),&ScrollBar::set_custom_step); + ClassDB::bind_method(_MD("get_custom_step"),&ScrollBar::get_custom_step); + ClassDB::bind_method(_MD("_drag_slave_input"),&ScrollBar::_drag_slave_input); + ClassDB::bind_method(_MD("_drag_slave_exit"),&ScrollBar::_drag_slave_exit); ADD_PROPERTY( PropertyInfo(Variant::REAL,"custom_step",PROPERTY_HINT_RANGE,"-1,4096"), _SCS("set_custom_step"),_SCS("get_custom_step")); @@ -832,7 +842,7 @@ ScrollBar::ScrollBar(Orientation p_orientation) if (focus_by_default) set_focus_mode( FOCUS_ALL ); - + set_step(0); } diff --git a/scene/gui/scroll_bar.h b/scene/gui/scroll_bar.h index c68db02b33..be8b394957 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-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 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 */ @@ -37,7 +37,7 @@ */ class ScrollBar : public Range { - OBJ_TYPE( ScrollBar, Range ); + GDCLASS( ScrollBar, Range ); enum HiliteStatus { HILITE_NONE, @@ -87,7 +87,7 @@ class ScrollBar : public Range { void _drag_slave_exit(); void _drag_slave_input(const InputEvent& p_input); - void _input_event(InputEvent p_event); + void _gui_input(InputEvent p_event); protected: void _notification(int p_what); @@ -109,7 +109,7 @@ public: class HScrollBar : public ScrollBar { - OBJ_TYPE( HScrollBar, ScrollBar ); + GDCLASS( HScrollBar, ScrollBar ); public: HScrollBar() : ScrollBar(HORIZONTAL) { set_v_size_flags(0); } @@ -117,7 +117,7 @@ public: class VScrollBar : public ScrollBar { - OBJ_TYPE( VScrollBar, ScrollBar ); + GDCLASS( VScrollBar, ScrollBar ); public: VScrollBar() : ScrollBar(VERTICAL) { set_h_size_flags(0); } diff --git a/scene/gui/scroll_container.cpp b/scene/gui/scroll_container.cpp index 9bf93aff77..b3ed9b209a 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-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 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 */ @@ -59,10 +59,10 @@ Size2 ScrollContainer::get_minimum_size() const { } } - if (h_scroll->is_visible()) { + if (h_scroll->is_visible_in_tree()) { min_size.y+=h_scroll->get_minimum_size().y; } - if (v_scroll->is_visible()) { + if (v_scroll->is_visible_in_tree()) { min_size.x+=v_scroll->get_minimum_size().x; } return min_size; @@ -79,23 +79,31 @@ void ScrollContainer::_cancel_drag() { drag_from=Vector2(); } -void ScrollContainer::_input_event(const InputEvent& p_input_event) { +void ScrollContainer::_gui_input(const InputEvent& p_gui_input) { - switch(p_input_event.type) { + switch(p_gui_input.type) { case InputEvent::MOUSE_BUTTON: { - const InputEventMouseButton &mb=p_input_event.mouse_button; + const InputEventMouseButton &mb=p_gui_input.mouse_button; - if (mb.button_index==BUTTON_WHEEL_UP && mb.pressed && v_scroll->is_visible()) { - - v_scroll->set_val( v_scroll->get_val()-v_scroll->get_page()/8 ); + if (mb.button_index==BUTTON_WHEEL_UP && mb.pressed) { + if (h_scroll->is_visible_in_tree() && !v_scroll->is_visible_in_tree()){ + // only horizontal is enabled, scroll horizontally + h_scroll->set_value( h_scroll->get_value()-h_scroll->get_page()/8 ); + } else if (v_scroll->is_visible_in_tree()) { + v_scroll->set_value( v_scroll->get_value()-v_scroll->get_page()/8 ); + } } - if (mb.button_index==BUTTON_WHEEL_DOWN && mb.pressed && v_scroll->is_visible()) { - - v_scroll->set_val( v_scroll->get_val()+v_scroll->get_page()/8 ); + if (mb.button_index==BUTTON_WHEEL_DOWN && mb.pressed) { + if (h_scroll->is_visible_in_tree() && !v_scroll->is_visible_in_tree()){ + // only horizontal is enabled, scroll horizontally + h_scroll->set_value( h_scroll->get_value()+h_scroll->get_page()/8 ); + } else if (v_scroll->is_visible_in_tree()) { + v_scroll->set_value( v_scroll->get_value()+v_scroll->get_page()/8 ); + } } if(!OS::get_singleton()->has_touchscreen_ui_hint()) @@ -120,7 +128,7 @@ void ScrollContainer::_input_event(const InputEvent& p_input_event) { drag_speed=Vector2(); drag_accum=Vector2(); last_drag_accum=Vector2(); - drag_from=Vector2(h_scroll->get_val(),v_scroll->get_val()); + drag_from=Vector2(h_scroll->get_value(),v_scroll->get_value()); drag_touching=OS::get_singleton()->has_touchscreen_ui_hint(); drag_touching_deaccel=false; time_since_motion=0; @@ -150,7 +158,7 @@ void ScrollContainer::_input_event(const InputEvent& p_input_event) { } break; case InputEvent::MOUSE_MOTION: { - const InputEventMouseMotion &mm=p_input_event.mouse_motion; + const InputEventMouseMotion &mm=p_gui_input.mouse_motion; if (drag_touching && ! drag_touching_deaccel) { @@ -159,11 +167,11 @@ void ScrollContainer::_input_event(const InputEvent& p_input_event) { Vector2 diff = drag_from+drag_accum; if (scroll_h) - h_scroll->set_val(diff.x); + h_scroll->set_value(diff.x); else drag_accum.x=0; if (scroll_v) - v_scroll->set_val(diff.y); + v_scroll->set_value(diff.y); else drag_accum.y=0; time_since_motion=0; @@ -177,7 +185,6 @@ void ScrollContainer::_input_event(const InputEvent& p_input_event) { void ScrollContainer::_update_scrollbar_pos() { - Size2 size = get_size(); Size2 hmin = h_scroll->get_combined_minimum_size(); Size2 vmin = v_scroll->get_combined_minimum_size(); @@ -209,10 +216,10 @@ void ScrollContainer::_notification(int p_what) { child_max_size = Size2(0, 0); Size2 size = get_size(); - if (h_scroll->is_visible()) + if (h_scroll->is_visible_in_tree()) size.y-=h_scroll->get_minimum_size().y; - if (v_scroll->is_visible()) + if (v_scroll->is_visible_in_tree()) size.x-=h_scroll->get_minimum_size().x; for(int i=0;i<get_child_count();i++) { @@ -229,14 +236,14 @@ void ScrollContainer::_notification(int p_what) { child_max_size.y = MAX(child_max_size.y, minsize.y); Rect2 r = Rect2(-scroll,minsize); - if (!scroll_h) { + if (!(scroll_h || h_scroll->is_visible_in_tree())) { r.pos.x=0; if (c->get_h_size_flags()&SIZE_EXPAND) r.size.width=MAX(size.width,minsize.width); else r.size.width=minsize.width; } - if (!scroll_v) { + if (!(scroll_v || v_scroll->is_visible_in_tree())) { r.pos.y=0; r.size.height=size.height; if (c->get_v_size_flags()&SIZE_EXPAND) @@ -254,7 +261,6 @@ void ScrollContainer::_notification(int p_what) { update_scrollbars(); - VisualServer::get_singleton()->canvas_item_set_clip(get_canvas_item(),true); } if (p_what==NOTIFICATION_FIXED_PROCESS) { @@ -263,7 +269,7 @@ void ScrollContainer::_notification(int p_what) { if (drag_touching_deaccel) { - Vector2 pos = Vector2(h_scroll->get_val(),v_scroll->get_val()); + Vector2 pos = Vector2(h_scroll->get_value(),v_scroll->get_value()); pos+=drag_speed*get_fixed_process_delta_time(); bool turnoff_h=false; @@ -288,9 +294,9 @@ void ScrollContainer::_notification(int p_what) { } if (scroll_h) - h_scroll->set_val(pos.x); + h_scroll->set_value(pos.x); if (scroll_v) - v_scroll->set_val(pos.y); + v_scroll->set_value(pos.y); float sgn_x = drag_speed.x<0? -1 : 1; float val_x = Math::abs(drag_speed.x); @@ -352,7 +358,7 @@ void ScrollContainer::update_scrollbars() { } else { v_scroll->show(); - scroll.y=v_scroll->get_val(); + scroll.y=v_scroll->get_value(); } @@ -369,14 +375,14 @@ void ScrollContainer::update_scrollbars() { h_scroll->show(); h_scroll->set_max(min.width); h_scroll->set_page(size.width - vmin.width); - scroll.x=h_scroll->get_val(); + scroll.x=h_scroll->get_value(); } } void ScrollContainer::_scroll_moved(float) { - scroll.x=h_scroll->get_val(); - scroll.y=v_scroll->get_val(); + scroll.x=h_scroll->get_value(); + scroll.y=v_scroll->get_value(); queue_sort(); update(); @@ -408,42 +414,66 @@ bool ScrollContainer::is_v_scroll_enabled() const{ int ScrollContainer::get_v_scroll() const { - return v_scroll->get_val(); + return v_scroll->get_value(); } void ScrollContainer::set_v_scroll(int p_pos) { - v_scroll->set_val(p_pos); + v_scroll->set_value(p_pos); _cancel_drag(); } int ScrollContainer::get_h_scroll() const { - return h_scroll->get_val(); + return h_scroll->get_value(); } void ScrollContainer::set_h_scroll(int p_pos) { - h_scroll->set_val(p_pos); + h_scroll->set_value(p_pos); _cancel_drag(); } +String ScrollContainer::get_configuration_warning() const { + + int found=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 (c == h_scroll || c == v_scroll) + continue; + + found++; + } + + if (found!=1) + return TTR("ScrollContainer is intended to work with a single child control.\nUse a container as child (VBox,HBox,etc), or a Control and set the custom minimum size manually."); + else + return ""; +} + void ScrollContainer::_bind_methods() { - ObjectTypeDB::bind_method(_MD("_scroll_moved"),&ScrollContainer::_scroll_moved); - ObjectTypeDB::bind_method(_MD("_input_event"),&ScrollContainer::_input_event); - ObjectTypeDB::bind_method(_MD("set_enable_h_scroll","enable"),&ScrollContainer::set_enable_h_scroll); - ObjectTypeDB::bind_method(_MD("is_h_scroll_enabled"),&ScrollContainer::is_h_scroll_enabled); - ObjectTypeDB::bind_method(_MD("set_enable_v_scroll","enable"),&ScrollContainer::set_enable_v_scroll); - ObjectTypeDB::bind_method(_MD("is_v_scroll_enabled"),&ScrollContainer::is_v_scroll_enabled); - ObjectTypeDB::bind_method(_MD("_update_scrollbar_pos"),&ScrollContainer::_update_scrollbar_pos); - ObjectTypeDB::bind_method(_MD("set_h_scroll","val"),&ScrollContainer::set_h_scroll); - ObjectTypeDB::bind_method(_MD("get_h_scroll"),&ScrollContainer::get_h_scroll); - ObjectTypeDB::bind_method(_MD("set_v_scroll","val"),&ScrollContainer::set_v_scroll); - ObjectTypeDB::bind_method(_MD("get_v_scroll"),&ScrollContainer::get_v_scroll); - - ADD_PROPERTY( PropertyInfo( Variant::BOOL, "scroll/horizontal"), _SCS("set_enable_h_scroll"),_SCS("is_h_scroll_enabled")); - ADD_PROPERTY( PropertyInfo( Variant::BOOL, "scroll/vertical"), _SCS("set_enable_v_scroll"),_SCS("is_v_scroll_enabled")); + ClassDB::bind_method(_MD("_scroll_moved"),&ScrollContainer::_scroll_moved); + ClassDB::bind_method(_MD("_gui_input"),&ScrollContainer::_gui_input); + ClassDB::bind_method(_MD("set_enable_h_scroll","enable"),&ScrollContainer::set_enable_h_scroll); + ClassDB::bind_method(_MD("is_h_scroll_enabled"),&ScrollContainer::is_h_scroll_enabled); + ClassDB::bind_method(_MD("set_enable_v_scroll","enable"),&ScrollContainer::set_enable_v_scroll); + ClassDB::bind_method(_MD("is_v_scroll_enabled"),&ScrollContainer::is_v_scroll_enabled); + ClassDB::bind_method(_MD("_update_scrollbar_pos"),&ScrollContainer::_update_scrollbar_pos); + ClassDB::bind_method(_MD("set_h_scroll","val"),&ScrollContainer::set_h_scroll); + ClassDB::bind_method(_MD("get_h_scroll"),&ScrollContainer::get_h_scroll); + ClassDB::bind_method(_MD("set_v_scroll","val"),&ScrollContainer::set_v_scroll); + ClassDB::bind_method(_MD("get_v_scroll"),&ScrollContainer::get_v_scroll); + + ADD_GROUP("Scroll","scroll_"); + ADD_PROPERTY( PropertyInfo( Variant::BOOL, "scroll_horizontal"), _SCS("set_enable_h_scroll"),_SCS("is_h_scroll_enabled")); + ADD_PROPERTY( PropertyInfo( Variant::BOOL, "scroll_vertical"), _SCS("set_enable_v_scroll"),_SCS("is_v_scroll_enabled")); }; @@ -466,6 +496,6 @@ ScrollContainer::ScrollContainer() { scroll_h=true; scroll_v=true; - + set_clip_contents(true); }; diff --git a/scene/gui/scroll_container.h b/scene/gui/scroll_container.h index 50ae236714..114cd06306 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-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 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 */ @@ -35,7 +35,7 @@ class ScrollContainer : public Container { - OBJ_TYPE(ScrollContainer, Container); + GDCLASS(ScrollContainer, Container); HScrollBar* h_scroll; VScrollBar* v_scroll; @@ -64,7 +64,7 @@ protected: Size2 get_minimum_size() const; - void _input_event(const InputEvent& p_input_event); + void _gui_input(const InputEvent& p_gui_input); void _notification(int p_what); void _scroll_moved(float); @@ -86,6 +86,9 @@ public: bool is_v_scroll_enabled() const; virtual bool clips_input() const; + + virtual String get_configuration_warning() const; + ScrollContainer(); }; diff --git a/scene/gui/separator.cpp b/scene/gui/separator.cpp index 626b093a2f..32bd2239fc 100644 --- a/scene/gui/separator.cpp +++ b/scene/gui/separator.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 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 7a7dc92b93..5fb17e1c2e 100644 --- a/scene/gui/separator.h +++ b/scene/gui/separator.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 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 */ @@ -36,7 +36,7 @@ #include "scene/gui/control.h" class Separator : public Control { - OBJ_TYPE( Separator, Control ); + GDCLASS( Separator, Control ); protected: @@ -54,7 +54,7 @@ public: class VSeparator : public Separator { - OBJ_TYPE( VSeparator, Separator ); + GDCLASS( VSeparator, Separator ); public: @@ -64,7 +64,7 @@ public: class HSeparator : public Separator { - OBJ_TYPE( HSeparator, Separator ); + GDCLASS( HSeparator, Separator ); public: diff --git a/scene/gui/slider.cpp b/scene/gui/slider.cpp index f66f909517..ad6e8786d7 100644 --- a/scene/gui/slider.cpp +++ b/scene/gui/slider.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 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 */ @@ -37,7 +37,7 @@ Size2 Slider::get_minimum_size() const { return ms; } -void Slider::_input_event(InputEvent p_event) { +void Slider::_gui_input(InputEvent p_event) { @@ -47,22 +47,25 @@ void Slider::_input_event(InputEvent p_event) { if (mb.button_index==BUTTON_LEFT) { if (mb.pressed) { + Ref<Texture> grabber = get_icon(mouse_inside||has_focus()?"grabber_hilite":"grabber"); grab.pos=orientation==VERTICAL?mb.y:mb.x; - double max = orientation==VERTICAL ? get_size().height : get_size().width ; + double grab_width = (double)grabber->get_size().width; + double grab_height = (double)grabber->get_size().height; + double max = orientation==VERTICAL ? get_size().height - grab_height : get_size().width - grab_width; if (orientation==VERTICAL) - set_unit_value( 1 - ((double)grab.pos / max) ); + set_as_ratio( 1 - (((double)grab.pos - (grab_height / 2.0)) / max) ); else - set_unit_value((double)grab.pos / max); + set_as_ratio(((double)grab.pos - (grab_width/2.0)) / max); grab.active=true; - grab.uvalue=get_unit_value(); + grab.uvalue=get_as_ratio(); } else { grab.active=false; } } else if (mb.pressed && mb.button_index==BUTTON_WHEEL_UP) { - set_val( get_val() + get_step()); + set_value( get_value() + get_step()); } else if (mb.pressed && mb.button_index==BUTTON_WHEEL_DOWN) { - set_val( get_val() - get_step()); + set_value( get_value() - get_step()); } } else if (p_event.type==InputEvent::MOUSE_MOTION) { @@ -78,7 +81,7 @@ void Slider::_input_event(InputEvent p_event) { if (areasize<=0) return; float umotion = motion / float(areasize); - set_unit_value( grab.uvalue + umotion ); + set_as_ratio( grab.uvalue + umotion ); } } else { @@ -86,26 +89,26 @@ void Slider::_input_event(InputEvent p_event) { if (orientation!=HORIZONTAL) return; - set_val( get_val() - (custom_step>=0?custom_step:get_step()) ); + set_value( get_value() - (custom_step>=0?custom_step:get_step()) ); accept_event(); } else if (p_event.is_action("ui_right") && p_event.is_pressed()) { if (orientation!=HORIZONTAL) return; - set_val( get_val() + (custom_step>=0?custom_step:get_step()) ); + set_value( get_value() + (custom_step>=0?custom_step:get_step()) ); accept_event(); } else if (p_event.is_action("ui_up") && p_event.is_pressed()) { if (orientation!=VERTICAL) return; - set_val( get_val() + (custom_step>=0?custom_step:get_step()) ); + set_value( get_value() + (custom_step>=0?custom_step:get_step()) ); accept_event(); } else if (p_event.is_action("ui_down") && p_event.is_pressed()) { if (orientation!=VERTICAL) return; - set_val( get_val() - (custom_step>=0?custom_step:get_step()) ); + set_value( get_value() - (custom_step>=0?custom_step:get_step()) ); accept_event(); } else if (p_event.type==InputEvent::KEY) { @@ -119,12 +122,12 @@ void Slider::_input_event(InputEvent p_event) { case KEY_HOME: { - set_val( get_min() ); + set_value( get_min() ); accept_event(); } break; case KEY_END: { - set_val( get_max() ); + set_value( get_max() ); accept_event(); } break; @@ -161,8 +164,10 @@ void Slider::_notification(int p_what) { if (orientation==VERTICAL) { style->draw(ci,Rect2i(Point2i(),Size2i(style->get_minimum_size().width+style->get_center_size().width,size.height))); - //if (mouse_inside||has_focus()) - // focus->draw(ci,Rect2i(Point2i(),Size2i(style->get_minimum_size().width+style->get_center_size().width,size.height))); + /* + if (mouse_inside||has_focus()) + focus->draw(ci,Rect2i(Point2i(),Size2i(style->get_minimum_size().width+style->get_center_size().width,size.height))); + */ float areasize = size.height - grabber->get_size().height; if (ticks>1) { int tickarea = size.height - tick->get_height(); @@ -173,11 +178,13 @@ void Slider::_notification(int p_what) { } } - grabber->draw(ci,Point2i(size.width/2-grabber->get_size().width/2,size.height - get_unit_value()*areasize - grabber->get_size().height)); + grabber->draw(ci,Point2i(size.width/2-grabber->get_size().width/2,size.height - get_as_ratio()*areasize - grabber->get_size().height)); } else { style->draw(ci,Rect2i(Point2i(),Size2i(size.width,style->get_minimum_size().height+style->get_center_size().height))); - //if (mouse_inside||has_focus()) - // focus->draw(ci,Rect2i(Point2i(),Size2i(size.width,style->get_minimum_size().height+style->get_center_size().height))); + /* + if (mouse_inside||has_focus()) + focus->draw(ci,Rect2i(Point2i(),Size2i(size.width,style->get_minimum_size().height+style->get_center_size().height))); + */ float areasize = size.width - grabber->get_size().width; if (ticks>1) { @@ -189,7 +196,7 @@ void Slider::_notification(int p_what) { } } - grabber->draw(ci,Point2i(get_unit_value()*areasize,size.height/2-grabber->get_size().height/2)); + grabber->draw(ci,Point2i(get_as_ratio()*areasize,size.height/2-grabber->get_size().height/2)); } } break; @@ -228,15 +235,16 @@ void Slider::set_ticks_on_borders(bool _tob){ void Slider::_bind_methods() { - ObjectTypeDB::bind_method(_MD("_input_event"),&Slider::_input_event); - ObjectTypeDB::bind_method(_MD("set_ticks","count"),&Slider::set_ticks); - ObjectTypeDB::bind_method(_MD("get_ticks"),&Slider::get_ticks); + ClassDB::bind_method(_MD("_gui_input"),&Slider::_gui_input); + ClassDB::bind_method(_MD("set_ticks","count"),&Slider::set_ticks); + ClassDB::bind_method(_MD("get_ticks"),&Slider::get_ticks); - ObjectTypeDB::bind_method(_MD("get_ticks_on_borders"),&Slider::get_ticks_on_borders); - ObjectTypeDB::bind_method(_MD("set_ticks_on_borders","ticks_on_border"),&Slider::set_ticks_on_borders); + ClassDB::bind_method(_MD("get_ticks_on_borders"),&Slider::get_ticks_on_borders); + ClassDB::bind_method(_MD("set_ticks_on_borders","ticks_on_border"),&Slider::set_ticks_on_borders); ADD_PROPERTY( PropertyInfo( Variant::INT, "tick_count", PROPERTY_HINT_RANGE,"0,4096,1"), _SCS("set_ticks"), _SCS("get_ticks") ); ADD_PROPERTY( PropertyInfo( Variant::BOOL, "ticks_on_borders" ), _SCS("set_ticks_on_borders"), _SCS("get_ticks_on_borders") ); + ADD_PROPERTY( PropertyInfo( Variant::INT,"focus_mode", PROPERTY_HINT_ENUM, "None,Click,All" ), _SCS("set_focus_mode"), _SCS("get_focus_mode") ); } diff --git a/scene/gui/slider.h b/scene/gui/slider.h index cf009b9a75..89eb32737b 100644 --- a/scene/gui/slider.h +++ b/scene/gui/slider.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 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 */ @@ -33,7 +33,7 @@ class Slider : public Range { - OBJ_TYPE( Slider, Range ); + GDCLASS( Slider, Range ); struct Grab { int pos; @@ -49,7 +49,7 @@ class Slider : public Range { protected: - void _input_event(InputEvent p_event); + void _gui_input(InputEvent p_event); void _notification(int p_what); static void _bind_methods(); bool ticks_on_borders; @@ -74,7 +74,7 @@ public: class HSlider : public Slider { - OBJ_TYPE( HSlider, Slider ); + GDCLASS( HSlider, Slider ); public: HSlider() : Slider(HORIZONTAL) { set_v_size_flags(0);} @@ -82,7 +82,7 @@ public: class VSlider : public Slider { - OBJ_TYPE( VSlider, Slider ); + GDCLASS( VSlider, Slider ); public: VSlider() : Slider(VERTICAL) { set_h_size_flags(0);} diff --git a/scene/gui/spin_box.cpp b/scene/gui/spin_box.cpp index 2b64d36a81..ec6be0d19d 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-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 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 */ @@ -39,7 +39,7 @@ Size2 SpinBox::get_minimum_size() const { void SpinBox::_value_changed(double) { - String value = String::num(get_val(),Math::decimals(get_step())); + String value = String::num(get_value(),Math::step_decimals(get_step())); if (prefix!="") value=prefix+" "+value; if (suffix!="") @@ -49,9 +49,14 @@ void SpinBox::_value_changed(double) { void SpinBox::_text_entered(const String& p_string) { - //if (!p_string.is_numeric()) - // return; - set_val( p_string.to_double() ); + /* + if (!p_string.is_numeric()) + return; + */ + String value = p_string; + if (prefix!="" && p_string.begins_with(prefix)) + value = p_string.substr(prefix.length(), p_string.length()-prefix.length()); + set_value( value.to_double() ); _value_changed(0); } @@ -73,7 +78,7 @@ void SpinBox::_range_click_timeout() { if (!drag.enabled && Input::get_singleton()->is_mouse_button_pressed(BUTTON_LEFT)) { bool up = get_local_mouse_pos().y < (get_size().height/2); - set_val( get_val() + (up?get_step():-get_step())); + set_value( get_value() + (up?get_step():-get_step())); if (range_click_timer->is_one_shot()) { range_click_timer->set_wait_time(0.075); @@ -87,8 +92,11 @@ void SpinBox::_range_click_timeout() { } -void SpinBox::_input_event(const InputEvent& p_event) { +void SpinBox::_gui_input(const InputEvent& p_event) { + if (!is_editable()) { + return; + } if (p_event.type==InputEvent::MOUSE_BUTTON && p_event.mouse_button.pressed) { const InputEventMouseButton &mb=p_event.mouse_button; @@ -101,25 +109,30 @@ void SpinBox::_input_event(const InputEvent& p_event) { case BUTTON_LEFT: { - set_val( get_val() + (up?get_step():-get_step())); + set_value( get_value() + (up?get_step():-get_step())); range_click_timer->set_wait_time(0.6); range_click_timer->set_one_shot(true); range_click_timer->start(); + line_edit->grab_focus(); } break; case BUTTON_RIGHT: { - set_val( (up?get_max():get_min()) ); - + set_value( (up?get_max():get_min()) ); + line_edit->grab_focus(); } break; case BUTTON_WHEEL_UP: { - - set_val( get_val() + get_step() ); + if (line_edit->has_focus()) { + set_value( get_value() + get_step() ); + accept_event(); + } } break; case BUTTON_WHEEL_DOWN: { - - set_val( get_val() - get_step() ); + if (line_edit->has_focus()) { + set_value( get_value() - get_step() ); + accept_event(); + } } break; } } @@ -155,13 +168,13 @@ void SpinBox::_input_event(const InputEvent& p_event) { drag.mouse_pos=cpos; drag.base_val=CLAMP(drag.base_val + get_step() * diff_y, get_min(), get_max()); - set_val( drag.base_val); + set_value( drag.base_val); } else if (drag.mouse_pos.distance_to(cpos)>2) { Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_CAPTURED); drag.enabled=true; - drag.base_val=get_val(); + drag.base_val=get_value(); drag.mouse_pos=cpos; drag.capture_pos=cpos; @@ -240,19 +253,19 @@ bool SpinBox::is_editable() const { void SpinBox::_bind_methods() { - //ObjectTypeDB::bind_method(_MD("_value_changed"),&SpinBox::_value_changed); - ObjectTypeDB::bind_method(_MD("_input_event"),&SpinBox::_input_event); - ObjectTypeDB::bind_method(_MD("_text_entered"),&SpinBox::_text_entered); - ObjectTypeDB::bind_method(_MD("set_suffix","suffix"),&SpinBox::set_suffix); - ObjectTypeDB::bind_method(_MD("get_suffix"),&SpinBox::get_suffix); - ObjectTypeDB::bind_method(_MD("set_prefix","prefix"),&SpinBox::set_prefix); - ObjectTypeDB::bind_method(_MD("get_prefix"),&SpinBox::get_prefix); - ObjectTypeDB::bind_method(_MD("set_editable","editable"),&SpinBox::set_editable); - ObjectTypeDB::bind_method(_MD("is_editable"),&SpinBox::is_editable); - ObjectTypeDB::bind_method(_MD("_line_edit_focus_exit"),&SpinBox::_line_edit_focus_exit); - ObjectTypeDB::bind_method(_MD("get_line_edit"),&SpinBox::get_line_edit); - ObjectTypeDB::bind_method(_MD("_line_edit_input"),&SpinBox::_line_edit_input); - ObjectTypeDB::bind_method(_MD("_range_click_timeout"),&SpinBox::_range_click_timeout); + //ClassDB::bind_method(_MD("_value_changed"),&SpinBox::_value_changed); + ClassDB::bind_method(_MD("_gui_input"),&SpinBox::_gui_input); + ClassDB::bind_method(_MD("_text_entered"),&SpinBox::_text_entered); + ClassDB::bind_method(_MD("set_suffix","suffix"),&SpinBox::set_suffix); + ClassDB::bind_method(_MD("get_suffix"),&SpinBox::get_suffix); + ClassDB::bind_method(_MD("set_prefix","prefix"),&SpinBox::set_prefix); + ClassDB::bind_method(_MD("get_prefix"),&SpinBox::get_prefix); + ClassDB::bind_method(_MD("set_editable","editable"),&SpinBox::set_editable); + ClassDB::bind_method(_MD("is_editable"),&SpinBox::is_editable); + ClassDB::bind_method(_MD("_line_edit_focus_exit"),&SpinBox::_line_edit_focus_exit); + ClassDB::bind_method(_MD("get_line_edit"),&SpinBox::get_line_edit); + ClassDB::bind_method(_MD("_line_edit_input"),&SpinBox::_line_edit_input); + ClassDB::bind_method(_MD("_range_click_timeout"),&SpinBox::_range_click_timeout); ADD_PROPERTY(PropertyInfo(Variant::BOOL,"editable"),_SCS("set_editable"),_SCS("is_editable")); @@ -271,8 +284,8 @@ SpinBox::SpinBox() { line_edit->set_area_as_parent_rect(); //connect("value_changed",this,"_value_changed"); line_edit->connect("text_entered",this,"_text_entered",Vector<Variant>(),CONNECT_DEFERRED); - line_edit->connect("focus_exit",this,"_line_edit_focus_exit",Vector<Variant>(),CONNECT_DEFERRED); - line_edit->connect("input_event",this,"_line_edit_input"); + line_edit->connect("focus_exited",this,"_line_edit_focus_exit",Vector<Variant>(),CONNECT_DEFERRED); + line_edit->connect("gui_input",this,"_line_edit_input"); drag.enabled=false; range_click_timer = memnew( Timer ); diff --git a/scene/gui/spin_box.h b/scene/gui/spin_box.h index acaea822ab..9974ec47bc 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-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 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 */ @@ -35,7 +35,7 @@ class SpinBox : public Range { - OBJ_TYPE( SpinBox, Range ); + GDCLASS( SpinBox, Range ); LineEdit *line_edit; int last_w; @@ -64,7 +64,7 @@ class SpinBox : public Range { protected: - void _input_event(const InputEvent& p_event); + void _gui_input(const InputEvent& p_event); void _notification(int p_what); diff --git a/scene/gui/split_container.cpp b/scene/gui/split_container.cpp index d22f6a0229..a39ad2fe99 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-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 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 */ @@ -47,7 +47,7 @@ Control *SplitContainer::_getch(int p_idx) const { for(int i=0;i<get_child_count();i++) { Control *c=get_child(i)->cast_to<Control>(); - if (!c || !c->is_visible()) + if (!c || !c->is_visible_in_tree()) continue; if (c->is_set_as_toplevel()) continue; @@ -299,7 +299,7 @@ void SplitContainer::_notification(int p_what) { } } -void SplitContainer::_input_event(const InputEvent& p_event) { +void SplitContainer::_gui_input(const InputEvent& p_event) { if (collapsed || !_getch(0) || !_getch(1) || dragger_visibility!=DRAGGER_VISIBLE) return; @@ -351,7 +351,7 @@ void SplitContainer::_input_event(const InputEvent& p_event) { } -Control::CursorShape SplitContainer::get_cursor_shape(const Point2& p_pos) { +Control::CursorShape SplitContainer::get_cursor_shape(const Point2& p_pos) const { if (collapsed) return Control::get_cursor_shape(p_pos); @@ -422,21 +422,21 @@ bool SplitContainer::is_collapsed() const { void SplitContainer::_bind_methods() { - ObjectTypeDB::bind_method(_MD("_input_event"),&SplitContainer::_input_event); - ObjectTypeDB::bind_method(_MD("set_split_offset","offset"),&SplitContainer::set_split_offset); - ObjectTypeDB::bind_method(_MD("get_split_offset"),&SplitContainer::get_split_offset); + ClassDB::bind_method(_MD("_gui_input"),&SplitContainer::_gui_input); + ClassDB::bind_method(_MD("set_split_offset","offset"),&SplitContainer::set_split_offset); + ClassDB::bind_method(_MD("get_split_offset"),&SplitContainer::get_split_offset); - ObjectTypeDB::bind_method(_MD("set_collapsed","collapsed"),&SplitContainer::set_collapsed); - ObjectTypeDB::bind_method(_MD("is_collapsed"),&SplitContainer::is_collapsed); + ClassDB::bind_method(_MD("set_collapsed","collapsed"),&SplitContainer::set_collapsed); + ClassDB::bind_method(_MD("is_collapsed"),&SplitContainer::is_collapsed); - ObjectTypeDB::bind_method(_MD("set_dragger_visibility","mode"),&SplitContainer::set_dragger_visibility); - ObjectTypeDB::bind_method(_MD("get_dragger_visibility"),&SplitContainer::get_dragger_visibility); + ClassDB::bind_method(_MD("set_dragger_visibility","mode"),&SplitContainer::set_dragger_visibility); + ClassDB::bind_method(_MD("get_dragger_visibility"),&SplitContainer::get_dragger_visibility); 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::BOOL,"split/collapsed"),_SCS("set_collapsed"),_SCS("is_collapsed")); - ADD_PROPERTY( PropertyInfo(Variant::INT,"split/dragger_visibility",PROPERTY_HINT_ENUM,"Visible,Hidden,Hidden & Collapsed"),_SCS("set_dragger_visibility"),_SCS("get_dragger_visibility")); + ADD_PROPERTY( PropertyInfo(Variant::INT,"split_offset"),_SCS("set_split_offset"),_SCS("get_split_offset")); + ADD_PROPERTY( PropertyInfo(Variant::BOOL,"collapsed"),_SCS("set_collapsed"),_SCS("is_collapsed")); + ADD_PROPERTY( PropertyInfo(Variant::INT,"dragger_visibility",PROPERTY_HINT_ENUM,"Visible,Hidden,Hidden & Collapsed"),_SCS("set_dragger_visibility"),_SCS("get_dragger_visibility")); BIND_CONSTANT( DRAGGER_VISIBLE ); BIND_CONSTANT( DRAGGER_HIDDEN ); diff --git a/scene/gui/split_container.h b/scene/gui/split_container.h index f721d16310..03b6b1a167 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-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 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 @@ class SplitContainer : public Container { - OBJ_TYPE(SplitContainer,Container); + GDCLASS(SplitContainer,Container); public: enum DraggerVisibility { DRAGGER_VISIBLE, @@ -59,7 +59,7 @@ private: protected: - void _input_event(const InputEvent& p_event); + void _gui_input(const InputEvent& p_event); void _notification(int p_what); static void _bind_methods(); public: @@ -75,7 +75,7 @@ public: void set_dragger_visibility(DraggerVisibility p_visibility); DraggerVisibility get_dragger_visibility() const; - virtual CursorShape get_cursor_shape(const Point2& p_pos=Point2i()); + virtual CursorShape get_cursor_shape(const Point2& p_pos=Point2i()) const; virtual Size2 get_minimum_size() const; @@ -86,7 +86,7 @@ VARIANT_ENUM_CAST(SplitContainer::DraggerVisibility); class HSplitContainer : public SplitContainer { - OBJ_TYPE(HSplitContainer,SplitContainer); + GDCLASS(HSplitContainer,SplitContainer); public: @@ -96,7 +96,7 @@ public: class VSplitContainer : public SplitContainer { - OBJ_TYPE(VSplitContainer,SplitContainer); + GDCLASS(VSplitContainer,SplitContainer); public: diff --git a/scene/gui/tab_container.cpp b/scene/gui/tab_container.cpp index c8bd1cb5a1..52d26b29de 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-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 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,8 +40,6 @@ int TabContainer::_get_top_margin() const { int h = MAX( tab_bg->get_minimum_size().height,tab_fg->get_minimum_size().height); -// h+=MIN( get_constant("label_valign_fg"), get_constant("label_valign_bg") ); - int ch = font->get_height();; for(int i=0;i<get_child_count();i++) { @@ -67,7 +65,7 @@ int TabContainer::_get_top_margin() const { -void TabContainer::_input_event(const InputEvent& p_event) { +void TabContainer::_gui_input(const InputEvent& p_event) { if (p_event.type==InputEvent::MOUSE_BUTTON && p_event.mouse_button.pressed && @@ -207,9 +205,7 @@ void TabContainer::_notification(int p_what) { Ref<StyleBox> tab_bg = get_stylebox("tab_bg"); Ref<StyleBox> tab_fg = get_stylebox("tab_fg"); 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> menu = get_icon("menu"); Ref<Texture> menu_hl = get_icon("menu_hl"); Ref<Font> font = get_font("font"); @@ -219,9 +215,6 @@ void TabContainer::_notification(int p_what) { int side_margin = get_constant("side_margin"); int top_margin = _get_top_margin(); - int label_valign_fg = get_constant("label_valign_fg"); - int label_valign_bg = get_constant("label_valign_bg"); - Size2 top_size = Size2( size.width, top_margin ); @@ -338,17 +331,14 @@ void TabContainer::_notification(int p_what) { Ref<StyleBox> sb; - int va; Color col; if (idx==current) { sb=tab_fg; - va=label_valign_fg; col=color_fg; } else { sb=tab_bg; - va=label_valign_bg; col=color_bg; } @@ -371,23 +361,7 @@ void TabContainer::_notification(int p_what) { } font->draw(ci, Point2i( lpos.x, sb->get_margin(MARGIN_TOP)+((sb_rect.size.y-sb_ms.y)-font->get_height())/2+font->get_ascent() ), s, col ); - //ofs+=sb_ms.x+w; - - /* - int sb_mw = sb->get_minimum_size().width; - int font_ofs = sb_mw / 2; - - Rect2i rect =Rect2( ofs, 0, w+sb_mw, top_margin); - rect.size - sb->draw(ci,rect); - rect.y+=va; - rect.height+=va; - int font_y = (rect.height - font->get_height())/2; - - font->draw(ci, Point2( ofs+font_ofs, va+font_y ), s, col ); - -*/ idx++; } @@ -411,10 +385,10 @@ void TabContainer::_notification(int p_what) { panel->draw(ci, Rect2( 0, top_size.height, size.width, size.height-top_size.height)); } break; - case NOTIFICATION_READY: case NOTIFICATION_THEME_CHANGED: { - - call_deferred("set_current_tab",get_current_tab()); //wait until all changed theme + if (get_tab_count() > 0) { + call_deferred("set_current_tab",get_current_tab()); //wait until all changed theme + } } break; } } @@ -426,6 +400,7 @@ void TabContainer::_child_renamed_callback() { void TabContainer::add_child_notify(Node *p_child) { + Control::add_child_notify(p_child); Control *c = p_child->cast_to<Control>(); if (!c) @@ -477,7 +452,6 @@ void TabContainer::set_current_tab(int p_current) { ERR_FAIL_INDEX( p_current, get_tab_count() ); - //printf("DEBUG %p: set_current_tab to %i\n", this, p_current); current=p_current; int idx=0; @@ -559,8 +533,9 @@ Control* TabContainer::get_current_tab_control() const { void TabContainer::remove_child_notify(Node *p_child) { + Control::remove_child_notify(p_child); + int tc = get_tab_count(); -// bool set_curent=false; if (current==tc-1) { current--; if (current<0) @@ -705,13 +680,10 @@ Size2 TabContainer::get_minimum_size() const { if (c->is_set_as_toplevel()) continue; - if (!c->has_meta("_tab_name")) + if (!c->is_visible_in_tree()) continue; - if (!c->is_visible()) - continue; - - Size2 cms = c->get_minimum_size(); + Size2 cms = c->get_combined_minimum_size(); ms.x=MAX(ms.x,cms.x); ms.y=MAX(ms.y,cms.y); } @@ -723,6 +695,9 @@ Size2 TabContainer::get_minimum_size() const { ms.y+=MAX(tab_bg->get_minimum_size().y,tab_fg->get_minimum_size().y); ms.y+=font->get_height(); + Ref<StyleBox> sb = get_stylebox("panel"); + ms+=sb->get_minimum_size(); + return ms; } @@ -739,24 +714,24 @@ Popup* TabContainer::get_popup() const { 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); - ObjectTypeDB::bind_method(_MD("are_tabs_visible"),&TabContainer::are_tabs_visible); - ObjectTypeDB::bind_method(_MD("set_tab_title","tab_idx","title"),&TabContainer::set_tab_title); - 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); + ClassDB::bind_method(_MD("_gui_input"),&TabContainer::_gui_input); + ClassDB::bind_method(_MD("get_tab_count"),&TabContainer::get_tab_count); + ClassDB::bind_method(_MD("set_current_tab","tab_idx"),&TabContainer::set_current_tab); + ClassDB::bind_method(_MD("get_current_tab"),&TabContainer::get_current_tab); + ClassDB::bind_method(_MD("get_current_tab_control:Control"),&TabContainer::get_current_tab_control); + ClassDB::bind_method(_MD("get_tab_control:Control","idx"),&TabContainer::get_tab_control); + ClassDB::bind_method(_MD("set_tab_align","align"),&TabContainer::set_tab_align); + ClassDB::bind_method(_MD("get_tab_align"),&TabContainer::get_tab_align); + ClassDB::bind_method(_MD("set_tabs_visible","visible"),&TabContainer::set_tabs_visible); + ClassDB::bind_method(_MD("are_tabs_visible"),&TabContainer::are_tabs_visible); + ClassDB::bind_method(_MD("set_tab_title","tab_idx","title"),&TabContainer::set_tab_title); + ClassDB::bind_method(_MD("get_tab_title","tab_idx"),&TabContainer::get_tab_title); + ClassDB::bind_method(_MD("set_tab_icon","tab_idx","icon:Texture"),&TabContainer::set_tab_icon); + ClassDB::bind_method(_MD("get_tab_icon:Texture","tab_idx"),&TabContainer::get_tab_icon); + ClassDB::bind_method(_MD("set_popup","popup:Popup"),&TabContainer::set_popup); + ClassDB::bind_method(_MD("get_popup:Popup"),&TabContainer::get_popup); + + ClassDB::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")); diff --git a/scene/gui/tab_container.h b/scene/gui/tab_container.h index 979ce927a0..8b6ca7704e 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-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 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 @@ #include "scene/gui/popup.h" class TabContainer : public Control { - OBJ_TYPE( TabContainer, Control ); + GDCLASS( TabContainer, Control ); public: enum TabAlign { @@ -61,7 +61,7 @@ private: protected: void _child_renamed_callback(); - void _input_event(const InputEvent& p_event); + void _gui_input(const InputEvent& p_event); void _notification(int p_what); virtual void add_child_notify(Node *p_child); virtual void remove_child_notify(Node *p_child); diff --git a/scene/gui/tabs.cpp b/scene/gui/tabs.cpp index eb060aa6b8..98d3f6230d 100644 --- a/scene/gui/tabs.cpp +++ b/scene/gui/tabs.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 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 */ @@ -76,7 +76,7 @@ Size2 Tabs::get_minimum_size() const { } -void Tabs::_input_event(const InputEvent& p_event) { +void Tabs::_gui_input(const InputEvent& p_event) { if (p_event.type==InputEvent::MOUSE_MOTION) { @@ -649,19 +649,19 @@ void Tabs::set_tab_close_display_policy(CloseButtonDisplayPolicy p_policy) { void Tabs::_bind_methods() { - ObjectTypeDB::bind_method(_MD("_input_event"),&Tabs::_input_event); - ObjectTypeDB::bind_method(_MD("get_tab_count"),&Tabs::get_tab_count); - ObjectTypeDB::bind_method(_MD("set_current_tab","tab_idx"),&Tabs::set_current_tab); - ObjectTypeDB::bind_method(_MD("get_current_tab"),&Tabs::get_current_tab); - ObjectTypeDB::bind_method(_MD("set_tab_title","tab_idx","title"),&Tabs::set_tab_title); - ObjectTypeDB::bind_method(_MD("get_tab_title","tab_idx"),&Tabs::get_tab_title); - ObjectTypeDB::bind_method(_MD("set_tab_icon","tab_idx","icon:Texture"),&Tabs::set_tab_icon); - 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); - ObjectTypeDB::bind_method(_MD("ensure_tab_visible","idx"),&Tabs::ensure_tab_visible); + ClassDB::bind_method(_MD("_gui_input"),&Tabs::_gui_input); + ClassDB::bind_method(_MD("get_tab_count"),&Tabs::get_tab_count); + ClassDB::bind_method(_MD("set_current_tab","tab_idx"),&Tabs::set_current_tab); + ClassDB::bind_method(_MD("get_current_tab"),&Tabs::get_current_tab); + ClassDB::bind_method(_MD("set_tab_title","tab_idx","title"),&Tabs::set_tab_title); + ClassDB::bind_method(_MD("get_tab_title","tab_idx"),&Tabs::get_tab_title); + ClassDB::bind_method(_MD("set_tab_icon","tab_idx","icon:Texture"),&Tabs::set_tab_icon); + ClassDB::bind_method(_MD("get_tab_icon:Texture","tab_idx"),&Tabs::get_tab_icon); + ClassDB::bind_method(_MD("remove_tab","tab_idx"),&Tabs::remove_tab); + ClassDB::bind_method(_MD("add_tab","title","icon:Texture"),&Tabs::add_tab); + ClassDB::bind_method(_MD("set_tab_align","align"),&Tabs::set_tab_align); + ClassDB::bind_method(_MD("get_tab_align"),&Tabs::get_tab_align); + ClassDB::bind_method(_MD("ensure_tab_visible","idx"),&Tabs::ensure_tab_visible); ADD_SIGNAL(MethodInfo("tab_changed",PropertyInfo(Variant::INT,"tab"))); ADD_SIGNAL(MethodInfo("right_button_pressed",PropertyInfo(Variant::INT,"tab"))); diff --git a/scene/gui/tabs.h b/scene/gui/tabs.h index 5a4533c3d2..9ba32297dc 100644 --- a/scene/gui/tabs.h +++ b/scene/gui/tabs.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 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 */ @@ -33,7 +33,7 @@ class Tabs : public Control { - OBJ_TYPE( Tabs, Control ); + GDCLASS( Tabs, Control ); public: enum TabAlign { @@ -92,7 +92,7 @@ private: protected: - void _input_event(const InputEvent& p_event); + void _gui_input(const InputEvent& p_event); void _notification(int p_what); static void _bind_methods(); diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index ceb40925ec..8efff21fc9 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-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 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,7 @@ #include "globals.h" #include "message_queue.h" +#include "scene/main/viewport.h" #define TAB_PIXELS @@ -346,7 +347,7 @@ void TextEdit::_update_scrollbars() { v_scroll->show(); v_scroll->set_max(total_rows); v_scroll->set_page(visible_rows); - v_scroll->set_val(cursor.line_ofs); + v_scroll->set_value(cursor.line_ofs); } else { cursor.line_ofs = 0; @@ -358,7 +359,7 @@ void TextEdit::_update_scrollbars() { h_scroll->show(); h_scroll->set_max(total_width); h_scroll->set_page(visible_width); - h_scroll->set_val(cursor.x_ofs); + h_scroll->set_value(cursor.x_ofs); } else { @@ -417,9 +418,24 @@ void TextEdit::_notification(int p_what) { _update_caches(); } break; + case MainLoop::NOTIFICATION_WM_FOCUS_IN: { + window_has_focus = true; + draw_caret = true; + update(); + } break; + case MainLoop::NOTIFICATION_WM_FOCUS_OUT: { + window_has_focus = false; + draw_caret = false; + update(); + } break; case NOTIFICATION_DRAW: { + if ((!has_focus() && !menu->has_focus()) || !window_has_focus) { + draw_caret = false; + } + if (draw_breakpoint_gutter) { + breakpoint_gutter_width = (get_row_height() * 55) / 100; cache.breakpoint_gutter_width = breakpoint_gutter_width; } else { cache.breakpoint_gutter_width = 0; @@ -466,12 +482,20 @@ void TextEdit::_notification(int p_what) { Color color = cache.font_color; int in_region=-1; + if (line_length_guideline) { + int x=xmargin_beg+cache.font->get_char_size('0').width*line_length_guideline_col-cursor.x_ofs; + if (x>xmargin_beg && x<xmargin_end) { + Color guideline_color(color.r,color.g,color.b,color.a*0.25f); + VisualServer::get_singleton()->canvas_item_add_line(ci,Point2(x,0),Point2(x,cache.size.height),guideline_color); + } + } + if (syntax_coloring) { - if (custom_bg_color.a>0.01) { + if (cache.background_color.a>0.01) { Point2i ofs = Point2i(cache.style_normal->get_offset())/2.0; - VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(ofs, get_size()-cache.style_normal->get_minimum_size()+ofs),custom_bg_color); + VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(ofs, get_size()-cache.style_normal->get_minimum_size()+ofs),cache.background_color); } //compute actual region to start (may be inside say, a comment). //slow in very large documments :( but ok for source! @@ -669,6 +693,8 @@ void TextEdit::_notification(int p_what) { // get the highlighted words String highlighted_text = get_selection_text(); + String line_num_padding = line_numbers_zero_padded ? "0" : " "; + for (int i=0;i<visible_rows;i++) { int line=i+cursor.line_ofs; @@ -684,6 +710,7 @@ void TextEdit::_notification(int p_what) { bool prev_is_char=false; bool prev_is_number = false; bool in_keyword=false; + bool underlined=false; bool in_word = false; bool in_function_name = false; bool in_member_variable = false; @@ -700,15 +727,6 @@ void TextEdit::_notification(int p_what) { if (highlighted_text.length() != 0 && highlighted_text != search_text) highlighted_text_col = _get_column_pos_of_word(highlighted_text, str, SEARCH_MATCH_CASE|SEARCH_WHOLE_WORDS, 0); - if (cache.line_number_w) { - String fc = String::num(line+1); - while (fc.length() < line_number_char_count) { - fc="0"+fc; - } - - cache.font->draw(ci,Point2(cache.style_normal->get_margin(MARGIN_LEFT)+cache.breakpoint_gutter_width,ofs_y+cache.font->get_ascent()),fc,cache.line_number_color); - } - const Map<int,Text::ColorRegionInfo>& cri_map=text.get_color_region_info(line); @@ -720,21 +738,32 @@ void TextEdit::_notification(int p_what) { if (text.is_breakpoint(line)) { VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(xmargin_beg, ofs_y,xmargin_end-xmargin_beg,get_row_height()),cache.breakpoint_color); + } - // draw breakpoint marker + if (line==cursor.line) { + VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(0, ofs_y,xmargin_end,get_row_height()),cache.current_line_color); + } + + // draw breakpoint marker + if (text.is_breakpoint(line)) { if (draw_breakpoint_gutter) { - int vertical_gap = cache.breakpoint_gutter_width / 2; - int marker_size = cache.breakpoint_gutter_width - vertical_gap; + int vertical_gap = (get_row_height() * 40) / 100; + int horizontal_gap = (cache.breakpoint_gutter_width * 30) / 100; + int marker_height = get_row_height() - (vertical_gap * 2); + int marker_width = cache.breakpoint_gutter_width - (horizontal_gap * 2); // no transparency on marker - VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(cache.style_normal->get_margin(MARGIN_LEFT) + 1, ofs_y + vertical_gap ,marker_size, marker_size),Color(cache.breakpoint_color.r, cache.breakpoint_color.g, cache.breakpoint_color.b)); + VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(cache.style_normal->get_margin(MARGIN_LEFT) + horizontal_gap - 2, ofs_y + vertical_gap ,marker_width, marker_height),Color(cache.breakpoint_color.r, cache.breakpoint_color.g, cache.breakpoint_color.b)); } } - if (line==cursor.line) { - - VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(xmargin_beg, ofs_y,xmargin_end-xmargin_beg,get_row_height()),cache.current_line_color); + if (cache.line_number_w) { + String fc = String::num(line+1); + while (fc.length() < line_number_char_count) { + fc=line_num_padding+fc; + } + cache.font->draw(ci,Point2(cache.style_normal->get_margin(MARGIN_LEFT)+cache.breakpoint_gutter_width,ofs_y+cache.font->get_ascent()),fc,cache.line_number_color); } for (int j=0;j<str.length();j++) { @@ -807,8 +836,10 @@ void TextEdit::_notification(int p_what) { } } - if (!is_char) + if (!is_char) { in_keyword=false; + underlined=false; + } if (in_region==-1 && !in_keyword && is_char && !prev_is_char) { @@ -826,6 +857,12 @@ void TextEdit::_notification(int p_what) { in_keyword=true; keyword_color=*col; } + + if (select_identifiers_enabled && hilighted_word!=String()) { + if (hilighted_word==range) { + underlined=true; + } + } } if (!in_function_name && in_word && !in_keyword) { @@ -835,6 +872,11 @@ void TextEdit::_notification(int p_what) { k++; } + // check for space between name and bracket + while (k < str.length() && (str[k] == '\t' || str[k] == ' ')) { + k++; + } + if (str[k] == '(') { in_function_name = true; } @@ -865,7 +907,7 @@ void TextEdit::_notification(int p_what) { else if (in_function_name) color=cache.function_color; else if (is_symbol) - color=symbol_color; + color=cache.symbol_color; else if (is_number) color=cache.number_color; @@ -943,6 +985,12 @@ void TextEdit::_notification(int p_what) { } bool in_highlighted_word = (j >= highlighted_text_col && j < highlighted_text_col+highlighted_text.length()); + + /* if this is the original highlighted text we don't want to highlight it again */ + if (cursor.line==line && (cursor.column >= highlighted_text_col && cursor.column <= highlighted_text_col+highlighted_text.length())) { + in_highlighted_word = false; + } + if (in_highlighted_word) { VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(Point2i( char_ofs+char_margin, ofs_y ), Size2i(char_w, get_row_height())),cache.word_highlighted_color); } @@ -971,34 +1019,43 @@ void TextEdit::_notification(int p_what) { } } - - if (str[j]>=32) - cache.font->draw_char(ci,Point2i( char_ofs+char_margin, ofs_y+ascent),str[j],str[j+1],in_selection?cache.font_selected_color:color); - - else if (draw_tabs && str[j]=='\t') { - int yofs= (get_row_height() - cache.tab_icon->get_height())/2; - cache.tab_icon->draw(ci, Point2(char_ofs+char_margin,ofs_y+yofs),in_selection?cache.font_selected_color:color); - } - - if (cursor.column==j && cursor.line==line) { cursor_pos = Point2i( char_ofs+char_margin, ofs_y ); if (insert_mode) { - cursor_pos.y += get_row_height(); + cursor_pos.y += (get_row_height() - 3); } + int caret_w = (str[j]=='\t') ? cache.font->get_char_size(' ').width : char_w; if (draw_caret) { if (insert_mode) { - VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(cursor_pos, Size2i(char_w,1)),cache.caret_color); + int caret_h = (block_caret) ? 4 : 1; + VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(cursor_pos, Size2i(caret_w,caret_h)),cache.caret_color); } else { - VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(cursor_pos, Size2i(1,get_row_height())),cache.caret_color); + caret_w = (block_caret) ? caret_w : 1; + VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(cursor_pos, Size2i(caret_w,get_row_height())),cache.caret_color); } } } - char_ofs+=char_w; + if (cursor.column==j && cursor.line==line && block_caret && draw_caret && !insert_mode) { + color = cache.caret_background_color; + } + + if (str[j]>=32) { + int w = cache.font->draw_char(ci,Point2i( char_ofs+char_margin, ofs_y+ascent),str[j],str[j+1],in_selection?cache.font_selected_color:color); + if (underlined) { + draw_rect(Rect2( char_ofs+char_margin, ofs_y+ascent+2,w,1),in_selection?cache.font_selected_color:color); + } + } + + else if (draw_tabs && str[j]=='\t') { + int yofs= (get_row_height() - cache.tab_icon->get_height())/2; + cache.tab_icon->draw(ci, Point2(char_ofs+char_margin,ofs_y+yofs),in_selection?cache.font_selected_color:color); + } + + char_ofs+=char_w; } if (cursor.column==str.length() && cursor.line==line && (char_ofs+char_margin)>=xmargin_beg) { @@ -1006,15 +1063,18 @@ void TextEdit::_notification(int p_what) { cursor_pos=Point2i( char_ofs+char_margin, ofs_y ); if (insert_mode) { - cursor_pos.y += get_row_height(); + cursor_pos.y += (get_row_height() - 3); } if (draw_caret) { if (insert_mode) { int char_w = cache.font->get_char_size(' ').width; - VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(cursor_pos, Size2i(char_w,1)),cache.caret_color); + int caret_h = (block_caret) ? 4 : 1; + VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(cursor_pos, Size2i(char_w,caret_h)),cache.caret_color); } else { - VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(cursor_pos, Size2i(1,get_row_height())),cache.caret_color); + int char_w = cache.font->get_char_size(' ').width; + int caret_w = (block_caret) ? char_w : 1; + VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(cursor_pos, Size2i(caret_w,get_row_height())),cache.caret_color); } } } @@ -1024,11 +1084,8 @@ void TextEdit::_notification(int p_what) { if (completion_active) { // code completion box Ref<StyleBox> csb = get_stylebox("completion"); - Ref<StyleBox> csel = get_stylebox("completion_selected"); int maxlines = get_constant("completion_lines"); int cmax_width = get_constant("completion_max_width")*cache.font->get_char_size('x').x; - Color existing = get_color("completion_existing"); - existing.a=0.2; int scrollw = get_constant("completion_scroll_width"); Color scrollc = get_color("completion_scroll_color"); @@ -1072,11 +1129,12 @@ void TextEdit::_notification(int p_what) { draw_style_box(csb,Rect2(completion_rect.pos-csb->get_offset(),completion_rect.size+csb->get_minimum_size()+Size2(scrollw,0))); - + if (cache.completion_background_color.a>0.01) { + VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(completion_rect.pos,completion_rect.size+Size2(scrollw,0)),cache.completion_background_color); + } int line_from = CLAMP(completion_index - lines/2, 0, completion_options.size() - lines); - draw_style_box(csel,Rect2(Point2(completion_rect.pos.x,completion_rect.pos.y+(completion_index-line_from)*get_row_height()),Size2(completion_rect.size.width,get_row_height()))); - - draw_rect(Rect2(completion_rect.pos,Size2(nofs,completion_rect.size.height)),existing); + VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(Point2(completion_rect.pos.x,completion_rect.pos.y+(completion_index-line_from)*get_row_height()),Size2(completion_rect.size.width,get_row_height())),cache.completion_selected_color); + draw_rect(Rect2(completion_rect.pos,Size2(nofs,completion_rect.size.height)),cache.completion_existing_color); @@ -1085,7 +1143,7 @@ void TextEdit::_notification(int p_what) { int l = line_from + i; ERR_CONTINUE( l < 0 || l>= completion_options.size()); - Color text_color = cache.font_color; + Color text_color = cache.completion_font_color; for(int j=0;j<color_regions.size();j++) { if (completion_options[l].begins_with(color_regions[j].begin_key)) { text_color=color_regions[j].color; @@ -1192,17 +1250,24 @@ void TextEdit::_notification(int p_what) { } break; case NOTIFICATION_FOCUS_ENTER: { + if (!caret_blink_enabled) { + draw_caret = true; + } if (OS::get_singleton()->has_virtual_keyboard()) OS::get_singleton()->show_virtual_keyboard(get_text(),get_global_rect()); + if (raised_from_completion) { + VisualServer::get_singleton()->canvas_item_set_z(get_canvas_item(), 1); + } } break; case NOTIFICATION_FOCUS_EXIT: { if (OS::get_singleton()->has_virtual_keyboard()) OS::get_singleton()->hide_virtual_keyboard(); - + if (raised_from_completion) { + VisualServer::get_singleton()->canvas_item_set_z(get_canvas_item(), 0); + } } break; - } } @@ -1403,13 +1468,13 @@ void TextEdit::_get_mouse_pos(const Point2i& p_mouse, int &r_row, int &r_col) co r_col=col; } -void TextEdit::_input_event(const InputEvent& p_input_event) { +void TextEdit::_gui_input(const InputEvent& p_gui_input) { - switch(p_input_event.type) { + switch(p_gui_input.type) { case InputEvent::MOUSE_BUTTON: { - const InputEventMouseButton &mb=p_input_event.mouse_button; + const InputEventMouseButton &mb=p_gui_input.mouse_button; if (completion_active && completion_rect.has_point(Point2(mb.x,mb.y))) { @@ -1449,30 +1514,39 @@ void TextEdit::_input_event(const InputEvent& p_input_event) { } if (mb.pressed) { - if (mb.button_index==BUTTON_WHEEL_UP) { - v_scroll->set_val( v_scroll->get_val() -3 ); + if (mb.button_index==BUTTON_WHEEL_UP && !mb.mod.command) { + v_scroll->set_value( v_scroll->get_value() -3 ); } - if (mb.button_index==BUTTON_WHEEL_DOWN) { - v_scroll->set_val( v_scroll->get_val() +3 ); + if (mb.button_index==BUTTON_WHEEL_DOWN && !mb.mod.command) { + v_scroll->set_value( v_scroll->get_value() +3 ); } if (mb.button_index==BUTTON_WHEEL_LEFT) { - h_scroll->set_val( h_scroll->get_val() -3 ); + h_scroll->set_value( h_scroll->get_value() -3 ); } if (mb.button_index==BUTTON_WHEEL_RIGHT) { - h_scroll->set_val( h_scroll->get_val() +3 ); + h_scroll->set_value( h_scroll->get_value() +3 ); } if (mb.button_index==BUTTON_LEFT) { + _reset_caret_blink_timer(); int row,col; _get_mouse_pos(Point2i(mb.x,mb.y), row,col); + if (mb.mod.command && hilighted_word!=String()) { + + emit_signal("symbol_lookup",hilighted_word,row,col); + return; + } + + // toggle breakpoint on gutter click if (draw_breakpoint_gutter) { int gutter=cache.style_normal->get_margin(MARGIN_LEFT); if (mb.x > gutter && mb.x <= gutter + cache.breakpoint_gutter_width + 3) { set_line_as_breakpoint(row, !is_line_set_as_breakpoint(row)); + emit_signal("breakpoint_toggled", row); return; } } @@ -1591,7 +1665,7 @@ void TextEdit::_input_event(const InputEvent& p_input_event) { update(); } - if (mb.button_index==BUTTON_RIGHT) { + if (mb.button_index==BUTTON_RIGHT && context_menu_enabled) { menu->set_pos(get_global_transform().xform(get_local_mouse_pos())); menu->set_size(Vector2(1,1)); @@ -1611,9 +1685,25 @@ void TextEdit::_input_event(const InputEvent& p_input_event) { } break; case InputEvent::MOUSE_MOTION: { - const InputEventMouseMotion &mm=p_input_event.mouse_motion; + const InputEventMouseMotion &mm=p_gui_input.mouse_motion; + + if (select_identifiers_enabled) { + if (mm.mod.command && mm.button_mask==0) { + + String new_word = get_word_at_pos(Vector2(mm.x,mm.y)); + if (new_word!=hilighted_word) { + hilighted_word=new_word; + update(); + } + } else { + if (hilighted_word!=String()) { + hilighted_word=String(); + update(); + } + } + } - if (mm.button_mask&BUTTON_MASK_LEFT) { + if (mm.button_mask&BUTTON_MASK_LEFT && get_viewport()->gui_get_drag_data()==Variant()) { //ignore if dragging if (selection.selecting_mode!=Selection::MODE_NONE) { @@ -1638,7 +1728,28 @@ void TextEdit::_input_event(const InputEvent& p_input_event) { case InputEvent::KEY: { - InputEventKey k=p_input_event.key; + InputEventKey k=p_gui_input.key; + + +#ifdef OSX_ENABLED + if (k.scancode==KEY_META) { +#else + if (k.scancode==KEY_CONTROL) { + +#endif + if (select_identifiers_enabled) { + + if (k.pressed) { + + hilighted_word = get_word_at_pos(get_local_mouse_pos()); + update(); + + } else { + hilighted_word=String(); + update(); + } + } + } if (!k.pressed) return; @@ -1730,7 +1841,7 @@ void TextEdit::_input_event(const InputEvent& p_input_event) { return; } - if (k.scancode==KEY_RETURN || k.scancode==KEY_TAB) { + if (k.scancode==KEY_ENTER || k.scancode==KEY_RETURN || k.scancode==KEY_TAB) { _confirm_completion(); accept_event(); @@ -1807,6 +1918,8 @@ void TextEdit::_input_event(const InputEvent& p_input_event) { if (!k.mod.command) { _reset_caret_blink_timer(); } + + // save here for insert mode, just in case it is cleared in the following section bool had_selection = selection.active; @@ -1955,6 +2068,7 @@ void TextEdit::_input_event(const InputEvent& p_input_event) { } } break; case KEY_TAB: { + if (k.mod.command) break; // avoid tab when command if (readonly) break; @@ -2047,6 +2161,12 @@ void TextEdit::_input_event(const InputEvent& p_input_event) { if (k.mod.shift) _pre_shift_selection(); +#ifdef APPLE_STYLE_KEYS + else +#else + else if (!k.mod.alt) +#endif + deselect(); #ifdef APPLE_STYLE_KEYS if (k.mod.command) { @@ -2100,6 +2220,12 @@ void TextEdit::_input_event(const InputEvent& p_input_event) { if (k.mod.shift) _pre_shift_selection(); +#ifdef APPLE_STYLE_KEYS + else +#else + else if (!k.mod.alt) +#endif + deselect(); #ifdef APPLE_STYLE_KEYS if (k.mod.command) { @@ -2430,7 +2556,9 @@ void TextEdit::_input_event(const InputEvent& p_input_event) { } break; case KEY_X: { - + if (readonly) { + break; + } if (!k.mod.command || k.mod.shift || k.mod.alt) { scancode_handled=false; break; @@ -2462,7 +2590,9 @@ void TextEdit::_input_event(const InputEvent& p_input_event) { undo(); } break; case KEY_V: { - + if (readonly) { + break; + } if (!k.mod.command || k.mod.shift || k.mod.alt) { scancode_handled=false; break; @@ -2507,7 +2637,7 @@ void TextEdit::_input_event(const InputEvent& p_input_event) { } update(); } - break;} + } break; default: { @@ -2889,7 +3019,7 @@ int TextEdit::get_char_count() { return totalsize; // omit last \n } -Size2 TextEdit::get_minimum_size() { +Size2 TextEdit::get_minimum_size() const { return cache.style_normal->get_minimum_size(); } @@ -2906,7 +3036,7 @@ void TextEdit::adjust_viewport_to_cursor() { cursor.line_ofs=cursor.line; int visible_width=cache.size.width-cache.style_normal->get_minimum_size().width-cache.line_number_w-cache.breakpoint_gutter_width; - if (v_scroll->is_visible()) + if (v_scroll->is_visible_in_tree()) visible_width-=v_scroll->get_combined_minimum_size().width; visible_width-=20; // give it a little more space @@ -2914,7 +3044,7 @@ void TextEdit::adjust_viewport_to_cursor() { //printf("rowofs %i, visrows %i, cursor.line %i\n",cursor.line_ofs,get_visible_rows(),cursor.line); int visible_rows = get_visible_rows(); - if (h_scroll->is_visible()) + if (h_scroll->is_visible_in_tree()) visible_rows-=((h_scroll->get_combined_minimum_size().height-1)/get_row_height()); if (cursor.line>=(cursor.line_ofs+visible_rows)) @@ -2942,6 +3072,34 @@ void TextEdit::adjust_viewport_to_cursor() { } +void TextEdit::center_viewport_to_cursor() { + + if (cursor.line_ofs>cursor.line) + cursor.line_ofs=cursor.line; + + int visible_width=cache.size.width-cache.style_normal->get_minimum_size().width-cache.line_number_w-cache.breakpoint_gutter_width; + if (v_scroll->is_visible_in_tree()) + visible_width-=v_scroll->get_combined_minimum_size().width; + visible_width-=20; // give it a little more space + + int visible_rows = get_visible_rows(); + if (h_scroll->is_visible_in_tree()) + visible_rows-=((h_scroll->get_combined_minimum_size().height-1)/get_row_height()); + + int max_ofs = text.size()-(scroll_past_end_of_file_enabled?1:visible_rows); + cursor.line_ofs=CLAMP(cursor.line-(visible_rows/2),0,max_ofs); + + int cursor_x = get_column_x_offset( cursor.column, text[cursor.line] ); + + if (cursor_x>(cursor.x_ofs+visible_width)) + cursor.x_ofs=cursor_x-visible_width+1; + + if (cursor_x < cursor.x_ofs) + cursor.x_ofs=cursor_x; + + update(); +} + void TextEdit::cursor_set_column(int p_col, bool p_adjust_viewport) { if (p_col<0) @@ -3032,16 +3190,25 @@ void TextEdit::cursor_set_blink_speed(const float p_speed) { caret_blink_timer->set_wait_time(p_speed); } +void TextEdit::cursor_set_block_mode(const bool p_enable){ + block_caret = p_enable; + update(); +} + +bool TextEdit::cursor_is_block_mode() const { + return block_caret; +} + void TextEdit::_scroll_moved(double p_to_val) { if (updating_scrolls) return; - if (h_scroll->is_visible()) - cursor.x_ofs=h_scroll->get_val(); - if (v_scroll->is_visible()) - cursor.line_ofs=v_scroll->get_val(); + if (h_scroll->is_visible_in_tree()) + cursor.x_ofs=h_scroll->get_value(); + if (v_scroll->is_visible_in_tree()) + cursor.line_ofs=v_scroll->get_value(); update(); } @@ -3134,6 +3301,9 @@ void TextEdit::insert_text_at_cursor(const String& p_text) { } Control::CursorShape TextEdit::get_cursor_shape(const Point2& p_pos) const { + if (hilighted_word!=String()) + return CURSOR_POINTING_HAND; + int gutter=cache.style_normal->get_margin(MARGIN_LEFT)+cache.line_number_w+cache.breakpoint_gutter_width; if((completion_active && completion_rect.has_point(p_pos)) || p_pos.x < gutter) { return CURSOR_ARROW; @@ -3157,7 +3327,7 @@ void TextEdit::set_text(String p_text){ cursor_set_column(0); update(); setting_text=false; - + _text_changed_emit(); //get_range()->set(0); }; @@ -3176,6 +3346,36 @@ String TextEdit::get_text() { }; + +String TextEdit::get_text_for_lookup_completion() { + + + int row,col; + _get_mouse_pos(get_local_mouse_pos(), row,col); + + + String longthing; + int len = text.size(); + for (int i=0;i<len;i++) { + + if (i==row) { + longthing+=text[i].substr(0,col); + longthing+=String::chr(0xFFFF); //not unicode, represents the cursor + longthing+=text[i].substr(col,text[i].size()); + } else { + + longthing+=text[i]; + } + + + if (i!=len-1) + longthing+="\n"; + } + + return longthing; + +} + String TextEdit::get_text_for_completion() { String longthing; @@ -3258,15 +3458,22 @@ void TextEdit::_reset_caret_blink_timer() { void TextEdit::_toggle_draw_caret() { draw_caret = !draw_caret; - update(); + if (is_visible_in_tree() && has_focus() && window_has_focus) { + update(); + } } void TextEdit::_update_caches() { cache.style_normal=get_stylebox("normal"); cache.style_focus=get_stylebox("focus"); + cache.completion_background_color=get_color("completion_background_color"); + cache.completion_selected_color=get_color("completion_selected_color"); + cache.completion_existing_color=get_color("completion_existing_color"); + cache.completion_font_color=get_color("completion_font_color"); cache.font=get_font("font"); cache.caret_color=get_color("caret_color"); + cache.caret_background_color=get_color("caret_background_color"); cache.line_number_color=get_color("line_number_color"); cache.font_color=get_color("font_color"); cache.font_selected_color=get_color("font_selected_color"); @@ -3282,6 +3489,8 @@ void TextEdit::_update_caches() { cache.word_highlighted_color=get_color("word_highlighted_color"); cache.search_result_color=get_color("search_result_color"); cache.search_result_border_color=get_color("search_result_border_color"); + cache.symbol_color=get_color("symbol_color"); + cache.background_color=get_color("background_color"); cache.line_spacing=get_constant("line_spacing"); cache.row_height = cache.font->get_height() + cache.line_spacing; cache.tab_icon=get_icon("tab"); @@ -3293,15 +3502,8 @@ void TextEdit::_update_caches() { void TextEdit::clear_colors() { keywords.clear(); - color_regions.clear();; + color_regions.clear(); text.clear_caches(); - custom_bg_color=Color(0,0,0,0); -} - -void TextEdit::set_custom_bg_color(const Color& p_color) { - - custom_bg_color=p_color; - update(); } void TextEdit::add_keyword_color(const String& p_keyword,const Color& p_color) { @@ -3319,12 +3521,6 @@ void TextEdit::add_color_region(const String& p_begin_key,const String& p_end_ke } -void TextEdit::set_symbol_color(const Color& p_color) { - - symbol_color=p_color; - update(); -} - void TextEdit::set_syntax_coloring(bool p_enabled) { syntax_coloring=p_enabled; @@ -3554,6 +3750,7 @@ void TextEdit::set_search_flags(uint32_t p_flags) { void TextEdit::set_current_search_result(int line, int col) { search_result_line = line; search_result_col = col; + update(); } void TextEdit::set_highlight_all_occurrences(const bool p_enabled) { @@ -3561,6 +3758,10 @@ void TextEdit::set_highlight_all_occurrences(const bool p_enabled) { update(); } +bool TextEdit::is_highlight_all_occurrences_enabled() const { + return highlight_all_occurrences; +} + int TextEdit::_get_column_pos_of_word(const String &p_key, const String &p_search, uint32_t p_search_flags, int p_from_column) { int col = -1; @@ -3582,7 +3783,7 @@ int TextEdit::_get_column_pos_of_word(const String &p_key, const String &p_searc if (col > 0 && _is_text_char(p_search[col-1])) { col = -1; - } else if (_is_text_char(p_search[col+p_key.length()])) { + } else if ((col + p_key.length()) < p_search.length() && _is_text_char(p_search[col+p_key.length()])) { col = -1; } } @@ -3593,11 +3794,11 @@ int TextEdit::_get_column_pos_of_word(const String &p_key, const String &p_searc return col; } -DVector<int> TextEdit::_search_bind(const String &p_key,uint32_t p_search_flags, int p_from_line,int p_from_column) const { +PoolVector<int> TextEdit::_search_bind(const String &p_key,uint32_t p_search_flags, int p_from_line,int p_from_column) const { int col,line; if (search(p_key,p_search_flags,p_from_line,p_from_column,col,line)) { - DVector<int> result; + PoolVector<int> result; result.resize(2); result.set(0,line); result.set(1,col); @@ -3605,7 +3806,7 @@ DVector<int> TextEdit::_search_bind(const String &p_key,uint32_t p_search_flags, } else { - return DVector<int>(); + return PoolVector<int>(); } } @@ -3819,16 +4020,26 @@ void TextEdit::undo() { _do_text_op(op, true); current_op.version=op.prev_version; if(undo_stack_pos->get().chain_backward) { - do { + while(true) { + ERR_BREAK(!undo_stack_pos->prev()); undo_stack_pos = undo_stack_pos->prev(); op = undo_stack_pos->get(); _do_text_op(op, true); current_op.version = op.prev_version; - } while(!undo_stack_pos->get().chain_forward); + if (undo_stack_pos->get().chain_forward) { + break; + } + } } - cursor_set_line(undo_stack_pos->get().from_line); - cursor_set_column(undo_stack_pos->get().from_column); + if (undo_stack_pos->get().type == TextOperation::TYPE_REMOVE) { + cursor_set_line(undo_stack_pos->get().to_line); + cursor_set_column(undo_stack_pos->get().to_column); + _cancel_code_hint(); + } else { + cursor_set_line(undo_stack_pos->get().from_line); + cursor_set_column(undo_stack_pos->get().from_column); + } update(); } @@ -3843,12 +4054,16 @@ void TextEdit::redo() { _do_text_op(op, false); current_op.version = op.version; if(undo_stack_pos->get().chain_forward) { - do { + + while(true) { + ERR_BREAK(!undo_stack_pos->next()); undo_stack_pos=undo_stack_pos->next(); op = undo_stack_pos->get(); _do_text_op(op, false); current_op.version = op.version; - } while(!undo_stack_pos->get().chain_backward); + if (undo_stack_pos->get().chain_backward) + break; + } } cursor_set_line(undo_stack_pos->get().to_line); cursor_set_column(undo_stack_pos->get().to_column); @@ -3940,21 +4155,21 @@ void TextEdit::tag_saved_version() { int TextEdit::get_v_scroll() const { - return v_scroll->get_val(); + return v_scroll->get_value(); } void TextEdit::set_v_scroll(int p_scroll) { - v_scroll->set_val(p_scroll); + v_scroll->set_value(p_scroll); cursor.line_ofs=p_scroll; } int TextEdit::get_h_scroll() const { - return h_scroll->get_val(); + return h_scroll->get_value(); } void TextEdit::set_h_scroll(int p_scroll) { - h_scroll->set_val(p_scroll); + h_scroll->set_value(p_scroll); } void TextEdit::set_completion(bool p_enabled,const Vector<String>& p_prefixes) { @@ -3967,39 +4182,35 @@ void TextEdit::set_completion(bool p_enabled,const Vector<String>& p_prefixes) { void TextEdit::_confirm_completion() { - String remaining=completion_current.substr(completion_base.length(),completion_current.length()-completion_base.length()); - String l = text[cursor.line]; - bool same=true; - //if what is going to be inserted is the same as what it is, don't change it - for(int i=0;i<remaining.length();i++) { - int c=i+cursor.column; - if (c>=l.length() || l[c]!=remaining[i]) { - same=false; - break; - } - } + begin_complex_operation(); - if (same) - cursor_set_column(cursor.column+remaining.length()); - else { - insert_text_at_cursor(remaining); - if (remaining.ends_with("(") && auto_brace_completion_enabled) { - insert_text_at_cursor(")"); - cursor.column--; - } + _remove_text(cursor.line, cursor.column - completion_base.length(), cursor.line, cursor.column); + cursor_set_column(cursor.column - completion_base.length(), false); + insert_text_at_cursor(completion_current); + + if (completion_current.ends_with("(") && auto_brace_completion_enabled) { + insert_text_at_cursor(")"); + cursor.column--; } + end_complex_operation(); + _cancel_completion(); } void TextEdit::_cancel_code_hint() { + + VisualServer::get_singleton()->canvas_item_set_z(get_canvas_item(), 0); + raised_from_completion = false; completion_hint=""; update(); } void TextEdit::_cancel_completion() { + VisualServer::get_singleton()->canvas_item_set_z(get_canvas_item(), 0); + raised_from_completion = false; if (!completion_active) return; @@ -4019,7 +4230,6 @@ void TextEdit::_update_completion_candidates() { String l = text[cursor.line]; int cofs = CLAMP(cursor.column,0,l.length()); - String s; //look for keywords first @@ -4068,14 +4278,14 @@ void TextEdit::_update_completion_candidates() { while(cofs>0 && l[cofs-1]>32 && _is_completable(l[cofs-1])) { s=String::chr(l[cofs-1])+s; - if (l[cofs-1]=='\'' || l[cofs-1]=='"') + if (l[cofs-1]=='\'' || l[cofs-1]=='"' || l[cofs-1]=='$') break; cofs--; } } - if (l[cursor.column - 1] == '(' && !pre_keyword && !completion_strings[0].begins_with("\"")) { + if (cursor.column > 0 && l[cursor.column - 1] == '(' && !pre_keyword && !completion_strings[0].begins_with("\"")) { cancel = true; } @@ -4090,31 +4300,43 @@ void TextEdit::_update_completion_candidates() { completion_options.clear(); completion_index=0; completion_base=s; - int ci_match=0; + Vector<float> sim_cache; for(int i=0;i<completion_strings.size();i++) { - if (completion_strings[i].begins_with(s)) { - // don't remove duplicates if no input is provided - if (completion_options.find(completion_strings[i]) != -1 && s != "") { - continue; - } - completion_options.push_back(completion_strings[i]); - int m=0; - int max=MIN(completion_current.length(),completion_strings[i].length()); - if (max<ci_match) - continue; - for(int j=0;j<max;j++) { + if (s == completion_strings[i]) { + // A perfect match, stop completion + _cancel_completion(); + return; + } - if (j>=completion_strings[i].length()) - break; - if (completion_current[j]!=completion_strings[i][j]) - break; - m++; + if (s.is_subsequence_ofi(completion_strings[i])) { + // don't remove duplicates if no input is provided + if (s != "" && completion_options.find(completion_strings[i]) != -1) { + continue; } - if (m>ci_match) { - ci_match=m; - completion_index=completion_options.size()-1; + // Calculate the similarity to keep completions in good order + float similarity; + if (completion_strings[i].to_lower().begins_with(s.to_lower())) { + // Substrings are the best candidates + similarity = 1.1; + } else { + // Otherwise compute the similarity + similarity = s.to_lower().similarity(completion_strings[i].to_lower()); } + int comp_size = completion_options.size(); + if (comp_size == 0) { + completion_options.push_back(completion_strings[i]); + sim_cache.push_back(similarity); + } else { + float comp_sim; + int pos = 0; + do { + comp_sim = sim_cache[pos++]; + } while(pos < comp_size && similarity < comp_sim); + pos = similarity > comp_sim ? pos - 1 : pos; // Pos will be off by one + completion_options.insert(pos, completion_strings[i]); + sim_cache.insert(pos, similarity); + } } } @@ -4123,24 +4345,24 @@ void TextEdit::_update_completion_candidates() { if (completion_options.size()==0) { //no options to complete, cancel _cancel_completion(); + return; } - completion_current=completion_options[completion_index]; + // The top of the list is the best match + completion_current=completion_options[0]; #if 0 // even there's only one option, user still get the chance to choose using it or not if (completion_options.size()==1) { //one option to complete, just complete it automagically _confirm_completion(); - // insert_text_at_cursor(completion_options[0].substr(s.length(),completion_options[0].length()-s.length())); + //insert_text_at_cursor(completion_options[0].substr(s.length(),completion_options[0].length()-s.length())); _cancel_completion(); return; } #endif - if (completion_options.size()==1 && s==completion_options[0]) - _cancel_completion(); completion_enabled=true; } @@ -4169,6 +4391,8 @@ void TextEdit::query_code_comple() { void TextEdit::set_code_hint(const String& p_hint) { + VisualServer::get_singleton()->canvas_item_set_z(get_canvas_item(), 1); + raised_from_completion = true; completion_hint=p_hint; completion_hint_offset=-0xFFFF; update(); @@ -4176,7 +4400,8 @@ void TextEdit::set_code_hint(const String& p_hint) { void TextEdit::code_complete(const Vector<String> &p_strings) { - + VisualServer::get_singleton()->canvas_item_set_z(get_canvas_item(), 1); + raised_from_completion = true; completion_strings=p_strings; completion_active=true; completion_current=""; @@ -4186,6 +4411,38 @@ void TextEdit::code_complete(const Vector<String> &p_strings) { } +String TextEdit::get_word_at_pos(const Vector2& p_pos) const { + + int row,col; + _get_mouse_pos(p_pos, row, col); + + String s = text[row]; + if (s.length()==0) + return ""; + int beg=CLAMP(col,0,s.length()); + int end=beg; + + + if (s[beg]>32 || beg==s.length()) { + + bool symbol = beg < s.length() && _is_symbol(s[beg]); //not sure if right but most editors behave like this + + while(beg>0 && s[beg-1]>32 && (symbol==_is_symbol(s[beg-1]))) { + beg--; + } + while(end<s.length() && s[end+1]>32 && (symbol==_is_symbol(s[end+1]))) { + end++; + } + + if (end<s.length()) + end+=1; + + return s.substr(beg,end-beg); + } + + return String(); +} + String TextEdit::get_tooltip(const Point2& p_pos) const { if (!tooltip_obj) @@ -4255,6 +4512,26 @@ void TextEdit::set_show_line_numbers(bool p_show) { update(); } +void TextEdit::set_line_numbers_zero_padded(bool p_zero_padded) { + + line_numbers_zero_padded=p_zero_padded; + update(); +} + +bool TextEdit::is_show_line_numbers_enabled() const { + return line_numbers; +} + +void TextEdit::set_show_line_length_guideline(bool p_show) { + line_length_guideline=p_show; + update(); +} + +void TextEdit::set_line_length_guideline_column(int p_column) { + line_length_guideline_col=p_column; + update(); +} + void TextEdit::set_draw_breakpoint_gutter(bool p_draw) { draw_breakpoint_gutter = p_draw; update(); @@ -4282,18 +4559,22 @@ void TextEdit::menu_option(int p_option) { switch( p_option ) { case MENU_CUT: { - - cut(); + if (!readonly) { + cut(); + } } break; case MENU_COPY: { copy(); } break; case MENU_PASTE: { - - paste(); + if (!readonly) { + paste(); + } } break; case MENU_CLEAR: { - clear(); + if (!readonly) { + clear(); + } } break; case MENU_SELECT_ALL: { select_all(); @@ -4305,6 +4586,21 @@ void TextEdit::menu_option(int p_option) { }; } + +void TextEdit::set_select_identifiers_on_hover(bool p_enable) { + + select_identifiers_enabled=p_enable; +} + +bool TextEdit::is_selecting_identifiers_on_hover_enabled() const { + + return select_identifiers_enabled; +} + +void TextEdit::set_context_menu_enabled(bool p_enable) { + context_menu_enabled = p_enable; +} + PopupMenu *TextEdit::get_menu() const { return menu; } @@ -4312,81 +4608,96 @@ PopupMenu *TextEdit::get_menu() const { void TextEdit::_bind_methods() { - ObjectTypeDB::bind_method(_MD("_input_event"),&TextEdit::_input_event); - ObjectTypeDB::bind_method(_MD("_scroll_moved"),&TextEdit::_scroll_moved); - ObjectTypeDB::bind_method(_MD("_cursor_changed_emit"),&TextEdit::_cursor_changed_emit); - ObjectTypeDB::bind_method(_MD("_text_changed_emit"),&TextEdit::_text_changed_emit); - ObjectTypeDB::bind_method(_MD("_push_current_op"),&TextEdit::_push_current_op); - ObjectTypeDB::bind_method(_MD("_click_selection_held"),&TextEdit::_click_selection_held); - ObjectTypeDB::bind_method(_MD("_toggle_draw_caret"),&TextEdit::_toggle_draw_caret); + ClassDB::bind_method(_MD("_gui_input"),&TextEdit::_gui_input); + ClassDB::bind_method(_MD("_scroll_moved"),&TextEdit::_scroll_moved); + ClassDB::bind_method(_MD("_cursor_changed_emit"),&TextEdit::_cursor_changed_emit); + ClassDB::bind_method(_MD("_text_changed_emit"),&TextEdit::_text_changed_emit); + ClassDB::bind_method(_MD("_push_current_op"),&TextEdit::_push_current_op); + ClassDB::bind_method(_MD("_click_selection_held"),&TextEdit::_click_selection_held); + ClassDB::bind_method(_MD("_toggle_draw_caret"),&TextEdit::_toggle_draw_caret); BIND_CONSTANT( SEARCH_MATCH_CASE ); BIND_CONSTANT( SEARCH_WHOLE_WORDS ); BIND_CONSTANT( SEARCH_BACKWARDS ); /* - ObjectTypeDB::bind_method(_MD("delete_char"),&TextEdit::delete_char); - ObjectTypeDB::bind_method(_MD("delete_line"),&TextEdit::delete_line); + ClassDB::bind_method(_MD("delete_char"),&TextEdit::delete_char); + ClassDB::bind_method(_MD("delete_line"),&TextEdit::delete_line); */ - ObjectTypeDB::bind_method(_MD("set_text","text"),&TextEdit::set_text); - ObjectTypeDB::bind_method(_MD("insert_text_at_cursor","text"),&TextEdit::insert_text_at_cursor); - - ObjectTypeDB::bind_method(_MD("get_line_count"),&TextEdit::get_line_count); - ObjectTypeDB::bind_method(_MD("get_text"),&TextEdit::get_text); - ObjectTypeDB::bind_method(_MD("get_line","line"),&TextEdit::get_line); - - ObjectTypeDB::bind_method(_MD("cursor_set_column","column","adjust_viewport"),&TextEdit::cursor_set_column,DEFVAL(false)); - ObjectTypeDB::bind_method(_MD("cursor_set_line","line","adjust_viewport"),&TextEdit::cursor_set_line,DEFVAL(false)); - - ObjectTypeDB::bind_method(_MD("cursor_get_column"),&TextEdit::cursor_get_column); - ObjectTypeDB::bind_method(_MD("cursor_get_line"),&TextEdit::cursor_get_line); - ObjectTypeDB::bind_method(_MD("cursor_set_blink_enabled", "enable"),&TextEdit::cursor_set_blink_enabled); - ObjectTypeDB::bind_method(_MD("cursor_get_blink_enabled"),&TextEdit::cursor_get_blink_enabled); - ObjectTypeDB::bind_method(_MD("cursor_set_blink_speed", "blink_speed"),&TextEdit::cursor_set_blink_speed); - ObjectTypeDB::bind_method(_MD("cursor_get_blink_speed"),&TextEdit::cursor_get_blink_speed); - - ObjectTypeDB::bind_method(_MD("set_readonly","enable"),&TextEdit::set_readonly); - ObjectTypeDB::bind_method(_MD("set_wrap","enable"),&TextEdit::set_wrap); - ObjectTypeDB::bind_method(_MD("set_max_chars","amount"),&TextEdit::set_max_chars); - - ObjectTypeDB::bind_method(_MD("cut"),&TextEdit::cut); - ObjectTypeDB::bind_method(_MD("copy"),&TextEdit::copy); - ObjectTypeDB::bind_method(_MD("paste"),&TextEdit::paste); - ObjectTypeDB::bind_method(_MD("select_all"),&TextEdit::select_all); - ObjectTypeDB::bind_method(_MD("select","from_line","from_column","to_line","to_column"),&TextEdit::select); - - ObjectTypeDB::bind_method(_MD("is_selection_active"),&TextEdit::is_selection_active); - ObjectTypeDB::bind_method(_MD("get_selection_from_line"),&TextEdit::get_selection_from_line); - ObjectTypeDB::bind_method(_MD("get_selection_from_column"),&TextEdit::get_selection_from_column); - ObjectTypeDB::bind_method(_MD("get_selection_to_line"),&TextEdit::get_selection_to_line); - ObjectTypeDB::bind_method(_MD("get_selection_to_column"),&TextEdit::get_selection_to_column); - ObjectTypeDB::bind_method(_MD("get_selection_text"),&TextEdit::get_selection_text); - ObjectTypeDB::bind_method(_MD("get_word_under_cursor"),&TextEdit::get_word_under_cursor); - ObjectTypeDB::bind_method(_MD("search","flags","from_line","from_column","to_line","to_column"),&TextEdit::_search_bind); - - ObjectTypeDB::bind_method(_MD("undo"),&TextEdit::undo); - ObjectTypeDB::bind_method(_MD("redo"),&TextEdit::redo); - ObjectTypeDB::bind_method(_MD("clear_undo_history"),&TextEdit::clear_undo_history); - - ObjectTypeDB::bind_method(_MD("set_syntax_coloring","enable"),&TextEdit::set_syntax_coloring); - ObjectTypeDB::bind_method(_MD("is_syntax_coloring_enabled"),&TextEdit::is_syntax_coloring_enabled); - - - ObjectTypeDB::bind_method(_MD("add_keyword_color","keyword","color"),&TextEdit::add_keyword_color); - ObjectTypeDB::bind_method(_MD("add_color_region","begin_key","end_key","color","line_only"),&TextEdit::add_color_region,DEFVAL(false)); - ObjectTypeDB::bind_method(_MD("set_symbol_color","color"),&TextEdit::set_symbol_color); - ObjectTypeDB::bind_method(_MD("set_custom_bg_color","color"),&TextEdit::set_custom_bg_color); - ObjectTypeDB::bind_method(_MD("clear_colors"),&TextEdit::clear_colors); - ObjectTypeDB::bind_method(_MD("menu_option"),&TextEdit::menu_option); - ObjectTypeDB::bind_method(_MD("get_menu:PopupMenu"),&TextEdit::get_menu); - - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "caret/caret_blink"), _SCS("cursor_set_blink_enabled"), _SCS("cursor_get_blink_enabled"));; - ADD_PROPERTYNZ(PropertyInfo(Variant::REAL, "caret/caret_blink_speed",PROPERTY_HINT_RANGE,"0.1,10,0.1"), _SCS("cursor_set_blink_speed"),_SCS("cursor_get_blink_speed") ); + ClassDB::bind_method(_MD("set_text","text"),&TextEdit::set_text); + ClassDB::bind_method(_MD("insert_text_at_cursor","text"),&TextEdit::insert_text_at_cursor); + + ClassDB::bind_method(_MD("get_line_count"),&TextEdit::get_line_count); + ClassDB::bind_method(_MD("get_text"),&TextEdit::get_text); + ClassDB::bind_method(_MD("get_line","line"),&TextEdit::get_line); + + ClassDB::bind_method(_MD("cursor_set_column","column","adjust_viewport"),&TextEdit::cursor_set_column,DEFVAL(false)); + ClassDB::bind_method(_MD("cursor_set_line","line","adjust_viewport"),&TextEdit::cursor_set_line,DEFVAL(false)); + + ClassDB::bind_method(_MD("cursor_get_column"),&TextEdit::cursor_get_column); + ClassDB::bind_method(_MD("cursor_get_line"),&TextEdit::cursor_get_line); + ClassDB::bind_method(_MD("cursor_set_blink_enabled", "enable"),&TextEdit::cursor_set_blink_enabled); + ClassDB::bind_method(_MD("cursor_get_blink_enabled"),&TextEdit::cursor_get_blink_enabled); + ClassDB::bind_method(_MD("cursor_set_blink_speed", "blink_speed"),&TextEdit::cursor_set_blink_speed); + ClassDB::bind_method(_MD("cursor_get_blink_speed"),&TextEdit::cursor_get_blink_speed); + ClassDB::bind_method(_MD("cursor_set_block_mode", "enable"), &TextEdit::cursor_set_block_mode); + ClassDB::bind_method(_MD("cursor_is_block_mode"), &TextEdit::cursor_is_block_mode); + + ClassDB::bind_method(_MD("set_readonly","enable"),&TextEdit::set_readonly); + ClassDB::bind_method(_MD("set_wrap","enable"),&TextEdit::set_wrap); + ClassDB::bind_method(_MD("set_max_chars","amount"),&TextEdit::set_max_chars); + + ClassDB::bind_method(_MD("cut"),&TextEdit::cut); + ClassDB::bind_method(_MD("copy"),&TextEdit::copy); + ClassDB::bind_method(_MD("paste"),&TextEdit::paste); + ClassDB::bind_method(_MD("select_all"),&TextEdit::select_all); + ClassDB::bind_method(_MD("select","from_line","from_column","to_line","to_column"),&TextEdit::select); + + ClassDB::bind_method(_MD("is_selection_active"),&TextEdit::is_selection_active); + ClassDB::bind_method(_MD("get_selection_from_line"),&TextEdit::get_selection_from_line); + ClassDB::bind_method(_MD("get_selection_from_column"),&TextEdit::get_selection_from_column); + ClassDB::bind_method(_MD("get_selection_to_line"),&TextEdit::get_selection_to_line); + ClassDB::bind_method(_MD("get_selection_to_column"),&TextEdit::get_selection_to_column); + ClassDB::bind_method(_MD("get_selection_text"),&TextEdit::get_selection_text); + ClassDB::bind_method(_MD("get_word_under_cursor"),&TextEdit::get_word_under_cursor); + ClassDB::bind_method(_MD("search","flags","from_line","from_column","to_line","to_column"),&TextEdit::_search_bind); + + ClassDB::bind_method(_MD("undo"),&TextEdit::undo); + ClassDB::bind_method(_MD("redo"),&TextEdit::redo); + ClassDB::bind_method(_MD("clear_undo_history"),&TextEdit::clear_undo_history); + + ClassDB::bind_method(_MD("set_show_line_numbers", "enable"), &TextEdit::set_show_line_numbers); + ClassDB::bind_method(_MD("is_show_line_numbers_enabled"), &TextEdit::is_show_line_numbers_enabled); + + ClassDB::bind_method(_MD("set_highlight_all_occurrences", "enable"), &TextEdit::set_highlight_all_occurrences); + ClassDB::bind_method(_MD("is_highlight_all_occurrences_enabled"), &TextEdit::is_highlight_all_occurrences_enabled); + + ClassDB::bind_method(_MD("set_syntax_coloring","enable"),&TextEdit::set_syntax_coloring); + ClassDB::bind_method(_MD("is_syntax_coloring_enabled"),&TextEdit::is_syntax_coloring_enabled); + + + ClassDB::bind_method(_MD("add_keyword_color","keyword","color"),&TextEdit::add_keyword_color); + ClassDB::bind_method(_MD("add_color_region","begin_key","end_key","color","line_only"),&TextEdit::add_color_region,DEFVAL(false)); + ClassDB::bind_method(_MD("clear_colors"),&TextEdit::clear_colors); + ClassDB::bind_method(_MD("menu_option"),&TextEdit::menu_option); + ClassDB::bind_method(_MD("get_menu:PopupMenu"),&TextEdit::get_menu); + + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "syntax_highlighting"), _SCS("set_syntax_coloring"), _SCS("is_syntax_coloring_enabled")); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "show_line_numbers"), _SCS("set_show_line_numbers"), _SCS("is_show_line_numbers_enabled")); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "highlight_all_occurrences"), _SCS("set_highlight_all_occurrences"), _SCS("is_highlight_all_occurrences_enabled")); + + + ADD_GROUP("Caret","caret_"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "caret_block_mode"), _SCS("cursor_set_block_mode"), _SCS("cursor_is_block_mode")); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "caret_blink"), _SCS("cursor_set_blink_enabled"), _SCS("cursor_get_blink_enabled")); + ADD_PROPERTYNZ(PropertyInfo(Variant::REAL, "caret_blink_speed",PROPERTY_HINT_RANGE,"0.1,10,0.1"), _SCS("cursor_set_blink_speed"),_SCS("cursor_get_blink_speed") ); ADD_SIGNAL(MethodInfo("cursor_changed")); ADD_SIGNAL(MethodInfo("text_changed")); ADD_SIGNAL(MethodInfo("request_completion")); + ADD_SIGNAL(MethodInfo("breakpoint_toggled", PropertyInfo( Variant::INT, "row"))); + ADD_SIGNAL(MethodInfo("symbol_lookup", PropertyInfo(Variant::STRING,"symbol"),PropertyInfo( Variant::INT, "row"),PropertyInfo( Variant::INT, "column"))); BIND_CONSTANT( MENU_CUT ); BIND_CONSTANT( MENU_COPY ); @@ -4397,6 +4708,7 @@ void TextEdit::_bind_methods() { BIND_CONSTANT( MENU_MAX ); + GLOBAL_DEF("gui/timers/text_edit_idle_detect_sec",3); } TextEdit::TextEdit() { @@ -4420,8 +4732,8 @@ TextEdit::TextEdit() { tab_size=4; text.set_tab_size(tab_size); text.clear(); - // text.insert(1,"Mongolia.."); - // text.insert(2,"PAIS GENEROSO!!"); + //text.insert(1,"Mongolia.."); + //text.insert(2,"PAIS GENEROSO!!"); text.set_color_regions(&color_regions); h_scroll = memnew( HScrollBar ); @@ -4446,6 +4758,7 @@ TextEdit::TextEdit() { selection.active=false; syntax_coloring=false; + block_caret=false; caret_blink_enabled=false; caret_blink_timer = memnew(Timer); add_child(caret_blink_timer); @@ -4453,11 +4766,10 @@ TextEdit::TextEdit() { caret_blink_timer->connect("timeout", this,"_toggle_draw_caret"); cursor_set_blink_enabled(false); - custom_bg_color=Color(0,0,0,0); idle_detect = memnew( Timer ); add_child(idle_detect); idle_detect->set_one_shot(true); - idle_detect->set_wait_time(GLOBAL_DEF("display/text_edit_idle_detect_sec",3)); + idle_detect->set_wait_time(GLOBAL_GET("gui/timers/text_edit_idle_detect_sec")); idle_detect->connect("timeout", this,"_push_current_op"); click_select_held = memnew( Timer ); @@ -4497,14 +4809,23 @@ TextEdit::TextEdit() { completion_line_ofs=0; tooltip_obj=NULL; line_numbers=false; + line_numbers_zero_padded=false; + line_length_guideline=false; + line_length_guideline_col=80; draw_breakpoint_gutter=false; next_operation_is_complex=false; scroll_past_end_of_file_enabled=false; auto_brace_completion_enabled=false; brace_matching_enabled=false; + highlight_all_occurrences=false; auto_indent=false; insert_mode = false; + window_has_focus=true; + select_identifiers_enabled=false; + + raised_from_completion = false; + context_menu_enabled=true; menu = memnew( PopupMenu ); add_child(menu); menu->add_item(TTR("Cut"),MENU_CUT,KEY_MASK_CMD|KEY_X); @@ -4515,7 +4836,7 @@ TextEdit::TextEdit() { menu->add_item(TTR("Clear"),MENU_CLEAR); menu->add_separator(); menu->add_item(TTR("Undo"),MENU_UNDO,KEY_MASK_CMD|KEY_Z); - menu->connect("item_pressed",this,"menu_option"); + menu->connect("id_pressed",this,"menu_option"); } diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h index 24a72afd48..6113fd72c2 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-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 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 */ @@ -37,7 +37,7 @@ class TextEdit : public Control { - OBJ_TYPE( TextEdit, Control ); + GDCLASS( TextEdit, Control ); struct Cursor { int last_fit_x; @@ -74,7 +74,12 @@ class TextEdit : public Control { Ref<StyleBox> style_normal; Ref<StyleBox> style_focus; Ref<Font> font; + Color completion_background_color; + Color completion_selected_color; + Color completion_existing_color; + Color completion_font_color; Color caret_color; + Color caret_background_color; Color line_number_color; Color font_color; Color font_selected_color; @@ -90,6 +95,8 @@ class TextEdit : public Control { Color word_highlighted_color; Color search_result_color; Color search_result_border_color; + Color symbol_color; + Color background_color; int row_height; int line_spacing; @@ -182,9 +189,7 @@ class TextEdit : public Control { //syntax coloring - Color symbol_color; HashMap<String,Color> keywords; - Color custom_bg_color; Vector<ColorRegion> color_regions; @@ -217,6 +222,8 @@ class TextEdit : public Control { Timer *caret_blink_timer; bool caret_blink_enabled; bool draw_caret; + bool window_has_focus; + bool block_caret; bool setting_row; bool wrap; @@ -225,6 +232,9 @@ class TextEdit : public Control { bool text_changed_dirty; bool undo_enabled; bool line_numbers; + bool line_numbers_zero_padded; + bool line_length_guideline; + int line_length_guideline_col; bool draw_breakpoint_gutter; int breakpoint_gutter_width; @@ -235,6 +245,11 @@ class TextEdit : public Control { bool auto_indent; bool cut_copy_line; bool insert_mode; + bool select_identifiers_enabled; + + bool raised_from_completion; + + String hilighted_word; uint64_t last_dblclk; @@ -259,6 +274,8 @@ class TextEdit : public Control { int search_result_line; int search_result_col; + bool context_menu_enabled; + int get_visible_rows() const; int get_char_count(); @@ -277,8 +294,8 @@ class TextEdit : public Control { void _scroll_lines_up(); void _scroll_lines_down(); -// void mouse_motion(const Point& p_pos, const Point& p_rel, int p_button_mask); - Size2 get_minimum_size(); + //void mouse_motion(const Point& p_pos, const Point& p_rel, int p_button_mask); + Size2 get_minimum_size() const; int get_row_height() const; @@ -299,7 +316,7 @@ class TextEdit : public Control { int _get_column_pos_of_word(const String &p_key, const String &p_search, uint32_t p_search_flags, int p_from_column); - DVector<int> _search_bind(const String &p_key,uint32_t p_search_flags, int p_from_line,int p_from_column) const; + PoolVector<int> _search_bind(const String &p_key,uint32_t p_search_flags, int p_from_line,int p_from_column) const; PopupMenu *menu; @@ -309,8 +326,6 @@ class TextEdit : public Control { void _confirm_completion(); void _update_completion_candidates(); - void _get_mouse_pos(const Point2i& p_mouse, int &r_row, int &r_col) const; - protected: virtual String get_tooltip(const Point2& p_pos) const; @@ -318,7 +333,7 @@ protected: void _insert_text(int p_line, int p_column,const String& p_text,int *r_end_line=NULL,int *r_end_char=NULL); void _remove_text(int p_from_line, int p_from_column,int p_to_line,int p_to_column); void _insert_text_at_cursor(const String& p_text); - void _input_event(const InputEvent& p_input); + void _gui_input(const InputEvent& p_input); void _notification(int p_what); void _consume_pair_symbol(CharType ch); @@ -350,6 +365,8 @@ public: virtual CursorShape get_cursor_shape(const Point2& p_pos=Point2i()) const; + void _get_mouse_pos(const Point2i& p_mouse, int &r_row, int &r_col) const; + //void delete_char(); //void delete_line(); @@ -389,6 +406,8 @@ public: } void set_auto_indent(bool p_auto_indent); + void center_viewport_to_cursor(); + void cursor_set_column(int p_col, bool p_adjust_viewport=true); void cursor_set_line(int p_row, bool p_adjust_viewport=true); @@ -401,6 +420,9 @@ public: float cursor_get_blink_speed() const; void cursor_set_blink_speed(const float p_speed); + void cursor_set_block_mode(const bool p_enable); + bool cursor_is_block_mode() const; + void set_readonly(bool p_readonly); void set_max_chars(int p_max_chars); @@ -423,14 +445,16 @@ public: void set_current_search_result(int line, int col); void set_highlight_all_occurrences(const bool p_enabled); + bool is_highlight_all_occurrences_enabled() const; bool is_selection_active() const; int get_selection_from_line() const; - int get_selection_from_column() const; + int get_selection_from_column() const; int get_selection_to_line() const; int get_selection_to_column() const; String get_selection_text() const; String get_word_under_cursor() const; + String get_word_at_pos(const Vector2& p_pos) const; bool search(const String &p_key,uint32_t p_search_flags, int p_from_line, int p_from_column,int &r_line,int &r_column) const; @@ -447,8 +471,6 @@ public: void add_keyword_color(const String& p_keyword,const Color& p_color); void add_color_region(const String& p_begin_key=String(),const String& p_end_key=String(),const Color &p_color=Color(),bool p_line_only=false); - void set_symbol_color(const Color& p_color); - void set_custom_bg_color(const Color& p_color); void clear_colors(); int get_v_scroll() const; @@ -464,6 +486,12 @@ public: void menu_option(int p_option); void set_show_line_numbers(bool p_show); + bool is_show_line_numbers_enabled() const; + + void set_line_numbers_zero_padded(bool p_zero_padded); + + void set_show_line_length_guideline(bool p_show); + void set_line_length_guideline_column(int p_column); void set_draw_breakpoint_gutter(bool p_draw); bool is_drawing_breakpoint_gutter() const; @@ -478,11 +506,16 @@ public: void set_code_hint(const String& p_hint); void query_code_comple(); + void set_select_identifiers_on_hover(bool p_enable); + bool is_selecting_identifiers_on_hover_enabled() const; + + void set_context_menu_enabled(bool p_enable); PopupMenu *get_menu() const; String get_text_for_completion(); + String get_text_for_lookup_completion(); - virtual bool is_text_field() const; + virtual bool is_text_field() const; TextEdit(); ~TextEdit(); }; diff --git a/scene/gui/texture_button.cpp b/scene/gui/texture_button.cpp index c885b2d73e..03e37e9d9f 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-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 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 */ @@ -76,10 +76,7 @@ void TextureButton::_notification(int p_what) { switch( p_what ) { case NOTIFICATION_DRAW: { - RID canvas_item = get_canvas_item(); DrawMode draw_mode = get_draw_mode(); -// if (normal.is_null()) -// break; Ref<Texture> texdraw; @@ -123,13 +120,13 @@ void TextureButton::_notification(int p_what) { if (texdraw.is_valid()) { Rect2 drect(Point2(),texdraw->get_size()*scale); - draw_texture_rect(texdraw,drect,false,modulate); + draw_texture_rect(texdraw,drect,false); } if (has_focus() && focused.is_valid()) { Rect2 drect(Point2(),focused->get_size()*scale); - draw_texture_rect(focused,drect,false,modulate); + draw_texture_rect(focused,drect,false); }; @@ -139,32 +136,30 @@ void TextureButton::_notification(int p_what) { void TextureButton::_bind_methods() { - ObjectTypeDB::bind_method(_MD("set_normal_texture","texture:Texture"),&TextureButton::set_normal_texture); - ObjectTypeDB::bind_method(_MD("set_pressed_texture","texture:Texture"),&TextureButton::set_pressed_texture); - ObjectTypeDB::bind_method(_MD("set_hover_texture","texture:Texture"),&TextureButton::set_hover_texture); - ObjectTypeDB::bind_method(_MD("set_disabled_texture","texture:Texture"),&TextureButton::set_disabled_texture); - ObjectTypeDB::bind_method(_MD("set_focused_texture","texture:Texture"),&TextureButton::set_focused_texture); - ObjectTypeDB::bind_method(_MD("set_click_mask","mask:BitMap"),&TextureButton::set_click_mask); - ObjectTypeDB::bind_method(_MD("set_texture_scale","scale"),&TextureButton::set_texture_scale); - ObjectTypeDB::bind_method(_MD("set_modulate","color"),&TextureButton::set_modulate); - - ObjectTypeDB::bind_method(_MD("get_normal_texture:Texture"),&TextureButton::get_normal_texture); - ObjectTypeDB::bind_method(_MD("get_pressed_texture:Texture"),&TextureButton::get_pressed_texture); - ObjectTypeDB::bind_method(_MD("get_hover_texture:Texture"),&TextureButton::get_hover_texture); - ObjectTypeDB::bind_method(_MD("get_disabled_texture:Texture"),&TextureButton::get_disabled_texture); - ObjectTypeDB::bind_method(_MD("get_focused_texture:Texture"),&TextureButton::get_focused_texture); - ObjectTypeDB::bind_method(_MD("get_click_mask:BitMap"),&TextureButton::get_click_mask); - ObjectTypeDB::bind_method(_MD("get_texture_scale"),&TextureButton::get_texture_scale); - ObjectTypeDB::bind_method(_MD("get_modulate"),&TextureButton::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_texture_scale"), _SCS("get_texture_scale")); - ADD_PROPERTYNO(PropertyInfo(Variant::COLOR,"params/modulate"), _SCS("set_modulate"), _SCS("get_modulate")); + ClassDB::bind_method(_MD("set_normal_texture","texture:Texture"),&TextureButton::set_normal_texture); + ClassDB::bind_method(_MD("set_pressed_texture","texture:Texture"),&TextureButton::set_pressed_texture); + ClassDB::bind_method(_MD("set_hover_texture","texture:Texture"),&TextureButton::set_hover_texture); + ClassDB::bind_method(_MD("set_disabled_texture","texture:Texture"),&TextureButton::set_disabled_texture); + ClassDB::bind_method(_MD("set_focused_texture","texture:Texture"),&TextureButton::set_focused_texture); + ClassDB::bind_method(_MD("set_click_mask","mask:BitMap"),&TextureButton::set_click_mask); + ClassDB::bind_method(_MD("set_texture_scale","scale"),&TextureButton::set_texture_scale); + + ClassDB::bind_method(_MD("get_normal_texture:Texture"),&TextureButton::get_normal_texture); + ClassDB::bind_method(_MD("get_pressed_texture:Texture"),&TextureButton::get_pressed_texture); + ClassDB::bind_method(_MD("get_hover_texture:Texture"),&TextureButton::get_hover_texture); + ClassDB::bind_method(_MD("get_disabled_texture:Texture"),&TextureButton::get_disabled_texture); + ClassDB::bind_method(_MD("get_focused_texture:Texture"),&TextureButton::get_focused_texture); + ClassDB::bind_method(_MD("get_click_mask:BitMap"),&TextureButton::get_click_mask); + ClassDB::bind_method(_MD("get_texture_scale"),&TextureButton::get_texture_scale); + + ADD_GROUP("Textures","texture_"); + ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT,"texture_normal",PROPERTY_HINT_RESOURCE_TYPE,"Texture"), _SCS("set_normal_texture"), _SCS("get_normal_texture")); + ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT,"texture_pressed",PROPERTY_HINT_RESOURCE_TYPE,"Texture"), _SCS("set_pressed_texture"), _SCS("get_pressed_texture")); + ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT,"texture_hover",PROPERTY_HINT_RESOURCE_TYPE,"Texture"), _SCS("set_hover_texture"), _SCS("get_hover_texture")); + ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT,"texture_disabled",PROPERTY_HINT_RESOURCE_TYPE,"Texture"), _SCS("set_disabled_texture"), _SCS("get_disabled_texture")); + ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT,"texture_focused",PROPERTY_HINT_RESOURCE_TYPE,"Texture"), _SCS("set_focused_texture"), _SCS("get_focused_texture")); + ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT,"texture_click_mask",PROPERTY_HINT_RESOURCE_TYPE,"BitMap"), _SCS("set_click_mask"), _SCS("get_click_mask")) ; + ADD_PROPERTYNO(PropertyInfo(Variant::VECTOR2,"texture_scale",PROPERTY_HINT_RANGE,"0.01,1024,0.01"), _SCS("set_texture_scale"), _SCS("get_texture_scale")); } @@ -244,17 +239,7 @@ Size2 TextureButton::get_texture_scale() const{ return scale; } -void TextureButton::set_modulate(const Color& p_modulate) { - modulate=p_modulate; - update(); -} - -Color TextureButton::get_modulate() const { - return modulate; -} - - TextureButton::TextureButton() { scale=Size2(1.0, 1.0); - modulate=Color(1,1,1); + } diff --git a/scene/gui/texture_button.h b/scene/gui/texture_button.h index 0556df8061..ef4d4d5b5b 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-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 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 */ @@ -33,7 +33,7 @@ #include "scene/resources/bit_mask.h" class TextureButton : public BaseButton { - OBJ_TYPE( TextureButton, BaseButton ); + GDCLASS( TextureButton, BaseButton ); Ref<Texture> normal; Ref<Texture> pressed; @@ -42,8 +42,6 @@ class TextureButton : public BaseButton { Ref<Texture> focused; Ref<BitMap> click_mask; Size2 scale; - Color modulate; - protected: @@ -71,9 +69,6 @@ public: void set_texture_scale(Size2 p_scale); Size2 get_texture_scale() const; - void set_modulate(const Color& p_modulate); - Color get_modulate() const; - TextureButton(); }; diff --git a/scene/gui/texture_progress.cpp b/scene/gui/texture_progress.cpp index 923a35031c..f6a33b5643 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-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 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 */ @@ -135,24 +135,24 @@ void TextureProgress::_notification(int p_what){ Size2 s = progress->get_size(); switch (mode) { case FILL_LEFT_TO_RIGHT: { - Rect2 region=Rect2(Point2(),Size2(s.x*get_unit_value(),s.y)); + Rect2 region=Rect2(Point2(),Size2(s.x*get_as_ratio(),s.y)); draw_texture_rect_region(progress,region,region); } break; case FILL_RIGHT_TO_LEFT: { - Rect2 region=Rect2(Point2(s.x-s.x*get_unit_value(),0),Size2(s.x*get_unit_value(),s.y)); + Rect2 region=Rect2(Point2(s.x-s.x*get_as_ratio(),0),Size2(s.x*get_as_ratio(),s.y)); draw_texture_rect_region(progress,region,region); } break; case FILL_TOP_TO_BOTTOM: { - Rect2 region=Rect2(Point2(),Size2(s.x,s.y*get_unit_value())); + Rect2 region=Rect2(Point2(),Size2(s.x,s.y*get_as_ratio())); draw_texture_rect_region(progress,region,region); } break; case FILL_BOTTOM_TO_TOP: { - Rect2 region=Rect2(Point2(0,s.y-s.y*get_unit_value()),Size2(s.x,s.y*get_unit_value())); + Rect2 region=Rect2(Point2(0,s.y-s.y*get_as_ratio()),Size2(s.x,s.y*get_as_ratio())); draw_texture_rect_region(progress,region,region); } break; case FILL_CLOCKWISE: case FILL_COUNTER_CLOCKWISE: { - float val=get_unit_value()*rad_max_degrees/360; + float val=get_as_ratio()*rad_max_degrees/360; if (val==1) { Rect2 region=Rect2(Point2(),s); draw_texture_rect_region(progress,region,region); @@ -192,7 +192,7 @@ void TextureProgress::_notification(int p_what){ } } break; default: - draw_texture_rect_region(progress,Rect2(Point2(),Size2(s.x*get_unit_value(),s.y)),Rect2(Point2(),Size2(s.x*get_unit_value(),s.y))); + draw_texture_rect_region(progress,Rect2(Point2(),Size2(s.x*get_as_ratio(),s.y)),Rect2(Point2(),Size2(s.x*get_as_ratio(),s.y))); } @@ -255,34 +255,36 @@ Point2 TextureProgress::get_radial_center_offset() void TextureProgress::_bind_methods() { - ObjectTypeDB::bind_method(_MD("set_under_texture","tex"),&TextureProgress::set_under_texture); - ObjectTypeDB::bind_method(_MD("get_under_texture"),&TextureProgress::get_under_texture); + ClassDB::bind_method(_MD("set_under_texture","tex"),&TextureProgress::set_under_texture); + ClassDB::bind_method(_MD("get_under_texture"),&TextureProgress::get_under_texture); - ObjectTypeDB::bind_method(_MD("set_progress_texture","tex"),&TextureProgress::set_progress_texture); - ObjectTypeDB::bind_method(_MD("get_progress_texture"),&TextureProgress::get_progress_texture); + ClassDB::bind_method(_MD("set_progress_texture","tex"),&TextureProgress::set_progress_texture); + ClassDB::bind_method(_MD("get_progress_texture"),&TextureProgress::get_progress_texture); - ObjectTypeDB::bind_method(_MD("set_over_texture","tex"),&TextureProgress::set_over_texture); - ObjectTypeDB::bind_method(_MD("get_over_texture"),&TextureProgress::get_over_texture); + ClassDB::bind_method(_MD("set_over_texture","tex"),&TextureProgress::set_over_texture); + ClassDB::bind_method(_MD("get_over_texture"),&TextureProgress::get_over_texture); - ObjectTypeDB::bind_method(_MD("set_fill_mode","mode"),&TextureProgress::set_fill_mode); - ObjectTypeDB::bind_method(_MD("get_fill_mode"), &TextureProgress::get_fill_mode); + ClassDB::bind_method(_MD("set_fill_mode","mode"),&TextureProgress::set_fill_mode); + ClassDB::bind_method(_MD("get_fill_mode"), &TextureProgress::get_fill_mode); - ObjectTypeDB::bind_method(_MD("set_radial_initial_angle","mode"),&TextureProgress::set_radial_initial_angle); - ObjectTypeDB::bind_method(_MD("get_radial_initial_angle"), &TextureProgress::get_radial_initial_angle); + ClassDB::bind_method(_MD("set_radial_initial_angle","mode"),&TextureProgress::set_radial_initial_angle); + ClassDB::bind_method(_MD("get_radial_initial_angle"), &TextureProgress::get_radial_initial_angle); - ObjectTypeDB::bind_method(_MD("set_radial_center_offset","mode"),&TextureProgress::set_radial_center_offset); - ObjectTypeDB::bind_method(_MD("get_radial_center_offset"), &TextureProgress::get_radial_center_offset); + ClassDB::bind_method(_MD("set_radial_center_offset","mode"),&TextureProgress::set_radial_center_offset); + ClassDB::bind_method(_MD("get_radial_center_offset"), &TextureProgress::get_radial_center_offset); - ObjectTypeDB::bind_method(_MD("set_fill_degrees","mode"),&TextureProgress::set_fill_degrees); - ObjectTypeDB::bind_method(_MD("get_fill_degrees"), &TextureProgress::get_fill_degrees); + ClassDB::bind_method(_MD("set_fill_degrees","mode"),&TextureProgress::set_fill_degrees); + ClassDB::bind_method(_MD("get_fill_degrees"), &TextureProgress::get_fill_degrees); - ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"texture/under",PROPERTY_HINT_RESOURCE_TYPE,"Texture"),_SCS("set_under_texture"),_SCS("get_under_texture")); - ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"texture/over",PROPERTY_HINT_RESOURCE_TYPE,"Texture"),_SCS("set_over_texture"),_SCS("get_over_texture")); - ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"texture/progress",PROPERTY_HINT_RESOURCE_TYPE,"Texture"),_SCS("set_progress_texture"),_SCS("get_progress_texture")); - ADD_PROPERTYNZ( PropertyInfo(Variant::INT,"mode",PROPERTY_HINT_ENUM,"Left to Right,Right to Left,Top to Bottom,Bottom to Top,Clockwise,Counter Clockwise"),_SCS("set_fill_mode"),_SCS("get_fill_mode")); - ADD_PROPERTYNZ( PropertyInfo(Variant::REAL,"radial_fill/initial_angle",PROPERTY_HINT_RANGE,"0.0,360.0,0.1,slider"),_SCS("set_radial_initial_angle"),_SCS("get_radial_initial_angle")); - ADD_PROPERTYNZ( PropertyInfo(Variant::REAL,"radial_fill/fill_degrees",PROPERTY_HINT_RANGE,"0.0,360.0,0.1,slider"),_SCS("set_fill_degrees"),_SCS("get_fill_degrees")); - ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"radial_fill/center_offset"),_SCS("set_radial_center_offset"),_SCS("get_radial_center_offset")); + ADD_GROUP("Textures","texture_"); + ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"texture_under",PROPERTY_HINT_RESOURCE_TYPE,"Texture"),_SCS("set_under_texture"),_SCS("get_under_texture")); + ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"texture_over",PROPERTY_HINT_RESOURCE_TYPE,"Texture"),_SCS("set_over_texture"),_SCS("get_over_texture")); + ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"texture_progress",PROPERTY_HINT_RESOURCE_TYPE,"Texture"),_SCS("set_progress_texture"),_SCS("get_progress_texture")); + ADD_PROPERTYNZ( PropertyInfo(Variant::INT,"fill_mode",PROPERTY_HINT_ENUM,"Left to Right,Right to Left,Top to Bottom,Bottom to Top,Clockwise,Counter Clockwise"),_SCS("set_fill_mode"),_SCS("get_fill_mode")); + ADD_GROUP("Radial Fill","radial_"); + ADD_PROPERTYNZ( PropertyInfo(Variant::REAL,"radial_initial_angle",PROPERTY_HINT_RANGE,"0.0,360.0,0.1,slider"),_SCS("set_radial_initial_angle"),_SCS("get_radial_initial_angle")); + ADD_PROPERTYNZ( PropertyInfo(Variant::REAL,"radial_fill_degrees",PROPERTY_HINT_RANGE,"0.0,360.0,0.1,slider"),_SCS("set_fill_degrees"),_SCS("get_fill_degrees")); + ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"radial_center_offset"),_SCS("set_radial_center_offset"),_SCS("get_radial_center_offset")); BIND_CONSTANT( FILL_LEFT_TO_RIGHT ); BIND_CONSTANT( FILL_RIGHT_TO_LEFT ); @@ -297,6 +299,7 @@ void TextureProgress::_bind_methods() { TextureProgress::TextureProgress() { mode=FILL_LEFT_TO_RIGHT; + rad_init_angle=0; rad_center_off=Point2(); rad_max_degrees=360; } diff --git a/scene/gui/texture_progress.h b/scene/gui/texture_progress.h index a4bbd71e94..02794354ef 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-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 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 */ @@ -33,7 +33,7 @@ class TextureProgress : public Range { - OBJ_TYPE( TextureProgress, Range ); + GDCLASS( TextureProgress, Range ); Ref<Texture> under; Ref<Texture> progress; diff --git a/scene/gui/texture_frame.cpp b/scene/gui/texture_rect.cpp index 2fe8735fda..cbb077ef5d 100644 --- a/scene/gui/texture_frame.cpp +++ b/scene/gui/texture_rect.cpp @@ -1,11 +1,11 @@ /*************************************************************************/ -/* texture_frame.cpp */ +/* texture_rect.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 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,10 +26,10 @@ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "texture_frame.h" +#include "texture_rect.h" #include "servers/visual_server.h" -void TextureFrame::_notification(int p_what) { +void TextureRect::_notification(int p_what) { if (p_what==NOTIFICATION_DRAW) { @@ -37,142 +37,135 @@ void TextureFrame::_notification(int p_what) { return; - - RID ci = get_canvas_item(); - switch(stretch_mode) { case STRETCH_SCALE_ON_EXPAND: { Size2 s=expand?get_size():texture->get_size(); - draw_texture_rect(texture,Rect2(Point2(),s),false,modulate); + draw_texture_rect(texture,Rect2(Point2(),s),false); } break; case STRETCH_SCALE: { - draw_texture_rect(texture,Rect2(Point2(),get_size()),false,modulate); + draw_texture_rect(texture,Rect2(Point2(),get_size()),false); } break; case STRETCH_TILE: { - draw_texture_rect(texture,Rect2(Point2(),get_size()),true,modulate); + draw_texture_rect(texture,Rect2(Point2(),get_size()),true); } break; case STRETCH_KEEP: { - draw_texture_rect(texture,Rect2(Point2(),texture->get_size()),false,modulate); + draw_texture_rect(texture,Rect2(Point2(),texture->get_size()),false); } break; case STRETCH_KEEP_CENTERED: { Vector2 ofs = (get_size() - texture->get_size())/2; - draw_texture_rect(texture,Rect2(ofs,texture->get_size()),false,modulate); + draw_texture_rect(texture,Rect2(ofs,texture->get_size()),false); + } break; + case STRETCH_KEEP_ASPECT_CENTERED: + case STRETCH_KEEP_ASPECT: { + + Size2 size=get_size(); + int tex_width = texture->get_width() * size.height / texture ->get_height(); + int tex_height = size.height; + + if (tex_width>size.width) { + tex_width=size.width; + tex_height=texture->get_height() * tex_width / texture->get_width(); + } + + int ofs_x = 0; + int ofs_y = 0; + + if (stretch_mode==STRETCH_KEEP_ASPECT_CENTERED) { + ofs_x+=(size.width - tex_width)/2; + ofs_y+=(size.height - tex_height)/2; + } + + draw_texture_rect(texture,Rect2(ofs_x,ofs_y,tex_width,tex_height)); } break; - } + } -/* - Vector<Point2> points; - points.resize(4); - points[0]=Point2(0,0); - points[1]=Point2(s.x,0); - points[2]=Point2(s.x,s.y); - points[3]=Point2(0,s.y); - Vector<Point2> uvs; - uvs.resize(4); - uvs[0]=Point2(0,0); - uvs[1]=Point2(1,0); - uvs[2]=Point2(1,1); - uvs[3]=Point2(0,1); - - VisualServer::get_singleton()->canvas_item_add_primitive(ci,points,Vector<Color>(),uvs,texture->get_rid()); -*/ } } -Size2 TextureFrame::get_minimum_size() const { +Size2 TextureRect::get_minimum_size() const { if (!expand && !texture.is_null()) return texture->get_size(); else return Size2(); } -void TextureFrame::_bind_methods() { +void TextureRect::_bind_methods() { - ObjectTypeDB::bind_method(_MD("set_texture","texture"), & TextureFrame::set_texture ); - ObjectTypeDB::bind_method(_MD("get_texture"), & TextureFrame::get_texture ); - ObjectTypeDB::bind_method(_MD("set_modulate","modulate"), & TextureFrame::set_modulate ); - ObjectTypeDB::bind_method(_MD("get_modulate"), & TextureFrame::get_modulate ); - ObjectTypeDB::bind_method(_MD("set_expand","enable"), & TextureFrame::set_expand ); - ObjectTypeDB::bind_method(_MD("has_expand"), & TextureFrame::has_expand ); - ObjectTypeDB::bind_method(_MD("set_stretch_mode","stretch_mode"), & TextureFrame::set_stretch_mode ); - ObjectTypeDB::bind_method(_MD("get_stretch_mode"), & TextureFrame::get_stretch_mode ); + ClassDB::bind_method(_MD("set_texture","texture"), & TextureRect::set_texture ); + ClassDB::bind_method(_MD("get_texture"), & TextureRect::get_texture ); + ClassDB::bind_method(_MD("set_expand","enable"), & TextureRect::set_expand ); + ClassDB::bind_method(_MD("has_expand"), & TextureRect::has_expand ); + ClassDB::bind_method(_MD("set_stretch_mode","stretch_mode"), & TextureRect::set_stretch_mode ); + ClassDB::bind_method(_MD("get_stretch_mode"), & TextureRect::get_stretch_mode ); 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") ); - ADD_PROPERTYNO( PropertyInfo( Variant::INT, "stretch_mode",PROPERTY_HINT_ENUM,"Scale On Expand (Compat),Scale,Tile,Keep,Keep Centered"), _SCS("set_stretch_mode"),_SCS("get_stretch_mode") ); + ADD_PROPERTYNO( PropertyInfo( Variant::INT, "stretch_mode",PROPERTY_HINT_ENUM,"Scale On Expand (Compat),Scale,Tile,Keep,Keep Centered,Keep Aspect,Keep Aspect Centered"), _SCS("set_stretch_mode"),_SCS("get_stretch_mode") ); BIND_CONSTANT( STRETCH_SCALE_ON_EXPAND ); BIND_CONSTANT( STRETCH_SCALE ); BIND_CONSTANT( STRETCH_TILE ); BIND_CONSTANT( STRETCH_KEEP ); BIND_CONSTANT( STRETCH_KEEP_CENTERED ); + BIND_CONSTANT( STRETCH_KEEP_ASPECT ); + BIND_CONSTANT( STRETCH_KEEP_ASPECT_CENTERED ); + } -void TextureFrame::set_texture(const Ref<Texture>& p_tex) { +void TextureRect::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(); } -Ref<Texture> TextureFrame::get_texture() const { +Ref<Texture> TextureRect::get_texture() const { return texture; } -void TextureFrame::set_modulate(const Color& p_tex) { - - modulate=p_tex; - update(); -} - -Color TextureFrame::get_modulate() const{ - - return modulate; -} - -void TextureFrame::set_expand(bool p_expand) { +void TextureRect::set_expand(bool p_expand) { expand=p_expand; update(); minimum_size_changed(); } -bool TextureFrame::has_expand() const { +bool TextureRect::has_expand() const { return expand; } -void TextureFrame::set_stretch_mode(StretchMode p_mode) { +void TextureRect::set_stretch_mode(StretchMode p_mode) { stretch_mode=p_mode; update(); } -TextureFrame::StretchMode TextureFrame::get_stretch_mode() const { +TextureRect::StretchMode TextureRect::get_stretch_mode() const { return stretch_mode; } -TextureFrame::TextureFrame() { +TextureRect::TextureRect() { expand=false; - modulate=Color(1,1,1,1); - set_ignore_mouse(true); + set_mouse_filter(MOUSE_FILTER_IGNORE); stretch_mode=STRETCH_SCALE_ON_EXPAND; } -TextureFrame::~TextureFrame() +TextureRect::~TextureRect() { } diff --git a/scene/gui/texture_frame.h b/scene/gui/texture_rect.h index a4acf588ea..e95d742759 100644 --- a/scene/gui/texture_frame.h +++ b/scene/gui/texture_rect.h @@ -1,11 +1,11 @@ /*************************************************************************/ -/* texture_frame.h */ +/* texture_rect.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 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 */ @@ -33,9 +33,9 @@ /** @author Juan Linietsky <reduzio@gmail.com> */ -class TextureFrame : public Control { +class TextureRect : public Control { - OBJ_TYPE(TextureFrame,Control); + GDCLASS(TextureRect,Control); public: enum StretchMode { STRETCH_SCALE_ON_EXPAND, //default, for backwards compatibility @@ -43,10 +43,12 @@ public: STRETCH_TILE, STRETCH_KEEP, STRETCH_KEEP_CENTERED, + STRETCH_KEEP_ASPECT, + STRETCH_KEEP_ASPECT_CENTERED, + }; private: bool expand; - Color modulate; Ref<Texture> texture; StretchMode stretch_mode; protected: @@ -60,8 +62,6 @@ public: void set_texture(const Ref<Texture>& p_tex); Ref<Texture> get_texture() const; - void set_modulate(const Color& p_tex); - Color get_modulate() const; void set_expand(bool p_expand); bool has_expand() const; @@ -69,10 +69,10 @@ public: void set_stretch_mode(StretchMode p_mode); StretchMode get_stretch_mode() const; - TextureFrame(); - ~TextureFrame(); + TextureRect(); + ~TextureRect(); }; -VARIANT_ENUM_CAST( TextureFrame::StretchMode ); +VARIANT_ENUM_CAST( TextureRect::StretchMode ); #endif // TEXTURE_FRAME_H diff --git a/scene/gui/tool_button.cpp b/scene/gui/tool_button.cpp index fd27800384..817b506f10 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-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 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 f48d7d413c..ddeb34273b 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-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 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 */ @@ -32,7 +32,7 @@ #include "scene/gui/button.h" class ToolButton : public Button { - OBJ_TYPE(ToolButton,Button); + GDCLASS(ToolButton,Button); public: ToolButton(); }; diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp index 2c39aea08c..58c829690f 100644 --- a/scene/gui/tree.cpp +++ b/scene/gui/tree.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 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 */ @@ -32,6 +32,7 @@ #include "os/keyboard.h" #include "globals.h" #include "os/input.h" +#include "scene/main/viewport.h" @@ -171,6 +172,21 @@ String TreeItem::get_text(int p_column) const { } +void TreeItem::set_suffix(int p_column,String p_suffix) { + + ERR_FAIL_INDEX( p_column, cells.size() ); + cells[p_column].suffix=p_suffix; + + _changed_notify(p_column); + +} + +String TreeItem::get_suffix(int p_column) const { + + ERR_FAIL_INDEX_V( p_column, cells.size(), "" ); + return cells[p_column].suffix; + +} void TreeItem::set_icon(int p_column,const Ref<Texture>& p_icon) { @@ -553,6 +569,15 @@ void TreeItem::set_button(int p_column,int p_idx,const Ref<Texture>& p_button){ } +void TreeItem::set_button_color(int p_column,int p_idx,const Color& p_color) { + + ERR_FAIL_INDEX( p_column, cells.size() ); + ERR_FAIL_INDEX( p_idx, cells[p_column].buttons.size() ); + cells[p_column].buttons[p_idx].color=p_color; + _changed_notify(p_column); + +} + void TreeItem::set_editable(int p_column,bool p_editable) { ERR_FAIL_INDEX( p_column, cells.size() ); @@ -632,75 +657,76 @@ Color TreeItem::get_custom_bg_color(int p_column) const { void TreeItem::_bind_methods() { - ObjectTypeDB::bind_method(_MD("set_cell_mode","column","mode"),&TreeItem::set_cell_mode); - ObjectTypeDB::bind_method(_MD("get_cell_mode","column"),&TreeItem::get_cell_mode); + ClassDB::bind_method(_MD("set_cell_mode","column","mode"),&TreeItem::set_cell_mode); + ClassDB::bind_method(_MD("get_cell_mode","column"),&TreeItem::get_cell_mode); - ObjectTypeDB::bind_method(_MD("set_checked","column","checked"),&TreeItem::set_checked); - ObjectTypeDB::bind_method(_MD("is_checked","column"),&TreeItem::is_checked); + ClassDB::bind_method(_MD("set_checked","column","checked"),&TreeItem::set_checked); + ClassDB::bind_method(_MD("is_checked","column"),&TreeItem::is_checked); - ObjectTypeDB::bind_method(_MD("set_text","column","text"),&TreeItem::set_text); - ObjectTypeDB::bind_method(_MD("get_text","column"),&TreeItem::get_text); + ClassDB::bind_method(_MD("set_text","column","text"),&TreeItem::set_text); + ClassDB::bind_method(_MD("get_text","column"),&TreeItem::get_text); - ObjectTypeDB::bind_method(_MD("set_icon","column","texture:Texture"),&TreeItem::set_icon); - ObjectTypeDB::bind_method(_MD("get_icon:Texture","column"),&TreeItem::get_icon); + ClassDB::bind_method(_MD("set_icon","column","texture:Texture"),&TreeItem::set_icon); + ClassDB::bind_method(_MD("get_icon:Texture","column"),&TreeItem::get_icon); - ObjectTypeDB::bind_method(_MD("set_icon_region","column","region"),&TreeItem::set_icon_region); - ObjectTypeDB::bind_method(_MD("get_icon_region","column"),&TreeItem::get_icon_region); + ClassDB::bind_method(_MD("set_icon_region","column","region"),&TreeItem::set_icon_region); + ClassDB::bind_method(_MD("get_icon_region","column"),&TreeItem::get_icon_region); - ObjectTypeDB::bind_method(_MD("set_icon_max_width","column","width"),&TreeItem::set_icon_max_width); - ObjectTypeDB::bind_method(_MD("get_icon_max_width","column"),&TreeItem::get_icon_max_width); + ClassDB::bind_method(_MD("set_icon_max_width","column","width"),&TreeItem::set_icon_max_width); + ClassDB::bind_method(_MD("get_icon_max_width","column"),&TreeItem::get_icon_max_width); - ObjectTypeDB::bind_method(_MD("set_range","column","value"),&TreeItem::set_range); - ObjectTypeDB::bind_method(_MD("get_range","column"),&TreeItem::get_range); - ObjectTypeDB::bind_method(_MD("set_range_config","column","min","max","step","expr"),&TreeItem::set_range_config,DEFVAL(false)); - ObjectTypeDB::bind_method(_MD("get_range_config","column"),&TreeItem::_get_range_config); + ClassDB::bind_method(_MD("set_range","column","value"),&TreeItem::set_range); + ClassDB::bind_method(_MD("get_range","column"),&TreeItem::get_range); + ClassDB::bind_method(_MD("set_range_config","column","min","max","step","expr"),&TreeItem::set_range_config,DEFVAL(false)); + ClassDB::bind_method(_MD("get_range_config","column"),&TreeItem::_get_range_config); - ObjectTypeDB::bind_method(_MD("set_metadata","column","meta"),&TreeItem::set_metadata); - ObjectTypeDB::bind_method(_MD("get_metadata","column"),&TreeItem::get_metadata); + ClassDB::bind_method(_MD("set_metadata","column","meta"),&TreeItem::set_metadata); + ClassDB::bind_method(_MD("get_metadata","column"),&TreeItem::get_metadata); - ObjectTypeDB::bind_method(_MD("set_custom_draw","column","object","callback"),&TreeItem::set_custom_draw); + ClassDB::bind_method(_MD("set_custom_draw","column","object","callback"),&TreeItem::set_custom_draw); - ObjectTypeDB::bind_method(_MD("set_collapsed","enable"),&TreeItem::set_collapsed); - ObjectTypeDB::bind_method(_MD("is_collapsed"),&TreeItem::is_collapsed); + ClassDB::bind_method(_MD("set_collapsed","enable"),&TreeItem::set_collapsed); + ClassDB::bind_method(_MD("is_collapsed"),&TreeItem::is_collapsed); - ObjectTypeDB::bind_method(_MD("get_next:TreeItem"),&TreeItem::get_next); - ObjectTypeDB::bind_method(_MD("get_prev:TreeItem"),&TreeItem::get_prev); - ObjectTypeDB::bind_method(_MD("get_parent:TreeItem"),&TreeItem::get_parent); - ObjectTypeDB::bind_method(_MD("get_children:TreeItem"),&TreeItem::get_children); + ClassDB::bind_method(_MD("get_next:TreeItem"),&TreeItem::get_next); + ClassDB::bind_method(_MD("get_prev:TreeItem"),&TreeItem::get_prev); + ClassDB::bind_method(_MD("get_parent:TreeItem"),&TreeItem::get_parent); + ClassDB::bind_method(_MD("get_children:TreeItem"),&TreeItem::get_children); - ObjectTypeDB::bind_method(_MD("get_next_visible:TreeItem"),&TreeItem::get_next_visible); - ObjectTypeDB::bind_method(_MD("get_prev_visible:TreeItem"),&TreeItem::get_prev_visible); + ClassDB::bind_method(_MD("get_next_visible:TreeItem"),&TreeItem::get_next_visible); + ClassDB::bind_method(_MD("get_prev_visible:TreeItem"),&TreeItem::get_prev_visible); - ObjectTypeDB::bind_method(_MD("remove_child:TreeItem","child"),&TreeItem::_remove_child); + ClassDB::bind_method(_MD("remove_child:TreeItem","child"),&TreeItem::_remove_child); - ObjectTypeDB::bind_method(_MD("set_selectable","column","selectable"),&TreeItem::set_selectable); - ObjectTypeDB::bind_method(_MD("is_selectable","column"),&TreeItem::is_selectable); + ClassDB::bind_method(_MD("set_selectable","column","selectable"),&TreeItem::set_selectable); + ClassDB::bind_method(_MD("is_selectable","column"),&TreeItem::is_selectable); - ObjectTypeDB::bind_method(_MD("is_selected","column"),&TreeItem::is_selected); - ObjectTypeDB::bind_method(_MD("select","column"),&TreeItem::select); - ObjectTypeDB::bind_method(_MD("deselect","column"),&TreeItem::deselect); + ClassDB::bind_method(_MD("is_selected","column"),&TreeItem::is_selected); + ClassDB::bind_method(_MD("select","column"),&TreeItem::select); + ClassDB::bind_method(_MD("deselect","column"),&TreeItem::deselect); - ObjectTypeDB::bind_method(_MD("set_editable","column","enabled"),&TreeItem::set_editable); - ObjectTypeDB::bind_method(_MD("is_editable","column"),&TreeItem::is_editable); + ClassDB::bind_method(_MD("set_editable","column","enabled"),&TreeItem::set_editable); + ClassDB::bind_method(_MD("is_editable","column"),&TreeItem::is_editable); - ObjectTypeDB::bind_method(_MD("set_custom_color","column","color"),&TreeItem::set_custom_color); - ObjectTypeDB::bind_method(_MD("clear_custom_color","column"),&TreeItem::clear_custom_color); + ClassDB::bind_method(_MD("set_custom_color","column","color"),&TreeItem::set_custom_color); + ClassDB::bind_method(_MD("clear_custom_color","column"),&TreeItem::clear_custom_color); - ObjectTypeDB::bind_method(_MD("set_custom_bg_color","column","color","just_outline"),&TreeItem::set_custom_bg_color,DEFVAL(false)); - ObjectTypeDB::bind_method(_MD("clear_custom_bg_color","column"),&TreeItem::clear_custom_bg_color); - ObjectTypeDB::bind_method(_MD("get_custom_bg_color","column"),&TreeItem::get_custom_bg_color); + ClassDB::bind_method(_MD("set_custom_bg_color","column","color","just_outline"),&TreeItem::set_custom_bg_color,DEFVAL(false)); + ClassDB::bind_method(_MD("clear_custom_bg_color","column"),&TreeItem::clear_custom_bg_color); + ClassDB::bind_method(_MD("get_custom_bg_color","column"),&TreeItem::get_custom_bg_color); - ObjectTypeDB::bind_method(_MD("add_button","column","button:Texture","button_idx","disabled"),&TreeItem::add_button,DEFVAL(-1),DEFVAL(false)); - ObjectTypeDB::bind_method(_MD("get_button_count","column"),&TreeItem::get_button_count); - ObjectTypeDB::bind_method(_MD("get_button:Texture","column","button_idx"),&TreeItem::get_button); - ObjectTypeDB::bind_method(_MD("erase_button","column","button_idx"),&TreeItem::erase_button); - ObjectTypeDB::bind_method(_MD("is_button_disabled","column","button_idx"),&TreeItem::is_button_disabled); + ClassDB::bind_method(_MD("add_button","column","button:Texture","button_idx","disabled"),&TreeItem::add_button,DEFVAL(-1),DEFVAL(false)); + ClassDB::bind_method(_MD("get_button_count","column"),&TreeItem::get_button_count); + ClassDB::bind_method(_MD("get_button:Texture","column","button_idx"),&TreeItem::get_button); + ClassDB::bind_method(_MD("set_button","column","button_idx","button:Texture"),&TreeItem::set_button); + ClassDB::bind_method(_MD("erase_button","column","button_idx"),&TreeItem::erase_button); + ClassDB::bind_method(_MD("is_button_disabled","column","button_idx"),&TreeItem::is_button_disabled); - ObjectTypeDB::bind_method(_MD("set_tooltip","column","tooltip"),&TreeItem::set_tooltip); - ObjectTypeDB::bind_method(_MD("get_tooltip","column"),&TreeItem::get_tooltip); + ClassDB::bind_method(_MD("set_tooltip","column","tooltip"),&TreeItem::set_tooltip); + ClassDB::bind_method(_MD("get_tooltip","column"),&TreeItem::get_tooltip); - ObjectTypeDB::bind_method(_MD("move_to_top"),&TreeItem::move_to_top); - ObjectTypeDB::bind_method(_MD("move_to_bottom"),&TreeItem::move_to_bottom); + ClassDB::bind_method(_MD("move_to_top"),&TreeItem::move_to_top); + ClassDB::bind_method(_MD("move_to_bottom"),&TreeItem::move_to_bottom); BIND_CONSTANT( CELL_MODE_STRING ); BIND_CONSTANT( CELL_MODE_CHECK ); @@ -811,6 +837,10 @@ void Tree::update_cache() { cache.item_margin=get_constant("item_margin"); cache.button_margin=get_constant("button_margin"); cache.guide_width=get_constant("guide_width"); + cache.draw_relationship_lines=get_constant("draw_relationship_lines"); + cache.relationship_line_color=get_color("relationship_line_color"); + cache.scroll_border=get_constant("scroll_border"); + cache.scroll_speed=get_constant("scroll_speed"); cache.title_button = get_stylebox("title_button_normal"); cache.title_button_pressed = get_stylebox("title_button_pressed"); @@ -919,13 +949,19 @@ void Tree::draw_item_rect(const TreeItem::Cell& p_cell,const Rect2i& p_rect,cons } -// if (p_tool) -// rect.size.x-=Math::floor(rect.size.y/2); + /* + if (p_tool) + rect.size.x-=Math::floor(rect.size.y/2); + */ Ref<Font> font = cache.font; + String text = p_cell.text; + if (p_cell.suffix!=String()) + text+=" "+p_cell.suffix; + rect.pos.y+=Math::floor((rect.size.y-font->get_height())/2.0) +font->get_ascent(); - font->draw(ci,rect.pos,p_cell.text,p_color,rect.size.x); + font->draw(ci,rect.pos,text,p_color,rect.size.x); } @@ -971,22 +1007,12 @@ int Tree::draw_item(const Point2i& p_pos,const Point2& p_draw_ofs, const Size2& /* Draw label, if height fits */ - Point2i guide_from; bool skip=(p_item==root && hide_root); - // printf("skip (%p == %p && %i) %i\n",p_item,root,hide_root,skip); if (!skip && (p_pos.y+label_h-cache.offset.y)>0) { - // printf("entering\n"); - - int height=label_h; - - Point2i guide_space=Point2i( cache.guide_width , height ); - - - if (!hide_folding && p_item->childs) { //has childs, draw the guide box Ref<Texture> arrow; @@ -1005,7 +1031,7 @@ int Tree::draw_item(const Point2i& p_pos,const Point2& p_draw_ofs, const Size2& } //draw separation. -// if (p_item->get_parent()!=root || !hide_root) + //if (p_item->get_parent()!=root || !hide_root) Ref<Font> font = cache.font; @@ -1038,7 +1064,7 @@ int Tree::draw_item(const Point2i& p_pos,const Point2& p_draw_ofs, const Size2& Point2i o = Point2i( ofs+w-s.width, p_pos.y )-cache.offset+p_draw_ofs; - if (cache.click_type==Cache::CLICK_BUTTON && cache.click_item==p_item && cache.click_column==i && !p_item->cells[i].buttons[j].disabled) { + if (cache.click_type==Cache::CLICK_BUTTON && cache.click_item==p_item && cache.click_column==i && cache.click_index==j && !p_item->cells[i].buttons[j].disabled) { //being pressed cache.button_pressed->draw(get_canvas_item(),Rect2(o,s)); } @@ -1046,7 +1072,7 @@ int Tree::draw_item(const Point2i& p_pos,const Point2& p_draw_ofs, const Size2& o.y+=(label_h-s.height)/2; o+=cache.button_pressed->get_offset(); - b->draw(ci,o,p_item->cells[i].buttons[j].disabled?Color(1,1,1,0.5):Color(1,1,1,1)); + b->draw(ci,o,p_item->cells[i].buttons[j].disabled?Color(1,1,1,0.5):p_item->cells[i].buttons[j].color); w-=s.width+cache.button_margin; bw+=s.width+cache.button_margin; } @@ -1079,11 +1105,21 @@ int Tree::draw_item(const Point2i& p_pos,const Point2& p_draw_ofs, const Size2& if (p_item->cells[i].selected && select_mode!=SELECT_ROW) { Rect2i r(item_rect.pos,item_rect.size); + if (p_item->cells[i].text.size() > 0){ + float icon_width = p_item->cells[i].get_icon_size().width; + r.pos.x += icon_width; + r.size.x -= icon_width; + } //r.grow(cache.selected->get_margin(MARGIN_LEFT)); - if (has_focus()) + if (has_focus()){ cache.selected_focus->draw(ci,r ); - else + p_item->set_meta("__focus_rect", Rect2(r.pos,r.size)); + } else { cache.selected->draw(ci,r ); + } + if (text_editor->is_visible_in_tree()){ + text_editor->set_pos(get_global_pos() + r.pos); + } } if (p_item->cells[i].custom_bg_color) { @@ -1172,6 +1208,9 @@ int Tree::draw_item(const Point2i& p_pos,const Point2& p_draw_ofs, const Size2& String s = p_item->cells[i].text; s=s.get_slicec(',',option); + if (p_item->cells[i].suffix!=String()) + s+=" "+p_item->cells[i].suffix; + Ref<Texture> downarrow = cache.select_arrow; font->draw(ci, text_pos, s, col,item_rect.size.x-downarrow->get_width() ); @@ -1186,7 +1225,12 @@ int Tree::draw_item(const Point2i& p_pos,const Point2& p_draw_ofs, const Size2& Ref<Texture> updown = cache.updown; - String valtext = String::num( p_item->cells[i].val, Math::decimals( p_item->cells[i].step ) ); + String valtext = String::num( p_item->cells[i].val, Math::step_decimals( p_item->cells[i].step ) ); + //String valtext = rtos( p_item->cells[i].val ); + + if (p_item->cells[i].suffix!=String()) + valtext+=" "+p_item->cells[i].suffix; + font->draw( ci, text_pos, valtext, col, item_rect.size.x-updown->get_width()); if (!p_item->cells[i].editable) @@ -1220,7 +1264,7 @@ int Tree::draw_item(const Point2i& p_pos,const Point2& p_draw_ofs, const Size2& } break; case TreeItem::CELL_MODE_CUSTOM: { - // int option = (int)p_item->cells[i].val; + //int option = (int)p_item->cells[i].val; @@ -1294,9 +1338,21 @@ int Tree::draw_item(const Point2i& p_pos,const Point2& p_draw_ofs, const Size2& while (c) { + if (cache.draw_relationship_lines == 1){ + int root_ofs = children_pos.x + (hide_folding?cache.hseparation:cache.item_margin); + int parent_ofs = p_pos.x + (hide_folding?cache.hseparation:cache.item_margin); + Point2i root_pos = Point2i(root_ofs, children_pos.y + label_h/2)-cache.offset+p_draw_ofs; + if (c->get_children() != NULL) + root_pos -= Point2i(cache.arrow->get_width(),0); + + Point2i parent_pos = Point2i(parent_ofs - cache.arrow->get_width()/2, p_pos.y + label_h/2 + cache.arrow->get_height()/2)-cache.offset+p_draw_ofs; + VisualServer::get_singleton()->canvas_item_add_line(ci, root_pos, Point2i(parent_pos.x, root_pos.y), cache.relationship_line_color); + VisualServer::get_singleton()->canvas_item_add_line(ci, Point2i(parent_pos.x, root_pos.y), parent_pos, cache.relationship_line_color); + } + int child_h=draw_item(children_pos, p_draw_ofs, p_draw_size, c ); - if (child_h<0) + if (child_h<0 && cache.draw_relationship_lines == 0) return -1; // break, stop drawing, no need to anymore htotal+=child_h; @@ -1330,7 +1386,7 @@ int Tree::_count_selected_items(TreeItem* p_from) const { return count; } -void Tree::select_single_item(TreeItem *p_selected,TreeItem *p_current,int p_col,TreeItem *p_prev,bool *r_in_range) { +void Tree::select_single_item(TreeItem *p_selected, TreeItem *p_current, int p_col, TreeItem *p_prev, bool *r_in_range, bool p_force_deselect) { TreeItem::Cell &selected_cell=p_selected->cells[p_col]; @@ -1340,6 +1396,8 @@ void Tree::select_single_item(TreeItem *p_selected,TreeItem *p_current,int p_col switched=true; } + bool emitted_row=false; + for (int i=0;i<columns.size();i++) { TreeItem::Cell &c=p_current->cells[i]; @@ -1349,35 +1407,29 @@ void Tree::select_single_item(TreeItem *p_selected,TreeItem *p_current,int p_col if (select_mode==SELECT_ROW) { - - if (p_selected==p_current) { - - if (!c.selected) { - + if (p_selected==p_current && !c.selected) { c.selected=true; selected_item=p_selected; selected_col=0; selected_item=p_selected; - emit_signal("item_selected"); - //if (p_col==i) - // p_current->selected_signal.call(p_col); - } - - } else { + if (!emitted_row) { + emit_signal("item_selected"); + emitted_row=true; + } + /* + if (p_col==i) + p_current->selected_signal.call(p_col); + */ - if (c.selected) { + } else if (c.selected) { c.selected=false; //p_current->deselected_signal.call(p_col); - } - } - } else if (select_mode==SELECT_SINGLE || select_mode==SELECT_MULTI) { if (!r_in_range && &selected_cell==&c) { - if (!selected_cell.selected) { selected_cell.selected=true; @@ -1388,6 +1440,8 @@ void Tree::select_single_item(TreeItem *p_selected,TreeItem *p_current,int p_col emit_signal("cell_selected"); if (select_mode==SELECT_MULTI) emit_signal("multi_selected",p_current,i,true); + else if(select_mode == SELECT_SINGLE) + emit_signal("item_selected"); } else if (select_mode==SELECT_MULTI && (selected_item!=p_selected || selected_col!=i)) { @@ -1399,7 +1453,7 @@ void Tree::select_single_item(TreeItem *p_selected,TreeItem *p_current,int p_col } else { - if (r_in_range && *r_in_range) { + if (r_in_range && *r_in_range && !p_force_deselect) { if (!c.selected && c.selectable) { @@ -1407,7 +1461,7 @@ void Tree::select_single_item(TreeItem *p_selected,TreeItem *p_current,int p_col emit_signal("multi_selected",p_current,i,true); } - } else if (!r_in_range){ + } else if (!r_in_range || p_force_deselect){ if (select_mode==SELECT_MULTI && c.selected) emit_signal("multi_selected",p_current,i,false); c.selected=false; @@ -1426,7 +1480,7 @@ void Tree::select_single_item(TreeItem *p_selected,TreeItem *p_current,int p_col while (c) { - select_single_item(p_selected,c,p_col,p_prev,r_in_range); + select_single_item(p_selected,c,p_col,p_prev,r_in_range,p_current->is_collapsed() || p_force_deselect); c=c->next; } @@ -1622,9 +1676,11 @@ int Tree::propagate_mouse_event(const Point2i &p_pos,int x_ofs,int y_ofs,bool p_ } } - //if (!c.selected && select_mode==SELECT_MULTI) { - // emit_signal("multi_selected",p_item,col,true); - //} + /* + if (!c.selected && select_mode==SELECT_MULTI) { + emit_signal("multi_selected",p_item,col,true); + } + */ update(); } @@ -1640,7 +1696,6 @@ int Tree::propagate_mouse_event(const Point2i &p_pos,int x_ofs,int y_ofs,bool p_ /* editing */ bool bring_up_editor=force_select_on_already_selected ? (c.selected && already_selected) : c.selected; - bool bring_up_value_editor=false; String editor_text=c.text; switch (c.mode) { @@ -1655,16 +1710,11 @@ int Tree::propagate_mouse_event(const Point2i &p_pos,int x_ofs,int y_ofs,bool p_ } break; case TreeItem::CELL_MODE_CHECK: { - Ref<Texture> checked = cache.checked; bring_up_editor=false; //checkboxes are not edited with editor - if (x>=0 && x<= checked->get_width()+cache.hseparation ) { - - - p_item->set_checked(col,!c.checked); - item_edited(col,p_item); - click_handled=true; - //p_item->edited_signal.call(col); - } + p_item->set_checked(col, !c.checked); + item_edited(col, p_item); + click_handled = true; + //p_item->edited_signal.call(col); } break; case TreeItem::CELL_MODE_RANGE: @@ -1691,9 +1741,6 @@ int Tree::propagate_mouse_event(const Point2i &p_pos,int x_ofs,int y_ofs,bool p_ bring_up_editor=false; } else { - Ref<Texture> updown = cache.updown; - - if (x >= (col_width-item_h/2)) { /* touching the combo */ @@ -1739,8 +1786,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos,int x_ofs,int y_ofs,bool p_ } else { - editor_text=String::num( p_item->cells[col].val, Math::decimals( p_item->cells[col].step ) ); - bring_up_value_editor=false; + editor_text=String::num( p_item->cells[col].val, Math::step_decimals( p_item->cells[col].step ) ); if (select_mode==SELECT_MULTI && get_tree()->get_last_event_id() == focus_in_id) bring_up_editor=false; @@ -1915,7 +1961,7 @@ void Tree::popup_select(int p_option) { -void Tree::_input_event(InputEvent p_event) { +void Tree::_gui_input(InputEvent p_event) { switch (p_event.type) { @@ -1957,7 +2003,7 @@ void Tree::_input_event(InputEvent p_event) { } break; case KEY_LEFT: { -// TreeItem *next = NULL; + //TreeItem *next = NULL; if (!selected_item) break; if (select_mode==SELECT_ROW) @@ -1987,7 +2033,7 @@ void Tree::_input_event(InputEvent p_event) { next=selected_item->get_next_visible(); -// if (diff < uint64_t(GLOBAL_DEF("gui/incr_search_max_interval_msec",2000))) { + //if (diff < uint64_t(GLOBAL_DEF("gui/incr_search_max_interval_msec",2000))) { if (last_keypress!=0) { //incr search next int col; @@ -2237,10 +2283,10 @@ void Tree::_input_event(InputEvent p_event) { mpos.y-=_get_title_button_height(); if (mpos.y>=0) { - if (h_scroll->is_visible()) - mpos.x+=h_scroll->get_val(); - if (v_scroll->is_visible()) - mpos.y+=v_scroll->get_val(); + if (h_scroll->is_visible_in_tree()) + mpos.x+=h_scroll->get_value(); + if (v_scroll->is_visible_in_tree()) + mpos.y+=v_scroll->get_value(); int col,h,section; TreeItem *it = _find_item_at_pos(root,mpos,col,h,section); @@ -2259,7 +2305,7 @@ void Tree::_input_event(InputEvent p_event) { update(); } - if (pressing_for_editor && popup_edited_item && popup_edited_item->get_cell_mode(popup_edited_item_col)==TreeItem::CELL_MODE_RANGE) { + if (pressing_for_editor && popup_edited_item && (popup_edited_item->get_cell_mode(popup_edited_item_col)==TreeItem::CELL_MODE_RANGE || popup_edited_item->get_cell_mode(popup_edited_item_col)==TreeItem::CELL_MODE_RANGE_EXPRESSION)) { //range drag if (!range_drag_enabled) { @@ -2289,7 +2335,7 @@ void Tree::_input_event(InputEvent p_event) { drag_accum-=b.relative_y; - v_scroll->set_val(drag_from+drag_accum); + v_scroll->set_value(drag_from+drag_accum); drag_speed=-b.speed_y; } @@ -2322,9 +2368,14 @@ void Tree::_input_event(InputEvent p_event) { range_drag_enabled=false; Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_VISIBLE); warp_mouse(range_drag_capture_pos); - } else - edit_selected(); - + } else { + Rect2 rect = get_selected()->get_meta("__focus_rect"); + if (rect.has_point(Point2(p_event.mouse_button.x,p_event.mouse_button.y))) { + edit_selected(); + } else { + emit_signal("item_double_clicked"); + } + } pressing_for_editor=false; } @@ -2360,6 +2411,9 @@ void Tree::_input_event(InputEvent p_event) { } + if (range_drag_enabled) + break; + switch(b.button_index) { case BUTTON_RIGHT: case BUTTON_LEFT: { @@ -2422,8 +2476,8 @@ void Tree::_input_event(InputEvent p_event) { if (!click_handled) { drag_speed=0; drag_accum=0; -// last_drag_accum=0; - drag_from=v_scroll->get_val(); + //last_drag_accum=0; + drag_from=v_scroll->get_value(); drag_touching=OS::get_singleton()->has_touchscreen_ui_hint(); drag_touching_deaccel=false; if (drag_touching) { @@ -2435,11 +2489,11 @@ void Tree::_input_event(InputEvent p_event) { } break; case BUTTON_WHEEL_UP: { - v_scroll->set_val( v_scroll->get_val()-v_scroll->get_page()/8 ); + v_scroll->set_value( v_scroll->get_value()-v_scroll->get_page()/8 ); } break; case BUTTON_WHEEL_DOWN: { - v_scroll->set_val( v_scroll->get_val()+v_scroll->get_page()/8 ); + v_scroll->set_value( v_scroll->get_value()+v_scroll->get_page()/8 ); } break; } @@ -2462,16 +2516,7 @@ bool Tree::edit_selected() { if (!s->cells[col].editable) return false; - Rect2 rect; - rect.pos.y = get_item_offset(s) - get_scroll().y; - - for(int i=0;i<col;i++) { - - rect.pos.x+=get_column_width(i); - } - - rect.size.width=get_column_width(col); - rect.size.height=compute_item_height(s)+cache.vseparation; + Rect2 rect = s->get_meta("__focus_rect"); popup_edited_item=s; popup_edited_item_col=col; @@ -2515,7 +2560,7 @@ bool Tree::edit_selected() { text_editor->set_pos( textedpos ); text_editor->set_size( rect.size); text_editor->clear(); - text_editor->set_text( c.mode==TreeItem::CELL_MODE_STRING?c.text:rtos(c.val) ); + text_editor->set_text( c.mode==TreeItem::CELL_MODE_STRING?c.text:String::num( c.val, Math::step_decimals( c.step ) ) ); text_editor->select_all(); if (c.mode==TreeItem::CELL_MODE_RANGE || c.mode==TreeItem::CELL_MODE_RANGE_EXPRESSION ) { @@ -2527,8 +2572,8 @@ bool Tree::edit_selected() { value_editor->set_min( c.min ); value_editor->set_max( c.max ); value_editor->set_step( c.step ); - value_editor->set_val( c.val ); - value_editor->set_exp_unit_value( c.expr ); + value_editor->set_value( c.val ); + value_editor->set_exp_ratio( c.expr ); updating_value_editor=false; } @@ -2587,7 +2632,7 @@ void Tree::update_scrollbars() { v_scroll->show(); v_scroll->set_max(min.height); v_scroll->set_page(size.height - hmin.height - tbh); - cache.offset.y=v_scroll->get_val(); + cache.offset.y=v_scroll->get_value(); } if (min.width < size.width - vmin.width) { @@ -2599,7 +2644,7 @@ void Tree::update_scrollbars() { h_scroll->show(); h_scroll->set_max(min.width); h_scroll->set_page(size.width - vmin.width); - cache.offset.x=h_scroll->get_val(); + cache.offset.x=h_scroll->get_value(); } } @@ -2635,11 +2680,17 @@ void Tree::_notification(int p_what) { if (p_what==NOTIFICATION_DRAG_END) { drop_mode_flags=0; + scrolling = false; + set_fixed_process(false); update(); } if (p_what==NOTIFICATION_DRAG_BEGIN) { single_select_defer=NULL; + if (cache.scroll_speed > 0 && get_rect().has_point(get_viewport()->get_mouse_pos() - get_global_pos())) { + scrolling = true; + set_fixed_process(true); + } } if (p_what==NOTIFICATION_FIXED_PROCESS) { @@ -2647,7 +2698,7 @@ void Tree::_notification(int p_what) { if (drag_touching_deaccel) { - float pos = v_scroll->get_val(); + float pos = v_scroll->get_value(); pos+=drag_speed*get_fixed_process_delta_time(); bool turnoff=false; @@ -2664,7 +2715,7 @@ void Tree::_notification(int p_what) { } - v_scroll->set_val(pos); + v_scroll->set_value(pos); float sgn = drag_speed<0? -1 : 1; float val = Math::abs(drag_speed); val-=1000*get_fixed_process_delta_time(); @@ -2685,6 +2736,28 @@ void Tree::_notification(int p_what) { } } + + if (scrolling) { + Point2 point = get_viewport()->get_mouse_pos() - get_global_pos(); + if (point.x < cache.scroll_border) { + point.x -= cache.scroll_border; + } else if (point.x > get_size().width - cache.scroll_border) { + point.x -= get_size().width - cache.scroll_border; + } else { + point.x = 0; + } + if (point.y < cache.scroll_border) { + point.y -= cache.scroll_border; + } else if (point.y > get_size().height - cache.scroll_border) { + point.y -= get_size().height - cache.scroll_border; + } else { + point.y = 0; + } + point *= cache.scroll_speed * get_fixed_process_delta_time(); + point += get_scroll(); + h_scroll->set_value(point.x); + v_scroll->set_value(point.y); + } } if (p_what==NOTIFICATION_DRAW) { @@ -2693,8 +2766,6 @@ void Tree::_notification(int p_what) { update_scrollbars(); RID ci = get_canvas_item(); - VisualServer::get_singleton()->canvas_item_set_clip(ci,true); - Ref<StyleBox> bg = cache.bg; Ref<StyleBox> bg_focus = get_stylebox("bg_focus"); @@ -2722,13 +2793,10 @@ void Tree::_notification(int p_what) { } int ofs=0; -// int from_y=exposed.pos.y+bg->get_margin(MARGIN_TOP); -// int size_y=exposed.size.height-bg->get_minimum_size().height; for (int i=0;i<(columns.size()-1-1);i++) { ofs+=get_column_width(i); - //get_painter()->draw_fill_rect( Point2(ofs+cache.hseparation/2, from_y), Size2( 1, size_y ),color( COLOR_TREE_GRID) ); } if (show_column_titles) { @@ -2842,7 +2910,6 @@ void Tree::item_changed(int p_column,TreeItem *p_item) { void Tree::item_selected(int p_column,TreeItem *p_item) { - if (select_mode==SELECT_MULTI) { if (!p_item->cells[p_column].selectable) @@ -2852,6 +2919,7 @@ void Tree::item_selected(int p_column,TreeItem *p_item) { //emit_signal("multi_selected",p_item,p_column,true); - NO this is for TreeItem::select } else { + select_single_item(p_item,root,p_column); } update(); @@ -2859,8 +2927,7 @@ void Tree::item_selected(int p_column,TreeItem *p_item) { void Tree::item_deselected(int p_column,TreeItem *p_item) { - if (select_mode==SELECT_MULTI) { - + if (select_mode==SELECT_MULTI || select_mode == SELECT_SINGLE) { p_item->cells[p_column].selected=false; } update(); @@ -2952,8 +3019,10 @@ int Tree::get_edited_column() const { TreeItem* Tree::get_next_selected( TreeItem* p_item) { - //if (!p_item) - // return NULL; + /* + if (!p_item) + return NULL; + */ if (!root) return NULL; @@ -3005,7 +3074,7 @@ int Tree::get_column_width(int p_column) const { int expand_area=get_size().width-(bg->get_margin(MARGIN_LEFT)+bg->get_margin(MARGIN_RIGHT)); - if (v_scroll->is_visible()) + if (v_scroll->is_visible_in_tree()) expand_area-=v_scroll->get_combined_minimum_size().width; int expanding_columns=0; @@ -3121,10 +3190,10 @@ void Tree::ensure_cursor_is_visible() { int h = compute_item_height(selected)+cache.vseparation; int screenh=get_size().height-h_scroll->get_combined_minimum_size().height; - if (ofs+h>v_scroll->get_val()+screenh) - v_scroll->set_val(ofs-screenh+h); - else if (ofs < v_scroll->get_val()) - v_scroll->set_val(ofs); + if (ofs+h>v_scroll->get_value()+screenh) + v_scroll->call_deferred("set_val", ofs-screenh+h); + else if (ofs < v_scroll->get_value()) + v_scroll->set_value(ofs); } int Tree::get_pressed_button() const { @@ -3190,10 +3259,10 @@ String Tree::get_column_title(int p_column) const { Point2 Tree::get_scroll() const { Point2 ofs; - if (h_scroll->is_visible()) - ofs.x=h_scroll->get_val(); - if (v_scroll->is_visible()) - ofs.y=v_scroll->get_val(); + if (h_scroll->is_visible_in_tree()) + ofs.x=h_scroll->get_value(); + if (v_scroll->is_visible_in_tree()) + ofs.y=v_scroll->get_value(); return ofs; } @@ -3236,7 +3305,7 @@ void Tree::_do_incr_search(const String& p_add) { uint64_t time = OS::get_singleton()->get_ticks_usec() / 1000; // convert to msec uint64_t diff = time - last_keypress; - if (diff > uint64_t(GLOBAL_DEF("gui/incr_search_max_interval_msec",2000))) + if (diff > uint64_t(GLOBAL_DEF("gui/timers/incremental_search_max_interval_msec",2000))) incr_search=p_add; else incr_search+=p_add; @@ -3331,10 +3400,10 @@ int Tree::get_column_at_pos(const Point2& p_pos) const { if (pos.y<0) return -1; - if (h_scroll->is_visible()) - pos.x+=h_scroll->get_val(); - if (v_scroll->is_visible()) - pos.y+=v_scroll->get_val(); + if (h_scroll->is_visible_in_tree()) + pos.x+=h_scroll->get_value(); + if (v_scroll->is_visible_in_tree()) + pos.y+=v_scroll->get_value(); int col,h,section; TreeItem *it = _find_item_at_pos(root,pos,col,h,section); @@ -3358,10 +3427,10 @@ int Tree::get_drop_section_at_pos(const Point2& p_pos) const { if (pos.y<0) return -100; - if (h_scroll->is_visible()) - pos.x+=h_scroll->get_val(); - if (v_scroll->is_visible()) - pos.y+=v_scroll->get_val(); + if (h_scroll->is_visible_in_tree()) + pos.x+=h_scroll->get_value(); + if (v_scroll->is_visible_in_tree()) + pos.y+=v_scroll->get_value(); int col,h,section; TreeItem *it = _find_item_at_pos(root,pos,col,h,section); @@ -3385,10 +3454,10 @@ TreeItem* Tree::get_item_at_pos(const Point2& p_pos) const { if (pos.y<0) return NULL; - if (h_scroll->is_visible()) - pos.x+=h_scroll->get_val(); - if (v_scroll->is_visible()) - pos.y+=v_scroll->get_val(); + if (h_scroll->is_visible_in_tree()) + pos.x+=h_scroll->get_value(); + if (v_scroll->is_visible_in_tree()) + pos.y+=v_scroll->get_value(); int col,h,section; TreeItem *it = _find_item_at_pos(root,pos,col,h,section); @@ -3413,10 +3482,10 @@ String Tree::get_tooltip(const Point2& p_pos) const { if (pos.y<0) return Control::get_tooltip(p_pos); - if (h_scroll->is_visible()) - pos.x+=h_scroll->get_val(); - if (v_scroll->is_visible()) - pos.y+=v_scroll->get_val(); + if (h_scroll->is_visible_in_tree()) + pos.x+=h_scroll->get_value(); + if (v_scroll->is_visible_in_tree()) + pos.y+=v_scroll->get_value(); int col,h,section; TreeItem *it = _find_item_at_pos(root,pos,col,h,section); @@ -3497,62 +3566,62 @@ bool Tree::get_allow_rmb_select() const{ return allow_rmb_select; } -void Tree::_bind_methods() { - ObjectTypeDB::bind_method(_MD("_range_click_timeout"),&Tree::_range_click_timeout); - ObjectTypeDB::bind_method(_MD("_input_event"),&Tree::_input_event); - ObjectTypeDB::bind_method(_MD("_popup_select"),&Tree::popup_select); - ObjectTypeDB::bind_method(_MD("_text_editor_enter"),&Tree::text_editor_enter); - ObjectTypeDB::bind_method(_MD("_text_editor_modal_close"),&Tree::_text_editor_modal_close); - ObjectTypeDB::bind_method(_MD("_value_editor_changed"),&Tree::value_editor_changed); - ObjectTypeDB::bind_method(_MD("_scroll_moved"),&Tree::_scroll_moved); +void Tree::_bind_methods() { - ObjectTypeDB::bind_method(_MD("clear"),&Tree::clear); - ObjectTypeDB::bind_method(_MD("create_item:TreeItem","parent:TreeItem"),&Tree::_create_item,DEFVAL(Variant())); + ClassDB::bind_method(_MD("_range_click_timeout"),&Tree::_range_click_timeout); + ClassDB::bind_method(_MD("_gui_input"),&Tree::_gui_input); + ClassDB::bind_method(_MD("_popup_select"),&Tree::popup_select); + ClassDB::bind_method(_MD("_text_editor_enter"),&Tree::text_editor_enter); + ClassDB::bind_method(_MD("_text_editor_modal_close"),&Tree::_text_editor_modal_close); + ClassDB::bind_method(_MD("_value_editor_changed"),&Tree::value_editor_changed); + ClassDB::bind_method(_MD("_scroll_moved"),&Tree::_scroll_moved); - ObjectTypeDB::bind_method(_MD("get_root:TreeItem"),&Tree::get_root); - ObjectTypeDB::bind_method(_MD("set_column_min_width","column","min_width"),&Tree::set_column_min_width); - ObjectTypeDB::bind_method(_MD("set_column_expand","column","expand"),&Tree::set_column_expand); - ObjectTypeDB::bind_method(_MD("get_column_width","column"),&Tree::get_column_width); + ClassDB::bind_method(_MD("clear"),&Tree::clear); + ClassDB::bind_method(_MD("create_item:TreeItem","parent:TreeItem"),&Tree::_create_item,DEFVAL(Variant())); - ObjectTypeDB::bind_method(_MD("set_hide_root","enable"),&Tree::set_hide_root); - ObjectTypeDB::bind_method(_MD("get_next_selected:TreeItem","from:TreeItem"),&Tree::_get_next_selected); - ObjectTypeDB::bind_method(_MD("get_selected:TreeItem"),&Tree::get_selected); - ObjectTypeDB::bind_method(_MD("get_selected_column"),&Tree::get_selected_column); - ObjectTypeDB::bind_method(_MD("get_pressed_button"),&Tree::get_pressed_button); - ObjectTypeDB::bind_method(_MD("set_select_mode","mode"),&Tree::set_select_mode); + ClassDB::bind_method(_MD("get_root:TreeItem"),&Tree::get_root); + ClassDB::bind_method(_MD("set_column_min_width","column","min_width"),&Tree::set_column_min_width); + ClassDB::bind_method(_MD("set_column_expand","column","expand"),&Tree::set_column_expand); + ClassDB::bind_method(_MD("get_column_width","column"),&Tree::get_column_width); - ObjectTypeDB::bind_method(_MD("set_columns","amount"),&Tree::set_columns); - ObjectTypeDB::bind_method(_MD("get_columns"),&Tree::get_columns); + ClassDB::bind_method(_MD("set_hide_root","enable"),&Tree::set_hide_root); + ClassDB::bind_method(_MD("get_next_selected:TreeItem","from:TreeItem"),&Tree::_get_next_selected); + ClassDB::bind_method(_MD("get_selected:TreeItem"),&Tree::get_selected); + ClassDB::bind_method(_MD("get_selected_column"),&Tree::get_selected_column); + ClassDB::bind_method(_MD("get_pressed_button"),&Tree::get_pressed_button); + ClassDB::bind_method(_MD("set_select_mode","mode"),&Tree::set_select_mode); - ObjectTypeDB::bind_method(_MD("get_edited:TreeItem"),&Tree::get_edited); - ObjectTypeDB::bind_method(_MD("get_edited_column"),&Tree::get_edited_column); - ObjectTypeDB::bind_method(_MD("get_custom_popup_rect"),&Tree::get_custom_popup_rect); - ObjectTypeDB::bind_method(_MD("get_item_area_rect","item:TreeItem","column"),&Tree::_get_item_rect,DEFVAL(-1)); - ObjectTypeDB::bind_method(_MD("get_item_at_pos:TreeItem","pos"),&Tree::get_item_at_pos); - ObjectTypeDB::bind_method(_MD("get_column_at_pos","pos"),&Tree::get_column_at_pos); + ClassDB::bind_method(_MD("set_columns","amount"),&Tree::set_columns); + ClassDB::bind_method(_MD("get_columns"),&Tree::get_columns); - ObjectTypeDB::bind_method(_MD("ensure_cursor_is_visible"),&Tree::ensure_cursor_is_visible); + ClassDB::bind_method(_MD("get_edited:TreeItem"),&Tree::get_edited); + ClassDB::bind_method(_MD("get_edited_column"),&Tree::get_edited_column); + ClassDB::bind_method(_MD("get_custom_popup_rect"),&Tree::get_custom_popup_rect); + ClassDB::bind_method(_MD("get_item_area_rect","item:TreeItem","column"),&Tree::_get_item_rect,DEFVAL(-1)); + ClassDB::bind_method(_MD("get_item_at_pos:TreeItem","pos"),&Tree::get_item_at_pos); + ClassDB::bind_method(_MD("get_column_at_pos","pos"),&Tree::get_column_at_pos); - ObjectTypeDB::bind_method(_MD("set_column_titles_visible","visible"),&Tree::set_column_titles_visible); - ObjectTypeDB::bind_method(_MD("are_column_titles_visible"),&Tree::are_column_titles_visible); + ClassDB::bind_method(_MD("ensure_cursor_is_visible"),&Tree::ensure_cursor_is_visible); - ObjectTypeDB::bind_method(_MD("set_column_title","column","title"),&Tree::set_column_title); - ObjectTypeDB::bind_method(_MD("get_column_title","column"),&Tree::get_column_title); - ObjectTypeDB::bind_method(_MD("get_scroll"),&Tree::get_scroll); + ClassDB::bind_method(_MD("set_column_titles_visible","visible"),&Tree::set_column_titles_visible); + ClassDB::bind_method(_MD("are_column_titles_visible"),&Tree::are_column_titles_visible); - ObjectTypeDB::bind_method(_MD("set_hide_folding","hide"),&Tree::set_hide_folding); - ObjectTypeDB::bind_method(_MD("is_folding_hidden"),&Tree::is_folding_hidden); + ClassDB::bind_method(_MD("set_column_title","column","title"),&Tree::set_column_title); + ClassDB::bind_method(_MD("get_column_title","column"),&Tree::get_column_title); + ClassDB::bind_method(_MD("get_scroll"),&Tree::get_scroll); - ObjectTypeDB::bind_method(_MD("set_drop_mode_flags","flags"),&Tree::set_drop_mode_flags); - ObjectTypeDB::bind_method(_MD("get_drop_mode_flags"),&Tree::get_drop_mode_flags); + ClassDB::bind_method(_MD("set_hide_folding","hide"),&Tree::set_hide_folding); + ClassDB::bind_method(_MD("is_folding_hidden"),&Tree::is_folding_hidden); - ObjectTypeDB::bind_method(_MD("set_allow_rmb_select","allow"),&Tree::set_allow_rmb_select); - ObjectTypeDB::bind_method(_MD("get_allow_rmb_select"),&Tree::get_allow_rmb_select); + ClassDB::bind_method(_MD("set_drop_mode_flags","flags"),&Tree::set_drop_mode_flags); + ClassDB::bind_method(_MD("get_drop_mode_flags"),&Tree::get_drop_mode_flags); + ClassDB::bind_method(_MD("set_allow_rmb_select","allow"),&Tree::set_allow_rmb_select); + ClassDB::bind_method(_MD("get_allow_rmb_select"),&Tree::get_allow_rmb_select); - ObjectTypeDB::bind_method(_MD("set_single_select_cell_editing_only_when_already_selected","enable"),&Tree::set_single_select_cell_editing_only_when_already_selected); - ObjectTypeDB::bind_method(_MD("get_single_select_cell_editing_only_when_already_selected"),&Tree::get_single_select_cell_editing_only_when_already_selected); + ClassDB::bind_method(_MD("set_single_select_cell_editing_only_when_already_selected","enable"),&Tree::set_single_select_cell_editing_only_when_already_selected); + ClassDB::bind_method(_MD("get_single_select_cell_editing_only_when_already_selected"),&Tree::get_single_select_cell_editing_only_when_already_selected); ADD_SIGNAL( MethodInfo("item_selected")); ADD_SIGNAL( MethodInfo("cell_selected")); @@ -3560,6 +3629,7 @@ void Tree::_bind_methods() { ADD_SIGNAL( MethodInfo("item_rmb_selected",PropertyInfo(Variant::VECTOR2,"pos"))); ADD_SIGNAL( MethodInfo("empty_tree_rmb_selected",PropertyInfo(Variant::VECTOR2,"pos"))); ADD_SIGNAL( MethodInfo("item_edited")); + ADD_SIGNAL( MethodInfo("item_double_clicked")); ADD_SIGNAL( MethodInfo("item_collapsed",PropertyInfo(Variant::OBJECT,"item"))); //ADD_SIGNAL( MethodInfo("item_doubleclicked" ) ); ADD_SIGNAL( MethodInfo("button_pressed",PropertyInfo(Variant::OBJECT,"item"),PropertyInfo(Variant::INT,"column"),PropertyInfo(Variant::INT,"id"))); @@ -3620,8 +3690,8 @@ Tree::Tree() { h_scroll->connect("value_changed", this,"_scroll_moved"); v_scroll->connect("value_changed", this,"_scroll_moved"); text_editor->connect("text_entered", this,"_text_editor_enter"); - text_editor->connect("modal_close", this,"_text_editor_modal_close"); - popup_menu->connect("item_pressed", this,"_popup_select"); + text_editor->connect("modal_closed", this,"_text_editor_modal_close"); + popup_menu->connect("id_pressed", this,"_popup_select"); value_editor->connect("value_changed", this,"_value_editor_changed"); value_editor->set_as_toplevel(true); @@ -3644,7 +3714,7 @@ Tree::Tree() { blocked=0; cursor_can_exit_tree=true; - set_stop_mouse(true); + set_mouse_filter(MOUSE_FILTER_STOP); drag_speed=0; drag_touching=false; @@ -3663,6 +3733,8 @@ Tree::Tree() { force_select_on_already_selected=false; allow_rmb_select=false; + + set_clip_contents(true); } @@ -3673,4 +3745,3 @@ Tree::~Tree() { } } - diff --git a/scene/gui/tree.h b/scene/gui/tree.h index 1dad26dffe..d715ff4772 100644 --- a/scene/gui/tree.h +++ b/scene/gui/tree.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 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 */ @@ -45,7 +45,7 @@ class Tree; class TreeItem : public Object { - OBJ_TYPE(TreeItem,Object); + GDCLASS(TreeItem,Object); public: enum TreeCellMode { @@ -69,6 +69,7 @@ friend class Tree; Ref<Texture> icon; Rect2i icon_region; String text; + String suffix; double min,max,step,val; int icon_max_w; bool expr; @@ -92,7 +93,8 @@ friend class Tree; int id; bool disabled; Ref<Texture> texture; - Button() { id=0; disabled=false; } + Color color; + Button() { id=0; disabled=false; color=Color(1,1,1,1); } }; Vector< Button > buttons; @@ -168,6 +170,9 @@ public: void set_text(int p_column,String p_text); String get_text(int p_column) const; + void set_suffix(int p_column,String p_suffix); + String get_suffix(int p_column) const; + void set_icon(int p_column,const Ref<Texture>& p_icon); Ref<Texture> get_icon(int p_column) const; @@ -185,6 +190,7 @@ public: int get_button_by_id(int p_column,int p_id) const; bool is_button_disabled(int p_column,int p_idx) const; void set_button(int p_column,int p_idx,const Ref<Texture>& p_button); + void set_button_color(int p_column,int p_idx,const Color& p_color); /* range works for mode number or mode combo */ @@ -251,7 +257,7 @@ VARIANT_ENUM_CAST( TreeItem::TreeCellMode ); class Tree : public Control { - OBJ_TYPE( Tree, Control ); + GDCLASS( Tree, Control ); public: enum SelectMode { SELECT_SINGLE, @@ -328,10 +334,10 @@ friend class TreeItem; int compute_item_height(TreeItem *p_item) const; int get_item_height(TreeItem *p_item) const; -// void draw_item_text(String p_text,const Ref<Texture>& p_icon,int p_icon_max_w,bool p_tool,Rect2i p_rect,const Color& p_color); + //void draw_item_text(String p_text,const Ref<Texture>& p_icon,int p_icon_max_w,bool p_tool,Rect2i p_rect,const Color& p_color); void draw_item_rect(const TreeItem::Cell& p_cell,const Rect2i& p_rect,const Color& p_color); int draw_item(const Point2i& p_pos,const Point2& p_draw_ofs, const Size2& p_draw_size,TreeItem *p_item); - void select_single_item(TreeItem *p_selected,TreeItem *p_current,int p_col,TreeItem *p_prev=NULL,bool *r_in_range=NULL); + void select_single_item(TreeItem *p_selected,TreeItem *p_current,int p_col,TreeItem *p_prev=NULL,bool *r_in_range=NULL,bool p_force_deselect=false); int propagate_mouse_event(const Point2i &p_pos,int x_ofs,int y_ofs,bool p_doubleclick,TreeItem *p_item,int p_button,const InputModifierState& p_mod); void text_editor_enter(String p_text); void _text_editor_modal_close(); @@ -339,7 +345,7 @@ friend class TreeItem; void popup_select(int p_option); - void _input_event(InputEvent p_event); + void _gui_input(InputEvent p_event); void _notification(int p_what); Size2 get_minimum_size() const; @@ -377,6 +383,7 @@ friend class TreeItem; Color font_color_selected; Color guide_color; Color drop_position_color; + Color relationship_line_color; int hseparation; int vseparation; @@ -384,6 +391,9 @@ friend class TreeItem; int guide_width; int button_margin; Point2 offset; + int draw_relationship_lines; + int scroll_border; + int scroll_speed; enum ClickType { CLICK_NONE, @@ -439,6 +449,7 @@ friend class TreeItem; bool drag_touching_deaccel; bool click_handled; bool allow_rmb_select; + bool scrolling; bool force_select_on_already_selected; @@ -532,4 +543,3 @@ public: VARIANT_ENUM_CAST( Tree::SelectMode ); #endif - diff --git a/scene/gui/video_player.cpp b/scene/gui/video_player.cpp index 26227d6389..4c177ea53c 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-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 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 */ @@ -116,13 +116,12 @@ void VideoPlayer::_notification(int p_notification) { case NOTIFICATION_ENTER_TREE: { - //set_idle_process(false); //don't annoy if (stream.is_valid() && autoplay && !get_tree()->is_editor_hint()) { play(); } } break; - case NOTIFICATION_PROCESS: { + case NOTIFICATION_INTERNAL_PROCESS: { if (stream.is_null()) return; @@ -141,13 +140,6 @@ void VideoPlayer::_notification(int p_notification) { playback->update(delta); - /*int prev_width = texture->get_width(); - stream->pop_frame(texture); - if (prev_width == 0) { - update(); - minimum_size_changed(); - };*/ - } break; case NOTIFICATION_DRAW: { @@ -158,8 +150,6 @@ void VideoPlayer::_notification(int p_notification) { return; Size2 s=expand?get_size():texture->get_size(); - RID ci = get_canvas_item(); - printf("drawing with size %f, %f\n", s.x, s.y); draw_texture_rect(texture,Rect2(Point2(),s),false); } break; @@ -208,10 +198,17 @@ void VideoPlayer::set_stream(const Ref<VideoStream> &p_stream) { playback->set_paused(paused); texture=playback->get_texture(); + const int channels = playback->get_channels(); + AudioServer::get_singleton()->lock(); - resampler.setup(playback->get_channels(),playback->get_mix_rate(),server_mix_rate,buffering_ms,0); + if (channels > 0) + resampler.setup(channels,playback->get_mix_rate(),server_mix_rate,buffering_ms,0); + else + resampler.clear(); AudioServer::get_singleton()->unlock(); - playback->set_mix_callback(_audio_mix_callback,this); + + if (channels > 0) + playback->set_mix_callback(_audio_mix_callback,this); } else { texture.unref(); @@ -236,7 +233,7 @@ void VideoPlayer::play() { return; playback->stop(); playback->play(); - set_process(true); + set_process_internal(true); AudioServer::get_singleton()->stream_set_active(stream_rid,true); AudioServer::get_singleton()->stream_set_volume_scale(stream_rid,volume); last_audio_time=0; @@ -251,8 +248,8 @@ void VideoPlayer::stop() { playback->stop(); AudioServer::get_singleton()->stream_set_active(stream_rid,false); - resampler.clear(); - set_process(false); + resampler.flush(); + set_process_internal(false); last_audio_time=0; }; @@ -269,7 +266,7 @@ void VideoPlayer::set_paused(bool p_paused) { paused=p_paused; if (playback.is_valid()) { playback->set_paused(p_paused); - set_process(!p_paused); + set_process_internal(!p_paused); }; last_audio_time = 0; }; @@ -360,47 +357,47 @@ bool VideoPlayer::has_autoplay() const { void VideoPlayer::_bind_methods() { - ObjectTypeDB::bind_method(_MD("set_stream","stream:VideoStream"),&VideoPlayer::set_stream); - ObjectTypeDB::bind_method(_MD("get_stream:VideoStream"),&VideoPlayer::get_stream); + ClassDB::bind_method(_MD("set_stream","stream:VideoStream"),&VideoPlayer::set_stream); + ClassDB::bind_method(_MD("get_stream:VideoStream"),&VideoPlayer::get_stream); - ObjectTypeDB::bind_method(_MD("play"),&VideoPlayer::play); - ObjectTypeDB::bind_method(_MD("stop"),&VideoPlayer::stop); + ClassDB::bind_method(_MD("play"),&VideoPlayer::play); + ClassDB::bind_method(_MD("stop"),&VideoPlayer::stop); - ObjectTypeDB::bind_method(_MD("is_playing"),&VideoPlayer::is_playing); + ClassDB::bind_method(_MD("is_playing"),&VideoPlayer::is_playing); - ObjectTypeDB::bind_method(_MD("set_paused","paused"),&VideoPlayer::set_paused); - ObjectTypeDB::bind_method(_MD("is_paused"),&VideoPlayer::is_paused); + ClassDB::bind_method(_MD("set_paused","paused"),&VideoPlayer::set_paused); + ClassDB::bind_method(_MD("is_paused"),&VideoPlayer::is_paused); - ObjectTypeDB::bind_method(_MD("set_volume","volume"),&VideoPlayer::set_volume); - ObjectTypeDB::bind_method(_MD("get_volume"),&VideoPlayer::get_volume); + ClassDB::bind_method(_MD("set_volume","volume"),&VideoPlayer::set_volume); + ClassDB::bind_method(_MD("get_volume"),&VideoPlayer::get_volume); - ObjectTypeDB::bind_method(_MD("set_volume_db","db"),&VideoPlayer::set_volume_db); - ObjectTypeDB::bind_method(_MD("get_volume_db"),&VideoPlayer::get_volume_db); + ClassDB::bind_method(_MD("set_volume_db","db"),&VideoPlayer::set_volume_db); + ClassDB::bind_method(_MD("get_volume_db"),&VideoPlayer::get_volume_db); - ObjectTypeDB::bind_method(_MD("set_audio_track","track"),&VideoPlayer::set_audio_track); - ObjectTypeDB::bind_method(_MD("get_audio_track"),&VideoPlayer::get_audio_track); + ClassDB::bind_method(_MD("set_audio_track","track"),&VideoPlayer::set_audio_track); + ClassDB::bind_method(_MD("get_audio_track"),&VideoPlayer::get_audio_track); - ObjectTypeDB::bind_method(_MD("get_stream_name"),&VideoPlayer::get_stream_name); + ClassDB::bind_method(_MD("get_stream_name"),&VideoPlayer::get_stream_name); - ObjectTypeDB::bind_method(_MD("get_stream_pos"),&VideoPlayer::get_stream_pos); + ClassDB::bind_method(_MD("get_stream_pos"),&VideoPlayer::get_stream_pos); - ObjectTypeDB::bind_method(_MD("set_autoplay","enabled"),&VideoPlayer::set_autoplay); - ObjectTypeDB::bind_method(_MD("has_autoplay"),&VideoPlayer::has_autoplay); + ClassDB::bind_method(_MD("set_autoplay","enabled"),&VideoPlayer::set_autoplay); + ClassDB::bind_method(_MD("has_autoplay"),&VideoPlayer::has_autoplay); - ObjectTypeDB::bind_method(_MD("set_expand","enable"), &VideoPlayer::set_expand ); - ObjectTypeDB::bind_method(_MD("has_expand"), &VideoPlayer::has_expand ); + ClassDB::bind_method(_MD("set_expand","enable"), &VideoPlayer::set_expand ); + ClassDB::bind_method(_MD("has_expand"), &VideoPlayer::has_expand ); - ObjectTypeDB::bind_method(_MD("set_buffering_msec","msec"),&VideoPlayer::set_buffering_msec); - ObjectTypeDB::bind_method(_MD("get_buffering_msec"),&VideoPlayer::get_buffering_msec); + ClassDB::bind_method(_MD("set_buffering_msec","msec"),&VideoPlayer::set_buffering_msec); + ClassDB::bind_method(_MD("get_buffering_msec"),&VideoPlayer::get_buffering_msec); - ObjectTypeDB::bind_method(_MD("get_video_texture:Texture"), &VideoPlayer::get_video_texture ); + ClassDB::bind_method(_MD("get_video_texture:Texture"), &VideoPlayer::get_video_texture ); - ADD_PROPERTY( PropertyInfo(Variant::INT, "stream/audio_track",PROPERTY_HINT_RANGE,"0,128,1"), _SCS("set_audio_track"), _SCS("get_audio_track") ); - ADD_PROPERTY( PropertyInfo(Variant::OBJECT, "stream/stream", PROPERTY_HINT_RESOURCE_TYPE,"VideoStream"), _SCS("set_stream"), _SCS("get_stream") ); -// ADD_PROPERTY( PropertyInfo(Variant::BOOL, "stream/loop"), _SCS("set_loop"), _SCS("has_loop") ); - ADD_PROPERTY( PropertyInfo(Variant::REAL, "stream/volume_db", PROPERTY_HINT_RANGE,"-80,24,0.01"), _SCS("set_volume_db"), _SCS("get_volume_db") ); - ADD_PROPERTY( PropertyInfo(Variant::BOOL, "stream/autoplay"), _SCS("set_autoplay"), _SCS("has_autoplay") ); - ADD_PROPERTY( PropertyInfo(Variant::BOOL, "stream/paused"), _SCS("set_paused"), _SCS("is_paused") ); + ADD_PROPERTY( PropertyInfo(Variant::INT, "audio_track",PROPERTY_HINT_RANGE,"0,128,1"), _SCS("set_audio_track"), _SCS("get_audio_track") ); + ADD_PROPERTY( PropertyInfo(Variant::OBJECT, "stream", PROPERTY_HINT_RESOURCE_TYPE,"VideoStream"), _SCS("set_stream"), _SCS("get_stream") ); + //ADD_PROPERTY( PropertyInfo(Variant::BOOL, "stream/loop"), _SCS("set_loop"), _SCS("has_loop") ); + ADD_PROPERTY( PropertyInfo(Variant::REAL, "volume_db", PROPERTY_HINT_RANGE,"-80,24,0.01"), _SCS("set_volume_db"), _SCS("get_volume_db") ); + ADD_PROPERTY( PropertyInfo(Variant::BOOL, "autoplay"), _SCS("set_autoplay"), _SCS("has_autoplay") ); + ADD_PROPERTY( PropertyInfo(Variant::BOOL, "paused"), _SCS("set_paused"), _SCS("is_paused") ); ADD_PROPERTY( PropertyInfo( Variant::BOOL, "expand" ), _SCS("set_expand"),_SCS("has_expand") ); } @@ -429,5 +426,6 @@ VideoPlayer::~VideoPlayer() { if (stream_rid.is_valid()) AudioServer::get_singleton()->free(stream_rid); + resampler.clear(); //Not necessary here, but make in consistent with other "stream_player" classes }; diff --git a/scene/gui/video_player.h b/scene/gui/video_player.h index 9ce1ba78f4..694cb253a4 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-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 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 */ @@ -35,7 +35,7 @@ class VideoPlayer : public Control { - OBJ_TYPE(VideoPlayer,Control); + GDCLASS(VideoPlayer,Control); struct InternalStream : public AudioServer::AudioStream { VideoPlayer *player; diff --git a/scene/gui/viewport_container.cpp b/scene/gui/viewport_container.cpp new file mode 100644 index 0000000000..9e89de66dd --- /dev/null +++ b/scene/gui/viewport_container.cpp @@ -0,0 +1,103 @@ +#include "viewport_container.h" +#include "scene/main/viewport.h" +Size2 ViewportContainer::get_minimum_size() const { + + + if (stretch) + return Size2(); + Size2 ms; + for(int i=0;i<get_child_count();i++) { + + Viewport *c = get_child(i)->cast_to<Viewport>(); + if (!c) + continue; + + Size2 minsize = c->get_size(); + ms.width = MAX(ms.width , minsize.width); + ms.height = MAX(ms.height , minsize.height); + } + + return ms; + +} + + +void ViewportContainer::set_stretch(bool p_enable) { + + stretch=p_enable; + queue_sort(); + update(); + +} + +bool ViewportContainer::is_stretch_enabled() const { + + return stretch; +} + + +void ViewportContainer::_notification(int p_what) { + + + if (p_what==NOTIFICATION_RESIZED) { + + if (!stretch) + return; + + for(int i=0;i<get_child_count();i++) { + + Viewport *c = get_child(i)->cast_to<Viewport>(); + if (!c) + continue; + + c->set_size(get_size()); + } + } + + if (p_what==NOTIFICATION_ENTER_TREE || p_what==NOTIFICATION_VISIBILITY_CHANGED) { + + for(int i=0;i<get_child_count();i++) { + + Viewport *c = get_child(i)->cast_to<Viewport>(); + if (!c) + continue; + + + if (is_visible_in_tree()) + c->set_update_mode(Viewport::UPDATE_ALWAYS); + else + c->set_update_mode(Viewport::UPDATE_DISABLED); + } + + } + + if (p_what==NOTIFICATION_DRAW) { + + for(int i=0;i<get_child_count();i++) { + + + Viewport *c = get_child(i)->cast_to<Viewport>(); + if (!c) + continue; + + if (stretch) + draw_texture_rect(c->get_texture(),Rect2(Vector2(),get_size()*Size2(1,-1))); + else + draw_texture_rect(c->get_texture(),Rect2(Vector2(),c->get_size()*Size2(1,-1))); + } + } + +} + +void ViewportContainer::_bind_methods() { + + ClassDB::bind_method(_MD("set_stretch","enable"),&ViewportContainer::set_stretch); + ClassDB::bind_method(_MD("is_stretch_enabled"),&ViewportContainer::is_stretch_enabled); + + ADD_PROPERTY( PropertyInfo(Variant::BOOL,"stretch"),_SCS("set_stretch"),_SCS("is_stretch_enabled")); +} + +ViewportContainer::ViewportContainer() { + + stretch=false; +} diff --git a/scene/gui/viewport_container.h b/scene/gui/viewport_container.h new file mode 100644 index 0000000000..632c54f2f4 --- /dev/null +++ b/scene/gui/viewport_container.h @@ -0,0 +1,25 @@ +#ifndef VIEWPORTCONTAINER_H +#define VIEWPORTCONTAINER_H + +#include "scene/gui/container.h" + +class ViewportContainer : public Container { + + GDCLASS( ViewportContainer, Container ); + + bool stretch; +protected: + + void _notification(int p_what); + static void _bind_methods(); +public: + + void set_stretch(bool p_enable); + bool is_stretch_enabled() const; + + virtual Size2 get_minimum_size() const; + + ViewportContainer(); +}; + +#endif // VIEWPORTCONTAINER_H |