Swap UI with swapee name

main
Ali Sharoz 4 weeks ago
parent c1f157103e
commit 8056f00505

@ -0,0 +1,6 @@
{
"version": "1.0",
"components": [
"Microsoft.VisualStudio.Workload.ManagedGame"
]
}

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 27ff2c6a21a006c458bd022e98146d74
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: c1764d69117881843b761dc14ca276d4
folderAsset: yes
timeCreated: 1561225368
licenseType: Store
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 19f677a9eb83d3942af6d4c5fa8dbeee
folderAsset: yes
timeCreated: 1520032274
licenseType: Store
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

@ -0,0 +1,29 @@
{
"name": "AssetUsageDetector.Editor",
"rootNamespace": "",
"references": [
"Unity.Addressables"
],
"includePlatforms": [
"Editor"
],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [
{
"name": "com.unity.addressables",
"expression": "0.0.0",
"define": "ASSET_USAGE_ADDRESSABLES"
},
{
"name": "com.unity.visualeffectgraph",
"expression": "0.0.0",
"define": "ASSET_USAGE_VFX_GRAPH"
}
],
"noEngineReferences": false
}

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 8579ab42c9ab63d4bac5fb07bd390b46
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 2c0dea52dcdb16e4e9b13f8dacc1590f
timeCreated: 1520032279
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

@ -0,0 +1,207 @@
using System;
using System.Collections.Generic;
using System.IO;
using UnityEditor;
using UnityEngine;
using Object = UnityEngine.Object;
namespace AssetUsageDetectorNamespace
{
public partial class AssetUsageDetector
{
#region Helper Classes
private class CacheEntry
{
public enum Result { Unknown = 0, No = 1, Yes = 2 };
public string hash;
public string[] dependencies;
public long[] fileSizes;
public bool verified;
public Result searchResult;
public CacheEntry( string path )
{
Verify( path );
}
public CacheEntry( string hash, string[] dependencies, long[] fileSizes )
{
this.hash = hash;
this.dependencies = dependencies;
this.fileSizes = fileSizes;
}
public void Verify( string path )
{
string hash = AssetDatabase.GetAssetDependencyHash( path ).ToString();
if( this.hash != hash )
{
this.hash = hash;
Refresh( path );
}
verified = true;
}
public void Refresh( string path )
{
dependencies = AssetDatabase.GetDependencies( path, false );
if( fileSizes == null || fileSizes.Length != dependencies.Length )
fileSizes = new long[dependencies.Length];
int length = dependencies.Length;
for( int i = 0; i < length; i++ )
{
if( !string.IsNullOrEmpty( dependencies[i] ) )
{
FileInfo assetFile = new FileInfo( dependencies[i] );
fileSizes[i] = assetFile.Exists ? assetFile.Length : 0L;
}
else
{
// This dependency is empty which causes issues when passed to FileInfo constructor
// Find a non-empty dependency and move it to this index
for( int j = length - 1; j > i; j--, length-- )
{
if( !string.IsNullOrEmpty( dependencies[j] ) )
{
dependencies[i--] = dependencies[j];
break;
}
}
length--;
}
}
if( length != fileSizes.Length )
{
Array.Resize( ref dependencies, length );
Array.Resize( ref fileSizes, length );
}
}
}
#endregion
// An optimization to fetch the dependencies of an asset only once (key is the path of the asset)
private Dictionary<string, CacheEntry> assetDependencyCache;
private CacheEntry lastRefreshedCacheEntry;
private string CachePath { get { return Application.dataPath + "/../Library/AssetUsageDetector.cache"; } } // Path of the cache file
public void SaveCache()
{
if( assetDependencyCache == null )
return;
try
{
using( FileStream stream = new FileStream( CachePath, FileMode.Create ) )
using( BinaryWriter writer = new BinaryWriter( stream ) )
{
writer.Write( assetDependencyCache.Count );
foreach( var keyValuePair in assetDependencyCache )
{
CacheEntry cacheEntry = keyValuePair.Value;
string[] dependencies = cacheEntry.dependencies;
long[] fileSizes = cacheEntry.fileSizes;
writer.Write( keyValuePair.Key );
writer.Write( cacheEntry.hash );
writer.Write( dependencies.Length );
for( int i = 0; i < dependencies.Length; i++ )
{
writer.Write( dependencies[i] );
writer.Write( fileSizes[i] );
}
}
}
}
catch( Exception e )
{
Debug.LogException( e );
}
}
private void LoadCache()
{
if( File.Exists( CachePath ) )
{
using( FileStream stream = new FileStream( CachePath, FileMode.Open, FileAccess.Read ) )
using( BinaryReader reader = new BinaryReader( stream ) )
{
try
{
int cacheSize = reader.ReadInt32();
assetDependencyCache = new Dictionary<string, CacheEntry>( cacheSize );
for( int i = 0; i < cacheSize; i++ )
{
string assetPath = reader.ReadString();
string hash = reader.ReadString();
int dependenciesLength = reader.ReadInt32();
string[] dependencies = new string[dependenciesLength];
long[] fileSizes = new long[dependenciesLength];
for( int j = 0; j < dependenciesLength; j++ )
{
dependencies[j] = reader.ReadString();
fileSizes[j] = reader.ReadInt64();
}
assetDependencyCache[assetPath] = new CacheEntry( hash, dependencies, fileSizes );
}
}
catch( Exception e )
{
assetDependencyCache = null;
Debug.LogWarning( "Couldn't load cache (probably cache format has changed in an update), will regenerate cache.\n" + e.ToString() );
}
}
}
// Generate cache for all assets for the first time
if( assetDependencyCache == null )
{
assetDependencyCache = new Dictionary<string, CacheEntry>( 1024 * 8 );
string[] allAssets = AssetDatabase.GetAllAssetPaths();
if( allAssets.Length > 0 )
{
double startTime = EditorApplication.timeSinceStartup;
try
{
for( int i = 0; i < allAssets.Length; i++ )
{
if( i % 30 == 0 && EditorUtility.DisplayCancelableProgressBar( "Please wait...", "Generating cache for the first time (optional)", (float) i / allAssets.Length ) )
{
EditorUtility.ClearProgressBar();
Debug.LogWarning( "Initial cache generation cancelled, cache will be generated on the fly as more and more assets are searched." );
break;
}
assetDependencyCache[allAssets[i]] = new CacheEntry( allAssets[i] );
}
EditorUtility.ClearProgressBar();
Debug.Log( "Cache generated in " + ( EditorApplication.timeSinceStartup - startTime ).ToString( "F2" ) + " seconds" );
Debug.Log( "You can always reset the cache by deleting " + Path.GetFullPath( CachePath ) );
SaveCache();
}
catch( Exception e )
{
EditorUtility.ClearProgressBar();
Debug.LogException( e );
}
}
}
}
}
}

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 71ea9a3fd0b82594d8130d882dbfc844
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 93aaae685d4c3db44baeb91a0296855e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

@ -0,0 +1,298 @@
using UnityEditor;
using UnityEngine;
namespace AssetUsageDetectorNamespace
{
public static class AssetUsageDetectorSettings
{
private static readonly GUILayoutOption GL_WIDTH_60 = GUILayout.Width( 60f );
#region Colors
private static Color? m_settingsHeaderColor = null;
public static Color SettingsHeaderColor
{
get { if( m_settingsHeaderColor == null ) m_settingsHeaderColor = GetColor( "AUD_SettingsHeaderTint", Color.cyan ); return m_settingsHeaderColor.Value; }
set { if( m_settingsHeaderColor == value ) return; m_settingsHeaderColor = value; SetColor( "AUD_SettingsHeaderTint", value ); }
}
private static Color? m_searchResultGroupHeaderColor = null;
public static Color SearchResultGroupHeaderColor
{
get { if( m_searchResultGroupHeaderColor == null ) m_searchResultGroupHeaderColor = GetColor( "AUD_ResultGroupHeaderTint", Color.cyan ); return m_searchResultGroupHeaderColor.Value; }
set { if( m_searchResultGroupHeaderColor == value ) return; m_searchResultGroupHeaderColor = value; SetColor( "AUD_ResultGroupHeaderTint", value ); }
}
private static Color? m_rootRowsBackgroundColor = null;
public static Color RootRowsBackgroundColor
{
get { if( m_rootRowsBackgroundColor == null ) m_rootRowsBackgroundColor = GetColor( "AUD_RootRowsTint", EditorGUIUtility.isProSkin ? new Color( 0f, 1f, 1f, 0.15f ) : new Color( 0f, 1f, 1f, 0.25f ) ); return m_rootRowsBackgroundColor.Value; }
set { if( m_rootRowsBackgroundColor == value ) return; m_rootRowsBackgroundColor = value; SetColor( "AUD_RootRowsTint", value ); }
}
private static Color? m_rootRowsBorderColor = null;
public static Color RootRowsBorderColor
{
get { if( m_rootRowsBorderColor == null ) m_rootRowsBorderColor = GetColor( "AUD_RootRowsBorderColor", EditorGUIUtility.isProSkin ? new Color( 0.15f, 0.15f, 0.15f, 1f ) : new Color( 0.375f, 0.375f, 0.375f, 1f ) ); return m_rootRowsBorderColor.Value; }
set { if( m_rootRowsBorderColor == value ) return; m_rootRowsBorderColor = value; SetColor( "AUD_RootRowsBorderColor", value ); }
}
private static Color? m_mainReferencesBackgroundColor = null;
public static Color MainReferencesBackgroundColor
{
get { if( m_mainReferencesBackgroundColor == null ) m_mainReferencesBackgroundColor = GetColor( "AUD_MainRefRowsTint", EditorGUIUtility.isProSkin ? new Color( 0f, 0.35f, 0f, 1f ) : new Color( 0.25f, 0.75f, 0.25f, 1f ) ); return m_mainReferencesBackgroundColor.Value; }
set { if( m_mainReferencesBackgroundColor == value ) return; m_mainReferencesBackgroundColor = value; SetColor( "AUD_MainRefRowsTint", value ); }
}
private static Color? m_selectedRowsParentTint = null;
public static Color SelectedRowParentsTint
{
get { if( m_selectedRowsParentTint == null ) m_selectedRowsParentTint = GetColor( "AUD_SelectedRowParentsTint", EditorGUIUtility.isProSkin ? new Color( 0.36f, 0.36f, 0.18f, 1f ) : new Color( 0.825f, 0.825f, 0.55f, 1f ) ); return m_selectedRowsParentTint.Value; }
set { if( m_selectedRowsParentTint == value ) return; m_selectedRowsParentTint = value; SetColor( "AUD_SelectedRowParentsTint", value ); }
}
private static Color? m_selectedRowOccurrencesColor = null;
public static Color SelectedRowOccurrencesColor
{
get { if( m_selectedRowOccurrencesColor == null ) m_selectedRowOccurrencesColor = GetColor( "AUD_SelectedRowOccurrencesTint", EditorGUIUtility.isProSkin ? new Color( 0f, 0.3f, 0.75f, 1f ) : new Color( 0.25f, 0.75f, 1f, 1f ) ); return m_selectedRowOccurrencesColor.Value; }
set { if( m_selectedRowOccurrencesColor == value ) return; m_selectedRowOccurrencesColor = value; SetColor( "AUD_SelectedRowOccurrencesTint", value ); }
}
private static Color? m_treeLinesColor = null;
public static Color TreeLinesColor
{
get { if( m_treeLinesColor == null ) m_treeLinesColor = GetColor( "AUD_TreeLinesColor", EditorGUIUtility.isProSkin ? new Color( 0.65f, 0.65f, 0.65f, 1f ) : new Color( 0.375f, 0.375f, 0.375f, 1f ) ); return m_treeLinesColor.Value; }
set { if( m_treeLinesColor == value ) return; m_treeLinesColor = value; SetColor( "AUD_TreeLinesColor", value ); }
}
private static Color? m_highlightedTreeLinesColor = null;
public static Color HighlightedTreeLinesColor
{
get { if( m_highlightedTreeLinesColor == null ) m_highlightedTreeLinesColor = GetColor( "AUD_HighlightTreeLinesColor", Color.cyan ); return m_highlightedTreeLinesColor.Value; }
set { if( m_highlightedTreeLinesColor == value ) return; m_highlightedTreeLinesColor = value; SetColor( "AUD_HighlightTreeLinesColor", value ); }
}
private static Color? m_searchMatchingTextColor = null;
public static Color SearchMatchingTextColor
{
get { if( m_searchMatchingTextColor == null ) m_searchMatchingTextColor = GetColor( "AUD_SearchTextColor", Color.red ); return m_searchMatchingTextColor.Value; }
set { if( m_searchMatchingTextColor == value ) return; m_searchMatchingTextColor = value; SetColor( "AUD_SearchTextColor", value ); ForEachAssetUsageDetectorWindow( ( window ) => window.OnSettingsChanged( highlightedSearchTextColorChanged: true ) ); }
}
private static Color? m_tooltipDescriptionTextColor = null;
public static Color TooltipDescriptionTextColor
{
get { if( m_tooltipDescriptionTextColor == null ) m_tooltipDescriptionTextColor = GetColor( "AUD_TooltipUsageTextColor", EditorGUIUtility.isProSkin ? new Color( 0f, 0.9f, 0.9f, 1f ) : new Color( 0.9f, 0f, 0f, 1f ) ); return m_tooltipDescriptionTextColor.Value; }
set { if( m_tooltipDescriptionTextColor == value ) return; m_tooltipDescriptionTextColor = value; SetColor( "AUD_TooltipUsageTextColor", value ); ForEachAssetUsageDetectorWindow( ( window ) => window.OnSettingsChanged( tooltipDescriptionsColorChanged: true ) ); }
}
#endregion
#region Size Adjustments
private static float? m_extraRowHeight = null;
public static float ExtraRowHeight
{
get { if( m_extraRowHeight == null ) m_extraRowHeight = EditorPrefs.GetFloat( "AUD_ExtraRowHeight", 0f ); return m_extraRowHeight.Value; }
set { if( m_extraRowHeight == value ) return; m_extraRowHeight = value; EditorPrefs.SetFloat( "AUD_ExtraRowHeight", value ); ForEachAssetUsageDetectorWindow( ( window ) => window.OnSettingsChanged() ); }
}
#endregion
#region Other Settings
private static bool? m_showRootAssetName = null;
public static bool ShowRootAssetName
{
get { if( m_showRootAssetName == null ) m_showRootAssetName = EditorPrefs.GetBool( "AUD_ShowRootAssetName", true ); return m_showRootAssetName.Value; }
set { if( m_showRootAssetName == value ) return; m_showRootAssetName = value; EditorPrefs.SetBool( "AUD_ShowRootAssetName", value ); }
}
private static bool? m_pingClickedObjects = null;
public static bool PingClickedObjects
{
get { if( m_pingClickedObjects == null ) m_pingClickedObjects = EditorPrefs.GetBool( "AUD_PingClickedObj", true ); return m_pingClickedObjects.Value; }
set { if( m_pingClickedObjects == value ) return; m_pingClickedObjects = value; EditorPrefs.SetBool( "AUD_PingClickedObj", value ); }
}
private static bool? m_selectClickedObjects = null;
public static bool SelectClickedObjects
{
get { if( m_selectClickedObjects == null ) m_selectClickedObjects = EditorPrefs.GetBool( "AUD_SelectClickedObj", false ); return m_selectClickedObjects.Value; }
set { if( m_selectClickedObjects == value ) return; m_selectClickedObjects = value; EditorPrefs.SetBool( "AUD_SelectClickedObj", value ); }
}
private static bool? m_selectDoubleClickedObjects = null;
public static bool SelectDoubleClickedObjects
{
get { if( m_selectDoubleClickedObjects == null ) m_selectDoubleClickedObjects = EditorPrefs.GetBool( "AUD_SelectDoubleClickedObj", true ); return m_selectDoubleClickedObjects.Value; }
set { if( m_selectDoubleClickedObjects == value ) return; m_selectDoubleClickedObjects = value; EditorPrefs.SetBool( "AUD_SelectDoubleClickedObj", value ); }
}
private static bool? m_markUsedAssetsSubAssetsAsUsed = null;
public static bool MarkUsedAssetsSubAssetsAsUsed
{
get { if( m_markUsedAssetsSubAssetsAsUsed == null ) m_markUsedAssetsSubAssetsAsUsed = EditorPrefs.GetBool( "AUD_MarkUsedAssetsSubAssetsAsUsed", true ); return m_markUsedAssetsSubAssetsAsUsed.Value; }
set { if( m_markUsedAssetsSubAssetsAsUsed == value ) return; m_markUsedAssetsSubAssetsAsUsed = value; EditorPrefs.SetBool( "AUD_MarkUsedAssetsSubAssetsAsUsed", value ); }
}
private static bool? m_showUnityTooltip = null;
public static bool ShowUnityTooltip
{
get { if( m_showUnityTooltip == null ) m_showUnityTooltip = EditorPrefs.GetBool( "AUD_ShowUnityTooltip", false ); return m_showUnityTooltip.Value; }
set { if( m_showUnityTooltip == value ) return; m_showUnityTooltip = value; EditorPrefs.SetBool( "AUD_ShowUnityTooltip", value ); }
}
private static bool? m_showCustomTooltip = null;
public static bool ShowCustomTooltip
{
get { if( m_showCustomTooltip == null ) m_showCustomTooltip = EditorPrefs.GetBool( "AUD_ShowCustomTooltip", true ); return m_showCustomTooltip.Value; }
set { if( m_showCustomTooltip == value ) return; m_showCustomTooltip = value; EditorPrefs.SetBool( "AUD_ShowCustomTooltip", value ); ForEachAssetUsageDetectorWindow( ( window ) => window.OnSettingsChanged() ); }
}
private static float? m_customTooltipDelay = null;
public static float CustomTooltipDelay
{
get { if( m_customTooltipDelay == null ) m_customTooltipDelay = EditorPrefs.GetFloat( "AUD_CustomTooltipDelay", 0.7f ); return m_customTooltipDelay.Value; }
set { if( m_customTooltipDelay == value ) return; m_customTooltipDelay = value; EditorPrefs.SetFloat( "AUD_CustomTooltipDelay", value ); }
}
private static bool? m_showTreeLines = null;
public static bool ShowTreeLines
{
get { if( m_showTreeLines == null ) m_showTreeLines = EditorPrefs.GetBool( "AUD_ShowTreeLines", true ); return m_showTreeLines.Value; }
set { if( m_showTreeLines == value ) return; m_showTreeLines = value; EditorPrefs.SetBool( "AUD_ShowTreeLines", value ); }
}
private static bool? m_applySelectedRowParentsTintToRootRows = null;
public static bool ApplySelectedRowParentsTintToRootRows
{
get { if( m_applySelectedRowParentsTintToRootRows == null ) m_applySelectedRowParentsTintToRootRows = EditorPrefs.GetBool( "AUD_SelectedRowParentsTintAtRoot", true ); return m_applySelectedRowParentsTintToRootRows.Value; }
set { if( m_applySelectedRowParentsTintToRootRows == value ) return; m_applySelectedRowParentsTintToRootRows = value; EditorPrefs.SetBool( "AUD_SelectedRowParentsTintAtRoot", value ); }
}
#endregion
#if UNITY_2018_3_OR_NEWER
[SettingsProvider]
public static SettingsProvider CreatePreferencesGUI()
{
return new SettingsProvider( "Project/yasirkula/Asset Usage Detector", SettingsScope.Project )
{
guiHandler = ( searchContext ) => PreferencesGUI(),
keywords = new System.Collections.Generic.HashSet<string>() { "Asset", "Usage", "Detector" }
};
}
#endif
#if !UNITY_2018_3_OR_NEWER
[PreferenceItem( "Asset Usage Detector" )]
#endif
public static void PreferencesGUI()
{
float labelWidth = EditorGUIUtility.labelWidth;
#if UNITY_2018_3_OR_NEWER
EditorGUIUtility.labelWidth += 60f;
#else
EditorGUIUtility.labelWidth += 20f;
#endif
EditorGUI.BeginChangeCheck();
ShowRootAssetName = AssetUsageDetectorWindow.WordWrappingToggleLeft( "Show Root Asset's Name For Sub-Assets (Requires Refresh)", ShowRootAssetName );
EditorGUILayout.Space();
PingClickedObjects = AssetUsageDetectorWindow.WordWrappingToggleLeft( "Ping Clicked Objects", PingClickedObjects );
SelectClickedObjects = AssetUsageDetectorWindow.WordWrappingToggleLeft( "Select Clicked Objects", SelectClickedObjects );
SelectDoubleClickedObjects = AssetUsageDetectorWindow.WordWrappingToggleLeft( "Select Double Clicked Objects", SelectDoubleClickedObjects );
EditorGUILayout.Space();
MarkUsedAssetsSubAssetsAsUsed = AssetUsageDetectorWindow.WordWrappingToggleLeft( "Hide unused sub-assets in \"Unused Objects\" list if their parent assets are used (Requires Refresh)", MarkUsedAssetsSubAssetsAsUsed );
EditorGUILayout.Space();
ShowUnityTooltip = AssetUsageDetectorWindow.WordWrappingToggleLeft( "Show Unity Tooltip", ShowUnityTooltip );
ShowCustomTooltip = AssetUsageDetectorWindow.WordWrappingToggleLeft( "Show Custom Tooltip", ShowCustomTooltip );
EditorGUI.indentLevel++;
CustomTooltipDelay = FloatField( "Delay", CustomTooltipDelay, 0.7f );
EditorGUI.indentLevel--;
TooltipDescriptionTextColor = ColorField( "Tooltip Descriptions Text Color", TooltipDescriptionTextColor, EditorGUIUtility.isProSkin ? new Color( 0f, 0.9f, 0.9f, 1f ) : new Color( 0.9f, 0f, 0f, 1f ) );
EditorGUILayout.Space();
ExtraRowHeight = Mathf.Max( 0f, FloatField( "Extra Row Height", ExtraRowHeight, 0f ) );
EditorGUILayout.Space();
SettingsHeaderColor = ColorField( "Settings Header Color", SettingsHeaderColor, Color.cyan );
SearchResultGroupHeaderColor = ColorField( "Group Header Color", SearchResultGroupHeaderColor, Color.cyan );
RootRowsBackgroundColor = ColorField( "Root Rows Background Color", RootRowsBackgroundColor, EditorGUIUtility.isProSkin ? new Color( 0f, 1f, 1f, 0.15f ) : new Color( 0f, 1f, 1f, 0.25f ) );
RootRowsBorderColor = ColorField( "Root Rows Border Color", RootRowsBorderColor, EditorGUIUtility.isProSkin ? new Color( 0.15f, 0.15f, 0.15f, 1f ) : new Color( 0.375f, 0.375f, 0.375f, 1f ) );
MainReferencesBackgroundColor = ColorField( "Main References Background Color", MainReferencesBackgroundColor, EditorGUIUtility.isProSkin ? new Color( 0f, 0.35f, 0f, 1f ) : new Color( 0.25f, 0.75f, 0.25f, 1f ) );
SelectedRowParentsTint = ColorField( "Selected Row Parents Tint", SelectedRowParentsTint, EditorGUIUtility.isProSkin ? new Color( 0.36f, 0.36f, 0.18f, 1f ) : new Color( 0.825f, 0.825f, 0.55f, 1f ) );
EditorGUI.indentLevel++;
ApplySelectedRowParentsTintToRootRows = !EditorGUILayout.Toggle( "Ignore Root Rows", !ApplySelectedRowParentsTintToRootRows );
EditorGUI.indentLevel--;
SelectedRowOccurrencesColor = ColorField( "Selected Row All Occurrences Tint", SelectedRowOccurrencesColor, EditorGUIUtility.isProSkin ? new Color( 0f, 0.3f, 0.75f, 1f ) : new Color( 0.25f, 0.75f, 1f, 1f ) );
SearchMatchingTextColor = ColorField( "Matching Search Text Color", SearchMatchingTextColor, Color.red );
ShowTreeLines = AssetUsageDetectorWindow.WordWrappingToggleLeft( "Show Tree Lines", ShowTreeLines );
EditorGUI.indentLevel++;
TreeLinesColor = ColorField( "Normal Color", TreeLinesColor, EditorGUIUtility.isProSkin ? new Color( 0.65f, 0.65f, 0.65f, 1f ) : new Color( 0.375f, 0.375f, 0.375f, 1f ) );
HighlightedTreeLinesColor = ColorField( "Highlighted Color", HighlightedTreeLinesColor, Color.cyan );
EditorGUI.indentLevel--;
EditorGUIUtility.labelWidth = labelWidth;
if( EditorGUI.EndChangeCheck() )
ForEachAssetUsageDetectorWindow( ( window ) => window.Repaint() );
}
private static Color ColorField( string label, Color value, Color defaultValue )
{
GUILayout.BeginHorizontal();
Color result = EditorGUILayout.ColorField( label, value );
if( GUILayout.Button( "Reset", GL_WIDTH_60 ) )
result = defaultValue;
GUILayout.EndHorizontal();
return result;
}
private static float FloatField( string label, float value, float defaultValue )
{
GUILayout.BeginHorizontal();
float result = EditorGUILayout.FloatField( label, value );
if( GUILayout.Button( "Reset", GL_WIDTH_60 ) )
result = defaultValue;
GUILayout.EndHorizontal();
return result;
}
private static Color GetColor( string pref, Color defaultColor )
{
if( EditorGUIUtility.isProSkin )
pref += "_Pro";
if( !EditorPrefs.HasKey( pref ) )
return defaultColor;
string[] parts = EditorPrefs.GetString( pref ).Split( ';' );
return new Color32( byte.Parse( parts[0] ), byte.Parse( parts[1] ), byte.Parse( parts[2] ), byte.Parse( parts[3] ) );
}
private static void SetColor( string pref, Color32 value )
{
if( EditorGUIUtility.isProSkin )
pref += "_Pro";
EditorPrefs.SetString( pref, string.Concat( value.r.ToString(), ";", value.g.ToString(), ";", value.b.ToString(), ";", value.a.ToString() ) );
}
private static void ForEachAssetUsageDetectorWindow( System.Action<AssetUsageDetectorWindow> action )
{
foreach( AssetUsageDetectorWindow window in Resources.FindObjectsOfTypeAll<AssetUsageDetectorWindow>() )
{
if( window )
action( window );
}
}
}
}

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 13295073724765e45aa3b77486e515f4
timeCreated: 1639982865
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

