@ -175,12 +175,127 @@
EditorNode * EditorNode : : singleton = NULL ;
void EditorNode : : disambiguate_filenames ( const Vector < String > p_full_paths , Vector < String > & r_filenames ) {
// Keep track of a list of "index sets," i.e. sets of indices
// within disambiguated_scene_names which contain the same name.
Vector < Set < int > > index_sets ;
Map < String , int > scene_name_to_set_index ;
for ( int i = 0 ; i < r_filenames . size ( ) ; i + + ) {
String scene_name = r_filenames [ i ] ;
if ( ! scene_name_to_set_index . has ( scene_name ) ) {
index_sets . push_back ( Set < int > ( ) ) ;
scene_name_to_set_index . insert ( r_filenames [ i ] , index_sets . size ( ) - 1 ) ;
}
index_sets . write [ scene_name_to_set_index [ scene_name ] ] . insert ( i ) ;
}
// For each index set with a size > 1, we need to disambiguate
for ( int i = 0 ; i < index_sets . size ( ) ; i + + ) {
Set < int > iset = index_sets [ i ] ;
while ( iset . size ( ) > 1 ) {
// Append the parent folder to each scene name
for ( Set < int > : : Element * E = iset . front ( ) ; E ; E = E - > next ( ) ) {
int set_idx = E - > get ( ) ;
String scene_name = r_filenames [ set_idx ] ;
String full_path = p_full_paths [ set_idx ] ;
// Get rid of file extensions and res:// prefixes
if ( scene_name . rfind ( " . " ) > = 0 ) {
scene_name = scene_name . substr ( 0 , scene_name . rfind ( " . " ) ) ;
}
if ( full_path . begins_with ( " res:// " ) ) {
full_path = full_path . substr ( 6 ) ;
}
if ( full_path . rfind ( " . " ) > = 0 ) {
full_path = full_path . substr ( 0 , full_path . rfind ( " . " ) ) ;
}
int scene_name_size = scene_name . size ( ) ;
int full_path_size = full_path . size ( ) ;
int difference = full_path_size - scene_name_size ;
// Find just the parent folder of the current path and append it.
// If the current name is foo.tscn, and the full path is /some/folder/foo.tscn
// then slash_idx is the second '/', so that we select just "folder", and
// append that to yield "folder/foo.tscn".
if ( difference > 0 ) {
String parent = full_path . substr ( 0 , difference ) ;
int slash_idx = parent . rfind ( " / " ) ;
slash_idx = parent . rfind ( " / " , slash_idx - 1 ) ;
parent = slash_idx > = 0 ? parent . substr ( slash_idx + 1 ) : parent ;
r_filenames . write [ set_idx ] = parent + r_filenames [ set_idx ] ;
}
}
// Loop back through scene names and remove non-ambiguous names
bool can_proceed = false ;
Set < int > : : Element * E = iset . front ( ) ;
while ( E ) {
String scene_name = r_filenames [ E - > get ( ) ] ;
bool duplicate_found = false ;
for ( Set < int > : : Element * F = iset . front ( ) ; F ; F = F - > next ( ) ) {
if ( E - > get ( ) = = F - > get ( ) ) {
continue ;
}
String other_scene_name = r_filenames [ F - > get ( ) ] ;
if ( other_scene_name = = scene_name ) {
duplicate_found = true ;
break ;
}
}
Set < int > : : Element * to_erase = duplicate_found ? nullptr : E ;
// We need to check that we could actually append anymore names
// if we wanted to for disambiguation. If we can't, then we have
// to abort even with ambiguous names. We clean the full path
// and the scene name first to remove extensions so that this
// comparison actually works.
String path = p_full_paths [ E - > get ( ) ] ;
if ( path . begins_with ( " res:// " ) ) {
path = path . substr ( 6 ) ;
}
if ( path . rfind ( " . " ) > = 0 ) {
path = path . substr ( 0 , path . rfind ( " . " ) ) ;
}
if ( scene_name . rfind ( " . " ) > = 0 ) {
scene_name = scene_name . substr ( 0 , scene_name . rfind ( " . " ) ) ;
}
// We can proceed iff the full path is longer than the scene name,
// meaning that there is at least one more parent folder we can
// tack onto the name.
can_proceed = can_proceed | | ( path . size ( ) - scene_name . size ( ) ) > = 1 ;
E = E - > next ( ) ;
if ( to_erase ) {
iset . erase ( to_erase ) ;
}
}
if ( ! can_proceed ) {
break ;
}
}
}
}
void EditorNode : : _update_scene_tabs ( ) {
bool show_rb = EditorSettings : : get_singleton ( ) - > get ( " interface/scene_tabs/show_script_button " ) ;
OS : : get_singleton ( ) - > global_menu_clear ( " _dock " ) ;
// Get all scene names, which may be ambiguous
Vector < String > disambiguated_scene_names ;
Vector < String > full_path_names ;
for ( int i = 0 ; i < editor_data . get_edited_scene_count ( ) ; i + + ) {
disambiguated_scene_names . push_back ( editor_data . get_scene_title ( i ) ) ;
full_path_names . push_back ( editor_data . get_scene_path ( i ) ) ;
}
disambiguate_filenames ( full_path_names , disambiguated_scene_names ) ;
scene_tabs - > clear_tabs ( ) ;
Ref < Texture > script_icon = gui_base - > get_icon ( " Script " , " EditorIcons " ) ;
for ( int i = 0 ; i < editor_data . get_edited_scene_count ( ) ; i + + ) {
@ -193,7 +308,7 @@ void EditorNode::_update_scene_tabs() {
int current = editor_data . get_edited_scene ( ) ;
bool unsaved = ( i = = current ) ? saved_version ! = editor_data . get_undo_redo ( ) . get_version ( ) : editor_data . get_scene_version ( i ) ! = 0 ;
scene_tabs - > add_tab ( editor_data. get_scene_title ( i ) + ( unsaved ? " (*) " : " " ) , icon ) ;
scene_tabs - > add_tab ( disambiguated_scene_names[ i ] + ( unsaved ? " (*) " : " " ) , icon ) ;
OS : : get_singleton ( ) - > global_menu_add_item ( " _dock " , editor_data . get_scene_title ( i ) + ( unsaved ? " (*) " : " " ) , GLOBAL_SCENE , i ) ;