Browse Source

Threaded networking for editor debugger.

Fabio Alessandrelli 5 years ago
parent
commit
540ca05a80

+ 35 - 9
editor/debugger/editor_debugger_node.cpp

@@ -31,9 +31,12 @@
 #include "editor_debugger_node.h"
 #include "editor_debugger_node.h"
 
 
 #include "editor/debugger/editor_debugger_tree.h"
 #include "editor/debugger/editor_debugger_tree.h"
+#include "editor/debugger/script_editor_debugger.h"
 #include "editor/editor_log.h"
 #include "editor/editor_log.h"
 #include "editor/editor_node.h"
 #include "editor/editor_node.h"
 #include "editor/plugins/script_editor_plugin.h"
 #include "editor/plugins/script_editor_plugin.h"
+#include "scene/gui/menu_button.h"
+#include "scene/gui/tab_container.h"
 
 
 template <typename Func>
 template <typename Func>
 void _for_all(TabContainer *p_node, const Func &p_func) {
 void _for_all(TabContainer *p_node, const Func &p_func) {
@@ -49,7 +52,6 @@ EditorDebuggerNode *EditorDebuggerNode::singleton = NULL;
 EditorDebuggerNode::EditorDebuggerNode() {
 EditorDebuggerNode::EditorDebuggerNode() {
 	if (!singleton)
 	if (!singleton)
 		singleton = this;
 		singleton = this;
-	server.instance();
 
 
 	add_constant_override("margin_left", -EditorNode::get_singleton()->get_gui_base()->get_stylebox("BottomPanelDebuggerOverride", "EditorStyles")->get_margin(MARGIN_LEFT));
 	add_constant_override("margin_left", -EditorNode::get_singleton()->get_gui_base()->get_stylebox("BottomPanelDebuggerOverride", "EditorStyles")->get_margin(MARGIN_LEFT));
 	add_constant_override("margin_right", -EditorNode::get_singleton()->get_gui_base()->get_stylebox("BottomPanelDebuggerOverride", "EditorStyles")->get_margin(MARGIN_RIGHT));
 	add_constant_override("margin_right", -EditorNode::get_singleton()->get_gui_base()->get_stylebox("BottomPanelDebuggerOverride", "EditorStyles")->get_margin(MARGIN_RIGHT));
@@ -179,10 +181,9 @@ Error EditorDebuggerNode::start() {
 		EditorNode::get_singleton()->make_bottom_panel_item_visible(this);
 		EditorNode::get_singleton()->make_bottom_panel_item_visible(this);
 	}
 	}
 
 
-	int remote_port = (int)EditorSettings::get_singleton()->get("network/debug/remote_port");
-	const Error err = server->listen(remote_port);
+	server = Ref<EditorDebuggerServer>(EditorDebuggerServer::create_default());
+	const Error err = server->start();
 	if (err != OK) {
 	if (err != OK) {
-		EditorNode::get_log()->add_message(String("Error listening on port ") + itos(remote_port), EditorLog::MSG_TYPE_ERROR);
 		return err;
 		return err;
 	}
 	}
 	set_process(true);
 	set_process(true);
@@ -191,9 +192,10 @@ Error EditorDebuggerNode::start() {
 }
 }
 
 
 void EditorDebuggerNode::stop() {
 void EditorDebuggerNode::stop() {
-	if (server->is_listening()) {
+	if (server.is_valid()) {
 		server->stop();
 		server->stop();
 		EditorNode::get_log()->add_message("--- Debugging process stopped ---", EditorLog::MSG_TYPE_EDITOR);
 		EditorNode::get_log()->add_message("--- Debugging process stopped ---", EditorLog::MSG_TYPE_EDITOR);
+		server.unref();
 	}
 	}
 	// Also close all debugging sessions.
 	// Also close all debugging sessions.
 	_for_all(tabs, [&](ScriptEditorDebugger *dbg) {
 	_for_all(tabs, [&](ScriptEditorDebugger *dbg) {
@@ -231,9 +233,14 @@ void EditorDebuggerNode::_notification(int p_what) {
 			break;
 			break;
 	}
 	}
 
 
-	if (p_what != NOTIFICATION_PROCESS || !server->is_listening())
+	if (p_what != NOTIFICATION_PROCESS || !server.is_valid())
 		return;
 		return;
 
 
+	if (!server.is_valid() || !server->is_active()) {
+		stop();
+		return;
+	}
+
 	// Errors and warnings
 	// Errors and warnings
 	int error_count = 0;
 	int error_count = 0;
 	int warning_count = 0;
 	int warning_count = 0;
@@ -293,9 +300,8 @@ void EditorDebuggerNode::_notification(int p_what) {
 			if (tabs->get_tab_count() <= 4) { // Max 4 debugging sessions active.
 			if (tabs->get_tab_count() <= 4) { // Max 4 debugging sessions active.
 				debugger = _add_debugger();
 				debugger = _add_debugger();
 			} else {
 			} else {
-				// We already have too many sessions, disconnecting new clients to prevent it from hanging.
-				// (Not keeping a reference to the connection will disconnect it)
-				server->take_connection();
+				// We already have too many sessions, disconnecting new clients to prevent them from hanging.
+				server->take_connection()->close();
 				return; // Can't add, stop here.
 				return; // Can't add, stop here.
 			}
 			}
 		}
 		}
@@ -462,6 +468,26 @@ void EditorDebuggerNode::reload_scripts() {
 	});
 	});
 }
 }
 
 
+void EditorDebuggerNode::debug_next() {
+	get_default_debugger()->debug_next();
+}
+
+void EditorDebuggerNode::debug_step() {
+	get_default_debugger()->debug_step();
+}
+
+void EditorDebuggerNode::debug_break() {
+	get_default_debugger()->debug_break();
+}
+
+void EditorDebuggerNode::debug_continue() {
+	get_default_debugger()->debug_continue();
+}
+
+String EditorDebuggerNode::get_var_value(const String &p_var) const {
+	return get_default_debugger()->get_var_value(p_var);
+}
+
 // LiveEdit/Inspector
 // LiveEdit/Inspector
 void EditorDebuggerNode::request_remote_tree() {
 void EditorDebuggerNode::request_remote_tree() {
 	get_current_debugger()->request_remote_tree();
 	get_current_debugger()->request_remote_tree();

+ 26 - 13
editor/debugger/editor_debugger_node.h

@@ -31,17 +31,30 @@
 #ifndef EDITOR_DEBUGGER_NODE_H
 #ifndef EDITOR_DEBUGGER_NODE_H
 #define EDITOR_DEBUGGER_NODE_H
 #define EDITOR_DEBUGGER_NODE_H
 
 
-#include "core/io/tcp_server.h"
-#include "editor/debugger/script_editor_debugger.h"
-#include "scene/gui/button.h"
-#include "scene/gui/tab_container.h"
+#include "editor/debugger/editor_debugger_server.h"
+#include "scene/gui/margin_container.h"
 
 
+class Button;
 class EditorDebuggerTree;
 class EditorDebuggerTree;
+class EditorDebuggerRemoteObject;
+class MenuButton;
+class ScriptEditorDebugger;
+class TabContainer;
 
 
 class EditorDebuggerNode : public MarginContainer {
 class EditorDebuggerNode : public MarginContainer {
 
 
 	GDCLASS(EditorDebuggerNode, MarginContainer);
 	GDCLASS(EditorDebuggerNode, MarginContainer);
 
 
+public:
+	enum CameraOverride {
+		OVERRIDE_NONE,
+		OVERRIDE_2D,
+		OVERRIDE_3D_1, // 3D Viewport 1
+		OVERRIDE_3D_2, // 3D Viewport 2
+		OVERRIDE_3D_3, // 3D Viewport 3
+		OVERRIDE_3D_4 // 3D Viewport 4
+	};
+
 private:
 private:
 	enum Options {
 	enum Options {
 		DEBUG_NEXT,
 		DEBUG_NEXT,
@@ -71,7 +84,7 @@ private:
 		}
 		}
 	};
 	};
 
 
-	Ref<TCP_Server> server = NULL;
+	Ref<EditorDebuggerServer> server;
 	TabContainer *tabs = NULL;
 	TabContainer *tabs = NULL;
 	Button *debugger_button = NULL;
 	Button *debugger_button = NULL;
 	MenuButton *script_menu = NULL;
 	MenuButton *script_menu = NULL;
@@ -87,7 +100,7 @@ private:
 	bool auto_switch_remote_scene_tree = false;
 	bool auto_switch_remote_scene_tree = false;
 	bool debug_with_external_editor = false;
 	bool debug_with_external_editor = false;
 	bool hide_on_stop = true;
 	bool hide_on_stop = true;
-	ScriptEditorDebugger::CameraOverride camera_override = ScriptEditorDebugger::OVERRIDE_NONE;
+	CameraOverride camera_override = OVERRIDE_NONE;
 	Map<Breakpoint, bool> breakpoints;
 	Map<Breakpoint, bool> breakpoints;
 
 
 	ScriptEditorDebugger *_add_debugger();
 	ScriptEditorDebugger *_add_debugger();
@@ -130,10 +143,10 @@ public:
 	ScriptEditorDebugger *get_default_debugger() const;
 	ScriptEditorDebugger *get_default_debugger() const;
 	ScriptEditorDebugger *get_debugger(int p_debugger) const;
 	ScriptEditorDebugger *get_debugger(int p_debugger) const;
 
 
-	void debug_next() { get_default_debugger()->debug_next(); }
-	void debug_step() { get_default_debugger()->debug_step(); }
-	void debug_break() { get_default_debugger()->debug_break(); }
-	void debug_continue() { get_default_debugger()->debug_continue(); }
+	void debug_next();
+	void debug_step();
+	void debug_break();
+	void debug_continue();
 
 
 	void set_script_debug_button(MenuButton *p_button);
 	void set_script_debug_button(MenuButton *p_button);
 
 
@@ -141,7 +154,7 @@ public:
 		debugger_button = p_button;
 		debugger_button = p_button;
 	}
 	}
 
 
-	String get_var_value(const String &p_var) const { return get_default_debugger()->get_var_value(p_var); }
+	String get_var_value(const String &p_var) const;
 	Ref<Script> get_dump_stack_script() const { return stack_script; } // Why do we need this?
 	Ref<Script> get_dump_stack_script() const { return stack_script; } // Why do we need this?
 
 
 	bool get_debug_with_external_editor() { return debug_with_external_editor; }
 	bool get_debug_with_external_editor() { return debug_with_external_editor; }
@@ -167,8 +180,8 @@ public:
 	void live_debug_reparent_node(const NodePath &p_at, const NodePath &p_new_place, const String &p_new_name, int p_at_pos);
 	void live_debug_reparent_node(const NodePath &p_at, const NodePath &p_new_place, const String &p_new_name, int p_at_pos);
 
 
 	// Camera
 	// Camera
-	void set_camera_override(ScriptEditorDebugger::CameraOverride p_override) { camera_override = p_override; }
-	ScriptEditorDebugger::CameraOverride get_camera_override() { return camera_override; }
+	void set_camera_override(CameraOverride p_override) { camera_override = p_override; }
+	CameraOverride get_camera_override() { return camera_override; }
 
 
 	Error start();
 	Error start();
 
 

+ 216 - 0
editor/debugger/editor_debugger_server.cpp

@@ -0,0 +1,216 @@
+/*************************************************************************/
+/*  editor_debugger_server.cpp                                           */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                      https://godotengine.org                          */
+/*************************************************************************/
+/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur.                 */
+/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md).   */
+/*                                                                       */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the       */
+/* "Software"), to deal in the Software without restriction, including   */
+/* without limitation the rights to use, copy, modify, merge, publish,   */
+/* distribute, sublicense, and/or sell copies of the Software, and to    */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions:                                             */
+/*                                                                       */
+/* The above copyright notice and this permission notice shall be        */
+/* included in all copies or substantial portions of the Software.       */
+/*                                                                       */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
+/*************************************************************************/
+
+#include "editor_debugger_server.h"
+
+#include "core/io/packet_peer.h"
+#include "core/io/tcp_server.h"
+#include "core/os/mutex.h"
+#include "core/os/thread.h"
+#include "editor/editor_log.h"
+#include "editor/editor_node.h"
+#include "editor/editor_settings.h"
+
+class EditorDebuggerPeerTCP : public EditorDebuggerPeer {
+
+private:
+	enum {
+		QUEUE_MAX = 2048,
+		POLL_USEC_MAX = 100,
+	};
+	Ref<StreamPeerTCP> tcp;
+	Ref<PacketPeerStream> packet_peer;
+	List<Array> out_queue;
+	List<Array> in_queue;
+	Mutex mutex;
+	bool connected = false;
+
+public:
+	Error poll() {
+		MutexLock lock(mutex);
+		connected = tcp->get_status() == StreamPeerTCP::STATUS_CONNECTED;
+		Error err = OK;
+		uint64_t ticks = OS::get_singleton()->get_ticks_usec();
+		while (connected && packet_peer->get_available_packet_count() > 0 && in_queue.size() < QUEUE_MAX && OS::get_singleton()->get_ticks_usec() - ticks < POLL_USEC_MAX) {
+			Variant var;
+			err = packet_peer->get_var(var);
+			connected = tcp->get_status() == StreamPeerTCP::STATUS_CONNECTED;
+			if (err != OK) {
+				ERR_PRINT("Error reading variant from peer");
+				break;
+			}
+			ERR_CONTINUE_MSG(var.get_type() != Variant::ARRAY, "Malformed packet received, not an Array.");
+			in_queue.push_back(var);
+		}
+		ticks = OS::get_singleton()->get_ticks_usec();
+		while (connected && out_queue.size() > 0 && OS::get_singleton()->get_ticks_usec() - ticks < POLL_USEC_MAX) {
+			Array arr = out_queue[0];
+			out_queue.pop_front();
+			packet_peer->put_var(arr);
+			connected = tcp->get_status() == StreamPeerTCP::STATUS_CONNECTED;
+		}
+		return err;
+	}
+
+	bool has_message() {
+		return in_queue.size() > 0;
+	}
+
+	Array get_message() {
+		MutexLock lock(mutex);
+		ERR_FAIL_COND_V(!has_message(), Array());
+		Array out = in_queue[0];
+		in_queue.pop_front();
+		return out;
+	}
+
+	Error put_message(const Array p_arr) {
+		MutexLock lock(mutex);
+		if (out_queue.size() > QUEUE_MAX) {
+			return ERR_OUT_OF_MEMORY;
+		}
+		out_queue.push_back(p_arr);
+		return OK;
+	}
+
+	int get_max_message_size() const {
+		return 8 << 20; // 8 MiB
+	}
+
+	bool is_peer_connected() {
+		return connected;
+	}
+
+	void close() {
+		MutexLock lock(mutex);
+		connected = false;
+		tcp->disconnect_from_host();
+	}
+
+	EditorDebuggerPeerTCP(Ref<StreamPeerTCP> p_stream) {
+		packet_peer.instance();
+		tcp = p_stream;
+		if (tcp.is_null()) {
+			tcp.instance(); // Bug?
+		}
+		packet_peer->set_stream_peer(tcp);
+	}
+
+	~EditorDebuggerPeerTCP() {
+		close();
+		packet_peer->set_stream_peer(Ref<StreamPeer>());
+	}
+};
+
+class EditorDebuggerServerTCP : public EditorDebuggerServer {
+
+private:
+	Ref<TCP_Server> server;
+	List<Ref<EditorDebuggerPeer> > peers;
+	Thread *thread = NULL;
+	Mutex mutex;
+	bool running = false;
+
+	static void _poll_func(void *p_ud);
+
+public:
+	virtual Error start();
+	virtual void stop();
+	virtual bool is_active() const;
+	virtual bool is_connection_available() const;
+	virtual Ref<EditorDebuggerPeer> take_connection();
+
+	EditorDebuggerServerTCP();
+};
+
+EditorDebuggerServerTCP::EditorDebuggerServerTCP() {
+	server.instance();
+}
+
+Error EditorDebuggerServerTCP::start() {
+	int remote_port = (int)EditorSettings::get_singleton()->get("network/debug/remote_port");
+	const Error err = server->listen(remote_port);
+	if (err != OK) {
+		EditorNode::get_log()->add_message(String("Error listening on port ") + itos(remote_port), EditorLog::MSG_TYPE_ERROR);
+		return err;
+	}
+	running = true;
+	thread = Thread::create(_poll_func, this);
+	return err;
+}
+
+void EditorDebuggerServerTCP::stop() {
+	server->stop();
+	if (thread != NULL) {
+		running = false;
+		Thread::wait_to_finish(thread);
+		memdelete(thread);
+		thread = NULL;
+	}
+}
+
+bool EditorDebuggerServerTCP::is_active() const {
+	return server->is_listening();
+}
+
+bool EditorDebuggerServerTCP::is_connection_available() const {
+	return server->is_listening() && server->is_connection_available();
+}
+
+Ref<EditorDebuggerPeer> EditorDebuggerServerTCP::take_connection() {
+	ERR_FAIL_COND_V(!is_connection_available(), Ref<EditorDebuggerPeer>());
+	MutexLock lock(mutex);
+	Ref<EditorDebuggerPeerTCP> peer = memnew(EditorDebuggerPeerTCP(server->take_connection()));
+	peers.push_back(peer);
+	return peer;
+}
+
+void EditorDebuggerServerTCP::_poll_func(void *p_ud) {
+	EditorDebuggerServerTCP *me = (EditorDebuggerServerTCP *)p_ud;
+	while (me->running) {
+		me->mutex.lock();
+		List<Ref<EditorDebuggerPeer> > remove;
+		for (int i = 0; i < me->peers.size(); i++) {
+			Ref<EditorDebuggerPeer> peer = me->peers[i];
+			Error err = ((EditorDebuggerPeerTCP *)peer.ptr())->poll();
+			if (err != OK || !peer->is_peer_connected())
+				remove.push_back(peer);
+		}
+		for (List<Ref<EditorDebuggerPeer> >::Element *E = remove.front(); E; E = E->next()) {
+			me->peers.erase(E->get());
+		}
+		me->mutex.unlock();
+		OS::get_singleton()->delay_usec(50);
+	}
+}
+
+EditorDebuggerServer *EditorDebuggerServer::create_default() {
+	return memnew(EditorDebuggerServerTCP);
+}

