using UnityEditor; using UnityEngine; using System; using System.Collections.Generic; using System.Linq; using System.Text; using Perforce.P4; using log4net; namespace P4Connect { public class Menus { private static readonly ILog log = LogManager.GetLogger(typeof(Menus)); #region Perforce Menus [MenuItem("Assets/Perforce/Refresh", true, 100)] public static bool ProjectViewCanRefresh() { return Config.ValidConfiguration; } [MenuItem("Assets/Perforce/Refresh", false, 100)] public static void ProjectViewRefresh() { // This command should go to the server to re-download everything. var paths = Utils.GetDeepSelectedEffectivePaths(); //log.Debug("Refresh Called on: " + Logger.StringArrayToString(paths.ToArray())); AssetStatusCache.Refresh(paths); Icons.UpdateDisplay(); } [MenuItem("Assets/Perforce/Workspaces", false, 100)] public static void ShowWorkspaces() { Engine.PerformConnectionOperation(con => { StringBuilder builder = new StringBuilder(); builder.AppendLine("RootPath: " + Main.RootPath + " Workspaces:"); ClientsCmdOptions opts = new ClientsCmdOptions(Perforce.P4.ClientsCmdFlags.IncludeTime, Config.Username, null, 0, null); IList< Client > clients = con.P4Depot.GetClients(opts); foreach(Client c in clients) { builder.AppendFormat("{0} {1} - {2} local: {3}\n", c.Name, c.OwnerName, c.Root, Utils.IsDirOrValidSubDirectoryOf(Main.RootPath, c.Root)); //builder.AppendLine(c.ToString()); } if (EditorUtility.DisplayDialog("Workspaces", builder.ToString(), "ok")) { // nothing yet } }); } [MenuItem("Assets/Perforce/Users", false, 100)] public static void ShowUsers() { Engine.PerformConnectionOperation(con => { StringBuilder builder = new StringBuilder(); builder.AppendLine(" Users:"); UsersCmdOptions opts = new UsersCmdOptions(Perforce.P4.UsersCmdFlags.None, 0); IList users = con.P4Depot.GetUsers(opts); if (EditorUtility.DisplayDialog("Users", builder.ToString(), "ok")) { // nothing yet } }); } [MenuItem("Assets/Perforce/Add to Depot", true, 100)] public static bool ProjectViewCanAddToDepot() { if (!Config.ValidConfiguration) return false; bool canAdd = true; if (Config.CheckStatusForMenus) { // Grab the statuses of all the items in the selection List paths = Utils.GetDeepSelectedEffectivePaths().ToList(); if (paths.Count < Config.CheckStatusForMenusMaxItems) { canAdd = false; Engine.PerformConnectionOperation(con => { List statuses = AssetStatusCache.GetAssetStatusesFromPaths(con, paths); // And indicate we can add to the depot if at least one of them isn't in the depot canAdd = statuses.Any(status => status.LocalState == FileState.None || (status.LocalState == FileState.InDepot && status.DepotState == DepotState.Deleted)); }); } } return canAdd; } [MenuItem("Assets/Perforce/Add to Depot", false, 100)] public static void ProjectViewAddToDepot() { List addFiles = new List(); Engine.PerformConnectionOperation(con => { // Grab the statuses of all the items in the selection IEnumerable paths = Utils.GetDeepSelectedEffectivePaths().AssetToLocalPaths(); List xpaths = Utils.ExplodeLocalPaths(paths).ToList(); List statuses = AssetStatusCache.GetAssetStatusesFromPaths(con, xpaths); for (int i = 0; i < xpaths.Count; ++i) { // Add directories, Add files not in the depot, add files which are in perforce but deleted previously, //if (Utils.IsDirectory(paths[i]) || statuses[i].LocalState == FileState.None || (statuses[i].LocalState == FileState.InDepot && statuses[i].DepotState == DepotState.Deleted)) if (statuses[i].LocalState == FileState.None || statuses[i].LocalState == FileState.InDepot) { addFiles.Add(xpaths[i]); } } }); log.Debug("ATD adding: " + Logger.StringArrayToString(addFiles.ToArray())); if (Engine.CreateAssets(addFiles.ToArray()).Count == 0) { Debug.Log("P4Connect - Add to Depot - No Changes"); } } [MenuItem("Assets/Perforce/Checkout", true, 100)] public static bool ProjectViewCanCheckoutAsset() { if (!Config.ValidConfiguration) return false; bool canCheckout = true; if (Config.CheckStatusForMenus) { // Grab the statuses of all the items in the selection List paths = Utils.GetDeepSelectedEffectivePaths().ToList(); if (paths.Count < Config.CheckStatusForMenusMaxItems) { canCheckout = false; Engine.PerformConnectionOperation(con => { List statuses = AssetStatusCache.GetAssetStatusesFromPaths(con, paths); // And indicate we can add to the depot if at least one of them in the depot for (int i = 0; i < paths.Count; ++i) { if (Utils.IsDirectory(paths[i]) || statuses[i].LocalState == FileState.InDepot) { canCheckout = true; } } }); } } return canCheckout; } [MenuItem("Assets/Perforce/Checkout", false, 100)] public static void ProjectViewCheckoutAsset() { List checkoutFiles = new List(); Engine.PerformConnectionOperation(con => { // Grab the statuses of all the items in the selection List paths = Utils.GetDeepSelectedEffectivePaths().ToList(); List statuses = AssetStatusCache.GetAssetStatusesFromPaths(con, paths); for (int i = 0; i < paths.Count; ++i) { if (Utils.IsDirectory(paths[i]) || statuses[i].IsOnServer()) { checkoutFiles.Add(paths[i]); } } }); if (Engine.CheckoutAssets(checkoutFiles.ToArray()).Count == 0) { Debug.Log("P4Connect - Checkout - No Changes"); } } [MenuItem("Assets/Perforce/Lock", true, 100)] public static bool ProjectViewCanLockAsset() { if (!Config.ValidConfiguration) return false; bool canLock = true; if (Config.CheckStatusForMenus) { // Grab the statuses of all the items in the selection List paths = Utils.GetDeepSelectedEffectivePaths().ToList(); if (paths.Count < Config.CheckStatusForMenusMaxItems) { canLock = false; Engine.PerformConnectionOperation(con => { List statuses = AssetStatusCache.GetAssetStatusesFromPaths(con, paths); // And indicate we can add to the depot if at least one of them in the depot for (int i = 0; i < paths.Count; ++i) { if ((statuses[i].IsOpened() && !statuses[i].IsLocked()) || Utils.IsDirectory(paths[i])) { canLock = true; } } }); } } return canLock; } [MenuItem("Assets/Perforce/Lock", false, 100)] public static void ProjectViewLockAsset() { List lockFiles = new List(); Engine.PerformConnectionOperation(con => { // Grab the statuses of all the items in the selection List paths = Utils.GetDeepSelectedEffectivePaths().ToList(); List statuses = AssetStatusCache.GetAssetStatusesFromPaths(con, paths); for (int i = 0; i < paths.Count; ++i) { if (Utils.IsDirectory(paths[i]) || !statuses[i].IsLocked()) { lockFiles.Add(paths[i]); } } }); if (Engine.LockAssets(lockFiles.ToArray()).Count == 0) { Debug.Log("P4Connect - Lock - No Changes"); } } [MenuItem("Assets/Perforce/Unlock", true, 100)] public static bool ProjectViewCanUnlockAsset() { if (!Config.ValidConfiguration) return false; bool canUnlock = true; if (Config.CheckStatusForMenus) { // Grab the statuses of all the items in the selection List paths = Utils.GetDeepSelectedEffectivePaths().ToList(); if (paths.Count < Config.CheckStatusForMenusMaxItems) { canUnlock = false; Engine.PerformConnectionOperation(con => { List statuses = AssetStatusCache.GetAssetStatusesFromPaths(con, paths); // And indicate we can add to the depot if at least one of them in the depot for (int i = 0; i < paths.Count; ++i) { if (Utils.IsDirectory(paths[i]) || statuses[i].LockState == LockState.OurLock) { canUnlock = true; } } }); } } return canUnlock; } [MenuItem("Assets/Perforce/Unlock", false, 100)] public static void ProjectViewUnlockAsset() { List unlockFiles = new List(); Engine.PerformConnectionOperation(con => { // Grab the statuses of all the items in the selection List paths = Utils.GetDeepSelectedEffectivePaths().ToList(); List statuses = AssetStatusCache.GetAssetStatusesFromPaths(con, paths); for (int i = 0; i < paths.Count; ++i) { if (Utils.IsDirectory(paths[i]) || statuses[i].LockState == LockState.OurLock) { unlockFiles.Add(paths[i]); } } }); if (Engine.UnlockAssets(unlockFiles.ToArray()).Count == 0) { Debug.Log("P4Connect - Unlock - No Changes"); } } [MenuItem("Assets/Perforce/Get Latest Revision", true, 100)] public static bool ProjectViewCanGetLatest() { return Config.ValidConfiguration; } [MenuItem("Assets/Perforce/Get Latest Revision", false, 100)] public static void ProjectViewGetLatest() { //Debug.Log("XYZZY"); // Grab all the items in the selection, add directory wildcards if needed List paths = Utils.GetDeepSelectedEffectivePaths().AddDirectoryWildcards().ToList(); Debug.Log("WithDirs: " + Logger.StringArrayToString(paths.ToArray())); List noDirPaths = paths.StripDirectories().ToList(); Debug.Log("noDirs: " + Logger.StringArrayToString(noDirPaths.ToArray())); List getLatestFiles = new List(); // Get Asset statuses for non-directores (if any). Then add them to list if in Perforce if (noDirPaths.Count != 0) { Engine.PerformConnectionOperation(con => { List statuses = AssetStatusCache.GetAssetStatusesFromPaths(con, noDirPaths); for (int i = 0; i < noDirPaths.Count; ++i) { if (statuses[i].LocalState != FileState.None) { getLatestFiles.Add(noDirPaths[i]); } } }); } // Always add the directories List dpaths = paths.JustDirectories().ToList(); foreach (string p in dpaths) { getLatestFiles.Add(p); } string[] aGetLatestFiles = getLatestFiles.ToArray(); //log.Debug("Filtered: " + Logger.StringArrayToString(aGetLatestFiles)); if (getLatestFiles.Count() > 0) { if (Engine.GetLatestAssets(aGetLatestFiles, false).Count == 0) { Debug.Log("P4Connect - Get Latest Revision - No Changes"); } } } [MenuItem("Assets/Perforce/Force Get Latest Revision", true, 100)] public static bool ProjectViewCanForceGetLatest() { return Config.ValidConfiguration; } [MenuItem("Assets/Perforce/Force Get Latest Revision", false, 100)] public static void ProjectViewForceGetLatest() { List getLatestFiles = new List(); Engine.PerformConnectionOperation(con => { // Grab the statuses of all the items in the selection List paths = Utils.GetDeepSelectedEffectivePaths().ToList(); log.Debug("Selected: " + Logger.StringArrayToString(paths.ToArray())); List statuses = AssetStatusCache.GetAssetStatusesFromPaths(con, paths); for (int i = 0; i < paths.Count; ++i) { if (Utils.IsDirectory(paths[i]) || statuses[i].LocalState != FileState.None) { getLatestFiles.Add(paths[i]); } } }); string[] aGetLatestFiles = getLatestFiles.ToArray(); log.Debug("Filtered: " + Logger.StringArrayToString(aGetLatestFiles)); if (aGetLatestFiles.Count() > 0) { // Build a string of the names StringBuilder builder = new StringBuilder(); builder.AppendLine("Are you sure you want to force-get the latest revision of the following assets?"); builder.AppendLine(); foreach (string path in getLatestFiles) { builder.AppendLine(path); } if (EditorUtility.DisplayDialog("P4Connect - Force Get Latest", builder.ToString(), "Yes", "No")) { if (Engine.GetLatestAssets(getLatestFiles.ToArray(), true).Count == 0) { Debug.Log("P4Connect - Force Get Latest - No Changes"); } } } } [MenuItem("Assets/Perforce/Diff against Have-Revision", true, 100)] public static bool ProjectViewCanDiffAsset() { if (!Config.ValidConfiguration) return false; bool canDiff = true; if (Config.CheckStatusForMenus) { // Grab the statuses of all the items in the selection List paths = Utils.GetDeepSelectedEffectivePaths().ToList(); if (paths.Count < Config.CheckStatusForMenusMaxItems) { canDiff = false; Engine.PerformConnectionOperation(con => { List statuses = AssetStatusCache.GetAssetStatusesFromPaths(con, paths); for (int i = 0; i < paths.Count; ++i) { if (Utils.IsDirectory(paths[i]) || statuses[i].LocalState != FileState.None) { canDiff = true; } } }); } } return canDiff; } [MenuItem("Assets/Perforce/Diff against Have-Revision", false, 100)] public static void ProjectViewDiffAsset() { List diffFiles = new List(); Engine.PerformConnectionOperation(con => { // Grab the statuses of all the items in the selection List paths = Utils.GetDeepSelectedEffectivePaths().ToList(); List statuses = AssetStatusCache.GetAssetStatusesFromPaths(con, paths); for (int i = 0; i < paths.Count; ++i) { if (Utils.IsDirectory(paths[i]) || statuses[i].LocalState != FileState.None) { diffFiles.Add(paths[i]); } } }); foreach (string file in diffFiles) { if (Utils.IsDirectory(file)) Utils.LaunchDiffAgainstHaveRev(Utils.MetaFromAsset(file)); else Utils.LaunchDiffAgainstHaveRev(file); } } [MenuItem("Assets/Perforce/Revert if Unchanged", true, 100)] public static bool ProjectViewCanRevertIfUnchanged() { return ProjectViewCanRevertAsset(); } [MenuItem("Assets/Perforce/Revert if Unchanged", false, 100)] public static void ProjectViewRevertAssetIfUnchanged() { List assetsToRevert = new List(); // Grab the statuses of all the items in the selection Engine.PerformConnectionOperation(con => { List paths = Utils.GetDeepSelectedEffectivePaths().ToList(); List statuses = AssetStatusCache.GetAssetStatusesFromPaths(con, paths); for (int i = 0; i < paths.Count; ++i) { if (Utils.IsDirectory(paths[i]) || statuses[i].LocalState != FileState.InDepot) { assetsToRevert.Add(paths[i]); } } }); if (Engine.RevertAssets(assetsToRevert.ToArray(), false).Count == 0) { Debug.Log("P4Connect - Revert if unchanged - No Changes"); } } [MenuItem("Assets/Perforce/Revert", true, 100)] public static bool ProjectViewCanRevertAsset() { if (!Config.ValidConfiguration) return false; bool canRevert = true; if (Config.CheckStatusForMenus) { // Grab the statuses of all the items in the selection List paths = Utils.GetDeepSelectedEffectivePaths().ToList(); if (paths.Count < Config.CheckStatusForMenusMaxItems) { canRevert = false; Engine.PerformConnectionOperation(con => { List statuses = AssetStatusCache.GetAssetStatusesFromPaths(con, paths); for (int i = 0; i < paths.Count; ++i) { if (Utils.IsDirectory(paths[i]) || statuses[i].LocalState != FileState.InDepot) { canRevert = true; } } }); } } return canRevert; } [MenuItem("Assets/Perforce/Revert", false, 100)] public static void ProjectViewRevertAsset() { List revertFiles = new List(); Engine.PerformConnectionOperation(con => { // Grab the statuses of all the items in the selection List paths = Utils.GetDeepSelectedEffectivePaths().ToList(); List statuses = AssetStatusCache.GetAssetStatusesFromPaths(con, paths); for (int i = 0; i < paths.Count; ++i) { if (Utils.IsDirectory(paths[i]) || statuses[i].LocalState != FileState.InDepot) { revertFiles.Add(paths[i]); } } }); // Build a string of the names StringBuilder builder = new StringBuilder(); builder.AppendLine("Are you sure you want to revert the following assets?"); builder.AppendLine(); foreach (string path in revertFiles) { builder.AppendLine(path); } if (EditorUtility.DisplayDialog("P4Connect - Revert", builder.ToString(), "Yes", "No")) { if (Engine.RevertAssets(revertFiles.ToArray(), true).Count == 0) { Debug.Log("P4Connect - Revert - No Changes"); } } } [MenuItem("Assets/Perforce/Commit...", true, 100)] public static bool ProjectViewCanCommitAsset() { if (!Config.ValidConfiguration) return false; bool canCommit = true; if (Config.CheckStatusForMenus) { // Grab the statuses of all the items in the selection List paths = Utils.GetDeepSelectedEffectivePaths().ToList(); if (paths.Count < Config.CheckStatusForMenusMaxItems) { canCommit = false; Engine.PerformConnectionOperation(con => { List statuses = AssetStatusCache.GetAssetStatusesFromPaths(con, paths); // We can only commit is all files can be committed for (int i = 0; i < paths.Count; ++i) { if (!Utils.IsDirectory(paths[i]) && (statuses[i].LocalState == FileState.MarkedForEdit || statuses[i].LocalState == FileState.MarkedForAdd || statuses[i].LocalState == FileState.MarkedForDelete || statuses[i].LocalState == FileState.MarkedForAddMove || statuses[i].LocalState == FileState.MarkedForDeleteMove) && statuses[i].LockState != LockState.TheirLock) { canCommit = true; } } }); } } return canCommit; } [MenuItem("Assets/Perforce/Commit...", false, 100)] public static void ProjectViewCommitAsset() { List commitFiles = new List(); Engine.PerformConnectionOperation(con => { // Grab the statuses of all the items in the selection List paths = Utils.GetDeepSelectedEffectivePaths().ToList(); List statuses = AssetStatusCache.GetAssetStatusesFromPaths(con, paths); for (int i = 0; i < paths.Count; ++i) { if (Utils.IsDirectory(paths[i]) || statuses[i].LocalState == FileState.MarkedForEdit || statuses[i].LocalState == FileState.MarkedForAdd || statuses[i].LocalState == FileState.MarkedForDelete || statuses[i].LocalState == FileState.MarkedForAddMove || statuses[i].LocalState == FileState.MarkedForDeleteMove) { commitFiles.Add(paths[i]); } } }); // Show the pending changes window and select only the files in the commit list PendingChanges window = EditorWindow.GetWindow(typeof(PendingChanges), false, "Perforce") as PendingChanges; window.SelectAssets(commitFiles); } #endregion #region PendingChanges Menus // Menu entries associated with the Pending Changes Dialog [MenuItem("CONTEXT/Perforce/Select in Project View", false, 10)] public static void SelectInProjectView(MenuCommand aCommand) { PendingChanges changes = aCommand.context as PendingChanges; List objects = new List(changes.SelectedAssets.Select(path => AssetDatabase.LoadMainAssetAtPath(path))); Selection.objects = objects.ToArray(); EditorUtility.FocusProjectWindow(); } [MenuItem("CONTEXT/Perforce/Force Get Latest Revision", false, 10)] public static void ProjectViewForceGetLatest1(MenuCommand aCommand) { PendingChanges changes = aCommand.context as PendingChanges; List assets = new List(changes.SelectedAssets); log.Debug("files: " + Logger.StringArrayToString(assets.ToArray())); if (assets.Count == 0) return; // Build a string of the names StringBuilder builder = new StringBuilder(); builder.AppendLine("Are you sure you want to force-get the latest revision of the following assets?"); builder.AppendLine(); foreach (string path in assets) { builder.AppendLine(path); } if (EditorUtility.DisplayDialog("P4Connect - Force Get Latest", builder.ToString(), "Yes", "No")) { Engine.GetLatestAssets(assets.ToArray(), true); } } [MenuItem("CONTEXT/Perforce/Revert if Unchanged", false, 10)] public static void RevertAssetIfUnchanged(MenuCommand aCommand) { PendingChanges changes = aCommand.context as PendingChanges; List assets = new List(changes.SelectedAssets); log.Debug("files: " + Logger.StringArrayToString(assets.ToArray())); Engine.RevertAssets(assets.ToArray(), false); } [MenuItem("CONTEXT/Perforce/Revert", false, 10)] public static void RevertAsset(MenuCommand aCommand) { // Grab the selected assets PendingChanges changes = aCommand.context as PendingChanges; List assets = new List(changes.SelectedAssets); log.Debug("files: " + Logger.StringArrayToString(assets.ToArray())); // Build a string of the names StringBuilder builder = new StringBuilder(); builder.AppendLine("Are you sure you want to revert the following assets?"); builder.AppendLine(); foreach (string path in assets) { builder.AppendLine(path); } if (EditorUtility.DisplayDialog("P4Connect - Revert", builder.ToString(), "Yes", "No")) { Engine.RevertAssets(assets.ToArray(), true); } } [MenuItem("CONTEXT/Perforce/Diff against Have-Revision", false, 10)] public static void DiffAsset(MenuCommand aCommand) { // Grab the selected assets PendingChanges changes = aCommand.context as PendingChanges; List assets = new List(changes.SelectedAssets); foreach (string asset in assets) { Utils.LaunchDiffAgainstHaveRev(asset); } } [MenuItem("CONTEXT/Perforce/Lock", false, 10)] public static void LockAsset(MenuCommand aCommand) { // Grab the selected assets PendingChanges changes = aCommand.context as PendingChanges; List assets = new List(changes.SelectedAssets); log.Debug("files: " + Logger.StringArrayToString(assets.ToArray())); Engine.LockAssets(assets.ToArray()); } [MenuItem("CONTEXT/Perforce/Unlock", false, 10)] public static void UnlockAsset(MenuCommand aCommand) { PendingChanges changes = aCommand.context as PendingChanges; List assets = new List(changes.SelectedAssets); log.Debug("files: " + Logger.StringArrayToString(assets.ToArray())); Engine.UnlockAssets(assets.ToArray()); } #endregion } }