Skip to content

Commit 034a4f9

Browse files
committed
fix: EGL surface validation, UI scale fixes, startup perf
- Add Egl.GetError() check after ImGui render to detect abandoned surfaces - Remove close button (×) from main window (ImGui.Begin without ref) - Defer ApplyConfig to first Render to avoid pre-context ImGui access - Scale ImGui styles (FramePadding, ItemSpacing, etc.) with font scale - ApplyStyleScale called on slider change for live button resizing - Switch ModManagerConfig.Load to Newtonsoft.Json (~2s faster startup) - Add Managed.cs startup timing (Stopwatch, single total line) - Add Benchmark class (Begin/End with Action<double>) - Guard all ImGuiInputHandler callbacks with IsInitialized flag - ImGuiEGLRender.CreateContext sets ImGuiInputHandler.IsInitialized = true - Fix ModManager.extractRuntime assets path ("runtime/" prefix) - ModManagerUpdater: add useNewThread param, adjust log levels, remove debug logs - Mods directory setting: text-only display, remove fixed-size buttons - Remove LoadPriority from IModPlugin/ModEntry/ModLoader
1 parent d26757a commit 034a4f9

13 files changed

Lines changed: 313 additions & 155 deletions

File tree

‎Android/library/src/main/java/starray/android/modmanager/ModManager.java‎

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ public int start(String dll, String type, String method,String... args) {
4444
}
4545

