summaryrefslogtreecommitdiff
path: root/scene/gui
diff options
context:
space:
mode:
Diffstat (limited to 'scene/gui')
-rw-r--r--scene/gui/base_button.cpp19
-rw-r--r--scene/gui/base_button.h5
-rw-r--r--scene/gui/code_edit.cpp19
-rw-r--r--scene/gui/code_edit.h1
-rw-r--r--scene/gui/color_mode.cpp8
-rw-r--r--scene/gui/color_picker.cpp141
-rw-r--r--scene/gui/color_picker.h27
-rw-r--r--scene/gui/flow_container.cpp41
-rw-r--r--scene/gui/flow_container.h13
-rw-r--r--scene/gui/scroll_container.cpp107
-rw-r--r--scene/gui/tab_container.cpp8
-rw-r--r--scene/gui/tab_container.h2
-rw-r--r--scene/gui/text_edit.cpp30
-rw-r--r--scene/gui/text_edit.h1
14 files changed, 330 insertions, 92 deletions
diff --git a/scene/gui/base_button.cpp b/scene/gui/base_button.cpp
index ca2ab8bd2b..ac9034c6fd 100644
--- a/scene/gui/base_button.cpp
+++ b/scene/gui/base_button.cpp
@@ -127,6 +127,7 @@ void BaseButton::_notification(int p_what) {
status.hovering = false;
status.press_attempt = false;
status.pressing_inside = false;
+ status.shortcut_press = false;
} break;
}
}
@@ -160,6 +161,7 @@ void BaseButton::on_action_event(Ref<InputEvent> p_event) {
if (action_mode == ACTION_MODE_BUTTON_PRESS) {
status.press_attempt = false;
status.pressing_inside = false;
+ status.shortcut_press = false;
}
status.pressed = !status.pressed;
_unpress_group();
@@ -185,6 +187,7 @@ void BaseButton::on_action_event(Ref<InputEvent> p_event) {
}
status.press_attempt = false;
status.pressing_inside = false;
+ status.shortcut_press = false;
emit_signal(SNAME("button_up"));
}
@@ -209,6 +212,7 @@ void BaseButton::set_disabled(bool p_disabled) {
}
status.press_attempt = false;
status.pressing_inside = false;
+ status.shortcut_press = false;
}
queue_redraw();
}
@@ -281,7 +285,7 @@ BaseButton::DrawMode BaseButton::get_draw_mode() const {
pressing = status.pressed;
}
- if (pressing) {
+ if ((shortcut_feedback || !status.shortcut_press) && pressing) {
return DRAW_PRESSED;
} else {
return DRAW_NORMAL;
@@ -347,6 +351,7 @@ void BaseButton::shortcut_input(const Ref<InputEvent> &p_event) {
ERR_FAIL_COND(p_event.is_null());
if (!is_disabled() && is_visible_in_tree() && !p_event->is_echo() && shortcut.is_valid() && shortcut->matches_event(p_event)) {
+ status.shortcut_press = true;
on_action_event(p_event);
accept_event();
}
@@ -386,6 +391,14 @@ bool BaseButton::_was_pressed_by_mouse() const {
return was_mouse_pressed;
}
+void BaseButton::set_shortcut_feedback(bool p_feedback) {
+ shortcut_feedback = p_feedback;
+}
+
+bool BaseButton::is_shortcut_feedback() const {
+ return shortcut_feedback;
+}
+
void BaseButton::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_pressed", "pressed"), &BaseButton::set_pressed);
ClassDB::bind_method(D_METHOD("is_pressed"), &BaseButton::is_pressed);
@@ -411,6 +424,9 @@ void BaseButton::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_button_group", "button_group"), &BaseButton::set_button_group);
ClassDB::bind_method(D_METHOD("get_button_group"), &BaseButton::get_button_group);
+ ClassDB::bind_method(D_METHOD("set_shortcut_feedback", "enabled"), &BaseButton::set_shortcut_feedback);
+ ClassDB::bind_method(D_METHOD("is_shortcut_feedback"), &BaseButton::is_shortcut_feedback);
+
GDVIRTUAL_BIND(_pressed);
GDVIRTUAL_BIND(_toggled, "button_pressed");
@@ -427,6 +443,7 @@ void BaseButton::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "button_mask", PROPERTY_HINT_FLAGS, "Mouse Left, Mouse Right, Mouse Middle"), "set_button_mask", "get_button_mask");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "keep_pressed_outside"), "set_keep_pressed_outside", "is_keep_pressed_outside");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "shortcut", PROPERTY_HINT_RESOURCE_TYPE, "Shortcut"), "set_shortcut", "get_shortcut");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "shortcut_feedback"), "set_shortcut_feedback", "is_shortcut_feedback");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "button_group", PROPERTY_HINT_RESOURCE_TYPE, "ButtonGroup"), "set_button_group", "get_button_group");
BIND_ENUM_CONSTANT(DRAW_NORMAL);
diff --git a/scene/gui/base_button.h b/scene/gui/base_button.h
index 7839239800..3acf535f54 100644
--- a/scene/gui/base_button.h
+++ b/scene/gui/base_button.h
@@ -53,6 +53,7 @@ private:
bool keep_pressed_outside = false;
Ref<Shortcut> shortcut;
ObjectID shortcut_context;
+ bool shortcut_feedback = true;
ActionMode action_mode = ACTION_MODE_BUTTON_RELEASE;
struct Status {
@@ -60,6 +61,7 @@ private:
bool hovering = false;
bool press_attempt = false;
bool pressing_inside = false;
+ bool shortcut_press = false;
bool disabled = false;
@@ -131,6 +133,9 @@ public:
void set_button_group(const Ref<ButtonGroup> &p_group);
Ref<ButtonGroup> get_button_group() const;
+ void set_shortcut_feedback(bool p_feedback);
+ bool is_shortcut_feedback() const;
+
BaseButton();
~BaseButton();
};
diff --git a/scene/gui/code_edit.cpp b/scene/gui/code_edit.cpp
index f61fa29a33..5f8f25154c 100644
--- a/scene/gui/code_edit.cpp
+++ b/scene/gui/code_edit.cpp
@@ -138,7 +138,7 @@ void CodeEdit::_notification(int p_what) {
code_completion_scroll_rect.position = code_completion_rect.position + Vector2(code_completion_rect.size.width, 0);
code_completion_scroll_rect.size = Vector2(scroll_width, code_completion_rect.size.height);
- code_completion_line_ofs = CLAMP(code_completion_current_selected - lines / 2, 0, code_completion_options_count - lines);
+ code_completion_line_ofs = CLAMP((code_completion_force_item_center < 0 ? code_completion_current_selected : code_completion_force_item_center) - lines / 2, 0, code_completion_options_count - lines);
RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2(code_completion_rect.position.x, code_completion_rect.position.y + (code_completion_current_selected - code_completion_line_ofs) * row_height), Size2(code_completion_rect.size.width, row_height)), code_completion_selected_color);
for (int i = 0; i < lines; i++) {
@@ -281,16 +281,22 @@ void CodeEdit::gui_input(const Ref<InputEvent> &p_gui_input) {
case MouseButton::WHEEL_UP: {
if (code_completion_current_selected > 0) {
code_completion_current_selected--;
+ code_completion_force_item_center = -1;
queue_redraw();
}
} break;
case MouseButton::WHEEL_DOWN: {
if (code_completion_current_selected < code_completion_options.size() - 1) {
code_completion_current_selected++;
+ code_completion_force_item_center = -1;
queue_redraw();
}
} break;
case MouseButton::LEFT: {
+ if (code_completion_force_item_center == -1) {
+ code_completion_force_item_center = code_completion_current_selected;
+ }
+
code_completion_current_selected = CLAMP(code_completion_line_ofs + (mb->get_position().y - code_completion_rect.position.y) / get_line_height(), 0, code_completion_options.size() - 1);
if (mb->is_double_click()) {
confirm_code_completion();
@@ -300,6 +306,7 @@ void CodeEdit::gui_input(const Ref<InputEvent> &p_gui_input) {
default:
break;
}
+
return;
} else if (code_completion_active && code_completion_scroll_rect.has_point(mb->get_position())) {
if (mb->get_button_index() != MouseButton::LEFT) {
@@ -448,6 +455,7 @@ void CodeEdit::gui_input(const Ref<InputEvent> &p_gui_input) {
} else {
code_completion_current_selected = code_completion_options.size() - 1;
}
+ code_completion_force_item_center = -1;
queue_redraw();
accept_event();
return;
@@ -458,30 +466,35 @@ void CodeEdit::gui_input(const Ref<InputEvent> &p_gui_input) {
} else {
code_completion_current_selected = 0;
}
+ code_completion_force_item_center = -1;
queue_redraw();
accept_event();
return;
}
if (k->is_action("ui_page_up", true)) {
code_completion_current_selected = MAX(0, code_completion_current_selected - code_completion_max_lines);
+ code_completion_force_item_center = -1;
queue_redraw();
accept_event();
return;
}
if (k->is_action("ui_page_down", true)) {
code_completion_current_selected = MIN(code_completion_options.size() - 1, code_completion_current_selected + code_completion_max_lines);
+ code_completion_force_item_center = -1;
queue_redraw();
accept_event();
return;
}
if (k->is_action("ui_home", true)) {
code_completion_current_selected = 0;
+ code_completion_force_item_center = -1;
queue_redraw();
accept_event();
return;
}
if (k->is_action("ui_end", true)) {
code_completion_current_selected = code_completion_options.size() - 1;
+ code_completion_force_item_center = -1;
queue_redraw();
accept_event();
return;
@@ -1978,6 +1991,7 @@ void CodeEdit::set_code_completion_selected_index(int p_index) {
}
ERR_FAIL_INDEX(p_index, code_completion_options.size());
code_completion_current_selected = p_index;
+ code_completion_force_item_center = -1;
queue_redraw();
}
@@ -2808,6 +2822,7 @@ void CodeEdit::_update_scroll_selected_line(float p_mouse_y) {
percent = CLAMP(percent, 0.0f, 1.0f);
code_completion_current_selected = (int)(percent * (code_completion_options.size() - 1));
+ code_completion_force_item_center = -1;
}
void CodeEdit::_filter_code_completion_candidates_impl() {
@@ -2867,6 +2882,7 @@ void CodeEdit::_filter_code_completion_candidates_impl() {
code_completion_longest_line = MIN(max_width, code_completion_max_width * font_size);
code_completion_current_selected = 0;
+ code_completion_force_item_center = -1;
code_completion_active = true;
queue_redraw();
return;
@@ -3123,6 +3139,7 @@ void CodeEdit::_filter_code_completion_candidates_impl() {
code_completion_longest_line = MIN(max_width, code_completion_max_width * font_size);
code_completion_current_selected = 0;
+ code_completion_force_item_center = -1;
code_completion_active = true;
queue_redraw();
}
diff --git a/scene/gui/code_edit.h b/scene/gui/code_edit.h
index 09c7ef80bf..cbbc13480e 100644
--- a/scene/gui/code_edit.h
+++ b/scene/gui/code_edit.h
@@ -214,6 +214,7 @@ private:
Vector<ScriptLanguage::CodeCompletionOption> code_completion_options;
int code_completion_line_ofs = 0;
int code_completion_current_selected = 0;
+ int code_completion_force_item_center = -1;
int code_completion_longest_line = 0;
Rect2i code_completion_rect;
Rect2i code_completion_scroll_rect;
diff --git a/scene/gui/color_mode.cpp b/scene/gui/color_mode.cpp
index a063cd344a..308fe057c5 100644
--- a/scene/gui/color_mode.cpp
+++ b/scene/gui/color_mode.cpp
@@ -158,8 +158,7 @@ void ColorModeHSV::slider_draw(int p_which) {
right_color.a = 1;
} else if (p_which == 0) {
Ref<Texture2D> hue = color_picker->get_theme_icon(SNAME("color_hue"), SNAME("ColorPicker"));
- slider->draw_set_transform(Point2(), -Math_PI / 2, Size2(1.0, 1.0));
- slider->draw_texture_rect(hue, Rect2(Vector2(margin * -1, 0), Vector2(margin, size.x)), false);
+ slider->draw_texture_rect(hue, Rect2(Vector2(), Vector2(size.x, margin)), false);
return;
} else {
Color s_col;
@@ -289,9 +288,8 @@ void ColorModeOKHSL::slider_draw(int p_which) {
const real_t margin = 16 * color_picker->get_theme_default_base_scale();
if (p_which == 0) { // H
- Ref<Texture2D> hue = color_picker->get_theme_icon(SNAME("color_hue"), SNAME("ColorPicker"));
- slider->draw_set_transform(Point2(), -Math_PI / 2, Size2(1.0, 1.0));
- slider->draw_texture_rect(hue, Rect2(Vector2(margin * -1, 0), Vector2(margin, size.x)), false);
+ Ref<Texture2D> hue = color_picker->get_theme_icon(SNAME("color_okhsl_hue"), SNAME("ColorPicker"));
+ slider->draw_texture_rect(hue, Rect2(Vector2(), Vector2(size.x, margin)), false);
return;
}
diff --git a/scene/gui/color_picker.cpp b/scene/gui/color_picker.cpp
index 1b87c1d709..724e5bcaf6 100644
--- a/scene/gui/color_picker.cpp
+++ b/scene/gui/color_picker.cpp
@@ -253,18 +253,20 @@ void ColorPicker::_update_controls() {
wheel_edit->hide();
w_edit->show();
uv_edit->show();
+ btn_shape->show();
break;
case SHAPE_HSV_WHEEL:
wheel_edit->show();
w_edit->hide();
uv_edit->hide();
-
+ btn_shape->show();
wheel->set_material(wheel_mat);
break;
case SHAPE_VHS_CIRCLE:
wheel_edit->show();
w_edit->show();
uv_edit->hide();
+ btn_shape->show();
wheel->set_material(circle_mat);
circle_mat->set_shader(circle_shader);
break;
@@ -272,9 +274,16 @@ void ColorPicker::_update_controls() {
wheel_edit->show();
w_edit->show();
uv_edit->hide();
+ btn_shape->show();
wheel->set_material(circle_mat);
circle_mat->set_shader(circle_ok_color_shader);
break;
+ case SHAPE_NONE:
+ wheel_edit->hide();
+ w_edit->hide();
+ uv_edit->hide();
+ btn_shape->hide();
+ break;
default: {
}
}
@@ -606,10 +615,13 @@ void ColorPicker::set_picker_shape(PickerShapeType p_shape) {
if (p_shape == current_shape) {
return;
}
- shape_popup->set_item_checked(current_shape, false);
- shape_popup->set_item_checked(p_shape, true);
-
- btn_shape->set_icon(shape_popup->get_item_icon(p_shape));
+ if (current_shape != SHAPE_NONE) {
+ shape_popup->set_item_checked(current_shape, false);
+ }
+ if (p_shape != SHAPE_NONE) {
+ shape_popup->set_item_checked(p_shape, true);
+ btn_shape->set_icon(shape_popup->get_item_icon(p_shape));
+ }
current_shape = p_shape;
@@ -1331,7 +1343,7 @@ void ColorPicker::_preset_input(const Ref<InputEvent> &p_event, const Color &p_c
set_pick_color(p_color);
add_recent_preset(color);
emit_signal(SNAME("color_changed"), p_color);
- } else if (bev->is_pressed() && bev->get_button_index() == MouseButton::RIGHT && presets_enabled) {
+ } else if (bev->is_pressed() && bev->get_button_index() == MouseButton::RIGHT && can_add_swatches) {
erase_preset(p_color);
emit_signal(SNAME("preset_removed"), p_color);
}
@@ -1421,11 +1433,11 @@ void ColorPicker::_html_focus_exit() {
_html_submitted(c_text->get_text());
}
-void ColorPicker::set_presets_enabled(bool p_enabled) {
- if (presets_enabled == p_enabled) {
+void ColorPicker::set_can_add_swatches(bool p_enabled) {
+ if (can_add_swatches == p_enabled) {
return;
}
- presets_enabled = p_enabled;
+ can_add_swatches = p_enabled;
if (!p_enabled) {
btn_add_preset->set_disabled(true);
btn_add_preset->set_focus_mode(FOCUS_NONE);
@@ -1435,8 +1447,8 @@ void ColorPicker::set_presets_enabled(bool p_enabled) {
}
}
-bool ColorPicker::are_presets_enabled() const {
- return presets_enabled;
+bool ColorPicker::are_swatches_enabled() const {
+ return can_add_swatches;
}
void ColorPicker::set_presets_visible(bool p_visible) {
@@ -1444,13 +1456,62 @@ void ColorPicker::set_presets_visible(bool p_visible) {
return;
}
presets_visible = p_visible;
- preset_container->set_visible(p_visible);
+ btn_preset->set_visible(p_visible);
+ btn_recent_preset->set_visible(p_visible);
}
bool ColorPicker::are_presets_visible() const {
return presets_visible;
}
+void ColorPicker::set_modes_visible(bool p_visible) {
+ if (color_modes_visible == p_visible) {
+ return;
+ }
+ color_modes_visible = p_visible;
+ mode_hbc->set_visible(p_visible);
+}
+
+bool ColorPicker::are_modes_visible() const {
+ return color_modes_visible;
+}
+
+void ColorPicker::set_sampler_visible(bool p_visible) {
+ if (sampler_visible == p_visible) {
+ return;
+ }
+ sampler_visible = p_visible;
+ sample_hbc->set_visible(p_visible);
+}
+
+bool ColorPicker::is_sampler_visible() const {
+ return sampler_visible;
+}
+
+void ColorPicker::set_sliders_visible(bool p_visible) {
+ if (sliders_visible == p_visible) {
+ return;
+ }
+ sliders_visible = p_visible;
+ slider_gc->set_visible(p_visible);
+}
+
+bool ColorPicker::are_sliders_visible() const {
+ return sliders_visible;
+}
+
+void ColorPicker::set_hex_visible(bool p_visible) {
+ if (hex_visible == p_visible) {
+ return;
+ }
+ hex_visible = p_visible;
+ hex_hbc->set_visible(p_visible);
+}
+
+bool ColorPicker::is_hex_visible() const {
+ return hex_visible;
+}
+
void ColorPicker::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_pick_color", "color"), &ColorPicker::set_pick_color);
ClassDB::bind_method(D_METHOD("get_pick_color"), &ColorPicker::get_pick_color);
@@ -1460,10 +1521,18 @@ void ColorPicker::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_color_mode"), &ColorPicker::get_color_mode);
ClassDB::bind_method(D_METHOD("set_edit_alpha", "show"), &ColorPicker::set_edit_alpha);
ClassDB::bind_method(D_METHOD("is_editing_alpha"), &ColorPicker::is_editing_alpha);
- ClassDB::bind_method(D_METHOD("set_presets_enabled", "enabled"), &ColorPicker::set_presets_enabled);
- ClassDB::bind_method(D_METHOD("are_presets_enabled"), &ColorPicker::are_presets_enabled);
+ ClassDB::bind_method(D_METHOD("set_can_add_swatches", "enabled"), &ColorPicker::set_can_add_swatches);
+ ClassDB::bind_method(D_METHOD("are_swatches_enabled"), &ColorPicker::are_swatches_enabled);
ClassDB::bind_method(D_METHOD("set_presets_visible", "visible"), &ColorPicker::set_presets_visible);
ClassDB::bind_method(D_METHOD("are_presets_visible"), &ColorPicker::are_presets_visible);
+ ClassDB::bind_method(D_METHOD("set_modes_visible", "visible"), &ColorPicker::set_modes_visible);
+ ClassDB::bind_method(D_METHOD("are_modes_visible"), &ColorPicker::are_modes_visible);
+ ClassDB::bind_method(D_METHOD("set_sampler_visible", "visible"), &ColorPicker::set_sampler_visible);
+ ClassDB::bind_method(D_METHOD("is_sampler_visible"), &ColorPicker::is_sampler_visible);
+ ClassDB::bind_method(D_METHOD("set_sliders_visible", "visible"), &ColorPicker::set_sliders_visible);
+ ClassDB::bind_method(D_METHOD("are_sliders_visible"), &ColorPicker::are_sliders_visible);
+ ClassDB::bind_method(D_METHOD("set_hex_visible", "visible"), &ColorPicker::set_hex_visible);
+ ClassDB::bind_method(D_METHOD("is_hex_visible"), &ColorPicker::is_hex_visible);
ClassDB::bind_method(D_METHOD("add_preset", "color"), &ColorPicker::add_preset);
ClassDB::bind_method(D_METHOD("erase_preset", "color"), &ColorPicker::erase_preset);
ClassDB::bind_method(D_METHOD("get_presets"), &ColorPicker::get_presets);
@@ -1481,8 +1550,13 @@ void ColorPicker::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "edit_alpha"), "set_edit_alpha", "is_editing_alpha");
ADD_PROPERTY(PropertyInfo(Variant::INT, "color_mode", PROPERTY_HINT_ENUM, "RGB,HSV,RAW,OKHSL"), "set_color_mode", "get_color_mode");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "deferred_mode"), "set_deferred_mode", "is_deferred_mode");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "picker_shape", PROPERTY_HINT_ENUM, "HSV Rectangle,HSV Rectangle Wheel,VHS Circle,OKHSL Circle"), "set_picker_shape", "get_picker_shape");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "presets_enabled"), "set_presets_enabled", "are_presets_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "picker_shape", PROPERTY_HINT_ENUM, "HSV Rectangle,HSV Rectangle Wheel,VHS Circle,OKHSL Circle,None"), "set_picker_shape", "get_picker_shape");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "can_add_swatches"), "set_can_add_swatches", "are_swatches_enabled");
+ ADD_GROUP("Customization", "");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sampler_visible"), "set_sampler_visible", "is_sampler_visible");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "color_modes_visible"), "set_modes_visible", "are_modes_visible");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sliders_visible"), "set_sliders_visible", "are_sliders_visible");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "hex_visible"), "set_hex_visible", "is_hex_visible");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "presets_visible"), "set_presets_visible", "are_presets_visible");
ADD_SIGNAL(MethodInfo("color_changed", PropertyInfo(Variant::COLOR, "color")));
@@ -1498,6 +1572,7 @@ void ColorPicker::_bind_methods() {
BIND_ENUM_CONSTANT(SHAPE_HSV_WHEEL);
BIND_ENUM_CONSTANT(SHAPE_VHS_CIRCLE);
BIND_ENUM_CONSTANT(SHAPE_OKHSL_CIRCLE);
+ BIND_ENUM_CONSTANT(SHAPE_NONE);
}
ColorPicker::ColorPicker() :
@@ -1514,24 +1589,24 @@ ColorPicker::ColorPicker() :
uv_edit->set_v_size_flags(SIZE_EXPAND_FILL);
uv_edit->connect("draw", callable_mp(this, &ColorPicker::_hsv_draw).bind(0, uv_edit));
- HBoxContainer *hb_smpl = memnew(HBoxContainer);
- add_child(hb_smpl, false, INTERNAL_MODE_FRONT);
+ sample_hbc = memnew(HBoxContainer);
+ add_child(sample_hbc, false, INTERNAL_MODE_FRONT);
btn_pick = memnew(Button);
- hb_smpl->add_child(btn_pick);
+ sample_hbc->add_child(btn_pick);
btn_pick->set_toggle_mode(true);
btn_pick->set_tooltip_text(RTR("Pick a color from the editor window."));
btn_pick->connect("pressed", callable_mp(this, &ColorPicker::_screen_pick_pressed));
sample = memnew(TextureRect);
- hb_smpl->add_child(sample);
+ sample_hbc->add_child(sample);
sample->set_h_size_flags(SIZE_EXPAND_FILL);
sample->connect("gui_input", callable_mp(this, &ColorPicker::_sample_input));
sample->connect("draw", callable_mp(this, &ColorPicker::_sample_draw));
btn_shape = memnew(MenuButton);
btn_shape->set_flat(false);
- hb_smpl->add_child(btn_shape);
+ sample_hbc->add_child(btn_shape);
btn_shape->set_toggle_mode(true);
btn_shape->set_tooltip_text(RTR("Select a picker shape."));
@@ -1552,7 +1627,7 @@ ColorPicker::ColorPicker() :
add_mode(new ColorModeRAW(this));
add_mode(new ColorModeOKHSL(this));
- HBoxContainer *mode_hbc = memnew(HBoxContainer);
+ mode_hbc = memnew(HBoxContainer);
add_child(mode_hbc, false, INTERNAL_MODE_FRONT);
mode_group.instantiate();
@@ -1598,26 +1673,26 @@ ColorPicker::ColorPicker() :
add_child(vbr, false, INTERNAL_MODE_FRONT);
vbr->set_h_size_flags(SIZE_EXPAND_FILL);
- GridContainer *gc = memnew(GridContainer);
+ slider_gc = memnew(GridContainer);
- vbr->add_child(gc);
- gc->set_h_size_flags(SIZE_EXPAND_FILL);
- gc->set_columns(3);
+ vbr->add_child(slider_gc);
+ slider_gc->set_h_size_flags(SIZE_EXPAND_FILL);
+ slider_gc->set_columns(3);
for (int i = 0; i < SLIDER_COUNT + 1; i++) {
- create_slider(gc, i);
+ create_slider(slider_gc, i);
}
alpha_label->set_text("A");
- HBoxContainer *hhb = memnew(HBoxContainer);
- hhb->set_alignment(ALIGNMENT_BEGIN);
- vbr->add_child(hhb);
+ hex_hbc = memnew(HBoxContainer);
+ hex_hbc->set_alignment(ALIGNMENT_BEGIN);
+ vbr->add_child(hex_hbc);
- hhb->add_child(memnew(Label("Hex")));
+ hex_hbc->add_child(memnew(Label("Hex")));
text_type = memnew(Button);
- hhb->add_child(text_type);
+ hex_hbc->add_child(text_type);
text_type->set_text("#");
text_type->set_tooltip_text(RTR("Switch between hexadecimal and code values."));
if (Engine::get_singleton()->is_editor_hint()) {
@@ -1628,7 +1703,7 @@ ColorPicker::ColorPicker() :
}
c_text = memnew(LineEdit);
- hhb->add_child(c_text);
+ hex_hbc->add_child(c_text);
c_text->set_select_all_on_focus(true);
c_text->connect("text_submitted", callable_mp(this, &ColorPicker::_html_submitted));
c_text->connect("text_changed", callable_mp(this, &ColorPicker::_text_changed));
diff --git a/scene/gui/color_picker.h b/scene/gui/color_picker.h
index a0843d6fa2..3208676539 100644
--- a/scene/gui/color_picker.h
+++ b/scene/gui/color_picker.h
@@ -86,6 +86,7 @@ public:
SHAPE_HSV_WHEEL,
SHAPE_VHS_CIRCLE,
SHAPE_OKHSL_CIRCLE,
+ SHAPE_NONE,
SHAPE_MAX
};
@@ -125,6 +126,10 @@ private:
PopupMenu *shape_popup = nullptr;
PopupMenu *mode_popup = nullptr;
MenuButton *btn_shape = nullptr;
+ HBoxContainer *mode_hbc = nullptr;
+ HBoxContainer *sample_hbc = nullptr;
+ GridContainer *slider_gc = nullptr;
+ HBoxContainer *hex_hbc = nullptr;
MenuButton *btn_mode = nullptr;
Button *mode_btns[MODE_BUTTON_COUNT];
Ref<ButtonGroup> mode_group = nullptr;
@@ -165,8 +170,12 @@ private:
bool updating = true;
bool changing_color = false;
bool spinning = false;
- bool presets_enabled = true;
+ bool can_add_swatches = true;
bool presets_visible = true;
+ bool color_modes_visible = true;
+ bool sampler_visible = true;
+ bool sliders_visible = true;
+ bool hex_visible = true;
bool line_edit_mouse_release = false;
bool text_changed = false;
@@ -267,12 +276,24 @@ public:
void set_deferred_mode(bool p_enabled);
bool is_deferred_mode() const;
- void set_presets_enabled(bool p_enabled);
- bool are_presets_enabled() const;
+ void set_can_add_swatches(bool p_enabled);
+ bool are_swatches_enabled() const;
void set_presets_visible(bool p_visible);
bool are_presets_visible() const;
+ void set_modes_visible(bool p_visible);
+ bool are_modes_visible() const;
+
+ void set_sampler_visible(bool p_visible);
+ bool is_sampler_visible() const;
+
+ void set_sliders_visible(bool p_visible);
+ bool are_sliders_visible() const;
+
+ void set_hex_visible(bool p_visible);
+ bool is_hex_visible() const;
+
void set_focus_on_line_edit();
ColorPicker();
diff --git a/scene/gui/flow_container.cpp b/scene/gui/flow_container.cpp
index b0d15aa7f4..44c5ec62f8 100644
--- a/scene/gui/flow_container.cpp
+++ b/scene/gui/flow_container.cpp
@@ -152,6 +152,28 @@ void FlowContainer::_resort() {
line_data = lines_data[current_line_idx];
}
+ // The first child of each line adds the offset caused by the alignment,
+ // but only if the line doesn't contain a child that expands.
+ if (child_idx_in_line == 0 && Math::is_equal_approx(line_data.stretch_ratio_total, 0)) {
+ int alignment_ofs = 0;
+ switch (alignment) {
+ case ALIGNMENT_CENTER:
+ alignment_ofs = line_data.stretch_avail / 2;
+ break;
+ case ALIGNMENT_END:
+ alignment_ofs = line_data.stretch_avail;
+ break;
+ default:
+ break;
+ }
+
+ if (vertical) { /* VERTICAL */
+ ofs.y += alignment_ofs;
+ } else { /* HORIZONTAL */
+ ofs.x += alignment_ofs;
+ }
+ }
+
if (vertical) { /* VERTICAL */
if (child->get_h_size_flags() & (SIZE_FILL | SIZE_SHRINK_CENTER | SIZE_SHRINK_END)) {
child_size.width = line_data.min_line_height;
@@ -282,6 +304,18 @@ int FlowContainer::get_line_count() const {
return cached_line_count;
}
+void FlowContainer::set_alignment(AlignmentMode p_alignment) {
+ if (alignment == p_alignment) {
+ return;
+ }
+ alignment = p_alignment;
+ _resort();
+}
+
+FlowContainer::AlignmentMode FlowContainer::get_alignment() const {
+ return alignment;
+}
+
void FlowContainer::set_vertical(bool p_vertical) {
ERR_FAIL_COND_MSG(is_fixed, "Can't change orientation of " + get_class() + ".");
vertical = p_vertical;
@@ -300,8 +334,15 @@ FlowContainer::FlowContainer(bool p_vertical) {
void FlowContainer::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_line_count"), &FlowContainer::get_line_count);
+ ClassDB::bind_method(D_METHOD("set_alignment", "alignment"), &FlowContainer::set_alignment);
+ ClassDB::bind_method(D_METHOD("get_alignment"), &FlowContainer::get_alignment);
ClassDB::bind_method(D_METHOD("set_vertical", "vertical"), &FlowContainer::set_vertical);
ClassDB::bind_method(D_METHOD("is_vertical"), &FlowContainer::is_vertical);
+ BIND_ENUM_CONSTANT(ALIGNMENT_BEGIN);
+ BIND_ENUM_CONSTANT(ALIGNMENT_CENTER);
+ BIND_ENUM_CONSTANT(ALIGNMENT_END);
+
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "alignment", PROPERTY_HINT_ENUM, "Begin,Center,End"), "set_alignment", "get_alignment");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "vertical"), "set_vertical", "is_vertical");
}
diff --git a/scene/gui/flow_container.h b/scene/gui/flow_container.h
index 536df27ad6..6a61e9b904 100644
--- a/scene/gui/flow_container.h
+++ b/scene/gui/flow_container.h
@@ -36,11 +36,19 @@
class FlowContainer : public Container {
GDCLASS(FlowContainer, Container);
+public:
+ enum AlignmentMode {
+ ALIGNMENT_BEGIN,
+ ALIGNMENT_CENTER,
+ ALIGNMENT_END
+ };
+
private:
int cached_size = 0;
int cached_line_count = 0;
bool vertical = false;
+ AlignmentMode alignment = ALIGNMENT_BEGIN;
struct ThemeCache {
int h_separation = 0;
@@ -61,6 +69,9 @@ protected:
public:
int get_line_count() const;
+ void set_alignment(AlignmentMode p_alignment);
+ AlignmentMode get_alignment() const;
+
void set_vertical(bool p_vertical);
bool is_vertical() const;
@@ -88,4 +99,6 @@ public:
FlowContainer(true) { is_fixed = true; }
};
+VARIANT_ENUM_CAST(FlowContainer::AlignmentMode);
+
#endif // FLOW_CONTAINER_H
diff --git a/scene/gui/scroll_container.cpp b/scene/gui/scroll_container.cpp
index a6aa4707ff..ec34a8d26d 100644
--- a/scene/gui/scroll_container.cpp
+++ b/scene/gui/scroll_container.cpp
@@ -107,45 +107,65 @@ void ScrollContainer::gui_input(const Ref<InputEvent> &p_gui_input) {
double prev_v_scroll = v_scroll->get_value();
double prev_h_scroll = h_scroll->get_value();
+ bool h_scroll_enabled = horizontal_scroll_mode != SCROLL_MODE_DISABLED;
+ bool v_scroll_enabled = vertical_scroll_mode != SCROLL_MODE_DISABLED;
Ref<InputEventMouseButton> mb = p_gui_input;
if (mb.is_valid()) {
- if (mb->get_button_index() == MouseButton::WHEEL_UP && mb->is_pressed()) {
- // only horizontal is enabled, scroll horizontally
- if (h_scroll->is_visible() && (!v_scroll->is_visible() || mb->is_shift_pressed())) {
- h_scroll->set_value(h_scroll->get_value() - h_scroll->get_page() / 8 * mb->get_factor());
- } else if (v_scroll->is_visible_in_tree()) {
- v_scroll->set_value(v_scroll->get_value() - v_scroll->get_page() / 8 * mb->get_factor());
+ if (mb->is_pressed()) {
+ bool scroll_value_modified = false;
+
+ bool v_scroll_hidden = !v_scroll->is_visible() && vertical_scroll_mode != SCROLL_MODE_SHOW_NEVER;
+ if (mb->get_button_index() == MouseButton::WHEEL_UP) {
+ // By default, the vertical orientation takes precedence. This is an exception.
+ if ((h_scroll_enabled && mb->is_shift_pressed()) || v_scroll_hidden) {
+ h_scroll->set_value(prev_h_scroll - h_scroll->get_page() / 8 * mb->get_factor());
+ scroll_value_modified = true;
+ } else if (v_scroll_enabled) {
+ v_scroll->set_value(prev_v_scroll - v_scroll->get_page() / 8 * mb->get_factor());
+ scroll_value_modified = true;
+ }
}
- }
-
- if (mb->get_button_index() == MouseButton::WHEEL_DOWN && mb->is_pressed()) {
- // only horizontal is enabled, scroll horizontally
- if (h_scroll->is_visible() && (!v_scroll->is_visible() || mb->is_shift_pressed())) {
- h_scroll->set_value(h_scroll->get_value() + h_scroll->get_page() / 8 * mb->get_factor());
- } else if (v_scroll->is_visible()) {
- v_scroll->set_value(v_scroll->get_value() + v_scroll->get_page() / 8 * mb->get_factor());
+ if (mb->get_button_index() == MouseButton::WHEEL_DOWN) {
+ if ((h_scroll_enabled && mb->is_shift_pressed()) || v_scroll_hidden) {
+ h_scroll->set_value(prev_h_scroll + h_scroll->get_page() / 8 * mb->get_factor());
+ scroll_value_modified = true;
+ } else if (v_scroll_enabled) {
+ v_scroll->set_value(prev_v_scroll + v_scroll->get_page() / 8 * mb->get_factor());
+ scroll_value_modified = true;
+ }
}
- }
- if (mb->get_button_index() == MouseButton::WHEEL_LEFT && mb->is_pressed()) {
- if (h_scroll->is_visible_in_tree()) {
- h_scroll->set_value(h_scroll->get_value() - h_scroll->get_page() * mb->get_factor() / 8);
+ bool h_scroll_hidden = !h_scroll->is_visible() && horizontal_scroll_mode != SCROLL_MODE_SHOW_NEVER;
+ if (mb->get_button_index() == MouseButton::WHEEL_LEFT) {
+ // By default, the horizontal orientation takes precedence. This is an exception.
+ if ((v_scroll_enabled && mb->is_shift_pressed()) || h_scroll_hidden) {
+ v_scroll->set_value(prev_v_scroll - v_scroll->get_page() / 8 * mb->get_factor());
+ scroll_value_modified = true;
+ } else if (h_scroll_enabled) {
+ h_scroll->set_value(prev_h_scroll - h_scroll->get_page() / 8 * mb->get_factor());
+ scroll_value_modified = true;
+ }
}
- }
-
- if (mb->get_button_index() == MouseButton::WHEEL_RIGHT && mb->is_pressed()) {
- if (h_scroll->is_visible_in_tree()) {
- h_scroll->set_value(h_scroll->get_value() + h_scroll->get_page() * mb->get_factor() / 8);
+ if (mb->get_button_index() == MouseButton::WHEEL_RIGHT) {
+ if ((v_scroll_enabled && mb->is_shift_pressed()) || h_scroll_hidden) {
+ v_scroll->set_value(prev_v_scroll + v_scroll->get_page() / 8 * mb->get_factor());
+ scroll_value_modified = true;
+ } else if (h_scroll_enabled) {
+ h_scroll->set_value(prev_h_scroll + h_scroll->get_page() / 8 * mb->get_factor());
+ scroll_value_modified = true;
+ }
}
- }
- if (v_scroll->get_value() != prev_v_scroll || h_scroll->get_value() != prev_h_scroll) {
- accept_event(); //accept event if scroll changed
+ if (scroll_value_modified && (v_scroll->get_value() != prev_v_scroll || h_scroll->get_value() != prev_h_scroll)) {
+ accept_event(); // Accept event if scroll changed.
+ return;
+ }
}
- if (!DisplayServer::get_singleton()->screen_is_touchscreen(DisplayServer::get_singleton()->window_get_current_screen(get_viewport()->get_window_id()))) {
+ bool screen_is_touchscreen = DisplayServer::get_singleton()->screen_is_touchscreen(DisplayServer::get_singleton()->window_get_current_screen(get_viewport()->get_window_id()));
+ if (!screen_is_touchscreen) {
return;
}
@@ -161,8 +181,8 @@ void ScrollContainer::gui_input(const Ref<InputEvent> &p_gui_input) {
drag_speed = Vector2();
drag_accum = Vector2();
last_drag_accum = Vector2();
- drag_from = Vector2(h_scroll->get_value(), v_scroll->get_value());
- drag_touching = DisplayServer::get_singleton()->screen_is_touchscreen(DisplayServer::get_singleton()->window_get_current_screen(get_viewport()->get_window_id()));
+ drag_from = Vector2(prev_h_scroll, prev_v_scroll);
+ drag_touching = screen_is_touchscreen;
drag_touching_deaccel = false;
beyond_deadzone = false;
time_since_motion = 0;
@@ -180,6 +200,7 @@ void ScrollContainer::gui_input(const Ref<InputEvent> &p_gui_input) {
}
}
}
+ return;
}
Ref<InputEventMouseMotion> mm = p_gui_input;
@@ -189,22 +210,22 @@ void ScrollContainer::gui_input(const Ref<InputEvent> &p_gui_input) {
Vector2 motion = mm->get_relative();
drag_accum -= motion;
- if (beyond_deadzone || (horizontal_scroll_mode != SCROLL_MODE_DISABLED && Math::abs(drag_accum.x) > deadzone) || (vertical_scroll_mode != SCROLL_MODE_DISABLED && Math::abs(drag_accum.y) > deadzone)) {
+ if (beyond_deadzone || (h_scroll_enabled && Math::abs(drag_accum.x) > deadzone) || (v_scroll_enabled && Math::abs(drag_accum.y) > deadzone)) {
if (!beyond_deadzone) {
propagate_notification(NOTIFICATION_SCROLL_BEGIN);
emit_signal(SNAME("scroll_started"));
beyond_deadzone = true;
- // resetting drag_accum here ensures smooth scrolling after reaching deadzone
+ // Resetting drag_accum here ensures smooth scrolling after reaching deadzone.
drag_accum = -motion;
}
Vector2 diff = drag_from + drag_accum;
- if (horizontal_scroll_mode != SCROLL_MODE_DISABLED) {
+ if (h_scroll_enabled) {
h_scroll->set_value(diff.x);
} else {
drag_accum.x = 0;
}
- if (vertical_scroll_mode != SCROLL_MODE_DISABLED) {
+ if (v_scroll_enabled) {
v_scroll->set_value(diff.y);
} else {
drag_accum.y = 0;
@@ -212,20 +233,26 @@ void ScrollContainer::gui_input(const Ref<InputEvent> &p_gui_input) {
time_since_motion = 0;
}
}
+
+ if (v_scroll->get_value() != prev_v_scroll || h_scroll->get_value() != prev_h_scroll) {
+ accept_event(); // Accept event if scroll changed.
+ }
+ return;
}
Ref<InputEventPanGesture> pan_gesture = p_gui_input;
if (pan_gesture.is_valid()) {
- if (h_scroll->is_visible_in_tree()) {
- h_scroll->set_value(h_scroll->get_value() + h_scroll->get_page() * pan_gesture->get_delta().x / 8);
+ if (h_scroll_enabled) {
+ h_scroll->set_value(prev_h_scroll + h_scroll->get_page() * pan_gesture->get_delta().x / 8);
}
- if (v_scroll->is_visible_in_tree()) {
- v_scroll->set_value(v_scroll->get_value() + v_scroll->get_page() * pan_gesture->get_delta().y / 8);
+ if (v_scroll_enabled) {
+ v_scroll->set_value(prev_v_scroll + v_scroll->get_page() * pan_gesture->get_delta().y / 8);
}
- }
- if (v_scroll->get_value() != prev_v_scroll || h_scroll->get_value() != prev_h_scroll) {
- accept_event(); //accept event if scroll changed
+ if (v_scroll->get_value() != prev_v_scroll || h_scroll->get_value() != prev_h_scroll) {
+ accept_event(); // Accept event if scroll changed.
+ }
+ return;
}
}
diff --git a/scene/gui/tab_container.cpp b/scene/gui/tab_container.cpp
index ab4808d312..9105267ad3 100644
--- a/scene/gui/tab_container.cpp
+++ b/scene/gui/tab_container.cpp
@@ -345,7 +345,7 @@ Vector<Control *> TabContainer::_get_tab_controls() const {
Vector<Control *> controls;
for (int i = 0; i < get_child_count(); i++) {
Control *control = Object::cast_to<Control>(get_child(i));
- if (!control || control->is_set_as_top_level() || control == tab_bar || control == child_removing) {
+ if (!control || control->is_set_as_top_level() || control == tab_bar || children_removing.has(control)) {
continue;
}
@@ -584,10 +584,10 @@ void TabContainer::remove_child_notify(Node *p_child) {
int idx = get_tab_idx_from_control(c);
- // Before this, the tab control has not changed; after this, the tab control has changed.
- child_removing = p_child;
+ // As the child hasn't been removed yet, keep track of it so when the "tab_changed" signal is fired it can be ignored.
+ children_removing.push_back(c);
tab_bar->remove_tab(idx);
- child_removing = nullptr;
+ children_removing.erase(c);
_update_margins();
if (get_tab_count() == 0) {
diff --git a/scene/gui/tab_container.h b/scene/gui/tab_container.h
index b552aa459b..60961e02d3 100644
--- a/scene/gui/tab_container.h
+++ b/scene/gui/tab_container.h
@@ -46,7 +46,7 @@ class TabContainer : public Container {
bool drag_to_rearrange_enabled = false;
bool use_hidden_tabs_for_min_size = false;
bool theme_changing = false;
- Node *child_removing = nullptr;
+ Vector<Control *> children_removing;
struct ThemeCache {
int side_margin = 0;
diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp
index 144aa2a1ef..1b8444abf4 100644
--- a/scene/gui/text_edit.cpp
+++ b/scene/gui/text_edit.cpp
@@ -833,7 +833,7 @@ void TextEdit::_notification(int p_what) {
continue;
}
- // If we've changed colour we are at the start of a new section, therefore we need to go back to the end
+ // If we've changed color we are at the start of a new section, therefore we need to go back to the end
// of the previous section to draw it, we'll also add the character back on.
if (color != previous_color) {
characters--;
@@ -2051,7 +2051,8 @@ void TextEdit::gui_input(const Ref<InputEvent> &p_gui_input) {
}
if (is_shortcut_keys_enabled()) {
- // SELECT ALL, SELECT WORD UNDER CARET, ADD SELECTION FOR NEXT OCCURRENCE, CUT, COPY, PASTE.
+ // SELECT ALL, SELECT WORD UNDER CARET, ADD SELECTION FOR NEXT OCCURRENCE,
+ // CLEAR CARETS AND SELECTIONS, CUT, COPY, PASTE.
if (k->is_action("ui_text_select_all", true)) {
select_all();
accept_event();
@@ -2067,6 +2068,13 @@ void TextEdit::gui_input(const Ref<InputEvent> &p_gui_input) {
accept_event();
return;
}
+ if (k->is_action("ui_text_clear_carets_and_selection", true)) {
+ // Since the default shortcut is ESC, accepts the event only if it's actually performed.
+ if (_clear_carets_and_selection()) {
+ accept_event();
+ return;
+ }
+ }
if (k->is_action("ui_cut", true)) {
cut();
accept_event();
@@ -2651,7 +2659,7 @@ void TextEdit::_do_backspace(bool p_word, bool p_all_to_left) {
set_caret_line(get_caret_line(caret_idx), false, true, 0, caret_idx);
set_caret_column(column, caret_idx == 0, caret_idx);
- // Now we can clean up the overlaping caret.
+ // Now we can clean up the overlapping caret.
if (overlapping_caret_index != -1) {
backspace(overlapping_caret_index);
i++;
@@ -2819,6 +2827,20 @@ void TextEdit::_move_caret_document_end(bool p_select) {
}
}
+bool TextEdit::_clear_carets_and_selection() {
+ if (get_caret_count() > 1) {
+ remove_secondary_carets();
+ return true;
+ }
+
+ if (has_selection()) {
+ deselect();
+ return true;
+ }
+
+ return false;
+}
+
void TextEdit::_get_above_below_caret_line_column(int p_old_line, int p_old_wrap_index, int p_old_column, bool p_below, int &p_new_line, int &p_new_column, int p_last_fit_x) const {
if (p_last_fit_x == -1) {
p_last_fit_x = _get_column_x_offset_for_line(p_old_column, p_old_line, p_old_column);
@@ -6538,7 +6560,7 @@ void TextEdit::_cut_internal(int p_caret) {
int indent_level = get_indent_level(cl);
double hscroll = get_h_scroll();
- // Check for overlaping carets.
+ // Check for overlapping carets.
// We don't need to worry about selections as that is caught before this entire section.
for (int j = i - 1; j >= 0; j--) {
if (get_caret_line(caret_edit_order[j]) == cl) {
diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h
index 935f2a7ce8..92acbaf521 100644
--- a/scene/gui/text_edit.h
+++ b/scene/gui/text_edit.h
@@ -597,6 +597,7 @@ private:
void _delete(bool p_word = false, bool p_all_to_right = false);
void _move_caret_document_start(bool p_select);
void _move_caret_document_end(bool p_select);
+ bool _clear_carets_and_selection();
// Used in add_caret_at_carets
void _get_above_below_caret_line_column(int p_old_line, int p_old_wrap_index, int p_old_column, bool p_below, int &p_new_line, int &p_new_column, int p_last_fit_x = -1) const;