1 /*************************************************************************/
2 /*  script_editor_plugin.h                                               */
3 /*************************************************************************/
4 /*                       This file is part of:                           */
5 /*                           GODOT ENGINE                                */
6 /*                      https://godotengine.org                          */
7 /*************************************************************************/
8 /* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur.                 */
9 /* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md)    */
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 #ifndef SCRIPT_EDITOR_PLUGIN_H
31 #define SCRIPT_EDITOR_PLUGIN_H
32 
33 #include "editor/code_editor.h"
34 #include "editor/editor_help.h"
35 #include "editor/editor_plugin.h"
36 #include "editor/script_create_dialog.h"
37 #include "scene/gui/item_list.h"
38 #include "scene/gui/menu_button.h"
39 #include "scene/gui/split_container.h"
40 #include "scene/gui/tab_container.h"
41 #include "scene/gui/text_edit.h"
42 #include "scene/gui/tool_button.h"
43 #include "scene/gui/tree.h"
44 #include "scene/main/timer.h"
45 #include "script_language.h"
46 
47 class ScriptEditorQuickOpen : public ConfirmationDialog {
48 
49 	OBJ_TYPE(ScriptEditorQuickOpen, ConfirmationDialog)
50 
51 	LineEdit *search_box;
52 	Tree *search_options;
53 	String function;
54 
55 	void _update_search();
56 
57 	void _sbox_input(const InputEvent &p_ie);
58 	Vector<String> functions;
59 
60 	void _confirmed();
61 	void _text_changed(const String &p_newtext);
62 
63 protected:
64 	void _notification(int p_what);
65 	static void _bind_methods();
66 
67 public:
68 	void popup(const Vector<String> &p_base, bool p_dontclear = false);
69 	ScriptEditorQuickOpen();
70 };
71 
72 class ScriptEditorDebugger;
73 
74 class ScriptTextEditor : public CodeTextEditor {
75 
76 	OBJ_TYPE(ScriptTextEditor, CodeTextEditor);
77 
78 	Ref<Script> script;
79 
80 	Vector<String> functions;
81 
82 protected:
83 	virtual void _validate_script();
84 	virtual void _code_complete_script(const String &p_code, List<String> *r_options);
85 	virtual void _load_theme_settings();
86 	void _notification(int p_what);
87 	static void _bind_methods();
88 
89 public:
90 	virtual void apply_code();
91 	Ref<Script> get_edited_script() const;
92 	Vector<String> get_functions();
93 	void set_edited_script(const Ref<Script> &p_script);
94 	void reload_text();
95 	String get_name();
96 	Ref<Texture> get_icon();
97 	bool is_unsaved();
98 	ScriptTextEditor();
99 };
100 
101 class EditorScriptCodeCompletionCache;
102 
103 class ScriptEditor : public VBoxContainer {
104 
105 	OBJ_TYPE(ScriptEditor, VBoxContainer);
106 
107 	EditorNode *editor;
108 	enum {
109 		FILE_NEW,
110 		FILE_OPEN,
111 		FILE_SAVE,
112 		FILE_SAVE_AS,
113 		FILE_SAVE_ALL,
114 		FILE_IMPORT_THEME,
115 		FILE_RELOAD_THEME,
116 		FILE_SAVE_THEME,
117 		FILE_SAVE_THEME_AS,
118 		FILE_CLOSE,
119 		FILE_CLOSE_OTHERS,
120 		FILE_CLOSE_ALL,
121 		FILE_COPY_SCRIPT_PATH,
122 		CLOSE_DOCS,
123 		EDIT_UNDO,
124 		EDIT_REDO,
125 		EDIT_CUT,
126 		EDIT_COPY,
127 		EDIT_PASTE,
128 		EDIT_SELECT_ALL,
129 		EDIT_UPPERCASE,
130 		EDIT_LOWERCASE,
131 		EDIT_COMPLETE,
132 		EDIT_AUTO_INDENT,
133 		EDIT_TRIM_TRAILING_WHITESAPCE,
134 		EDIT_TOGGLE_COMMENT,
135 		EDIT_MOVE_LINE_UP,
136 		EDIT_MOVE_LINE_DOWN,
137 		EDIT_INDENT_RIGHT,
138 		EDIT_INDENT_LEFT,
139 		EDIT_CLONE_DOWN,
140 		FILE_TOOL_RELOAD,
141 		FILE_TOOL_RELOAD_SOFT,
142 		SEARCH_FIND,
143 		SEARCH_FIND_NEXT,
144 		SEARCH_FIND_PREV,
145 		SEARCH_REPLACE,
146 		SEARCH_LOCATE_FUNCTION,
147 		SEARCH_GOTO_LINE,
148 		SEARCH_HELP,
149 		SEARCH_CLASSES,
150 		SEARCH_WEBSITE,
151 		DEBUG_TOGGLE_BREAKPOINT,
152 		DEBUG_REMOVE_ALL_BREAKPOINTS,
153 		DEBUG_GOTO_NEXT_BREAKPOINT,
154 		DEBUG_GOTO_PREV_BREAKPOINT,
155 		DEBUG_NEXT,
156 		DEBUG_STEP,
157 		DEBUG_BREAK,
158 		DEBUG_CONTINUE,
159 		DEBUG_SHOW,
160 		DEBUG_SHOW_KEEP_OPEN,
161 		HELP_CONTEXTUAL,
162 		WINDOW_MOVE_LEFT,
163 		WINDOW_MOVE_RIGHT,
164 		WINDOW_NEXT,
165 		WINDOW_PREV,
166 		WINDOW_SELECT_BASE = 100
167 	};
168 
169 	enum ScriptSortBy {
170 		SORT_BY_NAME,
171 		SORT_BY_PATH,
172 	};
173 
174 	enum ScriptListName {
175 		DISPLAY_NAME,
176 		DISPLAY_DIR_AND_NAME,
177 		DISPLAY_FULL_PATH,
178 	};
179 
180 	HBoxContainer *menu_hb;
181 	MenuButton *file_menu;
182 	MenuButton *edit_menu;
183 	MenuButton *search_menu;
184 	MenuButton *script_search_menu;
185 	MenuButton *debug_menu;
186 	MenuButton *help_menu;
187 	Timer *autosave_timer;
188 	uint64_t idle;
189 
190 	Button *help_search;
191 	Button *site_search;
192 	Button *class_search;
193 	EditorHelpSearch *help_search_dialog;
194 
195 	ItemList *script_list;
196 	PopupMenu *script_list_menu;
197 	HSplitContainer *script_split;
198 	ItemList *members_overview;
199 	bool members_overview_enabled;
200 	VSplitContainer *list_split;
201 	TabContainer *tab_container;
202 	EditorFileDialog *file_dialog;
203 	GotoLineDialog *goto_line_dialog;
204 	ConfirmationDialog *erase_tab_confirm;
205 	ScriptCreateDialog *script_create_dialog;
206 	ScriptEditorDebugger *debugger;
207 	ToolButton *scripts_visible;
208 
209 	String current_theme;
210 
211 	TextureFrame *script_icon;
212 	Label *script_name_label;
213 
214 	ToolButton *script_back;
215 	ToolButton *script_forward;
216 
217 	struct ScriptHistory {
218 
219 		Control *control;
220 		int scroll_pos;
221 		int cursor_column;
222 		int cursor_row;
223 	};
224 
225 	Vector<ScriptHistory> history;
226 	int history_pos;
227 
228 	EditorHelpIndex *help_index;
229 
230 	void _tab_changed(int p_which);
231 	void _menu_option(int p_optin);
232 
233 	Tree *disk_changed_list;
234 	ConfirmationDialog *disk_changed;
235 
236 	bool restoring_layout;
237 
238 	String _get_debug_tooltip(const String &p_text, Node *_ste);
239 
240 	void _resave_scripts(const String &p_str);
241 	void _reload_scripts();
242 
243 	bool _test_script_times_on_disk(Ref<Script> p_for_script = Ref<Script>());
244 
245 	void _close_tab(int p_idx);
246 
247 	void _close_current_tab();
248 	void _close_other_tabs(int idx);
249 	void _close_all_tab(int except);
250 	void _close_docs_tab();
251 	void _copy_script_path();
252 
253 	bool grab_focus_block;
254 
255 	bool pending_auto_reload;
256 	bool auto_reload_running_scripts;
257 	void _live_auto_reload_running_scripts();
258 
259 	ScriptEditorQuickOpen *quick_open;
260 
261 	EditorScriptCodeCompletionCache *completion_cache;
262 
263 	void _editor_play();
264 	void _editor_pause();
265 	void _editor_stop();
266 
267 	int edit_pass;
268 
269 	void _add_callback(Object *p_obj, const String &p_function, const StringArray &p_args);
270 	void _res_saved_callback(const Ref<Resource> &p_res);
271 
272 	bool trim_trailing_whitespace_on_save;
273 
274 	void _trim_trailing_whitespace(TextEdit *tx);
275 
276 	void _goto_script_line2(int p_line);
277 	void _goto_script_line(REF p_script, int p_line);
278 	void _breaked(bool p_breaked, bool p_can_debug);
279 	void _show_debugger(bool p_show);
280 	void _update_window_menu();
281 	void _script_created(Ref<Script> p_script);
282 
283 	void _save_layout();
284 	void _editor_settings_changed();
285 	void _autosave_scripts();
286 
287 	void _update_members_overview_visibility();
288 	void _update_members_overview();
289 	void _members_overview_selected(int p_idx);
290 
291 	void _update_script_names();
292 
293 	void _script_selected(int p_idx);
294 
295 	void _script_rmb_selected(int p_idx, const Vector2 &p_pos);
296 
297 	void _find_scripts(Node *p_base, Node *p_current, Set<Ref<Script> > &used);
298 
299 	void _tree_changed();
300 
301 	void _script_split_dragged(float);
302 
303 	void _unhandled_input(const InputEvent &p_event);
304 
305 	void _history_forward();
306 	void _history_back();
307 
308 	bool waiting_update_names;
309 
310 	void _help_class_open(const String &p_class);
311 	void _help_class_goto(const String &p_desc);
312 	void _update_history_arrows();
313 	void _go_to_tab(int p_idx);
314 	void _update_history_pos(int p_new_pos);
315 	void _update_script_colors();
316 	void _update_modified_scripts_for_external_editor(Ref<Script> p_for_script = Ref<Script>());
317 
318 	int file_dialog_option;
319 	void _file_dialog_action(String p_file);
320 
321 	static ScriptEditor *script_editor;
322 
323 protected:
324 	void _notification(int p_what);
325 	static void _bind_methods();
326 
327 public:
get_singleton()328 	static ScriptEditor *get_singleton() { return script_editor; }
329 
330 	void ensure_focus_current();
331 	void apply_scripts() const;
332 
333 	void ensure_select_current();
334 	void edit(const Ref<Script> &p_script);
335 
336 	Dictionary get_state() const;
337 	void set_state(const Dictionary &p_state);
338 	void clear();
339 
340 	void get_breakpoints(List<String> *p_breakpoints);
341 
342 	void swap_lines(TextEdit *tx, int line1, int line2);
343 	void _breakpoint_toggled(const int p_row);
344 
345 	void save_all_scripts();
346 
347 	void set_window_layout(Ref<ConfigFile> p_layout);
348 	void get_window_layout(Ref<ConfigFile> p_layout);
349 
350 	void set_scene_root_script(Ref<Script> p_script);
351 
352 	bool script_go_to_method(Ref<Script> p_script, const String &p_method);
353 
354 	virtual void edited_scene_changed();
355 
356 	void close_builtin_scripts_from_scene(const String &p_scene);
357 
goto_help(const String & p_desc)358 	void goto_help(const String &p_desc) { _help_class_goto(p_desc); }
359 
get_debugger()360 	ScriptEditorDebugger *get_debugger() { return debugger; }
361 	void set_live_auto_reload_running_scripts(bool p_enabled);
362 
363 	ScriptEditor(EditorNode *p_editor);
364 	~ScriptEditor();
365 };
366 
367 class ScriptEditorPlugin : public EditorPlugin {
368 
369 	OBJ_TYPE(ScriptEditorPlugin, EditorPlugin);
370 
371 	ScriptEditor *script_editor;
372 	EditorNode *editor;
373 
374 public:
get_name()375 	virtual String get_name() const { return "Script"; }
has_main_screen()376 	bool has_main_screen() const { return true; }
377 	virtual void edit(Object *p_node);
378 	virtual bool handles(Object *p_node) const;
379 	virtual void make_visible(bool p_visible);
380 	virtual void selected_notify();
381 
382 	Dictionary get_state() const;
383 	virtual void set_state(const Dictionary &p_state);
384 	virtual void clear();
385 
386 	virtual void save_external_data();
387 	virtual void apply_changes();
388 
389 	virtual void restore_global_state();
390 	virtual void save_global_state();
391 
392 	virtual void set_window_layout(Ref<ConfigFile> p_layout);
393 	virtual void get_window_layout(Ref<ConfigFile> p_layout);
394 
395 	virtual void get_breakpoints(List<String> *p_breakpoints);
396 
397 	virtual void edited_scene_changed();
398 
399 	ScriptEditorPlugin(EditorNode *p_node);
400 	~ScriptEditorPlugin();
401 };
402 
403 #endif // SCRIPT_EDITOR_PLUGIN_H
404