4646
private void extractRuntime(){
47-
if (Files.exists(Paths.get(runtimeDir))){
47+
if (Files.exists(Paths.get(runtimeDir, "System.Private.CoreLib.dll"))){
4848
return;
4949
}
5050
try {
@@ -54,8 +54,10 @@ private void extractRuntime(){
5454
Files.createDirectories(Paths.get(runtimeDir));
5555
}
5656
for (String dll : Objects.requireNonNull(dlls)) {
57-
var fis = activity.getAssets().open(dll);
58-
OutputStream out = new FileOutputStream(Paths.get(runtimeDir,new File(dll).getName()).toFile());
57+
var fis = activity.getAssets().open("runtime/" + dll);
58+
File outputDll = Paths.get(runtimeDir,new File(dll).getName()).toFile();
59+
outputDll.createNewFile();
60+
OutputStream out = new FileOutputStream(outputDll);
5961
{
6062
byte[] buffer = new byte[8192];
6163
int length;

‎Android/library/src/main/java/starray/android/modmanager/ModManagerUpdater.java‎

Lines changed: 195 additions & 105 deletions
Large diffs are not rendered by default.

‎Scripts/push_and_run.sh‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
TARGET_PATH="//sdcard/ModManager/manager"
1+
TARGET_PATH="//sdcard/ADOFAI/ModManager/manager"
22
dotnet build
33
adb push StArray.ModManager/bin/Debug/net10.0/StArray.ModManager.dll $TARGET_PATH/StArray.ModManager.dll
44
adb shell am force-stop com.DefaultCompany.Simple3D

‎StArray.ModManager/Managed.cs‎

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using System.Reflection;
1+
using System.Diagnostics;
2+
using System.Reflection;
23
using System.Runtime.CompilerServices;
34
using System.Runtime.InteropServices;
45
using StArray.ModManager.Manager;
@@ -11,23 +12,10 @@ namespace StArray.ModManager;
1112
/// <summary>CoreCLR entry / 加载器入口 — called by native delegate</summary>
1213
public static class Managed
1314
{
15+
public static string AssemblyPath = string.Empty;
1416
[UnmanagedCallersOnly(CallConvs = [typeof(CallConvCdecl)])]
1517
public static int Entry(int argc, IntPtr argv)
1618
{
17-
string[] args = new string[argc];
18-
for (int i = 0; i < argc; i++)
19-
{
20-
IntPtr pStr = Marshal.ReadIntPtr(argv, i * IntPtr.Size);
21-
args[i] = Marshal.PtrToStringUTF8(pStr)!;
22-
}
23-
24-
string modsPath = args.Length > 0
25-
? args[0]
26-
: Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)!, "..", "mods");
27-
28-
if (!Directory.Exists(modsPath))
29-
Directory.CreateDirectory(modsPath);
30-
3119
// 桥接 Logger → Android logcat
3220
Logger.OnLog += (level, tag, msg) =>
3321
{
@@ -41,10 +29,31 @@ public static int Entry(int argc, IntPtr argv)
4129
};
4230
AndroidUtils.Write(prio, tag, msg);
4331
};
32+
var sw = Stopwatch.StartNew();
33+
34+
string[] args = new string[argc];
35+
for (int i = 0; i < argc; i++)
36+
{
37+
IntPtr pStr = Marshal.ReadIntPtr(argv, i * IntPtr.Size);
38+
args[i] = Marshal.PtrToStringUTF8(pStr)!;
39+
}
40+
41+
string modsPath = args.Length > 0
42+
? args[0]
43+
: Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)!, "..", "mods");
44+
AssemblyPath = Path.Combine(Path.GetDirectoryName(modsPath), "manager", typeof(Managed).Namespace + ".dll");
45+
if (!Directory.Exists(modsPath))
46+
Directory.CreateDirectory(modsPath);
47+
48+
4449

4550
var loader = new ModLoader(modsPath);
46-
ImGuiEGLRender.OnRender += new ModManagerUI(loader).Render;
51+
var ui = new ModManagerUI(loader);
52+
ImGuiEGLRender.OnRender += ui.Render;
4753
ImGuiEGLRender.Install();
54+
55+
sw.Stop();
56+
Logger.Error(nameof(Managed), $"Startup completed in {sw.Elapsed.TotalSeconds:F3}s");
4857
return 0;
4958
}
5059
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
using System.Diagnostics;
2+
3+
namespace StArray.ModManager.Manager;
4+
5+
/// <summary>
6+
/// 轻量计时 — Begin 启动,End 传入 Action&lt;double&gt; 打印耗时
7+
/// <code>
8+
/// Benchmark.Begin();
9+
/// // ... work ...
10+
/// Benchmark.End(s => Logger.Info("Foo", $"done in {s:F3}s"));
11+
/// </code>
12+
/// </summary>
13+
public static class Benchmark
14+
{
15+
[ThreadStatic] private static Stopwatch? _sw;
16+
17+
public static void Begin()
18+
{
19+
_sw = Stopwatch.StartNew();
20+
}
21+
22+
public static void End(Action<double> onDone)
23+
{
24+
if (_sw == null) return;
25+
_sw.Stop();
26+
onDone(_sw.Elapsed.TotalSeconds);
27+
}
28+
}

‎StArray.ModManager/Manager/ModManagerConfig.cs‎

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System.Text.Json;
2+
using Newtonsoft.Json;
23

34
namespace StArray.ModManager.Manager;
45

@@ -24,16 +25,16 @@ public class ModManagerConfig
2425

2526
private const string FileName = "modmanager_config.json";
2627

27-
/// <summary>保存到指定目录</summary>
28+
/// <summary>保存到指定目录(System.Text.Json)</summary>
2829
public void Save(string directory)
2930
{
3031
var path = Path.Combine(directory, FileName);
31-
var json = JsonSerializer.Serialize(this,
32-
new JsonSerializerOptions { WriteIndented = true, IncludeFields = true });
32+
var json = System.Text.Json.JsonSerializer.Serialize(this,
33+
new System.Text.Json.JsonSerializerOptions { WriteIndented = true, IncludeFields = true });
3334
File.WriteAllText(path, json);
3435
}
3536

36-
/// <summary>从指定目录加载,失败返回默认</summary>
37+
/// <summary>从指定目录加载(Newtonsoft.Json),失败返回默认</summary>
3738
public static ModManagerConfig Load(string directory)
3839
{
3940
var path = Path.Combine(directory, FileName);
@@ -42,9 +43,8 @@ public static ModManagerConfig Load(string directory)
4243
if (File.Exists(path))
4344
{
4445
var json = File.ReadAllText(path);
45-
Console.WriteLine(json);
46-
return JsonSerializer.Deserialize<ModManagerConfig>(json,
47-
new JsonSerializerOptions { IncludeFields = true }) ?? new ModManagerConfig();
46+
return JsonConvert.DeserializeObject<ModManagerConfig>(json)
47+
?? new ModManagerConfig();
4848
}
4949
}
5050
catch { /* ignore corrupt config */ }

‎StArray.ModManager/Manager/ModManagerUI.Panels.cs‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ private void RenderModSettingsWindow()
6666
ImGui.Spacing();
6767
ImGui.Separator();
6868

69-
if (ImGui.Button(FontAwesome7.FloppyDisk + " " + L10n.Get("Btn.Save"), new Vector2(100, 0)))
69+
if (ImGui.Button(FontAwesome7.FloppyDisk + " " + L10n.Get("Btn.Save")))
7070
{
7171
SaveSettings(mod, settings);
7272
}
@@ -167,7 +167,7 @@ private void RenderAddModPopup()
167167
ImGui.Text(L10n.Get("AddMod_NotImplDetail"));
168168

169169
ImGui.Spacing();
170-
if (ImGui.Button(L10n.Get("Btn_Close"), new Vector2(100, 0)))
170+
if (ImGui.Button(L10n.Get("Btn_Close")))
171171
_showAddModPopup = false;
172172

173173
ImGui.EndPopup();

‎StArray.ModManager/Manager/ModManagerUI.cs‎

Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -20,24 +20,24 @@ public partial class ModManagerUI
2020
private readonly string _configDir;
2121

2222
private bool _showAddModPopup;
23-
private bool _showMainWindow = true;
2423
private string? _expandedModId;
2524

2625
// 通知
2726
private string _toastMessage = string.Empty;
2827
private float _toastTimer;
2928

29+
private bool _configApplied;
30+
3031
public ModManagerUI(ModLoader modManager)
3132
{
3233
_modManager = modManager;
3334
Logger.OnLog += OnLogMessage;
3435

35-
// 配置与 DLL 同目录
36-
_configDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)!;
36+
_configDir = Path.GetDirectoryName(Managed.AssemblyPath)!;
3737
_config = ModManagerConfig.Load(_configDir);
3838
if (string.IsNullOrEmpty(_config.ModsDirectory))
3939
_config.ModsDirectory = _modManager.ModsDirectory;
40-
ApplyConfig();
40+
_modManager.ScanMods();
4141
AutoEnableMods();
4242
}
4343

