Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 54 additions & 3 deletions EditorReaderHarness/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ private static void RunCommand(string cmd)
case "M": ErrorMonitor(); break;
case "C": CompareCandidateChecks(); break;
case "Z": ForceScanCheck(); break;
case "H": ScanHotColdCompare(); break;
case "W":
case "y":
// 手动触发:等待/附加 osu! + 输出诊断报告。
Expand Down Expand Up @@ -494,7 +495,7 @@ private static FailureTally RunStress(int milliseconds, int intervalMs, bool fet
_reader.FetchAll(fetchFull);
string? why = Snapshot.Validate(_reader, out int rejects, out var reasons);
ok = why == null;
if (!ok)
if (why != null)
{
tally.Bucket(why);
foreach (var kv in reasons) tally.RejectReasons[kv.Key] = tally.RejectReasons.GetValueOrDefault(kv.Key) + kv.Value;
Expand Down Expand Up @@ -1734,8 +1735,6 @@ void R(string what, IntPtr address, byte[] buf, int size)
}
}

int ptr(uint v) => (int)v;

// ---- SetEditor 之后的部分:FetchHOM / FetchBeatmap / FetchControlPoints / FetchObjects
R("pEditor+28 (HOM)", _reader.EditorAddress + 28, b4, 4);
int pHom = BitConverter.ToInt32(b4, 0);
Expand Down Expand Up @@ -3140,6 +3139,58 @@ private static void ForceScanCheck()
}
}

// ------------------------------------------------------------------ 扫描热/冷路径对比

/// <summary>
/// 对比冷扫描(lastFoundRegionBase 被清空,从第 0 个区域开始)与热扫描
/// (沿用上次命中的区域优先)的耗时与扫描区域数。
/// 用于回答环形游标 / 区域退避这类机制在 Windows 上到底有没有收益。
/// </summary>
private static void ScanHotColdCompare()
{
if (_osu == null) Attach();
if (_hProcess == IntPtr.Zero) { WriteLine("未附加到 osu!"); return; }

WriteLine("冷/热扫描对比:ResetEditor 会清掉命中区域记忆,因此下一次是冷扫描。");
WriteLine("对比耗时与实际扫描区域数(区域数越少,说明优先扫描省得越多)。\n");

var coldMs = new List<long>();
var coldRegions = new List<long>();
var hotMs = new List<long>();
var hotRegions = new List<long>();

for (int i = 0; i < 5; i++)
{
_reader.ResetEditor();
var sw = Stopwatch.StartNew();
try { _reader.SetEditor(); } catch (Exception ex) { WriteLine(" 冷扫描失败: " + ex.Message); continue; }
sw.Stop();
coldMs.Add(sw.ElapsedMilliseconds);
coldRegions.Add(_reader.DiagScanRegionsScanned);

sw.Restart();
try { _reader.SetEditor(); } catch (Exception ex) { WriteLine(" 热扫描失败: " + ex.Message); continue; }
sw.Stop();
hotMs.Add(sw.ElapsedMilliseconds);
hotRegions.Add(_reader.DiagScanRegionsScanned);
}

string FmtMs(List<long> xs) => xs.Count == 0 ? "(无数据)" : $"平均 {xs.Average():F0} ms [{string.Join(", ", xs)}]";
string FmtRegions(List<long> xs) => xs.Count == 0 ? "(无数据)" : $"平均 {xs.Average():F0} [{string.Join(", ", xs)}]";

WriteLine($"冷扫描(从区域 0 开始): {FmtMs(coldMs)}");
WriteLine($" 扫描区域数: {FmtRegions(coldRegions)}");
WriteLine($"热扫描(命中区域优先): {FmtMs(hotMs)}");
WriteLine($" 扫描区域数: {FmtRegions(hotRegions)}");
WriteLine();
if (coldMs.Count > 0 && hotMs.Count > 0)
{
WriteLine($"节省: {coldMs.Average() - hotMs.Average():F0} ms / 次,区域数差 {coldRegions.Average() - hotRegions.Average():F0} 个");
}
WriteLine();
WriteLine("说明:扫描只在绑定失效或编辑器被重建时发生,正常运行时不会反复扫。");
}

// ------------------------------------------------------------------ 8. 重试修复测试

