2025-07-08 10:46:31 +00:00
using System.Collections.Generic ;
using UnityEngine ;
using ES3Internal ;
using UnityEngine.SceneManagement ;
#if UNITY_EDITOR
using UnityEditor ;
using UnityEditor.SceneManagement ;
using System ;
using System.Linq ;
#endif
#if UNITY_VISUAL_SCRIPTING
using Unity.VisualScripting ;
[IncludeInSettings(true)]
#endif
public class ES3ReferenceMgr : ES3ReferenceMgrBase
{
#if UNITY_EDITOR
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
public void RefreshDependencies ( bool isEnteringPlayMode = false )
{
// Empty the refId so it has to be refreshed.
refId = null ;
ES3ReferenceMgrBase . isEnteringPlayMode = isEnteringPlayMode ;
// This will get the dependencies for all GameObjects and Components from the active scene.
AddDependencies ( this . gameObject . scene . GetRootGameObjects ( ) ) ;
AddDependenciesFromFolders ( ) ;
AddPrefabsToManager ( ) ;
RemoveNullOrInvalidValues ( ) ;
ES3ReferenceMgrBase . isEnteringPlayMode = false ;
}
[MenuItem("Tools/Easy Save 3/Refresh References for All Scenes", false, 150)]
static void RefreshDependenciesInAllScenes ( )
{
if ( ! EditorUtility . DisplayDialog ( "Refresh references in all scenes" , "This will open each scene which is enabled in your Build Settings, refresh each reference manager, and save the scene.\n\nWe recommend making a backup of your project before doing this for the first time." , "Ok" , "Cancel" , DialogOptOutDecisionType . ForThisMachine , "ES3RefreshAllOptOut" ) )
return ;
// Get a list of loaded scenes so we know whether we need to close them after refreshing references or not.
var loadedScenePaths = new string [ SceneManager . sceneCount ] ;
for ( int i = 0 ; i < SceneManager . sceneCount ; i + + )
loadedScenePaths [ i ] = SceneManager . GetSceneAt ( i ) . path ;
var scenes = EditorBuildSettings . scenes ;
var sceneNameList = "" ; // We use this so we can display a list of scenes at the end.
for ( int i = 0 ; i < scenes . Length ; i + + )
{
var buildSettingsScene = scenes [ i ] ;
if ( ! buildSettingsScene . enabled )
continue ;
if ( EditorUtility . DisplayCancelableProgressBar ( "Refreshing references" , $"Refreshing references for scene {buildSettingsScene.path}." , i / scenes . Length ) )
return ;
var sceneWasOpen = loadedScenePaths . Contains ( buildSettingsScene . path ) ;
var scene = EditorSceneManager . OpenScene ( buildSettingsScene . path , OpenSceneMode . Additive ) ;
var mgr = ES3ReferenceMgr . GetManagerFromScene ( scene , false ) ;
if ( mgr ! = null )
{
try
{
( ( ES3ReferenceMgr ) mgr ) . RefreshDependencies ( ) ;
}
catch ( Exception e )
{
ES3Debug . LogError ( $"Couldn't update references for scene {scene.name} as the following exception occurred:\n\n" + e ) ;
}
}
sceneNameList + = $"{scene.name}\n" ;
// If the scene wasn't originally open, save it and close it.
if ( ! sceneWasOpen )
{
// Temporarily disable refreshing on save so that it doesn't refresh again.
var updateReferencesOnSave = ES3Settings . defaultSettingsScriptableObject . updateReferencesWhenSceneIsSaved ;
ES3Settings . defaultSettingsScriptableObject . updateReferencesWhenSceneIsSaved = false ;
EditorSceneManager . SaveScene ( scene ) ;
EditorSceneManager . CloseScene ( scene , true ) ;
ES3Settings . defaultSettingsScriptableObject . updateReferencesWhenSceneIsSaved = updateReferencesOnSave ;
}
}
EditorUtility . ClearProgressBar ( ) ;
EditorUtility . DisplayDialog ( "References refreshed" , $"Refrences updated for scenes:\n\n{sceneNameList}" , "Ok" , DialogOptOutDecisionType . ForThisMachine , "ES3RefreshAllCompleteOptOut" ) ;
}
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
public void Optimize ( )
{
var dependencies = EditorUtility . CollectDependencies ( this . gameObject . scene . GetRootGameObjects ( ) . Where ( go = > go ! = this . gameObject ) . ToArray ( ) ) ;
var notDependenciesOfScene = new HashSet < UnityEngine . Object > ( ) ;
foreach ( var kvp in idRef )
if ( ! dependencies . Contains ( kvp . Value ) )
notDependenciesOfScene . Add ( kvp . Value ) ;
foreach ( var obj in notDependenciesOfScene )
Remove ( obj ) ;
}
/* Adds all dependencies from this scene to the manager */
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
public void AddDependencies ( )
{
var rootGameObjects = gameObject . scene . GetRootGameObjects ( ) ;
for ( int j = 0 ; j < rootGameObjects . Length ; j + + )
{
var go = rootGameObjects [ j ] ;
if ( EditorUtility . DisplayCancelableProgressBar ( "Gathering references" , "Populating reference manager with your scene dependencies so they can be saved and loaded by reference." , j / rootGameObjects . Length ) )
return ;
AddDependencies ( go ) ;
}
EditorUtility . ClearProgressBar ( ) ;
}
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
public void AddDependencies ( UnityEngine . Object [ ] objs )
{
var timeStarted = EditorApplication . timeSinceStartup ;
var timeout = ES3Settings . defaultSettingsScriptableObject . collectDependenciesTimeout ;
foreach ( var obj in objs )
{
if ( obj = = null | | obj . name = = "Easy Save 3 Manager" )
continue ;
var excludeTextures = new List < Texture2D > ( ) ;
foreach ( var dependency in EditorUtility . CollectDependencies ( new UnityEngine . Object [ ] { obj } ) )
{
if ( EditorApplication . timeSinceStartup - timeStarted > timeout )
{
ES3Debug . LogWarning ( $"Easy Save cancelled gathering of references for object {obj.name} because it took longer than {timeout} seconds. You can increase the timeout length in Tools > Easy Save 3 > Settings > Reference Gathering Timeout, or adjust the settings so that fewer objects are referenced in your scene." ) ;
return ;
}
// Exclude all Texture2Ds which are packed into a SpriteAtlas from this manager.
/ * if ( dependency is SpriteAtlas )
foreach ( var atlasDependency in EditorUtility . CollectDependencies ( new UnityEngine . Object [ ] { dependency } ) )
if ( atlasDependency is Texture2D )
ExcludeObject ( atlasDependency ) ; * /
Add ( dependency ) ;
if ( obj is ES3Prefab prefab )
AddPrefabToManager ( prefab ) ;
}
}
}
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
public void AddDependenciesFromFolders ( )
{
var folders = ES3Settings . defaultSettingsScriptableObject . referenceFolders ;
// Remove null or empty values.
ArrayUtility . Remove ( ref folders , "" ) ;
ArrayUtility . Remove ( ref folders , null ) ;
if ( folders = = null | | folders . Length = = 0 )
return ;
var guids = AssetDatabase . FindAssets ( "t:Object" , folders ) ;
foreach ( var guid in guids )
{
var path = AssetDatabase . GUIDToAssetPath ( guid ) ;
var obj = AssetDatabase . LoadAssetAtPath < UnityEngine . Object > ( path ) ;
if ( obj ! = null )
AddDependencies ( obj ) ;
}
}
/ * [ System . ComponentModel . EditorBrowsable ( System . ComponentModel . EditorBrowsableState . Never ) ]
public void AddDependenciesLegacy ( UnityEngine . Object [ ] objs )
{
for ( int i = 0 ; i < objs . Length ; i + + )
{
var obj = objs [ i ] ;
if ( obj . name = = "Easy Save 3 Manager" )
continue ;
var dependencies = CollectDependenciesLegacy ( obj ) ;
foreach ( var dependency in dependencies )
{
if ( dependency ! = null )
{
Add ( dependency ) ;
// Add the prefab if it's referenced by this scene.
if ( dependency . GetType ( ) = = typeof ( ES3Prefab ) )
AddPrefabToManager ( ( ES3Prefab ) dependency ) ;
}
}
}
Undo . RecordObject ( this , "Update Easy Save 3 Reference List" ) ;
} * /
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
public void AddDependencies ( UnityEngine . Object obj )
{
AddDependencies ( new UnityEngine . Object [ ] { obj } ) ;
}
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
public void GeneratePrefabReferences ( )
{
AddPrefabsToManager ( ) ;
foreach ( var es3Prefab in prefabs )
es3Prefab . GeneratePrefabReferences ( ) ;
}
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
public void AddPrefabsToManager ( )
{
if ( ES3Settings . defaultSettingsScriptableObject . addAllPrefabsToManager )
{
// Clear any null values. This isn't necessary if we're not adding all prefabs to manager as the list is cleared each time.
if ( this . prefabs . RemoveAll ( item = > item = = null ) > 0 )
Undo . RecordObject ( this , "Update Easy Save 3 Reference List" ) ;
foreach ( var es3Prefab in Resources . FindObjectsOfTypeAll < ES3Prefab > ( ) )
AddPrefabToManager ( es3Prefab ) ;
}
}
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
private void AddPrefabToManager ( ES3Prefab es3Prefab )
{
try
{
if ( es3Prefab ! = null & & EditorUtility . IsPersistent ( es3Prefab ) )
if ( AddPrefab ( es3Prefab ) )
Undo . RecordObject ( this , "Update Easy Save 3 Reference List" ) ;
es3Prefab . GeneratePrefabReferences ( ) ;
}
catch { }
}
#endif
}