@ -0,0 +1,812 @@
// Asset Usage Detector - by Suleyman Yasir KULA (yasirkula@gmail.com)
using UnityEngine;
using UnityEditor;
using System.Collections.Generic;
using System.Reflection;
using Object = UnityEngine.Object;
#if UNITY_2021_2_OR_NEWER
using PrefabStage = UnityEditor.SceneManagement.PrefabStage;
using PrefabStageUtility = UnityEditor.SceneManagement.PrefabStageUtility;
#elif UNITY_2018_3_OR_NEWER
using PrefabStage = UnityEditor.Experimental.SceneManagement.PrefabStage;
using PrefabStageUtility = UnityEditor.Experimental.SceneManagement.PrefabStageUtility;
#endif
namespace AssetUsageDetectorNamespace
{
public enum Phase { Setup, Processing, Complete };
public class AssetUsageDetectorWindow : EditorWindow, IHasCustomMenu
{
private enum WindowFilter { AlwaysReturnActive, ReturnActiveIfNotLocked, AlwaysReturnNew };
private const string PREFS_SEARCH_SCENES = "AUD_SceneSearch";
private const string PREFS_SEARCH_SCENE_LIGHTING_SETTINGS = "AUD_LightingSettingsSearch";
private const string PREFS_SEARCH_ASSETS = "AUD_AssetsSearch";
private const string PREFS_SEARCH_PROJECT_SETTINGS = "AUD_ProjectSettingsSearch";
private const string PREFS_DONT_SEARCH_SOURCE_ASSETS = "AUD_AssetsExcludeSrc";
private const string PREFS_SEARCH_DEPTH_LIMIT = "AUD_Depth";
private const string PREFS_SEARCH_FIELDS = "AUD_Fields";
private const string PREFS_SEARCH_PROPERTIES = "AUD_Properties";
private const string PREFS_SEARCH_NON_SERIALIZABLES = "AUD_NonSerializables";
private const string PREFS_SEARCH_UNUSED_MATERIAL_PROPERTIES = "AUD_SearchUnusedMaterialProps";
private const string PREFS_LAZY_SCENE_SEARCH = "AUD_LazySceneSearch";
private const string PREFS_ADDRESSABLES_SUPPORT = "AUD_AddressablesSupport";
private const string PREFS_CALCULATE_UNUSED_OBJECTS = "AUD_FindUnusedObjs";
private const string PREFS_HIDE_DUPLICATE_ROWS = "AUD_HideDuplicates";
private const string PREFS_HIDE_REDUNDANT_PREFAB_VARIANT_LINKS = "AUD_HideRedundantPVariantLinks";
private const string PREFS_SHOW_PROGRESS = "AUD_Progress";
private static readonly GUIContent windowTitle = new GUIContent( "Asset Usage Detector" );
private static readonly Vector2 windowMinSize = new Vector2( 325f, 220f );
private static readonly GUILayoutOption GL_WIDTH_12 = GUILayout.Width( 12f );
private GUIStyle lockButtonStyle;
private readonly AssetUsageDetector core = new AssetUsageDetector();
private SearchResult searchResult; // Overall search results
// This isn't readonly so that it can be serialized
private List<ObjectToSearch> objectsToSearch = new List<ObjectToSearch>() { new ObjectToSearch( null ) };
#pragma warning disable 0649
[SerializeField] // Since titleContent persists between Editor sessions, so should the IsLocked property because otherwise, "[L]" in title becomes confusing when the EditorWindow isn't actually locked
private bool m_isLocked;
private bool IsLocked
{
get { return m_isLocked; }
set
{
if( m_isLocked != value )
{
m_isLocked = value;
titleContent = value ? new GUIContent( "[L] " + windowTitle.text, EditorGUIUtility.IconContent( "InspectorLock" ).image ) : windowTitle;
}
}
}
#pragma warning restore 0649
private Phase currentPhase = Phase.Setup;
private bool searchInOpenScenes = true; // Scenes currently open in Hierarchy view
private bool searchInScenesInBuild = true; // Scenes in build
private bool searchInScenesInBuildTickedOnly = true; // Scenes in build (ticked only or not)
private bool searchInAllScenes = true; // All scenes (including scenes that are not in build)
private bool searchInSceneLightingSettings = true; // Window-Rendering-Lighting settings
private bool searchInAssetsFolder = true; // Assets in Project window
private bool dontSearchInSourceAssets = true; // objectsToSearch won't be searched for internal references
private bool searchInProjectSettings = true; // Player Settings, Graphics Settings etc.
private List<Object> searchInAssetsSubset = new List<Object>() { null }; // If not empty, only these assets are searched for references
private List<Object> excludedAssets = new List<Object>() { null }; // These assets won't be searched for references
private List<Object> excludedScenes = new List<Object>() { null }; // These scenes won't be searched for references
private int searchDepthLimit = 4; // Depth limit for recursively searching variables of objects
private bool lazySceneSearch = true;
#if ASSET_USAGE_ADDRESSABLES
private bool addressablesSupport = false;
#endif
private bool searchNonSerializableVariables = true;
private bool searchUnusedMaterialProperties = true;
private bool calculateUnusedObjects = false;
private bool hideDuplicateRows = true;
private bool hideReduntantPrefabVariantLinks = true;
private bool noAssetDatabaseChanges = false;
private bool showDetailedProgressBar = true;
private BindingFlags fieldModifiers, propertyModifiers;
private SearchRefactoring searchRefactoring = null; // Its value can be assigned via ShowAndSearch
private readonly ObjectToSearchListDrawer objectsToSearchDrawer = new ObjectToSearchListDrawer();
private readonly ObjectListDrawer searchInAssetsSubsetDrawer = new ObjectListDrawer( "Search following asset(s) only:", false );
private readonly ObjectListDrawer excludedAssetsDrawer = new ObjectListDrawer( "Don't search following asset(s):", false );
private readonly ObjectListDrawer excludedScenesDrawer = new ObjectListDrawer( "Don't search in following scene(s):", false );
private bool drawObjectsToSearchSection = true;
private Vector2 scrollPosition = Vector2.zero;
private bool shouldRepositionSelf;
private Rect windowTargetPosition;
void IHasCustomMenu.AddItemsToMenu( GenericMenu contextMenu )
{
contextMenu.AddItem( new GUIContent( "Lock" ), IsLocked, () => IsLocked = !IsLocked );
contextMenu.AddSeparator( "" );
#if UNITY_2018_3_OR_NEWER
contextMenu.AddItem( new GUIContent( "Settings" ), false, () => SettingsService.OpenProjectSettings( "Project/yasirkula/Asset Usage Detector" ) );
#else
contextMenu.AddItem( new GUIContent( "Settings" ), false, () =>
{
System.Type preferencesWindowType = typeof( EditorWindow ).Assembly.GetType( "UnityEditor.PreferencesWindow" );
preferencesWindowType.GetMethod( "ShowPreferencesWindow", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static ).Invoke( null, null );
EditorWindow preferencesWindow = GetWindow( preferencesWindowType );
if( (bool) preferencesWindowType.GetField( "m_RefreshCustomPreferences", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance ).GetValue( preferencesWindow ) )
{
preferencesWindowType.GetMethod( "AddCustomSections", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance ).Invoke( preferencesWindow, null );
preferencesWindowType.GetField( "m_RefreshCustomPreferences", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance ).SetValue( preferencesWindow, false );
}
int targetSectionIndex = -1;
System.Collections.IList sections = (System.Collections.IList) preferencesWindowType.GetField( "m_Sections", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance ).GetValue( preferencesWindow );
for( int i = 0; i < sections.Count; i++ )
{
if( ( (GUIContent) sections[i].GetType().GetField( "content", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance ).GetValue( sections[i] ) ).text == "Asset Usage Detector" )
{
targetSectionIndex = i;
break;
}
}
if( targetSectionIndex >= 0 )
preferencesWindowType.GetProperty( "selectedSectionIndex", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance ).SetValue( preferencesWindow, targetSectionIndex, null );
} );
#endif
if( currentPhase == Phase.Setup )
{
contextMenu.AddSeparator( "" );
contextMenu.AddItem( new GUIContent( "Refresh Sub-Assets of Searched Objects" ), false, () =>
{
for( int i = objectsToSearch.Count - 1; i >= 0; i-- )
objectsToSearch[i].RefreshSubAssets();
} );
}
else if( currentPhase == Phase.Complete )
{
if( searchResult != null && searchResult.NumberOfGroups > 0 )
{
contextMenu.AddSeparator( "" );
contextMenu.AddItem( new GUIContent( "Collapse All" ), false, searchResult.CollapseAllSearchResultGroups );
}
}
}
// Shows lock button at the top-right corner
// Credit: http://leahayes.co.uk/2013/04/30/adding-the-little-padlock-button-to-your-editorwindow.html
private void ShowButton( Rect position )
{
if( lockButtonStyle == null )
lockButtonStyle = "IN LockButton";
IsLocked = GUI.Toggle( position, IsLocked, GUIContent.none, lockButtonStyle );
}
private static AssetUsageDetectorWindow GetWindow( WindowFilter filter )
{
AssetUsageDetectorWindow[] windows = Resources.FindObjectsOfTypeAll<AssetUsageDetectorWindow>();
AssetUsageDetectorWindow window = System.Array.Find( windows, ( w ) => w && !w.IsLocked );
if( !window )
window = System.Array.Find( windows, ( w ) => w );
if( window && ( filter == WindowFilter.AlwaysReturnActive || ( !window.IsLocked && filter == WindowFilter.ReturnActiveIfNotLocked ) ) )
{
window.Show();
window.Focus();
return window;
}
Rect? windowTargetPosition = null;
if( window )
{
Rect position = window.position;
position.position += new Vector2( 50f, 50f );
windowTargetPosition = position;
}
window = CreateInstance<AssetUsageDetectorWindow>();
window.titleContent = windowTitle;
window.minSize = windowMinSize;
if( windowTargetPosition.HasValue )
{
window.shouldRepositionSelf = true;
window.windowTargetPosition = windowTargetPosition.Value;
}
window.Show( true );
window.Focus();
return window;
}
[MenuItem( "Window/Asset Usage Detector/Active Window" )]
private static void OpenActiveWindow()
{
GetWindow( WindowFilter.AlwaysReturnActive );
}
[MenuItem( "Window/Asset Usage Detector/New Window" )]
private static void OpenNewWindow()
{
GetWindow( WindowFilter.AlwaysReturnNew );
}
// Quickly initiate search for the selected assets
[MenuItem( "GameObject/Search for References/This Object Only", priority = 49 )]
[MenuItem( "Assets/Search for References", priority = 1000 )]
private static void SearchSelectedAssetReferences( MenuCommand command )
{
// This happens when this button is clicked via hierarchy's right click context menu
// and is called once for each object in the selection. We don't want that, we want
// the function to be called only once
if( command.context )
{
EditorApplication.update -= CallSearchSelectedAssetReferencesOnce;
EditorApplication.update += CallSearchSelectedAssetReferencesOnce;
}
else
ShowAndSearch( Selection.objects );
}
[MenuItem( "GameObject/Search for References/Include Children", priority = 49 )]
private static void SearchSelectedAssetReferencesWithChildren( MenuCommand command )
{
if( command.context )
{
EditorApplication.update -= CallSearchSelectedAssetReferencesWithChildrenOnce;
EditorApplication.update += CallSearchSelectedAssetReferencesWithChildrenOnce;
}
else
ShowAndSearch( Selection.objects, true );
}
// Show the menu item only if there is a selection in the Editor
[MenuItem( "GameObject/Search for References/This Object Only", validate = true )]
[MenuItem( "GameObject/Search for References/Include Children", validate = true )]
[MenuItem( "Assets/Search for References", validate = true )]
private static bool SearchSelectedAssetReferencesValidate( MenuCommand command )
{
return Selection.objects.Length > 0;
}
// Quickly show the AssetUsageDetector window and initiate a search
public static void ShowAndSearch( IEnumerable<Object> searchObjects, bool? shouldSearchChildren = null )
{
GetWindow( WindowFilter.ReturnActiveIfNotLocked ).ShowAndSearchInternal( searchObjects, null, shouldSearchChildren );
}
// Quickly show the AssetUsageDetector window and initiate a search
public static void ShowAndSearch( AssetUsageDetector.Parameters searchParameters, bool? shouldSearchChildren = null )
{
if( searchParameters == null )
{
Debug.LogError( "searchParameters can't be null!" );
return;
}
GetWindow( WindowFilter.ReturnActiveIfNotLocked ).ShowAndSearchInternal( searchParameters.objectsToSearch, searchParameters, shouldSearchChildren );
}
private static void CallSearchSelectedAssetReferencesOnce()
{
EditorApplication.update -= CallSearchSelectedAssetReferencesOnce;
SearchSelectedAssetReferences( new MenuCommand( null ) );
}
private static void CallSearchSelectedAssetReferencesWithChildrenOnce()
{
EditorApplication.update -= CallSearchSelectedAssetReferencesWithChildrenOnce;
SearchSelectedAssetReferencesWithChildren( new MenuCommand( null ) );
}
private void ShowAndSearchInternal( IEnumerable<Object> searchObjects, AssetUsageDetector.Parameters searchParameters, bool? shouldSearchChildren )
{
if( !ReturnToSetupPhase() )
{
Debug.LogError( "Need to reset the previous search first!" );
return;
}
objectsToSearch.Clear();
if( searchObjects != null )
{
foreach( Object obj in searchObjects )
objectsToSearch.Add( new ObjectToSearch( obj, shouldSearchChildren ) );
}
if( searchParameters != null )
{
ParseSceneSearchMode( searchParameters.searchInScenes );
searchInSceneLightingSettings = searchParameters.searchInSceneLightingSettings;
searchInAssetsFolder = searchParameters.searchInAssetsFolder;
dontSearchInSourceAssets = searchParameters.dontSearchInSourceAssets;
searchInProjectSettings = searchParameters.searchInProjectSettings;
searchDepthLimit = searchParameters.searchDepthLimit;
fieldModifiers = searchParameters.fieldModifiers;
propertyModifiers = searchParameters.propertyModifiers;
searchNonSerializableVariables = searchParameters.searchNonSerializableVariables;
searchUnusedMaterialProperties = searchParameters.searchUnusedMaterialProperties;
searchRefactoring = searchParameters.searchRefactoring;
lazySceneSearch = searchParameters.lazySceneSearch;
#if ASSET_USAGE_ADDRESSABLES
addressablesSupport = searchParameters.addressablesSupport;
#endif
calculateUnusedObjects = searchParameters.calculateUnusedObjects;
hideDuplicateRows = searchParameters.hideDuplicateRows;
hideReduntantPrefabVariantLinks = searchParameters.hideReduntantPrefabVariantLinks;
noAssetDatabaseChanges = searchParameters.noAssetDatabaseChanges;
showDetailedProgressBar = searchParameters.showDetailedProgressBar;
searchInAssetsSubset.Clear();
if( searchParameters.searchInAssetsSubset != null )
{
foreach( Object obj in searchParameters.searchInAssetsSubset )
searchInAssetsSubset.Add( obj );
}
excludedAssets.Clear();
if( searchParameters.excludedAssetsFromSearch != null )
{
foreach( Object obj in searchParameters.excludedAssetsFromSearch )
excludedAssets.Add( obj );
}
excludedScenes.Clear();
if( searchParameters.excludedScenesFromSearch != null )
{
foreach( Object obj in searchParameters.excludedScenesFromSearch )
excludedScenes.Add( obj );
}
}
InitiateSearch();
Repaint();
}
private void Awake()
{
LoadPrefs();
}
private void OnEnable()
{
if( currentPhase == Phase.Complete && AssetUsageDetectorSettings.ShowCustomTooltip )
wantsMouseMove = wantsMouseEnterLeaveWindow = true; // These values aren't preserved during domain reload on Unity 2020.3.0f1
#if UNITY_2018_3_OR_NEWER
PrefabStage.prefabStageClosing -= ReplacePrefabStageObjectsWithAssets;
PrefabStage.prefabStageClosing += ReplacePrefabStageObjectsWithAssets;
#endif
}
private void OnDisable()
{
#if UNITY_2018_3_OR_NEWER
PrefabStage.prefabStageClosing -= ReplacePrefabStageObjectsWithAssets;
#endif
SearchResultTooltip.Hide();
}
private void OnDestroy()
{
if( core != null )
core.SaveCache();
SavePrefs();
if( searchResult != null && currentPhase == Phase.Complete )
searchResult.RestoreInitialSceneSetup();
}
private void SavePrefs()
{
EditorPrefs.SetInt( PREFS_SEARCH_SCENES, (int) GetSceneSearchMode( false ) );
EditorPrefs.SetBool( PREFS_SEARCH_SCENE_LIGHTING_SETTINGS, searchInSceneLightingSettings );
EditorPrefs.SetBool( PREFS_SEARCH_ASSETS, searchInAssetsFolder );
EditorPrefs.SetBool( PREFS_DONT_SEARCH_SOURCE_ASSETS, dontSearchInSourceAssets );
EditorPrefs.SetBool( PREFS_SEARCH_PROJECT_SETTINGS, searchInProjectSettings );
EditorPrefs.SetInt( PREFS_SEARCH_DEPTH_LIMIT, searchDepthLimit );
EditorPrefs.SetInt( PREFS_SEARCH_FIELDS, (int) fieldModifiers );
EditorPrefs.SetInt( PREFS_SEARCH_PROPERTIES, (int) propertyModifiers );
EditorPrefs.SetBool( PREFS_SEARCH_NON_SERIALIZABLES, searchNonSerializableVariables );
EditorPrefs.SetBool( PREFS_SEARCH_UNUSED_MATERIAL_PROPERTIES, searchUnusedMaterialProperties );
EditorPrefs.SetBool( PREFS_LAZY_SCENE_SEARCH, lazySceneSearch );
#if ASSET_USAGE_ADDRESSABLES
EditorPrefs.SetBool( PREFS_ADDRESSABLES_SUPPORT, addressablesSupport );
#endif
EditorPrefs.SetBool( PREFS_CALCULATE_UNUSED_OBJECTS, calculateUnusedObjects );
EditorPrefs.SetBool( PREFS_HIDE_DUPLICATE_ROWS, hideDuplicateRows );
EditorPrefs.SetBool( PREFS_HIDE_REDUNDANT_PREFAB_VARIANT_LINKS, hideReduntantPrefabVariantLinks );
EditorPrefs.SetBool( PREFS_SHOW_PROGRESS, showDetailedProgressBar );
}
private void LoadPrefs()
{
ParseSceneSearchMode( (SceneSearchMode) EditorPrefs.GetInt( PREFS_SEARCH_SCENES, (int) ( SceneSearchMode.OpenScenes | SceneSearchMode.ScenesInBuildSettingsTickedOnly | SceneSearchMode.AllScenes ) ) );
searchInSceneLightingSettings = EditorPrefs.GetBool( PREFS_SEARCH_SCENE_LIGHTING_SETTINGS, true );
searchInAssetsFolder = EditorPrefs.GetBool( PREFS_SEARCH_ASSETS, true );
dontSearchInSourceAssets = EditorPrefs.GetBool( PREFS_DONT_SEARCH_SOURCE_ASSETS, true );
searchInProjectSettings = EditorPrefs.GetBool( PREFS_SEARCH_PROJECT_SETTINGS, true );
searchDepthLimit = EditorPrefs.GetInt( PREFS_SEARCH_DEPTH_LIMIT, 4 );
fieldModifiers = (BindingFlags) EditorPrefs.GetInt( PREFS_SEARCH_FIELDS, (int) ( BindingFlags.Public | BindingFlags.NonPublic ) );
propertyModifiers = (BindingFlags) EditorPrefs.GetInt( PREFS_SEARCH_PROPERTIES, (int) ( BindingFlags.Public | BindingFlags.NonPublic ) );
searchNonSerializableVariables = EditorPrefs.GetBool( PREFS_SEARCH_NON_SERIALIZABLES, true );
searchUnusedMaterialProperties = EditorPrefs.GetBool( PREFS_SEARCH_UNUSED_MATERIAL_PROPERTIES, true );
lazySceneSearch = EditorPrefs.GetBool( PREFS_LAZY_SCENE_SEARCH, true );
#if ASSET_USAGE_ADDRESSABLES
addressablesSupport = EditorPrefs.GetBool( PREFS_ADDRESSABLES_SUPPORT, false );
#endif
calculateUnusedObjects = EditorPrefs.GetBool( PREFS_CALCULATE_UNUSED_OBJECTS, false );
hideDuplicateRows = EditorPrefs.GetBool( PREFS_HIDE_DUPLICATE_ROWS, true );
hideReduntantPrefabVariantLinks = EditorPrefs.GetBool( PREFS_HIDE_REDUNDANT_PREFAB_VARIANT_LINKS, true );
showDetailedProgressBar = EditorPrefs.GetBool( PREFS_SHOW_PROGRESS, true );
}
private SceneSearchMode GetSceneSearchMode( bool hideOptionsInPlayMode )
{
SceneSearchMode sceneSearchMode = SceneSearchMode.None;
if( searchInOpenScenes )
sceneSearchMode |= SceneSearchMode.OpenScenes;
if( !hideOptionsInPlayMode || !EditorApplication.isPlaying )
{
if( searchInScenesInBuild )
sceneSearchMode |= searchInScenesInBuildTickedOnly ? SceneSearchMode.ScenesInBuildSettingsTickedOnly : SceneSearchMode.ScenesInBuildSettingsAll;
if( searchInAllScenes )
sceneSearchMode |= SceneSearchMode.AllScenes;
}
return sceneSearchMode;
}
private void ParseSceneSearchMode( SceneSearchMode sceneSearchMode )
{
searchInOpenScenes = ( sceneSearchMode & SceneSearchMode.OpenScenes ) == SceneSearchMode.OpenScenes;
searchInScenesInBuild = ( sceneSearchMode & SceneSearchMode.ScenesInBuildSettingsAll ) == SceneSearchMode.ScenesInBuildSettingsAll || ( sceneSearchMode & SceneSearchMode.ScenesInBuildSettingsTickedOnly ) == SceneSearchMode.ScenesInBuildSettingsTickedOnly;
searchInScenesInBuildTickedOnly = ( sceneSearchMode & SceneSearchMode.ScenesInBuildSettingsAll ) != SceneSearchMode.ScenesInBuildSettingsAll;
searchInAllScenes = ( sceneSearchMode & SceneSearchMode.AllScenes ) == SceneSearchMode.AllScenes;
}
private void Update()
{
if( shouldRepositionSelf )
{
shouldRepositionSelf = false;
position = windowTargetPosition;
}
}
private void OnGUI()
{
// Make the window scrollable
scrollPosition = EditorGUILayout.BeginScrollView( scrollPosition, Utilities.GL_EXPAND_WIDTH, Utilities.GL_EXPAND_HEIGHT );
GUILayout.BeginVertical();
if( currentPhase == Phase.Processing )
{
// If we are stuck at this phase, then we have encountered an exception
GUILayout.Label( ". . . Search in progress or something went wrong (check console) . . ." );
if( GUILayout.Button( "RETURN", Utilities.GL_HEIGHT_30 ) )
{
ReturnToSetupPhase();
GUIUtility.ExitGUI();
}
}
else if( currentPhase == Phase.Setup )
{
DrawObjectsToSearchSection();
GUILayout.Space( 10f );
Color c = GUI.backgroundColor;
GUI.backgroundColor = AssetUsageDetectorSettings.SettingsHeaderColor;
GUILayout.Box( "<b>SEARCH IN</b>", Utilities.BoxGUIStyle, Utilities.GL_EXPAND_WIDTH );
GUI.backgroundColor = c;
searchInAssetsFolder = WordWrappingToggleLeft( "Project window (Assets folder)", searchInAssetsFolder );
if( searchInAssetsFolder )
{
GUILayout.BeginHorizontal();
GUILayout.Space( 35f );
GUILayout.BeginVertical();
searchInAssetsSubsetDrawer.Draw( searchInAssetsSubset );
excludedAssetsDrawer.Draw( excludedAssets );
GUILayout.EndVertical();
GUILayout.EndHorizontal();
}
GUILayout.Space( 5f );
dontSearchInSourceAssets = WordWrappingToggleLeft( "Don't search \"SEARCHED OBJECTS\" themselves for references", dontSearchInSourceAssets );
searchUnusedMaterialProperties = WordWrappingToggleLeft( "Search unused material properties (e.g. normal map of a material that no longer uses normal mapping)", searchUnusedMaterialProperties );
Utilities.DrawSeparatorLine();
if( searchInAllScenes && !EditorApplication.isPlaying )
GUI.enabled = false;
searchInOpenScenes = WordWrappingToggleLeft( "Currently open (loaded) scene(s)", searchInOpenScenes );
if( !EditorApplication.isPlaying )
{
searchInScenesInBuild = WordWrappingToggleLeft( "Scenes in Build Settings", searchInScenesInBuild );
if( searchInScenesInBuild )
{
GUILayout.BeginHorizontal();
GUILayout.Space( 35f );
searchInScenesInBuildTickedOnly = EditorGUILayout.ToggleLeft( "Ticked only", searchInScenesInBuildTickedOnly, Utilities.GL_WIDTH_100 );
searchInScenesInBuildTickedOnly = !EditorGUILayout.ToggleLeft( "All", !searchInScenesInBuildTickedOnly, Utilities.GL_WIDTH_100 );
GUILayout.EndHorizontal();
}
GUI.enabled = true;
searchInAllScenes = WordWrappingToggleLeft( "All scenes in the project", searchInAllScenes );
}
GUILayout.BeginHorizontal();
GUILayout.Space( 35f );
GUILayout.BeginVertical();
excludedScenesDrawer.Draw( excludedScenes );
GUILayout.EndVertical();
GUILayout.EndHorizontal();
EditorGUI.BeginDisabledGroup( !searchInOpenScenes && !searchInScenesInBuild && !searchInAllScenes );
searchInSceneLightingSettings = WordWrappingToggleLeft( "Scene Lighting Settings (WARNING: This may change the active scene during search)", searchInSceneLightingSettings );
EditorGUI.EndDisabledGroup();
Utilities.DrawSeparatorLine();
searchInProjectSettings = WordWrappingToggleLeft( "Project Settings (Player Settings, Graphics Settings etc.)", searchInProjectSettings );
GUILayout.Space( 10f );
GUI.backgroundColor = AssetUsageDetectorSettings.SettingsHeaderColor;
GUILayout.Box( "<b>SETTINGS</b>", Utilities.BoxGUIStyle, Utilities.GL_EXPAND_WIDTH );
GUI.backgroundColor = c;
#if ASSET_USAGE_ADDRESSABLES
EditorGUI.BeginDisabledGroup( addressablesSupport );
#endif
lazySceneSearch = WordWrappingToggleLeft( "Lazy scene search: scenes are searched in detail only when they are manually refreshed (faster search)", lazySceneSearch );
#if ASSET_USAGE_ADDRESSABLES
EditorGUI.EndDisabledGroup();
addressablesSupport = WordWrappingToggleLeft( "Addressables support (Experimental) (WARNING: 'Lazy scene search' will be disabled) (slower search)", addressablesSupport );
#endif
calculateUnusedObjects = WordWrappingToggleLeft( "Calculate unused objects", calculateUnusedObjects );
hideDuplicateRows = WordWrappingToggleLeft( "Hide duplicate rows in search results", hideDuplicateRows );
#if UNITY_2018_3_OR_NEWER
hideReduntantPrefabVariantLinks = WordWrappingToggleLeft( "Hide redundant prefab variant links (when the same value is assigned to the same Component of a prefab and its variant(s))", hideReduntantPrefabVariantLinks );
#endif
noAssetDatabaseChanges = WordWrappingToggleLeft( "I haven't modified any assets/scenes since the last search (faster search)", noAssetDatabaseChanges );
showDetailedProgressBar = WordWrappingToggleLeft( "Update search progress bar more often (cancelable search) (slower search)", showDetailedProgressBar );
GUILayout.Space( 10f );
// Don't let the user press the GO button without any valid search location
if( !searchInAllScenes && !searchInOpenScenes && !searchInScenesInBuild && !searchInAssetsFolder && !searchInProjectSettings )
GUI.enabled = false;
if( GUILayout.Button( "GO!", Utilities.GL_HEIGHT_30 ) )
{
InitiateSearch();
GUIUtility.ExitGUI();
}
GUILayout.Space( 5f );
}
else if( currentPhase == Phase.Complete )
{
// Draw the results of the search
GUI.enabled = false;
DrawObjectsToSearchSection();
if( drawObjectsToSearchSection )
GUILayout.Space( 10f );
GUI.enabled = true;
if( GUILayout.Button( "Reset Search", Utilities.GL_HEIGHT_30 ) )
{
ReturnToSetupPhase();
GUIUtility.ExitGUI();
}
if( searchResult == null )
{
EditorGUILayout.HelpBox( "ERROR: searchResult is null", MessageType.Error );
return;
}
else if( !searchResult.SearchCompletedSuccessfully )
EditorGUILayout.HelpBox( "ERROR: search was interrupted, check the logs for more info", MessageType.Error );
if( searchResult.NumberOfGroups == 0 )
{
GUILayout.Space( 10f );
GUILayout.Box( "No references found...", Utilities.BoxGUIStyle, Utilities.GL_EXPAND_WIDTH );
}
else
{
noAssetDatabaseChanges = WordWrappingToggleLeft( "I haven't modified any assets/scenes since the last search (faster Refresh)", noAssetDatabaseChanges );
EditorGUILayout.Space();
scrollPosition.y = searchResult.DrawOnGUI( this, scrollPosition.y, noAssetDatabaseChanges );
}
}
if( Event.current.type == EventType.MouseLeaveWindow )
{
SearchResultTooltip.Hide();
if( searchResult != null )
searchResult.CancelDelayedTreeViewTooltip();
}
GUILayout.EndVertical();
EditorGUILayout.EndScrollView();
}
private void DrawObjectsToSearchSection()
{
Color c = GUI.backgroundColor;
GUI.backgroundColor = AssetUsageDetectorSettings.SettingsHeaderColor;
GUILayout.Box( "<b>SEARCHED OBJECTS</b>", Utilities.BoxGUIStyle, Utilities.GL_EXPAND_WIDTH );
GUI.backgroundColor = c;
Rect searchedObjectsHeaderRect = GUILayoutUtility.GetLastRect();
searchedObjectsHeaderRect.x += 5f;
searchedObjectsHeaderRect.yMin += ( searchedObjectsHeaderRect.height - EditorGUIUtility.singleLineHeight ) * 0.5f;
searchedObjectsHeaderRect.height = EditorGUIUtility.singleLineHeight;
drawObjectsToSearchSection = EditorGUI.Foldout( searchedObjectsHeaderRect, drawObjectsToSearchSection, GUIContent.none, true );
if( drawObjectsToSearchSection )
objectsToSearchDrawer.Draw( objectsToSearch );
}
public static bool WordWrappingToggleLeft( string label, bool value )
{
GUILayout.BeginHorizontal();
bool result = EditorGUILayout.ToggleLeft( GUIContent.none, value, GL_WIDTH_12 );
if( GUILayout.Button( label, EditorStyles.wordWrappedLabel ) )
{
GUI.FocusControl( null );
result = !value;
}
GUILayout.EndHorizontal();
return result;
}
private void InitiateSearch()
{
currentPhase = Phase.Processing;
SavePrefs();
#if UNITY_2018_3_OR_NEWER
ReplacePrefabStageObjectsWithAssets( PrefabStageUtility.GetCurrentPrefabStage() );
#endif
// Start searching
searchResult = core.Run( new AssetUsageDetector.Parameters()
{
objectsToSearch = !objectsToSearch.IsEmpty() ? new ObjectToSearchEnumerator( objectsToSearch ).ToArray() : null,
searchInScenes = GetSceneSearchMode( true ),
searchInSceneLightingSettings = searchInSceneLightingSettings,
searchInAssetsFolder = searchInAssetsFolder,
searchInAssetsSubset = !searchInAssetsSubset.IsEmpty() ? searchInAssetsSubset.ToArray() : null,
excludedAssetsFromSearch = !excludedAssets.IsEmpty() ? excludedAssets.ToArray() : null,
dontSearchInSourceAssets = dontSearchInSourceAssets,
excludedScenesFromSearch = !excludedScenes.IsEmpty() ? excludedScenes.ToArray() : null,
searchInProjectSettings = searchInProjectSettings,
//fieldModifiers = fieldModifiers,
//propertyModifiers = propertyModifiers,
//searchDepthLimit = searchDepthLimit,
//searchNonSerializableVariables = searchNonSerializableVariables,
searchUnusedMaterialProperties = searchUnusedMaterialProperties,
searchRefactoring = searchRefactoring,
#if ASSET_USAGE_ADDRESSABLES
lazySceneSearch = lazySceneSearch && !addressablesSupport,
addressablesSupport = addressablesSupport,
#else
lazySceneSearch = lazySceneSearch,
#endif
calculateUnusedObjects = calculateUnusedObjects,
hideDuplicateRows = hideDuplicateRows,
hideReduntantPrefabVariantLinks = hideReduntantPrefabVariantLinks,
noAssetDatabaseChanges = noAssetDatabaseChanges,
showDetailedProgressBar = showDetailedProgressBar
} );
currentPhase = Phase.Complete;
// We really don't want SearchRefactoring to affect next searches unless the search is initiated via ShowAndSearch again
searchRefactoring = null;
if( AssetUsageDetectorSettings.ShowCustomTooltip )
wantsMouseMove = wantsMouseEnterLeaveWindow = true;
}
#if UNITY_2018_3_OR_NEWER
// Try replacing searched objects who are part of currently open prefab stage with their corresponding prefab assets
public void ReplacePrefabStageObjectsWithAssets( PrefabStage prefabStage )
{
if( prefabStage == null || !prefabStage.stageHandle.IsValid() )
return;
#if UNITY_2020_1_OR_NEWER
GameObject prefabAsset = AssetDatabase.LoadAssetAtPath<GameObject>( prefabStage.assetPath );
#else
GameObject prefabAsset = AssetDatabase.LoadAssetAtPath<GameObject>( prefabStage.prefabAssetPath );
#endif
if( prefabAsset == null || prefabAsset.Equals( null ) )
return;
for( int i = 0; i < objectsToSearch.Count; i++ )
{
Object obj = objectsToSearch[i].obj;
if( obj != null && !obj.Equals( null ) && obj is GameObject && prefabStage.IsPartOfPrefabContents( (GameObject) obj ) )
{
GameObject prefabStageObjectSource = ( (GameObject) obj ).FollowSymmetricHierarchy( prefabStage.prefabContentsRoot, prefabAsset );
if( prefabStageObjectSource != null )
objectsToSearch[i].obj = prefabStageObjectSource;
List<ObjectToSearch.SubAsset> subAssets = objectsToSearch[i].subAssets;
for( int j = 0; j < subAssets.Count; j++ )
{
obj = subAssets[j].subAsset;
if( obj != null && !obj.Equals( null ) && obj is GameObject && prefabStage.IsPartOfPrefabContents( (GameObject) obj ) )
{
prefabStageObjectSource = ( (GameObject) obj ).FollowSymmetricHierarchy( prefabStage.prefabContentsRoot, prefabAsset );
if( prefabStageObjectSource != null )
subAssets[j].subAsset = prefabStageObjectSource;
}
}
}
}
}
#endif
private bool ReturnToSetupPhase()
{
if( searchResult != null && !EditorApplication.isPlaying && !searchResult.RestoreInitialSceneSetup() )
return false;
searchResult = null;
currentPhase = Phase.Setup;
wantsMouseMove = wantsMouseEnterLeaveWindow = false;
SearchResultTooltip.Hide();
return true;
}
internal void OnSettingsChanged( bool highlightedSearchTextColorChanged = false, bool tooltipDescriptionsColorChanged = false )
{
if( searchResult == null )
return;
wantsMouseMove = wantsMouseEnterLeaveWindow = AssetUsageDetectorSettings.ShowCustomTooltip;
for( int i = searchResult.NumberOfGroups - 1; i >= 0; i-- )
{
if( searchResult[i].treeView != null )
{
searchResult[i].treeView.rowHeight = EditorGUIUtility.singleLineHeight + AssetUsageDetectorSettings.ExtraRowHeight;
searchResult[i].treeView.OnSettingsChanged( highlightedSearchTextColorChanged, tooltipDescriptionsColorChanged );
}
}
}
}
}

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 271a22c69c3d96c4dbdd04cca415a840
timeCreated: 1520032279
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