+ 59 - 0
editor/debugger/editor_debugger_server.h

@@ -0,0 +1,59 @@
+/*************************************************************************/
+/*  editor_debugger_server.h                                             */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                      https://godotengine.org                          */
+/*************************************************************************/
+/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur.                 */
+/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md).   */
+/*                                                                       */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the       */
+/* "Software"), to deal in the Software without restriction, including   */
+/* without limitation the rights to use, copy, modify, merge, publish,   */
+/* distribute, sublicense, and/or sell copies of the Software, and to    */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions:                                             */
+/*                                                                       */
+/* The above copyright notice and this permission notice shall be        */
+/* included in all copies or substantial portions of the Software.       */
+/*                                                                       */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
+/*************************************************************************/
+
+#ifndef EDITOR_DEBUGGER_CONNECTION_H
+#define EDITOR_DEBUGGER_CONNECTION_H
+
+#include "core/reference.h"
+
+class EditorDebuggerPeer : public Reference {
+
+public:
+	virtual bool has_message() = 0;
+	virtual Array get_message() = 0;
+	virtual Error put_message(const Array p_arr) = 0;
+
+	virtual int get_max_message_size() const = 0;
+	virtual bool is_peer_connected() = 0;
+	virtual void close() = 0;
+};
+
+class EditorDebuggerServer : public Reference {
+
+public:
+	static EditorDebuggerServer *create_default();
+	virtual Error start() = 0;
+	virtual void stop() = 0;
+	virtual bool is_active() const = 0;
+	virtual bool is_connection_available() const = 0;
+	virtual Ref<EditorDebuggerPeer> take_connection() = 0;
+};
+
+#endif // EDITOR_DEBUGGER_CONNECTION_H

