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.cpp337
-rw-r--r--editor/connections_dialog.h32
-rw-r--r--editor/create_dialog.cpp7
-rw-r--r--editor/create_dialog.h3
-rw-r--r--editor/debugger/script_editor_debugger.cpp38
-rw-r--r--editor/debugger/script_editor_debugger.h2
-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.cpp8
-rw-r--r--editor/editor_run.cpp4
-rw-r--r--editor/editor_settings.cpp8
-rw-r--r--editor/editor_themes.cpp22
-rw-r--r--editor/editor_title_bar.cpp2
-rw-r--r--editor/editor_title_bar.h2
-rw-r--r--editor/editor_zoom_widget.cpp20
-rw-r--r--editor/export/editor_export_platform.cpp21
-rw-r--r--editor/filesystem_dock.cpp6
-rw-r--r--editor/filesystem_dock.h1
-rw-r--r--editor/import/resource_importer_texture.cpp16
-rw-r--r--editor/plugins/animation_player_editor_plugin.cpp10
-rw-r--r--editor/plugins/animation_state_machine_editor.cpp98
-rw-r--r--editor/plugins/animation_state_machine_editor.h22
-rw-r--r--editor/plugins/animation_tree_editor_plugin.cpp13
-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/navigation_link_2d_editor_plugin.cpp36
-rw-r--r--editor/plugins/navigation_link_2d_editor_plugin.h4
-rw-r--r--editor/plugins/node_3d_editor_gizmos.cpp68
-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/script_text_editor.cpp6
-rw-r--r--editor/plugins/sprite_frames_editor_plugin.cpp500
-rw-r--r--editor/plugins/sprite_frames_editor_plugin.h43
-rw-r--r--editor/plugins/texture_region_editor_plugin.cpp19
-rw-r--r--editor/plugins/texture_region_editor_plugin.h5
-rw-r--r--editor/plugins/tiles/tile_atlas_view.cpp41
-rw-r--r--editor/plugins/tiles/tile_atlas_view.h5
-rw-r--r--editor/plugins/tiles/tile_data_editors.cpp90
-rw-r--r--editor/plugins/tiles/tile_data_editors.h4
-rw-r--r--editor/plugins/tiles/tile_map_editor.cpp38
-rw-r--r--editor/plugins/tiles/tile_map_editor.h3
-rw-r--r--editor/plugins/tiles/tile_set_atlas_source_editor.cpp81
-rw-r--r--editor/plugins/tiles/tile_set_atlas_source_editor.h4
-rw-r--r--editor/plugins/tiles/tile_set_editor.cpp41
-rw-r--r--editor/plugins/tiles/tile_set_editor.h2
-rw-r--r--editor/plugins/tiles/tile_set_scenes_collection_source_editor.cpp25
-rw-r--r--editor/plugins/tiles/tile_set_scenes_collection_source_editor.h2
-rw-r--r--editor/plugins/tiles/tiles_editor_plugin.cpp4
-rw-r--r--editor/plugins/visual_shader_editor_plugin.cpp187
-rw-r--r--editor/plugins/visual_shader_editor_plugin.h11
-rw-r--r--editor/project_converter_3_to_4.cpp43
-rw-r--r--editor/scene_tree_dock.cpp4
-rw-r--r--editor/scene_tree_editor.cpp2
58 files changed, 1483 insertions, 642 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 9ff480f130..dee130ed0f 100644
--- a/editor/connections_dialog.cpp
+++ b/editor/connections_dialog.cpp
@@ -30,6 +30,7 @@
#include "connections_dialog.h"
+#include "core/config/project_settings.h"
#include "editor/doc_tools.h"
#include "editor/editor_help.h"
#include "editor/editor_node.h"
@@ -165,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();
}
@@ -182,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.
*/
@@ -242,14 +249,153 @@ StringName ConnectDialog::generate_method_callback_name(Node *p_source, String p
String dst_method;
if (p_source == p_target) {
- dst_method = String(EDITOR_GET("interface/editors/default_signal_callback_to_self_name")).format(subst);
+ dst_method = String(GLOBAL_GET("editor/naming/default_signal_callback_to_self_name")).format(subst);
} else {
- dst_method = String(EDITOR_GET("interface/editors/default_signal_callback_name")).format(subst);
+ dst_method = String(GLOBAL_GET("editor/naming/default_signal_callback_name")).format(subst);
}
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()) {
+ empty_tree_label->set_visible(root_item->get_first_child() == nullptr);
+ 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());
+
+ empty_tree_label->set_visible(root_item->get_first_child() == nullptr);
+}
+
+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.
@@ -262,7 +408,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;
}
@@ -288,14 +434,13 @@ 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"));
+ open_method_tree->set_icon(get_theme_icon("Edit", "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"));
}
@@ -303,10 +448,18 @@ Node *ConnectDialog::get_source() const {
return source;
}
+ConnectDialog::ConnectionData ConnectDialog::get_source_connection_data() const {
+ return source_connection_data;
+}
+
StringName ConnectDialog::get_signal_name() const {
return signal;
}
+PackedStringArray ConnectDialog::get_signal_args() const {
+ return signal_args;
+}
+
NodePath ConnectDialog::get_dst_path() const {
return dst_path;
}
@@ -355,11 +508,12 @@ bool ConnectDialog::is_editing() const {
* If creating a connection from scratch, sensible defaults are used.
* If editing an existing connection, previous data is retained.
*/
-void ConnectDialog::init(ConnectionData p_cd, bool p_edit) {
+void ConnectDialog::init(const ConnectionData &p_cd, const PackedStringArray &p_signal_args, bool p_edit) {
set_hide_on_ok(false);
source = static_cast<Node *>(p_cd.source);
signal = p_cd.signal;
+ signal_args = p_signal_args;
tree->set_selected(nullptr);
tree->set_marked(source, true);
@@ -377,22 +531,7 @@ void ConnectDialog::init(ConnectionData p_cd, bool p_edit) {
deferred->set_pressed(b_deferred);
one_shot->set_pressed(b_oneshot);
- MethodInfo r_signal;
- Ref<Script> source_script = source->get_script();
- if (source_script.is_valid() && source_script->has_script_signal(signal)) {
- List<MethodInfo> signals;
- source_script->get_script_signal_list(&signals);
- for (MethodInfo &mi : signals) {
- if (mi.name == signal) {
- r_signal = mi;
- break;
- }
- }
- } else {
- ClassDB::get_signal(source->get_class(), signal, &r_signal);
- }
-
- unbind_count->set_max(r_signal.arguments.size());
+ unbind_count->set_max(p_signal_args.size());
unbind_count->set_value(p_cd.unbinds);
_unbind_count_changed(p_cd.unbinds);
@@ -402,6 +541,8 @@ void ConnectDialog::init(ConnectionData p_cd, bool p_edit) {
cdbinds->notify_changed();
edit_mode = p_edit;
+
+ source_connection_data = p_cd;
}
void ConnectDialog::popup_dialog(const String &p_for_signal) {
@@ -437,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,8 +598,8 @@ ConnectDialog::ConnectDialog() {
vbc_left->set_h_size_flags(Control::SIZE_EXPAND_FILL);
from_signal = memnew(LineEdit);
- from_signal->set_editable(false);
vbc_left->add_margin_child(TTR("From Signal:"), from_signal);
+ from_signal->set_editable(false);
tree = memnew(SceneTreeEditor(false));
tree->set_connecting_signal(true);
@@ -476,6 +616,43 @@ 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));
+
+ empty_tree_label = memnew(Label(TTR("No method found matching given filters.")));
+ method_tree->add_child(empty_tree_label);
+ empty_tree_label->set_anchors_and_offsets_preset(Control::PRESET_CENTER);
+
+ 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);
@@ -521,14 +698,22 @@ 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);
+
+ open_method_tree = memnew(Button);
+ hbc_method->add_child(open_method_tree);
+ open_method_tree->set_text("Pick");
+ open_method_tree->connect("pressed", callable_mp(this, &ConnectDialog::_open_method_popup));
- advanced = memnew(CheckButton);
+ advanced = memnew(CheckButton(TTR("Advanced")));
vbc_left->add_child(advanced);
- advanced->set_text(TTR("Advanced"));
advanced->set_h_size_flags(Control::SIZE_SHRINK_BEGIN | Control::SIZE_EXPAND);
advanced->set_pressed(EditorSettings::get_singleton()->get_project_metadata("editor_metadata", "use_advanced_connections", false));
advanced->connect("pressed", callable_mp(this, &ConnectDialog::_advanced_pressed));
@@ -566,7 +751,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>"
@@ -605,9 +790,6 @@ void ConnectionsDock::_filter_changed(const String &p_text) {
* Creates or edits connections based on state of the ConnectDialog when "Connect" is pressed.
*/
void ConnectionsDock::_make_or_edit_connection() {
- TreeItem *it = tree->get_selected();
- ERR_FAIL_COND(!it);
-
NodePath dst_path = connect_dialog->get_dst_path();
Node *target = selected_node->get_node(dst_path);
ERR_FAIL_COND(!target);
@@ -645,27 +827,21 @@ void ConnectionsDock::_make_or_edit_connection() {
add_script_function = !found_inherited_function;
}
- PackedStringArray script_function_args;
- if (add_script_function) {
- // Pick up args here before "it" is deleted by update_tree.
- script_function_args = it->get_metadata(0).operator Dictionary()["args"];
- script_function_args.resize(script_function_args.size() - cd.unbinds);
- for (int i = 0; i < cd.binds.size(); i++) {
- script_function_args.push_back("extra_arg_" + itos(i) + ":" + Variant::get_type_name(cd.binds[i].get_type()));
- }
- }
if (connect_dialog->is_editing()) {
- _disconnect(*it);
+ _disconnect(connect_dialog->get_source_connection_data());
_connect(cd);
} else {
_connect(cd);
}
- // IMPORTANT NOTE: _disconnect and _connect cause an update_tree, which will delete the object "it" is pointing to.
- it = nullptr;
-
if (add_script_function) {
+ PackedStringArray script_function_args = connect_dialog->get_signal_args();
+ script_function_args.resize(script_function_args.size() - cd.unbinds);
+ for (int i = 0; i < cd.binds.size(); i++) {
+ script_function_args.push_back("extra_arg_" + itos(i) + ":" + Variant::get_type_name(cd.binds[i].get_type()));
+ }
+
EditorNode::get_singleton()->emit_signal(SNAME("script_add_function_request"), target, cd.method, script_function_args);
hide();
}
@@ -676,7 +852,7 @@ void ConnectionsDock::_make_or_edit_connection() {
/*
* Creates single connection w/ undo-redo functionality.
*/
-void ConnectionsDock::_connect(ConnectDialog::ConnectionData p_cd) {
+void ConnectionsDock::_connect(const ConnectDialog::ConnectionData &p_cd) {
Node *source = Object::cast_to<Node>(p_cd.source);
Node *target = Object::cast_to<Node>(p_cd.target);
@@ -700,18 +876,15 @@ void ConnectionsDock::_connect(ConnectDialog::ConnectionData p_cd) {
/*
* Break single connection w/ undo-redo functionality.
*/
-void ConnectionsDock::_disconnect(TreeItem &p_item) {
- Connection connection = p_item.get_metadata(0);
- ConnectDialog::ConnectionData cd = connection;
-
- ERR_FAIL_COND(cd.source != selected_node); // Shouldn't happen but... Bugcheck.
+void ConnectionsDock::_disconnect(const ConnectDialog::ConnectionData &p_cd) {
+ ERR_FAIL_COND(p_cd.source != selected_node); // Shouldn't happen but... Bugcheck.
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
- undo_redo->create_action(vformat(TTR("Disconnect '%s' from '%s'"), cd.signal, cd.method));
+ undo_redo->create_action(vformat(TTR("Disconnect '%s' from '%s'"), p_cd.signal, p_cd.method));
- Callable callable = cd.get_callable();
- undo_redo->add_do_method(selected_node, "disconnect", cd.signal, callable);
- undo_redo->add_undo_method(selected_node, "connect", cd.signal, callable, cd.binds, cd.flags);
+ Callable callable = p_cd.get_callable();
+ undo_redo->add_do_method(selected_node, "disconnect", p_cd.signal, callable);
+ undo_redo->add_undo_method(selected_node, "connect", p_cd.signal, callable, p_cd.flags);
undo_redo->add_do_method(this, "update_tree");
undo_redo->add_undo_method(this, "update_tree");
undo_redo->add_do_method(SceneTreeDock::get_singleton()->get_tree_editor(), "update_tree"); // To force redraw of scene tree.
@@ -741,7 +914,7 @@ void ConnectionsDock::_disconnect_all() {
if (!_is_connection_inherited(connection)) {
ConnectDialog::ConnectionData cd = connection;
undo_redo->add_do_method(selected_node, "disconnect", cd.signal, cd.get_callable());
- undo_redo->add_undo_method(selected_node, "connect", cd.signal, cd.get_callable(), cd.binds, cd.flags);
+ undo_redo->add_undo_method(selected_node, "connect", cd.signal, cd.get_callable(), cd.flags);
}
child = child->get_next();
}
@@ -795,7 +968,10 @@ bool ConnectionsDock::_is_connection_inherited(Connection &p_connection) {
* Open connection dialog with TreeItem data to CREATE a brand-new connection.
*/
void ConnectionsDock::_open_connection_dialog(TreeItem &p_item) {
- String signal_name = p_item.get_metadata(0).operator Dictionary()["name"];
+ Dictionary sinfo = p_item.get_metadata(0);
+ String signal_name = sinfo["name"];
+ PackedStringArray signal_args = sinfo["args"];
+
const String &signal_name_ref = signal_name;
Node *dst_node = selected_node->get_owner() ? selected_node->get_owner() : selected_node;
@@ -809,22 +985,30 @@ void ConnectionsDock::_open_connection_dialog(TreeItem &p_item) {
cd.target = dst_node;
cd.method = ConnectDialog::generate_method_callback_name(cd.source, signal_name, cd.target);
connect_dialog->popup_dialog(signal_name_ref);
- connect_dialog->init(cd);
+ connect_dialog->init(cd, signal_args);
connect_dialog->set_title(TTR("Connect a Signal to a Method"));
}
/*
* Open connection dialog with Connection data to EDIT an existing connection.
*/
-void ConnectionsDock::_open_connection_dialog(ConnectDialog::ConnectionData p_cd) {
- Node *src = Object::cast_to<Node>(p_cd.source);
- Node *dst = Object::cast_to<Node>(p_cd.target);
+void ConnectionsDock::_open_edit_connection_dialog(TreeItem &p_item) {
+ TreeItem *signal_item = p_item.get_parent();
+ ERR_FAIL_COND(!signal_item);
+
+ Connection connection = p_item.get_metadata(0);
+ ConnectDialog::ConnectionData cd = connection;
+
+ Node *src = Object::cast_to<Node>(cd.source);
+ Node *dst = Object::cast_to<Node>(cd.target);
if (src && dst) {
- const String &signal_name_ref = p_cd.signal;
- connect_dialog->set_title(TTR("Edit Connection:") + p_cd.signal);
+ const String &signal_name_ref = cd.signal;
+ PackedStringArray signal_args = signal_item->get_metadata(0).operator Dictionary()["args"];
+
+ connect_dialog->set_title(vformat(TTR("Edit Connection: '%s'"), cd.signal));
connect_dialog->popup_dialog(signal_name_ref);
- connect_dialog->init(p_cd, true);
+ connect_dialog->init(cd, signal_args, true);
}
}
@@ -899,14 +1083,14 @@ void ConnectionsDock::_handle_slot_menu_option(int p_option) {
switch (p_option) {
case EDIT: {
- Connection connection = item->get_metadata(0);
- _open_connection_dialog(connection);
+ _open_edit_connection_dialog(*item);
} break;
case GO_TO_SCRIPT: {
_go_to_script(*item);
} break;
case DISCONNECT: {
- _disconnect(*item);
+ Connection connection = item->get_metadata(0);
+ _disconnect(connection);
update_tree();
} break;
}
@@ -957,7 +1141,8 @@ void ConnectionsDock::_connect_pressed() {
if (_is_item_signal(*item)) {
_open_connection_dialog(*item);
} else {
- _disconnect(*item);
+ Connection connection = item->get_metadata(0);
+ _disconnect(connection);
update_tree();
}
}
@@ -985,6 +1170,10 @@ void ConnectionsDock::set_node(Node *p_node) {
}
void ConnectionsDock::update_tree() {
+ String prev_selected;
+ if (tree->is_anything_selected()) {
+ prev_selected = tree->get_selected()->get_text(0);
+ }
tree->clear();
if (!selected_node) {
@@ -1076,7 +1265,14 @@ void ConnectionsDock::update_tree() {
// Create the children of the subsection - the actual list of signals.
TreeItem *signal_item = tree->create_item(section_item);
- signal_item->set_text(0, String(signal_name) + signaldesc);
+ String signame = String(signal_name) + signaldesc;
+ signal_item->set_text(0, signame);
+
+ if (signame == prev_selected) {
+ signal_item->select(0);
+ prev_selected = "";
+ }
+
Dictionary sinfo;
sinfo["name"] = signal_name;
sinfo["args"] = argnames;
@@ -1238,9 +1434,6 @@ ConnectionsDock::ConnectionsDock() {
tree->connect("item_mouse_selected", callable_mp(this, &ConnectionsDock::_rmb_pressed));
add_theme_constant_override("separation", 3 * EDSCALE);
-
- EDITOR_DEF("interface/editors/default_signal_callback_name", "_on_{node_name}_{signal_name}");
- EDITOR_DEF("interface/editors/default_signal_callback_to_self_name", "_on_{signal_name}");
}
ConnectionsDock::~ConnectionsDock() {
diff --git a/editor/connections_dialog.h b/editor/connections_dialog.h
index 829a98caed..f70970996d 100644
--- a/editor/connections_dialog.h
+++ b/editor/connections_dialog.h
@@ -88,7 +88,7 @@ public:
method = base_callable.get_method();
}
- Callable get_callable() {
+ Callable get_callable() const {
if (unbinds > 0) {
return Callable(target, method).unbind(unbinds);
} else if (!binds.is_empty()) {
@@ -107,16 +107,26 @@ private:
Label *connect_to_label = nullptr;
LineEdit *from_signal = nullptr;
Node *source = nullptr;
+ ConnectionData source_connection_data;
StringName signal;
+ PackedStringArray signal_args;
LineEdit *dst_method = nullptr;
ConnectDialogBinds *cdbinds = nullptr;
bool edit_mode = false;
bool first_popup = true;
NodePath dst_path;
VBoxContainer *vbc_right = nullptr;
-
SceneTreeEditor *tree = nullptr;
AcceptDialog *error = nullptr;
+
+ Button *open_method_tree = nullptr;
+ AcceptDialog *method_popup = nullptr;
+ Tree *method_tree = nullptr;
+ Label *empty_tree_label = 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 +142,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();
@@ -145,7 +163,9 @@ protected:
public:
static StringName generate_method_callback_name(Node *p_source, String p_signal_name, Node *p_target);
Node *get_source() const;
+ ConnectionData get_source_connection_data() const;
StringName get_signal_name() const;
+ PackedStringArray get_signal_args() const;
NodePath get_dst_path() const;
void set_dst_node(Node *p_node);
StringName get_dst_method_name() const;
@@ -157,7 +177,7 @@ public:
bool get_one_shot() const;
bool is_editing() const;
- void init(ConnectionData p_cd, bool p_edit = false);
+ void init(const ConnectionData &p_cd, const PackedStringArray &p_signal_args, bool p_edit = false);
void popup_dialog(const String &p_for_signal);
ConnectDialog();
@@ -203,8 +223,8 @@ class ConnectionsDock : public VBoxContainer {
void _filter_changed(const String &p_text);
void _make_or_edit_connection();
- void _connect(ConnectDialog::ConnectionData p_cd);
- void _disconnect(TreeItem &p_item);
+ void _connect(const ConnectDialog::ConnectionData &p_cd);
+ void _disconnect(const ConnectDialog::ConnectionData &p_cd);
void _disconnect_all();
void _tree_item_selected();
@@ -213,7 +233,7 @@ class ConnectionsDock : public VBoxContainer {
bool _is_connection_inherited(Connection &p_connection);
void _open_connection_dialog(TreeItem &p_item);
- void _open_connection_dialog(ConnectDialog::ConnectionData p_cd);
+ void _open_edit_connection_dialog(TreeItem &p_item);
void _go_to_script(TreeItem &p_item);
void _handle_signal_menu_option(int p_option);
diff --git a/editor/create_dialog.cpp b/editor/create_dialog.cpp
index 0814d5b5ca..aee907854c 100644
--- a/editor/create_dialog.cpp
+++ b/editor/create_dialog.cpp
@@ -122,7 +122,7 @@ bool CreateDialog::_should_hide_type(const String &p_type) const {
return true;
}
- if (base_type == "Node" && p_type.begins_with("Editor")) {
+ if (is_base_type_node && p_type.begins_with("Editor")) {
return true; // Do not show editor nodes.
}
@@ -508,6 +508,11 @@ String CreateDialog::get_selected_type() {
return selected->get_text(0);
}
+void CreateDialog::set_base_type(const String &p_base) {
+ base_type = p_base;
+ is_base_type_node = ClassDB::is_parent_class(p_base, "Node");
+}
+
Variant CreateDialog::instantiate_selected() {
TreeItem *selected = search_options->get_selected();
diff --git a/editor/create_dialog.h b/editor/create_dialog.h
index ad63346a02..37579812cf 100644
--- a/editor/create_dialog.h
+++ b/editor/create_dialog.h
@@ -51,6 +51,7 @@ class CreateDialog : public ConfirmationDialog {
Tree *search_options = nullptr;
String base_type;
+ bool is_base_type_node = false;
String icon_fallback;
String preferred_search_result_type;
@@ -113,7 +114,7 @@ public:
Variant instantiate_selected();
String get_selected_type();
- void set_base_type(const String &p_base) { base_type = p_base; }
+ void set_base_type(const String &p_base);
String get_base_type() const { return base_type; }
void select_base();
diff --git a/editor/debugger/script_editor_debugger.cpp b/editor/debugger/script_editor_debugger.cpp
index 2c6b9990ed..945a3ef932 100644
--- a/editor/debugger/script_editor_debugger.cpp
+++ b/editor/debugger/script_editor_debugger.cpp
@@ -519,7 +519,7 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da
String error_title;
if (oe.callstack.size() > 0) {
// If available, use the script's stack in the error title.
- error_title = oe.callstack[oe.callstack.size() - 1].func + ": ";
+ error_title = _format_frame_text(&oe.callstack[0]) + ": ";
} else if (!oe.source_func.is_empty()) {
// Otherwise try to use the C++ source function.
error_title += oe.source_func + ": ";
@@ -530,13 +530,25 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da
error->set_text(1, error_title);
tooltip += " " + error_title + "\n";
+ // Find the language of the error's source file.
+ String source_language_name = "C++"; // Default value is the old hard-coded one.
+ const String source_file_extension = oe.source_file.get_extension();
+ for (int i = 0; i < ScriptServer::get_language_count(); ++i) {
+ ScriptLanguage *script_language = ScriptServer::get_language(i);
+ if (source_file_extension == script_language->get_extension()) {
+ source_language_name = script_language->get_name();
+ break;
+ }
+ }
+
if (!oe.error_descr.is_empty()) {
// Add item for C++ error condition.
TreeItem *cpp_cond = error_tree->create_item(error);
- cpp_cond->set_text(0, "<" + TTR("C++ Error") + ">");
+ // TRANSLATORS: %s is the name of a language, e.g. C++.
+ cpp_cond->set_text(0, "<" + vformat(TTR("%s Error"), source_language_name) + ">");
cpp_cond->set_text(1, oe.error);
cpp_cond->set_text_alignment(0, HORIZONTAL_ALIGNMENT_LEFT);
- tooltip += TTR("C++ Error:") + " " + oe.error + "\n";
+ tooltip += vformat(TTR("%s Error:"), source_language_name) + "\n";
if (source_is_project_file) {
cpp_cond->set_metadata(0, source_meta);
}
@@ -547,14 +559,18 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da
// Source of the error.
String source_txt = (source_is_project_file ? oe.source_file.get_file() : oe.source_file) + ":" + itos(oe.source_line);
if (!oe.source_func.is_empty()) {
- source_txt += " @ " + oe.source_func + "()";
+ source_txt += " @ " + oe.source_func;
+ if (!oe.source_func.ends_with(")")) {
+ source_txt += "()";
+ }
}
TreeItem *cpp_source = error_tree->create_item(error);
- cpp_source->set_text(0, "<" + (source_is_project_file ? TTR("Source") : TTR("C++ Source")) + ">");
+ // TRANSLATORS: %s is the name of a language, e.g. C++.
+ cpp_source->set_text(0, "<" + vformat(TTR("%s Source"), source_language_name) + ">");
cpp_source->set_text(1, source_txt);
cpp_source->set_text_alignment(0, HORIZONTAL_ALIGNMENT_LEFT);
- tooltip += (source_is_project_file ? TTR("Source:") : TTR("C++ Source:")) + " " + source_txt + "\n";
+ tooltip += vformat(TTR("%s Source:"), source_language_name) + source_txt + "\n";
// Set metadata to highlight error line in scripts.
if (source_is_project_file) {
@@ -581,7 +597,7 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da
tooltip += TTR("Stack Trace:") + "\n";
}
- String frame_txt = infos[i].file.get_file() + ":" + itos(infos[i].line) + " @ " + infos[i].func + "()";
+ String frame_txt = _format_frame_text(&infos[i]);
tooltip += frame_txt + "\n";
stack_trace->set_text(1, frame_txt);
}
@@ -901,6 +917,14 @@ void ScriptEditorDebugger::_breakpoint_tree_clicked() {
}
}
+String ScriptEditorDebugger::_format_frame_text(const ScriptLanguage::StackInfo *info) {
+ String text = info->file.get_file() + ":" + itos(info->line) + " @ " + info->func;
+ if (!text.ends_with(")")) {
+ text += "()";
+ }
+ return text;
+}
+
void ScriptEditorDebugger::start(Ref<RemoteDebuggerPeer> p_peer) {
_clear_errors_list();
stop();
diff --git a/editor/debugger/script_editor_debugger.h b/editor/debugger/script_editor_debugger.h
index e31b3af3d9..a0c420522a 100644
--- a/editor/debugger/script_editor_debugger.h
+++ b/editor/debugger/script_editor_debugger.h
@@ -210,6 +210,8 @@ private:
void _breakpoint_tree_clicked();
+ String _format_frame_text(const ScriptLanguage::StackInfo *info);
+
protected:
void _notification(int p_what);
static void _bind_methods();
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 c7ea7dc7cf..0d5c820a3c 100644
--- a/editor/editor_node.cpp
+++ b/editor/editor_node.cpp
@@ -3089,7 +3089,7 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
}
String EditorNode::adjust_scene_name_casing(const String &root_name) {
- switch (GLOBAL_GET("editor/scene/scene_naming").operator int()) {
+ switch (GLOBAL_GET("editor/naming/scene_name_casing").operator int()) {
case SCENE_NAME_CASING_AUTO:
// Use casing of the root node.
break;
@@ -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;
@@ -6429,7 +6430,7 @@ void EditorNode::_feature_profile_changed() {
}
void EditorNode::_bind_methods() {
- GLOBAL_DEF(PropertyInfo(Variant::INT, "editor/scene/scene_naming", PROPERTY_HINT_ENUM, "Auto,PascalCase,snake_case"), SCENE_NAME_CASING_SNAKE_CASE);
+ GLOBAL_DEF(PropertyInfo(Variant::INT, "editor/naming/scene_name_casing", PROPERTY_HINT_ENUM, "Auto,PascalCase,snake_case"), SCENE_NAME_CASING_SNAKE_CASE);
ClassDB::bind_method("edit_current", &EditorNode::edit_current);
ClassDB::bind_method("edit_node", &EditorNode::edit_node);
@@ -7261,6 +7262,7 @@ EditorNode::EditorNode() {
project_title->set_text_overrun_behavior(TextServer::OVERRUN_TRIM_ELLIPSIS);
project_title->set_vertical_alignment(VERTICAL_ALIGNMENT_CENTER);
project_title->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ project_title->set_mouse_filter(Control::MOUSE_FILTER_PASS);
left_spacer->add_child(project_title);
}
diff --git a/editor/editor_run.cpp b/editor/editor_run.cpp
index 4bcd91376a..d3cceee1a3 100644
--- a/editor/editor_run.cpp
+++ b/editor/editor_run.cpp
@@ -272,7 +272,9 @@ Error EditorRun::run(const String &p_scene, const String &p_write_movie) {
OS::ProcessID pid = 0;
Error err = OS::get_singleton()->create_instance(args, &pid);
ERR_FAIL_COND_V(err, err);
- pids.push_back(pid);
+ if (pid != 0) {
+ pids.push_back(pid);
+ }
}
status = STATUS_PLAY;
diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp
index 4879790b74..21e15bc996 100644
--- a/editor/editor_settings.cpp
+++ b/editor/editor_settings.cpp
@@ -474,10 +474,10 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
/* Filesystem */
// External Programs
- EDITOR_SETTING(Variant::STRING, PROPERTY_HINT_GLOBAL_DIR, "filesystem/external_programs/raster_image_editor", "", "")
- EDITOR_SETTING(Variant::STRING, PROPERTY_HINT_GLOBAL_DIR, "filesystem/external_programs/vector_image_editor", "", "")
- EDITOR_SETTING(Variant::STRING, PROPERTY_HINT_GLOBAL_DIR, "filesystem/external_programs/audio_editor", "", "")
- EDITOR_SETTING(Variant::STRING, PROPERTY_HINT_GLOBAL_DIR, "filesystem/external_programs/3d_model_editor", "", "")
+ EDITOR_SETTING(Variant::STRING, PROPERTY_HINT_GLOBAL_FILE, "filesystem/external_programs/raster_image_editor", "", "")
+ EDITOR_SETTING(Variant::STRING, PROPERTY_HINT_GLOBAL_FILE, "filesystem/external_programs/vector_image_editor", "", "")
+ EDITOR_SETTING(Variant::STRING, PROPERTY_HINT_GLOBAL_FILE, "filesystem/external_programs/audio_editor", "", "")
+ EDITOR_SETTING(Variant::STRING, PROPERTY_HINT_GLOBAL_FILE, "filesystem/external_programs/3d_model_editor", "", "")
// Directories
EDITOR_SETTING(Variant::STRING, PROPERTY_HINT_GLOBAL_DIR, "filesystem/directories/autoscan_project_path", "", "")
diff --git a/editor/editor_themes.cpp b/editor/editor_themes.cpp
index 745acca04b..5cae3ef3fd 100644
--- a/editor/editor_themes.cpp
+++ b/editor/editor_themes.cpp
@@ -198,7 +198,7 @@ static Ref<StyleBoxTexture> make_stylebox(Ref<Texture2D> p_texture, float p_left
Ref<StyleBoxTexture> style(memnew(StyleBoxTexture));
style->set_texture(p_texture);
style->set_texture_margin_individual(p_left * EDSCALE, p_top * EDSCALE, p_right * EDSCALE, p_bottom * EDSCALE);
- style->set_content_margin_individual(p_margin_left * EDSCALE, p_margin_top * EDSCALE, p_margin_right * EDSCALE, p_margin_bottom * EDSCALE);
+ style->set_content_margin_individual((p_left + p_margin_left) * EDSCALE, (p_top + p_margin_top) * EDSCALE, (p_right + p_margin_right) * EDSCALE, (p_bottom + p_margin_bottom) * EDSCALE);
style->set_draw_center(p_draw_center);
return style;
}
@@ -1492,11 +1492,11 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
// HScrollBar
Ref<Texture2D> empty_icon = memnew(ImageTexture);
- theme->set_stylebox("scroll", "HScrollBar", make_stylebox(theme->get_icon(SNAME("GuiScrollBg"), SNAME("EditorIcons")), 5, 5, 5, 5, 0, 0, 0, 0));
- theme->set_stylebox("scroll_focus", "HScrollBar", make_stylebox(theme->get_icon(SNAME("GuiScrollBg"), SNAME("EditorIcons")), 5, 5, 5, 5, 0, 0, 0, 0));
- theme->set_stylebox("grabber", "HScrollBar", make_stylebox(theme->get_icon(SNAME("GuiScrollGrabber"), SNAME("EditorIcons")), 6, 6, 6, 6, 2, 2, 2, 2));
- theme->set_stylebox("grabber_highlight", "HScrollBar", make_stylebox(theme->get_icon(SNAME("GuiScrollGrabberHl"), SNAME("EditorIcons")), 5, 5, 5, 5, 2, 2, 2, 2));
- theme->set_stylebox("grabber_pressed", "HScrollBar", make_stylebox(theme->get_icon(SNAME("GuiScrollGrabberPressed"), SNAME("EditorIcons")), 6, 6, 6, 6, 2, 2, 2, 2));
+ theme->set_stylebox("scroll", "HScrollBar", make_stylebox(theme->get_icon(SNAME("GuiScrollBg"), SNAME("EditorIcons")), 5, 5, 5, 5, 1, 1, 1, 1));
+ theme->set_stylebox("scroll_focus", "HScrollBar", make_stylebox(theme->get_icon(SNAME("GuiScrollBg"), SNAME("EditorIcons")), 5, 5, 5, 5, 1, 1, 1, 1));
+ theme->set_stylebox("grabber", "HScrollBar", make_stylebox(theme->get_icon(SNAME("GuiScrollGrabber"), SNAME("EditorIcons")), 6, 6, 6, 6, 1, 1, 1, 1));
+ theme->set_stylebox("grabber_highlight", "HScrollBar", make_stylebox(theme->get_icon(SNAME("GuiScrollGrabberHl"), SNAME("EditorIcons")), 5, 5, 5, 5, 1, 1, 1, 1));
+ theme->set_stylebox("grabber_pressed", "HScrollBar", make_stylebox(theme->get_icon(SNAME("GuiScrollGrabberPressed"), SNAME("EditorIcons")), 6, 6, 6, 6, 1, 1, 1, 1));
theme->set_icon("increment", "HScrollBar", empty_icon);
theme->set_icon("increment_highlight", "HScrollBar", empty_icon);
@@ -1506,11 +1506,11 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
theme->set_icon("decrement_pressed", "HScrollBar", empty_icon);
// VScrollBar
- theme->set_stylebox("scroll", "VScrollBar", make_stylebox(theme->get_icon(SNAME("GuiScrollBg"), SNAME("EditorIcons")), 5, 5, 5, 5, 0, 0, 0, 0));
- theme->set_stylebox("scroll_focus", "VScrollBar", make_stylebox(theme->get_icon(SNAME("GuiScrollBg"), SNAME("EditorIcons")), 5, 5, 5, 5, 0, 0, 0, 0));
- theme->set_stylebox("grabber", "VScrollBar", make_stylebox(theme->get_icon(SNAME("GuiScrollGrabber"), SNAME("EditorIcons")), 6, 6, 6, 6, 2, 2, 2, 2));
- theme->set_stylebox("grabber_highlight", "VScrollBar", make_stylebox(theme->get_icon(SNAME("GuiScrollGrabberHl"), SNAME("EditorIcons")), 5, 5, 5, 5, 2, 2, 2, 2));
- theme->set_stylebox("grabber_pressed", "VScrollBar", make_stylebox(theme->get_icon(SNAME("GuiScrollGrabberPressed"), SNAME("EditorIcons")), 6, 6, 6, 6, 2, 2, 2, 2));
+ theme->set_stylebox("scroll", "VScrollBar", make_stylebox(theme->get_icon(SNAME("GuiScrollBg"), SNAME("EditorIcons")), 5, 5, 5, 5, 1, 1, 1, 1));
+ theme->set_stylebox("scroll_focus", "VScrollBar", make_stylebox(theme->get_icon(SNAME("GuiScrollBg"), SNAME("EditorIcons")), 5, 5, 5, 5, 1, 1, 1, 1));
+ theme->set_stylebox("grabber", "VScrollBar", make_stylebox(theme->get_icon(SNAME("GuiScrollGrabber"), SNAME("EditorIcons")), 6, 6, 6, 6, 1, 1, 1, 1));
+ theme->set_stylebox("grabber_highlight", "VScrollBar", make_stylebox(theme->get_icon(SNAME("GuiScrollGrabberHl"), SNAME("EditorIcons")), 5, 5, 5, 5, 1, 1, 1, 1));
+ theme->set_stylebox("grabber_pressed", "VScrollBar", make_stylebox(theme->get_icon(SNAME("GuiScrollGrabberPressed"), SNAME("EditorIcons")), 6, 6, 6, 6, 1, 1, 1, 1));
theme->set_icon("increment", "VScrollBar", empty_icon);
theme->set_icon("increment_highlight", "VScrollBar", empty_icon);
diff --git a/editor/editor_title_bar.cpp b/editor/editor_title_bar.cpp
index 0271bbd64a..ae5cdfd72b 100644
--- a/editor/editor_title_bar.cpp
+++ b/editor/editor_title_bar.cpp
@@ -30,7 +30,7 @@
#include "editor/editor_title_bar.h"
-void EditorTitleBar::input(const Ref<InputEvent> &p_event) {
+void EditorTitleBar::gui_input(const Ref<InputEvent> &p_event) {
if (!can_move) {
return;
}
diff --git a/editor/editor_title_bar.h b/editor/editor_title_bar.h
index 6cac163830..4055476b82 100644
--- a/editor/editor_title_bar.h
+++ b/editor/editor_title_bar.h
@@ -42,7 +42,7 @@ class EditorTitleBar : public HBoxContainer {
bool can_move = false;
protected:
- virtual void input(const Ref<InputEvent> &p_event) override;
+ virtual void gui_input(const Ref<InputEvent> &p_event) override;
static void _bind_methods(){};
public:
diff --git a/editor/editor_zoom_widget.cpp b/editor/editor_zoom_widget.cpp
index 5a334bdaa6..3998b33a53 100644
--- a/editor/editor_zoom_widget.cpp
+++ b/editor/editor_zoom_widget.cpp
@@ -41,12 +41,12 @@ void EditorZoomWidget::_update_zoom_label() {
// lower the editor scale to increase the available real estate,
// even if their display doesn't have a particularly low DPI.
if (zoom >= 10) {
- // Don't show a decimal when the zoom level is higher than 1000 %.
- zoom_text = TS->format_number(rtos(Math::round((zoom / MAX(1, EDSCALE)) * 100))) + " " + TS->percent_sign();
+ zoom_text = TS->format_number(rtos(Math::round((zoom / MAX(1, EDSCALE)) * 100)));
} else {
- zoom_text = TS->format_number(rtos(Math::snapped((zoom / MAX(1, EDSCALE)) * 100, 0.1))) + " " + TS->percent_sign();
+ // 2 decimal places if the zoom is below 10%, 1 decimal place if it's below 1000%.
+ zoom_text = TS->format_number(rtos(Math::snapped((zoom / MAX(1, EDSCALE)) * 100, (zoom >= 0.1) ? 0.1 : 0.01)));
}
-
+ zoom_text += " " + TS->percent_sign();
zoom_reset->set_text(zoom_text);
}
@@ -134,7 +134,7 @@ void EditorZoomWidget::set_zoom_by_increments(int p_increment_count, bool p_inte
float new_zoom_index = closest_zoom_index + p_increment_count;
float new_zoom = Math::pow(2.f, new_zoom_index / 12.f);
- // Restore Editor scale transformation
+ // Restore Editor scale transformation.
new_zoom *= MAX(1, EDSCALE);
set_zoom(new_zoom);
@@ -179,8 +179,12 @@ EditorZoomWidget::EditorZoomWidget() {
zoom_reset = memnew(Button);
zoom_reset->set_flat(true);
+ zoom_reset->add_theme_style_override("normal", memnew(StyleBoxEmpty));
+ zoom_reset->add_theme_style_override("hover", memnew(StyleBoxEmpty));
+ zoom_reset->add_theme_style_override("focus", memnew(StyleBoxEmpty));
+ zoom_reset->add_theme_style_override("pressed", memnew(StyleBoxEmpty));
add_child(zoom_reset);
- zoom_reset->add_theme_constant_override("outline_size", 1);
+ zoom_reset->add_theme_constant_override("outline_size", Math::ceil(2 * EDSCALE));
zoom_reset->add_theme_color_override("font_outline_color", Color(0, 0, 0));
zoom_reset->add_theme_color_override("font_color", Color(1, 1, 1));
zoom_reset->connect("pressed", callable_mp(this, &EditorZoomWidget::_button_zoom_reset));
@@ -189,7 +193,7 @@ EditorZoomWidget::EditorZoomWidget() {
zoom_reset->set_focus_mode(FOCUS_NONE);
zoom_reset->set_text_alignment(HORIZONTAL_ALIGNMENT_CENTER);
// Prevent the button's size from changing when the text size changes
- zoom_reset->set_custom_minimum_size(Size2(75 * EDSCALE, 0));
+ zoom_reset->set_custom_minimum_size(Size2(56 * EDSCALE, 0));
zoom_plus = memnew(Button);
zoom_plus->set_flat(true);
@@ -201,5 +205,5 @@ EditorZoomWidget::EditorZoomWidget() {
_update_zoom_label();
- add_theme_constant_override("separation", Math::round(-8 * EDSCALE));
+ add_theme_constant_override("separation", 0);
}
diff --git a/editor/export/editor_export_platform.cpp b/editor/export/editor_export_platform.cpp
index 9f79eecfb7..b2a3085c36 100644
--- a/editor/export/editor_export_platform.cpp
+++ b/editor/export/editor_export_platform.cpp
@@ -1802,6 +1802,13 @@ Error EditorExportPlatform::ssh_run_on_remote(const String &p_host, const String
List<String> args;
args.push_back("-p");
args.push_back(p_port);
+ args.push_back("-q");
+ args.push_back("-o");
+ args.push_back("LogLevel=error");
+ args.push_back("-o");
+ args.push_back("BatchMode=yes");
+ args.push_back("-o");
+ args.push_back("StrictHostKeyChecking=no");
for (const String &E : p_ssh_args) {
args.push_back(E);
}
@@ -1852,6 +1859,13 @@ Error EditorExportPlatform::ssh_run_on_remote_no_wait(const String &p_host, cons
List<String> args;
args.push_back("-p");
args.push_back(p_port);
+ args.push_back("-q");
+ args.push_back("-o");
+ args.push_back("LogLevel=error");
+ args.push_back("-o");
+ args.push_back("BatchMode=yes");
+ args.push_back("-o");
+ args.push_back("StrictHostKeyChecking=no");
for (const String &E : p_ssh_args) {
args.push_back(E);
}
@@ -1882,6 +1896,13 @@ Error EditorExportPlatform::ssh_push_to_remote(const String &p_host, const Strin
List<String> args;
args.push_back("-P");
args.push_back(p_port);
+ args.push_back("-q");
+ args.push_back("-o");
+ args.push_back("LogLevel=error");
+ args.push_back("-o");
+ args.push_back("BatchMode=yes");
+ args.push_back("-o");
+ args.push_back("StrictHostKeyChecking=no");
for (const String &E : p_scp_args) {
args.push_back(E);
}
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/import/resource_importer_texture.cpp b/editor/import/resource_importer_texture.cpp
index 2f543ea02d..b9b6391432 100644
--- a/editor/import/resource_importer_texture.cpp
+++ b/editor/import/resource_importer_texture.cpp
@@ -322,15 +322,11 @@ void ResourceImporterTexture::save_to_ctex_format(Ref<FileAccess> f, const Ref<I
f->store_16(p_image->get_height());
f->store_32(p_image->get_mipmap_count());
f->store_32(p_image->get_format());
-
- for (int i = 0; i < p_image->get_mipmap_count() + 1; i++) {
- Vector<uint8_t> data = Image::basis_universal_packer(p_image->get_image_from_mipmap(i), p_channels);
- int data_len = data.size();
- f->store_32(data_len);
-
- const uint8_t *r = data.ptr();
- f->store_buffer(r, data_len);
- }
+ Vector<uint8_t> data = Image::basis_universal_packer(p_image, p_channels);
+ int data_len = data.size();
+ f->store_32(data_len);
+ const uint8_t *r = data.ptr();
+ f->store_buffer(r, data_len);
} break;
}
}
@@ -387,7 +383,7 @@ void ResourceImporterTexture::_save_ctex(const Ref<Image> &p_image, const String
Ref<Image> image = p_image->duplicate();
- if (((p_compress_mode == COMPRESS_BASIS_UNIVERSAL) || (p_compress_mode == COMPRESS_VRAM_COMPRESSED && p_force_po2_for_compressed)) && p_mipmaps) {
+ if (p_force_po2_for_compressed && p_mipmaps && ((p_compress_mode == COMPRESS_BASIS_UNIVERSAL) || (p_compress_mode == COMPRESS_VRAM_COMPRESSED))) {
image->resize_to_po2();
}
diff --git a/editor/plugins/animation_player_editor_plugin.cpp b/editor/plugins/animation_player_editor_plugin.cpp
index 06241d07cf..30e06bfcf4 100644
--- a/editor/plugins/animation_player_editor_plugin.cpp
+++ b/editor/plugins/animation_player_editor_plugin.cpp
@@ -245,7 +245,7 @@ void AnimationPlayerEditor::_play_bw_pressed() {
player->stop(); //so it won't blend with itself
}
ERR_FAIL_COND_EDMSG(!_validate_tracks(player->get_animation(current)), "Animation tracks may have any invalid key, abort playing.");
- player->play(current, -1, -1, true);
+ player->play_backwards(current);
}
//unstop
@@ -262,7 +262,7 @@ void AnimationPlayerEditor::_play_bw_from_pressed() {
}
ERR_FAIL_COND_EDMSG(!_validate_tracks(player->get_animation(current)), "Animation tracks may have any invalid key, abort playing.");
player->seek(time);
- player->play(current, -1, -1, true);
+ player->play_backwards(current);
}
//unstop
@@ -452,7 +452,9 @@ float AnimationPlayerEditor::_get_editor_step() const {
}
void AnimationPlayerEditor::_animation_name_edited() {
- player->stop();
+ if (player->is_playing()) {
+ player->stop();
+ }
String new_name = name->get_text();
if (!AnimationLibrary::is_valid_animation_name(new_name)) {
@@ -1675,7 +1677,7 @@ AnimationPlayerEditor::AnimationPlayerEditor(AnimationPlayerEditorPlugin *p_plug
stop = memnew(Button);
stop->set_flat(true);
hb->add_child(stop);
- stop->set_tooltip_text(TTR("Stop animation playback. (S)"));
+ stop->set_tooltip_text(TTR("Pause/stop animation playback. (S)"));
play = memnew(Button);
play->set_flat(true);
diff --git a/editor/plugins/animation_state_machine_editor.cpp b/editor/plugins/animation_state_machine_editor.cpp
index c0972d201e..9632670658 100644
--- a/editor/plugins/animation_state_machine_editor.cpp
+++ b/editor/plugins/animation_state_machine_editor.cpp
@@ -1127,7 +1127,7 @@ void AnimationNodeStateMachineEditor::_add_transition(const bool p_nested_action
connecting = false;
}
-void AnimationNodeStateMachineEditor::_connection_draw(const Vector2 &p_from, const Vector2 &p_to, AnimationNodeStateMachineTransition::SwitchMode p_mode, bool p_enabled, bool p_selected, bool p_travel, bool p_auto_advance, bool p_multi_transitions) {
+void AnimationNodeStateMachineEditor::_connection_draw(const Vector2 &p_from, const Vector2 &p_to, AnimationNodeStateMachineTransition::SwitchMode p_mode, bool p_enabled, bool p_selected, bool p_travel, float p_fade_ratio, bool p_auto_advance, bool p_multi_transitions) {
Color linecolor = get_theme_color(SNAME("font_color"), SNAME("Label"));
Color icon_color(1, 1, 1);
Color accent = get_theme_color(SNAME("accent_color"), SNAME("Editor"));
@@ -1138,7 +1138,7 @@ void AnimationNodeStateMachineEditor::_connection_draw(const Vector2 &p_from, co
accent.a *= 0.6;
}
- const Ref<Texture2D> icons[6] = {
+ const Ref<Texture2D> icons[] = {
get_theme_icon(SNAME("TransitionImmediateBig"), SNAME("EditorIcons")),
get_theme_icon(SNAME("TransitionSyncBig"), SNAME("EditorIcons")),
get_theme_icon(SNAME("TransitionEndBig"), SNAME("EditorIcons")),
@@ -1146,6 +1146,7 @@ void AnimationNodeStateMachineEditor::_connection_draw(const Vector2 &p_from, co
get_theme_icon(SNAME("TransitionSyncAutoBig"), SNAME("EditorIcons")),
get_theme_icon(SNAME("TransitionEndAutoBig"), SNAME("EditorIcons"))
};
+ const int ICON_COUNT = sizeof(icons) / sizeof(*icons);
if (p_selected) {
state_machine_draw->draw_line(p_from, p_to, accent, 6);
@@ -1153,12 +1154,18 @@ void AnimationNodeStateMachineEditor::_connection_draw(const Vector2 &p_from, co
if (p_travel) {
linecolor = accent;
- linecolor.set_hsv(1.0, linecolor.get_s(), linecolor.get_v());
}
state_machine_draw->draw_line(p_from, p_to, linecolor, 2);
- Ref<Texture2D> icon = icons[p_mode + (p_auto_advance ? 3 : 0)];
+ if (p_fade_ratio > 0.0) {
+ Color fade_linecolor = accent;
+ fade_linecolor.set_hsv(1.0, fade_linecolor.get_s(), fade_linecolor.get_v());
+ state_machine_draw->draw_line(p_from, p_from.lerp(p_to, p_fade_ratio), fade_linecolor, 2);
+ }
+ int icon_index = p_mode + (p_auto_advance ? ICON_COUNT / 2 : 0);
+ ERR_FAIL_COND(icon_index >= ICON_COUNT);
+ Ref<Texture2D> icon = icons[icon_index];
Transform2D xf;
xf.columns[0] = (p_to - p_from).normalized();
@@ -1327,7 +1334,7 @@ void AnimationNodeStateMachineEditor::_state_machine_draw() {
}
}
- _connection_draw(from, to, AnimationNodeStateMachineTransition::SwitchMode(switch_mode->get_selected()), true, false, false, false, false);
+ _connection_draw(from, to, AnimationNodeStateMachineTransition::SwitchMode(switch_mode->get_selected()), true, false, false, 0.0, false, false);
}
Ref<Texture2D> tr_reference_icon = get_theme_icon(SNAME("TransitionImmediateBig"), SNAME("EditorIcons"));
@@ -1357,6 +1364,7 @@ void AnimationNodeStateMachineEditor::_state_machine_draw() {
tl.mode = tr->get_switch_mode();
tl.width = tr_bidi_offset;
tl.travel = false;
+ tl.fade_ratio = 0.0;
tl.hidden = false;
if (state_machine->has_local_transition(local_to, local_from)) { //offset if same exists
@@ -1378,6 +1386,7 @@ void AnimationNodeStateMachineEditor::_state_machine_draw() {
if (blend_from == local_from && current == local_to) {
tl.travel = true;
+ tl.fade_ratio = MIN(1.0, fading_pos / fading_time);
}
if (travel_path.size()) {
@@ -1418,7 +1427,7 @@ void AnimationNodeStateMachineEditor::_state_machine_draw() {
for (int i = 0; i < transition_lines.size(); i++) {
TransitionLine tl = transition_lines[i];
if (!tl.hidden) {
- _connection_draw(tl.from, tl.to, tl.mode, !tl.disabled, tl.selected, tl.travel, tl.auto_advance, !tl.multi_transitions.is_empty());
+ _connection_draw(tl.from, tl.to, tl.mode, !tl.disabled, tl.selected, tl.travel, tl.fade_ratio, tl.auto_advance, !tl.multi_transitions.is_empty());
}
}
@@ -1508,25 +1517,24 @@ void AnimationNodeStateMachineEditor::_state_machine_draw() {
state_machine_play_pos->queue_redraw();
}
-void AnimationNodeStateMachineEditor::_state_machine_pos_draw() {
+void AnimationNodeStateMachineEditor::_state_machine_pos_draw_individual(String p_name, float p_ratio) {
AnimationTree *tree = AnimationTreeEditor::get_singleton()->get_animation_tree();
if (!tree) {
return;
}
Ref<AnimationNodeStateMachinePlayback> playback = tree->get(AnimationTreeEditor::get_singleton()->get_base_path() + "playback");
-
if (!playback.is_valid() || !playback->is_playing()) {
return;
}
- if (playback->get_current_node() == state_machine->start_node || playback->get_current_node() == state_machine->end_node) {
+ if (p_name == state_machine->start_node || p_name == state_machine->end_node || p_name.is_empty()) {
return;
}
int idx = -1;
for (int i = 0; i < node_rects.size(); i++) {
- if (node_rects[i].node_name == playback->get_current_node()) {
+ if (node_rects[i].node_name == p_name) {
idx = i;
break;
}
@@ -1550,10 +1558,7 @@ void AnimationNodeStateMachineEditor::_state_machine_pos_draw() {
}
to.y = from.y;
- float len = MAX(0.0001, current_length);
-
- float pos = CLAMP(play_pos, 0, len);
- float c = pos / len;
+ float c = p_ratio;
Color fg = get_theme_color(SNAME("font_color"), SNAME("Label"));
Color bg = fg;
bg.a *= 0.3;
@@ -1565,6 +1570,32 @@ void AnimationNodeStateMachineEditor::_state_machine_pos_draw() {
state_machine_play_pos->draw_line(from, to, fg, 2);
}
+void AnimationNodeStateMachineEditor::_state_machine_pos_draw_all() {
+ AnimationTree *tree = AnimationTreeEditor::get_singleton()->get_animation_tree();
+ if (!tree) {
+ return;
+ }
+
+ Ref<AnimationNodeStateMachinePlayback> playback = tree->get(AnimationTreeEditor::get_singleton()->get_base_path() + "playback");
+ if (!playback.is_valid() || !playback->is_playing()) {
+ return;
+ }
+
+ {
+ float len = MAX(0.0001, current_length);
+ float pos = CLAMP(current_play_pos, 0, len);
+ float c = pos / len;
+ _state_machine_pos_draw_individual(playback->get_current_node(), c);
+ }
+
+ {
+ float len = MAX(0.0001, fade_from_length);
+ float pos = CLAMP(fade_from_current_play_pos, 0, len);
+ float c = pos / len;
+ _state_machine_pos_draw_individual(playback->get_fading_from_node(), c);
+ }
+}
+
void AnimationNodeStateMachineEditor::_update_graph() {
if (updating) {
return;
@@ -1687,17 +1718,28 @@ void AnimationNodeStateMachineEditor::_notification(int p_what) {
Vector<StringName> tp;
bool is_playing = false;
StringName current_node;
- StringName blend_from_node;
- play_pos = 0;
+ StringName fading_from_node;
+
+ current_play_pos = 0;
current_length = 0;
+ fade_from_current_play_pos = 0;
+ fade_from_length = 0;
+
+ fading_time = 0;
+ fading_pos = 0;
+
if (playback.is_valid()) {
tp = playback->get_travel_path();
is_playing = playback->is_playing();
current_node = playback->get_current_node();
- blend_from_node = playback->get_fading_from_node();
- play_pos = playback->get_current_play_pos();
+ fading_from_node = playback->get_fading_from_node();
+ current_play_pos = playback->get_current_play_pos();
current_length = playback->get_current_length();
+ fade_from_current_play_pos = playback->get_fade_from_play_pos();
+ fade_from_length = playback->get_fade_from_length();
+ fading_time = playback->get_fading_time();
+ fading_pos = playback->get_fading_pos();
}
{
@@ -1714,12 +1756,19 @@ void AnimationNodeStateMachineEditor::_notification(int p_what) {
}
//redraw if travel state changed
- if (!same_travel_path || last_active != is_playing || last_current_node != current_node || last_blend_from_node != blend_from_node) {
+ if (!same_travel_path ||
+ last_active != is_playing ||
+ last_current_node != current_node ||
+ last_fading_from_node != fading_from_node ||
+ last_fading_time != fading_time ||
+ last_fading_pos != fading_pos) {
state_machine_draw->queue_redraw();
last_travel_path = tp;
last_current_node = current_node;
last_active = is_playing;
- last_blend_from_node = blend_from_node;
+ last_fading_from_node = fading_from_node;
+ last_fading_time = fading_time;
+ last_fading_pos = fading_pos;
state_machine_play_pos->queue_redraw();
}
@@ -1737,14 +1786,15 @@ void AnimationNodeStateMachineEditor::_notification(int p_what) {
// when current_node is a state machine, use playback of current_node to set play_pos
if (current_node_playback.is_valid()) {
- play_pos = current_node_playback->get_current_play_pos();
+ current_play_pos = current_node_playback->get_current_play_pos();
current_length = current_node_playback->get_current_length();
}
}
}
- if (last_play_pos != play_pos) {
- last_play_pos = play_pos;
+ if (last_play_pos != current_play_pos || fade_from_last_play_pos != fade_from_current_play_pos) {
+ last_play_pos = current_play_pos;
+ fade_from_last_play_pos = fade_from_current_play_pos;
state_machine_play_pos->queue_redraw();
}
} break;
@@ -2048,7 +2098,7 @@ AnimationNodeStateMachineEditor::AnimationNodeStateMachineEditor() {
state_machine_draw->add_child(state_machine_play_pos);
state_machine_play_pos->set_mouse_filter(MOUSE_FILTER_PASS); //pass all to parent
state_machine_play_pos->set_anchors_and_offsets_preset(PRESET_FULL_RECT);
- state_machine_play_pos->connect("draw", callable_mp(this, &AnimationNodeStateMachineEditor::_state_machine_pos_draw));
+ state_machine_play_pos->connect("draw", callable_mp(this, &AnimationNodeStateMachineEditor::_state_machine_pos_draw_all));
v_scroll = memnew(VScrollBar);
state_machine_draw->add_child(v_scroll);
diff --git a/editor/plugins/animation_state_machine_editor.h b/editor/plugins/animation_state_machine_editor.h
index 46fe13ccc1..66338c820e 100644
--- a/editor/plugins/animation_state_machine_editor.h
+++ b/editor/plugins/animation_state_machine_editor.h
@@ -85,9 +85,12 @@ class AnimationNodeStateMachineEditor : public AnimationTreeNodeEditorPlugin {
static AnimationNodeStateMachineEditor *singleton;
void _state_machine_gui_input(const Ref<InputEvent> &p_event);
- void _connection_draw(const Vector2 &p_from, const Vector2 &p_to, AnimationNodeStateMachineTransition::SwitchMode p_mode, bool p_enabled, bool p_selected, bool p_travel, bool p_auto_advance, bool p_multi_transitions);
+ void _connection_draw(const Vector2 &p_from, const Vector2 &p_to, AnimationNodeStateMachineTransition::SwitchMode p_mode, bool p_enabled, bool p_selected, bool p_travel, float p_fade_ratio, bool p_auto_advance, bool p_multi_transitions);
+
void _state_machine_draw();
- void _state_machine_pos_draw();
+
+ void _state_machine_pos_draw_individual(String p_name, float p_ratio);
+ void _state_machine_pos_draw_all();
void _update_graph();
@@ -150,6 +153,7 @@ class AnimationNodeStateMachineEditor : public AnimationTreeNodeEditorPlugin {
float width = 0;
bool selected;
bool travel;
+ float fade_ratio;
bool hidden;
int transition_index;
Vector<TransitionLine> multi_transitions;
@@ -204,13 +208,23 @@ class AnimationNodeStateMachineEditor : public AnimationTreeNodeEditorPlugin {
void _delete_tree_draw();
bool last_active = false;
- StringName last_blend_from_node;
+ StringName last_fading_from_node;
StringName last_current_node;
Vector<StringName> last_travel_path;
+
+ float fade_from_last_play_pos = 0.0f;
+ float fade_from_current_play_pos = 0.0f;
+ float fade_from_length = 0.0f;
+
float last_play_pos = 0.0f;
- float play_pos = 0.0f;
+ float current_play_pos = 0.0f;
float current_length = 0.0f;
+ float last_fading_time = 0.0f;
+ float last_fading_pos = 0.0f;
+ float fading_time = 0.0f;
+ float fading_pos = 0.0f;
+
float error_time = 0.0f;
String error_text;
diff --git a/editor/plugins/animation_tree_editor_plugin.cpp b/editor/plugins/animation_tree_editor_plugin.cpp
index 720deb0b92..ab46e8f04a 100644
--- a/editor/plugins/animation_tree_editor_plugin.cpp
+++ b/editor/plugins/animation_tree_editor_plugin.cpp
@@ -65,13 +65,14 @@ void AnimationTreeEditor::edit(AnimationTree *p_tree) {
tree = p_tree;
Vector<String> path;
- if (tree && tree->has_meta("_tree_edit_path")) {
- path = tree->get_meta("_tree_edit_path");
- } else {
- current_root = ObjectID();
+ if (tree) {
+ if (tree->has_meta("_tree_edit_path")) {
+ path = tree->get_meta("_tree_edit_path");
+ } else {
+ current_root = ObjectID();
+ }
+ edit_path(path);
}
-
- edit_path(path);
}
void AnimationTreeEditor::_node_removed(Node *p_node) {
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/navigation_link_2d_editor_plugin.cpp b/editor/plugins/navigation_link_2d_editor_plugin.cpp
index 21a1d839f0..dff92ced27 100644
--- a/editor/plugins/navigation_link_2d_editor_plugin.cpp
+++ b/editor/plugins/navigation_link_2d_editor_plugin.cpp
@@ -65,20 +65,20 @@ bool NavigationLink2DEditor::forward_canvas_gui_input(const Ref<InputEvent> &p_e
Ref<InputEventMouseButton> mb = p_event;
if (mb.is_valid() && mb->get_button_index() == MouseButton::LEFT) {
if (mb->is_pressed()) {
- // Start location
- if (xform.xform(node->get_start_location()).distance_to(mb->get_position()) < grab_threshold) {
+ // Start position
+ if (xform.xform(node->get_start_position()).distance_to(mb->get_position()) < grab_threshold) {
start_grabbed = true;
- original_start_location = node->get_start_location();
+ original_start_position = node->get_start_position();
return true;
} else {
start_grabbed = false;
}
- // End location
- if (xform.xform(node->get_end_location()).distance_to(mb->get_position()) < grab_threshold) {
+ // End position
+ if (xform.xform(node->get_end_position()).distance_to(mb->get_position()) < grab_threshold) {
end_grabbed = true;
- original_end_location = node->get_end_location();
+ original_end_position = node->get_end_position();
return true;
} else {
@@ -87,10 +87,10 @@ bool NavigationLink2DEditor::forward_canvas_gui_input(const Ref<InputEvent> &p_e
} else {
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
if (start_grabbed) {
- undo_redo->create_action(TTR("Set start_location"));
- undo_redo->add_do_method(node, "set_start_location", node->get_start_location());
+ undo_redo->create_action(TTR("Set start_position"));
+ undo_redo->add_do_method(node, "set_start_position", node->get_start_position());
undo_redo->add_do_method(canvas_item_editor, "update_viewport");
- undo_redo->add_undo_method(node, "set_start_location", original_start_location);
+ undo_redo->add_undo_method(node, "set_start_position", original_start_position);
undo_redo->add_undo_method(canvas_item_editor, "update_viewport");
undo_redo->commit_action();
@@ -100,10 +100,10 @@ bool NavigationLink2DEditor::forward_canvas_gui_input(const Ref<InputEvent> &p_e
}
if (end_grabbed) {
- undo_redo->create_action(TTR("Set end_location"));
- undo_redo->add_do_method(node, "set_end_location", node->get_end_location());
+ undo_redo->create_action(TTR("Set end_position"));
+ undo_redo->add_do_method(node, "set_end_position", node->get_end_position());
undo_redo->add_do_method(canvas_item_editor, "update_viewport");
- undo_redo->add_undo_method(node, "set_end_location", original_end_location);
+ undo_redo->add_undo_method(node, "set_end_position", original_end_position);
undo_redo->add_undo_method(canvas_item_editor, "update_viewport");
undo_redo->commit_action();
@@ -120,14 +120,14 @@ bool NavigationLink2DEditor::forward_canvas_gui_input(const Ref<InputEvent> &p_e
point = node->get_global_transform().affine_inverse().xform(point);
if (start_grabbed) {
- node->set_start_location(point);
+ node->set_start_position(point);
canvas_item_editor->update_viewport();
return true;
}
if (end_grabbed) {
- node->set_end_location(point);
+ node->set_end_position(point);
canvas_item_editor->update_viewport();
return true;
@@ -143,13 +143,13 @@ void NavigationLink2DEditor::forward_canvas_draw_over_viewport(Control *p_overla
}
Transform2D gt = canvas_item_editor->get_canvas_transform() * node->get_global_transform();
- Vector2 global_start_location = gt.xform(node->get_start_location());
- Vector2 global_end_location = gt.xform(node->get_end_location());
+ Vector2 global_start_position = gt.xform(node->get_start_position());
+ Vector2 global_end_position = gt.xform(node->get_end_position());
// Only drawing the handles here, since the debug rendering will fill in the rest.
const Ref<Texture2D> handle = get_theme_icon(SNAME("EditorHandle"), SNAME("EditorIcons"));
- p_overlay->draw_texture(handle, global_start_location - handle->get_size() / 2);
- p_overlay->draw_texture(handle, global_end_location - handle->get_size() / 2);
+ p_overlay->draw_texture(handle, global_start_position - handle->get_size() / 2);
+ p_overlay->draw_texture(handle, global_end_position - handle->get_size() / 2);
}
void NavigationLink2DEditor::edit(NavigationLink2D *p_node) {
diff --git a/editor/plugins/navigation_link_2d_editor_plugin.h b/editor/plugins/navigation_link_2d_editor_plugin.h
index 76444403d0..ea731ca2cd 100644
--- a/editor/plugins/navigation_link_2d_editor_plugin.h
+++ b/editor/plugins/navigation_link_2d_editor_plugin.h
@@ -43,10 +43,10 @@ class NavigationLink2DEditor : public Control {
NavigationLink2D *node = nullptr;
bool start_grabbed = false;
- Vector2 original_start_location;
+ Vector2 original_start_position;
bool end_grabbed = false;
- Vector2 original_end_location;
+ Vector2 original_end_position;
protected:
void _notification(int p_what);
diff --git a/editor/plugins/node_3d_editor_gizmos.cpp b/editor/plugins/node_3d_editor_gizmos.cpp
index bb71c27bff..e11dc1c81d 100644
--- a/editor/plugins/node_3d_editor_gizmos.cpp
+++ b/editor/plugins/node_3d_editor_gizmos.cpp
@@ -5057,8 +5057,8 @@ void NavigationLink3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
Vector3 up_vector = NavigationServer3D::get_singleton()->map_get_up(nav_map);
Vector3::Axis up_axis = up_vector.max_axis_index();
- Vector3 start_location = link->get_start_location();
- Vector3 end_location = link->get_end_location();
+ Vector3 start_position = link->get_start_position();
+ Vector3 end_position = link->get_end_position();
Ref<Material> link_material = get_material("navigation_link_material", p_gizmo);
Ref<Material> link_material_disabled = get_material("navigation_link_material_disabled", p_gizmo);
@@ -5068,10 +5068,10 @@ void NavigationLink3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
// Draw line between the points.
Vector<Vector3> lines;
- lines.append(start_location);
- lines.append(end_location);
+ lines.append(start_position);
+ lines.append(end_position);
- // Draw start location search radius
+ // Draw start position search radius
for (int i = 0; i < 30; i++) {
// Create a circle
const float ra = Math::deg_to_rad((float)(i * 12));
@@ -5082,21 +5082,21 @@ void NavigationLink3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
// Draw axis-aligned circle
switch (up_axis) {
case Vector3::AXIS_X:
- lines.append(start_location + Vector3(0, a.x, a.y));
- lines.append(start_location + Vector3(0, b.x, b.y));
+ lines.append(start_position + Vector3(0, a.x, a.y));
+ lines.append(start_position + Vector3(0, b.x, b.y));
break;
case Vector3::AXIS_Y:
- lines.append(start_location + Vector3(a.x, 0, a.y));
- lines.append(start_location + Vector3(b.x, 0, b.y));
+ lines.append(start_position + Vector3(a.x, 0, a.y));
+ lines.append(start_position + Vector3(b.x, 0, b.y));
break;
case Vector3::AXIS_Z:
- lines.append(start_location + Vector3(a.x, a.y, 0));
- lines.append(start_location + Vector3(b.x, b.y, 0));
+ lines.append(start_position + Vector3(a.x, a.y, 0));
+ lines.append(start_position + Vector3(b.x, b.y, 0));
break;
}
}
- // Draw end location search radius
+ // Draw end position search radius
for (int i = 0; i < 30; i++) {
// Create a circle
const float ra = Math::deg_to_rad((float)(i * 12));
@@ -5107,16 +5107,16 @@ void NavigationLink3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
// Draw axis-aligned circle
switch (up_axis) {
case Vector3::AXIS_X:
- lines.append(end_location + Vector3(0, a.x, a.y));
- lines.append(end_location + Vector3(0, b.x, b.y));
+ lines.append(end_position + Vector3(0, a.x, a.y));
+ lines.append(end_position + Vector3(0, b.x, b.y));
break;
case Vector3::AXIS_Y:
- lines.append(end_location + Vector3(a.x, 0, a.y));
- lines.append(end_location + Vector3(b.x, 0, b.y));
+ lines.append(end_position + Vector3(a.x, 0, a.y));
+ lines.append(end_position + Vector3(b.x, 0, b.y));
break;
case Vector3::AXIS_Z:
- lines.append(end_location + Vector3(a.x, a.y, 0));
- lines.append(end_location + Vector3(b.x, b.y, 0));
+ lines.append(end_position + Vector3(a.x, a.y, 0));
+ lines.append(end_position + Vector3(b.x, b.y, 0));
break;
}
}
@@ -5125,8 +5125,8 @@ void NavigationLink3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
p_gizmo->add_collision_segments(lines);
Vector<Vector3> handles;
- handles.append(start_location);
- handles.append(end_location);
+ handles.append(start_position);
+ handles.append(end_position);
p_gizmo->add_handles(handles, handles_material);
}
@@ -5136,7 +5136,7 @@ String NavigationLink3DGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_g
Variant NavigationLink3DGizmoPlugin::get_handle_value(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) const {
NavigationLink3D *link = Object::cast_to<NavigationLink3D>(p_gizmo->get_node_3d());
- return p_id == 0 ? link->get_start_location() : link->get_end_location();
+ return p_id == 0 ? link->get_start_position() : link->get_end_position();
}
void NavigationLink3DGizmoPlugin::set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary, Camera3D *p_camera, const Point2 &p_point) {
@@ -5151,8 +5151,8 @@ void NavigationLink3DGizmoPlugin::set_handle(const EditorNode3DGizmo *p_gizmo, i
Vector3 ray_from = p_camera->project_ray_origin(p_point);
Vector3 ray_dir = p_camera->project_ray_normal(p_point);
- Vector3 location = p_id == 0 ? link->get_start_location() : link->get_end_location();
- Plane move_plane = Plane(cam_dir, gt.xform(location));
+ Vector3 position = p_id == 0 ? link->get_start_position() : link->get_end_position();
+ Plane move_plane = Plane(cam_dir, gt.xform(position));
Vector3 intersection;
if (!move_plane.intersects_ray(ray_from, ray_dir, &intersection)) {
@@ -5164,11 +5164,11 @@ void NavigationLink3DGizmoPlugin::set_handle(const EditorNode3DGizmo *p_gizmo, i
intersection.snap(Vector3(snap, snap, snap));
}
- location = gi.xform(intersection);
+ position = gi.xform(intersection);
if (p_id == 0) {
- link->set_start_location(location);
+ link->set_start_position(position);
} else if (p_id == 1) {
- link->set_end_location(location);
+ link->set_end_position(position);
}
}
@@ -5177,22 +5177,22 @@ void NavigationLink3DGizmoPlugin::commit_handle(const EditorNode3DGizmo *p_gizmo
if (p_cancel) {
if (p_id == 0) {
- link->set_start_location(p_restore);
+ link->set_start_position(p_restore);
} else {
- link->set_end_location(p_restore);
+ link->set_end_position(p_restore);
}
return;
}
EditorUndoRedoManager *ur = EditorUndoRedoManager::get_singleton();
if (p_id == 0) {
- ur->create_action(TTR("Change Start Location"));
- ur->add_do_method(link, "set_start_location", link->get_start_location());
- ur->add_undo_method(link, "set_start_location", p_restore);
+ ur->create_action(TTR("Change Start Position"));
+ ur->add_do_method(link, "set_start_position", link->get_start_position());
+ ur->add_undo_method(link, "set_start_position", p_restore);
} else {
- ur->create_action(TTR("Change End Location"));
- ur->add_do_method(link, "set_end_location", link->get_end_location());
- ur->add_undo_method(link, "set_end_location", p_restore);
+ ur->create_action(TTR("Change End Position"));
+ ur->add_do_method(link, "set_end_position", link->get_end_position());
+ ur->add_undo_method(link, "set_end_position", p_restore);
}
ur->commit_action();
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/script_text_editor.cpp b/editor/plugins/script_text_editor.cpp
index b719a2ce30..6b4e7184d9 100644
--- a/editor/plugins/script_text_editor.cpp
+++ b/editor/plugins/script_text_editor.cpp
@@ -252,12 +252,14 @@ void ScriptTextEditor::_warning_clicked(Variant p_line) {
} else if (p_line.get_type() == Variant::DICTIONARY) {
Dictionary meta = p_line.operator Dictionary();
const int line = meta["line"].operator int64_t() - 1;
+ const String code = meta["code"].operator String();
+ const String quote_style = EDITOR_GET("text_editor/completion/use_single_quotes") ? "'" : "\"";
CodeEdit *text_editor = code_editor->get_text_editor();
String prev_line = line > 0 ? text_editor->get_line(line - 1) : "";
if (prev_line.contains("@warning_ignore")) {
const int closing_bracket_idx = prev_line.find(")");
- const String text_to_insert = ", " + meta["code"].operator String();
+ const String text_to_insert = ", " + code.quote(quote_style);
prev_line = prev_line.insert(closing_bracket_idx, text_to_insert);
text_editor->set_line(line - 1, prev_line);
} else {
@@ -268,7 +270,7 @@ void ScriptTextEditor::_warning_clicked(Variant p_line) {
} else {
annotation_indent = String(" ").repeat(text_editor->get_indent_size() * indent);
}
- text_editor->insert_line_at(line, annotation_indent + "@warning_ignore(" + meta["code"].operator String() + ")");
+ text_editor->insert_line_at(line, annotation_indent + "@warning_ignore(" + code.quote(quote_style) + ")");
}
_validate_script();
diff --git a/editor/plugins/sprite_frames_editor_plugin.cpp b/editor/plugins/sprite_frames_editor_plugin.cpp
index 74c9286325..a7b32ce0c3 100644
--- a/editor/plugins/sprite_frames_editor_plugin.cpp
+++ b/editor/plugins/sprite_frames_editor_plugin.cpp
@@ -40,7 +40,6 @@
#include "editor/editor_settings.h"
#include "editor/editor_undo_redo_manager.h"
#include "editor/scene_tree_dock.h"
-#include "scene/3d/sprite_3d.h"
#include "scene/gui/center_container.h"
#include "scene/gui/margin_container.h"
#include "scene/gui/panel_container.h"
@@ -252,8 +251,7 @@ void SpriteFramesEditor::_sheet_add_frames() {
const Size2i separation = _get_separation();
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
- undo_redo->create_action(TTR("Add Frame"));
-
+ undo_redo->create_action(TTR("Add Frame"), UndoRedo::MERGE_DISABLE, EditorNode::get_singleton()->get_edited_scene());
int fc = frames->get_frame_count(edited_anim);
for (const int &E : frames_selected) {
@@ -265,8 +263,8 @@ void SpriteFramesEditor::_sheet_add_frames() {
at->set_atlas(split_sheet_preview->get_texture());
at->set_region(Rect2(offset + frame_coords * (frame_size + separation), frame_size));
- undo_redo->add_do_method(frames, "add_frame", edited_anim, at, 1.0, -1);
- undo_redo->add_undo_method(frames, "remove_frame", edited_anim, fc);
+ undo_redo->add_do_method(frames.ptr(), "add_frame", edited_anim, at, 1.0, -1);
+ undo_redo->add_undo_method(frames.ptr(), "remove_frame", edited_anim, fc);
}
undo_redo->add_do_method(this, "_update_library");
@@ -415,8 +413,23 @@ void SpriteFramesEditor::_prepare_sprite_sheet(const String &p_file) {
void SpriteFramesEditor::_notification(int p_what) {
switch (p_what) {
- case NOTIFICATION_ENTER_TREE:
+ case NOTIFICATION_ENTER_TREE: {
+ get_tree()->connect("node_removed", callable_mp(this, &SpriteFramesEditor::_node_removed));
+
+ [[fallthrough]];
+ }
case NOTIFICATION_THEME_CHANGED: {
+ autoplay_icon = get_theme_icon(SNAME("AutoPlay"), SNAME("EditorIcons"));
+ stop_icon = get_theme_icon(SNAME("Stop"), SNAME("EditorIcons"));
+ pause_icon = get_theme_icon(SNAME("Pause"), SNAME("EditorIcons"));
+ _update_stop_icon();
+
+ autoplay->set_icon(get_theme_icon(SNAME("AutoPlay"), SNAME("EditorIcons")));
+ play->set_icon(get_theme_icon(SNAME("PlayStart"), SNAME("EditorIcons")));
+ play_from->set_icon(get_theme_icon(SNAME("Play"), SNAME("EditorIcons")));
+ play_bw->set_icon(get_theme_icon(SNAME("PlayStartBackwards"), SNAME("EditorIcons")));
+ play_bw_from->set_icon(get_theme_icon(SNAME("PlayBackwards"), SNAME("EditorIcons")));
+
load->set_icon(get_theme_icon(SNAME("Load"), SNAME("EditorIcons")));
load_sheet->set_icon(get_theme_icon(SNAME("SpriteSheet"), SNAME("EditorIcons")));
copy->set_icon(get_theme_icon(SNAME("ActionCopy"), SNAME("EditorIcons")));
@@ -441,6 +454,10 @@ void SpriteFramesEditor::_notification(int p_what) {
case NOTIFICATION_READY: {
add_theme_constant_override("autohide", 1); // Fixes the dragger always showing up.
} break;
+
+ case NOTIFICATION_EXIT_TREE: {
+ get_tree()->disconnect("node_removed", callable_mp(this, &SpriteFramesEditor::_node_removed));
+ } break;
}
}
@@ -471,14 +488,14 @@ void SpriteFramesEditor::_file_load_request(const Vector<String> &p_path, int p_
}
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
- undo_redo->create_action(TTR("Add Frame"));
+ undo_redo->create_action(TTR("Add Frame"), UndoRedo::MERGE_DISABLE, EditorNode::get_singleton()->get_edited_scene());
int fc = frames->get_frame_count(edited_anim);
int count = 0;
for (const Ref<Texture2D> &E : resources) {
- undo_redo->add_do_method(frames, "add_frame", edited_anim, E, 1.0, p_at_pos == -1 ? -1 : p_at_pos + count);
- undo_redo->add_undo_method(frames, "remove_frame", edited_anim, p_at_pos == -1 ? fc : p_at_pos);
+ undo_redo->add_do_method(frames.ptr(), "add_frame", edited_anim, E, 1.0, p_at_pos == -1 ? -1 : p_at_pos + count);
+ undo_redo->add_undo_method(frames.ptr(), "remove_frame", edited_anim, p_at_pos == -1 ? fc : p_at_pos);
count++;
}
undo_redo->add_do_method(this, "_update_library");
@@ -542,9 +559,9 @@ void SpriteFramesEditor::_paste_pressed() {
}
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
- undo_redo->create_action(TTR("Paste Frame"));
- undo_redo->add_do_method(frames, "add_frame", edited_anim, texture, duration);
- undo_redo->add_undo_method(frames, "remove_frame", edited_anim, frames->get_frame_count(edited_anim));
+ undo_redo->create_action(TTR("Paste Frame"), UndoRedo::MERGE_DISABLE, EditorNode::get_singleton()->get_edited_scene());
+ undo_redo->add_do_method(frames.ptr(), "add_frame", edited_anim, texture, duration);
+ undo_redo->add_undo_method(frames.ptr(), "remove_frame", edited_anim, frames->get_frame_count(edited_anim));
undo_redo->add_do_method(this, "_update_library");
undo_redo->add_undo_method(this, "_update_library");
undo_redo->commit_action();
@@ -585,9 +602,9 @@ void SpriteFramesEditor::_empty_pressed() {
Ref<Texture2D> texture;
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
- undo_redo->create_action(TTR("Add Empty"));
- undo_redo->add_do_method(frames, "add_frame", edited_anim, texture, 1.0, from);
- undo_redo->add_undo_method(frames, "remove_frame", edited_anim, from);
+ undo_redo->create_action(TTR("Add Empty"), UndoRedo::MERGE_DISABLE, EditorNode::get_singleton()->get_edited_scene());
+ undo_redo->add_do_method(frames.ptr(), "add_frame", edited_anim, texture, 1.0, from);
+ undo_redo->add_undo_method(frames.ptr(), "remove_frame", edited_anim, from);
undo_redo->add_do_method(this, "_update_library");
undo_redo->add_undo_method(this, "_update_library");
undo_redo->commit_action();
@@ -609,9 +626,9 @@ void SpriteFramesEditor::_empty2_pressed() {
Ref<Texture2D> texture;
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
- undo_redo->create_action(TTR("Add Empty"));
- undo_redo->add_do_method(frames, "add_frame", edited_anim, texture, 1.0, from + 1);
- undo_redo->add_undo_method(frames, "remove_frame", edited_anim, from + 1);
+ undo_redo->create_action(TTR("Add Empty"), UndoRedo::MERGE_DISABLE, EditorNode::get_singleton()->get_edited_scene());
+ undo_redo->add_do_method(frames.ptr(), "add_frame", edited_anim, texture, 1.0, from + 1);
+ undo_redo->add_undo_method(frames.ptr(), "remove_frame", edited_anim, from + 1);
undo_redo->add_do_method(this, "_update_library");
undo_redo->add_undo_method(this, "_update_library");
undo_redo->commit_action();
@@ -633,11 +650,11 @@ void SpriteFramesEditor::_up_pressed() {
sel -= 1;
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
- undo_redo->create_action(TTR("Move Frame"));
- undo_redo->add_do_method(frames, "set_frame", edited_anim, to_move, frames->get_frame_texture(edited_anim, to_move - 1), frames->get_frame_duration(edited_anim, to_move - 1));
- undo_redo->add_do_method(frames, "set_frame", edited_anim, to_move - 1, frames->get_frame_texture(edited_anim, to_move), frames->get_frame_duration(edited_anim, to_move));
- undo_redo->add_undo_method(frames, "set_frame", edited_anim, to_move, frames->get_frame_texture(edited_anim, to_move), frames->get_frame_duration(edited_anim, to_move));
- undo_redo->add_undo_method(frames, "set_frame", edited_anim, to_move - 1, frames->get_frame_texture(edited_anim, to_move - 1), frames->get_frame_duration(edited_anim, to_move - 1));
+ undo_redo->create_action(TTR("Move Frame"), UndoRedo::MERGE_DISABLE, EditorNode::get_singleton()->get_edited_scene());
+ undo_redo->add_do_method(frames.ptr(), "set_frame", edited_anim, to_move, frames->get_frame_texture(edited_anim, to_move - 1), frames->get_frame_duration(edited_anim, to_move - 1));
+ undo_redo->add_do_method(frames.ptr(), "set_frame", edited_anim, to_move - 1, frames->get_frame_texture(edited_anim, to_move), frames->get_frame_duration(edited_anim, to_move));
+ undo_redo->add_undo_method(frames.ptr(), "set_frame", edited_anim, to_move, frames->get_frame_texture(edited_anim, to_move), frames->get_frame_duration(edited_anim, to_move));
+ undo_redo->add_undo_method(frames.ptr(), "set_frame", edited_anim, to_move - 1, frames->get_frame_texture(edited_anim, to_move - 1), frames->get_frame_duration(edited_anim, to_move - 1));
undo_redo->add_do_method(this, "_update_library");
undo_redo->add_undo_method(this, "_update_library");
undo_redo->commit_action();
@@ -659,11 +676,11 @@ void SpriteFramesEditor::_down_pressed() {
sel += 1;
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
- undo_redo->create_action(TTR("Move Frame"));
- undo_redo->add_do_method(frames, "set_frame", edited_anim, to_move, frames->get_frame_texture(edited_anim, to_move + 1), frames->get_frame_duration(edited_anim, to_move + 1));
- undo_redo->add_do_method(frames, "set_frame", edited_anim, to_move + 1, frames->get_frame_texture(edited_anim, to_move), frames->get_frame_duration(edited_anim, to_move));
- undo_redo->add_undo_method(frames, "set_frame", edited_anim, to_move, frames->get_frame_texture(edited_anim, to_move), frames->get_frame_duration(edited_anim, to_move));
- undo_redo->add_undo_method(frames, "set_frame", edited_anim, to_move + 1, frames->get_frame_texture(edited_anim, to_move + 1), frames->get_frame_duration(edited_anim, to_move + 1));
+ undo_redo->create_action(TTR("Move Frame"), UndoRedo::MERGE_DISABLE, EditorNode::get_singleton()->get_edited_scene());
+ undo_redo->add_do_method(frames.ptr(), "set_frame", edited_anim, to_move, frames->get_frame_texture(edited_anim, to_move + 1), frames->get_frame_duration(edited_anim, to_move + 1));
+ undo_redo->add_do_method(frames.ptr(), "set_frame", edited_anim, to_move + 1, frames->get_frame_texture(edited_anim, to_move), frames->get_frame_duration(edited_anim, to_move));
+ undo_redo->add_undo_method(frames.ptr(), "set_frame", edited_anim, to_move, frames->get_frame_texture(edited_anim, to_move), frames->get_frame_duration(edited_anim, to_move));
+ undo_redo->add_undo_method(frames.ptr(), "set_frame", edited_anim, to_move + 1, frames->get_frame_texture(edited_anim, to_move + 1), frames->get_frame_duration(edited_anim, to_move + 1));
undo_redo->add_do_method(this, "_update_library");
undo_redo->add_undo_method(this, "_update_library");
undo_redo->commit_action();
@@ -682,15 +699,15 @@ void SpriteFramesEditor::_delete_pressed() {
}
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
- undo_redo->create_action(TTR("Delete Resource"));
- undo_redo->add_do_method(frames, "remove_frame", edited_anim, to_delete);
- undo_redo->add_undo_method(frames, "add_frame", edited_anim, frames->get_frame_texture(edited_anim, to_delete), frames->get_frame_duration(edited_anim, to_delete), to_delete);
+ undo_redo->create_action(TTR("Delete Resource"), UndoRedo::MERGE_DISABLE, EditorNode::get_singleton()->get_edited_scene());
+ undo_redo->add_do_method(frames.ptr(), "remove_frame", edited_anim, to_delete);
+ undo_redo->add_undo_method(frames.ptr(), "add_frame", edited_anim, frames->get_frame_texture(edited_anim, to_delete), frames->get_frame_duration(edited_anim, to_delete), to_delete);
undo_redo->add_do_method(this, "_update_library");
undo_redo->add_undo_method(this, "_update_library");
undo_redo->commit_action();
}
-void SpriteFramesEditor::_animation_select() {
+void SpriteFramesEditor::_animation_selected() {
if (updating) {
return;
}
@@ -705,9 +722,42 @@ void SpriteFramesEditor::_animation_select() {
TreeItem *selected = animations->get_selected();
ERR_FAIL_COND(!selected);
edited_anim = selected->get_text(0);
+
+ if (animated_sprite) {
+ sprite_node_updating = true;
+ animated_sprite->call("set_animation", edited_anim);
+ sprite_node_updating = false;
+ }
+
_update_library(true);
}
+void SpriteFramesEditor::_sync_animation() {
+ if (!animated_sprite || sprite_node_updating) {
+ return;
+ }
+ _select_animation(animated_sprite->call("get_animation"), false);
+ _update_stop_icon();
+}
+
+void SpriteFramesEditor::_select_animation(const String &p_name, bool p_update_node) {
+ TreeItem *selected = nullptr;
+ selected = animations->get_item_with_text(p_name);
+ if (!selected) {
+ return;
+ };
+
+ edited_anim = selected->get_text(0);
+
+ if (animated_sprite) {
+ if (p_update_node) {
+ animated_sprite->call("set_animation", edited_anim);
+ }
+ }
+
+ _update_library();
+}
+
static void _find_anim_sprites(Node *p_node, List<Node *> *r_nodes, Ref<SpriteFrames> p_sfames) {
Node *edited = EditorNode::get_singleton()->get_edited_scene();
if (!edited) {
@@ -765,26 +815,48 @@ void SpriteFramesEditor::_animation_name_edited() {
name = new_name + " " + itos(counter);
}
- List<Node *> nodes;
- _find_anim_sprites(EditorNode::get_singleton()->get_edited_scene(), &nodes, Ref<SpriteFrames>(frames));
-
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
- undo_redo->create_action(TTR("Rename Animation"));
- undo_redo->add_do_method(frames, "rename_animation", edited_anim, name);
- undo_redo->add_undo_method(frames, "rename_animation", name, edited_anim);
-
- for (Node *E : nodes) {
- String current = E->call("get_animation");
- undo_redo->add_do_method(E, "set_animation", name);
- undo_redo->add_undo_method(E, "set_animation", edited_anim);
- }
-
+ undo_redo->create_action(TTR("Rename Animation"), UndoRedo::MERGE_DISABLE, EditorNode::get_singleton()->get_edited_scene());
+ _rename_node_animation(undo_redo, false, edited_anim, "", "");
+ undo_redo->add_do_method(frames.ptr(), "rename_animation", edited_anim, name);
+ undo_redo->add_undo_method(frames.ptr(), "rename_animation", name, edited_anim);
+ _rename_node_animation(undo_redo, false, edited_anim, name, name);
+ _rename_node_animation(undo_redo, true, edited_anim, edited_anim, edited_anim);
undo_redo->add_do_method(this, "_update_library");
undo_redo->add_undo_method(this, "_update_library");
+ undo_redo->commit_action();
- edited_anim = name;
+ _select_animation(name);
+ animations->grab_focus();
+}
- undo_redo->commit_action();
+void SpriteFramesEditor::_rename_node_animation(EditorUndoRedoManager *undo_redo, bool is_undo, const String &p_filter, const String &p_new_animation, const String &p_new_autoplay) {
+ List<Node *> nodes;
+ _find_anim_sprites(EditorNode::get_singleton()->get_edited_scene(), &nodes, Ref<SpriteFrames>(frames));
+
+ if (is_undo) {
+ for (Node *E : nodes) {
+ String current_name = E->call("get_animation");
+ if (current_name == p_filter) {
+ undo_redo->add_undo_method(E, "set_animation", p_new_animation);
+ }
+ String autoplay_name = E->call("get_autoplay");
+ if (autoplay_name == p_filter) {
+ undo_redo->add_undo_method(E, "set_autoplay", p_new_autoplay);
+ }
+ }
+ } else {
+ for (Node *E : nodes) {
+ String current_name = E->call("get_animation");
+ if (current_name == p_filter) {
+ undo_redo->add_do_method(E, "set_animation", p_new_animation);
+ }
+ String autoplay_name = E->call("get_autoplay");
+ if (autoplay_name == p_filter) {
+ undo_redo->add_do_method(E, "set_autoplay", p_new_autoplay);
+ }
+ }
+ }
}
void SpriteFramesEditor::_animation_add() {
@@ -795,25 +867,15 @@ void SpriteFramesEditor::_animation_add() {
name = vformat("new_animation_%d", counter);
}
- List<Node *> nodes;
- _find_anim_sprites(EditorNode::get_singleton()->get_edited_scene(), &nodes, Ref<SpriteFrames>(frames));
-
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
- undo_redo->create_action(TTR("Add Animation"));
- undo_redo->add_do_method(frames, "add_animation", name);
- undo_redo->add_undo_method(frames, "remove_animation", name);
+ undo_redo->create_action(TTR("Add Animation"), UndoRedo::MERGE_DISABLE, EditorNode::get_singleton()->get_edited_scene());
+ undo_redo->add_do_method(frames.ptr(), "add_animation", name);
+ undo_redo->add_undo_method(frames.ptr(), "remove_animation", name);
undo_redo->add_do_method(this, "_update_library");
undo_redo->add_undo_method(this, "_update_library");
-
- for (Node *E : nodes) {
- String current = E->call("get_animation");
- undo_redo->add_do_method(E, "set_animation", name);
- undo_redo->add_undo_method(E, "set_animation", current);
- }
-
- edited_anim = name;
-
undo_redo->commit_action();
+
+ _select_animation(name);
animations->grab_focus();
}
@@ -831,24 +893,39 @@ void SpriteFramesEditor::_animation_remove() {
}
void SpriteFramesEditor::_animation_remove_confirmed() {
+ StringName new_edited;
+ List<StringName> anim_names;
+ frames->get_animation_list(&anim_names);
+ anim_names.sort_custom<StringName::AlphCompare>();
+ if (anim_names.size() >= 2) {
+ if (edited_anim == anim_names[0]) {
+ new_edited = anim_names[1];
+ } else {
+ new_edited = anim_names[0];
+ }
+ } else {
+ new_edited = StringName();
+ }
+
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
- undo_redo->create_action(TTR("Remove Animation"));
- undo_redo->add_do_method(frames, "remove_animation", edited_anim);
- undo_redo->add_undo_method(frames, "add_animation", edited_anim);
- undo_redo->add_undo_method(frames, "set_animation_speed", edited_anim, frames->get_animation_speed(edited_anim));
- undo_redo->add_undo_method(frames, "set_animation_loop", edited_anim, frames->get_animation_loop(edited_anim));
+ undo_redo->create_action(TTR("Remove Animation"), UndoRedo::MERGE_DISABLE, EditorNode::get_singleton()->get_edited_scene());
+ _rename_node_animation(undo_redo, false, edited_anim, new_edited, "");
+ undo_redo->add_do_method(frames.ptr(), "remove_animation", edited_anim);
+ undo_redo->add_undo_method(frames.ptr(), "add_animation", edited_anim);
+ _rename_node_animation(undo_redo, true, edited_anim, edited_anim, edited_anim);
+ undo_redo->add_undo_method(frames.ptr(), "set_animation_speed", edited_anim, frames->get_animation_speed(edited_anim));
+ undo_redo->add_undo_method(frames.ptr(), "set_animation_loop", edited_anim, frames->get_animation_loop(edited_anim));
int fc = frames->get_frame_count(edited_anim);
for (int i = 0; i < fc; i++) {
Ref<Texture2D> texture = frames->get_frame_texture(edited_anim, i);
float duration = frames->get_frame_duration(edited_anim, i);
- undo_redo->add_undo_method(frames, "add_frame", edited_anim, texture, duration);
+ undo_redo->add_undo_method(frames.ptr(), "add_frame", edited_anim, texture, duration);
}
undo_redo->add_do_method(this, "_update_library");
undo_redo->add_undo_method(this, "_update_library");
-
- edited_anim = StringName();
-
undo_redo->commit_action();
+
+ _select_animation(new_edited);
}
void SpriteFramesEditor::_animation_search_text_changed(const String &p_text) {
@@ -861,9 +938,9 @@ void SpriteFramesEditor::_animation_loop_changed() {
}
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
- undo_redo->create_action(TTR("Change Animation Loop"));
- undo_redo->add_do_method(frames, "set_animation_loop", edited_anim, anim_loop->is_pressed());
- undo_redo->add_undo_method(frames, "set_animation_loop", edited_anim, frames->get_animation_loop(edited_anim));
+ undo_redo->create_action(TTR("Change Animation Loop"), UndoRedo::MERGE_DISABLE, EditorNode::get_singleton()->get_edited_scene());
+ undo_redo->add_do_method(frames.ptr(), "set_animation_loop", edited_anim, anim_loop->is_pressed());
+ undo_redo->add_undo_method(frames.ptr(), "set_animation_loop", edited_anim, frames->get_animation_loop(edited_anim));
undo_redo->add_do_method(this, "_update_library", true);
undo_redo->add_undo_method(this, "_update_library", true);
undo_redo->commit_action();
@@ -875,9 +952,9 @@ void SpriteFramesEditor::_animation_speed_changed(double p_value) {
}
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
- undo_redo->create_action(TTR("Change Animation FPS"), UndoRedo::MERGE_ENDS);
- undo_redo->add_do_method(frames, "set_animation_speed", edited_anim, p_value);
- undo_redo->add_undo_method(frames, "set_animation_speed", edited_anim, frames->get_animation_speed(edited_anim));
+ undo_redo->create_action(TTR("Change Animation FPS"), UndoRedo::MERGE_ENDS, EditorNode::get_singleton()->get_edited_scene());
+ undo_redo->add_do_method(frames.ptr(), "set_animation_speed", edited_anim, p_value);
+ undo_redo->add_undo_method(frames.ptr(), "set_animation_speed", edited_anim, frames->get_animation_speed(edited_anim));
undo_redo->add_do_method(this, "_update_library", true);
undo_redo->add_undo_method(this, "_update_library", true);
undo_redo->commit_action();
@@ -927,9 +1004,9 @@ void SpriteFramesEditor::_frame_duration_changed(double p_value) {
float old_duration = frames->get_frame_duration(edited_anim, index);
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
- undo_redo->create_action(TTR("Set Frame Duration"));
- undo_redo->add_do_method(frames, "set_frame", edited_anim, index, texture, p_value);
- undo_redo->add_undo_method(frames, "set_frame", edited_anim, index, texture, old_duration);
+ undo_redo->create_action(TTR("Set Frame Duration"), UndoRedo::MERGE_DISABLE, EditorNode::get_singleton()->get_edited_scene());
+ undo_redo->add_do_method(frames.ptr(), "set_frame", edited_anim, index, texture, p_value);
+ undo_redo->add_undo_method(frames.ptr(), "set_frame", edited_anim, index, texture, old_duration);
undo_redo->add_do_method(this, "_update_library");
undo_redo->add_undo_method(this, "_update_library");
undo_redo->commit_action();
@@ -968,6 +1045,10 @@ void SpriteFramesEditor::_zoom_reset() {
}
void SpriteFramesEditor::_update_library(bool p_skip_selector) {
+ if (frames.is_null()) {
+ return;
+ }
+
updating = true;
frame_duration->set_value(1.0); // Default.
@@ -998,12 +1079,27 @@ void SpriteFramesEditor::_update_library(bool p_skip_selector) {
it->set_text(0, name);
it->set_editable(0, true);
+ if (animated_sprite) {
+ if (name == String(animated_sprite->call("get_autoplay"))) {
+ it->set_icon(0, autoplay_icon);
+ }
+ }
+
if (E == edited_anim) {
it->select(0);
}
}
}
+ if (animated_sprite) {
+ String autoplay_name = animated_sprite->call("get_autoplay");
+ if (autoplay_name.is_empty()) {
+ autoplay->set_pressed(false);
+ } else {
+ autoplay->set_pressed(String(edited_anim) == autoplay_name);
+ }
+ }
+
frame_list->clear();
if (!frames->has_animation(edited_anim)) {
@@ -1061,20 +1157,25 @@ void SpriteFramesEditor::_update_library(bool p_skip_selector) {
updating = false;
}
-void SpriteFramesEditor::edit(SpriteFrames *p_frames) {
- bool new_read_only_state = false;
- if (p_frames) {
- new_read_only_state = EditorNode::get_singleton()->is_resource_read_only(p_frames);
+void SpriteFramesEditor::_edit() {
+ if (!animated_sprite) {
+ return;
}
+ edit(animated_sprite->call("get_sprite_frames"));
+}
+
+void SpriteFramesEditor::edit(Ref<SpriteFrames> p_frames) {
+ _update_stop_icon();
- if (frames == p_frames && new_read_only_state == read_only) {
+ if (!p_frames.is_valid()) {
+ frames.unref();
return;
}
frames = p_frames;
- read_only = new_read_only_state;
+ read_only = EditorNode::get_singleton()->is_resource_read_only(p_frames);
- if (p_frames) {
+ if (p_frames.is_valid()) {
if (!p_frames->has_animation(edited_anim)) {
List<StringName> anim_names;
frames->get_animation_list(&anim_names);
@@ -1107,6 +1208,8 @@ void SpriteFramesEditor::edit(SpriteFrames *p_frames) {
move_up->set_disabled(read_only);
move_down->set_disabled(read_only);
delete_frame->set_disabled(read_only);
+
+ _fetch_sprite_node(); // Fetch node after set frames.
}
Variant SpriteFramesEditor::get_drag_data_fw(const Point2 &p_point, Control *p_from) {
@@ -1215,18 +1318,18 @@ void SpriteFramesEditor::drop_data_fw(const Point2 &p_point, const Variant &p_da
duration = frames->get_frame_duration(edited_anim, from_frame);
}
- undo_redo->create_action(TTR("Move Frame"));
- undo_redo->add_do_method(frames, "remove_frame", edited_anim, from_frame == -1 ? frames->get_frame_count(edited_anim) : from_frame);
- undo_redo->add_do_method(frames, "add_frame", edited_anim, texture, duration, at_pos == -1 ? -1 : at_pos);
- undo_redo->add_undo_method(frames, "remove_frame", edited_anim, at_pos == -1 ? frames->get_frame_count(edited_anim) - 1 : at_pos);
- undo_redo->add_undo_method(frames, "add_frame", edited_anim, texture, duration, from_frame);
+ undo_redo->create_action(TTR("Move Frame"), UndoRedo::MERGE_DISABLE, EditorNode::get_singleton()->get_edited_scene());
+ undo_redo->add_do_method(frames.ptr(), "remove_frame", edited_anim, from_frame == -1 ? frames->get_frame_count(edited_anim) : from_frame);
+ undo_redo->add_do_method(frames.ptr(), "add_frame", edited_anim, texture, duration, at_pos == -1 ? -1 : at_pos);
+ undo_redo->add_undo_method(frames.ptr(), "remove_frame", edited_anim, at_pos == -1 ? frames->get_frame_count(edited_anim) - 1 : at_pos);
+ undo_redo->add_undo_method(frames.ptr(), "add_frame", edited_anim, texture, duration, from_frame);
undo_redo->add_do_method(this, "_update_library");
undo_redo->add_undo_method(this, "_update_library");
undo_redo->commit_action();
} else {
- undo_redo->create_action(TTR("Add Frame"));
- undo_redo->add_do_method(frames, "add_frame", edited_anim, texture, 1.0, at_pos == -1 ? -1 : at_pos);
- undo_redo->add_undo_method(frames, "remove_frame", edited_anim, at_pos == -1 ? frames->get_frame_count(edited_anim) : at_pos);
+ undo_redo->create_action(TTR("Add Frame"), UndoRedo::MERGE_DISABLE, EditorNode::get_singleton()->get_edited_scene());
+ undo_redo->add_do_method(frames.ptr(), "add_frame", edited_anim, texture, 1.0, at_pos == -1 ? -1 : at_pos);
+ undo_redo->add_undo_method(frames.ptr(), "remove_frame", edited_anim, at_pos == -1 ? frames->get_frame_count(edited_anim) : at_pos);
undo_redo->add_do_method(this, "_update_library");
undo_redo->add_undo_method(this, "_update_library");
undo_redo->commit_action();
@@ -1245,10 +1348,156 @@ void SpriteFramesEditor::drop_data_fw(const Point2 &p_point, const Variant &p_da
}
}
+void SpriteFramesEditor::_update_stop_icon() {
+ bool is_playing = false;
+ if (animated_sprite) {
+ is_playing = animated_sprite->call("is_playing");
+ }
+ if (is_playing) {
+ stop->set_icon(pause_icon);
+ } else {
+ stop->set_icon(stop_icon);
+ }
+}
+
+void SpriteFramesEditor::_remove_sprite_node() {
+ if (!animated_sprite) {
+ return;
+ }
+ if (animated_sprite->is_connected("sprite_frames_changed", callable_mp(this, &SpriteFramesEditor::_edit))) {
+ animated_sprite->disconnect("sprite_frames_changed", callable_mp(this, &SpriteFramesEditor::_edit));
+ }
+ if (animated_sprite->is_connected("animation_changed", callable_mp(this, &SpriteFramesEditor::_sync_animation))) {
+ animated_sprite->disconnect("animation_changed", callable_mp(this, &SpriteFramesEditor::_sync_animation));
+ }
+ if (animated_sprite->is_connected("animation_finished", callable_mp(this, &SpriteFramesEditor::_update_stop_icon))) {
+ animated_sprite->disconnect("animation_finished", callable_mp(this, &SpriteFramesEditor::_update_stop_icon));
+ }
+ animated_sprite = nullptr;
+}
+
+void SpriteFramesEditor::_fetch_sprite_node() {
+ Node *selected = nullptr;
+ EditorSelection *editor_selection = EditorNode::get_singleton()->get_editor_selection();
+ if (editor_selection->get_selected_node_list().size() == 1) {
+ selected = editor_selection->get_selected_node_list()[0];
+ }
+
+ bool show_node_edit = false;
+ AnimatedSprite2D *as2d = Object::cast_to<AnimatedSprite2D>(selected);
+ AnimatedSprite3D *as3d = Object::cast_to<AnimatedSprite3D>(selected);
+ if (as2d || as3d) {
+ if (frames != selected->call("get_sprite_frames")) {
+ _remove_sprite_node();
+ } else {
+ animated_sprite = selected;
+ if (!animated_sprite->is_connected("sprite_frames_changed", callable_mp(this, &SpriteFramesEditor::_edit))) {
+ animated_sprite->connect("sprite_frames_changed", callable_mp(this, &SpriteFramesEditor::_edit));
+ }
+ if (!animated_sprite->is_connected("animation_changed", callable_mp(this, &SpriteFramesEditor::_sync_animation))) {
+ animated_sprite->connect("animation_changed", callable_mp(this, &SpriteFramesEditor::_sync_animation), CONNECT_DEFERRED);
+ }
+ if (!animated_sprite->is_connected("animation_finished", callable_mp(this, &SpriteFramesEditor::_update_stop_icon))) {
+ animated_sprite->connect("animation_finished", callable_mp(this, &SpriteFramesEditor::_update_stop_icon));
+ }
+ show_node_edit = true;
+ }
+ } else {
+ _remove_sprite_node();
+ }
+
+ if (show_node_edit) {
+ _sync_animation();
+ autoplay_container->show();
+ playback_container->show();
+ } else {
+ _update_library(); // To init autoplay icon.
+ autoplay_container->hide();
+ playback_container->hide();
+ }
+}
+
+void SpriteFramesEditor::_play_pressed() {
+ if (animated_sprite) {
+ animated_sprite->call("stop");
+ animated_sprite->call("play", animated_sprite->call("get_animation"));
+ }
+ _update_stop_icon();
+}
+
+void SpriteFramesEditor::_play_from_pressed() {
+ if (animated_sprite) {
+ animated_sprite->call("play", animated_sprite->call("get_animation"));
+ }
+ _update_stop_icon();
+}
+
+void SpriteFramesEditor::_play_bw_pressed() {
+ if (animated_sprite) {
+ animated_sprite->call("stop");
+ animated_sprite->call("play_backwards", animated_sprite->call("get_animation"));
+ }
+ _update_stop_icon();
+}
+
+void SpriteFramesEditor::_play_bw_from_pressed() {
+ if (animated_sprite) {
+ animated_sprite->call("play_backwards", animated_sprite->call("get_animation"));
+ }
+ _update_stop_icon();
+}
+
+void SpriteFramesEditor::_stop_pressed() {
+ if (animated_sprite) {
+ if (animated_sprite->call("is_playing")) {
+ animated_sprite->call("pause");
+ } else {
+ animated_sprite->call("stop");
+ }
+ }
+ _update_stop_icon();
+}
+
+void SpriteFramesEditor::_autoplay_pressed() {
+ if (updating) {
+ return;
+ }
+
+ if (animated_sprite) {
+ EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
+ undo_redo->create_action(TTR("Toggle Autoplay"), UndoRedo::MERGE_DISABLE, EditorNode::get_singleton()->get_edited_scene());
+ String current = animated_sprite->call("get_animation");
+ String current_auto = animated_sprite->call("get_autoplay");
+ if (current == current_auto) {
+ //unset
+ undo_redo->add_do_method(animated_sprite, "set_autoplay", "");
+ undo_redo->add_undo_method(animated_sprite, "set_autoplay", current_auto);
+ } else {
+ //set
+ undo_redo->add_do_method(animated_sprite, "set_autoplay", current);
+ undo_redo->add_undo_method(animated_sprite, "set_autoplay", current_auto);
+ }
+ undo_redo->add_do_method(this, "_update_library");
+ undo_redo->add_undo_method(this, "_update_library");
+ undo_redo->commit_action();
+ }
+
+ _update_library();
+}
+
void SpriteFramesEditor::_bind_methods() {
ClassDB::bind_method(D_METHOD("_update_library", "skipsel"), &SpriteFramesEditor::_update_library, DEFVAL(false));
}
+void SpriteFramesEditor::_node_removed(Node *p_node) {
+ if (animated_sprite) {
+ if (animated_sprite != p_node) {
+ return;
+ }
+ _remove_sprite_node();
+ }
+}
+
SpriteFramesEditor::SpriteFramesEditor() {
VBoxContainer *vbc_animlist = memnew(VBoxContainer);
add_child(vbc_animlist);
@@ -1272,8 +1521,16 @@ SpriteFramesEditor::SpriteFramesEditor() {
delete_anim->set_disabled(true);
delete_anim->connect("pressed", callable_mp(this, &SpriteFramesEditor::_animation_remove));
+ autoplay_container = memnew(HBoxContainer);
+ hbc_animlist->add_child(autoplay_container);
+ autoplay_container->add_child(memnew(VSeparator));
+ autoplay = memnew(Button);
+ autoplay->set_flat(true);
+ autoplay->set_tooltip_text(TTR("Autoplay on Load"));
+ autoplay_container->add_child(autoplay);
+
anim_search_box = memnew(LineEdit);
- hbc_animlist->add_child(anim_search_box);
+ sub_vb->add_child(anim_search_box);
anim_search_box->set_h_size_flags(SIZE_EXPAND_FILL);
anim_search_box->set_placeholder(TTR("Filter Animations"));
anim_search_box->set_clear_button_enabled(true);
@@ -1283,7 +1540,7 @@ SpriteFramesEditor::SpriteFramesEditor() {
sub_vb->add_child(animations);
animations->set_v_size_flags(SIZE_EXPAND_FILL);
animations->set_hide_root(true);
- animations->connect("cell_selected", callable_mp(this, &SpriteFramesEditor::_animation_select));
+ animations->connect("cell_selected", callable_mp(this, &SpriteFramesEditor::_animation_selected));
animations->connect("item_edited", callable_mp(this, &SpriteFramesEditor::_animation_name_edited));
animations->set_allow_reselect(true);
@@ -1319,6 +1576,44 @@ SpriteFramesEditor::SpriteFramesEditor() {
HBoxContainer *hbc = memnew(HBoxContainer);
sub_vb->add_child(hbc);
+ playback_container = memnew(HBoxContainer);
+ hbc->add_child(playback_container);
+
+ play_bw_from = memnew(Button);
+ play_bw_from->set_flat(true);
+ play_bw_from->set_tooltip_text(TTR("Play selected animation backwards from current pos. (A)"));
+ playback_container->add_child(play_bw_from);
+
+ play_bw = memnew(Button);
+ play_bw->set_flat(true);
+ play_bw->set_tooltip_text(TTR("Play selected animation backwards from end. (Shift+A)"));
+ playback_container->add_child(play_bw);
+
+ stop = memnew(Button);
+ stop->set_flat(true);
+ stop->set_tooltip_text(TTR("Pause/stop animation playback. (S)"));
+ playback_container->add_child(stop);
+
+ play = memnew(Button);
+ play->set_flat(true);
+ play->set_tooltip_text(TTR("Play selected animation from start. (Shift+D)"));
+ playback_container->add_child(play);
+
+ play_from = memnew(Button);
+ play_from->set_flat(true);
+ play_from->set_tooltip_text(TTR("Play selected animation from current pos. (D)"));
+ playback_container->add_child(play_from);
+
+ playback_container->add_child(memnew(VSeparator));
+
+ autoplay->connect("pressed", callable_mp(this, &SpriteFramesEditor::_autoplay_pressed));
+ autoplay->set_toggle_mode(true);
+ play->connect("pressed", callable_mp(this, &SpriteFramesEditor::_play_pressed));
+ play_from->connect("pressed", callable_mp(this, &SpriteFramesEditor::_play_from_pressed));
+ play_bw->connect("pressed", callable_mp(this, &SpriteFramesEditor::_play_bw_pressed));
+ play_bw_from->connect("pressed", callable_mp(this, &SpriteFramesEditor::_play_bw_from_pressed));
+ stop->connect("pressed", callable_mp(this, &SpriteFramesEditor::_stop_pressed));
+
load = memnew(Button);
load->set_flat(true);
hbc->add_child(load);
@@ -1369,9 +1664,10 @@ SpriteFramesEditor::SpriteFramesEditor() {
frame_duration = memnew(SpinBox);
frame_duration->set_prefix(String::utf8("×"));
- frame_duration->set_min(0);
+ frame_duration->set_min(SPRITE_FRAME_MINIMUM_DURATION); // Avoid zero div.
frame_duration->set_max(10);
frame_duration->set_step(0.01);
+ frame_duration->set_allow_lesser(false);
frame_duration->set_allow_greater(true);
hbc->add_child(frame_duration);
@@ -1616,16 +1912,16 @@ SpriteFramesEditor::SpriteFramesEditor() {
}
void SpriteFramesEditorPlugin::edit(Object *p_object) {
- SpriteFrames *s;
+ Ref<SpriteFrames> s;
AnimatedSprite2D *animated_sprite = Object::cast_to<AnimatedSprite2D>(p_object);
if (animated_sprite) {
- s = *animated_sprite->get_sprite_frames();
+ s = animated_sprite->get_sprite_frames();
} else {
AnimatedSprite3D *animated_sprite_3d = Object::cast_to<AnimatedSprite3D>(p_object);
if (animated_sprite_3d) {
- s = *animated_sprite_3d->get_sprite_frames();
+ s = animated_sprite_3d->get_sprite_frames();
} else {
- s = Object::cast_to<SpriteFrames>(p_object);
+ s = p_object;
}
}
diff --git a/editor/plugins/sprite_frames_editor_plugin.h b/editor/plugins/sprite_frames_editor_plugin.h
index a5e0e54fb8..19ecfb00ed 100644
--- a/editor/plugins/sprite_frames_editor_plugin.h
+++ b/editor/plugins/sprite_frames_editor_plugin.h
@@ -33,6 +33,7 @@
#include "editor/editor_plugin.h"
#include "scene/2d/animated_sprite_2d.h"
+#include "scene/3d/sprite_3d.h"
#include "scene/gui/button.h"
#include "scene/gui/check_button.h"
#include "scene/gui/dialogs.h"
@@ -57,6 +58,9 @@ public:
class SpriteFramesEditor : public HSplitContainer {
GDCLASS(SpriteFramesEditor, HSplitContainer);
+ Ref<SpriteFrames> frames;
+ Node *animated_sprite = nullptr;
+
enum {
PARAM_USE_CURRENT, // Used in callbacks to indicate `dominant_param` should be not updated.
PARAM_FRAME_COUNT, // Keep "Horizontal" & "Vertical" values.
@@ -66,6 +70,17 @@ class SpriteFramesEditor : public HSplitContainer {
bool read_only = false;
+ Ref<Texture2D> autoplay_icon;
+ Ref<Texture2D> stop_icon;
+ Ref<Texture2D> pause_icon;
+
+ HBoxContainer *playback_container = nullptr;
+ Button *stop = nullptr;
+ Button *play = nullptr;
+ Button *play_from = nullptr;
+ Button *play_bw = nullptr;
+ Button *play_bw_from = nullptr;
+
Button *load = nullptr;
Button *load_sheet = nullptr;
Button *delete_frame = nullptr;
@@ -85,6 +100,8 @@ class SpriteFramesEditor : public HSplitContainer {
Button *add_anim = nullptr;
Button *delete_anim = nullptr;
+ HBoxContainer *autoplay_container = nullptr;
+ Button *autoplay = nullptr;
LineEdit *anim_search_box = nullptr;
Tree *animations = nullptr;
@@ -95,8 +112,6 @@ class SpriteFramesEditor : public HSplitContainer {
AcceptDialog *dialog = nullptr;
- SpriteFrames *frames = nullptr;
-
StringName edited_anim;
ConfirmationDialog *delete_dialog = nullptr;
@@ -146,7 +161,15 @@ class SpriteFramesEditor : public HSplitContainer {
void _frame_duration_changed(double p_value);
void _update_library(bool p_skip_selector = false);
- void _animation_select();
+ void _update_stop_icon();
+ void _play_pressed();
+ void _play_from_pressed();
+ void _play_bw_pressed();
+ void _play_bw_from_pressed();
+ void _autoplay_pressed();
+ void _stop_pressed();
+
+ void _animation_selected();
void _animation_name_edited();
void _animation_add();
void _animation_remove();
@@ -183,12 +206,24 @@ class SpriteFramesEditor : public HSplitContainer {
void _sheet_zoom_reset();
void _sheet_select_clear_all_frames();
+ void _edit();
+ void _regist_scene_undo(EditorUndoRedoManager *undo_redo);
+ void _fetch_sprite_node();
+ void _remove_sprite_node();
+
+ bool sprite_node_updating = false;
+ void _sync_animation();
+
+ void _select_animation(const String &p_name, bool p_update_node = true);
+ void _rename_node_animation(EditorUndoRedoManager *undo_redo, bool is_undo, const String &p_filter, const String &p_new_animation, const String &p_new_autoplay);
+
protected:
void _notification(int p_what);
+ void _node_removed(Node *p_node);
static void _bind_methods();
public:
- void edit(SpriteFrames *p_frames);
+ void edit(Ref<SpriteFrames> p_frames);
SpriteFramesEditor();
};
diff --git a/editor/plugins/texture_region_editor_plugin.cpp b/editor/plugins/texture_region_editor_plugin.cpp
index d7559bc18e..c5aa60c816 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) {
@@ -748,6 +740,9 @@ void TextureRegionEditor::_update_rect() {
}
} else if (obj_styleBox.is_valid()) {
rect = obj_styleBox->get_region_rect();
+ if (rect == Rect2()) {
+ rect = Rect2(Vector2(), obj_styleBox->get_texture()->get_size());
+ }
}
}
@@ -1169,7 +1164,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..fd651dd507 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);
}
@@ -251,7 +247,7 @@ void TileAtlasView::_draw_base_tiles() {
for (int frame = 0; frame < tile_set_atlas_source->get_tile_animation_frames_count(atlas_coords); frame++) {
// Update the y to max value.
Rect2i base_frame_rect = tile_set_atlas_source->get_tile_texture_region(atlas_coords, frame);
- Vector2i offset_pos = base_frame_rect.get_center() + tile_set_atlas_source->get_tile_effective_texture_offset(atlas_coords, 0);
+ Vector2i offset_pos = base_frame_rect.get_center() + tile_set_atlas_source->get_tile_data(atlas_coords, 0)->get_texture_origin();
// Draw the tile.
TileMap::draw_tile(base_tiles_draw->get_canvas_item(), offset_pos, tile_set, source_id, atlas_coords, 0, frame);
@@ -326,18 +322,19 @@ void TileAtlasView::_draw_base_tiles_shape_grid() {
Vector2i tile_shape_size = tile_set->get_tile_size();
for (int i = 0; i < tile_set_atlas_source->get_tiles_count(); i++) {
Vector2i tile_id = tile_set_atlas_source->get_tile_id(i);
- Vector2 in_tile_base_offset = tile_set_atlas_source->get_tile_effective_texture_offset(tile_id, 0);
-
- for (int frame = 0; frame < tile_set_atlas_source->get_tile_animation_frames_count(tile_id); frame++) {
- Color color = grid_color;
- if (frame > 0) {
- color.a *= 0.3;
+ Vector2 in_tile_base_offset = tile_set_atlas_source->get_tile_data(tile_id, 0)->get_texture_origin();
+ if (tile_set_atlas_source->is_position_in_tile_texture_region(tile_id, 0, -tile_shape_size / 2) && tile_set_atlas_source->is_position_in_tile_texture_region(tile_id, 0, tile_shape_size / 2 - Vector2(1, 1))) {
+ for (int frame = 0; frame < tile_set_atlas_source->get_tile_animation_frames_count(tile_id); frame++) {
+ Color color = grid_color;
+ if (frame > 0) {
+ color.a *= 0.3;
+ }
+ Rect2i texture_region = tile_set_atlas_source->get_tile_texture_region(tile_id, frame);
+ Transform2D tile_xform;
+ tile_xform.set_origin(texture_region.get_center() + in_tile_base_offset);
+ tile_xform.set_scale(tile_shape_size);
+ tile_set->draw_tile_shape(base_tiles_shape_grid, tile_xform, color);
}
- Rect2i texture_region = tile_set_atlas_source->get_tile_texture_region(tile_id);
- Transform2D tile_xform;
- tile_xform.set_origin(texture_region.get_center() + in_tile_base_offset);
- tile_xform.set_scale(tile_shape_size);
- tile_set->draw_tile_shape(base_tiles_shape_grid, tile_xform, color);
}
}
}
@@ -376,10 +373,10 @@ void TileAtlasView::_draw_alternatives() {
// Update the y to max value.
Vector2i offset_pos;
if (transposed) {
- offset_pos = (current_pos + Vector2(texture_region_size.y, texture_region_size.x) / 2 + tile_set_atlas_source->get_tile_effective_texture_offset(atlas_coords, alternative_id));
+ offset_pos = (current_pos + Vector2(texture_region_size.y, texture_region_size.x) / 2 + tile_data->get_texture_origin());
y_increment = MAX(y_increment, texture_region_size.x);
} else {
- offset_pos = (current_pos + texture_region_size / 2 + tile_set_atlas_source->get_tile_effective_texture_offset(atlas_coords, alternative_id));
+ offset_pos = (current_pos + texture_region_size / 2 + tile_data->get_texture_origin());
y_increment = MAX(y_increment, texture_region_size.y);
}
@@ -583,7 +580,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/tile_data_editors.cpp b/editor/plugins/tiles/tile_data_editors.cpp
index 1a4223e9e6..3dd0c84ee7 100644
--- a/editor/plugins/tiles/tile_data_editors.cpp
+++ b/editor/plugins/tiles/tile_data_editors.cpp
@@ -1122,14 +1122,15 @@ void TileDataDefaultEditor::draw_over_tile(CanvasItem *p_canvas_item, Transform2
return;
}
+ Vector2 texture_origin = tile_data->get_texture_origin();
if (value.get_type() == Variant::BOOL) {
Ref<Texture2D> texture = (bool)value ? tile_bool_checked : tile_bool_unchecked;
int size = MIN(tile_set->get_tile_size().x, tile_set->get_tile_size().y) / 3;
- Rect2 rect = p_transform.xform(Rect2(Vector2(-size / 2, -size / 2), Vector2(size, size)));
+ Rect2 rect = p_transform.xform(Rect2(Vector2(-size / 2, -size / 2) - texture_origin, Vector2(size, size)));
p_canvas_item->draw_texture_rect(texture, rect);
} else if (value.get_type() == Variant::COLOR) {
int size = MIN(tile_set->get_tile_size().x, tile_set->get_tile_size().y) / 3;
- Rect2 rect = p_transform.xform(Rect2(Vector2(-size / 2, -size / 2), Vector2(size, size)));
+ Rect2 rect = p_transform.xform(Rect2(Vector2(-size / 2, -size / 2) - texture_origin, Vector2(size, size)));
p_canvas_item->draw_rect(rect, value);
} else {
Ref<Font> font = TileSetEditor::get_singleton()->get_theme_font(SNAME("bold"), SNAME("EditorFonts"));
@@ -1166,8 +1167,8 @@ void TileDataDefaultEditor::draw_over_tile(CanvasItem *p_canvas_item, Transform2
}
Vector2 string_size = font->get_string_size(text, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size);
- p_canvas_item->draw_string_outline(font, p_transform.get_origin() + Vector2i(-string_size.x / 2, string_size.y / 2), text, HORIZONTAL_ALIGNMENT_CENTER, string_size.x, font_size, 1, Color(0, 0, 0, 1));
- p_canvas_item->draw_string(font, p_transform.get_origin() + Vector2i(-string_size.x / 2, string_size.y / 2), text, HORIZONTAL_ALIGNMENT_CENTER, string_size.x, font_size, color);
+ p_canvas_item->draw_string_outline(font, p_transform.xform(-texture_origin) + Vector2i(-string_size.x / 2, string_size.y / 2), text, HORIZONTAL_ALIGNMENT_CENTER, string_size.x, font_size, 1, Color(0, 0, 0, 1));
+ p_canvas_item->draw_string(font, p_transform.xform(-texture_origin) + Vector2i(-string_size.x / 2, string_size.y / 2), text, HORIZONTAL_ALIGNMENT_CENTER, string_size.x, font_size, color);
}
}
@@ -1241,20 +1242,38 @@ TileDataDefaultEditor::~TileDataDefaultEditor() {
memdelete(dummy_object);
}
-void TileDataTextureOffsetEditor::draw_over_tile(CanvasItem *p_canvas_item, Transform2D p_transform, TileMapCell p_cell, bool p_selected) {
+void TileDataTextureOriginEditor::draw_over_tile(CanvasItem *p_canvas_item, Transform2D p_transform, TileMapCell p_cell, bool p_selected) {
TileData *tile_data = _get_tile_data(p_cell);
ERR_FAIL_COND(!tile_data);
Vector2i tile_set_tile_size = tile_set->get_tile_size();
- Color color = Color(1.0, 0.0, 0.0);
+ Color color = Color(1.0, 1.0, 1.0);
if (p_selected) {
Color grid_color = EDITOR_GET("editors/tiles_editor/grid_color");
Color selection_color = Color().from_hsv(Math::fposmod(grid_color.get_h() + 0.5, 1.0), grid_color.get_s(), grid_color.get_v(), 1.0);
color = selection_color;
}
- Transform2D tile_xform;
- tile_xform.set_scale(tile_set_tile_size);
- tile_set->draw_tile_shape(p_canvas_item, p_transform * tile_xform, color);
+
+ TileSetSource *source = *(tile_set->get_source(p_cell.source_id));
+ TileSetAtlasSource *atlas_source = Object::cast_to<TileSetAtlasSource>(source);
+ if (atlas_source->is_position_in_tile_texture_region(p_cell.get_atlas_coords(), p_cell.alternative_tile, -tile_set_tile_size / 2) && atlas_source->is_position_in_tile_texture_region(p_cell.get_atlas_coords(), p_cell.alternative_tile, tile_set_tile_size / 2 - Vector2(1, 1))) {
+ Transform2D tile_xform;
+ tile_xform.set_scale(tile_set_tile_size);
+ tile_set->draw_tile_shape(p_canvas_item, p_transform * tile_xform, color);
+ }
+
+ if (atlas_source->is_position_in_tile_texture_region(p_cell.get_atlas_coords(), p_cell.alternative_tile, Vector2())) {
+ Ref<Texture2D> position_icon = TileSetEditor::get_singleton()->get_theme_icon(SNAME("EditorPosition"), SNAME("EditorIcons"));
+ p_canvas_item->draw_texture(position_icon, p_transform.xform(Vector2()) - (position_icon->get_size() / 2), color);
+ } else {
+ Ref<Font> font = TileSetEditor::get_singleton()->get_theme_font(SNAME("bold"), SNAME("EditorFonts"));
+ int font_size = TileSetEditor::get_singleton()->get_theme_font_size(SNAME("bold_size"), SNAME("EditorFonts"));
+ Vector2 texture_origin = tile_data->get_texture_origin();
+ String text = vformat("%s", texture_origin);
+ Vector2 string_size = font->get_string_size(text, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size);
+ p_canvas_item->draw_string_outline(font, p_transform.xform(-texture_origin) + Vector2i(-string_size.x / 2, string_size.y / 2), text, HORIZONTAL_ALIGNMENT_CENTER, string_size.x, font_size, 1, Color(0, 0, 0, 1));
+ p_canvas_item->draw_string(font, p_transform.xform(-texture_origin) + Vector2i(-string_size.x / 2, string_size.y / 2), text, HORIZONTAL_ALIGNMENT_CENTER, string_size.x, font_size, color);
+ }
}
void TileDataPositionEditor::draw_over_tile(CanvasItem *p_canvas_item, Transform2D p_transform, TileMapCell p_cell, bool p_selected) {
@@ -1288,8 +1307,21 @@ void TileDataYSortEditor::draw_over_tile(CanvasItem *p_canvas_item, Transform2D
Color selection_color = Color().from_hsv(Math::fposmod(grid_color.get_h() + 0.5, 1.0), grid_color.get_s(), grid_color.get_v(), 1.0);
color = selection_color;
}
- Ref<Texture2D> position_icon = TileSetEditor::get_singleton()->get_theme_icon(SNAME("EditorPosition"), SNAME("EditorIcons"));
- p_canvas_item->draw_texture(position_icon, p_transform.xform(Vector2(0, tile_data->get_y_sort_origin())) - position_icon->get_size() / 2, color);
+ Vector2 texture_origin = tile_data->get_texture_origin();
+ TileSetSource *source = *(tile_set->get_source(p_cell.source_id));
+ TileSetAtlasSource *atlas_source = Object::cast_to<TileSetAtlasSource>(source);
+ if (atlas_source->is_position_in_tile_texture_region(p_cell.get_atlas_coords(), p_cell.alternative_tile, Vector2(0, tile_data->get_y_sort_origin()))) {
+ Ref<Texture2D> position_icon = TileSetEditor::get_singleton()->get_theme_icon(SNAME("EditorPosition"), SNAME("EditorIcons"));
+ p_canvas_item->draw_texture(position_icon, p_transform.xform(Vector2(0, tile_data->get_y_sort_origin())) - position_icon->get_size() / 2, color);
+ } else {
+ Ref<Font> font = TileSetEditor::get_singleton()->get_theme_font(SNAME("bold"), SNAME("EditorFonts"));
+ int font_size = TileSetEditor::get_singleton()->get_theme_font_size(SNAME("bold_size"), SNAME("EditorFonts"));
+ String text = vformat("%s", tile_data->get_y_sort_origin());
+
+ Vector2 string_size = font->get_string_size(text, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size);
+ p_canvas_item->draw_string_outline(font, p_transform.xform(-texture_origin) + Vector2i(-string_size.x / 2, string_size.y / 2), text, HORIZONTAL_ALIGNMENT_CENTER, string_size.x, font_size, 1, Color(0, 0, 0, 1));
+ p_canvas_item->draw_string(font, p_transform.xform(-texture_origin) + Vector2i(-string_size.x / 2, string_size.y / 2), text, HORIZONTAL_ALIGNMENT_CENTER, string_size.x, font_size, color);
+ }
}
void TileDataOcclusionShapeEditor::draw_over_tile(CanvasItem *p_canvas_item, Transform2D p_transform, TileMapCell p_cell, bool p_selected) {
@@ -1333,7 +1365,7 @@ void TileDataOcclusionShapeEditor::_set_painted_value(TileSetAtlasSource *p_tile
if (occluder_polygon.is_valid()) {
polygon_editor->add_polygon(occluder_polygon->get_polygon());
}
- polygon_editor->set_background(p_tile_set_atlas_source->get_texture(), p_tile_set_atlas_source->get_tile_texture_region(p_coords), p_tile_set_atlas_source->get_tile_effective_texture_offset(p_coords, p_alternative_tile), tile_data->get_flip_h(), tile_data->get_flip_v(), tile_data->get_transpose(), tile_data->get_modulate());
+ polygon_editor->set_background(p_tile_set_atlas_source->get_texture(), p_tile_set_atlas_source->get_tile_texture_region(p_coords), tile_data->get_texture_origin(), tile_data->get_flip_h(), tile_data->get_flip_v(), tile_data->get_transpose(), tile_data->get_modulate());
}
void TileDataOcclusionShapeEditor::_set_value(TileSetAtlasSource *p_tile_set_atlas_source, Vector2 p_coords, int p_alternative_tile, Variant p_value) {
@@ -1342,7 +1374,7 @@ void TileDataOcclusionShapeEditor::_set_value(TileSetAtlasSource *p_tile_set_atl
Ref<OccluderPolygon2D> occluder_polygon = p_value;
tile_data->set_occluder(occlusion_layer, occluder_polygon);
- polygon_editor->set_background(p_tile_set_atlas_source->get_texture(), p_tile_set_atlas_source->get_tile_texture_region(p_coords), p_tile_set_atlas_source->get_tile_effective_texture_offset(p_coords, p_alternative_tile), tile_data->get_flip_h(), tile_data->get_flip_v(), tile_data->get_transpose(), tile_data->get_modulate());
+ polygon_editor->set_background(p_tile_set_atlas_source->get_texture(), p_tile_set_atlas_source->get_tile_texture_region(p_coords), tile_data->get_texture_origin(), tile_data->get_flip_h(), tile_data->get_flip_v(), tile_data->get_transpose(), tile_data->get_modulate());
}
Variant TileDataOcclusionShapeEditor::_get_value(TileSetAtlasSource *p_tile_set_atlas_source, Vector2 p_coords, int p_alternative_tile) {
@@ -1489,7 +1521,7 @@ void TileDataCollisionEditor::_set_painted_value(TileSetAtlasSource *p_tile_set_
E.value->update_property();
}
- polygon_editor->set_background(p_tile_set_atlas_source->get_texture(), p_tile_set_atlas_source->get_tile_texture_region(p_coords), p_tile_set_atlas_source->get_tile_effective_texture_offset(p_coords, p_alternative_tile), tile_data->get_flip_h(), tile_data->get_flip_v(), tile_data->get_transpose(), tile_data->get_modulate());
+ polygon_editor->set_background(p_tile_set_atlas_source->get_texture(), p_tile_set_atlas_source->get_tile_texture_region(p_coords), tile_data->get_texture_origin(), tile_data->get_flip_h(), tile_data->get_flip_v(), tile_data->get_transpose(), tile_data->get_modulate());
}
void TileDataCollisionEditor::_set_value(TileSetAtlasSource *p_tile_set_atlas_source, Vector2 p_coords, int p_alternative_tile, Variant p_value) {
@@ -1508,7 +1540,7 @@ void TileDataCollisionEditor::_set_value(TileSetAtlasSource *p_tile_set_atlas_so
tile_data->set_collision_polygon_one_way_margin(physics_layer, i, polygon_dict["one_way_margin"]);
}
- polygon_editor->set_background(p_tile_set_atlas_source->get_texture(), p_tile_set_atlas_source->get_tile_texture_region(p_coords), p_tile_set_atlas_source->get_tile_effective_texture_offset(p_coords, p_alternative_tile), tile_data->get_flip_h(), tile_data->get_flip_v(), tile_data->get_transpose(), tile_data->get_modulate());
+ polygon_editor->set_background(p_tile_set_atlas_source->get_texture(), p_tile_set_atlas_source->get_tile_texture_region(p_coords), tile_data->get_texture_origin(), tile_data->get_flip_h(), tile_data->get_flip_v(), tile_data->get_transpose(), tile_data->get_modulate());
}
Variant TileDataCollisionEditor::_get_value(TileSetAtlasSource *p_tile_set_atlas_source, Vector2 p_coords, int p_alternative_tile) {
@@ -1741,7 +1773,7 @@ void TileDataTerrainsEditor::forward_draw_over_atlas(TileAtlasView *p_tile_atlas
TileData *tile_data = p_tile_set_atlas_source->get_tile_data(hovered_coords, 0);
int terrain_set = tile_data->get_terrain_set();
Rect2i texture_region = p_tile_set_atlas_source->get_tile_texture_region(hovered_coords);
- Vector2i position = texture_region.get_center() + p_tile_set_atlas_source->get_tile_effective_texture_offset(hovered_coords, 0);
+ Vector2i position = texture_region.get_center() + tile_data->get_texture_origin();
if (terrain_set >= 0 && terrain_set == int(dummy_object->get("terrain_set"))) {
// Draw hovered bit.
@@ -1792,7 +1824,7 @@ void TileDataTerrainsEditor::forward_draw_over_atlas(TileAtlasView *p_tile_atlas
// Text
p_canvas_item->draw_set_transform_matrix(Transform2D());
Rect2i texture_region = p_tile_set_atlas_source->get_tile_texture_region(coords);
- Vector2i position = texture_region.get_center() + p_tile_set_atlas_source->get_tile_effective_texture_offset(coords, 0);
+ Vector2i position = texture_region.get_center() + tile_data->get_texture_origin();
Color color = Color(1, 1, 1);
String text;
@@ -1885,7 +1917,7 @@ void TileDataTerrainsEditor::forward_draw_over_atlas(TileAtlasView *p_tile_atlas
Vector2i coords = E.get_atlas_coords();
Rect2i texture_region = p_tile_set_atlas_source->get_tile_texture_region(coords);
- Vector2i position = texture_region.get_center() + p_tile_set_atlas_source->get_tile_effective_texture_offset(coords, 0);
+ Vector2i position = texture_region.get_center() + p_tile_set_atlas_source->get_tile_data(coords, 0)->get_texture_origin();
Vector<Vector2> polygon = tile_set->get_terrain_polygon(terrain_set);
for (int j = 0; j < polygon.size(); j++) {
@@ -1930,7 +1962,7 @@ void TileDataTerrainsEditor::forward_draw_over_alternatives(TileAtlasView *p_til
TileData *tile_data = p_tile_set_atlas_source->get_tile_data(hovered_coords, hovered_alternative);
int terrain_set = tile_data->get_terrain_set();
Rect2i texture_region = p_tile_atlas_view->get_alternative_tile_rect(hovered_coords, hovered_alternative);
- Vector2i position = texture_region.get_center() + p_tile_set_atlas_source->get_tile_effective_texture_offset(hovered_coords, hovered_alternative);
+ Vector2i position = texture_region.get_center() + tile_data->get_texture_origin();
if (terrain_set == int(dummy_object->get("terrain_set"))) {
// Draw hovered bit.
@@ -1984,7 +2016,7 @@ void TileDataTerrainsEditor::forward_draw_over_alternatives(TileAtlasView *p_til
// Text
p_canvas_item->draw_set_transform_matrix(Transform2D());
Rect2i texture_region = p_tile_atlas_view->get_alternative_tile_rect(coords, alternative_tile);
- Vector2i position = texture_region.get_center() + p_tile_set_atlas_source->get_tile_effective_texture_offset(coords, 0);
+ Vector2i position = texture_region.get_center() + tile_data->get_texture_origin();
Color color = Color(1, 1, 1);
String text;
@@ -2069,7 +2101,7 @@ void TileDataTerrainsEditor::forward_painting_atlas_gui_input(TileAtlasView *p_t
// Set the terrains bits.
Rect2i texture_region = p_tile_set_atlas_source->get_tile_texture_region(coords);
- Vector2i position = texture_region.get_center() + p_tile_set_atlas_source->get_tile_effective_texture_offset(coords, 0);
+ Vector2i position = texture_region.get_center() + tile_data->get_texture_origin();
Vector<Vector2> polygon = tile_set->get_terrain_polygon(tile_data->get_terrain_set());
if (Geometry2D::is_segment_intersecting_polygon(mm->get_position() - position, drag_last_pos - position, polygon)) {
@@ -2103,7 +2135,7 @@ void TileDataTerrainsEditor::forward_painting_atlas_gui_input(TileAtlasView *p_t
TileData *tile_data = p_tile_set_atlas_source->get_tile_data(coords, 0);
int terrain_set = tile_data->get_terrain_set();
Rect2i texture_region = p_tile_set_atlas_source->get_tile_texture_region(coords);
- Vector2i position = texture_region.get_center() + p_tile_set_atlas_source->get_tile_effective_texture_offset(coords, 0);
+ Vector2i position = texture_region.get_center() + tile_data->get_texture_origin();
dummy_object->set("terrain_set", terrain_set);
dummy_object->set("terrain", -1);
@@ -2218,7 +2250,7 @@ void TileDataTerrainsEditor::forward_painting_atlas_gui_input(TileAtlasView *p_t
// Set the terrain bit.
Rect2i texture_region = p_tile_set_atlas_source->get_tile_texture_region(coords);
- Vector2i position = texture_region.get_center() + p_tile_set_atlas_source->get_tile_effective_texture_offset(coords, 0);
+ Vector2i position = texture_region.get_center() + tile_data->get_texture_origin();
Vector<Vector2> polygon = tile_set->get_terrain_polygon(terrain_set);
if (Geometry2D::is_point_in_polygon(mb->get_position() - position, polygon)) {
@@ -2365,7 +2397,7 @@ void TileDataTerrainsEditor::forward_painting_atlas_gui_input(TileAtlasView *p_t
TileData *tile_data = p_tile_set_atlas_source->get_tile_data(coords, 0);
Rect2i texture_region = p_tile_set_atlas_source->get_tile_texture_region(coords);
- Vector2i position = texture_region.get_center() + p_tile_set_atlas_source->get_tile_effective_texture_offset(coords, 0);
+ Vector2i position = texture_region.get_center() + tile_data->get_texture_origin();
Vector<Vector2> polygon = tile_set->get_terrain_polygon(terrain_set);
for (int j = 0; j < polygon.size(); j++) {
@@ -2465,7 +2497,7 @@ void TileDataTerrainsEditor::forward_painting_alternatives_gui_input(TileAtlasVi
// Set the terrains bits.
Rect2i texture_region = p_tile_atlas_view->get_alternative_tile_rect(coords, alternative_tile);
- Vector2i position = texture_region.get_center() + p_tile_set_atlas_source->get_tile_effective_texture_offset(coords, alternative_tile);
+ Vector2i position = texture_region.get_center() + tile_data->get_texture_origin();
Vector<Vector2> polygon = tile_set->get_terrain_polygon(tile_data->get_terrain_set());
if (Geometry2D::is_segment_intersecting_polygon(mm->get_position() - position, drag_last_pos - position, polygon)) {
@@ -2501,7 +2533,7 @@ void TileDataTerrainsEditor::forward_painting_alternatives_gui_input(TileAtlasVi
TileData *tile_data = p_tile_set_atlas_source->get_tile_data(coords, alternative_tile);
int terrain_set = tile_data->get_terrain_set();
Rect2i texture_region = p_tile_atlas_view->get_alternative_tile_rect(coords, alternative_tile);
- Vector2i position = texture_region.get_center() + p_tile_set_atlas_source->get_tile_effective_texture_offset(coords, alternative_tile);
+ Vector2i position = texture_region.get_center() + tile_data->get_texture_origin();
dummy_object->set("terrain_set", terrain_set);
dummy_object->set("terrain", -1);
@@ -2591,7 +2623,7 @@ void TileDataTerrainsEditor::forward_painting_alternatives_gui_input(TileAtlasVi
// Set the terrain bit.
Rect2i texture_region = p_tile_atlas_view->get_alternative_tile_rect(coords, alternative_tile);
- Vector2i position = texture_region.get_center() + p_tile_set_atlas_source->get_tile_effective_texture_offset(coords, alternative_tile);
+ Vector2i position = texture_region.get_center() + tile_data->get_texture_origin();
Vector<Vector2> polygon = tile_set->get_terrain_polygon(terrain_set);
if (Geometry2D::is_point_in_polygon(mb->get_position() - position, polygon)) {
@@ -2741,7 +2773,7 @@ void TileDataNavigationEditor::_set_painted_value(TileSetAtlasSource *p_tile_set
polygon_editor->add_polygon(nav_polygon->get_outline(i));
}
}
- polygon_editor->set_background(p_tile_set_atlas_source->get_texture(), p_tile_set_atlas_source->get_tile_texture_region(p_coords), p_tile_set_atlas_source->get_tile_effective_texture_offset(p_coords, p_alternative_tile), tile_data->get_flip_h(), tile_data->get_flip_v(), tile_data->get_transpose(), tile_data->get_modulate());
+ polygon_editor->set_background(p_tile_set_atlas_source->get_texture(), p_tile_set_atlas_source->get_tile_texture_region(p_coords), tile_data->get_texture_origin(), tile_data->get_flip_h(), tile_data->get_flip_v(), tile_data->get_transpose(), tile_data->get_modulate());
}
void TileDataNavigationEditor::_set_value(TileSetAtlasSource *p_tile_set_atlas_source, Vector2 p_coords, int p_alternative_tile, Variant p_value) {
@@ -2750,7 +2782,7 @@ void TileDataNavigationEditor::_set_value(TileSetAtlasSource *p_tile_set_atlas_s
Ref<NavigationPolygon> nav_polygon = p_value;
tile_data->set_navigation_polygon(navigation_layer, nav_polygon);
- polygon_editor->set_background(p_tile_set_atlas_source->get_texture(), p_tile_set_atlas_source->get_tile_texture_region(p_coords), p_tile_set_atlas_source->get_tile_effective_texture_offset(p_coords, p_alternative_tile), tile_data->get_flip_h(), tile_data->get_flip_v(), tile_data->get_transpose(), tile_data->get_modulate());
+ polygon_editor->set_background(p_tile_set_atlas_source->get_texture(), p_tile_set_atlas_source->get_tile_texture_region(p_coords), tile_data->get_texture_origin(), tile_data->get_flip_h(), tile_data->get_flip_v(), tile_data->get_transpose(), tile_data->get_modulate());
}
Variant TileDataNavigationEditor::_get_value(TileSetAtlasSource *p_tile_set_atlas_source, Vector2 p_coords, int p_alternative_tile) {
diff --git a/editor/plugins/tiles/tile_data_editors.h b/editor/plugins/tiles/tile_data_editors.h
index 02d4584428..1ebf30aecd 100644
--- a/editor/plugins/tiles/tile_data_editors.h
+++ b/editor/plugins/tiles/tile_data_editors.h
@@ -242,8 +242,8 @@ public:
~TileDataDefaultEditor();
};
-class TileDataTextureOffsetEditor : public TileDataDefaultEditor {
- GDCLASS(TileDataTextureOffsetEditor, TileDataDefaultEditor);
+class TileDataTextureOriginEditor : public TileDataDefaultEditor {
+ GDCLASS(TileDataTextureOriginEditor, TileDataDefaultEditor);
public:
virtual void draw_over_tile(CanvasItem *p_canvas_item, Transform2D p_transform, TileMapCell p_cell, bool p_selected = false) override;
diff --git a/editor/plugins/tiles/tile_map_editor.cpp b/editor/plugins/tiles/tile_map_editor.cpp
index 2394130ad6..f0a02a3768 100644
--- a/editor/plugins/tiles/tile_map_editor.cpp
+++ b/editor/plugins/tiles/tile_map_editor.cpp
@@ -266,7 +266,7 @@ void TileMapEditorTilesPlugin::_patterns_item_list_gui_input(const Ref<InputEven
}
Ref<TileSet> tile_set = tile_map->get_tileset();
- if (!tile_set.is_valid()) {
+ if (!tile_set.is_valid() || EditorNode::get_singleton()->is_resource_read_only(tile_set)) {
return;
}
@@ -897,7 +897,7 @@ void TileMapEditorTilesPlugin::forward_canvas_draw_over_viewport(Control *p_over
// Compute the offset
Rect2i source_rect = atlas_source->get_tile_texture_region(E.value.get_atlas_coords());
- Vector2i tile_offset = atlas_source->get_tile_effective_texture_offset(E.value.get_atlas_coords(), E.value.alternative_tile);
+ Vector2i tile_offset = tile_data->get_texture_origin();
// Compute the destination rectangle in the CanvasItem.
Rect2 dest_rect;
@@ -1277,13 +1277,15 @@ void TileMapEditorTilesPlugin::_stop_dragging() {
tile_map->set_cell(tile_map_layer, kv.key, kv.value.source_id, kv.value.get_atlas_coords(), kv.value.alternative_tile);
}
- // Creating a pattern in the pattern list.
- select_last_pattern = true;
- int new_pattern_index = tile_set->get_patterns_count();
- undo_redo->create_action(TTR("Add TileSet pattern"));
- undo_redo->add_do_method(*tile_set, "add_pattern", selection_pattern, new_pattern_index);
- undo_redo->add_undo_method(*tile_set, "remove_pattern", new_pattern_index);
- undo_redo->commit_action();
+ if (EditorNode::get_singleton()->is_resource_read_only(tile_set)) {
+ // Creating a pattern in the pattern list.
+ select_last_pattern = true;
+ int new_pattern_index = tile_set->get_patterns_count();
+ undo_redo->create_action(TTR("Add TileSet pattern"));
+ undo_redo->add_do_method(*tile_set, "add_pattern", selection_pattern, new_pattern_index);
+ undo_redo->add_undo_method(*tile_set, "remove_pattern", new_pattern_index);
+ undo_redo->commit_action();
+ }
} else {
// Get the top-left cell.
Vector2i top_left;
@@ -1989,6 +1991,15 @@ TypedArray<Vector2i> TileMapEditorTilesPlugin::_get_tile_map_selection() const {
void TileMapEditorTilesPlugin::edit(ObjectID p_tile_map_id, int p_tile_map_layer) {
_stop_dragging(); // Avoids staying in a wrong drag state.
+ // Disable sort button if the tileset is read-only
+ TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
+ if (tile_map) {
+ Ref<TileSet> tile_set = tile_map->get_tileset();
+ if (tile_set.is_valid()) {
+ source_sort_button->set_disabled(EditorNode::get_singleton()->is_resource_read_only(tile_set));
+ }
+ }
+
if (tile_map_id != p_tile_map_id) {
tile_map_id = p_tile_map_id;
@@ -3986,7 +3997,7 @@ TileMapEditor::TileMapEditor() {
tabs_bar->connect("tab_changed", callable_mp(this, &TileMapEditor::_tab_changed));
// --- TileMap toolbar ---
- tile_map_toolbar = memnew(HBoxContainer);
+ tile_map_toolbar = memnew(HFlowContainer);
tile_map_toolbar->set_h_size_flags(SIZE_EXPAND_FILL);
add_child(tile_map_toolbar);
@@ -4001,8 +4012,11 @@ TileMapEditor::TileMapEditor() {
}
}
- // Wide empty separation control.
- tile_map_toolbar->add_spacer();
+ // Wide empty separation control. (like BoxContainer::add_spacer())
+ Control *c = memnew(Control);
+ c->set_mouse_filter(MOUSE_FILTER_PASS);
+ c->set_h_size_flags(SIZE_EXPAND_FILL);
+ tile_map_toolbar->add_child(c);
// Layer selector.
layers_selection_button = memnew(OptionButton);
diff --git a/editor/plugins/tiles/tile_map_editor.h b/editor/plugins/tiles/tile_map_editor.h
index fb9c2f3689..1cab1d1500 100644
--- a/editor/plugins/tiles/tile_map_editor.h
+++ b/editor/plugins/tiles/tile_map_editor.h
@@ -38,6 +38,7 @@
#include "scene/2d/tile_map.h"
#include "scene/gui/box_container.h"
#include "scene/gui/check_box.h"
+#include "scene/gui/flow_container.h"
#include "scene/gui/item_list.h"
#include "scene/gui/menu_button.h"
#include "scene/gui/option_button.h"
@@ -323,7 +324,7 @@ private:
Vector<TileMapEditorPlugin *> tile_map_editor_plugins;
// Toolbar.
- HBoxContainer *tile_map_toolbar = nullptr;
+ HFlowContainer *tile_map_toolbar = nullptr;
OptionButton *layers_selection_button = nullptr;
Button *toggle_highlight_selected_layer_button = nullptr;
diff --git a/editor/plugins/tiles/tile_set_atlas_source_editor.cpp b/editor/plugins/tiles/tile_set_atlas_source_editor.cpp
index 32421daa92..840a3911af 100644
--- a/editor/plugins/tiles/tile_set_atlas_source_editor.cpp
+++ b/editor/plugins/tiles/tile_set_atlas_source_editor.cpp
@@ -585,6 +585,7 @@ void TileSetAtlasSourceEditor::_update_atlas_source_inspector() {
// Update visibility.
bool inspector_visible = tools_button_group->get_pressed_button() == tool_setup_atlas_source_button;
atlas_source_inspector->set_visible(inspector_visible);
+ atlas_source_inspector->set_read_only(read_only);
}
void TileSetAtlasSourceEditor::_update_tile_inspector() {
@@ -599,6 +600,7 @@ void TileSetAtlasSourceEditor::_update_tile_inspector() {
tile_inspector->hide();
tile_inspector_no_tile_selected_label->hide();
}
+ tile_inspector->set_read_only(read_only);
}
void TileSetAtlasSourceEditor::_update_tile_data_editors() {
@@ -638,14 +640,14 @@ void TileSetAtlasSourceEditor::_update_tile_data_editors() {
// --- Rendering ---
ADD_TILE_DATA_EDITOR_GROUP("Rendering");
- ADD_TILE_DATA_EDITOR(group, "Texture Offset", "texture_offset");
- if (!tile_data_editors.has("texture_offset")) {
- TileDataTextureOffsetEditor *tile_data_texture_offset_editor = memnew(TileDataTextureOffsetEditor);
- tile_data_texture_offset_editor->hide();
- tile_data_texture_offset_editor->setup_property_editor(Variant::VECTOR2, "texture_offset");
- tile_data_texture_offset_editor->connect("needs_redraw", callable_mp((CanvasItem *)tile_atlas_control_unscaled, &Control::queue_redraw));
- tile_data_texture_offset_editor->connect("needs_redraw", callable_mp((CanvasItem *)alternative_tiles_control_unscaled, &Control::queue_redraw));
- tile_data_editors["texture_offset"] = tile_data_texture_offset_editor;
+ ADD_TILE_DATA_EDITOR(group, "Texture Origin", "texture_origin");
+ if (!tile_data_editors.has("texture_origin")) {
+ TileDataTextureOriginEditor *tile_data_texture_origin_editor = memnew(TileDataTextureOriginEditor);
+ tile_data_texture_origin_editor->hide();
+ tile_data_texture_origin_editor->setup_property_editor(Variant::VECTOR2, "texture_origin");
+ tile_data_texture_origin_editor->connect("needs_redraw", callable_mp((CanvasItem *)tile_atlas_control_unscaled, &Control::queue_redraw));
+ tile_data_texture_origin_editor->connect("needs_redraw", callable_mp((CanvasItem *)alternative_tiles_control_unscaled, &Control::queue_redraw));
+ tile_data_editors["texture_origin"] = tile_data_texture_origin_editor;
}
ADD_TILE_DATA_EDITOR(group, "Modulate", "modulate");
@@ -970,19 +972,19 @@ void TileSetAtlasSourceEditor::_update_toolbar() {
current_tile_data_editor_toolbar->hide();
}
tools_settings_erase_button->show();
- tool_advanced_menu_buttom->show();
+ tool_advanced_menu_button->show();
} else if (tools_button_group->get_pressed_button() == tool_select_button) {
if (current_tile_data_editor_toolbar) {
current_tile_data_editor_toolbar->hide();
}
tools_settings_erase_button->hide();
- tool_advanced_menu_buttom->hide();
+ tool_advanced_menu_button->hide();
} else if (tools_button_group->get_pressed_button() == tool_paint_button) {
if (current_tile_data_editor_toolbar) {
current_tile_data_editor_toolbar->show();
}
tools_settings_erase_button->hide();
- tool_advanced_menu_buttom->hide();
+ tool_advanced_menu_button->hide();
}
}
@@ -1862,7 +1864,7 @@ void TileSetAtlasSourceEditor::_tile_atlas_control_unscaled_draw() {
for (int i = 0; i < tile_set_atlas_source->get_tiles_count(); i++) {
Vector2i coords = tile_set_atlas_source->get_tile_id(i);
Rect2i texture_region = tile_set_atlas_source->get_tile_texture_region(coords);
- Vector2i position = texture_region.get_center() + tile_set_atlas_source->get_tile_effective_texture_offset(coords, 0);
+ Vector2i position = texture_region.get_center() + tile_set_atlas_source->get_tile_data(coords, 0)->get_texture_origin();
Transform2D xform = tile_atlas_control->get_parent_control()->get_transform();
xform.translate_local(position);
@@ -1885,7 +1887,7 @@ void TileSetAtlasSourceEditor::_tile_atlas_control_unscaled_draw() {
continue;
}
Rect2i texture_region = tile_set_atlas_source->get_tile_texture_region(E.tile);
- Vector2i position = texture_region.get_center() + tile_set_atlas_source->get_tile_effective_texture_offset(E.tile, 0);
+ Vector2i position = texture_region.get_center() + tile_set_atlas_source->get_tile_data(E.tile, 0)->get_texture_origin();
Transform2D xform = tile_atlas_control->get_parent_control()->get_transform();
xform.translate_local(position);
@@ -2037,7 +2039,7 @@ void TileSetAtlasSourceEditor::_tile_alternatives_control_unscaled_draw() {
continue;
}
Rect2i rect = tile_atlas_view->get_alternative_tile_rect(coords, alternative_tile);
- Vector2 position = rect.get_center() + tile_set_atlas_source->get_tile_effective_texture_offset(coords, alternative_tile);
+ Vector2 position = rect.get_center() + tile_set_atlas_source->get_tile_data(coords, alternative_tile)->get_texture_origin();
Transform2D xform = alternative_tiles_control->get_parent_control()->get_transform();
xform.translate_local(position);
@@ -2061,7 +2063,7 @@ void TileSetAtlasSourceEditor::_tile_alternatives_control_unscaled_draw() {
continue;
}
Rect2i rect = tile_atlas_view->get_alternative_tile_rect(E.tile, E.alternative);
- Vector2 position = rect.get_center() + tile_set_atlas_source->get_tile_effective_texture_offset(E.tile, E.alternative);
+ Vector2 position = rect.get_center() + tile_set_atlas_source->get_tile_data(E.tile, E.alternative)->get_texture_origin();
Transform2D xform = alternative_tiles_control->get_parent_control()->get_transform();
xform.translate_local(position);
@@ -2188,7 +2190,12 @@ void TileSetAtlasSourceEditor::edit(Ref<TileSet> p_tile_set, TileSetAtlasSource
ERR_FAIL_COND(p_source_id < 0);
ERR_FAIL_COND(p_tile_set->get_source(p_source_id) != p_tile_set_atlas_source);
- if (p_tile_set == tile_set && p_tile_set_atlas_source == tile_set_atlas_source && p_source_id == tile_set_atlas_source_id) {
+ bool new_read_only_state = false;
+ if (p_tile_set.is_valid()) {
+ new_read_only_state = EditorNode::get_singleton()->is_resource_read_only(p_tile_set);
+ }
+
+ if (p_tile_set == tile_set && p_tile_set_atlas_source == tile_set_atlas_source && p_source_id == tile_set_atlas_source_id && new_read_only_state == read_only) {
return;
}
@@ -2205,11 +2212,23 @@ void TileSetAtlasSourceEditor::edit(Ref<TileSet> p_tile_set, TileSetAtlasSource
tile_set_atlas_source = p_tile_set_atlas_source;
tile_set_atlas_source_id = p_source_id;
- // Add the listener again.
+ // Read-only is off by default.
+ read_only = new_read_only_state;
+
if (tile_set.is_valid()) {
tile_set->connect("changed", callable_mp(this, &TileSetAtlasSourceEditor::_tile_set_changed));
}
+ if (read_only && tools_button_group->get_pressed_button() == tool_paint_button) {
+ tool_paint_button->set_pressed(false);
+ tool_setup_atlas_source_button->set_pressed(true);
+ }
+
+ // Disable buttons in read-only mode.
+ tool_paint_button->set_disabled(read_only);
+ tools_settings_erase_button->set_disabled(read_only);
+ tool_advanced_menu_button->set_disabled(read_only);
+
// Update everything.
_update_source_inspector();
@@ -2344,7 +2363,7 @@ void TileSetAtlasSourceEditor::_notification(int p_what) {
tools_settings_erase_button->set_icon(get_theme_icon(SNAME("Eraser"), SNAME("EditorIcons")));
- tool_advanced_menu_buttom->set_icon(get_theme_icon(SNAME("GuiTabMenuHl"), SNAME("EditorIcons")));
+ tool_advanced_menu_button->set_icon(get_theme_icon(SNAME("GuiTabMenuHl"), SNAME("EditorIcons")));
resize_handle = get_theme_icon(SNAME("EditorHandle"), SNAME("EditorIcons"));
resize_handle_disabled = get_theme_icon(SNAME("EditorHandleDisabled"), SNAME("EditorIcons"));
@@ -2352,6 +2371,18 @@ void TileSetAtlasSourceEditor::_notification(int p_what) {
case NOTIFICATION_INTERNAL_PROCESS: {
if (tile_set_changed_needs_update) {
+ // Read-only is off by default
+ read_only = false;
+ // Add the listener again and check for read-only status.
+ if (tile_set.is_valid()) {
+ read_only = EditorNode::get_singleton()->is_resource_read_only(tile_set);
+ }
+
+ // Disable buttons in read-only mode.
+ tool_paint_button->set_disabled(read_only);
+ tools_settings_erase_button->set_disabled(read_only);
+ tool_advanced_menu_button->set_disabled(read_only);
+
// Update everything.
_update_source_inspector();
@@ -2516,12 +2547,12 @@ TileSetAtlasSourceEditor::TileSetAtlasSourceEditor() {
tools_settings_erase_button->set_shortcut_context(this);
tool_settings->add_child(tools_settings_erase_button);
- tool_advanced_menu_buttom = memnew(MenuButton);
- tool_advanced_menu_buttom->set_flat(true);
- tool_advanced_menu_buttom->get_popup()->add_item(TTR("Create Tiles in Non-Transparent Texture Regions"), ADVANCED_AUTO_CREATE_TILES);
- tool_advanced_menu_buttom->get_popup()->add_item(TTR("Remove Tiles in Fully Transparent Texture Regions"), ADVANCED_AUTO_REMOVE_TILES);
- tool_advanced_menu_buttom->get_popup()->connect("id_pressed", callable_mp(this, &TileSetAtlasSourceEditor::_menu_option));
- tool_settings->add_child(tool_advanced_menu_buttom);
+ tool_advanced_menu_button = memnew(MenuButton);
+ tool_advanced_menu_button->set_flat(true);
+ tool_advanced_menu_button->get_popup()->add_item(TTR("Create Tiles in Non-Transparent Texture Regions"), ADVANCED_AUTO_CREATE_TILES);
+ tool_advanced_menu_button->get_popup()->add_item(TTR("Remove Tiles in Fully Transparent Texture Regions"), ADVANCED_AUTO_REMOVE_TILES);
+ tool_advanced_menu_button->get_popup()->connect("id_pressed", callable_mp(this, &TileSetAtlasSourceEditor::_menu_option));
+ tool_settings->add_child(tool_advanced_menu_button);
_update_toolbar();
@@ -2673,7 +2704,7 @@ void EditorPropertyTilePolygon::update_property() {
Vector2i coords = atlas_tile_proxy_object->get_edited_tiles().front()->get().tile;
int alternative = atlas_tile_proxy_object->get_edited_tiles().front()->get().alternative;
TileData *tile_data = tile_set_atlas_source->get_tile_data(coords, alternative);
- generic_tile_polygon_editor->set_background(tile_set_atlas_source->get_texture(), tile_set_atlas_source->get_tile_texture_region(coords), tile_set_atlas_source->get_tile_effective_texture_offset(coords, alternative), tile_data->get_flip_h(), tile_data->get_flip_v(), tile_data->get_transpose(), tile_data->get_modulate());
+ generic_tile_polygon_editor->set_background(tile_set_atlas_source->get_texture(), tile_set_atlas_source->get_tile_texture_region(coords), tile_data->get_texture_origin(), tile_data->get_flip_h(), tile_data->get_flip_v(), tile_data->get_transpose(), tile_data->get_modulate());
// Reset the polygons.
generic_tile_polygon_editor->clear_polygons();
diff --git a/editor/plugins/tiles/tile_set_atlas_source_editor.h b/editor/plugins/tiles/tile_set_atlas_source_editor.h
index bcab1296ad..a4826bc56f 100644
--- a/editor/plugins/tiles/tile_set_atlas_source_editor.h
+++ b/editor/plugins/tiles/tile_set_atlas_source_editor.h
@@ -113,6 +113,8 @@ public:
};
private:
+ bool read_only = false;
+
Ref<TileSet> tile_set;
TileSetAtlasSource *tile_set_atlas_source = nullptr;
int tile_set_atlas_source_id = TileSet::INVALID_SOURCE;
@@ -209,7 +211,7 @@ private:
HBoxContainer *tool_settings = nullptr;
HBoxContainer *tool_settings_tile_data_toolbar_container = nullptr;
Button *tools_settings_erase_button = nullptr;
- MenuButton *tool_advanced_menu_buttom = nullptr;
+ MenuButton *tool_advanced_menu_button = nullptr;
// Selection.
RBSet<TileSelection> selection;
diff --git a/editor/plugins/tiles/tile_set_editor.cpp b/editor/plugins/tiles/tile_set_editor.cpp
index 53c2d4de51..39d17c718e 100644
--- a/editor/plugins/tiles/tile_set_editor.cpp
+++ b/editor/plugins/tiles/tile_set_editor.cpp
@@ -89,6 +89,10 @@ void TileSetEditor::_drop_data_fw(const Point2 &p_point, const Variant &p_data,
bool TileSetEditor::_can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const {
ERR_FAIL_COND_V(!tile_set.is_valid(), false);
+ if (read_only) {
+ return false;
+ }
+
if (p_from == sources_list) {
Dictionary d = p_data;
@@ -223,7 +227,7 @@ void TileSetEditor::_source_selected(int p_source_index) {
ERR_FAIL_COND(!tile_set.is_valid());
// Update the selected source.
- sources_delete_button->set_disabled(p_source_index < 0);
+ sources_delete_button->set_disabled(p_source_index < 0 || read_only);
if (p_source_index >= 0) {
int source_id = sources_list->get_item_metadata(p_source_index);
@@ -356,8 +360,19 @@ void TileSetEditor::_notification(int p_what) {
if (tile_set.is_valid()) {
tile_set->set_edited(true);
}
+
+ read_only = false;
+ if (tile_set.is_valid()) {
+ read_only = EditorNode::get_singleton()->is_resource_read_only(tile_set);
+ }
+
_update_sources_list();
_update_patterns_list();
+
+ sources_add_button->set_disabled(read_only);
+ sources_advanced_menu_button->set_disabled(read_only);
+ source_sort_button->set_disabled(read_only);
+
tile_set_changed_needs_update = false;
}
} break;
@@ -367,6 +382,10 @@ void TileSetEditor::_notification(int p_what) {
void TileSetEditor::_patterns_item_list_gui_input(const Ref<InputEvent> &p_event) {
ERR_FAIL_COND(!tile_set.is_valid());
+ if (EditorNode::get_singleton()->is_resource_read_only(tile_set)) {
+ return;
+ }
+
if (ED_IS_SHORTCUT("tiles_editor/delete", p_event) && p_event->is_pressed() && !p_event->is_echo()) {
Vector<int> selected = patterns_item_list->get_selected_items();
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
@@ -667,7 +686,12 @@ void TileSetEditor::_undo_redo_inspector_callback(Object *p_undo_redo, Object *p
}
void TileSetEditor::edit(Ref<TileSet> p_tile_set) {
- if (p_tile_set == tile_set) {
+ bool new_read_only_state = false;
+ if (tile_set.is_valid()) {
+ new_read_only_state = EditorNode::get_singleton()->is_resource_read_only(p_tile_set);
+ }
+
+ if (p_tile_set == tile_set && new_read_only_state == read_only) {
return;
}
@@ -679,8 +703,15 @@ void TileSetEditor::edit(Ref<TileSet> p_tile_set) {
// Change the edited object.
tile_set = p_tile_set;
- // Add the listener again.
+ // Read-only status is false by default
+ read_only = new_read_only_state;
+
+ // Add the listener again and check for read-only status.
if (tile_set.is_valid()) {
+ sources_add_button->set_disabled(read_only);
+ sources_advanced_menu_button->set_disabled(read_only);
+ source_sort_button->set_disabled(read_only);
+
tile_set->connect("changed", callable_mp(this, &TileSetEditor::_tile_set_changed));
if (first_edit) {
first_edit = false;
@@ -690,10 +721,6 @@ void TileSetEditor::edit(Ref<TileSet> p_tile_set) {
}
_update_patterns_list();
}
-
- tile_set_atlas_source_editor->hide();
- tile_set_scenes_collection_source_editor->hide();
- no_source_selected_label->show();
}
TileSetEditor::TileSetEditor() {
diff --git a/editor/plugins/tiles/tile_set_editor.h b/editor/plugins/tiles/tile_set_editor.h
index e3dff11277..d36d3bde41 100644
--- a/editor/plugins/tiles/tile_set_editor.h
+++ b/editor/plugins/tiles/tile_set_editor.h
@@ -45,6 +45,8 @@ class TileSetEditor : public VBoxContainer {
static TileSetEditor *singleton;
private:
+ bool read_only = false;
+
Ref<TileSet> tile_set;
bool tile_set_changed_needs_update = false;
HSplitContainer *split_container = nullptr;
diff --git a/editor/plugins/tiles/tile_set_scenes_collection_source_editor.cpp b/editor/plugins/tiles/tile_set_scenes_collection_source_editor.cpp
index 6251cd18f7..cc276597fa 100644
--- a/editor/plugins/tiles/tile_set_scenes_collection_source_editor.cpp
+++ b/editor/plugins/tiles/tile_set_scenes_collection_source_editor.cpp
@@ -284,7 +284,7 @@ void TileSetScenesCollectionSourceEditor::_update_tile_inspector() {
void TileSetScenesCollectionSourceEditor::_update_action_buttons() {
Vector<int> selected_indices = scene_tiles_list->get_selected_items();
- scene_tile_delete_button->set_disabled(selected_indices.size() <= 0);
+ scene_tile_delete_button->set_disabled(selected_indices.size() <= 0 || read_only);
}
void TileSetScenesCollectionSourceEditor::_update_scenes_list() {
@@ -342,6 +342,12 @@ void TileSetScenesCollectionSourceEditor::_notification(int p_what) {
case NOTIFICATION_INTERNAL_PROCESS: {
if (tile_set_scenes_collection_source_changed_needs_update) {
+ read_only = false;
+ // Add the listener again and check for read-only status.
+ if (tile_set.is_valid()) {
+ read_only = EditorNode::get_singleton()->is_resource_read_only(tile_set);
+ }
+
// Update everything.
_update_source_inspector();
_update_scenes_list();
@@ -365,7 +371,12 @@ void TileSetScenesCollectionSourceEditor::edit(Ref<TileSet> p_tile_set, TileSetS
ERR_FAIL_COND(p_source_id < 0);
ERR_FAIL_COND(p_tile_set->get_source(p_source_id) != p_tile_set_scenes_collection_source);
- if (p_tile_set == tile_set && p_tile_set_scenes_collection_source == tile_set_scenes_collection_source && p_source_id == tile_set_source_id) {
+ bool new_read_only_state = false;
+ if (p_tile_set.is_valid()) {
+ new_read_only_state = EditorNode::get_singleton()->is_resource_read_only(p_tile_set);
+ }
+
+ if (p_tile_set == tile_set && p_tile_set_scenes_collection_source == tile_set_scenes_collection_source && p_source_id == tile_set_source_id && new_read_only_state == read_only) {
return;
}
@@ -379,6 +390,16 @@ void TileSetScenesCollectionSourceEditor::edit(Ref<TileSet> p_tile_set, TileSetS
tile_set_scenes_collection_source = p_tile_set_scenes_collection_source;
tile_set_source_id = p_source_id;
+ // Read-only status is false by default
+ read_only = new_read_only_state;
+
+ if (tile_set.is_valid()) {
+ scenes_collection_source_inspector->set_read_only(read_only);
+ tile_inspector->set_read_only(read_only);
+
+ scene_tile_add_button->set_disabled(read_only);
+ }
+
// Add the listener again.
if (tile_set_scenes_collection_source) {
tile_set_scenes_collection_source->connect("changed", callable_mp(this, &TileSetScenesCollectionSourceEditor::_tile_set_scenes_collection_source_changed));
diff --git a/editor/plugins/tiles/tile_set_scenes_collection_source_editor.h b/editor/plugins/tiles/tile_set_scenes_collection_source_editor.h
index 0901205a29..2a0e8595c4 100644
--- a/editor/plugins/tiles/tile_set_scenes_collection_source_editor.h
+++ b/editor/plugins/tiles/tile_set_scenes_collection_source_editor.h
@@ -91,6 +91,8 @@ private:
};
private:
+ bool read_only = false;
+
Ref<TileSet> tile_set;
TileSetScenesCollectionSource *tile_set_scenes_collection_source = nullptr;
int tile_set_source_id = -1;
diff --git a/editor/plugins/tiles/tiles_editor_plugin.cpp b/editor/plugins/tiles/tiles_editor_plugin.cpp
index 19ee0ae98d..fad36660d9 100644
--- a/editor/plugins/tiles/tiles_editor_plugin.cpp
+++ b/editor/plugins/tiles/tiles_editor_plugin.cpp
@@ -101,12 +101,12 @@ 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);
- Vector2 center = world_pos - atlas_source->get_tile_effective_texture_offset(coords, alternative);
+ Vector2 center = world_pos - atlas_source->get_tile_data(coords, alternative)->get_texture_origin();
encompassing_rect.expand_to(center - atlas_source->get_tile_texture_region(coords).size / 2);
encompassing_rect.expand_to(center + atlas_source->get_tile_texture_region(coords).size / 2);
}
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);
diff --git a/editor/project_converter_3_to_4.cpp b/editor/project_converter_3_to_4.cpp
index 727b2c9b4d..f38c8ee39d 100644
--- a/editor/project_converter_3_to_4.cpp
+++ b/editor/project_converter_3_to_4.cpp
@@ -215,7 +215,6 @@ static const char *gdscript_function_renames[][2] = {
{ "_get_configuration_warning", "_get_configuration_warnings" }, // Node
{ "_set_current", "set_current" }, // Camera2D
{ "_set_editor_description", "set_editor_description" }, // Node
- { "_set_playing", "set_playing" }, // AnimatedSprite3D
{ "_toplevel_raise_self", "_top_level_raise_self" }, // CanvasItem
{ "_update_wrap_at", "_update_wrap_at_column" }, // TextEdit
{ "add_animation", "add_animation_library" }, // AnimationPlayer
@@ -1168,6 +1167,7 @@ static const char *gdscript_properties_renames[][2] = {
{ "unit_db", "volume_db" }, // AudioStreamPlayer3D
{ "unit_offset", "progress_ratio" }, // PathFollow2D, PathFollow3D
{ "vseparation", "v_separation" }, // Theme
+ { "frames", "sprite_frames" }, // AnimatedSprite2D, AnimatedSprite3D
{ nullptr, nullptr },
};
@@ -1286,6 +1286,7 @@ static const char *gdscript_signals_renames[][2] = {
{ "about_to_show", "about_to_popup" }, // Popup
{ "button_release", "button_released" }, // XRController3D
{ "cancelled", "canceled" }, // AcceptDialog
+ { "item_double_clicked", "item_icon_double_clicked" }, // Tree
{ "network_peer_connected", "peer_connected" }, // MultiplayerAPI
{ "network_peer_disconnected", "peer_disconnected" }, // MultiplayerAPI
{ "network_peer_packet", "peer_packet" }, // MultiplayerAPI
@@ -2548,14 +2549,14 @@ bool ProjectConverter3To4::test_conversion(RegExContainer &reg_container) {
valid = valid && test_conversion_with_regex("tool", "@tool", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container);
valid = valid && test_conversion_with_regex("\n tool", "\n tool", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container);
valid = valid && test_conversion_with_regex("\n\ntool", "\n\n@tool", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container);
- valid = valid && test_conversion_with_regex("\n\nremote func", "\n\n@rpc(any_peer) func", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container);
- valid = valid && test_conversion_with_regex("\n\nremotesync func", "\n\n@rpc(any_peer, call_local) func", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container);
- valid = valid && test_conversion_with_regex("\n\nsync func", "\n\n@rpc(any_peer, call_local) func", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container);
+ valid = valid && test_conversion_with_regex("\n\nremote func", "\n\n@rpc(\"any_peer\") func", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container);
+ valid = valid && test_conversion_with_regex("\n\nremotesync func", "\n\n@rpc(\"any_peer\", \"call_local\") func", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container);
+ valid = valid && test_conversion_with_regex("\n\nsync func", "\n\n@rpc(\"any_peer\", \"call_local\") func", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container);
valid = valid && test_conversion_with_regex("\n\nslave func", "\n\n@rpc func", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container);
valid = valid && test_conversion_with_regex("\n\npuppet func", "\n\n@rpc func", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container);
- valid = valid && test_conversion_with_regex("\n\npuppetsync func", "\n\n@rpc(call_local) func", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container);
+ valid = valid && test_conversion_with_regex("\n\npuppetsync func", "\n\n@rpc(\"call_local\") func", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container);
valid = valid && test_conversion_with_regex("\n\nmaster func", "\n\nThe master and mastersync rpc behavior is not officially supported anymore. Try using another keyword or making custom logic using get_multiplayer().get_remote_sender_id()\n@rpc func", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container);
- valid = valid && test_conversion_with_regex("\n\nmastersync func", "\n\nThe master and mastersync rpc behavior is not officially supported anymore. Try using another keyword or making custom logic using get_multiplayer().get_remote_sender_id()\n@rpc(call_local) func", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container);
+ valid = valid && test_conversion_with_regex("\n\nmastersync func", "\n\nThe master and mastersync rpc behavior is not officially supported anymore. Try using another keyword or making custom logic using get_multiplayer().get_remote_sender_id()\n@rpc(\"call_local\") func", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container);
valid = valid && test_conversion_gdscript_builtin("var size : Vector2 = Vector2() setget set_function , get_function", "var size : Vector2 = Vector2() : get = get_function, set = set_function", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false);
valid = valid && test_conversion_gdscript_builtin("var size : Vector2 = Vector2() setget set_function , ", "var size : Vector2 = Vector2() : set = set_function", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false);
@@ -4086,13 +4087,13 @@ void ProjectConverter3To4::rename_gdscript_keywords(Vector<String> &lines, const
line = reg_container.keyword_gdscript_onready.sub(line, "@onready", true);
}
if (line.contains("remote")) {
- line = reg_container.keyword_gdscript_remote.sub(line, "@rpc(any_peer) func", true);
+ line = reg_container.keyword_gdscript_remote.sub(line, "@rpc(\"any_peer\") func", true);
}
if (line.contains("remote")) {
- line = reg_container.keyword_gdscript_remotesync.sub(line, "@rpc(any_peer, call_local) func", true);
+ line = reg_container.keyword_gdscript_remotesync.sub(line, "@rpc(\"any_peer\", \"call_local\") func", true);
}
if (line.contains("sync")) {
- line = reg_container.keyword_gdscript_sync.sub(line, "@rpc(any_peer, call_local) func", true);
+ line = reg_container.keyword_gdscript_sync.sub(line, "@rpc(\"any_peer\", \"call_local\") func", true);
}
if (line.contains("slave")) {
line = reg_container.keyword_gdscript_slave.sub(line, "@rpc func", true);
@@ -4101,13 +4102,13 @@ void ProjectConverter3To4::rename_gdscript_keywords(Vector<String> &lines, const
line = reg_container.keyword_gdscript_puppet.sub(line, "@rpc func", true);
}
if (line.contains("puppet")) {
- line = reg_container.keyword_gdscript_puppetsync.sub(line, "@rpc(call_local) func", true);
+ line = reg_container.keyword_gdscript_puppetsync.sub(line, "@rpc(\"call_local\") func", true);
}
if (line.contains("master")) {
line = reg_container.keyword_gdscript_master.sub(line, error_message + "@rpc func", true);
}
if (line.contains("master")) {
- line = reg_container.keyword_gdscript_mastersync.sub(line, error_message + "@rpc(call_local) func", true);
+ line = reg_container.keyword_gdscript_mastersync.sub(line, error_message + "@rpc(\"call_local\") func", true);
}
}
}
@@ -4155,25 +4156,25 @@ Vector<String> ProjectConverter3To4::check_for_rename_gdscript_keywords(Vector<S
if (line.contains("remote")) {
old = line;
- line = reg_container.keyword_gdscript_remote.sub(line, "@rpc(any_peer) func", true);
+ line = reg_container.keyword_gdscript_remote.sub(line, "@rpc(\"any_peer\") func", true);
if (old != line) {
- found_renames.append(line_formatter(current_line, "remote func", "@rpc(any_peer) func", line));
+ found_renames.append(line_formatter(current_line, "remote func", "@rpc(\"any_peer\") func", line));
}
}
if (line.contains("remote")) {
old = line;
- line = reg_container.keyword_gdscript_remotesync.sub(line, "@rpc(any_peer, call_local)) func", true);
+ line = reg_container.keyword_gdscript_remotesync.sub(line, "@rpc(\"any_peer\", \"call_local\")) func", true);
if (old != line) {
- found_renames.append(line_formatter(current_line, "remotesync func", "@rpc(any_peer, call_local)) func", line));
+ found_renames.append(line_formatter(current_line, "remotesync func", "@rpc(\"any_peer\", \"call_local\")) func", line));
}
}
if (line.contains("sync")) {
old = line;
- line = reg_container.keyword_gdscript_sync.sub(line, "@rpc(any_peer, call_local)) func", true);
+ line = reg_container.keyword_gdscript_sync.sub(line, "@rpc(\"any_peer\", \"call_local\")) func", true);
if (old != line) {
- found_renames.append(line_formatter(current_line, "sync func", "@rpc(any_peer, call_local)) func", line));
+ found_renames.append(line_formatter(current_line, "sync func", "@rpc(\"any_peer\", \"call_local\")) func", line));
}
}
@@ -4195,9 +4196,9 @@ Vector<String> ProjectConverter3To4::check_for_rename_gdscript_keywords(Vector<S
if (line.contains("puppet")) {
old = line;
- line = reg_container.keyword_gdscript_puppetsync.sub(line, "@rpc(call_local) func", true);
+ line = reg_container.keyword_gdscript_puppetsync.sub(line, "@rpc(\"call_local\") func", true);
if (old != line) {
- found_renames.append(line_formatter(current_line, "puppetsync func", "@rpc(call_local) func", line));
+ found_renames.append(line_formatter(current_line, "puppetsync func", "@rpc(\"call_local\") func", line));
}
}
@@ -4211,9 +4212,9 @@ Vector<String> ProjectConverter3To4::check_for_rename_gdscript_keywords(Vector<S
if (line.contains("master")) {
old = line;
- line = reg_container.keyword_gdscript_master.sub(line, "@rpc(call_local) func", true);
+ line = reg_container.keyword_gdscript_master.sub(line, "@rpc(\"call_local\") func", true);
if (old != line) {
- found_renames.append(line_formatter(current_line, "mastersync func", "@rpc(call_local) func", line));
+ found_renames.append(line_formatter(current_line, "mastersync func", "@rpc(\"call_local\") func", line));
}
}
}
diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp
index 5d1a2a49c5..86e77fbbbe 100644
--- a/editor/scene_tree_dock.cpp
+++ b/editor/scene_tree_dock.cpp
@@ -2191,7 +2191,7 @@ void SceneTreeDock::_do_create(Node *p_parent) {
ERR_FAIL_COND(!child);
String new_name = p_parent->validate_child_name(child);
- if (GLOBAL_GET("editor/node_naming/name_casing").operator int() != NAME_CASING_PASCAL_CASE) {
+ if (GLOBAL_GET("editor/naming/node_name_casing").operator int() != NAME_CASING_PASCAL_CASE) {
new_name = adjust_name_casing(new_name);
}
child->set_name(new_name);
@@ -3613,7 +3613,7 @@ SceneTreeDock::SceneTreeDock(Node *p_scene_root, EditorSelection *p_editor_selec
scene_tree->connect("script_dropped", callable_mp(this, &SceneTreeDock::_script_dropped));
scene_tree->connect("nodes_dragged", callable_mp(this, &SceneTreeDock::_nodes_drag_begin));
- scene_tree->get_scene_tree()->connect("item_double_clicked", callable_mp(this, &SceneTreeDock::_focus_node));
+ scene_tree->get_scene_tree()->connect("item_icon_double_clicked", callable_mp(this, &SceneTreeDock::_focus_node));
editor_selection->connect("selection_changed", callable_mp(this, &SceneTreeDock::_selection_changed));
diff --git a/editor/scene_tree_editor.cpp b/editor/scene_tree_editor.cpp
index e795cc919c..42801cdaf1 100644
--- a/editor/scene_tree_editor.cpp
+++ b/editor/scene_tree_editor.cpp
@@ -971,7 +971,7 @@ void SceneTreeEditor::_renamed() {
String raw_new_name = which->get_text(0);
if (raw_new_name.strip_edges().is_empty()) {
// If name is empty, fallback to class name.
- if (GLOBAL_GET("editor/node_naming/name_casing").operator int() != NAME_CASING_PASCAL_CASE) {
+ if (GLOBAL_GET("editor/naming/node_name_casing").operator int() != NAME_CASING_PASCAL_CASE) {
raw_new_name = Node::adjust_name_casing(n->get_class());
} else {
raw_new_name = n->get_class();