ExportVisualStudio

From Unify Community Wiki
Revision as of 13:50, 24 October 2009 by Statement (Talk | contribs)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

Author: Lasse Järvensivu a.k.a. Statement

Contents

What it does

  • Creates Visual Studio projects (2005, 2008, 2010 CTP) to allow Unity3D coders to benefit from intellisense.
  • Automatic documentation download for missing documentation (all you need to do is extract the contents).
  • Launches Visual Studio project for you.
  • Includes .cs .js .boo .shader files out of the box and easy to mod!

Installation

Add this script file into a folder called "Editor", and allow for unity to compile it.

Usage

  • 1) In Unity, select from the the menu "File/New Visual Studio Project/" the version of Visual Studio C# project you want to create. Please note that 2005 and 2008 versions are untested at the time of writing.
  • 2) In case Xml documentation is missing, this script will attempt to download it. To successfully install the documentation you need to extract the Xml files into the opened directory.
  • 3) If all went well, the script will offer to open the project for you.

C# - ExportVisualStudio.cs

<csharp>// ExportVisualStudio.cs // Created by Lasse Järvensivu (no email please, but I might be on IRC as 'Statement'). // Feel free to modify code, make money from it, or claim it is yours. // I don't care. 'I hold no ownership to this document'. I hope you enjoy.


// What it does: // * Creates Visual Studio projects (2005, 2008, 2010 CTP) to allow Unity3D coders to benefit from intellisense. // * Automatic documentation download for intellisense inline documentation (all you need to do is extract the contents). // * Launches Visual Studio project for you.


// Installaton: // 1) Add this script file into a folder called "Editor", and allow for unity to compile it.


// Usage: // 1) In Unity, select from the the menu "File/New Visual Studio Project/" the version of // Visual Studio C# project you want to create (Note that 2005 and 2008 versions are untested). // 2) In case Xml documentation is missing, this script will attempt to download it. To successfully // install the documentation you need to extract the Xml files into the opened directory. // 3) If all went well, the script will offer to open the project for you.


// Troubleshooting: // If you want to silence the nagging compability warning, simply remove the first two lines of code in // ExportVisualStudio.GenerateVisualC2005 and ExportVisualStudio.GenerateVisualC2008. // // If downloading the documentation locks up unity, remove the call to DocumentationHelper.CheckAndDownload // in ExportVisualStudio.GenerateVisualC2005, ExportVisualStudio.GenerateVisualC2008 and // ExportVisualStudio.GenerateVisualC2010. // // Finally, don't be afraid to change the code to suit your needs. Start in ExportVisualStudio functions // and then work your way around the calls to figure out how the code works. It is not complex, it just // contains a lot of xml generation.

using System; using System.IO; using System.Reflection; using System.Security.Cryptography; using System.Text; using System.Xml; using UnityEditor; using UnityEngine; using AssemblyReferences = System.Collections.Generic.List<VisualStudioProject.AssemblyReference>; using FileInfos = System.Collections.Generic.List<System.IO.FileInfo>;

public sealed class ExportVisualStudio {

