366 lines
11 KiB
C#
366 lines
11 KiB
C#
using System;
|
|
using System.IO;
|
|
using System.Linq;
|
|
|
|
using UnityEditor;
|
|
using UnityEngine;
|
|
|
|
using Codice.Client.BaseCommands;
|
|
using Codice.Client.Common;
|
|
using Codice.Client.Common.Connection;
|
|
using Codice.Client.Common.Encryption;
|
|
using Codice.Client.Common.EventTracking;
|
|
using Codice.Client.Common.Threading;
|
|
using Codice.Client.Common.WebApi;
|
|
using Codice.CM.Common;
|
|
using Codice.CM.ConfigureHelper;
|
|
using Codice.LogWrapper;
|
|
using CodiceApp.EventTracking;
|
|
using PlasticGui;
|
|
using PlasticPipe.Certificates;
|
|
using PlasticPipe.Client;
|
|
using Unity.PlasticSCM.Editor.CloudDrive;
|
|
using Unity.PlasticSCM.Editor.Configuration;
|
|
using Unity.PlasticSCM.Editor.Tool;
|
|
using Unity.PlasticSCM.Editor.UI;
|
|
|
|
namespace Unity.PlasticSCM.Editor
|
|
{
|
|
internal static class PlasticApp
|
|
{
|
|
internal static bool IsUnitTesting { get; set; }
|
|
|
|
internal static ILog GetLogger(string name)
|
|
{
|
|
if (!mIsDomainUnloadHandlerRegistered)
|
|
{
|
|
// Register the Domain Unload Handler before the LogManager is initialized,
|
|
// so the domain unload handler for the app is processed before the log manager one,
|
|
// and thus the AppDomainUnload is printed in the log
|
|
RegisterDomainUnloadHandler();
|
|
mIsDomainUnloadHandlerRegistered = true;
|
|
}
|
|
|
|
return LogManager.GetLogger(name);
|
|
}
|
|
|
|
internal static void InitializeIfNeeded()
|
|
{
|
|
if (mIsInitialized)
|
|
return;
|
|
|
|
mIsInitialized = true;
|
|
|
|
// Configure logging on initialize to avoid adding the performance cost of it
|
|
// on every Editor load and Domain reload for non-UVCS users.
|
|
ConfigureLogging();
|
|
|
|
mLog.Debug("InitializeIfNeeded");
|
|
|
|
mLog.DebugFormat("Unity version: {0}", Application.unityVersion);
|
|
mLog.DebugFormat("unityplastic.dll version: {0}", UnityPlasticDllVersion.GetFileVersion());
|
|
|
|
// Ensures that the Edition Token is initialized
|
|
UnityConfigurationChecker.SynchronizeUnityEditionToken();
|
|
PlasticInstallPath.LogInstallationInfo();
|
|
|
|
if (!IsUnitTesting)
|
|
GuiMessage.Initialize(new UnityPlasticGuiMessage());
|
|
|
|
RegisterExceptionHandlers();
|
|
RegisterApplicationFocusHandlers();
|
|
RegisterBeforeAssemblyReloadHandler();
|
|
RegisterEditorWantsToQuit();
|
|
RegisterEditorQuitting();
|
|
|
|
InitLocalization();
|
|
|
|
if (!IsUnitTesting)
|
|
ThreadWaiter.Initialize(new UnityThreadWaiterBuilder());
|
|
|
|
ServicePointConfigurator.ConfigureServicePoint();
|
|
CertificateUi.RegisterHandler(new ChannelCertificateUiImpl());
|
|
|
|
EditionManager.Get().DisableCapability(EnumEditionCapabilities.Extensions);
|
|
|
|
ClientHandlers.Register();
|
|
|
|
PlasticGuiConfig.SetConfigFile(PlasticGuiConfig.UNITY_GUI_CONFIG_FILE);
|
|
|
|
if (!IsUnitTesting)
|
|
{
|
|
mEventSenderScheduler = EventTracking.Configure(
|
|
(PlasticWebRestApi)PlasticGui.Plastic.WebRestAPI,
|
|
ApplicationIdentifier.UnityPackage,
|
|
IdentifyEventPlatform.Get());
|
|
}
|
|
|
|
PackageInfo.Initialize();
|
|
|
|
PlasticMethodExceptionHandling.InitializeAskCredentialsUi(
|
|
new CredentialsUiImpl());
|
|
ClientEncryptionServiceProvider.SetEncryptionPasswordProvider(
|
|
new MissingEncryptionPasswordPromptHandler());
|
|
}
|
|
|
|
internal static void Enable()
|
|
{
|
|
string webApiToken = CmConnection.Get().BuildWebApiTokenForCloudEditionDefaultUser();
|
|
|
|
if (string.IsNullOrEmpty(webApiToken))
|
|
return;
|
|
|
|
PlasticGui.Plastic.WebRestAPI.SetToken(webApiToken);
|
|
|
|
OrganizationsInformation.UpdateCloudOrganizationSlugsAsync(
|
|
PlasticGui.Plastic.WebRestAPI, PlasticGui.Plastic.API);
|
|
}
|
|
|
|
internal static void DisposeIfNeeded()
|
|
{
|
|
if (!mIsInitialized)
|
|
return;
|
|
|
|
if (UVCSPlugin.Instance.IsEnabled() ||
|
|
CloudDrivePlugin.Instance.IsEnabled())
|
|
return;
|
|
|
|
mLog.Debug("Dispose");
|
|
|
|
mIsInitialized = false;
|
|
|
|
UnRegisterDomainUnloadHandler();
|
|
UnRegisterExceptionHandlers();
|
|
UnRegisterApplicationFocusHandlers();
|
|
UnRegisterBeforeAssemblyReloadHandler();
|
|
UnRegisterEditorWantsToQuit();
|
|
UnRegisterEditorQuitting();
|
|
|
|
if (mEventSenderScheduler != null)
|
|
{
|
|
// Launching and forgetting to avoid a timeout when sending events files and no
|
|
// network connection is available.
|
|
// This will be refactored once a better mechanism to send event is in place
|
|
mEventSenderScheduler.EndAndSendEventsAsync();
|
|
}
|
|
|
|
ClientConnectionPool.Shutdown();
|
|
}
|
|
|
|
static void Shutdown()
|
|
{
|
|
UVCSPlugin.Instance.Shutdown();
|
|
|
|
CloudDrivePlugin.Instance.Shutdown();
|
|
|
|
DisposeIfNeeded();
|
|
}
|
|
|
|
static void RegisterDomainUnloadHandler()
|
|
{
|
|
AppDomain.CurrentDomain.DomainUnload += AppDomainUnload;
|
|
}
|
|
|
|
static void RegisterExceptionHandlers()
|
|
{
|
|
AppDomain.CurrentDomain.UnhandledException += HandleUnhandledException;
|
|
|
|
Application.logMessageReceivedThreaded += HandleLog;
|
|
}
|
|
|
|
static void RegisterApplicationFocusHandlers()
|
|
{
|
|
EditorWindowFocus.OnApplicationActivated += OnApplicationActivated;
|
|
|
|
EditorWindowFocus.OnApplicationDeactivated += OnApplicationDeactivated;
|
|
}
|
|
|
|
static void RegisterBeforeAssemblyReloadHandler()
|
|
{
|
|
AssemblyReloadEvents.beforeAssemblyReload += BeforeAssemblyReload;
|
|
}
|
|
|
|
static void RegisterEditorWantsToQuit()
|
|
{
|
|
EditorApplication.wantsToQuit += OnEditorWantsToQuit;
|
|
}
|
|
|
|
static void RegisterEditorQuitting()
|
|
{
|
|
EditorApplication.quitting += OnEditorQuitting;
|
|
}
|
|
|
|
static void UnRegisterDomainUnloadHandler()
|
|
{
|
|
AppDomain.CurrentDomain.DomainUnload -= AppDomainUnload;
|
|
}
|
|
|
|
static void UnRegisterExceptionHandlers()
|
|
{
|
|
AppDomain.CurrentDomain.UnhandledException -= HandleUnhandledException;
|
|
|
|
Application.logMessageReceivedThreaded -= HandleLog;
|
|
}
|
|
|
|
static void UnRegisterApplicationFocusHandlers()
|
|
{
|
|
EditorWindowFocus.OnApplicationActivated -= OnApplicationActivated;
|
|
|
|
EditorWindowFocus.OnApplicationDeactivated -= OnApplicationDeactivated;
|
|
}
|
|
|
|
static void UnRegisterBeforeAssemblyReloadHandler()
|
|
{
|
|
AssemblyReloadEvents.beforeAssemblyReload -= BeforeAssemblyReload;
|
|
}
|
|
|
|
static void UnRegisterEditorWantsToQuit()
|
|
{
|
|
EditorApplication.wantsToQuit -= OnEditorWantsToQuit;
|
|
}
|
|
|
|
static void UnRegisterEditorQuitting()
|
|
{
|
|
EditorApplication.quitting -= OnEditorQuitting;
|
|
}
|
|
|
|
static void AppDomainUnload(object sender, EventArgs e)
|
|
{
|
|
mLog.Debug("AppDomainUnload");
|
|
|
|
UnRegisterDomainUnloadHandler();
|
|
}
|
|
|
|
static void HandleUnhandledException(object sender, UnhandledExceptionEventArgs args)
|
|
{
|
|
Exception ex = (Exception)args.ExceptionObject;
|
|
|
|
if (CheckUnityException.IsExitGUIException(ex) ||
|
|
!IsPlasticStackTrace(ex.StackTrace))
|
|
throw ex;
|
|
|
|
GUIActionRunner.RunGUIAction(delegate {
|
|
ExceptionsHandler.HandleException("HandleUnhandledException", ex);
|
|
});
|
|
}
|
|
|
|
static void HandleLog(string logString, string stackTrace, LogType type)
|
|
{
|
|
if (type != LogType.Exception)
|
|
return;
|
|
|
|
if (!IsPlasticStackTrace(stackTrace))
|
|
return;
|
|
|
|
GUIActionRunner.RunGUIAction(delegate {
|
|
mLog.ErrorFormat("[HandleLog] Unexpected error: {0}", logString);
|
|
mLog.DebugFormat("Stack trace: {0}", stackTrace);
|
|
|
|
string message = logString;
|
|
if (ExceptionsHandler.DumpStackTrace())
|
|
message += Environment.NewLine + stackTrace;
|
|
|
|
GuiMessage.ShowError(message);
|
|
});
|
|
}
|
|
|
|
static void OnApplicationActivated()
|
|
{
|
|
mLog.Debug("OnApplicationActivated");
|
|
|
|
if (UVCSPlugin.Instance.IsEnabled())
|
|
UVCSPlugin.Instance.OnApplicationActivated();
|
|
|
|
if (CloudDrivePlugin.Instance.IsEnabled())
|
|
CloudDrivePlugin.Instance.OnApplicationActivated();
|
|
}
|
|
|
|
static void OnApplicationDeactivated()
|
|
{
|
|
mLog.Debug("OnApplicationDeactivated");
|
|
|
|
if (UVCSPlugin.Instance.IsEnabled())
|
|
UVCSPlugin.Instance.OnApplicationDeactivated();
|
|
}
|
|
|
|
static void BeforeAssemblyReload()
|
|
{
|
|
mLog.Debug("BeforeAssemblyReload");
|
|
|
|
UnRegisterBeforeAssemblyReloadHandler();
|
|
|
|
Shutdown();
|
|
}
|
|
|
|
static bool OnEditorWantsToQuit()
|
|
{
|
|
mLog.Debug("OnEditorWantsToQuit");
|
|
|
|
return UVCSPlugin.Instance.OnEditorWantsToQuit()
|
|
&& CloudDrivePlugin.Instance.OnEditorWantsToQuit();
|
|
}
|
|
|
|
static void OnEditorQuitting()
|
|
{
|
|
mLog.Debug("OnEditorQuitting");
|
|
|
|
Shutdown();
|
|
}
|
|
|
|
static void ConfigureLogging()
|
|
{
|
|
try
|
|
{
|
|
string log4netpath = ToolConfig.GetUnityPlasticLogConfigFile();
|
|
|
|
if (!File.Exists(log4netpath))
|
|
WriteLogConfiguration.For(log4netpath);
|
|
|
|
XmlConfigurator.Configure(new FileInfo(log4netpath));
|
|
|
|
mLog.DebugFormat("Configured logging in '{0}'", log4netpath);
|
|
}
|
|
catch
|
|
{
|
|
//it failed configuring the logging info; nothing to do.
|
|
}
|
|
}
|
|
|
|
static void InitLocalization()
|
|
{
|
|
string language = null;
|
|
try
|
|
{
|
|
language = ClientConfig.Get().GetLanguage();
|
|
}
|
|
catch
|
|
{
|
|
language = string.Empty;
|
|
}
|
|
|
|
Localization.Init(language);
|
|
PlasticLocalization.SetLanguage(language);
|
|
}
|
|
|
|
static bool IsPlasticStackTrace(string stackTrace)
|
|
{
|
|
if (stackTrace == null)
|
|
return false;
|
|
|
|
string[] namespaces = new[] {
|
|
"Codice.",
|
|
"GluonGui.",
|
|
"PlasticGui."
|
|
};
|
|
|
|
return namespaces.Any(stackTrace.Contains);
|
|
}
|
|
|
|
static bool mIsDomainUnloadHandlerRegistered;
|
|
static bool mIsInitialized;
|
|
static EventSenderScheduler mEventSenderScheduler;
|
|
|
|
static readonly ILog mLog = PlasticApp.GetLogger("PlasticApp");
|
|
}
|
|
}
|