@ -0,0 +1,130 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace AssetUsageDetectorNamespace
{
public class EmptyEnumerator<T> : IEnumerable<T>, IEnumerator<T>
{
public T Current { get { return default( T ); } }
object IEnumerator.Current { get { return Current; } }
public void Dispose() { }
public void Reset() { }
public bool MoveNext()
{
return false;
}
public IEnumerator<T> GetEnumerator()
{
return this;
}
IEnumerator IEnumerable.GetEnumerator()
{
return this;
}
}
public class ObjectToSearchEnumerator : IEnumerable<Object>
{
public class Enumerator : IEnumerator<Object>
{
public Object Current
{
get
{
if( subAssetIndex < 0 )
return source[index].obj;
return source[index].subAssets[subAssetIndex].subAsset;
}
}
object IEnumerator.Current { get { return Current; } }
private List<ObjectToSearch> source;
private int index;
private int subAssetIndex;
public Enumerator( List<ObjectToSearch> source )
{
this.source = source;
Reset();
}
public void Dispose()
{
source = null;
}
public bool MoveNext()
{
if( subAssetIndex < -1 )
{
subAssetIndex = -1;
if( ++index >= source.Count )
return false;
// Skip folder assets in the enumeration, AssetUsageDetector expands encountered folders automatically
// and we don't want that to happen as source[index].subAssets already contains the folder's contents
if( !source[index].obj.IsFolder() )
return true;
}
List<ObjectToSearch.SubAsset> subAssets = source[index].subAssets;
if( subAssets != null )
{
while( ++subAssetIndex < subAssets.Count && !subAssets[subAssetIndex].shouldSearch )
continue;
if( subAssetIndex < subAssets.Count )
return true;
}
subAssetIndex = -2;
return MoveNext();
}
public void Reset()
{
index = -1;
subAssetIndex = -2;
}
}
private readonly List<ObjectToSearch> source;
public ObjectToSearchEnumerator( List<ObjectToSearch> source )
{
this.source = source;
}
public IEnumerator<Object> GetEnumerator()
{
return new Enumerator( source );
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public Object[] ToArray()
{
int count = 0;
foreach( Object obj in this )
count++;
Object[] result = new Object[count];
int index = 0;
foreach( Object obj in this )
result[index++] = obj;
return result;
}
}
}

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 894047c47ce45cf40939dae24afcc72b
timeCreated: 1562079461
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

@ -0,0 +1,252 @@
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
namespace AssetUsageDetectorNamespace
{
public abstract class ListDrawer<T>
{
private readonly string label;
private readonly bool acceptSceneObjects;
protected ListDrawer( string label, bool acceptSceneObjects )
{
this.label = label;
this.acceptSceneObjects = acceptSceneObjects;
}
// Exposes a list on GUI
public bool Draw( List<T> list )
{
bool hasChanged = false;
bool guiEnabled = GUI.enabled;
Event ev = Event.current;
GUILayout.BeginHorizontal();
GUILayout.Label( label );
if( guiEnabled )
{
// Handle drag & drop references to array
// Credit: https://answers.unity.com/answers/657877/view.html
if( ( ev.type == EventType.DragPerform || ev.type == EventType.DragUpdated ) && GUILayoutUtility.GetLastRect().Contains( ev.mousePosition ) )
{
DragAndDrop.visualMode = DragAndDropVisualMode.Copy;
if( ev.type == EventType.DragPerform )
{
DragAndDrop.AcceptDrag();
Object[] draggedObjects = DragAndDrop.objectReferences;
if( draggedObjects.Length > 0 )
{
for( int i = 0; i < draggedObjects.Length; i++ )
{
if( draggedObjects[i] != null && !draggedObjects[i].Equals( null ) )
{
bool replacedNullElement = false;
for( int j = 0; j < list.Count; j++ )
{
if( IsElementNull( list[j] ) )
{
list[j] = CreateElement( draggedObjects[i] );
replacedNullElement = true;
break;
}
}
if( !replacedNullElement )
list.Add( CreateElement( draggedObjects[i] ) );
hasChanged = true;
}
}
}
}
ev.Use();
}
else if( ev.type == EventType.ContextClick && GUILayoutUtility.GetLastRect().Contains( ev.mousePosition ) )
{
GenericMenu contextMenu = new GenericMenu();
contextMenu.AddItem( new GUIContent( "Clear" ), false, () =>
{
list.Clear();
list.Add( CreateElement( null ) );
} );
contextMenu.ShowAsContext();
ev.Use();
}
if( GUILayout.Button( "+", Utilities.GL_WIDTH_25 ) )
list.Insert( 0, CreateElement( null ) );
}
GUILayout.EndHorizontal();
for( int i = 0; i < list.Count; i++ )
{
T element = list[i];
GUI.changed = false;
GUILayout.BeginHorizontal();
Object prevObject = GetObjectFromElement( element );
Object newObject = EditorGUILayout.ObjectField( "", prevObject, typeof( Object ), acceptSceneObjects );
if( GUI.changed )
{
hasChanged = true;
SetObjectOfElement( list, i, newObject );
}
if( guiEnabled )
{
if( GUILayout.Button( "+", Utilities.GL_WIDTH_25 ) )
list.Insert( i + 1, CreateElement( null ) );
if( GUILayout.Button( "-", Utilities.GL_WIDTH_25 ) )
{
if( element != null && !element.Equals( null ) )
hasChanged = true;
// Lists with no elements look ugly, always keep a dummy null variable
if( list.Count > 1 )
list.RemoveAt( i-- );
else
list[0] = CreateElement( null );
}
}
GUILayout.EndHorizontal();
PostElementDrawer( element );
}
return hasChanged;
}
protected abstract T CreateElement( Object source );
protected abstract Object GetObjectFromElement( T element );
protected abstract void SetObjectOfElement( List<T> list, int index, Object value );
protected abstract bool IsElementNull( T element );
protected abstract void PostElementDrawer( T element );
}
public class ObjectListDrawer : ListDrawer<Object>
{
public ObjectListDrawer( string label, bool acceptSceneObjects ) : base( label, acceptSceneObjects )
{
}
protected override Object CreateElement( Object source )
{
return source;
}
protected override Object GetObjectFromElement( Object element )
{
return element;
}
protected override void SetObjectOfElement( List<Object> list, int index, Object value )
{
list[index] = value;
}
protected override bool IsElementNull( Object element )
{
return element == null || element.Equals( null );
}
protected override void PostElementDrawer( Object element )
{
}
}
public class ObjectToSearchListDrawer : ListDrawer<ObjectToSearch>
{
public ObjectToSearchListDrawer() : base( "Find references of:", true )
{
}
protected override ObjectToSearch CreateElement( Object source )
{
return new ObjectToSearch( source );
}
protected override Object GetObjectFromElement( ObjectToSearch element )
{
return element.obj;
}
protected override void SetObjectOfElement( List<ObjectToSearch> list, int index, Object value )
{
list[index].obj = value;
list[index].RefreshSubAssets();
}
protected override bool IsElementNull( ObjectToSearch element )
{
return element == null || element.obj == null || element.obj.Equals( null );
}
protected override void PostElementDrawer( ObjectToSearch element )
{
List<ObjectToSearch.SubAsset> subAssetsToSearch = element.subAssets;
if( subAssetsToSearch.Count > 0 )
{
GUILayout.BeginHorizontal();
// 0-> all toggles off, 1-> mixed, 2-> all toggles on
bool toggleAllSubAssets = subAssetsToSearch[0].shouldSearch;
bool mixedToggle = false;
for( int j = 1; j < subAssetsToSearch.Count; j++ )
{
if( subAssetsToSearch[j].shouldSearch != toggleAllSubAssets )
{
mixedToggle = true;
break;
}
}
if( mixedToggle )
EditorGUI.showMixedValue = true;
GUI.changed = false;
toggleAllSubAssets = EditorGUILayout.Toggle( toggleAllSubAssets, Utilities.GL_WIDTH_25 );
if( GUI.changed )
{
for( int j = 0; j < subAssetsToSearch.Count; j++ )
subAssetsToSearch[j].shouldSearch = toggleAllSubAssets;
}
EditorGUI.showMixedValue = false;
element.showSubAssetsFoldout = EditorGUILayout.Foldout( element.showSubAssetsFoldout, "Include sub-assets in search:", true );
GUILayout.EndHorizontal();
if( element.showSubAssetsFoldout )
{
for( int j = 0; j < subAssetsToSearch.Count; j++ )
{
GUILayout.BeginHorizontal();
subAssetsToSearch[j].shouldSearch = EditorGUILayout.Toggle( subAssetsToSearch[j].shouldSearch, Utilities.GL_WIDTH_25 );
bool guiEnabled = GUI.enabled;
GUI.enabled = false;
EditorGUILayout.ObjectField( string.Empty, subAssetsToSearch[j].subAsset, typeof( Object ), true );
GUI.enabled = guiEnabled;
GUILayout.EndHorizontal();
}
}
}
}
}
}

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 88a4a4e861026b2498a437ce1e12b054
timeCreated: 1568758673
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

@ -0,0 +1,120 @@
using System;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using Object = UnityEngine.Object;
namespace AssetUsageDetectorNamespace
{
[Serializable]
public class ObjectToSearch
{
[Serializable]
public class SubAsset
{
public Object subAsset;
public bool shouldSearch;
public SubAsset( Object subAsset, bool shouldSearch )
{
this.subAsset = subAsset;
this.shouldSearch = shouldSearch;
}
}
public Object obj;
public List<SubAsset> subAssets;
public bool showSubAssetsFoldout;
private static HashSet<Object> currentSubAssets;
public ObjectToSearch( Object obj, bool? shouldSearchChildren = null )
{
this.obj = obj;
RefreshSubAssets( shouldSearchChildren );
}
public void RefreshSubAssets( bool? shouldSearchChildren = null )
{
if( subAssets == null )
subAssets = new List<SubAsset>();
else
subAssets.Clear();
if( currentSubAssets == null )
currentSubAssets = new HashSet<Object>();
else
currentSubAssets.Clear();
AddSubAssets( obj, false, shouldSearchChildren );
currentSubAssets.Clear();
}
private void AddSubAssets( Object target, bool includeTarget, bool? shouldSearchChildren )
{
if( target == null || target.Equals( null ) )
return;
if( !target.IsAsset() )
{
GameObject go = target as GameObject;
if( !go || !go.scene.IsValid() )
return;
// If this is a scene object, add its child objects to the sub-assets list
// but don't include them in the search by default
Transform goTransform = go.transform;
Transform[] children = go.GetComponentsInChildren<Transform>( true );
for( int i = 0; i < children.Length; i++ )
{
if( ReferenceEquals( children[i], goTransform ) )
continue;
subAssets.Add( new SubAsset( children[i].gameObject, shouldSearchChildren ?? false ) );
}
}
else
{
if( !AssetDatabase.IsMainAsset( target ) || target is SceneAsset )
return;
if( includeTarget )
{
if( currentSubAssets.Add( target ) )
subAssets.Add( new SubAsset( target, shouldSearchChildren ?? true ) );
}
else
{
// If asset is a directory, add all of its contents as sub-assets recursively
if( target.IsFolder() )
{
foreach( string filePath in Utilities.EnumerateFolderContents( target ) )
AddSubAssets( AssetDatabase.LoadAssetAtPath<Object>( filePath ), true, shouldSearchChildren );
return;
}
}
// Find sub-asset(s) of the asset (if any)
Object[] assets = AssetDatabase.LoadAllAssetsAtPath( AssetDatabase.GetAssetPath( target ) );
for( int i = 0; i < assets.Length; i++ )
{
Object asset = assets[i];
if( asset == null || asset.Equals( null ) || asset is Component || asset == target )
continue;
#if UNITY_2018_3_OR_NEWER
// Nested prefabs in prefab assets add an additional native object of type 'UnityEngine.PrefabInstance' to the prefab. Managed type of that native type
// is UnityEngine.Object (i.e. GetType() returns UnityEngine.Object, not UnityEngine.PrefabInstance). There are no possible references to these native
// objects so skip them (we're checking for UnityEngine.Prefab because it includes other native types like UnityEngine.PrefabCreation, as well)
if( target is GameObject && asset.GetType() == typeof( Object ) && asset.ToString().Contains( "(UnityEngine.Prefab" ) )
continue;
#endif
if( currentSubAssets.Add( asset ) )
subAssets.Add( new SubAsset( asset, shouldSearchChildren ?? true ) );
}
}
}
}
}

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 66d5a144a723fea40945afc069d4231d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

@ -0,0 +1,382 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using UnityEditor;
using UnityEditor.SceneManagement;
using UnityEngine;
using Object = UnityEngine.Object;
namespace AssetUsageDetectorNamespace
{
public delegate void SearchRefactoring( SearchMatch match );
public abstract class SearchMatch
{
public readonly object Source;
public readonly Object Context; // Almost always equal to Source. This is the Object that needs to be dirtied (if not null) to notify Unity of changes to Value
public Object Value { get; private set; }
protected SearchMatch( object source, Object value )
{
Source = source;
Context = source as Object;
Value = value;
}
protected SearchMatch( object source, Object value, Object context ) : this( source, value )
{
Context = context;
}
public void ChangeValue( Object newValue )
{
if( newValue == Value )
return;
if( Context && ( Context.hideFlags & HideFlags.NotEditable ) == HideFlags.NotEditable )
{
Debug.LogWarning( "Can't change value of read-only Object: " + Context, Context );
return;
}
try
{
bool setContextDirty;
if( ChangeValue( newValue, out setContextDirty ) )
OnValueChanged( newValue, setContextDirty );
}
catch( Exception e )
{
Debug.LogException( e );
}
}
protected abstract bool ChangeValue( Object newValue, out bool setContextDirty );
public void OnValueChanged( Object newValue, bool setContextDirty = true )
{
Value = newValue;
if( setContextDirty )
{
if( Context )
{
if( AssetDatabase.Contains( Context ) )
EditorUtility.SetDirty( Context );
else if( !EditorApplication.isPlaying )
{
EditorUtility.SetDirty( Context );
if( Context is Component )
EditorSceneManager.MarkSceneDirty( ( (Component) Context ).gameObject.scene );
else if( Context is GameObject )
EditorSceneManager.MarkSceneDirty( ( (GameObject) Context ).scene );
else
EditorSceneManager.MarkAllScenesDirty();
}
}
else if( !EditorApplication.isPlaying )
EditorSceneManager.MarkAllScenesDirty();
}
}
}
public abstract class GenericSearchMatch : SearchMatch
{
public delegate void SetterFunction( Object newValue );
public readonly SetterFunction Setter;
internal GenericSearchMatch( object source, Object value, SetterFunction setter ) : base( source, value ) { Setter = setter; }
internal GenericSearchMatch( object source, Object value, Object context, SetterFunction setter ) : base( source, value, context ) { Setter = setter; }
protected override bool ChangeValue( Object newValue, out bool setContextDirty )
{
Setter( newValue );
setContextDirty = true;
return true;
}
}
public abstract class ReadOnlySearchMatch : SearchMatch
{
internal ReadOnlySearchMatch( object source, Object value ) : base( source, value ) { }
protected override bool ChangeValue( Object newValue, out bool setContextDirty )
{
Debug.LogWarning( "Can't change value of " + GetType().Name );
setContextDirty = false;
return false;
}
}
/// <summary>
/// - Source: Object whose SerializedProperty points to Value
/// - Value: Referenced object
/// - SerializedProperty: The SerializedProperty that points to Value
/// </summary>
public class SerializedPropertyMatch : SearchMatch
{
public readonly SerializedProperty SerializedProperty; // Next or NextVisible mustn't be called with this SerializedProperty
internal SerializedPropertyMatch( Object source, Object value, SerializedProperty property ) : base( source, value ) { SerializedProperty = property; }
protected override bool ChangeValue( Object newValue, out bool setContextDirty )
{
setContextDirty = true;
switch( SerializedProperty.propertyType )
{
case SerializedPropertyType.ObjectReference:
SerializedProperty.objectReferenceValue = newValue;
if( SerializedProperty.objectReferenceValue != newValue )
{
Debug.LogWarning( "Couldn't cast " + newValue.GetType() + " to " + SerializedProperty.type );
SerializedProperty.objectReferenceValue = Value;
return false;
}
break;
case SerializedPropertyType.ExposedReference:
SerializedProperty.exposedReferenceValue = newValue;
if( SerializedProperty.exposedReferenceValue != newValue )
{
Debug.LogWarning( "Couldn't cast " + newValue.GetType() + " to " + SerializedProperty.type );
SerializedProperty.exposedReferenceValue = Value;
return false;
}
break;
#if UNITY_2019_3_OR_NEWER
case SerializedPropertyType.ManagedReference: SerializedProperty.managedReferenceValue = newValue; break;
#endif
}
SerializedProperty.serializedObject.ApplyModifiedPropertiesWithoutUndo();
return true;
}
}
/// <summary>
/// - Source: Object whose variable points to Value
/// - Value: Referenced object
/// - Variable: FieldInfo, PropertyInfo or IEnumerable (ChangeValue may not work for all IEnumerables)
/// </summary>
public class ReflectionMatch : SearchMatch
{
public readonly object Variable;
internal ReflectionMatch( object source, Object value, object variable ) : base( source, value ) { Variable = variable; }
protected override bool ChangeValue( Object newValue, out bool setContextDirty )
{
setContextDirty = true;
if( Variable is FieldInfo )
( (FieldInfo) Variable ).SetValue( Source, newValue );
else if( Variable is PropertyInfo )
{
PropertyInfo property = (PropertyInfo) Variable;
if( !property.CanWrite )
{
Debug.LogWarning( "Property is read-only: " + property.DeclaringType.FullName + "." + property.Name );
return false;
}
property.SetValue( Source, newValue, null );
}
else if( Variable is IList )
{
IList list = (IList) Variable;
for( int i = list.Count - 1; i >= 0; i-- )
{
if( ReferenceEquals( list[i], Value ) )
list[i] = newValue;
}
}
else if( Variable is IDictionary )
{
IDictionary dictionary = (IDictionary) Variable;
bool dictionaryModified;
do
{
dictionaryModified = false;
foreach( object dictKey in dictionary.Keys )
{
object dictValue = dictionary[dictKey];
if( ReferenceEquals( dictKey, Value ) )
{
dictionary.Remove( dictKey );
if( newValue )
dictionary[newValue] = dictValue;
dictionaryModified = true;
break;
}
else if( ReferenceEquals( dictValue, Value ) )
{
dictionary[dictKey] = newValue;
dictionaryModified = true;
break;
}
}
} while( dictionaryModified );
}
else
{
Debug.LogWarning( "Can't change value of " + Variable.GetType().Name );
return false;
}
return true;
}
}
/// <summary>
/// - Source: MonoImporter (for scripts) or ShaderImporter
/// - Value: Default value assigned to Source's specified variable in the Inspector
/// - Variable: The variable of Source that Value is assigned to as default value
/// - MonoScriptAllVariables: All variables of Source script if it's MonoImporter
/// </summary>
public class AssetImporterDefaultValueMatch : SearchMatch
{
public readonly string Variable;
public readonly VariableGetterHolder[] MonoScriptAllVariables;
internal AssetImporterDefaultValueMatch( Object source, Object value, string variable, VariableGetterHolder[] monoScriptAllVariables ) : base( source, value )
{
Variable = variable;
MonoScriptAllVariables = monoScriptAllVariables;
}
protected override bool ChangeValue( Object newValue, out bool setContextDirty )
{
setContextDirty = false;
if( Source is MonoImporter )
{
MonoImporter monoImporter = (MonoImporter) Source;
List<string> variableNames = new List<string>( 8 );
List<Object> variableValues = new List<Object>( 8 );
for( int i = 0; i < MonoScriptAllVariables.Length; i++ )
{
if( MonoScriptAllVariables[i].isSerializable && !MonoScriptAllVariables[i].IsProperty )
{
Object variableDefaultValue = monoImporter.GetDefaultReference( MonoScriptAllVariables[i].Name );
if( variableDefaultValue == Value && MonoScriptAllVariables[i].Name == Variable )
variableDefaultValue = newValue;
variableNames.Add( MonoScriptAllVariables[i].Name );
variableValues.Add( variableDefaultValue );
}
}
monoImporter.SetDefaultReferences( variableNames.ToArray(), variableValues.ToArray() );
EditorApplication.delayCall += () => AssetDatabase.ImportAsset( monoImporter.assetPath ); // If code recompiles during search, it will break the search. Give it a 1 frame delay
}
else if( Source is ShaderImporter )
{
ShaderImporter shaderImporter = (ShaderImporter) Source;
Shader shader = shaderImporter.GetShader();
List<string> textureNames = new List<string>( 16 );
List<Texture> textureValues = new List<Texture>( 16 );
#if UNITY_2018_1_OR_NEWER
List<string> nonModifiableTextureNames = new List<string>( 16 );
List<Texture> nonModifiableTextureValues = new List<Texture>( 16 );
#endif
int shaderPropertyCount = ShaderUtil.GetPropertyCount( shader );
for( int i = 0; i < shaderPropertyCount; i++ )
{
if( ShaderUtil.GetPropertyType( shader, i ) != ShaderUtil.ShaderPropertyType.TexEnv )
continue;
string propertyName = ShaderUtil.GetPropertyName( shader, i );
#if UNITY_2018_1_OR_NEWER
if( ShaderUtil.IsShaderPropertyNonModifiableTexureProperty( shader, i ) )
{
Texture propertyDefaultValue = shaderImporter.GetNonModifiableTexture( propertyName );
if( propertyDefaultValue == Value && propertyName == Variable )
propertyDefaultValue = (Texture) newValue;
nonModifiableTextureNames.Add( propertyName );
nonModifiableTextureValues.Add( propertyDefaultValue );
}
else
#endif
{
Texture propertyDefaultValue = shaderImporter.GetDefaultTexture( propertyName );
if( propertyDefaultValue == Value && propertyName == Variable )
propertyDefaultValue = (Texture) newValue;
textureNames.Add( propertyName );
textureValues.Add( propertyDefaultValue );
}
}
shaderImporter.SetDefaultTextures( textureNames.ToArray(), textureValues.ToArray() );
#if UNITY_2018_1_OR_NEWER
shaderImporter.SetNonModifiableTextures( nonModifiableTextureNames.ToArray(), nonModifiableTextureValues.ToArray() );
#endif
AssetDatabase.ImportAsset( shaderImporter.assetPath );
}
else
{
Debug.LogWarning( "Can't change default value of: " + Source.GetType() );
return false;
}
return true;
}
}
/// <summary>
/// - Source: Animation, Animator, AnimatorStateMachine, AnimatorState, AnimatorControllerLayer, BlendTree, PlayableDirector* or AnimationClip*
/// - Context: If Source is AnimatorControllerLayer, then its RuntimeAnimatorController. Otherwise, equal to Source
/// - Value: AnimationClip, AnimatorController or AvatarMask used in Source (*for PlayableDirector and AnimationClip, it can be any Object value)
/// </summary>
public class AnimationSystemMatch : GenericSearchMatch
{
internal AnimationSystemMatch( object source, Object value, SetterFunction setter ) : base( source, value, setter ) { }
internal AnimationSystemMatch( object source, Object value, Object context, SetterFunction setter ) : base( source, value, context, setter ) { }
}
/// <summary>
/// - Source: GameObject, AnimatorStateMachine or AnimatorState
/// - Value: The attached behaviour's source script (C# script or DLL, i.e. MonoScript)
/// - Behaviour: The attached behaviour (MonoBehaviour or StateMachineBehaviour)
/// </summary>
public class BehaviourUsageMatch : ReadOnlySearchMatch
{
public readonly Object Behaviour;
internal BehaviourUsageMatch( Object source, MonoScript value, Object behaviour ) : base( source, value ) { Behaviour = behaviour; }
}
/// <summary>
/// - Source: GameObject Instance
/// - Value: Prefab of that GameObject
/// </summary>
public class PrefabMatch : ReadOnlySearchMatch
{
internal PrefabMatch( Object source, Object value ) : base( source, value ) { }
}
/// <summary>
/// - Source: Object that references Value
/// - Value: Matched object
/// </summary>
public class OtherSearchMatch : GenericSearchMatch
{
internal OtherSearchMatch( object source, Object value, SetterFunction setter ) : base( source, value, setter ) { }
internal OtherSearchMatch( object source, Object value, Object context, SetterFunction setter ) : base( source, value, context, setter ) { }
}
}

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 3d15ef8bd8f7c7c4e8d228c99713b7eb
timeCreated: 1641132238
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load Diff

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ca236e4f3c5a9f447be89f0e61e485fa
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

@ -0,0 +1,91 @@
using System.Reflection;
using UnityEditor;
using UnityEngine;
namespace AssetUsageDetectorNamespace
{
public class SearchResultTooltip : EditorWindow
{
private static SearchResultTooltip mainWindow;
private static string tooltip;
private static GUIStyle m_style;
internal static GUIStyle Style
{
get
{
if( m_style == null )
{
m_style = (GUIStyle) typeof( EditorStyles ).GetProperty( "tooltip", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static ).GetValue( null, null );
m_style.richText = true;
}
return m_style;
}
}
public static void Show( Rect sourcePosition, string tooltip )
{
Vector2 preferredSize = Style.CalcSize( new GUIContent( tooltip ) ) + Style.contentOffset + new Vector2( Style.padding.horizontal + Style.margin.horizontal, Style.padding.vertical + Style.margin.vertical );
Rect preferredPosition;
Rect positionLeft = new Rect( sourcePosition.position - new Vector2( preferredSize.x, 0f ), preferredSize );
Rect screenFittedPositionLeft = Utilities.GetScreenFittedRect( positionLeft );
Vector2 positionOffset = positionLeft.position - screenFittedPositionLeft.position;
Vector2 sizeOffset = positionLeft.size - screenFittedPositionLeft.size;
if( positionOffset.sqrMagnitude <= 400f && sizeOffset.sqrMagnitude <= 400f )
preferredPosition = screenFittedPositionLeft;
else
{
Rect positionRight = new Rect( sourcePosition.position + new Vector2( sourcePosition.width, 0f ), preferredSize );
Rect screenFittedPositionRight = Utilities.GetScreenFittedRect( positionRight );
Vector2 positionOffset2 = positionRight.position - screenFittedPositionRight.position;
Vector2 sizeOffset2 = positionRight.size - screenFittedPositionRight.size;
if( positionOffset2.magnitude + sizeOffset2.magnitude < positionOffset.magnitude + sizeOffset.magnitude )
preferredPosition = screenFittedPositionRight;
else
preferredPosition = screenFittedPositionLeft;
}
// Don't lose focus to the previous window
EditorWindow prevFocusedWindow = focusedWindow;
if( !mainWindow )
{
mainWindow = CreateInstance<SearchResultTooltip>();
mainWindow.ShowPopup();
}
SearchResultTooltip.tooltip = tooltip;
mainWindow.minSize = preferredPosition.size;
mainWindow.position = preferredPosition;
mainWindow.Repaint();
if( prevFocusedWindow )
prevFocusedWindow.Focus();
}
public static void Hide()
{
if( mainWindow )
{
mainWindow.Close();
mainWindow = null;
}
}
private void OnGUI()
{
// If somehow the tooltip isn't automatically closed, allow closing it by clicking on it
if( Event.current.type == EventType.MouseDown )
{
Hide();
GUIUtility.ExitGUI();
}
GUI.Label( new Rect( Vector2.zero, position.size ), tooltip, Style );
}
}
}

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: c8bd4351b5024324ca5974ebcad1dde3
timeCreated: 1639247551
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: b3903f1d3149e9b4990e49206f8255c8
timeCreated: 1638690728
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

@ -0,0 +1,565 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Text;
#if UNITY_2018_1_OR_NEWER
using Unity.Collections;
#endif
using UnityEditor;
using UnityEditor.SceneManagement;
using UnityEngine;
using UnityEngine.SceneManagement;
using Object = UnityEngine.Object;
#if UNITY_2018_3_OR_NEWER && !UNITY_2021_2_OR_NEWER
using PrefabStage = UnityEditor.Experimental.SceneManagement.PrefabStage;
using PrefabStageUtility = UnityEditor.Experimental.SceneManagement.PrefabStageUtility;
#endif
namespace AssetUsageDetectorNamespace
{
public static class Utilities
{
// A set of commonly used Unity types
private static readonly HashSet<Type> primitiveUnityTypes = new HashSet<Type>()
{
typeof( string ), typeof( Vector4 ), typeof( Vector3 ), typeof( Vector2 ), typeof( Rect ),
typeof( Quaternion ), typeof( Color ), typeof( Color32 ), typeof( LayerMask ), typeof( Bounds ),
typeof( Matrix4x4 ), typeof( AnimationCurve ), typeof( Gradient ), typeof( RectOffset ),
typeof( bool[] ), typeof( byte[] ), typeof( sbyte[] ), typeof( char[] ), typeof( decimal[] ),
typeof( double[] ), typeof( float[] ), typeof( int[] ), typeof( uint[] ), typeof( long[] ),
typeof( ulong[] ), typeof( short[] ), typeof( ushort[] ), typeof( string[] ),
typeof( Vector4[] ), typeof( Vector3[] ), typeof( Vector2[] ), typeof( Rect[] ),
typeof( Quaternion[] ), typeof( Color[] ), typeof( Color32[] ), typeof( LayerMask[] ), typeof( Bounds[] ),
typeof( Matrix4x4[] ), typeof( AnimationCurve[] ), typeof( Gradient[] ), typeof( RectOffset[] ),
typeof( List<bool> ), typeof( List<byte> ), typeof( List<sbyte> ), typeof( List<char> ), typeof( List<decimal> ),
typeof( List<double> ), typeof( List<float> ), typeof( List<int> ), typeof( List<uint> ), typeof( List<long> ),
typeof( List<ulong> ), typeof( List<short> ), typeof( List<ushort> ), typeof( List<string> ),
typeof( List<Vector4> ), typeof( List<Vector3> ), typeof( List<Vector2> ), typeof( List<Rect> ),
typeof( List<Quaternion> ), typeof( List<Color> ), typeof( List<Color32> ), typeof( List<LayerMask> ), typeof( List<Bounds> ),
typeof( List<Matrix4x4> ), typeof( List<AnimationCurve> ), typeof( List<Gradient> ), typeof( List<RectOffset> ),
#if UNITY_2017_2_OR_NEWER
typeof( Vector3Int ), typeof( Vector2Int ), typeof( RectInt ), typeof( BoundsInt ),
typeof( Vector3Int[] ), typeof( Vector2Int[] ), typeof( RectInt[] ), typeof( BoundsInt[] ),
typeof( List<Vector3Int> ), typeof( List<Vector2Int> ), typeof( List<RectInt> ), typeof( List<BoundsInt> )
#endif
};
private static readonly string reflectionNamespace = typeof( Assembly ).Namespace;
#if UNITY_2018_1_OR_NEWER
private static readonly string nativeCollectionsNamespace = typeof( NativeArray<int> ).Namespace;
#endif
private static MethodInfo screenFittedRectGetter;
private static readonly HashSet<string> folderContentsSet = new HashSet<string>();
internal static readonly StringBuilder stringBuilder = new StringBuilder( 400 );
public static readonly GUILayoutOption GL_EXPAND_WIDTH = GUILayout.ExpandWidth( true );
public static readonly GUILayoutOption GL_EXPAND_HEIGHT = GUILayout.ExpandHeight( true );
public static readonly GUILayoutOption GL_WIDTH_25 = GUILayout.Width( 25 );
public static readonly GUILayoutOption GL_WIDTH_100 = GUILayout.Width( 100 );
public static readonly GUILayoutOption GL_WIDTH_250 = GUILayout.Width( 250 );
public static readonly GUILayoutOption GL_HEIGHT_0 = GUILayout.Height( 0 );
public static readonly GUILayoutOption GL_HEIGHT_2 = GUILayout.Height( 2 );
public static readonly GUILayoutOption GL_HEIGHT_30 = GUILayout.Height( 30 );
public static readonly GUILayoutOption GL_HEIGHT_35 = GUILayout.Height( 35 );
public static readonly GUILayoutOption GL_HEIGHT_40 = GUILayout.Height( 40 );
private static GUIStyle m_boxGUIStyle; // GUIStyle used to draw the results of the search
public static GUIStyle BoxGUIStyle
{
get
{
if( m_boxGUIStyle == null )
{
m_boxGUIStyle = new GUIStyle( EditorStyles.helpBox )
{
alignment = TextAnchor.MiddleCenter,
font = EditorStyles.label.font,
richText = true
};
Color textColor = GUI.skin.button.normal.textColor;
m_boxGUIStyle.normal.textColor = textColor;
m_boxGUIStyle.hover.textColor = textColor;
m_boxGUIStyle.focused.textColor = textColor;
m_boxGUIStyle.active.textColor = textColor;
#if !UNITY_2019_1_OR_NEWER || UNITY_2019_3_OR_NEWER
// On 2019.1 and 2019.2 versions, GUI.skin.button.fontSize returns 0 on some devices
// https://forum.unity.com/threads/asset-usage-detector-find-references-to-an-asset-object-open-source.408134/page-3#post-7285954
m_boxGUIStyle.fontSize = ( m_boxGUIStyle.fontSize + GUI.skin.button.fontSize ) / 2;
#endif
}
return m_boxGUIStyle;
}
}
// Check if object is an asset or a Scene object
public static bool IsAsset( this object obj )
{
return obj is Object && AssetDatabase.Contains( (Object) obj );
}
public static bool IsAsset( this Object obj )
{
return AssetDatabase.Contains( obj );
}
// Check if object is a folder asset
public static bool IsFolder( this Object obj )
{
return obj is DefaultAsset && AssetDatabase.IsValidFolder( AssetDatabase.GetAssetPath( obj ) );
}
// Returns an enumerator to iterate through all asset paths in the folder
public static IEnumerable<string> EnumerateFolderContents( Object folderAsset )
{
string[] folderContents = AssetDatabase.FindAssets( "", new string[] { AssetDatabase.GetAssetPath( folderAsset ) } );
if( folderContents == null )
return new EmptyEnumerator<string>();
folderContentsSet.Clear();
for( int i = 0; i < folderContents.Length; i++ )
{
string filePath = AssetDatabase.GUIDToAssetPath( folderContents[i] );
if( !string.IsNullOrEmpty( filePath ) && !AssetDatabase.IsValidFolder( filePath ) )
folderContentsSet.Add( filePath );
}
return folderContentsSet;
}
public static void GetObjectsToSelectAndPing( this Object obj, out Object selection, out Object pingTarget )
{
if( obj == null || obj.Equals( null ) )
{
selection = pingTarget = null;
return;
}
if( obj is Component )
obj = ( (Component) obj ).gameObject;
selection = pingTarget = obj;
if( obj.IsAsset() )
{
if( obj is GameObject )
{
// Pinging a prefab only works if the pinged object is the root of the prefab or a direct child of it. Pinging any grandchildren
// of the prefab doesn't work; in which case, traverse the parent hierarchy until a pingable parent is reached
#if UNITY_2018_3_OR_NEWER
Transform objTR = ( (GameObject) obj ).transform.root;
PrefabAssetType prefabAssetType = PrefabUtility.GetPrefabAssetType( objTR.gameObject );
if( prefabAssetType == PrefabAssetType.Regular || prefabAssetType == PrefabAssetType.Variant )
{
string assetPath = AssetDatabase.GetAssetPath( objTR.gameObject );
PrefabStage openPrefabStage = PrefabStageUtility.GetCurrentPrefabStage();
#if UNITY_2020_1_OR_NEWER
if( openPrefabStage != null && openPrefabStage.stageHandle.IsValid() && assetPath == openPrefabStage.assetPath )
#else
if( openPrefabStage != null && openPrefabStage.stageHandle.IsValid() && assetPath == openPrefabStage.prefabAssetPath )
#endif
{
GameObject prefabStageGO = FollowSymmetricHierarchy( (GameObject) obj, ( (GameObject) obj ).transform.root.gameObject, openPrefabStage.prefabContentsRoot );
if( prefabStageGO != null )
{
objTR = prefabStageGO.transform;
selection = objTR.gameObject;
}
}
#if UNITY_2019_1_OR_NEWER
else if( obj != objTR.gameObject )
selection = objTR.gameObject;
#endif
}
else if( prefabAssetType == PrefabAssetType.Model )
{
objTR = ( (GameObject) obj ).transform;
while( objTR.parent != null && objTR.parent.parent != null )
objTR = objTR.parent;
}
#else
Transform objTR = ( (GameObject) obj ).transform;
while( objTR.parent != null && objTR.parent.parent != null )
objTR = objTR.parent;
#endif
pingTarget = objTR.gameObject;
}
else if( ( obj.hideFlags & ( HideFlags.HideInInspector | HideFlags.HideInHierarchy ) ) != HideFlags.None )
{
// Can't ping assets that are hidden from Project window (e.g. animator states of AnimatorController), ping the main asset at that path instead
pingTarget = AssetDatabase.LoadMainAssetAtPath( AssetDatabase.GetAssetPath( obj ) );
}
else if( !AssetDatabase.IsMainAsset( obj ) && Array.IndexOf( AssetDatabase.LoadAllAssetRepresentationsAtPath( AssetDatabase.GetAssetPath( obj ) ), obj ) < 0 )
{
// VFX Graph assets' nodes are serialized as part of the graph but they are invisible in the Project window even though their hideFlags is None (I don't know how)
pingTarget = AssetDatabase.LoadMainAssetAtPath( AssetDatabase.GetAssetPath( obj ) );
}
}
}
// We are passing "go"s root Transform to thisRoot parameter. If we use go.transform.root instead, when we are in prefab mode on
// newer Unity versions, it points to the preview scene at the root of the prefab stage instead of pointing to the actual root of "go"
public static GameObject FollowSymmetricHierarchy( this GameObject go, GameObject thisRoot, GameObject symmetricRoot )
{
Transform target = go.transform;
Transform root1 = thisRoot.transform;
Transform root2 = symmetricRoot.transform;
while( root1 != target )
{
Transform temp = target;
while( temp.parent != root1 )
temp = temp.parent;
Transform newRoot2;
int siblingIndex = temp.GetSiblingIndex();
if( siblingIndex < root2.childCount )
{
newRoot2 = root2.GetChild( siblingIndex );
if( newRoot2.name != temp.name )
newRoot2 = root2.Find( temp.name );
}
else
newRoot2 = root2.Find( temp.name );
if( newRoot2 == null )
return null;
root2 = newRoot2;
root1 = temp;
}
return root2.gameObject;
}
// Returns -1 if t1 is above t2 in Hierarchy, 1 if t1 is below t2 in Hierarchy and 0 if they are the same object
public static int CompareHierarchySiblingIndices( Transform t1, Transform t2 )
{
Transform parent1 = t1.parent;
Transform parent2 = t2.parent;
if( parent1 == parent2 )
return t1.GetSiblingIndex() - t2.GetSiblingIndex();
int deltaHierarchyDepth = 0;
for( ; parent1; parent1 = parent1.parent )
deltaHierarchyDepth++;
for( ; parent2; parent2 = parent2.parent )
deltaHierarchyDepth--;
for( ; deltaHierarchyDepth > 0; deltaHierarchyDepth-- )
{
t1 = t1.parent;
if( t1 == t2 )
return 1;
}
for( ; deltaHierarchyDepth < 0; deltaHierarchyDepth++ )
{
t2 = t2.parent;
if( t1 == t2 )
return -1;
}
while( t1.parent != t2.parent )
{
t1 = t1.parent;
t2 = t2.parent;
}
return t1.GetSiblingIndex() - t2.GetSiblingIndex();
}
// Check if the field is serializable
public static bool IsSerializable( this FieldInfo fieldInfo )
{
// See Serialization Rules: https://docs.unity3d.com/Manual/script-Serialization.html
if( fieldInfo.IsInitOnly )
return false;
#if UNITY_2019_3_OR_NEWER
// SerializeReference makes even System.Object fields serializable
if( Attribute.IsDefined( fieldInfo, typeof( SerializeReference ) ) )
return true;
#endif
if( ( !fieldInfo.IsPublic || fieldInfo.IsNotSerialized ) && !Attribute.IsDefined( fieldInfo, typeof( SerializeField ) ) )
return false;
return IsTypeSerializable( fieldInfo.FieldType );
}
// Check if the property is serializable
public static bool IsSerializable( this PropertyInfo propertyInfo )
{
return IsTypeSerializable( propertyInfo.PropertyType );
}
// Check if type is serializable
private static bool IsTypeSerializable( Type type )
{
// see Serialization Rules: https://docs.unity3d.com/Manual/script-Serialization.html
if( typeof( Object ).IsAssignableFrom( type ) )
return true;
if( type.IsArray )
{
if( type.GetArrayRank() != 1 )
return false;
type = type.GetElementType();
if( typeof( Object ).IsAssignableFrom( type ) )
return true;
}
else if( type.IsGenericType )
{
// Generic types are allowed on 2020.1 and later
#if UNITY_2020_1_OR_NEWER
if( type.GetGenericTypeDefinition() == typeof( List<> ) )
{
type = type.GetGenericArguments()[0];
if( typeof( Object ).IsAssignableFrom( type ) )
return true;
}
#else
if( type.GetGenericTypeDefinition() != typeof( List<> ) )
return false;
type = type.GetGenericArguments()[0];
if( typeof( Object ).IsAssignableFrom( type ) )
return true;
#endif
}
#if !UNITY_2020_1_OR_NEWER
if( type.IsGenericType )
return false;
#endif
return Attribute.IsDefined( type, typeof( SerializableAttribute ), false );
}
// Check if instances of this type should be searched for references
public static bool IsIgnoredUnityType( this Type type )
{
if( type.IsPrimitive || primitiveUnityTypes.Contains( type ) || type.IsEnum )
return true;
#if UNITY_2018_1_OR_NEWER
// Searching NativeArrays for reference can throw InvalidOperationException if the collection is disposed
if( type.Namespace == nativeCollectionsNamespace )
return true;
#endif
// Searching assembly variables for reference throws InvalidCastException on .NET 4.0 runtime
if( typeof( Type ).IsAssignableFrom( type ) || type.Namespace == reflectionNamespace )
return true;
// Searching pointers or ref variables for reference throws ArgumentException
if( type.IsPointer || type.IsByRef )
return true;
return false;
}
// Get <get> function for a field
public static VariableGetVal CreateGetter( this FieldInfo fieldInfo, Type type )
{
// Commented the IL generator code below because it might actually be slower than simply using reflection
// Credit: https://www.codeproject.com/Articles/14560/Fast-Dynamic-Property-Field-Accessors
//DynamicMethod dm = new DynamicMethod( "Get" + fieldInfo.Name, fieldInfo.FieldType, new Type[] { typeof( object ) }, type );
//ILGenerator il = dm.GetILGenerator();
//// Load the instance of the object (argument 0) onto the stack
//il.Emit( OpCodes.Ldarg_0 );
//// Load the value of the object's field (fi) onto the stack
//il.Emit( OpCodes.Ldfld, fieldInfo );
//// return the value on the top of the stack
//il.Emit( OpCodes.Ret );
//return (VariableGetVal) dm.CreateDelegate( typeof( VariableGetVal ) );
return fieldInfo.GetValue;
}
// Get <get> function for a property
public static VariableGetVal CreateGetter( this PropertyInfo propertyInfo )
{
// Can't use PropertyWrapper (which uses CreateDelegate) for property getters of structs
if( propertyInfo.DeclaringType.IsValueType )
{
return !propertyInfo.CanRead ? (VariableGetVal) null : ( obj ) =>
{
try
{
return propertyInfo.GetValue( obj, null );
}
catch
{
// Property getters may return various kinds of exceptions if their backing fields are not initialized (yet)
return null;
}
};
}
Type GenType = typeof( PropertyWrapper<,> ).MakeGenericType( propertyInfo.DeclaringType, propertyInfo.PropertyType );
return ( (IPropertyAccessor) Activator.CreateInstance( GenType, propertyInfo.GetGetMethod( true ) ) ).GetValue;
}
// Check if all open scenes are saved (not dirty)
public static bool AreScenesSaved()
{
for( int i = 0; i < SceneManager.sceneCount; i++ )
{
Scene scene = SceneManager.GetSceneAt( i );
if( scene.isDirty || string.IsNullOrEmpty( scene.path ) )
return false;
}
return true;
}
// Returns file extension in lowercase (period not included)
public static string GetFileExtension( string path )
{
int extensionIndex = path.LastIndexOf( '.' );
if( extensionIndex < 0 || extensionIndex >= path.Length - 1 )
return "";
stringBuilder.Length = 0;
for( extensionIndex++; extensionIndex < path.Length; extensionIndex++ )
{
char ch = path[extensionIndex];
if( ch >= 65 && ch <= 90 ) // A-Z
ch += (char) 32; // Converted to a-z
stringBuilder.Append( ch );
}
return stringBuilder.ToString();
}
// Draw horizontal line inside OnGUI
public static void DrawSeparatorLine()
{
GUILayout.Space( 4f );
GUILayout.Box( "", GL_HEIGHT_2, GL_EXPAND_WIDTH );
GUILayout.Space( 4f );
}
// Restricts the given Rect within the screen's bounds
public static Rect GetScreenFittedRect( Rect originalRect )
{
if( screenFittedRectGetter == null )
screenFittedRectGetter = typeof( EditorWindow ).Assembly.GetType( "UnityEditor.ContainerWindow" ).GetMethod( "FitRectToScreen", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static );
return (Rect) screenFittedRectGetter.Invoke( null, new object[3] { originalRect, true, true } );
}
// Check if all the objects inside the list are null
public static bool IsEmpty( this List<ObjectToSearch> objectsToSearch )
{
if( objectsToSearch == null )
return true;
for( int i = 0; i < objectsToSearch.Count; i++ )
{
if( objectsToSearch[i].obj != null && !objectsToSearch[i].obj.Equals( null ) )
return false;
}
return true;
}
// Check if all the objects inside the list are null
public static bool IsEmpty( this List<Object> objects )
{
if( objects == null )
return true;
for( int i = 0; i < objects.Count; i++ )
{
if( objects[i] != null && !objects[i].Equals( null ) )
return false;
}
return true;
}
// Check if all the objects that are enumerated are null
public static bool IsEmpty( this IEnumerable<Object> objects )
{
if( objects == null )
return true;
using( IEnumerator<Object> enumerator = objects.GetEnumerator() )
{
while( enumerator.MoveNext() )
{
if( enumerator.Current != null && !enumerator.Current.Equals( null ) )
return false;
}
}
return true;
}
// Returns true is str starts with prefix
public static bool StartsWithFast( this string str, string prefix )
{
int aLen = str.Length;
int bLen = prefix.Length;
int ap = 0; int bp = 0;
while( ap < aLen && bp < bLen && str[ap] == prefix[bp] )
{
ap++;
bp++;
}
return bp == bLen;
}
// Returns true is str ends with postfix
public static bool EndsWithFast( this string str, string postfix )
{
int ap = str.Length - 1;
int bp = postfix.Length - 1;
while( ap >= 0 && bp >= 0 && str[ap] == postfix[bp] )
{
ap--;
bp--;
}
return bp < 0;
}
public static bool ContainsFast<T>( this List<T> list, T element )
{
if( !( element is ValueType ) )
{
for( int i = list.Count - 1; i >= 0; i-- )
{
if( ReferenceEquals( list[i], element ) )
return true;
}
}
else
{
for( int i = list.Count - 1; i >= 0; i-- )
{
if( element.Equals( list[i] ) )
return true;
}
}
return false;
}
}
}

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 52b272b7591fb90499916205261524e0
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

@ -0,0 +1,83 @@
using System;
using System.Reflection;
using System.Text;
using UnityEngine;
namespace AssetUsageDetectorNamespace
{
// Delegate to get the value of a variable (either field or property)
public delegate object VariableGetVal( object obj );
// Custom struct to hold a variable, its important properties and its getter function
public struct VariableGetterHolder
{
public readonly MemberInfo variable;
public readonly bool isSerializable;
private readonly VariableGetVal getter;
public string Name { get { return variable.Name; } }
public bool IsProperty { get { return variable is PropertyInfo; } }
public VariableGetterHolder( FieldInfo fieldInfo, VariableGetVal getter, bool isSerializable )
{
this.variable = fieldInfo;
this.isSerializable = isSerializable;
this.getter = getter;
}
public VariableGetterHolder( PropertyInfo propertyInfo, VariableGetVal getter, bool isSerializable )
{
this.variable = propertyInfo;
this.isSerializable = isSerializable;
this.getter = getter;
}
public object Get( object obj )
{
try
{
return getter( obj );
}
catch( Exception e )
{
StringBuilder sb = Utilities.stringBuilder;
sb.Length = 0;
sb.Append( "Error while getting the value of (" ).Append( IsProperty ? ( (PropertyInfo) variable ).PropertyType : ( (FieldInfo) variable ).FieldType ).Append( ") " )
.Append( variable.DeclaringType ).Append( "." ).Append( Name ).Append( ": " ).Append( e );
Debug.LogError( sb.ToString() );
return null;
}
}
}
// Credit: http://stackoverflow.com/questions/724143/how-do-i-create-a-delegate-for-a-net-property
public interface IPropertyAccessor
{
object GetValue( object source );
}
// A wrapper class for properties to get their values more efficiently
public class PropertyWrapper<TObject, TValue> : IPropertyAccessor where TObject : class
{
private readonly Func<TObject, TValue> getter;
public PropertyWrapper( MethodInfo getterMethod )
{
getter = (Func<TObject, TValue>) Delegate.CreateDelegate( typeof( Func<TObject, TValue> ), getterMethod );
}
public object GetValue( object obj )
{
try
{
return getter( (TObject) obj );
}
catch
{
// Property getters may return various kinds of exceptions if their backing fields are not initialized (yet)
return null;
}
}
}
}

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 9e94c83e8b850514ca0217aeff1491a6
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

@ -0,0 +1,4 @@
= Asset Usage Detector (v2.5.3) =
Documentation: https://github.com/yasirkula/UnityAssetUsageDetector
E-mail: yasirkula@gmail.com

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: ac528f1751f33a647a45caeff6a9344b
timeCreated: 1520032521
licenseType: Store
TextScriptImporter:
userData:
assetBundleName:
assetBundleVariant:

@ -243,6 +243,10 @@ PrefabInstance:
propertyPath: m_ClientVisualization
value:
objectReference: {fileID: 7209204667172237188}
- target: {fileID: 7420593339233078707, guid: 0d2d836e2e83b754fa1a1c4022d6d65d, type: 3}
propertyPath: uIStateDisplayHandler
value:
objectReference: {fileID: 2576537793715222015}
- target: {fileID: 7690172137830037487, guid: 0d2d836e2e83b754fa1a1c4022d6d65d, type: 3}
propertyPath: m_Enabled
value: 1
@ -700,6 +704,7 @@ MonoBehaviour:
m_DisplayHealth: 1
m_DisplayName: 1
m_UIStatePrefab: {fileID: -1943162842029199943, guid: 2b07482491a17964380023240087ce16, type: 3}
m_UIState: {fileID: 0}
m_NetworkHealthState: {fileID: 7751377510591478590}
m_NetworkNameState: {fileID: -8197545831548902967}
m_BaseHP: {fileID: 0}

@ -1,5 +1,137 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &1494894897330052786
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 9018035827392313124}
- component: {fileID: 5538368923929045334}
- component: {fileID: 1678916513842311094}
- component: {fileID: 2486900489436361486}
m_Layer: 5
m_Name: CrossButton
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &9018035827392313124
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1494894897330052786}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 8467790018694481767}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0}
m_AnchorMax: {x: 0.5, y: 0}
m_AnchoredPosition: {x: 20, y: 0}
m_SizeDelta: {x: 27.375, y: 27.25}
m_Pivot: {x: 0.5, y: 0}
--- !u!222 &5538368923929045334
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1494894897330052786}
m_CullTransparentMesh: 1
--- !u!114 &1678916513842311094
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1494894897330052786}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: -187649311, guid: 730b0201dba9701479b075c3cc0c9d0c, type: 3}
m_Type: 0
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!114 &2486900489436361486
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1494894897330052786}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Navigation:
m_Mode: 3
m_WrapAround: 0
m_SelectOnUp: {fileID: 0}
m_SelectOnDown: {fileID: 0}
m_SelectOnLeft: {fileID: 0}
m_SelectOnRight: {fileID: 0}
m_Transition: 1
m_Colors:
m_NormalColor: {r: 1, g: 1, b: 1, a: 1}
m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1}
m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608}
m_ColorMultiplier: 1
m_FadeDuration: 0.1
m_SpriteState:
m_HighlightedSprite: {fileID: 0}
m_PressedSprite: {fileID: 0}
m_SelectedSprite: {fileID: 0}
m_DisabledSprite: {fileID: 0}
m_AnimationTriggers:
m_NormalTrigger: Normal
m_HighlightedTrigger: Highlighted
m_PressedTrigger: Pressed
m_SelectedTrigger: Selected
m_DisabledTrigger: Disabled
m_Interactable: 1
m_TargetGraphic: {fileID: 1678916513842311094}
m_OnClick:
m_PersistentCalls:
m_Calls:
- m_Target: {fileID: 2833502134534602906}
m_TargetAssemblyTypeName: SwapConfirmationPanel, Unity.BossRoom.Gameplay
m_MethodName: OnDeclineButtonPressed
m_Mode: 1
m_Arguments:
m_ObjectArgument: {fileID: 0}
m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine
m_IntArgument: 0
m_FloatArgument: 0
m_StringArgument:
m_BoolArgument: 0
m_CallState: 2
--- !u!1 &1678686474824094549
GameObject:
m_ObjectHideFlags: 0
@ -28,11 +160,12 @@ RectTransform:
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 4684960432987786827}
- {fileID: 2113819744356243524}
- {fileID: 254771808888734010}
m_Father: {fileID: 0}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0.5}
m_AnchorMax: {x: 0.5, y: 0.5}
@ -77,13 +210,413 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: baba913bade45a84486ef7a3f715299e, type: 3}
m_Name:
m_EditorClassIdentifier:
swapConfirmationPanel: {fileID: 2833502134534602906}
playerName:
m_UIName: {fileID: 2963962490385848884}
m_UIHealth: {fileID: 6385511411654384321}
--- !u!1 &3198388185403688655
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 6284368815799428365}
- component: {fileID: 7797288771431175908}
- component: {fileID: 799420244153101338}
m_Layer: 0
m_Name: Text (TMP) (1)
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &6284368815799428365
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3198388185403688655}
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 8467790018694481767}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 1}
m_AnchorMax: {x: 0.5, y: 1}
m_AnchoredPosition: {x: 0, y: 10}
m_SizeDelta: {x: 100, y: 18}
m_Pivot: {x: 0.5, y: 1}
--- !u!222 &7797288771431175908
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3198388185403688655}
m_CullTransparentMesh: 1
--- !u!114 &799420244153101338
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3198388185403688655}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 0
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_text: SWAP?
m_isRightToLeft: 0
m_fontAsset: {fileID: 11400000, guid: 1a8c97d4cbe5134499b26527f8609c7e, type: 2}
m_sharedMaterial: {fileID: 2100000, guid: 9ba25c6f3254c4a4cb00e7407e967916, type: 2}
m_fontSharedMaterials: []
m_fontMaterial: {fileID: 0}
m_fontMaterials: []
m_fontColor32:
serializedVersion: 2
rgba: 4294967295
m_fontColor: {r: 1, g: 1, b: 1, a: 1}
m_enableVertexGradient: 0
m_colorMode: 3
m_fontColorGradient:
topLeft: {r: 1, g: 1, b: 1, a: 1}
topRight: {r: 1, g: 1, b: 1, a: 1}
bottomLeft: {r: 1, g: 1, b: 1, a: 1}
bottomRight: {r: 1, g: 1, b: 1, a: 1}
m_fontColorGradientPreset: {fileID: 0}
m_spriteAsset: {fileID: 0}
m_tintAllSprites: 0
m_StyleSheet: {fileID: 0}
m_TextStyleHashCode: -1183493901
m_overrideHtmlColors: 0
m_faceColor:
serializedVersion: 2
rgba: 4294967295
m_fontSize: 18
m_fontSizeBase: 22
m_fontWeight: 400
m_enableAutoSizing: 1
m_fontSizeMin: 18
m_fontSizeMax: 72
m_fontStyle: 0
m_HorizontalAlignment: 2
m_VerticalAlignment: 512
m_textAlignment: 65535
m_characterSpacing: 0
m_wordSpacing: 0
m_lineSpacing: 0
m_lineSpacingMax: 0
m_paragraphSpacing: 0
m_charWidthMaxAdj: 0
m_enableWordWrapping: 0
m_wordWrappingRatios: 0.4
m_overflowMode: 0
m_linkedTextComponent: {fileID: 0}
parentLinkedComponent: {fileID: 0}
m_enableKerning: 1
m_enableExtraPadding: 0
checkPaddingRequired: 0
m_isRichText: 1
m_parseCtrlCharacters: 1
m_isOrthographic: 1
m_isCullingEnabled: 0
m_horizontalMapping: 0
m_verticalMapping: 0
m_uvLineOffset: 0
m_geometrySortingOrder: 0
m_IsTextObjectScaleStatic: 0
m_VertexBufferAutoSizeReduction: 1
m_useMaxVisibleDescender: 1
m_pageToDisplay: 1
m_margin: {x: 0, y: 0, z: 0, w: 0}
m_isUsingLegacyAnimationComponent: 0
m_isVolumetricText: 0
m_hasFontAssetChanged: 0
m_baseMaterial: {fileID: 0}
m_maskOffset: {x: 0, y: 0, z: 0, w: 0}
--- !u!1 &3585409544634893643
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 8467790018694481767}
- component: {fileID: 6839476388405747010}
m_Layer: 5
m_Name: SwapConfirmationPanelNew
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 0
--- !u!224 &8467790018694481767
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3585409544634893643}
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 6284368815799428365}
- {fileID: 8966934417392808048}
- {fileID: 9018035827392313124}
m_Father: {fileID: 4684960432987786827}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 1, y: 1}
m_AnchoredPosition: {x: 0, y: 44.8}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!114 &6839476388405747010
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3585409544634893643}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 306cc8c2b49d7114eaa3623786fc2126, type: 3}
m_Name:
m_EditorClassIdentifier:
m_IgnoreLayout: 1
m_MinWidth: -1
m_MinHeight: -1
m_PreferredWidth: -1
m_PreferredHeight: -1
m_FlexibleWidth: -1
m_FlexibleHeight: -1
m_LayoutPriority: 1
--- !u!1 &4554001488283748877
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 8966934417392808048}
- component: {fileID: 2844404199525477580}
- component: {fileID: 7911038305113171221}
- component: {fileID: 7027835586965462475}
m_Layer: 5
m_Name: TickButton
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &8966934417392808048
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4554001488283748877}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 8467790018694481767}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0}
m_AnchorMax: {x: 0.5, y: 0}
m_AnchoredPosition: {x: -20, y: 0}
m_SizeDelta: {x: 27.375, y: 27.25}
m_Pivot: {x: 0.5, y: 0}
--- !u!222 &2844404199525477580
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4554001488283748877}
m_CullTransparentMesh: 1
--- !u!114 &7911038305113171221
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4554001488283748877}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 1065262782, guid: 730b0201dba9701479b075c3cc0c9d0c, type: 3}
m_Type: 0
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!114 &7027835586965462475
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4554001488283748877}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Navigation:
m_Mode: 3
m_WrapAround: 0
m_SelectOnUp: {fileID: 0}
m_SelectOnDown: {fileID: 0}
m_SelectOnLeft: {fileID: 0}
m_SelectOnRight: {fileID: 0}
m_Transition: 1
m_Colors:
m_NormalColor: {r: 1, g: 1, b: 1, a: 1}
m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1}
m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608}
m_ColorMultiplier: 1
m_FadeDuration: 0.1
m_SpriteState:
m_HighlightedSprite: {fileID: 0}
m_PressedSprite: {fileID: 0}
m_SelectedSprite: {fileID: 0}
m_DisabledSprite: {fileID: 0}
m_AnimationTriggers:
m_NormalTrigger: Normal
m_HighlightedTrigger: Highlighted
m_PressedTrigger: Pressed
m_SelectedTrigger: Selected
m_DisabledTrigger: Disabled
m_Interactable: 1
m_TargetGraphic: {fileID: 7911038305113171221}
m_OnClick:
m_PersistentCalls:
m_Calls:
- m_Target: {fileID: 2833502134534602906}
m_TargetAssemblyTypeName: SwapConfirmationPanel, Unity.BossRoom.Gameplay
m_MethodName: OnAcceptButtonPressed
m_Mode: 1
m_Arguments:
m_ObjectArgument: {fileID: 0}
m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine
m_IntArgument: 0
m_FloatArgument: 0
m_StringArgument:
m_BoolArgument: 0
m_CallState: 2
--- !u!1 &8235012725380876694
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 4684960432987786827}
- component: {fileID: 3288483462710877394}
- component: {fileID: 2833502134534602906}
m_Layer: 5
m_Name: SwapConfirmationPanelManager
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &4684960432987786827
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8235012725380876694}
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 8467790018694481767}
m_Father: {fileID: 7502187991751756120}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 1}
m_AnchorMax: {x: 0, y: 1}
m_AnchoredPosition: {x: 50, y: -20}
m_SizeDelta: {x: 100, y: 40}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!114 &3288483462710877394
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8235012725380876694}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 306cc8c2b49d7114eaa3623786fc2126, type: 3}
m_Name:
m_EditorClassIdentifier:
m_IgnoreLayout: 1
m_MinWidth: -1
m_MinHeight: -1
m_PreferredWidth: -1
m_PreferredHeight: -1
m_FlexibleWidth: -1
m_FlexibleHeight: -1
m_LayoutPriority: 1
--- !u!114 &2833502134534602906
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8235012725380876694}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: e799529efab1c9d4ab780bfd693439d1, type: 3}
m_Name:
m_EditorClassIdentifier:
confirmationPanel: {fileID: 3585409544634893643}
swapwithname: {fileID: 799420244153101338}
--- !u!1001 &1161329279327836704
PrefabInstance:
m_ObjectHideFlags: 0
serializedVersion: 2
m_Modification:
serializedVersion: 3
m_TransformParent: {fileID: 7502187991751756120}
m_Modifications:
- target: {fileID: 330850194307782490, guid: ef40e983a46e6194c83cdaa6aa2462d6, type: 3}
@ -183,6 +716,9 @@ PrefabInstance:
value: 0
objectReference: {fileID: 0}
m_RemovedComponents: []
m_RemovedGameObjects: []
m_AddedGameObjects: []
m_AddedComponents: []
m_SourcePrefab: {fileID: 100100000, guid: ef40e983a46e6194c83cdaa6aa2462d6, type: 3}
--- !u!224 &254771808888734010 stripped
RectTransform:
@ -205,12 +741,17 @@ PrefabInstance:
m_ObjectHideFlags: 0
serializedVersion: 2
m_Modification:
serializedVersion: 3
m_TransformParent: {fileID: 7502187991751756120}
m_Modifications:
- target: {fileID: 5566236674185336343, guid: bfbfd55622765a341a87916c843208ab, type: 3}
propertyPath: m_Name
value: UIName
objectReference: {fileID: 0}
- target: {fileID: 5566236674185336343, guid: bfbfd55622765a341a87916c843208ab, type: 3}
propertyPath: m_IsActive
value: 1
objectReference: {fileID: 0}
- target: {fileID: 7997572053438227093, guid: bfbfd55622765a341a87916c843208ab, type: 3}
propertyPath: m_Pivot.x
value: 0.5
@ -229,7 +770,7 @@ PrefabInstance:
objectReference: {fileID: 0}
- target: {fileID: 7997572053438227093, guid: bfbfd55622765a341a87916c843208ab, type: 3}
propertyPath: m_AnchorMax.y
value: 1
value: 0
objectReference: {fileID: 0}
- target: {fileID: 7997572053438227093, guid: bfbfd55622765a341a87916c843208ab, type: 3}
propertyPath: m_AnchorMin.x
@ -237,7 +778,7 @@ PrefabInstance:
objectReference: {fileID: 0}
- target: {fileID: 7997572053438227093, guid: bfbfd55622765a341a87916c843208ab, type: 3}
propertyPath: m_AnchorMin.y
value: 1
value: 0
objectReference: {fileID: 0}
- target: {fileID: 7997572053438227093, guid: bfbfd55622765a341a87916c843208ab, type: 3}
propertyPath: m_SizeDelta.x
@ -277,11 +818,11 @@ PrefabInstance:
objectReference: {fileID: 0}
- target: {fileID: 7997572053438227093, guid: bfbfd55622765a341a87916c843208ab, type: 3}
propertyPath: m_AnchoredPosition.x
value: 50
value: 0
objectReference: {fileID: 0}
- target: {fileID: 7997572053438227093, guid: bfbfd55622765a341a87916c843208ab, type: 3}
propertyPath: m_AnchoredPosition.y
value: 10
value: 0
objectReference: {fileID: 0}
- target: {fileID: 7997572053438227093, guid: bfbfd55622765a341a87916c843208ab, type: 3}
propertyPath: m_LocalEulerAnglesHint.x
@ -296,6 +837,9 @@ PrefabInstance:
value: 0
objectReference: {fileID: 0}
m_RemovedComponents: []
m_RemovedGameObjects: []
m_AddedGameObjects: []
m_AddedComponents: []
m_SourcePrefab: {fileID: 100100000, guid: bfbfd55622765a341a87916c843208ab, type: 3}
--- !u!224 &2113819744356243524 stripped
RectTransform:

