202 lines
8.3 KiB
C#
202 lines
8.3 KiB
C#
using Assets.Framework.Tool;
|
||
using Assets.MyGame.Scripts.Net.API.GameConfig_SubClass;
|
||
using TMPro;
|
||
using UnityEngine;
|
||
using UnityEngine.UI;
|
||
|
||
/// <summary>
|
||
/// 抽奖 item 层(第三层):挂在 toggle 层里的每个奖品格子上,
|
||
/// 记录道具信息以及奖励的详细信息(prize:类型/数量/权重/库存/道具 product 等),
|
||
/// 并负责展示——图标 + 数量文本由代码动态生成在格子下;
|
||
/// 已抽中的奖项置灰(奖励不重复)。
|
||
///
|
||
/// itemId = 本格子的位置编号(对应 prizeId 后两位,如 588203 → 3),
|
||
/// 初始化时奖品按它对号入座,Inspector 里按美术摆放顺序填 1、2、3……
|
||
/// </summary>
|
||
public class ChouJiangItem : MonoBehaviour
|
||
{
|
||
[Tooltip("本格子的位置编号 = prizeId 后两位(如 588203 → 3),初始化时奖品按它对号入座")]
|
||
public int itemId;
|
||
|
||
[Header("动态生成参数")]
|
||
[Tooltip("图标占格子短边的比例")]
|
||
public float iconRatio = 0.85f;
|
||
[Tooltip("图标中心相对格子中心的纵向偏移(0=居中,负数=往下贴)")]
|
||
public float iconOffsetY = 0f;
|
||
[Tooltip("数量文本字号")]
|
||
public float fontSize = 22f;
|
||
[Tooltip("已抽中置灰的颜色")]
|
||
public Color drawnColor = new Color(0.35f, 0.35f, 0.35f, 0.5f);
|
||
|
||
[Tooltip("遮罩蒙版图片(可选):适配不规则格子;蒙版大小=格子(背景)大小,图标放进蒙版里被裁出形状")]
|
||
public Sprite maskSprite;
|
||
|
||
[Header("奖励数据(Init 时由代码填充,Play 模式选中物体可实时查看)")]
|
||
[Tooltip("道具信息 + 奖励详细信息(prizeId/名称/图标/类型/数量/道具 product/权重/库存)")]
|
||
public LotteryPrize prize;
|
||
|
||
[Tooltip("是否已被抽中(奖励不重复,抽中后置灰)")]
|
||
[SerializeField] private bool isDrawn;
|
||
|
||
/// <summary>是否已被抽中</summary>
|
||
public bool IsDrawn => isDrawn;
|
||
|
||
private Image img_Icon; // 动态生成的图标
|
||
private TextMeshProUGUI tmp_Count; // 动态生成的数量文本
|
||
private GameObject maskObj; // 动态生成的遮罩蒙版(不规则裁剪用)
|
||
|
||
// 金币/钻石本地图标(Resources 根目录,与 BackPackPropItem 同一套),静态缓存避免重复加载
|
||
private static Sprite _goldSprite;
|
||
private static Sprite _diamondSprite;
|
||
|
||
/// <summary>记录奖励数据并展示(图标 + 数量)</summary>
|
||
public void Init(LotteryPrize prize)
|
||
{
|
||
this.prize = prize; // 记录道具信息以及奖励的详细信息
|
||
ClearUI();
|
||
if (prize == null) return;
|
||
|
||
RectTransform rt = transform as RectTransform;
|
||
if (rt == null)
|
||
{
|
||
Debug.LogWarning($"[ChouJiangItem] 格子不是 UI(缺 RectTransform):{name}");
|
||
return;
|
||
}
|
||
|
||
float w = rt.rect.width, h = rt.rect.height;
|
||
if (w < 1f || h < 1f) { w = 90f; h = 79f; } // 无尺寸兜底
|
||
|
||
// 遮罩蒙版:大小=格子(背景)大小,图标放进蒙版里被裁出形状(适配不规则格子)
|
||
RectTransform iconParent = rt;
|
||
if (maskSprite != null)
|
||
iconParent = CreateMask(rt, w, h);
|
||
|
||
// 图标:方形占短边 iconRatio,居中(iconOffsetY 可微调)
|
||
float side = Mathf.Min(w, h) * iconRatio;
|
||
img_Icon = CreateIcon(iconParent, side);
|
||
SetPrizeIcon(img_Icon, prize);
|
||
|
||
// 数量:压在图标底部(文字叠在图片上面,不进蒙版)
|
||
tmp_Count = CreateCountText(rt, w, side);
|
||
tmp_Count.text = prize.count.ToString();
|
||
|
||
// 新数据默认未抽中,已抽列表由面板 Init 后统一刷新
|
||
RefreshDrawnState(false);
|
||
}
|
||
|
||
/// <summary>置灰/恢复(奖励不重复,抽中后置灰)</summary>
|
||
public void RefreshDrawnState(bool drawn)
|
||
{
|
||
isDrawn = drawn;
|
||
if (img_Icon != null)
|
||
img_Icon.color = drawn ? drawnColor : Color.white;
|
||
}
|
||
|
||
/// <summary>清掉动态生成的 UI(重复 Init 复用前调用)</summary>
|
||
public void ClearUI()
|
||
{
|
||
if (img_Icon != null) { Destroy(img_Icon.gameObject); img_Icon = null; }
|
||
if (tmp_Count != null) { Destroy(tmp_Count.gameObject); tmp_Count = null; }
|
||
if (maskObj != null) { Destroy(maskObj); maskObj = null; }
|
||
}
|
||
|
||
/// <summary>生成遮罩蒙版:Image(maskSprite)+ Mask,居中、大小=格子(背景)大小;图标放它下面被裁剪</summary>
|
||
private RectTransform CreateMask(RectTransform parent, float w, float h)
|
||
{
|
||
maskObj = new GameObject("Mask", typeof(RectTransform));
|
||
RectTransform r = (RectTransform)maskObj.transform;
|
||
r.SetParent(parent, false);
|
||
r.anchorMin = r.anchorMax = r.pivot = Vector2.one * 0.5f;
|
||
r.anchoredPosition = Vector2.zero;
|
||
// 遮罩 0.9 倍背景大小(试过比全尺寸好看)
|
||
r.sizeDelta = new Vector2(w * 0.9f, h * 0.9f);
|
||
|
||
Image maskImg = maskObj.AddComponent<Image>();
|
||
maskImg.sprite = maskSprite;
|
||
maskImg.raycastTarget = false;
|
||
|
||
// 只当裁剪形状用,不显示蒙版图本身
|
||
Mask mask = maskObj.AddComponent<Mask>();
|
||
mask.showMaskGraphic = false;
|
||
return r;
|
||
}
|
||
|
||
/// <summary>生成格子里的图标物体(往下贴 iconOffsetY)</summary>
|
||
private Image CreateIcon(RectTransform parent, float side)
|
||
{
|
||
GameObject go = new GameObject("Icon", typeof(RectTransform));
|
||
RectTransform r = (RectTransform)go.transform;
|
||
r.SetParent(parent, false);
|
||
r.anchorMin = r.anchorMax = r.pivot = Vector2.one * 0.5f;
|
||
r.anchoredPosition = new Vector2(0f, iconOffsetY);
|
||
r.sizeDelta = new Vector2(side, side);
|
||
Image img = go.AddComponent<Image>();
|
||
img.raycastTarget = false;
|
||
return img;
|
||
}
|
||
|
||
/// <summary>生成压在图标底部的数量文本</summary>
|
||
private TextMeshProUGUI CreateCountText(RectTransform parent, float w, float iconSide)
|
||
{
|
||
GameObject go = new GameObject("Count", typeof(RectTransform));
|
||
RectTransform r = (RectTransform)go.transform;
|
||
r.SetParent(parent, false);
|
||
r.anchorMin = r.anchorMax = r.pivot = Vector2.one * 0.5f;
|
||
// 图标底边往上 0.8 个字高:文字压在图片上面
|
||
r.anchoredPosition = new Vector2(0f, iconOffsetY - iconSide / 2f + fontSize * 0.8f);
|
||
r.sizeDelta = new Vector2(w, fontSize * 1.6f);
|
||
TextMeshProUGUI tmp = go.AddComponent<TextMeshProUGUI>();
|
||
TMP_FontAsset font = TMP_Settings.defaultFontAsset;
|
||
if (font != null) tmp.font = font;
|
||
tmp.fontSize = fontSize;
|
||
tmp.alignment = TextAlignmentOptions.Center;
|
||
tmp.color = Color.white;
|
||
tmp.raycastTarget = false;
|
||
return tmp;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 设置奖励图标:1=金币 / 2=钻石 用 Resources 本地图,
|
||
/// 3=道具 / 4=道具碎片 下载 icon(为空时用 product.imageUrl)。
|
||
/// </summary>
|
||
private void SetPrizeIcon(Image img, LotteryPrize prize)
|
||
{
|
||
switch (prize.type)
|
||
{
|
||
case 1: // 金币
|
||
Sprite gold = _goldSprite != null ? _goldSprite
|
||
: (_goldSprite = Resources.Load<Sprite>("gold"));
|
||
if (gold != null) img.sprite = gold;
|
||
break;
|
||
|
||
case 2: // 钻石
|
||
Sprite diamond = _diamondSprite != null ? _diamondSprite
|
||
: (_diamondSprite = Resources.Load<Sprite>("diamond"));
|
||
if (diamond != null) img.sprite = diamond;
|
||
break;
|
||
|
||
default: // 道具/碎片:下载图标
|
||
string url = prize.icon;
|
||
if (string.IsNullOrEmpty(url) && prize.product != null)
|
||
url = prize.product.imageUrl;
|
||
if (!string.IsNullOrEmpty(url))
|
||
{
|
||
WebTool.DownImage(url, tex =>
|
||
{
|
||
// 回调触发时本物体可能已被销毁(关闭面板清空父节点),需判空
|
||
if (this == null || img == null) return;
|
||
if (tex != null)
|
||
img.sprite = Sprite.Create(tex, new Rect(0, 0, tex.width, tex.height),
|
||
Vector2.one * 0.5f);
|
||
});
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
|
||
private void OnDestroy()
|
||
{
|
||
ClearUI();
|
||
}
|
||
}
|