+ 29 - 45
editor/debugger/script_editor_debugger.cpp

@@ -45,6 +45,7 @@
 #include "editor/plugins/spatial_editor_plugin.h"
 #include "editor/plugins/spatial_editor_plugin.h"
 #include "editor/property_editor.h"
 #include "editor/property_editor.h"
 #include "main/performance.h"
 #include "main/performance.h"
+#include "scene/3d/camera.h"
 #include "scene/debugger/scene_debugger.h"
 #include "scene/debugger/scene_debugger.h"
 #include "scene/gui/dialogs.h"
 #include "scene/gui/dialogs.h"
 #include "scene/gui/label.h"
 #include "scene/gui/label.h"
@@ -58,12 +59,14 @@
 #include "scene/gui/tree.h"
 #include "scene/gui/tree.h"
 #include "scene/resources/packed_scene.h"
 #include "scene/resources/packed_scene.h"
 
 
+using CameraOverride = EditorDebuggerNode::CameraOverride;
+
 void ScriptEditorDebugger::_put_msg(String p_message, Array p_data) {
 void ScriptEditorDebugger::_put_msg(String p_message, Array p_data) {
 	if (is_session_active()) {
 	if (is_session_active()) {
 		Array msg;
 		Array msg;
 		msg.push_back(p_message);
 		msg.push_back(p_message);
 		msg.push_back(p_data);
 		msg.push_back(p_data);
-		ppeer->put_var(msg);
+		peer->put_message(msg);
 	}
 	}
 }
 }
 
 