   /// <summary>
   /// Creates projectname.csproj and attempts to conform to Visual C# 2005 specificatons.
   /// </summary>
   [MenuItem("File/New Visual Studio Project/Visual C# 2005")]
   public static void GenerateVisualC2005()
   {
       if (!EditorUtility.DisplayDialog("Compability warning.", "*Version 2005 of Visual C# project has not been tested.\nIt might produce an invalid project file and possibly overwrite a valid one.\nAre you sure you want to continue?", "Yes", "No"))
           return;
       DocumentationHelper.CheckAndDownload();
       string toolsVersion = "2.0";
       string targetFrameworkVersion = "v2.0";
       string productVersion = VisualStudioProject.VS2005ProjectVersion;
       GenerateProject(toolsVersion, targetFrameworkVersion, productVersion, true);
   }
   /// <summary>
   /// Creates projectname.csproj and attempts to conform to Visual C# 2008 specificatons.
   /// </summary>
   [MenuItem("File/New Visual Studio Project/Visual C# 2008")]
   public static void GenerateVisualC2008()
   {
       if (!EditorUtility.DisplayDialog("Compability warning.", "*Version 2008 of Visual C# project has not been tested.\nIt might produce an invalid project file and possibly overwrite a valid one.\nAre you sure you want to continue?", "Yes", "No"))
           return;
       DocumentationHelper.CheckAndDownload();
       string toolsVersion = "3.5";
       string targetFrameworkVersion = "v3.5";
       string productVersion = VisualStudioProject.VS2008ProjectVersion;
       GenerateProject(toolsVersion, targetFrameworkVersion, productVersion);
   }
   /// <summary>
   /// Creates projectname.csproj and attempts to conform to Visual C# 2010 CTP Beta specificatons.
   /// </summary>
   [MenuItem("File/New Visual Studio Project/Visual C# 2010 (CTP)")]
   public static void GenerateVisualC2010()
   {
       DocumentationHelper.CheckAndDownload();
       string toolsVersion = "4.0";
       string targetFrameworkVersion = "v3.5";
       string productVersion = VisualStudioProject.VS2010ProjectVersion;
       GenerateProject(toolsVersion, targetFrameworkVersion, productVersion);
   }
   /// <summary>
   /// Creates projectname.csproj.
   /// </summary>
   /// <param name="toolsVersion">The toolset version</param>
   /// <param name="targetFrameworkVersion">The intended target framework version of .net</param>
   /// <param name="productVersion">The version of visual studio to support</param>
   private static void GenerateProject(string toolsVersion, string targetFrameworkVersion, string productVersion)
   {
       GenerateProject(toolsVersion, targetFrameworkVersion, productVersion, false);
   }
   /// <summary>
   /// Creates projectname.csproj.
   /// </summary>
   /// <param name="toolsVersion">The toolset version</param>
   /// <param name="targetFrameworkVersion">The intended target framework version of .net</param>
   /// <param name="productVersion">The version of visual studio to support</param>
   /// <param name="exportFor2005">If true, Import directive is omitted from the build. Useful when exporting for 2005.</param>
   private static void GenerateProject(string toolsVersion, string targetFrameworkVersion, string productVersion, bool exportFor2005)
   {
       VisualStudioProject project = new VisualStudioProject();
       DirectoryInfo directoryInfo = new DirectoryInfo(Path.Combine(Directory.GetCurrentDirectory(), "Assets"));
       project.AssemblyName = VisualStudioProject.GetProjectName();
       project.Compiled.AddRange(directoryInfo.GetFiles("*.cs", SearchOption.AllDirectories));
       project.Contents.AddRange(directoryInfo.GetFiles("*.shader", SearchOption.AllDirectories));
       project.Contents.AddRange(directoryInfo.GetFiles("*.js", SearchOption.AllDirectories));
       project.Contents.AddRange(directoryInfo.GetFiles("*.boo", SearchOption.AllDirectories));
       project.ProductVersion = productVersion;
       project.ToolsVersion = toolsVersion;
       project.TargetFrameworkVersion = targetFrameworkVersion;
       project.ProjectGuid = VisualStudioProject.GetProjectGuid();
       project.References = VisualStudioProject.GetCommonReferences();
       project.RootNamespace = VisualStudioProject.GetProjectName();
       project.SkipImport = exportFor2005;
       project.Build();
       project.Save();
       if (EditorUtility.DisplayDialog("Generation complete.", "Would you like to open the project?", "Yes", "No"))
       {
           string path = Path.Combine(Directory.GetCurrentDirectory(), VisualStudioProject.GetProjectName() + ".csproj");
           FileInfo info = new FileInfo(path);
           System.Diagnostics.Process.Start(info.FullName);
       }
   }

}

