A game about forced loneliness, made by TACStudios
1using System; 2using System.ComponentModel; 3using System.Threading; 4using System.Threading.Tasks; 5 6using UnityEditor; 7using UnityEngine; 8 9using Codice.Client.Common.Connection; 10using Codice.CM.Common; 11using Codice.LogWrapper; 12using Unity.PlasticSCM.Editor.AssetMenu; 13using Unity.PlasticSCM.Editor.AssetsOverlays; 14using Unity.PlasticSCM.Editor.AssetsOverlays.Cache; 15using Unity.PlasticSCM.Editor.AssetUtils.Processor; 16using Unity.PlasticSCM.Editor.Hub; 17using Unity.PlasticSCM.Editor.Inspector; 18using Unity.PlasticSCM.Editor.SceneView; 19using Unity.PlasticSCM.Editor.UI; 20 21namespace Unity.PlasticSCM.Editor 22{ 23 // Internal usage. This isn't a public API. 24 // It supports calls across two different modules "Unity.CollabProxy.Editor".ToolbarButton -> "Unity.PlasticSCM.Editor".PlasticPlugin.Xxx() 25 // and the "Unity.CollabProxy.Editor" is itself required as it is hard-coded by the Unity Editor code 26 [EditorBrowsable(EditorBrowsableState.Never)] 27 [InitializeOnLoad] 28 public static class PlasticPlugin 29 { 30 // Internal usage between two different modules of the package. 31 [EditorBrowsable(EditorBrowsableState.Never)] 32 public static event Action OnNotificationUpdated = delegate { }; 33 34 // Internal usage between two different modules of the package. 35 // It's pending to rename the OpenPlasticWindowDisablingOfflineModeIfNeeded 36 // method to OpenPlasticWindowAndEnablePluginIfNeeded. We cannot do it now 37 // because it's a public method and this rename breaks the API validation 38 // check. We will do it when we change the major version number to v3.0.0 39 // (which is only allowed for a major new version of Unity) 40 [EditorBrowsable(EditorBrowsableState.Never)] 41 public static void OpenPlasticWindowDisablingOfflineModeIfNeeded() 42 { 43 if (!PlasticPluginIsEnabledPreference.IsEnabled()) 44 { 45 PlasticPluginIsEnabledPreference.Enable(); 46 Enable(); 47 } 48 49 ShowWindow.Plastic(); 50 } 51 52 // Internal usage between two different modules of the package. 53 [EditorBrowsable(EditorBrowsableState.Never)] 54 public static Texture GetPluginStatusIcon() 55 { 56 return PlasticNotification.GetIcon(mNotificationStatus); 57 } 58 59 internal static IAssetStatusCache AssetStatusCache 60 { 61 get { return mAssetStatusCache; } 62 } 63 64 internal static WorkspaceOperationsMonitor WorkspaceOperationsMonitor 65 { 66 get { return mWorkspaceOperationsMonitor; } 67 } 68 69 internal static PlasticConnectionMonitor ConnectionMonitor 70 { 71 get { return mPlasticConnectionMonitor; } 72 } 73 74 internal static bool IsUnitTesting { get; set; } 75 76 static PlasticPlugin() 77 { 78 EditorDispatcher.InitializeMainThreadIdAndContext( 79 Thread.CurrentThread.ManagedThreadId, 80 SynchronizationContext.Current); 81 82 ProcessHubCommand.Initialize(); 83 84 if (!FindWorkspace.HasWorkspace(ApplicationDataPath.Get())) 85 return; 86 87 if (!PlasticPluginIsEnabledPreference.IsEnabled()) 88 return; 89 90 CooldownWindowDelayer cooldownInitializeAction = new CooldownWindowDelayer( 91 Enable, UnityConstants.PLUGIN_DELAYED_INITIALIZE_INTERVAL); 92 cooldownInitializeAction.Ping(); 93 } 94 95 internal static void Enable() 96 { 97 if (mIsEnabled) 98 return; 99 100 mIsEnabled = true; 101 102 PlasticApp.InitializeIfNeeded(); 103 104 mLog.Debug("Enable"); 105 106 PlasticApp.Enable(); 107 108 WorkspaceInfo wkInfo = FindWorkspace.InfoForApplicationPath( 109 ApplicationDataPath.Get(), PlasticGui.Plastic.API); 110 111 if (wkInfo == null) 112 return; 113 114 EnableForWorkspace(wkInfo); 115 } 116 117 internal static void EnableForWorkspace(WorkspaceInfo wkInfo) 118 { 119 if (mIsEnabledForWorkspace) 120 return; 121 122 mIsEnabledForWorkspace = true; 123 124 mLog.Debug("EnableForWorkspace " + wkInfo.ClientPath); 125 126 PlasticGui.Plastic.API.UpgradeWorkspaceMetadataAfterOrgUnificationNeeded(wkInfo); 127 128 PlasticApp.SetWorkspace(wkInfo); 129 130 HandleCredsAliasAndServerCert.InitializeHostUnreachableExceptionListener( 131 mPlasticConnectionMonitor); 132 133 bool isGluonMode = PlasticGui.Plastic.API.IsGluonWorkspace(wkInfo); 134 135 mAssetStatusCache = new AssetStatusCache(wkInfo, isGluonMode); 136 137 PlasticAssetsProcessor plasticAssetsProcessor = new PlasticAssetsProcessor(); 138 139 mWorkspaceOperationsMonitor = BuildWorkspaceOperationsMonitor(plasticAssetsProcessor, isGluonMode); 140 mWorkspaceOperationsMonitor.Start(); 141 142 UnityCloudProjectLinkMonitor.CheckCloudProjectAlignmentAsync(wkInfo); 143 144 AssetsProcessors.Enable( 145 wkInfo.ClientPath, plasticAssetsProcessor, mAssetStatusCache); 146 AssetMenuItems.Enable( 147 wkInfo, PlasticGui.Plastic.API, mAssetStatusCache); 148 DrawAssetOverlay.Enable( 149 wkInfo.ClientPath, mAssetStatusCache); 150 DrawInspectorOperations.Enable( 151 wkInfo, PlasticGui.Plastic.API, mAssetStatusCache); 152 DrawSceneOperations.Enable( 153 wkInfo, PlasticGui.Plastic.API, 154 mWorkspaceOperationsMonitor, mAssetStatusCache); 155 156 Task.Run(() => EnsureServerConnection(wkInfo, mPlasticConnectionMonitor)); 157 } 158 159 internal static void Shutdown() 160 { 161 mLog.Debug("Shutdown"); 162 163 HandleCredsAliasAndServerCert.CleanHostUnreachableExceptionListener(); 164 mPlasticConnectionMonitor.Stop(); 165 166 Disable(); 167 } 168 169 internal static void Disable() 170 { 171 if (!mIsEnabled) 172 return; 173 174 try 175 { 176 mLog.Debug("Disable"); 177 178 DisableForWorkspace(); 179 180 PlasticApp.Dispose(); 181 } 182 finally 183 { 184 mIsEnabled = false; 185 } 186 } 187 188 internal static void SetNotificationStatus( 189 PlasticWindow plasticWindow, 190 PlasticNotification.Status status) 191 { 192 mNotificationStatus = status; 193 194 plasticWindow.UpdateWindowIcon(status); 195 196 if (OnNotificationUpdated != null) 197 OnNotificationUpdated.Invoke(); 198 } 199 200 static void DisableForWorkspace() 201 { 202 if (!mIsEnabledForWorkspace) 203 return; 204 205 try 206 { 207 mWorkspaceOperationsMonitor.Stop(); 208 mAssetStatusCache.Cancel(); 209 210 AssetsProcessors.Disable(); 211 AssetMenuItems.Disable(); 212 DrawAssetOverlay.Disable(); 213 DrawInspectorOperations.Disable(); 214 DrawSceneOperations.Disable(); 215 216 mAssetStatusCache.Clear(); 217 } 218 finally 219 { 220 mIsEnabledForWorkspace = false; 221 } 222 } 223 224 internal static PlasticNotification.Status GetNotificationStatus() 225 { 226 return mNotificationStatus; 227 } 228 229 static WorkspaceOperationsMonitor BuildWorkspaceOperationsMonitor( 230 PlasticAssetsProcessor plasticAssetsProcessor, 231 bool isGluonMode) 232 { 233 WorkspaceOperationsMonitor result = new WorkspaceOperationsMonitor( 234 PlasticGui.Plastic.API, plasticAssetsProcessor, isGluonMode); 235 plasticAssetsProcessor.SetWorkspaceOperationsMonitor(result); 236 return result; 237 } 238 239 static void EnsureServerConnection( 240 WorkspaceInfo wkInfo, 241 PlasticConnectionMonitor plasticConnectionMonitor) 242 { 243 if (IsUnitTesting) 244 return; 245 246 RepositorySpec repSpec = PlasticGui.Plastic.API.GetRepositorySpec(wkInfo); 247 248 plasticConnectionMonitor.SetRepositorySpecForEventTracking(repSpec); 249 250 try 251 { 252 // set the PlasticConnectionMonitor initially to have a valid connection 253 // then check that the server connection is valid. If failed, we call 254 // PlasticConnectionMonitor.OnConnectionError that fires the Plugin disable 255 // and the reconnection mechanism 256 257 plasticConnectionMonitor.SetAsConnected(); 258 259 if (!PlasticGui.Plastic.API.CheckServerConnection(repSpec.Server)) 260 throw new Exception(string.Format("Failed to connect to {0}", repSpec.Server)); 261 } 262 catch (Exception ex) 263 { 264 plasticConnectionMonitor.OnConnectionError(ex, repSpec.Server); 265 } 266 } 267 268 static PlasticNotification.Status mNotificationStatus; 269 static IAssetStatusCache mAssetStatusCache; 270 static WorkspaceOperationsMonitor mWorkspaceOperationsMonitor; 271 static PlasticConnectionMonitor mPlasticConnectionMonitor = new PlasticConnectionMonitor(); 272 static bool mIsEnabled; 273 static bool mIsEnabledForWorkspace; 274 275 static readonly ILog mLog = PlasticApp.GetLogger("PlasticPlugin"); 276 } 277}