@ -8597,11 +8597,11 @@ PrefabInstance:
objectReference: {fileID: 0}
- target: {fileID: 1676734515771252668, guid: 0193228de87741d40a42e561901c9083, type: 3}
propertyPath: m_LocalRotation.w
value: 0.85294455
value: 0.8529446
objectReference: {fileID: 0}
- target: {fileID: 1676734515771252668, guid: 0193228de87741d40a42e561901c9083, type: 3}
propertyPath: m_LocalRotation.x
value: 0.3943448
value: 0.39434478
objectReference: {fileID: 0}
- target: {fileID: 1676734515771252668, guid: 0193228de87741d40a42e561901c9083, type: 3}
propertyPath: m_LocalRotation.y
@ -8609,7 +8609,7 @@ PrefabInstance:
objectReference: {fileID: 0}
- target: {fileID: 1676734515771252668, guid: 0193228de87741d40a42e561901c9083, type: 3}
propertyPath: m_LocalRotation.z
value: -0.14352979
value: -0.14352977
objectReference: {fileID: 0}
- target: {fileID: 1676734516302391364, guid: 0193228de87741d40a42e561901c9083, type: 3}
propertyPath: m_UpdateMethod
@ -8758,15 +8758,15 @@ PrefabInstance:
objectReference: {fileID: 0}
- target: {fileID: 203267159508449512, guid: 36b3ee75677a1544191c0ddaaadd8140, type: 3}
propertyPath: m_LocalRotation.x
value: 0.39434484
value: 0.3943448
objectReference: {fileID: 0}
- target: {fileID: 203267159508449512, guid: 36b3ee75677a1544191c0ddaaadd8140, type: 3}
propertyPath: m_LocalRotation.y
value: 0.3104465
value: 0.31044644
objectReference: {fileID: 0}
- target: {fileID: 203267159508449512, guid: 36b3ee75677a1544191c0ddaaadd8140, type: 3}
propertyPath: m_LocalRotation.z
value: -0.1435298
value: -0.14352976
objectReference: {fileID: 0}
- target: {fileID: 203267159508449512, guid: 36b3ee75677a1544191c0ddaaadd8140, type: 3}
propertyPath: m_LocalEulerAnglesHint.x
@ -9221,7 +9221,7 @@ GameObject:
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
m_IsActive: 0
--- !u!114 &1486746209
MonoBehaviour:
m_ObjectHideFlags: 0

