using UnityEditor;
using UnityEngine;
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;
using Perforce.P4;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Xml.Linq;
using SyntaxTree.VisualStudio.Unity.Bridge;
namespace P4Connect
{
// Hook into Unitys Project File Generation.
[InitializeOnLoad]
public class VSTUFileHook
{
// necessary for XLinq to sae the xml project file in utf8
class Utf8StringWriter : StringWriter
{
public override Encoding Encoding
{
get { return Encoding.UTF8; }
}
}
static void ProjectFileHook()
{
ProjectFilesGenerator.ProjectFileGeneration += (string name, string content) =>
{
var document = XDocument.Parse(content);
document.Root.Add(new XComment("PRJ FIX ME"));
var str = new Utf8StringWriter();
document.Save(str);
return str.ToString();
};
}
static void SolutionFileHook()
{
ProjectFilesGenerator.SolutionFileGeneration += (string name, string content) =>
{
var document = XDocument.Parse(content);
document.Root.Add(new XComment("SLN FIX ME"));
var str = new Utf8StringWriter();
document.Save(str);
return str.ToString();
};
}
}
///
/// This class hooks up to and handles UnityVS modifying the project files
/// VSTU has changed a lot, this stuff may be useless by now....
///
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());
}
}
}
}