Repository navigation
Expand file tree
/
Copy pathPreviewQueue.cs
More file actions
108 lines (96 loc) · 3.74 KB
/
Copy pathPreviewQueue.cs
File metadata and controls
108 lines (96 loc) · 3.74 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
using System.Collections.Generic;
using UnityEngine;
namespace HTFToolkit
{
/// <summary>
/// 图鉴预览分帧渲染队列。
/// v1.9.8 关键改动:Unity 6000 URP RenderGraph 下,SubmitRenderRequest 的实际 GPU 渲染
/// 在帧末才执行 → 必须"延迟一帧读取"(布置帧 → 帧末渲染 → 下帧 ReadPixels)。
/// 流程:每帧布置 1 个(RT 共享,同帧布置多个只有最后一个留在 RT)+ 结算上一帧布置的。
/// 官方文档明确要求:读 RT 前需等帧末(WaitForEndOfFrame 或 endContextRendering),
/// "read right after Render() and wonder why it's empty → you're too early"。
/// </summary>
internal static class PreviewQueue
{
private sealed class Job
{
public Item Item;
public int SkinIndex; // -1 = 默认外观
public string Key;
}
private static readonly Queue<Job> _jobs = new Queue<Job>();
private static readonly Dictionary<string, Texture2D> _cache = new Dictionary<string, Texture2D>();
private static Job _staged; // 上一帧布置、等待本帧结算的 job
public static void Reset()
{
_jobs.Clear();
_cache.Clear();
_staged = null;
}
/// <summary>请求全部物品的默认外观预览(-1)或全部皮肤预览(索引 0..N)。</summary>
public static void RequestAll(List<Item> items, bool skins)
{
foreach (Item it in items)
{
if (it == null)
continue;
if (!skins)
{
Enqueue(it, -1);
}
else if (it.SkinPreset != null)
{
for (int i = 0; i < it.SkinPreset.Skins.Count; i++)
Enqueue(it, i);
}
}
}
private static void Enqueue(Item item, int skinIndex)
{
string key = KeyOf(item, skinIndex);
if (_cache.ContainsKey(key))
return;
_jobs.Enqueue(new Job { Item = item, SkinIndex = skinIndex, Key = key });
}
private static string KeyOf(Item item, int skinIndex)
{
return item.name + "|" + skinIndex;
}
/// <summary>每帧调用:发起上一帧布置的读取 + 布置一个新的。返回是否还有未完成任务。</summary>
public static bool Process()
{
// 1) 发起上一帧布置的读取(AsyncGPUReadback 异步,完成后经事件写 cache)
if (_staged != null)
{
SkinPreview.RequestStagedRead();
_staged = null;
}
// 2) 布置本帧的一个(RT 共享,同帧布置多个只有最后一个留下)
if (_jobs.Count > 0)
{
Job job = _jobs.Dequeue();
if (!_cache.ContainsKey(job.Key))
{
SkinPreview.Stage(job.Item, job.SkinIndex, job.Key);
_staged = job;
}
}
return _jobs.Count > 0 || _staged != null;
}
static PreviewQueue()
{
// 异步回读完成 → 写入缓存
SkinPreview.StagedTexReady += (key, tex) =>
{
if (tex != null && !_cache.ContainsKey(key))
_cache[key] = tex;
};
}
public static Texture2D Get(Item item, int skinIndex = -1)
{
_cache.TryGetValue(KeyOf(item, skinIndex), out Texture2D tex);
return tex;
}
public static int PendingCount => _jobs.Count + (_staged != null ? 1 : 0);
}
}