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
{
///
/// 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).
///
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);
//}
// 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.
// Note: This is not an override because Unity calls it through Invoke()
public static string[] OnWillSaveAssets(string[] arPaths)
{
#if DEBUG
log.Debug("OnWillSaveAssets: " + Logger.StringArrayToString(arPaths));
#endif
// Filter the files that are newly created from the ones that are modified
List filesToCheckout = new List(10);
List filesToAdd = new List(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 DEBUG
log.Debug("checkout: " + Logger.StringArrayToString(filesToCheckout.ToArray()));
#endif
Engine.CheckoutAssets(filesToCheckout.ToArray());
#if DEBUG
log.Debug("add: " + Logger.StringArrayToString(filesToAdd.ToArray()));
#endif
Engine.CreateAssets(filesToAdd.ToArray());
return arPaths;
}
// Unity Pro only
public static void OnWillCreateAsset(string path)
{
#if DEBUG
log.Debug("PRO: OnWillCreateAsset: " + path);
#endif
}
// Unity Pro only
public static AssetDeleteResult OnWillDeleteAsset(string path, RemoveAssetOptions options)
{
#if DEBUG
log.Debug("PRO: OnWillDeleteAsset: "+ path + " options: " + options.ToString());
#endif
return AssetDeleteResult.DidNotDelete;
}
// Unity Pro only
public static AssetMoveResult OnWillMoveAsset(string oldpath, string newpath)
{
#if DEBUG
log.Debug("PRO: OnWillMoveAsset: from: "+ oldpath + " to: " + newpath);
#endif
return AssetMoveResult.DidNotMove;
}
///
/// Called when the user double clicks an item to edit it
/// We use it to check the file out if necessary
///
[UnityEditor.Callbacks.OnOpenAsset(0)]
public static bool OpenFile(int aInstanceID, int aLine)
{
if (Config.ValidConfiguration)
{
var assetPath = AssetDatabase.GetAssetPath(aInstanceID);
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;
}
///
/// Called whenever the project files change
///
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 filesToTryAndCheckOut = new List(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 filesToCheckOut = new List(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();
}
///
/// Called whenever the project windows changes
///
static void OnProjectWindowChanged()
{
log.Debug("OnProjectWindowChanged");
CheckoutProjectFiles(Config.IncludeProjectFiles, Config.IncludeSolutionFiles);
}
}
}