1 | /**************************************************************************/ |
2 | /* editor_debugger_node.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 EDITOR_DEBUGGER_NODE_H |
32 | #define EDITOR_DEBUGGER_NODE_H |
33 | |
34 | #include "core/object/script_language.h" |
35 | #include "editor/debugger/editor_debugger_server.h" |
36 | #include "scene/gui/margin_container.h" |
37 | |
38 | class Button; |
39 | class DebugAdapterParser; |
40 | class EditorDebuggerPlugin; |
41 | class EditorDebuggerTree; |
42 | class EditorDebuggerRemoteObject; |
43 | class ; |
44 | class ScriptEditorDebugger; |
45 | class TabContainer; |
46 | class UndoRedo; |
47 | |
48 | class EditorDebuggerNode : public MarginContainer { |
49 | GDCLASS(EditorDebuggerNode, MarginContainer); |
50 | |
51 | public: |
52 | enum CameraOverride { |
53 | OVERRIDE_NONE, |
54 | OVERRIDE_2D, |
55 | OVERRIDE_3D_1, // 3D Viewport 1 |
56 | OVERRIDE_3D_2, // 3D Viewport 2 |
57 | OVERRIDE_3D_3, // 3D Viewport 3 |
58 | OVERRIDE_3D_4 // 3D Viewport 4 |
59 | }; |
60 | |
61 | private: |
62 | enum Options { |
63 | DEBUG_NEXT, |
64 | DEBUG_STEP, |
65 | DEBUG_BREAK, |
66 | DEBUG_CONTINUE, |
67 | DEBUG_WITH_EXTERNAL_EDITOR, |
68 | }; |
69 | |
70 | class Breakpoint { |
71 | public: |
72 | String source; |
73 | int line = 0; |
74 | |
75 | static uint32_t hash(const Breakpoint &p_val) { |
76 | uint32_t h = HashMapHasherDefault::hash(p_val.source); |
77 | return hash_murmur3_one_32(p_val.line, h); |
78 | } |
79 | bool operator==(const Breakpoint &p_b) const { |
80 | return (line == p_b.line && source == p_b.source); |
81 | } |
82 | |
83 | bool operator<(const Breakpoint &p_b) const { |
84 | if (line == p_b.line) { |
85 | return source < p_b.source; |
86 | } |
87 | return line < p_b.line; |
88 | } |
89 | |
90 | Breakpoint() {} |
91 | |
92 | Breakpoint(const String &p_source, int p_line) { |
93 | line = p_line; |
94 | source = p_source; |
95 | } |
96 | }; |
97 | |
98 | Ref<EditorDebuggerServer> server; |
99 | TabContainer *tabs = nullptr; |
100 | Button *debugger_button = nullptr; |
101 | MenuButton * = nullptr; |
102 | |
103 | Ref<Script> stack_script; // Why?!? |
104 | |
105 | int last_error_count = 0; |
106 | int last_warning_count = 0; |
107 | |
108 | float inspect_edited_object_timeout = 0; |
109 | EditorDebuggerTree *remote_scene_tree = nullptr; |
110 | float remote_scene_tree_timeout = 0.0; |
111 | bool auto_switch_remote_scene_tree = false; |
112 | bool debug_with_external_editor = false; |
113 | bool keep_open = false; |
114 | String current_uri; |
115 | |
116 | CameraOverride camera_override = OVERRIDE_NONE; |
117 | HashMap<Breakpoint, bool, Breakpoint> breakpoints; |
118 | |
119 | HashSet<Ref<EditorDebuggerPlugin>> debugger_plugins; |
120 | |
121 | ScriptEditorDebugger *_add_debugger(); |
122 | EditorDebuggerRemoteObject *get_inspected_remote_object(); |
123 | void _update_errors(); |
124 | |
125 | friend class DebuggerEditorPlugin; |
126 | friend class DebugAdapterParser; |
127 | static EditorDebuggerNode *singleton; |
128 | EditorDebuggerNode(); |
129 | |
130 | protected: |
131 | void _debugger_stopped(int p_id); |
132 | void _debugger_wants_stop(int p_id); |
133 | void _debugger_changed(int p_tab); |
134 | void _remote_tree_updated(int p_debugger); |
135 | void _remote_tree_button_pressed(Object *p_item, int p_column, int p_id, MouseButton p_button); |
136 | void _remote_object_updated(ObjectID p_id, int p_debugger); |
137 | void _remote_object_property_updated(ObjectID p_id, const String &p_property, int p_debugger); |
138 | void _remote_object_requested(ObjectID p_id, int p_debugger); |
139 | void _save_node_requested(ObjectID p_id, const String &p_file, int p_debugger); |
140 | |
141 | void _clear_execution(Ref<RefCounted> p_script) { |
142 | emit_signal(SNAME("clear_execution" ), p_script); |
143 | } |
144 | |
145 | void _text_editor_stack_goto(const ScriptEditorDebugger *p_debugger); |
146 | void _stack_frame_selected(int p_debugger); |
147 | void _error_selected(const String &p_file, int p_line, int p_debugger); |
148 | void _breaked(bool p_breaked, bool p_can_debug, String p_message, bool p_has_stackdump, int p_debugger); |
149 | void _paused(); |
150 | void _break_state_changed(); |
151 | void (int p_id); |
152 | void _update_debug_options(); |
153 | |
154 | protected: |
155 | void _notification(int p_what); |
156 | static void _bind_methods(); |
157 | |
158 | public: |
159 | static EditorDebuggerNode *get_singleton() { return singleton; } |
160 | void register_undo_redo(UndoRedo *p_undo_redo); |
161 | |
162 | ScriptEditorDebugger *get_current_debugger() const; |
163 | ScriptEditorDebugger *get_default_debugger() const; |
164 | ScriptEditorDebugger *get_debugger(int p_debugger) const; |
165 | |
166 | void debug_next(); |
167 | void debug_step(); |
168 | void debug_break(); |
169 | void debug_continue(); |
170 | |
171 | void (MenuButton *p_button); |
172 | |
173 | void set_tool_button(Button *p_button) { |
174 | debugger_button = p_button; |
175 | } |
176 | |
177 | String get_var_value(const String &p_var) const; |
178 | Ref<Script> get_dump_stack_script() const { return stack_script; } // Why do we need this? |
179 | |
180 | bool get_debug_with_external_editor() { return debug_with_external_editor; } |
181 | |
182 | bool is_skip_breakpoints() const; |
183 | void set_breakpoint(const String &p_path, int p_line, bool p_enabled); |
184 | void set_breakpoints(const String &p_path, Array p_lines); |
185 | void reload_scripts(); |
186 | |
187 | // Remote inspector/edit. |
188 | void request_remote_tree(); |
189 | static void _method_changeds(void *p_ud, Object *p_base, const StringName &p_name, const Variant **p_args, int p_argcount); |
190 | static void _property_changeds(void *p_ud, Object *p_base, const StringName &p_property, const Variant &p_value); |
191 | |
192 | // LiveDebug |
193 | void set_live_debugging(bool p_enabled); |
194 | void update_live_edit_root(); |
195 | void live_debug_create_node(const NodePath &p_parent, const String &p_type, const String &p_name); |
196 | void live_debug_instantiate_node(const NodePath &p_parent, const String &p_path, const String &p_name); |
197 | void live_debug_remove_node(const NodePath &p_at); |
198 | void live_debug_remove_and_keep_node(const NodePath &p_at, ObjectID p_keep_id); |
199 | void live_debug_restore_node(ObjectID p_id, const NodePath &p_at, int p_at_pos); |
200 | void live_debug_duplicate_node(const NodePath &p_at, const String &p_new_name); |
201 | void live_debug_reparent_node(const NodePath &p_at, const NodePath &p_new_place, const String &p_new_name, int p_at_pos); |
202 | |
203 | void set_camera_override(CameraOverride p_override); |
204 | CameraOverride get_camera_override(); |
205 | |
206 | String get_server_uri() const; |
207 | |
208 | void set_keep_open(bool p_keep_open); |
209 | Error start(const String &p_uri = "tcp://" ); |
210 | void stop(bool p_force = false); |
211 | |
212 | bool plugins_capture(ScriptEditorDebugger *p_debugger, const String &p_message, const Array &p_data); |
213 | void add_debugger_plugin(const Ref<EditorDebuggerPlugin> &p_plugin); |
214 | void remove_debugger_plugin(const Ref<EditorDebuggerPlugin> &p_plugin); |
215 | }; |
216 | |
217 | #endif // EDITOR_DEBUGGER_NODE_H |
218 | |