diff options
Diffstat (limited to 'scene/gui')
-rw-r--r-- | scene/gui/color_picker.cpp | 27 | ||||
-rw-r--r-- | scene/gui/color_picker.h | 4 | ||||
-rw-r--r-- | scene/gui/control.cpp | 26 | ||||
-rw-r--r-- | scene/gui/control.h | 12 | ||||
-rw-r--r-- | scene/gui/file_dialog.cpp | 1 | ||||
-rw-r--r-- | scene/gui/graph_edit.cpp | 33 | ||||
-rw-r--r-- | scene/gui/graph_edit.h | 8 | ||||
-rw-r--r-- | scene/gui/item_list.cpp | 1 | ||||
-rw-r--r-- | scene/gui/line_edit.cpp | 22 | ||||
-rw-r--r-- | scene/gui/popup.cpp | 34 | ||||
-rw-r--r-- | scene/gui/popup_menu.cpp | 25 | ||||
-rw-r--r-- | scene/gui/popup_menu.h | 4 | ||||
-rw-r--r-- | scene/gui/progress_bar.cpp | 6 | ||||
-rw-r--r-- | scene/gui/rich_text_label.cpp | 2 | ||||
-rw-r--r-- | scene/gui/scroll_container.cpp | 17 | ||||
-rw-r--r-- | scene/gui/scroll_container.h | 3 | ||||
-rw-r--r-- | scene/gui/tab_container.cpp | 40 | ||||
-rw-r--r-- | scene/gui/text_edit.cpp | 30 |
18 files changed, 218 insertions, 77 deletions
diff --git a/scene/gui/color_picker.cpp b/scene/gui/color_picker.cpp index 34891832e2..f8c188d33d 100644 --- a/scene/gui/color_picker.cpp +++ b/scene/gui/color_picker.cpp @@ -242,6 +242,14 @@ bool ColorPicker::is_raw_mode() const { return raw_mode_enabled; } +void ColorPicker::set_deferred_mode(bool p_enabled) { + deferred_mode_enabled = p_enabled; +} + +bool ColorPicker::is_deferred_mode() const { + return deferred_mode_enabled; +} + void ColorPicker::_update_text_value() { bool visible = true; if (text_is_constructor) { @@ -328,7 +336,11 @@ void ColorPicker::_uv_input(const Ref<InputEvent> &p_event) { last_hsv = color; set_pick_color(color); _update_color(); + if (!deferred_mode_enabled) + emit_signal("color_changed", color); + } else if (deferred_mode_enabled && !bev->is_pressed() && bev->get_button_index() == BUTTON_LEFT) { emit_signal("color_changed", color); + changing_color = false; } else { changing_color = false; } @@ -347,7 +359,8 @@ void ColorPicker::_uv_input(const Ref<InputEvent> &p_event) { last_hsv = color; set_pick_color(color); _update_color(); - emit_signal("color_changed", color); + if (!deferred_mode_enabled) + emit_signal("color_changed", color); } } @@ -368,7 +381,10 @@ void ColorPicker::_w_input(const Ref<InputEvent> &p_event) { last_hsv = color; set_pick_color(color); _update_color(); - emit_signal("color_changed", color); + if (!deferred_mode_enabled) + emit_signal("color_changed", color); + else if (!bev->is_pressed() && bev->get_button_index() == BUTTON_LEFT) + emit_signal("color_changed", color); } Ref<InputEventMouseMotion> mev = p_event; @@ -383,7 +399,8 @@ void ColorPicker::_w_input(const Ref<InputEvent> &p_event) { last_hsv = color; set_pick_color(color); _update_color(); - emit_signal("color_changed", color); + if (!deferred_mode_enabled) + emit_signal("color_changed", color); } } @@ -500,6 +517,8 @@ void ColorPicker::_bind_methods() { ClassDB::bind_method(D_METHOD("get_pick_color"), &ColorPicker::get_pick_color); ClassDB::bind_method(D_METHOD("set_raw_mode", "mode"), &ColorPicker::set_raw_mode); ClassDB::bind_method(D_METHOD("is_raw_mode"), &ColorPicker::is_raw_mode); + ClassDB::bind_method(D_METHOD("set_deferred_mode", "mode"), &ColorPicker::set_deferred_mode); + ClassDB::bind_method(D_METHOD("is_deferred_mode"), &ColorPicker::is_deferred_mode); 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); @@ -522,6 +541,7 @@ void ColorPicker::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::COLOR, "color"), "set_pick_color", "get_pick_color"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "edit_alpha"), "set_edit_alpha", "is_editing_alpha"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "raw_mode"), "set_raw_mode", "is_raw_mode"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "deferred_mode"), "set_deferred_mode", "is_deferred_mode"); ADD_SIGNAL(MethodInfo("color_changed", PropertyInfo(Variant::COLOR, "color"))); } @@ -533,6 +553,7 @@ ColorPicker::ColorPicker() : edit_alpha = true; text_is_constructor = false; raw_mode_enabled = false; + deferred_mode_enabled = false; changing_color = false; screen = NULL; diff --git a/scene/gui/color_picker.h b/scene/gui/color_picker.h index 6b63e5fe60..c8d8e1aa8a 100644 --- a/scene/gui/color_picker.h +++ b/scene/gui/color_picker.h @@ -67,6 +67,7 @@ private: Color color; bool raw_mode_enabled; + bool deferred_mode_enabled; bool updating; bool changing_color; float h, s, v; @@ -107,6 +108,9 @@ public: void set_raw_mode(bool p_enabled); bool is_raw_mode() const; + void set_deferred_mode(bool p_enabled); + bool is_deferred_mode() const; + void set_focus_on_line_edit(); ColorPicker(); diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp index d07b5a9f65..6ef8016dd5 100644 --- a/scene/gui/control.cpp +++ b/scene/gui/control.cpp @@ -160,8 +160,16 @@ void Control::_update_minimum_size_cache() { Size2 minsize = get_minimum_size(); minsize.x = MAX(minsize.x, data.custom_minimum_size.x); minsize.y = MAX(minsize.y, data.custom_minimum_size.y); + + bool size_changed = false; + if (data.minimum_size_cache != minsize) + size_changed = true; + data.minimum_size_cache = minsize; data.minimum_size_valid = true; + + if (size_changed) + minimum_size_changed(); } Size2 Control::get_combined_minimum_size() const { @@ -452,10 +460,8 @@ void Control::_notification(int p_notification) { } break; case NOTIFICATION_POST_ENTER_TREE: { - if (is_visible_in_tree()) { - data.minimum_size_valid = false; - _size_changed(); - } + data.minimum_size_valid = false; + _size_changed(); } break; case NOTIFICATION_EXIT_TREE: { @@ -2889,12 +2895,12 @@ void Control::_bind_methods() { ADD_PROPERTYNZ(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"), "set_focus_neighbour", "get_focus_neighbour", MARGIN_LEFT); - ADD_PROPERTYINZ(PropertyInfo(Variant::NODE_PATH, "focus_neighbour_top"), "set_focus_neighbour", "get_focus_neighbour", MARGIN_TOP); - ADD_PROPERTYINZ(PropertyInfo(Variant::NODE_PATH, "focus_neighbour_right"), "set_focus_neighbour", "get_focus_neighbour", MARGIN_RIGHT); - ADD_PROPERTYINZ(PropertyInfo(Variant::NODE_PATH, "focus_neighbour_bottom"), "set_focus_neighbour", "get_focus_neighbour", MARGIN_BOTTOM); - ADD_PROPERTYNZ(PropertyInfo(Variant::NODE_PATH, "focus_next"), "set_focus_next", "get_focus_next"); - ADD_PROPERTYNZ(PropertyInfo(Variant::NODE_PATH, "focus_previous"), "set_focus_previous", "get_focus_previous"); + 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_GROUP("Mouse", "mouse_"); diff --git a/scene/gui/control.h b/scene/gui/control.h index 9124256624..633f92f733 100644 --- a/scene/gui/control.h +++ b/scene/gui/control.h @@ -202,12 +202,12 @@ private: NodePath focus_next; NodePath focus_prev; - HashMap<StringName, Ref<Texture>, StringNameHasher> icon_override; - HashMap<StringName, Ref<Shader>, StringNameHasher> shader_override; - HashMap<StringName, Ref<StyleBox>, StringNameHasher> style_override; - HashMap<StringName, Ref<Font>, StringNameHasher> font_override; - HashMap<StringName, Color, StringNameHasher> color_override; - HashMap<StringName, int, StringNameHasher> constant_override; + HashMap<StringName, Ref<Texture> > icon_override; + HashMap<StringName, Ref<Shader> > shader_override; + HashMap<StringName, Ref<StyleBox> > style_override; + HashMap<StringName, Ref<Font> > font_override; + HashMap<StringName, Color> color_override; + HashMap<StringName, int> constant_override; Map<Ref<Font>, int> font_refcount; } data; diff --git a/scene/gui/file_dialog.cpp b/scene/gui/file_dialog.cpp index 4bd92d888d..25cb74a494 100644 --- a/scene/gui/file_dialog.cpp +++ b/scene/gui/file_dialog.cpp @@ -777,6 +777,7 @@ void FileDialog::_bind_methods() { ClassDB::bind_method(D_METHOD("set_mode", "mode"), &FileDialog::set_mode); ClassDB::bind_method(D_METHOD("get_mode"), &FileDialog::get_mode); ClassDB::bind_method(D_METHOD("get_vbox"), &FileDialog::get_vbox); + ClassDB::bind_method(D_METHOD("get_line_edit"), &FileDialog::get_line_edit); ClassDB::bind_method(D_METHOD("set_access", "access"), &FileDialog::set_access); ClassDB::bind_method(D_METHOD("get_access"), &FileDialog::get_access); ClassDB::bind_method(D_METHOD("set_show_hidden_files", "show"), &FileDialog::set_show_hidden_files); diff --git a/scene/gui/graph_edit.cpp b/scene/gui/graph_edit.cpp index 38ce91a4df..e2c730a56e 100644 --- a/scene/gui/graph_edit.cpp +++ b/scene/gui/graph_edit.cpp @@ -58,6 +58,7 @@ Error GraphEdit::connect_node(const StringName &p_from, int p_from_port, const S c.from_port = p_from_port; c.to = p_to; c.to_port = p_to_port; + c.activity = 0; connections.push_back(c); top_layer->update(); update(); @@ -624,6 +625,7 @@ void GraphEdit::_draw_cos_line(CanvasItem *p_where, const Vector2 &p_from, const void GraphEdit::_connections_layer_draw() { + Color activity_color = get_color("activity"); //draw connections List<List<Connection>::Element *> to_erase; for (List<Connection>::Element *E = connections.front(); E; E = E->next()) { @@ -661,6 +663,11 @@ void GraphEdit::_connections_layer_draw() { Color color = gfrom->get_connection_output_color(E->get().from_port); Vector2 topos = gto->get_connection_input_position(E->get().to_port) + gto->get_offset() * zoom; Color tocolor = gto->get_connection_input_color(E->get().to_port); + + if (E->get().activity > 0) { + color = color.linear_interpolate(activity_color, E->get().activity); + tocolor = tocolor.linear_interpolate(activity_color, E->get().activity); + } _draw_cos_line(connections_layer, frompos, topos, color, tocolor); } @@ -980,6 +987,23 @@ void GraphEdit::_gui_input(const Ref<InputEvent> &p_ev) { } } +void GraphEdit::set_connection_activity(const StringName &p_from, int p_from_port, const StringName &p_to, int p_to_port, float p_activity) { + + for (List<Connection>::Element *E = connections.front(); E; E = E->next()) { + + 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)) { + //update only if changed + top_layer->update(); + connections_layer->update(); + } + E->get().activity = p_activity; + return; + } + } +} + void GraphEdit::clear_connections() { connections.clear(); @@ -1141,11 +1165,16 @@ void GraphEdit::_snap_value_changed(double) { update(); } +HBoxContainer *GraphEdit::get_zoom_hbox() { + return zoom_hb; +} + void GraphEdit::_bind_methods() { ClassDB::bind_method(D_METHOD("connect_node", "from", "from_port", "to", "to_port"), &GraphEdit::connect_node); ClassDB::bind_method(D_METHOD("is_node_connected", "from", "from_port", "to", "to_port"), &GraphEdit::is_node_connected); ClassDB::bind_method(D_METHOD("disconnect_node", "from", "from_port", "to", "to_port"), &GraphEdit::disconnect_node); + ClassDB::bind_method(D_METHOD("set_connection_activity", "from", "from_port", "to", "to_port", "amount"), &GraphEdit::set_connection_activity); ClassDB::bind_method(D_METHOD("get_connection_list"), &GraphEdit::_get_connection_list); ClassDB::bind_method(D_METHOD("clear_connections"), &GraphEdit::clear_connections); ClassDB::bind_method(D_METHOD("get_scroll_ofs"), &GraphEdit::get_scroll_ofs); @@ -1187,6 +1216,8 @@ void GraphEdit::_bind_methods() { ClassDB::bind_method(D_METHOD("_update_scroll_offset"), &GraphEdit::_update_scroll_offset); ClassDB::bind_method(D_METHOD("_connections_layer_draw"), &GraphEdit::_connections_layer_draw); + ClassDB::bind_method(D_METHOD("get_zoom_hbox"), &GraphEdit::get_zoom_hbox); + ClassDB::bind_method(D_METHOD("set_selected", "node"), &GraphEdit::set_selected); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "right_disconnects"), "set_right_disconnects", "is_right_disconnects_enabled"); @@ -1253,7 +1284,7 @@ GraphEdit::GraphEdit() { zoom = 1; - HBoxContainer *zoom_hb = memnew(HBoxContainer); + zoom_hb = memnew(HBoxContainer); top_layer->add_child(zoom_hb); zoom_hb->set_position(Vector2(10, 10)); diff --git a/scene/gui/graph_edit.h b/scene/gui/graph_edit.h index 3bfde44854..14789001e4 100644 --- a/scene/gui/graph_edit.h +++ b/scene/gui/graph_edit.h @@ -31,6 +31,7 @@ #ifndef GRAPH_EDIT_H #define GRAPH_EDIT_H +#include "scene/gui/box_container.h" #include "scene/gui/graph_node.h" #include "scene/gui/scroll_bar.h" #include "scene/gui/slider.h" @@ -62,6 +63,7 @@ public: StringName to; int from_port; int to_port; + float activity; }; private: @@ -157,6 +159,8 @@ private: Set<int> valid_left_disconnect_types; Set<int> valid_right_disconnect_types; + HBoxContainer *zoom_hb; + friend class GraphEditFilter; bool _filter_input(const Point2 &p_point); void _snap_toggled(); @@ -175,6 +179,8 @@ public: void disconnect_node(const StringName &p_from, int p_from_port, const StringName &p_to, int p_to_port); void clear_connections(); + void set_connection_activity(const StringName &p_from, int p_from_port, const StringName &p_to, int p_to_port, float p_activity); + void add_valid_connection_type(int p_type, int p_with_type); void remove_valid_connection_type(int p_type, int p_with_type); bool is_valid_connection_type(int p_type, int p_with_type) const; @@ -206,6 +212,8 @@ public: int get_snap() const; void set_snap(int p_snap); + HBoxContainer *get_zoom_hbox(); + GraphEdit(); }; diff --git a/scene/gui/item_list.cpp b/scene/gui/item_list.cpp index 57b9a9a11b..72ed0e9b81 100644 --- a/scene/gui/item_list.cpp +++ b/scene/gui/item_list.cpp @@ -942,6 +942,7 @@ void ItemList::_notification(int p_what) { } } + minimum_size_changed(); shape_changed = false; } diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp index f1f1a66b47..0cd5219f8f 100644 --- a/scene/gui/line_edit.cpp +++ b/scene/gui/line_edit.cpp @@ -565,6 +565,9 @@ void LineEdit::_notification(int p_what) { #endif case NOTIFICATION_RESIZED: { + if (expand_to_text_length) { + window_pos = 0; //force scroll back since it's expanding to text length + } set_cursor_position(get_cursor_position()); } break; @@ -610,7 +613,8 @@ void LineEdit::_notification(int p_what) { } int x_ofs = 0; - int cached_text_width = text.empty() ? cached_placeholder_width : cached_width; + bool using_placeholder = text.empty(); + int cached_text_width = using_placeholder ? cached_placeholder_width : cached_width; switch (align) { @@ -645,9 +649,9 @@ void LineEdit::_notification(int p_what) { Color font_color_selected = get_color("font_color_selected"); Color cursor_color = get_color("cursor_color"); - const String &t = text.empty() ? placeholder : text; + const String &t = using_placeholder ? placeholder : text; // draw placeholder color - if (text.empty()) + if (using_placeholder) font_color.a *= placeholder_alpha; font_color.a *= disabled_alpha; @@ -756,7 +760,8 @@ void LineEdit::_notification(int p_what) { if (has_focus()) { - OS::get_singleton()->set_ime_position(get_global_position() + Point2(x_ofs, y_ofs + caret_height)); + 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; @@ -766,6 +771,7 @@ void LineEdit::_notification(int p_what) { draw_caret = true; } + 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); @@ -778,6 +784,7 @@ void LineEdit::_notification(int p_what) { 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(); @@ -1094,11 +1101,12 @@ void LineEdit::set_cursor_position(int p_pos) { for (int i = cursor_pos; i >= window_pos; i--) { if (i >= text.length()) { - accum_width = font->get_char_size(' ').width; //anything should do + //do not do this, because if the cursor is at the end, its just fine that it takes no space + //accum_width = font->get_char_size(' ').width; //anything should do } else { accum_width += font->get_char_size(text[i], i + 1 < text.length() ? text[i + 1] : 0).width; //anything should do } - if (accum_width >= window_width) + if (accum_width > window_width) break; wp = i; @@ -1165,7 +1173,7 @@ Size2 LineEdit::get_minimum_size() const { int mstext = get_constant("minimum_spaces") * space_size; if (expand_to_text_length) { - mstext = MAX(mstext, font->get_string_size(text).x + space_size); //add a spce because some fonts are too exact + mstext = MAX(mstext, font->get_string_size(text).x + space_size); //add a spce because some fonts are too exact, and because cursor needs a bit more when at the end } min.width += mstext; diff --git a/scene/gui/popup.cpp b/scene/gui/popup.cpp index d18a3a3f2f..26d01ecc09 100644 --- a/scene/gui/popup.cpp +++ b/scene/gui/popup.cpp @@ -113,37 +113,9 @@ void Popup::set_as_minsize() { void Popup::popup_centered_minsize(const Size2 &p_minsize) { - Size2 total_minsize = p_minsize; - - for (int i = 0; i < get_child_count(); i++) { - - Control *c = Object::cast_to<Control>(get_child(i)); - if (!c) - continue; - if (!c->is_visible()) - continue; - - Size2 minsize = c->get_combined_minimum_size(); - - for (int j = 0; j < 2; j++) { - - Margin m_beg = Margin(0 + j); - Margin m_end = Margin(2 + j); - - float margin_begin = c->get_margin(m_beg); - float margin_end = c->get_margin(m_end); - float anchor_begin = c->get_anchor(m_beg); - float anchor_end = c->get_anchor(m_end); - - minsize[j] += margin_begin * (ANCHOR_END - anchor_begin) + margin_end * anchor_end; - } - - total_minsize.width = MAX(total_minsize.width, minsize.width); - total_minsize.height = MAX(total_minsize.height, minsize.height); - } - - popup_centered(total_minsize); - popped_up = true; + set_custom_minimum_size(p_minsize); + _fix_size(); + popup_centered(); } void Popup::popup_centered(const Size2 &p_size) { diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp index 93865cebde..18e609c798 100644 --- a/scene/gui/popup_menu.cpp +++ b/scene/gui/popup_menu.cpp @@ -440,6 +440,8 @@ void PopupMenu::_notification(int p_what) { float h; Size2 icon_size; + 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()) { @@ -463,18 +465,18 @@ void PopupMenu::_notification(int p_what) { if (items[i].checkable_type) { Texture *icon = (items[i].checked ? check[items[i].checkable_type - 1] : uncheck[items[i].checkable_type - 1]).ptr(); - icon->draw(ci, item_ofs + Point2(0, Math::floor((h - icon->get_height()) / 2.0))); + icon->draw(ci, item_ofs + Point2(0, Math::floor((h - icon->get_height()) / 2.0)), icon_color); item_ofs.x += icon->get_width() + hseparation; } if (!items[i].icon.is_null()) { - items[i].icon->draw(ci, item_ofs + Point2(0, Math::floor((h - icon_size.height) / 2.0))); + items[i].icon->draw(ci, item_ofs + Point2(0, Math::floor((h - icon_size.height) / 2.0)), icon_color); item_ofs.x += items[i].icon->get_width(); item_ofs.x += hseparation; } if (items[i].submenu != "") { - submenu->draw(ci, Point2(size.width - style->get_margin(MARGIN_RIGHT) - submenu->get_width(), item_ofs.y + Math::floor(h - submenu->get_height()) / 2)); + submenu->draw(ci, Point2(size.width - style->get_margin(MARGIN_RIGHT) - submenu->get_width(), item_ofs.y + Math::floor(h - submenu->get_height()) / 2), icon_color); } item_ofs.y += font->get_ascent(); @@ -913,6 +915,13 @@ void PopupMenu::set_item_multistate(int p_idx, int p_state) { update(); } +void PopupMenu::set_item_shortcut_disabled(int p_idx, bool p_disabled) { + + ERR_FAIL_INDEX(p_idx, items.size()); + items[p_idx].shortcut_is_disabled = p_disabled; + update(); +} + void PopupMenu::toggle_item_multistate(int p_idx) { ERR_FAIL_INDEX(p_idx, items.size()); @@ -937,6 +946,12 @@ bool PopupMenu::is_item_radio_checkable(int p_idx) const { return items[p_idx].checkable_type == Item::CHECKABLE_TYPE_RADIO_BUTTON; } +bool PopupMenu::is_item_shortcut_disabled(int p_idx) const { + + ERR_FAIL_INDEX_V(p_idx, items.size(), false); + return items[p_idx].shortcut_is_disabled; +} + int PopupMenu::get_item_count() const { return items.size(); @@ -963,7 +978,7 @@ bool PopupMenu::activate_item_by_event(const Ref<InputEvent> &p_event, bool p_fo int il = items.size(); for (int i = 0; i < il; i++) { - if (is_item_disabled(i)) + if (is_item_disabled(i) || items[i].shortcut_is_disabled) continue; if (items[i].shortcut.is_valid() && items[i].shortcut->is_shortcut(p_event) && (items[i].shortcut_is_global || !p_for_global_only)) { @@ -1248,6 +1263,7 @@ void PopupMenu::_bind_methods() { ClassDB::bind_method(D_METHOD("set_item_tooltip", "idx", "tooltip"), &PopupMenu::set_item_tooltip); ClassDB::bind_method(D_METHOD("set_item_shortcut", "idx", "shortcut", "global"), &PopupMenu::set_item_shortcut, DEFVAL(false)); ClassDB::bind_method(D_METHOD("set_item_multistate", "idx", "state"), &PopupMenu::set_item_multistate); + ClassDB::bind_method(D_METHOD("set_item_shortcut_disabled", "idx", "disabled"), &PopupMenu::set_item_shortcut_disabled); ClassDB::bind_method(D_METHOD("toggle_item_checked", "idx"), &PopupMenu::toggle_item_checked); ClassDB::bind_method(D_METHOD("toggle_item_multistate", "idx"), &PopupMenu::toggle_item_multistate); @@ -1264,6 +1280,7 @@ void PopupMenu::_bind_methods() { ClassDB::bind_method(D_METHOD("is_item_separator", "idx"), &PopupMenu::is_item_separator); ClassDB::bind_method(D_METHOD("is_item_checkable", "idx"), &PopupMenu::is_item_checkable); ClassDB::bind_method(D_METHOD("is_item_radio_checkable", "idx"), &PopupMenu::is_item_radio_checkable); + ClassDB::bind_method(D_METHOD("is_item_shortcut_disabled", "idx"), &PopupMenu::is_item_shortcut_disabled); ClassDB::bind_method(D_METHOD("get_item_tooltip", "idx"), &PopupMenu::get_item_tooltip); ClassDB::bind_method(D_METHOD("get_item_shortcut", "idx"), &PopupMenu::get_item_shortcut); diff --git a/scene/gui/popup_menu.h b/scene/gui/popup_menu.h index fde91bd845..d3ee9be1c0 100644 --- a/scene/gui/popup_menu.h +++ b/scene/gui/popup_menu.h @@ -64,6 +64,7 @@ class PopupMenu : public Popup { int h_ofs; Ref<ShortCut> shortcut; bool shortcut_is_global; + bool shortcut_is_disabled; Item() { checked = false; @@ -76,6 +77,7 @@ class PopupMenu : public Popup { _ofs_cache = 0; h_ofs = 0; shortcut_is_global = false; + shortcut_is_disabled = false; } }; @@ -149,6 +151,7 @@ public: void set_item_h_offset(int p_idx, int p_offset); void set_item_multistate(int p_idx, int p_state); void toggle_item_multistate(int p_idx); + void set_item_shortcut_disabled(int p_idx, bool p_disabled); void toggle_item_checked(int p_idx); @@ -165,6 +168,7 @@ public: bool is_item_separator(int p_idx) const; bool is_item_checkable(int p_idx) const; bool is_item_radio_checkable(int p_idx) const; + bool is_item_shortcut_disabled(int p_idx) const; String get_item_tooltip(int p_idx) const; Ref<ShortCut> get_item_shortcut(int p_idx) const; int get_item_state(int p_idx) const; diff --git a/scene/gui/progress_bar.cpp b/scene/gui/progress_bar.cpp index 37e519e375..fc5d56237a 100644 --- a/scene/gui/progress_bar.cpp +++ b/scene/gui/progress_bar.cpp @@ -39,9 +39,9 @@ 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) { - minimum_size.height = MAX(minimum_size.height, bg->get_minimum_size().height + font->get_height()); - } + //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()); + //} return minimum_size; } diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp index f34559fc8d..ce2e3538da 100644 --- a/scene/gui/rich_text_label.cpp +++ b/scene/gui/rich_text_label.cpp @@ -324,7 +324,7 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int & 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)) { + if (_find_meta(text, &meta) && underline_meta) { underline = true; } diff --git a/scene/gui/scroll_container.cpp b/scene/gui/scroll_container.cpp index 2dd5c64378..495d618930 100644 --- a/scene/gui/scroll_container.cpp +++ b/scene/gui/scroll_container.cpp @@ -241,10 +241,10 @@ void ScrollContainer::_notification(int p_what) { size -= sb->get_minimum_size(); ofs += sb->get_offset(); - if (h_scroll->is_visible_in_tree()) + if (h_scroll->is_visible_in_tree() && h_scroll->get_parent() == this) //scrolls may have been moved out for reasons size.y -= h_scroll->get_minimum_size().y; - if (v_scroll->is_visible_in_tree()) + 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; for (int i = 0; i < get_child_count(); i++) { @@ -482,6 +482,16 @@ String ScrollContainer::get_configuration_warning() const { return ""; } +HScrollBar *ScrollContainer::get_h_scrollbar() { + + return h_scroll; +} + +VScrollBar *ScrollContainer::get_v_scrollbar() { + + return v_scroll; +} + void ScrollContainer::_bind_methods() { ClassDB::bind_method(D_METHOD("_scroll_moved"), &ScrollContainer::_scroll_moved); @@ -498,6 +508,9 @@ void ScrollContainer::_bind_methods() { ClassDB::bind_method(D_METHOD("set_deadzone", "deadzone"), &ScrollContainer::set_deadzone); ClassDB::bind_method(D_METHOD("get_deadzone"), &ScrollContainer::get_deadzone); + ClassDB::bind_method(D_METHOD("get_h_scrollbar"), &ScrollContainer::get_h_scrollbar); + ClassDB::bind_method(D_METHOD("get_v_scrollbar"), &ScrollContainer::get_v_scrollbar); + ADD_SIGNAL(MethodInfo("scroll_started")); ADD_SIGNAL(MethodInfo("scroll_ended")); diff --git a/scene/gui/scroll_container.h b/scene/gui/scroll_container.h index 3fe1ed447a..abef80294a 100644 --- a/scene/gui/scroll_container.h +++ b/scene/gui/scroll_container.h @@ -92,6 +92,9 @@ public: int get_deadzone() const; void set_deadzone(int p_deadzone); + HScrollBar *get_h_scrollbar(); + VScrollBar *get_v_scrollbar(); + virtual bool clips_input() const; virtual String get_configuration_warning() const; diff --git a/scene/gui/tab_container.cpp b/scene/gui/tab_container.cpp index 0363dd44c2..4f72b5c6ed 100644 --- a/scene/gui/tab_container.cpp +++ b/scene/gui/tab_container.cpp @@ -143,6 +143,42 @@ void TabContainer::_notification(int p_what) { switch (p_what) { + case NOTIFICATION_RESIZED: { + + Vector<Control *> tabs = _get_tabs(); + int side_margin = get_constant("side_margin"); + Ref<Texture> menu = get_icon("menu"); + Ref<Texture> increment = get_icon("increment"); + Ref<Texture> decrement = get_icon("decrement"); + int header_width = get_size().width - side_margin * 2; + + // Find the width of the header area. + if (popup) + header_width -= menu->get_width(); + if (buttons_visible_cache) + header_width -= increment->get_width() + decrement->get_width(); + if (popup || buttons_visible_cache) + header_width += side_margin; + + // Find the width of all tabs after first_tab_cache. + int all_tabs_width = 0; + for (int i = first_tab_cache; i < tabs.size(); i++) { + int tab_width = _get_tab_width(i); + all_tabs_width += tab_width; + } + + // Check if tabs before first_tab_cache would fit into the header area. + for (int i = first_tab_cache - 1; i >= 0; i--) { + int tab_width = _get_tab_width(i); + + if (all_tabs_width + tab_width > header_width) + break; + + all_tabs_width += tab_width; + first_tab_cache--; + } + } break; + case NOTIFICATION_DRAW: { RID canvas = get_canvas_item(); @@ -197,6 +233,10 @@ void TabContainer::_notification(int p_what) { header_width += side_margin; } + if (!buttons_visible_cache) { + first_tab_cache = 0; + } + // Go through the visible tabs to find the width they occupy. all_tabs_width = 0; Vector<int> tab_widths; diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index 55a650ff12..4fe06e9a4c 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -426,6 +426,9 @@ void TextEdit::_update_scrollbars() { void TextEdit::_click_selection_held() { + // Warning: is_mouse_button_pressed(BUTTON_LEFT) returns false for double+ clicks, so this doesn't work for MODE_WORD + // and MODE_LINE. However, moving the mouse triggers _gui_input, which calls these functions too, so that's not a huge problem. + // I'm unsure if there's an actual fix that doesn't have a ton of side effects. if (Input::get_singleton()->is_mouse_button_pressed(BUTTON_LEFT) && selection.selecting_mode != Selection::MODE_NONE) { switch (selection.selecting_mode) { case Selection::MODE_POINTER: { @@ -447,7 +450,7 @@ void TextEdit::_click_selection_held() { } void TextEdit::_update_selection_mode_pointer() { - Point2 mp = Input::get_singleton()->get_mouse_position() - get_global_position(); + Point2 mp = get_local_mouse_position(); int row, col; _get_mouse_pos(Point2i(mp.x, mp.y), row, col); @@ -455,14 +458,14 @@ void TextEdit::_update_selection_mode_pointer() { select(selection.selecting_line, selection.selecting_column, row, col); cursor_set_line(row, false); - cursor_set_column(col, false); + cursor_set_column(col); update(); click_select_held->start(); } void TextEdit::_update_selection_mode_word() { - Point2 mp = Input::get_singleton()->get_mouse_position() - get_global_position(); + Point2 mp = get_local_mouse_position(); int row, col; _get_mouse_pos(Point2i(mp.x, mp.y), row, col); @@ -496,26 +499,29 @@ void TextEdit::_update_selection_mode_word() { selection.selected_word_beg = beg; selection.selected_word_end = end; selection.selected_word_origin = beg; + cursor_set_line(selection.to_line, false); cursor_set_column(selection.to_column); } else { if ((col <= selection.selected_word_origin && row == selection.selecting_line) || row < selection.selecting_line) { selection.selecting_column = selection.selected_word_end; select(row, beg, selection.selecting_line, selection.selected_word_end); + cursor_set_line(selection.from_line, false); cursor_set_column(selection.from_column); } else { selection.selecting_column = selection.selected_word_beg; select(selection.selecting_line, selection.selected_word_beg, row, end); + cursor_set_line(selection.to_line, false); cursor_set_column(selection.to_column); } } - cursor_set_line(row, false); update(); + click_select_held->start(); } void TextEdit::_update_selection_mode_line() { - Point2 mp = Input::get_singleton()->get_mouse_position() - get_global_position(); + Point2 mp = get_local_mouse_position(); int row, col; _get_mouse_pos(Point2i(mp.x, mp.y), row, col); @@ -531,7 +537,7 @@ void TextEdit::_update_selection_mode_line() { selection.selecting_column = 0; col = text[row].length(); } - cursor_set_column(0, false); + cursor_set_column(0); select(selection.selecting_line, selection.selecting_column, row, col); update(); @@ -1388,6 +1394,7 @@ 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); } @@ -1399,6 +1406,7 @@ void TextEdit::_notification(int p_what) { draw_caret = true; } + 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); @@ -1413,6 +1421,7 @@ void TextEdit::_notification(int p_what) { 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(); @@ -1657,14 +1666,17 @@ void TextEdit::_get_mouse_pos(const Point2i &p_mouse, int &r_row, int &r_col) co rows /= get_row_height(); rows += get_v_scroll_offset(); int first_vis_line = get_first_visible_line(); + int last_vis_line = get_last_visible_line(); int row = first_vis_line + Math::floor(rows); int wrap_index = 0; if (is_wrap_enabled() || is_hiding_enabled()) { - int f_ofs = num_lines_from_rows(first_vis_line, cursor.wrap_ofs, rows + 1, wrap_index) - 1; - row = first_vis_line + f_ofs; - row = CLAMP(row, 0, get_last_visible_line() + 1); + int f_ofs = num_lines_from_rows(first_vis_line, cursor.wrap_ofs, rows + (1 * SGN(rows)), wrap_index) - 1; + if (rows < 0) + row = first_vis_line - f_ofs; + else + row = first_vis_line + f_ofs; } if (row < 0) |