using UnityEditor; using UnityEngine; using System; using System.Collections; using System.Collections.Generic; using System.Runtime.InteropServices; using Perforce.P4; using System.Linq; using System.Reflection; using System.Text; using log4net; namespace P4Connect { /// <summary> /// This class hooks onto the Asset Save/Delete/Move process and makes sure that /// Perforce is updated accordingly. It uses the perforce connection class /// (which internally uses Config to retrieve the connection settings) /// to open a connection to the server and add the required changes (add/checkout/delete/move). /// </summary> public class AssetBridge : UnityEditor.AssetModificationProcessor { private static readonly ILog log = LogManager.GetLogger(typeof(AssetBridge)); // Static constructor public static void Initialize() { // Register for project changes EditorApplication.projectWindowChanged += OnProjectWindowChanged; } //// This method is called by Unity when assets are created BY Unity itself //// Note: This is not an override because Unity calls it through Invoke() //public static void OnWillCreateAsset(string arPath) //{ // Engine.CreateAsset(arPath); //} /// <summary> /// This method is called by Unity when assets are about to be saved /// We take this opportunity to either check out or add the assets /// AND their associated .meta files. /// Only the files returned by this function will be further processed. /// Note: This is not an override because Unity calls it through Invoke() /// </summary> /// <param name="arPaths">Asset Paths from Unity</param> /// <returns>an array of asset paths for unity to continue processing</returns> public static string[] OnWillSaveAssets(string[] arPaths) { // I don't know why Unity calls this with empty lists??? if (arPaths == null || !arPaths.Any()) { #if DEBUG log.Debug("OnWillSaveAssets: No Files"); #endif return arPaths; } #if DEBUG log.Debug("OnWillSaveAssets: " + Logger.StringArrayToString(arPaths)); #endif // Filter the files that are newly created from the ones that are modified List<string> filesToCheckout = new List<string>(10); List<string> filesToAdd = new List<string>(10); foreach (string file in arPaths) { string fullpath = Utils.AssetPathToFullPath(file); if (System.IO.File.Exists(fullpath)) { // The file already exists, check it out filesToCheckout.Add(file); } else { // This will be a new file filesToAdd.Add(file); } } if (filesToCheckout.Count() != 0) { #if DEBUG log.Debug("checkout: " + Logger.StringArrayToString(filesToCheckout.ToArray())); #endif Engine.CheckoutAssets(filesToCheckout.ToArray()); } if (filesToAdd.Count() != 0) { #if DEBUG log.Debug("add: " + Logger.StringArrayToString(filesToAdd.ToArray())); #endif Engine.CreateAssets(filesToAdd.ToArray()); } return arPaths; } /// <summary> /// This method is called by Unity when assets are created BY Unity itself /// Only enabled when using Unity PRO /// </summary> /// <param name="path">Asset path of new asset</param> public static void OnWillCreateAsset(string path) { #if DEBUG log.Debug("PRO: OnWillCreateAsset: " + path); #endif } // Unity Pro only /// <summary> /// This method is called by Unity just before it deletes an asset /// Only enabled when using Unity PRO /// </summary> /// <param name="path">Asset path to the to-be-deleted Asset</param> /// <param name="options">enum RemoveAssetOptions</param> /// <returns>enum AssetDeleteResult</returns> public static AssetDeleteResult OnWillDeleteAsset(string path, RemoveAssetOptions options) { #if DEBUG log.Debug("PRO: OnWillDeleteAsset: "+ path + " options: " + options.ToString()); #endif return AssetDeleteResult.DidNotDelete; } /// <summary> /// This method is called by Unity just before it moves an asset /// Only enabled when using Unity PRO /// </summary> /// <param name="oldpath">original asset path</param> /// <param name="newpath">new asset path</param> /// <returns>enum AssetMoveResult</returns> public static AssetMoveResult OnWillMoveAsset(string oldpath, string newpath) { #if DEBUG log.Debug("PRO: OnWillMoveAsset: from: "+ oldpath + " to: " + newpath); #endif return AssetMoveResult.DidNotMove; } /// <summary> /// Called when the user double clicks an item to edit it /// We use it to check the file out if necessary /// </summary> /// <param name="aInstanceId">Object instance ID</param> /// <param name="aLine">Line number to go to</param> /// <returns>true if we opened asset, false to use external tool</returns> [UnityEditor.Callbacks.OnOpenAsset(0)] public static bool OpenFile(int aInstanceId, int aLine) { if (Config.ValidConfiguration) { var assetPath = AssetDatabase.GetAssetPath(aInstanceId); if (Utils.IsDirectoryAsset(assetPath)) return false; bool checkout = false; switch (Queries.GetFileState(assetPath)) { case FileState.None: goto case FileState.InDepot; case FileState.InDepot: if (Config.AskBeforeCheckout) { string filename = System.IO.Path.GetFileName(assetPath); checkout = EditorUtility.DisplayDialog("P4Connect - Checkout " + filename, "Would you like to check out " + filename + "?", "Yes", "No"); } else { checkout = true; } break; default: // don't check out break; } if (checkout) { Engine.CheckoutAsset(assetPath); } } // In all cases, let the normal asset handler open the file return false; } /// <summary> /// Called whenever the Visual Studio project files change /// </summary> /// <param name="aIncludeProjectFiles">true if .csproj files are to be stored in Perforce</param> /// <param name="aIncludeSolutionFiles">true if .sln files are to be stored in Perforce</param> public static void CheckoutProjectFiles(bool aIncludeProjectFiles, bool aIncludeSolutionFiles) { log.Debug("CheckoutProjectFiles: " + aIncludeProjectFiles.ToString() + " " + aIncludeSolutionFiles.ToString()); // Build a list of project and solution files we may want to check out List<string> filesToTryAndCheckOut = new List<string>(10); if (aIncludeProjectFiles) { filesToTryAndCheckOut.Add(System.IO.Path.Combine(Main.RootPath, "Assembly-CSharp.csproj")); filesToTryAndCheckOut.Add(System.IO.Path.Combine(Main.RootPath, "Assembly-CSharp-Editor.csproj")); filesToTryAndCheckOut.Add(System.IO.Path.Combine(Main.RootPath, "Assembly-CSharp-vs.csproj")); filesToTryAndCheckOut.Add(System.IO.Path.Combine(Main.RootPath, "Assembly-CSharp-Editor-vs.csproj")); } // Solution files if (aIncludeSolutionFiles) { filesToTryAndCheckOut.Add(System.IO.Path.Combine(Main.RootPath, Main.ProjectName + ".sln")); filesToTryAndCheckOut.Add(System.IO.Path.Combine(Main.RootPath, Main.ProjectName + "-csharp.sln")); } // These files may not exist (the -vs ones only exist if you have Visual Studio set up) // so don't try to add them and get an error if they don't exist List<string> filesToCheckOut = new List<string>(filesToTryAndCheckOut.Where(file => System.IO.File.Exists(file))); // Now pass those off to the Add method if (filesToCheckOut.Any()) { Engine.CheckoutAssets(filesToCheckOut.ToArray()); } // Force the UnityVS files to be checked out as well UnityVSBridge.OnProjectWindowChanged(); } /// <summary> /// Called whenever the project windows changes /// </summary> static void OnProjectWindowChanged() { log.Debug("OnProjectWindowChanged"); CheckoutProjectFiles(Config.IncludeProjectFiles, Config.IncludeSolutionFiles); } } }
# | Change | User | Description | Committed | |
---|---|---|---|---|---|
#1 | 19640 | Liz Lam | "Forking branch Main of perforce-software-p4connect to liz_lam-p4connect." | ||
//guest/perforce_software/p4connect/main/src/P4Connect/P4Connect/P4Connect.AssetBridge.cs | |||||
#3 | 16489 | Norman Morse |
Another pass at async fstats. Removed a UI update on exception |
||
#2 | 16350 | Norman Morse |
Minor Code Clean Up Minor Documentation Clean Up Changed Post Processor callback to ignore directories Added option to use Server Typemap |
||
#1 | 16209 | Norman Morse | Move entire source tree into "main" branch so workshop code will act correctly. | ||
//guest/perforce_software/p4connect/src/P4Connect/P4Connect/P4Connect.AssetBridge.cs | |||||
#4 | 15244 | Norman Morse |
Better Directory support in "add" "get latest" "refresh" and other commands. Improved Project Root detection Various Bug Fixes and Clean up |
||
#3 | 15079 | Norman Morse |
Rewrote AssetStatusCache to Cache AssetStatuses and FileMetaData Fixed Edge conditions on Engine Operations Change Debug output defaults. Will now Checkout files which request to be "added" but which already exist in perforce. Output P4Connect version to log on initialization. |
||
#2 | 12512 | Norman Morse | Integrate from Dev branch, preparing for Beta3 release | ||
#1 | 10940 | Norman Morse |
Inital Workshop release of P4Connect. Released under BSD-2 license |