summaryrefslogtreecommitdiff
path: root/scene/gui
diff options
context:
space:
mode:
Diffstat (limited to 'scene/gui')
-rw-r--r--scene/gui/base_button.cpp12
-rw-r--r--scene/gui/base_button.h3
-rw-r--r--scene/gui/code_edit.cpp35
-rw-r--r--scene/gui/code_edit.h10
-rw-r--r--scene/gui/color_picker.cpp198
-rw-r--r--scene/gui/color_picker.h39
-rw-r--r--scene/gui/control.cpp85
-rw-r--r--scene/gui/control.h10
-rw-r--r--scene/gui/graph_edit.cpp105
-rw-r--r--scene/gui/graph_edit.h5
-rw-r--r--scene/gui/popup_menu.cpp7
-rw-r--r--scene/gui/rich_text_effect.cpp29
-rw-r--r--scene/gui/rich_text_effect.h32
-rw-r--r--scene/gui/rich_text_label.cpp4
-rw-r--r--scene/gui/shortcut.cpp2
-rw-r--r--scene/gui/text_edit.cpp51
-rw-r--r--scene/gui/text_edit.h18
17 files changed, 341 insertions, 304 deletions
diff --git a/scene/gui/base_button.cpp b/scene/gui/base_button.cpp
index d252a4507c..03c75b25f4 100644
--- a/scene/gui/base_button.cpp
+++ b/scene/gui/base_button.cpp
@@ -121,17 +121,13 @@ void BaseButton::_notification(int p_what) {
}
void BaseButton::_pressed() {
- if (get_script_instance()) {
- get_script_instance()->call(SceneStringNames::get_singleton()->_pressed);
- }
+ GDVIRTUAL_CALL(_pressed);
pressed();
emit_signal(SNAME("pressed"));
}
void BaseButton::_toggled(bool p_pressed) {
- if (get_script_instance()) {
- get_script_instance()->call(SceneStringNames::get_singleton()->_toggled, p_pressed);
- }
+ GDVIRTUAL_CALL(_toggled, p_pressed);
toggled(p_pressed);
emit_signal(SNAME("toggled"), p_pressed);
}
@@ -440,8 +436,8 @@ void BaseButton::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_shortcut_context", "node"), &BaseButton::set_shortcut_context);
ClassDB::bind_method(D_METHOD("get_shortcut_context"), &BaseButton::get_shortcut_context);
- BIND_VMETHOD(MethodInfo("_pressed"));
- BIND_VMETHOD(MethodInfo("_toggled", PropertyInfo(Variant::BOOL, "button_pressed")));
+ GDVIRTUAL_BIND(_pressed);
+ GDVIRTUAL_BIND(_toggled, "button_pressed");
ADD_SIGNAL(MethodInfo("pressed"));
ADD_SIGNAL(MethodInfo("button_up"));
diff --git a/scene/gui/base_button.h b/scene/gui/base_button.h
index d86b35daf0..cf1904344b 100644
--- a/scene/gui/base_button.h
+++ b/scene/gui/base_button.h
@@ -81,6 +81,9 @@ protected:
bool _is_focus_owner_in_shorcut_context() const;
+ GDVIRTUAL0(_pressed)
+ GDVIRTUAL1(_toggled, bool)
+
public:
enum DrawMode {
DRAW_NORMAL,
diff --git a/scene/gui/code_edit.cpp b/scene/gui/code_edit.cpp
index 08dd7f28eb..7cc2352353 100644
--- a/scene/gui/code_edit.cpp
+++ b/scene/gui/code_edit.cpp
@@ -450,7 +450,7 @@ void CodeEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
}
if (k->is_action("ui_text_backspace", true)) {
backspace();
- _filter_code_completion_candidates();
+ _filter_code_completion_candidates_impl();
accept_event();
return;
}
@@ -522,7 +522,7 @@ void CodeEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
TextEdit::_gui_input(p_gui_input);
if (update_code_completion) {
- _filter_code_completion_candidates();
+ _filter_code_completion_candidates_impl();
}
}
@@ -557,7 +557,7 @@ Control::CursorShape CodeEdit::get_cursor_shape(const Point2 &p_pos) const {
/* Text manipulation */
// Overridable actions
-void CodeEdit::_handle_unicode_input(const uint32_t p_unicode) {
+void CodeEdit::_handle_unicode_input_internal(const uint32_t p_unicode) {
bool had_selection = has_selection();
if (had_selection) {
begin_complex_operation();
@@ -609,7 +609,7 @@ void CodeEdit::_handle_unicode_input(const uint32_t p_unicode) {
}
}
-void CodeEdit::_backspace() {
+void CodeEdit::_backspace_internal() {
if (!is_editable()) {
return;
}
@@ -1739,9 +1739,7 @@ String CodeEdit::get_text_for_code_completion() const {
}
void CodeEdit::request_code_completion(bool p_force) {
- ScriptInstance *si = get_script_instance();
- if (si && si->has_method("_request_code_completion")) {
- si->call("_request_code_completion", p_force);
+ if (GDVIRTUAL_CALL(_request_code_completion, p_force)) {
return;
}
@@ -1798,7 +1796,7 @@ void CodeEdit::update_code_completion_options(bool p_forced) {
code_completion_forced = p_forced;
code_completion_option_sources = code_completion_option_submitted;
code_completion_option_submitted.clear();
- _filter_code_completion_candidates();
+ _filter_code_completion_candidates_impl();
}
TypedArray<Dictionary> CodeEdit::get_code_completion_options() const {
@@ -1855,11 +1853,10 @@ void CodeEdit::confirm_code_completion(bool p_replace) {
return;
}
- ScriptInstance *si = get_script_instance();
- if (si && si->has_method("_confirm_code_completion")) {
- si->call("_confirm_code_completion", p_replace);
+ if (GDVIRTUAL_CALL(_confirm_code_completion, p_replace)) {
return;
}
+
begin_complex_operation();
int caret_line = get_caret_line();
@@ -2179,9 +2176,10 @@ void CodeEdit::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_code_comletion_prefixes"), &CodeEdit::get_code_completion_prefixes);
// Overridable
- BIND_VMETHOD(MethodInfo("_confirm_code_completion", PropertyInfo(Variant::BOOL, "replace")));
- BIND_VMETHOD(MethodInfo("_request_code_completion", PropertyInfo(Variant::BOOL, "force")));
- BIND_VMETHOD(MethodInfo(Variant::ARRAY, "_filter_code_completion_candidates", PropertyInfo(Variant::ARRAY, "candidates")));
+
+ GDVIRTUAL_BIND(_confirm_code_completion, "replace")
+ GDVIRTUAL_BIND(_request_code_completion, "force")
+ GDVIRTUAL_BIND(_filter_code_completion_candidates, "candidates")
/* Line length guidelines */
ClassDB::bind_method(D_METHOD("set_line_length_guidelines", "guideline_columns"), &CodeEdit::set_line_length_guidelines);
@@ -2650,11 +2648,10 @@ TypedArray<String> CodeEdit::_get_delimiters(DelimiterType p_type) const {
}
/* Code Completion */
-void CodeEdit::_filter_code_completion_candidates() {
- ScriptInstance *si = get_script_instance();
+void CodeEdit::_filter_code_completion_candidates_impl() {
int line_height = get_line_height();
- if (si && si->has_method("_filter_code_completion_candidates")) {
+ if (GDVIRTUAL_IS_OVERRIDEN(_filter_code_completion_candidates)) {
code_completion_options.clear();
code_completion_base = "";
@@ -2674,7 +2671,9 @@ void CodeEdit::_filter_code_completion_candidates() {
i++;
}
- TypedArray<Dictionary> completion_options = si->call("_filter_code_completion_candidates", completion_options_sources);
+ Array completion_options;
+
+ GDVIRTUAL_CALL(_filter_code_completion_candidates, completion_options_sources, completion_options);
/* No options to complete, cancel. */
if (completion_options.size() == 0) {
diff --git a/scene/gui/code_edit.h b/scene/gui/code_edit.h
index 76ac15f553..aa62cbdf3c 100644
--- a/scene/gui/code_edit.h
+++ b/scene/gui/code_edit.h
@@ -219,7 +219,7 @@ private:
List<ScriptCodeCompletionOption> code_completion_option_sources;
String code_completion_base;
- void _filter_code_completion_candidates();
+ void _filter_code_completion_candidates_impl();
/* Line length guidelines */
TypedArray<int> line_length_guideline_columns;
@@ -256,8 +256,12 @@ protected:
/* Text manipulation */
// Overridable actions
- virtual void _handle_unicode_input(const uint32_t p_unicode) override;
- virtual void _backspace() override;
+ virtual void _handle_unicode_input_internal(const uint32_t p_unicode) override;
+ virtual void _backspace_internal() override;
+
+ GDVIRTUAL1(_confirm_code_completion, bool)
+ GDVIRTUAL1(_request_code_completion, bool)
+ GDVIRTUAL1RC(Array, _filter_code_completion_candidates, TypedArray<Dictionary>)
public:
/* General overrides */
diff --git a/scene/gui/color_picker.cpp b/scene/gui/color_picker.cpp
index 261480bcdd..661e0dc648 100644
--- a/scene/gui/color_picker.cpp
+++ b/scene/gui/color_picker.cpp
@@ -46,13 +46,13 @@ void ColorPicker::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_THEME_CHANGED: {
btn_pick->set_icon(get_theme_icon(SNAME("screen_picker"), SNAME("ColorPicker")));
- bt_add_preset->set_icon(get_theme_icon(SNAME("add_preset")));
-
+ btn_add_preset->set_icon(get_theme_icon(SNAME("add_preset")));
+ _update_presets();
_update_controls();
} break;
case NOTIFICATION_ENTER_TREE: {
btn_pick->set_icon(get_theme_icon(SNAME("screen_picker"), SNAME("ColorPicker")));
- bt_add_preset->set_icon(get_theme_icon(SNAME("add_preset")));
+ btn_add_preset->set_icon(get_theme_icon(SNAME("add_preset")));
_update_controls();
_update_color();
@@ -69,7 +69,6 @@ void ColorPicker::_notification(int p_what) {
for (int i = 0; i < preset_cache.size(); i++) {
presets.push_back(preset_cache[i]);
}
- preset->update();
}
#endif
} break;
@@ -372,22 +371,23 @@ void ColorPicker::_update_color(bool p_update_sliders) {
}
void ColorPicker::_update_presets() {
- return;
- //presets should be shown using buttons or something else, this method is not a good idea
-
- presets_per_row = 10;
- Size2 size = bt_add_preset->get_size();
- Size2 preset_size = Size2(MIN(size.width * presets.size(), presets_per_row * size.width), size.height * (Math::ceil((float)presets.size() / presets_per_row)));
- preset->set_custom_minimum_size(preset_size);
- preset_container->set_custom_minimum_size(preset_size);
- preset->draw_rect(Rect2(Point2(), preset_size), Color(1, 1, 1, 0));
-
- for (int i = 0; i < presets.size(); i++) {
- int x = (i % presets_per_row) * size.width;
- int y = (Math::floor((float)i / presets_per_row)) * size.height;
- preset->draw_rect(Rect2(Point2(x, y), size), presets[i]);
+ int preset_size = _get_preset_size();
+ // Only update the preset button size if it has changed.
+ if (preset_size != prev_preset_size) {
+ prev_preset_size = preset_size;
+ btn_add_preset->set_custom_minimum_size(Size2(preset_size, preset_size));
+ for (int i = 1; i < preset_container->get_child_count(); i++) {
+ ColorPresetButton *cpb = Object::cast_to<ColorPresetButton>(preset_container->get_child(i));
+ cpb->set_custom_minimum_size(Size2(preset_size, preset_size));
+ }
+ }
+ // Only load preset buttons when the only child is the add-preset button.
+ if (preset_container->get_child_count() == 1) {
+ for (int i = 0; i < preset_cache.size(); i++) {
+ _add_preset_button(preset_size, preset_cache[i]);
+ }
+ _notification(NOTIFICATION_VISIBILITY_CHANGED);
}
- _notification(NOTIFICATION_VISIBILITY_CHANGED);
}
void ColorPicker::_text_type_toggled() {
@@ -422,14 +422,37 @@ ColorPicker::PickerShapeType ColorPicker::get_picker_shape() const {
return picker_type;
}
+inline int ColorPicker::_get_preset_size() {
+ return (int(get_minimum_size().width) - (preset_container->get_theme_constant(SNAME("hseparation")) * (preset_column_count - 1))) / preset_column_count;
+}
+
+void ColorPicker::_add_preset_button(int p_size, const Color &p_color) {
+ ColorPresetButton *btn_preset = memnew(ColorPresetButton(p_color));
+ btn_preset->set_preset_color(p_color);
+ btn_preset->set_custom_minimum_size(Size2(p_size, p_size));
+ btn_preset->connect("gui_input", callable_mp(this, &ColorPicker::_preset_input), varray(p_color));
+ btn_preset->set_tooltip(vformat(RTR("Color: #%s\nLMB: Apply color\nRMB: Remove preset"), p_color.to_html(p_color.a < 1)));
+ preset_container->add_child(btn_preset);
+}
+
void ColorPicker::add_preset(const Color &p_color) {
if (presets.find(p_color)) {
presets.move_to_back(presets.find(p_color));
+
+ // Find button to move to the end.
+ for (int i = 1; i < preset_container->get_child_count(); i++) {
+ ColorPresetButton *current_btn = Object::cast_to<ColorPresetButton>(preset_container->get_child(i));
+ if (current_btn && p_color == current_btn->get_preset_color()) {
+ preset_container->move_child(current_btn, preset_container->get_child_count() - 1);
+ break;
+ }
+ }
} else {
presets.push_back(p_color);
preset_cache.push_back(p_color);
+
+ _add_preset_button(_get_preset_size(), p_color);
}
- preset->update();
#ifdef TOOLS_ENABLED
if (Engine::get_singleton()->is_editor_hint()) {
@@ -443,7 +466,15 @@ void ColorPicker::erase_preset(const Color &p_color) {
if (presets.find(p_color)) {
presets.erase(presets.find(p_color));
preset_cache.erase(preset_cache.find(p_color));
- preset->update();
+
+ // Find preset button to remove.
+ for (int i = 1; i < preset_container->get_child_count(); i++) {
+ ColorPresetButton *current_btn = Object::cast_to<ColorPresetButton>(preset_container->get_child(i));
+ if (current_btn && p_color == current_btn->get_preset_color()) {
+ current_btn->queue_delete();
+ break;
+ }
+ }
#ifdef TOOLS_ENABLED
if (Engine::get_singleton()->is_editor_hint()) {
@@ -560,7 +591,7 @@ void ColorPicker::_sample_draw() {
const Rect2 rect_old = Rect2(Point2(), Size2(sample->get_size().width * 0.5, sample->get_size().height * 0.95));
if (display_old_color && old_color.a < 1.0) {
- sample->draw_texture_rect(get_theme_icon(SNAME("preset_bg"), SNAME("ColorPicker")), rect_old, true);
+ sample->draw_texture_rect(get_theme_icon(SNAME("sample_bg"), SNAME("ColorPicker")), rect_old, true);
}
sample->draw_rect(rect_old, old_color);
@@ -574,7 +605,7 @@ void ColorPicker::_sample_draw() {
}
if (color.a < 1.0) {
- sample->draw_texture_rect(get_theme_icon(SNAME("preset_bg"), SNAME("ColorPicker")), rect_new, true);
+ sample->draw_texture_rect(get_theme_icon(SNAME("sample_bg"), SNAME("ColorPicker")), rect_new, true);
}
sample->draw_rect(rect_new, color);
@@ -734,7 +765,7 @@ void ColorPicker::_slider_draw(int p_which) {
#endif
if (p_which == 3) {
- scroll[p_which]->draw_texture_rect(get_theme_icon(SNAME("preset_bg"), SNAME("ColorPicker")), Rect2(Point2(0, margin), Size2(size.x, margin)), true);
+ scroll[p_which]->draw_texture_rect(get_theme_icon(SNAME("sample_bg"), SNAME("ColorPicker")), Rect2(Point2(0, margin), Size2(size.x, margin)), true);
left_color = color;
left_color.a = 0;
@@ -932,43 +963,19 @@ void ColorPicker::_w_input(const Ref<InputEvent> &p_event) {
}
}
-void ColorPicker::_preset_input(const Ref<InputEvent> &p_event) {
+void ColorPicker::_preset_input(const Ref<InputEvent> &p_event, const Color &p_color) {
Ref<InputEventMouseButton> bev = p_event;
if (bev.is_valid()) {
- int index = 0;
if (bev->is_pressed() && bev->get_button_index() == MOUSE_BUTTON_LEFT) {
- for (int i = 0; i < presets.size(); i++) {
- int x = (i % presets_per_row) * bt_add_preset->get_size().x;
- int y = (Math::floor((float)i / presets_per_row)) * bt_add_preset->get_size().y;
- if (bev->get_position().x > x && bev->get_position().x < x + preset->get_size().x && bev->get_position().y > y && bev->get_position().y < y + preset->get_size().y) {
- index = i;
- }
- }
- set_pick_color(presets[index]);
+ set_pick_color(p_color);
_update_color();
- emit_signal(SNAME("color_changed"), color);
+ emit_signal(SNAME("color_changed"), p_color);
} else if (bev->is_pressed() && bev->get_button_index() == MOUSE_BUTTON_RIGHT && presets_enabled) {
- index = bev->get_position().x / (preset->get_size().x / presets.size());
- Color clicked_preset = presets[index];
- erase_preset(clicked_preset);
- emit_signal(SNAME("preset_removed"), clicked_preset);
- bt_add_preset->show();
+ erase_preset(p_color);
+ emit_signal(SNAME("preset_removed"), p_color);
}
}
-
- Ref<InputEventMouseMotion> mev = p_event;
-
- if (mev.is_valid()) {
- int index = mev->get_position().x * presets.size();
- if (preset->get_size().x != 0) {
- index /= preset->get_size().x;
- }
- if (index < 0 || index >= presets.size()) {
- return;
- }
- preset->set_tooltip(vformat(RTR("Color: #%s\nLMB: Set color\nRMB: Remove preset"), presets[index].to_html(presets[index].a < 1)));
- }
}
void ColorPicker::_screen_input(const Ref<InputEvent> &p_event) {
@@ -1064,11 +1071,11 @@ void ColorPicker::_html_focus_exit() {
void ColorPicker::set_presets_enabled(bool p_enabled) {
presets_enabled = p_enabled;
if (!p_enabled) {
- bt_add_preset->set_disabled(true);
- bt_add_preset->set_focus_mode(FOCUS_NONE);
+ btn_add_preset->set_disabled(true);
+ btn_add_preset->set_focus_mode(FOCUS_NONE);
} else {
- bt_add_preset->set_disabled(false);
- bt_add_preset->set_focus_mode(FOCUS_ALL);
+ btn_add_preset->set_disabled(false);
+ btn_add_preset->set_focus_mode(FOCUS_ALL);
}
}
@@ -1080,7 +1087,6 @@ void ColorPicker::set_presets_visible(bool p_visible) {
presets_visible = p_visible;
preset_separator->set_visible(p_visible);
preset_container->set_visible(p_visible);
- preset_container2->set_visible(p_visible);
}
bool ColorPicker::are_presets_visible() const {
@@ -1266,17 +1272,13 @@ ColorPicker::ColorPicker() :
add_child(preset_separator);
preset_container->set_h_size_flags(SIZE_EXPAND_FILL);
+ preset_container->set_columns(preset_column_count);
add_child(preset_container);
- preset_container->add_child(preset);
- preset->connect("gui_input", callable_mp(this, &ColorPicker::_preset_input));
- preset->connect("draw", callable_mp(this, &ColorPicker::_update_presets));
-
- preset_container2->set_h_size_flags(SIZE_EXPAND_FILL);
- add_child(preset_container2);
- preset_container2->add_child(bt_add_preset);
- bt_add_preset->set_tooltip(RTR("Add current color as a preset."));
- bt_add_preset->connect("pressed", callable_mp(this, &ColorPicker::_add_preset_pressed));
+ btn_add_preset->set_icon_align(Button::ALIGN_CENTER);
+ btn_add_preset->set_tooltip(RTR("Add current color as a preset."));
+ btn_add_preset->connect("pressed", callable_mp(this, &ColorPicker::_add_preset_pressed));
+ preset_container->add_child(btn_add_preset);
}
/////////////////
@@ -1303,6 +1305,7 @@ void ColorPickerButton::pressed() {
_update_picker();
popup->set_as_minsize();
+ picker->_update_presets();
Rect2i usable_rect = popup->get_usable_parent_rect();
//let's try different positions to see which one we can use
@@ -1428,3 +1431,64 @@ void ColorPickerButton::_bind_methods() {
ColorPickerButton::ColorPickerButton() {
set_toggle_mode(true);
}
+
+/////////////////
+
+void ColorPresetButton::_notification(int p_what) {
+ switch (p_what) {
+ case NOTIFICATION_DRAW: {
+ const Rect2 r = Rect2(Point2(0, 0), get_size());
+ Ref<StyleBox> sb_raw = get_theme_stylebox(SNAME("preset_fg"), SNAME("ColorPresetButton"))->duplicate();
+ Ref<StyleBoxFlat> sb_flat = sb_raw;
+ Ref<StyleBoxTexture> sb_texture = sb_raw;
+
+ if (sb_flat.is_valid()) {
+ if (preset_color.a < 1) {
+ // Draw a background pattern when the color is transparent.
+ sb_flat->set_bg_color(Color(1, 1, 1));
+ sb_flat->draw(get_canvas_item(), r);
+
+ Rect2 bg_texture_rect = r.grow_side(SIDE_LEFT, -sb_flat->get_margin(SIDE_LEFT));
+ bg_texture_rect = bg_texture_rect.grow_side(SIDE_RIGHT, -sb_flat->get_margin(SIDE_RIGHT));
+ bg_texture_rect = bg_texture_rect.grow_side(SIDE_TOP, -sb_flat->get_margin(SIDE_TOP));
+ bg_texture_rect = bg_texture_rect.grow_side(SIDE_BOTTOM, -sb_flat->get_margin(SIDE_BOTTOM));
+
+ draw_texture_rect(get_theme_icon(SNAME("preset_bg"), SNAME("ColorPresetButton")), bg_texture_rect, true);
+ sb_flat->set_bg_color(preset_color);
+ }
+ sb_flat->set_bg_color(preset_color);
+ sb_flat->draw(get_canvas_item(), r);
+ } else if (sb_texture.is_valid()) {
+ if (preset_color.a < 1) {
+ // Draw a background pattern when the color is transparent.
+ bool use_tile_texture = (sb_texture->get_h_axis_stretch_mode() == StyleBoxTexture::AxisStretchMode::AXIS_STRETCH_MODE_TILE) || (sb_texture->get_h_axis_stretch_mode() == StyleBoxTexture::AxisStretchMode::AXIS_STRETCH_MODE_TILE_FIT);
+ draw_texture_rect(get_theme_icon(SNAME("preset_bg"), SNAME("ColorPresetButton")), r, use_tile_texture);
+ }
+ sb_texture->set_modulate(preset_color);
+ sb_texture->draw(get_canvas_item(), r);
+ } else {
+ WARN_PRINT("Unsupported StyleBox used for ColorPresetButton. Use StyleBoxFlat or StyleBoxTexture instead.");
+ }
+ if (preset_color.r > 1 || preset_color.g > 1 || preset_color.b > 1) {
+ // Draw an indicator to denote that the color is "overbright" and can't be displayed accurately in the preview
+ draw_texture(Control::get_theme_icon(SNAME("overbright_indicator"), SNAME("ColorPresetButton")), Vector2(0, 0));
+ }
+
+ } break;
+ }
+}
+
+void ColorPresetButton::set_preset_color(const Color &p_color) {
+ preset_color = p_color;
+}
+
+Color ColorPresetButton::get_preset_color() const {
+ return preset_color;
+}
+
+ColorPresetButton::ColorPresetButton(Color p_color) {
+ preset_color = p_color;
+}
+
+ColorPresetButton::~ColorPresetButton() {
+}
diff --git a/scene/gui/color_picker.h b/scene/gui/color_picker.h
index 60da3957aa..67ca007eb5 100644
--- a/scene/gui/color_picker.h
+++ b/scene/gui/color_picker.h
@@ -35,6 +35,7 @@
#include "scene/gui/box_container.h"
#include "scene/gui/button.h"
#include "scene/gui/check_button.h"
+#include "scene/gui/grid_container.h"
#include "scene/gui/label.h"
#include "scene/gui/line_edit.h"
#include "scene/gui/popup.h"
@@ -43,6 +44,22 @@
#include "scene/gui/spin_box.h"
#include "scene/gui/texture_rect.h"
+class ColorPresetButton : public BaseButton {
+ GDCLASS(ColorPresetButton, BaseButton);
+
+ Color preset_color;
+
+protected:
+ void _notification(int);
+
+public:
+ void set_preset_color(const Color &p_color);
+ Color get_preset_color() const;
+
+ ColorPresetButton(Color p_color);
+ ~ColorPresetButton();
+};
+
class ColorPicker : public BoxContainer {
GDCLASS(ColorPicker, BoxContainer);
@@ -69,12 +86,9 @@ private:
Control *wheel = memnew(Control);
Control *wheel_uv = memnew(Control);
TextureRect *sample = memnew(TextureRect);
- TextureRect *preset = memnew(TextureRect);
- HBoxContainer *preset_container = memnew(HBoxContainer);
- HBoxContainer *preset_container2 = memnew(HBoxContainer);
+ GridContainer *preset_container = memnew(GridContainer);
HSeparator *preset_separator = memnew(HSeparator);
- Button *bt_add_preset = memnew(Button);
- List<Color> presets;
+ Button *btn_add_preset = memnew(Button);
Button *btn_pick = memnew(Button);
CheckButton *btn_hsv = memnew(CheckButton);
CheckButton *btn_raw = memnew(CheckButton);
@@ -83,14 +97,19 @@ private:
Label *labels[4];
Button *text_type = memnew(Button);
LineEdit *c_text = memnew(LineEdit);
+
bool edit_alpha = true;
Size2i ms;
bool text_is_constructor = false;
- int presets_per_row = 0;
PickerShapeType picker_type = SHAPE_HSV_WHEEL;
+ const int preset_column_count = 9;
+ int prev_preset_size = 0;
+ List<Color> presets;
+
Color color;
Color old_color;
+
bool display_old_color = false;
bool raw_mode_enabled = false;
bool hsv_mode_enabled = false;
@@ -100,6 +119,7 @@ private:
bool spinning = false;
bool presets_enabled = true;
bool presets_visible = true;
+
float h = 0.0;
float s = 0.0;
float v = 0.0;
@@ -109,7 +129,6 @@ private:
void _value_changed(double);
void _update_controls();
void _update_color(bool p_update_sliders = true);
- void _update_presets();
void _update_text_value();
void _text_type_toggled();
void _sample_input(const Ref<InputEvent> &p_event);
@@ -119,7 +138,7 @@ private:
void _uv_input(const Ref<InputEvent> &p_event, Control *c);
void _w_input(const Ref<InputEvent> &p_event);
- void _preset_input(const Ref<InputEvent> &p_event);
+ void _preset_input(const Ref<InputEvent> &p_event, const Color &p_color);
void _screen_input(const Ref<InputEvent> &p_event);
void _add_preset_pressed();
void _screen_pick_pressed();
@@ -127,6 +146,9 @@ private:
void _focus_exit();
void _html_focus_exit();
+ inline int _get_preset_size();
+ void _add_preset_button(int p_size, const Color &p_color);
+
protected:
void _notification(int);
static void _bind_methods();
@@ -152,6 +174,7 @@ public:
void add_preset(const Color &p_color);
void erase_preset(const Color &p_color);
PackedColorArray get_presets() const;
+ void _update_presets();
void set_hsv_mode(bool p_enabled);
bool is_hsv_mode() const;
diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp
index f114e06c75..6dba23d3c7 100644
--- a/scene/gui/control.cpp
+++ b/scene/gui/control.cpp
@@ -730,14 +730,9 @@ Variant Control::get_drag_data(const Point2 &p_point) {
}
}
- if (get_script_instance()) {
- Variant v = p_point;
- const Variant *p = &v;
- Callable::CallError ce;
- Variant ret = get_script_instance()->call(SceneStringNames::get_singleton()->_get_drag_data, &p, 1, ce);
- if (ce.error == Callable::CallError::CALL_OK) {
- return ret;
- }
+ Variant dd;
+ if (GDVIRTUAL_CALL(_get_drag_data, p_point, dd)) {
+ return dd;
}
return Variant();
@@ -752,16 +747,10 @@ bool Control::can_drop_data(const Point2 &p_point, const Variant &p_data) const
}
}
- if (get_script_instance()) {
- Variant v = p_point;
- const Variant *p[2] = { &v, &p_data };
- Callable::CallError ce;
- Variant ret = get_script_instance()->call(SceneStringNames::get_singleton()->_can_drop_data, p, 2, ce);
- if (ce.error == Callable::CallError::CALL_OK) {
- return ret;
- }
+ bool ret;
+ if (GDVIRTUAL_CALL(_can_drop_data, p_point, p_data, ret)) {
+ return ret;
}
-
return false;
}
@@ -775,15 +764,7 @@ void Control::drop_data(const Point2 &p_point, const Variant &p_data) {
}
}
- if (get_script_instance()) {
- Variant v = p_point;
- const Variant *p[2] = { &v, &p_data };
- Callable::CallError ce;
- Variant ret = get_script_instance()->call(SceneStringNames::get_singleton()->_drop_data, p, 2, ce);
- if (ce.error == Callable::CallError::CALL_OK) {
- return;
- }
- }
+ GDVIRTUAL_CALL(_drop_data, p_point, p_data);
}
void Control::force_drag(const Variant &p_data, Control *p_control) {
@@ -800,15 +781,11 @@ void Control::set_drag_preview(Control *p_control) {
}
Size2 Control::get_minimum_size() const {
- ScriptInstance *si = const_cast<Control *>(this)->get_script_instance();
- if (si) {
- Callable::CallError ce;
- Variant s = si->call(SceneStringNames::get_singleton()->_get_minimum_size, nullptr, 0, ce);
- if (ce.error == Callable::CallError::CALL_OK) {
- return s;
- }
+ Vector2 ms;
+ if (GDVIRTUAL_CALL(_get_minimum_size, ms)) {
+ return ms;
}
- return Size2();
+ return Vector2();
}
template <class T>
@@ -2123,8 +2100,9 @@ String Control::get_tooltip(const Point2 &p_pos) const {
}
Control *Control::make_custom_tooltip(const String &p_text) const {
- if (get_script_instance()) {
- return const_cast<Control *>(this)->call("_make_custom_tooltip", p_text);
+ Object *ret = nullptr;
+ if (GDVIRTUAL_CALL(_make_custom_tooltip, p_text, ret)) {
+ return Object::cast_to<Control>(ret);
}
return nullptr;
}
@@ -2499,14 +2477,11 @@ Vector<Vector2i> Control::structured_text_parser(StructuredTextParser p_theme_ty
}
} break;
case STRUCTURED_TEXT_CUSTOM: {
- if (get_script_instance()) {
- Variant data = get_script_instance()->call(SceneStringNames::get_singleton()->_structured_text_parser, p_args, p_text);
- if (data.get_type() == Variant::ARRAY) {
- Array _data = data;
- for (int i = 0; i < _data.size(); i++) {
- if (_data[i].get_type() == Variant::VECTOR2I) {
- ret.push_back(Vector2i(_data[i]));
- }
+ Array r;
+ if (GDVIRTUAL_CALL(_structured_text_parser, p_args, p_text, r)) {
+ for (int i = 0; i < r.size(); i++) {
+ if (r[i].get_type() == Variant::VECTOR2I) {
+ ret.push_back(Vector2i(r[i]));
}
}
}
@@ -2823,20 +2798,7 @@ void Control::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_auto_translate", "enable"), &Control::set_auto_translate);
ClassDB::bind_method(D_METHOD("is_auto_translating"), &Control::is_auto_translating);
- BIND_VMETHOD(MethodInfo("_structured_text_parser", PropertyInfo(Variant::ARRAY, "args"), PropertyInfo(Variant::STRING, "text")));
-
BIND_VMETHOD(MethodInfo("_gui_input", PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent")));
- BIND_VMETHOD(MethodInfo(Variant::VECTOR2, "_get_minimum_size"));
-
- MethodInfo get_drag_data = MethodInfo("_get_drag_data", PropertyInfo(Variant::VECTOR2, "position"));
- get_drag_data.return_val.usage |= PROPERTY_USAGE_NIL_IS_VARIANT;
- BIND_VMETHOD(get_drag_data);
-
- 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")));
- BIND_VMETHOD(MethodInfo(
- PropertyInfo(Variant::OBJECT, "control", PROPERTY_HINT_RESOURCE_TYPE, "Control"),
- "_make_custom_tooltip", PropertyInfo(Variant::STRING, "for_text")));
ADD_GROUP("Anchor", "anchor_");
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "anchor_left", PROPERTY_HINT_RANGE, "0,1,0.001,or_lesser,or_greater"), "_set_anchor", "get_anchor", SIDE_LEFT);
@@ -2994,5 +2956,12 @@ void Control::_bind_methods() {
ADD_SIGNAL(MethodInfo("minimum_size_changed"));
ADD_SIGNAL(MethodInfo("theme_changed"));
- GDVIRTUAL_BIND(_has_point);
+ GDVIRTUAL_BIND(_has_point, "position");
+ GDVIRTUAL_BIND(_structured_text_parser, "args", "text");
+ GDVIRTUAL_BIND(_get_minimum_size);
+
+ GDVIRTUAL_BIND(_get_drag_data, "at_position")
+ GDVIRTUAL_BIND(_can_drop_data, "at_position", "data")
+ GDVIRTUAL_BIND(_drop_data, "at_position", "data")
+ GDVIRTUAL_BIND(_make_custom_tooltip, "for_text")
}
diff --git a/scene/gui/control.h b/scene/gui/control.h
index a871a8e9fb..0d7a3b8de0 100644
--- a/scene/gui/control.h
+++ b/scene/gui/control.h
@@ -273,6 +273,16 @@ private:
_FORCE_INLINE_ void _get_theme_type_dependencies(const StringName &p_theme_type, List<StringName> *p_list) const;
GDVIRTUAL1RC(bool, _has_point, Vector2)
+ GDVIRTUAL2RC(Array, _structured_text_parser, Array, String)
+ GDVIRTUAL0RC(Vector2, _get_minimum_size)
+
+ GDVIRTUAL1RC(Variant, _get_drag_data, Vector2)
+ GDVIRTUAL2RC(bool, _can_drop_data, Vector2, Variant)
+ GDVIRTUAL2(_drop_data, Vector2, Variant)
+ GDVIRTUAL1RC(Object *, _make_custom_tooltip, String)
+
+ //GDVIRTUAL1(_gui_input, Ref<InputEvent>)
+
protected:
virtual void add_child_notify(Node *p_child) override;
virtual void remove_child_notify(Node *p_child) override;
diff --git a/scene/gui/graph_edit.cpp b/scene/gui/graph_edit.cpp
index fcecbb5fca..ac1dea5e94 100644
--- a/scene/gui/graph_edit.cpp
+++ b/scene/gui/graph_edit.cpp
@@ -805,68 +805,35 @@ bool GraphEdit::is_in_hot_zone(const Vector2 &pos, const Vector2 &p_mouse_pos, c
return true;
}
-template <class Vector2>
-static _FORCE_INLINE_ Vector2 _bezier_interp(real_t t, Vector2 start, Vector2 control_1, Vector2 control_2, Vector2 end) {
- /* Formula from Wikipedia article on Bezier curves. */
- real_t omt = (1.0 - t);
- real_t omt2 = omt * omt;
- real_t omt3 = omt2 * omt;
- real_t t2 = t * t;
- real_t t3 = t2 * t;
-
- return start * omt3 + control_1 * omt2 * t * 3.0 + control_2 * omt * t2 * 3.0 + end * t3;
-}
-
-void GraphEdit::_bake_segment2d(Vector<Vector2> &points, Vector<Color> &colors, float p_begin, float p_end, const Vector2 &p_a, const Vector2 &p_out, const Vector2 &p_b, const Vector2 &p_in, int p_depth, int p_min_depth, int p_max_depth, float p_tol, const Color &p_color, const Color &p_to_color, int &lines) const {
- float mp = p_begin + (p_end - p_begin) * 0.5;
- Vector2 beg = _bezier_interp(p_begin, p_a, p_a + p_out, p_b + p_in, p_b);
- Vector2 mid = _bezier_interp(mp, p_a, p_a + p_out, p_b + p_in, p_b);
- Vector2 end = _bezier_interp(p_end, p_a, p_a + p_out, p_b + p_in, p_b);
-
- Vector2 na = (mid - beg).normalized();
- Vector2 nb = (end - mid).normalized();
- float dp = Math::rad2deg(Math::acos(na.dot(nb)));
-
- if (p_depth >= p_min_depth && (dp < p_tol || p_depth >= p_max_depth)) {
- points.push_back((beg + end) * 0.5);
- colors.push_back(p_color.lerp(p_to_color, mp));
- lines++;
- } else {
- _bake_segment2d(points, colors, p_begin, mp, p_a, p_out, p_b, p_in, p_depth + 1, p_min_depth, p_max_depth, p_tol, p_color, p_to_color, lines);
- _bake_segment2d(points, colors, mp, p_end, p_a, p_out, p_b, p_in, p_depth + 1, p_min_depth, p_max_depth, p_tol, p_color, p_to_color, lines);
- }
-}
-
-void GraphEdit::_draw_cos_line(CanvasItem *p_where, const Vector2 &p_from, const Vector2 &p_to, const Color &p_color, const Color &p_to_color, float p_width, float p_bezier_ratio) {
- //cubic bezier code
- float diff = p_to.x - p_from.x;
- float cp_offset;
- int cp_len = get_theme_constant(SNAME("bezier_len_pos")) * p_bezier_ratio;
- int cp_neg_len = get_theme_constant(SNAME("bezier_len_neg")) * p_bezier_ratio;
-
- if (diff > 0) {
- cp_offset = MIN(cp_len, diff * 0.5);
- } else {
- cp_offset = MAX(MIN(cp_len - diff, cp_neg_len), -diff * 0.5);
+PackedVector2Array GraphEdit::get_connection_line(const Vector2 &p_from, const Vector2 &p_to) {
+ if (get_script_instance() && get_script_instance()->get_script().is_valid() && get_script_instance()->has_method("_get_connection_line")) {
+ return get_script_instance()->call("_get_connection_line", p_from, p_to);
}
- Vector2 c1 = Vector2(cp_offset * zoom, 0);
- Vector2 c2 = Vector2(-cp_offset * zoom, 0);
-
- int lines = 0;
+ Curve2D curve;
+ Vector<Color> colors;
+ curve.add_point(p_from);
+ curve.set_point_out(0, Vector2(60, 0));
+ curve.add_point(p_to);
+ curve.set_point_in(1, Vector2(-60, 0));
+ return curve.tessellate();
+}
- Vector<Point2> points;
+void GraphEdit::_draw_connection_line(CanvasItem *p_where, const Vector2 &p_from, const Vector2 &p_to, const Color &p_color, const Color &p_to_color, float p_width, float p_zoom) {
+ Vector<Vector2> points = get_connection_line(p_from / p_zoom, p_to / p_zoom);
+ Vector<Vector2> scaled_points;
Vector<Color> colors;
- points.push_back(p_from);
- colors.push_back(p_color);
- _bake_segment2d(points, colors, 0, 1, p_from, c1, p_to, c2, 0, 3, 9, 3, p_color, p_to_color, lines);
- points.push_back(p_to);
- colors.push_back(p_to_color);
+ float length = p_from.distance_to(p_to);
+ for (int i = 0; i < points.size(); i++) {
+ float d = p_from.distance_to(points[i]) / length;
+ colors.push_back(p_color.lerp(p_to_color, d));
+ scaled_points.push_back(points[i] * p_zoom);
+ }
#ifdef TOOLS_ENABLED
- p_where->draw_polyline_colors(points, colors, Math::floor(p_width * EDSCALE), lines_antialiased);
+ p_where->draw_polyline_colors(scaled_points, colors, Math::floor(p_width * EDSCALE), lines_antialiased);
#else
- p_where->draw_polyline_colors(points, colors, p_width, lines_antialiased);
+ p_where->draw_polyline_colors(scaled_points, colors, p_width, lines_antialiased);
#endif
}
@@ -913,7 +880,7 @@ void GraphEdit::_connections_layer_draw() {
color = color.lerp(activity_color, E->get().activity);
tocolor = tocolor.lerp(activity_color, E->get().activity);
}
- _draw_cos_line(connections_layer, frompos, topos, color, tocolor, lines_thickness);
+ _draw_connection_line(connections_layer, frompos, topos, color, tocolor, lines_thickness, zoom);
}
while (to_erase.size()) {
@@ -952,7 +919,7 @@ void GraphEdit::_top_layer_draw() {
if (!connecting_out) {
SWAP(pos, topos);
}
- _draw_cos_line(top_layer, pos, topos, col, col, lines_thickness);
+ _draw_connection_line(top_layer, pos, topos, col, col, lines_thickness, zoom);
}
if (box_selecting) {
@@ -1056,7 +1023,7 @@ void GraphEdit::_minimap_draw() {
from_color = from_color.lerp(activity_color, E.activity);
to_color = to_color.lerp(activity_color, E.activity);
}
- _draw_cos_line(minimap, from_position, to_position, from_color, to_color, 1.0, 0.5);
+ _draw_connection_line(minimap, from_position, to_position, from_color, to_color, 0.1, minimap->_convert_from_graph_position(Vector2(zoom, zoom)).length());
}
// Draw the "camera" viewport.
@@ -2048,7 +2015,6 @@ void GraphEdit::arrange_nodes() {
if (gn->is_selected()) {
selected_nodes.insert(gn->get_name());
- origin = origin < gn->get_position_offset() ? origin : gn->get_position_offset();
Set<StringName> s;
for (List<Connection>::Element *E = connections.front(); E; E = E->next()) {
GraphNode *p_from = Object::cast_to<GraphNode>(node_names[E->get().from]);
@@ -2072,6 +2038,11 @@ void GraphEdit::arrange_nodes() {
}
}
+ if (!selected_nodes.size()) {
+ arranging_graph = false;
+ return;
+ }
+
HashMap<int, Vector<StringName>> layers = _layering(selected_nodes, upper_neighbours);
_crossing_minimisation(layers, upper_neighbours);
@@ -2098,16 +2069,16 @@ void GraphEdit::arrange_nodes() {
for (const Set<StringName>::Element *E = block_heads.front(); E; E = E->next()) {
_place_block(E->get(), gap_v, layers, root, align, node_names, inner_shift, sink, shift, new_positions);
}
+ origin.y = Object::cast_to<GraphNode>(node_names[layers[0][0]])->get_position_offset().y - (new_positions[layers[0][0]].y + (float)inner_shift[layers[0][0]]);
+ origin.x = Object::cast_to<GraphNode>(node_names[layers[0][0]])->get_position_offset().x;
for (const Set<StringName>::Element *E = block_heads.front(); E; E = E->next()) {
StringName u = E->get();
- StringName prev = u;
float start_from = origin.y + new_positions[E->get()].y;
do {
Vector2 cal_pos;
cal_pos.y = start_from + (real_t)inner_shift[u];
new_positions.set(u, cal_pos);
- prev = u;
u = align[u];
} while (u != E->get());
}
@@ -2130,10 +2101,11 @@ void GraphEdit::arrange_nodes() {
if (current_node_size == largest_node_size) {
cal_pos.x = start_from;
} else {
- float current_node_start_pos;
- if (current_node_size >= largest_node_size / 2) {
- current_node_start_pos = start_from;
- } else {
+ float current_node_start_pos = start_from;
+ if (current_node_size < largest_node_size / 2) {
+ if (!(i || j)) {
+ start_from -= (largest_node_size - current_node_size);
+ }
current_node_start_pos = start_from + largest_node_size - current_node_size;
}
cal_pos.x = current_node_start_pos;
@@ -2179,6 +2151,7 @@ void GraphEdit::_bind_methods() {
ClassDB::bind_method(D_METHOD("add_valid_connection_type", "from_type", "to_type"), &GraphEdit::add_valid_connection_type);
ClassDB::bind_method(D_METHOD("remove_valid_connection_type", "from_type", "to_type"), &GraphEdit::remove_valid_connection_type);
ClassDB::bind_method(D_METHOD("is_valid_connection_type", "from_type", "to_type"), &GraphEdit::is_valid_connection_type);
+ ClassDB::bind_method(D_METHOD("get_connection_line", "from", "to"), &GraphEdit::get_connection_line);
ClassDB::bind_method(D_METHOD("set_zoom", "zoom"), &GraphEdit::set_zoom);
ClassDB::bind_method(D_METHOD("get_zoom"), &GraphEdit::get_zoom);
@@ -2227,6 +2200,8 @@ void GraphEdit::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_selected", "node"), &GraphEdit::set_selected);
+ BIND_VMETHOD(MethodInfo(Variant::PACKED_VECTOR2_ARRAY, "_get_connection_line", PropertyInfo(Variant::VECTOR2, "from"), PropertyInfo(Variant::VECTOR2, "to")));
+
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "right_disconnects"), "set_right_disconnects", "is_right_disconnects_enabled");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "scroll_offset"), "set_scroll_ofs", "get_scroll_ofs");
ADD_PROPERTY(PropertyInfo(Variant::INT, "snap_distance"), "set_snap", "get_snap");
diff --git a/scene/gui/graph_edit.h b/scene/gui/graph_edit.h
index 9fd7cbef22..7a9286be0f 100644
--- a/scene/gui/graph_edit.h
+++ b/scene/gui/graph_edit.h
@@ -169,9 +169,8 @@ private:
float lines_thickness = 2.0f;
bool lines_antialiased = true;
- void _bake_segment2d(Vector<Vector2> &points, Vector<Color> &colors, float p_begin, float p_end, const Vector2 &p_a, const Vector2 &p_out, const Vector2 &p_b, const Vector2 &p_in, int p_depth, int p_min_depth, int p_max_depth, float p_tol, const Color &p_color, const Color &p_to_color, int &lines) const;
-
- void _draw_cos_line(CanvasItem *p_where, const Vector2 &p_from, const Vector2 &p_to, const Color &p_color, const Color &p_to_color, float p_width, float p_bezier_ratio = 1.0);
+ PackedVector2Array get_connection_line(const Vector2 &p_from, const Vector2 &p_to);
+ void _draw_connection_line(CanvasItem *p_where, const Vector2 &p_from, const Vector2 &p_to, const Color &p_color, const Color &p_to_color, float p_width, float p_zoom);
void _graph_node_raised(Node *p_gn);
void _graph_node_moved(Node *p_gn);
diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp
index 4bd88fde5f..aff367e398 100644
--- a/scene/gui/popup_menu.cpp
+++ b/scene/gui/popup_menu.cpp
@@ -358,9 +358,10 @@ void PopupMenu::_gui_input(const Ref<InputEvent> &p_event) {
}
int button_idx = b->get_button_index();
- if (b->is_pressed() || (!b->is_pressed() && during_grabbed_click)) {
- // Allow activating item by releasing the LMB or any that was down when the popup appeared.
- // However, if button was not held when opening menu, do not allow release to activate item.
+ if (!b->is_pressed()) {
+ // Activate the item on release of either the left mouse button or
+ // any mouse button held down when the popup was opened.
+ // This allows for opening the popup and triggering an action in a single mouse click.
if (button_idx == MOUSE_BUTTON_LEFT || (initial_button_mask & (1 << (button_idx - 1)))) {
bool was_during_grabbed_click = during_grabbed_click;
during_grabbed_click = false;
diff --git a/scene/gui/rich_text_effect.cpp b/scene/gui/rich_text_effect.cpp
index 39718a269a..236d106af8 100644
--- a/scene/gui/rich_text_effect.cpp
+++ b/scene/gui/rich_text_effect.cpp
@@ -32,8 +32,15 @@
#include "core/object/script_language.h"
-void RichTextEffect::_bind_methods() {
- BIND_VMETHOD(MethodInfo(Variant::BOOL, "_process_custom_fx", PropertyInfo(Variant::OBJECT, "char_fx", PROPERTY_HINT_RESOURCE_TYPE, "CharFXTransform")));
+CharFXTransform::CharFXTransform() {
+}
+
+CharFXTransform::~CharFXTransform() {
+ environment.clear();
+}
+
+void RichTextEffect::_bind_methods(){
+ GDVIRTUAL_BIND(_process_custom_fx, "char_fx")
}
Variant RichTextEffect::get_bbcode() const {
@@ -49,15 +56,10 @@ Variant RichTextEffect::get_bbcode() const {
bool RichTextEffect::_process_effect_impl(Ref<CharFXTransform> p_cfx) {
bool return_value = false;
- if (get_script_instance()) {
- Variant v = get_script_instance()->call("_process_custom_fx", p_cfx);
- if (v.get_type() != Variant::BOOL) {
- return_value = false;
- } else {
- return_value = (bool)v;
- }
+ if (GDVIRTUAL_CALL(_process_custom_fx, p_cfx, return_value)) {
+ return return_value;
}
- return return_value;
+ return false;
}
RichTextEffect::RichTextEffect() {
@@ -101,10 +103,3 @@ void CharFXTransform::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "glyph_index"), "set_glyph_index", "get_glyph_index");
ADD_PROPERTY(PropertyInfo(Variant::RID, "font"), "set_font", "get_font");
}
-
-CharFXTransform::CharFXTransform() {
-}
-
-CharFXTransform::~CharFXTransform() {
- environment.clear();
-}
diff --git a/scene/gui/rich_text_effect.h b/scene/gui/rich_text_effect.h
index 67323e7f93..e674b2f62f 100644
--- a/scene/gui/rich_text_effect.h
+++ b/scene/gui/rich_text_effect.h
@@ -32,20 +32,8 @@
#define RICH_TEXT_EFFECT_H
#include "core/io/resource.h"
-
-class RichTextEffect : public Resource {
- GDCLASS(RichTextEffect, Resource);
- OBJ_SAVE_TYPE(RichTextEffect);
-
-protected:
- static void _bind_methods();
-
-public:
- Variant get_bbcode() const;
- bool _process_effect_impl(Ref<class CharFXTransform> p_cfx);
-
- RichTextEffect();
-};
+#include "core/object/gdvirtual.gen.inc"
+#include "core/object/script_language.h"
class CharFXTransform : public RefCounted {
GDCLASS(CharFXTransform, RefCounted);
@@ -89,4 +77,20 @@ public:
void set_environment(Dictionary p_environment) { environment = p_environment; }
};
+class RichTextEffect : public Resource {
+ GDCLASS(RichTextEffect, Resource);
+ OBJ_SAVE_TYPE(RichTextEffect);
+
+protected:
+ static void _bind_methods();
+
+ GDVIRTUAL1RC(bool, _process_custom_fx, Ref<CharFXTransform>)
+
+public:
+ Variant get_bbcode() const;
+ bool _process_effect_impl(Ref<class CharFXTransform> p_cfx);
+
+ RichTextEffect();
+};
+
#endif // RICH_TEXT_EFFECT_H
diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp
index cf2a1481a1..75c2da7ef9 100644
--- a/scene/gui/rich_text_label.cpp
+++ b/scene/gui/rich_text_label.cpp
@@ -1127,7 +1127,7 @@ void RichTextLabel::_find_click(ItemFrame *p_frame, const Point2i &p_click, Item
Point2 ofs = text_rect.get_position() + Vector2(0, main->lines[from_line].offset.y - vofs);
while (ofs.y < size.height && from_line < main->lines.size()) {
_find_click_in_line(p_frame, from_line, ofs, text_rect.size.x, p_click, r_click_frame, r_click_line, r_click_item, r_click_char);
- ofs.y += main->lines[from_line].text_buf->get_size().y;
+ ofs.y += main->lines[from_line].text_buf->get_size().y + get_theme_constant(SNAME("line_separation"));
if (((r_click_item != nullptr) && ((*r_click_item) != nullptr)) || ((r_click_frame != nullptr) && ((*r_click_frame) != nullptr))) {
if (r_outside != nullptr) {
*r_outside = false;
@@ -1435,7 +1435,7 @@ void RichTextLabel::_notification(int p_what) {
while (ofs.y < size.height && from_line < main->lines.size()) {
visible_paragraph_count++;
visible_line_count += _draw_line(main, from_line, ofs, text_rect.size.x, base_color, outline_size, outline_color, font_shadow_color, use_outline, shadow_ofs);
- ofs.y += main->lines[from_line].text_buf->get_size().y;
+ ofs.y += main->lines[from_line].text_buf->get_size().y + get_theme_constant(SNAME("line_separation"));
from_line++;
}
} break;
diff --git a/scene/gui/shortcut.cpp b/scene/gui/shortcut.cpp
index c0aac6d91a..d0cb08724e 100644
--- a/scene/gui/shortcut.cpp
+++ b/scene/gui/shortcut.cpp
@@ -32,7 +32,7 @@
#include "core/os/keyboard.h"
void Shortcut::set_event(const Ref<InputEvent> &p_event) {
- ERR_FAIL_COND(Object::cast_to<InputEventShortcut>(*p_event));
+ ERR_FAIL_COND_MSG(Object::cast_to<InputEventShortcut>(*p_event), "Cannot set a shortcut event to an instance of InputEventShortcut.");
event = p_event;
emit_changed();
}
diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp
index 87f06445ac..a65abd5f49 100644
--- a/scene/gui/text_edit.cpp
+++ b/scene/gui/text_edit.cpp
@@ -2768,48 +2768,38 @@ Point2i TextEdit::get_next_visible_line_index_offset_from(int p_line_from, int p
// Overridable actions
void TextEdit::handle_unicode_input(const uint32_t p_unicode) {
- ScriptInstance *si = get_script_instance();
- if (si && si->has_method("_handle_unicode_input")) {
- si->call("_handle_unicode_input", p_unicode);
+ if (GDVIRTUAL_CALL(_handle_unicode_input, p_unicode)) {
return;
}
- _handle_unicode_input(p_unicode);
+ _handle_unicode_input_internal(p_unicode);
}
void TextEdit::backspace() {
- ScriptInstance *si = get_script_instance();
- if (si && si->has_method("_backspace")) {
- si->call("_backspace");
+ if (GDVIRTUAL_CALL(_backspace)) {
return;
}
- _backspace();
+ _backspace_internal();
}
void TextEdit::cut() {
- ScriptInstance *si = get_script_instance();
- if (si && si->has_method("_cut")) {
- si->call("_cut");
+ if (GDVIRTUAL_CALL(_cut)) {
return;
}
- _cut();
+ _cut_internal();
}
void TextEdit::copy() {
- ScriptInstance *si = get_script_instance();
- if (si && si->has_method("_copy")) {
- si->call("_copy");
+ if (GDVIRTUAL_CALL(_copy)) {
return;
}
- _copy();
+ _copy_internal();
}
void TextEdit::paste() {
- ScriptInstance *si = get_script_instance();
- if (si && si->has_method("_paste")) {
- si->call("_paste");
+ if (GDVIRTUAL_CALL(_paste)) {
return;
}
- _paste();
+ _paste_internal();
}
// Context menu.
@@ -4452,12 +4442,11 @@ void TextEdit::_bind_methods() {
ClassDB::bind_method(D_METHOD("copy"), &TextEdit::copy);
ClassDB::bind_method(D_METHOD("paste"), &TextEdit::paste);
- BIND_VMETHOD(MethodInfo("_handle_unicode_input", PropertyInfo(Variant::INT, "unicode")))
- BIND_VMETHOD(MethodInfo("_backspace"));
-
- BIND_VMETHOD(MethodInfo("_cut"));
- BIND_VMETHOD(MethodInfo("_copy"));
- BIND_VMETHOD(MethodInfo("_paste"));
+ GDVIRTUAL_BIND(_handle_unicode_input, "unicode_char")
+ GDVIRTUAL_BIND(_backspace)
+ GDVIRTUAL_BIND(_cut)
+ GDVIRTUAL_BIND(_copy)
+ GDVIRTUAL_BIND(_paste)
// Context Menu
BIND_ENUM_CONSTANT(MENU_CUT);
@@ -4884,7 +4873,7 @@ void TextEdit::_set_symbol_lookup_word(const String &p_symbol) {
/* Text manipulation */
// Overridable actions
-void TextEdit::_handle_unicode_input(const uint32_t p_unicode) {
+void TextEdit::_handle_unicode_input_internal(const uint32_t p_unicode) {
if (!editable) {
return;
}
@@ -4915,7 +4904,7 @@ void TextEdit::_handle_unicode_input(const uint32_t p_unicode) {
}
}
-void TextEdit::_backspace() {
+void TextEdit::_backspace_internal() {
if (!editable) {
return;
}
@@ -4946,7 +4935,7 @@ void TextEdit::_backspace() {
set_caret_column(prev_column);
}
-void TextEdit::_cut() {
+void TextEdit::_cut_internal() {
if (!editable) {
return;
}
@@ -4976,7 +4965,7 @@ void TextEdit::_cut() {
cut_copy_line = clipboard;
}
-void TextEdit::_copy() {
+void TextEdit::_copy_internal() {
if (has_selection()) {
DisplayServer::get_singleton()->clipboard_set(get_selected_text());
cut_copy_line = "";
@@ -4991,7 +4980,7 @@ void TextEdit::_copy() {
}
}
-void TextEdit::_paste() {
+void TextEdit::_paste_internal() {
if (!editable) {
return;
}
diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h
index 69468978ab..7d00ce14af 100644
--- a/scene/gui/text_edit.h
+++ b/scene/gui/text_edit.h
@@ -562,12 +562,18 @@ protected:
/* Text manipulation */
// Overridable actions
- virtual void _handle_unicode_input(const uint32_t p_unicode);
- virtual void _backspace();
-
- virtual void _cut();
- virtual void _copy();
- virtual void _paste();
+ virtual void _handle_unicode_input_internal(const uint32_t p_unicode);
+ virtual void _backspace_internal();
+
+ virtual void _cut_internal();
+ virtual void _copy_internal();
+ virtual void _paste_internal();
+
+ GDVIRTUAL1(_handle_unicode_input, int)
+ GDVIRTUAL0(_backspace)
+ GDVIRTUAL0(_cut)
+ GDVIRTUAL0(_copy)
+ GDVIRTUAL0(_paste)
public:
/* General overrides. */