using System; using System.Threading.Tasks; using UnityEditor; using UnityEngine; using Codice.Client.Common.Connection; using Codice.CM.Common; using Unity.PlasticSCM.Editor.AssetMenu; using Unity.PlasticSCM.Editor.AssetsOverlays; using Unity.PlasticSCM.Editor.AssetsOverlays.Cache; using Unity.PlasticSCM.Editor.AssetUtils.Processor; using Unity.PlasticSCM.Editor.CollabMigration; using Unity.PlasticSCM.Editor.Inspector; using Unity.PlasticSCM.Editor.ProjectDownloader; using Unity.PlasticSCM.Editor.SceneView; using Unity.PlasticSCM.Editor.UI; namespace Unity.PlasticSCM.Editor { /// /// The Plastic SCM plugin for Unity editor. /// [InitializeOnLoad] public static class PlasticPlugin { /// /// Invoked when notification status changed. /// public static event Action OnNotificationUpdated = delegate { }; internal static IAssetStatusCache AssetStatusCache { get { return mAssetStatusCache; } } internal static WorkspaceOperationsMonitor WorkspaceOperationsMonitor { get { return mWorkspaceOperationsMonitor; } } internal static PlasticConnectionMonitor ConnectionMonitor { get { return mPlasticConnectionMonitor; } } internal static bool IsUnitTesting { get; set; } static PlasticPlugin() { CloudProjectDownloader.Initialize(); MigrateCollabProject.Initialize(); EditorDispatcher.Initialize(); if (!FindWorkspace.HasWorkspace(ApplicationDataPath.Get())) return; if (!PlasticPluginIsEnabledPreference.IsEnabled()) return; CooldownWindowDelayer cooldownInitializeAction = new CooldownWindowDelayer( Enable, UnityConstants.PLUGIN_DELAYED_INITIALIZE_INTERVAL); cooldownInitializeAction.Ping(); } /// /// Open the Plastic SCM window. /// Also, it enables the plugin IsEnabled preference if it is disabled. /// public static void OpenPlasticWindowDisablingOfflineModeIfNeeded() { // It's pending to rename the OpenPlasticWindowDisablingOfflineModeIfNeeded // method to OpenPlasticWindowAndEnablePluginIfNeeded. We cannot do it now // because it's a public method and this rename breaks the API validation // check. We will do it when we change the major version number to v3.0.0. if (!PlasticPluginIsEnabledPreference.IsEnabled()) { PlasticPluginIsEnabledPreference.Enable(); Enable(); } ShowWindow.Plastic(); } /// /// Get the plugin status icon. /// public static Texture GetPluginStatusIcon() { return PlasticNotification.GetIcon(mNotificationStatus); } internal static void Enable() { if (mIsEnabled) return; mIsEnabled = true; PlasticApp.InitializeIfNeeded(); if (!FindWorkspace.HasWorkspace(ApplicationDataPath.Get())) return; EnableForWorkspace(); } internal static void EnableForWorkspace() { if (mIsEnabledForWorkspace) return; WorkspaceInfo wkInfo = FindWorkspace.InfoForApplicationPath( ApplicationDataPath.Get(), PlasticGui.Plastic.API); if (wkInfo == null) return; mIsEnabledForWorkspace = true; PlasticApp.SetWorkspace(wkInfo); HandleCredsAliasAndServerCert.InitializeHostUnreachableExceptionListener( mPlasticConnectionMonitor); bool isGluonMode = PlasticGui.Plastic.API.IsGluonWorkspace(wkInfo); mAssetStatusCache = new AssetStatusCache(wkInfo, isGluonMode); PlasticAssetsProcessor plasticAssetsProcessor = new PlasticAssetsProcessor(); mWorkspaceOperationsMonitor = BuildWorkspaceOperationsMonitor( plasticAssetsProcessor, isGluonMode); mWorkspaceOperationsMonitor.Start(); AssetsProcessors.Enable( wkInfo.ClientPath, plasticAssetsProcessor, mAssetStatusCache); AssetMenuItems.Enable( wkInfo, mAssetStatusCache); DrawAssetOverlay.Enable( wkInfo.ClientPath, mAssetStatusCache); DrawInspectorOperations.Enable( wkInfo.ClientPath, mAssetStatusCache); DrawSceneOperations.Enable( wkInfo.ClientPath, mWorkspaceOperationsMonitor, mAssetStatusCache); Task.Run(() => EnsureServerConnection(wkInfo, mPlasticConnectionMonitor)); } internal static void Disable() { if (!mIsEnabled) return; try { PlasticApp.Dispose(); if (!mIsEnabledForWorkspace) return; mWorkspaceOperationsMonitor.Stop(); AssetsProcessors.Disable(); AssetMenuItems.Disable(); DrawAssetOverlay.Disable(); DrawInspectorOperations.Disable(); DrawSceneOperations.Disable(); } finally { mIsEnabled = false; mIsEnabledForWorkspace = false; } } internal static void SetNotificationStatus( PlasticWindow plasticWindow, PlasticNotification.Status status) { mNotificationStatus = status; plasticWindow.SetupWindowTitle(status); if (OnNotificationUpdated != null) OnNotificationUpdated.Invoke(); } static WorkspaceOperationsMonitor BuildWorkspaceOperationsMonitor( PlasticAssetsProcessor plasticAssetsProcessor, bool isGluonMode) { WorkspaceOperationsMonitor result = new WorkspaceOperationsMonitor( PlasticGui.Plastic.API, plasticAssetsProcessor, isGluonMode); plasticAssetsProcessor.SetWorkspaceOperationsMonitor(result); return result; } static void EnsureServerConnection( WorkspaceInfo wkInfo, PlasticConnectionMonitor plasticConnectionMonitor) { if (IsUnitTesting) return; RepositorySpec repSpec = PlasticGui.Plastic.API.GetRepositorySpec(wkInfo); plasticConnectionMonitor.SetRepositorySpecForEventTracking(repSpec); try { // set the PlasticConnectionMonitor initially to have a valid connection // then check that the server connection is valid. If failed, we call // PlasticConnectionMonitor.OnConnectionError that fires the Plugin disable // and the reconnection mechanism plasticConnectionMonitor.SetAsConnected(); if (!PlasticGui.Plastic.API.CheckServerConnection(repSpec.Server)) throw new Exception(string.Format("Failed to connect to {0}", repSpec.Server)); } catch (Exception ex) { plasticConnectionMonitor.OnConnectionError(ex, repSpec.Server); } } static PlasticNotification.Status mNotificationStatus; static AssetStatusCache mAssetStatusCache; static WorkspaceOperationsMonitor mWorkspaceOperationsMonitor; static PlasticConnectionMonitor mPlasticConnectionMonitor = new PlasticConnectionMonitor(); static bool mIsEnabled; static bool mIsEnabledForWorkspace; } }