2016-08-03 15:16:20 +00:00
/*************************************************************************/
/* script_text_editor.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
2017-08-27 12:16:55 +00:00
/* https://godotengine.org */
2016-08-03 15:16:20 +00:00
/*************************************************************************/
2021-01-01 19:13:46 +00:00
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
2016-08-03 15:16:20 +00:00
/* */
/* 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
2016-08-02 22:11:05 +00:00
# include "script_text_editor.h"
2017-01-16 07:04:19 +00:00
2019-08-07 14:31:33 +00:00
# include "core/math/expression.h"
2018-09-11 16:13:45 +00:00
# include "core/os/keyboard.h"
2020-02-07 01:52:05 +00:00
# include "editor/debugger/editor_debugger_node.h"
2021-05-29 13:28:16 +00:00
# include "editor/editor_command_palette.h"
2017-03-05 15:44:50 +00:00
# include "editor/editor_node.h"
2019-12-24 07:17:23 +00:00
# include "editor/editor_scale.h"
2017-03-05 13:21:25 +00:00
# include "editor/editor_settings.h"
2016-08-02 22:11:05 +00:00
2019-04-20 11:51:25 +00:00
void ConnectionInfoDialog : : ok_pressed ( ) {
}
void ConnectionInfoDialog : : popup_connections ( String p_method , Vector < Node * > p_nodes ) {
method - > set_text ( p_method ) ;
tree - > clear ( ) ;
TreeItem * root = tree - > create_item ( ) ;
for ( int i = 0 ; i < p_nodes . size ( ) ; i + + ) {
List < Connection > all_connections ;
p_nodes [ i ] - > get_signals_connected_to_this ( & all_connections ) ;
2021-07-24 13:46:25 +00:00
for ( const Connection & connection : all_connections ) {
2020-02-19 19:27:19 +00:00
if ( connection . callable . get_method ( ) ! = p_method ) {
2019-04-20 11:51:25 +00:00
continue ;
}
TreeItem * node_item = tree - > create_item ( root ) ;
2020-02-19 19:27:19 +00:00
node_item - > set_text ( 0 , Object : : cast_to < Node > ( connection . signal . get_object ( ) ) - > get_name ( ) ) ;
node_item - > set_icon ( 0 , EditorNode : : get_singleton ( ) - > get_object_icon ( connection . signal . get_object ( ) , " Node " ) ) ;
2019-04-20 11:51:25 +00:00
node_item - > set_selectable ( 0 , false ) ;
node_item - > set_editable ( 0 , false ) ;
2020-02-19 19:27:19 +00:00
node_item - > set_text ( 1 , connection . signal . get_name ( ) ) ;
2020-03-06 17:00:16 +00:00
Control * p = Object : : cast_to < Control > ( get_parent ( ) ) ;
2021-07-17 21:22:52 +00:00
node_item - > set_icon ( 1 , p - > get_theme_icon ( SNAME ( " Slot " ) , SNAME ( " EditorIcons " ) ) ) ;
2019-04-20 11:51:25 +00:00
node_item - > set_selectable ( 1 , false ) ;
node_item - > set_editable ( 1 , false ) ;
2020-02-19 19:27:19 +00:00
node_item - > set_text ( 2 , Object : : cast_to < Node > ( connection . callable . get_object ( ) ) - > get_name ( ) ) ;
node_item - > set_icon ( 2 , EditorNode : : get_singleton ( ) - > get_object_icon ( connection . callable . get_object ( ) , " Node " ) ) ;
2019-04-20 11:51:25 +00:00
node_item - > set_selectable ( 2 , false ) ;
node_item - > set_editable ( 2 , false ) ;
}
}
2020-02-15 15:36:10 +00:00
popup_centered ( Size2 ( 600 , 300 ) * EDSCALE ) ;
2019-04-20 11:51:25 +00:00
}
ConnectionInfoDialog : : ConnectionInfoDialog ( ) {
set_title ( TTR ( " Connections to method: " ) ) ;
VBoxContainer * vbc = memnew ( VBoxContainer ) ;
2020-12-22 16:24:29 +00:00
vbc - > set_anchor_and_offset ( SIDE_LEFT , Control : : ANCHOR_BEGIN , 8 * EDSCALE ) ;
vbc - > set_anchor_and_offset ( SIDE_TOP , Control : : ANCHOR_BEGIN , 8 * EDSCALE ) ;
vbc - > set_anchor_and_offset ( SIDE_RIGHT , Control : : ANCHOR_END , - 8 * EDSCALE ) ;
vbc - > set_anchor_and_offset ( SIDE_BOTTOM , Control : : ANCHOR_END , - 8 * EDSCALE ) ;
2019-04-20 11:51:25 +00:00
add_child ( vbc ) ;
method = memnew ( Label ) ;
method - > set_align ( Label : : ALIGN_CENTER ) ;
vbc - > add_child ( method ) ;
tree = memnew ( Tree ) ;
tree - > set_columns ( 3 ) ;
tree - > set_hide_root ( true ) ;
tree - > set_column_titles_visible ( true ) ;
tree - > set_column_title ( 0 , TTR ( " Source " ) ) ;
tree - > set_column_title ( 1 , TTR ( " Signal " ) ) ;
tree - > set_column_title ( 2 , TTR ( " Target " ) ) ;
vbc - > add_child ( tree ) ;
2020-03-06 17:00:16 +00:00
tree - > set_v_size_flags ( Control : : SIZE_EXPAND_FILL ) ;
2019-04-20 11:51:25 +00:00
tree - > set_allow_rmb_select ( true ) ;
}
////////////////////////////////////////////////////////////////////////////////
2017-03-05 15:44:50 +00:00
Vector < String > ScriptTextEditor : : get_functions ( ) {
2020-07-24 14:50:35 +00:00
CodeEdit * te = code_editor - > get_text_editor ( ) ;
2016-08-02 22:11:05 +00:00
String text = te - > get_text ( ) ;
List < String > fnc ;
2021-05-18 03:09:19 +00:00
if ( script - > get_language ( ) - > validate ( text , script - > get_path ( ) , & fnc ) ) {
2016-08-02 22:11:05 +00:00
//if valid rewrite functions to latest
functions . clear ( ) ;
2021-07-24 13:46:25 +00:00
for ( const String & E : fnc ) {
2021-07-16 03:45:57 +00:00
functions . push_back ( E ) ;
2016-08-02 22:11:05 +00:00
}
}
return functions ;
}
void ScriptTextEditor : : apply_code ( ) {
2020-05-14 14:41:43 +00:00
if ( script . is_null ( ) ) {
2016-08-02 22:11:05 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2020-07-24 14:50:35 +00:00
script - > set_source_code ( code_editor - > get_text_editor ( ) - > get_text ( ) ) ;
2016-08-02 22:11:05 +00:00
script - > update_exports ( ) ;
2020-07-24 14:50:35 +00:00
code_editor - > get_text_editor ( ) - > get_syntax_highlighter ( ) - > update_cache ( ) ;
2016-08-02 22:11:05 +00:00
}
2018-05-28 15:52:28 +00:00
RES ScriptTextEditor : : get_edited_resource ( ) const {
2016-08-02 22:11:05 +00:00
return script ;
}
2018-05-28 15:52:28 +00:00
void ScriptTextEditor : : set_edited_resource ( const RES & p_res ) {
2019-11-20 09:09:59 +00:00
ERR_FAIL_COND ( script . is_valid ( ) ) ;
ERR_FAIL_COND ( p_res . is_null ( ) ) ;
2018-05-28 15:52:28 +00:00
script = p_res ;
2020-07-24 14:50:35 +00:00
code_editor - > get_text_editor ( ) - > set_text ( script - > get_source_code ( ) ) ;
code_editor - > get_text_editor ( ) - > clear_undo_history ( ) ;
code_editor - > get_text_editor ( ) - > tag_saved_version ( ) ;
2018-05-28 15:52:28 +00:00
2021-07-17 21:22:52 +00:00
emit_signal ( SNAME ( " name_changed " ) ) ;
2018-05-28 15:52:28 +00:00
code_editor - > update_line_and_column ( ) ;
2019-11-20 09:09:59 +00:00
}
void ScriptTextEditor : : enable_editor ( ) {
if ( editor_enabled ) {
return ;
}
editor_enabled = true ;
_enable_code_editor ( ) ;
2019-04-16 00:14:58 +00:00
_validate_script ( ) ;
2018-05-28 15:52:28 +00:00
}
2016-08-02 22:11:05 +00:00
void ScriptTextEditor : : _load_theme_settings ( ) {
2020-07-24 14:50:35 +00:00
CodeEdit * text_edit = code_editor - > get_text_editor ( ) ;
2016-08-02 22:11:05 +00:00
2021-08-15 17:14:46 +00:00
Color updated_marked_line_color = EDITOR_GET ( " text_editor/theme/highlighting/mark_color " ) ;
Color updated_safe_line_number_color = EDITOR_GET ( " text_editor/theme/highlighting/safe_line_number_color " ) ;
2020-09-10 20:25:00 +00:00
bool safe_line_number_color_updated = updated_safe_line_number_color ! = safe_line_number_color ;
bool marked_line_color_updated = updated_marked_line_color ! = marked_line_color ;
if ( safe_line_number_color_updated | | marked_line_color_updated ) {
2020-07-30 10:41:05 +00:00
safe_line_number_color = updated_safe_line_number_color ;
for ( int i = 0 ; i < text_edit - > get_line_count ( ) ; i + + ) {
2020-09-10 20:25:00 +00:00
if ( marked_line_color_updated & & text_edit - > get_line_background_color ( i ) = = marked_line_color ) {
text_edit - > set_line_background_color ( i , updated_marked_line_color ) ;
}
if ( safe_line_number_color_updated & & text_edit - > get_line_gutter_item_color ( i , line_number_gutter ) ! = default_line_number_color ) {
2020-07-30 10:41:05 +00:00
text_edit - > set_line_gutter_item_color ( i , line_number_gutter , safe_line_number_color ) ;
}
}
2020-09-10 20:25:00 +00:00
marked_line_color = updated_marked_line_color ;
2020-07-30 10:41:05 +00:00
}
2017-10-02 23:33:42 +00:00
theme_loaded = true ;
2020-05-14 14:41:43 +00:00
if ( ! script . is_null ( ) ) {
2017-10-02 23:33:42 +00:00
_set_theme_for_script ( ) ;
2020-05-14 14:41:43 +00:00
}
2017-10-02 23:33:42 +00:00
}
void ScriptTextEditor : : _set_theme_for_script ( ) {
2020-05-14 14:41:43 +00:00
if ( ! theme_loaded ) {
2017-10-02 23:33:42 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2017-10-02 23:33:42 +00:00
2020-07-24 14:50:35 +00:00
CodeEdit * text_edit = code_editor - > get_text_editor ( ) ;
2020-05-03 16:08:15 +00:00
text_edit - > get_syntax_highlighter ( ) - > update_cache ( ) ;
2017-10-02 23:33:42 +00:00
2020-09-10 20:25:40 +00:00
List < String > strings ;
script - > get_language ( ) - > get_string_delimiters ( & strings ) ;
text_edit - > clear_string_delimiters ( ) ;
2021-07-24 13:46:25 +00:00
for ( const String & string : strings ) {
2020-09-10 20:25:40 +00:00
String beg = string . get_slice ( " " , 0 ) ;
String end = string . get_slice_count ( " " ) > 1 ? string . get_slice ( " " , 1 ) : String ( ) ;
2021-07-01 16:40:59 +00:00
if ( ! text_edit - > has_string_delimiter ( beg ) ) {
text_edit - > add_string_delimiter ( beg , end , end = = " " ) ;
}
2021-06-28 16:14:44 +00:00
if ( ! end . is_empty ( ) & & ! text_edit - > has_auto_brace_completion_open_key ( beg ) ) {
text_edit - > add_auto_brace_completion_pair ( beg , end ) ;
}
2020-09-10 20:25:40 +00:00
}
List < String > comments ;
script - > get_language ( ) - > get_comment_delimiters ( & comments ) ;
text_edit - > clear_comment_delimiters ( ) ;
2021-07-24 13:46:25 +00:00
for ( const String & comment : comments ) {
2020-09-10 20:25:40 +00:00
String beg = comment . get_slice ( " " , 0 ) ;
String end = comment . get_slice_count ( " " ) > 1 ? comment . get_slice ( " " , 1 ) : String ( ) ;
text_edit - > add_comment_delimiter ( beg , end , end = = " " ) ;
2021-06-28 16:14:44 +00:00
if ( ! end . is_empty ( ) & & ! text_edit - > has_auto_brace_completion_open_key ( beg ) ) {
text_edit - > add_auto_brace_completion_pair ( beg , end ) ;
}
2020-09-10 20:25:40 +00:00
}
2016-08-02 22:11:05 +00:00
}
2021-05-18 03:09:19 +00:00
void ScriptTextEditor : : _show_errors_panel ( bool p_show ) {
errors_panel - > set_visible ( p_show ) ;
}
2019-02-13 09:12:31 +00:00
void ScriptTextEditor : : _show_warnings_panel ( bool p_show ) {
warnings_panel - > set_visible ( p_show ) ;
2018-07-01 16:17:40 +00:00
}
void ScriptTextEditor : : _warning_clicked ( Variant p_line ) {
if ( p_line . get_type ( ) = = Variant : : INT ) {
2021-05-12 10:45:30 +00:00
goto_line_centered ( p_line . operator int64_t ( ) ) ;
2018-07-01 16:17:40 +00:00
} else if ( p_line . get_type ( ) = = Variant : : DICTIONARY ) {
Dictionary meta = p_line . operator Dictionary ( ) ;
2021-07-10 10:41:38 +00:00
code_editor - > get_text_editor ( ) - > insert_line_at ( meta [ " line " ] . operator int64_t ( ) - 1 , " # warning-ignore: " + meta [ " code " ] . operator String ( ) ) ;
2018-07-01 16:17:40 +00:00
_validate_script ( ) ;
}
}
2021-05-18 03:09:19 +00:00
void ScriptTextEditor : : _error_clicked ( Variant p_line ) {
if ( p_line . get_type ( ) = = Variant : : INT ) {
2021-07-08 17:35:56 +00:00
code_editor - > get_text_editor ( ) - > set_caret_line ( p_line . operator int64_t ( ) ) ;
2021-05-18 03:09:19 +00:00
}
}
2016-08-02 22:11:05 +00:00
void ScriptTextEditor : : reload_text ( ) {
2017-03-05 15:44:50 +00:00
ERR_FAIL_COND ( script . is_null ( ) ) ;
2016-08-02 22:11:05 +00:00
2020-07-24 14:50:35 +00:00
CodeEdit * te = code_editor - > get_text_editor ( ) ;
2021-07-08 17:35:56 +00:00
int column = te - > get_caret_column ( ) ;
int row = te - > get_caret_line ( ) ;
2016-08-02 22:11:05 +00:00
int h = te - > get_h_scroll ( ) ;
int v = te - > get_v_scroll ( ) ;
te - > set_text ( script - > get_source_code ( ) ) ;
2021-07-08 17:35:56 +00:00
te - > set_caret_line ( row ) ;
te - > set_caret_column ( column ) ;
2016-08-02 22:11:05 +00:00
te - > set_h_scroll ( h ) ;
te - > set_v_scroll ( v ) ;
te - > tag_saved_version ( ) ;
code_editor - > update_line_and_column ( ) ;
}
2020-02-17 21:06:54 +00:00
void ScriptTextEditor : : add_callback ( const String & p_function , PackedStringArray p_args ) {
2020-07-24 14:50:35 +00:00
String code = code_editor - > get_text_editor ( ) - > get_text ( ) ;
2017-03-05 15:44:50 +00:00
int pos = script - > get_language ( ) - > find_function ( p_function , code ) ;
if ( pos = = - 1 ) {
2016-08-02 22:11:05 +00:00
//does not exist
2020-07-24 14:50:35 +00:00
code_editor - > get_text_editor ( ) - > deselect ( ) ;
pos = code_editor - > get_text_editor ( ) - > get_line_count ( ) + 2 ;
2017-03-05 15:44:50 +00:00
String func = script - > get_language ( ) - > make_function ( " " , p_function , p_args ) ;
2016-08-02 22:11:05 +00:00
//code=code+func;
2021-07-08 17:35:56 +00:00
code_editor - > get_text_editor ( ) - > set_caret_line ( pos + 1 ) ;
code_editor - > get_text_editor ( ) - > set_caret_column ( 1000000 ) ; //none shall be that big
code_editor - > get_text_editor ( ) - > insert_text_at_caret ( " \n \n " + func ) ;
2016-08-02 22:11:05 +00:00
}
2021-07-08 17:35:56 +00:00
code_editor - > get_text_editor ( ) - > set_caret_line ( pos ) ;
code_editor - > get_text_editor ( ) - > set_caret_column ( 1 ) ;
2016-08-02 22:11:05 +00:00
}
2017-05-28 14:20:38 +00:00
bool ScriptTextEditor : : show_members_overview ( ) {
return true ;
}
2016-08-02 22:11:05 +00:00
void ScriptTextEditor : : update_settings ( ) {
2021-08-15 17:14:46 +00:00
code_editor - > get_text_editor ( ) - > set_gutter_draw ( connection_gutter , EditorSettings : : get_singleton ( ) - > get ( " text_editor/appearance/gutters/show_info_gutter " ) ) ;
2016-10-10 08:38:12 +00:00
code_editor - > update_editor_settings ( ) ;
2016-08-02 22:11:05 +00:00
}
2017-03-05 15:44:50 +00:00
bool ScriptTextEditor : : is_unsaved ( ) {
2020-07-23 12:21:28 +00:00
const bool unsaved =
2020-07-24 14:50:35 +00:00
code_editor - > get_text_editor ( ) - > get_version ( ) ! = code_editor - > get_text_editor ( ) - > get_saved_version ( ) | |
2020-12-15 12:04:21 +00:00
script - > get_path ( ) . is_empty ( ) ; // In memory.
2020-07-23 12:21:28 +00:00
return unsaved ;
2016-08-02 22:11:05 +00:00
}
Variant ScriptTextEditor : : get_edit_state ( ) {
2018-05-25 22:49:35 +00:00
return code_editor - > get_edit_state ( ) ;
}
2016-08-02 22:11:05 +00:00
2018-05-25 22:49:35 +00:00
void ScriptTextEditor : : set_edit_state ( const Variant & p_state ) {
code_editor - > set_edit_state ( p_state ) ;
2019-04-13 11:43:35 +00:00
Dictionary state = p_state ;
if ( state . has ( " syntax_highlighter " ) ) {
int idx = highlighter_menu - > get_item_idx_from_text ( state [ " syntax_highlighter " ] ) ;
if ( idx > = 0 ) {
_change_syntax_highlighter ( idx ) ;
}
}
2019-11-20 09:09:59 +00:00
if ( editor_enabled ) {
ensure_focus ( ) ;
}
2016-08-02 22:11:05 +00:00
}
2018-05-25 22:49:35 +00:00
void ScriptTextEditor : : _convert_case ( CodeTextEditor : : CaseStyle p_case ) {
code_editor - > convert_case ( p_case ) ;
2017-04-24 18:59:55 +00:00
}
2016-08-02 22:11:05 +00:00
void ScriptTextEditor : : trim_trailing_whitespace ( ) {
2018-05-25 22:49:35 +00:00
code_editor - > trim_trailing_whitespace ( ) ;
2016-08-02 22:11:05 +00:00
}
2019-05-28 21:27:32 +00:00
void ScriptTextEditor : : insert_final_newline ( ) {
code_editor - > insert_final_newline ( ) ;
}
2017-04-16 15:47:59 +00:00
void ScriptTextEditor : : convert_indent_to_spaces ( ) {
2018-05-25 22:49:35 +00:00
code_editor - > convert_indent_to_spaces ( ) ;
2017-04-16 15:47:59 +00:00
}
void ScriptTextEditor : : convert_indent_to_tabs ( ) {
2018-05-25 22:49:35 +00:00
code_editor - > convert_indent_to_tabs ( ) ;
2017-04-16 15:47:59 +00:00
}
2016-08-02 22:11:05 +00:00
void ScriptTextEditor : : tag_saved_version ( ) {
2020-07-24 14:50:35 +00:00
code_editor - > get_text_editor ( ) - > tag_saved_version ( ) ;
2016-08-02 22:11:05 +00:00
}
2016-08-06 22:00:54 +00:00
void ScriptTextEditor : : goto_line ( int p_line , bool p_with_error ) {
2018-05-25 22:49:35 +00:00
code_editor - > goto_line ( p_line ) ;
2018-02-12 01:36:15 +00:00
}
2018-05-25 22:49:35 +00:00
void ScriptTextEditor : : goto_line_selection ( int p_line , int p_begin , int p_end ) {
code_editor - > goto_line_selection ( p_line , p_begin , p_end ) ;
2016-08-02 22:11:05 +00:00
}
2019-01-04 12:09:01 +00:00
void ScriptTextEditor : : goto_line_centered ( int p_line ) {
code_editor - > goto_line_centered ( p_line ) ;
}
2019-04-22 16:20:27 +00:00
void ScriptTextEditor : : set_executing_line ( int p_line ) {
code_editor - > set_executing_line ( p_line ) ;
}
void ScriptTextEditor : : clear_executing_line ( ) {
code_editor - > clear_executing_line ( ) ;
}
2018-05-25 22:49:35 +00:00
void ScriptTextEditor : : ensure_focus ( ) {
2020-07-24 14:50:35 +00:00
code_editor - > get_text_editor ( ) - > grab_focus ( ) ;
2016-08-02 22:11:05 +00:00
}
2017-03-05 15:44:50 +00:00
String ScriptTextEditor : : get_name ( ) {
2016-08-02 22:11:05 +00:00
String name ;
2017-03-05 15:44:50 +00:00
if ( script - > get_path ( ) . find ( " local:// " ) = = - 1 & & script - > get_path ( ) . find ( " :: " ) = = - 1 ) {
name = script - > get_path ( ) . get_file ( ) ;
2016-08-02 22:11:05 +00:00
if ( is_unsaved ( ) ) {
2020-12-15 12:04:21 +00:00
if ( script - > get_path ( ) . is_empty ( ) ) {
2020-07-23 12:21:28 +00:00
name = TTR ( " [unsaved] " ) ;
}
2017-03-05 15:44:50 +00:00
name + = " (*) " ;
2016-08-02 22:11:05 +00:00
}
2020-05-14 14:41:43 +00:00
} else if ( script - > get_name ( ) ! = " " ) {
2017-03-05 15:44:50 +00:00
name = script - > get_name ( ) ;
2020-05-14 14:41:43 +00:00
} else {
2017-08-07 10:17:31 +00:00
name = script - > get_class ( ) + " ( " + itos ( script - > get_instance_id ( ) ) + " ) " ;
2020-05-14 14:41:43 +00:00
}
2016-08-02 22:11:05 +00:00
return name ;
}
2020-03-12 12:37:40 +00:00
Ref < Texture2D > ScriptTextEditor : : get_theme_icon ( ) {
if ( get_parent_control ( ) & & get_parent_control ( ) - > has_theme_icon ( script - > get_class ( ) , " EditorIcons " ) ) {
return get_parent_control ( ) - > get_theme_icon ( script - > get_class ( ) , " EditorIcons " ) ;
2016-08-02 22:11:05 +00:00
}
2019-06-11 18:43:37 +00:00
return Ref < Texture2D > ( ) ;
2016-08-02 22:11:05 +00:00
}
void ScriptTextEditor : : _validate_script ( ) {
2020-07-24 14:50:35 +00:00
CodeEdit * te = code_editor - > get_text_editor ( ) ;
2016-08-02 22:11:05 +00:00
String text = te - > get_text ( ) ;
List < String > fnc ;
2018-06-05 16:50:21 +00:00
Set < int > safe_lines ;
2018-07-01 16:17:40 +00:00
List < ScriptLanguage : : Warning > warnings ;
2021-05-18 03:09:19 +00:00
List < ScriptLanguage : : ScriptError > errors ;
2016-08-02 22:11:05 +00:00
2021-05-18 03:09:19 +00:00
if ( ! script - > get_language ( ) - > validate ( text , script - > get_path ( ) , & fnc , & errors , & warnings , & safe_lines ) ) {
String error_text = TTR ( " Error at " ) + " ( " + itos ( errors [ 0 ] . line ) + " , " + itos ( errors [ 0 ] . column ) + " ): " + errors [ 0 ] . message ;
2016-08-02 22:11:05 +00:00
code_editor - > set_error ( error_text ) ;
2021-05-18 03:09:19 +00:00
code_editor - > set_error_pos ( errors [ 0 ] . line - 1 , errors [ 0 ] . column - 1 ) ;
2019-11-02 13:38:25 +00:00
script_is_valid = false ;
2016-08-02 22:11:05 +00:00
} else {
code_editor - > set_error ( " " ) ;
if ( ! script - > is_tool ( ) ) {
script - > set_source_code ( text ) ;
script - > update_exports ( ) ;
2020-05-03 16:08:15 +00:00
te - > get_syntax_highlighter ( ) - > update_cache ( ) ;
2016-08-02 22:11:05 +00:00
}
functions . clear ( ) ;
2021-07-24 13:46:25 +00:00
for ( const String & E : fnc ) {
2021-07-16 03:45:57 +00:00
functions . push_back ( E ) ;
2016-08-02 22:11:05 +00:00
}
2019-11-02 13:38:25 +00:00
script_is_valid = true ;
2016-08-02 22:11:05 +00:00
}
2019-04-20 11:51:25 +00:00
_update_connected_methods ( ) ;
2016-08-02 22:11:05 +00:00
2019-06-11 22:48:35 +00:00
int warning_nb = warnings . size ( ) ;
2018-07-01 16:17:40 +00:00
warnings_panel - > clear ( ) ;
2019-04-20 11:51:25 +00:00
2019-06-11 22:48:35 +00:00
// Add missing connections.
if ( GLOBAL_GET ( " debug/gdscript/warnings/enable " ) . booleanize ( ) ) {
Node * base = get_tree ( ) - > get_edited_scene_root ( ) ;
if ( base & & missing_connections . size ( ) > 0 ) {
warnings_panel - > push_table ( 1 ) ;
2021-07-24 13:46:25 +00:00
for ( const Connection & connection : missing_connections ) {
2019-06-11 22:48:35 +00:00
String base_path = base - > get_name ( ) ;
2020-02-19 19:27:19 +00:00
String source_path = base = = connection . signal . get_object ( ) ? base_path : base_path + " / " + base - > get_path_to ( Object : : cast_to < Node > ( connection . signal . get_object ( ) ) ) ;
String target_path = base = = connection . callable . get_object ( ) ? base_path : base_path + " / " + base - > get_path_to ( Object : : cast_to < Node > ( connection . callable . get_object ( ) ) ) ;
2019-06-11 22:48:35 +00:00
warnings_panel - > push_cell ( ) ;
2021-07-17 21:22:52 +00:00
warnings_panel - > push_color ( warnings_panel - > get_theme_color ( SNAME ( " warning_color " ) , SNAME ( " Editor " ) ) ) ;
2020-02-19 19:27:19 +00:00
warnings_panel - > add_text ( vformat ( TTR ( " Missing connected method '%s' for signal '%s' from node '%s' to node '%s'. " ) , connection . callable . get_method ( ) , connection . signal . get_name ( ) , source_path , target_path ) ) ;
2019-06-11 22:48:35 +00:00
warnings_panel - > pop ( ) ; // Color.
warnings_panel - > pop ( ) ; // Cell.
}
warnings_panel - > pop ( ) ; // Table.
2019-04-20 11:51:25 +00:00
2019-06-11 22:48:35 +00:00
warning_nb + = missing_connections . size ( ) ;
2019-04-20 11:51:25 +00:00
}
}
2021-05-18 03:09:19 +00:00
code_editor - > set_error_count ( errors . size ( ) ) ;
code_editor - > set_warning_count ( warning_nb ) ;
2019-06-11 22:48:35 +00:00
// Add script warnings.
2018-07-01 16:17:40 +00:00
warnings_panel - > push_table ( 3 ) ;
2021-07-24 13:46:25 +00:00
for ( const ScriptLanguage : : Warning & w : warnings ) {
2020-05-24 12:30:09 +00:00
Dictionary ignore_meta ;
2020-06-11 22:31:28 +00:00
ignore_meta [ " line " ] = w . start_line ;
2020-05-24 12:30:09 +00:00
ignore_meta [ " code " ] = w . string_code . to_lower ( ) ;
warnings_panel - > push_cell ( ) ;
warnings_panel - > push_meta ( ignore_meta ) ;
warnings_panel - > push_color (
2021-07-17 21:22:52 +00:00
warnings_panel - > get_theme_color ( SNAME ( " accent_color " ) , SNAME ( " Editor " ) ) . lerp ( warnings_panel - > get_theme_color ( SNAME ( " mono_color " ) , SNAME ( " Editor " ) ) , 0.5 ) ) ;
2020-05-24 12:30:09 +00:00
warnings_panel - > add_text ( TTR ( " [Ignore] " ) ) ;
warnings_panel - > pop ( ) ; // Color.
warnings_panel - > pop ( ) ; // Meta ignore.
warnings_panel - > pop ( ) ; // Cell.
2018-07-01 16:17:40 +00:00
warnings_panel - > push_cell ( ) ;
2020-06-11 22:31:28 +00:00
warnings_panel - > push_meta ( w . start_line - 1 ) ;
2021-07-17 21:22:52 +00:00
warnings_panel - > push_color ( warnings_panel - > get_theme_color ( SNAME ( " warning_color " ) , SNAME ( " Editor " ) ) ) ;
2020-06-11 22:31:28 +00:00
warnings_panel - > add_text ( TTR ( " Line " ) + " " + itos ( w . start_line ) ) ;
2018-07-01 16:17:40 +00:00
warnings_panel - > add_text ( " ( " + w . string_code + " ): " ) ;
2019-06-11 22:48:35 +00:00
warnings_panel - > pop ( ) ; // Color.
warnings_panel - > pop ( ) ; // Meta goto.
warnings_panel - > pop ( ) ; // Cell.
2018-07-01 16:17:40 +00:00
warnings_panel - > push_cell ( ) ;
warnings_panel - > add_text ( w . message ) ;
2019-06-11 22:48:35 +00:00
warnings_panel - > pop ( ) ; // Cell.
2018-07-01 16:17:40 +00:00
}
2019-06-11 22:48:35 +00:00
warnings_panel - > pop ( ) ; // Table.
2018-07-01 16:17:40 +00:00
2021-05-18 03:09:19 +00:00
errors_panel - > clear ( ) ;
errors_panel - > push_table ( 2 ) ;
2021-07-24 13:46:25 +00:00
for ( const ScriptLanguage : : ScriptError & err : errors ) {
2021-05-18 03:09:19 +00:00
errors_panel - > push_cell ( ) ;
errors_panel - > push_meta ( err . line - 1 ) ;
2021-07-17 21:22:52 +00:00
errors_panel - > push_color ( warnings_panel - > get_theme_color ( SNAME ( " error_color " ) , SNAME ( " Editor " ) ) ) ;
2021-05-18 03:09:19 +00:00
errors_panel - > add_text ( TTR ( " Line " ) + " " + itos ( err . line ) + " : " ) ;
errors_panel - > pop ( ) ; // Color.
errors_panel - > pop ( ) ; // Meta goto.
errors_panel - > pop ( ) ; // Cell.
errors_panel - > push_cell ( ) ;
errors_panel - > add_text ( err . message ) ;
errors_panel - > pop ( ) ; // Cell.
}
errors_panel - > pop ( ) ; // Table
2021-08-15 17:14:46 +00:00
bool highlight_safe = EDITOR_DEF ( " text_editor/appearance/gutters/highlight_type_safe_lines " , true ) ;
2018-06-05 16:50:21 +00:00
bool last_is_safe = false ;
2017-03-05 15:44:50 +00:00
for ( int i = 0 ; i < te - > get_line_count ( ) ; i + + ) {
2021-05-18 03:09:19 +00:00
if ( errors . is_empty ( ) ) {
te - > set_line_background_color ( i , Color ( 0 , 0 , 0 , 0 ) ) ;
} else {
2021-07-24 13:46:25 +00:00
for ( const ScriptLanguage : : ScriptError & E : errors ) {
2021-07-16 03:45:57 +00:00
bool error_line = i = = E . line - 1 ;
2021-05-18 03:09:19 +00:00
te - > set_line_background_color ( i , error_line ? marked_line_color : Color ( 0 , 0 , 0 , 0 ) ) ;
if ( error_line ) {
break ;
}
}
}
2018-06-05 16:50:21 +00:00
if ( highlight_safe ) {
if ( safe_lines . has ( i + 1 ) ) {
2020-07-30 10:41:05 +00:00
te - > set_line_gutter_item_color ( i , line_number_gutter , safe_line_number_color ) ;
2018-06-05 16:50:21 +00:00
last_is_safe = true ;
2021-06-15 14:05:01 +00:00
} else if ( last_is_safe & & ( te - > is_in_comment ( i ) ! = - 1 | | te - > get_line ( i ) . strip_edges ( ) . is_empty ( ) ) ) {
2020-07-30 10:41:05 +00:00
te - > set_line_gutter_item_color ( i , line_number_gutter , safe_line_number_color ) ;
2018-06-05 16:50:21 +00:00
} else {
2020-07-30 10:41:05 +00:00
te - > set_line_gutter_item_color ( i , line_number_gutter , default_line_number_color ) ;
2018-06-05 16:50:21 +00:00
last_is_safe = false ;
}
} else {
2021-05-18 03:09:19 +00:00
te - > set_line_gutter_item_color ( i , 1 , default_line_number_color ) ;
2018-06-05 16:50:21 +00:00
}
2016-08-02 22:11:05 +00:00
}
2021-07-17 21:22:52 +00:00
emit_signal ( SNAME ( " name_changed " ) ) ;
emit_signal ( SNAME ( " edited_script_changed " ) ) ;
2016-08-02 22:11:05 +00:00
}
2019-05-21 08:07:48 +00:00
void ScriptTextEditor : : _update_bookmark_list ( ) {
2019-07-01 19:00:05 +00:00
bookmarks_menu - > clear ( ) ;
bookmarks_menu - > set_size ( Size2 ( 1 , 1 ) ) ;
2019-05-21 08:07:48 +00:00
2019-07-01 19:00:05 +00:00
bookmarks_menu - > add_shortcut ( ED_GET_SHORTCUT ( " script_text_editor/toggle_bookmark " ) , BOOKMARK_TOGGLE ) ;
bookmarks_menu - > add_shortcut ( ED_GET_SHORTCUT ( " script_text_editor/remove_all_bookmarks " ) , BOOKMARK_REMOVE_ALL ) ;
bookmarks_menu - > add_shortcut ( ED_GET_SHORTCUT ( " script_text_editor/goto_next_bookmark " ) , BOOKMARK_GOTO_NEXT ) ;
bookmarks_menu - > add_shortcut ( ED_GET_SHORTCUT ( " script_text_editor/goto_previous_bookmark " ) , BOOKMARK_GOTO_PREV ) ;
2019-05-21 08:07:48 +00:00
2020-07-26 14:57:23 +00:00
Array bookmark_list = code_editor - > get_text_editor ( ) - > get_bookmarked_lines ( ) ;
2019-05-21 08:07:48 +00:00
if ( bookmark_list . size ( ) = = 0 ) {
return ;
}
2019-07-01 19:00:05 +00:00
bookmarks_menu - > add_separator ( ) ;
2019-05-21 08:07:48 +00:00
for ( int i = 0 ; i < bookmark_list . size ( ) ; i + + ) {
2019-12-03 16:19:57 +00:00
// Strip edges to remove spaces or tabs.
// Also replace any tabs by spaces, since we can't print tabs in the menu.
2020-07-24 14:50:35 +00:00
String line = code_editor - > get_text_editor ( ) - > get_line ( bookmark_list [ i ] ) . replace ( " \t " , " " ) . strip_edges ( ) ;
2019-12-03 16:19:57 +00:00
2019-05-21 08:07:48 +00:00
// Limit the size of the line if too big.
if ( line . length ( ) > 50 ) {
line = line . substr ( 0 , 50 ) ;
}
2019-12-03 16:19:57 +00:00
bookmarks_menu - > add_item ( String : : num ( ( int ) bookmark_list [ i ] + 1 ) + " - ` " + line + " ` " ) ;
2019-07-01 19:00:05 +00:00
bookmarks_menu - > set_item_metadata ( bookmarks_menu - > get_item_count ( ) - 1 , bookmark_list [ i ] ) ;
2019-05-21 08:07:48 +00:00
}
}
void ScriptTextEditor : : _bookmark_item_pressed ( int p_idx ) {
if ( p_idx < 4 ) { // Any item before the separator.
2019-07-01 19:00:05 +00:00
_edit_option ( bookmarks_menu - > get_item_id ( p_idx ) ) ;
2019-05-21 08:07:48 +00:00
} else {
2021-03-24 16:29:14 +00:00
code_editor - > goto_line_centered ( bookmarks_menu - > get_item_metadata ( p_idx ) ) ;
2019-05-21 08:07:48 +00:00
}
}
2019-04-20 11:51:25 +00:00
static Vector < Node * > _find_all_node_for_script ( Node * p_base , Node * p_current , const Ref < Script > & p_script ) {
Vector < Node * > nodes ;
if ( p_current - > get_owner ( ) ! = p_base & & p_base ! = p_current ) {
return nodes ;
}
Ref < Script > c = p_current - > get_script ( ) ;
if ( c = = p_script ) {
nodes . push_back ( p_current ) ;
}
for ( int i = 0 ; i < p_current - > get_child_count ( ) ; i + + ) {
Vector < Node * > found = _find_all_node_for_script ( p_base , p_current - > get_child ( i ) , p_script ) ;
nodes . append_array ( found ) ;
}
return nodes ;
}
2017-03-05 15:44:50 +00:00
static Node * _find_node_for_script ( Node * p_base , Node * p_current , const Ref < Script > & p_script ) {
2020-05-14 14:41:43 +00:00
if ( p_current - > get_owner ( ) ! = p_base & & p_base ! = p_current ) {
2020-04-01 23:20:12 +00:00
return nullptr ;
2020-05-14 14:41:43 +00:00
}
2016-08-02 22:11:05 +00:00
Ref < Script > c = p_current - > get_script ( ) ;
2020-05-14 14:41:43 +00:00
if ( c = = p_script ) {
2016-08-02 22:11:05 +00:00
return p_current ;
2020-05-14 14:41:43 +00:00
}
2017-03-05 15:44:50 +00:00
for ( int i = 0 ; i < p_current - > get_child_count ( ) ; i + + ) {
Node * found = _find_node_for_script ( p_base , p_current - > get_child ( i ) , p_script ) ;
2020-05-14 14:41:43 +00:00
if ( found ) {
2016-08-02 22:11:05 +00:00
return found ;
2020-05-14 14:41:43 +00:00
}
2016-08-02 22:11:05 +00:00
}
2020-04-01 23:20:12 +00:00
return nullptr ;
2016-08-02 22:11:05 +00:00
}
2020-03-17 06:33:00 +00:00
static void _find_changed_scripts_for_external_editor ( Node * p_base , Node * p_current , Set < Ref < Script > > & r_scripts ) {
2020-05-14 14:41:43 +00:00
if ( p_current - > get_owner ( ) ! = p_base & & p_base ! = p_current ) {
2016-08-02 22:11:05 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2016-08-02 22:11:05 +00:00
Ref < Script > c = p_current - > get_script ( ) ;
2020-05-14 14:41:43 +00:00
if ( c . is_valid ( ) ) {
2016-08-02 22:11:05 +00:00
r_scripts . insert ( c ) ;
2020-05-14 14:41:43 +00:00
}
2016-08-02 22:11:05 +00:00
2017-03-05 15:44:50 +00:00
for ( int i = 0 ; i < p_current - > get_child_count ( ) ; i + + ) {
_find_changed_scripts_for_external_editor ( p_base , p_current - > get_child ( i ) , r_scripts ) ;
2016-08-02 22:11:05 +00:00
}
}
void ScriptEditor : : _update_modified_scripts_for_external_editor ( Ref < Script > p_for_script ) {
2020-05-14 14:41:43 +00:00
if ( ! bool ( EditorSettings : : get_singleton ( ) - > get ( " text_editor/external/use_external_editor " ) ) ) {
2016-08-02 22:11:05 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2016-08-02 22:11:05 +00:00
2017-06-25 09:20:01 +00:00
ERR_FAIL_COND ( ! get_tree ( ) ) ;
2020-03-17 06:33:00 +00:00
Set < Ref < Script > > scripts ;
2016-08-02 22:11:05 +00:00
Node * base = get_tree ( ) - > get_edited_scene_root ( ) ;
if ( base ) {
2017-03-05 15:44:50 +00:00
_find_changed_scripts_for_external_editor ( base , base , scripts ) ;
2016-08-02 22:11:05 +00:00
}
2020-03-17 06:33:00 +00:00
for ( Set < Ref < Script > > : : Element * E = scripts . front ( ) ; E ; E = E - > next ( ) ) {
2016-08-02 22:11:05 +00:00
Ref < Script > script = E - > get ( ) ;
2020-05-14 14:41:43 +00:00
if ( p_for_script . is_valid ( ) & & p_for_script ! = script ) {
2016-08-02 22:11:05 +00:00
continue ;
2020-05-14 14:41:43 +00:00
}
2016-08-02 22:11:05 +00:00
2017-03-05 15:44:50 +00:00
if ( script - > get_path ( ) = = " " | | script - > get_path ( ) . find ( " local:// " ) ! = - 1 | | script - > get_path ( ) . find ( " :: " ) ! = - 1 ) {
2016-08-02 22:11:05 +00:00
continue ; //internal script, who cares, though weird
}
uint64_t last_date = script - > get_last_modified_time ( ) ;
uint64_t date = FileAccess : : get_modified_time ( script - > get_path ( ) ) ;
2017-03-05 15:44:50 +00:00
if ( last_date ! = date ) {
2021-02-11 17:18:45 +00:00
Ref < Script > rel_script = ResourceLoader : : load ( script - > get_path ( ) , script - > get_class ( ) , ResourceFormatLoader : : CACHE_MODE_IGNORE ) ;
2016-08-02 22:11:05 +00:00
ERR_CONTINUE ( ! rel_script . is_valid ( ) ) ;
2017-03-05 15:44:50 +00:00
script - > set_source_code ( rel_script - > get_source_code ( ) ) ;
script - > set_last_modified_time ( rel_script - > get_last_modified_time ( ) ) ;
2016-08-02 22:11:05 +00:00
script - > update_exports ( ) ;
2021-08-17 08:32:23 +00:00
_trigger_live_script_reload ( ) ;
2016-08-02 22:11:05 +00:00
}
}
}
2019-06-13 09:17:20 +00:00
void ScriptTextEditor : : _code_complete_scripts ( void * p_ud , const String & p_code , List < ScriptCodeCompletionOption > * r_options , bool & r_force ) {
2016-08-02 22:11:05 +00:00
ScriptTextEditor * ste = ( ScriptTextEditor * ) p_ud ;
2017-08-24 03:06:56 +00:00
ste - > _code_complete_script ( p_code , r_options , r_force ) ;
2016-08-02 22:11:05 +00:00
}
2019-06-13 09:17:20 +00:00
void ScriptTextEditor : : _code_complete_script ( const String & p_code , List < ScriptCodeCompletionOption > * r_options , bool & r_force ) {
2020-05-14 14:41:43 +00:00
if ( color_panel - > is_visible ( ) ) {
2020-05-10 10:56:01 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2016-08-02 22:11:05 +00:00
Node * base = get_tree ( ) - > get_edited_scene_root ( ) ;
if ( base ) {
2017-03-05 15:44:50 +00:00
base = _find_node_for_script ( base , base , script ) ;
2016-08-02 22:11:05 +00:00
}
String hint ;
2019-04-16 20:27:13 +00:00
Error err = script - > get_language ( ) - > complete_code ( p_code , script - > get_path ( ) , base , r_options , r_force , hint ) ;
2019-10-02 09:21:48 +00:00
if ( err = = OK ) {
2020-07-24 14:50:35 +00:00
code_editor - > get_text_editor ( ) - > set_code_hint ( hint ) ;
2016-08-02 22:11:05 +00:00
}
}
2019-07-01 19:00:05 +00:00
void ScriptTextEditor : : _update_breakpoint_list ( ) {
breakpoints_menu - > clear ( ) ;
breakpoints_menu - > set_size ( Size2 ( 1 , 1 ) ) ;
breakpoints_menu - > add_shortcut ( ED_GET_SHORTCUT ( " script_text_editor/toggle_breakpoint " ) , DEBUG_TOGGLE_BREAKPOINT ) ;
breakpoints_menu - > add_shortcut ( ED_GET_SHORTCUT ( " script_text_editor/remove_all_breakpoints " ) , DEBUG_REMOVE_ALL_BREAKPOINTS ) ;
breakpoints_menu - > add_shortcut ( ED_GET_SHORTCUT ( " script_text_editor/goto_next_breakpoint " ) , DEBUG_GOTO_NEXT_BREAKPOINT ) ;
breakpoints_menu - > add_shortcut ( ED_GET_SHORTCUT ( " script_text_editor/goto_previous_breakpoint " ) , DEBUG_GOTO_PREV_BREAKPOINT ) ;
2020-07-26 14:57:23 +00:00
Array breakpoint_list = code_editor - > get_text_editor ( ) - > get_breakpointed_lines ( ) ;
2019-07-01 19:00:05 +00:00
if ( breakpoint_list . size ( ) = = 0 ) {
return ;
}
breakpoints_menu - > add_separator ( ) ;
for ( int i = 0 ; i < breakpoint_list . size ( ) ; i + + ) {
2019-12-03 16:19:57 +00:00
// Strip edges to remove spaces or tabs.
// Also replace any tabs by spaces, since we can't print tabs in the menu.
2020-07-24 14:50:35 +00:00
String line = code_editor - > get_text_editor ( ) - > get_line ( breakpoint_list [ i ] ) . replace ( " \t " , " " ) . strip_edges ( ) ;
2019-12-03 16:19:57 +00:00
2019-07-01 19:00:05 +00:00
// Limit the size of the line if too big.
if ( line . length ( ) > 50 ) {
line = line . substr ( 0 , 50 ) ;
}
2019-12-03 16:19:57 +00:00
breakpoints_menu - > add_item ( String : : num ( ( int ) breakpoint_list [ i ] + 1 ) + " - ` " + line + " ` " ) ;
2019-07-01 19:00:05 +00:00
breakpoints_menu - > set_item_metadata ( breakpoints_menu - > get_item_count ( ) - 1 , breakpoint_list [ i ] ) ;
}
}
void ScriptTextEditor : : _breakpoint_item_pressed ( int p_idx ) {
if ( p_idx < 4 ) { // Any item before the separator.
_edit_option ( breakpoints_menu - > get_item_id ( p_idx ) ) ;
} else {
code_editor - > goto_line ( breakpoints_menu - > get_item_metadata ( p_idx ) ) ;
2021-07-08 17:35:56 +00:00
code_editor - > get_text_editor ( ) - > call_deferred ( SNAME ( " center_viewport_to_caret " ) ) ; //Need to be deferred, because goto uses call_deferred().
2019-07-01 19:00:05 +00:00
}
}
2016-08-02 22:11:05 +00:00
void ScriptTextEditor : : _breakpoint_toggled ( int p_row ) {
2020-07-26 14:57:23 +00:00
EditorDebuggerNode : : get_singleton ( ) - > set_breakpoint ( script - > get_path ( ) , p_row + 1 , code_editor - > get_text_editor ( ) - > is_line_breakpointed ( p_row ) ) ;
2016-08-02 22:11:05 +00:00
}
2017-03-05 15:44:50 +00:00
void ScriptTextEditor : : _lookup_symbol ( const String & p_symbol , int p_row , int p_column ) {
2016-09-12 13:52:29 +00:00
Node * base = get_tree ( ) - > get_edited_scene_root ( ) ;
if ( base ) {
2017-03-05 15:44:50 +00:00
base = _find_node_for_script ( base , base , script ) ;
2016-09-12 13:52:29 +00:00
}
ScriptLanguage : : LookupResult result ;
2019-03-11 15:25:54 +00:00
if ( ScriptServer : : is_global_class ( p_symbol ) ) {
EditorNode : : get_singleton ( ) - > load_resource ( ScriptServer : : get_global_class_path ( p_symbol ) ) ;
} else if ( p_symbol . is_resource_file ( ) ) {
2017-08-02 17:20:27 +00:00
List < String > scene_extensions ;
ResourceLoader : : get_recognized_extensions_for_type ( " PackedScene " , & scene_extensions ) ;
if ( scene_extensions . find ( p_symbol . get_extension ( ) ) ) {
EditorNode : : get_singleton ( ) - > load_scene ( p_symbol ) ;
} else {
EditorNode : : get_singleton ( ) - > load_resource ( p_symbol ) ;
}
2021-07-01 16:10:54 +00:00
} else if ( script - > get_language ( ) - > lookup_code ( code_editor - > get_text_editor ( ) - > get_text_for_symbol_lookup ( ) , p_symbol , script - > get_path ( ) , base , result ) = = OK ) {
2016-09-12 13:52:29 +00:00
_goto_line ( p_row ) ;
2017-03-05 15:44:50 +00:00
switch ( result . type ) {
2016-09-12 13:52:29 +00:00
case ScriptLanguage : : LookupResult : : RESULT_SCRIPT_LOCATION : {
if ( result . script . is_valid ( ) ) {
2021-07-17 21:22:52 +00:00
emit_signal ( SNAME ( " request_open_script_at_line " ) , result . script , result . location - 1 ) ;
2016-09-12 13:52:29 +00:00
} else {
2021-07-17 21:22:52 +00:00
emit_signal ( SNAME ( " request_save_history " ) ) ;
2021-03-24 16:29:14 +00:00
goto_line_centered ( result . location - 1 ) ;
2016-09-12 13:52:29 +00:00
}
} break ;
case ScriptLanguage : : LookupResult : : RESULT_CLASS : {
2021-07-17 21:22:52 +00:00
emit_signal ( SNAME ( " go_to_help " ) , " class_name: " + result . class_name ) ;
2016-09-12 13:52:29 +00:00
} break ;
case ScriptLanguage : : LookupResult : : RESULT_CLASS_CONSTANT : {
StringName cname = result . class_name ;
bool success ;
2017-03-05 15:44:50 +00:00
while ( true ) {
ClassDB : : get_integer_constant ( cname , result . class_member , & success ) ;
2016-09-12 13:52:29 +00:00
if ( success ) {
2017-03-05 15:44:50 +00:00
result . class_name = cname ;
cname = ClassDB : : get_parent_class ( cname ) ;
2016-09-12 13:52:29 +00:00
} else {
break ;
}
}
2021-07-17 21:22:52 +00:00
emit_signal ( SNAME ( " go_to_help " ) , " class_constant: " + result . class_name + " : " + result . class_member ) ;
2016-09-12 13:52:29 +00:00
} break ;
case ScriptLanguage : : LookupResult : : RESULT_CLASS_PROPERTY : {
2021-07-17 21:22:52 +00:00
emit_signal ( SNAME ( " go_to_help " ) , " class_property: " + result . class_name + " : " + result . class_member ) ;
2016-09-12 13:52:29 +00:00
} break ;
case ScriptLanguage : : LookupResult : : RESULT_CLASS_METHOD : {
StringName cname = result . class_name ;
2017-03-05 15:44:50 +00:00
while ( true ) {
if ( ClassDB : : has_method ( cname , result . class_member ) ) {
result . class_name = cname ;
cname = ClassDB : : get_parent_class ( cname ) ;
2016-09-12 13:52:29 +00:00
} else {
break ;
}
}
2021-07-17 21:22:52 +00:00
emit_signal ( SNAME ( " go_to_help " ) , " class_method: " + result . class_name + " : " + result . class_member ) ;
2016-09-12 13:52:29 +00:00
} break ;
2018-03-30 14:20:24 +00:00
case ScriptLanguage : : LookupResult : : RESULT_CLASS_ENUM : {
StringName cname = result . class_name ;
StringName success ;
while ( true ) {
success = ClassDB : : get_integer_constant_enum ( cname , result . class_member , true ) ;
if ( success ! = StringName ( ) ) {
result . class_name = cname ;
cname = ClassDB : : get_parent_class ( cname ) ;
} else {
break ;
}
}
2021-07-17 21:22:52 +00:00
emit_signal ( SNAME ( " go_to_help " ) , " class_enum: " + result . class_name + " : " + result . class_member ) ;
2018-03-30 14:20:24 +00:00
} break ;
case ScriptLanguage : : LookupResult : : RESULT_CLASS_TBD_GLOBALSCOPE : {
2021-07-17 21:22:52 +00:00
emit_signal ( SNAME ( " go_to_help " ) , " class_global: " + result . class_name + " : " + result . class_member ) ;
2018-03-30 14:20:24 +00:00
} break ;
2016-09-12 13:52:29 +00:00
}
2020-06-17 23:45:08 +00:00
} else if ( ProjectSettings : : get_singleton ( ) - > has_autoload ( p_symbol ) ) {
// Check for Autoload scenes.
const ProjectSettings : : AutoloadInfo & info = ProjectSettings : : get_singleton ( ) - > get_autoload ( p_symbol ) ;
if ( info . is_singleton ) {
EditorNode : : get_singleton ( ) - > load_scene ( info . path ) ;
2020-03-28 08:12:19 +00:00
}
2021-08-29 23:43:47 +00:00
} else if ( p_symbol . is_relative_path ( ) ) {
2020-03-28 08:12:19 +00:00
// Every symbol other than absolute path is relative path so keep this condition at last.
String path = _get_absolute_path ( p_symbol ) ;
if ( FileAccess : : exists ( path ) ) {
List < String > scene_extensions ;
ResourceLoader : : get_recognized_extensions_for_type ( " PackedScene " , & scene_extensions ) ;
if ( scene_extensions . find ( path . get_extension ( ) ) ) {
EditorNode : : get_singleton ( ) - > load_scene ( path ) ;
} else {
EditorNode : : get_singleton ( ) - > load_resource ( path ) ;
}
}
2016-09-12 13:52:29 +00:00
}
}
2016-08-02 22:11:05 +00:00
2020-03-01 08:13:41 +00:00
void ScriptTextEditor : : _validate_symbol ( const String & p_symbol ) {
2020-07-24 14:50:35 +00:00
CodeEdit * text_edit = code_editor - > get_text_editor ( ) ;
2020-03-01 08:13:41 +00:00
Node * base = get_tree ( ) - > get_edited_scene_root ( ) ;
if ( base ) {
base = _find_node_for_script ( base , base , script ) ;
}
ScriptLanguage : : LookupResult result ;
2021-07-01 16:10:54 +00:00
if ( ScriptServer : : is_global_class ( p_symbol ) | | p_symbol . is_resource_file ( ) | | script - > get_language ( ) - > lookup_code ( code_editor - > get_text_editor ( ) - > get_text_for_symbol_lookup ( ) , p_symbol , script - > get_path ( ) , base , result ) = = OK | | ( ProjectSettings : : get_singleton ( ) - > has_autoload ( p_symbol ) & & ProjectSettings : : get_singleton ( ) - > get_autoload ( p_symbol ) . is_singleton ) ) {
text_edit - > set_symbol_lookup_word_as_valid ( true ) ;
2021-08-29 23:43:47 +00:00
} else if ( p_symbol . is_relative_path ( ) ) {
2020-03-28 08:12:19 +00:00
String path = _get_absolute_path ( p_symbol ) ;
if ( FileAccess : : exists ( path ) ) {
2021-07-01 16:10:54 +00:00
text_edit - > set_symbol_lookup_word_as_valid ( true ) ;
2020-03-28 08:12:19 +00:00
} else {
2021-07-01 16:10:54 +00:00
text_edit - > set_symbol_lookup_word_as_valid ( false ) ;
2020-03-28 08:12:19 +00:00
}
2020-03-01 08:13:41 +00:00
} else {
2021-07-01 16:10:54 +00:00
text_edit - > set_symbol_lookup_word_as_valid ( false ) ;
2020-03-01 08:13:41 +00:00
}
}
2020-03-28 08:12:19 +00:00
String ScriptTextEditor : : _get_absolute_path ( const String & rel_path ) {
String base_path = script - > get_path ( ) . get_base_dir ( ) ;
String path = base_path . plus_file ( rel_path ) ;
return path . replace ( " /// " , " // " ) . simplify_path ( ) ;
}
2019-12-18 19:32:25 +00:00
void ScriptTextEditor : : update_toggle_scripts_button ( ) {
2020-04-01 23:20:12 +00:00
if ( code_editor ! = nullptr ) {
2019-12-18 19:32:25 +00:00
code_editor - > update_toggle_scripts_button ( ) ;
}
}
2019-04-20 11:51:25 +00:00
void ScriptTextEditor : : _update_connected_methods ( ) {
2020-07-24 14:50:35 +00:00
CodeEdit * text_edit = code_editor - > get_text_editor ( ) ;
2021-07-10 10:41:38 +00:00
text_edit - > set_gutter_width ( connection_gutter , text_edit - > get_line_height ( ) ) ;
2020-07-29 21:26:49 +00:00
for ( int i = 0 ; i < text_edit - > get_line_count ( ) ; i + + ) {
if ( text_edit - > get_line_gutter_metadata ( i , connection_gutter ) = = " " ) {
continue ;
}
text_edit - > set_line_gutter_metadata ( i , connection_gutter , " " ) ;
text_edit - > set_line_gutter_icon ( i , connection_gutter , nullptr ) ;
text_edit - > set_line_gutter_clickable ( i , connection_gutter , false ) ;
}
2019-04-20 11:51:25 +00:00
missing_connections . clear ( ) ;
2019-11-02 13:38:25 +00:00
if ( ! script_is_valid ) {
2019-10-27 11:07:19 +00:00
return ;
}
2019-04-20 11:51:25 +00:00
Node * base = get_tree ( ) - > get_edited_scene_root ( ) ;
if ( ! base ) {
return ;
}
Vector < Node * > nodes = _find_all_node_for_script ( base , base , script ) ;
2019-10-27 11:07:19 +00:00
Set < StringName > methods_found ;
2019-04-20 11:51:25 +00:00
for ( int i = 0 ; i < nodes . size ( ) ; i + + ) {
List < Connection > connections ;
nodes [ i ] - > get_signals_connected_to_this ( & connections ) ;
2021-07-24 13:46:25 +00:00
for ( const Connection & connection : connections ) {
2019-04-20 11:51:25 +00:00
if ( ! ( connection . flags & CONNECT_PERSIST ) ) {
continue ;
}
2019-06-10 22:35:22 +00:00
// As deleted nodes are still accessible via the undo/redo system, check if they're still on the tree.
2020-02-19 19:27:19 +00:00
Node * source = Object : : cast_to < Node > ( connection . signal . get_object ( ) ) ;
2019-06-10 22:35:22 +00:00
if ( source & & ! source - > is_inside_tree ( ) ) {
continue ;
}
2020-02-19 19:27:19 +00:00
if ( methods_found . has ( connection . callable . get_method ( ) ) ) {
2019-10-27 11:07:19 +00:00
continue ;
}
2020-02-19 19:27:19 +00:00
if ( ! ClassDB : : has_method ( script - > get_instance_base_type ( ) , connection . callable . get_method ( ) ) ) {
2019-10-27 11:07:19 +00:00
int line = - 1 ;
2019-11-02 13:38:25 +00:00
for ( int j = 0 ; j < functions . size ( ) ; j + + ) {
String name = functions [ j ] . get_slice ( " : " , 0 ) ;
2020-02-19 19:27:19 +00:00
if ( name = = connection . callable . get_method ( ) ) {
2020-07-29 21:26:49 +00:00
line = functions [ j ] . get_slice ( " : " , 1 ) . to_int ( ) - 1 ;
text_edit - > set_line_gutter_metadata ( line , connection_gutter , connection . callable . get_method ( ) ) ;
2021-07-17 21:22:52 +00:00
text_edit - > set_line_gutter_icon ( line , connection_gutter , get_parent_control ( ) - > get_theme_icon ( SNAME ( " Slot " ) , SNAME ( " EditorIcons " ) ) ) ;
2020-07-29 21:26:49 +00:00
text_edit - > set_line_gutter_clickable ( line , connection_gutter , true ) ;
2020-02-19 19:27:19 +00:00
methods_found . insert ( connection . callable . get_method ( ) ) ;
2019-11-02 13:38:25 +00:00
break ;
}
}
if ( line > = 0 ) {
2019-10-27 11:07:19 +00:00
continue ;
}
2019-06-13 15:15:13 +00:00
2019-10-27 11:07:19 +00:00
// There is a chance that the method is inherited from another script.
bool found_inherited_function = false ;
Ref < Script > inherited_script = script - > get_base_script ( ) ;
while ( ! inherited_script . is_null ( ) ) {
2020-02-19 19:27:19 +00:00
if ( inherited_script - > has_method ( connection . callable . get_method ( ) ) ) {
2019-10-27 11:07:19 +00:00
found_inherited_function = true ;
break ;
2019-06-11 22:48:35 +00:00
}
2019-10-27 11:07:19 +00:00
inherited_script = inherited_script - > get_base_script ( ) ;
}
if ( ! found_inherited_function ) {
missing_connections . push_back ( connection ) ;
2019-06-11 22:48:35 +00:00
}
2019-04-20 11:51:25 +00:00
}
}
}
}
2020-07-29 21:26:49 +00:00
void ScriptTextEditor : : _update_gutter_indexes ( ) {
for ( int i = 0 ; i < code_editor - > get_text_editor ( ) - > get_gutter_count ( ) ; i + + ) {
if ( code_editor - > get_text_editor ( ) - > get_gutter_name ( i ) = = " connection_gutter " ) {
connection_gutter = i ;
2020-07-30 10:41:05 +00:00
continue ;
}
if ( code_editor - > get_text_editor ( ) - > get_gutter_name ( i ) = = " line_numbers " ) {
line_number_gutter = i ;
continue ;
2020-07-29 21:26:49 +00:00
}
}
}
void ScriptTextEditor : : _gutter_clicked ( int p_line , int p_gutter ) {
if ( p_gutter ! = connection_gutter ) {
return ;
}
String method = code_editor - > get_text_editor ( ) - > get_line_gutter_metadata ( p_line , p_gutter ) ;
if ( method = = " " ) {
return ;
}
2019-04-20 11:51:25 +00:00
Node * base = get_tree ( ) - > get_edited_scene_root ( ) ;
if ( ! base ) {
return ;
}
Vector < Node * > nodes = _find_all_node_for_script ( base , base , script ) ;
2020-07-29 21:26:49 +00:00
connection_info_dialog - > popup_connections ( method , nodes ) ;
2019-04-20 11:51:25 +00:00
}
2016-08-02 22:11:05 +00:00
void ScriptTextEditor : : _edit_option ( int p_op ) {
2020-07-24 14:50:35 +00:00
CodeEdit * tx = code_editor - > get_text_editor ( ) ;
2017-11-16 04:00:27 +00:00
2017-03-05 15:44:50 +00:00
switch ( p_op ) {
2016-08-02 22:11:05 +00:00
case EDIT_UNDO : {
2017-11-16 04:00:27 +00:00
tx - > undo ( ) ;
2021-07-17 21:22:52 +00:00
tx - > call_deferred ( SNAME ( " grab_focus " ) ) ;
2016-08-02 22:11:05 +00:00
} break ;
case EDIT_REDO : {
2017-11-16 04:00:27 +00:00
tx - > redo ( ) ;
2021-07-17 21:22:52 +00:00
tx - > call_deferred ( SNAME ( " grab_focus " ) ) ;
2016-08-02 22:11:05 +00:00
} break ;
case EDIT_CUT : {
2017-11-16 04:00:27 +00:00
tx - > cut ( ) ;
2021-07-17 21:22:52 +00:00
tx - > call_deferred ( SNAME ( " grab_focus " ) ) ;
2016-08-02 22:11:05 +00:00
} break ;
case EDIT_COPY : {
2017-11-16 04:00:27 +00:00
tx - > copy ( ) ;
2021-07-17 21:22:52 +00:00
tx - > call_deferred ( SNAME ( " grab_focus " ) ) ;
2016-08-02 22:11:05 +00:00
} break ;
case EDIT_PASTE : {
2017-11-16 04:00:27 +00:00
tx - > paste ( ) ;
2021-07-17 21:22:52 +00:00
tx - > call_deferred ( SNAME ( " grab_focus " ) ) ;
2016-08-02 22:11:05 +00:00
} break ;
case EDIT_SELECT_ALL : {
2017-11-16 04:00:27 +00:00
tx - > select_all ( ) ;
2021-07-17 21:22:52 +00:00
tx - > call_deferred ( SNAME ( " grab_focus " ) ) ;
2016-08-02 22:11:05 +00:00
} break ;
case EDIT_MOVE_LINE_UP : {
2018-05-25 22:49:35 +00:00
code_editor - > move_lines_up ( ) ;
2016-08-02 22:11:05 +00:00
} break ;
case EDIT_MOVE_LINE_DOWN : {
2018-05-25 22:49:35 +00:00
code_editor - > move_lines_down ( ) ;
2016-08-02 22:11:05 +00:00
} break ;
case EDIT_INDENT_LEFT : {
2018-05-28 15:52:28 +00:00
Ref < Script > scr = script ;
2020-05-14 14:41:43 +00:00
if ( scr . is_null ( ) ) {
2016-08-02 22:11:05 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2016-08-02 22:11:05 +00:00
2021-06-15 14:05:01 +00:00
tx - > unindent_lines ( ) ;
2016-08-02 22:11:05 +00:00
} break ;
case EDIT_INDENT_RIGHT : {
2018-05-28 15:52:28 +00:00
Ref < Script > scr = script ;
2020-05-14 14:41:43 +00:00
if ( scr . is_null ( ) ) {
2016-08-02 22:11:05 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2016-08-02 22:11:05 +00:00
2021-06-15 14:05:01 +00:00
tx - > indent_lines ( ) ;
2017-08-20 12:31:30 +00:00
} break ;
case EDIT_DELETE_LINE : {
2018-05-25 22:49:35 +00:00
code_editor - > delete_lines ( ) ;
2016-08-02 22:11:05 +00:00
} break ;
2021-06-29 10:09:07 +00:00
case EDIT_DUPLICATE_SELECTION : {
code_editor - > duplicate_selection ( ) ;
2016-08-02 22:11:05 +00:00
} break ;
2017-12-08 18:17:10 +00:00
case EDIT_TOGGLE_FOLD_LINE : {
2021-07-08 17:35:56 +00:00
tx - > toggle_foldable_line ( tx - > get_caret_line ( ) ) ;
2017-11-12 23:12:17 +00:00
tx - > update ( ) ;
} break ;
2017-11-16 04:00:27 +00:00
case EDIT_FOLD_ALL_LINES : {
tx - > fold_all_lines ( ) ;
tx - > update ( ) ;
} break ;
2017-11-12 23:12:17 +00:00
case EDIT_UNFOLD_ALL_LINES : {
2021-07-09 12:07:10 +00:00
tx - > unfold_all_lines ( ) ;
2017-11-12 23:12:17 +00:00
tx - > update ( ) ;
} break ;
2016-08-02 22:11:05 +00:00
case EDIT_TOGGLE_COMMENT : {
2019-02-04 19:17:44 +00:00
_edit_option_toggle_inline_comment ( ) ;
2016-08-02 22:11:05 +00:00
} break ;
case EDIT_COMPLETE : {
2020-09-13 20:14:20 +00:00
tx - > request_code_completion ( true ) ;
2016-08-02 22:11:05 +00:00
} break ;
case EDIT_AUTO_INDENT : {
2017-11-16 04:00:27 +00:00
String text = tx - > get_text ( ) ;
2018-05-28 15:52:28 +00:00
Ref < Script > scr = script ;
2020-05-14 14:41:43 +00:00
if ( scr . is_null ( ) ) {
2016-08-02 22:11:05 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2017-08-22 17:52:17 +00:00
2017-11-16 04:00:27 +00:00
tx - > begin_complex_operation ( ) ;
2017-03-05 15:44:50 +00:00
int begin , end ;
2021-07-09 11:42:55 +00:00
if ( tx - > has_selection ( ) ) {
2017-11-16 04:00:27 +00:00
begin = tx - > get_selection_from_line ( ) ;
end = tx - > get_selection_to_line ( ) ;
2017-08-22 17:52:17 +00:00
// ignore if the cursor is not past the first column
2017-11-16 04:00:27 +00:00
if ( tx - > get_selection_to_column ( ) = = 0 ) {
2017-08-22 17:52:17 +00:00
end - - ;
}
2016-08-02 22:11:05 +00:00
} else {
2017-03-05 15:44:50 +00:00
begin = 0 ;
2017-11-16 04:00:27 +00:00
end = tx - > get_line_count ( ) - 1 ;
2016-08-02 22:11:05 +00:00
}
2017-03-05 15:44:50 +00:00
scr - > get_language ( ) - > auto_indent_code ( text , begin , end ) ;
2017-08-22 17:52:17 +00:00
Vector < String > lines = text . split ( " \n " ) ;
for ( int i = begin ; i < = end ; + + i ) {
2017-11-16 04:00:27 +00:00
tx - > set_line ( i , lines [ i ] ) ;
2017-08-22 17:52:17 +00:00
}
2017-11-16 04:00:27 +00:00
tx - > end_complex_operation ( ) ;
2016-08-02 22:11:05 +00:00
} break ;
case EDIT_TRIM_TRAILING_WHITESAPCE : {
trim_trailing_whitespace ( ) ;
} break ;
2017-04-16 15:47:59 +00:00
case EDIT_CONVERT_INDENT_TO_SPACES : {
convert_indent_to_spaces ( ) ;
} break ;
case EDIT_CONVERT_INDENT_TO_TABS : {
convert_indent_to_tabs ( ) ;
} break ;
2016-09-29 07:12:45 +00:00
case EDIT_PICK_COLOR : {
color_panel - > popup ( ) ;
} break ;
2017-04-24 18:59:55 +00:00
case EDIT_TO_UPPERCASE : {
2018-05-25 22:49:35 +00:00
_convert_case ( CodeTextEditor : : UPPER ) ;
2017-04-24 18:59:55 +00:00
} break ;
case EDIT_TO_LOWERCASE : {
2018-05-25 22:49:35 +00:00
_convert_case ( CodeTextEditor : : LOWER ) ;
2017-04-24 18:59:55 +00:00
} break ;
case EDIT_CAPITALIZE : {
2018-05-25 22:49:35 +00:00
_convert_case ( CodeTextEditor : : CAPITALIZE ) ;
2017-04-24 18:59:55 +00:00
} break ;
2019-08-07 14:31:33 +00:00
case EDIT_EVALUATE : {
Expression expression ;
2021-07-09 11:42:55 +00:00
Vector < String > lines = code_editor - > get_text_editor ( ) - > get_selected_text ( ) . split ( " \n " ) ;
2020-02-17 21:06:54 +00:00
PackedStringArray results ;
2019-08-07 14:31:33 +00:00
for ( int i = 0 ; i < lines . size ( ) ; i + + ) {
String line = lines [ i ] ;
String whitespace = line . substr ( 0 , line . size ( ) - line . strip_edges ( true , false ) . size ( ) ) ; //extract the whitespace at the beginning
if ( expression . parse ( line ) = = OK ) {
Variant result = expression . execute ( Array ( ) , Variant ( ) , false ) ;
if ( expression . get_error_text ( ) = = " " ) {
2020-02-17 21:06:54 +00:00
results . push_back ( whitespace + result . get_construct_string ( ) ) ;
2019-08-07 14:31:33 +00:00
} else {
2020-02-17 21:06:54 +00:00
results . push_back ( line ) ;
2019-08-07 14:31:33 +00:00
}
} else {
2020-02-17 21:06:54 +00:00
results . push_back ( line ) ;
2019-08-07 14:31:33 +00:00
}
}
2020-07-24 14:50:35 +00:00
code_editor - > get_text_editor ( ) - > begin_complex_operation ( ) ; //prevents creating a two-step undo
2021-07-08 17:35:56 +00:00
code_editor - > get_text_editor ( ) - > insert_text_at_caret ( String ( " \n " ) . join ( results ) ) ;
2020-07-24 14:50:35 +00:00
code_editor - > get_text_editor ( ) - > end_complex_operation ( ) ;
2019-08-07 14:31:33 +00:00
} break ;
2016-08-02 22:11:05 +00:00
case SEARCH_FIND : {
code_editor - > get_find_replace_bar ( ) - > popup_search ( ) ;
} break ;
case SEARCH_FIND_NEXT : {
code_editor - > get_find_replace_bar ( ) - > search_next ( ) ;
} break ;
case SEARCH_FIND_PREV : {
code_editor - > get_find_replace_bar ( ) - > search_prev ( ) ;
} break ;
case SEARCH_REPLACE : {
code_editor - > get_find_replace_bar ( ) - > popup_replace ( ) ;
} break ;
2018-02-12 01:36:15 +00:00
case SEARCH_IN_FILES : {
2021-07-09 11:42:55 +00:00
String selected_text = code_editor - > get_text_editor ( ) - > get_selected_text ( ) ;
2018-02-12 01:36:15 +00:00
// Yep, because it doesn't make sense to instance this dialog for every single script open...
2019-05-21 08:07:48 +00:00
// So this will be delegated to the ScriptEditor.
2021-07-17 21:22:52 +00:00
emit_signal ( SNAME ( " search_in_files_requested " ) , selected_text ) ;
2018-02-12 01:36:15 +00:00
} break ;
2020-02-09 09:10:58 +00:00
case REPLACE_IN_FILES : {
2021-07-09 11:42:55 +00:00
String selected_text = code_editor - > get_text_editor ( ) - > get_selected_text ( ) ;
2020-02-09 09:10:58 +00:00
2021-07-17 21:22:52 +00:00
emit_signal ( SNAME ( " replace_in_files_requested " ) , selected_text ) ;
2020-02-09 09:10:58 +00:00
} break ;
2016-08-02 22:11:05 +00:00
case SEARCH_LOCATE_FUNCTION : {
2018-10-02 10:07:44 +00:00
quick_open - > popup_dialog ( get_functions ( ) ) ;
2018-09-25 20:44:50 +00:00
quick_open - > set_title ( TTR ( " Go to Function " ) ) ;
2016-08-02 22:11:05 +00:00
} break ;
case SEARCH_GOTO_LINE : {
2017-11-16 04:00:27 +00:00
goto_line_dialog - > popup_find_line ( tx ) ;
2016-08-02 22:11:05 +00:00
} break ;
2019-04-19 23:51:25 +00:00
case BOOKMARK_TOGGLE : {
code_editor - > toggle_bookmark ( ) ;
} break ;
case BOOKMARK_GOTO_NEXT : {
code_editor - > goto_next_bookmark ( ) ;
} break ;
case BOOKMARK_GOTO_PREV : {
code_editor - > goto_prev_bookmark ( ) ;
} break ;
case BOOKMARK_REMOVE_ALL : {
code_editor - > remove_all_bookmarks ( ) ;
} break ;
2016-08-02 22:11:05 +00:00
case DEBUG_TOGGLE_BREAKPOINT : {
2021-07-08 17:35:56 +00:00
int line = tx - > get_caret_line ( ) ;
2020-07-26 14:57:23 +00:00
bool dobreak = ! tx - > is_line_breakpointed ( line ) ;
2017-11-16 04:00:27 +00:00
tx - > set_line_as_breakpoint ( line , dobreak ) ;
2020-02-07 01:52:05 +00:00
EditorDebuggerNode : : get_singleton ( ) - > set_breakpoint ( script - > get_path ( ) , line + 1 , dobreak ) ;
2016-08-02 22:11:05 +00:00
} break ;
case DEBUG_REMOVE_ALL_BREAKPOINTS : {
2020-07-26 14:57:23 +00:00
Array bpoints = tx - > get_breakpointed_lines ( ) ;
2016-08-02 22:11:05 +00:00
2020-07-26 14:57:23 +00:00
for ( int i = 0 ; i < bpoints . size ( ) ; i + + ) {
int line = bpoints [ i ] ;
bool dobreak = ! tx - > is_line_breakpointed ( line ) ;
2017-11-16 04:00:27 +00:00
tx - > set_line_as_breakpoint ( line , dobreak ) ;
2020-02-07 01:52:05 +00:00
EditorDebuggerNode : : get_singleton ( ) - > set_breakpoint ( script - > get_path ( ) , line + 1 , dobreak ) ;
2016-08-02 22:11:05 +00:00
}
2019-04-05 12:06:16 +00:00
} break ;
2016-08-02 22:11:05 +00:00
case DEBUG_GOTO_NEXT_BREAKPOINT : {
2020-07-26 14:57:23 +00:00
Array bpoints = tx - > get_breakpointed_lines ( ) ;
2016-08-02 22:11:05 +00:00
if ( bpoints . size ( ) < = 0 ) {
return ;
}
2021-07-08 17:35:56 +00:00
int line = tx - > get_caret_line ( ) ;
2017-11-16 04:00:27 +00:00
2016-08-02 22:11:05 +00:00
// wrap around
2020-07-26 14:57:23 +00:00
if ( line > = ( int ) bpoints [ bpoints . size ( ) - 1 ] ) {
2017-11-16 04:00:27 +00:00
tx - > unfold_line ( bpoints [ 0 ] ) ;
2021-07-08 17:35:56 +00:00
tx - > set_caret_line ( bpoints [ 0 ] ) ;
tx - > center_viewport_to_caret ( ) ;
2016-08-02 22:11:05 +00:00
} else {
2020-07-26 14:57:23 +00:00
for ( int i = 0 ; i < bpoints . size ( ) ; i + + ) {
int bline = bpoints [ i ] ;
2016-08-02 22:11:05 +00:00
if ( bline > line ) {
2017-11-16 04:00:27 +00:00
tx - > unfold_line ( bline ) ;
2021-07-08 17:35:56 +00:00
tx - > set_caret_line ( bline ) ;
tx - > center_viewport_to_caret ( ) ;
2016-08-02 22:11:05 +00:00
return ;
}
}
}
} break ;
case DEBUG_GOTO_PREV_BREAKPOINT : {
2020-07-26 14:57:23 +00:00
Array bpoints = tx - > get_breakpointed_lines ( ) ;
2016-08-02 22:11:05 +00:00
if ( bpoints . size ( ) < = 0 ) {
return ;
}
2021-07-08 17:35:56 +00:00
int line = tx - > get_caret_line ( ) ;
2016-08-02 22:11:05 +00:00
// wrap around
2020-07-26 14:57:23 +00:00
if ( line < = ( int ) bpoints [ 0 ] ) {
2017-11-16 04:00:27 +00:00
tx - > unfold_line ( bpoints [ bpoints . size ( ) - 1 ] ) ;
2021-07-08 17:35:56 +00:00
tx - > set_caret_line ( bpoints [ bpoints . size ( ) - 1 ] ) ;
tx - > center_viewport_to_caret ( ) ;
2016-08-02 22:11:05 +00:00
} else {
2021-09-14 11:05:29 +00:00
for ( int i = bpoints . size ( ) - 1 ; i > = 0 ; i - - ) {
2020-07-26 14:57:23 +00:00
int bline = bpoints [ i ] ;
2016-08-02 22:11:05 +00:00
if ( bline < line ) {
2017-11-16 04:00:27 +00:00
tx - > unfold_line ( bline ) ;
2021-07-08 17:35:56 +00:00
tx - > set_caret_line ( bline ) ;
tx - > center_viewport_to_caret ( ) ;
2016-08-02 22:11:05 +00:00
return ;
}
}
}
} break ;
case HELP_CONTEXTUAL : {
2021-07-09 11:42:55 +00:00
String text = tx - > get_selected_text ( ) ;
2020-05-14 14:41:43 +00:00
if ( text = = " " ) {
2021-07-08 17:35:56 +00:00
text = tx - > get_word_under_caret ( ) ;
2020-05-14 14:41:43 +00:00
}
2016-08-02 22:11:05 +00:00
if ( text ! = " " ) {
2021-07-17 21:22:52 +00:00
emit_signal ( SNAME ( " request_help " ) , text ) ;
2016-08-02 22:11:05 +00:00
}
} break ;
2018-01-02 07:10:49 +00:00
case LOOKUP_SYMBOL : {
2021-07-08 17:35:56 +00:00
String text = tx - > get_word_under_caret ( ) ;
2020-05-14 14:41:43 +00:00
if ( text = = " " ) {
2021-07-09 11:42:55 +00:00
text = tx - > get_selected_text ( ) ;
2020-05-14 14:41:43 +00:00
}
2018-01-02 07:10:49 +00:00
if ( text ! = " " ) {
2021-07-08 17:35:56 +00:00
_lookup_symbol ( text , tx - > get_caret_line ( ) , tx - > get_caret_column ( ) ) ;
2018-01-02 07:10:49 +00:00
}
} break ;
2016-08-02 22:11:05 +00:00
}
}
2019-02-04 19:17:44 +00:00
void ScriptTextEditor : : _edit_option_toggle_inline_comment ( ) {
2020-05-14 14:41:43 +00:00
if ( script . is_null ( ) ) {
2019-02-04 19:17:44 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2019-02-04 19:17:44 +00:00
String delimiter = " # " ;
List < String > comment_delimiters ;
script - > get_language ( ) - > get_comment_delimiters ( & comment_delimiters ) ;
2021-07-24 13:46:25 +00:00
for ( const String & script_delimiter : comment_delimiters ) {
2019-02-04 19:17:44 +00:00
if ( script_delimiter . find ( " " ) = = - 1 ) {
delimiter = script_delimiter ;
break ;
}
}
code_editor - > toggle_inline_comment ( delimiter ) ;
}
2020-05-03 16:08:15 +00:00
void ScriptTextEditor : : add_syntax_highlighter ( Ref < EditorSyntaxHighlighter > p_highlighter ) {
2019-11-20 09:09:59 +00:00
ERR_FAIL_COND ( p_highlighter . is_null ( ) ) ;
2020-03-07 11:17:18 +00:00
highlighters [ p_highlighter - > _get_name ( ) ] = p_highlighter ;
highlighter_menu - > add_radio_check_item ( p_highlighter - > _get_name ( ) ) ;
2018-04-02 11:41:44 +00:00
}
2020-05-03 16:08:15 +00:00
void ScriptTextEditor : : set_syntax_highlighter ( Ref < EditorSyntaxHighlighter > p_highlighter ) {
2019-11-20 09:09:59 +00:00
ERR_FAIL_COND ( p_highlighter . is_null ( ) ) ;
Map < String , Ref < EditorSyntaxHighlighter > > : : Element * el = highlighters . front ( ) ;
while ( el ! = nullptr ) {
int highlighter_index = highlighter_menu - > get_item_idx_from_text ( el - > key ( ) ) ;
highlighter_menu - > set_item_checked ( highlighter_index , el - > value ( ) = = p_highlighter ) ;
el = el - > next ( ) ;
}
2020-07-24 14:50:35 +00:00
CodeEdit * te = code_editor - > get_text_editor ( ) ;
2020-05-03 16:08:15 +00:00
p_highlighter - > _set_edited_resource ( script ) ;
te - > set_syntax_highlighter ( p_highlighter ) ;
2018-04-02 11:41:44 +00:00
}
void ScriptTextEditor : : _change_syntax_highlighter ( int p_idx ) {
2018-06-01 19:32:19 +00:00
set_syntax_highlighter ( highlighters [ highlighter_menu - > get_item_text ( p_idx ) ] ) ;
2018-04-02 11:41:44 +00:00
}
2020-07-29 21:26:49 +00:00
void ScriptTextEditor : : _notification ( int p_what ) {
switch ( p_what ) {
2020-09-18 07:36:10 +00:00
case NOTIFICATION_THEME_CHANGED :
case NOTIFICATION_ENTER_TREE : {
2021-07-10 10:41:38 +00:00
code_editor - > get_text_editor ( ) - > set_gutter_width ( connection_gutter , code_editor - > get_text_editor ( ) - > get_line_height ( ) ) ;
2020-07-29 21:26:49 +00:00
} break ;
default :
break ;
}
}
2016-08-02 22:11:05 +00:00
void ScriptTextEditor : : _bind_methods ( ) {
2019-04-20 11:51:25 +00:00
ClassDB : : bind_method ( " _update_connected_methods " , & ScriptTextEditor : : _update_connected_methods ) ;
2016-09-12 13:52:29 +00:00
2021-05-15 21:48:59 +00:00
ClassDB : : bind_method ( " _get_drag_data_fw " , & ScriptTextEditor : : get_drag_data_fw ) ;
ClassDB : : bind_method ( " _can_drop_data_fw " , & ScriptTextEditor : : can_drop_data_fw ) ;
ClassDB : : bind_method ( " _drop_data_fw " , & ScriptTextEditor : : drop_data_fw ) ;
2020-03-07 14:29:44 +00:00
ClassDB : : bind_method ( D_METHOD ( " add_syntax_highlighter " , " highlighter " ) , & ScriptTextEditor : : add_syntax_highlighter ) ;
2016-08-02 22:11:05 +00:00
}
Control * ScriptTextEditor : : get_edit_menu ( ) {
return edit_hb ;
}
2017-07-01 00:30:17 +00:00
void ScriptTextEditor : : clear_edit_menu ( ) {
memdelete ( edit_hb ) ;
}
2021-06-02 23:05:41 +00:00
void ScriptTextEditor : : set_find_replace_bar ( FindReplaceBar * p_bar ) {
code_editor - > set_find_replace_bar ( p_bar ) ;
}
2016-08-02 22:11:05 +00:00
void ScriptTextEditor : : reload ( bool p_soft ) {
2020-07-24 14:50:35 +00:00
CodeEdit * te = code_editor - > get_text_editor ( ) ;
2018-05-28 15:52:28 +00:00
Ref < Script > scr = script ;
2020-05-14 14:41:43 +00:00
if ( scr . is_null ( ) ) {
2016-08-02 22:11:05 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2016-08-02 22:11:05 +00:00
scr - > set_source_code ( te - > get_text ( ) ) ;
2017-03-05 15:44:50 +00:00
bool soft = p_soft | | scr - > get_instance_base_type ( ) = = " EditorPlugin " ; //always soft-reload editor plugins
2016-08-02 22:11:05 +00:00
2017-03-05 15:44:50 +00:00
scr - > get_language ( ) - > reload_tool_script ( scr , soft ) ;
2016-08-02 22:11:05 +00:00
}
2020-07-26 14:57:23 +00:00
Array ScriptTextEditor : : get_breakpoints ( ) {
return code_editor - > get_text_editor ( ) - > get_breakpointed_lines ( ) ;
2016-08-02 22:11:05 +00:00
}
2021-07-20 11:24:56 +00:00
void ScriptTextEditor : : set_breakpoint ( int p_line , bool p_enabled ) {
code_editor - > get_text_editor ( ) - > set_line_as_breakpoint ( p_line , p_enabled ) ;
}
void ScriptTextEditor : : clear_breakpoints ( ) {
code_editor - > get_text_editor ( ) - > clear_breakpointed_lines ( ) ;
}
2017-03-05 15:44:50 +00:00
void ScriptTextEditor : : set_tooltip_request_func ( String p_method , Object * p_obj ) {
2020-07-24 14:50:35 +00:00
code_editor - > get_text_editor ( ) - > set_tooltip_request_func ( p_obj , p_method , this ) ;
2016-08-02 22:11:05 +00:00
}
2016-08-06 22:00:54 +00:00
void ScriptTextEditor : : set_debugger_active ( bool p_active ) {
}
2021-05-13 19:50:25 +00:00
Control * ScriptTextEditor : : get_base_editor ( ) const {
return code_editor - > get_text_editor ( ) ;
}
2017-03-05 15:44:50 +00:00
Variant ScriptTextEditor : : get_drag_data_fw ( const Point2 & p_point , Control * p_from ) {
2016-09-11 14:28:01 +00:00
return Variant ( ) ;
}
2017-03-05 15:44:50 +00:00
bool ScriptTextEditor : : can_drop_data_fw ( const Point2 & p_point , const Variant & p_data , Control * p_from ) const {
2016-09-11 14:28:01 +00:00
Dictionary d = p_data ;
2018-02-04 02:33:32 +00:00
if ( d . has ( " type " ) & & ( String ( d [ " type " ] ) = = " resource " | |
String ( d [ " type " ] ) = = " files " | |
2019-05-15 17:36:26 +00:00
String ( d [ " type " ] ) = = " nodes " | |
2021-08-13 15:01:40 +00:00
String ( d [ " type " ] ) = = " obj_property " | |
2019-05-15 17:36:26 +00:00
String ( d [ " type " ] ) = = " files_and_dirs " ) ) {
2017-03-05 15:44:50 +00:00
return true ;
2016-09-11 14:28:01 +00:00
}
return false ;
}
2017-03-05 15:44:50 +00:00
static Node * _find_script_node ( Node * p_edited_scene , Node * p_current_node , const Ref < Script > & script ) {
2020-05-14 14:41:43 +00:00
if ( p_edited_scene ! = p_current_node & & p_current_node - > get_owner ( ) ! = p_edited_scene ) {
2020-04-01 23:20:12 +00:00
return nullptr ;
2020-05-14 14:41:43 +00:00
}
2016-09-11 14:28:01 +00:00
Ref < Script > scr = p_current_node - > get_script ( ) ;
2020-05-14 14:41:43 +00:00
if ( scr . is_valid ( ) & & scr = = script ) {
2016-09-11 14:28:01 +00:00
return p_current_node ;
2020-05-14 14:41:43 +00:00
}
2016-09-11 14:28:01 +00:00
2017-03-05 15:44:50 +00:00
for ( int i = 0 ; i < p_current_node - > get_child_count ( ) ; i + + ) {
Node * n = _find_script_node ( p_edited_scene , p_current_node - > get_child ( i ) , script ) ;
2020-05-14 14:41:43 +00:00
if ( n ) {
2016-09-11 14:28:01 +00:00
return n ;
2020-05-14 14:41:43 +00:00
}
2016-09-11 14:28:01 +00:00
}
2020-04-01 23:20:12 +00:00
return nullptr ;
2016-09-11 14:28:01 +00:00
}
2017-03-05 15:44:50 +00:00
void ScriptTextEditor : : drop_data_fw ( const Point2 & p_point , const Variant & p_data , Control * p_from ) {
2021-08-13 19:24:02 +00:00
const String quote_style = EDITOR_GET ( " text_editor/completion/use_single_quotes " ) ? " ' " : " \" " ;
2016-09-11 14:28:01 +00:00
Dictionary d = p_data ;
2020-07-24 14:50:35 +00:00
CodeEdit * te = code_editor - > get_text_editor ( ) ;
2021-07-10 10:41:38 +00:00
Point2i pos = te - > get_line_column_at_pos ( p_point ) ;
int row = pos . y ;
int col = pos . x ;
2018-02-04 02:33:32 +00:00
2017-03-05 15:44:50 +00:00
if ( d . has ( " type " ) & & String ( d [ " type " ] ) = = " resource " ) {
2016-09-11 14:28:01 +00:00
Ref < Resource > res = d [ " resource " ] ;
if ( ! res . is_valid ( ) ) {
return ;
}
if ( res - > get_path ( ) . is_resource_file ( ) ) {
2017-08-23 20:25:14 +00:00
EditorNode : : get_singleton ( ) - > show_warning ( TTR ( " Only resources from filesystem can be dropped. " ) ) ;
2016-09-11 14:28:01 +00:00
return ;
}
2021-07-08 17:35:56 +00:00
te - > set_caret_line ( row ) ;
te - > set_caret_column ( col ) ;
te - > insert_text_at_caret ( res - > get_path ( ) ) ;
2016-09-11 14:28:01 +00:00
}
2019-05-15 17:36:26 +00:00
if ( d . has ( " type " ) & & ( String ( d [ " type " ] ) = = " files " | | String ( d [ " type " ] ) = = " files_and_dirs " ) ) {
2016-09-11 14:28:01 +00:00
Array files = d [ " files " ] ;
String text_to_drop ;
2021-05-26 22:29:36 +00:00
bool preload = Input : : get_singleton ( ) - > is_key_pressed ( KEY_CTRL ) ;
2017-03-05 15:44:50 +00:00
for ( int i = 0 ; i < files . size ( ) ; i + + ) {
2020-05-14 14:41:43 +00:00
if ( i > 0 ) {
2021-05-26 22:29:36 +00:00
text_to_drop + = " , " ;
}
if ( preload ) {
2021-07-02 23:41:39 +00:00
text_to_drop + = " preload( " + String ( files [ i ] ) . c_escape ( ) . quote ( quote_style ) + " ) " ;
2021-05-26 22:29:36 +00:00
} else {
2021-07-02 23:41:39 +00:00
text_to_drop + = String ( files [ i ] ) . c_escape ( ) . quote ( quote_style ) ;
2020-05-14 14:41:43 +00:00
}
2016-09-11 14:28:01 +00:00
}
2021-07-08 17:35:56 +00:00
te - > set_caret_line ( row ) ;
te - > set_caret_column ( col ) ;
te - > insert_text_at_caret ( text_to_drop ) ;
2016-09-11 14:28:01 +00:00
}
2017-03-05 15:44:50 +00:00
if ( d . has ( " type " ) & & String ( d [ " type " ] ) = = " nodes " ) {
Node * sn = _find_script_node ( get_tree ( ) - > get_edited_scene_root ( ) , get_tree ( ) - > get_edited_scene_root ( ) , script ) ;
2016-09-11 14:28:01 +00:00
if ( ! sn ) {
2019-12-27 02:31:55 +00:00
EditorNode : : get_singleton ( ) - > show_warning ( vformat ( TTR ( " Can't drop nodes because script '%s' is not used in this scene. " ) , get_name ( ) ) ) ;
2016-09-11 14:28:01 +00:00
return ;
}
Array nodes = d [ " nodes " ] ;
String text_to_drop ;
2017-03-05 15:44:50 +00:00
for ( int i = 0 ; i < nodes . size ( ) ; i + + ) {
2020-05-14 14:41:43 +00:00
if ( i > 0 ) {
2017-03-05 15:44:50 +00:00
text_to_drop + = " , " ;
2020-05-14 14:41:43 +00:00
}
2016-09-11 14:28:01 +00:00
NodePath np = nodes [ i ] ;
Node * node = get_node ( np ) ;
if ( ! node ) {
continue ;
}
String path = sn - > get_path_to ( node ) ;
2021-08-13 19:24:02 +00:00
text_to_drop + = path . c_escape ( ) . quote ( quote_style ) ;
2016-09-11 14:28:01 +00:00
}
2021-07-08 17:35:56 +00:00
te - > set_caret_line ( row ) ;
te - > set_caret_column ( col ) ;
te - > insert_text_at_caret ( text_to_drop ) ;
2016-09-11 14:28:01 +00:00
}
2021-08-13 15:01:40 +00:00
if ( d . has ( " type " ) & & String ( d [ " type " ] ) = = " obj_property " ) {
const String text_to_drop = String ( d [ " property " ] ) . c_escape ( ) . quote ( quote_style ) ;
te - > set_caret_line ( row ) ;
te - > set_caret_column ( col ) ;
te - > insert_text_at_caret ( text_to_drop ) ;
}
2016-09-11 14:28:01 +00:00
}
2017-05-20 15:38:03 +00:00
void ScriptTextEditor : : _text_edit_gui_input ( const Ref < InputEvent > & ev ) {
Ref < InputEventMouseButton > mb = ev ;
2019-06-22 18:22:52 +00:00
Ref < InputEventKey > k = ev ;
Point2 local_pos ;
bool create_menu = false ;
2017-05-20 15:38:03 +00:00
2020-07-24 14:50:35 +00:00
CodeEdit * tx = code_editor - > get_text_editor ( ) ;
2021-01-08 03:37:37 +00:00
if ( mb . is_valid ( ) & & mb - > get_button_index ( ) = = MOUSE_BUTTON_RIGHT & & mb - > is_pressed ( ) ) {
2019-06-22 18:22:52 +00:00
local_pos = mb - > get_global_position ( ) - tx - > get_global_position ( ) ;
create_menu = true ;
2021-07-08 17:35:56 +00:00
} else if ( k . is_valid ( ) & & k - > is_action ( " ui_menu " , true ) ) {
tx - > adjust_viewport_to_caret ( ) ;
local_pos = tx - > get_caret_draw_pos ( ) ;
2019-06-22 18:22:52 +00:00
create_menu = true ;
}
2017-12-20 01:36:47 +00:00
2019-06-22 18:22:52 +00:00
if ( create_menu ) {
2021-07-10 10:41:38 +00:00
Point2i pos = tx - > get_line_column_at_pos ( local_pos ) ;
int row = pos . y ;
int col = pos . x ;
2017-12-20 01:36:47 +00:00
2021-08-15 17:14:46 +00:00
tx - > set_move_caret_on_right_click_enabled ( EditorSettings : : get_singleton ( ) - > get ( " text_editor/behavior/navigation/move_caret_on_right_click " ) ) ;
2021-07-08 17:35:56 +00:00
if ( tx - > is_move_caret_on_right_click_enabled ( ) ) {
2021-07-09 11:42:55 +00:00
if ( tx - > has_selection ( ) ) {
2019-06-22 18:22:52 +00:00
int from_line = tx - > get_selection_from_line ( ) ;
int to_line = tx - > get_selection_to_line ( ) ;
int from_column = tx - > get_selection_from_column ( ) ;
int to_column = tx - > get_selection_to_column ( ) ;
if ( row < from_line | | row > to_line | | ( row = = from_line & & col < from_column ) | | ( row = = to_line & & col > to_column ) ) {
// Right click is outside the selected text
tx - > deselect ( ) ;
2017-12-20 01:36:47 +00:00
}
}
2021-07-09 11:42:55 +00:00
if ( ! tx - > has_selection ( ) ) {
2021-07-08 17:35:56 +00:00
tx - > set_caret_line ( row , false , false ) ;
tx - > set_caret_column ( col ) ;
2019-06-22 18:22:52 +00:00
}
}
2017-12-20 01:36:47 +00:00
2019-06-22 18:22:52 +00:00
String word_at_pos = tx - > get_word_at_pos ( local_pos ) ;
2020-05-14 14:41:43 +00:00
if ( word_at_pos = = " " ) {
2021-07-08 17:35:56 +00:00
word_at_pos = tx - > get_word_under_caret ( ) ;
2020-05-14 14:41:43 +00:00
}
if ( word_at_pos = = " " ) {
2021-07-09 11:42:55 +00:00
word_at_pos = tx - > get_selected_text ( ) ;
2020-05-14 14:41:43 +00:00
}
2018-01-02 07:10:49 +00:00
2019-06-22 18:22:52 +00:00
bool has_color = ( word_at_pos = = " Color " ) ;
2021-03-13 14:09:49 +00:00
bool foldable = tx - > can_fold_line ( row ) | | tx - > is_line_folded ( row ) ;
2019-06-22 18:22:52 +00:00
bool open_docs = false ;
bool goto_definition = false ;
2018-01-02 07:10:49 +00:00
2019-06-22 18:22:52 +00:00
if ( word_at_pos . is_resource_file ( ) ) {
open_docs = true ;
} else {
Node * base = get_tree ( ) - > get_edited_scene_root ( ) ;
if ( base ) {
base = _find_node_for_script ( base , base , script ) ;
}
ScriptLanguage : : LookupResult result ;
2021-07-01 16:10:54 +00:00
if ( script - > get_language ( ) - > lookup_code ( code_editor - > get_text_editor ( ) - > get_text_for_symbol_lookup ( ) , word_at_pos , script - > get_path ( ) , base , result ) = = OK ) {
2018-01-02 07:10:49 +00:00
open_docs = true ;
}
2019-06-22 18:22:52 +00:00
}
2018-01-02 07:10:49 +00:00
2019-06-22 18:22:52 +00:00
if ( has_color ) {
String line = tx - > get_line ( row ) ;
color_position . x = row ;
color_position . y = col ;
int begin = 0 ;
int end = 0 ;
bool valid = false ;
for ( int i = col ; i < line . length ( ) ; i + + ) {
if ( line [ i ] = = ' ( ' ) {
begin = i ;
continue ;
} else if ( line [ i ] = = ' ) ' ) {
end = i + 1 ;
valid = true ;
break ;
2018-01-02 07:10:49 +00:00
}
2019-06-22 18:22:52 +00:00
}
if ( valid ) {
color_args = line . substr ( begin , end - begin ) ;
String stripped = color_args . replace ( " " , " " ) . replace ( " ( " , " " ) . replace ( " ) " , " " ) ;
Vector < float > color = stripped . split_floats ( " , " ) ;
if ( color . size ( ) > 2 ) {
float alpha = color . size ( ) > 3 ? color [ 3 ] : 1.0f ;
color_picker - > set_pick_color ( Color ( color [ 0 ] , color [ 1 ] , color [ 2 ] , alpha ) ) ;
2016-09-29 07:12:45 +00:00
}
2019-06-22 18:22:52 +00:00
color_panel - > set_position ( get_global_transform ( ) . xform ( local_pos ) ) ;
} else {
has_color = false ;
2016-09-29 07:12:45 +00:00
}
}
2021-07-09 11:42:55 +00:00
_make_context_menu ( tx - > has_selection ( ) , has_color , foldable , open_docs , goto_definition , local_pos ) ;
2016-09-29 07:12:45 +00:00
}
}
2017-03-05 15:44:50 +00:00
void ScriptTextEditor : : _color_changed ( const Color & p_color ) {
2016-09-29 07:12:45 +00:00
String new_args ;
if ( p_color . a = = 1.0f ) {
2017-03-05 15:44:50 +00:00
new_args = String ( " ( " + rtos ( p_color . r ) + " , " + rtos ( p_color . g ) + " , " + rtos ( p_color . b ) + " ) " ) ;
2016-09-29 07:12:45 +00:00
} else {
2017-03-05 15:44:50 +00:00
new_args = String ( " ( " + rtos ( p_color . r ) + " , " + rtos ( p_color . g ) + " , " + rtos ( p_color . b ) + " , " + rtos ( p_color . a ) + " ) " ) ;
2016-09-29 07:12:45 +00:00
}
2020-07-24 14:50:35 +00:00
String line = code_editor - > get_text_editor ( ) - > get_line ( color_position . x ) ;
2019-08-02 20:32:33 +00:00
int color_args_pos = line . find ( color_args , color_position . y ) ;
String line_with_replaced_args = line ;
line_with_replaced_args . erase ( color_args_pos , color_args . length ( ) ) ;
line_with_replaced_args = line_with_replaced_args . insert ( color_args_pos , new_args ) ;
2016-09-29 07:12:45 +00:00
color_args = new_args ;
2020-07-24 14:50:35 +00:00
code_editor - > get_text_editor ( ) - > begin_complex_operation ( ) ;
code_editor - > get_text_editor ( ) - > set_line ( color_position . x , line_with_replaced_args ) ;
code_editor - > get_text_editor ( ) - > end_complex_operation ( ) ;
code_editor - > get_text_editor ( ) - > update ( ) ;
2016-09-29 07:12:45 +00:00
}
2021-08-17 03:41:46 +00:00
void ScriptTextEditor : : _prepare_edit_menu ( ) {
const CodeEdit * tx = code_editor - > get_text_editor ( ) ;
PopupMenu * popup = edit_menu - > get_popup ( ) ;
popup - > set_item_disabled ( popup - > get_item_index ( EDIT_UNDO ) , ! tx - > has_undo ( ) ) ;
popup - > set_item_disabled ( popup - > get_item_index ( EDIT_REDO ) , ! tx - > has_redo ( ) ) ;
}
2019-06-22 18:22:52 +00:00
void ScriptTextEditor : : _make_context_menu ( bool p_selection , bool p_color , bool p_foldable , bool p_open_docs , bool p_goto_definition , Vector2 p_pos ) {
2016-09-29 07:12:45 +00:00
context_menu - > clear ( ) ;
2020-12-07 11:32:00 +00:00
context_menu - > add_shortcut ( ED_GET_SHORTCUT ( " ui_undo " ) , EDIT_UNDO ) ;
context_menu - > add_shortcut ( ED_GET_SHORTCUT ( " ui_redo " ) , EDIT_REDO ) ;
2016-09-29 07:12:45 +00:00
2019-08-12 20:23:00 +00:00
context_menu - > add_separator ( ) ;
2020-12-07 11:32:00 +00:00
context_menu - > add_shortcut ( ED_GET_SHORTCUT ( " ui_cut " ) , EDIT_CUT ) ;
context_menu - > add_shortcut ( ED_GET_SHORTCUT ( " ui_copy " ) , EDIT_COPY ) ;
context_menu - > add_shortcut ( ED_GET_SHORTCUT ( " ui_paste " ) , EDIT_PASTE ) ;
2019-08-12 20:23:00 +00:00
2016-09-29 07:12:45 +00:00
context_menu - > add_separator ( ) ;
2020-12-07 11:32:00 +00:00
context_menu - > add_shortcut ( ED_GET_SHORTCUT ( " ui_text_select_all " ) , EDIT_SELECT_ALL ) ;
2019-08-12 20:23:00 +00:00
2017-12-14 09:10:53 +00:00
context_menu - > add_separator ( ) ;
context_menu - > add_shortcut ( ED_GET_SHORTCUT ( " script_text_editor/indent_left " ) , EDIT_INDENT_LEFT ) ;
context_menu - > add_shortcut ( ED_GET_SHORTCUT ( " script_text_editor/indent_right " ) , EDIT_INDENT_RIGHT ) ;
context_menu - > add_shortcut ( ED_GET_SHORTCUT ( " script_text_editor/toggle_comment " ) , EDIT_TOGGLE_COMMENT ) ;
2019-04-19 23:51:25 +00:00
context_menu - > add_shortcut ( ED_GET_SHORTCUT ( " script_text_editor/toggle_bookmark " ) , BOOKMARK_TOGGLE ) ;
2016-09-29 07:12:45 +00:00
if ( p_selection ) {
context_menu - > add_separator ( ) ;
2017-12-07 08:09:02 +00:00
context_menu - > add_shortcut ( ED_GET_SHORTCUT ( " script_text_editor/convert_to_uppercase " ) , EDIT_TO_UPPERCASE ) ;
context_menu - > add_shortcut ( ED_GET_SHORTCUT ( " script_text_editor/convert_to_lowercase " ) , EDIT_TO_LOWERCASE ) ;
2019-08-07 14:31:33 +00:00
context_menu - > add_shortcut ( ED_GET_SHORTCUT ( " script_text_editor/evaluate_selection " ) , EDIT_EVALUATE ) ;
2016-09-29 07:12:45 +00:00
}
2020-05-14 14:41:43 +00:00
if ( p_foldable ) {
2017-12-08 18:17:10 +00:00
context_menu - > add_shortcut ( ED_GET_SHORTCUT ( " script_text_editor/toggle_fold_line " ) , EDIT_TOGGLE_FOLD_LINE ) ;
2020-05-14 14:41:43 +00:00
}
2017-12-08 18:17:10 +00:00
2018-01-02 07:10:49 +00:00
if ( p_color | | p_open_docs | | p_goto_definition ) {
2016-09-29 07:12:45 +00:00
context_menu - > add_separator ( ) ;
2020-05-14 14:41:43 +00:00
if ( p_open_docs ) {
2018-01-02 07:10:49 +00:00
context_menu - > add_item ( TTR ( " Lookup Symbol " ) , LOOKUP_SYMBOL ) ;
2020-05-14 14:41:43 +00:00
}
if ( p_color ) {
2018-01-02 07:10:49 +00:00
context_menu - > add_item ( TTR ( " Pick Color " ) , EDIT_PICK_COLOR ) ;
2020-05-14 14:41:43 +00:00
}
2016-09-29 07:12:45 +00:00
}
2018-01-02 07:10:49 +00:00
2021-08-17 03:41:46 +00:00
const CodeEdit * tx = code_editor - > get_text_editor ( ) ;
context_menu - > set_item_disabled ( context_menu - > get_item_index ( EDIT_UNDO ) , ! tx - > has_undo ( ) ) ;
context_menu - > set_item_disabled ( context_menu - > get_item_index ( EDIT_REDO ) , ! tx - > has_redo ( ) ) ;
2019-06-22 18:22:52 +00:00
context_menu - > set_position ( get_global_transform ( ) . xform ( p_pos ) ) ;
2016-09-29 07:12:45 +00:00
context_menu - > set_size ( Vector2 ( 1 , 1 ) ) ;
context_menu - > popup ( ) ;
}
2016-09-11 14:28:01 +00:00
2019-11-20 09:09:59 +00:00
void ScriptTextEditor : : _enable_code_editor ( ) {
ERR_FAIL_COND ( code_editor - > get_parent ( ) ) ;
2017-10-02 23:33:42 +00:00
2018-07-01 16:17:40 +00:00
VSplitContainer * editor_box = memnew ( VSplitContainer ) ;
add_child ( editor_box ) ;
2020-12-22 16:24:29 +00:00
editor_box - > set_anchors_and_offsets_preset ( Control : : PRESET_WIDE ) ;
2018-07-01 16:17:40 +00:00
editor_box - > set_v_size_flags ( SIZE_EXPAND_FILL ) ;
editor_box - > add_child ( code_editor ) ;
2021-05-18 03:09:19 +00:00
code_editor - > connect ( " show_errors_panel " , callable_mp ( this , & ScriptTextEditor : : _show_errors_panel ) ) ;
2019-11-20 09:09:59 +00:00
code_editor - > connect ( " show_warnings_panel " , callable_mp ( this , & ScriptTextEditor : : _show_warnings_panel ) ) ;
2020-02-21 17:28:45 +00:00
code_editor - > connect ( " validate_script " , callable_mp ( this , & ScriptTextEditor : : _validate_script ) ) ;
code_editor - > connect ( " load_theme_settings " , callable_mp ( this , & ScriptTextEditor : : _load_theme_settings ) ) ;
2020-07-24 14:50:35 +00:00
code_editor - > get_text_editor ( ) - > connect ( " breakpoint_toggled " , callable_mp ( this , & ScriptTextEditor : : _breakpoint_toggled ) ) ;
code_editor - > get_text_editor ( ) - > connect ( " symbol_lookup " , callable_mp ( this , & ScriptTextEditor : : _lookup_symbol ) ) ;
code_editor - > get_text_editor ( ) - > connect ( " symbol_validate " , callable_mp ( this , & ScriptTextEditor : : _validate_symbol ) ) ;
2020-07-29 21:26:49 +00:00
code_editor - > get_text_editor ( ) - > connect ( " gutter_added " , callable_mp ( this , & ScriptTextEditor : : _update_gutter_indexes ) ) ;
code_editor - > get_text_editor ( ) - > connect ( " gutter_removed " , callable_mp ( this , & ScriptTextEditor : : _update_gutter_indexes ) ) ;
code_editor - > get_text_editor ( ) - > connect ( " gutter_clicked " , callable_mp ( this , & ScriptTextEditor : : _gutter_clicked ) ) ;
2020-07-24 14:50:35 +00:00
code_editor - > get_text_editor ( ) - > connect ( " gui_input " , callable_mp ( this , & ScriptTextEditor : : _text_edit_gui_input ) ) ;
2019-12-17 08:16:17 +00:00
code_editor - > show_toggle_scripts_button ( ) ;
2020-07-30 10:41:05 +00:00
_update_gutter_indexes ( ) ;
2018-07-01 16:17:40 +00:00
editor_box - > add_child ( warnings_panel ) ;
2020-05-24 12:30:09 +00:00
warnings_panel - > add_theme_font_override (
2021-07-17 21:22:52 +00:00
" normal_font " , EditorNode : : get_singleton ( ) - > get_gui_base ( ) - > get_theme_font ( SNAME ( " main " ) , SNAME ( " EditorFonts " ) ) ) ;
2020-09-03 11:22:16 +00:00
warnings_panel - > add_theme_font_size_override (
2021-07-17 21:22:52 +00:00
" normal_font_size " , EditorNode : : get_singleton ( ) - > get_gui_base ( ) - > get_theme_font_size ( SNAME ( " main_size " ) , SNAME ( " EditorFonts " ) ) ) ;
2020-02-21 17:28:45 +00:00
warnings_panel - > connect ( " meta_clicked " , callable_mp ( this , & ScriptTextEditor : : _warning_clicked ) ) ;
2016-09-12 13:52:29 +00:00
2021-05-18 03:09:19 +00:00
editor_box - > add_child ( errors_panel ) ;
errors_panel - > add_theme_font_override (
2021-07-17 21:22:52 +00:00
" normal_font " , EditorNode : : get_singleton ( ) - > get_gui_base ( ) - > get_theme_font ( SNAME ( " main " ) , SNAME ( " EditorFonts " ) ) ) ;
2021-05-18 03:09:19 +00:00
errors_panel - > add_theme_font_size_override (
2021-07-17 21:22:52 +00:00
" normal_font_size " , EditorNode : : get_singleton ( ) - > get_gui_base ( ) - > get_theme_font_size ( SNAME ( " main_size " ) , SNAME ( " EditorFonts " ) ) ) ;
2021-05-18 03:09:19 +00:00
errors_panel - > connect ( " meta_clicked " , callable_mp ( this , & ScriptTextEditor : : _error_clicked ) ) ;
2016-09-29 07:12:45 +00:00
add_child ( context_menu ) ;
2020-02-21 17:28:45 +00:00
context_menu - > connect ( " id_pressed " , callable_mp ( this , & ScriptTextEditor : : _edit_option ) ) ;
2016-09-29 07:12:45 +00:00
add_child ( color_panel ) ;
2019-11-20 09:09:59 +00:00
2016-09-29 07:12:45 +00:00
color_picker = memnew ( ColorPicker ) ;
2019-08-02 20:32:33 +00:00
color_picker - > set_deferred_mode ( true ) ;
2020-02-21 17:28:45 +00:00
color_picker - > connect ( " color_changed " , callable_mp ( this , & ScriptTextEditor : : _color_changed ) ) ;
2016-09-12 13:52:29 +00:00
2019-11-20 09:09:59 +00:00
color_panel - > add_child ( color_picker ) ;
2019-08-30 20:25:15 +00:00
// get default color picker mode from editor settings
int default_color_mode = EDITOR_GET ( " interface/inspector/default_color_picker_mode " ) ;
2020-05-14 14:41:43 +00:00
if ( default_color_mode = = 1 ) {
2019-08-30 20:25:15 +00:00
color_picker - > set_hsv_mode ( true ) ;
2020-05-14 14:41:43 +00:00
} else if ( default_color_mode = = 2 ) {
2019-08-30 20:25:15 +00:00
color_picker - > set_raw_mode ( true ) ;
2020-05-14 14:41:43 +00:00
}
2019-08-30 20:25:15 +00:00
2021-02-23 10:22:46 +00:00
int picker_shape = EDITOR_GET ( " interface/inspector/default_color_picker_shape " ) ;
color_picker - > set_picker_shape ( ( ColorPicker : : PickerShapeType ) picker_shape ) ;
2019-11-20 09:09:59 +00:00
quick_open = memnew ( ScriptEditorQuickOpen ) ;
quick_open - > connect ( " goto_line " , callable_mp ( this , & ScriptTextEditor : : _goto_line ) ) ;
add_child ( quick_open ) ;
2016-08-02 22:11:05 +00:00
2019-11-20 09:09:59 +00:00
goto_line_dialog = memnew ( GotoLineDialog ) ;
add_child ( goto_line_dialog ) ;
add_child ( connection_info_dialog ) ;
edit_hb - > add_child ( search_menu ) ;
search_menu - > get_popup ( ) - > add_shortcut ( ED_GET_SHORTCUT ( " script_text_editor/find " ) , SEARCH_FIND ) ;
search_menu - > get_popup ( ) - > add_shortcut ( ED_GET_SHORTCUT ( " script_text_editor/find_next " ) , SEARCH_FIND_NEXT ) ;
search_menu - > get_popup ( ) - > add_shortcut ( ED_GET_SHORTCUT ( " script_text_editor/find_previous " ) , SEARCH_FIND_PREV ) ;
search_menu - > get_popup ( ) - > add_shortcut ( ED_GET_SHORTCUT ( " script_text_editor/replace " ) , SEARCH_REPLACE ) ;
search_menu - > get_popup ( ) - > add_separator ( ) ;
search_menu - > get_popup ( ) - > add_shortcut ( ED_GET_SHORTCUT ( " script_text_editor/find_in_files " ) , SEARCH_IN_FILES ) ;
search_menu - > get_popup ( ) - > add_separator ( ) ;
search_menu - > get_popup ( ) - > add_shortcut ( ED_GET_SHORTCUT ( " script_text_editor/contextual_help " ) , HELP_CONTEXTUAL ) ;
search_menu - > get_popup ( ) - > connect ( " id_pressed " , callable_mp ( this , & ScriptTextEditor : : _edit_option ) ) ;
2020-03-12 12:37:40 +00:00
2019-11-20 09:09:59 +00:00
edit_hb - > add_child ( edit_menu ) ;
2021-08-17 03:41:46 +00:00
edit_menu - > connect ( " about_to_popup " , callable_mp ( this , & ScriptTextEditor : : _prepare_edit_menu ) ) ;
2020-12-07 11:32:00 +00:00
edit_menu - > get_popup ( ) - > add_shortcut ( ED_GET_SHORTCUT ( " ui_undo " ) , EDIT_UNDO ) ;
edit_menu - > get_popup ( ) - > add_shortcut ( ED_GET_SHORTCUT ( " ui_redo " ) , EDIT_REDO ) ;
2016-08-02 22:11:05 +00:00
edit_menu - > get_popup ( ) - > add_separator ( ) ;
2020-12-07 11:32:00 +00:00
edit_menu - > get_popup ( ) - > add_shortcut ( ED_GET_SHORTCUT ( " ui_cut " ) , EDIT_CUT ) ;
edit_menu - > get_popup ( ) - > add_shortcut ( ED_GET_SHORTCUT ( " ui_copy " ) , EDIT_COPY ) ;
edit_menu - > get_popup ( ) - > add_shortcut ( ED_GET_SHORTCUT ( " ui_paste " ) , EDIT_PASTE ) ;
2016-08-02 22:11:05 +00:00
edit_menu - > get_popup ( ) - > add_separator ( ) ;
2020-12-07 11:32:00 +00:00
edit_menu - > get_popup ( ) - > add_shortcut ( ED_GET_SHORTCUT ( " ui_text_select_all " ) , EDIT_SELECT_ALL ) ;
2016-08-02 22:11:05 +00:00
edit_menu - > get_popup ( ) - > add_separator ( ) ;
edit_menu - > get_popup ( ) - > add_shortcut ( ED_GET_SHORTCUT ( " script_text_editor/move_up " ) , EDIT_MOVE_LINE_UP ) ;
edit_menu - > get_popup ( ) - > add_shortcut ( ED_GET_SHORTCUT ( " script_text_editor/move_down " ) , EDIT_MOVE_LINE_DOWN ) ;
edit_menu - > get_popup ( ) - > add_shortcut ( ED_GET_SHORTCUT ( " script_text_editor/indent_left " ) , EDIT_INDENT_LEFT ) ;
edit_menu - > get_popup ( ) - > add_shortcut ( ED_GET_SHORTCUT ( " script_text_editor/indent_right " ) , EDIT_INDENT_RIGHT ) ;
2017-08-20 12:31:30 +00:00
edit_menu - > get_popup ( ) - > add_shortcut ( ED_GET_SHORTCUT ( " script_text_editor/delete_line " ) , EDIT_DELETE_LINE ) ;
2016-08-02 22:11:05 +00:00
edit_menu - > get_popup ( ) - > add_shortcut ( ED_GET_SHORTCUT ( " script_text_editor/toggle_comment " ) , EDIT_TOGGLE_COMMENT ) ;
2017-12-08 18:17:10 +00:00
edit_menu - > get_popup ( ) - > add_shortcut ( ED_GET_SHORTCUT ( " script_text_editor/toggle_fold_line " ) , EDIT_TOGGLE_FOLD_LINE ) ;
2017-11-16 04:00:27 +00:00
edit_menu - > get_popup ( ) - > add_shortcut ( ED_GET_SHORTCUT ( " script_text_editor/fold_all_lines " ) , EDIT_FOLD_ALL_LINES ) ;
2017-11-12 23:12:17 +00:00
edit_menu - > get_popup ( ) - > add_shortcut ( ED_GET_SHORTCUT ( " script_text_editor/unfold_all_lines " ) , EDIT_UNFOLD_ALL_LINES ) ;
2016-08-02 22:11:05 +00:00
edit_menu - > get_popup ( ) - > add_separator ( ) ;
2021-06-29 10:09:07 +00:00
edit_menu - > get_popup ( ) - > add_shortcut ( ED_GET_SHORTCUT ( " script_text_editor/duplicate_selection " ) , EDIT_DUPLICATE_SELECTION ) ;
2020-12-07 11:32:00 +00:00
edit_menu - > get_popup ( ) - > add_shortcut ( ED_GET_SHORTCUT ( " ui_text_completion_query " ) , EDIT_COMPLETE ) ;
2019-08-07 14:31:33 +00:00
edit_menu - > get_popup ( ) - > add_shortcut ( ED_GET_SHORTCUT ( " script_text_editor/evaluate_selection " ) , EDIT_EVALUATE ) ;
2016-08-02 22:11:05 +00:00
edit_menu - > get_popup ( ) - > add_shortcut ( ED_GET_SHORTCUT ( " script_text_editor/trim_trailing_whitespace " ) , EDIT_TRIM_TRAILING_WHITESAPCE ) ;
2017-04-16 15:47:59 +00:00
edit_menu - > get_popup ( ) - > add_shortcut ( ED_GET_SHORTCUT ( " script_text_editor/convert_indent_to_spaces " ) , EDIT_CONVERT_INDENT_TO_SPACES ) ;
edit_menu - > get_popup ( ) - > add_shortcut ( ED_GET_SHORTCUT ( " script_text_editor/convert_indent_to_tabs " ) , EDIT_CONVERT_INDENT_TO_TABS ) ;
2016-08-02 22:11:05 +00:00
edit_menu - > get_popup ( ) - > add_shortcut ( ED_GET_SHORTCUT ( " script_text_editor/auto_indent " ) , EDIT_AUTO_INDENT ) ;
2020-02-21 17:28:45 +00:00
edit_menu - > get_popup ( ) - > connect ( " id_pressed " , callable_mp ( this , & ScriptTextEditor : : _edit_option ) ) ;
2016-08-02 22:11:05 +00:00
edit_menu - > get_popup ( ) - > add_separator ( ) ;
2018-06-01 19:32:19 +00:00
2017-04-24 18:59:55 +00:00
edit_menu - > get_popup ( ) - > add_child ( convert_case ) ;
edit_menu - > get_popup ( ) - > add_submenu_item ( TTR ( " Convert Case " ) , " convert_case " ) ;
2018-09-01 14:20:47 +00:00
convert_case - > add_shortcut ( ED_SHORTCUT ( " script_text_editor/convert_to_uppercase " , TTR ( " Uppercase " ) , KEY_MASK_SHIFT | KEY_F4 ) , EDIT_TO_UPPERCASE ) ;
convert_case - > add_shortcut ( ED_SHORTCUT ( " script_text_editor/convert_to_lowercase " , TTR ( " Lowercase " ) , KEY_MASK_SHIFT | KEY_F5 ) , EDIT_TO_LOWERCASE ) ;
convert_case - > add_shortcut ( ED_SHORTCUT ( " script_text_editor/capitalize " , TTR ( " Capitalize " ) , KEY_MASK_SHIFT | KEY_F6 ) , EDIT_CAPITALIZE ) ;
2020-02-21 17:28:45 +00:00
convert_case - > connect ( " id_pressed " , callable_mp ( this , & ScriptTextEditor : : _edit_option ) ) ;
2016-08-02 22:11:05 +00:00
2018-06-01 19:32:19 +00:00
edit_menu - > get_popup ( ) - > add_child ( highlighter_menu ) ;
edit_menu - > get_popup ( ) - > add_submenu_item ( TTR ( " Syntax Highlighter " ) , " highlighter_menu " ) ;
2020-02-21 17:28:45 +00:00
highlighter_menu - > connect ( " id_pressed " , callable_mp ( this , & ScriptTextEditor : : _change_syntax_highlighter ) ) ;
2018-06-01 19:32:19 +00:00
2019-11-20 09:09:59 +00:00
_load_theme_settings ( ) ;
search_menu - > get_popup ( ) - > add_shortcut ( ED_GET_SHORTCUT ( " script_text_editor/replace_in_files " ) , REPLACE_IN_FILES ) ;
edit_hb - > add_child ( goto_menu ) ;
goto_menu - > get_popup ( ) - > add_shortcut ( ED_GET_SHORTCUT ( " script_text_editor/goto_function " ) , SEARCH_LOCATE_FUNCTION ) ;
goto_menu - > get_popup ( ) - > add_shortcut ( ED_GET_SHORTCUT ( " script_text_editor/goto_line " ) , SEARCH_GOTO_LINE ) ;
goto_menu - > get_popup ( ) - > add_separator ( ) ;
goto_menu - > get_popup ( ) - > add_child ( bookmarks_menu ) ;
goto_menu - > get_popup ( ) - > add_submenu_item ( TTR ( " Bookmarks " ) , " Bookmarks " ) ;
_update_bookmark_list ( ) ;
bookmarks_menu - > connect ( " about_to_popup " , callable_mp ( this , & ScriptTextEditor : : _update_bookmark_list ) ) ;
bookmarks_menu - > connect ( " index_pressed " , callable_mp ( this , & ScriptTextEditor : : _bookmark_item_pressed ) ) ;
goto_menu - > get_popup ( ) - > add_child ( breakpoints_menu ) ;
goto_menu - > get_popup ( ) - > add_submenu_item ( TTR ( " Breakpoints " ) , " Breakpoints " ) ;
_update_breakpoint_list ( ) ;
breakpoints_menu - > connect ( " about_to_popup " , callable_mp ( this , & ScriptTextEditor : : _update_breakpoint_list ) ) ;
breakpoints_menu - > connect ( " index_pressed " , callable_mp ( this , & ScriptTextEditor : : _breakpoint_item_pressed ) ) ;
goto_menu - > get_popup ( ) - > connect ( " id_pressed " , callable_mp ( this , & ScriptTextEditor : : _edit_option ) ) ;
}
ScriptTextEditor : : ScriptTextEditor ( ) {
code_editor = memnew ( CodeTextEditor ) ;
code_editor - > add_theme_constant_override ( " separation " , 2 ) ;
2020-12-22 16:24:29 +00:00
code_editor - > set_anchors_and_offsets_preset ( Control : : PRESET_WIDE ) ;
2019-11-20 09:09:59 +00:00
code_editor - > set_code_complete_func ( _code_complete_scripts , this ) ;
code_editor - > set_v_size_flags ( SIZE_EXPAND_FILL ) ;
2020-07-30 11:22:09 +00:00
code_editor - > get_text_editor ( ) - > set_draw_breakpoints_gutter ( true ) ;
code_editor - > get_text_editor ( ) - > set_draw_executing_lines_gutter ( true ) ;
2020-07-29 21:26:49 +00:00
connection_gutter = 1 ;
code_editor - > get_text_editor ( ) - > add_gutter ( connection_gutter ) ;
code_editor - > get_text_editor ( ) - > set_gutter_name ( connection_gutter , " connection_gutter " ) ;
code_editor - > get_text_editor ( ) - > set_gutter_draw ( connection_gutter , false ) ;
code_editor - > get_text_editor ( ) - > set_gutter_overwritable ( connection_gutter , true ) ;
2021-07-19 08:16:00 +00:00
code_editor - > get_text_editor ( ) - > set_gutter_type ( connection_gutter , TextEdit : : GUTTER_TYPE_ICON ) ;
2020-07-29 21:26:49 +00:00
2019-11-20 09:09:59 +00:00
warnings_panel = memnew ( RichTextLabel ) ;
warnings_panel - > set_custom_minimum_size ( Size2 ( 0 , 100 * EDSCALE ) ) ;
warnings_panel - > set_h_size_flags ( SIZE_EXPAND_FILL ) ;
warnings_panel - > set_meta_underline ( true ) ;
warnings_panel - > set_selection_enabled ( true ) ;
warnings_panel - > set_focus_mode ( FOCUS_CLICK ) ;
warnings_panel - > hide ( ) ;
2021-05-18 03:09:19 +00:00
errors_panel = memnew ( RichTextLabel ) ;
errors_panel - > set_custom_minimum_size ( Size2 ( 0 , 100 * EDSCALE ) ) ;
errors_panel - > set_h_size_flags ( SIZE_EXPAND_FILL ) ;
errors_panel - > set_meta_underline ( true ) ;
errors_panel - > set_selection_enabled ( true ) ;
errors_panel - > set_focus_mode ( FOCUS_CLICK ) ;
errors_panel - > hide ( ) ;
2019-11-20 09:09:59 +00:00
update_settings ( ) ;
2020-09-18 19:45:47 +00:00
code_editor - > get_text_editor ( ) - > set_code_hint_draw_below ( EditorSettings : : get_singleton ( ) - > get ( " text_editor/completion/put_callhint_tooltip_below_current_line " ) ) ;
2019-11-20 09:09:59 +00:00
2021-07-01 16:10:54 +00:00
code_editor - > get_text_editor ( ) - > set_symbol_lookup_on_click_enabled ( true ) ;
2020-07-24 14:50:35 +00:00
code_editor - > get_text_editor ( ) - > set_context_menu_enabled ( false ) ;
2019-11-20 09:09:59 +00:00
context_menu = memnew ( PopupMenu ) ;
color_panel = memnew ( PopupPanel ) ;
edit_hb = memnew ( HBoxContainer ) ;
edit_menu = memnew ( MenuButton ) ;
edit_menu - > set_text ( TTR ( " Edit " ) ) ;
edit_menu - > set_switch_on_hover ( true ) ;
2020-09-17 01:40:00 +00:00
edit_menu - > set_shortcut_context ( this ) ;
2019-11-20 09:09:59 +00:00
convert_case = memnew ( PopupMenu ) ;
convert_case - > set_name ( " convert_case " ) ;
highlighter_menu = memnew ( PopupMenu ) ;
highlighter_menu - > set_name ( " highlighter_menu " ) ;
2020-05-03 16:08:15 +00:00
Ref < EditorPlainTextSyntaxHighlighter > plain_highlighter ;
2021-06-17 22:03:09 +00:00
plain_highlighter . instantiate ( ) ;
2020-05-03 16:08:15 +00:00
add_syntax_highlighter ( plain_highlighter ) ;
Ref < EditorStandardSyntaxHighlighter > highlighter ;
2021-06-17 22:03:09 +00:00
highlighter . instantiate ( ) ;
2020-05-03 16:08:15 +00:00
add_syntax_highlighter ( highlighter ) ;
set_syntax_highlighter ( highlighter ) ;
2017-03-05 15:44:50 +00:00
search_menu = memnew ( MenuButton ) ;
2016-08-02 22:11:05 +00:00
search_menu - > set_text ( TTR ( " Search " ) ) ;
2018-07-29 22:26:43 +00:00
search_menu - > set_switch_on_hover ( true ) ;
2020-09-17 01:40:00 +00:00
search_menu - > set_shortcut_context ( this ) ;
2020-03-12 12:37:40 +00:00
2019-11-20 09:09:59 +00:00
goto_menu = memnew ( MenuButton ) ;
2019-07-01 19:00:05 +00:00
goto_menu - > set_text ( TTR ( " Go To " ) ) ;
goto_menu - > set_switch_on_hover ( true ) ;
2020-09-17 01:40:00 +00:00
goto_menu - > set_shortcut_context ( this ) ;
2019-07-01 19:00:05 +00:00
bookmarks_menu = memnew ( PopupMenu ) ;
bookmarks_menu - > set_name ( " Bookmarks " ) ;
breakpoints_menu = memnew ( PopupMenu ) ;
breakpoints_menu - > set_name ( " Breakpoints " ) ;
2016-09-11 14:28:01 +00:00
2019-04-20 11:51:25 +00:00
connection_info_dialog = memnew ( ConnectionInfoDialog ) ;
2020-07-24 14:50:35 +00:00
code_editor - > get_text_editor ( ) - > set_drag_forwarding ( this ) ;
2016-08-02 22:11:05 +00:00
}
2019-07-25 16:30:48 +00:00
ScriptTextEditor : : ~ ScriptTextEditor ( ) {
highlighters . clear ( ) ;
2019-11-20 09:09:59 +00:00
if ( ! editor_enabled ) {
memdelete ( code_editor ) ;
memdelete ( warnings_panel ) ;
2021-05-18 03:09:19 +00:00
memdelete ( errors_panel ) ;
2019-11-20 09:09:59 +00:00
memdelete ( context_menu ) ;
memdelete ( color_panel ) ;
memdelete ( edit_hb ) ;
memdelete ( edit_menu ) ;
memdelete ( convert_case ) ;
memdelete ( highlighter_menu ) ;
memdelete ( search_menu ) ;
memdelete ( goto_menu ) ;
memdelete ( bookmarks_menu ) ;
memdelete ( breakpoints_menu ) ;
memdelete ( connection_info_dialog ) ;
}
2019-07-25 16:30:48 +00:00
}
2018-05-28 15:52:28 +00:00
static ScriptEditorBase * create_editor ( const RES & p_resource ) {
if ( Object : : cast_to < Script > ( * p_resource ) ) {
return memnew ( ScriptTextEditor ) ;
}
2020-04-01 23:20:12 +00:00
return nullptr ;
2016-08-02 22:11:05 +00:00
}
void ScriptTextEditor : : register_editor ( ) {
2017-03-05 15:44:50 +00:00
ED_SHORTCUT ( " script_text_editor/move_up " , TTR ( " Move Up " ) , KEY_MASK_ALT | KEY_UP ) ;
ED_SHORTCUT ( " script_text_editor/move_down " , TTR ( " Move Down " ) , KEY_MASK_ALT | KEY_DOWN ) ;
2018-06-11 05:53:25 +00:00
ED_SHORTCUT ( " script_text_editor/delete_line " , TTR ( " Delete Line " ) , KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_K ) ;
2017-01-04 20:37:45 +00:00
2019-08-09 01:36:51 +00:00
// Leave these at zero, same can be accomplished with tab/shift-tab, including selection.
// The next/previous in history shortcut in this case makes a lot more sense.
2017-01-04 20:37:45 +00:00
2021-06-20 17:12:33 +00:00
ED_SHORTCUT ( " script_text_editor/indent_left " , TTR ( " Indent Left " ) , KEY_NONE ) ;
ED_SHORTCUT ( " script_text_editor/indent_right " , TTR ( " Indent Right " ) , KEY_NONE ) ;
2017-03-05 15:44:50 +00:00
ED_SHORTCUT ( " script_text_editor/toggle_comment " , TTR ( " Toggle Comment " ) , KEY_MASK_CMD | KEY_K ) ;
2017-12-08 18:17:10 +00:00
ED_SHORTCUT ( " script_text_editor/toggle_fold_line " , TTR ( " Fold/Unfold Line " ) , KEY_MASK_ALT | KEY_F ) ;
2021-06-20 17:12:33 +00:00
ED_SHORTCUT ( " script_text_editor/fold_all_lines " , TTR ( " Fold All Lines " ) , KEY_NONE ) ;
ED_SHORTCUT ( " script_text_editor/unfold_all_lines " , TTR ( " Unfold All Lines " ) , KEY_NONE ) ;
2016-08-02 22:11:05 +00:00
# ifdef OSX_ENABLED
2021-06-29 10:09:07 +00:00
ED_SHORTCUT ( " script_text_editor/duplicate_selection " , TTR ( " Duplicate Selection " ) , KEY_MASK_SHIFT | KEY_MASK_CMD | KEY_C ) ;
2016-08-02 22:11:05 +00:00
# else
2021-06-29 10:09:07 +00:00
ED_SHORTCUT ( " script_text_editor/duplicate_selection " , TTR ( " Duplicate Selection " ) , KEY_MASK_SHIFT | KEY_MASK_CMD | KEY_D ) ;
2018-08-27 18:35:47 +00:00
# endif
2019-08-07 14:31:33 +00:00
ED_SHORTCUT ( " script_text_editor/evaluate_selection " , TTR ( " Evaluate Selection " ) , KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_E ) ;
2018-06-11 05:53:25 +00:00
ED_SHORTCUT ( " script_text_editor/trim_trailing_whitespace " , TTR ( " Trim Trailing Whitespace " ) , KEY_MASK_CMD | KEY_MASK_ALT | KEY_T ) ;
2018-10-26 19:11:36 +00:00
ED_SHORTCUT ( " script_text_editor/convert_indent_to_spaces " , TTR ( " Convert Indent to Spaces " ) , KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_Y ) ;
ED_SHORTCUT ( " script_text_editor/convert_indent_to_tabs " , TTR ( " Convert Indent to Tabs " ) , KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_I ) ;
2017-03-05 15:44:50 +00:00
ED_SHORTCUT ( " script_text_editor/auto_indent " , TTR ( " Auto Indent " ) , KEY_MASK_CMD | KEY_I ) ;
2016-08-02 22:11:05 +00:00
2021-05-29 13:28:16 +00:00
ED_SHORTCUT_AND_COMMAND ( " script_text_editor/find " , TTR ( " Find... " ) , KEY_MASK_CMD | KEY_F ) ;
2018-06-11 05:53:25 +00:00
# ifdef OSX_ENABLED
ED_SHORTCUT ( " script_text_editor/find_next " , TTR ( " Find Next " ) , KEY_MASK_CMD | KEY_G ) ;
ED_SHORTCUT ( " script_text_editor/find_previous " , TTR ( " Find Previous " ) , KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_G ) ;
2021-05-29 13:28:16 +00:00
ED_SHORTCUT_AND_COMMAND ( " script_text_editor/replace " , TTR ( " Replace... " ) , KEY_MASK_ALT | KEY_MASK_CMD | KEY_F ) ;
2018-06-11 05:53:25 +00:00
# else
2016-08-02 22:11:05 +00:00
ED_SHORTCUT ( " script_text_editor/find_next " , TTR ( " Find Next " ) , KEY_F3 ) ;
2017-03-05 15:44:50 +00:00
ED_SHORTCUT ( " script_text_editor/find_previous " , TTR ( " Find Previous " ) , KEY_MASK_SHIFT | KEY_F3 ) ;
2021-05-29 13:28:16 +00:00
ED_SHORTCUT_AND_COMMAND ( " script_text_editor/replace " , TTR ( " Replace... " ) , KEY_MASK_CMD | KEY_R ) ;
2018-08-27 18:18:13 +00:00
# endif
2016-08-02 22:11:05 +00:00
2018-09-25 20:44:50 +00:00
ED_SHORTCUT ( " script_text_editor/find_in_files " , TTR ( " Find in Files... " ) , KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_F ) ;
2020-02-09 09:10:58 +00:00
ED_SHORTCUT ( " script_text_editor/replace_in_files " , TTR ( " Replace in Files... " ) , KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_R ) ;
2018-02-12 01:36:15 +00:00
2019-08-09 01:36:51 +00:00
# ifdef OSX_ENABLED
ED_SHORTCUT ( " script_text_editor/contextual_help " , TTR ( " Contextual Help " ) , KEY_MASK_ALT | KEY_MASK_SHIFT | KEY_SPACE ) ;
# else
ED_SHORTCUT ( " script_text_editor/contextual_help " , TTR ( " Contextual Help " ) , KEY_MASK_ALT | KEY_F1 ) ;
# endif
ED_SHORTCUT ( " script_text_editor/toggle_bookmark " , TTR ( " Toggle Bookmark " ) , KEY_MASK_CMD | KEY_MASK_ALT | KEY_B ) ;
ED_SHORTCUT ( " script_text_editor/goto_next_bookmark " , TTR ( " Go to Next Bookmark " ) , KEY_MASK_CMD | KEY_B ) ;
ED_SHORTCUT ( " script_text_editor/goto_previous_bookmark " , TTR ( " Go to Previous Bookmark " ) , KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_B ) ;
2021-06-20 17:12:33 +00:00
ED_SHORTCUT ( " script_text_editor/remove_all_bookmarks " , TTR ( " Remove All Bookmarks " ) , KEY_NONE ) ;
2019-08-09 01:36:51 +00:00
2018-08-27 18:18:13 +00:00
# ifdef OSX_ENABLED
2018-09-25 20:44:50 +00:00
ED_SHORTCUT ( " script_text_editor/goto_function " , TTR ( " Go to Function... " ) , KEY_MASK_CTRL | KEY_MASK_CMD | KEY_J ) ;
2018-08-27 18:18:13 +00:00
# else
2018-09-25 20:44:50 +00:00
ED_SHORTCUT ( " script_text_editor/goto_function " , TTR ( " Go to Function... " ) , KEY_MASK_ALT | KEY_MASK_CMD | KEY_F ) ;
2018-08-27 18:18:13 +00:00
# endif
2018-09-25 20:44:50 +00:00
ED_SHORTCUT ( " script_text_editor/goto_line " , TTR ( " Go to Line... " ) , KEY_MASK_CMD | KEY_L ) ;
2016-08-02 22:11:05 +00:00
2018-06-11 05:53:25 +00:00
# ifdef OSX_ENABLED
2019-08-09 01:36:51 +00:00
ED_SHORTCUT ( " script_text_editor/toggle_breakpoint " , TTR ( " Toggle Breakpoint " ) , KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_B ) ;
2018-06-11 05:53:25 +00:00
# else
2019-08-09 01:36:51 +00:00
ED_SHORTCUT ( " script_text_editor/toggle_breakpoint " , TTR ( " Toggle Breakpoint " ) , KEY_F9 ) ;
2018-06-11 05:53:25 +00:00
# endif
2019-08-09 01:36:51 +00:00
ED_SHORTCUT ( " script_text_editor/remove_all_breakpoints " , TTR ( " Remove All Breakpoints " ) , KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_F9 ) ;
ED_SHORTCUT ( " script_text_editor/goto_next_breakpoint " , TTR ( " Go to Next Breakpoint " ) , KEY_MASK_CMD | KEY_PERIOD ) ;
ED_SHORTCUT ( " script_text_editor/goto_previous_breakpoint " , TTR ( " Go to Previous Breakpoint " ) , KEY_MASK_CMD | KEY_COMMA ) ;
2016-08-02 22:11:05 +00:00
ScriptEditor : : register_create_script_editor_function ( create_editor ) ;
}
2019-05-08 16:49:49 +00:00
void ScriptTextEditor : : validate ( ) {
this - > code_editor - > validate_script ( ) ;
}