diff options
Diffstat (limited to 'scene/gui')
99 files changed, 1777 insertions, 1280 deletions
diff --git a/scene/gui/SCsub b/scene/gui/SCsub index bf9125be7f..b01e2fd54d 100644 --- a/scene/gui/SCsub +++ b/scene/gui/SCsub @@ -3,5 +3,3 @@ Import('env') 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 d17ae1d84c..806c8afa5b 100644 --- a/scene/gui/base_button.cpp +++ b/scene/gui/base_button.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,7 +30,7 @@ #include "base_button.h" -#include "os/keyboard.h" +#include "core/os/keyboard.h" #include "scene/main/viewport.h" #include "scene/scene_string_names.h" @@ -82,16 +82,16 @@ void BaseButton::_gui_input(Ref<InputEvent> p_event) { get_script_instance()->call(SceneStringNames::get_singleton()->_pressed, NULL, 0, ce); } - emit_signal("pressed"); _unpress_group(); + emit_signal("pressed"); } else { status.pressed = !status.pressed; pressed(); - emit_signal("pressed"); _unpress_group(); + emit_signal("pressed"); toggled(status.pressed); if (get_script_instance()) { @@ -135,6 +135,7 @@ void BaseButton::_gui_input(Ref<InputEvent> p_event) { get_script_instance()->call(SceneStringNames::get_singleton()->_pressed, NULL, 0, ce); } + _unpress_group(); emit_signal("pressed"); } else { @@ -142,6 +143,7 @@ void BaseButton::_gui_input(Ref<InputEvent> p_event) { status.pressed = !status.pressed; pressed(); + _unpress_group(); emit_signal("pressed"); toggled(status.pressed); @@ -150,8 +152,6 @@ void BaseButton::_gui_input(Ref<InputEvent> p_event) { } emit_signal("toggled", status.pressed); } - - _unpress_group(); } status.press_attempt = false; @@ -215,12 +215,14 @@ void BaseButton::_gui_input(Ref<InputEvent> p_event) { get_script_instance()->call(SceneStringNames::get_singleton()->_pressed, NULL, 0, ce); } + _unpress_group(); emit_signal("pressed"); } else { status.pressed = !status.pressed; pressed(); + _unpress_group(); emit_signal("pressed"); toggled(status.pressed); @@ -229,8 +231,6 @@ void BaseButton::_gui_input(Ref<InputEvent> p_event) { } emit_signal("toggled", status.pressed); } - - _unpress_group(); } accept_event(); @@ -315,6 +315,14 @@ void BaseButton::set_disabled(bool p_disabled) { return; status.disabled = p_disabled; + if (p_disabled) { + if (!toggle_mode) { + status.pressed = false; + } + status.press_attempt = false; + status.pressing_inside = false; + status.pressing_button = 0; + } update(); _change_notify("disabled"); } @@ -360,7 +368,9 @@ BaseButton::DrawMode BaseButton::get_draw_mode() const { return DRAW_DISABLED; }; - if (status.press_attempt == false && status.hovering && !status.pressed) { + if (!status.press_attempt && status.hovering) { + if (status.pressed) + return DRAW_HOVER_PRESSED; return DRAW_HOVER; } else { @@ -396,6 +406,16 @@ bool BaseButton::is_toggle_mode() const { return toggle_mode; } +void BaseButton::set_shortcut_in_tooltip(bool p_on) { + + shortcut_in_tooltip = p_on; +} + +bool BaseButton::is_shortcut_in_tooltip_enabled() const { + + return shortcut_in_tooltip; +} + void BaseButton::set_action_mode(ActionMode p_mode) { action_mode = p_mode; @@ -461,7 +481,7 @@ void BaseButton::_unhandled_input(Ref<InputEvent> p_event) { String BaseButton::get_tooltip(const Point2 &p_pos) const { String tooltip = Control::get_tooltip(p_pos); - if (shortcut.is_valid() && shortcut->is_valid()) { + if (shortcut_in_tooltip && shortcut.is_valid() && shortcut->is_valid()) { String text = shortcut->get_name() + " (" + shortcut->get_as_text() + ")"; if (shortcut->get_name().nocasecmp_to(tooltip) != 0) { text += "\n" + tooltip; @@ -500,6 +520,8 @@ void BaseButton::_bind_methods() { ClassDB::bind_method(D_METHOD("is_hovered"), &BaseButton::is_hovered); ClassDB::bind_method(D_METHOD("set_toggle_mode", "enabled"), &BaseButton::set_toggle_mode); ClassDB::bind_method(D_METHOD("is_toggle_mode"), &BaseButton::is_toggle_mode); + ClassDB::bind_method(D_METHOD("set_shortcut_in_tooltip", "enabled"), &BaseButton::set_shortcut_in_tooltip); + ClassDB::bind_method(D_METHOD("is_shortcut_in_tooltip_enabled"), &BaseButton::is_shortcut_in_tooltip_enabled); ClassDB::bind_method(D_METHOD("set_disabled", "disabled"), &BaseButton::set_disabled); ClassDB::bind_method(D_METHOD("is_disabled"), &BaseButton::is_disabled); ClassDB::bind_method(D_METHOD("set_action_mode", "mode"), &BaseButton::set_action_mode); @@ -523,11 +545,12 @@ void BaseButton::_bind_methods() { ADD_SIGNAL(MethodInfo("button_up")); ADD_SIGNAL(MethodInfo("button_down")); ADD_SIGNAL(MethodInfo("toggled", PropertyInfo(Variant::BOOL, "button_pressed"))); - ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL, "disabled"), "set_disabled", "is_disabled"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "disabled"), "set_disabled", "is_disabled"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "toggle_mode"), "set_toggle_mode", "is_toggle_mode"); - ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL, "pressed"), "set_pressed", "is_pressed"); - ADD_PROPERTYNO(PropertyInfo(Variant::INT, "action_mode", PROPERTY_HINT_ENUM, "Button Press,Button Release"), "set_action_mode", "get_action_mode"); - ADD_PROPERTYNO(PropertyInfo(Variant::INT, "button_mask", PROPERTY_HINT_FLAGS, "Mouse Left, Mouse Right, Mouse Middle"), "set_button_mask", "get_button_mask"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "shortcut_in_tooltip"), "set_shortcut_in_tooltip", "is_shortcut_in_tooltip_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "pressed"), "set_pressed", "is_pressed"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "action_mode", PROPERTY_HINT_ENUM, "Button Press,Button Release"), "set_action_mode", "get_action_mode"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "button_mask", PROPERTY_HINT_FLAGS, "Mouse Left, Mouse Right, Mouse Middle"), "set_button_mask", "get_button_mask"); ADD_PROPERTY(PropertyInfo(Variant::INT, "enabled_focus_mode", PROPERTY_HINT_ENUM, "None,Click,All"), "set_enabled_focus_mode", "get_enabled_focus_mode"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "shortcut", PROPERTY_HINT_RESOURCE_TYPE, "ShortCut"), "set_shortcut", "get_shortcut"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "group", PROPERTY_HINT_RESOURCE_TYPE, "ButtonGroup"), "set_button_group", "get_button_group"); @@ -536,6 +559,7 @@ void BaseButton::_bind_methods() { BIND_ENUM_CONSTANT(DRAW_PRESSED); BIND_ENUM_CONSTANT(DRAW_HOVER); BIND_ENUM_CONSTANT(DRAW_DISABLED); + BIND_ENUM_CONSTANT(DRAW_HOVER_PRESSED); BIND_ENUM_CONSTANT(ACTION_MODE_BUTTON_PRESS); BIND_ENUM_CONSTANT(ACTION_MODE_BUTTON_RELEASE); @@ -544,6 +568,7 @@ void BaseButton::_bind_methods() { BaseButton::BaseButton() { toggle_mode = false; + shortcut_in_tooltip = true; status.pressed = false; status.press_attempt = false; status.hovering = false; @@ -570,6 +595,16 @@ void ButtonGroup::get_buttons(List<BaseButton *> *r_buttons) { } } +Array ButtonGroup::_get_buttons() { + + Array btns; + for (Set<BaseButton *>::Element *E = buttons.front(); E; E = E->next()) { + btns.push_back(E->get()); + } + + return btns; +} + BaseButton *ButtonGroup::get_pressed_button() { for (Set<BaseButton *>::Element *E = buttons.front(); E; E = E->next()) { @@ -583,6 +618,7 @@ BaseButton *ButtonGroup::get_pressed_button() { void ButtonGroup::_bind_methods() { ClassDB::bind_method(D_METHOD("get_pressed_button"), &ButtonGroup::get_pressed_button); + ClassDB::bind_method(D_METHOD("get_buttons"), &ButtonGroup::_get_buttons); } ButtonGroup::ButtonGroup() { diff --git a/scene/gui/base_button.h b/scene/gui/base_button.h index 79638bbcce..9a00cc79f2 100644 --- a/scene/gui/base_button.h +++ b/scene/gui/base_button.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -51,6 +51,7 @@ public: private: int button_mask; bool toggle_mode; + bool shortcut_in_tooltip; FocusMode enabled_focus_mode; Ref<ShortCut> shortcut; @@ -85,6 +86,7 @@ public: DRAW_PRESSED, DRAW_HOVER, DRAW_DISABLED, + DRAW_HOVER_PRESSED, }; DrawMode get_draw_mode() const; @@ -99,6 +101,9 @@ public: void set_toggle_mode(bool p_on); bool is_toggle_mode() const; + void set_shortcut_in_tooltip(bool p_on); + bool is_shortcut_in_tooltip_enabled() const; + void set_disabled(bool p_disabled); bool is_disabled() const; @@ -138,6 +143,7 @@ protected: public: BaseButton *get_pressed_button(); void get_buttons(List<BaseButton *> *r_buttons); + Array _get_buttons(); ButtonGroup(); }; diff --git a/scene/gui/box_container.cpp b/scene/gui/box_container.cpp index 12b9fe7c03..cc37d4cf7d 100644 --- a/scene/gui/box_container.cpp +++ b/scene/gui/box_container.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -255,6 +255,10 @@ void BoxContainer::_notification(int p_what) { _resort(); } break; + case NOTIFICATION_THEME_CHANGED: { + + minimum_size_changed(); + } break; } } diff --git a/scene/gui/box_container.h b/scene/gui/box_container.h index abc228f804..89924f7fcb 100644 --- a/scene/gui/box_container.h +++ b/scene/gui/box_container.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/button.cpp b/scene/gui/button.cpp index a34f2f1ad5..c734136895 100644 --- a/scene/gui/button.cpp +++ b/scene/gui/button.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -29,8 +29,8 @@ /*************************************************************************/ #include "button.h" +#include "core/translation.h" #include "servers/visual_server.h" -#include "translation.h" Size2 Button::get_minimum_size() const { @@ -88,6 +88,21 @@ void Button::_notification(int p_what) { if (has_color("icon_color_normal")) color_icon = get_color("icon_color_normal"); } break; + case DRAW_HOVER_PRESSED: { + if (has_stylebox("hover_pressed") && has_stylebox_override("hover_pressed")) { + style = get_stylebox("hover_pressed"); + if (!flat) + style->draw(ci, Rect2(Point2(0, 0), size)); + if (has_color("font_color_hover_pressed")) + color = get_color("font_color_hover_pressed"); + else + color = get_color("font_color"); + if (has_color("icon_color_hover_pressed")) + color_icon = get_color("icon_color_hover_pressed"); + + break; + } + } case DRAW_PRESSED: { style = get_stylebox("pressed"); @@ -125,8 +140,8 @@ void Button::_notification(int p_what) { if (has_focus()) { - Ref<StyleBox> style = get_stylebox("focus"); - style->draw(ci, Rect2(Point2(), size)); + Ref<StyleBox> style2 = get_stylebox("focus"); + style2->draw(ci, Rect2(Point2(), size)); } Ref<Font> font = get_font("font"); @@ -259,10 +274,10 @@ void Button::_bind_methods() { BIND_ENUM_CONSTANT(ALIGN_CENTER); BIND_ENUM_CONSTANT(ALIGN_RIGHT); - ADD_PROPERTYNZ(PropertyInfo(Variant::STRING, "text", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT_INTL), "set_text", "get_text"); - ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT, "icon", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_button_icon", "get_button_icon"); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "text", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT_INTL), "set_text", "get_text"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "icon", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_button_icon", "get_button_icon"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "flat"), "set_flat", "is_flat"); - ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL, "clip_text"), "set_clip_text", "get_clip_text"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "clip_text"), "set_clip_text", "get_clip_text"); ADD_PROPERTY(PropertyInfo(Variant::INT, "align", PROPERTY_HINT_ENUM, "Left,Center,Right"), "set_text_align", "get_text_align"); } diff --git a/scene/gui/button.h b/scene/gui/button.h index 0b41b14f02..6ba3475e5a 100644 --- a/scene/gui/button.h +++ b/scene/gui/button.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/center_container.cpp b/scene/gui/center_container.cpp index cf71f89830..7c842999d1 100644 --- a/scene/gui/center_container.cpp +++ b/scene/gui/center_container.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/center_container.h b/scene/gui/center_container.h index 519e1493ec..9c9f61388c 100644 --- a/scene/gui/center_container.h +++ b/scene/gui/center_container.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/check_box.cpp b/scene/gui/check_box.cpp index 0790f87ea7..1d8b74d9db 100644 --- a/scene/gui/check_box.cpp +++ b/scene/gui/check_box.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/check_box.h b/scene/gui/check_box.h index 8375b46ca0..adfb12e7a1 100644 --- a/scene/gui/check_box.h +++ b/scene/gui/check_box.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* 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.cpp b/scene/gui/check_button.cpp index f9ed0ecdbb..35e3119473 100644 --- a/scene/gui/check_button.cpp +++ b/scene/gui/check_button.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,7 +30,7 @@ #include "check_button.h" -#include "print_string.h" +#include "core/print_string.h" #include "servers/visual_server.h" Size2 CheckButton::get_icon_size() const { diff --git a/scene/gui/check_button.h b/scene/gui/check_button.h index a11749e3f6..13b0dbc194 100644 --- a/scene/gui/check_button.h +++ b/scene/gui/check_button.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/color_picker.cpp b/scene/gui/color_picker.cpp index 8e232c6f46..7aca6acd00 100644 --- a/scene/gui/color_picker.cpp +++ b/scene/gui/color_picker.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,9 +30,15 @@ #include "color_picker.h" -#include "os/input.h" -#include "os/keyboard.h" -#include "os/os.h" +#include "core/os/input.h" +#include "core/os/keyboard.h" +#include "core/os/os.h" + +#ifdef TOOLS_ENABLED +#include "editor_scale.h" +#include "editor_settings.h" +#endif + #include "scene/gui/separator.h" #include "scene/main/viewport.h" @@ -52,6 +58,16 @@ void ColorPicker::_notification(int p_what) { bt_add_preset->set_icon(get_icon("add_preset")); _update_color(); + +#ifdef TOOLS_ENABLED + if (Engine::get_singleton()->is_editor_hint()) { + PoolColorArray saved_presets = EditorSettings::get_singleton()->get_project_metadata("color_picker", "presets", PoolColorArray()); + + for (int i = 0; i < saved_presets.size(); i++) { + add_preset(saved_presets[i]); + } + } +#endif } break; case NOTIFICATION_PARENTED: { @@ -66,11 +82,8 @@ void ColorPicker::_notification(int p_what) { } break; case MainLoop::NOTIFICATION_WM_QUIT_REQUEST: { - if (screen != NULL) { - if (screen->is_visible()) { - screen->hide(); - } - } + if (screen != NULL && screen->is_visible()) + screen->hide(); } break; } } @@ -141,10 +154,13 @@ void ColorPicker::_value_changed(double) { void ColorPicker::_html_entered(const String &p_html) { - if (updating) + if (updating || text_is_constructor || !c_text->is_visible()) return; + float last_alpha = color.a; color = Color::html(p_html); + if (!is_editing_alpha()) + color.a = last_alpha; if (!is_inside_tree()) return; @@ -158,14 +174,15 @@ void ColorPicker::_update_color() { updating = true; for (int i = 0; i < 4; i++) { - scroll[i]->set_step(0.01); if (raw_mode_enabled) { + scroll[i]->set_step(0.01); scroll[i]->set_max(100); if (i == 3) scroll[i]->set_max(1); scroll[i]->set_value(color.components[i]); } else { - const int byte_value = color.components[i] * 255; + scroll[i]->set_step(1); + const float byte_value = color.components[i] * 255.0; scroll[i]->set_max(next_power_of_2(MAX(255, byte_value)) - 1); scroll[i]->set_value(byte_value); } @@ -192,15 +209,18 @@ void ColorPicker::_update_presets() { } void ColorPicker::_text_type_toggled() { - if (!Engine::get_singleton()->is_editor_hint()) - return; + text_is_constructor = !text_is_constructor; if (text_is_constructor) { text_type->set_text(""); text_type->set_icon(get_icon("Script", "EditorIcons")); + + c_text->set_editable(false); } else { text_type->set_text("#"); text_type->set_icon(NULL); + + c_text->set_editable(true); } _update_color(); } @@ -220,6 +240,38 @@ void ColorPicker::add_preset(const Color &p_color) { preset->update(); if (presets.size() == 10) bt_add_preset->hide(); + +#ifdef TOOLS_ENABLED + if (Engine::get_singleton()->is_editor_hint()) { + PoolColorArray arr_to_save = get_presets(); + EditorSettings::get_singleton()->set_project_metadata("color_picker", "presets", arr_to_save); + } +#endif +} + +void ColorPicker::erase_preset(const Color &p_color) { + + if (presets.find(p_color)) { + presets.erase(presets.find(p_color)); + preset->update(); + +#ifdef TOOLS_ENABLED + if (Engine::get_singleton()->is_editor_hint()) { + PoolColorArray arr_to_save = get_presets(); + EditorSettings::get_singleton()->set_project_metadata("color_picker", "presets", arr_to_save); + } +#endif + } +} + +PoolColorArray ColorPicker::get_presets() const { + + PoolColorArray arr; + arr.resize(presets.size()); + for (int i = 0; i < presets.size(); i++) { + arr.set(i, presets[i]); + } + return arr; } void ColorPicker::set_raw_mode(bool p_enabled) { @@ -253,19 +305,21 @@ bool ColorPicker::is_deferred_mode() const { void ColorPicker::_update_text_value() { bool visible = true; if (text_is_constructor) { - String t = "Color(" + String::num(color.r) + "," + String::num(color.g) + "," + String::num(color.b); + 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) + ")"); + t += ", " + String::num(color.a) + ")"; else t += ")"; c_text->set_text(t); - } else { - if (color.r > 1 || color.g > 1 || color.b > 1 || color.r < 0 || color.g < 0 || color.b < 0) { - visible = false; - } else { - c_text->set_text(color.to_html(edit_alpha && color.a < 1)); - } } + + if (color.r > 1 || color.g > 1 || color.b > 1 || color.r < 0 || color.g < 0 || color.b < 0) { + visible = false; + } else if (!text_is_constructor) { + c_text->set_text(color.to_html(edit_alpha && color.a < 1)); + } + + text_type->set_visible(visible); c_text->set_visible(visible); } @@ -413,14 +467,15 @@ void ColorPicker::_preset_input(const Ref<InputEvent> &p_event) { if (bev->is_pressed() && bev->get_button_index() == BUTTON_LEFT) { int index = bev->get_position().x / (preset->get_size().x / presets.size()); set_pick_color(presets[index]); + _update_color(); + emit_signal("color_changed", color); } else if (bev->is_pressed() && bev->get_button_index() == BUTTON_RIGHT) { int index = bev->get_position().x / (preset->get_size().x / presets.size()); - presets.erase(presets[index]); - preset->update(); + Color clicked_preset = presets[index]; + erase_preset(clicked_preset); + emit_signal("preset_removed", clicked_preset); bt_add_preset->show(); } - _update_color(); - emit_signal("color_changed", color); } Ref<InputEventMouseMotion> mev = p_event; @@ -442,21 +497,17 @@ void ColorPicker::_preset_input(const Ref<InputEvent> &p_event) { void ColorPicker::_screen_input(const Ref<InputEvent> &p_event) { Ref<InputEventMouseButton> bev = p_event; - - if (bev.is_valid()) { - - if (bev->get_button_index() == BUTTON_LEFT && !bev->is_pressed()) { - emit_signal("color_changed", color); - screen->hide(); - } + if (bev.is_valid() && bev->get_button_index() == BUTTON_LEFT && !bev->is_pressed()) { + emit_signal("color_changed", color); + screen->hide(); } Ref<InputEventMouseMotion> mev = p_event; - if (mev.is_valid()) { Viewport *r = get_tree()->get_root(); if (!r->get_visible_rect().has_point(Point2(mev->get_global_position().x, mev->get_global_position().y))) return; + Ref<Image> img = r->get_texture()->get_data(); if (img.is_valid() && !img->empty()) { img->lock(); @@ -470,6 +521,7 @@ void ColorPicker::_screen_input(const Ref<InputEvent> &p_event) { void ColorPicker::_add_preset_pressed() { add_preset(color); + emit_signal("preset_added", color); } void ColorPicker::_screen_pick_pressed() { @@ -481,6 +533,8 @@ void ColorPicker::_screen_pick_pressed() { screen->set_anchors_and_margins_preset(Control::PRESET_WIDE); screen->set_default_cursor_shape(CURSOR_POINTING_HAND); screen->connect("gui_input", this, "_screen_input"); + // It immediately toggles off in the first press otherwise. + screen->call_deferred("connect", "hide", btn_pick, "set_pressed", varray(false)); } screen->raise(); screen->show_modal(); @@ -522,6 +576,8 @@ void ColorPicker::_bind_methods() { ClassDB::bind_method(D_METHOD("set_edit_alpha", "show"), &ColorPicker::set_edit_alpha); ClassDB::bind_method(D_METHOD("is_editing_alpha"), &ColorPicker::is_editing_alpha); ClassDB::bind_method(D_METHOD("add_preset", "color"), &ColorPicker::add_preset); + ClassDB::bind_method(D_METHOD("erase_preset", "color"), &ColorPicker::erase_preset); + ClassDB::bind_method(D_METHOD("get_presets"), &ColorPicker::get_presets); ClassDB::bind_method(D_METHOD("_value_changed"), &ColorPicker::_value_changed); ClassDB::bind_method(D_METHOD("_html_entered"), &ColorPicker::_html_entered); ClassDB::bind_method(D_METHOD("_text_type_toggled"), &ColorPicker::_text_type_toggled); @@ -544,6 +600,8 @@ void ColorPicker::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "deferred_mode"), "set_deferred_mode", "is_deferred_mode"); ADD_SIGNAL(MethodInfo("color_changed", PropertyInfo(Variant::COLOR, "color"))); + ADD_SIGNAL(MethodInfo("preset_added", PropertyInfo(Variant::COLOR, "color"))); + ADD_SIGNAL(MethodInfo("preset_removed", PropertyInfo(Variant::COLOR, "color"))); } ColorPicker::ColorPicker() : @@ -558,22 +616,25 @@ ColorPicker::ColorPicker() : screen = NULL; HBoxContainer *hb_smpl = memnew(HBoxContainer); - btn_pick = memnew(ToolButton); - btn_pick->connect("pressed", this, "_screen_pick_pressed"); + add_child(hb_smpl); sample = memnew(TextureRect); + hb_smpl->add_child(sample); sample->set_h_size_flags(SIZE_EXPAND_FILL); sample->connect("draw", this, "_sample_draw"); - hb_smpl->add_child(sample); + btn_pick = memnew(ToolButton); hb_smpl->add_child(btn_pick); - add_child(hb_smpl); + btn_pick->set_toggle_mode(true); + btn_pick->set_tooltip(TTR("Pick a color from the screen.")); + btn_pick->connect("pressed", this, "_screen_pick_pressed"); HBoxContainer *hb_edit = memnew(HBoxContainer); + add_child(hb_edit); hb_edit->set_v_size_flags(SIZE_EXPAND_FILL); uv_edit = memnew(Control); - + hb_edit->add_child(uv_edit); uv_edit->connect("gui_input", this, "_uv_input"); uv_edit->set_mouse_filter(MOUSE_FILTER_PASS); uv_edit->set_h_size_flags(SIZE_EXPAND_FILL); @@ -581,19 +642,14 @@ ColorPicker::ColorPicker() : uv_edit->set_custom_minimum_size(Size2(get_constant("sv_width"), get_constant("sv_height"))); uv_edit->connect("draw", this, "_hsv_draw", make_binds(0, uv_edit)); - add_child(hb_edit); - w_edit = memnew(Control); + hb_edit->add_child(w_edit); w_edit->set_custom_minimum_size(Size2(get_constant("h_width"), 0)); w_edit->set_h_size_flags(SIZE_FILL); w_edit->set_v_size_flags(SIZE_EXPAND_FILL); w_edit->connect("gui_input", this, "_w_input"); w_edit->connect("draw", this, "_hsv_draw", make_binds(1, w_edit)); - hb_edit->add_child(uv_edit); - hb_edit->add_child(memnew(VSeparator)); - hb_edit->add_child(w_edit); - VBoxContainer *vbl = memnew(VBoxContainer); add_child(vbl); @@ -634,31 +690,43 @@ ColorPicker::ColorPicker() : } HBoxContainer *hhb = memnew(HBoxContainer); + vbr->add_child(hhb); btn_mode = memnew(CheckButton); + hhb->add_child(btn_mode); btn_mode->set_text(TTR("Raw Mode")); btn_mode->connect("toggled", this, "set_raw_mode"); - hhb->add_child(btn_mode); - vbr->add_child(hhb); + text_type = memnew(Button); - text_type->set_flat(true); - text_type->connect("pressed", this, "_text_type_toggled"); hhb->add_child(text_type); + text_type->set_text("#"); + text_type->set_tooltip(TTR("Switch between hexadecimal and code values.")); + if (Engine::get_singleton()->is_editor_hint()) { + +#ifdef TOOLS_ENABLED + text_type->set_custom_minimum_size(Size2(28 * EDSCALE, 0)); // Adjust for the width of the "Script" icon. +#endif + text_type->connect("pressed", this, "_text_type_toggled"); + } else { + + text_type->set_flat(true); + text_type->set_mouse_filter(MOUSE_FILTER_IGNORE); + } c_text = memnew(LineEdit); hhb->add_child(c_text); + c_text->set_h_size_flags(SIZE_EXPAND_FILL); c_text->connect("text_entered", this, "_html_entered"); c_text->connect("focus_entered", this, "_focus_enter"); c_text->connect("focus_exited", this, "_html_focus_exit"); - text_type->set_text("#"); - c_text->set_h_size_flags(SIZE_EXPAND_FILL); - _update_controls(); updating = false; set_pick_color(Color(1, 1, 1)); + add_child(memnew(HSeparator)); + HBoxContainer *bbc = memnew(HBoxContainer); add_child(bbc); @@ -668,9 +736,9 @@ ColorPicker::ColorPicker() : preset->connect("draw", this, "_update_presets"); bt_add_preset = memnew(Button); - bt_add_preset->set_tooltip(TTR("Add current color as a preset")); - bt_add_preset->connect("pressed", this, "_add_preset_pressed"); bbc->add_child(bt_add_preset); + bt_add_preset->set_tooltip(TTR("Add current color as a preset.")); + bt_add_preset->connect("pressed", this, "_add_preset_pressed"); } ///////////////// @@ -781,9 +849,9 @@ void ColorPickerButton::_bind_methods() { ColorPickerButton::ColorPickerButton() { - //Initialization is now done deferred - //this improves performance in the inspector as the color picker - //can be expensive to initialize + // Initialization is now done deferred, + // this improves performance in the inspector as the color picker + // can be expensive to initialize. picker = NULL; popup = NULL; edit_alpha = true; diff --git a/scene/gui/color_picker.h b/scene/gui/color_picker.h index 0166da7118..b78844839a 100644 --- a/scene/gui/color_picker.h +++ b/scene/gui/color_picker.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -105,6 +105,9 @@ public: Color get_pick_color() const; void add_preset(const Color &p_color); + void erase_preset(const Color &p_color); + PoolColorArray get_presets() const; + void set_raw_mode(bool p_enabled); bool is_raw_mode() const; diff --git a/scene/gui/color_rect.cpp b/scene/gui/color_rect.cpp index 463f3911dc..df9b4e8498 100644 --- a/scene/gui/color_rect.cpp +++ b/scene/gui/color_rect.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/color_rect.h b/scene/gui/color_rect.h index a841008f76..d7f9ef275d 100644 --- a/scene/gui/color_rect.h +++ b/scene/gui/color_rect.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/container.cpp b/scene/gui/container.cpp index 7df03bf7c6..7f1ca58d58 100644 --- a/scene/gui/container.cpp +++ b/scene/gui/container.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -29,7 +29,7 @@ /*************************************************************************/ #include "container.h" -#include "message_queue.h" +#include "core/message_queue.h" #include "scene/scene_string_names.h" void Container::_child_minsize_changed() { @@ -95,6 +95,7 @@ void Container::_sort_children() { void Container::fit_child_in_rect(Control *p_child, const Rect2 &p_rect) { + ERR_FAIL_COND(!p_child); ERR_FAIL_COND(p_child->get_parent() != this); Size2 minsize = p_child->get_combined_minimum_size(); @@ -168,6 +169,19 @@ void Container::_notification(int p_what) { } } +String Container::get_configuration_warning() const { + + String warning = Control::get_configuration_warning(); + + if (get_class() == "Container" && get_script().is_null()) { + if (warning != String()) { + warning += "\n"; + } + warning += TTR("Container by itself serves no purpose unless a script configures it's children placement behavior.\nIf you dont't intend to add a script, then please use a plain 'Control' node instead."); + } + return warning; +} + void Container::_bind_methods() { ClassDB::bind_method(D_METHOD("_sort_children"), &Container::_sort_children); diff --git a/scene/gui/container.h b/scene/gui/container.h index c472162f58..80d3f6ee5d 100644 --- a/scene/gui/container.h +++ b/scene/gui/container.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -57,6 +57,8 @@ public: void fit_child_in_rect(Control *p_child, const Rect2 &p_rect); + virtual String get_configuration_warning() const; + Container(); }; diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp index e094a063be..86894ce070 100644 --- a/scene/gui/control.cpp +++ b/scene/gui/control.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -29,15 +29,15 @@ /*************************************************************************/ #include "control.h" -#include "project_settings.h" +#include "core/project_settings.h" #include "scene/main/canvas_layer.h" #include "scene/main/viewport.h" #include "servers/visual_server.h" -#include "message_queue.h" -#include "os/keyboard.h" -#include "os/os.h" -#include "print_string.h" +#include "core/message_queue.h" +#include "core/os/keyboard.h" +#include "core/os/os.h" +#include "core/print_string.h" #include "scene/gui/label.h" #include "scene/gui/panel.h" #include "scene/scene_string_names.h" @@ -206,65 +206,62 @@ bool Control::_set(const StringName &p_name, const Variant &p_value) { if (name.begins_with("custom_icons/")) { String dname = name.get_slicec('/', 1); + if (data.icon_override.has(dname)) { + data.icon_override[dname]->disconnect("changed", this, "_override_changed"); + } data.icon_override.erase(dname); notification(NOTIFICATION_THEME_CHANGED); - update(); } else if (name.begins_with("custom_shaders/")) { String dname = name.get_slicec('/', 1); + if (data.shader_override.has(dname)) { + data.shader_override[dname]->disconnect("changed", this, "_override_changed"); + } data.shader_override.erase(dname); notification(NOTIFICATION_THEME_CHANGED); - update(); } else if (name.begins_with("custom_styles/")) { String dname = name.get_slicec('/', 1); + if (data.style_override.has(dname)) { + data.style_override[dname]->disconnect("changed", this, "_override_changed"); + } data.style_override.erase(dname); notification(NOTIFICATION_THEME_CHANGED); - 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[dname]->disconnect("changed", this, "_override_changed"); } data.font_override.erase(dname); notification(NOTIFICATION_THEME_CHANGED); - update(); } else if (name.begins_with("custom_colors/")) { String dname = name.get_slicec('/', 1); data.color_override.erase(dname); notification(NOTIFICATION_THEME_CHANGED); - update(); } else if (name.begins_with("custom_constants/")) { String dname = name.get_slicec('/', 1); data.constant_override.erase(dname); notification(NOTIFICATION_THEME_CHANGED); - update(); } else return false; } else { if (name.begins_with("custom_icons/")) { String dname = name.get_slicec('/', 1); - notification(NOTIFICATION_THEME_CHANGED); add_icon_override(dname, p_value); } else if (name.begins_with("custom_shaders/")) { String dname = name.get_slicec('/', 1); add_shader_override(dname, p_value); - notification(NOTIFICATION_THEME_CHANGED); } else if (name.begins_with("custom_styles/")) { String dname = name.get_slicec('/', 1); add_style_override(dname, p_value); - notification(NOTIFICATION_THEME_CHANGED); } else if (name.begins_with("custom_fonts/")) { String dname = name.get_slicec('/', 1); add_font_override(dname, p_value); - notification(NOTIFICATION_THEME_CHANGED); } else if (name.begins_with("custom_colors/")) { String dname = name.get_slicec('/', 1); add_color_override(dname, p_value); - notification(NOTIFICATION_THEME_CHANGED); } else if (name.begins_with("custom_constants/")) { String dname = name.get_slicec('/', 1); add_constant_override(dname, p_value); - notification(NOTIFICATION_THEME_CHANGED); } else return false; } @@ -328,13 +325,15 @@ bool Control::_get(const StringName &p_name, Variant &r_ret) const { } void Control::_get_property_list(List<PropertyInfo> *p_list) const { - Ref<Theme> theme; + Ref<Theme> theme = Theme::get_default(); + /* Using the default theme since the properties below are meant for editor only if (data.theme.is_valid()) { theme = data.theme; } else { theme = Theme::get_default(); - } + + }*/ { List<StringName> names; @@ -449,6 +448,11 @@ void Control::_update_canvas_item_transform() { Transform2D xform = _get_internal_transform(); xform[2] += get_position(); + // We use a little workaround to avoid flickering when moving the pivot with _edit_set_pivot() + if (is_inside_tree() && Math::abs(Math::sin(data.rotation * 4.0f)) < 0.00001f && get_viewport()->is_snap_controls_to_pixels_enabled()) { + xform[2] = xform[2].round(); + } + VisualServer::get_singleton()->canvas_item_set_transform(get_canvas_item(), xform); } @@ -769,7 +773,7 @@ void Control::force_drag(const Variant &p_data, Control *p_control) { void Control::set_drag_preview(Control *p_control) { ERR_FAIL_COND(!is_inside_tree()); - ERR_FAIL_COND(get_viewport()->gui_is_dragging()); + ERR_FAIL_COND(!get_viewport()->gui_is_dragging()); get_viewport()->_gui_set_drag_preview(this, p_control); } @@ -1079,7 +1083,7 @@ bool Control::has_constant_override(const StringName &p_name) const { bool Control::has_icon(const StringName &p_name, const StringName &p_type) const { if (p_type == StringName() || p_type == "") { - if (has_icon_override(p_name) == true) + if (has_icon_override(p_name)) return true; } @@ -1113,7 +1117,7 @@ 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() || p_type == "") { - if (has_shader_override(p_name) == true) + if (has_shader_override(p_name)) return true; } @@ -1146,7 +1150,7 @@ 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() || p_type == "") { - if (has_stylebox_override(p_name) == true) + if (has_stylebox_override(p_name)) return true; } @@ -1179,7 +1183,7 @@ bool Control::has_stylebox(const StringName &p_name, const StringName &p_type) c bool Control::has_font(const StringName &p_name, const StringName &p_type) const { if (p_type == StringName() || p_type == "") { - if (has_font_override(p_name) == true) + if (has_font_override(p_name)) return true; } @@ -1213,7 +1217,7 @@ bool Control::has_font(const StringName &p_name, const StringName &p_type) const 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) + if (has_color_override(p_name)) return true; } @@ -1247,7 +1251,7 @@ bool Control::has_color(const StringName &p_name, const StringName &p_type) cons bool Control::has_constant(const StringName &p_name, const StringName &p_type) const { if (p_type == StringName() || p_type == "") { - if (has_constant_override(p_name) == true) + if (has_constant_override(p_name)) return true; } @@ -1334,11 +1338,6 @@ void Control::_size_changed() { new_size_cache.height = minimum_size.height; } - // We use a little workaround to avoid flickering when moving the pivot with _edit_set_pivot() - if (is_inside_tree() && Math::abs(Math::sin(data.rotation * 4.0f)) < 0.00001f && get_viewport()->is_snap_controls_to_pixels_enabled()) { - new_size_cache = new_size_cache.round(); - new_pos_cache = new_pos_cache.round(); - } bool pos_changed = new_pos_cache != data.pos_cache; bool size_changed = new_size_cache != data.size_cache; @@ -1738,10 +1737,10 @@ Rect2 Control::_compute_child_rect(const float p_anchors[4], const float p_margi void Control::_compute_margins(Rect2 p_rect, const float p_anchors[4], float (&r_margins)[4]) { Size2 parent_rect_size = get_parent_anchorable_rect().size; - r_margins[0] = Math::floor(p_rect.position.x - (p_anchors[0] * parent_rect_size.x)); - r_margins[1] = Math::floor(p_rect.position.y - (p_anchors[1] * parent_rect_size.y)); - r_margins[2] = Math::floor(p_rect.position.x + p_rect.size.x - (p_anchors[2] * parent_rect_size.x)); - r_margins[3] = Math::floor(p_rect.position.y + p_rect.size.y - (p_anchors[3] * parent_rect_size.y)); + r_margins[0] = p_rect.position.x - (p_anchors[0] * parent_rect_size.x); + r_margins[1] = p_rect.position.y - (p_anchors[1] * parent_rect_size.y); + r_margins[2] = p_rect.position.x + p_rect.size.x - (p_anchors[2] * parent_rect_size.x); + r_margins[3] = p_rect.position.y + p_rect.size.y - (p_anchors[3] * parent_rect_size.y); } void Control::set_position(const Size2 &p_point) { @@ -1798,51 +1797,63 @@ Rect2 Control::get_anchorable_rect() const { void Control::add_icon_override(const StringName &p_name, const Ref<Texture> &p_icon) { ERR_FAIL_COND(p_icon.is_null()); + if (data.icon_override.has(p_name)) { + data.icon_override[p_name]->disconnect("changed", this, "_override_changed"); + } data.icon_override[p_name] = p_icon; + if (data.icon_override[p_name].is_valid()) { + data.icon_override[p_name]->connect("changed", this, "_override_changed", Vector<Variant>(), CONNECT_REFERENCE_COUNTED); + } notification(NOTIFICATION_THEME_CHANGED); - update(); } void Control::add_shader_override(const StringName &p_name, const Ref<Shader> &p_shader) { ERR_FAIL_COND(p_shader.is_null()); + if (data.shader_override.has(p_name)) { + data.shader_override[p_name]->disconnect("changed", this, "_override_changed"); + } data.shader_override[p_name] = p_shader; + if (data.shader_override[p_name].is_valid()) { + data.shader_override[p_name]->connect("changed", this, "_override_changed", Vector<Variant>(), CONNECT_REFERENCE_COUNTED); + } notification(NOTIFICATION_THEME_CHANGED); - update(); } void Control::add_style_override(const StringName &p_name, const Ref<StyleBox> &p_style) { ERR_FAIL_COND(p_style.is_null()); + if (data.style_override.has(p_name)) { + data.style_override[p_name]->disconnect("changed", this, "_override_changed"); + } data.style_override[p_name] = p_style; + if (data.style_override[p_name].is_valid()) { + data.style_override[p_name]->connect("changed", this, "_override_changed", Vector<Variant>(), CONNECT_REFERENCE_COUNTED); + } + notification(NOTIFICATION_THEME_CHANGED); - update(); } 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]->disconnect("changed", this, "_override_changed"); } data.font_override[p_name] = p_font; - - if (p_font.is_valid()) { - _ref_font(p_font); + if (data.font_override[p_name].is_valid()) { + data.font_override[p_name]->connect("changed", this, "_override_changed", Vector<Variant>(), CONNECT_REFERENCE_COUNTED); } notification(NOTIFICATION_THEME_CHANGED); - update(); } void Control::add_color_override(const StringName &p_name, const Color &p_color) { data.color_override[p_name] = p_color; notification(NOTIFICATION_THEME_CHANGED); - update(); } void Control::add_constant_override(const StringName &p_name, int p_constant) { data.constant_override[p_name] = p_constant; notification(NOTIFICATION_THEME_CHANGED); - update(); } void Control::set_focus_mode(FocusMode p_focus_mode) { @@ -1993,7 +2004,7 @@ Control *Control::find_prev_valid_focus() const { if (!from) { - ERR_EXPLAIN("Prev focus node is not a control: " + n->get_name()); + ERR_EXPLAIN("Previous focus node is not a control: " + n->get_name()); ERR_FAIL_V(NULL); } } else { @@ -2062,8 +2073,11 @@ void Control::grab_focus() { if (!is_inside_tree()) { ERR_FAIL_COND(!is_inside_tree()); } - if (data.focus_mode == FOCUS_NONE) + + if (data.focus_mode == FOCUS_NONE) { + WARN_PRINT("This control can't grab focus. Use set_focus_mode() to allow a control to get focus."); return; + } get_viewport()->_gui_control_grab_focus(this); } @@ -2138,7 +2152,6 @@ void Control::_propagate_theme_changed(CanvasItem *p_at, Control *p_owner, bool c->data.theme_owner = p_owner; } c->notification(NOTIFICATION_THEME_CHANGED); - c->update(); } } @@ -2232,13 +2245,13 @@ String Control::_get_tooltip() const { void Control::set_focus_neighbour(Margin p_margin, const NodePath &p_neighbour) { - ERR_FAIL_INDEX(p_margin, 4); + ERR_FAIL_INDEX((int)p_margin, 4); data.focus_neighbour[p_margin] = p_neighbour; } NodePath Control::get_focus_neighbour(Margin p_margin) const { - ERR_FAIL_INDEX_V(p_margin, 4, NodePath()); + ERR_FAIL_INDEX_V((int)p_margin, 4, NodePath()); return data.focus_neighbour[p_margin]; } @@ -2545,32 +2558,10 @@ float Control::get_rotation_degrees() const { return Math::rad2deg(get_rotation()); } -//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() { +void Control::_override_changed() { - update(); notification(NOTIFICATION_THEME_CHANGED); - minimum_size_changed(); //fonts affect minimum size pretty much almost always + minimum_size_changed(); // overrides are likely to affect minimum size } void Control::set_pivot_offset(const Vector2 &p_pivot) { @@ -2730,7 +2721,7 @@ void Control::_bind_methods() { ClassDB::bind_method(D_METHOD("get_scale"), &Control::get_scale); ClassDB::bind_method(D_METHOD("get_pivot_offset"), &Control::get_pivot_offset); ClassDB::bind_method(D_METHOD("get_custom_minimum_size"), &Control::get_custom_minimum_size); - ClassDB::bind_method(D_METHOD("get_parent_area_size"), &Control::get_size); + ClassDB::bind_method(D_METHOD("get_parent_area_size"), &Control::get_parent_area_size); ClassDB::bind_method(D_METHOD("get_global_position"), &Control::get_global_position); ClassDB::bind_method(D_METHOD("get_rect"), &Control::get_rect); ClassDB::bind_method(D_METHOD("get_global_rect"), &Control::get_global_rect); @@ -2824,7 +2815,7 @@ void Control::_bind_methods() { ClassDB::bind_method(D_METHOD("_theme_changed"), &Control::_theme_changed); - ClassDB::bind_method(D_METHOD("_font_changed"), &Control::_font_changed); + ClassDB::bind_method(D_METHOD("_override_changed"), &Control::_override_changed); BIND_VMETHOD(MethodInfo("_gui_input", PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent"))); BIND_VMETHOD(MethodInfo(Variant::VECTOR2, "_get_minimum_size")); @@ -2841,47 +2832,47 @@ void Control::_bind_methods() { ADD_PROPERTYI(PropertyInfo(Variant::REAL, "anchor_bottom", PROPERTY_HINT_RANGE, "0,1,0.01"), "_set_anchor", "get_anchor", MARGIN_BOTTOM); ADD_GROUP("Margin", "margin_"); - ADD_PROPERTYINZ(PropertyInfo(Variant::INT, "margin_left", PROPERTY_HINT_RANGE, "-4096,4096"), "set_margin", "get_margin", MARGIN_LEFT); - ADD_PROPERTYINZ(PropertyInfo(Variant::INT, "margin_top", PROPERTY_HINT_RANGE, "-4096,4096"), "set_margin", "get_margin", MARGIN_TOP); - ADD_PROPERTYINZ(PropertyInfo(Variant::INT, "margin_right", PROPERTY_HINT_RANGE, "-4096,4096"), "set_margin", "get_margin", MARGIN_RIGHT); - ADD_PROPERTYINZ(PropertyInfo(Variant::INT, "margin_bottom", PROPERTY_HINT_RANGE, "-4096,4096"), "set_margin", "get_margin", MARGIN_BOTTOM); + ADD_PROPERTYI(PropertyInfo(Variant::INT, "margin_left", PROPERTY_HINT_RANGE, "-4096,4096"), "set_margin", "get_margin", MARGIN_LEFT); + ADD_PROPERTYI(PropertyInfo(Variant::INT, "margin_top", PROPERTY_HINT_RANGE, "-4096,4096"), "set_margin", "get_margin", MARGIN_TOP); + ADD_PROPERTYI(PropertyInfo(Variant::INT, "margin_right", PROPERTY_HINT_RANGE, "-4096,4096"), "set_margin", "get_margin", MARGIN_RIGHT); + ADD_PROPERTYI(PropertyInfo(Variant::INT, "margin_bottom", PROPERTY_HINT_RANGE, "-4096,4096"), "set_margin", "get_margin", MARGIN_BOTTOM); ADD_GROUP("Grow Direction", "grow_"); - ADD_PROPERTYNO(PropertyInfo(Variant::INT, "grow_horizontal", PROPERTY_HINT_ENUM, "Begin,End,Both"), "set_h_grow_direction", "get_h_grow_direction"); - ADD_PROPERTYNO(PropertyInfo(Variant::INT, "grow_vertical", PROPERTY_HINT_ENUM, "Begin,End,Both"), "set_v_grow_direction", "get_v_grow_direction"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "grow_horizontal", PROPERTY_HINT_ENUM, "Begin,End,Both"), "set_h_grow_direction", "get_h_grow_direction"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "grow_vertical", PROPERTY_HINT_ENUM, "Begin,End,Both"), "set_v_grow_direction", "get_v_grow_direction"); ADD_GROUP("Rect", "rect_"); - ADD_PROPERTYNZ(PropertyInfo(Variant::VECTOR2, "rect_position", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_position", "get_position"); - ADD_PROPERTYNZ(PropertyInfo(Variant::VECTOR2, "rect_global_position", PROPERTY_HINT_NONE, "", 0), "set_global_position", "get_global_position"); - ADD_PROPERTYNZ(PropertyInfo(Variant::VECTOR2, "rect_size", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_size", "get_size"); - ADD_PROPERTYNZ(PropertyInfo(Variant::VECTOR2, "rect_min_size"), "set_custom_minimum_size", "get_custom_minimum_size"); - ADD_PROPERTYNZ(PropertyInfo(Variant::REAL, "rect_rotation", PROPERTY_HINT_RANGE, "-1080,1080,0.01"), "set_rotation_degrees", "get_rotation_degrees"); - ADD_PROPERTYNO(PropertyInfo(Variant::VECTOR2, "rect_scale"), "set_scale", "get_scale"); - ADD_PROPERTYNO(PropertyInfo(Variant::VECTOR2, "rect_pivot_offset"), "set_pivot_offset", "get_pivot_offset"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "rect_position", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_position", "get_position"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "rect_global_position", PROPERTY_HINT_NONE, "", 0), "set_global_position", "get_global_position"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "rect_size", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_size", "get_size"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "rect_min_size"), "set_custom_minimum_size", "get_custom_minimum_size"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "rect_rotation", PROPERTY_HINT_RANGE, "-1080,1080,0.01"), "set_rotation_degrees", "get_rotation_degrees"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "rect_scale"), "set_scale", "get_scale"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "rect_pivot_offset"), "set_pivot_offset", "get_pivot_offset"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "rect_clip_content"), "set_clip_contents", "is_clipping_contents"); ADD_GROUP("Hint", "hint_"); - ADD_PROPERTYNZ(PropertyInfo(Variant::STRING, "hint_tooltip", PROPERTY_HINT_MULTILINE_TEXT), "set_tooltip", "_get_tooltip"); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "hint_tooltip", PROPERTY_HINT_MULTILINE_TEXT), "set_tooltip", "_get_tooltip"); ADD_GROUP("Focus", "focus_"); - ADD_PROPERTYINZ(PropertyInfo(Variant::NODE_PATH, "focus_neighbour_left", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Control"), "set_focus_neighbour", "get_focus_neighbour", MARGIN_LEFT); - ADD_PROPERTYINZ(PropertyInfo(Variant::NODE_PATH, "focus_neighbour_top", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Control"), "set_focus_neighbour", "get_focus_neighbour", MARGIN_TOP); - ADD_PROPERTYINZ(PropertyInfo(Variant::NODE_PATH, "focus_neighbour_right", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Control"), "set_focus_neighbour", "get_focus_neighbour", MARGIN_RIGHT); - ADD_PROPERTYINZ(PropertyInfo(Variant::NODE_PATH, "focus_neighbour_bottom", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Control"), "set_focus_neighbour", "get_focus_neighbour", MARGIN_BOTTOM); - ADD_PROPERTYNZ(PropertyInfo(Variant::NODE_PATH, "focus_next", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Control"), "set_focus_next", "get_focus_next"); - ADD_PROPERTYNZ(PropertyInfo(Variant::NODE_PATH, "focus_previous", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Control"), "set_focus_previous", "get_focus_previous"); - ADD_PROPERTYNZ(PropertyInfo(Variant::INT, "focus_mode", PROPERTY_HINT_ENUM, "None,Click,All"), "set_focus_mode", "get_focus_mode"); + ADD_PROPERTYI(PropertyInfo(Variant::NODE_PATH, "focus_neighbour_left", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Control"), "set_focus_neighbour", "get_focus_neighbour", MARGIN_LEFT); + ADD_PROPERTYI(PropertyInfo(Variant::NODE_PATH, "focus_neighbour_top", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Control"), "set_focus_neighbour", "get_focus_neighbour", MARGIN_TOP); + ADD_PROPERTYI(PropertyInfo(Variant::NODE_PATH, "focus_neighbour_right", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Control"), "set_focus_neighbour", "get_focus_neighbour", MARGIN_RIGHT); + ADD_PROPERTYI(PropertyInfo(Variant::NODE_PATH, "focus_neighbour_bottom", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Control"), "set_focus_neighbour", "get_focus_neighbour", MARGIN_BOTTOM); + ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "focus_next", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Control"), "set_focus_next", "get_focus_next"); + ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "focus_previous", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Control"), "set_focus_previous", "get_focus_previous"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "focus_mode", PROPERTY_HINT_ENUM, "None,Click,All"), "set_focus_mode", "get_focus_mode"); ADD_GROUP("Mouse", "mouse_"); ADD_PROPERTY(PropertyInfo(Variant::INT, "mouse_filter", PROPERTY_HINT_ENUM, "Stop,Pass,Ignore"), "set_mouse_filter", "get_mouse_filter"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "mouse_default_cursor_shape", PROPERTY_HINT_ENUM, "Arrow,Ibeam,Pointing hand,Cross,Wait,Busy,Drag,Can drop,Forbidden,Vertical resize,Horizontal resize,Secondary diagonal resize,Main diagonal resize,Move,Vertial split,Horizontal split,Help"), "set_default_cursor_shape", "get_default_cursor_shape"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "mouse_default_cursor_shape", PROPERTY_HINT_ENUM, "Arrow,Ibeam,Pointing hand,Cross,Wait,Busy,Drag,Can drop,Forbidden,Vertical resize,Horizontal resize,Secondary diagonal resize,Main diagonal resize,Move,Vertical split,Horizontal split,Help"), "set_default_cursor_shape", "get_default_cursor_shape"); ADD_GROUP("Size Flags", "size_flags_"); ADD_PROPERTY(PropertyInfo(Variant::INT, "size_flags_horizontal", PROPERTY_HINT_FLAGS, "Fill,Expand,Shrink Center,Shrink End"), "set_h_size_flags", "get_h_size_flags"); ADD_PROPERTY(PropertyInfo(Variant::INT, "size_flags_vertical", PROPERTY_HINT_FLAGS, "Fill,Expand,Shrink Center,Shrink End"), "set_v_size_flags", "get_v_size_flags"); - ADD_PROPERTYNO(PropertyInfo(Variant::REAL, "size_flags_stretch_ratio", PROPERTY_HINT_RANGE, "0,128,0.01"), "set_stretch_ratio", "get_stretch_ratio"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "size_flags_stretch_ratio", PROPERTY_HINT_RANGE, "0,128,0.01"), "set_stretch_ratio", "get_stretch_ratio"); ADD_GROUP("Theme", ""); - ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT, "theme", PROPERTY_HINT_RESOURCE_TYPE, "Theme"), "set_theme", "get_theme"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "theme", PROPERTY_HINT_RESOURCE_TYPE, "Theme"), "set_theme", "get_theme"); ADD_GROUP("", ""); BIND_ENUM_CONSTANT(FOCUS_NONE); @@ -2956,7 +2947,7 @@ void Control::_bind_methods() { BIND_ENUM_CONSTANT(ANCHOR_END); ADD_SIGNAL(MethodInfo("resized")); - ADD_SIGNAL(MethodInfo("gui_input", PropertyInfo(Variant::OBJECT, "ev", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent"))); + ADD_SIGNAL(MethodInfo("gui_input", PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent"))); ADD_SIGNAL(MethodInfo("mouse_entered")); ADD_SIGNAL(MethodInfo("mouse_exited")); ADD_SIGNAL(MethodInfo("focus_entered")); diff --git a/scene/gui/control.h b/scene/gui/control.h index c6bd2f097d..5e33f6ba43 100644 --- a/scene/gui/control.h +++ b/scene/gui/control.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,13 +31,13 @@ #ifndef CONTROL_H #define CONTROL_H -#include "rid.h" +#include "core/math/transform_2d.h" +#include "core/rid.h" #include "scene/2d/canvas_item.h" #include "scene/gui/shortcut.h" #include "scene/main/node.h" #include "scene/main/timer.h" #include "scene/resources/theme.h" -#include "transform_2d.h" /** @author Juan Linietsky <reduzio@gmail.com> */ @@ -76,7 +76,7 @@ public: SIZE_EXPAND = 2, SIZE_EXPAND_FILL = SIZE_EXPAND | SIZE_FILL, SIZE_SHRINK_CENTER = 4, //ignored by expand or fill - SIZE_SHRINK_END = 8, //ignored by expand or fil + SIZE_SHRINK_END = 8, //ignored by expand or fill }; @@ -207,7 +207,6 @@ private: HashMap<StringName, Ref<Font> > font_override; HashMap<StringName, Color> color_override; HashMap<StringName, int> constant_override; - Map<Ref<Font>, int> font_refcount; } data; @@ -234,9 +233,7 @@ private: void _size_changed(); String _get_tooltip() const; - void _ref_font(Ref<Font> p_sc); - void _unref_font(Ref<Font> p_sc); - void _font_changed(); + void _override_changed(); void _update_canvas_item_transform(); diff --git a/scene/gui/dialogs.cpp b/scene/gui/dialogs.cpp index d9737fa21a..89f3d509d0 100644 --- a/scene/gui/dialogs.cpp +++ b/scene/gui/dialogs.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -29,9 +29,9 @@ /*************************************************************************/ #include "dialogs.h" +#include "core/print_string.h" +#include "core/translation.h" #include "line_edit.h" -#include "print_string.h" -#include "translation.h" #ifdef TOOLS_ENABLED #include "editor/editor_node.h" @@ -535,7 +535,7 @@ void AcceptDialog::_bind_methods() { ADD_SIGNAL(MethodInfo("custom_action", PropertyInfo(Variant::STRING, "action"))); ADD_GROUP("Dialog", "dialog"); - ADD_PROPERTYNZ(PropertyInfo(Variant::STRING, "dialog_text", PROPERTY_HINT_MULTILINE_TEXT, "", PROPERTY_USAGE_DEFAULT_INTL), "set_text", "get_text"); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "dialog_text", PROPERTY_HINT_MULTILINE_TEXT, "", PROPERTY_USAGE_DEFAULT_INTL), "set_text", "get_text"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "dialog_hide_on_ok"), "set_hide_on_ok", "get_hide_on_ok"); } diff --git a/scene/gui/dialogs.h b/scene/gui/dialogs.h index feb080dd06..4b89ac54c5 100644 --- a/scene/gui/dialogs.h +++ b/scene/gui/dialogs.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/file_dialog.cpp b/scene/gui/file_dialog.cpp index 9bddaa7d29..059e59ea21 100644 --- a/scene/gui/file_dialog.cpp +++ b/scene/gui/file_dialog.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -29,8 +29,9 @@ /*************************************************************************/ #include "file_dialog.h" -#include "os/keyboard.h" -#include "print_string.h" + +#include "core/os/keyboard.h" +#include "core/print_string.h" #include "scene/gui/label.h" FileDialog::GetIconFunc FileDialog::get_icon_func = NULL; @@ -330,6 +331,10 @@ void FileDialog::deselect_items() { case MODE_OPEN_DIR: get_ok()->set_text(RTR("Select Current Folder")); break; + case MODE_OPEN_ANY: + case MODE_SAVE_FILE: + // FIXME: Implement, or refactor to avoid duplication with set_mode + break; } } } @@ -349,7 +354,7 @@ void FileDialog::_tree_selected() { file->set_text(d["name"]); } else if (mode == MODE_OPEN_DIR) { - get_ok()->set_text(RTR("Select this Folder")); + get_ok()->set_text(RTR("Select This Folder")); } get_ok()->set_disabled(_is_open_should_be_disabled()); @@ -592,7 +597,7 @@ void FileDialog::set_current_file(const String &p_file) { int lp = p_file.find_last("."); if (lp != -1) { file->select(0, lp); - if (file->is_inside_tree()) + if (file->is_inside_tree() && !get_tree()->is_node_being_edited(file)) file->grab_focus(); } } @@ -856,7 +861,7 @@ FileDialog::FileDialog() { HBoxContainer *hbc = memnew(HBoxContainer); dir_up = memnew(ToolButton); - dir_up->set_tooltip(RTR("Go to parent folder")); + dir_up->set_tooltip(RTR("Go to parent folder.")); hbc->add_child(dir_up); dir_up->connect("pressed", this, "_go_up"); @@ -866,6 +871,7 @@ FileDialog::FileDialog() { dir->set_h_size_flags(SIZE_EXPAND_FILL); refresh = memnew(ToolButton); + refresh->set_tooltip(RTR("Refresh")); refresh->connect("pressed", this, "_update_file_list"); hbc->add_child(refresh); diff --git a/scene/gui/file_dialog.h b/scene/gui/file_dialog.h index 3227f1c3a8..85edac0b12 100644 --- a/scene/gui/file_dialog.h +++ b/scene/gui/file_dialog.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* 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 @@ #define FILE_DIALOG_H #include "box_container.h" -#include "os/dir_access.h" +#include "core/os/dir_access.h" #include "scene/gui/dialogs.h" #include "scene/gui/line_edit.h" #include "scene/gui/option_button.h" diff --git a/scene/gui/gradient_edit.cpp b/scene/gui/gradient_edit.cpp index e82c0c4ad1..cfbc9d6d18 100644 --- a/scene/gui/gradient_edit.cpp +++ b/scene/gui/gradient_edit.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -29,7 +29,10 @@ /*************************************************************************/ #include "gradient_edit.h" -#include "os/keyboard.h" +#include "core/os/keyboard.h" +#include "editor/editor_scale.h" + +#define SPACING (3 * EDSCALE) GradientEdit::GradientEdit() { grabbed = -1; @@ -49,11 +52,15 @@ GradientEdit::GradientEdit() { int GradientEdit::_get_point_from_pos(int x) { int result = -1; - int total_w = get_size().width - get_size().height - 3; + int total_w = get_size().width - get_size().height - SPACING; + float min_distance = 1e20; for (int i = 0; i < points.size(); i++) { //Check if we clicked at point - if (ABS(x - points[i].offset * total_w + 1) < (POINT_WIDTH / 2 + 1)) { + float distance = ABS(x - points[i].offset * total_w); + float min = (POINT_WIDTH / 2 * 1.7); //make it easier to grab + if (distance <= min && distance < min_distance) { result = i; + min_distance = distance; } } return result; @@ -63,7 +70,16 @@ void GradientEdit::_show_color_picker() { if (grabbed == -1) return; picker->set_pick_color(points[grabbed].color); - popup->set_position(get_global_position() - popup->get_combined_minimum_size()); + Size2 minsize = popup->get_combined_minimum_size(); + bool show_above = false; + if (get_global_position().y + get_size().y + minsize.y > get_viewport_rect().size.y) { + show_above = true; + } + if (show_above) { + popup->set_position(get_global_position() - Vector2(0, minsize.y)); + } else { + popup->set_position(get_global_position() + Vector2(0, get_size().y)); + } popup->popup(); } @@ -112,7 +128,7 @@ void GradientEdit::_gui_input(const Ref<InputEvent> &p_event) { grabbed = _get_point_from_pos(x); if (grabbed != -1) { - int total_w = get_size().width - get_size().height - 3; + int total_w = get_size().width - get_size().height - SPACING; Gradient::Point newPoint = points[grabbed]; newPoint.offset = CLAMP(x / float(total_w), 0, 1); @@ -130,14 +146,15 @@ void GradientEdit::_gui_input(const Ref<InputEvent> &p_event) { } } + //select if (mb.is_valid() && mb->get_button_index() == 1 && mb->is_pressed()) { update(); int x = mb->get_position().x; - int total_w = get_size().width - get_size().height - 3; + int total_w = get_size().width - get_size().height - SPACING; //Check if color selector was clicked. - if (x > total_w + 3) { + if (x > total_w + SPACING) { _show_color_picker(); return; } @@ -211,7 +228,7 @@ void GradientEdit::_gui_input(const Ref<InputEvent> &p_event) { if (mm.is_valid() && grabbing) { - int total_w = get_size().width - get_size().height - 3; + int total_w = get_size().width - get_size().height - SPACING; int x = mm->get_position().x; @@ -219,23 +236,23 @@ void GradientEdit::_gui_input(const Ref<InputEvent> &p_event) { //Snap to nearest point if holding shift if (mm->get_shift()) { - float snap_treshhold = 0.03; - float smallest_ofs = snap_treshhold; - bool founded = false; - int nearest_point; + float snap_threshold = 0.03; + float smallest_ofs = snap_threshold; + bool found = false; + int nearest_point = 0; for (int i = 0; i < points.size(); ++i) { if (i != grabbed) { float temp_ofs = ABS(points[i].offset - newofs); if (temp_ofs < smallest_ofs) { smallest_ofs = temp_ofs; nearest_point = i; - if (founded) + if (found) break; - founded = true; + found = true; } } } - if (founded) { + if (found) { if (points[nearest_point].offset < newofs) newofs = points[nearest_point].offset + 0.00001; else @@ -286,7 +303,7 @@ void GradientEdit::_notification(int p_what) { if (w == 0 || h == 0) return; //Safety check. We have division by 'h'. And in any case there is nothing to draw with such size - int total_w = get_size().width - get_size().height - 3; + int total_w = get_size().width - get_size().height - SPACING; //Draw checker pattern for ramp _draw_checker(0, 0, total_w, h); @@ -335,27 +352,36 @@ void GradientEdit::_notification(int p_what) { //Draw point markers for (int i = 0; i < points.size(); i++) { - Color col = i == grabbed ? Color(1, 0.0, 0.0, 0.9) : points[i].color.contrasted(); + Color col = points[i].color.contrasted(); col.a = 0.9; draw_line(Vector2(points[i].offset * total_w, 0), Vector2(points[i].offset * total_w, h / 2), col); - draw_rect(Rect2(points[i].offset * total_w - POINT_WIDTH / 2, h / 2, POINT_WIDTH, h / 2), Color(0.6, 0.6, 0.6, i == grabbed ? 0.9 : 0.4)); - draw_line(Vector2(points[i].offset * total_w - POINT_WIDTH / 2, h / 2), Vector2(points[i].offset * total_w - POINT_WIDTH / 2, h - 1), col); - draw_line(Vector2(points[i].offset * total_w + POINT_WIDTH / 2, h / 2), Vector2(points[i].offset * total_w + POINT_WIDTH / 2, h - 1), col); - draw_line(Vector2(points[i].offset * total_w - POINT_WIDTH / 2, h / 2), Vector2(points[i].offset * total_w + POINT_WIDTH / 2, h / 2), col); - draw_line(Vector2(points[i].offset * total_w - POINT_WIDTH / 2, h - 1), Vector2(points[i].offset * total_w + POINT_WIDTH / 2, h - 1), col); + Rect2 rect = Rect2(points[i].offset * total_w - POINT_WIDTH / 2, h / 2, POINT_WIDTH, h / 2); + draw_rect(rect, points[i].color, true); + draw_rect(rect, col, false); + if (grabbed == i) { + rect = rect.grow(-1); + if (has_focus()) { + draw_rect(rect, Color(1, 0, 0, 0.9), false); + } else { + draw_rect(rect, Color(0.6, 0, 0, 0.9), false); + } + + rect = rect.grow(-1); + draw_rect(rect, col, false); + } } //Draw "button" for color selector - _draw_checker(total_w + 3, 0, h, h); + _draw_checker(total_w + SPACING, 0, h, h); if (grabbed != -1) { //Draw with selection color - draw_rect(Rect2(total_w + 3, 0, h, h), points[grabbed].color); + draw_rect(Rect2(total_w + SPACING, 0, h, h), points[grabbed].color); } else { //if no color selected draw grey color with 'X' on top. - draw_rect(Rect2(total_w + 3, 0, h, h), Color(0.5, 0.5, 0.5, 1)); - draw_line(Vector2(total_w + 3, 0), Vector2(total_w + 3 + h, h), Color(1, 1, 1, 0.6)); - draw_line(Vector2(total_w + 3, h), Vector2(total_w + 3 + h, 0), Color(1, 1, 1, 0.6)); + draw_rect(Rect2(total_w + SPACING, 0, h, h), Color(0.5, 0.5, 0.5, 1)); + draw_line(Vector2(total_w + SPACING, 0), Vector2(total_w + SPACING + h, h), Color(1, 1, 1, 0.6)); + draw_line(Vector2(total_w + SPACING, h), Vector2(total_w + SPACING + h, 0), Color(1, 1, 1, 0.6)); } //Draw borders around color ramp if in focus diff --git a/scene/gui/gradient_edit.h b/scene/gui/gradient_edit.h index e7834ea0de..662278a17b 100644 --- a/scene/gui/gradient_edit.h +++ b/scene/gui/gradient_edit.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -33,10 +33,10 @@ #include "scene/gui/color_picker.h" #include "scene/gui/popup.h" -#include "scene/resources/color_ramp.h" #include "scene/resources/default_theme/theme_data.h" +#include "scene/resources/gradient.h" -#define POINT_WIDTH 8 +#define POINT_WIDTH (8 * EDSCALE) class GradientEdit : public Control { diff --git a/scene/gui/graph_edit.cpp b/scene/gui/graph_edit.cpp index a7163adbe6..68e734502b 100644 --- a/scene/gui/graph_edit.cpp +++ b/scene/gui/graph_edit.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,10 +30,14 @@ #include "graph_edit.h" -#include "os/input.h" -#include "os/keyboard.h" +#include "core/os/input.h" +#include "core/os/keyboard.h" #include "scene/gui/box_container.h" +#ifdef TOOLS_ENABLED +#include "editor/editor_scale.h" +#endif + #define ZOOM_SCALE 1.2 #define MIN_ZOOM (((1 / ZOOM_SCALE) / ZOOM_SCALE) / ZOOM_SCALE) @@ -217,8 +221,8 @@ void GraphEdit::_graph_node_raised(Node *p_gn) { } int first_not_comment = 0; for (int i = 0; i < get_child_count(); i++) { - GraphNode *gn = Object::cast_to<GraphNode>(get_child(i)); - if (gn && !gn->is_comment()) { + GraphNode *gn2 = Object::cast_to<GraphNode>(get_child(i)); + if (gn2 && !gn2->is_comment()) { first_not_comment = i; break; } @@ -257,8 +261,9 @@ void GraphEdit::add_child_notify(Node *p_child) { void GraphEdit::remove_child_notify(Node *p_child) { Control::remove_child_notify(p_child); - - top_layer->call_deferred("raise"); //top layer always on top! + if (is_inside_tree()) { + top_layer->call_deferred("raise"); //top layer always on top! + } GraphNode *gn = Object::cast_to<GraphNode>(p_child); if (gn) { gn->disconnect("offset_changed", this, "_graph_node_moved"); @@ -406,7 +411,7 @@ void GraphEdit::_top_layer_input(const Ref<InputEvent> &p_ev) { connecting_color = Object::cast_to<GraphNode>(to)->get_connection_input_color(E->get().to_port); connecting_target = false; connecting_to = pos; - just_disconected = true; + just_disconnected = 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 @@ -427,7 +432,7 @@ void GraphEdit::_top_layer_input(const Ref<InputEvent> &p_ev) { connecting_color = gn->get_connection_output_color(j); connecting_target = false; connecting_to = pos; - just_disconected = false; + just_disconnected = false; return; } } @@ -453,7 +458,7 @@ void GraphEdit::_top_layer_input(const Ref<InputEvent> &p_ev) { connecting_color = Object::cast_to<GraphNode>(fr)->get_connection_output_color(E->get().from_port); connecting_target = false; connecting_to = pos; - just_disconected = true; + just_disconnected = 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 @@ -474,7 +479,7 @@ void GraphEdit::_top_layer_input(const Ref<InputEvent> &p_ev) { connecting_color = gn->get_connection_input_color(j); connecting_target = false; connecting_to = pos; - just_disconected = true; + just_disconnected = true; return; } @@ -544,7 +549,7 @@ void GraphEdit::_top_layer_input(const Ref<InputEvent> &p_ev) { } emit_signal("connection_request", from, from_slot, to, to_slot); - } else if (!just_disconected) { + } else if (!just_disconnected) { String from = connecting_from; int from_slot = connecting_index; Vector2 ofs = Vector2(mb->get_position().x, mb->get_position().y); @@ -665,11 +670,15 @@ void GraphEdit::_draw_cos_line(CanvasItem *p_where, const Vector2 &p_from, const Vector<Color> colors; points.push_back(p_from); colors.push_back(p_color); - _bake_segment2d(points, colors, 0, 1, p_from, c1, p_to, c2, 0, 3, 9, 8, p_color, p_to_color, lines); + _bake_segment2d(points, colors, 0, 1, p_from, c1, p_to, c2, 0, 3, 9, 3, p_color, p_to_color, lines); points.push_back(p_to); colors.push_back(p_to_color); +#ifdef TOOLS_ENABLED + p_where->draw_polyline_colors(points, colors, Math::floor(2 * EDSCALE), true); +#else p_where->draw_polyline_colors(points, colors, 2, true); +#endif } void GraphEdit::_connections_layer_draw() { @@ -950,33 +959,33 @@ void GraphEdit::_gui_input(const Ref<InputEvent> &p_ev) { previus_selected.clear(); for (int i = get_child_count() - 1; i >= 0; i--) { - GraphNode *gn = Object::cast_to<GraphNode>(get_child(i)); - if (!gn || !gn->is_selected()) + GraphNode *gn2 = Object::cast_to<GraphNode>(get_child(i)); + if (!gn2 || !gn2->is_selected()) continue; - previus_selected.push_back(gn); + previus_selected.push_back(gn2); } } else if (b->get_shift()) { box_selection_mode_aditive = false; previus_selected.clear(); for (int i = get_child_count() - 1; i >= 0; i--) { - GraphNode *gn = Object::cast_to<GraphNode>(get_child(i)); - if (!gn || !gn->is_selected()) + GraphNode *gn2 = Object::cast_to<GraphNode>(get_child(i)); + if (!gn2 || !gn2->is_selected()) continue; - previus_selected.push_back(gn); + previus_selected.push_back(gn2); } } else { box_selection_mode_aditive = true; previus_selected.clear(); for (int i = get_child_count() - 1; i >= 0; i--) { - GraphNode *gn = Object::cast_to<GraphNode>(get_child(i)); - if (!gn) + GraphNode *gn2 = Object::cast_to<GraphNode>(get_child(i)); + if (!gn2) continue; - gn->set_selected(false); + gn2->set_selected(false); } } } @@ -1042,7 +1051,7 @@ void GraphEdit::set_connection_activity(const StringName &p_from, int p_from_por if (E->get().from == p_from && E->get().from_port == p_from_port && E->get().to == p_to && E->get().to_port == p_to_port) { - if (ABS(E->get().activity != p_activity)) { + if (ABS(E->get().activity - p_activity) < CMP_EPSILON) { //update only if changed top_layer->update(); connections_layer->update(); @@ -1277,9 +1286,9 @@ void GraphEdit::_bind_methods() { 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("popup_request", PropertyInfo(Variant::VECTOR2, "position"))); ADD_SIGNAL(MethodInfo("duplicate_nodes_request")); - ADD_SIGNAL(MethodInfo("node_selected", PropertyInfo(Variant::OBJECT, "node"))); + ADD_SIGNAL(MethodInfo("node_selected", PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, "Node"))); ADD_SIGNAL(MethodInfo("connection_to_empty", PropertyInfo(Variant::STRING, "from"), PropertyInfo(Variant::INT, "from_slot"), PropertyInfo(Variant::VECTOR2, "release_position"))); ADD_SIGNAL(MethodInfo("delete_nodes_request")); ADD_SIGNAL(MethodInfo("_begin_node_move")); @@ -1304,7 +1313,7 @@ GraphEdit::GraphEdit() { 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 + connections_layer->set_disable_visibility_clip(true); // so it can draw freely and be offset connections_layer->set_mouse_filter(MOUSE_FILTER_IGNORE); h_scroll = memnew(HScrollBar); @@ -1339,21 +1348,25 @@ GraphEdit::GraphEdit() { zoom_minus = memnew(ToolButton); zoom_hb->add_child(zoom_minus); + zoom_minus->set_tooltip(RTR("Zoom Out")); zoom_minus->connect("pressed", this, "_zoom_minus"); zoom_minus->set_focus_mode(FOCUS_NONE); zoom_reset = memnew(ToolButton); zoom_hb->add_child(zoom_reset); + zoom_reset->set_tooltip(RTR("Zoom Reset")); zoom_reset->connect("pressed", this, "_zoom_reset"); zoom_reset->set_focus_mode(FOCUS_NONE); zoom_plus = memnew(ToolButton); zoom_hb->add_child(zoom_plus); + zoom_plus->set_tooltip(RTR("Zoom In")); zoom_plus->connect("pressed", this, "_zoom_plus"); zoom_plus->set_focus_mode(FOCUS_NONE); snap_button = memnew(ToolButton); snap_button->set_toggle_mode(true); + snap_button->set_tooltip(RTR("Enable snap and show grid.")); snap_button->connect("pressed", this, "_snap_toggled"); snap_button->set_pressed(true); snap_button->set_focus_mode(FOCUS_NONE); @@ -1368,6 +1381,6 @@ GraphEdit::GraphEdit() { zoom_hb->add_child(snap_amount); setting_scroll_ofs = false; - just_disconected = false; + just_disconnected = false; set_clip_contents(true); } diff --git a/scene/gui/graph_edit.h b/scene/gui/graph_edit.h index 31a449eb59..de826bf505 100644 --- a/scene/gui/graph_edit.h +++ b/scene/gui/graph_edit.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -94,7 +94,7 @@ private: Vector2 connecting_to; String connecting_target_to; int connecting_target_index; - bool just_disconected; + bool just_disconnected; bool dragging; bool just_selected; diff --git a/scene/gui/graph_node.cpp b/scene/gui/graph_node.cpp index 24857d49fa..8c588109d6 100644 --- a/scene/gui/graph_node.cpp +++ b/scene/gui/graph_node.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -29,7 +29,8 @@ /*************************************************************************/ #include "graph_node.h" -#include "method_bind_ext.gen.inc" + +#include "core/method_bind_ext.gen.inc" bool GraphNode::_set(const StringName &p_name, const Variant &p_value) { @@ -191,97 +192,104 @@ bool GraphNode::has_point(const Point2 &p_point) const { void GraphNode::_notification(int p_what) { - if (p_what == NOTIFICATION_DRAW) { + switch (p_what) { + case NOTIFICATION_DRAW: { - Ref<StyleBox> sb; + Ref<StyleBox> sb; - if (comment) { - sb = get_stylebox(selected ? "commentfocus" : "comment"); + if (comment) { + sb = get_stylebox(selected ? "commentfocus" : "comment"); - } else { + } else { - sb = get_stylebox(selected ? "selectedframe" : "frame"); - } + 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"); - int close_h_offset = get_constant("close_h_offset"); - Color close_color = get_color("close_color"); - Ref<Font> title_font = get_font("title_font"); - int title_offset = get_constant("title_offset"); - int title_h_offset = get_constant("title_h_offset"); - Color title_color = get_color("title_color"); - 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; - } + //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"); + int close_h_offset = get_constant("close_h_offset"); + Color close_color = get_color("close_color"); + Ref<Font> title_font = get_font("title_font"); + int title_offset = get_constant("title_offset"); + int title_h_offset = get_constant("title_h_offset"); + Color title_color = get_color("title_color"); + 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; + int w = get_size().width - sb->get_minimum_size().x; - if (show_close) - w -= close->get_width(); + if (show_close) + w -= close->get_width(); - draw_string(title_font, Point2(sb->get_margin(MARGIN_LEFT) + title_h_offset, -title_font->get_height() + title_font->get_ascent() + title_offset), title, title_color, w); - if (show_close) { - Vector2 cpos = Point2(w + sb->get_margin(MARGIN_LEFT) + close_h_offset, -close->get_height() + close_offset); - draw_texture(close, cpos, close_color); - close_rect.position = cpos; - close_rect.size = close->get_size(); - } else { - close_rect = Rect2(); - } + draw_string(title_font, Point2(sb->get_margin(MARGIN_LEFT) + title_h_offset, -title_font->get_height() + title_font->get_ascent() + title_offset), title, title_color, w); + if (show_close) { + Vector2 cpos = Point2(w + sb->get_margin(MARGIN_LEFT) + close_h_offset, -close->get_height() + close_offset); + draw_texture(close, cpos, close_color); + close_rect.position = cpos; + close_rect.size = close->get_size(); + } else { + close_rect = Rect2(); + } - for (Map<int, Slot>::Element *E = slot_info.front(); E; E = E->next()) { - - if (E->key() < 0 || E->key() >= cache_y.size()) - continue; - if (!slot_info.has(E->key())) - continue; - const Slot &s = slot_info[E->key()]; - //left - if (s.enable_left) { - Ref<Texture> p = port; - if (s.custom_slot_left.is_valid()) { - p = s.custom_slot_left; + for (Map<int, Slot>::Element *E = slot_info.front(); E; E = E->next()) { + + if (E->key() < 0 || E->key() >= cache_y.size()) + continue; + if (!slot_info.has(E->key())) + continue; + const Slot &s = slot_info[E->key()]; + //left + 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); } - 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; + 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); } - p->draw(get_canvas_item(), icofs + Point2(get_size().x - edgeofs, cache_y[E->key()]), s.color_right); } - } - if (resizable) { - draw_texture(resizer, get_size() - resizer->get_size()); - } - } + if (resizable) { + draw_texture(resizer, get_size() - resizer->get_size()); + } + } break; + + case NOTIFICATION_SORT_CHILDREN: { + + _resort(); + } break; - if (p_what == NOTIFICATION_SORT_CHILDREN) { + case NOTIFICATION_THEME_CHANGED: { - _resort(); + minimum_size_changed(); + } break; } } diff --git a/scene/gui/graph_node.h b/scene/gui/graph_node.h index 20d25a69b0..2179904cc4 100644 --- a/scene/gui/graph_node.h +++ b/scene/gui/graph_node.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/grid_container.cpp b/scene/gui/grid_container.cpp index 278e4123d7..d0e2edc7b5 100644 --- a/scene/gui/grid_container.cpp +++ b/scene/gui/grid_container.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -164,6 +164,10 @@ void GridContainer::_notification(int p_what) { } } break; + case NOTIFICATION_THEME_CHANGED: { + + minimum_size_changed(); + } break; } } @@ -184,8 +188,6 @@ void GridContainer::_bind_methods() { ClassDB::bind_method(D_METHOD("set_columns", "columns"), &GridContainer::set_columns); ClassDB::bind_method(D_METHOD("get_columns"), &GridContainer::get_columns); - ClassDB::bind_method(D_METHOD("get_child_control_at_cell", "row", "column"), - &GridContainer::get_child_control_at_cell); ADD_PROPERTY(PropertyInfo(Variant::INT, "columns", PROPERTY_HINT_RANGE, "1,1024,1"), "set_columns", "get_columns"); } @@ -241,21 +243,6 @@ Size2 GridContainer::get_minimum_size() const { return ms; } -Control *GridContainer::get_child_control_at_cell(int row, int column) { - Control *c; - int grid_index = row * columns + column; - for (int i = 0; i < get_child_count(); i++) { - c = Object::cast_to<Control>(get_child(i)); - if (!c || !c->is_visible_in_tree()) - continue; - - if (grid_index == i) { - break; - } - } - return c; -} - GridContainer::GridContainer() { set_mouse_filter(MOUSE_FILTER_PASS); diff --git a/scene/gui/grid_container.h b/scene/gui/grid_container.h index 7e3470dc89..3196046378 100644 --- a/scene/gui/grid_container.h +++ b/scene/gui/grid_container.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -47,7 +47,6 @@ public: void set_columns(int p_columns); int get_columns() const; virtual Size2 get_minimum_size() const; - Control *get_child_control_at_cell(int row, int column); GridContainer(); }; diff --git a/scene/gui/item_list.cpp b/scene/gui/item_list.cpp index 9f5c12e87f..026374ded1 100644 --- a/scene/gui/item_list.cpp +++ b/scene/gui/item_list.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -29,13 +29,14 @@ /*************************************************************************/ #include "item_list.h" -#include "os/os.h" -#include "project_settings.h" +#include "core/os/os.h" +#include "core/project_settings.h" void ItemList::add_item(const String &p_item, const Ref<Texture> &p_texture, bool p_selectable) { Item item; item.icon = p_texture; + item.icon_transposed = false; item.icon_region = Rect2i(); item.icon_modulate = Color(1, 1, 1, 1); item.text = p_item; @@ -54,6 +55,7 @@ void ItemList::add_icon_item(const Ref<Texture> &p_item, bool p_selectable) { Item item; item.icon = p_item; + item.icon_transposed = false; item.icon_region = Rect2i(); item.icon_modulate = Color(1, 1, 1, 1); //item.text=p_item; @@ -124,6 +126,22 @@ Ref<Texture> ItemList::get_item_icon(int p_idx) const { return items[p_idx].icon; } +void ItemList::set_item_icon_transposed(int p_idx, const bool p_transposed) { + + ERR_FAIL_INDEX(p_idx, items.size()); + + items.write[p_idx].icon_transposed = p_transposed; + update(); + shape_changed = true; +} + +bool ItemList::is_item_icon_transposed(int p_idx) const { + + ERR_FAIL_INDEX_V(p_idx, items.size(), false); + + return items[p_idx].icon_transposed; +} + void ItemList::set_item_icon_region(int p_idx, const Rect2 &p_region) { ERR_FAIL_INDEX(p_idx, items.size()); @@ -416,6 +434,7 @@ void ItemList::set_icon_mode(IconMode p_mode) { update(); shape_changed = true; } + ItemList::IconMode ItemList::get_icon_mode() const { return icon_mode; @@ -435,10 +454,18 @@ Size2 ItemList::Item::get_icon_size() const { if (icon.is_null()) return Size2(); - if (icon_region.has_no_area()) - return icon->get_size(); - return icon_region.size; + Size2 size_result = Size2(icon_region.size).abs(); + if (icon_region.size.x == 0 || icon_region.size.y == 0) + size_result = icon->get_size(); + + if (icon_transposed) { + Size2 size_tmp = size_result; + size_result.x = size_tmp.y; + size_result.y = size_tmp.x; + } + + return size_result; } void ItemList::_gui_input(const Ref<InputEvent> &p_event) { @@ -688,9 +715,9 @@ void ItemList::_gui_input(const Ref<InputEvent> &p_event) { } } else if (p_event->is_action("ui_cancel")) { search_string = ""; - } else if (p_event->is_action("ui_select")) { + } else if (p_event->is_action("ui_select") && select_mode == SELECT_MULTI) { - if (select_mode == SELECT_MULTI && current >= 0 && current < items.size()) { + if (current >= 0 && current < items.size()) { if (items[current].selectable && !items[current].disabled && !items[current].selected) { select(current, false); emit_signal("multi_selected", current, true); @@ -1067,10 +1094,15 @@ void ItemList::_notification(int p_what) { if (items[i].disabled) modulate.a *= 0.5; - if (items[i].icon_region.has_no_area()) - draw_texture_rect(items[i].icon, draw_rect, false, modulate); - else - draw_texture_rect_region(items[i].icon, draw_rect, items[i].icon_region, modulate); + // If the icon is transposed, we have to switch the size so that it is drawn correctly + if (items[i].icon_transposed) { + Size2 size_tmp = draw_rect.size; + draw_rect.size.x = size_tmp.y; + draw_rect.size.y = size_tmp.x; + } + + Rect2 region = (items[i].icon_region.size.x == 0 || items[i].icon_region.size.y == 0) ? Rect2(Vector2(), items[i].icon->get_size()) : Rect2(items[i].icon_region); + draw_texture_rect_region(items[i].icon, draw_rect, region, modulate, items[i].icon_transposed); } if (items[i].tag_icon.is_valid()) { @@ -1082,13 +1114,13 @@ void ItemList::_notification(int p_what) { int max_len = -1; - Vector2 size = font->get_string_size(items[i].text); + Vector2 size2 = font->get_string_size(items[i].text); if (fixed_column_width) max_len = fixed_column_width; else if (same_column_width) max_len = items[i].rect_cache.size.x; else - max_len = size.x; + max_len = size2.x; Color modulate = items[i].selected ? font_color_selected : (items[i].custom_fg != Color() ? items[i].custom_fg : font_color); if (items[i].disabled) @@ -1138,12 +1170,12 @@ void ItemList::_notification(int p_what) { } else { if (fixed_column_width > 0) - size.x = MIN(size.x, fixed_column_width); + size2.x = MIN(size2.x, fixed_column_width); if (icon_mode == ICON_MODE_TOP) { - text_ofs.x += (items[i].rect_cache.size.width - size.x) / 2; + text_ofs.x += (items[i].rect_cache.size.width - size2.x) / 2; } else { - text_ofs.y += (items[i].rect_cache.size.height - size.y) / 2; + text_ofs.y += (items[i].rect_cache.size.height - size2.y) / 2; } text_ofs.y += font->get_ascent(); @@ -1405,6 +1437,9 @@ void ItemList::_bind_methods() { ClassDB::bind_method(D_METHOD("set_item_icon", "idx", "icon"), &ItemList::set_item_icon); ClassDB::bind_method(D_METHOD("get_item_icon", "idx"), &ItemList::get_item_icon); + ClassDB::bind_method(D_METHOD("set_item_icon_transposed", "idx", "rect"), &ItemList::set_item_icon_transposed); + ClassDB::bind_method(D_METHOD("is_item_icon_transposed", "idx"), &ItemList::is_item_icon_transposed); + ClassDB::bind_method(D_METHOD("set_item_icon_region", "idx", "rect"), &ItemList::set_item_icon_region); ClassDB::bind_method(D_METHOD("get_item_icon_region", "idx"), &ItemList::get_item_icon_region); @@ -1498,17 +1533,17 @@ void ItemList::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "select_mode", PROPERTY_HINT_ENUM, "Single,Multi"), "set_select_mode", "get_select_mode"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "allow_reselect"), "set_allow_reselect", "get_allow_reselect"); - ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL, "allow_rmb_select"), "set_allow_rmb_select", "get_allow_rmb_select"); - ADD_PROPERTYNO(PropertyInfo(Variant::INT, "max_text_lines"), "set_max_text_lines", "get_max_text_lines"); - ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL, "auto_height"), "set_auto_height", "has_auto_height"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "allow_rmb_select"), "set_allow_rmb_select", "get_allow_rmb_select"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "max_text_lines"), "set_max_text_lines", "get_max_text_lines"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "auto_height"), "set_auto_height", "has_auto_height"); ADD_GROUP("Columns", ""); - ADD_PROPERTYNO(PropertyInfo(Variant::INT, "max_columns"), "set_max_columns", "get_max_columns"); - ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL, "same_column_width"), "set_same_column_width", "is_same_column_width"); - ADD_PROPERTYNZ(PropertyInfo(Variant::INT, "fixed_column_width"), "set_fixed_column_width", "get_fixed_column_width"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "max_columns"), "set_max_columns", "get_max_columns"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "same_column_width"), "set_same_column_width", "is_same_column_width"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "fixed_column_width"), "set_fixed_column_width", "get_fixed_column_width"); ADD_GROUP("Icon", ""); ADD_PROPERTY(PropertyInfo(Variant::INT, "icon_mode", PROPERTY_HINT_ENUM, "Top,Left"), "set_icon_mode", "get_icon_mode"); - ADD_PROPERTYNO(PropertyInfo(Variant::REAL, "icon_scale"), "set_icon_scale", "get_icon_scale"); - ADD_PROPERTYNO(PropertyInfo(Variant::VECTOR2, "fixed_icon_size"), "set_fixed_icon_size", "get_fixed_icon_size"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "icon_scale"), "set_icon_scale", "get_icon_scale"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "fixed_icon_size"), "set_fixed_icon_size", "get_fixed_icon_size"); BIND_ENUM_CONSTANT(ICON_MODE_TOP); BIND_ENUM_CONSTANT(ICON_MODE_LEFT); @@ -1524,6 +1559,7 @@ void ItemList::_bind_methods() { ADD_SIGNAL(MethodInfo("nothing_selected")); GLOBAL_DEF("gui/timers/incremental_search_max_interval_msec", 2000); + ProjectSettings::get_singleton()->set_custom_property_info("gui/timers/incremental_search_max_interval_msec", PropertyInfo(Variant::INT, "gui/timers/incremental_search_max_interval_msec", PROPERTY_HINT_RANGE, "0,10000,1,or_greater")); // No negative numbers } ItemList::ItemList() { diff --git a/scene/gui/item_list.h b/scene/gui/item_list.h index 58771c1777..3a7cc65ab4 100644 --- a/scene/gui/item_list.h +++ b/scene/gui/item_list.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -53,6 +53,7 @@ private: struct Item { Ref<Texture> icon; + bool icon_transposed; Rect2i icon_region; Color icon_modulate; Ref<Texture> tag_icon; @@ -133,6 +134,9 @@ public: void set_item_icon(int p_idx, const Ref<Texture> &p_icon); Ref<Texture> get_item_icon(int p_idx) const; + void set_item_icon_transposed(int p_idx, const bool transposed); + bool is_item_icon_transposed(int p_idx) const; + void set_item_icon_region(int p_idx, const Rect2 &p_region); Rect2 get_item_icon_region(int p_idx) const; diff --git a/scene/gui/label.cpp b/scene/gui/label.cpp index 0b36e1663c..e3e9368a12 100644 --- a/scene/gui/label.cpp +++ b/scene/gui/label.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -29,9 +29,9 @@ /*************************************************************************/ #include "label.h" -#include "print_string.h" -#include "project_settings.h" -#include "translation.h" +#include "core/print_string.h" +#include "core/project_settings.h" +#include "core/translation.h" void Label::set_autowrap(bool p_autowrap) { @@ -244,7 +244,7 @@ void Label::_notification(int p_what) { CharType n = xl_text[i + pos + 1]; if (uppercase) { c = String::char_uppercase(c); - n = String::char_uppercase(c); + n = String::char_uppercase(n); } float move = font->draw_char(ci, Point2(x_ofs_shadow, y_ofs) + shadow_ofs, c, n, font_color_shadow, false); @@ -265,7 +265,7 @@ void Label::_notification(int p_what) { CharType n = xl_text[i + pos + 1]; if (uppercase) { c = String::char_uppercase(c); - n = String::char_uppercase(c); + n = String::char_uppercase(n); } x_ofs += drawer.draw_char(ci, Point2(x_ofs, y_ofs), c, n, font_color); @@ -295,14 +295,13 @@ Size2 Label::get_minimum_size() const { Size2 min_style = get_stylebox("normal")->get_minimum_size(); + // don't want to mutable everything + if (word_cache_dirty) + const_cast<Label *>(this)->regenerate_word_cache(); + if (autowrap) return Size2(1, clip ? 1 : minsize.height) + min_style; else { - - // don't want to mutable everything - if (word_cache_dirty) - const_cast<Label *>(this)->regenerate_word_cache(); - Size2 ms = minsize; if (clip) ms.width = 1; @@ -394,9 +393,9 @@ void Label::regenerate_word_cache() { WordCache *last = NULL; - for (int i = 0; i < xl_text.size() + 1; i++) { + for (int i = 0; i <= xl_text.length(); i++) { - CharType current = i < xl_text.length() ? xl_text[i] : ' '; //always a space at the end, so the algo works + CharType current = i < xl_text.length() ? xl_text[i] : L' '; //always a space at the end, so the algo works if (uppercase) current = String::char_uppercase(current); @@ -430,12 +429,11 @@ void Label::regenerate_word_cache() { if (current == '\n') { insert_newline = true; - } else { + } else if (current != ' ') { total_char_cache++; } 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++; line_width += space_width; @@ -512,7 +510,7 @@ void Label::regenerate_word_cache() { void Label::set_align(Align p_align) { - ERR_FAIL_INDEX(p_align, 4); + ERR_FAIL_INDEX((int)p_align, 4); align = p_align; update(); } @@ -524,7 +522,7 @@ Label::Align Label::get_align() const { void Label::set_valign(VAlign p_align) { - ERR_FAIL_INDEX(p_align, 4); + ERR_FAIL_INDEX((int)p_align, 4); valign = p_align; update(); } @@ -666,12 +664,12 @@ void Label::_bind_methods() { BIND_ENUM_CONSTANT(VALIGN_BOTTOM); BIND_ENUM_CONSTANT(VALIGN_FILL); - ADD_PROPERTYNZ(PropertyInfo(Variant::STRING, "text", PROPERTY_HINT_MULTILINE_TEXT, "", PROPERTY_USAGE_DEFAULT_INTL), "set_text", "get_text"); - ADD_PROPERTYNZ(PropertyInfo(Variant::INT, "align", PROPERTY_HINT_ENUM, "Left,Center,Right,Fill"), "set_align", "get_align"); - ADD_PROPERTYNZ(PropertyInfo(Variant::INT, "valign", PROPERTY_HINT_ENUM, "Top,Center,Bottom,Fill"), "set_valign", "get_valign"); - ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL, "autowrap"), "set_autowrap", "has_autowrap"); - ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL, "clip_text"), "set_clip_text", "is_clipping_text"); - ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL, "uppercase"), "set_uppercase", "is_uppercase"); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "text", PROPERTY_HINT_MULTILINE_TEXT, "", PROPERTY_USAGE_DEFAULT_INTL), "set_text", "get_text"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "align", PROPERTY_HINT_ENUM, "Left,Center,Right,Fill"), "set_align", "get_align"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "valign", PROPERTY_HINT_ENUM, "Top,Center,Bottom,Fill"), "set_valign", "get_valign"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "autowrap"), "set_autowrap", "has_autowrap"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "clip_text"), "set_clip_text", "is_clipping_text"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "uppercase"), "set_uppercase", "is_uppercase"); ADD_PROPERTY(PropertyInfo(Variant::INT, "visible_characters", PROPERTY_HINT_RANGE, "-1,128000,1", PROPERTY_USAGE_EDITOR), "set_visible_characters", "get_visible_characters"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "percent_visible", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_percent_visible", "get_percent_visible"); ADD_PROPERTY(PropertyInfo(Variant::INT, "lines_skipped", PROPERTY_HINT_RANGE, "0,999,1"), "set_lines_skipped", "get_lines_skipped"); diff --git a/scene/gui/label.h b/scene/gui/label.h index d5e0b60773..561c42ef9e 100644 --- a/scene/gui/label.h +++ b/scene/gui/label.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* 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/line_edit.cpp b/scene/gui/line_edit.cpp index 1f3d5e6e13..bf6833e512 100644 --- a/scene/gui/line_edit.cpp +++ b/scene/gui/line_edit.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -29,12 +29,12 @@ /*************************************************************************/ #include "line_edit.h" +#include "core/message_queue.h" +#include "core/os/keyboard.h" +#include "core/os/os.h" +#include "core/print_string.h" +#include "core/translation.h" #include "label.h" -#include "message_queue.h" -#include "os/keyboard.h" -#include "os/os.h" -#include "print_string.h" -#include "translation.h" #ifdef TOOLS_ENABLED #include "editor/editor_scale.h" @@ -248,7 +248,9 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) { set_cursor_position(text.length()); } break; #endif - default: { handled = false; } + default: { + handled = false; + } } if (handled) { @@ -527,7 +529,7 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) { void LineEdit::set_align(Align p_align) { - ERR_FAIL_INDEX(p_align, 4); + ERR_FAIL_INDEX((int)p_align, 4); align = p_align; update(); } @@ -831,7 +833,6 @@ void LineEdit::_notification(int p_what) { OS::get_singleton()->set_ime_active(true); OS::get_singleton()->set_ime_position(get_global_position() + Point2(using_placeholder ? 0 : x_ofs, y_ofs + caret_height)); - OS::get_singleton()->set_ime_intermediate_text_callback(_ime_text_callback, this); } } break; case NOTIFICATION_FOCUS_ENTER: { @@ -843,7 +844,6 @@ void LineEdit::_notification(int p_what) { OS::get_singleton()->set_ime_active(true); Point2 cursor_pos = Point2(get_cursor_position(), 1) * get_minimum_size().height; OS::get_singleton()->set_ime_position(get_global_position() + cursor_pos); - OS::get_singleton()->set_ime_intermediate_text_callback(_ime_text_callback, this); if (OS::get_singleton()->has_virtual_keyboard()) OS::get_singleton()->show_virtual_keyboard(text, get_global_rect()); @@ -852,7 +852,6 @@ void LineEdit::_notification(int p_what) { case NOTIFICATION_FOCUS_EXIT: { OS::get_singleton()->set_ime_position(Point2()); - OS::get_singleton()->set_ime_intermediate_text_callback(NULL, NULL); OS::get_singleton()->set_ime_active(false); ime_text = ""; ime_selection = Point2(); @@ -861,6 +860,14 @@ void LineEdit::_notification(int p_what) { OS::get_singleton()->hide_virtual_keyboard(); } break; + case MainLoop::NOTIFICATION_OS_IME_UPDATE: { + + if (has_focus()) { + ime_text = OS::get_singleton()->get_ime_text(); + ime_selection = OS::get_singleton()->get_ime_selection(); + update(); + } + } break; } } @@ -1147,9 +1154,7 @@ void LineEdit::set_cursor_position(int p_pos) { if (cursor_pos <= window_pos) { /* Adjust window if cursor goes too much to the left */ - if (window_pos > 0) - set_window_pos(window_pos - 1); - + set_window_pos(MAX(0, cursor_pos - 1)); } else if (cursor_pos > window_pos) { /* Adjust window if cursor goes too much to the right */ int window_width = get_size().width - style->get_minimum_size().width; @@ -1283,13 +1288,11 @@ int LineEdit::get_max_length() const { void LineEdit::selection_fill_at_cursor() { - int aux; - selection.begin = cursor_pos; selection.end = selection.cursor_start; if (selection.end < selection.begin) { - aux = selection.end; + int aux = selection.end; selection.end = selection.begin; selection.begin = aux; } @@ -1461,13 +1464,6 @@ void LineEdit::set_right_icon(const Ref<Texture> &p_icon) { update(); } -void LineEdit::_ime_text_callback(void *p_self, String p_text, Point2 p_selection) { - LineEdit *self = (LineEdit *)p_self; - self->ime_text = p_text; - self->ime_selection = p_selection; - self->update(); -} - void LineEdit::_text_changed() { if (expand_to_text_length) @@ -1573,22 +1569,22 @@ void LineEdit::_bind_methods() { BIND_ENUM_CONSTANT(MENU_REDO); BIND_ENUM_CONSTANT(MENU_MAX); - ADD_PROPERTYNZ(PropertyInfo(Variant::STRING, "text"), "set_text", "get_text"); - ADD_PROPERTYNZ(PropertyInfo(Variant::INT, "align", PROPERTY_HINT_ENUM, "Left,Center,Right,Fill"), "set_align", "get_align"); - ADD_PROPERTYNZ(PropertyInfo(Variant::INT, "max_length"), "set_max_length", "get_max_length"); - ADD_PROPERTYNO(PropertyInfo(Variant::BOOL, "editable"), "set_editable", "is_editable"); - ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL, "secret"), "set_secret", "is_secret"); - ADD_PROPERTYNZ(PropertyInfo(Variant::STRING, "secret_character"), "set_secret_character", "get_secret_character"); - ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL, "expand_to_text_length"), "set_expand_to_text_length", "get_expand_to_text_length"); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "text"), "set_text", "get_text"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "align", PROPERTY_HINT_ENUM, "Left,Center,Right,Fill"), "set_align", "get_align"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "max_length"), "set_max_length", "get_max_length"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "editable"), "set_editable", "is_editable"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "secret"), "set_secret", "is_secret"); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "secret_character"), "set_secret_character", "get_secret_character"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "expand_to_text_length"), "set_expand_to_text_length", "get_expand_to_text_length"); ADD_PROPERTY(PropertyInfo(Variant::INT, "focus_mode", PROPERTY_HINT_ENUM, "None,Click,All"), "set_focus_mode", "get_focus_mode"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "context_menu_enabled"), "set_context_menu_enabled", "is_context_menu_enabled"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "clear_button_enabled"), "set_clear_button_enabled", "is_clear_button_enabled"); ADD_GROUP("Placeholder", "placeholder_"); - ADD_PROPERTYNZ(PropertyInfo(Variant::STRING, "placeholder_text"), "set_placeholder", "get_placeholder"); - ADD_PROPERTYNZ(PropertyInfo(Variant::REAL, "placeholder_alpha", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_placeholder_alpha", "get_placeholder_alpha"); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "placeholder_text"), "set_placeholder", "get_placeholder"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "placeholder_alpha", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_placeholder_alpha", "get_placeholder_alpha"); ADD_GROUP("Caret", "caret_"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "caret_blink"), "cursor_set_blink_enabled", "cursor_get_blink_enabled"); - ADD_PROPERTYNZ(PropertyInfo(Variant::REAL, "caret_blink_speed", PROPERTY_HINT_RANGE, "0.1,10,0.01"), "cursor_set_blink_speed", "cursor_get_blink_speed"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "caret_blink_speed", PROPERTY_HINT_RANGE, "0.1,10,0.01"), "cursor_set_blink_speed", "cursor_get_blink_speed"); ADD_PROPERTY(PropertyInfo(Variant::INT, "caret_position"), "set_cursor_position", "get_cursor_position"); } @@ -1608,6 +1604,8 @@ LineEdit::LineEdit() { text_changed_dirty = false; placeholder_alpha = 0.6; clear_button_enabled = false; + clear_button_status.press_attempt = false; + clear_button_status.pressing_inside = false; deselect(); set_focus_mode(FOCUS_ALL); diff --git a/scene/gui/line_edit.h b/scene/gui/line_edit.h index 5294d99da0..3b29780dc0 100644 --- a/scene/gui/line_edit.h +++ b/scene/gui/line_edit.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -122,7 +122,6 @@ private: Timer *caret_blink_timer; - static void _ime_text_callback(void *p_self, String p_text, Point2 p_selection); void _text_changed(); void _emit_text_change(); bool expand_to_text_length; diff --git a/scene/gui/link_button.cpp b/scene/gui/link_button.cpp index 8560efdde5..21527e9bfc 100644 --- a/scene/gui/link_button.cpp +++ b/scene/gui/link_button.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -75,6 +75,7 @@ void LinkButton::_notification(int p_what) { color = get_color("font_color"); do_underline = underline_mode == UNDERLINE_MODE_ALWAYS; } break; + case DRAW_HOVER_PRESSED: case DRAW_PRESSED: { if (has_color("font_color_pressed")) @@ -133,8 +134,8 @@ void LinkButton::_bind_methods() { BIND_ENUM_CONSTANT(UNDERLINE_MODE_ON_HOVER); BIND_ENUM_CONSTANT(UNDERLINE_MODE_NEVER); - ADD_PROPERTYNZ(PropertyInfo(Variant::STRING, "text"), "set_text", "get_text"); - ADD_PROPERTYNZ(PropertyInfo(Variant::INT, "underline", PROPERTY_HINT_ENUM, "Always,On Hover,Never"), "set_underline_mode", "get_underline_mode"); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "text"), "set_text", "get_text"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "underline", PROPERTY_HINT_ENUM, "Always,On Hover,Never"), "set_underline_mode", "get_underline_mode"); } LinkButton::LinkButton() { diff --git a/scene/gui/link_button.h b/scene/gui/link_button.h index 0821ad9c0d..17c4bca67b 100644 --- a/scene/gui/link_button.h +++ b/scene/gui/link_button.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* 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 @@ #define LINKBUTTON_H #include "scene/gui/base_button.h" -#include "scene/resources/bit_mask.h" +#include "scene/resources/bit_map.h" class LinkButton : public BaseButton { diff --git a/scene/gui/margin_container.cpp b/scene/gui/margin_container.cpp index 5e1d53fe1d..62ba45c484 100644 --- a/scene/gui/margin_container.cpp +++ b/scene/gui/margin_container.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -64,27 +64,33 @@ Size2 MarginContainer::get_minimum_size() const { void MarginContainer::_notification(int p_what) { - if (p_what == NOTIFICATION_SORT_CHILDREN) { + switch (p_what) { + case NOTIFICATION_SORT_CHILDREN: { - int margin_left = get_constant("margin_left"); - int margin_top = get_constant("margin_top"); - int margin_right = get_constant("margin_right"); - int margin_bottom = get_constant("margin_bottom"); + int margin_left = get_constant("margin_left"); + int margin_top = get_constant("margin_top"); + int margin_right = get_constant("margin_right"); + int margin_bottom = get_constant("margin_bottom"); - Size2 s = get_size(); + Size2 s = get_size(); - for (int i = 0; i < get_child_count(); i++) { + for (int i = 0; i < get_child_count(); i++) { - Control *c = Object::cast_to<Control>(get_child(i)); - if (!c) - continue; - if (c->is_set_as_toplevel()) - continue; + Control *c = Object::cast_to<Control>(get_child(i)); + if (!c) + continue; + if (c->is_set_as_toplevel()) + continue; - int w = s.width - margin_left - margin_right; - int h = s.height - margin_top - margin_bottom; - fit_child_in_rect(c, Rect2(margin_left, margin_top, w, h)); - } + int w = s.width - margin_left - margin_right; + int h = s.height - margin_top - margin_bottom; + fit_child_in_rect(c, Rect2(margin_left, margin_top, w, h)); + } + } break; + case NOTIFICATION_THEME_CHANGED: { + + minimum_size_changed(); + } break; } } diff --git a/scene/gui/margin_container.h b/scene/gui/margin_container.h index ea75109248..336b68665f 100644 --- a/scene/gui/margin_container.h +++ b/scene/gui/margin_container.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/menu_button.cpp b/scene/gui/menu_button.cpp index 87cf4dc334..b67d8c00d6 100644 --- a/scene/gui/menu_button.cpp +++ b/scene/gui/menu_button.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -29,7 +29,7 @@ /*************************************************************************/ #include "menu_button.h" -#include "os/keyboard.h" +#include "core/os/keyboard.h" #include "scene/main/viewport.h" void MenuButton::_unhandled_key_input(Ref<InputEvent> p_event) { @@ -71,13 +71,24 @@ PopupMenu *MenuButton::get_popup() const { return popup; } +void MenuButton::_set_items(const Array &p_items) { + + popup->set("items", p_items); +} + Array MenuButton::_get_items() const { return popup->get("items"); } -void MenuButton::_set_items(const Array &p_items) { - popup->set("items", p_items); +void MenuButton::set_switch_on_hover(bool p_enabled) { + + switch_on_hover = p_enabled; +} + +bool MenuButton::is_switch_on_hover() { + + return switch_on_hover; } void MenuButton::_bind_methods() { @@ -86,9 +97,12 @@ void MenuButton::_bind_methods() { ClassDB::bind_method(D_METHOD("_unhandled_key_input"), &MenuButton::_unhandled_key_input); ClassDB::bind_method(D_METHOD("_set_items"), &MenuButton::_set_items); ClassDB::bind_method(D_METHOD("_get_items"), &MenuButton::_get_items); + ClassDB::bind_method(D_METHOD("set_switch_on_hover", "enable"), &MenuButton::set_switch_on_hover); + ClassDB::bind_method(D_METHOD("is_switch_on_hover"), &MenuButton::is_switch_on_hover); ClassDB::bind_method(D_METHOD("set_disable_shortcuts", "disabled"), &MenuButton::set_disable_shortcuts); ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "items", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_items", "_get_items"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "switch_on_hover"), "set_switch_on_hover", "is_switch_on_hover"); ADD_SIGNAL(MethodInfo("about_to_show")); } @@ -100,6 +114,7 @@ void MenuButton::set_disable_shortcuts(bool p_disabled) { MenuButton::MenuButton() { + switch_on_hover = false; set_flat(true); set_disable_shortcuts(false); set_enabled_focus_mode(FOCUS_NONE); diff --git a/scene/gui/menu_button.h b/scene/gui/menu_button.h index 0636accfee..794840035e 100644 --- a/scene/gui/menu_button.h +++ b/scene/gui/menu_button.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -41,6 +41,7 @@ class MenuButton : public Button { GDCLASS(MenuButton, Button); bool clicked; + bool switch_on_hover; bool disable_shortcuts; PopupMenu *popup; @@ -57,6 +58,8 @@ public: virtual void pressed(); PopupMenu *get_popup() const; + void set_switch_on_hover(bool p_enabled); + bool is_switch_on_hover(); void set_disable_shortcuts(bool p_disabled); MenuButton(); diff --git a/scene/gui/nine_patch_rect.cpp b/scene/gui/nine_patch_rect.cpp index b8f6ffe6d2..23e0ea876d 100644 --- a/scene/gui/nine_patch_rect.cpp +++ b/scene/gui/nine_patch_rect.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -70,18 +70,18 @@ void NinePatchRect::_bind_methods() { ADD_SIGNAL(MethodInfo("texture_changed")); - ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture"); - ADD_PROPERTYNO(PropertyInfo(Variant::BOOL, "draw_center"), "set_draw_center", "is_draw_center_enabled"); - ADD_PROPERTYNZ(PropertyInfo(Variant::RECT2, "region_rect"), "set_region_rect", "get_region_rect"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "draw_center"), "set_draw_center", "is_draw_center_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::RECT2, "region_rect"), "set_region_rect", "get_region_rect"); ADD_GROUP("Patch Margin", "patch_margin_"); - ADD_PROPERTYINZ(PropertyInfo(Variant::INT, "patch_margin_left", PROPERTY_HINT_RANGE, "0,16384,1"), "set_patch_margin", "get_patch_margin", MARGIN_LEFT); - ADD_PROPERTYINZ(PropertyInfo(Variant::INT, "patch_margin_top", PROPERTY_HINT_RANGE, "0,16384,1"), "set_patch_margin", "get_patch_margin", MARGIN_TOP); - ADD_PROPERTYINZ(PropertyInfo(Variant::INT, "patch_margin_right", PROPERTY_HINT_RANGE, "0,16384,1"), "set_patch_margin", "get_patch_margin", MARGIN_RIGHT); - ADD_PROPERTYINZ(PropertyInfo(Variant::INT, "patch_margin_bottom", PROPERTY_HINT_RANGE, "0,16384,1"), "set_patch_margin", "get_patch_margin", MARGIN_BOTTOM); + ADD_PROPERTYI(PropertyInfo(Variant::INT, "patch_margin_left", PROPERTY_HINT_RANGE, "0,16384,1"), "set_patch_margin", "get_patch_margin", MARGIN_LEFT); + ADD_PROPERTYI(PropertyInfo(Variant::INT, "patch_margin_top", PROPERTY_HINT_RANGE, "0,16384,1"), "set_patch_margin", "get_patch_margin", MARGIN_TOP); + ADD_PROPERTYI(PropertyInfo(Variant::INT, "patch_margin_right", PROPERTY_HINT_RANGE, "0,16384,1"), "set_patch_margin", "get_patch_margin", MARGIN_RIGHT); + ADD_PROPERTYI(PropertyInfo(Variant::INT, "patch_margin_bottom", PROPERTY_HINT_RANGE, "0,16384,1"), "set_patch_margin", "get_patch_margin", MARGIN_BOTTOM); ADD_GROUP("Axis Stretch", "axis_stretch_"); - ADD_PROPERTYNZ(PropertyInfo(Variant::INT, "axis_stretch_horizontal", PROPERTY_HINT_ENUM, "Stretch,Tile,Tile Fit"), "set_h_axis_stretch_mode", "get_h_axis_stretch_mode"); - ADD_PROPERTYNZ(PropertyInfo(Variant::INT, "axis_stretch_vertical", PROPERTY_HINT_ENUM, "Stretch,Tile,Tile Fit"), "set_v_axis_stretch_mode", "get_v_axis_stretch_mode"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "axis_stretch_horizontal", PROPERTY_HINT_ENUM, "Stretch,Tile,Tile Fit"), "set_h_axis_stretch_mode", "get_h_axis_stretch_mode"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "axis_stretch_vertical", PROPERTY_HINT_ENUM, "Stretch,Tile,Tile Fit"), "set_v_axis_stretch_mode", "get_v_axis_stretch_mode"); BIND_ENUM_CONSTANT(AXIS_STRETCH_MODE_STRETCH); BIND_ENUM_CONSTANT(AXIS_STRETCH_MODE_TILE); @@ -110,7 +110,7 @@ Ref<Texture> NinePatchRect::get_texture() const { void NinePatchRect::set_patch_margin(Margin p_margin, int p_size) { - ERR_FAIL_INDEX(p_margin, 4); + ERR_FAIL_INDEX((int)p_margin, 4); margin[p_margin] = p_size; update(); minimum_size_changed(); @@ -132,7 +132,7 @@ void NinePatchRect::set_patch_margin(Margin p_margin, int p_size) { int NinePatchRect::get_patch_margin(Margin p_margin) const { - ERR_FAIL_INDEX_V(p_margin, 4, 0); + ERR_FAIL_INDEX_V((int)p_margin, 4, 0); return margin[p_margin]; } diff --git a/scene/gui/nine_patch_rect.h b/scene/gui/nine_patch_rect.h index b4b4602a7d..ac17e52fc1 100644 --- a/scene/gui/nine_patch_rect.h +++ b/scene/gui/nine_patch_rect.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/option_button.cpp b/scene/gui/option_button.cpp index 2901176a69..b9b270ce0c 100644 --- a/scene/gui/option_button.cpp +++ b/scene/gui/option_button.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -29,7 +29,7 @@ /*************************************************************************/ #include "option_button.h" -#include "print_string.h" +#include "core/print_string.h" Size2 OptionButton::get_minimum_size() const { @@ -160,6 +160,12 @@ int OptionButton::get_item_id(int p_idx) const { return popup->get_item_id(p_idx); } + +int OptionButton::get_item_index(int p_id) const { + + return popup->get_item_index(p_id); +} + Variant OptionButton::get_item_metadata(int p_idx) const { return popup->get_item_metadata(p_idx); @@ -306,6 +312,7 @@ void OptionButton::_bind_methods() { ClassDB::bind_method(D_METHOD("get_item_text", "idx"), &OptionButton::get_item_text); ClassDB::bind_method(D_METHOD("get_item_icon", "idx"), &OptionButton::get_item_icon); ClassDB::bind_method(D_METHOD("get_item_id", "idx"), &OptionButton::get_item_id); + ClassDB::bind_method(D_METHOD("get_item_index", "id"), &OptionButton::get_item_index); ClassDB::bind_method(D_METHOD("get_item_metadata", "idx"), &OptionButton::get_item_metadata); ClassDB::bind_method(D_METHOD("is_item_disabled", "idx"), &OptionButton::is_item_disabled); ClassDB::bind_method(D_METHOD("get_item_count"), &OptionButton::get_item_count); diff --git a/scene/gui/option_button.h b/scene/gui/option_button.h index d5f866d806..63b451377a 100644 --- a/scene/gui/option_button.h +++ b/scene/gui/option_button.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -71,6 +71,7 @@ public: String get_item_text(int p_idx) const; Ref<Texture> get_item_icon(int p_idx) const; int get_item_id(int p_idx) const; + int get_item_index(int p_id) const; Variant get_item_metadata(int p_idx) const; bool is_item_disabled(int p_idx) const; diff --git a/scene/gui/panel.cpp b/scene/gui/panel.cpp index 4375e03a50..c26bd09f50 100644 --- a/scene/gui/panel.cpp +++ b/scene/gui/panel.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -29,7 +29,7 @@ /*************************************************************************/ #include "panel.h" -#include "print_string.h" +#include "core/print_string.h" void Panel::_notification(int p_what) { diff --git a/scene/gui/panel.h b/scene/gui/panel.h index db8b35372e..f8d15e4261 100644 --- a/scene/gui/panel.h +++ b/scene/gui/panel.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/panel_container.cpp b/scene/gui/panel_container.cpp index a778d62659..b1fced87fc 100644 --- a/scene/gui/panel_container.cpp +++ b/scene/gui/panel_container.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/panel_container.h b/scene/gui/panel_container.h index 267e2b921f..15661d3e35 100644 --- a/scene/gui/panel_container.h +++ b/scene/gui/panel_container.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/popup.cpp b/scene/gui/popup.cpp index 26d01ecc09..80ec7049fc 100644 --- a/scene/gui/popup.cpp +++ b/scene/gui/popup.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,8 +30,8 @@ #include "popup.h" -#include "engine.h" -#include "os/keyboard.h" +#include "core/engine.h" +#include "core/os/keyboard.h" void Popup::_gui_input(Ref<InputEvent> p_event) { } @@ -52,9 +52,13 @@ void Popup::_notification(int p_what) { //small helper to make editing of these easier in editor #ifdef TOOLS_ENABLED if (Engine::get_singleton()->is_editor_hint() && get_tree()->get_edited_scene_root() && get_tree()->get_edited_scene_root()->is_a_parent_of(this)) { + //edited on editor set_as_toplevel(false); - } + } else #endif + if (is_visible()) { + hide(); + } } } @@ -120,49 +124,22 @@ void Popup::popup_centered_minsize(const Size2 &p_minsize) { void Popup::popup_centered(const Size2 &p_size) { - Point2 window_size = get_viewport_rect().size; - - emit_signal("about_to_show"); Rect2 rect; + Size2 window_size = get_viewport_rect().size; rect.size = p_size == Size2() ? get_size() : p_size; - rect.position = ((window_size - rect.size) / 2.0).floor(); - set_position(rect.position); - set_size(rect.size); - - show_modal(exclusive); - _fix_size(); - Control *focusable = find_next_valid_focus(); - if (focusable) - focusable->grab_focus(); - - _post_popup(); - notification(NOTIFICATION_POST_POPUP); - popped_up = true; + popup(rect); } void Popup::popup_centered_ratio(float p_screen_ratio) { - emit_signal("about_to_show"); - Rect2 rect; - Point2 window_size = get_viewport_rect().size; + Size2 window_size = get_viewport_rect().size; rect.size = (window_size * p_screen_ratio).floor(); rect.position = ((window_size - rect.size) / 2.0).floor(); - set_position(rect.position); - set_size(rect.size); - - show_modal(exclusive); - _fix_size(); - Control *focusable = find_next_valid_focus(); - if (focusable) - focusable->grab_focus(); - - _post_popup(); - notification(NOTIFICATION_POST_POPUP); - popped_up = true; + popup(rect); } void Popup::popup(const Rect2 &p_bounds) { @@ -234,15 +211,46 @@ String Popup::get_configuration_warning() const { Popup::~Popup() { } -void PopupPanel::set_child_rect(Control *p_child) { - ERR_FAIL_NULL(p_child); +Size2 PopupPanel::get_minimum_size() const { + + Ref<StyleBox> p = get_stylebox("panel"); + + Size2 ms; + + for (int i = 0; i < get_child_count(); i++) { + Control *c = Object::cast_to<Control>(get_child(i)); + if (!c) + continue; + + if (c->is_set_as_toplevel()) + continue; + + Size2 cms = c->get_combined_minimum_size(); + ms.x = MAX(cms.x, ms.x); + ms.y = MAX(cms.y, ms.y); + } + + return ms + p->get_minimum_size(); +} + +void PopupPanel::_update_child_rects() { Ref<StyleBox> p = get_stylebox("panel"); - p_child->set_anchors_preset(Control::PRESET_WIDE); - p_child->set_margin(MARGIN_LEFT, p->get_margin(MARGIN_LEFT)); - p_child->set_margin(MARGIN_RIGHT, -p->get_margin(MARGIN_RIGHT)); - p_child->set_margin(MARGIN_TOP, p->get_margin(MARGIN_TOP)); - p_child->set_margin(MARGIN_BOTTOM, -p->get_margin(MARGIN_BOTTOM)); + + Vector2 cpos(p->get_offset()); + Vector2 csize(get_size() - p->get_minimum_size()); + + for (int i = 0; i < get_child_count(); i++) { + Control *c = Object::cast_to<Control>(get_child(i)); + if (!c) + continue; + + if (c->is_set_as_toplevel()) + continue; + + c->set_position(cpos); + c->set_size(csize); + } } void PopupPanel::_notification(int p_what) { @@ -250,6 +258,12 @@ void PopupPanel::_notification(int p_what) { if (p_what == NOTIFICATION_DRAW) { get_stylebox("panel")->draw(get_canvas_item(), Rect2(Point2(), get_size())); + } else if (p_what == NOTIFICATION_READY) { + + _update_child_rects(); + } else if (p_what == NOTIFICATION_RESIZED) { + + _update_child_rects(); } } diff --git a/scene/gui/popup.h b/scene/gui/popup.h index 550e803578..7ccefe1d75 100644 --- a/scene/gui/popup.h +++ b/scene/gui/popup.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -77,10 +77,12 @@ class PopupPanel : public Popup { GDCLASS(PopupPanel, Popup); protected: + void _update_child_rects(); void _notification(int p_what); public: void set_child_rect(Control *p_child); + virtual Size2 get_minimum_size() const; PopupPanel(); }; diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp index 436dda41a4..28b124d143 100644 --- a/scene/gui/popup_menu.cpp +++ b/scene/gui/popup_menu.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -29,10 +29,10 @@ /*************************************************************************/ #include "popup_menu.h" -#include "os/input.h" -#include "os/keyboard.h" -#include "print_string.h" -#include "translation.h" +#include "core/os/input.h" +#include "core/os/keyboard.h" +#include "core/print_string.h" +#include "core/translation.h" String PopupMenu::_get_accel_text(int p_item) const { @@ -453,7 +453,6 @@ void PopupMenu::_notification(int p_what) { Color icon_color(1, 1, 1, items[i].disabled ? 0.5 : 1); - item_ofs.x += items[i].h_ofs; if (!items[i].icon.is_null()) { icon_size = items[i].icon->get_size(); @@ -470,6 +469,7 @@ void PopupMenu::_notification(int p_what) { String text = items[i].shortcut.is_valid() ? String(tr(items[i].shortcut->get_name())) : items[i].xl_text; + item_ofs.x += items[i].h_ofs; if (items[i].separator) { int sep_h = separator->get_center_size().height + separator->get_minimum_size().height; @@ -519,9 +519,9 @@ void PopupMenu::_notification(int p_what) { if (items[i].accel || (items[i].shortcut.is_valid() && items[i].shortcut->is_valid())) { //accelerator - 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); + String text2 = _get_accel_text(i); + item_ofs.x = size.width - style->get_margin(MARGIN_RIGHT) - font->get_string_size(text2).width; + font->draw(ci, item_ofs + Point2(0, Math::floor((h - font_h) / 2.0)), text2, i == mouse_over ? font_color_hover : font_color_accel); } items.write[i]._ofs_cache = ofs.y; @@ -557,6 +557,21 @@ void PopupMenu::_notification(int p_what) { mouse_over = -1; update(); } + + for (int i = 0; i < items.size(); i++) { + if (items[i].submenu == "") + continue; + + Node *n = get_node(items[i].submenu); + if (!n) + continue; + + PopupMenu *pm = Object::cast_to<PopupMenu>(n); + if (!pm || !pm->is_visible()) + continue; + + pm->hide(); + } } break; } } @@ -1012,8 +1027,7 @@ bool PopupMenu::activate_item_by_event(const Ref<InputEvent> &p_event, bool p_fo code |= KEY_MASK_SHIFT; } - int il = items.size(); - for (int i = 0; i < il; i++) { + for (int i = 0; i < items.size(); i++) { if (is_item_disabled(i) || items[i].shortcut_is_disabled) continue; @@ -1381,9 +1395,9 @@ void PopupMenu::_bind_methods() { ClassDB::bind_method(D_METHOD("_submenu_timeout"), &PopupMenu::_submenu_timeout); ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "items", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_items", "_get_items"); - ADD_PROPERTYNO(PropertyInfo(Variant::BOOL, "hide_on_item_selection"), "set_hide_on_item_selection", "is_hide_on_item_selection"); - ADD_PROPERTYNO(PropertyInfo(Variant::BOOL, "hide_on_checkable_item_selection"), "set_hide_on_checkable_item_selection", "is_hide_on_checkable_item_selection"); - ADD_PROPERTYNO(PropertyInfo(Variant::BOOL, "hide_on_state_item_selection"), "set_hide_on_state_item_selection", "is_hide_on_state_item_selection"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "hide_on_item_selection"), "set_hide_on_item_selection", "is_hide_on_item_selection"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "hide_on_checkable_item_selection"), "set_hide_on_checkable_item_selection", "is_hide_on_checkable_item_selection"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "hide_on_state_item_selection"), "set_hide_on_state_item_selection", "is_hide_on_state_item_selection"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "submenu_popup_delay"), "set_submenu_popup_delay", "get_submenu_popup_delay"); ADD_SIGNAL(MethodInfo("id_pressed", PropertyInfo(Variant::INT, "ID"))); @@ -1411,6 +1425,7 @@ PopupMenu::PopupMenu() { set_hide_on_item_selection(true); set_hide_on_checkable_item_selection(true); set_hide_on_multistate_item_selection(false); + set_hide_on_window_lose_focus(true); submenu_timer = memnew(Timer); submenu_timer->set_wait_time(0.3); diff --git a/scene/gui/popup_menu.h b/scene/gui/popup_menu.h index a06a17c9fe..767ff568fe 100644 --- a/scene/gui/popup_menu.h +++ b/scene/gui/popup_menu.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/progress_bar.cpp b/scene/gui/progress_bar.cpp index fc5d56237a..264eda4035 100644 --- a/scene/gui/progress_bar.cpp +++ b/scene/gui/progress_bar.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -39,9 +39,12 @@ Size2 ProgressBar::get_minimum_size() const { Size2 minimum_size = bg->get_minimum_size(); minimum_size.height = MAX(minimum_size.height, fg->get_minimum_size().height); minimum_size.width = MAX(minimum_size.width, fg->get_minimum_size().width); - //if (percent_visible) { this is needed, else the progressbar will collapse - minimum_size.height = MAX(minimum_size.height, bg->get_minimum_size().height + font->get_height()); - //} + if (percent_visible) { + minimum_size.height = MAX(minimum_size.height, bg->get_minimum_size().height + font->get_height()); + } else { // this is needed, else the progressbar will collapse + minimum_size.width = MAX(minimum_size.width, 1); + minimum_size.height = MAX(minimum_size.height, 1); + } return minimum_size; } @@ -92,5 +95,6 @@ void ProgressBar::_bind_methods() { ProgressBar::ProgressBar() { set_v_size_flags(0); + set_step(0.01); percent_visible = true; } diff --git a/scene/gui/progress_bar.h b/scene/gui/progress_bar.h index d091c983b1..6157183e0f 100644 --- a/scene/gui/progress_bar.h +++ b/scene/gui/progress_bar.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/range.cpp b/scene/gui/range.cpp index 09d8664240..c24e62c8cb 100644 --- a/scene/gui/range.cpp +++ b/scene/gui/range.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,6 +30,19 @@ #include "range.h" +String Range::get_configuration_warning() const { + String warning = Control::get_configuration_warning(); + + if (shared->exp_ratio && shared->min <= 0) { + if (warning != String()) { + warning += "\n"; + } + warning += TTR("If exp_edit is true min_value must be > 0."); + } + + return warning; +} + void Range::_value_changed_notify() { _value_changed(shared->val); @@ -66,10 +79,11 @@ void Range::Shared::emit_changed(const char *p_what) { } void Range::set_value(double p_val) { + if (shared->step > 0) + p_val = Math::round(p_val / shared->step) * shared->step; - if (_rounded_values) { + if (_rounded_values) p_val = Math::round(p_val); - } if (!shared->allow_greater && p_val > shared->max - shared->page) p_val = shared->max - shared->page; @@ -90,6 +104,8 @@ void Range::set_min(double p_min) { set_value(shared->val); shared->emit_changed("min"); + + update_configuration_warning(); } void Range::set_max(double p_max) { @@ -277,6 +293,8 @@ bool Range::is_using_rounded_values() const { void Range::set_exp_ratio(bool p_enable) { shared->exp_ratio = p_enable; + + update_configuration_warning(); } bool Range::is_ratio_exp() const { diff --git a/scene/gui/range.h b/scene/gui/range.h index 125f559248..cf0add8c89 100644 --- a/scene/gui/range.h +++ b/scene/gui/range.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -97,6 +97,8 @@ public: void share(Range *p_range); void unshare(); + virtual String get_configuration_warning() const; + Range(); ~Range(); }; diff --git a/scene/gui/reference_rect.cpp b/scene/gui/reference_rect.cpp index 74e68598f4..553e133946 100644 --- a/scene/gui/reference_rect.cpp +++ b/scene/gui/reference_rect.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,7 +30,7 @@ #include "reference_rect.h" -#include "engine.h" +#include "core/engine.h" void ReferenceRect::_notification(int p_what) { diff --git a/scene/gui/reference_rect.h b/scene/gui/reference_rect.h index 9fad1a06b0..de3ccaeeca 100644 --- a/scene/gui/reference_rect.h +++ b/scene/gui/reference_rect.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp index a5f9bea1b1..9bcf10d5e7 100644 --- a/scene/gui/rich_text_label.cpp +++ b/scene/gui/rich_text_label.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -29,12 +29,13 @@ /*************************************************************************/ #include "rich_text_label.h" -#include "os/keyboard.h" -#include "os/os.h" + +#include "core/os/keyboard.h" +#include "core/os/os.h" #include "scene/scene_string_names.h" #ifdef TOOLS_ENABLED -#include "editor/editor_node.h" +#include "editor/editor_scale.h" #endif RichTextLabel::Item *RichTextLabel::_get_next_item(Item *p_item, bool p_free) { @@ -219,13 +220,14 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int & case ALIGN_LEFT: l.offset_caches.push_back(0); break; \ case ALIGN_CENTER: l.offset_caches.push_back(((p_width - margin) - used) / 2); break; \ case ALIGN_RIGHT: l.offset_caches.push_back(((p_width - margin) - used)); break; \ - case ALIGN_FILL: l.offset_caches.push_back((p_width - margin) - used /*+spaces_size*/); break; \ + case ALIGN_FILL: l.offset_caches.push_back(line_wrapped ? ((p_width - margin) - used) : 0); break; \ } \ l.height_caches.push_back(line_height); \ l.ascent_caches.push_back(line_ascent); \ l.descent_caches.push_back(line_descent); \ l.space_caches.push_back(spaces); \ } \ + line_wrapped = false; \ y += line_height + get_constant(SceneStringNames::get_singleton()->line_separation); \ line_height = 0; \ line_ascent = 0; \ @@ -253,6 +255,7 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int & l.minimum_width = MAX(l.minimum_width, m_width); \ } \ if (wofs + m_width > p_width) { \ + line_wrapped = true; \ if (p_mode == PROCESS_CACHE) { \ if (spaces > 0) \ spaces -= 1; \ @@ -297,6 +300,7 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int & int rchar = 0; int lh = 0; bool line_is_blank = true; + bool line_wrapped = false; int fh = 0; while (it) { @@ -319,14 +323,17 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int & Color color; Color font_color_shadow; bool underline = false; + bool strikethrough = false; if (p_mode == PROCESS_DRAW) { color = _find_color(text, p_base_color); font_color_shadow = _find_color(text, p_font_color_shadow); - underline = _find_underline(text); - if (_find_meta(text, &meta) && underline_meta) { + if (_find_underline(text) || (_find_meta(text, &meta) && underline_meta)) { underline = true; + } else if (_find_strikethrough(text)) { + + strikethrough = true; } } else if (p_mode == PROCESS_CACHE) { @@ -417,7 +424,7 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int & int cw = 0; - bool visible = visible_characters < 0 || p_char_count < visible_characters && YRANGE_VISIBLE(y + lh - line_descent - line_ascent, line_ascent + line_descent); + bool visible = visible_characters < 0 || (p_char_count < visible_characters && YRANGE_VISIBLE(y + lh - line_descent - line_ascent, line_ascent + line_descent)); if (visible) line_is_blank = false; @@ -468,6 +475,15 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int & underline_width *= EDSCALE; #endif VS::get_singleton()->canvas_item_add_line(ci, p_ofs + Point2(align_ofs + wofs, uy), p_ofs + Point2(align_ofs + wofs + w, uy), uc, underline_width); + } else if (strikethrough) { + Color uc = color; + uc.a *= 0.5; + int uy = y + lh / 2 - line_descent + 2; + float strikethrough_width = 1.0; +#ifdef TOOLS_ENABLED + strikethrough_width *= EDSCALE; +#endif + VS::get_singleton()->canvas_item_add_line(ci, p_ofs + Point2(align_ofs + wofs, uy), p_ofs + Point2(align_ofs + wofs + w, uy), uc, strikethrough_width); } } @@ -496,7 +512,7 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int & ENSURE_WIDTH(img->image->get_width()); - bool visible = visible_characters < 0 || p_char_count < visible_characters && YRANGE_VISIBLE(y + lh - font->get_descent() - img->image->get_height(), img->image->get_height()); + bool visible = visible_characters < 0 || (p_char_count < visible_characters && YRANGE_VISIBLE(y + lh - font->get_descent() - img->image->get_height(), img->image->get_height())); if (visible) line_is_blank = false; @@ -528,7 +544,7 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int & Vector2 draw_ofs = Point2(wofs, y); Color font_color_shadow = get_color("font_color_shadow"); bool use_outline = get_constant("shadow_as_outline"); - Point2 shadow_ofs(get_constant("shadow_offset_x"), get_constant("shadow_offset_y")); + Point2 shadow_ofs2(get_constant("shadow_offset_x"), get_constant("shadow_offset_y")); if (p_mode == PROCESS_CACHE) { @@ -552,7 +568,7 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int & for (int i = 0; i < frame->lines.size(); i++) { - _process_line(frame, Point2(), ly, available_width, i, PROCESS_CACHE, cfont, Color(), font_color_shadow, use_outline, shadow_ofs); + _process_line(frame, Point2(), ly, available_width, i, PROCESS_CACHE, cfont, Color(), font_color_shadow, use_outline, shadow_ofs2); table->columns.write[column].min_width = MAX(table->columns[column].min_width, frame->lines[i].minimum_width); table->columns.write[column].max_width = MAX(table->columns[column].max_width, frame->lines[i].maximum_width); } @@ -625,7 +641,7 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int & for (int i = 0; i < frame->lines.size(); i++) { int ly = 0; - _process_line(frame, Point2(), ly, table->columns[column].width, i, PROCESS_CACHE, cfont, Color(), font_color_shadow, use_outline, shadow_ofs); + _process_line(frame, Point2(), ly, table->columns[column].width, i, PROCESS_CACHE, cfont, Color(), font_color_shadow, use_outline, shadow_ofs2); frame->lines.write[i].height_cache = ly; //actual height frame->lines.write[i].height_accum_cache = ly; //actual height } @@ -658,9 +674,9 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int & if (visible) { if (p_mode == PROCESS_DRAW) { - nonblank_line_count += _process_line(frame, p_ofs + offset + draw_ofs + Vector2(0, yofs), ly, table->columns[column].width, i, PROCESS_DRAW, cfont, ccolor, font_color_shadow, use_outline, shadow_ofs); + nonblank_line_count += _process_line(frame, p_ofs + offset + draw_ofs + Vector2(0, yofs), ly, table->columns[column].width, i, PROCESS_DRAW, cfont, ccolor, font_color_shadow, use_outline, shadow_ofs2); } else if (p_mode == PROCESS_POINTER) { - _process_line(frame, p_ofs + offset + draw_ofs + Vector2(0, yofs), ly, table->columns[column].width, i, PROCESS_POINTER, cfont, ccolor, font_color_shadow, use_outline, shadow_ofs, p_click_pos, r_click_item, r_click_char, r_outside); + _process_line(frame, p_ofs + offset + draw_ofs + Vector2(0, yofs), ly, table->columns[column].width, i, PROCESS_POINTER, cfont, ccolor, font_color_shadow, use_outline, shadow_ofs2, p_click_pos, r_click_item, r_click_char, r_outside); if (r_click_item && *r_click_item) { RETURN; // exit early } @@ -749,20 +765,19 @@ void RichTextLabel::_update_scroll() { if (exceeds) { scroll_visible = true; - main->first_invalid_line = 0; scroll_w = vscroll->get_combined_minimum_size().width; vscroll->show(); vscroll->set_anchor_and_margin(MARGIN_LEFT, ANCHOR_END, -scroll_w); - _validate_line_caches(main); - } else { - scroll_visible = false; - vscroll->hide(); scroll_w = 0; - _validate_line_caches(main); + vscroll->hide(); } + + main->first_invalid_line = 0; //invalidate ALL + _validate_line_caches(main); } + scroll_updated = true; } void RichTextLabel::_notification(int p_what) { @@ -834,8 +849,6 @@ void RichTextLabel::_notification(int p_what) { bool use_outline = get_constant("shadow_as_outline"); Point2 shadow_ofs(get_constant("shadow_offset_x"), get_constant("shadow_offset_y")); - float x_ofs = 0; - visible_line_count = 0; while (y < size.height && from_line < main->lines.size()) { @@ -853,7 +866,6 @@ void RichTextLabel::_find_click(ItemFrame *p_frame, const Point2i &p_click, Item if (r_click_item) *r_click_item = NULL; - Size2 size = get_size(); Rect2 text_rect = _get_text_rect(); int ofs = vscroll->get_value(); Color font_color_shadow = get_color("font_color_shadow"); @@ -918,6 +930,7 @@ void RichTextLabel::_gui_input(Ref<InputEvent> p_event) { if (true) { if (b->is_pressed() && !b->is_doubleclick()) { + scroll_updated = false; int line = 0; Item *item = NULL; @@ -926,12 +939,7 @@ void RichTextLabel::_gui_input(Ref<InputEvent> p_event) { if (item) { - Variant meta; - if (!outside && _find_meta(item, &meta)) { - //meta clicked - - emit_signal("meta_clicked", meta); - } else if (selection.enabled) { + if (selection.enabled) { selection.click = item; selection.click_char = line; @@ -980,6 +988,24 @@ void RichTextLabel::_gui_input(Ref<InputEvent> p_event) { } else if (!b->is_pressed()) { selection.click = NULL; + + if (!b->is_doubleclick() && !scroll_updated) { + int line = 0; + Item *item = NULL; + + bool outside; + _find_click(main, b->get_position(), &item, &line, &outside); + + if (item) { + + Variant meta; + if (!outside && _find_meta(item, &meta)) { + //meta clicked + + emit_signal("meta_clicked", meta); + } + } + } } } } @@ -1107,12 +1133,13 @@ void RichTextLabel::_gui_input(Ref<InputEvent> p_event) { } Variant meta; - if (item && !outside && _find_meta(item, &meta)) { - if (meta_hovering != item) { + ItemMeta *item_meta; + if (item && !outside && _find_meta(item, &meta, &item_meta)) { + if (meta_hovering != item_meta) { if (meta_hovering) { emit_signal("meta_hover_ended", current_meta); } - meta_hovering = static_cast<ItemMeta *>(item); + meta_hovering = item_meta; current_meta = meta; emit_signal("meta_hover_started", meta); } @@ -1226,7 +1253,24 @@ bool RichTextLabel::_find_underline(Item *p_item) { return false; } -bool RichTextLabel::_find_meta(Item *p_item, Variant *r_meta) { +bool RichTextLabel::_find_strikethrough(Item *p_item) { + + Item *item = p_item; + + while (item) { + + if (item->type == ITEM_STRIKETHROUGH) { + + return true; + } + + item = item->parent; + } + + return false; +} + +bool RichTextLabel::_find_meta(Item *p_item, Variant *r_meta, ItemMeta **r_item) { Item *item = p_item; @@ -1237,6 +1281,8 @@ bool RichTextLabel::_find_meta(Item *p_item, Variant *r_meta) { ItemMeta *meta = static_cast<ItemMeta *>(item); if (r_meta) *r_meta = meta->meta; + if (r_item) + *r_item = meta; return true; } @@ -1423,18 +1469,28 @@ bool RichTextLabel::remove_line(const int p_line) { if (p_line >= current_frame->lines.size() || p_line < 0) return false; - int lines = p_line * 2; + int i = 0; + while (i < current->subitems.size() && current->subitems[i]->line < p_line) { + i++; + } - if (current->subitems[lines]->type != ITEM_NEWLINE) - _remove_item(current->subitems[lines], current->subitems[lines]->line, lines); + bool was_newline = false; + while (i < current->subitems.size()) { + was_newline = current->subitems[i]->type == ITEM_NEWLINE; + _remove_item(current->subitems[i], current->subitems[i]->line, p_line); + if (was_newline) + break; + } - _remove_item(current->subitems[lines], current->subitems[lines]->line, lines); + if (!was_newline) { + current_frame->lines.remove(p_line); + } - if (p_line == 0) { + if (p_line == 0 && current->subitems.size() > 0) main->lines.write[0].from = main; - } main->first_invalid_line = 0; + return true; } @@ -1447,6 +1503,7 @@ void RichTextLabel::push_font(const Ref<Font> &p_font) { item->font = p_font; _add_item(item, true); } + void RichTextLabel::push_color(const Color &p_color) { ERR_FAIL_COND(current->type == ITEM_TABLE); @@ -1455,6 +1512,7 @@ void RichTextLabel::push_color(const Color &p_color) { item->color = p_color; _add_item(item, true); } + void RichTextLabel::push_underline() { ERR_FAIL_COND(current->type == ITEM_TABLE); @@ -1463,6 +1521,14 @@ void RichTextLabel::push_underline() { _add_item(item, true); } +void RichTextLabel::push_strikethrough() { + + ERR_FAIL_COND(current->type == ITEM_TABLE); + ItemStrikethrough *item = memnew(ItemStrikethrough); + + _add_item(item, true); +} + void RichTextLabel::push_align(Align p_align) { ERR_FAIL_COND(current->type == ITEM_TABLE); @@ -1672,7 +1738,7 @@ Error RichTextLabel::append_bbcode(const String &p_bbcode) { } if (brk_pos == p_bbcode.length()) - break; //nothing else o add + break; //nothing else to add int brk_end = p_bbcode.find("]", brk_pos + 1); @@ -1738,7 +1804,7 @@ Error RichTextLabel::append_bbcode(const String &p_bbcode) { int columns = tag.substr(6, tag.length()).to_int(); if (columns < 1) columns = 1; - //use monospace font + push_table(columns); pos = brk_end + 1; tag_stack.push_front("table"); @@ -1752,7 +1818,7 @@ Error RichTextLabel::append_bbcode(const String &p_bbcode) { int ratio = tag.substr(5, tag.length()).to_int(); if (ratio < 1) ratio = 1; - //use monospace font + set_table_column_expand(get_current_table_column(), true, ratio); push_cell(); pos = brk_end + 1; @@ -1765,43 +1831,37 @@ Error RichTextLabel::append_bbcode(const String &p_bbcode) { tag_stack.push_front(tag); } else if (tag == "s") { - //use strikethrough (not supported underline instead) - push_underline(); + //use strikethrough + push_strikethrough(); pos = brk_end + 1; tag_stack.push_front(tag); } else if (tag == "center") { - //use underline push_align(ALIGN_CENTER); pos = brk_end + 1; tag_stack.push_front(tag); } else if (tag == "fill") { - //use underline push_align(ALIGN_FILL); pos = brk_end + 1; tag_stack.push_front(tag); } else if (tag == "right") { - //use underline push_align(ALIGN_RIGHT); pos = brk_end + 1; tag_stack.push_front(tag); } else if (tag == "ul") { - //use underline push_list(LIST_DOTS); pos = brk_end + 1; tag_stack.push_front(tag); } else if (tag == "ol") { - //use underline push_list(LIST_NUMBERS); pos = brk_end + 1; tag_stack.push_front(tag); } else if (tag == "indent") { - //use underline indent_level++; push_indent(indent_level); pos = brk_end + 1; @@ -1809,7 +1869,6 @@ Error RichTextLabel::append_bbcode(const String &p_bbcode) { } else if (tag == "url") { - //use strikethrough (not supported underline instead) int end = p_bbcode.find("[", brk_end); if (end == -1) end = p_bbcode.length(); @@ -1827,7 +1886,6 @@ Error RichTextLabel::append_bbcode(const String &p_bbcode) { tag_stack.push_front("url"); } else if (tag == "img") { - //use strikethrough (not supported underline instead) int end = p_bbcode.find("[", brk_end); if (end == -1) end = p_bbcode.length(); @@ -2134,6 +2192,7 @@ void RichTextLabel::_bind_methods() { ClassDB::bind_method(D_METHOD("push_list", "type"), &RichTextLabel::push_list); ClassDB::bind_method(D_METHOD("push_meta", "data"), &RichTextLabel::push_meta); ClassDB::bind_method(D_METHOD("push_underline"), &RichTextLabel::push_underline); + ClassDB::bind_method(D_METHOD("push_strikethrough"), &RichTextLabel::push_strikethrough); ClassDB::bind_method(D_METHOD("push_table", "columns"), &RichTextLabel::push_table); ClassDB::bind_method(D_METHOD("set_table_column_expand", "column", "expand", "ratio"), &RichTextLabel::set_table_column_expand); ClassDB::bind_method(D_METHOD("push_cell"), &RichTextLabel::push_cell); @@ -2194,7 +2253,7 @@ void RichTextLabel::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "meta_underlined"), "set_meta_underline", "is_meta_underlined"); ADD_PROPERTY(PropertyInfo(Variant::INT, "tab_size", PROPERTY_HINT_RANGE, "0,24,1"), "set_tab_size", "get_tab_size"); - ADD_PROPERTY(PropertyInfo(Variant::STRING, "text"), "set_text", "get_text"); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "text", PROPERTY_HINT_MULTILINE_TEXT), "set_text", "get_text"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "scroll_active"), "set_scroll_active", "is_scroll_active"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "scroll_following"), "set_scroll_follow", "is_scroll_following"); @@ -2222,6 +2281,7 @@ void RichTextLabel::_bind_methods() { BIND_ENUM_CONSTANT(ITEM_FONT); BIND_ENUM_CONSTANT(ITEM_COLOR); BIND_ENUM_CONSTANT(ITEM_UNDERLINE); + BIND_ENUM_CONSTANT(ITEM_STRIKETHROUGH); BIND_ENUM_CONSTANT(ITEM_ALIGN); BIND_ENUM_CONSTANT(ITEM_INDENT); BIND_ENUM_CONSTANT(ITEM_LIST); @@ -2282,10 +2342,11 @@ RichTextLabel::RichTextLabel() { updating_scroll = false; scroll_active = true; scroll_w = 0; + scroll_updated = false; vscroll = memnew(VScrollBar); add_child(vscroll); - vscroll->set_drag_slave(String("..")); + vscroll->set_drag_node(String("..")); vscroll->set_step(1); vscroll->set_anchor_and_margin(MARGIN_TOP, ANCHOR_BEGIN, 0); vscroll->set_anchor_and_margin(MARGIN_BOTTOM, ANCHOR_END, 0); diff --git a/scene/gui/rich_text_label.h b/scene/gui/rich_text_label.h index 06e9b8efe3..114c6103e2 100644 --- a/scene/gui/rich_text_label.h +++ b/scene/gui/rich_text_label.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -62,6 +62,7 @@ public: ITEM_FONT, ITEM_COLOR, ITEM_UNDERLINE, + ITEM_STRIKETHROUGH, ITEM_ALIGN, ITEM_INDENT, ITEM_LIST, @@ -164,6 +165,11 @@ private: ItemUnderline() { type = ITEM_UNDERLINE; } }; + struct ItemStrikethrough : public Item { + + ItemStrikethrough() { type = ITEM_STRIKETHROUGH; } + }; + struct ItemMeta : public Item { Variant meta; @@ -219,6 +225,7 @@ private: bool scroll_following; bool scroll_active; int scroll_w; + bool scroll_updated; bool updating_scroll; int current_idx; int visible_line_count; @@ -277,7 +284,8 @@ private: Align _find_align(Item *p_item); Color _find_color(Item *p_item, const Color &p_default_color); bool _find_underline(Item *p_item); - bool _find_meta(Item *p_item, Variant *r_meta); + bool _find_strikethrough(Item *p_item); + bool _find_meta(Item *p_item, Variant *r_meta, ItemMeta **r_item = NULL); void _update_scroll(); void _scroll_changed(double); @@ -307,6 +315,7 @@ public: void push_font(const Ref<Font> &p_font); void push_color(const Color &p_color); void push_underline(); + void push_strikethrough(); void push_align(Align p_align); void push_indent(int p_level); void push_list(ListType p_list); diff --git a/scene/gui/scroll_bar.cpp b/scene/gui/scroll_bar.cpp index e5bd1c453d..2938654ed9 100644 --- a/scene/gui/scroll_bar.cpp +++ b/scene/gui/scroll_bar.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,9 +30,9 @@ #include "scroll_bar.h" -#include "os/keyboard.h" -#include "os/os.h" -#include "print_string.h" +#include "core/os/keyboard.h" +#include "core/os/os.h" +#include "core/print_string.h" bool ScrollBar::focus_by_default = false; @@ -300,24 +300,24 @@ void ScrollBar::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE) { - if (has_node(drag_slave_path)) { - Node *n = get_node(drag_slave_path); - drag_slave = Object::cast_to<Control>(n); + if (has_node(drag_node_path)) { + Node *n = get_node(drag_node_path); + drag_node = Object::cast_to<Control>(n); } - if (drag_slave) { - drag_slave->connect("gui_input", this, "_drag_slave_input"); - drag_slave->connect("tree_exiting", this, "_drag_slave_exit", varray(), CONNECT_ONESHOT); + if (drag_node) { + drag_node->connect("gui_input", this, "_drag_node_input"); + drag_node->connect("tree_exiting", this, "_drag_node_exit", varray(), CONNECT_ONESHOT); } } if (p_what == NOTIFICATION_EXIT_TREE) { - if (drag_slave) { - drag_slave->disconnect("gui_input", this, "_drag_slave_input"); - drag_slave->disconnect("tree_exiting", this, "_drag_slave_exit"); + if (drag_node) { + drag_node->disconnect("gui_input", this, "_drag_node_input"); + drag_node->disconnect("tree_exiting", this, "_drag_node_exit"); } - drag_slave = NULL; + drag_node = NULL; } if (p_what == NOTIFICATION_INTERNAL_PHYSICS_PROCESS) { @@ -330,6 +330,8 @@ void ScrollBar::_notification(int p_what) { if (Math::abs(vel) >= dist) { set_value(target_scroll); + scrolling = false; + set_physics_process_internal(false); } else { set_value(get_value() + vel); } @@ -337,12 +339,13 @@ void ScrollBar::_notification(int p_what) { scrolling = false; set_physics_process_internal(false); } - } else if (drag_slave_touching) { - if (drag_slave_touching_deaccel) { + } else if (drag_node_touching) { + + if (drag_node_touching_deaccel) { Vector2 pos = Vector2(orientation == HORIZONTAL ? get_value() : 0, orientation == VERTICAL ? get_value() : 0); - pos += drag_slave_speed * get_physics_process_delta_time(); + pos += drag_node_speed * get_physics_process_delta_time(); bool turnoff = false; @@ -360,15 +363,15 @@ void ScrollBar::_notification(int p_what) { set_value(pos.x); - float sgn_x = drag_slave_speed.x < 0 ? -1 : 1; - float val_x = Math::abs(drag_slave_speed.x); + float sgn_x = drag_node_speed.x < 0 ? -1 : 1; + float val_x = Math::abs(drag_node_speed.x); val_x -= 1000 * get_physics_process_delta_time(); if (val_x < 0) { turnoff = true; } - drag_slave_speed.x = sgn_x * val_x; + drag_node_speed.x = sgn_x * val_x; } else { @@ -384,29 +387,29 @@ void ScrollBar::_notification(int p_what) { set_value(pos.y); - float sgn_y = drag_slave_speed.y < 0 ? -1 : 1; - float val_y = Math::abs(drag_slave_speed.y); + float sgn_y = drag_node_speed.y < 0 ? -1 : 1; + float val_y = Math::abs(drag_node_speed.y); val_y -= 1000 * get_physics_process_delta_time(); if (val_y < 0) { turnoff = true; } - drag_slave_speed.y = sgn_y * val_y; + drag_node_speed.y = sgn_y * val_y; } if (turnoff) { set_physics_process_internal(false); - drag_slave_touching = false; - drag_slave_touching_deaccel = false; + drag_node_touching = false; + drag_node_touching_deaccel = false; } } else { if (time_since_motion == 0 || time_since_motion > 0.1) { - Vector2 diff = drag_slave_accum - last_drag_slave_accum; - last_drag_slave_accum = drag_slave_accum; - drag_slave_speed = diff / get_physics_process_delta_time(); + Vector2 diff = drag_node_accum - last_drag_node_accum; + last_drag_node_accum = drag_node_accum; + drag_node_speed = diff / get_physics_process_delta_time(); } time_since_motion += get_physics_process_delta_time(); @@ -544,15 +547,15 @@ float ScrollBar::get_custom_step() const { return custom_step; } -void ScrollBar::_drag_slave_exit() { +void ScrollBar::_drag_node_exit() { - if (drag_slave) { - drag_slave->disconnect("gui_input", this, "_drag_slave_input"); + if (drag_node) { + drag_node->disconnect("gui_input", this, "_drag_node_input"); } - drag_slave = NULL; + drag_node = NULL; } -void ScrollBar::_drag_slave_input(const Ref<InputEvent> &p_input) { +void ScrollBar::_drag_node_input(const Ref<InputEvent> &p_input) { Ref<InputEventMouseButton> mb = p_input; @@ -563,43 +566,30 @@ void ScrollBar::_drag_slave_input(const Ref<InputEvent> &p_input) { if (mb->is_pressed()) { - if (drag_slave_touching) { - set_physics_process_internal(false); - drag_slave_touching_deaccel = false; - drag_slave_touching = false; - drag_slave_speed = Vector2(); - drag_slave_accum = Vector2(); - last_drag_slave_accum = Vector2(); - drag_slave_from = Vector2(); - } + drag_node_speed = Vector2(); + drag_node_accum = Vector2(); + last_drag_node_accum = Vector2(); + drag_node_from = Vector2(orientation == HORIZONTAL ? get_value() : 0, orientation == VERTICAL ? get_value() : 0); - if (true) { - drag_slave_speed = Vector2(); - 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_value() : 0, orientation == VERTICAL ? get_value() : 0); + drag_node_touching = OS::get_singleton()->has_touchscreen_ui_hint(); + drag_node_touching_deaccel = false; + time_since_motion = 0; - drag_slave_touching = OS::get_singleton()->has_touchscreen_ui_hint(); - drag_slave_touching_deaccel = false; + if (drag_node_touching) { + set_physics_process_internal(true); time_since_motion = 0; - if (drag_slave_touching) { - set_physics_process_internal(true); - time_since_motion = 0; - } } } else { - if (drag_slave_touching) { + if (drag_node_touching) { - if (drag_slave_speed == Vector2()) { - drag_slave_touching_deaccel = false; - drag_slave_touching = false; + if (drag_node_speed == Vector2()) { + drag_node_touching_deaccel = false; + drag_node_touching = false; set_physics_process_internal(false); } else { - - drag_slave_touching_deaccel = true; + drag_node_touching_deaccel = true; } } } @@ -609,60 +599,54 @@ void ScrollBar::_drag_slave_input(const Ref<InputEvent> &p_input) { if (mm.is_valid()) { - if (drag_slave_touching && !drag_slave_touching_deaccel) { + if (drag_node_touching && !drag_node_touching_deaccel) { Vector2 motion = Vector2(mm->get_relative().x, mm->get_relative().y); - drag_slave_accum -= motion; - Vector2 diff = drag_slave_from + drag_slave_accum; + drag_node_accum -= motion; + Vector2 diff = drag_node_from + drag_node_accum; if (orientation == HORIZONTAL) set_value(diff.x); - /* - else - drag_slave_accum.x=0; - */ + if (orientation == VERTICAL) set_value(diff.y); - /* - else - drag_slave_accum.y=0; - */ + time_since_motion = 0; } } } -void ScrollBar::set_drag_slave(const NodePath &p_path) { +void ScrollBar::set_drag_node(const NodePath &p_path) { if (is_inside_tree()) { - if (drag_slave) { - drag_slave->disconnect("gui_input", this, "_drag_slave_input"); - drag_slave->disconnect("tree_exiting", this, "_drag_slave_exit"); + if (drag_node) { + drag_node->disconnect("gui_input", this, "_drag_node_input"); + drag_node->disconnect("tree_exiting", this, "_drag_node_exit"); } } - drag_slave = NULL; - drag_slave_path = p_path; + drag_node = NULL; + drag_node_path = p_path; if (is_inside_tree()) { if (has_node(p_path)) { Node *n = get_node(p_path); - drag_slave = Object::cast_to<Control>(n); + drag_node = Object::cast_to<Control>(n); } - if (drag_slave) { - drag_slave->connect("gui_input", this, "_drag_slave_input"); - drag_slave->connect("tree_exiting", this, "_drag_slave_exit", varray(), CONNECT_ONESHOT); + if (drag_node) { + drag_node->connect("gui_input", this, "_drag_node_input"); + drag_node->connect("tree_exiting", this, "_drag_node_exit", varray(), CONNECT_ONESHOT); } } } -NodePath ScrollBar::get_drag_slave() const { +NodePath ScrollBar::get_drag_node() const { - return drag_slave_path; + return drag_node_path; } void ScrollBar::set_smooth_scroll_enabled(bool p_enable) { @@ -678,8 +662,8 @@ void ScrollBar::_bind_methods() { ClassDB::bind_method(D_METHOD("_gui_input"), &ScrollBar::_gui_input); ClassDB::bind_method(D_METHOD("set_custom_step", "step"), &ScrollBar::set_custom_step); ClassDB::bind_method(D_METHOD("get_custom_step"), &ScrollBar::get_custom_step); - ClassDB::bind_method(D_METHOD("_drag_slave_input"), &ScrollBar::_drag_slave_input); - ClassDB::bind_method(D_METHOD("_drag_slave_exit"), &ScrollBar::_drag_slave_exit); + ClassDB::bind_method(D_METHOD("_drag_node_input"), &ScrollBar::_drag_node_input); + ClassDB::bind_method(D_METHOD("_drag_node_exit"), &ScrollBar::_drag_node_exit); ADD_SIGNAL(MethodInfo("scrolling")); @@ -691,13 +675,13 @@ ScrollBar::ScrollBar(Orientation p_orientation) { orientation = p_orientation; highlight = HIGHLIGHT_NONE; custom_step = -1; - drag_slave = NULL; + drag_node = NULL; drag.active = false; - drag_slave_speed = Vector2(); - drag_slave_touching = false; - drag_slave_touching_deaccel = false; + drag_node_speed = Vector2(); + drag_node_touching = false; + drag_node_touching_deaccel = false; scrolling = false; target_scroll = 0; diff --git a/scene/gui/scroll_bar.h b/scene/gui/scroll_bar.h index 15e037f8bb..5ceabfc06b 100644 --- a/scene/gui/scroll_bar.h +++ b/scene/gui/scroll_bar.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -36,6 +36,7 @@ /** @author Juan Linietsky <reduzio@gmail.com> */ + class ScrollBar : public Range { GDCLASS(ScrollBar, Range); @@ -71,25 +72,25 @@ class ScrollBar : public Range { static void set_can_focus_by_default(bool p_can_focus); - Node *drag_slave; - NodePath drag_slave_path; + Node *drag_node; + NodePath drag_node_path; - Vector2 drag_slave_speed; - Vector2 drag_slave_accum; - Vector2 drag_slave_from; - Vector2 last_drag_slave_accum; - float last_drag_slave_time; + Vector2 drag_node_speed; + Vector2 drag_node_accum; + Vector2 drag_node_from; + Vector2 last_drag_node_accum; + float last_drag_node_time; float time_since_motion; - bool drag_slave_touching; - bool drag_slave_touching_deaccel; + bool drag_node_touching; + bool drag_node_touching_deaccel; bool click_handled; bool scrolling; double target_scroll; bool smooth_scroll_enabled; - void _drag_slave_exit(); - void _drag_slave_input(const Ref<InputEvent> &p_input); + void _drag_node_exit(); + void _drag_node_input(const Ref<InputEvent> &p_input); void _gui_input(Ref<InputEvent> p_event); @@ -102,8 +103,8 @@ public: void set_custom_step(float p_custom_step); float get_custom_step() const; - void set_drag_slave(const NodePath &p_path); - NodePath get_drag_slave() const; + void set_drag_node(const NodePath &p_path); + NodePath get_drag_node() const; void set_smooth_scroll_enabled(bool p_enable); bool is_smooth_scroll_enabled() const; diff --git a/scene/gui/scroll_container.cpp b/scene/gui/scroll_container.cpp index 977d345ca8..e50a71b0ff 100644 --- a/scene/gui/scroll_container.cpp +++ b/scene/gui/scroll_container.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -29,7 +29,8 @@ /*************************************************************************/ #include "scroll_container.h" -#include "os/os.h" +#include "core/os/os.h" + bool ScrollContainer::clips_input() const { return true; @@ -170,7 +171,7 @@ void ScrollContainer::_gui_input(const Ref<InputEvent> &p_gui_input) { Vector2 motion = Vector2(mm->get_relative().x, mm->get_relative().y); drag_accum -= motion; - if (beyond_deadzone || scroll_h && Math::abs(drag_accum.x) > deadzone || scroll_v && Math::abs(drag_accum.y) > deadzone) { + if (beyond_deadzone || (scroll_h && Math::abs(drag_accum.x) > deadzone) || (scroll_v && Math::abs(drag_accum.y) > deadzone)) { if (!beyond_deadzone) { propagate_notification(NOTIFICATION_SCROLL_BEGIN); emit_signal("scroll_started"); @@ -245,7 +246,7 @@ void ScrollContainer::_notification(int p_what) { size.y -= h_scroll->get_minimum_size().y; if (v_scroll->is_visible_in_tree() && v_scroll->get_parent() == this) //scrolls may have been moved out for reasons - size.x -= h_scroll->get_minimum_size().x; + size.x -= v_scroll->get_minimum_size().x; for (int i = 0; i < get_child_count(); i++) { @@ -270,7 +271,6 @@ void ScrollContainer::_notification(int p_what) { } if (!scroll_v || (!v_scroll->is_visible_in_tree() && c->get_v_size_flags() & SIZE_EXPAND)) { r.position.y = 0; - r.size.height = size.height; if (c->get_v_size_flags() & SIZE_EXPAND) r.size.height = MAX(size.height, minsize.height); else diff --git a/scene/gui/scroll_container.h b/scene/gui/scroll_container.h index abef80294a..2ab169f4d0 100644 --- a/scene/gui/scroll_container.h +++ b/scene/gui/scroll_container.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/separator.cpp b/scene/gui/separator.cpp index cd0b06da81..a717420b9b 100644 --- a/scene/gui/separator.cpp +++ b/scene/gui/separator.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* 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 7949c7ca9b..54ad9b5bb5 100644 --- a/scene/gui/separator.h +++ b/scene/gui/separator.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* 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/shortcut.cpp b/scene/gui/shortcut.cpp index 36490cf254..400fdca082 100644 --- a/scene/gui/shortcut.cpp +++ b/scene/gui/shortcut.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,7 +30,7 @@ #include "shortcut.h" -#include "os/keyboard.h" +#include "core/os/keyboard.h" void ShortCut::set_shortcut(const Ref<InputEvent> &p_shortcut) { diff --git a/scene/gui/shortcut.h b/scene/gui/shortcut.h index f9240642bf..df0623ed50 100644 --- a/scene/gui/shortcut.h +++ b/scene/gui/shortcut.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,8 +31,8 @@ #ifndef SHORTCUT_H #define SHORTCUT_H -#include "os/input_event.h" -#include "resource.h" +#include "core/os/input_event.h" +#include "core/resource.h" class ShortCut : public Resource { diff --git a/scene/gui/slider.cpp b/scene/gui/slider.cpp index b820e2eafd..eb04b85931 100644 --- a/scene/gui/slider.cpp +++ b/scene/gui/slider.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -29,7 +29,7 @@ /*************************************************************************/ #include "slider.h" -#include "os/keyboard.h" +#include "core/os/keyboard.h" Size2 Slider::get_minimum_size() const { diff --git a/scene/gui/slider.h b/scene/gui/slider.h index 4d02348159..d0ab7baecf 100644 --- a/scene/gui/slider.h +++ b/scene/gui/slider.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/spin_box.cpp b/scene/gui/spin_box.cpp index 145981d498..d21143739c 100644 --- a/scene/gui/spin_box.cpp +++ b/scene/gui/spin_box.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -29,7 +29,7 @@ /*************************************************************************/ #include "spin_box.h" -#include "os/input.h" +#include "core/os/input.h" Size2 SpinBox::get_minimum_size() const { @@ -110,6 +110,9 @@ void SpinBox::_gui_input(const Ref<InputEvent> &p_event) { range_click_timer->start(); line_edit->grab_focus(); + + drag.allowed = true; + drag.capture_pos = mb->get_position(); } break; case BUTTON_RIGHT: { @@ -133,14 +136,7 @@ void SpinBox::_gui_input(const Ref<InputEvent> &p_event) { } } - if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == 1) { - - //set_default_cursor_shape(CURSOR_VSIZE); - Vector2 cpos = Vector2(mb->get_position().x, mb->get_position().y); - drag.mouse_pos = cpos; - } - - if (mb.is_valid() && !mb->is_pressed() && mb->get_button_index() == 1) { + if (mb.is_valid() && !mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) { //set_default_cursor_shape(CURSOR_ARROW); range_click_timer->stop(); @@ -150,32 +146,24 @@ void SpinBox::_gui_input(const Ref<InputEvent> &p_event) { Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_VISIBLE); warp_mouse(drag.capture_pos); } + drag.allowed = false; } Ref<InputEventMouseMotion> mm = p_event; - if (mm.is_valid() && mm->get_button_mask() & 1) { - - Vector2 cpos = mm->get_position(); + if (mm.is_valid() && mm->get_button_mask() & BUTTON_MASK_LEFT) { if (drag.enabled) { - float diff_y = drag.mouse_pos.y - cpos.y; - diff_y = Math::pow(ABS(diff_y), 1.8f) * SGN(diff_y); - diff_y *= 0.1; - - drag.mouse_pos = cpos; - drag.base_val = CLAMP(drag.base_val + get_step() * diff_y, get_min(), get_max()); - - set_value(drag.base_val); - - } else if (drag.mouse_pos.distance_to(cpos) > 2) { + drag.diff_y += mm->get_relative().y; + float diff_y = -0.01 * Math::pow(ABS(drag.diff_y), 1.8f) * SGN(drag.diff_y); + set_value(CLAMP(drag.base_val + get_step() * diff_y, get_min(), get_max())); + } else if (drag.allowed && drag.capture_pos.distance_to(mm->get_position()) > 2) { Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_CAPTURED); drag.enabled = true; drag.base_val = get_value(); - drag.mouse_pos = cpos; - drag.capture_pos = cpos; + drag.diff_y = 0; } } } @@ -217,6 +205,16 @@ void SpinBox::_notification(int p_what) { } } +void SpinBox::set_align(LineEdit::Align p_align) { + + line_edit->set_align(p_align); +} + +LineEdit::Align SpinBox::get_align() const { + + return line_edit->get_align(); +} + void SpinBox::set_suffix(const String &p_suffix) { suffix = p_suffix; @@ -253,6 +251,8 @@ void SpinBox::_bind_methods() { //ClassDB::bind_method(D_METHOD("_value_changed"),&SpinBox::_value_changed); ClassDB::bind_method(D_METHOD("_gui_input"), &SpinBox::_gui_input); ClassDB::bind_method(D_METHOD("_text_entered"), &SpinBox::_text_entered); + ClassDB::bind_method(D_METHOD("set_align", "align"), &SpinBox::set_align); + ClassDB::bind_method(D_METHOD("get_align"), &SpinBox::get_align); ClassDB::bind_method(D_METHOD("set_suffix", "suffix"), &SpinBox::set_suffix); ClassDB::bind_method(D_METHOD("get_suffix"), &SpinBox::get_suffix); ClassDB::bind_method(D_METHOD("set_prefix", "prefix"), &SpinBox::set_prefix); @@ -264,6 +264,7 @@ void SpinBox::_bind_methods() { ClassDB::bind_method(D_METHOD("_line_edit_input"), &SpinBox::_line_edit_input); ClassDB::bind_method(D_METHOD("_range_click_timeout"), &SpinBox::_range_click_timeout); + ADD_PROPERTY(PropertyInfo(Variant::INT, "align", PROPERTY_HINT_ENUM, "Left,Center,Right,Fill"), "set_align", "get_align"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "editable"), "set_editable", "is_editable"); ADD_PROPERTY(PropertyInfo(Variant::STRING, "prefix"), "set_prefix", "get_prefix"); ADD_PROPERTY(PropertyInfo(Variant::STRING, "suffix"), "set_suffix", "get_suffix"); diff --git a/scene/gui/spin_box.h b/scene/gui/spin_box.h index 8863f44bef..49dc6d950c 100644 --- a/scene/gui/spin_box.h +++ b/scene/gui/spin_box.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -54,10 +54,10 @@ class SpinBox : public Range { struct Drag { float base_val; + bool allowed; bool enabled; - Vector2 from; - Vector2 mouse_pos; Vector2 capture_pos; + float diff_y; } drag; void _line_edit_focus_exit(); @@ -76,6 +76,9 @@ public: virtual Size2 get_minimum_size() const; + void set_align(LineEdit::Align p_align); + LineEdit::Align get_align() const; + void set_editable(bool p_editable); bool is_editable() const; diff --git a/scene/gui/split_container.cpp b/scene/gui/split_container.cpp index c38c411333..e5d1844d39 100644 --- a/scene/gui/split_container.cpp +++ b/scene/gui/split_container.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -62,39 +62,28 @@ void SplitContainer::_resort() { // If we have only one element if (!first || !second) { if (first) { - fit_child_in_rect(_getch(0), Rect2(Point2(), get_size())); + fit_child_in_rect(first, Rect2(Point2(), get_size())); } else if (second) { - fit_child_in_rect(_getch(1), Rect2(Point2(), get_size())); + fit_child_in_rect(second, Rect2(Point2(), get_size())); } return; } // Determine expanded children - bool first_expanded = false; - bool second_expanded = false; - if (vertical) { - first_expanded = first->get_v_size_flags() & SIZE_EXPAND; - second_expanded = second->get_v_size_flags() & SIZE_EXPAND; - } else { - first_expanded = first->get_h_size_flags() & SIZE_EXPAND; - second_expanded = second->get_h_size_flags() & SIZE_EXPAND; - } + bool first_expanded = (vertical ? first->get_v_size_flags() : first->get_h_size_flags()) & SIZE_EXPAND; + bool second_expanded = (vertical ? second->get_v_size_flags() : second->get_h_size_flags()) & SIZE_EXPAND; // Determine the separation between items Ref<Texture> g = get_icon("grabber"); int sep = get_constant("separation"); - if (dragger_visibility == DRAGGER_HIDDEN_COLLAPSED) { - sep = 0; - } else { - sep = MAX(sep, vertical ? g->get_height() : g->get_width()); - } + sep = (dragger_visibility != DRAGGER_HIDDEN_COLLAPSED) ? MAX(sep, vertical ? g->get_height() : g->get_width()) : 0; // Compute the minimum size Size2 ms_first = first->get_combined_minimum_size(); Size2 ms_second = second->get_combined_minimum_size(); + // Compute the separator position without the split offset float ratio = first->get_stretch_ratio() / (first->get_stretch_ratio() + second->get_stretch_ratio()); - int no_offset_middle_sep = 0; if (first_expanded && second_expanded) { no_offset_middle_sep = get_size()[axis] * ratio - sep / 2; @@ -104,12 +93,16 @@ void SplitContainer::_resort() { no_offset_middle_sep = ms_first[axis]; } + // Compute the final middle separation middle_sep = no_offset_middle_sep; - middle_sep += (collapsed) ? 0 : split_offset; - middle_sep = MIN(middle_sep, get_size()[axis] - ms_second[axis] - sep); - middle_sep = MAX(middle_sep, ms_first[axis]); if (!collapsed) { - split_offset = middle_sep - no_offset_middle_sep; + int clamped_split_offset = CLAMP(split_offset, ms_first[axis] - no_offset_middle_sep, (get_size()[axis] - ms_second[axis] - sep) - no_offset_middle_sep); + middle_sep += clamped_split_offset; + if (should_clamp_split_offset) { + split_offset = clamped_split_offset; + _change_notify("split_offset"); + should_clamp_split_offset = false; + } } if (vertical) { @@ -123,7 +116,6 @@ void SplitContainer::_resort() { } update(); - _change_notify("split_offset"); } Size2 SplitContainer::get_minimum_size() const { @@ -131,8 +123,8 @@ Size2 SplitContainer::get_minimum_size() const { /* Calculate MINIMUM SIZE */ Size2i minimum; - int sep = get_constant("separation"); Ref<Texture> g = get_icon("grabber"); + int sep = get_constant("separation"); sep = (dragger_visibility != DRAGGER_HIDDEN_COLLAPSED) ? MAX(sep, vertical ? g->get_height() : g->get_width()) : 0; for (int i = 0; i < 2; i++) { @@ -172,34 +164,35 @@ void SplitContainer::_notification(int p_what) { _resort(); } break; - case NOTIFICATION_MOUSE_ENTER: { - - mouse_inside = true; - update(); - } break; case NOTIFICATION_MOUSE_EXIT: { mouse_inside = false; - update(); + if (get_constant("autohide")) + update(); } break; case NOTIFICATION_DRAW: { if (!_getch(0) || !_getch(1)) return; - if (collapsed || (!mouse_inside && get_constant("autohide"))) + if (collapsed || (!dragging && !mouse_inside && get_constant("autohide"))) + return; + + if (dragger_visibility != DRAGGER_VISIBLE) return; int sep = dragger_visibility != DRAGGER_HIDDEN_COLLAPSED ? get_constant("separation") : 0; Ref<Texture> tex = get_icon("grabber"); Size2 size = get_size(); - if (dragger_visibility == DRAGGER_VISIBLE) { - if (vertical) - draw_texture(tex, Point2i((size.x - tex->get_width()) / 2, middle_sep + (sep - tex->get_height()) / 2)); - else - draw_texture(tex, Point2i(middle_sep + (sep - tex->get_width()) / 2, (size.y - tex->get_height()) / 2)); - } + if (vertical) + draw_texture(tex, Point2i((size.x - tex->get_width()) / 2, middle_sep + (sep - tex->get_height()) / 2)); + else + draw_texture(tex, Point2i(middle_sep + (sep - tex->get_width()) / 2, (size.y - tex->get_height()) / 2)); + } break; + case NOTIFICATION_THEME_CHANGED: { + + minimum_size_changed(); } break; } } @@ -245,9 +238,26 @@ void SplitContainer::_gui_input(const Ref<InputEvent> &p_event) { Ref<InputEventMouseMotion> mm = p_event; - if (mm.is_valid() && dragging) { + if (mm.is_valid()) { + + bool mouse_inside_state = false; + if (vertical) + mouse_inside_state = mm->get_position().y > middle_sep && mm->get_position().y < middle_sep + get_constant("separation"); + else + mouse_inside_state = mm->get_position().x > middle_sep && mm->get_position().x < middle_sep + get_constant("separation"); + + if (mouse_inside != mouse_inside_state) { + + mouse_inside = mouse_inside_state; + if (get_constant("autohide")) + update(); + } + + if (!dragging) + return; split_offset = drag_ofs + ((vertical ? mm->get_position().y : mm->get_position().x) - drag_from); + should_clamp_split_offset = true; queue_sort(); emit_signal("dragged", get_split_offset()); } @@ -282,6 +292,7 @@ void SplitContainer::set_split_offset(int p_offset) { return; split_offset = p_offset; + queue_sort(); } @@ -290,6 +301,12 @@ int SplitContainer::get_split_offset() const { return split_offset; } +void SplitContainer::clamp_split_offset() { + should_clamp_split_offset = true; + + queue_sort(); +} + void SplitContainer::set_collapsed(bool p_collapsed) { if (collapsed == p_collapsed) @@ -319,8 +336,10 @@ bool SplitContainer::is_collapsed() const { void SplitContainer::_bind_methods() { ClassDB::bind_method(D_METHOD("_gui_input"), &SplitContainer::_gui_input); + ClassDB::bind_method(D_METHOD("set_split_offset", "offset"), &SplitContainer::set_split_offset); ClassDB::bind_method(D_METHOD("get_split_offset"), &SplitContainer::get_split_offset); + ClassDB::bind_method(D_METHOD("clamp_split_offset"), &SplitContainer::clamp_split_offset); ClassDB::bind_method(D_METHOD("set_collapsed", "collapsed"), &SplitContainer::set_collapsed); ClassDB::bind_method(D_METHOD("is_collapsed"), &SplitContainer::is_collapsed); @@ -343,6 +362,7 @@ SplitContainer::SplitContainer(bool p_vertical) { mouse_inside = false; split_offset = 0; + should_clamp_split_offset = false; middle_sep = 0; vertical = p_vertical; dragging = false; diff --git a/scene/gui/split_container.h b/scene/gui/split_container.h index 321f7fd3b7..3c1ca09a9f 100644 --- a/scene/gui/split_container.h +++ b/scene/gui/split_container.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -45,9 +45,10 @@ public: }; private: - bool vertical; + bool should_clamp_split_offset; int split_offset; int middle_sep; + bool vertical; bool dragging; int drag_from; int drag_ofs; @@ -67,6 +68,7 @@ protected: public: void set_split_offset(int p_offset); int get_split_offset() const; + void clamp_split_offset(); void set_collapsed(bool p_collapsed); bool is_collapsed() const; diff --git a/scene/gui/tab_container.cpp b/scene/gui/tab_container.cpp index c30fa96327..212efa4976 100644 --- a/scene/gui/tab_container.cpp +++ b/scene/gui/tab_container.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,7 +30,7 @@ #include "tab_container.h" -#include "message_queue.h" +#include "core/message_queue.h" #include "scene/gui/box_container.h" #include "scene/gui/label.h" #include "scene/gui/texture_rect.h" @@ -338,6 +338,7 @@ void TabContainer::_notification(int p_what) { } } break; case NOTIFICATION_THEME_CHANGED: { + minimum_size_changed(); call_deferred("_on_theme_changed"); //wait until all changed theme } break; } diff --git a/scene/gui/tab_container.h b/scene/gui/tab_container.h index 8a3c9d2bb2..c110f041d0 100644 --- a/scene/gui/tab_container.h +++ b/scene/gui/tab_container.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* 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/tabs.cpp b/scene/gui/tabs.cpp index 2075f7ce70..ac643c1320 100644 --- a/scene/gui/tabs.cpp +++ b/scene/gui/tabs.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,7 +30,7 @@ #include "tabs.h" -#include "message_queue.h" +#include "core/message_queue.h" #include "scene/gui/box_container.h" #include "scene/gui/label.h" #include "scene/gui/texture_rect.h" @@ -53,7 +53,7 @@ Size2 Tabs::get_minimum_size() const { ms.width += get_constant("hseparation"); } - ms.width += font->get_string_size(tabs[i].text).width; + ms.width += Math::ceil(font->get_string_size(tabs[i].text).width); if (tabs[i].disabled) ms.width += tab_disabled->get_minimum_size().width; @@ -106,41 +106,8 @@ void Tabs::_gui_input(const Ref<InputEvent> &p_event) { } } - // test hovering to display right or close button - int hover_now = -1; - int hover_buttons = -1; - for (int i = 0; i < tabs.size(); i++) { - - if (i < offset) - continue; - - Rect2 rect = get_tab_rect(i); - if (rect.has_point(pos)) { - hover_now = i; - } - if (tabs[i].rb_rect.has_point(pos)) { - rb_hover = i; - cb_hover = -1; - hover_buttons = i; - break; - } else if (!tabs[i].disabled && tabs[i].cb_rect.has_point(pos)) { - cb_hover = i; - rb_hover = -1; - hover_buttons = i; - break; - } - } - if (hover != hover_now) { - hover = hover_now; - emit_signal("tab_hover", hover); - } - - if (hover_buttons == -1) { // no hover - rb_hover = hover_buttons; - cb_hover = hover_buttons; - } + _update_hover(); update(); - return; } @@ -522,6 +489,48 @@ Ref<Texture> Tabs::get_tab_right_button(int p_tab) const { return tabs[p_tab].right_button; } +void Tabs::_update_hover() { + + if (!is_inside_tree()) { + return; + } + + const Point2 &pos = get_local_mouse_position(); + // test hovering to display right or close button + int hover_now = -1; + int hover_buttons = -1; + for (int i = 0; i < tabs.size(); i++) { + + if (i < offset) + continue; + + Rect2 rect = get_tab_rect(i); + if (rect.has_point(pos)) { + hover_now = i; + } + if (tabs[i].rb_rect.has_point(pos)) { + rb_hover = i; + cb_hover = -1; + hover_buttons = i; + break; + } else if (!tabs[i].disabled && tabs[i].cb_rect.has_point(pos)) { + cb_hover = i; + rb_hover = -1; + hover_buttons = i; + break; + } + } + if (hover != hover_now) { + hover = hover_now; + emit_signal("tab_hover", hover); + } + + if (hover_buttons == -1) { // no hover + rb_hover = hover_buttons; + cb_hover = hover_buttons; + } +} + void Tabs::_update_cache() { Ref<StyleBox> tab_disabled = get_stylebox("tab_disabled"); Ref<StyleBox> tab_bg = get_stylebox("tab_bg"); @@ -538,7 +547,7 @@ void Tabs::_update_cache() { for (int i = 0; i < tabs.size(); i++) { tabs.write[i].ofs_cache = mw; tabs.write[i].size_cache = get_tab_width(i); - tabs.write[i].size_text = font->get_string_size(tabs[i].text).width; + tabs.write[i].size_text = Math::ceil(font->get_string_size(tabs[i].text).width); mw += tabs[i].size_cache; if (tabs[i].size_cache <= min_width || i == current) { size_fixed += tabs[i].size_cache; @@ -597,6 +606,7 @@ void Tabs::add_tab(const String &p_str, const Ref<Texture> &p_icon) { tabs.push_back(t); _update_cache(); + call_deferred("_update_hover"); update(); minimum_size_changed(); } @@ -604,6 +614,7 @@ void Tabs::add_tab(const String &p_str, const Ref<Texture> &p_icon) { void Tabs::clear_tabs() { tabs.clear(); current = 0; + call_deferred("_update_hover"); update(); } @@ -614,6 +625,7 @@ void Tabs::remove_tab(int p_idx) { if (current >= p_idx) current--; _update_cache(); + call_deferred("_update_hover"); update(); minimum_size_changed(); @@ -791,7 +803,7 @@ int Tabs::get_tab_width(int p_idx) const { x += get_constant("hseparation"); } - x += font->get_string_size(tabs[p_idx].text).width; + x += Math::ceil(font->get_string_size(tabs[p_idx].text).width); if (tabs[p_idx].disabled) x += tab_disabled->get_minimum_size().width; @@ -931,6 +943,7 @@ bool Tabs::get_select_with_rmb() const { void Tabs::_bind_methods() { ClassDB::bind_method(D_METHOD("_gui_input"), &Tabs::_gui_input); + ClassDB::bind_method(D_METHOD("_update_hover"), &Tabs::_update_hover); ClassDB::bind_method(D_METHOD("get_tab_count"), &Tabs::get_tab_count); ClassDB::bind_method(D_METHOD("set_current_tab", "tab_idx"), &Tabs::set_current_tab); ClassDB::bind_method(D_METHOD("get_current_tab"), &Tabs::get_current_tab); @@ -970,7 +983,7 @@ void Tabs::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "current_tab", PROPERTY_HINT_RANGE, "-1,4096,1", PROPERTY_USAGE_EDITOR), "set_current_tab", "get_current_tab"); ADD_PROPERTY(PropertyInfo(Variant::INT, "tab_align", PROPERTY_HINT_ENUM, "Left,Center,Right"), "set_tab_align", "get_tab_align"); - ADD_PROPERTYNZ(PropertyInfo(Variant::INT, "tab_close_display_policy", PROPERTY_HINT_ENUM, "Show Never,Show Active Only,Show Always"), "set_tab_close_display_policy", "get_tab_close_display_policy"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "tab_close_display_policy", PROPERTY_HINT_ENUM, "Show Never,Show Active Only,Show Always"), "set_tab_close_display_policy", "get_tab_close_display_policy"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "scrolling_enabled"), "set_scrolling_enabled", "get_scrolling_enabled"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "drag_to_rearrange_enabled"), "set_drag_to_rearrange_enabled", "get_drag_to_rearrange_enabled"); diff --git a/scene/gui/tabs.h b/scene/gui/tabs.h index e204f4364b..7c54f1acf2 100644 --- a/scene/gui/tabs.h +++ b/scene/gui/tabs.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -97,6 +97,8 @@ private: int get_tab_width(int p_idx) const; void _ensure_no_over_offset(); + + void _update_hover(); void _update_cache(); protected: diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index ec98b01ced..2bf2364873 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,11 +30,11 @@ #include "text_edit.h" -#include "message_queue.h" -#include "os/input.h" -#include "os/keyboard.h" -#include "os/os.h" -#include "project_settings.h" +#include "core/message_queue.h" +#include "core/os/input.h" +#include "core/os/keyboard.h" +#include "core/os/os.h" +#include "core/project_settings.h" #include "scene/main/viewport.h" #ifdef TOOLS_ENABLED @@ -334,15 +334,12 @@ void TextEdit::_update_scrollbars() { h_scroll->set_begin(Point2(0, size.height - hmin.height)); h_scroll->set_end(Point2(size.width - vmin.width, size.height)); - int hscroll_rows = ((hmin.height - 1) / get_row_height()) + 1; int visible_rows = get_visible_rows(); - int total_rows = get_total_visible_rows(); if (scroll_past_end_of_file_enabled) { total_rows += visible_rows - 1; } - int vscroll_pixels = v_scroll->get_combined_minimum_size().width; int visible_width = size.width - cache.style_normal->get_minimum_size().width; int total_width = text.get_max_width(true) + vmin.x; @@ -367,12 +364,12 @@ void TextEdit::_update_scrollbars() { } else { - if (total_rows > visible_rows && total_width <= visible_width - vscroll_pixels) { + if (total_rows > visible_rows && total_width <= visible_width) { //thanks yessopie for this clever bit of logic use_hscroll = false; } - if (total_rows <= visible_rows - hscroll_rows && total_width > visible_width) { + if (total_rows <= visible_rows && total_width > visible_width) { //thanks yessopie for this clever bit of logic use_vscroll = false; } @@ -552,17 +549,17 @@ void TextEdit::_notification(int p_what) { MessageQueue::get_singleton()->push_call(this, "_cursor_changed_emit"); if (text_changed_dirty) MessageQueue::get_singleton()->push_call(this, "_text_changed_emit"); - update_wrap_at(); + _update_wrap_at(); } break; case NOTIFICATION_RESIZED: { - cache.size = get_size(); _update_scrollbars(); - update_wrap_at(); + call_deferred("_update_wrap_at"); } break; case NOTIFICATION_THEME_CHANGED: { _update_caches(); + _update_wrap_at(); } break; case MainLoop::NOTIFICATION_WM_FOCUS_IN: { window_has_focus = true; @@ -593,6 +590,7 @@ void TextEdit::_notification(int p_what) { } } break; case NOTIFICATION_DRAW: { + Size2 size = get_size(); if ((!has_focus() && !menu->has_focus()) || !window_has_focus) { draw_caret = false; } @@ -634,24 +632,22 @@ void TextEdit::_notification(int p_what) { RID ci = get_canvas_item(); VisualServer::get_singleton()->canvas_item_set_clip(get_canvas_item(), true); int xmargin_beg = cache.style_normal->get_margin(MARGIN_LEFT) + cache.line_number_w + cache.breakpoint_gutter_width + cache.fold_gutter_width; - int xmargin_end = cache.size.width - cache.style_normal->get_margin(MARGIN_RIGHT); + int xmargin_end = size.width - cache.style_normal->get_margin(MARGIN_RIGHT); //let's do it easy for now: - cache.style_normal->draw(ci, Rect2(Point2(), cache.size)); + cache.style_normal->draw(ci, Rect2(Point2(), size)); float readonly_alpha = 1.0; // used to set the input text color when in read-only mode if (readonly) { - cache.style_readonly->draw(ci, Rect2(Point2(), cache.size)); + cache.style_readonly->draw(ci, Rect2(Point2(), size)); readonly_alpha = .5; draw_caret = false; } if (has_focus()) - cache.style_focus->draw(ci, Rect2(Point2(), cache.size)); + cache.style_focus->draw(ci, Rect2(Point2(), size)); int ascent = cache.font->get_ascent(); int visible_rows = get_visible_rows() + 1; - int tab_w = cache.font->get_char_size(' ').width * indent_size; - Color color = cache.font_color; color.a *= readonly_alpha; @@ -670,7 +666,7 @@ void TextEdit::_notification(int p_what) { bool brace_close_matching = false; bool brace_close_mismatch = false; - if (brace_matching_enabled) { + if (brace_matching_enabled && cursor.line >= 0 && cursor.line < text.size() && cursor.column >= 0) { if (cursor.column < text[cursor.line].length()) { //check for open @@ -807,6 +803,7 @@ void TextEdit::_notification(int p_what) { } Point2 cursor_pos; + int cursor_insert_offset_y = 0; // get the highlighted words String highlighted_text = get_selection_text(); @@ -851,9 +848,9 @@ void TextEdit::_notification(int p_what) { bool underlined = false; + Vector<String> wrap_rows = get_wrap_rows_text(line); int line_wrap_amount = times_line_wraps(line); int last_wrap_column = 0; - Vector<String> wrap_rows = get_wrap_rows_text(line); for (int line_wrap_index = 0; line_wrap_index < line_wrap_amount + 1; line_wrap_index++) { if (line_wrap_index != 0) { @@ -864,6 +861,9 @@ void TextEdit::_notification(int p_what) { const String &str = wrap_rows[line_wrap_index]; int indent_px = line_wrap_index != 0 ? get_indent_level(line) * cache.font->get_char_size(' ').width : 0; + if (indent_px >= wrap_at) { + indent_px = 0; + } if (line_wrap_index > 0) last_wrap_column += wrap_rows[line_wrap_index - 1].length(); @@ -1113,9 +1113,11 @@ void TextEdit::_notification(int p_what) { if (cursor.column == last_wrap_column + j && cursor.line == line && cursor_wrap_index == line_wrap_index) { cursor_pos = Point2i(char_ofs + char_margin + ofs_x, ofs_y); + cursor_pos.y += (get_row_height() - cache.font->get_height()) / 2; if (insert_mode) { - cursor_pos.y += (get_row_height() - 3); + cursor_insert_offset_y = (cache.font->get_height() - 3); + cursor_pos.y += cursor_insert_offset_y; } int caret_w = (str[j] == '\t') ? cache.font->get_char_size(' ').width : char_w; @@ -1160,7 +1162,8 @@ void TextEdit::_notification(int p_what) { #else caret_w = (block_caret) ? caret_w : 2; #endif - VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(cursor_pos, Size2i(caret_w, get_row_height())), cache.caret_color); + + VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(cursor_pos, Size2i(caret_w, cache.font->get_height())), cache.caret_color); } } } @@ -1203,9 +1206,11 @@ void TextEdit::_notification(int p_what) { if (cursor.column == last_wrap_column + str.length() && cursor.line == line && cursor_wrap_index == line_wrap_index && (char_ofs + char_margin) >= xmargin_beg) { cursor_pos = Point2i(char_ofs + char_margin + ofs_x, ofs_y); + cursor_pos.y += (get_row_height() - cache.font->get_height()) / 2; if (insert_mode) { - cursor_pos.y += (get_row_height() - 3); + cursor_insert_offset_y = cache.font->get_height() - 3; + cursor_pos.y += cursor_insert_offset_y; } if (ime_text.length() > 0) { int ofs = 0; @@ -1250,7 +1255,8 @@ void TextEdit::_notification(int p_what) { #else int caret_w = (block_caret) ? char_w : 2; #endif - VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(cursor_pos, Size2i(caret_w, get_row_height())), cache.caret_color); + + VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(cursor_pos, Size2i(caret_w, cache.font->get_height())), cache.caret_color); } } } @@ -1261,7 +1267,7 @@ void TextEdit::_notification(int p_what) { 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) { - VisualServer::get_singleton()->canvas_item_add_line(ci, Point2(x, 0), Point2(x, cache.size.height), cache.line_length_guideline_color); + VisualServer::get_singleton()->canvas_item_add_line(ci, Point2(x, 0), Point2(x, size.height), cache.line_length_guideline_color); } } @@ -1292,9 +1298,9 @@ void TextEdit::_notification(int p_what) { int th = h + csb->get_minimum_size().y; if (cursor_pos.y + get_row_height() + th > get_size().height) { - completion_rect.position.y = cursor_pos.y - th; + completion_rect.position.y = cursor_pos.y - th - (cache.line_spacing / 2.0f) - cursor_insert_offset_y; } else { - completion_rect.position.y = cursor_pos.y + get_row_height() + csb->get_offset().y; + completion_rect.position.y = cursor_pos.y + cache.font->get_height() + (cache.line_spacing / 2.0f) + csb->get_offset().y - cursor_insert_offset_y; completion_below = true; } @@ -1328,7 +1334,8 @@ void TextEdit::_notification(int p_what) { text_color = color_regions[j].color; } } - draw_string(cache.font, Point2(completion_rect.position.x, completion_rect.position.y + i * get_row_height() + cache.font->get_ascent()), completion_options[l], text_color, completion_rect.size.width); + int yofs = (get_row_height() - cache.font->get_height()) / 2; + draw_string(cache.font, Point2(completion_rect.position.x, completion_rect.position.y + i * get_row_height() + cache.font->get_ascent() + yofs), completion_options[l], text_color, completion_rect.size.width); } if (scrollw) { @@ -1377,8 +1384,8 @@ void TextEdit::_notification(int p_what) { } } - Size2 size = Size2(max_w, sc * font->get_height() + spacing); - Size2 minsize = size + sb->get_minimum_size(); + Size2 size2 = Size2(max_w, sc * font->get_height() + spacing); + Size2 minsize = size2 + sb->get_minimum_size(); if (completion_hint_offset == -0xFFFF) { completion_hint_offset = cursor_pos.x - offset; @@ -1417,7 +1424,6 @@ void TextEdit::_notification(int p_what) { if (has_focus()) { OS::get_singleton()->set_ime_active(true); OS::get_singleton()->set_ime_position(get_global_position() + cursor_pos + Point2(0, get_row_height())); - OS::get_singleton()->set_ime_intermediate_text_callback(_ime_text_callback, this); } } break; @@ -1430,38 +1436,31 @@ void TextEdit::_notification(int p_what) { OS::get_singleton()->set_ime_active(true); Point2 cursor_pos = Point2(cursor_get_column(), cursor_get_line()) * get_row_height(); OS::get_singleton()->set_ime_position(get_global_position() + cursor_pos); - OS::get_singleton()->set_ime_intermediate_text_callback(_ime_text_callback, this); 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_index(get_canvas_item(), 1); - } } break; case NOTIFICATION_FOCUS_EXIT: { OS::get_singleton()->set_ime_position(Point2()); - OS::get_singleton()->set_ime_intermediate_text_callback(NULL, NULL); OS::get_singleton()->set_ime_active(false); ime_text = ""; ime_selection = Point2(); if (OS::get_singleton()->has_virtual_keyboard()) OS::get_singleton()->hide_virtual_keyboard(); - if (raised_from_completion) { - VisualServer::get_singleton()->canvas_item_set_z_index(get_canvas_item(), 0); + } break; + case MainLoop::NOTIFICATION_OS_IME_UPDATE: { + + if (has_focus()) { + ime_text = OS::get_singleton()->get_ime_text(); + ime_selection = OS::get_singleton()->get_ime_selection(); + update(); } } break; } } -void TextEdit::_ime_text_callback(void *p_self, String p_text, Point2 p_selection) { - TextEdit *self = (TextEdit *)p_self; - self->ime_text = p_text; - self->ime_selection = p_selection; - self->update(); -} - void TextEdit::_consume_pair_symbol(CharType ch) { int cursor_position_to_move = cursor_get_column() + 1; @@ -1718,10 +1717,10 @@ void TextEdit::_get_mouse_pos(const Point2i &p_mouse, int &r_row, int &r_col) co col = get_char_pos_for_line(colx, row, wrap_index); if (is_wrap_enabled() && wrap_index < times_line_wraps(row)) { // move back one if we are at the end of the row - Vector<String> rows = get_wrap_rows_text(row); + Vector<String> rows2 = get_wrap_rows_text(row); int row_end_col = 0; for (int i = 0; i < wrap_index + 1; i++) { - row_end_col += rows[i].length(); + row_end_col += rows2[i].length(); } if (col >= row_end_col) col -= 1; @@ -1942,7 +1941,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) { int to_column = get_selection_to_column(); if (row < from_line || row > to_line || (row == from_line && col < from_column) || (row == to_line && col > to_column)) { - // Right click is outside the seleted text + // Right click is outside the selected text deselect(); } } @@ -2206,10 +2205,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) { bool had_selection = selection.active; // stuff to do when selection is active.. - if (selection.active) { - - if (readonly) - return; + if (!readonly && selection.active) { bool clear = false; bool unselect = false; @@ -2336,9 +2332,9 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) { // no need to indent if we are going upwards. if (auto_indent && !(k->get_command() && k->get_shift())) { - // indent once again if previous line will end with ':' or '{' + // indent once again if previous line will end with ':' or '{' and the line is not a comment // (i.e. colon/brace precedes current cursor position) - if (cursor.column > 0 && (text[cursor.line][cursor.column - 1] == ':' || text[cursor.line][cursor.column - 1] == '{')) { + if (cursor.column > 0 && (text[cursor.line][cursor.column - 1] == ':' || text[cursor.line][cursor.column - 1] == '{') && !is_line_comment(cursor.line)) { if (indent_using_spaces) { ins += space_indent; } else { @@ -2649,24 +2645,26 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) { } case KEY_UP: { - if (k->get_shift()) - _pre_shift_selection(); if (k->get_alt()) { scancode_handled = false; break; } #ifndef APPLE_STYLE_KEYS if (k->get_command()) { - _scroll_lines_up(); - break; - } #else if (k->get_command() && k->get_alt()) { +#endif _scroll_lines_up(); break; } + if (k->get_shift()) { + _pre_shift_selection(); + } + +#ifdef APPLE_STYLE_KEYS if (k->get_command()) { + cursor_set_line(0); } else #endif @@ -2700,24 +2698,24 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) { } case KEY_DOWN: { - if (k->get_shift()) - _pre_shift_selection(); if (k->get_alt()) { scancode_handled = false; break; } #ifndef APPLE_STYLE_KEYS if (k->get_command()) { - _scroll_lines_down(); - break; - } - #else if (k->get_command() && k->get_alt()) { +#endif _scroll_lines_down(); break; } + if (k->get_shift()) { + _pre_shift_selection(); + } + +#ifdef APPLE_STYLE_KEYS if (k->get_command()) { cursor_set_line(get_last_unhidden_line(), true, false, 9999); } else @@ -3119,16 +3117,14 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) { if (selection.active) { int ini = selection.from_line; int end = selection.to_line; + for (int i = ini; i <= end; i++) { - if (get_line(i).begins_with("#")) - _remove_text(i, 0, i, 1); + _uncomment_line(i); } } else { - if (get_line(cursor.line).begins_with("#")) { - _remove_text(cursor.line, 0, cursor.line, 1); - if (cursor.column >= get_line(cursor.line).length()) { - cursor.column = MAX(0, get_line(cursor.line).length() - 1); - } + _uncomment_line(cursor.line); + if (cursor.column >= get_line(cursor.line).length()) { + cursor.column = MAX(0, get_line(cursor.line).length() - 1); } } update(); @@ -3208,6 +3204,24 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) { } } +void TextEdit::_uncomment_line(int p_line) { + String line_text = get_line(p_line); + for (int i = 0; i < line_text.length(); i++) { + if (line_text[i] == '#') { + _remove_text(p_line, i, p_line, i + 1); + if (p_line == selection.to_line && selection.to_column > line_text.length() - 1) { + selection.to_column -= 1; + if (selection.to_column >= selection.from_column) { + selection.active = false; + } + } + return; + } else if (line_text[i] != '\t' && line_text[i] != ' ') { + return; + } + } +} + void TextEdit::_scroll_up(real_t p_delta) { if (scrolling && smooth_scroll_enabled && SGN(target_v_scroll - v_scroll->get_value()) != SGN(-p_delta)) @@ -3246,10 +3260,9 @@ void TextEdit::_scroll_down(real_t p_delta) { } if (smooth_scroll_enabled) { - int max_v_scroll = v_scroll->get_max() - v_scroll->get_page(); + int max_v_scroll = round(v_scroll->get_max() - v_scroll->get_page()); if (target_v_scroll > max_v_scroll) { target_v_scroll = max_v_scroll; - v_scroll->set_value(target_v_scroll); } if (Math::abs(target_v_scroll - v_scroll->get_value()) < 1.0) { v_scroll->set_value(target_v_scroll); @@ -3362,20 +3375,20 @@ void TextEdit::_base_insert_text(int p_line, int p_char, const String &p_text, i String preinsert_text = text[p_line].substr(0, p_char); String postinsert_text = text[p_line].substr(p_char, text[p_line].size()); - for (int i = 0; i < substrings.size(); i++) { + for (int j = 0; j < substrings.size(); j++) { //insert the substrings - if (i == 0) { + if (j == 0) { - text.set(p_line, preinsert_text + substrings[i]); + text.set(p_line, preinsert_text + substrings[j]); } else { - text.insert(p_line + i, substrings[i]); + text.insert(p_line + j, substrings[j]); } - if (i == substrings.size() - 1) { + if (j == substrings.size() - 1) { - text.set(p_line + i, text[p_line + i] + postinsert_text); + text.set(p_line + j, text[p_line + j] + postinsert_text); } } @@ -3609,7 +3622,7 @@ Size2 TextEdit::get_minimum_size() const { int TextEdit::get_visible_rows() const { - int total = cache.size.height; + int total = get_size().height; total -= cache.style_normal->get_minimum_size().height; if (h_scroll->is_visible_in_tree()) total -= h_scroll->get_size().height; @@ -3634,9 +3647,9 @@ int TextEdit::get_total_visible_rows() const { return total_rows; } -void TextEdit::update_wrap_at() { +void TextEdit::_update_wrap_at() { - wrap_at = cache.size.width - cache.style_normal->get_minimum_size().width - cache.line_number_w - cache.breakpoint_gutter_width - cache.fold_gutter_width - wrap_right_offset; + wrap_at = get_size().width - cache.style_normal->get_minimum_size().width - cache.line_number_w - cache.breakpoint_gutter_width - cache.fold_gutter_width - wrap_right_offset; update_cursor_wrap_offset(); text.clear_wrap_cache(); @@ -3670,7 +3683,7 @@ void TextEdit::adjust_viewport_to_cursor() { set_line_as_last_visible(cur_line, cur_wrap); } - int visible_width = cache.size.width - cache.style_normal->get_minimum_size().width - cache.line_number_w - cache.breakpoint_gutter_width - cache.fold_gutter_width; + int visible_width = get_size().width - cache.style_normal->get_minimum_size().width - cache.line_number_w - cache.breakpoint_gutter_width - cache.fold_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 @@ -3701,7 +3714,7 @@ void TextEdit::center_viewport_to_cursor() { unfold_line(cursor.line); set_line_as_center_visible(cursor.line, get_cursor_wrap_index()); - int visible_width = cache.size.width - cache.style_normal->get_minimum_size().width - cache.line_number_w - cache.breakpoint_gutter_width - cache.fold_gutter_width; + int visible_width = get_size().width - cache.style_normal->get_minimum_size().width - cache.line_number_w - cache.breakpoint_gutter_width - cache.fold_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 @@ -3778,43 +3791,56 @@ Vector<String> TextEdit::get_wrap_rows_text(int p_line) const { int cur_wrap_index = 0; int tab_offset_px = get_indent_level(p_line) * cache.font->get_char_size(' ').width; + if (tab_offset_px >= wrap_at) { + tab_offset_px = 0; + } while (col < line_text.length()) { - char c = line_text[col]; + CharType c = line_text[col]; int w = text.get_char_width(c, line_text[col + 1], px + word_px); int indent_ofs = (cur_wrap_index != 0 ? tab_offset_px : 0); - word_str += c; - word_px += w; - if (c == ' ') { - // end of a word; add this word to the substring + if (indent_ofs + word_px + w > wrap_at) { + // not enough space to add this char; start next line wrap_substring += word_str; - px += word_px; - word_str = ""; - word_px = 0; - } + lines.push_back(wrap_substring); + cur_wrap_index++; + wrap_substring = ""; + px = 0; - if ((indent_ofs + px + word_px) > wrap_at) { - // do not want to add this word - if (indent_ofs + word_px > wrap_at) { - // not enough space; add it anyway + word_str = ""; + word_str += c; + word_px = w; + } else { + word_str += c; + word_px += w; + if (c == ' ') { + // end of a word; add this word to the substring wrap_substring += word_str; px += word_px; word_str = ""; word_px = 0; } - lines.push_back(wrap_substring); - // reset for next wrap - cur_wrap_index++; - wrap_substring = ""; - px = 0; + + if (indent_ofs + px + word_px > wrap_at) { + // this word will be moved to the next line + lines.push_back(wrap_substring); + // reset for next wrap + cur_wrap_index++; + wrap_substring = ""; + px = 0; + } } col++; } // line ends before hit wrap_at; add this word to the substring wrap_substring += word_str; lines.push_back(wrap_substring); + + // update cache + text.set_line_wrap_amount(p_line, lines.size() - 1); + return lines; } @@ -4017,6 +4043,9 @@ int TextEdit::get_char_pos_for_line(int p_px, int p_line, int p_wrap_index) cons int line_wrap_amount = times_line_wraps(p_line); int wrap_offset_px = get_indent_level(p_line) * cache.font->get_char_size(' ').width; + if (wrap_offset_px >= wrap_at) { + wrap_offset_px = 0; + } if (p_wrap_index > line_wrap_amount) p_wrap_index = line_wrap_amount; if (p_wrap_index > 0) @@ -4058,6 +4087,9 @@ int TextEdit::get_column_x_offset_for_line(int p_char, int p_line) const { int px = get_column_x_offset(n_char, rows[wrap_index]); int wrap_offset_px = get_indent_level(p_line) * cache.font->get_char_size(' ').width; + if (wrap_offset_px >= wrap_at) { + wrap_offset_px = 0; + } if (wrap_index != 0) px += wrap_offset_px; @@ -4158,7 +4190,7 @@ Control::CursorShape TextEdit::get_cursor_shape(const Point2 &p_pos) const { } } - return CURSOR_IBEAM; + return get_default_cursor_shape(); } void TextEdit::set_text(String p_text) { @@ -4259,6 +4291,7 @@ void TextEdit::_clear() { cursor.line_ofs = 0; cursor.wrap_ofs = 0; cursor.last_fit_x = 0; + selection.active = false; } void TextEdit::clear() { @@ -4386,7 +4419,7 @@ int TextEdit::_is_line_in_region(int p_line) { // if not find the closest line we have int previous_line = p_line - 1; - for (previous_line; previous_line > -1; previous_line--) { + for (; previous_line > -1; previous_line--) { if (color_region_cache.has(p_line)) { break; } @@ -4531,9 +4564,13 @@ void TextEdit::cut() { void TextEdit::copy() { if (!selection.active) { - String clipboard = _base_get_text(cursor.line, 0, cursor.line, text[cursor.line].length()); - OS::get_singleton()->set_clipboard(clipboard); - cut_copy_line = clipboard; + + if (text[cursor.line].length() != 0) { + + String clipboard = _base_get_text(cursor.line, 0, cursor.line, text[cursor.line].length()); + OS::get_singleton()->set_clipboard(clipboard); + cut_copy_line = clipboard; + } } else { String clipboard = _base_get_text(selection.from_line, selection.from_column, selection.to_line, selection.to_column); OS::get_singleton()->set_clipboard(clipboard); @@ -4822,28 +4859,27 @@ bool TextEdit::search(const String &p_key, uint32_t p_search_flags, int p_from_l pos = -1; - int pos_from = 0; + int pos_from = (p_search_flags & SEARCH_BACKWARDS) ? text_line.length() : 0; int last_pos = -1; while (true) { - while ((last_pos = (p_search_flags & SEARCH_MATCH_CASE) ? text_line.find(p_key, pos_from) : text_line.findn(p_key, pos_from)) != -1) { - - if (p_search_flags & SEARCH_BACKWARDS) { - - if (last_pos > from_column) + if (p_search_flags & SEARCH_BACKWARDS) { + while ((last_pos = (p_search_flags & SEARCH_MATCH_CASE) ? text_line.rfind(p_key, pos_from) : text_line.rfindn(p_key, pos_from)) != -1) { + if (last_pos <= from_column) { + pos = last_pos; break; - pos = last_pos; - - } else { - + } + pos_from = last_pos - p_key.length(); + } + } else { + while ((last_pos = (p_search_flags & SEARCH_MATCH_CASE) ? text_line.find(p_key, pos_from) : text_line.findn(p_key, pos_from)) != -1) { if (last_pos >= from_column) { pos = last_pos; break; } + pos_from = last_pos + p_key.length(); } - - pos_from = last_pos + p_key.length(); } bool is_match = true; @@ -4856,11 +4892,15 @@ bool TextEdit::search(const String &p_key, uint32_t p_search_flags, int p_from_l is_match = false; } + if (pos_from == -1) { + pos = -1; + } + if (is_match || last_pos == -1 || pos == -1) { break; } - pos_from = pos + 1; + pos_from = (p_search_flags & SEARCH_BACKWARDS) ? pos - 1 : pos + 1; pos = -1; } @@ -5133,7 +5173,7 @@ bool TextEdit::can_fold(int p_line) const { return false; if (p_line + 1 >= text.size()) return false; - if (text[p_line].size() == 0) + if (text[p_line].strip_edges().size() == 0) return false; if (is_folded(p_line)) return false; @@ -5145,7 +5185,7 @@ bool TextEdit::can_fold(int p_line) const { int start_indent = get_indent_level(p_line); for (int i = p_line + 1; i < text.size(); i++) { - if (text[i].size() == 0) + if (text[i].strip_edges().size() == 0) continue; int next_indent = get_indent_level(i); if (is_line_comment(i)) { @@ -5543,7 +5583,7 @@ int TextEdit::get_last_visible_line_wrap_index() const { double TextEdit::get_visible_rows_offset() const { - double total = cache.size.height; + double total = get_size().height; total -= cache.style_normal->get_minimum_size().height; if (h_scroll->is_visible_in_tree()) total -= h_scroll->get_size().height; @@ -5648,16 +5688,12 @@ void TextEdit::_confirm_completion() { void TextEdit::_cancel_code_hint() { - VisualServer::get_singleton()->canvas_item_set_z_index(get_canvas_item(), 0); - raised_from_completion = false; completion_hint = ""; update(); } void TextEdit::_cancel_completion() { - VisualServer::get_singleton()->canvas_item_set_z_index(get_canvas_item(), 0); - raised_from_completion = false; if (!completion_active) return; @@ -5749,6 +5785,7 @@ void TextEdit::_update_completion_candidates() { completion_base = s; Vector<float> sim_cache; bool single_quote = s.begins_with("'"); + Vector<String> completion_options_casei; for (int i = 0; i < completion_strings.size(); i++) { if (single_quote && completion_strings[i].is_quoted()) { @@ -5757,9 +5794,13 @@ void TextEdit::_update_completion_candidates() { if (completion_strings[i].begins_with(s)) { completion_options.push_back(completion_strings[i]); + } else if (completion_strings[i].to_lower().begins_with(s.to_lower())) { + completion_options_casei.push_back(completion_strings[i]); } } + completion_options.append_array(completion_options_casei); + if (completion_options.size() == 0) { for (int i = 0; i < completion_strings.size(); i++) { if (s.is_subsequence_of(completion_strings[i])) { @@ -5815,8 +5856,6 @@ void TextEdit::query_code_comple() { void TextEdit::set_code_hint(const String &p_hint) { - VisualServer::get_singleton()->canvas_item_set_z_index(get_canvas_item(), 1); - raised_from_completion = true; completion_hint = p_hint; completion_hint_offset = -0xFFFF; update(); @@ -5824,8 +5863,6 @@ void TextEdit::set_code_hint(const String &p_hint) { void TextEdit::code_complete(const Vector<String> &p_strings, bool p_forced) { - VisualServer::get_singleton()->canvas_item_set_z_index(get_canvas_item(), 1); - raised_from_completion = true; completion_strings = p_strings; completion_active = true; completion_forced = p_forced; @@ -5847,7 +5884,7 @@ String TextEdit::get_word_at_pos(const Vector2 &p_pos) const { if (select_word(s, col, beg, end)) { bool inside_quotes = false; - char selected_quote = '\0'; + CharType selected_quote = '\0'; int qbegin = 0, qend = 0; for (int i = 0; i < s.length(); i++) { if (s[i] == '"' || s[i] == '\'') { @@ -5910,6 +5947,9 @@ void TextEdit::set_line(int line, String new_text) { if (cursor.line == line) { cursor.column = MIN(cursor.column, new_text.length()); } + if (is_selection_active() && line == selection.to_line && selection.to_column > text[line].length()) { + selection.to_column = text[line].length(); + } } void TextEdit::insert_at(const String &p_text, int at) { @@ -6032,7 +6072,10 @@ void TextEdit::menu_option(int p_option) { case MENU_UNDO: { undo(); } break; - }; + case MENU_REDO: { + redo(); + } + } } void TextEdit::set_select_identifiers_on_hover(bool p_enable) { @@ -6067,6 +6110,7 @@ void TextEdit::_bind_methods() { ClassDB::bind_method(D_METHOD("_click_selection_held"), &TextEdit::_click_selection_held); ClassDB::bind_method(D_METHOD("_toggle_draw_caret"), &TextEdit::_toggle_draw_caret); ClassDB::bind_method(D_METHOD("_v_scroll_input"), &TextEdit::_v_scroll_input); + ClassDB::bind_method(D_METHOD("_update_wrap_at"), &TextEdit::_update_wrap_at); BIND_ENUM_CONSTANT(SEARCH_MATCH_CASE); BIND_ENUM_CONSTANT(SEARCH_WHOLE_WORDS); @@ -6193,7 +6237,7 @@ void TextEdit::_bind_methods() { ADD_GROUP("Caret", "caret_"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "caret_block_mode"), "cursor_set_block_mode", "cursor_is_block_mode"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "caret_blink"), "cursor_set_blink_enabled", "cursor_get_blink_enabled"); - ADD_PROPERTYNZ(PropertyInfo(Variant::REAL, "caret_blink_speed", PROPERTY_HINT_RANGE, "0.1,10,0.01"), "cursor_set_blink_speed", "cursor_get_blink_speed"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "caret_blink_speed", PROPERTY_HINT_RANGE, "0.1,10,0.01"), "cursor_set_blink_speed", "cursor_get_blink_speed"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "caret_moving_by_right_click"), "set_right_click_moves_caret", "is_right_click_moving_caret"); ADD_SIGNAL(MethodInfo("cursor_changed")); @@ -6208,9 +6252,11 @@ void TextEdit::_bind_methods() { BIND_ENUM_CONSTANT(MENU_CLEAR); BIND_ENUM_CONSTANT(MENU_SELECT_ALL); BIND_ENUM_CONSTANT(MENU_UNDO); + BIND_ENUM_CONSTANT(MENU_REDO); BIND_ENUM_CONSTANT(MENU_MAX); GLOBAL_DEF("gui/timers/text_edit_idle_detect_sec", 3); + ProjectSettings::get_singleton()->set_custom_property_info("gui/timers/text_edit_idle_detect_sec", PropertyInfo(Variant::REAL, "gui/timers/text_edit_idle_detect_sec", PROPERTY_HINT_RANGE, "0,10,0.01,or_greater")); // No negative numbers } TextEdit::TextEdit() { @@ -6227,7 +6273,6 @@ TextEdit::TextEdit() { set_focus_mode(FOCUS_ALL); syntax_highlighter = NULL; _update_caches(); - cache.size = Size2(1, 1); cache.row_height = 1; cache.line_spacing = 1; cache.line_number_w = 1; @@ -6235,6 +6280,7 @@ TextEdit::TextEdit() { breakpoint_gutter_width = 0; cache.fold_gutter_width = 0; fold_gutter_width = 0; + set_default_cursor_shape(CURSOR_IBEAM); indent_size = 4; text.set_indent_size(indent_size); @@ -6324,8 +6370,6 @@ TextEdit::TextEdit() { target_v_scroll = 0; v_scroll_speed = 80; - raised_from_completion = false; - context_menu_enabled = true; menu = memnew(PopupMenu); add_child(menu); @@ -6337,6 +6381,7 @@ TextEdit::TextEdit() { menu->add_item(RTR("Clear"), MENU_CLEAR); menu->add_separator(); menu->add_item(RTR("Undo"), MENU_UNDO, KEY_MASK_CMD | KEY_Z); + menu->add_item(RTR("Redo"), MENU_REDO, KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_Z); menu->connect("id_pressed", this, "menu_option"); } @@ -6400,8 +6445,8 @@ Map<int, TextEdit::HighlighterInfo> TextEdit::_get_line_syntax_highlighting(int is_hex_notation = false; } - // check for dot or underscore or 'x' for hex notation in floating point number - if ((str[j] == '.' || str[j] == 'x' || str[j] == '_' || str[j] == 'f') && !in_word && prev_is_number && !is_number) { + // check for dot or underscore or 'x' for hex notation in floating point number or 'e' for scientific notation + if ((str[j] == '.' || str[j] == 'x' || str[j] == '_' || str[j] == 'f' || str[j] == 'e') && !in_word && prev_is_number && !is_number) { is_number = true; is_symbol = false; is_char = false; diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h index 19b5d574c6..95f1fbbee5 100644 --- a/scene/gui/text_edit.h +++ b/scene/gui/text_edit.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -193,7 +193,6 @@ private: int line_number_w; int breakpoint_gutter_width; int fold_gutter_width; - Size2 size; } cache; Map<int, int> color_region_cache; @@ -307,8 +306,6 @@ private: float target_v_scroll; float v_scroll_speed; - bool raised_from_completion; - String highlighted_word; uint64_t last_dblclk; @@ -339,7 +336,7 @@ private: int get_total_visible_rows() const; void update_cursor_wrap_offset(); - void update_wrap_at(); + void _update_wrap_at(); bool line_wraps(int line) const; int times_line_wraps(int line) const; Vector<String> get_wrap_rows_text(int p_line) const; @@ -373,6 +370,7 @@ private: void _update_selection_mode_word(); void _update_selection_mode_line(); + void _uncomment_line(int p_line); void _scroll_up(real_t p_delta); void _scroll_down(real_t p_delta); @@ -382,8 +380,6 @@ private: void _scroll_lines_up(); void _scroll_lines_down(); - static void _ime_text_callback(void *p_self, String p_text, Point2 p_selection); - //void mouse_motion(const Point& p_pos, const Point& p_rel, int p_button_mask); Size2 get_minimum_size() const; @@ -446,6 +442,7 @@ public: MENU_CLEAR, MENU_SELECT_ALL, MENU_UNDO, + MENU_REDO, MENU_MAX }; diff --git a/scene/gui/texture_button.cpp b/scene/gui/texture_button.cpp index 6bd3b26280..19bef9fdf5 100644 --- a/scene/gui/texture_button.cpp +++ b/scene/gui/texture_button.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -64,7 +64,9 @@ bool TextureButton::has_point(const Point2 &p_point) const { Rect2 rect = Rect2(); Size2 mask_size = click_mask->get_size(); - if (_tile) { + if (_position_rect.no_area()) { + rect.size = mask_size; + } else if (_tile) { // if the stretch mode is tile we offset the point to keep it inside the mask size rect.size = mask_size; if (_position_rect.has_point(point)) { @@ -88,6 +90,9 @@ bool TextureButton::has_point(const Point2 &p_point) const { scale.y = min; ofs -= _texture_region.position / min; } break; + default: { + // FIXME: Why a switch if we only handle one enum value? + } } // offset and scale the new point position to adjust it to the bitmask size @@ -125,6 +130,7 @@ void TextureButton::_notification(int p_what) { if (normal.is_valid()) texdraw = normal; } break; + case DRAW_HOVER_PRESSED: case DRAW_PRESSED: { if (pressed.is_null()) { @@ -202,8 +208,8 @@ void TextureButton::_notification(int p_what) { Size2 scaleSize(size.width / tex_size.width, size.height / tex_size.height); float scale = scaleSize.width > scaleSize.height ? scaleSize.width : scaleSize.height; Size2 scaledTexSize = tex_size * scale; - Point2 ofs = ((scaledTexSize - size) / scale).abs() / 2.0f; - _texture_region = Rect2(ofs, size / scale); + Point2 ofs2 = ((scaledTexSize - size) / scale).abs() / 2.0f; + _texture_region = Rect2(ofs2, size / scale); } break; } } @@ -212,6 +218,8 @@ void TextureButton::_notification(int p_what) { draw_texture_rect(texdraw, _position_rect, _tile); else draw_texture_rect_region(texdraw, _position_rect, _texture_region); + } else { + _position_rect = Rect2(); } if (has_focus() && focused.is_valid()) { @@ -243,14 +251,14 @@ void TextureButton::_bind_methods() { ClassDB::bind_method(D_METHOD("get_stretch_mode"), &TextureButton::get_stretch_mode); ADD_GROUP("Textures", "texture_"); - ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT, "texture_normal", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_normal_texture", "get_normal_texture"); - ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT, "texture_pressed", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_pressed_texture", "get_pressed_texture"); - ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT, "texture_hover", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_hover_texture", "get_hover_texture"); - ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT, "texture_disabled", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_disabled_texture", "get_disabled_texture"); - ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT, "texture_focused", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_focused_texture", "get_focused_texture"); - ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT, "texture_click_mask", PROPERTY_HINT_RESOURCE_TYPE, "BitMap"), "set_click_mask", "get_click_mask"); - ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL, "expand", PROPERTY_HINT_RESOURCE_TYPE, "bool"), "set_expand", "get_expand"); - ADD_PROPERTYNZ(PropertyInfo(Variant::INT, "stretch_mode", PROPERTY_HINT_ENUM, "Scale,Tile,Keep,Keep Centered,Keep Aspect,Keep Aspect Centered,Keep Aspect Covered"), "set_stretch_mode", "get_stretch_mode"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture_normal", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_normal_texture", "get_normal_texture"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture_pressed", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_pressed_texture", "get_pressed_texture"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture_hover", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_hover_texture", "get_hover_texture"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture_disabled", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_disabled_texture", "get_disabled_texture"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture_focused", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_focused_texture", "get_focused_texture"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture_click_mask", PROPERTY_HINT_RESOURCE_TYPE, "BitMap"), "set_click_mask", "get_click_mask"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "expand", PROPERTY_HINT_RESOURCE_TYPE, "bool"), "set_expand", "get_expand"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "stretch_mode", PROPERTY_HINT_ENUM, "Scale,Tile,Keep,Keep Centered,Keep Aspect,Keep Aspect Centered,Keep Aspect Covered"), "set_stretch_mode", "get_stretch_mode"); BIND_ENUM_CONSTANT(STRETCH_SCALE); BIND_ENUM_CONSTANT(STRETCH_TILE); diff --git a/scene/gui/texture_button.h b/scene/gui/texture_button.h index d42df390e8..d9224de686 100644 --- a/scene/gui/texture_button.h +++ b/scene/gui/texture_button.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* 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 @@ #define TEXTURE_BUTTON_H #include "scene/gui/base_button.h" -#include "scene/resources/bit_mask.h" +#include "scene/resources/bit_map.h" class TextureButton : public BaseButton { GDCLASS(TextureButton, BaseButton); diff --git a/scene/gui/texture_progress.cpp b/scene/gui/texture_progress.cpp index ff90576c1b..c534df5cbe 100644 --- a/scene/gui/texture_progress.cpp +++ b/scene/gui/texture_progress.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,7 +30,7 @@ #include "texture_progress.h" -#include "engine.h" +#include "core/engine.h" void TextureProgress::set_under_texture(const Ref<Texture> &p_texture) { @@ -59,14 +59,14 @@ Ref<Texture> TextureProgress::get_over_texture() const { } void TextureProgress::set_stretch_margin(Margin p_margin, int p_size) { - ERR_FAIL_INDEX(p_margin, 4); + ERR_FAIL_INDEX((int)p_margin, 4); stretch_margin[p_margin] = p_size; update(); minimum_size_changed(); } int TextureProgress::get_stretch_margin(Margin p_margin) const { - ERR_FAIL_INDEX_V(p_margin, 4, 0); + ERR_FAIL_INDEX_V((int)p_margin, 4, 0); return stretch_margin[p_margin]; } @@ -148,9 +148,9 @@ Point2 TextureProgress::unit_val_to_uv(float val) { float angle = (val * Math_TAU) - Math_PI * 0.5; Point2 dir = Vector2(Math::cos(angle), Math::sin(angle)); float t1 = 1.0; - float cp; - float cq; - float cr; + float cp = 0; + float cq = 0; + float cr = 0; float edgeLeft = 0.0; float edgeRight = 1.0; float edgeBottom = 0.0; @@ -160,23 +160,27 @@ Point2 TextureProgress::unit_val_to_uv(float val) { if (edge == 0) { if (dir.x > 0) continue; - cp = -dir.x; cq = -(edgeLeft - p.x); + dir.x *= 2.0 * cq; + cp = -dir.x; } else if (edge == 1) { if (dir.x < 0) continue; - cp = dir.x; cq = (edgeRight - p.x); + dir.x *= 2.0 * cq; + cp = dir.x; } else if (edge == 2) { if (dir.y > 0) continue; - cp = -dir.y; cq = -(edgeBottom - p.y); + dir.y *= 2.0 * cq; + cp = -dir.y; } else if (edge == 3) { if (dir.y < 0) continue; - cp = dir.y; cq = (edgeTop - p.y); + dir.y *= 2.0 * cq; + cp = dir.y; } cr = cq / cp; if (cr >= 0 && cr < t1) @@ -229,6 +233,17 @@ void TextureProgress::draw_nine_patch_stretched(const Ref<Texture> &p_texture, F first_section_size = topleft.y; last_section_size = bottomright.y; } break; + case FILL_BILINEAR_LEFT_AND_RIGHT: { + // TODO: Implement + } break; + case FILL_BILINEAR_TOP_AND_BOTTOM: { + // TODO: Implement + } break; + case FILL_CLOCKWISE: + case FILL_CLOCKWISE_AND_COUNTER_CLOCKWISE: + case FILL_COUNTER_CLOCKWISE: { + // Those modes are circular, not relevant for nine patch + } break; } double width_filled = width_total * p_ratio; @@ -236,12 +251,14 @@ void TextureProgress::draw_nine_patch_stretched(const Ref<Texture> &p_texture, F middle_section_size *= MIN(1.0, (MAX(0.0, width_filled - first_section_size) / MAX(1.0, width_total - first_section_size - last_section_size))); last_section_size = MAX(0.0, last_section_size - (width_total - width_filled)); + first_section_size = MIN(first_section_size, width_filled); width_texture = MIN(width_texture, first_section_size + middle_section_size + last_section_size); switch (mode) { case FILL_LEFT_TO_RIGHT: { src_rect.size.x = width_texture; dst_rect.size.x = width_filled; + topleft.x = first_section_size; bottomright.x = last_section_size; } break; case FILL_RIGHT_TO_LEFT: { @@ -250,11 +267,13 @@ void TextureProgress::draw_nine_patch_stretched(const Ref<Texture> &p_texture, F dst_rect.position.x += width_total - width_filled; dst_rect.size.x = width_filled; topleft.x = last_section_size; + bottomright.x = first_section_size; } break; case FILL_TOP_TO_BOTTOM: { src_rect.size.y = width_texture; dst_rect.size.y = width_filled; bottomright.y = last_section_size; + topleft.y = first_section_size; } break; case FILL_BOTTOM_TO_TOP: { src_rect.position.y += src_rect.size.y - width_texture; @@ -262,6 +281,18 @@ void TextureProgress::draw_nine_patch_stretched(const Ref<Texture> &p_texture, F dst_rect.position.y += width_total - width_filled; dst_rect.size.y = width_filled; topleft.y = last_section_size; + bottomright.y = first_section_size; + } break; + case FILL_BILINEAR_LEFT_AND_RIGHT: { + // TODO: Implement + } break; + case FILL_BILINEAR_TOP_AND_BOTTOM: { + // TODO: Implement + } break; + case FILL_CLOCKWISE: + case FILL_CLOCKWISE_AND_COUNTER_CLOCKWISE: + case FILL_COUNTER_CLOCKWISE: { + // Those modes are circular, not relevant for nine patch } break; } } @@ -464,21 +495,21 @@ void TextureProgress::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture_under", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_under_texture", "get_under_texture"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture_over", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_over_texture", "get_over_texture"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture_progress", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_progress_texture", "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,Bilinear (Left and Right),Bilinear (Top and Bottom), Clockwise and Counter Clockwise"), "set_fill_mode", "get_fill_mode"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "fill_mode", PROPERTY_HINT_ENUM, "Left to Right,Right to Left,Top to Bottom,Bottom to Top,Clockwise,Counter Clockwise,Bilinear (Left and Right),Bilinear (Top and Bottom), Clockwise and Counter Clockwise"), "set_fill_mode", "get_fill_mode"); ADD_GROUP("Tint", "tint_"); - ADD_PROPERTY(PropertyInfo(Variant::COLOR, "tint_under", PROPERTY_HINT_COLOR_NO_ALPHA), "set_tint_under", "get_tint_under"); - ADD_PROPERTY(PropertyInfo(Variant::COLOR, "tint_over", PROPERTY_HINT_COLOR_NO_ALPHA), "set_tint_over", "get_tint_over"); - ADD_PROPERTY(PropertyInfo(Variant::COLOR, "tint_progress", PROPERTY_HINT_COLOR_NO_ALPHA), "set_tint_progress", "get_tint_progress"); + ADD_PROPERTY(PropertyInfo(Variant::COLOR, "tint_under"), "set_tint_under", "get_tint_under"); + ADD_PROPERTY(PropertyInfo(Variant::COLOR, "tint_over"), "set_tint_over", "get_tint_over"); + ADD_PROPERTY(PropertyInfo(Variant::COLOR, "tint_progress"), "set_tint_progress", "get_tint_progress"); ADD_GROUP("Radial Fill", "radial_"); - ADD_PROPERTYNZ(PropertyInfo(Variant::REAL, "radial_initial_angle", PROPERTY_HINT_RANGE, "0.0,360.0,0.1,slider"), "set_radial_initial_angle", "get_radial_initial_angle"); - ADD_PROPERTYNZ(PropertyInfo(Variant::REAL, "radial_fill_degrees", PROPERTY_HINT_RANGE, "0.0,360.0,0.1,slider"), "set_fill_degrees", "get_fill_degrees"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "radial_initial_angle", PROPERTY_HINT_RANGE, "0.0,360.0,0.1,slider"), "set_radial_initial_angle", "get_radial_initial_angle"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "radial_fill_degrees", PROPERTY_HINT_RANGE, "0.0,360.0,0.1,slider"), "set_fill_degrees", "get_fill_degrees"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "radial_center_offset"), "set_radial_center_offset", "get_radial_center_offset"); ADD_GROUP("Stretch", "stretch_"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "nine_patch_stretch"), "set_nine_patch_stretch", "get_nine_patch_stretch"); - ADD_PROPERTYINZ(PropertyInfo(Variant::INT, "stretch_margin_left", PROPERTY_HINT_RANGE, "0,16384,1"), "set_stretch_margin", "get_stretch_margin", MARGIN_LEFT); - ADD_PROPERTYINZ(PropertyInfo(Variant::INT, "stretch_margin_top", PROPERTY_HINT_RANGE, "0,16384,1"), "set_stretch_margin", "get_stretch_margin", MARGIN_TOP); - ADD_PROPERTYINZ(PropertyInfo(Variant::INT, "stretch_margin_right", PROPERTY_HINT_RANGE, "0,16384,1"), "set_stretch_margin", "get_stretch_margin", MARGIN_RIGHT); - ADD_PROPERTYINZ(PropertyInfo(Variant::INT, "stretch_margin_bottom", PROPERTY_HINT_RANGE, "0,16384,1"), "set_stretch_margin", "get_stretch_margin", MARGIN_BOTTOM); + ADD_PROPERTYI(PropertyInfo(Variant::INT, "stretch_margin_left", PROPERTY_HINT_RANGE, "0,16384,1"), "set_stretch_margin", "get_stretch_margin", MARGIN_LEFT); + ADD_PROPERTYI(PropertyInfo(Variant::INT, "stretch_margin_top", PROPERTY_HINT_RANGE, "0,16384,1"), "set_stretch_margin", "get_stretch_margin", MARGIN_TOP); + ADD_PROPERTYI(PropertyInfo(Variant::INT, "stretch_margin_right", PROPERTY_HINT_RANGE, "0,16384,1"), "set_stretch_margin", "get_stretch_margin", MARGIN_RIGHT); + ADD_PROPERTYI(PropertyInfo(Variant::INT, "stretch_margin_bottom", PROPERTY_HINT_RANGE, "0,16384,1"), "set_stretch_margin", "get_stretch_margin", MARGIN_BOTTOM); BIND_ENUM_CONSTANT(FILL_LEFT_TO_RIGHT); BIND_ENUM_CONSTANT(FILL_RIGHT_TO_LEFT); diff --git a/scene/gui/texture_progress.h b/scene/gui/texture_progress.h index a11e55234a..008bf5b038 100644 --- a/scene/gui/texture_progress.h +++ b/scene/gui/texture_progress.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/texture_rect.cpp b/scene/gui/texture_rect.cpp index f4285525f6..caae48336b 100644 --- a/scene/gui/texture_rect.cpp +++ b/scene/gui/texture_rect.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -109,9 +109,9 @@ void TextureRect::_bind_methods() { ClassDB::bind_method(D_METHOD("set_stretch_mode", "stretch_mode"), &TextureRect::set_stretch_mode); ClassDB::bind_method(D_METHOD("get_stretch_mode"), &TextureRect::get_stretch_mode); - ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture"); - ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL, "expand"), "set_expand", "has_expand"); - ADD_PROPERTYNO(PropertyInfo(Variant::INT, "stretch_mode", PROPERTY_HINT_ENUM, "Scale On Expand (Compat),Scale,Tile,Keep,Keep Centered,Keep Aspect,Keep Aspect Centered,Keep Aspect Covered"), "set_stretch_mode", "get_stretch_mode"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "expand"), "set_expand", "has_expand"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "stretch_mode", PROPERTY_HINT_ENUM, "Scale On Expand (Compat),Scale,Tile,Keep,Keep Centered,Keep Aspect,Keep Aspect Centered,Keep Aspect Covered"), "set_stretch_mode", "get_stretch_mode"); BIND_ENUM_CONSTANT(STRETCH_SCALE_ON_EXPAND); BIND_ENUM_CONSTANT(STRETCH_SCALE); diff --git a/scene/gui/texture_rect.h b/scene/gui/texture_rect.h index b684ac816c..ddd101573b 100644 --- a/scene/gui/texture_rect.h +++ b/scene/gui/texture_rect.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/tool_button.cpp b/scene/gui/tool_button.cpp index 4220a6b5ce..a81cc34efa 100644 --- a/scene/gui/tool_button.cpp +++ b/scene/gui/tool_button.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* 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 b8be18e560..8f729cd4df 100644 --- a/scene/gui/tool_button.h +++ b/scene/gui/tool_button.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp index 6f09488b64..49cad6fccf 100644 --- a/scene/gui/tree.cpp +++ b/scene/gui/tree.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* 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 "tree.h" #include <limits.h> -#include "math_funcs.h" -#include "os/input.h" -#include "os/keyboard.h" -#include "os/os.h" -#include "print_string.h" -#include "project_settings.h" +#include "core/math/math_funcs.h" +#include "core/os/input.h" +#include "core/os/keyboard.h" +#include "core/os/os.h" +#include "core/print_string.h" +#include "core/project_settings.h" #include "scene/main/viewport.h" #ifdef TOOLS_ENABLED @@ -159,7 +159,7 @@ void TreeItem::set_text(int p_column, String p_text) { ERR_FAIL_INDEX(p_column, cells.size()); cells.write[p_column].text = p_text; - if (cells[p_column].mode == TreeItem::CELL_MODE_RANGE || cells[p_column].mode == TreeItem::CELL_MODE_RANGE_EXPRESSION) { + if (cells[p_column].mode == TreeItem::CELL_MODE_RANGE) { Vector<String> strings = p_text.split(","); cells.write[p_column].min = INT_MAX; @@ -791,7 +791,6 @@ void TreeItem::_bind_methods() { BIND_ENUM_CONSTANT(CELL_MODE_STRING); BIND_ENUM_CONSTANT(CELL_MODE_CHECK); BIND_ENUM_CONSTANT(CELL_MODE_RANGE); - BIND_ENUM_CONSTANT(CELL_MODE_RANGE_EXPRESSION); BIND_ENUM_CONSTANT(CELL_MODE_ICON); BIND_ENUM_CONSTANT(CELL_MODE_CUSTOM); @@ -902,6 +901,7 @@ 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_guides = get_constant("draw_guides"); 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"); @@ -1071,11 +1071,11 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2 int font_ascent = font->get_ascent(); int ofs = p_pos.x + ((p_item->disable_folding || hide_folding) ? cache.hseparation : cache.item_margin); - int skip = 0; + int skip2 = 0; for (int i = 0; i < columns.size(); i++) { - if (skip) { - skip--; + if (skip2) { + skip2--; continue; } @@ -1102,7 +1102,7 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2 while (i + plus < columns.size() && !p_item->cells[i + plus].editable && p_item->cells[i + plus].mode == TreeItem::CELL_MODE_STRING && p_item->cells[i + plus].text == "" && p_item->cells[i + plus].icon.is_null()) { w += get_column_width(i + plus); plus++; - skip++; + skip2++; } } @@ -1133,7 +1133,9 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2 cell_rect.size.x += cache.hseparation; } - VisualServer::get_singleton()->canvas_item_add_line(ci, Point2i(cell_rect.position.x, cell_rect.position.y + cell_rect.size.height), cell_rect.position + cell_rect.size, cache.guide_color, 1); + if (cache.draw_guides) { + VisualServer::get_singleton()->canvas_item_add_line(ci, Point2i(cell_rect.position.x, cell_rect.position.y + cell_rect.size.height), cell_rect.position + cell_rect.size, cache.guide_color, 1); + } if (i == 0) { @@ -1156,16 +1158,15 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2 r.position.x += icon_width; r.size.x -= icon_width; } - //r.grow(cache.selected->get_margin(MARGIN_LEFT)); + p_item->set_meta("__focus_rect", Rect2(r.position, r.size)); if (has_focus()) { cache.selected_focus->draw(ci, r); - p_item->set_meta("__focus_rect", Rect2(r.position, r.size)); } else { cache.selected->draw(ci, r); } if (text_editor->is_visible_in_tree()) { - Vector2 ofs(0, (text_editor->get_size().height - r.size.height) / 2); - text_editor->set_position(get_global_position() + r.position - ofs); + Vector2 ofs2(0, (text_editor->get_size().height - r.size.height) / 2); + text_editor->set_position(get_global_position() + r.position - ofs2); } } @@ -1245,9 +1246,7 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2 //font->draw( ci, text_pos, p_item->cells[i].text, col,item_rect.size.x-check_w ); } break; - case TreeItem::CELL_MODE_RANGE: - case TreeItem::CELL_MODE_RANGE_EXPRESSION: { - + case TreeItem::CELL_MODE_RANGE: { if (p_item->cells[i].text != "") { if (!p_item->cells[i].editable) @@ -1257,13 +1256,13 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2 String s = RTR("(Other)"); Vector<String> strings = p_item->cells[i].text.split(","); - for (int i = 0; i < strings.size(); i++) { - int value = i; - if (!strings[i].get_slicec(':', 1).empty()) { - value = strings[i].get_slicec(':', 1).to_int(); + for (int j = 0; j < strings.size(); j++) { + int value = j; + if (!strings[j].get_slicec(':', 1).empty()) { + value = strings[j].get_slicec(':', 1).to_int(); } if (option == value) { - s = strings[i].get_slicec(':', 0); + s = strings[j].get_slicec(':', 0); break; } } @@ -1417,12 +1416,15 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2 TreeItem *c = p_item->children; + int prev_ofs = children_pos.y - cache.offset.y + p_draw_ofs.y; + while (c) { - if (cache.draw_relationship_lines == 1) { + if (cache.draw_relationship_lines > 0 && (!hide_root || c->parent != root)) { int root_ofs = children_pos.x + ((p_item->disable_folding || hide_folding) ? cache.hseparation : cache.item_margin); int parent_ofs = p_pos.x + ((p_item->disable_folding || 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); @@ -1435,12 +1437,13 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2 if (root_pos.y + line_width >= 0) { VisualServer::get_singleton()->canvas_item_add_line(ci, root_pos, Point2i(parent_pos.x - Math::floor(line_width / 2), root_pos.y), cache.relationship_line_color, line_width); - VisualServer::get_singleton()->canvas_item_add_line(ci, Point2i(parent_pos.x, root_pos.y), parent_pos, cache.relationship_line_color, line_width); + VisualServer::get_singleton()->canvas_item_add_line(ci, Point2i(parent_pos.x, root_pos.y), Point2i(parent_pos.x, prev_ofs), cache.relationship_line_color, line_width); } if (htotal < 0) { return -1; } + prev_ofs = root_pos.y; } if (htotal >= 0) { @@ -1602,6 +1605,7 @@ void Tree::_range_click_timeout() { mb.instance(); ; + propagate_mouse_activated = false; // done from outside, so signal handler can't clear the tree in the middle of emit (which is a common case) blocked++; propagate_mouse_event(pos + cache.offset, 0, 0, false, root, BUTTON_LEFT, mb); blocked--; @@ -1615,6 +1619,11 @@ void Tree::_range_click_timeout() { if (!click_handled) range_click_timer->stop(); + if (propagate_mouse_activated) { + emit_signal("item_activated"); + propagate_mouse_activated = false; + } + } else { range_click_timer->stop(); } @@ -1721,9 +1730,10 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool if (p_button == BUTTON_LEFT || (p_button == BUTTON_RIGHT && allow_rmb_select)) { /* process selection */ - if (p_doubleclick && (!c.editable || c.mode == TreeItem::CELL_MODE_CUSTOM || c.mode == TreeItem::CELL_MODE_ICON /*|| c.mode==TreeItem::CELL_MODE_CHECK*/)) { //it' s confusing for check + if (p_doubleclick && (!c.editable || c.mode == TreeItem::CELL_MODE_CUSTOM || c.mode == TreeItem::CELL_MODE_ICON /*|| c.mode==TreeItem::CELL_MODE_CHECK*/)) { //it's confusing for check + + propagate_mouse_activated = true; - emit_signal("item_activated"); incr_search.clear(); return -1; } @@ -1821,9 +1831,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool //p_item->edited_signal.call(col); } break; - case TreeItem::CELL_MODE_RANGE: - case TreeItem::CELL_MODE_RANGE_EXPRESSION: { - + case TreeItem::CELL_MODE_RANGE: { if (c.text != "") { //if (x >= (get_column_width(col)-item_h/2)) { @@ -2010,21 +2018,6 @@ void Tree::text_editor_enter(String p_text) { //popup_edited_item->edited_signal.call( popup_edited_item_col ); } break; - case TreeItem::CELL_MODE_RANGE_EXPRESSION: { - - if (evaluator) - c.val = evaluator->eval(p_text); - else - c.val = p_text.to_double(); - - if (c.step > 0) - c.val = Math::stepify(c.val, c.step); - if (c.val < c.min) - c.val = c.min; - else if (c.val > c.max) - c.val = c.max; - - } break; default: { ERR_FAIL(); } } @@ -2203,6 +2196,7 @@ void Tree::_gui_input(Ref<InputEvent> p_event) { Ref<InputEventKey> k = p_event; + bool is_command = k.is_valid() && k->get_command(); if (p_event->is_action("ui_right") && p_event->is_pressed()) { if (!cursor_can_exit_tree) accept_event(); @@ -2239,13 +2233,13 @@ void Tree::_gui_input(Ref<InputEvent> p_event) { _go_left(); } - } else if (p_event->is_action("ui_up") && p_event->is_pressed()) { + } else if (p_event->is_action("ui_up") && p_event->is_pressed() && !is_command) { if (!cursor_can_exit_tree) accept_event(); _go_up(); - } else if (p_event->is_action("ui_down") && p_event->is_pressed()) { + } else if (p_event->is_action("ui_down") && p_event->is_pressed() && !is_command) { if (!cursor_can_exit_tree) accept_event(); @@ -2453,7 +2447,7 @@ void Tree::_gui_input(Ref<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 || popup_edited_item->get_cell_mode(popup_edited_item_col) == TreeItem::CELL_MODE_RANGE_EXPRESSION)) { + if (pressing_for_editor && popup_edited_item && (popup_edited_item->get_cell_mode(popup_edited_item_col) == TreeItem::CELL_MODE_RANGE)) { //range drag if (!range_drag_enabled) { @@ -2538,7 +2532,7 @@ void Tree::_gui_input(Ref<InputEvent> p_event) { pressing_for_editor = false; } - if (cache.click_type == Cache::CLICK_BUTTON) { + if (cache.click_type == Cache::CLICK_BUTTON && cache.click_item != NULL) { // make sure in case of wrong reference after reconstructing whole TreeItems cache.click_item = get_item_at_position(cache.click_pos); emit_signal("button_pressed", cache.click_item, cache.click_column, cache.click_id); @@ -2607,6 +2601,7 @@ void Tree::_gui_input(Ref<InputEvent> p_event) { click_handled = false; pressing_for_editor = false; + propagate_mouse_activated = false; blocked++; propagate_mouse_event(pos + cache.offset, 0, 0, b->is_doubleclick(), root, b->get_button_index(), b); @@ -2644,6 +2639,11 @@ void Tree::_gui_input(Ref<InputEvent> p_event) { } } + if (propagate_mouse_activated) { + emit_signal("item_activated"); + propagate_mouse_activated = false; + } + } break; case BUTTON_WHEEL_UP: { @@ -2697,13 +2697,13 @@ bool Tree::edit_selected() { item_edited(col, s); return true; - } else if ((c.mode == TreeItem::CELL_MODE_RANGE || c.mode == TreeItem::CELL_MODE_RANGE_EXPRESSION) && c.text != "") { + } else if (c.mode == TreeItem::CELL_MODE_RANGE && c.text != "") { popup_menu->clear(); for (int i = 0; i < c.text.get_slice_count(","); i++) { - String s = c.text.get_slicec(',', i); - popup_menu->add_item(s.get_slicec(':', 0), s.get_slicec(':', 1).empty() ? i : s.get_slicec(':', 1).to_int()); + String s2 = c.text.get_slicec(',', i); + popup_menu->add_item(s2.get_slicec(':', 0), s2.get_slicec(':', 1).empty() ? i : s2.get_slicec(':', 1).to_int()); } popup_menu->set_size(Size2(rect.size.width, 0)); @@ -2713,17 +2713,18 @@ bool Tree::edit_selected() { popup_edited_item_col = col; return true; - } else if (c.mode == TreeItem::CELL_MODE_STRING || c.mode == TreeItem::CELL_MODE_RANGE || c.mode == TreeItem::CELL_MODE_RANGE_EXPRESSION) { + } else if (c.mode == TreeItem::CELL_MODE_STRING || c.mode == TreeItem::CELL_MODE_RANGE) { Vector2 ofs(0, (text_editor->get_size().height - rect.size.height) / 2); Point2i textedpos = get_global_position() + rect.position - ofs; + cache.text_editor_position = textedpos; text_editor->set_position(textedpos); text_editor->set_size(rect.size); text_editor->clear(); 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) { + if (c.mode == TreeItem::CELL_MODE_RANGE) { value_editor->set_position(textedpos + Point2i(0, text_editor->get_size().height)); value_editor->set_size(Size2(rect.size.width, 1)); @@ -2953,15 +2954,15 @@ void Tree::_notification(int p_what) { if (show_column_titles) { - //title butons - int ofs = cache.bg->get_margin(MARGIN_LEFT); + //title buttons + int ofs2 = cache.bg->get_margin(MARGIN_LEFT); for (int i = 0; i < columns.size(); i++) { Ref<StyleBox> sb = (cache.click_type == Cache::CLICK_TITLE && cache.click_index == i) ? cache.title_button_pressed : ((cache.hover_type == Cache::CLICK_TITLE && cache.hover_index == i) ? cache.title_button_hover : cache.title_button); Ref<Font> f = cache.tb_font; - Rect2 tbrect = Rect2(ofs - cache.offset.x, bg->get_margin(MARGIN_TOP), get_column_width(i), tbh); + Rect2 tbrect = Rect2(ofs2 - cache.offset.x, bg->get_margin(MARGIN_TOP), get_column_width(i), tbh); sb->draw(ci, tbrect); - ofs += tbrect.size.width; + ofs2 += tbrect.size.width; //text int clip_w = tbrect.size.width - sb->get_minimum_size().width; f->draw_halign(ci, tbrect.position + Point2i(sb->get_offset().x, (tbrect.size.height - f->get_height()) / 2 + f->get_ascent()), HALIGN_CENTER, clip_w, columns[i].title, cache.title_button_color); @@ -2972,6 +2973,21 @@ void Tree::_notification(int p_what) { if (p_what == NOTIFICATION_THEME_CHANGED) { update_cache(); } + + if (p_what == NOTIFICATION_RESIZED || p_what == NOTIFICATION_TRANSFORM_CHANGED) { + + if (popup_edited_item != NULL) { + Rect2 rect = popup_edited_item->get_meta("__focus_rect"); + Vector2 ofs(0, (text_editor->get_size().height - rect.size.height) / 2); + Point2i textedpos = get_global_position() + rect.position - ofs; + + if (cache.text_editor_position != textedpos) { + cache.text_editor_position = textedpos; + text_editor->set_position(textedpos); + value_editor->set_position(textedpos + Point2i(0, text_editor->get_size().height)); + } + } + } } Size2 Tree::get_minimum_size() const { @@ -3713,10 +3729,6 @@ bool Tree::is_folding_hidden() const { return hide_folding; } -void Tree::set_value_evaluator(ValueEvaluator *p_evaluator) { - evaluator = p_evaluator; -} - void Tree::set_drop_mode_flags(int p_flags) { if (drop_mode_flags == p_flags) return; @@ -3831,16 +3843,16 @@ void Tree::_bind_methods() { ADD_SIGNAL(MethodInfo("item_selected")); ADD_SIGNAL(MethodInfo("cell_selected")); - ADD_SIGNAL(MethodInfo("multi_selected", PropertyInfo(Variant::OBJECT, "item"), PropertyInfo(Variant::INT, "column"), PropertyInfo(Variant::BOOL, "selected"))); + ADD_SIGNAL(MethodInfo("multi_selected", PropertyInfo(Variant::OBJECT, "item", PROPERTY_HINT_RESOURCE_TYPE, "TreeItem"), PropertyInfo(Variant::INT, "column"), PropertyInfo(Variant::BOOL, "selected"))); ADD_SIGNAL(MethodInfo("item_rmb_selected", PropertyInfo(Variant::VECTOR2, "position"))); ADD_SIGNAL(MethodInfo("empty_tree_rmb_selected", PropertyInfo(Variant::VECTOR2, "position"))); ADD_SIGNAL(MethodInfo("item_edited")); ADD_SIGNAL(MethodInfo("item_rmb_edited")); ADD_SIGNAL(MethodInfo("item_custom_button_pressed")); ADD_SIGNAL(MethodInfo("item_double_clicked")); - ADD_SIGNAL(MethodInfo("item_collapsed", PropertyInfo(Variant::OBJECT, "item"))); + ADD_SIGNAL(MethodInfo("item_collapsed", PropertyInfo(Variant::OBJECT, "item", PROPERTY_HINT_RESOURCE_TYPE, "TreeItem"))); //ADD_SIGNAL( MethodInfo("item_doubleclicked" ) ); - ADD_SIGNAL(MethodInfo("button_pressed", PropertyInfo(Variant::OBJECT, "item"), PropertyInfo(Variant::INT, "column"), PropertyInfo(Variant::INT, "id"))); + ADD_SIGNAL(MethodInfo("button_pressed", PropertyInfo(Variant::OBJECT, "item", PROPERTY_HINT_RESOURCE_TYPE, "TreeItem"), PropertyInfo(Variant::INT, "column"), PropertyInfo(Variant::INT, "id"))); ADD_SIGNAL(MethodInfo("custom_popup_edited", PropertyInfo(Variant::BOOL, "arrow_clicked"))); ADD_SIGNAL(MethodInfo("item_activated")); ADD_SIGNAL(MethodInfo("column_title_pressed", PropertyInfo(Variant::INT, "column"))); @@ -3904,6 +3916,7 @@ Tree::Tree() { value_editor->set_as_toplevel(true); text_editor->set_as_toplevel(true); + set_notify_transform(true); updating_value_editor = false; pressed_button = -1; @@ -3934,8 +3947,6 @@ Tree::Tree() { hide_folding = false; - evaluator = NULL; - drop_mode_flags = 0; drop_mode_over = NULL; drop_mode_section = 0; @@ -3950,6 +3961,7 @@ Tree::Tree() { cache.hover_cell = -1; allow_reselect = false; + propagate_mouse_activated = false; } Tree::~Tree() { diff --git a/scene/gui/tree.h b/scene/gui/tree.h index 5af66c5faa..26d64baafb 100644 --- a/scene/gui/tree.h +++ b/scene/gui/tree.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,7 +31,6 @@ #ifndef TREE_H #define TREE_H -#include "core/helper/value_evaluator.h" #include "scene/gui/control.h" #include "scene/gui/line_edit.h" #include "scene/gui/popup_menu.h" @@ -54,7 +53,6 @@ public: CELL_MODE_STRING, ///< just a string CELL_MODE_CHECK, ///< string + check CELL_MODE_RANGE, ///< Contains a range - CELL_MODE_RANGE_EXPRESSION, ///< Contains a range CELL_MODE_ICON, ///< Contains an icon, not editable CELL_MODE_CUSTOM, ///< Contains a custom value, show a string, and an edit button }; @@ -331,6 +329,8 @@ private: bool range_drag_enabled; Vector2 range_drag_capture_pos; + bool propagate_mouse_activated; + //TreeItem *cursor_item; //int cursor_column; @@ -436,6 +436,7 @@ private: int button_margin; Point2 offset; int draw_relationship_lines; + int draw_guides; int scroll_border; int scroll_speed; @@ -458,6 +459,8 @@ private: TreeItem *hover_item; int hover_cell; + Point2i text_editor_position; + } cache; int _get_title_button_height() const; @@ -504,8 +507,6 @@ private: bool hide_folding; - ValueEvaluator *evaluator; - int _count_selected_items(TreeItem *p_from) const; void _go_left(); void _go_right(); @@ -516,7 +517,7 @@ protected: static void _bind_methods(); //bind helpers - Object *_create_item(Object *p_parent, int p_idx = -1) { + TreeItem *_create_item(Object *p_parent, int p_idx = -1) { return create_item(Object::cast_to<TreeItem>(p_parent), p_idx); } @@ -601,8 +602,6 @@ public: void set_allow_reselect(bool p_allow); bool get_allow_reselect() const; - void set_value_evaluator(ValueEvaluator *p_evaluator); - Tree(); ~Tree(); }; diff --git a/scene/gui/video_player.cpp b/scene/gui/video_player.cpp index 88e1847533..5768f58977 100644 --- a/scene/gui/video_player.cpp +++ b/scene/gui/video_player.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,7 +31,7 @@ #include "video_player.h" #include "scene/scene_string_names.h" -#include "os/os.h" +#include "core/os/os.h" #include "servers/audio_server.h" int VideoPlayer::sp_get_channel_count() const { @@ -90,49 +90,32 @@ void VideoPlayer::_mix_audio() { AudioFrame vol = AudioFrame(volume, volume); - // Copy to server's audio buffer - switch (AudioServer::get_singleton()->get_speaker_mode()) { + int cc = AudioServer::get_singleton()->get_channel_count(); - case AudioServer::SPEAKER_MODE_STEREO: { - AudioFrame *target = AudioServer::get_singleton()->thread_get_channel_mix_buffer(bus_index, 0); + if (cc == 1) { + AudioFrame *target = AudioServer::get_singleton()->thread_get_channel_mix_buffer(bus_index, 0); + ERR_FAIL_COND(!target); - for (int j = 0; j < buffer_size; j++) { + for (int j = 0; j < buffer_size; j++) { - target[j] += buffer[j] * vol; - } - - } break; - case AudioServer::SPEAKER_SURROUND_51: { - - AudioFrame *targets[2] = { - AudioServer::get_singleton()->thread_get_channel_mix_buffer(bus_index, 1), - AudioServer::get_singleton()->thread_get_channel_mix_buffer(bus_index, 2), - }; - - for (int j = 0; j < buffer_size; j++) { + target[j] += buffer[j] * vol; + } - AudioFrame frame = buffer[j] * vol; - targets[0][j] = frame; - targets[1][j] = frame; - } - } break; - case AudioServer::SPEAKER_SURROUND_71: { + } else { + AudioFrame *targets[4]; - AudioFrame *targets[3] = { - AudioServer::get_singleton()->thread_get_channel_mix_buffer(bus_index, 1), - AudioServer::get_singleton()->thread_get_channel_mix_buffer(bus_index, 2), - AudioServer::get_singleton()->thread_get_channel_mix_buffer(bus_index, 3) - }; + for (int k = 0; k < cc; k++) { + targets[k] = AudioServer::get_singleton()->thread_get_channel_mix_buffer(bus_index, k); + ERR_FAIL_COND(!targets[k]); + } - for (int j = 0; j < buffer_size; j++) { + for (int j = 0; j < buffer_size; j++) { - AudioFrame frame = buffer[j] * vol; - targets[0][j] += frame; - targets[1][j] += frame; - targets[2][j] += frame; + AudioFrame frame = buffer[j] * vol; + for (int k = 0; k < cc; k++) { + targets[k][j] += frame; } - - } break; + } } } diff --git a/scene/gui/video_player.h b/scene/gui/video_player.h index 5c379b5620..62fb7838b6 100644 --- a/scene/gui/video_player.h +++ b/scene/gui/video_player.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* 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/viewport_container.cpp b/scene/gui/viewport_container.cpp index ac5e6020eb..3f7a110c1b 100644 --- a/scene/gui/viewport_container.cpp +++ b/scene/gui/viewport_container.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -121,6 +121,8 @@ void ViewportContainer::_notification(int p_what) { c->set_update_mode(Viewport::UPDATE_ALWAYS); else c->set_update_mode(Viewport::UPDATE_DISABLED); + + c->set_handle_input_locally(false); //do not handle input locally here } } @@ -165,8 +167,34 @@ void ViewportContainer::_input(const Ref<InputEvent> &p_event) { } } +void ViewportContainer::_unhandled_input(const Ref<InputEvent> &p_event) { + + if (Engine::get_singleton()->is_editor_hint()) + return; + + Transform2D xform = get_global_transform(); + + if (stretch) { + Transform2D scale_xf; + scale_xf.scale(Vector2(shrink, shrink)); + xform *= scale_xf; + } + + Ref<InputEvent> ev = p_event->xformed_by(xform.affine_inverse()); + + for (int i = 0; i < get_child_count(); i++) { + + Viewport *c = Object::cast_to<Viewport>(get_child(i)); + if (!c || c->is_input_disabled()) + continue; + + c->unhandled_input(ev); + } +} + void ViewportContainer::_bind_methods() { + ClassDB::bind_method(D_METHOD("_unhandled_input", "event"), &ViewportContainer::_unhandled_input); ClassDB::bind_method(D_METHOD("_input", "event"), &ViewportContainer::_input); ClassDB::bind_method(D_METHOD("set_stretch", "enable"), &ViewportContainer::set_stretch); ClassDB::bind_method(D_METHOD("is_stretch_enabled"), &ViewportContainer::is_stretch_enabled); diff --git a/scene/gui/viewport_container.h b/scene/gui/viewport_container.h index 45c4cd03a1..b4ecc583ba 100644 --- a/scene/gui/viewport_container.h +++ b/scene/gui/viewport_container.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -49,6 +49,7 @@ public: bool is_stretch_enabled() const; void _input(const Ref<InputEvent> &p_event); + void _unhandled_input(const Ref<InputEvent> &p_event); void set_stretch_shrink(int p_shrink); int get_stretch_shrink() const; |