summaryrefslogtreecommitdiff
path: root/editor
diff options
context:
space:
mode:
Diffstat (limited to 'editor')
-rw-r--r--editor/animation_bezier_editor.cpp25
-rw-r--r--editor/animation_bezier_editor.h5
-rw-r--r--editor/animation_track_editor.cpp46
-rw-r--r--editor/animation_track_editor.h10
-rw-r--r--editor/connections_dialog.cpp207
-rw-r--r--editor/connections_dialog.h16
-rw-r--r--editor/dependency_editor.cpp12
-rw-r--r--editor/editor_help.cpp2
-rw-r--r--editor/editor_inspector.cpp2
-rw-r--r--editor/editor_node.cpp3
-rw-r--r--editor/filesystem_dock.cpp6
-rw-r--r--editor/filesystem_dock.h1
-rw-r--r--editor/plugins/canvas_item_editor_plugin.cpp56
-rw-r--r--editor/plugins/canvas_item_editor_plugin.h6
-rw-r--r--editor/plugins/polygon_2d_editor_plugin.cpp16
-rw-r--r--editor/plugins/polygon_2d_editor_plugin.h5
-rw-r--r--editor/plugins/texture_region_editor_plugin.cpp16
-rw-r--r--editor/plugins/texture_region_editor_plugin.h5
-rw-r--r--editor/plugins/tiles/tile_atlas_view.cpp12
-rw-r--r--editor/plugins/tiles/tile_atlas_view.h5
-rw-r--r--editor/plugins/tiles/tiles_editor_plugin.cpp2
-rw-r--r--editor/plugins/visual_shader_editor_plugin.cpp187
-rw-r--r--editor/plugins/visual_shader_editor_plugin.h11
23 files changed, 448 insertions, 208 deletions
diff --git a/editor/animation_bezier_editor.cpp b/editor/animation_bezier_editor.cpp
index 639f5e6de5..8defa04ada 100644
--- a/editor/animation_bezier_editor.cpp
+++ b/editor/animation_bezier_editor.cpp
@@ -1489,32 +1489,21 @@ void AnimationBezierTrackEdit::gui_input(const Ref<InputEvent> &p_event) {
}
}
-void AnimationBezierTrackEdit::_scroll_callback(Vector2 p_scroll_vec, bool p_alt) {
- _pan_callback(-p_scroll_vec * 32);
-}
-
-void AnimationBezierTrackEdit::_pan_callback(Vector2 p_scroll_vec) {
+void AnimationBezierTrackEdit::_pan_callback(Vector2 p_scroll_vec, Ref<InputEvent> p_event) {
v_scroll += p_scroll_vec.y * v_zoom;
v_scroll = CLAMP(v_scroll, -100000, 100000);
timeline->set_value(timeline->get_value() - p_scroll_vec.x / timeline->get_zoom_scale());
queue_redraw();
}
-void AnimationBezierTrackEdit::_zoom_callback(Vector2 p_scroll_vec, Vector2 p_origin, bool p_alt) {
+void AnimationBezierTrackEdit::_zoom_callback(float p_zoom_factor, Vector2 p_origin, Ref<InputEvent> p_event) {
const float v_zoom_orig = v_zoom;
- if (p_alt) {
+ Ref<InputEventWithModifiers> iewm = p_event;
+ if (iewm.is_valid() && iewm->is_alt_pressed()) {
// Alternate zoom (doesn't affect timeline).
- if (p_scroll_vec.y > 0) {
- v_zoom = MIN(v_zoom * 1.2, 100000);
- } else {
- v_zoom = MAX(v_zoom / 1.2, 0.000001);
- }
+ v_zoom = CLAMP(v_zoom * p_zoom_factor, 0.000001, 100000);
} else {
- if (p_scroll_vec.y > 0) {
- timeline->get_zoom()->set_value(timeline->get_zoom()->get_value() / 1.05);
- } else {
- timeline->get_zoom()->set_value(timeline->get_zoom()->get_value() * 1.05);
- }
+ timeline->get_zoom()->set_value(timeline->get_zoom()->get_value() / p_zoom_factor);
}
v_scroll = v_scroll + (p_origin.y - get_size().y / 2.0) * (v_zoom - v_zoom_orig);
queue_redraw();
@@ -1681,7 +1670,7 @@ void AnimationBezierTrackEdit::_bind_methods() {
AnimationBezierTrackEdit::AnimationBezierTrackEdit() {
panner.instantiate();
- panner->set_callbacks(callable_mp(this, &AnimationBezierTrackEdit::_scroll_callback), callable_mp(this, &AnimationBezierTrackEdit::_pan_callback), callable_mp(this, &AnimationBezierTrackEdit::_zoom_callback));
+ panner->set_callbacks(callable_mp(this, &AnimationBezierTrackEdit::_pan_callback), callable_mp(this, &AnimationBezierTrackEdit::_zoom_callback));
play_position = memnew(Control);
play_position->set_mouse_filter(MOUSE_FILTER_PASS);
diff --git a/editor/animation_bezier_editor.h b/editor/animation_bezier_editor.h
index e6d6424ef2..dbc231ccac 100644
--- a/editor/animation_bezier_editor.h
+++ b/editor/animation_bezier_editor.h
@@ -174,9 +174,8 @@ class AnimationBezierTrackEdit : public Control {
SelectionSet selection;
Ref<ViewPanner> panner;
- void _scroll_callback(Vector2 p_scroll_vec, bool p_alt);
- void _pan_callback(Vector2 p_scroll_vec);
- void _zoom_callback(Vector2 p_scroll_vec, Vector2 p_origin, bool p_alt);
+ void _pan_callback(Vector2 p_scroll_vec, Ref<InputEvent> p_event);
+ void _zoom_callback(float p_zoom_factor, Vector2 p_origin, Ref<InputEvent> p_event);
void _draw_line_clipped(const Vector2 &p_from, const Vector2 &p_to, const Color &p_color, int p_clip_left, int p_clip_right);
void _draw_track(int p_track, const Color &p_color);
diff --git a/editor/animation_track_editor.cpp b/editor/animation_track_editor.cpp
index 857a9a664a..338a22c070 100644
--- a/editor/animation_track_editor.cpp
+++ b/editor/animation_track_editor.cpp
@@ -1704,25 +1704,13 @@ Control::CursorShape AnimationTimelineEdit::get_cursor_shape(const Point2 &p_pos
}
}
-void AnimationTimelineEdit::_scroll_callback(Vector2 p_scroll_vec, bool p_alt) {
- // Timeline has no vertical scroll, so we change it to horizontal.
- p_scroll_vec.x += p_scroll_vec.y;
- _pan_callback(-p_scroll_vec * 32);
-}
-
-void AnimationTimelineEdit::_pan_callback(Vector2 p_scroll_vec) {
+void AnimationTimelineEdit::_pan_callback(Vector2 p_scroll_vec, Ref<InputEvent> p_event) {
set_value(get_value() - p_scroll_vec.x / get_zoom_scale());
}
-void AnimationTimelineEdit::_zoom_callback(Vector2 p_scroll_vec, Vector2 p_origin, bool p_alt) {
- double new_zoom_value;
+void AnimationTimelineEdit::_zoom_callback(float p_zoom_factor, Vector2 p_origin, Ref<InputEvent> p_event) {
double current_zoom_value = get_zoom()->get_value();
- if (current_zoom_value <= 0.1) {
- new_zoom_value = MAX(0.01, current_zoom_value - 0.01 * SIGN(p_scroll_vec.y));
- } else {
- new_zoom_value = p_scroll_vec.y > 0 ? MAX(0.01, current_zoom_value / 1.05) : current_zoom_value * 1.05;
- }
- get_zoom()->set_value(new_zoom_value);
+ get_zoom()->set_value(MAX(0.01, current_zoom_value * p_zoom_factor));
}
void AnimationTimelineEdit::set_use_fps(bool p_use_fps) {
@@ -1798,7 +1786,8 @@ AnimationTimelineEdit::AnimationTimelineEdit() {
len_hb->hide();
panner.instantiate();
- panner->set_callbacks(callable_mp(this, &AnimationTimelineEdit::_scroll_callback), callable_mp(this, &AnimationTimelineEdit::_pan_callback), callable_mp(this, &AnimationTimelineEdit::_zoom_callback));
+ panner->set_callbacks(callable_mp(this, &AnimationTimelineEdit::_pan_callback), callable_mp(this, &AnimationTimelineEdit::_zoom_callback));
+ panner->set_pan_axis(ViewPanner::PAN_AXIS_HORIZONTAL);
set_layout_direction(Control::LAYOUT_DIRECTION_LTR);
}
@@ -5358,32 +5347,23 @@ void AnimationTrackEditor::_toggle_bezier_edit() {
}
}
-void AnimationTrackEditor::_scroll_callback(Vector2 p_scroll_vec, bool p_alt) {
- if (p_alt) {
+void AnimationTrackEditor::_pan_callback(Vector2 p_scroll_vec, Ref<InputEvent> p_event) {
+ Ref<InputEventWithModifiers> iewm = p_event;
+ if (iewm.is_valid() && iewm->is_alt_pressed()) {
if (p_scroll_vec.x < 0 || p_scroll_vec.y < 0) {
goto_prev_step(true);
} else {
goto_next_step(true);
}
} else {
- _pan_callback(-p_scroll_vec * 32);
+ timeline->set_value(timeline->get_value() - p_scroll_vec.x / timeline->get_zoom_scale());
+ scroll->set_v_scroll(scroll->get_v_scroll() - p_scroll_vec.y);
}
}
-void AnimationTrackEditor::_pan_callback(Vector2 p_scroll_vec) {
- timeline->set_value(timeline->get_value() - p_scroll_vec.x / timeline->get_zoom_scale());
- scroll->set_v_scroll(scroll->get_v_scroll() - p_scroll_vec.y);
-}
-
-void AnimationTrackEditor::_zoom_callback(Vector2 p_scroll_vec, Vector2 p_origin, bool p_alt) {
- double new_zoom_value;
+void AnimationTrackEditor::_zoom_callback(float p_zoom_factor, Vector2 p_origin, Ref<InputEvent> p_event) {
double current_zoom_value = timeline->get_zoom()->get_value();
- if (current_zoom_value <= 0.1) {
- new_zoom_value = MAX(0.01, current_zoom_value - 0.01 * SIGN(p_scroll_vec.y));
- } else {
- new_zoom_value = p_scroll_vec.y > 0 ? MAX(0.01, current_zoom_value / 1.05) : current_zoom_value * 1.05;
- }
- timeline->get_zoom()->set_value(new_zoom_value);
+ timeline->get_zoom()->set_value(MAX(0.01, current_zoom_value * p_zoom_factor));
}
void AnimationTrackEditor::_cancel_bezier_edit() {
@@ -6398,7 +6378,7 @@ AnimationTrackEditor::AnimationTrackEditor() {
timeline->connect("length_changed", callable_mp(this, &AnimationTrackEditor::_update_length));
panner.instantiate();
- panner->set_callbacks(callable_mp(this, &AnimationTrackEditor::_scroll_callback), callable_mp(this, &AnimationTrackEditor::_pan_callback), callable_mp(this, &AnimationTrackEditor::_zoom_callback));
+ panner->set_callbacks(callable_mp(this, &AnimationTrackEditor::_pan_callback), callable_mp(this, &AnimationTrackEditor::_zoom_callback));
scroll = memnew(ScrollContainer);
timeline_vbox->add_child(scroll);
diff --git a/editor/animation_track_editor.h b/editor/animation_track_editor.h
index ef06445011..8506d9b80d 100644
--- a/editor/animation_track_editor.h
+++ b/editor/animation_track_editor.h
@@ -159,9 +159,8 @@ class AnimationTimelineEdit : public Range {
bool use_fps = false;
Ref<ViewPanner> panner;
- void _scroll_callback(Vector2 p_scroll_vec, bool p_alt);
- void _pan_callback(Vector2 p_scroll_vec);
- void _zoom_callback(Vector2 p_scroll_vec, Vector2 p_origin, bool p_alt);
+ void _pan_callback(Vector2 p_scroll_vec, Ref<InputEvent> p_event);
+ void _zoom_callback(float p_zoom_factor, Vector2 p_origin, Ref<InputEvent> p_event);
bool dragging_timeline = false;
bool dragging_hsize = false;
@@ -460,9 +459,8 @@ class AnimationTrackEditor : public VBoxContainer {
PropertyInfo _find_hint_for_track(int p_idx, NodePath &r_base_path, Variant *r_current_val = nullptr);
Ref<ViewPanner> panner;
- void _scroll_callback(Vector2 p_scroll_vec, bool p_alt);
- void _pan_callback(Vector2 p_scroll_vec);
- void _zoom_callback(Vector2 p_scroll_vec, Vector2 p_origin, bool p_alt);
+ void _pan_callback(Vector2 p_scroll_vec, Ref<InputEvent> p_event);
+ void _zoom_callback(float p_zoom_factor, Vector2 p_origin, Ref<InputEvent> p_event);
void _timeline_value_changed(double);
diff --git a/editor/connections_dialog.cpp b/editor/connections_dialog.cpp
index b89fdbfa00..db12dbc72b 100644
--- a/editor/connections_dialog.cpp
+++ b/editor/connections_dialog.cpp
@@ -166,6 +166,7 @@ void ConnectDialog::_tree_node_selected() {
if (!edit_mode) {
set_dst_method(generate_method_callback_name(source, signal, current));
}
+ _update_method_tree();
_update_ok_enabled();
}
@@ -183,6 +184,11 @@ void ConnectDialog::_unbind_count_changed(double p_count) {
}
}
+void ConnectDialog::_method_selected() {
+ TreeItem *selected_item = method_tree->get_selected();
+ dst_method->set_text(selected_item->get_text(0));
+}
+
/*
* Adds a new parameter bind to connection.
*/
@@ -251,6 +257,142 @@ StringName ConnectDialog::generate_method_callback_name(Node *p_source, String p
return dst_method;
}
+void ConnectDialog::_create_method_tree_items(const List<MethodInfo> &p_methods, TreeItem *p_parent_item) {
+ for (const MethodInfo &mi : p_methods) {
+ TreeItem *method_item = method_tree->create_item(p_parent_item);
+ method_item->set_text(0, mi.name);
+ if (mi.return_val.type == Variant::NIL) {
+ method_item->set_icon(0, get_theme_icon(SNAME("Variant"), "EditorIcons"));
+ } else {
+ method_item->set_icon(0, get_theme_icon(Variant::get_type_name(mi.return_val.type), "EditorIcons"));
+ }
+ }
+}
+
+List<MethodInfo> ConnectDialog::_filter_method_list(const List<MethodInfo> &p_methods, const MethodInfo &p_signal, const String &p_search_string) const {
+ bool check_signal = compatible_methods_only->is_pressed();
+ List<MethodInfo> ret;
+
+ for (const MethodInfo &mi : p_methods) {
+ if (!p_search_string.is_empty() && !mi.name.contains(p_search_string)) {
+ continue;
+ }
+
+ if (check_signal) {
+ if (mi.arguments.size() != p_signal.arguments.size()) {
+ continue;
+ }
+
+ bool type_mismatch = false;
+ const List<PropertyInfo>::Element *E = p_signal.arguments.front();
+ for (const List<PropertyInfo>::Element *F = mi.arguments.front(); F; F = F->next(), E = E->next()) {
+ Variant::Type stype = E->get().type;
+ Variant::Type mtype = F->get().type;
+
+ if (stype != Variant::NIL && mtype != Variant::NIL && stype != mtype) {
+ type_mismatch = true;
+ break;
+ }
+ }
+
+ if (type_mismatch) {
+ continue;
+ }
+ }
+ ret.push_back(mi);
+ }
+ return ret;
+}
+
+void ConnectDialog::_update_method_tree() {
+ method_tree->clear();
+
+ Color disabled_color = get_theme_color(SNAME("accent_color"), SNAME("Editor")) * 0.7;
+ String search_string = method_search->get_text();
+ Node *target = tree->get_selected();
+ if (!target) {
+ return;
+ }
+
+ MethodInfo signal_info;
+ if (compatible_methods_only->is_pressed()) {
+ List<MethodInfo> signals;
+ source->get_signal_list(&signals);
+ for (const MethodInfo &mi : signals) {
+ if (mi.name == signal) {
+ signal_info = mi;
+ break;
+ }
+ }
+ }
+
+ TreeItem *root_item = method_tree->create_item();
+ root_item->set_text(0, TTR("Methods"));
+ root_item->set_selectable(0, false);
+
+ // If a script is attached, get methods from it.
+ ScriptInstance *si = target->get_script_instance();
+ if (si) {
+ TreeItem *si_item = method_tree->create_item(root_item);
+ si_item->set_text(0, TTR("Attached Script"));
+ si_item->set_icon(0, get_theme_icon(SNAME("Script"), SNAME("EditorIcons")));
+ si_item->set_selectable(0, false);
+
+ List<MethodInfo> methods;
+ si->get_method_list(&methods);
+ methods = _filter_method_list(methods, signal_info, search_string);
+
+ if (methods.is_empty()) {
+ si_item->set_custom_color(0, disabled_color);
+ } else {
+ _create_method_tree_items(methods, si_item);
+ }
+ }
+
+ if (script_methods_only->is_pressed()) {
+ return;
+ }
+
+ // Get methods from each class in the heirarchy.
+ StringName current_class = target->get_class_name();
+ do {
+ TreeItem *class_item = method_tree->create_item(root_item);
+ class_item->set_text(0, current_class);
+ Ref<Texture2D> icon = get_theme_icon(SNAME("Node"), SNAME("EditorIcons"));
+ if (has_theme_icon(current_class, SNAME("EditorIcons"))) {
+ icon = get_theme_icon(current_class, SNAME("EditorIcons"));
+ }
+ class_item->set_icon(0, icon);
+ class_item->set_selectable(0, false);
+
+ List<MethodInfo> methods;
+ ClassDB::get_method_list(current_class, &methods, true);
+ methods = _filter_method_list(methods, signal_info, search_string);
+
+ if (methods.is_empty()) {
+ class_item->set_custom_color(0, disabled_color);
+ } else {
+ _create_method_tree_items(methods, class_item);
+ }
+ current_class = ClassDB::get_parent_class_nocheck(current_class);
+ } while (current_class != StringName());
+}
+
+void ConnectDialog::_method_check_button_pressed(const CheckButton *p_button) {
+ if (p_button == script_methods_only) {
+ EditorSettings::get_singleton()->set_project_metadata("editor_metadata", "show_script_methods_only", p_button->is_pressed());
+ } else if (p_button == compatible_methods_only) {
+ EditorSettings::get_singleton()->set_project_metadata("editor_metadata", "show_compatible_methods_only", p_button->is_pressed());
+ }
+ _update_method_tree();
+}
+
+void ConnectDialog::_open_method_popup() {
+ method_popup->popup_centered();
+ method_search->clear();
+ method_search->grab_focus();
+}
+
/*
* Enables or disables the connect button. The connect button is enabled if a
* node is selected and valid in the selected mode.
@@ -263,7 +405,7 @@ void ConnectDialog::_update_ok_enabled() {
return;
}
- if (!advanced->is_pressed() && target->get_script().is_null()) {
+ if (dst_method->get_text().is_empty()) {
get_ok_button()->set_disabled(true);
return;
}
@@ -289,14 +431,12 @@ void ConnectDialog::_notification(int p_what) {
style->set_content_margin(SIDE_TOP, style->get_content_margin(SIDE_TOP) + 1.0);
from_signal->add_theme_style_override("normal", style);
}
+ method_search->set_right_icon(get_theme_icon("Search", "EditorIcons"));
} break;
}
}
void ConnectDialog::_bind_methods() {
- ClassDB::bind_method("_cancel", &ConnectDialog::_cancel_pressed);
- ClassDB::bind_method("_update_ok_enabled", &ConnectDialog::_update_ok_enabled);
-
ADD_SIGNAL(MethodInfo("connected"));
}
@@ -438,7 +578,6 @@ void ConnectDialog::_advanced_pressed() {
error_label->set_visible(!_find_first_script(get_tree()->get_edited_scene_root(), get_tree()->get_edited_scene_root()));
}
- _update_ok_enabled();
EditorSettings::get_singleton()->set_project_metadata("editor_metadata", "use_advanced_connections", advanced->is_pressed());
popup_centered();
@@ -458,9 +597,18 @@ ConnectDialog::ConnectDialog() {
main_hb->add_child(vbc_left);
vbc_left->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ HBoxContainer *from_signal_hb = memnew(HBoxContainer);
+
from_signal = memnew(LineEdit);
from_signal->set_editable(false);
- vbc_left->add_margin_child(TTR("From Signal:"), from_signal);
+ from_signal->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ from_signal_hb->add_child(from_signal);
+
+ advanced = memnew(CheckButton(TTR("Advanced")));
+ from_signal_hb->add_child(advanced);
+ advanced->connect("pressed", callable_mp(this, &ConnectDialog::_advanced_pressed));
+
+ vbc_left->add_margin_child(TTR("From Signal:"), from_signal_hb);
tree = memnew(SceneTreeEditor(false));
tree->set_connecting_signal(true);
@@ -477,6 +625,39 @@ ConnectDialog::ConnectDialog() {
vbc_left->add_child(error_label);
error_label->hide();
+ method_popup = memnew(AcceptDialog);
+ method_popup->set_title(TTR("Select Method"));
+ method_popup->set_min_size(Vector2(400, 600) * EDSCALE);
+ add_child(method_popup);
+
+ VBoxContainer *method_vbc = memnew(VBoxContainer);
+ method_popup->add_child(method_vbc);
+
+ method_search = memnew(LineEdit);
+ method_vbc->add_child(method_search);
+ method_search->set_placeholder(TTR("Filter Methods"));
+ method_search->set_clear_button_enabled(true);
+ method_search->connect("text_changed", callable_mp(this, &ConnectDialog::_update_method_tree).unbind(1));
+
+ method_tree = memnew(Tree);
+ method_vbc->add_child(method_tree);
+ method_tree->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+ method_tree->set_hide_root(true);
+ method_tree->connect("item_selected", callable_mp(this, &ConnectDialog::_method_selected));
+ method_tree->connect("item_activated", callable_mp((Window *)method_popup, &Window::hide));
+
+ script_methods_only = memnew(CheckButton(TTR("Script Methods Only")));
+ method_vbc->add_child(script_methods_only);
+ script_methods_only->set_h_size_flags(Control::SIZE_SHRINK_END);
+ script_methods_only->set_pressed(EditorSettings::get_singleton()->get_project_metadata("editor_metadata", "show_script_methods_only", true));
+ script_methods_only->connect("pressed", callable_mp(this, &ConnectDialog::_method_check_button_pressed).bind(script_methods_only));
+
+ compatible_methods_only = memnew(CheckButton(TTR("Compatible Methods Only")));
+ method_vbc->add_child(compatible_methods_only);
+ compatible_methods_only->set_h_size_flags(Control::SIZE_SHRINK_END);
+ compatible_methods_only->set_pressed(EditorSettings::get_singleton()->get_project_metadata("editor_metadata", "show_compatible_methods_only", true));
+ compatible_methods_only->connect("pressed", callable_mp(this, &ConnectDialog::_method_check_button_pressed).bind(compatible_methods_only));
+
vbc_right = memnew(VBoxContainer);
main_hb->add_child(vbc_right);
vbc_right->set_h_size_flags(Control::SIZE_EXPAND_FILL);
@@ -522,10 +703,20 @@ ConnectDialog::ConnectDialog() {
vbc_right->add_margin_child(TTR("Unbind Signal Arguments:"), unbind_count);
+ HBoxContainer *hbc_method = memnew(HBoxContainer);
+ vbc_left->add_margin_child(TTR("Receiver Method:"), hbc_method);
+
dst_method = memnew(LineEdit);
dst_method->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ dst_method->connect("text_changed", callable_mp(method_tree, &Tree::deselect_all).unbind(1));
dst_method->connect("text_submitted", callable_mp(this, &ConnectDialog::_text_submitted));
- vbc_left->add_margin_child(TTR("Receiver Method:"), dst_method);
+ hbc_method->add_child(dst_method);
+
+ Button *open_tree_button = memnew(Button);
+ open_tree_button->set_flat(false);
+ open_tree_button->set_text("...");
+ open_tree_button->connect("pressed", callable_mp(this, &ConnectDialog::_open_method_popup));
+ hbc_method->add_child(open_tree_button);
advanced = memnew(CheckButton);
vbc_left->add_child(advanced);
@@ -567,7 +758,7 @@ ConnectDialog::~ConnectDialog() {
// Originally copied and adapted from EditorProperty, try to keep style in sync.
Control *ConnectionsDockTree::make_custom_tooltip(const String &p_text) const {
EditorHelpBit *help_bit = memnew(EditorHelpBit);
- help_bit->get_rich_text()->set_fixed_size_to_width(360 * EDSCALE);
+ help_bit->get_rich_text()->set_custom_minimum_size(Size2(360 * EDSCALE, 1));
// p_text is expected to be something like this:
// "gui_input::(event: InputEvent)::<Signal description>"
diff --git a/editor/connections_dialog.h b/editor/connections_dialog.h
index 829a98caed..0bea897976 100644
--- a/editor/connections_dialog.h
+++ b/editor/connections_dialog.h
@@ -114,9 +114,15 @@ private:
bool first_popup = true;
NodePath dst_path;
VBoxContainer *vbc_right = nullptr;
-
SceneTreeEditor *tree = nullptr;
AcceptDialog *error = nullptr;
+
+ AcceptDialog *method_popup = nullptr;
+ Tree *method_tree = nullptr;
+ LineEdit *method_search = nullptr;
+ CheckButton *script_methods_only = nullptr;
+ CheckButton *compatible_methods_only = nullptr;
+
SpinBox *unbind_count = nullptr;
EditorInspector *bind_editor = nullptr;
OptionButton *type_list = nullptr;
@@ -132,6 +138,14 @@ private:
void _item_activated();
void _text_submitted(const String &p_text);
void _tree_node_selected();
+
+ void _method_selected();
+ void _create_method_tree_items(const List<MethodInfo> &p_methods, TreeItem *p_parent_item);
+ List<MethodInfo> _filter_method_list(const List<MethodInfo> &p_methods, const MethodInfo &p_signal, const String &p_search_string) const;
+ void _update_method_tree();
+ void _method_check_button_pressed(const CheckButton *p_button);
+ void _open_method_popup();
+
void _unbind_count_changed(double p_count);
void _add_bind();
void _remove_bind();
diff --git a/editor/dependency_editor.cpp b/editor/dependency_editor.cpp
index a925e2d1d3..c98ec7b2d5 100644
--- a/editor/dependency_editor.cpp
+++ b/editor/dependency_editor.cpp
@@ -536,12 +536,17 @@ void DependencyRemoveDialog::show(const Vector<String> &p_folders, const Vector<
}
void DependencyRemoveDialog::ok_pressed() {
- for (int i = 0; i < files_to_delete.size(); ++i) {
- if (ResourceCache::has(files_to_delete[i])) {
- Ref<Resource> res = ResourceCache::get_ref(files_to_delete[i]);
+ for (const KeyValue<String, String> &E : all_remove_files) {
+ String file = E.key;
+
+ if (ResourceCache::has(file)) {
+ Ref<Resource> res = ResourceCache::get_ref(file);
+ emit_signal(SNAME("resource_removed"), res);
res->set_path("");
}
+ }
+ for (int i = 0; i < files_to_delete.size(); ++i) {
// If the file we are deleting for e.g. the main scene, default environment,
// or audio bus layout, we must clear its definition in Project Settings.
if (files_to_delete[i] == String(GLOBAL_GET("application/config/icon"))) {
@@ -621,6 +626,7 @@ void DependencyRemoveDialog::ok_pressed() {
}
void DependencyRemoveDialog::_bind_methods() {
+ ADD_SIGNAL(MethodInfo("resource_removed", PropertyInfo(Variant::OBJECT, "obj")));
ADD_SIGNAL(MethodInfo("file_removed", PropertyInfo(Variant::STRING, "file")));
ADD_SIGNAL(MethodInfo("folder_removed", PropertyInfo(Variant::STRING, "folder")));
}
diff --git a/editor/editor_help.cpp b/editor/editor_help.cpp
index 4cf947b006..e11251596a 100644
--- a/editor/editor_help.cpp
+++ b/editor/editor_help.cpp
@@ -2370,7 +2370,7 @@ EditorHelpBit::EditorHelpBit() {
rich_text = memnew(RichTextLabel);
add_child(rich_text);
rich_text->connect("meta_clicked", callable_mp(this, &EditorHelpBit::_meta_clicked));
- rich_text->set_fit_content_height(true);
+ rich_text->set_fit_content(true);
set_custom_minimum_size(Size2(0, 50 * EDSCALE));
}
diff --git a/editor/editor_inspector.cpp b/editor/editor_inspector.cpp
index 4753761f05..0166d4c719 100644
--- a/editor/editor_inspector.cpp
+++ b/editor/editor_inspector.cpp
@@ -886,7 +886,7 @@ void EditorProperty::_update_pin_flags() {
static Control *make_help_bit(const String &p_text, bool p_property) {
EditorHelpBit *help_bit = memnew(EditorHelpBit);
- help_bit->get_rich_text()->set_fixed_size_to_width(360 * EDSCALE);
+ help_bit->get_rich_text()->set_custom_minimum_size(Size2(360 * EDSCALE, 1));
PackedStringArray slices = p_text.split("::", false);
if (slices.is_empty()) {
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp
index 58cd592404..173cbc6893 100644
--- a/editor/editor_node.cpp
+++ b/editor/editor_node.cpp
@@ -3902,7 +3902,7 @@ Error EditorNode::load_scene(const String &p_scene, bool p_ignore_broken_deps, b
Ref<SceneState> state = sdata->get_state();
state->set_path(lpath);
new_scene->set_scene_inherited_state(state);
- new_scene->set_scene_file_path(lpath);
+ new_scene->set_scene_file_path(String());
}
new_scene->set_scene_instance_state(Ref<SceneState>());
@@ -6113,6 +6113,7 @@ void EditorNode::reload_instances_with_path_in_edited_scenes(const String &p_ins
Ref<SceneState> state = current_packed_scene->get_state();
state->set_path(current_packed_scene->get_path());
instantiated_node->set_scene_inherited_state(state);
+ instantiated_node->set_scene_file_path(String());
}
editor_data.set_edited_scene_root(instantiated_node);
current_edited_scene = instantiated_node;
diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp
index a078c58e72..378e06b4c9 100644
--- a/editor/filesystem_dock.cpp
+++ b/editor/filesystem_dock.cpp
@@ -1531,6 +1531,10 @@ void FileSystemDock::_make_scene_confirm() {
EditorNode::get_singleton()->save_scene_list({ scene_path });
}
+void FileSystemDock::_resource_removed(const Ref<Resource> &p_resource) {
+ emit_signal(SNAME("resource_removed"), p_resource);
+}
+
void FileSystemDock::_file_removed(String p_file) {
emit_signal(SNAME("file_removed"), p_file);
@@ -3095,6 +3099,7 @@ void FileSystemDock::_bind_methods() {
ADD_SIGNAL(MethodInfo("inherit", PropertyInfo(Variant::STRING, "file")));
ADD_SIGNAL(MethodInfo("instantiate", PropertyInfo(Variant::PACKED_STRING_ARRAY, "files")));
+ ADD_SIGNAL(MethodInfo("resource_removed", PropertyInfo(Variant::OBJECT, "resource", PROPERTY_HINT_RESOURCE_TYPE, "Resource")));
ADD_SIGNAL(MethodInfo("file_removed", PropertyInfo(Variant::STRING, "file")));
ADD_SIGNAL(MethodInfo("folder_removed", PropertyInfo(Variant::STRING, "folder")));
ADD_SIGNAL(MethodInfo("files_moved", PropertyInfo(Variant::STRING, "old_file"), PropertyInfo(Variant::STRING, "new_file")));
@@ -3254,6 +3259,7 @@ FileSystemDock::FileSystemDock() {
add_child(owners_editor);
remove_dialog = memnew(DependencyRemoveDialog);
+ remove_dialog->connect("resource_removed", callable_mp(this, &FileSystemDock::_resource_removed));
remove_dialog->connect("file_removed", callable_mp(this, &FileSystemDock::_file_removed));
remove_dialog->connect("folder_removed", callable_mp(this, &FileSystemDock::_folder_removed));
add_child(remove_dialog);
diff --git a/editor/filesystem_dock.h b/editor/filesystem_dock.h
index 42a72b7ee8..ede6869eea 100644
--- a/editor/filesystem_dock.h
+++ b/editor/filesystem_dock.h
@@ -227,6 +227,7 @@ private:
void _update_favorites_list_after_move(const HashMap<String, String> &p_files_renames, const HashMap<String, String> &p_folders_renames) const;
void _update_project_settings_after_move(const HashMap<String, String> &p_renames) const;
+ void _resource_removed(const Ref<Resource> &p_resource);
void _file_removed(String p_file);
void _folder_removed(String p_folder);
diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp
index 5d0555a10e..e09636d297 100644
--- a/editor/plugins/canvas_item_editor_plugin.cpp
+++ b/editor/plugins/canvas_item_editor_plugin.cpp
@@ -1259,57 +1259,25 @@ bool CanvasItemEditor::_gui_input_zoom_or_pan(const Ref<InputEvent> &p_event, bo
}
}
- Ref<InputEventMagnifyGesture> magnify_gesture = p_event;
- if (magnify_gesture.is_valid() && !p_already_accepted) {
- // Zoom gesture
- _zoom_on_position(zoom * magnify_gesture->get_factor(), magnify_gesture->get_position());
- return true;
- }
-
- Ref<InputEventPanGesture> pan_gesture = p_event;
- if (pan_gesture.is_valid() && !p_already_accepted) {
- // If ctrl key pressed, then zoom instead of pan.
- if (pan_gesture->is_ctrl_pressed()) {
- const real_t factor = pan_gesture->get_delta().y;
-
- zoom_widget->set_zoom_by_increments(1);
- if (factor != 1.f) {
- zoom_widget->set_zoom(zoom * ((zoom_widget->get_zoom() / zoom - 1.f) * factor + 1.f));
- }
- _zoom_on_position(zoom_widget->get_zoom(), pan_gesture->get_position());
-
- return true;
- }
-
- // Pan gesture
- const Vector2 delta = (pan_speed / zoom) * pan_gesture->get_delta();
- view_offset.x += delta.x;
- view_offset.y += delta.y;
- update_viewport();
- return true;
- }
-
return false;
}
-void CanvasItemEditor::_scroll_callback(Vector2 p_scroll_vec, bool p_alt) {
- _pan_callback(-p_scroll_vec * pan_speed);
-}
-
-void CanvasItemEditor::_pan_callback(Vector2 p_scroll_vec) {
+void CanvasItemEditor::_pan_callback(Vector2 p_scroll_vec, Ref<InputEvent> p_event) {
view_offset.x -= p_scroll_vec.x / zoom;
view_offset.y -= p_scroll_vec.y / zoom;
update_viewport();
}
-void CanvasItemEditor::_zoom_callback(Vector2 p_scroll_vec, Vector2 p_origin, bool p_alt) {
- int scroll_sign = (int)SIGN(p_scroll_vec.y);
- // Inverted so that scrolling up (-1) zooms in, scrolling down (+1) zooms out.
- zoom_widget->set_zoom_by_increments(-scroll_sign, p_alt);
- if (!Math::is_equal_approx(ABS(p_scroll_vec.y), (real_t)1.0)) {
- // Handle high-precision (analog) scrolling.
- zoom_widget->set_zoom(zoom * ((zoom_widget->get_zoom() / zoom - 1.f) * ABS(p_scroll_vec.y) + 1.f));
+void CanvasItemEditor::_zoom_callback(float p_zoom_factor, Vector2 p_origin, Ref<InputEvent> p_event) {
+ Ref<InputEventMouseButton> mb = p_event;
+ if (mb.is_valid()) {
+ // Special behvior for scroll events, as the zoom_by_increment method can smartly end up on powers of two.
+ int increment = p_zoom_factor > 1.0 ? 1 : -1;
+ zoom_widget->set_zoom_by_increments(increment, mb->is_alt_pressed());
+ } else {
+ zoom_widget->set_zoom(zoom_widget->get_zoom() * p_zoom_factor);
}
+
_zoom_on_position(zoom_widget->get_zoom(), p_origin);
}
@@ -3868,7 +3836,7 @@ void CanvasItemEditor::_update_editor_settings() {
context_menu_panel->add_theme_style_override("panel", get_theme_stylebox(SNAME("ContextualToolbar"), SNAME("EditorStyles")));
panner->setup((ViewPanner::ControlScheme)EDITOR_GET("editors/panning/2d_editor_panning_scheme").operator int(), ED_GET_SHORTCUT("canvas_item_editor/pan_view"), bool(EDITOR_GET("editors/panning/simple_panning")));
- pan_speed = int(EDITOR_GET("editors/panning/2d_editor_pan_speed"));
+ panner->set_scroll_speed(EDITOR_GET("editors/panning/2d_editor_pan_speed"));
warped_panning = bool(EDITOR_GET("editors/panning/warped_mouse_panning"));
}
@@ -5059,7 +5027,7 @@ CanvasItemEditor::CanvasItemEditor() {
zoom_widget->connect("zoom_changed", callable_mp(this, &CanvasItemEditor::_update_zoom));
panner.instantiate();
- panner->set_callbacks(callable_mp(this, &CanvasItemEditor::_scroll_callback), callable_mp(this, &CanvasItemEditor::_pan_callback), callable_mp(this, &CanvasItemEditor::_zoom_callback));
+ panner->set_callbacks(callable_mp(this, &CanvasItemEditor::_pan_callback), callable_mp(this, &CanvasItemEditor::_zoom_callback));
viewport = memnew(CanvasItemEditorViewport(this));
viewport_scrollable->add_child(viewport);
diff --git a/editor/plugins/canvas_item_editor_plugin.h b/editor/plugins/canvas_item_editor_plugin.h
index 1e01eac82d..ebe87a56f7 100644
--- a/editor/plugins/canvas_item_editor_plugin.h
+++ b/editor/plugins/canvas_item_editor_plugin.h
@@ -363,10 +363,8 @@ private:
Ref<ViewPanner> panner;
bool warped_panning = true;
- int pan_speed = 20;
- void _scroll_callback(Vector2 p_scroll_vec, bool p_alt);
- void _pan_callback(Vector2 p_scroll_vec);
- void _zoom_callback(Vector2 p_scroll_vec, Vector2 p_origin, bool p_alt);
+ void _pan_callback(Vector2 p_scroll_vec, Ref<InputEvent> p_event);
+ void _zoom_callback(float p_zoom_factor, Vector2 p_origin, Ref<InputEvent> p_event);
bool _is_node_locked(const Node *p_node) const;
bool _is_node_movable(const Node *p_node, bool p_popup_warning = false);
diff --git a/editor/plugins/polygon_2d_editor_plugin.cpp b/editor/plugins/polygon_2d_editor_plugin.cpp
index c30f0ec62d..fb35668310 100644
--- a/editor/plugins/polygon_2d_editor_plugin.cpp
+++ b/editor/plugins/polygon_2d_editor_plugin.cpp
@@ -939,21 +939,13 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) {
}
}
-void Polygon2DEditor::_uv_scroll_callback(Vector2 p_scroll_vec, bool p_alt) {
- _uv_pan_callback(-p_scroll_vec * 32);
-}
-
-void Polygon2DEditor::_uv_pan_callback(Vector2 p_scroll_vec) {
+void Polygon2DEditor::_uv_pan_callback(Vector2 p_scroll_vec, Ref<InputEvent> p_event) {
uv_hscroll->set_value(uv_hscroll->get_value() - p_scroll_vec.x);
uv_vscroll->set_value(uv_vscroll->get_value() - p_scroll_vec.y);
}
-void Polygon2DEditor::_uv_zoom_callback(Vector2 p_scroll_vec, Vector2 p_origin, bool p_alt) {
- if (p_scroll_vec.y < 0) {
- uv_zoom->set_value(uv_zoom->get_value() / (1 - (0.1 * Math::abs(p_scroll_vec.y))));
- } else {
- uv_zoom->set_value(uv_zoom->get_value() * (1 - (0.1 * Math::abs(p_scroll_vec.y))));
- }
+void Polygon2DEditor::_uv_zoom_callback(float p_zoom_factor, Vector2 p_origin, Ref<InputEvent> p_event) {
+ uv_zoom->set_value(uv_zoom->get_value() * p_zoom_factor);
}
void Polygon2DEditor::_uv_scroll_changed(real_t) {
@@ -1478,7 +1470,7 @@ Polygon2DEditor::Polygon2DEditor() {
bone_scroll->add_child(bone_scroll_vb);
uv_panner.instantiate();
- uv_panner->set_callbacks(callable_mp(this, &Polygon2DEditor::_uv_scroll_callback), callable_mp(this, &Polygon2DEditor::_uv_pan_callback), callable_mp(this, &Polygon2DEditor::_uv_zoom_callback));
+ uv_panner->set_callbacks(callable_mp(this, &Polygon2DEditor::_uv_pan_callback), callable_mp(this, &Polygon2DEditor::_uv_zoom_callback));
uv_edit_draw->connect("draw", callable_mp(this, &Polygon2DEditor::_uv_draw));
uv_edit_draw->connect("gui_input", callable_mp(this, &Polygon2DEditor::_uv_input));
diff --git a/editor/plugins/polygon_2d_editor_plugin.h b/editor/plugins/polygon_2d_editor_plugin.h
index 7246c08bea..2c55a5f631 100644
--- a/editor/plugins/polygon_2d_editor_plugin.h
+++ b/editor/plugins/polygon_2d_editor_plugin.h
@@ -90,9 +90,8 @@ class Polygon2DEditor : public AbstractPolygon2DEditor {
TextureRect *uv_icon_zoom = nullptr;
Ref<ViewPanner> uv_panner;
- void _uv_scroll_callback(Vector2 p_scroll_vec, bool p_alt);
- void _uv_pan_callback(Vector2 p_scroll_vec);
- void _uv_zoom_callback(Vector2 p_scroll_vec, Vector2 p_origin, bool p_alt);
+ void _uv_pan_callback(Vector2 p_scroll_vec, Ref<InputEvent> p_event);
+ void _uv_zoom_callback(float p_zoom_factor, Vector2 p_origin, Ref<InputEvent> p_event);
VBoxContainer *bone_scroll_main_vb = nullptr;
ScrollContainer *bone_scroll = nullptr;
diff --git a/editor/plugins/texture_region_editor_plugin.cpp b/editor/plugins/texture_region_editor_plugin.cpp
index d7559bc18e..76f2bb7bb5 100644
--- a/editor/plugins/texture_region_editor_plugin.cpp
+++ b/editor/plugins/texture_region_editor_plugin.cpp
@@ -620,22 +620,14 @@ void TextureRegionEditor::_region_input(const Ref<InputEvent> &p_input) {
}
}
-void TextureRegionEditor::_scroll_callback(Vector2 p_scroll_vec, bool p_alt) {
- _pan_callback(-p_scroll_vec * 32);
-}
-
-void TextureRegionEditor::_pan_callback(Vector2 p_scroll_vec) {
+void TextureRegionEditor::_pan_callback(Vector2 p_scroll_vec, Ref<InputEvent> p_event) {
p_scroll_vec /= draw_zoom;
hscroll->set_value(hscroll->get_value() - p_scroll_vec.x);
vscroll->set_value(vscroll->get_value() - p_scroll_vec.y);
}
-void TextureRegionEditor::_zoom_callback(Vector2 p_scroll_vec, Vector2 p_origin, bool p_alt) {
- if (p_scroll_vec.y < 0) {
- _zoom_on_position(draw_zoom * ((0.95 + (0.05 * Math::abs(p_scroll_vec.y))) / 0.95), p_origin);
- } else {
- _zoom_on_position(draw_zoom * (1 - (0.05 * Math::abs(p_scroll_vec.y))), p_origin);
- }
+void TextureRegionEditor::_zoom_callback(float p_zoom_factor, Vector2 p_origin, Ref<InputEvent> p_event) {
+ _zoom_on_position(draw_zoom * p_zoom_factor, p_origin);
}
void TextureRegionEditor::_scroll_changed(float) {
@@ -1169,7 +1161,7 @@ TextureRegionEditor::TextureRegionEditor() {
hb_grid->hide();
panner.instantiate();
- panner->set_callbacks(callable_mp(this, &TextureRegionEditor::_scroll_callback), callable_mp(this, &TextureRegionEditor::_pan_callback), callable_mp(this, &TextureRegionEditor::_zoom_callback));
+ panner->set_callbacks(callable_mp(this, &TextureRegionEditor::_pan_callback), callable_mp(this, &TextureRegionEditor::_zoom_callback));
edit_draw = memnew(Panel);
vb->add_child(edit_draw);
diff --git a/editor/plugins/texture_region_editor_plugin.h b/editor/plugins/texture_region_editor_plugin.h
index 0325700d25..ba64a04084 100644
--- a/editor/plugins/texture_region_editor_plugin.h
+++ b/editor/plugins/texture_region_editor_plugin.h
@@ -103,9 +103,8 @@ class TextureRegionEditor : public AcceptDialog {
bool request_center = false;
Ref<ViewPanner> panner;
- void _scroll_callback(Vector2 p_scroll_vec, bool p_alt);
- void _pan_callback(Vector2 p_scroll_vec);
- void _zoom_callback(Vector2 p_scroll_vec, Vector2 p_origin, bool p_alt);
+ void _pan_callback(Vector2 p_scroll_vec, Ref<InputEvent> p_event);
+ void _zoom_callback(float p_zoom_factor, Vector2 p_origin, Ref<InputEvent> p_event);
void _set_snap_mode(int p_mode);
void _set_snap_off_x(float p_val);
diff --git a/editor/plugins/tiles/tile_atlas_view.cpp b/editor/plugins/tiles/tile_atlas_view.cpp
index 0ac375407c..e430848875 100644
--- a/editor/plugins/tiles/tile_atlas_view.cpp
+++ b/editor/plugins/tiles/tile_atlas_view.cpp
@@ -47,18 +47,14 @@ void TileAtlasView::gui_input(const Ref<InputEvent> &p_event) {
}
}
-void TileAtlasView::_scroll_callback(Vector2 p_scroll_vec, bool p_alt) {
- _pan_callback(-p_scroll_vec * 32);
-}
-
-void TileAtlasView::_pan_callback(Vector2 p_scroll_vec) {
+void TileAtlasView::_pan_callback(Vector2 p_scroll_vec, Ref<InputEvent> p_event) {
panning += p_scroll_vec;
_update_zoom_and_panning(true);
emit_signal(SNAME("transform_changed"), zoom_widget->get_zoom(), panning);
}
-void TileAtlasView::_zoom_callback(Vector2 p_scroll_vec, Vector2 p_origin, bool p_alt) {
- zoom_widget->set_zoom_by_increments(-p_scroll_vec.y * 2);
+void TileAtlasView::_zoom_callback(float p_zoom_factor, Vector2 p_origin, Ref<InputEvent> p_event) {
+ zoom_widget->set_zoom(zoom_widget->get_zoom() * p_zoom_factor);
_update_zoom_and_panning(true);
emit_signal(SNAME("transform_changed"), zoom_widget->get_zoom(), panning);
}
@@ -583,7 +579,7 @@ TileAtlasView::TileAtlasView() {
add_child(button_center_view);
panner.instantiate();
- panner->set_callbacks(callable_mp(this, &TileAtlasView::_scroll_callback), callable_mp(this, &TileAtlasView::_pan_callback), callable_mp(this, &TileAtlasView::_zoom_callback));
+ panner->set_callbacks(callable_mp(this, &TileAtlasView::_pan_callback), callable_mp(this, &TileAtlasView::_zoom_callback));
panner->set_enable_rmb(true);
center_container = memnew(CenterContainer);
diff --git a/editor/plugins/tiles/tile_atlas_view.h b/editor/plugins/tiles/tile_atlas_view.h
index f719bee704..4a7547f34b 100644
--- a/editor/plugins/tiles/tile_atlas_view.h
+++ b/editor/plugins/tiles/tile_atlas_view.h
@@ -65,9 +65,8 @@ private:
virtual void gui_input(const Ref<InputEvent> &p_event) override;
Ref<ViewPanner> panner;
- void _scroll_callback(Vector2 p_scroll_vec, bool p_alt);
- void _pan_callback(Vector2 p_scroll_vec);
- void _zoom_callback(Vector2 p_scroll_vec, Vector2 p_origin, bool p_alt);
+ void _pan_callback(Vector2 p_scroll_vec, Ref<InputEvent> p_event);
+ void _zoom_callback(float p_zoom_factor, Vector2 p_origin, Ref<InputEvent> p_event);
HashMap<Vector2, HashMap<int, Rect2i>> alternative_tiles_rect_cache;
void _update_alternative_tiles_rect_cache();
diff --git a/editor/plugins/tiles/tiles_editor_plugin.cpp b/editor/plugins/tiles/tiles_editor_plugin.cpp
index 19ee0ae98d..77dd0f7793 100644
--- a/editor/plugins/tiles/tiles_editor_plugin.cpp
+++ b/editor/plugins/tiles/tiles_editor_plugin.cpp
@@ -101,7 +101,7 @@ void TilesEditorPlugin::_thread() {
encompassing_rect.expand_to(world_pos);
// Texture.
- Ref<TileSetAtlasSource> atlas_source = tile_set->get_source(tile_map->get_cell_source_id(0, cell));
+ Ref<TileSetAtlasSource> atlas_source = item.tile_set->get_source(tile_map->get_cell_source_id(0, cell));
if (atlas_source.is_valid()) {
Vector2i coords = tile_map->get_cell_atlas_coords(0, cell);
int alternative = tile_map->get_cell_alternative_tile(0, cell);
diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp
index 4c5cde926a..af70e64b6a 100644
--- a/editor/plugins/visual_shader_editor_plugin.cpp
+++ b/editor/plugins/visual_shader_editor_plugin.cpp
@@ -40,6 +40,7 @@
#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/editor_undo_redo_manager.h"
+#include "editor/filesystem_dock.h"
#include "editor/inspector_dock.h"
#include "editor/plugins/curve_editor_plugin.h"
#include "editor/plugins/shader_editor_plugin.h"
@@ -1271,18 +1272,55 @@ Dictionary VisualShaderEditor::get_custom_node_data(Ref<VisualShaderNodeCustom>
return dict;
}
-void VisualShaderEditor::update_custom_type(const Ref<Resource> &p_resource) {
- Ref<Script> scr = Ref<Script>(p_resource.ptr());
- if (scr.is_null() || scr->get_instance_base_type() != "VisualShaderNodeCustom") {
+void VisualShaderEditor::_get_current_mode_limits(int &r_begin_type, int &r_end_type) const {
+ switch (visual_shader->get_mode()) {
+ case Shader::MODE_CANVAS_ITEM:
+ case Shader::MODE_SPATIAL: {
+ r_begin_type = 0;
+ r_end_type = 3;
+ } break;
+ case Shader::MODE_PARTICLES: {
+ r_begin_type = 3;
+ r_end_type = 5 + r_begin_type;
+ } break;
+ case Shader::MODE_SKY: {
+ r_begin_type = 8;
+ r_end_type = 1 + r_begin_type;
+ } break;
+ case Shader::MODE_FOG: {
+ r_begin_type = 9;
+ r_end_type = 1 + r_begin_type;
+ } break;
+ default: {
+ } break;
+ }
+}
+
+void VisualShaderEditor::_script_created(const Ref<Script> &p_script) {
+ if (p_script.is_null() || p_script->get_instance_base_type() != "VisualShaderNodeCustom") {
+ return;
+ }
+ Ref<VisualShaderNodeCustom> ref;
+ ref.instantiate();
+ ref->set_script(p_script);
+
+ Dictionary dict = get_custom_node_data(ref);
+ add_custom_type(dict["name"], dict["script"], dict["description"], dict["return_icon_type"], dict["category"], dict["highend"]);
+
+ _update_options_menu();
+}
+
+void VisualShaderEditor::_update_custom_script(const Ref<Script> &p_script) {
+ if (p_script.is_null() || p_script->get_instance_base_type() != "VisualShaderNodeCustom") {
return;
}
Ref<VisualShaderNodeCustom> ref;
ref.instantiate();
- ref->set_script(scr);
+ ref->set_script(p_script);
if (!ref->is_available(visual_shader->get_mode(), visual_shader->get_shader_type())) {
for (int i = 0; i < add_options.size(); i++) {
- if (add_options[i].is_custom && add_options[i].script == scr) {
+ if (add_options[i].is_custom && add_options[i].script == p_script) {
add_options.remove_at(i);
_update_options_menu();
// TODO: Make indication for the existed custom nodes with that script on graph to be disabled.
@@ -1296,8 +1334,8 @@ void VisualShaderEditor::update_custom_type(const Ref<Resource> &p_resource) {
bool found_type = false;
bool need_rebuild = false;
- for (int i = 0; i < add_options.size(); i++) {
- if (add_options[i].is_custom && add_options[i].script == scr) {
+ for (int i = custom_node_option_idx; i < add_options.size(); i++) {
+ if (add_options[i].script == p_script) {
found_type = true;
add_options.write[i].name = dict["name"];
@@ -1306,31 +1344,11 @@ void VisualShaderEditor::update_custom_type(const Ref<Resource> &p_resource) {
add_options.write[i].category = dict["category"];
add_options.write[i].highend = dict["highend"];
- int max_type = 0;
- int type_offset = 0;
- switch (visual_shader->get_mode()) {
- case Shader::MODE_CANVAS_ITEM:
- case Shader::MODE_SPATIAL: {
- max_type = 3;
- } break;
- case Shader::MODE_PARTICLES: {
- max_type = 5;
- type_offset = 3;
- } break;
- case Shader::MODE_SKY: {
- max_type = 1;
- type_offset = 8;
- } break;
- case Shader::MODE_FOG: {
- max_type = 1;
- type_offset = 9;
- } break;
- default: {
- } break;
- }
- max_type = type_offset + max_type;
+ int begin_type = 0;
+ int end_type = 0;
+ _get_current_mode_limits(begin_type, end_type);
- for (int t = type_offset; t < max_type; t++) {
+ for (int t = begin_type; t < end_type; t++) {
VisualShader::Type type = (VisualShader::Type)t;
Vector<int> nodes = visual_shader->get_node_list(type);
@@ -1339,28 +1357,27 @@ void VisualShaderEditor::update_custom_type(const Ref<Resource> &p_resource) {
List<VisualShader::Connection> custom_node_input_connections;
List<VisualShader::Connection> custom_node_output_connections;
+
for (const VisualShader::Connection &E : node_connections) {
int from = E.from_node;
- int from_idx = E.from_port;
+ int from_port = E.from_port;
int to = E.to_node;
- int to_idx = E.to_port;
+ int to_port = E.to_port;
- if (graph_plugin->get_node_script(from) == scr) {
- custom_node_output_connections.push_back({ from, from_idx, to, to_idx });
- } else if (graph_plugin->get_node_script(to) == scr) {
- custom_node_input_connections.push_back({ from, from_idx, to, to_idx });
+ if (graph_plugin->get_node_script(from) == p_script) {
+ custom_node_output_connections.push_back({ from, from_port, to, to_port });
+ } else if (graph_plugin->get_node_script(to) == p_script) {
+ custom_node_input_connections.push_back({ from, from_port, to, to_port });
}
}
- for (int j = 0; j < nodes.size(); j++) {
- int node_id = nodes[j];
-
+ for (int node_id : nodes) {
Ref<VisualShaderNode> vsnode = visual_shader->get_node(type, node_id);
if (vsnode.is_null()) {
continue;
}
Ref<VisualShaderNodeCustom> custom_node = Ref<VisualShaderNodeCustom>(vsnode.ptr());
- if (custom_node.is_null() || custom_node->get_script() != scr) {
+ if (custom_node.is_null() || custom_node->get_script() != p_script) {
continue;
}
need_rebuild = true;
@@ -1429,6 +1446,89 @@ void VisualShaderEditor::update_custom_type(const Ref<Resource> &p_resource) {
}
}
+void VisualShaderEditor::_resource_saved(const Ref<Resource> &p_resource) {
+ _update_custom_script(Ref<Script>(p_resource.ptr()));
+}
+
+void VisualShaderEditor::_resources_removed() {
+ bool has_any_instance = false;
+
+ for (const Ref<Script> &scr : custom_scripts_to_delete) {
+ for (int i = custom_node_option_idx; i < add_options.size(); i++) {
+ if (add_options[i].script == scr) {
+ add_options.remove_at(i);
+
+ // Removes all node instances using that script from the graph.
+ {
+ int begin_type = 0;
+ int end_type = 0;
+ _get_current_mode_limits(begin_type, end_type);
+
+ for (int t = begin_type; t < end_type; t++) {
+ VisualShader::Type type = (VisualShader::Type)t;
+
+ List<VisualShader::Connection> node_connections;
+ visual_shader->get_node_connections(type, &node_connections);
+
+ for (const VisualShader::Connection &E : node_connections) {
+ int from = E.from_node;
+ int from_port = E.from_port;
+ int to = E.to_node;
+ int to_port = E.to_port;
+
+ if (graph_plugin->get_node_script(from) == scr || graph_plugin->get_node_script(to) == scr) {
+ visual_shader->disconnect_nodes(type, from, from_port, to, to_port);
+ graph_plugin->disconnect_nodes(type, from, from_port, to, to_port);
+ }
+ }
+
+ Vector<int> nodes = visual_shader->get_node_list(type);
+ for (int node_id : nodes) {
+ Ref<VisualShaderNode> vsnode = visual_shader->get_node(type, node_id);
+ if (vsnode.is_null()) {
+ continue;
+ }
+ Ref<VisualShaderNodeCustom> custom_node = Ref<VisualShaderNodeCustom>(vsnode.ptr());
+ if (custom_node.is_null() || custom_node->get_script() != scr) {
+ continue;
+ }
+ visual_shader->remove_node(type, node_id);
+ graph_plugin->remove_node(type, node_id, false);
+
+ has_any_instance = true;
+ }
+ }
+ }
+
+ break;
+ }
+ }
+ }
+ if (has_any_instance) {
+ EditorUndoRedoManager::get_singleton()->clear_history(); // Need to clear undo history, otherwise it may lead to hard-detected errors and crashes (since the script was removed).
+ ResourceSaver::save(visual_shader, visual_shader->get_path());
+ }
+ _update_options_menu();
+
+ custom_scripts_to_delete.clear();
+ pending_custom_scripts_to_delete = false;
+}
+
+void VisualShaderEditor::_resource_removed(const Ref<Resource> &p_resource) {
+ Ref<Script> scr = Ref<Script>(p_resource.ptr());
+ if (scr.is_null() || scr->get_instance_base_type() != "VisualShaderNodeCustom") {
+ return;
+ }
+
+ custom_scripts_to_delete.push_back(scr);
+
+ if (!pending_custom_scripts_to_delete) {
+ pending_custom_scripts_to_delete = true;
+
+ call_deferred("_resources_removed");
+ }
+}
+
void VisualShaderEditor::_update_options_menu_deferred() {
_update_options_menu();
@@ -4901,13 +5001,16 @@ void VisualShaderEditor::_bind_methods() {
ClassDB::bind_method("_expand_output_port", &VisualShaderEditor::_expand_output_port);
ClassDB::bind_method("_update_options_menu_deferred", &VisualShaderEditor::_update_options_menu_deferred);
ClassDB::bind_method("_rebuild_shader_deferred", &VisualShaderEditor::_rebuild_shader_deferred);
+ ClassDB::bind_method("_resources_removed", &VisualShaderEditor::_resources_removed);
ClassDB::bind_method("_is_available", &VisualShaderEditor::_is_available);
}
VisualShaderEditor::VisualShaderEditor() {
ShaderLanguage::get_keyword_list(&keyword_list);
- EditorNode::get_singleton()->connect("resource_saved", callable_mp(this, &VisualShaderEditor::update_custom_type));
+ EditorNode::get_singleton()->connect("resource_saved", callable_mp(this, &VisualShaderEditor::_resource_saved));
+ FileSystemDock::get_singleton()->get_script_create_dialog()->connect("script_created", callable_mp(this, &VisualShaderEditor::_script_created));
+ FileSystemDock::get_singleton()->connect("resource_removed", callable_mp(this, &VisualShaderEditor::_resource_removed));
graph = memnew(GraphEdit);
graph->get_zoom_hbox()->set_h_size_flags(SIZE_EXPAND_FILL);
diff --git a/editor/plugins/visual_shader_editor_plugin.h b/editor/plugins/visual_shader_editor_plugin.h
index c4f6b4952c..519a390ccc 100644
--- a/editor/plugins/visual_shader_editor_plugin.h
+++ b/editor/plugins/visual_shader_editor_plugin.h
@@ -188,6 +188,9 @@ class VisualShaderEditor : public VBoxContainer {
PanelContainer *error_panel = nullptr;
Label *error_label = nullptr;
+ bool pending_custom_scripts_to_delete = false;
+ List<Ref<Script>> custom_scripts_to_delete;
+
bool _block_update_options_menu = false;
bool _block_rebuild_shader = false;
@@ -503,6 +506,13 @@ class VisualShaderEditor : public VBoxContainer {
void _visibility_changed();
+ void _get_current_mode_limits(int &r_begin_type, int &r_end_type) const;
+ void _update_custom_script(const Ref<Script> &p_script);
+ void _script_created(const Ref<Script> &p_script);
+ void _resource_saved(const Ref<Resource> &p_resource);
+ void _resource_removed(const Ref<Resource> &p_resource);
+ void _resources_removed();
+
protected:
void _notification(int p_what);
static void _bind_methods();
@@ -517,7 +527,6 @@ public:
void add_custom_type(const String &p_name, const Ref<Script> &p_script, const String &p_description, int p_return_icon_type, const String &p_category, bool p_highend);
Dictionary get_custom_node_data(Ref<VisualShaderNodeCustom> &p_custom_node);
- void update_custom_type(const Ref<Resource> &p_resource);
virtual Size2 get_minimum_size() const override;
void edit(VisualShader *p_visual_shader);