@@ -776,7 +779,7 @@ void ScriptEditorDebugger::_notification(int p_what) {
 
 
 			if (is_session_active()) {
 			if (is_session_active()) {
 
 
-				if (camera_override == OVERRIDE_2D) {
+				if (camera_override == CameraOverride::OVERRIDE_2D) {
 					CanvasItemEditor *editor = CanvasItemEditor::get_singleton();
 					CanvasItemEditor *editor = CanvasItemEditor::get_singleton();
 
 
 					Dictionary state = editor->get_state();
 					Dictionary state = editor->get_state();
@@ -791,8 +794,8 @@ void ScriptEditorDebugger::_notification(int p_what) {
 					msg.push_back(transform);
 					msg.push_back(transform);
 					_put_msg("override_camera_2D:transform", msg);
 					_put_msg("override_camera_2D:transform", msg);
 
 
-				} else if (camera_override >= OVERRIDE_3D_1) {
-					int viewport_idx = camera_override - OVERRIDE_3D_1;
+				} else if (camera_override >= CameraOverride::OVERRIDE_3D_1) {
+					int viewport_idx = camera_override - CameraOverride::OVERRIDE_3D_1;
 					SpatialEditorViewport *viewport = SpatialEditor::get_singleton()->get_editor_viewport(viewport_idx);
 					SpatialEditorViewport *viewport = SpatialEditor::get_singleton()->get_editor_viewport(viewport_idx);
 					Camera *const cam = viewport->get_camera();
 					Camera *const cam = viewport->get_camera();
 
 
@@ -811,30 +814,11 @@ void ScriptEditorDebugger::_notification(int p_what) {
 				}
 				}
 			}
 			}
 
 
-			if (!is_session_active()) {
-				_stop_and_notify();
-				break;
-			};
-
-			if (ppeer->get_available_packet_count() <= 0) {
-				break;
-			};
-
 			const uint64_t until = OS::get_singleton()->get_ticks_msec() + 20;
 			const uint64_t until = OS::get_singleton()->get_ticks_msec() + 20;
 
 
-			while (ppeer->get_available_packet_count() > 0) {
+			while (peer->has_message()) {
 
 
-				Variant cmd;
-				Error ret = ppeer->get_var(cmd);
-				if (ret != OK) {
-					_stop_and_notify();
-					ERR_FAIL_MSG("Error decoding variant from peer");
-				}
-				if (cmd.get_type() != Variant::ARRAY) {
-					_stop_and_notify();
-					ERR_FAIL_MSG("Invalid message format received from peer");
-				}
-				Array arr = cmd;
+				Array arr = peer->get_message();
 				if (arr.size() != 2 || arr[0].get_type() != Variant::STRING || arr[1].get_type() != Variant::ARRAY) {
 				if (arr.size() != 2 || arr[0].get_type() != Variant::STRING || arr[1].get_type() != Variant::ARRAY) {
 					_stop_and_notify();
 					_stop_and_notify();
 					ERR_FAIL_MSG("Invalid message format received from peer");
 					ERR_FAIL_MSG("Invalid message format received from peer");
@@ -844,6 +828,10 @@ void ScriptEditorDebugger::_notification(int p_what) {
 				if (OS::get_singleton()->get_ticks_msec() > until)
 				if (OS::get_singleton()->get_ticks_msec() > until)
 					break;
 					break;
 			}
 			}
+			if (!is_session_active()) {
+				_stop_and_notify();
+				break;
+			};
 		} break;
 		} break;
 		case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: {
 		case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: {
 
 
@@ -875,14 +863,13 @@ void ScriptEditorDebugger::_clear_execution() {
 	inspector->clear_stack_variables();
 	inspector->clear_stack_variables();
 }
 }
 
 
-void ScriptEditorDebugger::start(Ref<StreamPeerTCP> p_connection) {
+void ScriptEditorDebugger::start(Ref<EditorDebuggerPeer> p_peer) {
 
 
 	error_count = 0;
 	error_count = 0;
 	warning_count = 0;
 	warning_count = 0;
 	stop();
 	stop();
 
 
-	connection = p_connection;
-	ppeer->set_stream_peer(connection);
+	peer = p_peer;
 
 
 	perf_history.clear();
 	perf_history.clear();
 	for (int i = 0; i < Performance::MONITOR_MAX; i++) {
 	for (int i = 0; i < Performance::MONITOR_MAX; i++) {
@@ -893,7 +880,7 @@ void ScriptEditorDebugger::start(Ref<StreamPeerTCP> p_connection) {
 	set_process(true);
 	set_process(true);
 	breaked = false;
 	breaked = false;
 	can_debug = true;
 	can_debug = true;
-	camera_override = OVERRIDE_NONE;
+	camera_override = CameraOverride::OVERRIDE_NONE;
 
 
 	tabs->set_current_tab(0);
 	tabs->set_current_tab(0);
 	_set_reason_text(TTR("Debug session started."), MESSAGE_SUCCESS);
 	_set_reason_text(TTR("Debug session started."), MESSAGE_SUCCESS);
@@ -936,10 +923,10 @@ void ScriptEditorDebugger::stop() {
 	_clear_execution();
 	_clear_execution();
 
 
 	inspector->clear_cache();
 	inspector->clear_cache();
-	ppeer->set_stream_peer(Ref<StreamPeer>());
 
 
-	if (connection.is_valid()) {
-		connection.unref();
+	if (peer.is_valid()) {
+		peer->close();
+		peer.unref();
 		reason->set_text("");
 		reason->set_text("");
 		reason->set_tooltip("");
 		reason->set_tooltip("");
 	}
 	}
@@ -971,9 +958,6 @@ void ScriptEditorDebugger::_profiler_activate(bool p_enable) {
 
 
 void ScriptEditorDebugger::_visual_profiler_activate(bool p_enable) {
 void ScriptEditorDebugger::_visual_profiler_activate(bool p_enable) {
 
 
-	if (!connection.is_valid())
-		return;
-
 	if (p_enable) {
 	if (p_enable) {
 		profiler_signature.clear();
 		profiler_signature.clear();
 		_put_msg("start_visual_profiling", Array());
 		_put_msg("start_visual_profiling", Array());
@@ -1328,25 +1312,25 @@ void ScriptEditorDebugger::live_debug_reparent_node(const NodePath &p_at, const
 	}
 	}
 }
 }
 
 
-ScriptEditorDebugger::CameraOverride ScriptEditorDebugger::get_camera_override() const {
+CameraOverride ScriptEditorDebugger::get_camera_override() const {
 	return camera_override;
 	return camera_override;
 }
 }
 
 
 void ScriptEditorDebugger::set_camera_override(CameraOverride p_override) {
 void ScriptEditorDebugger::set_camera_override(CameraOverride p_override) {
 
 
-	if (p_override == OVERRIDE_2D && camera_override != OVERRIDE_2D) {
+	if (p_override == CameraOverride::OVERRIDE_2D && camera_override != CameraOverride::OVERRIDE_2D) {
 		Array msg;
 		Array msg;
 		msg.push_back(true);
 		msg.push_back(true);
 		_put_msg("override_camera_2D:set", msg);
 		_put_msg("override_camera_2D:set", msg);
-	} else if (p_override != OVERRIDE_2D && camera_override == OVERRIDE_2D) {
+	} else if (p_override != CameraOverride::OVERRIDE_2D && camera_override == CameraOverride::OVERRIDE_2D) {
 		Array msg;
 		Array msg;
 		msg.push_back(false);
 		msg.push_back(false);
 		_put_msg("override_camera_2D:set", msg);
 		_put_msg("override_camera_2D:set", msg);
-	} else if (p_override >= OVERRIDE_3D_1 && camera_override < OVERRIDE_3D_1) {
+	} else if (p_override >= CameraOverride::OVERRIDE_3D_1 && camera_override < CameraOverride::OVERRIDE_3D_1) {
 		Array msg;
 		Array msg;
 		msg.push_back(true);
 		msg.push_back(true);
 		_put_msg("override_camera_3D:set", msg);
 		_put_msg("override_camera_3D:set", msg);
-	} else if (p_override < OVERRIDE_3D_1 && camera_override >= OVERRIDE_3D_1) {
+	} else if (p_override < CameraOverride::OVERRIDE_3D_1 && camera_override >= CameraOverride::OVERRIDE_3D_1) {
 		Array msg;
 		Array msg;
 		msg.push_back(false);
 		msg.push_back(false);
 		_put_msg("override_camera_3D:set", msg);
 		_put_msg("override_camera_3D:set", msg);
@@ -1423,7 +1407,6 @@ void ScriptEditorDebugger::_clear_errors_list() {
 	error_tree->clear();
 	error_tree->clear();
 	error_count = 0;
 	error_count = 0;
 	warning_count = 0;
 	warning_count = 0;
-	update_tabs();
 }
 }
 
 
 // Right click on specific file(s) or folder(s).
 // Right click on specific file(s) or folder(s).
@@ -1502,8 +1485,6 @@ void ScriptEditorDebugger::_bind_methods() {
 
 
 ScriptEditorDebugger::ScriptEditorDebugger(EditorNode *p_editor) {
 ScriptEditorDebugger::ScriptEditorDebugger(EditorNode *p_editor) {
 
 
-	ppeer = Ref<PacketPeerStream>(memnew(PacketPeerStream));
-	ppeer->set_input_buffer_max_size((1024 * 1024 * 8) - 4); // 8 MiB should be enough, minus 4 bytes for separator.
 	editor = p_editor;
 	editor = p_editor;
 
 
 	tabs = memnew(TabContainer);
 	tabs = memnew(TabContainer);
@@ -1824,7 +1805,7 @@ ScriptEditorDebugger::ScriptEditorDebugger(EditorNode *p_editor) {
 	add_child(msgdialog);
 	add_child(msgdialog);
 
 
 	live_debug = true;
 	live_debug = true;
-	camera_override = OVERRIDE_NONE;
+	camera_override = CameraOverride::OVERRIDE_NONE;
 	last_path_id = false;
 	last_path_id = false;
 	error_count = 0;
 	error_count = 0;
 	warning_count = 0;
 	warning_count = 0;
@@ -1833,6 +1814,9 @@ ScriptEditorDebugger::ScriptEditorDebugger(EditorNode *p_editor) {
 
 
 ScriptEditorDebugger::~ScriptEditorDebugger() {
 ScriptEditorDebugger::~ScriptEditorDebugger() {
 
 
-	ppeer->set_stream_peer(Ref<StreamPeer>());
+	if (peer.is_valid()) {
+		peer->close();
+		peer.unref();
+	}
 	memdelete(scene_tree);
 	memdelete(scene_tree);
 }
 }

+ 11 - 23
editor/debugger/script_editor_debugger.h

@@ -31,14 +31,13 @@
 #ifndef SCRIPT_EDITOR_DEBUGGER_H
 #ifndef SCRIPT_EDITOR_DEBUGGER_H
 #define SCRIPT_EDITOR_DEBUGGER_H
 #define SCRIPT_EDITOR_DEBUGGER_H
 
 
-#include "core/io/packet_peer.h"
-#include "core/io/stream_peer_tcp.h"
+#include "core/os/os.h"
 #include "editor/debugger/editor_debugger_inspector.h"
 #include "editor/debugger/editor_debugger_inspector.h"
-#include "editor/editor_inspector.h"
-#include "editor/property_editor.h"
-#include "scene/3d/camera.h"
-#include "scene/gui/box_container.h"
+#include "editor/debugger/editor_debugger_node.h"
+#include "editor/debugger/editor_debugger_server.h"
+#include "editor/editor_file_dialog.h"
 #include "scene/gui/button.h"
 #include "scene/gui/button.h"
+#include "scene/gui/margin_container.h"
 
 
 class Tree;
 class Tree;
 class EditorNode;
 class EditorNode;
@@ -61,16 +60,6 @@ class ScriptEditorDebugger : public MarginContainer {
 
 
 	friend class EditorDebuggerNode;
 	friend class EditorDebuggerNode;
 
 
-public:
-	enum CameraOverride {
-		OVERRIDE_NONE,
-		OVERRIDE_2D,
-		OVERRIDE_3D_1, // 3D Viewport 1
-		OVERRIDE_3D_2, // 3D Viewport 2
-		OVERRIDE_3D_3, // 3D Viewport 3
-		OVERRIDE_3D_4 // 3D Viewport 4
-	};
-
 private:
 private:
 	enum MessageType {
 	enum MessageType {
 		MESSAGE_ERROR,
 		MESSAGE_ERROR,
@@ -132,8 +121,7 @@ private:
 	EditorDebuggerInspector *inspector;
 	EditorDebuggerInspector *inspector;
 	SceneDebuggerTree *scene_tree;
 	SceneDebuggerTree *scene_tree;
 
 
-	Ref<StreamPeerTCP> connection;
-	Ref<PacketPeerStream> ppeer;
+	Ref<EditorDebuggerPeer> peer;
 
 
 	HashMap<NodePath, int> node_path_cache;
 	HashMap<NodePath, int> node_path_cache;
 	int last_path_id;
 	int last_path_id;
@@ -151,7 +139,7 @@ private:
 
 
 	bool live_debug;
 	bool live_debug;
 
 
-	CameraOverride camera_override;
+	EditorDebuggerNode::CameraOverride camera_override;
 
 
 	void _performance_draw();
 	void _performance_draw();
 	void _performance_select();
 	void _performance_select();
@@ -216,7 +204,7 @@ public:
 	void request_remote_tree();
 	void request_remote_tree();
 	const SceneDebuggerTree *get_remote_tree();
 	const SceneDebuggerTree *get_remote_tree();
 
 
-	void start(Ref<StreamPeerTCP> p_connection);
+	void start(Ref<EditorDebuggerPeer> p_peer);
 	void stop();
 	void stop();
 
 
 	void debug_skip_breakpoints();
 	void debug_skip_breakpoints();
@@ -228,7 +216,7 @@ public:
 	void debug_continue();
 	void debug_continue();
 	bool is_breaked() const { return breaked; }
 	bool is_breaked() const { return breaked; }
 	bool is_debuggable() const { return can_debug; }
 	bool is_debuggable() const { return can_debug; }
-	bool is_session_active() { return connection.is_valid() && connection->is_connected_to_host(); };
+	bool is_session_active() { return peer.is_valid() && peer->is_peer_connected(); };
 	int get_remote_pid() const { return remote_pid; }
 	int get_remote_pid() const { return remote_pid; }
 
 
 	int get_error_count() const { return error_count; }
 	int get_error_count() const { return error_count; }
@@ -252,8 +240,8 @@ public:
 	void live_debug_duplicate_node(const NodePath &p_at, const String &p_new_name);
 	void live_debug_duplicate_node(const NodePath &p_at, const String &p_new_name);
 	void live_debug_reparent_node(const NodePath &p_at, const NodePath &p_new_place, const String &p_new_name, int p_at_pos);
 	void live_debug_reparent_node(const NodePath &p_at, const NodePath &p_new_place, const String &p_new_name, int p_at_pos);
 
 
-	CameraOverride get_camera_override() const;
-	void set_camera_override(CameraOverride p_override);
+	EditorDebuggerNode::CameraOverride get_camera_override() const;
+	void set_camera_override(EditorDebuggerNode::CameraOverride p_override);
 
 
 	void set_breakpoint(const String &p_path, int p_line, bool p_enabled);
 	void set_breakpoint(const String &p_path, int p_line, bool p_enabled);
 
 

+ 3 - 3
editor/plugins/canvas_item_editor_plugin.cpp

@@ -3992,7 +3992,7 @@ void CanvasItemEditor::_notification(int p_what) {
 		if (!is_visible() && override_camera_button->is_pressed()) {
 		if (!is_visible() && override_camera_button->is_pressed()) {
 			EditorDebuggerNode *debugger = EditorDebuggerNode::get_singleton();
 			EditorDebuggerNode *debugger = EditorDebuggerNode::get_singleton();
 
 
-			debugger->set_camera_override(ScriptEditorDebugger::OVERRIDE_NONE);
+			debugger->set_camera_override(EditorDebuggerNode::OVERRIDE_NONE);
 			override_camera_button->set_pressed(false);
 			override_camera_button->set_pressed(false);
 		}
 		}
 	}
 	}
@@ -4348,9 +4348,9 @@ void CanvasItemEditor::_button_override_camera(bool p_pressed) {
 	EditorDebuggerNode *debugger = EditorDebuggerNode::get_singleton();
 	EditorDebuggerNode *debugger = EditorDebuggerNode::get_singleton();
 
 
 	if (p_pressed) {
 	if (p_pressed) {
-		debugger->set_camera_override(ScriptEditorDebugger::OVERRIDE_2D);
+		debugger->set_camera_override(EditorDebuggerNode::OVERRIDE_2D);
 	} else {
 	} else {
-		debugger->set_camera_override(ScriptEditorDebugger::OVERRIDE_NONE);
+		debugger->set_camera_override(EditorDebuggerNode::OVERRIDE_NONE);
 	}
 	}
 }
 }
 
 

+ 0 - 1
editor/plugins/script_editor_plugin.cpp

@@ -37,7 +37,6 @@
 #include "core/os/os.h"
 #include "core/os/os.h"
 #include "core/project_settings.h"
 #include "core/project_settings.h"
 #include "editor/debugger/editor_debugger_node.h"
 #include "editor/debugger/editor_debugger_node.h"
-#include "editor/debugger/script_editor_debugger.h"
 #include "editor/editor_node.h"
 #include "editor/editor_node.h"
 #include "editor/editor_run_script.h"
 #include "editor/editor_run_script.h"
 #include "editor/editor_scale.h"
 #include "editor/editor_scale.h"

+ 5 - 5
editor/plugins/spatial_editor_plugin.cpp

@@ -4487,12 +4487,12 @@ void SpatialEditor::_menu_item_toggled(bool pressed, int p_option) {
 		case MENU_TOOL_OVERRIDE_CAMERA: {
 		case MENU_TOOL_OVERRIDE_CAMERA: {
 			EditorDebuggerNode *const debugger = EditorDebuggerNode::get_singleton();
 			EditorDebuggerNode *const debugger = EditorDebuggerNode::get_singleton();
 
 
+			using Override = EditorDebuggerNode::CameraOverride;
 			if (pressed) {
 			if (pressed) {
-				using Override = ScriptEditorDebugger::CameraOverride;
 
 
 				debugger->set_camera_override((Override)(Override::OVERRIDE_3D_1 + camera_override_viewport_id));
 				debugger->set_camera_override((Override)(Override::OVERRIDE_3D_1 + camera_override_viewport_id));
 			} else {
 			} else {
-				debugger->set_camera_override(ScriptEditorDebugger::OVERRIDE_NONE);
+				debugger->set_camera_override(Override::OVERRIDE_NONE);
 			}
 			}
 
 
 		} break;
 		} break;
@@ -4545,8 +4545,8 @@ void SpatialEditor::_update_camera_override_viewport(Object *p_viewport) {
 	EditorDebuggerNode *const debugger = EditorDebuggerNode::get_singleton();
 	EditorDebuggerNode *const debugger = EditorDebuggerNode::get_singleton();
 
 
 	camera_override_viewport_id = current_viewport->index;
 	camera_override_viewport_id = current_viewport->index;
-	if (debugger->get_camera_override() >= ScriptEditorDebugger::OVERRIDE_3D_1) {
-		using Override = ScriptEditorDebugger::CameraOverride;
+	if (debugger->get_camera_override() >= EditorDebuggerNode::OVERRIDE_3D_1) {
+		using Override = EditorDebuggerNode::CameraOverride;
 
 
 		debugger->set_camera_override((Override)(Override::OVERRIDE_3D_1 + camera_override_viewport_id));
 		debugger->set_camera_override((Override)(Override::OVERRIDE_3D_1 + camera_override_viewport_id));
 	}
 	}
@@ -5503,7 +5503,7 @@ void SpatialEditor::_notification(int p_what) {
 		if (!is_visible() && tool_option_button[TOOL_OPT_OVERRIDE_CAMERA]->is_pressed()) {
 		if (!is_visible() && tool_option_button[TOOL_OPT_OVERRIDE_CAMERA]->is_pressed()) {
 			EditorDebuggerNode *debugger = EditorDebuggerNode::get_singleton();
 			EditorDebuggerNode *debugger = EditorDebuggerNode::get_singleton();
 
 
-			debugger->set_camera_override(ScriptEditorDebugger::OVERRIDE_NONE);
+			debugger->set_camera_override(EditorDebuggerNode::OVERRIDE_NONE);
 			tool_option_button[TOOL_OPT_OVERRIDE_CAMERA]->set_pressed(false);
 			tool_option_button[TOOL_OPT_OVERRIDE_CAMERA]->set_pressed(false);
 		}
 		}
 	}
 	}

+ 1 - 1
modules/mono/mono_gd/gd_mono_utils.cpp

@@ -39,7 +39,7 @@
 #include "core/reference.h"
 #include "core/reference.h"
 
 
 #ifdef TOOLS_ENABLED
 #ifdef TOOLS_ENABLED
-#include "editor/debugger/script_editor_debugger.h"
+#include "editor/debugger/editor_debugger_node.h"
 #endif
 #endif
 
 
 #include "../csharp_script.h"
 #include "../csharp_script.h"