Skip to content

Commit 302f914

Browse files
committed
feat: cli build 命令
1 parent 3abfc40 commit 302f914

2 files changed

Lines changed: 131 additions & 0 deletions

File tree

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
using System.ComponentModel;
2+
using System.Text.RegularExpressions;
3+
using MaiChartManager.CLI.Utils;
4+
using MaiChartManager.Utils;
5+
using Spectre.Console;
6+
using Spectre.Console.Cli;
7+
8+
namespace MaiChartManager.CLI.Commands;
9+
10+
public partial class MakeAbCommand : AsyncCommand<MakeAbCommand.Settings>
11+
{
12+
[GeneratedRegex(@"^(?<id>\d+)\.(png|jpg|jpeg)$", RegexOptions.IgnoreCase)]
13+
private static partial Regex NumericFileRegex();
14+
15+
[GeneratedRegex(@"^ui_jacket_(?<id>\d+)\.(png|jpg|jpeg)$", RegexOptions.IgnoreCase)]
16+
private static partial Regex UiJacketFileRegex();
17+
18+
public class Settings : CommandSettings
19+
{
20+
[CommandArgument(0, "<folder>")]
21+
[Description("包含封面图片的文件夹路径")]
22+
public string Folder { get; set; } = "";
23+
24+
public override ValidationResult Validate()
25+
{
26+
if (!Directory.Exists(Folder))
27+
return ValidationResult.Error($"文件夹不存在: {Folder}");
28+
29+
return ValidationResult.Success();
30+
}
31+
}
32+
33+
public override async Task<int> ExecuteAsync(CommandContext context, Settings settings, CancellationToken cancellationToken)
34+
{
35+
var candidates = Directory.EnumerateFiles(settings.Folder)
36+
.Select(path => (Path: path, Name: Path.GetFileName(path)))
37+
.Select(x =>
38+
{
39+
var m = NumericFileRegex().Match(x.Name);
40+
if (m.Success) return (x.Path, Id: m.Groups["id"].Value);
41+
42+
m = UiJacketFileRegex().Match(x.Name);
43+
if (m.Success) return (x.Path, Id: m.Groups["id"].Value);
44+
45+
return (Path: (string?)null, Id: (string?)null);
46+
})
47+
.Where(x => x.Path is not null)
48+
.ToList();
49+
50+
if (candidates.Count == 0)
51+
{
52+
AnsiConsole.MarkupLine("[red]✗ 未找到有效的图片文件(需要:纯6位数字文件名或 ui_jacket_xxxxxx 格式,PNG/JPG)[/]");
53+
return 1;
54+
}
55+
56+
var jacketDir = Path.Combine(settings.Folder, "jacket");
57+
var jacketSmallDir = Path.Combine(settings.Folder, "jacket_s");
58+
Directory.CreateDirectory(jacketDir);
59+
Directory.CreateDirectory(jacketSmallDir);
60+
61+
AnsiConsole.MarkupLine($"[yellow]找到 {candidates.Count} 张图片,开始转换...[/]");
62+
63+
var errors = new List<string>();
64+
65+
await AnsiConsole.Progress()
66+
.AutoClear(false)
67+
.Columns(
68+
new TaskDescriptionColumn(),
69+
new ProgressBarColumn(),
70+
new PercentageColumn(),
71+
new SpinnerColumn())
72+
.StartAsync(async ctx =>
73+
{
74+
var task = ctx.AddTask("转换中", maxValue: candidates.Count);
75+
76+
foreach (var (path, id) in candidates)
77+
{
78+
task.Description = $"[green]ui_jacket_{id}[/]";
79+
80+
try
81+
{
82+
await Task.Run(() =>
83+
{
84+
AssetBundleCreator.CreateTextureAssetBundle(
85+
path!,
86+
Path.Combine(jacketDir, $"ui_jacket_{id}.ab"),
87+
$"UI_Jacket_{id}",
88+
$"assets/assetbundle/jacket/ui_jacket_{id}.png",
89+
$"jacket/ui_jacket_{id}.ab");
90+
91+
AssetBundleCreator.CreateTextureAssetBundle(
92+
path!,
93+
Path.Combine(jacketSmallDir, $"ui_jacket_{id}_s.ab"),
94+
$"UI_Jacket_{id}_s",
95+
$"assets/assetbundle/jacket_s/ui_jacket_{id}_s.png",
96+
$"jacket_s/ui_jacket_{id}_s.ab",
97+
resizeWidth: 200,
98+
resizeHeight: 200);
99+
}, cancellationToken);
100+
}
101+
catch (Exception ex)
102+
{
103+
SentrySdk.CaptureException(ex);
104+
errors.Add($"{Path.GetFileName(path!)}: {ex.Message}");
105+
}
106+
107+
task.Increment(1);
108+
TerminalProgress.Set((int)(task.Value * 100 / task.MaxValue));
109+
}
110+
111+
TerminalProgress.Clear();
112+
});
113+
114+
if (errors.Count > 0)
115+
{
116+
AnsiConsole.MarkupLine($"[red]✗ {errors.Count}/{candidates.Count} 个文件转换失败:[/]");
117+
foreach (var e in errors)
118+
AnsiConsole.MarkupLine($"[red] {e}[/]");
119+
return 1;
120+
}
121+
122+
AnsiConsole.MarkupLine($"[green]✓ {candidates.Count} 张图片全部转换成功![/]");
123+
AnsiConsole.MarkupLine($"[green] jacket → {jacketDir}[/]");
124+
AnsiConsole.MarkupLine($"[green] jacket_s → {jacketSmallDir}[/]");
125+
return 0;
126+
}
127+
}

MaiChartManager.CLI/Program.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,10 @@
5656
.WithExample("makeacb", "audio.mp3", "-O", "output.acb")
5757
.WithExample("makeacb", "audio1.wav", "audio2.mp3", "--padding", "0.5");
5858

59+
config.AddCommand<MakeAbCommand>("makeab")
60+
.WithDescription("将文件夹中的封面图片批量转换为 AssetBundle 格式")
61+
.WithExample("makeab", "D:\\images");
62+
5963
config.AddCommand<DebugCommand>("debug")
6064
.WithDescription("以控制台模式启动主程序,用于查看日志输出");
6165
});

0 commit comments

Comments
 (0)