diff options
Diffstat (limited to 'modules/mono/editor')
12 files changed, 410 insertions, 31 deletions
diff --git a/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/Client.cs b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/Client.cs index d069651dd3..572c541412 100644 --- a/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/Client.cs +++ b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/Client.cs @@ -19,9 +19,12 @@ namespace GodotTools.IdeMessaging          private readonly string identity;          private string MetaFilePath { get; } +        private DateTime? metaFileModifiedTime;          private GodotIdeMetadata godotIdeMetadata;          private readonly FileSystemWatcher fsWatcher; +        public string GodotEditorExecutablePath => godotIdeMetadata.EditorExecutablePath; +          private readonly IMessageHandler messageHandler;          private Peer peer; @@ -123,7 +126,7 @@ namespace GodotTools.IdeMessaging              MetaFilePath = Path.Combine(projectMetadataDir, GodotIdeMetadata.DefaultFileName);              // FileSystemWatcher requires an existing directory -            if (!File.Exists(projectMetadataDir)) +            if (!Directory.Exists(projectMetadataDir))                  Directory.CreateDirectory(projectMetadataDir);              fsWatcher = new FileSystemWatcher(projectMetadataDir, GodotIdeMetadata.DefaultFileName); @@ -142,6 +145,13 @@ namespace GodotTools.IdeMessaging                  if (!File.Exists(MetaFilePath))                      return; +                var lastWriteTime = File.GetLastWriteTime(MetaFilePath); + +                if (lastWriteTime == metaFileModifiedTime) +                    return; + +                metaFileModifiedTime = lastWriteTime; +                  var metadata = ReadMetadataFile();                  if (metadata != null && metadata != godotIdeMetadata) @@ -173,6 +183,13 @@ namespace GodotTools.IdeMessaging                  if (IsConnected || !File.Exists(MetaFilePath))                      return; +                var lastWriteTime = File.GetLastWriteTime(MetaFilePath); + +                if (lastWriteTime == metaFileModifiedTime) +                    return; + +                metaFileModifiedTime = lastWriteTime; +                  var metadata = ReadMetadataFile();                  if (metadata != null) @@ -185,7 +202,8 @@ namespace GodotTools.IdeMessaging          private GodotIdeMetadata? ReadMetadataFile()          { -            using (var reader = File.OpenText(MetaFilePath)) +            using (var fileStream = new FileStream(MetaFilePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) +            using (var reader = new StreamReader(fileStream))              {                  string portStr = reader.ReadLine(); @@ -272,6 +290,7 @@ namespace GodotTools.IdeMessaging          // ReSharper disable once UnusedMember.Global          public async void Start()          { +            fsWatcher.Created += OnMetaFileChanged;              fsWatcher.Changed += OnMetaFileChanged;              fsWatcher.Deleted += OnMetaFileDeleted;              fsWatcher.EnableRaisingEvents = true; diff --git a/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/GodotTools.IdeMessaging.csproj b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/GodotTools.IdeMessaging.csproj index 67815959a6..dad6b9ae7a 100644 --- a/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/GodotTools.IdeMessaging.csproj +++ b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/GodotTools.IdeMessaging.csproj @@ -4,7 +4,7 @@      <TargetFramework>netstandard2.0</TargetFramework>      <LangVersion>7.2</LangVersion>      <PackageId>GodotTools.IdeMessaging</PackageId> -    <Version>1.1.0</Version> +    <Version>1.1.1</Version>      <AssemblyVersion>$(Version)</AssemblyVersion>      <Authors>Godot Engine contributors</Authors>      <Company /> diff --git a/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/Peer.cs b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/Peer.cs index a4e86d6177..10d7e1898e 100644 --- a/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/Peer.cs +++ b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/Peer.cs @@ -105,49 +105,45 @@ namespace GodotTools.IdeMessaging                      try                      { -                        try +                        if (msg.Kind == MessageKind.Request)                          { -                            if (msg.Kind == MessageKind.Request) -                            { -                                var responseContent = await messageHandler.HandleRequest(this, msg.Id, msg.Content, Logger); -                                await WriteMessage(new Message(MessageKind.Response, msg.Id, responseContent)); -                            } -                            else if (msg.Kind == MessageKind.Response) -                            { -                                ResponseAwaiter responseAwaiter; +                            var responseContent = await messageHandler.HandleRequest(this, msg.Id, msg.Content, Logger); +                            await WriteMessage(new Message(MessageKind.Response, msg.Id, responseContent)); +                        } +                        else if (msg.Kind == MessageKind.Response) +                        { +                            ResponseAwaiter responseAwaiter; -                                using (await requestsSem.UseAsync()) +                            using (await requestsSem.UseAsync()) +                            { +                                if (!requestAwaiterQueues.TryGetValue(msg.Id, out var queue) || queue.Count <= 0)                                  { -                                    if (!requestAwaiterQueues.TryGetValue(msg.Id, out var queue) || queue.Count <= 0) -                                    { -                                        Logger.LogError($"Received unexpected response: {msg.Id}"); -                                        return; -                                    } - -                                    responseAwaiter = queue.Dequeue(); +                                    Logger.LogError($"Received unexpected response: {msg.Id}"); +                                    return;                                  } -                                responseAwaiter.SetResult(msg.Content); -                            } -                            else -                            { -                                throw new IndexOutOfRangeException($"Invalid message kind {msg.Kind}"); +                                responseAwaiter = queue.Dequeue();                              } + +                            responseAwaiter.SetResult(msg.Content);                          } -                        catch (Exception e) +                        else                          { -                            Logger.LogError($"Message handler for '{msg}' failed with exception", e); +                            throw new IndexOutOfRangeException($"Invalid message kind {msg.Kind}");                          }                      }                      catch (Exception e)                      { -                        Logger.LogError($"Exception thrown from message handler. Message: {msg}", e); +                        Logger.LogError($"Message handler for '{msg}' failed with exception", e);                      }                  }              }              catch (Exception e)              { -                Logger.LogError("Unhandled exception in the peer loop", e); +                if (!IsDisposed || !(e is SocketException || e.InnerException is SocketException)) +                { +                    Logger.LogError("Unhandled exception in the peer loop", e); +                }              }          } diff --git a/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/Requests/Requests.cs b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/Requests/Requests.cs index 1dd4f852e5..e93db9377b 100644 --- a/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/Requests/Requests.cs +++ b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/Requests/Requests.cs @@ -67,6 +67,19 @@ namespace GodotTools.IdeMessaging.Requests      {      } +    public sealed class StopPlayRequest : Request +    { +        public new const string Id = "StopPlay"; + +        public StopPlayRequest() : base(Id) +        { +        } +    } + +    public sealed class StopPlayResponse : Response +    { +    } +      public sealed class DebugPlayRequest : Request      {          public string DebuggerHost { get; set; } diff --git a/modules/mono/editor/GodotTools/GodotTools.OpenVisualStudio/GodotTools.OpenVisualStudio.csproj b/modules/mono/editor/GodotTools/GodotTools.OpenVisualStudio/GodotTools.OpenVisualStudio.csproj new file mode 100644 index 0000000000..5b3ed0b1b7 --- /dev/null +++ b/modules/mono/editor/GodotTools/GodotTools.OpenVisualStudio/GodotTools.OpenVisualStudio.csproj @@ -0,0 +1,12 @@ +<Project Sdk="Microsoft.NET.Sdk"> +    <PropertyGroup> +        <ProjectGuid>{EAFFF236-FA96-4A4D-BD23-0E51EF988277}</ProjectGuid> +        <OutputType>Exe</OutputType> +        <TargetFramework>net472</TargetFramework> +        <LangVersion>7.2</LangVersion> +    </PropertyGroup> +    <ItemGroup> +        <PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.0" PrivateAssets="All" /> +        <PackageReference Include="EnvDTE" Version="8.0.2" /> +    </ItemGroup> +</Project> diff --git a/modules/mono/editor/GodotTools/GodotTools.OpenVisualStudio/Program.cs b/modules/mono/editor/GodotTools/GodotTools.OpenVisualStudio/Program.cs new file mode 100644 index 0000000000..affb2a47e7 --- /dev/null +++ b/modules/mono/editor/GodotTools/GodotTools.OpenVisualStudio/Program.cs @@ -0,0 +1,270 @@ +using System; +using System.IO; +using System.Runtime.InteropServices; +using System.Runtime.InteropServices.ComTypes; +using System.Text.RegularExpressions; +using EnvDTE; + +namespace GodotTools.OpenVisualStudio +{ +    internal static class Program +    { +        [DllImport("ole32.dll")] +        private static extern int GetRunningObjectTable(int reserved, out IRunningObjectTable pprot); + +        [DllImport("ole32.dll")] +        private static extern void CreateBindCtx(int reserved, out IBindCtx ppbc); + +        [DllImport("user32.dll")] +        private static extern bool SetForegroundWindow(IntPtr hWnd); + +        private static void ShowHelp() +        { +            Console.WriteLine("Opens the file(s) in a Visual Studio instance that is editing the specified solution."); +            Console.WriteLine("If an existing instance for the solution is not found, a new one is created."); +            Console.WriteLine(); +            Console.WriteLine("Usage:"); +            Console.WriteLine(@"  GodotTools.OpenVisualStudio.exe solution [file[;line[;col]]...]"); +            Console.WriteLine(); +            Console.WriteLine("Lines and columns begin at one. Zero or lower will result in an error."); +            Console.WriteLine("If a line is specified but a column is not, the line is selected in the text editor."); +        } + +        // STAThread needed, otherwise CoRegisterMessageFilter may return CO_E_NOT_SUPPORTED. +        [STAThread] +        private static int Main(string[] args) +        { +            if (args.Length == 0 || args[0] == "--help" || args[0] == "-h") +            { +                ShowHelp(); +                return 0; +            } + +            string solutionFile = NormalizePath(args[0]); + +            var dte = FindInstanceEditingSolution(solutionFile); + +            if (dte == null) +            { +                // Open a new instance + +                var visualStudioDteType = Type.GetTypeFromProgID("VisualStudio.DTE.16.0", throwOnError: true); +                dte = (DTE)Activator.CreateInstance(visualStudioDteType); + +                dte.UserControl = true; + +                try +                { +                    dte.Solution.Open(solutionFile); +                } +                catch (ArgumentException) +                { +                    Console.Error.WriteLine("Solution.Open: Invalid path or file not found"); +                    return 1; +                } + +                dte.MainWindow.Visible = true; +            } + +            MessageFilter.Register(); + +            try +            { +                // Open files + +                for (int i = 1; i < args.Length; i++) +                { +                    // Both the line number and the column begin at one + +                    string[] fileArgumentParts = args[i].Split(';'); + +                    string filePath = NormalizePath(fileArgumentParts[0]); + +                    try +                    { +                        dte.ItemOperations.OpenFile(filePath); +                    } +                    catch (ArgumentException) +                    { +                        Console.Error.WriteLine("ItemOperations.OpenFile: Invalid path or file not found"); +                        return 1; +                    } + +                    if (fileArgumentParts.Length > 1) +                    { +                        if (int.TryParse(fileArgumentParts[1], out int line)) +                        { +                            var textSelection = (TextSelection)dte.ActiveDocument.Selection; + +                            if (fileArgumentParts.Length > 2) +                            { +                                if (int.TryParse(fileArgumentParts[2], out int column)) +                                { +                                    textSelection.MoveToLineAndOffset(line, column); +                                } +                                else +                                { +                                    Console.Error.WriteLine("The column part of the argument must be a valid integer"); +                                    return 1; +                                } +                            } +                            else +                            { +                                textSelection.GotoLine(line, Select: true); +                            } +                        } +                        else +                        { +                            Console.Error.WriteLine("The line part of the argument must be a valid integer"); +                            return 1; +                        } +                    } +                } +            } +            finally +            { +                var mainWindow = dte.MainWindow; +                mainWindow.Activate(); +                SetForegroundWindow(new IntPtr(mainWindow.HWnd)); + +                MessageFilter.Revoke(); +            } + +            return 0; +        } + +        private static DTE FindInstanceEditingSolution(string solutionPath) +        { +            if (GetRunningObjectTable(0, out IRunningObjectTable pprot) != 0) +                return null; + +            try +            { +                pprot.EnumRunning(out IEnumMoniker ppenumMoniker); +                ppenumMoniker.Reset(); + +                var moniker = new IMoniker[1]; + +                while (ppenumMoniker.Next(1, moniker, IntPtr.Zero) == 0) +                { +                    string ppszDisplayName; + +                    CreateBindCtx(0, out IBindCtx ppbc); + +                    try +                    { +                        moniker[0].GetDisplayName(ppbc, null, out ppszDisplayName); +                    } +                    finally +                    { +                        Marshal.ReleaseComObject(ppbc); +                    } + +                    if (ppszDisplayName == null) +                        continue; + +                    // The digits after the colon are the process ID +                    if (!Regex.IsMatch(ppszDisplayName, "!VisualStudio.DTE.16.0:[0-9]")) +                        continue; + +                    if (pprot.GetObject(moniker[0], out object ppunkObject) == 0) +                    { +                        if (ppunkObject is DTE dte && dte.Solution.FullName.Length > 0) +                        { +                            if (NormalizePath(dte.Solution.FullName) == solutionPath) +                                return dte; +                        } +                    } +                } +            } +            finally +            { +                Marshal.ReleaseComObject(pprot); +            } + +            return null; +        } + +        static string NormalizePath(string path) +        { +            return new Uri(Path.GetFullPath(path)).LocalPath +                .TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar) +                .ToUpperInvariant(); +        } + +        #region MessageFilter. See: http: //msdn.microsoft.com/en-us/library/ms228772.aspx + +        private class MessageFilter : IOleMessageFilter +        { +            // Class containing the IOleMessageFilter +            // thread error-handling functions + +            private static IOleMessageFilter _oldFilter; + +            // Start the filter +            public static void Register() +            { +                IOleMessageFilter newFilter = new MessageFilter(); +                int ret = CoRegisterMessageFilter(newFilter, out _oldFilter); +                if (ret != 0) +                    Console.Error.WriteLine($"CoRegisterMessageFilter failed with error code: {ret}"); +            } + +            // Done with the filter, close it +            public static void Revoke() +            { +                int ret = CoRegisterMessageFilter(_oldFilter, out _); +                if (ret != 0) +                    Console.Error.WriteLine($"CoRegisterMessageFilter failed with error code: {ret}"); +            } + +            // +            // IOleMessageFilter functions +            // Handle incoming thread requests +            int IOleMessageFilter.HandleInComingCall(int dwCallType, IntPtr hTaskCaller, int dwTickCount, IntPtr lpInterfaceInfo) +            { +                // Return the flag SERVERCALL_ISHANDLED +                return 0; +            } + +            // Thread call was rejected, so try again. +            int IOleMessageFilter.RetryRejectedCall(IntPtr hTaskCallee, int dwTickCount, int dwRejectType) +            { +                if (dwRejectType == 2) +                    // flag = SERVERCALL_RETRYLATER +                { +                    // Retry the thread call immediately if return >= 0 & < 100 +                    return 99; +                } + +                // Too busy; cancel call +                return -1; +            } + +            int IOleMessageFilter.MessagePending(IntPtr hTaskCallee, int dwTickCount, int dwPendingType) +            { +                // Return the flag PENDINGMSG_WAITDEFPROCESS +                return 2; +            } + +            // Implement the IOleMessageFilter interface +            [DllImport("ole32.dll")] +            private static extern int CoRegisterMessageFilter(IOleMessageFilter newFilter, out IOleMessageFilter oldFilter); +        } + +        [ComImport(), Guid("00000016-0000-0000-C000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] +        private interface IOleMessageFilter +        { +            [PreserveSig] +            int HandleInComingCall(int dwCallType, IntPtr hTaskCaller, int dwTickCount, IntPtr lpInterfaceInfo); + +            [PreserveSig] +            int RetryRejectedCall(IntPtr hTaskCallee, int dwTickCount, int dwRejectType); + +            [PreserveSig] +            int MessagePending(IntPtr hTaskCallee, int dwTickCount, int dwPendingType); +        } + +        #endregion +    } +} diff --git a/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/ProjectGenerator.cs b/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/ProjectGenerator.cs index fb2beb6995..679d5bb444 100644 --- a/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/ProjectGenerator.cs +++ b/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/ProjectGenerator.cs @@ -12,6 +12,11 @@ namespace GodotTools.ProjectEditor          private const string CoreApiProjectName = "GodotSharp";          private const string EditorApiProjectName = "GodotSharpEditor"; +        public const string CSharpProjectTypeGuid = "{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}"; +        public const string GodotProjectTypeGuid = "{8F3E2DF0-C35C-4265-82FC-BEA011F4A7ED}"; + +        public static readonly string GodotDefaultProjectTypeGuids = $"{GodotProjectTypeGuid};{CSharpProjectTypeGuid}"; +          public static string GenGameProject(string dir, string name, IEnumerable<string> compileItems)          {              string path = Path.Combine(dir, name + ".csproj"); @@ -19,6 +24,7 @@ namespace GodotTools.ProjectEditor              ProjectPropertyGroupElement mainGroup;              var root = CreateLibraryProject(name, "Debug", out mainGroup); +            mainGroup.SetProperty("ProjectTypeGuids", GodotDefaultProjectTypeGuids);              mainGroup.SetProperty("OutputPath", Path.Combine(".mono", "temp", "bin", "$(Configuration)"));              mainGroup.SetProperty("BaseIntermediateOutputPath", Path.Combine(".mono", "temp", "obj"));              mainGroup.SetProperty("IntermediateOutputPath", Path.Combine("$(BaseIntermediateOutputPath)", "$(Configuration)")); diff --git a/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/ProjectUtils.cs b/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/ProjectUtils.cs index 069a1edaa3..8774b4ee31 100644 --- a/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/ProjectUtils.cs +++ b/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/ProjectUtils.cs @@ -165,6 +165,21 @@ namespace GodotTools.ProjectEditor              return result.ToArray();          } +        public static void EnsureHasProjectTypeGuids(MSBuildProject project) +        { +            var root = project.Root; + +            bool found = root.PropertyGroups.Any(pg => +                string.IsNullOrEmpty(pg.Condition) && pg.Properties.Any(p => p.Name == "ProjectTypeGuids")); + +            if (found) +                return; + +            root.AddProperty("ProjectTypeGuids", ProjectGenerator.GodotDefaultProjectTypeGuids); + +            project.HasUnsavedChanges = true; +        } +          ///  Simple function to make sure the Api assembly references are configured correctly          public static void FixApiHintPath(MSBuildProject project)          { diff --git a/modules/mono/editor/GodotTools/GodotTools.sln b/modules/mono/editor/GodotTools/GodotTools.sln index f6147eb5bb..ba5379e562 100644 --- a/modules/mono/editor/GodotTools/GodotTools.sln +++ b/modules/mono/editor/GodotTools/GodotTools.sln @@ -11,6 +11,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GodotTools.BuildLogger", "G  EndProject  Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GodotTools.IdeMessaging", "GodotTools.IdeMessaging\GodotTools.IdeMessaging.csproj", "{92600954-25F0-4291-8E11-1FEE9FC4BE20}"  EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GodotTools.OpenVisualStudio", "GodotTools.OpenVisualStudio\GodotTools.OpenVisualStudio.csproj", "{EAFFF236-FA96-4A4D-BD23-0E51EF988277}" +EndProject  Global  	GlobalSection(SolutionConfigurationPlatforms) = preSolution  		Debug|Any CPU = Debug|Any CPU @@ -37,5 +39,9 @@ Global  		{92600954-25F0-4291-8E11-1FEE9FC4BE20}.Debug|Any CPU.Build.0 = Debug|Any CPU  		{92600954-25F0-4291-8E11-1FEE9FC4BE20}.Release|Any CPU.ActiveCfg = Release|Any CPU  		{92600954-25F0-4291-8E11-1FEE9FC4BE20}.Release|Any CPU.Build.0 = Release|Any CPU +		{EAFFF236-FA96-4A4D-BD23-0E51EF988277}.Debug|Any CPU.ActiveCfg = Debug|Any CPU +		{EAFFF236-FA96-4A4D-BD23-0E51EF988277}.Debug|Any CPU.Build.0 = Debug|Any CPU +		{EAFFF236-FA96-4A4D-BD23-0E51EF988277}.Release|Any CPU.ActiveCfg = Release|Any CPU +		{EAFFF236-FA96-4A4D-BD23-0E51EF988277}.Release|Any CPU.Build.0 = Release|Any CPU  	EndGlobalSection  EndGlobal diff --git a/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs b/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs index c874025be0..403e25781d 100644 --- a/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs +++ b/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs @@ -6,6 +6,7 @@ using System;  using System.Collections.Generic;  using System.Diagnostics.CodeAnalysis;  using System.IO; +using System.Linq;  using GodotTools.Ides;  using GodotTools.Ides.Rider;  using GodotTools.Internals; @@ -238,7 +239,31 @@ namespace GodotTools                      // Not an error. Tells the caller to fallback to the global external editor settings or the built-in editor.                      return Error.Unavailable;                  case ExternalEditorId.VisualStudio: -                    throw new NotSupportedException(); +                { +                    string scriptPath = ProjectSettings.GlobalizePath(script.ResourcePath); + +                    var args = new List<string> +                    { +                        GodotSharpDirs.ProjectSlnPath, +                        line >= 0 ? $"{scriptPath};{line + 1};{col + 1}" : scriptPath +                    }; + +                    string command = Path.Combine(GodotSharpDirs.DataEditorToolsDir, "GodotTools.OpenVisualStudio.exe"); + +                    try +                    { +                        if (Godot.OS.IsStdoutVerbose()) +                            Console.WriteLine($"Running: \"{command}\" {string.Join(" ", args.Select(a => $"\"{a}\""))}"); + +                        OS.RunProcess(command, args); +                    } +                    catch (Exception e) +                    { +                        GD.PushError($"Error when trying to run code editor: VisualStudio. Exception message: '{e.Message}'"); +                    } + +                    break; +                }                  case ExternalEditorId.VisualStudioForMac:                      goto case ExternalEditorId.MonoDevelop;                  case ExternalEditorId.Rider: @@ -458,6 +483,9 @@ namespace GodotTools                      // Apply the other fixes only after configurations have been migrated +                    // Make sure the existing project has the ProjectTypeGuids property (for VisualStudio) +                    ProjectUtils.EnsureHasProjectTypeGuids(msbuildProject); +                      // Make sure the existing project has Api assembly references configured correctly                      ProjectUtils.FixApiHintPath(msbuildProject); @@ -501,7 +529,8 @@ namespace GodotTools              if (OS.IsWindows)              { -                settingsHintStr += $",MonoDevelop:{(int)ExternalEditorId.MonoDevelop}" + +                settingsHintStr += $",Visual Studio:{(int)ExternalEditorId.VisualStudio}" + +                                   $",MonoDevelop:{(int)ExternalEditorId.MonoDevelop}" +                                     $",Visual Studio Code:{(int)ExternalEditorId.VsCode}" +                                     $",JetBrains Rider:{(int)ExternalEditorId.Rider}";              } diff --git a/modules/mono/editor/GodotTools/GodotTools/GodotTools.csproj b/modules/mono/editor/GodotTools/GodotTools/GodotTools.csproj index ba527ca3b5..3f14629b11 100644 --- a/modules/mono/editor/GodotTools/GodotTools/GodotTools.csproj +++ b/modules/mono/editor/GodotTools/GodotTools/GodotTools.csproj @@ -33,5 +33,7 @@      <ProjectReference Include="..\GodotTools.IdeMessaging\GodotTools.IdeMessaging.csproj" />      <ProjectReference Include="..\GodotTools.ProjectEditor\GodotTools.ProjectEditor.csproj" />      <ProjectReference Include="..\GodotTools.Core\GodotTools.Core.csproj" /> +    <!-- Include it if this is an SCons build targeting Windows, or if it's not an SCons build but we're on Windows --> +    <ProjectReference Include="..\GodotTools.OpenVisualStudio\GodotTools.OpenVisualStudio.csproj" Condition=" '$(GodotPlatform)' == 'windows' Or ( '$(GodotPlatform)' == '' And '$(OS)' == 'Windows_NT' ) " />    </ItemGroup>  </Project> diff --git a/modules/mono/editor/GodotTools/GodotTools/Ides/MessagingServer.cs b/modules/mono/editor/GodotTools/GodotTools/Ides/MessagingServer.cs index 32f264d100..98e8d13be0 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Ides/MessagingServer.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Ides/MessagingServer.cs @@ -307,6 +307,11 @@ namespace GodotTools.Ides                          var request = JsonConvert.DeserializeObject<DebugPlayRequest>(content.Body);                          return await HandleDebugPlay(request);                      }, +                    [StopPlayRequest.Id] = async (peer, content) => +                    { +                        var request = JsonConvert.DeserializeObject<StopPlayRequest>(content.Body); +                        return await HandleStopPlay(request); +                    },                      [ReloadScriptsRequest.Id] = async (peer, content) =>                      {                          _ = JsonConvert.DeserializeObject<ReloadScriptsRequest>(content.Body); @@ -343,6 +348,12 @@ namespace GodotTools.Ides                  return Task.FromResult<Response>(new DebugPlayResponse());              } +            private static Task<Response> HandleStopPlay(StopPlayRequest request) +            { +                DispatchToMainThread(Internal.EditorRunStop); +                return Task.FromResult<Response>(new StopPlayResponse()); +            } +              private static Task<Response> HandleReloadScripts()              {                  DispatchToMainThread(Internal.ScriptEditorDebugger_ReloadScripts);  |