diff --git a/GodotAddinVS/Commands/CommandResetGodot.cs b/GodotAddinVS/Commands/CommandResetGodot.cs
new file mode 100644
index 0000000..83c4c7c
--- /dev/null
+++ b/GodotAddinVS/Commands/CommandResetGodot.cs
@@ -0,0 +1,101 @@
+using Microsoft.VisualStudio.Shell;
+using Microsoft.VisualStudio.Shell.Interop;
+using System;
+using System.ComponentModel.Design;
+using System.Globalization;
+using System.IO;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+using Microsoft.VisualStudio.Settings;
+using Microsoft.VisualStudio.Shell.Settings;
+using Task = System.Threading.Tasks.Task;
+
+namespace GodotAddinVS.Commands {
+ ///
+ /// Command handler
+ ///
+ internal sealed class CommandResetGodot {
+ ///
+ /// Command ID.
+ ///
+ public const int CommandId = 256;
+
+ ///
+ /// Command menu group (command set GUID).
+ ///
+ public static readonly Guid CommandSet = new Guid("38009f93-330e-4875-ab88-e127fd85bb88");
+
+ ///
+ /// VS Package that provides this command, not null.
+ ///
+ private readonly AsyncPackage package;
+
+ ///
+ /// Initializes a new instance of the class.
+ /// Adds our command handlers for menu (commands must exist in the command table file)
+ ///
+ /// Owner package, not null.
+ /// Command service to add command to, not null.
+ private CommandResetGodot(AsyncPackage package, OleMenuCommandService commandService) {
+ this.package = package ?? throw new ArgumentNullException(nameof(package));
+ commandService = commandService ?? throw new ArgumentNullException(nameof(commandService));
+
+ var menuCommandID = new CommandID(CommandSet, CommandId);
+ var menuItem = new MenuCommand(this.Execute, menuCommandID);
+ commandService.AddCommand(menuItem);
+ }
+
+ ///
+ /// Gets the instance of the command.
+ ///
+ public static CommandResetGodot Instance {
+ get;
+ private set;
+ }
+
+ ///
+ /// Gets the service provider from the owner package.
+ ///
+ private Microsoft.VisualStudio.Shell.IAsyncServiceProvider ServiceProvider {
+ get {
+ return this.package;
+ }
+ }
+
+ ///
+ /// Initializes the singleton instance of the command.
+ ///
+ /// Owner package, not null.
+ public static async Task InitializeAsync(AsyncPackage package) {
+ // Switch to the main thread - the call to AddCommand in CommandResetGodot's constructor requires
+ // the UI thread.
+ await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(package.DisposalToken);
+
+ OleMenuCommandService commandService = await package.GetServiceAsync(typeof(IMenuCommandService)) as OleMenuCommandService;
+ Instance = new CommandResetGodot(package, commandService);
+ }
+
+ ///
+ /// This function is the callback used to execute the command when the menu item is clicked.
+ /// See the constructor to see how the menu item is associated with this function using
+ /// OleMenuCommandService service and MenuCommand class.
+ ///
+ /// Event sender.
+ /// Event args.
+ private void Execute(object sender, EventArgs e) {
+ ThreadHelper.ThrowIfNotOnUIThread();
+ var settingsManager = new ShellSettingsManager(package);
+ var config = settingsManager.GetWritableSettingsStore(SettingsScope.UserSettings);
+
+ var ofd = new OpenFileDialog {
+ Filter = @"GoDot executable (.exe)|*.exe"
+ };
+ var result = ofd.ShowDialog(null);
+
+ if (result != DialogResult.OK) return;
+ config.SetString("External Tools", "GoDotExecutable", ofd.FileName);
+ config.SetString("External Tools", "GoDotPath", Path.GetDirectoryName(ofd.FileName));
+ }
+ }
+}
diff --git a/GodotAddinVS/Commands/CommandRunGodot.cs b/GodotAddinVS/Commands/CommandRunGodot.cs
new file mode 100644
index 0000000..0b32050
--- /dev/null
+++ b/GodotAddinVS/Commands/CommandRunGodot.cs
@@ -0,0 +1,132 @@
+using Microsoft.VisualStudio.Shell;
+using Microsoft.VisualStudio.Shell.Interop;
+using System;
+using System.ComponentModel.Design;
+using System.Diagnostics;
+using System.Globalization;
+using System.IO;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+using Microsoft.VisualStudio.Settings;
+using Microsoft.VisualStudio.Shell.Settings;
+using Task = System.Threading.Tasks.Task;
+
+namespace GodotAddinVS.Commands {
+ ///
+ /// Command handler
+ ///
+ internal sealed class CommandRunGodot {
+ ///
+ /// Command ID.
+ ///
+ public const int CommandId = 256;
+
+ ///
+ /// Command menu group (command set GUID).
+ ///
+ public static readonly Guid CommandSet = new Guid("d71528ca-92b8-49bb-8655-8b478b495499");
+
+ ///
+ /// VS Package that provides this command, not null.
+ ///
+ private readonly AsyncPackage package;
+
+ ///
+ /// Initializes a new instance of the class.
+ /// Adds our command handlers for menu (commands must exist in the command table file)
+ ///
+ /// Owner package, not null.
+ /// Command service to add command to, not null.
+ private CommandRunGodot(AsyncPackage package, OleMenuCommandService commandService) {
+ this.package = package ?? throw new ArgumentNullException(nameof(package));
+ commandService = commandService ?? throw new ArgumentNullException(nameof(commandService));
+
+ var menuCommandId = new CommandID(CommandSet, CommandId);
+ var menuItem = new MenuCommand(Execute, menuCommandId);
+ commandService.AddCommand(menuItem);
+ }
+
+ ///
+ /// Gets the instance of the command.
+ ///
+ public static CommandRunGodot Instance {
+ get;
+ private set;
+ }
+
+ ///
+ /// Gets the service provider from the owner package.
+ ///
+ private Microsoft.VisualStudio.Shell.IAsyncServiceProvider ServiceProvider {
+ get {
+ return this.package;
+ }
+ }
+
+ ///
+ /// Initializes the singleton instance of the command.
+ ///
+ /// Owner package, not null.
+ public static async Task InitializeAsync(AsyncPackage package) {
+ // Switch to the main thread - the call to AddCommand in CommandRunGodot's constructor requires
+ // the UI thread.
+ await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(package.DisposalToken);
+
+ var commandService = await package.GetServiceAsync(typeof(IMenuCommandService)) as OleMenuCommandService;
+ Instance = new CommandRunGodot(package, commandService);
+ }
+
+ ///
+ /// This function is the callback used to execute the command when the menu item is clicked.
+ /// See the constructor to see how the menu item is associated with this function using
+ /// OleMenuCommandService service and MenuCommand class.
+ ///
+ /// Event sender.
+ /// Event args.
+ private void Execute(object sender, EventArgs e) {
+ ThreadHelper.ThrowIfNotOnUIThread();
+
+ string goDotPath;
+ string goDotExecutable;
+
+ var settingsManager = new ShellSettingsManager(package);
+ var config = settingsManager.GetWritableSettingsStore(SettingsScope.UserSettings);
+
+ if (!config.CollectionExists("External Tools")) {
+ config.CreateCollection("External Tools");
+ }
+
+ if (!config.PropertyExists("External Tools", "GoDotExecutable")) {
+ var ofd = new OpenFileDialog {
+ Filter = @"GoDot executable (.exe)|*.exe"
+ };
+ var result = ofd.ShowDialog(null);
+
+ if (result == DialogResult.OK) {
+ goDotExecutable = ofd.FileName;
+ goDotPath = Path.GetDirectoryName(goDotExecutable);
+
+ config.SetString("External Tools", "GoDotExecutable", goDotExecutable);
+ config.SetString("External Tools", "GoDotPath", goDotPath);
+ } else return;
+
+ } else {
+ goDotPath = config.GetString("External Tools", "GoDotPath");
+ goDotExecutable = config.GetString("External Tools", "GoDotExecutable");
+ }
+
+ if (string.IsNullOrEmpty(goDotExecutable)) {
+ MessageBox.Show("GoDot", "GoDot path not set");
+ return;
+ }
+
+ if (!File.Exists(goDotExecutable)) {
+ MessageBox.Show("GoDot", @$"GoDot does not exist at {goDotExecutable}");
+ return;
+ }
+
+ Process.Start(goDotExecutable);
+ }
+ }
+}
diff --git a/GodotAddinVS/GodotAddinVS.csproj b/GodotAddinVS/GodotAddinVS.csproj
index cb3223c..b61454f 100644
--- a/GodotAddinVS/GodotAddinVS.csproj
+++ b/GodotAddinVS/GodotAddinVS.csproj
@@ -46,6 +46,8 @@
4
+
+
@@ -73,6 +75,11 @@
+
+
+
+
+
@@ -109,6 +116,7 @@
GodotCompletionProviders
+
$(GetVsixSourceItemsDependsOn);IncludeNuGetResolvedAssets
diff --git a/GodotAddinVS/GodotPackage.cs b/GodotAddinVS/GodotPackage.cs
index fcb9552..975c78e 100644
--- a/GodotAddinVS/GodotPackage.cs
+++ b/GodotAddinVS/GodotPackage.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
@@ -68,6 +68,10 @@ namespace GodotAddinVS
// Do any initialization that requires the UI thread after switching to the UI thread.
await JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken);
+ // Commands
+ await Commands.CommandRunGodot.InitializeAsync(this);
+ await Commands.CommandResetGodot.InitializeAsync(this);
+
RegisterProjectFactory(new GodotFlavoredProjectFactory(this));
GodotSolutionEventsListener = new GodotSolutionEventsListener(this);
diff --git a/GodotAddinVS/GodotPackage.vsct b/GodotAddinVS/GodotPackage.vsct
index 717ae5c..2c2ba77 100644
--- a/GodotAddinVS/GodotPackage.vsct
+++ b/GodotAddinVS/GodotPackage.vsct
@@ -1,9 +1,10 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file