summaryrefslogtreecommitdiff
path: root/scene/gui
diff options
context:
space:
mode:
Diffstat (limited to 'scene/gui')
-rw-r--r--scene/gui/SCsub4
-rw-r--r--scene/gui/base_button.cpp255
-rw-r--r--scene/gui/base_button.h57
-rw-r--r--scene/gui/box_container.cpp23
-rw-r--r--scene/gui/box_container.h8
-rw-r--r--scene/gui/button.cpp45
-rw-r--r--scene/gui/button.h12
-rw-r--r--scene/gui/button_array.cpp106
-rw-r--r--scene/gui/button_array.h22
-rw-r--r--scene/gui/button_group.cpp21
-rw-r--r--scene/gui/button_group.h7
-rw-r--r--scene/gui/center_container.cpp8
-rw-r--r--scene/gui/center_container.h4
-rw-r--r--scene/gui/check_box.cpp10
-rw-r--r--scene/gui/check_box.h4
-rw-r--r--scene/gui/check_button.cpp2
-rw-r--r--scene/gui/check_button.h4
-rw-r--r--scene/gui/color_picker.cpp338
-rw-r--r--scene/gui/color_picker.h31
-rw-r--r--scene/gui/color_ramp_edit.cpp42
-rw-r--r--scene/gui/color_ramp_edit.h34
-rw-r--r--scene/gui/color_rect.cpp (renamed from scene/gui/custom_button.cpp)35
-rw-r--r--scene/gui/color_rect.h (renamed from scene/gui/custom_button.h)29
-rw-r--r--scene/gui/container.cpp20
-rw-r--r--scene/gui/container.h4
-rw-r--r--scene/gui/control.cpp997
-rw-r--r--scene/gui/control.h75
-rw-r--r--scene/gui/dialogs.cpp122
-rw-r--r--scene/gui/dialogs.h21
-rw-r--r--scene/gui/file_dialog.cpp189
-rw-r--r--scene/gui/file_dialog.h8
-rw-r--r--scene/gui/graph_edit.cpp626
-rw-r--r--scene/gui/graph_edit.h99
-rw-r--r--scene/gui/graph_node.cpp253
-rw-r--r--scene/gui/graph_node.h67
-rw-r--r--scene/gui/grid_container.cpp20
-rw-r--r--scene/gui/grid_container.h4
-rw-r--r--scene/gui/input_action.cpp125
-rw-r--r--scene/gui/input_action.h26
-rw-r--r--scene/gui/item_list.cpp375
-rw-r--r--scene/gui/item_list.h51
-rw-r--r--scene/gui/label.cpp130
-rw-r--r--scene/gui/label.h6
-rw-r--r--scene/gui/line_edit.cpp630
-rw-r--r--scene/gui/line_edit.h40
-rw-r--r--scene/gui/link_button.cpp45
-rw-r--r--scene/gui/link_button.h33
-rw-r--r--scene/gui/margin_container.cpp4
-rw-r--r--scene/gui/margin_container.h4
-rw-r--r--scene/gui/menu_button.cpp44
-rw-r--r--scene/gui/menu_button.h6
-rw-r--r--scene/gui/option_button.cpp56
-rw-r--r--scene/gui/option_button.h4
-rw-r--r--scene/gui/panel.cpp4
-rw-r--r--scene/gui/panel.h6
-rw-r--r--scene/gui/panel_container.cpp6
-rw-r--r--scene/gui/panel_container.h4
-rw-r--r--scene/gui/patch_9_frame.cpp132
-rw-r--r--scene/gui/patch_9_frame.h40
-rw-r--r--scene/gui/patch_9_rect.cpp186
-rw-r--r--scene/gui/patch_9_rect.h68
-rw-r--r--scene/gui/popup.cpp31
-rw-r--r--scene/gui/popup.h8
-rw-r--r--scene/gui/popup_menu.cpp370
-rw-r--r--scene/gui/popup_menu.h36
-rw-r--r--scene/gui/progress_bar.cpp15
-rw-r--r--scene/gui/progress_bar.h4
-rw-r--r--scene/gui/range.cpp109
-rw-r--r--scene/gui/range.h22
-rw-r--r--scene/gui/reference_rect.cpp (renamed from scene/gui/reference_frame.cpp)10
-rw-r--r--scene/gui/reference_rect.h (renamed from scene/gui/reference_frame.h)16
-rw-r--r--scene/gui/rich_text_label.cpp240
-rw-r--r--scene/gui/rich_text_label.h7
-rw-r--r--scene/gui/scroll_bar.cpp110
-rw-r--r--scene/gui/scroll_bar.h10
-rw-r--r--scene/gui/scroll_container.cpp126
-rw-r--r--scene/gui/scroll_container.h9
-rw-r--r--scene/gui/separator.cpp2
-rw-r--r--scene/gui/separator.h8
-rw-r--r--scene/gui/slider.cpp60
-rw-r--r--scene/gui/slider.h10
-rw-r--r--scene/gui/spin_box.cpp75
-rw-r--r--scene/gui/spin_box.h6
-rw-r--r--scene/gui/split_container.cpp28
-rw-r--r--scene/gui/split_container.h12
-rw-r--r--scene/gui/tab_container.cpp87
-rw-r--r--scene/gui/tab_container.h6
-rw-r--r--scene/gui/tabs.cpp30
-rw-r--r--scene/gui/tabs.h6
-rw-r--r--scene/gui/text_edit.cpp769
-rw-r--r--scene/gui/text_edit.h61
-rw-r--r--scene/gui/texture_button.cpp71
-rw-r--r--scene/gui/texture_button.h9
-rw-r--r--scene/gui/texture_progress.cpp59
-rw-r--r--scene/gui/texture_progress.h4
-rw-r--r--scene/gui/texture_rect.cpp (renamed from scene/gui/texture_frame.cpp)121
-rw-r--r--scene/gui/texture_rect.h (renamed from scene/gui/texture_frame.h)20
-rw-r--r--scene/gui/tool_button.cpp2
-rw-r--r--scene/gui/tool_button.h4
-rw-r--r--scene/gui/tree.cpp519
-rw-r--r--scene/gui/tree.h26
-rw-r--r--scene/gui/video_player.cpp90
-rw-r--r--scene/gui/video_player.h4
-rw-r--r--scene/gui/viewport_container.cpp103
-rw-r--r--scene/gui/viewport_container.h25
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