using System.Collections.Generic; using System.Linq; using Decentralized.Domain; using TMPro; using UnityEngine; using UnityEngine.UI; namespace Decentralized { /// /// 放大镜检视显卡:和香烟一样把物品放大摆在检视台上,正反面各一张,下面是标签栏。 /// 标签栏每行一个标签(型号、风扇、金手指、挡板、丝印、贴纸):左边是卖家的说法,右边的按钮"指出"—— /// 说法属实就没事,隐瞒了问题价格回到真实情况,指错了掉信誉。归自己的卡,有标签机时按钮改成"改",随便改说法。 /// 游戏没有给 mod 开放检视界面,这里不打补丁,只在检视台(InspectionUIManager.panel)下面挂一个自己的界面, /// 用一个常驻的 MonoBehaviour 每帧看一眼是否正在检视显卡。 /// public sealed class GpuInspectView : MonoBehaviour { private const float RowH = 30f, CardScale = 3f, PanelTop = -112f, DetailH = 26f, GroupGap = 8f; private const int RowCount = 5; private TextMeshProUGUI detailText; private static GpuInspectView instance; private RectTransform root, cardRoot; private Button flip; private TextMeshProUGUI flipText; private GameItem shown; private string shownSig; private bool hidGlass; private Transform buttonTemplate; private TMP_FontAsset font; private readonly TextMeshProUGUI[] rowName = new TextMeshProUGUI[RowCount], rowText = new TextMeshProUGUI[RowCount]; private readonly Button[] rowButton = new Button[RowCount]; private readonly TextMeshProUGUI[] rowButtonText = new TextMeshProUGUI[RowCount]; private TextMeshProUGUI serialText; public static void Ensure() { if (instance != null) return; var go = new GameObject("pd_gpu_inspect_view"); DontDestroyOnLoad(go); instance = go.AddComponent(); } public static void Remove() { if (instance != null) Destroy(instance.gameObject); instance = null; } private void Update() { var m = InspectionUIManager.Instance; var item = m != null && m.panel != null && m.panel.activeSelf ? m.currentInspectingItem : null; if (item == null || !Items.IsGpu(item)) { if (root != null && root.gameObject.activeSelf) root.gameObject.SetActive(false); shown = null; if (hidGlass && m != null && m.magnifyingGlass != null) { m.magnifyingGlass.SetActive(true); hidGlass = false; } return; } Log.Guard("显卡检视大图", () => { if (root == null) Build(m); if (!root.gameObject.activeSelf) root.gameObject.SetActive(true); // 检视台自带的放大镜图标会压在大图下面,显卡用不着 if (m.magnifyingGlass != null && m.magnifyingGlass.activeSelf) { m.magnifyingGlass.SetActive(false); hidGlass = true; } var keys = new List(); string sig = Items.LookKeys(item, keys) + "|" + string.Join(",", keys) + "|" + item.unitValue + "|" + Items.Exposed(item) + "|" + (Items.GetClaim(item)?.Encode() ?? "") + "|" + GeneralHelper.IsItemOwned(item) + "|" + HasLabeler(); if (item != shown || sig != shownSig) { shown = item; shownSig = sig; Redraw(item); UpdateRows(item); } }); } /// 检视台上的叠加层:每个标签的每个取值对应一种细节,一一对应。 public static List BigOverlays(GameItem item) { var o = new List(); var u = Items.ToUnit(item); if (u.Dead) return o; var l = u.Appearance; string P = "gpu_big_ov_"; if (!Items.IsBack(item)) { int n = Items.FansOf(u); if (l.Fan == 1) o.Add(P + "fan_dust2_" + n); if (l.Fan == 2) { o.Add(P + "fan_dust1_" + n); o.Add(P + "fan_chip_" + n); } if (l.Fingers == 1) o.Add(P + "fin_dim"); if (l.Fingers == 2) o.Add(P + "fin_oxide"); if (l.Bracket == 1) o.Add(P + "brk_scratch"); } else { string model = (l.Print == 1 && u.FakeOf != null ? u.FakeOf : u.Model).ToLowerInvariant(); o.Add(P + "print_" + (l.Print == 2 ? "skew_" : l.Print == 1 ? "stamp_" : "normal_") + model); if (l.Sticker == 2) o.Add(P + "seal_missing"); } return o; } private static bool HasLabeler() => EmporiumEntry.Instance != null && EmporiumEntry.Instance.GetAllOwnedItemsByTag("LABELER_TAG").Count > 0; private static void MakeRect(Transform parent, string name, Vector2 pos, Vector2 size, Color color) { var go = new GameObject(name, typeof(RectTransform), typeof(Image)); var rt = go.GetComponent(); rt.SetParent(parent, false); rt.sizeDelta = size; rt.localPosition = pos; var img = go.GetComponent(); img.color = color; img.raycastTarget = false; } private TextMeshProUGUI MakeText(Transform parent, string name, Vector2 pos, Vector2 size, TextAlignmentOptions align, float fontSize) { var go = new GameObject(name, typeof(RectTransform), typeof(TextMeshProUGUI)); var rt = go.GetComponent(); rt.SetParent(parent, false); rt.sizeDelta = size; rt.localPosition = pos; var t = go.GetComponent(); if (font != null) t.font = font; t.fontSize = fontSize; t.alignment = align; t.enableWordWrapping = false; t.overflowMode = TextOverflowModes.Ellipsis; t.raycastTarget = false; return t; } private Button MakeButton(Transform parent, string name, Vector2 pos, Vector2 size, out TextMeshProUGUI label) { var go = Instantiate(buttonTemplate.gameObject, parent, false); go.name = name; var rt = (RectTransform)go.transform; rt.sizeDelta = size; rt.localPosition = pos; var b = go.GetComponent