2014-02-10 01:10:30 +00:00
/*************************************************************************/
2017-01-16 07:04:19 +00:00
/* filesystem_dock.cpp */
2014-02-10 01:10:30 +00:00
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
2017-08-27 12:16:55 +00:00
/* https://godotengine.org */
2014-02-10 01:10:30 +00:00
/*************************************************************************/
2022-01-03 20:27:34 +00:00
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
2014-02-10 01:10:30 +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-07-21 13:34:57 +00:00
# include "filesystem_dock.h"
2017-01-16 07:04:19 +00:00
2020-11-07 22:33:38 +00:00
# include "core/config/project_settings.h"
2021-06-11 12:51:48 +00:00
# include "core/io/dir_access.h"
# include "core/io/file_access.h"
2018-09-11 16:13:45 +00:00
# include "core/io/resource_loader.h"
2018-01-05 19:45:54 +00:00
# include "core/os/keyboard.h"
2018-09-11 16:13:45 +00:00
# include "core/os/os.h"
2020-11-07 22:33:38 +00:00
# include "core/templates/list.h"
2019-12-24 07:17:23 +00:00
# include "editor_feature_profile.h"
2017-03-05 15:44:50 +00:00
# include "editor_node.h"
2019-12-24 07:17:23 +00:00
# include "editor_resource_preview.h"
# include "editor_scale.h"
2017-03-05 15:44:50 +00:00
# include "editor_settings.h"
2019-12-24 07:17:23 +00:00
# include "import_dock.h"
2020-03-04 01:51:12 +00:00
# include "scene/main/window.h"
2019-08-15 17:47:21 +00:00
# include "scene/resources/packed_scene.h"
2020-03-03 13:36:29 +00:00
# include "servers/display_server.h"
2021-12-03 14:45:32 +00:00
# include "shader_create_dialog.h"
2016-07-06 17:04:21 +00:00
2021-11-17 20:08:55 +00:00
FileSystemDock * FileSystemDock : : singleton = nullptr ;
2020-10-07 19:56:53 +00:00
Ref < Texture2D > FileSystemDock : : _get_tree_item_icon ( bool p_is_valid , String p_file_type ) {
2019-06-11 18:43:37 +00:00
Ref < Texture2D > file_icon ;
2020-10-07 19:56:53 +00:00
if ( ! p_is_valid ) {
2021-07-17 21:22:52 +00:00
file_icon = get_theme_icon ( SNAME ( " ImportFail " ) , SNAME ( " EditorIcons " ) ) ;
2018-08-23 15:00:30 +00:00
} else {
2021-07-17 21:22:52 +00:00
file_icon = ( has_theme_icon ( p_file_type , SNAME ( " EditorIcons " ) ) ) ? get_theme_icon ( p_file_type , SNAME ( " EditorIcons " ) ) : get_theme_icon ( SNAME ( " File " ) , SNAME ( " EditorIcons " ) ) ;
2018-08-23 15:00:30 +00:00
}
return file_icon ;
}
2019-11-21 14:40:11 +00:00
bool FileSystemDock : : _create_tree ( TreeItem * p_parent , EditorFileSystemDirectory * p_dir , Vector < String > & uncollapsed_paths , bool p_select_in_favorites , bool p_unfold_path ) {
2018-09-13 19:49:56 +00:00
bool parent_should_expand = false ;
2019-08-22 04:22:52 +00:00
// Create a tree item for the subdirectory.
2018-08-23 15:00:30 +00:00
TreeItem * subdirectory_item = tree - > create_item ( p_parent ) ;
2017-03-05 15:44:50 +00:00
String dname = p_dir - > get_name ( ) ;
2021-12-09 09:42:46 +00:00
if ( dname . is_empty ( ) ) {
2017-03-05 15:44:50 +00:00
dname = " res:// " ;
2020-05-14 14:41:43 +00:00
}
2015-08-23 23:15:56 +00:00
2018-08-23 15:00:30 +00:00
subdirectory_item - > set_text ( 0 , dname ) ;
2020-09-03 11:22:16 +00:00
subdirectory_item - > set_structured_text_bidi_override ( 0 , STRUCTURED_TEXT_FILE ) ;
2021-07-17 21:22:52 +00:00
subdirectory_item - > set_icon ( 0 , get_theme_icon ( SNAME ( " Folder " ) , SNAME ( " EditorIcons " ) ) ) ;
subdirectory_item - > set_icon_modulate ( 0 , get_theme_color ( SNAME ( " folder_icon_modulate " ) , SNAME ( " FileDialog " ) ) ) ;
2018-08-23 15:00:30 +00:00
subdirectory_item - > set_selectable ( 0 , true ) ;
2015-08-23 23:15:56 +00:00
String lpath = p_dir - > get_path ( ) ;
2018-08-23 15:00:30 +00:00
subdirectory_item - > set_metadata ( 0 , lpath ) ;
2019-02-25 22:39:49 +00:00
if ( ! p_select_in_favorites & & ( path = = lpath | | ( ( display_mode = = DISPLAY_MODE_SPLIT ) & & path . get_base_dir ( ) = = lpath ) ) ) {
2018-08-23 15:00:30 +00:00
subdirectory_item - > select ( 0 ) ;
2021-01-03 11:01:03 +00:00
// Keep select an item when re-created a tree
// To prevent crashing when nothing is selected.
subdirectory_item - > set_as_cursor ( 0 ) ;
2015-08-23 23:15:56 +00:00
}
2019-11-21 14:40:11 +00:00
if ( p_unfold_path & & path . begins_with ( lpath ) & & path ! = lpath ) {
subdirectory_item - > set_collapsed ( false ) ;
} else {
subdirectory_item - > set_collapsed ( uncollapsed_paths . find ( lpath ) < 0 ) ;
}
2018-09-13 19:49:56 +00:00
if ( searched_string . length ( ) > 0 & & dname . to_lower ( ) . find ( searched_string ) > = 0 ) {
parent_should_expand = true ;
}
2017-09-03 20:35:18 +00:00
2019-08-22 04:22:52 +00:00
// Create items for all subdirectories.
2020-10-22 21:38:41 +00:00
bool reversed = file_sort = = FILE_SORT_NAME_REVERSE ;
for ( int i = reversed ? p_dir - > get_subdir_count ( ) - 1 : 0 ;
reversed ? i > = 0 : i < p_dir - > get_subdir_count ( ) ;
reversed ? i - - : i + + ) {
2019-11-21 14:40:11 +00:00
parent_should_expand = ( _create_tree ( subdirectory_item , p_dir - > get_subdir ( i ) , uncollapsed_paths , p_select_in_favorites , p_unfold_path ) | | parent_should_expand ) ;
2020-05-14 14:41:43 +00:00
}
2018-08-23 15:00:30 +00:00
2019-08-22 04:22:52 +00:00
// Create all items for the files in the subdirectory.
2019-02-25 22:39:49 +00:00
if ( display_mode = = DISPLAY_MODE_TREE_ONLY ) {
2020-01-07 17:09:31 +00:00
String main_scene = ProjectSettings : : get_singleton ( ) - > get ( " application/run/main_scene " ) ;
2020-10-07 19:56:53 +00:00
// Build the list of the files to display.
List < FileInfo > file_list ;
2018-08-23 15:00:30 +00:00
for ( int i = 0 ; i < p_dir - > get_file_count ( ) ; i + + ) {
2019-04-08 22:18:03 +00:00
String file_type = p_dir - > get_file_type ( i ) ;
2021-09-23 21:09:15 +00:00
if ( file_type ! = " TextFile " & & _is_file_type_disabled_by_feature_profile ( file_type ) ) {
2019-08-22 04:22:52 +00:00
// If type is disabled, file won't be displayed.
2019-04-08 22:18:03 +00:00
continue ;
}
2018-08-23 15:00:30 +00:00
2020-10-07 19:56:53 +00:00
String file_name = p_dir - > get_file ( i ) ;
2018-09-13 19:49:56 +00:00
if ( searched_string . length ( ) > 0 ) {
if ( file_name . to_lower ( ) . find ( searched_string ) < 0 ) {
2019-08-22 04:22:52 +00:00
// The searched string is not in the file name, we skip it.
2018-09-13 19:49:56 +00:00
continue ;
} else {
2019-08-22 04:22:52 +00:00
// We expand all parents.
2018-09-13 19:49:56 +00:00
parent_should_expand = true ;
}
}
2020-10-07 19:56:53 +00:00
FileInfo fi ;
fi . name = p_dir - > get_file ( i ) ;
fi . type = p_dir - > get_file_type ( i ) ;
fi . import_broken = ! p_dir - > get_file_import_is_valid ( i ) ;
2020-10-22 21:38:41 +00:00
fi . modified_time = p_dir - > get_file_modified_time ( i ) ;
2020-10-07 19:56:53 +00:00
file_list . push_back ( fi ) ;
}
// Sort the file list if needed.
2020-10-22 21:38:41 +00:00
_sort_file_info_list ( file_list ) ;
2020-10-07 19:56:53 +00:00
// Build the tree.
2021-07-24 13:46:25 +00:00
for ( const FileInfo & fi : file_list ) {
2018-08-23 15:00:30 +00:00
TreeItem * file_item = tree - > create_item ( subdirectory_item ) ;
2020-10-07 19:56:53 +00:00
file_item - > set_text ( 0 , fi . name ) ;
2020-09-03 11:22:16 +00:00
file_item - > set_structured_text_bidi_override ( 0 , STRUCTURED_TEXT_FILE ) ;
2020-10-07 19:56:53 +00:00
file_item - > set_icon ( 0 , _get_tree_item_icon ( ! fi . import_broken , fi . type ) ) ;
String file_metadata = lpath . plus_file ( fi . name ) ;
2018-08-23 15:00:30 +00:00
file_item - > set_metadata ( 0 , file_metadata ) ;
2019-01-17 19:40:38 +00:00
if ( ! p_select_in_favorites & & path = = file_metadata ) {
2018-08-23 15:00:30 +00:00
file_item - > select ( 0 ) ;
2018-09-13 17:06:40 +00:00
file_item - > set_as_cursor ( 0 ) ;
2018-08-23 15:00:30 +00:00
}
2019-10-29 18:24:38 +00:00
if ( main_scene = = file_metadata ) {
2021-07-17 21:22:52 +00:00
file_item - > set_custom_color ( 0 , get_theme_color ( SNAME ( " accent_color " ) , SNAME ( " Editor " ) ) ) ;
2019-10-29 18:24:38 +00:00
}
2018-09-12 11:10:49 +00:00
Array udata ;
udata . push_back ( tree_update_id ) ;
udata . push_back ( file_item ) ;
EditorResourcePreview : : get_singleton ( ) - > queue_resource_preview ( file_metadata , this , " _tree_thumbnail_done " , udata ) ;
2018-08-23 15:00:30 +00:00
}
2019-12-28 19:07:56 +00:00
} else if ( display_mode = = DISPLAY_MODE_SPLIT ) {
if ( lpath . get_base_dir ( ) = = path . get_base_dir ( ) ) {
subdirectory_item - > select ( 0 ) ;
subdirectory_item - > set_as_cursor ( 0 ) ;
}
2018-08-23 15:00:30 +00:00
}
2016-07-08 07:15:31 +00:00
2018-09-13 19:49:56 +00:00
if ( searched_string . length ( ) > 0 ) {
if ( parent_should_expand ) {
subdirectory_item - > set_collapsed ( false ) ;
2018-09-13 21:28:21 +00:00
} else if ( dname ! = " res:// " ) {
2018-09-13 19:49:56 +00:00
subdirectory_item - > get_parent ( ) - > remove_child ( subdirectory_item ) ;
2020-01-15 20:44:43 +00:00
memdelete ( subdirectory_item ) ;
2018-09-13 19:49:56 +00:00
}
}
return parent_should_expand ;
2014-02-10 01:10:30 +00:00
}
2018-09-13 21:28:21 +00:00
Vector < String > FileSystemDock : : _compute_uncollapsed_paths ( ) {
2019-08-22 04:22:52 +00:00
// Register currently collapsed paths.
2017-09-03 20:35:18 +00:00
Vector < String > uncollapsed_paths ;
2018-09-13 21:28:21 +00:00
TreeItem * root = tree - > get_root ( ) ;
if ( root ) {
2021-03-07 20:07:30 +00:00
TreeItem * favorites_item = root - > get_first_child ( ) ;
2018-09-28 22:11:26 +00:00
if ( ! favorites_item - > is_collapsed ( ) ) {
uncollapsed_paths . push_back ( favorites_item - > get_metadata ( 0 ) ) ;
}
2021-03-07 20:07:30 +00:00
TreeItem * resTree = root - > get_first_child ( ) - > get_next ( ) ;
2018-09-13 21:28:21 +00:00
if ( resTree ) {
Vector < TreeItem * > needs_check ;
needs_check . push_back ( resTree ) ;
while ( needs_check . size ( ) ) {
if ( ! needs_check [ 0 ] - > is_collapsed ( ) ) {
uncollapsed_paths . push_back ( needs_check [ 0 ] - > get_metadata ( 0 ) ) ;
2021-03-07 20:07:30 +00:00
TreeItem * child = needs_check [ 0 ] - > get_first_child ( ) ;
2018-09-13 21:28:21 +00:00
while ( child ) {
needs_check . push_back ( child ) ;
child = child - > get_next ( ) ;
2017-09-03 20:35:18 +00:00
}
}
2021-07-03 22:17:03 +00:00
needs_check . remove_at ( 0 ) ;
2017-09-03 20:35:18 +00:00
}
}
}
2018-09-13 21:28:21 +00:00
return uncollapsed_paths ;
}
2019-11-21 14:40:11 +00:00
void FileSystemDock : : _update_tree ( const Vector < String > & p_uncollapsed_paths , bool p_uncollapse_root , bool p_select_in_favorites , bool p_unfold_path ) {
2019-08-22 04:22:52 +00:00
// Recreate the tree.
2014-02-10 01:10:30 +00:00
tree - > clear ( ) ;
2018-09-12 11:10:49 +00:00
tree_update_id + + ;
2017-03-05 15:44:50 +00:00
updating_tree = true ;
2015-08-23 23:15:56 +00:00
TreeItem * root = tree - > create_item ( ) ;
2018-08-23 15:00:30 +00:00
2019-08-22 04:22:52 +00:00
// Handles the favorites.
2015-08-23 23:15:56 +00:00
TreeItem * favorites = tree - > create_item ( root ) ;
2021-07-17 21:22:52 +00:00
favorites - > set_icon ( 0 , get_theme_icon ( SNAME ( " Favorites " ) , SNAME ( " EditorIcons " ) ) ) ;
2017-03-05 15:44:50 +00:00
favorites - > set_text ( 0 , TTR ( " Favorites: " ) ) ;
2018-09-28 22:11:26 +00:00
favorites - > set_metadata ( 0 , " Favorites " ) ;
favorites - > set_collapsed ( p_uncollapsed_paths . find ( " Favorites " ) < 0 ) ;
2017-09-03 20:35:18 +00:00
2018-09-18 12:02:59 +00:00
Vector < String > favorite_paths = EditorSettings : : get_singleton ( ) - > get_favorites ( ) ;
2017-09-03 20:35:18 +00:00
for ( int i = 0 ; i < favorite_paths . size ( ) ; i + + ) {
String fave = favorite_paths [ i ] ;
2020-05-14 14:41:43 +00:00
if ( ! fave . begins_with ( " res:// " ) ) {
2015-08-23 23:15:56 +00:00
continue ;
2020-05-14 14:41:43 +00:00
}
2015-08-23 23:15:56 +00:00
2021-07-17 21:22:52 +00:00
Ref < Texture2D > folder_icon = get_theme_icon ( SNAME ( " Folder " ) , SNAME ( " EditorIcons " ) ) ;
const Color folder_color = get_theme_color ( SNAME ( " folder_icon_modulate " ) , SNAME ( " FileDialog " ) ) ;
2018-08-23 15:00:30 +00:00
2018-09-13 19:49:56 +00:00
String text ;
2019-06-11 18:43:37 +00:00
Ref < Texture2D > icon ;
2019-08-19 22:08:40 +00:00
Color color ;
2018-08-23 15:00:30 +00:00
if ( fave = = " res:// " ) {
2018-09-13 19:49:56 +00:00
text = " / " ;
icon = folder_icon ;
2019-08-19 22:08:40 +00:00
color = folder_color ;
2018-08-23 15:00:30 +00:00
} else if ( fave . ends_with ( " / " ) ) {
2018-09-13 19:49:56 +00:00
text = fave . substr ( 0 , fave . length ( ) - 1 ) . get_file ( ) ;
icon = folder_icon ;
2019-08-19 22:08:40 +00:00
color = folder_color ;
2018-08-23 15:00:30 +00:00
} else {
2018-09-13 19:49:56 +00:00
text = fave . get_file ( ) ;
2018-08-23 15:00:30 +00:00
int index ;
EditorFileSystemDirectory * dir = EditorFileSystem : : get_singleton ( ) - > find_file ( fave , & index ) ;
if ( dir ) {
2020-10-07 19:56:53 +00:00
icon = _get_tree_item_icon ( dir - > get_file_import_is_valid ( index ) , dir - > get_file_type ( index ) ) ;
2018-08-23 15:00:30 +00:00
} else {
2021-07-17 21:22:52 +00:00
icon = get_theme_icon ( SNAME ( " File " ) , SNAME ( " EditorIcons " ) ) ;
2018-08-23 15:00:30 +00:00
}
2019-08-19 22:08:40 +00:00
color = Color ( 1 , 1 , 1 ) ;
2018-08-23 15:00:30 +00:00
}
2018-09-13 19:49:56 +00:00
if ( searched_string . length ( ) = = 0 | | text . to_lower ( ) . find ( searched_string ) > = 0 ) {
TreeItem * ti = tree - > create_item ( favorites ) ;
ti - > set_text ( 0 , text ) ;
ti - > set_icon ( 0 , icon ) ;
2019-08-24 15:13:48 +00:00
ti - > set_icon_modulate ( 0 , color ) ;
2018-09-13 19:49:56 +00:00
ti - > set_tooltip ( 0 , fave ) ;
ti - > set_selectable ( 0 , true ) ;
ti - > set_metadata ( 0 , fave ) ;
2019-01-17 19:40:38 +00:00
if ( p_select_in_favorites & & fave = = path ) {
ti - > select ( 0 ) ;
ti - > set_as_cursor ( 0 ) ;
}
2018-09-28 22:11:26 +00:00
if ( ! fave . ends_with ( " / " ) ) {
Array udata ;
udata . push_back ( tree_update_id ) ;
udata . push_back ( ti ) ;
EditorResourcePreview : : get_singleton ( ) - > queue_resource_preview ( fave , this , " _tree_thumbnail_done " , udata ) ;
}
2018-09-13 19:49:56 +00:00
}
}
2018-09-13 21:28:21 +00:00
Vector < String > uncollapsed_paths = p_uncollapsed_paths ;
2018-02-01 01:53:31 +00:00
if ( p_uncollapse_root ) {
uncollapsed_paths . push_back ( " res:// " ) ;
}
2019-08-22 04:22:52 +00:00
// Create the remaining of the tree.
2019-11-21 14:40:11 +00:00
_create_tree ( root , EditorFileSystem : : get_singleton ( ) - > get_filesystem ( ) , uncollapsed_paths , p_select_in_favorites , p_unfold_path ) ;
2017-12-16 13:52:51 +00:00
tree - > ensure_cursor_is_visible ( ) ;
2017-03-05 15:44:50 +00:00
updating_tree = false ;
2014-02-10 01:10:30 +00:00
}
2019-02-25 22:39:49 +00:00
void FileSystemDock : : set_display_mode ( DisplayMode p_display_mode ) {
display_mode = p_display_mode ;
_update_display_mode ( false ) ;
}
2018-10-22 08:31:50 +00:00
void FileSystemDock : : _update_display_mode ( bool p_force ) {
2019-08-22 04:22:52 +00:00
// Compute the new display mode.
2019-02-25 22:39:49 +00:00
if ( p_force | | old_display_mode ! = display_mode ) {
2019-06-26 13:08:25 +00:00
button_toggle_display_mode - > set_pressed ( display_mode = = DISPLAY_MODE_SPLIT ) ;
2018-09-14 11:59:19 +00:00
switch ( display_mode ) {
2018-09-13 15:35:44 +00:00
case DISPLAY_MODE_TREE_ONLY :
2018-08-13 17:05:31 +00:00
tree - > show ( ) ;
tree - > set_v_size_flags ( SIZE_EXPAND_FILL ) ;
2019-02-25 22:39:49 +00:00
if ( display_mode = = DISPLAY_MODE_TREE_ONLY ) {
2020-10-07 19:56:53 +00:00
toolbar2_hbc - > show ( ) ;
2018-09-13 19:49:56 +00:00
} else {
2020-10-07 19:56:53 +00:00
toolbar2_hbc - > hide ( ) ;
2018-09-13 19:49:56 +00:00
}
2016-05-15 23:25:51 +00:00
2018-09-13 21:28:21 +00:00
_update_tree ( _compute_uncollapsed_paths ( ) ) ;
2018-08-13 17:05:31 +00:00
file_list_vb - > hide ( ) ;
break ;
2016-05-15 23:25:51 +00:00
2018-09-13 15:35:44 +00:00
case DISPLAY_MODE_SPLIT :
2018-08-13 17:05:31 +00:00
tree - > show ( ) ;
tree - > set_v_size_flags ( SIZE_EXPAND_FILL ) ;
tree - > ensure_cursor_is_visible ( ) ;
2020-10-07 19:56:53 +00:00
toolbar2_hbc - > hide ( ) ;
2018-09-13 21:28:21 +00:00
_update_tree ( _compute_uncollapsed_paths ( ) ) ;
2016-05-15 23:25:51 +00:00
2018-08-13 17:05:31 +00:00
file_list_vb - > show ( ) ;
2018-09-28 11:26:36 +00:00
_update_file_list ( true ) ;
2018-08-13 17:05:31 +00:00
break ;
}
2019-02-25 22:39:49 +00:00
old_display_mode = display_mode ;
2018-08-13 17:05:31 +00:00
}
}
2016-05-15 23:25:51 +00:00
2018-08-13 17:05:31 +00:00
void FileSystemDock : : _notification ( int p_what ) {
switch ( p_what ) {
2020-09-03 11:22:16 +00:00
case NOTIFICATION_TRANSLATION_CHANGED :
case NOTIFICATION_LAYOUT_DIRECTION_CHANGED :
2014-11-06 00:20:42 +00:00
case NOTIFICATION_ENTER_TREE : {
2020-05-14 14:41:43 +00:00
if ( initialized ) {
2015-08-23 23:15:56 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2017-03-05 15:44:50 +00:00
initialized = true ;
2020-02-21 17:28:45 +00:00
EditorFeatureProfileManager : : get_singleton ( ) - > connect ( " current_feature_profile_changed " , callable_mp ( this , & FileSystemDock : : _feature_profile_changed ) ) ;
2014-02-10 01:10:30 +00:00
2020-02-21 17:28:45 +00:00
EditorFileSystem : : get_singleton ( ) - > connect ( " filesystem_changed " , callable_mp ( this , & FileSystemDock : : _fs_changed ) ) ;
EditorResourcePreview : : get_singleton ( ) - > connect ( " preview_invalidated " , callable_mp ( this , & FileSystemDock : : _preview_invalidated ) ) ;
2014-02-10 01:10:30 +00:00
2022-02-06 13:12:19 +00:00
button_reload - > set_icon ( get_theme_icon ( SNAME ( " Reload " ) , SNAME ( " EditorIcons " ) ) ) ;
button_toggle_display_mode - > set_icon ( get_theme_icon ( SNAME ( " Panels2 " ) , SNAME ( " EditorIcons " ) ) ) ;
2020-02-21 17:28:45 +00:00
button_file_list_display_mode - > connect ( " pressed " , callable_mp ( this , & FileSystemDock : : _toggle_file_display ) ) ;
2018-09-13 22:16:43 +00:00
2020-02-21 17:28:45 +00:00
files - > connect ( " item_activated " , callable_mp ( this , & FileSystemDock : : _file_list_activate_file ) ) ;
button_hist_next - > connect ( " pressed " , callable_mp ( this , & FileSystemDock : : _fw_history ) ) ;
button_hist_prev - > connect ( " pressed " , callable_mp ( this , & FileSystemDock : : _bw_history ) ) ;
2020-10-07 19:56:53 +00:00
2022-02-06 13:12:19 +00:00
tree_search_box - > set_right_icon ( get_theme_icon ( SNAME ( " Search " ) , SNAME ( " EditorIcons " ) ) ) ;
2018-09-13 19:49:56 +00:00
tree_search_box - > set_clear_button_enabled ( true ) ;
2022-02-06 13:12:19 +00:00
tree_button_sort - > set_icon ( get_theme_icon ( SNAME ( " Sort " ) , SNAME ( " EditorIcons " ) ) ) ;
2020-10-07 19:56:53 +00:00
2022-02-06 13:12:19 +00:00
file_list_search_box - > set_right_icon ( get_theme_icon ( SNAME ( " Search " ) , SNAME ( " EditorIcons " ) ) ) ;
2018-09-13 19:49:56 +00:00
file_list_search_box - > set_clear_button_enabled ( true ) ;
2022-02-06 13:12:19 +00:00
file_list_button_sort - > set_icon ( get_theme_icon ( SNAME ( " Sort " ) , SNAME ( " EditorIcons " ) ) ) ;
2017-03-05 15:44:50 +00:00
2020-09-03 11:22:16 +00:00
if ( is_layout_rtl ( ) ) {
2022-02-06 13:12:19 +00:00
button_hist_next - > set_icon ( get_theme_icon ( SNAME ( " Back " ) , SNAME ( " EditorIcons " ) ) ) ;
button_hist_prev - > set_icon ( get_theme_icon ( SNAME ( " Forward " ) , SNAME ( " EditorIcons " ) ) ) ;
2020-09-03 11:22:16 +00:00
} else {
2022-02-06 13:12:19 +00:00
button_hist_next - > set_icon ( get_theme_icon ( SNAME ( " Forward " ) , SNAME ( " EditorIcons " ) ) ) ;
button_hist_prev - > set_icon ( get_theme_icon ( SNAME ( " Back " ) , SNAME ( " EditorIcons " ) ) ) ;
2020-09-03 11:22:16 +00:00
}
2020-02-21 17:28:45 +00:00
file_list_popup - > connect ( " id_pressed " , callable_mp ( this , & FileSystemDock : : _file_list_rmb_option ) ) ;
tree_popup - > connect ( " id_pressed " , callable_mp ( this , & FileSystemDock : : _tree_rmb_option ) ) ;
2017-03-05 15:44:50 +00:00
2021-06-16 16:43:34 +00:00
current_path - > connect ( " text_submitted " , callable_mp ( this , & FileSystemDock : : _navigate_to_path ) , make_binds ( false ) ) ;
2014-02-10 01:10:30 +00:00
2018-08-23 15:00:30 +00:00
always_show_folders = bool ( EditorSettings : : get_singleton ( ) - > get ( " docks/filesystem/always_show_folders " ) ) ;
2019-03-02 23:12:02 +00:00
set_file_list_display_mode ( FileSystemDock : : FILE_LIST_DISPLAY_LIST ) ;
2018-09-21 07:42:41 +00:00
_update_display_mode ( ) ;
2015-08-23 23:15:56 +00:00
if ( EditorFileSystem : : get_singleton ( ) - > is_scanning ( ) ) {
2017-01-21 12:07:29 +00:00
_set_scanning_mode ( ) ;
2017-09-03 20:35:18 +00:00
} else {
2018-09-13 21:28:21 +00:00
_update_tree ( Vector < String > ( ) , true ) ;
2014-02-10 01:10:30 +00:00
}
2015-08-23 23:15:56 +00:00
} break ;
2019-08-22 04:22:52 +00:00
2015-08-23 23:15:56 +00:00
case NOTIFICATION_PROCESS : {
if ( EditorFileSystem : : get_singleton ( ) - > is_scanning ( ) ) {
2017-03-05 15:44:50 +00:00
scanning_progress - > set_value ( EditorFileSystem : : get_singleton ( ) - > get_scanning_progress ( ) * 100 ) ;
2015-08-23 23:15:56 +00:00
}
2014-02-10 01:10:30 +00:00
} break ;
2016-05-15 23:25:51 +00:00
case NOTIFICATION_DRAG_BEGIN : {
Dictionary dd = get_viewport ( ) - > gui_get_drag_data ( ) ;
2017-03-05 15:44:50 +00:00
if ( tree - > is_visible_in_tree ( ) & & dd . has ( " type " ) ) {
2019-10-20 17:39:21 +00:00
if ( dd . has ( " favorite " ) ) {
2020-05-14 14:41:43 +00:00
if ( ( String ( dd [ " favorite " ] ) = = " all " ) ) {
2019-10-20 17:39:21 +00:00
tree - > set_drop_mode_flags ( Tree : : DROP_MODE_INBETWEEN ) ;
2020-05-14 14:41:43 +00:00
}
2019-10-20 17:39:21 +00:00
} else if ( ( String ( dd [ " type " ] ) = = " files " ) | | ( String ( dd [ " type " ] ) = = " files_and_dirs " ) | | ( String ( dd [ " type " ] ) = = " resource " ) ) {
2018-08-23 15:00:30 +00:00
tree - > set_drop_mode_flags ( Tree : : DROP_MODE_ON_ITEM | Tree : : DROP_MODE_INBETWEEN ) ;
2016-05-24 02:24:17 +00:00
}
2016-05-15 23:25:51 +00:00
}
} break ;
2019-08-22 04:22:52 +00:00
case NOTIFICATION_DRAG_END : {
2016-05-15 23:25:51 +00:00
tree - > set_drop_mode_flags ( 0 ) ;
2014-02-10 01:10:30 +00:00
} break ;
2019-08-22 04:22:52 +00:00
2018-10-22 08:31:50 +00:00
case NOTIFICATION_THEME_CHANGED : {
2018-10-29 13:20:31 +00:00
if ( is_visible_in_tree ( ) ) {
2018-10-25 10:20:45 +00:00
_update_display_mode ( true ) ;
}
2018-10-22 08:31:50 +00:00
} break ;
2019-08-22 04:22:52 +00:00
2015-12-15 16:39:13 +00:00
case EditorSettings : : NOTIFICATION_EDITOR_SETTINGS_CHANGED : {
2019-08-22 04:22:52 +00:00
// Update icons.
2022-02-06 13:12:19 +00:00
button_reload - > set_icon ( get_theme_icon ( SNAME ( " Reload " ) , SNAME ( " EditorIcons " ) ) ) ;
button_toggle_display_mode - > set_icon ( get_theme_icon ( SNAME ( " Panels2 " ) , SNAME ( " EditorIcons " ) ) ) ;
2020-09-03 11:22:16 +00:00
if ( is_layout_rtl ( ) ) {
2022-02-06 13:12:19 +00:00
button_hist_next - > set_icon ( get_theme_icon ( SNAME ( " Back " ) , SNAME ( " EditorIcons " ) ) ) ;
button_hist_prev - > set_icon ( get_theme_icon ( SNAME ( " Forward " ) , SNAME ( " EditorIcons " ) ) ) ;
2020-09-03 11:22:16 +00:00
} else {
2022-02-06 13:12:19 +00:00
button_hist_next - > set_icon ( get_theme_icon ( SNAME ( " Forward " ) , SNAME ( " EditorIcons " ) ) ) ;
button_hist_prev - > set_icon ( get_theme_icon ( SNAME ( " Back " ) , SNAME ( " EditorIcons " ) ) ) ;
2020-09-03 11:22:16 +00:00
}
2019-03-05 18:05:53 +00:00
if ( file_list_display_mode = = FILE_LIST_DISPLAY_LIST ) {
2021-07-17 21:22:52 +00:00
button_file_list_display_mode - > set_icon ( get_theme_icon ( SNAME ( " FileThumbnail " ) , SNAME ( " EditorIcons " ) ) ) ;
2018-10-22 08:31:50 +00:00
} else {
2021-07-17 21:22:52 +00:00
button_file_list_display_mode - > set_icon ( get_theme_icon ( SNAME ( " FileList " ) , SNAME ( " EditorIcons " ) ) ) ;
2018-10-22 08:31:50 +00:00
}
2017-08-29 23:03:13 +00:00
2022-02-06 13:12:19 +00:00
tree_search_box - > set_right_icon ( get_theme_icon ( SNAME ( " Search " ) , SNAME ( " EditorIcons " ) ) ) ;
2018-09-13 19:49:56 +00:00
tree_search_box - > set_clear_button_enabled ( true ) ;
2022-02-06 13:12:19 +00:00
tree_button_sort - > set_icon ( get_theme_icon ( SNAME ( " Sort " ) , SNAME ( " EditorIcons " ) ) ) ;
2020-10-07 19:56:53 +00:00
2022-02-06 13:12:19 +00:00
file_list_search_box - > set_right_icon ( get_theme_icon ( SNAME ( " Search " ) , SNAME ( " EditorIcons " ) ) ) ;
2018-09-13 19:49:56 +00:00
file_list_search_box - > set_clear_button_enabled ( true ) ;
2022-02-06 13:12:19 +00:00
file_list_button_sort - > set_icon ( get_theme_icon ( SNAME ( " Sort " ) , SNAME ( " EditorIcons " ) ) ) ;
2017-08-29 23:03:13 +00:00
2019-08-22 04:22:52 +00:00
// Update always show folders.
2018-08-23 15:00:30 +00:00
bool new_always_show_folders = bool ( EditorSettings : : get_singleton ( ) - > get ( " docks/filesystem/always_show_folders " ) ) ;
if ( new_always_show_folders ! = always_show_folders ) {
always_show_folders = new_always_show_folders ;
2018-09-28 11:26:36 +00:00
_update_file_list ( true ) ;
2018-08-23 15:00:30 +00:00
}
2019-08-22 04:22:52 +00:00
// Change full tree mode.
2018-08-13 17:05:31 +00:00
_update_display_mode ( ) ;
2015-12-15 16:39:13 +00:00
} break ;
2014-02-10 01:10:30 +00:00
}
}
2018-08-23 15:00:30 +00:00
void FileSystemDock : : _tree_multi_selected ( Object * p_item , int p_column , bool p_selected ) {
2019-08-22 04:22:52 +00:00
// Update the import dock.
2018-09-24 12:26:26 +00:00
import_dock_needs_update = true ;
2021-07-17 21:22:52 +00:00
call_deferred ( SNAME ( " _update_import_dock " ) ) ;
2015-08-23 23:15:56 +00:00
2019-08-22 04:22:52 +00:00
// Return if we don't select something new.
2020-05-14 14:41:43 +00:00
if ( ! p_selected ) {
2018-08-23 15:00:30 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2018-08-23 15:00:30 +00:00
2019-08-22 04:22:52 +00:00
// Tree item selected.
2018-09-28 22:11:26 +00:00
TreeItem * selected = tree - > get_selected ( ) ;
2020-05-14 14:41:43 +00:00
if ( ! selected ) {
2018-08-23 15:00:30 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2018-09-28 22:11:26 +00:00
2021-03-07 20:07:30 +00:00
TreeItem * favorites_item = tree - > get_root ( ) - > get_first_child ( ) ;
2018-10-19 20:43:48 +00:00
if ( selected - > get_parent ( ) = = favorites_item & & ! String ( selected - > get_metadata ( 0 ) ) . ends_with ( " / " ) ) {
2019-08-22 04:22:52 +00:00
// Go to the favorites if we click in the favorites and the path has changed.
2018-09-28 22:11:26 +00:00
path = " Favorites " ;
} else {
path = selected - > get_metadata ( 0 ) ;
2019-08-22 04:22:52 +00:00
// Note: the "Favorites" item also leads to this path.
2018-09-28 22:11:26 +00:00
}
2018-08-23 15:00:30 +00:00
2019-08-22 04:22:52 +00:00
// Set the current path.
2018-09-28 22:11:26 +00:00
_set_current_path_text ( path ) ;
2017-09-03 20:35:18 +00:00
_push_to_history ( ) ;
2016-05-15 23:25:51 +00:00
2019-08-22 04:22:52 +00:00
// Update the file list.
2018-09-13 15:35:44 +00:00
if ( ! updating_tree & & display_mode = = DISPLAY_MODE_SPLIT ) {
2018-09-28 11:26:36 +00:00
_update_file_list ( false ) ;
2015-08-23 23:15:56 +00:00
}
}
2016-07-21 13:34:57 +00:00
String FileSystemDock : : get_selected_path ( ) const {
2020-05-14 14:41:43 +00:00
if ( path . ends_with ( " / " ) ) {
2018-08-23 15:00:30 +00:00
return path ;
2020-05-14 14:41:43 +00:00
} else {
2018-08-23 15:00:30 +00:00
return path . get_base_dir ( ) ;
2020-05-14 14:41:43 +00:00
}
2014-02-10 01:10:30 +00:00
}
2016-07-21 13:34:57 +00:00
String FileSystemDock : : get_current_path ( ) const {
2016-05-27 17:18:40 +00:00
return path ;
}
2014-02-10 01:10:30 +00:00
2018-09-28 22:11:26 +00:00
void FileSystemDock : : _set_current_path_text ( const String & p_path ) {
if ( p_path = = " Favorites " ) {
current_path - > set_text ( TTR ( " Favorites " ) ) ;
} else {
current_path - > set_text ( path ) ;
}
}
2019-01-17 19:40:38 +00:00
void FileSystemDock : : _navigate_to_path ( const String & p_path , bool p_select_in_favorites ) {
2018-09-28 22:11:26 +00:00
if ( p_path = = " Favorites " ) {
path = p_path ;
2017-01-14 17:14:46 +00:00
} else {
2018-09-28 22:11:26 +00:00
String target_path = p_path ;
// If the path is a file, do not only go to the directory in the tree, also select the file in the file list.
if ( target_path . ends_with ( " / " ) ) {
target_path = target_path . substr ( 0 , target_path . length ( ) - 1 ) ;
}
DirAccess * dirAccess = DirAccess : : open ( " res:// " ) ;
if ( dirAccess - > file_exists ( p_path ) ) {
path = target_path ;
} else if ( dirAccess - > dir_exists ( p_path ) ) {
path = target_path + " / " ;
} else {
2019-05-30 19:31:05 +00:00
memdelete ( dirAccess ) ;
2019-08-15 02:57:49 +00:00
ERR_FAIL_MSG ( vformat ( " Cannot navigate to '%s' as it has not been found in the file system! " , p_path ) ) ;
2018-09-28 22:11:26 +00:00
}
2019-05-30 19:31:05 +00:00
memdelete ( dirAccess ) ;
2017-01-14 17:14:46 +00:00
}
2018-09-28 22:11:26 +00:00
_set_current_path_text ( path ) ;
2017-09-03 20:35:18 +00:00
_push_to_history ( ) ;
2017-01-14 17:14:46 +00:00
2019-11-21 14:40:11 +00:00
_update_tree ( _compute_uncollapsed_paths ( ) , false , p_select_in_favorites , true ) ;
2018-09-13 15:35:44 +00:00
if ( display_mode = = DISPLAY_MODE_SPLIT ) {
2018-09-28 11:26:36 +00:00
_update_file_list ( false ) ;
2021-11-30 16:46:36 +00:00
files - > get_v_scroll_bar ( ) - > set_value ( 0 ) ;
2017-09-03 20:35:18 +00:00
}
2017-01-14 17:14:46 +00:00
2018-08-23 15:00:30 +00:00
String file_name = p_path . get_file ( ) ;
2020-12-15 12:04:21 +00:00
if ( ! file_name . is_empty ( ) ) {
2017-03-05 15:44:50 +00:00
for ( int i = 0 ; i < files - > get_item_count ( ) ; i + + ) {
2017-01-14 17:14:46 +00:00
if ( files - > get_item_text ( i ) = = file_name ) {
2017-03-05 15:44:50 +00:00
files - > select ( i , true ) ;
2017-01-14 17:14:46 +00:00
files - > ensure_current_is_visible ( ) ;
break ;
}
}
}
}
2019-01-17 19:40:38 +00:00
void FileSystemDock : : navigate_to_path ( const String & p_path ) {
2019-09-25 11:14:45 +00:00
file_list_search_box - > clear ( ) ;
2019-01-17 19:40:38 +00:00
_navigate_to_path ( p_path ) ;
}
2019-06-11 18:43:37 +00:00
void FileSystemDock : : _file_list_thumbnail_done ( const String & p_path , const Ref < Texture2D > & p_preview , const Ref < Texture2D > & p_small_preview , const Variant & p_udata ) {
2017-09-03 20:35:18 +00:00
if ( ( file_list_vb - > is_visible_in_tree ( ) | | path = = p_path . get_base_dir ( ) ) & & p_preview . is_valid ( ) ) {
2017-03-05 15:44:50 +00:00
Array uarr = p_udata ;
int idx = uarr [ 0 ] ;
String file = uarr [ 1 ] ;
2018-09-28 11:26:36 +00:00
if ( idx < files - > get_item_count ( ) & & files - > get_item_text ( idx ) = = file & & files - > get_item_metadata ( idx ) = = p_path ) {
if ( file_list_display_mode = = FILE_LIST_DISPLAY_LIST ) {
2020-05-14 14:41:43 +00:00
if ( p_small_preview . is_valid ( ) ) {
2018-09-28 11:26:36 +00:00
files - > set_item_icon ( idx , p_small_preview ) ;
2020-05-14 14:41:43 +00:00
}
2018-09-28 11:26:36 +00:00
} else {
files - > set_item_icon ( idx , p_preview ) ;
}
}
2015-08-23 23:15:56 +00:00
}
}
2019-06-11 18:43:37 +00:00
void FileSystemDock : : _tree_thumbnail_done ( const String & p_path , const Ref < Texture2D > & p_preview , const Ref < Texture2D > & p_small_preview , const Variant & p_udata ) {
2018-09-12 11:10:49 +00:00
if ( p_small_preview . is_valid ( ) ) {
Array uarr = p_udata ;
if ( tree_update_id = = ( int ) uarr [ 0 ] ) {
TreeItem * file_item = Object : : cast_to < TreeItem > ( uarr [ 1 ] ) ;
if ( file_item ) {
file_item - > set_icon ( 0 , p_small_preview ) ;
}
}
}
}
2019-03-05 06:55:08 +00:00
void FileSystemDock : : _toggle_file_display ( ) {
_set_file_display ( file_list_display_mode ! = FILE_LIST_DISPLAY_LIST ) ;
2021-07-17 21:22:52 +00:00
emit_signal ( SNAME ( " display_mode_changed " ) ) ;
2019-02-27 20:36:12 +00:00
}
2015-08-23 23:15:56 +00:00
2019-02-27 20:36:12 +00:00
void FileSystemDock : : _set_file_display ( bool p_active ) {
if ( p_active ) {
2018-08-13 17:05:31 +00:00
file_list_display_mode = FILE_LIST_DISPLAY_LIST ;
2021-07-17 21:22:52 +00:00
button_file_list_display_mode - > set_icon ( get_theme_icon ( SNAME ( " FileThumbnail " ) , SNAME ( " EditorIcons " ) ) ) ;
2018-08-13 17:05:31 +00:00
button_file_list_display_mode - > set_tooltip ( TTR ( " View items as a grid of thumbnails. " ) ) ;
2015-08-23 23:15:56 +00:00
} else {
2018-08-13 17:05:31 +00:00
file_list_display_mode = FILE_LIST_DISPLAY_THUMBNAILS ;
2021-07-17 21:22:52 +00:00
button_file_list_display_mode - > set_icon ( get_theme_icon ( SNAME ( " FileList " ) , SNAME ( " EditorIcons " ) ) ) ;
2018-08-13 17:05:31 +00:00
button_file_list_display_mode - > set_tooltip ( TTR ( " View items as a list. " ) ) ;
2015-08-23 23:15:56 +00:00
}
2016-08-16 16:25:42 +00:00
2018-09-28 11:26:36 +00:00
_update_file_list ( true ) ;
2015-08-23 23:15:56 +00:00
}
2019-04-08 22:18:03 +00:00
bool FileSystemDock : : _is_file_type_disabled_by_feature_profile ( const StringName & p_class ) {
Ref < EditorFeatureProfile > profile = EditorFeatureProfileManager : : get_singleton ( ) - > get_current_profile ( ) ;
if ( profile . is_null ( ) ) {
return false ;
}
StringName class_name = p_class ;
while ( class_name ! = StringName ( ) ) {
if ( profile - > is_class_disabled ( class_name ) ) {
return true ;
}
class_name = ClassDB : : get_parent_class ( class_name ) ;
}
return false ;
}
2017-03-05 15:44:50 +00:00
void FileSystemDock : : _search ( EditorFileSystemDirectory * p_path , List < FileInfo > * matches , int p_max_items ) {
2020-05-14 14:41:43 +00:00
if ( matches - > size ( ) > p_max_items ) {
2016-05-15 23:25:51 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2016-05-15 23:25:51 +00:00
2017-03-05 15:44:50 +00:00
for ( int i = 0 ; i < p_path - > get_subdir_count ( ) ; i + + ) {
_search ( p_path - > get_subdir ( i ) , matches , p_max_items ) ;
2016-05-15 23:25:51 +00:00
}
2017-03-05 15:44:50 +00:00
for ( int i = 0 ; i < p_path - > get_file_count ( ) ; i + + ) {
2016-05-15 23:25:51 +00:00
String file = p_path - > get_file ( i ) ;
2022-02-03 16:03:38 +00:00
if ( file . to_lower ( ) . contains ( searched_string ) ) {
2016-05-15 23:25:51 +00:00
FileInfo fi ;
2017-03-05 15:44:50 +00:00
fi . name = file ;
fi . type = p_path - > get_file_type ( i ) ;
fi . path = p_path - > get_file_path ( i ) ;
2017-08-29 23:17:34 +00:00
fi . import_broken = ! p_path - > get_file_import_is_valid ( i ) ;
2020-10-22 21:38:41 +00:00
fi . modified_time = p_path - > get_file_modified_time ( i ) ;
2016-05-27 17:18:40 +00:00
2019-04-08 22:18:03 +00:00
if ( _is_file_type_disabled_by_feature_profile ( fi . type ) ) {
2019-08-22 04:22:52 +00:00
// This type is disabled, will not appear here.
2019-04-08 22:18:03 +00:00
continue ;
}
2016-05-15 23:25:51 +00:00
matches - > push_back ( fi ) ;
2020-05-14 14:41:43 +00:00
if ( matches - > size ( ) > p_max_items ) {
2016-05-15 23:25:51 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2016-05-15 23:25:51 +00:00
}
}
}
2020-10-22 21:38:41 +00:00
struct FileSystemDock : : FileInfoTypeComparator {
bool operator ( ) ( const FileInfo & p_a , const FileInfo & p_b ) const {
// Uses the extension, then the icon name to distinguish file types.
String icon_path_a = " " ;
String icon_path_b = " " ;
Ref < Texture2D > icon_a = EditorNode : : get_singleton ( ) - > get_class_icon ( p_a . type ) ;
if ( icon_a . is_valid ( ) ) {
icon_path_a = icon_a - > get_name ( ) ;
}
Ref < Texture2D > icon_b = EditorNode : : get_singleton ( ) - > get_class_icon ( p_b . type ) ;
if ( icon_b . is_valid ( ) ) {
icon_path_b = icon_b - > get_name ( ) ;
}
return NaturalNoCaseComparator ( ) ( p_a . name . get_extension ( ) + icon_path_a + p_a . name . get_basename ( ) , p_b . name . get_extension ( ) + icon_path_b + p_b . name . get_basename ( ) ) ;
}
} ;
struct FileSystemDock : : FileInfoModifiedTimeComparator {
bool operator ( ) ( const FileInfo & p_a , const FileInfo & p_b ) const {
return p_a . modified_time > p_b . modified_time ;
}
} ;
void FileSystemDock : : _sort_file_info_list ( List < FileSystemDock : : FileInfo > & r_file_list ) {
// Sort the file list if needed.
switch ( file_sort ) {
case FILE_SORT_TYPE :
r_file_list . sort_custom < FileInfoTypeComparator > ( ) ;
break ;
case FILE_SORT_TYPE_REVERSE :
r_file_list . sort_custom < FileInfoTypeComparator > ( ) ;
2021-03-14 07:21:32 +00:00
r_file_list . reverse ( ) ;
2020-10-22 21:38:41 +00:00
break ;
case FILE_SORT_MODIFIED_TIME :
r_file_list . sort_custom < FileInfoModifiedTimeComparator > ( ) ;
break ;
case FILE_SORT_MODIFIED_TIME_REVERSE :
r_file_list . sort_custom < FileInfoModifiedTimeComparator > ( ) ;
2021-03-14 07:21:32 +00:00
r_file_list . reverse ( ) ;
2020-10-22 21:38:41 +00:00
break ;
case FILE_SORT_NAME_REVERSE :
2021-10-23 07:51:26 +00:00
r_file_list . sort ( ) ;
2021-03-14 07:21:32 +00:00
r_file_list . reverse ( ) ;
2020-10-22 21:38:41 +00:00
break ;
default : // FILE_SORT_NAME
2021-10-23 07:51:26 +00:00
r_file_list . sort ( ) ;
2020-10-22 21:38:41 +00:00
break ;
}
}
2018-09-28 11:26:36 +00:00
void FileSystemDock : : _update_file_list ( bool p_keep_selection ) {
2019-08-22 04:22:52 +00:00
// Register the previously selected items.
2015-08-23 23:15:56 +00:00
Set < String > cselection ;
if ( p_keep_selection ) {
2017-03-05 15:44:50 +00:00
for ( int i = 0 ; i < files - > get_item_count ( ) ; i + + ) {
2020-05-14 14:41:43 +00:00
if ( files - > is_selected ( i ) ) {
2015-08-23 23:15:56 +00:00
cselection . insert ( files - > get_item_text ( i ) ) ;
2020-05-14 14:41:43 +00:00
}
2015-08-23 23:15:56 +00:00
}
}
files - > clear ( ) ;
2018-09-28 22:11:26 +00:00
_set_current_path_text ( path ) ;
2016-05-15 23:25:51 +00:00
2018-08-23 15:00:30 +00:00
String directory = path ;
String file = " " ;
2015-08-23 23:15:56 +00:00
2017-01-05 22:41:36 +00:00
int thumbnail_size = EditorSettings : : get_singleton ( ) - > get ( " docks/filesystem/thumbnail_size " ) ;
2017-03-05 15:44:50 +00:00
thumbnail_size * = EDSCALE ;
2019-06-11 18:43:37 +00:00
Ref < Texture2D > folder_thumbnail ;
Ref < Texture2D > file_thumbnail ;
Ref < Texture2D > file_thumbnail_broken ;
2015-08-23 23:15:56 +00:00
2018-08-13 17:05:31 +00:00
bool use_thumbnails = ( file_list_display_mode = = FILE_LIST_DISPLAY_THUMBNAILS ) ;
2015-08-23 23:15:56 +00:00
2017-09-03 20:35:18 +00:00
if ( use_thumbnails ) {
2019-08-22 04:22:52 +00:00
// Thumbnails mode.
2015-08-23 23:15:56 +00:00
files - > set_max_columns ( 0 ) ;
files - > set_icon_mode ( ItemList : : ICON_MODE_TOP ) ;
2017-03-05 15:44:50 +00:00
files - > set_fixed_column_width ( thumbnail_size * 3 / 2 ) ;
2015-08-23 23:15:56 +00:00
files - > set_max_text_lines ( 2 ) ;
2017-03-05 15:44:50 +00:00
files - > set_fixed_icon_size ( Size2 ( thumbnail_size , thumbnail_size ) ) ;
2015-08-23 23:15:56 +00:00
2017-09-08 07:32:43 +00:00
if ( thumbnail_size < 64 ) {
2022-02-06 13:12:19 +00:00
folder_thumbnail = get_theme_icon ( SNAME ( " FolderMediumThumb " ) , SNAME ( " EditorIcons " ) ) ;
file_thumbnail = get_theme_icon ( SNAME ( " FileMediumThumb " ) , SNAME ( " EditorIcons " ) ) ;
file_thumbnail_broken = get_theme_icon ( SNAME ( " FileDeadMediumThumb " ) , SNAME ( " EditorIcons " ) ) ;
2017-09-08 07:32:43 +00:00
} else {
2022-02-06 13:12:19 +00:00
folder_thumbnail = get_theme_icon ( SNAME ( " FolderBigThumb " ) , SNAME ( " EditorIcons " ) ) ;
file_thumbnail = get_theme_icon ( SNAME ( " FileBigThumb " ) , SNAME ( " EditorIcons " ) ) ;
file_thumbnail_broken = get_theme_icon ( SNAME ( " FileDeadBigThumb " ) , SNAME ( " EditorIcons " ) ) ;
2015-08-23 23:15:56 +00:00
}
} else {
2019-08-22 04:22:52 +00:00
// No thumbnails.
2015-08-23 23:15:56 +00:00
files - > set_icon_mode ( ItemList : : ICON_MODE_LEFT ) ;
files - > set_max_columns ( 1 ) ;
files - > set_max_text_lines ( 1 ) ;
files - > set_fixed_column_width ( 0 ) ;
2016-06-12 19:51:27 +00:00
files - > set_fixed_icon_size ( Size2 ( ) ) ;
2014-10-14 22:44:41 +00:00
}
2014-02-10 01:10:30 +00:00
2021-07-17 21:22:52 +00:00
Ref < Texture2D > folder_icon = ( use_thumbnails ) ? folder_thumbnail : get_theme_icon ( SNAME ( " folder " ) , SNAME ( " FileDialog " ) ) ;
const Color folder_color = get_theme_color ( SNAME ( " folder_icon_modulate " ) , SNAME ( " FileDialog " ) ) ;
2014-02-10 01:10:30 +00:00
2019-08-22 04:22:52 +00:00
// Build the FileInfo list.
2020-10-07 19:56:53 +00:00
List < FileInfo > file_list ;
2018-09-28 22:11:26 +00:00
if ( path = = " Favorites " ) {
2019-08-22 04:22:52 +00:00
// Display the favorites.
2018-09-28 22:11:26 +00:00
Vector < String > favorites = EditorSettings : : get_singleton ( ) - > get_favorites ( ) ;
for ( int i = 0 ; i < favorites . size ( ) ; i + + ) {
String favorite = favorites [ i ] ;
String text ;
2019-06-11 18:43:37 +00:00
Ref < Texture2D > icon ;
2018-09-28 22:11:26 +00:00
if ( favorite = = " res:// " ) {
text = " / " ;
icon = folder_icon ;
if ( searched_string . length ( ) = = 0 | | text . to_lower ( ) . find ( searched_string ) > = 0 ) {
files - > add_item ( text , icon , true ) ;
files - > set_item_metadata ( files - > get_item_count ( ) - 1 , favorite ) ;
}
} else if ( favorite . ends_with ( " / " ) ) {
text = favorite . substr ( 0 , favorite . length ( ) - 1 ) . get_file ( ) ;
icon = folder_icon ;
if ( searched_string . length ( ) = = 0 | | text . to_lower ( ) . find ( searched_string ) > = 0 ) {
files - > add_item ( text , icon , true ) ;
files - > set_item_metadata ( files - > get_item_count ( ) - 1 , favorite ) ;
}
} else {
int index ;
EditorFileSystemDirectory * efd = EditorFileSystem : : get_singleton ( ) - > find_file ( favorite , & index ) ;
FileInfo fi ;
fi . name = favorite . get_file ( ) ;
fi . path = favorite ;
if ( efd ) {
fi . type = efd - > get_file_type ( index ) ;
fi . import_broken = ! efd - > get_file_import_is_valid ( index ) ;
2020-10-22 21:38:41 +00:00
fi . modified_time = efd - > get_file_modified_time ( index ) ;
2018-09-28 22:11:26 +00:00
} else {
fi . type = " " ;
fi . import_broken = true ;
2020-10-22 21:38:41 +00:00
fi . modified_time = 0 ;
2018-09-28 22:11:26 +00:00
}
2016-05-15 23:25:51 +00:00
2018-09-28 22:11:26 +00:00
if ( searched_string . length ( ) = = 0 | | fi . name . to_lower ( ) . find ( searched_string ) > = 0 ) {
2020-10-07 19:56:53 +00:00
file_list . push_back ( fi ) ;
2018-09-28 22:11:26 +00:00
}
}
}
} else {
2019-08-22 04:22:52 +00:00
// Get infos on the directory + file.
2018-09-28 22:11:26 +00:00
if ( directory . ends_with ( " / " ) & & directory ! = " res:// " ) {
directory = directory . substr ( 0 , directory . length ( ) - 1 ) ;
}
EditorFileSystemDirectory * efd = EditorFileSystem : : get_singleton ( ) - > get_filesystem_path ( directory ) ;
if ( ! efd ) {
directory = path . get_base_dir ( ) ;
file = path . get_file ( ) ;
efd = EditorFileSystem : : get_singleton ( ) - > get_filesystem_path ( directory ) ;
2015-08-23 23:15:56 +00:00
}
2020-05-14 14:41:43 +00:00
if ( ! efd ) {
2018-09-28 22:11:26 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2015-08-23 23:15:56 +00:00
2018-09-28 22:11:26 +00:00
if ( searched_string . length ( ) > 0 ) {
2019-08-22 04:22:52 +00:00
// Display the search results.
2021-03-22 13:44:47 +00:00
// Limit the number of results displayed to avoid an infinite loop.
_search ( EditorFileSystem : : get_singleton ( ) - > get_filesystem ( ) , & file_list , 10000 ) ;
2018-09-28 22:11:26 +00:00
} else {
2018-10-16 20:08:00 +00:00
if ( display_mode = = DISPLAY_MODE_TREE_ONLY | | always_show_folders ) {
2019-08-22 04:22:52 +00:00
// Display folders in the list.
2018-09-28 22:11:26 +00:00
if ( directory ! = " res:// " ) {
files - > add_item ( " .. " , folder_icon , true ) ;
2016-05-15 23:25:51 +00:00
2018-09-28 22:11:26 +00:00
String bd = directory . get_base_dir ( ) ;
2020-05-14 14:41:43 +00:00
if ( bd ! = " res:// " & & ! bd . ends_with ( " / " ) ) {
2018-09-28 22:11:26 +00:00
bd + = " / " ;
2020-05-14 14:41:43 +00:00
}
2015-08-23 23:15:56 +00:00
2018-09-28 22:11:26 +00:00
files - > set_item_metadata ( files - > get_item_count ( ) - 1 , bd ) ;
files - > set_item_selectable ( files - > get_item_count ( ) - 1 , false ) ;
2019-08-19 22:08:40 +00:00
files - > set_item_icon_modulate ( files - > get_item_count ( ) - 1 , folder_color ) ;
2018-09-28 22:11:26 +00:00
}
2015-08-23 23:15:56 +00:00
2020-10-22 21:38:41 +00:00
bool reversed = file_sort = = FILE_SORT_NAME_REVERSE ;
for ( int i = reversed ? efd - > get_subdir_count ( ) - 1 : 0 ;
reversed ? i > = 0 : i < efd - > get_subdir_count ( ) ;
reversed ? i - - : i + + ) {
2018-09-28 22:11:26 +00:00
String dname = efd - > get_subdir ( i ) - > get_name ( ) ;
files - > add_item ( dname , folder_icon , true ) ;
files - > set_item_metadata ( files - > get_item_count ( ) - 1 , directory . plus_file ( dname ) + " / " ) ;
2019-08-19 22:08:40 +00:00
files - > set_item_icon_modulate ( files - > get_item_count ( ) - 1 , folder_color ) ;
2018-09-28 22:11:26 +00:00
if ( cselection . has ( dname ) ) {
files - > select ( files - > get_item_count ( ) - 1 , false ) ;
}
}
}
2019-08-22 04:22:52 +00:00
// Display the folder content.
2018-09-28 22:11:26 +00:00
for ( int i = 0 ; i < efd - > get_file_count ( ) ; i + + ) {
FileInfo fi ;
fi . name = efd - > get_file ( i ) ;
fi . path = directory . plus_file ( fi . name ) ;
fi . type = efd - > get_file_type ( i ) ;
fi . import_broken = ! efd - > get_file_import_is_valid ( i ) ;
2020-10-22 21:38:41 +00:00
fi . modified_time = efd - > get_file_modified_time ( i ) ;
2018-09-28 22:11:26 +00:00
2020-10-07 19:56:53 +00:00
file_list . push_back ( fi ) ;
2018-09-28 22:11:26 +00:00
}
2016-05-15 23:25:51 +00:00
}
2020-10-07 19:56:53 +00:00
}
// Sort the file list if needed.
2020-10-22 21:38:41 +00:00
_sort_file_info_list ( file_list ) ;
2015-08-23 23:15:56 +00:00
2019-08-22 04:22:52 +00:00
// Fills the ItemList control node from the FileInfos.
2020-01-07 17:09:31 +00:00
String main_scene = ProjectSettings : : get_singleton ( ) - > get ( " application/run/main_scene " ) ;
2021-07-16 03:45:57 +00:00
for ( FileInfo & E : file_list ) {
FileInfo * finfo = & ( E ) ;
2017-09-03 20:35:18 +00:00
String fname = finfo - > name ;
String fpath = finfo - > path ;
String ftype = finfo - > type ;
2015-08-23 23:15:56 +00:00
2019-06-11 18:43:37 +00:00
Ref < Texture2D > type_icon ;
Ref < Texture2D > big_icon ;
2015-08-23 23:15:56 +00:00
2019-05-05 13:21:38 +00:00
String tooltip = fpath ;
2016-05-27 17:18:40 +00:00
2019-08-22 04:22:52 +00:00
// Select the icons.
2017-09-03 20:35:18 +00:00
if ( ! finfo - > import_broken ) {
2022-02-06 13:12:19 +00:00
type_icon = ( has_theme_icon ( ftype , SNAME ( " EditorIcons " ) ) ) ? get_theme_icon ( ftype , SNAME ( " EditorIcons " ) ) : get_theme_icon ( SNAME ( " Object " ) , SNAME ( " EditorIcons " ) ) ;
2017-09-03 20:35:18 +00:00
big_icon = file_thumbnail ;
2017-08-29 23:17:34 +00:00
} else {
2022-02-06 13:12:19 +00:00
type_icon = get_theme_icon ( SNAME ( " ImportFail " ) , SNAME ( " EditorIcons " ) ) ;
2017-08-29 23:17:34 +00:00
big_icon = file_thumbnail_broken ;
2018-01-06 13:32:21 +00:00
tooltip + = " \n " + TTR ( " Status: Import of file failed. Please fix file and reimport manually. " ) ;
2016-05-27 17:18:40 +00:00
}
2019-08-22 04:22:52 +00:00
// Add the item to the ItemList.
2017-09-03 20:35:18 +00:00
int item_index ;
2015-08-23 23:15:56 +00:00
if ( use_thumbnails ) {
2017-08-29 23:17:34 +00:00
files - > add_item ( fname , big_icon , true ) ;
2017-09-03 20:35:18 +00:00
item_index = files - > get_item_count ( ) - 1 ;
files - > set_item_metadata ( item_index , fpath ) ;
files - > set_item_tag_icon ( item_index , type_icon ) ;
2018-09-28 11:26:36 +00:00
2015-08-23 23:15:56 +00:00
} else {
2017-03-05 15:44:50 +00:00
files - > add_item ( fname , type_icon , true ) ;
2017-09-03 20:35:18 +00:00
item_index = files - > get_item_count ( ) - 1 ;
files - > set_item_metadata ( item_index , fpath ) ;
2015-08-23 23:15:56 +00:00
}
2020-01-07 17:09:31 +00:00
if ( fpath = = main_scene ) {
2021-07-17 21:22:52 +00:00
files - > set_item_custom_fg_color ( item_index , get_theme_color ( SNAME ( " accent_color " ) , SNAME ( " Editor " ) ) ) ;
2020-01-07 17:09:31 +00:00
}
2019-08-22 04:22:52 +00:00
// Generate the preview.
2018-09-28 11:26:36 +00:00
if ( ! finfo - > import_broken ) {
Array udata ;
udata . resize ( 2 ) ;
udata [ 0 ] = item_index ;
udata [ 1 ] = fname ;
EditorResourcePreview : : get_singleton ( ) - > queue_resource_preview ( fpath , this , " _file_list_thumbnail_done " , udata ) ;
}
2019-08-22 04:22:52 +00:00
// Select the items.
2020-05-14 14:41:43 +00:00
if ( cselection . has ( fname ) ) {
2017-09-03 20:35:18 +00:00
files - > select ( item_index , false ) ;
2020-05-14 14:41:43 +00:00
}
2016-05-27 17:18:40 +00:00
2021-12-09 09:42:46 +00:00
if ( ! p_keep_selection & & ! file . is_empty ( ) & & fname = = file ) {
2018-08-23 15:00:30 +00:00
files - > select ( item_index , true ) ;
files - > ensure_current_is_visible ( ) ;
}
2019-08-22 04:22:52 +00:00
// Tooltip.
2017-09-03 20:35:18 +00:00
if ( finfo - > sources . size ( ) ) {
for ( int j = 0 ; j < finfo - > sources . size ( ) ; j + + ) {
tooltip + = " \n Source: " + finfo - > sources [ j ] ;
}
}
files - > set_item_tooltip ( item_index , tooltip ) ;
2015-08-23 23:15:56 +00:00
}
}
2019-07-10 09:54:12 +00:00
void FileSystemDock : : _select_file ( const String & p_path , bool p_select_in_favorites ) {
2018-08-23 15:00:30 +00:00
String fpath = p_path ;
2017-09-03 20:35:18 +00:00
if ( fpath . ends_with ( " / " ) ) {
if ( fpath ! = " res:// " ) {
fpath = fpath . substr ( 0 , fpath . length ( ) - 1 ) ;
2017-10-09 13:59:48 +00:00
}
2018-09-28 22:11:26 +00:00
} else if ( fpath ! = " Favorites " ) {
2021-03-23 14:20:14 +00:00
if ( FileAccess : : exists ( fpath + " .import " ) ) {
Ref < ConfigFile > config ;
2021-06-17 22:03:09 +00:00
config . instantiate ( ) ;
2021-03-23 14:20:14 +00:00
Error err = config - > load ( fpath + " .import " ) ;
if ( err = = OK ) {
if ( config - > has_section_key ( " remap " , " importer " ) ) {
String importer = config - > get_value ( " remap " , " importer " ) ;
if ( importer = = " keep " ) {
EditorNode : : get_singleton ( ) - > show_warning ( TTR ( " Importing has been disabled for this file, so it can't be opened for editing. " ) ) ;
return ;
}
}
}
}
2017-11-01 11:31:13 +00:00
if ( ResourceLoader : : get_resource_type ( fpath ) = = " PackedScene " ) {
2021-03-19 12:57:52 +00:00
bool is_imported = false ;
{
List < String > importer_exts ;
ResourceImporterScene : : get_singleton ( ) - > get_recognized_extensions ( & importer_exts ) ;
String extension = fpath . get_extension ( ) ;
2021-07-24 13:46:25 +00:00
for ( const String & E : importer_exts ) {
2021-07-16 03:45:57 +00:00
if ( extension . nocasecmp_to ( E ) = = 0 ) {
2021-03-19 12:57:52 +00:00
is_imported = true ;
break ;
}
}
}
if ( is_imported ) {
ResourceImporterScene : : get_singleton ( ) - > show_advanced_options ( fpath ) ;
} else {
editor - > open_request ( fpath ) ;
}
2017-10-09 13:59:48 +00:00
} else {
2017-11-01 11:31:13 +00:00
editor - > load_resource ( fpath ) ;
2017-10-09 13:59:48 +00:00
}
}
2019-01-17 19:40:38 +00:00
_navigate_to_path ( fpath , p_select_in_favorites ) ;
2015-08-23 23:15:56 +00:00
}
2018-08-23 15:00:30 +00:00
void FileSystemDock : : _tree_activate_file ( ) {
TreeItem * selected = tree - > get_selected ( ) ;
if ( selected ) {
2019-01-17 19:40:38 +00:00
String path = selected - > get_metadata ( 0 ) ;
TreeItem * parent = selected - > get_parent ( ) ;
2020-04-01 23:20:12 +00:00
bool is_favorite = parent ! = nullptr & & parent - > get_metadata ( 0 ) = = " Favorites " ;
2018-08-23 15:00:30 +00:00
2019-01-17 19:40:38 +00:00
if ( ( ! is_favorite & & path . ends_with ( " / " ) ) | | path = = " Favorites " ) {
2018-09-28 22:11:26 +00:00
bool collapsed = selected - > is_collapsed ( ) ;
selected - > set_collapsed ( ! collapsed ) ;
2019-01-17 19:40:38 +00:00
} else {
_select_file ( path , is_favorite & & ! path . ends_with ( " / " ) ) ;
2018-09-28 22:11:26 +00:00
}
2017-09-03 20:35:18 +00:00
}
2018-08-13 17:05:31 +00:00
}
2018-08-23 15:00:30 +00:00
2018-10-16 20:08:00 +00:00
void FileSystemDock : : _file_list_activate_file ( int p_idx ) {
_select_file ( files - > get_item_metadata ( p_idx ) ) ;
2015-08-23 23:15:56 +00:00
}
2017-03-05 15:44:50 +00:00
void FileSystemDock : : _preview_invalidated ( const String & p_path ) {
2018-09-13 19:49:56 +00:00
if ( file_list_display_mode = = FILE_LIST_DISPLAY_THUMBNAILS & & p_path . get_base_dir ( ) = = path & & searched_string . length ( ) = = 0 & & file_list_vb - > is_visible_in_tree ( ) ) {
2017-03-05 15:44:50 +00:00
for ( int i = 0 ; i < files - > get_item_count ( ) ; i + + ) {
if ( files - > get_item_metadata ( i ) = = p_path ) {
2019-08-22 04:22:52 +00:00
// Re-request preview.
2016-07-03 16:15:15 +00:00
Array udata ;
udata . resize ( 2 ) ;
2017-03-05 15:44:50 +00:00
udata [ 0 ] = i ;
udata [ 1 ] = files - > get_item_text ( i ) ;
2018-09-12 11:10:49 +00:00
EditorResourcePreview : : get_singleton ( ) - > queue_resource_preview ( p_path , this , " _file_list_thumbnail_done " , udata ) ;
2016-07-03 16:15:15 +00:00
break ;
}
}
}
}
2016-07-21 13:34:57 +00:00
void FileSystemDock : : _fs_changed ( ) {
2017-03-05 15:44:50 +00:00
button_hist_prev - > set_disabled ( history_pos = = 0 ) ;
2017-09-03 20:35:18 +00:00
button_hist_next - > set_disabled ( history_pos = = history . size ( ) - 1 ) ;
2015-08-23 23:15:56 +00:00
scanning_vb - > hide ( ) ;
2016-05-15 23:25:51 +00:00
split_box - > show ( ) ;
2015-08-23 23:15:56 +00:00
2017-01-13 13:45:50 +00:00
if ( tree - > is_visible ( ) ) {
2018-09-13 21:28:21 +00:00
_update_tree ( _compute_uncollapsed_paths ( ) ) ;
2016-05-15 23:25:51 +00:00
}
2017-01-13 13:45:50 +00:00
if ( file_list_vb - > is_visible ( ) ) {
2018-09-28 11:26:36 +00:00
_update_file_list ( true ) ;
2015-08-23 23:15:56 +00:00
}
set_process ( false ) ;
}
2017-01-21 12:07:29 +00:00
void FileSystemDock : : _set_scanning_mode ( ) {
2015-08-23 23:15:56 +00:00
button_hist_prev - > set_disabled ( true ) ;
button_hist_next - > set_disabled ( true ) ;
2017-09-03 20:35:18 +00:00
split_box - > hide ( ) ;
2015-08-23 23:15:56 +00:00
scanning_vb - > show ( ) ;
set_process ( true ) ;
if ( EditorFileSystem : : get_singleton ( ) - > is_scanning ( ) ) {
2017-03-05 15:44:50 +00:00
scanning_progress - > set_value ( EditorFileSystem : : get_singleton ( ) - > get_scanning_progress ( ) * 100 ) ;
2015-08-23 23:15:56 +00:00
} else {
2017-01-04 04:16:14 +00:00
scanning_progress - > set_value ( 0 ) ;
2015-08-23 23:15:56 +00:00
}
}
2016-07-21 13:34:57 +00:00
void FileSystemDock : : _fw_history ( ) {
2020-05-14 14:41:43 +00:00
if ( history_pos < history . size ( ) - 1 ) {
2015-08-23 23:15:56 +00:00
history_pos + + ;
2020-05-14 14:41:43 +00:00
}
2015-08-23 23:15:56 +00:00
2017-09-03 20:35:18 +00:00
_update_history ( ) ;
2015-08-23 23:15:56 +00:00
}
2016-07-21 13:34:57 +00:00
void FileSystemDock : : _bw_history ( ) {
2020-05-14 14:41:43 +00:00
if ( history_pos > 0 ) {
2015-08-23 23:15:56 +00:00
history_pos - - ;
2020-05-14 14:41:43 +00:00
}
2015-08-23 23:15:56 +00:00
2017-09-03 20:35:18 +00:00
_update_history ( ) ;
}
void FileSystemDock : : _update_history ( ) {
2017-03-05 15:44:50 +00:00
path = history [ history_pos ] ;
2018-09-28 22:11:26 +00:00
_set_current_path_text ( path ) ;
2016-05-15 23:25:51 +00:00
2017-01-13 13:45:50 +00:00
if ( tree - > is_visible ( ) ) {
2018-09-13 21:28:21 +00:00
_update_tree ( _compute_uncollapsed_paths ( ) ) ;
2015-08-23 23:15:56 +00:00
tree - > grab_focus ( ) ;
tree - > ensure_cursor_is_visible ( ) ;
2016-05-15 23:25:51 +00:00
}
2017-01-13 13:45:50 +00:00
if ( file_list_vb - > is_visible ( ) ) {
2018-09-28 11:26:36 +00:00
_update_file_list ( false ) ;
2015-08-23 23:15:56 +00:00
}
2017-03-05 15:44:50 +00:00
button_hist_prev - > set_disabled ( history_pos = = 0 ) ;
2017-09-03 20:35:18 +00:00
button_hist_next - > set_disabled ( history_pos = = history . size ( ) - 1 ) ;
2015-08-23 23:15:56 +00:00
}
2016-07-21 13:34:57 +00:00
void FileSystemDock : : _push_to_history ( ) {
2017-03-05 15:44:50 +00:00
if ( history [ history_pos ] ! = path ) {
2017-09-03 20:35:18 +00:00
history . resize ( history_pos + 1 ) ;
2015-08-23 23:15:56 +00:00
history . push_back ( path ) ;
history_pos + + ;
2017-09-03 20:35:18 +00:00
if ( history . size ( ) > history_max_size ) {
2021-07-03 22:17:03 +00:00
history . remove_at ( 0 ) ;
2017-09-03 20:35:18 +00:00
history_pos = history_max_size - 1 ;
}
2015-08-23 23:15:56 +00:00
}
2017-03-05 15:44:50 +00:00
button_hist_prev - > set_disabled ( history_pos = = 0 ) ;
2017-09-03 20:35:18 +00:00
button_hist_next - > set_disabled ( history_pos = = history . size ( ) - 1 ) ;
2015-08-23 23:15:56 +00:00
}
2018-02-28 23:14:12 +00:00
void FileSystemDock : : _get_all_items_in_dir ( EditorFileSystemDirectory * efsd , Vector < String > & files , Vector < String > & folders ) const {
2020-05-14 14:41:43 +00:00
if ( efsd = = nullptr ) {
2017-10-01 21:59:27 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2015-08-23 23:15:56 +00:00
2017-03-05 15:44:50 +00:00
for ( int i = 0 ; i < efsd - > get_subdir_count ( ) ; i + + ) {
2018-02-28 23:14:12 +00:00
folders . push_back ( efsd - > get_subdir ( i ) - > get_path ( ) ) ;
_get_all_items_in_dir ( efsd - > get_subdir ( i ) , files , folders ) ;
2015-08-23 23:15:56 +00:00
}
2017-03-05 15:44:50 +00:00
for ( int i = 0 ; i < efsd - > get_file_count ( ) ; i + + ) {
2015-08-23 23:15:56 +00:00
files . push_back ( efsd - > get_file_path ( i ) ) ;
}
}
2014-02-10 01:10:30 +00:00
2017-10-01 21:59:27 +00:00
void FileSystemDock : : _find_remaps ( EditorFileSystemDirectory * efsd , const Map < String , String > & renames , Vector < String > & to_remaps ) const {
2017-03-05 15:44:50 +00:00
for ( int i = 0 ; i < efsd - > get_subdir_count ( ) ; i + + ) {
_find_remaps ( efsd - > get_subdir ( i ) , renames , to_remaps ) ;
2015-08-23 23:15:56 +00:00
}
2017-03-05 15:44:50 +00:00
for ( int i = 0 ; i < efsd - > get_file_count ( ) ; i + + ) {
Vector < String > deps = efsd - > get_file_deps ( i ) ;
for ( int j = 0 ; j < deps . size ( ) ; j + + ) {
2015-08-23 23:15:56 +00:00
if ( renames . has ( deps [ j ] ) ) {
to_remaps . push_back ( efsd - > get_file_path ( i ) ) ;
break ;
}
}
}
}
2018-02-28 23:14:12 +00:00
void FileSystemDock : : _try_move_item ( const FileOrFolder & p_item , const String & p_new_path ,
2018-11-13 19:17:33 +00:00
Map < String , String > & p_file_renames , Map < String , String > & p_folder_renames ) {
2019-08-22 04:22:52 +00:00
// Ensure folder paths end with "/".
2017-10-01 21:59:27 +00:00
String old_path = ( p_item . is_file | | p_item . path . ends_with ( " / " ) ) ? p_item . path : ( p_item . path + " / " ) ;
String new_path = ( p_item . is_file | | p_new_path . ends_with ( " / " ) ) ? p_new_path : ( p_new_path + " / " ) ;
2015-08-23 23:15:56 +00:00
2017-10-01 21:59:27 +00:00
if ( new_path = = old_path ) {
2015-08-23 23:15:56 +00:00
return ;
2017-10-01 21:59:27 +00:00
} else if ( old_path = = " res:// " ) {
EditorNode : : get_singleton ( ) - > add_io_error ( TTR ( " Cannot move/rename resources root. " ) ) ;
return ;
} else if ( ! p_item . is_file & & new_path . begins_with ( old_path ) ) {
2019-08-22 04:22:52 +00:00
// This check doesn't erroneously catch renaming to a longer name as folder paths always end with "/".
2018-01-04 19:00:39 +00:00
EditorNode : : get_singleton ( ) - > add_io_error ( TTR ( " Cannot move a folder into itself. " ) + " \n " + old_path + " \n " ) ;
2015-08-23 23:15:56 +00:00
return ;
}
2019-08-22 04:22:52 +00:00
// Build a list of files which will have new paths as a result of this operation.
2018-02-28 23:14:12 +00:00
Vector < String > file_changed_paths ;
Vector < String > folder_changed_paths ;
2017-10-01 21:59:27 +00:00
if ( p_item . is_file ) {
2018-02-28 23:14:12 +00:00
file_changed_paths . push_back ( old_path ) ;
2017-10-01 21:59:27 +00:00
} else {
2018-02-28 23:14:12 +00:00
folder_changed_paths . push_back ( old_path ) ;
_get_all_items_in_dir ( EditorFileSystem : : get_singleton ( ) - > get_filesystem_path ( old_path ) , file_changed_paths , folder_changed_paths ) ;
2015-08-23 23:15:56 +00:00
}
2017-03-05 15:44:50 +00:00
DirAccess * da = DirAccess : : create ( DirAccess : : ACCESS_RESOURCES ) ;
2018-08-24 07:35:07 +00:00
print_verbose ( " Moving " + old_path + " -> " + new_path ) ;
2017-10-01 21:59:27 +00:00
Error err = da - > rename ( old_path , new_path ) ;
if ( err = = OK ) {
2019-08-22 04:22:52 +00:00
// Move/Rename any corresponding import settings too.
2017-10-01 21:59:27 +00:00
if ( p_item . is_file & & FileAccess : : exists ( old_path + " .import " ) ) {
err = da - > rename ( old_path + " .import " , new_path + " .import " ) ;
if ( err ! = OK ) {
2018-01-04 19:00:39 +00:00
EditorNode : : get_singleton ( ) - > add_io_error ( TTR ( " Error moving: " ) + " \n " + old_path + " .import \n " ) ;
2017-10-01 21:59:27 +00:00
}
}
2015-08-23 23:15:56 +00:00
2019-08-22 04:22:52 +00:00
// Update scene if it is open.
2018-02-28 23:14:12 +00:00
for ( int i = 0 ; i < file_changed_paths . size ( ) ; + + i ) {
String new_item_path = p_item . is_file ? new_path : file_changed_paths [ i ] . replace_first ( old_path , new_path ) ;
if ( ResourceLoader : : get_resource_type ( new_item_path ) = = " PackedScene " & & editor - > is_scene_open ( file_changed_paths [ i ] ) ) {
2017-11-29 00:48:09 +00:00
EditorData * ed = & editor - > get_editor_data ( ) ;
for ( int j = 0 ; j < ed - > get_edited_scene_count ( ) ; j + + ) {
2018-02-28 23:14:12 +00:00
if ( ed - > get_scene_path ( j ) = = file_changed_paths [ i ] ) {
2021-09-30 14:30:55 +00:00
ed - > get_edited_scene_root ( j ) - > set_scene_file_path ( new_item_path ) ;
2019-04-15 20:17:49 +00:00
editor - > save_layout ( ) ;
2017-11-29 00:48:09 +00:00
break ;
}
}
}
}
2019-08-22 04:22:52 +00:00
// Only treat as a changed dependency if it was successfully moved.
2018-02-28 23:14:12 +00:00
for ( int i = 0 ; i < file_changed_paths . size ( ) ; + + i ) {
p_file_renames [ file_changed_paths [ i ] ] = file_changed_paths [ i ] . replace_first ( old_path , new_path ) ;
2018-08-24 07:35:07 +00:00
print_verbose ( " Remap: " + file_changed_paths [ i ] + " -> " + p_file_renames [ file_changed_paths [ i ] ] ) ;
2021-07-17 21:22:52 +00:00
emit_signal ( SNAME ( " files_moved " ) , file_changed_paths [ i ] , p_file_renames [ file_changed_paths [ i ] ] ) ;
2018-02-28 23:14:12 +00:00
}
for ( int i = 0 ; i < folder_changed_paths . size ( ) ; + + i ) {
p_folder_renames [ folder_changed_paths [ i ] ] = folder_changed_paths [ i ] . replace_first ( old_path , new_path ) ;
2021-07-17 21:22:52 +00:00
emit_signal ( SNAME ( " folder_moved " ) , folder_changed_paths [ i ] , p_folder_renames [ folder_changed_paths [ i ] ] . substr ( 0 , p_folder_renames [ folder_changed_paths [ i ] ] . length ( ) - 1 ) ) ;
2017-10-01 21:59:27 +00:00
}
} else {
2018-01-04 19:00:39 +00:00
EditorNode : : get_singleton ( ) - > add_io_error ( TTR ( " Error moving: " ) + " \n " + old_path + " \n " ) ;
2015-08-23 23:15:56 +00:00
}
memdelete ( da ) ;
}
2017-12-01 11:13:50 +00:00
void FileSystemDock : : _try_duplicate_item ( const FileOrFolder & p_item , const String & p_new_path ) const {
2019-08-22 04:22:52 +00:00
// Ensure folder paths end with "/".
2017-12-01 11:13:50 +00:00
String old_path = ( p_item . is_file | | p_item . path . ends_with ( " / " ) ) ? p_item . path : ( p_item . path + " / " ) ;
String new_path = ( p_item . is_file | | p_new_path . ends_with ( " / " ) ) ? p_new_path : ( p_new_path + " / " ) ;
if ( new_path = = old_path ) {
return ;
} else if ( old_path = = " res:// " ) {
EditorNode : : get_singleton ( ) - > add_io_error ( TTR ( " Cannot move/rename resources root. " ) ) ;
return ;
} else if ( ! p_item . is_file & & new_path . begins_with ( old_path ) ) {
2019-08-22 04:22:52 +00:00
// This check doesn't erroneously catch renaming to a longer name as folder paths always end with "/".
2018-01-04 19:00:39 +00:00
EditorNode : : get_singleton ( ) - > add_io_error ( TTR ( " Cannot move a folder into itself. " ) + " \n " + old_path + " \n " ) ;
2017-12-01 11:13:50 +00:00
return ;
}
DirAccess * da = DirAccess : : create ( DirAccess : : ACCESS_RESOURCES ) ;
2018-08-24 07:35:07 +00:00
print_verbose ( " Duplicating " + old_path + " -> " + new_path ) ;
2017-12-31 17:10:03 +00:00
Error err = p_item . is_file ? da - > copy ( old_path , new_path ) : da - > copy_dir ( old_path , new_path ) ;
2017-12-01 11:13:50 +00:00
if ( err = = OK ) {
2019-08-22 04:22:52 +00:00
// Move/Rename any corresponding import settings too.
2017-12-01 11:13:50 +00:00
if ( p_item . is_file & & FileAccess : : exists ( old_path + " .import " ) ) {
err = da - > copy ( old_path + " .import " , new_path + " .import " ) ;
if ( err ! = OK ) {
2018-01-04 19:00:39 +00:00
EditorNode : : get_singleton ( ) - > add_io_error ( TTR ( " Error duplicating: " ) + " \n " + old_path + " .import \n " ) ;
2017-12-01 11:13:50 +00:00
}
2021-12-03 11:54:57 +00:00
// Remove uid from .import file to avoid conflict.
Ref < ConfigFile > cfg ;
cfg . instantiate ( ) ;
cfg - > load ( new_path + " .import " ) ;
cfg - > erase_section_key ( " remap " , " uid " ) ;
cfg - > save ( new_path + " .import " ) ;
} else if ( p_item . is_file & & ( old_path . get_extension ( ) = = " tscn " | | old_path . get_extension ( ) = = " tres " ) ) {
// FIXME: Quick hack to fix text resources. This should be fixed properly.
FileAccessRef file = FileAccess : : open ( old_path , FileAccess : : READ , & err ) ;
if ( err = = OK ) {
PackedStringArray lines = file - > get_as_utf8_string ( ) . split ( " \n " ) ;
String line = lines [ 0 ] ;
if ( line . contains ( " uid " ) ) {
line = line . substr ( 0 , line . find ( " uid " ) ) + " ] " ;
lines . write [ 0 ] = line ;
FileAccessRef file2 = FileAccess : : open ( new_path , FileAccess : : WRITE , & err ) ;
if ( err = = OK ) {
file2 - > store_string ( String ( " \n " ) . join ( lines ) ) ;
}
}
}
2017-12-01 11:13:50 +00:00
}
} else {
2018-01-04 19:00:39 +00:00
EditorNode : : get_singleton ( ) - > add_io_error ( TTR ( " Error duplicating: " ) + " \n " + old_path + " \n " ) ;
2017-12-01 11:13:50 +00:00
}
memdelete ( da ) ;
}
2017-12-26 19:32:12 +00:00
void FileSystemDock : : _update_resource_paths_after_move ( const Map < String , String > & p_renames ) const {
2019-08-22 04:22:52 +00:00
// Rename all resources loaded, be it subresources or actual resources.
2020-03-17 06:33:00 +00:00
List < Ref < Resource > > cached ;
2017-12-26 19:32:12 +00:00
ResourceCache : : get_cached_resources ( & cached ) ;
2021-07-26 15:50:35 +00:00
for ( Ref < Resource > & r : cached ) {
2017-12-26 19:32:12 +00:00
String base_path = r - > get_path ( ) ;
String extra_path ;
int sep_pos = r - > get_path ( ) . find ( " :: " ) ;
if ( sep_pos > = 0 ) {
extra_path = base_path . substr ( sep_pos , base_path . length ( ) ) ;
base_path = base_path . substr ( 0 , sep_pos ) ;
}
if ( p_renames . has ( base_path ) ) {
base_path = p_renames [ base_path ] ;
}
r - > set_path ( base_path + extra_path ) ;
}
for ( int i = 0 ; i < EditorNode : : get_editor_data ( ) . get_edited_scene_count ( ) ; i + + ) {
String path ;
if ( i = = EditorNode : : get_editor_data ( ) . get_edited_scene ( ) ) {
2020-05-14 14:41:43 +00:00
if ( ! get_tree ( ) - > get_edited_scene_root ( ) ) {
2017-12-26 19:32:12 +00:00
continue ;
2020-05-14 14:41:43 +00:00
}
2017-12-26 19:32:12 +00:00
2021-09-30 14:30:55 +00:00
path = get_tree ( ) - > get_edited_scene_root ( ) - > get_scene_file_path ( ) ;
2017-12-26 19:32:12 +00:00
} else {
path = EditorNode : : get_editor_data ( ) . get_scene_path ( i ) ;
}
if ( p_renames . has ( path ) ) {
path = p_renames [ path ] ;
}
if ( i = = EditorNode : : get_editor_data ( ) . get_edited_scene ( ) ) {
2021-09-30 14:30:55 +00:00
get_tree ( ) - > get_edited_scene_root ( ) - > set_scene_file_path ( path ) ;
2017-12-26 19:32:12 +00:00
} else {
EditorNode : : get_editor_data ( ) . set_scene_path ( i , path ) ;
}
}
}
2017-10-01 21:59:27 +00:00
void FileSystemDock : : _update_dependencies_after_move ( const Map < String , String > & p_renames ) const {
2019-08-22 04:22:52 +00:00
// The following code assumes that the following holds:
2017-10-01 21:59:27 +00:00
// 1) EditorFileSystem contains the old paths/folder structure from before the rename/move.
// 2) ResourceLoader can use the new paths without needing to call rescan.
Vector < String > remaps ;
_find_remaps ( EditorFileSystem : : get_singleton ( ) - > get_filesystem ( ) , p_renames , remaps ) ;
for ( int i = 0 ; i < remaps . size ( ) ; + + i ) {
2019-08-22 04:22:52 +00:00
// Because we haven't called a rescan yet the found remap might still be an old path itself.
2017-10-01 21:59:27 +00:00
String file = p_renames . has ( remaps [ i ] ) ? p_renames [ remaps [ i ] ] : remaps [ i ] ;
2018-08-24 07:35:07 +00:00
print_verbose ( " Remapping dependencies for: " + file ) ;
2017-10-01 21:59:27 +00:00
Error err = ResourceLoader : : rename_dependencies ( file , p_renames ) ;
2017-11-29 00:48:09 +00:00
if ( err = = OK ) {
2020-05-14 14:41:43 +00:00
if ( ResourceLoader : : get_resource_type ( file ) = = " PackedScene " ) {
2017-11-29 00:48:09 +00:00
editor - > reload_scene ( file ) ;
2020-05-14 14:41:43 +00:00
}
2017-11-29 00:48:09 +00:00
} else {
2018-01-04 19:00:39 +00:00
EditorNode : : get_singleton ( ) - > add_io_error ( TTR ( " Unable to update dependencies: " ) + " \n " + remaps [ i ] + " \n " ) ;
2015-08-23 23:15:56 +00:00
}
2017-09-03 03:22:54 +00:00
}
2017-10-01 21:59:27 +00:00
}
2017-09-03 03:22:54 +00:00
2018-05-26 18:19:38 +00:00
void FileSystemDock : : _update_project_settings_after_move ( const Map < String , String > & p_renames ) const {
2019-08-22 04:22:52 +00:00
// Find all project settings of type FILE and replace them if needed.
2018-05-26 18:19:38 +00:00
const Map < StringName , PropertyInfo > prop_info = ProjectSettings : : get_singleton ( ) - > get_custom_property_info ( ) ;
2021-08-09 20:13:42 +00:00
for ( const KeyValue < StringName , PropertyInfo > & E : prop_info ) {
if ( E . value . hint = = PROPERTY_HINT_FILE ) {
String old_path = GLOBAL_GET ( E . key ) ;
2018-05-26 18:19:38 +00:00
if ( p_renames . has ( old_path ) ) {
2021-08-09 20:13:42 +00:00
ProjectSettings : : get_singleton ( ) - > set_setting ( E . key , p_renames [ old_path ] ) ;
2018-05-26 18:19:38 +00:00
}
} ;
}
2018-10-14 05:05:53 +00:00
// Also search for the file in autoload, as they are stored differently from normal files.
List < PropertyInfo > property_list ;
ProjectSettings : : get_singleton ( ) - > get_property_list ( & property_list ) ;
2021-07-16 03:45:57 +00:00
for ( const PropertyInfo & E : property_list ) {
if ( E . name . begins_with ( " autoload/ " ) ) {
2018-10-14 05:05:53 +00:00
// If the autoload resource paths has a leading "*", it indicates that it is a Singleton,
// so we have to handle both cases when updating.
2021-07-16 03:45:57 +00:00
String autoload = GLOBAL_GET ( E . name ) ;
2018-10-14 05:05:53 +00:00
String autoload_singleton = autoload . substr ( 1 , autoload . length ( ) ) ;
if ( p_renames . has ( autoload ) ) {
2021-07-16 03:45:57 +00:00
ProjectSettings : : get_singleton ( ) - > set_setting ( E . name , p_renames [ autoload ] ) ;
2018-10-14 05:05:53 +00:00
} else if ( autoload . begins_with ( " * " ) & & p_renames . has ( autoload_singleton ) ) {
2021-07-16 03:45:57 +00:00
ProjectSettings : : get_singleton ( ) - > set_setting ( E . name , " * " + p_renames [ autoload_singleton ] ) ;
2018-10-14 05:05:53 +00:00
}
}
}
2018-05-26 18:19:38 +00:00
ProjectSettings : : get_singleton ( ) - > save ( ) ;
}
2018-09-18 12:02:59 +00:00
void FileSystemDock : : _update_favorites_list_after_move ( const Map < String , String > & p_files_renames , const Map < String , String > & p_folders_renames ) const {
Vector < String > favorites = EditorSettings : : get_singleton ( ) - > get_favorites ( ) ;
Vector < String > new_favorites ;
2018-02-28 23:14:12 +00:00
2018-09-18 12:02:59 +00:00
for ( int i = 0 ; i < favorites . size ( ) ; i + + ) {
String old_path = favorites [ i ] ;
if ( p_folders_renames . has ( old_path ) ) {
new_favorites . push_back ( p_folders_renames [ old_path ] ) ;
} else if ( p_files_renames . has ( old_path ) ) {
new_favorites . push_back ( p_files_renames [ old_path ] ) ;
2018-02-28 23:14:12 +00:00
} else {
2018-09-18 12:02:59 +00:00
new_favorites . push_back ( old_path ) ;
2018-02-28 23:14:12 +00:00
}
}
2018-09-18 12:02:59 +00:00
EditorSettings : : get_singleton ( ) - > set_favorites ( new_favorites ) ;
2018-02-28 23:14:12 +00:00
}
2019-06-04 03:36:23 +00:00
void FileSystemDock : : _save_scenes_after_move ( const Map < String , String > & p_renames ) const {
Vector < String > remaps ;
_find_remaps ( EditorFileSystem : : get_singleton ( ) - > get_filesystem ( ) , p_renames , remaps ) ;
Vector < String > new_filenames ;
for ( int i = 0 ; i < remaps . size ( ) ; + + i ) {
String file = p_renames . has ( remaps [ i ] ) ? p_renames [ remaps [ i ] ] : remaps [ i ] ;
if ( ResourceLoader : : get_resource_type ( file ) = = " PackedScene " ) {
new_filenames . push_back ( file ) ;
}
}
editor - > save_scene_list ( new_filenames ) ;
}
2017-10-01 22:33:43 +00:00
void FileSystemDock : : _make_dir_confirm ( ) {
String dir_name = make_dir_dialog_text - > get_text ( ) . strip_edges ( ) ;
if ( dir_name . length ( ) = = 0 ) {
2018-12-17 23:03:25 +00:00
EditorNode : : get_singleton ( ) - > show_warning ( TTR ( " No name provided. " ) ) ;
2017-10-01 22:33:43 +00:00
return ;
2022-02-03 16:03:38 +00:00
} else if ( dir_name . contains ( " / " ) | | dir_name . contains ( " \\ " ) | | dir_name . contains ( " : " ) | | dir_name . contains ( " * " ) | |
dir_name . contains ( " | " ) | | dir_name . contains ( " > " ) | | dir_name . ends_with ( " . " ) | | dir_name . ends_with ( " " ) ) {
2019-03-25 00:54:29 +00:00
EditorNode : : get_singleton ( ) - > show_warning ( TTR ( " Provided name contains invalid characters. " ) ) ;
2017-10-01 22:33:43 +00:00
return ;
}
2018-08-23 15:00:30 +00:00
String directory = path ;
if ( ! directory . ends_with ( " / " ) ) {
directory = directory . get_base_dir ( ) ;
}
print_verbose ( " Making folder " + dir_name + " in " + directory ) ;
2017-10-01 22:33:43 +00:00
DirAccess * da = DirAccess : : create ( DirAccess : : ACCESS_RESOURCES ) ;
2018-08-23 15:00:30 +00:00
Error err = da - > change_dir ( directory ) ;
2017-10-01 22:33:43 +00:00
if ( err = = OK ) {
err = da - > make_dir ( dir_name ) ;
}
memdelete ( da ) ;
if ( err = = OK ) {
2018-08-24 07:35:07 +00:00
print_verbose ( " FileSystem: calling rescan. " ) ;
2017-10-01 22:33:43 +00:00
_rescan ( ) ;
} else {
EditorNode : : get_singleton ( ) - > show_warning ( TTR ( " Could not create folder. " ) ) ;
}
}
2019-08-15 17:47:21 +00:00
void FileSystemDock : : _make_scene_confirm ( ) {
String scene_name = make_scene_dialog_text - > get_text ( ) . strip_edges ( ) ;
if ( scene_name . length ( ) = = 0 ) {
EditorNode : : get_singleton ( ) - > show_warning ( TTR ( " No name provided. " ) ) ;
return ;
}
String directory = path ;
if ( ! directory . ends_with ( " / " ) ) {
directory = directory . get_base_dir ( ) ;
}
String extension = scene_name . get_extension ( ) ;
List < String > extensions ;
Ref < PackedScene > sd = memnew ( PackedScene ) ;
ResourceSaver : : get_recognized_extensions ( sd , & extensions ) ;
bool extension_correct = false ;
2021-07-24 13:46:25 +00:00
for ( const String & E : extensions ) {
2021-07-16 03:45:57 +00:00
if ( E = = extension ) {
2019-08-15 17:47:21 +00:00
extension_correct = true ;
break ;
}
}
2020-05-14 14:41:43 +00:00
if ( ! extension_correct ) {
2019-08-15 17:47:21 +00:00
scene_name = scene_name . get_basename ( ) + " .tscn " ;
2020-05-14 14:41:43 +00:00
}
2019-08-15 17:47:21 +00:00
scene_name = directory . plus_file ( scene_name ) ;
DirAccess * da = DirAccess : : create ( DirAccess : : ACCESS_RESOURCES ) ;
if ( da - > file_exists ( scene_name ) ) {
EditorNode : : get_singleton ( ) - > show_warning ( TTR ( " A file or folder with this name already exists. " ) ) ;
memdelete ( da ) ;
return ;
}
memdelete ( da ) ;
int idx = editor - > new_scene ( ) ;
editor - > get_editor_data ( ) . set_scene_path ( idx , scene_name ) ;
}
2020-03-17 00:40:15 +00:00
void FileSystemDock : : _file_removed ( String p_file ) {
2021-07-17 21:22:52 +00:00
emit_signal ( SNAME ( " file_removed " ) , p_file ) ;
2021-01-16 15:30:56 +00:00
2021-02-09 14:40:55 +00:00
// Find the closest parent directory available, in case multiple items were deleted along the same path.
path = p_file . get_base_dir ( ) ;
DirAccessRef da = DirAccess : : create ( DirAccess : : ACCESS_RESOURCES ) ;
while ( ! da - > dir_exists ( path ) ) {
path = path . get_base_dir ( ) ;
}
2021-01-16 15:30:56 +00:00
current_path - > set_text ( path ) ;
2018-11-13 19:17:33 +00:00
}
2020-03-17 00:40:15 +00:00
void FileSystemDock : : _folder_removed ( String p_folder ) {
2021-07-17 21:22:52 +00:00
emit_signal ( SNAME ( " folder_removed " ) , p_folder ) ;
2021-01-16 15:30:56 +00:00
2021-02-09 14:40:55 +00:00
// Find the closest parent directory available, in case multiple items were deleted along the same path.
path = p_folder . get_base_dir ( ) ;
DirAccessRef da = DirAccess : : create ( DirAccess : : ACCESS_RESOURCES ) ;
while ( ! da - > dir_exists ( path ) ) {
path = path . get_base_dir ( ) ;
}
2021-01-16 15:30:56 +00:00
current_path - > set_text ( path ) ;
2021-02-27 20:43:26 +00:00
EditorFileSystemDirectory * efd = EditorFileSystem : : get_singleton ( ) - > get_filesystem_path ( path ) ;
if ( efd ) {
efd - > force_update ( ) ;
}
2018-11-13 19:17:33 +00:00
}
2017-10-01 21:59:27 +00:00
void FileSystemDock : : _rename_operation_confirm ( ) {
String new_name = rename_dialog_text - > get_text ( ) . strip_edges ( ) ;
2022-01-16 18:08:40 +00:00
String old_name = tree - > get_selected ( ) - > get_text ( 0 ) ;
2017-10-01 21:59:27 +00:00
if ( new_name . length ( ) = = 0 ) {
EditorNode : : get_singleton ( ) - > show_warning ( TTR ( " No name provided. " ) ) ;
return ;
2022-02-03 16:03:38 +00:00
} else if ( new_name . contains ( " / " ) | | new_name . contains ( " \\ " ) | | new_name . contains ( " : " ) ) {
2017-10-01 21:59:27 +00:00
EditorNode : : get_singleton ( ) - > show_warning ( TTR ( " Name contains invalid characters. " ) ) ;
return ;
2022-01-16 18:08:40 +00:00
} else if ( to_rename . is_file & & old_name . get_extension ( ) ! = new_name . get_extension ( ) ) {
if ( ! EditorFileSystem : : get_singleton ( ) - > get_valid_extensions ( ) . find ( new_name . get_extension ( ) ) ) {
EditorNode : : get_singleton ( ) - > show_warning ( TTR ( " This file extension is not recognized by the editor. \n If you want to rename it anyway, use your operating system's file manager. \n After renaming to an unknown extension, the file won't be shown in the editor anymore. " ) ) ;
return ;
}
2015-08-23 23:15:56 +00:00
}
2017-10-01 21:59:27 +00:00
String old_path = to_rename . path . ends_with ( " / " ) ? to_rename . path . substr ( 0 , to_rename . path . length ( ) - 1 ) : to_rename . path ;
String new_path = old_path . get_base_dir ( ) . plus_file ( new_name ) ;
if ( old_path = = new_path ) {
return ;
2015-08-23 23:15:56 +00:00
}
2019-04-19 18:54:33 +00:00
if ( EditorFileSystem : : get_singleton ( ) - > is_group_file ( old_path ) ) {
EditorFileSystem : : get_singleton ( ) - > move_group_file ( old_path , new_path ) ;
}
2019-08-22 04:22:52 +00:00
// Present a more user friendly warning for name conflict.
2017-03-05 15:44:50 +00:00
DirAccess * da = DirAccess : : create ( DirAccess : : ACCESS_RESOURCES ) ;
2018-01-22 02:04:16 +00:00
# if defined(WINDOWS_ENABLED) || defined(UWP_ENABLED)
2019-08-22 04:22:52 +00:00
// Workaround case insensitivity on Windows.
2018-01-22 02:04:16 +00:00
if ( ( da - > file_exists ( new_path ) | | da - > dir_exists ( new_path ) ) & & new_path . to_lower ( ) ! = old_path . to_lower ( ) ) {
# else
2017-10-01 21:59:27 +00:00
if ( da - > file_exists ( new_path ) | | da - > dir_exists ( new_path ) ) {
2018-01-22 02:04:16 +00:00
# endif
2017-10-01 21:59:27 +00:00
EditorNode : : get_singleton ( ) - > show_warning ( TTR ( " A file or folder with this name already exists. " ) ) ;
memdelete ( da ) ;
return ;
2015-08-23 23:15:56 +00:00
}
2017-10-01 21:59:27 +00:00
memdelete ( da ) ;
2015-08-23 23:15:56 +00:00
2018-02-28 23:14:12 +00:00
Map < String , String > file_renames ;
Map < String , String > folder_renames ;
_try_move_item ( to_rename , new_path , file_renames , folder_renames ) ;
2019-06-04 03:36:23 +00:00
int current_tab = editor - > get_current_tab ( ) ;
2019-07-16 03:50:03 +00:00
_save_scenes_after_move ( file_renames ) ; // save scenes before updating
2018-02-28 23:14:12 +00:00
_update_dependencies_after_move ( file_renames ) ;
_update_resource_paths_after_move ( file_renames ) ;
2018-05-26 18:19:38 +00:00
_update_project_settings_after_move ( file_renames ) ;
2018-09-18 12:02:59 +00:00
_update_favorites_list_after_move ( file_renames , folder_renames ) ;
2015-08-23 23:15:56 +00:00
2019-06-04 03:36:23 +00:00
editor - > set_current_tab ( current_tab ) ;
2018-08-24 07:35:07 +00:00
print_verbose ( " FileSystem: calling rescan. " ) ;
2017-10-01 21:59:27 +00:00
_rescan ( ) ;
2019-06-04 03:36:23 +00:00
print_verbose ( " FileSystem: saving moved scenes. " ) ;
_save_scenes_after_move ( file_renames ) ;
2021-01-16 15:30:56 +00:00
path = new_path ;
current_path - > set_text ( path ) ;
2017-10-01 21:59:27 +00:00
}
2016-05-15 23:25:51 +00:00
2017-12-01 11:13:50 +00:00
void FileSystemDock : : _duplicate_operation_confirm ( ) {
String new_name = duplicate_dialog_text - > get_text ( ) . strip_edges ( ) ;
if ( new_name . length ( ) = = 0 ) {
EditorNode : : get_singleton ( ) - > show_warning ( TTR ( " No name provided. " ) ) ;
return ;
2022-02-03 16:03:38 +00:00
} else if ( new_name . contains ( " / " ) | | new_name . contains ( " \\ " ) | | new_name . contains ( " : " ) ) {
2017-12-01 11:13:50 +00:00
EditorNode : : get_singleton ( ) - > show_warning ( TTR ( " Name contains invalid characters. " ) ) ;
return ;
}
2017-12-31 17:10:03 +00:00
String base_dir = to_duplicate . path . get_base_dir ( ) ;
2019-07-04 09:42:40 +00:00
// get_base_dir() returns "some/path" if the original path was "some/path/", so work it around.
if ( to_duplicate . path . ends_with ( " / " ) ) {
base_dir = base_dir . get_base_dir ( ) ;
2017-12-01 11:13:50 +00:00
}
2019-07-04 09:42:40 +00:00
String new_path = base_dir . plus_file ( new_name ) ;
2019-08-22 04:22:52 +00:00
// Present a more user friendly warning for name conflict
2017-12-01 11:13:50 +00:00
DirAccess * da = DirAccess : : create ( DirAccess : : ACCESS_RESOURCES ) ;
if ( da - > file_exists ( new_path ) | | da - > dir_exists ( new_path ) ) {
EditorNode : : get_singleton ( ) - > show_warning ( TTR ( " A file or folder with this name already exists. " ) ) ;
memdelete ( da ) ;
return ;
}
memdelete ( da ) ;
2017-12-31 17:10:03 +00:00
_try_duplicate_item ( to_duplicate , new_path ) ;
2017-12-01 11:13:50 +00:00
2019-08-22 04:22:52 +00:00
// Rescan everything.
2018-08-24 07:35:07 +00:00
print_verbose ( " FileSystem: calling rescan. " ) ;
2017-12-01 11:13:50 +00:00
_rescan ( ) ;
}
2018-05-29 12:33:11 +00:00
void FileSystemDock : : _move_with_overwrite ( ) {
_move_operation_confirm ( to_move_path , true ) ;
}
2020-12-10 11:53:56 +00:00
Vector < String > FileSystemDock : : _check_existing ( ) {
Vector < String > conflicting_items ;
2018-05-29 12:33:11 +00:00
String & p_to_path = to_move_path ;
for ( int i = 0 ; i < to_move . size ( ) ; i + + ) {
String ol_pth = to_move [ i ] . path . ends_with ( " / " ) ? to_move [ i ] . path . substr ( 0 , to_move [ i ] . path . length ( ) - 1 ) : to_move [ i ] . path ;
String p_new_path = p_to_path . plus_file ( ol_pth . get_file ( ) ) ;
FileOrFolder p_item = to_move [ i ] ;
String old_path = ( p_item . is_file | | p_item . path . ends_with ( " / " ) ) ? p_item . path : ( p_item . path + " / " ) ;
String new_path = ( p_item . is_file | | p_new_path . ends_with ( " / " ) ) ? p_new_path : ( p_new_path + " / " ) ;
2020-12-10 11:53:56 +00:00
if ( ( p_item . is_file & & FileAccess : : exists ( new_path ) ) | |
( ! p_item . is_file & & DirAccess : : exists ( new_path ) ) ) {
conflicting_items . push_back ( old_path ) ;
2018-05-29 12:33:11 +00:00
}
}
2020-12-10 11:53:56 +00:00
return conflicting_items ;
2018-05-29 12:33:11 +00:00
}
2020-03-03 09:46:03 +00:00
void FileSystemDock : : _move_operation_confirm ( const String & p_to_path , bool p_overwrite ) {
if ( ! p_overwrite ) {
2018-05-29 12:33:11 +00:00
to_move_path = p_to_path ;
2020-12-10 11:53:56 +00:00
Vector < String > conflicting_items = _check_existing ( ) ;
2020-12-15 12:04:21 +00:00
if ( ! conflicting_items . is_empty ( ) ) {
2019-08-22 04:22:52 +00:00
// Ask to do something.
2020-12-10 11:53:56 +00:00
overwrite_dialog - > set_text ( vformat (
TTR ( " The following files or folders conflict with items in the target location '%s': \n \n %s \n \n Do you wish to overwrite them? " ) ,
to_move_path ,
String ( " \n " ) . join ( conflicting_items ) ) ) ;
2020-03-06 17:00:16 +00:00
overwrite_dialog - > popup_centered ( ) ;
2018-05-29 12:33:11 +00:00
return ;
}
}
2016-05-15 23:25:51 +00:00
2019-08-22 04:22:52 +00:00
// Check groups.
2019-04-19 18:54:33 +00:00
for ( int i = 0 ; i < to_move . size ( ) ; i + + ) {
if ( to_move [ i ] . is_file & & EditorFileSystem : : get_singleton ( ) - > is_group_file ( to_move [ i ] . path ) ) {
EditorFileSystem : : get_singleton ( ) - > move_group_file ( to_move [ i ] . path , p_to_path . plus_file ( to_move [ i ] . path . get_file ( ) ) ) ;
}
}
2018-02-28 23:14:12 +00:00
Map < String , String > file_renames ;
Map < String , String > folder_renames ;
2018-06-18 22:43:16 +00:00
bool is_moved = false ;
2017-10-01 21:59:27 +00:00
for ( int i = 0 ; i < to_move . size ( ) ; i + + ) {
String old_path = to_move [ i ] . path . ends_with ( " / " ) ? to_move [ i ] . path . substr ( 0 , to_move [ i ] . path . length ( ) - 1 ) : to_move [ i ] . path ;
String new_path = p_to_path . plus_file ( old_path . get_file ( ) ) ;
2018-06-18 22:43:16 +00:00
if ( old_path ! = new_path ) {
_try_move_item ( to_move [ i ] , new_path , file_renames , folder_renames ) ;
is_moved = true ;
}
2015-08-23 23:15:56 +00:00
}
2018-06-18 22:43:16 +00:00
if ( is_moved ) {
2019-06-04 03:36:23 +00:00
int current_tab = editor - > get_current_tab ( ) ;
2020-02-04 22:20:01 +00:00
_save_scenes_after_move ( file_renames ) ; // Save scenes before updating.
2018-06-18 22:43:16 +00:00
_update_dependencies_after_move ( file_renames ) ;
_update_resource_paths_after_move ( file_renames ) ;
2018-05-26 18:19:38 +00:00
_update_project_settings_after_move ( file_renames ) ;
2018-09-18 12:02:59 +00:00
_update_favorites_list_after_move ( file_renames , folder_renames ) ;
2017-12-26 19:32:12 +00:00
2019-06-04 03:36:23 +00:00
editor - > set_current_tab ( current_tab ) ;
2018-08-24 07:35:07 +00:00
print_verbose ( " FileSystem: calling rescan. " ) ;
2018-06-18 22:43:16 +00:00
_rescan ( ) ;
2019-06-04 03:36:23 +00:00
print_verbose ( " FileSystem: saving moved scenes. " ) ;
_save_scenes_after_move ( file_renames ) ;
2021-01-16 15:30:56 +00:00
2021-02-09 14:40:55 +00:00
path = p_to_path ;
2021-01-16 15:30:56 +00:00
current_path - > set_text ( path ) ;
2018-06-18 22:43:16 +00:00
}
2015-08-23 23:15:56 +00:00
}
2018-08-23 15:00:30 +00:00
Vector < String > FileSystemDock : : _tree_get_selected ( bool remove_self_inclusion ) {
2019-08-22 04:22:52 +00:00
// Build a list of selected items with the active one at the first position.
2018-08-23 15:00:30 +00:00
Vector < String > selected_strings ;
2021-03-07 20:07:30 +00:00
TreeItem * favorites_item = tree - > get_root ( ) - > get_first_child ( ) ;
2018-08-23 15:00:30 +00:00
TreeItem * active_selected = tree - > get_selected ( ) ;
2018-09-28 22:11:26 +00:00
if ( active_selected & & active_selected ! = favorites_item ) {
2018-08-23 15:00:30 +00:00
selected_strings . push_back ( active_selected - > get_metadata ( 0 ) ) ;
}
TreeItem * selected = tree - > get_root ( ) ;
selected = tree - > get_next_selected ( selected ) ;
while ( selected ) {
2018-09-28 22:11:26 +00:00
if ( selected ! = active_selected & & selected ! = favorites_item ) {
2018-08-23 15:00:30 +00:00
selected_strings . push_back ( selected - > get_metadata ( 0 ) ) ;
}
selected = tree - > get_next_selected ( selected ) ;
}
2019-08-09 23:15:25 +00:00
if ( remove_self_inclusion ) {
selected_strings = _remove_self_included_paths ( selected_strings ) ;
}
return selected_strings ;
}
Vector < String > FileSystemDock : : _remove_self_included_paths ( Vector < String > selected_strings ) {
2019-08-22 04:22:52 +00:00
// Remove paths or files that are included into another.
2019-08-09 23:15:25 +00:00
if ( selected_strings . size ( ) > 1 ) {
2018-08-23 15:00:30 +00:00
selected_strings . sort_custom < NaturalNoCaseComparator > ( ) ;
String last_path = " " ;
for ( int i = 0 ; i < selected_strings . size ( ) ; i + + ) {
2021-12-09 09:42:46 +00:00
if ( ! last_path . is_empty ( ) & & selected_strings [ i ] . begins_with ( last_path ) ) {
2021-07-03 22:17:03 +00:00
selected_strings . remove_at ( i ) ;
2018-08-23 15:00:30 +00:00
i - - ;
}
if ( selected_strings [ i ] . ends_with ( " / " ) ) {
last_path = selected_strings [ i ] ;
}
}
}
return selected_strings ;
}
void FileSystemDock : : _tree_rmb_option ( int p_option ) {
2019-08-09 23:15:25 +00:00
Vector < String > selected_strings = _tree_get_selected ( false ) ;
2018-08-23 15:00:30 +00:00
2019-08-22 04:22:52 +00:00
// Execute the current option.
2017-03-05 15:44:50 +00:00
switch ( p_option ) {
2018-08-23 15:00:30 +00:00
case FOLDER_EXPAND_ALL :
case FOLDER_COLLAPSE_ALL : {
// Expand or collapse the folder
if ( selected_strings . size ( ) = = 1 ) {
bool is_collapsed = ( p_option = = FOLDER_COLLAPSE_ALL ) ;
2018-03-28 09:34:46 +00:00
2018-08-23 15:00:30 +00:00
Vector < TreeItem * > needs_check ;
needs_check . push_back ( tree - > get_selected ( ) ) ;
2018-03-28 09:34:46 +00:00
2018-08-23 15:00:30 +00:00
while ( needs_check . size ( ) ) {
needs_check [ 0 ] - > set_collapsed ( is_collapsed ) ;
2021-03-07 20:07:30 +00:00
TreeItem * child = needs_check [ 0 ] - > get_first_child ( ) ;
2018-08-23 15:00:30 +00:00
while ( child ) {
needs_check . push_back ( child ) ;
child = child - > get_next ( ) ;
}
2018-03-28 09:34:46 +00:00
2021-07-03 22:17:03 +00:00
needs_check . remove_at ( 0 ) ;
2018-08-23 15:00:30 +00:00
}
2018-03-28 09:34:46 +00:00
}
2018-08-23 15:00:30 +00:00
} break ;
default : {
_file_option ( p_option , selected_strings ) ;
} break ;
}
}
2018-03-28 09:34:46 +00:00
2018-08-23 15:00:30 +00:00
void FileSystemDock : : _file_list_rmb_option ( int p_option ) {
Vector < int > selected_id = files - > get_selected_items ( ) ;
Vector < String > selected ;
for ( int i = 0 ; i < selected_id . size ( ) ; i + + ) {
selected . push_back ( files - > get_item_metadata ( selected_id [ i ] ) ) ;
}
_file_option ( p_option , selected ) ;
}
2019-07-10 09:54:12 +00:00
void FileSystemDock : : _file_option ( int p_option , const Vector < String > & p_selected ) {
2019-08-22 04:22:52 +00:00
// The first one should be the active item.
2018-08-23 15:00:30 +00:00
switch ( p_option ) {
case FILE_SHOW_IN_EXPLORER : {
2019-08-22 04:22:52 +00:00
// Show the file/folder in the OS explorer.
2018-08-23 15:00:30 +00:00
String fpath = path ;
2019-04-06 20:49:32 +00:00
if ( path = = " Favorites " ) {
fpath = p_selected [ 0 ] ;
}
2018-08-23 15:00:30 +00:00
if ( ! fpath . ends_with ( " / " ) ) {
fpath = fpath . get_base_dir ( ) ;
}
String dir = ProjectSettings : : get_singleton ( ) - > globalize_path ( fpath ) ;
OS : : get_singleton ( ) - > shell_open ( String ( " file:// " ) + dir ) ;
2017-10-09 13:59:48 +00:00
} break ;
2018-08-23 15:00:30 +00:00
2016-05-15 23:25:51 +00:00
case FILE_OPEN : {
2019-08-22 04:22:52 +00:00
// Open folders.
2019-05-10 14:50:43 +00:00
TreeItem * selected = tree - > get_root ( ) ;
selected = tree - > get_next_selected ( selected ) ;
while ( selected ) {
if ( p_selected . find ( selected - > get_metadata ( 0 ) ) > = 0 ) {
selected - > set_collapsed ( false ) ;
}
selected = tree - > get_next_selected ( selected ) ;
}
2019-08-22 04:22:52 +00:00
// Open the file.
2018-08-23 15:00:30 +00:00
for ( int i = 0 ; i < p_selected . size ( ) ; i + + ) {
_select_file ( p_selected [ i ] ) ;
2017-12-01 08:01:50 +00:00
}
2016-05-15 23:25:51 +00:00
} break ;
2019-05-08 02:35:23 +00:00
case FILE_INHERIT : {
2019-08-22 04:22:52 +00:00
// Create a new scene inherited from the selected one.
2019-05-08 02:35:23 +00:00
if ( p_selected . size ( ) = = 1 ) {
2021-07-17 21:22:52 +00:00
emit_signal ( SNAME ( " inherit " ) , p_selected [ 0 ] ) ;
2019-05-08 02:35:23 +00:00
}
} break ;
2019-10-29 18:24:38 +00:00
case FILE_MAIN_SCENE : {
// Set as main scene with selected scene file.
if ( p_selected . size ( ) = = 1 ) {
ProjectSettings : : get_singleton ( ) - > set ( " application/run/main_scene " , p_selected [ 0 ] ) ;
ProjectSettings : : get_singleton ( ) - > save ( ) ;
_update_tree ( _compute_uncollapsed_paths ( ) ) ;
2020-01-09 00:51:31 +00:00
_update_file_list ( true ) ;
2019-10-29 18:24:38 +00:00
}
} break ;
2018-08-23 15:00:30 +00:00
case FILE_INSTANCE : {
2019-08-22 04:22:52 +00:00
// Instance all selected scenes.
2016-07-20 17:09:03 +00:00
Vector < String > paths ;
2018-08-23 15:00:30 +00:00
for ( int i = 0 ; i < p_selected . size ( ) ; i + + ) {
String fpath = p_selected [ i ] ;
2017-09-03 20:35:18 +00:00
if ( EditorFileSystem : : get_singleton ( ) - > get_file_type ( fpath ) = = " PackedScene " ) {
paths . push_back ( fpath ) ;
2016-05-15 23:25:51 +00:00
}
}
2020-12-15 12:04:21 +00:00
if ( ! paths . is_empty ( ) ) {
2021-07-17 21:22:52 +00:00
emit_signal ( SNAME ( " instance " ) , paths ) ;
2016-07-20 17:09:03 +00:00
}
2016-05-15 23:25:51 +00:00
} break ;
2015-08-23 23:15:56 +00:00
2018-09-13 16:11:05 +00:00
case FILE_ADD_FAVORITE : {
2019-08-22 04:22:52 +00:00
// Add the files from favorites.
2018-09-18 12:02:59 +00:00
Vector < String > favorites = EditorSettings : : get_singleton ( ) - > get_favorites ( ) ;
2018-09-13 16:11:05 +00:00
for ( int i = 0 ; i < p_selected . size ( ) ; i + + ) {
2022-02-01 18:19:13 +00:00
if ( ! favorites . has ( p_selected [ i ] ) ) {
2018-09-13 16:11:05 +00:00
favorites . push_back ( p_selected [ i ] ) ;
}
}
2018-09-18 12:02:59 +00:00
EditorSettings : : get_singleton ( ) - > set_favorites ( favorites ) ;
2018-09-13 21:28:21 +00:00
_update_tree ( _compute_uncollapsed_paths ( ) ) ;
2018-09-13 16:11:05 +00:00
} break ;
case FILE_REMOVE_FAVORITE : {
2019-08-22 04:22:52 +00:00
// Remove the files from favorites.
2018-09-18 12:02:59 +00:00
Vector < String > favorites = EditorSettings : : get_singleton ( ) - > get_favorites ( ) ;
2018-09-13 16:11:05 +00:00
for ( int i = 0 ; i < p_selected . size ( ) ; i + + ) {
favorites . erase ( p_selected [ i ] ) ;
}
2018-09-18 12:02:59 +00:00
EditorSettings : : get_singleton ( ) - > set_favorites ( favorites ) ;
2018-09-13 21:28:21 +00:00
_update_tree ( _compute_uncollapsed_paths ( ) ) ;
2020-05-14 14:41:43 +00:00
if ( path = = " Favorites " ) {
2018-09-28 22:11:26 +00:00
_update_file_list ( true ) ;
2020-05-14 14:41:43 +00:00
}
2018-09-13 16:11:05 +00:00
} break ;
2018-08-23 15:00:30 +00:00
case FILE_DEPENDENCIES : {
2019-08-22 04:22:52 +00:00
// Checkout the file dependencies.
2020-12-15 12:04:21 +00:00
if ( ! p_selected . is_empty ( ) ) {
2018-08-23 15:00:30 +00:00
String fpath = p_selected [ 0 ] ;
deps_editor - > edit ( fpath ) ;
}
2015-08-23 23:15:56 +00:00
} break ;
2018-08-23 15:00:30 +00:00
case FILE_OWNERS : {
2019-08-22 04:22:52 +00:00
// Checkout the file owners.
2020-12-15 12:04:21 +00:00
if ( ! p_selected . is_empty ( ) ) {
2018-08-23 15:00:30 +00:00
String fpath = p_selected [ 0 ] ;
owners_editor - > show ( fpath ) ;
}
2015-08-23 23:15:56 +00:00
} break ;
2018-08-23 15:00:30 +00:00
2015-08-23 23:15:56 +00:00
case FILE_MOVE : {
2019-08-22 04:22:52 +00:00
// Move the files to a given location.
2017-10-01 21:59:27 +00:00
to_move . clear ( ) ;
2019-08-09 23:15:25 +00:00
Vector < String > collapsed_paths = _remove_self_included_paths ( p_selected ) ;
for ( int i = collapsed_paths . size ( ) - 1 ; i > = 0 ; i - - ) {
String fpath = collapsed_paths [ i ] ;
2018-08-23 15:00:30 +00:00
if ( fpath ! = " res:// " ) {
to_move . push_back ( FileOrFolder ( fpath , ! fpath . ends_with ( " / " ) ) ) ;
}
2015-08-23 23:15:56 +00:00
}
2017-10-01 21:59:27 +00:00
if ( to_move . size ( ) > 0 ) {
2015-08-23 23:15:56 +00:00
move_dialog - > popup_centered_ratio ( ) ;
}
2017-10-01 21:59:27 +00:00
} break ;
2015-08-23 23:15:56 +00:00
2018-08-23 15:00:30 +00:00
case FILE_RENAME : {
2019-08-22 04:22:52 +00:00
// Rename the active file.
2020-12-15 12:04:21 +00:00
if ( ! p_selected . is_empty ( ) ) {
2018-08-23 15:00:30 +00:00
to_rename . path = p_selected [ 0 ] ;
if ( to_rename . path ! = " res:// " ) {
to_rename . is_file = ! to_rename . path . ends_with ( " / " ) ;
if ( to_rename . is_file ) {
String name = to_rename . path . get_file ( ) ;
rename_dialog - > set_title ( TTR ( " Renaming file: " ) + " " + name ) ;
rename_dialog_text - > set_text ( name ) ;
2020-07-03 13:26:22 +00:00
rename_dialog_text - > select ( 0 , name . rfind ( " . " ) ) ;
2018-08-23 15:00:30 +00:00
} else {
String name = to_rename . path . substr ( 0 , to_rename . path . length ( ) - 1 ) . get_file ( ) ;
rename_dialog - > set_title ( TTR ( " Renaming folder: " ) + " " + name ) ;
rename_dialog_text - > set_text ( name ) ;
rename_dialog_text - > select ( 0 , name . length ( ) ) ;
}
2020-03-06 17:00:16 +00:00
rename_dialog - > popup_centered ( Size2 ( 250 , 80 ) * EDSCALE ) ;
2018-08-23 15:00:30 +00:00
rename_dialog_text - > grab_focus ( ) ;
}
2017-10-01 21:59:27 +00:00
}
2015-08-23 23:15:56 +00:00
} break ;
2018-08-23 15:00:30 +00:00
2015-08-23 23:15:56 +00:00
case FILE_REMOVE : {
2019-08-22 04:22:52 +00:00
// Remove the selected files.
2017-10-01 22:24:49 +00:00
Vector < String > remove_files ;
Vector < String > remove_folders ;
2019-08-09 23:15:25 +00:00
Vector < String > collapsed_paths = _remove_self_included_paths ( p_selected ) ;
2015-08-23 23:15:56 +00:00
2019-08-09 23:15:25 +00:00
for ( int i = 0 ; i < collapsed_paths . size ( ) ; i + + ) {
String fpath = collapsed_paths [ i ] ;
2018-08-23 15:00:30 +00:00
if ( fpath ! = " res:// " ) {
2017-09-03 20:35:18 +00:00
if ( fpath . ends_with ( " / " ) ) {
remove_folders . push_back ( fpath ) ;
2017-10-01 22:24:49 +00:00
} else {
2017-09-03 20:35:18 +00:00
remove_files . push_back ( fpath ) ;
2017-10-01 22:24:49 +00:00
}
}
2015-08-23 23:15:56 +00:00
}
2017-10-01 22:24:49 +00:00
if ( remove_files . size ( ) + remove_folders . size ( ) > 0 ) {
remove_dialog - > show ( remove_folders , remove_files ) ;
2015-08-23 23:15:56 +00:00
}
} break ;
2017-12-01 11:13:50 +00:00
2018-08-23 15:00:30 +00:00
case FILE_DUPLICATE : {
2019-08-22 04:22:52 +00:00
// Duplicate the selected files.
2018-08-23 15:00:30 +00:00
for ( int i = 0 ; i < p_selected . size ( ) ; i + + ) {
to_duplicate . path = p_selected [ i ] ;
to_duplicate . is_file = ! to_duplicate . path . ends_with ( " / " ) ;
if ( to_duplicate . is_file ) {
String name = to_duplicate . path . get_file ( ) ;
duplicate_dialog - > set_title ( TTR ( " Duplicating file: " ) + " " + name ) ;
duplicate_dialog_text - > set_text ( name ) ;
2020-07-03 13:26:22 +00:00
duplicate_dialog_text - > select ( 0 , name . rfind ( " . " ) ) ;
2018-08-23 15:00:30 +00:00
} else {
String name = to_duplicate . path . substr ( 0 , to_duplicate . path . length ( ) - 1 ) . get_file ( ) ;
duplicate_dialog - > set_title ( TTR ( " Duplicating folder: " ) + " " + name ) ;
duplicate_dialog_text - > set_text ( name ) ;
duplicate_dialog_text - > select ( 0 , name . length ( ) ) ;
}
2020-03-06 17:00:16 +00:00
duplicate_dialog - > popup_centered ( Size2 ( 250 , 80 ) * EDSCALE ) ;
2018-08-23 15:00:30 +00:00
duplicate_dialog_text - > grab_focus ( ) ;
2017-12-01 11:13:50 +00:00
}
} break ;
2018-08-23 15:00:30 +00:00
2015-08-23 23:15:56 +00:00
case FILE_INFO : {
} break ;
2016-05-27 17:18:40 +00:00
2018-08-23 15:00:30 +00:00
case FILE_REIMPORT : {
2019-08-22 04:22:52 +00:00
// Reimport all selected files.
2016-05-27 17:18:40 +00:00
Vector < String > reimport ;
2018-08-23 15:00:30 +00:00
for ( int i = 0 ; i < p_selected . size ( ) ; i + + ) {
reimport . push_back ( p_selected [ i ] ) ;
2016-05-27 17:18:40 +00:00
}
2019-09-25 08:28:50 +00:00
ERR_FAIL_COND_MSG ( reimport . size ( ) = = 0 , " You need to select files to reimport them. " ) ;
2016-05-27 17:18:40 +00:00
} break ;
2018-08-23 15:00:30 +00:00
2017-10-01 22:33:43 +00:00
case FILE_NEW_FOLDER : {
make_dir_dialog_text - > set_text ( " new folder " ) ;
make_dir_dialog_text - > select_all ( ) ;
2020-03-06 17:00:16 +00:00
make_dir_dialog - > popup_centered ( Size2 ( 250 , 80 ) * EDSCALE ) ;
2017-10-01 22:33:43 +00:00
make_dir_dialog_text - > grab_focus ( ) ;
} break ;
2018-08-23 15:00:30 +00:00
2019-08-15 17:47:21 +00:00
case FILE_NEW_SCENE : {
make_scene_dialog_text - > set_text ( " new scene " ) ;
make_scene_dialog_text - > select_all ( ) ;
2020-03-06 17:00:16 +00:00
make_scene_dialog - > popup_centered ( Size2 ( 250 , 80 ) * EDSCALE ) ;
2019-08-15 17:47:21 +00:00
make_scene_dialog_text - > grab_focus ( ) ;
} break ;
2018-04-25 07:18:10 +00:00
case FILE_NEW_SCRIPT : {
2018-08-23 15:00:30 +00:00
String fpath = path ;
if ( ! fpath . ends_with ( " / " ) ) {
fpath = fpath . get_base_dir ( ) ;
2018-04-25 07:18:10 +00:00
}
2020-01-08 22:43:55 +00:00
make_script_dialog - > config ( " Node " , fpath . plus_file ( " new_script.gd " ) , false , false ) ;
2020-01-08 04:15:05 +00:00
make_script_dialog - > popup_centered ( ) ;
2018-04-25 07:18:10 +00:00
} break ;
2018-08-23 15:00:30 +00:00
2017-10-09 13:59:48 +00:00
case FILE_COPY_PATH : {
2020-12-15 12:04:21 +00:00
if ( ! p_selected . is_empty ( ) ) {
2018-08-23 15:00:30 +00:00
String fpath = p_selected [ 0 ] ;
2020-03-03 13:36:29 +00:00
DisplayServer : : get_singleton ( ) - > clipboard_set ( fpath ) ;
2018-08-23 15:00:30 +00:00
}
2017-10-09 13:59:48 +00:00
} break ;
2018-08-23 15:00:30 +00:00
2018-07-22 15:53:40 +00:00
case FILE_NEW_RESOURCE : {
new_resource_dialog - > popup_create ( true ) ;
} break ;
2021-09-23 21:09:15 +00:00
case FILE_NEW_TEXTFILE : {
String fpath = path ;
if ( ! fpath . ends_with ( " / " ) ) {
fpath = fpath . get_base_dir ( ) ;
}
ScriptEditor : : get_singleton ( ) - > open_text_file_create_dialog ( fpath ) ;
} break ;
2015-08-23 23:15:56 +00:00
}
2014-02-10 01:10:30 +00:00
}
2020-02-21 16:44:59 +00:00
void FileSystemDock : : _resource_created ( ) {
2021-12-03 14:45:32 +00:00
String fpath = path ;
if ( ! fpath . ends_with ( " / " ) ) {
fpath = fpath . get_base_dir ( ) ;
}
String type_name = new_resource_dialog - > get_selected_type ( ) ;
if ( type_name = = " Shader " ) {
make_shader_dialog - > config ( fpath . plus_file ( " new_shader " ) , false , false , 0 ) ;
make_shader_dialog - > popup_centered ( ) ;
return ;
} else if ( type_name = = " VisualShader " ) {
make_shader_dialog - > config ( fpath . plus_file ( " new_shader " ) , false , false , 1 ) ;
make_shader_dialog - > popup_centered ( ) ;
return ;
}
2021-01-06 19:25:05 +00:00
Variant c = new_resource_dialog - > instance_selected ( ) ;
2018-07-22 15:53:40 +00:00
ERR_FAIL_COND ( ! c ) ;
Resource * r = Object : : cast_to < Resource > ( c ) ;
ERR_FAIL_COND ( ! r ) ;
2020-02-09 06:21:10 +00:00
PackedScene * scene = Object : : cast_to < PackedScene > ( r ) ;
if ( scene ) {
Node * node = memnew ( Node ) ;
node - > set_name ( " Node " ) ;
scene - > pack ( node ) ;
memdelete ( node ) ;
}
2021-01-06 19:25:05 +00:00
editor - > push_item ( r ) ;
editor - > save_resource_as ( RES ( r ) , fpath ) ;
2017-01-10 12:19:59 +00:00
}
2018-09-13 19:49:56 +00:00
void FileSystemDock : : _search_changed ( const String & p_text , const Control * p_from ) {
2019-11-21 14:40:11 +00:00
if ( searched_string . length ( ) = = 0 ) {
2019-08-22 04:22:52 +00:00
// Register the uncollapsed paths before they change.
2018-09-13 21:28:21 +00:00
uncollapsed_paths_before_search = _compute_uncollapsed_paths ( ) ;
}
2018-09-13 19:49:56 +00:00
searched_string = p_text . to_lower ( ) ;
2015-08-23 23:15:56 +00:00
2020-05-14 14:41:43 +00:00
if ( p_from = = tree_search_box ) {
2018-09-13 19:49:56 +00:00
file_list_search_box - > set_text ( searched_string ) ;
2020-05-14 14:41:43 +00:00
} else { // File_list_search_box.
2018-09-13 19:49:56 +00:00
tree_search_box - > set_text ( searched_string ) ;
2020-05-14 14:41:43 +00:00
}
2018-09-13 19:49:56 +00:00
2021-12-09 09:42:46 +00:00
bool unfold_path = ( p_text . is_empty ( ) & & ! path . is_empty ( ) ) ;
2018-09-13 19:49:56 +00:00
switch ( display_mode ) {
case DISPLAY_MODE_TREE_ONLY : {
2019-11-21 14:40:11 +00:00
_update_tree ( searched_string . length ( ) = = 0 ? uncollapsed_paths_before_search : Vector < String > ( ) , false , false , unfold_path ) ;
2018-09-13 19:49:56 +00:00
} break ;
case DISPLAY_MODE_SPLIT : {
2018-09-28 11:26:36 +00:00
_update_file_list ( false ) ;
2019-11-21 14:40:11 +00:00
_update_tree ( searched_string . length ( ) = = 0 ? uncollapsed_paths_before_search : Vector < String > ( ) , false , false , unfold_path ) ;
2018-09-13 19:49:56 +00:00
} break ;
}
2016-05-15 23:25:51 +00:00
}
2015-08-23 23:15:56 +00:00
2016-07-21 13:34:57 +00:00
void FileSystemDock : : _rescan ( ) {
2017-01-21 12:07:29 +00:00
_set_scanning_mode ( ) ;
2014-02-10 01:10:30 +00:00
EditorFileSystem : : get_singleton ( ) - > scan ( ) ;
2015-08-23 23:15:56 +00:00
}
2018-09-13 22:16:43 +00:00
void FileSystemDock : : _toggle_split_mode ( bool p_active ) {
2019-02-25 22:39:49 +00:00
set_display_mode ( p_active ? DISPLAY_MODE_SPLIT : DISPLAY_MODE_TREE_ONLY ) ;
2021-07-17 21:22:52 +00:00
emit_signal ( SNAME ( " display_mode_changed " ) ) ;
2018-09-13 22:16:43 +00:00
}
2017-03-05 15:44:50 +00:00
void FileSystemDock : : fix_dependencies ( const String & p_for_file ) {
2015-08-23 23:15:56 +00:00
deps_editor - > edit ( p_for_file ) ;
}
2016-07-21 13:34:57 +00:00
void FileSystemDock : : focus_on_filter ( ) {
2021-06-03 23:22:50 +00:00
LineEdit * current_search_box = nullptr ;
if ( display_mode = = DISPLAY_MODE_TREE_ONLY ) {
current_search_box = tree_search_box ;
} else if ( display_mode = = DISPLAY_MODE_SPLIT ) {
current_search_box = file_list_search_box ;
}
if ( current_search_box ) {
current_search_box - > grab_focus ( ) ;
current_search_box - > select_all ( ) ;
}
2014-02-10 01:10:30 +00:00
}
2019-02-25 22:39:49 +00:00
void FileSystemDock : : set_file_list_display_mode ( FileListDisplayMode p_mode ) {
2020-05-14 14:41:43 +00:00
if ( p_mode = = file_list_display_mode ) {
2016-08-16 16:25:42 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2015-12-15 16:39:13 +00:00
2019-03-05 06:55:08 +00:00
_toggle_file_display ( ) ;
2015-12-15 16:39:13 +00:00
}
2017-03-05 15:44:50 +00:00
Variant FileSystemDock : : get_drag_data_fw ( const Point2 & p_point , Control * p_from ) {
2018-08-23 15:00:30 +00:00
bool all_favorites = true ;
bool all_not_favorites = true ;
2017-10-24 22:09:04 +00:00
Vector < String > paths ;
2016-05-11 14:46:08 +00:00
2017-03-05 15:44:50 +00:00
if ( p_from = = tree ) {
2019-08-22 04:22:52 +00:00
// Check if the first selected is in favorite.
2018-08-23 15:00:30 +00:00
TreeItem * selected = tree - > get_next_selected ( tree - > get_root ( ) ) ;
while ( selected ) {
2021-03-07 20:07:30 +00:00
TreeItem * favorites_item = tree - > get_root ( ) - > get_first_child ( ) ;
2018-09-28 22:11:26 +00:00
if ( selected = = favorites_item ) {
2019-08-22 04:22:52 +00:00
// The "Favorites" item is not draggable.
2018-09-28 22:11:26 +00:00
return Variant ( ) ;
}
2021-03-07 20:07:30 +00:00
bool is_favorite = selected - > get_parent ( ) ! = nullptr & & tree - > get_root ( ) - > get_first_child ( ) = = selected - > get_parent ( ) ;
2018-08-23 15:00:30 +00:00
all_favorites & = is_favorite ;
all_not_favorites & = ! is_favorite ;
selected = tree - > get_next_selected ( selected ) ;
}
2019-10-20 17:39:21 +00:00
if ( ! all_not_favorites ) {
2018-08-23 15:00:30 +00:00
paths = _tree_get_selected ( false ) ;
} else {
paths = _tree_get_selected ( ) ;
}
2017-10-24 22:09:04 +00:00
} else if ( p_from = = files ) {
2017-03-05 15:44:50 +00:00
for ( int i = 0 ; i < files - > get_item_count ( ) ; i + + ) {
2016-05-11 14:46:08 +00:00
if ( files - > is_selected ( i ) ) {
2017-10-24 22:09:04 +00:00
paths . push_back ( files - > get_item_metadata ( i ) ) ;
2016-05-11 14:46:08 +00:00
}
}
2018-08-23 15:00:30 +00:00
all_favorites = false ;
all_not_favorites = true ;
2017-10-24 22:09:04 +00:00
}
2016-05-11 14:46:08 +00:00
2020-12-15 12:04:21 +00:00
if ( paths . is_empty ( ) ) {
2017-10-24 22:09:04 +00:00
return Variant ( ) ;
2020-05-14 14:41:43 +00:00
}
2017-09-03 20:35:18 +00:00
2017-10-24 22:09:04 +00:00
Dictionary drag_data = EditorNode : : get_singleton ( ) - > drag_files_and_dirs ( paths , p_from ) ;
2019-10-20 17:39:21 +00:00
if ( ! all_not_favorites ) {
drag_data [ " favorite " ] = all_favorites ? " all " : " mixed " ;
2016-05-11 14:46:08 +00:00
}
2017-10-24 22:09:04 +00:00
return drag_data ;
2016-05-11 14:46:08 +00:00
}
2017-03-05 15:44:50 +00:00
bool FileSystemDock : : can_drop_data_fw ( const Point2 & p_point , const Variant & p_data , Control * p_from ) const {
2016-05-11 14:46:08 +00:00
Dictionary drag_data = p_data ;
2019-10-20 17:39:21 +00:00
if ( drag_data . has ( " favorite " ) ) {
if ( String ( drag_data [ " favorite " ] ) ! = " all " ) {
return false ;
}
2016-05-24 02:24:17 +00:00
2019-08-22 04:22:52 +00:00
// Moving favorite around.
2017-09-10 13:37:49 +00:00
TreeItem * ti = tree - > get_item_at_position ( p_point ) ;
2020-05-14 14:41:43 +00:00
if ( ! ti ) {
2016-05-24 02:24:17 +00:00
return false ;
2020-05-14 14:41:43 +00:00
}
2016-05-24 02:24:17 +00:00
2018-08-23 15:00:30 +00:00
int drop_section = tree - > get_drop_section_at_position ( p_point ) ;
2021-03-07 20:07:30 +00:00
TreeItem * favorites_item = tree - > get_root ( ) - > get_first_child ( ) ;
2018-09-14 11:59:19 +00:00
2018-08-23 15:00:30 +00:00
TreeItem * resources_item = favorites_item - > get_next ( ) ;
2016-05-24 02:24:17 +00:00
2018-08-23 15:00:30 +00:00
if ( ti = = favorites_item ) {
2019-08-22 04:22:52 +00:00
return ( drop_section = = 1 ) ; // The parent, first fav.
2016-05-24 02:24:17 +00:00
}
2018-08-23 15:00:30 +00:00
if ( ti - > get_parent ( ) & & favorites_item = = ti - > get_parent ( ) ) {
return true ; // A favorite
2016-05-24 02:24:17 +00:00
}
2018-08-23 15:00:30 +00:00
if ( ti = = resources_item ) {
2019-08-22 04:22:52 +00:00
return ( drop_section = = - 1 ) ; // The tree, last fav.
2016-05-24 02:24:17 +00:00
}
return false ;
}
2017-03-05 15:44:50 +00:00
if ( drag_data . has ( " type " ) & & String ( drag_data [ " type " ] ) = = " resource " ) {
2019-08-22 04:22:52 +00:00
// Move resources.
2018-09-13 20:38:35 +00:00
String to_dir ;
bool favorite ;
_get_drag_target_folder ( to_dir , favorite , p_point , p_from ) ;
2020-12-15 12:04:21 +00:00
return ! to_dir . is_empty ( ) ;
2016-05-11 14:46:08 +00:00
}
2017-03-05 15:44:50 +00:00
if ( drag_data . has ( " type " ) & & ( String ( drag_data [ " type " ] ) = = " files " | | String ( drag_data [ " type " ] ) = = " files_and_dirs " ) ) {
2019-08-22 04:22:52 +00:00
// Move files or dir.
2018-09-13 20:38:35 +00:00
String to_dir ;
bool favorite ;
_get_drag_target_folder ( to_dir , favorite , p_point , p_from ) ;
2020-05-14 14:41:43 +00:00
if ( favorite ) {
2018-09-13 20:38:35 +00:00
return true ;
2020-05-14 14:41:43 +00:00
}
2018-09-13 20:38:35 +00:00
2020-12-15 12:04:21 +00:00
if ( to_dir . is_empty ( ) ) {
2017-10-25 14:27:35 +00:00
return false ;
2020-05-14 14:41:43 +00:00
}
2016-05-11 14:46:08 +00:00
2019-08-22 04:22:52 +00:00
// Attempting to move a folder into itself will fail later,
2020-02-04 22:20:01 +00:00
// rather than bring up a message don't try to do it in the first place.
2017-10-25 14:27:35 +00:00
to_dir = to_dir . ends_with ( " / " ) ? to_dir : ( to_dir + " / " ) ;
2016-05-11 14:46:08 +00:00
Vector < String > fnames = drag_data [ " files " ] ;
2017-10-25 14:27:35 +00:00
for ( int i = 0 ; i < fnames . size ( ) ; + + i ) {
2020-05-14 14:41:43 +00:00
if ( fnames [ i ] . ends_with ( " / " ) & & to_dir . begins_with ( fnames [ i ] ) ) {
2016-05-15 23:25:51 +00:00
return false ;
2020-05-14 14:41:43 +00:00
}
2016-05-15 23:25:51 +00:00
}
2017-10-25 14:27:35 +00:00
return true ;
2016-05-11 14:46:08 +00:00
}
2021-09-08 22:43:14 +00:00
if ( drag_data . has ( " type " ) & & String ( drag_data [ " type " ] ) = = " nodes " ) {
// Save branch as scene.
String to_dir ;
bool favorite ;
_get_drag_target_folder ( to_dir , favorite , p_point , p_from ) ;
return ! favorite & & Array ( drag_data [ " nodes " ] ) . size ( ) = = 1 ;
}
2016-05-11 14:46:08 +00:00
return false ;
}
2017-03-05 15:44:50 +00:00
void FileSystemDock : : drop_data_fw ( const Point2 & p_point , const Variant & p_data , Control * p_from ) {
2020-05-14 14:41:43 +00:00
if ( ! can_drop_data_fw ( p_point , p_data , p_from ) ) {
2016-05-11 14:46:08 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2016-05-11 14:46:08 +00:00
Dictionary drag_data = p_data ;
2018-09-18 12:02:59 +00:00
Vector < String > dirs = EditorSettings : : get_singleton ( ) - > get_favorites ( ) ;
2016-05-24 02:24:17 +00:00
2019-10-20 17:39:21 +00:00
if ( drag_data . has ( " favorite " ) ) {
if ( String ( drag_data [ " favorite " ] ) ! = " all " ) {
return ;
}
2019-08-22 04:22:52 +00:00
// Moving favorite around.
2017-09-10 13:37:49 +00:00
TreeItem * ti = tree - > get_item_at_position ( p_point ) ;
2020-05-14 14:41:43 +00:00
if ( ! ti ) {
2016-05-24 02:24:17 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2018-08-23 15:00:30 +00:00
int drop_section = tree - > get_drop_section_at_position ( p_point ) ;
2016-05-24 02:24:17 +00:00
2018-08-23 15:00:30 +00:00
int drop_position ;
2016-05-24 02:24:17 +00:00
Vector < String > files = drag_data [ " files " ] ;
2021-03-07 20:07:30 +00:00
TreeItem * favorites_item = tree - > get_root ( ) - > get_first_child ( ) ;
2018-08-23 15:00:30 +00:00
TreeItem * resources_item = favorites_item - > get_next ( ) ;
if ( ti = = favorites_item ) {
2019-08-22 04:22:52 +00:00
// Drop on the favorite folder.
2018-08-23 15:00:30 +00:00
drop_position = 0 ;
} else if ( ti = = resources_item ) {
2019-08-22 04:22:52 +00:00
// Drop on the resource item.
2018-08-23 15:00:30 +00:00
drop_position = dirs . size ( ) ;
} else {
2019-08-22 04:22:52 +00:00
// Drop in the list.
2018-08-23 15:00:30 +00:00
drop_position = dirs . find ( ti - > get_metadata ( 0 ) ) ;
if ( drop_section = = 1 ) {
drop_position + + ;
2016-05-24 02:24:17 +00:00
}
}
2019-08-22 04:22:52 +00:00
// Remove dragged favorites.
2018-08-23 15:00:30 +00:00
Vector < int > to_remove ;
int offset = 0 ;
for ( int i = 0 ; i < files . size ( ) ; i + + ) {
int to_remove_pos = dirs . find ( files [ i ] ) ;
to_remove . push_back ( to_remove_pos ) ;
2018-09-14 11:59:19 +00:00
if ( to_remove_pos < drop_position ) {
2018-08-23 15:00:30 +00:00
offset + + ;
2016-05-24 02:24:17 +00:00
}
}
2018-08-23 15:00:30 +00:00
drop_position - = offset ;
to_remove . sort ( ) ;
for ( int i = 0 ; i < to_remove . size ( ) ; i + + ) {
2021-07-03 22:17:03 +00:00
dirs . remove_at ( to_remove [ i ] - i ) ;
2018-08-23 15:00:30 +00:00
}
2016-05-24 02:24:17 +00:00
2019-08-22 04:22:52 +00:00
// Re-add them at the right position.
2018-08-23 15:00:30 +00:00
for ( int i = 0 ; i < files . size ( ) ; i + + ) {
dirs . insert ( drop_position , files [ i ] ) ;
drop_position + + ;
2016-05-24 02:24:17 +00:00
}
2018-09-18 12:02:59 +00:00
EditorSettings : : get_singleton ( ) - > set_favorites ( dirs ) ;
2018-09-13 21:28:21 +00:00
_update_tree ( _compute_uncollapsed_paths ( ) ) ;
2018-09-28 22:11:26 +00:00
2020-05-14 14:41:43 +00:00
if ( display_mode = = DISPLAY_MODE_SPLIT & & path = = " Favorites " ) {
2018-09-28 22:11:26 +00:00
_update_file_list ( true ) ;
2020-05-14 14:41:43 +00:00
}
2016-05-24 02:24:17 +00:00
return ;
}
2017-03-05 15:44:50 +00:00
if ( drag_data . has ( " type " ) & & String ( drag_data [ " type " ] ) = = " resource " ) {
2019-08-22 04:22:52 +00:00
// Moving resource.
2016-05-11 14:46:08 +00:00
Ref < Resource > res = drag_data [ " resource " ] ;
2018-09-13 20:38:35 +00:00
String to_dir ;
bool favorite ;
_get_drag_target_folder ( to_dir , favorite , p_point , p_from ) ;
2020-12-15 12:04:21 +00:00
if ( res . is_valid ( ) & & ! to_dir . is_empty ( ) ) {
2017-10-25 14:40:33 +00:00
EditorNode : : get_singleton ( ) - > push_item ( res . ptr ( ) ) ;
EditorNode : : get_singleton ( ) - > save_resource_as ( res , to_dir ) ;
2016-05-15 23:25:51 +00:00
}
2016-05-11 14:46:08 +00:00
}
2017-03-05 15:44:50 +00:00
if ( drag_data . has ( " type " ) & & ( String ( drag_data [ " type " ] ) = = " files " | | String ( drag_data [ " type " ] ) = = " files_and_dirs " ) ) {
2019-08-22 04:22:52 +00:00
// Move files or add to favorites.
2018-09-13 20:38:35 +00:00
String to_dir ;
bool favorite ;
_get_drag_target_folder ( to_dir , favorite , p_point , p_from ) ;
2020-12-15 12:04:21 +00:00
if ( ! to_dir . is_empty ( ) ) {
2016-05-15 23:25:51 +00:00
Vector < String > fnames = drag_data [ " files " ] ;
2017-10-01 21:59:27 +00:00
to_move . clear ( ) ;
2017-03-05 15:44:50 +00:00
for ( int i = 0 ; i < fnames . size ( ) ; i + + ) {
2020-02-04 22:20:01 +00:00
if ( fnames [ i ] . get_base_dir ( ) ! = to_dir ) {
to_move . push_back ( FileOrFolder ( fnames [ i ] , ! fnames [ i ] . ends_with ( " / " ) ) ) ;
}
}
2020-12-15 12:04:21 +00:00
if ( ! to_move . is_empty ( ) ) {
2021-08-13 21:31:57 +00:00
if ( Input : : get_singleton ( ) - > is_key_pressed ( Key : : CTRL ) ) {
2020-06-04 23:53:35 +00:00
for ( int i = 0 ; i < to_move . size ( ) ; i + + ) {
String new_path ;
String new_path_base ;
if ( to_move [ i ] . is_file ) {
new_path = to_dir . plus_file ( to_move [ i ] . path . get_file ( ) ) ;
new_path_base = new_path . get_basename ( ) + " (%d). " + new_path . get_extension ( ) ;
} else {
PackedStringArray path_split = to_move [ i ] . path . split ( " / " ) ;
new_path = to_dir . plus_file ( path_split [ path_split . size ( ) - 2 ] ) ;
new_path_base = new_path + " (%d) " ;
}
int exist_counter = 1 ;
DirAccessRef da = DirAccess : : create ( DirAccess : : ACCESS_RESOURCES ) ;
while ( da - > file_exists ( new_path ) | | da - > dir_exists ( new_path ) ) {
exist_counter + + ;
new_path = vformat ( new_path_base , exist_counter ) ;
}
_try_duplicate_item ( to_move [ i ] , new_path ) ;
}
_rescan ( ) ;
} else {
_move_operation_confirm ( to_dir ) ;
}
2016-05-15 23:25:51 +00:00
}
2018-09-13 20:38:35 +00:00
} else if ( favorite ) {
2020-02-04 22:20:01 +00:00
// Add the files from favorites.
2018-09-13 20:38:35 +00:00
Vector < String > fnames = drag_data [ " files " ] ;
2018-09-18 12:02:59 +00:00
Vector < String > favorites = EditorSettings : : get_singleton ( ) - > get_favorites ( ) ;
2018-09-13 20:38:35 +00:00
for ( int i = 0 ; i < fnames . size ( ) ; i + + ) {
2022-02-01 18:19:13 +00:00
if ( ! favorites . has ( fnames [ i ] ) ) {
2018-09-13 20:38:35 +00:00
favorites . push_back ( fnames [ i ] ) ;
}
}
2018-09-18 12:02:59 +00:00
EditorSettings : : get_singleton ( ) - > set_favorites ( favorites ) ;
2018-09-13 21:28:21 +00:00
_update_tree ( _compute_uncollapsed_paths ( ) ) ;
2016-05-15 23:25:51 +00:00
}
2016-05-11 14:46:08 +00:00
}
2021-09-08 22:43:14 +00:00
if ( drag_data . has ( " type " ) & & String ( drag_data [ " type " ] ) = = " nodes " ) {
String to_dir ;
bool favorite ;
_get_drag_target_folder ( to_dir , favorite , p_point , p_from ) ;
2021-11-17 20:08:55 +00:00
SceneTreeDock : : get_singleton ( ) - > save_branch_to_file ( to_dir ) ;
2021-09-08 22:43:14 +00:00
}
2016-05-11 14:46:08 +00:00
}
2018-09-13 20:38:35 +00:00
void FileSystemDock : : _get_drag_target_folder ( String & target , bool & target_favorites , const Point2 & p_point , Control * p_from ) const {
target = String ( ) ;
target_favorites = false ;
2019-08-22 04:22:52 +00:00
// In the file list.
2017-10-25 14:27:35 +00:00
if ( p_from = = files ) {
int pos = files - > get_item_at_position ( p_point , true ) ;
2018-09-13 20:38:35 +00:00
if ( pos = = - 1 ) {
return ;
}
2017-10-25 14:27:35 +00:00
2018-09-13 20:38:35 +00:00
String ltarget = files - > get_item_metadata ( pos ) ;
2018-10-02 13:23:58 +00:00
target = ltarget . ends_with ( " / " ) ? ltarget : path . get_base_dir ( ) ;
2018-09-13 20:38:35 +00:00
return ;
2017-10-25 14:27:35 +00:00
}
2019-08-22 04:22:52 +00:00
// In the tree.
2017-10-25 14:27:35 +00:00
if ( p_from = = tree ) {
TreeItem * ti = tree - > get_item_at_position ( p_point ) ;
2018-09-13 20:38:35 +00:00
int section = tree - > get_drop_section_at_position ( p_point ) ;
if ( ti ) {
2019-08-22 04:22:52 +00:00
// Check the favorites first.
2021-03-07 20:07:30 +00:00
if ( ti = = tree - > get_root ( ) - > get_first_child ( ) & & section > = 0 ) {
2018-09-13 20:38:35 +00:00
target_favorites = true ;
return ;
2021-03-07 20:07:30 +00:00
} else if ( ti - > get_parent ( ) = = tree - > get_root ( ) - > get_first_child ( ) ) {
2018-09-13 20:38:35 +00:00
target_favorites = true ;
return ;
2018-08-23 15:00:30 +00:00
} else {
2018-09-13 20:38:35 +00:00
String fpath = ti - > get_metadata ( 0 ) ;
if ( section = = 0 ) {
if ( fpath . ends_with ( " / " ) ) {
2019-08-22 04:22:52 +00:00
// We drop on a folder.
2018-09-13 20:38:35 +00:00
target = fpath ;
return ;
2020-02-04 22:20:01 +00:00
} else {
// We drop on the folder that the target file is in.
target = fpath . get_base_dir ( ) ;
return ;
2018-09-13 20:38:35 +00:00
}
} else {
2021-03-07 20:07:30 +00:00
if ( ti - > get_parent ( ) ! = tree - > get_root ( ) - > get_first_child ( ) ) {
2019-08-22 04:22:52 +00:00
// Not in the favorite section.
2018-09-13 20:38:35 +00:00
if ( fpath ! = " res:// " ) {
// We drop between two files
if ( fpath . ends_with ( " / " ) ) {
fpath = fpath . substr ( 0 , fpath . length ( ) - 1 ) ;
}
target = fpath . get_base_dir ( ) ;
return ;
2018-08-23 15:00:30 +00:00
}
}
}
}
}
2017-10-25 14:27:35 +00:00
}
}
2018-11-03 17:36:59 +00:00
void FileSystemDock : : _file_and_folders_fill_popup ( PopupMenu * p_popup , Vector < String > p_paths , bool p_display_path_dependent_options ) {
2019-08-22 04:22:52 +00:00
// Add options for files and folders.
2020-12-15 12:04:21 +00:00
ERR_FAIL_COND_MSG ( p_paths . is_empty ( ) , " Path cannot be empty. " ) ;
2016-05-15 23:25:51 +00:00
2017-10-09 13:59:48 +00:00
Vector < String > filenames ;
Vector < String > foldernames ;
2016-05-15 23:25:51 +00:00
2018-09-18 12:02:59 +00:00
Vector < String > favorites = EditorSettings : : get_singleton ( ) - > get_favorites ( ) ;
2018-09-13 16:11:05 +00:00
2017-10-09 13:59:48 +00:00
bool all_files = true ;
bool all_files_scenes = true ;
bool all_folders = true ;
2018-09-13 16:11:05 +00:00
bool all_favorites = true ;
bool all_not_favorites = true ;
2019-09-06 11:57:51 +00:00
2018-08-23 15:00:30 +00:00
for ( int i = 0 ; i < p_paths . size ( ) ; i + + ) {
String fpath = p_paths [ i ] ;
2017-09-03 20:35:18 +00:00
if ( fpath . ends_with ( " / " ) ) {
foldernames . push_back ( fpath ) ;
2017-10-09 13:59:48 +00:00
all_files = false ;
2016-05-27 17:18:40 +00:00
} else {
2017-09-03 20:35:18 +00:00
filenames . push_back ( fpath ) ;
2017-10-09 13:59:48 +00:00
all_folders = false ;
2017-09-03 20:35:18 +00:00
all_files_scenes & = ( EditorFileSystem : : get_singleton ( ) - > get_file_type ( fpath ) = = " PackedScene " ) ;
2016-05-27 17:18:40 +00:00
}
2018-09-13 16:11:05 +00:00
2019-08-22 04:22:52 +00:00
// Check if in favorites.
2018-09-13 16:11:05 +00:00
bool found = false ;
for ( int j = 0 ; j < favorites . size ( ) ; j + + ) {
if ( favorites [ j ] = = fpath ) {
found = true ;
break ;
}
}
if ( found ) {
all_not_favorites = false ;
} else {
all_favorites = false ;
}
2016-05-15 23:25:51 +00:00
}
2017-12-01 08:01:50 +00:00
if ( all_files ) {
2019-05-08 02:35:23 +00:00
if ( all_files_scenes ) {
if ( filenames . size ( ) = = 1 ) {
2021-07-17 21:22:52 +00:00
p_popup - > add_icon_item ( get_theme_icon ( SNAME ( " Load " ) , SNAME ( " EditorIcons " ) ) , TTR ( " Open Scene " ) , FILE_OPEN ) ;
p_popup - > add_icon_item ( get_theme_icon ( SNAME ( " CreateNewSceneFrom " ) , SNAME ( " EditorIcons " ) ) , TTR ( " New Inherited Scene " ) , FILE_INHERIT ) ;
2019-11-11 15:41:46 +00:00
if ( ProjectSettings : : get_singleton ( ) - > get ( " application/run/main_scene " ) ! = filenames [ 0 ] ) {
2021-07-17 21:22:52 +00:00
p_popup - > add_icon_item ( get_theme_icon ( SNAME ( " PlayScene " ) , SNAME ( " EditorIcons " ) ) , TTR ( " Set As Main Scene " ) , FILE_MAIN_SCENE ) ;
2019-11-11 15:41:46 +00:00
}
2019-05-08 02:35:23 +00:00
} else {
2021-07-17 21:22:52 +00:00
p_popup - > add_icon_item ( get_theme_icon ( SNAME ( " Load " ) , SNAME ( " EditorIcons " ) ) , TTR ( " Open Scenes " ) , FILE_OPEN ) ;
2019-05-08 02:35:23 +00:00
}
2021-07-17 21:22:52 +00:00
p_popup - > add_icon_item ( get_theme_icon ( SNAME ( " Instance " ) , SNAME ( " EditorIcons " ) ) , TTR ( " Instance " ) , FILE_INSTANCE ) ;
2018-08-23 15:00:30 +00:00
p_popup - > add_separator ( ) ;
2019-05-08 02:35:23 +00:00
} else if ( filenames . size ( ) = = 1 ) {
2021-07-17 21:22:52 +00:00
p_popup - > add_icon_item ( get_theme_icon ( SNAME ( " Load " ) , SNAME ( " EditorIcons " ) ) , TTR ( " Open " ) , FILE_OPEN ) ;
2018-08-23 15:00:30 +00:00
p_popup - > add_separator ( ) ;
2017-12-09 02:33:28 +00:00
}
2018-09-13 16:11:05 +00:00
}
if ( p_paths . size ( ) > = 1 ) {
if ( ! all_favorites ) {
2021-07-17 21:22:52 +00:00
p_popup - > add_icon_item ( get_theme_icon ( SNAME ( " Favorites " ) , SNAME ( " EditorIcons " ) ) , TTR ( " Add to Favorites " ) , FILE_ADD_FAVORITE ) ;
2018-09-13 16:11:05 +00:00
}
if ( ! all_not_favorites ) {
2021-07-17 21:22:52 +00:00
p_popup - > add_icon_item ( get_theme_icon ( SNAME ( " NonFavorite " ) , SNAME ( " EditorIcons " ) ) , TTR ( " Remove from Favorites " ) , FILE_REMOVE_FAVORITE ) ;
2018-09-13 16:11:05 +00:00
}
p_popup - > add_separator ( ) ;
}
2017-12-09 02:33:28 +00:00
2018-09-13 16:11:05 +00:00
if ( all_files ) {
2017-12-09 02:33:28 +00:00
if ( filenames . size ( ) = = 1 ) {
2018-08-23 15:00:30 +00:00
p_popup - > add_item ( TTR ( " Edit Dependencies... " ) , FILE_DEPENDENCIES ) ;
p_popup - > add_item ( TTR ( " View Owners... " ) , FILE_OWNERS ) ;
p_popup - > add_separator ( ) ;
2017-10-09 13:59:48 +00:00
}
2017-12-09 02:33:28 +00:00
2017-10-09 13:59:48 +00:00
} else if ( all_folders & & foldernames . size ( ) > 0 ) {
2021-07-17 21:22:52 +00:00
p_popup - > add_icon_item ( get_theme_icon ( SNAME ( " Load " ) , SNAME ( " EditorIcons " ) ) , TTR ( " Open " ) , FILE_OPEN ) ;
2018-08-23 15:00:30 +00:00
p_popup - > add_separator ( ) ;
2016-05-15 23:25:51 +00:00
}
2018-08-23 15:00:30 +00:00
if ( p_paths . size ( ) = = 1 ) {
2021-07-17 21:22:52 +00:00
p_popup - > add_icon_shortcut ( get_theme_icon ( SNAME ( " ActionCopy " ) , SNAME ( " EditorIcons " ) ) , ED_GET_SHORTCUT ( " filesystem_dock/copy_path " ) , FILE_COPY_PATH ) ;
2019-08-09 23:15:25 +00:00
if ( p_paths [ 0 ] ! = " res:// " ) {
2021-07-17 21:22:52 +00:00
p_popup - > add_icon_shortcut ( get_theme_icon ( SNAME ( " Rename " ) , SNAME ( " EditorIcons " ) ) , ED_GET_SHORTCUT ( " filesystem_dock/rename " ) , FILE_RENAME ) ;
p_popup - > add_icon_shortcut ( get_theme_icon ( SNAME ( " Duplicate " ) , SNAME ( " EditorIcons " ) ) , ED_GET_SHORTCUT ( " filesystem_dock/duplicate " ) , FILE_DUPLICATE ) ;
2019-08-09 23:15:25 +00:00
}
2018-08-23 15:00:30 +00:00
}
2019-08-09 23:15:25 +00:00
if ( p_paths . size ( ) > 1 | | p_paths [ 0 ] ! = " res:// " ) {
2021-07-17 21:22:52 +00:00
p_popup - > add_icon_item ( get_theme_icon ( SNAME ( " MoveUp " ) , SNAME ( " EditorIcons " ) ) , TTR ( " Move To... " ) , FILE_MOVE ) ;
p_popup - > add_icon_shortcut ( get_theme_icon ( SNAME ( " Remove " ) , SNAME ( " EditorIcons " ) ) , ED_GET_SHORTCUT ( " filesystem_dock/delete " ) , FILE_REMOVE ) ;
2019-08-09 23:15:25 +00:00
}
2018-08-23 15:00:30 +00:00
if ( p_paths . size ( ) = = 1 ) {
p_popup - > add_separator ( ) ;
2018-11-03 17:36:59 +00:00
if ( p_display_path_dependent_options ) {
2021-07-17 21:22:52 +00:00
p_popup - > add_icon_item ( get_theme_icon ( SNAME ( " Folder " ) , SNAME ( " EditorIcons " ) ) , TTR ( " New Folder... " ) , FILE_NEW_FOLDER ) ;
p_popup - > add_icon_item ( get_theme_icon ( SNAME ( " PackedScene " ) , SNAME ( " EditorIcons " ) ) , TTR ( " New Scene... " ) , FILE_NEW_SCENE ) ;
p_popup - > add_icon_item ( get_theme_icon ( SNAME ( " Script " ) , SNAME ( " EditorIcons " ) ) , TTR ( " New Script... " ) , FILE_NEW_SCRIPT ) ;
p_popup - > add_icon_item ( get_theme_icon ( SNAME ( " Object " ) , SNAME ( " EditorIcons " ) ) , TTR ( " New Resource... " ) , FILE_NEW_RESOURCE ) ;
2021-09-23 21:09:15 +00:00
p_popup - > add_icon_item ( get_theme_icon ( SNAME ( " TextFile " ) , SNAME ( " EditorIcons " ) ) , TTR ( " New TextFile... " ) , FILE_NEW_TEXTFILE ) ;
2019-08-22 04:22:52 +00:00
p_popup - > add_separator ( ) ;
2018-11-03 17:36:59 +00:00
}
2018-08-23 15:00:30 +00:00
String fpath = p_paths [ 0 ] ;
2018-10-26 19:11:36 +00:00
String item_text = fpath . ends_with ( " / " ) ? TTR ( " Open in File Manager " ) : TTR ( " Show in File Manager " ) ;
2021-07-17 21:22:52 +00:00
p_popup - > add_icon_item ( get_theme_icon ( SNAME ( " Filesystem " ) , SNAME ( " EditorIcons " ) ) , item_text , FILE_SHOW_IN_EXPLORER ) ;
2022-01-18 23:51:10 +00:00
path = fpath ;
2016-05-15 23:25:51 +00:00
}
2018-08-23 15:00:30 +00:00
}
2016-05-15 23:25:51 +00:00
2018-08-23 15:00:30 +00:00
void FileSystemDock : : _tree_rmb_select ( const Vector2 & p_pos ) {
2019-08-22 04:22:52 +00:00
// Right click is pressed in the tree.
2019-08-09 23:15:25 +00:00
Vector < String > paths = _tree_get_selected ( false ) ;
2018-08-11 12:43:00 +00:00
2020-09-07 12:09:53 +00:00
tree_popup - > clear ( ) ;
2018-08-23 15:00:30 +00:00
if ( paths . size ( ) = = 1 ) {
if ( paths [ 0 ] . ends_with ( " / " ) ) {
2021-07-17 21:22:52 +00:00
tree_popup - > add_icon_item ( get_theme_icon ( SNAME ( " GuiTreeArrowDown " ) , SNAME ( " EditorIcons " ) ) , TTR ( " Expand All " ) , FOLDER_EXPAND_ALL ) ;
tree_popup - > add_icon_item ( get_theme_icon ( SNAME ( " GuiTreeArrowRight " ) , SNAME ( " EditorIcons " ) ) , TTR ( " Collapse All " ) , FOLDER_COLLAPSE_ALL ) ;
2018-08-23 15:00:30 +00:00
tree_popup - > add_separator ( ) ;
}
}
2016-05-18 07:37:59 +00:00
2019-08-22 04:22:52 +00:00
// Popup.
2020-12-15 12:04:21 +00:00
if ( ! paths . is_empty ( ) ) {
2021-11-20 08:04:57 +00:00
tree_popup - > reset_size ( ) ;
2018-08-23 15:00:30 +00:00
_file_and_folders_fill_popup ( tree_popup , paths ) ;
2020-07-01 17:44:19 +00:00
tree_popup - > set_position ( tree - > get_screen_position ( ) + p_pos ) ;
2021-08-31 15:43:35 +00:00
tree_popup - > reset_size ( ) ;
2018-08-23 15:00:30 +00:00
tree_popup - > popup ( ) ;
}
2016-05-15 23:25:51 +00:00
}
2016-05-11 14:46:08 +00:00
2019-04-09 17:22:14 +00:00
void FileSystemDock : : _tree_rmb_empty ( const Vector2 & p_pos ) {
2019-08-22 04:22:52 +00:00
// Right click is pressed in the empty space of the tree.
2019-04-09 17:22:14 +00:00
path = " res:// " ;
tree_popup - > clear ( ) ;
2021-11-20 08:04:57 +00:00
tree_popup - > reset_size ( ) ;
2021-07-17 21:22:52 +00:00
tree_popup - > add_icon_item ( get_theme_icon ( SNAME ( " Folder " ) , SNAME ( " EditorIcons " ) ) , TTR ( " New Folder... " ) , FILE_NEW_FOLDER ) ;
tree_popup - > add_icon_item ( get_theme_icon ( SNAME ( " PackedScene " ) , SNAME ( " EditorIcons " ) ) , TTR ( " New Scene... " ) , FILE_NEW_SCENE ) ;
tree_popup - > add_icon_item ( get_theme_icon ( SNAME ( " Script " ) , SNAME ( " EditorIcons " ) ) , TTR ( " New Script... " ) , FILE_NEW_SCRIPT ) ;
tree_popup - > add_icon_item ( get_theme_icon ( SNAME ( " Object " ) , SNAME ( " EditorIcons " ) ) , TTR ( " New Resource... " ) , FILE_NEW_RESOURCE ) ;
2021-09-23 21:09:15 +00:00
tree_popup - > add_icon_item ( get_theme_icon ( SNAME ( " TextFile " ) , SNAME ( " EditorIcons " ) ) , TTR ( " New TextFile... " ) , FILE_NEW_TEXTFILE ) ;
2022-01-18 23:51:10 +00:00
tree_popup - > add_separator ( ) ;
tree_popup - > add_icon_item ( get_theme_icon ( SNAME ( " Filesystem " ) , SNAME ( " EditorIcons " ) ) , TTR ( " Open in File Manager " ) , FILE_SHOW_IN_EXPLORER ) ;
2021-08-31 15:43:35 +00:00
tree_popup - > set_position ( tree - > get_screen_position ( ) + p_pos ) ;
tree_popup - > reset_size ( ) ;
2019-04-09 17:22:14 +00:00
tree_popup - > popup ( ) ;
}
2019-04-09 12:54:41 +00:00
void FileSystemDock : : _tree_empty_selected ( ) {
tree - > deselect_all ( ) ;
}
2018-08-23 15:00:30 +00:00
void FileSystemDock : : _file_list_rmb_select ( int p_item , const Vector2 & p_pos ) {
2019-08-22 04:22:52 +00:00
// Right click is pressed in the file list.
2018-08-23 15:00:30 +00:00
Vector < String > paths ;
for ( int i = 0 ; i < files - > get_item_count ( ) ; i + + ) {
2020-05-14 14:41:43 +00:00
if ( ! files - > is_selected ( i ) ) {
2018-08-23 15:00:30 +00:00
continue ;
2020-05-14 14:41:43 +00:00
}
2018-08-23 15:00:30 +00:00
if ( files - > get_item_text ( p_item ) = = " .. " ) {
2020-12-21 10:26:41 +00:00
files - > deselect ( i ) ;
2018-08-23 15:00:30 +00:00
continue ;
}
paths . push_back ( files - > get_item_metadata ( i ) ) ;
}
2017-11-20 18:25:13 +00:00
2019-08-22 04:22:52 +00:00
// Popup.
2020-12-15 12:04:21 +00:00
if ( ! paths . is_empty ( ) ) {
2018-08-23 15:00:30 +00:00
file_list_popup - > clear ( ) ;
2018-11-03 17:36:59 +00:00
_file_and_folders_fill_popup ( file_list_popup , paths , searched_string . length ( ) = = 0 ) ;
2021-08-31 15:43:35 +00:00
file_list_popup - > set_position ( files - > get_screen_position ( ) + p_pos ) ;
file_list_popup - > reset_size ( ) ;
2018-08-23 15:00:30 +00:00
file_list_popup - > popup ( ) ;
}
}
void FileSystemDock : : _file_list_rmb_pressed ( const Vector2 & p_pos ) {
2019-08-22 04:22:52 +00:00
// Right click on empty space for file list.
2020-05-14 14:41:43 +00:00
if ( searched_string . length ( ) > 0 ) {
2018-11-03 17:36:59 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2018-11-03 17:36:59 +00:00
2022-01-18 23:51:10 +00:00
path = current_path - > get_text ( ) ;
2018-08-23 15:00:30 +00:00
file_list_popup - > clear ( ) ;
2021-11-20 08:04:57 +00:00
file_list_popup - > reset_size ( ) ;
2018-08-23 15:00:30 +00:00
2021-07-17 21:22:52 +00:00
file_list_popup - > add_icon_item ( get_theme_icon ( SNAME ( " Folder " ) , SNAME ( " EditorIcons " ) ) , TTR ( " New Folder... " ) , FILE_NEW_FOLDER ) ;
file_list_popup - > add_icon_item ( get_theme_icon ( SNAME ( " PackedScene " ) , SNAME ( " EditorIcons " ) ) , TTR ( " New Scene... " ) , FILE_NEW_SCENE ) ;
file_list_popup - > add_icon_item ( get_theme_icon ( SNAME ( " Script " ) , SNAME ( " EditorIcons " ) ) , TTR ( " New Script... " ) , FILE_NEW_SCRIPT ) ;
file_list_popup - > add_icon_item ( get_theme_icon ( SNAME ( " Object " ) , SNAME ( " EditorIcons " ) ) , TTR ( " New Resource... " ) , FILE_NEW_RESOURCE ) ;
2021-09-23 21:09:15 +00:00
file_list_popup - > add_icon_item ( get_theme_icon ( SNAME ( " TextFile " ) , SNAME ( " EditorIcons " ) ) , TTR ( " New TextFile... " ) , FILE_NEW_TEXTFILE ) ;
2019-08-22 04:22:52 +00:00
file_list_popup - > add_separator ( ) ;
2021-07-17 21:22:52 +00:00
file_list_popup - > add_icon_item ( get_theme_icon ( SNAME ( " Filesystem " ) , SNAME ( " EditorIcons " ) ) , TTR ( " Open in File Manager " ) , FILE_SHOW_IN_EXPLORER ) ;
2021-08-31 15:43:35 +00:00
file_list_popup - > set_position ( files - > get_screen_position ( ) + p_pos ) ;
file_list_popup - > reset_size ( ) ;
2018-08-23 15:00:30 +00:00
file_list_popup - > popup ( ) ;
2017-11-20 18:25:13 +00:00
}
2017-03-05 15:44:50 +00:00
void FileSystemDock : : select_file ( const String & p_file ) {
2019-01-17 19:40:38 +00:00
_navigate_to_path ( p_file ) ;
2017-01-25 17:30:40 +00:00
}
2017-03-05 15:44:50 +00:00
void FileSystemDock : : _file_multi_selected ( int p_index , bool p_selected ) {
2019-08-22 04:22:52 +00:00
// Set the path to the current focused item.
2018-08-23 15:00:30 +00:00
int current = files - > get_current ( ) ;
if ( current = = p_index ) {
String fpath = files - > get_item_metadata ( current ) ;
if ( ! fpath . ends_with ( " / " ) ) {
path = fpath ;
2018-09-13 15:35:44 +00:00
if ( display_mode = = DISPLAY_MODE_SPLIT ) {
2018-09-13 21:28:21 +00:00
_update_tree ( _compute_uncollapsed_paths ( ) ) ;
2018-08-23 15:00:30 +00:00
}
}
}
2019-08-22 04:22:52 +00:00
// Update the import dock.
2017-11-02 13:05:34 +00:00
import_dock_needs_update = true ;
2021-07-17 21:22:52 +00:00
call_deferred ( SNAME ( " _update_import_dock " ) ) ;
2017-02-01 12:45:45 +00:00
}
2018-08-23 15:00:30 +00:00
void FileSystemDock : : _tree_gui_input ( Ref < InputEvent > p_event ) {
2018-01-05 19:45:54 +00:00
Ref < InputEventKey > key = p_event ;
if ( key . is_valid ( ) & & key - > is_pressed ( ) & & ! key - > is_echo ( ) ) {
if ( ED_IS_SHORTCUT ( " filesystem_dock/duplicate " , p_event ) ) {
2018-08-23 15:00:30 +00:00
_tree_rmb_option ( FILE_DUPLICATE ) ;
2018-01-05 19:45:54 +00:00
} else if ( ED_IS_SHORTCUT ( " filesystem_dock/copy_path " , p_event ) ) {
2018-08-23 15:00:30 +00:00
_tree_rmb_option ( FILE_COPY_PATH ) ;
2018-01-05 19:45:54 +00:00
} else if ( ED_IS_SHORTCUT ( " filesystem_dock/delete " , p_event ) ) {
2018-08-23 15:00:30 +00:00
_tree_rmb_option ( FILE_REMOVE ) ;
2018-03-26 17:50:48 +00:00
} else if ( ED_IS_SHORTCUT ( " filesystem_dock/rename " , p_event ) ) {
2018-08-23 15:00:30 +00:00
_tree_rmb_option ( FILE_RENAME ) ;
2021-05-14 00:13:17 +00:00
} else if ( ED_IS_SHORTCUT ( " editor/open_search " , p_event ) ) {
2021-06-03 23:22:50 +00:00
focus_on_filter ( ) ;
2020-12-02 22:15:33 +00:00
} else {
return ;
2018-01-05 19:45:54 +00:00
}
2020-12-02 22:15:33 +00:00
accept_event ( ) ;
2018-01-05 19:45:54 +00:00
}
}
2018-08-23 15:00:30 +00:00
void FileSystemDock : : _file_list_gui_input ( Ref < InputEvent > p_event ) {
Ref < InputEventKey > key = p_event ;
if ( key . is_valid ( ) & & key - > is_pressed ( ) & & ! key - > is_echo ( ) ) {
if ( ED_IS_SHORTCUT ( " filesystem_dock/duplicate " , p_event ) ) {
_file_list_rmb_option ( FILE_DUPLICATE ) ;
} else if ( ED_IS_SHORTCUT ( " filesystem_dock/copy_path " , p_event ) ) {
_file_list_rmb_option ( FILE_COPY_PATH ) ;
} else if ( ED_IS_SHORTCUT ( " filesystem_dock/delete " , p_event ) ) {
_file_list_rmb_option ( FILE_REMOVE ) ;
} else if ( ED_IS_SHORTCUT ( " filesystem_dock/rename " , p_event ) ) {
_file_list_rmb_option ( FILE_RENAME ) ;
2021-05-14 00:13:17 +00:00
} else if ( ED_IS_SHORTCUT ( " editor/open_search " , p_event ) ) {
2021-06-03 23:22:50 +00:00
focus_on_filter ( ) ;
2020-12-02 22:15:33 +00:00
} else {
return ;
2018-08-23 15:00:30 +00:00
}
2020-12-02 22:15:33 +00:00
accept_event ( ) ;
2018-08-23 15:00:30 +00:00
}
2017-11-02 13:05:34 +00:00
}
2020-08-14 06:31:41 +00:00
void FileSystemDock : : _get_imported_files ( const String & p_path , Vector < String > & files ) const {
if ( ! p_path . ends_with ( " / " ) ) {
if ( FileAccess : : exists ( p_path + " .import " ) ) {
files . push_back ( p_path ) ;
}
2017-11-02 13:05:34 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2017-11-02 13:05:34 +00:00
2020-08-14 06:31:41 +00:00
DirAccess * da = DirAccess : : open ( p_path ) ;
da - > list_dir_begin ( ) ;
String n = da - > get_next ( ) ;
2021-12-09 09:42:46 +00:00
while ( ! n . is_empty ( ) ) {
2020-08-14 06:31:41 +00:00
if ( n ! = " . " & & n ! = " .. " & & ! n . ends_with ( " .import " ) ) {
String npath = p_path + n + ( da - > current_is_dir ( ) ? " / " : " " ) ;
_get_imported_files ( npath , files ) ;
}
n = da - > get_next ( ) ;
}
da - > list_dir_end ( ) ;
}
void FileSystemDock : : _update_import_dock ( ) {
2021-04-05 12:09:59 +00:00
if ( ! import_dock_needs_update ) {
2020-08-14 06:31:41 +00:00
return ;
2021-04-05 12:09:59 +00:00
}
2020-08-14 06:31:41 +00:00
2019-08-22 04:22:52 +00:00
// List selected.
2018-09-24 12:26:26 +00:00
Vector < String > selected ;
2019-02-25 22:39:49 +00:00
if ( display_mode = = DISPLAY_MODE_TREE_ONLY ) {
2018-09-24 12:26:26 +00:00
// Use the tree
selected = _tree_get_selected ( ) ;
} else {
2019-08-22 04:22:52 +00:00
// Use the file list.
2018-09-24 12:26:26 +00:00
for ( int i = 0 ; i < files - > get_item_count ( ) ; i + + ) {
2021-04-05 12:09:59 +00:00
if ( ! files - > is_selected ( i ) ) {
2018-09-24 12:26:26 +00:00
continue ;
2021-04-05 12:09:59 +00:00
}
2018-09-24 12:26:26 +00:00
selected . push_back ( files - > get_item_metadata ( i ) ) ;
}
}
2020-08-14 06:31:41 +00:00
// Expand directory selection
Vector < String > efiles ;
for ( int i = 0 ; i < selected . size ( ) ; i + + ) {
_get_imported_files ( selected [ i ] , efiles ) ;
}
2019-08-22 04:22:52 +00:00
// Check import.
2017-02-01 12:45:45 +00:00
Vector < String > imports ;
String import_type ;
2020-08-14 06:31:41 +00:00
for ( int i = 0 ; i < efiles . size ( ) ; i + + ) {
String fpath = efiles [ i ] ;
2017-02-01 12:45:45 +00:00
Ref < ConfigFile > cf ;
2021-06-17 22:03:09 +00:00
cf . instantiate ( ) ;
2017-09-03 20:35:18 +00:00
Error err = cf - > load ( fpath + " .import " ) ;
2017-03-05 15:44:50 +00:00
if ( err ! = OK ) {
2017-02-01 12:45:45 +00:00
imports . clear ( ) ;
break ;
}
2021-03-23 14:20:14 +00:00
String type ;
if ( cf - > has_section_key ( " remap " , " type " ) ) {
type = cf - > get_value ( " remap " , " type " ) ;
}
2021-12-09 09:42:46 +00:00
if ( import_type . is_empty ( ) ) {
2017-03-05 15:44:50 +00:00
import_type = type ;
} else if ( import_type ! = type ) {
2019-08-22 04:22:52 +00:00
// All should be the same type.
2017-02-01 12:45:45 +00:00
imports . clear ( ) ;
break ;
}
2017-09-03 20:35:18 +00:00
imports . push_back ( fpath ) ;
2017-02-01 12:45:45 +00:00
}
2017-03-05 15:44:50 +00:00
if ( imports . size ( ) = = 0 ) {
2021-11-17 20:08:55 +00:00
ImportDock : : get_singleton ( ) - > clear ( ) ;
2017-03-05 15:44:50 +00:00
} else if ( imports . size ( ) = = 1 ) {
2021-11-17 20:08:55 +00:00
ImportDock : : get_singleton ( ) - > set_edit_path ( imports [ 0 ] ) ;
2017-02-01 12:45:45 +00:00
} else {
2021-11-17 20:08:55 +00:00
ImportDock : : get_singleton ( ) - > set_edit_multiple_paths ( imports ) ;
2017-02-01 12:45:45 +00:00
}
2017-11-02 13:05:34 +00:00
import_dock_needs_update = false ;
2017-02-01 12:45:45 +00:00
}
2019-04-08 22:18:03 +00:00
void FileSystemDock : : _feature_profile_changed ( ) {
_update_display_mode ( true ) ;
}
2020-10-07 19:56:53 +00:00
void FileSystemDock : : set_file_sort ( FileSortOption p_file_sort ) {
for ( int i = 0 ; i ! = FILE_SORT_MAX ; i + + ) {
tree_button_sort - > get_popup ( ) - > set_item_checked ( i , ( i = = ( int ) p_file_sort ) ) ;
file_list_button_sort - > get_popup ( ) - > set_item_checked ( i , ( i = = ( int ) p_file_sort ) ) ;
}
file_sort = p_file_sort ;
// Update everything needed.
_update_tree ( _compute_uncollapsed_paths ( ) ) ;
_update_file_list ( true ) ;
}
void FileSystemDock : : _file_sort_popup ( int p_id ) {
set_file_sort ( ( FileSortOption ) p_id ) ;
}
MenuButton * FileSystemDock : : _create_file_menu_button ( ) {
MenuButton * button = memnew ( MenuButton ) ;
button - > set_flat ( true ) ;
button - > set_tooltip ( TTR ( " Sort files " ) ) ;
PopupMenu * p = button - > get_popup ( ) ;
p - > connect ( " id_pressed " , callable_mp ( this , & FileSystemDock : : _file_sort_popup ) ) ;
2021-05-15 16:59:57 +00:00
p - > add_radio_check_item ( TTR ( " Sort by Name (Ascending) " ) , FILE_SORT_NAME ) ;
p - > add_radio_check_item ( TTR ( " Sort by Name (Descending) " ) , FILE_SORT_NAME_REVERSE ) ;
p - > add_radio_check_item ( TTR ( " Sort by Type (Ascending) " ) , FILE_SORT_TYPE ) ;
p - > add_radio_check_item ( TTR ( " Sort by Type (Descending) " ) , FILE_SORT_TYPE_REVERSE ) ;
p - > add_radio_check_item ( TTR ( " Sort by Last Modified " ) , FILE_SORT_MODIFIED_TIME ) ;
p - > add_radio_check_item ( TTR ( " Sort by First Modified " ) , FILE_SORT_MODIFIED_TIME_REVERSE ) ;
2020-10-07 19:56:53 +00:00
p - > set_item_checked ( file_sort , true ) ;
return button ;
}
2016-07-21 13:34:57 +00:00
void FileSystemDock : : _bind_methods ( ) {
2017-03-05 15:44:50 +00:00
ClassDB : : bind_method ( D_METHOD ( " _update_tree " ) , & FileSystemDock : : _update_tree ) ;
2018-11-13 19:17:33 +00:00
2018-09-12 11:10:49 +00:00
ClassDB : : bind_method ( D_METHOD ( " _file_list_thumbnail_done " ) , & FileSystemDock : : _file_list_thumbnail_done ) ;
ClassDB : : bind_method ( D_METHOD ( " _tree_thumbnail_done " ) , & FileSystemDock : : _tree_thumbnail_done ) ;
2017-02-13 11:47:24 +00:00
ClassDB : : bind_method ( D_METHOD ( " _select_file " ) , & FileSystemDock : : _select_file ) ;
2021-05-15 21:48:59 +00:00
ClassDB : : bind_method ( D_METHOD ( " _get_drag_data_fw " , " position " , " from " ) , & FileSystemDock : : get_drag_data_fw ) ;
ClassDB : : bind_method ( D_METHOD ( " _can_drop_data_fw " , " position " , " data " , " from " ) , & FileSystemDock : : can_drop_data_fw ) ;
ClassDB : : bind_method ( D_METHOD ( " _drop_data_fw " , " position " , " data " , " from " ) , & FileSystemDock : : drop_data_fw ) ;
2020-07-01 12:18:13 +00:00
ClassDB : : bind_method ( D_METHOD ( " navigate_to_path " , " path " ) , & FileSystemDock : : navigate_to_path ) ;
2016-07-03 16:15:15 +00:00
2017-11-02 13:05:34 +00:00
ClassDB : : bind_method ( D_METHOD ( " _update_import_dock " ) , & FileSystemDock : : _update_import_dock ) ;
2016-07-03 16:15:15 +00:00
2019-05-08 02:35:23 +00:00
ADD_SIGNAL ( MethodInfo ( " inherit " , PropertyInfo ( Variant : : STRING , " file " ) ) ) ;
2020-02-17 21:06:54 +00:00
ADD_SIGNAL ( MethodInfo ( " instance " , PropertyInfo ( Variant : : PACKED_STRING_ARRAY , " files " ) ) ) ;
2018-11-13 19:17:33 +00:00
ADD_SIGNAL ( MethodInfo ( " file_removed " , PropertyInfo ( Variant : : STRING , " file " ) ) ) ;
ADD_SIGNAL ( MethodInfo ( " folder_removed " , PropertyInfo ( Variant : : STRING , " folder " ) ) ) ;
ADD_SIGNAL ( MethodInfo ( " files_moved " , PropertyInfo ( Variant : : STRING , " old_file " ) , PropertyInfo ( Variant : : STRING , " new_file " ) ) ) ;
ADD_SIGNAL ( MethodInfo ( " folder_moved " , PropertyInfo ( Variant : : STRING , " old_folder " ) , PropertyInfo ( Variant : : STRING , " new_file " ) ) ) ;
2019-02-25 22:39:49 +00:00
ADD_SIGNAL ( MethodInfo ( " display_mode_changed " ) ) ;
2014-02-10 01:10:30 +00:00
}
2016-07-21 13:34:57 +00:00
FileSystemDock : : FileSystemDock ( EditorNode * p_editor ) {
2021-11-17 20:08:55 +00:00
singleton = this ;
2017-11-26 01:59:31 +00:00
set_name ( " FileSystem " ) ;
2017-03-05 15:44:50 +00:00
editor = p_editor ;
2017-09-03 20:35:18 +00:00
path = " res:// " ;
2016-05-15 23:25:51 +00:00
2021-08-13 21:31:57 +00:00
// `KeyModifierMask::CMD | Key::C` conflicts with other editor shortcuts.
ED_SHORTCUT ( " filesystem_dock/copy_path " , TTR ( " Copy Path " ) , KeyModifierMask : : CMD | KeyModifierMask : : SHIFT | Key : : C ) ;
ED_SHORTCUT ( " filesystem_dock/duplicate " , TTR ( " Duplicate... " ) , KeyModifierMask : : CMD | Key : : D ) ;
ED_SHORTCUT ( " filesystem_dock/delete " , TTR ( " Delete " ) , Key : : KEY_DELETE ) ;
ED_SHORTCUT ( " filesystem_dock/rename " , TTR ( " Rename... " ) , Key : : F2 ) ;
ED_SHORTCUT_OVERRIDE ( " filesystem_dock/rename " , " macos " , Key : : ENTER ) ;
2018-01-05 19:45:54 +00:00
2018-09-13 19:49:56 +00:00
VBoxContainer * top_vbc = memnew ( VBoxContainer ) ;
add_child ( top_vbc ) ;
2017-03-05 15:44:50 +00:00
HBoxContainer * toolbar_hbc = memnew ( HBoxContainer ) ;
2022-02-08 09:14:58 +00:00
toolbar_hbc - > add_theme_constant_override ( " separation " , 0 ) ;
2018-09-13 19:49:56 +00:00
top_vbc - > add_child ( toolbar_hbc ) ;
2014-02-10 01:10:30 +00:00
2020-06-19 18:49:04 +00:00
button_hist_prev = memnew ( Button ) ;
button_hist_prev - > set_flat ( true ) ;
2015-08-23 23:15:56 +00:00
button_hist_prev - > set_disabled ( true ) ;
2017-09-03 20:35:18 +00:00
button_hist_prev - > set_focus_mode ( FOCUS_NONE ) ;
2019-03-05 17:04:22 +00:00
button_hist_prev - > set_tooltip ( TTR ( " Previous Folder/File " ) ) ;
2017-09-03 20:35:18 +00:00
toolbar_hbc - > add_child ( button_hist_prev ) ;
2015-08-23 23:15:56 +00:00
2020-06-19 18:49:04 +00:00
button_hist_next = memnew ( Button ) ;
button_hist_next - > set_flat ( true ) ;
2015-08-23 23:15:56 +00:00
button_hist_next - > set_disabled ( true ) ;
button_hist_next - > set_focus_mode ( FOCUS_NONE ) ;
2019-03-05 17:04:22 +00:00
button_hist_next - > set_tooltip ( TTR ( " Next Folder/File " ) ) ;
2017-09-03 20:35:18 +00:00
toolbar_hbc - > add_child ( button_hist_next ) ;
2015-08-23 23:15:56 +00:00
2017-03-05 15:44:50 +00:00
current_path = memnew ( LineEdit ) ;
2020-09-03 11:22:16 +00:00
current_path - > set_structured_text_bidi_override ( Control : : STRUCTURED_TEXT_FILE ) ;
2016-05-24 02:24:17 +00:00
current_path - > set_h_size_flags ( SIZE_EXPAND_FILL ) ;
2018-09-28 22:11:26 +00:00
_set_current_path_text ( path ) ;
2016-05-24 02:24:17 +00:00
toolbar_hbc - > add_child ( current_path ) ;
2017-03-05 15:44:50 +00:00
button_reload = memnew ( Button ) ;
2020-02-21 17:28:45 +00:00
button_reload - > connect ( " pressed " , callable_mp ( this , & FileSystemDock : : _rescan ) ) ;
2015-08-23 23:15:56 +00:00
button_reload - > set_focus_mode ( FOCUS_NONE ) ;
2016-05-04 01:25:37 +00:00
button_reload - > set_tooltip ( TTR ( " Re-Scan Filesystem " ) ) ;
2016-05-24 02:24:17 +00:00
button_reload - > hide ( ) ;
2017-09-03 20:35:18 +00:00
toolbar_hbc - > add_child ( button_reload ) ;
2015-08-23 23:15:56 +00:00
2018-09-13 22:16:43 +00:00
button_toggle_display_mode = memnew ( Button ) ;
button_toggle_display_mode - > set_toggle_mode ( true ) ;
2020-02-21 17:28:45 +00:00
button_toggle_display_mode - > connect ( " toggled " , callable_mp ( this , & FileSystemDock : : _toggle_split_mode ) ) ;
2018-09-13 22:16:43 +00:00
button_toggle_display_mode - > set_focus_mode ( FOCUS_NONE ) ;
2019-03-05 17:04:22 +00:00
button_toggle_display_mode - > set_tooltip ( TTR ( " Toggle Split Mode " ) ) ;
2021-05-27 15:32:30 +00:00
button_toggle_display_mode - > set_flat ( true ) ;
2018-09-13 22:16:43 +00:00
toolbar_hbc - > add_child ( button_toggle_display_mode ) ;
2020-10-07 19:56:53 +00:00
toolbar2_hbc = memnew ( HBoxContainer ) ;
2022-02-08 09:14:58 +00:00
toolbar2_hbc - > add_theme_constant_override ( " separation " , 0 ) ;
2018-09-13 19:49:56 +00:00
top_vbc - > add_child ( toolbar2_hbc ) ;
tree_search_box = memnew ( LineEdit ) ;
tree_search_box - > set_h_size_flags ( SIZE_EXPAND_FILL ) ;
tree_search_box - > set_placeholder ( TTR ( " Search files " ) ) ;
2020-02-21 17:28:45 +00:00
tree_search_box - > connect ( " text_changed " , callable_mp ( this , & FileSystemDock : : _search_changed ) , varray ( tree_search_box ) ) ;
2018-09-13 19:49:56 +00:00
toolbar2_hbc - > add_child ( tree_search_box ) ;
2020-10-07 19:56:53 +00:00
tree_button_sort = _create_file_menu_button ( ) ;
toolbar2_hbc - > add_child ( tree_button_sort ) ;
2018-08-23 15:00:30 +00:00
file_list_popup = memnew ( PopupMenu ) ;
2020-03-12 12:37:40 +00:00
2018-08-23 15:00:30 +00:00
add_child ( file_list_popup ) ;
2015-08-23 23:15:56 +00:00
2018-08-23 15:00:30 +00:00
tree_popup = memnew ( PopupMenu ) ;
2020-03-12 12:37:40 +00:00
2018-08-23 15:00:30 +00:00
add_child ( tree_popup ) ;
2017-01-10 12:19:59 +00:00
2017-03-05 15:44:50 +00:00
split_box = memnew ( VSplitContainer ) ;
2016-05-15 23:25:51 +00:00
split_box - > set_v_size_flags ( SIZE_EXPAND_FILL ) ;
2017-09-03 20:35:18 +00:00
add_child ( split_box ) ;
2014-05-16 11:48:23 +00:00
2017-03-05 15:44:50 +00:00
tree = memnew ( Tree ) ;
2015-08-23 23:15:56 +00:00
tree - > set_hide_root ( true ) ;
2016-05-15 23:25:51 +00:00
tree - > set_drag_forwarding ( this ) ;
2017-01-10 12:19:59 +00:00
tree - > set_allow_rmb_select ( true ) ;
2018-08-23 15:00:30 +00:00
tree - > set_select_mode ( Tree : : SELECT_MULTI ) ;
2018-09-24 09:59:43 +00:00
tree - > set_custom_minimum_size ( Size2 ( 0 , 15 * EDSCALE ) ) ;
2017-09-03 20:35:18 +00:00
split_box - > add_child ( tree ) ;
2014-05-16 11:48:23 +00:00
2020-02-21 17:28:45 +00:00
tree - > connect ( " item_activated " , callable_mp ( this , & FileSystemDock : : _tree_activate_file ) ) ;
tree - > connect ( " multi_selected " , callable_mp ( this , & FileSystemDock : : _tree_multi_selected ) ) ;
tree - > connect ( " item_rmb_selected " , callable_mp ( this , & FileSystemDock : : _tree_rmb_select ) ) ;
tree - > connect ( " empty_rmb " , callable_mp ( this , & FileSystemDock : : _tree_rmb_empty ) ) ;
tree - > connect ( " nothing_selected " , callable_mp ( this , & FileSystemDock : : _tree_empty_selected ) ) ;
tree - > connect ( " gui_input " , callable_mp ( this , & FileSystemDock : : _tree_gui_input ) ) ;
2015-08-23 23:15:56 +00:00
2017-03-05 15:44:50 +00:00
file_list_vb = memnew ( VBoxContainer ) ;
2016-05-15 23:25:51 +00:00
file_list_vb - > set_v_size_flags ( SIZE_EXPAND_FILL ) ;
2017-09-03 20:35:18 +00:00
split_box - > add_child ( file_list_vb ) ;
2015-08-23 23:15:56 +00:00
2017-03-05 15:44:50 +00:00
path_hb = memnew ( HBoxContainer ) ;
2016-05-15 23:25:51 +00:00
file_list_vb - > add_child ( path_hb ) ;
2018-09-13 19:49:56 +00:00
file_list_search_box = memnew ( LineEdit ) ;
file_list_search_box - > set_h_size_flags ( SIZE_EXPAND_FILL ) ;
file_list_search_box - > set_placeholder ( TTR ( " Search files " ) ) ;
2020-02-21 17:28:45 +00:00
file_list_search_box - > connect ( " text_changed " , callable_mp ( this , & FileSystemDock : : _search_changed ) , varray ( file_list_search_box ) ) ;
2018-09-13 19:49:56 +00:00
path_hb - > add_child ( file_list_search_box ) ;
2016-05-15 23:25:51 +00:00
2020-10-07 19:56:53 +00:00
file_list_button_sort = _create_file_menu_button ( ) ;
path_hb - > add_child ( file_list_button_sort ) ;
2020-06-19 18:49:04 +00:00
button_file_list_display_mode = memnew ( Button ) ;
button_file_list_display_mode - > set_flat ( true ) ;
2018-08-13 17:05:31 +00:00
path_hb - > add_child ( button_file_list_display_mode ) ;
2015-08-23 23:15:56 +00:00
2017-09-03 20:35:18 +00:00
files = memnew ( ItemList ) ;
files - > set_v_size_flags ( SIZE_EXPAND_FILL ) ;
files - > set_select_mode ( ItemList : : SELECT_MULTI ) ;
files - > set_drag_forwarding ( this ) ;
2020-02-21 17:28:45 +00:00
files - > connect ( " item_rmb_selected " , callable_mp ( this , & FileSystemDock : : _file_list_rmb_select ) ) ;
files - > connect ( " gui_input " , callable_mp ( this , & FileSystemDock : : _file_list_gui_input ) ) ;
files - > connect ( " multi_selected " , callable_mp ( this , & FileSystemDock : : _file_multi_selected ) ) ;
files - > connect ( " rmb_clicked " , callable_mp ( this , & FileSystemDock : : _file_list_rmb_pressed ) ) ;
2018-09-24 09:59:43 +00:00
files - > set_custom_minimum_size ( Size2 ( 0 , 15 * EDSCALE ) ) ;
2017-09-03 20:35:18 +00:00
files - > set_allow_rmb_select ( true ) ;
2016-05-15 23:25:51 +00:00
file_list_vb - > add_child ( files ) ;
2015-08-23 23:15:56 +00:00
2017-03-05 15:44:50 +00:00
scanning_vb = memnew ( VBoxContainer ) ;
2017-09-03 20:35:18 +00:00
scanning_vb - > hide ( ) ;
add_child ( scanning_vb ) ;
2017-03-05 15:44:50 +00:00
Label * slabel = memnew ( Label ) ;
2018-04-22 17:36:01 +00:00
slabel - > set_text ( TTR ( " Scanning Files, \n Please Wait... " ) ) ;
2021-11-25 02:58:47 +00:00
slabel - > set_horizontal_alignment ( HORIZONTAL_ALIGNMENT_CENTER ) ;
2015-08-23 23:15:56 +00:00
scanning_vb - > add_child ( slabel ) ;
2017-09-03 20:35:18 +00:00
2017-03-05 15:44:50 +00:00
scanning_progress = memnew ( ProgressBar ) ;
2015-08-23 23:15:56 +00:00
scanning_vb - > add_child ( scanning_progress ) ;
2017-03-05 15:44:50 +00:00
deps_editor = memnew ( DependencyEditor ) ;
2015-08-23 23:15:56 +00:00
add_child ( deps_editor ) ;
2017-11-15 04:05:49 +00:00
owners_editor = memnew ( DependencyEditorOwners ( editor ) ) ;
2015-08-23 23:15:56 +00:00
add_child ( owners_editor ) ;
2017-03-05 15:44:50 +00:00
remove_dialog = memnew ( DependencyRemoveDialog ) ;
2020-03-17 00:40:15 +00:00
remove_dialog - > connect ( " file_removed " , callable_mp ( this , & FileSystemDock : : _file_removed ) ) ;
remove_dialog - > connect ( " folder_removed " , callable_mp ( this , & FileSystemDock : : _folder_removed ) ) ;
2015-08-23 23:15:56 +00:00
add_child ( remove_dialog ) ;
2017-03-05 15:44:50 +00:00
move_dialog = memnew ( EditorDirDialog ) ;
2020-12-14 18:37:30 +00:00
move_dialog - > get_ok_button ( ) - > set_text ( TTR ( " Move " ) ) ;
2016-03-08 23:00:52 +00:00
add_child ( move_dialog ) ;
2020-03-03 09:46:03 +00:00
move_dialog - > connect ( " dir_selected " , callable_mp ( this , & FileSystemDock : : _move_operation_confirm ) , make_binds ( false ) ) ;
2016-03-08 23:00:52 +00:00
2017-10-01 21:59:27 +00:00
rename_dialog = memnew ( ConfirmationDialog ) ;
VBoxContainer * rename_dialog_vb = memnew ( VBoxContainer ) ;
rename_dialog - > add_child ( rename_dialog_vb ) ;
rename_dialog_text = memnew ( LineEdit ) ;
rename_dialog_vb - > add_margin_child ( TTR ( " Name: " ) , rename_dialog_text ) ;
2020-12-14 18:37:30 +00:00
rename_dialog - > get_ok_button ( ) - > set_text ( TTR ( " Rename " ) ) ;
2015-08-23 23:15:56 +00:00
add_child ( rename_dialog ) ;
2017-10-01 21:59:27 +00:00
rename_dialog - > register_text_enter ( rename_dialog_text ) ;
2020-02-21 17:28:45 +00:00
rename_dialog - > connect ( " confirmed " , callable_mp ( this , & FileSystemDock : : _rename_operation_confirm ) ) ;
2014-02-10 01:10:30 +00:00
2018-05-29 12:33:11 +00:00
overwrite_dialog = memnew ( ConfirmationDialog ) ;
2020-12-14 18:37:30 +00:00
overwrite_dialog - > get_ok_button ( ) - > set_text ( TTR ( " Overwrite " ) ) ;
2018-05-29 12:33:11 +00:00
add_child ( overwrite_dialog ) ;
2020-02-21 17:28:45 +00:00
overwrite_dialog - > connect ( " confirmed " , callable_mp ( this , & FileSystemDock : : _move_with_overwrite ) ) ;
2018-05-29 12:33:11 +00:00
2017-12-01 11:13:50 +00:00
duplicate_dialog = memnew ( ConfirmationDialog ) ;
VBoxContainer * duplicate_dialog_vb = memnew ( VBoxContainer ) ;
duplicate_dialog - > add_child ( duplicate_dialog_vb ) ;
duplicate_dialog_text = memnew ( LineEdit ) ;
duplicate_dialog_vb - > add_margin_child ( TTR ( " Name: " ) , duplicate_dialog_text ) ;
2020-12-14 18:37:30 +00:00
duplicate_dialog - > get_ok_button ( ) - > set_text ( TTR ( " Duplicate " ) ) ;
2017-12-01 11:13:50 +00:00
add_child ( duplicate_dialog ) ;
duplicate_dialog - > register_text_enter ( duplicate_dialog_text ) ;
2020-02-21 17:28:45 +00:00
duplicate_dialog - > connect ( " confirmed " , callable_mp ( this , & FileSystemDock : : _duplicate_operation_confirm ) ) ;
2017-12-01 11:13:50 +00:00
2017-10-01 22:33:43 +00:00
make_dir_dialog = memnew ( ConfirmationDialog ) ;
make_dir_dialog - > set_title ( TTR ( " Create Folder " ) ) ;
VBoxContainer * make_folder_dialog_vb = memnew ( VBoxContainer ) ;
make_dir_dialog - > add_child ( make_folder_dialog_vb ) ;
make_dir_dialog_text = memnew ( LineEdit ) ;
make_folder_dialog_vb - > add_margin_child ( TTR ( " Name: " ) , make_dir_dialog_text ) ;
add_child ( make_dir_dialog ) ;
make_dir_dialog - > register_text_enter ( make_dir_dialog_text ) ;
2020-02-21 17:28:45 +00:00
make_dir_dialog - > connect ( " confirmed " , callable_mp ( this , & FileSystemDock : : _make_dir_confirm ) ) ;
2017-10-01 22:33:43 +00:00
2019-08-15 17:47:21 +00:00
make_scene_dialog = memnew ( ConfirmationDialog ) ;
make_scene_dialog - > set_title ( TTR ( " Create Scene " ) ) ;
VBoxContainer * make_scene_dialog_vb = memnew ( VBoxContainer ) ;
make_scene_dialog - > add_child ( make_scene_dialog_vb ) ;
make_scene_dialog_text = memnew ( LineEdit ) ;
make_scene_dialog_vb - > add_margin_child ( TTR ( " Name: " ) , make_scene_dialog_text ) ;
add_child ( make_scene_dialog ) ;
make_scene_dialog - > register_text_enter ( make_scene_dialog_text ) ;
2020-02-21 17:28:45 +00:00
make_scene_dialog - > connect ( " confirmed " , callable_mp ( this , & FileSystemDock : : _make_scene_confirm ) ) ;
2019-08-15 17:47:21 +00:00
2019-12-24 06:37:55 +00:00
make_script_dialog = memnew ( ScriptCreateDialog ) ;
make_script_dialog - > set_title ( TTR ( " Create Script " ) ) ;
add_child ( make_script_dialog ) ;
2018-04-25 07:18:10 +00:00
2021-12-03 14:45:32 +00:00
make_shader_dialog = memnew ( ShaderCreateDialog ) ;
add_child ( make_shader_dialog ) ;
2018-07-22 15:53:40 +00:00
new_resource_dialog = memnew ( CreateDialog ) ;
add_child ( new_resource_dialog ) ;
new_resource_dialog - > set_base_type ( " Resource " ) ;
2020-02-21 17:28:45 +00:00
new_resource_dialog - > connect ( " create " , callable_mp ( this , & FileSystemDock : : _resource_created ) ) ;
2018-07-22 15:53:40 +00:00
2018-09-13 22:16:43 +00:00
searched_string = String ( ) ;
uncollapsed_paths_before_search = Vector < String > ( ) ;
2017-03-05 15:44:50 +00:00
updating_tree = false ;
2018-09-12 11:10:49 +00:00
tree_update_id = 0 ;
2017-03-05 15:44:50 +00:00
initialized = false ;
2017-11-02 13:05:34 +00:00
import_dock_needs_update = false ;
2014-02-10 01:10:30 +00:00
2017-03-05 15:44:50 +00:00
history_pos = 0 ;
2017-09-03 20:35:18 +00:00
history_max_size = 20 ;
history . push_back ( " res:// " ) ;
2016-05-15 23:25:51 +00:00
2019-02-25 22:39:49 +00:00
display_mode = DISPLAY_MODE_TREE_ONLY ;
old_display_mode = DISPLAY_MODE_TREE_ONLY ;
2018-08-13 17:05:31 +00:00
file_list_display_mode = FILE_LIST_DISPLAY_THUMBNAILS ;
2018-08-23 15:00:30 +00:00
always_show_folders = false ;
2014-05-16 11:48:23 +00:00
}
2016-07-21 13:34:57 +00:00
FileSystemDock : : ~ FileSystemDock ( ) {
2021-11-17 20:08:55 +00:00
singleton = nullptr ;
2014-05-16 11:48:23 +00:00
}