Initial commit

This commit is contained in:
lethanhsonvsp
2025-11-17 15:02:30 +07:00
commit 0a84b9d75e
15481 changed files with 2009655 additions and 0 deletions

View File

@@ -0,0 +1,48 @@
using System.Collections.Generic;
using UnityEditor;
using Codice.CM.Common;
using PlasticGui;
using PlasticGui.WorkspaceWindow;
using Unity.PlasticSCM.Editor.AssetsOverlays.Cache;
using Unity.PlasticSCM.Editor.AssetUtils;
namespace Unity.PlasticSCM.Editor.AssetMenu
{
internal class AssetCopyPathOperation : IAssetMenuCopyPathOperation
{
internal AssetCopyPathOperation(
WorkspaceInfo wkInfo,
IPlasticAPI plasticApi,
IAssetStatusCache assetStatusCache,
AssetVcsOperations.IAssetSelection assetSelection)
{
mWkInfo = wkInfo;
mPlasticAPI = plasticApi;
mAssetStatusCache = assetStatusCache;
mAssetSelection = assetSelection;
}
void IAssetMenuCopyPathOperation.CopyFilePath(bool relativePath)
{
List<string> selectedPaths = GetSelectedPaths.ForOperation(
mWkInfo,
mAssetSelection.GetSelectedAssets(),
mPlasticAPI,
mAssetStatusCache,
AssetMenuOperations.CopyFilePath,
includeMetaFiles: false);
EditorGUIUtility.systemCopyBuffer = GetFilePathList.FromSelectedPaths(
selectedPaths,
relativePath,
mWkInfo.ClientPath);
}
readonly WorkspaceInfo mWkInfo;
readonly IPlasticAPI mPlasticAPI;
readonly IAssetStatusCache mAssetStatusCache;
readonly AssetVcsOperations.IAssetSelection mAssetSelection;
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: d2a9f8ad3405465db8e62d36f2686b68
timeCreated: 1730989830

View File

@@ -0,0 +1,274 @@
using Codice.Client.BaseCommands;
using PlasticGui;
using PlasticGui.WorkspaceWindow.Items;
using Unity.PlasticSCM.Editor.UI;
namespace Unity.PlasticSCM.Editor.AssetMenu
{
internal interface IAssetFilesFilterPatternsMenuOperations
{
void AddFilesFilterPatterns(
FilterTypes type, FilterActions action, FilterOperationType operation);
}
internal class AssetFilesFilterPatternsMenuBuilder
{
internal string IgnoredSubmenuItem { get { return mIgnoredSubmenuItem; } }
internal string HiddenChangesSubmenuItem { get { return mHiddenChangesSubmenuItem; } }
internal AssetFilesFilterPatternsMenuBuilder(
int ignoredMenuItemsPriority,
int hiddenChangesMenuItemsPriority)
{
mIgnoredMenuItemsPriority = ignoredMenuItemsPriority;
mHiddenChangesMenuItemsPriority = hiddenChangesMenuItemsPriority;
mIgnoredSubmenuItem = string.Format(
"{0}/{1}",
PlasticLocalization.GetString(PlasticLocalization.Name.PrefixUnityVersionControlMenu),
PlasticLocalization.GetString(PlasticLocalization.Name.MenuAddToIgnoreList));
mHiddenChangesSubmenuItem = string.Format(
"{0}/{1}",
PlasticLocalization.GetString(PlasticLocalization.Name.PrefixUnityVersionControlMenu),
PlasticLocalization.GetString(PlasticLocalization.Name.MenuAddToHiddenChangesList));
}
internal void SetOperations(
IAssetFilesFilterPatternsMenuOperations operations)
{
mOperations = operations;
}
internal void UpdateMenuItems(FilterMenuActions actions)
{
UpdateIgnoredMenuItems(actions);
UpdateHiddenChangesMenuItems(actions);
HandleMenuItem.UpdateAllMenus();
}
internal void RemoveMenuItems()
{
RemoveIgnoredMenuItems();
RemoveHiddenChangesMenuItems();
}
internal void IgnoredByName_Click()
{
if (mOperations == null)
ShowWindow.Plastic();
mOperations.AddFilesFilterPatterns(
FilterTypes.Ignored, FilterActions.ByName,
GetIgnoredFilterOperationType());
}
internal void IgnoredByExtension_Click()
{
if (mOperations == null)
ShowWindow.Plastic();
mOperations.AddFilesFilterPatterns(
FilterTypes.Ignored, FilterActions.ByExtension,
GetIgnoredFilterOperationType());
}
internal void IgnoredByFullPath_Click()
{
if (mOperations == null)
ShowWindow.Plastic();
mOperations.AddFilesFilterPatterns(
FilterTypes.Ignored, FilterActions.ByFullPath,
GetIgnoredFilterOperationType());
}
internal void HiddenChangesByName_Click()
{
if (mOperations == null)
ShowWindow.Plastic();
mOperations.AddFilesFilterPatterns(
FilterTypes.HiddenChanges, FilterActions.ByName,
GetHiddenChangesFilterOperationType());
}
internal void HiddenChangesByExtension_Click()
{
if (mOperations == null)
ShowWindow.Plastic();
mOperations.AddFilesFilterPatterns(
FilterTypes.HiddenChanges, FilterActions.ByExtension,
GetHiddenChangesFilterOperationType());
}
internal void HiddenChangesByFullPath_Click()
{
if (mOperations == null)
ShowWindow.Plastic();
mOperations.AddFilesFilterPatterns(
FilterTypes.HiddenChanges, FilterActions.ByFullPath,
GetHiddenChangesFilterOperationType());
}
void UpdateIgnoredMenuItems(FilterMenuActions actions)
{
RemoveIgnoredMenuItems();
mIgnoredSubmenuItem = string.Format(
"{0}/{1}",
PlasticLocalization.Name.PrefixUnityVersionControlMenu.GetString(),
actions.IgnoredTitle);
if (!actions.Operations.HasFlag(FilterMenuOperations.Ignore))
{
HandleMenuItem.AddMenuItem(
mIgnoredSubmenuItem,
mIgnoredMenuItemsPriority,
DisabledMenuItem_Click, ValidateDisabledMenuItem);
return;
}
mIgnoredByNameMenuItem = GetIgnoredMenuItemName(actions.FilterByName);
mIgnoredByExtensionMenuItem = GetIgnoredMenuItemName(actions.FilterByExtension);
mIgnoredByFullPathMenuItem = GetIgnoredMenuItemName(actions.FilterByFullPath);
HandleMenuItem.AddMenuItem(
mIgnoredByNameMenuItem,
mIgnoredMenuItemsPriority,
IgnoredByName_Click, ValidateEnabledMenuItem);
if (actions.Operations.HasFlag(FilterMenuOperations.IgnoreByExtension))
HandleMenuItem.AddMenuItem(
mIgnoredByExtensionMenuItem,
mIgnoredMenuItemsPriority,
IgnoredByExtension_Click, ValidateEnabledMenuItem);
HandleMenuItem.AddMenuItem(
mIgnoredByFullPathMenuItem,
mIgnoredMenuItemsPriority,
IgnoredByFullPath_Click, ValidateEnabledMenuItem);
}
void UpdateHiddenChangesMenuItems(FilterMenuActions actions)
{
RemoveHiddenChangesMenuItems();
mHiddenChangesSubmenuItem = string.Format(
"{0}/{1}",
PlasticLocalization.Name.PrefixUnityVersionControlMenu.GetString(),
actions.HiddenChangesTitle);
if (!actions.Operations.HasFlag(FilterMenuOperations.HideChanged))
{
HandleMenuItem.AddMenuItem(
mHiddenChangesSubmenuItem,
mHiddenChangesMenuItemsPriority,
DisabledMenuItem_Click, ValidateDisabledMenuItem);
return;
}
mHiddenChangesByNameMenuItem = GetHiddenChangesMenuItemName(actions.FilterByName);
mHiddenChangesByExtensionMenuItem = GetHiddenChangesMenuItemName(actions.FilterByExtension);
mHiddenChangesByFullPathMenuItem = GetHiddenChangesMenuItemName(actions.FilterByFullPath);
HandleMenuItem.AddMenuItem(
mHiddenChangesByNameMenuItem,
mIgnoredMenuItemsPriority,
HiddenChangesByName_Click, ValidateEnabledMenuItem);
if (actions.Operations.HasFlag(FilterMenuOperations.HideChangedByExtension))
HandleMenuItem.AddMenuItem(
mHiddenChangesByExtensionMenuItem,
mIgnoredMenuItemsPriority,
HiddenChangesByExtension_Click, ValidateEnabledMenuItem);
HandleMenuItem.AddMenuItem(
mHiddenChangesByFullPathMenuItem,
mIgnoredMenuItemsPriority,
HiddenChangesByFullPath_Click, ValidateEnabledMenuItem);
}
void RemoveIgnoredMenuItems()
{
HandleMenuItem.RemoveMenuItem(mIgnoredSubmenuItem);
HandleMenuItem.RemoveMenuItem(mIgnoredByNameMenuItem);
HandleMenuItem.RemoveMenuItem(mIgnoredByExtensionMenuItem);
HandleMenuItem.RemoveMenuItem(mIgnoredByFullPathMenuItem);
}
void RemoveHiddenChangesMenuItems()
{
HandleMenuItem.RemoveMenuItem(mHiddenChangesSubmenuItem);
HandleMenuItem.RemoveMenuItem(mHiddenChangesByNameMenuItem);
HandleMenuItem.RemoveMenuItem(mHiddenChangesByExtensionMenuItem);
HandleMenuItem.RemoveMenuItem(mHiddenChangesByFullPathMenuItem);
}
FilterOperationType GetIgnoredFilterOperationType()
{
return GetFilterOperationType(
mIgnoredByNameMenuItem,
PlasticLocalization.Name.MenuAddToIgnoreList);
}
FilterOperationType GetHiddenChangesFilterOperationType()
{
return GetFilterOperationType(
mHiddenChangesByNameMenuItem,
PlasticLocalization.Name.MenuAddToHiddenChangesList);
}
static FilterOperationType GetFilterOperationType(string menuItemName, PlasticLocalization.Name expectedTitle)
{
string[] split = menuItemName.Split('/');
if (split.Length < 2)
return FilterOperationType.Remove;
string parentMenu = split[split.Length - 2];
return parentMenu.StartsWith(expectedTitle.GetString())
? FilterOperationType.Add
: FilterOperationType.Remove;
}
void DisabledMenuItem_Click() { }
bool ValidateEnabledMenuItem() { return true; }
bool ValidateDisabledMenuItem() { return false; }
string GetIgnoredMenuItemName(string filterPattern)
{
return UnityMenuItem.GetText(
mIgnoredSubmenuItem,
UnityMenuItem.EscapedText(filterPattern));
}
string GetHiddenChangesMenuItemName(string filterPattern)
{
return UnityMenuItem.GetText(
mHiddenChangesSubmenuItem,
UnityMenuItem.EscapedText(filterPattern));
}
IAssetFilesFilterPatternsMenuOperations mOperations;
string mIgnoredSubmenuItem;
string mHiddenChangesSubmenuItem;
string mIgnoredByNameMenuItem;
string mHiddenChangesByNameMenuItem;
string mIgnoredByExtensionMenuItem;
string mHiddenChangesByExtensionMenuItem;
string mIgnoredByFullPathMenuItem;
string mHiddenChangesByFullPathMenuItem;
readonly int mIgnoredMenuItemsPriority;
readonly int mHiddenChangesMenuItemsPriority;
}
}

View File

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

View File

@@ -0,0 +1,376 @@
using UnityEditor.VersionControl;
using Codice.CM.Common;
using Codice.Client.Common.EventTracking;
using Codice.LogWrapper;
using PlasticGui;
using PlasticGui.WorkspaceWindow;
using PlasticGui.WorkspaceWindow.Items;
using Unity.PlasticSCM.Editor.AssetsOverlays.Cache;
using Unity.PlasticSCM.Editor.AssetUtils;
using Unity.PlasticSCM.Editor.AssetUtils.Processor;
using Unity.PlasticSCM.Editor.UI;
using Unity.PlasticSCM.Editor.Tool;
namespace Unity.PlasticSCM.Editor.AssetMenu
{
internal class AssetMenuItems
{
internal static void Enable(
WorkspaceInfo wkInfo,
IPlasticAPI plasticApi,
IAssetStatusCache assetStatusCache)
{
if (mIsEnabled)
return;
mLog.Debug("Enable");
mWkInfo = wkInfo;
mPlasticAPI = plasticApi;
mAssetStatusCache = assetStatusCache;
mIsEnabled = true;
mAssetSelection = new ProjectViewAssetSelection(UpdateFilterMenuItems);
mAssetMenuCopyPathOperation = new AssetCopyPathOperation(
wkInfo, mPlasticAPI, assetStatusCache, mAssetSelection);
mFilterMenuBuilder = new AssetFilesFilterPatternsMenuBuilder(
IGNORE_MENU_ITEMS_PRIORITY,
HIDDEN_MENU_ITEMS_PRIORITY);
AddMenuItems();
}
internal static void Disable()
{
mLog.Debug("Disable");
mIsEnabled = false;
RemoveMenuItems();
if (mAssetSelection != null)
mAssetSelection.Dispose();
mWkInfo = null;
mAssetStatusCache = null;
mAssetSelection = null;
mFilterMenuBuilder = null;
mAssetMenuVcsOperations = null;
mAssetMenuCopyPathOperation = null;
}
internal static void BuildOperations(
WorkspaceInfo wkInfo,
IPlasticAPI plasticApi,
WorkspaceWindow workspaceWindow,
IViewSwitcher viewSwitcher,
IHistoryViewLauncher historyViewLauncher,
GluonGui.ViewHost viewHost,
WorkspaceOperationsMonitor workspaceOperationsMonitor,
ISaveAssets saveAssets,
PlasticGui.WorkspaceWindow.NewIncomingChangesUpdater incomingChangesUpdater,
ShelvedChangesUpdater shelvedChangesUpdater,
IAssetStatusCache assetStatusCache,
IMergeViewLauncher mergeViewLauncher,
PlasticGui.Gluon.IGluonViewSwitcher gluonViewSwitcher,
LaunchTool.IShowDownloadPlasticExeWindow showDownloadPlasticExeWindow,
bool isGluonMode)
{
if (!mIsEnabled)
Enable(wkInfo, plasticApi, assetStatusCache);
AssetVcsOperations assetVcsOperations = new AssetVcsOperations(
wkInfo,
plasticApi,
workspaceWindow,
viewSwitcher,
historyViewLauncher,
viewHost,
workspaceOperationsMonitor,
saveAssets,
incomingChangesUpdater,
shelvedChangesUpdater,
mAssetStatusCache,
mergeViewLauncher,
gluonViewSwitcher,
mAssetSelection,
showDownloadPlasticExeWindow,
isGluonMode);
mAssetMenuVcsOperations = assetVcsOperations;
mFilterMenuBuilder.SetOperations(assetVcsOperations);
}
static void RemoveMenuItems()
{
mFilterMenuBuilder.RemoveMenuItems();
HandleMenuItem.RemoveMenuItem(
PlasticLocalization.GetString(PlasticLocalization.Name.PrefixUnityVersionControlMenu));
HandleMenuItem.UpdateAllMenus();
}
static void UpdateFilterMenuItems()
{
AssetList assetList = ((AssetVcsOperations.IAssetSelection)
mAssetSelection).GetSelectedAssets();
SelectedPathsGroupInfo info = AssetsSelection.GetSelectedPathsGroupInfo(
mWkInfo.ClientPath, assetList, mAssetStatusCache);
FilterMenuActions actions =
assetList.Count != info.SelectedCount ?
new FilterMenuActions() :
FilterMenuUpdater.GetMenuActions(info);
mFilterMenuBuilder.UpdateMenuItems(actions);
}
static void AddMenuItems()
{
// TODO: Try removing this
// Somehow first item always disappears. So this is a filler item
HandleMenuItem.AddMenuItem(
GetPlasticMenuItemName(PlasticLocalization.Name.PendingChangesPlasticMenu),
PENDING_CHANGES_MENU_ITEM_PRIORITY,
PendingChanges, ValidatePendingChanges);
HandleMenuItem.AddMenuItem(
GetPlasticMenuItemName(PlasticLocalization.Name.PendingChangesPlasticMenu),
PENDING_CHANGES_MENU_ITEM_PRIORITY,
PendingChanges, ValidatePendingChanges);
HandleMenuItem.AddMenuItem(
GetPlasticMenuItemName(PlasticLocalization.Name.AddPlasticMenu),
ADD_MENU_ITEM_PRIORITY,
Add, ValidateAdd);
HandleMenuItem.AddMenuItem(
GetPlasticMenuItemName(PlasticLocalization.Name.CheckoutPlasticMenu),
CHECKOUT_MENU_ITEM_PRIORITY,
Checkout, ValidateCheckout);
HandleMenuItem.AddMenuItem(
GetPlasticMenuItemName(PlasticLocalization.Name.CheckinPlasticMenu),
CHECKIN_MENU_ITEM_PRIORITY,
Checkin, ValidateCheckin);
HandleMenuItem.AddMenuItem(
GetPlasticMenuItemName(PlasticLocalization.Name.UndoPlasticMenu),
UNDO_MENU_ITEM_PRIORITY,
Undo, ValidateUndo);
HandleMenuItem.AddMenuItem(
GetPlasticMenuItemName(PlasticLocalization.Name.CopyFilePathMenuItem),
COPY_FILE_PATH_MENU_ITEM_PRIORITY,
CopyFilePath,
ValidateCopyFilePath);
HandleMenuItem.AddMenuItem(
GetPlasticMenuItemName(PlasticLocalization.Name.CopyRelativeFilePathMenuItem),
COPY_RELATIVE_FILE_PATH_MENU_ITEM_PRIORITY,
CopyRelativeFilePath,
ValidateCopyFilePath);
UpdateFilterMenuItems();
HandleMenuItem.AddMenuItem(
GetPlasticMenuItemName(PlasticLocalization.Name.DiffPlasticMenu),
GetPlasticShortcut.ForAssetDiff(),
DIFF_MENU_ITEM_PRIORITY,
Diff, ValidateDiff);
HandleMenuItem.AddMenuItem(
GetPlasticMenuItemName(PlasticLocalization.Name.HistoryPlasticMenu),
GetPlasticShortcut.ForHistory(),
HISTORY_MENU_ITEM_PRIORITY,
History, ValidateHistory);
HandleMenuItem.UpdateAllMenus();
}
static void PendingChanges()
{
ShowWindow.Plastic();
mAssetMenuVcsOperations.ShowPendingChanges();
}
static bool ValidatePendingChanges()
{
return true;
}
static void Add()
{
if (mAssetMenuVcsOperations == null)
ShowWindow.Plastic();
mAssetMenuVcsOperations.Add();
}
static bool ValidateAdd()
{
return ShouldMenuItemBeEnabled(
mWkInfo, mAssetSelection, mAssetStatusCache,
AssetMenuOperations.Add);
}
static void Checkout()
{
if (mAssetMenuVcsOperations == null)
ShowWindow.Plastic();
mAssetMenuVcsOperations.Checkout();
}
static bool ValidateCheckout()
{
return ShouldMenuItemBeEnabled(
mWkInfo, mAssetSelection, mAssetStatusCache,
AssetMenuOperations.Checkout);
}
static void Checkin()
{
TrackFeatureUseEvent.For(
PlasticGui.Plastic.API.GetRepositorySpec(mWkInfo),
TrackFeatureUseEvent.Features.ContextMenuCheckinOption);
if (mAssetMenuVcsOperations == null)
ShowWindow.Plastic();
mAssetMenuVcsOperations.Checkin();
}
static bool ValidateCheckin()
{
return ShouldMenuItemBeEnabled(
mWkInfo, mAssetSelection, mAssetStatusCache,
AssetMenuOperations.Checkin);
}
static void Undo()
{
if (mAssetMenuVcsOperations == null)
ShowWindow.Plastic();
mAssetMenuVcsOperations.Undo();
}
static bool ValidateUndo()
{
return ShouldMenuItemBeEnabled(
mWkInfo, mAssetSelection, mAssetStatusCache,
AssetMenuOperations.Undo);
}
static void CopyFilePath()
{
mAssetMenuCopyPathOperation.CopyFilePath(relativePath: false);
}
static void CopyRelativeFilePath()
{
mAssetMenuCopyPathOperation.CopyFilePath(relativePath: true);
}
static bool ValidateCopyFilePath()
{
return ShouldMenuItemBeEnabled(
mWkInfo, mAssetSelection, mAssetStatusCache,
AssetMenuOperations.CopyFilePath);
}
static void Diff()
{
if (mAssetMenuVcsOperations == null)
ShowWindow.Plastic();
mAssetMenuVcsOperations.ShowDiff();
}
static bool ValidateDiff()
{
return ShouldMenuItemBeEnabled(
mWkInfo, mAssetSelection, mAssetStatusCache,
AssetMenuOperations.Diff);
}
static void History()
{
ShowWindow.Plastic();
mAssetMenuVcsOperations.ShowHistory();
}
static bool ValidateHistory()
{
return ShouldMenuItemBeEnabled(
mWkInfo, mAssetSelection, mAssetStatusCache,
AssetMenuOperations.History);
}
static bool ShouldMenuItemBeEnabled(
WorkspaceInfo wkInfo,
AssetVcsOperations.IAssetSelection assetSelection,
IAssetStatusCache statusCache,
AssetMenuOperations operation)
{
AssetList assetList = assetSelection.GetSelectedAssets();
if (assetList.Count == 0)
return false;
SelectedAssetGroupInfo selectedGroupInfo = SelectedAssetGroupInfo.
BuildFromAssetList(wkInfo, assetList, mPlasticAPI, statusCache);
if (assetList.Count != selectedGroupInfo.SelectedCount)
return false;
AssetMenuOperations operations = AssetMenuUpdater.
GetAvailableMenuOperations(selectedGroupInfo);
return operations.HasFlag(operation);
}
static string GetPlasticMenuItemName(PlasticLocalization.Name name)
{
return string.Format("{0}/{1}",
PlasticLocalization.GetString(PlasticLocalization.Name.PrefixUnityVersionControlMenu),
PlasticLocalization.GetString(name));
}
static IAssetMenuVCSOperations mAssetMenuVcsOperations;
static IAssetMenuCopyPathOperation mAssetMenuCopyPathOperation;
static ProjectViewAssetSelection mAssetSelection;
static AssetFilesFilterPatternsMenuBuilder mFilterMenuBuilder;
static bool mIsEnabled;
static IAssetStatusCache mAssetStatusCache;
static IPlasticAPI mPlasticAPI;
static WorkspaceInfo mWkInfo;
#if UNITY_6000_0_OR_NEWER
// Puts Unity Version Control in a new section, as it precedes the Create menu with the old value
const int BASE_MENU_ITEM_PRIORITY = 71;
#else
// Puts Unity Version Control right below the Create menu
const int BASE_MENU_ITEM_PRIORITY = 19;
#endif
// incrementing the "order" param by 11 causes the menu system to add a separator
const int PENDING_CHANGES_MENU_ITEM_PRIORITY = BASE_MENU_ITEM_PRIORITY;
const int ADD_MENU_ITEM_PRIORITY = PENDING_CHANGES_MENU_ITEM_PRIORITY + 11;
const int CHECKOUT_MENU_ITEM_PRIORITY = PENDING_CHANGES_MENU_ITEM_PRIORITY + 12;
const int CHECKIN_MENU_ITEM_PRIORITY = PENDING_CHANGES_MENU_ITEM_PRIORITY + 13;
const int UNDO_MENU_ITEM_PRIORITY = PENDING_CHANGES_MENU_ITEM_PRIORITY + 14;
const int COPY_FILE_PATH_MENU_ITEM_PRIORITY = PENDING_CHANGES_MENU_ITEM_PRIORITY + 25;
const int COPY_RELATIVE_FILE_PATH_MENU_ITEM_PRIORITY = PENDING_CHANGES_MENU_ITEM_PRIORITY + 26;
const int IGNORE_MENU_ITEMS_PRIORITY = PENDING_CHANGES_MENU_ITEM_PRIORITY + 37;
const int HIDDEN_MENU_ITEMS_PRIORITY = PENDING_CHANGES_MENU_ITEM_PRIORITY + 38;
const int DIFF_MENU_ITEM_PRIORITY = PENDING_CHANGES_MENU_ITEM_PRIORITY + 49;
const int HISTORY_MENU_ITEM_PRIORITY = PENDING_CHANGES_MENU_ITEM_PRIORITY + 50;
static readonly ILog mLog = PlasticApp.GetLogger("AssetMenuItems");
}
}

View File

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

View File

@@ -0,0 +1,263 @@
using System;
using UnityEditor.VersionControl;
using Codice;
using Codice.Client.Commands.Tree;
using Codice.Client.Commands.WkTree;
using Codice.CM.Common;
using PlasticGui;
using Unity.PlasticSCM.Editor.AssetsOverlays.Cache;
using Unity.PlasticSCM.Editor.AssetsOverlays;
using Unity.PlasticSCM.Editor.AssetUtils;
namespace Unity.PlasticSCM.Editor.AssetMenu
{
[Flags]
internal enum AssetMenuOperations : byte
{
None = 0,
Checkout = 1 << 0,
Diff = 1 << 1,
History = 1 << 2,
Add = 1 << 3,
Checkin = 1 << 4,
Undo = 1 << 5,
CopyFilePath = 1 << 6
}
internal class SelectedAssetGroupInfo
{
internal int SelectedCount;
internal bool IsControlledSelection;
internal bool IsCheckedInSelection;
internal bool IsCheckedOutSelection;
internal bool IsPrivateSelection;
internal bool IsAddedSelection;
internal bool IsFileSelection;
internal bool IsMovedSelection;
internal bool HasAnyAddedInSelection;
internal bool HasAnyRemoteLockedInSelection;
internal static SelectedAssetGroupInfo BuildFromAssetList(
WorkspaceInfo wkInfo,
AssetList assetList,
IPlasticAPI plasticApi,
IAssetStatusCache statusCache)
{
bool isCheckedInSelection = true;
bool isControlledSelection = true;
bool isCheckedOutSelection = true;
bool isPrivateSelection = true;
bool isAddedSelection = true;
bool isFileSelection = true;
bool isMovedSelection = true;
bool hasAnyAddedInSelection = false;
bool hasAnyRemoteLockedInSelection = false;
int selectedCount = 0;
foreach (Asset asset in assetList)
{
string fullPath = AssetsPath.GetFullPathUnderWorkspace.
ForAsset(wkInfo.ClientPath, asset.path);
if (fullPath == null)
continue;
SelectedAssetGroupInfo singleFileGroupInfo = BuildFromSingleFile(
fullPath, asset.isFolder, wkInfo, plasticApi, statusCache);
if (!singleFileGroupInfo.IsCheckedInSelection)
isCheckedInSelection = false;
if (!singleFileGroupInfo.IsControlledSelection)
isControlledSelection = false;
if (!singleFileGroupInfo.IsCheckedOutSelection)
isCheckedOutSelection = false;
if (!singleFileGroupInfo.IsPrivateSelection)
isPrivateSelection = false;
if (!singleFileGroupInfo.IsAddedSelection)
isAddedSelection = false;
if (!singleFileGroupInfo.IsFileSelection)
isFileSelection = false;
if (!singleFileGroupInfo.IsMovedSelection)
isMovedSelection = false;
if (singleFileGroupInfo.HasAnyAddedInSelection)
hasAnyAddedInSelection = true;
if (singleFileGroupInfo.HasAnyRemoteLockedInSelection)
hasAnyRemoteLockedInSelection = true;
selectedCount++;
}
return new SelectedAssetGroupInfo()
{
IsCheckedInSelection = isCheckedInSelection,
IsCheckedOutSelection = isCheckedOutSelection,
IsControlledSelection = isControlledSelection,
IsPrivateSelection = isPrivateSelection,
IsAddedSelection = isAddedSelection,
IsFileSelection = isFileSelection,
IsMovedSelection = isMovedSelection,
HasAnyAddedInSelection = hasAnyAddedInSelection,
HasAnyRemoteLockedInSelection = hasAnyRemoteLockedInSelection,
SelectedCount = selectedCount,
};
}
internal static SelectedAssetGroupInfo BuildFromSingleFile(
string fullPath,
bool isDirectory,
WorkspaceInfo wkInfo,
IPlasticAPI plasticApi,
IAssetStatusCache statusCache)
{
bool isCheckedInSelection = true;
bool isControlledSelection = true;
bool isCheckedOutSelection = true;
bool isPrivateSelection = true;
bool isAddedSelection = true;
bool isFileSelection = true;
bool isMovedSelection = false;
bool hasAnyAddedInSelection = false;
bool hasAnyRemoteLockedInSelection = false;
WorkspaceTreeNode wkTreeNode = plasticApi.
GetWorkspaceTreeNode(fullPath);
if (isDirectory)
isFileSelection = false;
if (CheckWorkspaceTreeNodeStatus.IsPrivate(wkTreeNode))
isControlledSelection = false;
else
isPrivateSelection = false;
if (CheckWorkspaceTreeNodeStatus.IsCheckedOut(wkTreeNode))
isCheckedInSelection = false;
else
isCheckedOutSelection = false;
if (CheckWorkspaceTreeNodeStatus.IsAdded(wkTreeNode))
hasAnyAddedInSelection = true;
else
isAddedSelection = false;
if (wkTreeNode != null)
{
TreeChangedNode treeChangedNode = plasticApi.
GetChangedNodeForPath(wkInfo, fullPath);
if (treeChangedNode != null)
isMovedSelection = treeChangedNode.MovedDst;
}
AssetStatus assetStatus = statusCache.GetStatus(fullPath);
if (ClassifyAssetStatus.IsLockedRemote(assetStatus))
hasAnyRemoteLockedInSelection = true;
return new SelectedAssetGroupInfo()
{
IsCheckedInSelection = isCheckedInSelection,
IsCheckedOutSelection = isCheckedOutSelection,
IsControlledSelection = isControlledSelection,
IsPrivateSelection = isPrivateSelection,
IsAddedSelection = isAddedSelection,
IsFileSelection = isFileSelection,
IsMovedSelection = isMovedSelection,
HasAnyAddedInSelection = hasAnyAddedInSelection,
HasAnyRemoteLockedInSelection = hasAnyRemoteLockedInSelection,
SelectedCount = 1,
};
}
}
internal interface IAssetMenuVCSOperations
{
void ShowPendingChanges();
void Add();
void Checkout();
void Checkin();
void Undo();
void ShowDiff();
void ShowHistory();
}
internal interface IAssetMenuCopyPathOperation
{
void CopyFilePath(bool relativePath);
}
internal static class AssetMenuUpdater
{
internal static AssetMenuOperations GetAvailableMenuOperations(
SelectedAssetGroupInfo info)
{
AssetMenuOperations result = AssetMenuOperations.None;
if (info.SelectedCount == 0)
{
return result;
}
result |= AssetMenuOperations.CopyFilePath;
if (info.IsControlledSelection &&
info.IsCheckedInSelection &&
info.IsFileSelection &&
!info.HasAnyRemoteLockedInSelection)
{
result |= AssetMenuOperations.Checkout;
}
if (info.IsFileSelection &&
info.IsPrivateSelection)
{
result |= AssetMenuOperations.Add;
}
if (info.IsFileSelection &&
info.IsControlledSelection &&
info.IsCheckedOutSelection)
{
result |= AssetMenuOperations.Checkin;
}
if ((info.IsControlledSelection &&
info.IsMovedSelection) ||
(info.IsFileSelection &&
info.IsControlledSelection &&
info.IsCheckedOutSelection))
{
result |= AssetMenuOperations.Undo;
}
if (info.SelectedCount == 1 &&
info.IsControlledSelection &&
!info.HasAnyAddedInSelection &&
info.IsFileSelection)
{
result |= AssetMenuOperations.Diff;
}
if (info.SelectedCount == 1 &&
info.IsControlledSelection &&
!info.HasAnyAddedInSelection)
{
result |= AssetMenuOperations.History;
}
return result;
}
}
}

View File

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

View File

@@ -0,0 +1,329 @@
using System;
using System.IO;
using System.Collections.Generic;
using UnityEditor;
using UnityEditor.VersionControl;
using Codice.Client.BaseCommands;
using Codice.Client.Commands;
using Codice.Client.Commands.WkTree;
using Codice.Client.Common;
using Codice.Client.Common.EventTracking;
using Codice.Client.Common.Threading;
using Codice.CM.Common;
using GluonGui;
using PlasticGui;
using PlasticGui.Gluon;
using PlasticGui.WorkspaceWindow;
using PlasticGui.WorkspaceWindow.Diff;
using PlasticGui.WorkspaceWindow.Items;
using Unity.PlasticSCM.Editor.AssetMenu.Dialogs;
using Unity.PlasticSCM.Editor.AssetsOverlays.Cache;
using Unity.PlasticSCM.Editor.AssetUtils;
using Unity.PlasticSCM.Editor.AssetUtils.Processor;
using Unity.PlasticSCM.Editor.Tool;
using Unity.PlasticSCM.Editor.UI;
using Unity.PlasticSCM.Editor.Views.PendingChanges.Dialogs;
using GluonCheckoutOperation = GluonGui.WorkspaceWindow.Views.WorkspaceExplorer.Explorer.Operations.CheckoutOperation;
using GluonUndoCheckoutOperation = GluonGui.WorkspaceWindow.Views.WorkspaceExplorer.Explorer.Operations.UndoCheckoutOperation;
using GluonAddoperation = GluonGui.WorkspaceWindow.Views.WorkspaceExplorer.Explorer.Operations.AddOperation;
namespace Unity.PlasticSCM.Editor.AssetMenu
{
internal class AssetVcsOperations :
IAssetMenuVCSOperations,
IAssetFilesFilterPatternsMenuOperations
{
internal interface IAssetSelection
{
AssetList GetSelectedAssets();
}
internal AssetVcsOperations(
WorkspaceInfo wkInfo,
IPlasticAPI plasticApi,
IWorkspaceWindow workspaceWindow,
IViewSwitcher viewSwitcher,
IHistoryViewLauncher historyViewLauncher,
ViewHost viewHost,
WorkspaceOperationsMonitor workspaceOperationsMonitor,
ISaveAssets saveAssets,
NewIncomingChangesUpdater newIncomingChangesUpdater,
ShelvedChangesUpdater shelvedChangesUpdater,
IAssetStatusCache assetStatusCache,
IMergeViewLauncher mergeViewLauncher,
IGluonViewSwitcher gluonViewSwitcher,
IAssetSelection assetSelection,
LaunchTool.IShowDownloadPlasticExeWindow showDownloadPlasticExeWindow,
bool isGluonMode)
{
mWkInfo = wkInfo;
mPlasticAPI = plasticApi;
mWorkspaceWindow = workspaceWindow;
mViewSwitcher = viewSwitcher;
mHistoryViewLauncher = historyViewLauncher;
mViewHost = viewHost;
mWorkspaceOperationsMonitor = workspaceOperationsMonitor;
mSaveAssets = saveAssets;
mNewIncomingChangesUpdater = newIncomingChangesUpdater;
mShelvedChangesUpdater = shelvedChangesUpdater;
mAssetStatusCache = assetStatusCache;
mMergeViewLauncher = mergeViewLauncher;
mGluonViewSwitcher = gluonViewSwitcher;
mAssetSelection = assetSelection;
mShowDownloadPlasticExeWindow = showDownloadPlasticExeWindow;
mIsGluonMode = isGluonMode;
mGuiMessage = new UnityPlasticGuiMessage();
mProgressControls = new EditorProgressControls(mGuiMessage);
}
void IAssetMenuVCSOperations.ShowPendingChanges()
{
mViewSwitcher.ShowPendingChanges();
}
void IAssetMenuVCSOperations.Add()
{
List<string> selectedPaths = GetSelectedPaths.ForOperation(
mWkInfo,
mAssetSelection.GetSelectedAssets(),
mPlasticAPI,
mAssetStatusCache,
AssetMenuOperations.Add);
if (mIsGluonMode)
{
GluonAddoperation.Add(
mViewHost,
mProgressControls,
mGuiMessage,
selectedPaths.ToArray(),
false,
RefreshAsset.VersionControlCache);
return;
}
AddOperation.Run(
mWorkspaceWindow,
mProgressControls,
null,
null,
selectedPaths,
false,
mNewIncomingChangesUpdater,
mShelvedChangesUpdater,
RefreshAsset.VersionControlCache);
}
void IAssetMenuVCSOperations.Checkout()
{
List<string> selectedPaths = GetSelectedPaths.ForOperation(
mWkInfo,
mAssetSelection.GetSelectedAssets(),
mPlasticAPI,
mAssetStatusCache,
AssetMenuOperations.Checkout);
if (mIsGluonMode)
{
GluonCheckoutOperation.Checkout(
mViewHost,
mProgressControls,
mGuiMessage,
selectedPaths.ToArray(),
false,
RefreshAsset.VersionControlCache,
mWkInfo);
return;
}
CheckoutOperation.Checkout(
mWorkspaceWindow,
null,
mProgressControls,
selectedPaths,
mNewIncomingChangesUpdater,
mShelvedChangesUpdater,
RefreshAsset.VersionControlCache,
mWkInfo);
}
void IAssetMenuVCSOperations.Checkin()
{
List<string> selectedPaths = GetSelectedPaths.ForOperation(
mWkInfo,
mAssetSelection.GetSelectedAssets(),
mPlasticAPI,
mAssetStatusCache,
AssetMenuOperations.Checkin);
if (!CheckinDialog.CheckinPaths(
mWkInfo,
selectedPaths,
mAssetStatusCache,
mIsGluonMode,
mWorkspaceWindow,
mViewHost,
mWorkspaceOperationsMonitor,
mSaveAssets,
mGuiMessage,
mMergeViewLauncher,
mGluonViewSwitcher))
return;
RefreshAsset.UnityAssetDatabase();
}
void IAssetMenuVCSOperations.Undo()
{
List<string> selectedPaths = GetSelectedPaths.ForOperation(
mWkInfo,
mAssetSelection.GetSelectedAssets(),
mPlasticAPI,
mAssetStatusCache,
AssetMenuOperations.Undo);
mSaveAssets.ForPathsWithoutConfirmation(
mWkInfo.ClientPath, selectedPaths, mWorkspaceOperationsMonitor);
if (mIsGluonMode)
{
GluonUndoCheckoutOperation.UndoCheckout(
mWkInfo,
mViewHost,
mProgressControls,
selectedPaths.ToArray(),
false,
RefreshAsset.UnityAssetDatabase);
return;
}
UndoCheckoutOperation.Run(
mWorkspaceWindow,
null,
mProgressControls,
selectedPaths,
mNewIncomingChangesUpdater,
mShelvedChangesUpdater,
RefreshAsset.UnityAssetDatabase);
}
void IAssetMenuVCSOperations.ShowDiff()
{
string selectedPath = AssetsSelection.GetSelectedPath(
mWkInfo.ClientPath,
mAssetSelection.GetSelectedAssets());
DiffInfo diffInfo = null;
IThreadWaiter waiter = ThreadWaiter.GetWaiter(10);
waiter.Execute(
/*threadOperationDelegate*/ delegate
{
string symbolicName = GetSymbolicName(selectedPath);
string extension = Path.GetExtension(selectedPath);
diffInfo = PlasticGui.Plastic.API.BuildDiffInfoForDiffWithPrevious(
selectedPath, symbolicName, selectedPath, extension, mWkInfo);
},
/*afterOperationDelegate*/ delegate
{
if (waiter.Exception != null)
{
ExceptionsHandler.DisplayException(waiter.Exception);
return;
}
DiffOperation.DiffWithPrevious(
diffInfo,
PlasticExeLauncher.BuildForShowDiff(mWkInfo, mIsGluonMode, mShowDownloadPlasticExeWindow),
null);
});
}
void IAssetMenuVCSOperations.ShowHistory()
{
Asset selectedAsset = AssetsSelection.GetSelectedAsset(
mWkInfo.ClientPath,
mAssetSelection.GetSelectedAssets());
string selectedPath = Path.GetFullPath(selectedAsset.path);
WorkspaceTreeNode node = PlasticGui.Plastic.API.
GetWorkspaceTreeNode(selectedPath);
mHistoryViewLauncher.ShowHistoryView(
node.RepSpec,
node.RevInfo.ItemId,
selectedPath,
selectedAsset.isFolder);
}
void IAssetFilesFilterPatternsMenuOperations.AddFilesFilterPatterns(
FilterTypes type,
FilterActions action,
FilterOperationType operation)
{
List<string> selectedPaths = AssetsSelection.GetSelectedPaths(
mWkInfo.ClientPath,
mAssetSelection.GetSelectedAssets());
string[] rules = FilterRulesGenerator.GenerateRules(
selectedPaths, mWkInfo.ClientPath, action, operation);
bool isApplicableToAllWorkspaces = !mIsGluonMode;
bool isAddOperation = operation == FilterOperationType.Add;
FilterRulesConfirmationData filterRulesConfirmationData =
FilterRulesConfirmationDialog.AskForConfirmation(
rules, isAddOperation, isApplicableToAllWorkspaces, EditorWindow.focusedWindow);
AddFilesFilterPatternsOperation.Run(
mWkInfo, mWorkspaceWindow, type, operation, filterRulesConfirmationData);
}
static string GetSymbolicName(string selectedPath)
{
WorkspaceTreeNode node = PlasticGui.Plastic.API.
GetWorkspaceTreeNode(selectedPath);
string branchName = string.Empty;
BranchInfoCache.TryGetBranchName(
node.RepSpec, node.RevInfo.BranchId, out branchName);
string userName = PlasticGui.Plastic.API.GetUserName(
node.RepSpec.Server, node.RevInfo.Owner);
string symbolicName = string.Format(
"cs:{0}@{1} {2} {3}",
node.RevInfo.Changeset,
string.Format("br:{0}", branchName),
userName,
"Workspace Revision");
return symbolicName;
}
readonly WorkspaceInfo mWkInfo;
readonly IPlasticAPI mPlasticAPI;
readonly IViewSwitcher mViewSwitcher;
readonly IHistoryViewLauncher mHistoryViewLauncher;
readonly IWorkspaceWindow mWorkspaceWindow;
readonly ViewHost mViewHost;
readonly WorkspaceOperationsMonitor mWorkspaceOperationsMonitor;
readonly ISaveAssets mSaveAssets;
readonly NewIncomingChangesUpdater mNewIncomingChangesUpdater;
readonly ShelvedChangesUpdater mShelvedChangesUpdater;
readonly IAssetStatusCache mAssetStatusCache;
readonly IMergeViewLauncher mMergeViewLauncher;
readonly IGluonViewSwitcher mGluonViewSwitcher;
readonly bool mIsGluonMode;
readonly GuiMessage.IGuiMessage mGuiMessage;
readonly EditorProgressControls mProgressControls;
readonly IAssetSelection mAssetSelection;
readonly LaunchTool.IShowDownloadPlasticExeWindow mShowDownloadPlasticExeWindow;
}
}

View File

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

View File

@@ -0,0 +1,141 @@
using System.Collections.Generic;
using System.IO;
using UnityEditor.VersionControl;
using PlasticGui.WorkspaceWindow.Items;
using Unity.PlasticSCM.Editor.AssetsOverlays;
using Unity.PlasticSCM.Editor.AssetsOverlays.Cache;
using Unity.PlasticSCM.Editor.AssetUtils;
namespace Unity.PlasticSCM.Editor.AssetMenu
{
internal static class AssetsSelection
{
internal static Asset GetSelectedAsset(
string wkPath,
AssetList assetList)
{
if (assetList.Count == 0)
return null;
foreach (Asset asset in assetList)
{
if (AssetsPath.GetFullPathUnderWorkspace.
ForAsset(wkPath, asset.path) == null)
continue;
return asset;
}
return null;
}
internal static string GetSelectedPath(
string wkPath,
AssetList assetList)
{
Asset result = GetSelectedAsset(wkPath, assetList);
if (result == null)
return null;
return Path.GetFullPath(result.path);
}
internal static List<string> GetSelectedPaths(
string wkPath,
IEnumerable<Asset> assetList)
{
List<string> result = new List<string>();
foreach (Asset asset in assetList)
{
string fullPath = AssetsPath.GetFullPathUnderWorkspace.
ForAsset(wkPath, asset.path);
if (fullPath == null)
continue;
result.Add(fullPath);
}
return result;
}
internal static SelectedPathsGroupInfo GetSelectedPathsGroupInfo(
string wkPath,
AssetList assetList,
IAssetStatusCache statusCache)
{
SelectedPathsGroupInfo result = new SelectedPathsGroupInfo();
if (assetList.Count == 0)
return result;
result.IsRootSelected = false;
result.IsCheckedoutEverySelected = true;
result.IsDirectoryEverySelected = true;
result.IsCheckedinEverySelected = true;
result.IsChangedEverySelected = true;
foreach (Asset asset in assetList)
{
string fullPath = AssetsPath.GetFullPathUnderWorkspace.
ForAsset(wkPath, asset.path);
if (fullPath == null)
continue;
if (MetaPath.IsMetaPath(fullPath))
fullPath = MetaPath.GetPathFromMetaPath(fullPath);
AssetStatus status = statusCache.GetStatus(fullPath);
string assetName = GetAssetName(asset);
result.IsCheckedoutEverySelected &= ClassifyAssetStatus.IsCheckedOut(status);
result.IsDirectoryEverySelected &= asset.isFolder;
result.IsCheckedinEverySelected &= false; // TODO: not implemented yet
result.IsChangedEverySelected &= false; // TODO: not implemented yet
result.IsAnyDirectorySelected |= asset.isFolder;
result.IsAnyPrivateSelected |= ClassifyAssetStatus.IsPrivate(status) || ClassifyAssetStatus.IsIgnored(status);
result.FilterInfo.IsAnyIgnoredSelected |= ClassifyAssetStatus.IsIgnored(status);
result.FilterInfo.IsAnyHiddenChangedSelected |= ClassifyAssetStatus.IsHiddenChanged(status);
result.SelectedCount++;
if (result.SelectedCount == 1)
{
result.FirstIsControlled = ClassifyAssetStatus.IsControlled(status);
result.FirstIsDirectory = asset.isFolder;
result.FilterInfo.CommonName = assetName;
result.FilterInfo.CommonExtension = Path.GetExtension(assetName);
result.FilterInfo.CommonFullPath = asset.assetPath;
continue;
}
if (result.FilterInfo.CommonName != assetName)
result.FilterInfo.CommonName = null;
if (result.FilterInfo.CommonExtension != Path.GetExtension(assetName))
result.FilterInfo.CommonExtension = null;
if (result.FilterInfo.CommonFullPath != asset.assetPath)
result.FilterInfo.CommonFullPath = null;
}
return result;
}
static string GetAssetName(Asset asset)
{
if (asset.isFolder)
return Path.GetFileName(Path.GetDirectoryName(asset.path));
return asset.fullName;
}
}
}

View File

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

View File

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

View File

@@ -0,0 +1,401 @@
using System.Collections.Generic;
using System.IO;
using UnityEditor;
using UnityEngine;
using Codice.Client.Common;
using Codice.Client.Common.EventTracking;
using Codice.CM.Common;
using GluonGui;
using PlasticGui;
using PlasticGui.Gluon;
using Unity.PlasticSCM.Editor.AssetsOverlays;
using Unity.PlasticSCM.Editor.AssetsOverlays.Cache;
using Unity.PlasticSCM.Editor.AssetUtils;
using Unity.PlasticSCM.Editor.AssetUtils.Processor;
using Unity.PlasticSCM.Editor.UI;
using Unity.PlasticSCM.Editor.UI.Progress;
using Unity.PlasticSCM.Editor.UI.Tree;
namespace Unity.PlasticSCM.Editor.AssetMenu.Dialogs
{
internal class CheckinDialog : PlasticDialog
{
protected override Rect DefaultRect
{
get
{
var baseRect = base.DefaultRect;
return new Rect(baseRect.x, baseRect.y, 700, 450);
}
}
protected override string GetTitle()
{
return PlasticLocalization.GetString(
PlasticLocalization.Name.CheckinChanges);
}
internal static bool CheckinPaths(
WorkspaceInfo wkInfo,
List<string> paths,
IAssetStatusCache assetStatusCache,
bool isGluonMode,
IWorkspaceWindow workspaceWindow,
ViewHost viewHost,
WorkspaceOperationsMonitor workspaceOperationsMonitor,
ISaveAssets saveAssets,
GuiMessage.IGuiMessage guiMessage,
IMergeViewLauncher mergeViewLauncher,
IGluonViewSwitcher gluonViewSwitcher)
{
MetaCache metaCache = new MetaCache();
metaCache.Build(paths);
CheckinDialog dialog = Create(
wkInfo,
paths,
assetStatusCache,
metaCache,
isGluonMode,
new ProgressControlsForDialogs(),
workspaceWindow,
viewHost,
workspaceOperationsMonitor,
saveAssets,
guiMessage,
mergeViewLauncher,
gluonViewSwitcher);
return dialog.RunModal(focusedWindow) == ResponseType.Ok;
}
protected override void OnModalGUI()
{
Title(PlasticLocalization.GetString(PlasticLocalization.Name.CheckinOnlyComment));
GUI.SetNextControlName(CHECKIN_TEXTAREA_NAME);
mComment = GUILayout.TextArea(
mComment,
EditorStyles.textArea,
GUILayout.MinHeight(120));
if (!mTextAreaFocused)
{
EditorGUI.FocusTextInControl(CHECKIN_TEXTAREA_NAME);
mTextAreaFocused = true;
}
Title(PlasticLocalization.GetString(PlasticLocalization.Name.Files));
DoFileList(
mWkInfo,
mPaths,
mAssetStatusCache,
mMetaCache);
DrawProgressForDialogs.For(
mProgressControls.ProgressData);
DoButtonsArea();
mProgressControls.ForcedUpdateProgress(this);
}
void DoFileList(
WorkspaceInfo wkInfo,
List<string> paths,
IAssetStatusCache assetStatusCache,
MetaCache metaCache)
{
mFileListScrollPosition = GUILayout.BeginScrollView(
mFileListScrollPosition,
EditorStyles.helpBox,
GUILayout.ExpandHeight(true));
foreach (string path in paths)
{
if (MetaPath.IsMetaPath(path))
continue;
Texture fileIcon = Directory.Exists(path) ?
Images.GetDirectoryIcon() :
Images.GetFileIcon(path);
string label = WorkspacePath.GetWorkspaceRelativePath(
wkInfo.ClientPath, path);
if (metaCache.HasMeta(path))
label = string.Concat(label, UnityConstants.TREEVIEW_META_LABEL);
AssetsOverlays.AssetStatus assetStatus =
assetStatusCache.GetStatus(path);
Rect selectionRect = EditorGUILayout.GetControlRect();
DoListViewItem(selectionRect, fileIcon, label, assetStatus);
}
GUILayout.EndScrollView();
}
void DoListViewItem(
Rect itemRect,
Texture fileIcon,
string label,
AssetsOverlays.AssetStatus statusToDraw)
{
Texture overlayIcon = DrawAssetOverlay.DrawOverlayIcon.
GetOverlayIcon(statusToDraw);
itemRect = DrawTreeViewItem.DrawIconLeft(
itemRect,
UnityConstants.TREEVIEW_ROW_HEIGHT,
fileIcon,
overlayIcon);
GUI.Label(itemRect, label);
}
void DoButtonsArea()
{
using (new EditorGUILayout.HorizontalScope())
{
GUILayout.FlexibleSpace();
if (Application.platform == RuntimePlatform.WindowsEditor)
{
DoCheckinButton();
DoCancelButton();
return;
}
DoCancelButton();
DoCheckinButton();
}
}
void DoCheckinButton()
{
GUI.enabled = IsCheckinButtonEnabled();
try
{
if (!AcceptButton(PlasticLocalization.GetString(
PlasticLocalization.Name.CheckinButton)))
return;
}
finally
{
if (!mSentCheckinTrackEvent)
{
TrackFeatureUseEvent.For(
PlasticGui.Plastic.API.GetRepositorySpec(mWkInfo),
TrackFeatureUseEvent.Features.ContextMenuCheckinDialogCheckin);
mSentCheckinTrackEvent = true;
}
GUI.enabled = true;
}
OkButtonWithCheckinAction();
}
void DoCancelButton()
{
if (!NormalButton(PlasticLocalization.GetString(
PlasticLocalization.Name.CancelButton)))
return;
if (!mSentCancelTrackEvent)
{
TrackFeatureUseEvent.For(
PlasticGui.Plastic.API.GetRepositorySpec(mWkInfo),
TrackFeatureUseEvent.Features.ContextMenuCheckinDialogCancel);
mSentCancelTrackEvent = true;
}
CancelButtonAction();
}
void OkButtonWithCheckinAction()
{
if (!IsCheckinButtonEnabled())
return;
bool isCancelled;
mSaveAssets.ForPathsWithConfirmation(
mWkInfo.ClientPath, mPaths, mWorkspaceOperationsMonitor,
out isCancelled);
if (isCancelled)
return;
mIsRunningCheckin = true;
mPaths.AddRange(mMetaCache.GetExistingMeta(mPaths));
if (mIsGluonMode)
{
CheckinDialogOperations.CheckinPathsPartial(
mWkInfo,
mPaths,
mComment,
mViewHost,
this,
mGuiMessage,
mProgressControls,
mGluonViewSwitcher);
return;
}
CheckinDialogOperations.CheckinPaths(
mWkInfo,
mPaths,
mComment,
mWorkspaceWindow,
this,
mGuiMessage,
mProgressControls,
mMergeViewLauncher);
}
bool IsCheckinButtonEnabled()
{
return !string.IsNullOrEmpty(mComment) && !mIsRunningCheckin;
}
static CheckinDialog Create(
WorkspaceInfo wkInfo,
List<string> paths,
IAssetStatusCache assetStatusCache,
MetaCache metaCache,
bool isGluonMode,
ProgressControlsForDialogs progressControls,
IWorkspaceWindow workspaceWindow,
ViewHost viewHost,
WorkspaceOperationsMonitor workspaceOperationsMonitor,
ISaveAssets saveAssets,
GuiMessage.IGuiMessage guiMessage,
IMergeViewLauncher mergeViewLauncher,
IGluonViewSwitcher gluonViewSwitcher)
{
var instance = CreateInstance<CheckinDialog>();
instance.IsResizable = true;
instance.minSize = new Vector2(520, 370);
instance.mWkInfo = wkInfo;
instance.mPaths = paths;
instance.mAssetStatusCache = assetStatusCache;
instance.mMetaCache = metaCache;
instance.mIsGluonMode = isGluonMode;
instance.mProgressControls = progressControls;
instance.mWorkspaceWindow = workspaceWindow;
instance.mViewHost = viewHost;
instance.mWorkspaceOperationsMonitor = workspaceOperationsMonitor;
instance.mSaveAssets = saveAssets;
instance.mGuiMessage = guiMessage;
instance.mMergeViewLauncher = mergeViewLauncher;
instance.mGluonViewSwitcher = gluonViewSwitcher;
instance.mEnterKeyAction = instance.OkButtonWithCheckinAction;
instance.AddControlConsumingEnterKey(CHECKIN_TEXTAREA_NAME);
instance.mEscapeKeyAction = instance.CancelButtonAction;
return instance;
}
WorkspaceInfo mWkInfo;
List<string> mPaths;
IAssetStatusCache mAssetStatusCache;
MetaCache mMetaCache;
bool mIsGluonMode;
bool mTextAreaFocused;
string mComment;
bool mIsRunningCheckin;
Vector2 mFileListScrollPosition;
// IMGUI evaluates every frame, need to make sure feature tracks get sent only once
bool mSentCheckinTrackEvent = false;
bool mSentCancelTrackEvent = false;
ProgressControlsForDialogs mProgressControls;
IWorkspaceWindow mWorkspaceWindow;
WorkspaceOperationsMonitor mWorkspaceOperationsMonitor;
ISaveAssets mSaveAssets;
ViewHost mViewHost;
IMergeViewLauncher mMergeViewLauncher;
IGluonViewSwitcher mGluonViewSwitcher;
GuiMessage.IGuiMessage mGuiMessage;
const string CHECKIN_TEXTAREA_NAME = "checkin_textarea";
class MetaCache
{
internal bool HasMeta(string path)
{
return mCache.Contains(MetaPath.GetMetaPath(path));
}
internal List<string> GetExistingMeta(List<string> paths)
{
List<string> result = new List<string>();
foreach (string path in paths)
{
string metaPath = MetaPath.GetMetaPath(path);
if (!mCache.Contains(metaPath))
continue;
result.Add(metaPath);
}
return result;
}
internal void Build(List<string> paths)
{
HashSet<string> indexedKeys = BuildIndexedKeys(paths);
for (int i = paths.Count - 1; i >= 0; i--)
{
string currentPath = paths[i];
if (!MetaPath.IsMetaPath(currentPath))
continue;
string realPath = MetaPath.GetPathFromMetaPath(currentPath);
if (!indexedKeys.Contains(realPath))
continue;
// found foo.c and foo.c.meta
// with the same chage types - move .meta to cache
mCache.Add(currentPath);
paths.RemoveAt(i);
}
}
static HashSet<string> BuildIndexedKeys(List<string> paths)
{
HashSet<string> result = new HashSet<string>();
foreach (string path in paths)
{
if (MetaPath.IsMetaPath(path))
continue;
result.Add(path);
}
return result;
}
HashSet<string> mCache = new HashSet<string>();
}
}
}

View File

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

View File

@@ -0,0 +1,148 @@
using System;
using System.Collections.Generic;
using Codice.Client.BaseCommands;
using Codice.Client.Commands.CheckIn;
using Codice.Client.Common;
using Codice.Client.Common.Threading;
using Codice.Client.GameUI.Checkin;
using Codice.CM.Common;
using Codice.CM.Common.Checkin.Partial;
using GluonGui;
using PlasticGui;
using PlasticGui.Gluon;
using PlasticGui.WorkspaceWindow.PendingChanges;
namespace Unity.PlasticSCM.Editor.AssetMenu.Dialogs
{
internal static class CheckinDialogOperations
{
internal static void CheckinPaths(
WorkspaceInfo wkInfo,
List<string> paths,
string comment,
IWorkspaceWindow workspaceWindow,
CheckinDialog dialog,
GuiMessage.IGuiMessage guiMessage,
IProgressControls progressControls,
IMergeViewLauncher mergeViewLauncher)
{
BaseCommandsImpl baseCommands = new BaseCommandsImpl();
progressControls.ShowProgress("Checkin in files");
IThreadWaiter waiter = ThreadWaiter.GetWaiter(50);
waiter.Execute(
/*threadOperationDelegate*/ delegate
{
CheckinParams ciParams = new CheckinParams();
ciParams.paths = paths.ToArray();
ciParams.comment = comment;
ciParams.time = DateTime.MinValue;
ciParams.flags = CheckinFlags.Recurse | CheckinFlags.ProcessSymlinks;
baseCommands.CheckIn(ciParams);
},
/*afterOperationDelegate*/ delegate
{
progressControls.HideProgress();
((IPlasticDialogCloser)dialog).CloseDialog();
if (waiter.Exception is CmClientMergeNeededException)
{
// we need to explicitly call EditorWindow.Close() to ensure
// that the dialog is closed before asking the user
dialog.Close();
if (!UserWantsToShowIncomingView(guiMessage))
return;
ShowIncomingChanges.FromCheckin(
wkInfo,
mergeViewLauncher,
progressControls);
return;
}
if (waiter.Exception != null)
{
ExceptionsHandler.DisplayException(waiter.Exception);
return;
}
workspaceWindow.RefreshView(ViewType.PendingChangesView);
workspaceWindow.RefreshView(ViewType.HistoryView);
workspaceWindow.RefreshView(ViewType.BranchesView);
workspaceWindow.RefreshView(ViewType.ChangesetsView);
workspaceWindow.RefreshView(ViewType.LocksView);
});
}
internal static void CheckinPathsPartial(
WorkspaceInfo wkInfo,
List<string> paths,
string comment,
ViewHost viewHost,
CheckinDialog dialog,
GuiMessage.IGuiMessage guiMessage,
IProgressControls progressControls,
IGluonViewSwitcher gluonViewSwitcher)
{
BaseCommandsImpl baseCommands = new BaseCommandsImpl();
progressControls.ShowProgress(PlasticLocalization.GetString(
PlasticLocalization.Name.CheckinInFilesProgress));
IThreadWaiter waiter = ThreadWaiter.GetWaiter(50);
waiter.Execute(
/*threadOperationDelegate*/ delegate
{
baseCommands.PartialCheckin(wkInfo, paths, comment);
},
/*afterOperationDelegate*/ delegate
{
progressControls.HideProgress();
((IPlasticDialogCloser)dialog).CloseDialog();
if (waiter.Exception is CheckinConflictsException)
{
// we need to explicitly call EditorWindow.Close() to ensure
// that the dialog is closed before asking the user
dialog.Close();
if (!UserWantsToShowIncomingView(guiMessage))
return;
gluonViewSwitcher.ShowIncomingChangesView();
return;
}
if (waiter.Exception != null)
{
ExceptionsHandler.DisplayException(waiter.Exception);
return;
}
viewHost.RefreshView(ViewType.CheckinView);
viewHost.RefreshView(ViewType.HistoryView);
viewHost.RefreshView(ViewType.LocksView);
});
}
static bool UserWantsToShowIncomingView(GuiMessage.IGuiMessage guiMessage)
{
GuiMessage.GuiMessageResponseButton result = guiMessage.ShowQuestion(
PlasticLocalization.GetString(PlasticLocalization.Name.CheckinConflictsTitle),
PlasticLocalization.GetString(PlasticLocalization.Name.UnityCheckinConflictsExplanation),
PlasticLocalization.GetString(PlasticLocalization.Name.CheckinShowIncomingChangesView),
PlasticLocalization.GetString(PlasticLocalization.Name.CancelButton),
null);
return result == GuiMessage.GuiMessageResponseButton.Positive;
}
}
}

View File

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

View File

@@ -0,0 +1,61 @@
using System;
using UnityEditor;
using UnityEditor.VersionControl;
using Unity.PlasticSCM.Editor.AssetUtils;
namespace Unity.PlasticSCM.Editor.AssetMenu
{
internal class ProjectViewAssetSelection : AssetVcsOperations.IAssetSelection
{
internal ProjectViewAssetSelection(Action assetSelectionChangedAction)
{
mAssetSelectionChangedAction = assetSelectionChangedAction;
Selection.selectionChanged += SelectionChanged;
}
internal void Dispose()
{
Selection.selectionChanged -= SelectionChanged;
}
void SelectionChanged()
{
// Selection.selectionChanged gets triggered on both
// project view and scene view. We only want to trigger
// the action if user selects on project view (has assets)
if (HasSelectedAssets())
mAssetSelectionChangedAction();
}
AssetList AssetVcsOperations.IAssetSelection.GetSelectedAssets()
{
if (Selection.assetGUIDs.Length == 0)
return new AssetList();
AssetList result = new AssetList();
foreach (string guid in Selection.assetGUIDs)
{
string assetPath = AssetsPath.GetFullPath.ForGuid(guid);
if (string.IsNullOrEmpty(assetPath))
continue;
result.Add(new Asset(assetPath));
}
return result;
}
bool HasSelectedAssets()
{
// Objects in project view have GUIDs, objects in scene view don't
return Selection.assetGUIDs.Length > 0;
}
Action mAssetSelectionChangedAction;
}
}

View File

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