summaryrefslogtreecommitdiff
path: root/scene/gui
diff options
context:
space:
mode:
Diffstat (limited to 'scene/gui')
-rw-r--r--scene/gui/base_button.cpp4
-rw-r--r--scene/gui/color_picker.cpp49
-rw-r--r--scene/gui/control.cpp184
-rw-r--r--scene/gui/control.h36
-rw-r--r--scene/gui/file_dialog.cpp32
-rw-r--r--scene/gui/graph_edit.cpp53
-rw-r--r--scene/gui/graph_node.cpp17
-rw-r--r--scene/gui/graph_node.h4
-rw-r--r--scene/gui/item_list.cpp51
-rw-r--r--scene/gui/item_list.h2
-rw-r--r--scene/gui/line_edit.cpp167
-rw-r--r--scene/gui/line_edit.h18
-rw-r--r--scene/gui/nine_patch_rect.cpp (renamed from scene/gui/patch_9_rect.cpp)4
-rw-r--r--scene/gui/nine_patch_rect.h (renamed from scene/gui/patch_9_rect.h)8
-rw-r--r--scene/gui/popup.cpp2
-rw-r--r--scene/gui/range.cpp10
-rw-r--r--scene/gui/rich_text_label.cpp92
-rw-r--r--scene/gui/rich_text_label.h8
-rw-r--r--scene/gui/scroll_bar.cpp38
-rw-r--r--scene/gui/scroll_container.cpp28
-rw-r--r--scene/gui/scroll_container.h2
-rw-r--r--scene/gui/separator.cpp6
-rw-r--r--scene/gui/slider.cpp10
-rw-r--r--scene/gui/spin_box.cpp4
-rw-r--r--scene/gui/tab_container.cpp24
-rw-r--r--scene/gui/tabs.cpp2
-rw-r--r--scene/gui/text_edit.cpp300
-rw-r--r--scene/gui/text_edit.h18
-rw-r--r--scene/gui/tree.cpp104
-rw-r--r--scene/gui/tree.h8
-rw-r--r--scene/gui/video_player.cpp13
-rw-r--r--scene/gui/video_player.h3
-rw-r--r--scene/gui/viewport_container.cpp35
-rw-r--r--scene/gui/viewport_container.h4
34 files changed, 932 insertions, 408 deletions
diff --git a/scene/gui/base_button.cpp b/scene/gui/base_button.cpp
index 5713a35b7a..148277f2dd 100644
--- a/scene/gui/base_button.cpp
+++ b/scene/gui/base_button.cpp
@@ -39,7 +39,9 @@ void BaseButton::_unpress_group() {
if (!button_group.is_valid())
return;
- status.pressed = true;
+ if (toggle_mode) {
+ status.pressed = true;
+ }
for (Set<BaseButton *>::Element *E = button_group->buttons.front(); E; E = E->next()) {
if (E->get() == this)
diff --git a/scene/gui/color_picker.cpp b/scene/gui/color_picker.cpp
index 704c00b1d6..dbd7c1bbc0 100644
--- a/scene/gui/color_picker.cpp
+++ b/scene/gui/color_picker.cpp
@@ -40,12 +40,15 @@ void ColorPicker::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_THEME_CHANGED: {
//sample->set_texture(get_icon("color_sample"));
+ btn_pick->set_icon(get_icon("screen_picker", "ColorPicker"));
+ bt_add_preset->set_icon(get_icon("add_preset"));
_update_controls();
} break;
case NOTIFICATION_ENTER_TREE: {
btn_pick->set_icon(get_icon("screen_picker", "ColorPicker"));
+ bt_add_preset->set_icon(get_icon("add_preset"));
_update_color();
} break;
@@ -177,29 +180,14 @@ void ColorPicker::_update_color() {
void ColorPicker::_update_presets() {
Size2 size = bt_add_preset->get_size();
- preset->set_custom_minimum_size(Size2(size.width * presets.size(), size.height));
-
- PoolVector<uint8_t> img;
- img.resize(size.x * presets.size() * size.y * 3);
-
- {
- PoolVector<uint8_t>::Write w = img.write();
- for (int y = 0; y < size.y; y++) {
- for (int x = 0; x < size.x * presets.size(); x++) {
- int ofs = (y * (size.x * presets.size()) + x) * 3;
- w[ofs + 0] = uint8_t(CLAMP(presets[(int)x / size.x].r * 255.0, 0, 255));
- w[ofs + 1] = uint8_t(CLAMP(presets[(int)x / size.x].g * 255.0, 0, 255));
- w[ofs + 2] = uint8_t(CLAMP(presets[(int)x / size.x].b * 255.0, 0, 255));
- }
- }
- }
+ Size2 preset_size = Size2(size.width * presets.size(), size.height);
+ preset->set_custom_minimum_size(preset_size);
- Ref<Image> i = memnew(Image(size.x * presets.size(), size.y, false, Image::FORMAT_RGB8, img));
+ preset->draw_texture_rect(get_icon("preset_bg", "ColorPicker"), Rect2(Point2(), preset_size), true);
- Ref<ImageTexture> t;
- t.instance();
- t->create_from_image(i);
- preset->set_texture(t);
+ for (int i = 0; i < presets.size(); i++) {
+ preset->draw_rect(Rect2(Point2(size.width * i, 0), size), presets[i]);
+ }
}
void ColorPicker::_text_type_toggled() {
@@ -227,7 +215,7 @@ void ColorPicker::add_preset(const Color &p_color) {
} else {
presets.push_back(p_color);
}
- _update_presets();
+ preset->update();
if (presets.size() == 10)
bt_add_preset->hide();
}
@@ -266,7 +254,11 @@ void ColorPicker::_update_text_value() {
}
void ColorPicker::_sample_draw() {
- sample->draw_rect(Rect2(Point2(), Size2(uv_edit->get_size().width, sample->get_size().height * 0.95)), color);
+ Rect2 r = Rect2(Point2(), Size2(uv_edit->get_size().width, sample->get_size().height * 0.95));
+ if (color.a < 1.0) {
+ sample->draw_texture_rect(get_icon("preset_bg", "ColorPicker"), r, true);
+ }
+ sample->draw_rect(r, color);
}
void ColorPicker::_hsv_draw(int p_which, Control *c) {
@@ -399,7 +391,7 @@ void ColorPicker::_preset_input(const Ref<InputEvent> &p_event) {
} else if (bev->is_pressed() && bev->get_button_index() == BUTTON_RIGHT) {
int index = bev->get_position().x / (preset->get_size().x / presets.size());
presets.erase(presets[index]);
- _update_presets();
+ preset->update();
bt_add_preset->show();
}
_update_color();
@@ -461,7 +453,7 @@ void ColorPicker::_screen_pick_pressed() {
screen = memnew(Control);
r->add_child(screen);
screen->set_as_toplevel(true);
- screen->set_area_as_parent_rect();
+ screen->set_anchors_and_margins_preset(Control::PRESET_WIDE);
screen->set_default_cursor_shape(CURSOR_POINTING_HAND);
screen->connect("gui_input", this, "_screen_input");
}
@@ -484,6 +476,7 @@ void ColorPicker::_bind_methods() {
ClassDB::bind_method(D_METHOD("_add_preset_pressed"), &ColorPicker::_add_preset_pressed);
ClassDB::bind_method(D_METHOD("_screen_pick_pressed"), &ColorPicker::_screen_pick_pressed);
ClassDB::bind_method(D_METHOD("_sample_draw"), &ColorPicker::_sample_draw);
+ ClassDB::bind_method(D_METHOD("_update_presets"), &ColorPicker::_update_presets);
ClassDB::bind_method(D_METHOD("_hsv_draw"), &ColorPicker::_hsv_draw);
ClassDB::bind_method(D_METHOD("_uv_input"), &ColorPicker::_uv_input);
ClassDB::bind_method(D_METHOD("_w_input"), &ColorPicker::_w_input);
@@ -608,9 +601,9 @@ ColorPicker::ColorPicker()
bbc->add_child(preset);
//preset->set_ignore_mouse(false);
preset->connect("gui_input", this, "_preset_input");
+ preset->connect("draw", this, "_update_presets");
bt_add_preset = memnew(Button);
- bt_add_preset->set_icon(get_icon("add_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);
@@ -636,7 +629,9 @@ void ColorPickerButton::_notification(int p_what) {
if (p_what == NOTIFICATION_DRAW) {
Ref<StyleBox> normal = get_stylebox("normal");
- draw_rect(Rect2(normal->get_offset(), get_size() - normal->get_minimum_size()), picker->get_pick_color());
+ Rect2 r = Rect2(normal->get_offset(), get_size() - normal->get_minimum_size());
+ draw_texture_rect(Control::get_icon("bg", "ColorPickerButton"), r, true);
+ draw_rect(r, picker->get_pick_color());
}
if (p_what == MainLoop::NOTIFICATION_WM_QUIT_REQUEST) {
diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp
index 2d5b54257a..54a58159ac 100644
--- a/scene/gui/control.cpp
+++ b/scene/gui/control.cpp
@@ -49,7 +49,7 @@ Variant Control::edit_get_state() const {
Dictionary s;
s["rect"] = get_rect();
- s["rot"] = get_rotation();
+ s["rotation"] = get_rotation();
s["scale"] = get_scale();
Array anchors;
anchors.push_back(get_anchor(MARGIN_LEFT));
@@ -66,7 +66,7 @@ void Control::edit_set_state(const Variant &p_state) {
Rect2 state = s["rect"];
set_position(state.position);
set_size(state.size);
- set_rotation(s["rot"]);
+ set_rotation(s["rotation"]);
set_scale(s["scale"]);
Array anchors = s["anchors"];
set_anchor(MARGIN_LEFT, anchors[0]);
@@ -1471,6 +1471,140 @@ void Control::set_anchors_preset(LayoutPreset p_preset, bool p_keep_margin) {
}
}
+void Control::set_margins_preset(LayoutPreset p_preset, LayoutPresetMode p_resize_mode, int p_margin) {
+ // Calculate the size if the node is not resized
+ Size2 min_size = get_minimum_size();
+ Size2 new_size = get_size();
+ if (p_resize_mode == PRESET_MODE_MINSIZE || p_resize_mode == PRESET_MODE_KEEP_HEIGHT) {
+ new_size.x = min_size.x;
+ }
+ if (p_resize_mode == PRESET_MODE_MINSIZE || p_resize_mode == PRESET_MODE_KEEP_WIDTH) {
+ new_size.y = min_size.y;
+ }
+
+ float pw = _get_parent_range(0);
+ float ph = _get_parent_range(1);
+
+ //Left
+ switch (p_preset) {
+ case PRESET_TOP_LEFT:
+ case PRESET_BOTTOM_LEFT:
+ case PRESET_CENTER_LEFT:
+ case PRESET_TOP_WIDE:
+ case PRESET_BOTTOM_WIDE:
+ case PRESET_LEFT_WIDE:
+ case PRESET_HCENTER_WIDE:
+ case PRESET_WIDE:
+ data.margin[0] = pw * (0.0 - data.anchor[0]) + p_margin;
+ break;
+
+ case PRESET_CENTER_TOP:
+ case PRESET_CENTER_BOTTOM:
+ case PRESET_CENTER:
+ case PRESET_VCENTER_WIDE:
+ data.margin[0] = pw * (0.5 - data.anchor[0]) - new_size.x / 2;
+ break;
+
+ case PRESET_TOP_RIGHT:
+ case PRESET_BOTTOM_RIGHT:
+ case PRESET_CENTER_RIGHT:
+ case PRESET_RIGHT_WIDE:
+ data.margin[0] = pw * (1.0 - data.anchor[0]) - new_size.x - p_margin;
+ break;
+ }
+
+ // Top
+ switch (p_preset) {
+ case PRESET_TOP_LEFT:
+ case PRESET_TOP_RIGHT:
+ case PRESET_CENTER_TOP:
+ case PRESET_LEFT_WIDE:
+ case PRESET_RIGHT_WIDE:
+ case PRESET_TOP_WIDE:
+ case PRESET_VCENTER_WIDE:
+ case PRESET_WIDE:
+ data.margin[1] = ph * (0.0 - data.anchor[1]) + p_margin;
+ break;
+
+ case PRESET_CENTER_LEFT:
+ case PRESET_CENTER_RIGHT:
+ case PRESET_CENTER:
+ case PRESET_HCENTER_WIDE:
+ data.margin[1] = ph * (0.5 - data.anchor[1]) - new_size.y / 2;
+ break;
+
+ case PRESET_BOTTOM_LEFT:
+ case PRESET_BOTTOM_RIGHT:
+ case PRESET_CENTER_BOTTOM:
+ case PRESET_BOTTOM_WIDE:
+ data.margin[1] = ph * (1.0 - data.anchor[1]) - new_size.y - p_margin;
+ break;
+ }
+
+ // Right
+ switch (p_preset) {
+ case PRESET_TOP_LEFT:
+ case PRESET_BOTTOM_LEFT:
+ case PRESET_CENTER_LEFT:
+ case PRESET_LEFT_WIDE:
+ data.margin[2] = pw * (0.0 - data.anchor[2]) + new_size.x + p_margin;
+ break;
+
+ case PRESET_CENTER_TOP:
+ case PRESET_CENTER_BOTTOM:
+ case PRESET_CENTER:
+ case PRESET_VCENTER_WIDE:
+ data.margin[2] = pw * (0.5 - data.anchor[2]) + new_size.x / 2;
+ break;
+
+ case PRESET_TOP_RIGHT:
+ case PRESET_BOTTOM_RIGHT:
+ case PRESET_CENTER_RIGHT:
+ case PRESET_TOP_WIDE:
+ case PRESET_RIGHT_WIDE:
+ case PRESET_BOTTOM_WIDE:
+ case PRESET_HCENTER_WIDE:
+ case PRESET_WIDE:
+ data.margin[2] = pw * (1.0 - data.anchor[2]) - p_margin;
+ break;
+ }
+
+ // Bottom
+ switch (p_preset) {
+ case PRESET_TOP_LEFT:
+ case PRESET_TOP_RIGHT:
+ case PRESET_CENTER_TOP:
+ case PRESET_TOP_WIDE:
+ data.margin[3] = ph * (0.0 - data.anchor[3]) + new_size.y + p_margin;
+ break;
+
+ case PRESET_CENTER_LEFT:
+ case PRESET_CENTER_RIGHT:
+ case PRESET_CENTER:
+ case PRESET_HCENTER_WIDE:
+ data.margin[3] = ph * (0.5 - data.anchor[3]) + new_size.y / 2;
+ break;
+
+ case PRESET_BOTTOM_LEFT:
+ case PRESET_BOTTOM_RIGHT:
+ case PRESET_CENTER_BOTTOM:
+ case PRESET_LEFT_WIDE:
+ case PRESET_RIGHT_WIDE:
+ case PRESET_BOTTOM_WIDE:
+ case PRESET_VCENTER_WIDE:
+ case PRESET_WIDE:
+ data.margin[3] = ph * (1.0 - data.anchor[3]) - p_margin;
+ break;
+ }
+
+ _size_changed();
+}
+
+void Control::set_anchors_and_margins_preset(LayoutPreset p_preset, LayoutPresetMode p_resize_mode, int p_margin) {
+ set_anchors_preset(p_preset);
+ set_margins_preset(p_preset, p_resize_mode, p_margin);
+}
+
float Control::get_anchor(Margin p_margin) const {
return data.anchor[p_margin];
@@ -1622,20 +1756,6 @@ Rect2 Control::get_item_rect() const {
return Rect2(Point2(), get_size());
}
-void Control::set_area_as_parent_rect(int p_margin) {
-
- data.anchor[MARGIN_LEFT] = ANCHOR_BEGIN;
- data.margin[MARGIN_LEFT] = p_margin;
- data.anchor[MARGIN_TOP] = ANCHOR_BEGIN;
- data.margin[MARGIN_TOP] = p_margin;
- data.anchor[MARGIN_RIGHT] = ANCHOR_END;
- data.margin[MARGIN_RIGHT] = -p_margin;
- data.anchor[MARGIN_BOTTOM] = ANCHOR_END;
- data.margin[MARGIN_BOTTOM] = -p_margin;
-
- _size_changed();
-}
-
void Control::add_icon_override(const StringName &p_name, const Ref<Texture> &p_icon) {
ERR_FAIL_COND(p_icon.is_null());
@@ -2471,18 +2591,20 @@ void Control::_bind_methods() {
ClassDB::bind_method(D_METHOD("accept_event"), &Control::accept_event);
ClassDB::bind_method(D_METHOD("get_minimum_size"), &Control::get_minimum_size);
ClassDB::bind_method(D_METHOD("get_combined_minimum_size"), &Control::get_combined_minimum_size);
+ ClassDB::bind_method(D_METHOD("set_anchors_preset", "preset", "keep_margin"), &Control::set_anchors_preset, DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("set_margins_preset", "preset", "resize_mode", "margin"), &Control::set_margins_preset, DEFVAL(PRESET_MODE_MINSIZE), DEFVAL(0));
+ ClassDB::bind_method(D_METHOD("set_anchors_and_margins_preset", "preset", "resize_mode", "margin"), &Control::set_anchors_and_margins_preset, DEFVAL(PRESET_MODE_MINSIZE), DEFVAL(0));
ClassDB::bind_method(D_METHOD("set_anchor", "margin", "anchor", "keep_margin", "push_opposite_anchor"), &Control::set_anchor, DEFVAL(false), DEFVAL(true));
ClassDB::bind_method(D_METHOD("_set_anchor", "margin", "anchor"), &Control::_set_anchor);
- ClassDB::bind_method(D_METHOD("set_anchors_preset", "preset", "keep_margin"), &Control::set_anchors_preset, DEFVAL(false));
ClassDB::bind_method(D_METHOD("get_anchor", "margin"), &Control::get_anchor);
ClassDB::bind_method(D_METHOD("set_margin", "margin", "offset"), &Control::set_margin);
ClassDB::bind_method(D_METHOD("set_anchor_and_margin", "margin", "anchor", "offset", "push_opposite_anchor"), &Control::set_anchor_and_margin, DEFVAL(false));
- ClassDB::bind_method(D_METHOD("set_begin", "pos"), &Control::set_begin);
- ClassDB::bind_method(D_METHOD("set_end", "pos"), &Control::set_end);
- ClassDB::bind_method(D_METHOD("set_position", "pos"), &Control::set_position);
+ ClassDB::bind_method(D_METHOD("set_begin", "position"), &Control::set_begin);
+ ClassDB::bind_method(D_METHOD("set_end", "position"), &Control::set_end);
+ ClassDB::bind_method(D_METHOD("set_position", "position"), &Control::set_position);
ClassDB::bind_method(D_METHOD("set_size", "size"), &Control::set_size);
ClassDB::bind_method(D_METHOD("set_custom_minimum_size", "size"), &Control::set_custom_minimum_size);
- ClassDB::bind_method(D_METHOD("set_global_position", "pos"), &Control::set_global_position);
+ ClassDB::bind_method(D_METHOD("set_global_position", "position"), &Control::set_global_position);
ClassDB::bind_method(D_METHOD("set_rotation", "radians"), &Control::set_rotation);
ClassDB::bind_method(D_METHOD("set_rotation_deg", "degrees"), &Control::set_rotation_deg);
// TODO: Obsolete this method (old name) properly (GH-4397)
@@ -2505,7 +2627,6 @@ void Control::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_global_position"), &Control::get_global_position);
ClassDB::bind_method(D_METHOD("get_rect"), &Control::get_rect);
ClassDB::bind_method(D_METHOD("get_global_rect"), &Control::get_global_rect);
- ClassDB::bind_method(D_METHOD("set_area_as_parent_rect", "margin"), &Control::set_area_as_parent_rect, DEFVAL(0));
ClassDB::bind_method(D_METHOD("show_modal", "exclusive"), &Control::show_modal, DEFVAL(false));
ClassDB::bind_method(D_METHOD("set_focus_mode", "mode"), &Control::set_focus_mode);
ClassDB::bind_method(D_METHOD("get_focus_mode"), &Control::get_focus_mode);
@@ -2560,12 +2681,12 @@ void Control::_bind_methods() {
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", "at_position"), &Control::get_tooltip, DEFVAL(Point2()));
ClassDB::bind_method(D_METHOD("_get_tooltip"), &Control::_get_tooltip);
ClassDB::bind_method(D_METHOD("set_default_cursor_shape", "shape"), &Control::set_default_cursor_shape);
ClassDB::bind_method(D_METHOD("get_default_cursor_shape"), &Control::get_default_cursor_shape);
- ClassDB::bind_method(D_METHOD("get_cursor_shape", "pos"), &Control::get_cursor_shape, DEFVAL(Point2()));
+ ClassDB::bind_method(D_METHOD("get_cursor_shape", "position"), &Control::get_cursor_shape, DEFVAL(Point2()));
ClassDB::bind_method(D_METHOD("set_focus_neighbour", "margin", "neighbour"), &Control::set_focus_neighbour);
ClassDB::bind_method(D_METHOD("get_focus_neighbour", "margin"), &Control::get_focus_neighbour);
@@ -2583,7 +2704,7 @@ void Control::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_drag_forwarding", "target"), &Control::set_drag_forwarding);
ClassDB::bind_method(D_METHOD("set_drag_preview", "control"), &Control::set_drag_preview);
- ClassDB::bind_method(D_METHOD("warp_mouse", "to_pos"), &Control::warp_mouse);
+ ClassDB::bind_method(D_METHOD("warp_mouse", "to_position"), &Control::warp_mouse);
ClassDB::bind_method(D_METHOD("minimum_size_changed"), &Control::minimum_size_changed);
@@ -2593,9 +2714,9 @@ void Control::_bind_methods() {
BIND_VMETHOD(MethodInfo("_gui_input", PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent")));
BIND_VMETHOD(MethodInfo(Variant::VECTOR2, "_get_minimum_size"));
- BIND_VMETHOD(MethodInfo(Variant::OBJECT, "get_drag_data", PropertyInfo(Variant::VECTOR2, "pos")));
- BIND_VMETHOD(MethodInfo(Variant::BOOL, "can_drop_data", PropertyInfo(Variant::VECTOR2, "pos"), PropertyInfo(Variant::NIL, "data")));
- BIND_VMETHOD(MethodInfo("drop_data", PropertyInfo(Variant::VECTOR2, "pos"), PropertyInfo(Variant::NIL, "data")));
+ BIND_VMETHOD(MethodInfo(Variant::OBJECT, "get_drag_data", PropertyInfo(Variant::VECTOR2, "position")));
+ BIND_VMETHOD(MethodInfo(Variant::BOOL, "can_drop_data", PropertyInfo(Variant::VECTOR2, "position"), PropertyInfo(Variant::NIL, "data")));
+ BIND_VMETHOD(MethodInfo("drop_data", PropertyInfo(Variant::VECTOR2, "position"), PropertyInfo(Variant::NIL, "data")));
ADD_GROUP("Anchor", "anchor_");
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "anchor_left", PROPERTY_HINT_RANGE, "0,1,0.01"), "_set_anchor", "get_anchor", MARGIN_LEFT);
@@ -2689,8 +2810,13 @@ void Control::_bind_methods() {
BIND_ENUM_CONSTANT(PRESET_HCENTER_WIDE);
BIND_ENUM_CONSTANT(PRESET_WIDE);
- BIND_ENUM_CONSTANT(SIZE_EXPAND);
+ BIND_ENUM_CONSTANT(PRESET_MODE_MINSIZE);
+ BIND_ENUM_CONSTANT(PRESET_MODE_KEEP_WIDTH);
+ BIND_ENUM_CONSTANT(PRESET_MODE_KEEP_HEIGHT);
+ BIND_ENUM_CONSTANT(PRESET_MODE_KEEP_SIZE);
+
BIND_ENUM_CONSTANT(SIZE_FILL);
+ BIND_ENUM_CONSTANT(SIZE_EXPAND);
BIND_ENUM_CONSTANT(SIZE_EXPAND_FILL);
BIND_ENUM_CONSTANT(SIZE_SHRINK_CENTER);
BIND_ENUM_CONSTANT(SIZE_SHRINK_END);
diff --git a/scene/gui/control.h b/scene/gui/control.h
index da5c4d0908..5b146b4454 100644
--- a/scene/gui/control.h
+++ b/scene/gui/control.h
@@ -124,6 +124,13 @@ public:
PRESET_WIDE
};
+ enum LayoutPresetMode {
+ PRESET_MODE_MINSIZE,
+ PRESET_MODE_KEEP_WIDTH,
+ PRESET_MODE_KEEP_HEIGHT,
+ PRESET_MODE_KEEP_SIZE
+ };
+
private:
struct CComparator {
@@ -294,34 +301,32 @@ public:
/* POSITIONING */
- void set_anchor(Margin p_margin, float p_anchor, bool p_keep_margin = false, bool p_push_opposite_anchor = true);
- void set_anchor_and_margin(Margin p_margin, float p_anchor, float p_pos, bool p_push_opposite_anchor = true);
void set_anchors_preset(LayoutPreset p_preset, bool p_keep_margin = false);
+ void set_margins_preset(LayoutPreset p_preset, LayoutPresetMode p_resize_mode = PRESET_MODE_MINSIZE, int p_margin = 0);
+ void set_anchors_and_margins_preset(LayoutPreset p_preset, LayoutPresetMode p_resize_mode = PRESET_MODE_MINSIZE, int p_margin = 0);
+ void set_anchor(Margin p_margin, float p_anchor, bool p_keep_margin = false, bool p_push_opposite_anchor = true);
float get_anchor(Margin p_margin) const;
void set_margin(Margin p_margin, float p_value);
+ float get_margin(Margin p_margin) const;
+
+ void set_anchor_and_margin(Margin p_margin, float p_anchor, float p_pos, bool p_push_opposite_anchor = true);
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;
void set_position(const Point2 &p_point);
- void set_size(const Size2 &p_size);
void set_global_position(const Point2 &p_point);
-
Point2 get_position() const;
Point2 get_global_position() const;
+
+ void set_size(const Size2 &p_size);
Size2 get_size() const;
+
Rect2 get_rect() const;
Rect2 get_global_rect() const;
Rect2 get_window_rect() const; ///< use with care, as it blocks waiting for the visual server
@@ -331,14 +336,18 @@ public:
float get_rotation() const;
float get_rotation_deg() const;
+ 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;
+
void set_pivot_offset(const Vector2 &p_pivot);
Vector2 get_pivot_offset() const;
void set_scale(const Vector2 &p_scale);
Vector2 get_scale() const;
- void set_area_as_parent_rect(int p_margin = 0);
-
void show_modal(bool p_exclusive = false);
void set_theme(const Ref<Theme> &p_theme);
@@ -449,6 +458,7 @@ VARIANT_ENUM_CAST(Control::FocusMode);
VARIANT_ENUM_CAST(Control::SizeFlags);
VARIANT_ENUM_CAST(Control::CursorShape);
VARIANT_ENUM_CAST(Control::LayoutPreset);
+VARIANT_ENUM_CAST(Control::LayoutPresetMode);
VARIANT_ENUM_CAST(Control::MouseFilter);
VARIANT_ENUM_CAST(Control::GrowDirection);
VARIANT_ENUM_CAST(Control::Anchor);
diff --git a/scene/gui/file_dialog.cpp b/scene/gui/file_dialog.cpp
index 87a232e766..6ade4fcc38 100644
--- a/scene/gui/file_dialog.cpp
+++ b/scene/gui/file_dialog.cpp
@@ -115,6 +115,9 @@ Vector<String> FileDialog::get_selected_files() const {
void FileDialog::update_dir() {
dir->set_text(dir_access->get_current_dir());
+ if (drives->is_visible()) {
+ drives->select(dir_access->get_current_drive());
+ }
}
void FileDialog::_dir_entered(String p_dir) {
@@ -666,7 +669,6 @@ void FileDialog::_update_drives() {
drives->show();
for (int i = 0; i < dir_access->get_drive_count(); i++) {
- String d = dir_access->get_drive(i);
drives->add_item(dir_access->get_drive(i));
}
@@ -757,38 +759,42 @@ FileDialog::FileDialog() {
mode = MODE_SAVE_FILE;
set_title(RTR("Save a File"));
+ HBoxContainer *hbc = memnew(HBoxContainer);
+ hbc->add_child(memnew(Label(RTR("Path:"))));
dir = memnew(LineEdit);
- HBoxContainer *pathhb = memnew(HBoxContainer);
- pathhb->add_child(dir);
+ hbc->add_child(dir);
dir->set_h_size_flags(SIZE_EXPAND_FILL);
refresh = memnew(ToolButton);
refresh->connect("pressed", this, "_update_file_list");
- pathhb->add_child(refresh);
+ hbc->add_child(refresh);
drives = memnew(OptionButton);
- pathhb->add_child(drives);
+ hbc->add_child(drives);
drives->connect("item_selected", this, "_select_drive");
makedir = memnew(Button);
makedir->set_text(RTR("Create Folder"));
makedir->connect("pressed", this, "_make_dir");
- pathhb->add_child(makedir);
-
- vbc->add_margin_child(RTR("Path:"), pathhb);
+ hbc->add_child(makedir);
+ vbc->add_child(hbc);
tree = memnew(Tree);
tree->set_hide_root(true);
vbc->add_margin_child(RTR("Directories & Files:"), tree, true);
+ hbc = memnew(HBoxContainer);
+ hbc->add_child(memnew(Label(RTR("File:"))));
file = memnew(LineEdit);
- //add_child(file);
- vbc->add_margin_child(RTR("File:"), file);
-
+ file->set_stretch_ratio(4);
+ file->set_h_size_flags(SIZE_EXPAND_FILL);
+ hbc->add_child(file);
filter = memnew(OptionButton);
- //add_child(filter);
- vbc->add_margin_child(RTR("Filter:"), filter);
+ filter->set_stretch_ratio(3);
+ filter->set_h_size_flags(SIZE_EXPAND_FILL);
filter->set_clip_text(true); //too many extensions overflow it
+ hbc->add_child(filter);
+ vbc->add_child(hbc);
dir_access = DirAccess::create(DirAccess::ACCESS_RESOURCES);
access = ACCESS_RESOURCES;
diff --git a/scene/gui/graph_edit.cpp b/scene/gui/graph_edit.cpp
index 5b00aab2ef..946a8c47a3 100644
--- a/scene/gui/graph_edit.cpp
+++ b/scene/gui/graph_edit.cpp
@@ -284,7 +284,6 @@ void GraphEdit::_notification(int p_what) {
zoom_reset->set_icon(get_icon("reset"));
zoom_plus->set_icon(get_icon("more"));
snap_button->set_icon(get_icon("snap"));
- //zoom_icon->set_texture( get_icon("Zoom", "EditorIcons"));
}
if (p_what == NOTIFICATION_DRAW) {
@@ -352,14 +351,14 @@ bool GraphEdit::_filter_input(const Point2 &p_point) {
for (int j = 0; j < gn->get_connection_output_count(); j++) {
- Vector2 pos = gn->get_connection_output_pos(j) + gn->get_position();
+ Vector2 pos = gn->get_connection_output_position(j) + gn->get_position();
if (pos.distance_to(p_point) < grab_r)
return true;
}
for (int j = 0; j < gn->get_connection_input_count(); j++) {
- Vector2 pos = gn->get_connection_input_pos(j) + gn->get_position();
+ Vector2 pos = gn->get_connection_input_position(j) + gn->get_position();
if (pos.distance_to(p_point) < grab_r) {
return true;
}
@@ -386,7 +385,7 @@ void GraphEdit::_top_layer_input(const Ref<InputEvent> &p_ev) {
for (int j = 0; j < gn->get_connection_output_count(); j++) {
- Vector2 pos = gn->get_connection_output_pos(j) + gn->get_position();
+ Vector2 pos = gn->get_connection_output_position(j) + gn->get_position();
if (pos.distance_to(mpos) < grab_r) {
if (valid_left_disconnect_types.has(gn->get_connection_output_type(j))) {
@@ -433,7 +432,7 @@ void GraphEdit::_top_layer_input(const Ref<InputEvent> &p_ev) {
for (int j = 0; j < gn->get_connection_input_count(); j++) {
- Vector2 pos = gn->get_connection_input_pos(j) + gn->get_position();
+ Vector2 pos = gn->get_connection_input_position(j) + gn->get_position();
if (pos.distance_to(mpos) < grab_r) {
@@ -501,7 +500,7 @@ void GraphEdit::_top_layer_input(const Ref<InputEvent> &p_ev) {
if (!connecting_out) {
for (int j = 0; j < gn->get_connection_output_count(); j++) {
- Vector2 pos = gn->get_connection_output_pos(j) + gn->get_position();
+ Vector2 pos = gn->get_connection_output_position(j) + gn->get_position();
int type = gn->get_connection_output_type(j);
if ((type == connecting_type || valid_connection_types.has(ConnType(type, connecting_type))) && pos.distance_to(mpos) < grab_r) {
@@ -516,7 +515,7 @@ void GraphEdit::_top_layer_input(const Ref<InputEvent> &p_ev) {
for (int j = 0; j < gn->get_connection_input_count(); j++) {
- Vector2 pos = gn->get_connection_input_pos(j) + gn->get_position();
+ Vector2 pos = gn->get_connection_input_position(j) + gn->get_position();
int type = gn->get_connection_input_type(j);
if ((type == connecting_type || valid_connection_types.has(ConnType(type, connecting_type))) && pos.distance_to(mpos) < grab_r) {
connecting_target = true;
@@ -657,9 +656,9 @@ void GraphEdit::_connections_layer_draw() {
continue;
}
- Vector2 frompos = gfrom->get_connection_output_pos(E->get().from_port) + gfrom->get_offset() * zoom;
+ Vector2 frompos = gfrom->get_connection_output_position(E->get().from_port) + gfrom->get_offset() * zoom;
Color color = gfrom->get_connection_output_color(E->get().from_port);
- Vector2 topos = gto->get_connection_input_pos(E->get().to_port) + gto->get_offset() * zoom;
+ Vector2 topos = gto->get_connection_input_position(E->get().to_port) + gto->get_offset() * zoom;
Color tocolor = gto->get_connection_input_color(E->get().to_port);
_draw_cos_line(connections_layer, frompos, topos, color, tocolor);
}
@@ -682,9 +681,9 @@ void GraphEdit::_top_layer_draw() {
ERR_FAIL_COND(!from);
Vector2 pos;
if (connecting_out)
- pos = from->get_connection_output_pos(connecting_index);
+ pos = from->get_connection_output_position(connecting_index);
else
- pos = from->get_connection_input_pos(connecting_index);
+ pos = from->get_connection_input_position(connecting_index);
pos += from->get_position();
Vector2 topos;
@@ -733,7 +732,7 @@ void GraphEdit::_gui_input(const Ref<InputEvent> &p_ev) {
just_selected = true;
// TODO: Remove local mouse pos hack if/when InputEventMouseMotion is fixed to support floats
//drag_accum+=Vector2(mm->get_relative().x,mm->get_relative().y);
- drag_accum = get_local_mouse_pos() - drag_origin;
+ drag_accum = get_local_mouse_position() - drag_origin;
for (int i = get_child_count() - 1; i >= 0; i--) {
GraphNode *gn = Object::cast_to<GraphNode>(get_child(i));
if (gn && gn->is_selected()) {
@@ -750,7 +749,7 @@ void GraphEdit::_gui_input(const Ref<InputEvent> &p_ev) {
}
if (mm.is_valid() && box_selecting) {
- box_selecting_to = get_local_mouse_pos();
+ box_selecting_to = get_local_mouse_position();
box_selecting_rect = Rect2(MIN(box_selecting_from.x, box_selecting_to.x),
MIN(box_selecting_from.y, box_selecting_to.y),
@@ -810,7 +809,7 @@ void GraphEdit::_gui_input(const Ref<InputEvent> &p_ev) {
if (gn) {
Rect2 r = gn->get_rect();
r.size *= zoom;
- if (r.has_point(get_local_mouse_pos()))
+ if (r.has_point(get_local_mouse_position()))
gn->set_selected(false);
}
}
@@ -848,7 +847,7 @@ void GraphEdit::_gui_input(const Ref<InputEvent> &p_ev) {
if (gn_selected->is_resizing())
continue;
- if (gn_selected->has_point(gn_selected->get_local_mouse_pos())) {
+ if (gn_selected->has_point(gn_selected->get_local_mouse_position())) {
gn = gn_selected;
break;
}
@@ -862,7 +861,7 @@ void GraphEdit::_gui_input(const Ref<InputEvent> &p_ev) {
dragging = true;
drag_accum = Vector2();
- drag_origin = get_local_mouse_pos();
+ drag_origin = get_local_mouse_position();
just_selected = !gn->is_selected();
if (!gn->is_selected() && !Input::get_singleton()->is_key_pressed(KEY_CONTROL)) {
for (int i = 0; i < get_child_count(); i++) {
@@ -888,7 +887,7 @@ void GraphEdit::_gui_input(const Ref<InputEvent> &p_ev) {
return;
box_selecting = true;
- box_selecting_from = get_local_mouse_pos();
+ box_selecting_from = get_local_mouse_position();
if (b->get_control()) {
box_selection_mode_aditive = true;
previus_selected.clear();
@@ -941,17 +940,17 @@ void GraphEdit::_gui_input(const Ref<InputEvent> &p_ev) {
//too difficult to get right
//set_zoom(zoom/ZOOM_SCALE);
}
- if (b->get_button_index() == BUTTON_WHEEL_UP) {
- h_scroll->set_value(h_scroll->get_value() - h_scroll->get_page() * b->get_factor() / 8);
- }
- if (b->get_button_index() == BUTTON_WHEEL_DOWN) {
- h_scroll->set_value(h_scroll->get_value() + h_scroll->get_page() * b->get_factor() / 8);
+ if (b->get_button_index() == 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);
}
- if (b->get_button_index() == BUTTON_WHEEL_RIGHT) {
+ if (b->get_button_index() == BUTTON_WHEEL_DOWN && !Input::get_singleton()->is_key_pressed(KEY_SHIFT)) {
v_scroll->set_value(v_scroll->get_value() + v_scroll->get_page() * b->get_factor() / 8);
}
- if (b->get_button_index() == BUTTON_WHEEL_LEFT) {
- v_scroll->set_value(v_scroll->get_value() - v_scroll->get_page() * b->get_factor() / 8);
+ if (b->get_button_index() == BUTTON_WHEEL_RIGHT || (b->get_button_index() == BUTTON_WHEEL_DOWN && Input::get_singleton()->is_key_pressed(KEY_SHIFT))) {
+ h_scroll->set_value(h_scroll->get_value() + h_scroll->get_page() * b->get_factor() / 8);
+ }
+ if (b->get_button_index() == BUTTON_WHEEL_LEFT || (b->get_button_index() == BUTTON_WHEEL_UP && Input::get_singleton()->is_key_pressed(KEY_SHIFT))) {
+ h_scroll->set_value(h_scroll->get_value() - h_scroll->get_page() * b->get_factor() / 8);
}
}
@@ -1167,7 +1166,7 @@ void GraphEdit::_bind_methods() {
ADD_SIGNAL(MethodInfo("popup_request", PropertyInfo(Variant::VECTOR2, "p_position")));
ADD_SIGNAL(MethodInfo("duplicate_nodes_request"));
ADD_SIGNAL(MethodInfo("node_selected", PropertyInfo(Variant::OBJECT, "node")));
- ADD_SIGNAL(MethodInfo("connection_to_empty", PropertyInfo(Variant::STRING, "from"), PropertyInfo(Variant::INT, "from_slot"), PropertyInfo(Variant::VECTOR2, "release_pos")));
+ ADD_SIGNAL(MethodInfo("connection_to_empty", PropertyInfo(Variant::STRING, "from"), PropertyInfo(Variant::INT, "from_slot"), PropertyInfo(Variant::VECTOR2, "release_position")));
ADD_SIGNAL(MethodInfo("delete_nodes_request"));
ADD_SIGNAL(MethodInfo("_begin_node_move"));
ADD_SIGNAL(MethodInfo("_end_node_move"));
@@ -1182,7 +1181,7 @@ GraphEdit::GraphEdit() {
top_layer = memnew(GraphEditFilter(this));
add_child(top_layer);
top_layer->set_mouse_filter(MOUSE_FILTER_PASS);
- top_layer->set_area_as_parent_rect();
+ top_layer->set_anchors_and_margins_preset(Control::PRESET_WIDE);
top_layer->connect("draw", this, "_top_layer_draw");
top_layer->set_mouse_filter(MOUSE_FILTER_PASS);
top_layer->connect("gui_input", this, "_top_layer_input");
diff --git a/scene/gui/graph_node.cpp b/scene/gui/graph_node.cpp
index bef0808fd0..7655363631 100644
--- a/scene/gui/graph_node.cpp
+++ b/scene/gui/graph_node.cpp
@@ -208,8 +208,11 @@ void GraphNode::_notification(int p_what) {
Ref<Texture> close = get_icon("close");
Ref<Texture> resizer = get_icon("resizer");
int close_offset = get_constant("close_offset");
+ int close_h_offset = get_constant("close_h_offset");
+ Color close_color = get_color("close_color");
Ref<Font> title_font = get_font("title_font");
int title_offset = get_constant("title_offset");
+ int title_h_offset = get_constant("title_h_offset");
Color title_color = get_color("title_color");
Point2i icofs = -port->get_size() * 0.5;
int edgeofs = get_constant("port_offset");
@@ -236,10 +239,10 @@ void GraphNode::_notification(int p_what) {
if (show_close)
w -= close->get_width();
- draw_string(title_font, Point2(sb->get_margin(MARGIN_LEFT), -title_font->get_height() + title_font->get_ascent() + title_offset), title, title_color, w);
+ draw_string(title_font, Point2(sb->get_margin(MARGIN_LEFT) + title_h_offset, -title_font->get_height() + title_font->get_ascent() + title_offset), title, title_color, w);
if (show_close) {
- Vector2 cpos = Point2(w + sb->get_margin(MARGIN_LEFT), -close->get_height() + close_offset);
- draw_texture(close, cpos);
+ Vector2 cpos = Point2(w + sb->get_margin(MARGIN_LEFT) + close_h_offset, -close->get_height() + close_offset);
+ draw_texture(close, cpos, close_color);
close_rect.position = cpos;
close_rect.size = close->get_size();
} else {
@@ -515,7 +518,7 @@ int GraphNode::get_connection_output_count() {
return conn_output_cache.size();
}
-Vector2 GraphNode::get_connection_input_pos(int p_idx) {
+Vector2 GraphNode::get_connection_input_position(int p_idx) {
if (connpos_dirty)
_connpos_update();
@@ -545,7 +548,7 @@ Color GraphNode::get_connection_input_color(int p_idx) {
return conn_input_cache[p_idx].color;
}
-Vector2 GraphNode::get_connection_output_pos(int p_idx) {
+Vector2 GraphNode::get_connection_output_position(int p_idx) {
if (connpos_dirty)
_connpos_update();
@@ -687,10 +690,10 @@ void GraphNode::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_connection_output_count"), &GraphNode::get_connection_output_count);
ClassDB::bind_method(D_METHOD("get_connection_input_count"), &GraphNode::get_connection_input_count);
- ClassDB::bind_method(D_METHOD("get_connection_output_pos", "idx"), &GraphNode::get_connection_output_pos);
+ ClassDB::bind_method(D_METHOD("get_connection_output_position", "idx"), &GraphNode::get_connection_output_position);
ClassDB::bind_method(D_METHOD("get_connection_output_type", "idx"), &GraphNode::get_connection_output_type);
ClassDB::bind_method(D_METHOD("get_connection_output_color", "idx"), &GraphNode::get_connection_output_color);
- ClassDB::bind_method(D_METHOD("get_connection_input_pos", "idx"), &GraphNode::get_connection_input_pos);
+ ClassDB::bind_method(D_METHOD("get_connection_input_position", "idx"), &GraphNode::get_connection_input_position);
ClassDB::bind_method(D_METHOD("get_connection_input_type", "idx"), &GraphNode::get_connection_input_type);
ClassDB::bind_method(D_METHOD("get_connection_input_color", "idx"), &GraphNode::get_connection_input_color);
diff --git a/scene/gui/graph_node.h b/scene/gui/graph_node.h
index a606e47acd..a0840544dd 100644
--- a/scene/gui/graph_node.h
+++ b/scene/gui/graph_node.h
@@ -138,10 +138,10 @@ public:
int get_connection_input_count();
int get_connection_output_count();
- Vector2 get_connection_input_pos(int p_idx);
+ Vector2 get_connection_input_position(int p_idx);
int get_connection_input_type(int p_idx);
Color get_connection_input_color(int p_idx);
- Vector2 get_connection_output_pos(int p_idx);
+ Vector2 get_connection_output_position(int p_idx);
int get_connection_output_type(int p_idx);
Color get_connection_output_color(int p_idx);
diff --git a/scene/gui/item_list.cpp b/scene/gui/item_list.cpp
index 9a605c98f3..623a110263 100644
--- a/scene/gui/item_list.cpp
+++ b/scene/gui/item_list.cpp
@@ -489,7 +489,7 @@ void ItemList::_gui_input(const Ref<InputEvent> &p_event) {
if (mb->get_button_index() == BUTTON_RIGHT) {
- emit_signal("item_rmb_selected", i, pos);
+ emit_signal("item_rmb_selected", i, get_local_mouse_position());
}
} else {
@@ -500,7 +500,7 @@ void ItemList::_gui_input(const Ref<InputEvent> &p_event) {
if (items[i].selected && mb->get_button_index() == BUTTON_RIGHT) {
- emit_signal("item_rmb_selected", i, pos);
+ emit_signal("item_rmb_selected", i, get_local_mouse_position());
} else {
bool selected = !items[i].selected;
@@ -515,7 +515,7 @@ void ItemList::_gui_input(const Ref<InputEvent> &p_event) {
if (mb->get_button_index() == BUTTON_RIGHT) {
- emit_signal("item_rmb_selected", i, pos);
+ emit_signal("item_rmb_selected", i, get_local_mouse_position());
} else if (/*select_mode==SELECT_SINGLE &&*/ mb->is_doubleclick()) {
emit_signal("item_activated", i);
@@ -524,11 +524,6 @@ void ItemList::_gui_input(const Ref<InputEvent> &p_event) {
}
return;
- } else {
- Vector<int> sItems = get_selected_items();
- for (int i = 0; i < sItems.size(); i++) {
- unselect(sItems[i]);
- }
}
}
if (mb.is_valid() && mb->get_button_index() == BUTTON_WHEEL_UP && mb->is_pressed()) {
@@ -750,8 +745,8 @@ void ItemList::_notification(int p_what) {
Ref<StyleBox> bg = get_stylebox("bg");
int mw = scroll_bar->get_minimum_size().x;
- scroll_bar->set_anchor_and_margin(MARGIN_LEFT, ANCHOR_END, -mw + bg->get_margin(MARGIN_RIGHT));
- scroll_bar->set_anchor_and_margin(MARGIN_RIGHT, ANCHOR_END, -bg->get_margin(MARGIN_RIGHT));
+ scroll_bar->set_anchor_and_margin(MARGIN_LEFT, ANCHOR_END, -mw);
+ scroll_bar->set_anchor_and_margin(MARGIN_RIGHT, ANCHOR_END, 0);
scroll_bar->set_anchor_and_margin(MARGIN_TOP, ANCHOR_BEGIN, bg->get_margin(MARGIN_TOP));
scroll_bar->set_anchor_and_margin(MARGIN_BOTTOM, ANCHOR_END, -bg->get_margin(MARGIN_BOTTOM));
@@ -838,6 +833,10 @@ void ItemList::_notification(int p_what) {
if (fixed_column_width > 0)
minsize.x = fixed_column_width;
max_column_width = MAX(max_column_width, minsize.x);
+
+ // elements need to adapt to the selected size
+ minsize.y += vseparation;
+ minsize.x += hseparation;
items[i].rect_cache.size = minsize;
items[i].min_rect_cache.size = minsize;
}
@@ -851,7 +850,6 @@ void ItemList::_notification(int p_what) {
while (true) {
//repeat util all fits
- //print_line("try with "+itos(current_columns));
bool all_fit = true;
Vector2 ofs;
int col = 0;
@@ -866,13 +864,11 @@ void ItemList::_notification(int p_what) {
break;
}
- items[i].rect_cache = items[i].min_rect_cache;
if (same_column_width)
items[i].rect_cache.size.x = max_column_width;
items[i].rect_cache.position = ofs;
max_h = MAX(max_h, items[i].rect_cache.size.y);
ofs.x += items[i].rect_cache.size.x + hseparation;
- //print_line("item "+itos(i)+" ofs "+rtos(items[i].rect_cache.size.x));
col++;
if (col == current_columns) {
@@ -901,7 +897,6 @@ void ItemList::_notification(int p_what) {
auto_height_value = ofs.y + max_h + bg->get_minimum_size().height;
scroll_bar->set_max(max);
scroll_bar->set_page(page);
- //print_line("max: "+rtos(max)+" page "+rtos(page));
if (max <= page) {
scroll_bar->set_value(0);
scroll_bar->hide();
@@ -950,23 +945,23 @@ void ItemList::_notification(int p_what) {
if (items[i].selected) {
Rect2 r = rcache;
r.position += base_ofs;
+ r.position.y -= vseparation / 2;
+ r.size.y += vseparation;
+ r.position.x -= hseparation / 2;
+ r.size.x += hseparation;
- // Use stylebox to dimension potential bg color
- r.position.x -= sbsel->get_margin(MARGIN_LEFT);
- r.size.x += sbsel->get_margin(MARGIN_LEFT) + sbsel->get_margin(MARGIN_RIGHT);
- r.position.y -= sbsel->get_margin(MARGIN_TOP);
- r.size.y += sbsel->get_margin(MARGIN_TOP) + sbsel->get_margin(MARGIN_BOTTOM);
draw_style_box(sbsel, r);
}
-
if (items[i].custom_bg.a > 0.001) {
-
Rect2 r = rcache;
r.position += base_ofs;
// Size rect to make the align the temperature colors
r.position.y -= vseparation / 2;
r.size.y += vseparation;
+ r.position.x -= hseparation / 2;
+ r.size.x += hseparation;
+
draw_rect(r, items[i].custom_bg);
}
@@ -1103,12 +1098,16 @@ void ItemList::_notification(int p_what) {
Rect2 r = rcache;
r.position += base_ofs;
+ r.position.y -= vseparation / 2;
+ r.size.y += vseparation;
+ r.position.x -= hseparation / 2;
+ r.size.x += hseparation;
draw_style_box(cursor, r);
}
}
for (int i = 0; i < separators.size(); i++) {
- draw_line(Vector2(bg->get_margin(MARGIN_LEFT), base_ofs.y + separators[i]), Vector2(size.width - bg->get_margin(MARGIN_LEFT), base_ofs.y + separators[i]), guide_color);
+ draw_line(Vector2(bg->get_margin(MARGIN_LEFT), base_ofs.y + separators[i]), Vector2(size.width - bg->get_margin(MARGIN_RIGHT), base_ofs.y + separators[i]), guide_color);
}
}
}
@@ -1117,7 +1116,7 @@ void ItemList::_scroll_changed(double) {
update();
}
-int ItemList::get_item_at_pos(const Point2 &p_pos, bool p_exact) const {
+int ItemList::get_item_at_position(const Point2 &p_pos, bool p_exact) const {
Vector2 pos = p_pos;
Ref<StyleBox> bg = get_stylebox("bg");
@@ -1165,7 +1164,7 @@ bool ItemList::is_pos_at_end_of_items(const Point2 &p_pos) const {
String ItemList::get_tooltip(const Point2 &p_pos) const {
- int closest = get_item_at_pos(p_pos);
+ int closest = get_item_at_position(p_pos);
if (closest != -1) {
if (!items[closest].tooltip_enabled) {
@@ -1362,7 +1361,7 @@ void ItemList::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_auto_height", "enable"), &ItemList::set_auto_height);
ClassDB::bind_method(D_METHOD("has_auto_height"), &ItemList::has_auto_height);
- ClassDB::bind_method(D_METHOD("get_item_at_pos", "pos", "exact"), &ItemList::get_item_at_pos, DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("get_item_at_position", "position", "exact"), &ItemList::get_item_at_position, DEFVAL(false));
ClassDB::bind_method(D_METHOD("ensure_current_is_visible"), &ItemList::ensure_current_is_visible);
@@ -1395,7 +1394,7 @@ void ItemList::_bind_methods() {
BIND_ENUM_CONSTANT(SELECT_MULTI);
ADD_SIGNAL(MethodInfo("item_selected", PropertyInfo(Variant::INT, "index")));
- ADD_SIGNAL(MethodInfo("item_rmb_selected", PropertyInfo(Variant::INT, "index"), PropertyInfo(Variant::VECTOR2, "atpos")));
+ ADD_SIGNAL(MethodInfo("item_rmb_selected", PropertyInfo(Variant::INT, "index"), PropertyInfo(Variant::VECTOR2, "at_position")));
ADD_SIGNAL(MethodInfo("multi_selected", PropertyInfo(Variant::INT, "index"), PropertyInfo(Variant::BOOL, "selected")));
ADD_SIGNAL(MethodInfo("item_activated", PropertyInfo(Variant::INT, "index")));
diff --git a/scene/gui/item_list.h b/scene/gui/item_list.h
index 673b7d8956..ccdd705325 100644
--- a/scene/gui/item_list.h
+++ b/scene/gui/item_list.h
@@ -199,7 +199,7 @@ public:
int find_metadata(const Variant &p_metadata) const;
virtual String get_tooltip(const Point2 &p_pos) const;
- int get_item_at_pos(const Point2 &p_pos, bool p_exact = false) const;
+ int get_item_at_position(const Point2 &p_pos, bool p_exact = false) const;
bool is_pos_at_end_of_items(const Point2 &p_pos) const;
void set_icon_scale(real_t p_scale);
diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp
index 6a5f56c78c..40e2dba6c2 100644
--- a/scene/gui/line_edit.cpp
+++ b/scene/gui/line_edit.cpp
@@ -49,7 +49,7 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) {
if (b.is_valid()) {
if (b->is_pressed() && b->get_button_index() == BUTTON_RIGHT) {
- menu->set_position(get_global_transform().xform(get_local_mouse_pos()));
+ menu->set_position(get_global_transform().xform(get_local_mouse_position()));
menu->set_size(Vector2(1, 1));
menu->popup();
grab_focus();
@@ -161,13 +161,14 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) {
} break;
- case (KEY_Z): { // Simple One level undo
-
+ case (KEY_Z): { // undo / redo
if (editable) {
-
- undo();
+ if (k->get_shift()) {
+ redo();
+ } else {
+ undo();
+ }
}
-
} break;
case (KEY_U): { // Delete from start to cursor
@@ -175,7 +176,6 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) {
if (editable) {
selection_clear();
- undo_text = text;
text = text.substr(cursor_pos, text.length() - cursor_pos);
Ref<Font> font = get_font("font");
@@ -186,7 +186,7 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) {
cached_width += font->get_char_size(text[i]).width;
}
- set_cursor_pos(0);
+ set_cursor_position(0);
_text_changed();
}
@@ -205,7 +205,6 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) {
if (editable) {
selection_clear();
- undo_text = text;
text = text.substr(0, cursor_pos);
_text_changed();
}
@@ -245,7 +244,6 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) {
break;
if (selection.enabled) {
- undo_text = text;
selection_delete();
break;
}
@@ -273,10 +271,9 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) {
delete_text(cc, cursor_pos);
- set_cursor_pos(cc);
+ set_cursor_position(cc);
} else {
- undo_text = text;
delete_char();
}
@@ -297,7 +294,7 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) {
#ifdef APPLE_STYLE_KEYS
if (k->get_command()) {
- set_cursor_pos(0);
+ set_cursor_position(0);
} else if (k->get_alt()) {
#else
@@ -319,10 +316,10 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) {
cc--;
}
- set_cursor_pos(cc);
+ set_cursor_position(cc);
} else {
- set_cursor_pos(get_cursor_pos() - 1);
+ set_cursor_position(get_cursor_position() - 1);
}
shift_selection_check_post(k->get_shift());
@@ -341,7 +338,7 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) {
#ifdef APPLE_STYLE_KEYS
if (k->get_command()) {
- set_cursor_pos(text.length());
+ set_cursor_position(text.length());
} else if (k->get_alt()) {
#else
if (k->get_alt()) {
@@ -362,10 +359,10 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) {
cc++;
}
- set_cursor_pos(cc);
+ set_cursor_position(cc);
} else {
- set_cursor_pos(get_cursor_pos() + 1);
+ set_cursor_position(get_cursor_position() + 1);
}
shift_selection_check_post(k->get_shift());
@@ -382,7 +379,6 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) {
}
if (selection.enabled) {
- undo_text = text;
selection_delete();
break;
}
@@ -417,8 +413,7 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) {
delete_text(cursor_pos, cc);
} else {
- undo_text = text;
- set_cursor_pos(cursor_pos + 1);
+ set_cursor_position(cursor_pos + 1);
delete_char();
}
@@ -433,7 +428,7 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) {
case KEY_HOME: {
shift_selection_check_pre(k->get_shift());
- set_cursor_pos(0);
+ set_cursor_position(0);
shift_selection_check_post(k->get_shift());
} break;
case KEY_KP_1: {
@@ -446,7 +441,7 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) {
case KEY_END: {
shift_selection_check_pre(k->get_shift());
- set_cursor_pos(text.length());
+ set_cursor_position(text.length());
shift_selection_check_post(k->get_shift());
} break;
@@ -534,7 +529,7 @@ void LineEdit::_notification(int p_what) {
switch (p_what) {
#ifdef TOOLS_ENABLED
case NOTIFICATION_ENTER_TREE: {
- if (Engine::get_singleton()->is_editor_hint()) {
+ if (Engine::get_singleton()->is_editor_hint() && !get_tree()->is_node_being_edited(this)) {
cursor_set_blink_enabled(EDITOR_DEF("text_editor/cursor/caret_blink", false));
cursor_set_blink_speed(EDITOR_DEF("text_editor/cursor/caret_blink_speed", 0.65));
@@ -546,7 +541,7 @@ void LineEdit::_notification(int p_what) {
#endif
case NOTIFICATION_RESIZED: {
- set_cursor_pos(get_cursor_pos());
+ set_cursor_position(get_cursor_position());
} break;
case MainLoop::NOTIFICATION_WM_FOCUS_IN: {
@@ -601,7 +596,10 @@ void LineEdit::_notification(int p_what) {
} break;
case ALIGN_CENTER: {
- x_ofs = int(size.width - (cached_width)) / 2;
+ if (window_pos != 0)
+ x_ofs = style->get_offset().x;
+ else
+ x_ofs = int(size.width - (cached_width)) / 2;
} break;
case ALIGN_RIGHT: {
@@ -742,7 +740,7 @@ void LineEdit::_notification(int p_what) {
draw_caret = true;
}
- Point2 cursor_pos = Point2(get_cursor_pos(), 1) * get_minimum_size().height;
+ Point2 cursor_pos = Point2(get_cursor_position(), 1) * get_minimum_size().height;
OS::get_singleton()->set_ime_position(get_global_position() + cursor_pos);
OS::get_singleton()->set_ime_intermediate_text_callback(_ime_text_callback, this);
@@ -775,7 +773,6 @@ void LineEdit::copy_text() {
void LineEdit::cut_text() {
if (selection.enabled) {
- undo_text = text;
OS::get_singleton()->set_clipboard(text.substr(selection.begin, selection.end - selection.begin));
selection_delete();
}
@@ -795,23 +792,33 @@ void LineEdit::paste_text() {
}
void LineEdit::undo() {
-
- int old_cursor_pos = cursor_pos;
- text = undo_text;
-
- Ref<Font> font = get_font("font");
-
- cached_width = 0;
- for (int i = 0; i < text.length(); i++)
- cached_width += font->get_char_size(text[i]).width;
-
- if (old_cursor_pos > text.length()) {
- set_cursor_pos(text.length());
- } else {
- set_cursor_pos(old_cursor_pos);
+ if (undo_stack_pos == NULL) {
+ if (undo_stack.size() <= 1) {
+ return;
+ }
+ undo_stack_pos = undo_stack.back();
+ } else if (undo_stack_pos == undo_stack.front()) {
+ return;
}
+ undo_stack_pos = undo_stack_pos->prev();
+ TextOperation op = undo_stack_pos->get();
+ text = op.text;
+ set_cursor_position(op.cursor_pos);
+ _emit_text_change();
+}
- _text_changed();
+void LineEdit::redo() {
+ if (undo_stack_pos == NULL) {
+ return;
+ }
+ if (undo_stack_pos == undo_stack.back()) {
+ return;
+ }
+ undo_stack_pos = undo_stack_pos->next();
+ TextOperation op = undo_stack_pos->get();
+ text = op.text;
+ set_cursor_position(op.cursor_pos);
+ _emit_text_change();
}
void LineEdit::shift_selection_check_pre(bool p_shift) {
@@ -846,7 +853,10 @@ void LineEdit::set_cursor_at_pixel_pos(int p_x) {
} break;
case ALIGN_CENTER: {
- pixel_ofs = int(size.width - (cached_width)) / 2;
+ if (window_pos != 0)
+ pixel_ofs = int(style->get_offset().x);
+ else
+ pixel_ofs = int(size.width - (cached_width)) / 2;
} break;
case ALIGN_RIGHT: {
@@ -869,14 +879,14 @@ void LineEdit::set_cursor_at_pixel_pos(int p_x) {
ofs++;
}
- set_cursor_pos(ofs);
+ set_cursor_position(ofs);
/*
int new_cursor_pos=p_x;
int charwidth=draw_area->get_font_char_width(' ',0);
new_cursor_pos=( ( (new_cursor_pos-2)+ (charwidth/2) ) /charwidth );
if (new_cursor_pos>(int)text.length()) new_cursor_pos=text.length();
- set_cursor_pos(window_pos+new_cursor_pos); */
+ set_cursor_position(window_pos+new_cursor_pos); */
}
bool LineEdit::cursor_get_blink_enabled() const {
@@ -929,7 +939,7 @@ void LineEdit::delete_char() {
text.erase(cursor_pos - 1, 1);
- set_cursor_pos(get_cursor_pos() - 1);
+ set_cursor_position(get_cursor_position() - 1);
if (cursor_pos == window_pos) {
@@ -941,8 +951,6 @@ void LineEdit::delete_char() {
void LineEdit::delete_text(int p_from_column, int p_to_column) {
- undo_text = text;
-
if (text.size() > 0) {
Ref<Font> font = get_font("font");
if (font != NULL) {
@@ -1011,7 +1019,7 @@ float LineEdit::get_placeholder_alpha() const {
return placeholder_alpha;
}
-void LineEdit::set_cursor_pos(int p_pos) {
+void LineEdit::set_cursor_position(int p_pos) {
if (p_pos > (int)text.length())
p_pos = text.length();
@@ -1030,9 +1038,11 @@ void LineEdit::set_cursor_pos(int p_pos) {
Ref<StyleBox> style = get_stylebox("normal");
Ref<Font> font = get_font("font");
- if (cursor_pos < window_pos) {
+ if (cursor_pos <= window_pos) {
/* Adjust window if cursor goes too much to the left */
- set_window_pos(cursor_pos);
+ if (window_pos > 0)
+ set_window_pos(window_pos - 1);
+
} else if (cursor_pos > window_pos) {
/* Adjust window if cursor goes too much to the right */
int window_width = get_size().width - style->get_minimum_size().width;
@@ -1065,7 +1075,7 @@ void LineEdit::set_cursor_pos(int p_pos) {
update();
}
-int LineEdit::get_cursor_pos() const {
+int LineEdit::get_cursor_position() const {
return cursor_pos;
}
@@ -1080,8 +1090,6 @@ void LineEdit::append_at_cursor(String p_text) {
if ((max_length <= 0) || (text.length() + p_text.length() <= max_length)) {
- undo_text = text;
-
Ref<Font> font = get_font("font");
if (font != NULL) {
for (int i = 0; i < p_text.length(); i++)
@@ -1093,12 +1101,13 @@ void LineEdit::append_at_cursor(String p_text) {
String pre = text.substr(0, cursor_pos);
String post = text.substr(cursor_pos, text.length() - cursor_pos);
text = pre + p_text + post;
- set_cursor_pos(cursor_pos + p_text.length());
+ set_cursor_position(cursor_pos + p_text.length());
}
}
void LineEdit::clear_internal() {
+ _clear_undo_stack();
cached_width = 0;
cursor_pos = 0;
window_pos = 0;
@@ -1269,6 +1278,11 @@ void LineEdit::menu_option(int p_option) {
undo();
}
} break;
+ case MENU_REDO: {
+ if (editable) {
+ redo();
+ }
+ }
}
}
@@ -1306,10 +1320,43 @@ void LineEdit::_text_changed() {
if (expand_to_text_length)
minimum_size_changed();
+ _emit_text_change();
+ _clear_redo();
+}
+
+void LineEdit::_emit_text_change() {
emit_signal("text_changed", text);
_change_notify("text");
}
+void LineEdit::_clear_redo() {
+ _create_undo_state();
+ if (undo_stack_pos == NULL) {
+ return;
+ }
+
+ undo_stack_pos = undo_stack_pos->next();
+ while (undo_stack_pos) {
+ List<TextOperation>::Element *elem = undo_stack_pos;
+ undo_stack_pos = undo_stack_pos->next();
+ undo_stack.erase(elem);
+ }
+ _create_undo_state();
+}
+
+void LineEdit::_clear_undo_stack() {
+ undo_stack.clear();
+ undo_stack_pos = NULL;
+ _create_undo_state();
+}
+
+void LineEdit::_create_undo_state() {
+ TextOperation op;
+ op.text = text;
+ op.cursor_pos = cursor_pos;
+ undo_stack.push_back(op);
+}
+
void LineEdit::_bind_methods() {
ClassDB::bind_method(D_METHOD("_toggle_draw_caret"), &LineEdit::_toggle_draw_caret);
@@ -1330,8 +1377,8 @@ void LineEdit::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_placeholder"), &LineEdit::get_placeholder);
ClassDB::bind_method(D_METHOD("set_placeholder_alpha", "alpha"), &LineEdit::set_placeholder_alpha);
ClassDB::bind_method(D_METHOD("get_placeholder_alpha"), &LineEdit::get_placeholder_alpha);
- ClassDB::bind_method(D_METHOD("set_cursor_pos", "pos"), &LineEdit::set_cursor_pos);
- ClassDB::bind_method(D_METHOD("get_cursor_pos"), &LineEdit::get_cursor_pos);
+ ClassDB::bind_method(D_METHOD("set_cursor_position", "position"), &LineEdit::set_cursor_position);
+ ClassDB::bind_method(D_METHOD("get_cursor_position"), &LineEdit::get_cursor_position);
ClassDB::bind_method(D_METHOD("set_expand_to_text_length", "enabled"), &LineEdit::set_expand_to_text_length);
ClassDB::bind_method(D_METHOD("get_expand_to_text_length"), &LineEdit::get_expand_to_text_length);
ClassDB::bind_method(D_METHOD("cursor_set_blink_enabled", "enabled"), &LineEdit::cursor_set_blink_enabled);
@@ -1363,6 +1410,7 @@ void LineEdit::_bind_methods() {
BIND_ENUM_CONSTANT(MENU_CLEAR);
BIND_ENUM_CONSTANT(MENU_SELECT_ALL);
BIND_ENUM_CONSTANT(MENU_UNDO);
+ BIND_ENUM_CONSTANT(MENU_REDO);
BIND_ENUM_CONSTANT(MENU_MAX);
ADD_PROPERTYNZ(PropertyInfo(Variant::STRING, "text"), "set_text", "get_text");
@@ -1382,6 +1430,8 @@ void LineEdit::_bind_methods() {
LineEdit::LineEdit() {
+ undo_stack_pos = NULL;
+ _create_undo_state();
align = ALIGN_LEFT;
cached_width = 0;
cursor_pos = 0;
@@ -1415,6 +1465,7 @@ LineEdit::LineEdit() {
menu->add_item(TTR("Clear"), MENU_CLEAR);
menu->add_separator();
menu->add_item(TTR("Undo"), MENU_UNDO, KEY_MASK_CMD | KEY_Z);
+ menu->add_item(TTR("Redo"), MENU_REDO, KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_Z);
menu->connect("id_pressed", this, "menu_option");
expand_to_text_length = false;
}
diff --git a/scene/gui/line_edit.h b/scene/gui/line_edit.h
index 52a4a29a33..bece29a37d 100644
--- a/scene/gui/line_edit.h
+++ b/scene/gui/line_edit.h
@@ -56,6 +56,7 @@ public:
MENU_CLEAR,
MENU_SELECT_ALL,
MENU_UNDO,
+ MENU_REDO,
MENU_MAX
};
@@ -92,10 +93,22 @@ private:
bool drag_attempt;
} selection;
+ struct TextOperation {
+ int cursor_pos;
+ String text;
+ };
+ List<TextOperation> undo_stack;
+ List<TextOperation>::Element *undo_stack_pos;
+
+ void _clear_undo_stack();
+ void _clear_redo();
+ void _create_undo_state();
+
Timer *caret_blink_timer;
static void _ime_text_callback(void *p_self, String p_text, Point2 p_selection);
void _text_changed();
+ void _emit_text_change();
bool expand_to_text_length;
bool caret_blink_enabled;
@@ -149,8 +162,8 @@ public:
String get_placeholder() const;
void set_placeholder_alpha(float p_alpha);
float get_placeholder_alpha() const;
- void set_cursor_pos(int p_pos);
- int get_cursor_pos() const;
+ void set_cursor_position(int p_pos);
+ int get_cursor_position() const;
void set_max_length(int p_max_length);
int get_max_length() const;
void append_at_cursor(String p_text);
@@ -166,6 +179,7 @@ public:
void cut_text();
void paste_text();
void undo();
+ void redo();
void set_editable(bool p_editable);
bool is_editable() const;
diff --git a/scene/gui/patch_9_rect.cpp b/scene/gui/nine_patch_rect.cpp
index 92c34dd3f9..c02d80bba8 100644
--- a/scene/gui/patch_9_rect.cpp
+++ b/scene/gui/nine_patch_rect.cpp
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* patch_9_rect.cpp */
+/* nine_patch_rect.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -27,7 +27,7 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "patch_9_rect.h"
+#include "nine_patch_rect.h"
#include "servers/visual_server.h"
diff --git a/scene/gui/patch_9_rect.h b/scene/gui/nine_patch_rect.h
index 808b7a1f5d..809daf9db3 100644
--- a/scene/gui/patch_9_rect.h
+++ b/scene/gui/nine_patch_rect.h
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* patch_9_rect.h */
+/* nine_patch_rect.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -27,8 +27,8 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef PATCH_9_FRAME_H
-#define PATCH_9_FRAME_H
+#ifndef NINE_PATCH_RECT_H
+#define NINE_PATCH_RECT_H
#include "scene/gui/control.h"
/**
@@ -81,4 +81,4 @@ public:
};
VARIANT_ENUM_CAST(NinePatchRect::AxisStretchMode)
-#endif // PATCH_9_FRAME_H
+#endif // NINE_PATCH_RECT_H
diff --git a/scene/gui/popup.cpp b/scene/gui/popup.cpp
index 5a2a552943..2110298950 100644
--- a/scene/gui/popup.cpp
+++ b/scene/gui/popup.cpp
@@ -265,7 +265,7 @@ void PopupPanel::set_child_rect(Control *p_child) {
ERR_FAIL_NULL(p_child);
Ref<StyleBox> p = get_stylebox("panel");
- p_child->set_area_as_parent_rect();
+ p_child->set_anchors_preset(Control::PRESET_WIDE);
p_child->set_margin(MARGIN_LEFT, p->get_margin(MARGIN_LEFT));
p_child->set_margin(MARGIN_RIGHT, -p->get_margin(MARGIN_RIGHT));
p_child->set_margin(MARGIN_TOP, p->get_margin(MARGIN_TOP));
diff --git a/scene/gui/range.cpp b/scene/gui/range.cpp
index 1dbec6e5a1..f8fb786fa7 100644
--- a/scene/gui/range.cpp
+++ b/scene/gui/range.cpp
@@ -208,10 +208,12 @@ void Range::_ref_shared(Shared *p_shared) {
void Range::_unref_shared() {
- shared->owners.erase(this);
- if (shared->owners.size() == 0) {
- memdelete(shared);
- shared = NULL;
+ if (shared) {
+ shared->owners.erase(this);
+ if (shared->owners.size() == 0) {
+ memdelete(shared);
+ shared = NULL;
+ }
}
}
diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp
index 71b9c4ec72..798acb9d52 100644
--- a/scene/gui/rich_text_label.cpp
+++ b/scene/gui/rich_text_label.cpp
@@ -84,7 +84,7 @@ Rect2 RichTextLabel::_get_text_rect() {
Ref<StyleBox> style = get_stylebox("normal");
return Rect2(style->get_offset(), get_size() - style->get_minimum_size());
}
-void RichTextLabel::_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, Item **r_click_item, int *r_click_char, bool *r_outside, int p_char_count) {
+int RichTextLabel::_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, Item **r_click_item, int *r_click_char, bool *r_outside, int p_char_count) {
RID ci;
if (r_outside)
@@ -104,9 +104,11 @@ void RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int
int line = 0;
int spaces = 0;
+ int height = get_size().y;
+
if (p_mode != PROCESS_CACHE) {
- ERR_FAIL_INDEX(line, l.offset_caches.size());
+ ERR_FAIL_INDEX_V(line, l.offset_caches.size(), 0);
line_ofs = l.offset_caches[line];
}
@@ -133,12 +135,20 @@ void RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int
//line height should be the font height for the first time, this ensures that an empty line will never have zero height and successive newlines are displayed
int line_height = cfont->get_height();
+ int nonblank_line_count = 0; //number of nonblank lines as counted during PROCESS_DRAW
+
Variant meta;
+#define RETURN return nonblank_line_count
+
#define NEW_LINE \
{ \
if (p_mode != PROCESS_CACHE) { \
line++; \
+ if (!line_is_blank) { \
+ nonblank_line_count++; \
+ } \
+ line_is_blank = true; \
if (line < l.offset_caches.size()) \
line_ofs = l.offset_caches[line]; \
wofs = margin; \
@@ -168,7 +178,7 @@ void RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int
if (r_outside) *r_outside = true; \
*r_click_item = it; \
*r_click_char = rchar; \
- return; \
+ RETURN; \
} \
}
@@ -185,7 +195,7 @@ void RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int
if (r_outside) *r_outside = true; \
*r_click_item = it; \
*r_click_char = rchar; \
- return; \
+ RETURN; \
} \
NEW_LINE \
}
@@ -196,7 +206,7 @@ void RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int
if (r_outside) *r_outside = false; \
*r_click_item = it; \
*r_click_char = rchar; \
- return; \
+ RETURN; \
} \
wofs += m_width; \
}
@@ -206,6 +216,9 @@ void RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int
line_height = m_height; \
}
+#define YRANGE_VISIBLE(m_top, m_height) \
+ (m_height > 0 && ((m_top >= 0 && m_top < height) || ((m_top + m_height - 1) >= 0 && (m_top + m_height - 1) < height)))
+
Color selection_fg;
Color selection_bg;
@@ -214,8 +227,10 @@ void RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int
selection_fg = get_color("font_color_selected");
selection_bg = get_color("selection_color");
}
+
int rchar = 0;
int lh = 0;
+ bool line_is_blank = true;
while (it) {
@@ -327,7 +342,10 @@ void RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int
int cw = 0;
- bool visible = visible_characters < 0 || p_char_count < visible_characters;
+ bool visible = visible_characters < 0 || p_char_count < visible_characters && YRANGE_VISIBLE(y + lh - (fh - 0 * ascent), fh); //getting rid of ascent seems to work??
+ if (visible)
+ line_is_blank = false;
+
if (c[i] == '\t')
visible = false;
@@ -336,7 +354,7 @@ void RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int
cw = font->get_char_size(c[i], c[i + 1]).x;
draw_rect(Rect2(p_ofs.x + pofs, p_ofs.y + y, cw, lh), selection_bg);
if (visible)
- font->draw_char(ci, p_ofs + Point2(align_ofs + pofs, y + lh - (fh - ascent)), c[i], c[i + 1], selection_fg);
+ font->draw_char(ci, p_ofs + Point2(align_ofs + pofs, y + lh - (fh - ascent)), c[i], c[i + 1], override_selected_font_color ? selection_fg : color);
} else {
if (visible)
@@ -384,7 +402,9 @@ void RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int
ENSURE_WIDTH(img->image->get_width());
- bool visible = visible_characters < 0 || p_char_count < visible_characters;
+ bool visible = visible_characters < 0 || p_char_count < visible_characters && YRANGE_VISIBLE(y + lh - font->get_descent() - img->image->get_height(), img->image->get_height());
+ if (visible)
+ line_is_blank = false;
if (p_mode == PROCESS_DRAW && visible) {
img->image->draw(ci, p_ofs + Point2(align_ofs + wofs, y + lh - font->get_descent() - img->image->get_height()));
@@ -398,8 +418,10 @@ void RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int
case ITEM_NEWLINE: {
lh = 0;
- if (p_mode != PROCESS_CACHE)
+ if (p_mode != PROCESS_CACHE) {
lh = line < l.height_caches.size() ? l.height_caches[line] : 1;
+ line_is_blank = true;
+ }
} break;
case ITEM_TABLE: {
@@ -436,7 +458,7 @@ void RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int
idx++;
}
- //compute available width and total radio (for expanders)
+ //compute available width and total ratio (for expanders)
int total_ratio = 0;
int available_width = p_width - hseparation * (table->columns.size() - 1);
@@ -494,14 +516,19 @@ void RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int
int lines_ofs = p_ofs.y + offset.y + draw_ofs.y;
bool visible = lines_ofs < get_size().height && lines_ofs + lines_h >= 0;
+ if (visible)
+ line_is_blank = false;
for (int i = 0; i < frame->lines.size(); i++) {
if (visible) {
if (p_mode == PROCESS_DRAW) {
- _process_line(frame, p_ofs + offset + draw_ofs + Vector2(0, yofs), ly, table->columns[column].width, i, PROCESS_DRAW, cfont, ccolor);
+ nonblank_line_count += _process_line(frame, p_ofs + offset + draw_ofs + Vector2(0, yofs), ly, table->columns[column].width, i, PROCESS_DRAW, cfont, ccolor);
} else if (p_mode == PROCESS_POINTER) {
_process_line(frame, p_ofs + offset + draw_ofs + Vector2(0, yofs), ly, table->columns[column].width, i, PROCESS_POINTER, cfont, ccolor, p_click_pos, r_click_item, r_click_char, r_outside);
+ if (r_click_item && *r_click_item) {
+ RETURN; // exit early
+ }
}
}
@@ -547,15 +574,17 @@ void RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int
if (r_outside) *r_outside = true;
*r_click_item = itp;
*r_click_char = rchar;
- return;
+ RETURN;
}
break;
}
}
-
NEW_LINE;
+ RETURN;
+
+#undef RETURN
#undef NEW_LINE
#undef ENSURE_WIDTH
#undef ADVANCE
@@ -665,14 +694,14 @@ void RichTextLabel::_notification(int p_what) {
if (from_line >= main->lines.size())
break; //nothing to draw
-
int y = (main->lines[from_line].height_accum_cache - main->lines[from_line].height_cache) - ofs;
Ref<Font> base_font = get_font("normal_font");
Color base_color = get_color("default_color");
+ visible_line_count = 0;
while (y < size.height && from_line < main->lines.size()) {
- _process_line(main, text_rect.get_position(), y, text_rect.get_size().width - scroll_w, from_line, PROCESS_DRAW, base_font, base_color, Point2i(), NULL, NULL, NULL, total_chars);
+ visible_line_count += _process_line(main, text_rect.get_position(), y, text_rect.get_size().width - scroll_w, from_line, PROCESS_DRAW, base_font, base_color, Point2i(), NULL, NULL, NULL, total_chars);
total_chars += main->lines[from_line].char_count;
from_line++;
}
@@ -1013,7 +1042,7 @@ void RichTextLabel::_validate_line_caches(ItemFrame *p_frame) {
if (p_frame->first_invalid_line == p_frame->lines.size())
return;
- //validate invalid lines!s
+ //validate invalid lines
Size2 size = get_size();
Rect2 text_rect = _get_text_rect();
@@ -1169,8 +1198,9 @@ void RichTextLabel::add_newline() {
return;
ItemNewline *item = memnew(ItemNewline);
item->line = current_frame->lines.size();
- current_frame->lines.resize(current_frame->lines.size() + 1);
_add_item(item, false);
+ current_frame->lines.resize(current_frame->lines.size() + 1);
+ _invalidate_current_line(current_frame);
}
bool RichTextLabel::remove_line(const int p_line) {
@@ -1350,6 +1380,16 @@ bool RichTextLabel::is_meta_underlined() const {
return underline_meta;
}
+void RichTextLabel::set_override_selected_font_color(bool p_override_selected_font_color) {
+
+ override_selected_font_color = p_override_selected_font_color;
+}
+
+bool RichTextLabel::is_overriding_selected_font_color() const {
+
+ return override_selected_font_color;
+}
+
void RichTextLabel::set_offset(int p_pixel) {
vscroll->set_value(p_pixel);
@@ -1665,6 +1705,12 @@ int RichTextLabel::get_line_count() const {
return current_frame->lines.size();
}
+int RichTextLabel::get_visible_line_count() const {
+ if (!is_visible())
+ return 0;
+ return visible_line_count;
+}
+
void RichTextLabel::set_selection_enabled(bool p_enabled) {
selection.enabled = p_enabled;
@@ -1874,6 +1920,9 @@ void RichTextLabel::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_meta_underline", "enable"), &RichTextLabel::set_meta_underline);
ClassDB::bind_method(D_METHOD("is_meta_underlined"), &RichTextLabel::is_meta_underlined);
+ ClassDB::bind_method(D_METHOD("set_override_selected_font_color", "override"), &RichTextLabel::set_override_selected_font_color);
+ ClassDB::bind_method(D_METHOD("is_overriding_selected_font_color"), &RichTextLabel::is_overriding_selected_font_color);
+
ClassDB::bind_method(D_METHOD("set_scroll_active", "active"), &RichTextLabel::set_scroll_active);
ClassDB::bind_method(D_METHOD("is_scroll_active"), &RichTextLabel::is_scroll_active);
@@ -1907,14 +1956,18 @@ void RichTextLabel::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_use_bbcode", "enable"), &RichTextLabel::set_use_bbcode);
ClassDB::bind_method(D_METHOD("is_using_bbcode"), &RichTextLabel::is_using_bbcode);
+ ClassDB::bind_method(D_METHOD("get_line_count"), &RichTextLabel::get_line_count);
+ ClassDB::bind_method(D_METHOD("get_visible_line_count"), &RichTextLabel::get_visible_line_count);
+
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_PROPERTY(PropertyInfo(Variant::BOOL, "override_selected_font_color"), "set_override_selected_font_color", "is_overriding_selected_font_color");
- ADD_SIGNAL(MethodInfo("meta_clicked", PropertyInfo(Variant::NIL, "meta")));
+ ADD_SIGNAL(MethodInfo("meta_clicked", PropertyInfo(Variant::NIL, "meta", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NIL_IS_VARIANT)));
BIND_ENUM_CONSTANT(ALIGN_LEFT);
BIND_ENUM_CONSTANT(ALIGN_CENTER);
@@ -1935,6 +1988,7 @@ void RichTextLabel::_bind_methods() {
BIND_ENUM_CONSTANT(ITEM_ALIGN);
BIND_ENUM_CONSTANT(ITEM_INDENT);
BIND_ENUM_CONSTANT(ITEM_LIST);
+ BIND_ENUM_CONSTANT(ITEM_TABLE);
BIND_ENUM_CONSTANT(ITEM_META);
}
@@ -1968,6 +2022,7 @@ RichTextLabel::RichTextLabel() {
tab_size = 4;
default_align = ALIGN_LEFT;
underline_meta = true;
+ override_selected_font_color = false;
scroll_visible = false;
scroll_follow = false;
@@ -1995,6 +2050,7 @@ RichTextLabel::RichTextLabel() {
visible_characters = -1;
percent_visible = 1;
+ visible_line_count = 0;
set_clip_contents(true);
}
diff --git a/scene/gui/rich_text_label.h b/scene/gui/rich_text_label.h
index 4db2c3a8e9..f9e37b1094 100644
--- a/scene/gui/rich_text_label.h
+++ b/scene/gui/rich_text_label.h
@@ -217,9 +217,11 @@ private:
int scroll_w;
bool updating_scroll;
int current_idx;
+ int visible_line_count;
int tab_size;
bool underline_meta;
+ bool override_selected_font_color;
Align default_align;
@@ -260,7 +262,7 @@ private:
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);
+ int _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);
Ref<Font> _find_font(Item *p_item);
@@ -312,6 +314,9 @@ public:
void set_meta_underline(bool p_underline);
bool is_meta_underlined() const;
+ void set_override_selected_font_color(bool p_override_selected_font_color);
+ bool is_overriding_selected_font_color() const;
+
void set_scroll_active(bool p_active);
bool is_scroll_active() const;
@@ -325,6 +330,7 @@ public:
void scroll_to_line(int p_line);
int get_line_count() const;
+ int get_visible_line_count() const;
VScrollBar *get_v_scroll() { return vscroll; }
diff --git a/scene/gui/scroll_bar.cpp b/scene/gui/scroll_bar.cpp
index 16d1b320b7..c5ffec2d5e 100644
--- a/scene/gui/scroll_bar.cpp
+++ b/scene/gui/scroll_bar.cpp
@@ -106,14 +106,14 @@ void ScrollBar::_gui_input(Ref<InputEvent> p_event) {
if (ofs < grabber_ofs) {
if (scrolling) {
- target_scroll = target_scroll - get_page();
+ target_scroll = CLAMP(target_scroll - get_page(), get_min(), get_max() - get_page());
} else {
- target_scroll = get_value() - get_page();
+ target_scroll = CLAMP(get_value() - get_page(), get_min(), get_max() - get_page());
}
if (smooth_scroll_enabled) {
scrolling = true;
- set_fixed_process(true);
+ set_physics_process(true);
} else {
set_value(target_scroll);
}
@@ -130,14 +130,14 @@ void ScrollBar::_gui_input(Ref<InputEvent> p_event) {
update();
} else {
if (scrolling) {
- target_scroll = target_scroll + get_page();
+ target_scroll = CLAMP(target_scroll + get_page(), get_min(), get_max() - get_page());
} else {
- target_scroll = get_value() + get_page();
+ target_scroll = CLAMP(get_value() + get_page(), get_min(), get_max() - get_page());
}
if (smooth_scroll_enabled) {
scrolling = true;
- set_fixed_process(true);
+ set_physics_process(true);
} else {
set_value(target_scroll);
}
@@ -335,29 +335,29 @@ void ScrollBar::_notification(int p_what) {
drag_slave = NULL;
}
- if (p_what == NOTIFICATION_FIXED_PROCESS) {
+ if (p_what == NOTIFICATION_PHYSICS_PROCESS) {
if (scrolling) {
if (get_value() != target_scroll) {
double target = target_scroll - get_value();
double dist = sqrt(target * target);
- double vel = ((target / dist) * 500) * get_fixed_process_delta_time();
+ double vel = ((target / dist) * 500) * get_physics_process_delta_time();
- if (vel >= dist) {
+ if (Math::abs(vel) >= dist) {
set_value(target_scroll);
} else {
set_value(get_value() + vel);
}
} else {
scrolling = false;
- set_fixed_process(false);
+ set_physics_process(false);
}
} else if (drag_slave_touching) {
if (drag_slave_touching_deaccel) {
Vector2 pos = Vector2(orientation == HORIZONTAL ? get_value() : 0, orientation == VERTICAL ? get_value() : 0);
- pos += drag_slave_speed * get_fixed_process_delta_time();
+ pos += drag_slave_speed * get_physics_process_delta_time();
bool turnoff = false;
@@ -377,7 +377,7 @@ void ScrollBar::_notification(int p_what) {
float sgn_x = drag_slave_speed.x < 0 ? -1 : 1;
float val_x = Math::abs(drag_slave_speed.x);
- val_x -= 1000 * get_fixed_process_delta_time();
+ val_x -= 1000 * get_physics_process_delta_time();
if (val_x < 0) {
turnoff = true;
@@ -401,7 +401,7 @@ void ScrollBar::_notification(int p_what) {
float sgn_y = drag_slave_speed.y < 0 ? -1 : 1;
float val_y = Math::abs(drag_slave_speed.y);
- val_y -= 1000 * get_fixed_process_delta_time();
+ val_y -= 1000 * get_physics_process_delta_time();
if (val_y < 0) {
turnoff = true;
@@ -410,7 +410,7 @@ void ScrollBar::_notification(int p_what) {
}
if (turnoff) {
- set_fixed_process(false);
+ set_physics_process(false);
drag_slave_touching = false;
drag_slave_touching_deaccel = false;
}
@@ -421,10 +421,10 @@ void ScrollBar::_notification(int p_what) {
Vector2 diff = drag_slave_accum - last_drag_slave_accum;
last_drag_slave_accum = drag_slave_accum;
- drag_slave_speed = diff / get_fixed_process_delta_time();
+ drag_slave_speed = diff / get_physics_process_delta_time();
}
- time_since_motion += get_fixed_process_delta_time();
+ time_since_motion += get_physics_process_delta_time();
}
}
}
@@ -579,7 +579,7 @@ void ScrollBar::_drag_slave_input(const Ref<InputEvent> &p_input) {
if (mb->is_pressed()) {
if (drag_slave_touching) {
- set_fixed_process(false);
+ set_physics_process(false);
drag_slave_touching_deaccel = false;
drag_slave_touching = false;
drag_slave_speed = Vector2();
@@ -599,7 +599,7 @@ void ScrollBar::_drag_slave_input(const Ref<InputEvent> &p_input) {
drag_slave_touching_deaccel = false;
time_since_motion = 0;
if (drag_slave_touching) {
- set_fixed_process(true);
+ set_physics_process(true);
time_since_motion = 0;
}
}
@@ -611,7 +611,7 @@ void ScrollBar::_drag_slave_input(const Ref<InputEvent> &p_input) {
if (drag_slave_speed == Vector2()) {
drag_slave_touching_deaccel = false;
drag_slave_touching = false;
- set_fixed_process(false);
+ set_physics_process(false);
} else {
drag_slave_touching_deaccel = true;
diff --git a/scene/gui/scroll_container.cpp b/scene/gui/scroll_container.cpp
index e182e491d3..1ad1e3f638 100644
--- a/scene/gui/scroll_container.cpp
+++ b/scene/gui/scroll_container.cpp
@@ -67,7 +67,7 @@ Size2 ScrollContainer::get_minimum_size() const {
};
void ScrollContainer::_cancel_drag() {
- set_fixed_process(false);
+ set_physics_process(false);
drag_touching_deaccel = false;
drag_touching = false;
drag_speed = Vector2();
@@ -121,7 +121,7 @@ void ScrollContainer::_gui_input(const Ref<InputEvent> &p_gui_input) {
if (mb->is_pressed()) {
if (drag_touching) {
- set_fixed_process(false);
+ set_physics_process(false);
drag_touching_deaccel = false;
drag_touching = false;
drag_speed = Vector2();
@@ -139,7 +139,7 @@ void ScrollContainer::_gui_input(const Ref<InputEvent> &p_gui_input) {
drag_touching_deaccel = false;
time_since_motion = 0;
if (drag_touching) {
- set_fixed_process(true);
+ set_physics_process(true);
time_since_motion = 0;
}
}
@@ -150,7 +150,7 @@ void ScrollContainer::_gui_input(const Ref<InputEvent> &p_gui_input) {
if (drag_speed == Vector2()) {
drag_touching_deaccel = false;
drag_touching = false;
- set_fixed_process(false);
+ set_physics_process(false);
} else {
drag_touching_deaccel = true;
@@ -182,7 +182,7 @@ void ScrollContainer::_gui_input(const Ref<InputEvent> &p_gui_input) {
}
}
-void ScrollContainer::_update_scrollbar_pos() {
+void ScrollContainer::_update_scrollbar_position() {
Size2 hmin = h_scroll->get_combined_minimum_size();
Size2 vmin = v_scroll->get_combined_minimum_size();
@@ -205,7 +205,7 @@ void ScrollContainer::_notification(int p_what) {
if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) {
- call_deferred("_update_scrollbar_pos");
+ call_deferred("_update_scrollbar_position");
};
if (p_what == NOTIFICATION_SORT_CHILDREN) {
@@ -257,14 +257,14 @@ void ScrollContainer::_notification(int p_what) {
update_scrollbars();
}
- if (p_what == NOTIFICATION_FIXED_PROCESS) {
+ if (p_what == NOTIFICATION_PHYSICS_PROCESS) {
if (drag_touching) {
if (drag_touching_deaccel) {
Vector2 pos = Vector2(h_scroll->get_value(), v_scroll->get_value());
- pos += drag_speed * get_fixed_process_delta_time();
+ pos += drag_speed * get_physics_process_delta_time();
bool turnoff_h = false;
bool turnoff_v = false;
@@ -294,7 +294,7 @@ void ScrollContainer::_notification(int p_what) {
float sgn_x = drag_speed.x < 0 ? -1 : 1;
float val_x = Math::abs(drag_speed.x);
- val_x -= 1000 * get_fixed_process_delta_time();
+ val_x -= 1000 * get_physics_process_delta_time();
if (val_x < 0) {
turnoff_h = true;
@@ -302,7 +302,7 @@ void ScrollContainer::_notification(int p_what) {
float sgn_y = drag_speed.y < 0 ? -1 : 1;
float val_y = Math::abs(drag_speed.y);
- val_y -= 1000 * get_fixed_process_delta_time();
+ val_y -= 1000 * get_physics_process_delta_time();
if (val_y < 0) {
turnoff_v = true;
@@ -311,7 +311,7 @@ void ScrollContainer::_notification(int p_what) {
drag_speed = Vector2(sgn_x * val_x, sgn_y * val_y);
if (turnoff_h && turnoff_v) {
- set_fixed_process(false);
+ set_physics_process(false);
drag_touching = false;
drag_touching_deaccel = false;
}
@@ -322,10 +322,10 @@ void ScrollContainer::_notification(int p_what) {
Vector2 diff = drag_accum - last_drag_accum;
last_drag_accum = drag_accum;
- drag_speed = diff / get_fixed_process_delta_time();
+ drag_speed = diff / get_physics_process_delta_time();
}
- time_since_motion += get_fixed_process_delta_time();
+ time_since_motion += get_physics_process_delta_time();
}
}
}
@@ -448,7 +448,7 @@ void ScrollContainer::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_h_scroll_enabled"), &ScrollContainer::is_h_scroll_enabled);
ClassDB::bind_method(D_METHOD("set_enable_v_scroll", "enable"), &ScrollContainer::set_enable_v_scroll);
ClassDB::bind_method(D_METHOD("is_v_scroll_enabled"), &ScrollContainer::is_v_scroll_enabled);
- ClassDB::bind_method(D_METHOD("_update_scrollbar_pos"), &ScrollContainer::_update_scrollbar_pos);
+ ClassDB::bind_method(D_METHOD("_update_scrollbar_position"), &ScrollContainer::_update_scrollbar_position);
ClassDB::bind_method(D_METHOD("set_h_scroll", "val"), &ScrollContainer::set_h_scroll);
ClassDB::bind_method(D_METHOD("get_h_scroll"), &ScrollContainer::get_h_scroll);
ClassDB::bind_method(D_METHOD("set_v_scroll", "val"), &ScrollContainer::set_v_scroll);
diff --git a/scene/gui/scroll_container.h b/scene/gui/scroll_container.h
index 9076be0d72..2c5d60de6c 100644
--- a/scene/gui/scroll_container.h
+++ b/scene/gui/scroll_container.h
@@ -70,7 +70,7 @@ protected:
void _scroll_moved(float);
static void _bind_methods();
- void _update_scrollbar_pos();
+ void _update_scrollbar_position();
public:
int get_v_scroll() const;
diff --git a/scene/gui/separator.cpp b/scene/gui/separator.cpp
index 3db234f7cc..55d837458a 100644
--- a/scene/gui/separator.cpp
+++ b/scene/gui/separator.cpp
@@ -32,7 +32,11 @@
Size2 Separator::get_minimum_size() const {
Size2 ms(3, 3);
- ms[orientation] = get_constant("separation");
+ if (orientation == VERTICAL) {
+ ms.x = get_constant("separation");
+ } else { // HORIZONTAL
+ ms.y = get_constant("separation");
+ }
return ms;
}
diff --git a/scene/gui/slider.cpp b/scene/gui/slider.cpp
index 8fda5df53c..e88742a3e3 100644
--- a/scene/gui/slider.cpp
+++ b/scene/gui/slider.cpp
@@ -157,6 +157,12 @@ void Slider::_notification(int p_what) {
mouse_inside = false;
update();
} break;
+ case NOTIFICATION_VISIBILITY_CHANGED: // fallthrough
+ case NOTIFICATION_EXIT_TREE: {
+
+ mouse_inside = false;
+ grab.active = false;
+ } break;
case NOTIFICATION_DRAW: {
RID ci = get_canvas_item();
Size2i size = get_size();
@@ -181,7 +187,7 @@ void Slider::_notification(int p_what) {
for (int i = 0; i < ticks; i++) {
if (!ticks_on_borders && (i == 0 || i + 1 == ticks)) continue;
int ofs = i * tickarea / (ticks - 1);
- tick->draw(ci, Point2(0, ofs));
+ tick->draw(ci, Point2i((size.width - widget_width) / 2, ofs));
}
}
grabber->draw(ci, Point2i(size.width / 2 - grabber->get_size().width / 2, size.height - get_as_ratio() * areasize - grabber->get_size().height));
@@ -202,7 +208,7 @@ void Slider::_notification(int p_what) {
for (int i = 0; i < ticks; i++) {
if ((!ticks_on_borders) && ((i == 0) || ((i + 1) == ticks))) continue;
int ofs = i * tickarea / (ticks - 1);
- tick->draw(ci, Point2(ofs, 0));
+ tick->draw(ci, Point2i(ofs, (size.height - widget_height) / 2));
}
}
grabber->draw(ci, Point2i(get_as_ratio() * areasize, size.height / 2 - grabber->get_size().height / 2));
diff --git a/scene/gui/spin_box.cpp b/scene/gui/spin_box.cpp
index f462989f53..05f2809bfc 100644
--- a/scene/gui/spin_box.cpp
+++ b/scene/gui/spin_box.cpp
@@ -72,7 +72,7 @@ void SpinBox::_range_click_timeout() {
if (!drag.enabled && Input::get_singleton()->is_mouse_button_pressed(BUTTON_LEFT)) {
- bool up = get_local_mouse_pos().y < (get_size().height / 2);
+ bool up = get_local_mouse_position().y < (get_size().height / 2);
set_value(get_value() + (up ? get_step() : -get_step()));
if (range_click_timer->is_one_shot()) {
@@ -268,7 +268,7 @@ SpinBox::SpinBox() {
line_edit = memnew(LineEdit);
add_child(line_edit);
- line_edit->set_area_as_parent_rect();
+ line_edit->set_anchors_and_margins_preset(Control::PRESET_WIDE);
//connect("value_changed",this,"_value_changed");
line_edit->connect("text_entered", this, "_text_entered", Vector<Variant>(), CONNECT_DEFERRED);
line_edit->connect("focus_exited", this, "_line_edit_focus_exit", Vector<Variant>(), CONNECT_DEFERRED);
diff --git a/scene/gui/tab_container.cpp b/scene/gui/tab_container.cpp
index 98a8db336e..581034ddee 100644
--- a/scene/gui/tab_container.cpp
+++ b/scene/gui/tab_container.cpp
@@ -90,19 +90,28 @@ void TabContainer::_gui_input(const Ref<InputEvent> &p_event) {
return;
}
+ // Do not activate tabs when tabs is empty
+ if (get_tab_count() == 0)
+ return;
+
Vector<Control *> tabs = _get_tabs();
// Handle navigation buttons.
if (buttons_visible_cache) {
+ int popup_ofs = 0;
+ if (popup) {
+ popup_ofs = menu->get_width();
+ }
+
Ref<Texture> increment = get_icon("increment");
Ref<Texture> decrement = get_icon("decrement");
- if (pos.x > size.width - increment->get_width()) {
+ if (pos.x > size.width - increment->get_width() - popup_ofs) {
if (last_tab_cache < tabs.size() - 1) {
first_tab_cache += 1;
update();
}
return;
- } else if (pos.x > size.width - increment->get_width() - decrement->get_width()) {
+ } else if (pos.x > size.width - increment->get_width() - decrement->get_width() - popup_ofs) {
if (first_tab_cache > 0) {
first_tab_cache -= 1;
update();
@@ -264,9 +273,9 @@ void TabContainer::_notification(int p_what) {
if (popup) {
x -= menu->get_width();
if (mouse_x_cache > x)
- menu_hl->draw(get_canvas_item(), Size2(x, 0));
+ menu_hl->draw(get_canvas_item(), Size2(x, (header_height - menu_hl->get_height()) / 2));
else
- menu->draw(get_canvas_item(), Size2(x, 0));
+ menu->draw(get_canvas_item(), Size2(x, (header_height - menu->get_height()) / 2));
}
// Draw the navigation buttons.
@@ -293,6 +302,8 @@ void TabContainer::_notification(int p_what) {
}
int TabContainer::_get_tab_width(int p_index) const {
+
+ ERR_FAIL_INDEX_V(p_index, get_tab_count(), 0);
Control *control = Object::cast_to<Control>(_get_tabs()[p_index]);
if (!control || control->is_set_as_toplevel())
return 0;
@@ -367,7 +378,7 @@ void TabContainer::add_child_notify(Node *p_child) {
current = 0;
previous = 0;
}
- c->set_area_as_parent_rect();
+ c->set_anchors_and_margins_preset(Control::PRESET_WIDE);
if (tabs_visible)
c->set_margin(MARGIN_TOP, _get_top_margin());
Ref<StyleBox> sb = get_stylebox("panel");
@@ -401,7 +412,7 @@ void TabContainer::set_current_tab(int p_current) {
Control *c = tabs[i];
if (i == current) {
c->show();
- c->set_area_as_parent_rect();
+ c->set_anchors_and_margins_preset(Control::PRESET_WIDE);
if (tabs_visible)
c->set_margin(MARGIN_TOP, _get_top_margin());
c->set_margin(Margin(MARGIN_TOP), c->get_margin(Margin(MARGIN_TOP)) + sb->get_margin(Margin(MARGIN_TOP)));
@@ -664,6 +675,7 @@ void TabContainer::_bind_methods() {
TabContainer::TabContainer() {
first_tab_cache = 0;
+ last_tab_cache = 0;
buttons_visible_cache = false;
tabs_ofs_cache = 0;
current = 0;
diff --git a/scene/gui/tabs.cpp b/scene/gui/tabs.cpp
index 085f6de6b8..49823e18fc 100644
--- a/scene/gui/tabs.cpp
+++ b/scene/gui/tabs.cpp
@@ -820,9 +820,9 @@ void Tabs::_bind_methods() {
BIND_ENUM_CONSTANT(ALIGN_RIGHT);
BIND_ENUM_CONSTANT(ALIGN_MAX);
+ BIND_ENUM_CONSTANT(CLOSE_BUTTON_SHOW_NEVER);
BIND_ENUM_CONSTANT(CLOSE_BUTTON_SHOW_ACTIVE_ONLY);
BIND_ENUM_CONSTANT(CLOSE_BUTTON_SHOW_ALWAYS);
- BIND_ENUM_CONSTANT(CLOSE_BUTTON_SHOW_NEVER);
BIND_ENUM_CONSTANT(CLOSE_BUTTON_MAX);
}
diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp
index 2ca4c81319..7d200a799b 100644
--- a/scene/gui/text_edit.cpp
+++ b/scene/gui/text_edit.cpp
@@ -376,24 +376,116 @@ void TextEdit::_update_scrollbars() {
void TextEdit::_click_selection_held() {
if (Input::get_singleton()->is_mouse_button_pressed(BUTTON_LEFT) && selection.selecting_mode != Selection::MODE_NONE) {
+ switch (selection.selecting_mode) {
+ case Selection::MODE_POINTER: {
+ _update_selection_mode_pointer();
+ } break;
+ case Selection::MODE_WORD: {
+ _update_selection_mode_word();
+ } break;
+ case Selection::MODE_LINE: {
+ _update_selection_mode_line();
+ } break;
+ default: {
+ break;
+ }
+ }
+ } else {
+ click_select_held->stop();
+ }
+}
- Point2 mp = Input::get_singleton()->get_mouse_position() - get_global_position();
+void TextEdit::_update_selection_mode_pointer() {
+ Point2 mp = Input::get_singleton()->get_mouse_position() - get_global_position();
- int row, col;
- _get_mouse_pos(Point2i(mp.x, mp.y), row, col);
+ int row, col;
+ _get_mouse_pos(Point2i(mp.x, mp.y), row, col);
- select(selection.selecting_line, selection.selecting_column, row, col);
+ select(selection.selecting_line, selection.selecting_column, row, col);
- cursor_set_line(row);
- cursor_set_column(col);
- update();
+ cursor_set_line(row);
+ cursor_set_column(col);
+ update();
+
+ click_select_held->start();
+}
- click_select_held->start();
+void TextEdit::_update_selection_mode_word() {
+ Point2 mp = Input::get_singleton()->get_mouse_position() - get_global_position();
+ int row, col;
+ _get_mouse_pos(Point2i(mp.x, mp.y), row, col);
+
+ String line = text[row];
+ int beg = CLAMP(col, 0, line.length());
+ // if its the first selection and on whitespace make sure we grab the word instead..
+ if (!selection.active) {
+ while (beg > 0 && line[beg] <= 32) {
+ beg--;
+ }
+ }
+ int end = beg;
+ bool symbol = beg < line.length() && _is_symbol(line[beg]);
+
+ // get the word end and begin points
+ while (beg > 0 && line[beg - 1] > 32 && (symbol == _is_symbol(line[beg - 1]))) {
+ beg--;
+ }
+ while (end < line.length() && line[end + 1] > 32 && (symbol == _is_symbol(line[end + 1]))) {
+ end++;
+ }
+ if (end < line.length()) {
+ end += 1;
+ }
+
+ // inital selection
+ if (!selection.active) {
+ select(row, beg, row, end);
+ selection.selecting_column = beg;
+ selection.selected_word_beg = beg;
+ selection.selected_word_end = end;
+ selection.selected_word_origin = beg;
+ cursor_set_column(selection.to_column);
} else {
+ if ((col <= selection.selected_word_origin && row == selection.selecting_line) || row < selection.selecting_line) {
+ selection.selecting_column = selection.selected_word_end;
+ select(row, beg, selection.selecting_line, selection.selected_word_end);
+ cursor_set_column(selection.from_column);
+ } else {
+ selection.selecting_column = selection.selected_word_beg;
+ select(selection.selecting_line, selection.selected_word_beg, row, end);
+ cursor_set_column(selection.to_column);
+ }
+ }
+ cursor_set_line(row);
- click_select_held->stop();
+ update();
+ click_select_held->start();
+}
+
+void TextEdit::_update_selection_mode_line() {
+ Point2 mp = Input::get_singleton()->get_mouse_position() - get_global_position();
+
+ int row, col;
+ _get_mouse_pos(Point2i(mp.x, mp.y), row, col);
+
+ col = 0;
+ if (row < selection.selecting_line) {
+ // cursor is above us
+ cursor_set_line(row - 1);
+ selection.selecting_column = text[selection.selecting_line].length();
+ } else {
+ // cursor is below us
+ cursor_set_line(row + 1);
+ selection.selecting_column = 0;
+ col = text[row].length();
}
+ cursor_set_column(0);
+
+ select(selection.selecting_line, selection.selecting_column, row, col);
+ update();
+
+ click_select_held->start();
}
void TextEdit::_notification(int p_what) {
@@ -428,22 +520,22 @@ void TextEdit::_notification(int p_what) {
draw_caret = false;
update();
} break;
- case NOTIFICATION_FIXED_PROCESS: {
+ case NOTIFICATION_PHYSICS_PROCESS: {
if (scrolling && v_scroll->get_value() != target_v_scroll) {
double target_y = target_v_scroll - v_scroll->get_value();
double dist = sqrt(target_y * target_y);
- double vel = ((target_y / dist) * v_scroll_speed) * get_fixed_process_delta_time();
+ double vel = ((target_y / dist) * v_scroll_speed) * get_physics_process_delta_time();
if (Math::abs(vel) >= dist) {
v_scroll->set_value(target_v_scroll);
scrolling = false;
- set_fixed_process(false);
+ set_physics_process(false);
} else {
v_scroll->set_value(v_scroll->get_value() + vel);
}
} else {
scrolling = false;
- set_fixed_process(false);
+ set_physics_process(false);
}
} break;
case NOTIFICATION_DRAW: {
@@ -501,8 +593,7 @@ void TextEdit::_notification(int p_what) {
if (cache.background_color.a > 0.01) {
- Point2i ofs = Point2i(cache.style_normal->get_offset()) / 2.0;
- VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(ofs, get_size() - cache.style_normal->get_minimum_size() + ofs), cache.background_color);
+ VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2i(), get_size()), cache.background_color);
}
//compute actual region to start (may be inside say, a comment).
//slow in very large documments :( but ok for source!
@@ -733,8 +824,17 @@ void TextEdit::_notification(int p_what) {
VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(xmargin_beg, ofs_y, xmargin_end - xmargin_beg, get_row_height()), cache.mark_color);
}
- if (line == cursor.line) {
- VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(0, ofs_y, xmargin_end, get_row_height()), cache.current_line_color);
+ if (str.length() == 0) {
+ // draw line background if empty as we won't loop at at all
+ if (line == cursor.line && highlight_current_line) {
+ VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(0, ofs_y, xmargin_end, get_row_height()), cache.current_line_color);
+ }
+
+ // give visual indication of empty selected line
+ if (selection.active && line >= selection.from_line && line <= selection.to_line) {
+ int char_w = cache.font->get_char_size(' ').width;
+ VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(xmargin_beg, ofs_y, char_w, get_row_height()), cache.selection_color);
+ }
}
if (text.is_breakpoint(line) && !draw_breakpoint_gutter) {
@@ -765,6 +865,7 @@ void TextEdit::_notification(int p_what) {
cache.font->draw(ci, Point2(cache.style_normal->get_margin(MARGIN_LEFT) + cache.breakpoint_gutter_width, ofs_y + cache.font->get_ascent()), fc, cache.line_number_color);
}
+ //loop through charcters in one line
for (int j = 0; j < str.length(); j++) {
//look for keyword
@@ -953,10 +1054,25 @@ void TextEdit::_notification(int p_what) {
}
}
+ //current line highlighting
bool in_selection = (selection.active && line >= selection.from_line && line <= selection.to_line && (line > selection.from_line || j >= selection.from_column) && (line < selection.to_line || j < selection.to_column));
+ if (line == cursor.line && highlight_current_line) {
+ // if its the first char draw behind line numbers
+ if (j == 0) {
+ VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(0, ofs_y, (char_ofs + char_margin), get_row_height()), cache.current_line_color);
+ }
+ // if its the last char draw to end of the line
+ if (j == str.length() - 1) {
+ VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(char_ofs + char_margin + char_w, ofs_y, xmargin_end - (char_ofs + char_margin + char_w), get_row_height()), cache.current_line_color);
+ }
+ // actual text
+ if (!in_selection) {
+ VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2i(char_ofs + char_margin, ofs_y), Size2i(char_w, get_row_height())), cache.current_line_color);
+ }
+ }
+
if (in_selection) {
- //inside selection!
VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2i(char_ofs + char_margin, ofs_y), Size2i(char_w, get_row_height())), cache.selection_color);
}
@@ -999,7 +1115,7 @@ void TextEdit::_notification(int p_what) {
if (brace_open_mismatch)
color = cache.brace_mismatch_color;
- cache.font->draw_char(ci, Point2i(char_ofs + char_margin, ofs_y + ascent), '_', str[j + 1], in_selection ? cache.font_selected_color : color);
+ cache.font->draw_char(ci, Point2i(char_ofs + char_margin, ofs_y + ascent), '_', str[j + 1], in_selection && override_selected_font_color ? cache.font_selected_color : color);
}
if (
@@ -1008,7 +1124,7 @@ void TextEdit::_notification(int p_what) {
if (brace_close_mismatch)
color = cache.brace_mismatch_color;
- cache.font->draw_char(ci, Point2i(char_ofs + char_margin, ofs_y + ascent), '_', str[j + 1], in_selection ? cache.font_selected_color : color);
+ cache.font->draw_char(ci, Point2i(char_ofs + char_margin, ofs_y + ascent), '_', str[j + 1], in_selection && override_selected_font_color ? cache.font_selected_color : color);
}
}
@@ -1067,15 +1183,15 @@ void TextEdit::_notification(int p_what) {
}
if (str[j] >= 32) {
- int w = cache.font->draw_char(ci, Point2i(char_ofs + char_margin, ofs_y + ascent), str[j], str[j + 1], in_selection ? cache.font_selected_color : color);
+ int w = cache.font->draw_char(ci, Point2i(char_ofs + char_margin, ofs_y + ascent), str[j], str[j + 1], in_selection && override_selected_font_color ? cache.font_selected_color : color);
if (underlined) {
- draw_rect(Rect2(char_ofs + char_margin, ofs_y + ascent + 2, w, 1), in_selection ? cache.font_selected_color : color);
+ draw_rect(Rect2(char_ofs + char_margin, ofs_y + ascent + 2, w, 1), in_selection && override_selected_font_color ? cache.font_selected_color : color);
}
}
else if (draw_tabs && str[j] == '\t') {
int yofs = (get_row_height() - cache.tab_icon->get_height()) / 2;
- cache.tab_icon->draw(ci, Point2(char_ofs + char_margin, ofs_y + yofs), in_selection ? cache.font_selected_color : color);
+ cache.tab_icon->draw(ci, Point2(char_ofs + char_margin, ofs_y + yofs), in_selection && override_selected_font_color ? cache.font_selected_color : color);
}
char_ofs += char_w;
@@ -1611,7 +1727,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
target_v_scroll = 0;
}
scrolling = true;
- set_fixed_process(true);
+ set_physics_process(true);
} else {
v_scroll->set_value(target_v_scroll);
}
@@ -1633,7 +1749,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
target_v_scroll = max_v_scroll;
}
scrolling = true;
- set_fixed_process(true);
+ set_physics_process(true);
} else {
v_scroll->set_value(target_v_scroll);
}
@@ -1735,36 +1851,15 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
if (!mb->is_doubleclick() && (OS::get_singleton()->get_ticks_msec() - last_dblclk) < 600 && cursor.line == prev_line) {
//tripleclick select line
- select(cursor.line, 0, cursor.line, text[cursor.line].length());
- selection.selecting_column = 0;
+ selection.selecting_mode = Selection::MODE_LINE;
+ _update_selection_mode_line();
last_dblclk = 0;
} else if (mb->is_doubleclick() && text[cursor.line].length()) {
//doubleclick select world
- String s = text[cursor.line];
- int beg = CLAMP(cursor.column, 0, s.length());
- int end = beg;
-
- if (s[beg] > 32 || beg == s.length()) {
-
- bool symbol = beg < s.length() && _is_symbol(s[beg]); //not sure if right but most editors behave like this
-
- while (beg > 0 && s[beg - 1] > 32 && (symbol == _is_symbol(s[beg - 1]))) {
- beg--;
- }
- while (end < s.length() && s[end + 1] > 32 && (symbol == _is_symbol(s[end + 1]))) {
- end++;
- }
-
- if (end < s.length())
- end += 1;
-
- select(cursor.line, beg, cursor.line, end);
-
- selection.selecting_column = beg;
- }
-
+ selection.selecting_mode = Selection::MODE_WORD;
+ _update_selection_mode_word();
last_dblclk = OS::get_singleton()->get_ticks_msec();
}
@@ -1773,7 +1868,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
if (mb->get_button_index() == BUTTON_RIGHT && context_menu_enabled) {
- menu->set_position(get_global_transform().xform(get_local_mouse_pos()));
+ menu->set_position(get_global_transform().xform(get_local_mouse_position()));
menu->set_size(Vector2(1, 1));
menu->popup();
grab_focus();
@@ -1809,21 +1904,21 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
}
if (mm->get_button_mask() & BUTTON_MASK_LEFT && get_viewport()->gui_get_drag_data() == Variant()) { //ignore if dragging
+ _reset_caret_blink_timer();
- if (selection.selecting_mode != Selection::MODE_NONE) {
-
- _reset_caret_blink_timer();
-
- int row, col;
- _get_mouse_pos(mm->get_position(), row, col);
-
- select(selection.selecting_line, selection.selecting_column, row, col);
-
- cursor_set_line(row);
- cursor_set_column(col);
- update();
-
- click_select_held->start();
+ switch (selection.selecting_mode) {
+ case Selection::MODE_POINTER: {
+ _update_selection_mode_pointer();
+ } break;
+ case Selection::MODE_WORD: {
+ _update_selection_mode_word();
+ } break;
+ case Selection::MODE_LINE: {
+ _update_selection_mode_line();
+ } break;
+ default: {
+ break;
+ }
}
}
}
@@ -1844,7 +1939,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
if (k->is_pressed()) {
- highlighted_word = get_word_at_pos(get_local_mouse_pos());
+ highlighted_word = get_word_at_pos(get_local_mouse_position());
update();
} else {
@@ -2164,7 +2259,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
}
}
}
-
+ begin_complex_operation();
bool first_line = false;
if (k->get_command()) {
if (k->get_shift()) {
@@ -2180,8 +2275,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
}
}
- _insert_text_at_cursor(ins);
- _push_current_op();
+ insert_text_at_cursor(ins);
if (first_line) {
cursor_set_line(0);
@@ -2189,7 +2283,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
cursor_set_line(cursor.line - 1);
cursor_set_column(text[cursor.line].length());
}
-
+ end_complex_operation();
} break;
case KEY_ESCAPE: {
if (completion_hint != "") {
@@ -2824,19 +2918,19 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
if (scancode_handled)
accept_event();
/*
- if (!scancode_handled && !k->get_command() && !k->get_alt()) {
+ if (!scancode_handled && !k->get_command() && !k->get_alt()) {
if (k->get_unicode()>=32) {
- if (readonly)
+ if (readonly)
break;
- accept_event();
+ accept_event();
} else {
- break;
+ break;
+ }
}
- }
*/
if (k->get_scancode() == KEY_INSERT) {
set_insert_mode(!insert_mode);
@@ -3228,11 +3322,11 @@ void TextEdit::adjust_viewport_to_cursor() {
update();
/*
- get_range()->set_max(text.size());
+ get_range()->set_max(text.size());
- get_range()->set_page(get_visible_rows());
+ get_range()->set_page(get_visible_rows());
- get_range()->set((int)cursor.line_ofs);
+ get_range()->set((int)cursor.line_ofs);
*/
}
@@ -3499,7 +3593,7 @@ String TextEdit::get_text() {
String TextEdit::get_text_for_lookup_completion() {
int row, col;
- _get_mouse_pos(get_local_mouse_pos(), row, col);
+ _get_mouse_pos(get_local_mouse_position(), row, col);
String longthing;
int len = text.size();
@@ -4257,6 +4351,13 @@ bool TextEdit::is_drawing_tabs() const {
return draw_tabs;
}
+void TextEdit::set_override_selected_font_color(bool p_override_selected_font_color) {
+ override_selected_font_color = p_override_selected_font_color;
+}
+bool TextEdit::is_overriding_selected_font_color() const {
+ return override_selected_font_color;
+}
+
void TextEdit::set_insert_mode(bool p_enabled) {
insert_mode = p_enabled;
update();
@@ -4266,6 +4367,10 @@ bool TextEdit::is_insert_mode() const {
return insert_mode;
}
+bool TextEdit::is_insert_text_operation() {
+ return (current_op.type == TextOperation::TYPE_INSERT);
+}
+
uint32_t TextEdit::get_version() const {
return current_op.version;
}
@@ -4284,6 +4389,14 @@ int TextEdit::get_v_scroll() const {
}
void TextEdit::set_v_scroll(int p_scroll) {
+ if (p_scroll < 0) {
+ p_scroll = 0;
+ }
+ if (!scroll_past_end_of_file_enabled) {
+ if (p_scroll + get_visible_rows() > get_line_count()) {
+ p_scroll = get_line_count() - get_visible_rows();
+ }
+ }
v_scroll->set_value(p_scroll);
cursor.line_ofs = p_scroll;
}
@@ -4446,7 +4559,13 @@ void TextEdit::_update_completion_candidates() {
completion_index = 0;
completion_base = s;
Vector<float> sim_cache;
+ bool single_quote = s.begins_with("'");
+
for (int i = 0; i < completion_strings.size(); i++) {
+ if (single_quote && completion_strings[i].is_quoted()) {
+ completion_strings[i] = completion_strings[i].unquote().quote("'");
+ }
+
if (s == completion_strings[i]) {
// A perfect match, stop completion
_cancel_completion();
@@ -4689,6 +4808,15 @@ int TextEdit::get_breakpoint_gutter_width() const {
return cache.breakpoint_gutter_width;
}
+void TextEdit::set_highlight_current_line(bool p_enabled) {
+ highlight_current_line = p_enabled;
+ update();
+}
+
+bool TextEdit::is_highlight_current_line_enabled() const {
+ return highlight_current_line;
+}
+
bool TextEdit::is_text_field() const {
return true;
@@ -4758,8 +4886,8 @@ void TextEdit::_bind_methods() {
BIND_ENUM_CONSTANT(SEARCH_BACKWARDS);
/*
- ClassDB::bind_method(D_METHOD("delete_char"),&TextEdit::delete_char);
- ClassDB::bind_method(D_METHOD("delete_line"),&TextEdit::delete_line);
+ ClassDB::bind_method(D_METHOD("delete_char"),&TextEdit::delete_char);
+ ClassDB::bind_method(D_METHOD("delete_line"),&TextEdit::delete_line);
*/
ClassDB::bind_method(D_METHOD("set_text", "text"), &TextEdit::set_text);
@@ -4810,9 +4938,15 @@ void TextEdit::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_highlight_all_occurrences", "enable"), &TextEdit::set_highlight_all_occurrences);
ClassDB::bind_method(D_METHOD("is_highlight_all_occurrences_enabled"), &TextEdit::is_highlight_all_occurrences_enabled);
+ ClassDB::bind_method(D_METHOD("set_override_selected_font_color", "override"), &TextEdit::set_override_selected_font_color);
+ ClassDB::bind_method(D_METHOD("is_overriding_selected_font_color"), &TextEdit::is_overriding_selected_font_color);
+
ClassDB::bind_method(D_METHOD("set_syntax_coloring", "enable"), &TextEdit::set_syntax_coloring);
ClassDB::bind_method(D_METHOD("is_syntax_coloring_enabled"), &TextEdit::is_syntax_coloring_enabled);
+ ClassDB::bind_method(D_METHOD("set_highlight_current_line", "enabled"), &TextEdit::set_highlight_current_line);
+ ClassDB::bind_method(D_METHOD("is_highlight_current_line_enabled"), &TextEdit::is_highlight_current_line_enabled);
+
ClassDB::bind_method(D_METHOD("set_smooth_scroll_enable", "enable"), &TextEdit::set_smooth_scroll_enabled);
ClassDB::bind_method(D_METHOD("is_smooth_scroll_enabled"), &TextEdit::is_smooth_scroll_enabled);
ClassDB::bind_method(D_METHOD("set_v_scroll_speed", "speed"), &TextEdit::set_v_scroll_speed);
@@ -4824,9 +4958,11 @@ void TextEdit::_bind_methods() {
ClassDB::bind_method(D_METHOD("menu_option", "option"), &TextEdit::menu_option);
ClassDB::bind_method(D_METHOD("get_menu"), &TextEdit::get_menu);
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "highlight_current_line"), "set_highlight_current_line", "is_highlight_current_line_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "syntax_highlighting"), "set_syntax_coloring", "is_syntax_coloring_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "show_line_numbers"), "set_show_line_numbers", "is_show_line_numbers_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "highlight_all_occurrences"), "set_highlight_all_occurrences", "is_highlight_all_occurrences_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "override_selected_font_color"), "set_override_selected_font_color", "is_overriding_selected_font_color");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "smooth_scrolling"), "set_smooth_scroll_enable", "is_smooth_scroll_enabled");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "v_scroll_speed"), "set_v_scroll_speed", "get_v_scroll_speed");
@@ -4857,6 +4993,7 @@ TextEdit::TextEdit() {
readonly = false;
setting_row = false;
draw_tabs = false;
+ override_selected_font_color = false;
draw_caret = true;
max_chars = 0;
clear();
@@ -4943,6 +5080,7 @@ TextEdit::TextEdit() {
auto_brace_completion_enabled = false;
brace_matching_enabled = false;
highlight_all_occurrences = false;
+ highlight_current_line = false;
indent_using_spaces = false;
space_indent = " ";
auto_indent = false;
diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h
index 68ef559f46..81310b7c10 100644
--- a/scene/gui/text_edit.h
+++ b/scene/gui/text_edit.h
@@ -51,11 +51,14 @@ class TextEdit : public Control {
MODE_NONE,
MODE_SHIFT,
- MODE_POINTER
+ MODE_POINTER,
+ MODE_WORD,
+ MODE_LINE
};
Mode selecting_mode;
int selecting_line, selecting_column;
+ int selected_word_beg, selected_word_end, selected_word_origin;
bool selecting_text;
bool active;
@@ -238,6 +241,7 @@ class TextEdit : public Control {
bool setting_row;
bool wrap;
bool draw_tabs;
+ bool override_selected_font_color;
bool cursor_changed_dirty;
bool text_changed_dirty;
bool undo_enabled;
@@ -252,6 +256,7 @@ class TextEdit : public Control {
bool scroll_past_end_of_file_enabled;
bool auto_brace_completion_enabled;
bool brace_matching_enabled;
+ bool highlight_current_line;
bool auto_indent;
bool cut_copy_line;
bool insert_mode;
@@ -303,6 +308,10 @@ class TextEdit : public Control {
void _v_scroll_input();
void _click_selection_held();
+ void _update_selection_mode_pointer();
+ void _update_selection_mode_word();
+ void _update_selection_mode_line();
+
void _pre_shift_selection();
void _post_shift_selection();
@@ -386,6 +395,8 @@ public:
void begin_complex_operation();
void end_complex_operation();
+ bool is_insert_text_operation();
+
void set_text(String p_text);
void insert_text_at_cursor(const String &p_text);
void insert_at(const String &p_text, int at);
@@ -480,6 +491,8 @@ public:
void set_indent_size(const int p_size);
void set_draw_tabs(bool p_draw);
bool is_drawing_tabs() const;
+ void set_override_selected_font_color(bool p_override_selected_font_color);
+ bool is_overriding_selected_font_color() const;
void set_insert_mode(bool p_enabled);
bool is_insert_mode() const;
@@ -509,6 +522,9 @@ public:
void set_show_line_numbers(bool p_show);
bool is_show_line_numbers_enabled() const;
+ void set_highlight_current_line(bool p_enabled);
+ bool is_highlight_current_line_enabled() const;
+
void set_line_numbers_zero_padded(bool p_zero_padded);
void set_show_line_length_guideline(bool p_show);
diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp
index 1aaea98798..f2e5919b5f 100644
--- a/scene/gui/tree.cpp
+++ b/scene/gui/tree.cpp
@@ -47,18 +47,21 @@ void TreeItem::move_to_top() {
}
void TreeItem::move_to_bottom() {
-
if (!parent || !next)
return;
- while (next) {
+ TreeItem *prev = get_prev();
+ TreeItem *last = next;
+ while (last->next)
+ last = last->next;
- if (parent->childs == this)
- parent->childs = next;
- TreeItem *n = next;
- next = n->next;
- n->next = this;
+ if (prev) {
+ prev->next = next;
+ } else {
+ parent->childs = next;
}
+ last->next = this;
+ next = NULL;
}
Size2 TreeItem::Cell::get_icon_size() const {
@@ -862,6 +865,7 @@ void Tree::update_cache() {
cache.arrow_collapsed = get_icon("arrow_collapsed");
cache.arrow = get_icon("arrow");
cache.select_arrow = get_icon("select_arrow");
+ cache.select_option = get_icon("select_option");
cache.updown = get_icon("updown");
cache.custom_button = get_stylebox("custom_button");
@@ -1122,7 +1126,7 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
if (p_item->cells[i].selected && select_mode != SELECT_ROW) {
- Rect2i r(item_rect.position, item_rect.size);
+ Rect2i r(cell_rect.position, cell_rect.size);
if (p_item->cells[i].text.size() > 0) {
float icon_width = p_item->cells[i].get_icon_size().width;
r.position.x += icon_width;
@@ -1528,7 +1532,7 @@ void Tree::_range_click_timeout() {
if (range_item_last && !range_drag_enabled && Input::get_singleton()->is_mouse_button_pressed(BUTTON_LEFT)) {
- Point2 pos = get_local_mouse_pos() - cache.bg->get_offset();
+ Point2 pos = get_local_mouse_position() - cache.bg->get_offset();
if (show_column_titles) {
pos.y -= _get_title_button_height();
@@ -1676,7 +1680,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool
p_item->select(col);
emit_signal("multi_selected", p_item, col, true);
if (p_button == BUTTON_RIGHT) {
- emit_signal("item_rmb_selected", get_local_mouse_pos());
+ emit_signal("item_rmb_selected", get_local_mouse_position());
}
//p_item->selected_signal.call(col);
@@ -1697,7 +1701,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool
select_single_item(p_item, root, col, selected_item, &inrange);
if (p_button == BUTTON_RIGHT) {
- emit_signal("item_rmb_selected", get_local_mouse_pos());
+ emit_signal("item_rmb_selected", get_local_mouse_position());
}
} else {
@@ -1713,7 +1717,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool
}
if (p_button == BUTTON_RIGHT) {
- emit_signal("item_rmb_selected", get_local_mouse_pos());
+ emit_signal("item_rmb_selected", get_local_mouse_position());
}
}
}
@@ -1914,7 +1918,7 @@ void Tree::_text_editor_modal_close() {
return;
}
- if (value_editor->has_point(value_editor->get_local_mouse_pos()))
+ if (value_editor->has_point(value_editor->get_local_mouse_position()))
return;
text_editor_enter(text_editor->get_text());
@@ -2135,8 +2139,15 @@ void Tree::_gui_input(Ref<InputEvent> p_event) {
if (selected_item->get_children() != NULL && !selected_item->is_collapsed()) {
selected_item->set_collapsed(true);
} else {
- selected_col = columns.size() - 1;
- dobreak = false; // fall through to key_up
+ if (columns.size() == 1) { // goto parent with one column
+ TreeItem *parent = selected_item->get_parent();
+ if (selected_item != get_root() && parent && parent->is_selectable(selected_col) && !(hide_root && parent == get_root())) {
+ select_single_item(parent, get_root(), selected_col);
+ }
+ } else {
+ selected_col = columns.size() - 1;
+ dobreak = false; // fall through to key_up
+ }
}
} else {
if (select_mode == SELECT_MULTI) {
@@ -2149,6 +2160,7 @@ void Tree::_gui_input(Ref<InputEvent> p_event) {
}
update();
accept_event();
+ ensure_cursor_is_visible();
if (dobreak) {
break;
@@ -2470,7 +2482,7 @@ void Tree::_gui_input(Ref<InputEvent> p_event) {
if (cache.click_type == Cache::CLICK_BUTTON) {
// make sure in case of wrong reference after reconstructing whole TreeItems
- cache.click_item = get_item_at_pos(cache.click_pos);
+ cache.click_item = get_item_at_position(cache.click_pos);
emit_signal("button_pressed", cache.click_item, cache.click_column, cache.click_id);
}
cache.click_type = Cache::CLICK_NONE;
@@ -2484,7 +2496,7 @@ void Tree::_gui_input(Ref<InputEvent> p_event) {
if (drag_speed == 0) {
drag_touching_deaccel = false;
drag_touching = false;
- set_fixed_process(false);
+ set_physics_process(false);
} else {
drag_touching_deaccel = true;
@@ -2530,7 +2542,7 @@ void Tree::_gui_input(Ref<InputEvent> p_event) {
}
if (!root || (!root->get_children() && hide_root)) {
if (b->get_button_index() == BUTTON_RIGHT && allow_rmb_select) {
- emit_signal("empty_tree_rmb_selected", get_local_mouse_pos());
+ emit_signal("empty_tree_rmb_selected", get_local_mouse_position());
}
break;
}
@@ -2550,7 +2562,7 @@ void Tree::_gui_input(Ref<InputEvent> p_event) {
break;
if (drag_touching) {
- set_fixed_process(false);
+ set_physics_process(false);
drag_touching_deaccel = false;
drag_touching = false;
drag_speed = 0;
@@ -2565,7 +2577,7 @@ void Tree::_gui_input(Ref<InputEvent> p_event) {
drag_touching = OS::get_singleton()->has_touchscreen_ui_hint();
drag_touching_deaccel = false;
if (drag_touching) {
- set_fixed_process(true);
+ set_physics_process(true);
}
}
@@ -2756,7 +2768,7 @@ void Tree::_notification(int p_what) {
drop_mode_flags = 0;
scrolling = false;
- set_fixed_process(false);
+ set_physics_process(false);
update();
}
if (p_what == NOTIFICATION_DRAG_BEGIN) {
@@ -2764,23 +2776,23 @@ void Tree::_notification(int p_what) {
single_select_defer = NULL;
if (cache.scroll_speed > 0 && get_rect().has_point(get_viewport()->get_mouse_position() - get_global_position())) {
scrolling = true;
- set_fixed_process(true);
+ set_physics_process(true);
}
}
- if (p_what == NOTIFICATION_FIXED_PROCESS) {
+ if (p_what == NOTIFICATION_PHYSICS_PROCESS) {
if (drag_touching) {
if (drag_touching_deaccel) {
float pos = v_scroll->get_value();
- pos += drag_speed * get_fixed_process_delta_time();
+ pos += drag_speed * get_physics_process_delta_time();
bool turnoff = false;
if (pos < 0) {
pos = 0;
turnoff = true;
- set_fixed_process(false);
+ set_physics_process(false);
drag_touching = false;
drag_touching_deaccel = false;
}
@@ -2792,7 +2804,7 @@ void Tree::_notification(int p_what) {
v_scroll->set_value(pos);
float sgn = drag_speed < 0 ? -1 : 1;
float val = Math::abs(drag_speed);
- val -= 1000 * get_fixed_process_delta_time();
+ val -= 1000 * get_physics_process_delta_time();
if (val < 0) {
turnoff = true;
@@ -2800,7 +2812,7 @@ void Tree::_notification(int p_what) {
drag_speed = sgn * val;
if (turnoff) {
- set_fixed_process(false);
+ set_physics_process(false);
drag_touching = false;
drag_touching_deaccel = false;
}
@@ -2825,7 +2837,7 @@ void Tree::_notification(int p_what) {
} else {
point.y = 0;
}
- point *= cache.scroll_speed * get_fixed_process_delta_time();
+ point *= cache.scroll_speed * get_physics_process_delta_time();
point += get_scroll();
h_scroll->set_value(point.x);
v_scroll->set_value(point.y);
@@ -3320,6 +3332,26 @@ Point2 Tree::get_scroll() const {
return ofs;
}
+void Tree::scroll_to_item(TreeItem *p_item) {
+
+ if (!is_visible_in_tree()) {
+
+ // hack to work around crash in get_item_rect() if Tree is not in tree.
+ return;
+ }
+
+ // make sure the scrollbar min and max are up to date with latest changes.
+ update_scrollbars();
+
+ const Rect2 r = get_item_rect(p_item);
+
+ if (r.position.y < v_scroll->get_value()) {
+ v_scroll->set_value(r.position.y);
+ } else if (r.position.y + r.size.y + 2 * cache.vseparation > v_scroll->get_value() + get_size().y) {
+ v_scroll->set_value(r.position.y + r.size.y + 2 * cache.vseparation - get_size().y);
+ }
+}
+
TreeItem *Tree::_search_item_text(TreeItem *p_at, const String &p_find, int *r_col, bool p_selectable, bool p_backwards) {
while (p_at) {
@@ -3428,7 +3460,7 @@ TreeItem *Tree::_find_item_at_pos(TreeItem *p_item, const Point2 &p_pos, int &r_
return NULL;
}
-int Tree::get_column_at_pos(const Point2 &p_pos) const {
+int Tree::get_column_at_position(const Point2 &p_pos) const {
if (root) {
@@ -3454,7 +3486,7 @@ int Tree::get_column_at_pos(const Point2 &p_pos) const {
return -1;
}
-int Tree::get_drop_section_at_pos(const Point2 &p_pos) const {
+int Tree::get_drop_section_at_position(const Point2 &p_pos) const {
if (root) {
@@ -3479,7 +3511,7 @@ int Tree::get_drop_section_at_pos(const Point2 &p_pos) const {
return -100;
}
-TreeItem *Tree::get_item_at_pos(const Point2 &p_pos) const {
+TreeItem *Tree::get_item_at_position(const Point2 &p_pos) const {
if (root) {
@@ -3652,9 +3684,9 @@ void Tree::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_edited_column"), &Tree::get_edited_column);
ClassDB::bind_method(D_METHOD("get_custom_popup_rect"), &Tree::get_custom_popup_rect);
ClassDB::bind_method(D_METHOD("get_item_area_rect", "item", "column"), &Tree::_get_item_rect, DEFVAL(-1));
- ClassDB::bind_method(D_METHOD("get_item_at_pos", "pos"), &Tree::get_item_at_pos);
- ClassDB::bind_method(D_METHOD("get_column_at_pos", "pos"), &Tree::get_column_at_pos);
- ClassDB::bind_method(D_METHOD("get_drop_section_at_pos", "pos"), &Tree::get_drop_section_at_pos);
+ ClassDB::bind_method(D_METHOD("get_item_at_position", "position"), &Tree::get_item_at_position);
+ ClassDB::bind_method(D_METHOD("get_column_at_position", "position"), &Tree::get_column_at_position);
+ ClassDB::bind_method(D_METHOD("get_drop_section_at_position", "position"), &Tree::get_drop_section_at_position);
ClassDB::bind_method(D_METHOD("ensure_cursor_is_visible"), &Tree::ensure_cursor_is_visible);
@@ -3680,8 +3712,8 @@ void Tree::_bind_methods() {
ADD_SIGNAL(MethodInfo("item_selected"));
ADD_SIGNAL(MethodInfo("cell_selected"));
ADD_SIGNAL(MethodInfo("multi_selected", PropertyInfo(Variant::OBJECT, "item"), PropertyInfo(Variant::INT, "column"), PropertyInfo(Variant::BOOL, "selected")));
- ADD_SIGNAL(MethodInfo("item_rmb_selected", PropertyInfo(Variant::VECTOR2, "pos")));
- ADD_SIGNAL(MethodInfo("empty_tree_rmb_selected", PropertyInfo(Variant::VECTOR2, "pos")));
+ ADD_SIGNAL(MethodInfo("item_rmb_selected", PropertyInfo(Variant::VECTOR2, "position")));
+ ADD_SIGNAL(MethodInfo("empty_tree_rmb_selected", PropertyInfo(Variant::VECTOR2, "position")));
ADD_SIGNAL(MethodInfo("item_edited"));
ADD_SIGNAL(MethodInfo("item_rmb_edited"));
ADD_SIGNAL(MethodInfo("item_custom_button_pressed"));
diff --git a/scene/gui/tree.h b/scene/gui/tree.h
index 5f19558597..64d6016942 100644
--- a/scene/gui/tree.h
+++ b/scene/gui/tree.h
@@ -418,6 +418,7 @@ private:
Ref<Texture> arrow_collapsed;
Ref<Texture> arrow;
Ref<Texture> select_arrow;
+ Ref<Texture> select_option;
Ref<Texture> updown;
Color font_color;
@@ -525,9 +526,9 @@ protected:
public:
virtual String get_tooltip(const Point2 &p_pos) const;
- TreeItem *get_item_at_pos(const Point2 &p_pos) const;
- int get_column_at_pos(const Point2 &p_pos) const;
- int get_drop_section_at_pos(const Point2 &p_pos) const;
+ TreeItem *get_item_at_position(const Point2 &p_pos) const;
+ int get_column_at_position(const Point2 &p_pos) const;
+ int get_drop_section_at_position(const Point2 &p_pos) const;
void clear();
@@ -569,6 +570,7 @@ public:
TreeItem *search_item_text(const String &p_find, int *r_col = NULL, bool p_selectable = false);
Point2 get_scroll() const;
+ void scroll_to_item(TreeItem *p_item);
void set_cursor_can_exit_tree(bool p_enable);
bool can_cursor_exit_tree() const;
diff --git a/scene/gui/video_player.cpp b/scene/gui/video_player.cpp
index a92155cc4f..190ccd50d5 100644
--- a/scene/gui/video_player.cpp
+++ b/scene/gui/video_player.cpp
@@ -278,13 +278,19 @@ String VideoPlayer::get_stream_name() const {
return stream->get_name();
};
-float VideoPlayer::get_stream_pos() const {
+float VideoPlayer::get_stream_position() const {
if (playback.is_null())
return 0;
- return playback->get_pos();
+ return playback->get_playback_position();
};
+void VideoPlayer::set_stream_position(float p_position) {
+
+ if (playback.is_valid())
+ playback->seek(p_position);
+}
+
Ref<Texture> VideoPlayer::get_video_texture() {
if (playback.is_valid())
@@ -327,7 +333,8 @@ void VideoPlayer::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_stream_name"), &VideoPlayer::get_stream_name);
- ClassDB::bind_method(D_METHOD("get_stream_pos"), &VideoPlayer::get_stream_pos);
+ ClassDB::bind_method(D_METHOD("set_stream_position", "position"), &VideoPlayer::set_stream_position);
+ ClassDB::bind_method(D_METHOD("get_stream_position"), &VideoPlayer::get_stream_position);
ClassDB::bind_method(D_METHOD("set_autoplay", "enabled"), &VideoPlayer::set_autoplay);
ClassDB::bind_method(D_METHOD("has_autoplay"), &VideoPlayer::has_autoplay);
diff --git a/scene/gui/video_player.h b/scene/gui/video_player.h
index b78f3aabe7..f04e90365f 100644
--- a/scene/gui/video_player.h
+++ b/scene/gui/video_player.h
@@ -92,7 +92,8 @@ public:
float get_volume_db() const;
String get_stream_name() const;
- float get_stream_pos() const;
+ float get_stream_position() const;
+ void set_stream_position(float p_position);
void set_autoplay(bool p_enable);
bool has_autoplay() const;
diff --git a/scene/gui/viewport_container.cpp b/scene/gui/viewport_container.cpp
index c321b873fd..9244d8de2f 100644
--- a/scene/gui/viewport_container.cpp
+++ b/scene/gui/viewport_container.cpp
@@ -62,6 +62,34 @@ bool ViewportContainer::is_stretch_enabled() const {
return stretch;
}
+void ViewportContainer::set_stretch_shrink(int p_shrink) {
+
+ ERR_FAIL_COND(p_shrink < 1);
+ if (shrink == p_shrink)
+ return;
+
+ shrink = p_shrink;
+
+ if (!stretch)
+ return;
+
+ for (int i = 0; i < get_child_count(); i++) {
+
+ Viewport *c = Object::cast_to<Viewport>(get_child(i));
+ if (!c)
+ continue;
+
+ c->set_size(get_size() / shrink);
+ }
+
+ update();
+}
+
+int ViewportContainer::get_stretch_shrink() const {
+
+ return shrink;
+}
+
void ViewportContainer::_notification(int p_what) {
if (p_what == NOTIFICATION_RESIZED) {
@@ -75,7 +103,7 @@ void ViewportContainer::_notification(int p_what) {
if (!c)
continue;
- c->set_size(get_size());
+ c->set_size(get_size() / shrink);
}
}
@@ -115,10 +143,15 @@ void ViewportContainer::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_stretch", "enable"), &ViewportContainer::set_stretch);
ClassDB::bind_method(D_METHOD("is_stretch_enabled"), &ViewportContainer::is_stretch_enabled);
+ ClassDB::bind_method(D_METHOD("set_stretch_shrink", "amount"), &ViewportContainer::set_stretch_shrink);
+ ClassDB::bind_method(D_METHOD("get_stretch_shrink"), &ViewportContainer::get_stretch_shrink);
+
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "stretch"), "set_stretch", "is_stretch_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "stretch_shrink"), "set_stretch_shrink", "get_stretch_shrink");
}
ViewportContainer::ViewportContainer() {
stretch = false;
+ shrink = 1;
}
diff --git a/scene/gui/viewport_container.h b/scene/gui/viewport_container.h
index 630523b5fb..ebf5869ed9 100644
--- a/scene/gui/viewport_container.h
+++ b/scene/gui/viewport_container.h
@@ -37,6 +37,7 @@ class ViewportContainer : public Container {
GDCLASS(ViewportContainer, Container);
bool stretch;
+ int shrink;
protected:
void _notification(int p_what);
@@ -46,6 +47,9 @@ public:
void set_stretch(bool p_enable);
bool is_stretch_enabled() const;
+ void set_stretch_shrink(int p_shrink);
+ int get_stretch_shrink() const;
+
virtual Size2 get_minimum_size() const;
ViewportContainer();