internal static class DocumentationHelper {

   /// <summary>
   /// Checks for documentation files and attempts to download these if not found.
   /// </summary>
   internal static void CheckAndDownload()
   {
       FileInfo unityEngineDll = new FileInfo(VisualStudioProject.GetAssemblyPath(typeof(UnityEngine.Object)));
       FileInfo unityEditorDll = new FileInfo(VisualStudioProject.GetAssemblyPath(typeof(UnityEditor.Editor)));
       FileInfo unityEngineXml = new FileInfo(Path.Combine(unityEngineDll.Directory.ToString(), "UnityEngine.xml"));
       FileInfo unityEditorXml = new FileInfo(Path.Combine(unityEditorDll.Directory.ToString(), "UnityEditor.xml"));
       if ((!unityEngineXml.Exists || !unityEditorXml.Exists))
       {
           string title = "Documentation missing.";
           string message = "Unity3D documentation not found.\nWould you attempt to download this now?\n(Documentation provided by unifycommuinty.com)";
           bool download = EditorUtility.DisplayDialog(title, message, "Download", "Skip");
           if (download)
           {
               DownloadDocumentationTo(unityEngineXml.Directory.FullName);
           }
       }
   }
   /// <summary>
   /// Downloads documentation to folder.
   /// </summary>
   /// <param name="destination">The folder where to place documentation zip to.</param>
   private static void DownloadDocumentationTo(string destination)
   {
       string url = @"http://www.unifycommunity.com/wiki/images/d/d2/Visual_Studio_docs_2.5.zip";
       string file = Path.Combine(destination, "Visual_Studio_docs_2.5.zip");
       try
       {
           WWW www = new WWW(url);
           while (!www.isDone)
           {
               EditorUtility.DisplayProgressBar("Downloading documentation...", "Downloading documentation for Visual Studio...", www.progress);
           }
           EditorUtility.DisplayProgressBar("Downloading documentation...", "Saving file...", 0.5f);
           File.WriteAllBytes(file, www.bytes);
           EditorUtility.ClearProgressBar();
           System.Diagnostics.Process.Start(destination);
           bool open = EditorUtility.DisplayDialog("Documentation downloaded.", "Would you like to open the zipped archive?", "Yes", "No");
           if (open)
           {
               System.Diagnostics.Process.Start(file);
           }
       }
       catch (Exception e)
       {
           Debug.LogWarning(string.Format("File download error ({0})", e.Message));
       }
   }

}