@@ -48,6 +48,18 @@ private void ApplyConfig()
4848
var style = ImGui.GetStyle();
4949
style.GrabMinSize = _config.GrabMinSize;
5050
style.ScrollbarSize = _config.ScrollbarSize;
51+
ApplyStyleScale();
52+
}
53+
54+
private void ApplyStyleScale()
55+
{
56+
float scale = ImGui.GetIO().FontGlobalScale / 2f;
57+
var style = ImGui.GetStyle();
58+
style.FramePadding = new Vector2(4f * scale, 3f * scale);
59+
style.ItemSpacing = new Vector2(8f * scale, 4f * scale);
60+
style.ItemInnerSpacing = new Vector2(4f * scale, 4f * scale);
61+
style.FrameRounding = 3f * scale;
62+
style.WindowPadding = new Vector2(8f * scale, 8f * scale);
5163
}
5264

5365
/// <summary>保存管理器全局配置</summary>
@@ -103,6 +115,11 @@ private void OnLogMessage(Logger.Level level, string tag, string msg)
103115
/// </summary>
104116
public void Render()
105117
{
118+
if (!_configApplied)
119+
{
120+
ApplyConfig();
121+
_configApplied = true;
122+
}
106123
RenderMainWindow();
107124
RenderModSettingsWindow();
108125
RenderAddModPopup();
@@ -111,11 +128,8 @@ public void Render()
111128

112129
private void RenderMainWindow()
113130
{
114-
if (!_showMainWindow) return;
115-
116131
ImGui.SetNextWindowSize(new Vector2(680, 650), ImGuiCond.FirstUseEver);
117-
if (ImGui.Begin(L10n.Get("MainWindow_Title"), ref _showMainWindow))
118-
{
132+
ImGui.Begin(L10n.Get("MainWindow_Title"));
119133
ImGui.PushTextWrapPos();
120134
if (ImGui.BeginTabBar("MainTabs"))
121135
{
@@ -217,17 +231,16 @@ private void RenderMainWindow()
217231

218232
if (ImGui.BeginTabItem(L10n.Get("Tab_Settings")))
219233
{
220-
var dir = _config.ModsDirectory;
221-
ImGui.Text(L10n.Get("Settings_ModsDir"));
222-
ImGui.SameLine();
223-
ImGui.InputText("##modsDir", ref dir, 500);
224-
if (dir != _config.ModsDirectory) _config.ModsDirectory = dir;
234+
ImGui.Text(L10n.Get("Settings_ModsDir") + " " + _config.ModsDirectory);
225235
ImGui.Separator();
226236

227237
ImGui.Text(L10n.Get("Settings_UiScale"));
228238
float uiscale = ImGui.GetIO().FontGlobalScale;
229239
if (ImGui.SliderFloat("##uiscale", ref uiscale, 1f, 5f, "%.1f"))
240+
{
230241
ImGui.GetIO().FontGlobalScale = uiscale;
242+
ApplyStyleScale();
243+
}
231244

232245
var style = ImGui.GetStyle();
233246
ImGui.Text(L10n.Get("Settings_GrabSize"));
@@ -241,7 +254,7 @@ private void RenderMainWindow()
241254
style.ScrollbarSize = scrollW;
242255

243256
ImGui.Separator();
244-
if (ImGui.Button($"{FontAwesome7.FloppyDisk} 保存设置", new Vector2(120, 0)))
257+
if (ImGui.Button($"{FontAwesome7.FloppyDisk} 保存设置"))
245258
{
246259
SaveConfig();
247260
_toastMessage = $"{FontAwesome7.CircleCheck} 设置已保存";
@@ -264,7 +277,6 @@ private void RenderMainWindow()
264277
ImGui.EndTabBar();
265278
}
266279
ImGui.PopTextWrapPos();
267-
}
268280
ImGui.End();
269281
}
270282

‎StArray.ModManager/StArray.ModManager.csproj‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,13 @@
1313
</PropertyGroup>
1414

1515
<ItemGroup>
16+
<PackageReference Include="Newtonsoft.Json" Version="13.0.4" />
1617
<PackageReference Include="OpenTK.Graphics" Version="4.9.4" />
1718
<PackageReference Include="ImGui.NET" Version="1.91.6.1" />
1819
</ItemGroup>
1920

2021
<ItemGroup>
22+
<Folder Include="Extensions\" />
2123
<Folder Include="Model\" />
2224
<Folder Include="Resources\" />
2325
<EmbeddedResource Include="Resources\fa-solid-900.ttf" />

‎StArray.ModManager/UI/ImGuiEGLRender.cs‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,9 @@ public static int OnSwapBuffers(IntPtr display, IntPtr surface)
9292
var self = s_instance!;
9393
try
9494
{
95+
// 检查 surface 是否仍然有效
96+
Egl.GetError(); // 清除之前的错误
97+
9598
// 使用 EGL 查询 surface 尺寸
9699
if (!Egl.QuerySurface(display, surface, Egl.WIDTH, out var width) ||
97100
!Egl.QuerySurface(display, surface, Egl.HEIGHT, out var height))
@@ -124,6 +127,13 @@ public static int OnSwapBuffers(IntPtr display, IntPtr surface)
124127
// 渲染
125128
ImGui.Render();
126129
ImGuiImplOpenGL3.RenderDrawData((IntPtr)ImGui.GetDrawData().NativePtr);
130+
131+
// 渲染后检查 surface 是否已被废弃
132+
var err = Egl.GetError();
133+
if (err != ErrorCode.SUCCESS)
134+
{
135+
Logger.Warn(nameof(ImGuiEGLRenderer), $"EGL error after render: 0x{err:X}");
136+
}
127137
}
128138
catch (Exception ex)
129139
{
@@ -151,6 +161,7 @@ private void InitImGui(IntPtr display, IntPtr surface)
151161

152162
// 创建 ImGui 上下文
153163
ImGui.CreateContext();
164+
ImGuiInputHandler.IsInitialized = true;
154165

155166
var io = ImGui.GetIO();
156167
io.ConfigFlags |= ImGuiConfigFlags.NavEnableKeyboard;

0 commit comments

Comments
 (0)