@ -4,6 +4,7 @@ using Unity.BossRoom.ConnectionManagement;
using Unity.BossRoom.Gameplay.Actions;
using Unity.BossRoom.Gameplay.Configuration;
using Unity.BossRoom.Gameplay.GameplayObjects.Character.AI;
using Unity.BossRoom.Gameplay.UI;
using Unity.Multiplayer.Samples.BossRoom;
using Unity.Netcode;
using UnityEngine;
@ -146,40 +147,56 @@ namespace Unity.BossRoom.Gameplay.GameplayObjects.Character
public bool IsOnAPlatform { get; private set; } = false;
public bool IsCrow { get; private set; } = false;
public UIStateDisplayHandler uIStateDisplayHandler;
void Awake()
{
m_ServerActionPlayer = new ServerActionPlayer(this);
NetLifeState = GetComponent<NetworkLifeState>();
NetHealthState = GetComponent<NetworkHealthState>();
m_State = GetComponent<NetworkAvatarGuidState>();
uIStateDisplayHandler= GetComponent<UIStateDisplayHandler>();
}
//Hazim
[Rpc(SendTo.Everyone)]
private void ShowSwapConfirmationPanelClientRpc()
private void ShowSwapConfirmationPanelClientRpc(string name)
{
if (NetworkManager.Singleton.LocalClientId == OwnerClientId)
{
// Show the confirmation panel for the specific player
var panel = FindObjectOfType<SwapConfirmationPanel>();
var uistate= uIStateDisplayHandler.m_UIState;
var panel = uistate.swapConfirmationPanel;
if (panel != null)
{
uistate.swapConfirmationPanel.swapwithname.text = "Swap with " + name;
panel.ShowPanel(this); // Pass the current ServerCharacter reference
}
else
{
Debug.LogError("SwapConfirmationPanel not found in the scene!");
}
//// Show the confirmation panel for the specific player
//var panel = FindObjectOfType<SwapConfirmationPanel>();
//if (panel != null)
//{
// panel.ShowPanel(this); // Pass the current ServerCharacter reference
//}
//else
//{
// Debug.LogError("SwapConfirmationPanel not found in the scene!");
//}
}
}
public void SetAsCrow(bool status)
{
IsCrow = status;
}
public void SetTargetPlatform(int platformId)
{
TargetPlatformId = platformId;
@ -200,12 +217,12 @@ namespace Unity.BossRoom.Gameplay.GameplayObjects.Character
{
SetOnPlatform(false);
}
public void SetOnPlatform(bool status)
{
IsOnAPlatform = status;
}
private void HandleOccupiedPlatform(Platform currentPlatform)
{
@ -239,15 +256,15 @@ namespace Unity.BossRoom.Gameplay.GameplayObjects.Character
}
[Rpc(SendTo.Server, RequireOwnership = false)]
public void NotifySwapRequestRpc(ulong initiatingPlayerId)
public void NotifySwapRequestRpc(ulong initiatingPlayerId,string name)
{
PendingSwapRequest = initiatingPlayerId;
// Notify all clients except the server, filtered by target
ShowSwapConfirmationPanelClientRpc();
ShowSwapConfirmationPanelClientRpc(name);
Debug.Log($"Swap request received from Player {initiatingPlayerId}. Waiting for confirmation.");
}
@ -295,7 +312,7 @@ namespace Unity.BossRoom.Gameplay.GameplayObjects.Character
}
//Hazim
public override void OnNetworkSpawn()
{
CrowManager.Instance.OnPlayerSpawned(this);

@ -5,10 +5,11 @@ using Unity.Multiplayer.Samples.BossRoom;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.UI;
using TMPro;
public class SwapConfirmationPanel : MonoBehaviour
{
[SerializeField] private GameObject confirmationPanel;
public TextMeshProUGUI swapwithname;
private ServerCharacter associatedCharacter; // Reference to the correct ServerCharacter instance
public void ShowPanel(ServerCharacter character)

@ -1,4 +1,5 @@
using System;
using Unity.BossRoom.Gameplay.GameplayObjects.Character;
using Unity.BossRoom.Utils;
using Unity.Netcode;
using UnityEngine;
@ -10,6 +11,8 @@ namespace Unity.BossRoom.Gameplay.UI
/// </summary>
public class UIStateDisplay : MonoBehaviour
{
public SwapConfirmationPanel swapConfirmationPanel;
public string playerName;
[SerializeField]
UIName m_UIName;
@ -20,6 +23,10 @@ namespace Unity.BossRoom.Gameplay.UI
{
m_UIName.gameObject.SetActive(true);
m_UIName.Initialize(networkedName);
playerName=networkedName.Value.ToString();
//var servercharacterName = GetComponentInParent<ServerCharacter>();
//servercharacterName.name = playerName;
swapConfirmationPanel.gameObject.name += networkedName.Value;
}
public void DisplayHealth(NetworkVariable<int> networkedHealth, int maxValue)

@ -29,7 +29,7 @@ namespace Unity.BossRoom.Gameplay.UI
UIStateDisplay m_UIStatePrefab;
// spawned in world (only one instance of this)
UIStateDisplay m_UIState;
public UIStateDisplay m_UIState;
RectTransform m_UIStateRectTransform;

@ -558,7 +558,7 @@ namespace Unity.BossRoom.Gameplay.UserInput
if (targetNetObj.TryGetComponent(out ServerCharacter targetCharacter))
{
// Initiate the swap
targetCharacter.NotifySwapRequestRpc(m_ServerCharacter.NetworkObjectId);
targetCharacter.NotifySwapRequestRpc(m_ServerCharacter.NetworkObjectId,m_ServerCharacter.uIStateDisplayHandler.m_UIState.playerName);
Debug.Log($"Swap request sent to {targetCharacter.name}.");
isCharacterClicked = true;
break; // Exit the loop after initiating the swap

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

@ -0,0 +1,158 @@
fileFormatVersion: 2
guid: 730b0201dba9701479b075c3cc0c9d0c
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 12
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 1
wrapV: 1
wrapW: 0
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 2
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites:
- serializedVersion: 2
name: tick
rect:
serializedVersion: 2
x: 31
y: 147
width: 219
height: 218
alignment: 0
pivot: {x: 0, y: 0}
border: {x: 0, y: 0, z: 0, w: 0}
outline: []
physicsShape: []
tessellationDetail: 0
bones: []
spriteID: cb9db3cf4f25a424db73d054f5083d70
internalID: 1065262782
vertices: []
indices:
edges: []
weights: []
- serializedVersion: 2
name: cross
rect:
serializedVersion: 2
x: 262
y: 147
width: 219
height: 218
alignment: 0
pivot: {x: 0, y: 0}
border: {x: 0, y: 0, z: 0, w: 0}
outline: []
physicsShape: []
tessellationDetail: 0
bones: []
spriteID: 570ede4f598fcfe44ab1b710195bcbd4
internalID: -187649311
vertices: []
indices:
edges: []
weights: []
outline: []
physicsShape: []
bones: []
spriteID: e9791250060e17a4db2bb0ae9ee6b852
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
nameFileIdTable:
cross: -187649311
tick: 1065262782
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:
Loading…
Cancel
Save