VSCode.cs 49 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372
  1. /*
  2. * Unity VSCode Support
  3. *
  4. * Seamless support for Microsoft Visual Studio Code in Unity
  5. *
  6. * Version:
  7. * 2.7
  8. *
  9. * Authors:
  10. * Matthew Davey <matthew.davey@dotbunny.com>
  11. */
  12. namespace dotBunny.Unity
  13. {
  14. using System;
  15. using System.IO;
  16. using System.Text.RegularExpressions;
  17. using UnityEditor;
  18. using UnityEngine;
  19. [InitializeOnLoad]
  20. public static class VSCode
  21. {
  22. /// <summary>
  23. /// Current Version Number
  24. /// </summary>
  25. public const float Version = 2.7f;
  26. /// <summary>
  27. /// Current Version Code
  28. /// </summary>
  29. public const string VersionCode = "-RELEASE";
  30. /// <summary>
  31. /// Additional File Extensions
  32. /// </summary>
  33. public const string FileExtensions = ".ts, .bjs, .javascript, .json, .html";
  34. /// <summary>
  35. /// Download URL for Unity Debbuger
  36. /// </summary>
  37. public const string UnityDebuggerURL = "https://unity.gallery.vsassets.io/_apis/public/gallery/publisher/unity/extension/unity-debug/latest/assetbyname/Microsoft.VisualStudio.Services.VSIXPackage";
  38. #region Properties
  39. /// <summary>
  40. /// Path to VSCode executable
  41. public static string CodePath
  42. {
  43. get
  44. {
  45. string current = EditorPrefs.GetString("VSCode_CodePath", "");
  46. if(current == "" || !VSCodeExists(current))
  47. {
  48. //Value not set, set to "" or current path is invalid, try to autodetect it
  49. //If autodetect fails, a error will be printed and the default value set
  50. EditorPrefs.SetString("VSCode_CodePath", AutodetectCodePath());
  51. //If its not installed or the install folder isn't a "normal" one,
  52. //AutodetectCodePath will print a error message to the Unity Console
  53. }
  54. return EditorPrefs.GetString("VSCode_CodePath", current);
  55. }
  56. set
  57. {
  58. EditorPrefs.SetString("VSCode_CodePath", value);
  59. }
  60. }
  61. /// <summary>
  62. /// Get Program Files Path
  63. /// </summary>
  64. /// <returns>The platforms "Program Files" path.</returns>
  65. static string ProgramFilesx86()
  66. {
  67. if( 8 == IntPtr.Size
  68. || (!String.IsNullOrEmpty(Environment.GetEnvironmentVariable("PROCESSOR_ARCHITEW6432"))))
  69. {
  70. return Environment.GetEnvironmentVariable("ProgramFiles(x86)");
  71. }
  72. return Environment.GetEnvironmentVariable("ProgramFiles");
  73. }
  74. /// <summary>
  75. /// Should debug information be displayed in the Unity terminal?
  76. /// </summary>
  77. public static bool Debug
  78. {
  79. get
  80. {
  81. return EditorPrefs.GetBool("VSCode_Debug", false);
  82. }
  83. set
  84. {
  85. EditorPrefs.SetBool("VSCode_Debug", value);
  86. }
  87. }
  88. /// <summary>
  89. /// Is the Visual Studio Code Integration Enabled?
  90. /// </summary>
  91. /// <remarks>
  92. /// We do not want to automatically turn it on, for in larger projects not everyone is using VSCode
  93. /// </remarks>
  94. public static bool Enabled
  95. {
  96. get
  97. {
  98. return EditorPrefs.GetBool("VSCode_Enabled", false);
  99. }
  100. set
  101. {
  102. // When turning the plugin on, we should remove all the previous project files
  103. if (!Enabled && value)
  104. {
  105. ClearProjectFiles();
  106. }
  107. EditorPrefs.SetBool("VSCode_Enabled", value);
  108. }
  109. }
  110. public static bool UseUnityDebugger
  111. {
  112. get
  113. {
  114. return EditorPrefs.GetBool("VSCode_UseUnityDebugger", false);
  115. }
  116. set
  117. {
  118. if ( value != UseUnityDebugger ) {
  119. // Set value
  120. EditorPrefs.SetBool("VSCode_UseUnityDebugger", value);
  121. // Do not write the launch JSON file because the debugger uses its own
  122. if ( value ) {
  123. WriteLaunchFile = false;
  124. }
  125. // Update launch file
  126. UpdateLaunchFile();
  127. }
  128. }
  129. }
  130. /// <summary>
  131. /// When opening a project in Unity, should it automatically open in VS Code.
  132. /// </summary>
  133. public static bool AutoOpenEnabled
  134. {
  135. get
  136. {
  137. return EditorPrefs.GetBool("VSCode_AutoOpenEnabled", false);
  138. }
  139. set
  140. {
  141. EditorPrefs.SetBool("VSCode_AutoOpenEnabled", value);
  142. }
  143. }
  144. /// <summary>
  145. /// Should the launch.json file be written?
  146. /// </summary>
  147. /// <remarks>
  148. /// Useful to disable if someone has their own custom one rigged up
  149. /// </remarks>
  150. public static bool WriteLaunchFile
  151. {
  152. get
  153. {
  154. return EditorPrefs.GetBool("VSCode_WriteLaunchFile", true);
  155. }
  156. set
  157. {
  158. EditorPrefs.SetBool("VSCode_WriteLaunchFile", value);
  159. }
  160. }
  161. /// <summary>
  162. /// Should the plugin automatically update itself.
  163. /// </summary>
  164. static bool AutomaticUpdates
  165. {
  166. get
  167. {
  168. return EditorPrefs.GetBool("VSCode_AutomaticUpdates", false);
  169. }
  170. set
  171. {
  172. EditorPrefs.SetBool("VSCode_AutomaticUpdates", value);
  173. }
  174. }
  175. static float GitHubVersion
  176. {
  177. get
  178. {
  179. return EditorPrefs.GetFloat("VSCode_GitHubVersion", Version);
  180. }
  181. set
  182. {
  183. EditorPrefs.SetFloat("VSCode_GitHubVersion", value);
  184. }
  185. }
  186. /// <summary>
  187. /// When was the last time that the plugin was updated?
  188. /// </summary>
  189. static DateTime LastUpdate
  190. {
  191. get
  192. {
  193. // Feature creation date.
  194. DateTime lastTime = new DateTime(2015, 10, 8);
  195. if (EditorPrefs.HasKey("VSCode_LastUpdate"))
  196. {
  197. DateTime.TryParse(EditorPrefs.GetString("VSCode_LastUpdate"), out lastTime);
  198. }
  199. return lastTime;
  200. }
  201. set
  202. {
  203. EditorPrefs.SetString("VSCode_LastUpdate", value.ToString());
  204. }
  205. }
  206. /// <summary>
  207. /// Quick reference to the VSCode launch settings file
  208. /// </summary>
  209. static string LaunchPath
  210. {
  211. get
  212. {
  213. return SettingsFolder + System.IO.Path.DirectorySeparatorChar + "launch.json";
  214. }
  215. }
  216. /// <summary>
  217. /// The full path to the project
  218. /// </summary>
  219. static string ProjectPath
  220. {
  221. get
  222. {
  223. return System.IO.Path.GetDirectoryName(UnityEngine.Application.dataPath);
  224. }
  225. }
  226. /// <summary>
  227. /// Should the script editor be reverted when quiting Unity.
  228. /// </summary>
  229. /// <remarks>
  230. /// Useful for environments where you do not use VSCode for everything.
  231. /// </remarks>
  232. static bool RevertExternalScriptEditorOnExit
  233. {
  234. get
  235. {
  236. return EditorPrefs.GetBool("VSCode_RevertScriptEditorOnExit", true);
  237. }
  238. set
  239. {
  240. EditorPrefs.SetBool("VSCode_RevertScriptEditorOnExit", value);
  241. }
  242. }
  243. /// <summary>
  244. /// Quick reference to the VSCode settings folder
  245. /// </summary>
  246. static string SettingsFolder
  247. {
  248. get
  249. {
  250. return ProjectPath + System.IO.Path.DirectorySeparatorChar + ".vscode";
  251. }
  252. }
  253. static string SettingsPath
  254. {
  255. get
  256. {
  257. return SettingsFolder + System.IO.Path.DirectorySeparatorChar + "settings.json";
  258. }
  259. }
  260. static int UpdateTime
  261. {
  262. get
  263. {
  264. return EditorPrefs.GetInt("VSCode_UpdateTime", 7);
  265. }
  266. set
  267. {
  268. EditorPrefs.SetInt("VSCode_UpdateTime", value);
  269. }
  270. }
  271. #endregion
  272. /// <summary>
  273. /// Integration Constructor
  274. /// </summary>
  275. static VSCode()
  276. {
  277. if (Enabled)
  278. {
  279. UpdateUnityPreferences(true);
  280. UpdateLaunchFile();
  281. // Add Update Check
  282. DateTime targetDate = LastUpdate.AddDays(UpdateTime);
  283. if (DateTime.Now >= targetDate && AutomaticUpdates)
  284. {
  285. CheckForUpdate();
  286. }
  287. // Open VS Code automatically when project is loaded
  288. if (AutoOpenEnabled)
  289. {
  290. CheckForAutoOpen();
  291. }
  292. }
  293. // Event for when script is reloaded
  294. System.AppDomain.CurrentDomain.DomainUnload += System_AppDomain_CurrentDomain_DomainUnload;
  295. }
  296. static void System_AppDomain_CurrentDomain_DomainUnload(object sender, System.EventArgs e)
  297. {
  298. if (Enabled && RevertExternalScriptEditorOnExit)
  299. {
  300. UpdateUnityPreferences(false);
  301. }
  302. }
  303. #region Public Members
  304. /// <summary>
  305. /// Force Unity To Write Project File
  306. /// </summary>
  307. /// <remarks>
  308. /// Reflection!
  309. /// </remarks>
  310. public static void SyncSolution()
  311. {
  312. System.Type T = System.Type.GetType("UnityEditor.SyncVS,UnityEditor");
  313. System.Reflection.MethodInfo SyncSolution = T.GetMethod("SyncSolution", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static);
  314. SyncSolution.Invoke(null, null);
  315. }
  316. /// <summary>
  317. /// Update the solution files so that they work with VS Code
  318. /// </summary>
  319. public static void UpdateSolution()
  320. {
  321. // No need to process if we are not enabled
  322. if (!VSCode.Enabled)
  323. {
  324. return;
  325. }
  326. if (VSCode.Debug)
  327. {
  328. UnityEngine.Debug.Log("[VSCode] Updating Solution & Project Files");
  329. }
  330. var currentDirectory = Directory.GetCurrentDirectory();
  331. var solutionFiles = Directory.GetFiles(currentDirectory, "*.sln");
  332. var projectFiles = Directory.GetFiles(currentDirectory, "*.csproj");
  333. foreach (var filePath in solutionFiles)
  334. {
  335. string content = File.ReadAllText(filePath);
  336. content = ScrubSolutionContent(content);
  337. File.WriteAllText(filePath, content);
  338. ScrubFile(filePath);
  339. }
  340. foreach (var filePath in projectFiles)
  341. {
  342. string content = File.ReadAllText(filePath);
  343. content = ScrubProjectContent(content);
  344. File.WriteAllText(filePath, content);
  345. ScrubFile(filePath);
  346. }
  347. }
  348. #endregion
  349. #region Private Members
  350. /// <summary>
  351. /// Try to find automatically the installation of VSCode
  352. /// </summary>
  353. static string AutodetectCodePath()
  354. {
  355. string[] possiblePaths =
  356. #if UNITY_EDITOR_OSX
  357. {
  358. "/Applications/Visual Studio Code.app",
  359. "/Applications/Visual Studio Code - Insiders.app"
  360. };
  361. #elif UNITY_EDITOR_WIN
  362. {
  363. ProgramFilesx86() + Path.DirectorySeparatorChar + "Microsoft VS Code"
  364. + Path.DirectorySeparatorChar + "bin" + Path.DirectorySeparatorChar + "code.cmd",
  365. ProgramFilesx86() + Path.DirectorySeparatorChar + "Microsoft VS Code Insiders"
  366. + Path.DirectorySeparatorChar + "bin" + Path.DirectorySeparatorChar + "code-insiders.cmd"
  367. };
  368. #else
  369. {
  370. "/usr/bin/code",
  371. "/bin/code",
  372. "/usr/local/bin/code"
  373. };
  374. #endif
  375. for(int i = 0; i < possiblePaths.Length; i++)
  376. {
  377. if(VSCodeExists(possiblePaths[i]))
  378. {
  379. return possiblePaths[i];
  380. }
  381. }
  382. PrintNotFound(possiblePaths[0]);
  383. return possiblePaths[0]; //returns the default one, printing a warning message 'executable not found'
  384. }
  385. /// <summary>
  386. /// Call VSCode with arguments
  387. /// </summary>
  388. static void CallVSCode(string args)
  389. {
  390. System.Diagnostics.Process proc = new System.Diagnostics.Process();
  391. if(!VSCodeExists(CodePath))
  392. {
  393. PrintNotFound(CodePath);
  394. return;
  395. }
  396. #if UNITY_EDITOR_OSX
  397. proc.StartInfo.FileName = "open";
  398. // Check the path to see if there is "Insiders"
  399. if (CodePath.Contains("Insiders"))
  400. {
  401. proc.StartInfo.Arguments = " -n -b \"com.microsoft.VSCodeInsiders\" --args " + args.Replace(@"\", @"\\");
  402. }
  403. else
  404. {
  405. proc.StartInfo.Arguments = " -n -b \"com.microsoft.VSCode\" --args " + args.Replace(@"\", @"\\");
  406. }
  407. proc.StartInfo.UseShellExecute = false;
  408. #elif UNITY_EDITOR_WIN
  409. proc.StartInfo.FileName = CodePath;
  410. proc.StartInfo.Arguments = args;
  411. proc.StartInfo.UseShellExecute = false;
  412. #else
  413. proc.StartInfo.FileName = CodePath;
  414. proc.StartInfo.Arguments = args.Replace(@"\", @"\\");
  415. proc.StartInfo.UseShellExecute = false;
  416. #endif
  417. proc.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
  418. proc.StartInfo.CreateNoWindow = true;
  419. proc.StartInfo.RedirectStandardOutput = true;
  420. proc.Start();
  421. }
  422. /// <summary>
  423. /// Check for Updates with GitHub
  424. /// </summary>
  425. static void CheckForUpdate()
  426. {
  427. var fileContent = string.Empty;
  428. EditorUtility.DisplayProgressBar("VSCode", "Checking for updates ...", 0.5f);
  429. // Because were not a runtime framework, lets just use the simplest way of doing this
  430. try
  431. {
  432. using (var webClient = new System.Net.WebClient())
  433. {
  434. fileContent = webClient.DownloadString("https://raw.githubusercontent.com/dotBunny/VSCode/master/Plugins/Editor/VSCode.cs");
  435. }
  436. }
  437. catch (Exception e)
  438. {
  439. if (Debug)
  440. {
  441. UnityEngine.Debug.Log("[VSCode] " + e.Message);
  442. }
  443. // Don't go any further if there is an error
  444. return;
  445. }
  446. finally
  447. {
  448. EditorUtility.ClearProgressBar();
  449. }
  450. // Set the last update time
  451. LastUpdate = DateTime.Now;
  452. // Fix for oddity in downlo
  453. if (fileContent.Substring(0, 2) != "/*")
  454. {
  455. int startPosition = fileContent.IndexOf("/*", StringComparison.CurrentCultureIgnoreCase);
  456. // Jump over junk characters
  457. fileContent = fileContent.Substring(startPosition);
  458. }
  459. string[] fileExploded = fileContent.Split('\n');
  460. if (fileExploded.Length > 7)
  461. {
  462. float github = Version;
  463. if (float.TryParse(fileExploded[6].Replace("*", "").Trim(), out github))
  464. {
  465. GitHubVersion = github;
  466. }
  467. if (github > Version)
  468. {
  469. var GUIDs = AssetDatabase.FindAssets("t:Script VSCode");
  470. var path = Application.dataPath.Substring(0, Application.dataPath.Length - "/Assets".Length) + System.IO.Path.DirectorySeparatorChar +
  471. AssetDatabase.GUIDToAssetPath(GUIDs[0]).Replace('/', System.IO.Path.DirectorySeparatorChar);
  472. if (EditorUtility.DisplayDialog("VSCode Update", "A newer version of the VSCode plugin is available, would you like to update your version?", "Yes", "No"))
  473. {
  474. // Always make sure the file is writable
  475. System.IO.FileInfo fileInfo = new System.IO.FileInfo(path);
  476. fileInfo.IsReadOnly = false;
  477. // Write update file
  478. File.WriteAllText(path, fileContent);
  479. // Force update on text file
  480. AssetDatabase.ImportAsset(AssetDatabase.GUIDToAssetPath(GUIDs[0]), ImportAssetOptions.ForceUpdate);
  481. }
  482. }
  483. }
  484. }
  485. /// <summary>
  486. /// Checks whether it should auto-open VSCode
  487. /// </summary>
  488. /// <remarks>
  489. /// VSCode() gets called on Launch and Run, through IntializeOnLoad
  490. /// https://docs.unity3d.com/ScriptReference/InitializeOnLoadAttribute.html
  491. /// To make sure it only opens VSCode when Unity (re)launches (i.e. opens a project),
  492. /// we compare the launch time, which we calculate using EditorApplication.timeSinceStartup.
  493. /// </remarks>
  494. static void CheckForAutoOpen()
  495. {
  496. double timeInSeconds = (DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds;
  497. int unityLaunchTimeInSeconds = (int)(timeInSeconds - EditorApplication.timeSinceStartup);
  498. int prevUnityLaunchTime = EditorPrefs.GetInt("VSCode_UnityLaunchTime", 0);
  499. // If launch time has changed, then Unity was re-opened
  500. if (unityLaunchTimeInSeconds > prevUnityLaunchTime) {
  501. // Launch VSCode
  502. VSCode.MenuOpenProject();
  503. // Save new launch time
  504. EditorPrefs.SetInt("VSCode_UnityLaunchTime", unityLaunchTimeInSeconds);
  505. }
  506. }
  507. /// <summary>
  508. /// Clear out any existing project files and lingering stuff that might cause problems
  509. /// </summary>
  510. static void ClearProjectFiles()
  511. {
  512. var currentDirectory = Directory.GetCurrentDirectory();
  513. var solutionFiles = Directory.GetFiles(currentDirectory, "*.sln");
  514. var projectFiles = Directory.GetFiles(currentDirectory, "*.csproj");
  515. var unityProjectFiles = Directory.GetFiles(currentDirectory, "*.unityproj");
  516. foreach (string solutionFile in solutionFiles)
  517. {
  518. File.Delete(solutionFile);
  519. }
  520. foreach (string projectFile in projectFiles)
  521. {
  522. File.Delete(projectFile);
  523. }
  524. foreach (string unityProjectFile in unityProjectFiles)
  525. {
  526. File.Delete(unityProjectFile);
  527. }
  528. // Replace with our clean files (only in Unity 5)
  529. #if !UNITY_4_0 && !UNITY_4_1 && !UNITY_4_2 && !UNITY_4_3 && !UNITY_4_5 && !UNITY_4_6 && !UNITY_4_7
  530. SyncSolution();
  531. #endif
  532. }
  533. /// <summary>
  534. /// Force Unity Preferences Window To Read From Settings
  535. /// </summary>
  536. static void FixUnityPreferences()
  537. {
  538. // I want that window, please and thank you
  539. System.Type T = System.Type.GetType("UnityEditor.PreferencesWindow,UnityEditor");
  540. if (EditorWindow.focusedWindow == null)
  541. return;
  542. // Only run this when the editor window is visible (cause its what screwed us up)
  543. if (EditorWindow.focusedWindow.GetType() == T)
  544. {
  545. var window = EditorWindow.GetWindow(T, true, "Unity Preferences");
  546. if (window == null)
  547. {
  548. if (Debug)
  549. {
  550. UnityEngine.Debug.Log("[VSCode] No Preferences Window Found (really?)");
  551. }
  552. return;
  553. }
  554. var invokerType = window.GetType();
  555. var invokerMethod = invokerType.GetMethod("ReadPreferences",
  556. System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
  557. if (invokerMethod != null)
  558. {
  559. invokerMethod.Invoke(window, null);
  560. }
  561. else if (Debug)
  562. {
  563. UnityEngine.Debug.Log("[VSCode] No Reflection Method Found For Preferences");
  564. }
  565. }
  566. }
  567. /// <summary>
  568. /// Determine what port Unity is listening for on Windows
  569. /// </summary>
  570. static int GetDebugPort()
  571. {
  572. #if UNITY_EDITOR_WIN
  573. System.Diagnostics.Process process = new System.Diagnostics.Process();
  574. process.StartInfo.FileName = "netstat";
  575. process.StartInfo.Arguments = "-a -n -o -p TCP";
  576. process.StartInfo.UseShellExecute = false;
  577. process.StartInfo.RedirectStandardOutput = true;
  578. process.Start();
  579. string output = process.StandardOutput.ReadToEnd();
  580. string[] lines = output.Split('\n');
  581. process.WaitForExit();
  582. foreach (string line in lines)
  583. {
  584. string[] tokens = Regex.Split(line, "\\s+");
  585. if (tokens.Length > 4)
  586. {
  587. int test = -1;
  588. int.TryParse(tokens[5], out test);
  589. if (test > 1023)
  590. {
  591. try
  592. {
  593. var p = System.Diagnostics.Process.GetProcessById(test);
  594. if (p.ProcessName == "Unity")
  595. {
  596. return test;
  597. }
  598. }
  599. catch
  600. {
  601. }
  602. }
  603. }
  604. }
  605. #else
  606. System.Diagnostics.Process process = new System.Diagnostics.Process();
  607. process.StartInfo.FileName = "lsof";
  608. process.StartInfo.Arguments = "-c /^Unity$/ -i 4tcp -a";
  609. process.StartInfo.UseShellExecute = false;
  610. process.StartInfo.RedirectStandardOutput = true;
  611. process.Start();
  612. // Not thread safe (yet!)
  613. string output = process.StandardOutput.ReadToEnd();
  614. string[] lines = output.Split('\n');
  615. process.WaitForExit();
  616. foreach (string line in lines)
  617. {
  618. int port = -1;
  619. if (line.StartsWith("Unity"))
  620. {
  621. string[] portions = line.Split(new string[] { "TCP *:" }, System.StringSplitOptions.None);
  622. if (portions.Length >= 2)
  623. {
  624. Regex digitsOnly = new Regex(@"[^\d]");
  625. string cleanPort = digitsOnly.Replace(portions[1], "");
  626. if (int.TryParse(cleanPort, out port))
  627. {
  628. if (port > -1)
  629. {
  630. return port;
  631. }
  632. }
  633. }
  634. }
  635. }
  636. #endif
  637. return -1;
  638. }
  639. /// <summary>
  640. /// Manually install the original Unity Debuger
  641. /// </summary>
  642. /// <remarks>
  643. /// This should auto update to the latest.
  644. /// </remarks>
  645. static void InstallUnityDebugger()
  646. {
  647. EditorUtility.DisplayProgressBar("VSCode", "Downloading Unity Debugger ...", 0.1f);
  648. byte[] fileContent;
  649. try
  650. {
  651. using (var webClient = new System.Net.WebClient())
  652. {
  653. fileContent = webClient.DownloadData(UnityDebuggerURL);
  654. }
  655. }
  656. catch (Exception e)
  657. {
  658. if (Debug)
  659. {
  660. UnityEngine.Debug.Log("[VSCode] " + e.Message);
  661. }
  662. // Don't go any further if there is an error
  663. return;
  664. }
  665. finally
  666. {
  667. EditorUtility.ClearProgressBar();
  668. }
  669. // Do we have a file to install?
  670. if ( fileContent != null ) {
  671. string fileName = System.IO.Path.GetTempPath() + Guid.NewGuid().ToString() + ".vsix";
  672. File.WriteAllBytes(fileName, fileContent);
  673. CallVSCode(fileName);
  674. }
  675. }
  676. // HACK: This is in until Unity can figure out why MD keeps opening even though a different program is selected.
  677. [MenuItem("Assets/Open C# Project In Code", false, 1000)]
  678. static void MenuOpenProject()
  679. {
  680. // Force the project files to be sync
  681. SyncSolution();
  682. // Load Project
  683. CallVSCode("\"" + ProjectPath + "\"");
  684. }
  685. /// <summary>
  686. /// Print a error message to the Unity Console about not finding the code executable
  687. /// </summary>
  688. static void PrintNotFound(string path)
  689. {
  690. UnityEngine.Debug.LogError("[VSCode] Code executable in '" + path + "' not found. Check your" +
  691. "Visual Studio Code installation and insert the correct path in the Preferences menu.");
  692. }
  693. [MenuItem("Assets/Open C# Project In Code", true, 1000)]
  694. static bool ValidateMenuOpenProject()
  695. {
  696. return Enabled;
  697. }
  698. /// <summary>
  699. /// VS Code Integration Preferences Item
  700. /// </summary>
  701. /// <remarks>
  702. /// Contains all 3 toggles: Enable/Disable; Debug On/Off; Writing Launch File On/Off
  703. /// </remarks>
  704. [PreferenceItem("VSCode")]
  705. static void VSCodePreferencesItem()
  706. {
  707. if (EditorApplication.isCompiling)
  708. {
  709. EditorGUILayout.HelpBox("Please wait for Unity to finish compiling. \nIf the window doesn't refresh, simply click on the window or move it around to cause a repaint to happen.", MessageType.Warning);
  710. return;
  711. }
  712. EditorGUILayout.BeginVertical();
  713. var developmentInfo = "Support development of this plugin, follow @reapazor and @dotbunny on Twitter.";
  714. var versionInfo = string.Format("{0:0.00}", Version) + VersionCode + ", GitHub version @ " + string.Format("{0:0.00}", GitHubVersion);
  715. EditorGUILayout.HelpBox(developmentInfo + " --- [ " + versionInfo + " ]", MessageType.None);
  716. EditorGUI.BeginChangeCheck();
  717. // Need the VS Code executable
  718. EditorGUILayout.BeginHorizontal();
  719. EditorGUILayout.LabelField("VS Code Path", GUILayout.Width(75));
  720. #if UNITY_5_3_OR_NEWER
  721. CodePath = EditorGUILayout.DelayedTextField(CodePath, GUILayout.ExpandWidth(true));
  722. #else
  723. CodePath = EditorGUILayout.TextField(CodePath, GUILayout.ExpandWidth(true));
  724. #endif
  725. GUI.SetNextControlName("PathSetButton");
  726. if(GUILayout.Button("...", GUILayout.Height(14), GUILayout.Width(20)))
  727. {
  728. GUI.FocusControl("PathSetButton");
  729. string path = EditorUtility.OpenFilePanel( "Visual Studio Code Executable", "", "" );
  730. if( path.Length != 0 && File.Exists(path) || Directory.Exists(path))
  731. {
  732. CodePath = path;
  733. }
  734. }
  735. EditorGUILayout.EndHorizontal();
  736. EditorGUILayout.Space();
  737. Enabled = EditorGUILayout.Toggle(new GUIContent("Enable Integration", "Should the integration work its magic for you?"), Enabled);
  738. UseUnityDebugger = EditorGUILayout.Toggle(new GUIContent("Use Unity Debugger", "Should the integration integrate with Unity's VSCode Extension (must be installed)."), UseUnityDebugger);
  739. AutoOpenEnabled = EditorGUILayout.Toggle(new GUIContent("Enable Auto Open", "When opening a project in Unity, should it automatically open in VS Code?"), AutoOpenEnabled);
  740. EditorGUILayout.Space();
  741. RevertExternalScriptEditorOnExit = EditorGUILayout.Toggle(new GUIContent("Revert Script Editor On Unload", "Should the external script editor setting be reverted to its previous setting on project unload? This is useful if you do not use Code with all your projects."),RevertExternalScriptEditorOnExit);
  742. Debug = EditorGUILayout.Toggle(new GUIContent("Output Messages To Console", "Should informational messages be sent to Unity's Console?"), Debug);
  743. WriteLaunchFile = EditorGUILayout.Toggle(new GUIContent("Always Write Launch File", "Always write the launch.json settings when entering play mode?"), WriteLaunchFile);
  744. EditorGUILayout.Space();
  745. AutomaticUpdates = EditorGUILayout.Toggle(new GUIContent("Automatic Updates", "Should the plugin automatically update itself?"), AutomaticUpdates);
  746. UpdateTime = EditorGUILayout.IntSlider(new GUIContent("Update Timer (Days)", "After how many days should updates be checked for?"), UpdateTime, 1, 31);
  747. EditorGUILayout.Space();
  748. EditorGUILayout.Space();
  749. if (EditorGUI.EndChangeCheck())
  750. {
  751. UpdateUnityPreferences(Enabled);
  752. // TODO: Force Unity To Reload Preferences
  753. // This seems to be a hick up / issue
  754. if (VSCode.Debug)
  755. {
  756. if (Enabled)
  757. {
  758. UnityEngine.Debug.Log("[VSCode] Integration Enabled");
  759. }
  760. else
  761. {
  762. UnityEngine.Debug.Log("[VSCode] Integration Disabled");
  763. }
  764. }
  765. }
  766. if (GUILayout.Button(new GUIContent("Force Update", "Check for updates to the plugin, right NOW!")))
  767. {
  768. CheckForUpdate();
  769. EditorGUILayout.EndVertical();
  770. return;
  771. }
  772. if (GUILayout.Button(new GUIContent("Write Workspace Settings", "Output a default set of workspace settings for VSCode to use, ignoring many different types of files.")))
  773. {
  774. WriteWorkspaceSettings();
  775. EditorGUILayout.EndVertical();
  776. return;
  777. }
  778. EditorGUILayout.Space();
  779. if (UseUnityDebugger)
  780. {
  781. EditorGUILayout.HelpBox("In order for the \"Use Unity Debuggger\" option to function above, you need to have installed the Unity Debugger Extension for Visual Studio Code.", MessageType.Warning);
  782. if (GUILayout.Button(new GUIContent("Install Unity Debugger", "Install the Unity Debugger Extension into Code")))
  783. {
  784. InstallUnityDebugger();
  785. EditorGUILayout.EndVertical();
  786. return;
  787. }
  788. }
  789. }
  790. /// <summary>
  791. /// Asset Open Callback (from Unity)
  792. /// </summary>
  793. /// <remarks>
  794. /// Called when Unity is about to open an asset.
  795. /// </remarks>
  796. [UnityEditor.Callbacks.OnOpenAssetAttribute()]
  797. static bool OnOpenedAsset(int instanceID, int line)
  798. {
  799. // bail out if we are not using VSCode
  800. if (!Enabled)
  801. {
  802. return false;
  803. }
  804. // current path without the asset folder
  805. string appPath = ProjectPath;
  806. // determine asset that has been double clicked in the project view
  807. UnityEngine.Object selected = EditorUtility.InstanceIDToObject(instanceID);
  808. // additional file extensions
  809. string selectedFilePath = AssetDatabase.GetAssetPath(selected);
  810. string selectedFileExt = Path.GetExtension(selectedFilePath);
  811. if (selectedFileExt == null) {
  812. selectedFileExt = String.Empty;
  813. }
  814. if (!String.IsNullOrEmpty(selectedFileExt)) {
  815. selectedFileExt = selectedFileExt.ToLower();
  816. }
  817. // open supported object types
  818. if (selected.GetType().ToString() == "UnityEditor.MonoScript" ||
  819. selected.GetType().ToString() == "UnityEngine.Shader" ||
  820. VSCode.FileExtensions.IndexOf(selectedFileExt, StringComparison.OrdinalIgnoreCase) >= 0)
  821. {
  822. string completeFilepath = appPath + Path.DirectorySeparatorChar + AssetDatabase.GetAssetPath(selected);
  823. string args = null;
  824. if (line == -1)
  825. {
  826. args = "\"" + ProjectPath + "\" \"" + completeFilepath + "\" -r";
  827. }
  828. else
  829. {
  830. args = "\"" + ProjectPath + "\" -g \"" + completeFilepath + ":" + line.ToString() + "\" -r";
  831. }
  832. // call 'open'
  833. CallVSCode(args);
  834. return true;
  835. }
  836. // Didnt find a code file? let Unity figure it out
  837. return false;
  838. }
  839. /// <summary>
  840. /// Executed when the Editor's playmode changes allowing for capture of required data
  841. /// </summary>
  842. static void OnPlaymodeStateChanged()
  843. {
  844. if (UnityEngine.Application.isPlaying && EditorApplication.isPlayingOrWillChangePlaymode)
  845. {
  846. UpdateLaunchFile();
  847. }
  848. }
  849. /// <summary>
  850. /// Detect when scripts are reloaded and relink playmode detection
  851. /// </summary>
  852. [UnityEditor.Callbacks.DidReloadScripts()]
  853. static void OnScriptReload()
  854. {
  855. EditorApplication.playmodeStateChanged -= OnPlaymodeStateChanged;
  856. EditorApplication.playmodeStateChanged += OnPlaymodeStateChanged;
  857. }
  858. /// <summary>
  859. /// Remove extra/erroneous lines from a file.
  860. static void ScrubFile(string path)
  861. {
  862. string[] lines = File.ReadAllLines(path);
  863. System.Collections.Generic.List<string> newLines = new System.Collections.Generic.List<string>();
  864. for (int i = 0; i < lines.Length; i++)
  865. {
  866. // Check Empty
  867. if (string.IsNullOrEmpty(lines[i].Trim()) || lines[i].Trim() == "\t" || lines[i].Trim() == "\t\t")
  868. {
  869. }
  870. else
  871. {
  872. newLines.Add(lines[i]);
  873. }
  874. }
  875. File.WriteAllLines(path, newLines.ToArray());
  876. }
  877. /// <summary>
  878. /// Remove extra/erroneous data from project file (content).
  879. /// </summary>
  880. static string ScrubProjectContent(string content)
  881. {
  882. if (content.Length == 0)
  883. return "";
  884. #if !UNITY_EDITOR_WIN
  885. // Moved to 3.5, 2.0 is legacy.
  886. if (content.IndexOf("<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>") != -1)
  887. {
  888. content = Regex.Replace(content, "<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>", "<TargetFrameworkVersion>v2.0</TargetFrameworkVersion>");
  889. }
  890. #endif
  891. string targetPath = "";// "<TargetPath>Temp" + Path.DirectorySeparatorChar + "bin" + Path.DirectorySeparatorChar + "Debug" + Path.DirectorySeparatorChar + "</TargetPath>"; //OutputPath
  892. string langVersion = "<LangVersion>default</LangVersion>";
  893. bool found = true;
  894. int location = 0;
  895. string addedOptions = "";
  896. int startLocation = -1;
  897. int endLocation = -1;
  898. int endLength = 0;
  899. while (found)
  900. {
  901. startLocation = -1;
  902. endLocation = -1;
  903. endLength = 0;
  904. addedOptions = "";
  905. startLocation = content.IndexOf("<PropertyGroup", location);
  906. if (startLocation != -1)
  907. {
  908. endLocation = content.IndexOf("</PropertyGroup>", startLocation);
  909. endLength = (endLocation - startLocation);
  910. if (endLocation == -1)
  911. {
  912. found = false;
  913. continue;
  914. }
  915. else
  916. {
  917. found = true;
  918. location = endLocation;
  919. }
  920. if (content.Substring(startLocation, endLength).IndexOf("<TargetPath>") == -1)
  921. {
  922. addedOptions += "\n\r\t" + targetPath + "\n\r";
  923. }
  924. if (content.Substring(startLocation, endLength).IndexOf("<LangVersion>") == -1)
  925. {
  926. addedOptions += "\n\r\t" + langVersion + "\n\r";
  927. }
  928. if (!string.IsNullOrEmpty(addedOptions))
  929. {
  930. content = content.Substring(0, endLocation) + addedOptions + content.Substring(endLocation);
  931. }
  932. }
  933. else
  934. {
  935. found = false;
  936. }
  937. }
  938. return content;
  939. }
  940. /// <summary>
  941. /// Remove extra/erroneous data from solution file (content).
  942. /// </summary>
  943. static string ScrubSolutionContent(string content)
  944. {
  945. // Replace Solution Version
  946. content = content.Replace(
  947. "Microsoft Visual Studio Solution File, Format Version 11.00\r\n# Visual Studio 2008\r\n",
  948. "\r\nMicrosoft Visual Studio Solution File, Format Version 12.00\r\n# Visual Studio 2012");
  949. // Remove Solution Properties (Unity Junk)
  950. int startIndex = content.IndexOf("GlobalSection(SolutionProperties) = preSolution");
  951. if (startIndex != -1)
  952. {
  953. int endIndex = content.IndexOf("EndGlobalSection", startIndex);
  954. content = content.Substring(0, startIndex) + content.Substring(endIndex + 16);
  955. }
  956. return content;
  957. }
  958. /// <summary>
  959. /// Update Visual Studio Code Launch file
  960. /// </summary>
  961. static void UpdateLaunchFile()
  962. {
  963. if (!VSCode.Enabled)
  964. {
  965. return;
  966. }
  967. else if (VSCode.UseUnityDebugger)
  968. {
  969. if (!Directory.Exists(VSCode.SettingsFolder))
  970. System.IO.Directory.CreateDirectory(VSCode.SettingsFolder);
  971. // Write out proper formatted JSON (hence no more SimpleJSON here)
  972. string fileContent = "{\n\t\"version\": \"0.2.0\",\n\t\"configurations\": [\n\t\t{\n\t\t\t\"name\": \"Unity Editor\",\n\t\t\t\"type\": \"unity\",\n\t\t\t\"request\": \"launch\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"Windows Player\",\n\t\t\t\"type\": \"unity\",\n\t\t\t\"request\": \"launch\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"OSX Player\",\n\t\t\t\"type\": \"unity\",\n\t\t\t\"request\": \"launch\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"Linux Player\",\n\t\t\t\"type\": \"unity\",\n\t\t\t\"request\": \"launch\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"iOS Player\",\n\t\t\t\"type\": \"unity\",\n\t\t\t\"request\": \"launch\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"Android Player\",\n\t\t\t\"type\": \"unity\",\n\t\t\t\"request\": \"launch\"\n\n\t\t}\n\t]\n}";
  973. File.WriteAllText(VSCode.LaunchPath, fileContent);
  974. }
  975. else if (VSCode.WriteLaunchFile)
  976. {
  977. int port = GetDebugPort();
  978. if (port > -1)
  979. {
  980. if (!Directory.Exists(VSCode.SettingsFolder))
  981. System.IO.Directory.CreateDirectory(VSCode.SettingsFolder);
  982. // Write out proper formatted JSON (hence no more SimpleJSON here)
  983. string fileContent = "{\n\t\"version\":\"0.2.0\",\n\t\"configurations\":[ \n\t\t{\n\t\t\t\"name\":\"Unity\",\n\t\t\t\"type\":\"mono\",\n\t\t\t\"request\":\"attach\",\n\t\t\t\"address\":\"localhost\",\n\t\t\t\"port\":" + port + "\n\t\t}\n\t]\n}";
  984. File.WriteAllText(VSCode.LaunchPath, fileContent);
  985. if (VSCode.Debug)
  986. {
  987. UnityEngine.Debug.Log("[VSCode] Debug Port Found (" + port + ")");
  988. }
  989. }
  990. else
  991. {
  992. if (VSCode.Debug)
  993. {
  994. UnityEngine.Debug.LogWarning("[VSCode] Unable to determine debug port.");
  995. }
  996. }
  997. }
  998. }
  999. /// <summary>
  1000. /// Update Unity Editor Preferences
  1001. /// </summary>
  1002. /// <param name="enabled">Should we turn on this party!</param>
  1003. static void UpdateUnityPreferences(bool enabled)
  1004. {
  1005. if (enabled)
  1006. {
  1007. // App
  1008. if (EditorPrefs.GetString("kScriptsDefaultApp") != CodePath)
  1009. {
  1010. EditorPrefs.SetString("VSCode_PreviousApp", EditorPrefs.GetString("kScriptsDefaultApp"));
  1011. }
  1012. EditorPrefs.SetString("kScriptsDefaultApp", CodePath);
  1013. // Arguments
  1014. if (EditorPrefs.GetString("kScriptEditorArgs") != "-r -g `$(File):$(Line)`")
  1015. {
  1016. EditorPrefs.SetString("VSCode_PreviousArgs", EditorPrefs.GetString("kScriptEditorArgs"));
  1017. }
  1018. EditorPrefs.SetString("kScriptEditorArgs", "-r -g `$(File):$(Line)`");
  1019. EditorPrefs.SetString("kScriptEditorArgs" + CodePath, "-r -g `$(File):$(Line)`");
  1020. // MonoDevelop Solution
  1021. if (EditorPrefs.GetBool("kMonoDevelopSolutionProperties", false))
  1022. {
  1023. EditorPrefs.SetBool("VSCode_PreviousMD", true);
  1024. }
  1025. EditorPrefs.SetBool("kMonoDevelopSolutionProperties", false);
  1026. // Support Unity Proj (JS)
  1027. if (EditorPrefs.GetBool("kExternalEditorSupportsUnityProj", false))
  1028. {
  1029. EditorPrefs.SetBool("VSCode_PreviousUnityProj", true);
  1030. }
  1031. EditorPrefs.SetBool("kExternalEditorSupportsUnityProj", false);
  1032. if (!EditorPrefs.GetBool("AllowAttachedDebuggingOfEditor", false))
  1033. {
  1034. EditorPrefs.SetBool("VSCode_PreviousAttach", false);
  1035. }
  1036. EditorPrefs.SetBool("AllowAttachedDebuggingOfEditor", true);
  1037. }
  1038. else
  1039. {
  1040. // Restore previous app
  1041. if (!string.IsNullOrEmpty(EditorPrefs.GetString("VSCode_PreviousApp")))
  1042. {
  1043. EditorPrefs.SetString("kScriptsDefaultApp", EditorPrefs.GetString("VSCode_PreviousApp"));
  1044. }
  1045. // Restore previous args
  1046. if (!string.IsNullOrEmpty(EditorPrefs.GetString("VSCode_PreviousArgs")))
  1047. {
  1048. EditorPrefs.SetString("kScriptEditorArgs", EditorPrefs.GetString("VSCode_PreviousArgs"));
  1049. }
  1050. // Restore MD setting
  1051. if (EditorPrefs.GetBool("VSCode_PreviousMD", false))
  1052. {
  1053. EditorPrefs.SetBool("kMonoDevelopSolutionProperties", true);
  1054. }
  1055. // Restore MD setting
  1056. if (EditorPrefs.GetBool("VSCode_PreviousUnityProj", false))
  1057. {
  1058. EditorPrefs.SetBool("kExternalEditorSupportsUnityProj", true);
  1059. }
  1060. // Always leave editor attaching on, I know, it solves the problem of needing to restart for this
  1061. // to actually work
  1062. EditorPrefs.SetBool("AllowAttachedDebuggingOfEditor", true);
  1063. }
  1064. FixUnityPreferences();
  1065. }
  1066. /// <summary>
  1067. /// Determines if the current path to the code executable is valid or not (exists)
  1068. /// </summary>
  1069. static bool VSCodeExists(string curPath)
  1070. {
  1071. #if UNITY_EDITOR_OSX
  1072. return System.IO.Directory.Exists(curPath);
  1073. #else
  1074. System.IO.FileInfo code = new System.IO.FileInfo(curPath);
  1075. return code.Exists;
  1076. #endif
  1077. }
  1078. /// <summary>
  1079. /// Write Default Workspace Settings
  1080. /// </summary>
  1081. static void WriteWorkspaceSettings()
  1082. {
  1083. if (Debug)
  1084. {
  1085. UnityEngine.Debug.Log("[VSCode] Workspace Settings Written");
  1086. }
  1087. if (!Directory.Exists(VSCode.SettingsFolder))
  1088. {
  1089. System.IO.Directory.CreateDirectory(VSCode.SettingsFolder);
  1090. }
  1091. string exclusions =
  1092. // Associations
  1093. "{\n" +
  1094. "\t\"files.associations\":\n" +
  1095. "\t{\n" +
  1096. "\t\t\"*.bjs\":\"javascript\",\n" +
  1097. "\t\t\"*.javascript\":\"javascript\"\n" +
  1098. "\t},\n" +
  1099. "\t\"files.exclude\":\n" +
  1100. "\t{\n" +
  1101. // Hidden Files
  1102. "\t\t\"**/.DS_Store\":true,\n" +
  1103. "\t\t\"**/.git\":true,\n" +
  1104. "\t\t\"**/.gitignore\":true,\n" +
  1105. "\t\t\"**/.gitattributes\":true,\n" +
  1106. "\t\t\"**/.gitmodules\":true,\n" +
  1107. "\t\t\"**/.svn\":true,\n" +
  1108. // Project Files
  1109. "\t\t\"**/*.booproj\":true,\n" +
  1110. "\t\t\"**/*.pidb\":true,\n" +
  1111. "\t\t\"**/*.suo\":true,\n" +
  1112. "\t\t\"**/*.user\":true,\n" +
  1113. "\t\t\"**/*.userprefs\":true,\n" +
  1114. "\t\t\"**/*.unityproj\":true,\n" +
  1115. "\t\t\"**/*.dll\":true,\n" +
  1116. "\t\t\"**/*.exe\":true,\n" +
  1117. // Media Files
  1118. "\t\t\"**/*.pdf\":true,\n" +
  1119. // Video
  1120. "\t\t\"**/*.mp4\":true,\n" +
  1121. // Audio
  1122. "\t\t\"**/*.mid\":true,\n" +
  1123. "\t\t\"**/*.midi\":true,\n" +
  1124. "\t\t\"**/*.wav\":true,\n" +
  1125. "\t\t\"**/*.mp3\":true,\n" +
  1126. "\t\t\"**/*.ogg\":true,\n" +
  1127. // Textures
  1128. "\t\t\"**/*.gif\":true,\n" +
  1129. "\t\t\"**/*.ico\":true,\n" +
  1130. "\t\t\"**/*.jpg\":true,\n" +
  1131. "\t\t\"**/*.jpeg\":true,\n" +
  1132. "\t\t\"**/*.png\":true,\n" +
  1133. "\t\t\"**/*.psd\":true,\n" +
  1134. "\t\t\"**/*.tga\":true,\n" +
  1135. "\t\t\"**/*.tif\":true,\n" +
  1136. "\t\t\"**/*.tiff\":true,\n" +
  1137. "\t\t\"**/*.hdr\":true,\n" +
  1138. "\t\t\"**/*.exr\":true,\n" +
  1139. // Models
  1140. "\t\t\"**/*.3ds\":true,\n" +
  1141. "\t\t\"**/*.3DS\":true,\n" +
  1142. "\t\t\"**/*.fbx\":true,\n" +
  1143. "\t\t\"**/*.FBX\":true,\n" +
  1144. "\t\t\"**/*.lxo\":true,\n" +
  1145. "\t\t\"**/*.LXO\":true,\n" +
  1146. "\t\t\"**/*.ma\":true,\n" +
  1147. "\t\t\"**/*.MA\":true,\n" +
  1148. "\t\t\"**/*.obj\":true,\n" +
  1149. "\t\t\"**/*.OBJ\":true,\n" +
  1150. // Unity File Types
  1151. "\t\t\"**/*.asset\":true,\n" +
  1152. "\t\t\"**/*.cubemap\":true,\n" +
  1153. "\t\t\"**/*.flare\":true,\n" +
  1154. "\t\t\"**/*.mat\":true,\n" +
  1155. "\t\t\"**/*.meta\":true,\n" +
  1156. "\t\t\"**/*.prefab\":true,\n" +
  1157. "\t\t\"**/*.unity\":true,\n" +
  1158. // Folders
  1159. "\t\t\"build/\":true,\n" +
  1160. "\t\t\"Build/\":true,\n" +
  1161. "\t\t\"Library/\":true,\n" +
  1162. "\t\t\"library/\":true,\n" +
  1163. "\t\t\"obj/\":true,\n" +
  1164. "\t\t\"Obj/\":true,\n" +
  1165. "\t\t\"ProjectSettings/\":true,\r" +
  1166. "\t\t\"temp/\":true,\n" +
  1167. "\t\t\"Temp/\":true\n" +
  1168. "\t}\n" +
  1169. "}";
  1170. // Dont like the replace but it fixes the issue with the JSON
  1171. File.WriteAllText(VSCode.SettingsPath, exclusions);
  1172. }
  1173. #endregion
  1174. }
  1175. /// <summary>
  1176. /// VSCode Asset AssetPostprocessor
  1177. /// <para>This will ensure any time that the project files are generated the VSCode versions will be made</para>
  1178. /// </summary>
  1179. /// <remarks>Undocumented Event</remarks>
  1180. public class VSCodeAssetPostprocessor : AssetPostprocessor
  1181. {
  1182. /// <summary>
  1183. /// On documented, project generation event callback
  1184. /// </summary>
  1185. private static void OnGeneratedCSProjectFiles()
  1186. {
  1187. // Force execution of VSCode update
  1188. VSCode.UpdateSolution();
  1189. }
  1190. }
  1191. }