diff options
Diffstat (limited to 'scene/gui')
-rw-r--r-- | scene/gui/base_button.cpp | 4 | ||||
-rw-r--r-- | scene/gui/color_picker.cpp | 388 | ||||
-rw-r--r-- | scene/gui/color_picker.h | 49 | ||||
-rw-r--r-- | scene/gui/control.cpp | 95 | ||||
-rw-r--r-- | scene/gui/control.h | 7 | ||||
-rw-r--r-- | scene/gui/file_dialog.cpp | 2 | ||||
-rw-r--r-- | scene/gui/gradient_edit.cpp | 2 | ||||
-rw-r--r-- | scene/gui/graph_edit.cpp | 25 | ||||
-rw-r--r-- | scene/gui/graph_edit.h | 2 | ||||
-rw-r--r-- | scene/gui/graph_node.cpp | 2 | ||||
-rw-r--r-- | scene/gui/item_list.cpp | 2 | ||||
-rw-r--r-- | scene/gui/line_edit.cpp | 2 | ||||
-rw-r--r-- | scene/gui/menu_button.cpp | 2 | ||||
-rw-r--r-- | scene/gui/popup_menu.cpp | 2 | ||||
-rw-r--r-- | scene/gui/rich_text_label.cpp | 26 | ||||
-rw-r--r-- | scene/gui/scroll_bar.cpp | 2 | ||||
-rw-r--r-- | scene/gui/scroll_container.cpp | 2 | ||||
-rw-r--r-- | scene/gui/slider.cpp | 2 | ||||
-rw-r--r-- | scene/gui/spin_box.cpp | 2 | ||||
-rw-r--r-- | scene/gui/split_container.cpp | 2 | ||||
-rw-r--r-- | scene/gui/subviewport_container.cpp | 4 | ||||
-rw-r--r-- | scene/gui/tab_container.cpp | 2 | ||||
-rw-r--r-- | scene/gui/tabs.cpp | 61 | ||||
-rw-r--r-- | scene/gui/tabs.h | 4 | ||||
-rw-r--r-- | scene/gui/text_edit.cpp | 2 | ||||
-rw-r--r-- | scene/gui/tree.cpp | 2 |
26 files changed, 526 insertions, 169 deletions
diff --git a/scene/gui/base_button.cpp b/scene/gui/base_button.cpp index db13b9b11f..826fd0189b 100644 --- a/scene/gui/base_button.cpp +++ b/scene/gui/base_button.cpp @@ -53,6 +53,8 @@ void BaseButton::_unpress_group() { } void BaseButton::_gui_input(Ref<InputEvent> p_event) { + ERR_FAIL_COND(p_event.is_null()); + if (status.disabled) { // no interaction with disabled button return; } @@ -323,6 +325,8 @@ Ref<Shortcut> BaseButton::get_shortcut() const { } void BaseButton::_unhandled_key_input(Ref<InputEvent> p_event) { + ERR_FAIL_COND(p_event.is_null()); + if (!_is_focus_owner_in_shorcut_context()) { return; } diff --git a/scene/gui/color_picker.cpp b/scene/gui/color_picker.cpp index 5822119b46..b78f9cad24 100644 --- a/scene/gui/color_picker.cpp +++ b/scene/gui/color_picker.cpp @@ -115,19 +115,22 @@ void ColorPicker::_update_controls() { if (raw_mode_enabled) { for (int i = 0; i < 3; i++) { - scroll[i]->add_theme_icon_override("grabber", Ref<Texture2D>()); - scroll[i]->add_theme_icon_override("grabber_highlight", Ref<Texture2D>()); - scroll[i]->add_theme_style_override("slider", Ref<StyleBox>()); - scroll[i]->add_theme_style_override("grabber_area", Ref<StyleBox>()); - scroll[i]->add_theme_style_override("grabber_area_highlight", Ref<StyleBox>()); + scroll[i]->remove_theme_icon_override("grabber"); + scroll[i]->remove_theme_icon_override("grabber_highlight"); + scroll[i]->remove_theme_style_override("slider"); + scroll[i]->remove_theme_style_override("grabber_area"); + scroll[i]->remove_theme_style_override("grabber_area_highlight"); } } else { - for (int i = 0; i < 3; i++) { - scroll[i]->add_theme_icon_override("grabber", get_theme_icon("bar_arrow")); - scroll[i]->add_theme_icon_override("grabber_highlight", get_theme_icon("bar_arrow")); - scroll[i]->add_theme_style_override("slider", Ref<StyleBoxEmpty>(memnew(StyleBoxEmpty))); - scroll[i]->add_theme_style_override("grabber_area", Ref<StyleBoxEmpty>(memnew(StyleBoxEmpty))); - scroll[i]->add_theme_style_override("grabber_area_highlight", Ref<StyleBoxEmpty>(memnew(StyleBoxEmpty))); + Ref<StyleBoxEmpty> style_box_empty(memnew(StyleBoxEmpty)); + Ref<Texture2D> bar_arrow = get_theme_icon("bar_arrow"); + + for (int i = 0; i < 4; i++) { + scroll[i]->add_theme_icon_override("grabber", bar_arrow); + scroll[i]->add_theme_icon_override("grabber_highlight", bar_arrow); + scroll[i]->add_theme_style_override("slider", style_box_empty); + scroll[i]->add_theme_style_override("grabber_area", style_box_empty); + scroll[i]->add_theme_style_override("grabber_area_highlight", style_box_empty); } } @@ -140,6 +143,30 @@ void ColorPicker::_update_controls() { scroll[3]->hide(); labels[3]->hide(); } + + switch (picker_type) { + case SHAPE_HSV_RECTANGLE: + wheel_edit->hide(); + w_edit->show(); + uv_edit->show(); + break; + case SHAPE_HSV_WHEEL: + wheel_edit->show(); + w_edit->hide(); + uv_edit->hide(); + + wheel->set_material(wheel_mat); + break; + case SHAPE_VHS_CIRCLE: + wheel_edit->show(); + w_edit->show(); + uv_edit->hide(); + + wheel->set_material(circle_mat); + break; + default: { + } + } } void ColorPicker::_set_pick_color(const Color &p_color, bool p_update_sliders) { @@ -264,6 +291,8 @@ void ColorPicker::_update_color(bool p_update_sliders) { for (int i = 0; i < 4; i++) { scroll[i]->update(); } + wheel->update(); + wheel_uv->update(); updating = false; } @@ -306,6 +335,18 @@ Color ColorPicker::get_pick_color() const { return color; } +void ColorPicker::set_picker_shape(PickerShapeType p_picker_type) { + ERR_FAIL_INDEX(p_picker_type, SHAPE_MAX); + picker_type = p_picker_type; + + _update_controls(); + _update_color(); +} + +ColorPicker::PickerShapeType ColorPicker::get_picker_shape() const { + return picker_type; +} + void ColorPicker::add_preset(const Color &p_color) { if (presets.find(p_color)) { presets.move_to_back(presets.find(p_color)); @@ -418,7 +459,7 @@ void ColorPicker::_update_text_value() { } void ColorPicker::_sample_draw() { - const Rect2 r = Rect2(Point2(), Size2(uv_edit->get_size().width, sample->get_size().height * 0.95)); + const Rect2 r = Rect2(Point2(), Size2(sample->get_size().width, sample->get_size().height * 0.95)); if (color.a < 1.0) { sample->draw_texture_rect(get_theme_icon("preset_bg", "ColorPicker"), r, true); @@ -438,42 +479,131 @@ void ColorPicker::_hsv_draw(int p_which, Control *c) { } if (p_which == 0) { Vector<Point2> points; - points.push_back(Vector2()); - points.push_back(Vector2(c->get_size().x, 0)); - points.push_back(c->get_size()); - points.push_back(Vector2(0, c->get_size().y)); Vector<Color> colors; - colors.push_back(Color(1, 1, 1, 1)); - colors.push_back(Color(1, 1, 1, 1)); - colors.push_back(Color(0, 0, 0, 1)); - colors.push_back(Color(0, 0, 0, 1)); - c->draw_polygon(points, colors); Vector<Color> colors2; Color col = color; + Vector2 center = c->get_size() / 2.0; + + switch (picker_type) { + case SHAPE_HSV_WHEEL: { + points.resize(4); + colors.resize(4); + colors2.resize(4); + real_t ring_radius_x = Math_SQRT12 * c->get_size().width * 0.42; + real_t ring_radius_y = Math_SQRT12 * c->get_size().height * 0.42; + + points.set(0, center - Vector2(ring_radius_x, ring_radius_y)); + points.set(1, center + Vector2(ring_radius_x, -ring_radius_y)); + points.set(2, center + Vector2(ring_radius_x, ring_radius_y)); + points.set(3, center + Vector2(-ring_radius_x, ring_radius_y)); + colors.set(0, Color(1, 1, 1, 1)); + colors.set(1, Color(1, 1, 1, 1)); + colors.set(2, Color(0, 0, 0, 1)); + colors.set(3, Color(0, 0, 0, 1)); + c->draw_polygon(points, colors); + + col.set_hsv(h, 1, 1); + col.a = 0; + colors2.set(0, col); + col.a = 1; + colors2.set(1, col); + col.set_hsv(h, 1, 0); + colors2.set(2, col); + col.a = 0; + colors2.set(3, col); + c->draw_polygon(points, colors2); + break; + } + case SHAPE_HSV_RECTANGLE: { + points.resize(4); + colors.resize(4); + colors2.resize(4); + points.set(0, Vector2()); + points.set(1, Vector2(c->get_size().x, 0)); + points.set(2, c->get_size()); + points.set(3, Vector2(0, c->get_size().y)); + colors.set(0, Color(1, 1, 1, 1)); + colors.set(1, Color(1, 1, 1, 1)); + colors.set(2, Color(0, 0, 0, 1)); + colors.set(3, Color(0, 0, 0, 1)); + c->draw_polygon(points, colors); + col = color; + col.set_hsv(h, 1, 1); + col.a = 0; + colors2.set(0, col); + col.a = 1; + colors2.set(1, col); + col.set_hsv(h, 1, 0); + colors2.set(2, col); + col.a = 0; + colors2.set(3, col); + c->draw_polygon(points, colors2); + break; + } + default: { + } + } + Ref<Texture2D> cursor = get_theme_icon("picker_cursor", "ColorPicker"); + int x; + int y; + if (picker_type == SHAPE_VHS_CIRCLE) { + x = center.x + (center.x * Math::cos(h * Math_TAU) * s) - (cursor->get_width() / 2); + y = center.y + (center.y * Math::sin(h * Math_TAU) * s) - (cursor->get_height() / 2); + } else { + real_t corner_x = (c == wheel_uv) ? center.x - Math_SQRT12 * c->get_size().width * 0.42 : 0; + real_t corner_y = (c == wheel_uv) ? center.y - Math_SQRT12 * c->get_size().height * 0.42 : 0; + + Size2 real_size(c->get_size().x - corner_x * 2, c->get_size().y - corner_y * 2); + x = CLAMP(real_size.x * s, 0, real_size.x) + corner_x - (cursor->get_width() / 2); + y = CLAMP(real_size.y - real_size.y * v, 0, real_size.y) + corner_y - (cursor->get_height() / 2); + } + c->draw_texture(cursor, Point2(x, y)); + col.set_hsv(h, 1, 1); - col.a = 0; - colors2.push_back(col); - col.a = 1; - colors2.push_back(col); - col.set_hsv(h, 1, 0); - colors2.push_back(col); - col.a = 0; - colors2.push_back(col); - c->draw_polygon(points, colors2); - int x = CLAMP(c->get_size().x * s, 0, c->get_size().x); - int y = CLAMP(c->get_size().y - c->get_size().y * v, 0, c->get_size().y); - col = color; - col.a = 1; - c->draw_line(Point2(x, 0), Point2(x, c->get_size().y), col.inverted()); - c->draw_line(Point2(0, y), Point2(c->get_size().x, y), col.inverted()); - c->draw_line(Point2(x, y), Point2(x, y), Color(1, 1, 1), 2); + if (picker_type == SHAPE_HSV_WHEEL) { + points.resize(4); + double h1 = h - (0.5 / 360); + double h2 = h + (0.5 / 360); + points.set(0, Point2(center.x + (center.x * Math::cos(h1 * Math_TAU)), center.y + (center.y * Math::sin(h1 * Math_TAU)))); + points.set(1, Point2(center.x + (center.x * Math::cos(h1 * Math_TAU) * 0.84), center.y + (center.y * Math::sin(h1 * Math_TAU) * 0.84))); + points.set(2, Point2(center.x + (center.x * Math::cos(h2 * Math_TAU)), center.y + (center.y * Math::sin(h2 * Math_TAU)))); + points.set(3, Point2(center.x + (center.x * Math::cos(h2 * Math_TAU) * 0.84), center.y + (center.y * Math::sin(h2 * Math_TAU) * 0.84))); + c->draw_multiline(points, col.inverted()); + } + } else if (p_which == 1) { - Ref<Texture2D> hue = get_theme_icon("color_hue", "ColorPicker"); - c->draw_texture_rect(hue, Rect2(Point2(), c->get_size())); - int y = c->get_size().y - c->get_size().y * (1.0 - h); - Color col = Color(); - col.set_hsv(h, 1, 1); - c->draw_line(Point2(0, y), Point2(c->get_size().x, y), col.inverted()); + if (picker_type == SHAPE_HSV_RECTANGLE) { + Ref<Texture2D> hue = get_theme_icon("color_hue", "ColorPicker"); + c->draw_texture_rect(hue, Rect2(Point2(), c->get_size())); + int y = c->get_size().y - c->get_size().y * (1.0 - h); + Color col; + col.set_hsv(h, 1, 1); + c->draw_line(Point2(0, y), Point2(c->get_size().x, y), col.inverted()); + } else if (picker_type == SHAPE_VHS_CIRCLE) { + Vector<Point2> points; + Vector<Color> colors; + Color col; + col.set_hsv(h, s, 1); + points.resize(4); + colors.resize(4); + points.set(0, Vector2()); + points.set(1, Vector2(c->get_size().x, 0)); + points.set(2, c->get_size()); + points.set(3, Vector2(0, c->get_size().y)); + colors.set(0, col); + colors.set(1, col); + colors.set(2, Color(0, 0, 0)); + colors.set(3, Color(0, 0, 0)); + c->draw_polygon(points, colors); + int y = c->get_size().y - c->get_size().y * CLAMP(v, 0, 1); + col.set_hsv(h, 1, v); + c->draw_line(Point2(0, y), Point2(c->get_size().x, y), col.inverted()); + } + } else if (p_which == 2) { + c->draw_rect(Rect2(Point2(), c->get_size()), Color(1, 1, 1)); + if (picker_type == SHAPE_VHS_CIRCLE) { + circle_mat->set_shader_param("v", v); + } } } @@ -540,16 +670,51 @@ void ColorPicker::_slider_draw(int p_which) { scroll[p_which]->draw_polygon(pos, col); } -void ColorPicker::_uv_input(const Ref<InputEvent> &p_event) { +void ColorPicker::_uv_input(const Ref<InputEvent> &p_event, Control *c) { Ref<InputEventMouseButton> bev = p_event; if (bev.is_valid()) { if (bev->is_pressed() && bev->get_button_index() == MOUSE_BUTTON_LEFT) { + Vector2 center = c->get_size() / 2.0; + if (picker_type == SHAPE_VHS_CIRCLE) { + real_t dist = center.distance_to(bev->get_position()); + + if (dist <= center.x) { + real_t rad = Math::atan2(bev->get_position().y - center.y, bev->get_position().x - center.x); + h = ((rad >= 0) ? rad : (Math_TAU + rad)) / Math_TAU; + s = CLAMP(dist / center.x, 0, 1); + } else { + return; + } + } else { + real_t corner_x = (c == wheel_uv) ? center.x - Math_SQRT12 * c->get_size().width * 0.42 : 0; + real_t corner_y = (c == wheel_uv) ? center.y - Math_SQRT12 * c->get_size().height * 0.42 : 0; + Size2 real_size(c->get_size().x - corner_x * 2, c->get_size().y - corner_y * 2); + + if (bev->get_position().x < corner_x || bev->get_position().x > c->get_size().x - corner_x || + bev->get_position().y < corner_y || bev->get_position().y > c->get_size().y - corner_y) { + { + real_t dist = center.distance_to(bev->get_position()); + + if (dist >= center.x * 0.84 && dist <= center.x) { + real_t rad = Math::atan2(bev->get_position().y - center.y, bev->get_position().x - center.x); + h = ((rad >= 0) ? rad : (Math_TAU + rad)) / Math_TAU; + spinning = true; + } else { + return; + } + } + } + + if (!spinning) { + real_t x = CLAMP(bev->get_position().x, corner_x, c->get_size().x - corner_x); + real_t y = CLAMP(bev->get_position().y, corner_x, c->get_size().y - corner_y); + + s = (x - c->get_position().x - corner_x) / real_size.x; + v = 1.0 - (y - c->get_position().y - corner_y) / real_size.y; + } + } changing_color = true; - float x = CLAMP((float)bev->get_position().x, 0, uv_edit->get_size().width); - float y = CLAMP((float)bev->get_position().y, 0, uv_edit->get_size().height); - s = x / uv_edit->get_size().width; - v = 1.0 - y / uv_edit->get_size().height; color.set_hsv(h, s, v, color.a); last_hsv = color; set_pick_color(color); @@ -560,8 +725,10 @@ void ColorPicker::_uv_input(const Ref<InputEvent> &p_event) { } else if (deferred_mode_enabled && !bev->is_pressed() && bev->get_button_index() == MOUSE_BUTTON_LEFT) { emit_signal("color_changed", color); changing_color = false; + spinning = false; } else { changing_color = false; + spinning = false; } } @@ -571,10 +738,30 @@ void ColorPicker::_uv_input(const Ref<InputEvent> &p_event) { if (!changing_color) { return; } - float x = CLAMP((float)mev->get_position().x, 0, uv_edit->get_size().width); - float y = CLAMP((float)mev->get_position().y, 0, uv_edit->get_size().height); - s = x / uv_edit->get_size().width; - v = 1.0 - y / uv_edit->get_size().height; + + Vector2 center = c->get_size() / 2.0; + if (picker_type == SHAPE_VHS_CIRCLE) { + real_t dist = center.distance_to(mev->get_position()); + real_t rad = Math::atan2(mev->get_position().y - center.y, mev->get_position().x - center.x); + h = ((rad >= 0) ? rad : (Math_TAU + rad)) / Math_TAU; + s = CLAMP(dist / center.x, 0, 1); + } else { + if (spinning) { + real_t rad = Math::atan2(mev->get_position().y - center.y, mev->get_position().x - center.x); + h = ((rad >= 0) ? rad : (Math_TAU + rad)) / Math_TAU; + } else { + real_t corner_x = (c == wheel_uv) ? center.x - Math_SQRT12 * c->get_size().width * 0.42 : 0; + real_t corner_y = (c == wheel_uv) ? center.y - Math_SQRT12 * c->get_size().height * 0.42 : 0; + Size2 real_size(c->get_size().x - corner_x * 2, c->get_size().y - corner_y * 2); + + real_t x = CLAMP(mev->get_position().x, corner_x, c->get_size().x - corner_x); + real_t y = CLAMP(mev->get_position().y, corner_x, c->get_size().y - corner_y); + + s = (x - corner_x) / real_size.x; + v = 1.0 - (y - corner_y) / real_size.y; + } + } + color.set_hsv(h, s, v, color.a); last_hsv = color; set_pick_color(color); @@ -592,7 +779,11 @@ void ColorPicker::_w_input(const Ref<InputEvent> &p_event) { if (bev->is_pressed() && bev->get_button_index() == MOUSE_BUTTON_LEFT) { changing_color = true; float y = CLAMP((float)bev->get_position().y, 0, w_edit->get_size().height); - h = y / w_edit->get_size().height; + if (picker_type == SHAPE_VHS_CIRCLE) { + v = 1.0 - (y / w_edit->get_size().height); + } else { + h = y / w_edit->get_size().height; + } } else { changing_color = false; } @@ -614,7 +805,11 @@ void ColorPicker::_w_input(const Ref<InputEvent> &p_event) { return; } float y = CLAMP((float)mev->get_position().y, 0, w_edit->get_size().height); - h = y / w_edit->get_size().height; + if (picker_type == SHAPE_VHS_CIRCLE) { + v = 1.0 - (y / w_edit->get_size().height); + } else { + h = y / w_edit->get_size().height; + } color.set_hsv(h, s, v, color.a); last_hsv = color; set_pick_color(color); @@ -682,7 +877,7 @@ void ColorPicker::_screen_input(const Ref<InputEvent> &p_event) { return; } - Ref<Image> img = r->get_texture()->get_data(); + Ref<Image> img = r->get_texture()->get_image(); if (img.is_valid() && !img->is_empty()) { Vector2 ofs = mev->get_global_position() - r->get_visible_rect().get_position(); Color c = img->get_pixel(ofs.x, r->get_visible_rect().size.height - ofs.y); @@ -798,18 +993,25 @@ void ColorPicker::_bind_methods() { 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("set_picker_shape", "picker"), &ColorPicker::set_picker_shape); + ClassDB::bind_method(D_METHOD("get_picker_shape"), &ColorPicker::get_picker_shape); 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, "hsv_mode"), "set_hsv_mode", "is_hsv_mode"); 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_PROPERTY(PropertyInfo(Variant::INT, "picker_shape", PROPERTY_HINT_ENUM, "HSV Rectangle,HSV Rectangle Wheel,VHS Circle"), "set_picker_shape", "get_picker_shape"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "presets_enabled"), "set_presets_enabled", "are_presets_enabled"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "presets_visible"), "set_presets_visible", "are_presets_visible"); 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"))); + + BIND_ENUM_CONSTANT(SHAPE_HSV_RECTANGLE); + BIND_ENUM_CONSTANT(SHAPE_HSV_WHEEL); + BIND_ENUM_CONSTANT(SHAPE_VHS_CIRCLE); } ColorPicker::ColorPicker() : @@ -818,36 +1020,25 @@ ColorPicker::ColorPicker() : 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", callable_mp(this, &ColorPicker::_uv_input)); + uv_edit->connect("gui_input", callable_mp(this, &ColorPicker::_uv_input), make_binds(uv_edit)); uv_edit->set_mouse_filter(MOUSE_FILTER_PASS); uv_edit->set_h_size_flags(SIZE_EXPAND_FILL); uv_edit->set_v_size_flags(SIZE_EXPAND_FILL); uv_edit->set_custom_minimum_size(Size2(get_theme_constant("sv_width"), get_theme_constant("sv_height"))); uv_edit->connect("draw", callable_mp(this, &ColorPicker::_hsv_draw), make_binds(0, uv_edit)); - w_edit = memnew(Control); - hb_edit->add_child(w_edit); - w_edit->set_custom_minimum_size(Size2(get_theme_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", callable_mp(this, &ColorPicker::_w_input)); - w_edit->connect("draw", callable_mp(this, &ColorPicker::_hsv_draw), make_binds(1, w_edit)); - HBoxContainer *hb_smpl = memnew(HBoxContainer); add_child(hb_smpl); - sample = memnew(TextureRect); hb_smpl->add_child(sample); sample->set_h_size_flags(SIZE_EXPAND_FILL); sample->connect("draw", callable_mp(this, &ColorPicker::_sample_draw)); - btn_pick = memnew(Button); btn_pick->set_flat(true); hb_smpl->add_child(btn_pick); btn_pick->set_toggle_mode(true); - btn_pick->set_tooltip(TTR("Pick a color from the editor window.")); + btn_pick->set_tooltip(RTR("Pick a color from the editor window.")); btn_pick->connect("pressed", callable_mp(this, &ColorPicker::_screen_pick_pressed)); VBoxContainer *vbl = memnew(VBoxContainer); @@ -887,27 +1078,20 @@ ColorPicker::ColorPicker() : vbr->add_child(hbc); } + labels[3]->set_text("A"); - scroll[3]->add_theme_icon_override("grabber", get_theme_icon("bar_arrow")); - scroll[3]->add_theme_icon_override("grabber_highlight", get_theme_icon("bar_arrow")); - scroll[3]->add_theme_style_override("slider", Ref<StyleBoxEmpty>(memnew(StyleBoxEmpty))); - scroll[3]->add_theme_style_override("grabber_area", Ref<StyleBoxEmpty>(memnew(StyleBoxEmpty))); - scroll[3]->add_theme_style_override("grabber_area_highlight", Ref<StyleBoxEmpty>(memnew(StyleBoxEmpty))); HBoxContainer *hhb = memnew(HBoxContainer); vbr->add_child(hhb); - btn_hsv = memnew(CheckButton); hhb->add_child(btn_hsv); - btn_hsv->set_text(TTR("HSV")); + btn_hsv->set_text(RTR("HSV")); btn_hsv->connect("toggled", callable_mp(this, &ColorPicker::set_hsv_mode)); - btn_raw = memnew(CheckButton); hhb->add_child(btn_raw); - btn_raw->set_text(TTR("Raw")); + btn_raw->set_text(RTR("Raw")); btn_raw->connect("toggled", callable_mp(this, &ColorPicker::set_raw_mode)); - text_type = memnew(Button); hhb->add_child(text_type); text_type->set_text("#"); text_type->set_tooltip(TTR("Switch between hexadecimal and code values.")); @@ -921,36 +1105,70 @@ ColorPicker::ColorPicker() : 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", callable_mp(this, &ColorPicker::_html_entered)); c_text->connect("focus_entered", callable_mp(this, &ColorPicker::_focus_enter)); c_text->connect("focus_exited", callable_mp(this, &ColorPicker::_html_focus_exit)); + wheel_edit->set_h_size_flags(SIZE_EXPAND_FILL); + wheel_edit->set_v_size_flags(SIZE_EXPAND_FILL); + wheel_edit->set_custom_minimum_size(Size2(get_theme_constant("sv_width"), get_theme_constant("sv_height"))); + hb_edit->add_child(wheel_edit); + + wheel_mat.instance(); + circle_mat.instance(); + + Ref<Shader> wheel_shader(memnew(Shader)); + wheel_shader->set_code("shader_type canvas_item;const float TAU=6.28318530718;void fragment(){float x=UV.x-0.5;float y=UV.y-0.5;float a=atan(y,x);x+=0.001;y+=0.001;float b=float(sqrt(x*x+y*y)<0.5)*float(sqrt(x*x+y*y)>0.42);x-=0.002;float b2=float(sqrt(x*x+y*y)<0.5)*float(sqrt(x*x+y*y)>0.42);y-=0.002;float b3=float(sqrt(x*x+y*y)<0.5)*float(sqrt(x*x+y*y)>0.42);x+=0.002;float b4=float(sqrt(x*x+y*y)<0.5)*float(sqrt(x*x+y*y)>0.42);COLOR=vec4(clamp((abs(fract(((a-TAU)/TAU)+vec3(3.0,2.0,1.0)/3.0)*6.0-3.0)-1.0),0.0,1.0),(b+b2+b3+b4)/4.00);}"); + wheel_mat->set_shader(wheel_shader); + + Ref<Shader> circle_shader(memnew(Shader)); + circle_shader->set_code("shader_type canvas_item;const float TAU=6.28318530718;uniform float v=1.0;void fragment(){float x=UV.x-0.5;float y=UV.y-0.5;float a=atan(y,x);x+=0.001;y+=0.001;float b=float(sqrt(x*x+y*y)<0.5);x-=0.002;float b2=float(sqrt(x*x+y*y)<0.5);y-=0.002;float b3=float(sqrt(x*x+y*y)<0.5);x+=0.002;float b4=float(sqrt(x*x+y*y)<0.5);COLOR=vec4(mix(vec3(1.0),clamp(abs(fract(vec3((a-TAU)/TAU)+vec3(1.0,2.0/3.0,1.0/3.0))*6.0-vec3(3.0))-vec3(1.0),0.0,1.0),((float(sqrt(x*x+y*y))*2.0))/1.0)*vec3(v),(b+b2+b3+b4)/4.00);}"); + circle_mat->set_shader(circle_shader); + + MarginContainer *wheel_margin(memnew(MarginContainer)); +#ifdef TOOLS_ENABLED + wheel_margin->add_theme_constant_override("margin_bottom", 8 * EDSCALE); +#else + wheel_margin->add_theme_constant_override("margin_bottom", 8); +#endif + wheel_edit->add_child(wheel_margin); + + wheel_margin->add_child(wheel); + wheel->set_mouse_filter(MOUSE_FILTER_PASS); + wheel->connect("draw", callable_mp(this, &ColorPicker::_hsv_draw), make_binds(2, wheel)); + + wheel_margin->add_child(wheel_uv); + wheel_uv->connect("gui_input", callable_mp(this, &ColorPicker::_uv_input), make_binds(wheel_uv)); + wheel_uv->connect("draw", callable_mp(this, &ColorPicker::_hsv_draw), make_binds(0, wheel_uv)); + + hb_edit->add_child(w_edit); + w_edit->set_custom_minimum_size(Size2(get_theme_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", callable_mp(this, &ColorPicker::_w_input)); + w_edit->connect("draw", callable_mp(this, &ColorPicker::_hsv_draw), make_binds(1, w_edit)); + + picker_type = SHAPE_HSV_RECTANGLE; _update_controls(); updating = false; set_pick_color(Color(1, 1, 1)); - preset_separator = memnew(HSeparator); add_child(preset_separator); - preset_container = memnew(HBoxContainer); preset_container->set_h_size_flags(SIZE_EXPAND_FILL); add_child(preset_container); - preset = memnew(TextureRect); preset_container->add_child(preset); preset->connect("gui_input", callable_mp(this, &ColorPicker::_preset_input)); preset->connect("draw", callable_mp(this, &ColorPicker::_update_presets)); - preset_container2 = memnew(HBoxContainer); preset_container2->set_h_size_flags(SIZE_EXPAND_FILL); add_child(preset_container2); - bt_add_preset = memnew(Button); preset_container2->add_child(bt_add_preset); - bt_add_preset->set_tooltip(TTR("Add current color as a preset.")); + bt_add_preset->set_tooltip(RTR("Add current color as a preset.")); bt_add_preset->connect("pressed", callable_mp(this, &ColorPicker::_add_preset_pressed)); } diff --git a/scene/gui/color_picker.h b/scene/gui/color_picker.h index 24e1746c41..a0d2aa95ca 100644 --- a/scene/gui/color_picker.h +++ b/scene/gui/color_picker.h @@ -31,6 +31,7 @@ #ifndef COLOR_PICKER_H #define COLOR_PICKER_H +#include "scene/gui/aspect_ratio_container.h" #include "scene/gui/box_container.h" #include "scene/gui/button.h" #include "scene/gui/check_button.h" @@ -45,29 +46,44 @@ class ColorPicker : public BoxContainer { GDCLASS(ColorPicker, BoxContainer); +public: + enum PickerShapeType { + SHAPE_HSV_RECTANGLE, + SHAPE_HSV_WHEEL, + SHAPE_VHS_CIRCLE, + + SHAPE_MAX + }; + private: Control *screen = nullptr; - Control *uv_edit; - Control *w_edit; - TextureRect *sample; - TextureRect *preset; - HBoxContainer *preset_container; - HBoxContainer *preset_container2; - HSeparator *preset_separator; - Button *bt_add_preset; + Control *uv_edit = memnew(Control); + Control *w_edit = memnew(Control); + AspectRatioContainer *wheel_edit = memnew(AspectRatioContainer); + Ref<ShaderMaterial> wheel_mat; + Ref<ShaderMaterial> circle_mat; + Control *wheel = memnew(Control); + Control *wheel_uv = memnew(Control); + TextureRect *sample = memnew(TextureRect); + TextureRect *preset = memnew(TextureRect); + HBoxContainer *preset_container = memnew(HBoxContainer); + HBoxContainer *preset_container2 = memnew(HBoxContainer); + HSeparator *preset_separator = memnew(HSeparator); + Button *bt_add_preset = memnew(Button); List<Color> presets; - Button *btn_pick; - CheckButton *btn_hsv; - CheckButton *btn_raw; + Button *btn_pick = memnew(Button); + CheckButton *btn_hsv = memnew(CheckButton); + CheckButton *btn_raw = memnew(CheckButton); HSlider *scroll[4]; SpinBox *values[4]; Label *labels[4]; - Button *text_type; - LineEdit *c_text; + Button *text_type = memnew(Button); + LineEdit *c_text = memnew(LineEdit); bool edit_alpha = true; Size2i ms; bool text_is_constructor = false; int presets_per_row = 0; + PickerShapeType picker_type = SHAPE_HSV_WHEEL; Color color; bool raw_mode_enabled = false; @@ -75,6 +91,7 @@ private: bool deferred_mode_enabled = false; bool updating = true; bool changing_color = false; + bool spinning = false; bool presets_enabled = true; bool presets_visible = true; float h = 0.0; @@ -93,7 +110,7 @@ private: void _hsv_draw(int p_which, Control *c); void _slider_draw(int p_which); - void _uv_input(const Ref<InputEvent> &p_event); + void _uv_input(const Ref<InputEvent> &p_event, Control *c); void _w_input(const Ref<InputEvent> &p_event); void _preset_input(const Ref<InputEvent> &p_event); void _screen_input(const Ref<InputEvent> &p_event); @@ -115,6 +132,9 @@ public: void set_pick_color(const Color &p_color); Color get_pick_color() const; + void set_picker_shape(PickerShapeType p_picker_type); + PickerShapeType get_picker_shape() const; + void add_preset(const Color &p_color); void erase_preset(const Color &p_color); PackedColorArray get_presets() const; @@ -175,4 +195,5 @@ public: ColorPickerButton(); }; +VARIANT_ENUM_CAST(ColorPicker::PickerShapeType); #endif // COLOR_PICKER_H diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp index 2e391adf2c..300201c0db 100644 --- a/scene/gui/control.cpp +++ b/scene/gui/control.cpp @@ -290,15 +290,11 @@ void Control::_update_minimum_size() { } Size2 minsize = get_combined_minimum_size(); - if (minsize.x > data.size_cache.x || - minsize.y > data.size_cache.y) { - _size_changed(); - } - data.updating_last_minimum_size = false; if (minsize != data.last_minimum_size) { data.last_minimum_size = minsize; + _size_changed(); emit_signal(SceneStringNames::get_singleton()->minimum_size_changed); } } @@ -327,7 +323,6 @@ bool Control::_get(const StringName &p_name, Variant &r_ret) const { r_ret = data.color_override.has(name) ? Variant(data.color_override[name]) : Variant(); } else if (sname.begins_with("custom_constants/")) { String name = sname.get_slicec('/', 1); - r_ret = data.constant_override.has(name) ? Variant(data.constant_override[name]) : Variant(); } else { return false; @@ -1780,53 +1775,38 @@ Rect2 Control::get_anchorable_rect() const { } void Control::add_theme_icon_override(const StringName &p_name, const Ref<Texture2D> &p_icon) { + ERR_FAIL_COND(!p_icon.is_valid()); + if (data.icon_override.has(p_name)) { data.icon_override[p_name]->disconnect("changed", callable_mp(this, &Control::_override_changed)); } - // clear if "null" is passed instead of an icon - if (p_icon.is_null()) { - data.icon_override.erase(p_name); - } else { - data.icon_override[p_name] = p_icon; - if (data.icon_override[p_name].is_valid()) { - data.icon_override[p_name]->connect("changed", callable_mp(this, &Control::_override_changed), Vector<Variant>(), CONNECT_REFERENCE_COUNTED); - } - } + data.icon_override[p_name] = p_icon; + data.icon_override[p_name]->connect("changed", callable_mp(this, &Control::_override_changed), Vector<Variant>(), CONNECT_REFERENCE_COUNTED); notification(NOTIFICATION_THEME_CHANGED); } void Control::add_theme_style_override(const StringName &p_name, const Ref<StyleBox> &p_style) { + ERR_FAIL_COND(!p_style.is_valid()); + if (data.style_override.has(p_name)) { data.style_override[p_name]->disconnect("changed", callable_mp(this, &Control::_override_changed)); } - // clear if "null" is passed instead of a style - if (p_style.is_null()) { - data.style_override.erase(p_name); - } else { - data.style_override[p_name] = p_style; - if (data.style_override[p_name].is_valid()) { - data.style_override[p_name]->connect("changed", callable_mp(this, &Control::_override_changed), Vector<Variant>(), CONNECT_REFERENCE_COUNTED); - } - } + data.style_override[p_name] = p_style; + data.style_override[p_name]->connect("changed", callable_mp(this, &Control::_override_changed), Vector<Variant>(), CONNECT_REFERENCE_COUNTED); notification(NOTIFICATION_THEME_CHANGED); } void Control::add_theme_font_override(const StringName &p_name, const Ref<Font> &p_font) { + ERR_FAIL_COND(!p_font.is_valid()); + if (data.font_override.has(p_name)) { data.font_override[p_name]->disconnect("changed", callable_mp(this, &Control::_override_changed)); } - // clear if "null" is passed instead of a font - if (p_font.is_null()) { - data.font_override.erase(p_name); - } else { - data.font_override[p_name] = p_font; - if (data.font_override[p_name].is_valid()) { - data.font_override[p_name]->connect("changed", callable_mp(this, &Control::_override_changed), Vector<Variant>(), CONNECT_REFERENCE_COUNTED); - } - } + data.font_override[p_name] = p_font; + data.font_override[p_name]->connect("changed", callable_mp(this, &Control::_override_changed), Vector<Variant>(), CONNECT_REFERENCE_COUNTED); notification(NOTIFICATION_THEME_CHANGED); } @@ -1845,6 +1825,48 @@ void Control::add_theme_constant_override(const StringName &p_name, int p_consta notification(NOTIFICATION_THEME_CHANGED); } +void Control::remove_theme_icon_override(const StringName &p_name) { + if (data.icon_override.has(p_name)) { + data.icon_override[p_name]->disconnect("changed", callable_mp(this, &Control::_override_changed)); + } + + data.icon_override.erase(p_name); + notification(NOTIFICATION_THEME_CHANGED); +} + +void Control::remove_theme_style_override(const StringName &p_name) { + if (data.style_override.has(p_name)) { + data.style_override[p_name]->disconnect("changed", callable_mp(this, &Control::_override_changed)); + } + + data.style_override.erase(p_name); + notification(NOTIFICATION_THEME_CHANGED); +} + +void Control::remove_theme_font_override(const StringName &p_name) { + if (data.font_override.has(p_name)) { + data.font_override[p_name]->disconnect("changed", callable_mp(this, &Control::_override_changed)); + } + + data.font_override.erase(p_name); + notification(NOTIFICATION_THEME_CHANGED); +} + +void Control::remove_theme_font_size_override(const StringName &p_name) { + data.font_size_override.erase(p_name); + notification(NOTIFICATION_THEME_CHANGED); +} + +void Control::remove_theme_color_override(const StringName &p_name) { + data.color_override.erase(p_name); + notification(NOTIFICATION_THEME_CHANGED); +} + +void Control::remove_theme_constant_override(const StringName &p_name) { + data.constant_override.erase(p_name); + notification(NOTIFICATION_THEME_CHANGED); +} + void Control::set_focus_mode(FocusMode p_focus_mode) { ERR_FAIL_INDEX((int)p_focus_mode, 3); @@ -2799,6 +2821,13 @@ void Control::_bind_methods() { ClassDB::bind_method(D_METHOD("add_theme_color_override", "name", "color"), &Control::add_theme_color_override); ClassDB::bind_method(D_METHOD("add_theme_constant_override", "name", "constant"), &Control::add_theme_constant_override); + ClassDB::bind_method(D_METHOD("remove_theme_icon_override", "name"), &Control::remove_theme_icon_override); + ClassDB::bind_method(D_METHOD("remove_theme_stylebox_override", "name"), &Control::remove_theme_style_override); + ClassDB::bind_method(D_METHOD("remove_theme_font_override", "name"), &Control::remove_theme_font_override); + ClassDB::bind_method(D_METHOD("remove_theme_font_size_override", "name"), &Control::remove_theme_font_size_override); + ClassDB::bind_method(D_METHOD("remove_theme_color_override", "name"), &Control::remove_theme_color_override); + ClassDB::bind_method(D_METHOD("remove_theme_constant_override", "name"), &Control::remove_theme_constant_override); + ClassDB::bind_method(D_METHOD("get_theme_icon", "name", "node_type"), &Control::get_theme_icon, DEFVAL("")); ClassDB::bind_method(D_METHOD("get_theme_stylebox", "name", "node_type"), &Control::get_theme_stylebox, DEFVAL("")); ClassDB::bind_method(D_METHOD("get_theme_font", "name", "node_type"), &Control::get_theme_font, DEFVAL("")); diff --git a/scene/gui/control.h b/scene/gui/control.h index a911d69c3f..184b2df6d3 100644 --- a/scene/gui/control.h +++ b/scene/gui/control.h @@ -459,6 +459,13 @@ public: void add_theme_color_override(const StringName &p_name, const Color &p_color); void add_theme_constant_override(const StringName &p_name, int p_constant); + void remove_theme_icon_override(const StringName &p_name); + void remove_theme_style_override(const StringName &p_name); + void remove_theme_font_override(const StringName &p_name); + void remove_theme_font_size_override(const StringName &p_name); + void remove_theme_color_override(const StringName &p_name); + void remove_theme_constant_override(const StringName &p_name); + Ref<Texture2D> get_theme_icon(const StringName &p_name, const StringName &p_node_type = StringName()) const; Ref<StyleBox> get_theme_stylebox(const StringName &p_name, const StringName &p_node_type = StringName()) const; Ref<Font> get_theme_font(const StringName &p_name, const StringName &p_node_type = StringName()) const; diff --git a/scene/gui/file_dialog.cpp b/scene/gui/file_dialog.cpp index 7ac8dbccca..5409b44b9e 100644 --- a/scene/gui/file_dialog.cpp +++ b/scene/gui/file_dialog.cpp @@ -96,6 +96,8 @@ void FileDialog::_notification(int p_what) { } void FileDialog::_unhandled_input(const Ref<InputEvent> &p_event) { + ERR_FAIL_COND(p_event.is_null()); + Ref<InputEventKey> k = p_event; if (k.is_valid() && has_focus()) { if (k->is_pressed()) { diff --git a/scene/gui/gradient_edit.cpp b/scene/gui/gradient_edit.cpp index 36b383f16c..e72709e847 100644 --- a/scene/gui/gradient_edit.cpp +++ b/scene/gui/gradient_edit.cpp @@ -92,6 +92,8 @@ GradientEdit::~GradientEdit() { } void GradientEdit::_gui_input(const Ref<InputEvent> &p_event) { + ERR_FAIL_COND(p_event.is_null()); + Ref<InputEventKey> k = p_event; if (k.is_valid() && k->is_pressed() && k->get_keycode() == KEY_DELETE && grabbed != -1) { diff --git a/scene/gui/graph_edit.cpp b/scene/gui/graph_edit.cpp index 315bef38e8..06c9cf1b63 100644 --- a/scene/gui/graph_edit.cpp +++ b/scene/gui/graph_edit.cpp @@ -154,6 +154,8 @@ Vector2 GraphEditMinimap::_convert_to_graph_position(const Vector2 &p_position) } void GraphEditMinimap::_gui_input(const Ref<InputEvent> &p_ev) { + ERR_FAIL_COND(p_ev.is_null()); + if (!ge->is_minimap_enabled()) { return; } @@ -1066,6 +1068,8 @@ void GraphEdit::set_selected(Node *p_child) { } void GraphEdit::_gui_input(const Ref<InputEvent> &p_ev) { + ERR_FAIL_COND(p_ev.is_null()); + Ref<InputEventMouseMotion> mm = p_ev; if (mm.is_valid() && (mm->get_button_mask() & MOUSE_BUTTON_MASK_MIDDLE || (mm->get_button_mask() & MOUSE_BUTTON_MASK_LEFT && Input::get_singleton()->is_key_pressed(KEY_SPACE)))) { h_scroll->set_value(h_scroll->get_value() - mm->get_relative().x); @@ -1123,7 +1127,7 @@ void GraphEdit::_gui_input(const Ref<InputEvent> &p_ev) { } gn->set_selected(box_selection_mode_additive); } else { - bool select = (previus_selected.find(gn) != nullptr); + bool select = (previous_selected.find(gn) != nullptr); if (gn->is_selected() && !select) { emit_signal("node_deselected", gn); } else if (!gn->is_selected() && select) { @@ -1148,7 +1152,7 @@ void GraphEdit::_gui_input(const Ref<InputEvent> &p_ev) { continue; } - bool select = (previus_selected.find(gn) != nullptr); + bool select = (previous_selected.find(gn) != nullptr); if (gn->is_selected() && !select) { emit_signal("node_deselected", gn); } else if (!gn->is_selected() && select) { @@ -1273,29 +1277,29 @@ void GraphEdit::_gui_input(const Ref<InputEvent> &p_ev) { box_selecting_from = b->get_position(); if (b->get_control()) { box_selection_mode_additive = true; - previus_selected.clear(); + previous_selected.clear(); for (int i = get_child_count() - 1; i >= 0; i--) { GraphNode *gn2 = Object::cast_to<GraphNode>(get_child(i)); if (!gn2 || !gn2->is_selected()) { continue; } - previus_selected.push_back(gn2); + previous_selected.push_back(gn2); } } else if (b->get_shift()) { box_selection_mode_additive = false; - previus_selected.clear(); + previous_selected.clear(); for (int i = get_child_count() - 1; i >= 0; i--) { GraphNode *gn2 = Object::cast_to<GraphNode>(get_child(i)); if (!gn2 || !gn2->is_selected()) { continue; } - previus_selected.push_back(gn2); + previous_selected.push_back(gn2); } } else { box_selection_mode_additive = true; - previus_selected.clear(); + previous_selected.clear(); for (int i = get_child_count() - 1; i >= 0; i--) { GraphNode *gn2 = Object::cast_to<GraphNode>(get_child(i)); if (!gn2) { @@ -1312,15 +1316,16 @@ void GraphEdit::_gui_input(const Ref<InputEvent> &p_ev) { if (b->get_button_index() == MOUSE_BUTTON_LEFT && !b->is_pressed() && box_selecting) { box_selecting = false; - previus_selected.clear(); + box_selecting_rect = Rect2(); + previous_selected.clear(); top_layer->update(); minimap->update(); } if (b->get_button_index() == MOUSE_BUTTON_WHEEL_UP && Input::get_singleton()->is_key_pressed(KEY_CONTROL)) { - set_zoom(zoom * ZOOM_SCALE); + set_zoom_custom(zoom * ZOOM_SCALE, b->get_position()); } else if (b->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN && Input::get_singleton()->is_key_pressed(KEY_CONTROL)) { - set_zoom(zoom / ZOOM_SCALE); + set_zoom_custom(zoom / ZOOM_SCALE, b->get_position()); } else if (b->get_button_index() == MOUSE_BUTTON_WHEEL_UP && !Input::get_singleton()->is_key_pressed(KEY_SHIFT)) { v_scroll->set_value(v_scroll->get_value() - v_scroll->get_page() * b->get_factor() / 8); } else if (b->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN && !Input::get_singleton()->is_key_pressed(KEY_SHIFT)) { diff --git a/scene/gui/graph_edit.h b/scene/gui/graph_edit.h index 8fdf975319..fa3b113705 100644 --- a/scene/gui/graph_edit.h +++ b/scene/gui/graph_edit.h @@ -150,7 +150,7 @@ private: Point2 box_selecting_from; Point2 box_selecting_to; Rect2 box_selecting_rect; - List<GraphNode *> previus_selected; + List<GraphNode *> previous_selected; bool setting_scroll_ofs = false; bool right_disconnects = false; diff --git a/scene/gui/graph_node.cpp b/scene/gui/graph_node.cpp index 8eba473d57..7d5c53effe 100644 --- a/scene/gui/graph_node.cpp +++ b/scene/gui/graph_node.cpp @@ -804,6 +804,8 @@ Color GraphNode::get_connection_output_color(int p_idx) { } void GraphNode::_gui_input(const Ref<InputEvent> &p_ev) { + ERR_FAIL_COND(p_ev.is_null()); + Ref<InputEventMouseButton> mb = p_ev; if (mb.is_valid()) { ERR_FAIL_COND_MSG(get_parent_control() == nullptr, "GraphNode must be the child of a GraphEdit node."); diff --git a/scene/gui/item_list.cpp b/scene/gui/item_list.cpp index 482560d29d..86d070f9b1 100644 --- a/scene/gui/item_list.cpp +++ b/scene/gui/item_list.cpp @@ -530,6 +530,8 @@ Size2 ItemList::Item::get_icon_size() const { } void ItemList::_gui_input(const Ref<InputEvent> &p_event) { + ERR_FAIL_COND(p_event.is_null()); + double prev_scroll = scroll_bar->get_value(); Ref<InputEventMouseMotion> mm = p_event; diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp index d1cd73c803..2d8eb3191c 100644 --- a/scene/gui/line_edit.cpp +++ b/scene/gui/line_edit.cpp @@ -215,6 +215,8 @@ void LineEdit::_delete(bool p_word, bool p_all_to_right) { } void LineEdit::_gui_input(Ref<InputEvent> p_event) { + ERR_FAIL_COND(p_event.is_null()); + Ref<InputEventMouseButton> b = p_event; if (b.is_valid()) { diff --git a/scene/gui/menu_button.cpp b/scene/gui/menu_button.cpp index 5acc7e808a..1e9baa77fc 100644 --- a/scene/gui/menu_button.cpp +++ b/scene/gui/menu_button.cpp @@ -34,6 +34,8 @@ #include "scene/main/window.h" void MenuButton::_unhandled_key_input(Ref<InputEvent> p_event) { + ERR_FAIL_COND(p_event.is_null()); + if (!_is_focus_owner_in_shorcut_context()) { return; } diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp index bfbd46a9f0..44df8eafdc 100644 --- a/scene/gui/popup_menu.cpp +++ b/scene/gui/popup_menu.cpp @@ -252,6 +252,8 @@ void PopupMenu::_submenu_timeout() { } void PopupMenu::_gui_input(const Ref<InputEvent> &p_event) { + ERR_FAIL_COND(p_event.is_null()); + if (p_event->is_action("ui_down") && p_event->is_pressed()) { int search_from = mouse_over + 1; if (search_from >= items.size()) { diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp index 13b57ece6c..c763ae6bd6 100644 --- a/scene/gui/rich_text_label.cpp +++ b/scene/gui/rich_text_label.cpp @@ -760,7 +760,7 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o //draw_rect(Rect2(p_ofs + off, TS->shaped_text_get_size(rid)), Color(1,0,0), false, 2); //DEBUG_RECTS - off.y += TS->shaped_text_get_ascent(rid); + off.y += TS->shaped_text_get_ascent(rid) + l.text_buf->get_spacing_top(); // Draw inlined objects. Array objects = TS->shaped_text_get_objects(rid); for (int i = 0; i < objects.size(); i++) { @@ -1079,7 +1079,7 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o off.x += glyphs[i].advance; } } - off.y += TS->shaped_text_get_descent(rid); + off.y += TS->shaped_text_get_descent(rid) + l.text_buf->get_spacing_bottom(); } return line_count; @@ -1174,7 +1174,7 @@ float RichTextLabel::_find_click_in_line(ItemFrame *p_frame, int p_line, const V } break; } - off.y += TS->shaped_text_get_ascent(rid); + off.y += TS->shaped_text_get_ascent(rid) + l.text_buf->get_spacing_top(); Array objects = TS->shaped_text_get_objects(rid); for (int i = 0; i < objects.size(); i++) { @@ -1238,7 +1238,7 @@ float RichTextLabel::_find_click_in_line(ItemFrame *p_frame, int p_line, const V if (rect.has_point(p_click) && !table_hit) { char_pos = TS->shaped_text_hit_test_position(rid, p_click.x - rect.position.x); } - off.y += TS->shaped_text_get_descent(rid); + off.y += TS->shaped_text_get_descent(rid) + l.text_buf->get_spacing_bottom(); } if (char_pos >= 0) { @@ -1469,6 +1469,8 @@ Control::CursorShape RichTextLabel::get_cursor_shape(const Point2 &p_pos) const } void RichTextLabel::_gui_input(Ref<InputEvent> p_event) { + ERR_FAIL_COND(p_event.is_null()); + Ref<InputEventMouseButton> b = p_event; if (b.is_valid()) { @@ -3756,7 +3758,9 @@ void RichTextLabel::set_effects(const Vector<Variant> &effects) { custom_effects.push_back(effect); } - parse_bbcode(bbcode); + if ((bbcode != "") && use_bbcode) { + parse_bbcode(bbcode); + } } Vector<Variant> RichTextLabel::get_effects() { @@ -3773,7 +3777,9 @@ void RichTextLabel::install_effect(const Variant effect) { if (rteffect.is_valid()) { custom_effects.push_back(effect); - parse_bbcode(bbcode); + if ((bbcode != "") && use_bbcode) { + parse_bbcode(bbcode); + } } } @@ -3999,14 +4005,16 @@ void RichTextLabel::set_fixed_size_to_width(int p_width) { } Size2 RichTextLabel::get_minimum_size() const { - Size2 size(0, 0); + Ref<StyleBox> style = get_theme_stylebox("normal"); + Size2 size = style->get_minimum_size(); + if (fixed_width != -1) { - size.x = fixed_width; + size.x += fixed_width; } if (fixed_width != -1 || fit_content_height) { const_cast<RichTextLabel *>(this)->_validate_line_caches(main); - size.y = get_content_height(); + size.y += get_content_height(); } return size; diff --git a/scene/gui/scroll_bar.cpp b/scene/gui/scroll_bar.cpp index a56bf15507..62276e3af0 100644 --- a/scene/gui/scroll_bar.cpp +++ b/scene/gui/scroll_bar.cpp @@ -42,6 +42,8 @@ void ScrollBar::set_can_focus_by_default(bool p_can_focus) { } void ScrollBar::_gui_input(Ref<InputEvent> p_event) { + ERR_FAIL_COND(p_event.is_null()); + Ref<InputEventMouseMotion> m = p_event; if (!m.is_valid() || drag.active) { emit_signal("scrolling"); diff --git a/scene/gui/scroll_container.cpp b/scene/gui/scroll_container.cpp index 90a528482f..757a0841ea 100644 --- a/scene/gui/scroll_container.cpp +++ b/scene/gui/scroll_container.cpp @@ -88,6 +88,8 @@ void ScrollContainer::_cancel_drag() { } void ScrollContainer::_gui_input(const Ref<InputEvent> &p_gui_input) { + ERR_FAIL_COND(p_gui_input.is_null()); + double prev_v_scroll = v_scroll->get_value(); double prev_h_scroll = h_scroll->get_value(); diff --git a/scene/gui/slider.cpp b/scene/gui/slider.cpp index 7f1d19a87a..a407ef21cb 100644 --- a/scene/gui/slider.cpp +++ b/scene/gui/slider.cpp @@ -46,6 +46,8 @@ Size2 Slider::get_minimum_size() const { } void Slider::_gui_input(Ref<InputEvent> p_event) { + ERR_FAIL_COND(p_event.is_null()); + if (!editable) { return; } diff --git a/scene/gui/spin_box.cpp b/scene/gui/spin_box.cpp index 50b25fa7b4..9dc2afdb2d 100644 --- a/scene/gui/spin_box.cpp +++ b/scene/gui/spin_box.cpp @@ -100,6 +100,8 @@ void SpinBox::_release_mouse() { } void SpinBox::_gui_input(const Ref<InputEvent> &p_event) { + ERR_FAIL_COND(p_event.is_null()); + if (!is_editable()) { return; } diff --git a/scene/gui/split_container.cpp b/scene/gui/split_container.cpp index c80120f87d..13ff2c5b86 100644 --- a/scene/gui/split_container.cpp +++ b/scene/gui/split_container.cpp @@ -207,6 +207,8 @@ void SplitContainer::_notification(int p_what) { } void SplitContainer::_gui_input(const Ref<InputEvent> &p_event) { + ERR_FAIL_COND(p_event.is_null()); + if (collapsed || !_getch(0) || !_getch(1) || dragger_visibility != DRAGGER_VISIBLE) { return; } diff --git a/scene/gui/subviewport_container.cpp b/scene/gui/subviewport_container.cpp index 8ffdd269a4..bfc7e29f9c 100644 --- a/scene/gui/subviewport_container.cpp +++ b/scene/gui/subviewport_container.cpp @@ -140,6 +140,8 @@ void SubViewportContainer::_notification(int p_what) { } void SubViewportContainer::_input(const Ref<InputEvent> &p_event) { + ERR_FAIL_COND(p_event.is_null()); + if (Engine::get_singleton()->is_editor_hint()) { return; } @@ -165,6 +167,8 @@ void SubViewportContainer::_input(const Ref<InputEvent> &p_event) { } void SubViewportContainer::_unhandled_input(const Ref<InputEvent> &p_event) { + ERR_FAIL_COND(p_event.is_null()); + if (Engine::get_singleton()->is_editor_hint()) { return; } diff --git a/scene/gui/tab_container.cpp b/scene/gui/tab_container.cpp index 1e31f9e206..ff9dafa0f9 100644 --- a/scene/gui/tab_container.cpp +++ b/scene/gui/tab_container.cpp @@ -72,6 +72,8 @@ int TabContainer::_get_top_margin() const { } void TabContainer::_gui_input(const Ref<InputEvent> &p_event) { + ERR_FAIL_COND(p_event.is_null()); + Ref<InputEventMouseButton> mb = p_event; Popup *popup = get_popup(); diff --git a/scene/gui/tabs.cpp b/scene/gui/tabs.cpp index 4a7285a154..6cbc5890ce 100644 --- a/scene/gui/tabs.cpp +++ b/scene/gui/tabs.cpp @@ -83,11 +83,16 @@ Size2 Tabs::get_minimum_size() const { } } - ms.width = 0; //TODO: should make this optional + if (clip_tabs) { + ms.width = 0; + } + return ms; } void Tabs::_gui_input(const Ref<InputEvent> &p_event) { + ERR_FAIL_COND(p_event.is_null()); + Ref<InputEventMouseMotion> mm = p_event; if (mm.is_valid()) { @@ -105,10 +110,10 @@ void Tabs::_gui_input(const Ref<InputEvent> &p_event) { highlight_arrow = 0; } } else { - int limit = get_size().width - incr->get_width() - decr->get_width(); - if (pos.x > limit + decr->get_width()) { + int limit_minus_buttons = get_size().width - incr->get_width() - decr->get_width(); + if (pos.x > limit_minus_buttons + decr->get_width()) { highlight_arrow = 1; - } else if (pos.x > limit) { + } else if (pos.x > limit_minus_buttons) { highlight_arrow = 0; } } @@ -305,7 +310,8 @@ void Tabs::_notification(int p_what) { Ref<Texture2D> incr_hl = get_theme_icon("increment_highlight"); Ref<Texture2D> decr_hl = get_theme_icon("decrement_highlight"); - int limit = get_size().width - incr->get_size().width - decr->get_size().width; + int limit = get_size().width; + int limit_minus_buttons = get_size().width - incr->get_width() - decr->get_width(); missing_right = false; @@ -328,7 +334,8 @@ void Tabs::_notification(int p_what) { col = font_unselected_color; } - if (w + lsize > limit) { + int new_width = w + lsize; + if (new_width > limit || (i < tabs.size() - 1 && new_width > limit_minus_buttons)) { // For the last tab, we accept if the tab covers the buttons. max_drawn_tab = i - 1; missing_right = true; break; @@ -459,15 +466,15 @@ void Tabs::_notification(int p_what) { } } else { if (offset > 0) { - draw_texture(highlight_arrow == 0 ? decr_hl : decr, Point2(limit, vofs)); + draw_texture(highlight_arrow == 0 ? decr_hl : decr, Point2(limit_minus_buttons, vofs)); } else { - draw_texture(decr, Point2(limit, vofs), Color(1, 1, 1, 0.5)); + draw_texture(decr, Point2(limit_minus_buttons, vofs), Color(1, 1, 1, 0.5)); } if (missing_right) { - draw_texture(highlight_arrow == 1 ? incr_hl : incr, Point2(limit + decr->get_size().width, vofs)); + draw_texture(highlight_arrow == 1 ? incr_hl : incr, Point2(limit_minus_buttons + decr->get_size().width, vofs)); } else { - draw_texture(incr, Point2(limit + decr->get_size().width, vofs), Color(1, 1, 1, 0.5)); + draw_texture(incr, Point2(limit_minus_buttons + decr->get_size().width, vofs), Color(1, 1, 1, 0.5)); } } @@ -666,7 +673,7 @@ void Tabs::_update_cache() { Ref<StyleBox> tab_selected = get_theme_stylebox("tab_selected"); Ref<Texture2D> incr = get_theme_icon("increment"); Ref<Texture2D> decr = get_theme_icon("decrement"); - int limit = get_size().width - incr->get_width() - decr->get_width(); + int limit_minus_buttons = get_size().width - incr->get_width() - decr->get_width(); int w = 0; int mw = 0; @@ -686,7 +693,7 @@ void Tabs::_update_cache() { } int m_width = min_width; if (count_resize > 0) { - m_width = MAX((limit - size_fixed) / count_resize, min_width); + m_width = MAX((limit_minus_buttons - size_fixed) / count_resize, min_width); } for (int i = offset; i < tabs.size(); i++) { Ref<StyleBox> sb; @@ -699,7 +706,7 @@ void Tabs::_update_cache() { } int lsize = tabs[i].size_cache; int slen = tabs[i].size_text; - if (min_width > 0 && mw > limit && i != current) { + if (min_width > 0 && mw > limit_minus_buttons && i != current) { if (lsize > m_width) { slen = m_width - (sb->get_margin(SIDE_LEFT) + sb->get_margin(SIDE_RIGHT)); if (tabs[i].icon.is_valid()) { @@ -909,6 +916,19 @@ Tabs::TabAlign Tabs::get_tab_align() const { return tab_align; } +void Tabs::set_clip_tabs(bool p_clip_tabs) { + if (clip_tabs == p_clip_tabs) { + return; + } + clip_tabs = p_clip_tabs; + update(); + minimum_size_changed(); +} + +bool Tabs::get_clip_tabs() const { + return clip_tabs; +} + void Tabs::move_tab(int from, int to) { if (from == to) { return; @@ -975,7 +995,8 @@ void Tabs::_ensure_no_over_offset() { Ref<Texture2D> incr = get_theme_icon("increment"); Ref<Texture2D> decr = get_theme_icon("decrement"); - int limit = get_size().width - incr->get_width() - decr->get_width(); + int limit = get_size().width; + int limit_minus_buttons = get_size().width - incr->get_width() - decr->get_width(); while (offset > 0) { int total_w = 0; @@ -983,7 +1004,7 @@ void Tabs::_ensure_no_over_offset() { total_w += tabs[i].size_cache; } - if (total_w < limit) { + if ((buttons_visible && total_w < limit_minus_buttons) || total_w < limit) { // For the last tab, we accept if the tab covers the buttons. offset--; update(); } else { @@ -1014,9 +1035,12 @@ void Tabs::ensure_tab_visible(int p_idx) { int prev_offset = offset; Ref<Texture2D> incr = get_theme_icon("increment"); Ref<Texture2D> decr = get_theme_icon("decrement"); - int limit = get_size().width - incr->get_width() - decr->get_width(); + int limit = get_size().width; + int limit_minus_buttons = get_size().width - incr->get_width() - decr->get_width(); + for (int i = offset; i <= p_idx; i++) { - if (tabs[i].ofs_cache + tabs[i].size_cache > limit) { + int total_w = tabs[i].ofs_cache + tabs[i].size_cache; + if (total_w > limit || (buttons_visible && total_w > limit_minus_buttons)) { offset++; } } @@ -1105,6 +1129,8 @@ void Tabs::_bind_methods() { ClassDB::bind_method(D_METHOD("add_tab", "title", "icon"), &Tabs::add_tab, DEFVAL(""), DEFVAL(Ref<Texture2D>())); ClassDB::bind_method(D_METHOD("set_tab_align", "align"), &Tabs::set_tab_align); ClassDB::bind_method(D_METHOD("get_tab_align"), &Tabs::get_tab_align); + ClassDB::bind_method(D_METHOD("set_clip_tabs", "clip_tabs"), &Tabs::set_clip_tabs); + ClassDB::bind_method(D_METHOD("get_clip_tabs"), &Tabs::get_clip_tabs); ClassDB::bind_method(D_METHOD("get_tab_offset"), &Tabs::get_tab_offset); ClassDB::bind_method(D_METHOD("get_offset_buttons_visible"), &Tabs::get_offset_buttons_visible); ClassDB::bind_method(D_METHOD("ensure_tab_visible", "idx"), &Tabs::ensure_tab_visible); @@ -1131,6 +1157,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_PROPERTY(PropertyInfo(Variant::BOOL, "clip_tabs"), "set_clip_tabs", "get_clip_tabs"); 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 86877f4d80..61c9a5d96a 100644 --- a/scene/gui/tabs.h +++ b/scene/gui/tabs.h @@ -85,6 +85,7 @@ private: int previous = 0; int _get_top_margin() const; TabAlign tab_align = ALIGN_CENTER; + bool clip_tabs = true; int rb_hover = -1; bool rb_pressing = false; @@ -148,6 +149,9 @@ public: void set_tab_align(TabAlign p_align); TabAlign get_tab_align() const; + void set_clip_tabs(bool p_clip_tabs); + bool get_clip_tabs() const; + void move_tab(int from, int to); void set_tab_close_display_policy(CloseButtonDisplayPolicy p_policy); diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index 74c530f1b0..f54ab004c6 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -2854,6 +2854,8 @@ void TextEdit::_get_minimap_mouse_row(const Point2i &p_mouse, int &r_row) const } void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) { + ERR_FAIL_COND(p_gui_input.is_null()); + double prev_v_scroll = v_scroll->get_value(); double prev_h_scroll = h_scroll->get_value(); diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp index abfea241f3..73fd9dbcd7 100644 --- a/scene/gui/tree.cpp +++ b/scene/gui/tree.cpp @@ -2402,6 +2402,8 @@ void Tree::_go_down() { } void Tree::_gui_input(Ref<InputEvent> p_event) { + ERR_FAIL_COND(p_event.is_null()); + Ref<InputEventKey> k = p_event; bool is_command = k.is_valid() && k->get_command(); |