2016-07-04 23:22:28 +00:00
/**************************************************************************/
/* editor_autoload_settings.cpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
2018-01-04 23:50:27 +00:00
2016-07-04 23:22:28 +00:00
# include "editor_autoload_settings.h"
2020-11-07 22:33:38 +00:00
# include "core/config/project_settings.h"
# include "core/core_constants.h"
2022-02-12 01:46:22 +00:00
# include "editor/editor_node.h"
2023-08-13 00:33:39 +00:00
# include "editor/editor_string_names.h"
2022-03-25 17:06:46 +00:00
# include "editor/editor_undo_redo_manager.h"
2022-03-10 16:46:31 +00:00
# include "editor/filesystem_dock.h"
2023-04-07 16:59:49 +00:00
# include "editor/gui/editor_file_dialog.h"
# include "editor/project_settings_editor.h"
2024-01-15 12:14:55 +00:00
# include "editor/themes/editor_scale.h"
2020-03-04 01:51:12 +00:00
# include "scene/main/window.h"
2018-05-01 14:06:23 +00:00
# include "scene/resources/packed_scene.h"
2016-07-04 23:22:28 +00:00
# define PREVIEW_LIST_MAX_SIZE 10
void EditorAutoloadSettings : : _notification ( int p_what ) {
2022-02-15 23:52:32 +00:00
switch ( p_what ) {
case NOTIFICATION_ENTER_TREE : {
List < String > afn ;
ResourceLoader : : get_recognized_extensions_for_type ( " Script " , & afn ) ;
ResourceLoader : : get_recognized_extensions_for_type ( " PackedScene " , & afn ) ;
2016-07-04 23:22:28 +00:00
2022-02-15 23:52:32 +00:00
for ( const String & E : afn ) {
file_dialog - > add_filter ( " *. " + E ) ;
}
2018-05-22 16:26:13 +00:00
2024-10-09 22:21:47 +00:00
browse_button - > set_button_icon ( get_editor_theme_icon ( SNAME ( " Folder " ) ) ) ;
2022-02-15 23:52:32 +00:00
} break ;
case NOTIFICATION_THEME_CHANGED : {
2024-10-09 22:21:47 +00:00
browse_button - > set_button_icon ( get_editor_theme_icon ( SNAME ( " Folder " ) ) ) ;
add_autoload - > set_button_icon ( get_editor_theme_icon ( SNAME ( " Add " ) ) ) ;
2022-02-15 23:52:32 +00:00
} break ;
2022-03-10 16:46:31 +00:00
case NOTIFICATION_VISIBILITY_CHANGED : {
FileSystemDock * dock = FileSystemDock : : get_singleton ( ) ;
if ( dock ! = nullptr ) {
ScriptCreateDialog * dialog = dock - > get_script_create_dialog ( ) ;
if ( dialog ! = nullptr ) {
Callable script_created = callable_mp ( this , & EditorAutoloadSettings : : _script_created ) ;
if ( is_visible_in_tree ( ) ) {
if ( ! dialog - > is_connected ( SNAME ( " script_created " ) , script_created ) ) {
dialog - > connect ( " script_created " , script_created ) ;
}
} else {
if ( dialog - > is_connected ( SNAME ( " script_created " ) , script_created ) ) {
dialog - > disconnect ( " script_created " , script_created ) ;
}
}
}
}
} break ;
2016-07-04 23:22:28 +00:00
}
}
bool EditorAutoloadSettings : : _autoload_name_is_valid ( const String & p_name , String * r_error ) {
2024-09-21 08:47:19 +00:00
if ( ! p_name . is_valid_unicode_identifier ( ) ) {
2020-05-14 14:41:43 +00:00
if ( r_error ) {
2024-09-21 08:47:19 +00:00
* r_error = TTR ( " Invalid name. " ) + " " + TTR ( " Must be a valid Unicode identifier. " ) ;
2020-05-14 14:41:43 +00:00
}
2016-07-04 23:22:28 +00:00
return false ;
}
2017-01-03 02:03:46 +00:00
if ( ClassDB : : class_exists ( p_name ) ) {
2020-05-14 14:41:43 +00:00
if ( r_error ) {
2021-09-13 20:54:20 +00:00
* r_error = TTR ( " Invalid name. " ) + " " + TTR ( " Must not collide with an existing engine class name. " ) ;
2020-05-14 14:41:43 +00:00
}
2016-07-04 23:22:28 +00:00
return false ;
}
2021-09-13 13:51:29 +00:00
if ( ScriptServer : : is_global_class ( p_name ) ) {
if ( r_error ) {
* r_error = TTR ( " Invalid name. " ) + " \n " + TTR ( " Must not collide with an existing global script class name. " ) ;
}
return false ;
}
2016-07-04 23:22:28 +00:00
for ( int i = 0 ; i < Variant : : VARIANT_MAX ; i + + ) {
if ( Variant : : get_type_name ( Variant : : Type ( i ) ) = = p_name ) {
2020-05-14 14:41:43 +00:00
if ( r_error ) {
2021-09-13 20:54:20 +00:00
* r_error = TTR ( " Invalid name. " ) + " " + TTR ( " Must not collide with an existing built-in type name. " ) ;
2020-05-14 14:41:43 +00:00
}
2016-07-04 23:22:28 +00:00
return false ;
}
}
2020-11-07 22:33:38 +00:00
for ( int i = 0 ; i < CoreConstants : : get_global_constant_count ( ) ; i + + ) {
if ( CoreConstants : : get_global_constant_name ( i ) = = p_name ) {
2020-05-14 14:41:43 +00:00
if ( r_error ) {
2021-09-13 20:54:20 +00:00
* r_error = TTR ( " Invalid name. " ) + " " + TTR ( " Must not collide with an existing global constant name. " ) ;
2020-05-14 14:41:43 +00:00
}
2016-07-04 23:22:28 +00:00
return false ;
}
}
2018-12-15 04:22:04 +00:00
for ( int i = 0 ; i < ScriptServer : : get_language_count ( ) ; i + + ) {
List < String > keywords ;
ScriptServer : : get_language ( i ) - > get_reserved_words ( & keywords ) ;
2021-07-24 13:46:25 +00:00
for ( const String & E : keywords ) {
2021-07-16 03:45:57 +00:00
if ( E = = p_name ) {
2020-05-14 14:41:43 +00:00
if ( r_error ) {
2022-03-09 07:03:03 +00:00
* r_error = TTR ( " Invalid name. " ) + " " + TTR ( " Keyword cannot be used as an Autoload name. " ) ;
2020-05-14 14:41:43 +00:00
}
2018-12-15 04:22:04 +00:00
return false ;
}
}
}
2016-07-04 23:22:28 +00:00
return true ;
}
void EditorAutoloadSettings : : _autoload_add ( ) {
2022-03-10 16:46:31 +00:00
if ( autoload_add_path - > get_text ( ) . is_empty ( ) ) {
ScriptCreateDialog * dialog = FileSystemDock : : get_singleton ( ) - > get_script_create_dialog ( ) ;
String fpath = path ;
if ( ! fpath . ends_with ( " / " ) ) {
fpath = fpath . get_base_dir ( ) ;
}
2023-06-11 16:23:48 +00:00
dialog - > config ( " Node " , fpath . path_join ( vformat ( " %s.gd " , autoload_add_name - > get_text ( ) ) ) , false , false ) ;
2022-03-10 16:46:31 +00:00
dialog - > popup_centered ( ) ;
} else {
if ( autoload_add ( autoload_add_name - > get_text ( ) , autoload_add_path - > get_text ( ) ) ) {
autoload_add_path - > set_text ( " " ) ;
}
2016-07-04 23:22:28 +00:00
2022-03-10 16:46:31 +00:00
autoload_add_name - > set_text ( " " ) ;
add_autoload - > set_disabled ( true ) ;
}
2016-07-04 23:22:28 +00:00
}
void EditorAutoloadSettings : : _autoload_selected ( ) {
TreeItem * ti = tree - > get_selected ( ) ;
2020-05-14 14:41:43 +00:00
if ( ! ti ) {
2016-07-04 23:22:28 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2016-07-04 23:22:28 +00:00
selected_autoload = " autoload/ " + ti - > get_text ( 0 ) ;
}
void EditorAutoloadSettings : : _autoload_edited ( ) {
2020-05-14 14:41:43 +00:00
if ( updating_autoload ) {
2016-07-04 23:22:28 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2016-07-04 23:22:28 +00:00
TreeItem * ti = tree - > get_edited ( ) ;
int column = tree - > get_edited_column ( ) ;
2022-12-23 22:53:16 +00:00
EditorUndoRedoManager * undo_redo = EditorUndoRedoManager : : get_singleton ( ) ;
2016-07-04 23:22:28 +00:00
if ( column = = 0 ) {
String name = ti - > get_text ( 0 ) ;
String old_name = selected_autoload . get_slice ( " / " , 1 ) ;
2020-05-14 14:41:43 +00:00
if ( name = = old_name ) {
2016-07-04 23:22:28 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2016-07-04 23:22:28 +00:00
String error ;
if ( ! _autoload_name_is_valid ( name , & error ) ) {
ti - > set_text ( 0 , old_name ) ;
EditorNode : : get_singleton ( ) - > show_warning ( error ) ;
return ;
}
2017-10-05 18:34:34 +00:00
if ( ProjectSettings : : get_singleton ( ) - > has_setting ( " autoload/ " + name ) ) {
2016-07-04 23:22:28 +00:00
ti - > set_text ( 0 , old_name ) ;
EditorNode : : get_singleton ( ) - > show_warning ( vformat ( TTR ( " Autoload '%s' already exists! " ) , name ) ) ;
return ;
}
updating_autoload = true ;
name = " autoload/ " + name ;
2017-07-19 20:00:46 +00:00
int order = ProjectSettings : : get_singleton ( ) - > get_order ( selected_autoload ) ;
2022-10-18 14:43:37 +00:00
String scr_path = GLOBAL_GET ( selected_autoload ) ;
2016-07-04 23:22:28 +00:00
undo_redo - > create_action ( TTR ( " Rename Autoload " ) ) ;
2022-09-29 09:53:28 +00:00
undo_redo - > add_do_property ( ProjectSettings : : get_singleton ( ) , name , scr_path ) ;
2017-07-19 20:00:46 +00:00
undo_redo - > add_do_method ( ProjectSettings : : get_singleton ( ) , " set_order " , name , order ) ;
undo_redo - > add_do_method ( ProjectSettings : : get_singleton ( ) , " clear " , selected_autoload ) ;
2016-07-04 23:22:28 +00:00
2022-09-29 09:53:28 +00:00
undo_redo - > add_undo_property ( ProjectSettings : : get_singleton ( ) , selected_autoload , scr_path ) ;
2017-07-19 20:00:46 +00:00
undo_redo - > add_undo_method ( ProjectSettings : : get_singleton ( ) , " set_order " , selected_autoload , order ) ;
undo_redo - > add_undo_method ( ProjectSettings : : get_singleton ( ) , " clear " , name ) ;
2016-07-04 23:22:28 +00:00
2024-05-13 14:56:03 +00:00
undo_redo - > add_do_method ( this , CoreStringName ( call_deferred ) , " update_autoload " ) ;
undo_redo - > add_undo_method ( this , CoreStringName ( call_deferred ) , " update_autoload " ) ;
2016-07-04 23:22:28 +00:00
undo_redo - > add_do_method ( this , " emit_signal " , autoload_changed ) ;
undo_redo - > add_undo_method ( this , " emit_signal " , autoload_changed ) ;
undo_redo - > commit_action ( ) ;
selected_autoload = name ;
} else if ( column = = 2 ) {
updating_autoload = true ;
bool checked = ti - > is_checked ( 2 ) ;
String base = " autoload/ " + ti - > get_text ( 0 ) ;
2017-07-19 20:00:46 +00:00
int order = ProjectSettings : : get_singleton ( ) - > get_order ( base ) ;
2022-10-18 14:43:37 +00:00
String scr_path = GLOBAL_GET ( base ) ;
2016-07-04 23:22:28 +00:00
2022-09-29 09:53:28 +00:00
if ( scr_path . begins_with ( " * " ) ) {
scr_path = scr_path . substr ( 1 , scr_path . length ( ) ) ;
2020-05-14 14:41:43 +00:00
}
2016-07-04 23:22:28 +00:00
2018-10-14 05:05:53 +00:00
// Singleton autoloads are represented with a leading "*" in their path.
2020-05-14 14:41:43 +00:00
if ( checked ) {
2022-09-29 09:53:28 +00:00
scr_path = " * " + scr_path ;
2020-05-14 14:41:43 +00:00
}
2016-07-04 23:22:28 +00:00
2022-03-09 07:03:03 +00:00
undo_redo - > create_action ( TTR ( " Toggle Autoload Globals " ) ) ;
2016-07-04 23:22:28 +00:00
2022-09-29 09:53:28 +00:00
undo_redo - > add_do_property ( ProjectSettings : : get_singleton ( ) , base , scr_path ) ;
2022-10-18 14:43:37 +00:00
undo_redo - > add_undo_property ( ProjectSettings : : get_singleton ( ) , base , GLOBAL_GET ( base ) ) ;
2016-07-04 23:22:28 +00:00
2017-07-19 20:00:46 +00:00
undo_redo - > add_do_method ( ProjectSettings : : get_singleton ( ) , " set_order " , base , order ) ;
undo_redo - > add_undo_method ( ProjectSettings : : get_singleton ( ) , " set_order " , base , order ) ;
2016-07-04 23:22:28 +00:00
2024-05-13 14:56:03 +00:00
undo_redo - > add_do_method ( this , CoreStringName ( call_deferred ) , " update_autoload " ) ;
undo_redo - > add_undo_method ( this , CoreStringName ( call_deferred ) , " update_autoload " ) ;
2016-07-04 23:22:28 +00:00
undo_redo - > add_do_method ( this , " emit_signal " , autoload_changed ) ;
undo_redo - > add_undo_method ( this , " emit_signal " , autoload_changed ) ;
undo_redo - > commit_action ( ) ;
}
updating_autoload = false ;
}
2021-09-18 07:33:18 +00:00
void EditorAutoloadSettings : : _autoload_button_pressed ( Object * p_item , int p_column , int p_button , MouseButton p_mouse_button ) {
if ( p_mouse_button ! = MouseButton : : LEFT ) {
return ;
}
2017-08-24 20:58:51 +00:00
TreeItem * ti = Object : : cast_to < TreeItem > ( p_item ) ;
2016-07-04 23:22:28 +00:00
String name = " autoload/ " + ti - > get_text ( 0 ) ;
2022-12-23 22:53:16 +00:00
EditorUndoRedoManager * undo_redo = EditorUndoRedoManager : : get_singleton ( ) ;
2016-07-04 23:22:28 +00:00
switch ( p_button ) {
2018-01-02 06:24:02 +00:00
case BUTTON_OPEN : {
_autoload_open ( ti - > get_text ( 1 ) ) ;
} break ;
2016-07-04 23:22:28 +00:00
case BUTTON_MOVE_UP :
case BUTTON_MOVE_DOWN : {
2020-04-01 23:20:12 +00:00
TreeItem * swap = nullptr ;
2016-07-04 23:22:28 +00:00
if ( p_button = = BUTTON_MOVE_UP ) {
swap = ti - > get_prev ( ) ;
} else {
swap = ti - > get_next ( ) ;
}
2020-05-14 14:41:43 +00:00
if ( ! swap ) {
2016-07-04 23:22:28 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2016-07-04 23:22:28 +00:00
String swap_name = " autoload/ " + swap - > get_text ( 0 ) ;
2017-07-19 20:00:46 +00:00
int order = ProjectSettings : : get_singleton ( ) - > get_order ( name ) ;
int swap_order = ProjectSettings : : get_singleton ( ) - > get_order ( swap_name ) ;
2016-07-04 23:22:28 +00:00
undo_redo - > create_action ( TTR ( " Move Autoload " ) ) ;
2017-07-19 20:00:46 +00:00
undo_redo - > add_do_method ( ProjectSettings : : get_singleton ( ) , " set_order " , name , swap_order ) ;
undo_redo - > add_undo_method ( ProjectSettings : : get_singleton ( ) , " set_order " , name , order ) ;
2016-07-04 23:22:28 +00:00
2017-07-19 20:00:46 +00:00
undo_redo - > add_do_method ( ProjectSettings : : get_singleton ( ) , " set_order " , swap_name , order ) ;
undo_redo - > add_undo_method ( ProjectSettings : : get_singleton ( ) , " set_order " , swap_name , swap_order ) ;
2016-07-04 23:22:28 +00:00
undo_redo - > add_do_method ( this , " update_autoload " ) ;
undo_redo - > add_undo_method ( this , " update_autoload " ) ;
undo_redo - > add_do_method ( this , " emit_signal " , autoload_changed ) ;
undo_redo - > add_undo_method ( this , " emit_signal " , autoload_changed ) ;
undo_redo - > commit_action ( ) ;
} break ;
case BUTTON_DELETE : {
2017-07-19 20:00:46 +00:00
int order = ProjectSettings : : get_singleton ( ) - > get_order ( name ) ;
2016-07-04 23:22:28 +00:00
undo_redo - > create_action ( TTR ( " Remove Autoload " ) ) ;
2017-07-19 20:00:46 +00:00
undo_redo - > add_do_property ( ProjectSettings : : get_singleton ( ) , name , Variant ( ) ) ;
2016-07-04 23:22:28 +00:00
2022-10-18 14:43:37 +00:00
undo_redo - > add_undo_property ( ProjectSettings : : get_singleton ( ) , name , GLOBAL_GET ( name ) ) ;
2023-07-23 17:19:40 +00:00
undo_redo - > add_undo_method ( ProjectSettings : : get_singleton ( ) , " set_order " , name , order ) ;
2016-07-04 23:22:28 +00:00
undo_redo - > add_do_method ( this , " update_autoload " ) ;
undo_redo - > add_undo_method ( this , " update_autoload " ) ;
undo_redo - > add_do_method ( this , " emit_signal " , autoload_changed ) ;
undo_redo - > add_undo_method ( this , " emit_signal " , autoload_changed ) ;
undo_redo - > commit_action ( ) ;
} break ;
}
}
2018-01-02 06:24:02 +00:00
void EditorAutoloadSettings : : _autoload_activated ( ) {
TreeItem * ti = tree - > get_selected ( ) ;
2020-05-14 14:41:43 +00:00
if ( ! ti ) {
2018-01-02 06:24:02 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2018-01-02 06:24:02 +00:00
_autoload_open ( ti - > get_text ( 1 ) ) ;
}
void EditorAutoloadSettings : : _autoload_open ( const String & fpath ) {
if ( ResourceLoader : : get_resource_type ( fpath ) = = " PackedScene " ) {
EditorNode : : get_singleton ( ) - > open_request ( fpath ) ;
} else {
EditorNode : : get_singleton ( ) - > load_resource ( fpath ) ;
}
ProjectSettingsEditor : : get_singleton ( ) - > hide ( ) ;
}
2018-12-15 04:22:04 +00:00
2016-07-04 23:22:28 +00:00
void EditorAutoloadSettings : : _autoload_file_callback ( const String & p_path ) {
2019-11-27 23:07:01 +00:00
// Convert the file name to PascalCase, which is the convention for classes in GDScript.
2022-08-30 09:36:24 +00:00
const String class_name = p_path . get_file ( ) . get_basename ( ) . to_pascal_case ( ) ;
2019-11-27 23:07:01 +00:00
// If the name collides with a built-in class, prefix the name to make it possible to add without having to edit the name.
// The prefix is subjective, but it provides better UX than leaving the Add button disabled :)
const String prefix = ClassDB : : class_exists ( class_name ) ? " Global " : " " ;
autoload_add_name - > set_text ( prefix + class_name ) ;
add_autoload - > set_disabled ( false ) ;
}
2024-02-15 16:25:58 +00:00
void EditorAutoloadSettings : : _autoload_text_submitted ( const String & p_name ) {
2021-12-09 09:42:46 +00:00
if ( ! autoload_add_path - > get_text ( ) . is_empty ( ) & & _autoload_name_is_valid ( p_name , nullptr ) ) {
2019-11-27 23:07:01 +00:00
_autoload_add ( ) ;
}
}
2024-02-15 16:25:58 +00:00
void EditorAutoloadSettings : : _autoload_path_text_changed ( const String & p_path ) {
2022-03-10 16:46:31 +00:00
add_autoload - > set_disabled ( ! _autoload_name_is_valid ( autoload_add_name - > get_text ( ) , nullptr ) ) ;
2019-11-27 23:07:01 +00:00
}
2024-02-15 16:25:58 +00:00
void EditorAutoloadSettings : : _autoload_text_changed ( const String & p_name ) {
2021-09-13 20:54:20 +00:00
String error_string ;
bool is_name_valid = _autoload_name_is_valid ( p_name , & error_string ) ;
2022-03-10 16:46:31 +00:00
add_autoload - > set_disabled ( ! is_name_valid ) ;
2021-09-13 20:54:20 +00:00
error_message - > set_text ( error_string ) ;
2021-12-09 09:42:46 +00:00
error_message - > set_visible ( ! autoload_add_name - > get_text ( ) . is_empty ( ) & & ! is_name_valid ) ;
2016-07-04 23:22:28 +00:00
}
2018-05-22 16:26:13 +00:00
Node * EditorAutoloadSettings : : _create_autoload ( const String & p_path ) {
2020-04-01 23:20:12 +00:00
Node * n = nullptr ;
2022-11-23 23:13:13 +00:00
if ( ResourceLoader : : get_resource_type ( p_path ) = = " PackedScene " ) {
// Cache the scene reference before loading it (for cyclic references)
Ref < PackedScene > scn ;
scn . instantiate ( ) ;
scn - > set_path ( p_path ) ;
scn - > reload_from_file ( ) ;
2023-11-23 15:19:24 +00:00
ERR_FAIL_COND_V_MSG ( ! scn . is_valid ( ) , nullptr , vformat ( " Failed to create an autoload, can't load from path: %s. " , p_path ) ) ;
2022-11-23 23:13:13 +00:00
if ( scn . is_valid ( ) ) {
n = scn - > instantiate ( ) ;
}
} else {
Ref < Resource > res = ResourceLoader : : load ( p_path ) ;
2023-11-23 15:19:24 +00:00
ERR_FAIL_COND_V_MSG ( res . is_null ( ) , nullptr , vformat ( " Failed to create an autoload, can't load from path: %s. " , p_path ) ) ;
2018-05-22 16:26:13 +00:00
2022-11-23 23:13:13 +00:00
Ref < Script > scr = res ;
if ( scr . is_valid ( ) ) {
2024-05-24 05:30:16 +00:00
ERR_FAIL_COND_V_MSG ( ! scr - > is_valid ( ) , nullptr , vformat ( " Failed to create an autoload, script '%s' is not compiling. " , p_path ) ) ;
2022-11-23 23:13:13 +00:00
StringName ibt = scr - > get_instance_base_type ( ) ;
bool valid_type = ClassDB : : is_parent_class ( ibt , " Node " ) ;
2023-11-23 15:19:24 +00:00
ERR_FAIL_COND_V_MSG ( ! valid_type , nullptr , vformat ( " Failed to create an autoload, script '%s' does not inherit from 'Node'. " , p_path ) ) ;
2018-05-22 16:26:13 +00:00
2022-11-23 23:13:13 +00:00
Object * obj = ClassDB : : instantiate ( ibt ) ;
2023-11-23 15:19:24 +00:00
ERR_FAIL_NULL_V_MSG ( obj , nullptr , vformat ( " Failed to create an autoload, cannot instantiate '%s'. " , ibt ) ) ;
2022-11-23 23:13:13 +00:00
n = Object : : cast_to < Node > ( obj ) ;
n - > set_script ( scr ) ;
}
2018-05-22 16:26:13 +00:00
}
2023-11-23 15:19:24 +00:00
ERR_FAIL_NULL_V_MSG ( n , nullptr , vformat ( " Failed to create an autoload, path is not pointing to a scene or a script: %s. " , p_path ) ) ;
2018-05-22 16:26:13 +00:00
return n ;
}
2024-05-24 05:30:16 +00:00
void EditorAutoloadSettings : : init_autoloads ( ) {
for ( AutoloadInfo & info : autoload_cache ) {
info . node = _create_autoload ( info . path ) ;
if ( info . node ) {
Ref < Script > scr = info . node - > get_script ( ) ;
info . in_editor = scr . is_valid ( ) & & scr - > is_tool ( ) ;
info . node - > set_name ( info . name ) ;
}
if ( info . is_singleton ) {
for ( int i = 0 ; i < ScriptServer : : get_language_count ( ) ; i + + ) {
ScriptServer : : get_language ( i ) - > add_named_global_constant ( info . name , info . node ) ;
}
}
if ( ! info . is_singleton & & ! info . in_editor & & info . node ! = nullptr ) {
memdelete ( info . node ) ;
info . node = nullptr ;
}
}
for ( const AutoloadInfo & info : autoload_cache ) {
if ( info . node & & info . in_editor ) {
2024-07-26 14:29:38 +00:00
// It's important to add the node without deferring because code in plugins or tool scripts
// could use the autoload node when they are enabled.
get_tree ( ) - > get_root ( ) - > add_child ( info . node ) ;
2024-05-24 05:30:16 +00:00
}
}
}
2016-07-04 23:22:28 +00:00
void EditorAutoloadSettings : : update_autoload ( ) {
2020-05-14 14:41:43 +00:00
if ( updating_autoload ) {
2016-07-04 23:22:28 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2016-07-04 23:22:28 +00:00
updating_autoload = true ;
2022-05-13 13:04:37 +00:00
HashMap < String , AutoloadInfo > to_remove ;
2022-03-09 07:03:03 +00:00
List < AutoloadInfo * > to_add ;
2018-05-01 14:06:23 +00:00
2022-03-09 07:03:03 +00:00
for ( const AutoloadInfo & info : autoload_cache ) {
2018-05-22 16:26:13 +00:00
to_remove . insert ( info . name , info ) ;
2018-05-01 14:06:23 +00:00
}
2016-07-04 23:22:28 +00:00
autoload_cache . clear ( ) ;
tree - > clear ( ) ;
TreeItem * root = tree - > create_item ( ) ;
List < PropertyInfo > props ;
2017-07-19 20:00:46 +00:00
ProjectSettings : : get_singleton ( ) - > get_property_list ( & props ) ;
2016-07-04 23:22:28 +00:00
2021-07-24 13:46:25 +00:00
for ( const PropertyInfo & pi : props ) {
2020-05-14 14:41:43 +00:00
if ( ! pi . name . begins_with ( " autoload/ " ) ) {
2016-07-04 23:22:28 +00:00
continue ;
2020-05-14 14:41:43 +00:00
}
2016-07-04 23:22:28 +00:00
String name = pi . name . get_slice ( " / " , 1 ) ;
2022-10-18 14:43:37 +00:00
String scr_path = GLOBAL_GET ( pi . name ) ;
2016-07-04 23:22:28 +00:00
2020-12-15 12:04:21 +00:00
if ( name . is_empty ( ) ) {
2016-07-04 23:22:28 +00:00
continue ;
2020-05-14 14:41:43 +00:00
}
2016-07-04 23:22:28 +00:00
2022-03-09 07:03:03 +00:00
AutoloadInfo info ;
2022-09-29 09:53:28 +00:00
info . is_singleton = scr_path . begins_with ( " * " ) ;
2016-07-04 23:22:28 +00:00
2018-05-01 14:06:23 +00:00
if ( info . is_singleton ) {
2022-09-29 09:53:28 +00:00
scr_path = scr_path . substr ( 1 , scr_path . length ( ) ) ;
2018-05-01 14:06:23 +00:00
}
2016-07-04 23:22:28 +00:00
2018-05-01 14:06:23 +00:00
info . name = name ;
2022-09-29 09:53:28 +00:00
info . path = scr_path ;
2018-05-01 14:06:23 +00:00
info . order = ProjectSettings : : get_singleton ( ) - > get_order ( pi . name ) ;
2016-07-04 23:22:28 +00:00
2018-05-22 16:26:13 +00:00
bool need_to_add = true ;
if ( to_remove . has ( name ) ) {
2022-03-09 07:03:03 +00:00
AutoloadInfo & old_info = to_remove [ name ] ;
2018-05-01 14:06:23 +00:00
if ( old_info . path = = info . path ) {
2018-05-22 16:26:13 +00:00
// Still the same resource, check status
info . node = old_info . node ;
if ( info . node ) {
Ref < Script > scr = info . node - > get_script ( ) ;
info . in_editor = scr . is_valid ( ) & & scr - > is_tool ( ) ;
if ( info . is_singleton = = old_info . is_singleton & & info . in_editor = = old_info . in_editor ) {
to_remove . erase ( name ) ;
need_to_add = false ;
2018-05-01 14:06:23 +00:00
} else {
2020-04-01 23:20:12 +00:00
info . node = nullptr ;
2018-05-01 14:06:23 +00:00
}
}
}
2016-07-04 23:22:28 +00:00
}
2018-05-01 14:06:23 +00:00
autoload_cache . push_back ( info ) ;
2018-05-22 16:26:13 +00:00
if ( need_to_add ) {
to_add . push_back ( & ( autoload_cache . back ( ) - > get ( ) ) ) ;
}
2016-07-04 23:22:28 +00:00
TreeItem * item = tree - > create_item ( root ) ;
item - > set_text ( 0 , name ) ;
item - > set_editable ( 0 , true ) ;
2022-09-29 09:53:28 +00:00
item - > set_text ( 1 , scr_path ) ;
2018-01-02 06:24:02 +00:00
item - > set_selectable ( 1 , true ) ;
2016-07-04 23:22:28 +00:00
item - > set_cell_mode ( 2 , TreeItem : : CELL_MODE_CHECK ) ;
item - > set_editable ( 2 , true ) ;
item - > set_text ( 2 , TTR ( " Enable " ) ) ;
2018-05-01 14:06:23 +00:00
item - > set_checked ( 2 , info . is_singleton ) ;
2023-08-13 00:33:39 +00:00
item - > add_button ( 3 , get_editor_theme_icon ( SNAME ( " Load " ) ) , BUTTON_OPEN ) ;
item - > add_button ( 3 , get_editor_theme_icon ( SNAME ( " MoveUp " ) ) , BUTTON_MOVE_UP ) ;
item - > add_button ( 3 , get_editor_theme_icon ( SNAME ( " MoveDown " ) ) , BUTTON_MOVE_DOWN ) ;
item - > add_button ( 3 , get_editor_theme_icon ( SNAME ( " Remove " ) ) , BUTTON_DELETE ) ;
2016-07-04 23:22:28 +00:00
item - > set_selectable ( 3 , false ) ;
}
2018-05-22 16:26:13 +00:00
// Remove deleted/changed autoloads
2022-03-09 07:03:03 +00:00
for ( KeyValue < String , AutoloadInfo > & E : to_remove ) {
AutoloadInfo & info = E . value ;
2018-05-22 16:26:13 +00:00
if ( info . is_singleton ) {
for ( int i = 0 ; i < ScriptServer : : get_language_count ( ) ; i + + ) {
ScriptServer : : get_language ( i ) - > remove_named_global_constant ( info . name ) ;
}
}
if ( info . in_editor ) {
ERR_CONTINUE ( ! info . node ) ;
2023-12-18 14:46:56 +00:00
callable_mp ( ( Node * ) get_tree ( ) - > get_root ( ) , & Node : : remove_child ) . call_deferred ( info . node ) ;
2018-05-22 16:26:13 +00:00
}
2018-05-01 14:06:23 +00:00
2018-05-22 16:26:13 +00:00
if ( info . node ) {
2022-10-24 21:07:02 +00:00
info . node - > queue_free ( ) ;
2020-04-01 23:20:12 +00:00
info . node = nullptr ;
2018-05-01 14:06:23 +00:00
}
}
2018-05-22 16:26:13 +00:00
// Load new/changed autoloads
2018-05-01 14:06:23 +00:00
List < Node * > nodes_to_add ;
2022-03-09 07:03:03 +00:00
for ( AutoloadInfo * info : to_add ) {
2018-05-22 16:26:13 +00:00
info - > node = _create_autoload ( info - > path ) ;
2018-05-01 14:06:23 +00:00
2018-05-22 16:26:13 +00:00
ERR_CONTINUE ( ! info - > node ) ;
info - > node - > set_name ( info - > name ) ;
2018-05-01 14:06:23 +00:00
2018-05-22 16:26:13 +00:00
Ref < Script > scr = info - > node - > get_script ( ) ;
info - > in_editor = scr . is_valid ( ) & & scr - > is_tool ( ) ;
2018-05-01 14:06:23 +00:00
2018-05-22 16:26:13 +00:00
if ( info - > in_editor ) {
//defer so references are all valid on _ready()
nodes_to_add . push_back ( info - > node ) ;
}
if ( info - > is_singleton ) {
2018-05-01 14:06:23 +00:00
for ( int i = 0 ; i < ScriptServer : : get_language_count ( ) ; i + + ) {
2018-05-22 16:26:13 +00:00
ScriptServer : : get_language ( i ) - > add_named_global_constant ( info - > name , info - > node ) ;
2018-05-01 14:06:23 +00:00
}
}
2018-05-22 16:26:13 +00:00
if ( ! info - > in_editor & & ! info - > is_singleton ) {
// No reason to keep this node
memdelete ( info - > node ) ;
2020-04-01 23:20:12 +00:00
info - > node = nullptr ;
2018-05-22 16:26:13 +00:00
}
2018-05-01 14:06:23 +00:00
}
2021-07-16 03:45:57 +00:00
for ( Node * E : nodes_to_add ) {
get_tree ( ) - > get_root ( ) - > add_child ( E ) ;
2018-05-01 14:06:23 +00:00
}
2016-07-04 23:22:28 +00:00
updating_autoload = false ;
}
2022-03-10 16:46:31 +00:00
void EditorAutoloadSettings : : _script_created ( Ref < Script > p_script ) {
FileSystemDock : : get_singleton ( ) - > get_script_create_dialog ( ) - > hide ( ) ;
path = p_script - > get_path ( ) . get_base_dir ( ) ;
autoload_add_path - > set_text ( p_script - > get_path ( ) ) ;
2022-08-30 09:36:24 +00:00
autoload_add_name - > set_text ( p_script - > get_path ( ) . get_file ( ) . get_basename ( ) . to_pascal_case ( ) ) ;
2022-03-10 16:46:31 +00:00
_autoload_add ( ) ;
}
2023-08-30 18:11:21 +00:00
LineEdit * EditorAutoloadSettings : : get_path_box ( ) const {
return autoload_add_path ;
}
2016-07-04 23:22:28 +00:00
Variant EditorAutoloadSettings : : get_drag_data_fw ( const Point2 & p_point , Control * p_control ) {
2020-05-14 14:41:43 +00:00
if ( autoload_cache . size ( ) < = 1 ) {
2016-07-04 23:22:28 +00:00
return false ;
2020-05-14 14:41:43 +00:00
}
2016-07-04 23:22:28 +00:00
2020-02-17 21:06:54 +00:00
PackedStringArray autoloads ;
2016-07-04 23:22:28 +00:00
2020-04-01 23:20:12 +00:00
TreeItem * next = tree - > get_next_selected ( nullptr ) ;
2016-07-04 23:22:28 +00:00
while ( next ) {
autoloads . push_back ( next - > get_text ( 0 ) ) ;
next = tree - > get_next_selected ( next ) ;
}
2020-05-14 14:41:43 +00:00
if ( autoloads . size ( ) = = 0 | | autoloads . size ( ) = = autoload_cache . size ( ) ) {
2016-07-04 23:22:28 +00:00
return Variant ( ) ;
2020-05-14 14:41:43 +00:00
}
2016-07-04 23:22:28 +00:00
VBoxContainer * preview = memnew ( VBoxContainer ) ;
int max_size = MIN ( PREVIEW_LIST_MAX_SIZE , autoloads . size ( ) ) ;
for ( int i = 0 ; i < max_size ; i + + ) {
Label * label = memnew ( Label ( autoloads [ i ] ) ) ;
2016-10-03 19:33:42 +00:00
label - > set_self_modulate ( Color ( 1 , 1 , 1 , Math : : lerp ( 1 , 0 , float ( i ) / PREVIEW_LIST_MAX_SIZE ) ) ) ;
2024-09-19 00:14:00 +00:00
label - > set_auto_translate_mode ( AUTO_TRANSLATE_MODE_DISABLED ) ;
2016-07-04 23:22:28 +00:00
preview - > add_child ( label ) ;
}
tree - > set_drop_mode_flags ( Tree : : DROP_MODE_INBETWEEN ) ;
tree - > set_drag_preview ( preview ) ;
Dictionary drop_data ;
drop_data [ " type " ] = " autoload " ;
drop_data [ " autoloads " ] = autoloads ;
return drop_data ;
}
bool EditorAutoloadSettings : : can_drop_data_fw ( const Point2 & p_point , const Variant & p_data , Control * p_control ) const {
2020-05-14 14:41:43 +00:00
if ( updating_autoload ) {
2016-07-04 23:22:28 +00:00
return false ;
2020-05-14 14:41:43 +00:00
}
2016-07-04 23:22:28 +00:00
Dictionary drop_data = p_data ;
2020-05-14 14:41:43 +00:00
if ( ! drop_data . has ( " type " ) ) {
2016-07-04 23:22:28 +00:00
return false ;
2020-05-14 14:41:43 +00:00
}
2016-07-04 23:22:28 +00:00
if ( drop_data . has ( " type " ) ) {
2017-09-10 13:37:49 +00:00
TreeItem * ti = tree - > get_item_at_position ( p_point ) ;
2016-07-04 23:22:28 +00:00
2020-05-14 14:41:43 +00:00
if ( ! ti ) {
2016-07-04 23:22:28 +00:00
return false ;
2020-05-14 14:41:43 +00:00
}
2016-07-04 23:22:28 +00:00
2017-09-10 13:37:49 +00:00
int section = tree - > get_drop_section_at_position ( p_point ) ;
2016-07-04 23:22:28 +00:00
2019-06-26 13:08:25 +00:00
return section > = - 1 ;
2016-07-04 23:22:28 +00:00
}
return false ;
}
void EditorAutoloadSettings : : drop_data_fw ( const Point2 & p_point , const Variant & p_data , Control * p_control ) {
2017-09-10 13:37:49 +00:00
TreeItem * ti = tree - > get_item_at_position ( p_point ) ;
2016-07-04 23:22:28 +00:00
2020-05-14 14:41:43 +00:00
if ( ! ti ) {
2016-07-04 23:22:28 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2016-07-04 23:22:28 +00:00
2017-09-10 13:37:49 +00:00
int section = tree - > get_drop_section_at_position ( p_point ) ;
2016-07-04 23:22:28 +00:00
2020-05-14 14:41:43 +00:00
if ( section < - 1 ) {
2016-07-04 23:22:28 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2016-07-04 23:22:28 +00:00
String name ;
bool move_to_back = false ;
if ( section < 0 ) {
name = ti - > get_text ( 0 ) ;
} else if ( ti - > get_next ( ) ) {
name = ti - > get_next ( ) - > get_text ( 0 ) ;
} else {
name = ti - > get_text ( 0 ) ;
move_to_back = true ;
}
2017-07-19 20:00:46 +00:00
int order = ProjectSettings : : get_singleton ( ) - > get_order ( " autoload/ " + name ) ;
2016-07-04 23:22:28 +00:00
2022-03-09 07:03:03 +00:00
AutoloadInfo aux ;
List < AutoloadInfo > : : Element * E = nullptr ;
2016-07-04 23:22:28 +00:00
if ( ! move_to_back ) {
aux . order = order ;
E = autoload_cache . find ( aux ) ;
}
Dictionary drop_data = p_data ;
2020-02-17 21:06:54 +00:00
PackedStringArray autoloads = drop_data [ " autoloads " ] ;
2016-07-04 23:22:28 +00:00
Vector < int > orders ;
orders . resize ( autoload_cache . size ( ) ) ;
for ( int i = 0 ; i < autoloads . size ( ) ; i + + ) {
2017-07-19 20:00:46 +00:00
aux . order = ProjectSettings : : get_singleton ( ) - > get_order ( " autoload/ " + autoloads [ i ] ) ;
2016-07-04 23:22:28 +00:00
2022-03-09 07:03:03 +00:00
List < AutoloadInfo > : : Element * I = autoload_cache . find ( aux ) ;
2016-07-04 23:22:28 +00:00
if ( move_to_back ) {
autoload_cache . move_to_back ( I ) ;
} else if ( E ! = I ) {
autoload_cache . move_before ( I , E ) ;
} else if ( E - > next ( ) ) {
E = E - > next ( ) ;
} else {
break ;
}
}
int i = 0 ;
2022-03-09 07:03:03 +00:00
for ( const AutoloadInfo & F : autoload_cache ) {
2021-07-16 03:45:57 +00:00
orders . write [ i + + ] = F . order ;
2016-07-04 23:22:28 +00:00
}
orders . sort ( ) ;
2022-12-23 22:53:16 +00:00
EditorUndoRedoManager * undo_redo = EditorUndoRedoManager : : get_singleton ( ) ;
2016-07-04 23:22:28 +00:00
undo_redo - > create_action ( TTR ( " Rearrange Autoloads " ) ) ;
i = 0 ;
2022-03-09 07:03:03 +00:00
for ( const AutoloadInfo & F : autoload_cache ) {
2021-07-16 03:45:57 +00:00
undo_redo - > add_do_method ( ProjectSettings : : get_singleton ( ) , " set_order " , " autoload/ " + F . name , orders [ i + + ] ) ;
undo_redo - > add_undo_method ( ProjectSettings : : get_singleton ( ) , " set_order " , " autoload/ " + F . name , F . order ) ;
2016-07-04 23:22:28 +00:00
}
orders . clear ( ) ;
undo_redo - > add_do_method ( this , " update_autoload " ) ;
undo_redo - > add_undo_method ( this , " update_autoload " ) ;
undo_redo - > add_do_method ( this , " emit_signal " , autoload_changed ) ;
undo_redo - > add_undo_method ( this , " emit_signal " , autoload_changed ) ;
undo_redo - > commit_action ( ) ;
}
2018-12-15 04:22:04 +00:00
bool EditorAutoloadSettings : : autoload_add ( const String & p_name , const String & p_path ) {
2018-02-14 04:31:38 +00:00
String name = p_name ;
String error ;
if ( ! _autoload_name_is_valid ( name , & error ) ) {
2022-03-09 07:03:03 +00:00
EditorNode : : get_singleton ( ) - > show_warning ( TTR ( " Can't add Autoload: " ) + " \n " + error ) ;
2018-12-15 04:22:04 +00:00
return false ;
2018-02-14 04:31:38 +00:00
}
2022-09-29 09:53:28 +00:00
if ( ! FileAccess : : exists ( p_path ) ) {
2024-06-18 07:49:26 +00:00
EditorNode : : get_singleton ( ) - > show_warning ( TTR ( " Can't add Autoload: " ) + " \n " + vformat ( TTR ( " %s is an invalid path. File does not exist. " ) , p_path ) ) ;
2018-12-15 04:22:04 +00:00
return false ;
2018-02-14 04:31:38 +00:00
}
2022-09-29 09:53:28 +00:00
if ( ! p_path . begins_with ( " res:// " ) ) {
2024-06-18 07:49:26 +00:00
EditorNode : : get_singleton ( ) - > show_warning ( TTR ( " Can't add Autoload: " ) + " \n " + vformat ( TTR ( " %s is an invalid path. Not in resource path (res://). " ) , p_path ) ) ;
2018-12-15 04:22:04 +00:00
return false ;
2018-02-14 04:31:38 +00:00
}
name = " autoload/ " + name ;
2022-12-23 22:53:16 +00:00
EditorUndoRedoManager * undo_redo = EditorUndoRedoManager : : get_singleton ( ) ;
2018-02-14 04:31:38 +00:00
2022-03-09 07:03:03 +00:00
undo_redo - > create_action ( TTR ( " Add Autoload " ) ) ;
2018-10-14 05:05:53 +00:00
// Singleton autoloads are represented with a leading "*" in their path.
2022-09-29 09:53:28 +00:00
undo_redo - > add_do_property ( ProjectSettings : : get_singleton ( ) , name , " * " + p_path ) ;
2018-02-14 04:31:38 +00:00
if ( ProjectSettings : : get_singleton ( ) - > has_setting ( name ) ) {
2022-10-18 14:43:37 +00:00
undo_redo - > add_undo_property ( ProjectSettings : : get_singleton ( ) , name , GLOBAL_GET ( name ) ) ;
2018-02-14 04:31:38 +00:00
} else {
undo_redo - > add_undo_property ( ProjectSettings : : get_singleton ( ) , name , Variant ( ) ) ;
}
undo_redo - > add_do_method ( this , " update_autoload " ) ;
undo_redo - > add_undo_method ( this , " update_autoload " ) ;
undo_redo - > add_do_method ( this , " emit_signal " , autoload_changed ) ;
undo_redo - > add_undo_method ( this , " emit_signal " , autoload_changed ) ;
undo_redo - > commit_action ( ) ;
2018-12-15 04:22:04 +00:00
return true ;
2018-02-14 04:31:38 +00:00
}
void EditorAutoloadSettings : : autoload_remove ( const String & p_name ) {
String name = " autoload/ " + p_name ;
2022-12-23 22:53:16 +00:00
EditorUndoRedoManager * undo_redo = EditorUndoRedoManager : : get_singleton ( ) ;
2018-02-14 04:31:38 +00:00
int order = ProjectSettings : : get_singleton ( ) - > get_order ( name ) ;
undo_redo - > create_action ( TTR ( " Remove Autoload " ) ) ;
undo_redo - > add_do_property ( ProjectSettings : : get_singleton ( ) , name , Variant ( ) ) ;
2022-10-18 14:43:37 +00:00
undo_redo - > add_undo_property ( ProjectSettings : : get_singleton ( ) , name , GLOBAL_GET ( name ) ) ;
2023-07-23 17:19:40 +00:00
undo_redo - > add_undo_method ( ProjectSettings : : get_singleton ( ) , " set_order " , name , order ) ;
2018-02-14 04:31:38 +00:00
undo_redo - > add_do_method ( this , " update_autoload " ) ;
undo_redo - > add_undo_method ( this , " update_autoload " ) ;
undo_redo - > add_do_method ( this , " emit_signal " , autoload_changed ) ;
undo_redo - > add_undo_method ( this , " emit_signal " , autoload_changed ) ;
undo_redo - > commit_action ( ) ;
}
2016-07-04 23:22:28 +00:00
void EditorAutoloadSettings : : _bind_methods ( ) {
2017-01-03 02:03:46 +00:00
ClassDB : : bind_method ( " update_autoload " , & EditorAutoloadSettings : : update_autoload ) ;
2018-02-14 04:31:38 +00:00
ClassDB : : bind_method ( " autoload_add " , & EditorAutoloadSettings : : autoload_add ) ;
ClassDB : : bind_method ( " autoload_remove " , & EditorAutoloadSettings : : autoload_remove ) ;
2016-07-04 23:22:28 +00:00
ADD_SIGNAL ( MethodInfo ( " autoload_changed " ) ) ;
}
EditorAutoloadSettings : : EditorAutoloadSettings ( ) {
2022-06-08 15:52:19 +00:00
ProjectSettings : : get_singleton ( ) - > add_hidden_prefix ( " autoload/ " ) ;
2018-05-01 14:06:23 +00:00
// Make first cache
List < PropertyInfo > props ;
ProjectSettings : : get_singleton ( ) - > get_property_list ( & props ) ;
2021-07-24 13:46:25 +00:00
for ( const PropertyInfo & pi : props ) {
2020-05-14 14:41:43 +00:00
if ( ! pi . name . begins_with ( " autoload/ " ) ) {
2018-05-01 14:06:23 +00:00
continue ;
2020-05-14 14:41:43 +00:00
}
2018-05-01 14:06:23 +00:00
String name = pi . name . get_slice ( " / " , 1 ) ;
2022-10-18 14:43:37 +00:00
String scr_path = GLOBAL_GET ( pi . name ) ;
2018-05-01 14:06:23 +00:00
2020-12-15 12:04:21 +00:00
if ( name . is_empty ( ) ) {
2018-05-01 14:06:23 +00:00
continue ;
2020-05-14 14:41:43 +00:00
}
2018-05-01 14:06:23 +00:00
2022-03-09 07:03:03 +00:00
AutoloadInfo info ;
2022-09-29 09:53:28 +00:00
info . is_singleton = scr_path . begins_with ( " * " ) ;
2018-05-01 14:06:23 +00:00
if ( info . is_singleton ) {
2022-09-29 09:53:28 +00:00
scr_path = scr_path . substr ( 1 , scr_path . length ( ) ) ;
2018-05-01 14:06:23 +00:00
}
info . name = name ;
2022-09-29 09:53:28 +00:00
info . path = scr_path ;
2018-05-01 14:06:23 +00:00
info . order = ProjectSettings : : get_singleton ( ) - > get_order ( pi . name ) ;
2018-06-18 18:52:46 +00:00
if ( info . is_singleton ) {
// Make sure name references work before parsing scripts
for ( int i = 0 ; i < ScriptServer : : get_language_count ( ) ; i + + ) {
ScriptServer : : get_language ( i ) - > add_named_global_constant ( info . name , Variant ( ) ) ;
}
}
autoload_cache . push_back ( info ) ;
}
2016-07-04 23:22:28 +00:00
HBoxContainer * hbc = memnew ( HBoxContainer ) ;
add_child ( hbc ) ;
2021-09-13 20:54:20 +00:00
error_message = memnew ( Label ) ;
error_message - > hide ( ) ;
2021-11-25 02:58:47 +00:00
error_message - > set_horizontal_alignment ( HORIZONTAL_ALIGNMENT_RIGHT ) ;
2024-05-14 13:57:29 +00:00
error_message - > add_theme_color_override ( SceneStringName ( font_color ) , EditorNode : : get_singleton ( ) - > get_editor_theme ( ) - > get_color ( SNAME ( " error_color " ) , EditorStringName ( Editor ) ) ) ;
2021-09-13 20:54:20 +00:00
add_child ( error_message ) ;
2017-12-17 17:22:26 +00:00
Label * l = memnew ( Label ) ;
l - > set_text ( TTR ( " Path: " ) ) ;
hbc - > add_child ( l ) ;
2016-07-04 23:22:28 +00:00
2020-04-04 23:08:23 +00:00
autoload_add_path = memnew ( LineEdit ) ;
2017-12-17 17:22:26 +00:00
hbc - > add_child ( autoload_add_path ) ;
2020-04-04 23:08:23 +00:00
autoload_add_path - > set_h_size_flags ( Control : : SIZE_EXPAND_FILL ) ;
2022-03-10 16:46:31 +00:00
autoload_add_path - > set_clear_button_enabled ( true ) ;
2023-02-09 16:24:52 +00:00
autoload_add_path - > set_placeholder ( vformat ( TTR ( " Set path or press \" %s \" to create a script. " ) , TTR ( " Add " ) ) ) ;
2024-05-14 09:42:00 +00:00
autoload_add_path - > connect ( SceneStringName ( text_changed ) , callable_mp ( this , & EditorAutoloadSettings : : _autoload_path_text_changed ) ) ;
2020-04-04 23:08:23 +00:00
browse_button = memnew ( Button ) ;
hbc - > add_child ( browse_button ) ;
2024-05-14 07:40:21 +00:00
browse_button - > connect ( SceneStringName ( pressed ) , callable_mp ( this , & EditorAutoloadSettings : : _browse_autoload_add_path ) ) ;
2020-04-04 23:08:23 +00:00
file_dialog = memnew ( EditorFileDialog ) ;
hbc - > add_child ( file_dialog ) ;
file_dialog - > connect ( " file_selected " , callable_mp ( this , & EditorAutoloadSettings : : _set_autoload_add_path ) ) ;
file_dialog - > connect ( " dir_selected " , callable_mp ( this , & EditorAutoloadSettings : : _set_autoload_add_path ) ) ;
file_dialog - > connect ( " files_selected " , callable_mp ( this , & EditorAutoloadSettings : : _set_autoload_add_path ) ) ;
hbc - > set_h_size_flags ( SIZE_EXPAND_FILL ) ;
file_dialog - > set_file_mode ( EditorFileDialog : : FILE_MODE_OPEN_FILE ) ;
file_dialog - > connect ( " file_selected " , callable_mp ( this , & EditorAutoloadSettings : : _autoload_file_callback ) ) ;
2016-07-04 23:22:28 +00:00
2017-12-17 17:22:26 +00:00
l = memnew ( Label ) ;
l - > set_text ( TTR ( " Node Name: " ) ) ;
hbc - > add_child ( l ) ;
2016-07-04 23:22:28 +00:00
autoload_add_name = memnew ( LineEdit ) ;
autoload_add_name - > set_h_size_flags ( SIZE_EXPAND_FILL ) ;
2021-06-16 16:43:34 +00:00
autoload_add_name - > connect ( " text_submitted " , callable_mp ( this , & EditorAutoloadSettings : : _autoload_text_submitted ) ) ;
2024-05-14 09:42:00 +00:00
autoload_add_name - > connect ( SceneStringName ( text_changed ) , callable_mp ( this , & EditorAutoloadSettings : : _autoload_text_changed ) ) ;
2017-12-17 17:22:26 +00:00
hbc - > add_child ( autoload_add_name ) ;
2016-07-04 23:22:28 +00:00
2019-11-27 23:07:01 +00:00
add_autoload = memnew ( Button ) ;
2016-07-04 23:22:28 +00:00
add_autoload - > set_text ( TTR ( " Add " ) ) ;
2024-05-14 07:40:21 +00:00
add_autoload - > connect ( SceneStringName ( pressed ) , callable_mp ( this , & EditorAutoloadSettings : : _autoload_add ) ) ;
2019-11-27 23:07:01 +00:00
// The button will be enabled once a valid name is entered (either automatically or manually).
add_autoload - > set_disabled ( true ) ;
2017-12-17 17:22:26 +00:00
hbc - > add_child ( add_autoload ) ;
2016-07-04 23:22:28 +00:00
tree = memnew ( Tree ) ;
tree - > set_hide_root ( true ) ;
tree - > set_select_mode ( Tree : : SELECT_MULTI ) ;
2017-08-18 21:19:12 +00:00
tree - > set_allow_reselect ( true ) ;
2016-07-04 23:22:28 +00:00
2023-01-14 02:37:19 +00:00
SET_DRAG_FORWARDING_GCD ( tree , EditorAutoloadSettings ) ;
2016-07-04 23:22:28 +00:00
tree - > set_columns ( 4 ) ;
tree - > set_column_titles_visible ( true ) ;
tree - > set_column_title ( 0 , TTR ( " Name " ) ) ;
tree - > set_column_expand ( 0 , true ) ;
2021-07-04 03:13:28 +00:00
tree - > set_column_expand_ratio ( 0 , 1 ) ;
2016-07-04 23:22:28 +00:00
tree - > set_column_title ( 1 , TTR ( " Path " ) ) ;
tree - > set_column_expand ( 1 , true ) ;
2021-07-04 03:13:28 +00:00
tree - > set_column_clip_content ( 1 , true ) ;
tree - > set_column_expand_ratio ( 1 , 2 ) ;
2016-07-04 23:22:28 +00:00
2021-05-10 17:06:57 +00:00
tree - > set_column_title ( 2 , TTR ( " Global Variable " ) ) ;
2016-07-04 23:22:28 +00:00
tree - > set_column_expand ( 2 , false ) ;
tree - > set_column_expand ( 3 , false ) ;
2020-02-21 17:28:45 +00:00
tree - > connect ( " cell_selected " , callable_mp ( this , & EditorAutoloadSettings : : _autoload_selected ) ) ;
tree - > connect ( " item_edited " , callable_mp ( this , & EditorAutoloadSettings : : _autoload_edited ) ) ;
2021-09-18 07:33:18 +00:00
tree - > connect ( " button_clicked " , callable_mp ( this , & EditorAutoloadSettings : : _autoload_button_pressed ) ) ;
2020-02-21 17:28:45 +00:00
tree - > connect ( " item_activated " , callable_mp ( this , & EditorAutoloadSettings : : _autoload_activated ) ) ;
2017-12-17 17:22:26 +00:00
tree - > set_v_size_flags ( SIZE_EXPAND_FILL ) ;
add_child ( tree , true ) ;
2016-07-04 23:22:28 +00:00
}
2018-05-22 16:26:13 +00:00
EditorAutoloadSettings : : ~ EditorAutoloadSettings ( ) {
2022-03-09 07:03:03 +00:00
for ( const AutoloadInfo & info : autoload_cache ) {
2018-05-22 16:26:13 +00:00
if ( info . node & & ! info . in_editor ) {
memdelete ( info . node ) ;
}
}
}
2020-04-04 23:08:23 +00:00
void EditorAutoloadSettings : : _set_autoload_add_path ( const String & p_text ) {
autoload_add_path - > set_text ( p_text ) ;
2021-07-17 21:22:52 +00:00
autoload_add_path - > emit_signal ( SNAME ( " text_submitted " ) , p_text ) ;
2020-04-04 23:08:23 +00:00
}
void EditorAutoloadSettings : : _browse_autoload_add_path ( ) {
2020-07-11 16:45:19 +00:00
file_dialog - > popup_file_dialog ( ) ;
2020-06-01 06:32:28 +00:00
}