1/**************************************************************************/
2/* text_shader_editor.h */
3/**************************************************************************/
4/* This file is part of: */
5/* GODOT ENGINE */
6/* https://godotengine.org */
7/**************************************************************************/
8/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
9/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
10/* */
11/* Permission is hereby granted, free of charge, to any person obtaining */
12/* a copy of this software and associated documentation files (the */
13/* "Software"), to deal in the Software without restriction, including */
14/* without limitation the rights to use, copy, modify, merge, publish, */
15/* distribute, sublicense, and/or sell copies of the Software, and to */
16/* permit persons to whom the Software is furnished to do so, subject to */
17/* the following conditions: */
18/* */
19/* The above copyright notice and this permission notice shall be */
20/* included in all copies or substantial portions of the Software. */
21/* */
22/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
25/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29/**************************************************************************/
30
31#ifndef TEXT_SHADER_EDITOR_H
32#define TEXT_SHADER_EDITOR_H
33
34#include "editor/code_editor.h"
35#include "scene/gui/menu_button.h"
36#include "scene/gui/panel_container.h"
37#include "scene/gui/rich_text_label.h"
38#include "servers/rendering/shader_warnings.h"
39
40class GDShaderSyntaxHighlighter : public CodeHighlighter {
41 GDCLASS(GDShaderSyntaxHighlighter, CodeHighlighter)
42
43private:
44 Vector<Point2i> disabled_branch_regions;
45 Color disabled_branch_color;
46
47public:
48 virtual Dictionary _get_line_syntax_highlighting_impl(int p_line) override;
49
50 void add_disabled_branch_region(const Point2i &p_region);
51 void clear_disabled_branch_regions();
52 void set_disabled_branch_color(const Color &p_color);
53};
54
55class ShaderTextEditor : public CodeTextEditor {
56 GDCLASS(ShaderTextEditor, CodeTextEditor);
57
58 Color marked_line_color = Color(1, 1, 1);
59
60 struct WarningsComparator {
61 _ALWAYS_INLINE_ bool operator()(const ShaderWarning &p_a, const ShaderWarning &p_b) const { return (p_a.get_line() < p_b.get_line()); }
62 };
63
64 Ref<GDShaderSyntaxHighlighter> syntax_highlighter;
65 RichTextLabel *warnings_panel = nullptr;
66 Ref<Shader> shader;
67 Ref<ShaderInclude> shader_inc;
68 List<ShaderWarning> warnings;
69 Error last_compile_result = Error::OK;
70
71 void _check_shader_mode();
72 void _update_warning_panel();
73
74 bool block_shader_changed = false;
75 void _shader_changed();
76
77 uint32_t dependencies_version = 0; // Incremented if deps changed
78
79protected:
80 void _notification(int p_what);
81 static void _bind_methods();
82 virtual void _load_theme_settings() override;
83
84 virtual void _code_complete_script(const String &p_code, List<ScriptLanguage::CodeCompletionOption> *r_options) override;
85
86public:
87 void set_block_shader_changed(bool p_block) { block_shader_changed = p_block; }
88 uint32_t get_dependencies_version() const { return dependencies_version; }
89
90 virtual void _validate_script() override;
91
92 void reload_text();
93 void set_warnings_panel(RichTextLabel *p_warnings_panel);
94
95 Ref<Shader> get_edited_shader() const;
96 Ref<ShaderInclude> get_edited_shader_include() const;
97
98 void set_edited_shader(const Ref<Shader> &p_shader);
99 void set_edited_shader(const Ref<Shader> &p_shader, const String &p_code);
100 void set_edited_shader_include(const Ref<ShaderInclude> &p_include);
101 void set_edited_shader_include(const Ref<ShaderInclude> &p_include, const String &p_code);
102 void set_edited_code(const String &p_code);
103
104 ShaderTextEditor();
105};
106
107class TextShaderEditor : public MarginContainer {
108 GDCLASS(TextShaderEditor, MarginContainer);
109
110 enum {
111 EDIT_UNDO,
112 EDIT_REDO,
113 EDIT_CUT,
114 EDIT_COPY,
115 EDIT_PASTE,
116 EDIT_SELECT_ALL,
117 EDIT_MOVE_LINE_UP,
118 EDIT_MOVE_LINE_DOWN,
119 EDIT_INDENT,
120 EDIT_UNINDENT,
121 EDIT_DELETE_LINE,
122 EDIT_DUPLICATE_SELECTION,
123 EDIT_TOGGLE_WORD_WRAP,
124 EDIT_TOGGLE_COMMENT,
125 EDIT_COMPLETE,
126 SEARCH_FIND,
127 SEARCH_FIND_NEXT,
128 SEARCH_FIND_PREV,
129 SEARCH_REPLACE,
130 SEARCH_GOTO_LINE,
131 BOOKMARK_TOGGLE,
132 BOOKMARK_GOTO_NEXT,
133 BOOKMARK_GOTO_PREV,
134 BOOKMARK_REMOVE_ALL,
135 HELP_DOCS,
136 };
137
138 MenuButton *edit_menu = nullptr;
139 MenuButton *search_menu = nullptr;
140 PopupMenu *bookmarks_menu = nullptr;
141 MenuButton *help_menu = nullptr;
142 PopupMenu *context_menu = nullptr;
143 RichTextLabel *warnings_panel = nullptr;
144 uint64_t idle = 0;
145
146 GotoLineDialog *goto_line_dialog = nullptr;
147 ConfirmationDialog *erase_tab_confirm = nullptr;
148 ConfirmationDialog *disk_changed = nullptr;
149
150 ShaderTextEditor *shader_editor = nullptr;
151 bool compilation_success = true;
152
153 void _menu_option(int p_option);
154 mutable Ref<Shader> shader;
155 mutable Ref<ShaderInclude> shader_inc;
156
157 void _editor_settings_changed();
158 void _project_settings_changed();
159
160 void _check_for_external_edit();
161 void _reload_shader_from_disk();
162 void _reload_shader_include_from_disk();
163 void _reload();
164 void _show_warnings_panel(bool p_show);
165 void _warning_clicked(Variant p_line);
166 void _update_warnings(bool p_validate);
167
168 void _script_validated(bool p_valid) {
169 compilation_success = p_valid;
170 emit_signal(SNAME("validation_changed"));
171 }
172
173 uint32_t dependencies_version = 0xFFFFFFFF;
174
175 bool trim_trailing_whitespace_on_save;
176
177protected:
178 void _notification(int p_what);
179 static void _bind_methods();
180 void _make_context_menu(bool p_selection, Vector2 p_position);
181 void _text_edit_gui_input(const Ref<InputEvent> &p_ev);
182
183 void _update_bookmark_list();
184 void _bookmark_item_pressed(int p_idx);
185
186public:
187 bool was_compilation_successful() const { return compilation_success; }
188 bool get_trim_trailing_whitespace_on_save() const { return trim_trailing_whitespace_on_save; }
189 void apply_shaders();
190 void ensure_select_current();
191 void edit(const Ref<Shader> &p_shader);
192 void edit(const Ref<ShaderInclude> &p_shader_inc);
193 void goto_line_selection(int p_line, int p_begin, int p_end);
194 void save_external_data(const String &p_str = "");
195 void trim_trailing_whitespace();
196 void validate_script();
197 bool is_unsaved() const;
198 void tag_saved_version();
199
200 virtual Size2 get_minimum_size() const override { return Size2(0, 200); }
201
202 TextShaderEditor();
203};
204
205#endif // TEXT_SHADER_EDITOR_H
206