You've already forked com.unity.ide.cursor
mirror of
https://github.com/boxqkrtm/com.unity.ide.cursor.git
synced 2026-05-14 14:20:09 +00:00
com.unity.ide.visualstudio@2.0.0
## [2.0.0] - 2019-11-06 - Improved Visual Studio and Visual Studio for Mac automatic discovery - Added support for the VSTU messaging system (start/stop features from Visual Studio) - Added support for solution roundtrip (preserves references to external projects and solution properties) - Added support for VSTU Analyzers (requires Visual Studio 2019 16.3, Visual Studio for Mac 8.3) - Added a warning when using legacy pdb symbol files. - Fixed issues while Opening Visual Studio on Windows - Fixed issues while Opening Visual Studio on Mac ## [1.1.1] - 2019-05-29 Fix Bridge assembly loading with non VS2017 editors ## [1.1.0] - 2019-05-27 Move internal extension handling to package.
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 36422aa067e092e45b9820da2ee3e728
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
fileFormatVersion: 2
|
||||
guid: 36422aa067e092e45b9820da2ee3e728
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 41b2d972bdac29e4a89ef08b3b52c248
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
fileFormatVersion: 2
|
||||
guid: 41b2d972bdac29e4a89ef08b3b52c248
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
||||
Binary file not shown.
BIN
Editor/COMIntegration/Release/COMIntegration.exe
Normal file
BIN
Editor/COMIntegration/Release/COMIntegration.exe
Normal file
Binary file not shown.
@@ -1,7 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cb67edc1800c2ec4ba8dfb1cf0dfc84a
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
fileFormatVersion: 2
|
||||
guid: cb67edc1800c2ec4ba8dfb1cf0dfc84a
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,275 +1,165 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Unity.CodeEditor;
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using System.Diagnostics;
|
||||
using Microsoft.Win32;
|
||||
|
||||
namespace VisualStudioEditor
|
||||
{
|
||||
public interface IDiscovery {
|
||||
CodeEditor.Installation[] PathCallback();
|
||||
}
|
||||
|
||||
public class Discovery : IDiscovery {
|
||||
internal static string VisualStudioVersionToNiceName(VisualStudioVersion version)
|
||||
{
|
||||
switch (version)
|
||||
{
|
||||
case VisualStudioVersion.Invalid: return "Invalid Version";
|
||||
case VisualStudioVersion.VisualStudio2008: return "Visual Studio 2008";
|
||||
case VisualStudioVersion.VisualStudio2010: return "Visual Studio 2010";
|
||||
case VisualStudioVersion.VisualStudio2012: return "Visual Studio 2012";
|
||||
case VisualStudioVersion.VisualStudio2013: return "Visual Studio 2013";
|
||||
case VisualStudioVersion.VisualStudio2015: return "Visual Studio 2015";
|
||||
case VisualStudioVersion.VisualStudio2017: return "Visual Studio 2017";
|
||||
case VisualStudioVersion.VisualStudio2019: return "Visual Studio 2019";
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(version), version, null);
|
||||
}
|
||||
}
|
||||
|
||||
public CodeEditor.Installation[] PathCallback()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (VSEditor.IsWindows)
|
||||
{
|
||||
return GetInstalledVisualStudios().Select(pair => new CodeEditor.Installation
|
||||
{
|
||||
Path = pair.Value[0],
|
||||
Name = VisualStudioVersionToNiceName(pair.Key)
|
||||
}).ToArray();
|
||||
}
|
||||
if (VSEditor.IsOSX)
|
||||
{
|
||||
var installationList = new List<CodeEditor.Installation>();
|
||||
AddIfDirectoryExists("Visual Studio", "/Applications/Visual Studio.app", installationList);
|
||||
AddIfDirectoryExists("Visual Studio (Preview)", "/Applications/Visual Studio (Preview).app", installationList);
|
||||
return installationList.ToArray();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
UnityEngine.Debug.Log($"Error detecting Visual Studio installations: {ex.Message}{Environment.NewLine}{ex.StackTrace}");
|
||||
}
|
||||
return new CodeEditor.Installation[0];
|
||||
}
|
||||
|
||||
void AddIfDirectoryExists(string name, string path, List<CodeEditor.Installation> installations)
|
||||
{
|
||||
if (Directory.Exists(path))
|
||||
{
|
||||
installations.Add(new CodeEditor.Installation { Name = name, Path = path });
|
||||
}
|
||||
}
|
||||
|
||||
static string GetRegistryValue(string path, string key)
|
||||
{
|
||||
try
|
||||
{
|
||||
return Registry.GetValue(path, key, null) as string;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Derives the Visual Studio installation path from the debugger path
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The Visual Studio installation path (to devenv.exe)
|
||||
/// </returns>
|
||||
/// <param name='debuggerPath'>
|
||||
/// The debugger path from the windows registry
|
||||
/// </param>
|
||||
static string DeriveVisualStudioPath(string debuggerPath)
|
||||
{
|
||||
string startSentinel = DeriveProgramFilesSentinel();
|
||||
string endSentinel = "Common7";
|
||||
bool started = false;
|
||||
string[] tokens = debuggerPath.Split(new[] { Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar }, StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
string path = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles);
|
||||
|
||||
// Walk directories in debugger path, chop out "Program Files\INSTALLATION\PATH\HERE\Common7"
|
||||
foreach (var token in tokens)
|
||||
{
|
||||
if (!started && string.Equals(startSentinel, token, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
started = true;
|
||||
continue;
|
||||
}
|
||||
if (started)
|
||||
{
|
||||
path = Path.Combine(path, token);
|
||||
if (string.Equals(endSentinel, token, StringComparison.OrdinalIgnoreCase))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return Path.Combine(path, "IDE", "devenv.exe");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Derives the program files sentinel for grabbing the VS installation path.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// From a path like 'c:\Archivos de programa (x86)', returns 'Archivos de programa'
|
||||
/// </remarks>
|
||||
static string DeriveProgramFilesSentinel()
|
||||
{
|
||||
string path = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles)
|
||||
.Split(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar)
|
||||
.LastOrDefault();
|
||||
|
||||
if (!string.IsNullOrEmpty(path))
|
||||
{
|
||||
// This needs to be the "real" Program Files regardless of 64bitness
|
||||
int index = path.LastIndexOf("(x86)");
|
||||
if (0 <= index)
|
||||
path = path.Remove(index);
|
||||
return path.TrimEnd();
|
||||
}
|
||||
|
||||
return "Program Files";
|
||||
}
|
||||
|
||||
public static void ParseRawDevEnvPaths(string[] rawDevEnvPaths, Dictionary<VisualStudioVersion, string[]> versions)
|
||||
{
|
||||
if (rawDevEnvPaths == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var v2017 = rawDevEnvPaths.Where(path => path.Contains("2017")).ToArray();
|
||||
var v2019 = rawDevEnvPaths.Where(path => path.Contains("2019")).ToArray();
|
||||
|
||||
if (v2017.Length > 0)
|
||||
{
|
||||
versions[VisualStudioVersion.VisualStudio2017] = v2017;
|
||||
}
|
||||
|
||||
if (v2019.Length > 0)
|
||||
{
|
||||
versions[VisualStudioVersion.VisualStudio2019] = v2019;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Detects Visual Studio installations using the Windows registry
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The detected Visual Studio installations
|
||||
/// </returns>
|
||||
public static Dictionary<VisualStudioVersion, string[]> GetInstalledVisualStudios()
|
||||
{
|
||||
var versions = new Dictionary<VisualStudioVersion, string[]>();
|
||||
|
||||
if (VSEditor.IsWindows)
|
||||
{
|
||||
foreach (VisualStudioVersion version in Enum.GetValues(typeof(VisualStudioVersion)))
|
||||
{
|
||||
if (version > VisualStudioVersion.VisualStudio2015)
|
||||
continue;
|
||||
|
||||
try
|
||||
{
|
||||
// Try COMNTOOLS environment variable first
|
||||
FindLegacyVisualStudio(version, versions);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
UnityEngine.Debug.LogError($"VS: {e.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
var raw = FindVisualStudioDevEnvPaths();
|
||||
|
||||
ParseRawDevEnvPaths(raw.ToArray(), versions);
|
||||
}
|
||||
|
||||
return versions;
|
||||
}
|
||||
|
||||
static void FindLegacyVisualStudio(VisualStudioVersion version, Dictionary<VisualStudioVersion, string[]> versions)
|
||||
{
|
||||
string key = Environment.GetEnvironmentVariable($"VS{(int)version}0COMNTOOLS");
|
||||
if (!string.IsNullOrEmpty(key))
|
||||
{
|
||||
string path = Path.Combine(key, "..", "IDE", "devenv.exe");
|
||||
if (File.Exists(path))
|
||||
{
|
||||
versions[version] = new[] { path };
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Try the proper registry key
|
||||
key = GetRegistryValue(
|
||||
$@"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\{(int)version}.0", "InstallDir");
|
||||
|
||||
// Try to fallback to the 32bits hive
|
||||
if (string.IsNullOrEmpty(key))
|
||||
key = GetRegistryValue(
|
||||
$@"HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\VisualStudio\{(int)version}.0", "InstallDir");
|
||||
|
||||
if (!string.IsNullOrEmpty(key))
|
||||
{
|
||||
string path = Path.Combine(key, "devenv.exe");
|
||||
if (File.Exists(path))
|
||||
{
|
||||
versions[version] = new[] { path };
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback to debugger key
|
||||
key = GetRegistryValue(
|
||||
// VS uses this key for the local debugger path
|
||||
$@"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\{(int)version}.0\Debugger", "FEQARuntimeImplDll");
|
||||
if (!string.IsNullOrEmpty(key))
|
||||
{
|
||||
string path = DeriveVisualStudioPath(key);
|
||||
if (!string.IsNullOrEmpty(path) && File.Exists(path))
|
||||
versions[version] = new[] { DeriveVisualStudioPath(key) };
|
||||
}
|
||||
}
|
||||
|
||||
static IEnumerable<string> FindVisualStudioDevEnvPaths()
|
||||
{
|
||||
string asset = AssetDatabase.FindAssets("VSWhere a:packages").Select(AssetDatabase.GUIDToAssetPath).FirstOrDefault(assetPath => assetPath.Contains("vswhere.exe"));
|
||||
if (string.IsNullOrWhiteSpace(asset)) // This may be called too early where the asset database has not replicated this information yet.
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
UnityEditor.PackageManager.PackageInfo packageInfo = UnityEditor.PackageManager.PackageInfo.FindForAssetPath(asset);
|
||||
var progpath = packageInfo.resolvedPath + asset.Substring("Packages/com.unity.ide.visualstudio".Length);
|
||||
var process = new Process
|
||||
{
|
||||
StartInfo = new ProcessStartInfo
|
||||
{
|
||||
FileName = progpath,
|
||||
Arguments = "-prerelease -property productPath",
|
||||
UseShellExecute = false,
|
||||
CreateNoWindow = true,
|
||||
RedirectStandardOutput = true,
|
||||
RedirectStandardError = true,
|
||||
}
|
||||
};
|
||||
|
||||
process.Start();
|
||||
process.WaitForExit();
|
||||
|
||||
while (!process.StandardOutput.EndOfStream)
|
||||
{
|
||||
yield return process.StandardOutput.ReadLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Unity Technologies.
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using System.Diagnostics;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Linq;
|
||||
|
||||
namespace Microsoft.Unity.VisualStudio.Editor
|
||||
{
|
||||
internal static class Discovery
|
||||
{
|
||||
public static IEnumerable<VisualStudioInstallation> GetVisualStudioInstallations()
|
||||
{
|
||||
if (VisualStudioEditor.IsWindows)
|
||||
{
|
||||
foreach (var installation in QueryVsWhere())
|
||||
yield return installation;
|
||||
}
|
||||
|
||||
if (VisualStudioEditor.IsOSX)
|
||||
{
|
||||
var candidates = Directory.EnumerateDirectories("/Applications", "*.app");
|
||||
foreach (var candidate in candidates)
|
||||
{
|
||||
if (TryDiscoverInstallation(candidate, out var installation))
|
||||
yield return installation;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static bool IsCandidateToDiscovery(string path)
|
||||
{
|
||||
if (File.Exists(path) && VisualStudioEditor.IsWindows && Regex.IsMatch(path, "devenv.exe$", RegexOptions.IgnoreCase))
|
||||
return true;
|
||||
|
||||
if (Directory.Exists(path) && VisualStudioEditor.IsOSX && Regex.IsMatch(path, "Visual\\s?Studio(?!.*Code.*).*.app$", RegexOptions.IgnoreCase))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool TryDiscoverInstallation(string editorPath, out VisualStudioInstallation installation)
|
||||
{
|
||||
installation = null;
|
||||
|
||||
if (string.IsNullOrEmpty(editorPath))
|
||||
return false;
|
||||
|
||||
if (!IsCandidateToDiscovery(editorPath))
|
||||
return false;
|
||||
|
||||
// On windows we use the executable directly, so we can query extra information
|
||||
var fvi = editorPath;
|
||||
|
||||
// On Mac we use the .app folder, so we need to access to main assembly
|
||||
if (VisualStudioEditor.IsOSX)
|
||||
fvi = Path.Combine(editorPath, "Contents", "Resources", "lib", "monodevelop", "bin", "VisualStudio.exe");
|
||||
|
||||
if (!File.Exists(fvi))
|
||||
return false;
|
||||
|
||||
// VS preview are not using the isPrerelease flag so far
|
||||
// On Windows FileDescription contains "Preview", but not on Mac
|
||||
var vi = FileVersionInfo.GetVersionInfo(fvi);
|
||||
var version = new Version(vi.ProductVersion);
|
||||
var isPrerelease = vi.IsPreRelease || string.Concat(editorPath, "/" + vi.FileDescription).ToLower().Contains("preview");
|
||||
|
||||
installation = new VisualStudioInstallation()
|
||||
{
|
||||
IsPrerelease = isPrerelease,
|
||||
Name = $"{vi.FileDescription}{(isPrerelease && VisualStudioEditor.IsOSX ? " Preview" : string.Empty)} [{version.ToString(3)}]",
|
||||
Path = editorPath,
|
||||
Version = version
|
||||
};
|
||||
return true;
|
||||
}
|
||||
|
||||
#region VsWhere Json Schema
|
||||
#pragma warning disable CS0649
|
||||
[Serializable]
|
||||
internal class VsWhereResult
|
||||
{
|
||||
public VsWhereEntry[] entries;
|
||||
|
||||
public static VsWhereResult FromJson(string json)
|
||||
{
|
||||
return JsonUtility.FromJson<VsWhereResult>("{ \"" + nameof(VsWhereResult.entries) + "\": " + json + " }");
|
||||
}
|
||||
|
||||
public IEnumerable<VisualStudioInstallation> ToVisualStudioInstallations()
|
||||
{
|
||||
foreach(var entry in entries)
|
||||
{
|
||||
yield return new VisualStudioInstallation()
|
||||
{
|
||||
Name = $"{entry.displayName} [{entry.catalog.productDisplayVersion}]",
|
||||
Path = entry.productPath,
|
||||
IsPrerelease = entry.isPrerelease,
|
||||
Version = Version.Parse(entry.catalog.buildVersion)
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
internal class VsWhereEntry
|
||||
{
|
||||
public string displayName;
|
||||
public bool isPrerelease;
|
||||
public string productPath;
|
||||
public VsWhereCatalog catalog;
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
internal class VsWhereCatalog
|
||||
{
|
||||
public string productDisplayVersion; // non parseable like "16.3.0 Preview 3.0"
|
||||
public string buildVersion;
|
||||
}
|
||||
#pragma warning restore CS3021
|
||||
#endregion
|
||||
|
||||
private static IEnumerable<VisualStudioInstallation> QueryVsWhere()
|
||||
{
|
||||
var progpath = FileUtility
|
||||
.FindPackageAssetFullPath("VSWhere a:packages", "vswhere.exe")
|
||||
.FirstOrDefault();
|
||||
|
||||
if (string.IsNullOrWhiteSpace(progpath))
|
||||
return Enumerable.Empty<VisualStudioInstallation>();
|
||||
|
||||
var process = new Process
|
||||
{
|
||||
StartInfo = new ProcessStartInfo
|
||||
{
|
||||
FileName = progpath,
|
||||
Arguments = "-prerelease -format json",
|
||||
UseShellExecute = false,
|
||||
CreateNoWindow = true,
|
||||
RedirectStandardOutput = true,
|
||||
RedirectStandardError = true,
|
||||
}
|
||||
};
|
||||
|
||||
using (process)
|
||||
{
|
||||
var json = string.Empty;
|
||||
|
||||
process.OutputDataReceived += (o, e) => json += e.Data;
|
||||
process.Start();
|
||||
process.BeginOutputReadLine();
|
||||
process.WaitForExit();
|
||||
|
||||
var result = VsWhereResult.FromJson(json);
|
||||
return result.ToVisualStudioInstallations();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: abe003ac6fee32e4892100a78f555011
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
fileFormatVersion: 2
|
||||
guid: abe003ac6fee32e4892100a78f555011
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
||||
92
Editor/FileUtility.cs
Normal file
92
Editor/FileUtility.cs
Normal file
@@ -0,0 +1,92 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Unity Technologies.
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Microsoft.Unity.VisualStudio.Editor
|
||||
{
|
||||
internal static class FileUtility
|
||||
{
|
||||
public const char WinSeparator = '\\';
|
||||
public const char UnixSeparator = '/';
|
||||
|
||||
// Safe for packages as we use packageInfo.resolvedPath, so this should work in library package cache as well
|
||||
public static string[] FindPackageAssetFullPath(string assetfilter, string filefilter)
|
||||
{
|
||||
return AssetDatabase.FindAssets(assetfilter)
|
||||
.Select(AssetDatabase.GUIDToAssetPath)
|
||||
.Where(assetPath => assetPath.Contains(filefilter))
|
||||
.Select(asset =>
|
||||
{
|
||||
var packageInfo = UnityEditor.PackageManager.PackageInfo.FindForAssetPath(asset);
|
||||
return Normalize(packageInfo.resolvedPath + asset.Substring(packageInfo.assetPath.Length));
|
||||
})
|
||||
.ToArray();
|
||||
}
|
||||
|
||||
public static string GetAssetFullPath(string asset)
|
||||
{
|
||||
var basePath = Path.GetFullPath(Path.Combine(Application.dataPath, ".."));
|
||||
return Path.GetFullPath(Path.Combine(basePath, Normalize(asset)));
|
||||
}
|
||||
|
||||
public static string Normalize(string path)
|
||||
{
|
||||
if (string.IsNullOrEmpty(path))
|
||||
return path;
|
||||
|
||||
if (Path.DirectorySeparatorChar == WinSeparator)
|
||||
path = path.Replace(UnixSeparator, WinSeparator);
|
||||
|
||||
return path.Replace(string.Concat(WinSeparator, WinSeparator), WinSeparator.ToString());
|
||||
}
|
||||
|
||||
internal static bool IsFileInProjectDirectory(string fileName)
|
||||
{
|
||||
var basePath = Path.GetFullPath(Path.Combine(Application.dataPath, ".."));
|
||||
fileName = Normalize(fileName);
|
||||
|
||||
if (!Path.IsPathRooted(fileName))
|
||||
fileName = Path.Combine(basePath, fileName);
|
||||
|
||||
return string.Equals(Path.GetDirectoryName(fileName), basePath, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
public static string FileNameWithoutExtension(string path)
|
||||
{
|
||||
if (string.IsNullOrEmpty(path))
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
var indexOfDot = -1;
|
||||
var indexOfSlash = 0;
|
||||
for (var i = path.Length - 1; i >= 0; i--)
|
||||
{
|
||||
if (indexOfDot == -1 && path[i] == '.')
|
||||
{
|
||||
indexOfDot = i;
|
||||
}
|
||||
|
||||
if (indexOfSlash == 0 && path[i] == '/' || path[i] == '\\')
|
||||
{
|
||||
indexOfSlash = i + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (indexOfDot == -1)
|
||||
{
|
||||
indexOfDot = path.Length - 1;
|
||||
}
|
||||
|
||||
return path.Substring(indexOfSlash, indexOfDot - indexOfSlash);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6f1dc05fb6e7d3e4f89ae9ca482735be
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
fileFormatVersion: 2
|
||||
guid: 6f1dc05fb6e7d3e4f89ae9ca482735be
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,8 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 55aae143147983c4ca41af0f79695248
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
fileFormatVersion: 2
|
||||
guid: 2f820130c86c28547a0f1a2f4c73155b
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
40
Editor/Messaging/Deserializer.cs
Normal file
40
Editor/Messaging/Deserializer.cs
Normal file
@@ -0,0 +1,40 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
namespace Microsoft.Unity.VisualStudio.Editor.Messaging
|
||||
{
|
||||
internal class Deserializer
|
||||
{
|
||||
private readonly BinaryReader _reader;
|
||||
|
||||
// Max UDP packet size is 65507
|
||||
private const int MaxStringLength = 65000;
|
||||
|
||||
public Deserializer(byte[] buffer)
|
||||
{
|
||||
_reader = new BinaryReader(new MemoryStream(buffer));
|
||||
}
|
||||
|
||||
public int ReadInt32()
|
||||
{
|
||||
return _reader.ReadInt32();
|
||||
}
|
||||
|
||||
public string ReadString()
|
||||
{
|
||||
var length = ReadInt32();
|
||||
return length > 0 && length <= MaxStringLength
|
||||
? Encoding.UTF8.GetString(_reader.ReadBytes(length))
|
||||
: "";
|
||||
}
|
||||
|
||||
public bool CanReadMore()
|
||||
{
|
||||
return _reader.BaseStream.Position < _reader.BaseStream.Length;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c70a64eb158b0104bb528b12e1d80c2a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
fileFormatVersion: 2
|
||||
guid: 3eda7a83649158546826efb3ffe6c1e3
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
18
Editor/Messaging/ExceptionEventArgs.cs
Normal file
18
Editor/Messaging/ExceptionEventArgs.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
using System;
|
||||
|
||||
namespace Microsoft.Unity.VisualStudio.Editor.Messaging
|
||||
{
|
||||
internal class ExceptionEventArgs
|
||||
{
|
||||
public Exception Exception { get; }
|
||||
|
||||
public ExceptionEventArgs(Exception exception)
|
||||
{
|
||||
Exception = exception;
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Editor/Messaging/ExceptionEventArgs.cs.meta
Normal file
11
Editor/Messaging/ExceptionEventArgs.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 917a51fff055ce547b4ad1215321f3da
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
23
Editor/Messaging/Message.cs
Normal file
23
Editor/Messaging/Message.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
using System.Globalization;
|
||||
using System.Net;
|
||||
|
||||
namespace Microsoft.Unity.VisualStudio.Editor.Messaging
|
||||
{
|
||||
internal class Message
|
||||
{
|
||||
public MessageType Type { get; set; }
|
||||
|
||||
public string Value { get; set; }
|
||||
|
||||
public IPEndPoint Origin { get; set; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format(CultureInfo.InvariantCulture, "<Message type:{0} value:{1}>", Type, Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Editor/Messaging/Message.cs.meta
Normal file
11
Editor/Messaging/Message.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: de1c9ea7b82c9904d9e5fba2ee70a998
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
19
Editor/Messaging/MessageEventArgs.cs
Normal file
19
Editor/Messaging/MessageEventArgs.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
namespace Microsoft.Unity.VisualStudio.Editor.Messaging
|
||||
{
|
||||
internal class MessageEventArgs
|
||||
{
|
||||
public Message Message
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
public MessageEventArgs(Message message)
|
||||
{
|
||||
Message = message;
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Editor/Messaging/MessageEventArgs.cs.meta
Normal file
11
Editor/Messaging/MessageEventArgs.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 275143c81d816ef4286fdc67aabc20c8
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
34
Editor/Messaging/MessageType.cs
Normal file
34
Editor/Messaging/MessageType.cs
Normal file
@@ -0,0 +1,34 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
namespace Microsoft.Unity.VisualStudio.Editor.Messaging
|
||||
{
|
||||
internal enum MessageType
|
||||
{
|
||||
None = 0,
|
||||
|
||||
Ping,
|
||||
Pong,
|
||||
|
||||
Play,
|
||||
Stop,
|
||||
Pause,
|
||||
Unpause,
|
||||
|
||||
Build,
|
||||
Refresh,
|
||||
|
||||
Info,
|
||||
Error,
|
||||
Warning,
|
||||
|
||||
Open,
|
||||
Opened,
|
||||
|
||||
Version,
|
||||
UpdatePackage,
|
||||
|
||||
ProjectPath,
|
||||
}
|
||||
}
|
||||
11
Editor/Messaging/MessageType.cs.meta
Normal file
11
Editor/Messaging/MessageType.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f3edbdc86577af648a23263aa75161e1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
176
Editor/Messaging/Messenger.cs
Normal file
176
Editor/Messaging/Messenger.cs
Normal file
@@ -0,0 +1,176 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
|
||||
namespace Microsoft.Unity.VisualStudio.Editor.Messaging
|
||||
{
|
||||
internal class Messager : IDisposable
|
||||
{
|
||||
public event EventHandler<MessageEventArgs> ReceiveMessage;
|
||||
public event EventHandler<ExceptionEventArgs> MessagerException;
|
||||
|
||||
private readonly UdpSocket _socket;
|
||||
private readonly object _disposeLock = new object();
|
||||
private bool _disposed;
|
||||
|
||||
protected Messager(int port)
|
||||
{
|
||||
_socket = new UdpSocket();
|
||||
_socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ExclusiveAddressUse, false);
|
||||
_socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
|
||||
_socket.Bind(IPAddress.Any, port);
|
||||
|
||||
BeginReceiveMessage();
|
||||
}
|
||||
|
||||
private void BeginReceiveMessage()
|
||||
{
|
||||
var buffer = new byte[UdpSocket.BufferSize];
|
||||
var any = UdpSocket.Any();
|
||||
|
||||
try
|
||||
{
|
||||
lock (_disposeLock)
|
||||
{
|
||||
if (_disposed)
|
||||
return;
|
||||
|
||||
_socket.BeginReceiveFrom(buffer, 0, buffer.Length, SocketFlags.None, ref any, ReceiveMessageCallback, buffer);
|
||||
}
|
||||
}
|
||||
catch (SocketException se)
|
||||
{
|
||||
MessagerException?.Invoke(this, new ExceptionEventArgs(se));
|
||||
|
||||
BeginReceiveMessage();
|
||||
}
|
||||
catch (ObjectDisposedException)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
private void ReceiveMessageCallback(IAsyncResult result)
|
||||
{
|
||||
try
|
||||
{
|
||||
var endPoint = UdpSocket.Any();
|
||||
|
||||
lock (_disposeLock)
|
||||
{
|
||||
if (_disposed)
|
||||
return;
|
||||
|
||||
_socket.EndReceiveFrom(result, ref endPoint);
|
||||
}
|
||||
|
||||
var message = DeserializeMessage(UdpSocket.BufferFor(result));
|
||||
if (message != null)
|
||||
{
|
||||
message.Origin = (IPEndPoint)endPoint;
|
||||
ReceiveMessage?.Invoke(this, new MessageEventArgs(message));
|
||||
}
|
||||
}
|
||||
catch (ObjectDisposedException)
|
||||
{
|
||||
return;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
RaiseMessagerException(e);
|
||||
}
|
||||
|
||||
BeginReceiveMessage();
|
||||
}
|
||||
|
||||
private void RaiseMessagerException(Exception e)
|
||||
{
|
||||
MessagerException?.Invoke(this, new ExceptionEventArgs(e));
|
||||
}
|
||||
|
||||
private static Message MessageFor(MessageType type, string value)
|
||||
{
|
||||
return new Message { Type = type, Value = value };
|
||||
}
|
||||
|
||||
public void SendMessage(IPEndPoint target, MessageType type, string value = "")
|
||||
{
|
||||
var message = MessageFor(type, value);
|
||||
var buffer = SerializeMessage(message);
|
||||
|
||||
try
|
||||
{
|
||||
lock (_disposeLock)
|
||||
{
|
||||
if (_disposed)
|
||||
return;
|
||||
|
||||
_socket.BeginSendTo(buffer, 0, Math.Min(buffer.Length, UdpSocket.BufferSize), SocketFlags.None, target, SendMessageCallback, null);
|
||||
}
|
||||
}
|
||||
catch (SocketException se)
|
||||
{
|
||||
MessagerException?.Invoke(this, new ExceptionEventArgs(se));
|
||||
}
|
||||
}
|
||||
|
||||
private void SendMessageCallback(IAsyncResult result)
|
||||
{
|
||||
try
|
||||
{
|
||||
lock (_disposeLock)
|
||||
{
|
||||
if (_disposed)
|
||||
return;
|
||||
|
||||
_socket.EndSendTo(result);
|
||||
}
|
||||
}
|
||||
catch (SocketException se)
|
||||
{
|
||||
MessagerException?.Invoke(this, new ExceptionEventArgs(se));
|
||||
}
|
||||
catch (ObjectDisposedException)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
private static byte[] SerializeMessage(Message message)
|
||||
{
|
||||
var serializer = new Serializer();
|
||||
serializer.WriteInt32((int)message.Type);
|
||||
serializer.WriteString(message.Value);
|
||||
|
||||
return serializer.Buffer();
|
||||
}
|
||||
|
||||
private static Message DeserializeMessage(byte[] buffer)
|
||||
{
|
||||
if (buffer.Length < 4)
|
||||
return null;
|
||||
|
||||
var deserializer = new Deserializer(buffer);
|
||||
var type = (MessageType)deserializer.ReadInt32();
|
||||
var value = deserializer.ReadString();
|
||||
|
||||
return new Message { Type = type, Value = value };
|
||||
}
|
||||
|
||||
public static Messager BindTo(int port)
|
||||
{
|
||||
return new Messager(port);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
lock (_disposeLock)
|
||||
{
|
||||
_disposed = true;
|
||||
_socket.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Editor/Messaging/Messenger.cs.meta
Normal file
11
Editor/Messaging/Messenger.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5e249ae353801f043a6e4173410c6152
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
43
Editor/Messaging/Serializer.cs
Normal file
43
Editor/Messaging/Serializer.cs
Normal file
@@ -0,0 +1,43 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
namespace Microsoft.Unity.VisualStudio.Editor.Messaging
|
||||
{
|
||||
internal class Serializer
|
||||
{
|
||||
private readonly MemoryStream _stream;
|
||||
private readonly BinaryWriter _writer;
|
||||
|
||||
public Serializer()
|
||||
{
|
||||
_stream = new MemoryStream();
|
||||
_writer = new BinaryWriter(_stream);
|
||||
}
|
||||
|
||||
public void WriteInt32(int i)
|
||||
{
|
||||
_writer.Write(i);
|
||||
}
|
||||
|
||||
public void WriteString(string s)
|
||||
{
|
||||
var bytes = Encoding.UTF8.GetBytes(s ?? "");
|
||||
if (bytes.Length > 0)
|
||||
{
|
||||
_writer.Write(bytes.Length);
|
||||
_writer.Write(bytes);
|
||||
}
|
||||
else
|
||||
_writer.Write(0);
|
||||
}
|
||||
|
||||
public byte[] Buffer()
|
||||
{
|
||||
return _stream.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Editor/Messaging/Serializer.cs.meta
Normal file
11
Editor/Messaging/Serializer.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 369c09afe05d2c346af49faef943c773
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
53
Editor/Messaging/UdpSocket.cs
Normal file
53
Editor/Messaging/UdpSocket.cs
Normal file
@@ -0,0 +1,53 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
|
||||
namespace Microsoft.Unity.VisualStudio.Editor.Messaging
|
||||
{
|
||||
internal class UdpSocket : Socket
|
||||
{
|
||||
public const int BufferSize = 1024 * 8;
|
||||
|
||||
internal UdpSocket()
|
||||
: base(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp)
|
||||
{
|
||||
SetIOControl();
|
||||
}
|
||||
|
||||
public void Bind(IPAddress address, int port = 0)
|
||||
{
|
||||
Bind(new IPEndPoint(address ?? IPAddress.Any, port));
|
||||
}
|
||||
|
||||
private void SetIOControl()
|
||||
{
|
||||
if (!VisualStudioEditor.IsWindows)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
const int SIO_UDP_CONNRESET = -1744830452;
|
||||
|
||||
IOControl(SIO_UDP_CONNRESET, new byte[] { 0 }, new byte[0]);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// fallback
|
||||
}
|
||||
}
|
||||
|
||||
public static byte[] BufferFor(IAsyncResult result)
|
||||
{
|
||||
return (byte[])result.AsyncState;
|
||||
}
|
||||
|
||||
public static EndPoint Any()
|
||||
{
|
||||
return new IPEndPoint(IPAddress.Any, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Editor/Messaging/UdpSocket.cs.meta
Normal file
11
Editor/Messaging/UdpSocket.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 38cb3a4a17d2cfd41926da95ce675934
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,8 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1e5abb64fdd0542b38f4dc1b60343e8a
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
fileFormatVersion: 2
|
||||
guid: 1e5abb64fdd0542b38f4dc1b60343e8a
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
||||
@@ -1,28 +1,28 @@
|
||||
fileFormatVersion: 2
|
||||
guid: dd66e4390e06fc14e92b9822744f2fb1
|
||||
folderAsset: yes
|
||||
PluginImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
iconMap: {}
|
||||
executionOrder: {}
|
||||
defineConstraints: []
|
||||
isPreloaded: 0
|
||||
isOverridable: 1
|
||||
isExplicitlyReferenced: 0
|
||||
validateReferences: 1
|
||||
platformData:
|
||||
- first:
|
||||
Any:
|
||||
second:
|
||||
enabled: 0
|
||||
settings: {}
|
||||
- first:
|
||||
Editor: Editor
|
||||
second:
|
||||
enabled: 1
|
||||
settings:
|
||||
DefaultValueInitialized: true
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
fileFormatVersion: 2
|
||||
guid: a20df6e3467b24ed5b49c857ce39e096
|
||||
folderAsset: yes
|
||||
PluginImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
iconMap: {}
|
||||
executionOrder: {}
|
||||
defineConstraints: []
|
||||
isPreloaded: 0
|
||||
isOverridable: 1
|
||||
isExplicitlyReferenced: 0
|
||||
validateReferences: 1
|
||||
platformData:
|
||||
- first:
|
||||
Any:
|
||||
second:
|
||||
enabled: 0
|
||||
settings: {}
|
||||
- first:
|
||||
Editor: Editor
|
||||
second:
|
||||
enabled: 1
|
||||
settings:
|
||||
DefaultValueInitialized: true
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,8 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 179209ff257e808409c755d32ecf1086
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
fileFormatVersion: 2
|
||||
guid: 058b02c03ea09473aab4dc5fc50af1ef
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,44 +1,42 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>BuildMachineOSBuild</key>
|
||||
<string>18E226</string>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>AppleEventIntegrationPlugin</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.unity.AppleEventIntegrationPlugin</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>AppleEventIntegrationPlugin</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>BNDL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleSupportedPlatforms</key>
|
||||
<array>
|
||||
<string>MacOSX</string>
|
||||
</array>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>DTCompiler</key>
|
||||
<string>com.apple.compilers.llvm.clang.1_0</string>
|
||||
<key>DTPlatformBuild</key>
|
||||
<string>10E1001</string>
|
||||
<key>DTPlatformVersion</key>
|
||||
<string>GM</string>
|
||||
<key>DTSDKBuild</key>
|
||||
<string>18E219</string>
|
||||
<key>DTSDKName</key>
|
||||
<string>macosx10.14</string>
|
||||
<key>DTXcode</key>
|
||||
<string>1020</string>
|
||||
<key>DTXcodeBuild</key>
|
||||
<string>10E1001</string>
|
||||
<key>NSHumanReadableCopyright</key>
|
||||
<string>Copyright © 2019 Unity. All rights reserved.</string>
|
||||
</dict>
|
||||
</plist>
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>BuildMachineOSBuild</key>
|
||||
<string>19B88</string>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>AppleEventIntegration</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.unity.visualstudio.AppleEventIntegration</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>AppleEventIntegration</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleSupportedPlatforms</key>
|
||||
<array>
|
||||
<string>MacOSX</string>
|
||||
</array>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>DTCompiler</key>
|
||||
<string>com.apple.compilers.llvm.clang.1_0</string>
|
||||
<key>DTPlatformBuild</key>
|
||||
<string>10E125</string>
|
||||
<key>DTPlatformVersion</key>
|
||||
<string>GM</string>
|
||||
<key>DTSDKBuild</key>
|
||||
<string>18E219</string>
|
||||
<key>DTSDKName</key>
|
||||
<string>macosx10.14</string>
|
||||
<key>DTXcode</key>
|
||||
<string>1020</string>
|
||||
<key>DTXcodeBuild</key>
|
||||
<string>10E125</string>
|
||||
<key>NSHumanReadableCopyright</key>
|
||||
<string>Copyright © 2019 Unity. All rights reserved.</string>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -1,7 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d2694cce95579ec47a939a1a3efb8f33
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
fileFormatVersion: 2
|
||||
guid: 680cf1008b4284eddbb82ec4d76644a1
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,8 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a0f0c231a0e381e4ea37a97a8e7837a0
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
fileFormatVersion: 2
|
||||
guid: ba4355216f6c44abbb17503872c42c97
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Binary file not shown.
@@ -1,7 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b94b55fbf62c6bd42a2f3edf2fd52f83
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
fileFormatVersion: 2
|
||||
guid: 4e53c7f7b5c7e4a3d890cb596ed56c22
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Binary file not shown.
@@ -1,115 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>files</key>
|
||||
<dict/>
|
||||
<key>files2</key>
|
||||
<dict/>
|
||||
<key>rules</key>
|
||||
<dict>
|
||||
<key>^Resources/</key>
|
||||
<true/>
|
||||
<key>^Resources/.*\.lproj/</key>
|
||||
<dict>
|
||||
<key>optional</key>
|
||||
<true/>
|
||||
<key>weight</key>
|
||||
<real>1000</real>
|
||||
</dict>
|
||||
<key>^Resources/.*\.lproj/locversion.plist$</key>
|
||||
<dict>
|
||||
<key>omit</key>
|
||||
<true/>
|
||||
<key>weight</key>
|
||||
<real>1100</real>
|
||||
</dict>
|
||||
<key>^Resources/Base\.lproj/</key>
|
||||
<dict>
|
||||
<key>weight</key>
|
||||
<real>1010</real>
|
||||
</dict>
|
||||
<key>^version.plist$</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>rules2</key>
|
||||
<dict>
|
||||
<key>.*\.dSYM($|/)</key>
|
||||
<dict>
|
||||
<key>weight</key>
|
||||
<real>11</real>
|
||||
</dict>
|
||||
<key>^(.*/)?\.DS_Store$</key>
|
||||
<dict>
|
||||
<key>omit</key>
|
||||
<true/>
|
||||
<key>weight</key>
|
||||
<real>2000</real>
|
||||
</dict>
|
||||
<key>^(Frameworks|SharedFrameworks|PlugIns|Plug-ins|XPCServices|Helpers|MacOS|Library/(Automator|Spotlight|LoginItems))/</key>
|
||||
<dict>
|
||||
<key>nested</key>
|
||||
<true/>
|
||||
<key>weight</key>
|
||||
<real>10</real>
|
||||
</dict>
|
||||
<key>^.*</key>
|
||||
<true/>
|
||||
<key>^Info\.plist$</key>
|
||||
<dict>
|
||||
<key>omit</key>
|
||||
<true/>
|
||||
<key>weight</key>
|
||||
<real>20</real>
|
||||
</dict>
|
||||
<key>^PkgInfo$</key>
|
||||
<dict>
|
||||
<key>omit</key>
|
||||
<true/>
|
||||
<key>weight</key>
|
||||
<real>20</real>
|
||||
</dict>
|
||||
<key>^Resources/</key>
|
||||
<dict>
|
||||
<key>weight</key>
|
||||
<real>20</real>
|
||||
</dict>
|
||||
<key>^Resources/.*\.lproj/</key>
|
||||
<dict>
|
||||
<key>optional</key>
|
||||
<true/>
|
||||
<key>weight</key>
|
||||
<real>1000</real>
|
||||
</dict>
|
||||
<key>^Resources/.*\.lproj/locversion.plist$</key>
|
||||
<dict>
|
||||
<key>omit</key>
|
||||
<true/>
|
||||
<key>weight</key>
|
||||
<real>1100</real>
|
||||
</dict>
|
||||
<key>^Resources/Base\.lproj/</key>
|
||||
<dict>
|
||||
<key>weight</key>
|
||||
<real>1010</real>
|
||||
</dict>
|
||||
<key>^[^/]+$</key>
|
||||
<dict>
|
||||
<key>nested</key>
|
||||
<true/>
|
||||
<key>weight</key>
|
||||
<real>10</real>
|
||||
</dict>
|
||||
<key>^embedded\.provisionprofile$</key>
|
||||
<dict>
|
||||
<key>weight</key>
|
||||
<real>20</real>
|
||||
</dict>
|
||||
<key>^version\.plist$</key>
|
||||
<dict>
|
||||
<key>weight</key>
|
||||
<real>20</real>
|
||||
</dict>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -1,7 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8529f5a60acb8cd4395bd1cec74495ae
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,11 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c55bbb5ab4b342946980281be9e63c1a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
fileFormatVersion: 2
|
||||
guid: c55bbb5ab4b342946980281be9e63c1a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
||||
12
Editor/Solution.cs
Normal file
12
Editor/Solution.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
namespace Microsoft.Unity.VisualStudio.Editor
|
||||
{
|
||||
internal class Solution
|
||||
{
|
||||
public SolutionProjectEntry[] Projects { get; set; }
|
||||
public SolutionProperties[] Properties { get; set; }
|
||||
}
|
||||
}
|
||||
11
Editor/Solution.cs.meta
Normal file
11
Editor/Solution.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: af4c2c762e1d8e949a6bc458973df6e7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
80
Editor/SolutionParser.cs
Normal file
80
Editor/SolutionParser.cs
Normal file
@@ -0,0 +1,80 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace Microsoft.Unity.VisualStudio.Editor
|
||||
{
|
||||
internal static class SolutionParser
|
||||
{
|
||||
// Compared to the bridge implementation, we are not returning "{" "}" from Guids
|
||||
private static readonly Regex ProjectDeclaration = new Regex(@"Project\(\""{(?<projectFactoryGuid>.*?)}\""\)\s+=\s+\""(?<name>.*?)\"",\s+\""(?<fileName>.*?)\"",\s+\""{(?<projectGuid>.*?)}\""(?<content>.*?)\bEndProject\b", RegexOptions.Singleline | RegexOptions.ExplicitCapture);
|
||||
private static readonly Regex PropertiesDeclaration = new Regex(@"GlobalSection\((?<name>[\w]+Properties)\)\s+=\s+(?<type>(?:post|pre)Solution)(?<entries>.*?)EndGlobalSection", RegexOptions.Singleline | RegexOptions.ExplicitCapture);
|
||||
private static readonly Regex PropertiesEntryDeclaration = new Regex(@"^\s*(?<key>.*?)=(?<value>.*?)$", RegexOptions.Multiline | RegexOptions.ExplicitCapture);
|
||||
|
||||
public static Solution ParseSolutionFile(string filename)
|
||||
{
|
||||
return ParseSolutionContent(File.ReadAllText(filename));
|
||||
}
|
||||
|
||||
public static Solution ParseSolutionContent(string content)
|
||||
{
|
||||
return new Solution
|
||||
{
|
||||
Projects = ParseSolutionProjects(content),
|
||||
Properties = ParseSolutionProperties(content)
|
||||
};
|
||||
}
|
||||
|
||||
private static SolutionProjectEntry[] ParseSolutionProjects(string content)
|
||||
{
|
||||
var projects = new List<SolutionProjectEntry>();
|
||||
var mc = ProjectDeclaration.Matches(content);
|
||||
|
||||
foreach (Match match in mc)
|
||||
{
|
||||
projects.Add(new SolutionProjectEntry
|
||||
{
|
||||
ProjectFactoryGuid = match.Groups["projectFactoryGuid"].Value,
|
||||
Name = match.Groups["name"].Value,
|
||||
FileName = match.Groups["fileName"].Value,
|
||||
ProjectGuid = match.Groups["projectGuid"].Value,
|
||||
});
|
||||
}
|
||||
|
||||
return projects.ToArray();
|
||||
}
|
||||
|
||||
private static SolutionProperties[] ParseSolutionProperties(string content)
|
||||
{
|
||||
var properties = new List<SolutionProperties>();
|
||||
var mc = PropertiesDeclaration.Matches(content);
|
||||
|
||||
foreach (Match match in mc)
|
||||
{
|
||||
var sp = new SolutionProperties
|
||||
{
|
||||
Entries = new List<KeyValuePair<string, string>>(),
|
||||
Name = match.Groups["name"].Value,
|
||||
Type = match.Groups["type"].Value
|
||||
};
|
||||
|
||||
var entries = match.Groups["entries"].Value;
|
||||
var mec = PropertiesEntryDeclaration.Matches(entries);
|
||||
foreach (Match entry in mec)
|
||||
{
|
||||
var key = entry.Groups["key"].Value.Trim();
|
||||
var value = entry.Groups["value"].Value.Trim();
|
||||
sp.Entries.Add(new KeyValuePair<string, string>(key, value));
|
||||
}
|
||||
|
||||
properties.Add(sp);
|
||||
}
|
||||
|
||||
return properties.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Editor/SolutionParser.cs.meta
Normal file
11
Editor/SolutionParser.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fbbb1ee655846b043baf6c3502b5ce49
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
14
Editor/SolutionProjectEntry.cs
Normal file
14
Editor/SolutionProjectEntry.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
namespace Microsoft.Unity.VisualStudio.Editor
|
||||
{
|
||||
internal class SolutionProjectEntry
|
||||
{
|
||||
public string ProjectFactoryGuid { get; set; }
|
||||
public string Name { get; set; }
|
||||
public string FileName { get; set; }
|
||||
public string ProjectGuid { get; set; }
|
||||
}
|
||||
}
|
||||
11
Editor/SolutionProjectEntry.cs.meta
Normal file
11
Editor/SolutionProjectEntry.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5c1b8a755d2c97640bbb207c43f4cf61
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
15
Editor/SolutionProperties.cs
Normal file
15
Editor/SolutionProperties.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Microsoft.Unity.VisualStudio.Editor
|
||||
{
|
||||
internal class SolutionProperties
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public IList<KeyValuePair<string, string>> Entries { get; set; }
|
||||
public string Type { get; set; }
|
||||
}
|
||||
}
|
||||
11
Editor/SolutionProperties.cs.meta
Normal file
11
Editor/SolutionProperties.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 829d4d6bc39fd1044ba4c5fc2a9c911f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
30
Editor/Symbols.cs
Normal file
30
Editor/Symbols.cs
Normal file
@@ -0,0 +1,30 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace Microsoft.Unity.VisualStudio.Editor
|
||||
{
|
||||
internal static class Symbols
|
||||
{
|
||||
public static bool IsPortableSymbolFile(string pdbFile)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (var stream = File.OpenRead(pdbFile))
|
||||
{
|
||||
return stream.ReadByte() == 'B'
|
||||
&& stream.ReadByte() == 'S'
|
||||
&& stream.ReadByte() == 'J'
|
||||
&& stream.ReadByte() == 'B';
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Editor/Symbols.cs.meta
Normal file
11
Editor/Symbols.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b9308b762484008498bb5cd1886aa491
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,35 +0,0 @@
|
||||
namespace VisualStudioEditor
|
||||
{
|
||||
public static class Utility
|
||||
{
|
||||
public static string FileNameWithoutExtension(string path)
|
||||
{
|
||||
if (string.IsNullOrEmpty(path))
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
var indexOfDot = -1;
|
||||
var indexOfSlash = 0;
|
||||
for (var i = path.Length - 1; i >= 0; i--)
|
||||
{
|
||||
if (indexOfDot == -1 && path[i] == '.')
|
||||
{
|
||||
indexOfDot = i;
|
||||
}
|
||||
if (indexOfSlash == 0 && path[i] == '/' || path[i] == '\\')
|
||||
{
|
||||
indexOfSlash = i + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (indexOfDot == -1)
|
||||
{
|
||||
indexOfDot = path.Length - 1;
|
||||
}
|
||||
|
||||
return path.Substring(indexOfSlash, indexOfDot - indexOfSlash);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,335 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Microsoft.Win32;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using Debug = System.Diagnostics.Debug;
|
||||
using Unity.CodeEditor;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
|
||||
namespace VisualStudioEditor
|
||||
{
|
||||
public enum VisualStudioVersion
|
||||
{
|
||||
Invalid = 0,
|
||||
VisualStudio2008 = 9,
|
||||
VisualStudio2010 = 10,
|
||||
VisualStudio2012 = 11,
|
||||
VisualStudio2013 = 12,
|
||||
VisualStudio2015 = 14,
|
||||
VisualStudio2017 = 15,
|
||||
VisualStudio2019 = 16,
|
||||
}
|
||||
|
||||
[InitializeOnLoad]
|
||||
public class VSEditor : IExternalCodeEditor
|
||||
{
|
||||
static readonly string k_ExpressNotSupportedMessage = L10n.Tr(
|
||||
"Unfortunately Visual Studio Express does not allow itself to be controlled by external applications. " +
|
||||
"You can still use it by manually opening the Visual Studio project file, but Unity cannot automatically open files for you when you doubleclick them. " +
|
||||
"\n(This does work with Visual Studio Pro)"
|
||||
);
|
||||
|
||||
static VSEditor()
|
||||
{
|
||||
try
|
||||
{
|
||||
InstalledVisualStudios = Discovery.GetInstalledVisualStudios();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
UnityEngine.Debug.Log($@"Error detecting Visual Studio installations: {ex.Message}{Environment.NewLine}{ex.StackTrace}");
|
||||
InstalledVisualStudios = new Dictionary<VisualStudioVersion, string[]>();
|
||||
}
|
||||
var editor = new VSEditor(new Discovery(), new ProjectGeneration());
|
||||
CodeEditor.Register(editor);
|
||||
var current = CodeEditor.CurrentEditorInstallation;
|
||||
if (editor.TryGetInstallationForPath(current, out var installation))
|
||||
{
|
||||
if (installation.Name != "MonoDevelop")
|
||||
{
|
||||
editor.Initialize(current);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const string unity_generate_all = "unity_generate_all_csproj";
|
||||
IDiscovery m_Discoverability;
|
||||
IGenerator m_Generation;
|
||||
CodeEditor.Installation m_Installation;
|
||||
VSInitializer m_Initializer = new VSInitializer();
|
||||
|
||||
public VSEditor(IDiscovery discovery, IGenerator projectGeneration)
|
||||
{
|
||||
m_Discoverability = discovery;
|
||||
m_Generation = projectGeneration;
|
||||
}
|
||||
|
||||
internal static Dictionary<VisualStudioVersion, string[]> InstalledVisualStudios { get; private set; }
|
||||
|
||||
internal static bool IsOSX => Application.platform == RuntimePlatform.OSXEditor;
|
||||
internal static bool IsWindows => !IsOSX && Path.DirectorySeparatorChar == '\\' && Environment.NewLine == "\r\n";
|
||||
|
||||
public CodeEditor.Installation[] Installations => m_Discoverability.PathCallback();
|
||||
|
||||
public void CreateIfDoesntExist()
|
||||
{
|
||||
if (!m_Generation.HasSolutionBeenGenerated())
|
||||
{
|
||||
m_Generation.Sync();
|
||||
}
|
||||
}
|
||||
|
||||
public bool TryGetInstallationForPath(string editorPath, out CodeEditor.Installation installation)
|
||||
{
|
||||
var lowerCasePath = editorPath.ToLower();
|
||||
if (lowerCasePath.EndsWith("vcsexpress.exe", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
installation = new CodeEditor.Installation
|
||||
{
|
||||
Name = "VSExpress",
|
||||
Path = editorPath
|
||||
};
|
||||
m_Installation = installation;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (lowerCasePath.EndsWith("devenv.exe", StringComparison.OrdinalIgnoreCase)
|
||||
|| lowerCasePath.Replace(" ", "").EndsWith("visualstudio.app", StringComparison.OrdinalIgnoreCase)
|
||||
|| lowerCasePath.Replace(" ", "").EndsWith("visualstudio(preview).app", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
installation = new CodeEditor.Installation
|
||||
{
|
||||
Name = "VisualStudio",
|
||||
Path = editorPath
|
||||
};
|
||||
m_Installation = installation;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (lowerCasePath.Contains("monodevelop")
|
||||
|| lowerCasePath.Replace(" ", "").Contains("xamarinstudio"))
|
||||
{
|
||||
installation = new CodeEditor.Installation
|
||||
{
|
||||
Name = "MonoDevelop",
|
||||
Path = editorPath
|
||||
};
|
||||
m_Installation = installation;
|
||||
return true;
|
||||
}
|
||||
|
||||
installation = default;
|
||||
m_Installation = installation;
|
||||
return false;
|
||||
}
|
||||
|
||||
public void OnGUI()
|
||||
{
|
||||
if (m_Installation.Name.Equals("VSExpress"))
|
||||
{
|
||||
GUILayout.BeginHorizontal(EditorStyles.helpBox);
|
||||
GUILayout.Label("", "CN EntryWarn");
|
||||
GUILayout.Label(k_ExpressNotSupportedMessage, "WordWrappedLabel");
|
||||
GUILayout.EndHorizontal();
|
||||
}
|
||||
|
||||
var prevGenerate = EditorPrefs.GetBool(unity_generate_all, false);
|
||||
var generateAll = EditorGUILayout.Toggle("Generate all .csproj files.", prevGenerate);
|
||||
if (generateAll != prevGenerate)
|
||||
{
|
||||
EditorPrefs.SetBool(unity_generate_all, generateAll);
|
||||
}
|
||||
m_Generation.GenerateAll(generateAll);
|
||||
}
|
||||
|
||||
public void SyncIfNeeded(string[] addedFiles, string[] deletedFiles, string[] movedFiles, string[] movedFromFiles, string[] importedFiles)
|
||||
{
|
||||
m_Generation.SyncIfNeeded(addedFiles.Union(deletedFiles).Union(movedFiles).Union(movedFromFiles), importedFiles);
|
||||
}
|
||||
|
||||
public void SyncAll()
|
||||
{
|
||||
AssetDatabase.Refresh();
|
||||
m_Generation.Sync();
|
||||
}
|
||||
|
||||
public void Initialize(string editorInstallationPath)
|
||||
{
|
||||
m_Initializer.Initialize(editorInstallationPath, InstalledVisualStudios);
|
||||
}
|
||||
|
||||
public bool OpenProject(string path, int line, int column)
|
||||
{
|
||||
if (m_Installation.Name == "MonoDevelop") {
|
||||
return OpenAppMonoDev(path, line, column);
|
||||
}
|
||||
|
||||
if (IsOSX)
|
||||
{
|
||||
return OpenOSXApp(path, line, column);
|
||||
}
|
||||
|
||||
if (IsWindows)
|
||||
{
|
||||
return OpenWindowsApp(path, line);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool OpenWindowsApp(string path, int line)
|
||||
{
|
||||
var comAssetPath = AssetDatabase.FindAssets("COMIntegration a:packages").Select(AssetDatabase.GUIDToAssetPath).First(assetPath => assetPath.Contains("COMIntegration.dom"));
|
||||
if (string.IsNullOrWhiteSpace(comAssetPath)) // This may be called too early where the asset database has not replicated this information yet.
|
||||
{
|
||||
return false;
|
||||
}
|
||||
UnityEditor.PackageManager.PackageInfo packageInfo = UnityEditor.PackageManager.PackageInfo.FindForAssetPath(comAssetPath);
|
||||
var progpath = packageInfo.resolvedPath + comAssetPath.Substring("Packages/com.unity.ide.visualstudio".Length);
|
||||
string absolutePath = "";
|
||||
if (!string.IsNullOrWhiteSpace(path))
|
||||
{
|
||||
absolutePath = Path.GetFullPath(path);
|
||||
}
|
||||
|
||||
|
||||
var solution = GetOrGenerateSolutionFile(path);
|
||||
solution = solution == "" ? "" : $"\"{solution}\"";
|
||||
var process = new Process
|
||||
{
|
||||
StartInfo = new ProcessStartInfo
|
||||
{
|
||||
FileName = progpath,
|
||||
Arguments = $"\"{CodeEditor.CurrentEditorInstallation}\" \"{absolutePath}\" {solution} {line}",
|
||||
CreateNoWindow = true,
|
||||
UseShellExecute = false,
|
||||
RedirectStandardOutput = true,
|
||||
RedirectStandardError = true,
|
||||
}
|
||||
};
|
||||
var result = process.Start();
|
||||
|
||||
while (!process.StandardOutput.EndOfStream)
|
||||
{
|
||||
var outputLine = process.StandardOutput.ReadLine();
|
||||
if (outputLine == "displayProgressBar")
|
||||
{
|
||||
EditorUtility.DisplayProgressBar("Opening Visual Studio", "Starting up Visual Studio, this might take some time.", .5f);
|
||||
}
|
||||
|
||||
if (outputLine == "clearprogressbar")
|
||||
{
|
||||
EditorUtility.ClearProgressBar();
|
||||
}
|
||||
}
|
||||
var errorOutput = process.StandardError.ReadToEnd();
|
||||
if (!string.IsNullOrEmpty(errorOutput))
|
||||
{
|
||||
Console.WriteLine("Error: \n" + errorOutput);
|
||||
}
|
||||
|
||||
process.WaitForExit();
|
||||
return result;
|
||||
}
|
||||
|
||||
bool OpenAppMonoDev(string path, int line, int column)
|
||||
{
|
||||
string absolutePath = "";
|
||||
if (!string.IsNullOrWhiteSpace(path))
|
||||
{
|
||||
absolutePath = Path.GetFullPath(path);
|
||||
}
|
||||
|
||||
var solution = GetOrGenerateSolutionFile(path);
|
||||
solution = solution == "" ? "" : $"\"{solution}\"";
|
||||
var pathArguments = path == "" ? "" : $"\"{path}\";{line}";
|
||||
var fileName = IsOSX ? "open" : CodeEditor.CurrentEditorInstallation;
|
||||
var arguments = IsOSX
|
||||
? $"\"{CodeEditor.CurrentEditorInstallation}\" --args --nologo {solution} {pathArguments}"
|
||||
: $"--nologo {solution} {pathArguments}";
|
||||
var process = new Process
|
||||
{
|
||||
StartInfo = new ProcessStartInfo
|
||||
{
|
||||
FileName = fileName,
|
||||
Arguments = arguments,
|
||||
CreateNoWindow = true,
|
||||
UseShellExecute = true,
|
||||
}
|
||||
};
|
||||
|
||||
process.Start();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
[DllImport ("AppleEventIntegrationPlugin")]
|
||||
static extern void OpenVisualStudio(string appPath, string solutionPath, string filePath, int line, StringBuilder sb, int sbLength);
|
||||
|
||||
bool OpenOSXApp(string path, int line, int column)
|
||||
{
|
||||
string absolutePath = "";
|
||||
if (!string.IsNullOrWhiteSpace(path))
|
||||
{
|
||||
absolutePath = Path.GetFullPath(path);
|
||||
}
|
||||
|
||||
string solution = GetOrGenerateSolutionFile(path);
|
||||
|
||||
StringBuilder sb = new StringBuilder(4096);
|
||||
|
||||
OpenVisualStudio(CodeEditor.CurrentEditorInstallation, solution, absolutePath, line, sb, sb.Capacity);
|
||||
|
||||
Console.WriteLine(sb.ToString());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private string GetOrGenerateSolutionFile(string path)
|
||||
{
|
||||
var solution = GetSolutionFile(path);
|
||||
if (solution == "")
|
||||
{
|
||||
m_Generation.Sync();
|
||||
solution = GetSolutionFile(path);
|
||||
}
|
||||
|
||||
return solution;
|
||||
}
|
||||
|
||||
string GetSolutionFile(string path)
|
||||
{
|
||||
if (UnityEditor.Unsupported.IsDeveloperBuild())
|
||||
{
|
||||
var baseFolder = GetBaseUnityDeveloperFolder();
|
||||
var lowerPath = path.ToLowerInvariant();
|
||||
var isUnitySourceCode =
|
||||
lowerPath.Contains((baseFolder + "/Runtime").ToLowerInvariant())
|
||||
|| lowerPath.Contains((baseFolder + "/Editor").ToLowerInvariant());
|
||||
|
||||
if (isUnitySourceCode)
|
||||
{
|
||||
return Path.Combine(baseFolder, "Projects/CSharp/Unity.CSharpProjects.gen.sln");
|
||||
}
|
||||
}
|
||||
var solutionFile = m_Generation.SolutionFile();
|
||||
if (File.Exists(solutionFile))
|
||||
{
|
||||
return solutionFile;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
static string GetBaseUnityDeveloperFolder()
|
||||
{
|
||||
return Directory.GetParent(EditorApplication.applicationPath).Parent.Parent.FullName;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,276 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text.RegularExpressions;
|
||||
using Microsoft.Win32;
|
||||
using UnityEngine;
|
||||
using Debug = UnityEngine.Debug;
|
||||
|
||||
namespace VisualStudioEditor
|
||||
{
|
||||
internal class VSInitializer
|
||||
{
|
||||
public void Initialize(string editorPath, Dictionary<VisualStudioVersion, string[]> installedVisualStudios)
|
||||
{
|
||||
switch (Application.platform) {
|
||||
case RuntimePlatform.OSXEditor:
|
||||
InitializeVSForMac(editorPath);
|
||||
break;
|
||||
case RuntimePlatform.WindowsEditor:
|
||||
InitializeVisualStudio(editorPath, installedVisualStudios);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void InitializeVSForMac(string externalEditor)
|
||||
{
|
||||
if (!IsVSForMac(externalEditor, out var vsfmVersion))
|
||||
return;
|
||||
|
||||
var bridgeFile = GetVSForMacBridgeAssembly(externalEditor, vsfmVersion);
|
||||
if (string.IsNullOrEmpty(bridgeFile) || !File.Exists(bridgeFile))
|
||||
{
|
||||
Debug.Log("Unable to find Tools for Unity bridge dll for Visual Studio for Mac " + externalEditor);
|
||||
return;
|
||||
}
|
||||
|
||||
AppDomain.CurrentDomain.Load(AssemblyName.GetAssemblyName(bridgeFile));
|
||||
}
|
||||
|
||||
static bool IsVisualStudioForMac(string path)
|
||||
{
|
||||
var lowerCasePath = path.ToLower();
|
||||
var filename = Path.GetFileName(lowerCasePath).Replace(" ", "");
|
||||
return filename.StartsWith("visualstudio") && !filename.Contains("code") && filename.EndsWith(".app");
|
||||
}
|
||||
|
||||
static bool IsVSForMac(string externalEditor, out Version vsfmVersion)
|
||||
{
|
||||
vsfmVersion = null;
|
||||
|
||||
if (!IsVisualStudioForMac(externalEditor))
|
||||
return false;
|
||||
|
||||
// We need to extract the version used by VS for Mac
|
||||
// to lookup its addin registry
|
||||
try
|
||||
{
|
||||
return GetVSForMacVersion(externalEditor, out vsfmVersion);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.Log("Failed to read Visual Studio for Mac information");
|
||||
Debug.LogException(e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static bool GetVSForMacVersion(string externalEditor, out Version vsfmVersion)
|
||||
{
|
||||
vsfmVersion = null;
|
||||
|
||||
// Read the full VS for Mac version from the plist, it will look like this:
|
||||
//
|
||||
// <key>CFBundleShortVersionString</key>
|
||||
// <string>X.X.X.X</string>
|
||||
|
||||
var plist = Path.Combine(externalEditor, "Contents/Info.plist");
|
||||
if (!File.Exists(plist))
|
||||
return false;
|
||||
|
||||
const string versionStringRegex = @"\<key\>CFBundleShortVersionString\</key\>\s+\<string\>(?<version>\d+\.\d+\.\d+\.\d+?)\</string\>";
|
||||
|
||||
var file = File.ReadAllText(plist);
|
||||
var match = Regex.Match(file, versionStringRegex);
|
||||
var versionGroup = match.Groups["version"];
|
||||
if (!versionGroup.Success)
|
||||
return false;
|
||||
|
||||
vsfmVersion = new Version(versionGroup.Value);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void InitializeVisualStudio(string externalEditor, Dictionary<VisualStudioVersion, string[]> installedVisualStudios)
|
||||
{
|
||||
if (!externalEditor.Contains("2017"))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
FindVisualStudio(externalEditor, out var vsVersion, installedVisualStudios);
|
||||
var bridgeFile = GetVstuBridgeAssembly(vsVersion);
|
||||
if (bridgeFile == null)
|
||||
{
|
||||
Debug.Log("Unable to find bridge dll in registry for Microsoft Visual Studio Tools for Unity for " + externalEditor);
|
||||
return;
|
||||
}
|
||||
if (!File.Exists(bridgeFile))
|
||||
{
|
||||
Debug.Log("Unable to find bridge dll on disk for Microsoft Visual Studio Tools for Unity for " + bridgeFile);
|
||||
return;
|
||||
}
|
||||
|
||||
AppDomain.CurrentDomain.Load(AssemblyName.GetAssemblyName(bridgeFile));
|
||||
}
|
||||
|
||||
static string GetVstuBridgeAssembly(VisualStudioVersion version)
|
||||
{
|
||||
try
|
||||
{
|
||||
var vsVersion = string.Empty;
|
||||
|
||||
switch (version)
|
||||
{
|
||||
// Starting with VS 15, the registry key is using the VS version
|
||||
// to avoid taking a dependency on the product name
|
||||
case VisualStudioVersion.VisualStudio2017:
|
||||
vsVersion = "15.0";
|
||||
break;
|
||||
case VisualStudioVersion.VisualStudio2019:
|
||||
vsVersion = "16.0";
|
||||
break;
|
||||
// VS 2015 and under are still installed in the registry
|
||||
// using their project names
|
||||
case VisualStudioVersion.VisualStudio2015:
|
||||
vsVersion = "2015";
|
||||
break;
|
||||
case VisualStudioVersion.VisualStudio2013:
|
||||
vsVersion = "2013";
|
||||
break;
|
||||
case VisualStudioVersion.VisualStudio2012:
|
||||
vsVersion = "2012";
|
||||
break;
|
||||
case VisualStudioVersion.VisualStudio2010:
|
||||
vsVersion = "2010";
|
||||
break;
|
||||
}
|
||||
|
||||
// search first for the current user with a fallback to machine wide setting
|
||||
return GetVstuBridgePathFromRegistry(vsVersion, true)
|
||||
?? GetVstuBridgePathFromRegistry(vsVersion, false);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
static string GetVstuBridgePathFromRegistry(string vsVersion, bool currentUser)
|
||||
{
|
||||
var registryKey = $@"{(currentUser ? "HKEY_CURRENT_USER" : "HKEY_LOCAL_MACHINE")}\Software\Microsoft\Microsoft Visual Studio {vsVersion} Tools for Unity";
|
||||
|
||||
return (string)Registry.GetValue(registryKey, "UnityExtensionPath", null);
|
||||
}
|
||||
|
||||
static void FindVisualStudio(string externalEditor, out VisualStudioVersion vsVersion, Dictionary<VisualStudioVersion, string[]> installedVisualStudios)
|
||||
{
|
||||
if (string.IsNullOrEmpty(externalEditor))
|
||||
{
|
||||
vsVersion = VisualStudioVersion.Invalid;
|
||||
return;
|
||||
}
|
||||
|
||||
// If it's a VS found through envvars or the registry
|
||||
var matches = installedVisualStudios.Where(kvp => kvp.Value.Any(v => Path.GetFullPath(v).Equals(Path.GetFullPath(externalEditor), StringComparison.OrdinalIgnoreCase))).ToArray();
|
||||
if (matches.Length > 0)
|
||||
{
|
||||
vsVersion = matches[0].Key;
|
||||
return;
|
||||
}
|
||||
|
||||
// If it's a side-by-side VS selected manually
|
||||
if (externalEditor.EndsWith("devenv.exe", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
if (TryGetVisualStudioVersion(externalEditor, out vsVersion)) return;
|
||||
}
|
||||
|
||||
vsVersion = VisualStudioVersion.Invalid;
|
||||
}
|
||||
|
||||
static bool TryGetVisualStudioVersion(string externalEditor, out VisualStudioVersion vsVersion)
|
||||
{
|
||||
switch (ProductVersion(externalEditor).Major)
|
||||
{
|
||||
case 9:
|
||||
vsVersion = VisualStudioVersion.VisualStudio2008;
|
||||
return true;
|
||||
case 10:
|
||||
vsVersion = VisualStudioVersion.VisualStudio2010;
|
||||
return true;
|
||||
case 11:
|
||||
vsVersion = VisualStudioVersion.VisualStudio2012;
|
||||
return true;
|
||||
case 12:
|
||||
vsVersion = VisualStudioVersion.VisualStudio2013;
|
||||
return true;
|
||||
case 14:
|
||||
vsVersion = VisualStudioVersion.VisualStudio2015;
|
||||
return true;
|
||||
case 15:
|
||||
vsVersion = VisualStudioVersion.VisualStudio2017;
|
||||
return true;
|
||||
case 16:
|
||||
vsVersion = VisualStudioVersion.VisualStudio2019;
|
||||
return true;
|
||||
}
|
||||
|
||||
vsVersion = VisualStudioVersion.Invalid;
|
||||
return false;
|
||||
}
|
||||
|
||||
static Version ProductVersion(string externalEditor)
|
||||
{
|
||||
try
|
||||
{
|
||||
return new Version(FileVersionInfo.GetVersionInfo(externalEditor).ProductVersion);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return new Version(0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static string GetVSForMacBridgeAssembly(string externalEditor, Version vsfmVersion)
|
||||
{
|
||||
// Check first if we're overriden
|
||||
// Useful when developing UnityVS for Mac
|
||||
var bridge = Environment.GetEnvironmentVariable("VSTUM_BRIDGE");
|
||||
if (!string.IsNullOrEmpty(bridge) && File.Exists(bridge))
|
||||
return bridge;
|
||||
|
||||
// Look for installed addin
|
||||
const string addinBridge = "Editor/SyntaxTree.VisualStudio.Unity.Bridge.dll";
|
||||
const string addinName = "MonoDevelop.Unity";
|
||||
|
||||
// Check if we're installed in the user addins repository
|
||||
// ~/Library/Application Support/VisualStudio/X.0/LocalInstall/Addins
|
||||
var localAddins = Path.Combine(
|
||||
Environment.GetFolderPath(Environment.SpecialFolder.Personal),
|
||||
"Library/Application Support/VisualStudio/" + vsfmVersion.Major + ".0" + "/LocalInstall/Addins");
|
||||
|
||||
// In the user addins repository, the addins are suffixed by their versions, like `MonoDevelop.Unity.1.0`
|
||||
// When installing another local user addin, MD will remove files inside the folder
|
||||
// So we browse all VSTUM addins, and return the one with a bridge, which is the one MD will load
|
||||
if (Directory.Exists(localAddins))
|
||||
{
|
||||
foreach (var folder in Directory.GetDirectories(localAddins, addinName + "*", SearchOption.TopDirectoryOnly))
|
||||
{
|
||||
bridge = Path.Combine(folder, addinBridge);
|
||||
if (File.Exists(bridge))
|
||||
return bridge;
|
||||
}
|
||||
}
|
||||
|
||||
// Check in Visual Studio.app/
|
||||
// In that case the name of the addin is used
|
||||
bridge = Path.Combine(externalEditor, "Contents/Resources/lib/monodevelop/AddIns/" + addinName + "/" + addinBridge);
|
||||
if (File.Exists(bridge))
|
||||
return bridge;
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5b17896803f77494da73d73448fb6cb4
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
fileFormatVersion: 2
|
||||
guid: 5b17896803f77494da73d73448fb6cb4
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 585c3fb85b32bd64e8814074e754163e
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
fileFormatVersion: 2
|
||||
guid: 585c3fb85b32bd64e8814074e754163e
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
||||
258
Editor/VisualStudioEditor.cs
Normal file
258
Editor/VisualStudioEditor.cs
Normal file
@@ -0,0 +1,258 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Unity Technologies.
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using Unity.CodeEditor;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Microsoft.Unity.VisualStudio.Editor
|
||||
{
|
||||
[InitializeOnLoad]
|
||||
public class VisualStudioEditor : IExternalCodeEditor
|
||||
{
|
||||
private static readonly VisualStudioInstallation[] _installations;
|
||||
|
||||
internal static bool IsOSX => Application.platform == RuntimePlatform.OSXEditor;
|
||||
internal static bool IsWindows => !IsOSX && Path.DirectorySeparatorChar == '\\' && Environment.NewLine == "\r\n";
|
||||
|
||||
CodeEditor.Installation[] IExternalCodeEditor.Installations => _installations
|
||||
.Select(i => i.ToCodeEditorInstallation())
|
||||
.ToArray();
|
||||
|
||||
private readonly IGenerator _generator = new ProjectGeneration();
|
||||
|
||||
static VisualStudioEditor()
|
||||
{
|
||||
try
|
||||
{
|
||||
_installations = Discovery
|
||||
.GetVisualStudioInstallations()
|
||||
.ToArray();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
UnityEngine.Debug.Log($"Error detecting Visual Studio installations: {ex}");
|
||||
_installations = Array.Empty<VisualStudioInstallation>();
|
||||
}
|
||||
|
||||
CodeEditor.Register(new VisualStudioEditor());
|
||||
}
|
||||
|
||||
public void CreateIfDoesntExist()
|
||||
{
|
||||
if (!_generator.HasSolutionBeenGenerated())
|
||||
_generator.Sync();
|
||||
}
|
||||
|
||||
public void Initialize(string editorInstallationPath)
|
||||
{
|
||||
}
|
||||
|
||||
internal bool TryGetVisualStudioInstallationForPath(string editorPath, out VisualStudioInstallation installation)
|
||||
{
|
||||
// lookup for well known installations
|
||||
foreach (var candidate in _installations)
|
||||
{
|
||||
if (!string.Equals(Path.GetFullPath(editorPath), Path.GetFullPath(candidate.Path), StringComparison.OrdinalIgnoreCase))
|
||||
continue;
|
||||
|
||||
installation = candidate;
|
||||
return true;
|
||||
}
|
||||
|
||||
return Discovery.TryDiscoverInstallation(editorPath, out installation);
|
||||
}
|
||||
|
||||
public bool TryGetInstallationForPath(string editorPath, out CodeEditor.Installation installation)
|
||||
{
|
||||
var result = TryGetVisualStudioInstallationForPath(editorPath, out var vsi);
|
||||
installation = vsi == null ? default : vsi.ToCodeEditorInstallation();
|
||||
return result;
|
||||
}
|
||||
|
||||
public void OnGUI()
|
||||
{
|
||||
const string unity_generate_all = "unity_generate_all_csproj";
|
||||
|
||||
GUILayout.BeginHorizontal();
|
||||
GUILayout.FlexibleSpace();
|
||||
|
||||
var package = UnityEditor.PackageManager.PackageInfo.FindForAssembly(GetType().Assembly);
|
||||
|
||||
var style = new GUIStyle
|
||||
{
|
||||
richText = true,
|
||||
margin = new RectOffset(0, 4, 0, 0)
|
||||
};
|
||||
|
||||
GUILayout.Label($"<size=10><color=grey>{package.displayName} v{package.version} enabled</color></size>", style);
|
||||
GUILayout.EndHorizontal();
|
||||
|
||||
var prevGenerate = EditorPrefs.GetBool(unity_generate_all, false);
|
||||
var generateAll = EditorGUILayout.Toggle("Generate all .csproj files.", prevGenerate);
|
||||
if (generateAll != prevGenerate)
|
||||
{
|
||||
EditorPrefs.SetBool(unity_generate_all, generateAll);
|
||||
}
|
||||
|
||||
_generator.GenerateAll(generateAll);
|
||||
}
|
||||
|
||||
public void SyncIfNeeded(string[] addedFiles, string[] deletedFiles, string[] movedFiles, string[] movedFromFiles, string[] importedFiles)
|
||||
{
|
||||
_generator.SyncIfNeeded(addedFiles.Union(deletedFiles).Union(movedFiles).Union(movedFromFiles), importedFiles);
|
||||
|
||||
foreach (var file in importedFiles.Where(a => Path.GetExtension(a) == ".pdb"))
|
||||
{
|
||||
var pdbFile = FileUtility.GetAssetFullPath(file);
|
||||
if (Symbols.IsPortableSymbolFile(pdbFile))
|
||||
continue;
|
||||
|
||||
UnityEngine.Debug.LogWarning($"Unity is only able to load mdb or portable-pdb symbols. {file} is using a legacy pdb format.");
|
||||
}
|
||||
}
|
||||
|
||||
public void SyncAll()
|
||||
{
|
||||
AssetDatabase.Refresh();
|
||||
_generator.Sync();
|
||||
}
|
||||
|
||||
bool IsSupportedPath(string path)
|
||||
{
|
||||
// Path is empty with "Open C# Project", as we only want to open the solution without specific files
|
||||
if (string.IsNullOrEmpty(path))
|
||||
return true;
|
||||
|
||||
// cs, uxml, uss, shader, compute, cginc, hlsl, glslinc, template are part of Unity builtin extensions
|
||||
// txt, xml, fnt, cd are -often- par of Unity user extensions
|
||||
// asdmdef is mandatory included
|
||||
if (_generator.IsSupportedFile(path))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool OpenProject(string path, int line, int column)
|
||||
{
|
||||
if (!IsSupportedPath(path))
|
||||
return false;
|
||||
|
||||
if (IsOSX)
|
||||
return OpenOSXApp(path, line, column);
|
||||
|
||||
if (IsWindows)
|
||||
return OpenWindowsApp(path, line);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool OpenWindowsApp(string path, int line)
|
||||
{
|
||||
var progpath = FileUtility
|
||||
.FindPackageAssetFullPath("COMIntegration a:packages", "COMIntegration.exe")
|
||||
.FirstOrDefault();
|
||||
|
||||
if (string.IsNullOrWhiteSpace(progpath))
|
||||
return false;
|
||||
|
||||
string absolutePath = "";
|
||||
if (!string.IsNullOrWhiteSpace(path))
|
||||
{
|
||||
absolutePath = Path.GetFullPath(path);
|
||||
}
|
||||
|
||||
// We remove all invalid chars from the solution filename, but we cannot prevent the user from using a specific path for the Unity project
|
||||
// So process the fullpath to make it compatible with VS
|
||||
var solution = GetOrGenerateSolutionFile(path);
|
||||
if (!string.IsNullOrWhiteSpace(solution))
|
||||
{
|
||||
solution = $"\"{solution}\"";
|
||||
solution = solution.Replace("^", "^^");
|
||||
}
|
||||
|
||||
var process = new Process
|
||||
{
|
||||
StartInfo = new ProcessStartInfo
|
||||
{
|
||||
FileName = progpath,
|
||||
Arguments = $"\"{CodeEditor.CurrentEditorInstallation}\" \"{absolutePath}\" {solution} {line}",
|
||||
CreateNoWindow = true,
|
||||
UseShellExecute = false,
|
||||
RedirectStandardOutput = true,
|
||||
RedirectStandardError = true,
|
||||
}
|
||||
};
|
||||
var result = process.Start();
|
||||
|
||||
while (!process.StandardOutput.EndOfStream)
|
||||
{
|
||||
var outputLine = process.StandardOutput.ReadLine();
|
||||
if (outputLine == "displayProgressBar")
|
||||
{
|
||||
EditorUtility.DisplayProgressBar("Opening Visual Studio", "Starting up Visual Studio, this might take some time.", .5f);
|
||||
}
|
||||
|
||||
if (outputLine == "clearprogressbar")
|
||||
{
|
||||
EditorUtility.ClearProgressBar();
|
||||
}
|
||||
}
|
||||
|
||||
var errorOutput = process.StandardError.ReadToEnd();
|
||||
if (!string.IsNullOrEmpty(errorOutput))
|
||||
{
|
||||
Console.WriteLine("Error: \n" + errorOutput);
|
||||
}
|
||||
|
||||
process.WaitForExit();
|
||||
return result;
|
||||
}
|
||||
|
||||
[DllImport("AppleEventIntegration")]
|
||||
static extern bool OpenVisualStudio(string appPath, string solutionPath, string filePath, int line);
|
||||
|
||||
bool OpenOSXApp(string path, int line, int column)
|
||||
{
|
||||
string absolutePath = "";
|
||||
if (!string.IsNullOrWhiteSpace(path))
|
||||
{
|
||||
absolutePath = Path.GetFullPath(path);
|
||||
}
|
||||
|
||||
string solution = GetOrGenerateSolutionFile(path);
|
||||
return OpenVisualStudio(CodeEditor.CurrentEditorInstallation, solution, absolutePath, line);
|
||||
}
|
||||
|
||||
private string GetOrGenerateSolutionFile(string path)
|
||||
{
|
||||
var solution = GetSolutionFile(path);
|
||||
if (solution == "")
|
||||
{
|
||||
_generator.Sync();
|
||||
solution = GetSolutionFile(path);
|
||||
}
|
||||
|
||||
return solution;
|
||||
}
|
||||
|
||||
string GetSolutionFile(string path)
|
||||
{
|
||||
var solutionFile = _generator.SolutionFile();
|
||||
if (File.Exists(solutionFile))
|
||||
{
|
||||
return solutionFile;
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0173aff8c07e06b42af07ebdd7f08032
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
fileFormatVersion: 2
|
||||
guid: 0173aff8c07e06b42af07ebdd7f08032
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
126
Editor/VisualStudioInstallation.cs
Normal file
126
Editor/VisualStudioInstallation.cs
Normal file
@@ -0,0 +1,126 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
using System;
|
||||
using System.IO;
|
||||
using Microsoft.Win32;
|
||||
using Unity.CodeEditor;
|
||||
using IOPath = System.IO.Path;
|
||||
|
||||
namespace Microsoft.Unity.VisualStudio.Editor
|
||||
{
|
||||
internal class VisualStudioInstallation
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public string Path { get; set; }
|
||||
public Version Version { get; set; }
|
||||
public bool IsPrerelease { get; set; }
|
||||
|
||||
public bool SupportsAnalyzers
|
||||
{
|
||||
get
|
||||
{
|
||||
if (VisualStudioEditor.IsWindows)
|
||||
return Version >= new Version(16, 3);
|
||||
|
||||
if (VisualStudioEditor.IsOSX)
|
||||
return Version >= new Version(8, 3);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static string ReadRegistry(RegistryKey hive, string keyName, string valueName)
|
||||
{
|
||||
try
|
||||
{
|
||||
var unitykey = hive.OpenSubKey(keyName);
|
||||
|
||||
var result = (string)unitykey?.GetValue(valueName);
|
||||
return result;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// We only use this to find analyzers, we do not need to load this assembly anymore
|
||||
private string GetBridgeLocation()
|
||||
{
|
||||
if (VisualStudioEditor.IsWindows)
|
||||
{
|
||||
// Registry, using legacy bridge location
|
||||
var keyName = $"Software\\Microsoft\\Microsoft Visual Studio {Version.Major}.0 Tools for Unity";
|
||||
const string valueName = "UnityExtensionPath";
|
||||
|
||||
var bridge = ReadRegistry(Registry.CurrentUser, keyName, valueName);
|
||||
if (string.IsNullOrEmpty(bridge))
|
||||
bridge = ReadRegistry(Registry.LocalMachine, keyName, valueName);
|
||||
|
||||
return bridge;
|
||||
}
|
||||
|
||||
if (VisualStudioEditor.IsOSX)
|
||||
{
|
||||
// Environment, useful when developing UnityVS for Mac
|
||||
var bridge = Environment.GetEnvironmentVariable("VSTUM_BRIDGE");
|
||||
if (!string.IsNullOrEmpty(bridge) && File.Exists(bridge))
|
||||
return bridge;
|
||||
|
||||
const string addinBridge = "Editor/SyntaxTree.VisualStudio.Unity.Bridge.dll";
|
||||
const string addinName = "MonoDevelop.Unity";
|
||||
|
||||
// user addins repository
|
||||
var localAddins = IOPath.Combine(
|
||||
Environment.GetFolderPath(Environment.SpecialFolder.Personal),
|
||||
$"Library/Application Support/VisualStudio/${Version.Major}.0" + "/LocalInstall/Addins");
|
||||
|
||||
// In the user addins repository, the addins are suffixed by their versions, like `MonoDevelop.Unity.1.0`
|
||||
// When installing another local user addin, MD will remove files inside the folder
|
||||
// So we browse all VSTUM addins, and return the one with a bridge, which is the one MD will load
|
||||
if (Directory.Exists(localAddins))
|
||||
{
|
||||
foreach (var folder in Directory.GetDirectories(localAddins, addinName + "*", SearchOption.TopDirectoryOnly))
|
||||
{
|
||||
bridge = IOPath.Combine(folder, addinBridge);
|
||||
if (File.Exists(bridge))
|
||||
return bridge;
|
||||
}
|
||||
}
|
||||
|
||||
// Check in Visual Studio.app/
|
||||
// In that case the name of the addin is used
|
||||
bridge = IOPath.Combine(Path, $"Contents/Resources/lib/monodevelop/AddIns/{addinName}/{addinBridge}");
|
||||
if (File.Exists(bridge))
|
||||
return bridge;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public string[] GetAnalyzers()
|
||||
{
|
||||
var bridge = GetBridgeLocation();
|
||||
|
||||
if (!string.IsNullOrEmpty(bridge))
|
||||
{
|
||||
var baseLocation = IOPath.Combine(IOPath.GetDirectoryName(bridge), "..");
|
||||
var analyzerLocation = IOPath.GetFullPath(IOPath.Combine(baseLocation, "Analyzers"));
|
||||
|
||||
if (Directory.Exists(analyzerLocation))
|
||||
return Directory.GetFiles(analyzerLocation, "*Analyzers.dll", SearchOption.AllDirectories);
|
||||
}
|
||||
|
||||
// Local assets
|
||||
// return FileUtility.FindPackageAssetFullPath("Analyzers a:packages", ".Analyzers.dll");
|
||||
return Array.Empty<string>();
|
||||
}
|
||||
|
||||
public CodeEditor.Installation ToCodeEditorInstallation()
|
||||
{
|
||||
return new CodeEditor.Installation() { Name = Name, Path = Path };
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Editor/VisualStudioInstallation.cs.meta
Normal file
11
Editor/VisualStudioInstallation.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bb86eea06f54fb24caa7046a8a764945
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
174
Editor/VisualStudioIntegration.cs
Normal file
174
Editor/VisualStudioIntegration.cs
Normal file
@@ -0,0 +1,174 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using Microsoft.Unity.VisualStudio.Editor.Messaging;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using MessageType = Microsoft.Unity.VisualStudio.Editor.Messaging.MessageType;
|
||||
|
||||
namespace Microsoft.Unity.VisualStudio.Editor
|
||||
{
|
||||
[InitializeOnLoad]
|
||||
internal class VisualStudioIntegration
|
||||
{
|
||||
private static Messager _messager;
|
||||
|
||||
private static readonly Queue<Message> Incoming = new Queue<Message>();
|
||||
private static readonly object IncomingLock = new object();
|
||||
|
||||
public static Application.LogCallback LogCallback = delegate { };
|
||||
|
||||
static VisualStudioIntegration()
|
||||
{
|
||||
RunOnceOnUpdate(() =>
|
||||
{
|
||||
_messager = Messager.BindTo(MessagingPort());
|
||||
_messager.ReceiveMessage += ReceiveMessage;
|
||||
|
||||
RunOnShutdown(Shutdown);
|
||||
});
|
||||
|
||||
EditorApplication.update += OnUpdate;
|
||||
}
|
||||
|
||||
private static void RunOnceOnUpdate(Action action)
|
||||
{
|
||||
var callback = null as EditorApplication.CallbackFunction;
|
||||
|
||||
callback = () =>
|
||||
{
|
||||
EditorApplication.update -= callback;
|
||||
action();
|
||||
};
|
||||
|
||||
EditorApplication.update += callback;
|
||||
}
|
||||
|
||||
private static void RunOnShutdown(Action action)
|
||||
{
|
||||
// Mono on OSX has all kinds of quirks on AppDomain shutdown
|
||||
if (!VisualStudioEditor.IsWindows)
|
||||
return;
|
||||
|
||||
AppDomain.CurrentDomain.DomainUnload += (_, __) => action();
|
||||
}
|
||||
|
||||
private static int DebuggingPort()
|
||||
{
|
||||
return 56000 + (System.Diagnostics.Process.GetCurrentProcess().Id % 1000);
|
||||
}
|
||||
|
||||
private static int MessagingPort()
|
||||
{
|
||||
return DebuggingPort() + 2;
|
||||
}
|
||||
|
||||
private static void ReceiveMessage(object sender, MessageEventArgs args)
|
||||
{
|
||||
OnMessage(args.Message);
|
||||
}
|
||||
|
||||
private static void OnUpdate()
|
||||
{
|
||||
lock (IncomingLock)
|
||||
{
|
||||
while (Incoming.Count > 0)
|
||||
{
|
||||
ProcessIncoming(Incoming.Dequeue());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void AddMessage(Message message)
|
||||
{
|
||||
lock (IncomingLock)
|
||||
{
|
||||
Incoming.Enqueue(message);
|
||||
}
|
||||
}
|
||||
|
||||
private static void ProcessIncoming(Message message)
|
||||
{
|
||||
switch (message.Type)
|
||||
{
|
||||
case MessageType.Ping:
|
||||
Answer(message, MessageType.Pong);
|
||||
break;
|
||||
case MessageType.Play:
|
||||
Shutdown();
|
||||
EditorApplication.isPlaying = true;
|
||||
break;
|
||||
case MessageType.Stop:
|
||||
EditorApplication.isPlaying = false;
|
||||
break;
|
||||
case MessageType.Pause:
|
||||
EditorApplication.isPaused = true;
|
||||
break;
|
||||
case MessageType.Unpause:
|
||||
EditorApplication.isPaused = false;
|
||||
break;
|
||||
case MessageType.Build:
|
||||
// Not used anymore
|
||||
break;
|
||||
case MessageType.Refresh:
|
||||
Refresh();
|
||||
break;
|
||||
case MessageType.Version:
|
||||
Answer(message, MessageType.Version, PackageVersion());
|
||||
break;
|
||||
case MessageType.UpdatePackage:
|
||||
// Not used anymore
|
||||
break;
|
||||
case MessageType.ProjectPath:
|
||||
Answer(message, MessageType.ProjectPath, Path.GetFullPath(Path.Combine(Application.dataPath, "..")));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private static string PackageVersion()
|
||||
{
|
||||
var package = UnityEditor.PackageManager.PackageInfo.FindForAssembly(typeof(VisualStudioIntegration).Assembly);
|
||||
return package.version;
|
||||
}
|
||||
|
||||
private static void Refresh()
|
||||
{
|
||||
RunOnceOnUpdate(AssetDatabase.Refresh);
|
||||
}
|
||||
|
||||
private static void OnMessage(Message message)
|
||||
{
|
||||
AddMessage(message);
|
||||
}
|
||||
|
||||
private static void Answer(Message message, MessageType answerType, string answerValue = "")
|
||||
{
|
||||
var targetEndPoint = message.Origin;
|
||||
|
||||
Answer(
|
||||
targetEndPoint,
|
||||
answerType,
|
||||
answerValue);
|
||||
}
|
||||
|
||||
private static void Answer(IPEndPoint targetEndPoint, MessageType answerType, string answerValue)
|
||||
{
|
||||
_messager?.SendMessage(targetEndPoint, answerType, answerValue);
|
||||
}
|
||||
|
||||
private static void Shutdown()
|
||||
{
|
||||
if (_messager == null)
|
||||
return;
|
||||
|
||||
_messager.ReceiveMessage -= ReceiveMessage;
|
||||
_messager.Dispose();
|
||||
_messager = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Editor/VisualStudioIntegration.cs.meta
Normal file
11
Editor/VisualStudioIntegration.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 48fcd6ebd5ce8fd4cbe931895233677d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,9 +1,9 @@
|
||||
{
|
||||
"name": "Unity.VisualStudio.Editor",
|
||||
"references": [],
|
||||
"optionalUnityReferences": [],
|
||||
"includePlatforms": [
|
||||
"Editor"
|
||||
],
|
||||
"excludePlatforms": []
|
||||
}
|
||||
{
|
||||
"name": "Unity.VisualStudio.Editor",
|
||||
"references": [],
|
||||
"optionalUnityReferences": [],
|
||||
"includePlatforms": [
|
||||
"Editor"
|
||||
],
|
||||
"excludePlatforms": []
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b93f844d45cfcc44fa2b0eed5c9ec6bb
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
fileFormatVersion: 2
|
||||
guid: b93f844d45cfcc44fa2b0eed5c9ec6bb
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
||||
Reference in New Issue
Block a user