summaryrefslogtreecommitdiff
path: root/editor
diff options
context:
space:
mode:
Diffstat (limited to 'editor')
-rw-r--r--editor/action_map_editor.cpp15
-rw-r--r--editor/action_map_editor.h3
-rw-r--r--editor/animation_track_editor.cpp50
-rw-r--r--editor/animation_track_editor.h5
-rw-r--r--editor/code_editor.cpp4
-rw-r--r--editor/connections_dialog.cpp231
-rw-r--r--editor/connections_dialog.h19
-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/doc_tools.cpp15
-rw-r--r--editor/editor_file_system.cpp5
-rw-r--r--editor/editor_inspector.h8
-rw-r--r--editor/editor_node.cpp23
-rw-r--r--editor/editor_node.h1
-rw-r--r--editor/editor_properties.cpp3
-rw-r--r--editor/editor_properties_array_dict.cpp158
-rw-r--r--editor/editor_properties_array_dict.h2
-rw-r--r--editor/editor_property_name_processor.cpp1
-rw-r--r--editor/editor_run.cpp4
-rw-r--r--editor/editor_settings.cpp9
-rw-r--r--editor/editor_themes.cpp31
-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.cpp14
-rw-r--r--editor/export/editor_export_platform.cpp29
-rw-r--r--editor/export/editor_export_platform.h1
-rw-r--r--editor/icons/UseBlendDisable.svg1
-rw-r--r--editor/icons/UseBlendEnable.svg1
-rw-r--r--editor/import/resource_importer_layered_texture.cpp124
-rw-r--r--editor/import/resource_importer_layered_texture.h2
-rw-r--r--editor/import/resource_importer_scene.cpp14
-rw-r--r--editor/import/resource_importer_scene.h18
-rw-r--r--editor/import/resource_importer_texture.cpp130
-rw-r--r--editor/import/scene_import_settings.cpp2
-rw-r--r--editor/input_event_configuration_dialog.cpp8
-rw-r--r--editor/plugins/animation_blend_space_1d_editor.cpp16
-rw-r--r--editor/plugins/animation_blend_space_1d_editor.h2
-rw-r--r--editor/plugins/animation_player_editor_plugin.cpp29
-rw-r--r--editor/plugins/animation_state_machine_editor.cpp7
-rw-r--r--editor/plugins/animation_tree_editor_plugin.cpp13
-rw-r--r--editor/plugins/canvas_item_editor_plugin.cpp2
-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/node_3d_editor_plugin.cpp12
-rw-r--r--editor/plugins/script_text_editor.cpp6
-rw-r--r--editor/plugins/sprite_frames_editor_plugin.cpp561
-rw-r--r--editor/plugins/sprite_frames_editor_plugin.h51
-rw-r--r--editor/plugins/text_shader_editor.cpp5
-rw-r--r--editor/plugins/texture_region_editor_plugin.cpp3
-rw-r--r--editor/plugins/tiles/tile_atlas_view.cpp29
-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.cpp11
-rw-r--r--editor/plugins/tiles/tile_map_editor.h3
-rw-r--r--editor/plugins/tiles/tile_set_atlas_source_editor.cpp26
-rw-r--r--editor/plugins/tiles/tiles_editor_plugin.cpp2
-rw-r--r--editor/progress_dialog.cpp1
-rw-r--r--editor/project_converter_3_to_4.cpp111
-rw-r--r--editor/project_converter_3_to_4.h16
-rw-r--r--editor/project_settings_editor.cpp14
64 files changed, 1368 insertions, 759 deletions
diff --git a/editor/action_map_editor.cpp b/editor/action_map_editor.cpp
index ae54c20fe2..146b5a794c 100644
--- a/editor/action_map_editor.cpp
+++ b/editor/action_map_editor.cpp
@@ -198,6 +198,14 @@ void ActionMapEditor::_tree_button_pressed(Object *p_item, int p_column, int p_i
emit_signal(SNAME("action_edited"), action_name, action);
} break;
+ case ActionMapEditor::BUTTON_REVERT_ACTION: {
+ ERR_FAIL_COND_MSG(!item->has_meta("__action_initial"), "Tree Item for action which can be reverted is expected to have meta value with initial value of action.");
+
+ Dictionary action = item->get_meta("__action_initial").duplicate();
+ String action_name = item->get_meta("__name");
+
+ emit_signal(SNAME("action_edited"), action_name, action);
+ } break;
default:
break;
}
@@ -427,6 +435,13 @@ void ActionMapEditor::update_action_list(const Vector<ActionInfo> &p_action_info
action_item->set_range(1, deadzone);
// Third column - buttons
+ if (action_info.has_initial) {
+ bool deadzone_eq = action_info.action_initial["deadzone"] == action_info.action["deadzone"];
+ bool events_eq = Shortcut::is_event_array_equal(action_info.action_initial["events"], action_info.action["events"]);
+ bool action_eq = deadzone_eq && events_eq;
+ action_item->set_meta("__action_initial", action_info.action_initial);
+ action_item->add_button(2, action_tree->get_theme_icon(SNAME("ReloadSmall"), SNAME("EditorIcons")), BUTTON_REVERT_ACTION, action_eq, action_eq ? TTR("Cannot Revert - Action is same as initial") : TTR("Revert Action"));
+ }
action_item->add_button(2, action_tree->get_theme_icon(SNAME("Add"), SNAME("EditorIcons")), BUTTON_ADD_EVENT, false, TTR("Add Event"));
action_item->add_button(2, action_tree->get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")), BUTTON_REMOVE_ACTION, !action_info.editable, action_info.editable ? TTR("Remove Action") : TTR("Cannot Remove Action"));
diff --git a/editor/action_map_editor.h b/editor/action_map_editor.h
index 433a72a807..2848d23e83 100644
--- a/editor/action_map_editor.h
+++ b/editor/action_map_editor.h
@@ -49,6 +49,8 @@ public:
struct ActionInfo {
String name;
Dictionary action;
+ bool has_initial = false;
+ Dictionary action_initial;
Ref<Texture2D> icon = Ref<Texture2D>();
bool editable = true;
@@ -60,6 +62,7 @@ private:
BUTTON_EDIT_EVENT,
BUTTON_REMOVE_ACTION,
BUTTON_REMOVE_EVENT,
+ BUTTON_REVERT_ACTION,
};
Vector<ActionInfo> actions_cache;
diff --git a/editor/animation_track_editor.cpp b/editor/animation_track_editor.cpp
index 338a22c070..8dd087451c 100644
--- a/editor/animation_track_editor.cpp
+++ b/editor/animation_track_editor.cpp
@@ -1954,6 +1954,10 @@ void AnimationTrackEdit::_notification(int p_what) {
get_theme_icon(SNAME("TrackDiscrete"), SNAME("EditorIcons")),
get_theme_icon(SNAME("TrackCapture"), SNAME("EditorIcons"))
};
+ Ref<Texture2D> blend_icon[2] = {
+ get_theme_icon(SNAME("UseBlendEnable"), SNAME("EditorIcons")),
+ get_theme_icon(SNAME("UseBlendDisable"), SNAME("EditorIcons")),
+ };
int ofs = get_size().width - timeline->get_buttons_width();
@@ -1982,6 +1986,11 @@ void AnimationTrackEdit::_notification(int p_what) {
if (!animation->track_is_compressed(track) && animation->track_get_type(track) == Animation::TYPE_VALUE) {
draw_texture(update_icon, update_mode_rect.position);
}
+ if (animation->track_get_type(track) == Animation::TYPE_AUDIO) {
+ Ref<Texture2D> use_blend_icon = blend_icon[animation->audio_track_is_use_blend(track) ? 0 : 1];
+ Vector2 use_blend_icon_pos = update_mode_rect.position + (update_mode_rect.size - use_blend_icon->get_size()) / 2;
+ draw_texture(use_blend_icon, use_blend_icon_pos);
+ }
// Make it easier to click.
update_mode_rect.position.y = 0;
update_mode_rect.size.y = get_size().height;
@@ -1990,13 +1999,12 @@ void AnimationTrackEdit::_notification(int p_what) {
update_mode_rect.size.x += hsep / 2;
if (!read_only) {
- if (animation->track_get_type(track) == Animation::TYPE_VALUE) {
+ if (animation->track_get_type(track) == Animation::TYPE_VALUE || animation->track_get_type(track) == Animation::TYPE_AUDIO) {
draw_texture(down_icon, Vector2(ofs, int(get_size().height - down_icon->get_height()) / 2));
update_mode_rect.size.x += down_icon->get_width();
} else if (animation->track_get_type(track) == Animation::TYPE_BEZIER) {
Ref<Texture2D> bezier_icon = get_theme_icon(SNAME("EditBezier"), SNAME("EditorIcons"));
update_mode_rect.size.x += down_icon->get_width();
-
update_mode_rect = Rect2();
} else {
update_mode_rect = Rect2();
@@ -2439,7 +2447,11 @@ String AnimationTrackEdit::get_tooltip(const Point2 &p_pos) const {
}
if (update_mode_rect.has_point(p_pos)) {
- return TTR("Update Mode (How this property is set)");
+ if (animation->track_get_type(track) == Animation::TYPE_AUDIO) {
+ return TTR("Use Blend");
+ } else {
+ return TTR("Update Mode (How this property is set)");
+ }
}
if (interp_mode_rect.has_point(p_pos)) {
@@ -2641,9 +2653,14 @@ void AnimationTrackEdit::gui_input(const Ref<InputEvent> &p_event) {
menu->connect("id_pressed", callable_mp(this, &AnimationTrackEdit::_menu_selected));
}
menu->clear();
- menu->add_icon_item(get_theme_icon(SNAME("TrackContinuous"), SNAME("EditorIcons")), TTR("Continuous"), MENU_CALL_MODE_CONTINUOUS);
- menu->add_icon_item(get_theme_icon(SNAME("TrackDiscrete"), SNAME("EditorIcons")), TTR("Discrete"), MENU_CALL_MODE_DISCRETE);
- menu->add_icon_item(get_theme_icon(SNAME("TrackCapture"), SNAME("EditorIcons")), TTR("Capture"), MENU_CALL_MODE_CAPTURE);
+ if (animation->track_get_type(track) == Animation::TYPE_AUDIO) {
+ menu->add_icon_item(get_theme_icon(SNAME("UseBlendEnable"), SNAME("EditorIcons")), TTR("Use Blend"), MENU_USE_BLEND_ENABLED);
+ menu->add_icon_item(get_theme_icon(SNAME("UseBlendDisable"), SNAME("EditorIcons")), TTR("Don't Use Blend"), MENU_USE_BLEND_DISABLED);
+ } else {
+ menu->add_icon_item(get_theme_icon(SNAME("TrackContinuous"), SNAME("EditorIcons")), TTR("Continuous"), MENU_CALL_MODE_CONTINUOUS);
+ menu->add_icon_item(get_theme_icon(SNAME("TrackDiscrete"), SNAME("EditorIcons")), TTR("Discrete"), MENU_CALL_MODE_DISCRETE);
+ menu->add_icon_item(get_theme_icon(SNAME("TrackCapture"), SNAME("EditorIcons")), TTR("Capture"), MENU_CALL_MODE_CAPTURE);
+ }
menu->reset_size();
Vector2 popup_pos = get_screen_position() + update_mode_rect.position + Vector2(0, update_mode_rect.size.height);
@@ -2662,7 +2679,7 @@ void AnimationTrackEdit::gui_input(const Ref<InputEvent> &p_event) {
menu->add_icon_item(get_theme_icon(SNAME("InterpRaw"), SNAME("EditorIcons")), TTR("Nearest"), MENU_INTERPOLATION_NEAREST);
menu->add_icon_item(get_theme_icon(SNAME("InterpLinear"), SNAME("EditorIcons")), TTR("Linear"), MENU_INTERPOLATION_LINEAR);
menu->add_icon_item(get_theme_icon(SNAME("InterpCubic"), SNAME("EditorIcons")), TTR("Cubic"), MENU_INTERPOLATION_CUBIC);
- // Check is angle property.
+ // Check whether it is angle property.
AnimationPlayerEditor *ape = AnimationPlayerEditor::get_singleton();
if (ape) {
AnimationPlayer *ap = ape->get_player();
@@ -3055,6 +3072,16 @@ void AnimationTrackEdit::_menu_selected(int p_index) {
emit_signal(SNAME("delete_request"));
} break;
+ case MENU_USE_BLEND_ENABLED:
+ case MENU_USE_BLEND_DISABLED: {
+ bool use_blend = p_index == MENU_USE_BLEND_ENABLED;
+ EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
+ undo_redo->create_action(TTR("Change Animation Use Blend"));
+ undo_redo->add_do_method(animation.ptr(), "audio_track_set_use_blend", track, use_blend);
+ undo_redo->add_undo_method(animation.ptr(), "audio_track_set_use_blend", track, animation->audio_track_is_use_blend(track));
+ undo_redo->commit_action();
+ queue_redraw();
+ } break;
}
}
@@ -3488,6 +3515,9 @@ void AnimationTrackEditor::_animation_track_remove_request(int p_track, Ref<Anim
if (p_from_animation->track_get_type(idx) == Animation::TYPE_VALUE) {
undo_redo->add_undo_method(p_from_animation.ptr(), "value_track_set_update_mode", idx, p_from_animation->value_track_get_update_mode(idx));
}
+ if (animation->track_get_type(idx) == Animation::TYPE_AUDIO) {
+ undo_redo->add_undo_method(animation.ptr(), "audio_track_set_use_blend", idx, animation->audio_track_is_use_blend(idx));
+ }
undo_redo->commit_action();
}
@@ -5618,6 +5648,9 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) {
if (tc.track_type == Animation::TYPE_VALUE) {
tc.update_mode = animation->value_track_get_update_mode(idx);
}
+ if (tc.track_type == Animation::TYPE_AUDIO) {
+ tc.use_blend = animation->audio_track_is_use_blend(idx);
+ }
tc.loop_wrap = animation->track_get_interpolation_loop_wrap(idx);
tc.enabled = animation->track_is_enabled(idx);
for (int i = 0; i < animation->track_get_key_count(idx); i++) {
@@ -5662,6 +5695,9 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) {
if (track_clipboard[i].track_type == Animation::TYPE_VALUE) {
undo_redo->add_do_method(animation.ptr(), "value_track_set_update_mode", base_track, track_clipboard[i].update_mode);
}
+ if (track_clipboard[i].track_type == Animation::TYPE_AUDIO) {
+ undo_redo->add_do_method(animation.ptr(), "audio_track_set_use_blend", base_track, track_clipboard[i].use_blend);
+ }
for (int j = 0; j < track_clipboard[i].keys.size(); j++) {
undo_redo->add_do_method(animation.ptr(), "track_insert_key", base_track, track_clipboard[i].keys[j].time, track_clipboard[i].keys[j].value, track_clipboard[i].keys[j].transition);
diff --git a/editor/animation_track_editor.h b/editor/animation_track_editor.h
index 8506d9b80d..2a59bda2a4 100644
--- a/editor/animation_track_editor.h
+++ b/editor/animation_track_editor.h
@@ -220,7 +220,9 @@ class AnimationTrackEdit : public Control {
MENU_KEY_INSERT,
MENU_KEY_DUPLICATE,
MENU_KEY_ADD_RESET,
- MENU_KEY_DELETE
+ MENU_KEY_DELETE,
+ MENU_USE_BLEND_ENABLED,
+ MENU_USE_BLEND_DISABLED,
};
AnimationTimelineEdit *timeline = nullptr;
@@ -566,6 +568,7 @@ class AnimationTrackEditor : public VBoxContainer {
Animation::LoopMode loop_mode = Animation::LOOP_PINGPONG;
bool loop_wrap = false;
bool enabled = false;
+ bool use_blend = false;
struct Key {
float time = 0;
diff --git a/editor/code_editor.cpp b/editor/code_editor.cpp
index 644735a4d8..28d687488c 100644
--- a/editor/code_editor.cpp
+++ b/editor/code_editor.cpp
@@ -143,7 +143,9 @@ void FindReplaceBar::unhandled_input(const Ref<InputEvent> &p_event) {
}
bool FindReplaceBar::_search(uint32_t p_flags, int p_from_line, int p_from_col) {
- text_editor->remove_secondary_carets();
+ if (!preserve_cursor) {
+ text_editor->remove_secondary_carets();
+ }
String text = get_search_text();
Point2i pos = text_editor->search(text, p_flags, p_from_line, p_from_col);
diff --git a/editor/connections_dialog.cpp b/editor/connections_dialog.cpp
index db12dbc72b..aaa07e98c8 100644
--- a/editor/connections_dialog.cpp
+++ b/editor/connections_dialog.cpp
@@ -186,7 +186,7 @@ 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));
+ dst_method->set_text(selected_item->get_metadata(0));
}
/*
@@ -260,12 +260,8 @@ StringName ConnectDialog::generate_method_callback_name(Node *p_source, String p
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"));
- }
+ method_item->set_text(0, get_signature(mi));
+ method_item->set_metadata(0, mi.name);
}
}
@@ -293,6 +289,11 @@ List<MethodInfo> ConnectDialog::_filter_method_list(const List<MethodInfo> &p_me
type_mismatch = true;
break;
}
+
+ if (stype == Variant::OBJECT && mtype == Variant::OBJECT && E->get().class_name != F->get().class_name) {
+ type_mismatch = true;
+ break;
+ }
}
if (type_mismatch) {
@@ -350,10 +351,11 @@ void ConnectDialog::_update_method_tree() {
}
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.
+ // Get methods from each class in the hierarchy.
StringName current_class = target->get_class_name();
do {
TreeItem *class_item = method_tree->create_item(root_item);
@@ -376,6 +378,8 @@ void ConnectDialog::_update_method_tree() {
}
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) {
@@ -432,6 +436,7 @@ void ConnectDialog::_notification(int p_what) {
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;
}
}
@@ -444,10 +449,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;
}
@@ -476,6 +489,34 @@ Vector<Variant> ConnectDialog::get_binds() const {
return cdbinds->params;
}
+String ConnectDialog::get_signature(const MethodInfo &p_method, PackedStringArray *r_arg_names) {
+ PackedStringArray signature;
+ signature.append(p_method.name);
+ signature.append("(");
+
+ for (int i = 0; i < p_method.arguments.size(); i++) {
+ if (i > 0) {
+ signature.append(", ");
+ }
+
+ const PropertyInfo &pi = p_method.arguments[i];
+ String tname = "var";
+ if (pi.type == Variant::OBJECT && pi.class_name != StringName()) {
+ tname = pi.class_name.operator String();
+ } else if (pi.type != Variant::NIL) {
+ tname = Variant::get_type_name(pi.type);
+ }
+
+ signature.append((pi.name.is_empty() ? String("arg " + itos(i)) : pi.name) + ": " + tname);
+ if (r_arg_names) {
+ r_arg_names->push_back(pi.name + ":" + tname);
+ }
+ }
+
+ signature.append(")");
+ return String().join(signature);
+}
+
bool ConnectDialog::get_deferred() const {
return deferred->is_pressed();
}
@@ -496,11 +537,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);
@@ -518,22 +560,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);
@@ -543,9 +570,11 @@ 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) {
+void ConnectDialog::popup_dialog(const String p_for_signal) {
from_signal->set_text(p_for_signal);
error_label->add_theme_color_override("font_color", error_label->get_theme_color(SNAME("error_color"), SNAME("Editor")));
if (!advanced->is_pressed()) {
@@ -597,18 +626,9 @@ ConnectDialog::ConnectDialog() {
main_hb->add_child(vbc_left);
vbc_left->set_h_size_flags(Control::SIZE_EXPAND_FILL);
- HBoxContainer *from_signal_hb = memnew(HBoxContainer);
-
from_signal = memnew(LineEdit);
+ vbc_left->add_margin_child(TTR("From Signal:"), from_signal);
from_signal->set_editable(false);
- from_signal->set_h_size_flags(Control::SIZE_EXPAND_FILL);
- from_signal_hb->add_child(from_signal);
-
- advanced = memnew(CheckButton(TTR("Advanced")));
- from_signal_hb->add_child(advanced);
- advanced->connect("pressed", callable_mp(this, &ConnectDialog::_advanced_pressed));
-
- vbc_left->add_margin_child(TTR("From Signal:"), from_signal_hb);
tree = memnew(SceneTreeEditor(false));
tree->set_connecting_signal(true);
@@ -646,6 +666,10 @@ ConnectDialog::ConnectDialog() {
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);
@@ -712,15 +736,13 @@ ConnectDialog::ConnectDialog() {
dst_method->connect("text_submitted", callable_mp(this, &ConnectDialog::_text_submitted));
hbc_method->add_child(dst_method);
- Button *open_tree_button = memnew(Button);
- open_tree_button->set_flat(false);
- open_tree_button->set_text("...");
- open_tree_button->connect("pressed", callable_mp(this, &ConnectDialog::_open_method_popup));
- hbc_method->add_child(open_tree_button);
+ 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));
@@ -797,9 +819,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);
@@ -837,27 +856,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();
}
@@ -868,7 +881,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);
@@ -892,18 +905,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.
@@ -933,7 +943,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();
}
@@ -987,8 +997,9 @@ 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"];
- const String &signal_name_ref = signal_name;
+ Dictionary sinfo = p_item.get_metadata(0);
+ String signal_name = sinfo["name"];
+ PackedStringArray signal_args = sinfo["args"];
Node *dst_node = selected_node->get_owner() ? selected_node->get_owner() : selected_node;
if (!dst_node || dst_node->get_script().is_null()) {
@@ -997,26 +1008,34 @@ void ConnectionsDock::_open_connection_dialog(TreeItem &p_item) {
ConnectDialog::ConnectionData cd;
cd.source = selected_node;
- cd.signal = StringName(signal_name_ref);
+ cd.signal = StringName(signal_name);
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->popup_dialog(signal_name + "(" + String(", ").join(signal_args) + ")");
+ 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);
}
}
@@ -1091,14 +1110,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;
}
@@ -1149,7 +1168,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();
}
}
@@ -1177,6 +1197,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) {
@@ -1238,37 +1262,22 @@ void ConnectionsDock::update_tree() {
}
for (MethodInfo &mi : node_signals2) {
- StringName signal_name = mi.name;
- String signaldesc = "(";
- PackedStringArray argnames;
-
- String filter_text = search_box->get_text();
- if (!filter_text.is_subsequence_ofn(signal_name)) {
+ const StringName signal_name = mi.name;
+ if (!search_box->get_text().is_subsequence_ofn(signal_name)) {
continue;
}
+ PackedStringArray argnames;
- if (mi.arguments.size()) {
- for (int i = 0; i < mi.arguments.size(); i++) {
- PropertyInfo &pi = mi.arguments[i];
+ // Create the children of the subsection - the actual list of signals.
+ TreeItem *signal_item = tree->create_item(section_item);
+ String signame = connect_dialog->get_signature(mi, &argnames);
+ signal_item->set_text(0, signame);
- if (i > 0) {
- signaldesc += ", ";
- }
- String tname = "var";
- if (pi.type == Variant::OBJECT && pi.class_name != StringName()) {
- tname = pi.class_name.operator String();
- } else if (pi.type != Variant::NIL) {
- tname = Variant::get_type_name(pi.type);
- }
- signaldesc += (pi.name.is_empty() ? String("arg " + itos(i)) : pi.name) + ": " + tname;
- argnames.push_back(pi.name + ":" + tname);
- }
+ if (signame == prev_selected) {
+ signal_item->select(0);
+ prev_selected = "";
}
- signaldesc += ")";
- // 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);
Dictionary sinfo;
sinfo["name"] = signal_name;
sinfo["args"] = argnames;
@@ -1309,7 +1318,7 @@ void ConnectionsDock::update_tree() {
}
// "::" separators used in make_custom_tooltip for formatting.
- signal_item->set_tooltip_text(0, String(signal_name) + "::" + signaldesc + "::" + descr);
+ signal_item->set_tooltip_text(0, String(signal_name) + "::" + signame.trim_prefix(mi.name) + "::" + descr);
}
// List existing connections.
diff --git a/editor/connections_dialog.h b/editor/connections_dialog.h
index 0bea897976..277ea03cf7 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,7 +107,9 @@ 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;
@@ -117,8 +119,10 @@ private:
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;
@@ -159,21 +163,24 @@ 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;
void set_dst_method(const StringName &p_method);
int get_unbinds() const;
Vector<Variant> get_binds() const;
+ String get_signature(const MethodInfo &p_method, PackedStringArray *r_arg_names = nullptr);
bool get_deferred() const;
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);
+ void popup_dialog(const String p_for_signal);
ConnectDialog();
~ConnectDialog();
};
@@ -217,8 +224,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();
@@ -227,7 +234,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..32952a367d 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) + " " + oe.error + "\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/doc_tools.cpp b/editor/doc_tools.cpp
index 5bdef32c60..d71ef78d88 100644
--- a/editor/doc_tools.cpp
+++ b/editor/doc_tools.cpp
@@ -461,7 +461,7 @@ void DocTools::generate(bool p_basic_types) {
}
if (default_value_valid && default_value.get_type() != Variant::OBJECT) {
- prop.default_value = default_value.get_construct_string().replace("\n", " ");
+ prop.default_value = DocData::get_default_value_string(default_value);
}
StringName setter = ClassDB::get_property_setter(name, E.name);
@@ -591,7 +591,7 @@ void DocTools::generate(bool p_basic_types) {
tid.name = E;
tid.type = "Color";
tid.data_type = "color";
- tid.default_value = Variant(ThemeDB::get_singleton()->get_default_theme()->get_color(E, cname)).get_construct_string().replace("\n", " ");
+ tid.default_value = DocData::get_default_value_string(ThemeDB::get_singleton()->get_default_theme()->get_color(E, cname));
c.theme_properties.push_back(tid);
}
@@ -772,8 +772,7 @@ void DocTools::generate(bool p_basic_types) {
int darg_idx = mi.default_arguments.size() - mi.arguments.size() + j;
if (darg_idx >= 0) {
- Variant default_arg = mi.default_arguments[darg_idx];
- ad.default_value = default_arg.get_construct_string().replace("\n", " ");
+ ad.default_value = DocData::get_default_value_string(mi.default_arguments[darg_idx]);
}
method.arguments.push_back(ad);
@@ -817,7 +816,7 @@ void DocTools::generate(bool p_basic_types) {
DocData::PropertyDoc property;
property.name = pi.name;
property.type = Variant::get_type_name(pi.type);
- property.default_value = v.get(pi.name).get_construct_string().replace("\n", " ");
+ property.default_value = DocData::get_default_value_string(v.get(pi.name));
c.properties.push_back(property);
}
@@ -948,8 +947,7 @@ void DocTools::generate(bool p_basic_types) {
int darg_idx = j - (mi.arguments.size() - mi.default_arguments.size());
if (darg_idx >= 0) {
- Variant default_arg = mi.default_arguments[darg_idx];
- ad.default_value = default_arg.get_construct_string().replace("\n", " ");
+ ad.default_value = DocData::get_default_value_string(mi.default_arguments[darg_idx]);
}
md.arguments.push_back(ad);
@@ -993,8 +991,7 @@ void DocTools::generate(bool p_basic_types) {
int darg_idx = j - (ai.arguments.size() - ai.default_arguments.size());
if (darg_idx >= 0) {
- Variant default_arg = ai.default_arguments[darg_idx];
- ad.default_value = default_arg.get_construct_string().replace("\n", " ");
+ ad.default_value = DocData::get_default_value_string(ai.default_arguments[darg_idx]);
}
atd.arguments.push_back(ad);
diff --git a/editor/editor_file_system.cpp b/editor/editor_file_system.cpp
index ef33b82390..644c32e8a4 100644
--- a/editor/editor_file_system.cpp
+++ b/editor/editor_file_system.cpp
@@ -1591,6 +1591,11 @@ void EditorFileSystem::_update_script_classes() {
void EditorFileSystem::_update_pending_script_classes() {
if (!update_script_paths.is_empty()) {
_update_script_classes();
+ } else {
+ // In case the class cache file was removed somehow, regenerate it.
+ if (!FileAccess::exists(ScriptServer::get_global_class_cache_file_path())) {
+ ScriptServer::save_global_classes();
+ }
}
}
diff --git a/editor/editor_inspector.h b/editor/editor_inspector.h
index 1690302e6e..6a1c77d376 100644
--- a/editor/editor_inspector.h
+++ b/editor/editor_inspector.h
@@ -47,11 +47,7 @@ class TextureRect;
class EditorPropertyRevert {
public:
- static bool get_instantiated_node_original_property(Node *p_node, const StringName &p_prop, Variant &value, bool p_check_class_default = true);
- static bool is_node_property_different(Node *p_node, const Variant &p_current, const Variant &p_orig);
- static bool is_property_value_different(const Variant &p_a, const Variant &p_b);
static Variant get_property_revert_value(Object *p_object, const StringName &p_property, bool *r_is_valid);
-
static bool can_property_revert(Object *p_object, const StringName &p_property, const Variant *p_custom_current_value = nullptr);
};
@@ -331,7 +327,7 @@ class EditorInspectorArray : public EditorInspectorSection {
AcceptDialog *resize_dialog = nullptr;
SpinBox *new_size_spin_box = nullptr;
- // Pagination
+ // Pagination.
int page_length = 5;
int page = 0;
int max_page = 0;
@@ -495,7 +491,7 @@ class EditorInspector : public ScrollContainer {
HashMap<ObjectID, int> scroll_cache;
- String property_prefix; //used for sectioned inspector
+ String property_prefix; // Used for sectioned inspector.
String object_class;
Variant property_clipboard;
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp
index 173cbc6893..0405749147 100644
--- a/editor/editor_node.cpp
+++ b/editor/editor_node.cpp
@@ -581,6 +581,7 @@ void EditorNode::_notification(int p_what) {
ResourceImporterTexture::get_singleton()->update_imports();
+ bottom_panel_updating = false;
} break;
case NOTIFICATION_ENTER_TREE: {
@@ -643,7 +644,7 @@ void EditorNode::_notification(int p_what) {
}
RenderingServer::get_singleton()->viewport_set_disable_2d(get_scene_root()->get_viewport_rid(), true);
- RenderingServer::get_singleton()->viewport_set_disable_environment(get_viewport()->get_viewport_rid(), true);
+ RenderingServer::get_singleton()->viewport_set_environment_mode(get_viewport()->get_viewport_rid(), RenderingServer::VIEWPORT_ENVIRONMENT_DISABLED);
feature_profile_manager->notify_changed();
@@ -2096,14 +2097,25 @@ void EditorNode::edit_item(Object *p_object, Object *p_editing_owner) {
if (!item_plugins.is_empty()) {
ObjectID owner_id = p_editing_owner->get_instance_id();
+ List<EditorPlugin *> to_remove;
for (EditorPlugin *plugin : active_plugins[owner_id]) {
if (!item_plugins.has(plugin)) {
+ // Remove plugins no longer used by this editing owner.
+ to_remove.push_back(plugin);
plugin->make_visible(false);
plugin->edit(nullptr);
}
}
+ for (EditorPlugin *plugin : to_remove) {
+ active_plugins[owner_id].erase(plugin);
+ }
+
for (EditorPlugin *plugin : item_plugins) {
+ if (active_plugins[owner_id].has(plugin)) {
+ continue;
+ }
+
for (KeyValue<ObjectID, HashSet<EditorPlugin *>> &kv : active_plugins) {
if (kv.key != owner_id) {
EditorPropertyResource *epres = Object::cast_to<EditorPropertyResource>(ObjectDB::get_instance(kv.key));
@@ -5590,12 +5602,16 @@ void EditorNode::remove_bottom_panel_item(Control *p_item) {
}
void EditorNode::_bottom_panel_switch(bool p_enable, int p_idx) {
+ if (bottom_panel_updating) {
+ return;
+ }
ERR_FAIL_INDEX(p_idx, bottom_panel_items.size());
if (bottom_panel_items[p_idx].control->is_visible() == p_enable) {
return;
}
+ bottom_panel_updating = true;
if (p_enable) {
for (int i = 0; i < bottom_panel_items.size(); i++) {
bottom_panel_items[i].button->set_pressed(i == p_idx);
@@ -6195,7 +6211,7 @@ void EditorNode::reload_instances_with_path_in_edited_scenes(const String &p_ins
List<PropertyInfo> pinfo;
modifiable_node->get_property_list(&pinfo);
- // Get names of all valid property names (TODO: make this more efficent).
+ // Get names of all valid property names (TODO: make this more efficient).
List<String> property_names;
for (const PropertyInfo &E2 : pinfo) {
if (E2.usage & PROPERTY_USAGE_STORAGE) {
@@ -6213,7 +6229,7 @@ void EditorNode::reload_instances_with_path_in_edited_scenes(const String &p_ins
for (const ConnectionWithNodePath &E2 : E.value.connections_to) {
Connection conn = E2.connection;
- // Get the node the callable is targetting.
+ // Get the node the callable is targeting.
Node *target_node = cast_to<Node>(conn.callable.get_object());
// If the callable object no longer exists or is marked for deletion,
@@ -7262,6 +7278,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_node.h b/editor/editor_node.h
index bb10abb589..3967f64c6b 100644
--- a/editor/editor_node.h
+++ b/editor/editor_node.h
@@ -460,6 +460,7 @@ private:
EditorToaster *editor_toaster = nullptr;
LinkButton *version_btn = nullptr;
Button *bottom_panel_raise = nullptr;
+ bool bottom_panel_updating = false;
Tree *disk_changed_list = nullptr;
ConfirmationDialog *disk_changed = nullptr;
diff --git a/editor/editor_properties.cpp b/editor/editor_properties.cpp
index 152e77acb7..f022027e65 100644
--- a/editor/editor_properties.cpp
+++ b/editor/editor_properties.cpp
@@ -1323,10 +1323,12 @@ void EditorPropertyObjectID::update_property() {
ObjectID id = get_edited_object()->get(get_edited_property());
if (id.is_valid()) {
edit->set_text(type + " ID: " + uitos(id));
+ edit->set_tooltip_text(type + " ID: " + uitos(id));
edit->set_disabled(false);
edit->set_icon(EditorNode::get_singleton()->get_class_icon(type));
} else {
edit->set_text(TTR("<empty>"));
+ edit->set_tooltip_text("");
edit->set_disabled(true);
edit->set_icon(Ref<Texture2D>());
}
@@ -1343,6 +1345,7 @@ EditorPropertyObjectID::EditorPropertyObjectID() {
edit = memnew(Button);
add_child(edit);
add_focusable(edit);
+ edit->set_text_overrun_behavior(TextServer::OVERRUN_TRIM_ELLIPSIS);
edit->connect("pressed", callable_mp(this, &EditorPropertyObjectID::_edit_pressed));
}
diff --git a/editor/editor_properties_array_dict.cpp b/editor/editor_properties_array_dict.cpp
index 28c0b047d8..b96ac9dbcb 100644
--- a/editor/editor_properties_array_dict.cpp
+++ b/editor/editor_properties_array_dict.cpp
@@ -158,17 +158,32 @@ EditorPropertyDictionaryObject::EditorPropertyDictionaryObject() {
///////////////////// ARRAY ///////////////////////////
+void EditorPropertyArray::initialize_array(Variant &p_array) {
+ if (array_type == Variant::ARRAY && subtype != Variant::NIL) {
+ Array array;
+ StringName subtype_class;
+ Ref<Script> subtype_script;
+ if (subtype == Variant::OBJECT && !subtype_hint_string.is_empty()) {
+ if (ClassDB::class_exists(subtype_hint_string)) {
+ subtype_class = subtype_hint_string;
+ }
+ }
+ array.set_typed(subtype, subtype_class, subtype_script);
+ p_array = array;
+ } else {
+ VariantInternal::initialize(&p_array, array_type);
+ }
+}
+
void EditorPropertyArray::_property_changed(const String &p_property, Variant p_value, const String &p_name, bool p_changing) {
if (p_property.begins_with("indices")) {
int index = p_property.get_slice("/", 1).to_int();
- Variant array = object->get_array();
+
+ Variant array = object->get_array().duplicate();
array.set(index, p_value);
- emit_changed(get_edited_property(), array, "", true);
- if (array.get_type() == Variant::ARRAY) {
- array = array.call("duplicate"); // Duplicate, so undo/redo works better.
- }
object->set_array(array);
+ emit_changed(get_edited_property(), array, "", true);
}
}
@@ -188,18 +203,12 @@ void EditorPropertyArray::_change_type_menu(int p_index) {
}
Variant value;
- Callable::CallError ce;
- Variant::construct(Variant::Type(p_index), value, nullptr, 0, ce);
- Variant array = object->get_array();
+ VariantInternal::initialize(&value, Variant::Type(p_index));
+
+ Variant array = object->get_array().duplicate();
array.set(changing_type_index, value);
emit_changed(get_edited_property(), array, "", true);
-
- if (array.get_type() == Variant::ARRAY) {
- array = array.call("duplicate"); // Duplicate, so undo/redo works better.
- }
-
- object->set_array(array);
update_property();
}
@@ -234,6 +243,8 @@ void EditorPropertyArray::update_property() {
return;
}
+ object->set_array(array);
+
int size = array.call("size");
int max_page = MAX(0, size - 1) / page_length;
page_index = MIN(page_index, max_page);
@@ -305,12 +316,6 @@ void EditorPropertyArray::update_property() {
paginator->update(page_index, max_page);
paginator->set_visible(max_page > 0);
- if (array.get_type() == Variant::ARRAY) {
- array = array.call("duplicate");
- }
-
- object->set_array(array);
-
int amount = MIN(size - offset, page_length);
for (int i = 0; i < amount; i++) {
bool reorder_is_from_current_page = reorder_from_index / page_length == page_index;
@@ -401,7 +406,7 @@ void EditorPropertyArray::update_property() {
}
void EditorPropertyArray::_remove_pressed(int p_index) {
- Variant array = object->get_array();
+ Variant array = object->get_array().duplicate();
array.call("remove_at", p_index);
emit_changed(get_edited_property(), array, "", false);
@@ -469,8 +474,9 @@ void EditorPropertyArray::drop_data_fw(const Point2 &p_point, const Variant &p_d
// Handle the case where array is not initialized yet.
if (!array.is_array()) {
- Callable::CallError ce;
- Variant::construct(array_type, array, nullptr, 0, ce);
+ initialize_array(array);
+ } else {
+ array = array.duplicate();
}
// Loop the file array and add to existing array.
@@ -483,13 +489,7 @@ void EditorPropertyArray::drop_data_fw(const Point2 &p_point, const Variant &p_d
}
}
- if (array.get_type() == Variant::ARRAY) {
- array = array.call("duplicate");
- }
-
emit_changed(get_edited_property(), array, "", false);
- object->set_array(array);
-
update_property();
}
}
@@ -536,10 +536,8 @@ void EditorPropertyArray::_notification(int p_what) {
void EditorPropertyArray::_edit_pressed() {
Variant array = get_edited_object()->get(get_edited_property());
- if (!array.is_array()) {
- Callable::CallError ce;
- Variant::construct(array_type, array, nullptr, 0, ce);
-
+ if (!array.is_array() && edit->is_pressed()) {
+ initialize_array(array);
get_edited_object()->set(get_edited_property(), array);
}
@@ -560,37 +558,10 @@ void EditorPropertyArray::_length_changed(double p_page) {
return;
}
- Variant array = object->get_array();
- int previous_size = array.call("size");
-
+ Variant array = object->get_array().duplicate();
array.call("resize", int(p_page));
- if (array.get_type() == Variant::ARRAY) {
- if (subtype != Variant::NIL) {
- int size = array.call("size");
- for (int i = previous_size; i < size; i++) {
- if (array.get(i).get_type() == Variant::NIL) {
- Callable::CallError ce;
- Variant r;
- Variant::construct(subtype, r, nullptr, 0, ce);
- array.set(i, r);
- }
- }
- }
- array = array.call("duplicate"); // Duplicate, so undo/redo works better.
- } else {
- int size = array.call("size");
- // Pool*Array don't initialize their elements, have to do it manually.
- for (int i = previous_size; i < size; i++) {
- Callable::CallError ce;
- Variant r;
- Variant::construct(array.get(i).get_type(), r, nullptr, 0, ce);
- array.set(i, r);
- }
- }
-
emit_changed(get_edited_property(), array, "", false);
- object->set_array(array);
update_property();
}
@@ -677,14 +648,13 @@ void EditorPropertyArray::_reorder_button_up() {
if (reorder_from_index != reorder_to_index) {
// Move the element.
- Variant array = object->get_array();
+ Variant array = object->get_array().duplicate();
Variant value_to_move = array.get(reorder_from_index);
array.call("remove_at", reorder_from_index);
array.call("insert", reorder_to_index, value_to_move);
emit_changed(get_edited_property(), array, "", false);
- object->set_array(array);
update_property();
}
@@ -742,14 +712,13 @@ void EditorPropertyDictionary::_property_changed(const String &p_property, Varia
object->set_new_item_value(p_value);
} else if (p_property.begins_with("indices")) {
int index = p_property.get_slice("/", 1).to_int();
- Dictionary dict = object->get_dict();
+
+ Dictionary dict = object->get_dict().duplicate();
Variant key = dict.get_key_at_index(index);
dict[key] = p_value;
- emit_changed(get_edited_property(), dict, "", true);
-
- dict = dict.duplicate(); // Duplicate, so undo/redo works better.
object->set_dict(dict);
+ emit_changed(get_edited_property(), dict, "", true);
}
}
@@ -769,24 +738,19 @@ void EditorPropertyDictionary::_add_key_value() {
return;
}
- Dictionary dict = object->get_dict();
-
+ Dictionary dict = object->get_dict().duplicate();
dict[object->get_new_item_key()] = object->get_new_item_value();
object->set_new_item_key(Variant());
object->set_new_item_value(Variant());
emit_changed(get_edited_property(), dict, "", false);
-
- dict = dict.duplicate(); // Duplicate, so undo/redo works better.
- object->set_dict(dict);
update_property();
}
void EditorPropertyDictionary::_change_type_menu(int p_index) {
if (changing_type_index < 0) {
Variant value;
- Callable::CallError ce;
- Variant::construct(Variant::Type(p_index), value, nullptr, 0, ce);
+ VariantInternal::initialize(&value, Variant::Type(p_index));
if (changing_type_index == -1) {
object->set_new_item_key(value);
} else {
@@ -796,12 +760,10 @@ void EditorPropertyDictionary::_change_type_menu(int p_index) {
return;
}
- Dictionary dict = object->get_dict();
-
+ Dictionary dict = object->get_dict().duplicate();
if (p_index < Variant::VARIANT_MAX) {
Variant value;
- Callable::CallError ce;
- Variant::construct(Variant::Type(p_index), value, nullptr, 0, ce);
+ VariantInternal::initialize(&value, Variant::Type(p_index));
Variant key = dict.get_key_at_index(changing_type_index);
dict[key] = value;
} else {
@@ -810,9 +772,6 @@ void EditorPropertyDictionary::_change_type_menu(int p_index) {
}
emit_changed(get_edited_property(), dict, "", false);
-
- dict = dict.duplicate(); // Duplicate, so undo/redo works better.
- object->set_dict(dict);
update_property();
}
@@ -836,6 +795,7 @@ void EditorPropertyDictionary::update_property() {
}
Dictionary dict = updated_val;
+ object->set_dict(updated_val);
edit->set_text(vformat(TTR("Dictionary (size %d)"), dict.size()));
@@ -883,9 +843,6 @@ void EditorPropertyDictionary::update_property() {
int amount = MIN(size - offset, page_length);
int total_amount = page_index == max_page ? amount + 2 : amount; // For the "Add Key/Value Pair" box on last page.
- dict = dict.duplicate();
-
- object->set_dict(dict);
VBoxContainer *add_vbox = nullptr;
double default_float_step = EDITOR_GET("interface/inspector/default_float_step");
@@ -1225,9 +1182,8 @@ void EditorPropertyDictionary::_notification(int p_what) {
void EditorPropertyDictionary::_edit_pressed() {
Variant prop_val = get_edited_object()->get(get_edited_property());
- if (prop_val.get_type() == Variant::NIL) {
- Callable::CallError ce;
- Variant::construct(Variant::DICTIONARY, prop_val, nullptr, 0, ce);
+ if (prop_val.get_type() == Variant::NIL && edit->is_pressed()) {
+ VariantInternal::initialize(&prop_val, Variant::DICTIONARY);
get_edited_object()->set(get_edited_property(), prop_val);
}
@@ -1272,14 +1228,13 @@ EditorPropertyDictionary::EditorPropertyDictionary() {
void EditorPropertyLocalizableString::_property_changed(const String &p_property, Variant p_value, const String &p_name, bool p_changing) {
if (p_property.begins_with("indices")) {
int index = p_property.get_slice("/", 1).to_int();
- Dictionary dict = object->get_dict();
+
+ Dictionary dict = object->get_dict().duplicate();
Variant key = dict.get_key_at_index(index);
dict[key] = p_value;
- emit_changed(get_edited_property(), dict, "", true);
-
- dict = dict.duplicate(); // Duplicate, so undo/redo works better.
object->set_dict(dict);
+ emit_changed(get_edited_property(), dict, "", true);
}
}
@@ -1288,29 +1243,22 @@ void EditorPropertyLocalizableString::_add_locale_popup() {
}
void EditorPropertyLocalizableString::_add_locale(const String &p_locale) {
- Dictionary dict = object->get_dict();
-
+ Dictionary dict = object->get_dict().duplicate();
object->set_new_item_key(p_locale);
object->set_new_item_value(String());
dict[object->get_new_item_key()] = object->get_new_item_value();
emit_changed(get_edited_property(), dict, "", false);
-
- dict = dict.duplicate(); // Duplicate, so undo/redo works better.
- object->set_dict(dict);
update_property();
}
void EditorPropertyLocalizableString::_remove_item(Object *p_button, int p_index) {
- Dictionary dict = object->get_dict();
+ Dictionary dict = object->get_dict().duplicate();
Variant key = dict.get_key_at_index(p_index);
dict.erase(key);
emit_changed(get_edited_property(), dict, "", false);
-
- dict = dict.duplicate(); // Duplicate, so undo/redo works better.
- object->set_dict(dict);
update_property();
}
@@ -1330,6 +1278,7 @@ void EditorPropertyLocalizableString::update_property() {
}
Dictionary dict = updated_val;
+ object->set_dict(dict);
edit->set_text(vformat(TTR("Localizable String (size %d)"), dict.size()));
@@ -1376,10 +1325,6 @@ void EditorPropertyLocalizableString::update_property() {
int amount = MIN(size - offset, page_length);
- dict = dict.duplicate();
-
- object->set_dict(dict);
-
for (int i = 0; i < amount; i++) {
String prop_name;
Variant key;
@@ -1451,9 +1396,8 @@ void EditorPropertyLocalizableString::_notification(int p_what) {
void EditorPropertyLocalizableString::_edit_pressed() {
Variant prop_val = get_edited_object()->get(get_edited_property());
- if (prop_val.get_type() == Variant::NIL) {
- Callable::CallError ce;
- Variant::construct(Variant::DICTIONARY, prop_val, nullptr, 0, ce);
+ if (prop_val.get_type() == Variant::NIL && edit->is_pressed()) {
+ VariantInternal::initialize(&prop_val, Variant::DICTIONARY);
get_edited_object()->set(get_edited_property(), prop_val);
}
diff --git a/editor/editor_properties_array_dict.h b/editor/editor_properties_array_dict.h
index 73a16e3687..3b880c60a8 100644
--- a/editor/editor_properties_array_dict.h
+++ b/editor/editor_properties_array_dict.h
@@ -102,6 +102,8 @@ class EditorPropertyArray : public EditorProperty {
HBoxContainer *reorder_selected_element_hbox = nullptr;
Button *reorder_selected_button = nullptr;
+ void initialize_array(Variant &p_array);
+
void _page_changed(int p_page);
void _reorder_button_gui_input(const Ref<InputEvent> &p_event);
diff --git a/editor/editor_property_name_processor.cpp b/editor/editor_property_name_processor.cpp
index 18ba19f5f6..5380fddde2 100644
--- a/editor/editor_property_name_processor.cpp
+++ b/editor/editor_property_name_processor.cpp
@@ -115,6 +115,7 @@ EditorPropertyNameProcessor::EditorPropertyNameProcessor() {
capitalize_string_remaps["arm64-v8a"] = "arm64-v8a";
capitalize_string_remaps["armeabi-v7a"] = "armeabi-v7a";
capitalize_string_remaps["arvr"] = "ARVR";
+ capitalize_string_remaps["astc"] = "ASTC";
capitalize_string_remaps["bg"] = "BG";
capitalize_string_remaps["bidi"] = "BiDi";
capitalize_string_remaps["bp"] = "BP";
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..1c988840ac 100644
--- a/editor/editor_settings.cpp
+++ b/editor/editor_settings.cpp
@@ -453,6 +453,7 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
// Theme
EDITOR_SETTING(Variant::STRING, PROPERTY_HINT_ENUM, "interface/theme/preset", "Default", "Default,Breeze Dark,Godot 2,Gray,Light,Solarized (Dark),Solarized (Light),Black (OLED),Custom")
+ EDITOR_SETTING(Variant::BOOL, PROPERTY_HINT_NONE, "interface/theme/enable_touchscreen_touch_area", DisplayServer::get_singleton()->is_touchscreen_available(), "")
EDITOR_SETTING(Variant::INT, PROPERTY_HINT_ENUM, "interface/theme/icon_and_font_color", 0, "Auto,Dark,Light")
EDITOR_SETTING(Variant::COLOR, PROPERTY_HINT_NONE, "interface/theme/base_color", Color(0.2, 0.23, 0.31), "")
EDITOR_SETTING(Variant::COLOR, PROPERTY_HINT_NONE, "interface/theme/accent_color", Color(0.41, 0.61, 0.91), "")
@@ -474,10 +475,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..d2c82ad013 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;
}
@@ -394,6 +394,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
Color accent_color = EDITOR_GET("interface/theme/accent_color");
Color base_color = EDITOR_GET("interface/theme/base_color");
float contrast = EDITOR_GET("interface/theme/contrast");
+ bool enable_touchscreen_touch_area = EDITOR_GET("interface/theme/enable_touchscreen_touch_area");
bool draw_extra_borders = EDITOR_GET("interface/theme/draw_extra_borders");
float icon_saturation = EDITOR_GET("interface/theme/icon_saturation");
float relationship_line_opacity = EDITOR_GET("interface/theme/relationship_line_opacity");
@@ -1492,11 +1493,15 @@ 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));
+ if (enable_touchscreen_touch_area) {
+ theme->set_stylebox("scroll", "HScrollBar", make_line_stylebox(separator_color, 50));
+ } else {
+ 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 +1511,15 @@ 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));
+ if (enable_touchscreen_touch_area) {
+ theme->set_stylebox("scroll", "VScrollBar", make_line_stylebox(separator_color, 50, 1, 1, true));
+ } else {
+ 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.cpp b/editor/export/editor_export.cpp
index 4900ced2e4..bc429e1111 100644
--- a/editor/export/editor_export.cpp
+++ b/editor/export/editor_export.cpp
@@ -129,10 +129,20 @@ void EditorExport::add_export_preset(const Ref<EditorExportPreset> &p_preset, in
}
String EditorExportPlatform::test_etc2() const {
- const bool etc2_supported = GLOBAL_GET("rendering/textures/vram_compression/import_etc2");
+ const bool etc2_supported = GLOBAL_GET("rendering/textures/vram_compression/import_etc2_astc");
if (!etc2_supported) {
- return TTR("Target platform requires 'ETC2' texture compression. Enable 'Import Etc 2' in Project Settings.");
+ return TTR("Target platform requires 'ETC2/ASTC' texture compression. Enable 'Import ETC2 ASTC' in Project Settings.");
+ }
+
+ return String();
+}
+
+String EditorExportPlatform::test_bc() const {
+ const bool bc_supported = GLOBAL_GET("rendering/textures/vram_compression/import_s3tc_bptc");
+
+ if (!bc_supported) {
+ return TTR("Target platform requires 'S3TC/BPTC' texture compression. Enable 'Import S3TC BPTC' in Project Settings.");
}
return String();
diff --git a/editor/export/editor_export_platform.cpp b/editor/export/editor_export_platform.cpp
index 9f79eecfb7..a46484bb0e 100644
--- a/editor/export/editor_export_platform.cpp
+++ b/editor/export/editor_export_platform.cpp
@@ -785,10 +785,10 @@ String EditorExportPlatform::_export_customize(const String &p_path, LocalVector
break;
}
}
- }
- if (_export_customize_object(res.ptr(), customize_resources_plugins)) {
- modified = true;
+ if (_export_customize_object(res.ptr(), customize_resources_plugins)) {
+ modified = true;
+ }
}
if (modified || p_force_save) {
@@ -814,7 +814,7 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> &
HashSet<String> paths;
Vector<String> path_remaps;
- paths.insert(ProjectSettings::get_singleton()->get_project_data_path().path_join("global_script_class_cache.cfg"));
+ paths.insert(ProjectSettings::get_singleton()->get_global_class_list_path());
if (p_preset->get_export_filter() == EditorExportPreset::EXPORT_ALL_RESOURCES) {
//find stuff
_export_find_resources(EditorFileSystem::get_singleton()->get_filesystem(), paths);
@@ -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/export/editor_export_platform.h b/editor/export/editor_export_platform.h
index 3b4e92c9bd..05d985eb6a 100644
--- a/editor/export/editor_export_platform.h
+++ b/editor/export/editor_export_platform.h
@@ -229,6 +229,7 @@ public:
virtual Ref<Texture2D> get_run_icon() const { return get_logo(); }
String test_etc2() const;
+ String test_bc() const;
bool can_export(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates) const;
virtual bool has_valid_export_configuration(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates) const = 0;
virtual bool has_valid_project_configuration(const Ref<EditorExportPreset> &p_preset, String &r_error) const = 0;
diff --git a/editor/icons/UseBlendDisable.svg b/editor/icons/UseBlendDisable.svg
new file mode 100644
index 0000000000..449dc2d0c8
--- /dev/null
+++ b/editor/icons/UseBlendDisable.svg
@@ -0,0 +1 @@
+<svg enable-background="new -595.5 420.5 16 16" height="16" viewBox="-595.5 420.5 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m-591 421.5h7v14h-7z" fill="#a3e595" opacity=".5"/><g fill="none" stroke="#a3e595" stroke-linecap="square" stroke-width="2"><path d="m-585 434.5v-12"/><path d="m-590 422.5v12"/><path d="m-581.5 422.5h-12"/></g></svg>
diff --git a/editor/icons/UseBlendEnable.svg b/editor/icons/UseBlendEnable.svg
new file mode 100644
index 0000000000..5567b2d8c6
--- /dev/null
+++ b/editor/icons/UseBlendEnable.svg
@@ -0,0 +1 @@
+<svg enable-background="new -595.5 420.5 16 16" height="16" viewBox="-595.5 420.5 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m-587.5 423.244c-3.995 2.354-7 6.775-7 11.256v1h14v-1c0-4.48-3.005-8.901-7-11.256z" fill="#95c6e8" opacity=".5"/><g fill="none" stroke="#95c6e8" stroke-linecap="square" stroke-width="2"><path d="m-581.5 422.5c-6 0-12 6-12 12"/><path d="m-581.5 434.5c0-6-6-12-12-12"/></g></svg>
diff --git a/editor/import/resource_importer_layered_texture.cpp b/editor/import/resource_importer_layered_texture.cpp
index bc4ced7ea2..10a0c2662f 100644
--- a/editor/import/resource_importer_layered_texture.cpp
+++ b/editor/import/resource_importer_layered_texture.cpp
@@ -123,6 +123,9 @@ bool ResourceImporterLayeredTexture::get_option_visibility(const String &p_path,
if (p_option == "compress/lossy_quality" && p_options.has("compress/mode")) {
return int(p_options["compress/mode"]) == COMPRESS_LOSSY;
}
+ if ((p_option == "compress/high_quality" || p_option == "compress/hdr_compression") && p_options.has("compress/mode")) {
+ return int(p_options["compress/mode"]) == COMPRESS_VRAM_COMPRESSED;
+ }
return true;
}
@@ -136,9 +139,9 @@ String ResourceImporterLayeredTexture::get_preset_name(int p_idx) const {
void ResourceImporterLayeredTexture::get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset) const {
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "compress/mode", PROPERTY_HINT_ENUM, "Lossless,Lossy,VRAM Compressed,VRAM Uncompressed,Basis Universal", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), 1));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "compress/high_quality"), false));
r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "compress/lossy_quality", PROPERTY_HINT_RANGE, "0,1,0.01"), 0.7));
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "compress/hdr_compression", PROPERTY_HINT_ENUM, "Disabled,Opaque Only,Always"), 1));
- r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "compress/bptc_ldr", PROPERTY_HINT_ENUM, "Disabled,Enabled,RGBA Only"), 0));
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "compress/channel_pack", PROPERTY_HINT_ENUM, "sRGB Friendly,Optimized,Normal Map (RG Channels)"), 0));
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "mipmaps/generate"), true));
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "mipmaps/limit", PROPERTY_HINT_RANGE, "-1,256"), -1));
@@ -283,8 +286,8 @@ void ResourceImporterLayeredTexture::_save_tex(Vector<Ref<Image>> p_images, cons
Error ResourceImporterLayeredTexture::import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) {
int compress_mode = p_options["compress/mode"];
float lossy = p_options["compress/lossy_quality"];
+ float high_quality = p_options["compress/high_quality"];
int hdr_compression = p_options["compress/hdr_compression"];
- int bptc_ldr = p_options["compress/bptc_ldr"];
bool mipmaps = p_options["mipmaps/generate"];
int channel_pack = p_options["compress/channel_pack"];
@@ -389,9 +392,10 @@ Error ResourceImporterLayeredTexture::import(const String &p_source_file, const
texture_import->compress_mode = compress_mode;
texture_import->lossy = lossy;
texture_import->hdr_compression = hdr_compression;
- texture_import->bptc_ldr = bptc_ldr;
texture_import->mipmaps = mipmaps;
texture_import->used_channels = used_channels;
+ texture_import->high_quality = high_quality;
+
_check_compress_ctex(p_source_file, texture_import);
if (r_metadata) {
Dictionary meta;
@@ -406,12 +410,11 @@ Error ResourceImporterLayeredTexture::import(const String &p_source_file, const
}
const char *ResourceImporterLayeredTexture::compression_formats[] = {
- "bptc",
- "s3tc",
- "etc",
- "etc2",
+ "s3tc_bptc",
+ "etc2_astc",
nullptr
};
+
String ResourceImporterLayeredTexture::get_import_settings_string() const {
String s;
@@ -450,12 +453,16 @@ bool ResourceImporterLayeredTexture::are_import_settings_valid(const String &p_p
bool valid = true;
while (compression_formats[index]) {
String setting_path = "rendering/textures/vram_compression/import_" + String(compression_formats[index]);
- bool test = GLOBAL_GET(setting_path);
- if (test) {
- if (!formats_imported.has(compression_formats[index])) {
- valid = false;
- break;
+ if (ProjectSettings::get_singleton()->has_setting(setting_path)) {
+ bool test = GLOBAL_GET(setting_path);
+ if (test) {
+ if (!formats_imported.has(compression_formats[index])) {
+ valid = false;
+ break;
+ }
}
+ } else {
+ WARN_PRINT("Setting for imported format not found: " + setting_path);
}
index++;
}
@@ -484,64 +491,83 @@ void ResourceImporterLayeredTexture::_check_compress_ctex(const String &p_source
// Must import in all formats, in order of priority (so platform choses the best supported one. IE, etc2 over etc).
// Android, GLES 2.x
- bool can_bptc = GLOBAL_GET("rendering/textures/vram_compression/import_bptc");
- if (can_bptc) {
- r_texture_import->formats_imported.push_back("bptc"); // BPTC needs to be added anyway.
+ const bool can_s3tc_bptc = GLOBAL_GET("rendering/textures/vram_compression/import_s3tc_bptc") || OS::get_singleton()->get_preferred_texture_format() == OS::PREFERRED_TEXTURE_FORMAT_S3TC_BPTC;
+ const bool can_etc2_astc = GLOBAL_GET("rendering/textures/vram_compression/import_etc2_astc") || OS::get_singleton()->get_preferred_texture_format() == OS::PREFERRED_TEXTURE_FORMAT_ETC2_ASTC;
+
+ // Add list of formats imported
+ if (can_s3tc_bptc) {
+ r_texture_import->formats_imported.push_back("s3tc_bptc");
}
+ if (can_etc2_astc) {
+ r_texture_import->formats_imported.push_back("etc2_astc");
+ }
+
bool can_compress_hdr = r_texture_import->hdr_compression > 0;
ERR_FAIL_NULL(r_texture_import->image);
bool is_hdr = (r_texture_import->image->get_format() >= Image::FORMAT_RF && r_texture_import->image->get_format() <= Image::FORMAT_RGBE9995);
- bool is_ldr = (r_texture_import->image->get_format() >= Image::FORMAT_L8 && r_texture_import->image->get_format() <= Image::FORMAT_RGB565);
- bool can_s3tc = GLOBAL_GET("rendering/textures/vram_compression/import_s3tc");
ERR_FAIL_NULL(r_texture_import->slices);
// Can compress hdr, but hdr with alpha is not compressible.
- if (r_texture_import->hdr_compression == 2) {
- // The user selected to compress hdr anyway, so force an alpha-less format.
- if (r_texture_import->image->get_format() == Image::FORMAT_RGBAF) {
- for (int i = 0; i < r_texture_import->slices->size(); i++) {
- r_texture_import->slices->write[i]->convert(Image::FORMAT_RGBF);
- }
+ bool use_uncompressed = false;
+
+ if (is_hdr) {
+ if (r_texture_import->used_channels == Image::USED_CHANNELS_LA || r_texture_import->used_channels == Image::USED_CHANNELS_RGBA) {
+ if (r_texture_import->hdr_compression == 2) {
+ // The user selected to compress hdr anyway, so force an alpha-less format.
+ if (r_texture_import->image->get_format() == Image::FORMAT_RGBAF) {
+ for (int i = 0; i < r_texture_import->slices->size(); i++) {
+ r_texture_import->slices->write[i]->convert(Image::FORMAT_RGBF);
+ }
- } else if (r_texture_import->image->get_format() == Image::FORMAT_RGBAH) {
- for (int i = 0; i < r_texture_import->slices->size(); i++) {
- r_texture_import->slices->write[i]->convert(Image::FORMAT_RGBH);
+ } else if (r_texture_import->image->get_format() == Image::FORMAT_RGBAH) {
+ for (int i = 0; i < r_texture_import->slices->size(); i++) {
+ r_texture_import->slices->write[i]->convert(Image::FORMAT_RGBH);
+ }
+ }
+ } else {
+ can_compress_hdr = false;
}
}
- } else {
- can_compress_hdr = false;
- }
- if (is_hdr && can_compress_hdr) {
- if (!can_bptc) {
+ if (!can_compress_hdr) {
//default to rgbe
if (r_texture_import->image->get_format() != Image::FORMAT_RGBE9995) {
for (int i = 0; i < r_texture_import->slices->size(); i++) {
r_texture_import->slices->write[i]->convert(Image::FORMAT_RGBE9995);
}
}
+ use_uncompressed = true;
}
- } else {
- can_bptc = false;
}
- if (is_ldr && can_bptc) {
- if (r_texture_import->bptc_ldr == 0 || (r_texture_import->bptc_ldr == 1 && !(r_texture_import->used_channels == Image::USED_CHANNELS_LA || r_texture_import->used_channels == Image::USED_CHANNELS_RGBA))) {
- can_bptc = false;
- }
- }
- if (!(r_texture_import->used_channels == Image::USED_CHANNELS_LA || r_texture_import->used_channels == Image::USED_CHANNELS_RGBA)) {
- if (GLOBAL_GET("rendering/textures/vram_compression/import_etc2")) {
- _save_tex(*r_texture_import->slices, r_texture_import->save_path + ".etc2." + extension, r_texture_import->compress_mode, r_texture_import->lossy, Image::COMPRESS_ETC2, *r_texture_import->csource, r_texture_import->used_channels, r_texture_import->mipmaps, true);
- r_texture_import->platform_variants->push_back("etc2");
- r_texture_import->formats_imported.push_back("etc2");
+ if (use_uncompressed) {
+ _save_tex(*r_texture_import->slices, r_texture_import->save_path + "." + extension, COMPRESS_VRAM_UNCOMPRESSED, r_texture_import->lossy, Image::COMPRESS_S3TC /* IGNORED */, *r_texture_import->csource, r_texture_import->used_channels, r_texture_import->mipmaps, false);
+ } else {
+ if (can_s3tc_bptc) {
+ Image::CompressMode image_compress_mode;
+ String image_compress_format;
+ if (r_texture_import->high_quality || is_hdr) {
+ image_compress_mode = Image::COMPRESS_BPTC;
+ image_compress_format = "bptc";
+ } else {
+ image_compress_mode = Image::COMPRESS_S3TC;
+ image_compress_format = "s3tc";
+ }
+ _save_tex(*r_texture_import->slices, r_texture_import->save_path + "." + image_compress_format + "." + extension, r_texture_import->compress_mode, r_texture_import->lossy, image_compress_mode, *r_texture_import->csource, r_texture_import->used_channels, r_texture_import->mipmaps, true);
+ r_texture_import->platform_variants->push_back(image_compress_format);
}
- if (can_bptc || can_s3tc) {
- _save_tex(*r_texture_import->slices, r_texture_import->save_path + ".s3tc." + extension, r_texture_import->compress_mode, r_texture_import->lossy, can_bptc ? Image::COMPRESS_BPTC : Image::COMPRESS_S3TC, *r_texture_import->csource, r_texture_import->used_channels, r_texture_import->mipmaps, false);
- r_texture_import->platform_variants->push_back("s3tc");
- r_texture_import->formats_imported.push_back("s3tc");
+ if (can_etc2_astc) {
+ Image::CompressMode image_compress_mode;
+ String image_compress_format;
+ if (r_texture_import->high_quality || is_hdr) {
+ image_compress_mode = Image::COMPRESS_ASTC;
+ image_compress_format = "astc";
+ } else {
+ image_compress_mode = Image::COMPRESS_ETC2;
+ image_compress_format = "etc2";
+ }
+ _save_tex(*r_texture_import->slices, r_texture_import->save_path + "." + image_compress_format + "." + extension, r_texture_import->compress_mode, r_texture_import->lossy, image_compress_mode, *r_texture_import->csource, r_texture_import->used_channels, r_texture_import->mipmaps, true);
+ r_texture_import->platform_variants->push_back(image_compress_format);
}
- return;
}
- EditorNode::add_io_error(vformat(TTR("%s: No suitable PC VRAM compression algorithm enabled in Project Settings (S3TC or BPTC). This texture may not display correctly on desktop platforms."), p_source_file));
}
diff --git a/editor/import/resource_importer_layered_texture.h b/editor/import/resource_importer_layered_texture.h
index 5118ad7ba4..52fd37639d 100644
--- a/editor/import/resource_importer_layered_texture.h
+++ b/editor/import/resource_importer_layered_texture.h
@@ -51,8 +51,8 @@ public:
int compress_mode = 0;
float lossy = 1.0;
int hdr_compression = 0;
- int bptc_ldr = 0;
bool mipmaps = true;
+ bool high_quality = false;
Image::UsedChannels used_channels = Image::USED_CHANNELS_RGBA;
virtual ~LayeredTextureImport() {}
};
diff --git a/editor/import/resource_importer_scene.cpp b/editor/import/resource_importer_scene.cpp
index 102fa903b8..6c6c89bcc0 100644
--- a/editor/import/resource_importer_scene.cpp
+++ b/editor/import/resource_importer_scene.cpp
@@ -1085,10 +1085,10 @@ Node *ResourceImporterScene::_post_fix_animations(Node *p_node, Node *p_root, co
return p_node;
}
-Node *ResourceImporterScene::_post_fix_node(Node *p_node, Node *p_root, HashMap<Ref<ImporterMesh>, Vector<Ref<Shape3D>>> &collision_map, Pair<PackedVector3Array, PackedInt32Array> &r_occluder_arrays, HashSet<Ref<ImporterMesh>> &r_scanned_meshes, const Dictionary &p_node_data, const Dictionary &p_material_data, const Dictionary &p_animation_data, float p_animation_fps) {
+Node *ResourceImporterScene::_post_fix_node(Node *p_node, Node *p_root, HashMap<Ref<ImporterMesh>, Vector<Ref<Shape3D>>> &collision_map, Pair<PackedVector3Array, PackedInt32Array> &r_occluder_arrays, HashSet<Ref<ImporterMesh>> &r_scanned_meshes, const Dictionary &p_node_data, const Dictionary &p_material_data, const Dictionary &p_animation_data, float p_animation_fps, float p_applied_root_scale) {
// children first
for (int i = 0; i < p_node->get_child_count(); i++) {
- Node *r = _post_fix_node(p_node->get_child(i), p_root, collision_map, r_occluder_arrays, r_scanned_meshes, p_node_data, p_material_data, p_animation_data, p_animation_fps);
+ Node *r = _post_fix_node(p_node->get_child(i), p_root, collision_map, r_occluder_arrays, r_scanned_meshes, p_node_data, p_material_data, p_animation_data, p_animation_fps, p_applied_root_scale);
if (!r) {
i--; //was erased
}
@@ -1231,7 +1231,8 @@ Node *ResourceImporterScene::_post_fix_node(Node *p_node, Node *p_root, HashMap<
} else {
shapes = get_collision_shapes(
m->get_mesh(),
- node_settings);
+ node_settings,
+ p_applied_root_scale);
}
if (shapes.size()) {
@@ -1242,6 +1243,7 @@ Node *ResourceImporterScene::_post_fix_node(Node *p_node, Node *p_root, HashMap<
p_node->add_child(col, true);
col->set_owner(p_node->get_owner());
col->set_transform(get_collision_shapes_transform(node_settings));
+ col->set_position(p_applied_root_scale * col->get_position());
base = col;
} break;
case MESH_PHYSICS_RIGID_BODY_AND_MESH: {
@@ -1249,6 +1251,7 @@ Node *ResourceImporterScene::_post_fix_node(Node *p_node, Node *p_root, HashMap<
rigid_body->set_name(p_node->get_name());
p_node->replace_by(rigid_body);
rigid_body->set_transform(mi->get_transform() * get_collision_shapes_transform(node_settings));
+ rigid_body->set_position(p_applied_root_scale * rigid_body->get_position());
p_node = rigid_body;
mi->set_transform(Transform3D());
rigid_body->add_child(mi, true);
@@ -1258,6 +1261,7 @@ Node *ResourceImporterScene::_post_fix_node(Node *p_node, Node *p_root, HashMap<
case MESH_PHYSICS_STATIC_COLLIDER_ONLY: {
StaticBody3D *col = memnew(StaticBody3D);
col->set_transform(mi->get_transform() * get_collision_shapes_transform(node_settings));
+ col->set_position(p_applied_root_scale * col->get_position());
col->set_name(p_node->get_name());
p_node->replace_by(col);
memdelete(p_node);
@@ -1267,6 +1271,7 @@ Node *ResourceImporterScene::_post_fix_node(Node *p_node, Node *p_root, HashMap<
case MESH_PHYSICS_AREA_ONLY: {
Area3D *area = memnew(Area3D);
area->set_transform(mi->get_transform() * get_collision_shapes_transform(node_settings));
+ area->set_position(p_applied_root_scale * area->get_position());
area->set_name(p_node->get_name());
p_node->replace_by(area);
memdelete(p_node);
@@ -1865,6 +1870,7 @@ void ResourceImporterScene::get_import_options(const String &p_path, List<Import
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "animation/import"), true));
r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "animation/fps", PROPERTY_HINT_RANGE, "1,120,1"), 30));
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "animation/trimming"), false));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "animation/remove_immutable_tracks"), true));
r_options->push_back(ImportOption(PropertyInfo(Variant::STRING, "import_script/path", PROPERTY_HINT_FILE, script_ext_hint), ""));
r_options->push_back(ImportOption(PropertyInfo(Variant::DICTIONARY, "_subresources", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), Dictionary()));
@@ -2397,7 +2403,7 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p
fps = (float)p_options[SNAME("animation/fps")];
}
_pre_fix_animations(scene, scene, node_data, animation_data, fps);
- _post_fix_node(scene, scene, collision_map, occluder_arrays, scanned_meshes, node_data, material_data, animation_data, fps);
+ _post_fix_node(scene, scene, collision_map, occluder_arrays, scanned_meshes, node_data, material_data, animation_data, fps, apply_root ? root_scale : 1.0);
_post_fix_animations(scene, scene, node_data, animation_data, fps);
String root_type = p_options["nodes/root_type"];
diff --git a/editor/import/resource_importer_scene.h b/editor/import/resource_importer_scene.h
index 2d08d4df50..aa057d3404 100644
--- a/editor/import/resource_importer_scene.h
+++ b/editor/import/resource_importer_scene.h
@@ -279,7 +279,7 @@ public:
Node *_pre_fix_node(Node *p_node, Node *p_root, HashMap<Ref<ImporterMesh>, Vector<Ref<Shape3D>>> &r_collision_map, Pair<PackedVector3Array, PackedInt32Array> *r_occluder_arrays, List<Pair<NodePath, Node *>> &r_node_renames);
Node *_pre_fix_animations(Node *p_node, Node *p_root, const Dictionary &p_node_data, const Dictionary &p_animation_data, float p_animation_fps);
- Node *_post_fix_node(Node *p_node, Node *p_root, HashMap<Ref<ImporterMesh>, Vector<Ref<Shape3D>>> &collision_map, Pair<PackedVector3Array, PackedInt32Array> &r_occluder_arrays, HashSet<Ref<ImporterMesh>> &r_scanned_meshes, const Dictionary &p_node_data, const Dictionary &p_material_data, const Dictionary &p_animation_data, float p_animation_fps);
+ Node *_post_fix_node(Node *p_node, Node *p_root, HashMap<Ref<ImporterMesh>, Vector<Ref<Shape3D>>> &collision_map, Pair<PackedVector3Array, PackedInt32Array> &r_occluder_arrays, HashSet<Ref<ImporterMesh>> &r_scanned_meshes, const Dictionary &p_node_data, const Dictionary &p_material_data, const Dictionary &p_animation_data, float p_animation_fps, float p_applied_root_scale);
Node *_post_fix_animations(Node *p_node, Node *p_root, const Dictionary &p_node_data, const Dictionary &p_animation_data, float p_animation_fps);
Ref<Animation> _save_animation_to_file(Ref<Animation> anim, bool p_save_to_file, String p_save_to_path, bool p_keep_custom_tracks);
@@ -298,7 +298,7 @@ public:
ResourceImporterScene(bool p_animation_import = false);
template <class M>
- static Vector<Ref<Shape3D>> get_collision_shapes(const Ref<Mesh> &p_mesh, const M &p_options);
+ static Vector<Ref<Shape3D>> get_collision_shapes(const Ref<Mesh> &p_mesh, const M &p_options, float p_applied_root_scale);
template <class M>
static Transform3D get_collision_shapes_transform(const M &p_options);
@@ -314,7 +314,7 @@ public:
};
template <class M>
-Vector<Ref<Shape3D>> ResourceImporterScene::get_collision_shapes(const Ref<Mesh> &p_mesh, const M &p_options) {
+Vector<Ref<Shape3D>> ResourceImporterScene::get_collision_shapes(const Ref<Mesh> &p_mesh, const M &p_options, float p_applied_root_scale) {
ShapeType generate_shape_type = SHAPE_TYPE_DECOMPOSE_CONVEX;
if (p_options.has(SNAME("physics/shape_type"))) {
generate_shape_type = (ShapeType)p_options[SNAME("physics/shape_type")].operator int();
@@ -409,7 +409,7 @@ Vector<Ref<Shape3D>> ResourceImporterScene::get_collision_shapes(const Ref<Mesh>
Ref<BoxShape3D> box;
box.instantiate();
if (p_options.has(SNAME("primitive/size"))) {
- box->set_size(p_options[SNAME("primitive/size")]);
+ box->set_size(p_options[SNAME("primitive/size")].operator Vector3() * p_applied_root_scale);
}
Vector<Ref<Shape3D>> shapes;
@@ -420,7 +420,7 @@ Vector<Ref<Shape3D>> ResourceImporterScene::get_collision_shapes(const Ref<Mesh>
Ref<SphereShape3D> sphere;
sphere.instantiate();
if (p_options.has(SNAME("primitive/radius"))) {
- sphere->set_radius(p_options[SNAME("primitive/radius")]);
+ sphere->set_radius(p_options[SNAME("primitive/radius")].operator float() * p_applied_root_scale);
}
Vector<Ref<Shape3D>> shapes;
@@ -430,10 +430,10 @@ Vector<Ref<Shape3D>> ResourceImporterScene::get_collision_shapes(const Ref<Mesh>
Ref<CylinderShape3D> cylinder;
cylinder.instantiate();
if (p_options.has(SNAME("primitive/height"))) {
- cylinder->set_height(p_options[SNAME("primitive/height")]);
+ cylinder->set_height(p_options[SNAME("primitive/height")].operator float() * p_applied_root_scale);
}
if (p_options.has(SNAME("primitive/radius"))) {
- cylinder->set_radius(p_options[SNAME("primitive/radius")]);
+ cylinder->set_radius(p_options[SNAME("primitive/radius")].operator float() * p_applied_root_scale);
}
Vector<Ref<Shape3D>> shapes;
@@ -443,10 +443,10 @@ Vector<Ref<Shape3D>> ResourceImporterScene::get_collision_shapes(const Ref<Mesh>
Ref<CapsuleShape3D> capsule;
capsule.instantiate();
if (p_options.has(SNAME("primitive/height"))) {
- capsule->set_height(p_options[SNAME("primitive/height")]);
+ capsule->set_height(p_options[SNAME("primitive/height")].operator float() * p_applied_root_scale);
}
if (p_options.has(SNAME("primitive/radius"))) {
- capsule->set_radius(p_options[SNAME("primitive/radius")]);
+ capsule->set_radius(p_options[SNAME("primitive/radius")].operator float() * p_applied_root_scale);
}
Vector<Ref<Shape3D>> shapes;
diff --git a/editor/import/resource_importer_texture.cpp b/editor/import/resource_importer_texture.cpp
index 2f543ea02d..c05e7582eb 100644
--- a/editor/import/resource_importer_texture.cpp
+++ b/editor/import/resource_importer_texture.cpp
@@ -169,9 +169,14 @@ String ResourceImporterTexture::get_resource_type() const {
}
bool ResourceImporterTexture::get_option_visibility(const String &p_path, const String &p_option, const HashMap<StringName, Variant> &p_options) const {
- if (p_option == "compress/lossy_quality") {
+ if (p_option == "compress/high_quality" || p_option == "compress/hdr_compression") {
int compress_mode = int(p_options["compress/mode"]);
- if (compress_mode != COMPRESS_LOSSY && compress_mode != COMPRESS_VRAM_COMPRESSED) {
+ if (compress_mode != COMPRESS_VRAM_COMPRESSED) {
+ return false;
+ }
+ } else if (p_option == "compress/lossy_quality") {
+ int compress_mode = int(p_options["compress/mode"]);
+ if (compress_mode != COMPRESS_LOSSY) {
return false;
}
} else if (p_option == "compress/hdr_mode") {
@@ -186,15 +191,6 @@ bool ResourceImporterTexture::get_option_visibility(const String &p_path, const
}
} else if (p_option == "mipmaps/limit") {
return p_options["mipmaps/generate"];
-
- } else if (p_option == "compress/bptc_ldr") {
- int compress_mode = int(p_options["compress/mode"]);
- if (compress_mode < COMPRESS_VRAM_COMPRESSED) {
- return false;
- }
- if (!GLOBAL_GET("rendering/textures/vram_compression/import_bptc")) {
- return false;
- }
}
return true;
@@ -216,9 +212,9 @@ String ResourceImporterTexture::get_preset_name(int p_idx) const {
void ResourceImporterTexture::get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset) const {
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "compress/mode", PROPERTY_HINT_ENUM, "Lossless,Lossy,VRAM Compressed,VRAM Uncompressed,Basis Universal", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), p_preset == PRESET_3D ? 2 : 0));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "compress/high_quality"), false));
r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "compress/lossy_quality", PROPERTY_HINT_RANGE, "0,1,0.01"), 0.7));
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "compress/hdr_compression", PROPERTY_HINT_ENUM, "Disabled,Opaque Only,Always"), 1));
- r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "compress/bptc_ldr", PROPERTY_HINT_ENUM, "Disabled,Enabled,RGBA Only"), 0));
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "compress/normal_map", PROPERTY_HINT_ENUM, "Detect,Enable,Disabled"), 0));
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "compress/channel_pack", PROPERTY_HINT_ENUM, "sRGB Friendly,Optimized"), 0));
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "mipmaps/generate"), (p_preset == PRESET_3D ? true : false)));
@@ -289,7 +285,7 @@ void ResourceImporterTexture::save_to_ctex_format(Ref<FileAccess> f, const Ref<I
case COMPRESS_VRAM_COMPRESSED: {
Ref<Image> image = p_image->duplicate();
- image->compress_from_channels(p_compress_format, p_channels, p_lossy_quality);
+ image->compress_from_channels(p_compress_format, p_channels);
f->store_32(CompressedTexture2D::DATA_FORMAT_IMAGE);
f->store_16(image->get_width());
@@ -322,15 +318,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 +379,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();
}
@@ -425,7 +417,7 @@ Error ResourceImporterTexture::import(const String &p_source_file, const String
const int pack_channels = p_options["compress/channel_pack"];
const int normal = p_options["compress/normal_map"];
const int hdr_compression = p_options["compress/hdr_compression"];
- const int bptc_ldr = p_options["compress/bptc_ldr"];
+ const int high_quality = p_options["compress/high_quality"];
// Mipmaps.
const bool mipmaps = p_options["mipmaps/generate"];
@@ -598,19 +590,22 @@ Error ResourceImporterTexture::import(const String &p_source_file, const String
// Android, GLES 2.x
const bool is_hdr = (image->get_format() >= Image::FORMAT_RF && image->get_format() <= Image::FORMAT_RGBE9995);
- bool is_ldr = (image->get_format() >= Image::FORMAT_L8 && image->get_format() <= Image::FORMAT_RGB565);
- const bool can_bptc = GLOBAL_GET("rendering/textures/vram_compression/import_bptc");
- const bool can_s3tc = GLOBAL_GET("rendering/textures/vram_compression/import_s3tc");
+ const bool can_s3tc_bptc = GLOBAL_GET("rendering/textures/vram_compression/import_s3tc_bptc") || OS::get_singleton()->get_preferred_texture_format() == OS::PREFERRED_TEXTURE_FORMAT_S3TC_BPTC;
+ const bool can_etc2_astc = GLOBAL_GET("rendering/textures/vram_compression/import_etc2_astc") || OS::get_singleton()->get_preferred_texture_format() == OS::PREFERRED_TEXTURE_FORMAT_ETC2_ASTC;
- if (can_bptc) {
- // Add to the list anyway.
- formats_imported.push_back("bptc");
+ // Add list of formats imported
+ if (can_s3tc_bptc) {
+ formats_imported.push_back("s3tc_bptc");
+ }
+ if (can_etc2_astc) {
+ formats_imported.push_back("etc2_astc");
}
bool can_compress_hdr = hdr_compression > 0;
bool has_alpha = image->detect_alpha() != Image::ALPHA_NONE;
+ bool use_uncompressed = false;
- if (is_hdr && can_compress_hdr) {
+ if (is_hdr) {
if (has_alpha) {
// Can compress HDR, but HDR with alpha is not compressible.
if (hdr_compression == 2) {
@@ -629,36 +624,41 @@ Error ResourceImporterTexture::import(const String &p_source_file, const String
// Fallback to RGBE99995.
if (image->get_format() != Image::FORMAT_RGBE9995) {
image->convert(Image::FORMAT_RGBE9995);
+ use_uncompressed = true;
}
}
}
- bool ok_on_pc = false;
- if (can_bptc || can_s3tc) {
- ok_on_pc = true;
- Image::CompressMode image_compress_mode = Image::COMPRESS_BPTC;
- if (!bptc_ldr && can_s3tc && is_ldr) {
- image_compress_mode = Image::COMPRESS_S3TC;
+ if (use_uncompressed) {
+ _save_ctex(image, p_save_path + ".ctex", COMPRESS_VRAM_UNCOMPRESSED, lossy, Image::COMPRESS_S3TC /*this is ignored */, mipmaps, stream, detect_3d, detect_roughness, detect_normal, force_normal, srgb_friendly_pack, false, mipmap_limit, normal_image, roughness_channel);
+ } else {
+ if (can_s3tc_bptc) {
+ Image::CompressMode image_compress_mode;
+ String image_compress_format;
+ if (high_quality || is_hdr) {
+ image_compress_mode = Image::COMPRESS_BPTC;
+ image_compress_format = "bptc";
+ } else {
+ image_compress_mode = Image::COMPRESS_S3TC;
+ image_compress_format = "s3tc";
+ }
+ _save_ctex(image, p_save_path + "." + image_compress_format + ".ctex", compress_mode, lossy, image_compress_mode, mipmaps, stream, detect_3d, detect_roughness, detect_normal, force_normal, srgb_friendly_pack, false, mipmap_limit, normal_image, roughness_channel);
+ r_platform_variants->push_back(image_compress_format);
}
- _save_ctex(image, p_save_path + ".s3tc.ctex", compress_mode, lossy, image_compress_mode, mipmaps, stream, detect_3d, detect_roughness, detect_normal, force_normal, srgb_friendly_pack, false, mipmap_limit, normal_image, roughness_channel);
- r_platform_variants->push_back("s3tc");
- formats_imported.push_back("s3tc");
- }
-
- if (GLOBAL_GET("rendering/textures/vram_compression/import_etc2")) {
- _save_ctex(image, p_save_path + ".etc2.ctex", compress_mode, lossy, Image::COMPRESS_ETC2, mipmaps, stream, detect_3d, detect_roughness, detect_normal, force_normal, srgb_friendly_pack, true, mipmap_limit, normal_image, roughness_channel);
- r_platform_variants->push_back("etc2");
- formats_imported.push_back("etc2");
- }
- if (GLOBAL_GET("rendering/textures/vram_compression/import_etc")) {
- _save_ctex(image, p_save_path + ".etc.ctex", compress_mode, lossy, Image::COMPRESS_ETC, mipmaps, stream, detect_3d, detect_roughness, detect_normal, force_normal, srgb_friendly_pack, true, mipmap_limit, normal_image, roughness_channel);
- r_platform_variants->push_back("etc");
- formats_imported.push_back("etc");
- }
-
- if (!ok_on_pc) {
- EditorNode::add_io_error(vformat(TTR("%s: No suitable desktop VRAM compression algorithm enabled in Project Settings (S3TC or BPTC). This texture may not display correctly on desktop platforms."), p_source_file));
+ if (can_etc2_astc) {
+ Image::CompressMode image_compress_mode;
+ String image_compress_format;
+ if (high_quality || is_hdr) {
+ image_compress_mode = Image::COMPRESS_ASTC;
+ image_compress_format = "astc";
+ } else {
+ image_compress_mode = Image::COMPRESS_ETC2;
+ image_compress_format = "etc2";
+ }
+ _save_ctex(image, p_save_path + "." + image_compress_format + ".ctex", compress_mode, lossy, image_compress_mode, mipmaps, stream, detect_3d, detect_roughness, detect_normal, force_normal, srgb_friendly_pack, false, mipmap_limit, normal_image, roughness_channel);
+ r_platform_variants->push_back(image_compress_format);
+ }
}
} else {
// Import normally.
@@ -692,10 +692,8 @@ Error ResourceImporterTexture::import(const String &p_source_file, const String
}
const char *ResourceImporterTexture::compression_formats[] = {
- "bptc",
- "s3tc",
- "etc",
- "etc2",
+ "s3tc_bptc",
+ "etc2_astc",
nullptr
};
String ResourceImporterTexture::get_import_settings_string() const {
@@ -745,12 +743,16 @@ bool ResourceImporterTexture::are_import_settings_valid(const String &p_path) co
bool valid = true;
while (compression_formats[index]) {
String setting_path = "rendering/textures/vram_compression/import_" + String(compression_formats[index]);
- bool test = GLOBAL_GET(setting_path);
- if (test) {
- if (!formats_imported.has(compression_formats[index])) {
- valid = false;
- break;
+ if (ProjectSettings::get_singleton()->has_setting(setting_path)) {
+ bool test = GLOBAL_GET(setting_path);
+ if (test) {
+ if (!formats_imported.has(compression_formats[index])) {
+ valid = false;
+ break;
+ }
}
+ } else {
+ WARN_PRINT("Setting for imported format not found: " + setting_path);
}
index++;
}
diff --git a/editor/import/scene_import_settings.cpp b/editor/import/scene_import_settings.cpp
index 044f7475c2..8d26feebf4 100644
--- a/editor/import/scene_import_settings.cpp
+++ b/editor/import/scene_import_settings.cpp
@@ -441,7 +441,7 @@ void SceneImportSettings::_update_view_gizmos() {
// This collider_view doesn't have a mesh so we need to generate a new one.
// Generate the mesh collider.
- Vector<Ref<Shape3D>> shapes = ResourceImporterScene::get_collision_shapes(mesh_node->get_mesh(), e.value.settings);
+ Vector<Ref<Shape3D>> shapes = ResourceImporterScene::get_collision_shapes(mesh_node->get_mesh(), e.value.settings, 1.0);
const Transform3D transform = ResourceImporterScene::get_collision_shapes_transform(e.value.settings);
Ref<ArrayMesh> collider_view_mesh;
diff --git a/editor/input_event_configuration_dialog.cpp b/editor/input_event_configuration_dialog.cpp
index 48e3759e57..fb450a41d3 100644
--- a/editor/input_event_configuration_dialog.cpp
+++ b/editor/input_event_configuration_dialog.cpp
@@ -201,7 +201,7 @@ void InputEventConfigurationDialog::_on_listen_input_changed(const Ref<InputEven
}
if (k.is_valid()) {
- k->set_pressed(false); // To avoid serialisation of 'pressed' property - doesn't matter for actions anyway.
+ k->set_pressed(false); // To avoid serialization of 'pressed' property - doesn't matter for actions anyway.
if (key_mode->get_selected_id() == KEYMODE_KEYCODE) {
k->set_physical_keycode(Key::NONE);
k->set_key_label(Key::NONE);
@@ -685,9 +685,9 @@ InputEventConfigurationDialog::InputEventConfigurationDialog() {
// Key Mode Selection
key_mode = memnew(OptionButton);
- key_mode->add_item("Keycode (Latin equvialent)", KEYMODE_KEYCODE);
- key_mode->add_item("Physical Keycode (poistion of US QWERTY keyboard)", KEYMODE_PHY_KEYCODE);
- key_mode->add_item("Unicode (case-insencetive)", KEYMODE_UNICODE);
+ key_mode->add_item(TTR("Keycode (Latin Equivalent)"), KEYMODE_KEYCODE);
+ key_mode->add_item(TTR("Physical Keycode (Position on US QWERTY Keyboard)"), KEYMODE_PHY_KEYCODE);
+ key_mode->add_item(TTR("Key Label (Unicode, Case-Insensitive)"), KEYMODE_UNICODE);
key_mode->connect("item_selected", callable_mp(this, &InputEventConfigurationDialog::_key_mode_selected));
key_mode->hide();
additional_options_container->add_child(key_mode);
diff --git a/editor/plugins/animation_blend_space_1d_editor.cpp b/editor/plugins/animation_blend_space_1d_editor.cpp
index 33aebe5883..df94815105 100644
--- a/editor/plugins/animation_blend_space_1d_editor.cpp
+++ b/editor/plugins/animation_blend_space_1d_editor.cpp
@@ -38,6 +38,7 @@
#include "editor/editor_undo_redo_manager.h"
#include "scene/animation/animation_blend_tree.h"
#include "scene/gui/check_box.h"
+#include "scene/gui/option_button.h"
#include "scene/gui/panel_container.h"
StringName AnimationNodeBlendSpace1DEditor::get_blend_position_path() const {
@@ -335,6 +336,7 @@ void AnimationNodeBlendSpace1DEditor::_update_space() {
min_value->set_value(blend_space->get_min_space());
sync->set_pressed(blend_space->is_using_sync());
+ interpolation->select(blend_space->get_blend_mode());
label_value->set_text(blend_space->get_value_label());
@@ -361,6 +363,8 @@ void AnimationNodeBlendSpace1DEditor::_config_changed(double) {
undo_redo->add_undo_method(blend_space.ptr(), "set_snap", blend_space->get_snap());
undo_redo->add_do_method(blend_space.ptr(), "set_use_sync", sync->is_pressed());
undo_redo->add_undo_method(blend_space.ptr(), "set_use_sync", blend_space->is_using_sync());
+ undo_redo->add_do_method(blend_space.ptr(), "set_blend_mode", interpolation->get_selected());
+ undo_redo->add_undo_method(blend_space.ptr(), "set_blend_mode", blend_space->get_blend_mode());
undo_redo->add_do_method(this, "_update_space");
undo_redo->add_undo_method(this, "_update_space");
undo_redo->commit_action();
@@ -579,6 +583,10 @@ void AnimationNodeBlendSpace1DEditor::_notification(int p_what) {
tool_erase->set_icon(get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")));
snap->set_icon(get_theme_icon(SNAME("SnapGrid"), SNAME("EditorIcons")));
open_editor->set_icon(get_theme_icon(SNAME("Edit"), SNAME("EditorIcons")));
+ interpolation->clear();
+ interpolation->add_icon_item(get_theme_icon(SNAME("TrackContinuous"), SNAME("EditorIcons")), "", 0);
+ interpolation->add_icon_item(get_theme_icon(SNAME("TrackDiscrete"), SNAME("EditorIcons")), "", 1);
+ interpolation->add_icon_item(get_theme_icon(SNAME("TrackCapture"), SNAME("EditorIcons")), "", 2);
} break;
case NOTIFICATION_PROCESS: {
@@ -639,6 +647,7 @@ void AnimationNodeBlendSpace1DEditor::edit(const Ref<AnimationNode> &p_node) {
min_value->set_editable(!read_only);
max_value->set_editable(!read_only);
sync->set_disabled(read_only);
+ interpolation->set_disabled(read_only);
}
AnimationNodeBlendSpace1DEditor *AnimationNodeBlendSpace1DEditor::singleton = nullptr;
@@ -707,6 +716,13 @@ AnimationNodeBlendSpace1DEditor::AnimationNodeBlendSpace1DEditor() {
top_hb->add_child(sync);
sync->connect("toggled", callable_mp(this, &AnimationNodeBlendSpace1DEditor::_config_changed));
+ top_hb->add_child(memnew(VSeparator));
+
+ top_hb->add_child(memnew(Label(TTR("Blend:"))));
+ interpolation = memnew(OptionButton);
+ top_hb->add_child(interpolation);
+ interpolation->connect("item_selected", callable_mp(this, &AnimationNodeBlendSpace1DEditor::_config_changed));
+
edit_hb = memnew(HBoxContainer);
top_hb->add_child(edit_hb);
edit_hb->add_child(memnew(VSeparator));
diff --git a/editor/plugins/animation_blend_space_1d_editor.h b/editor/plugins/animation_blend_space_1d_editor.h
index e71a4bd1b9..90104fc310 100644
--- a/editor/plugins/animation_blend_space_1d_editor.h
+++ b/editor/plugins/animation_blend_space_1d_editor.h
@@ -41,6 +41,7 @@
#include "scene/gui/tree.h"
class CheckBox;
+class OptionButton;
class PanelContainer;
class AnimationNodeBlendSpace1DEditor : public AnimationTreeNodeEditorPlugin {
@@ -66,6 +67,7 @@ class AnimationNodeBlendSpace1DEditor : public AnimationTreeNodeEditorPlugin {
SpinBox *min_value = nullptr;
CheckBox *sync = nullptr;
+ OptionButton *interpolation = nullptr;
HBoxContainer *edit_hb = nullptr;
SpinBox *edit_value = nullptr;
diff --git a/editor/plugins/animation_player_editor_plugin.cpp b/editor/plugins/animation_player_editor_plugin.cpp
index 06241d07cf..b33ad67f23 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)) {
@@ -1103,9 +1105,24 @@ void AnimationPlayerEditor::_animation_duplicate() {
return;
}
+ int count = 2;
String new_name = current;
- while (player->has_animation(new_name)) {
- new_name = new_name + " (copy)";
+ PackedStringArray split = new_name.split("_");
+ int last_index = split.size() - 1;
+ if (last_index > 0 && split[last_index].is_valid_int() && split[last_index].to_int() >= 0) {
+ count = split[last_index].to_int();
+ split.remove_at(last_index);
+ new_name = String("_").join(split);
+ }
+ while (true) {
+ String attempt = new_name;
+ attempt += vformat("_%d", count);
+ if (player->has_animation(attempt)) {
+ count++;
+ continue;
+ }
+ new_name = attempt;
+ break;
}
if (new_name.contains("/")) {
@@ -1675,7 +1692,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 7ede0bd68c..9632670658 100644
--- a/editor/plugins/animation_state_machine_editor.cpp
+++ b/editor/plugins/animation_state_machine_editor.cpp
@@ -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);
@@ -1162,7 +1163,9 @@ void AnimationNodeStateMachineEditor::_connection_draw(const Vector2 &p_from, co
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);
}
- Ref<Texture2D> icon = icons[p_mode + (p_auto_advance ? 3 : 0)];
+ 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();
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 e09636d297..0f9ce89f02 100644
--- a/editor/plugins/canvas_item_editor_plugin.cpp
+++ b/editor/plugins/canvas_item_editor_plugin.cpp
@@ -5401,11 +5401,13 @@ void CanvasItemEditorPlugin::make_visible(bool p_visible) {
canvas_item_editor->show();
canvas_item_editor->set_physics_process(true);
RenderingServer::get_singleton()->viewport_set_disable_2d(EditorNode::get_singleton()->get_scene_root()->get_viewport_rid(), false);
+ RenderingServer::get_singleton()->viewport_set_environment_mode(EditorNode::get_singleton()->get_scene_root()->get_viewport_rid(), RS::VIEWPORT_ENVIRONMENT_ENABLED);
} else {
canvas_item_editor->hide();
canvas_item_editor->set_physics_process(false);
RenderingServer::get_singleton()->viewport_set_disable_2d(EditorNode::get_singleton()->get_scene_root()->get_viewport_rid(), true);
+ RenderingServer::get_singleton()->viewport_set_environment_mode(EditorNode::get_singleton()->get_scene_root()->get_viewport_rid(), RS::VIEWPORT_ENVIRONMENT_DISABLED);
}
}
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 814fbb6d8e..e48a5bb95d 100644
--- a/editor/plugins/node_3d_editor_gizmos.cpp
+++ b/editor/plugins/node_3d_editor_gizmos.cpp
@@ -5058,8 +5058,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);
@@ -5069,10 +5069,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));
@@ -5083,21 +5083,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));
@@ -5108,16 +5108,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;
}
}
@@ -5126,8 +5126,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);
}
@@ -5137,7 +5137,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) {
@@ -5152,8 +5152,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)) {
@@ -5165,11 +5165,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);
}
}
@@ -5178,22 +5178,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/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp
index f1b7ed73b8..36d1e54246 100644
--- a/editor/plugins/node_3d_editor_plugin.cpp
+++ b/editor/plugins/node_3d_editor_plugin.cpp
@@ -1414,7 +1414,7 @@ Transform3D Node3DEditorViewport::_compute_transform(TransformMode p_mode, const
// Recalculate orthogonalized scale without moving origin.
if (p_orthogonal) {
- s.basis = p_original_local.basis.scaled_orthogonal(p_motion + Vector3(1, 1, 1));
+ s.basis = p_original.basis.scaled_orthogonal(p_motion + Vector3(1, 1, 1));
// The scaled_orthogonal() does not require orthogonal Basis,
// but it may make a bit skew by precision problems.
s.basis.orthogonalize();
@@ -4611,7 +4611,9 @@ void Node3DEditorViewport::update_transform(Point2 p_mousepos, bool p_shift) {
// TRANSLATORS: Refers to changing the scale of a node in the 3D editor.
set_message(TTR("Scaling:") + " (" + String::num(motion_snapped.x, snap_step_decimals) + ", " +
String::num(motion_snapped.y, snap_step_decimals) + ", " + String::num(motion_snapped.z, snap_step_decimals) + ")");
- motion = _edit.original.basis.inverse().xform(motion);
+ if (local_coords) {
+ motion = _edit.original.basis.inverse().xform(motion);
+ }
List<Node *> &selection = editor_selection->get_selected_node_list();
for (Node *E : selection) {
@@ -4639,7 +4641,7 @@ void Node3DEditorViewport::update_transform(Point2 p_mousepos, bool p_shift) {
se->gizmo->set_subgizmo_transform(GE.key, new_xform);
}
} else {
- Transform3D new_xform = _compute_transform(TRANSFORM_SCALE, se->original, se->original_local, motion, snap, local_coords, sp->get_rotation_edit_mode() != Node3D::ROTATION_EDIT_MODE_BASIS);
+ Transform3D new_xform = _compute_transform(TRANSFORM_SCALE, se->original, se->original_local, motion, snap, local_coords, sp->get_rotation_edit_mode() != Node3D::ROTATION_EDIT_MODE_BASIS && _edit.plane != TRANSFORM_VIEW);
_transform_gizmo_apply(se->sp, new_xform, local_coords);
}
}
@@ -4712,7 +4714,9 @@ void Node3DEditorViewport::update_transform(Point2 p_mousepos, bool p_shift) {
// TRANSLATORS: Refers to changing the position of a node in the 3D editor.
set_message(TTR("Translating:") + " (" + String::num(motion_snapped.x, snap_step_decimals) + ", " +
String::num(motion_snapped.y, snap_step_decimals) + ", " + String::num(motion_snapped.z, snap_step_decimals) + ")");
- motion = spatial_editor->get_gizmo_transform().basis.inverse().xform(motion);
+ if (local_coords) {
+ motion = spatial_editor->get_gizmo_transform().basis.inverse().xform(motion);
+ }
List<Node *> &selection = editor_selection->get_selected_node_list();
for (Node *E : selection) {
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..14b5f7cefb 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,24 @@ 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")));
+ anim_loop->set_icon(get_theme_icon(SNAME("Loop"), 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 +455,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 +489,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 +560,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 +603,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 +627,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 +651,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 +677,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 +700,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 +723,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 +816,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();
+
+ _select_animation(name);
+ animations->grab_focus();
+}
- edited_anim = name;
+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));
- undo_redo->commit_action();
+ 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 +868,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 +894,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 +939,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 +953,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 +1005,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 +1046,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 +1080,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)) {
@@ -1018,18 +1115,19 @@ void SpriteFramesEditor::_update_library(bool p_skip_selector) {
}
for (int i = 0; i < frames->get_frame_count(edited_anim); i++) {
- String name;
+ String name = itos(i);
Ref<Texture2D> texture = frames->get_frame_texture(edited_anim, i);
float duration = frames->get_frame_duration(edited_anim, i);
- String duration_string;
- if (duration != 1.0f) {
- duration_string = String::utf8(" [ ×") + String::num_real(frames->get_frame_duration(edited_anim, i)) + " ]";
- }
if (texture.is_null()) {
- name = itos(i) + ": " + TTR("(empty)") + duration_string;
- } else {
- name = itos(i) + ": " + texture->get_name() + duration_string;
+ texture = empty_icon;
+ name += ": " + TTR("(empty)");
+ } else if (!texture->get_name().is_empty()) {
+ name += ": " + texture->get_name();
+ }
+
+ if (duration != 1.0f) {
+ name += String::utf8(" [× ") + String::num(duration, 2) + "]";
}
frame_list->add_item(name, texture);
@@ -1061,20 +1159,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 +1210,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 +1320,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 +1350,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 +1523,37 @@ 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);
+
+ hbc_animlist->add_child(memnew(VSeparator));
+
+ anim_loop = memnew(Button);
+ anim_loop->set_toggle_mode(true);
+ anim_loop->set_flat(true);
+ anim_loop->set_tooltip_text(TTR("Animation Looping"));
+ anim_loop->connect("pressed", callable_mp(this, &SpriteFramesEditor::_animation_loop_changed));
+ hbc_animlist->add_child(anim_loop);
+
+ anim_speed = memnew(SpinBox);
+ anim_speed->set_suffix(TTR("FPS"));
+ anim_speed->set_min(0);
+ anim_speed->set_max(120);
+ anim_speed->set_step(0.01);
+ anim_speed->set_custom_arrow_step(1);
+ anim_speed->set_tooltip_text(TTR("Animation Speed"));
+ anim_speed->connect("value_changed", callable_mp(this, &SpriteFramesEditor::_animation_speed_changed));
+ hbc_animlist->add_child(anim_speed);
+
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 +1563,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);
@@ -1292,23 +1572,6 @@ SpriteFramesEditor::SpriteFramesEditor() {
delete_anim->set_shortcut_context(animations);
delete_anim->set_shortcut(ED_SHORTCUT("sprite_frames/delete_animation", TTR("Delete Animation"), Key::KEY_DELETE));
- HBoxContainer *hbc_anim_speed = memnew(HBoxContainer);
- hbc_anim_speed->add_child(memnew(Label(TTR("Speed:"))));
- vbc_animlist->add_child(hbc_anim_speed);
- anim_speed = memnew(SpinBox);
- anim_speed->set_suffix(TTR("FPS"));
- anim_speed->set_min(0);
- anim_speed->set_max(120);
- anim_speed->set_step(0.01);
- anim_speed->set_h_size_flags(SIZE_EXPAND_FILL);
- hbc_anim_speed->add_child(anim_speed);
- anim_speed->connect("value_changed", callable_mp(this, &SpriteFramesEditor::_animation_speed_changed));
-
- anim_loop = memnew(CheckButton);
- anim_loop->set_text(TTR("Loop"));
- vbc_animlist->add_child(anim_loop);
- anim_loop->connect("pressed", callable_mp(this, &SpriteFramesEditor::_animation_loop_changed));
-
VBoxContainer *vbc = memnew(VBoxContainer);
add_child(vbc);
vbc->set_h_size_flags(SIZE_EXPAND_FILL);
@@ -1319,6 +1582,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 +1670,11 @@ 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_custom_arrow_step(0.1);
+ frame_duration->set_allow_lesser(false);
frame_duration->set_allow_greater(true);
hbc->add_child(frame_duration);
@@ -1616,16 +1919,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;
}
}
@@ -1650,9 +1953,7 @@ void SpriteFramesEditorPlugin::make_visible(bool p_visible) {
EditorNode::get_singleton()->make_bottom_panel_item_visible(frames_editor);
} else {
button->hide();
- if (frames_editor->is_visible_in_tree()) {
- EditorNode::get_singleton()->hide_bottom_panel();
- }
+ frames_editor->edit(Ref<SpriteFrames>());
}
}
diff --git a/editor/plugins/sprite_frames_editor_plugin.h b/editor/plugins/sprite_frames_editor_plugin.h
index a5e0e54fb8..1dfb909388 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,18 @@ class SpriteFramesEditor : public HSplitContainer {
bool read_only = false;
+ Ref<Texture2D> autoplay_icon;
+ Ref<Texture2D> stop_icon;
+ Ref<Texture2D> pause_icon;
+ Ref<Texture2D> empty_icon = memnew(ImageTexture);
+
+ 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,18 +101,19 @@ class SpriteFramesEditor : public HSplitContainer {
Button *add_anim = nullptr;
Button *delete_anim = nullptr;
- LineEdit *anim_search_box = nullptr;
+ SpinBox *anim_speed = nullptr;
+ Button *anim_loop = nullptr;
+
+ HBoxContainer *autoplay_container = nullptr;
+ Button *autoplay = nullptr;
+ LineEdit *anim_search_box = nullptr;
Tree *animations = nullptr;
- SpinBox *anim_speed = nullptr;
- CheckButton *anim_loop = nullptr;
EditorFileDialog *file = nullptr;
AcceptDialog *dialog = nullptr;
- SpriteFrames *frames = nullptr;
-
StringName edited_anim;
ConfirmationDialog *delete_dialog = nullptr;
@@ -146,7 +163,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 +208,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/text_shader_editor.cpp b/editor/plugins/text_shader_editor.cpp
index 1b29999796..ffd9564816 100644
--- a/editor/plugins/text_shader_editor.cpp
+++ b/editor/plugins/text_shader_editor.cpp
@@ -383,11 +383,12 @@ void ShaderTextEditor::_code_complete_script(const String &p_code, List<ScriptLa
List<ScriptLanguage::CodeCompletionOption> pp_defines;
ShaderPreprocessor preprocessor;
String code;
- complete_from_path = (shader.is_valid() ? shader->get_path() : shader_inc->get_path()).get_base_dir();
+ String resource_path = (shader.is_valid() ? shader->get_path() : shader_inc->get_path());
+ complete_from_path = resource_path.get_base_dir();
if (!complete_from_path.ends_with("/")) {
complete_from_path += "/";
}
- preprocessor.preprocess(p_code, "", code, nullptr, nullptr, nullptr, nullptr, &pp_options, &pp_defines, _complete_include_paths);
+ preprocessor.preprocess(p_code, resource_path, code, nullptr, nullptr, nullptr, nullptr, &pp_options, &pp_defines, _complete_include_paths);
complete_from_path = String();
if (pp_options.size()) {
for (const ScriptLanguage::CodeCompletionOption &E : pp_options) {
diff --git a/editor/plugins/texture_region_editor_plugin.cpp b/editor/plugins/texture_region_editor_plugin.cpp
index 76f2bb7bb5..c5aa60c816 100644
--- a/editor/plugins/texture_region_editor_plugin.cpp
+++ b/editor/plugins/texture_region_editor_plugin.cpp
@@ -740,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());
+ }
}
}
diff --git a/editor/plugins/tiles/tile_atlas_view.cpp b/editor/plugins/tiles/tile_atlas_view.cpp
index e430848875..fd651dd507 100644
--- a/editor/plugins/tiles/tile_atlas_view.cpp
+++ b/editor/plugins/tiles/tile_atlas_view.cpp
@@ -247,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);
@@ -322,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);
}
}
}
@@ -372,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);
}
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 3dc42b4481..f0a02a3768 100644
--- a/editor/plugins/tiles/tile_map_editor.cpp
+++ b/editor/plugins/tiles/tile_map_editor.cpp
@@ -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;
@@ -3997,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);
@@ -4012,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 a12a647e99..840a3911af 100644
--- a/editor/plugins/tiles/tile_set_atlas_source_editor.cpp
+++ b/editor/plugins/tiles/tile_set_atlas_source_editor.cpp
@@ -640,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");
@@ -1864,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);
@@ -1887,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);
@@ -2039,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);
@@ -2063,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);
@@ -2704,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/tiles_editor_plugin.cpp b/editor/plugins/tiles/tiles_editor_plugin.cpp
index 77dd0f7793..fad36660d9 100644
--- a/editor/plugins/tiles/tiles_editor_plugin.cpp
+++ b/editor/plugins/tiles/tiles_editor_plugin.cpp
@@ -106,7 +106,7 @@ void TilesEditorPlugin::_thread() {
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/progress_dialog.cpp b/editor/progress_dialog.cpp
index 37f941c7b2..9695a7042d 100644
--- a/editor/progress_dialog.cpp
+++ b/editor/progress_dialog.cpp
@@ -257,6 +257,7 @@ ProgressDialog::ProgressDialog() {
add_child(main);
main->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT);
set_exclusive(true);
+ set_flag(Window::FLAG_POPUP, false);
last_progress_tick = 0;
singleton = this;
cancel_hb = memnew(HBoxContainer);
diff --git a/editor/project_converter_3_to_4.cpp b/editor/project_converter_3_to_4.cpp
index 88fb88de98..d3e16211f7 100644
--- a/editor/project_converter_3_to_4.cpp
+++ b/editor/project_converter_3_to_4.cpp
@@ -32,10 +32,11 @@
#include "modules/modules_enabled.gen.h"
-const int ERROR_CODE = 77;
-
+#ifndef DISABLE_DEPRECATED
#ifdef MODULE_REGEX_ENABLED
+const int ERROR_CODE = 77;
+
#include "modules/regex/regex.h"
#include "core/io/dir_access.h"
@@ -44,7 +45,7 @@ const int ERROR_CODE = 77;
#include "core/templates/list.h"
#include "core/templates/local_vector.h"
-static const char *enum_renames[][2] = {
+const char *ProjectConverter3To4::enum_renames[][2] = {
//// constants
{ "TYPE_COLOR_ARRAY", "TYPE_PACKED_COLOR_ARRAY" },
{ "TYPE_FLOAT64_ARRAY", "TYPE_PACKED_FLOAT64_ARRAY" },
@@ -164,7 +165,7 @@ static const char *enum_renames[][2] = {
{ nullptr, nullptr },
};
-static const char *gdscript_function_renames[][2] = {
+const char *ProjectConverter3To4::gdscript_function_renames[][2] = {
// { "_set_name", "get_tracker_name"}, // XRPositionalTracker - CameraFeed use this
// { "_unhandled_input", "_unhandled_key_input"}, // BaseButton, ViewportContainer broke Node, FileDialog,SubViewportContainer
// { "create_gizmo", "_create_gizmo"}, // EditorNode3DGizmoPlugin - may be used
@@ -215,7 +216,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
@@ -241,6 +241,9 @@ static const char *gdscript_function_renames[][2] = {
{ "can_generate_small_preview", "_can_generate_small_preview" }, // EditorResourcePreviewGenerator
{ "can_instance", "can_instantiate" }, // PackedScene, Script
{ "canvas_light_set_scale", "canvas_light_set_texture_scale" }, // RenderingServer
+ { "capture_get_device", "get_input_device" }, // AudioServer
+ { "capture_get_device_list", "get_input_device_list" }, // AudioServer
+ { "capture_set_device", "set_input_device" }, // AudioServer
{ "center_viewport_to_cursor", "center_viewport_to_caret" }, // TextEdit
{ "change_scene", "change_scene_to_file" }, // SceneTree
{ "change_scene_to", "change_scene_to_packed" }, // SceneTree
@@ -301,6 +304,8 @@ static const char *gdscript_function_renames[][2] = {
{ "get_cursor_position", "get_caret_column" }, // LineEdit
{ "get_d", "get_distance" }, // LineShape2D
{ "get_depth_bias_enable", "get_depth_bias_enabled" }, // RDPipelineRasterizationState
+ { "get_device", "get_output_device" }, // AudioServer
+ { "get_device_list", "get_output_device_list" }, // AudioServer
{ "get_drag_data", "_get_drag_data" }, // Control
{ "get_editor_viewport", "get_editor_main_screen" }, // EditorPlugin
{ "get_enabled_focus_mode", "get_focus_mode" }, // BaseButton
@@ -312,8 +317,8 @@ static const char *gdscript_function_renames[][2] = {
{ "get_font_types", "get_font_type_list" }, // Theme
{ "get_frame_color", "get_color" }, // ColorRect
{ "get_global_rate_scale", "get_playback_speed_scale" }, // AudioServer
- { "get_gravity_distance_scale", "get_gravity_point_distance_scale" }, //Area2D
- { "get_gravity_vector", "get_gravity_direction" }, //Area2D
+ { "get_gravity_distance_scale", "get_gravity_point_unit_distance" }, // Area(2D/3D)
+ { "get_gravity_vector", "get_gravity_direction" }, // Area(2D/3D)
{ "get_h_scrollbar", "get_h_scroll_bar" }, //ScrollContainer
{ "get_hand", "get_tracker_hand" }, // XRPositionalTracker
{ "get_handle_name", "_get_handle_name" }, // EditorNode3DGizmo
@@ -499,6 +504,7 @@ static const char *gdscript_function_renames[][2] = {
{ "set_cursor_position", "set_caret_column" }, // LineEdit
{ "set_d", "set_distance" }, // WorldMarginShape2D
{ "set_depth_bias_enable", "set_depth_bias_enabled" }, // RDPipelineRasterizationState
+ { "set_device", "set_output_device" }, // AudioServer
{ "set_doubleclick", "set_double_click" }, // InputEventMouseButton
{ "set_draw_red", "set_draw_warning" }, // EditorProperty
{ "set_enable_follow_smoothing", "set_position_smoothing_enabled" }, // Camera2D
@@ -510,8 +516,8 @@ static const char *gdscript_function_renames[][2] = {
{ "set_follow_smoothing", "set_position_smoothing_speed" }, // Camera2D
{ "set_frame_color", "set_color" }, // ColorRect
{ "set_global_rate_scale", "set_playback_speed_scale" }, // AudioServer
- { "set_gravity_distance_scale", "set_gravity_point_distance_scale" }, // Area2D
- { "set_gravity_vector", "set_gravity_direction" }, // Area2D
+ { "set_gravity_distance_scale", "set_gravity_point_unit_distance" }, // Area(2D/3D)
+ { "set_gravity_vector", "set_gravity_direction" }, // Area(2D/3D)
{ "set_h_drag_enabled", "set_drag_horizontal_enabled" }, // Camera2D
{ "set_icon_align", "set_icon_alignment" }, // Button
{ "set_interior_ambient", "set_ambient_color" }, // ReflectionProbe
@@ -620,7 +626,7 @@ static const char *gdscript_function_renames[][2] = {
};
// gdscript_function_renames clone with CamelCase
-static const char *csharp_function_renames[][2] = {
+const char *ProjectConverter3To4::csharp_function_renames[][2] = {
// { "_SetName", "GetTrackerName"}, // XRPositionalTracker - CameraFeed use this
// { "_UnhandledInput", "_UnhandledKeyInput"}, // BaseButton, ViewportContainer broke Node, FileDialog,SubViewportContainer
// { "CreateGizmo", "_CreateGizmo"}, // EditorNode3DGizmoPlugin - may be used
@@ -697,6 +703,9 @@ static const char *csharp_function_renames[][2] = {
{ "CanGenerateSmallPreview", "_CanGenerateSmallPreview" }, // EditorResourcePreviewGenerator
{ "CanInstance", "CanInstantiate" }, // PackedScene, Script
{ "CanvasLightSetScale", "CanvasLightSetTextureScale" }, // RenderingServer
+ { "CaptureGetDevice", "GetInputDevice" }, // AudioServer
+ { "CaptureGetDeviceList", "GetInputDeviceList" }, // AudioServer
+ { "CaptureSetDevice", "SetInputDevice" }, // AudioServer
{ "CenterViewportToCursor", "CenterViewportToCaret" }, // TextEdit
{ "ChangeScene", "ChangeSceneToFile" }, // SceneTree
{ "ChangeSceneTo", "ChangeSceneToPacked" }, // SceneTree
@@ -754,6 +763,8 @@ static const char *csharp_function_renames[][2] = {
{ "GetCursorPosition", "GetCaretColumn" }, // LineEdit
{ "GetD", "GetDistance" }, // LineShape2D
{ "GetDepthBiasEnable", "GetDepthBiasEnabled" }, // RDPipelineRasterizationState
+ { "GetDevice", "GetOutputDevice" }, // AudioServer
+ { "GetDeviceList", "GetOutputDeviceList" }, // AudioServer
{ "GetDragDataFw", "_GetDragDataFw" }, // ScriptEditor
{ "GetEditorViewport", "GetViewport" }, // EditorPlugin
{ "GetEnabledFocusMode", "GetFocusMode" }, // BaseButton
@@ -942,6 +953,7 @@ static const char *csharp_function_renames[][2] = {
{ "SetCursorPosition", "SetCaretColumn" }, // LineEdit
{ "SetD", "SetDistance" }, // WorldMarginShape2D
{ "SetDepthBiasEnable", "SetDepthBiasEnabled" }, // RDPipelineRasterizationState
+ { "SetDevice", "SetOutputDevice" }, // AudioServer
{ "SetDoubleclick", "SetDoubleClick" }, // InputEventMouseButton
{ "SetEnableFollowSmoothing", "SetFollowSmoothingEnabled" }, // Camera2D
{ "SetEnabledFocusMode", "SetFocusMode" }, // BaseButton
@@ -1057,7 +1069,7 @@ static const char *csharp_function_renames[][2] = {
};
// Some needs to be disabled, because users can use this names as variables
-static const char *gdscript_properties_renames[][2] = {
+const char *ProjectConverter3To4::gdscript_properties_renames[][2] = {
// // { "d", "distance" }, //WorldMarginShape2D - TODO, looks that polish letters ą ę are treaten as space, not as letter, so `będą` are renamed to `będistanceą`
// // {"alt","alt_pressed"}, // This may broke a lot of comments and user variables
// // {"command","command_pressed"},// This may broke a lot of comments and user variables
@@ -1070,6 +1082,7 @@ static const char *gdscript_properties_renames[][2] = {
// // {"shift","shift_pressed"},// This may broke a lot of comments and user variables
// { "autowrap", "autowrap_mode" }, // Label
// { "cast_to", "target_position" }, // RayCast2D, RayCast3D
+ // { "device", "output_device"}, // AudioServer - Too vague, most likely breaks comments & variables
// { "doubleclick", "double_click" }, // InputEventMouseButton
// { "group", "button_group" }, // BaseButton
// { "process_mode", "process_callback" }, // AnimationTree, Camera2D
@@ -1085,6 +1098,7 @@ static const char *gdscript_properties_renames[][2] = {
{ "bbcode_text", "text" }, // RichTextLabel
{ "bg", "panel" }, // Theme
{ "bg_focus", "focus" }, // Theme
+ { "capture_device", "input_device" }, // AudioServer
{ "caret_blink_speed", "caret_blink_interval" }, // TextEdit, LineEdit
{ "caret_moving_by_right_click", "caret_move_on_right_click" }, // TextEdit
{ "caret_position", "caret_column" }, // LineEdit
@@ -1112,8 +1126,8 @@ static const char *gdscript_properties_renames[][2] = {
{ "files_disabled", "file_disabled_color" }, // Theme
{ "folder_icon_modulate", "folder_icon_color" }, // Theme
{ "global_rate_scale", "playback_speed_scale" }, // AudioServer
- { "gravity_distance_scale", "gravity_point_distance_scale" }, // Area2D
- { "gravity_vec", "gravity_direction" }, // Area2D
+ { "gravity_distance_scale", "gravity_point_unit_distance" }, // Area(2D/3D)
+ { "gravity_vec", "gravity_direction" }, // Area(2D/3D)
{ "hint_tooltip", "tooltip_text" }, // Control
{ "hseparation", "h_separation" }, // Theme
{ "icon_align", "icon_alignment" }, // Button
@@ -1168,12 +1182,13 @@ 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 },
};
// Some needs to be disabled, because users can use this names as variables
-static const char *csharp_properties_renames[][2] = {
+const char *ProjectConverter3To4::csharp_properties_renames[][2] = {
// // { "D", "Distance" }, //WorldMarginShape2D - TODO, looks that polish letters ą ę are treaten as space, not as letter, so `będą` are renamed to `będistanceą`
// // {"Alt","AltPressed"}, // This may broke a lot of comments and user variables
// // {"Command","CommandPressed"},// This may broke a lot of comments and user variables
@@ -1278,7 +1293,7 @@ static const char *csharp_properties_renames[][2] = {
{ nullptr, nullptr },
};
-static const char *gdscript_signals_renames[][2] = {
+const char *ProjectConverter3To4::gdscript_signals_renames[][2] = {
// {"instantiate","instance"}, // FileSystemDock
// { "hide", "hidden" }, // CanvasItem - function with same name exists
// { "tween_all_completed","loop_finished"}, // Tween - TODO, not sure
@@ -1303,7 +1318,7 @@ static const char *gdscript_signals_renames[][2] = {
{ nullptr, nullptr },
};
-static const char *csharp_signals_renames[][2] = {
+const char *ProjectConverter3To4::csharp_signals_renames[][2] = {
// {"Instantiate","Instance"}, // FileSystemDock
// { "Hide", "Hidden" }, // CanvasItem - function with same name exists
// { "TweenAllCompleted","LoopFinished"}, // Tween - TODO, not sure
@@ -1327,7 +1342,7 @@ static const char *csharp_signals_renames[][2] = {
};
-static const char *project_settings_renames[][2] = {
+const char *ProjectConverter3To4::project_settings_renames[][2] = {
{ "audio/channel_disable_threshold_db", "audio/buses/channel_disable_threshold_db" },
{ "audio/channel_disable_time", "audio/buses/channel_disable_time" },
{ "audio/default_bus_layout", "audio/buses/default_bus_layout" },
@@ -1362,16 +1377,17 @@ static const char *project_settings_renames[][2] = {
{ "rendering/quality/shadow_atlas/quadrant_3_subdiv", "rendering/lights_and_shadows/shadow_atlas/quadrant_3_subdiv" },
{ "rendering/quality/shadow_atlas/size", "rendering/lights_and_shadows/shadow_atlas/size" },
{ "rendering/quality/shadow_atlas/size.mobile", "rendering/lights_and_shadows/shadow_atlas/size.mobile" },
- { "rendering/vram_compression/import_bptc", "rendering/textures/vram_compression/import_bptc" },
- { "rendering/vram_compression/import_etc", "rendering/textures/vram_compression/import_etc" },
- { "rendering/vram_compression/import_etc2", "rendering/textures/vram_compression/import_etc2" },
- { "rendering/vram_compression/import_pvrtc", "rendering/textures/vram_compression/import_pvrtc" },
- { "rendering/vram_compression/import_s3tc", "rendering/textures/vram_compression/import_s3tc" },
+ { "rendering/vram_compression/import_etc2", "rendering/textures/vram_compression/import_etc2_astc" },
+ { "rendering/vram_compression/import_s3tc", "rendering/textures/vram_compression/import_s3tc_bptc" },
+ { "window/size/width", "window/size/viewport_width" },
+ { "window/size/height", "window/size/viewport_height" },
+ { "window/size/test_width", "window/size/window_width_override" },
+ { "window/size/test_height", "window/size/window_height_override" },
{ nullptr, nullptr },
};
-static const char *input_map_renames[][2] = {
+const char *ProjectConverter3To4::input_map_renames[][2] = {
{ ",\"alt\":", ",\"alt_pressed\":" },
{ ",\"shift\":", ",\"shift_pressed\":" },
{ ",\"control\":", ",\"ctrl_pressed\":" },
@@ -1383,7 +1399,7 @@ static const char *input_map_renames[][2] = {
{ nullptr, nullptr },
};
-static const char *builtin_types_renames[][2] = {
+const char *ProjectConverter3To4::builtin_types_renames[][2] = {
{ "PoolByteArray", "PackedByteArray" },
{ "PoolColorArray", "PackedColorArray" },
{ "PoolIntArray", "PackedInt32Array" },
@@ -1397,7 +1413,7 @@ static const char *builtin_types_renames[][2] = {
{ nullptr, nullptr },
};
-static const char *shaders_renames[][2] = {
+const char *ProjectConverter3To4::shaders_renames[][2] = {
{ "ALPHA_SCISSOR", "ALPHA_SCISSOR_THRESHOLD" },
{ "CAMERA_MATRIX", "INV_VIEW_MATRIX" },
{ "INV_CAMERA_MATRIX", "VIEW_MATRIX" },
@@ -1415,7 +1431,7 @@ static const char *shaders_renames[][2] = {
{ nullptr, nullptr },
};
-static const char *class_renames[][2] = {
+const char *ProjectConverter3To4::class_renames[][2] = {
// { "BulletPhysicsDirectBodyState", "BulletPhysicsDirectBodyState3D" }, // Class is not visible in ClassDB
// { "BulletPhysicsServer", "BulletPhysicsServer3D" }, // Class is not visible in ClassDB
// { "GDScriptFunctionState", "Node3D" }, // TODO - not sure to which should be changed
@@ -1640,7 +1656,7 @@ static const char *class_renames[][2] = {
{ nullptr, nullptr },
};
-static const char *color_renames[][2] = {
+const char *ProjectConverter3To4::ProjectConverter3To4::color_renames[][2] = {
{ "aliceblue", "ALICE_BLUE" },
{ "antiquewhite", "ANTIQUE_WHITE" },
{ "aqua", "AQUA" },
@@ -2549,14 +2565,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);
@@ -4087,13 +4103,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);
@@ -4102,13 +4118,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);
}
}
}
@@ -4156,25 +4172,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));
}
}
@@ -4196,9 +4212,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));
}
}
@@ -4212,9 +4228,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));
}
}
}
@@ -4349,3 +4365,4 @@ int ProjectConverter3To4::validate_conversion() {
}
#endif // MODULE_REGEX_ENABLED
+#endif // DISABLE_DEPRECATED
diff --git a/editor/project_converter_3_to_4.h b/editor/project_converter_3_to_4.h
index b3aa52f1e3..6ec2dd188d 100644
--- a/editor/project_converter_3_to_4.h
+++ b/editor/project_converter_3_to_4.h
@@ -29,6 +29,7 @@
/**************************************************************************/
#ifndef PROJECT_CONVERTER_3_TO_4_H
+#ifndef DISABLE_DEPRECATED
#define PROJECT_CONVERTER_3_TO_4_H
#include "core/io/file_access.h"
@@ -41,6 +42,19 @@ class RegEx;
class ProjectConverter3To4 {
public:
class RegExContainer;
+ static const char *enum_renames[][2];
+ static const char *gdscript_function_renames[][2];
+ static const char *csharp_function_renames[][2];
+ static const char *gdscript_properties_renames[][2];
+ static const char *csharp_properties_renames[][2];
+ static const char *gdscript_signals_renames[][2];
+ static const char *csharp_signals_renames[][2];
+ static const char *project_settings_renames[][2];
+ static const char *input_map_renames[][2];
+ static const char *builtin_types_renames[][2];
+ static const char *shaders_renames[][2];
+ static const char *class_renames[][2];
+ static const char *color_renames[][2];
private:
uint64_t maximum_file_size;
@@ -97,4 +111,6 @@ public:
int convert();
};
+#endif // DISABLE_DEPRECATED
+
#endif // PROJECT_CONVERTER_3_TO_4_H
diff --git a/editor/project_settings_editor.cpp b/editor/project_settings_editor.cpp
index 560549d249..a43745b70f 100644
--- a/editor/project_settings_editor.cpp
+++ b/editor/project_settings_editor.cpp
@@ -370,17 +370,7 @@ void ProjectSettingsEditor::_action_edited(const String &p_name, const Dictionar
} else {
// Events changed
- int act_event_count = ((Array)p_action["events"]).size();
- int old_event_count = ((Array)old_val["events"]).size();
-
- if (act_event_count == old_event_count) {
- undo_redo->create_action(TTR("Edit Input Action Event"));
- } else if (act_event_count > old_event_count) {
- undo_redo->create_action(TTR("Add Input Action Event"));
- } else {
- undo_redo->create_action(TTR("Remove Input Action Event"));
- }
-
+ undo_redo->create_action(TTR("Change Input Action Event(s)"));
undo_redo->add_do_method(ProjectSettings::get_singleton(), "set", property_name, p_action);
undo_redo->add_undo_method(ProjectSettings::get_singleton(), "set", property_name, old_val);
}
@@ -527,6 +517,8 @@ void ProjectSettingsEditor::_update_action_map_editor() {
if (is_builtin_input) {
action_info.editable = false;
action_info.icon = builtin_icon;
+ action_info.has_initial = true;
+ action_info.action_initial = ProjectSettings::get_singleton()->property_get_revert(property_name);
}
actions.push_back(action_info);