// ---------------------------------------------------------------------------- // fix missing reference // ---------------------------------------------------------------------------- public static FixResult FixMissingReference(Object unityObject, string propertyPath, RecordLocation location) { var so = new SerializedObject(unityObject); var sp = so.FindProperty(propertyPath); if (MissingReferenceDetector.IsPropertyHasMissingReference(sp)) { sp.objectReferenceInstanceIDValue = 0; var fileId = sp.FindPropertyRelative("m_FileID"); if (fileId != null) { fileId.intValue = 0; } // fixes dirty scene flag after batch issues fix // due to the additional undo action so.ApplyModifiedPropertiesWithoutUndo(); if (location == RecordLocation.Scene) { CSSceneTools.MarkSceneDirty(); } else { if (unityObject != null) { EditorUtility.SetDirty(unityObject); } } } return(new FixResult(true)); }
protected override bool PerformFix(bool batchMode) { Object obj = null; Component component = null; CSSceneTools.OpenSceneResult openSceneResult = null; if (!batchMode && Location == RecordLocation.Scene) { openSceneResult = CSSceneTools.OpenScene(Path); if (!openSceneResult.success) { return(false); } } obj = GetObjectWithThisIssue(); if (obj == null) { if (batchMode) { Debug.LogWarning(Maintainer.LogPrefix + "Can't find Object for issue:\n" + this); } else { MaintainerWindow.ShowNotification("Couldn't find Object " + transformPath); } return(false); } if (!string.IsNullOrEmpty(componentName) && obj is GameObject) { component = GetComponentWithThisIssue(obj as GameObject); if (component == null) { if (batchMode) { Debug.LogWarning(Maintainer.LogPrefix + "Can't find component for issue:\n" + this); } else { MaintainerWindow.ShowNotification("Can't find component " + componentName); } return(false); } } var fixResult = IssuesFixer.FixObjectIssue(this, obj, component, Kind); if (!batchMode && Location == RecordLocation.Scene && openSceneResult != null) { CSSceneTools.SaveScene(openSceneResult.scene); CSSceneTools.CloseOpenedSceneIfNeeded(openSceneResult); } return(fixResult); }
private static bool ProcessSelectedScenes(List <IssueRecord> issues) { bool result = true; currentPhase++; for (int i = 0; i < scenesCount; i++) { string scenePath = scenesPaths[i]; string sceneName = Path.GetFileNameWithoutExtension(scenePath); if (EditorUtility.DisplayCancelableProgressBar(string.Format(PROGRESS_CAPTION, currentPhase, phasesCount, i + 1, scenesCount), string.Format("Opening scene: " + Path.GetFileNameWithoutExtension(scenePath)), (float)i / scenesCount)) { result = false; break; } if (CSSceneTools.GetCurrentScenePath() != scenePath) { CSSceneTools.OpenScene(scenePath); } #if UNITY_5_3_PLUS // if we're scanning currently opened scene and going to scan more scenes, // we need to close all additional scenes to avoid duplicates else if (EditorSceneManager.loadedSceneCount > 1 && scenesCount > 1) { CSSceneTools.CloseAllScenesButActive(); } #endif GameObject[] gameObjects = CSEditorTools.GetAllSuitableGameObjectsInCurrentScene(); int objectsCount = gameObjects.Length; for (int j = 0; j < objectsCount; j++) { if (EditorUtility.DisplayCancelableProgressBar(string.Format(PROGRESS_CAPTION, currentPhase, phasesCount, i + 1, scenesCount), string.Format("Processing scene: {0} ... {1}%", sceneName, j * 100 / objectsCount), (float)i / scenesCount)) { result = false; break; } CheckObjectForIssues(issues, scenePath, gameObjects[j], true); } if (!result) { break; } } return(result); }
public void Show() { GameObject[] allObjects; if (location == RecordLocation.Scene) { if (CSSceneTools.GetCurrentScenePath() != path) { if (!CSSceneTools.SaveCurrentSceneIfUserWantsTo()) { return; } CSSceneTools.OpenScene(path); } allObjects = CSEditorTools.GetAllSuitableGameObjectsInCurrentScene(); CSEditorTools.PingObjectDelayed(AssetDatabase.LoadAssetAtPath(path, typeof(Object))); } else { List <GameObject> prefabs = new List <GameObject>(); CSEditorTools.GetAllSuitableGameObjectsInPrefabAssets(prefabs); allObjects = prefabs.ToArray(); } GameObject go = FindObjectInCollection(allObjects); if (go != null) { if (location == RecordLocation.Scene) { Selection.activeTransform = go.transform; } else { Selection.activeGameObject = go; if (gameObjectPath.Split('/').Length > 2) { CSEditorTools.PingObjectDelayed(AssetDatabase.LoadAssetAtPath(path, typeof(Object))); } } } else { MaintainerWindow.ShowNotification("Can't find object " + gameObjectPath); } }
private static bool ScanSceneFiles(List <CleanerRecord> results, bool showProgress = true) { bool canceled = false; currentPhase++; string[] scenesPaths = CSEditorTools.FindAssetsFiltered("t:Scene", MaintainerSettings.Cleaner.pathIgnores); int scenesCount = scenesPaths.Length; for (int i = 0; i < scenesCount; i++) { if (showProgress && EditorUtility.DisplayCancelableProgressBar(string.Format(PROGRESS_CAPTION, currentPhase, phasesCount, i + 1, scenesCount), "Scanning scene files...", (float)i / scenesCount)) { canceled = true; break; } string scenePath = scenesPaths[i]; if (CSSceneTools.GetCurrentScenePath() != scenePath) { CSSceneTools.OpenScene(scenePath); } #if UNITY_5_3_PLUS // if we're scanning currently opened scene and going to scan more scenes, // we need to close all additional scenes to avoid duplicates else if (EditorSceneManager.loadedSceneCount > 1 && scenesCount > 1) { CSSceneTools.CloseAllScenesButActive(); } #endif int objectsInScene = 0; GameObject[] gameObjects = CSEditorTools.GetAllSuitableGameObjectsInCurrentScene(); objectsInScene = gameObjects.Length; if (objectsInScene == 0) { results.Add(AssetRecord.Create(RecordType.EmptyScene, scenePath)); } } return(!canceled); }
private static void ProcessSceneForProjectLevelReferences(string path, List <TreeConjunction> conjunctions) { var openSceneResult = CSSceneTools.OpenScene(path); if (!openSceneResult.success) { Debug.LogWarning(Maintainer.ConstructWarning("Can't open scene " + path)); return; } SceneSettingsProcessor.Process(conjunctions); EntryFinder.currentLocation = Location.SceneGameObject; CSTraverseTools.TraverseSceneGameObjects(openSceneResult.scene, true, false, EntryFinder.OnGameObjectTraverse); CSSceneTools.CloseOpenedSceneIfNeeded(openSceneResult); }
private bool OpenNeededSceneIfNecessary(bool askForSave) { if (location == RecordLocation.Scene) { if (CSSceneTools.GetCurrentScenePath() != path) { if (askForSave && !CSSceneTools.SaveCurrentSceneIfUserWantsTo()) { return(false); } CSSceneTools.OpenScene(path); } } return(true); }
private static void ProcessScene() { var path = assetConjunctions.asset.Path; var openSceneResult = CSSceneTools.OpenScene(path); if (!openSceneResult.success) { Debug.LogWarning(Maintainer.ConstructWarning("Can't open scene " + path)); return; } SceneSettingsProcessor.Process(assetConjunctions.conjunctions); currentLocation = Location.SceneGameObject; CSTraverseTools.TraverseSceneGameObjects(openSceneResult.scene, true, OnGameObjectTraverse); CSSceneTools.CloseOpenedSceneIfNeeded(openSceneResult); }
private static void FinishSearch() { if (MaintainerSettings.Issues.lookInScenes) { if (string.IsNullOrEmpty(searchStartScene)) { if (MaintainerSettings.Issues.scenesSelection != IssuesFinderSettings.ScenesSelection.CurrentSceneOnly) { CSSceneTools.NewScene(); } } else if (CSSceneTools.GetCurrentScenePath() != searchStartScene) { EditorUtility.DisplayProgressBar("Opening initial scene", "Opening scene: " + Path.GetFileNameWithoutExtension(searchStartScene), 0); CSSceneTools.OpenScene(searchStartScene); } } EditorUtility.ClearProgressBar(); }
private Object GetObjectWithThisIssue() { Object result = null; if (Location == RecordLocation.Scene) { var scene = CSSceneTools.GetSceneByPath(Path); result = CSObjectTools.FindGameObjectInScene(scene, objectId, transformPath); } else { //var assetFile = AssetsMap.GetAssetInfoWithPath(path); var prefabRoot = CSPrefabTools.GetPrefabAssetRoot(Path); if (prefabRoot != null) { result = CSObjectTools.FindChildGameObjectRecursive(prefabRoot.transform, objectId, prefabRoot.transform.name, transformPath); } } return(result); }
protected override FixResult PerformFix(bool batchMode) { CSSceneTools.OpenSceneResult openSceneResult = null; if (!batchMode) { openSceneResult = CSSceneTools.OpenScene(Path); if (!openSceneResult.success) { return(FixResult.CreateError("Couldn't open scene")); } } FixResult result; var settingsObject = GetSettingsObjectWithThisIssue(); if (settingsObject == null) { result = new FixResult(false); if (batchMode) { Debug.LogWarning(Maintainer.LogPrefix + "Couldn't find " + SettingsKind + " object for issue:\n" + this); } else { result.SetErrorText("Couldn't find " + SettingsKind + " object at\n" + Path); } return(result); } result = IssuesFixer.FixMissingReference(settingsObject, PropertyPath, RecordLocation.Scene); if (!batchMode) { CSSceneTools.SaveScene(openSceneResult.scene); CSSceneTools.CloseOpenedSceneIfNeeded(openSceneResult); } return(result); }
private static void FillSettingsAssetDependencies(ref HashSet <string> dependenciesGUIDs, string assetPath, AssetSettingsKind settingsKind) { if (settingsKind == AssetSettingsKind.EditorBuildSettings) { var scenesInBuildGUIDs = CSSceneTools.GetScenesInBuildGUIDs(true); if (scenesInBuildGUIDs != null) { dependenciesGUIDs.UnionWith(scenesInBuildGUIDs); } } else { var settingsAsset = AssetDatabase.LoadAllAssetsAtPath(assetPath); if (settingsAsset != null && settingsAsset.Length > 0) { var settingsAssetSerialized = new SerializedObject(settingsAsset[0]); var sp = settingsAssetSerialized.GetIterator(); while (sp.Next(true)) { if (sp.propertyType == SerializedPropertyType.ObjectReference) { var instanceId = sp.objectReferenceInstanceIDValue; if (instanceId != 0) { var path = CSPathTools.EnforceSlashes(AssetDatabase.GetAssetPath(instanceId)); if (!string.IsNullOrEmpty(path) && path.StartsWith("Assets")) { var guid = AssetDatabase.AssetPathToGUID(path); if (!string.IsNullOrEmpty(guid)) { dependenciesGUIDs.Add(guid); } } } } } } } }
private static string[] GetAssetsReferencedInPlayerSettingsAsset(string assetPath, AssetSettingsKind settingsKind) { var referencedAssets = new List <string>(); if (settingsKind == AssetSettingsKind.EditorBuildSettings) { referencedAssets.AddRange(CSSceneTools.GetScenesInBuild(true)); } else { var settingsAsset = AssetDatabase.LoadAllAssetsAtPath(assetPath); if (settingsAsset != null && settingsAsset.Length > 0) { var settingsAssetSerialized = new SerializedObject(settingsAsset[0]); var sp = settingsAssetSerialized.GetIterator(); while (sp.Next(true)) { if (sp.propertyType == SerializedPropertyType.ObjectReference) { var instanceId = sp.objectReferenceInstanceIDValue; if (instanceId != 0) { var path = CSPathTools.EnforceSlashes(AssetDatabase.GetAssetPath(instanceId)); if (!string.IsNullOrEmpty(path) && path.StartsWith("Assets")) { if (referencedAssets.IndexOf(path) == -1) { referencedAssets.Add(path); } } } } } } } return(referencedAssets.ToArray()); }
// ---------------------------------------------------------------------------- // fix missing component // ---------------------------------------------------------------------------- private static void FixMissingComponents(GameObjectIssueRecord issue, GameObject go) { CSObjectTools.SelectGameObject(go, issue.location); ActiveEditorTracker tracker = CSEditorTools.GetActiveEditorTrackerForSelectedObject(); tracker.RebuildIfNecessary(); bool touched = false; Editor[] activeEditors = tracker.activeEditors; for (int i = activeEditors.Length - 1; i >= 0; i--) { Editor editor = activeEditors[i]; if (CSObjectTools.GetLocalIdentifierInFileForObject(editor.serializedObject.targetObject) == issue.componentId) { Object.DestroyImmediate(editor.target, true); touched = true; } } if (touched) { #if UNITY_5_0_PLUS if (issue.location == RecordLocation.Scene) { CSSceneTools.MarkSceneDirty(); } else { EditorUtility.SetDirty(go); } #else EditorUtility.SetDirty(go); #endif } //CSObjectTools.SelectGameObject(null, issue.location); }
protected override bool PerformFix(bool batchMode) { CSSceneTools.OpenSceneResult openSceneResult = null; if (!batchMode) { openSceneResult = CSSceneTools.OpenScene(Path); if (!openSceneResult.success) { return(false); } } var settingsObject = GetSettingsObjectWithThisIssue(); if (settingsObject == null) { if (batchMode) { Debug.LogWarning(Maintainer.LogPrefix + "Couldn't find " + SettingsKind + " object for issue:\n" + this); } else { MaintainerWindow.ShowNotification("Couldn't find " + SettingsKind + " object at " + Path); } return(false); } var fixResult = IssuesFixer.FixMissingReference(settingsObject, PropertyPath, RecordLocation.Scene); if (!batchMode) { CSSceneTools.SaveScene(openSceneResult.scene); CSSceneTools.CloseOpenedSceneIfNeeded(openSceneResult); } return(fixResult); }
private static void ProcessScene(AssetInfo asset, string assetName, int sceneIndex, int totalScenes) { currentObjectIndex = 0; itemIndex = sceneIndex; totalItems = totalScenes; currentAssetName = assetName; var openSceneResult = CSSceneTools.OpenScene(asset.Path); if (!openSceneResult.success) { Debug.LogWarning(Maintainer.ConstructWarning("Can't open scene " + asset.Path)); return; } var skipCleanPrefabInstances = ProjectSettings.Issues.scanGameObjects && ProjectSettings.Issues.lookInAssets; IssuesDetector.SceneStart(asset); CSTraverseTools.TraverseSceneGameObjects(openSceneResult.scene, skipCleanPrefabInstances, false, OnGameObjectTraverse); IssuesDetector.SceneEnd(asset); CSSceneTools.CloseOpenedSceneIfNeeded(openSceneResult); }
// ---------------------------------------------------------------------------- // fix missing reference // ---------------------------------------------------------------------------- private static bool FixMissingReference(GameObjectIssueRecord issue, Component component) { SerializedObject so = new SerializedObject(component); SerializedProperty sp = so.FindProperty(issue.propertyPath); if (sp.propertyType == SerializedPropertyType.ObjectReference) { if (sp.objectReferenceValue == null && sp.objectReferenceInstanceIDValue != 0) { sp.objectReferenceInstanceIDValue = 0; #if UNITY_5_2_PLUS // fixes dirty scene flag after batch issues fix // due to the additional undo action so.ApplyModifiedPropertiesWithoutUndo(); #else so.ApplyModifiedProperties(); #endif #if UNITY_5_0_PLUS if (issue.location == RecordLocation.Scene) { CSSceneTools.MarkSceneDirty(); } else { EditorUtility.SetDirty(component); } #else EditorUtility.SetDirty(component); #endif } } return(true); }
/// <summary> /// Starts search with current settings. /// </summary> /// <param name="showResults">Shows results in the %Maintainer window if true.</param> /// <returns>Array of IssueRecords in case you wish to manually iterate over them and make custom report.</returns> public static IssueRecord[] StartSearch(bool showResults) { if (!ProjectSettings.Issues.lookInScenes && !ProjectSettings.Issues.lookInAssets && !ProjectSettings.Issues.lookInProjectSettings) { MaintainerWindow.ShowNotification("Nowhere to search!"); return(null); } if (ProjectSettings.Issues.lookInScenes) { if (!CSSceneTools.SaveCurrentModifiedScenes(false)) { Debug.Log(Maintainer.LogPrefix + "Issues search canceled by user!"); return(null); } } var issues = new List <IssueRecord>(); PrepareToBatchOperation(); try { var sw = Stopwatch.StartNew(); CSTraverseTools.ClearStats(); var targetAssets = TargetCollector.CollectTargetAssets(); /*foreach (var targetAsset in targetAssets) * { * Debug.Log(targetAsset.Path); * }*/ TargetProcessor.SetIssuesList(issues); TargetProcessor.ProcessTargetAssets(targetAssets); var traverseStats = CSTraverseTools.GetStats(); var checkedAssets = targetAssets.Length; sw.Stop(); if (!operationCanceled) { var result = string.Format(CultureInfo.InvariantCulture, Maintainer.LogPrefix + ModuleName + " found issues: {0}\n" + "Seconds: {1:0.000}; Assets: {2}; Game Objects: {3}; Components: {4}; Properties: {5}", issues.Count, sw.Elapsed.TotalSeconds, checkedAssets, traverseStats.gameObjectsTraversed, traverseStats.componentsTraversed, traverseStats.propertiesTraversed); Debug.Log(result); } else { Debug.Log(Maintainer.LogPrefix + "Search canceled by user!"); } SearchResultsStorage.IssuesSearchResults = issues.ToArray(); if (showResults) { MaintainerWindow.ShowIssues(); } } catch (Exception e) { Debug.LogError(Maintainer.LogPrefix + ModuleName + ": something went wrong :(\n" + e); } EditorUtility.ClearProgressBar(); return(issues.ToArray()); }
/// <summary> /// Starts fix of the issues found with StartSearch() method. /// </summary> /// <param name="recordsToFix">Pass records you wish to fix here or leave null to let it load last search results.</param> /// <param name="showResults">Shows results in the %Maintainer window if true.</param> /// <param name="showConfirmation">Shows confirmation dialog before performing fix if true.</param> /// <returns>Array of IssueRecords which were fixed up.</returns> public static IssueRecord[] StartFix(IssueRecord[] recordsToFix = null, bool showResults = true, bool showConfirmation = true) { var records = recordsToFix; if (records == null) { records = SearchResultsStorage.IssuesSearchResults; } if (records.Length == 0) { Debug.Log(Maintainer.LogPrefix + "Nothing to fix!"); return(null); } recordsToFixCount = 0; foreach (var record in records) { if (record.selected) { recordsToFixCount++; } } if (recordsToFixCount == 0) { EditorUtility.DisplayDialog(ModuleName, "Please select issues to fix!", "Ok"); return(null); } if (!CSSceneTools.SaveCurrentModifiedScenes(false)) { Debug.Log(Maintainer.LogPrefix + "Issues batch fix canceled by user!"); return(null); } if (showConfirmation && !EditorUtility.DisplayDialog("Confirmation", "Do you really wish to let Maintainer automatically fix " + recordsToFixCount + " issues?\n" + Maintainer.DataLossWarning, "Go for it!", "Cancel")) { return(null); } var fixedRecords = new List <IssueRecord>(records.Length); var notFixedRecords = new List <IssueRecord>(records.Length); PrepareToBatchOperation(); try { var sw = Stopwatch.StartNew(); lastOpenSceneResult = null; CSEditorTools.lastRevealSceneOpenResult = null; IssuesFixer.FixRecords(records); foreach (var record in records) { if (record.fixResult != null && record.fixResult.Success) { fixedRecords.Add(record); } else { notFixedRecords.Add(record); } } records = notFixedRecords.ToArray(); sw.Stop(); if (!operationCanceled) { var results = fixedRecords.Count + " issues fixed in " + sw.Elapsed.TotalSeconds.ToString("0.000") + " seconds"; Debug.Log(Maintainer.LogPrefix + ModuleName + " results: " + results); MaintainerWindow.ShowNotification(results); } else { Debug.Log(Maintainer.LogPrefix + "Fix canceled by user!"); } if (lastOpenSceneResult != null) { CSSceneTools.SaveScene(lastOpenSceneResult.scene); CSSceneTools.CloseOpenedSceneIfNeeded(lastOpenSceneResult); lastOpenSceneResult = null; } SearchResultsStorage.IssuesSearchResults = records; if (showResults) { MaintainerWindow.ShowIssues(); } } catch (Exception e) { Debug.LogError(Maintainer.LogPrefix + ModuleName + ": something went wrong :(\n" + e); } EditorUtility.ClearProgressBar(); return(fixedRecords.ToArray()); }
public static void FixRecords(IssueRecord[] results, bool showProgress = true) { var i = 0; var count = results.Length; var sortedRecords = results.OrderBy(RecordsSortings.issueRecordByPath).ToArray(); var updateStep = Math.Max(count / ProjectSettings.UpdateProgressStep, 1); for (var k = 0; k < count; k++) { var item = sortedRecords[k]; if (showProgress) { if (k % updateStep == 0) { if (IssuesFinder.ShowProgressBar(1, 1, i, count, "Resolving selected issues...")) { IssuesFinder.operationCanceled = true; break; } } } if (item.selected && item.IsFixable) { if (item.Location == RecordLocation.Scene) { var assetIssue = item as AssetIssueRecord; if (assetIssue != null) { var newOpenSceneResult = CSSceneTools.OpenScene(assetIssue.Path); if (!newOpenSceneResult.success) { continue; } if (newOpenSceneResult.sceneWasLoaded) { if (IssuesFinder.lastOpenSceneResult != null) { CSSceneTools.SaveScene(IssuesFinder.lastOpenSceneResult.scene); CSSceneTools.CloseOpenedSceneIfNeeded(IssuesFinder.lastOpenSceneResult); } } if (IssuesFinder.lastOpenSceneResult == null || IssuesFinder.lastOpenSceneResult.scene != newOpenSceneResult.scene) { IssuesFinder.lastOpenSceneResult = newOpenSceneResult; } } } item.Fix(true); i++; } } AssetDatabase.SaveAssets(); AssetDatabase.Refresh(); }
// ---------------------------------------------------------------------------- // fix missing component // ---------------------------------------------------------------------------- private static bool FixMissingComponents(GameObjectIssueRecord issue, GameObject go, bool alternative) { var touched = false; #if UNITY_2019_1_OR_NEWER var removedCount = GameObjectUtility.RemoveMonoBehavioursWithMissingScript(go); if (removedCount > 0) { touched = true; } #else if (!alternative) { CSObjectTools.SelectGameObject(go, issue.Location == RecordLocation.Scene); } var tracker = CSEditorTools.GetActiveEditorTrackerForSelectedObject(); if (tracker == null) { Debug.LogError(Maintainer.ConstructError("Can't get active tracker.")); return(false); } tracker.RebuildIfNecessary(); var activeEditors = tracker.activeEditors; for (var i = activeEditors.Length - 1; i >= 0; i--) { var editor = activeEditors[i]; if (editor.serializedObject.targetObject == null) { Object.DestroyImmediate(editor.target, true); touched = true; } } if (alternative) { return(touched); } if (!touched) { // missing script could be hidden with hide flags, so let's try select it directly and repeat var serializedObject = new SerializedObject(go); var componentsArray = serializedObject.FindProperty("m_Component"); if (componentsArray != null) { for (var i = componentsArray.arraySize - 1; i >= 0; i--) { var componentPair = componentsArray.GetArrayElementAtIndex(i); var nestedComponent = componentPair.FindPropertyRelative("component"); if (nestedComponent != null) { if (MissingReferenceDetector.IsPropertyHasMissingReference(nestedComponent)) { var instanceId = nestedComponent.objectReferenceInstanceIDValue; if (instanceId == 0) { var fileId = nestedComponent.FindPropertyRelative("m_FileID"); if (fileId != null) { instanceId = fileId.intValue; } } Selection.instanceIDs = new [] { instanceId }; touched |= FixMissingComponents(issue, go, true); } } else { Debug.LogError(Maintainer.LogPrefix + "Couldn't find component in component pair!"); break; } } if (touched) { CSObjectTools.SelectGameObject(go, issue.Location == RecordLocation.Scene); } } else { Debug.LogError(Maintainer.LogPrefix + "Couldn't find components array!"); } } #endif if (touched) { if (issue.Location == RecordLocation.Scene) { CSSceneTools.MarkSceneDirty(); } else { EditorUtility.SetDirty(go); } } return(touched); }
private static bool LookForReferences(FilterItem[] selectedAssets, List <ReferencesTreeElement> results) { var canceled = !CSSceneTools.SaveCurrentModifiedScenes(false); if (!canceled) { var map = AssetsMap.GetUpdated(); if (map == null) { return(true); } var count = map.assets.Count; var updateStep = Math.Max(count / MaintainerSettings.UpdateProgressStep, 1); var root = new ReferencesTreeElement { id = results.Count, name = "root", depth = -1 }; results.Add(root); for (var i = 0; i < count; i++) { if (i % updateStep == 0 && EditorUtility.DisplayCancelableProgressBar( string.Format(ProgressCaption, 1, PhasesCount), string.Format(ProgressText, "Building references tree", i + 1, count), (float)i / count)) { canceled = true; break; } var assetInfo = map.assets[i]; // excludes settings assets from the list depth 0 items if (assetInfo.Kind == AssetKind.Settings) { continue; } // excludes all assets except selected ones from the list depth 0 items, if any was selected if (selectedAssets != null) { if (!CSFilterTools.IsValueMatchesAnyFilter(assetInfo.Path, selectedAssets)) { continue; } } if (MaintainerSettings.References.pathIncludesFilters != null && MaintainerSettings.References.pathIncludesFilters.Length > 0) { // excludes all root assets except included ones if (!CSFilterTools.IsValueMatchesAnyFilter(assetInfo.Path, MaintainerSettings.References.pathIncludesFilters)) { continue; } } // excludes ignored root asset if (CSFilterTools.IsValueMatchesAnyFilter(assetInfo.Path, MaintainerSettings.References.pathIgnoresFilters)) { continue; } var branchElements = new List <ReferencesTreeElement>(); TreeBuilder.BuildTreeBranch(assetInfo, 0, results.Count, branchElements); results.AddRange(branchElements); } } if (!canceled) { canceled = ReferenceEntryFinder.FillReferenceEntries(); } if (!canceled) { AssetsMap.Save(); } if (canceled) { ReferencesTab.AutoShowExistsNotification = false; ReferencesTab.AutoSelectPath = null; } return(canceled); }
/// <summary> /// Starts garbage search with current settings. /// </summary> /// <param name="showResults">Shows results in %Maintainer window if true.</param> /// <returns>Array of CleanerRecords in case you wish to manually iterate over them and make custom report.</returns> public static CleanerRecord[] StartSearch(bool showResults) { var results = new List <CleanerRecord>(); phasesCount = 0; currentPhase = 0; if (MaintainerSettings.Cleaner.findEmptyFolders) { phasesCount++; } if (MaintainerSettings.Cleaner.findUnreferencedAssets) { phasesCount++; } var searchCanceled = !CSSceneTools.SaveCurrentModifiedScenes(true); if (searchCanceled) { Debug.Log(Maintainer.LogPrefix + "Search canceled by user!"); return(null); } AssetDatabase.SaveAssets(); AssetDatabase.Refresh(ImportAssetOptions.ForceSynchronousImport); try { var sw = System.Diagnostics.Stopwatch.StartNew(); CSEditorTools.lastRevealSceneOpenResult = null; if (MaintainerSettings.Cleaner.findEmptyFolders) { searchCanceled = ScanFolders(results); } if (!searchCanceled && MaintainerSettings.Cleaner.findUnreferencedAssets) { searchCanceled = ScanProjectFiles(results); } sw.Stop(); EditorUtility.ClearProgressBar(); if (!searchCanceled) { Debug.Log(Maintainer.LogPrefix + ModuleName + " results: " + results.Count + " items found in " + sw.Elapsed.TotalSeconds.ToString("0.000") + " seconds."); } else { Debug.Log(Maintainer.LogPrefix + "Search canceled by user!"); } } catch (Exception e) { Debug.Log(Maintainer.LogPrefix + e); EditorUtility.ClearProgressBar(); } SearchResultsStorage.CleanerSearchResults = results.ToArray(); if (showResults) { MaintainerWindow.ShowCleaner(); } return(results.ToArray()); }
/// <summary> /// Starts garbage search with current settings. /// </summary> /// <param name="showResults">Shows results in %Maintainer window if true.</param> /// <returns>Array of CleanerRecords in case you wish to manually iterate over them and make custom report.</returns> public static CleanerRecord[] StartSearch(bool showResults) { List <CleanerRecord> results = new List <CleanerRecord>(); phasesCount = 0; currentPhase = 0; if (MaintainerSettings.Cleaner.findEmptyFolders) { phasesCount++; } if (MaintainerSettings.Cleaner.findEmptyScenes) { if (!CSSceneTools.SaveCurrentSceneIfUserWantsTo()) { Debug.Log(Maintainer.LOG_PREFIX + "Search canceled by user!"); return(null); } phasesCount++; searchStartScene = CSSceneTools.GetCurrentScenePath(true); } Stopwatch sw = Stopwatch.StartNew(); bool searchCanceled = false; if (MaintainerSettings.Cleaner.findEmptyFolders) { searchCanceled = !ScanFolders(results); } if (MaintainerSettings.Cleaner.findEmptyScenes) { searchCanceled = !ScanSceneFiles(results); } sw.Stop(); // opening scene where we started scan if (MaintainerSettings.Cleaner.findEmptyScenes) { if (string.IsNullOrEmpty(searchStartScene)) { CSSceneTools.NewScene(); } else if (CSSceneTools.GetCurrentScenePath() != searchStartScene) { CSSceneTools.OpenScene(searchStartScene); } } EditorUtility.ClearProgressBar(); if (!searchCanceled) { Debug.Log(Maintainer.LOG_PREFIX + MODULE_NAME + " results: " + results.Count + " items found in " + sw.Elapsed.TotalSeconds.ToString("0.000") + " seconds."); } else { Debug.Log(Maintainer.LOG_PREFIX + "Search canceled by user!"); } SearchResultsStorage.CleanerSearchResults = results.ToArray(); if (showResults) { MaintainerWindow.ShowCleaner(); } return(results.ToArray()); }
internal override FixResult PerformFix(bool batchMode) { Component component = null; FixResult result; CSSceneTools.OpenSceneResult openSceneResult = null; if (!batchMode && Location == RecordLocation.Scene) { openSceneResult = CSSceneTools.OpenScene(Path); if (!openSceneResult.success) { return(FixResult.CreateError("Couldn't open scene")); } } var obj = GetObjectWithThisIssue(); if (obj == null) { result = new FixResult(false); if (batchMode) { Debug.LogWarning(Maintainer.LogPrefix + "Can't find Object for issue:\n" + this); } else { result.SetErrorText("Couldn't find Object\n" + transformPath); } return(result); } if (!string.IsNullOrEmpty(componentName) && obj is GameObject) { component = GetComponentWithThisIssue(obj as GameObject); if (component == null) { result = new FixResult(false); if (batchMode) { Debug.LogWarning(Maintainer.LogPrefix + "Can't find component for issue:\n" + this); } else { result.SetErrorText("Can't find component\n" + componentName); } return(result); } } result = IssuesFixer.FixObjectIssue(this, obj, component, Kind); if (!batchMode && Location == RecordLocation.Scene && openSceneResult != null) { CSSceneTools.SaveScene(openSceneResult.scene); CSSceneTools.CloseOpenedSceneIfNeeded(openSceneResult); } return(result); }
private static void ShowItem(ExactReferencesListItem <T> item) { var assetPath = item.data.assetPath; var referencingEntry = item.data.entry; if (referencingEntry.location == Location.SceneLightingSettings || referencingEntry.location == Location.SceneNavigationSettings) { var sceneOpenResult = CSSceneTools.OpenSceneWithSavePrompt(assetPath); if (!sceneOpenResult.success) { Debug.LogError(Maintainer.ConstructError("Can't open scene " + assetPath)); MaintainerWindow.ShowNotification("Can't show it properly"); return; } } switch (referencingEntry.location) { case Location.ScriptAsset: case Location.ScriptableObjectAsset: if (!CSSelectionTools.RevealAndSelectFileAsset(assetPath)) { MaintainerWindow.ShowNotification("Can't show it properly"); } break; case Location.PrefabAssetObject: if (!CSSelectionTools.RevealAndSelectSubAsset(assetPath, referencingEntry.transformPath, referencingEntry.objectId)) { MaintainerWindow.ShowNotification("Can't show it properly"); } break; case Location.PrefabAssetGameObject: case Location.SceneGameObject: if (!CSSelectionTools.RevealAndSelectGameObject(assetPath, referencingEntry.transformPath, referencingEntry.objectId, referencingEntry.componentId)) { MaintainerWindow.ShowNotification("Can't show it properly"); } break; case Location.SceneLightingSettings: if (!CSMenuTools.ShowSceneSettingsLighting()) { Debug.LogError(Maintainer.ConstructError("Can't open Lighting settings!")); MaintainerWindow.ShowNotification("Can't show it properly"); } break; case Location.SceneNavigationSettings: if (!CSMenuTools.ShowSceneSettingsNavigation()) { Debug.LogError(Maintainer.ConstructError("Can't open Navigation settings!")); MaintainerWindow.ShowNotification("Can't show it properly"); } break; case Location.NotFound: case Location.Invisible: break; case Location.TileMap: if (!CSSelectionTools.RevealAndSelectGameObject(assetPath, referencingEntry.transformPath, referencingEntry.objectId, referencingEntry.componentId)) { MaintainerWindow.ShowNotification("Can't show it properly"); } // TODO: open tile map editor window? break; default: throw new ArgumentOutOfRangeException(); } }
public void Draw() { using (new GUILayout.HorizontalScope()) { /* logo */ using (new GUILayout.VerticalScope(UIHelpers.panelWithBackground, GUILayout.ExpandHeight(true), GUILayout.ExpandWidth(true))) { GUILayout.FlexibleSpace(); using (new GUILayout.HorizontalScope()) { GUILayout.FlexibleSpace(); var logo = CSImages.Logo; if (logo != null) { logo.wrapMode = TextureWrapMode.Clamp; var logoRect = EditorGUILayout.GetControlRect(GUILayout.Width(logo.width), GUILayout.Height(logo.height)); GUI.DrawTexture(logoRect, logo); GUILayout.Space(5); } GUILayout.FlexibleSpace(); } GUILayout.FlexibleSpace(); } /* buttons and stuff */ using (new GUILayout.VerticalScope(UIHelpers.panelWithBackground, GUILayout.ExpandHeight(true), GUILayout.ExpandWidth(true))) { GUILayout.Space(10); GUILayout.Label("<size=18>Maintainer v.<b>" + Maintainer.Version + "</b></size>", UIHelpers.centeredLabel); GUILayout.Space(5); GUILayout.Label("Developed by Dmitriy Yukhanov\n" + "Logo by Daniele Giardini\n" + "Icons by Google, Austin Andrews, Cody", UIHelpers.centeredLabel); GUILayout.Space(10); UIHelpers.Separator(); GUILayout.Space(5); if (UIHelpers.ImageButton("Homepage", CSIcons.Home)) { Application.OpenURL(Homepage); } GUILayout.Space(5); if (UIHelpers.ImageButton("Support contacts", CSIcons.Support)) { Application.OpenURL(SupportLink); } GUILayout.Space(5); if (UIHelpers.ImageButton("Full changelog (online)", CSIcons.Log)) { Application.OpenURL(ChangelogLink); } GUILayout.Space(5); //GUILayout.Space(10); //GUILayout.Label("Asset Store links", UIHelpers.centeredLabel); UIHelpers.Separator(); GUILayout.Space(5); if (UIHelpers.ImageButton("Plugin at Unity Asset Store", "Hold CTRL / CMD to open in built-in Asset Store browser.", CSIcons.AssetStore)) { if (!Event.current.control) { Application.OpenURL(UasLink); } else { UnityEditorInternal.AssetStore.Open(UasLinkShort); } } GUILayout.Label("It's really important to know your opinion,\n rates & reviews are <b>greatly appreciated!</b>", UIHelpers.centeredLabel); GUILayout.Space(5); if (UIHelpers.ImageButton("My profile at Unity Asset Store", CSIcons.Publisher)) { Application.OpenURL(UasProfileLink); } GUILayout.Label("Check all my plugins!", UIHelpers.centeredLabel); #if UNITY_2018_3_OR_NEWER if (Event.current.isKey && Event.current.type == EventType.KeyDown && Event.current.control && Event.current.keyCode == KeyCode.D) #else if (Event.current.isKey && Event.current.control && Event.current.keyCode == KeyCode.D) #endif { showDebug = !showDebug; Event.current.Use(); } if (showDebug) { GUILayout.Space(5); UIHelpers.Separator(); GUILayout.Space(5); GUILayout.Label("Welcome to secret debug mode =D"); if (GUILayout.Button("Remove Assets Map")) { AssetsMap.Delete(); } if (GUILayout.Button("Measure Assets Map build time")) { var sw = Stopwatch.StartNew(); AssetsMap.CreateNew(); sw.Stop(); Debug.Log("Asset Map build took " + sw.Elapsed.TotalSeconds.ToString("0.000", CultureInfo.InvariantCulture) + " seconds"); } if (GUILayout.Button("Remove Settings and Close")) { window.Close(); MaintainerSettings.Delete(); } if (GUILayout.Button("Re-save all scenes in project")) { CSSceneTools.ReSaveAllScenes(); } } } } }
private static bool LookForAssetsReferences(FilterItem[] selectedAssets, List <ProjectReferenceItem> results) { var canceled = !CSSceneTools.SaveCurrentModifiedScenes(false); if (!canceled) { var map = AssetsMap.GetUpdated(); if (map == null) { return(true); } var count = map.assets.Count; #if !UNITY_2020_1_OR_NEWER var updateStep = Math.Max(count / ProjectSettings.UpdateProgressStep, 1); #endif var root = new ProjectReferenceItem { id = results.Count, name = "root", depth = -1 }; results.Add(root); for (var i = 0; i < count; i++) { if ( #if !UNITY_2020_1_OR_NEWER i % updateStep == 0 && #endif EditorUtility.DisplayCancelableProgressBar( string.Format(ReferencesFinder.ProgressCaption, 1, ReferencesFinder.PhasesCount), string.Format(ReferencesFinder.ProgressText, "Building references tree", i + 1, count), (float)i / count)) { canceled = true; break; } var assetInfo = map.assets[i]; // excludes settings assets from the list depth 0 items if (assetInfo.Kind == AssetKind.Settings) { continue; } // excludes all assets except selected ones from the list depth 0 items, if any was selected if (selectedAssets != null) { if (!CSFilterTools.IsValueMatchesAnyFilter(assetInfo.Path, selectedAssets)) { continue; } } if (ProjectSettings.References.pathIncludesFilters != null && ProjectSettings.References.pathIncludesFilters.Length > 0) { // excludes all root assets except included ones if (!CSFilterTools.IsValueMatchesAnyFilter(assetInfo.Path, ProjectSettings.References.pathIncludesFilters)) { continue; } } // excludes ignored root asset if (CSFilterTools.IsValueMatchesAnyFilter(assetInfo.Path, ProjectSettings.References.pathIgnoresFilters)) { continue; } var branchElements = new List <ProjectReferenceItem>(); ProjectScopeReferencesTreeBuilder.BuildTreeBranch(assetInfo, 0, results.Count, ConjunctionInfoList, branchElements); results.AddRange(branchElements); } } if (!canceled) { canceled = ProjectEntryFinder.FillProjectScopeReferenceEntries(ConjunctionInfoList, TryAddEntryToMatchedConjunctions); } // TODO: remove this work-around when this bug will be fixed: // https://issuetracker.unity3d.com/issues/assets-used-in-components-of-a-nested-prefab-are-counted-as-direct-dependencies-of-all-higher-level-nested-prefabs for (var i = results.Count - 1; i >= 0; i--) { var result = results[i]; var resultEntries = result.referencingEntries; if (resultEntries == null || resultEntries.Length == 0) { continue; } foreach (var referencingEntry in resultEntries) { if (referencingEntry.Location == Location.NotFound && result.assetTypeName == "GameObject") { results.Remove(result); break; } } } if (!canceled) { AssetsMap.Save(); } if (canceled) { ProjectReferencesTab.AutoSelectPath = null; } return(canceled); }
internal static AssetInfo[] CollectTargetAssets() { var map = AssetsMap.GetUpdated(); if (map == null) { Debug.LogError(Maintainer.LogPrefix + "Can't get updated assets map!"); return(null); } EditorUtility.DisplayProgressBar(IssuesFinder.ModuleName, "Collecting input data...", 0); var supportedKinds = new List <AssetKind> { AssetKind.Regular, AssetKind.Settings }; var assets = CSFilterTools.GetAssetInfosWithKinds(map.assets, supportedKinds); var result = new HashSet <AssetInfo>(); try { var targetAssetTypes = new List <TypeFilter>(); if (MaintainerSettings.Issues.lookInScenes) { switch (MaintainerSettings.Issues.scenesSelection) { case IssuesFinderSettings.ScenesSelection.AllScenes: { targetAssetTypes.Add(new TypeFilter(CSReflectionTools.sceneAssetType)); break; } case IssuesFinderSettings.ScenesSelection.IncludedScenes: { if (MaintainerSettings.Issues.includeScenesInBuild) { var paths = CSSceneTools.GetScenesInBuild(!MaintainerSettings.Issues.includeOnlyEnabledScenesInBuild); result.UnionWith(CSFilterTools.GetAssetInfosWithPaths(assets, paths)); } var assetInfos = CSFilterTools.FilterAssetInfos(assets, MaintainerSettings.Issues.sceneIncludesFilters); result.UnionWith(assetInfos); break; } case IssuesFinderSettings.ScenesSelection.OpenedScenesOnly: { var paths = CSSceneTools.GetScenesSetup().Select(s => s.path).ToArray(); result.UnionWith(CSFilterTools.GetAssetInfosWithPaths(assets, paths)); break; } default: throw new ArgumentOutOfRangeException(); } } if (MaintainerSettings.Issues.lookInAssets) { targetAssetTypes.Add(new TypeFilter(CSReflectionTools.scriptableObjectType, true)); targetAssetTypes.Add(new TypeFilter(null)); #if UNITY_2019_1_OR_NEWER targetAssetTypes.Add(new TypeFilter(CSReflectionTools.shaderType)); #endif if (MaintainerSettings.Issues.scanGameObjects) { targetAssetTypes.Add(new TypeFilter(CSReflectionTools.gameObjectType)); } } var filtered = CSFilterTools.FilterAssetInfos( assets, targetAssetTypes, MaintainerSettings.Issues.pathIncludesFilters, MaintainerSettings.Issues.pathIgnoresFilters ); result.UnionWith(filtered); if (MaintainerSettings.Issues.lookInProjectSettings) { result.UnionWith(CSFilterTools.GetAssetInfosWithKind(assets, AssetKind.Settings)); } } catch (Exception e) { Console.WriteLine(e); throw; } var resultArray = new AssetInfo[result.Count]; result.CopyTo(resultArray); return(resultArray); }
private static bool ScanProjectFiles(ICollection <CleanerRecord> results, bool showProgress = true) { currentPhase++; var ignoredScenes = new List <string>(); if (MaintainerSettings.Cleaner.ignoreScenesInBuild) { ignoredScenes.AddRange(CSSceneTools.GetScenesInBuild(!MaintainerSettings.Cleaner.ignoreOnlyEnabledScenesInBuild)); } foreach (var scene in MaintainerSettings.Cleaner.sceneIgnoresFilters) { if (ignoredScenes.IndexOf(scene.value) == -1) { ignoredScenes.Add(scene.value); } } CheckScenesForExistence(results, ignoredScenes); if (ignoredScenes.Count == 0) { results.Add(CleanerErrorRecord.Create("Please tell me what scenes you wish to keep.\n" + "Add them to the build settings and / or configure manually\n" + "at the Manage Filters > Scenes Ignores tab.")); return(false); } var map = AssetsMap.GetUpdated(); if (map == null) { results.Add(CleanerErrorRecord.Create("Can't get assets map!")); return(false); } EditorUtility.DisplayCancelableProgressBar(string.Format(ProgressCaption, currentPhase, phasesCount, 0, 0), "Analyzing Assets Map for references...", 0); var allAssetsInProject = map.assets; var count = allAssetsInProject.Count; var updateStep = Math.Max(count / MaintainerSettings.UpdateProgressStep, 1); var referencedAssets = new HashSet <AssetInfo>(); for (var i = 0; i < count; i++) { if (showProgress && i % updateStep == 0 && i != 0 && EditorUtility.DisplayCancelableProgressBar( string.Format(ProgressCaption, currentPhase, phasesCount, i + 1, count), "Analyzing Assets Map for references...", (float)(i + 1) / count)) { return(true); } var asset = allAssetsInProject[i]; /*if (asset.Path.EndsWith("1.pdf")) * { * Debug.Log(asset.Type); * if (asset.Type == CSReflectionTools.defaultAssetType) * { * var importer = AssetImporter.GetAtPath(asset.Path); * Debug.Log(importer); * } * }*/ if (asset.Kind != AssetKind.Regular) { continue; } if (AssetInIgnores(asset, ignoredScenes)) { referencedAssets.Add(asset); var references = asset.GetReferencesRecursive(); foreach (var reference in references) { referencedAssets.Add(reference); } } if (AssetInIgnoresSecondPass(asset, referencedAssets)) { referencedAssets.Add(asset); var references = asset.GetReferencesRecursive(); foreach (var reference in references) { if (!referencedAssets.Contains(reference)) { referencedAssets.Add(reference); } } } } var unreferencedAssets = new List <AssetInfo>(count); for (var i = 0; i < count; i++) { if (showProgress && i % updateStep == 0 && i != 0 && EditorUtility.DisplayCancelableProgressBar( string.Format(ProgressCaption, currentPhase, phasesCount, i + 1, count), "Filtering out unreferenced assets...", (float)(i + 1) / count)) { return(true); } var asset = allAssetsInProject[i]; if (asset.Kind != AssetKind.Regular) { continue; } if (!referencedAssets.Contains(asset)) { if (unreferencedAssets.IndexOf(asset) == -1) { unreferencedAssets.Add(asset); } } } count = unreferencedAssets.Count; updateStep = Math.Max(count / MaintainerSettings.UpdateProgressStep, 1); for (var i = count - 1; i > -1; i--) { if (showProgress && i % updateStep == 0 && i != 0) { var index = count - i; if (EditorUtility.DisplayCancelableProgressBar( string.Format(ProgressCaption, currentPhase, phasesCount, index, count), "Populating results...", (float)index / count)) { return(true); } } var unreferencedAsset = unreferencedAssets[i]; results.Add(AssetRecord.Create(RecordType.UnreferencedAsset, unreferencedAsset)); } return(false); }