2023-01-05 12:25:55 +00:00
/**************************************************************************/
/* script_editor_debugger.cpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* 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. */
/**************************************************************************/
2018-01-04 23:50:27 +00:00
2014-02-13 21:03:28 +00:00
# include "script_editor_debugger.h"
2017-01-16 07:04:19 +00:00
2020-11-07 22:33:38 +00:00
# include "core/config/project_settings.h"
2020-03-08 11:21:08 +00:00
# include "core/debugger/debugger_marshalls.h"
2020-05-01 16:23:51 +00:00
# include "core/debugger/remote_debugger.h"
2018-09-28 17:08:31 +00:00
# include "core/io/marshalls.h"
2020-11-07 22:33:38 +00:00
# include "core/string/ustring.h"
2021-04-18 00:07:05 +00:00
# include "core/version.h"
2021-06-04 18:39:38 +00:00
# include "editor/debugger/debug_adapter/debug_adapter_protocol.h"
2020-06-04 13:18:57 +00:00
# include "editor/debugger/editor_performance_profiler.h"
2020-03-08 11:21:08 +00:00
# include "editor/debugger/editor_profiler.h"
# include "editor/debugger/editor_visual_profiler.h"
2023-03-24 18:38:08 +00:00
# include "editor/editor_file_system.h"
2019-09-20 20:58:06 +00:00
# include "editor/editor_log.h"
2020-02-07 01:52:05 +00:00
# include "editor/editor_node.h"
2022-03-29 03:29:15 +00:00
# include "editor/editor_property_name_processor.h"
2020-02-07 01:52:05 +00:00
# include "editor/editor_scale.h"
# include "editor/editor_settings.h"
2023-04-07 16:59:49 +00:00
# include "editor/gui/editor_file_dialog.h"
2022-11-19 11:45:49 +00:00
# include "editor/inspector_dock.h"
2020-02-11 13:01:43 +00:00
# include "editor/plugins/canvas_item_editor_plugin.h"
2020-05-18 14:55:49 +00:00
# include "editor/plugins/editor_debugger_plugin.h"
2020-03-27 07:44:44 +00:00
# include "editor/plugins/node_3d_editor_plugin.h"
2014-02-13 21:03:28 +00:00
# include "main/performance.h"
2020-03-26 21:49:16 +00:00
# include "scene/3d/camera_3d.h"
2022-10-05 15:50:19 +00:00
# include "scene/debugger/scene_debugger.h"
2014-02-13 21:03:28 +00:00
# include "scene/gui/dialogs.h"
2022-11-19 11:45:49 +00:00
# include "scene/gui/grid_container.h"
2014-02-13 21:03:28 +00:00
# include "scene/gui/label.h"
# include "scene/gui/line_edit.h"
# include "scene/gui/margin_container.h"
# include "scene/gui/rich_text_label.h"
# include "scene/gui/separator.h"
# include "scene/gui/split_container.h"
# include "scene/gui/tab_container.h"
# include "scene/gui/texture_button.h"
# include "scene/gui/tree.h"
2018-02-21 15:07:49 +00:00
# include "scene/resources/packed_scene.h"
2022-02-06 01:29:08 +00:00
# include "servers/debugger/servers_debugger.h"
2020-03-03 13:36:29 +00:00
# include "servers/display_server.h"
2014-02-13 21:03:28 +00:00
2020-02-24 05:21:15 +00:00
using CameraOverride = EditorDebuggerNode : : CameraOverride ;
2023-04-29 15:20:38 +00:00
void ScriptEditorDebugger : : _put_msg ( String p_message , Array p_data , uint64_t p_thread_id ) {
ERR_FAIL_COND ( p_thread_id = = Thread : : UNASSIGNED_ID ) ;
2020-02-07 01:52:05 +00:00
if ( is_session_active ( ) ) {
Array msg ;
msg . push_back ( p_message ) ;
2023-04-29 15:20:38 +00:00
msg . push_back ( p_thread_id ) ;
2020-02-07 01:52:05 +00:00
msg . push_back ( p_data ) ;
2020-02-24 05:21:15 +00:00
peer - > put_message ( msg ) ;
2017-10-17 14:37:25 +00:00
}
2020-02-07 01:52:05 +00:00
}
2016-05-22 22:28:37 +00:00
2018-02-13 16:46:45 +00:00
void ScriptEditorDebugger : : debug_copy ( ) {
String msg = reason - > get_text ( ) ;
2021-12-09 09:42:46 +00:00
if ( msg . is_empty ( ) ) {
2018-02-13 16:46:45 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2020-03-03 13:36:29 +00:00
DisplayServer : : get_singleton ( ) - > clipboard_set ( msg ) ;
2018-02-13 16:46:45 +00:00
}
2019-07-29 18:09:22 +00:00
void ScriptEditorDebugger : : debug_skip_breakpoints ( ) {
skip_breakpoints_value = ! skip_breakpoints_value ;
2020-05-14 14:41:43 +00:00
if ( skip_breakpoints_value ) {
2021-07-17 21:22:52 +00:00
skip_breakpoints - > set_icon ( get_theme_icon ( SNAME ( " DebugSkipBreakpointsOn " ) , SNAME ( " EditorIcons " ) ) ) ;
2020-05-14 14:41:43 +00:00
} else {
2021-07-17 21:22:52 +00:00
skip_breakpoints - > set_icon ( get_theme_icon ( SNAME ( " DebugSkipBreakpointsOff " ) , SNAME ( " EditorIcons " ) ) ) ;
2020-05-14 14:41:43 +00:00
}
2019-07-29 18:09:22 +00:00
2020-02-07 01:52:05 +00:00
Array msg ;
msg . push_back ( skip_breakpoints_value ) ;
2023-04-29 15:20:38 +00:00
_put_msg ( " set_skip_breakpoints " , msg , debugging_thread_id ! = Thread : : UNASSIGNED_ID ? debugging_thread_id : Thread : : MAIN_ID ) ;
2019-07-29 18:09:22 +00:00
}
2014-02-13 21:03:28 +00:00
void ScriptEditorDebugger : : debug_next ( ) {
2023-04-29 15:20:38 +00:00
ERR_FAIL_COND ( ! is_breaked ( ) ) ;
2020-02-07 01:52:05 +00:00
2023-04-29 15:20:38 +00:00
_put_msg ( " next " , Array ( ) , debugging_thread_id ) ;
2019-04-22 16:20:27 +00:00
_clear_execution ( ) ;
2014-02-13 21:03:28 +00:00
}
2020-05-14 12:29:06 +00:00
2014-02-13 21:03:28 +00:00
void ScriptEditorDebugger : : debug_step ( ) {
2023-04-29 15:20:38 +00:00
ERR_FAIL_COND ( ! is_breaked ( ) ) ;
2014-02-13 21:03:28 +00:00
2023-04-29 15:20:38 +00:00
_put_msg ( " step " , Array ( ) , debugging_thread_id ) ;
2019-04-22 16:20:27 +00:00
_clear_execution ( ) ;
2014-02-13 21:03:28 +00:00
}
void ScriptEditorDebugger : : debug_break ( ) {
2023-04-29 15:20:38 +00:00
ERR_FAIL_COND ( is_breaked ( ) ) ;
2014-02-13 21:03:28 +00:00
2020-02-07 01:52:05 +00:00
_put_msg ( " break " , Array ( ) ) ;
2014-02-13 21:03:28 +00:00
}
void ScriptEditorDebugger : : debug_continue ( ) {
2023-04-29 15:20:38 +00:00
ERR_FAIL_COND ( ! is_breaked ( ) ) ;
2014-02-13 21:03:28 +00:00
2020-02-07 01:52:05 +00:00
// Allow focus stealing only if we actually run this client for security.
2020-05-14 14:41:43 +00:00
if ( remote_pid & & EditorNode : : get_singleton ( ) - > has_child_process ( remote_pid ) ) {
2020-03-03 13:36:29 +00:00
DisplayServer : : get_singleton ( ) - > enable_for_stealing_focus ( remote_pid ) ;
2020-05-14 14:41:43 +00:00
}
2016-09-14 02:02:18 +00:00
2019-04-22 16:20:27 +00:00
_clear_execution ( ) ;
2023-04-29 15:20:38 +00:00
_put_msg ( " continue " , Array ( ) , debugging_thread_id ) ;
2022-02-06 16:18:44 +00:00
_put_msg ( " servers:foreground " , Array ( ) ) ;
2014-02-13 21:03:28 +00:00
}
2020-02-07 01:52:05 +00:00
void ScriptEditorDebugger : : update_tabs ( ) {
if ( error_count = = 0 & & warning_count = = 0 ) {
errors_tab - > set_name ( TTR ( " Errors " ) ) ;
2022-03-02 14:37:10 +00:00
tabs - > set_tab_icon ( tabs - > get_tab_idx_from_control ( errors_tab ) , Ref < Texture2D > ( ) ) ;
2016-05-22 22:28:37 +00:00
} else {
2020-02-07 01:52:05 +00:00
errors_tab - > set_name ( TTR ( " Errors " ) + " ( " + itos ( error_count + warning_count ) + " ) " ) ;
2020-05-09 13:29:13 +00:00
if ( error_count > = 1 & & warning_count > = 1 ) {
2022-03-02 14:37:10 +00:00
tabs - > set_tab_icon ( tabs - > get_tab_idx_from_control ( errors_tab ) , get_theme_icon ( SNAME ( " ErrorWarning " ) , SNAME ( " EditorIcons " ) ) ) ;
2020-05-09 13:29:13 +00:00
} else if ( error_count > = 1 ) {
2022-03-02 14:37:10 +00:00
tabs - > set_tab_icon ( tabs - > get_tab_idx_from_control ( errors_tab ) , get_theme_icon ( SNAME ( " Error " ) , SNAME ( " EditorIcons " ) ) ) ;
2020-05-09 13:29:13 +00:00
} else {
2022-03-02 14:37:10 +00:00
tabs - > set_tab_icon ( tabs - > get_tab_idx_from_control ( errors_tab ) , get_theme_icon ( SNAME ( " Warning " ) , SNAME ( " EditorIcons " ) ) ) ;
2020-02-07 01:52:05 +00:00
}
2016-05-22 22:28:37 +00:00
}
}
2020-02-22 04:04:55 +00:00
void ScriptEditorDebugger : : clear_style ( ) {
2022-02-08 09:14:58 +00:00
tabs - > remove_theme_style_override ( " panel " ) ;
2020-02-22 04:04:55 +00:00
}
2020-02-07 01:52:05 +00:00
void ScriptEditorDebugger : : save_node ( ObjectID p_id , const String & p_file ) {
Array msg ;
msg . push_back ( p_id ) ;
msg . push_back ( p_file ) ;
2020-03-08 11:21:08 +00:00
_put_msg ( " scene:save_node " , msg ) ;
2020-02-07 01:52:05 +00:00
}
2016-05-22 22:28:37 +00:00
2020-02-07 01:52:05 +00:00
void ScriptEditorDebugger : : _file_selected ( const String & p_file ) {
2020-03-17 12:46:18 +00:00
switch ( file_dialog_purpose ) {
case SAVE_MONITORS_CSV : {
Error err ;
2022-03-23 09:08:58 +00:00
Ref < FileAccess > file = FileAccess : : open ( p_file , FileAccess : : WRITE , & err ) ;
2016-05-22 22:28:37 +00:00
2020-03-17 12:46:18 +00:00
if ( err ! = OK ) {
ERR_PRINT ( " Failed to open " + p_file ) ;
return ;
}
Vector < String > line ;
line . resize ( Performance : : MONITOR_MAX ) ;
2016-05-22 22:28:37 +00:00
2020-03-17 12:46:18 +00:00
// signatures
for ( int i = 0 ; i < Performance : : MONITOR_MAX ; i + + ) {
line . write [ i ] = Performance : : get_singleton ( ) - > get_monitor_name ( Performance : : Monitor ( i ) ) ;
}
file - > store_csv_line ( line ) ;
2016-05-22 22:28:37 +00:00
2020-03-17 12:46:18 +00:00
// values
2020-06-04 13:18:57 +00:00
Vector < List < float > : : Element * > iterators ;
iterators . resize ( Performance : : MONITOR_MAX ) ;
bool continue_iteration = false ;
for ( int i = 0 ; i < Performance : : MONITOR_MAX ; i + + ) {
iterators . write [ i ] = performance_profiler - > get_monitor_data ( Performance : : get_singleton ( ) - > get_monitor_name ( Performance : : Monitor ( i ) ) ) - > back ( ) ;
continue_iteration = continue_iteration | | iterators [ i ] ;
}
while ( continue_iteration ) {
continue_iteration = false ;
for ( int i = 0 ; i < Performance : : MONITOR_MAX ; i + + ) {
if ( iterators [ i ] ) {
line . write [ i ] = String : : num_real ( iterators [ i ] - > get ( ) ) ;
iterators . write [ i ] = iterators [ i ] - > prev ( ) ;
} else {
line . write [ i ] = " " ;
}
continue_iteration = continue_iteration | | iterators [ i ] ;
2020-03-17 12:46:18 +00:00
}
file - > store_csv_line ( line ) ;
}
file - > store_string ( " \n " ) ;
Vector < Vector < String > > profiler_data = profiler - > get_data_as_csv ( ) ;
for ( int i = 0 ; i < profiler_data . size ( ) ; i + + ) {
file - > store_csv_line ( profiler_data [ i ] ) ;
}
} break ;
case SAVE_VRAM_CSV : {
Error err ;
2022-03-23 09:08:58 +00:00
Ref < FileAccess > file = FileAccess : : open ( p_file , FileAccess : : WRITE , & err ) ;
2018-02-21 15:07:49 +00:00
2020-03-17 12:46:18 +00:00
if ( err ! = OK ) {
ERR_PRINT ( " Failed to open " + p_file ) ;
return ;
}
Vector < String > headers ;
headers . resize ( vmem_tree - > get_columns ( ) ) ;
for ( int i = 0 ; i < vmem_tree - > get_columns ( ) ; + + i ) {
headers . write [ i ] = vmem_tree - > get_column_title ( i ) ;
}
file - > store_csv_line ( headers ) ;
if ( vmem_tree - > get_root ( ) ) {
2021-03-07 20:07:30 +00:00
TreeItem * ti = vmem_tree - > get_root ( ) - > get_first_child ( ) ;
2020-03-17 12:46:18 +00:00
while ( ti ) {
Vector < String > values ;
values . resize ( vmem_tree - > get_columns ( ) ) ;
for ( int i = 0 ; i < vmem_tree - > get_columns ( ) ; + + i ) {
values . write [ i ] = ti - > get_text ( i ) ;
}
file - > store_csv_line ( values ) ;
ti = ti - > get_next ( ) ;
}
}
} break ;
2020-02-07 01:52:05 +00:00
}
2018-02-21 15:07:49 +00:00
}
2020-02-07 01:52:05 +00:00
void ScriptEditorDebugger : : request_remote_tree ( ) {
2020-03-08 11:21:08 +00:00
_put_msg ( " scene:request_scene_tree " , Array ( ) ) ;
2020-02-07 01:52:05 +00:00
}
2019-02-18 00:25:26 +00:00
2020-02-07 01:52:05 +00:00
const SceneDebuggerTree * ScriptEditorDebugger : : get_remote_tree ( ) {
return scene_tree ;
2018-02-21 15:07:49 +00:00
}
2020-02-07 01:52:05 +00:00
void ScriptEditorDebugger : : update_remote_object ( ObjectID p_obj_id , const String & p_prop , const Variant & p_value ) {
2016-05-22 22:28:37 +00:00
Array msg ;
2020-02-07 01:52:05 +00:00
msg . push_back ( p_obj_id ) ;
2016-05-22 22:28:37 +00:00
msg . push_back ( p_prop ) ;
msg . push_back ( p_value ) ;
2020-03-08 11:21:08 +00:00
_put_msg ( " scene:set_object_property " , msg ) ;
2016-05-22 22:28:37 +00:00
}
2020-02-07 01:52:05 +00:00
void ScriptEditorDebugger : : request_remote_object ( ObjectID p_obj_id ) {
ERR_FAIL_COND ( p_obj_id . is_null ( ) ) ;
2016-05-22 22:28:37 +00:00
Array msg ;
2020-02-07 01:52:05 +00:00
msg . push_back ( p_obj_id ) ;
2020-03-08 11:21:08 +00:00
_put_msg ( " scene:inspect_object " , msg ) ;
2016-05-22 22:28:37 +00:00
}
2020-02-07 01:52:05 +00:00
Object * ScriptEditorDebugger : : get_remote_object ( ObjectID p_id ) {
return inspector - > get_object ( p_id ) ;
}
2019-07-30 13:11:13 +00:00
2020-02-07 01:52:05 +00:00
void ScriptEditorDebugger : : _remote_object_selected ( ObjectID p_id ) {
2021-07-17 21:22:52 +00:00
emit_signal ( SNAME ( " remote_object_requested " ) , p_id ) ;
2020-02-07 01:52:05 +00:00
}
2018-10-25 08:39:02 +00:00
2020-02-07 01:52:05 +00:00
void ScriptEditorDebugger : : _remote_object_edited ( ObjectID p_id , const String & p_prop , const Variant & p_value ) {
update_remote_object ( p_id , p_prop , p_value ) ;
request_remote_object ( p_id ) ;
}
2018-10-25 08:39:02 +00:00
2020-02-07 01:52:05 +00:00
void ScriptEditorDebugger : : _remote_object_property_updated ( ObjectID p_id , const String & p_property ) {
2021-07-17 21:22:52 +00:00
emit_signal ( SNAME ( " remote_object_property_updated " ) , p_id , p_property ) ;
2018-10-25 08:39:02 +00:00
}
2015-10-21 12:50:44 +00:00
void ScriptEditorDebugger : : _video_mem_request ( ) {
2022-02-06 01:29:08 +00:00
_put_msg ( " servers:memory " , Array ( ) ) ;
2015-10-21 12:50:44 +00:00
}
2020-03-17 12:46:18 +00:00
void ScriptEditorDebugger : : _video_mem_export ( ) {
file_dialog - > set_file_mode ( EditorFileDialog : : FILE_MODE_SAVE_FILE ) ;
file_dialog - > set_access ( EditorFileDialog : : ACCESS_FILESYSTEM ) ;
file_dialog - > clear_filters ( ) ;
file_dialog_purpose = SAVE_VRAM_CSV ;
2020-07-11 16:45:19 +00:00
file_dialog - > popup_file_dialog ( ) ;
2020-03-17 12:46:18 +00:00
}
2014-02-13 21:03:28 +00:00
Size2 ScriptEditorDebugger : : get_minimum_size ( ) const {
2019-11-18 08:42:28 +00:00
Size2 ms = MarginContainer : : get_minimum_size ( ) ;
2018-10-20 20:05:11 +00:00
ms . y = MAX ( ms . y , 250 * EDSCALE ) ;
2014-02-13 21:03:28 +00:00
return ms ;
}
2019-05-05 07:59:10 +00:00
2023-04-29 15:20:38 +00:00
void ScriptEditorDebugger : : _thread_debug_enter ( uint64_t p_thread_id ) {
ERR_FAIL_COND ( ! threads_debugged . has ( p_thread_id ) ) ;
ThreadDebugged & td = threads_debugged [ p_thread_id ] ;
_set_reason_text ( td . error , MESSAGE_ERROR ) ;
emit_signal ( SNAME ( " breaked " ) , true , td . can_debug , td . error , td . has_stackdump ) ;
if ( ! td . error . is_empty ( ) ) {
tabs - > set_current_tab ( 0 ) ;
}
inspector - > clear_cache ( ) ; // Take a chance to force remote objects update.
_put_msg ( " get_stack_dump " , Array ( ) , p_thread_id ) ;
}
void ScriptEditorDebugger : : _select_thread ( int p_index ) {
debugging_thread_id = threads - > get_item_metadata ( threads - > get_selected ( ) ) ;
_thread_debug_enter ( debugging_thread_id ) ;
}
void ScriptEditorDebugger : : _parse_message ( const String & p_msg , uint64_t p_thread_id , const Array & p_data ) {
2021-07-20 11:24:56 +00:00
emit_signal ( SNAME ( " debug_data " ) , p_msg , p_data ) ;
2014-02-13 21:03:28 +00:00
if ( p_msg = = " debug_enter " ) {
2023-04-29 15:20:38 +00:00
ERR_FAIL_COND ( p_data . size ( ) ! = 4 ) ;
ThreadDebugged td ;
td . name = p_data [ 3 ] ;
td . error = p_data [ 1 ] ;
td . can_debug = p_data [ 0 ] ;
td . has_stackdump = p_data [ 2 ] ;
td . thread_id = p_thread_id ;
static uint32_t order_inc = 0 ;
td . debug_order = order_inc + + ;
threads_debugged . insert ( p_thread_id , td ) ;
if ( threads_debugged . size ( ) = = 1 ) {
// First thread that requests debug
debugging_thread_id = p_thread_id ;
_thread_debug_enter ( p_thread_id ) ;
can_request_idle_draw = true ;
if ( is_move_to_foreground ( ) ) {
DisplayServer : : get_singleton ( ) - > window_move_to_foreground ( ) ;
}
profiler - > set_enabled ( false , false ) ;
visual_profiler - > set_enabled ( false ) ;
2016-07-17 12:17:35 +00:00
}
2023-04-29 15:20:38 +00:00
_update_buttons_state ( ) ;
2016-01-17 23:03:57 +00:00
2014-02-13 21:03:28 +00:00
} else if ( p_msg = = " debug_exit " ) {
2023-04-29 15:20:38 +00:00
threads_debugged . erase ( p_thread_id ) ;
if ( p_thread_id = = debugging_thread_id ) {
_clear_execution ( ) ;
if ( threads_debugged . size ( ) = = 0 ) {
debugging_thread_id = Thread : : UNASSIGNED_ID ;
} else {
// Find next thread to debug.
uint32_t min_order = 0xFFFFFFFF ;
uint64_t next_thread = Thread : : UNASSIGNED_ID ;
for ( KeyValue < uint64_t , ThreadDebugged > T : threads_debugged ) {
if ( T . value . debug_order < min_order ) {
min_order = T . value . debug_order ;
next_thread = T . key ;
}
}
debugging_thread_id = next_thread ;
}
2022-12-16 15:35:44 +00:00
2023-04-29 15:20:38 +00:00
if ( debugging_thread_id = = Thread : : UNASSIGNED_ID ) {
// Nothing else to debug.
profiler - > set_enabled ( true , false ) ;
profiler - > disable_seeking ( ) ;
2022-12-16 15:35:44 +00:00
2023-04-29 15:20:38 +00:00
visual_profiler - > set_enabled ( true ) ;
_set_reason_text ( TTR ( " Execution resumed. " ) , MESSAGE_SUCCESS ) ;
emit_signal ( SNAME ( " breaked " ) , false , false , " " , false ) ;
_update_buttons_state ( ) ;
} else {
_thread_debug_enter ( debugging_thread_id ) ;
}
} else {
_update_buttons_state ( ) ;
}
2022-12-16 15:35:44 +00:00
2020-03-08 11:21:08 +00:00
} else if ( p_msg = = " set_pid " ) {
2020-02-07 01:52:05 +00:00
ERR_FAIL_COND ( p_data . size ( ) < 1 ) ;
remote_pid = p_data [ 0 ] ;
2020-03-08 11:21:08 +00:00
} else if ( p_msg = = " scene:click_ctrl " ) {
2020-02-07 01:52:05 +00:00
ERR_FAIL_COND ( p_data . size ( ) < 2 ) ;
2014-02-13 21:03:28 +00:00
clicked_ctrl - > set_text ( p_data [ 0 ] ) ;
clicked_ctrl_type - > set_text ( p_data [ 1 ] ) ;
2020-03-08 11:21:08 +00:00
} else if ( p_msg = = " scene:scene_tree " ) {
2020-02-07 01:52:05 +00:00
scene_tree - > nodes . clear ( ) ;
scene_tree - > deserialize ( p_data ) ;
2021-07-17 21:22:52 +00:00
emit_signal ( SNAME ( " remote_tree_updated " ) ) ;
2020-02-07 01:52:05 +00:00
_update_buttons_state ( ) ;
2020-03-08 11:21:08 +00:00
} else if ( p_msg = = " scene:inspect_object " ) {
2020-02-07 01:52:05 +00:00
ObjectID id = inspector - > add_object ( p_data ) ;
2020-05-14 14:41:43 +00:00
if ( id . is_valid ( ) ) {
2021-07-17 21:22:52 +00:00
emit_signal ( SNAME ( " remote_object_updated " ) , id ) ;
2020-05-14 14:41:43 +00:00
}
2022-02-06 01:29:08 +00:00
} else if ( p_msg = = " servers:memory_usage " ) {
2015-10-21 12:50:44 +00:00
vmem_tree - > clear ( ) ;
TreeItem * root = vmem_tree - > create_item ( ) ;
2022-02-06 01:29:08 +00:00
ServersDebugger : : ResourceUsage usage ;
2020-02-07 01:52:05 +00:00
usage . deserialize ( p_data ) ;
2015-10-21 12:50:44 +00:00
2021-03-05 21:48:11 +00:00
uint64_t total = 0 ;
2015-10-21 12:50:44 +00:00
2022-02-06 01:29:08 +00:00
for ( const ServersDebugger : : ResourceInfo & E : usage . infos ) {
2015-10-21 12:50:44 +00:00
TreeItem * it = vmem_tree - > create_item ( root ) ;
2021-07-16 03:45:57 +00:00
String type = E . type ;
int bytes = E . vram ;
it - > set_text ( 0 , E . path ) ;
2020-02-07 01:52:05 +00:00
it - > set_text ( 1 , type ) ;
2021-07-16 03:45:57 +00:00
it - > set_text ( 2 , E . format ) ;
2020-02-07 01:52:05 +00:00
it - > set_text ( 3 , String : : humanize_size ( bytes ) ) ;
2015-10-21 12:50:44 +00:00
total + = bytes ;
2017-03-05 15:44:50 +00:00
2021-07-17 21:22:52 +00:00
if ( has_theme_icon ( type , SNAME ( " EditorIcons " ) ) ) {
it - > set_icon ( 0 , get_theme_icon ( type , SNAME ( " EditorIcons " ) ) ) ;
2020-05-14 14:41:43 +00:00
}
2015-10-21 12:50:44 +00:00
}
2022-08-25 10:42:17 +00:00
vmem_total - > set_tooltip_text ( TTR ( " Bytes: " ) + " " + itos ( total ) ) ;
2015-10-21 12:50:44 +00:00
vmem_total - > set_text ( String : : humanize_size ( total ) ) ;
2023-02-07 11:10:28 +00:00
} else if ( p_msg = = " servers:drawn " ) {
can_request_idle_draw = true ;
2014-02-13 21:03:28 +00:00
} else if ( p_msg = = " stack_dump " ) {
2020-03-08 11:21:08 +00:00
DebuggerMarshalls : : ScriptStackDump stack ;
2020-02-07 01:52:05 +00:00
stack . deserialize ( p_data ) ;
2014-02-13 21:03:28 +00:00
stack_dump - > clear ( ) ;
2020-02-07 01:52:05 +00:00
inspector - > clear_stack_variables ( ) ;
2014-02-13 21:03:28 +00:00
TreeItem * r = stack_dump - > create_item ( ) ;
2021-06-04 18:39:38 +00:00
Array stack_dump_info ;
2020-02-07 01:52:05 +00:00
for ( int i = 0 ; i < stack . frames . size ( ) ; i + + ) {
2014-02-13 21:03:28 +00:00
TreeItem * s = stack_dump - > create_item ( r ) ;
2020-02-07 01:52:05 +00:00
Dictionary d ;
2014-02-13 21:03:28 +00:00
d [ " frame " ] = i ;
2020-02-07 01:52:05 +00:00
d [ " file " ] = stack . frames [ i ] . file ;
d [ " function " ] = stack . frames [ i ] . func ;
d [ " line " ] = stack . frames [ i ] . line ;
2021-06-04 18:39:38 +00:00
stack_dump_info . push_back ( d ) ;
2014-02-13 21:03:28 +00:00
s - > set_metadata ( 0 , d ) ;
2022-02-13 12:41:29 +00:00
String line = itos ( i ) + " - " + String ( d [ " file " ] ) + " : " + itos ( d [ " line " ] ) + " - at function: " + String ( d [ " function " ] ) ;
2014-02-13 21:03:28 +00:00
s - > set_text ( 0 , line ) ;
2020-05-14 14:41:43 +00:00
if ( i = = 0 ) {
2014-02-13 21:03:28 +00:00
s - > select ( 0 ) ;
2020-05-14 14:41:43 +00:00
}
2014-02-13 21:03:28 +00:00
}
2021-08-20 12:48:34 +00:00
emit_signal ( SNAME ( " stack_dump " ) , stack_dump_info ) ;
2014-02-13 21:03:28 +00:00
} else if ( p_msg = = " stack_frame_vars " ) {
2020-02-07 01:52:05 +00:00
inspector - > clear_stack_variables ( ) ;
2021-06-04 18:39:38 +00:00
ERR_FAIL_COND ( p_data . size ( ) ! = 1 ) ;
2021-08-20 12:48:34 +00:00
emit_signal ( SNAME ( " stack_frame_vars " ) , p_data [ 0 ] ) ;
2020-02-07 01:52:05 +00:00
} else if ( p_msg = = " stack_frame_var " ) {
inspector - > add_stack_variable ( p_data ) ;
2021-08-20 12:48:34 +00:00
emit_signal ( SNAME ( " stack_frame_var " ) , p_data ) ;
2014-02-13 21:03:28 +00:00
} else if ( p_msg = = " output " ) {
2020-05-01 16:23:51 +00:00
ERR_FAIL_COND ( p_data . size ( ) ! = 2 ) ;
2020-03-08 11:21:08 +00:00
ERR_FAIL_COND ( p_data [ 0 ] . get_type ( ) ! = Variant : : PACKED_STRING_ARRAY ) ;
2020-05-01 16:23:51 +00:00
Vector < String > output_strings = p_data [ 0 ] ;
ERR_FAIL_COND ( p_data [ 1 ] . get_type ( ) ! = Variant : : PACKED_INT32_ARRAY ) ;
Vector < int > output_types = p_data [ 1 ] ;
ERR_FAIL_COND ( output_strings . size ( ) ! = output_types . size ( ) ) ;
for ( int i = 0 ; i < output_strings . size ( ) ; i + + ) {
RemoteDebugger : : MessageType type = ( RemoteDebugger : : MessageType ) ( int ) ( output_types [ i ] ) ;
EditorLog : : MessageType msg_type ;
switch ( type ) {
case RemoteDebugger : : MESSAGE_TYPE_LOG : {
msg_type = EditorLog : : MSG_TYPE_STD ;
} break ;
2022-06-30 19:33:59 +00:00
case RemoteDebugger : : MESSAGE_TYPE_LOG_RICH : {
msg_type = EditorLog : : MSG_TYPE_STD_RICH ;
} break ;
2020-05-01 16:23:51 +00:00
case RemoteDebugger : : MESSAGE_TYPE_ERROR : {
msg_type = EditorLog : : MSG_TYPE_ERROR ;
} break ;
default : {
WARN_PRINT ( " Unhandled script debugger message type: " + itos ( type ) ) ;
msg_type = EditorLog : : MSG_TYPE_STD ;
} break ;
}
EditorNode : : get_log ( ) - > add_message ( output_strings [ i ] , msg_type ) ;
2021-08-20 12:48:34 +00:00
emit_signal ( SNAME ( " output " ) , output_strings [ i ] ) ;
2020-05-01 16:23:51 +00:00
}
2020-03-08 11:21:08 +00:00
} else if ( p_msg = = " performance:profile_frame " ) {
2020-06-04 13:18:57 +00:00
Vector < float > frame_data ;
frame_data . resize ( p_data . size ( ) ) ;
2020-02-07 01:52:05 +00:00
for ( int i = 0 ; i < p_data . size ( ) ; i + + ) {
2020-06-04 13:18:57 +00:00
frame_data . write [ i ] = p_data [ i ] ;
2014-02-13 21:03:28 +00:00
}
2020-06-04 13:18:57 +00:00
performance_profiler - > add_profile_frame ( frame_data ) ;
2020-03-08 11:21:08 +00:00
} else if ( p_msg = = " visual:profile_frame " ) {
2022-02-06 01:29:08 +00:00
ServersDebugger : : VisualProfilerFrame frame ;
2020-03-08 11:21:08 +00:00
frame . deserialize ( p_data ) ;
2019-09-20 20:58:06 +00:00
EditorVisualProfiler : : Metric metric ;
2020-03-08 11:21:08 +00:00
metric . areas . resize ( frame . areas . size ( ) ) ;
metric . frame_number = frame . frame_number ;
2019-09-20 20:58:06 +00:00
metric . valid = true ;
{
EditorVisualProfiler : : Metric : : Area * areas_ptr = metric . areas . ptrw ( ) ;
2020-03-08 11:21:08 +00:00
for ( int i = 0 ; i < frame . areas . size ( ) ; i + + ) {
areas_ptr [ i ] . name = frame . areas [ i ] . name ;
areas_ptr [ i ] . cpu_time = frame . areas [ i ] . cpu_msec ;
areas_ptr [ i ] . gpu_time = frame . areas [ i ] . gpu_msec ;
2019-09-20 20:58:06 +00:00
}
}
visual_profiler - > add_frame_metric ( metric ) ;
2015-08-04 12:47:32 +00:00
} else if ( p_msg = = " error " ) {
2020-03-08 11:21:08 +00:00
DebuggerMarshalls : : OutputError oe ;
2020-02-07 01:52:05 +00:00
ERR_FAIL_COND_MSG ( oe . deserialize ( p_data ) = = false , " Failed to deserialize error message " ) ;
2019-09-25 08:47:41 +00:00
// Format time.
Array time_vals ;
2020-02-07 01:52:05 +00:00
time_vals . push_back ( oe . hr ) ;
time_vals . push_back ( oe . min ) ;
time_vals . push_back ( oe . sec ) ;
time_vals . push_back ( oe . msec ) ;
2015-08-04 12:47:32 +00:00
bool e ;
2020-02-07 01:52:05 +00:00
String time = String ( " %d:%02d:%02d:%04d " ) . sprintf ( time_vals , & e ) ;
2015-08-04 12:47:32 +00:00
2019-09-25 08:47:41 +00:00
// Rest of the error data.
2020-02-07 01:52:05 +00:00
bool source_is_project_file = oe . source_file . begins_with ( " res:// " ) ;
2019-09-25 08:47:41 +00:00
// Metadata to highlight error line in scripts.
Array source_meta ;
2020-02-07 01:52:05 +00:00
source_meta . push_back ( oe . source_file ) ;
source_meta . push_back ( oe . source_line ) ;
2019-09-25 08:47:41 +00:00
// Create error tree to display above error or warning details.
2018-09-08 23:31:49 +00:00
TreeItem * r = error_tree - > get_root ( ) ;
if ( ! r ) {
r = error_tree - > create_item ( ) ;
}
2015-08-04 12:47:32 +00:00
2019-09-25 08:47:41 +00:00
// Also provide the relevant details as tooltip to quickly check without
// uncollapsing the tree.
2020-02-07 01:52:05 +00:00
String tooltip = oe . warning ? TTR ( " Warning: " ) : TTR ( " Error: " ) ;
2019-09-25 08:47:41 +00:00
2018-09-08 23:31:49 +00:00
TreeItem * error = error_tree - > create_item ( r ) ;
2023-03-10 17:16:00 +00:00
if ( oe . warning ) {
error - > set_meta ( " _is_warning " , true ) ;
} else {
error - > set_meta ( " _is_error " , true ) ;
}
2018-09-08 23:31:49 +00:00
error - > set_collapsed ( true ) ;
2015-08-04 12:47:32 +00:00
2022-02-06 14:53:53 +00:00
error - > set_icon ( 0 , get_theme_icon ( oe . warning ? SNAME ( " Warning " ) : SNAME ( " Error " ) , SNAME ( " EditorIcons " ) ) ) ;
2018-09-08 23:31:49 +00:00
error - > set_text ( 0 , time ) ;
2021-11-25 02:58:47 +00:00
error - > set_text_alignment ( 0 , HORIZONTAL_ALIGNMENT_LEFT ) ;
2018-09-08 23:31:49 +00:00
2021-09-23 23:15:24 +00:00
const Color color = get_theme_color ( oe . warning ? SNAME ( " warning_color " ) : SNAME ( " error_color " ) , SNAME ( " Editor " ) ) ;
error - > set_custom_color ( 0 , color ) ;
error - > set_custom_color ( 1 , color ) ;
2019-09-25 08:47:41 +00:00
String error_title ;
2020-10-12 05:35:40 +00:00
if ( oe . callstack . size ( ) > 0 ) {
// If available, use the script's stack in the error title.
2023-01-23 22:18:03 +00:00
error_title = _format_frame_text ( & oe . callstack [ 0 ] ) + " : " ;
2020-12-15 12:04:21 +00:00
} else if ( ! oe . source_func . is_empty ( ) ) {
2020-10-12 05:35:40 +00:00
// Otherwise try to use the C++ source function.
2020-02-07 01:52:05 +00:00
error_title + = oe . source_func + " : " ;
2020-05-14 14:41:43 +00:00
}
2019-09-25 08:47:41 +00:00
// If we have a (custom) error message, use it as title, and add a C++ Error
// item with the original error condition.
2020-12-15 12:04:21 +00:00
error_title + = oe . error_descr . is_empty ( ) ? oe . error : oe . error_descr ;
2019-09-25 08:47:41 +00:00
error - > set_text ( 1 , error_title ) ;
tooltip + = " " + error_title + " \n " ;
2023-01-23 22:18:03 +00:00
// Find the language of the error's source file.
String source_language_name = " C++ " ; // Default value is the old hard-coded one.
const String source_file_extension = oe . source_file . get_extension ( ) ;
for ( int i = 0 ; i < ScriptServer : : get_language_count ( ) ; + + i ) {
ScriptLanguage * script_language = ScriptServer : : get_language ( i ) ;
if ( source_file_extension = = script_language - > get_extension ( ) ) {
source_language_name = script_language - > get_name ( ) ;
break ;
}
}
2020-12-15 12:04:21 +00:00
if ( ! oe . error_descr . is_empty ( ) ) {
2019-09-25 08:47:41 +00:00
// Add item for C++ error condition.
TreeItem * cpp_cond = error_tree - > create_item ( error ) ;
2023-01-23 22:18:03 +00:00
// TRANSLATORS: %s is the name of a language, e.g. C++.
cpp_cond - > set_text ( 0 , " < " + vformat ( TTR ( " %s Error " ) , source_language_name ) + " > " ) ;
2020-02-07 01:52:05 +00:00
cpp_cond - > set_text ( 1 , oe . error ) ;
2021-11-25 02:58:47 +00:00
cpp_cond - > set_text_alignment ( 0 , HORIZONTAL_ALIGNMENT_LEFT ) ;
2023-01-28 11:34:12 +00:00
tooltip + = vformat ( TTR ( " %s Error: " ) , source_language_name ) + " " + oe . error + " \n " ;
2020-05-14 14:41:43 +00:00
if ( source_is_project_file ) {
2019-09-25 08:47:41 +00:00
cpp_cond - > set_metadata ( 0 , source_meta ) ;
2020-05-14 14:41:43 +00:00
}
2019-09-25 08:47:41 +00:00
}
2020-02-07 01:52:05 +00:00
Vector < uint8_t > v ;
v . resize ( 100 ) ;
2018-09-08 23:31:49 +00:00
2019-09-25 08:47:41 +00:00
// Source of the error.
2020-02-07 01:52:05 +00:00
String source_txt = ( source_is_project_file ? oe . source_file . get_file ( ) : oe . source_file ) + " : " + itos ( oe . source_line ) ;
2020-12-15 12:04:21 +00:00
if ( ! oe . source_func . is_empty ( ) ) {
2023-01-23 22:18:03 +00:00
source_txt + = " @ " + oe . source_func ;
if ( ! oe . source_func . ends_with ( " ) " ) ) {
source_txt + = " () " ;
}
2020-05-14 14:41:43 +00:00
}
2015-08-04 12:47:32 +00:00
2019-09-25 08:47:41 +00:00
TreeItem * cpp_source = error_tree - > create_item ( error ) ;
2023-01-23 22:18:03 +00:00
// TRANSLATORS: %s is the name of a language, e.g. C++.
cpp_source - > set_text ( 0 , " < " + vformat ( TTR ( " %s Source " ) , source_language_name ) + " > " ) ;
2019-09-25 08:47:41 +00:00
cpp_source - > set_text ( 1 , source_txt ) ;
2021-11-25 02:58:47 +00:00
cpp_source - > set_text_alignment ( 0 , HORIZONTAL_ALIGNMENT_LEFT ) ;
2023-01-28 11:34:12 +00:00
tooltip + = vformat ( TTR ( " %s Source: " ) , source_language_name ) + " " + source_txt + " \n " ;
2018-09-08 23:31:49 +00:00
2019-09-25 08:47:41 +00:00
// Set metadata to highlight error line in scripts.
2018-09-08 23:31:49 +00:00
if ( source_is_project_file ) {
2019-09-25 08:47:41 +00:00
error - > set_metadata ( 0 , source_meta ) ;
cpp_source - > set_metadata ( 0 , source_meta ) ;
2015-08-04 12:47:32 +00:00
}
2019-09-25 08:47:41 +00:00
// Format stack trace.
// stack_items_count is the number of elements to parse, with 3 items per frame
// of the stack trace (script, method, line).
2020-02-07 01:52:05 +00:00
const ScriptLanguage : : StackInfo * infos = oe . callstack . ptr ( ) ;
for ( unsigned int i = 0 ; i < ( unsigned int ) oe . callstack . size ( ) ; i + + ) {
2018-09-08 23:31:49 +00:00
TreeItem * stack_trace = error_tree - > create_item ( error ) ;
Array meta ;
2020-02-07 01:52:05 +00:00
meta . push_back ( infos [ i ] . file ) ;
meta . push_back ( infos [ i ] . line ) ;
2018-09-08 23:31:49 +00:00
stack_trace - > set_metadata ( 0 , meta ) ;
if ( i = = 0 ) {
stack_trace - > set_text ( 0 , " < " + TTR ( " Stack Trace " ) + " > " ) ;
2021-11-25 02:58:47 +00:00
stack_trace - > set_text_alignment ( 0 , HORIZONTAL_ALIGNMENT_LEFT ) ;
2018-09-08 23:31:49 +00:00
error - > set_metadata ( 0 , meta ) ;
2020-10-12 05:35:40 +00:00
tooltip + = TTR ( " Stack Trace: " ) + " \n " ;
2018-09-08 23:31:49 +00:00
}
2020-10-12 05:35:40 +00:00
2023-01-23 22:18:03 +00:00
String frame_txt = _format_frame_text ( & infos [ i ] ) ;
2020-10-12 05:35:40 +00:00
tooltip + = frame_txt + " \n " ;
stack_trace - > set_text ( 1 , frame_txt ) ;
2018-09-08 23:31:49 +00:00
}
2015-08-04 12:47:32 +00:00
2022-08-29 13:55:49 +00:00
error - > set_tooltip_text ( 0 , tooltip ) ;
error - > set_tooltip_text ( 1 , tooltip ) ;
2020-10-12 05:35:40 +00:00
2021-11-12 19:14:40 +00:00
if ( warning_count = = 0 & & error_count = = 0 ) {
expand_all_button - > set_disabled ( false ) ;
collapse_all_button - > set_disabled ( false ) ;
clear_button - > set_disabled ( false ) ;
}
2020-05-14 14:41:43 +00:00
if ( oe . warning ) {
2018-08-16 05:41:03 +00:00
warning_count + + ;
2020-05-14 14:41:43 +00:00
} else {
2018-08-16 05:41:03 +00:00
error_count + + ;
2020-05-14 14:41:43 +00:00
}
2020-03-08 11:21:08 +00:00
} else if ( p_msg = = " servers:function_signature " ) {
2020-02-07 01:52:05 +00:00
// Cache a profiler signature.
2022-02-06 01:29:08 +00:00
ServersDebugger : : ScriptFunctionSignature sig ;
2020-02-07 01:52:05 +00:00
sig . deserialize ( p_data ) ;
profiler_signature [ sig . id ] = sig . name ;
2020-03-08 11:21:08 +00:00
} else if ( p_msg = = " servers:profile_frame " | | p_msg = = " servers:profile_total " ) {
2016-05-22 00:18:16 +00:00
EditorProfiler : : Metric metric ;
2022-02-06 01:29:08 +00:00
ServersDebugger : : ServersProfilerFrame frame ;
2020-02-07 01:52:05 +00:00
frame . deserialize ( p_data ) ;
2016-05-22 00:18:16 +00:00
metric . valid = true ;
2020-02-07 01:52:05 +00:00
metric . frame_number = frame . frame_number ;
metric . frame_time = frame . frame_time ;
2022-05-05 18:23:47 +00:00
metric . process_time = frame . process_time ;
2020-02-07 01:52:05 +00:00
metric . physics_time = frame . physics_time ;
metric . physics_frame_time = frame . physics_frame_time ;
2016-05-22 00:18:16 +00:00
2020-03-08 11:21:08 +00:00
if ( frame . servers . size ( ) ) {
2016-05-22 00:18:16 +00:00
EditorProfiler : : Metric : : Category frame_time ;
frame_time . signature = " category_frame_time " ;
frame_time . name = " Frame Time " ;
frame_time . total_time = metric . frame_time ;
EditorProfiler : : Metric : : Category : : Item item ;
item . calls = 1 ;
item . line = 0 ;
2018-04-19 11:04:41 +00:00
2017-10-21 14:28:08 +00:00
item . name = " Physics Time " ;
2017-09-30 14:19:07 +00:00
item . total = metric . physics_time ;
2016-05-22 00:18:16 +00:00
item . self = item . total ;
2017-09-30 14:19:07 +00:00
item . signature = " physics_time " ;
2016-05-22 00:18:16 +00:00
frame_time . items . push_back ( item ) ;
2022-05-05 18:23:47 +00:00
item . name = " Process Time " ;
item . total = metric . process_time ;
2016-05-22 00:18:16 +00:00
item . self = item . total ;
2022-05-05 18:23:47 +00:00
item . signature = " process_time " ;
2016-05-22 00:18:16 +00:00
frame_time . items . push_back ( item ) ;
2017-10-21 14:28:08 +00:00
item . name = " Physics Frame Time " ;
2017-09-30 14:19:07 +00:00
item . total = metric . physics_frame_time ;
2016-05-22 00:18:16 +00:00
item . self = item . total ;
2017-09-30 14:19:07 +00:00
item . signature = " physics_frame_time " ;
2016-05-22 00:18:16 +00:00
frame_time . items . push_back ( item ) ;
metric . categories . push_back ( frame_time ) ;
}
2020-03-08 11:21:08 +00:00
for ( int i = 0 ; i < frame . servers . size ( ) ; i + + ) {
2022-02-06 01:29:08 +00:00
const ServersDebugger : : ServerInfo & srv = frame . servers [ i ] ;
2016-05-22 00:18:16 +00:00
EditorProfiler : : Metric : : Category c ;
2020-03-08 11:21:08 +00:00
const String name = srv . name ;
2022-03-29 03:29:15 +00:00
c . name = EditorPropertyNameProcessor : : get_singleton ( ) - > process_name ( name , EditorPropertyNameProcessor : : STYLE_CAPITALIZED ) ;
2020-03-08 11:21:08 +00:00
c . items . resize ( srv . functions . size ( ) ) ;
2016-05-22 00:18:16 +00:00
c . total_time = 0 ;
c . signature = " categ:: " + name ;
2020-03-08 11:21:08 +00:00
for ( int j = 0 ; j < srv . functions . size ( ) ; j + + ) {
2016-05-22 00:18:16 +00:00
EditorProfiler : : Metric : : Category : : Item item ;
item . calls = 1 ;
2018-04-19 11:04:41 +00:00
item . line = 0 ;
2020-03-08 11:21:08 +00:00
item . name = srv . functions [ j ] . name ;
item . self = srv . functions [ j ] . time ;
2016-05-22 00:18:16 +00:00
item . total = item . self ;
item . signature = " categ:: " + name + " :: " + item . name ;
2022-03-29 03:29:15 +00:00
item . name = EditorPropertyNameProcessor : : get_singleton ( ) - > process_name ( item . name , EditorPropertyNameProcessor : : STYLE_CAPITALIZED ) ;
2016-05-22 00:18:16 +00:00
c . total_time + = item . total ;
2020-03-08 11:21:08 +00:00
c . items . write [ j ] = item ;
2016-05-22 00:18:16 +00:00
}
metric . categories . push_back ( c ) ;
}
EditorProfiler : : Metric : : Category funcs ;
2020-02-07 01:52:05 +00:00
funcs . total_time = frame . script_time ;
2020-03-08 11:21:08 +00:00
funcs . items . resize ( frame . script_functions . size ( ) ) ;
2016-05-22 00:18:16 +00:00
funcs . name = " Script Functions " ;
funcs . signature = " script_functions " ;
2020-03-08 11:21:08 +00:00
for ( int i = 0 ; i < frame . script_functions . size ( ) ; i + + ) {
int signature = frame . script_functions [ i ] . sig_id ;
int calls = frame . script_functions [ i ] . call_count ;
float total = frame . script_functions [ i ] . total_time ;
float self = frame . script_functions [ i ] . self_time ;
2016-05-22 00:18:16 +00:00
EditorProfiler : : Metric : : Category : : Item item ;
if ( profiler_signature . has ( signature ) ) {
item . signature = profiler_signature [ signature ] ;
String name = profiler_signature [ signature ] ;
Vector < String > strings = name . split ( " :: " ) ;
if ( strings . size ( ) = = 3 ) {
item . name = strings [ 2 ] ;
item . script = strings [ 0 ] ;
item . line = strings [ 1 ] . to_int ( ) ;
2019-01-25 01:19:06 +00:00
} else if ( strings . size ( ) = = 4 ) { //Built-in scripts have an :: in their name
item . name = strings [ 3 ] ;
item . script = strings [ 0 ] + " :: " + strings [ 1 ] ;
item . line = strings [ 2 ] . to_int ( ) ;
2016-05-22 00:18:16 +00:00
}
} else {
item . name = " SigErr " + itos ( signature ) ;
}
item . calls = calls ;
item . self = self ;
item . total = total ;
2018-07-25 01:11:03 +00:00
funcs . items . write [ i ] = item ;
2016-05-22 00:18:16 +00:00
}
metric . categories . push_back ( funcs ) ;
2020-05-14 14:41:43 +00:00
if ( p_msg = = " servers:profile_frame " ) {
2016-05-22 00:18:16 +00:00
profiler - > add_frame_metric ( metric , false ) ;
2020-05-14 14:41:43 +00:00
} else {
2016-05-22 00:18:16 +00:00
profiler - > add_frame_metric ( metric , true ) ;
2020-05-14 14:41:43 +00:00
}
2020-03-08 11:21:08 +00:00
} else if ( p_msg = = " request_quit " ) {
2021-07-17 21:22:52 +00:00
emit_signal ( SNAME ( " stop_requested " ) ) ;
2020-02-07 01:52:05 +00:00
_stop_and_notify ( ) ;
2020-06-04 13:18:57 +00:00
} else if ( p_msg = = " performance:profile_names " ) {
Vector < StringName > monitors ;
monitors . resize ( p_data . size ( ) ) ;
for ( int i = 0 ; i < p_data . size ( ) ; i + + ) {
ERR_FAIL_COND ( p_data [ i ] . get_type ( ) ! = Variant : : STRING_NAME ) ;
monitors . set ( i , p_data [ i ] ) ;
}
performance_profiler - > update_monitors ( monitors ) ;
2023-03-24 18:38:08 +00:00
} else if ( p_msg = = " filesystem:update_file " ) {
ERR_FAIL_COND ( p_data . size ( ) < 1 ) ;
if ( EditorFileSystem : : get_singleton ( ) ) {
EditorFileSystem : : get_singleton ( ) - > update_file ( p_data [ 0 ] ) ;
}
2020-03-08 11:21:08 +00:00
} else {
2020-05-18 14:55:49 +00:00
int colon_index = p_msg . find_char ( ' : ' ) ;
ERR_FAIL_COND_MSG ( colon_index < 1 , " Invalid message received " ) ;
2022-10-03 13:21:25 +00:00
bool parsed = EditorDebuggerNode : : get_singleton ( ) - > plugins_capture ( this , p_msg , p_data ) ;
2020-05-18 14:55:49 +00:00
if ( ! parsed ) {
WARN_PRINT ( " unknown message " + p_msg ) ;
}
2014-02-13 21:03:28 +00:00
}
}
2017-08-22 19:16:08 +00:00
void ScriptEditorDebugger : : _set_reason_text ( const String & p_reason , MessageType p_type ) {
switch ( p_type ) {
case MESSAGE_ERROR :
2022-02-08 09:14:58 +00:00
reason - > add_theme_color_override ( " font_color " , get_theme_color ( SNAME ( " error_color " ) , SNAME ( " Editor " ) ) ) ;
2017-08-22 19:16:08 +00:00
break ;
case MESSAGE_WARNING :
2022-02-08 09:14:58 +00:00
reason - > add_theme_color_override ( " font_color " , get_theme_color ( SNAME ( " warning_color " ) , SNAME ( " Editor " ) ) ) ;
2017-08-22 19:16:08 +00:00
break ;
default :
2022-02-08 09:14:58 +00:00
reason - > add_theme_color_override ( " font_color " , get_theme_color ( SNAME ( " success_color " ) , SNAME ( " Editor " ) ) ) ;
2017-08-22 19:16:08 +00:00
}
reason - > set_text ( p_reason ) ;
2022-08-18 08:20:20 +00:00
const PackedInt32Array boundaries = TS - > string_get_word_breaks ( p_reason , " " , 80 ) ;
PackedStringArray lines ;
for ( int i = 0 ; i < boundaries . size ( ) ; i + = 2 ) {
const int start = boundaries [ i ] ;
const int end = boundaries [ i + 1 ] ;
lines . append ( p_reason . substr ( start , end - start + 1 ) ) ;
}
reason - > set_tooltip_text ( String ( " \n " ) . join ( lines ) ) ;
2017-08-22 19:16:08 +00:00
}
2014-02-13 21:03:28 +00:00
void ScriptEditorDebugger : : _notification ( int p_what ) {
switch ( p_what ) {
2014-11-06 00:20:42 +00:00
case NOTIFICATION_ENTER_TREE : {
2020-02-21 17:28:45 +00:00
le_set - > connect ( " pressed " , callable_mp ( this , & ScriptEditorDebugger : : _live_edit_set ) ) ;
le_clear - > connect ( " pressed " , callable_mp ( this , & ScriptEditorDebugger : : _live_edit_clear ) ) ;
error_tree - > connect ( " item_selected " , callable_mp ( this , & ScriptEditorDebugger : : _error_selected ) ) ;
error_tree - > connect ( " item_activated " , callable_mp ( this , & ScriptEditorDebugger : : _error_activated ) ) ;
2021-10-07 18:39:12 +00:00
breakpoints_tree - > connect ( " item_activated " , callable_mp ( this , & ScriptEditorDebugger : : _breakpoint_tree_clicked ) ) ;
2022-08-29 09:04:31 +00:00
[[fallthrough]] ;
}
2022-03-15 15:05:12 +00:00
case NOTIFICATION_THEME_CHANGED : {
2023-03-10 17:16:00 +00:00
tabs - > add_theme_style_override ( " panel " , get_theme_stylebox ( SNAME ( " DebuggerPanel " ) , SNAME ( " EditorStyles " ) ) ) ;
2022-03-15 15:05:12 +00:00
skip_breakpoints - > set_icon ( get_theme_icon ( skip_breakpoints_value ? SNAME ( " DebugSkipBreakpointsOn " ) : SNAME ( " DebugSkipBreakpointsOff " ) , SNAME ( " EditorIcons " ) ) ) ;
copy - > set_icon ( get_theme_icon ( SNAME ( " ActionCopy " ) , SNAME ( " EditorIcons " ) ) ) ;
step - > set_icon ( get_theme_icon ( SNAME ( " DebugStep " ) , SNAME ( " EditorIcons " ) ) ) ;
next - > set_icon ( get_theme_icon ( SNAME ( " DebugNext " ) , SNAME ( " EditorIcons " ) ) ) ;
dobreak - > set_icon ( get_theme_icon ( SNAME ( " Pause " ) , SNAME ( " EditorIcons " ) ) ) ;
docontinue - > set_icon ( get_theme_icon ( SNAME ( " DebugContinue " ) , SNAME ( " EditorIcons " ) ) ) ;
2021-07-17 21:22:52 +00:00
vmem_refresh - > set_icon ( get_theme_icon ( SNAME ( " Reload " ) , SNAME ( " EditorIcons " ) ) ) ;
vmem_export - > set_icon ( get_theme_icon ( SNAME ( " Save " ) , SNAME ( " EditorIcons " ) ) ) ;
2022-01-12 11:53:32 +00:00
search - > set_right_icon ( get_theme_icon ( SNAME ( " Search " ) , SNAME ( " EditorIcons " ) ) ) ;
2014-02-13 21:03:28 +00:00
2022-02-08 09:14:58 +00:00
reason - > add_theme_color_override ( " font_color " , get_theme_color ( SNAME ( " error_color " ) , SNAME ( " Editor " ) ) ) ;
2023-03-10 17:16:00 +00:00
TreeItem * error_root = error_tree - > get_root ( ) ;
if ( error_root ) {
TreeItem * error = error_root - > get_first_child ( ) ;
while ( error ) {
if ( error - > has_meta ( " _is_warning " ) ) {
error - > set_icon ( 0 , get_theme_icon ( SNAME ( " Warning " ) , SNAME ( " EditorIcons " ) ) ) ;
error - > set_custom_color ( 0 , get_theme_color ( SNAME ( " warning_color " ) , SNAME ( " Editor " ) ) ) ;
error - > set_custom_color ( 1 , get_theme_color ( SNAME ( " warning_color " ) , SNAME ( " Editor " ) ) ) ;
} else if ( error - > has_meta ( " _is_error " ) ) {
error - > set_icon ( 0 , get_theme_icon ( SNAME ( " Error " ) , SNAME ( " EditorIcons " ) ) ) ;
error - > set_custom_color ( 0 , get_theme_color ( SNAME ( " error_color " ) , SNAME ( " Editor " ) ) ) ;
error - > set_custom_color ( 1 , get_theme_color ( SNAME ( " error_color " ) , SNAME ( " Editor " ) ) ) ;
}
error = error - > get_next ( ) ;
}
}
2014-02-13 21:03:28 +00:00
} break ;
2022-02-15 23:52:32 +00:00
2014-02-13 21:03:28 +00:00
case NOTIFICATION_PROCESS : {
2020-02-07 01:52:05 +00:00
if ( is_session_active ( ) ) {
2020-03-16 08:37:43 +00:00
peer - > poll ( ) ;
2020-02-24 05:21:15 +00:00
if ( camera_override = = CameraOverride : : OVERRIDE_2D ) {
2022-01-27 09:36:51 +00:00
Dictionary state = CanvasItemEditor : : get_singleton ( ) - > get_state ( ) ;
2019-04-06 20:55:01 +00:00
float zoom = state [ " zoom " ] ;
Point2 offset = state [ " ofs " ] ;
Transform2D transform ;
transform . scale_basis ( Size2 ( zoom , zoom ) ) ;
2022-04-24 21:59:24 +00:00
transform . columns [ 2 ] = - offset * zoom ;
2019-04-06 20:55:01 +00:00
Array msg ;
msg . push_back ( transform ) ;
2020-03-08 11:21:08 +00:00
_put_msg ( " scene:override_camera_2D:transform " , msg ) ;
2019-04-06 20:55:01 +00:00
2020-02-24 05:21:15 +00:00
} else if ( camera_override > = CameraOverride : : OVERRIDE_3D_1 ) {
int viewport_idx = camera_override - CameraOverride : : OVERRIDE_3D_1 ;
2020-03-26 21:49:16 +00:00
Node3DEditorViewport * viewport = Node3DEditor : : get_singleton ( ) - > get_editor_viewport ( viewport_idx ) ;
2020-04-28 15:04:07 +00:00
Camera3D * const cam = viewport - > get_camera_3d ( ) ;
2019-04-06 20:55:01 +00:00
Array msg ;
msg . push_back ( cam - > get_camera_transform ( ) ) ;
2020-03-26 21:49:16 +00:00
if ( cam - > get_projection ( ) = = Camera3D : : PROJECTION_ORTHOGONAL ) {
2019-04-06 20:55:01 +00:00
msg . push_back ( false ) ;
msg . push_back ( cam - > get_size ( ) ) ;
} else {
msg . push_back ( true ) ;
msg . push_back ( cam - > get_fov ( ) ) ;
}
2020-12-16 12:40:42 +00:00
msg . push_back ( cam - > get_near ( ) ) ;
msg . push_back ( cam - > get_far ( ) ) ;
2020-03-08 11:21:08 +00:00
_put_msg ( " scene:override_camera_3D:transform " , msg ) ;
2014-02-13 21:03:28 +00:00
}
2023-04-29 15:20:38 +00:00
if ( is_breaked ( ) & & can_request_idle_draw ) {
2022-02-06 16:18:44 +00:00
_put_msg ( " servers:draw " , Array ( ) ) ;
2023-02-07 11:10:28 +00:00
can_request_idle_draw = false ;
2022-02-06 16:18:44 +00:00
}
2019-06-04 05:37:57 +00:00
}
2018-01-03 14:59:10 +00:00
const uint64_t until = OS : : get_singleton ( ) - > get_ticks_msec ( ) + 20 ;
2020-03-19 01:51:43 +00:00
while ( peer . is_valid ( ) & & peer - > has_message ( ) ) {
2020-02-24 05:21:15 +00:00
Array arr = peer - > get_message ( ) ;
2023-04-29 15:20:38 +00:00
if ( arr . size ( ) ! = 3 | | arr [ 0 ] . get_type ( ) ! = Variant : : STRING | | arr [ 1 ] . get_type ( ) ! = Variant : : INT | | arr [ 2 ] . get_type ( ) ! = Variant : : ARRAY ) {
2020-02-07 01:52:05 +00:00
_stop_and_notify ( ) ;
ERR_FAIL_MSG ( " Invalid message format received from peer " ) ;
}
2023-04-29 15:20:38 +00:00
_parse_message ( arr [ 0 ] , arr [ 1 ] , arr [ 2 ] ) ;
2018-01-03 14:59:10 +00:00
2020-05-14 14:41:43 +00:00
if ( OS : : get_singleton ( ) - > get_ticks_msec ( ) > until ) {
2018-01-03 14:59:10 +00:00
break ;
2020-05-14 14:41:43 +00:00
}
2014-02-13 21:03:28 +00:00
}
2020-02-24 05:21:15 +00:00
if ( ! is_session_active ( ) ) {
_stop_and_notify ( ) ;
break ;
} ;
2014-02-13 21:03:28 +00:00
} break ;
}
}
2019-04-22 16:20:27 +00:00
void ScriptEditorDebugger : : _clear_execution ( ) {
TreeItem * ti = stack_dump - > get_selected ( ) ;
2020-05-14 14:41:43 +00:00
if ( ! ti ) {
2019-04-22 16:20:27 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2019-04-22 16:20:27 +00:00
Dictionary d = ti - > get_metadata ( 0 ) ;
stack_script = ResourceLoader : : load ( d [ " file " ] ) ;
2021-07-17 21:22:52 +00:00
emit_signal ( SNAME ( " clear_execution " ) , stack_script ) ;
2019-04-22 16:20:27 +00:00
stack_script . unref ( ) ;
2020-02-07 01:52:05 +00:00
stack_dump - > clear ( ) ;
inspector - > clear_stack_variables ( ) ;
2019-04-22 16:20:27 +00:00
}
2021-07-20 11:24:56 +00:00
void ScriptEditorDebugger : : _set_breakpoint ( const String & p_file , const int & p_line , const bool & p_enabled ) {
2022-09-29 09:53:28 +00:00
Ref < Script > scr = ResourceLoader : : load ( p_file ) ;
emit_signal ( SNAME ( " set_breakpoint " ) , scr , p_line - 1 , p_enabled ) ;
scr . unref ( ) ;
2021-07-20 11:24:56 +00:00
}
void ScriptEditorDebugger : : _clear_breakpoints ( ) {
2022-02-06 14:53:53 +00:00
emit_signal ( SNAME ( " clear_breakpoints " ) ) ;
2021-07-20 11:24:56 +00:00
}
2021-10-07 18:39:12 +00:00
void ScriptEditorDebugger : : _breakpoint_tree_clicked ( ) {
TreeItem * selected = breakpoints_tree - > get_selected ( ) ;
if ( selected - > has_meta ( " line " ) ) {
emit_signal ( SNAME ( " breakpoint_selected " ) , selected - > get_parent ( ) - > get_text ( 0 ) , int ( selected - > get_meta ( " line " ) ) ) ;
}
}
2023-01-23 22:18:03 +00:00
String ScriptEditorDebugger : : _format_frame_text ( const ScriptLanguage : : StackInfo * info ) {
String text = info - > file . get_file ( ) + " : " + itos ( info - > line ) + " @ " + info - > func ;
if ( ! text . ends_with ( " ) " ) ) {
text + = " () " ;
}
return text ;
}
2020-03-08 11:21:08 +00:00
void ScriptEditorDebugger : : start ( Ref < RemoteDebuggerPeer > p_peer ) {
2021-09-16 11:29:23 +00:00
_clear_errors_list ( ) ;
2014-02-13 21:03:28 +00:00
stop ( ) ;
2022-09-06 15:15:00 +00:00
profiler - > set_enabled ( true , true ) ;
2022-12-16 15:35:44 +00:00
visual_profiler - > set_enabled ( true ) ;
2022-09-06 15:15:00 +00:00
2020-02-24 05:21:15 +00:00
peer = p_peer ;
2020-03-08 11:21:08 +00:00
ERR_FAIL_COND ( p_peer . is_null ( ) ) ;
2014-02-13 21:03:28 +00:00
2020-06-04 13:18:57 +00:00
performance_profiler - > reset ( ) ;
2014-02-13 21:03:28 +00:00
set_process ( true ) ;
2020-02-24 05:21:15 +00:00
camera_override = CameraOverride : : OVERRIDE_NONE ;
2020-02-07 01:52:05 +00:00
tabs - > set_current_tab ( 0 ) ;
_set_reason_text ( TTR ( " Debug session started. " ) , MESSAGE_SUCCESS ) ;
_update_buttons_state ( ) ;
2021-07-17 21:22:52 +00:00
emit_signal ( SNAME ( " started " ) ) ;
2014-02-13 21:03:28 +00:00
}
2020-02-07 01:52:05 +00:00
void ScriptEditorDebugger : : _update_buttons_state ( ) {
const bool active = is_session_active ( ) ;
const bool has_editor_tree = active & & editor_remote_tree & & editor_remote_tree - > get_selected ( ) ;
vmem_refresh - > set_disabled ( ! active ) ;
2023-04-29 15:20:38 +00:00
step - > set_disabled ( ! active | | ! is_breaked ( ) | | ! is_debuggable ( ) ) ;
next - > set_disabled ( ! active | | ! is_breaked ( ) | | ! is_debuggable ( ) ) ;
copy - > set_disabled ( ! active | | ! is_breaked ( ) ) ;
docontinue - > set_disabled ( ! active | | ! is_breaked ( ) ) ;
dobreak - > set_disabled ( ! active | | is_breaked ( ) ) ;
2020-02-07 01:52:05 +00:00
le_clear - > set_disabled ( ! active ) ;
le_set - > set_disabled ( ! has_editor_tree ) ;
2023-04-29 15:20:38 +00:00
thread_list_updating = true ;
LocalVector < ThreadDebugged * > threadss ;
for ( KeyValue < uint64_t , ThreadDebugged > & I : threads_debugged ) {
threadss . push_back ( & I . value ) ;
}
threadss . sort_custom < ThreadSort > ( ) ;
threads - > clear ( ) ;
int32_t selected_index = - 1 ;
for ( uint32_t i = 0 ; i < threadss . size ( ) ; i + + ) {
if ( debugging_thread_id = = threadss [ i ] - > thread_id ) {
selected_index = i ;
}
threads - > add_item ( threadss [ i ] - > name ) ;
threads - > set_item_metadata ( threads - > get_item_count ( ) - 1 , threadss [ i ] - > thread_id ) ;
}
if ( selected_index ! = - 1 ) {
threads - > select ( selected_index ) ;
}
thread_list_updating = false ;
2014-02-13 21:03:28 +00:00
}
2020-02-07 01:52:05 +00:00
void ScriptEditorDebugger : : _stop_and_notify ( ) {
stop ( ) ;
2021-07-17 21:22:52 +00:00
emit_signal ( SNAME ( " stopped " ) ) ;
2020-02-07 01:52:05 +00:00
_set_reason_text ( TTR ( " Debug session closed. " ) , MESSAGE_WARNING ) ;
2014-02-13 21:03:28 +00:00
}
void ScriptEditorDebugger : : stop ( ) {
set_process ( false ) ;
2023-04-29 15:20:38 +00:00
threads_debugged . clear ( ) ;
debugging_thread_id = Thread : : UNASSIGNED_ID ;
2020-02-07 01:52:05 +00:00
remote_pid = 0 ;
2019-04-22 16:20:27 +00:00
_clear_execution ( ) ;
2014-02-13 21:03:28 +00:00
2020-02-07 01:52:05 +00:00
inspector - > clear_cache ( ) ;
2014-02-13 21:03:28 +00:00
2020-02-24 05:21:15 +00:00
if ( peer . is_valid ( ) ) {
peer - > close ( ) ;
peer . unref ( ) ;
2018-08-20 18:46:14 +00:00
reason - > set_text ( " " ) ;
2022-08-25 10:42:17 +00:00
reason - > set_tooltip_text ( " " ) ;
2014-02-13 21:03:28 +00:00
}
2015-08-02 15:29:37 +00:00
node_path_cache . clear ( ) ;
res_path_cache . clear ( ) ;
2016-05-22 00:18:16 +00:00
profiler_signature . clear ( ) ;
2022-12-16 15:35:44 +00:00
profiler - > set_enabled ( false , false ) ;
profiler - > set_pressed ( false ) ;
visual_profiler - > set_enabled ( false ) ;
visual_profiler - > set_pressed ( false ) ;
2022-09-06 15:15:00 +00:00
2020-04-01 23:20:12 +00:00
inspector - > edit ( nullptr ) ;
2020-02-07 01:52:05 +00:00
_update_buttons_state ( ) ;
2014-02-13 21:03:28 +00:00
}
2020-03-08 11:21:08 +00:00
void ScriptEditorDebugger : : _profiler_activate ( bool p_enable , int p_type ) {
2022-09-29 09:53:28 +00:00
Array msg_data ;
msg_data . push_back ( p_enable ) ;
2020-03-08 11:21:08 +00:00
switch ( p_type ) {
case PROFILER_VISUAL :
2022-09-29 09:53:28 +00:00
_put_msg ( " profiler:visual " , msg_data ) ;
2020-03-08 11:21:08 +00:00
break ;
case PROFILER_SCRIPTS_SERVERS :
if ( p_enable ) {
// Clear old script signatures. (should we move all this into the profiler?)
profiler_signature . clear ( ) ;
// Add max funcs options to request.
Array opts ;
2022-10-18 14:43:37 +00:00
int max_funcs = EDITOR_GET ( " debugger/profiler_frame_max_functions " ) ;
2020-03-08 11:21:08 +00:00
opts . push_back ( CLAMP ( max_funcs , 16 , 512 ) ) ;
2022-09-29 09:53:28 +00:00
msg_data . push_back ( opts ) ;
2020-03-08 11:21:08 +00:00
}
2022-09-29 09:53:28 +00:00
_put_msg ( " profiler:servers " , msg_data ) ;
2020-03-08 11:21:08 +00:00
break ;
default :
ERR_FAIL_MSG ( " Invalid profiler type " ) ;
2019-09-01 16:38:58 +00:00
}
}
2016-05-22 00:18:16 +00:00
void ScriptEditorDebugger : : _profiler_seeked ( ) {
2023-04-29 15:20:38 +00:00
if ( is_breaked ( ) ) {
2016-05-22 00:18:16 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2017-01-14 17:03:38 +00:00
debug_break ( ) ;
2016-05-22 00:18:16 +00:00
}
2014-02-13 21:03:28 +00:00
void ScriptEditorDebugger : : _stack_dump_frame_selected ( ) {
2021-07-17 21:22:52 +00:00
emit_signal ( SNAME ( " stack_frame_selected " ) ) ;
2014-02-13 21:03:28 +00:00
2020-02-07 01:52:05 +00:00
int frame = get_stack_script_frame ( ) ;
2014-02-13 21:03:28 +00:00
2021-06-04 18:39:38 +00:00
if ( ! request_stack_dump ( frame ) ) {
2020-04-01 23:20:12 +00:00
inspector - > edit ( nullptr ) ;
2018-02-21 11:28:26 +00:00
}
2014-02-13 21:03:28 +00:00
}
2019-02-18 00:25:26 +00:00
void ScriptEditorDebugger : : _export_csv ( ) {
2020-03-06 17:00:16 +00:00
file_dialog - > set_file_mode ( EditorFileDialog : : FILE_MODE_SAVE_FILE ) ;
2020-01-24 11:18:00 +00:00
file_dialog - > set_access ( EditorFileDialog : : ACCESS_FILESYSTEM ) ;
2020-03-17 12:46:18 +00:00
file_dialog_purpose = SAVE_MONITORS_CSV ;
2020-07-11 16:45:19 +00:00
file_dialog - > popup_file_dialog ( ) ;
2019-02-18 00:25:26 +00:00
}
2014-02-13 21:03:28 +00:00
String ScriptEditorDebugger : : get_var_value ( const String & p_var ) const {
2023-04-29 15:20:38 +00:00
if ( ! is_breaked ( ) ) {
2014-02-13 21:03:28 +00:00
return String ( ) ;
2020-05-14 14:41:43 +00:00
}
2020-02-07 01:52:05 +00:00
return inspector - > get_stack_variable ( p_var ) ;
2014-02-13 21:03:28 +00:00
}
2015-08-02 15:29:37 +00:00
int ScriptEditorDebugger : : _get_node_path_cache ( const NodePath & p_path ) {
const int * r = node_path_cache . getptr ( p_path ) ;
2020-05-14 14:41:43 +00:00
if ( r ) {
2015-08-02 15:29:37 +00:00
return * r ;
2020-05-14 14:41:43 +00:00
}
2015-08-02 15:29:37 +00:00
last_path_id + + ;
node_path_cache [ p_path ] = last_path_id ;
Array msg ;
msg . push_back ( p_path ) ;
msg . push_back ( last_path_id ) ;
2020-03-08 11:21:08 +00:00
_put_msg ( " scene:live_node_path " , msg ) ;
2015-08-02 15:29:37 +00:00
return last_path_id ;
}
int ScriptEditorDebugger : : _get_res_path_cache ( const String & p_path ) {
2022-05-13 13:04:37 +00:00
HashMap < String , int > : : Iterator E = res_path_cache . find ( p_path ) ;
2015-08-02 15:29:37 +00:00
2020-05-14 14:41:43 +00:00
if ( E ) {
2022-05-13 13:04:37 +00:00
return E - > value ;
2020-05-14 14:41:43 +00:00
}
2015-08-02 15:29:37 +00:00
last_path_id + + ;
res_path_cache [ p_path ] = last_path_id ;
Array msg ;
msg . push_back ( p_path ) ;
msg . push_back ( last_path_id ) ;
2020-03-08 11:21:08 +00:00
_put_msg ( " scene:live_res_path " , msg ) ;
2015-08-02 15:29:37 +00:00
return last_path_id ;
}
2022-03-09 13:58:40 +00:00
void ScriptEditorDebugger : : _method_changed ( Object * p_base , const StringName & p_name , const Variant * * p_args , int p_argcount ) {
2022-01-27 09:36:51 +00:00
if ( ! p_base | | ! live_debug | | ! is_session_active ( ) | | ! EditorNode : : get_singleton ( ) - > get_edited_scene ( ) ) {
2015-08-02 15:29:37 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2015-08-02 15:29:37 +00:00
2017-08-24 20:58:51 +00:00
Node * node = Object : : cast_to < Node > ( p_base ) ;
2015-08-02 15:29:37 +00:00
2022-03-09 13:58:40 +00:00
for ( int i = 0 ; i < p_argcount ; i + + ) {
2015-08-02 15:29:37 +00:00
//no pointers, sorry
2022-03-09 13:58:40 +00:00
if ( p_args [ i ] - > get_type ( ) = = Variant : : OBJECT | | p_args [ i ] - > get_type ( ) = = Variant : : RID ) {
2015-08-02 15:29:37 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2015-08-02 15:29:37 +00:00
}
if ( node ) {
2022-01-27 09:36:51 +00:00
NodePath path = EditorNode : : get_singleton ( ) - > get_edited_scene ( ) - > get_path_to ( node ) ;
2015-08-02 15:29:37 +00:00
int pathid = _get_node_path_cache ( path ) ;
Array msg ;
msg . push_back ( pathid ) ;
msg . push_back ( p_name ) ;
2022-03-09 13:58:40 +00:00
for ( int i = 0 ; i < p_argcount ; i + + ) {
2015-08-02 15:29:37 +00:00
//no pointers, sorry
2022-03-09 13:58:40 +00:00
msg . push_back ( * p_args [ i ] ) ;
2015-08-02 15:29:37 +00:00
}
2020-03-08 11:21:08 +00:00
_put_msg ( " scene:live_node_call " , msg ) ;
2015-08-02 15:29:37 +00:00
return ;
}
2017-08-24 20:58:51 +00:00
Resource * res = Object : : cast_to < Resource > ( p_base ) ;
2015-08-02 15:29:37 +00:00
2021-12-09 09:42:46 +00:00
if ( res & & ! res - > get_path ( ) . is_empty ( ) ) {
2015-08-02 15:29:37 +00:00
String respath = res - > get_path ( ) ;
int pathid = _get_res_path_cache ( respath ) ;
Array msg ;
msg . push_back ( pathid ) ;
msg . push_back ( p_name ) ;
2022-03-09 13:58:40 +00:00
for ( int i = 0 ; i < p_argcount ; i + + ) {
2015-08-02 15:29:37 +00:00
//no pointers, sorry
2022-03-09 13:58:40 +00:00
msg . push_back ( * p_args [ i ] ) ;
2015-08-02 15:29:37 +00:00
}
2020-03-08 11:21:08 +00:00
_put_msg ( " scene:live_res_call " , msg ) ;
2015-08-02 15:29:37 +00:00
return ;
}
}
void ScriptEditorDebugger : : _property_changed ( Object * p_base , const StringName & p_property , const Variant & p_value ) {
2022-01-27 09:36:51 +00:00
if ( ! p_base | | ! live_debug | | ! EditorNode : : get_singleton ( ) - > get_edited_scene ( ) ) {
2015-08-02 15:29:37 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2015-08-02 15:29:37 +00:00
2017-08-24 20:58:51 +00:00
Node * node = Object : : cast_to < Node > ( p_base ) ;
2015-08-02 15:29:37 +00:00
if ( node ) {
2022-01-27 09:36:51 +00:00
NodePath path = EditorNode : : get_singleton ( ) - > get_edited_scene ( ) - > get_path_to ( node ) ;
2015-08-02 15:29:37 +00:00
int pathid = _get_node_path_cache ( path ) ;
2021-08-26 19:37:17 +00:00
if ( p_value . is_ref_counted ( ) ) {
2015-08-02 15:29:37 +00:00
Ref < Resource > res = p_value ;
2021-12-09 09:42:46 +00:00
if ( res . is_valid ( ) & & ! res - > get_path ( ) . is_empty ( ) ) {
2015-08-02 15:29:37 +00:00
Array msg ;
msg . push_back ( pathid ) ;
msg . push_back ( p_property ) ;
msg . push_back ( res - > get_path ( ) ) ;
2020-03-08 11:21:08 +00:00
_put_msg ( " scene:live_node_prop_res " , msg ) ;
2015-08-02 15:29:37 +00:00
}
} else {
Array msg ;
msg . push_back ( pathid ) ;
msg . push_back ( p_property ) ;
msg . push_back ( p_value ) ;
2020-03-08 11:21:08 +00:00
_put_msg ( " scene:live_node_prop " , msg ) ;
2015-08-02 15:29:37 +00:00
}
return ;
}
2017-08-24 20:58:51 +00:00
Resource * res = Object : : cast_to < Resource > ( p_base ) ;
2015-08-02 15:29:37 +00:00
2021-12-09 09:42:46 +00:00
if ( res & & ! res - > get_path ( ) . is_empty ( ) ) {
2015-08-02 15:29:37 +00:00
String respath = res - > get_path ( ) ;
int pathid = _get_res_path_cache ( respath ) ;
2021-08-26 19:37:17 +00:00
if ( p_value . is_ref_counted ( ) ) {
2019-02-12 20:10:08 +00:00
Ref < Resource > res2 = p_value ;
2021-12-09 09:42:46 +00:00
if ( res2 . is_valid ( ) & & ! res2 - > get_path ( ) . is_empty ( ) ) {
2015-08-02 15:29:37 +00:00
Array msg ;
msg . push_back ( pathid ) ;
msg . push_back ( p_property ) ;
2019-02-12 20:10:08 +00:00
msg . push_back ( res2 - > get_path ( ) ) ;
2020-03-08 11:21:08 +00:00
_put_msg ( " scene:live_res_prop_res " , msg ) ;
2015-08-02 15:29:37 +00:00
}
} else {
Array msg ;
msg . push_back ( pathid ) ;
msg . push_back ( p_property ) ;
msg . push_back ( p_value ) ;
2020-03-08 11:21:08 +00:00
_put_msg ( " scene:live_res_prop " , msg ) ;
2015-08-02 15:29:37 +00:00
}
return ;
}
}
2021-06-04 18:39:38 +00:00
bool ScriptEditorDebugger : : is_move_to_foreground ( ) const {
return move_to_foreground ;
}
void ScriptEditorDebugger : : set_move_to_foreground ( const bool & p_move_to_foreground ) {
move_to_foreground = p_move_to_foreground ;
}
2020-02-07 01:52:05 +00:00
String ScriptEditorDebugger : : get_stack_script_file ( ) const {
TreeItem * ti = stack_dump - > get_selected ( ) ;
2020-05-14 14:41:43 +00:00
if ( ! ti ) {
2020-02-07 01:52:05 +00:00
return " " ;
2020-05-14 14:41:43 +00:00
}
2020-02-07 01:52:05 +00:00
Dictionary d = ti - > get_metadata ( 0 ) ;
return d [ " file " ] ;
2015-08-02 15:29:37 +00:00
}
2020-02-07 01:52:05 +00:00
int ScriptEditorDebugger : : get_stack_script_line ( ) const {
TreeItem * ti = stack_dump - > get_selected ( ) ;
2020-05-14 14:41:43 +00:00
if ( ! ti ) {
2020-02-07 01:52:05 +00:00
return - 1 ;
2020-05-14 14:41:43 +00:00
}
2020-02-07 01:52:05 +00:00
Dictionary d = ti - > get_metadata ( 0 ) ;
return d [ " line " ] ;
}
2015-08-02 15:29:37 +00:00
2020-02-07 01:52:05 +00:00
int ScriptEditorDebugger : : get_stack_script_frame ( ) const {
TreeItem * ti = stack_dump - > get_selected ( ) ;
2020-05-14 14:41:43 +00:00
if ( ! ti ) {
2020-02-07 01:52:05 +00:00
return - 1 ;
2020-05-14 14:41:43 +00:00
}
2020-02-07 01:52:05 +00:00
Dictionary d = ti - > get_metadata ( 0 ) ;
return d [ " frame " ] ;
2015-08-02 15:29:37 +00:00
}
2021-06-04 18:39:38 +00:00
bool ScriptEditorDebugger : : request_stack_dump ( const int & p_frame ) {
ERR_FAIL_COND_V ( ! is_session_active ( ) | | p_frame < 0 , false ) ;
Array msg ;
msg . push_back ( p_frame ) ;
2023-04-29 15:20:38 +00:00
_put_msg ( " get_stack_frame_vars " , msg , debugging_thread_id ) ;
2021-06-04 18:39:38 +00:00
return true ;
}
2015-08-02 15:29:37 +00:00
void ScriptEditorDebugger : : set_live_debugging ( bool p_enable ) {
live_debug = p_enable ;
}
void ScriptEditorDebugger : : _live_edit_set ( ) {
2020-05-14 14:41:43 +00:00
if ( ! is_session_active ( ) | | ! editor_remote_tree ) {
2015-08-02 15:29:37 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2015-08-02 15:29:37 +00:00
2020-02-07 01:52:05 +00:00
TreeItem * ti = editor_remote_tree - > get_selected ( ) ;
2020-05-14 14:41:43 +00:00
if ( ! ti ) {
2015-08-02 15:29:37 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2020-02-07 01:52:05 +00:00
2015-08-02 15:29:37 +00:00
String path ;
while ( ti ) {
String lp = ti - > get_text ( 0 ) ;
path = " / " + lp + path ;
ti = ti - > get_parent ( ) ;
}
NodePath np = path ;
2022-01-27 09:36:51 +00:00
EditorNode : : get_singleton ( ) - > get_editor_data ( ) . set_edited_scene_live_edit_root ( np ) ;
2015-08-02 15:29:37 +00:00
update_live_edit_root ( ) ;
}
void ScriptEditorDebugger : : _live_edit_clear ( ) {
NodePath np = NodePath ( " /root " ) ;
2022-01-27 09:36:51 +00:00
EditorNode : : get_singleton ( ) - > get_editor_data ( ) . set_edited_scene_live_edit_root ( np ) ;
2015-08-02 15:29:37 +00:00
update_live_edit_root ( ) ;
}
void ScriptEditorDebugger : : update_live_edit_root ( ) {
2022-01-27 09:36:51 +00:00
NodePath np = EditorNode : : get_singleton ( ) - > get_editor_data ( ) . get_edited_scene_live_edit_root ( ) ;
2015-08-02 15:29:37 +00:00
2020-02-07 01:52:05 +00:00
Array msg ;
msg . push_back ( np ) ;
2022-01-27 09:36:51 +00:00
if ( EditorNode : : get_singleton ( ) - > get_edited_scene ( ) ) {
msg . push_back ( EditorNode : : get_singleton ( ) - > get_edited_scene ( ) - > get_scene_file_path ( ) ) ;
2020-05-14 14:41:43 +00:00
} else {
2020-02-07 01:52:05 +00:00
msg . push_back ( " " ) ;
2020-05-14 14:41:43 +00:00
}
2020-03-08 11:21:08 +00:00
_put_msg ( " scene:live_set_root " , msg ) ;
2015-08-02 15:29:37 +00:00
live_edit_root - > set_text ( np ) ;
}
void ScriptEditorDebugger : : live_debug_create_node ( const NodePath & p_parent , const String & p_type , const String & p_name ) {
2020-02-07 01:52:05 +00:00
if ( live_debug ) {
2015-08-02 15:29:37 +00:00
Array msg ;
msg . push_back ( p_parent ) ;
msg . push_back ( p_type ) ;
msg . push_back ( p_name ) ;
2020-03-08 11:21:08 +00:00
_put_msg ( " scene:live_create_node " , msg ) ;
2015-08-02 15:29:37 +00:00
}
}
2022-11-15 23:13:39 +00:00
void ScriptEditorDebugger : : live_debug_instantiate_node ( const NodePath & p_parent , const String & p_path , const String & p_name ) {
2020-02-07 01:52:05 +00:00
if ( live_debug ) {
2015-08-02 15:29:37 +00:00
Array msg ;
msg . push_back ( p_parent ) ;
msg . push_back ( p_path ) ;
msg . push_back ( p_name ) ;
2022-11-15 23:13:39 +00:00
_put_msg ( " scene:live_instantiate_node " , msg ) ;
2015-08-02 15:29:37 +00:00
}
}
2020-05-14 12:29:06 +00:00
2015-08-02 15:29:37 +00:00
void ScriptEditorDebugger : : live_debug_remove_node ( const NodePath & p_at ) {
2020-02-07 01:52:05 +00:00
if ( live_debug ) {
2015-08-02 15:29:37 +00:00
Array msg ;
msg . push_back ( p_at ) ;
2020-03-08 11:21:08 +00:00
_put_msg ( " scene:live_remove_node " , msg ) ;
2015-08-02 15:29:37 +00:00
}
}
2020-05-14 12:29:06 +00:00
2015-08-02 15:29:37 +00:00
void ScriptEditorDebugger : : live_debug_remove_and_keep_node ( const NodePath & p_at , ObjectID p_keep_id ) {
2020-02-07 01:52:05 +00:00
if ( live_debug ) {
2015-08-02 15:29:37 +00:00
Array msg ;
msg . push_back ( p_at ) ;
msg . push_back ( p_keep_id ) ;
2020-03-08 11:21:08 +00:00
_put_msg ( " scene:live_remove_and_keep_node " , msg ) ;
2015-08-02 15:29:37 +00:00
}
}
2020-05-14 12:29:06 +00:00
2015-08-02 15:29:37 +00:00
void ScriptEditorDebugger : : live_debug_restore_node ( ObjectID p_id , const NodePath & p_at , int p_at_pos ) {
2020-02-07 01:52:05 +00:00
if ( live_debug ) {
2015-08-02 15:29:37 +00:00
Array msg ;
msg . push_back ( p_id ) ;
msg . push_back ( p_at ) ;
msg . push_back ( p_at_pos ) ;
2020-03-08 11:21:08 +00:00
_put_msg ( " scene:live_restore_node " , msg ) ;
2015-08-02 15:29:37 +00:00
}
}
2020-05-14 12:29:06 +00:00
2015-08-02 15:29:37 +00:00
void ScriptEditorDebugger : : live_debug_duplicate_node ( const NodePath & p_at , const String & p_new_name ) {
2020-02-07 01:52:05 +00:00
if ( live_debug ) {
2015-08-02 15:29:37 +00:00
Array msg ;
msg . push_back ( p_at ) ;
msg . push_back ( p_new_name ) ;
2020-03-08 11:21:08 +00:00
_put_msg ( " scene:live_duplicate_node " , msg ) ;
2015-08-02 15:29:37 +00:00
}
}
2020-05-14 12:29:06 +00:00
2015-08-02 23:28:10 +00:00
void ScriptEditorDebugger : : live_debug_reparent_node ( const NodePath & p_at , const NodePath & p_new_place , const String & p_new_name , int p_at_pos ) {
2020-02-07 01:52:05 +00:00
if ( live_debug ) {
2015-08-02 15:29:37 +00:00
Array msg ;
msg . push_back ( p_at ) ;
msg . push_back ( p_new_place ) ;
msg . push_back ( p_new_name ) ;
2015-08-02 23:28:10 +00:00
msg . push_back ( p_at_pos ) ;
2020-03-08 11:21:08 +00:00
_put_msg ( " scene:live_reparent_node " , msg ) ;
2015-08-02 15:29:37 +00:00
}
}
2020-02-24 05:21:15 +00:00
CameraOverride ScriptEditorDebugger : : get_camera_override ( ) const {
2019-04-06 20:55:01 +00:00
return camera_override ;
}
void ScriptEditorDebugger : : set_camera_override ( CameraOverride p_override ) {
2020-02-24 05:21:15 +00:00
if ( p_override = = CameraOverride : : OVERRIDE_2D & & camera_override ! = CameraOverride : : OVERRIDE_2D ) {
2020-02-07 01:52:05 +00:00
Array msg ;
msg . push_back ( true ) ;
2020-03-08 11:21:08 +00:00
_put_msg ( " scene:override_camera_2D:set " , msg ) ;
2020-02-24 05:21:15 +00:00
} else if ( p_override ! = CameraOverride : : OVERRIDE_2D & & camera_override = = CameraOverride : : OVERRIDE_2D ) {
2020-02-07 01:52:05 +00:00
Array msg ;
msg . push_back ( false ) ;
2020-03-08 11:21:08 +00:00
_put_msg ( " scene:override_camera_2D:set " , msg ) ;
2020-02-24 05:21:15 +00:00
} else if ( p_override > = CameraOverride : : OVERRIDE_3D_1 & & camera_override < CameraOverride : : OVERRIDE_3D_1 ) {
2020-02-07 01:52:05 +00:00
Array msg ;
msg . push_back ( true ) ;
2020-03-08 11:21:08 +00:00
_put_msg ( " scene:override_camera_3D:set " , msg ) ;
2020-02-24 05:21:15 +00:00
} else if ( p_override < CameraOverride : : OVERRIDE_3D_1 & & camera_override > = CameraOverride : : OVERRIDE_3D_1 ) {
2020-02-07 01:52:05 +00:00
Array msg ;
msg . push_back ( false ) ;
2020-03-08 11:21:08 +00:00
_put_msg ( " scene:override_camera_3D:set " , msg ) ;
2019-04-06 20:55:01 +00:00
}
camera_override = p_override ;
}
2015-08-04 23:17:13 +00:00
void ScriptEditorDebugger : : set_breakpoint ( const String & p_path , int p_line , bool p_enabled ) {
2020-02-07 01:52:05 +00:00
Array msg ;
msg . push_back ( p_path ) ;
msg . push_back ( p_line ) ;
msg . push_back ( p_enabled ) ;
2023-04-29 15:20:38 +00:00
_put_msg ( " breakpoint " , msg , debugging_thread_id ! = Thread : : UNASSIGNED_ID ? debugging_thread_id : Thread : : MAIN_ID ) ;
2021-10-07 18:39:12 +00:00
TreeItem * path_item = breakpoints_tree - > search_item_text ( p_path ) ;
if ( path_item = = nullptr ) {
if ( ! p_enabled ) {
return ;
}
path_item = breakpoints_tree - > create_item ( ) ;
path_item - > set_text ( 0 , p_path ) ;
}
int idx = 0 ;
TreeItem * breakpoint_item ;
for ( breakpoint_item = path_item - > get_first_child ( ) ; breakpoint_item ; breakpoint_item = breakpoint_item - > get_next ( ) ) {
if ( ( int ) breakpoint_item - > get_meta ( " line " ) < p_line ) {
idx + + ;
continue ;
}
if ( ( int ) breakpoint_item - > get_meta ( " line " ) = = p_line ) {
break ;
}
}
if ( breakpoint_item = = nullptr ) {
if ( ! p_enabled ) {
return ;
}
breakpoint_item = breakpoints_tree - > create_item ( path_item , idx ) ;
breakpoint_item - > set_meta ( " line " , p_line ) ;
breakpoint_item - > set_text ( 0 , vformat ( TTR ( " Line %d " ) , p_line ) ) ;
return ;
}
if ( ! p_enabled ) {
path_item - > remove_child ( breakpoint_item ) ;
if ( path_item - > get_first_child ( ) = = nullptr ) {
breakpoints_tree - > get_root ( ) - > remove_child ( path_item ) ;
}
}
2015-08-04 23:17:13 +00:00
}
2016-06-01 23:22:02 +00:00
void ScriptEditorDebugger : : reload_scripts ( ) {
2023-04-29 15:20:38 +00:00
_put_msg ( " reload_scripts " , Array ( ) , debugging_thread_id ! = Thread : : UNASSIGNED_ID ? debugging_thread_id : Thread : : MAIN_ID ) ;
2016-06-01 23:22:02 +00:00
}
2019-07-29 18:09:22 +00:00
bool ScriptEditorDebugger : : is_skip_breakpoints ( ) {
return skip_breakpoints_value ;
}
2018-09-08 23:31:49 +00:00
void ScriptEditorDebugger : : _error_activated ( ) {
TreeItem * selected = error_tree - > get_selected ( ) ;
2015-08-04 12:47:32 +00:00
2022-07-06 13:19:46 +00:00
if ( ! selected ) {
return ;
}
2021-03-07 20:07:30 +00:00
TreeItem * ci = selected - > get_first_child ( ) ;
2018-09-08 23:31:49 +00:00
if ( ci ) {
selected - > set_collapsed ( ! selected - > is_collapsed ( ) ) ;
2015-08-04 12:47:32 +00:00
}
}
2018-09-08 23:31:49 +00:00
void ScriptEditorDebugger : : _error_selected ( ) {
TreeItem * selected = error_tree - > get_selected ( ) ;
2022-07-06 13:19:46 +00:00
if ( ! selected ) {
return ;
}
2018-09-08 23:31:49 +00:00
Array meta = selected - > get_metadata ( 0 ) ;
if ( meta . size ( ) = = 0 ) {
2015-08-04 12:47:32 +00:00
return ;
2018-09-08 23:31:49 +00:00
}
2015-08-04 12:47:32 +00:00
2021-07-17 21:22:52 +00:00
emit_signal ( SNAME ( " error_selected " ) , String ( meta [ 0 ] ) , int ( meta [ 1 ] ) ) ;
2015-08-04 12:47:32 +00:00
}
2018-09-13 02:53:10 +00:00
void ScriptEditorDebugger : : _expand_errors_list ( ) {
TreeItem * root = error_tree - > get_root ( ) ;
2020-05-14 14:41:43 +00:00
if ( ! root ) {
2018-09-13 02:53:10 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2018-09-13 02:53:10 +00:00
2021-03-07 20:07:30 +00:00
TreeItem * item = root - > get_first_child ( ) ;
2018-09-13 02:53:10 +00:00
while ( item ) {
item - > set_collapsed ( false ) ;
item = item - > get_next ( ) ;
}
}
void ScriptEditorDebugger : : _collapse_errors_list ( ) {
TreeItem * root = error_tree - > get_root ( ) ;
2020-05-14 14:41:43 +00:00
if ( ! root ) {
2018-09-13 02:53:10 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2018-09-13 02:53:10 +00:00
2021-03-07 20:07:30 +00:00
TreeItem * item = root - > get_first_child ( ) ;
2018-09-13 02:53:10 +00:00
while ( item ) {
item - > set_collapsed ( true ) ;
item = item - > get_next ( ) ;
}
}
2017-12-17 22:16:11 +00:00
void ScriptEditorDebugger : : _clear_errors_list ( ) {
2018-09-08 23:31:49 +00:00
error_tree - > clear ( ) ;
2017-12-17 22:16:11 +00:00
error_count = 0 ;
2018-08-16 05:41:03 +00:00
warning_count = 0 ;
2022-06-05 23:27:09 +00:00
emit_signal ( SNAME ( " errors_cleared " ) ) ;
2021-11-12 19:14:40 +00:00
update_tabs ( ) ;
expand_all_button - > set_disabled ( true ) ;
collapse_all_button - > set_disabled ( true ) ;
clear_button - > set_disabled ( true ) ;
2017-12-17 22:16:11 +00:00
}
2021-09-18 07:33:18 +00:00
void ScriptEditorDebugger : : _breakpoints_item_rmb_selected ( const Vector2 & p_pos , MouseButton p_button ) {
if ( p_button ! = MouseButton : : RIGHT ) {
return ;
}
2021-10-07 18:39:12 +00:00
breakpoints_menu - > clear ( ) ;
breakpoints_menu - > set_size ( Size2 ( 1 , 1 ) ) ;
const TreeItem * selected = breakpoints_tree - > get_selected ( ) ;
String file = selected - > get_text ( 0 ) ;
if ( selected - > has_meta ( " line " ) ) {
breakpoints_menu - > add_icon_item ( get_theme_icon ( SNAME ( " Remove " ) , SNAME ( " EditorIcons " ) ) , TTR ( " Delete Breakpoint " ) , ACTION_DELETE_BREAKPOINT ) ;
file = selected - > get_parent ( ) - > get_text ( 0 ) ;
}
2022-06-08 09:42:51 +00:00
breakpoints_menu - > add_icon_item ( get_theme_icon ( SNAME ( " Remove " ) , SNAME ( " EditorIcons " ) ) , TTR ( " Delete All Breakpoints in: " ) + " " + file , ACTION_DELETE_BREAKPOINTS_IN_FILE ) ;
2021-10-07 18:39:12 +00:00
breakpoints_menu - > add_icon_item ( get_theme_icon ( SNAME ( " Remove " ) , SNAME ( " EditorIcons " ) ) , TTR ( " Delete All Breakpoints " ) , ACTION_DELETE_ALL_BREAKPOINTS ) ;
breakpoints_menu - > set_position ( breakpoints_tree - > get_global_position ( ) + p_pos ) ;
breakpoints_menu - > popup ( ) ;
}
2017-12-17 22:16:11 +00:00
// Right click on specific file(s) or folder(s).
2021-09-18 07:33:18 +00:00
void ScriptEditorDebugger : : _error_tree_item_rmb_selected ( const Vector2 & p_pos , MouseButton p_button ) {
if ( p_button ! = MouseButton : : RIGHT ) {
return ;
}
2017-12-17 22:16:11 +00:00
item_menu - > clear ( ) ;
2021-11-20 08:04:57 +00:00
item_menu - > reset_size ( ) ;
2017-12-17 22:16:11 +00:00
2018-09-08 23:31:49 +00:00
if ( error_tree - > is_anything_selected ( ) ) {
2021-07-17 21:22:52 +00:00
item_menu - > add_icon_item ( get_theme_icon ( SNAME ( " ActionCopy " ) , SNAME ( " EditorIcons " ) ) , TTR ( " Copy Error " ) , ACTION_COPY_ERROR ) ;
2022-04-24 15:21:14 +00:00
item_menu - > add_icon_item ( get_theme_icon ( SNAME ( " ExternalLink " ) , SNAME ( " EditorIcons " ) ) , TTR ( " Open C++ Source on GitHub " ) , ACTION_OPEN_SOURCE ) ;
2017-12-17 22:16:11 +00:00
}
if ( item_menu - > get_item_count ( ) > 0 ) {
2021-08-31 15:43:35 +00:00
item_menu - > set_position ( error_tree - > get_screen_position ( ) + p_pos ) ;
2017-12-17 22:16:11 +00:00
item_menu - > popup ( ) ;
}
}
void ScriptEditorDebugger : : _item_menu_id_pressed ( int p_option ) {
2021-04-18 00:07:05 +00:00
switch ( p_option ) {
case ACTION_COPY_ERROR : {
TreeItem * ti = error_tree - > get_selected ( ) ;
while ( ti - > get_parent ( ) ! = error_tree - > get_root ( ) ) {
ti = ti - > get_parent ( ) ;
}
2017-12-17 22:16:11 +00:00
2021-04-18 00:07:05 +00:00
String type ;
2018-02-21 15:07:49 +00:00
2023-03-10 17:16:00 +00:00
if ( ti - > has_meta ( " _is_warning " ) ) {
2021-04-18 00:07:05 +00:00
type = " W " ;
2023-03-10 17:16:00 +00:00
} else if ( ti - > has_meta ( " _is_error " ) ) {
2021-04-18 00:07:05 +00:00
type = " E " ;
}
2019-05-05 07:59:10 +00:00
2021-04-18 00:07:05 +00:00
String text = ti - > get_text ( 0 ) + " " ;
int rpad_len = text . length ( ) ;
2019-05-05 07:59:10 +00:00
2021-04-18 00:07:05 +00:00
text = type + text + ti - > get_text ( 1 ) + " \n " ;
2021-03-07 20:07:30 +00:00
TreeItem * ci = ti - > get_first_child ( ) ;
2021-04-18 00:07:05 +00:00
while ( ci ) {
text + = " " + ci - > get_text ( 0 ) . rpad ( rpad_len ) + ci - > get_text ( 1 ) + " \n " ;
ci = ci - > get_next ( ) ;
}
2020-02-07 01:52:05 +00:00
2021-04-18 00:07:05 +00:00
DisplayServer : : get_singleton ( ) - > clipboard_set ( text ) ;
} break ;
case ACTION_OPEN_SOURCE : {
TreeItem * ti = error_tree - > get_selected ( ) ;
while ( ti - > get_parent ( ) ! = error_tree - > get_root ( ) ) {
ti = ti - > get_parent ( ) ;
}
2022-10-06 09:45:27 +00:00
// Find the child with the "C++ Source".
// It's not at a fixed position as "C++ Error" may come first.
2021-03-07 20:07:30 +00:00
TreeItem * ci = ti - > get_first_child ( ) ;
2022-10-06 09:45:27 +00:00
const String cpp_source = " < " + TTR ( " C++ Source " ) + " > " ;
while ( ci ) {
if ( ci - > get_text ( 0 ) = = cpp_source ) {
break ;
}
ci = ci - > get_next ( ) ;
}
if ( ! ci ) {
WARN_PRINT_ED ( " No C++ source reference is available for this error. " ) ;
return ;
}
2021-04-18 00:07:05 +00:00
// Parse back the `file:line @ method()` string.
const Vector < String > file_line_number = ci - > get_text ( 1 ) . split ( " @ " ) [ 0 ] . strip_edges ( ) . split ( " : " ) ;
ERR_FAIL_COND_MSG ( file_line_number . size ( ) < 2 , " Incorrect C++ source stack trace file:line format (please report). " ) ;
const String file = file_line_number [ 0 ] ;
const int line_number = file_line_number [ 1 ] . to_int ( ) ;
// Construct a GitHub repository URL and open it in the user's default web browser.
2022-02-08 19:50:37 +00:00
// If the commit hash is available, use it for greater accuracy. Otherwise fall back to tagged release.
String git_ref = String ( VERSION_HASH ) . is_empty ( ) ? String ( VERSION_NUMBER ) + " -stable " : String ( VERSION_HASH ) ;
OS : : get_singleton ( ) - > shell_open ( vformat ( " https://github.com/godotengine/godot/blob/%s/%s#L%d " ,
git_ref , file , line_number ) ) ;
2021-04-18 00:07:05 +00:00
} break ;
2021-10-07 18:39:12 +00:00
case ACTION_DELETE_BREAKPOINT : {
const TreeItem * selected = breakpoints_tree - > get_selected ( ) ;
_set_breakpoint ( selected - > get_parent ( ) - > get_text ( 0 ) , selected - > get_meta ( " line " ) , false ) ;
} break ;
case ACTION_DELETE_BREAKPOINTS_IN_FILE : {
TreeItem * file_item = breakpoints_tree - > get_selected ( ) ;
if ( file_item - > has_meta ( " line " ) ) {
file_item = file_item - > get_parent ( ) ;
}
// Store first else we will be removing as we loop.
List < int > lines ;
for ( TreeItem * breakpoint_item = file_item - > get_first_child ( ) ; breakpoint_item ; breakpoint_item = breakpoint_item - > get_next ( ) ) {
lines . push_back ( breakpoint_item - > get_meta ( " line " ) ) ;
}
for ( const int & line : lines ) {
_set_breakpoint ( file_item - > get_text ( 0 ) , line , false ) ;
}
} break ;
case ACTION_DELETE_ALL_BREAKPOINTS : {
_clear_breakpoints ( ) ;
} break ;
2021-04-18 00:07:05 +00:00
}
2017-12-17 22:16:11 +00:00
}
2019-11-28 15:37:15 +00:00
void ScriptEditorDebugger : : _tab_changed ( int p_tab ) {
if ( tabs - > get_tab_title ( p_tab ) = = TTR ( " Video RAM " ) ) {
2020-03-11 17:59:18 +00:00
// "Video RAM" tab was clicked, refresh the data it's displaying when entering the tab.
2019-11-28 15:37:15 +00:00
_video_mem_request ( ) ;
}
}
2014-02-13 21:03:28 +00:00
void ScriptEditorDebugger : : _bind_methods ( ) {
2017-02-13 11:47:24 +00:00
ClassDB : : bind_method ( D_METHOD ( " live_debug_create_node " ) , & ScriptEditorDebugger : : live_debug_create_node ) ;
2022-11-15 23:13:39 +00:00
ClassDB : : bind_method ( D_METHOD ( " live_debug_instantiate_node " ) , & ScriptEditorDebugger : : live_debug_instantiate_node ) ;
2017-02-13 11:47:24 +00:00
ClassDB : : bind_method ( D_METHOD ( " live_debug_remove_node " ) , & ScriptEditorDebugger : : live_debug_remove_node ) ;
ClassDB : : bind_method ( D_METHOD ( " live_debug_remove_and_keep_node " ) , & ScriptEditorDebugger : : live_debug_remove_and_keep_node ) ;
ClassDB : : bind_method ( D_METHOD ( " live_debug_restore_node " ) , & ScriptEditorDebugger : : live_debug_restore_node ) ;
ClassDB : : bind_method ( D_METHOD ( " live_debug_duplicate_node " ) , & ScriptEditorDebugger : : live_debug_duplicate_node ) ;
ClassDB : : bind_method ( D_METHOD ( " live_debug_reparent_node " ) , & ScriptEditorDebugger : : live_debug_reparent_node ) ;
2020-02-07 01:52:05 +00:00
ClassDB : : bind_method ( D_METHOD ( " request_remote_object " , " id " ) , & ScriptEditorDebugger : : request_remote_object ) ;
ClassDB : : bind_method ( D_METHOD ( " update_remote_object " , " id " , " property " , " value " ) , & ScriptEditorDebugger : : update_remote_object ) ;
2014-02-13 21:03:28 +00:00
2020-05-18 14:55:49 +00:00
ADD_SIGNAL ( MethodInfo ( " started " ) ) ;
2020-02-07 01:52:05 +00:00
ADD_SIGNAL ( MethodInfo ( " stopped " ) ) ;
ADD_SIGNAL ( MethodInfo ( " stop_requested " ) ) ;
ADD_SIGNAL ( MethodInfo ( " stack_frame_selected " , PropertyInfo ( Variant : : INT , " frame " ) ) ) ;
ADD_SIGNAL ( MethodInfo ( " error_selected " , PropertyInfo ( Variant : : INT , " error " ) ) ) ;
2021-10-07 18:39:12 +00:00
ADD_SIGNAL ( MethodInfo ( " breakpoint_selected " , PropertyInfo ( " script " ) , PropertyInfo ( Variant : : INT , " line " ) ) ) ;
2019-04-22 16:20:27 +00:00
ADD_SIGNAL ( MethodInfo ( " set_execution " , PropertyInfo ( " script " ) , PropertyInfo ( Variant : : INT , " line " ) ) ) ;
ADD_SIGNAL ( MethodInfo ( " clear_execution " , PropertyInfo ( " script " ) ) ) ;
2021-06-04 18:39:38 +00:00
ADD_SIGNAL ( MethodInfo ( " breaked " , PropertyInfo ( Variant : : BOOL , " reallydid " ) , PropertyInfo ( Variant : : BOOL , " can_debug " ) , PropertyInfo ( Variant : : STRING , " reason " ) , PropertyInfo ( Variant : : BOOL , " has_stackdump " ) ) ) ;
2020-02-07 01:52:05 +00:00
ADD_SIGNAL ( MethodInfo ( " remote_object_requested " , PropertyInfo ( Variant : : INT , " id " ) ) ) ;
ADD_SIGNAL ( MethodInfo ( " remote_object_updated " , PropertyInfo ( Variant : : INT , " id " ) ) ) ;
ADD_SIGNAL ( MethodInfo ( " remote_object_property_updated " , PropertyInfo ( Variant : : INT , " id " ) , PropertyInfo ( Variant : : STRING , " property " ) ) ) ;
ADD_SIGNAL ( MethodInfo ( " remote_tree_updated " ) ) ;
2021-06-04 18:39:38 +00:00
ADD_SIGNAL ( MethodInfo ( " output " ) ) ;
ADD_SIGNAL ( MethodInfo ( " stack_dump " , PropertyInfo ( Variant : : ARRAY , " stack_dump " ) ) ) ;
ADD_SIGNAL ( MethodInfo ( " stack_frame_vars " , PropertyInfo ( Variant : : INT , " num_vars " ) ) ) ;
ADD_SIGNAL ( MethodInfo ( " stack_frame_var " , PropertyInfo ( Variant : : ARRAY , " data " ) ) ) ;
2021-07-20 11:24:56 +00:00
ADD_SIGNAL ( MethodInfo ( " debug_data " , PropertyInfo ( Variant : : STRING , " msg " ) , PropertyInfo ( Variant : : ARRAY , " data " ) ) ) ;
ADD_SIGNAL ( MethodInfo ( " set_breakpoint " , PropertyInfo ( " script " ) , PropertyInfo ( Variant : : INT , " line " ) , PropertyInfo ( Variant : : BOOL , " enabled " ) ) ) ;
ADD_SIGNAL ( MethodInfo ( " clear_breakpoints " ) ) ;
2022-06-05 23:27:09 +00:00
ADD_SIGNAL ( MethodInfo ( " errors_cleared " ) ) ;
2014-02-13 21:03:28 +00:00
}
2022-10-03 13:21:25 +00:00
void ScriptEditorDebugger : : add_debugger_tab ( Control * p_control ) {
tabs - > add_child ( p_control ) ;
2020-05-18 14:55:49 +00:00
}
2022-10-03 13:21:25 +00:00
void ScriptEditorDebugger : : remove_debugger_tab ( Control * p_control ) {
int idx = tabs - > get_tab_idx_from_control ( p_control ) ;
ERR_FAIL_COND ( idx < 0 ) ;
p_control - > queue_free ( ) ;
2020-05-18 14:55:49 +00:00
}
2023-05-11 02:17:03 +00:00
int ScriptEditorDebugger : : get_current_debugger_tab ( ) const {
return tabs - > get_current_tab ( ) ;
}
void ScriptEditorDebugger : : switch_to_debugger ( int p_debugger_tab_idx ) {
tabs - > set_current_tab ( p_debugger_tab_idx ) ;
}
2020-05-18 14:55:49 +00:00
void ScriptEditorDebugger : : send_message ( const String & p_message , const Array & p_args ) {
_put_msg ( p_message , p_args ) ;
}
2022-10-03 13:21:25 +00:00
void ScriptEditorDebugger : : toggle_profiler ( const String & p_profiler , bool p_enable , const Array & p_data ) {
Array msg_data ;
msg_data . push_back ( p_enable ) ;
msg_data . append_array ( p_data ) ;
_put_msg ( " profiler: " + p_profiler , msg_data ) ;
2020-05-18 14:55:49 +00:00
}
2022-01-27 09:36:51 +00:00
ScriptEditorDebugger : : ScriptEditorDebugger ( ) {
2014-02-13 21:03:28 +00:00
tabs = memnew ( TabContainer ) ;
add_child ( tabs ) ;
2023-03-10 17:16:00 +00:00
tabs - > connect ( " tab_changed " , callable_mp ( this , & ScriptEditorDebugger : : _tab_changed ) ) ;
2014-02-13 21:03:28 +00:00
2022-11-25 03:09:18 +00:00
InspectorDock : : get_inspector_singleton ( ) - > connect ( " object_id_selected " , callable_mp ( this , & ScriptEditorDebugger : : _remote_object_selected ) ) ;
2016-05-22 22:28:37 +00:00
{ //debugger
VBoxContainer * vbc = memnew ( VBoxContainer ) ;
2023-05-10 03:58:49 +00:00
vbc - > set_name ( TTR ( " Stack Trace " ) ) ;
2016-05-22 22:28:37 +00:00
Control * dbg = vbc ;
2014-02-13 21:03:28 +00:00
2016-05-22 22:28:37 +00:00
HBoxContainer * hbc = memnew ( HBoxContainer ) ;
vbc - > add_child ( hbc ) ;
2014-02-13 21:03:28 +00:00
2017-08-08 02:55:24 +00:00
reason = memnew ( Label ) ;
2016-05-22 22:28:37 +00:00
reason - > set_text ( " " ) ;
hbc - > add_child ( reason ) ;
reason - > set_h_size_flags ( SIZE_EXPAND_FILL ) ;
2022-06-15 08:01:45 +00:00
reason - > set_autowrap_mode ( TextServer : : AUTOWRAP_WORD_SMART ) ;
2018-05-26 11:50:46 +00:00
reason - > set_max_lines_visible ( 3 ) ;
reason - > set_mouse_filter ( Control : : MOUSE_FILTER_PASS ) ;
2014-02-13 21:03:28 +00:00
2016-05-22 22:28:37 +00:00
hbc - > add_child ( memnew ( VSeparator ) ) ;
2019-07-29 18:09:22 +00:00
2020-06-19 18:49:04 +00:00
skip_breakpoints = memnew ( Button ) ;
skip_breakpoints - > set_flat ( true ) ;
2019-07-29 18:09:22 +00:00
hbc - > add_child ( skip_breakpoints ) ;
2022-08-25 10:42:17 +00:00
skip_breakpoints - > set_tooltip_text ( TTR ( " Skip Breakpoints " ) ) ;
2020-02-21 17:28:45 +00:00
skip_breakpoints - > connect ( " pressed " , callable_mp ( this , & ScriptEditorDebugger : : debug_skip_breakpoints ) ) ;
2019-07-29 18:09:22 +00:00
hbc - > add_child ( memnew ( VSeparator ) ) ;
2014-02-13 21:03:28 +00:00
2020-06-19 18:49:04 +00:00
copy = memnew ( Button ) ;
copy - > set_flat ( true ) ;
2018-02-13 16:46:45 +00:00
hbc - > add_child ( copy ) ;
2022-08-25 10:42:17 +00:00
copy - > set_tooltip_text ( TTR ( " Copy Error " ) ) ;
2020-02-21 17:28:45 +00:00
copy - > connect ( " pressed " , callable_mp ( this , & ScriptEditorDebugger : : debug_copy ) ) ;
2018-02-13 16:46:45 +00:00
hbc - > add_child ( memnew ( VSeparator ) ) ;
2020-06-19 18:49:04 +00:00
step = memnew ( Button ) ;
step - > set_flat ( true ) ;
2016-05-22 22:28:37 +00:00
hbc - > add_child ( step ) ;
2022-08-25 10:42:17 +00:00
step - > set_tooltip_text ( TTR ( " Step Into " ) ) ;
2019-09-22 17:19:53 +00:00
step - > set_shortcut ( ED_GET_SHORTCUT ( " debugger/step_into " ) ) ;
2020-02-21 17:28:45 +00:00
step - > connect ( " pressed " , callable_mp ( this , & ScriptEditorDebugger : : debug_step ) ) ;
2014-02-13 21:03:28 +00:00
2020-06-19 18:49:04 +00:00
next = memnew ( Button ) ;
next - > set_flat ( true ) ;
2016-05-22 22:28:37 +00:00
hbc - > add_child ( next ) ;
2022-08-25 10:42:17 +00:00
next - > set_tooltip_text ( TTR ( " Step Over " ) ) ;
2019-09-22 17:19:53 +00:00
next - > set_shortcut ( ED_GET_SHORTCUT ( " debugger/step_over " ) ) ;
2020-02-21 17:28:45 +00:00
next - > connect ( " pressed " , callable_mp ( this , & ScriptEditorDebugger : : debug_next ) ) ;
2014-02-13 21:03:28 +00:00
2016-05-22 22:28:37 +00:00
hbc - > add_child ( memnew ( VSeparator ) ) ;
2014-02-13 21:03:28 +00:00
2020-06-19 18:49:04 +00:00
dobreak = memnew ( Button ) ;
dobreak - > set_flat ( true ) ;
2016-05-22 22:28:37 +00:00
hbc - > add_child ( dobreak ) ;
2022-08-25 10:42:17 +00:00
dobreak - > set_tooltip_text ( TTR ( " Break " ) ) ;
2019-09-22 17:19:53 +00:00
dobreak - > set_shortcut ( ED_GET_SHORTCUT ( " debugger/break " ) ) ;
2020-02-21 17:28:45 +00:00
dobreak - > connect ( " pressed " , callable_mp ( this , & ScriptEditorDebugger : : debug_break ) ) ;
2014-02-13 21:03:28 +00:00
2020-06-19 18:49:04 +00:00
docontinue = memnew ( Button ) ;
docontinue - > set_flat ( true ) ;
2016-05-22 22:28:37 +00:00
hbc - > add_child ( docontinue ) ;
2022-08-25 10:42:17 +00:00
docontinue - > set_tooltip_text ( TTR ( " Continue " ) ) ;
2019-09-22 17:19:53 +00:00
docontinue - > set_shortcut ( ED_GET_SHORTCUT ( " debugger/continue " ) ) ;
2020-02-21 17:28:45 +00:00
docontinue - > connect ( " pressed " , callable_mp ( this , & ScriptEditorDebugger : : debug_continue ) ) ;
2014-02-13 21:03:28 +00:00
2021-10-07 18:39:12 +00:00
HSplitContainer * parent_sc = memnew ( HSplitContainer ) ;
vbc - > add_child ( parent_sc ) ;
parent_sc - > set_v_size_flags ( SIZE_EXPAND_FILL ) ;
parent_sc - > set_split_offset ( 500 * EDSCALE ) ;
2016-05-22 22:28:37 +00:00
HSplitContainer * sc = memnew ( HSplitContainer ) ;
sc - > set_v_size_flags ( SIZE_EXPAND_FILL ) ;
2021-10-07 18:39:12 +00:00
sc - > set_h_size_flags ( SIZE_EXPAND_FILL ) ;
parent_sc - > add_child ( sc ) ;
2014-02-13 21:03:28 +00:00
2023-04-29 15:20:38 +00:00
VBoxContainer * stack_vb = memnew ( VBoxContainer ) ;
stack_vb - > set_h_size_flags ( SIZE_EXPAND_FILL ) ;
sc - > add_child ( stack_vb ) ;
HBoxContainer * thread_hb = memnew ( HBoxContainer ) ;
stack_vb - > add_child ( thread_hb ) ;
thread_hb - > add_child ( memnew ( Label ( TTR ( " Thread: " ) ) ) ) ;
threads = memnew ( OptionButton ) ;
thread_hb - > add_child ( threads ) ;
threads - > set_h_size_flags ( SIZE_EXPAND_FILL ) ;
threads - > connect ( " item_selected " , callable_mp ( this , & ScriptEditorDebugger : : _select_thread ) ) ;
2016-05-22 22:28:37 +00:00
stack_dump = memnew ( Tree ) ;
2018-02-20 02:35:52 +00:00
stack_dump - > set_allow_reselect ( true ) ;
2016-05-22 22:28:37 +00:00
stack_dump - > set_columns ( 1 ) ;
stack_dump - > set_column_titles_visible ( true ) ;
stack_dump - > set_column_title ( 0 , TTR ( " Stack Frames " ) ) ;
stack_dump - > set_hide_root ( true ) ;
2023-04-29 15:20:38 +00:00
stack_dump - > set_v_size_flags ( SIZE_EXPAND_FILL ) ;
2020-02-21 17:28:45 +00:00
stack_dump - > connect ( " cell_selected " , callable_mp ( this , & ScriptEditorDebugger : : _stack_dump_frame_selected ) ) ;
2023-04-29 15:20:38 +00:00
stack_vb - > add_child ( stack_dump ) ;
2014-02-13 21:03:28 +00:00
2022-01-12 11:53:32 +00:00
VBoxContainer * inspector_vbox = memnew ( VBoxContainer ) ;
2021-10-07 18:39:12 +00:00
inspector_vbox - > set_h_size_flags ( SIZE_EXPAND_FILL ) ;
2022-01-12 11:53:32 +00:00
sc - > add_child ( inspector_vbox ) ;
HBoxContainer * tools_hb = memnew ( HBoxContainer ) ;
inspector_vbox - > add_child ( tools_hb ) ;
search = memnew ( LineEdit ) ;
search - > set_h_size_flags ( Control : : SIZE_EXPAND_FILL ) ;
2022-05-27 04:02:48 +00:00
search - > set_placeholder ( TTR ( " Filter Stack Variables " ) ) ;
2022-01-12 11:53:32 +00:00
search - > set_clear_button_enabled ( true ) ;
tools_hb - > add_child ( search ) ;
2020-02-07 01:52:05 +00:00
inspector = memnew ( EditorDebuggerInspector ) ;
2016-05-22 22:28:37 +00:00
inspector - > set_h_size_flags ( SIZE_EXPAND_FILL ) ;
2022-01-12 11:53:32 +00:00
inspector - > set_v_size_flags ( SIZE_EXPAND_FILL ) ;
2022-03-23 01:46:59 +00:00
inspector - > set_property_name_style ( EditorPropertyNameProcessor : : STYLE_RAW ) ;
2016-05-22 22:28:37 +00:00
inspector - > set_read_only ( true ) ;
2020-02-21 17:28:45 +00:00
inspector - > connect ( " object_selected " , callable_mp ( this , & ScriptEditorDebugger : : _remote_object_selected ) ) ;
inspector - > connect ( " object_edited " , callable_mp ( this , & ScriptEditorDebugger : : _remote_object_edited ) ) ;
inspector - > connect ( " object_property_updated " , callable_mp ( this , & ScriptEditorDebugger : : _remote_object_property_updated ) ) ;
2022-01-12 11:53:32 +00:00
inspector - > register_text_enter ( search ) ;
inspector - > set_use_filter ( true ) ;
inspector_vbox - > add_child ( inspector ) ;
2021-10-07 18:39:12 +00:00
breakpoints_tree = memnew ( Tree ) ;
breakpoints_tree - > set_h_size_flags ( SIZE_EXPAND_FILL ) ;
breakpoints_tree - > set_column_titles_visible ( true ) ;
breakpoints_tree - > set_column_title ( 0 , TTR ( " Breakpoints " ) ) ;
breakpoints_tree - > set_allow_reselect ( true ) ;
breakpoints_tree - > set_allow_rmb_select ( true ) ;
breakpoints_tree - > set_hide_root ( true ) ;
2021-09-18 07:33:18 +00:00
breakpoints_tree - > connect ( " item_mouse_selected " , callable_mp ( this , & ScriptEditorDebugger : : _breakpoints_item_rmb_selected ) ) ;
2021-10-07 18:39:12 +00:00
breakpoints_tree - > create_item ( ) ;
parent_sc - > add_child ( breakpoints_tree ) ;
2016-05-22 22:28:37 +00:00
tabs - > add_child ( dbg ) ;
2021-10-07 18:39:12 +00:00
breakpoints_menu = memnew ( PopupMenu ) ;
breakpoints_menu - > connect ( " id_pressed " , callable_mp ( this , & ScriptEditorDebugger : : _item_menu_id_pressed ) ) ;
breakpoints_tree - > add_child ( breakpoints_menu ) ;
2016-05-22 22:28:37 +00:00
}
{ //errors
2019-02-28 21:12:14 +00:00
errors_tab = memnew ( VBoxContainer ) ;
errors_tab - > set_name ( TTR ( " Errors " ) ) ;
2018-09-13 02:53:10 +00:00
2021-11-12 19:14:40 +00:00
HBoxContainer * error_hbox = memnew ( HBoxContainer ) ;
errors_tab - > add_child ( error_hbox ) ;
2018-09-13 02:53:10 +00:00
2021-11-12 19:14:40 +00:00
expand_all_button = memnew ( Button ) ;
expand_all_button - > set_text ( TTR ( " Expand All " ) ) ;
expand_all_button - > set_disabled ( true ) ;
expand_all_button - > connect ( " pressed " , callable_mp ( this , & ScriptEditorDebugger : : _expand_errors_list ) ) ;
error_hbox - > add_child ( expand_all_button ) ;
2018-09-13 02:53:10 +00:00
2021-11-12 19:14:40 +00:00
collapse_all_button = memnew ( Button ) ;
collapse_all_button - > set_text ( TTR ( " Collapse All " ) ) ;
collapse_all_button - > set_disabled ( true ) ;
collapse_all_button - > connect ( " pressed " , callable_mp ( this , & ScriptEditorDebugger : : _collapse_errors_list ) ) ;
error_hbox - > add_child ( collapse_all_button ) ;
2018-09-13 02:53:10 +00:00
Control * space = memnew ( Control ) ;
space - > set_h_size_flags ( SIZE_EXPAND_FILL ) ;
2021-11-12 19:14:40 +00:00
error_hbox - > add_child ( space ) ;
clear_button = memnew ( Button ) ;
clear_button - > set_text ( TTR ( " Clear " ) ) ;
clear_button - > set_h_size_flags ( 0 ) ;
clear_button - > set_disabled ( true ) ;
clear_button - > connect ( " pressed " , callable_mp ( this , & ScriptEditorDebugger : : _clear_errors_list ) ) ;
error_hbox - > add_child ( clear_button ) ;
2017-12-17 22:16:11 +00:00
2018-09-08 23:31:49 +00:00
error_tree = memnew ( Tree ) ;
error_tree - > set_columns ( 2 ) ;
2017-12-17 22:16:11 +00:00
2018-09-08 23:31:49 +00:00
error_tree - > set_column_expand ( 0 , false ) ;
2021-06-28 13:40:56 +00:00
error_tree - > set_column_custom_minimum_width ( 0 , 140 ) ;
2021-07-04 03:13:28 +00:00
error_tree - > set_column_clip_content ( 0 , true ) ;
2017-12-17 22:16:11 +00:00
2018-09-08 23:31:49 +00:00
error_tree - > set_column_expand ( 1 , true ) ;
2021-07-04 03:13:28 +00:00
error_tree - > set_column_clip_content ( 1 , true ) ;
2017-12-17 22:16:11 +00:00
2018-09-08 23:31:49 +00:00
error_tree - > set_select_mode ( Tree : : SELECT_ROW ) ;
error_tree - > set_hide_root ( true ) ;
2018-09-13 02:53:10 +00:00
error_tree - > set_v_size_flags ( SIZE_EXPAND_FILL ) ;
2018-09-08 23:31:49 +00:00
error_tree - > set_allow_rmb_select ( true ) ;
2023-06-10 19:31:08 +00:00
error_tree - > set_allow_reselect ( true ) ;
2021-09-18 07:33:18 +00:00
error_tree - > connect ( " item_mouse_selected " , callable_mp ( this , & ScriptEditorDebugger : : _error_tree_item_rmb_selected ) ) ;
2019-02-28 21:12:14 +00:00
errors_tab - > add_child ( error_tree ) ;
2017-12-17 22:16:11 +00:00
2018-09-08 23:31:49 +00:00
item_menu = memnew ( PopupMenu ) ;
2020-02-21 17:28:45 +00:00
item_menu - > connect ( " id_pressed " , callable_mp ( this , & ScriptEditorDebugger : : _item_menu_id_pressed ) ) ;
2018-09-08 23:31:49 +00:00
error_tree - > add_child ( item_menu ) ;
2016-05-22 22:28:37 +00:00
2019-02-28 21:12:14 +00:00
tabs - > add_child ( errors_tab ) ;
2016-05-22 22:28:37 +00:00
}
2018-02-21 15:07:49 +00:00
{ // File dialog
file_dialog = memnew ( EditorFileDialog ) ;
2020-02-21 17:28:45 +00:00
file_dialog - > connect ( " file_selected " , callable_mp ( this , & ScriptEditorDebugger : : _file_selected ) ) ;
2018-02-21 15:07:49 +00:00
add_child ( file_dialog ) ;
}
2016-05-22 22:28:37 +00:00
{ //profiler
profiler = memnew ( EditorProfiler ) ;
2016-05-30 18:47:53 +00:00
profiler - > set_name ( TTR ( " Profiler " ) ) ;
2016-05-22 22:28:37 +00:00
tabs - > add_child ( profiler ) ;
2022-07-28 20:56:41 +00:00
profiler - > connect ( " enable_profiling " , callable_mp ( this , & ScriptEditorDebugger : : _profiler_activate ) . bind ( PROFILER_SCRIPTS_SERVERS ) ) ;
2020-02-21 17:28:45 +00:00
profiler - > connect ( " break_request " , callable_mp ( this , & ScriptEditorDebugger : : _profiler_seeked ) ) ;
2016-05-22 22:28:37 +00:00
}
2019-09-20 20:58:06 +00:00
{ //frame profiler
visual_profiler = memnew ( EditorVisualProfiler ) ;
visual_profiler - > set_name ( TTR ( " Visual Profiler " ) ) ;
tabs - > add_child ( visual_profiler ) ;
2022-07-28 20:56:41 +00:00
visual_profiler - > connect ( " enable_profiling " , callable_mp ( this , & ScriptEditorDebugger : : _profiler_activate ) . bind ( PROFILER_VISUAL ) ) ;
2019-09-20 20:58:06 +00:00
}
2016-05-22 22:28:37 +00:00
{ //monitors
2020-06-04 13:18:57 +00:00
performance_profiler = memnew ( EditorPerformanceProfiler ) ;
tabs - > add_child ( performance_profiler ) ;
2016-05-22 22:28:37 +00:00
}
{ //vmem inspect
VBoxContainer * vmem_vb = memnew ( VBoxContainer ) ;
HBoxContainer * vmem_hb = memnew ( HBoxContainer ) ;
Label * vmlb = memnew ( Label ( TTR ( " List of Video Memory Usage by Resource: " ) + " " ) ) ;
2021-07-08 13:29:15 +00:00
vmlb - > set_theme_type_variation ( " HeaderSmall " ) ;
2016-05-22 22:28:37 +00:00
vmlb - > set_h_size_flags ( SIZE_EXPAND_FILL ) ;
vmem_hb - > add_child ( vmlb ) ;
vmem_hb - > add_child ( memnew ( Label ( TTR ( " Total: " ) + " " ) ) ) ;
vmem_total = memnew ( LineEdit ) ;
vmem_total - > set_editable ( false ) ;
2019-09-04 05:20:57 +00:00
vmem_total - > set_custom_minimum_size ( Size2 ( 100 , 0 ) * EDSCALE ) ;
2016-05-22 22:28:37 +00:00
vmem_hb - > add_child ( vmem_total ) ;
2020-06-19 18:49:04 +00:00
vmem_refresh = memnew ( Button ) ;
vmem_refresh - > set_flat ( true ) ;
2016-05-22 22:28:37 +00:00
vmem_hb - > add_child ( vmem_refresh ) ;
2020-06-19 18:49:04 +00:00
vmem_export = memnew ( Button ) ;
vmem_export - > set_flat ( true ) ;
2022-08-25 10:42:17 +00:00
vmem_export - > set_tooltip_text ( TTR ( " Export list to a CSV file " ) ) ;
2020-03-17 12:46:18 +00:00
vmem_hb - > add_child ( vmem_export ) ;
2016-05-22 22:28:37 +00:00
vmem_vb - > add_child ( vmem_hb ) ;
2020-02-21 17:28:45 +00:00
vmem_refresh - > connect ( " pressed " , callable_mp ( this , & ScriptEditorDebugger : : _video_mem_request ) ) ;
2020-03-17 12:46:18 +00:00
vmem_export - > connect ( " pressed " , callable_mp ( this , & ScriptEditorDebugger : : _video_mem_export ) ) ;
2016-05-22 22:28:37 +00:00
2017-08-08 02:55:24 +00:00
VBoxContainer * vmmc = memnew ( VBoxContainer ) ;
2016-05-22 22:28:37 +00:00
vmem_tree = memnew ( Tree ) ;
vmem_tree - > set_v_size_flags ( SIZE_EXPAND_FILL ) ;
vmem_tree - > set_h_size_flags ( SIZE_EXPAND_FILL ) ;
vmmc - > add_child ( vmem_tree ) ;
vmmc - > set_v_size_flags ( SIZE_EXPAND_FILL ) ;
vmem_vb - > add_child ( vmmc ) ;
2019-11-28 15:37:15 +00:00
vmem_vb - > set_name ( TTR ( " Video RAM " ) ) ;
2016-05-22 22:28:37 +00:00
vmem_tree - > set_columns ( 4 ) ;
vmem_tree - > set_column_titles_visible ( true ) ;
vmem_tree - > set_column_title ( 0 , TTR ( " Resource Path " ) ) ;
vmem_tree - > set_column_expand ( 0 , true ) ;
vmem_tree - > set_column_expand ( 1 , false ) ;
vmem_tree - > set_column_title ( 1 , TTR ( " Type " ) ) ;
2021-06-28 13:40:56 +00:00
vmem_tree - > set_column_custom_minimum_width ( 1 , 100 * EDSCALE ) ;
2016-05-22 22:28:37 +00:00
vmem_tree - > set_column_expand ( 2 , false ) ;
vmem_tree - > set_column_title ( 2 , TTR ( " Format " ) ) ;
2021-06-28 13:40:56 +00:00
vmem_tree - > set_column_custom_minimum_width ( 2 , 150 * EDSCALE ) ;
2016-05-22 22:28:37 +00:00
vmem_tree - > set_column_expand ( 3 , false ) ;
vmem_tree - > set_column_title ( 3 , TTR ( " Usage " ) ) ;
2021-06-28 13:40:56 +00:00
vmem_tree - > set_column_custom_minimum_width ( 3 , 80 * EDSCALE ) ;
2016-05-22 22:28:37 +00:00
vmem_tree - > set_hide_root ( true ) ;
tabs - > add_child ( vmem_vb ) ;
}
{ // misc
2019-02-18 00:25:26 +00:00
VBoxContainer * misc = memnew ( VBoxContainer ) ;
misc - > set_name ( TTR ( " Misc " ) ) ;
tabs - > add_child ( misc ) ;
2017-07-18 06:09:19 +00:00
GridContainer * info_left = memnew ( GridContainer ) ;
info_left - > set_columns ( 2 ) ;
2019-02-18 00:25:26 +00:00
misc - > add_child ( info_left ) ;
2016-05-22 22:28:37 +00:00
clicked_ctrl = memnew ( LineEdit ) ;
2022-08-18 19:34:12 +00:00
clicked_ctrl - > set_editable ( false ) ;
2017-07-18 06:09:19 +00:00
clicked_ctrl - > set_h_size_flags ( SIZE_EXPAND_FILL ) ;
info_left - > add_child ( memnew ( Label ( TTR ( " Clicked Control: " ) ) ) ) ;
info_left - > add_child ( clicked_ctrl ) ;
2016-05-22 22:28:37 +00:00
clicked_ctrl_type = memnew ( LineEdit ) ;
2022-08-18 19:34:12 +00:00
clicked_ctrl_type - > set_editable ( false ) ;
2017-07-18 06:09:19 +00:00
info_left - > add_child ( memnew ( Label ( TTR ( " Clicked Control Type: " ) ) ) ) ;
info_left - > add_child ( clicked_ctrl_type ) ;
2016-05-22 22:28:37 +00:00
2020-02-07 01:52:05 +00:00
scene_tree = memnew ( SceneDebuggerTree ) ;
2016-05-22 22:28:37 +00:00
live_edit_root = memnew ( LineEdit ) ;
2022-08-18 19:34:12 +00:00
live_edit_root - > set_editable ( false ) ;
2017-07-18 06:09:19 +00:00
live_edit_root - > set_h_size_flags ( SIZE_EXPAND_FILL ) ;
2016-05-22 22:28:37 +00:00
{
HBoxContainer * lehb = memnew ( HBoxContainer ) ;
2017-05-02 21:02:06 +00:00
Label * l = memnew ( Label ( TTR ( " Live Edit Root: " ) ) ) ;
2017-07-18 06:09:19 +00:00
info_left - > add_child ( l ) ;
lehb - > add_child ( live_edit_root ) ;
2016-05-22 22:28:37 +00:00
le_set = memnew ( Button ( TTR ( " Set From Tree " ) ) ) ;
lehb - > add_child ( le_set ) ;
le_clear = memnew ( Button ( TTR ( " Clear " ) ) ) ;
lehb - > add_child ( le_clear ) ;
2017-05-02 21:02:06 +00:00
info_left - > add_child ( lehb ) ;
2016-05-22 22:28:37 +00:00
}
2019-02-18 00:25:26 +00:00
misc - > add_child ( memnew ( VSeparator ) ) ;
HBoxContainer * buttons = memnew ( HBoxContainer ) ;
export_csv = memnew ( Button ( TTR ( " Export measures as CSV " ) ) ) ;
2020-02-21 17:28:45 +00:00
export_csv - > connect ( " pressed " , callable_mp ( this , & ScriptEditorDebugger : : _export_csv ) ) ;
2019-02-18 00:25:26 +00:00
buttons - > add_child ( export_csv ) ;
misc - > add_child ( buttons ) ;
2015-08-02 15:29:37 +00:00
}
2014-02-13 21:03:28 +00:00
msgdialog = memnew ( AcceptDialog ) ;
add_child ( msgdialog ) ;
2018-11-11 12:14:06 +00:00
live_debug = true ;
2020-02-24 05:21:15 +00:00
camera_override = CameraOverride : : OVERRIDE_NONE ;
2015-08-02 15:29:37 +00:00
last_path_id = false ;
2015-08-04 12:47:32 +00:00
error_count = 0 ;
2018-08-16 05:41:03 +00:00
warning_count = 0 ;
2020-02-07 01:52:05 +00:00
_update_buttons_state ( ) ;
2014-02-13 21:03:28 +00:00
}
ScriptEditorDebugger : : ~ ScriptEditorDebugger ( ) {
2020-02-24 05:21:15 +00:00
if ( peer . is_valid ( ) ) {
peer - > close ( ) ;
peer . unref ( ) ;
}
2020-02-07 01:52:05 +00:00
memdelete ( scene_tree ) ;
2014-02-13 21:03:28 +00:00
}