Files
probably-decentralized/src/Decentralized/GpuInspectView.cs
T

142 lines
6.5 KiB
C#
Raw Normal View History

using System.Collections.Generic;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
namespace Decentralized
{
/// <summary>
/// 放大镜检视显卡时的大图:和香烟一样把物品放大摆在检视台上,正反面各一张,看外观自己判断真假。
/// 游戏没有给 mod 开放检视界面,这里不打补丁,只在检视台(InspectionUIManager.panel)下面挂一个自己的界面,
/// 用一个常驻的 MonoBehaviour 每帧看一眼是否正在检视显卡。
/// </summary>
public sealed class GpuInspectView : MonoBehaviour
{
private static GpuInspectView instance;
private RectTransform root, cardRoot;
private Button flip;
private TextMeshProUGUI flipText;
private GameItem shown;
private string shownSig;
public static void Ensure()
{
if (instance != null) return;
var go = new GameObject("pd_gpu_inspect_view");
DontDestroyOnLoad(go);
instance = go.AddComponent<GpuInspectView>();
}
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;
return;
}
Log.Guard("显卡检视大图", () =>
{
if (root == null) Build(m);
if (!root.gameObject.activeSelf) root.gameObject.SetActive(true);
var keys = new List<string>();
string sig = Items.LookKeys(item, keys) + "|" + string.Join(",", keys);
if (item != shown || sig != shownSig)
{
shown = item;
shownSig = sig;
Redraw(item);
}
});
}
/// <summary>检视大图的叠加层。五个维度各自对应一种或几种细节,组合时再加几处同源的小细节(磕碰、开过壳的螺丝、重新粘过的封条)。</summary>
public static List<string> BigOverlays(GameItem item)
{
var o = new List<string>();
var u = Items.ToUnit(item);
if (u.Dead) return o;
var l = u.Look;
string P = "gpu_big_ov_";
if (!Items.IsBack(item))
{
if (l.Fan == 1) o.Add(P + (l.Fingers > 0 ? "fan_dust2" : "fan_dust1"));
if (l.Fan == 2) { o.Add(P + "fan_chip"); if (l.Fingers == 2) o.Add(P + "fan_oil"); }
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"); if (l.Fan > 0) o.Add(P + "shroud_chip"); }
if (l.Bracket == 2) o.Add(P + "brk_port");
}
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.Print == 2) o.Add(P + "screw_opened"); // 重印过,说明拆开过
if (l.Sticker == 1) o.Add(P + "sticker_hand");
if (l.Sticker == 2) o.Add(P + (l.Print != 0 ? "seal_reglued" : "seal_missing"));
}
return o;
}
private void Build(InspectionUIManager m)
{
root = new GameObject("_PdGpuInspection", typeof(RectTransform)).GetComponent<RectTransform>();
root.SetParent(m.panel.transform, false);
root.sizeDelta = new Vector2(1920, 1080);
root.localPosition = Vector3.zero;
cardRoot = new GameObject("Card", typeof(RectTransform)).GetComponent<RectTransform>();
cardRoot.SetParent(root, false);
cardRoot.localPosition = new Vector3(0, 40, 0);
// 翻面按钮:复制鉴定面板里"发送"按钮的外观
var template = m.appraisalPanel.transform.Find("buttonSend");
if (template != null)
{
var go = Instantiate(template.gameObject, root, false);
go.name = "Flip";
go.transform.localPosition = new Vector3(0, -300, 0);
flip = go.GetComponent<Button>();
flip.onClick = new Button.ButtonClickedEvent();
flip.onClick.AddListener(() => { if (shown != null) Items.Flip(shown); });
flipText = go.GetComponentInChildren<TextMeshProUGUI>();
// 去掉复制来的按钮上驱动文字的组件(本地化 / 提交逻辑),文字由这里设置
foreach (var mb in go.GetComponentsInChildren<MonoBehaviour>(true))
{
string n = mb.GetType().Name;
if (mb is Button || mb is Image || mb is TextMeshProUGUI || mb is CanvasRenderer) continue;
if (n.Contains("Local") || n.Contains("Appraisal") || n.Contains("Send")) Destroy(mb);
}
}
}
private void Redraw(GameItem item)
{
foreach (Transform c in cardRoot) Destroy(c.gameObject);
var keys = new List<string>();
string baseKey = Items.LookKeys(item, keys); // 小图键名只用来取底图(品牌与正反面)
var layers = new List<string> { "gpu_big_" + baseKey.Substring("gpu_".Length) };
layers.AddRange(BigOverlays(item));
foreach (var k in layers)
{
var sprite = Items.ModSprite(k);
if (sprite == null) continue;
var go = new GameObject(k, typeof(RectTransform), typeof(Image));
var rt = go.GetComponent<RectTransform>();
rt.SetParent(cardRoot, false);
rt.sizeDelta = new Vector2(sprite.rect.width, sprite.rect.height);
rt.localScale = Vector3.one * 4f;
var img = go.GetComponent<Image>();
img.sprite = sprite;
img.raycastTarget = false;
}
if (flipText != null) flipText.text = L.T(Items.IsBack(item) ? "inspect.flip.front" : "inspect.flip.back");
}
}
}