diff options
Diffstat (limited to 'scene/gui')
-rw-r--r-- | scene/gui/color_picker.cpp | 47 | ||||
-rw-r--r-- | scene/gui/container.cpp | 18 | ||||
-rw-r--r-- | scene/gui/control.cpp | 108 | ||||
-rw-r--r-- | scene/gui/control.h | 24 | ||||
-rw-r--r-- | scene/gui/graph_edit.cpp | 20 | ||||
-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 | 46 | ||||
-rw-r--r-- | scene/gui/item_list.h | 3 | ||||
-rw-r--r-- | scene/gui/label.cpp | 7 | ||||
-rw-r--r-- | scene/gui/rich_text_label.cpp | 37 | ||||
-rw-r--r-- | scene/gui/rich_text_label.h | 6 | ||||
-rw-r--r-- | scene/gui/slider.cpp | 22 | ||||
-rw-r--r-- | scene/gui/slider.h | 4 | ||||
-rw-r--r-- | scene/gui/split_container.cpp | 22 | ||||
-rw-r--r-- | scene/gui/tabs.cpp | 38 | ||||
-rw-r--r-- | scene/gui/tabs.h | 7 | ||||
-rw-r--r-- | scene/gui/tree.cpp | 153 | ||||
-rw-r--r-- | scene/gui/tree.h | 22 |
19 files changed, 500 insertions, 88 deletions
diff --git a/scene/gui/color_picker.cpp b/scene/gui/color_picker.cpp index ee6af21dbd..9ef340edbc 100644 --- a/scene/gui/color_picker.cpp +++ b/scene/gui/color_picker.cpp @@ -122,9 +122,6 @@ void ColorPicker::_value_changed(double) { } set_pick_color(color); - - _update_text_value(); - emit_signal("color_changed", color); } @@ -257,7 +254,7 @@ void ColorPicker::_update_text_value() { } void ColorPicker::_sample_draw() { - sample->draw_rect(Rect2(Point2(), Size2(256, 20)), color); + sample->draw_rect(Rect2(Point2(), Size2(uv_edit->get_size().width, 20)), color); } void ColorPicker::_hsv_draw(int p_wich, Control *c) { @@ -277,12 +274,12 @@ void ColorPicker::_hsv_draw(int p_wich, Control *c) { c->draw_polygon(points, colors); Vector<Color> colors2; Color col = color; - col.set_hsv(color.get_h(), 1, 1); + col.set_hsv(h, 1, 1); col.a = 0; colors2.push_back(col); col.a = 1; colors2.push_back(col); - col.set_hsv(color.get_h(), 1, 0); + col.set_hsv(h, 1, 0); colors2.push_back(col); col.a = 0; colors2.push_back(col); @@ -311,10 +308,10 @@ void ColorPicker::_uv_input(const Ref<InputEvent> &ev) { if (bev.is_valid()) { if (bev->is_pressed() && bev->get_button_index() == BUTTON_LEFT) { changing_color = true; - float x = CLAMP((float)bev->get_position().x, 0, 256); - float y = CLAMP((float)bev->get_position().y, 0, 256); - s = x / 256; - v = 1.0 - y / 256.0; + 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); @@ -330,10 +327,10 @@ void ColorPicker::_uv_input(const Ref<InputEvent> &ev) { if (mev.is_valid()) { if (!changing_color) return; - float x = CLAMP((float)mev->get_position().x, 0, 256); - float y = CLAMP((float)mev->get_position().y, 0, 256); - s = x / 256; - v = 1.0 - y / 256.0; + 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; color.set_hsv(h, s, v, color.a); last_hsv = color; set_pick_color(color); @@ -350,8 +347,8 @@ void ColorPicker::_w_input(const Ref<InputEvent> &ev) { if (bev->is_pressed() && bev->get_button_index() == BUTTON_LEFT) { changing_color = true; - h = 1 - (256.0 - (float)bev->get_position().y) / 256.0; - + float y = CLAMP((float)bev->get_position().y, 0, w_edit->get_size().height); + h = y / w_edit->get_size().height; } else { changing_color = false; } @@ -368,9 +365,8 @@ void ColorPicker::_w_input(const Ref<InputEvent> &ev) { if (!changing_color) return; - float y = CLAMP((float)mev->get_position().y, 0, 256); - //h = 1.0 - y / 256.0; - h = y / 256.0; + float y = CLAMP((float)mev->get_position().y, 0, w_edit->get_size().height); + h = y / w_edit->get_size().height; color.set_hsv(h, s, v, color.a); last_hsv = color; set_pick_color(color); @@ -508,12 +504,14 @@ ColorPicker::ColorPicker() add_child(hb_smpl); HBoxContainer *hb_edit = memnew(HBoxContainer); + hb_edit->set_v_size_flags(SIZE_EXPAND_FILL); uv_edit = memnew(Control); uv_edit->connect("gui_input", this, "_uv_input"); uv_edit->set_mouse_filter(MOUSE_FILTER_PASS); - uv_edit->set_custom_minimum_size(Size2(256, 256)); + uv_edit->set_h_size_flags(SIZE_EXPAND_FILL); + uv_edit->set_v_size_flags(SIZE_EXPAND_FILL); Vector<Variant> args = Vector<Variant>(); args.push_back(0); args.push_back(uv_edit); @@ -523,7 +521,9 @@ ColorPicker::ColorPicker() w_edit = memnew(Control); //w_edit->set_ignore_mouse(false); - w_edit->set_custom_minimum_size(Size2(30, 256)); + w_edit->set_custom_minimum_size(Size2(30, 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"); args.clear(); args.push_back(1); @@ -549,6 +549,7 @@ ColorPicker::ColorPicker() HBoxContainer *hbc = memnew(HBoxContainer); labels[i] = memnew(Label(lt[i])); + labels[i]->set_custom_minimum_size(Size2(10, 0)); hbc->add_child(labels[i]); scroll[i] = memnew(HSlider); @@ -570,7 +571,7 @@ ColorPicker::ColorPicker() HBoxContainer *hhb = memnew(HBoxContainer); btn_mode = memnew(CheckButton); - btn_mode->set_text("RAW 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); @@ -601,7 +602,7 @@ ColorPicker::ColorPicker() bt_add_preset = memnew(Button); bt_add_preset->set_icon(get_icon("add_preset")); - bt_add_preset->set_tooltip("Add current color as a preset"); + 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); } diff --git a/scene/gui/container.cpp b/scene/gui/container.cpp index 92bb5d43a7..2a96f8260c 100644 --- a/scene/gui/container.cpp +++ b/scene/gui/container.cpp @@ -95,13 +95,25 @@ void Container::fit_child_in_rect(Control *p_child, const Rect2 &p_rect) { Rect2 r = p_rect; if (!(p_child->get_h_size_flags() & SIZE_FILL)) { - r.size.x = minsize.x; - r.position.x += Math::floor((p_rect.size.x - minsize.x) / 2); + r.size.x = minsize.width; + if (p_child->get_h_size_flags() & SIZE_SHRINK_END) { + r.position.x += p_rect.size.width - minsize.width; + } else if (p_child->get_h_size_flags() & SIZE_SHRINK_CENTER) { + r.position.x += Math::floor((p_rect.size.x - minsize.width) / 2); + } else { + r.position.x += 0; + } } if (!(p_child->get_v_size_flags() & SIZE_FILL)) { r.size.y = minsize.y; - r.position.y += Math::floor((p_rect.size.y - minsize.y) / 2); + if (p_child->get_v_size_flags() & SIZE_SHRINK_END) { + r.position.y += p_rect.size.height - minsize.height; + } else if (p_child->get_v_size_flags() & SIZE_SHRINK_CENTER) { + r.position.y += Math::floor((p_rect.size.y - minsize.height) / 2); + } else { + r.position.y += 0; + } } for (int i = 0; i < 4; i++) diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp index 45485b768e..e9e299ffc5 100644 --- a/scene/gui/control.cpp +++ b/scene/gui/control.cpp @@ -90,11 +90,22 @@ Size2 Control::edit_get_minimum_size() const { return get_combined_minimum_size(); } +Transform2D Control::_get_internal_transform() const { + + Transform2D rot_scale; + rot_scale.set_rotation_and_scale(data.rotation, data.scale); + Transform2D offset; + offset.set_origin(-data.pivot_offset); + + return offset.affine_inverse() * (rot_scale * offset); +} void Control::edit_set_rect(const Rect2 &p_edit_rect) { - Transform2D postxf; - postxf.set_rotation_and_scale(data.rotation, data.scale); - Vector2 new_pos = postxf.xform(p_edit_rect.position); + Transform2D xform = _get_internal_transform(); + + // xform[2] += get_position(); + + Vector2 new_pos = xform.basis_xform(p_edit_rect.position); Vector2 pos = get_position() + new_pos; @@ -353,8 +364,9 @@ void Control::remove_child_notify(Node *p_child) { void Control::_update_canvas_item_transform() { - Transform2D xform = Transform2D(data.rotation, get_position()); - xform.scale_basis(data.scale); + Transform2D xform = _get_internal_transform(); + xform[2] += get_position(); + VisualServer::get_singleton()->canvas_item_set_transform(get_canvas_item(), xform); } @@ -1217,12 +1229,28 @@ void Control::_size_changed() { } } - Point2 new_pos_cache = Point2(margin_pos[0], margin_pos[1]).floor(); - Size2 new_size_cache = Point2(margin_pos[2], margin_pos[3]).floor() - new_pos_cache; + Point2 new_pos_cache = Point2(margin_pos[0], margin_pos[1]); + Size2 new_size_cache = Point2(margin_pos[2], margin_pos[3]) - new_pos_cache; + Size2 minimum_size = get_combined_minimum_size(); - new_size_cache.x = MAX(minimum_size.x, new_size_cache.x); - new_size_cache.y = MAX(minimum_size.y, new_size_cache.y); + if (data.h_grow == GROW_DIRECTION_BEGIN) { + if (minimum_size.width > new_size_cache.width) { + new_pos_cache.x = new_pos_cache.x + new_size_cache.width - minimum_size.width; + new_size_cache.width = minimum_size.width; + } + } else { + new_size_cache.width = MAX(minimum_size.width, new_size_cache.width); + } + + if (data.v_grow == GROW_DIRECTION_BEGIN) { + if (minimum_size.height > new_size_cache.height) { + new_pos_cache.y = new_pos_cache.y + new_size_cache.height - minimum_size.height; + new_size_cache.height = minimum_size.height; + } + } else { + new_size_cache.height = MAX(minimum_size.height, new_size_cache.height); + } bool pos_changed = new_pos_cache != data.pos_cache; bool size_changed = new_size_cache != data.size_cache; @@ -1887,8 +1915,8 @@ Control::CursorShape Control::get_cursor_shape(const Point2 &p_pos) const { Transform2D Control::get_transform() const { - Transform2D xform = Transform2D(data.rotation, get_position()); - xform.scale_basis(data.scale); + Transform2D xform = _get_internal_transform(); + xform[2] += get_position(); return xform; } @@ -2214,6 +2242,19 @@ void Control::_font_changed() { minimum_size_changed(); //fonts affect minimum size pretty much almost always } +void Control::set_pivot_offset(const Vector2 &p_pivot) { + + data.pivot_offset = p_pivot; + update(); + _notify_transform(); + _change_notify("rect_pivot_offset"); +} + +Vector2 Control::get_pivot_offset() const { + + return data.pivot_offset; +} + void Control::set_scale(const Vector2 &p_scale) { data.scale = p_scale; @@ -2300,6 +2341,27 @@ bool Control::is_clipping_contents() { return data.clip_contents; } +void Control::set_h_grow_direction(GrowDirection p_direction) { + + data.h_grow = p_direction; + _size_changed(); +} + +Control::GrowDirection Control::get_h_grow_direction() const { + + return data.h_grow; +} + +void Control::set_v_grow_direction(GrowDirection p_direction) { + + data.v_grow = p_direction; + _size_changed(); +} +Control::GrowDirection Control::get_v_grow_direction() const { + + return data.v_grow; +} + void Control::_bind_methods() { //ClassDB::bind_method(D_METHOD("_window_resize_event"),&Control::_window_resize_event); @@ -2325,6 +2387,7 @@ void Control::_bind_methods() { // TODO: Obsolete this method (old name) properly (GH-4397) ClassDB::bind_method(D_METHOD("_set_rotation_deg", "degrees"), &Control::_set_rotation_deg); ClassDB::bind_method(D_METHOD("set_scale", "scale"), &Control::set_scale); + ClassDB::bind_method(D_METHOD("set_pivot_offset", "pivot_offset"), &Control::set_pivot_offset); ClassDB::bind_method(D_METHOD("get_margin", "margin"), &Control::get_margin); ClassDB::bind_method(D_METHOD("get_begin"), &Control::get_begin); ClassDB::bind_method(D_METHOD("get_end"), &Control::get_end); @@ -2335,6 +2398,7 @@ void Control::_bind_methods() { // TODO: Obsolete this method (old name) properly (GH-4397) ClassDB::bind_method(D_METHOD("_get_rotation_deg"), &Control::_get_rotation_deg); 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_global_position"), &Control::get_global_position); @@ -2388,6 +2452,12 @@ void Control::_bind_methods() { ClassDB::bind_method(D_METHOD("get_parent_control:Control"), &Control::get_parent_control); + ClassDB::bind_method(D_METHOD("set_h_grow_direction", "direction"), &Control::set_h_grow_direction); + ClassDB::bind_method(D_METHOD("get_h_grow_direction"), &Control::get_h_grow_direction); + + ClassDB::bind_method(D_METHOD("set_v_grow_direction", "direction"), &Control::set_v_grow_direction); + ClassDB::bind_method(D_METHOD("get_v_grow_direction"), &Control::get_v_grow_direction); + ClassDB::bind_method(D_METHOD("set_tooltip", "tooltip"), &Control::set_tooltip); ClassDB::bind_method(D_METHOD("get_tooltip", "atpos"), &Control::get_tooltip, DEFVAL(Point2())); ClassDB::bind_method(D_METHOD("_get_tooltip"), &Control::_get_tooltip); @@ -2438,12 +2508,17 @@ void Control::_bind_methods() { 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_GROUP("Grow Direction", "grow_"); + ADD_PROPERTYNO(PropertyInfo(Variant::INT, "grow_horizontal", PROPERTY_HINT_ENUM, "Begin,End"), "set_h_grow_direction", "get_h_grow_direction"); + ADD_PROPERTYNO(PropertyInfo(Variant::INT, "grow_vertical", PROPERTY_HINT_ENUM, "Begin,End"), "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_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_deg", "get_rotation_deg"); 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_PROPERTYNO(PropertyInfo(Variant::BOOL, "rect_clip_content"), "set_clip_contents", "is_clipping_contents"); ADD_GROUP("Hint", "hint_"); @@ -2459,8 +2534,8 @@ void Control::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "mouse_filter", PROPERTY_HINT_ENUM, "Stop,Pass,Ignore"), "set_mouse_filter", "get_mouse_filter"); ADD_GROUP("Size Flags", "size_flags_"); - ADD_PROPERTYNO(PropertyInfo(Variant::INT, "size_flags_horizontal", PROPERTY_HINT_FLAGS, "Fill,Expand"), "set_h_size_flags", "get_h_size_flags"); - ADD_PROPERTYNO(PropertyInfo(Variant::INT, "size_flags_vertical", PROPERTY_HINT_FLAGS, "Fill,Expand"), "set_v_size_flags", "get_v_size_flags"); + ADD_PROPERTYNO(PropertyInfo(Variant::INT, "size_flags_horizontal", PROPERTY_HINT_FLAGS, "Fill,Expand,Shrink Center,Shrink End"), "set_h_size_flags", "get_h_size_flags"); + ADD_PROPERTYNO(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::INT, "size_flags_stretch_ratio", PROPERTY_HINT_RANGE, "1,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"); @@ -2502,11 +2577,16 @@ void Control::_bind_methods() { BIND_CONSTANT(SIZE_EXPAND); BIND_CONSTANT(SIZE_FILL); BIND_CONSTANT(SIZE_EXPAND_FILL); + BIND_CONSTANT(SIZE_SHRINK_CENTER); + BIND_CONSTANT(SIZE_SHRINK_END); BIND_CONSTANT(MOUSE_FILTER_STOP); BIND_CONSTANT(MOUSE_FILTER_PASS); BIND_CONSTANT(MOUSE_FILTER_IGNORE); + BIND_CONSTANT(GROW_DIRECTION_BEGIN); + BIND_CONSTANT(GROW_DIRECTION_END); + ADD_SIGNAL(MethodInfo("resized")); ADD_SIGNAL(MethodInfo("gui_input", PropertyInfo(Variant::OBJECT, "ev", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent"))); ADD_SIGNAL(MethodInfo("mouse_entered")); @@ -2543,6 +2623,8 @@ Control::Control() { data.modal_frame = 0; data.block_minimum_size_adjust = false; data.disable_visibility_clip = false; + data.h_grow = GROW_DIRECTION_END; + data.v_grow = GROW_DIRECTION_END; data.clip_contents = false; for (int i = 0; i < 4; i++) { diff --git a/scene/gui/control.h b/scene/gui/control.h index 5834d1550a..86cf8f6dbd 100644 --- a/scene/gui/control.h +++ b/scene/gui/control.h @@ -57,6 +57,11 @@ public: ANCHOR_CENTER, }; + enum GrowDirection { + GROW_DIRECTION_BEGIN, + GROW_DIRECTION_END + }; + enum FocusMode { FOCUS_NONE, FOCUS_CLICK, @@ -67,7 +72,9 @@ public: SIZE_FILL = 1, SIZE_EXPAND = 2, - SIZE_EXPAND_FILL = SIZE_EXPAND | SIZE_FILL + 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 }; @@ -117,9 +124,12 @@ private: float margin[4]; AnchorType anchor[4]; FocusMode focus_mode; + GrowDirection h_grow; + GrowDirection v_grow; float rotation; Vector2 scale; + Vector2 pivot_offset; bool pending_resize; @@ -200,6 +210,8 @@ private: void _update_canvas_item_transform(); + Transform2D _get_internal_transform() const; + friend class Viewport; void _modal_stack_remove(); void _modal_set_prev_focus_owner(ObjectID p_prev); @@ -273,6 +285,12 @@ public: void set_begin(const Point2 &p_point); // helper void set_end(const Point2 &p_point); // helper + void set_h_grow_direction(GrowDirection p_direction); + GrowDirection get_h_grow_direction() const; + + void set_v_grow_direction(GrowDirection p_direction); + GrowDirection get_v_grow_direction() const; + float get_margin(Margin p_margin) const; Point2 get_begin() const; Point2 get_end() const; @@ -293,6 +311,9 @@ public: float get_rotation() const; float get_rotation_deg() const; + void set_pivot_offset(const Vector2 &p_pivot); + Vector2 get_pivot_offset() const; + void set_scale(const Vector2 &p_scale); Vector2 get_scale() const; @@ -409,5 +430,6 @@ VARIANT_ENUM_CAST(Control::FocusMode); VARIANT_ENUM_CAST(Control::SizeFlags); VARIANT_ENUM_CAST(Control::CursorShape); VARIANT_ENUM_CAST(Control::MouseFilter); +VARIANT_ENUM_CAST(Control::GrowDirection); #endif diff --git a/scene/gui/graph_edit.cpp b/scene/gui/graph_edit.cpp index 8d085d5399..9d45b6e70a 100644 --- a/scene/gui/graph_edit.cpp +++ b/scene/gui/graph_edit.cpp @@ -568,7 +568,7 @@ static _FORCE_INLINE_ Vector2 _bezier_interp(real_t t, Vector2 start, Vector2 co return start * omt3 + control_1 * omt2 * t * 3.0 + control_2 * omt * t2 * 3.0 + end * t3; } -void GraphEdit::_bake_segment2d(CanvasItem *p_where, float p_begin, float p_end, const Vector2 &p_a, const Vector2 &p_out, const Vector2 &p_b, const Vector2 &p_in, int p_depth, int p_min_depth, int p_max_depth, float p_tol, const Color &p_color, const Color &p_to_color, int &lines) const { +void GraphEdit::_bake_segment2d(Vector<Vector2> &points, Vector<Color> &colors, float p_begin, float p_end, const Vector2 &p_a, const Vector2 &p_out, const Vector2 &p_b, const Vector2 &p_in, int p_depth, int p_min_depth, int p_max_depth, float p_tol, const Color &p_color, const Color &p_to_color, int &lines) const { float mp = p_begin + (p_end - p_begin) * 0.5; Vector2 beg = _bezier_interp(p_begin, p_a, p_a + p_out, p_b + p_in, p_b); @@ -581,11 +581,12 @@ void GraphEdit::_bake_segment2d(CanvasItem *p_where, float p_begin, float p_end, if (p_depth >= p_min_depth && (dp < p_tol || p_depth >= p_max_depth)) { - p_where->draw_line(beg, end, p_color.linear_interpolate(p_to_color, mp), 2, true); + points.push_back((beg + end) * 0.5); + colors.push_back(p_color.linear_interpolate(p_to_color, mp)); lines++; } else { - _bake_segment2d(p_where, p_begin, mp, p_a, p_out, p_b, p_in, p_depth + 1, p_min_depth, p_max_depth, p_tol, p_color, p_to_color, lines); - _bake_segment2d(p_where, mp, p_end, p_a, p_out, p_b, p_in, p_depth + 1, p_min_depth, p_max_depth, p_tol, p_color, p_to_color, lines); + _bake_segment2d(points, colors, p_begin, mp, p_a, p_out, p_b, p_in, p_depth + 1, p_min_depth, p_max_depth, p_tol, p_color, p_to_color, lines); + _bake_segment2d(points, colors, mp, p_end, p_a, p_out, p_b, p_in, p_depth + 1, p_min_depth, p_max_depth, p_tol, p_color, p_to_color, lines); } } @@ -609,7 +610,16 @@ void GraphEdit::_draw_cos_line(CanvasItem *p_where, const Vector2 &p_from, const Vector2 c2 = Vector2(-cp_offset * zoom, 0); int lines = 0; - _bake_segment2d(p_where, 0, 1, p_from, c1, p_to, c2, 0, 3, 9, 8, p_color, p_to_color, lines); + + Vector<Point2> points; + 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); + points.push_back(p_to); + colors.push_back(p_to_color); + + p_where->draw_polyline_colors(points, colors, 2, true); #else diff --git a/scene/gui/graph_edit.h b/scene/gui/graph_edit.h index 22d053d312..e908829d5f 100644 --- a/scene/gui/graph_edit.h +++ b/scene/gui/graph_edit.h @@ -110,7 +110,7 @@ private: bool awaiting_scroll_offset_update; List<Connection> connections; - void _bake_segment2d(CanvasItem *p_where, float p_begin, float p_end, const Vector2 &p_a, const Vector2 &p_out, const Vector2 &p_b, const Vector2 &p_in, int p_depth, int p_min_depth, int p_max_depth, float p_tol, const Color &p_color, const Color &p_to_color, int &lines) const; + void _bake_segment2d(Vector<Vector2> &points, Vector<Color> &colors, float p_begin, float p_end, const Vector2 &p_a, const Vector2 &p_out, const Vector2 &p_b, const Vector2 &p_in, int p_depth, int p_min_depth, int p_max_depth, float p_tol, const Color &p_color, const Color &p_to_color, int &lines) const; void _draw_cos_line(CanvasItem *p_where, const Vector2 &p_from, const Vector2 &p_to, const Color &p_color, const Color &p_to_color); diff --git a/scene/gui/graph_node.cpp b/scene/gui/graph_node.cpp index 95f65f31d6..538dd846e4 100644 --- a/scene/gui/graph_node.cpp +++ b/scene/gui/graph_node.cpp @@ -28,7 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ #include "graph_node.h" -#include "method_bind_ext.inc" +#include "method_bind_ext.gen.inc" bool GraphNode::_set(const StringName &p_name, const Variant &p_value) { diff --git a/scene/gui/item_list.cpp b/scene/gui/item_list.cpp index 2f0c7b9aaf..160b7b151a 100644 --- a/scene/gui/item_list.cpp +++ b/scene/gui/item_list.cpp @@ -1223,6 +1223,36 @@ Vector<int> ItemList::get_selected_items() { return selected; } +void ItemList::_set_items(const Array &p_items) { + + ERR_FAIL_COND(p_items.size() % 3); + clear(); + + for (int i = 0; i < p_items.size(); i += 3) { + + String text = p_items[i + 0]; + Ref<Texture> icon = p_items[i + 1]; + bool disabled = p_items[i + 2]; + + int idx = get_item_count(); + add_item(text, icon); + set_item_disabled(idx, disabled); + } +} + +Array ItemList::_get_items() const { + + Array items; + for (int i = 0; i < get_item_count(); i++) { + + items.push_back(get_item_text(i)); + items.push_back(get_item_icon(i)); + items.push_back(is_item_disabled(i)); + } + + return items; +} + void ItemList::_bind_methods() { ClassDB::bind_method(D_METHOD("add_item", "text", "icon:Texture", "selectable"), &ItemList::add_item, DEFVAL(Variant()), DEFVAL(true)); @@ -1302,6 +1332,22 @@ void ItemList::_bind_methods() { ClassDB::bind_method(D_METHOD("_scroll_changed"), &ItemList::_scroll_changed); ClassDB::bind_method(D_METHOD("_gui_input"), &ItemList::_gui_input); + ClassDB::bind_method(D_METHOD("_set_items"), &ItemList::_set_items); + ClassDB::bind_method(D_METHOD("_get_items"), &ItemList::_get_items); + + ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "items", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "_set_items", "_get_items"); + + ADD_PROPERTY(PropertyInfo(Variant::INT, "select_mode", PROPERTY_HINT_ENUM, "Single,Multi"), "set_select_mode", "get_select_mode"); + 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_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_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"); + BIND_CONSTANT(ICON_MODE_TOP); BIND_CONSTANT(ICON_MODE_LEFT); BIND_CONSTANT(SELECT_SINGLE); diff --git a/scene/gui/item_list.h b/scene/gui/item_list.h index c7abc2990f..9cb7016b60 100644 --- a/scene/gui/item_list.h +++ b/scene/gui/item_list.h @@ -103,6 +103,9 @@ private: real_t icon_scale; + Array _get_items() const; + void _set_items(const Array &p_items); + void _scroll_changed(double); void _gui_input(const Ref<InputEvent> &p_event); diff --git a/scene/gui/label.cpp b/scene/gui/label.cpp index f3a279bada..fb85930ceb 100644 --- a/scene/gui/label.cpp +++ b/scene/gui/label.cpp @@ -65,7 +65,12 @@ void Label::_notification(int p_what) { if (p_what == NOTIFICATION_TRANSLATION_CHANGED) { - xl_text = XL_MESSAGE(text); + String new_text = XL_MESSAGE(text); + if (new_text == xl_text) + return; //nothing new + xl_text = new_text; + + regenerate_word_cache(); minimum_size_changed(); update(); } diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp index 0b8595de42..c6b8398736 100644 --- a/scene/gui/rich_text_label.cpp +++ b/scene/gui/rich_text_label.cpp @@ -1822,16 +1822,41 @@ String RichTextLabel::get_text() { return text; } +void RichTextLabel::set_text(const String &p_string) { + clear(); + add_text(p_string); +} + +void RichTextLabel::set_percent_visible(float p_percent) { + + if (p_percent < 0 || p_percent >= 1) { + + visible_characters = -1; + percent_visible = 1; + + } else { + + visible_characters = get_total_character_count() * p_percent; + percent_visible = p_percent; + } + update(); +} + +float RichTextLabel::get_percent_visible() const { + return percent_visible; +} + void RichTextLabel::_bind_methods() { ClassDB::bind_method(D_METHOD("_gui_input"), &RichTextLabel::_gui_input); ClassDB::bind_method(D_METHOD("_scroll_changed"), &RichTextLabel::_scroll_changed); ClassDB::bind_method(D_METHOD("get_text"), &RichTextLabel::get_text); ClassDB::bind_method(D_METHOD("add_text", "text"), &RichTextLabel::add_text); + ClassDB::bind_method(D_METHOD("set_text", "text"), &RichTextLabel::set_text); ClassDB::bind_method(D_METHOD("add_image", "image:Texture"), &RichTextLabel::add_image); ClassDB::bind_method(D_METHOD("newline"), &RichTextLabel::add_newline); ClassDB::bind_method(D_METHOD("remove_line"), &RichTextLabel::remove_line); - ClassDB::bind_method(D_METHOD("push_font", "font"), &RichTextLabel::push_font); + ClassDB::bind_method(D_METHOD("push_font", "font:Font"), &RichTextLabel::push_font); ClassDB::bind_method(D_METHOD("push_color", "color"), &RichTextLabel::push_color); ClassDB::bind_method(D_METHOD("push_align", "align"), &RichTextLabel::push_align); ClassDB::bind_method(D_METHOD("push_indent", "level"), &RichTextLabel::push_indent); @@ -1854,7 +1879,7 @@ void RichTextLabel::_bind_methods() { ClassDB::bind_method(D_METHOD("set_scroll_follow", "follow"), &RichTextLabel::set_scroll_follow); ClassDB::bind_method(D_METHOD("is_scroll_following"), &RichTextLabel::is_scroll_following); - ClassDB::bind_method(D_METHOD("get_v_scroll"), &RichTextLabel::get_v_scroll); + ClassDB::bind_method(D_METHOD("get_v_scroll:VScrollBar"), &RichTextLabel::get_v_scroll); ClassDB::bind_method(D_METHOD("scroll_to_line", "line"), &RichTextLabel::scroll_to_line); @@ -1873,6 +1898,9 @@ void RichTextLabel::_bind_methods() { ClassDB::bind_method(D_METHOD("set_visible_characters", "amount"), &RichTextLabel::set_visible_characters); ClassDB::bind_method(D_METHOD("get_visible_characters"), &RichTextLabel::get_visible_characters); + ClassDB::bind_method(D_METHOD("set_percent_visible", "percent_visible"), &RichTextLabel::set_percent_visible); + ClassDB::bind_method(D_METHOD("get_percent_visible"), &RichTextLabel::get_percent_visible); + ClassDB::bind_method(D_METHOD("get_total_character_count"), &RichTextLabel::get_total_character_count); ClassDB::bind_method(D_METHOD("set_use_bbcode", "enable"), &RichTextLabel::set_use_bbcode); @@ -1881,7 +1909,9 @@ void RichTextLabel::_bind_methods() { ADD_GROUP("BBCode", "bbcode_"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "bbcode_enabled"), "set_use_bbcode", "is_using_bbcode"); ADD_PROPERTY(PropertyInfo(Variant::STRING, "bbcode_text", PROPERTY_HINT_MULTILINE_TEXT), "set_bbcode", "get_bbcode"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "visible_characters", PROPERTY_HINT_RANGE, "-1,128000,1"), "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_SIGNAL(MethodInfo("meta_clicked", PropertyInfo(Variant::NIL, "meta"))); @@ -1914,7 +1944,6 @@ void RichTextLabel::set_visible_characters(int p_visible) { } int RichTextLabel::get_visible_characters() const { - return visible_characters; } int RichTextLabel::get_total_character_count() const { @@ -1964,11 +1993,11 @@ RichTextLabel::RichTextLabel() { selection.enabled = false; visible_characters = -1; + percent_visible = 1; set_clip_contents(true); } RichTextLabel::~RichTextLabel() { - memdelete(main); } diff --git a/scene/gui/rich_text_label.h b/scene/gui/rich_text_label.h index eedb7e54db..409a8f6b3f 100644 --- a/scene/gui/rich_text_label.h +++ b/scene/gui/rich_text_label.h @@ -258,6 +258,7 @@ private: Selection selection; int visible_characters; + float percent_visible; void _process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int &y, int p_width, int p_line, ProcessMode p_mode, const Ref<Font> &p_base_font, const Color &p_base_color, const Point2i &p_click_pos = Point2i(), Item **r_click_item = NULL, int *r_click_char = NULL, bool *r_outside = NULL, int p_char_count = 0); void _find_click(ItemFrame *p_frame, const Point2i &p_click, Item **r_click_item = NULL, int *r_click_char = NULL, bool *r_outside = NULL); @@ -340,10 +341,15 @@ public: void set_bbcode(const String &p_bbcode); String get_bbcode() const; + void set_text(const String &p_string); + void set_visible_characters(int p_visible); int get_visible_characters() const; int get_total_character_count() const; + void set_percent_visible(float p_percent); + float get_percent_visible() const; + RichTextLabel(); ~RichTextLabel(); }; diff --git a/scene/gui/slider.cpp b/scene/gui/slider.cpp index d0e708bf73..c84608ef2e 100644 --- a/scene/gui/slider.cpp +++ b/scene/gui/slider.cpp @@ -39,6 +39,10 @@ Size2 Slider::get_minimum_size() const { void Slider::_gui_input(Ref<InputEvent> p_event) { + if (!editable) { + return; + } + Ref<InputEventMouseButton> mb = p_event; if (mb.is_valid()) { @@ -158,7 +162,7 @@ void Slider::_notification(int p_what) { Size2i size = get_size(); Ref<StyleBox> style = get_stylebox("slider"); Ref<StyleBox> focus = get_stylebox("focus"); - Ref<Texture> grabber = get_icon(mouse_inside || has_focus() ? "grabber_highlight" : "grabber"); + Ref<Texture> grabber = get_icon(editable ? ((mouse_inside || has_focus()) ? "grabber_highlight" : "grabber") : "grabber_disabled"); Ref<Texture> tick = get_icon("tick"); if (orientation == VERTICAL) { @@ -231,6 +235,17 @@ void Slider::set_ticks_on_borders(bool _tob) { update(); } +void Slider::set_editable(bool p_editable) { + + editable = p_editable; + update(); +} + +bool Slider::is_editable() const { + + return editable; +} + void Slider::_bind_methods() { ClassDB::bind_method(D_METHOD("_gui_input"), &Slider::_gui_input); @@ -240,6 +255,10 @@ void Slider::_bind_methods() { ClassDB::bind_method(D_METHOD("get_ticks_on_borders"), &Slider::get_ticks_on_borders); ClassDB::bind_method(D_METHOD("set_ticks_on_borders", "ticks_on_border"), &Slider::set_ticks_on_borders); + ClassDB::bind_method(D_METHOD("set_editable", "editable"), &Slider::set_editable); + ClassDB::bind_method(D_METHOD("is_editable"), &Slider::is_editable); + + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "editable"), "set_editable", "is_editable"); ADD_PROPERTY(PropertyInfo(Variant::INT, "tick_count", PROPERTY_HINT_RANGE, "0,4096,1"), "set_ticks", "get_ticks"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "ticks_on_borders"), "set_ticks_on_borders", "get_ticks_on_borders"); ADD_PROPERTY(PropertyInfo(Variant::INT, "focus_mode", PROPERTY_HINT_ENUM, "None,Click,All"), "set_focus_mode", "get_focus_mode"); @@ -251,5 +270,6 @@ Slider::Slider(Orientation p_orientation) { grab.active = false; ticks = 0; custom_step = -1; + editable = true; set_focus_mode(FOCUS_ALL); } diff --git a/scene/gui/slider.h b/scene/gui/slider.h index 7194484058..f3cf3c6f48 100644 --- a/scene/gui/slider.h +++ b/scene/gui/slider.h @@ -46,6 +46,7 @@ class Slider : public Range { bool mouse_inside; Orientation orientation; float custom_step; + bool editable; protected: void _gui_input(Ref<InputEvent> p_event); @@ -65,6 +66,9 @@ public: void set_ticks_on_borders(bool); bool get_ticks_on_borders() const; + void set_editable(bool p_editable); + bool is_editable() const; + Slider(Orientation p_orientation = VERTICAL); }; diff --git a/scene/gui/split_container.cpp b/scene/gui/split_container.cpp index 31236fa277..e3dad08809 100644 --- a/scene/gui/split_container.cpp +++ b/scene/gui/split_container.cpp @@ -131,7 +131,12 @@ void SplitContainer::_resort() { if (ratiomode) { - middle_sep = ms_first[axis] + available / 2; + int first_ratio = first->get_stretch_ratio(); + int second_ratio = second->get_stretch_ratio(); + + float ratio = float(first_ratio) / (first_ratio + second_ratio); + + middle_sep = ms_first[axis] + available * ratio; } else if (expand_first_mode) { @@ -144,12 +149,17 @@ void SplitContainer::_resort() { } else if (ratiomode) { - if (expand_ofs < -(available / 2)) - expand_ofs = -(available / 2); - else if (expand_ofs > (available / 2)) - expand_ofs = (available / 2); + int first_ratio = first->get_stretch_ratio(); + int second_ratio = second->get_stretch_ratio(); + + float ratio = float(first_ratio) / (first_ratio + second_ratio); + + if (expand_ofs < -(available * ratio)) + expand_ofs = -(available * ratio); + else if (expand_ofs > (available * (1.0 - ratio))) + expand_ofs = (available * (1.0 - ratio)); - middle_sep = ms_first[axis] + available / 2 + expand_ofs; + middle_sep = ms_first[axis] + available * ratio + expand_ofs; } else if (expand_first_mode) { diff --git a/scene/gui/tabs.cpp b/scene/gui/tabs.cpp index 600493b439..4316f06a53 100644 --- a/scene/gui/tabs.cpp +++ b/scene/gui/tabs.cpp @@ -593,6 +593,41 @@ void Tabs::remove_tab(int p_idx) { _ensure_no_over_offset(); } +Variant Tabs::get_drag_data(const Point2 &p_point) { + + return get_tab_idx_at_point(p_point); +} + +bool Tabs::can_drop_data(const Point2 &p_point, const Variant &p_data) const { + + return get_tab_idx_at_point(p_point) > -1; +} + +void Tabs::drop_data(const Point2 &p_point, const Variant &p_data) { + + int hover_now = get_tab_idx_at_point(p_point); + + ERR_FAIL_INDEX(hover_now, tabs.size()); + emit_signal("reposition_active_tab_request", hover_now); +} + +int Tabs::get_tab_idx_at_point(const Point2 &p_point) const { + + int hover_now = -1; + for (int i = 0; i < tabs.size(); i++) { + + if (i < offset) + continue; + + Rect2 rect = get_tab_rect(i); + if (rect.has_point(p_point)) { + hover_now = i; + } + } + + return hover_now; +} + void Tabs::set_tab_align(TabAlign p_align) { tab_align = p_align; @@ -708,7 +743,7 @@ void Tabs::ensure_tab_visible(int p_idx) { } } -Rect2 Tabs::get_tab_rect(int p_tab) { +Rect2 Tabs::get_tab_rect(int p_tab) const { return Rect2(tabs[p_tab].ofs_cache, 0, tabs[p_tab].size_cache, get_size().height); } @@ -743,6 +778,7 @@ void Tabs::_bind_methods() { ADD_SIGNAL(MethodInfo("right_button_pressed", PropertyInfo(Variant::INT, "tab"))); ADD_SIGNAL(MethodInfo("tab_close", PropertyInfo(Variant::INT, "tab"))); ADD_SIGNAL(MethodInfo("tab_hover", PropertyInfo(Variant::INT, "tab"))); + ADD_SIGNAL(MethodInfo("reposition_active_tab_request", PropertyInfo(Variant::INT, "idx_to"))); ADD_PROPERTY(PropertyInfo(Variant::INT, "current_tab", PROPERTY_HINT_RANGE, "-1,4096,1", PROPERTY_USAGE_EDITOR), "set_current_tab", "get_current_tab"); diff --git a/scene/gui/tabs.h b/scene/gui/tabs.h index 65d409c410..613c604b12 100644 --- a/scene/gui/tabs.h +++ b/scene/gui/tabs.h @@ -96,6 +96,11 @@ protected: void _notification(int p_what); static void _bind_methods(); + Variant get_drag_data(const Point2 &p_point); + bool can_drop_data(const Point2 &p_point, const Variant &p_data) const; + void drop_data(const Point2 &p_point, const Variant &p_data); + int get_tab_idx_at_point(const Point2 &p_point) const; + public: void add_tab(const String &p_str = "", const Ref<Texture> &p_icon = Ref<Texture>()); @@ -128,7 +133,7 @@ public: void ensure_tab_visible(int p_idx); void set_min_width(int p_width); - Rect2 get_tab_rect(int p_tab); + Rect2 get_tab_rect(int p_tab) const; Size2 get_minimum_size() const; Tabs(); diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp index d864d9fce7..d8788b4eca 100644 --- a/scene/gui/tree.cpp +++ b/scene/gui/tree.cpp @@ -622,6 +622,40 @@ bool TreeItem::is_custom_set_as_button(int p_column) const { return cells[p_column].custom_button; } +void TreeItem::set_text_align(int p_column, TextAlign p_align) { + ERR_FAIL_INDEX(p_column, cells.size()); + cells[p_column].text_align = p_align; + _changed_notify(p_column); +} + +TreeItem::TextAlign TreeItem::get_text_align(int p_column) const { + ERR_FAIL_INDEX_V(p_column, cells.size(), ALIGN_LEFT); + return cells[p_column].text_align; +} + +void TreeItem::set_expand_right(int p_column, bool p_enable) { + + ERR_FAIL_INDEX(p_column, cells.size()); + cells[p_column].expand_right = p_enable; + _changed_notify(p_column); +} + +bool TreeItem::get_expand_right(int p_column) const { + + ERR_FAIL_INDEX_V(p_column, cells.size(), false); + return cells[p_column].expand_right; +} + +void TreeItem::set_disable_folding(bool p_disable) { + + disable_folding = p_disable; + _changed_notify(0); +} + +bool TreeItem::is_folding_disabled() const { + return disable_folding; +} + void TreeItem::_bind_methods() { ClassDB::bind_method(D_METHOD("set_cell_mode", "column", "mode"), &TreeItem::set_cell_mode); @@ -692,12 +726,19 @@ void TreeItem::_bind_methods() { ClassDB::bind_method(D_METHOD("erase_button", "column", "button_idx"), &TreeItem::erase_button); ClassDB::bind_method(D_METHOD("is_button_disabled", "column", "button_idx"), &TreeItem::is_button_disabled); + ClassDB::bind_method(D_METHOD("set_expand_right", "column", "enable"), &TreeItem::set_expand_right); + ClassDB::bind_method(D_METHOD("get_expand_right", "column"), &TreeItem::get_expand_right); + ClassDB::bind_method(D_METHOD("set_tooltip", "column", "tooltip"), &TreeItem::set_tooltip); ClassDB::bind_method(D_METHOD("get_tooltip", "column"), &TreeItem::get_tooltip); - + ClassDB::bind_method(D_METHOD("set_text_align", "column", "text_align"), &TreeItem::set_text_align); + ClassDB::bind_method(D_METHOD("get_text_align", "column"), &TreeItem::get_text_align); ClassDB::bind_method(D_METHOD("move_to_top"), &TreeItem::move_to_top); ClassDB::bind_method(D_METHOD("move_to_bottom"), &TreeItem::move_to_bottom); + ClassDB::bind_method(D_METHOD("set_disable_folding", "disable"), &TreeItem::set_disable_folding); + ClassDB::bind_method(D_METHOD("is_folding_disabled"), &TreeItem::is_folding_disabled); + BIND_CONSTANT(CELL_MODE_STRING); BIND_CONSTANT(CELL_MODE_CHECK); BIND_CONSTANT(CELL_MODE_RANGE); @@ -724,6 +765,7 @@ TreeItem::TreeItem(Tree *p_tree) { tree = p_tree; collapsed = false; + disable_folding = false; parent = 0; // parent item next = 0; // next in list @@ -894,6 +936,32 @@ int Tree::get_item_height(TreeItem *p_item) const { void Tree::draw_item_rect(const TreeItem::Cell &p_cell, const Rect2i &p_rect, const Color &p_color) { Rect2i rect = p_rect; + Ref<Font> font = cache.font; + String text = p_cell.text; + if (p_cell.suffix != String()) + text += " " + p_cell.suffix; + + int w = 0; + if (!p_cell.icon.is_null()) { + Size2i bmsize = p_cell.get_icon_size(); + + if (p_cell.icon_max_w > 0 && bmsize.width > p_cell.icon_max_w) { + bmsize.width = p_cell.icon_max_w; + } + w += bmsize.width + cache.hseparation; + } + w += font->get_string_size(text).width; + + switch (p_cell.text_align) { + case TreeItem::ALIGN_LEFT: + break; //do none + case TreeItem::ALIGN_CENTER: + rect.position.x = MAX(0, (rect.size.width - w) / 2); + break; //do none + case TreeItem::ALIGN_RIGHT: + rect.position.x = MAX(0, (rect.size.width - w)); + break; //do none + } RID ci = get_canvas_item(); if (!p_cell.icon.is_null()) { @@ -914,12 +982,6 @@ void Tree::draw_item_rect(const TreeItem::Cell &p_cell, const Rect2i &p_rect, co rect.size.x-=Math::floor(rect.size.y/2); */ - Ref<Font> font = cache.font; - - String text = p_cell.text; - if (p_cell.suffix != String()) - text += " " + p_cell.suffix; - rect.position.y += Math::floor((rect.size.y - font->get_height()) / 2.0) + font->get_ascent(); font->draw(ci, rect.position, text, p_color, rect.size.x); } @@ -970,20 +1032,6 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2 if (!skip && (p_pos.y + label_h - cache.offset.y) > 0) { - if (!hide_folding && p_item->childs) { //has childs, draw the guide box - - Ref<Texture> arrow; - - if (p_item->collapsed) { - - arrow = cache.arrow_collapsed; - } else { - arrow = cache.arrow; - } - - arrow->draw(ci, p_pos + p_draw_ofs + Point2i(0, (label_h - arrow->get_height()) / 2) - cache.offset); - } - //draw separation. //if (p_item->get_parent()!=root || !hide_root) @@ -991,9 +1039,15 @@ 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 + (hide_folding ? cache.hseparation : cache.item_margin); + int ofs = p_pos.x + ((p_item->disable_folding || hide_folding) ? cache.hseparation : cache.item_margin); + int skip = 0; for (int i = 0; i < columns.size(); i++) { + if (skip) { + skip--; + continue; + } + int w = get_column_width(i); if (i == 0) { @@ -1011,6 +1065,16 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2 w -= cache.hseparation; } + if (p_item->cells[i].expand_right) { + + int plus = 1; + 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++; + } + } + int bw = 0; for (int j = p_item->cells[i].buttons.size() - 1; j >= 0; j--) { Ref<Texture> b = p_item->cells[i].buttons[j].texture; @@ -1076,8 +1140,13 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2 if (p_item->cells[i].custom_bg_color) { Rect2 r = cell_rect; - r.position.x -= cache.hseparation; - r.size.x += cache.hseparation; + if (i == 0) { + r.position.x = p_draw_ofs.x; + r.size.x = w + ofs; + } else { + r.position.x -= cache.hseparation; + r.size.x += cache.hseparation; + } if (p_item->cells[i].custom_bg_outline) { VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(r.position.x, r.position.y, r.size.x, 1), p_item->cells[i].bg_color); VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(r.position.x, r.position.y + r.size.y - 1, r.size.x, 1), p_item->cells[i].bg_color); @@ -1274,6 +1343,19 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2 } } + if (!p_item->disable_folding && !hide_folding && p_item->childs) { //has childs, draw the guide box + + Ref<Texture> arrow; + + if (p_item->collapsed) { + + arrow = cache.arrow_collapsed; + } else { + arrow = cache.arrow; + } + + arrow->draw(ci, p_pos + p_draw_ofs + Point2i(0, (label_h - arrow->get_height()) / 2) - cache.offset); + } //separator //get_painter()->draw_fill_rect( Point2i(0,pos.y),Size2i(get_size().width,1),color( COLOR_TREE_GRID) ); @@ -1295,8 +1377,8 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2 while (c) { if (cache.draw_relationship_lines == 1) { - int root_ofs = children_pos.x + (hide_folding ? cache.hseparation : cache.item_margin); - int parent_ofs = p_pos.x + (hide_folding ? cache.hseparation : cache.item_margin); + 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); @@ -1488,7 +1570,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool return -1; } - if (!hide_folding && (p_pos.x >= x_ofs && p_pos.x < (x_ofs + cache.item_margin))) { + if (!p_item->disable_folding && !hide_folding && (p_pos.x >= x_ofs && p_pos.x < (x_ofs + cache.item_margin))) { if (p_item->childs) p_item->set_collapsed(!p_item->is_collapsed()); @@ -1504,6 +1586,18 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool for (int i = 0; i < columns.size(); i++) { col_width = get_column_width(i); + + if (p_item->cells[i].expand_right) { + + int plus = 1; + 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()) { + plus++; + col_width += cache.hseparation; + col_width += get_column_width(i + plus); + plus++; + } + } + if (x > col_width) { col_ofs += col_width; x -= col_width; @@ -1528,6 +1622,11 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool x -= cache.hseparation; } + if (!p_item->disable_folding && !hide_folding && !p_item->cells[col].editable && !p_item->cells[col].selectable && p_item->get_children()) { + p_item->set_collapsed(!p_item->is_collapsed()); + return -1; //collapse/uncollapse because nothing can be done with item + } + TreeItem::Cell &c = p_item->cells[col]; bool already_selected = c.selected; diff --git a/scene/gui/tree.h b/scene/gui/tree.h index 097e0110e8..59e35bb230 100644 --- a/scene/gui/tree.h +++ b/scene/gui/tree.h @@ -58,6 +58,12 @@ public: CELL_MODE_CUSTOM, ///< Contains a custom value, show a string, and an edit button }; + enum TextAlign { + ALIGN_LEFT, + ALIGN_CENTER, + ALIGN_RIGHT + }; + private: friend class Tree; @@ -82,6 +88,9 @@ private: bool custom_bg_outline; Color bg_color; bool custom_button; + bool expand_right; + + TextAlign text_align; Variant meta; String tooltip; @@ -122,6 +131,8 @@ private: custom_bg_color = false; expr = false; icon_max_w = 0; + text_align = ALIGN_LEFT; + expand_right = false; } Size2 get_icon_size() const; @@ -131,6 +142,7 @@ private: Vector<Cell> cells; bool collapsed; // wont show childs + bool disable_folding; TreeItem *parent; // parent item TreeItem *next; // next in list @@ -248,13 +260,23 @@ public: void clear_children(); + void set_text_align(int p_column, TextAlign p_align); + TextAlign get_text_align(int p_column) const; + + void set_expand_right(int p_column, bool p_enable); + bool get_expand_right(int p_column) const; + void move_to_top(); void move_to_bottom(); + void set_disable_folding(bool p_disable); + bool is_folding_disabled() const; + ~TreeItem(); }; VARIANT_ENUM_CAST(TreeItem::TreeCellMode); +VARIANT_ENUM_CAST(TreeItem::TextAlign); class Tree : public Control { |