134 lines
5.8 KiB
C#
134 lines
5.8 KiB
C#
#nullable enable
|
|
|
|
using System;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Text.RegularExpressions;
|
|
using Godot;
|
|
using ShrinkSDK.Installer;
|
|
|
|
namespace ShrinkSDK.Godot.Editor;
|
|
|
|
[Tool]
|
|
public partial class ShrinkGodotInstallerPlugin : EditorPlugin
|
|
{
|
|
private EditorDock? _panel;
|
|
private Label? _status;
|
|
private RichTextLabel? _output;
|
|
private readonly System.Collections.Generic.Dictionary<string, Button> _installActions =
|
|
new(StringComparer.OrdinalIgnoreCase);
|
|
private readonly System.Collections.Generic.Dictionary<string, Button> _removeActions =
|
|
new(StringComparer.OrdinalIgnoreCase);
|
|
private string ProjectDirectory => ProjectSettings.GlobalizePath("res://");
|
|
private string ProjectPath => Directory.GetFiles(ProjectDirectory, "*.csproj", SearchOption.TopDirectoryOnly).Single();
|
|
|
|
public override void _EnterTree()
|
|
{
|
|
_panel = new EditorDock { Name = "ShrinkSDK", Title = "ShrinkSDK", DefaultSlot = EditorDock.DockSlot.LeftBr };
|
|
var content = new VBoxContainer();
|
|
_panel.AddChild(content);
|
|
content.AddChild(new Label { Text = "ShrinkSDK Packages" });
|
|
_installActions.Clear();
|
|
_removeActions.Clear();
|
|
foreach (var package in ShrinkProjectPackageEditor.RecommendedPackages)
|
|
{
|
|
var row = new HBoxContainer();
|
|
row.AddChild(new Label { Text = $"{package.Key} {package.Value}", SizeFlagsHorizontal = Control.SizeFlags.ExpandFill });
|
|
var install = new Button { Text = "Install / Update" };
|
|
install.Pressed += () => ChangePackage(package.Key, package.Value);
|
|
row.AddChild(install);
|
|
_installActions[package.Key] = install;
|
|
var remove = new Button { Text = "Remove" };
|
|
remove.Pressed += () => ChangePackage(package.Key, null);
|
|
row.AddChild(remove);
|
|
_removeActions[package.Key] = remove;
|
|
content.AddChild(row);
|
|
}
|
|
var restore = new Button { Text = "Restore and Build" };
|
|
restore.Pressed += BuildProject;
|
|
content.AddChild(restore);
|
|
_status = new Label { Text = "CodeGen: not built" };
|
|
content.AddChild(_status);
|
|
_output = new RichTextLabel { FitContent = true, CustomMinimumSize = new Vector2(360, 180) };
|
|
content.AddChild(_output);
|
|
AddDock(_panel);
|
|
RefreshInstalledState();
|
|
}
|
|
|
|
public override void _ExitTree()
|
|
{
|
|
if (_panel == null) return;
|
|
RemoveDock(_panel);
|
|
_panel.QueueFree();
|
|
_panel = null;
|
|
}
|
|
|
|
private async void ChangePackage(string packageId, string? version)
|
|
{
|
|
try
|
|
{
|
|
ShrinkProjectPackageEditor.EnsureShrinkFeed(Path.Combine(ProjectDirectory, "NuGet.Config"));
|
|
ShrinkProjectPackageEditor.SetPackageReference(ProjectPath, packageId, version);
|
|
await RunBuild("restore");
|
|
}
|
|
catch (Exception exception) { ShowFailure(exception); }
|
|
}
|
|
|
|
private async void BuildProject()
|
|
{
|
|
try { await RunBuild("build"); }
|
|
catch (Exception exception) { ShowFailure(exception); }
|
|
}
|
|
|
|
private async System.Threading.Tasks.Task RunBuild(string command)
|
|
{
|
|
_status!.Text = $"CodeGen: running dotnet {command}";
|
|
var result = await ShrinkProjectPackageEditor.RunDotnetAsync(ProjectDirectory, $"{command} \"{ProjectPath}\" /nr:false");
|
|
_output!.Text = result.Output;
|
|
var match = Regex.Matches(result.Output, @"\[ShrinkSDK\.CodeGen\].*woven: instance=(\d+), static=(\d+), registry=(\d+)").Cast<Match>().LastOrDefault();
|
|
_status.Text = result.ExitCode == 0
|
|
? match == null ? "CodeGen: build succeeded (no attributed registrations)" : $"CodeGen: woven; instance={match.Groups[1].Value}, static={match.Groups[2].Value}, registry={match.Groups[3].Value}"
|
|
: "CodeGen: build failed";
|
|
RefreshInstalledState();
|
|
}
|
|
|
|
private void RefreshInstalledState()
|
|
{
|
|
if (_output == null) return;
|
|
var installed = File.Exists(ProjectPath)
|
|
? ShrinkProjectPackageEditor.ReadPackageReferences(ProjectPath)
|
|
: new System.Collections.Generic.Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
|
foreach (var package in ShrinkProjectPackageEditor.RecommendedPackages)
|
|
{
|
|
var hasInstalled = installed.TryGetValue(package.Key, out var installedVersion);
|
|
var relation = hasInstalled
|
|
? ShrinkPackageVersion.Classify(installedVersion, package.Value)
|
|
: ShrinkPackageVersionRelation.Unknown;
|
|
if (_installActions.TryGetValue(package.Key, out var install))
|
|
{
|
|
install.Text = !hasInstalled
|
|
? $"Install {package.Value}"
|
|
: relation switch
|
|
{
|
|
ShrinkPackageVersionRelation.Equal => $"Installed {installedVersion}",
|
|
ShrinkPackageVersionRelation.Newer => $"Newer {installedVersion}",
|
|
ShrinkPackageVersionRelation.Older => $"Upgrade {installedVersion} → {package.Value}",
|
|
_ => $"Update {installedVersion} → {package.Value}"
|
|
};
|
|
install.Disabled = hasInstalled && relation is
|
|
ShrinkPackageVersionRelation.Equal or ShrinkPackageVersionRelation.Newer;
|
|
}
|
|
if (_removeActions.TryGetValue(package.Key, out var remove))
|
|
remove.Disabled = !hasInstalled;
|
|
}
|
|
_output.Text = "Direct packages: " + string.Join(", ", installed.Select(item => $"{item.Key}@{item.Value}"));
|
|
}
|
|
|
|
private void ShowFailure(Exception exception)
|
|
{
|
|
_status!.Text = "CodeGen: operation failed";
|
|
_output!.Text = exception.ToString();
|
|
GD.PushError(exception.ToString());
|
|
}
|
|
}
|