Skip to content

Commit 4a34c24

Browse files
committed
Save scene together with script/shader when ctrl-s is pressed.
Fixes godotengine#84601. The scene will also silently be saved (just like before), since many users are not necessarily aware that the script or shader editor editors are focused at the time of saving. Now, however, if something causes the save to fail it will not be notified to the user, in case the user to avoid the annoyance caused by godotengine#84039.
1 parent 3e7f638 commit 4a34c24

File tree

6 files changed

+97
-11
lines changed

6 files changed

+97
-11
lines changed

core/input/shortcut.cpp

+24
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,30 @@ String Shortcut::get_as_text() const {
8686
return "None";
8787
}
8888

89+
bool Shortcut::is_match(const Ref<Shortcut> &p_shortcut) const {
90+
if (p_shortcut.is_null()) {
91+
return false;
92+
}
93+
94+
for (int i = 0; i < events.size(); i++) {
95+
Ref<InputEvent> ie = events[i];
96+
if (!ie.is_valid()) {
97+
continue;
98+
}
99+
for (int j = 0; j < p_shortcut->events.size(); j++) {
100+
Ref<InputEvent> ie_overlap = p_shortcut->events[i];
101+
if (!ie_overlap.is_valid()) {
102+
continue;
103+
}
104+
105+
if (ie->is_match(ie_overlap)) {
106+
return true;
107+
}
108+
}
109+
}
110+
return false;
111+
}
112+
89113
bool Shortcut::has_valid_event() const {
90114
// Tests if there is ANY input event which is valid.
91115
for (int i = 0; i < events.size(); i++) {

core/input/shortcut.h

+2
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ class Shortcut : public Resource {
5151
bool matches_event(const Ref<InputEvent> &p_event) const;
5252
bool has_valid_event() const;
5353

54+
bool is_match(const Ref<Shortcut> &p_shortcut) const;
55+
5456
String get_as_text() const;
5557

5658
static bool is_event_array_equal(const Array &p_event_array1, const Array &p_event_array2);

editor/editor_node.cpp

+35-7
Original file line numberDiff line numberDiff line change
@@ -1579,7 +1579,7 @@ void EditorNode::_find_node_types(Node *p_node, int &count_2d, int &count_3d) {
15791579
}
15801580
}
15811581

1582-
void EditorNode::_save_scene_with_preview(String p_file, int p_idx) {
1582+
void EditorNode::_save_scene_with_preview(String p_file, int p_idx, bool p_show_error_dialogs) {
15831583
EditorProgress save("save", TTR("Saving Scene"), 4);
15841584

15851585
if (editor_data.get_edited_scene_root() != nullptr) {
@@ -1656,7 +1656,7 @@ void EditorNode::_save_scene_with_preview(String p_file, int p_idx) {
16561656
}
16571657

16581658
save.step(TTR("Saving Scene"), 4);
1659-
_save_scene(p_file, p_idx);
1659+
_save_scene(p_file, p_idx, p_show_error_dialogs);
16601660

16611661
if (!singleton->cmdline_export_mode) {
16621662
EditorResourcePreview::get_singleton()->check_for_invalidation(p_file);
@@ -1745,16 +1745,40 @@ static void _reset_animation_mixers(Node *p_node, List<Pair<AnimationMixer *, Re
17451745
}
17461746
}
17471747

1748-
void EditorNode::_save_scene(String p_file, int idx) {
1748+
void EditorNode::save_scene_if_valid() {
1749+
// Do not save if no editing was made.
1750+
if (!EditorUndoRedoManager::get_singleton()->is_history_unsaved(editor_data.get_current_edited_scene_history_id())) {
1751+
return;
1752+
}
1753+
// Do not save if not saved before.
1754+
Node *scene = editor_data.get_edited_scene_root();
1755+
if (!scene || scene->get_scene_file_path().is_empty()) {
1756+
return;
1757+
}
1758+
1759+
// Do not save if path gone.
1760+
if (!DirAccess::exists(scene->get_scene_file_path().get_base_dir())) {
1761+
return;
1762+
}
1763+
1764+
_save_scene(scene->get_scene_file_path(), -1, false);
1765+
save_editor_layout_delayed();
1766+
}
1767+
1768+
void EditorNode::_save_scene(String p_file, int idx, bool p_show_error_dialogs) {
17491769
Node *scene = editor_data.get_edited_scene_root(idx);
17501770

17511771
if (!scene) {
1752-
show_accept(TTR("This operation can't be done without a tree root."), TTR("OK"));
1772+
if (p_show_error_dialogs) {
1773+
show_accept(TTR("This operation can't be done without a tree root."), TTR("OK"));
1774+
}
17531775
return;
17541776
}
17551777

17561778
if (!scene->get_scene_file_path().is_empty() && _validate_scene_recursive(scene->get_scene_file_path(), scene)) {
1757-
show_accept(TTR("This scene can't be saved because there is a cyclic instance inclusion.\nPlease resolve it and then attempt to save again."), TTR("OK"));
1779+
if (p_show_error_dialogs) {
1780+
show_accept(TTR("This scene can't be saved because there is a cyclic instance inclusion.\nPlease resolve it and then attempt to save again."), TTR("OK"));
1781+
}
17581782
return;
17591783
}
17601784

@@ -1786,7 +1810,9 @@ void EditorNode::_save_scene(String p_file, int idx) {
17861810
Error err = sdata->pack(scene);
17871811

17881812
if (err != OK) {
1789-
show_accept(TTR("Couldn't save scene. Likely dependencies (instances or inheritance) couldn't be satisfied."), TTR("OK"));
1813+
if (p_show_error_dialogs) {
1814+
show_accept(TTR("Couldn't save scene. Likely dependencies (instances or inheritance) couldn't be satisfied."), TTR("OK"));
1815+
}
17901816
return;
17911817
}
17921818

@@ -1818,7 +1844,9 @@ void EditorNode::_save_scene(String p_file, int idx) {
18181844
_update_title();
18191845
scene_tabs->update_scene_tabs();
18201846
} else {
1821-
_dialog_display_save_error(p_file, err);
1847+
if (p_show_error_dialogs) {
1848+
_dialog_display_save_error(p_file, err);
1849+
}
18221850
}
18231851

18241852
scene->propagate_notification(NOTIFICATION_EDITOR_POST_SAVE);

editor/editor_node.h

+4-2
Original file line numberDiff line numberDiff line change
@@ -581,7 +581,7 @@ class EditorNode : public Node {
581581
void _set_current_scene(int p_idx);
582582
void _set_current_scene_nocheck(int p_idx);
583583
bool _validate_scene_recursive(const String &p_filename, Node *p_node);
584-
void _save_scene(String p_file, int idx = -1);
584+
void _save_scene(String p_file, int idx = -1, bool p_show_error_dialogs = true);
585585
void _save_all_scenes();
586586
int _next_unsaved_scene(bool p_valid_filename, int p_start = 0);
587587
void _discard_changes(const String &p_str = String());
@@ -622,7 +622,7 @@ class EditorNode : public Node {
622622
void _mark_unsaved_scenes();
623623

624624
void _find_node_types(Node *p_node, int &count_2d, int &count_3d);
625-
void _save_scene_with_preview(String p_file, int p_idx = -1);
625+
void _save_scene_with_preview(String p_file, int p_idx = -1, bool p_show_error_dialogs = true);
626626

627627
bool _find_scene_in_use(Node *p_node, const String &p_path) const;
628628

@@ -878,6 +878,8 @@ class EditorNode : public Node {
878878

879879
Control *get_gui_base() { return gui_base; }
880880

881+
void save_scene_if_valid();
882+
881883
void save_scene_to_path(String p_file, bool p_with_preview = true) {
882884
if (p_with_preview) {
883885
_save_scene_with_preview(p_file);

editor/plugins/script_editor_plugin.cpp

+12
Original file line numberDiff line numberDiff line change
@@ -1311,6 +1311,18 @@ void ScriptEditor::_menu_option(int p_option) {
13111311
switch (p_option) {
13121312
case FILE_SAVE: {
13131313
save_current_script();
1314+
{
1315+
// If both scene and script use same shortcut to save (most likely ctrl-s),
1316+
// save the current scene silently (omitting error dialogs if any).
1317+
Ref<Shortcut> save_shortcut = ED_GET_SHORTCUT("script_editor/save");
1318+
Ref<Shortcut> scene_save_shortcut = ED_GET_SHORTCUT("editor/save_scene");
1319+
if (save_shortcut.is_valid()) {
1320+
if (save_shortcut->is_match(scene_save_shortcut)) {
1321+
EditorNode::get_singleton()->save_scene_if_valid();
1322+
}
1323+
}
1324+
}
1325+
13141326
} break;
13151327
case FILE_SAVE_AS: {
13161328
if (trim_trailing_whitespace_on_save) {

editor/plugins/shader_editor_plugin.cpp

+20-2
Original file line numberDiff line numberDiff line change
@@ -413,11 +413,29 @@ void ShaderEditorPlugin::_menu_item_pressed(int p_index) {
413413
if (editor && editor->get_trim_trailing_whitespace_on_save()) {
414414
editor->trim_trailing_whitespace();
415415
}
416+
417+
Ref<Resource> resource;
416418
if (edited_shaders[index].shader.is_valid()) {
417-
EditorNode::get_singleton()->save_resource(edited_shaders[index].shader);
419+
resource = edited_shaders[index].shader;
418420
} else {
419-
EditorNode::get_singleton()->save_resource(edited_shaders[index].shader_inc);
421+
resource = edited_shaders[index].shader_inc;
420422
}
423+
424+
EditorNode::get_singleton()->save_resource(resource);
425+
426+
if (resource->get_path().is_resource_file()) {
427+
// If resource file exists, this means that the shader will not trigger a save-as popup-up.
428+
// If both scene and script use same shortcut to save (most likely ctrl-s),
429+
// save the current scene silently (omitting error dialogs if any).
430+
Ref<Shortcut> save_shortcut = ED_GET_SHORTCUT("shader_editor/save");
431+
Ref<Shortcut> scene_save_shortcut = ED_GET_SHORTCUT("editor/save_scene");
432+
if (save_shortcut.is_valid()) {
433+
if (save_shortcut->is_match(scene_save_shortcut)) {
434+
EditorNode::get_singleton()->save_scene_if_valid();
435+
}
436+
}
437+
}
438+
421439
if (editor) {
422440
editor->tag_saved_version();
423441
}

0 commit comments

Comments
 (0)