From 5f9439c9aae45bdb10d697366d639d551189ac10 Mon Sep 17 00:00:00 2001 From: Matt Parker <61717342+MattParkerDev@users.noreply.github.com> Date: Fri, 29 Aug 2025 19:01:06 +1000 Subject: [PATCH] wire up debug panel --- .../Features/Events/GlobalEvents.cs | 6 +++ .../Features/Run/RunService.cs | 33 ++++++++++++---- .../Features/Debug_/DebugPanel.cs | 39 ++++++++++--------- .../Features/Debug_/DebugPanel.tscn | 4 +- .../Features/Run/Resources/Debug.svg | 5 +++ .../Features/Run/Resources/Debug.svg.import | 37 ++++++++++++++++++ .../Features/Run/RunMenuItem.cs | 11 ++++++ .../Features/Run/RunMenuItem.tscn | 8 +++- src/SharpIDE.Godot/Features/Run/RunPanel.cs | 1 + 9 files changed, 116 insertions(+), 28 deletions(-) create mode 100644 src/SharpIDE.Godot/Features/Run/Resources/Debug.svg create mode 100644 src/SharpIDE.Godot/Features/Run/Resources/Debug.svg.import diff --git a/src/SharpIDE.Application/Features/Events/GlobalEvents.cs b/src/SharpIDE.Application/Features/Events/GlobalEvents.cs index 29dba2e..ccc7251 100644 --- a/src/SharpIDE.Application/Features/Events/GlobalEvents.cs +++ b/src/SharpIDE.Application/Features/Events/GlobalEvents.cs @@ -12,6 +12,12 @@ public static class GlobalEvents public static event Func StartedRunningProject = () => Task.CompletedTask; public static void InvokeStartedRunningProject() => StartedRunningProject?.InvokeParallelFireAndForget(); + public static event Func ProjectStartedDebugging = _ => Task.CompletedTask; + public static void InvokeProjectStartedDebugging(SharpIdeProjectModel project) => ProjectStartedDebugging?.InvokeParallelFireAndForget(project); + + public static event Func ProjectStoppedDebugging = _ => Task.CompletedTask; + public static void InvokeProjectStoppedDebugging(SharpIdeProjectModel project) => ProjectStoppedDebugging?.InvokeParallelFireAndForget(project); + public static event Func ProjectStartedRunning = _ => Task.CompletedTask; public static void InvokeProjectStartedRunning(SharpIdeProjectModel project) => ProjectStartedRunning?.InvokeParallelFireAndForget(project); diff --git a/src/SharpIDE.Application/Features/Run/RunService.cs b/src/SharpIDE.Application/Features/Run/RunService.cs index cc75573..a8e4800 100644 --- a/src/SharpIDE.Application/Features/Run/RunService.cs +++ b/src/SharpIDE.Application/Features/Run/RunService.cs @@ -15,9 +15,8 @@ public class RunService private readonly ConcurrentDictionary _projectLocks = []; public ConcurrentDictionary> Breakpoints { get; } = []; private Debugger? _debugger; // TODO: Support multiple debuggers for multiple running projects - public async Task RunProject(SharpIdeProjectModel project) + public async Task RunProject(SharpIdeProjectModel project, bool isDebug = false) { - var isDebug = true; Guard.Against.Null(project, nameof(project)); Guard.Against.NullOrWhiteSpace(project.FilePath, nameof(project.FilePath), "Project file path cannot be null or empty."); await Task.CompletedTask.ConfigureAwait(ConfigureAwaitOptions.ForceYielding); @@ -92,9 +91,16 @@ public class RunService project.Running = true; project.OpenInRunPanel = true; - GlobalEvents.InvokeProjectsRunningChanged(); - GlobalEvents.InvokeStartedRunningProject(); - GlobalEvents.InvokeProjectStartedRunning(project); + if (isDebug) + { + GlobalEvents.InvokeProjectStartedDebugging(project); + } + else + { + GlobalEvents.InvokeProjectsRunningChanged(); + GlobalEvents.InvokeStartedRunningProject(); + GlobalEvents.InvokeProjectStartedRunning(project); + } project.InvokeProjectStartedRunning(); await process.WaitForExitAsync().WaitAsync(project.RunningCancellationTokenSource.Token).ConfigureAwait(ConfigureAwaitOptions.SuppressThrowing); if (project.RunningCancellationTokenSource.IsCancellationRequested) @@ -107,8 +113,16 @@ public class RunService project.RunningCancellationTokenSource.Dispose(); project.RunningCancellationTokenSource = null; project.Running = false; - GlobalEvents.InvokeProjectsRunningChanged(); - GlobalEvents.InvokeProjectStoppedRunning(project); + if (isDebug) + { + GlobalEvents.InvokeProjectStoppedDebugging(project); + } + else + { + GlobalEvents.InvokeProjectsRunningChanged(); + GlobalEvents.InvokeProjectStoppedRunning(project); + } + project.InvokeProjectStoppedRunning(); Console.WriteLine("Project finished running"); @@ -133,6 +147,11 @@ public class RunService await _debugger!.StepOver(threadId); } + public async Task GetInfoAtStopPoint() + { + await _debugger!.GetInfoAtStopPoint(); + } + private string GetRunArguments(SharpIdeProjectModel project) { var dllFullPath = ProjectEvaluation.GetOutputDllFullPath(project); diff --git a/src/SharpIDE.Godot/Features/Debug_/DebugPanel.cs b/src/SharpIDE.Godot/Features/Debug_/DebugPanel.cs index 50055c1..0ccd0d1 100644 --- a/src/SharpIDE.Godot/Features/Debug_/DebugPanel.cs +++ b/src/SharpIDE.Godot/Features/Debug_/DebugPanel.cs @@ -13,27 +13,28 @@ public partial class DebugPanel : Control [Export] public Texture2D RunningIcon { get; set; } = null!; - private PackedScene _runPanelTabScene = GD.Load("res://Features/Run/RunPanelTab.tscn"); + private PackedScene _debugPanelTabScene = GD.Load("res://Features/Debug_/DebugPanelTab.tscn"); public override void _Ready() { + if (RunningIcon is null) throw new Exception("RunningIcon is null in DebugPanel"); _tabBar = GetNode("%TabBar"); _tabBar.ClearTabs(); //_tabBar.TabClosePressed _tabBar.TabClicked += OnTabBarTabClicked; _tabsPanel = GetNode("%TabsPanel"); - GlobalEvents.ProjectStartedRunning += async projectModel => + GlobalEvents.ProjectStartedDebugging += async projectModel => { - await this.InvokeAsync(() => ProjectStartedRunning(projectModel)); + await this.InvokeAsync(() => ProjectStartedDebugging(projectModel)); }; - GlobalEvents.ProjectStoppedRunning += async projectModel => + GlobalEvents.ProjectStoppedDebugging += async projectModel => { - await this.InvokeAsync(() => ProjectStoppedRunning(projectModel)); + await this.InvokeAsync(() => ProjectStoppedDebugging(projectModel)); }; } private void OnTabBarTabClicked(long idx) { - var children = _tabsPanel.GetChildren().OfType().ToList(); + var children = _tabsPanel.GetChildren().OfType().ToList(); foreach (var child in children) { child.Visible = false; @@ -43,9 +44,9 @@ public partial class DebugPanel : Control tab.Visible = true; } - public void ProjectStartedRunning(SharpIdeProjectModel projectModel) + public void ProjectStartedDebugging(SharpIdeProjectModel projectModel) { - var existingRunPanelTab = _tabsPanel.GetChildren().OfType().SingleOrDefault(s => s.Project == projectModel); + var existingRunPanelTab = _tabsPanel.GetChildren().OfType().SingleOrDefault(s => s.Project == projectModel); if (existingRunPanelTab != null) { _tabBar.SetTabIcon(existingRunPanelTab.TabBarTab, RunningIcon); @@ -56,21 +57,21 @@ public partial class DebugPanel : Control return; } - var runPanelTab = _runPanelTabScene.Instantiate(); - runPanelTab.Project = projectModel; + var debugPanelTab = _debugPanelTabScene.Instantiate(); + debugPanelTab.Project = projectModel; _tabBar.AddTab(projectModel.Name); var tabIdx = _tabBar.GetTabCount() - 1; - runPanelTab.TabBarTab = tabIdx; - _tabBar.SetTabIcon(runPanelTab.TabBarTab, RunningIcon); - _tabBar.CurrentTab = runPanelTab.TabBarTab; - _tabsPanel.AddChild(runPanelTab); - OnTabBarTabClicked(runPanelTab.TabBarTab); - runPanelTab.StartWritingFromProjectOutput(); + debugPanelTab.TabBarTab = tabIdx; + _tabBar.SetTabIcon(debugPanelTab.TabBarTab, RunningIcon); + _tabBar.CurrentTab = debugPanelTab.TabBarTab; + _tabsPanel.AddChild(debugPanelTab); + OnTabBarTabClicked(debugPanelTab.TabBarTab); + debugPanelTab.StartWritingFromProjectOutput(); } - public void ProjectStoppedRunning(SharpIdeProjectModel projectModel) + public void ProjectStoppedDebugging(SharpIdeProjectModel projectModel) { - var runPanelTab = _tabsPanel.GetChildren().OfType().Single(s => s.Project == projectModel); - _tabBar.SetTabIcon(runPanelTab.TabBarTab, null); + var debugPanelTab = _tabsPanel.GetChildren().OfType().Single(s => s.Project == projectModel); + _tabBar.SetTabIcon(debugPanelTab.TabBarTab, null); } } \ No newline at end of file diff --git a/src/SharpIDE.Godot/Features/Debug_/DebugPanel.tscn b/src/SharpIDE.Godot/Features/Debug_/DebugPanel.tscn index 5ba8ff7..0a6abc6 100644 --- a/src/SharpIDE.Godot/Features/Debug_/DebugPanel.tscn +++ b/src/SharpIDE.Godot/Features/Debug_/DebugPanel.tscn @@ -1,6 +1,7 @@ -[gd_scene load_steps=2 format=3 uid="uid://dkjips8oudqou"] +[gd_scene load_steps=3 format=3 uid="uid://dkjips8oudqou"] [ext_resource type="Script" uid="uid://ddyadu54qitw4" path="res://Features/Debug_/DebugPanel.cs" id="1_h4rcc"] +[ext_resource type="Texture2D" uid="uid://0digl54lqm6p" path="res://Features/Run/Resources/Running.svg" id="2_pub1e"] [node name="DebugPanel" type="Control"] layout_mode = 3 @@ -10,6 +11,7 @@ anchor_bottom = 1.0 grow_horizontal = 2 grow_vertical = 2 script = ExtResource("1_h4rcc") +RunningIcon = ExtResource("2_pub1e") [node name="Label" type="Label" parent="."] layout_mode = 1 diff --git a/src/SharpIDE.Godot/Features/Run/Resources/Debug.svg b/src/SharpIDE.Godot/Features/Run/Resources/Debug.svg new file mode 100644 index 0000000..aacb116 --- /dev/null +++ b/src/SharpIDE.Godot/Features/Run/Resources/Debug.svg @@ -0,0 +1,5 @@ + + \ No newline at end of file diff --git a/src/SharpIDE.Godot/Features/Run/Resources/Debug.svg.import b/src/SharpIDE.Godot/Features/Run/Resources/Debug.svg.import new file mode 100644 index 0000000..d2c9055 --- /dev/null +++ b/src/SharpIDE.Godot/Features/Run/Resources/Debug.svg.import @@ -0,0 +1,37 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://c7cmou8hipsvc" +path="res://.godot/imported/Debug.svg-ae946e7dd0fbc448ad458ff70295702c.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://Features/Run/Resources/Debug.svg" +dest_files=["res://.godot/imported/Debug.svg-ae946e7dd0fbc448ad458ff70295702c.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 +svg/scale=1.0 +editor/scale_with_editor_scale=false +editor/convert_colors_with_editor_theme=false diff --git a/src/SharpIDE.Godot/Features/Run/RunMenuItem.cs b/src/SharpIDE.Godot/Features/Run/RunMenuItem.cs index 4955d1f..bb7bf7c 100644 --- a/src/SharpIDE.Godot/Features/Run/RunMenuItem.cs +++ b/src/SharpIDE.Godot/Features/Run/RunMenuItem.cs @@ -9,6 +9,7 @@ public partial class RunMenuItem : HBoxContainer public SharpIdeProjectModel Project { get; set; } = null!; private Label _label = null!; private Button _runButton = null!; + private Button _debugButton = null!; private Button _stopButton = null!; public override void _Ready() { @@ -18,6 +19,8 @@ public partial class RunMenuItem : HBoxContainer _runButton.Pressed += OnRunButtonPressed; _stopButton = GetNode