diff options
Diffstat (limited to 'editor')
25 files changed, 1243 insertions, 891 deletions
diff --git a/editor/code_editor.cpp b/editor/code_editor.cpp index 37db3ba780..ede6dde239 100644 --- a/editor/code_editor.cpp +++ b/editor/code_editor.cpp @@ -40,7 +40,7 @@ #include "scene/gui/separator.h" #include "scene/resources/dynamic_font.h" -void GotoLineDialog::popup_find_line(TextEdit *p_edit) { +void GotoLineDialog::popup_find_line(CodeEdit *p_edit) { text_editor = p_edit; line->set_text(itos(text_editor->cursor_get_line())); @@ -113,7 +113,7 @@ void FindReplaceBar::_unhandled_input(const Ref<InputEvent> &p_event) { } Control *focus_owner = get_focus_owner(); - if (text_edit->has_focus() || (focus_owner && vbc_lineedit->is_a_parent_of(focus_owner))) { + if (text_editor->has_focus() || (focus_owner && vbc_lineedit->is_a_parent_of(focus_owner))) { bool accepted = true; switch (k->get_keycode()) { @@ -135,20 +135,20 @@ bool FindReplaceBar::_search(uint32_t p_flags, int p_from_line, int p_from_col) int line, col; String text = get_search_text(); - bool found = text_edit->search(text, p_flags, p_from_line, p_from_col, line, col); + bool found = text_editor->search(text, p_flags, p_from_line, p_from_col, line, col); if (found) { if (!preserve_cursor) { - text_edit->unfold_line(line); - text_edit->cursor_set_line(line, false); - text_edit->cursor_set_column(col + text.length(), false); - text_edit->center_viewport_to_cursor(); - text_edit->select(line, col, line, col + text.length()); + text_editor->unfold_line(line); + text_editor->cursor_set_line(line, false); + text_editor->cursor_set_column(col + text.length(), false); + text_editor->center_viewport_to_cursor(); + text_editor->select(line, col, line, col + text.length()); } - text_edit->set_search_text(text); - text_edit->set_search_flags(p_flags); - text_edit->set_current_search_result(line, col); + text_editor->set_search_text(text); + text_editor->set_search_flags(p_flags); + text_editor->set_current_search_result(line, col); result_line = line; result_col = col; @@ -158,9 +158,9 @@ bool FindReplaceBar::_search(uint32_t p_flags, int p_from_line, int p_from_col) results_count = 0; result_line = -1; result_col = -1; - text_edit->set_search_text(""); - text_edit->set_search_flags(p_flags); - text_edit->set_current_search_result(line, col); + text_editor->set_search_text(""); + text_editor->set_search_flags(p_flags); + text_editor->set_current_search_result(line, col); } _update_matches_label(); @@ -169,67 +169,67 @@ bool FindReplaceBar::_search(uint32_t p_flags, int p_from_line, int p_from_col) } void FindReplaceBar::_replace() { - bool selection_enabled = text_edit->is_selection_active(); + bool selection_enabled = text_editor->is_selection_active(); Point2i selection_begin, selection_end; if (selection_enabled) { - selection_begin = Point2i(text_edit->get_selection_from_line(), text_edit->get_selection_from_column()); - selection_end = Point2i(text_edit->get_selection_to_line(), text_edit->get_selection_to_column()); + selection_begin = Point2i(text_editor->get_selection_from_line(), text_editor->get_selection_from_column()); + selection_end = Point2i(text_editor->get_selection_to_line(), text_editor->get_selection_to_column()); } String replace_text = get_replace_text(); int search_text_len = get_search_text().length(); - text_edit->begin_complex_operation(); + text_editor->begin_complex_operation(); if (selection_enabled && is_selection_only()) { // To restrict search_current() to selected region - text_edit->cursor_set_line(selection_begin.width); - text_edit->cursor_set_column(selection_begin.height); + text_editor->cursor_set_line(selection_begin.width); + text_editor->cursor_set_column(selection_begin.height); } if (search_current()) { - text_edit->unfold_line(result_line); - text_edit->select(result_line, result_col, result_line, result_col + search_text_len); + text_editor->unfold_line(result_line); + text_editor->select(result_line, result_col, result_line, result_col + search_text_len); if (selection_enabled && is_selection_only()) { Point2i match_from(result_line, result_col); Point2i match_to(result_line, result_col + search_text_len); if (!(match_from < selection_begin || match_to > selection_end)) { - text_edit->insert_text_at_cursor(replace_text); + text_editor->insert_text_at_cursor(replace_text); if (match_to.x == selection_end.x) { // Adjust selection bounds if necessary selection_end.y += replace_text.length() - search_text_len; } } } else { - text_edit->insert_text_at_cursor(replace_text); + text_editor->insert_text_at_cursor(replace_text); } } - text_edit->end_complex_operation(); + text_editor->end_complex_operation(); results_count = -1; if (selection_enabled && is_selection_only()) { // Reselect in order to keep 'Replace' restricted to selection - text_edit->select(selection_begin.x, selection_begin.y, selection_end.x, selection_end.y); + text_editor->select(selection_begin.x, selection_begin.y, selection_end.x, selection_end.y); } else { - text_edit->deselect(); + text_editor->deselect(); } } void FindReplaceBar::_replace_all() { - text_edit->disconnect("text_changed", callable_mp(this, &FindReplaceBar::_editor_text_changed)); + text_editor->disconnect("text_changed", callable_mp(this, &FindReplaceBar::_editor_text_changed)); // Line as x so it gets priority in comparison, column as y. - Point2i orig_cursor(text_edit->cursor_get_line(), text_edit->cursor_get_column()); + Point2i orig_cursor(text_editor->cursor_get_line(), text_editor->cursor_get_column()); Point2i prev_match = Point2(-1, -1); - bool selection_enabled = text_edit->is_selection_active(); + bool selection_enabled = text_editor->is_selection_active(); Point2i selection_begin, selection_end; if (selection_enabled) { - selection_begin = Point2i(text_edit->get_selection_from_line(), text_edit->get_selection_from_column()); - selection_end = Point2i(text_edit->get_selection_to_line(), text_edit->get_selection_to_column()); + selection_begin = Point2i(text_editor->get_selection_from_line(), text_editor->get_selection_from_column()); + selection_end = Point2i(text_editor->get_selection_to_line(), text_editor->get_selection_to_column()); } - int vsval = text_edit->get_v_scroll(); + int vsval = text_editor->get_v_scroll(); - text_edit->cursor_set_line(0); - text_edit->cursor_set_column(0); + text_editor->cursor_set_line(0); + text_editor->cursor_set_column(0); String replace_text = get_replace_text(); int search_text_len = get_search_text().length(); @@ -238,11 +238,11 @@ void FindReplaceBar::_replace_all() { replace_all_mode = true; - text_edit->begin_complex_operation(); + text_editor->begin_complex_operation(); if (selection_enabled && is_selection_only()) { - text_edit->cursor_set_line(selection_begin.width); - text_edit->cursor_set_column(selection_begin.height); + text_editor->cursor_set_line(selection_begin.width); + text_editor->cursor_set_column(selection_begin.height); } if (search_current()) { do { @@ -256,8 +256,8 @@ void FindReplaceBar::_replace_all() { prev_match = Point2i(result_line, result_col + replace_text.length()); - text_edit->unfold_line(result_line); - text_edit->select(result_line, result_col, result_line, match_to.y); + text_editor->unfold_line(result_line); + text_editor->select(result_line, result_col, result_line, match_to.y); if (selection_enabled && is_selection_only()) { if (match_from < selection_begin || match_to > selection_end) { @@ -265,48 +265,48 @@ void FindReplaceBar::_replace_all() { } // Replace but adjust selection bounds. - text_edit->insert_text_at_cursor(replace_text); + text_editor->insert_text_at_cursor(replace_text); if (match_to.x == selection_end.x) { selection_end.y += replace_text.length() - search_text_len; } } else { // Just replace. - text_edit->insert_text_at_cursor(replace_text); + text_editor->insert_text_at_cursor(replace_text); } rc++; } while (search_next()); } - text_edit->end_complex_operation(); + text_editor->end_complex_operation(); replace_all_mode = false; // Restore editor state (selection, cursor, scroll). - text_edit->cursor_set_line(orig_cursor.x); - text_edit->cursor_set_column(orig_cursor.y); + text_editor->cursor_set_line(orig_cursor.x); + text_editor->cursor_set_column(orig_cursor.y); if (selection_enabled && is_selection_only()) { // Reselect. - text_edit->select(selection_begin.x, selection_begin.y, selection_end.x, selection_end.y); + text_editor->select(selection_begin.x, selection_begin.y, selection_end.x, selection_end.y); } else { - text_edit->deselect(); + text_editor->deselect(); } - text_edit->set_v_scroll(vsval); + text_editor->set_v_scroll(vsval); matches_label->add_theme_color_override("font_color", rc > 0 ? get_theme_color("font_color", "Label") : get_theme_color("error_color", "Editor")); matches_label->set_text(vformat(TTR("%d replaced."), rc)); - text_edit->call_deferred("connect", "text_changed", Callable(this, "_editor_text_changed")); + text_editor->call_deferred("connect", "text_changed", Callable(this, "_editor_text_changed")); results_count = -1; } void FindReplaceBar::_get_search_from(int &r_line, int &r_col) { - r_line = text_edit->cursor_get_line(); - r_col = text_edit->cursor_get_column(); + r_line = text_editor->cursor_get_line(); + r_col = text_editor->cursor_get_column(); - if (text_edit->is_selection_active() && is_selection_only()) { + if (text_editor->is_selection_active() && is_selection_only()) { return; } @@ -327,7 +327,7 @@ void FindReplaceBar::_update_results_count() { return; } - String full_text = text_edit->get_text(); + String full_text = text_editor->get_text(); int from_pos = 0; @@ -399,7 +399,7 @@ bool FindReplaceBar::search_prev() { int line, col; _get_search_from(line, col); - if (text_edit->is_selection_active()) { + if (text_editor->is_selection_active()) { col--; // Skip currently selected word. } @@ -407,9 +407,9 @@ bool FindReplaceBar::search_prev() { if (col < 0) { line -= 1; if (line < 0) { - line = text_edit->get_line_count() - 1; + line = text_editor->get_line_count() - 1; } - col = text_edit->get_line(line).length(); + col = text_editor->get_line(line).length(); } return _search(flags, line, col); @@ -440,9 +440,9 @@ bool FindReplaceBar::search_next() { if (line == result_line && col == result_col) { col += text.length(); - if (col > text_edit->get_line(line).length()) { + if (col > text_editor->get_line(line).length()) { line += 1; - if (line >= text_edit->get_line_count()) { + if (line >= text_editor->get_line_count()) { line = 0; } col = 0; @@ -454,10 +454,10 @@ bool FindReplaceBar::search_next() { void FindReplaceBar::_hide_bar() { if (replace_text->has_focus() || search_text->has_focus()) { - text_edit->grab_focus(); + text_editor->grab_focus(); } - text_edit->set_search_text(""); + text_editor->set_search_text(""); result_line = -1; result_col = -1; hide(); @@ -477,8 +477,8 @@ void FindReplaceBar::_show_search(bool p_focus_replace, bool p_show_only) { search_text->call_deferred("grab_focus"); } - if (text_edit->is_selection_active() && !selection_only->is_pressed()) { - search_text->set_text(text_edit->get_selection_text()); + if (text_editor->is_selection_active() && !selection_only->is_pressed()) { + search_text->set_text(text_editor->get_selection_text()); } if (!get_search_text().empty()) { @@ -511,9 +511,9 @@ void FindReplaceBar::popup_replace() { hbc_option_replace->show(); } - selection_only->set_pressed((text_edit->is_selection_active() && text_edit->get_selection_from_line() < text_edit->get_selection_to_line())); + selection_only->set_pressed((text_editor->is_selection_active() && text_editor->get_selection_from_line() < text_editor->get_selection_to_line())); - _show_search(is_visible() || text_edit->is_selection_active()); + _show_search(is_visible() || text_editor->is_selection_active()); } void FindReplaceBar::_search_options_changed(bool p_pressed) { @@ -544,7 +544,7 @@ void FindReplaceBar::_search_text_entered(const String &p_text) { } void FindReplaceBar::_replace_text_entered(const String &p_text) { - if (selection_only->is_pressed() && text_edit->is_selection_active()) { + if (selection_only->is_pressed() && text_editor->is_selection_active()) { _replace_all(); _hide_bar(); } else if (Input::get_singleton()->is_key_pressed(KEY_SHIFT)) { @@ -579,10 +579,10 @@ void FindReplaceBar::set_error(const String &p_label) { emit_signal("error", p_label); } -void FindReplaceBar::set_text_edit(TextEdit *p_text_edit) { +void FindReplaceBar::set_text_edit(CodeEdit *p_text_edit) { results_count = -1; - text_edit = p_text_edit; - text_edit->connect("text_changed", callable_mp(this, &FindReplaceBar::_editor_text_changed)); + text_editor = p_text_edit; + text_editor->connect("text_changed", callable_mp(this, &FindReplaceBar::_editor_text_changed)); } void FindReplaceBar::_bind_methods() { @@ -932,11 +932,9 @@ void CodeTextEditor::update_editor_settings() { text_editor->set_v_scroll_speed(EditorSettings::get_singleton()->get("text_editor/navigation/v_scroll_speed")); text_editor->set_draw_minimap(EditorSettings::get_singleton()->get("text_editor/navigation/show_minimap")); text_editor->set_minimap_width((int)EditorSettings::get_singleton()->get("text_editor/navigation/minimap_width") * EDSCALE); - text_editor->set_show_line_numbers(EditorSettings::get_singleton()->get("text_editor/appearance/show_line_numbers")); + text_editor->set_draw_line_numbers(EditorSettings::get_singleton()->get("text_editor/appearance/show_line_numbers")); text_editor->set_line_numbers_zero_padded(EditorSettings::get_singleton()->get("text_editor/appearance/line_numbers_zero_padded")); - text_editor->set_bookmark_gutter_enabled(EditorSettings::get_singleton()->get("text_editor/appearance/show_bookmark_gutter")); - text_editor->set_breakpoint_gutter_enabled(EditorSettings::get_singleton()->get("text_editor/appearance/show_breakpoint_gutter")); - text_editor->set_draw_info_gutter(EditorSettings::get_singleton()->get("text_editor/appearance/show_info_gutter")); + text_editor->set_draw_bookmarks_gutter(EditorSettings::get_singleton()->get("text_editor/appearance/show_bookmark_gutter")); text_editor->set_hiding_enabled(EditorSettings::get_singleton()->get("text_editor/appearance/code_folding")); text_editor->set_draw_fold_gutter(EditorSettings::get_singleton()->get("text_editor/appearance/code_folding")); text_editor->set_wrap_enabled(EditorSettings::get_singleton()->get("text_editor/appearance/word_wrap")); @@ -1390,11 +1388,11 @@ void CodeTextEditor::goto_line_centered(int p_line) { } void CodeTextEditor::set_executing_line(int p_line) { - text_editor->set_executing_line(p_line); + text_editor->set_line_as_executing(p_line, true); } void CodeTextEditor::clear_executing_line() { - text_editor->clear_executing_line(); + text_editor->clear_executing_lines(); } Variant CodeTextEditor::get_edit_state() { @@ -1405,8 +1403,8 @@ Variant CodeTextEditor::get_edit_state() { state["column"] = text_editor->cursor_get_column(); state["row"] = text_editor->cursor_get_line(); - state["selection"] = get_text_edit()->is_selection_active(); - if (get_text_edit()->is_selection_active()) { + state["selection"] = get_text_editor()->is_selection_active(); + if (get_text_editor()->is_selection_active()) { state["selection_from_line"] = text_editor->get_selection_from_line(); state["selection_from_column"] = text_editor->get_selection_from_column(); state["selection_to_line"] = text_editor->get_selection_to_line(); @@ -1414,8 +1412,8 @@ Variant CodeTextEditor::get_edit_state() { } state["folded_lines"] = text_editor->get_folded_lines(); - state["breakpoints"] = text_editor->get_breakpoints_array(); - state["bookmarks"] = text_editor->get_bookmarks_array(); + state["breakpoints"] = text_editor->get_breakpointed_lines(); + state["bookmarks"] = text_editor->get_bookmarked_lines(); Ref<EditorSyntaxHighlighter> syntax_highlighter = text_editor->get_syntax_highlighter(); state["syntax_highlighter"] = syntax_highlighter->_get_name(); @@ -1453,7 +1451,7 @@ void CodeTextEditor::set_edit_state(const Variant &p_state) { if (state.has("bookmarks")) { Array bookmarks = state["bookmarks"]; for (int i = 0; i < bookmarks.size(); i++) { - text_editor->set_line_as_bookmark(bookmarks[i], true); + text_editor->set_line_as_bookmarked(bookmarks[i], true); } } } @@ -1591,27 +1589,26 @@ void CodeTextEditor::set_warning_nb(int p_warning_nb) { void CodeTextEditor::toggle_bookmark() { int line = text_editor->cursor_get_line(); - text_editor->set_line_as_bookmark(line, !text_editor->is_line_set_as_bookmark(line)); + text_editor->set_line_as_bookmarked(line, !text_editor->is_line_bookmarked(line)); } void CodeTextEditor::goto_next_bookmark() { - List<int> bmarks; - text_editor->get_bookmarks(&bmarks); + Array bmarks = text_editor->get_bookmarked_lines(); if (bmarks.size() <= 0) { return; } int line = text_editor->cursor_get_line(); - if (line >= bmarks[bmarks.size() - 1]) { + if (line >= (int)bmarks[bmarks.size() - 1]) { text_editor->unfold_line(bmarks[0]); text_editor->cursor_set_line(bmarks[0]); text_editor->center_viewport_to_cursor(); } else { - for (List<int>::Element *E = bmarks.front(); E; E = E->next()) { - int bline = E->get(); - if (bline > line) { - text_editor->unfold_line(bline); - text_editor->cursor_set_line(bline); + for (int i = 0; i < bmarks.size(); i++) { + int bmark_line = bmarks[i]; + if (bmark_line > line) { + text_editor->unfold_line(bmark_line); + text_editor->cursor_set_line(bmark_line); text_editor->center_viewport_to_cursor(); return; } @@ -1620,23 +1617,22 @@ void CodeTextEditor::goto_next_bookmark() { } void CodeTextEditor::goto_prev_bookmark() { - List<int> bmarks; - text_editor->get_bookmarks(&bmarks); + Array bmarks = text_editor->get_bookmarked_lines(); if (bmarks.size() <= 0) { return; } int line = text_editor->cursor_get_line(); - if (line <= bmarks[0]) { + if (line <= (int)bmarks[0]) { text_editor->unfold_line(bmarks[bmarks.size() - 1]); text_editor->cursor_set_line(bmarks[bmarks.size() - 1]); text_editor->center_viewport_to_cursor(); } else { - for (List<int>::Element *E = bmarks.back(); E; E = E->prev()) { - int bline = E->get(); - if (bline < line) { - text_editor->unfold_line(bline); - text_editor->cursor_set_line(bline); + for (int i = bmarks.size(); i >= 0; i--) { + int bmark_line = bmarks[i]; + if (bmark_line < line) { + text_editor->unfold_line(bmark_line); + text_editor->cursor_set_line(bmark_line); text_editor->center_viewport_to_cursor(); return; } @@ -1645,12 +1641,7 @@ void CodeTextEditor::goto_prev_bookmark() { } void CodeTextEditor::remove_all_bookmarks() { - List<int> bmarks; - text_editor->get_bookmarks(&bmarks); - - for (List<int>::Element *E = bmarks.front(); E; E = E->next()) { - text_editor->set_line_as_bookmark(E->get(), false); - } + text_editor->clear_bookmarked_lines(); } void CodeTextEditor::_bind_methods() { @@ -1681,7 +1672,7 @@ CodeTextEditor::CodeTextEditor() { ED_SHORTCUT("script_editor/zoom_out", TTR("Zoom Out"), KEY_MASK_CMD | KEY_MINUS); ED_SHORTCUT("script_editor/reset_zoom", TTR("Reset Zoom"), KEY_MASK_CMD | KEY_0); - text_editor = memnew(TextEdit); + text_editor = memnew(CodeEdit); add_child(text_editor); text_editor->set_v_size_flags(SIZE_EXPAND_FILL); @@ -1693,7 +1684,7 @@ CodeTextEditor::CodeTextEditor() { find_replace_bar->set_text_edit(text_editor); - text_editor->set_show_line_numbers(true); + text_editor->set_draw_line_numbers(true); text_editor->set_brace_matching(true); text_editor->set_auto_indent(true); diff --git a/editor/code_editor.h b/editor/code_editor.h index 450c85c64b..b38170cbf5 100644 --- a/editor/code_editor.h +++ b/editor/code_editor.h @@ -34,9 +34,9 @@ #include "editor/editor_plugin.h" #include "scene/gui/check_box.h" #include "scene/gui/check_button.h" +#include "scene/gui/code_edit.h" #include "scene/gui/dialogs.h" #include "scene/gui/line_edit.h" -#include "scene/gui/text_edit.h" #include "scene/main/timer.h" class GotoLineDialog : public ConfirmationDialog { @@ -45,15 +45,15 @@ class GotoLineDialog : public ConfirmationDialog { Label *line_label; LineEdit *line; - TextEdit *text_editor; + CodeEdit *text_editor; virtual void ok_pressed() override; public: - void popup_find_line(TextEdit *p_edit); + void popup_find_line(CodeEdit *p_edit); int get_line() const; - void set_text_editor(TextEdit *p_text_editor); + void set_text_editor(CodeEdit *p_text_editor); GotoLineDialog(); }; @@ -77,7 +77,7 @@ class FindReplaceBar : public HBoxContainer { HBoxContainer *hbc_button_replace; HBoxContainer *hbc_option_replace; - TextEdit *text_edit; + CodeEdit *text_editor; int result_line; int result_col; @@ -120,7 +120,7 @@ public: bool is_selection_only() const; void set_error(const String &p_label); - void set_text_edit(TextEdit *p_text_edit); + void set_text_edit(CodeEdit *p_text_edit); void popup_search(bool p_show_only = false); void popup_replace(); @@ -137,7 +137,7 @@ typedef void (*CodeTextEditorCodeCompleteFunc)(void *p_ud, const String &p_code, class CodeTextEditor : public VBoxContainer { GDCLASS(CodeTextEditor, VBoxContainer); - TextEdit *text_editor; + CodeEdit *text_editor; FindReplaceBar *find_replace_bar; HBoxContainer *status_bar; @@ -240,7 +240,7 @@ public: void set_error(const String &p_error); void set_error_pos(int p_line, int p_column); void update_line_and_column() { _line_col_changed(); } - TextEdit *get_text_edit() { return text_editor; } + CodeEdit *get_text_editor() { return text_editor; } FindReplaceBar *get_find_replace_bar() { return find_replace_bar; } virtual void apply_code() {} void goto_error(); diff --git a/editor/connections_dialog.cpp b/editor/connections_dialog.cpp index 20d29d47f4..d1661fd7b3 100644 --- a/editor/connections_dialog.cpp +++ b/editor/connections_dialog.cpp @@ -754,8 +754,9 @@ void ConnectionsDock::_open_connection_dialog(ConnectDialog::ConnectionData cToE Node *dst = static_cast<Node *>(cToEdit.target); if (src && dst) { + const String &signalname = cToEdit.signal; connect_dialog->set_title(TTR("Edit Connection:") + cToEdit.signal); - connect_dialog->popup_centered(); + connect_dialog->popup_dialog(signalname); connect_dialog->init(cToEdit, true); } } diff --git a/editor/editor_builders.py b/editor/editor_builders.py index ea32e24f6e..86c5c87a68 100644 --- a/editor/editor_builders.py +++ b/editor/editor_builders.py @@ -54,7 +54,6 @@ def make_fonts_header(target, source, env): g.write("#define _EDITOR_FONTS_H\n") # saving uncompressed, since freetype will reference from memory pointer - xl_names = [] for i in range(len(source)): with open(source[i], "rb") as f: buf = f.read() diff --git a/editor/editor_log.cpp b/editor/editor_log.cpp index 9595eb8a72..6fbafc7ff3 100644 --- a/editor/editor_log.cpp +++ b/editor/editor_log.cpp @@ -79,7 +79,15 @@ void EditorLog::_clear_request() { } void EditorLog::_copy_request() { - log->selection_copy(); + String text = log->get_selected_text(); + + if (text == "") { + text = log->get_text(); + } + + if (text != "") { + DisplayServer::get_singleton()->clipboard_set(text); + } } void EditorLog::clear() { diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 4835b4beab..8edda3123b 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -2545,6 +2545,8 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { } } break; case RUN_PROJECT_DATA_FOLDER: { + // ensure_user_data_dir() to prevent the edge case: "Open Project Data Folder" won't work after the project was renamed in ProjectSettingsEditor unless the project is saved + OS::get_singleton()->ensure_user_data_dir(); OS::get_singleton()->shell_open(String("file://") + OS::get_singleton()->get_user_data_dir()); } break; case FILE_EXPLORE_ANDROID_BUILD_TEMPLATES: { @@ -6198,7 +6200,9 @@ EditorNode::EditorNode() { #else p->add_shortcut(ED_SHORTCUT("editor/fullscreen_mode", TTR("Toggle Fullscreen"), KEY_MASK_SHIFT | KEY_F11), SETTINGS_TOGGLE_FULLSCREEN); #endif -#ifdef WINDOWS_ENABLED +#if defined(WINDOWS_ENABLED) && defined(WINDOWS_SUBSYSTEM_CONSOLE) + // The console can only be toggled if the application was built for the console subsystem, + // not the GUI subsystem. p->add_item(TTR("Toggle System Console"), SETTINGS_TOGGLE_CONSOLE); #endif p->add_separator(); diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp index 8be157ffb5..ac27c4a837 100644 --- a/editor/editor_settings.cpp +++ b/editor/editor_settings.cpp @@ -445,7 +445,6 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) { _initial_set("text_editor/appearance/show_line_numbers", true); _initial_set("text_editor/appearance/line_numbers_zero_padded", false); _initial_set("text_editor/appearance/show_bookmark_gutter", true); - _initial_set("text_editor/appearance/show_breakpoint_gutter", true); _initial_set("text_editor/appearance/show_info_gutter", true); _initial_set("text_editor/appearance/code_folding", true); _initial_set("text_editor/appearance/word_wrap", false); @@ -707,8 +706,8 @@ void EditorSettings::_load_default_text_editor_theme() { _initial_set("text_editor/highlighting/member_variable_color", Color(0.9, 0.31, 0.35)); _initial_set("text_editor/highlighting/mark_color", Color(1.0, 0.4, 0.4, 0.4)); _initial_set("text_editor/highlighting/bookmark_color", Color(0.08, 0.49, 0.98)); - _initial_set("text_editor/highlighting/breakpoint_color", Color(0.8, 0.8, 0.4, 0.2)); - _initial_set("text_editor/highlighting/executing_line_color", Color(0.2, 0.8, 0.2, 0.4)); + _initial_set("text_editor/highlighting/breakpoint_color", Color(0.9, 0.29, 0.3)); + _initial_set("text_editor/highlighting/executing_line_color", Color(0.98, 0.89, 0.27)); _initial_set("text_editor/highlighting/code_folding_color", Color(0.8, 0.8, 0.8, 0.8)); _initial_set("text_editor/highlighting/search_result_color", Color(0.05, 0.25, 0.05, 1)); _initial_set("text_editor/highlighting/search_result_border_color", Color(0.41, 0.61, 0.91, 0.38)); diff --git a/editor/editor_themes.cpp b/editor/editor_themes.cpp index 8d54bc8021..79525ced51 100644 --- a/editor/editor_themes.cpp +++ b/editor/editor_themes.cpp @@ -218,8 +218,15 @@ void editor_register_and_generate_icons(Ref<Theme> p_theme, bool p_dark_theme = // Generate icons. if (!p_only_thumbs) { for (int i = 0; i < editor_icons_count; i++) { + float icon_scale = EDSCALE; + + // Always keep the DefaultProjectIcon at the default size + if (strcmp(editor_icons_names[i], "DefaultProjectIcon") == 0) { + icon_scale = 1.0f; + } + const int is_exception = exceptions.has(editor_icons_names[i]); - const Ref<ImageTexture> icon = editor_generate_icon(i, !is_exception); + const Ref<ImageTexture> icon = editor_generate_icon(i, !is_exception, icon_scale); p_theme->set_icon(editor_icons_names[i], "EditorIcons", icon); } @@ -868,12 +875,24 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { theme->set_constant("side_margin", "TabContainer", 0); theme->set_icon("tab", "TextEdit", theme->get_icon("GuiTab", "EditorIcons")); theme->set_icon("space", "TextEdit", theme->get_icon("GuiSpace", "EditorIcons")); - theme->set_icon("folded", "TextEdit", theme->get_icon("GuiTreeArrowRight", "EditorIcons")); - theme->set_icon("fold", "TextEdit", theme->get_icon("GuiTreeArrowDown", "EditorIcons")); theme->set_color("font_color", "TextEdit", font_color); theme->set_color("caret_color", "TextEdit", font_color); theme->set_color("selection_color", "TextEdit", font_color_selection); + // CodeEdit + theme->set_stylebox("normal", "CodeEdit", style_widget); + theme->set_stylebox("focus", "CodeEdit", style_widget_hover); + theme->set_stylebox("read_only", "CodeEdit", style_widget_disabled); + theme->set_constant("side_margin", "TabContainer", 0); + theme->set_icon("tab", "CodeEdit", theme->get_icon("GuiTab", "EditorIcons")); + theme->set_icon("space", "CodeEdit", theme->get_icon("GuiSpace", "EditorIcons")); + theme->set_icon("folded", "CodeEdit", theme->get_icon("GuiTreeArrowRight", "EditorIcons")); + theme->set_icon("can_fold", "CodeEdit", theme->get_icon("GuiTreeArrowDown", "EditorIcons")); + theme->set_icon("executing_line", "CodeEdit", theme->get_icon("MainPlay", "EditorIcons")); + theme->set_color("font_color", "CodeEdit", font_color); + theme->set_color("caret_color", "CodeEdit", font_color); + theme->set_color("selection_color", "CodeEdit", font_color_selection); + // H/VSplitContainer theme->set_stylebox("bg", "VSplitContainer", make_stylebox(theme->get_icon("GuiVsplitBg", "EditorIcons"), 1, 1, 1, 1)); theme->set_stylebox("bg", "HSplitContainer", make_stylebox(theme->get_icon("GuiHsplitBg", "EditorIcons"), 1, 1, 1, 1)); @@ -1179,7 +1198,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { const Color mark_color = Color(error_color.r, error_color.g, error_color.b, 0.3); const Color bookmark_color = Color(0.08, 0.49, 0.98); const Color breakpoint_color = error_color; - const Color executing_line_color = Color(0.2, 0.8, 0.2, 0.4); + const Color executing_line_color = Color(0.98, 0.89, 0.27); const Color code_folding_color = alpha3; const Color search_result_color = alpha1; const Color search_result_border_color = Color(0.41, 0.61, 0.91, 0.38); diff --git a/editor/node_3d_editor_gizmos.cpp b/editor/node_3d_editor_gizmos.cpp index 2ddcf3d877..6e5fb6389d 100644 --- a/editor/node_3d_editor_gizmos.cpp +++ b/editor/node_3d_editor_gizmos.cpp @@ -1912,7 +1912,7 @@ void RayCast3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { Vector<Vector3> lines; lines.push_back(Vector3()); - lines.push_back(raycast->get_cast_to()); + lines.push_back(raycast->get_target_position()); const Ref<StandardMaterial3D> material = get_material(raycast->is_enabled() ? "shape_material" : "shape_material_disabled", p_gizmo); diff --git a/editor/plugins/mesh_instance_3d_editor_plugin.cpp b/editor/plugins/mesh_instance_3d_editor_plugin.cpp index 1b65987af0..5b241deab0 100644 --- a/editor/plugins/mesh_instance_3d_editor_plugin.cpp +++ b/editor/plugins/mesh_instance_3d_editor_plugin.cpp @@ -138,6 +138,7 @@ void MeshInstance3DEditor::_menu_option(int p_option) { CollisionShape3D *cshape = memnew(CollisionShape3D); cshape->set_shape(shape); + cshape->set_transform(node->get_transform()); Node *owner = node->get_owner(); diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp index 20eef1cebd..be8ddf789b 100644 --- a/editor/plugins/script_editor_plugin.cpp +++ b/editor/plugins/script_editor_plugin.cpp @@ -1585,15 +1585,14 @@ void ScriptEditor::get_breakpoints(List<String> *p_breakpoints) { continue; } - List<int> bpoints; - se->get_breakpoints(&bpoints); String base = script->get_path(); if (base.begins_with("local://") || base == "") { continue; } - for (List<int>::Element *E = bpoints.front(); E; E = E->next()) { - p_breakpoints->push_back(base + ":" + itos(E->get() + 1)); + Array bpoints = se->get_breakpoints(); + for (int j = 0; j < bpoints.size(); j++) { + p_breakpoints->push_back(base + ":" + itos((int)bpoints[j] + 1)); } } } diff --git a/editor/plugins/script_editor_plugin.h b/editor/plugins/script_editor_plugin.h index 1234ebd267..c2b0b458eb 100644 --- a/editor/plugins/script_editor_plugin.h +++ b/editor/plugins/script_editor_plugin.h @@ -151,7 +151,7 @@ public: virtual void ensure_focus() = 0; virtual void tag_saved_version() = 0; virtual void reload(bool p_soft) {} - virtual void get_breakpoints(List<int> *p_breakpoints) = 0; + virtual Array get_breakpoints() = 0; virtual void add_callback(const String &p_function, PackedStringArray p_args) = 0; virtual void update_settings() = 0; virtual void set_debugger_active(bool p_active) = 0; diff --git a/editor/plugins/script_text_editor.cpp b/editor/plugins/script_text_editor.cpp index 4b89ca1216..7feb7cb3d3 100644 --- a/editor/plugins/script_text_editor.cpp +++ b/editor/plugins/script_text_editor.cpp @@ -111,7 +111,7 @@ ConnectionInfoDialog::ConnectionInfoDialog() { Vector<String> ScriptTextEditor::get_functions() { String errortxt; int line = -1, col; - TextEdit *te = code_editor->get_text_edit(); + CodeEdit *te = code_editor->get_text_editor(); String text = te->get_text(); List<String> fnc; @@ -130,9 +130,9 @@ void ScriptTextEditor::apply_code() { if (script.is_null()) { return; } - script->set_source_code(code_editor->get_text_edit()->get_text()); + script->set_source_code(code_editor->get_text_editor()->get_text()); script->update_exports(); - code_editor->get_text_edit()->get_syntax_highlighter()->update_cache(); + code_editor->get_text_editor()->get_syntax_highlighter()->update_cache(); } RES ScriptTextEditor::get_edited_resource() const { @@ -145,9 +145,9 @@ void ScriptTextEditor::set_edited_resource(const RES &p_res) { script = p_res; - code_editor->get_text_edit()->set_text(script->get_source_code()); - code_editor->get_text_edit()->clear_undo_history(); - code_editor->get_text_edit()->tag_saved_version(); + code_editor->get_text_editor()->set_text(script->get_source_code()); + code_editor->get_text_editor()->clear_undo_history(); + code_editor->get_text_editor()->tag_saved_version(); emit_signal("name_changed"); code_editor->update_line_and_column(); @@ -167,9 +167,19 @@ void ScriptTextEditor::enable_editor() { } void ScriptTextEditor::_load_theme_settings() { - TextEdit *text_edit = code_editor->get_text_edit(); + CodeEdit *text_edit = code_editor->get_text_editor(); text_edit->clear_keywords(); + Color updated_safe_line_number_color = EDITOR_GET("text_editor/highlighting/safe_line_number_color"); + if (updated_safe_line_number_color != safe_line_number_color) { + safe_line_number_color = updated_safe_line_number_color; + for (int i = 0; i < text_edit->get_line_count(); i++) { + if (text_edit->get_line_gutter_item_color(i, line_number_gutter) != default_line_number_color) { + text_edit->set_line_gutter_item_color(i, line_number_gutter, safe_line_number_color); + } + } + } + Color background_color = EDITOR_GET("text_editor/highlighting/background_color"); Color completion_background_color = EDITOR_GET("text_editor/highlighting/completion_background_color"); Color completion_selected_color = EDITOR_GET("text_editor/highlighting/completion_selected_color"); @@ -178,7 +188,6 @@ void ScriptTextEditor::_load_theme_settings() { Color completion_font_color = EDITOR_GET("text_editor/highlighting/completion_font_color"); Color text_color = EDITOR_GET("text_editor/highlighting/text_color"); Color line_number_color = EDITOR_GET("text_editor/highlighting/line_number_color"); - Color safe_line_number_color = EDITOR_GET("text_editor/highlighting/safe_line_number_color"); Color caret_color = EDITOR_GET("text_editor/highlighting/caret_color"); Color caret_background_color = EDITOR_GET("text_editor/highlighting/caret_background_color"); Color text_selected_color = EDITOR_GET("text_editor/highlighting/text_selected_color"); @@ -203,7 +212,6 @@ void ScriptTextEditor::_load_theme_settings() { text_edit->add_theme_color_override("completion_font_color", completion_font_color); text_edit->add_theme_color_override("font_color", text_color); text_edit->add_theme_color_override("line_number_color", line_number_color); - text_edit->add_theme_color_override("safe_line_number_color", safe_line_number_color); text_edit->add_theme_color_override("caret_color", caret_color); text_edit->add_theme_color_override("caret_background_color", caret_background_color); text_edit->add_theme_color_override("font_color_selected", text_selected_color); @@ -233,7 +241,7 @@ void ScriptTextEditor::_set_theme_for_script() { return; } - TextEdit *text_edit = code_editor->get_text_edit(); + CodeEdit *text_edit = code_editor->get_text_editor(); text_edit->get_syntax_highlighter()->update_cache(); /* add keywords for auto completion */ @@ -284,10 +292,10 @@ void ScriptTextEditor::_show_warnings_panel(bool p_show) { void ScriptTextEditor::_warning_clicked(Variant p_line) { if (p_line.get_type() == Variant::INT) { - code_editor->get_text_edit()->cursor_set_line(p_line.operator int64_t()); + code_editor->get_text_editor()->cursor_set_line(p_line.operator int64_t()); } else if (p_line.get_type() == Variant::DICTIONARY) { Dictionary meta = p_line.operator Dictionary(); - code_editor->get_text_edit()->insert_at("# warning-ignore:" + meta["code"].operator String(), meta["line"].operator int64_t() - 1); + code_editor->get_text_editor()->insert_at("# warning-ignore:" + meta["code"].operator String(), meta["line"].operator int64_t() - 1); _validate_script(); } } @@ -295,7 +303,7 @@ void ScriptTextEditor::_warning_clicked(Variant p_line) { void ScriptTextEditor::reload_text() { ERR_FAIL_COND(script.is_null()); - TextEdit *te = code_editor->get_text_edit(); + CodeEdit *te = code_editor->get_text_editor(); int column = te->cursor_get_column(); int row = te->cursor_get_line(); int h = te->get_h_scroll(); @@ -313,20 +321,20 @@ void ScriptTextEditor::reload_text() { } void ScriptTextEditor::add_callback(const String &p_function, PackedStringArray p_args) { - String code = code_editor->get_text_edit()->get_text(); + String code = code_editor->get_text_editor()->get_text(); int pos = script->get_language()->find_function(p_function, code); if (pos == -1) { //does not exist - code_editor->get_text_edit()->deselect(); - pos = code_editor->get_text_edit()->get_line_count() + 2; + code_editor->get_text_editor()->deselect(); + pos = code_editor->get_text_editor()->get_line_count() + 2; String func = script->get_language()->make_function("", p_function, p_args); //code=code+func; - code_editor->get_text_edit()->cursor_set_line(pos + 1); - code_editor->get_text_edit()->cursor_set_column(1000000); //none shall be that big - code_editor->get_text_edit()->insert_text_at_cursor("\n\n" + func); + code_editor->get_text_editor()->cursor_set_line(pos + 1); + code_editor->get_text_editor()->cursor_set_column(1000000); //none shall be that big + code_editor->get_text_editor()->insert_text_at_cursor("\n\n" + func); } - code_editor->get_text_edit()->cursor_set_line(pos); - code_editor->get_text_edit()->cursor_set_column(1); + code_editor->get_text_editor()->cursor_set_line(pos); + code_editor->get_text_editor()->cursor_set_column(1); } bool ScriptTextEditor::show_members_overview() { @@ -334,12 +342,13 @@ bool ScriptTextEditor::show_members_overview() { } void ScriptTextEditor::update_settings() { + code_editor->get_text_editor()->set_gutter_draw(connection_gutter, EditorSettings::get_singleton()->get("text_editor/appearance/show_info_gutter")); code_editor->update_editor_settings(); } bool ScriptTextEditor::is_unsaved() { const bool unsaved = - code_editor->get_text_edit()->get_version() != code_editor->get_text_edit()->get_saved_version() || + code_editor->get_text_editor()->get_version() != code_editor->get_text_editor()->get_saved_version() || script->get_path().empty(); // In memory. return unsaved; } @@ -385,7 +394,7 @@ void ScriptTextEditor::convert_indent_to_tabs() { } void ScriptTextEditor::tag_saved_version() { - code_editor->get_text_edit()->tag_saved_version(); + code_editor->get_text_editor()->tag_saved_version(); } void ScriptTextEditor::goto_line(int p_line, bool p_with_error) { @@ -409,7 +418,7 @@ void ScriptTextEditor::clear_executing_line() { } void ScriptTextEditor::ensure_focus() { - code_editor->get_text_edit()->grab_focus(); + code_editor->get_text_editor()->grab_focus(); } String ScriptTextEditor::get_name() { @@ -443,7 +452,7 @@ Ref<Texture2D> ScriptTextEditor::get_theme_icon() { void ScriptTextEditor::_validate_script() { String errortxt; int line = -1, col; - TextEdit *te = code_editor->get_text_edit(); + CodeEdit *te = code_editor->get_text_editor(); String text = te->get_text(); List<String> fnc; @@ -540,16 +549,16 @@ void ScriptTextEditor::_validate_script() { te->set_line_as_marked(i, line == i); if (highlight_safe) { if (safe_lines.has(i + 1)) { - te->set_line_as_safe(i, true); + te->set_line_gutter_item_color(i, line_number_gutter, safe_line_number_color); last_is_safe = true; } else if (last_is_safe && (te->is_line_comment(i) || te->get_line(i).strip_edges().empty())) { - te->set_line_as_safe(i, true); + te->set_line_gutter_item_color(i, line_number_gutter, safe_line_number_color); } else { - te->set_line_as_safe(i, false); + te->set_line_gutter_item_color(i, line_number_gutter, default_line_number_color); last_is_safe = false; } } else { - te->set_line_as_safe(i, false); + te->set_line_gutter_item_color(line, 1, default_line_number_color); } } @@ -566,7 +575,7 @@ void ScriptTextEditor::_update_bookmark_list() { bookmarks_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/goto_next_bookmark"), BOOKMARK_GOTO_NEXT); bookmarks_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/goto_previous_bookmark"), BOOKMARK_GOTO_PREV); - Array bookmark_list = code_editor->get_text_edit()->get_bookmarks_array(); + Array bookmark_list = code_editor->get_text_editor()->get_bookmarked_lines(); if (bookmark_list.size() == 0) { return; } @@ -576,7 +585,7 @@ void ScriptTextEditor::_update_bookmark_list() { for (int i = 0; i < bookmark_list.size(); i++) { // Strip edges to remove spaces or tabs. // Also replace any tabs by spaces, since we can't print tabs in the menu. - String line = code_editor->get_text_edit()->get_line(bookmark_list[i]).replace("\t", " ").strip_edges(); + String line = code_editor->get_text_editor()->get_line(bookmark_list[i]).replace("\t", " ").strip_edges(); // Limit the size of the line if too big. if (line.length() > 50) { @@ -593,7 +602,7 @@ void ScriptTextEditor::_bookmark_item_pressed(int p_idx) { _edit_option(bookmarks_menu->get_item_id(p_idx)); } else { code_editor->goto_line(bookmarks_menu->get_item_metadata(p_idx)); - code_editor->get_text_edit()->call_deferred("center_viewport_to_cursor"); //Need to be deferred, because goto uses call_deferred(). + code_editor->get_text_editor()->call_deferred("center_viewport_to_cursor"); //Need to be deferred, because goto uses call_deferred(). } } @@ -704,7 +713,7 @@ void ScriptTextEditor::_code_complete_script(const String &p_code, List<ScriptCo String hint; Error err = script->get_language()->complete_code(p_code, script->get_path(), base, r_options, r_force, hint); if (err == OK) { - code_editor->get_text_edit()->set_code_hint(hint); + code_editor->get_text_editor()->set_code_hint(hint); } } @@ -717,7 +726,7 @@ void ScriptTextEditor::_update_breakpoint_list() { breakpoints_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/goto_next_breakpoint"), DEBUG_GOTO_NEXT_BREAKPOINT); breakpoints_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/goto_previous_breakpoint"), DEBUG_GOTO_PREV_BREAKPOINT); - Array breakpoint_list = code_editor->get_text_edit()->get_breakpoints_array(); + Array breakpoint_list = code_editor->get_text_editor()->get_breakpointed_lines(); if (breakpoint_list.size() == 0) { return; } @@ -727,7 +736,7 @@ void ScriptTextEditor::_update_breakpoint_list() { for (int i = 0; i < breakpoint_list.size(); i++) { // Strip edges to remove spaces or tabs. // Also replace any tabs by spaces, since we can't print tabs in the menu. - String line = code_editor->get_text_edit()->get_line(breakpoint_list[i]).replace("\t", " ").strip_edges(); + String line = code_editor->get_text_editor()->get_line(breakpoint_list[i]).replace("\t", " ").strip_edges(); // Limit the size of the line if too big. if (line.length() > 50) { @@ -744,12 +753,12 @@ void ScriptTextEditor::_breakpoint_item_pressed(int p_idx) { _edit_option(breakpoints_menu->get_item_id(p_idx)); } else { code_editor->goto_line(breakpoints_menu->get_item_metadata(p_idx)); - code_editor->get_text_edit()->call_deferred("center_viewport_to_cursor"); //Need to be deferred, because goto uses call_deferred(). + code_editor->get_text_editor()->call_deferred("center_viewport_to_cursor"); //Need to be deferred, because goto uses call_deferred(). } } void ScriptTextEditor::_breakpoint_toggled(int p_row) { - EditorDebuggerNode::get_singleton()->set_breakpoint(script->get_path(), p_row + 1, code_editor->get_text_edit()->is_line_set_as_breakpoint(p_row)); + EditorDebuggerNode::get_singleton()->set_breakpoint(script->get_path(), p_row + 1, code_editor->get_text_editor()->is_line_breakpointed(p_row)); } void ScriptTextEditor::_lookup_symbol(const String &p_symbol, int p_row, int p_column) { @@ -771,7 +780,7 @@ void ScriptTextEditor::_lookup_symbol(const String &p_symbol, int p_row, int p_c EditorNode::get_singleton()->load_resource(p_symbol); } - } else if (script->get_language()->lookup_code(code_editor->get_text_edit()->get_text_for_lookup_completion(), p_symbol, script->get_path(), base, result) == OK) { + } else if (script->get_language()->lookup_code(code_editor->get_text_editor()->get_text_for_lookup_completion(), p_symbol, script->get_path(), base, result) == OK) { _goto_line(p_row); result.class_name = result.class_name.trim_prefix("_"); @@ -866,7 +875,7 @@ void ScriptTextEditor::_lookup_symbol(const String &p_symbol, int p_row, int p_c } void ScriptTextEditor::_validate_symbol(const String &p_symbol) { - TextEdit *text_edit = code_editor->get_text_edit(); + CodeEdit *text_edit = code_editor->get_text_editor(); Node *base = get_tree()->get_edited_scene_root(); if (base) { @@ -874,7 +883,7 @@ void ScriptTextEditor::_validate_symbol(const String &p_symbol) { } ScriptLanguage::LookupResult result; - if (ScriptServer::is_global_class(p_symbol) || p_symbol.is_resource_file() || script->get_language()->lookup_code(code_editor->get_text_edit()->get_text_for_lookup_completion(), p_symbol, script->get_path(), base, result) == OK || (ProjectSettings::get_singleton()->has_autoload(p_symbol) && ProjectSettings::get_singleton()->get_autoload(p_symbol).is_singleton)) { + if (ScriptServer::is_global_class(p_symbol) || p_symbol.is_resource_file() || script->get_language()->lookup_code(code_editor->get_text_editor()->get_text_for_lookup_completion(), p_symbol, script->get_path(), base, result) == OK || (ProjectSettings::get_singleton()->has_autoload(p_symbol) && ProjectSettings::get_singleton()->get_autoload(p_symbol).is_singleton)) { text_edit->set_highlighted_word(p_symbol); } else if (p_symbol.is_rel_path()) { String path = _get_absolute_path(p_symbol); @@ -902,8 +911,15 @@ void ScriptTextEditor::update_toggle_scripts_button() { } void ScriptTextEditor::_update_connected_methods() { - TextEdit *text_edit = code_editor->get_text_edit(); - text_edit->clear_info_icons(); + CodeEdit *text_edit = code_editor->get_text_editor(); + for (int i = 0; i < text_edit->get_line_count(); i++) { + if (text_edit->get_line_gutter_metadata(i, connection_gutter) == "") { + continue; + } + text_edit->set_line_gutter_metadata(i, connection_gutter, ""); + text_edit->set_line_gutter_icon(i, connection_gutter, nullptr); + text_edit->set_line_gutter_clickable(i, connection_gutter, false); + } missing_connections.clear(); if (!script_is_valid) { @@ -943,8 +959,10 @@ void ScriptTextEditor::_update_connected_methods() { for (int j = 0; j < functions.size(); j++) { String name = functions[j].get_slice(":", 0); if (name == connection.callable.get_method()) { - line = functions[j].get_slice(":", 1).to_int(); - text_edit->set_line_info_icon(line - 1, get_parent_control()->get_theme_icon("Slot", "EditorIcons"), connection.callable.get_method()); + line = functions[j].get_slice(":", 1).to_int() - 1; + text_edit->set_line_gutter_metadata(line, connection_gutter, connection.callable.get_method()); + text_edit->set_line_gutter_icon(line, connection_gutter, get_parent_control()->get_theme_icon("Slot", "EditorIcons")); + text_edit->set_line_gutter_clickable(line, connection_gutter, true); methods_found.insert(connection.callable.get_method()); break; } @@ -974,18 +992,41 @@ void ScriptTextEditor::_update_connected_methods() { } } -void ScriptTextEditor::_lookup_connections(int p_row, String p_method) { +void ScriptTextEditor::_update_gutter_indexes() { + for (int i = 0; i < code_editor->get_text_editor()->get_gutter_count(); i++) { + if (code_editor->get_text_editor()->get_gutter_name(i) == "connection_gutter") { + connection_gutter = i; + continue; + } + + if (code_editor->get_text_editor()->get_gutter_name(i) == "line_numbers") { + line_number_gutter = i; + continue; + } + } +} + +void ScriptTextEditor::_gutter_clicked(int p_line, int p_gutter) { + if (p_gutter != connection_gutter) { + return; + } + + String method = code_editor->get_text_editor()->get_line_gutter_metadata(p_line, p_gutter); + if (method == "") { + return; + } + Node *base = get_tree()->get_edited_scene_root(); if (!base) { return; } Vector<Node *> nodes = _find_all_node_for_script(base, base, script); - connection_info_dialog->popup_connections(p_method, nodes); + connection_info_dialog->popup_connections(method, nodes); } void ScriptTextEditor::_edit_option(int p_op) { - TextEdit *tx = code_editor->get_text_edit(); + CodeEdit *tx = code_editor->get_text_editor(); switch (p_op) { case EDIT_UNDO: { @@ -1109,7 +1150,7 @@ void ScriptTextEditor::_edit_option(int p_op) { } break; case EDIT_EVALUATE: { Expression expression; - Vector<String> lines = code_editor->get_text_edit()->get_selection_text().split("\n"); + Vector<String> lines = code_editor->get_text_editor()->get_selection_text().split("\n"); PackedStringArray results; for (int i = 0; i < lines.size(); i++) { @@ -1128,9 +1169,9 @@ void ScriptTextEditor::_edit_option(int p_op) { } } - code_editor->get_text_edit()->begin_complex_operation(); //prevents creating a two-step undo - code_editor->get_text_edit()->insert_text_at_cursor(String("\n").join(results)); - code_editor->get_text_edit()->end_complex_operation(); + code_editor->get_text_editor()->begin_complex_operation(); //prevents creating a two-step undo + code_editor->get_text_editor()->insert_text_at_cursor(String("\n").join(results)); + code_editor->get_text_editor()->end_complex_operation(); } break; case SEARCH_FIND: { code_editor->get_find_replace_bar()->popup_search(); @@ -1145,14 +1186,14 @@ void ScriptTextEditor::_edit_option(int p_op) { code_editor->get_find_replace_bar()->popup_replace(); } break; case SEARCH_IN_FILES: { - String selected_text = code_editor->get_text_edit()->get_selection_text(); + String selected_text = code_editor->get_text_editor()->get_selection_text(); // Yep, because it doesn't make sense to instance this dialog for every single script open... // So this will be delegated to the ScriptEditor. emit_signal("search_in_files_requested", selected_text); } break; case REPLACE_IN_FILES: { - String selected_text = code_editor->get_text_edit()->get_selection_text(); + String selected_text = code_editor->get_text_editor()->get_selection_text(); emit_signal("replace_in_files_requested", selected_text); } break; @@ -1177,24 +1218,22 @@ void ScriptTextEditor::_edit_option(int p_op) { } break; case DEBUG_TOGGLE_BREAKPOINT: { int line = tx->cursor_get_line(); - bool dobreak = !tx->is_line_set_as_breakpoint(line); + bool dobreak = !tx->is_line_breakpointed(line); tx->set_line_as_breakpoint(line, dobreak); EditorDebuggerNode::get_singleton()->set_breakpoint(script->get_path(), line + 1, dobreak); } break; case DEBUG_REMOVE_ALL_BREAKPOINTS: { - List<int> bpoints; - tx->get_breakpoints(&bpoints); + Array bpoints = tx->get_breakpointed_lines(); - for (List<int>::Element *E = bpoints.front(); E; E = E->next()) { - int line = E->get(); - bool dobreak = !tx->is_line_set_as_breakpoint(line); + for (int i = 0; i < bpoints.size(); i++) { + int line = bpoints[i]; + bool dobreak = !tx->is_line_breakpointed(line); tx->set_line_as_breakpoint(line, dobreak); EditorDebuggerNode::get_singleton()->set_breakpoint(script->get_path(), line + 1, dobreak); } } break; case DEBUG_GOTO_NEXT_BREAKPOINT: { - List<int> bpoints; - tx->get_breakpoints(&bpoints); + Array bpoints = tx->get_breakpointed_lines(); if (bpoints.size() <= 0) { return; } @@ -1202,13 +1241,13 @@ void ScriptTextEditor::_edit_option(int p_op) { int line = tx->cursor_get_line(); // wrap around - if (line >= bpoints[bpoints.size() - 1]) { + if (line >= (int)bpoints[bpoints.size() - 1]) { tx->unfold_line(bpoints[0]); tx->cursor_set_line(bpoints[0]); tx->center_viewport_to_cursor(); } else { - for (List<int>::Element *E = bpoints.front(); E; E = E->next()) { - int bline = E->get(); + for (int i = 0; i < bpoints.size(); i++) { + int bline = bpoints[i]; if (bline > line) { tx->unfold_line(bline); tx->cursor_set_line(bline); @@ -1220,21 +1259,20 @@ void ScriptTextEditor::_edit_option(int p_op) { } break; case DEBUG_GOTO_PREV_BREAKPOINT: { - List<int> bpoints; - tx->get_breakpoints(&bpoints); + Array bpoints = tx->get_breakpointed_lines(); if (bpoints.size() <= 0) { return; } int line = tx->cursor_get_line(); // wrap around - if (line <= bpoints[0]) { + if (line <= (int)bpoints[0]) { tx->unfold_line(bpoints[bpoints.size() - 1]); tx->cursor_set_line(bpoints[bpoints.size() - 1]); tx->center_viewport_to_cursor(); } else { - for (List<int>::Element *E = bpoints.back(); E; E = E->prev()) { - int bline = E->get(); + for (int i = bpoints.size(); i >= 0; i--) { + int bline = bpoints[i]; if (bline < line) { tx->unfold_line(bline); tx->cursor_set_line(bline); @@ -1303,7 +1341,7 @@ void ScriptTextEditor::set_syntax_highlighter(Ref<EditorSyntaxHighlighter> p_hig el = el->next(); } - TextEdit *te = code_editor->get_text_edit(); + CodeEdit *te = code_editor->get_text_editor(); p_highlighter->_set_edited_resource(script); te->set_syntax_highlighter(p_highlighter); } @@ -1312,6 +1350,16 @@ void ScriptTextEditor::_change_syntax_highlighter(int p_idx) { set_syntax_highlighter(highlighters[highlighter_menu->get_item_text(p_idx)]); } +void ScriptTextEditor::_notification(int p_what) { + switch (p_what) { + case NOTIFICATION_THEME_CHANGED: { + code_editor->get_text_editor()->set_gutter_width(connection_gutter, code_editor->get_text_editor()->get_row_height()); + } break; + default: + break; + } +} + void ScriptTextEditor::_bind_methods() { ClassDB::bind_method("_update_connected_methods", &ScriptTextEditor::_update_connected_methods); @@ -1331,7 +1379,7 @@ void ScriptTextEditor::clear_edit_menu() { } void ScriptTextEditor::reload(bool p_soft) { - TextEdit *te = code_editor->get_text_edit(); + CodeEdit *te = code_editor->get_text_editor(); Ref<Script> scr = script; if (scr.is_null()) { return; @@ -1342,12 +1390,12 @@ void ScriptTextEditor::reload(bool p_soft) { scr->get_language()->reload_tool_script(scr, soft); } -void ScriptTextEditor::get_breakpoints(List<int> *p_breakpoints) { - code_editor->get_text_edit()->get_breakpoints(p_breakpoints); +Array ScriptTextEditor::get_breakpoints() { + return code_editor->get_text_editor()->get_breakpointed_lines(); } void ScriptTextEditor::set_tooltip_request_func(String p_method, Object *p_obj) { - code_editor->get_text_edit()->set_tooltip_request_func(p_obj, p_method, this); + code_editor->get_text_editor()->set_tooltip_request_func(p_obj, p_method, this); } void ScriptTextEditor::set_debugger_active(bool p_active) { @@ -1393,7 +1441,7 @@ static Node *_find_script_node(Node *p_edited_scene, Node *p_current_node, const void ScriptTextEditor::drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) { Dictionary d = p_data; - TextEdit *te = code_editor->get_text_edit(); + CodeEdit *te = code_editor->get_text_editor(); int row, col; te->_get_mouse_pos(p_point, row, col); @@ -1466,7 +1514,7 @@ void ScriptTextEditor::_text_edit_gui_input(const Ref<InputEvent> &ev) { Point2 local_pos; bool create_menu = false; - TextEdit *tx = code_editor->get_text_edit(); + CodeEdit *tx = code_editor->get_text_editor(); if (mb.is_valid() && mb->get_button_index() == BUTTON_RIGHT && mb->is_pressed()) { local_pos = mb->get_global_position() - tx->get_global_position(); create_menu = true; @@ -1519,7 +1567,7 @@ void ScriptTextEditor::_text_edit_gui_input(const Ref<InputEvent> &ev) { base = _find_node_for_script(base, base, script); } ScriptLanguage::LookupResult result; - if (script->get_language()->lookup_code(code_editor->get_text_edit()->get_text_for_lookup_completion(), word_at_pos, script->get_path(), base, result) == OK) { + if (script->get_language()->lookup_code(code_editor->get_text_editor()->get_text_for_lookup_completion(), word_at_pos, script->get_path(), base, result) == OK) { open_docs = true; } } @@ -1567,17 +1615,17 @@ void ScriptTextEditor::_color_changed(const Color &p_color) { new_args = String("(" + rtos(p_color.r) + ", " + rtos(p_color.g) + ", " + rtos(p_color.b) + ", " + rtos(p_color.a) + ")"); } - String line = code_editor->get_text_edit()->get_line(color_position.x); + String line = code_editor->get_text_editor()->get_line(color_position.x); int color_args_pos = line.find(color_args, color_position.y); String line_with_replaced_args = line; line_with_replaced_args.erase(color_args_pos, color_args.length()); line_with_replaced_args = line_with_replaced_args.insert(color_args_pos, new_args); color_args = new_args; - code_editor->get_text_edit()->begin_complex_operation(); - code_editor->get_text_edit()->set_line(color_position.x, line_with_replaced_args); - code_editor->get_text_edit()->end_complex_operation(); - code_editor->get_text_edit()->update(); + code_editor->get_text_editor()->begin_complex_operation(); + code_editor->get_text_editor()->set_line(color_position.x, line_with_replaced_args); + code_editor->get_text_editor()->end_complex_operation(); + code_editor->get_text_editor()->update(); } void ScriptTextEditor::_make_context_menu(bool p_selection, bool p_color, bool p_foldable, bool p_open_docs, bool p_goto_definition, Vector2 p_pos) { @@ -1636,12 +1684,15 @@ void ScriptTextEditor::_enable_code_editor() { code_editor->connect("show_warnings_panel", callable_mp(this, &ScriptTextEditor::_show_warnings_panel)); code_editor->connect("validate_script", callable_mp(this, &ScriptTextEditor::_validate_script)); code_editor->connect("load_theme_settings", callable_mp(this, &ScriptTextEditor::_load_theme_settings)); - code_editor->get_text_edit()->connect("breakpoint_toggled", callable_mp(this, &ScriptTextEditor::_breakpoint_toggled)); - code_editor->get_text_edit()->connect("symbol_lookup", callable_mp(this, &ScriptTextEditor::_lookup_symbol)); - code_editor->get_text_edit()->connect("symbol_validate", callable_mp(this, &ScriptTextEditor::_validate_symbol)); - code_editor->get_text_edit()->connect("info_clicked", callable_mp(this, &ScriptTextEditor::_lookup_connections)); - code_editor->get_text_edit()->connect("gui_input", callable_mp(this, &ScriptTextEditor::_text_edit_gui_input)); + code_editor->get_text_editor()->connect("breakpoint_toggled", callable_mp(this, &ScriptTextEditor::_breakpoint_toggled)); + code_editor->get_text_editor()->connect("symbol_lookup", callable_mp(this, &ScriptTextEditor::_lookup_symbol)); + code_editor->get_text_editor()->connect("symbol_validate", callable_mp(this, &ScriptTextEditor::_validate_symbol)); + code_editor->get_text_editor()->connect("gutter_added", callable_mp(this, &ScriptTextEditor::_update_gutter_indexes)); + code_editor->get_text_editor()->connect("gutter_removed", callable_mp(this, &ScriptTextEditor::_update_gutter_indexes)); + code_editor->get_text_editor()->connect("gutter_clicked", callable_mp(this, &ScriptTextEditor::_gutter_clicked)); + code_editor->get_text_editor()->connect("gui_input", callable_mp(this, &ScriptTextEditor::_text_edit_gui_input)); code_editor->show_toggle_scripts_button(); + _update_gutter_indexes(); editor_box->add_child(warnings_panel); warnings_panel->add_theme_font_override( @@ -1758,6 +1809,16 @@ ScriptTextEditor::ScriptTextEditor() { code_editor->set_code_complete_func(_code_complete_scripts, this); code_editor->set_v_size_flags(SIZE_EXPAND_FILL); + code_editor->get_text_editor()->set_draw_breakpoints_gutter(true); + code_editor->get_text_editor()->set_draw_executing_lines_gutter(true); + + connection_gutter = 1; + code_editor->get_text_editor()->add_gutter(connection_gutter); + code_editor->get_text_editor()->set_gutter_name(connection_gutter, "connection_gutter"); + code_editor->get_text_editor()->set_gutter_draw(connection_gutter, false); + code_editor->get_text_editor()->set_gutter_overwritable(connection_gutter, true); + code_editor->get_text_editor()->set_gutter_type(connection_gutter, TextEdit::GUTTER_TPYE_ICON); + warnings_panel = memnew(RichTextLabel); warnings_panel->set_custom_minimum_size(Size2(0, 100 * EDSCALE)); warnings_panel->set_h_size_flags(SIZE_EXPAND_FILL); @@ -1768,12 +1829,12 @@ ScriptTextEditor::ScriptTextEditor() { update_settings(); - code_editor->get_text_edit()->set_callhint_settings( + code_editor->get_text_editor()->set_callhint_settings( EditorSettings::get_singleton()->get("text_editor/completion/put_callhint_tooltip_below_current_line"), EditorSettings::get_singleton()->get("text_editor/completion/callhint_tooltip_offset")); - code_editor->get_text_edit()->set_select_identifiers_on_hover(true); - code_editor->get_text_edit()->set_context_menu_enabled(false); + code_editor->get_text_editor()->set_select_identifiers_on_hover(true); + code_editor->get_text_editor()->set_context_menu_enabled(false); context_menu = memnew(PopupMenu); @@ -1816,7 +1877,7 @@ ScriptTextEditor::ScriptTextEditor() { connection_info_dialog = memnew(ConnectionInfoDialog); - code_editor->get_text_edit()->set_drag_forwarding(this); + code_editor->get_text_editor()->set_drag_forwarding(this); } ScriptTextEditor::~ScriptTextEditor() { diff --git a/editor/plugins/script_text_editor.h b/editor/plugins/script_text_editor.h index e931c9fdc6..1e436fbe65 100644 --- a/editor/plugins/script_text_editor.h +++ b/editor/plugins/script_text_editor.h @@ -81,6 +81,14 @@ class ScriptTextEditor : public ScriptEditorBase { ScriptEditorQuickOpen *quick_open = nullptr; ConnectionInfoDialog *connection_info_dialog = nullptr; + int connection_gutter = -1; + void _gutter_clicked(int p_line, int p_gutter); + void _update_gutter_indexes(); + + int line_number_gutter = -1; + Color default_line_number_color = Color(1, 1, 1); + Color safe_line_number_color = Color(1, 1, 1); + PopupPanel *color_panel = nullptr; ColorPicker *color_picker = nullptr; Vector2 color_position; @@ -154,6 +162,7 @@ protected: void _show_warnings_panel(bool p_show); void _warning_clicked(Variant p_line); + void _notification(int p_what); static void _bind_methods(); Map<String, Ref<EditorSyntaxHighlighter>> highlighters; @@ -169,8 +178,6 @@ protected: void _lookup_symbol(const String &p_symbol, int p_row, int p_column); void _validate_symbol(const String &p_symbol); - void _lookup_connections(int p_row, String p_method); - void _convert_case(CodeTextEditor::CaseStyle p_case); Variant get_drag_data_fw(const Point2 &p_point, Control *p_from); @@ -211,7 +218,7 @@ public: virtual void clear_executing_line() override; virtual void reload(bool p_soft) override; - virtual void get_breakpoints(List<int> *p_breakpoints) override; + virtual Array get_breakpoints() override; virtual void add_callback(const String &p_function, PackedStringArray p_args) override; virtual void update_settings() override; diff --git a/editor/plugins/shader_editor_plugin.cpp b/editor/plugins/shader_editor_plugin.cpp index 2a7f3f0656..29db284b44 100644 --- a/editor/plugins/shader_editor_plugin.cpp +++ b/editor/plugins/shader_editor_plugin.cpp @@ -55,8 +55,8 @@ void ShaderTextEditor::set_edited_shader(const Ref<Shader> &p_shader) { _load_theme_settings(); - get_text_edit()->set_text(p_shader->get_code()); - get_text_edit()->clear_undo_history(); + get_text_editor()->set_text(p_shader->get_code()); + get_text_editor()->clear_undo_history(); _validate_script(); _line_col_changed(); @@ -65,7 +65,7 @@ void ShaderTextEditor::set_edited_shader(const Ref<Shader> &p_shader) { void ShaderTextEditor::reload_text() { ERR_FAIL_COND(shader.is_null()); - TextEdit *te = get_text_edit(); + CodeEdit *te = get_text_editor(); int column = te->cursor_get_column(); int row = te->cursor_get_line(); int h = te->get_h_scroll(); @@ -107,29 +107,29 @@ void ShaderTextEditor::_load_theme_settings() { Color search_result_color = EDITOR_GET("text_editor/highlighting/search_result_color"); Color search_result_border_color = EDITOR_GET("text_editor/highlighting/search_result_border_color"); - get_text_edit()->add_theme_color_override("background_color", background_color); - get_text_edit()->add_theme_color_override("completion_background_color", completion_background_color); - get_text_edit()->add_theme_color_override("completion_selected_color", completion_selected_color); - get_text_edit()->add_theme_color_override("completion_existing_color", completion_existing_color); - get_text_edit()->add_theme_color_override("completion_scroll_color", completion_scroll_color); - get_text_edit()->add_theme_color_override("completion_font_color", completion_font_color); - get_text_edit()->add_theme_color_override("font_color", text_color); - get_text_edit()->add_theme_color_override("line_number_color", line_number_color); - get_text_edit()->add_theme_color_override("caret_color", caret_color); - get_text_edit()->add_theme_color_override("caret_background_color", caret_background_color); - get_text_edit()->add_theme_color_override("font_color_selected", text_selected_color); - get_text_edit()->add_theme_color_override("selection_color", selection_color); - get_text_edit()->add_theme_color_override("brace_mismatch_color", brace_mismatch_color); - get_text_edit()->add_theme_color_override("current_line_color", current_line_color); - get_text_edit()->add_theme_color_override("line_length_guideline_color", line_length_guideline_color); - get_text_edit()->add_theme_color_override("word_highlighted_color", word_highlighted_color); - get_text_edit()->add_theme_color_override("mark_color", mark_color); - get_text_edit()->add_theme_color_override("bookmark_color", bookmark_color); - get_text_edit()->add_theme_color_override("breakpoint_color", breakpoint_color); - get_text_edit()->add_theme_color_override("executing_line_color", executing_line_color); - get_text_edit()->add_theme_color_override("code_folding_color", code_folding_color); - get_text_edit()->add_theme_color_override("search_result_color", search_result_color); - get_text_edit()->add_theme_color_override("search_result_border_color", search_result_border_color); + get_text_editor()->add_theme_color_override("background_color", background_color); + get_text_editor()->add_theme_color_override("completion_background_color", completion_background_color); + get_text_editor()->add_theme_color_override("completion_selected_color", completion_selected_color); + get_text_editor()->add_theme_color_override("completion_existing_color", completion_existing_color); + get_text_editor()->add_theme_color_override("completion_scroll_color", completion_scroll_color); + get_text_editor()->add_theme_color_override("completion_font_color", completion_font_color); + get_text_editor()->add_theme_color_override("font_color", text_color); + get_text_editor()->add_theme_color_override("line_number_color", line_number_color); + get_text_editor()->add_theme_color_override("caret_color", caret_color); + get_text_editor()->add_theme_color_override("caret_background_color", caret_background_color); + get_text_editor()->add_theme_color_override("font_color_selected", text_selected_color); + get_text_editor()->add_theme_color_override("selection_color", selection_color); + get_text_editor()->add_theme_color_override("brace_mismatch_color", brace_mismatch_color); + get_text_editor()->add_theme_color_override("current_line_color", current_line_color); + get_text_editor()->add_theme_color_override("line_length_guideline_color", line_length_guideline_color); + get_text_editor()->add_theme_color_override("word_highlighted_color", word_highlighted_color); + get_text_editor()->add_theme_color_override("mark_color", mark_color); + get_text_editor()->add_theme_color_override("bookmark_color", bookmark_color); + get_text_editor()->add_theme_color_override("breakpoint_color", breakpoint_color); + get_text_editor()->add_theme_color_override("executing_line_color", executing_line_color); + get_text_editor()->add_theme_color_override("code_folding_color", code_folding_color); + get_text_editor()->add_theme_color_override("search_result_color", search_result_color); + get_text_editor()->add_theme_color_override("search_result_border_color", search_result_border_color); syntax_highlighter->set_number_color(EDITOR_GET("text_editor/highlighting/number_color")); syntax_highlighter->set_symbol_color(EDITOR_GET("text_editor/highlighting/symbol_color")); @@ -176,7 +176,7 @@ void ShaderTextEditor::_load_theme_settings() { } void ShaderTextEditor::_check_shader_mode() { - String type = ShaderLanguage::get_shader_type(get_text_edit()->get_text()); + String type = ShaderLanguage::get_shader_type(get_text_editor()->get_text()); Shader::Mode mode; @@ -189,7 +189,7 @@ void ShaderTextEditor::_check_shader_mode() { } if (shader->get_mode() != mode) { - shader->set_code(get_text_edit()->get_text()); + shader->set_code(get_text_editor()->get_text()); _load_theme_settings(); } } @@ -207,13 +207,13 @@ void ShaderTextEditor::_code_complete_script(const String &p_code, List<ScriptCo sl.complete(p_code, ShaderTypes::get_singleton()->get_functions(RenderingServer::ShaderMode(shader->get_mode())), ShaderTypes::get_singleton()->get_modes(RenderingServer::ShaderMode(shader->get_mode())), ShaderTypes::get_singleton()->get_types(), _get_global_variable_type, r_options, calltip); - get_text_edit()->set_code_hint(calltip); + get_text_editor()->set_code_hint(calltip); } void ShaderTextEditor::_validate_script() { _check_shader_mode(); - String code = get_text_edit()->get_text(); + String code = get_text_editor()->get_text(); //List<StringName> params; //shader->get_param_list(¶ms); @@ -225,14 +225,14 @@ void ShaderTextEditor::_validate_script() { String error_text = "error(" + itos(sl.get_error_line()) + "): " + sl.get_error_text(); set_error(error_text); set_error_pos(sl.get_error_line() - 1, 0); - for (int i = 0; i < get_text_edit()->get_line_count(); i++) { - get_text_edit()->set_line_as_marked(i, false); + for (int i = 0; i < get_text_editor()->get_line_count(); i++) { + get_text_editor()->set_line_as_marked(i, false); } - get_text_edit()->set_line_as_marked(sl.get_error_line() - 1, true); + get_text_editor()->set_line_as_marked(sl.get_error_line() - 1, true); } else { - for (int i = 0; i < get_text_edit()->get_line_count(); i++) { - get_text_edit()->set_line_as_marked(i, false); + for (int i = 0; i < get_text_editor()->get_line_count(); i++) { + get_text_editor()->set_line_as_marked(i, false); } set_error(""); } @@ -245,7 +245,7 @@ void ShaderTextEditor::_bind_methods() { ShaderTextEditor::ShaderTextEditor() { syntax_highlighter.instance(); - get_text_edit()->set_syntax_highlighter(syntax_highlighter); + get_text_editor()->set_syntax_highlighter(syntax_highlighter); } /*** SCRIPT EDITOR ******/ @@ -253,22 +253,22 @@ ShaderTextEditor::ShaderTextEditor() { void ShaderEditor::_menu_option(int p_option) { switch (p_option) { case EDIT_UNDO: { - shader_editor->get_text_edit()->undo(); + shader_editor->get_text_editor()->undo(); } break; case EDIT_REDO: { - shader_editor->get_text_edit()->redo(); + shader_editor->get_text_editor()->redo(); } break; case EDIT_CUT: { - shader_editor->get_text_edit()->cut(); + shader_editor->get_text_editor()->cut(); } break; case EDIT_COPY: { - shader_editor->get_text_edit()->copy(); + shader_editor->get_text_editor()->copy(); } break; case EDIT_PASTE: { - shader_editor->get_text_edit()->paste(); + shader_editor->get_text_editor()->paste(); } break; case EDIT_SELECT_ALL: { - shader_editor->get_text_edit()->select_all(); + shader_editor->get_text_editor()->select_all(); } break; case EDIT_MOVE_LINE_UP: { shader_editor->move_lines_up(); @@ -281,7 +281,7 @@ void ShaderEditor::_menu_option(int p_option) { return; } - TextEdit *tx = shader_editor->get_text_edit(); + CodeEdit *tx = shader_editor->get_text_editor(); tx->indent_left(); } break; @@ -290,7 +290,7 @@ void ShaderEditor::_menu_option(int p_option) { return; } - TextEdit *tx = shader_editor->get_text_edit(); + CodeEdit *tx = shader_editor->get_text_editor(); tx->indent_right(); } break; @@ -309,7 +309,7 @@ void ShaderEditor::_menu_option(int p_option) { } break; case EDIT_COMPLETE: { - shader_editor->get_text_edit()->query_code_comple(); + shader_editor->get_text_editor()->query_code_comple(); } break; case SEARCH_FIND: { shader_editor->get_find_replace_bar()->popup_search(); @@ -324,7 +324,7 @@ void ShaderEditor::_menu_option(int p_option) { shader_editor->get_find_replace_bar()->popup_replace(); } break; case SEARCH_GOTO_LINE: { - goto_line_dialog->popup_find_line(shader_editor->get_text_edit()); + goto_line_dialog->popup_find_line(shader_editor->get_text_editor()); } break; case BOOKMARK_TOGGLE: { shader_editor->toggle_bookmark(); @@ -343,7 +343,7 @@ void ShaderEditor::_menu_option(int p_option) { } break; } if (p_option != SEARCH_FIND && p_option != SEARCH_REPLACE && p_option != SEARCH_GOTO_LINE) { - shader_editor->get_text_edit()->call_deferred("grab_focus"); + shader_editor->get_text_editor()->call_deferred("grab_focus"); } } @@ -358,28 +358,11 @@ void ShaderEditor::_params_changed() { } void ShaderEditor::_editor_settings_changed() { - shader_editor->get_text_edit()->set_auto_brace_completion(EditorSettings::get_singleton()->get("text_editor/completion/auto_brace_complete")); - shader_editor->get_text_edit()->set_scroll_pass_end_of_file(EditorSettings::get_singleton()->get("text_editor/cursor/scroll_past_end_of_file")); - shader_editor->get_text_edit()->set_indent_size(EditorSettings::get_singleton()->get("text_editor/indent/size")); - shader_editor->get_text_edit()->set_indent_using_spaces(EditorSettings::get_singleton()->get("text_editor/indent/type")); - shader_editor->get_text_edit()->set_auto_indent(EditorSettings::get_singleton()->get("text_editor/indent/auto_indent")); - shader_editor->get_text_edit()->set_draw_tabs(EditorSettings::get_singleton()->get("text_editor/indent/draw_tabs")); - shader_editor->get_text_edit()->set_draw_spaces(EditorSettings::get_singleton()->get("text_editor/indent/draw_spaces")); - shader_editor->get_text_edit()->set_show_line_numbers(EditorSettings::get_singleton()->get("text_editor/appearance/show_line_numbers")); - shader_editor->get_text_edit()->set_highlight_all_occurrences(EditorSettings::get_singleton()->get("text_editor/highlighting/highlight_all_occurrences")); - shader_editor->get_text_edit()->set_highlight_current_line(EditorSettings::get_singleton()->get("text_editor/highlighting/highlight_current_line")); - shader_editor->get_text_edit()->cursor_set_blink_enabled(EditorSettings::get_singleton()->get("text_editor/cursor/caret_blink")); - shader_editor->get_text_edit()->cursor_set_blink_speed(EditorSettings::get_singleton()->get("text_editor/cursor/caret_blink_speed")); - shader_editor->get_text_edit()->add_theme_constant_override("line_spacing", EditorSettings::get_singleton()->get("text_editor/theme/line_spacing")); - shader_editor->get_text_edit()->cursor_set_block_mode(EditorSettings::get_singleton()->get("text_editor/cursor/block_caret")); - shader_editor->get_text_edit()->set_smooth_scroll_enabled(EditorSettings::get_singleton()->get("text_editor/navigation/smooth_scrolling")); - shader_editor->get_text_edit()->set_v_scroll_speed(EditorSettings::get_singleton()->get("text_editor/navigation/v_scroll_speed")); - shader_editor->get_text_edit()->set_draw_minimap(EditorSettings::get_singleton()->get("text_editor/navigation/show_minimap")); - shader_editor->get_text_edit()->set_minimap_width((int)EditorSettings::get_singleton()->get("text_editor/navigation/minimap_width") * EDSCALE); - shader_editor->get_text_edit()->set_show_line_length_guidelines(EditorSettings::get_singleton()->get("text_editor/appearance/show_line_length_guidelines")); - shader_editor->get_text_edit()->set_line_length_guideline_soft_column(EditorSettings::get_singleton()->get("text_editor/appearance/line_length_guideline_soft_column")); - shader_editor->get_text_edit()->set_line_length_guideline_hard_column(EditorSettings::get_singleton()->get("text_editor/appearance/line_length_guideline_hard_column")); - shader_editor->get_text_edit()->set_breakpoint_gutter_enabled(false); + shader_editor->update_editor_settings(); + + shader_editor->get_text_editor()->add_theme_constant_override("line_spacing", EditorSettings::get_singleton()->get("text_editor/theme/line_spacing")); + shader_editor->get_text_editor()->set_draw_breakpoints_gutter(false); + shader_editor->get_text_editor()->set_draw_executing_lines_gutter(false); } void ShaderEditor::_bind_methods() { @@ -466,7 +449,7 @@ void ShaderEditor::save_external_data(const String &p_str) { void ShaderEditor::apply_shaders() { if (shader.is_valid()) { String shader_code = shader->get_code(); - String editor_code = shader_editor->get_text_edit()->get_text(); + String editor_code = shader_editor->get_text_editor()->get_text(); if (shader_code != editor_code) { shader->set_code(editor_code); shader->set_edited(true); @@ -480,7 +463,7 @@ void ShaderEditor::_text_edit_gui_input(const Ref<InputEvent> &ev) { if (mb.is_valid()) { if (mb->get_button_index() == BUTTON_RIGHT && mb->is_pressed()) { int col, row; - TextEdit *tx = shader_editor->get_text_edit(); + CodeEdit *tx = shader_editor->get_text_editor(); tx->_get_mouse_pos(mb->get_global_position() - tx->get_global_position(), row, col); tx->set_right_click_moves_caret(EditorSettings::get_singleton()->get("text_editor/cursor/right_click_moves_caret")); @@ -507,7 +490,7 @@ void ShaderEditor::_text_edit_gui_input(const Ref<InputEvent> &ev) { Ref<InputEventKey> k = ev; if (k.is_valid() && k->is_pressed() && k->get_keycode() == KEY_MENU) { - TextEdit *tx = shader_editor->get_text_edit(); + CodeEdit *tx = shader_editor->get_text_editor(); _make_context_menu(tx->is_selection_active(), (get_global_transform().inverse() * tx->get_global_transform()).xform(tx->_get_cursor_pixel_pos())); context_menu->grab_focus(); } @@ -521,7 +504,7 @@ void ShaderEditor::_update_bookmark_list() { bookmarks_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/goto_next_bookmark"), BOOKMARK_GOTO_NEXT); bookmarks_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/goto_previous_bookmark"), BOOKMARK_GOTO_PREV); - Array bookmark_list = shader_editor->get_text_edit()->get_bookmarks_array(); + Array bookmark_list = shader_editor->get_text_editor()->get_bookmarked_lines(); if (bookmark_list.size() == 0) { return; } @@ -529,7 +512,7 @@ void ShaderEditor::_update_bookmark_list() { bookmarks_menu->add_separator(); for (int i = 0; i < bookmark_list.size(); i++) { - String line = shader_editor->get_text_edit()->get_line(bookmark_list[i]).strip_edges(); + String line = shader_editor->get_text_editor()->get_line(bookmark_list[i]).strip_edges(); // Limit the size of the line if too big. if (line.length() > 50) { line = line.substr(0, 50); @@ -581,13 +564,13 @@ ShaderEditor::ShaderEditor(EditorNode *p_node) { shader_editor->connect("script_changed", callable_mp(this, &ShaderEditor::apply_shaders)); EditorSettings::get_singleton()->connect("settings_changed", callable_mp(this, &ShaderEditor::_editor_settings_changed)); - shader_editor->get_text_edit()->set_callhint_settings( + shader_editor->get_text_editor()->set_callhint_settings( EditorSettings::get_singleton()->get("text_editor/completion/put_callhint_tooltip_below_current_line"), EditorSettings::get_singleton()->get("text_editor/completion/callhint_tooltip_offset")); - shader_editor->get_text_edit()->set_select_identifiers_on_hover(true); - shader_editor->get_text_edit()->set_context_menu_enabled(false); - shader_editor->get_text_edit()->connect("gui_input", callable_mp(this, &ShaderEditor::_text_edit_gui_input)); + shader_editor->get_text_editor()->set_select_identifiers_on_hover(true); + shader_editor->get_text_editor()->set_context_menu_enabled(false); + shader_editor->get_text_editor()->connect("gui_input", callable_mp(this, &ShaderEditor::_text_edit_gui_input)); shader_editor->update_editor_settings(); diff --git a/editor/plugins/text_editor.cpp b/editor/plugins/text_editor.cpp index 82e231e396..8935b698b6 100644 --- a/editor/plugins/text_editor.cpp +++ b/editor/plugins/text_editor.cpp @@ -50,7 +50,7 @@ void TextEditor::set_syntax_highlighter(Ref<EditorSyntaxHighlighter> p_highlight el = el->next(); } - TextEdit *te = code_editor->get_text_edit(); + CodeEdit *te = code_editor->get_text_editor(); te->set_syntax_highlighter(p_highlighter); } @@ -59,7 +59,7 @@ void TextEditor::_change_syntax_highlighter(int p_idx) { } void TextEditor::_load_theme_settings() { - TextEdit *text_edit = code_editor->get_text_edit(); + CodeEdit *text_edit = code_editor->get_text_editor(); text_edit->get_syntax_highlighter()->update_cache(); Color background_color = EDITOR_GET("text_editor/highlighting/background_color"); @@ -147,9 +147,9 @@ void TextEditor::set_edited_resource(const RES &p_res) { text_file = p_res; - code_editor->get_text_edit()->set_text(text_file->get_text()); - code_editor->get_text_edit()->clear_undo_history(); - code_editor->get_text_edit()->tag_saved_version(); + code_editor->get_text_editor()->set_text(text_file->get_text()); + code_editor->get_text_editor()->clear_undo_history(); + code_editor->get_text_editor()->tag_saved_version(); emit_signal("name_changed"); code_editor->update_line_and_column(); @@ -171,13 +171,14 @@ void TextEditor::add_callback(const String &p_function, PackedStringArray p_args void TextEditor::set_debugger_active(bool p_active) { } -void TextEditor::get_breakpoints(List<int> *p_breakpoints) { +Array TextEditor::get_breakpoints() { + return Array(); } void TextEditor::reload_text() { ERR_FAIL_COND(text_file.is_null()); - TextEdit *te = code_editor->get_text_edit(); + CodeEdit *te = code_editor->get_text_editor(); int column = te->cursor_get_column(); int row = te->cursor_get_line(); int h = te->get_h_scroll(); @@ -207,7 +208,7 @@ void TextEditor::_update_bookmark_list() { bookmarks_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/goto_next_bookmark"), BOOKMARK_GOTO_NEXT); bookmarks_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/goto_previous_bookmark"), BOOKMARK_GOTO_PREV); - Array bookmark_list = code_editor->get_text_edit()->get_bookmarks_array(); + Array bookmark_list = code_editor->get_text_editor()->get_bookmarked_lines(); if (bookmark_list.size() == 0) { return; } @@ -215,7 +216,7 @@ void TextEditor::_update_bookmark_list() { bookmarks_menu->add_separator(); for (int i = 0; i < bookmark_list.size(); i++) { - String line = code_editor->get_text_edit()->get_line(bookmark_list[i]).strip_edges(); + String line = code_editor->get_text_editor()->get_line(bookmark_list[i]).strip_edges(); // Limit the size of the line if too big. if (line.length() > 50) { line = line.substr(0, 50); @@ -235,12 +236,12 @@ void TextEditor::_bookmark_item_pressed(int p_idx) { } void TextEditor::apply_code() { - text_file->set_text(code_editor->get_text_edit()->get_text()); + text_file->set_text(code_editor->get_text_editor()->get_text()); } bool TextEditor::is_unsaved() { const bool unsaved = - code_editor->get_text_edit()->get_version() != code_editor->get_text_edit()->get_saved_version() || + code_editor->get_text_editor()->get_version() != code_editor->get_text_editor()->get_saved_version() || text_file->get_path().empty(); // In memory. return unsaved; } @@ -280,7 +281,7 @@ void TextEditor::convert_indent_to_tabs() { } void TextEditor::tag_saved_version() { - code_editor->get_text_edit()->tag_saved_version(); + code_editor->get_text_editor()->tag_saved_version(); } void TextEditor::goto_line(int p_line, bool p_with_error) { @@ -300,7 +301,7 @@ void TextEditor::clear_executing_line() { } void TextEditor::ensure_focus() { - code_editor->get_text_edit()->grab_focus(); + code_editor->get_text_editor()->grab_focus(); } Vector<String> TextEditor::get_functions() { @@ -316,7 +317,7 @@ void TextEditor::update_settings() { } void TextEditor::set_tooltip_request_func(String p_method, Object *p_obj) { - code_editor->get_text_edit()->set_tooltip_request_func(p_obj, p_method, this); + code_editor->get_text_editor()->set_tooltip_request_func(p_obj, p_method, this); } Control *TextEditor::get_edit_menu() { @@ -328,7 +329,7 @@ void TextEditor::clear_edit_menu() { } void TextEditor::_edit_option(int p_op) { - TextEdit *tx = code_editor->get_text_edit(); + CodeEdit *tx = code_editor->get_text_editor(); switch (p_op) { case EDIT_UNDO: { @@ -416,14 +417,14 @@ void TextEditor::_edit_option(int p_op) { code_editor->get_find_replace_bar()->popup_replace(); } break; case SEARCH_IN_FILES: { - String selected_text = code_editor->get_text_edit()->get_selection_text(); + String selected_text = code_editor->get_text_editor()->get_selection_text(); // Yep, because it doesn't make sense to instance this dialog for every single script open... // So this will be delegated to the ScriptEditor. emit_signal("search_in_files_requested", selected_text); } break; case REPLACE_IN_FILES: { - String selected_text = code_editor->get_text_edit()->get_selection_text(); + String selected_text = code_editor->get_text_editor()->get_selection_text(); emit_signal("replace_in_files_requested", selected_text); } break; @@ -470,7 +471,7 @@ void TextEditor::_text_edit_gui_input(const Ref<InputEvent> &ev) { if (mb.is_valid()) { if (mb->get_button_index() == BUTTON_RIGHT) { int col, row; - TextEdit *tx = code_editor->get_text_edit(); + CodeEdit *tx = code_editor->get_text_editor(); tx->_get_mouse_pos(mb->get_global_position() - tx->get_global_position(), row, col); tx->set_right_click_moves_caret(EditorSettings::get_singleton()->get("text_editor/cursor/right_click_moves_caret")); @@ -503,7 +504,7 @@ void TextEditor::_text_edit_gui_input(const Ref<InputEvent> &ev) { Ref<InputEventKey> k = ev; if (k.is_valid() && k->is_pressed() && k->get_keycode() == KEY_MENU) { - TextEdit *tx = code_editor->get_text_edit(); + CodeEdit *tx = code_editor->get_text_editor(); int line = tx->cursor_get_line(); _make_context_menu(tx->is_selection_active(), tx->can_fold(line), tx->is_folded(line), (get_global_transform().inverse() * tx->get_global_transform()).xform(tx->_get_cursor_pixel_pos())); context_menu->grab_focus(); @@ -552,8 +553,8 @@ TextEditor::TextEditor() { update_settings(); - code_editor->get_text_edit()->set_context_menu_enabled(false); - code_editor->get_text_edit()->connect("gui_input", callable_mp(this, &TextEditor::_text_edit_gui_input)); + code_editor->get_text_editor()->set_context_menu_enabled(false); + code_editor->get_text_editor()->connect("gui_input", callable_mp(this, &TextEditor::_text_edit_gui_input)); context_menu = memnew(PopupMenu); add_child(context_menu); @@ -649,7 +650,7 @@ TextEditor::TextEditor() { goto_line_dialog = memnew(GotoLineDialog); add_child(goto_line_dialog); - code_editor->get_text_edit()->set_drag_forwarding(this); + code_editor->get_text_editor()->set_drag_forwarding(this); } TextEditor::~TextEditor() { diff --git a/editor/plugins/text_editor.h b/editor/plugins/text_editor.h index f3e9e599cf..ea425bd033 100644 --- a/editor/plugins/text_editor.h +++ b/editor/plugins/text_editor.h @@ -119,7 +119,7 @@ public: virtual Variant get_edit_state() override; virtual void set_edit_state(const Variant &p_state) override; virtual Vector<String> get_functions() override; - virtual void get_breakpoints(List<int> *p_breakpoints) override; + virtual Array get_breakpoints() override; virtual void goto_line(int p_line, bool p_with_error = false) override; void goto_line_selection(int p_line, int p_begin, int p_end); virtual void set_executing_line(int p_line) override; diff --git a/editor/plugins/tile_map_editor_plugin.cpp b/editor/plugins/tile_map_editor_plugin.cpp index e71485e9fc..8cd8aaf277 100644 --- a/editor/plugins/tile_map_editor_plugin.cpp +++ b/editor/plugins/tile_map_editor_plugin.cpp @@ -802,7 +802,6 @@ void TileMapEditor::_draw_cell(Control *p_viewport, int p_cell, const Point2i &p r.size = node->get_tileset()->autotile_get_size(p_cell); r.position += (r.size + Vector2(spacing, spacing)) * offset; } - Size2 sc = p_xform.get_scale(); Size2 cell_size = node->get_cell_size(); bool centered_texture = node->is_centered_textures_enabled(); bool compatibility_mode_enabled = node->is_compatibility_mode_enabled(); @@ -838,12 +837,12 @@ void TileMapEditor::_draw_cell(Control *p_viewport, int p_cell, const Point2i &p } if (p_flip_h) { - sc.x *= -1.0; + rect.size.x *= -1.0; tile_ofs.x *= -1.0; } if (p_flip_v) { - sc.y *= -1.0; + rect.size.y *= -1.0; tile_ofs.y *= -1.0; } diff --git a/editor/plugins/tile_set_editor_plugin.cpp b/editor/plugins/tile_set_editor_plugin.cpp index 274c64263f..684d8f0f10 100644 --- a/editor/plugins/tile_set_editor_plugin.cpp +++ b/editor/plugins/tile_set_editor_plugin.cpp @@ -3109,6 +3109,7 @@ Vector2 TileSetEditor::snap_point(const Vector2 &point) { anchor += tileset->tile_get_region(get_current_tile()).position; anchor += WORKSPACE_MARGIN; Rect2 region(anchor, tile_size); + Rect2 tile_region(tileset->tile_get_region(get_current_tile()).position + WORKSPACE_MARGIN, tileset->tile_get_region(get_current_tile()).size); if (tileset->tile_get_tile_mode(get_current_tile()) == TileSet::SINGLE_TILE) { region.position = tileset->tile_get_region(get_current_tile()).position + WORKSPACE_MARGIN; region.size = tileset->tile_get_region(get_current_tile()).size; @@ -3118,6 +3119,7 @@ Vector2 TileSetEditor::snap_point(const Vector2 &point) { p.x = Math::snap_scalar_separation(snap_offset.x, snap_step.x, p.x, snap_separation.x); p.y = Math::snap_scalar_separation(snap_offset.y, snap_step.y, p.y, snap_separation.y); } + if (tools[SHAPE_KEEP_INSIDE_TILE]->is_pressed()) { if (p.x < region.position.x) { p.x = region.position.x; @@ -3132,6 +3134,20 @@ Vector2 TileSetEditor::snap_point(const Vector2 &point) { p.y = region.position.y + region.size.y; } } + + if (p.x < tile_region.position.x) { + p.x = tile_region.position.x; + } + if (p.y < tile_region.position.y) { + p.y = tile_region.position.y; + } + if (p.x > (tile_region.position.x + tile_region.size.x)) { + p.x = (tile_region.position.x + tile_region.size.x); + } + if (p.y > (tile_region.position.y + tile_region.size.y)) { + p.y = (tile_region.position.y + tile_region.size.y); + } + return p; } diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp index ccd236cbe4..7a70f4c5b6 100644 --- a/editor/plugins/visual_shader_editor_plugin.cpp +++ b/editor/plugins/visual_shader_editor_plugin.cpp @@ -60,25 +60,51 @@ void VisualShaderNodePlugin::_bind_methods() { /////////////////// +static Ref<StyleBoxEmpty> make_empty_stylebox(float p_margin_left = -1, float p_margin_top = -1, float p_margin_right = -1, float p_margin_bottom = -1) { + Ref<StyleBoxEmpty> style(memnew(StyleBoxEmpty)); + style->set_default_margin(MARGIN_LEFT, p_margin_left * EDSCALE); + style->set_default_margin(MARGIN_RIGHT, p_margin_right * EDSCALE); + style->set_default_margin(MARGIN_BOTTOM, p_margin_bottom * EDSCALE); + style->set_default_margin(MARGIN_TOP, p_margin_top * EDSCALE); + return style; +} + +/////////////////// + VisualShaderGraphPlugin::VisualShaderGraphPlugin() { } void VisualShaderGraphPlugin::_bind_methods() { + ClassDB::bind_method("add_node", &VisualShaderGraphPlugin::add_node); + ClassDB::bind_method("remove_node", &VisualShaderGraphPlugin::remove_node); + ClassDB::bind_method("connect_nodes", &VisualShaderGraphPlugin::connect_nodes); + ClassDB::bind_method("disconnect_nodes", &VisualShaderGraphPlugin::disconnect_nodes); + ClassDB::bind_method("set_node_position", &VisualShaderGraphPlugin::set_node_position); + ClassDB::bind_method("set_node_size", &VisualShaderGraphPlugin::set_node_size); ClassDB::bind_method("show_port_preview", &VisualShaderGraphPlugin::show_port_preview); + ClassDB::bind_method("update_node", &VisualShaderGraphPlugin::update_node); + ClassDB::bind_method("update_node_deferred", &VisualShaderGraphPlugin::update_node_deferred); + ClassDB::bind_method("set_input_port_default_value", &VisualShaderGraphPlugin::set_input_port_default_value); + ClassDB::bind_method("set_uniform_name", &VisualShaderGraphPlugin::set_uniform_name); } void VisualShaderGraphPlugin::register_shader(VisualShader *p_shader) { visual_shader = Ref<VisualShader>(p_shader); } -void VisualShaderGraphPlugin::show_port_preview(int p_port_id, int p_node_id) { - if (links.has(p_node_id) && links[p_node_id].type == visual_shader->get_shader_type()) { +void VisualShaderGraphPlugin::set_connections(List<VisualShader::Connection> &p_connections) { + connections = p_connections; +} + +void VisualShaderGraphPlugin::show_port_preview(VisualShader::Type p_type, int p_node_id, int p_port_id) { + if (visual_shader->get_shader_type() == p_type && links.has(p_node_id)) { for (Map<int, Port>::Element *E = links[p_node_id].output_ports.front(); E; E = E->next()) { E->value().preview_button->set_pressed(false); } - if (links[p_node_id].preview_visible && !is_dirty()) { + if (links[p_node_id].preview_visible && !is_dirty() && links[p_node_id].preview_box != nullptr) { links[p_node_id].graph_node->remove_child(links[p_node_id].preview_box); + memdelete(links[p_node_id].preview_box); links[p_node_id].graph_node->set_size(Vector2(-1, -1)); links[p_node_id].preview_visible = false; } @@ -109,6 +135,84 @@ void VisualShaderGraphPlugin::show_port_preview(int p_port_id, int p_node_id) { } } +void VisualShaderGraphPlugin::update_node_deferred(VisualShader::Type p_type, int p_node_id) { + call_deferred("update_node", p_type, p_node_id); +} + +void VisualShaderGraphPlugin::update_node(VisualShader::Type p_type, int p_node_id) { + if (p_type != visual_shader->get_shader_type() || !links.has(p_node_id)) { + return; + } + remove_node(p_type, p_node_id); + add_node(p_type, p_node_id); +} + +void VisualShaderGraphPlugin::set_input_port_default_value(VisualShader::Type p_type, int p_node_id, int p_port_id, Variant p_value) { + if (p_type != visual_shader->get_shader_type() || !links.has(p_node_id)) { + return; + } + + Button *button = links[p_node_id].input_ports[p_port_id].default_input_button; + + switch (p_value.get_type()) { + case Variant::COLOR: { + button->set_custom_minimum_size(Size2(30, 0) * EDSCALE); + if (!button->is_connected("draw", callable_mp(VisualShaderEditor::get_singleton(), &VisualShaderEditor::_draw_color_over_button))) { + button->connect("draw", callable_mp(VisualShaderEditor::get_singleton(), &VisualShaderEditor::_draw_color_over_button), varray(button, p_value)); + } + } break; + case Variant::BOOL: { + button->set_text(((bool)p_value) ? "true" : "false"); + } break; + case Variant::INT: + case Variant::FLOAT: { + button->set_text(String::num(p_value, 4)); + } break; + case Variant::VECTOR3: { + Vector3 v = p_value; + button->set_text(String::num(v.x, 3) + "," + String::num(v.y, 3) + "," + String::num(v.z, 3)); + } break; + default: { + } + } +} + +void VisualShaderGraphPlugin::set_uniform_name(VisualShader::Type p_type, int p_node_id, const String &p_name) { + if (visual_shader->get_shader_type() == p_type && links.has(p_node_id) && links[p_node_id].uniform_name != nullptr) { + links[p_node_id].uniform_name->set_text(p_name); + } +} + +void VisualShaderGraphPlugin::register_default_input_button(int p_node_id, int p_port_id, Button *p_button) { + links[p_node_id].input_ports.insert(p_port_id, { p_button }); +} + +void VisualShaderGraphPlugin::update_uniform_refs() { + for (Map<int, Link>::Element *E = links.front(); E; E = E->next()) { + VisualShaderNodeUniformRef *ref = Object::cast_to<VisualShaderNodeUniformRef>(E->get().visual_node); + if (ref) { + remove_node(E->get().type, E->key()); + add_node(E->get().type, E->key()); + } + } +} + +VisualShader::Type VisualShaderGraphPlugin::get_shader_type() const { + return visual_shader->get_shader_type(); +} + +void VisualShaderGraphPlugin::set_node_position(VisualShader::Type p_type, int p_id, const Vector2 &p_position) { + if (visual_shader->get_shader_type() == p_type && links.has(p_id)) { + links[p_id].graph_node->set_offset(p_position); + } +} + +void VisualShaderGraphPlugin::set_node_size(VisualShader::Type p_type, int p_id, const Vector2 &p_size) { + if (visual_shader->get_shader_type() == p_type && links.has(p_id)) { + links[p_id].graph_node->set_size(p_size); + } +} + bool VisualShaderGraphPlugin::is_preview_visible(int p_id) const { return links[p_id].preview_visible; } @@ -126,17 +230,397 @@ void VisualShaderGraphPlugin::make_dirty(bool p_enabled) { } void VisualShaderGraphPlugin::register_link(VisualShader::Type p_type, int p_id, VisualShaderNode *p_visual_node, GraphNode *p_graph_node) { - links.insert(p_id, { p_type, p_visual_node, p_graph_node, p_visual_node->get_output_port_for_preview() != -1, -1, Map<int, Port>(), nullptr }); - - if (!p_visual_node->is_connected("show_port_preview", callable_mp(this, &VisualShaderGraphPlugin::show_port_preview))) { - p_visual_node->connect("show_port_preview", callable_mp(this, &VisualShaderGraphPlugin::show_port_preview), varray(p_id), CONNECT_DEFERRED); - } + links.insert(p_id, { p_type, p_visual_node, p_graph_node, p_visual_node->get_output_port_for_preview() != -1, -1, Map<int, InputPort>(), Map<int, Port>(), nullptr, nullptr }); } void VisualShaderGraphPlugin::register_output_port(int p_node_id, int p_port, TextureButton *p_button) { links[p_node_id].output_ports.insert(p_port, { p_button }); } +void VisualShaderGraphPlugin::register_uniform_name(int p_node_id, LineEdit *p_uniform_name) { + links[p_node_id].uniform_name = p_uniform_name; +} + +void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) { + if (p_type != visual_shader->get_shader_type()) { + return; + } + + Control *offset; + + static Ref<StyleBoxEmpty> label_style = make_empty_stylebox(2, 1, 2, 1); + + static const Color type_color[6] = { + Color(0.38, 0.85, 0.96), // scalar (float) + Color(0.49, 0.78, 0.94), // scalar (int) + Color(0.84, 0.49, 0.93), // vector + Color(0.55, 0.65, 0.94), // boolean + Color(0.96, 0.66, 0.43), // transform + Color(1.0, 1.0, 0.0), // sampler + }; + + Ref<VisualShaderNode> vsnode = visual_shader->get_node(p_type, p_id); + + Ref<VisualShaderNodeGroupBase> group_node = Object::cast_to<VisualShaderNodeGroupBase>(vsnode.ptr()); + bool is_group = !group_node.is_null(); + Size2 size = Size2(0, 0); + + Ref<VisualShaderNodeExpression> expression_node = Object::cast_to<VisualShaderNodeExpression>(group_node.ptr()); + bool is_expression = !expression_node.is_null(); + String expression = ""; + + GraphNode *node = memnew(GraphNode); + register_link(p_type, p_id, vsnode.ptr(), node); + + if (is_group) { + size = group_node->get_size(); + + node->set_resizable(true); + node->connect("resize_request", callable_mp(VisualShaderEditor::get_singleton(), &VisualShaderEditor::_node_resized), varray((int)p_type, p_id)); + } + if (is_expression) { + expression = expression_node->get_expression(); + } + + node->set_offset(visual_shader->get_node_position(p_type, p_id)); + node->set_title(vsnode->get_caption()); + node->set_name(itos(p_id)); + + if (p_id >= 2) { + node->set_show_close_button(true); + node->connect("close_request", callable_mp(VisualShaderEditor::get_singleton(), &VisualShaderEditor::_delete_request), varray(p_id), CONNECT_DEFERRED); + } + + node->connect("dragged", callable_mp(VisualShaderEditor::get_singleton(), &VisualShaderEditor::_node_dragged), varray(p_id)); + + Control *custom_editor = nullptr; + int port_offset = 0; + + if (is_group) { + port_offset += 2; + } + + Ref<VisualShaderNodeUniform> uniform = vsnode; + if (uniform.is_valid()) { + VisualShaderEditor::get_singleton()->graph->add_child(node); + VisualShaderEditor::get_singleton()->_update_created_node(node); + + LineEdit *uniform_name = memnew(LineEdit); + register_uniform_name(p_id, uniform_name); + uniform_name->set_text(uniform->get_uniform_name()); + node->add_child(uniform_name); + uniform_name->connect("text_entered", callable_mp(VisualShaderEditor::get_singleton(), &VisualShaderEditor::_uniform_line_edit_changed), varray(p_id)); + uniform_name->connect("focus_exited", callable_mp(VisualShaderEditor::get_singleton(), &VisualShaderEditor::_uniform_line_edit_focus_out), varray(uniform_name, p_id)); + + if (vsnode->get_input_port_count() == 0 && vsnode->get_output_port_count() == 1 && vsnode->get_output_port_name(0) == "") { + //shortcut + VisualShaderNode::PortType port_right = vsnode->get_output_port_type(0); + node->set_slot(0, false, VisualShaderNode::PORT_TYPE_SCALAR, Color(), true, port_right, type_color[port_right]); + if (!vsnode->is_use_prop_slots()) { + return; + } + } + port_offset++; + } + + for (int i = 0; i < VisualShaderEditor::get_singleton()->plugins.size(); i++) { + vsnode->set_meta("id", p_id); + vsnode->set_meta("shader_type", (int)p_type); + custom_editor = VisualShaderEditor::get_singleton()->plugins.write[i]->create_editor(visual_shader, vsnode); + vsnode->remove_meta("id"); + vsnode->remove_meta("shader_type"); + if (custom_editor) { + if (vsnode->is_show_prop_names()) { + custom_editor->call_deferred("_show_prop_names", true); + } + break; + } + } + + if (custom_editor && !vsnode->is_use_prop_slots() && vsnode->get_output_port_count() > 0 && vsnode->get_output_port_name(0) == "" && (vsnode->get_input_port_count() == 0 || vsnode->get_input_port_name(0) == "")) { + //will be embedded in first port + } else if (custom_editor) { + port_offset++; + node->add_child(custom_editor); + if (vsnode->is_use_prop_slots()) { + return; + } + custom_editor = nullptr; + } + + if (is_group) { + offset = memnew(Control); + offset->set_custom_minimum_size(Size2(0, 6 * EDSCALE)); + node->add_child(offset); + + if (group_node->is_editable()) { + HBoxContainer *hb2 = memnew(HBoxContainer); + + Button *add_input_btn = memnew(Button); + add_input_btn->set_text(TTR("Add Input")); + add_input_btn->connect("pressed", callable_mp(VisualShaderEditor::get_singleton(), &VisualShaderEditor::_add_input_port), varray(p_id, group_node->get_free_input_port_id(), VisualShaderNode::PORT_TYPE_VECTOR, "input" + itos(group_node->get_free_input_port_id())), CONNECT_DEFERRED); + hb2->add_child(add_input_btn); + + hb2->add_spacer(); + + Button *add_output_btn = memnew(Button); + add_output_btn->set_text(TTR("Add Output")); + add_output_btn->connect("pressed", callable_mp(VisualShaderEditor::get_singleton(), &VisualShaderEditor::_add_output_port), varray(p_id, group_node->get_free_output_port_id(), VisualShaderNode::PORT_TYPE_VECTOR, "output" + itos(group_node->get_free_output_port_id())), CONNECT_DEFERRED); + hb2->add_child(add_output_btn); + + node->add_child(hb2); + } + } + + for (int i = 0; i < MAX(vsnode->get_input_port_count(), vsnode->get_output_port_count()); i++) { + if (vsnode->is_port_separator(i)) { + node->add_child(memnew(HSeparator)); + port_offset++; + } + + bool valid_left = i < vsnode->get_input_port_count(); + VisualShaderNode::PortType port_left = VisualShaderNode::PORT_TYPE_SCALAR; + bool port_left_used = false; + String name_left; + if (valid_left) { + name_left = vsnode->get_input_port_name(i); + port_left = vsnode->get_input_port_type(i); + for (List<VisualShader::Connection>::Element *E = connections.front(); E; E = E->next()) { + if (E->get().to_node == p_id && E->get().to_port == i) { + port_left_used = true; + } + } + } + + bool valid_right = i < vsnode->get_output_port_count(); + VisualShaderNode::PortType port_right = VisualShaderNode::PORT_TYPE_SCALAR; + String name_right; + if (valid_right) { + name_right = vsnode->get_output_port_name(i); + port_right = vsnode->get_output_port_type(i); + } + + HBoxContainer *hb = memnew(HBoxContainer); + hb->add_theme_constant_override("separation", 7 * EDSCALE); + + Variant default_value; + + if (valid_left && !port_left_used) { + default_value = vsnode->get_input_port_default_value(i); + } + + Button *button = memnew(Button); + hb->add_child(button); + register_default_input_button(p_id, i, button); + button->connect("pressed", callable_mp(VisualShaderEditor::get_singleton(), &VisualShaderEditor::_edit_port_default_input), varray(button, p_id, i)); + if (default_value.get_type() != Variant::NIL) { // only a label + set_input_port_default_value(p_type, p_id, i, default_value); + } else { + button->hide(); + } + + if (i == 0 && custom_editor) { + hb->add_child(custom_editor); + custom_editor->set_h_size_flags(Control::SIZE_EXPAND_FILL); + } else { + if (valid_left) { + if (is_group) { + OptionButton *type_box = memnew(OptionButton); + hb->add_child(type_box); + type_box->add_item(TTR("Float")); + type_box->add_item(TTR("Int")); + type_box->add_item(TTR("Vector")); + type_box->add_item(TTR("Boolean")); + type_box->add_item(TTR("Transform")); + type_box->add_item(TTR("Sampler")); + type_box->select(group_node->get_input_port_type(i)); + type_box->set_custom_minimum_size(Size2(100 * EDSCALE, 0)); + type_box->connect("item_selected", callable_mp(VisualShaderEditor::get_singleton(), &VisualShaderEditor::_change_input_port_type), varray(p_id, i), CONNECT_DEFERRED); + + LineEdit *name_box = memnew(LineEdit); + hb->add_child(name_box); + name_box->set_custom_minimum_size(Size2(65 * EDSCALE, 0)); + name_box->set_h_size_flags(Control::SIZE_EXPAND_FILL); + name_box->set_text(name_left); + name_box->connect("text_entered", callable_mp(VisualShaderEditor::get_singleton(), &VisualShaderEditor::_change_input_port_name), varray(name_box, p_id, i)); + name_box->connect("focus_exited", callable_mp(VisualShaderEditor::get_singleton(), &VisualShaderEditor::_port_name_focus_out), varray(name_box, p_id, i, false)); + + Button *remove_btn = memnew(Button); + remove_btn->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon("Remove", "EditorIcons")); + remove_btn->set_tooltip(TTR("Remove") + " " + name_left); + remove_btn->connect("pressed", callable_mp(VisualShaderEditor::get_singleton(), &VisualShaderEditor::_remove_input_port), varray(p_id, i), CONNECT_DEFERRED); + hb->add_child(remove_btn); + } else { + Label *label = memnew(Label); + label->set_text(name_left); + label->add_theme_style_override("normal", label_style); //more compact + hb->add_child(label); + + if (vsnode->get_input_port_default_hint(i) != "" && !port_left_used) { + Label *hint_label = memnew(Label); + hint_label->set_text("[" + vsnode->get_input_port_default_hint(i) + "]"); + hint_label->add_theme_color_override("font_color", VisualShaderEditor::get_singleton()->get_theme_color("font_color_readonly", "TextEdit")); + hint_label->add_theme_style_override("normal", label_style); + hb->add_child(hint_label); + } + } + } + + if (!is_group) { + hb->add_spacer(); + } + + if (valid_right) { + if (is_group) { + Button *remove_btn = memnew(Button); + remove_btn->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon("Remove", "EditorIcons")); + remove_btn->set_tooltip(TTR("Remove") + " " + name_left); + remove_btn->connect("pressed", callable_mp(VisualShaderEditor::get_singleton(), &VisualShaderEditor::_remove_output_port), varray(p_id, i), CONNECT_DEFERRED); + hb->add_child(remove_btn); + + LineEdit *name_box = memnew(LineEdit); + hb->add_child(name_box); + name_box->set_custom_minimum_size(Size2(65 * EDSCALE, 0)); + name_box->set_h_size_flags(Control::SIZE_EXPAND_FILL); + name_box->set_text(name_right); + name_box->connect("text_entered", callable_mp(VisualShaderEditor::get_singleton(), &VisualShaderEditor::_change_output_port_name), varray(name_box, p_id, i)); + name_box->connect("focus_exited", callable_mp(VisualShaderEditor::get_singleton(), &VisualShaderEditor::_port_name_focus_out), varray(name_box, p_id, i, true)); + + OptionButton *type_box = memnew(OptionButton); + hb->add_child(type_box); + type_box->add_item(TTR("Float")); + type_box->add_item(TTR("Int")); + type_box->add_item(TTR("Vector")); + type_box->add_item(TTR("Boolean")); + type_box->add_item(TTR("Transform")); + type_box->select(group_node->get_output_port_type(i)); + type_box->set_custom_minimum_size(Size2(100 * EDSCALE, 0)); + type_box->connect("item_selected", callable_mp(VisualShaderEditor::get_singleton(), &VisualShaderEditor::_change_output_port_type), varray(p_id, i), CONNECT_DEFERRED); + } else { + Label *label = memnew(Label); + label->set_text(name_right); + label->add_theme_style_override("normal", label_style); //more compact + hb->add_child(label); + } + } + } + + if (valid_right && visual_shader->get_shader_type() == VisualShader::TYPE_FRAGMENT && port_right != VisualShaderNode::PORT_TYPE_TRANSFORM && port_right != VisualShaderNode::PORT_TYPE_SAMPLER) { + TextureButton *preview = memnew(TextureButton); + preview->set_toggle_mode(true); + preview->set_normal_texture(VisualShaderEditor::get_singleton()->get_theme_icon("GuiVisibilityHidden", "EditorIcons")); + preview->set_pressed_texture(VisualShaderEditor::get_singleton()->get_theme_icon("GuiVisibilityVisible", "EditorIcons")); + preview->set_v_size_flags(Control::SIZE_SHRINK_CENTER); + + register_output_port(p_id, i, preview); + + preview->connect("pressed", callable_mp(VisualShaderEditor::get_singleton(), &VisualShaderEditor::_preview_select_port), varray(p_id, i), CONNECT_DEFERRED); + hb->add_child(preview); + } + + if (is_group) { + offset = memnew(Control); + offset->set_custom_minimum_size(Size2(0, 5 * EDSCALE)); + node->add_child(offset); + port_offset++; + } + + node->add_child(hb); + + node->set_slot(i + port_offset, valid_left, port_left, type_color[port_left], valid_right, port_right, type_color[port_right]); + } + + if (vsnode->get_output_port_for_preview() >= 0) { + show_port_preview(p_type, p_id, vsnode->get_output_port_for_preview()); + } + + offset = memnew(Control); + offset->set_custom_minimum_size(Size2(0, 4 * EDSCALE)); + node->add_child(offset); + + String error = vsnode->get_warning(visual_shader->get_mode(), p_type); + if (error != String()) { + Label *error_label = memnew(Label); + error_label->add_theme_color_override("font_color", VisualShaderEditor::get_singleton()->get_theme_color("error_color", "Editor")); + error_label->set_text(error); + node->add_child(error_label); + } + + if (is_expression) { + CodeEdit *expression_box = memnew(CodeEdit); + Ref<CodeHighlighter> expression_syntax_highlighter; + expression_syntax_highlighter.instance(); + expression_node->set_control(expression_box, 0); + node->add_child(expression_box); + + Color background_color = EDITOR_GET("text_editor/highlighting/background_color"); + Color text_color = EDITOR_GET("text_editor/highlighting/text_color"); + Color keyword_color = EDITOR_GET("text_editor/highlighting/keyword_color"); + Color comment_color = EDITOR_GET("text_editor/highlighting/comment_color"); + Color symbol_color = EDITOR_GET("text_editor/highlighting/symbol_color"); + Color function_color = EDITOR_GET("text_editor/highlighting/function_color"); + Color number_color = EDITOR_GET("text_editor/highlighting/number_color"); + Color members_color = EDITOR_GET("text_editor/highlighting/member_variable_color"); + + expression_box->set_syntax_highlighter(expression_syntax_highlighter); + expression_box->add_theme_color_override("background_color", background_color); + + for (List<String>::Element *E = VisualShaderEditor::get_singleton()->keyword_list.front(); E; E = E->next()) { + expression_syntax_highlighter->add_keyword_color(E->get(), keyword_color); + } + + expression_box->add_theme_font_override("font", VisualShaderEditor::get_singleton()->get_theme_font("expression", "EditorFonts")); + expression_box->add_theme_color_override("font_color", text_color); + expression_syntax_highlighter->set_number_color(number_color); + expression_syntax_highlighter->set_symbol_color(symbol_color); + expression_syntax_highlighter->set_function_color(function_color); + expression_syntax_highlighter->set_member_variable_color(members_color); + expression_syntax_highlighter->add_color_region("/*", "*/", comment_color, false); + expression_syntax_highlighter->add_color_region("//", "", comment_color, true); + + expression_box->set_text(expression); + expression_box->set_context_menu_enabled(false); + expression_box->set_draw_line_numbers(true); + + expression_box->connect("focus_exited", callable_mp(VisualShaderEditor::get_singleton(), &VisualShaderEditor::_expression_focus_out), varray(expression_box, p_id)); + } + + if (!uniform.is_valid()) { + VisualShaderEditor::get_singleton()->graph->add_child(node); + VisualShaderEditor::get_singleton()->_update_created_node(node); + if (is_group) { + VisualShaderEditor::get_singleton()->call_deferred("_set_node_size", (int)p_type, p_id, size); + } + } +} + +void VisualShaderGraphPlugin::remove_node(VisualShader::Type p_type, int p_id) { + if (visual_shader->get_shader_type() == p_type && links.has(p_id)) { + links[p_id].graph_node->get_parent()->remove_child(links[p_id].graph_node); + memdelete(links[p_id].graph_node); + links.erase(p_id); + } +} + +void VisualShaderGraphPlugin::connect_nodes(VisualShader::Type p_type, int p_from_node, int p_from_port, int p_to_node, int p_to_port) { + if (visual_shader->get_shader_type() == p_type) { + VisualShaderEditor::get_singleton()->graph->connect_node(itos(p_from_node), p_from_port, itos(p_to_node), p_to_port); + if (links[p_to_node].input_ports.has(p_to_port) && links[p_to_node].input_ports[p_to_port].default_input_button != nullptr) { + links[p_to_node].input_ports[p_to_port].default_input_button->hide(); + } + } +} + +void VisualShaderGraphPlugin::disconnect_nodes(VisualShader::Type p_type, int p_from_node, int p_from_port, int p_to_node, int p_to_port) { + if (visual_shader->get_shader_type() == p_type) { + VisualShaderEditor::get_singleton()->graph->disconnect_node(itos(p_from_node), p_from_port, itos(p_to_node), p_to_port); + if (links[p_to_node].input_ports.has(p_to_port) && links[p_to_node].input_ports[p_to_port].default_input_button != nullptr && links[p_to_node].visual_node->get_input_port_default_value(p_to_port).get_type() != Variant::NIL) { + links[p_to_node].input_ports[p_to_port].default_input_button->show(); + set_input_port_default_value(p_type, p_to_node, p_to_port, links[p_to_node].visual_node->get_input_port_default_value(p_to_port)); + } + } +} + VisualShaderGraphPlugin::~VisualShaderGraphPlugin() { } @@ -164,19 +648,7 @@ void VisualShaderEditor::edit(VisualShader *p_visual_shader) { } #endif visual_shader->set_graph_offset(graph->get_scroll_ofs() / EDSCALE); - - if (visual_shader->get_mode() == VisualShader::MODE_PARTICLES) { - edit_type_standart->set_visible(false); - edit_type_particles->set_visible(true); - edit_type = edit_type_particles; - particles_mode = true; - } else { - edit_type_particles->set_visible(false); - edit_type_standart->set_visible(true); - edit_type = edit_type_standart; - particles_mode = false; - } - visual_shader->set_shader_type(get_current_shader_type()); + _set_mode(visual_shader->get_mode()); } else { if (visual_shader.is_valid()) { if (visual_shader->is_connected("changed", callable_mp(this, &VisualShaderEditor::_update_preview))) { @@ -193,8 +665,8 @@ void VisualShaderEditor::edit(VisualShader *p_visual_shader) { _clear_buffer(); _update_options_menu(); _update_preview(); + _update_graph(); } - _update_graph(); } } @@ -484,6 +956,21 @@ void VisualShaderEditor::_update_options_menu() { } } +void VisualShaderEditor::_set_mode(int p_which) { + if (p_which == VisualShader::MODE_PARTICLES) { + edit_type_standart->set_visible(false); + edit_type_particles->set_visible(true); + edit_type = edit_type_particles; + particles_mode = true; + } else { + edit_type_particles->set_visible(false); + edit_type_standart->set_visible(true); + edit_type = edit_type_standart; + particles_mode = false; + } + visual_shader->set_shader_type(get_current_shader_type()); +} + Size2 VisualShaderEditor::get_minimum_size() const { return Size2(10, 200); } @@ -498,15 +985,6 @@ void VisualShaderEditor::_draw_color_over_button(Object *obj, Color p_color) { button->draw_rect(Rect2(normal->get_offset(), button->get_size() - normal->get_minimum_size()), p_color); } -static Ref<StyleBoxEmpty> make_empty_stylebox(float p_margin_left = -1, float p_margin_top = -1, float p_margin_right = -1, float p_margin_bottom = -1) { - Ref<StyleBoxEmpty> style(memnew(StyleBoxEmpty)); - style->set_default_margin(MARGIN_LEFT, p_margin_left * EDSCALE); - style->set_default_margin(MARGIN_RIGHT, p_margin_right * EDSCALE); - style->set_default_margin(MARGIN_BOTTOM, p_margin_bottom * EDSCALE); - style->set_default_margin(MARGIN_TOP, p_margin_top * EDSCALE); - return style; -} - void VisualShaderEditor::_update_created_node(GraphNode *node) { if (EditorSettings::get_singleton()->get("interface/theme/use_graph_node_headers")) { Ref<StyleBoxFlat> sb = node->get_theme_stylebox("frame", "GraphNode"); @@ -530,50 +1008,9 @@ void VisualShaderEditor::_update_created_node(GraphNode *node) { } } -void VisualShaderEditor::_update_graph() { - if (updating) { - return; - } - - if (visual_shader.is_null()) { - return; - } - - graph->set_scroll_ofs(visual_shader->get_graph_offset() * EDSCALE); - - VisualShader::Type type = get_current_shader_type(); - - graph->clear_connections(); - //erase all nodes - for (int i = 0; i < graph->get_child_count(); i++) { - if (Object::cast_to<GraphNode>(graph->get_child(i))) { - Node *node = graph->get_child(i); - graph->remove_child(node); - memdelete(node); - i--; - } - } - - static const Color type_color[6] = { - Color(0.38, 0.85, 0.96), // scalar (float) - Color(0.49, 0.78, 0.94), // scalar (int) - Color(0.84, 0.49, 0.93), // vector - Color(0.55, 0.65, 0.94), // boolean - Color(0.96, 0.66, 0.43), // transform - Color(1.0, 1.0, 0.0), // sampler - }; - - List<VisualShader::Connection> connections; - visual_shader->get_node_connections(type, &connections); - - Ref<StyleBoxEmpty> label_style = make_empty_stylebox(2, 1, 2, 1); - - Vector<int> nodes = visual_shader->get_node_list(type); - +void VisualShaderEditor::_update_uniforms(bool p_update_refs) { VisualShaderNodeUniformRef::clear_uniforms(); - // scan for all uniforms - for (int t = 0; t < VisualShader::TYPE_MAX; t++) { Vector<int> tnodes = visual_shader->get_node_list((VisualShader::Type)t); for (int i = 0; i < tnodes.size(); i++) { @@ -608,378 +1045,69 @@ void VisualShaderEditor::_update_graph() { } } } + if (p_update_refs) { + graph_plugin->update_uniform_refs(); + } +} - Control *offset; - - graph_plugin->clear_links(); - graph_plugin->make_dirty(true); - - for (int n_i = 0; n_i < nodes.size(); n_i++) { - Vector2 position = visual_shader->get_node_position(type, nodes[n_i]); - Ref<VisualShaderNode> vsnode = visual_shader->get_node(type, nodes[n_i]); - - Ref<VisualShaderNodeGroupBase> group_node = Object::cast_to<VisualShaderNodeGroupBase>(vsnode.ptr()); - bool is_group = !group_node.is_null(); - Size2 size = Size2(0, 0); - - Ref<VisualShaderNodeExpression> expression_node = Object::cast_to<VisualShaderNodeExpression>(group_node.ptr()); - bool is_expression = !expression_node.is_null(); - String expression = ""; - - GraphNode *node = memnew(GraphNode); - visual_shader->set_graph_node(type, nodes[n_i], node); - graph_plugin->register_link(type, nodes[n_i], vsnode.ptr(), node); - - if (is_group) { - size = group_node->get_size(); - - node->set_resizable(true); - node->connect("resize_request", callable_mp(this, &VisualShaderEditor::_node_resized), varray((int)type, nodes[n_i])); - } - if (is_expression) { - expression = expression_node->get_expression(); - } - - node->set_offset(position); - - node->set_title(vsnode->get_caption()); - node->set_name(itos(nodes[n_i])); - - if (nodes[n_i] >= 2) { - node->set_show_close_button(true); - node->connect("close_request", callable_mp(this, &VisualShaderEditor::_delete_request), varray(nodes[n_i]), CONNECT_DEFERRED); - } - - node->connect("dragged", callable_mp(this, &VisualShaderEditor::_node_dragged), varray(nodes[n_i])); - - Control *custom_editor = nullptr; - int port_offset = 0; - - if (is_group) { - port_offset += 2; - } - - Ref<VisualShaderNodeUniform> uniform = vsnode; - Ref<VisualShaderNodeFloatUniform> float_uniform = vsnode; - Ref<VisualShaderNodeIntUniform> int_uniform = vsnode; - Ref<VisualShaderNodeVec3Uniform> vec3_uniform = vsnode; - Ref<VisualShaderNodeColorUniform> color_uniform = vsnode; - Ref<VisualShaderNodeBooleanUniform> bool_uniform = vsnode; - Ref<VisualShaderNodeTransformUniform> transform_uniform = vsnode; - if (uniform.is_valid()) { - graph->add_child(node); - _update_created_node(node); - - LineEdit *uniform_name = memnew(LineEdit); - uniform_name->set_text(uniform->get_uniform_name()); - node->add_child(uniform_name); - uniform_name->connect("text_entered", callable_mp(this, &VisualShaderEditor::_line_edit_changed), varray(uniform_name, nodes[n_i])); - uniform_name->connect("focus_exited", callable_mp(this, &VisualShaderEditor::_line_edit_focus_out), varray(uniform_name, nodes[n_i])); - - String error = vsnode->get_warning(visual_shader->get_mode(), type); - if (error != String()) { - offset = memnew(Control); - offset->set_custom_minimum_size(Size2(0, 4 * EDSCALE)); - node->add_child(offset); - Label *error_label = memnew(Label); - error_label->add_theme_color_override("font_color", get_theme_color("error_color", "Editor")); - error_label->set_text(error); - node->add_child(error_label); - } - - if (vsnode->get_input_port_count() == 0 && vsnode->get_output_port_count() == 1 && vsnode->get_output_port_name(0) == "") { - //shortcut - VisualShaderNode::PortType port_right = vsnode->get_output_port_type(0); - node->set_slot(0, false, VisualShaderNode::PORT_TYPE_SCALAR, Color(), true, port_right, type_color[port_right]); - if (!float_uniform.is_valid() && !int_uniform.is_valid() && !vec3_uniform.is_valid() && !color_uniform.is_valid() && !bool_uniform.is_valid() && !transform_uniform.is_valid()) { - continue; - } - } - port_offset++; - } - - for (int i = 0; i < plugins.size(); i++) { - custom_editor = plugins.write[i]->create_editor(visual_shader, vsnode); - if (custom_editor) { - break; - } - } - - if (custom_editor && !float_uniform.is_valid() && !int_uniform.is_valid() && !vec3_uniform.is_valid() && !bool_uniform.is_valid() && !transform_uniform.is_valid() && vsnode->get_output_port_count() > 0 && vsnode->get_output_port_name(0) == "" && (vsnode->get_input_port_count() == 0 || vsnode->get_input_port_name(0) == "")) { - //will be embedded in first port - } else if (custom_editor) { - port_offset++; - node->add_child(custom_editor); - if (color_uniform.is_valid()) { - custom_editor->call_deferred("_show_prop_names", true); - } - if (float_uniform.is_valid() || int_uniform.is_valid() || vec3_uniform.is_valid() || bool_uniform.is_valid() || transform_uniform.is_valid()) { - custom_editor->call_deferred("_show_prop_names", true); - continue; - } - custom_editor = nullptr; - } - - if (is_group) { - offset = memnew(Control); - offset->set_custom_minimum_size(Size2(0, 6 * EDSCALE)); - node->add_child(offset); - - if (group_node->is_editable()) { - HBoxContainer *hb2 = memnew(HBoxContainer); - - Button *add_input_btn = memnew(Button); - add_input_btn->set_text(TTR("Add Input")); - add_input_btn->connect("pressed", callable_mp(this, &VisualShaderEditor::_add_input_port), varray(nodes[n_i], group_node->get_free_input_port_id(), VisualShaderNode::PORT_TYPE_VECTOR, "input" + itos(group_node->get_free_input_port_id())), CONNECT_DEFERRED); - hb2->add_child(add_input_btn); - - hb2->add_spacer(); - - Button *add_output_btn = memnew(Button); - add_output_btn->set_text(TTR("Add Output")); - add_output_btn->connect("pressed", callable_mp(this, &VisualShaderEditor::_add_output_port), varray(nodes[n_i], group_node->get_free_output_port_id(), VisualShaderNode::PORT_TYPE_VECTOR, "output" + itos(group_node->get_free_output_port_id())), CONNECT_DEFERRED); - hb2->add_child(add_output_btn); - - node->add_child(hb2); - } - } - - for (int i = 0; i < MAX(vsnode->get_input_port_count(), vsnode->get_output_port_count()); i++) { - if (vsnode->is_port_separator(i)) { - node->add_child(memnew(HSeparator)); - port_offset++; - } - - bool valid_left = i < vsnode->get_input_port_count(); - VisualShaderNode::PortType port_left = VisualShaderNode::PORT_TYPE_SCALAR; - bool port_left_used = false; - String name_left; - if (valid_left) { - name_left = vsnode->get_input_port_name(i); - port_left = vsnode->get_input_port_type(i); - for (List<VisualShader::Connection>::Element *E = connections.front(); E; E = E->next()) { - if (E->get().to_node == nodes[n_i] && E->get().to_port == i) { - port_left_used = true; - } - } - } - - bool valid_right = i < vsnode->get_output_port_count(); - VisualShaderNode::PortType port_right = VisualShaderNode::PORT_TYPE_SCALAR; - String name_right; - if (valid_right) { - name_right = vsnode->get_output_port_name(i); - port_right = vsnode->get_output_port_type(i); - } - - HBoxContainer *hb = memnew(HBoxContainer); - hb->add_theme_constant_override("separation", 7 * EDSCALE); - - Variant default_value; - - if (valid_left && !port_left_used) { - default_value = vsnode->get_input_port_default_value(i); - } - - if (default_value.get_type() != Variant::NIL) { // only a label - Button *button = memnew(Button); - hb->add_child(button); - button->connect("pressed", callable_mp(this, &VisualShaderEditor::_edit_port_default_input), varray(button, nodes[n_i], i)); - - switch (default_value.get_type()) { - case Variant::COLOR: { - button->set_custom_minimum_size(Size2(30, 0) * EDSCALE); - button->connect("draw", callable_mp(this, &VisualShaderEditor::_draw_color_over_button), varray(button, default_value)); - } break; - case Variant::BOOL: { - button->set_text(((bool)default_value) ? "true" : "false"); - } break; - case Variant::INT: - case Variant::FLOAT: { - button->set_text(String::num(default_value, 4)); - } break; - case Variant::VECTOR3: { - Vector3 v = default_value; - button->set_text(String::num(v.x, 3) + "," + String::num(v.y, 3) + "," + String::num(v.z, 3)); - } break; - default: { - } - } - } - - if (i == 0 && custom_editor) { - hb->add_child(custom_editor); - custom_editor->set_h_size_flags(SIZE_EXPAND_FILL); - } else { - if (valid_left) { - if (is_group) { - OptionButton *type_box = memnew(OptionButton); - hb->add_child(type_box); - type_box->add_item(TTR("Float")); - type_box->add_item(TTR("Int")); - type_box->add_item(TTR("Vector")); - type_box->add_item(TTR("Boolean")); - type_box->add_item(TTR("Transform")); - type_box->add_item(TTR("Sampler")); - type_box->select(group_node->get_input_port_type(i)); - type_box->set_custom_minimum_size(Size2(100 * EDSCALE, 0)); - type_box->connect("item_selected", callable_mp(this, &VisualShaderEditor::_change_input_port_type), varray(nodes[n_i], i), CONNECT_DEFERRED); - - LineEdit *name_box = memnew(LineEdit); - hb->add_child(name_box); - name_box->set_custom_minimum_size(Size2(65 * EDSCALE, 0)); - name_box->set_h_size_flags(SIZE_EXPAND_FILL); - name_box->set_text(name_left); - name_box->connect("text_entered", callable_mp(this, &VisualShaderEditor::_change_input_port_name), varray(name_box, nodes[n_i], i)); - name_box->connect("focus_exited", callable_mp(this, &VisualShaderEditor::_port_name_focus_out), varray(name_box, nodes[n_i], i, false)); - - Button *remove_btn = memnew(Button); - remove_btn->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon("Remove", "EditorIcons")); - remove_btn->set_tooltip(TTR("Remove") + " " + name_left); - remove_btn->connect("pressed", callable_mp(this, &VisualShaderEditor::_remove_input_port), varray(nodes[n_i], i), CONNECT_DEFERRED); - hb->add_child(remove_btn); - } else { - Label *label = memnew(Label); - label->set_text(name_left); - label->add_theme_style_override("normal", label_style); //more compact - hb->add_child(label); - - if (vsnode->get_input_port_default_hint(i) != "" && !port_left_used) { - Label *hint_label = memnew(Label); - hint_label->set_text("[" + vsnode->get_input_port_default_hint(i) + "]"); - hint_label->add_theme_color_override("font_color", get_theme_color("font_color_readonly", "TextEdit")); - hint_label->add_theme_style_override("normal", label_style); - hb->add_child(hint_label); - } - } - } - - if (!is_group) { - hb->add_spacer(); - } +void VisualShaderEditor::_update_uniform_refs(Set<String> &p_deleted_names) { + for (int i = 0; i < VisualShader::TYPE_MAX; i++) { + VisualShader::Type type = VisualShader::Type(i); - if (valid_right) { - if (is_group) { - Button *remove_btn = memnew(Button); - remove_btn->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon("Remove", "EditorIcons")); - remove_btn->set_tooltip(TTR("Remove") + " " + name_left); - remove_btn->connect("pressed", callable_mp(this, &VisualShaderEditor::_remove_output_port), varray(nodes[n_i], i), CONNECT_DEFERRED); - hb->add_child(remove_btn); - - LineEdit *name_box = memnew(LineEdit); - hb->add_child(name_box); - name_box->set_custom_minimum_size(Size2(65 * EDSCALE, 0)); - name_box->set_h_size_flags(SIZE_EXPAND_FILL); - name_box->set_text(name_right); - name_box->connect("text_entered", callable_mp(this, &VisualShaderEditor::_change_output_port_name), varray(name_box, nodes[n_i], i)); - name_box->connect("focus_exited", callable_mp(this, &VisualShaderEditor::_port_name_focus_out), varray(name_box, nodes[n_i], i, true)); - - OptionButton *type_box = memnew(OptionButton); - hb->add_child(type_box); - type_box->add_item(TTR("Float")); - type_box->add_item(TTR("Int")); - type_box->add_item(TTR("Vector")); - type_box->add_item(TTR("Boolean")); - type_box->add_item(TTR("Transform")); - type_box->select(group_node->get_output_port_type(i)); - type_box->set_custom_minimum_size(Size2(100 * EDSCALE, 0)); - type_box->connect("item_selected", callable_mp(this, &VisualShaderEditor::_change_output_port_type), varray(nodes[n_i], i), CONNECT_DEFERRED); - } else { - Label *label = memnew(Label); - label->set_text(name_right); - label->add_theme_style_override("normal", label_style); //more compact - hb->add_child(label); + Vector<int> nodes = visual_shader->get_node_list(type); + for (int j = 0; j < nodes.size(); j++) { + if (j > 0) { + Ref<VisualShaderNodeUniformRef> ref = visual_shader->get_node(type, nodes[j]); + if (ref.is_valid()) { + if (p_deleted_names.has(ref->get_uniform_name())) { + undo_redo->add_do_method(ref.ptr(), "set_uniform_name", "[None]"); + undo_redo->add_undo_method(ref.ptr(), "set_uniform_name", ref->get_uniform_name()); + undo_redo->add_do_method(graph_plugin.ptr(), "update_node", VisualShader::Type(i), nodes[j]); + undo_redo->add_undo_method(graph_plugin.ptr(), "update_node", VisualShader::Type(i), nodes[j]); } } } - - if (valid_right && edit_type->get_selected() == VisualShader::TYPE_FRAGMENT && port_right != VisualShaderNode::PORT_TYPE_TRANSFORM && port_right != VisualShaderNode::PORT_TYPE_SAMPLER) { - TextureButton *preview = memnew(TextureButton); - preview->set_toggle_mode(true); - preview->set_normal_texture(get_theme_icon("GuiVisibilityHidden", "EditorIcons")); - preview->set_pressed_texture(get_theme_icon("GuiVisibilityVisible", "EditorIcons")); - preview->set_v_size_flags(SIZE_SHRINK_CENTER); - - graph_plugin->register_output_port(nodes[n_i], i, preview); - - preview->connect("pressed", callable_mp(this, &VisualShaderEditor::_preview_select_port), varray(nodes[n_i], i), CONNECT_DEFERRED); - hb->add_child(preview); - } - - if (is_group) { - offset = memnew(Control); - offset->set_custom_minimum_size(Size2(0, 5 * EDSCALE)); - node->add_child(offset); - port_offset++; - } - - node->add_child(hb); - - node->set_slot(i + port_offset, valid_left, port_left, type_color[port_left], valid_right, port_right, type_color[port_right]); - } - - if (vsnode->get_output_port_for_preview() >= 0) { - graph_plugin->show_port_preview(vsnode->get_output_port_for_preview(), nodes[n_i]); } + } +} - offset = memnew(Control); - offset->set_custom_minimum_size(Size2(0, 4 * EDSCALE)); - node->add_child(offset); +void VisualShaderEditor::_update_graph() { + if (updating) { + return; + } - String error = vsnode->get_warning(visual_shader->get_mode(), type); - if (error != String()) { - Label *error_label = memnew(Label); - error_label->add_theme_color_override("font_color", get_theme_color("error_color", "Editor")); - error_label->set_text(error); - node->add_child(error_label); - } + if (visual_shader.is_null()) { + return; + } - if (is_expression) { - TextEdit *expression_box = memnew(TextEdit); - Ref<CodeHighlighter> expression_syntax_highlighter; - expression_syntax_highlighter.instance(); - expression_node->set_control(expression_box, 0); - node->add_child(expression_box); + graph->set_scroll_ofs(visual_shader->get_graph_offset() * EDSCALE); - Color background_color = EDITOR_GET("text_editor/highlighting/background_color"); - Color text_color = EDITOR_GET("text_editor/highlighting/text_color"); - Color keyword_color = EDITOR_GET("text_editor/highlighting/keyword_color"); - Color comment_color = EDITOR_GET("text_editor/highlighting/comment_color"); - Color symbol_color = EDITOR_GET("text_editor/highlighting/symbol_color"); - Color function_color = EDITOR_GET("text_editor/highlighting/function_color"); - Color number_color = EDITOR_GET("text_editor/highlighting/number_color"); - Color members_color = EDITOR_GET("text_editor/highlighting/member_variable_color"); + VisualShader::Type type = get_current_shader_type(); - expression_box->set_syntax_highlighter(expression_syntax_highlighter); - expression_box->add_theme_color_override("background_color", background_color); + graph->clear_connections(); + //erase all nodes + for (int i = 0; i < graph->get_child_count(); i++) { + if (Object::cast_to<GraphNode>(graph->get_child(i))) { + Node *node = graph->get_child(i); + graph->remove_child(node); + memdelete(node); + i--; + } + } - for (List<String>::Element *E = keyword_list.front(); E; E = E->next()) { - expression_syntax_highlighter->add_keyword_color(E->get(), keyword_color); - } + List<VisualShader::Connection> connections; + visual_shader->get_node_connections(type, &connections); + graph_plugin->set_connections(connections); - expression_box->add_theme_font_override("font", get_theme_font("expression", "EditorFonts")); - expression_box->add_theme_color_override("font_color", text_color); - expression_syntax_highlighter->set_number_color(number_color); - expression_syntax_highlighter->set_symbol_color(symbol_color); - expression_syntax_highlighter->set_function_color(function_color); - expression_syntax_highlighter->set_member_variable_color(members_color); - expression_syntax_highlighter->add_color_region("/*", "*/", comment_color, false); - expression_syntax_highlighter->add_color_region("//", "", comment_color, true); + Vector<int> nodes = visual_shader->get_node_list(type); - expression_box->set_text(expression); - expression_box->set_context_menu_enabled(false); - expression_box->set_show_line_numbers(true); + _update_uniforms(false); - expression_box->connect("focus_exited", callable_mp(this, &VisualShaderEditor::_expression_focus_out), varray(expression_box, nodes[n_i])); - } + graph_plugin->clear_links(); + graph_plugin->make_dirty(true); - if (!uniform.is_valid()) { - graph->add_child(node); - _update_created_node(node); - if (is_group) { - call_deferred("_set_node_size", (int)type, nodes[n_i], size); - } - } + for (int n_i = 0; n_i < nodes.size(); n_i++) { + graph_plugin->add_node(type, nodes[n_i]); } graph_plugin->make_dirty(false); @@ -1014,10 +1142,8 @@ void VisualShaderEditor::_add_input_port(int p_node, int p_port, int p_port_type undo_redo->create_action(TTR("Add input port")); undo_redo->add_do_method(node.ptr(), "add_input_port", p_port, p_port_type, p_name); undo_redo->add_undo_method(node.ptr(), "remove_input_port", p_port); - undo_redo->add_do_method(this, "_update_graph"); - undo_redo->add_undo_method(this, "_update_graph"); - undo_redo->add_do_method(this, "_rebuild"); - undo_redo->add_undo_method(this, "_rebuild"); + undo_redo->add_do_method(graph_plugin.ptr(), "update_node", type, p_node); + undo_redo->add_undo_method(graph_plugin.ptr(), "update_node", type, p_node); undo_redo->commit_action(); } @@ -1031,10 +1157,8 @@ void VisualShaderEditor::_add_output_port(int p_node, int p_port, int p_port_typ undo_redo->create_action(TTR("Add output port")); undo_redo->add_do_method(node.ptr(), "add_output_port", p_port, p_port_type, p_name); undo_redo->add_undo_method(node.ptr(), "remove_output_port", p_port); - undo_redo->add_do_method(this, "_update_graph"); - undo_redo->add_undo_method(this, "_update_graph"); - undo_redo->add_do_method(this, "_rebuild"); - undo_redo->add_undo_method(this, "_rebuild"); + undo_redo->add_do_method(graph_plugin.ptr(), "update_node", type, p_node); + undo_redo->add_undo_method(graph_plugin.ptr(), "update_node", type, p_node); undo_redo->commit_action(); } @@ -1048,10 +1172,8 @@ void VisualShaderEditor::_change_input_port_type(int p_type, int p_node, int p_p undo_redo->create_action(TTR("Change input port type")); undo_redo->add_do_method(node.ptr(), "set_input_port_type", p_port, p_type); undo_redo->add_undo_method(node.ptr(), "set_input_port_type", p_port, node->get_input_port_type(p_port)); - undo_redo->add_do_method(this, "_update_graph"); - undo_redo->add_undo_method(this, "_update_graph"); - undo_redo->add_do_method(this, "_rebuild"); - undo_redo->add_undo_method(this, "_rebuild"); + undo_redo->add_do_method(graph_plugin.ptr(), "update_node", type, p_node); + undo_redo->add_undo_method(graph_plugin.ptr(), "update_node", type, p_node); undo_redo->commit_action(); } @@ -1065,10 +1187,8 @@ void VisualShaderEditor::_change_output_port_type(int p_type, int p_node, int p_ undo_redo->create_action(TTR("Change output port type")); undo_redo->add_do_method(node.ptr(), "set_output_port_type", p_port, p_type); undo_redo->add_undo_method(node.ptr(), "set_output_port_type", p_port, node->get_output_port_type(p_port)); - undo_redo->add_do_method(this, "_update_graph"); - undo_redo->add_undo_method(this, "_update_graph"); - undo_redo->add_do_method(this, "_rebuild"); - undo_redo->add_undo_method(this, "_rebuild"); + undo_redo->add_do_method(graph_plugin.ptr(), "update_node", type, p_node); + undo_redo->add_undo_method(graph_plugin.ptr(), "update_node", type, p_node); undo_redo->commit_action(); } @@ -1081,8 +1201,8 @@ void VisualShaderEditor::_change_input_port_name(const String &p_text, Object *l undo_redo->create_action(TTR("Change input port name")); undo_redo->add_do_method(node.ptr(), "set_input_port_name", p_port_id, p_text); undo_redo->add_undo_method(node.ptr(), "set_input_port_name", p_port_id, node->get_input_port_name(p_port_id)); - undo_redo->add_do_method(this, "_rebuild"); - undo_redo->add_undo_method(this, "_rebuild"); + undo_redo->add_do_method(graph_plugin.ptr(), "update_node", type, p_node_id); + undo_redo->add_undo_method(graph_plugin.ptr(), "update_node", type, p_node_id); undo_redo->commit_action(); } @@ -1095,8 +1215,8 @@ void VisualShaderEditor::_change_output_port_name(const String &p_text, Object * undo_redo->create_action(TTR("Change output port name")); undo_redo->add_do_method(node.ptr(), "set_output_port_name", p_port_id, p_text); undo_redo->add_undo_method(node.ptr(), "set_output_port_name", p_port_id, node->get_output_port_name(p_port_id)); - undo_redo->add_do_method(this, "_rebuild"); - undo_redo->add_undo_method(this, "_rebuild"); + undo_redo->add_do_method(graph_plugin.ptr(), "update_node", type, p_node_id); + undo_redo->add_undo_method(graph_plugin.ptr(), "update_node", type, p_node_id); undo_redo->commit_action(); } @@ -1121,12 +1241,21 @@ void VisualShaderEditor::_remove_input_port(int p_node, int p_port) { if (to_port == p_port) { undo_redo->add_do_method(visual_shader.ptr(), "disconnect_nodes", type, from_node, from_port, to_node, to_port); undo_redo->add_undo_method(visual_shader.ptr(), "connect_nodes_forced", type, from_node, from_port, to_node, to_port); + + undo_redo->add_do_method(graph_plugin.ptr(), "disconnect_nodes", type, from_node, from_port, to_node, to_port); + undo_redo->add_undo_method(graph_plugin.ptr(), "connect_nodes", type, from_node, from_port, to_node, to_port); } else if (to_port > p_port) { undo_redo->add_do_method(visual_shader.ptr(), "disconnect_nodes", type, from_node, from_port, to_node, to_port); undo_redo->add_undo_method(visual_shader.ptr(), "connect_nodes_forced", type, from_node, from_port, to_node, to_port); + undo_redo->add_do_method(graph_plugin.ptr(), "disconnect_nodes", type, from_node, from_port, to_node, to_port); + undo_redo->add_undo_method(graph_plugin.ptr(), "connect_nodes", type, from_node, from_port, to_node, to_port); + undo_redo->add_do_method(visual_shader.ptr(), "connect_nodes_forced", type, from_node, from_port, to_node, to_port - 1); undo_redo->add_undo_method(visual_shader.ptr(), "disconnect_nodes", type, from_node, from_port, to_node, to_port - 1); + + undo_redo->add_do_method(graph_plugin.ptr(), "connect_nodes", type, from_node, from_port, to_node, to_port - 1); + undo_redo->add_undo_method(graph_plugin.ptr(), "disconnect_nodes", type, from_node, from_port, to_node, to_port - 1); } } } @@ -1134,11 +1263,8 @@ void VisualShaderEditor::_remove_input_port(int p_node, int p_port) { undo_redo->add_do_method(node.ptr(), "remove_input_port", p_port); undo_redo->add_undo_method(node.ptr(), "add_input_port", p_port, (int)node->get_input_port_type(p_port), node->get_input_port_name(p_port)); - undo_redo->add_do_method(this, "_update_graph"); - undo_redo->add_undo_method(this, "_update_graph"); - - undo_redo->add_do_method(this, "_rebuild"); - undo_redo->add_undo_method(this, "_rebuild"); + undo_redo->add_do_method(graph_plugin.ptr(), "update_node", type, p_node); + undo_redo->add_undo_method(graph_plugin.ptr(), "update_node", type, p_node); undo_redo->commit_action(); } @@ -1164,12 +1290,21 @@ void VisualShaderEditor::_remove_output_port(int p_node, int p_port) { if (from_port == p_port) { undo_redo->add_do_method(visual_shader.ptr(), "disconnect_nodes", type, from_node, from_port, to_node, to_port); undo_redo->add_undo_method(visual_shader.ptr(), "connect_nodes_forced", type, from_node, from_port, to_node, to_port); + + undo_redo->add_do_method(graph_plugin.ptr(), "disconnect_nodes", type, from_node, from_port, to_node, to_port); + undo_redo->add_undo_method(graph_plugin.ptr(), "connect_nodes", type, from_node, from_port, to_node, to_port); } else if (from_port > p_port) { undo_redo->add_do_method(visual_shader.ptr(), "disconnect_nodes", type, from_node, from_port, to_node, to_port); undo_redo->add_undo_method(visual_shader.ptr(), "connect_nodes_forced", type, from_node, from_port, to_node, to_port); + undo_redo->add_do_method(graph_plugin.ptr(), "disconnect_nodes", type, from_node, from_port, to_node, to_port); + undo_redo->add_undo_method(graph_plugin.ptr(), "connect_nodes", type, from_node, from_port, to_node, to_port); + undo_redo->add_do_method(visual_shader.ptr(), "connect_nodes_forced", type, from_node, from_port - 1, to_node, to_port); undo_redo->add_undo_method(visual_shader.ptr(), "disconnect_nodes", type, from_node, from_port - 1, to_node, to_port); + + undo_redo->add_do_method(graph_plugin.ptr(), "connect_nodes", type, from_node, from_port - 1, to_node, to_port); + undo_redo->add_undo_method(graph_plugin.ptr(), "disconnect_nodes", type, from_node, from_port - 1, to_node, to_port); } } } @@ -1177,23 +1312,20 @@ void VisualShaderEditor::_remove_output_port(int p_node, int p_port) { undo_redo->add_do_method(node.ptr(), "remove_output_port", p_port); undo_redo->add_undo_method(node.ptr(), "add_output_port", p_port, (int)node->get_output_port_type(p_port), node->get_output_port_name(p_port)); - undo_redo->add_do_method(this, "_update_graph"); - undo_redo->add_undo_method(this, "_update_graph"); - - undo_redo->add_do_method(this, "_rebuild"); - undo_redo->add_undo_method(this, "_rebuild"); + undo_redo->add_do_method(graph_plugin.ptr(), "update_node", type, p_node); + undo_redo->add_undo_method(graph_plugin.ptr(), "update_node", type, p_node); undo_redo->commit_action(); } -void VisualShaderEditor::_expression_focus_out(Object *text_edit, int p_node) { +void VisualShaderEditor::_expression_focus_out(Object *code_edit, int p_node) { VisualShader::Type type = get_current_shader_type(); Ref<VisualShaderNodeExpression> node = visual_shader->get_node(type, p_node); if (node.is_null()) { return; } - TextEdit *expression_box = Object::cast_to<TextEdit>(text_edit); + CodeEdit *expression_box = Object::cast_to<CodeEdit>(code_edit); if (node->get_expression() == expression_box->get_text()) { return; @@ -1202,18 +1334,9 @@ void VisualShaderEditor::_expression_focus_out(Object *text_edit, int p_node) { undo_redo->create_action(TTR("Set expression")); undo_redo->add_do_method(node.ptr(), "set_expression", expression_box->get_text()); undo_redo->add_undo_method(node.ptr(), "set_expression", node->get_expression()); - undo_redo->add_do_method(this, "_rebuild"); - undo_redo->add_undo_method(this, "_rebuild"); undo_redo->commit_action(); } -void VisualShaderEditor::_rebuild() { - if (visual_shader != nullptr) { - EditorNode::get_singleton()->get_log()->clear(); - visual_shader->rebuild(); - } -} - void VisualShaderEditor::_set_node_size(int p_type, int p_node, const Vector2 &p_size) { VisualShader::Type type = get_current_shader_type(); Ref<VisualShaderNode> node = visual_shader->get_node(type, p_node); @@ -1280,17 +1403,19 @@ void VisualShaderEditor::_preview_select_port(int p_node, int p_port) { if (node.is_null()) { return; } - + int prev_port = node->get_output_port_for_preview(); if (node->get_output_port_for_preview() == p_port) { p_port = -1; //toggle it } undo_redo->create_action(p_port == -1 ? TTR("Hide Port Preview") : TTR("Show Port Preview")); undo_redo->add_do_method(node.ptr(), "set_output_port_for_preview", p_port); - undo_redo->add_undo_method(node.ptr(), "set_output_port_for_preview", node->get_output_port_for_preview()); + undo_redo->add_undo_method(node.ptr(), "set_output_port_for_preview", prev_port); + undo_redo->add_do_method(graph_plugin.ptr(), "show_port_preview", (int)type, p_node, p_port); + undo_redo->add_undo_method(graph_plugin.ptr(), "show_port_preview", (int)type, p_node, prev_port); undo_redo->commit_action(); } -void VisualShaderEditor::_line_edit_changed(const String &p_text, Object *line_edit, int p_node_id) { +void VisualShaderEditor::_uniform_line_edit_changed(const String &p_text, int p_node_id) { VisualShader::Type type = get_current_shader_type(); Ref<VisualShaderNodeUniform> node = visual_shader->get_node(type, p_node_id); @@ -1298,21 +1423,28 @@ void VisualShaderEditor::_line_edit_changed(const String &p_text, Object *line_e String validated_name = visual_shader->validate_uniform_name(p_text, node); - updating = true; + if (validated_name == node->get_uniform_name()) { + return; + } + undo_redo->create_action(TTR("Set Uniform Name")); undo_redo->add_do_method(node.ptr(), "set_uniform_name", validated_name); undo_redo->add_undo_method(node.ptr(), "set_uniform_name", node->get_uniform_name()); - undo_redo->add_do_method(this, "_update_graph"); - undo_redo->add_undo_method(this, "_update_graph"); - undo_redo->commit_action(); - updating = false; + undo_redo->add_do_method(graph_plugin.ptr(), "set_uniform_name", type, p_node_id, validated_name); + undo_redo->add_undo_method(graph_plugin.ptr(), "set_uniform_name", type, p_node_id, node->get_uniform_name()); + + undo_redo->add_do_method(this, "_update_uniforms", true); + undo_redo->add_undo_method(this, "_update_uniforms", true); - Object::cast_to<LineEdit>(line_edit)->set_text(validated_name); + Set<String> changed_names; + changed_names.insert(node->get_uniform_name()); + _update_uniform_refs(changed_names); + + undo_redo->commit_action(); } -void VisualShaderEditor::_line_edit_focus_out(Object *line_edit, int p_node_id) { - String text = Object::cast_to<LineEdit>(line_edit)->get_text(); - _line_edit_changed(text, line_edit, p_node_id); +void VisualShaderEditor::_uniform_line_edit_focus_out(Object *line_edit, int p_node_id) { + _uniform_line_edit_changed(Object::cast_to<LineEdit>(line_edit)->get_text(), p_node_id); } void VisualShaderEditor::_port_name_focus_out(Object *line_edit, int p_node_id, int p_port_id, bool p_output) { @@ -1376,8 +1508,8 @@ void VisualShaderEditor::_port_edited() { undo_redo->create_action(TTR("Set Input Default Port")); undo_redo->add_do_method(vsn.ptr(), "set_input_port_default_value", editing_port, value); undo_redo->add_undo_method(vsn.ptr(), "set_input_port_default_value", editing_port, vsn->get_input_port_default_value(editing_port)); - undo_redo->add_do_method(this, "_update_graph"); - undo_redo->add_undo_method(this, "_update_graph"); + undo_redo->add_do_method(graph_plugin.ptr(), "set_input_port_default_value", type, editing_node, editing_port, value); + undo_redo->add_undo_method(graph_plugin.ptr(), "set_input_port_default_value", type, editing_node, editing_port, vsn->get_input_port_default_value(editing_port)); undo_redo->commit_action(); property_editor->hide(); @@ -1557,6 +1689,8 @@ VisualShaderNode *VisualShaderEditor::_add_node(int p_idx, int p_op_idx) { undo_redo->create_action(TTR("Add Node to Visual Shader")); undo_redo->add_do_method(visual_shader.ptr(), "add_node", type, vsnode, position, id_to_use); undo_redo->add_undo_method(visual_shader.ptr(), "remove_node", type, id_to_use); + undo_redo->add_do_method(graph_plugin.ptr(), "add_node", type, id_to_use); + undo_redo->add_undo_method(graph_plugin.ptr(), "remove_node", type, id_to_use); VisualShaderNodeExpression *expr = Object::cast_to<VisualShaderNodeExpression>(vsnode.ptr()); if (expr) { @@ -1571,6 +1705,8 @@ VisualShaderNode *VisualShaderEditor::_add_node(int p_idx, int p_op_idx) { if (visual_shader->is_port_types_compatible(vsnode->get_output_port_type(_from_slot), visual_shader->get_node(type, to_node)->get_input_port_type(to_slot))) { undo_redo->add_do_method(visual_shader.ptr(), "connect_nodes", type, _from_node, _from_slot, to_node, to_slot); undo_redo->add_undo_method(visual_shader.ptr(), "disconnect_nodes", type, _from_node, _from_slot, to_node, to_slot); + undo_redo->add_do_method(graph_plugin.ptr(), "connect_nodes", type, _from_node, _from_slot, to_node, to_slot); + undo_redo->add_undo_method(graph_plugin.ptr(), "disconnect_nodes", type, _from_node, _from_slot, to_node, to_slot); } } } else if (from_node != -1 && from_slot != -1) { @@ -1579,14 +1715,20 @@ VisualShaderNode *VisualShaderEditor::_add_node(int p_idx, int p_op_idx) { int _to_slot = 0; if (visual_shader->is_port_types_compatible(visual_shader->get_node(type, from_node)->get_output_port_type(from_slot), vsnode->get_input_port_type(_to_slot))) { - undo_redo->add_do_method(visual_shader.ptr(), "connect_nodes", type, from_node, from_slot, _to_node, _to_slot); undo_redo->add_undo_method(visual_shader.ptr(), "disconnect_nodes", type, from_node, from_slot, _to_node, _to_slot); + undo_redo->add_do_method(visual_shader.ptr(), "connect_nodes", type, from_node, from_slot, _to_node, _to_slot); + undo_redo->add_undo_method(graph_plugin.ptr(), "disconnect_nodes", type, from_node, from_slot, _to_node, _to_slot); + undo_redo->add_do_method(graph_plugin.ptr(), "connect_nodes", type, from_node, from_slot, _to_node, _to_slot); } } } - undo_redo->add_do_method(this, "_update_graph"); - undo_redo->add_undo_method(this, "_update_graph"); + VisualShaderNodeUniform *uniform = Object::cast_to<VisualShaderNodeUniform>(vsnode.ptr()); + if (uniform) { + undo_redo->add_do_method(this, "_update_uniforms", true); + undo_redo->add_undo_method(this, "_update_uniforms", true); + } + undo_redo->commit_action(); return vsnode.ptr(); } @@ -1597,6 +1739,8 @@ void VisualShaderEditor::_node_dragged(const Vector2 &p_from, const Vector2 &p_t undo_redo->create_action(TTR("Node Moved")); undo_redo->add_do_method(visual_shader.ptr(), "set_node_position", type, p_node, p_to); undo_redo->add_undo_method(visual_shader.ptr(), "set_node_position", type, p_node, p_from); + undo_redo->add_do_method(graph_plugin.ptr(), "set_node_position", type, p_node, p_to); + undo_redo->add_undo_method(graph_plugin.ptr(), "set_node_position", type, p_node, p_from); undo_redo->commit_action(); } @@ -1619,13 +1763,15 @@ void VisualShaderEditor::_connection_request(const String &p_from, int p_from_in if (E->get().to_node == to && E->get().to_port == p_to_index) { undo_redo->add_do_method(visual_shader.ptr(), "disconnect_nodes", type, E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port); undo_redo->add_undo_method(visual_shader.ptr(), "connect_nodes", type, E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port); + undo_redo->add_do_method(graph_plugin.ptr(), "disconnect_nodes", type, E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port); + undo_redo->add_undo_method(graph_plugin.ptr(), "connect_nodes", type, E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port); } } undo_redo->add_do_method(visual_shader.ptr(), "connect_nodes", type, from, p_from_index, to, p_to_index); undo_redo->add_undo_method(visual_shader.ptr(), "disconnect_nodes", type, from, p_from_index, to, p_to_index); - undo_redo->add_do_method(this, "_update_graph"); - undo_redo->add_undo_method(this, "_update_graph"); + undo_redo->add_do_method(graph_plugin.ptr(), "connect_nodes", type, from, p_from_index, to, p_to_index); + undo_redo->add_undo_method(graph_plugin.ptr(), "disconnect_nodes", type, from, p_from_index, to, p_to_index); undo_redo->commit_action(); } @@ -1637,14 +1783,12 @@ void VisualShaderEditor::_disconnection_request(const String &p_from, int p_from int from = p_from.to_int(); int to = p_to.to_int(); - //updating = true; seems graph edit can handle this, no need to protect undo_redo->create_action(TTR("Nodes Disconnected")); undo_redo->add_do_method(visual_shader.ptr(), "disconnect_nodes", type, from, p_from_index, to, p_to_index); undo_redo->add_undo_method(visual_shader.ptr(), "connect_nodes", type, from, p_from_index, to, p_to_index); - undo_redo->add_do_method(this, "_update_graph"); - undo_redo->add_undo_method(this, "_update_graph"); + undo_redo->add_do_method(graph_plugin.ptr(), "disconnect_nodes", type, from, p_from_index, to, p_to_index); + undo_redo->add_undo_method(graph_plugin.ptr(), "connect_nodes", type, from, p_from_index, to, p_to_index); undo_redo->commit_action(); - //updating = false; } void VisualShaderEditor::_connection_to_empty(const String &p_from, int p_from_slot, const Vector2 &p_release_position) { @@ -1664,8 +1808,18 @@ void VisualShaderEditor::_delete_request(int which) { Ref<VisualShaderNode> node = Ref<VisualShaderNode>(visual_shader->get_node(type, which)); undo_redo->create_action(TTR("Delete Node")); + + List<VisualShader::Connection> conns; + visual_shader->get_node_connections(type, &conns); + for (List<VisualShader::Connection>::Element *E = conns.front(); E; E = E->next()) { + if (E->get().from_node == which || E->get().to_node == which) { + undo_redo->add_do_method(graph_plugin.ptr(), "disconnect_nodes", type, E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port); + } + } + undo_redo->add_do_method(visual_shader.ptr(), "remove_node", type, which); undo_redo->add_undo_method(visual_shader.ptr(), "add_node", type, node, visual_shader->get_node_position(type, which), which); + undo_redo->add_undo_method(graph_plugin.ptr(), "add_node", type, which); undo_redo->add_do_method(this, "_clear_buffer"); undo_redo->add_undo_method(this, "_clear_buffer"); @@ -1684,17 +1838,26 @@ void VisualShaderEditor::_delete_request(int which) { undo_redo->add_undo_method(expression, "set_expression", expression->get_expression()); } - List<VisualShader::Connection> conns; - visual_shader->get_node_connections(type, &conns); - for (List<VisualShader::Connection>::Element *E = conns.front(); E; E = E->next()) { if (E->get().from_node == which || E->get().to_node == which) { undo_redo->add_undo_method(visual_shader.ptr(), "connect_nodes", type, E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port); + undo_redo->add_undo_method(graph_plugin.ptr(), "connect_nodes", type, E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port); } } + // delete a node from the graph + undo_redo->add_do_method(graph_plugin.ptr(), "remove_node", type, which); + + VisualShaderNodeUniform *uniform = Object::cast_to<VisualShaderNodeUniform>(node.ptr()); + if (uniform) { + undo_redo->add_do_method(this, "_update_uniforms", true); + undo_redo->add_undo_method(this, "_update_uniforms", true); + + Set<String> uniform_names; + uniform_names.insert(uniform->get_uniform_name()); + + _update_uniform_refs(uniform_names); + } - undo_redo->add_do_method(this, "_update_graph"); - undo_redo->add_undo_method(this, "_update_graph"); undo_redo->commit_action(); } @@ -1953,12 +2116,13 @@ void VisualShaderEditor::_dup_paste_nodes(int p_type, int p_pasted_type, List<in Ref<VisualShaderNode> dupli = node->duplicate(); undo_redo->add_do_method(visual_shader.ptr(), "add_node", type, dupli, visual_shader->get_node_position(pasted_type, E->get()) + p_offset, id_from); - undo_redo->add_undo_method(visual_shader.ptr(), "remove_node", type, id_from); + undo_redo->add_do_method(graph_plugin.ptr(), "add_node", type, id_from); // duplicate size, inputs and outputs if node is group Ref<VisualShaderNodeGroupBase> group = Object::cast_to<VisualShaderNodeGroupBase>(node.ptr()); if (!group.is_null()) { undo_redo->add_do_method(dupli.ptr(), "set_size", group->get_size()); + undo_redo->add_do_method(graph_plugin.ptr(), "set_node_size", type, id_from, group->get_size()); undo_redo->add_do_method(dupli.ptr(), "set_inputs", group->get_inputs()); undo_redo->add_do_method(dupli.ptr(), "set_outputs", group->get_outputs()); } @@ -1979,12 +2143,19 @@ void VisualShaderEditor::_dup_paste_nodes(int p_type, int p_pasted_type, List<in continue; } if (connection_remap.has(E->get().from_node) && connection_remap.has(E->get().to_node)) { - undo_redo->add_do_method(visual_shader.ptr(), "connect_nodes_forced", type, connection_remap[E->get().from_node], E->get().from_port, connection_remap[E->get().to_node], E->get().to_port); + undo_redo->add_do_method(visual_shader.ptr(), "connect_nodes", type, connection_remap[E->get().from_node], E->get().from_port, connection_remap[E->get().to_node], E->get().to_port); + undo_redo->add_do_method(graph_plugin.ptr(), "connect_nodes", type, connection_remap[E->get().from_node], E->get().from_port, connection_remap[E->get().to_node], E->get().to_port); + undo_redo->add_undo_method(graph_plugin.ptr(), "disconnect_nodes", type, connection_remap[E->get().from_node], E->get().from_port, connection_remap[E->get().to_node], E->get().to_port); } } - undo_redo->add_do_method(this, "_update_graph"); - undo_redo->add_undo_method(this, "_update_graph"); + id_from = base_id; + for (List<int>::Element *E = r_nodes.front(); E; E = E->next()) { + undo_redo->add_undo_method(visual_shader.ptr(), "remove_node", type, id_from); + undo_redo->add_undo_method(graph_plugin.ptr(), "remove_node", type, id_from); + id_from++; + } + undo_redo->commit_action(); if (p_select) { @@ -2075,11 +2246,25 @@ void VisualShaderEditor::_delete_nodes() { undo_redo->create_action(TTR("Delete Nodes")); + List<VisualShader::Connection> conns; + visual_shader->get_node_connections(type, &conns); + + for (List<int>::Element *F = to_erase.front(); F; F = F->next()) { + for (List<VisualShader::Connection>::Element *E = conns.front(); E; E = E->next()) { + if (E->get().from_node == F->get() || E->get().to_node == F->get()) { + undo_redo->add_do_method(graph_plugin.ptr(), "disconnect_nodes", type, E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port); + } + } + } + + Set<String> uniform_names; + for (List<int>::Element *F = to_erase.front(); F; F = F->next()) { Ref<VisualShaderNode> node = visual_shader->get_node(type, F->get()); undo_redo->add_do_method(visual_shader.ptr(), "remove_node", type, F->get()); undo_redo->add_undo_method(visual_shader.ptr(), "add_node", type, node, visual_shader->get_node_position(type, F->get()), F->get()); + undo_redo->add_undo_method(graph_plugin.ptr(), "add_node", type, F->get()); undo_redo->add_do_method(this, "_clear_buffer"); undo_redo->add_undo_method(this, "_clear_buffer"); @@ -2097,10 +2282,12 @@ void VisualShaderEditor::_delete_nodes() { if (expression) { undo_redo->add_undo_method(expression, "set_expression", expression->get_expression()); } - } - List<VisualShader::Connection> conns; - visual_shader->get_node_connections(type, &conns); + VisualShaderNodeUniform *uniform = Object::cast_to<VisualShaderNodeUniform>(node.ptr()); + if (uniform) { + uniform_names.insert(uniform->get_uniform_name()); + } + } List<VisualShader::Connection> used_conns; for (List<int>::Element *F = to_erase.front(); F; F = F->next()) { @@ -2115,54 +2302,78 @@ void VisualShaderEditor::_delete_nodes() { } if (!cancel) { undo_redo->add_undo_method(visual_shader.ptr(), "connect_nodes", type, E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port); + undo_redo->add_undo_method(graph_plugin.ptr(), "connect_nodes", type, E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port); used_conns.push_back(E->get()); } } } } - undo_redo->add_do_method(this, "_update_graph"); - undo_redo->add_undo_method(this, "_update_graph"); + // delete nodes from the graph + for (List<int>::Element *F = to_erase.front(); F; F = F->next()) { + undo_redo->add_do_method(graph_plugin.ptr(), "remove_node", type, F->get()); + } + + // update uniform refs if any uniform has been deleted + if (uniform_names.size() > 0) { + undo_redo->add_do_method(this, "_update_uniforms", true); + undo_redo->add_undo_method(this, "_update_uniforms", true); + + _update_uniform_refs(uniform_names); + } + undo_redo->commit_action(); } void VisualShaderEditor::_mode_selected(int p_id) { - visual_shader->set_shader_type(VisualShader::Type(p_id)); + visual_shader->set_shader_type(particles_mode ? VisualShader::Type(p_id + 3) : VisualShader::Type(p_id)); _update_options_menu(); _update_graph(); } -void VisualShaderEditor::_input_select_item(Ref<VisualShaderNodeInput> input, String name) { - String prev_name = input->get_input_name(); +void VisualShaderEditor::_input_select_item(Ref<VisualShaderNodeInput> p_input, String p_name) { + String prev_name = p_input->get_input_name(); - if (name == prev_name) { + if (p_name == prev_name) { return; } - bool type_changed = input->get_input_type_by_name(name) != input->get_input_type_by_name(prev_name); + bool type_changed = p_input->get_input_type_by_name(p_name) != p_input->get_input_type_by_name(prev_name); UndoRedo *undo_redo = EditorNode::get_singleton()->get_undo_redo(); undo_redo->create_action(TTR("Visual Shader Input Type Changed")); - undo_redo->add_do_method(input.ptr(), "set_input_name", name); - undo_redo->add_undo_method(input.ptr(), "set_input_name", prev_name); - - if (type_changed) { - //restore connections if type changed - VisualShader::Type type = get_current_shader_type(); - int id = visual_shader->find_node_id(type, input); - List<VisualShader::Connection> conns; - visual_shader->get_node_connections(type, &conns); - for (List<VisualShader::Connection>::Element *E = conns.front(); E; E = E->next()) { - if (E->get().from_node == id) { - undo_redo->add_undo_method(visual_shader.ptr(), "connect_nodes", type, E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port); + undo_redo->add_do_method(p_input.ptr(), "set_input_name", p_name); + undo_redo->add_undo_method(p_input.ptr(), "set_input_name", prev_name); + + // update output port + for (int type_id = 0; type_id < VisualShader::TYPE_MAX; type_id++) { + VisualShader::Type type = VisualShader::Type(type_id); + int id = visual_shader->find_node_id(type, p_input); + if (id != VisualShader::NODE_ID_INVALID) { + if (type_changed) { + List<VisualShader::Connection> conns; + visual_shader->get_node_connections(type, &conns); + for (List<VisualShader::Connection>::Element *E = conns.front(); E; E = E->next()) { + if (E->get().from_node == id) { + if (visual_shader->is_port_types_compatible(p_input->get_input_type_by_name(p_name), visual_shader->get_node(type, E->get().to_node)->get_input_port_type(E->get().to_port))) { + undo_redo->add_do_method(visual_shader.ptr(), "connect_nodes", type, E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port); + undo_redo->add_undo_method(visual_shader.ptr(), "connect_nodes", type, E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port); + continue; + } + undo_redo->add_do_method(visual_shader.ptr(), "disconnect_nodes", type, E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port); + undo_redo->add_undo_method(visual_shader.ptr(), "connect_nodes", type, E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port); + undo_redo->add_do_method(graph_plugin.ptr(), "disconnect_nodes", type, E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port); + undo_redo->add_undo_method(graph_plugin.ptr(), "connect_nodes", type, E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port); + } + } } + undo_redo->add_do_method(graph_plugin.ptr(), "update_node", type_id, id); + undo_redo->add_undo_method(graph_plugin.ptr(), "update_node", type_id, id); + break; } } - undo_redo->add_do_method(VisualShaderEditor::get_singleton(), "_update_graph"); - undo_redo->add_undo_method(VisualShaderEditor::get_singleton(), "_update_graph"); - undo_redo->commit_action(); } @@ -2181,23 +2392,32 @@ void VisualShaderEditor::_uniform_select_item(Ref<VisualShaderNodeUniformRef> p_ undo_redo->add_do_method(p_uniform_ref.ptr(), "set_uniform_name", p_name); undo_redo->add_undo_method(p_uniform_ref.ptr(), "set_uniform_name", prev_name); - if (type_changed) { - //restore connections if type changed - VisualShader::Type type = get_current_shader_type(); + // update output port + for (int type_id = 0; type_id < VisualShader::TYPE_MAX; type_id++) { + VisualShader::Type type = VisualShader::Type(type_id); int id = visual_shader->find_node_id(type, p_uniform_ref); - List<VisualShader::Connection> conns; - visual_shader->get_node_connections(type, &conns); - for (List<VisualShader::Connection>::Element *E = conns.front(); E; E = E->next()) { - if (E->get().from_node == id) { - undo_redo->add_do_method(visual_shader.ptr(), "disconnect_nodes", type, E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port); - undo_redo->add_undo_method(visual_shader.ptr(), "connect_nodes", type, E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port); + if (id != VisualShader::NODE_ID_INVALID) { + if (type_changed) { + List<VisualShader::Connection> conns; + visual_shader->get_node_connections(type, &conns); + for (List<VisualShader::Connection>::Element *E = conns.front(); E; E = E->next()) { + if (E->get().from_node == id) { + if (visual_shader->is_port_types_compatible(p_uniform_ref->get_uniform_type_by_name(p_name), visual_shader->get_node(type, E->get().to_node)->get_input_port_type(E->get().to_port))) { + continue; + } + undo_redo->add_do_method(visual_shader.ptr(), "disconnect_nodes", type, E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port); + undo_redo->add_undo_method(visual_shader.ptr(), "connect_nodes", type, E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port); + undo_redo->add_do_method(graph_plugin.ptr(), "disconnect_nodes", type, E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port); + undo_redo->add_undo_method(graph_plugin.ptr(), "connect_nodes", type, E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port); + } + } } + undo_redo->add_do_method(graph_plugin.ptr(), "update_node", type_id, id); + undo_redo->add_undo_method(graph_plugin.ptr(), "update_node", type_id, id); + break; } } - undo_redo->add_do_method(VisualShaderEditor::get_singleton(), "_update_graph"); - undo_redo->add_undo_method(VisualShaderEditor::get_singleton(), "_update_graph"); - undo_redo->commit_action(); } @@ -2420,7 +2640,6 @@ void VisualShaderEditor::_update_preview() { } void VisualShaderEditor::_bind_methods() { - ClassDB::bind_method("_rebuild", &VisualShaderEditor::_rebuild); ClassDB::bind_method("_update_graph", &VisualShaderEditor::_update_graph); ClassDB::bind_method("_update_options_menu", &VisualShaderEditor::_update_options_menu); ClassDB::bind_method("_add_node", &VisualShaderEditor::_add_node); @@ -2429,6 +2648,8 @@ void VisualShaderEditor::_bind_methods() { ClassDB::bind_method("_uniform_select_item", &VisualShaderEditor::_uniform_select_item); ClassDB::bind_method("_set_node_size", &VisualShaderEditor::_set_node_size); ClassDB::bind_method("_clear_buffer", &VisualShaderEditor::_clear_buffer); + ClassDB::bind_method("_update_uniforms", &VisualShaderEditor::_update_uniforms); + ClassDB::bind_method("_set_mode", &VisualShaderEditor::_set_mode); ClassDB::bind_method(D_METHOD("get_drag_data_fw"), &VisualShaderEditor::get_drag_data_fw); ClassDB::bind_method(D_METHOD("can_drop_data_fw"), &VisualShaderEditor::can_drop_data_fw); @@ -2550,14 +2771,14 @@ VisualShaderEditor::VisualShaderEditor() { preview_vbox = memnew(VBoxContainer); preview_vbox->set_visible(preview_showed); main_box->add_child(preview_vbox); - preview_text = memnew(TextEdit); + preview_text = memnew(CodeEdit); syntax_highlighter.instance(); preview_vbox->add_child(preview_text); preview_text->set_h_size_flags(SIZE_EXPAND_FILL); preview_text->set_v_size_flags(SIZE_EXPAND_FILL); preview_text->set_custom_minimum_size(Size2(400 * EDSCALE, 0)); preview_text->set_syntax_highlighter(syntax_highlighter); - preview_text->set_show_line_numbers(true); + preview_text->set_draw_line_numbers(true); preview_text->set_readonly(true); error_text = memnew(Label); @@ -2974,12 +3195,15 @@ VisualShaderEditor::VisualShaderEditor() { add_options.push_back(AddOption("CubeMap", "Textures", "Functions", "VisualShaderNodeCubemap", TTR("Perform the cubic texture lookup."), -1, -1)); texture_node_option_idx = add_options.size(); - add_options.push_back(AddOption("Texture2D", "Textures", "Functions", "VisualShaderNodeTexture", TTR("Perform the texture lookup."), -1, -1)); - add_options.push_back(AddOption("CubeMapUniform", "Textures", "Variables", "VisualShaderNodeCubemapUniform", TTR("Cubic texture uniform lookup."), -1, -1)); + add_options.push_back(AddOption("Texture2D", "Textures", "Functions", "VisualShaderNodeTexture", TTR("Perform the 2D texture lookup."), -1, -1)); add_options.push_back(AddOption("Texture2DArray", "Textures", "Functions", "VisualShaderNodeTexture2DArray", TTR("Perform the 2D-array texture lookup."), -1, -1, -1, -1, -1)); + add_options.push_back(AddOption("Texture3D", "Textures", "Functions", "VisualShaderNodeTexture3D", TTR("Perform the 3D texture lookup."), -1, -1)); + + add_options.push_back(AddOption("CubeMapUniform", "Textures", "Variables", "VisualShaderNodeCubemapUniform", TTR("Cubic texture uniform lookup."), -1, -1)); add_options.push_back(AddOption("TextureUniform", "Textures", "Variables", "VisualShaderNodeTextureUniform", TTR("2D texture uniform lookup."), -1, -1)); add_options.push_back(AddOption("TextureUniformTriplanar", "Textures", "Variables", "VisualShaderNodeTextureUniformTriplanar", TTR("2D texture uniform lookup with triplanar."), -1, -1, TYPE_FLAGS_FRAGMENT | TYPE_FLAGS_LIGHT, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("Texture2DArrayUniform", "Textures", "Variables", "VisualShaderNodeTexture2DArrayUniform", TTR("2D array of textures uniform lookup."), -1, -1, -1, -1, -1)); + add_options.push_back(AddOption("Texture3DUniform", "Textures", "Variables", "VisualShaderNodeTexture3DUniform", TTR("3D texture uniform lookup."), -1, -1, -1, -1, -1)); // TRANSFORM @@ -3248,6 +3472,8 @@ public: class VisualShaderNodePluginDefaultEditor : public VBoxContainer { GDCLASS(VisualShaderNodePluginDefaultEditor, VBoxContainer); Ref<Resource> parent_resource; + int node_id; + VisualShader::Type shader_type; public: void _property_changed(const String &p_property, const Variant &p_value, const String &p_field = "", bool p_changing = false) { @@ -3276,8 +3502,10 @@ public: } else { undo_redo->add_undo_method(this, "_open_inspector", (RES)parent_resource.ptr()); } - undo_redo->add_do_method(this, "_refresh_request"); - undo_redo->add_undo_method(this, "_refresh_request"); + } + if (p_property != "constant") { + undo_redo->add_do_method(VisualShaderEditor::get_singleton()->get_graph_plugin(), "update_node_deferred", shader_type, node_id); + undo_redo->add_undo_method(VisualShaderEditor::get_singleton()->get_graph_plugin(), "update_node_deferred", shader_type, node_id); } undo_redo->commit_action(); @@ -3293,10 +3521,6 @@ public: } } - void _refresh_request() { - VisualShaderEditor::get_singleton()->call_deferred("_update_graph"); - } - void _resource_selected(const String &p_path, RES p_resource) { _open_inspector(p_resource); } @@ -3322,6 +3546,9 @@ public: node = p_node; properties = p_properties; + node_id = (int)p_node->get_meta("id"); + shader_type = VisualShader::Type((int)p_node->get_meta("shader_type")); + for (int i = 0; i < p_properties.size(); i++) { HBoxContainer *hbox = memnew(HBoxContainer); hbox->set_h_size_flags(SIZE_EXPAND_FILL); @@ -3349,11 +3576,9 @@ public: properties[i]->set_name_split_ratio(0); } node->connect("changed", callable_mp(this, &VisualShaderNodePluginDefaultEditor::_node_changed)); - node->connect("editor_refresh_request", callable_mp(this, &VisualShaderNodePluginDefaultEditor::_refresh_request), varray(), CONNECT_DEFERRED); } static void _bind_methods() { - ClassDB::bind_method("_refresh_request", &VisualShaderNodePluginDefaultEditor::_refresh_request); // Used by UndoRedo. ClassDB::bind_method("_open_inspector", &VisualShaderNodePluginDefaultEditor::_open_inspector); // Used by UndoRedo. ClassDB::bind_method("_show_prop_names", &VisualShaderNodePluginDefaultEditor::_show_prop_names); // Used with call_deferred. } @@ -3442,6 +3667,10 @@ void EditorPropertyShaderMode::_option_selected(int p_which) { //do is easy undo_redo->add_do_method(visual_shader.ptr(), "set_mode", p_which); undo_redo->add_undo_method(visual_shader.ptr(), "set_mode", visual_shader->get_mode()); + + undo_redo->add_do_method(VisualShaderEditor::get_singleton(), "_set_mode", p_which); + undo_redo->add_undo_method(VisualShaderEditor::get_singleton(), "_set_mode", visual_shader->get_mode()); + //now undo is hell //1. restore connections to output diff --git a/editor/plugins/visual_shader_editor_plugin.h b/editor/plugins/visual_shader_editor_plugin.h index 59d4765ec9..531a117156 100644 --- a/editor/plugins/visual_shader_editor_plugin.h +++ b/editor/plugins/visual_shader_editor_plugin.h @@ -54,6 +54,10 @@ class VisualShaderGraphPlugin : public Reference { GDCLASS(VisualShaderGraphPlugin, Reference); private: + struct InputPort { + Button *default_input_button; + }; + struct Port { TextureButton *preview_button; }; @@ -64,12 +68,15 @@ private: GraphNode *graph_node; bool preview_visible; int preview_pos; + Map<int, InputPort> input_ports; Map<int, Port> output_ports; VBoxContainer *preview_box; + LineEdit *uniform_name; }; Ref<VisualShader> visual_shader; Map<int, Link> links; + List<VisualShader::Connection> connections; bool dirty = false; protected: @@ -77,15 +84,30 @@ protected: public: void register_shader(VisualShader *p_visual_shader); + void set_connections(List<VisualShader::Connection> &p_connections); void register_link(VisualShader::Type p_type, int p_id, VisualShaderNode *p_visual_node, GraphNode *p_graph_node); void register_output_port(int p_id, int p_port, TextureButton *p_button); + void register_uniform_name(int p_id, LineEdit *p_uniform_name); void clear_links(); void set_shader_type(VisualShader::Type p_type); bool is_preview_visible(int p_id) const; bool is_dirty() const; void make_dirty(bool p_enabled); - - void show_port_preview(int p_node_id, int p_port_id); + void update_node(VisualShader::Type p_type, int p_id); + void update_node_deferred(VisualShader::Type p_type, int p_node_id); + void add_node(VisualShader::Type p_type, int p_id); + void remove_node(VisualShader::Type p_type, int p_id); + void connect_nodes(VisualShader::Type p_type, int p_from_node, int p_from_port, int p_to_node, int p_to_port); + void disconnect_nodes(VisualShader::Type p_type, int p_from_node, int p_from_port, int p_to_node, int p_to_port); + void show_port_preview(VisualShader::Type p_type, int p_node_id, int p_port_id); + void set_node_position(VisualShader::Type p_type, int p_id, const Vector2 &p_position); + void set_node_size(VisualShader::Type p_type, int p_id, const Vector2 &p_size); + void refresh_node_ports(VisualShader::Type p_type, int p_node); + void set_input_port_default_value(VisualShader::Type p_type, int p_node_id, int p_port_id, Variant p_value); + void register_default_input_button(int p_node_id, int p_port_id, Button *p_button); + void update_uniform_refs(); + void set_uniform_name(VisualShader::Type p_type, int p_node_id, const String &p_name); + VisualShader::Type get_shader_type() const; VisualShaderGraphPlugin(); ~VisualShaderGraphPlugin(); @@ -115,7 +137,7 @@ class VisualShaderEditor : public VBoxContainer { bool pending_update_preview; bool shader_error; VBoxContainer *preview_vbox; - TextEdit *preview_text; + CodeEdit *preview_text; Ref<CodeHighlighter> syntax_highlighter; Label *error_text; @@ -223,12 +245,15 @@ class VisualShaderEditor : public VBoxContainer { int custom_node_option_idx; List<String> keyword_list; + List<VisualShaderNodeUniformRef> uniform_refs; + void _draw_color_over_button(Object *obj, Color p_color); void _add_custom_node(const String &p_path); void _add_texture_node(const String &p_path); VisualShaderNode *_add_node(int p_idx, int p_op_idx = -1); void _update_options_menu(); + void _set_mode(int p_which); void _show_preview_text(); void _update_preview(); @@ -263,8 +288,8 @@ class VisualShaderEditor : public VBoxContainer { void _connection_to_empty(const String &p_from, int p_from_slot, const Vector2 &p_release_position); void _connection_from_empty(const String &p_to, int p_to_slot, const Vector2 &p_release_position); - void _line_edit_changed(const String &p_text, Object *line_edit, int p_node_id); - void _line_edit_focus_out(Object *line_edit, int p_node_id); + void _uniform_line_edit_changed(const String &p_text, int p_node_id); + void _uniform_line_edit_focus_out(Object *line_edit, int p_node_id); void _port_name_focus_out(Object *line_edit, int p_node_id, int p_port_id, bool p_output); @@ -287,7 +312,6 @@ class VisualShaderEditor : public VBoxContainer { Ref<VisualShaderGraphPlugin> graph_plugin; void _mode_selected(int p_id); - void _rebuild(); void _input_select_item(Ref<VisualShaderNodeInput> input, String name); void _uniform_select_item(Ref<VisualShaderNodeUniformRef> p_uniform, String p_name); @@ -304,7 +328,7 @@ class VisualShaderEditor : public VBoxContainer { void _change_output_port_type(int p_type, int p_node, int p_port); void _change_output_port_name(const String &p_text, Object *line_edit, int p_node, int p_port); - void _expression_focus_out(Object *text_edit, int p_node); + void _expression_focus_out(Object *code_edit, int p_node); void _set_node_size(int p_type, int p_node, const Size2 &p_size); void _node_resized(const Vector2 &p_new_size, int p_type, int p_node); @@ -328,6 +352,8 @@ class VisualShaderEditor : public VBoxContainer { bool _is_available(int p_mode); void _update_created_node(GraphNode *node); + void _update_uniforms(bool p_update_refs); + void _update_uniform_refs(Set<String> &p_names); protected: void _notification(int p_what); @@ -339,6 +365,7 @@ public: void remove_plugin(const Ref<VisualShaderNodePlugin> &p_plugin); static VisualShaderEditor *get_singleton() { return singleton; } + VisualShaderGraphPlugin *get_graph_plugin() { return graph_plugin.ptr(); } void clear_custom_types(); void add_custom_type(const String &p_name, const Ref<Script> &p_script, const String &p_description, int p_return_icon_type, const String &p_category, bool p_highend); diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp index ce869feddd..d9c95b1944 100644 --- a/editor/scene_tree_dock.cpp +++ b/editor/scene_tree_dock.cpp @@ -1115,7 +1115,7 @@ void SceneTreeDock::_notification(int p_what) { beginner_node_shortcuts->set_name("BeginnerNodeShortcuts"); node_shortcuts->add_child(beginner_node_shortcuts); - Button *button_2d = memnew(Button); + button_2d = memnew(Button); beginner_node_shortcuts->add_child(button_2d); button_2d->set_text(TTR("2D Scene")); button_2d->set_icon(get_theme_icon("Node2D", "EditorIcons")); @@ -1127,7 +1127,7 @@ void SceneTreeDock::_notification(int p_what) { button_3d->set_icon(get_theme_icon("Node3D", "EditorIcons")); button_3d->connect("pressed", callable_mp(this, &SceneTreeDock::_tool_selected), make_binds(TOOL_CREATE_3D_SCENE, false)); - Button *button_ui = memnew(Button); + button_ui = memnew(Button); beginner_node_shortcuts->add_child(button_ui); button_ui->set_text(TTR("User Interface")); button_ui->set_icon(get_theme_icon("Control", "EditorIcons")); @@ -1137,7 +1137,7 @@ void SceneTreeDock::_notification(int p_what) { favorite_node_shortcuts->set_name("FavoriteNodeShortcuts"); node_shortcuts->add_child(favorite_node_shortcuts); - Button *button_custom = memnew(Button); + button_custom = memnew(Button); node_shortcuts->add_child(button_custom); button_custom->set_text(TTR("Other Node")); button_custom->set_icon(get_theme_icon("Add", "EditorIcons")); @@ -1160,6 +1160,10 @@ void SceneTreeDock::_notification(int p_what) { button_instance->set_icon(get_theme_icon("Instance", "EditorIcons")); button_create_script->set_icon(get_theme_icon("ScriptCreate", "EditorIcons")); button_detach_script->set_icon(get_theme_icon("ScriptRemove", "EditorIcons")); + button_2d->set_icon(get_theme_icon("Node2D", "EditorIcons")); + button_3d->set_icon(get_theme_icon("Node3D", "EditorIcons")); + button_ui->set_icon(get_theme_icon("Control", "EditorIcons")); + button_custom->set_icon(get_theme_icon("Add", "EditorIcons")); filter->set_right_icon(get_theme_icon("Search", "EditorIcons")); filter->set_clear_button_enabled(true); diff --git a/editor/scene_tree_dock.h b/editor/scene_tree_dock.h index 150c1976ef..c2c877bf68 100644 --- a/editor/scene_tree_dock.h +++ b/editor/scene_tree_dock.h @@ -110,7 +110,10 @@ class SceneTreeDock : public VBoxContainer { Button *button_create_script; Button *button_detach_script; + Button *button_2d; Button *button_3d; + Button *button_ui; + Button *button_custom; HBoxContainer *button_hb; Button *edit_local, *edit_remote; diff --git a/editor/scene_tree_editor.cpp b/editor/scene_tree_editor.cpp index a62448169d..5a504da397 100644 --- a/editor/scene_tree_editor.cpp +++ b/editor/scene_tree_editor.cpp @@ -777,6 +777,9 @@ void SceneTreeEditor::_renamed() { return; } + // Trim leading/trailing whitespace to prevent node names from containing accidental whitespace, which would make it more difficult to get the node via `get_node()`. + new_name = new_name.strip_edges(); + if (!undo_redo) { n->set_name(new_name); which->set_metadata(0, n->get_path()); diff --git a/editor/translations/extract.py b/editor/translations/extract.py index 0dafd20eed..93124ec30c 100755 --- a/editor/translations/extract.py +++ b/editor/translations/extract.py @@ -70,7 +70,6 @@ def _write_message(msgctx, msg, msg_plural, location): def _add_additional_location(msgctx, msg, location): global main_po # Add additional location to previous occurrence. - msg_pos = -1 if msgctx != "": msg_pos = main_po.find('\nmsgctxt "' + msgctx + '"\nmsgid "' + msg + '"') else: @@ -86,7 +85,6 @@ def _write_translator_comment(msgctx, msg, translator_comment): return global main_po - msg_pos = -1 if msgctx != "": msg_pos = main_po.find('\nmsgctxt "' + msgctx + '"\nmsgid "' + msg + '"') else: |