将原来遗漏的脚本文件夹改名为正确的 DisplayItemInfo -> ItemTooltip
This commit is contained in:
@@ -0,0 +1,61 @@
|
||||
using SepCore.CustomUtility;
|
||||
using SepCore.Definition;
|
||||
using UnityEngine;
|
||||
|
||||
namespace SepCore.UI
|
||||
{
|
||||
public class ItemTooltipContext : UIContext
|
||||
{
|
||||
public int Index;
|
||||
public string IconAssetName;
|
||||
public string Title;
|
||||
public ItemType ItemType;
|
||||
public ItemRarity Rarity;
|
||||
public string Description;
|
||||
public int Price;
|
||||
public Vector3 TargetPos;
|
||||
public bool ShowRecycleButton;
|
||||
|
||||
public ItemTooltipContext()
|
||||
{
|
||||
Index = -1;
|
||||
IconAssetName = string.Empty;
|
||||
Title = string.Empty;
|
||||
ItemType = ItemType.None;
|
||||
Rarity = ItemRarity.White;
|
||||
Description = string.Empty;
|
||||
Price = 0;
|
||||
TargetPos = Vector3.zero;
|
||||
ShowRecycleButton = false;
|
||||
}
|
||||
|
||||
public ItemTooltipContext(ItemTooltipRawData rawData)
|
||||
{
|
||||
Index = rawData.Index;
|
||||
ItemType = rawData.ItemType;
|
||||
Rarity = rawData.Rarity;
|
||||
Price = rawData.Price;
|
||||
TargetPos = rawData.TargetPos;
|
||||
ShowRecycleButton = rawData.OnRecycle != null;
|
||||
if (ItemType == ItemType.None)
|
||||
{
|
||||
IconAssetName = string.Empty;
|
||||
Title = string.Empty;
|
||||
}
|
||||
else if (ItemType == ItemType.Weapon)
|
||||
{
|
||||
var data = rawData.WeaponData;
|
||||
IconAssetName = data.IconAssetName;
|
||||
Title = data.Title;
|
||||
Description = ItemDescUtility.CreateWeaponDescription(data);
|
||||
}
|
||||
else
|
||||
{
|
||||
var data = rawData.PropData;
|
||||
IconAssetName = data.IconAssetName;
|
||||
Title = data.Title;
|
||||
Description = ItemDescUtility.CreatePropDescription(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cdcef9502b7fa944ca95cb839fdc60bc
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,151 @@
|
||||
using System;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using SepCore.Event;
|
||||
using SepCore.Definition;
|
||||
using GameFramework.Event;
|
||||
using UnityEngine;
|
||||
using UnityGameFramework.Runtime;
|
||||
|
||||
namespace SepCore.UI
|
||||
{
|
||||
public class ItemTooltipController : UIControllerBase<ItemTooltipContext, ItemTooltipForm>
|
||||
{
|
||||
protected override UIFormType UIFormType => UIFormType.ItemTooltipForm;
|
||||
|
||||
private bool _locked = false;
|
||||
private Action<int, int> _onRecycle;
|
||||
|
||||
protected override void SubscribeCustomEvents()
|
||||
{
|
||||
GameEntry.Event.Subscribe(DisplayItemLockEventArgs.EventId, OnDisplayItemLock);
|
||||
GameEntry.Event.Subscribe(DisplayItemHideEventArgs.EventId, OnDisplayItemHide);
|
||||
GameEntry.Event.Subscribe(ItemTooltipRecycleEventArgs.EventId, ItemTooltipRecycle);
|
||||
}
|
||||
|
||||
protected override void UnsubscribeCustomEvents()
|
||||
{
|
||||
GameEntry.Event.Unsubscribe(DisplayItemLockEventArgs.EventId, OnDisplayItemLock);
|
||||
GameEntry.Event.Unsubscribe(DisplayItemHideEventArgs.EventId, OnDisplayItemHide);
|
||||
GameEntry.Event.Unsubscribe(ItemTooltipRecycleEventArgs.EventId, ItemTooltipRecycle);
|
||||
}
|
||||
|
||||
protected override void RefreshUI(ItemTooltipForm form, ItemTooltipContext context)
|
||||
{
|
||||
form.RefreshUI(context).Forget();
|
||||
}
|
||||
|
||||
protected override void CloseLoadedFormDirect(ItemTooltipForm form)
|
||||
{
|
||||
GameEntry.UI.CloseUIForm(form);
|
||||
}
|
||||
|
||||
private static ItemTooltipContext BuildContext(ItemTooltipRawData rawData)
|
||||
{
|
||||
if (rawData == null)
|
||||
{
|
||||
Log.Error("ItemTooltipController.BuildContext() rawData is null.");
|
||||
return null;
|
||||
}
|
||||
|
||||
return new ItemTooltipContext(rawData);
|
||||
}
|
||||
|
||||
public override async UniTask OpenUIAsync(object userData = null, float timeout = 30f)
|
||||
{
|
||||
if (userData is not ItemTooltipRawData rawData)
|
||||
{
|
||||
if (userData != null)
|
||||
{
|
||||
Log.Warning("ItemTooltipController.OpenUIAsync() userData type is invalid.");
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.Warning("ItemTooltipController.OpenUIAsync() rawData is required.");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
ItemTooltipContext context = BuildContext(rawData);
|
||||
if (context == null)
|
||||
{
|
||||
Log.Warning("ItemTooltipController.OpenUIAsync() rawData is invalid.");
|
||||
return;
|
||||
}
|
||||
|
||||
_onRecycle = rawData.OnRecycle;
|
||||
await OpenFormAsync(context, timeout);
|
||||
}
|
||||
|
||||
public override async UniTask CloseUIAsync(object userData = null, float timeout = 30f)
|
||||
{
|
||||
_locked = false;
|
||||
_onRecycle = null;
|
||||
await base.CloseUIAsync(userData, timeout);
|
||||
}
|
||||
|
||||
public override void BindUseCase(IUIUseCase useCase)
|
||||
{
|
||||
if (useCase != null)
|
||||
{
|
||||
Log.Warning("ItemTooltipController does not use a use case.");
|
||||
}
|
||||
}
|
||||
|
||||
private bool IsCurrentFormSender(object sender)
|
||||
{
|
||||
if (sender is ItemTooltipForm ItemTooltipForm)
|
||||
{
|
||||
return ItemTooltipForm == Form;
|
||||
}
|
||||
|
||||
if (sender is Component component && Form != null)
|
||||
{
|
||||
return component.transform.IsChildOf(Form.transform);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#region Event Handlers
|
||||
|
||||
private void OnDisplayItemLock(object sender, GameEventArgs e)
|
||||
{
|
||||
if (e is not DisplayItemLockEventArgs)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_locked = true;
|
||||
}
|
||||
|
||||
private void OnDisplayItemHide(object sender, GameEventArgs e)
|
||||
{
|
||||
if (e is not DisplayItemHideEventArgs args)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (_locked && !args.Force) return;
|
||||
|
||||
GameEntry.UIRouter.CloseUIAsync(UIFormType.ItemTooltipForm).Forget();
|
||||
}
|
||||
|
||||
private void ItemTooltipRecycle(object sender, GameEventArgs e)
|
||||
{
|
||||
if (e is not ItemTooltipRecycleEventArgs args)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!IsCurrentFormSender(sender))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_onRecycle?.Invoke(args.Index, args.Price);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8a9b5acbc476ae44a8259a5aea1c0cf2
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,214 @@
|
||||
using System;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using SepCore.Event;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using UnityGameFramework.Runtime;
|
||||
|
||||
namespace SepCore.UI
|
||||
{
|
||||
public class ItemTooltipForm : UGuiForm
|
||||
{
|
||||
[SerializeField] private RectTransform _content;
|
||||
|
||||
[SerializeField] private IconArea _iconArea;
|
||||
|
||||
[SerializeField] private TMP_Text _itemTitle;
|
||||
|
||||
[SerializeField] private TMP_Text _itemTypeText;
|
||||
|
||||
[SerializeField] private TMP_Text _itemDescription;
|
||||
|
||||
[SerializeField] private CommonButton _recycleButton;
|
||||
|
||||
[SerializeField] private TMP_Text _itemPrice;
|
||||
|
||||
[SerializeField] private bool _autoResizeHeight = true;
|
||||
|
||||
[SerializeField] private float _fixedTopHeight = 150f;
|
||||
|
||||
[SerializeField] private float _fixedBottomHeight = 150f;
|
||||
|
||||
[SerializeField] private float _fixedWidth = 300f;
|
||||
|
||||
[SerializeField] private float _screenEdgePadding = 0f;
|
||||
|
||||
private ItemTooltipContext _context;
|
||||
|
||||
private Vector3 _targetPos;
|
||||
|
||||
public async UniTaskVoid RefreshUI(ItemTooltipContext context)
|
||||
{
|
||||
if (context == null)
|
||||
{
|
||||
Log.Warning("ItemTooltipForm context is invalid.");
|
||||
return;
|
||||
}
|
||||
|
||||
_context = context;
|
||||
|
||||
_targetPos = ConvertWorldToAnchored(_context.TargetPos);
|
||||
Log.Info($"{_context.TargetPos}->{_targetPos}");
|
||||
|
||||
if (_content != null)
|
||||
{
|
||||
_content.anchoredPosition3D = _targetPos;
|
||||
}
|
||||
|
||||
_itemTitle.text = _context.Title ?? string.Empty;
|
||||
_itemTypeText.text = BuildTypeText(_context.ItemType) ?? string.Empty;
|
||||
_itemDescription.text = _context.Description ?? string.Empty;
|
||||
_itemPrice.text = $"{_context.Price} <sprite name=\"coin\" index=0>";
|
||||
|
||||
if (_recycleButton != null)
|
||||
{
|
||||
_recycleButton.gameObject.SetActive(_context.ShowRecycleButton);
|
||||
}
|
||||
|
||||
if (_iconArea != null && !string.IsNullOrEmpty(_context.IconAssetName))
|
||||
{
|
||||
string iconAssetName = _context.IconAssetName;
|
||||
var sprite = await GameEntry.SpriteCache.GetSprite(iconAssetName);
|
||||
if (_context != null && _context.IconAssetName == iconAssetName)
|
||||
{
|
||||
_iconArea.OnInit(sprite, context.Rarity);
|
||||
ResizeToFitContent();
|
||||
ApplyClampedTargetPos();
|
||||
}
|
||||
}
|
||||
|
||||
ResizeToFitContent();
|
||||
ApplyClampedTargetPos();
|
||||
}
|
||||
|
||||
protected override void OnOpen(object userData)
|
||||
{
|
||||
base.OnOpen(userData);
|
||||
|
||||
if (!(userData is ItemTooltipContext context))
|
||||
{
|
||||
Log.Error("ItemTooltipForm context is invalid.");
|
||||
return;
|
||||
}
|
||||
|
||||
RefreshUI(context).Forget();
|
||||
}
|
||||
|
||||
protected override void OnClose(bool isShutdown, object userData)
|
||||
{
|
||||
_context = null;
|
||||
base.OnClose(isShutdown, userData);
|
||||
}
|
||||
|
||||
private void ResizeToFitContent()
|
||||
{
|
||||
if (!_autoResizeHeight || _content == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (_itemDescription == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_itemDescription.ForceMeshUpdate();
|
||||
var descriptionSize = _itemDescription.rectTransform.sizeDelta;
|
||||
descriptionSize.y = _itemDescription.preferredHeight;
|
||||
_itemDescription.rectTransform.sizeDelta = descriptionSize;
|
||||
float descriptionHeight = Mathf.Max(0f, _itemDescription.preferredHeight);
|
||||
float targetHeight = _fixedTopHeight + descriptionHeight + _fixedBottomHeight;
|
||||
|
||||
Vector2 size = new Vector2(_fixedWidth, targetHeight);
|
||||
_content.sizeDelta = size;
|
||||
}
|
||||
|
||||
private void ApplyClampedTargetPos()
|
||||
{
|
||||
if (_content == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
RectTransform parent = _content.parent as RectTransform;
|
||||
if (parent == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Vector2 size = _content.sizeDelta;
|
||||
if (size.x <= 0f || size.y <= 0f)
|
||||
{
|
||||
size = _content.rect.size;
|
||||
}
|
||||
|
||||
Vector2 pivot = _content.pivot;
|
||||
float halfWidth = parent.rect.width * 0.5f;
|
||||
float halfHeight = parent.rect.height * 0.5f;
|
||||
|
||||
float minX = -halfWidth + size.x * pivot.x + _screenEdgePadding;
|
||||
float maxX = halfWidth - size.x * (1f - pivot.x) - _screenEdgePadding;
|
||||
float minY = -halfHeight + size.y * pivot.y + _screenEdgePadding;
|
||||
float maxY = halfHeight - size.y * (1f - pivot.y) - _screenEdgePadding;
|
||||
|
||||
float clampedX = minX <= maxX ? Mathf.Clamp(_targetPos.x, minX, maxX) : 0f;
|
||||
float clampedY = minY <= maxY ? Mathf.Clamp(_targetPos.y, minY, maxY) : 0f;
|
||||
|
||||
_content.anchoredPosition3D = new Vector3(clampedX, clampedY, _targetPos.z);
|
||||
}
|
||||
|
||||
private Vector3 ConvertWorldToAnchored(Vector3 worldPos)
|
||||
{
|
||||
if (_content == null)
|
||||
{
|
||||
return worldPos;
|
||||
}
|
||||
|
||||
RectTransform parent = _content.parent as RectTransform;
|
||||
if (parent == null)
|
||||
{
|
||||
return worldPos;
|
||||
}
|
||||
|
||||
Canvas canvas = _content.GetComponentInParent<Canvas>();
|
||||
Canvas rootCanvas = canvas != null ? canvas.rootCanvas : null;
|
||||
Camera uiCamera = null;
|
||||
if (rootCanvas != null && rootCanvas.renderMode != RenderMode.ScreenSpaceOverlay)
|
||||
{
|
||||
uiCamera = rootCanvas.worldCamera != null ? rootCanvas.worldCamera : Camera.main;
|
||||
}
|
||||
|
||||
Vector2 screenPoint = RectTransformUtility.WorldToScreenPoint(uiCamera, worldPos);
|
||||
if (!RectTransformUtility.ScreenPointToLocalPointInRectangle(parent, screenPoint, uiCamera,
|
||||
out Vector2 localPoint))
|
||||
{
|
||||
return worldPos;
|
||||
}
|
||||
|
||||
float z = _content.anchoredPosition3D.z;
|
||||
return new Vector3(localPoint.x, localPoint.y, z);
|
||||
}
|
||||
|
||||
public void OnRecycleButtonClick()
|
||||
{
|
||||
if (_context == null) return;
|
||||
GameEntry.Event.Fire(this, ItemTooltipRecycleEventArgs.Create(_context.Index, _context.Price));
|
||||
}
|
||||
|
||||
public void OnCancelButtonClick()
|
||||
{
|
||||
GameEntry.Event.Fire(this, ItemTooltipHideEventArgs.Create(true));
|
||||
}
|
||||
|
||||
private string BuildTypeText(ItemType type)
|
||||
{
|
||||
return type switch
|
||||
{
|
||||
ItemType.None => "error",
|
||||
ItemType.Weapon => "武器",
|
||||
ItemType.Prop => "道具",
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(type), type, null)
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 32469245f20597240a3c51d2cd1fb0c5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user