Adaug proiectul Unity

This commit is contained in:
2026-11-01 23:39:55 +02:00
parent cb14d9d37d
commit 863eac8f2c
23463 changed files with 5412601 additions and 0 deletions
@@ -0,0 +1,796 @@
using System;
using System.Collections.Generic;
using System.IO;
using UnityEditor;
using UnityEngine;
using Codice.Client.Common;
using Codice.Client.Common.EventTracking;
using Codice.Client.Common.WebApi;
using Codice.CM.Common;
using PlasticGui;
using PlasticGui.CloudDrive;
using PlasticGui.CloudDrive.Workspaces;
using PlasticGui.WorkspaceWindow.Items;
using Unity.PlasticSCM.Editor.AssetUtils;
using Unity.PlasticSCM.Editor.UI;
using Unity.PlasticSCM.Editor.CloudDrive.CreateWorkspace;
using Unity.PlasticSCM.Editor.CloudDrive.Workspaces.DirectoryContent;
using Unity.PlasticSCM.Editor.CloudDrive.Workspaces.DragAndDrop;
using Unity.PlasticSCM.Editor.CloudDrive.Workspaces.Tree;
using Unity.PlasticSCM.Editor.UI.Errors;
using Unity.PlasticSCM.Editor.UI.Progress;
#if !UNITY_6000_3_OR_NEWER
using SplitterGUILayout = Unity.PlasticSCM.Editor.UnityInternals.UnityEditor.SplitterGUILayout;
using SplitterState = Unity.PlasticSCM.Editor.UnityInternals.UnityEditor.SplitterState;
#endif
namespace Unity.PlasticSCM.Editor.CloudDrive.Workspaces
{
internal interface IDragAndDrop
{
List<string> GetDragSourcePaths();
void ClearDragTargetPath();
void SetDragTargetPath(string path);
void ExecuteDropAction(string[] paths);
}
internal class CloudWorkspacesView :
IRefreshableView,
INotifyUpdatePaths,
FillOrganizationsAndProjects.INotify,
ICloudWorkspacesOperations,
IDragAndDrop
{
internal const float MIN_WIDTH =
TREE_VIEW_MIN_SIZE +
SPLITTER_WIDTH +
DIRECTORY_CONTENT_MIN_SIZE;
internal CloudWorkspacesView(
string proposedCloudServer,
string proposedProject,
WorkspaceInfo workspaceToSelect,
IPlasticWebRestApi restApi,
IPlasticAPI plasticApi,
IProgressControls progressControls,
EditorWindow parentWindow)
{
mRestApi = restApi;
mPlasticApi = plasticApi;
mProgressControls = progressControls;
mParentWindow = parentWindow;
mFillCloudWorkspacesView = new FillCloudWorkspaces();
InitializeProposedOrganizationProject(proposedCloudServer, proposedProject);
BuildComponents(workspaceToSelect, parentWindow);
mSplitterState = new SplitterState(
SplitterSettings.Load(
UnityConstants.CLOUD_WORKSPACES_SPLITTER_SETTINGS_NAME,
new float[] { 0.25f, 0.75f }),
new int[] { TREE_VIEW_MIN_SIZE, DIRECTORY_CONTENT_MIN_SIZE },
new int[] { 100000, 100000 }
);
#if UNITY_6000_3_OR_NEWER
UnityEditor.DragAndDrop.AddDropHandlerV2(ProjectBrowserDropHandler);
#else
UnityEditor.DragAndDrop.AddDropHandler(ProjectBrowserDropHandler);
#endif
Refresh();
}
internal void SelectWorkspaceAndCopyPaths(
string organization,
string project,
WorkspaceInfo wkInfo,
string[] assetPaths,
string dstRelativePath)
{
OnOrganizationSelected(organization);
OnProjectSelected(project);
mCloudWorkspacesTreeView.WorkspaceToSelect = wkInfo;
mCloudWorkspacesTreeView.Reload();
TrackFeatureUseEvent.For(
PlasticGui.Plastic.API.GetRepositorySpec(wkInfo),
TrackFeatureUseEvent.Features.UnityPackage.AddAssetsToCloudDrive);
CopyPaths(
assetPaths,
AssetsPath.GetFullPath.ForPath(string.Concat(wkInfo.ClientPath, dstRelativePath)),
mCloudWorkspacesTreeView,
wkInfo,
mParentWindow,
this,
beforeStartingOperationDelegate: null,
endOperationDelegate: null,
shouldRefreshView: true);
}
internal bool IsOperationRunning()
{
return mCloudWorkspacesTreeView.IsOperationRunning();
}
internal void AutoRefresh()
{
Refresh();
}
internal void OnGUI(Rect rect, bool hasFocus)
{
Event e = Event.current;
if (ProcessTabKeyActionIfNeeded(e, mCloudWorkspacesTreeView))
e.Use();
if (ProcessF5KeyActionIfNeeded(e, this))
e.Use();
UpdateDirectoryContentFocusIfNeeded(
e, mCloudWorkspacesTreeView, mDirectoryContentPanel.Rect);
DoContentArea(
mCloudWorkspacesTreeView,
mDirectoryContentPanel,
mSplitterState,
rect.width,
rect.height - EditorStyles.toolbar.fixedHeight,
hasFocus);
DoToolbar(
GetToolbarRect(rect),
mCloudWorkspacesTreeView.Width,
mOrganizations,
mProjects,
this);
}
internal void OnEnable()
{
#if UNITY_6000_3_OR_NEWER
UnityEditor.DragAndDrop.AddDropHandlerV2(ProjectBrowserDropHandler);
#else
UnityEditor.DragAndDrop.AddDropHandler(ProjectBrowserDropHandler);
#endif
}
internal void OnDisable()
{
#if UNITY_6000_3_OR_NEWER
UnityEditor.DragAndDrop.RemoveDropHandlerV2(ProjectBrowserDropHandler);
#else
UnityEditor.DragAndDrop.RemoveDropHandler(ProjectBrowserDropHandler);
#endif
SplitterSettings.Save(
mSplitterState,
UnityConstants.CLOUD_WORKSPACES_SPLITTER_SETTINGS_NAME);
}
internal void Update(EditorWindow parentWindow)
{
mCloudWorkspacesTreeView.Update(parentWindow);
}
void IRefreshableView.Refresh()
{
Refresh();
}
void INotifyUpdatePaths.RefreshViewSilently()
{
mFillCloudWorkspacesView.LoadExpandedTrees(
mSelectedOrganization,
mSelectedProject,
mCloudWorkspacesTreeView,
progressControls: null);
}
void INotifyUpdatePaths.ShowErrors(string wkName, List<ErrorMessage> errors)
{
ErrorsDialog.ShowDialog(
PlasticLocalization.Name.CopyFileErrorsTitle.GetString(),
PlasticLocalization.Name.CopyFileErrorsMessage.GetString(wkName),
errors,
mParentWindow);
}
void FillOrganizationsAndProjects.INotify.OrganizationsRetrieved(List<string> organizations)
{
mOrganizations = organizations;
mSelectedOrganization = GetDefaultValue(mProposedOrganization, mOrganizations);
if (mSelectedOrganization == null)
return;
OnOrganizationSelected(mSelectedOrganization);
}
void FillOrganizationsAndProjects.INotify.ProjectsRetrieved(List<string> projects)
{
mProjects = projects;
mProjects.Insert(0, PlasticLocalization.Name.AllProjects.GetString());
mProjects.Insert(1, string.Empty);
mSelectedProject = GetDefaultValue(mProposedProject, mProjects);
if (mSelectedProject == null)
return;
OnProjectSelected(mSelectedProject);
}
List<string> IDragAndDrop.GetDragSourcePaths()
{
return mDirectoryContentPanel.ItemsGridView.GetSelectedItemsPaths();
}
void IDragAndDrop.ClearDragTargetPath()
{
mDragTargetPath = null;
}
void IDragAndDrop.SetDragTargetPath(string path)
{
mDragTargetPath = path;
}
void IDragAndDrop.ExecuteDropAction(string[] paths)
{
WorkspaceInfo wkInfo = mCloudWorkspacesTreeView.GetSelectedWorkspaceInfo();
TrackFeatureUseEvent.For(
PlasticGui.Plastic.API.GetRepositorySpec(wkInfo),
TrackFeatureUseEvent.Features.UnityPackage.CloudDriveDragToWindow);
CopyPaths(
paths,
mDragTargetPath,
mCloudWorkspacesTreeView,
wkInfo,
mParentWindow,
this,
beforeStartingOperationDelegate: null,
endOperationDelegate: null,
shouldRefreshView: true);
}
void ICloudWorkspacesOperations.DeleteItems(List<string> paths)
{
WorkspaceInfo wkInfo = mCloudWorkspacesTreeView.GetSelectedWorkspaceInfo();
ProgressControlsForViews workspaceProgressControls =
mCloudWorkspacesTreeView.GetWorkspaceProgressControls(wkInfo);
if (workspaceProgressControls.IsOperationRunning())
{
GuiMessage.ShowInformation(PlasticLocalization.Name.OperationInProgress.GetString());
return;
}
DeletePathsOperation.DeleteRecursively(
paths.ToArray(),
Path.GetFileName(wkInfo.ClientPath),
this,
workspaceProgressControls);
}
void ICloudWorkspacesOperations.ImportInProject(string[] paths, string projectPath)
{
WorkspaceInfo wkInfo = mCloudWorkspacesTreeView.GetSelectedWorkspaceInfo();
TrackFeatureUseEvent.For(
PlasticGui.Plastic.API.GetRepositorySpec(wkInfo),
TrackFeatureUseEvent.Features.UnityPackage.CloudDriveImportToProject);
CopyPaths(
paths,
AssetsPath.GetFullPath.ForPath(string.Join(ProjectPath.Get(), projectPath)),
mCloudWorkspacesTreeView,
wkInfo,
mParentWindow,
this,
BeforeCopyPathsForProjectBrowserDropAction,
AfterCopyPathsForProjectBrowserDropAction,
shouldRefreshView: false);
}
void Refresh()
{
FillOrganizationsAndProjects.LoadOrganizations(
mRestApi, mPlasticApi, mProgressControls, this);
RefreshTree();
}
void RefreshTree()
{
mFillCloudWorkspacesView.LoadExpandedTrees(
mSelectedOrganization,
mSelectedProject,
mCloudWorkspacesTreeView,
mProgressControls);
}
void OnTreeViewSelectionChanged()
{
List<ExpandedTreeNode> selectedNodes = CloudWorkspacesSelection.
GetSelectedNodes(mCloudWorkspacesTreeView);
if (selectedNodes.Count != 1)
{
mDirectoryContentPanel.CleanItems();
return;
}
mDirectoryContentPanel.UpdateItemsForDirectory(selectedNodes[0]);
}
DragAndDropVisualMode ProjectBrowserDropHandler(
#if UNITY_6000_3_OR_NEWER
EntityId dragEntityId, string dropUponPath, bool perform)
#else
int dragInstanceId, string dropUponPath, bool perform)
#endif
{
if (perform == false)
return DragAndDropVisualMode.None;
if (UnityEditor.DragAndDrop.objectReferences.Length == 0 ||
UnityEditor.DragAndDrop.objectReferences[0] != mParentWindow)
return DragAndDropVisualMode.None;
WorkspaceInfo wkInfo = mCloudWorkspacesTreeView.GetSelectedWorkspaceInfo();
TrackFeatureUseEvent.For(
PlasticGui.Plastic.API.GetRepositorySpec(wkInfo),
TrackFeatureUseEvent.Features.UnityPackage.CloudDriveDragToProjectView);
CopyPaths(
UnityEditor.DragAndDrop.paths,
AssetsPath.GetFullPath.ForPath(dropUponPath),
mCloudWorkspacesTreeView,
wkInfo,
mParentWindow,
this,
BeforeCopyPathsForProjectBrowserDropAction,
AfterCopyPathsForProjectBrowserDropAction,
shouldRefreshView: false);
return DragAndDropVisualMode.Copy;
}
void BeforeCopyPathsForProjectBrowserDropAction()
{
if (mCopyPathsForProjectBrowserDropCount == 0)
RefreshAsset.BeforeLongAssetOperation();
mCopyPathsForProjectBrowserDropCount++;
}
void AfterCopyPathsForProjectBrowserDropAction()
{
if (mCopyPathsForProjectBrowserDropCount == 1)
RefreshAsset.AfterLongAssetOperation();
mCopyPathsForProjectBrowserDropCount--;
}
void OnOrganizationSelected(object organization)
{
mSelectedOrganization = organization.ToString();
mProposedOrganization = mSelectedOrganization;
mSelectedProject = null;
PlasticGuiConfig.Get().Configuration.LastUsedCloudDriveServer = mSelectedOrganization;
PlasticGuiConfig.Get().Save();
mProjects.Clear();
if (!CloudServer.IsUnityOrganization(mSelectedOrganization))
{
OnProjectSelected(string.Empty);
return;
}
FillOrganizationsAndProjects.LoadProjects(
mSelectedOrganization, mPlasticApi, mProgressControls, this);
}
void OnProjectSelected(object project)
{
mSelectedProject = project.ToString();
mProposedProject = mSelectedProject;
PlasticGuiConfig.Get().Configuration.LastUsedCloudDriveProject = mSelectedProject;
PlasticGuiConfig.Get().Save();
RefreshTree();
}
static void CopyPaths(
string[] paths,
string targetPath,
CloudWorkspacesTreeView cloudWorkspacesTreeView,
WorkspaceInfo wkInfo,
EditorWindow parentWindow,
INotifyUpdatePaths notify,
Action beforeStartingOperationDelegate,
Action endOperationDelegate,
bool shouldRefreshView)
{
ProgressControlsForViews workspaceProgressControls =
cloudWorkspacesTreeView.GetWorkspaceProgressControls(wkInfo);
if (workspaceProgressControls.IsOperationRunning())
{
GuiMessage.ShowInformation(PlasticLocalization.Name.OperationInProgress.GetString());
return;
}
CopyPathsOperation.CopyRecursivelyTo(
paths,
targetPath,
Path.GetFileName(wkInfo.ClientPath),
new AskUserForExistingFile(parentWindow),
notify,
workspaceProgressControls,
beforeStartingOperationDelegate,
endOperationDelegate,
shouldRefreshView);
}
static bool ProcessTabKeyActionIfNeeded(
Event e,
CloudWorkspacesTreeView treeView)
{
if (!Keyboard.IsTabPressed(e))
return false;
if (!treeView.HasFocus())
{
treeView.SetFocus();
return true;
}
GUI.FocusControl(null);
return true;
}
static bool ProcessF5KeyActionIfNeeded(
Event e,
IRefreshableView view)
{
if (!Keyboard.IsKeyPressed(e, KeyCode.F5))
return false;
view.Refresh();
return true;
}
static void UpdateDirectoryContentFocusIfNeeded(
Event e,
CloudWorkspacesTreeView treeView,
Rect directoryContentRect)
{
if (e.type != EventType.MouseDown)
return;
if (!directoryContentRect.Contains(e.mousePosition))
return;
if (!treeView.HasFocus())
return;
GUI.FocusControl(null);
}
void DoContentArea(
CloudWorkspacesTreeView cloudWorkspacesTreeView,
DirectoryContentPanel directoryContentPanel,
SplitterState splitterState,
float width,
float height,
bool hasFocus)
{
SplitterGUILayout.BeginHorizontalSplit(splitterState);
Rect treeAreaRect = GetTreeRect(width, height);
Rect directoryContentPanelRect = GetDirectoryContentPanelRect(width, height);
SplitterGUILayout.EndHorizontalSplit();
DoTreeArea(cloudWorkspacesTreeView, treeAreaRect);
directoryContentPanel.OnGUI(
directoryContentPanelRect,
hasFocus && !cloudWorkspacesTreeView.HasFocus());
EditorGUI.DrawRect(
GetSplitterRect(directoryContentPanel.Rect),
UnityStyles.Colors.BarBorder);
}
void DoTreeArea(
CloudWorkspacesTreeView cloudWorkspacesTreeView,
Rect treeAreaRect)
{
Rect newDriveButtonRect = new Rect(
treeAreaRect.x + NEW_DRIVE_BUTTON_MARGIN,
treeAreaRect.y + NEW_DRIVE_BUTTON_MARGIN,
treeAreaRect.width - 2 * NEW_DRIVE_BUTTON_MARGIN,
EditorStyles.miniButton.fixedHeight + NEW_DRIVE_BUTTON_MARGIN);
if (GUI.Button(
newDriveButtonRect,
PlasticLocalization.Name.NewDriveButton.GetString(),
EditorStyles.miniButton))
{
WorkspaceCreationData wkCreationData = CreateWorkspaceDialog.CreateWorkspace(
mSelectedOrganization,
mSelectedProject,
mRestApi,
mPlasticApi,
mParentWindow);
CreateWorkspaceOperation.CreateWorkspace(
wkCreationData, mPlasticApi, mProgressControls,
(createdWorkspace) =>
{
TrackFeatureUseEvent.For(
PlasticGui.Plastic.API.GetRepositorySpec(createdWorkspace),
TrackFeatureUseEvent.Features.UnityPackage.CloudDriveCreateWorkspaceFromNewDriveButton);
OnOrganizationSelected(wkCreationData.CloudServer);
mProposedProject = CloudProjectRepository.GetProjectName(
wkCreationData.WorkspaceName);
mCloudWorkspacesTreeView.WorkspaceToSelect = createdWorkspace;
mCloudWorkspacesTreeView.Reload();
});
}
Rect treeRect = new Rect(
treeAreaRect.x,
treeAreaRect.y + EditorStyles.miniButton.fixedHeight + 2 * NEW_DRIVE_BUTTON_MARGIN,
treeAreaRect.width,
treeAreaRect.height - EditorStyles.miniButton.fixedHeight - 2 * NEW_DRIVE_BUTTON_MARGIN);
cloudWorkspacesTreeView.OnGUI(treeRect);
}
void DoToolbar(
Rect rect,
float combosAreaWidth,
List<string> organizations,
List<string> projects,
IRefreshableView view)
{
GUILayout.BeginArea(rect);
EditorGUILayout.BeginHorizontal(EditorStyles.toolbar);
DoCombosArea(combosAreaWidth, organizations, projects);
GUILayout.FlexibleSpace();
DoRefreshButton(view);
EditorGUILayout.EndHorizontal();
GUILayout.EndArea();
}
void DoCombosArea(
float combosAreaWidth,
List<string> organizations,
List<string> projects)
{
EditorGUILayout.BeginHorizontal(GUILayout.Width(combosAreaWidth));
DoOrganizationsCombo(organizations);
DoProjectsCombo(projects);
EditorGUILayout.EndHorizontal();
}
void DoOrganizationsCombo(List<string> organizations)
{
GUIContent content = new GUIContent(
PlasticLocalization.Name.OrganizationsComboBoxLabel.GetString(
mSelectedOrganization));
Rect rect = GUILayoutUtility.GetRect(content, EditorStyles.toolbarPopup);
if (GUI.Button(rect, content, EditorStyles.toolbarPopup))
{
GenericMenu menu = new GenericMenu();
foreach (string option in organizations)
{
menu.AddItem(
new GUIContent(UnityMenuItem.EscapedText(option)),
false,
OnOrganizationSelected,
option);
}
menu.DropDown(rect);
}
}
void DoProjectsCombo(List<string> projects)
{
if (projects.Count == 0)
return;
GUIContent content = new GUIContent(
PlasticLocalization.Name.ProjectsComboBoxLabel.GetString(mSelectedProject));
Rect rect = GUILayoutUtility.GetRect(content, EditorStyles.toolbarPopup);
if (GUI.Button(rect, content, EditorStyles.toolbarPopup))
{
GenericMenu menu = new GenericMenu();
foreach (string option in projects)
{
menu.AddItem(
new GUIContent(UnityMenuItem.EscapedText(option)),
false,
OnProjectSelected,
option);
}
menu.DropDown(rect);
}
}
static void DoRefreshButton(IRefreshableView view)
{
if (DrawToolbarButton(
Images.GetRefreshIcon(),
PlasticLocalization.Name.RefreshButton.GetString()))
view.Refresh();
}
static bool DrawToolbarButton(Texture icon, string tooltip)
{
return GUILayout.Button(
new GUIContent(icon, tooltip),
EditorStyles.toolbarButton,
GUILayout.Width(26));
}
static Rect GetToolbarRect(Rect rect)
{
return new Rect(
rect.x,
rect.y,
rect.width,
EditorStyles.toolbar.fixedHeight);
}
static Rect GetSplitterRect(Rect directoryContentRect)
{
return new Rect(
directoryContentRect.x,
directoryContentRect.y,
SPLITTER_WIDTH,
directoryContentRect.height);
}
static Rect GetTreeRect(float width, float height)
{
Rect result = GUILayoutUtility.GetRect(
width, height,
GUILayout.ExpandWidth(true));
result.y += EditorStyles.toolbar.fixedHeight;
return result;
}
static Rect GetDirectoryContentPanelRect(float width, float height)
{
Rect result = GUILayoutUtility.GetRect(
width, height,
GUILayout.ExpandWidth(true));
result.y += EditorStyles.toolbar.fixedHeight;
return result;
}
static string GetDefaultValue(string proposedValue, List<string> values)
{
if (values.Count == 0)
return null;
if (!string.IsNullOrEmpty(proposedValue) && values.Contains(proposedValue))
return proposedValue;
return values[0];
}
void BuildComponents(WorkspaceInfo workspaceToSelect, EditorWindow parentWindow)
{
mCloudWorkspacesTreeView = new CloudWorkspacesTreeView(
OnTreeViewSelectionChanged, mProgressControls, parentWindow);
mCloudWorkspacesTreeView.WorkspaceToSelect = workspaceToSelect;
mCloudWorkspacesTreeView.Reload();
mDirectoryContentPanel = new DirectoryContentPanel(
mCloudWorkspacesTreeView, this, this, parentWindow);
}
void InitializeProposedOrganizationProject(
string proposedCloudServer, string proposedProject)
{
if (!string.IsNullOrEmpty(proposedCloudServer) &&
!string.IsNullOrEmpty(proposedProject))
{
mProposedOrganization = proposedCloudServer;
mProposedProject = proposedProject;
return;
}
string lastUsedServer = PlasticGuiConfig.Get().Configuration.LastUsedCloudDriveServer;
string lastUsedProject = PlasticGuiConfig.Get().Configuration.LastUsedCloudDriveProject;
if (!string.IsNullOrEmpty(lastUsedServer) && !string.IsNullOrEmpty(lastUsedProject))
{
mProposedOrganization = lastUsedServer;
mProposedProject = lastUsedProject;
return;
}
GetProposedOrganizationProject.Values proposedOrganizationProject =
GetProposedOrganizationProject.FromCloudProjectSettings();
mProposedOrganization = proposedOrganizationProject != null ?
proposedOrganizationProject.Organization :
GetDefaultServer.FromConfig(mRestApi);
mProposedProject = proposedOrganizationProject != null ?
proposedOrganizationProject.Project :
Application.productName;
}
int mCopyPathsForProjectBrowserDropCount = 0;
string mDragTargetPath;
CloudWorkspacesTreeView mCloudWorkspacesTreeView;
DirectoryContentPanel mDirectoryContentPanel;
List<string> mOrganizations = new List<string>();
List<string> mProjects = new List<string>();
string mProposedOrganization;
string mProposedProject;
string mSelectedOrganization;
string mSelectedProject;
readonly SplitterState mSplitterState;
readonly FillCloudWorkspaces mFillCloudWorkspacesView;
readonly IPlasticWebRestApi mRestApi;
readonly IPlasticAPI mPlasticApi;
readonly IProgressControls mProgressControls;
readonly EditorWindow mParentWindow;
const float SPLITTER_WIDTH = 1;
const float NEW_DRIVE_BUTTON_MARGIN = 5;
const int TREE_VIEW_MIN_SIZE = 139;
const int DIRECTORY_CONTENT_MIN_SIZE =
2 * (int)DrawItemsGridView.GRID_AREA_MARGIN +
(int)DrawExpandedTreeNode.ICON_SIZE;
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: c63e2acf5cfd4816b950cf4bf6381b6f
timeCreated: 1749035122
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 158cb24897c04303a383697ef5349bc9
timeCreated: 1747998731
@@ -0,0 +1,111 @@
using UnityEditor;
using UnityEngine;
using PlasticGui;
using Unity.PlasticSCM.Editor.UI;
namespace Unity.PlasticSCM.Editor.CloudDrive.Workspaces.DirectoryContent
{
internal class DeleteWorkspaceDialog : PlasticDialog
{
protected override Rect DefaultRect
{
get
{
var baseRect = base.DefaultRect;
return new Rect(baseRect.x, baseRect.y, 500, 200);
}
}
internal static bool UserConfirmsDelete(
string workspaceName,
EditorWindow parentWindow)
{
DeleteWorkspaceDialog dialog = Create(workspaceName);
ResponseType dialogResult = dialog.RunModal(parentWindow);
return dialogResult == ResponseType.Ok;
}
static DeleteWorkspaceDialog Create(string workspaceName)
{
var instance = CreateInstance<DeleteWorkspaceDialog>();
instance.mWorkspaceName = workspaceName;
instance.mConfirmationText = string.Empty;
instance.mEnterKeyAction = instance.OkButtonAction;
instance.mEscapeKeyAction = instance.CancelButtonAction;
return instance;
}
protected override string GetTitle()
{
return PlasticLocalization.Name.DeleteCloudDriveTitle.GetString();
}
protected override void DoComponentsArea()
{
DoWarningArea();
GUILayout.Space(10f);
DoConfirmationArea();
}
void DoWarningArea()
{
using (new EditorGUILayout.VerticalScope())
{
EditorGUILayout.LabelField(
string.Format(PlasticLocalization.Name.DeleteCloudDriveWarningText.GetString(), mWorkspaceName),
EditorStyles.wordWrappedLabel);
}
}
void DoConfirmationArea()
{
using (new EditorGUILayout.HorizontalScope())
{
string confirmText = PlasticLocalization.Name.DeleteCloudDriveConfirmText.GetString();
EditorGUILayout.LabelField(confirmText, GUILayout.Width(220));
GUILayout.Space(10f);
GUI.SetNextControlName(CONFIRMATION_TEXTAREA_NAME);
mConfirmationText = GUILayout.TextField(
mConfirmationText,
GUILayout.ExpandWidth(true));
FocusTextAreaIfNeeded(CONFIRMATION_TEXTAREA_NAME);
}
}
protected override void DoOkButton()
{
using (new GuiEnabled(mWorkspaceName == mConfirmationText))
{
if (!NormalButton(PlasticLocalization.Name.DeleteButton.GetString()))
return;
OkButtonAction();
}
}
internal override void OkButtonAction()
{
if (mWorkspaceName != mConfirmationText)
return;
base.OkButtonAction();
}
string mWorkspaceName;
string mConfirmationText;
const string CONFIRMATION_TEXTAREA_NAME = "confirmation_textarea";
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: eb450999e4f7add47adebc90f7f87c79
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,339 @@
using System.Collections.Generic;
using System.IO;
using Codice.CM.Common;
using Codice.Utils;
using UnityEditor;
using UnityEngine;
using PlasticGui;
using PlasticGui.WorkspaceWindow.Items;
using Unity.PlasticSCM.Editor.UI;
using Unity.PlasticSCM.Editor.Views;
namespace Unity.PlasticSCM.Editor.CloudDrive.Workspaces.DirectoryContent
{
internal interface ICloudWorkspacesOperations
{
void ImportInProject(string[] srcPaths, string dstProjectPath);
void DeleteItems(List<string> paths);
}
internal class DirectoryContentPanel : IDirectoryContentMenuOperations
{
internal Rect Rect { get { return mLastValidRect; } }
internal ItemsGridView ItemsGridView { get { return mItemsGridView; } }
internal interface ICloudWorkspacesTreeView
{
void SelectNode(string wkPath, string fullPath);
}
internal DirectoryContentPanel(
ICloudWorkspacesTreeView treeView,
IDragAndDrop dragAndDrop,
ICloudWorkspacesOperations cloudWorkspacesOperations,
EditorWindow parentWindow)
{
mTreeView = treeView;
mCloudWorkspacesOperations = cloudWorkspacesOperations;
mParentWindow = parentWindow;
BuildComponents(
new DirectoryContentPanelMenu(this),
dragAndDrop,
parentWindow);
}
internal void OnGUI(Rect rect, bool hasFocus)
{
if (Event.current.type == EventType.Repaint && rect != mLastValidRect)
{
mLastValidRect = rect;
mParentWindow.Repaint();
}
mItemsGridView.OnGUI(
GetGridAreaRect(mLastValidRect),
hasFocus);
EditorGUI.DrawRect(
GetSeparatorRect(mLastValidRect),
UnityStyles.Colors.BarBorder);
DrawItemNameBar.Draw(
GetItemNameBarRect(mLastValidRect),
mItemsGridView.GetSelectedItem());
}
internal void UpdateItemsForDirectory(ExpandedTreeNode node)
{
mItemsDirNode = node;
string itemsDirPath = node.GetFullPath();
bool isItemsDirPathChanging =
itemsDirPath != mItemsGridView.GetItemsDirPath();
List<string> itemsPathsToSelect = ItemsGridSelection.
GetItemsPathsToSelect(isItemsDirPathChanging, mItemsGridView);
mItemsGridView.UpdateItems(itemsDirPath, node.GetChildren());
ItemsGridSelection.SelectItems(
isItemsDirPathChanging,
itemsPathsToSelect,
mItemsGridView);
mParentWindow.Repaint();
}
internal void CleanItems()
{
mItemsDirNode = null;
mItemsGridView.CleanItems();
mParentWindow.Repaint();
}
int IDirectoryContentMenuOperations.GetSelectedItemsCount()
{
return mItemsGridView.GetSelectedItemsCount();
}
bool IDirectoryContentMenuOperations.IsAnyFileSelected()
{
List<string> selectedPaths = mItemsGridView.GetSelectedItemsPaths();
foreach (string path in selectedPaths)
{
if (File.Exists(path))
return true;
}
return false;
}
bool IDirectoryContentMenuOperations.IsPathSelected()
{
return mItemsDirNode != null;
}
void IDirectoryContentMenuOperations.CreateFolder()
{
List<string> selectedPaths = mItemsGridView.GetSelectedItemsPaths();
string parentPath;
if (selectedPaths.Count == 0 && mItemsDirNode != null)
parentPath = mItemsDirNode.GetFullPath();
else if (selectedPaths.Count == 1)
parentPath = selectedPaths[0];
else
return;
string newName = NewNameDialog.GetNewNameForCreate(
parentPath, true, mParentWindow);
if (string.IsNullOrEmpty(newName))
return;
Directory.CreateDirectory(
Path.Combine(parentPath, newName));
}
void IDirectoryContentMenuOperations.OpenInExplorer()
{
if (mItemsDirNode == null)
return;
List<string> selectedPaths = mItemsGridView.GetSelectedItemsPaths();
if (selectedPaths.Count == 0)
{
FileSystemOperation.OpenInExplorer(mItemsDirNode.GetFullPath());
return;
}
FileSystemOperation.OpenInExplorer(selectedPaths);
}
void IDirectoryContentMenuOperations.OpenUnityCloud()
{
ExpandedTreeNode selectedNode = mItemsGridView.GetSelectedItem();
if (selectedNode == null)
selectedNode = mItemsDirNode;
WorkspaceInfo workspaceInfo = selectedNode.WkInfo;
RepositorySpec repSpec = PlasticGui.Plastic.API.GetRepositorySpec(workspaceInfo);
string cloudServer = CloudServer.GetOrganizationName(repSpec.Server);
RepositoryInfo repInfo = PlasticGui.Plastic.API.GetRepositoryInfo(repSpec);
if (ExpandedTreeNode.IsDirectory(selectedNode))
{
OpenBrowser.TryOpen(UnityUrl.UnityDashboard.CloudDrive.GetWorkspaceDirPath(
cloudServer,
repInfo.GUID.ToString(),
selectedNode.RelativePath));
return;
}
OpenBrowser.TryOpen(UnityUrl.UnityDashboard.CloudDrive.GetWorkspaceItemPath(
cloudServer,
repInfo.GUID.ToString(),
selectedNode.RelativePath));
}
void IDirectoryContentMenuOperations.Open()
{
ExpandedTreeNode node = mItemsGridView.GetSelectedItem();
if (node == null)
return;
if (!ExpandedTreeNode.IsDirectory(node))
{
OpenOperation.OpenFile(node.GetFullPath());
return;
}
mTreeView.SelectNode(node.WkInfo.ClientPath, node.GetFullPath());
}
void IDirectoryContentMenuOperations.Delete()
{
List<string> selectedPaths = mItemsGridView.GetSelectedItemsPaths();
if (selectedPaths.Count == 0)
{
mCloudWorkspacesOperations.DeleteItems(
new List<string> { mItemsDirNode.GetFullPath() });
return;
}
mCloudWorkspacesOperations.DeleteItems(selectedPaths);
}
void IDirectoryContentMenuOperations.Rename()
{
ExpandedTreeNode node = mItemsGridView.GetSelectedItem();
string currentPath = node == null ?
mItemsDirNode.GetFullPath() : node.GetFullPath();
string parentPath = Path.GetDirectoryName(currentPath);
string currentName = Path.GetFileName(currentPath);
bool isDirectory = Directory.Exists(currentPath);
string newName = NewNameDialog.GetNewNameForRename(
parentPath,
currentName,
isDirectory,
mParentWindow);
if (string.IsNullOrEmpty(newName) || newName == currentName)
return;
string newPath = Path.Combine(parentPath, newName);
if (File.Exists(currentPath))
File.Move(currentPath, newPath);
else
Directory.Move(currentPath, newPath);
}
void IDirectoryContentMenuOperations.ImportInProject()
{
if (mItemsDirNode == null)
return;
bool hasItemsSelected = mItemsGridView.GetSelectedItemsCount() > 0;
string projectPath = ImportInProjectDialog.GetProjectPathToImport(
hasItemsSelected ?
mItemsDirNode.GetFullPath() :
Path.GetDirectoryName(mItemsDirNode.GetFullPath()),
mItemsDirNode.WkInfo.ClientPath,
mParentWindow);
if (string.IsNullOrEmpty(projectPath))
return;
mCloudWorkspacesOperations.ImportInProject(
hasItemsSelected ?
mItemsGridView.GetSelectedItemsPaths().ToArray() :
new string[] { mItemsDirNode.GetFullPath() },
projectPath);
}
void NavigateBackAction()
{
if (mItemsDirNode == null)
return;
ExpandedTreeNode parentNode = (ExpandedTreeNode)
((IPlasticTreeNode)mItemsDirNode).GetParent();
if (parentNode == null)
return;
mTreeView.SelectNode(parentNode.WkInfo.ClientPath, parentNode.GetFullPath());
}
void OnItemDoubleClickAction()
{
if (mItemsGridView.GetSelectedItemsCount() != 1)
return;
((IDirectoryContentMenuOperations)this).Open();
}
static Rect GetGridAreaRect(Rect rect)
{
return new Rect(
rect.x, rect.y,
rect.width, rect.height - ITEM_NAME_BAR_HEIGHT - SEPARATOR_HEIGHT);
}
static Rect GetSeparatorRect(Rect rect)
{
return new Rect(
rect.x, GetItemNameBarRect(rect).y - SEPARATOR_HEIGHT,
rect.width, SEPARATOR_HEIGHT);
}
static Rect GetItemNameBarRect(Rect rect)
{
return new Rect(
rect.x, rect.yMax - ITEM_NAME_BAR_HEIGHT,
rect.width, ITEM_NAME_BAR_HEIGHT);
}
void BuildComponents(
DirectoryContentPanelMenu menu,
IDragAndDrop dragAndDrop,
EditorWindow parentWindow)
{
mItemsGridView = new ItemsGridView(
menu,
dragAndDrop,
parentWindow,
OnItemDoubleClickAction,
NavigateBackAction);
}
ItemsGridView mItemsGridView;
Rect mLastValidRect;
ExpandedTreeNode mItemsDirNode;
readonly ICloudWorkspacesTreeView mTreeView;
readonly ICloudWorkspacesOperations mCloudWorkspacesOperations;
readonly EditorWindow mParentWindow;
const int SEPARATOR_HEIGHT = 1;
const int ITEM_NAME_BAR_HEIGHT = 20;
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 7f9122bc11da473eaa9082bf340c3047
timeCreated: 1747662141
@@ -0,0 +1,314 @@
using System;
using UnityEditor;
using UnityEngine;
using Codice.Utils;
using PlasticGui;
using Unity.PlasticSCM.Editor.UI;
namespace Unity.PlasticSCM.Editor.CloudDrive.Workspaces.DirectoryContent
{
[Flags]
internal enum DirectoryContentMenuOperations : short
{
None = 0,
CreateFolder = 1 << 0,
OpenInExplorer = 1 << 1,
OpenUnityCloud = 1 << 2,
Open = 1 << 3,
Delete = 1 << 4,
Rename = 1 << 5,
ImportInProject = 1 << 6
}
internal static class DirectoryContentMenuUpdater
{
internal static DirectoryContentMenuOperations GetAvailableMenuOperations(
int selectedItemsCount, bool isAnyFileSelected, bool isPathSelected)
{
DirectoryContentMenuOperations result = DirectoryContentMenuOperations.None;
if (!isPathSelected)
return result;
result |= DirectoryContentMenuOperations.OpenInExplorer |
DirectoryContentMenuOperations.Delete |
DirectoryContentMenuOperations.ImportInProject;
if (selectedItemsCount <= 1)
result |= DirectoryContentMenuOperations.Rename |
DirectoryContentMenuOperations.OpenUnityCloud;
if (selectedItemsCount == 1)
result |= DirectoryContentMenuOperations.Open;
if ((selectedItemsCount == 1 && !isAnyFileSelected) ||
selectedItemsCount == 0)
result |= DirectoryContentMenuOperations.CreateFolder;
return result;
}
}
internal interface IDirectoryContentMenuOperations
{
int GetSelectedItemsCount();
bool IsAnyFileSelected();
bool IsPathSelected();
void CreateFolder();
void OpenInExplorer();
void OpenUnityCloud();
void Open();
void Delete();
void Rename();
void ImportInProject();
}
internal class DirectoryContentPanelMenu
{
internal DirectoryContentPanelMenu(IDirectoryContentMenuOperations operations)
{
mOperations = operations;
BuildComponents();
}
internal void Popup()
{
GenericMenu menu = new GenericMenu();
UpdateMenuItems(menu);
menu.ShowAsContext();
}
internal bool ProcessKeyActionIfNeeded(Event e)
{
DirectoryContentMenuOperations operationToExecute = GetMenuOperation(e);
if (operationToExecute == DirectoryContentMenuOperations.None)
return false;
int selectedCount = mOperations.GetSelectedItemsCount();
bool isAnyFileSelected = mOperations.IsAnyFileSelected();
bool isPathSelected = mOperations.IsPathSelected();
DirectoryContentMenuOperations operations =
DirectoryContentMenuUpdater.GetAvailableMenuOperations(
selectedCount, isAnyFileSelected, isPathSelected);
if (!operations.HasFlag(operationToExecute))
return false;
ProcessMenuOperation(operationToExecute);
return true;
}
void CreateFolderMenuItem_Click()
{
mOperations.CreateFolder();
}
void OpenInExplorerMenuItem_Click()
{
mOperations.OpenInExplorer();
}
void OpenUnityCloudMenuItem_Click()
{
mOperations.OpenUnityCloud();
}
void OpenMenuItem_Click()
{
mOperations.Open();
}
void DeleteMenuItem_Click()
{
mOperations.Delete();
}
void RenameMenuItem_Click()
{
mOperations.Rename();
}
void ImportInProjectMenuItem_Click()
{
mOperations.ImportInProject();
}
void UpdateMenuItems(GenericMenu menu)
{
int selectedCount = mOperations.GetSelectedItemsCount();
bool isAnyFileSelected = mOperations.IsAnyFileSelected();
bool isPathSelected = mOperations.IsPathSelected();
DirectoryContentMenuOperations operations =
DirectoryContentMenuUpdater.GetAvailableMenuOperations(
selectedCount, isAnyFileSelected, isPathSelected);
AddMenuItem(
mCreateFolderMenuItemContent,
menu,
operations,
DirectoryContentMenuOperations.CreateFolder,
CreateFolderMenuItem_Click);
AddMenuItem(
mOpenInExplorerMenuItemContent,
menu,
operations,
DirectoryContentMenuOperations.OpenInExplorer,
OpenInExplorerMenuItem_Click);
AddMenuItem(
mOpenUnityCloudMenuItemContent,
menu,
operations,
DirectoryContentMenuOperations.OpenUnityCloud,
OpenUnityCloudMenuItem_Click);
AddMenuItem(
mOpenMenuItemContent,
menu,
operations,
DirectoryContentMenuOperations.Open,
OpenMenuItem_Click);
AddMenuItem(
mDeleteMenuItemContent,
menu,
operations,
DirectoryContentMenuOperations.Delete,
DeleteMenuItem_Click);
AddMenuItem(
mRenameMenuItemContent,
menu,
operations,
DirectoryContentMenuOperations.Rename,
RenameMenuItem_Click);
menu.AddSeparator(string.Empty);
AddMenuItem(
mImportInProjectMenuItemContent,
menu,
operations,
DirectoryContentMenuOperations.ImportInProject,
ImportInProjectMenuItem_Click);
}
static void AddMenuItem(
GUIContent menuItemContent,
GenericMenu menu,
DirectoryContentMenuOperations operations,
DirectoryContentMenuOperations operationsToCheck,
GenericMenu.MenuFunction menuFunction)
{
if (operations.HasFlag(operationsToCheck))
{
menu.AddItem(menuItemContent, false, menuFunction);
return;
}
menu.AddDisabledItem(menuItemContent);
}
void ProcessMenuOperation(DirectoryContentMenuOperations operationToExecute)
{
if (operationToExecute == DirectoryContentMenuOperations.OpenInExplorer)
{
OpenInExplorerMenuItem_Click();
return;
}
if (operationToExecute == DirectoryContentMenuOperations.Open)
{
OpenMenuItem_Click();
return;
}
if (operationToExecute == DirectoryContentMenuOperations.Delete)
{
DeleteMenuItem_Click();
return;
}
if (operationToExecute == DirectoryContentMenuOperations.Rename)
{
RenameMenuItem_Click();
return;
}
}
static DirectoryContentMenuOperations GetMenuOperation(Event e)
{
if (Keyboard.HasControlOrCommandModifier(e) &&
Keyboard.HasShiftModifier(e) &&
Keyboard.IsKeyPressed(e, KeyCode.S))
{
return DirectoryContentMenuOperations.OpenInExplorer;
}
if (Keyboard.IsReturnOrEnterKeyPressed(e))
return DirectoryContentMenuOperations.Open;
if (Keyboard.IsDeleteKeyPressed(e))
return DirectoryContentMenuOperations.Delete;
if (Keyboard.IsKeyPressed(e, KeyCode.F2))
return DirectoryContentMenuOperations.Rename;
return DirectoryContentMenuOperations.None;
}
void BuildComponents()
{
mCreateFolderMenuItemContent =
new GUIContent(PlasticLocalization.Name.CreateFolderMenuItem.GetString());
mOpenInExplorerMenuItemContent = new GUIContent(
string.Format("{0} {1}",
PlatformIdentifier.IsMac() ?
PlasticLocalization.Name.ItemsMenuItemRevealInFinder.GetString() :
PlasticLocalization.Name.ShowInExplorerMenuItem.GetString(),
GetPlasticShortcut.ForShowInExplorer()));
mOpenUnityCloudMenuItemContent = new GUIContent(
PlasticLocalization.Name.OpenUnityDashboard.GetString());
mOpenMenuItemContent = new GUIContent(
string.Format("{0} {1}",
PlasticLocalization.Name.ItemsMenuItemOpen.GetString(),
GetPlasticShortcut.ForEnter()));
mDeleteMenuItemContent = new GUIContent(
string.Format("{0} {1}",
PlasticLocalization.Name.ItemsMenuItemDelete.GetString(),
GetPlasticShortcut.ForDelete()));
mRenameMenuItemContent = new GUIContent(
string.Format("{0} {1}",
PlasticLocalization.Name.ItemsMenuItemRename.GetString(),
GetPlasticShortcut.ForRename()));
mImportInProjectMenuItemContent = new GUIContent(
PlasticLocalization.Name.ImportInProjectMenuItem.GetString());
}
GUIContent mCreateFolderMenuItemContent;
GUIContent mOpenInExplorerMenuItemContent;
GUIContent mOpenUnityCloudMenuItemContent;
GUIContent mOpenMenuItemContent;
GUIContent mDeleteMenuItemContent;
GUIContent mRenameMenuItemContent;
GUIContent mImportInProjectMenuItemContent;
readonly IDirectoryContentMenuOperations mOperations;
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 091f2d65ecc2b10409b1f65c29e2b2a4
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,283 @@
using System;
using System.IO;
using UnityEngine;
using PlasticGui.WorkspaceWindow.Items;
using Unity.PlasticSCM.Editor.UI;
namespace Unity.PlasticSCM.Editor.CloudDrive.Workspaces.DirectoryContent
{
internal static class DrawExpandedTreeNode
{
internal const float ICON_SIZE = 66;
internal const float PADDING = 5;
internal static void Draw(
Rect rect,
ExpandedTreeNode node,
bool isSelected,
bool hasFocus,
bool isDragTarget)
{
DrawIcon(
new Rect(
rect.x + (rect.width - ICON_SIZE) / 2,
rect.y + PADDING,
ICON_SIZE,
ICON_SIZE),
GetIcon(node),
isSelected);
string fileName = Path.GetFileName(node.GetFullPath());
DrawLabel(
new Rect(
rect.x + PADDING,
rect.y + PADDING + ICON_SIZE,
rect.width - 2 * PADDING,
rect.height - ICON_SIZE - 2 * PADDING),
ExpandedTreeNode.IsDirectory(node) ? fileName : GetFileNameWithoutExtension(fileName),
fileName,
isSelected,
hasFocus,
isDragTarget);
}
internal static Texture GetIcon(ExpandedTreeNode node)
{
if (ExpandedTreeNode.IsDirectory(node))
return Images.GetFolderIcon();
return Images.GetFileIcon(node.GetFullPath());
}
static void DrawIcon(Rect rect, Texture icon, bool isSelected)
{
Color originalColor = GUI.color;
try
{
if (isSelected)
GUI.color *= UnityStyles.Colors.SelectedIcon;
GUI.DrawTexture(rect, icon);
}
finally
{
GUI.color = originalColor;
}
}
static void DrawLabel(
Rect rect,
string text,
string tooltip,
bool isSelected,
bool hasFocus,
bool isDragTarget)
{
GUIStyle normalStyle = UnityStyles.CloudDrive.ItemsListLabel;
GUIStyle focusedStyle = UnityStyles.CloudDrive.ItemsListLabelFocused;
float textWidth;
string cutText = CutText(
text, normalStyle, rect.width,
out textWidth);
Rect labelRect = new Rect(
rect.x + (rect.width - textWidth) / 2,
rect.y + (rect.height - normalStyle.lineHeight) / 2,
textWidth,
normalStyle.lineHeight);
if (isSelected)
{
Rect selectionRect = new Rect(
labelRect.x - 1, labelRect.y - 1,
labelRect.width + 2, labelRect.height + 2);
Color rectColor = hasFocus ?
UnityStyles.Colors.SelectedFocusedTextBackground :
UnityStyles.Colors.SelectedUnfocusedTextBackground;
Texture2D selectionTexture = CreateRoundedRectTexture(
selectionRect.size,
radius: 1,
borderColor: rectColor,
fillColor: rectColor,
thickness: 1);
GUI.DrawTexture(selectionRect, selectionTexture);
}
if (isDragTarget)
{
Rect dragTargetRect = new Rect(
rect.x, rect.y - 2,
rect.width, rect.height + 4);
Texture2D dragTexture = CreateRoundedRectTexture(
dragTargetRect.size,
radius: 6,
borderColor: UnityStyles.Colors.SelectedFocusedDropLineBackground,
fillColor: UnityStyles.Colors.SelectedFocusedDropLabelBackground,
thickness: 2);
GUI.DrawTexture(dragTargetRect, dragTexture);
}
GUI.Label(
labelRect,
new GUIContent(cutText, cutText == tooltip ? null : tooltip),
isSelected && hasFocus ? focusedStyle : normalStyle);
}
static string CutText(
string text,
GUIStyle style,
float availableWidth,
out float usedWidth)
{
usedWidth = 0;
availableWidth -= style.margin.horizontal + style.padding.horizontal;
float fullTextWidth = style.CalcSize(
new GUIContent(text)).x;
if (fullTextWidth <= availableWidth)
{
usedWidth = fullTextWidth;
return text;
}
string resultText = string.Empty;
foreach (char c in text)
{
float currentWidth = style.CalcSize(
new GUIContent(resultText + c + ELLIPSIS)).x;
if (currentWidth > availableWidth)
return resultText + ELLIPSIS;
usedWidth = currentWidth;
resultText += c;
}
return resultText + ELLIPSIS;
}
static string GetFileNameWithoutExtension(string fileName)
{
if (fileName.LastIndexOf(".") <= 0)
return fileName;
if (MetaPath.IsMetaPath(fileName))
fileName = MetaPath.GetPathFromMetaPath(fileName);
if (fileName.LastIndexOf(".") <= 0)
return fileName;
return Path.GetFileNameWithoutExtension(fileName);
}
static Texture2D CreateRoundedRectTexture(
Vector2 rectSize,
float radius,
Color borderColor,
Color fillColor,
float thickness)
{
int width = (int)rectSize.x;
int height = (int)rectSize.y;
radius = Math.Min(radius, Math.Min(width, height) / 2);
thickness = Math.Min(radius, thickness);
Texture2D result = new Texture2D(width, height, TextureFormat.ARGB32, false);
Color32[] pixels = new Color32[width * height];
double outerRadiusSquared = Math.Pow(radius, 2);
double innerRadiusSquared = Math.Pow(radius - thickness, 2);
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
int pixelIdx = y * width + x;
double distanceSquared;
if (InCorner(x, y, width, height, radius, out distanceSquared))
{
if (distanceSquared > outerRadiusSquared)
continue;
pixels[pixelIdx] =
distanceSquared >= innerRadiusSquared ?
borderColor : fillColor;
continue;
}
pixels[pixelIdx] =
IsBorder(x, y, width, height, radius, thickness) ?
borderColor : fillColor;
}
}
result.SetPixels32(pixels);
result.Apply();
return result;
}
static bool InCorner(
int x,
int y,
float width,
float height,
float radius,
out double distanceSquared)
{
bool inTop = y < radius;
bool inBottom = y >= height - radius;
bool inLeft = x < radius;
bool inRight = x >= width - radius;
if ((!inTop && !inBottom) || (!inLeft && !inRight))
{
distanceSquared = 0;
return false;
}
float centerX = inLeft ? radius : width - radius - 1;
float centerY = inTop ? radius : height - radius - 1;
float deltaX = x - centerX;
float deltaY = y - centerY;
distanceSquared = Math.Pow(deltaX, 2) + Math.Pow(deltaY, 2);
return true;
}
static bool IsBorder(int x, int y, float width, float height, float radius, float thickness)
{
if (y < thickness && x >= radius && x < width - radius) // top border
return true;
if (y >= height - thickness && x >= radius && x < width - radius) // bottom border
return true;
if (x < thickness && y >= radius && y < height - radius) // left border
return true;
if (x >= width - thickness && y >= radius && y < height - radius) // right border
return true;
return false;
}
const string ELLIPSIS = "...";
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: b4c28e55281f4ec5bc041b8f52b7d891
timeCreated: 1747998783
@@ -0,0 +1,32 @@
using System.IO;
using UnityEditor;
using UnityEngine;
using PlasticGui.WorkspaceWindow.Items;
using Unity.PlasticSCM.Editor.UI;
namespace Unity.PlasticSCM.Editor.CloudDrive.Workspaces.DirectoryContent
{
internal static class DrawItemNameBar
{
internal static void Draw(Rect rect, ExpandedTreeNode node)
{
EditorGUI.DrawRect(
rect,
UnityStyles.Colors.FooterBarBackground);
if (node == null)
return;
GUI.Label(
rect,
new GUIContent(
Path.Combine(
Path.GetFileName(node.WkInfo.ClientPath),
node.RelativePath).Replace("\\", "/"),
DrawExpandedTreeNode.GetIcon(node)),
UnityStyles.CloudDrive.ItemNameBarLabel);
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 35caf055aec448e6bd68e33611eb916d
timeCreated: 1748337312
@@ -0,0 +1,139 @@
using System;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using PlasticGui.WorkspaceWindow.Items;
using Unity.PlasticSCM.Editor.UI;
using Unity.PlasticSCM.Editor.UI.Tree;
namespace Unity.PlasticSCM.Editor.CloudDrive.Workspaces.DirectoryContent
{
internal static class DrawItemsGridView
{
internal const float GRID_AREA_MARGIN = 10;
internal static void Draw(
Rect rect,
EmptyStatePanel emptyStatePanel,
IItemsGridView itemsGridView,
List<ExpandedTreeNode> items,
List<int> selectedItemsIndexes,
Vector2 itemSize,
float scrollPosition,
int rowsCount,
int columnsCount,
bool shouldScrollbarBeVisible,
bool hasFocus,
int dragTargetIndex,
ref bool shouldShowEmptyState)
{
DrawBackground(rect);
if (Event.current.type == EventType.Layout)
shouldShowEmptyState = !emptyStatePanel.IsEmpty();
if (shouldShowEmptyState)
{
emptyStatePanel.OnGUI(rect);
return;
}
DrawGrid(
rect,
items,
selectedItemsIndexes,
itemSize,
scrollPosition,
columnsCount,
hasFocus,
dragTargetIndex);
if (!shouldScrollbarBeVisible)
return;
itemsGridView.UpdateScrollPosition(
GUI.VerticalScrollbar(
new Rect(
rect.xMax - UnityConstants.SCROLLBAR_WIDTH,
rect.y,
UnityConstants.SCROLLBAR_WIDTH,
rect.height),
scrollPosition,
rect.height,
0,
rowsCount * itemSize.y + GRID_AREA_MARGIN * 2));
}
static void DrawBackground(Rect rect)
{
EditorGUI.DrawRect(rect, UnityStyles.Colors.BackgroundLighter);
}
static void DrawGrid(
Rect rect,
List<ExpandedTreeNode> items,
IList<int> selectedItemsIndexes,
Vector2 itemSize,
float scrollPosition,
int columnsCount,
bool hasFocus,
int dragTargetIndex)
{
scrollPosition -= GRID_AREA_MARGIN;
int firstVisibleRow = Math.Max(0, Mathf.FloorToInt(scrollPosition / itemSize.y));
int lastVisibleRow = Mathf.FloorToInt((scrollPosition + rect.height) / itemSize.y);
float offset = scrollPosition % itemSize.y;
for (int rowIndex = firstVisibleRow; rowIndex <= lastVisibleRow; rowIndex++)
{
DrawRow(
new Rect(
rect.x,
rect.y - offset + (rowIndex - firstVisibleRow) * itemSize.y,
rect.width,
itemSize.y),
items,
selectedItemsIndexes,
itemSize,
rowIndex,
columnsCount,
hasFocus,
dragTargetIndex);
}
}
static void DrawRow(
Rect rect,
List<ExpandedTreeNode> items,
IList<int> selectedItemsIndexes,
Vector2 itemSize,
int rowIndex,
int columnsCount,
bool hasFocus,
int dragTargetIndex)
{
for (int columnIndex = 0; columnIndex < columnsCount; columnIndex++)
{
int nodeIndex = rowIndex * columnsCount + columnIndex;
if (nodeIndex >= items.Count)
return;
DrawExpandedTreeNode.Draw(
new Rect(
rect.x + GRID_AREA_MARGIN + columnIndex * itemSize.x,
rect.y,
itemSize.x,
rect.height),
items[nodeIndex],
selectedItemsIndexes.Contains(nodeIndex),
hasFocus,
dragTargetIndex == nodeIndex);
}
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ec42e544b2c5739459971099e469936b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,142 @@
using UnityEditor;
using UnityEngine;
using PlasticGui;
using Unity.PlasticSCM.Editor.AssetUtils;
using Unity.PlasticSCM.Editor.UI;
namespace Unity.PlasticSCM.Editor.CloudDrive.Workspaces.DirectoryContent
{
internal class ImportInProjectDialog : PlasticDialog
{
protected override Rect DefaultRect
{
get
{
var baseRect = base.DefaultRect;
return new Rect(baseRect.x, baseRect.y, 600, 200);
}
}
internal static string GetProjectPathToImport(
string currentCloudDrivePath,
string workspacePath,
EditorWindow parentWindow)
{
ImportInProjectDialog dialog = Create(currentCloudDrivePath, workspacePath);
ResponseType dialogResult = dialog.RunModal(parentWindow);
if (dialogResult != ResponseType.Ok)
return string.Empty;
return dialog.mRelativeProjectPath;
}
protected override string GetTitle()
{
return PlasticLocalization.Name.ImportInProjectDialogTitle.GetString();
}
protected override string GetExplanation()
{
return PlasticLocalization.Name.ImportInProjectDialogExplanation.GetString();
}
protected override void DoComponentsArea()
{
using (new EditorGUILayout.HorizontalScope())
{
mRelativeProjectPath = EntryBuilder.CreateTextEntry(
PlasticLocalization.Name.ProjectPathLabel.GetString(),
mRelativeProjectPath,
ENTRY_WIDTH - BROWSE_BUTTON_WIDTH,
ENTRY_X);
Rect browseButtonRect = new Rect(
ENTRY_X + ENTRY_WIDTH - BROWSE_BUTTON_WIDTH + BUTTON_MARGIN,
GUILayoutUtility.GetLastRect().y,
BROWSE_BUTTON_WIDTH - BUTTON_MARGIN,
20);
if (GUI.Button(browseButtonRect, "..."))
DoBrowseForPath();
}
}
static ImportInProjectDialog Create(string currentCloudDrivePath, string workspacePath)
{
var instance = CreateInstance<ImportInProjectDialog>();
instance.IsResizable = false;
instance.mRelativeProjectPath = GetProposedProjectPath(
currentCloudDrivePath, workspacePath);
instance.mEnterKeyAction = instance.OkButtonAction;
instance.mEscapeKeyAction = instance.CancelButtonAction;
instance.mOkButtonText = PlasticLocalization.Name.ImportButton.GetString();
return instance;
}
void DoBrowseForPath()
{
string projectPath = AssetsPath.GetFullPath.ForPath(ProjectPath.Get());
string selectedPath = AssetsPath.GetFullPath.ForPath(EditorUtility.SaveFolderPanel(
PlasticLocalization.Name.SelectProjectPathDialogTitle.GetString(),
projectPath,
""));
if (string.IsNullOrEmpty(selectedPath))
return;
if (!selectedPath.StartsWith(projectPath))
{
((IProgressControls)mProgressControls).ShowError(
PlasticLocalization.Name.PathMustBeInsideProjectFolder.GetString());
return;
}
((IProgressControls)mProgressControls).HideProgress();
if (selectedPath == projectPath)
{
mRelativeProjectPath = "/";
return;
}
mRelativeProjectPath = selectedPath.Substring(projectPath.Length).Replace('\\', '/');
}
internal override void OkButtonAction()
{
if (!mRelativeProjectPath.StartsWith("/"))
{
((IProgressControls)mProgressControls).ShowError(
PlasticLocalization.Name.PathMustStartWithSlash.GetString());
return;
}
base.OkButtonAction();
}
static string GetProposedProjectPath(string currentCloudDrivePath, string workspacePath)
{
string relativeProjectPath =
currentCloudDrivePath.Substring(workspacePath.Length).Replace('\\', '/');
if (string.IsNullOrEmpty(relativeProjectPath))
return "/";
return relativeProjectPath;
}
string mRelativeProjectPath;
const float ENTRY_WIDTH = 400;
const float ENTRY_X = 120f;
const float BROWSE_BUTTON_WIDTH = 30;
const float BUTTON_MARGIN = 5;
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 4b51fa1c43534178b0b4bd9a425e187b
timeCreated: 1756822169
@@ -0,0 +1,31 @@
using System.Collections.Generic;
namespace Unity.PlasticSCM.Editor.CloudDrive.Workspaces.DirectoryContent
{
internal static class ItemsGridSelection
{
internal static List<string> GetItemsPathsToSelect(
bool isItemsDirPathChanging,
ItemsGridView itemsGridView)
{
if (isItemsDirPathChanging)
return new List<string>();
return itemsGridView.GetSelectedItemsPaths();
}
internal static void SelectItems(
bool isItemsDirPathChanging,
List<string> itemsPathsToSelect,
ItemsGridView itemsGridView)
{
if (isItemsDirPathChanging)
{
itemsGridView.ClearSelection();
return;
}
itemsGridView.SelectItemsFromPaths(itemsPathsToSelect);
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 474f848599824c969ea9f3e5db753200
timeCreated: 1751452393
@@ -0,0 +1,302 @@
using System;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using PlasticGui;
using PlasticGui.WorkspaceWindow.Items;
using Unity.PlasticSCM.Editor.UI;
using Unity.PlasticSCM.Editor.UI.Tree;
namespace Unity.PlasticSCM.Editor.CloudDrive.Workspaces.DirectoryContent
{
internal interface IItemsGridView
{
void ClearSelectedItems();
void SetSelection(List<int> itemIndexesToSelect);
void UpdateScrollPosition(float scrollPosition);
void ClearDragTargetIndex();
void SetDragTargetIndexFromPath(string path);
string GetDragTargetPathFromIndex(int index);
}
internal class ItemsGridView : IItemsGridView
{
internal ItemsGridView(
DirectoryContentPanelMenu menu,
IDragAndDrop dragAndDrop,
EditorWindow parentWindow,
Action doubleClickAction,
Action navigateBackAction)
{
mMenu = menu;
mDragAndDrop = dragAndDrop;
mParentWindow = parentWindow;
mDoubleClickAction = doubleClickAction;
mNavigateBackAction = navigateBackAction;
mEmptyStatePanel = new EmptyStatePanel(parentWindow.Repaint);
mEmptyStatePanel.UpdateContent(GetEmptyStateText(nodes: null));
}
internal string GetItemsDirPath()
{
return mItemsDirPath;
}
internal int GetSelectedItemsCount()
{
return mSelectedItemsIndexes.Count;
}
internal ExpandedTreeNode GetSelectedItem()
{
if (mSelectedItemsIndexes.Count == 0)
return null;
return mItems[mSelectedItemsIndexes[0]];
}
internal List<string> GetSelectedItemsPaths()
{
List<string> result = new List<string>(mSelectedItemsIndexes.Count);
foreach (int selectedItemIndex in mSelectedItemsIndexes)
result.Add(mItems[selectedItemIndex].GetFullPath());
return result;
}
internal void CleanItems()
{
mItemsDirPath = null;
mItems = null;
mEmptyStatePanel.UpdateContent(GetEmptyStateText(nodes: null));
ClearSelection();
}
internal void ClearSelection()
{
mSelectedItemsIndexes.Clear();
ClearScrollPosition();
}
internal void UpdateItems(string itemsDirPath, List<ExpandedTreeNode> items)
{
mItems = new List<ExpandedTreeNode>();
foreach (ExpandedTreeNode item in items)
{
if (ExpandedTreeNode.IsOnDisk(item))
mItems.Add(item);
}
mItemsDirPath = itemsDirPath;
mEmptyStatePanel.UpdateContent(GetEmptyStateText(mItems));
}
internal void SelectItemsFromPaths(List<string> itemsPathsToSelect)
{
mSelectedItemsIndexes.Clear();
Dictionary<string, int> indexesByPath = new Dictionary<string, int>();
for (int i = 0; i < mItems.Count; i++)
indexesByPath[mItems[i].GetFullPath()] = i;
foreach (string itemPathToSelect in itemsPathsToSelect)
{
int index;
if (!indexesByPath.TryGetValue(itemPathToSelect, out index))
continue;
mSelectedItemsIndexes.Add(index);
}
}
internal void OnGUI(Rect rect, bool hasFocus)
{
int itemsCount = GetItemsCount();
UpdateSize(rect, itemsCount);
bool shouldScrollbarBeVisible =
mRows * mItemSize.y + 2 * DrawItemsGridView.GRID_AREA_MARGIN > rect.height;
if (!shouldScrollbarBeVisible)
ClearScrollPosition();
DrawItemsGridView.Draw(
rect, mEmptyStatePanel, this, mItems, mSelectedItemsIndexes, mItemSize,
mScrollPosition.y, mRows, mColumns, shouldScrollbarBeVisible, hasFocus,
mDragTargetIndex, ref mShouldShowEmptyState);
Event e = Event.current;
if (ProcessItemsGridViewEvent.IfNeeded(
e,
mMenu,
this,
mDragAndDrop,
mParentWindow,
mDoubleClickAction,
mNavigateBackAction,
mSelectedItemsIndexes,
rect,
mItemSize,
mScrollPosition.y,
mColumns,
itemsCount,
hasFocus,
shouldScrollbarBeVisible,
mItemsDirPath != null))
e.Use();
}
void IItemsGridView.ClearSelectedItems()
{
mSelectedItemsIndexes.Clear();
}
void IItemsGridView.SetSelection(List<int> itemIndexesToSelect)
{
if (itemIndexesToSelect.Count == 0)
{
ClearSelection();
return;
}
mSelectedItemsIndexes.Clear();
mSelectedItemsIndexes.AddRange(itemIndexesToSelect);
mScrollPosition.y = ItemsPosition.GetScrollPosition(
mRows,
mColumns,
mSelectedItemsIndexes[mSelectedItemsIndexes.Count - 1],
mItemSize.y,
mAvailableHeight,
mScrollPosition.y);
}
void IItemsGridView.UpdateScrollPosition(float scrollPosition)
{
mScrollPosition.y = scrollPosition;
}
void IItemsGridView.ClearDragTargetIndex()
{
mDragTargetIndex = -1;
}
void IItemsGridView.SetDragTargetIndexFromPath(string path)
{
if (path == mItemsDirPath)
{
mDragTargetIndex = -1;
return;
}
for (int i = 0; i < mItems.Count; i++)
{
if (mItems[i].GetFullPath() == path)
{
mDragTargetIndex = i;
return;
}
}
mDragTargetIndex = -1;
}
string IItemsGridView.GetDragTargetPathFromIndex(int index)
{
if (index < 0 || index >= GetItemsCount())
return mItemsDirPath;
ExpandedTreeNode dragTargetNode = mItems[index];
if (!ExpandedTreeNode.IsDirectory(dragTargetNode))
return mItemsDirPath;
return dragTargetNode.GetFullPath();
}
void ClearScrollPosition()
{
mScrollPosition.y = 0;
}
void UpdateSize(Rect rect, int itemsCount)
{
mAvailableHeight = rect.height;
if (itemsCount == 0)
{
mColumns = 0;
mRows = 0;
mItemSize = Vector2.zero;
return;
}
float availableItemsWidth = rect.width - DrawItemsGridView.GRID_AREA_MARGIN * 2;
mColumns = Math.Max(
1, (int)(availableItemsWidth / (DrawExpandedTreeNode.ICON_SIZE + 2 * DrawExpandedTreeNode.PADDING)));
mRows = Mathf.CeilToInt((float)itemsCount / mColumns);
float itemWidth = availableItemsWidth / mColumns;
float itemHeight = DrawExpandedTreeNode.ICON_SIZE
+ ((GUIStyle)UnityStyles.CloudDrive.ItemsListLabel).lineHeight
+ 2 * DrawExpandedTreeNode.PADDING;
mItemSize = new Vector2(itemWidth, itemHeight);
}
int GetItemsCount()
{
if (mItems == null)
return 0;
return mItems.Count;
}
static string GetEmptyStateText(List<ExpandedTreeNode> nodes)
{
if (nodes == null)
return PlasticLocalization.Name.NoDirectorySelectedEmptyState.GetString();
return nodes.Count == 0 ?
PlasticLocalization.Name.EmptyDirectoryEmptyState.GetString() :
string.Empty;
}
bool mShouldShowEmptyState;
int mRows;
int mColumns;
float mAvailableHeight;
Vector2 mItemSize;
Vector2 mScrollPosition;
int mDragTargetIndex = -1;
string mItemsDirPath;
List<ExpandedTreeNode> mItems;
readonly List<int> mSelectedItemsIndexes = new List<int>();
readonly EmptyStatePanel mEmptyStatePanel;
readonly DirectoryContentPanelMenu mMenu;
readonly IDragAndDrop mDragAndDrop;
readonly EditorWindow mParentWindow;
readonly Action mDoubleClickAction;
readonly Action mNavigateBackAction;
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: f14e29936e8d4feb9bb398b7cbb8fd5a
timeCreated: 1748341831
@@ -0,0 +1,109 @@
using UnityEngine;
using Unity.PlasticSCM.Editor.UI;
namespace Unity.PlasticSCM.Editor.CloudDrive.Workspaces.DirectoryContent
{
internal static class ItemsPosition
{
internal static bool IsMousePositionInsideGrid(
Vector2 mousePosition,
Rect rect,
bool isScrollbarVisible)
{
if (mousePosition.y < 0 || mousePosition.y > rect.height)
return false;
if (isScrollbarVisible)
rect.width -= UnityConstants.SCROLLBAR_WIDTH;
if (mousePosition.x < 0 || mousePosition.x > rect.width)
return false;
return true;
}
internal static bool IsMousePositionNearTopEdge(
Vector2 mousePosition)
{
return mousePosition.y < 10;
}
internal static bool IsMousePositionNearBottomEdge(
Vector2 mousePosition,
Rect rect)
{
return mousePosition.y > rect.height - 10;
}
internal static int GetItemIndexFromMousePosition(
Vector2 mousePosition,
Vector2 itemSize,
float scrollPosition,
int columnsCount,
int itemsCount)
{
Vector2 itemsGridContentMousePosition =
new Vector2(
mousePosition.x - DrawItemsGridView.GRID_AREA_MARGIN,
mousePosition.y - DrawItemsGridView.GRID_AREA_MARGIN + scrollPosition);
if (itemsGridContentMousePosition.x < 0 || itemsGridContentMousePosition.y < 0)
return -1;
if (itemsGridContentMousePosition.x > itemSize.x * columnsCount)
return -1;
int col = (int)(itemsGridContentMousePosition.x / itemSize.x);
int row = (int)(itemsGridContentMousePosition.y / itemSize.y);
if (row * columnsCount + col >= itemsCount)
return -1;
Vector2 itemMousePosition =
new Vector2(
itemsGridContentMousePosition.x - (col * itemSize.x),
itemsGridContentMousePosition.y - (row * itemSize.y));
if (itemMousePosition.x < DrawExpandedTreeNode.PADDING ||
itemMousePosition.x > itemSize.x - DrawExpandedTreeNode.PADDING ||
itemMousePosition.y < DrawExpandedTreeNode.PADDING ||
itemMousePosition.y > itemSize.y - DrawExpandedTreeNode.PADDING)
{
return -1;
}
return row * columnsCount + col;
}
internal static float GetScrollPosition(
int rowsCount,
int columnsCount,
int itemIndex,
float itemHeight,
float availableHeight,
float scrollPosition)
{
int row = itemIndex / columnsCount;
if (row == 0)
return 0;
if (row == rowsCount - 1)
return itemHeight * rowsCount + 2 * DrawItemsGridView.GRID_AREA_MARGIN - availableHeight;
float top = itemHeight * row + DrawItemsGridView.GRID_AREA_MARGIN;
float bottom = top + itemHeight;
float targetPosition = scrollPosition;
if (bottom > availableHeight + scrollPosition)
targetPosition = bottom - availableHeight;
if (top < scrollPosition)
targetPosition = top;
return Mathf.Max(targetPosition, 0f);
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 583732806f7c49c3aece28f1c2ad8d7b
timeCreated: 1747998962
@@ -0,0 +1,172 @@
using System.IO;
using UnityEditor;
using UnityEngine;
using Codice.Client.Common;
using PlasticGui;
using Unity.PlasticSCM.Editor.UI;
namespace Unity.PlasticSCM.Editor.CloudDrive.Workspaces.DirectoryContent
{
internal class NewNameDialog : PlasticDialog
{
protected override Rect DefaultRect
{
get
{
var baseRect = base.DefaultRect;
return new Rect(baseRect.x, baseRect.y, 500, 200);
}
}
internal static string GetNewNameForCreate(
string parentPath,
bool bIsDirectory,
EditorWindow parentWindow)
{
return GetNewName(
parentPath, string.Empty, bIsDirectory, true, parentWindow);
}
internal static string GetNewNameForRename(
string parentPath,
string currentName,
bool bIsDirectory,
EditorWindow parentWindow)
{
return GetNewName(
parentPath, currentName, bIsDirectory, false, parentWindow);
}
static string GetNewName(
string parentPath,
string currentName,
bool bIsDirectory,
bool bIsCreation,
EditorWindow parentWindow)
{
NewNameDialog dialog = Create(
parentPath,
currentName,
bIsDirectory,
bIsCreation);
ResponseType dialogResult = dialog.RunModal(parentWindow);
if (dialogResult != ResponseType.Ok)
return string.Empty;
return dialog.mNewName;
}
static NewNameDialog Create(
string parentPath,
string currentName,
bool bIsDirectory,
bool bIsCreation)
{
var instance = CreateInstance<NewNameDialog>();
instance.mParentPath = parentPath;
instance.mCurrentName = currentName;
instance.mNewName = currentName;
instance.mIsCreation = bIsCreation;
instance.mIsDirectory = bIsDirectory;
instance.mEnterKeyAction = instance.OkButtonAction;
instance.mEscapeKeyAction = instance.CancelButtonAction;
instance.mOkButtonText = bIsCreation ?
PlasticLocalization.Name.CreateButton.GetString() :
PlasticLocalization.Name.RenameButton.GetString();
return instance;
}
protected override string GetTitle()
{
if (mIsCreation)
return mIsDirectory ?
PlasticLocalization.Name.NewDirectoryTitle.GetString() :
PlasticLocalization.Name.NewFileTitle.GetString();
return mIsDirectory ?
PlasticLocalization.Name.RenameDirectoryTitle.GetString() :
PlasticLocalization.Name.RenameFileTitle.GetString();
}
protected override void DoComponentsArea()
{
using (new EditorGUILayout.HorizontalScope())
{
string labelText = mIsCreation ?
PlasticLocalization.Name.Name.GetString() :
PlasticLocalization.Name.NewName.GetString();
GUILayout.Label(labelText, GUILayout.ExpandWidth(false));
GUILayout.Space(10f);
GUI.SetNextControlName(NEW_NAME_TEXTAREA_NAME);
mNewName = GUILayout.TextField(
mNewName,
GUILayout.ExpandWidth(true));
FocusTextAreaIfNeeded(NEW_NAME_TEXTAREA_NAME);
}
}
internal override void OkButtonAction()
{
if (!IsValidInput(mParentPath, mCurrentName, mNewName, mProgressControls))
return;
base.OkButtonAction();
}
static bool IsValidInput(
string parentPath,
string oldName,
string newName,
IProgressControls progressControls)
{
if (string.IsNullOrEmpty(newName))
{
progressControls.ShowError(
PlasticLocalization.Name.ItemNameEmpty.GetString());
return false;
}
if (newName == oldName)
{
progressControls.ShowError(
PlasticLocalization.Name.ProvideDifferentItemName.GetString());
return false;
}
if (!PathHelper.IsCaseInsensitiveFsSameName(oldName, newName) &&
IsOnDisk(Path.Combine(parentPath, newName)))
{
progressControls.ShowError(
PlasticLocalization.Name.ItemExists.GetString(newName));
return false;
}
return true;
}
static bool IsOnDisk(string path)
{
return Directory.Exists(path) || File.Exists(path);
}
string mParentPath;
string mCurrentName;
string mNewName;
bool mIsCreation;
bool mIsDirectory;
const string NEW_NAME_TEXTAREA_NAME = "new_name_textarea";
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: bc4f0ef4de664ad4db65a2ea866ffa47
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,174 @@
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using Codice.Client.Common;
namespace Unity.PlasticSCM.Editor.CloudDrive.Workspaces.DirectoryContent
{
internal static class ProcessDragEvent
{
internal static void ProcessMouseDrag(
IDragAndDrop dragAndDrop,
EditorWindow parentWindow)
{
List<string> selectedPaths = dragAndDrop.GetDragSourcePaths();
if (selectedPaths.Count == 0)
return;
UnityEditor.DragAndDrop.PrepareStartDrag();
UnityEditor.DragAndDrop.paths = selectedPaths.ToArray();
UnityEditor.DragAndDrop.objectReferences = new Object[] { parentWindow };
UnityEditor.DragAndDrop.StartDrag(string.Empty);
}
internal static void ProcessDragExited(
IItemsGridView itemsGridView,
IDragAndDrop dragAndDrop)
{
itemsGridView.ClearDragTargetIndex();
dragAndDrop.ClearDragTargetPath();
}
internal static void ProcessDragUpdated(
IItemsGridView itemsGridView,
IDragAndDrop dragAndDrop,
EditorWindow parentWindow,
Vector2 mousePosition,
Rect rect,
Vector2 itemSize,
float scrollPosition,
int columnsCount,
int itemsCount,
bool isScrollbarVisible)
{
string dragTargetPath;
if (!IsValidDragTarget(
itemsGridView,
parentWindow,
mousePosition,
rect,
itemSize,
scrollPosition,
columnsCount,
itemsCount,
isScrollbarVisible,
out dragTargetPath))
{
itemsGridView.ClearDragTargetIndex();
dragAndDrop.ClearDragTargetPath();
return;
}
UnityEditor.DragAndDrop.visualMode = DragAndDropVisualMode.Copy;
itemsGridView.SetDragTargetIndexFromPath(dragTargetPath);
}
internal static void ProcessDragPerform(
IItemsGridView itemsGridView,
IDragAndDrop dragAndDrop,
EditorWindow parentWindow,
Vector2 mousePosition,
Rect rect,
Vector2 itemSize,
float scrollPosition,
int columnsCount,
int itemsCount,
bool isScrollbarVisible)
{
string dragTargetPath;
if (!IsValidDragTarget(
itemsGridView,
parentWindow,
mousePosition,
rect,
itemSize,
scrollPosition,
columnsCount,
itemsCount,
isScrollbarVisible,
out dragTargetPath))
{
itemsGridView.ClearDragTargetIndex();
dragAndDrop.ClearDragTargetPath();
return;
}
itemsGridView.SetDragTargetIndexFromPath(dragTargetPath);
dragAndDrop.SetDragTargetPath(dragTargetPath);
dragAndDrop.ExecuteDropAction(UnityEditor.DragAndDrop.paths);
}
static bool IsValidDragTarget(
IItemsGridView itemsGridView,
EditorWindow parentWindow,
Vector2 mousePosition,
Rect rect,
Vector2 itemSize,
float scrollPosition,
int columnsCount,
int itemsCount,
bool isScrollbarVisible,
out string dragTargetPath)
{
dragTargetPath = string.Empty;
mousePosition -= rect.position;
if (!ItemsPosition.IsMousePositionInsideGrid(mousePosition, rect, isScrollbarVisible))
return false;
UpdateScrollPositionIfMouseNearEdge(itemsGridView, scrollPosition, mousePosition, rect);
if (UnityEditor.DragAndDrop.objectReferences.Length != 0 &&
UnityEditor.DragAndDrop.objectReferences[0] == parentWindow)
{
return false;
}
dragTargetPath = itemsGridView.GetDragTargetPathFromIndex(
ItemsPosition.GetItemIndexFromMousePosition(
mousePosition, itemSize, scrollPosition, columnsCount, itemsCount));
if (IsAnyPathContainedOnDestination(UnityEditor.DragAndDrop.paths, dragTargetPath))
return false;
return true;
}
static bool IsAnyPathContainedOnDestination(
string[] srcPaths,
string dstPath)
{
foreach (string srcPath in srcPaths)
{
if (PathHelper.IsContainedOn(srcPath, dstPath))
return true;
}
return false;
}
static void UpdateScrollPositionIfMouseNearEdge(
IItemsGridView itemsGridView,
float scrollPosition,
Vector2 mousePosition,
Rect rect)
{
if (ItemsPosition.IsMousePositionNearTopEdge(mousePosition))
{
itemsGridView.UpdateScrollPosition(
scrollPosition - ProcessItemsGridViewEvent.VERTICAL_SCROLL_STEP);
return;
}
if (ItemsPosition.IsMousePositionNearBottomEdge(mousePosition, rect))
{
itemsGridView.UpdateScrollPosition(
scrollPosition + ProcessItemsGridViewEvent.VERTICAL_SCROLL_STEP);
}
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 906bc1afa6344104953c1f8f08e54b11
timeCreated: 1752737204
@@ -0,0 +1,443 @@
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEditor;
using Unity.PlasticSCM.Editor.UI;
namespace Unity.PlasticSCM.Editor.CloudDrive.Workspaces.DirectoryContent
{
internal static class ProcessItemsGridViewEvent
{
internal const int VERTICAL_SCROLL_STEP = 20;
internal static bool IfNeeded(
Event e,
DirectoryContentPanelMenu menu,
IItemsGridView itemsGridView,
IDragAndDrop dragAndDrop,
EditorWindow parentWindow,
Action doubleClickAction,
Action navigateBackAction,
List<int> selectedItemsIndexes,
Rect rect,
Vector2 itemSize,
float scrollPosition,
int columnsCount,
int itemsCount,
bool hasFocus,
bool isScrollbarVisible,
bool isDragAvailable)
{
if (isScrollbarVisible &&
ProcessScrollWheelIfNeeded(e, itemsGridView, scrollPosition))
return true;
if (ProcessMouseClickIfNeeded(
e, menu, itemsGridView, doubleClickAction, selectedItemsIndexes, rect, itemSize,
scrollPosition, columnsCount, itemsCount, isScrollbarVisible))
return true;
if (hasFocus &&
ProcessKeyDownIfNeeded(
e, menu, itemsGridView, navigateBackAction,
selectedItemsIndexes, columnsCount, itemsCount))
return true;
if (ProcessMouseDragIfNeeded(
e, itemsGridView, dragAndDrop, parentWindow, rect, itemSize, scrollPosition,
columnsCount, itemsCount, isScrollbarVisible, isDragAvailable))
return true;
return false;
}
static bool ProcessScrollWheelIfNeeded(
Event e,
IItemsGridView itemsGridView,
float scrollPosition)
{
if (e.type != EventType.ScrollWheel)
return false;
itemsGridView.UpdateScrollPosition(
scrollPosition + e.delta.y * VERTICAL_SCROLL_STEP);
return true;
}
static bool ProcessMouseClickIfNeeded(
Event e,
DirectoryContentPanelMenu menu,
IItemsGridView itemsGridView,
Action doubleClickAction,
List<int> selectedItemsIndexes,
Rect rect,
Vector2 itemSize,
float scrollPosition,
int columnsCount,
int itemsCount,
bool isScrollbarVisible)
{
if (e.type != EventType.MouseDown &&
e.type != EventType.MouseUp)
return false;
Vector2 mousePosition = e.mousePosition - rect.position;
if (!ItemsPosition.IsMousePositionInsideGrid(
mousePosition, rect, isScrollbarVisible))
{
return false;
}
int itemIndexToSelect = ItemsPosition.GetItemIndexFromMousePosition(
mousePosition, itemSize, scrollPosition, columnsCount, itemsCount);
bool shouldUpdateSelection = ShouldUpdateSelection(
selectedItemsIndexes.Contains(itemIndexToSelect),
Keyboard.HasControlOrCommandModifier(e),
Mouse.IsRightMouseButtonPressed(e),
e.type == EventType.MouseDown);
if (ProcessMouseDownIfNeeded(
e,
itemsGridView,
doubleClickAction,
selectedItemsIndexes,
itemIndexToSelect,
shouldUpdateSelection))
return true;
if (ProcessMouseUpIfNeeded(
e,
menu,
itemsGridView,
selectedItemsIndexes,
itemIndexToSelect,
shouldUpdateSelection))
return true;
return false;
}
static bool ProcessMouseDownIfNeeded(
Event e,
IItemsGridView itemsGridView,
Action doubleClickAction,
List<int> selectedItemsIndexes,
int itemIndexToSelect,
bool shouldUpdateSelection)
{
if (e.type != EventType.MouseDown)
return false;
if (Mouse.IsLeftMouseButtonDoubleClicked(e))
{
if (itemIndexToSelect == -1)
return false;
doubleClickAction();
return true;
}
if (!shouldUpdateSelection)
return true;
HandleMouseSelection(
itemsGridView, selectedItemsIndexes, itemIndexToSelect,
Keyboard.HasControlOrCommandModifier(e),
Keyboard.HasShiftModifier(e));
return true;
}
static bool ProcessMouseUpIfNeeded(
Event e,
DirectoryContentPanelMenu menu,
IItemsGridView itemsGridView,
List<int> selectedItemsIndexes,
int itemIndexToSelect,
bool shouldUpdateSelection)
{
if (e.type != EventType.MouseUp)
return false;
if (Mouse.IsLeftMouseButtonDoubleClicked(e))
return false;
if (Mouse.IsRightMouseButtonPressed(e))
{
menu.Popup();
return true;
}
if (!shouldUpdateSelection)
return true;
HandleMouseSelection(
itemsGridView, selectedItemsIndexes, itemIndexToSelect,
Keyboard.HasControlOrCommandModifier(e),
Keyboard.HasShiftModifier(e));
return true;
}
static bool ProcessKeyDownIfNeeded(
Event e,
DirectoryContentPanelMenu menu,
IItemsGridView itemsGridView,
Action navigateBackAction,
List<int> selectedItemsIndexes,
int columnsCount,
int itemsCount)
{
if (e.type != EventType.KeyDown)
return false;
if (menu.ProcessKeyActionIfNeeded(e))
return true;
bool shouldExtendSelection =
Keyboard.HasControlOrCommandModifier(e) ||
Keyboard.HasShiftModifier(e);
switch (e.keyCode)
{
case KeyCode.Backspace:
navigateBackAction();
break;
case KeyCode.UpArrow:
HandleKeyboardSelection(
itemsGridView,
selectedItemsIndexes,
GetItemIndexToSelectForOffset(selectedItemsIndexes, -columnsCount),
itemsCount,
shouldExtendSelection);
break;
case KeyCode.DownArrow:
HandleKeyboardSelection(
itemsGridView,
selectedItemsIndexes,
GetItemIndexToSelectForOffset(selectedItemsIndexes, columnsCount),
itemsCount,
shouldExtendSelection);
break;
case KeyCode.LeftArrow:
HandleKeyboardSelection(
itemsGridView,
selectedItemsIndexes,
GetItemIndexToSelectForOffset(selectedItemsIndexes, -1),
itemsCount,
shouldExtendSelection);
break;
case KeyCode.RightArrow:
HandleKeyboardSelection(
itemsGridView,
selectedItemsIndexes,
GetItemIndexToSelectForOffset(selectedItemsIndexes, 1),
itemsCount,
shouldExtendSelection);
break;
}
return true;
}
static bool ProcessMouseDragIfNeeded(
Event e,
IItemsGridView itemsGridView,
IDragAndDrop dragAndDrop,
EditorWindow parentWindow,
Rect rect,
Vector2 itemSize,
float scrollPosition,
int columnsCount,
int itemsCount,
bool isScrollbarVisible,
bool isDragAvailable)
{
if (!isDragAvailable)
return false;
if (e.type == EventType.MouseDrag)
{
ProcessDragEvent.ProcessMouseDrag(dragAndDrop, parentWindow);
return true;
}
if (e.type == EventType.DragExited)
{
ProcessDragEvent.ProcessDragExited(itemsGridView, dragAndDrop);
return true;
}
if (e.type == EventType.DragUpdated)
{
ProcessDragEvent.ProcessDragUpdated(
itemsGridView,
dragAndDrop,
parentWindow,
e.mousePosition,
rect,
itemSize,
scrollPosition,
columnsCount,
itemsCount,
isScrollbarVisible);
return true;
}
if (e.type == EventType.DragPerform)
{
ProcessDragEvent.ProcessDragPerform(
itemsGridView,
dragAndDrop,
parentWindow,
e.mousePosition,
rect,
itemSize,
scrollPosition,
columnsCount,
itemsCount,
isScrollbarVisible);
return true;
}
return false;
}
static void HandleMouseSelection(
IItemsGridView itemsGridView,
List<int> selectedItemsIndexes,
int itemIndexToSelect,
bool shouldToggleSelection,
bool shouldExtendSelection)
{
if (itemIndexToSelect == -1)
{
itemsGridView.ClearSelectedItems();
return;
}
List<int> indexesToSelect = GetItemsIndexesToSelect(
selectedItemsIndexes, itemIndexToSelect,
shouldToggleSelection, shouldExtendSelection);
if (indexesToSelect.Count == 0)
{
itemsGridView.ClearSelectedItems();
return;
}
itemsGridView.SetSelection(indexesToSelect);
}
static void HandleKeyboardSelection(
IItemsGridView itemsGridView,
List<int> selectedItemsIndexes,
int itemIndexToSelect,
int itemsCount,
bool shouldExtendSelection)
{
if (itemIndexToSelect < 0 || itemIndexToSelect >= itemsCount)
return;
List<int> indexesToSelect = GetItemsIndexesToSelect(
selectedItemsIndexes, itemIndexToSelect,
false, shouldExtendSelection);
if (indexesToSelect.Count == 0)
{
itemsGridView.ClearSelectedItems();
return;
}
itemsGridView.SetSelection(indexesToSelect);
}
static bool ShouldUpdateSelection(
bool clickedOnSelection,
bool hasControlPressed,
bool isRightClick,
bool isMouseDown)
{
if (isRightClick)
return !clickedOnSelection && !hasControlPressed && isMouseDown;
if (clickedOnSelection && !hasControlPressed)
return !isMouseDown;
return isMouseDown;
}
static int GetItemIndexToSelectForOffset(
List<int> selectedItemsIndexes,
int offset)
{
if (selectedItemsIndexes.Count == 0)
return 0;
return selectedItemsIndexes.Last() + offset;
}
static List<int> GetItemsIndexesToSelect(
List<int> selectedItemsIndexes,
int indexToSelect,
bool shouldToggleSelection,
bool shouldExtendSelection)
{
if (shouldExtendSelection)
{
return GetItemsIndexesToSelectByExtending(
selectedItemsIndexes, indexToSelect);
}
if (shouldToggleSelection)
{
return GetItemsIndexesToSelectByToggling(
selectedItemsIndexes, indexToSelect);
}
return new List<int> { indexToSelect };
}
static List<int> GetItemsIndexesToSelectByExtending(
IList<int> selectedItemsIndexes,
int target)
{
int anchor = selectedItemsIndexes.FirstOrDefault();
int direction = anchor < target ? 1 : -1;
int count = Math.Abs(target - anchor);
List<int> result = new List<int>();
for (int i = 0; i <= count; i++)
result.Add(anchor + i * direction);
return result;
}
static List<int> GetItemsIndexesToSelectByToggling(
IList<int> selectedItemsIndexes,
int target)
{
List<int> result = new List<int>(selectedItemsIndexes);
if (result.Contains(target))
{
result.Remove(target);
return result;
}
result.Add(target);
return result;
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 6de94dccb9344367a5c94b087d3cc1e2
timeCreated: 1749560562
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 8ca43dc9595f9ff41b68d7bd4cc66c2f
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,56 @@
using UnityEditor;
using Codice.Client.Common;
using PlasticGui;
using PlasticGui.CloudDrive;
using Unity.PlasticSCM.Editor.AssetUtils;
using Unity.PlasticSCM.Editor.UI;
namespace Unity.PlasticSCM.Editor.CloudDrive.Workspaces.DragAndDrop
{
internal class AskUserForExistingFile : CopyPathsOperation.IAskUserForExistingFile
{
internal AskUserForExistingFile(EditorWindow parentWindow)
{
mParentWindow = parentWindow;
}
CopyPathsOperation.CopyAction CopyPathsOperation.IAskUserForExistingFile.Ask(
string filePath,
bool showApplyToAllCheckbox,
out bool applyToAll)
{
GuiMessage.GuiMessageResponseButton response = DialogWithCheckBox.Show(
PlasticLocalization.Name.AskUserForExistingFileTitle.GetString(),
PlasticLocalization.Name.AskUserForExistingFileMessage.GetString(
AssetsPath.GetFullPath.ForPath(filePath)),
PlasticLocalization.Name.ReplaceButton.GetString(),
PlasticLocalization.Name.KeepBothButton.GetString(),
PlasticLocalization.Name.SkipButton.GetString(),
GuiMessage.GuiMessageType.Warning,
showApplyToAllCheckbox ?
new MultiLinkLabelData(PlasticLocalization.Name.ApplyToAllFollowingFiles.GetString()) :
null,
mParentWindow,
out applyToAll);
switch (response)
{
case GuiMessage.GuiMessageResponseButton.Positive:
return CopyPathsOperation.CopyAction.Replace;
case GuiMessage.GuiMessageResponseButton.Neutral:
return CopyPathsOperation.CopyAction.KeepBoth;
case GuiMessage.GuiMessageResponseButton.Negative:
return CopyPathsOperation.CopyAction.Skip;
case GuiMessage.GuiMessageResponseButton.None:
default:
return CopyPathsOperation.CopyAction.Cancel;
}
}
readonly EditorWindow mParentWindow;
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 509ecc6807ba438a92fbda6424603ecb
timeCreated: 1750088468
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 4bf7a307054547ce958185ee96f94aed
timeCreated: 1748001685
@@ -0,0 +1,15 @@
using System.Collections.Generic;
using PlasticGui.WorkspaceWindow.Items;
namespace Unity.PlasticSCM.Editor.CloudDrive.Workspaces.Tree
{
internal static class CloudWorkspacesSelection
{
internal static List<ExpandedTreeNode> GetSelectedNodes(
CloudWorkspacesTreeView treeView)
{
return treeView.GetSelectedNodes();
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 72b48557f4cf3d8438cbf59b123364ff
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,811 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnityEditor;
using UnityEditor.IMGUI.Controls;
using UnityEngine;
using Codice.Client.Common;
using Codice.CM.Common;
using Codice.Utils;
using PlasticGui;
using PlasticGui.CloudDrive.Workspaces;
using PlasticGui.WorkspaceWindow.Items;
using Unity.PlasticSCM.Editor.CloudDrive.ShareWorkspace;
using Unity.PlasticSCM.Editor.CloudDrive.Workspaces.DirectoryContent;
using Unity.PlasticSCM.Editor.UI;
using Unity.PlasticSCM.Editor.UI.Progress;
using Unity.PlasticSCM.Editor.UI.Tree;
using Unity.PlasticSCM.Editor.Views;
#if UNITY_6000_2_OR_NEWER
using TreeViewItem = UnityEditor.IMGUI.Controls.TreeViewItem<int>;
#endif
namespace Unity.PlasticSCM.Editor.CloudDrive.Workspaces.Tree
{
internal class CloudWorkspacesTreeView :
PlasticTreeView,
FillCloudWorkspaces.ICloudWorkspacesTree,
DirectoryContentPanel.ICloudWorkspacesTreeView,
ICloudWorkspacesTreeMenuOperations
{
internal float Width { get { return mLastValidWidth; } }
internal WorkspaceInfo WorkspaceToSelect { set { mWorkspaceToSelect = value; } }
internal CloudWorkspacesTreeView(
Action delayedSelectionChangedAction,
IProgressControls progressControls,
EditorWindow parentWindow) : base(showCustomBackground: false)
{
mDelayedSelectionChangedAction = delayedSelectionChangedAction;
mProgressControls = progressControls;
mParentWindow = parentWindow;
mDelayedSelectionRunner = new DelayedActionBySecondsRunner(
DelayedSelectionChanged, UnityConstants.SELECTION_DELAYED_INPUT_ACTION_INTERVAL);
mMenu = new CloudWorkspacesTreeViewMenu(this);
rowHeight = 16;
}
protected override bool CanChangeExpandedState(TreeViewItem item)
{
if (item is CloudWorkspacesLabelTreeViewItem)
return false;
return ((CloudWorkspacesTreeViewItem)item).IsExpandable;
}
protected override IList<TreeViewItem> BuildRows(TreeViewItem rootItem)
{
RegenerateRows(
mMyDrivesByWorkspace.Values.ToList(),
mDrivesSharedWithMeByWorkspace.Values.ToList(),
mTreeViewItemIds,
this,
rootItem,
mRows);
SelectWorkspaceIfNeeded();
if (GetSelectedNode() != null)
DelayedSelectionChanged();
return mRows;
}
protected override float GetCustomRowHeight(int row, TreeViewItem item)
{
if (item is CloudWorkspacesLabelTreeViewItem)
return 30f;
return base.GetCustomRowHeight(row, item);
}
public override void OnGUI(Rect rect)
{
if (Event.current.type == EventType.Repaint && mLastValidWidth != rect.width)
mLastValidWidth = rect.width;
base.OnGUI(rect);
if (!HasFocus())
return;
Event e = Event.current;
if (e.type != EventType.KeyDown)
return;
bool isProcessed = mMenu.ProcessKeyActionIfNeeded(e);
if (isProcessed)
e.Use();
}
protected override void ContextClickedItem(int id)
{
mMenu.Popup();
Repaint();
}
protected override void RowGUI(RowGUIArgs args)
{
if (args.item is CloudWorkspacesLabelTreeViewItem)
{
EditorGUI.LabelField(
args.rowRect,
((CloudWorkspacesLabelTreeViewItem)args.item).Label,
UnityStyles.Tree.BoldLabelWithMargin);
return;
}
if (args.item is CloudWorkspacesTreeViewItem)
{
CloudWorkspacesTreeViewItem item = (CloudWorkspacesTreeViewItem)args.item;
args.rowRect.width = mLastValidWidth;
WorkspaceContentTreeViewItemGUI(
args.rowRect,
this,
item,
GetProgressControlsDataForNode(
item.ExpandedTreeNode,
mProgressControlsByWorkspace),
args.selected,
args.focused);
return;
}
base.RowGUI(args);
}
protected override void SelectionChanged(IList<int> selectedIds)
{
List<int> selectedIdsToSet = new List<int>();
foreach (int selectedId in selectedIds)
{
ExpandedTreeNode selectedNode;
if (mTreeViewItemIds.TryGetItemById(selectedId, out selectedNode))
selectedIdsToSet.Add(selectedId);
}
SetSelection(selectedIdsToSet);
mDelayedSelectionRunner.Run();
}
protected override void ExpandedStateChanged()
{
IList<int> expandedIds = GetExpanded();
ReloadExpandedTreeNodes(
expandedIds.Except(mLastExpandedIds),
mTreeViewItemIds,
mMyDrivesByWorkspace,
mDrivesSharedWithMeByWorkspace);
mLastExpandedIds = expandedIds;
}
internal bool IsOperationRunning()
{
foreach (ProgressControlsForViews progressControls
in mProgressControlsByWorkspace.Values)
{
if (progressControls.IsOperationRunning())
return true;
}
return false;
}
internal ProgressControlsForViews GetWorkspaceProgressControls(WorkspaceInfo wkInfo)
{
ProgressControlsForViews result;
if (mProgressControlsByWorkspace.TryGetValue(wkInfo, out result))
return result;
mProgressControlsByWorkspace[wkInfo] = new ProgressControlsForViews();
return mProgressControlsByWorkspace[wkInfo];
}
internal WorkspaceInfo GetSelectedWorkspaceInfo()
{
ExpandedTreeNode selectedNode = GetSelectedNode();
if (selectedNode == null)
return null;
return selectedNode.WkInfo;
}
internal ExpandedTreeNode GetSelectedNode()
{
IList<int> selectedIds = GetSelection();
if (selectedIds.Count != 1)
return null;
int selectedId = selectedIds[0];
ExpandedTreeNode result;
if (!mTreeViewItemIds.TryGetItemById(selectedId, out result))
return null;
return result;
}
internal List<ExpandedTreeNode> GetSelectedNodes()
{
List<ExpandedTreeNode> result = new List<ExpandedTreeNode>();
IList<int> selectedIds = GetSelection();
foreach (int selectedId in selectedIds)
{
ExpandedTreeNode selectedNode;
if (!mTreeViewItemIds.TryGetItemById(selectedId, out selectedNode))
continue;
result.Add(selectedNode);
}
return result;
}
internal void Update(EditorWindow parentWindow)
{
foreach (ProgressControlsForViews progressControls
in mProgressControlsByWorkspace.Values)
{
progressControls.UpdateProgress(parentWindow);
}
}
void FillCloudWorkspaces.ICloudWorkspacesTree.ExpandedTreesRetrieved(
List<ExpandedTree> myDrives,
List<ExpandedTree> drivesSharedWithMe)
{
mMyDrivesByWorkspace = BuildExpandedTrees(myDrives);
mDrivesSharedWithMeByWorkspace = BuildExpandedTrees(drivesSharedWithMe);
BuildProgressControls(
myDrives.Concat(drivesSharedWithMe),
mProgressControlsByWorkspace);
Reload();
}
void DirectoryContentPanel.ICloudWorkspacesTreeView.SelectNode(
string wkPath, string fullPath)
{
SelectNode(wkPath, fullPath);
}
int ICloudWorkspacesTreeMenuOperations.GetSelectedItemsCount()
{
return GetSelection().Count;
}
bool ICloudWorkspacesTreeMenuOperations.IsAnyNonRootItemSelected()
{
List<ExpandedTreeNode> selectedNodes = GetSelectedNodes();
foreach (ExpandedTreeNode node in selectedNodes)
{
if (!ExpandedTreeNode.IsRootNode(node))
return true;
}
return false;
}
bool ICloudWorkspacesTreeMenuOperations.IsAnySharedDriveSelected()
{
List<ExpandedTreeNode> selectedNodes = GetSelectedNodes();
foreach (ExpandedTreeNode node in selectedNodes)
{
if (mDrivesSharedWithMeByWorkspace.ContainsKey(node.WkInfo))
return true;
}
return false;
}
void ICloudWorkspacesTreeMenuOperations.OpenInExplorer()
{
List<ExpandedTreeNode> selectedNodes = GetSelectedNodes();
if (selectedNodes.Count != 1)
return;
FileSystemOperation.OpenInExplorer(selectedNodes[0].GetFullPath());
}
void ICloudWorkspacesTreeMenuOperations.OpenUnityCloud()
{
List<ExpandedTreeNode> selectedNodes = GetSelectedNodes();
if (selectedNodes.Count != 1)
return;
WorkspaceInfo workspaceInfo = selectedNodes[0].WkInfo;
RepositorySpec repSpec = PlasticGui.Plastic.API.GetRepositorySpec(workspaceInfo);
string cloudServer = CloudServer.GetOrganizationName(repSpec.Server);
RepositoryInfo repInfo = PlasticGui.Plastic.API.GetRepositoryInfo(repSpec);
OpenBrowser.TryOpen(UnityUrl.UnityDashboard.
CloudDrive.GetWorkspace(cloudServer, repInfo.GUID.ToString()));
}
void ICloudWorkspacesTreeMenuOperations.Delete()
{
List<ExpandedTreeNode> selectedNodes = GetSelectedNodes();
if (selectedNodes.Count != 1)
return;
WorkspaceInfo workspaceInfo = selectedNodes[0].WkInfo;
ProgressControlsForViews workspaceProgressControls =
GetWorkspaceProgressControls(workspaceInfo);
if (workspaceProgressControls.IsOperationRunning())
{
GuiMessage.ShowInformation(
PlasticLocalization.Name.OperationInProgress.GetString());
return;
}
string workspaceName = Path.GetFileName(workspaceInfo.ClientPath);
if (!DeleteWorkspaceDialog.UserConfirmsDelete(workspaceName, mParentWindow))
return;
DeleteWorkspaceOperation.DeleteWorkspace(
workspaceInfo,
mProgressControls,
Reload);
}
void ICloudWorkspacesTreeMenuOperations.Share()
{
List<ExpandedTreeNode> selectedNodes = GetSelectedNodes();
if (selectedNodes.Count != 1)
return;
WorkspaceInfo workspaceInfo = selectedNodes[0].WkInfo;
ProgressControlsForViews workspaceProgressControls =
GetWorkspaceProgressControls(workspaceInfo);
if (workspaceProgressControls.IsOperationRunning())
{
GuiMessage.ShowInformation(
PlasticLocalization.Name.OperationInProgress.GetString());
return;
}
List<SecurityMember> collaboratorsToAdd;
List<SecurityMember> collaboratorsToRemove;
if (!ShareWorkspaceDialog.ShareWorkspace(
workspaceInfo,
mParentWindow,
out collaboratorsToAdd,
out collaboratorsToRemove))
return;
WorkspaceShareOperations.ShareWorkspace(
workspaceInfo, collaboratorsToAdd, mProgressControls);
WorkspaceShareOperations.UnshareWorkspace(
workspaceInfo, collaboratorsToRemove, mProgressControls);
}
void ICloudWorkspacesTreeMenuOperations.UnshareWithMe()
{
List<ExpandedTreeNode> selectedNodes = GetSelectedNodes();
if (selectedNodes.Count != 1)
return;
WorkspaceInfo workspaceInfo = selectedNodes[0].WkInfo;
ProgressControlsForViews workspaceProgressControls =
GetWorkspaceProgressControls(workspaceInfo);
if (workspaceProgressControls.IsOperationRunning())
{
GuiMessage.ShowInformation(
PlasticLocalization.Name.OperationInProgress.GetString());
return;
}
if (!GuiMessage.ShowQuestion(
PlasticLocalization.Name.UnshareWithMeMenuItem.GetString(),
PlasticLocalization.Name.UnshareConfirmationMessage.GetString(),
PlasticLocalization.Name.UnshareButton.GetString()))
{
return;
}
WorkspaceShareOperations.UnshareWorkspaceWithMe(
workspaceInfo,
mProgressControls,
Reload);
}
void SelectWorkspaceIfNeeded()
{
if (mWorkspaceToSelect == null)
return;
int idToSelect;
if (!mTreeViewItemIds.TryGetItemIdByKey(mWorkspaceToSelect.ClientPath, out idToSelect))
return;
SetSelection(new List<int> { idToSelect });
mWorkspaceToSelect = null;
}
void DelayedSelectionChanged()
{
if (mIsSelectionChangedEventDisabled)
return;
IList<int> selectedIds = GetSelection();
if (selectedIds.Count == 1)
ReloadExpandedTreeNodeIfChildrenNotLoaded(
selectedIds[0],
mTreeViewItemIds,
mMyDrivesByWorkspace,
mDrivesSharedWithMeByWorkspace);
mDelayedSelectionChangedAction();
}
void SelectNode(string wkPath, string fullPath)
{
if (ExpandAncestors(wkPath, fullPath, mTreeViewItemIds, this))
Reload();
int idToSelect;
if (!mTreeViewItemIds.TryGetItemIdByKey(fullPath, out idToSelect))
return;
mIsSelectionChangedEventDisabled = true;
try
{
TableViewOperations.SetSelectionAndScroll(
this, new List<int> { idToSelect });
}
finally
{
mIsSelectionChangedEventDisabled = false;
}
DelayedSelectionChanged();
}
static void WorkspaceContentTreeViewItemGUI(
Rect rowRect,
CloudWorkspacesTreeView tree,
CloudWorkspacesTreeViewItem item,
ProgressControlsForViews.Data progressControlsData,
bool isSelected,
bool isFocused)
{
DrawTreeViewItem.ForIndentedItemWithIcon(
rowRect,
tree.rowHeight,
item.depth,
Path.GetFileName(item.ExpandedTreeNode.GetFullPath()),
string.Empty,
GetItemIcon(tree, item),
isSelected,
isFocused);
if (progressControlsData == null || !progressControlsData.IsOperationRunning)
return;
DoProgress(rowRect, progressControlsData);
}
static void DoProgress(
Rect rowRect,
ProgressControlsForViews.Data progressControlsData)
{
GUILayout.BeginArea(rowRect);
GUILayout.BeginHorizontal();
GUILayout.FlexibleSpace();
LoadingSpinner.OnGUI(
progressControlsData.ProgressPercent,
progressControlsData.ProgressMessage);
GUILayout.Space(2);
GUILayout.EndHorizontal();
GUILayout.EndArea();
}
static void ReloadExpandedTreeNodes(
IEnumerable<int> idsToReload,
TreeViewItemIds<ExpandedTreeNode> treeViewItemIds,
Dictionary<WorkspaceInfo, ExpandedTree> myDrivesByWorkspace,
Dictionary<WorkspaceInfo, ExpandedTree> drivesSharedWithMeByWorkspace)
{
foreach (int id in idsToReload)
{
ExpandedTreeNode node;
if (!treeViewItemIds.TryGetItemById(id, out node))
continue;
ExpandedTree expandedTree;
if (!myDrivesByWorkspace.TryGetValue(node.WkInfo, out expandedTree) &&
!drivesSharedWithMeByWorkspace.TryGetValue(node.WkInfo, out expandedTree))
continue;
expandedTree.ReloadNode(node);
}
}
static void ReloadExpandedTreeNodeIfChildrenNotLoaded(
int idToReload,
TreeViewItemIds<ExpandedTreeNode> treeViewItemIds,
Dictionary<WorkspaceInfo, ExpandedTree> myDrivesByWorkspace,
Dictionary<WorkspaceInfo, ExpandedTree> drivesSharedWithMeByWorkspace)
{
ExpandedTreeNode node;
if (!treeViewItemIds.TryGetItemById(idToReload, out node))
return;
if (node.GetChildren() != null)
return;
ExpandedTree expandedTree;
if (!myDrivesByWorkspace.TryGetValue(node.WkInfo, out expandedTree) &&
!drivesSharedWithMeByWorkspace.TryGetValue(node.WkInfo, out expandedTree))
return;
expandedTree.ReloadNode(node);
}
static bool ExpandAncestors(
string wkPath,
string nodePath,
TreeViewItemIds<ExpandedTreeNode> treeViewItemIds,
CloudWorkspacesTreeView treeView)
{
List<string> ancestors = GetAncestorsPaths(wkPath, nodePath);
bool result = false;
foreach (string ancestor in ancestors)
{
int ancestorId;
if (!treeViewItemIds.TryGetItemIdByKey(ancestor, out ancestorId))
continue;
if (treeView.IsExpanded(ancestorId))
continue;
treeView.SetExpanded(ancestorId, true);
result = true;
}
return result;
}
static void RegenerateRows(
List<ExpandedTree> myDrives,
List<ExpandedTree> drivesSharedWithMe,
TreeViewItemIds<ExpandedTreeNode> treeViewItemIds,
CloudWorkspacesTreeView treeView,
TreeViewItem rootItem,
List<TreeViewItem> rows)
{
ClearRows(rootItem, rows);
treeViewItemIds.ClearItems();
AddLabelRow(PlasticLocalization.Name.MyDrivesLabel.GetString(), treeViewItemIds, rows);
AddExpandedTrees(myDrives, treeViewItemIds, treeView, rootItem, rows);
AddLabelRow(
PlasticLocalization.Name.DrivesSharedWithMeLabel.GetString(), treeViewItemIds, rows);
AddExpandedTrees(drivesSharedWithMe, treeViewItemIds, treeView, rootItem, rows);
}
static void AddExpandedTrees(
List<ExpandedTree> expandedTrees,
TreeViewItemIds<ExpandedTreeNode> treeViewItemIds,
CloudWorkspacesTreeView treeView,
TreeViewItem rootItem,
List<TreeViewItem> rows)
{
foreach (ExpandedTree expandedTree in expandedTrees)
{
ExpandedTreeNode rootNode = expandedTree.GetRootNode();
if (rootNode == null)
continue;
AddNode(
rootNode,
expandedTree,
treeViewItemIds,
treeView,
rootItem,
rows);
}
}
static void AddLabelRow(
string label,
TreeViewItemIds<ExpandedTreeNode> treeViewItemIds,
List<TreeViewItem> rows)
{
int nodeId;
if (!treeViewItemIds.TryGetItemIdByKey(label, out nodeId))
nodeId = treeViewItemIds.AddItemIdByKey(label);
rows.Add(new CloudWorkspacesLabelTreeViewItem(nodeId, label));
}
static void AddNode(
ExpandedTreeNode node,
ExpandedTree expandedTree,
TreeViewItemIds<ExpandedTreeNode> treeViewItemIds,
CloudWorkspacesTreeView treeView,
TreeViewItem parentItem,
List<TreeViewItem> rows)
{
if (!ExpandedTreeNode.IsOnDisk(node))
return;
int nodeId;
if (!treeViewItemIds.TryGetItemIdByKey(node.GetFullPath(), out nodeId))
nodeId = treeViewItemIds.AddItemIdByKey(node.GetFullPath());
treeViewItemIds.AddItemById(nodeId, node);
CloudWorkspacesTreeViewItem viewItem =
new CloudWorkspacesTreeViewItem(
nodeId,
node,
Directory.GetDirectories(node.GetFullPath()).Length > 0,
parentItem.depth + 1);
rows.Add(viewItem);
parentItem.AddChild(viewItem);
if (!treeView.IsExpanded(nodeId))
return;
if (node.GetChildren() == null)
expandedTree.ReloadNode(node);
foreach (ExpandedTreeNode childNode in node.GetChildren())
{
if (!ExpandedTreeNode.IsDirectory(childNode))
continue;
AddNode(
childNode,
expandedTree,
treeViewItemIds,
treeView,
viewItem,
rows);
}
}
static void ClearRows(
TreeViewItem rootItem,
List<TreeViewItem> rows)
{
if (rootItem.hasChildren)
rootItem.children.Clear();
rows.Clear();
}
static Texture GetItemIcon(
CloudWorkspacesTreeView tree,
CloudWorkspacesTreeViewItem item)
{
if (item.parent.id == 0)
return Images.GetCloudWorkspaceIcon();
if (tree.IsExpanded(item.id))
return Images.GetFolderOpenedIcon();
return Images.GetFolderIcon();
}
static Dictionary<WorkspaceInfo, ExpandedTree> BuildExpandedTrees(
List<ExpandedTree> expandedTrees)
{
Dictionary<WorkspaceInfo, ExpandedTree> result =
new Dictionary<WorkspaceInfo, ExpandedTree>();
foreach (ExpandedTree expandedTree in expandedTrees)
result[expandedTree.WkInfo] = expandedTree;
return result;
}
static void BuildProgressControls(
IEnumerable<ExpandedTree> expandedTrees,
Dictionary<WorkspaceInfo, ProgressControlsForViews> progressControlsByWorkspace)
{
List<WorkspaceInfo> workspaceInfos = new List<WorkspaceInfo>();
foreach (ExpandedTree expandedTree in expandedTrees)
workspaceInfos.Add(expandedTree.GetRootNode().WkInfo);
for (int i = progressControlsByWorkspace.Keys.Count - 1; i >= 0; i--)
{
WorkspaceInfo wkInfo = progressControlsByWorkspace.Keys.ElementAt(i);
if (!workspaceInfos.Contains(wkInfo))
progressControlsByWorkspace.Remove(wkInfo);
}
foreach (WorkspaceInfo wkInfo in workspaceInfos)
{
if (progressControlsByWorkspace.ContainsKey(wkInfo))
continue;
progressControlsByWorkspace[wkInfo] = new ProgressControlsForViews();
}
}
static List<string> GetAncestorsPaths(
string wkPath,
string nodePath)
{
List<string> ancestors = new List<string>();
while (!PathHelper.IsSamePath(wkPath, nodePath))
{
nodePath = Directory.GetParent(nodePath).FullName;
ancestors.Add(nodePath);
}
ancestors.Reverse();
return ancestors;
}
static ProgressControlsForViews.Data GetProgressControlsDataForNode(
ExpandedTreeNode node,
Dictionary<WorkspaceInfo, ProgressControlsForViews> progressControlsByWorkspace)
{
if (!ExpandedTreeNode.IsRootNode(node))
return null;
ProgressControlsForViews progressControls;
if (!progressControlsByWorkspace.TryGetValue(
node.WkInfo,
out progressControls))
return null;
return progressControls.ProgressData;
}
float mLastValidWidth;
bool mIsSelectionChangedEventDisabled = false;
IEnumerable<int> mLastExpandedIds = new List<int>();
Dictionary<WorkspaceInfo, ExpandedTree> mMyDrivesByWorkspace =
new Dictionary<WorkspaceInfo, ExpandedTree>();
Dictionary<WorkspaceInfo, ExpandedTree> mDrivesSharedWithMeByWorkspace =
new Dictionary<WorkspaceInfo, ExpandedTree>();
WorkspaceInfo mWorkspaceToSelect;
readonly CloudWorkspacesTreeViewMenu mMenu;
readonly DelayedActionBySecondsRunner mDelayedSelectionRunner;
readonly Action mDelayedSelectionChangedAction;
readonly IProgressControls mProgressControls;
readonly EditorWindow mParentWindow;
readonly TreeViewItemIds<ExpandedTreeNode> mTreeViewItemIds =
new TreeViewItemIds<ExpandedTreeNode>();
readonly Dictionary<WorkspaceInfo, ProgressControlsForViews> mProgressControlsByWorkspace =
new Dictionary<WorkspaceInfo, ProgressControlsForViews>();
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: e69fc09d7758466798e76f1655c2c27f
timeCreated: 1746788531
@@ -0,0 +1,36 @@
using UnityEditor.IMGUI.Controls;
using PlasticGui.WorkspaceWindow.Items;
#if UNITY_6000_2_OR_NEWER
using TreeViewItem = UnityEditor.IMGUI.Controls.TreeViewItem<int>;
#endif
namespace Unity.PlasticSCM.Editor.CloudDrive.Workspaces.Tree
{
internal class CloudWorkspacesTreeViewItem : TreeViewItem
{
internal ExpandedTreeNode ExpandedTreeNode { get; private set; }
internal bool IsExpandable { get; private set; }
internal CloudWorkspacesTreeViewItem(
int id, ExpandedTreeNode expandedTreeNode, bool isExpandable, int depth)
: base(id, depth)
{
ExpandedTreeNode = expandedTreeNode;
IsExpandable = isExpandable;
displayName = expandedTreeNode.RelativePath;
}
}
internal class CloudWorkspacesLabelTreeViewItem : TreeViewItem
{
internal string Label { get; private set; }
internal CloudWorkspacesLabelTreeViewItem(int id, string label) : base(id, 0)
{
Label = label;
displayName = label;
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 7deb947d51d34c76aa03ec6d3a07a4ec
timeCreated: 1746788701
@@ -0,0 +1,268 @@
using System;
using UnityEditor;
using UnityEngine;
using Codice.Utils;
using PlasticGui;
using Unity.PlasticSCM.Editor.UI;
namespace Unity.PlasticSCM.Editor.CloudDrive.Workspaces.Tree
{
[Flags]
internal enum CloudWorkspacesTreeOperations : short
{
None = 0,
OpenInExplorer = 1 << 0,
OpenUnityCloud = 1 << 1,
Delete = 1 << 2,
Share = 1 << 3,
UnshareWithMe = 1 << 4,
}
internal static class CloudWorkspacesTreeMenuUpdater
{
internal static CloudWorkspacesTreeOperations GetAvailableMenuOperations(
int selectedItemsCount,
bool isAnyNonRootItemSelected,
bool isAnySharedDriveSelected)
{
CloudWorkspacesTreeOperations result = CloudWorkspacesTreeOperations.None;
if (selectedItemsCount != 1)
return result;
result |= CloudWorkspacesTreeOperations.OpenInExplorer;
if (isAnyNonRootItemSelected)
return result;
result |= CloudWorkspacesTreeOperations.Delete |
CloudWorkspacesTreeOperations.OpenUnityCloud;
if (isAnySharedDriveSelected)
result |= CloudWorkspacesTreeOperations.UnshareWithMe;
else
result |= CloudWorkspacesTreeOperations.Share;
return result;
}
}
internal interface ICloudWorkspacesTreeMenuOperations
{
int GetSelectedItemsCount();
bool IsAnyNonRootItemSelected();
bool IsAnySharedDriveSelected();
void OpenInExplorer();
void OpenUnityCloud();
void Delete();
void Share();
void UnshareWithMe();
}
internal class CloudWorkspacesTreeViewMenu
{
internal CloudWorkspacesTreeViewMenu(ICloudWorkspacesTreeMenuOperations operations)
{
mOperations = operations;
BuildComponents();
}
internal void Popup()
{
GenericMenu menu = new GenericMenu();
UpdateMenuItems(menu);
menu.ShowAsContext();
}
internal bool ProcessKeyActionIfNeeded(Event e)
{
CloudWorkspacesTreeOperations operationToExecute = GetMenuOperation(e);
if (operationToExecute == CloudWorkspacesTreeOperations.None)
return false;
int selectedCount = mOperations.GetSelectedItemsCount();
bool isAnyNonRootItemSelected = mOperations.IsAnyNonRootItemSelected();
bool isAnySharedDriveSelected = mOperations.IsAnySharedDriveSelected();
CloudWorkspacesTreeOperations operations =
CloudWorkspacesTreeMenuUpdater.GetAvailableMenuOperations(
selectedCount, isAnyNonRootItemSelected, isAnySharedDriveSelected);
if (!operations.HasFlag(operationToExecute))
return false;
ProcessMenuOperation(operationToExecute);
return true;
}
void OpenInExplorerMenuItem_Click()
{
mOperations.OpenInExplorer();
}
void OpenUnityCloud_Click()
{
mOperations.OpenUnityCloud();
}
void DeleteMenuItem_Click()
{
mOperations.Delete();
}
void ShareMenuItem_Click()
{
mOperations.Share();
}
void UnshareWithMeMenuItem_Click()
{
mOperations.UnshareWithMe();
}
void UpdateMenuItems(GenericMenu menu)
{
int selectedCount = mOperations.GetSelectedItemsCount();
bool isAnyNonRootItemSelected = mOperations.IsAnyNonRootItemSelected();
bool isAnySharedDriveSelected = mOperations.IsAnySharedDriveSelected();
CloudWorkspacesTreeOperations operations =
CloudWorkspacesTreeMenuUpdater.GetAvailableMenuOperations(
selectedCount, isAnyNonRootItemSelected, isAnySharedDriveSelected);
AddMenuItem(
mOpenInExplorerMenuItemContent,
menu,
operations,
CloudWorkspacesTreeOperations.OpenInExplorer,
OpenInExplorerMenuItem_Click);
AddMenuItem(
mOpenUnityCloudMenuItemContent,
menu,
operations,
CloudWorkspacesTreeOperations.OpenUnityCloud,
OpenUnityCloud_Click);
AddMenuItem(
mDeleteMenuItemContent,
menu,
operations,
CloudWorkspacesTreeOperations.Delete,
DeleteMenuItem_Click);
if (!operations.HasFlag(CloudWorkspacesTreeOperations.Share) &&
!operations.HasFlag(CloudWorkspacesTreeOperations.UnshareWithMe))
{
return;
}
menu.AddSeparator(string.Empty);
if (operations.HasFlag(CloudWorkspacesTreeOperations.Share))
{
AddMenuItem(
mShareMenuItemContent,
menu,
operations,
CloudWorkspacesTreeOperations.Share,
ShareMenuItem_Click);
}
if (operations.HasFlag(CloudWorkspacesTreeOperations.UnshareWithMe))
{
AddMenuItem(
mUnshareWithMeMenuItemContent,
menu,
operations,
CloudWorkspacesTreeOperations.UnshareWithMe,
UnshareWithMeMenuItem_Click);
}
}
static void AddMenuItem(
GUIContent menuItemContent,
GenericMenu menu,
CloudWorkspacesTreeOperations operations,
CloudWorkspacesTreeOperations operationsToCheck,
GenericMenu.MenuFunction menuFunction)
{
if (operations.HasFlag(operationsToCheck))
{
menu.AddItem(menuItemContent, false, menuFunction);
return;
}
menu.AddDisabledItem(menuItemContent);
}
void ProcessMenuOperation(CloudWorkspacesTreeOperations operationToExecute)
{
if (operationToExecute == CloudWorkspacesTreeOperations.OpenInExplorer)
{
OpenInExplorerMenuItem_Click();
return;
}
if (operationToExecute == CloudWorkspacesTreeOperations.Delete)
{
DeleteMenuItem_Click();
return;
}
}
static CloudWorkspacesTreeOperations GetMenuOperation(Event e)
{
if (Keyboard.HasControlOrCommandModifier(e) &&
Keyboard.HasShiftModifier(e) &&
Keyboard.IsKeyPressed(e, KeyCode.S))
{
return CloudWorkspacesTreeOperations.OpenInExplorer;
}
if (Keyboard.IsDeleteKeyPressed(e))
return CloudWorkspacesTreeOperations.Delete;
return CloudWorkspacesTreeOperations.None;
}
void BuildComponents()
{
mOpenInExplorerMenuItemContent = new GUIContent(
string.Format("{0} {1}",
PlatformIdentifier.IsMac() ?
PlasticLocalization.Name.ItemsMenuItemRevealInFinder.GetString() :
PlasticLocalization.Name.ShowInExplorerMenuItem.GetString(),
GetPlasticShortcut.ForShowInExplorer()));
mOpenUnityCloudMenuItemContent = new GUIContent(
PlasticLocalization.Name.OpenUnityDashboard.GetString());
mDeleteMenuItemContent = new GUIContent(
string.Format("{0} {1}",
PlasticLocalization.Name.ItemsMenuItemDelete.GetString(),
GetPlasticShortcut.ForDelete()));
mShareMenuItemContent = new GUIContent(
PlasticLocalization.Name.ShareMenuItem.GetString());
mUnshareWithMeMenuItemContent = new GUIContent(
PlasticLocalization.Name.UnshareWithMeMenuItem.GetString());
}
GUIContent mOpenInExplorerMenuItemContent;
GUIContent mOpenUnityCloudMenuItemContent;
GUIContent mDeleteMenuItemContent;
GUIContent mShareMenuItemContent;
GUIContent mUnshareWithMeMenuItemContent;
readonly ICloudWorkspacesTreeMenuOperations mOperations;
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 413847c0678742c299af4cfac5ce8cb1
timeCreated: 1756718482