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;
namespace P4Connect
{
///
/// This class hooks up to and handles UnityVS modifying the project files
///
public class UnityVSBridge
{
// A bunch of strings used to find the project file generation event through reflection
public const string UnityVSAssemblyName = "SyntaxTree.VisualStudio.Unity.Bridge";
public const string UnityVSProjectFileGeneratorTypename = "SyntaxTree.VisualStudio.Unity.Bridge.ProjectFilesGenerator";
public const string UnityVSProjectFileGenerationEventName = "ProjectFileGeneration";
public const string UnityVSProjectFileGenerationEventHandlerType = "SyntaxTree.VisualStudio.Unity.Bridge.FileGenerationHandler";
///
/// Static constructor
///
public static void Initialize()
{
// And hook us up to UnityVS
if (Config.UnityVsSupport)
SetupUnityVSHook();
// Hook the connection settings event
Config.PrefsChanged += OnConnectionSettingsChanged;
// Register for project changes
EditorApplication.projectWindowChanged += OnProjectWindowChanged;
}
///
/// Event handler called when the connection settings change
///
static void OnConnectionSettingsChanged()
{
// Setup the root directories based on the updated path
if (Config.UnityVsSupport)
SetupUnityVSHook();
}
///
/// Hook up to UnityVS ProjectFile event through reflection
///
static void SetupUnityVSHook()
{
// First, find the UnityVS assembly
Assembly unityVSAssembly = null;
Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
for (int i = 0; unityVSAssembly == null && i < assemblies.Length; ++i)
{
if (assemblies[i].FullName.Contains(UnityVSAssemblyName))
unityVSAssembly = assemblies[i];
}
if (unityVSAssembly != null)
{
// Now that we have the assembly, find the project file generator class
Type projectFileGeneratorType = unityVSAssembly.GetType(UnityVSProjectFileGeneratorTypename);
if (projectFileGeneratorType != null)
{
// Then the project file generation event itself
FieldInfo projectGeneration = projectFileGeneratorType.GetField(UnityVSProjectFileGenerationEventName);
if (projectGeneration != null)
{
// Make a bridge delegate to our function
Func currentDelegate = OnUnityVSProjectFilesChange;
Type handlerType = unityVSAssembly.GetType(UnityVSProjectFileGenerationEventHandlerType);
Delegate unityVSBridgeDelegate = Delegate.CreateDelegate(handlerType, currentDelegate.Target, currentDelegate.Method);
if (unityVSBridgeDelegate != null)
{
// Register with the event handler
projectGeneration.SetValue(null, unityVSBridgeDelegate);
}
else
{
Debug.LogError("P4Connect - Could not create conversion delegate to UnityVS ProjectFileGenerator");
}
}
else
{
Debug.LogError("P4Connect - Could not find ProjectFileGeneration.ProjectFileGeneration() in UnityVS namespace");
}
}
else
{
Debug.LogError("P4Connect - Could not find ProjectFileGeneration class in UnityVS namespace");
}
}
else
{
Debug.LogError("P4Connect - UnityVS Assembly doesn't appear to be loaded");
}
}
///
/// Called when unityVS re-creates project files
///
/// The project being modified
/// The content of the project file
/// modified content if desired, we don't, we just use this method as an event
static string OnUnityVSProjectFilesChange(string name, string content)
{
if (Config.UnityVsSupport)
{
string[] files = new string[2];
// First file is the solution file, which we derive from the project name
files[0] = "UnityVS." + Main.ProjectName + ".sln";
// Second file is the project file itself
files[1] = name;
Engine.CheckoutAssets(files);
}
// We don't touch the content
return content;
}
// Called whenever the project files change
public static void OnProjectWindowChanged()
{
// The following files don't exist unless you have UnityVS
if (Config.UnityVsSupport)
{
// Build a list of project and solution files we may want to check out
List filesToTryAndCheckOut = new List(10);
filesToTryAndCheckOut.Add(System.IO.Path.Combine(Main.RootPath, "UnityVS." + Main.ProjectName + ".CSharp.csproj"));
filesToTryAndCheckOut.Add(System.IO.Path.Combine(Main.RootPath, "UnityVS." + Main.ProjectName + ".CSharp.Editor.csproj"));
filesToTryAndCheckOut.Add(System.IO.Path.Combine(Main.RootPath, "UnityVS." + Main.ProjectName + ".CSharp.Plugins.csproj"));
filesToTryAndCheckOut.Add(System.IO.Path.Combine(Main.RootPath, "UnityVS." + Main.ProjectName + ".sln"));
filesToTryAndCheckOut.Add(System.IO.Path.Combine(Main.RootPath, "UnityVS." + Main.ProjectName + ".sln.DotSettings"));
filesToTryAndCheckOut.Add(System.IO.Path.Combine(Main.RootPath, "UnityVS." + Main.ProjectName + ".UnityScript.Plugins.unityproj"));
// 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
// The using statement will make sure the connection is Disposed (i.e. closed)
Engine.CheckoutAssets(filesToCheckOut.ToArray());
}
}
}
}