/// <summary> /// Handles building a visual studio project. /// </summary> internal sealed class VisualStudioProject {

   public const string VS2005ProjectVersion = "8.0.50727";
   public const string VS2008ProjectVersion = "9.0.21022";
   public const string VS2010ProjectVersion = "10.0.20506"; // This is from the public beta build.
   /// <summary>
   /// See GetProjectGuid()
   /// </summary>
   public Guid ProjectGuid = Guid.Empty;
   /// <summary>
   /// The version of Visual Studio this project is targetted for
   /// </summary>
   public string ProductVersion = VS2010ProjectVersion;
   /// <summary>
   /// The projects root namespace (used when creating new files through visual studio)
   /// </summary>
   public string RootNamespace = string.Empty;
   /// <summary>
   /// The projects assembly name. Commonly the project name. See GetProjectName()
   /// </summary>
   public string AssemblyName = string.Empty;
   /// <summary>
   /// Some sort of version identifier for the tools in visual studio. 
   /// </summary>
   public string ToolsVersion = "4.0";
   /// <summary>
   /// The target .net framework version.
   /// </summary>
   public string TargetFrameworkVersion = "v3.5";
   /// <summary>
   /// Relative path to the project where debug files are emitted during build events.
   /// </summary>
   public string DebugOutput = "Visual Studio/Debug/";
   /// <summary>
   /// Relative path to the project where release files are emitted during build events.
   /// </summary>
   public string ReleaseOutput = "Visual Studio/Release/";
   /// <summary>
   /// Mainly used for Visual Studio 2005 support.
   /// </summary>
   public bool SkipImport = false;
   /// <summary>
   /// List of references in the project
   /// </summary>
   public AssemblyReferences References = new AssemblyReferences();
   /// <summary>
   /// All content that is not to compiled and included in the project
   /// </summary>
   public FileInfos Compiled = new FileInfos();
   /// <summary>
   /// All content that is not to be compiled, but included in the project
   /// </summary>
   public FileInfos Contents = new FileInfos();
   /// <summary>
   /// Is set on Build() and contains the XmlDocument which makes up this project.
   /// </summary>
   public XmlDocument GeneratedDocument;
   /// <summary>
   /// References to Assemblies
   /// </summary>
   internal sealed class AssemblyReference
   {
       public string Name;
       public string HintPath;
       public AssemblyReference(string name)
           : this(name, string.Empty)
       {
       }
       public AssemblyReference(string name, string hintPath)
       {
           Name = name;
           HintPath = hintPath;
       }
   }


   /// <summary>
   /// Builds the project as defined through the member settings. 
   /// Access GeneratedDocument if you need to process contents easily through Xml.
   /// </summary>
   public void Build()
   {
       GeneratedDocument = new XmlDocument();
       XmlDeclaration declaration = GeneratedDocument.CreateXmlDeclaration("1.0", "utf-8", null);
       GeneratedDocument.AppendChild(declaration);
       BuildProject(GeneratedDocument);
   }
   /// <summary>
   /// Saves the project to yourprojectname.csproj.
   /// </summary>
   public void Save()
   {
       if (GeneratedDocument != null)
           GeneratedDocument.Save(Path.Combine(Directory.GetCurrentDirectory(), GetProjectName() + ".csproj"));
       else
           Debug.LogError("Must build document before Save");
   } 


   #region Helper functions
   /// <summary>
   /// Returns a list of assembly references commonly accessed, such as System.Core, System.Xml and the assemblies exposed by Unity3D.
   /// </summary>
   /// <returns>A list of common assembly references.</returns>
   public static AssemblyReferences GetCommonReferences()
   {
       AssemblyReferences references = new AssemblyReferences();
       AssemblyReference system = new AssemblyReference("System");
       references.Add(system);
       AssemblyReference systemCore = new AssemblyReference("System.Core");
       references.Add(systemCore);
       AssemblyReference systemXml = new AssemblyReference("System.XML");
       references.Add(systemXml);
       AssemblyReference unityEngine = new AssemblyReference("UnityEngine", GetAssemblyPath(typeof(UnityEngine.Object)));
       references.Add(unityEngine);
       AssemblyReference unityEditor = new AssemblyReference("UnityEditor", GetAssemblyPath(typeof(UnityEditor.Editor)));
       references.Add(unityEditor);
       return references;
   }
   /// <summary>
   /// Returns the path where the assembly which holds type exists.
   /// </summary>
   /// <param name="type">The type to discover its associated assemblys path.</param>
   /// <returns>The associated assemblys path.</returns>
   public static string GetAssemblyPath(Type type)
   {
       return Assembly.GetAssembly(type).Location;
   }
   /// <summary>
   /// Creates a deterministic Guid based on a string.
   /// </summary>
   /// <param name="input">The string used as input to generate a Guid.</param>
   /// <returns>The generated Guid based on input.</returns>
   public static Guid StringGuid(string input)
   {
       MD5 md5 = MD5.Create();
       Encoding encoding = Encoding.Default;
       byte[] bytes = encoding.GetBytes(input);
       byte[] hash = md5.ComputeHash(bytes);
       Guid guid = new Guid(hash);
       return guid;
   }
   /// <summary>
   /// Returns the project name based on the current directorys name (in lack of any API function).
   /// </summary>
   /// <returns>The current project name.</returns>
   public static string GetProjectName()
   {
       DirectoryInfo directoryInfo = new DirectoryInfo(Directory.GetCurrentDirectory());
       string projectName = directoryInfo.Name;
       return projectName;
   }
   /// <summary>
   /// Creates a deterministic guid based on the MD5 hash of the current project name.
   /// </summary>
   /// <returns>A guid for this project name.</returns>
   public static Guid GetProjectGuid()
   {
       return StringGuid(GetProjectName());
   }
   #endregion
   #region Helper functions to build the project in steps
   private void BuildProject(XmlDocument document)
   {
       XmlElement project = document.CreateElement("Project");
       project.SetAttribute("ToolsVersion", ToolsVersion);
       project.SetAttribute("DefaultTargets", "Build");
       project.SetAttribute("xmlns", "http://schemas.microsoft.com/developer/msbuild/2003");
       BuildProperties(project, document);
       BuildConfigurationDebug(project, document);
       BuildConfigurationRelease(project, document);
       BuildReferences(project, document);
       BuildFiles(project, document);
       // Visual Studio 2005 security fix.
       if (!SkipImport)
       {
           BuildImport(project, document);
       }
       document.AppendChild(project);
   }
   private void BuildProperties(XmlElement project, XmlDocument document)
   {
       XmlElement propertyGroup = document.CreateElement("PropertyGroup");
       XmlElement configuration = document.CreateElement("Configuration");
       configuration.SetAttribute("Condition", " '$(Configuration)' ==  ");
       configuration.InnerText = "Debug";
       propertyGroup.AppendChild(configuration);
       XmlElement platform = document.CreateElement("Platform");
       platform.SetAttribute("Condition", " '$(Platform)' ==  ");
       platform.InnerText = "AnyCPU";
       propertyGroup.AppendChild(platform);
       XmlElement productVersion = document.CreateElement("ProductVersion");
       productVersion.InnerText = ProductVersion;
       propertyGroup.AppendChild(productVersion);
       XmlElement schemaVersion = document.CreateElement("SchemaVersion");
       schemaVersion.InnerText = "2.0";
       propertyGroup.AppendChild(schemaVersion);
       XmlElement projectGuid = document.CreateElement("ProjectGuid");
       projectGuid.InnerText = ProjectGuid.ToString();
       propertyGroup.AppendChild(projectGuid);
       XmlElement outputType = document.CreateElement("OutputType");
       outputType.InnerText = "Library";
       propertyGroup.AppendChild(outputType);
       XmlElement appDesignerFolder = document.CreateElement("AppDesignerFolder");
       appDesignerFolder.InnerText = "Properties";
       propertyGroup.AppendChild(appDesignerFolder);
       XmlElement rootNamespace = document.CreateElement("RootNamespace");
       rootNamespace.InnerText = RootNamespace;
       propertyGroup.AppendChild(rootNamespace);
       XmlElement assemblyName = document.CreateElement("AssemblyName");
       assemblyName.InnerText = AssemblyName;
       propertyGroup.AppendChild(assemblyName);
       XmlElement targetFrameworkVersion = document.CreateElement("TargetFrameworkVersion");
       targetFrameworkVersion.InnerText = TargetFrameworkVersion;
       propertyGroup.AppendChild(targetFrameworkVersion);
       project.AppendChild(propertyGroup);
   }
   private void BuildConfigurationDebug(XmlElement project, XmlDocument document)
   {
       XmlElement propertyGroup = document.CreateElement("PropertyGroup");
       propertyGroup.SetAttribute("Condition", " '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ");
       XmlElement debugSymbols = document.CreateElement("DebugSymbols");
       debugSymbols.InnerText = "true";
       propertyGroup.AppendChild(debugSymbols);
       XmlElement debugType = document.CreateElement("DebugType");
       debugType.InnerText = "full";
       propertyGroup.AppendChild(debugType);
       XmlElement optimize = document.CreateElement("Optimize");
       optimize.InnerText = "false";
       propertyGroup.AppendChild(optimize);
       XmlElement outputPath = document.CreateElement("OutputPath");
       outputPath.InnerText = DebugOutput;
       propertyGroup.AppendChild(outputPath);
       XmlElement defineConstants = document.CreateElement("DefineConstants");
       defineConstants.InnerText = "DEBUG;TRACE";
       propertyGroup.AppendChild(defineConstants);
       XmlElement errorReport = document.CreateElement("ErrorReport");
       errorReport.InnerText = "prompt";
       propertyGroup.AppendChild(errorReport);
       XmlElement warningLevel = document.CreateElement("WarningLevel");
       warningLevel.InnerText = "4";
       propertyGroup.AppendChild(warningLevel);
       project.AppendChild(propertyGroup);
   }
   private void BuildConfigurationRelease(XmlElement project, XmlDocument document)
   {
       XmlElement propertyGroup = document.CreateElement("PropertyGroup");
       propertyGroup.SetAttribute("Condition", " '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ");
       XmlElement debugType = document.CreateElement("DebugType");
       debugType.InnerText = "pdbonly";
       propertyGroup.AppendChild(debugType);
       XmlElement optimize = document.CreateElement("Optimize");
       optimize.InnerText = "true";
       propertyGroup.AppendChild(optimize);
       XmlElement outputPath = document.CreateElement("OutputPath");
       outputPath.InnerText = ReleaseOutput;
       propertyGroup.AppendChild(outputPath);
       XmlElement defineConstants = document.CreateElement("DefineConstants");
       defineConstants.InnerText = "TRACE";
       propertyGroup.AppendChild(defineConstants);
       XmlElement errorReport = document.CreateElement("ErrorReport");
       errorReport.InnerText = "prompt";
       propertyGroup.AppendChild(errorReport);
       XmlElement warningLevel = document.CreateElement("WarningLevel");
       warningLevel.InnerText = "4";
       propertyGroup.AppendChild(warningLevel);
       project.AppendChild(propertyGroup);
   }
   private void BuildReferences(XmlElement project, XmlDocument document)
   {
       XmlElement itemGroup = document.CreateElement("ItemGroup");
       foreach (AssemblyReference assemblyReference in References)
       {
           XmlElement reference = document.CreateElement("Reference");
           reference.SetAttribute("Include", assemblyReference.Name);
           if (!string.IsNullOrEmpty(assemblyReference.HintPath))
           {
               XmlElement hintPath = document.CreateElement("HintPath");
               hintPath.InnerText = assemblyReference.HintPath;
               reference.AppendChild(hintPath);
           }
           itemGroup.AppendChild(reference);
       }
       project.AppendChild(itemGroup);
   }
   private void BuildFiles(XmlElement project, XmlDocument document)
   {
       XmlElement itemGroup = document.CreateElement("ItemGroup");
       foreach (FileInfo fileInfo in Compiled)
       {
           // For each compiled file
           XmlElement compile = document.CreateElement("Compile");
           compile.SetAttribute("Include", fileInfo.FullName);
           itemGroup.AppendChild(compile);
       }
       foreach (FileInfo fileInfo in Contents)
       {
           // For each .shader/.js/.boo
           XmlElement none = document.CreateElement("None");
           none.SetAttribute("Include", fileInfo.FullName);
           itemGroup.AppendChild(none);
       }
       project.AppendChild(itemGroup);
   }
   private void BuildImport(XmlElement project, XmlDocument document)
   {
       XmlElement import = document.CreateElement("Import");
       import.SetAttribute("Project", @"$(MSBuildToolsPath)/Microsoft.CSharp.targets");
       project.AppendChild(import);
   }
   #endregion

}</csharp> --Statement 06:50, 24 October 2009 (PDT)

Personal tools
Namespaces

Variants
Actions
Navigation
Extras
Toolbox