init project

This commit is contained in:
2026-02-16 14:02:58 +01:00
parent 0a3f464e9d
commit 9528038aaa
14854 changed files with 930822 additions and 0 deletions

View File

@@ -0,0 +1,94 @@
using System;
using PlasticGui;
namespace Unity.PlasticSCM.Editor.AssetsOverlays
{
internal static class AssetOverlay
{
internal static string GetStatusString(AssetStatus assetStatus)
{
if (ClassifyAssetStatus.IsPrivate(assetStatus))
return PlasticLocalization.Name.Private.GetString();
if (ClassifyAssetStatus.IsIgnored(assetStatus))
return PlasticLocalization.Name.StatusIgnored.GetString();
if (ClassifyAssetStatus.IsAdded(assetStatus))
return PlasticLocalization.Name.StatusAdded.GetString();
if (ClassifyAssetStatus.IsConflicted(assetStatus))
return PlasticLocalization.Name.StatusConflicted.GetString();
if (ClassifyAssetStatus.IsDeletedOnServer(assetStatus))
return PlasticLocalization.Name.StatusDeletedOnServer.GetString();
if (ClassifyAssetStatus.IsLockedRemote(assetStatus))
return PlasticLocalization.Name.StatusLockedRemote.GetString();
if (ClassifyAssetStatus.IsOutOfDate(assetStatus))
return PlasticLocalization.Name.StatusOutOfDate.GetString();
if (ClassifyAssetStatus.IsLocked(assetStatus))
return PlasticLocalization.Name.StatusLockedByMe.GetString();
if (ClassifyAssetStatus.IsRetained(assetStatus))
return PlasticLocalization.Name.StatusRetained.GetString();
if (ClassifyAssetStatus.IsCheckedOut(assetStatus))
return PlasticLocalization.Name.StatusCheckout.GetString();
if (ClassifyAssetStatus.IsChanged(assetStatus))
return PlasticLocalization.Name.ChangedStatus.GetString();
if (ClassifyAssetStatus.ContainsChanges(assetStatus))
return PlasticLocalization.Name.ContainsChanges.GetString();
if (ClassifyAssetStatus.IsControlled(assetStatus))
return PlasticLocalization.Name.Controlled.GetString();
return string.Empty;
}
internal static string GetTooltipText(
AssetStatus statusValue,
LockStatusData lockStatusData)
{
string statusText = GetStatusString(statusValue);
if (lockStatusData == null)
return statusText;
// example:
// Changed by:
// * dani_pen@hotmail.com
// * workspace wkLocal"
char bulletCharacter = '\u25cf';
string line1 = ClassifyAssetStatus.IsLocked(statusValue) ?
statusText + ":" :
PlasticLocalization.GetString(
PlasticLocalization.Name.AssetOverlayTooltipStatus,
statusText);
string line2 = string.Format("{0} {1}",
bulletCharacter,
lockStatusData.LockedBy);
string line3 = string.Format("{0} {1}",
bulletCharacter,
PlasticLocalization.GetString(
PlasticLocalization.Name.AssetOverlayTooltipOn,
lockStatusData.HolderBranchName));
return string.Format(
"{0}" + Environment.NewLine +
"{1}" + Environment.NewLine +
"{2}",
line1,
line2,
line3);
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 408f89d90a01494cbef838c7d21449a9
timeCreated: 1750849696

View File

@@ -0,0 +1,120 @@
using System;
namespace Unity.PlasticSCM.Editor.AssetsOverlays
{
[Flags]
internal enum AssetStatus
{
None = 0,
Private = 1 << 0,
Ignored = 1 << 2,
Added = 1 << 3,
Checkout = 1 << 4,
Controlled = 1 << 5,
UpToDate = 1 << 6,
Changed = 1 << 7,
ContainsChanges = 1 << 8,
OutOfDate = 1 << 9,
Conflicted = 1 << 10,
DeletedOnServer = 1 << 11,
Locked = 1 << 12,
LockedRemote = 1 << 13,
Retained = 1 << 14,
HiddenChanged = 1 << 15,
}
internal class LockStatusData
{
internal readonly AssetStatus Status;
internal readonly string LockedBy;
internal readonly string HolderBranchName;
internal LockStatusData(
AssetStatus status,
string lockedBy,
string holderBranchName)
{
Status = status;
LockedBy = lockedBy;
HolderBranchName = holderBranchName;
}
}
internal class ClassifyAssetStatus
{
internal static bool IsPrivate(AssetStatus status)
{
return ContainsAny(status, AssetStatus.Private);
}
internal static bool IsIgnored(AssetStatus status)
{
return ContainsAny(status, AssetStatus.Ignored);
}
internal static bool IsControlled(AssetStatus status)
{
return ContainsAny(status, AssetStatus.Controlled);
}
internal static bool IsLocked(AssetStatus status)
{
return ContainsAny(status, AssetStatus.Locked);
}
internal static bool IsLockedRemote(AssetStatus status)
{
return ContainsAny(status, AssetStatus.LockedRemote);
}
internal static bool IsRetained(AssetStatus status)
{
return ContainsAny(status, AssetStatus.Retained);
}
internal static bool IsOutOfDate(AssetStatus status)
{
return ContainsAny(status, AssetStatus.OutOfDate);
}
internal static bool IsDeletedOnServer(AssetStatus status)
{
return ContainsAny(status, AssetStatus.DeletedOnServer);
}
internal static bool IsConflicted(AssetStatus status)
{
return ContainsAny(status, AssetStatus.Conflicted);
}
internal static bool IsAdded(AssetStatus status)
{
return ContainsAny(status, AssetStatus.Added);
}
internal static bool IsCheckedOut(AssetStatus status)
{
return ContainsAny(status, AssetStatus.Checkout);
}
internal static bool IsChanged(AssetStatus status)
{
return ContainsAny(status, AssetStatus.Changed);
}
internal static bool ContainsChanges(AssetStatus status)
{
return ContainsAny(status, AssetStatus.ContainsChanges);
}
internal static bool IsHiddenChanged(AssetStatus status)
{
return ContainsAny(status, AssetStatus.HiddenChanged);
}
static bool ContainsAny(AssetStatus status, AssetStatus matchTo)
{
return (status & matchTo) != AssetStatus.None;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 062535eac3e5dd1409b6a50b0d043e2c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 6a94a55dca335c547ac65bd4b85d2a55
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,66 @@
using Codice.CM.Common;
namespace Unity.PlasticSCM.Editor.AssetsOverlays.Cache
{
internal interface IAssetStatusCache
{
AssetStatus GetStatus(string fullPath);
LockStatusData GetLockStatusData(string fullPath);
void Clear();
void ClearLocks();
void Cancel();
}
internal class AssetStatusCache : IAssetStatusCache
{
internal AssetStatusCache(
WorkspaceInfo wkInfo,
bool isGluonMode)
{
mLocalStatusCache = new LocalStatusCache(wkInfo);
mRemoteStatusCache = new RemoteStatusCache(wkInfo, isGluonMode);
mLockStatusCache = new LockStatusCache(wkInfo);
}
AssetStatus IAssetStatusCache.GetStatus(string fullPath)
{
AssetStatus localStatus = mLocalStatusCache.GetStatus(fullPath);
if (!ClassifyAssetStatus.IsControlled(localStatus))
return localStatus;
AssetStatus remoteStatus = mRemoteStatusCache.GetStatus(fullPath);
AssetStatus lockStatus = mLockStatusCache.GetStatus(fullPath);
return localStatus | remoteStatus | lockStatus;
}
LockStatusData IAssetStatusCache.GetLockStatusData(string fullPath)
{
return mLockStatusCache.GetLockStatusData(fullPath);
}
void IAssetStatusCache.Clear()
{
mLocalStatusCache.Clear();
mRemoteStatusCache.Clear();
mLockStatusCache.Clear();
}
void IAssetStatusCache.ClearLocks()
{
mLockStatusCache.Clear();
}
void IAssetStatusCache.Cancel()
{
mRemoteStatusCache.Cancel();
mLockStatusCache.Cancel();
}
readonly LocalStatusCache mLocalStatusCache;
readonly RemoteStatusCache mRemoteStatusCache;
readonly LockStatusCache mLockStatusCache;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 3f227b28cf424364489edd67fce697bc
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
using Codice.Utils;
namespace Unity.PlasticSCM.Editor.AssetsOverlays.Cache
{
internal static class BuildPathDictionary
{
internal static Dictionary<string, T> ForPlatform<T>()
{
if (PlatformIdentifier.IsWindows())
return new Dictionary<string, T>(
StringComparer.OrdinalIgnoreCase);
return new Dictionary<string, T>();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 9c963b5d17c74314eb7105e71377cdb8
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,98 @@
using System.Collections.Generic;
using Codice;
using Codice.CM.Common;
using Codice.Client.BaseCommands;
using Codice.Client.Commands.WkTree;
using PlasticGui.WorkspaceWindow;
namespace Unity.PlasticSCM.Editor.AssetsOverlays.Cache
{
internal class LocalStatusCache
{
internal LocalStatusCache(WorkspaceInfo wkInfo)
{
mWkInfo = wkInfo;
}
internal AssetStatus GetStatus(string fullPath)
{
AssetStatus result;
if (mStatusByPathCache.TryGetValue(fullPath, out result))
return result;
result = CalculateStatus(
mWkInfo,
fullPath,
FilterManager.Get().GetIgnoredFilter(),
FilterManager.Get().GetHiddenChangesFilter());
mStatusByPathCache.Add(fullPath, result);
return result;
}
internal void Clear()
{
mStatusByPathCache.Clear();
}
static AssetStatus CalculateStatus(
WorkspaceInfo wkInfo,
string fullPath,
IgnoredFilesFilter ignoredFilter,
HiddenChangesFilesFilter hiddenChangesFilter)
{
WorkspaceTreeNode node = PlasticGui.Plastic.API.GetWorkspaceTreeNode(
wkInfo, fullPath);
if (CheckWorkspaceTreeNodeStatus.IsPrivate(node))
{
return ignoredFilter.IsIgnored(fullPath) ?
AssetStatus.Ignored : AssetStatus.Private;
}
if (CheckWorkspaceTreeNodeStatus.IsAdded(node))
return AssetStatus.Added;
AssetStatus status = AssetStatus.Controlled;
status |= CalculateControlledFlags(wkInfo, fullPath, node);
status |= GetHiddenChangeFlag(fullPath, hiddenChangesFilter);
return status;
}
static AssetStatus CalculateControlledFlags(
WorkspaceInfo wkInfo,
string fullPath,
WorkspaceTreeNode node)
{
if (CheckWorkspaceTreeNodeStatus.IsCheckedOut(node))
return AssetStatus.Checkout;
if (CheckWorkspaceTreeNodeStatus.IsDirectory(node))
return PlasticGui.Plastic.API.IsOnChangedTree(wkInfo, fullPath)
? AssetStatus.ContainsChanges
: AssetStatus.None;
return ChangedFileChecker.IsChanged(node.LocalInfo, fullPath, wkInfo.IsDynamic, false)
? AssetStatus.Changed
: AssetStatus.None;
}
static AssetStatus GetHiddenChangeFlag(
string fullPath,
HiddenChangesFilesFilter hiddenChangesFilter)
{
return hiddenChangesFilter.IsHiddenChanged(fullPath)
? AssetStatus.HiddenChanged
: AssetStatus.None;
}
readonly WorkspaceInfo mWkInfo;
readonly Dictionary<string, AssetStatus> mStatusByPathCache =
BuildPathDictionary.ForPlatform<AssetStatus>();
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 226459a134855504d841db6b61519d2b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,184 @@
using System.Collections.Generic;
using Codice;
using Codice.Client.Commands.WkTree;
using Codice.Client.Common;
using Codice.Client.Common.Locks;
using Codice.Client.Common.Threading;
using Codice.Client.Common.WkTree;
using Codice.CM.Common;
using Codice.CM.Common.Mount;
using Codice.Utils;
using PlasticGui.WorkspaceWindow;
using PlasticGui.WorkspaceWindow.Items.Locks;
using Unity.PlasticSCM.Editor.AssetUtils;
namespace Unity.PlasticSCM.Editor.AssetsOverlays.Cache
{
internal class LockStatusCache
{
internal LockStatusCache(
WorkspaceInfo wkInfo)
{
mWkInfo = wkInfo;
}
internal AssetStatus GetStatus(string fullPath)
{
LockStatusData lockStatusData = GetLockStatusData(fullPath);
if (lockStatusData == null)
return AssetStatus.None;
return lockStatusData.Status;
}
internal LockStatusData GetLockStatusData(string fullPath)
{
lock (mLock)
{
if (mStatusByPathCache == null)
{
mStatusByPathCache = BuildPathDictionary.ForPlatform<LockStatusData>();
mCurrentCancelToken.Cancel();
mCurrentCancelToken = new CancelToken();
AsyncCalculateStatus(mCurrentCancelToken);
return null;
}
LockStatusData result;
if (mStatusByPathCache.TryGetValue(fullPath, out result))
return result;
return null;
}
}
internal void Clear()
{
lock (mLock)
{
mCurrentCancelToken.Cancel();
mStatusByPathCache = null;
}
}
internal void Cancel()
{
lock (mLock)
{
mCurrentCancelToken.Cancel();
}
}
void AsyncCalculateStatus(CancelToken cancelToken)
{
Dictionary<string, LockStatusData> statusByPathCache = null;
IThreadWaiter waiter = ThreadWaiter.GetWaiter(50);
waiter.Execute(
/*threadOperationDelegate*/ delegate
{
Dictionary<MountPointWithPath, List<WorkspaceTreeNode>> lockCandidates =
new Dictionary<MountPointWithPath, List<WorkspaceTreeNode>>();
FillLockCandidates.ForTree(mWkInfo, lockCandidates);
if (cancelToken.IsCancelled())
return;
Dictionary<WorkspaceTreeNode, LockInfo> lockInfoByNode =
SearchLocks.GetLocksInfo(mWkInfo, lockCandidates);
if (cancelToken.IsCancelled())
return;
statusByPathCache = BuildStatusByNodeCache.
ForLocks(mWkInfo.ClientPath, lockInfoByNode);
},
/*afterOperationDelegate*/ delegate
{
if (cancelToken.IsCancelled())
return;
if (waiter.Exception != null)
{
ExceptionsHandler.LogException(
"LockStatusCache",
waiter.Exception);
return;
}
lock (mLock)
{
mStatusByPathCache = statusByPathCache;
}
RepaintEditor.AllWindowsWithOverlays();
});
}
static class BuildStatusByNodeCache
{
internal static Dictionary<string, LockStatusData> ForLocks(
string wkPath,
Dictionary<WorkspaceTreeNode, LockInfo> lockInfoByNode)
{
Dictionary<string, LockStatusData> result =
BuildPathDictionary.ForPlatform<LockStatusData>();
LockOwnerNameResolver nameResolver = new LockOwnerNameResolver();
foreach (WorkspaceTreeNode node in lockInfoByNode.Keys)
{
LockStatusData lockStatusData = BuildLockStatusData(
node, lockInfoByNode[node], nameResolver);
string nodeWkPath = WorkspacePath.GetWorkspacePathFromCmPath(
wkPath,
WorkspaceNodeOperations.GetCmPath(node),
PathHelper.GetDirectorySeparatorChar(wkPath));
result.Add(nodeWkPath, lockStatusData);
}
return result;
}
static LockStatusData BuildLockStatusData(
WorkspaceTreeNode node,
LockInfo lockInfo,
LockOwnerNameResolver nameResolver)
{
return new LockStatusData(
GetAssetStatus(node, lockInfo),
nameResolver.GetSeidName(lockInfo.SEIDData),
BranchInfoCache.GetProtectedBranchName(
node.RepSpec, lockInfo.HolderBranchId));
}
static AssetStatus GetAssetStatus(
WorkspaceTreeNode node,
LockInfo lockInfo)
{
if (lockInfo.Status == LockInfo.LockStatus.Retained)
return AssetStatus.Retained;
return CheckWorkspaceTreeNodeStatus.IsCheckedOut(node) ?
AssetStatus.Locked : AssetStatus.LockedRemote;
}
}
CancelToken mCurrentCancelToken = new CancelToken();
Dictionary<string, LockStatusData> mStatusByPathCache;
readonly WorkspaceInfo mWkInfo;
static object mLock = new object();
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 953c29d2e0dece647a64940343c91547
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,181 @@
using System.Collections.Generic;
using Codice.Client.Common;
using Codice.Client.Common.Threading;
using Codice.CM.Common;
using Codice.CM.Common.Merge;
using Codice.CM.Common.Mount;
using Codice.CM.Common.Partial;
using Codice.CM.Common.Update.Partial;
using Codice.Utils;
using GluonGui.WorkspaceWindow.Views;
using Unity.PlasticSCM.Editor.AssetUtils;
namespace Unity.PlasticSCM.Editor.AssetsOverlays.Cache
{
internal class RemoteStatusCache
{
internal RemoteStatusCache(
WorkspaceInfo wkInfo,
bool isGluonMode)
{
mWkInfo = wkInfo;
mIsGluonMode = isGluonMode;
}
internal AssetStatus GetStatus(string fullPath)
{
if (!mIsGluonMode)
return AssetStatus.UpToDate;
lock(mLock)
{
if (mStatusByPathCache == null)
{
mStatusByPathCache = BuildPathDictionary.ForPlatform<AssetStatus>();
mCurrentCancelToken.Cancel();
mCurrentCancelToken = new CancelToken();
AsyncCalculateStatus(mCurrentCancelToken);
return AssetStatus.UpToDate;
}
AssetStatus result;
if (mStatusByPathCache.TryGetValue(fullPath, out result))
return result;
return AssetStatus.UpToDate;
}
}
internal void Clear()
{
lock (mLock)
{
mCurrentCancelToken.Cancel();
mStatusByPathCache = null;
}
}
internal void Cancel()
{
lock (mLock)
{
mCurrentCancelToken.Cancel();
}
}
void AsyncCalculateStatus(CancelToken cancelToken)
{
Dictionary<string, AssetStatus> statusByPathCache = null;
IThreadWaiter waiter = ThreadWaiter.GetWaiter(50);
waiter.Execute(
/*threadOperationDelegate*/ delegate
{
OutOfDateItems outOfDateItems =
OutOfDateUpdater.CalculateOutOfDateItems(
mWkInfo, new List<ErrorMessage>(),
OutOfDateCalculator.Options.IsIncomingChanges);
if (cancelToken.IsCancelled())
return;
statusByPathCache = BuildStatusByPathCache.
ForOutOfDateItems(outOfDateItems, mWkInfo.ClientPath);
},
/*afterOperationDelegate*/ delegate
{
if (cancelToken.IsCancelled())
return;
if (waiter.Exception != null)
{
ExceptionsHandler.LogException(
"RemoteStatusCache",
waiter.Exception);
return;
}
lock (mLock)
{
mStatusByPathCache = statusByPathCache;
}
RepaintEditor.AllWindowsWithOverlays();
});
}
static class BuildStatusByPathCache
{
internal static Dictionary<string, AssetStatus> ForOutOfDateItems(
OutOfDateItems outOfDateItems,
string wkPath)
{
Dictionary<string, AssetStatus> result =
BuildPathDictionary.ForPlatform<AssetStatus>();
if (outOfDateItems == null)
return result;
foreach (OutOfDateItemsByMount diffs in
outOfDateItems.GetOutOfDateItemsByMountList(PathHelper.GetPathSorter()))
{
foreach (Difference diff in diffs.Changed)
{
if (diff is DiffXlinkChanged)
continue;
string path = GetPathForDiff(wkPath, diffs.Mount, diff.Path);
result.Add(path, AssetStatus.OutOfDate);
}
foreach (Difference diff in diffs.Deleted)
{
string path = GetPathForDiff(wkPath, diffs.Mount, diff.Path);
result.Add(path, AssetStatus.DeletedOnServer);
}
}
foreach (GluonFileConflict fileConflict in
outOfDateItems.GetFileConflicts())
{
string path = GetPathForConflict(wkPath, fileConflict.CmPath);
result.Add(path, AssetStatus.Conflicted);
}
return result;
}
static string GetPathForDiff(
string wkPath,
MountPointWithPath mountPoint,
string cmSubPath)
{
return WorkspacePath.GetWorkspacePathFromCmPath(
wkPath,
WorkspacePath.ComposeMountPath(mountPoint.MountPath, cmSubPath),
PathHelper.GetDirectorySeparatorChar(wkPath));
}
static string GetPathForConflict(
string wkPath,
string cmPath)
{
return WorkspacePath.GetWorkspacePathFromCmPath(
wkPath, cmPath,
PathHelper.GetDirectorySeparatorChar(wkPath));
}
}
CancelToken mCurrentCancelToken = new CancelToken();
Dictionary<string, AssetStatus> mStatusByPathCache;
readonly bool mIsGluonMode;
readonly WorkspaceInfo mWkInfo;
static object mLock = new object();
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a9acb575a60d7e045ad7fadd3e3e137d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,86 @@
using UnityEngine;
using Unity.PlasticSCM.Editor.UI;
namespace Unity.PlasticSCM.Editor.AssetsOverlays
{
internal static class DrawAssetOverlayIcon
{
internal static void ForStatus(
Rect selectionRect,
AssetStatus status,
string tooltipText)
{
Texture overlayIcon = GetOverlayIcon(status);
if (overlayIcon == null)
return;
Rect overlayRect = GetOverlayRect.ForSelectionRect(selectionRect);
GUI.DrawTexture(overlayRect, overlayIcon, ScaleMode.ScaleToFit);
Rect tooltipRect = GetTooltipRect(selectionRect, overlayRect);
GUI.Label(tooltipRect, new GUIContent(string.Empty, tooltipText));
}
internal static Texture GetOverlayIcon(AssetStatus assetStatus)
{
if (ClassifyAssetStatus.IsPrivate(assetStatus))
return Images.GetPrivateOverlayIcon();
if (ClassifyAssetStatus.IsIgnored(assetStatus))
return Images.GetIgnoredOverlayIcon();
if (ClassifyAssetStatus.IsAdded(assetStatus))
return Images.GetAddedOverlayIcon();
if (ClassifyAssetStatus.IsConflicted(assetStatus))
return Images.GetConflictedOverlayIcon();
if (ClassifyAssetStatus.IsDeletedOnServer(assetStatus))
return Images.GetDeletedRemoteOverlayIcon();
if (ClassifyAssetStatus.IsLockedRemote(assetStatus))
return Images.GetLockedRemoteOverlayIcon();
if (ClassifyAssetStatus.IsOutOfDate(assetStatus))
return Images.GetOutOfSyncOverlayIcon();
if (ClassifyAssetStatus.IsLocked(assetStatus))
return Images.GetLockedLocalOverlayIcon();
if (ClassifyAssetStatus.IsRetained(assetStatus))
return Images.GetRetainedOverlayIcon();
if (ClassifyAssetStatus.IsCheckedOut(assetStatus) ||
ClassifyAssetStatus.IsChanged(assetStatus) ||
ClassifyAssetStatus.ContainsChanges(assetStatus))
return Images.GetCheckedOutOverlayIcon();
return null;
}
static Rect Inflate(Rect rect, float width, float height)
{
return new Rect(
rect.x - width,
rect.y - height,
rect.width + 2f * width,
rect.height + 2f * height);
}
static Rect GetTooltipRect(
Rect selectionRect,
Rect overlayRect)
{
if (selectionRect.width > selectionRect.height)
{
return overlayRect;
}
return Inflate(overlayRect, 3f, 3f);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a92f7c4434405984a811b4e7c316594e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,210 @@
using System;
using UnityEditor;
using UnityEditor.SceneManagement;
using UnityEngine;
using UnityEngine.SceneManagement;
using Codice.Client.Common.Threading;
using Codice.LogWrapper;
using Unity.PlasticSCM.Editor.AssetsOverlays.Cache;
using Unity.PlasticSCM.Editor.AssetUtils;
using Object = UnityEngine.Object;
namespace Unity.PlasticSCM.Editor.AssetsOverlays
{
internal static class DrawHierarchyOverlay
{
internal interface IGetAssetPathFromInstance
{
bool TryGetAssetPath(int instanceID, out string assetPath);
}
internal static IGetAssetPathFromInstance GetSubSceneAssetPath;
internal static void Enable(
string wkPath,
IAssetStatusCache assetStatusCache)
{
if (mIsEnabled)
return;
mLog.Debug("Enable");
mWkPath = wkPath;
mAssetStatusCache = assetStatusCache;
mIsEnabled = true;
#if UNITY_6000_4_OR_NEWER
EditorApplication.hierarchyWindowItemByEntityIdOnGUI += OnHierarchyGUIByEntityId;
#else
EditorApplication.hierarchyWindowItemOnGUI += OnHierarchyGUI;
#endif
RepaintEditor.HierarchyWindow();
}
internal static void Disable()
{
mLog.Debug("Disable");
mIsEnabled = false;
#if UNITY_6000_4_OR_NEWER
EditorApplication.hierarchyWindowItemByEntityIdOnGUI -= OnHierarchyGUIByEntityId;
#else
EditorApplication.hierarchyWindowItemOnGUI -= OnHierarchyGUI;
#endif
RepaintEditor.HierarchyWindow();
mWkPath = null;
mAssetStatusCache = null;
}
#if UNITY_6000_4_OR_NEWER
static void OnHierarchyGUIByEntityId(EntityId entityId, Rect selectionRect)
{
OnHierarchyGUI((int)entityId.GetRawData(), selectionRect);
}
#endif
static void OnHierarchyGUI(int instanceID, Rect selectionRect)
{
if (Event.current.type != EventType.Repaint)
return;
try
{
string assetPath = GetAssetPathFromInstanceID(instanceID);
if (assetPath == null)
return;
string assetFullPath = AssetsPath.GetFullPathUnderWorkspace.ForAsset(mWkPath, assetPath);
if (assetFullPath == null)
return;
DrawOverlayForAsset(assetFullPath, selectionRect, mAssetStatusCache);
}
catch (Exception ex)
{
ExceptionsHandler.LogException(typeof(DrawHierarchyOverlay).Name, ex);
}
}
static string GetAssetPathFromInstanceID(int instanceID)
{
string sceneAssetPath;
if (TryGetAssetPathForScene(instanceID, out sceneAssetPath))
{
return sceneAssetPath;
}
string subSceneAssetPath;
if (TryGetAssetPathForSubScene(instanceID, out subSceneAssetPath))
{
return subSceneAssetPath;
}
string prefabAssetPath;
if (TryGetAssetPathForPrefab(instanceID, out prefabAssetPath))
{
return prefabAssetPath;
}
return null;
}
static bool TryGetAssetPathForScene(int instanceID, out string assetPath)
{
assetPath = null;
if (FindUnityObject.ForInstanceID(instanceID) != null)
return false;
assetPath = FindScenePathForHandle(instanceID);
return assetPath != null;
}
static string FindScenePathForHandle(int sceneHandle)
{
for (int i = 0; i < SceneManager.sceneCount; i++)
{
Scene scene = SceneManager.GetSceneAt(i);
#if UNITY_6000_4_OR_NEWER
if (scene.handle == SceneHandle.FromRawData((ulong)sceneHandle) && scene.path != null)
#else
if (scene.handle == sceneHandle && scene.path != null)
#endif
{
return scene.path;
}
}
return null;
}
static bool TryGetAssetPathForSubScene(int instanceID, out string assetPath)
{
assetPath = null;
string subSceneAssetPath;
if (GetSubSceneAssetPath != null &&
GetSubSceneAssetPath.TryGetAssetPath(instanceID, out subSceneAssetPath))
{
assetPath = subSceneAssetPath;
}
return assetPath != null;
}
static bool TryGetAssetPathForPrefab(int instanceID, out string assetPath)
{
assetPath = null;
PrefabStage prefabStage = PrefabStageUtility.GetCurrentPrefabStage();
if (prefabStage == null)
return false;
Object hierarchyObject = FindUnityObject.ForInstanceID(instanceID);
if (hierarchyObject == null)
return false;
if (prefabStage.prefabContentsRoot == hierarchyObject)
assetPath = prefabStage.assetPath;
return assetPath != null;
}
static void DrawOverlayForAsset(
string assetFullPath,
Rect selectionRect,
IAssetStatusCache assetStatusCache)
{
AssetStatus assetStatus = assetStatusCache.GetStatus(assetFullPath);
string tooltipText = AssetOverlay.GetTooltipText(
assetStatus,
assetStatusCache.GetLockStatusData(assetFullPath));
DrawAssetOverlayIcon.ForStatus(
selectionRect,
assetStatus,
tooltipText);
}
static bool mIsEnabled;
static IAssetStatusCache mAssetStatusCache;
static string mWkPath;
static readonly ILog mLog = PlasticApp.GetLogger("DrawHierarchyOverlay");
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 68f2f2587930106408dd3b00fb4974ff
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,87 @@
using System;
using UnityEditor;
using UnityEngine;
using Codice.Client.Common.Threading;
using Codice.LogWrapper;
using PlasticGui;
using Unity.PlasticSCM.Editor.AssetsOverlays.Cache;
using Unity.PlasticSCM.Editor.AssetUtils;
namespace Unity.PlasticSCM.Editor.AssetsOverlays
{
internal static class DrawProjectOverlay
{
internal static void Enable(
string wkPath,
IAssetStatusCache assetStatusCache)
{
if (mIsEnabled)
return;
mLog.Debug("Enable");
mWkPath = wkPath;
mAssetStatusCache = assetStatusCache;
mIsEnabled = true;
EditorApplication.projectWindowItemOnGUI += OnProjectWindowItemGUI;
RepaintEditor.ProjectWindow();
}
internal static void Disable()
{
mLog.Debug("Disable");
mIsEnabled = false;
EditorApplication.projectWindowItemOnGUI -= OnProjectWindowItemGUI;
RepaintEditor.ProjectWindow();
mWkPath = null;
mAssetStatusCache = null;
}
static void OnProjectWindowItemGUI(string guid, Rect selectionRect)
{
try
{
if (string.IsNullOrEmpty(guid))
return;
if (Event.current.type != EventType.Repaint)
return;
string fullPath = AssetsPath.GetFullPathUnderWorkspace.ForGuid(mWkPath, guid);
if (fullPath == null)
return;
AssetStatus assetStatus = mAssetStatusCache.GetStatus(fullPath);
string tooltipText = AssetOverlay.GetTooltipText(
assetStatus,
mAssetStatusCache.GetLockStatusData(fullPath));
DrawAssetOverlayIcon.ForStatus(
selectionRect,
assetStatus,
tooltipText);
}
catch (Exception ex)
{
ExceptionsHandler.LogException(typeof(DrawProjectOverlay).Name, ex);
}
}
static bool mIsEnabled;
static IAssetStatusCache mAssetStatusCache;
static string mWkPath;
static readonly ILog mLog = PlasticApp.GetLogger("DrawProjectOverlay");
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d30dfeb72257204458e1e8e1576b84ba
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: