A game about forced loneliness, made by TACStudios
at master 242 lines 8.2 kB view raw
1using System.Collections.Generic; 2using System.Linq; 3 4using Codice.Client.Common; 5using Codice.LogWrapper; 6using Unity.PlasticSCM.Editor.UI; 7 8namespace Unity.PlasticSCM.Editor.AssetUtils.Processor 9{ 10 class AssetPostprocessor : UnityEditor.AssetPostprocessor 11 { 12 internal struct PathToMove 13 { 14 internal readonly string SrcPath; 15 internal readonly string DstPath; 16 17 internal PathToMove(string srcPath, string dstPath) 18 { 19 SrcPath = srcPath; 20 DstPath = dstPath; 21 } 22 } 23 24 internal static bool IsAutomaticAddEnabled { get; private set; } 25 26 static AssetPostprocessor() 27 { 28 IsAutomaticAddEnabled = BoolSetting.Load( 29 UnityConstants.AUTOMATIC_ADD_KEY_NAME, true); 30 } 31 32 internal static void Enable( 33 string wkPath, 34 PlasticAssetsProcessor plasticAssetsProcessor) 35 { 36 mLog.Debug("Enable"); 37 38 mWkPath = wkPath; 39 mPlasticAssetsProcessor = plasticAssetsProcessor; 40 41 mIsEnabled = true; 42 } 43 44 internal static void Disable() 45 { 46 mLog.Debug("Disable"); 47 48 mIsEnabled = false; 49 50 mWkPath = null; 51 mPlasticAssetsProcessor = null; 52 } 53 54 internal static void SetAutomaticAddPreference(bool isEnabled) 55 { 56 if (IsAutomaticAddEnabled == isEnabled) 57 return; 58 59 IsAutomaticAddEnabled = isEnabled; 60 61 BoolSetting.Save(isEnabled, UnityConstants.AUTOMATIC_ADD_KEY_NAME); 62 } 63 64 internal static void SetIsRepaintNeededAfterAssetDatabaseRefresh() 65 { 66 mIsRepaintNeededAfterAssetDatabaseRefresh = true; 67 } 68 69 static void OnPostprocessAllAssets( 70 string[] importedAssets, 71 string[] deletedAssets, 72 string[] movedAssets, 73 string[] movedFromAssetPaths) 74 { 75 if (!mIsEnabled) 76 return; 77 78 if (mIsRepaintNeededAfterAssetDatabaseRefresh) 79 { 80 mIsRepaintNeededAfterAssetDatabaseRefresh = false; 81 82 ProjectWindow.Repaint(); 83 RepaintInspector.All(); 84 } 85 86 // Ensure that the MonoFSWatcher is enabled before processing Plastic operations. 87 // It fixes the following scenario: 88 // 1. Close PlasticSCM window. 89 // 2. Create an asset, it appears with the added overlay. 90 // 3. Open PlasticSCM window, the asset should appear as added instead of deleted locally. 91 PlasticApp.EnableMonoFsWatcherIfNeeded(); 92 93 List<PathToMove> pathsToMove = GetPathsToMoveOnWorkspace( 94 mWkPath, movedAssets, movedFromAssetPaths); 95 96 mPlasticAssetsProcessor.MoveOnSourceControl(pathsToMove); 97 98 List<string> pathsToCheckout; 99 List<string> pathsToAdd; 100 GetPathsToCheckoutOrAddOnWorkspace( 101 mWkPath, importedAssets, pathsToMove, IsAutomaticAddEnabled, 102 out pathsToCheckout, out pathsToAdd); 103 104 mPlasticAssetsProcessor.CheckoutOnSourceControl(pathsToCheckout); 105 106 mPlasticAssetsProcessor.DeleteFromSourceControl( 107 GetPathsContainedOnWorkspace(mWkPath, deletedAssets)); 108 109 mPlasticAssetsProcessor.AddToSourceControl(pathsToAdd); 110 111 // Unity Editor notifies the modified assets through 112 // AssetModificationProcessor.OnWillSaveAssets before getting here. 113 // Known Issue: renamed prefabs not triggering OnWillSaveAssets. 114 mPlasticAssetsProcessor.CheckoutOnSourceControl( 115 GetPathsContainedOnWorkspace( 116 mWkPath, AssetModificationProcessor.ExtractModifiedAssetsToProcess())); 117 } 118 119 static List<PathToMove> GetPathsToMoveOnWorkspace( 120 string wkPath, 121 string[] movedAssets, 122 string[] movedFromAssetPaths) 123 { 124 List<PathToMove> proposedPathsToMove = GetPathsToMoveContainedOnWorkspace( 125 wkPath, movedAssets, movedFromAssetPaths); 126 127 // Unity Editor does not notify the moved assets in order. So, we have 128 // to process the move operations in hierarchical order, otherwise, that 129 // will end up with locally moved paths. This also avoids unnecessary 130 // move operations for children when their parents are also moved. 131 132 proposedPathsToMove.Sort((x, y) => PathHelper. 133 GetPathMatchSorter().Compare(x.SrcPath, y.SrcPath)); 134 135 List<PathToMove> result = new List<PathToMove>(); 136 137 foreach (PathToMove proposedPathToMove in proposedPathsToMove) 138 { 139 if (result.Any(pathToMove => PathHelper. 140 IsContainedOn(proposedPathToMove.SrcPath, pathToMove.SrcPath))) 141 continue; 142 143 result.Add(proposedPathToMove); 144 } 145 146 return result; 147 } 148 149 static void GetPathsToCheckoutOrAddOnWorkspace( 150 string wkPath, 151 string[] importedAssets, 152 List<PathToMove> pathsToMove, 153 bool isAutomaticAddEnabled, 154 out List<string> pathsToCheckout, 155 out List<string> pathsToAdd) 156 { 157 pathsToCheckout = new List<string>(); 158 pathsToAdd = new List<string>(); 159 160 // Unity Editor notifies as imported assets a combination of moved+modified 161 // assets and added assets. To ensure proper version control operations, 162 // we need to categorize them accordingly: 163 // • moved+modified assets → check-out them to handle as controlled changes. 164 // • added assets → add them when the automatic add preference is enabled. 165 166 foreach (string asset in importedAssets) 167 { 168 string fullPath = AssetsPath.GetFullPathUnderWorkspace. 169 ForAsset(wkPath, asset); 170 171 if (fullPath == null) 172 continue; 173 174 if (pathsToMove.FindIndex(pathToMove => 175 pathToMove.DstPath.Equals(fullPath)) != -1) 176 { 177 pathsToCheckout.Add(fullPath); 178 continue; 179 } 180 181 if (isAutomaticAddEnabled) 182 pathsToAdd.Add(fullPath); 183 } 184 } 185 186 static List<PathToMove> GetPathsToMoveContainedOnWorkspace( 187 string wkPath, 188 string[] movedAssets, 189 string[] movedFromAssetPaths) 190 { 191 List<PathToMove> result = new List<PathToMove>(movedAssets.Length); 192 193 for (int i = 0; i < movedAssets.Length; i++) 194 { 195 string fullSrcPath = AssetsPath.GetFullPathUnderWorkspace. 196 ForAsset(wkPath, movedFromAssetPaths[i]); 197 198 if (fullSrcPath == null) 199 continue; 200 201 string fullDstPath = AssetsPath.GetFullPathUnderWorkspace. 202 ForAsset(wkPath, movedAssets[i]); 203 204 if (fullDstPath == null) 205 continue; 206 207 result.Add(new PathToMove( 208 fullSrcPath, fullDstPath)); 209 } 210 211 return result; 212 } 213 214 static List<string> GetPathsContainedOnWorkspace( 215 string wkPath, string[] assets) 216 { 217 List<string> result = new List<string>( 218 assets.Length); 219 220 foreach (string asset in assets) 221 { 222 string fullPath = AssetsPath.GetFullPathUnderWorkspace. 223 ForAsset(wkPath, asset); 224 225 if (fullPath == null) 226 continue; 227 228 result.Add(fullPath); 229 } 230 231 return result; 232 } 233 234 static bool mIsEnabled; 235 static bool mIsRepaintNeededAfterAssetDatabaseRefresh; 236 237 static PlasticAssetsProcessor mPlasticAssetsProcessor; 238 static string mWkPath; 239 240 static readonly ILog mLog = PlasticApp.GetLogger("AssetPostprocessor"); 241 } 242}