private static void RetryHealTest()
Expand Down
6 changes: 1 addition & 5 deletions osucatch-editor-realtimeviewer/BeatmapConverterOsuStable.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using osu.Game.Beatmaps;
using osu.Game.Beatmaps;
using osu.Game.Rulesets.Catch.Beatmaps;
using osu.Game.Rulesets.Catch.Objects;
using System.Globalization;
Expand All @@ -15,10 +15,6 @@ public override List<PalpableCatchHitObject> GetPalpableObjects(IBeatmap beatmap
Log.ConsoleLog("Building hitobjects.", Log.LogType.BeatmapConverter, Log.LogLevel.Debug);
HitObjectManagerCatch manager = new(beatmap, mods, false);

float? lastPosition = null;
double lastStartTime = 0;
bool isFirstSame = true;

int sourceIndex = 0;
foreach (var currentObject in beatmap.HitObjects)
{
Expand Down
20 changes: 14 additions & 6 deletions osucatch-editor-realtimeviewer/BookmarkPlus.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System.Reflection;
using System.Reflection;
using System.Text.Json;
using System.Text.Json.Serialization;

Expand All @@ -21,12 +21,14 @@ public class LineStyle : IComparable

[JsonConverter(typeof(ColorConverter))]
public Color Color { get; set; }
public string Comment { get; set; }

/// <summary>线条说明文字(如 HyperDash);没写过时为空字符串而不是 null(设置窗口直接读它填文本框)。</summary>
public string Comment { get; set; } = "";

public int CompareTo(object? lineStyle)
{
if (lineStyle == null) return 1;
LineStyle otherLineStyle = lineStyle as LineStyle;
LineStyle? otherLineStyle = lineStyle as LineStyle;
if (otherLineStyle == null) throw new ArgumentException("Object is not a LineStyle.");
return otherLineStyle.Id - Id;
}
Expand All @@ -40,7 +42,7 @@ public class Bookmark : IComparable
public int CompareTo(object? bookmark)
{
if (bookmark == null) return 1;
Bookmark otherBookmark = bookmark as Bookmark;
Bookmark? otherBookmark = bookmark as Bookmark;
if (otherBookmark == null) throw new ArgumentException("Object is not a Bookmark.");
return (int)(otherBookmark.Time - Time);
}
Expand Down Expand Up @@ -296,8 +298,14 @@ public class BookmarkManager
{
public List<Bookmark> Bookmarks { get; set; } = new();

public string BeatmapFolder;
public string BeatmapFilename;
/// <summary>
/// 当前书签对应的谱面位置;还没绑定到任何谱面时为空字符串
/// (调用方用 <c>== ""</c> 判断“编辑器没在运行 / 还没读到谱面”)。
/// </summary>
public string BeatmapFolder = "";

/// <inheritdoc cref="BeatmapFolder"/>
public string BeatmapFilename = "";

public BookmarkManager()
{
Expand Down
13 changes: 7 additions & 6 deletions osucatch-editor-realtimeviewer/Canvas.cs
Original file line number Diff line number Diff line change
Expand Up @@ -622,7 +622,7 @@ private static void DrawJudgementLine()
{
double baseY = (screensContain > 1) ? 240.0 * screensContain : 408;
DrawingHelper drawing = Form1.drawingHelper;
double y = JudgementLineY(baseY, drawing.FixedPreviewTime, drawing.EditorTime, drawing.CurrentTime, drawing.TimePerPixels);
double y = JudgementLineY(baseY, drawing.FixedPreviewTime, drawing.EditorTime, drawing.CurrentTime, drawing.PixelsPerMs);

Vector2 rp0 = new Vector2(64, (float)y);
Vector2 rp1 = new Vector2(576, (float)y);
Expand All @@ -631,15 +631,16 @@ private static void DrawJudgementLine()

/// <summary>
/// 判定线(当前时刻线)在画面上的 Y 坐标。
/// 正常模式:画在判定线本身的位置(当前时刻所在高度)。
/// 正常模式:画在判定线本身的位置(当前时刻所在高度,垂直缩放的基准,因此不受缩放影响)。
/// 固定预览时刻:画面停在预览时刻,判定线改为按 editor 时刻在画面上的位置绘制
/// (换算方式与绘制物件完全一致:<c>baseY - (time - CurrentTime) / TimePerPixels</c>),
/// (换算方式与绘制物件完全一致:<c>baseY - (time - CurrentTime) × PixelsPerMs</c>,
/// 其中 <see cref="DrawingHelper.PixelsPerMs"/> 已含垂直缩放),
/// 这样固定预览时也能一眼看出当前编辑位置在画面的哪里。
/// </summary>
private static double JudgementLineY(double baseY, bool fixedPreviewTime, double editorTime, double currentTime, double timePerPixels)
private static double JudgementLineY(double baseY, bool fixedPreviewTime, double editorTime, double currentTime, double pixelsPerMs)
{
if (!fixedPreviewTime || !(timePerPixels > 0)) return baseY;
return baseY - (editorTime - currentTime) / timePerPixels;
if (!fixedPreviewTime || !(pixelsPerMs > 0)) return baseY;
return baseY - (editorTime - currentTime) * pixelsPerMs;
}
}
}
Loading
Loading