- 规范 UI 设计成为:
- UIForm 负责展示
- Controller 负责控制
- UseCase 负责业务逻辑
- RawData 负责提供原始数据
- Context 负责为 UIForm 提供数据
- 添加和补充一系列 UI 功能
This commit is contained in:
+1
-1
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c13ac6879bf568a42b12d798738efd84
|
||||
guid: 6cf6edb3e93c9814dbeb37df22394fed
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace UI
|
||||
{
|
||||
public interface IUIFormController
|
||||
{
|
||||
int? OpenUI(object userData = null);
|
||||
void CloseUI();
|
||||
void BindUseCase(IUIUseCase useCase);
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3ec6493d4e6c45d489e1dd3d5c6228a6
|
||||
guid: 08145adf06b2b2c4b9d61d3ef6d39cfc
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
@@ -0,0 +1,10 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UI
|
||||
{
|
||||
public interface IUIUseCase
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8b527e4ad6d6207418137211caa179d5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+1
-1
@@ -242,4 +242,4 @@ namespace UI
|
||||
GameEntry.UI.CloseUIForm(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UI
|
||||
{
|
||||
public class UIContext
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7ac4a8b30b5b7684ca58f70386314a4b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+3
-15
@@ -157,24 +157,12 @@ namespace UI
|
||||
return uiComponent.OpenUIForm(assetName, drUIForm.UIGroupName, Constant.AssetPriority.UIFormAsset, drUIForm.PauseCoveredUIForm, userData);
|
||||
}
|
||||
|
||||
public static void OpenDialog(this UIComponent uiComponent, DialogParams dialogParams)
|
||||
{
|
||||
if (((ProcedureBase)GameEntry.Procedure.CurrentProcedure).UseNativeDialog)
|
||||
{
|
||||
OpenNativeDialog(dialogParams);
|
||||
}
|
||||
else
|
||||
{
|
||||
uiComponent.OpenUIForm(UIFormType.DialogForm, dialogParams);
|
||||
}
|
||||
}
|
||||
|
||||
private static void OpenNativeDialog(DialogParams dialogParams)
|
||||
private static void OpenNativeDialog(DialogFormRawData rawData)
|
||||
{
|
||||
// TODO:这里应该弹出原生对话框,先简化实现为直接按确认按钮
|
||||
if (dialogParams.OnClickConfirm != null)
|
||||
if (rawData != null && rawData.OnClickConfirm != null)
|
||||
{
|
||||
dialogParams.OnClickConfirm(dialogParams.UserData);
|
||||
rawData.OnClickConfirm(rawData.UserData);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
namespace UI
|
||||
{
|
||||
public abstract class UIFormControllerBase<TContext> : IUIFormController where TContext : UIContext
|
||||
{
|
||||
protected abstract int? OpenUIInternal(TContext context);
|
||||
public abstract int? OpenUI(object userData = null);
|
||||
public abstract void CloseUI();
|
||||
public abstract void BindUseCase(IUIUseCase useCase);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,179 @@
|
||||
using Definition.Enum;
|
||||
using GameFramework.Event;
|
||||
using UnityGameFramework.Runtime;
|
||||
|
||||
namespace UI
|
||||
{
|
||||
public class TUIFormController : UIFormControllerBase<UIContext>
|
||||
{
|
||||
private IUIUseCase _useCase;
|
||||
private UIContext _context;
|
||||
private TUIForm _tForm;
|
||||
private int? _tFormSerialId;
|
||||
private bool _pendingRefresh;
|
||||
private bool _isBindEvent;
|
||||
|
||||
private void SubscribeEvents()
|
||||
{
|
||||
if (_isBindEvent) return;
|
||||
|
||||
GameEntry.Event.Subscribe(OpenUIFormSuccessEventArgs.EventId, OpenUIFormSuccess);
|
||||
GameEntry.Event.Subscribe(CloseUIFormCompleteEventArgs.EventId, CloseUIFormComplete);
|
||||
|
||||
_isBindEvent = true;
|
||||
}
|
||||
|
||||
private void UnsubscribeEvents()
|
||||
{
|
||||
if (!_isBindEvent) return;
|
||||
|
||||
GameEntry.Event.Unsubscribe(OpenUIFormSuccessEventArgs.EventId, OpenUIFormSuccess);
|
||||
GameEntry.Event.Unsubscribe(CloseUIFormCompleteEventArgs.EventId, CloseUIFormComplete);
|
||||
|
||||
_isBindEvent = false;
|
||||
}
|
||||
|
||||
protected override int? OpenUIInternal(UIContext context)
|
||||
{
|
||||
if (context == null)
|
||||
{
|
||||
Log.Warning("TUIFormController open failed. context is null.");
|
||||
return null;
|
||||
}
|
||||
|
||||
_context = context;
|
||||
|
||||
if (_tForm != null && _tFormSerialId.HasValue &&
|
||||
GameEntry.UI.HasUIForm(_tFormSerialId.Value))
|
||||
{
|
||||
_tForm.RefreshUI(_context);
|
||||
return _tFormSerialId;
|
||||
}
|
||||
|
||||
CloseUI();
|
||||
_pendingRefresh = true;
|
||||
SubscribeEvents();
|
||||
_tFormSerialId = GameEntry.UI.OpenUIForm(UIFormType.TUIForm, context);
|
||||
return _tFormSerialId;
|
||||
}
|
||||
|
||||
public override int? OpenUI(object userData = null)
|
||||
{
|
||||
if (userData is UIContext context)
|
||||
{
|
||||
return OpenUIInternal(context);
|
||||
}
|
||||
|
||||
if (userData != null)
|
||||
{
|
||||
Log.Warning("TUIFormController.OpenUI() userData type is invalid.");
|
||||
return null;
|
||||
}
|
||||
|
||||
return OpenUIInternal(_context);
|
||||
}
|
||||
|
||||
public override void CloseUI()
|
||||
{
|
||||
_pendingRefresh = false;
|
||||
UnsubscribeEvents();
|
||||
|
||||
if (_tFormSerialId.HasValue)
|
||||
{
|
||||
if (GameEntry.UI.HasUIForm(_tFormSerialId.Value))
|
||||
{
|
||||
GameEntry.UI.CloseUIForm(_tFormSerialId.Value);
|
||||
}
|
||||
|
||||
_tForm = null;
|
||||
_tFormSerialId = null;
|
||||
return;
|
||||
}
|
||||
|
||||
if (_tForm != null)
|
||||
{
|
||||
_tForm.Close();
|
||||
_tForm = null;
|
||||
}
|
||||
}
|
||||
|
||||
public override void BindUseCase(IUIUseCase useCase)
|
||||
{
|
||||
if (!(useCase is IUIUseCase UIFormUseCase))
|
||||
{
|
||||
Log.Error("LevelUpForm.BindUseCase() useCase is invalid.");
|
||||
return;
|
||||
}
|
||||
|
||||
_useCase = UIFormUseCase;
|
||||
}
|
||||
|
||||
private void TryRefreshUI()
|
||||
{
|
||||
if (_context == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (_tForm == null)
|
||||
{
|
||||
_pendingRefresh = true;
|
||||
return;
|
||||
}
|
||||
|
||||
_tForm.RefreshUI(_context);
|
||||
_pendingRefresh = false;
|
||||
}
|
||||
|
||||
#region EventHanlders
|
||||
|
||||
private void OpenUIFormSuccess(object sender, GameEventArgs e)
|
||||
{
|
||||
if (!(e is OpenUIFormSuccessEventArgs args))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_tFormSerialId.HasValue)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (args.UIForm == null || args.UIForm.SerialId != _tFormSerialId.Value || args.UserData != _context)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_tForm = args.UIForm.Logic as TUIForm;
|
||||
|
||||
if (_tForm == null)
|
||||
{
|
||||
Log.Warning("DialogFormController open success but form logic is invalid.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (_pendingRefresh)
|
||||
{
|
||||
TryRefreshUI();
|
||||
}
|
||||
}
|
||||
|
||||
private void CloseUIFormComplete(object sender, GameEventArgs e)
|
||||
{
|
||||
if (!(e is CloseUIFormCompleteEventArgs args))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (args.SerialId != _tFormSerialId)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_tForm = null;
|
||||
_tFormSerialId = null;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7e46538e3d51b6b4ca463fa6080ad335
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,27 @@
|
||||
using UnityEngine;
|
||||
using UnityGameFramework.Runtime;
|
||||
|
||||
namespace UI
|
||||
{
|
||||
public class TUIForm : UGuiForm
|
||||
{
|
||||
|
||||
public void RefreshUI(UIContext context)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
protected override void OnOpen(object userData)
|
||||
{
|
||||
base.OnOpen(userData);
|
||||
|
||||
if (!(userData is UIContext context))
|
||||
{
|
||||
Log.Error("UIContext is invalid.");
|
||||
return;
|
||||
}
|
||||
|
||||
RefreshUI(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e8bc5e59a2be3094798c8c46d1a4999f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -5,16 +5,13 @@
|
||||
// Feedback: mailto:ellan@gameframework.cn
|
||||
//------------------------------------------------------------
|
||||
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
using UnityEngine.EventSystems;
|
||||
using UnityEngine.Serialization;
|
||||
using UnityGameFramework.Runtime;
|
||||
|
||||
namespace UI
|
||||
{
|
||||
public class CommonButton : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler, IPointerDownHandler,
|
||||
public class CommonButton : MonoBehaviour, IPointerEnterHandler, IPointerDownHandler, IPointerExitHandler,
|
||||
IPointerUpHandler
|
||||
{
|
||||
private const float FadeTime = 0.3f;
|
||||
@@ -27,6 +24,8 @@ namespace UI
|
||||
|
||||
[SerializeField] private UnityEvent _onPointerExitAction = null;
|
||||
|
||||
[SerializeField] private bool _enableFade = true;
|
||||
|
||||
private CanvasGroup _canvasGroup = null;
|
||||
|
||||
private void Awake()
|
||||
@@ -47,22 +46,11 @@ namespace UI
|
||||
}
|
||||
|
||||
StopAllCoroutines();
|
||||
StartCoroutine(_canvasGroup.FadeToAlpha(OnHoverAlpha, FadeTime));
|
||||
if (_enableFade)
|
||||
StartCoroutine(_canvasGroup.FadeToAlpha(OnHoverAlpha, FadeTime));
|
||||
_onPointerEnterAction.Invoke();
|
||||
}
|
||||
|
||||
public void OnPointerExit(PointerEventData eventData)
|
||||
{
|
||||
if (eventData.button != PointerEventData.InputButton.Left)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
StopAllCoroutines();
|
||||
StartCoroutine(_canvasGroup.FadeToAlpha(1f, FadeTime));
|
||||
_onPointerExitAction?.Invoke();
|
||||
}
|
||||
|
||||
public void OnPointerDown(PointerEventData eventData)
|
||||
{
|
||||
if (eventData.button != PointerEventData.InputButton.Left)
|
||||
@@ -84,45 +72,17 @@ namespace UI
|
||||
_canvasGroup.alpha = OnHoverAlpha;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 注册鼠标相关事件
|
||||
/// </summary>
|
||||
/// <param name="actionId">0、1、2 分别是 Enter、Click、Exit</param>
|
||||
/// <param name="action">回调事件</param>
|
||||
public void RegisterAction(int actionId, UnityAction action)
|
||||
public void OnPointerExit(PointerEventData eventData)
|
||||
{
|
||||
switch (actionId)
|
||||
if (eventData.button != PointerEventData.InputButton.Left)
|
||||
{
|
||||
case 0:
|
||||
_onPointerEnterAction.AddListener(action);
|
||||
break;
|
||||
case 1:
|
||||
_onClickAction.AddListener(action);
|
||||
break;
|
||||
case 2:
|
||||
_onPointerExitAction.AddListener(action);
|
||||
break;
|
||||
default:
|
||||
throw new IndexOutOfRangeException("actionId 无效");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
public void UnRegisterAction(int actionId, UnityAction action)
|
||||
{
|
||||
switch (actionId)
|
||||
{
|
||||
case 0:
|
||||
_onPointerEnterAction.RemoveListener(action);
|
||||
break;
|
||||
case 1:
|
||||
_onClickAction.RemoveListener(action);
|
||||
break;
|
||||
case 2:
|
||||
_onPointerExitAction.RemoveListener(action);
|
||||
break;
|
||||
default:
|
||||
throw new IndexOutOfRangeException("actionId 无效");
|
||||
}
|
||||
StopAllCoroutines();
|
||||
if (_enableFade)
|
||||
StartCoroutine(_canvasGroup.FadeToAlpha(1.0f, FadeTime));
|
||||
_onPointerExitAction.Invoke();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
using Definition.Enum;
|
||||
|
||||
namespace UI
|
||||
{
|
||||
public class DisplayItemContext : UIContext
|
||||
{
|
||||
public string IconAssetName;
|
||||
public ItemRarity Rarity;
|
||||
public bool IsWeapon;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: df1bccc6ff70fbc4089c7809e35c1f61
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,17 @@
|
||||
using Definition.Enum;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UI
|
||||
{
|
||||
public class DisplayItemInfoFormContext : UIContext
|
||||
{
|
||||
public string IconAssetName;
|
||||
public string Title;
|
||||
public string TypeText;
|
||||
public ItemRarity Rarity;
|
||||
public string Description;
|
||||
public int Price;
|
||||
public bool IsWeapon;
|
||||
public Vector3 TargetPos;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cdcef9502b7fa944ca95cb839fdc60bc
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,14 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UI
|
||||
{
|
||||
public class DisplayListAreaContext : UIContext
|
||||
{
|
||||
public string Title;
|
||||
public int CurrentCount;
|
||||
public int MaxCount = -1;
|
||||
public DisplayItemContext[] ItemContexts;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a10dfda6cc0f45247bfcdbfb578110bc
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,40 +1,15 @@
|
||||
using System.Text;
|
||||
using DataTable;
|
||||
using Definition.DataStruct;
|
||||
using Definition.Enum;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UI
|
||||
{
|
||||
public class GoodsItemContext
|
||||
public class GoodsItemContext : UIContext
|
||||
{
|
||||
public string Title;
|
||||
public ItemRarity Rarity;
|
||||
public string Type;
|
||||
public Sprite Icon;
|
||||
public string Description;
|
||||
public int Price;
|
||||
|
||||
public static string CreateWeaponDescription(DRWeapon drWeapon)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.Append($"伤害:{drWeapon.Attack}\n");
|
||||
sb.Append($"冷却:{drWeapon.Cooldown}\n");
|
||||
sb.Append($"范围:{drWeapon.AttackRange}\n");
|
||||
sb.Append(CreatePropDescription(drWeapon.Modifiers));
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
public static string CreatePropDescription(StatModifier[] modifiers)
|
||||
{
|
||||
if (modifiers == null || modifiers.Length == 0) return null;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
foreach (var modifier in modifiers)
|
||||
{
|
||||
sb.Append(modifier.ToString());
|
||||
sb.Append("\n");
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UI
|
||||
{
|
||||
public class HudFormContext : UIContext
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3f8d476720436b84483bd1c29da4d558
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -2,9 +2,9 @@ using System.Collections.Generic;
|
||||
|
||||
namespace UI
|
||||
{
|
||||
public class LevelUpFormContext
|
||||
public class LevelUpFormContext : UIContext
|
||||
{
|
||||
public int Level;
|
||||
public List<LevelUpPropContext> Props;
|
||||
public List<LevelUpRewardItemContext> Props;
|
||||
public int RefreshPrice;
|
||||
}
|
||||
}
|
||||
|
||||
+1
-3
@@ -2,11 +2,9 @@ using UnityEngine;
|
||||
|
||||
namespace UI
|
||||
{
|
||||
public class LevelUpPropContext
|
||||
public class LevelUpRewardItemContext : UIContext
|
||||
{
|
||||
public int PropId;
|
||||
public string Title;
|
||||
public string Type;
|
||||
public Sprite Icon;
|
||||
public string Description;
|
||||
public string IconAssetName;
|
||||
@@ -2,11 +2,13 @@ using System.Collections.Generic;
|
||||
|
||||
namespace UI
|
||||
{
|
||||
public class ShopFormContext
|
||||
public class ShopFormContext : UIContext
|
||||
{
|
||||
public int CurrentLevel;
|
||||
public int RefreshPrice;
|
||||
public int PlayerCoin;
|
||||
public List<GoodsItemContext> GoodsItems;
|
||||
public DisplayListAreaContext PropListContext;
|
||||
public DisplayListAreaContext WeaponListContext;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,216 @@
|
||||
using Definition.Enum;
|
||||
using GameFramework.Event;
|
||||
using UnityGameFramework.Runtime;
|
||||
|
||||
namespace UI
|
||||
{
|
||||
public class DisplayItemInfoFormController : UIFormControllerBase<DisplayItemInfoFormContext>
|
||||
{
|
||||
private DisplayItemInfoFormContext _context;
|
||||
|
||||
private DisplayItemInfoForm _itemInfoForm;
|
||||
|
||||
private int? _itemInfoFormSerialId;
|
||||
|
||||
private bool _pendingRefresh;
|
||||
|
||||
private bool _isBindEvent = false;
|
||||
|
||||
private void SubscribeEvents()
|
||||
{
|
||||
if (_isBindEvent) return;
|
||||
|
||||
GameEntry.Event.Subscribe(OpenUIFormSuccessEventArgs.EventId, OpenUIFormSuccess);
|
||||
GameEntry.Event.Subscribe(CloseUIFormCompleteEventArgs.EventId, CloseUIFormComplete);
|
||||
|
||||
_isBindEvent = true;
|
||||
}
|
||||
|
||||
private void UnsubscribeEvents()
|
||||
{
|
||||
if (!_isBindEvent) return;
|
||||
|
||||
GameEntry.Event.Unsubscribe(OpenUIFormSuccessEventArgs.EventId, OpenUIFormSuccess);
|
||||
GameEntry.Event.Unsubscribe(CloseUIFormCompleteEventArgs.EventId, CloseUIFormComplete);
|
||||
|
||||
_isBindEvent = false;
|
||||
}
|
||||
|
||||
private static DisplayItemInfoFormContext BuildContext(DisplayItemInfoFormRawData rawData)
|
||||
{
|
||||
if (rawData == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return new DisplayItemInfoFormContext
|
||||
{
|
||||
IconAssetName = rawData.IconAssetName,
|
||||
Title = rawData.Title,
|
||||
Rarity = rawData.Rarity,
|
||||
TypeText = rawData.TypeText,
|
||||
Description = rawData.Description,
|
||||
Price = rawData.Price,
|
||||
IsWeapon = rawData.IsWeapon,
|
||||
TargetPos = rawData.TargetPos
|
||||
};
|
||||
}
|
||||
|
||||
#region UI Methods
|
||||
|
||||
protected override int? OpenUIInternal(DisplayItemInfoFormContext context)
|
||||
{
|
||||
if (context == null)
|
||||
{
|
||||
Log.Warning("ItemInfoFormController open failed. context is null.");
|
||||
return null;
|
||||
}
|
||||
|
||||
_context = context;
|
||||
|
||||
if (_itemInfoForm != null && _itemInfoFormSerialId.HasValue &&
|
||||
GameEntry.UI.HasUIForm(_itemInfoFormSerialId.Value))
|
||||
{
|
||||
_itemInfoForm.RefreshUI(_context);
|
||||
return _itemInfoFormSerialId;
|
||||
}
|
||||
|
||||
CloseUI();
|
||||
_pendingRefresh = true;
|
||||
SubscribeEvents();
|
||||
_itemInfoFormSerialId = GameEntry.UI.OpenUIForm(UIFormType.DisplayItemInfoForm, context);
|
||||
return _itemInfoFormSerialId;
|
||||
}
|
||||
|
||||
public int? OpenUI(DisplayItemInfoFormRawData rawData)
|
||||
{
|
||||
DisplayItemInfoFormContext context = BuildContext(rawData);
|
||||
return OpenUIInternal(context);
|
||||
}
|
||||
|
||||
public override int? OpenUI(object userData = null)
|
||||
{
|
||||
if (userData is DisplayItemInfoFormContext context)
|
||||
{
|
||||
return OpenUIInternal(context);
|
||||
}
|
||||
|
||||
if (userData is DisplayItemInfoFormRawData rawData)
|
||||
{
|
||||
return OpenUI(rawData);
|
||||
}
|
||||
|
||||
if (userData != null)
|
||||
{
|
||||
Log.Warning("DisplayItemInfoFormController.OpenUI() userData type is invalid.");
|
||||
return null;
|
||||
}
|
||||
|
||||
return OpenUIInternal(_context);
|
||||
}
|
||||
|
||||
public override void CloseUI()
|
||||
{
|
||||
_pendingRefresh = false;
|
||||
|
||||
UnsubscribeEvents();
|
||||
|
||||
if (_itemInfoFormSerialId.HasValue)
|
||||
{
|
||||
if (GameEntry.UI.HasUIForm(_itemInfoFormSerialId.Value))
|
||||
{
|
||||
GameEntry.UI.CloseUIForm(_itemInfoFormSerialId.Value);
|
||||
}
|
||||
|
||||
_itemInfoForm = null;
|
||||
_itemInfoFormSerialId = null;
|
||||
return;
|
||||
}
|
||||
|
||||
if (_itemInfoForm != null)
|
||||
{
|
||||
GameEntry.UI.CloseUIForm(_itemInfoForm);
|
||||
_itemInfoForm = null;
|
||||
}
|
||||
}
|
||||
|
||||
public override void BindUseCase(IUIUseCase useCase)
|
||||
{
|
||||
if (!(useCase is DisplayItemInfoFormUseCase))
|
||||
{
|
||||
Log.Error("DisplayItemInfoForm.BindUseCase() useCase is invalid.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private void TryRefreshUI()
|
||||
{
|
||||
if (_context == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (_itemInfoForm == null)
|
||||
{
|
||||
_pendingRefresh = true;
|
||||
return;
|
||||
}
|
||||
|
||||
_itemInfoForm.RefreshUI(_context);
|
||||
_pendingRefresh = false;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region EventHanlders
|
||||
|
||||
private void OpenUIFormSuccess(object sender, GameEventArgs e)
|
||||
{
|
||||
if (!(e is OpenUIFormSuccessEventArgs args))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_itemInfoFormSerialId.HasValue)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (args.UIForm == null || args.UIForm.SerialId != _itemInfoFormSerialId.Value || args.UserData != _context)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_itemInfoForm = args.UIForm.Logic as DisplayItemInfoForm;
|
||||
|
||||
if (_itemInfoForm == null)
|
||||
{
|
||||
Log.Warning("DisplayItemInfoFormController open success but form logic is invalid.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (_pendingRefresh)
|
||||
{
|
||||
TryRefreshUI();
|
||||
}
|
||||
}
|
||||
|
||||
private void CloseUIFormComplete(object sender, GameEventArgs e)
|
||||
{
|
||||
if (!(e is CloseUIFormCompleteEventArgs args))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (args.SerialId != _itemInfoFormSerialId)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_itemInfoForm = null;
|
||||
_itemInfoFormSerialId = null;
|
||||
}
|
||||
|
||||
#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,192 @@
|
||||
using Definition.Enum;
|
||||
using GameFramework.Event;
|
||||
using UnityGameFramework.Runtime;
|
||||
|
||||
namespace UI
|
||||
{
|
||||
public class HudFormController : UIFormControllerBase<HudFormContext>
|
||||
{
|
||||
private HudFormContext _context;
|
||||
|
||||
private HudForm _hudForm;
|
||||
|
||||
private int? _hudFormSerialId;
|
||||
|
||||
private bool _pendingRefresh;
|
||||
|
||||
private bool _isBindEvent;
|
||||
|
||||
private void SubscribeEvents()
|
||||
{
|
||||
if (_isBindEvent) return;
|
||||
|
||||
GameEntry.Event.Subscribe(OpenUIFormSuccessEventArgs.EventId, OpenUIFormSuccess);
|
||||
GameEntry.Event.Subscribe(CloseUIFormCompleteEventArgs.EventId, CloseUIFormComplete);
|
||||
|
||||
_isBindEvent = true;
|
||||
}
|
||||
|
||||
private void UnsubscribeEvents()
|
||||
{
|
||||
if (!_isBindEvent) return;
|
||||
|
||||
GameEntry.Event.Unsubscribe(OpenUIFormSuccessEventArgs.EventId, OpenUIFormSuccess);
|
||||
GameEntry.Event.Unsubscribe(CloseUIFormCompleteEventArgs.EventId, CloseUIFormComplete);
|
||||
|
||||
_isBindEvent = false;
|
||||
}
|
||||
|
||||
private static HudFormContext BuildHudFormContext()
|
||||
{
|
||||
return new HudFormContext();
|
||||
}
|
||||
|
||||
#region UI Methods
|
||||
|
||||
protected override int? OpenUIInternal(HudFormContext context)
|
||||
{
|
||||
if (context == null)
|
||||
{
|
||||
Log.Warning("HudFormController.OpenUI() context is null.");
|
||||
return null;
|
||||
}
|
||||
|
||||
_context = context;
|
||||
|
||||
if (_hudForm != null && _hudFormSerialId.HasValue &&
|
||||
GameEntry.UI.HasUIForm(_hudFormSerialId.Value))
|
||||
{
|
||||
_hudForm.RefreshUI(_context);
|
||||
return _hudFormSerialId;
|
||||
}
|
||||
|
||||
CloseUI();
|
||||
_pendingRefresh = true;
|
||||
SubscribeEvents();
|
||||
_hudFormSerialId = GameEntry.UI.OpenUIForm(UIFormType.HudForm, context);
|
||||
return _hudFormSerialId;
|
||||
}
|
||||
|
||||
public override int? OpenUI(object userData = null)
|
||||
{
|
||||
if (userData is HudFormContext context)
|
||||
{
|
||||
return OpenUIInternal(context);
|
||||
}
|
||||
|
||||
if (userData != null)
|
||||
{
|
||||
Log.Warning("HudFormController.OpenUI() userData type is invalid.");
|
||||
return null;
|
||||
}
|
||||
|
||||
return OpenUIInternal(BuildHudFormContext());
|
||||
}
|
||||
|
||||
public int? OpenUI(HudFormContext context)
|
||||
{
|
||||
return OpenUIInternal(context);
|
||||
}
|
||||
|
||||
public override void CloseUI()
|
||||
{
|
||||
_pendingRefresh = false;
|
||||
UnsubscribeEvents();
|
||||
|
||||
if (_hudFormSerialId.HasValue)
|
||||
{
|
||||
if (GameEntry.UI.HasUIForm(_hudFormSerialId.Value))
|
||||
{
|
||||
GameEntry.UI.CloseUIForm(_hudFormSerialId.Value);
|
||||
}
|
||||
|
||||
_hudForm = null;
|
||||
_hudFormSerialId = null;
|
||||
return;
|
||||
}
|
||||
|
||||
if (_hudForm != null)
|
||||
{
|
||||
_hudForm.Close();
|
||||
_hudForm = null;
|
||||
}
|
||||
}
|
||||
|
||||
public override void BindUseCase(IUIUseCase useCase)
|
||||
{
|
||||
Log.Info("HudFormController doesn't need UseCase");
|
||||
}
|
||||
|
||||
private void TryRefreshUI()
|
||||
{
|
||||
if (_context == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (_hudForm == null)
|
||||
{
|
||||
_pendingRefresh = true;
|
||||
return;
|
||||
}
|
||||
|
||||
_hudForm.RefreshUI(_context);
|
||||
_pendingRefresh = false;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region Event Handlers
|
||||
|
||||
private void OpenUIFormSuccess(object sender, GameEventArgs e)
|
||||
{
|
||||
if (!(e is OpenUIFormSuccessEventArgs args))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_hudFormSerialId.HasValue)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (args.UIForm == null || args.UIForm.SerialId != _hudFormSerialId.Value ||
|
||||
args.UserData != _context)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_hudForm = args.UIForm.Logic as HudForm;
|
||||
|
||||
if (_hudForm == null)
|
||||
{
|
||||
Log.Warning("HudFormController open success but form logic is invalid.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (_pendingRefresh)
|
||||
{
|
||||
TryRefreshUI();
|
||||
}
|
||||
}
|
||||
|
||||
private void CloseUIFormComplete(object sender, GameEventArgs e)
|
||||
{
|
||||
if (!(e is CloseUIFormCompleteEventArgs args))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (args.SerialId != _hudFormSerialId)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_hudForm = null;
|
||||
_hudFormSerialId = null;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b7360b01093fa984d86105e2dd024dd5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,8 +0,0 @@
|
||||
namespace UI
|
||||
{
|
||||
public interface IFormController<TContext>
|
||||
{
|
||||
int? OpenUI(TContext context);
|
||||
void CloseUI();
|
||||
}
|
||||
}
|
||||
@@ -1,44 +1,81 @@
|
||||
using System.Collections.Generic;
|
||||
using CustomEvent;
|
||||
using DataTable;
|
||||
using Definition.Enum;
|
||||
using GameFramework.DataTable;
|
||||
using Game.Utility;
|
||||
using GameFramework.Event;
|
||||
using UnityEngine;
|
||||
using Procedure;
|
||||
using UnityGameFramework.Runtime;
|
||||
|
||||
namespace UI
|
||||
{
|
||||
public class LevelUpFormController : IFormController<LevelUpFormContext>
|
||||
public class LevelUpFormController : UIFormControllerBase<LevelUpFormContext>
|
||||
{
|
||||
private int _currentLevel = 1;
|
||||
private int _buildCount = 4;
|
||||
private LevelUpFormUseCase _useCase;
|
||||
|
||||
private bool _pendingRefresh;
|
||||
|
||||
private int? _levelUpFormSerialId;
|
||||
|
||||
private LevelUpForm _levelUpForm;
|
||||
|
||||
private LevelUpFormContext _context;
|
||||
|
||||
public LevelUpFormController()
|
||||
private bool _isBindEvent;
|
||||
|
||||
private void SubscribeEvents()
|
||||
{
|
||||
if (_isBindEvent) return;
|
||||
|
||||
GameEntry.Event.Subscribe(OpenUIFormSuccessEventArgs.EventId, OpenUIFormSuccess);
|
||||
GameEntry.Event.Subscribe(CloseUIFormCompleteEventArgs.EventId, CloseUIFormComplete);
|
||||
GameEntry.Event.Subscribe(RefreshEventArgs.EventId, OnRefresh);
|
||||
GameEntry.Event.Subscribe(LevelUpPropSelectedEventArgs.EventId, OnLevelUpPropSelected);
|
||||
|
||||
_isBindEvent = true;
|
||||
}
|
||||
|
||||
~LevelUpFormController()
|
||||
private void UnsubscribeEvents()
|
||||
{
|
||||
if (!_isBindEvent) return;
|
||||
|
||||
GameEntry.Event.Unsubscribe(OpenUIFormSuccessEventArgs.EventId, OpenUIFormSuccess);
|
||||
GameEntry.Event.Unsubscribe(CloseUIFormCompleteEventArgs.EventId, CloseUIFormComplete);
|
||||
GameEntry.Event.Unsubscribe(RefreshEventArgs.EventId, OnRefresh);
|
||||
GameEntry.Event.Unsubscribe(LevelUpPropSelectedEventArgs.EventId, OnLevelUpPropSelected);
|
||||
|
||||
_isBindEvent = false;
|
||||
}
|
||||
|
||||
public void ConfigureBuild(int level, int count = 4)
|
||||
private static LevelUpFormContext BuildContext(LevelUpFormRawData rawData)
|
||||
{
|
||||
_currentLevel = Mathf.Max(1, level);
|
||||
_buildCount = Mathf.Max(0, count);
|
||||
List<LevelUpRewardItemContext> props = new List<LevelUpRewardItemContext>(rawData.Rewards.Count);
|
||||
foreach (var reward in rawData.Rewards)
|
||||
{
|
||||
if (reward == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
props.Add(new LevelUpRewardItemContext
|
||||
{
|
||||
Title = reward.Title,
|
||||
Icon = null,
|
||||
Description = ItemDescUtility.CreatePropDescription(reward.Modifiers),
|
||||
IconAssetName = reward.IconAssetName
|
||||
});
|
||||
}
|
||||
|
||||
return new LevelUpFormContext
|
||||
{
|
||||
RefreshPrice = rawData.RefreshPrice,
|
||||
Props = props
|
||||
};
|
||||
}
|
||||
|
||||
public int? OpenUI(LevelUpFormContext context)
|
||||
|
||||
#region UI Methods
|
||||
|
||||
protected override int? OpenUIInternal(LevelUpFormContext context)
|
||||
{
|
||||
if (context == null)
|
||||
{
|
||||
@@ -48,7 +85,8 @@ namespace UI
|
||||
|
||||
_context = context;
|
||||
|
||||
if (_levelUpForm != null)
|
||||
if (_levelUpForm != null && _levelUpFormSerialId.HasValue &&
|
||||
GameEntry.UI.HasUIForm(_levelUpFormSerialId.Value))
|
||||
{
|
||||
_levelUpForm.RefreshUI(_context);
|
||||
return _levelUpFormSerialId;
|
||||
@@ -56,37 +94,43 @@ namespace UI
|
||||
|
||||
CloseUI();
|
||||
_pendingRefresh = true;
|
||||
SubscribeEvents();
|
||||
_levelUpFormSerialId = GameEntry.UI.OpenUIForm(UIFormType.LevelUpForm, context);
|
||||
return _levelUpFormSerialId;
|
||||
}
|
||||
|
||||
public void CloseUI()
|
||||
public override int? OpenUI(object userData = null)
|
||||
{
|
||||
_pendingRefresh = false;
|
||||
|
||||
if (_levelUpFormSerialId.HasValue)
|
||||
if (userData is LevelUpFormContext context)
|
||||
{
|
||||
GameEntry.UI.CloseUIForm(_levelUpFormSerialId.Value);
|
||||
return;
|
||||
return OpenUIInternal(context);
|
||||
}
|
||||
|
||||
if (_levelUpForm != null)
|
||||
if (userData is LevelUpFormRawData rawDataFromUserData)
|
||||
{
|
||||
_levelUpForm.Close();
|
||||
return OpenUI(rawDataFromUserData);
|
||||
}
|
||||
|
||||
if (userData != null)
|
||||
{
|
||||
Log.Warning("LevelUpFormController.OpenUI() userData type is invalid.");
|
||||
return null;
|
||||
}
|
||||
|
||||
if (_useCase == null)
|
||||
{
|
||||
Log.Error("LevelUpFormController.OpenUI() useCase is null.");
|
||||
return null;
|
||||
}
|
||||
|
||||
LevelUpFormRawData rawData = _useCase.CreateInitialModel();
|
||||
return OpenUI(rawData);
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
public int? OpenUI(LevelUpFormRawData rawData)
|
||||
{
|
||||
_context = null;
|
||||
_levelUpForm = null;
|
||||
_levelUpFormSerialId = null;
|
||||
_pendingRefresh = false;
|
||||
}
|
||||
|
||||
public void OnSelectProp(int propId)
|
||||
{
|
||||
|
||||
LevelUpFormContext context = BuildContext(rawData);
|
||||
return OpenUIInternal(context);
|
||||
}
|
||||
|
||||
private void TryRefreshUI()
|
||||
@@ -106,6 +150,82 @@ namespace UI
|
||||
_pendingRefresh = false;
|
||||
}
|
||||
|
||||
public override void CloseUI()
|
||||
{
|
||||
_pendingRefresh = false;
|
||||
UnsubscribeEvents();
|
||||
|
||||
if (_levelUpFormSerialId.HasValue)
|
||||
{
|
||||
if (GameEntry.UI.HasUIForm(_levelUpFormSerialId.Value))
|
||||
{
|
||||
GameEntry.UI.CloseUIForm(_levelUpFormSerialId.Value);
|
||||
}
|
||||
|
||||
_levelUpForm = null;
|
||||
_levelUpFormSerialId = null;
|
||||
return;
|
||||
}
|
||||
|
||||
if (_levelUpForm != null)
|
||||
{
|
||||
_levelUpForm.Close();
|
||||
_levelUpForm = null;
|
||||
}
|
||||
}
|
||||
|
||||
public override void BindUseCase(IUIUseCase useCase)
|
||||
{
|
||||
if (!(useCase is LevelUpFormUseCase levelUpFormUseCase))
|
||||
{
|
||||
Log.Error("LevelUpForm.BindUseCase() useCase is invalid.");
|
||||
return;
|
||||
}
|
||||
|
||||
_useCase = levelUpFormUseCase;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Service
|
||||
|
||||
private void SelectReward(int selectedIndex)
|
||||
{
|
||||
if (_useCase == null)
|
||||
{
|
||||
Log.Error("LevelUpFormController.OpenUI() useCase is null.");
|
||||
return;
|
||||
}
|
||||
|
||||
LevelUpFormRawData rawData = _useCase.SelectReward(selectedIndex);
|
||||
|
||||
if (rawData == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
OpenUI(rawData);
|
||||
}
|
||||
|
||||
private void RefreshRewardList(int refreshCost)
|
||||
{
|
||||
if (_useCase == null)
|
||||
{
|
||||
Log.Error("LevelUpFormController.OpenUI() useCase is null.");
|
||||
return;
|
||||
}
|
||||
|
||||
LevelUpFormRawData rawData = _useCase.TryRefresh(refreshCost);
|
||||
if (rawData == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
OpenUI(rawData);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Event Handlers
|
||||
|
||||
private void OpenUIFormSuccess(object sender, GameEventArgs e)
|
||||
@@ -149,6 +269,31 @@ namespace UI
|
||||
_levelUpFormSerialId = null;
|
||||
}
|
||||
|
||||
private void OnRefresh(object sender, GameEventArgs e)
|
||||
{
|
||||
if (!(sender is LevelUpForm))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(e is RefreshEventArgs args))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
RefreshRewardList(args.Cost);
|
||||
}
|
||||
|
||||
private void OnLevelUpPropSelected(object sender, GameEventArgs e)
|
||||
{
|
||||
if (!(e is LevelUpPropSelectedEventArgs args))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
SelectReward(args.SelectedId);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,17 @@
|
||||
using System.Collections.Generic;
|
||||
using CustomEvent;
|
||||
using Definition.DataStruct;
|
||||
using Definition.Enum;
|
||||
using Entity;
|
||||
using Game.Utility;
|
||||
using GameFramework.Event;
|
||||
using UnityGameFramework.Runtime;
|
||||
|
||||
namespace UI
|
||||
{
|
||||
public class ShopFormController : IFormController<ShopFormContext>
|
||||
public class ShopFormController : UIFormControllerBase<ShopFormContext>
|
||||
{
|
||||
#region Property
|
||||
private ShopFormUseCase _useCase;
|
||||
|
||||
private bool _pendingRefresh;
|
||||
|
||||
@@ -14,23 +19,167 @@ namespace UI
|
||||
|
||||
private ShopForm _shopForm;
|
||||
|
||||
private ShopFormRawData _rawData;
|
||||
|
||||
private ShopFormContext _context;
|
||||
|
||||
private bool _isBindEvent;
|
||||
|
||||
private void SubscribeEvents()
|
||||
{
|
||||
if (_isBindEvent) return;
|
||||
|
||||
GameEntry.Event.Subscribe(OpenUIFormSuccessEventArgs.EventId, OpenUIFormSuccess);
|
||||
GameEntry.Event.Subscribe(CloseUIFormCompleteEventArgs.EventId, CloseUIFormComplete);
|
||||
GameEntry.Event.Subscribe(RefreshEventArgs.EventId, Refresh);
|
||||
GameEntry.Event.Subscribe(ShopPurchaseEventArgs.EventId, ShopPurchase);
|
||||
GameEntry.Event.Subscribe(ShopContinueEventArgs.EventId, ShopContinue);
|
||||
GameEntry.Event.Subscribe(DisplayItemShowEventArgs.EventId, DisplayItemShow);
|
||||
GameEntry.Event.Subscribe(DisplayItemHideEventArgs.EventId, DisplayItemHide);
|
||||
|
||||
_isBindEvent = true;
|
||||
}
|
||||
|
||||
private void UnsubscribeEvents()
|
||||
{
|
||||
if (!_isBindEvent) return;
|
||||
|
||||
GameEntry.Event.Unsubscribe(OpenUIFormSuccessEventArgs.EventId, OpenUIFormSuccess);
|
||||
GameEntry.Event.Unsubscribe(CloseUIFormCompleteEventArgs.EventId, CloseUIFormComplete);
|
||||
GameEntry.Event.Unsubscribe(RefreshEventArgs.EventId, Refresh);
|
||||
GameEntry.Event.Unsubscribe(ShopPurchaseEventArgs.EventId, ShopPurchase);
|
||||
GameEntry.Event.Unsubscribe(ShopContinueEventArgs.EventId, ShopContinue);
|
||||
GameEntry.Event.Unsubscribe(DisplayItemShowEventArgs.EventId, DisplayItemShow);
|
||||
GameEntry.Event.Unsubscribe(DisplayItemHideEventArgs.EventId, DisplayItemHide);
|
||||
|
||||
_isBindEvent = false;
|
||||
}
|
||||
|
||||
#region BuildContext
|
||||
|
||||
private ShopFormContext BuildContext(ShopFormRawData rawData)
|
||||
{
|
||||
if (rawData == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
_rawData = rawData;
|
||||
|
||||
return new ShopFormContext
|
||||
{
|
||||
CurrentLevel = rawData.CurrentLevel,
|
||||
RefreshPrice = rawData.RefreshPrice,
|
||||
PlayerCoin = rawData.PlayerCoin,
|
||||
GoodsItems = rawData.GoodsItems,
|
||||
PropListContext = BuildDisplayListAreaContext("道具", rawData.PropItems, rawData.PropMaxCount),
|
||||
WeaponListContext = BuildDisplayListAreaContext("武器", rawData.WeaponItems, rawData.WeaponMaxCount)
|
||||
};
|
||||
}
|
||||
|
||||
private static DisplayListAreaContext BuildDisplayListAreaContext(string title, IReadOnlyList<object> items,
|
||||
int maxCount)
|
||||
{
|
||||
DisplayItemContext[] itemContexts = new DisplayItemContext[items.Count];
|
||||
if (title == "武器")
|
||||
{
|
||||
if (items is IReadOnlyList<WeaponBase> weapons)
|
||||
{
|
||||
for (int i = 0; i < weapons.Count; i++)
|
||||
{
|
||||
WeaponBase weapon = weapons[i];
|
||||
if (weapon == null) break;
|
||||
itemContexts[i] = BuildWeaponItem(weapon);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (title == "道具")
|
||||
{
|
||||
if (items is IReadOnlyList<PropItem> propItems)
|
||||
{
|
||||
for (int i = 0; i < propItems.Count; i++)
|
||||
{
|
||||
PropItem propItem = propItems[i];
|
||||
if (propItem == null) break;
|
||||
itemContexts[i] = BuildPropItem(propItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int currentCount = itemContexts.Length;
|
||||
return new DisplayListAreaContext
|
||||
{
|
||||
Title = title,
|
||||
CurrentCount = currentCount,
|
||||
MaxCount = maxCount,
|
||||
ItemContexts = itemContexts
|
||||
};
|
||||
}
|
||||
|
||||
private static DisplayItemContext BuildPropItem(PropItem propItem)
|
||||
{
|
||||
string iconAssetName = null;
|
||||
ItemRarity rarity = ItemRarity.None;
|
||||
|
||||
if (propItem != null)
|
||||
{
|
||||
iconAssetName = propItem.IconAssetName;
|
||||
rarity = propItem.Rarity;
|
||||
}
|
||||
|
||||
return new DisplayItemContext
|
||||
{
|
||||
IconAssetName = iconAssetName,
|
||||
Rarity = rarity,
|
||||
IsWeapon = false
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
private static DisplayItemContext BuildWeaponItem(WeaponBase weaponBase)
|
||||
{
|
||||
string iconAssetName = null;
|
||||
ItemRarity rarity = ItemRarity.None;
|
||||
|
||||
if (weaponBase != null && weaponBase.WeaponData != null)
|
||||
{
|
||||
iconAssetName = weaponBase.WeaponData.IconAssetName;
|
||||
rarity = weaponBase.WeaponData.Rarity;
|
||||
}
|
||||
|
||||
return new DisplayItemContext
|
||||
{
|
||||
IconAssetName = iconAssetName,
|
||||
Rarity = rarity,
|
||||
IsWeapon = true
|
||||
};
|
||||
}
|
||||
|
||||
private static void AppendDisplayItemContext(DisplayListAreaContext listContext, DisplayItemContext newItem)
|
||||
{
|
||||
if (listContext == null || newItem == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int oldCount = listContext.ItemContexts != null ? listContext.ItemContexts.Length : 0;
|
||||
DisplayItemContext[] newContexts = new DisplayItemContext[oldCount + 1];
|
||||
if (oldCount > 0)
|
||||
{
|
||||
System.Array.Copy(listContext.ItemContexts, newContexts, oldCount);
|
||||
}
|
||||
|
||||
newContexts[oldCount] = newItem;
|
||||
listContext.ItemContexts = newContexts;
|
||||
listContext.CurrentCount = oldCount + 1;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public ShopFormController()
|
||||
{
|
||||
GameEntry.Event.Subscribe(OpenUIFormSuccessEventArgs.EventId, OpenUIFormSuccess);
|
||||
GameEntry.Event.Subscribe(CloseUIFormCompleteEventArgs.EventId, CloseUIFormComplete);
|
||||
}
|
||||
|
||||
~ShopFormController()
|
||||
{
|
||||
GameEntry.Event.Unsubscribe(OpenUIFormSuccessEventArgs.EventId, OpenUIFormSuccess);
|
||||
GameEntry.Event.Unsubscribe(CloseUIFormCompleteEventArgs.EventId, CloseUIFormComplete);
|
||||
}
|
||||
#region UI Methods
|
||||
|
||||
public int? OpenUI(ShopFormContext context)
|
||||
protected override int? OpenUIInternal(ShopFormContext context)
|
||||
{
|
||||
if (context == null)
|
||||
{
|
||||
@@ -40,7 +189,8 @@ namespace UI
|
||||
|
||||
_context = context;
|
||||
|
||||
if (_shopForm != null)
|
||||
if (_shopForm != null && _shopFormSerialId.HasValue &&
|
||||
GameEntry.UI.HasUIForm(_shopFormSerialId.Value))
|
||||
{
|
||||
_shopForm.RefreshUI(_context);
|
||||
return _shopFormSerialId;
|
||||
@@ -48,26 +198,79 @@ namespace UI
|
||||
|
||||
CloseUI();
|
||||
_pendingRefresh = true;
|
||||
SubscribeEvents();
|
||||
_shopFormSerialId = GameEntry.UI.OpenUIForm(UIFormType.ShopForm, context);
|
||||
return _shopFormSerialId;
|
||||
}
|
||||
|
||||
public void CloseUI()
|
||||
public int? OpenUI(ShopFormRawData rawData)
|
||||
{
|
||||
ShopFormContext context = BuildContext(rawData);
|
||||
return OpenUIInternal(context);
|
||||
}
|
||||
|
||||
public override int? OpenUI(object userData = null)
|
||||
{
|
||||
if (userData is ShopFormContext context)
|
||||
{
|
||||
return OpenUIInternal(context);
|
||||
}
|
||||
|
||||
if (userData is ShopFormRawData rawDataFromUserData)
|
||||
{
|
||||
return OpenUI(rawDataFromUserData);
|
||||
}
|
||||
|
||||
if (userData != null)
|
||||
{
|
||||
Log.Warning("ShopFormController.OpenUI() userData type is invalid.");
|
||||
return null;
|
||||
}
|
||||
|
||||
if (_useCase == null)
|
||||
{
|
||||
Log.Error("ShopForm.OpenUI():: useCase is null.");
|
||||
return null;
|
||||
}
|
||||
|
||||
ShopFormRawData rawData = _useCase.CreateInitialModel();
|
||||
return OpenUI(rawData);
|
||||
}
|
||||
|
||||
public override void CloseUI()
|
||||
{
|
||||
_pendingRefresh = false;
|
||||
|
||||
UnsubscribeEvents();
|
||||
if (_shopFormSerialId.HasValue)
|
||||
{
|
||||
GameEntry.UI.CloseUIForm(_shopFormSerialId.Value);
|
||||
if (GameEntry.UI.HasUIForm(_shopFormSerialId.Value))
|
||||
{
|
||||
GameEntry.UI.CloseUIForm(_shopFormSerialId.Value);
|
||||
}
|
||||
|
||||
_shopForm = null;
|
||||
_shopFormSerialId = null;
|
||||
return;
|
||||
}
|
||||
|
||||
if (_shopForm != null)
|
||||
{
|
||||
_shopForm.Close();
|
||||
_shopForm = null;
|
||||
}
|
||||
}
|
||||
|
||||
public override void BindUseCase(IUIUseCase useCase)
|
||||
{
|
||||
if (!(useCase is ShopFormUseCase shopFormUseCase))
|
||||
{
|
||||
Log.Error("LevelUpForm.BindUseCase() useCase is invalid.");
|
||||
return;
|
||||
}
|
||||
|
||||
_useCase = shopFormUseCase;
|
||||
}
|
||||
|
||||
private void TryRefreshUI()
|
||||
{
|
||||
if (_context == null)
|
||||
@@ -84,7 +287,59 @@ namespace UI
|
||||
_shopForm.RefreshUI(_context);
|
||||
_pendingRefresh = false;
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region Service
|
||||
|
||||
private void RefreshGoodsItems(ShopRefreshResult result)
|
||||
{
|
||||
if (_context == null || result == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_context.GoodsItems = result.GoodsItems;
|
||||
_context.RefreshPrice = result.RefreshPrice;
|
||||
|
||||
if (_shopForm == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_shopForm.RefreshGoodsItems(result.GoodsItems);
|
||||
_shopForm.RefreshRefreshPrice(result.RefreshPrice);
|
||||
}
|
||||
|
||||
private void ApplyGoodsPurchased(ShopPurchaseResult result)
|
||||
{
|
||||
if (_context == null || result == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (_context.GoodsItems != null && result.GoodsIndex >= 0 && result.GoodsIndex < _context.GoodsItems.Count)
|
||||
{
|
||||
_context.GoodsItems[result.GoodsIndex] = null;
|
||||
}
|
||||
|
||||
if (result.DisplayItem != null)
|
||||
{
|
||||
if (result.DisplayItem.IsWeapon)
|
||||
{
|
||||
AppendDisplayItemContext(_context.WeaponListContext, result.DisplayItem);
|
||||
}
|
||||
else
|
||||
{
|
||||
AppendDisplayItemContext(_context.PropListContext, result.DisplayItem);
|
||||
}
|
||||
}
|
||||
|
||||
_shopForm?.ApplyGoodsPurchased(result.GoodsIndex, result.DisplayItem);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Event Handlers
|
||||
|
||||
private void OpenUIFormSuccess(object sender, GameEventArgs e)
|
||||
@@ -128,6 +383,103 @@ namespace UI
|
||||
_shopFormSerialId = null;
|
||||
}
|
||||
|
||||
private void Refresh(object sender, GameEventArgs e)
|
||||
{
|
||||
if (!(sender is ShopForm))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(e is RefreshEventArgs args))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ShopRefreshResult result = _useCase.TryRefresh(args.Cost);
|
||||
if (result == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
RefreshGoodsItems(result);
|
||||
}
|
||||
|
||||
private void ShopPurchase(object sender, GameEventArgs e)
|
||||
{
|
||||
if (!(sender is ShopForm))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(e is ShopPurchaseEventArgs args))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ShopPurchaseResult result = _useCase.TryPurchase(args.GoodsIndex);
|
||||
if (result == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ApplyGoodsPurchased(result);
|
||||
}
|
||||
|
||||
private void ShopContinue(object sender, GameEventArgs e)
|
||||
{
|
||||
if (!(sender is ShopForm))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(e is ShopContinueEventArgs))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_useCase?.Continue();
|
||||
}
|
||||
|
||||
private void DisplayItemShow(object sender, GameEventArgs e)
|
||||
{
|
||||
if (!(e is DisplayItemShowEventArgs args)) return;
|
||||
|
||||
DisplayItemInfoFormRawData rawData = new();
|
||||
rawData.TargetPos = args.TargetPos;
|
||||
if (args.IsWeapon)
|
||||
{
|
||||
var weaponData = _rawData.WeaponItems[args.Index].WeaponData;
|
||||
rawData.IconAssetName = weaponData.IconAssetName;
|
||||
rawData.Title = weaponData.Title;
|
||||
rawData.Rarity = weaponData.Rarity;
|
||||
rawData.TypeText = "武器";
|
||||
rawData.Description = ItemDescUtility.CreateWeaponDescription(weaponData);
|
||||
rawData.Price = 0;
|
||||
rawData.IsWeapon = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
var propItem = _rawData.PropItems[args.Index];
|
||||
rawData.IconAssetName = propItem.IconAssetName;
|
||||
rawData.Title = propItem.Title;
|
||||
rawData.Rarity = propItem.Rarity;
|
||||
rawData.TypeText = "道具";
|
||||
rawData.Description = ItemDescUtility.CreatePropDescription(propItem);
|
||||
rawData.Price = 0;
|
||||
rawData.IsWeapon = false;
|
||||
}
|
||||
|
||||
GameEntry.UIRouter.OpenUI(UIFormType.DisplayItemInfoForm, rawData);
|
||||
}
|
||||
|
||||
|
||||
private void DisplayItemHide(object sender, GameEventArgs e)
|
||||
{
|
||||
if (!(e is DisplayItemHideEventArgs)) return;
|
||||
|
||||
GameEntry.UIRouter.CloseUI(UIFormType.DisplayItemInfoForm);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ac5b4f32ba8b93e4f93b94bc402245bd
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,19 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Definition.Enum;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UI
|
||||
{
|
||||
public class DisplayItemInfoFormRawData
|
||||
{
|
||||
public string IconAssetName;
|
||||
public string Title;
|
||||
public string TypeText;
|
||||
public ItemRarity Rarity;
|
||||
public string Description;
|
||||
public int Price;
|
||||
public bool IsWeapon;
|
||||
public Vector3 TargetPos;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 012ded06be40bcf48b3e79ce89df4e2b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,11 @@
|
||||
using System.Collections.Generic;
|
||||
using DataTable;
|
||||
|
||||
namespace UI
|
||||
{
|
||||
public class LevelUpFormRawData
|
||||
{
|
||||
public List<DRLevelUpReward> Rewards;
|
||||
public int RefreshPrice;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a3ece8e2fb75f424cb4885d4344434d2
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,18 @@
|
||||
using System.Collections.Generic;
|
||||
using Definition.DataStruct;
|
||||
using Entity;
|
||||
|
||||
namespace UI
|
||||
{
|
||||
public class ShopFormRawData
|
||||
{
|
||||
public int CurrentLevel;
|
||||
public int RefreshPrice;
|
||||
public int PlayerCoin;
|
||||
public List<GoodsItemContext> GoodsItems;
|
||||
public IReadOnlyList<PropItem> PropItems;
|
||||
public int PropMaxCount = -1;
|
||||
public IReadOnlyList<WeaponBase> WeaponItems;
|
||||
public int WeaponMaxCount = -1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 533bff5f9d3bc7847af44dcd1cdffba3
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 134aefa2f7839e641b5824d665cbb8ef
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,74 @@
|
||||
using Definition.DataStruct;
|
||||
using Entity;
|
||||
using Game.Utility;
|
||||
using Procedure;
|
||||
|
||||
namespace UI
|
||||
{
|
||||
public class DisplayItemInfoFormUseCase : IUIUseCase
|
||||
{
|
||||
private readonly ProcedureGame _procedureGame;
|
||||
|
||||
private Player Player => _procedureGame != null ? _procedureGame.Player : null;
|
||||
|
||||
public DisplayItemInfoFormUseCase(ProcedureGame procedureGame)
|
||||
{
|
||||
_procedureGame = procedureGame;
|
||||
}
|
||||
|
||||
public DisplayItemInfoFormRawData CreateModel(int index, bool isWeapon)
|
||||
{
|
||||
if (index < 0 || Player == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (isWeapon)
|
||||
{
|
||||
var weapons = Player.Weapons;
|
||||
if (weapons == null || index >= weapons.Count)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
WeaponBase weapon = weapons[index];
|
||||
if (weapon == null || weapon.WeaponData == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return new DisplayItemInfoFormRawData
|
||||
{
|
||||
IconAssetName = weapon.WeaponData.IconAssetName,
|
||||
Title = weapon.WeaponData.Title,
|
||||
TypeText = "Weapon",
|
||||
Description = ItemDescUtility.CreateWeaponDescription(weapon),
|
||||
Price = 0,
|
||||
IsWeapon = true
|
||||
};
|
||||
}
|
||||
|
||||
var props = Player.Props;
|
||||
if (props == null || index >= props.Count)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
PropItem prop = props[index];
|
||||
if (prop == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return new DisplayItemInfoFormRawData
|
||||
{
|
||||
IconAssetName = prop.IconAssetName,
|
||||
Title = prop.Title,
|
||||
TypeText = "Prop",
|
||||
Description = ItemDescUtility.CreatePropDescription(prop),
|
||||
Price = 0,
|
||||
IsWeapon = false
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 48c1f32fe95e20c43b8015ac1438d54e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,137 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using DataTable;
|
||||
using Definition.DataStruct;
|
||||
using Definition.Enum;
|
||||
using Entity;
|
||||
using Procedure;
|
||||
using UnityEngine;
|
||||
using UnityGameFramework.Runtime;
|
||||
|
||||
namespace UI
|
||||
{
|
||||
internal class LevelUpFormUseCase : IUIUseCase
|
||||
{
|
||||
private const int BaseRefreshPrice = 2;
|
||||
private readonly GameStateLevelUp _gameStateLevelUp;
|
||||
private readonly DRLevelUpReward[] _allRewards;
|
||||
|
||||
private int _refreshCount;
|
||||
private LevelUpFormRawData _currentModel;
|
||||
|
||||
private readonly Player _player;
|
||||
|
||||
public LevelUpFormUseCase(Player player, GameStateLevelUp gameStateLevelUp)
|
||||
{
|
||||
_player = player;
|
||||
_gameStateLevelUp = gameStateLevelUp;
|
||||
_allRewards = GameEntry.DataTable.GetDataTable<DRLevelUpReward>().ToArray();
|
||||
}
|
||||
|
||||
public LevelUpFormRawData CreateInitialModel(int count = 4)
|
||||
{
|
||||
_refreshCount = 0;
|
||||
|
||||
if (_gameStateLevelUp == null || _player.PendingLevelPoints <= 0)
|
||||
{
|
||||
_currentModel = null;
|
||||
return null;
|
||||
}
|
||||
|
||||
_currentModel = BuildModel(BaseRefreshPrice, count);
|
||||
return _currentModel;
|
||||
}
|
||||
|
||||
public LevelUpFormRawData TryRefresh(int refreshCost, int count = 4)
|
||||
{
|
||||
if (_currentModel == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (_player == null || _player.Coin < refreshCost)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
_player.Coin -= refreshCost;
|
||||
|
||||
_refreshCount++;
|
||||
_currentModel = BuildModel((_refreshCount + 1) * BaseRefreshPrice, count);
|
||||
return _currentModel;
|
||||
}
|
||||
|
||||
public LevelUpFormRawData SelectReward(int selectedIndex, int count = 4)
|
||||
{
|
||||
if (_currentModel?.Rewards == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (selectedIndex < 0 || selectedIndex >= _currentModel.Rewards.Count)
|
||||
{
|
||||
Log.Warning("LevelUpFormUseCase::SelectReward: Invalid index");
|
||||
return null;
|
||||
}
|
||||
|
||||
ApplyReward(_currentModel.Rewards[selectedIndex]);
|
||||
|
||||
if (--_player.PendingLevelPoints > 0)
|
||||
{
|
||||
_refreshCount = 0;
|
||||
_currentModel = BuildModel(BaseRefreshPrice, count);
|
||||
return _currentModel;
|
||||
}
|
||||
|
||||
_gameStateLevelUp.IsCompleted = true;
|
||||
_currentModel = null;
|
||||
return null;
|
||||
}
|
||||
|
||||
private LevelUpFormRawData BuildModel(int refreshPrice, int count)
|
||||
{
|
||||
if (_allRewards == null || _allRewards.Length == 0)
|
||||
{
|
||||
Log.Error("LevelUpFormUseCase::BuildModel(): _allRewards is empty");
|
||||
return null;
|
||||
}
|
||||
|
||||
int finalCount = count > 0 ? System.Math.Min(count, _allRewards.Length) : _allRewards.Length;
|
||||
List<DRLevelUpReward> selections = new List<DRLevelUpReward>(finalCount);
|
||||
|
||||
for (int i = 0; i < finalCount; i++)
|
||||
{
|
||||
int index = Random.Range(0, _allRewards.Length);
|
||||
selections.Add(_allRewards[index]);
|
||||
}
|
||||
|
||||
return new LevelUpFormRawData
|
||||
{
|
||||
Rewards = selections,
|
||||
RefreshPrice = refreshPrice
|
||||
};
|
||||
}
|
||||
|
||||
private void ApplyReward(DRLevelUpReward reward)
|
||||
{
|
||||
if (reward == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (_player == null)
|
||||
{
|
||||
Log.Warning("LevelUpFormUseCase::ApplyReward: Player is null");
|
||||
return;
|
||||
}
|
||||
|
||||
if (reward.Modifiers == null || reward.Modifiers.Length == 0)
|
||||
{
|
||||
Log.Warning("LevelUpFormUseCase::ApplyReward: Reward modifiers are empty");
|
||||
return;
|
||||
}
|
||||
|
||||
_player.AddProp(new PropItem(reward.Modifiers, ItemRarity.White, reward.Title, reward.IconAssetName));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 19d2fa806b03510498d072c5b8710bcb
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,248 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using DataTable;
|
||||
using Definition.DataStruct;
|
||||
using Definition.Enum;
|
||||
using Entity;
|
||||
using Game.Utility;
|
||||
using GameFramework.DataTable;
|
||||
using Procedure;
|
||||
using UnityEngine;
|
||||
using UnityGameFramework.Runtime;
|
||||
using Random = UnityEngine.Random;
|
||||
|
||||
namespace UI
|
||||
{
|
||||
internal sealed class ShopRefreshResult
|
||||
{
|
||||
public List<GoodsItemContext> GoodsItems;
|
||||
public int RefreshPrice;
|
||||
}
|
||||
|
||||
internal sealed class ShopPurchaseResult
|
||||
{
|
||||
public int GoodsIndex;
|
||||
public DisplayItemContext DisplayItem;
|
||||
}
|
||||
|
||||
internal class ShopFormUseCase : IUIUseCase
|
||||
{
|
||||
private readonly ProcedureGame _procedureGame;
|
||||
private readonly GameStateShop _gameStateShop;
|
||||
|
||||
private readonly DRGoods[] _allGoods;
|
||||
private readonly IDataTable<DRProp> _propDataTable;
|
||||
private readonly IDataTable<DRWeapon> _weaponDataTable;
|
||||
|
||||
private readonly List<ShopGoodsSelection> _selections = new();
|
||||
private int _refreshTime;
|
||||
|
||||
private Player Player => _procedureGame.Player;
|
||||
|
||||
private sealed class ShopGoodsSelection
|
||||
{
|
||||
public GoodsType GoodsType;
|
||||
public int GoodsTypeId;
|
||||
public int Price;
|
||||
}
|
||||
|
||||
public ShopFormUseCase(ProcedureGame procedureGame, GameStateShop gameStateShop)
|
||||
{
|
||||
_procedureGame = procedureGame;
|
||||
_gameStateShop = gameStateShop;
|
||||
_allGoods = GameEntry.DataTable.GetDataTable<DRGoods>().ToArray();
|
||||
_propDataTable = GameEntry.DataTable.GetDataTable<DRProp>();
|
||||
_weaponDataTable = GameEntry.DataTable.GetDataTable<DRWeapon>();
|
||||
}
|
||||
|
||||
public ShopFormRawData CreateInitialModel()
|
||||
{
|
||||
_refreshTime = 0;
|
||||
|
||||
Player player = Player;
|
||||
if (_procedureGame == null || player == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
int currentLevel = _procedureGame.CurrentLevel;
|
||||
return new ShopFormRawData
|
||||
{
|
||||
CurrentLevel = currentLevel,
|
||||
RefreshPrice = currentLevel,
|
||||
PlayerCoin = player.Coin,
|
||||
GoodsItems = BuildRandomGoodsItems(4),
|
||||
PropItems = player.Props,
|
||||
PropMaxCount = -1,
|
||||
WeaponItems = player.Weapons,
|
||||
WeaponMaxCount = player.WeaponCapacity
|
||||
};
|
||||
}
|
||||
|
||||
public ShopRefreshResult TryRefresh(int cost)
|
||||
{
|
||||
Player player = Player;
|
||||
if (player == null || _procedureGame == null || player.Coin < cost)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
player.Coin -= cost;
|
||||
|
||||
int refreshPrice = (_refreshTime + 1) * _procedureGame.CurrentLevel;
|
||||
_refreshTime++;
|
||||
|
||||
return new ShopRefreshResult
|
||||
{
|
||||
GoodsItems = BuildRandomGoodsItems(4),
|
||||
RefreshPrice = refreshPrice
|
||||
};
|
||||
}
|
||||
|
||||
public ShopPurchaseResult TryPurchase(int goodsIndex)
|
||||
{
|
||||
if (goodsIndex < 0 || goodsIndex >= _selections.Count)
|
||||
{
|
||||
Log.Warning("ShopFormUseCase::TryPurchase: Invalid index");
|
||||
return null;
|
||||
}
|
||||
|
||||
ShopGoodsSelection selection = _selections[goodsIndex];
|
||||
if (selection == null)
|
||||
{
|
||||
Log.Warning("ShopFormUseCase::TryPurchase: Item already purchased.");
|
||||
return null;
|
||||
}
|
||||
|
||||
Player player = Player;
|
||||
if (player == null || player.Coin < selection.Price)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
player.Coin -= selection.Price;
|
||||
DisplayItemContext displayItem = ApplyGoodsPurchase(selection);
|
||||
_selections[goodsIndex] = null;
|
||||
|
||||
return new ShopPurchaseResult
|
||||
{
|
||||
GoodsIndex = goodsIndex,
|
||||
DisplayItem = displayItem
|
||||
};
|
||||
}
|
||||
|
||||
public void Continue()
|
||||
{
|
||||
_gameStateShop.ShopFinish = true;
|
||||
}
|
||||
|
||||
private List<GoodsItemContext> BuildRandomGoodsItems(int count)
|
||||
{
|
||||
if (_allGoods == null || _allGoods.Length == 0)
|
||||
{
|
||||
Log.Error("ShopFormUseCase::BuildRandomGoodsItems(): _allGoods is empty");
|
||||
return null;
|
||||
}
|
||||
|
||||
int finalCount = Mathf.Min(count, _allGoods.Length);
|
||||
List<GoodsItemContext> goodsItems = new List<GoodsItemContext>(finalCount);
|
||||
_selections.Clear();
|
||||
|
||||
for (int i = 0; i < finalCount; i++)
|
||||
{
|
||||
int index = Random.Range(0, _allGoods.Length);
|
||||
DRGoods drGoods = _allGoods[index];
|
||||
GoodsItemContext goodsItem = new GoodsItemContext();
|
||||
int price;
|
||||
|
||||
if (drGoods.GoodsType == GoodsType.Prop)
|
||||
{
|
||||
DRProp drProp = _propDataTable.GetDataRow(drGoods.GoodsTypeId);
|
||||
if (drProp == null)
|
||||
{
|
||||
Log.Warning($"ShopFormUseCase::BuildRandomGoodsItems: Missing DRProp, id = {drGoods.GoodsTypeId}");
|
||||
continue;
|
||||
}
|
||||
|
||||
price = CalculateRandomizedPrice(drProp.Price, drProp.PriceRandomPercent);
|
||||
goodsItem.Title = drProp.Title;
|
||||
goodsItem.Type = "Prop";
|
||||
goodsItem.Rarity = drProp.Rarity;
|
||||
GameEntry.SpriteCache.GetSprite(drProp.IconAssetName, sprite => goodsItem.Icon = sprite);
|
||||
goodsItem.Description = ItemDescUtility.CreatePropDescription(drProp.Modifiers);
|
||||
}
|
||||
else if (drGoods.GoodsType == GoodsType.Weapon)
|
||||
{
|
||||
DRWeapon drWeapon = _weaponDataTable.GetDataRow(drGoods.GoodsTypeId);
|
||||
if (drWeapon == null)
|
||||
{
|
||||
Log.Warning($"ShopFormUseCase::BuildRandomGoodsItems: Missing DRWeapon, id = {drGoods.GoodsTypeId}");
|
||||
continue;
|
||||
}
|
||||
|
||||
price = CalculateRandomizedPrice(drWeapon.Price, drWeapon.PriceRandomPercent);
|
||||
goodsItem.Title = drWeapon.Title;
|
||||
goodsItem.Type = "Weapon";
|
||||
goodsItem.Rarity = drWeapon.Rarity;
|
||||
GameEntry.SpriteCache.GetSprite(drWeapon.IconAssetName, sprite => goodsItem.Icon = sprite);
|
||||
goodsItem.Description = ItemDescUtility.CreateWeaponDescription(drWeapon);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.Warning($"ShopFormUseCase::BuildRandomGoodsItems: Unsupported goods type = {drGoods.GoodsType}");
|
||||
continue;
|
||||
}
|
||||
|
||||
goodsItem.Price = price;
|
||||
|
||||
_selections.Add(new ShopGoodsSelection
|
||||
{
|
||||
GoodsType = drGoods.GoodsType,
|
||||
GoodsTypeId = drGoods.GoodsTypeId,
|
||||
Price = price
|
||||
});
|
||||
|
||||
goodsItems.Add(goodsItem);
|
||||
}
|
||||
|
||||
return goodsItems;
|
||||
}
|
||||
|
||||
private static int CalculateRandomizedPrice(int basePrice, float priceRandomPercent)
|
||||
{
|
||||
float normalizedPercent = priceRandomPercent > 1f ? priceRandomPercent / 100f : priceRandomPercent;
|
||||
normalizedPercent = Mathf.Max(0f, normalizedPercent);
|
||||
float offsetPercent = Random.Range(-normalizedPercent, normalizedPercent);
|
||||
int finalPrice = Mathf.RoundToInt(basePrice * (1f + offsetPercent));
|
||||
return Mathf.Max(1, finalPrice);
|
||||
}
|
||||
|
||||
private DisplayItemContext ApplyGoodsPurchase(ShopGoodsSelection goods)
|
||||
{
|
||||
if (goods == null || Player == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (goods.GoodsType == GoodsType.Prop)
|
||||
{
|
||||
DRProp drProp = _propDataTable != null ? _propDataTable.GetDataRow(goods.GoodsTypeId) : null;
|
||||
if (drProp == null || drProp.Modifiers == null || drProp.Modifiers.Length == 0)
|
||||
{
|
||||
Log.Warning("ShopFormUseCase::ApplyGoodsPurchase: Prop modifiers are empty");
|
||||
return null;
|
||||
}
|
||||
|
||||
Player.AddProp(new PropItem(drProp.Modifiers, drProp.Rarity, drProp.Title, drProp.IconAssetName));
|
||||
return new DisplayItemContext
|
||||
{
|
||||
IconAssetName = drProp.IconAssetName,
|
||||
Rarity = drProp.Rarity,
|
||||
IsWeapon = false
|
||||
};
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e973748d1bd846349d42e219a80f07c2
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,59 @@
|
||||
using CustomEvent;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace UI
|
||||
{
|
||||
public class DisplayItem : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private IconArea _iconArea;
|
||||
|
||||
[SerializeField] private RectTransform _itemRect;
|
||||
|
||||
private DisplayItemContext _context;
|
||||
|
||||
private int _index = -1;
|
||||
|
||||
public void OnInit(DisplayItemContext context, int index)
|
||||
{
|
||||
if (context == null) return;
|
||||
|
||||
_context = context;
|
||||
_index = index;
|
||||
|
||||
if (_iconArea != null)
|
||||
{
|
||||
string iconName = _context.IconAssetName;
|
||||
GameEntry.SpriteCache.GetSprite(iconName, sprite => { _iconArea.OnInit(sprite, context.Rarity); });
|
||||
}
|
||||
}
|
||||
|
||||
public void OnReset()
|
||||
{
|
||||
_context = null;
|
||||
_index = -1;
|
||||
|
||||
if (_iconArea != null)
|
||||
{
|
||||
_iconArea.OnReset();
|
||||
}
|
||||
}
|
||||
|
||||
public void OnItemInfoShow()
|
||||
{
|
||||
if (_index < 0) return;
|
||||
Vector3 targetPos = _itemRect.position + new Vector3(0, _itemRect.sizeDelta.y / 2, 0);
|
||||
GameEntry.Event.Fire(this, DisplayItemShowEventArgs.Create(_index, _context.IsWeapon, targetPos));
|
||||
}
|
||||
|
||||
public void SetIndex(int index)
|
||||
{
|
||||
_index = index;
|
||||
}
|
||||
|
||||
public void OnItemInfoHide()
|
||||
{
|
||||
GameEntry.Event.Fire(this, DisplayItemHideEventArgs.Create());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7fe0ad0e96348114786974bb02d62914
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,191 @@
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityGameFramework.Runtime;
|
||||
|
||||
namespace UI
|
||||
{
|
||||
public class DisplayItemInfoForm : 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 DisplayItemInfoFormContext _context;
|
||||
private Vector3 _targetPos;
|
||||
|
||||
public void RefreshUI(DisplayItemInfoFormContext context)
|
||||
{
|
||||
if (context == null)
|
||||
{
|
||||
Log.Warning("DisplayItemInfoForm context is invalid.");
|
||||
return;
|
||||
}
|
||||
|
||||
_context = context;
|
||||
|
||||
_targetPos = ConvertWorldToAnchored(_context.TargetPos);
|
||||
|
||||
if (_content != null)
|
||||
{
|
||||
_content.anchoredPosition3D = _targetPos;
|
||||
}
|
||||
|
||||
if (_itemTitle != null) _itemTitle.text = _context.Title ?? string.Empty;
|
||||
if (_itemTypeText != null) _itemTypeText.text = _context.TypeText ?? string.Empty;
|
||||
if (_itemDescription != null) _itemDescription.text = _context.Description ?? string.Empty;
|
||||
if (_itemPrice != null) _itemPrice.text = $"{_context.Price} <sprite name=\"coin\" index=0>";
|
||||
|
||||
if (_recycleButton != null)
|
||||
{
|
||||
_recycleButton.gameObject.SetActive(_context.IsWeapon);
|
||||
}
|
||||
|
||||
if (_iconArea != null)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(_context.IconAssetName))
|
||||
{
|
||||
string iconAssetName = _context.IconAssetName;
|
||||
GameEntry.SpriteCache.GetSprite(iconAssetName, sprite =>
|
||||
{
|
||||
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 DisplayItemInfoFormContext context))
|
||||
{
|
||||
Log.Error("DisplayItemInfoFormContext is invalid.");
|
||||
return;
|
||||
}
|
||||
|
||||
RefreshUI(context);
|
||||
}
|
||||
|
||||
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>();
|
||||
Camera uiCamera = null;
|
||||
if (canvas != null && canvas.renderMode != RenderMode.ScreenSpaceOverlay)
|
||||
{
|
||||
uiCamera = canvas.worldCamera;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 32469245f20597240a3c51d2cd1fb0c5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,27 @@
|
||||
using GameFramework;
|
||||
using GameFramework.ObjectPool;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UI
|
||||
{
|
||||
public class DisplayItemObject : ObjectBase
|
||||
{
|
||||
public static DisplayItemObject Create(object target)
|
||||
{
|
||||
DisplayItemObject displayItemObject = ReferencePool.Acquire<DisplayItemObject>();
|
||||
displayItemObject.Initialize(target);
|
||||
return displayItemObject;
|
||||
}
|
||||
|
||||
protected override void Release(bool isShutdown)
|
||||
{
|
||||
DisplayItem item = (DisplayItem)Target;
|
||||
if (item == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Object.Destroy(item.gameObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f21ab051c635de04998b80804d9bafe5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,278 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using GameFramework.ObjectPool;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityGameFramework.Runtime;
|
||||
|
||||
namespace UI
|
||||
{
|
||||
public class DisplayListArea : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private TMP_Text _titleText;
|
||||
|
||||
[SerializeField] private TMP_Text _countText;
|
||||
|
||||
[SerializeField] private DisplayItem _displayItemTemplate;
|
||||
|
||||
[SerializeField] private Transform _displayItemRoot;
|
||||
|
||||
[SerializeField] private Vector2 _startPosition = Vector2.zero;
|
||||
|
||||
[SerializeField] private float _itemSize = 150f;
|
||||
|
||||
[SerializeField] private float _itemSpacing = 10f;
|
||||
|
||||
[SerializeField] private int _fixedColumnCount = 0;
|
||||
|
||||
[SerializeField] private int _instancePoolCapacity = 32;
|
||||
|
||||
private DisplayListAreaContext _context;
|
||||
|
||||
private IObjectPool<DisplayItemObject> _displayItemObjectPool;
|
||||
private const string DisplayItemPoolName = "DisplayItem";
|
||||
|
||||
private readonly List<DisplayItem> _activeItems = new List<DisplayItem>();
|
||||
|
||||
public void OnInit(DisplayListAreaContext context)
|
||||
{
|
||||
if (context == null)
|
||||
{
|
||||
Log.Warning("DisplayListArea context is invalid.");
|
||||
return;
|
||||
}
|
||||
|
||||
EnsurePool();
|
||||
_context = context;
|
||||
|
||||
if (_titleText != null) _titleText.text = context.Title;
|
||||
UpdateCountText(context.CurrentCount, context.MaxCount);
|
||||
|
||||
int itemCount = context.ItemContexts?.Length ?? 0;
|
||||
int targetCount = Mathf.Min(context.CurrentCount, itemCount);
|
||||
EnsureItemCount(targetCount);
|
||||
for (int i = 0; i < targetCount; i++)
|
||||
{
|
||||
_activeItems[i].OnInit(context.ItemContexts[i], i);
|
||||
}
|
||||
|
||||
LayoutItems();
|
||||
}
|
||||
|
||||
public void OnReset()
|
||||
{
|
||||
_context = null;
|
||||
|
||||
for (int i = _activeItems.Count - 1; i >= 0; i--)
|
||||
{
|
||||
HideItem(_activeItems[i]);
|
||||
}
|
||||
}
|
||||
|
||||
public void OnDestroy()
|
||||
{
|
||||
_displayItemObjectPool.ReleaseAllUnused();
|
||||
}
|
||||
|
||||
public DisplayItem AddItem(DisplayItemContext itemContext)
|
||||
{
|
||||
EnsurePool();
|
||||
if (_displayItemObjectPool == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
DisplayItem item = CreateItem();
|
||||
if (item == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
int index = _activeItems.Count;
|
||||
_activeItems.Add(item);
|
||||
item.OnInit(itemContext, index);
|
||||
item.SetIndex(index);
|
||||
|
||||
int columnCount = _fixedColumnCount > 0 ? _fixedColumnCount : CalculateColumnCount(GetRootWidth());
|
||||
LayoutItem(item, index, columnCount);
|
||||
|
||||
int currentCount = _activeItems.Count;
|
||||
int maxCount = _context != null ? _context.MaxCount : -1;
|
||||
if (_context != null)
|
||||
{
|
||||
_context.CurrentCount = currentCount;
|
||||
}
|
||||
|
||||
UpdateCountText(currentCount, maxCount);
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
public bool RemoveItemAt(int index)
|
||||
{
|
||||
if (index < 0 || index >= _activeItems.Count)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
HideItem(_activeItems[index]);
|
||||
LayoutItems();
|
||||
|
||||
int currentCount = _activeItems.Count;
|
||||
int maxCount = _context != null ? _context.MaxCount : -1;
|
||||
if (_context != null)
|
||||
{
|
||||
_context.CurrentCount = currentCount;
|
||||
}
|
||||
|
||||
UpdateCountText(currentCount, maxCount);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void EnsurePool()
|
||||
{
|
||||
if (_displayItemObjectPool != null) return;
|
||||
|
||||
if (_displayItemRoot == null)
|
||||
{
|
||||
_displayItemRoot = transform;
|
||||
}
|
||||
|
||||
GridLayoutGroup gridLayout = _displayItemRoot.GetComponent<GridLayoutGroup>();
|
||||
if (gridLayout != null)
|
||||
{
|
||||
gridLayout.enabled = false;
|
||||
}
|
||||
|
||||
if (GameEntry.ObjectPool.HasObjectPool<DisplayItemObject>(DisplayItemPoolName))
|
||||
{
|
||||
_displayItemObjectPool = GameEntry.ObjectPool.GetObjectPool<DisplayItemObject>(DisplayItemPoolName);
|
||||
return;
|
||||
}
|
||||
|
||||
if (_displayItemTemplate == null)
|
||||
{
|
||||
Debug.LogError("DisplayListArea requires a DisplayItem template.");
|
||||
return;
|
||||
}
|
||||
|
||||
_displayItemObjectPool =
|
||||
GameEntry.ObjectPool.CreateSingleSpawnObjectPool<DisplayItemObject>(DisplayItemPoolName,
|
||||
_instancePoolCapacity);
|
||||
}
|
||||
|
||||
private void EnsureItemCount(int count)
|
||||
{
|
||||
if (_displayItemObjectPool == null) return;
|
||||
|
||||
for (int i = _activeItems.Count; i < count; i++)
|
||||
{
|
||||
DisplayItem item = CreateItem();
|
||||
if (item == null)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
_activeItems.Add(item);
|
||||
}
|
||||
|
||||
for (int i = _activeItems.Count - 1; i >= count; i--)
|
||||
{
|
||||
HideItem(_activeItems[i]);
|
||||
}
|
||||
}
|
||||
|
||||
private DisplayItem CreateItem()
|
||||
{
|
||||
DisplayItem item = null;
|
||||
DisplayItemObject itemObject = _displayItemObjectPool.Spawn();
|
||||
if (itemObject != null)
|
||||
{
|
||||
item = (DisplayItem)itemObject.Target;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_displayItemTemplate == null)
|
||||
{
|
||||
Debug.LogError("DisplayListArea requires a DisplayItem template.");
|
||||
return null;
|
||||
}
|
||||
|
||||
item = Instantiate(_displayItemTemplate);
|
||||
_displayItemObjectPool.Register(DisplayItemObject.Create(item), true);
|
||||
}
|
||||
|
||||
if (_displayItemRoot != null)
|
||||
{
|
||||
Transform itemTransform = item.transform;
|
||||
itemTransform.SetParent(_displayItemRoot, false);
|
||||
}
|
||||
|
||||
item.gameObject.SetActive(true);
|
||||
return item;
|
||||
}
|
||||
|
||||
private void HideItem(DisplayItem item)
|
||||
{
|
||||
if (item == null) return;
|
||||
item.OnReset();
|
||||
_activeItems.Remove(item);
|
||||
item.gameObject.SetActive(false);
|
||||
_displayItemObjectPool?.Unspawn(item);
|
||||
}
|
||||
|
||||
private void LayoutItems()
|
||||
{
|
||||
if (_displayItemRoot == null) return;
|
||||
|
||||
int columnCount = _fixedColumnCount > 0 ? _fixedColumnCount : CalculateColumnCount(GetRootWidth());
|
||||
|
||||
for (int i = 0; i < _activeItems.Count; i++)
|
||||
{
|
||||
DisplayItem item = _activeItems[i];
|
||||
item.SetIndex(i);
|
||||
LayoutItem(item, i, columnCount);
|
||||
}
|
||||
}
|
||||
|
||||
private void LayoutItem(DisplayItem item, int index, int columnCount)
|
||||
{
|
||||
if (item == null) return;
|
||||
RectTransform itemRect = item.GetComponent<RectTransform>();
|
||||
if (itemRect == null) return;
|
||||
|
||||
float step = _itemSize + _itemSpacing;
|
||||
int row = index / columnCount;
|
||||
int col = index % columnCount;
|
||||
|
||||
itemRect.anchorMin = new Vector2(0f, 1f);
|
||||
itemRect.anchorMax = new Vector2(0f, 1f);
|
||||
itemRect.pivot = new Vector2(0f, 1f);
|
||||
itemRect.sizeDelta = new Vector2(_itemSize, _itemSize);
|
||||
itemRect.anchoredPosition = _startPosition + new Vector2(col * step, -row * step);
|
||||
}
|
||||
|
||||
private float GetRootWidth()
|
||||
{
|
||||
RectTransform rootRect = _displayItemRoot as RectTransform;
|
||||
return rootRect != null ? rootRect.rect.width : 0f;
|
||||
}
|
||||
|
||||
private int CalculateColumnCount(float rootWidth)
|
||||
{
|
||||
if (rootWidth <= 0f) return 1;
|
||||
|
||||
float step = _itemSize + _itemSpacing;
|
||||
int columns = Mathf.FloorToInt((rootWidth + _itemSpacing) / step);
|
||||
return Mathf.Max(1, columns);
|
||||
}
|
||||
|
||||
private void UpdateCountText(int currentCount, int maxCount)
|
||||
{
|
||||
if (_countText == null) return;
|
||||
_countText.text = maxCount == -1 ? $"({currentCount})" : $"({currentCount}/{maxCount})";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 58c6ff306e4be41458bdf4dd82ad92e1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -13,32 +13,47 @@ namespace UI
|
||||
[SerializeField] private float _sliderFadeDuration = 0.5f;
|
||||
|
||||
[SerializeField] private Slider _hpSlider;
|
||||
|
||||
[SerializeField] private TMP_Text _hpText;
|
||||
|
||||
private float _currentHpPercent = 0;
|
||||
private Coroutine _hpSliderFadeCoroutine;
|
||||
|
||||
[SerializeField] private Slider _expSlider;
|
||||
|
||||
private float _currentExpPercent = 0;
|
||||
private Coroutine _expSliderFadeCoroutine;
|
||||
|
||||
[SerializeField] private TMP_Text _expText;
|
||||
|
||||
private int _playerCurrentLevel = 1;
|
||||
|
||||
[SerializeField] private TMP_Text _coinText;
|
||||
private int _currentCoin = 0;
|
||||
|
||||
public void RefreshUI(HudFormContext hudFormContext)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
#region FSM
|
||||
|
||||
protected override void OnInit(object userData)
|
||||
{
|
||||
base.OnInit(userData);
|
||||
|
||||
GameEntry.Event.Subscribe(PlayerHealthChangeEventArgs.EventId, OnPlayerHpChange);
|
||||
GameEntry.Event.Subscribe(PlayerExpChangeEventArgs.EventId, OnPlayerExpChange);
|
||||
GameEntry.Event.Subscribe(PlayerCoinChangeEventArgs.EventId, OnPlayerCoinChange);
|
||||
GameEntry.Event.Subscribe(PlayerHealthChangeEventArgs.EventId, PlayerHpChange);
|
||||
GameEntry.Event.Subscribe(PlayerExpChangeEventArgs.EventId, PlayerExpChange);
|
||||
GameEntry.Event.Subscribe(PlayerCoinChangeEventArgs.EventId, PlayerCoinChange);
|
||||
GameEntry.Event.Subscribe(PlayerLevelUpEventArgs.EventId, PlayerLevelUp);
|
||||
}
|
||||
|
||||
protected override void OnClose(bool isShutdown, object userData)
|
||||
{
|
||||
GameEntry.Event.Unsubscribe(PlayerHealthChangeEventArgs.EventId, OnPlayerHpChange);
|
||||
GameEntry.Event.Unsubscribe(PlayerExpChangeEventArgs.EventId, OnPlayerExpChange);
|
||||
GameEntry.Event.Unsubscribe(PlayerCoinChangeEventArgs.EventId, OnPlayerCoinChange);
|
||||
GameEntry.Event.Unsubscribe(PlayerLevelUpEventArgs.EventId, PlayerLevelUp);
|
||||
GameEntry.Event.Unsubscribe(PlayerHealthChangeEventArgs.EventId, PlayerHpChange);
|
||||
GameEntry.Event.Unsubscribe(PlayerExpChangeEventArgs.EventId, PlayerExpChange);
|
||||
GameEntry.Event.Unsubscribe(PlayerCoinChangeEventArgs.EventId, PlayerCoinChange);
|
||||
|
||||
base.OnClose(isShutdown, userData);
|
||||
}
|
||||
@@ -47,9 +62,12 @@ namespace UI
|
||||
|
||||
#region Event Handlers
|
||||
|
||||
private void OnPlayerHpChange(object sender, GameEventArgs e)
|
||||
private void PlayerHpChange(object sender, GameEventArgs e)
|
||||
{
|
||||
if (!(e is PlayerHealthChangeEventArgs args)) return;
|
||||
|
||||
_hpText.text = $"{args.CurrentHealth}/{args.MaxHealth}";
|
||||
|
||||
float percent = (float)args.CurrentHealth / args.MaxHealth;
|
||||
if (Mathf.Approximately(_currentHpPercent, percent)) return;
|
||||
|
||||
@@ -59,7 +77,7 @@ namespace UI
|
||||
_hpSliderFadeCoroutine = StartCoroutine(_hpSlider.SmoothValue(percent, _sliderFadeDuration));
|
||||
}
|
||||
|
||||
private void OnPlayerExpChange(object sender, GameEventArgs e)
|
||||
private void PlayerExpChange(object sender, GameEventArgs e)
|
||||
{
|
||||
if (!(e is PlayerExpChangeEventArgs args)) return;
|
||||
float percent = (float)args.CurrentExp / args.MaxExp;
|
||||
@@ -71,12 +89,20 @@ namespace UI
|
||||
_expSliderFadeCoroutine = StartCoroutine(_expSlider.SmoothValue(percent, _sliderFadeDuration));
|
||||
}
|
||||
|
||||
private void OnPlayerCoinChange(object sender, GameEventArgs e)
|
||||
private void PlayerLevelUp(object sender, GameEventArgs e)
|
||||
{
|
||||
if (!(e is PlayerLevelUpEventArgs)) return;
|
||||
|
||||
_playerCurrentLevel++;
|
||||
_expText.text = $"LV.{_playerCurrentLevel}";
|
||||
}
|
||||
|
||||
private void PlayerCoinChange(object sender, GameEventArgs e)
|
||||
{
|
||||
if (!(e is PlayerCoinChangeEventArgs args)) return;
|
||||
if (_currentCoin == args.CoinCount) return;
|
||||
|
||||
_coinText.text = args.CoinCount.ToString();
|
||||
_coinText.text = $"<sprite name=\"coin\" index=0> {args.CoinCount}";
|
||||
_currentCoin = args.CoinCount;
|
||||
}
|
||||
|
||||
@@ -100,4 +126,4 @@ namespace UI
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,21 +7,16 @@ namespace UI
|
||||
{
|
||||
public class LevelUpForm : UGuiForm
|
||||
{
|
||||
[SerializeField] private TMP_Text _titleText;
|
||||
[SerializeField] private LevelUpRewardItem[] _propItems;
|
||||
|
||||
[SerializeField] private LevelUpPropItem[] _propItems;
|
||||
[SerializeField] private TMP_Text _refreshButtonText;
|
||||
|
||||
private LevelUpFormContext _context;
|
||||
|
||||
public void RefreshUI(LevelUpFormContext context)
|
||||
{
|
||||
_context = context;
|
||||
|
||||
if (_titleText != null)
|
||||
{
|
||||
_titleText.text = $"Level Up (Lv.{_context.Level})";
|
||||
}
|
||||
|
||||
|
||||
foreach (var propItem in _propItems)
|
||||
{
|
||||
propItem.gameObject.SetActive(false);
|
||||
@@ -33,6 +28,9 @@ namespace UI
|
||||
_propItems[i].gameObject.SetActive(true);
|
||||
_propItems[i].Init(_context.Props[i]);
|
||||
}
|
||||
|
||||
//刷新 -20 <sprite name="coin" index=0>
|
||||
_refreshButtonText.text = $"刷新 -{context.RefreshPrice} <sprite name=\"coin\" index=0>";
|
||||
}
|
||||
|
||||
#region FSM
|
||||
@@ -58,9 +56,14 @@ namespace UI
|
||||
|
||||
#endregion
|
||||
|
||||
private void OnSelectProp(int index)
|
||||
public void OnSelectButtonClick(int index)
|
||||
{
|
||||
GameEntry.Event.Fire(this, LevelUpPropSelectedEventArgs.Create(index));
|
||||
}
|
||||
|
||||
public void OnRefreshButtonClick()
|
||||
{
|
||||
GameEntry.Event.Fire(this, RefreshEventArgs.Create(_context.RefreshPrice));
|
||||
}
|
||||
}
|
||||
}
|
||||
+7
-10
@@ -1,15 +1,13 @@
|
||||
using System;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
using UnityEngine.UI;
|
||||
using UnityGameFramework.Runtime;
|
||||
|
||||
namespace UI
|
||||
{
|
||||
public class LevelUpPropItem : MonoBehaviour
|
||||
public class LevelUpRewardItem : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private Image _iconImage;
|
||||
[SerializeField] private IconArea _iconArea;
|
||||
|
||||
[SerializeField] private TMP_Text _titleText;
|
||||
|
||||
@@ -17,10 +15,10 @@ namespace UI
|
||||
|
||||
[SerializeField] private TMP_Text _descriptionText;
|
||||
|
||||
private LevelUpPropContext _context;
|
||||
private LevelUpRewardItemContext _context;
|
||||
|
||||
|
||||
public void Init(LevelUpPropContext context)
|
||||
public void Init(LevelUpRewardItemContext context)
|
||||
{
|
||||
if (context == null)
|
||||
{
|
||||
@@ -31,20 +29,19 @@ namespace UI
|
||||
_context = context;
|
||||
|
||||
if (_titleText != null) _titleText.text = context.Title;
|
||||
if (_typeText != null) _typeText.text = context.Type;
|
||||
if (_descriptionText != null) _descriptionText.text = context.Description;
|
||||
if (_iconImage != null) _iconImage.sprite = context.Icon;
|
||||
if (_iconArea != null) _iconArea.SetIcon(context.Icon);
|
||||
|
||||
LoadIcon(_context.IconAssetName);
|
||||
}
|
||||
|
||||
private void LoadIcon(string iconAssetName)
|
||||
{
|
||||
if (_iconImage == null) return;
|
||||
if (_iconArea == null) return;
|
||||
|
||||
if (string.IsNullOrEmpty(iconAssetName)) return;
|
||||
|
||||
GameEntry.SpriteCache.GetSprite(iconAssetName, sprite => _iconImage.sprite = sprite);
|
||||
GameEntry.SpriteCache.GetSprite(iconAssetName, sprite => _iconArea.SetIcon(sprite));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,9 @@
|
||||
using System.Collections.Generic;
|
||||
using CustomEvent;
|
||||
using GameFramework.Event;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using UnityGameFramework.Runtime;
|
||||
|
||||
namespace UI
|
||||
{
|
||||
@@ -18,7 +20,11 @@ namespace UI
|
||||
[SerializeField] private TMP_Text _playerCoinText;
|
||||
private int _currentCoin;
|
||||
|
||||
[SerializeField] private GoodsItem[] _goodsItems;
|
||||
[SerializeField] private ShopGoodsItem[] _goodsItems;
|
||||
|
||||
[SerializeField] private DisplayListArea _propListArea;
|
||||
|
||||
[SerializeField] private DisplayListArea _weaponListArea;
|
||||
|
||||
private ShopFormContext _context;
|
||||
|
||||
@@ -31,22 +37,89 @@ namespace UI
|
||||
|
||||
_titleText.text = $"商店 (Lv.{context.CurrentLevel})";
|
||||
_continueButtonText.text = $"继续 (Lv.{context.CurrentLevel + 1})";
|
||||
_refreshPriceText.text = $"-{context.RefreshPrice}";
|
||||
_playerCoinText.text = context.PlayerCoin.ToString();
|
||||
RefreshRefreshPrice(context.RefreshPrice);
|
||||
_playerCoinText.text = $"<sprite name=\"coin\" index=0> {context.PlayerCoin}";
|
||||
|
||||
RefreshGoodsItems(context.GoodsItems);
|
||||
|
||||
if (_propListArea != null && context.PropListContext != null)
|
||||
{
|
||||
_propListArea.OnInit(context.PropListContext);
|
||||
}
|
||||
|
||||
if (_weaponListArea != null && context.WeaponListContext != null)
|
||||
{
|
||||
_weaponListArea.OnInit(context.WeaponListContext);
|
||||
}
|
||||
}
|
||||
|
||||
internal void RefreshGoodsItems(List<GoodsItemContext> goodsItems)
|
||||
{
|
||||
foreach (var item in _goodsItems)
|
||||
{
|
||||
item.gameObject.SetActive(false);
|
||||
}
|
||||
|
||||
if (_context.GoodsItems == null) return;
|
||||
for (int i = 0; i < _context.GoodsItems.Count; i++)
|
||||
if (goodsItems == null)
|
||||
{
|
||||
_goodsItems[i].Init(context.GoodsItems[i]);
|
||||
return;
|
||||
}
|
||||
|
||||
int count = Mathf.Min(_goodsItems.Length, goodsItems.Count);
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
_goodsItems[i].Init(goodsItems[i]);
|
||||
_goodsItems[i].gameObject.SetActive(true);
|
||||
}
|
||||
}
|
||||
|
||||
internal void RefreshRefreshPrice(int refreshPrice)
|
||||
{
|
||||
_refreshPriceText.text = $"刷新 -{refreshPrice} <sprite name=\"coin\" index=0>";
|
||||
}
|
||||
|
||||
internal void ApplyGoodsPurchased(int goodsIndex, DisplayItemContext displayItem)
|
||||
{
|
||||
SetGoodsItemVisible(goodsIndex, false);
|
||||
|
||||
if (displayItem == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (displayItem.IsWeapon)
|
||||
{
|
||||
AddWeaponDisplayItem(displayItem);
|
||||
}
|
||||
else
|
||||
{
|
||||
AddPropDisplayItem(displayItem);
|
||||
}
|
||||
}
|
||||
|
||||
private void SetGoodsItemVisible(int index, bool visible)
|
||||
{
|
||||
if (_goodsItems == null || index < 0 || index >= _goodsItems.Length)
|
||||
{
|
||||
Log.Warning("ShopForm.SetGoodsItemVisible: Invalid index.");
|
||||
return;
|
||||
}
|
||||
|
||||
_goodsItems[index].gameObject.SetActive(visible);
|
||||
}
|
||||
|
||||
private void AddPropDisplayItem(DisplayItemContext context)
|
||||
{
|
||||
if (_propListArea == null || context == null) return;
|
||||
_propListArea.AddItem(context);
|
||||
}
|
||||
|
||||
private void AddWeaponDisplayItem(DisplayItemContext context)
|
||||
{
|
||||
if (_weaponListArea == null || context == null) return;
|
||||
_weaponListArea.AddItem(context);
|
||||
}
|
||||
|
||||
#region ButtonClick
|
||||
|
||||
public void OnContinueButtonClick()
|
||||
@@ -61,7 +134,7 @@ namespace UI
|
||||
|
||||
public void OnRefreshButtonClick()
|
||||
{
|
||||
GameEntry.Event.Fire(this, ShopRefreshEventArgs.Create(_context.RefreshPrice));
|
||||
GameEntry.Event.Fire(this, RefreshEventArgs.Create(_context.RefreshPrice));
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -80,7 +153,7 @@ namespace UI
|
||||
return;
|
||||
}
|
||||
|
||||
UnityGameFramework.Runtime.Log.Warning("ShopForm requires ShopFormContext as userData.");
|
||||
Log.Warning("ShopForm requires ShopFormContext as userData.");
|
||||
}
|
||||
|
||||
protected override void OnClose(bool isShutdown, object userData)
|
||||
@@ -89,6 +162,9 @@ namespace UI
|
||||
|
||||
GameEntry.Event.Unsubscribe(PlayerCoinChangeEventArgs.EventId, OnPlayerCoinChange);
|
||||
|
||||
_propListArea?.OnReset();
|
||||
_weaponListArea?.OnReset();
|
||||
|
||||
base.OnClose(isShutdown, userData);
|
||||
}
|
||||
|
||||
@@ -102,9 +178,9 @@ namespace UI
|
||||
if (args.CoinCount == _currentCoin) return;
|
||||
|
||||
_currentCoin = args.CoinCount;
|
||||
_playerCoinText.text = _currentCoin.ToString();
|
||||
_playerCoinText.text = $"<sprite name=\"coin\" index=0> {_currentCoin}";
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+4
-6
@@ -4,9 +4,9 @@ using UnityEngine.UI;
|
||||
|
||||
namespace UI
|
||||
{
|
||||
public class GoodsItem : MonoBehaviour
|
||||
public class ShopGoodsItem : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private Image _iconImage;
|
||||
[SerializeField] private IconArea _iconArea;
|
||||
|
||||
[SerializeField] private TMP_Text _titleText;
|
||||
|
||||
@@ -15,18 +15,16 @@ namespace UI
|
||||
[SerializeField] private TMP_Text _descriptionText;
|
||||
|
||||
[SerializeField] private TMP_Text _costText;
|
||||
|
||||
[SerializeField] private CommonButton _purchaseButton;
|
||||
|
||||
#region Init
|
||||
|
||||
public void Init(GoodsItemContext data)
|
||||
{
|
||||
_iconImage.sprite = data.Icon;
|
||||
_iconArea.OnInit(data.Icon, data.Rarity);
|
||||
_titleText.text = data.Title;
|
||||
_typeText.text = data.Type;
|
||||
_descriptionText.text = data.Description;
|
||||
_costText.text = data.Price.ToString();
|
||||
_costText.text = $"{data.Price} <sprite name=\"coin\" index=0>";
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 85f5f27b7946745469a9e6d5e6316048
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 96db679da2f373f40aed4ad29967aede
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,19 @@
|
||||
using GameFramework;
|
||||
|
||||
namespace UI
|
||||
{
|
||||
public class DialogFormContext : UIContext
|
||||
{
|
||||
public int Mode;
|
||||
public string Title;
|
||||
public string Message;
|
||||
public bool PauseGame;
|
||||
public string ConfirmText;
|
||||
public GameFrameworkAction<object> OnClickConfirm;
|
||||
public string CancelText;
|
||||
public GameFrameworkAction<object> OnClickCancel;
|
||||
public string OtherText;
|
||||
public GameFrameworkAction<object> OnClickOther;
|
||||
public object UserData;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e9602a461df53c048af85df015fa8cb7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: eab5a115034214041b5647a33d64c224
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,215 @@
|
||||
using Definition.Enum;
|
||||
using GameFramework.Event;
|
||||
using UnityGameFramework.Runtime;
|
||||
|
||||
namespace UI
|
||||
{
|
||||
public class DialogFormController : UIFormControllerBase<DialogFormContext>
|
||||
{
|
||||
private DialogFormContext _context;
|
||||
|
||||
private DialogForm _dialogForm;
|
||||
|
||||
private int? _dialogFormSerialId;
|
||||
|
||||
private bool _pendingRefresh;
|
||||
|
||||
private bool _isBindEvent;
|
||||
|
||||
private void SubscribeEvents()
|
||||
{
|
||||
if (_isBindEvent) return;
|
||||
|
||||
GameEntry.Event.Subscribe(OpenUIFormSuccessEventArgs.EventId, OpenUIFormSuccess);
|
||||
GameEntry.Event.Subscribe(CloseUIFormCompleteEventArgs.EventId, CloseUIFormComplete);
|
||||
|
||||
_isBindEvent = true;
|
||||
}
|
||||
|
||||
private void UnsubscribeEvents()
|
||||
{
|
||||
if (!_isBindEvent) return;
|
||||
|
||||
GameEntry.Event.Unsubscribe(OpenUIFormSuccessEventArgs.EventId, OpenUIFormSuccess);
|
||||
GameEntry.Event.Unsubscribe(CloseUIFormCompleteEventArgs.EventId, CloseUIFormComplete);
|
||||
|
||||
_isBindEvent = false;
|
||||
}
|
||||
|
||||
private static DialogFormContext BuildContext(DialogFormRawData rawData)
|
||||
{
|
||||
if (rawData == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return new DialogFormContext
|
||||
{
|
||||
Mode = rawData.Mode,
|
||||
Title = rawData.Title,
|
||||
Message = rawData.Message,
|
||||
PauseGame = rawData.PauseGame,
|
||||
ConfirmText = rawData.ConfirmText,
|
||||
OnClickConfirm = rawData.OnClickConfirm,
|
||||
CancelText = rawData.CancelText,
|
||||
OnClickCancel = rawData.OnClickCancel,
|
||||
OtherText = rawData.OtherText,
|
||||
OnClickOther = rawData.OnClickOther,
|
||||
UserData = rawData.UserData
|
||||
};
|
||||
}
|
||||
|
||||
protected override int? OpenUIInternal(DialogFormContext context)
|
||||
{
|
||||
if (context == null)
|
||||
{
|
||||
Log.Warning("DialogFormController.OpenUI() context is null.");
|
||||
return null;
|
||||
}
|
||||
|
||||
_context = context;
|
||||
|
||||
if (_dialogForm != null && _dialogFormSerialId.HasValue &&
|
||||
GameEntry.UI.HasUIForm(_dialogFormSerialId.Value))
|
||||
{
|
||||
_dialogForm.RefreshUI(_context);
|
||||
return _dialogFormSerialId;
|
||||
}
|
||||
|
||||
CloseUI();
|
||||
_pendingRefresh = true;
|
||||
SubscribeEvents();
|
||||
_dialogFormSerialId = GameEntry.UI.OpenUIForm(UIFormType.DialogForm, context);
|
||||
return _dialogFormSerialId;
|
||||
}
|
||||
|
||||
public int? OpenUI(DialogFormRawData rawData)
|
||||
{
|
||||
DialogFormContext context = BuildContext(rawData);
|
||||
return OpenUIInternal(context);
|
||||
}
|
||||
|
||||
public override int? OpenUI(object userData = null)
|
||||
{
|
||||
if (userData is DialogFormContext context)
|
||||
{
|
||||
return OpenUIInternal(context);
|
||||
}
|
||||
|
||||
if (userData is DialogFormRawData rawData)
|
||||
{
|
||||
return OpenUI(rawData);
|
||||
}
|
||||
|
||||
if (userData is DialogFormRawData dialogParams)
|
||||
{
|
||||
return OpenUIInternal(BuildContext(dialogParams));
|
||||
}
|
||||
|
||||
if (userData != null)
|
||||
{
|
||||
Log.Warning("DialogFormController.OpenUI() userData type is invalid.");
|
||||
return null;
|
||||
}
|
||||
|
||||
return OpenUIInternal(_context);
|
||||
}
|
||||
|
||||
public override void CloseUI()
|
||||
{
|
||||
_pendingRefresh = false;
|
||||
UnsubscribeEvents();
|
||||
|
||||
if (_dialogFormSerialId.HasValue)
|
||||
{
|
||||
if (GameEntry.UI.HasUIForm(_dialogFormSerialId.Value))
|
||||
{
|
||||
GameEntry.UI.CloseUIForm(_dialogFormSerialId.Value);
|
||||
}
|
||||
|
||||
_dialogForm = null;
|
||||
_dialogFormSerialId = null;
|
||||
return;
|
||||
}
|
||||
|
||||
if (_dialogForm != null)
|
||||
{
|
||||
GameEntry.UI.CloseUIForm(_dialogForm);
|
||||
_dialogForm = null;
|
||||
}
|
||||
}
|
||||
|
||||
public override void BindUseCase(IUIUseCase useCase)
|
||||
{
|
||||
if (useCase != null)
|
||||
{
|
||||
Log.Warning("DialogFormController does not use a use case.");
|
||||
}
|
||||
}
|
||||
|
||||
private void TryRefreshUI()
|
||||
{
|
||||
if (_context == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (_dialogForm == null)
|
||||
{
|
||||
_pendingRefresh = true;
|
||||
return;
|
||||
}
|
||||
|
||||
_dialogForm.RefreshUI(_context);
|
||||
_pendingRefresh = false;
|
||||
}
|
||||
|
||||
private void OpenUIFormSuccess(object sender, GameEventArgs e)
|
||||
{
|
||||
if (!(e is OpenUIFormSuccessEventArgs args))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_dialogFormSerialId.HasValue)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (args.UIForm == null || args.UIForm.SerialId != _dialogFormSerialId.Value ||
|
||||
args.UserData != _context)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_dialogForm = args.UIForm.Logic as DialogForm;
|
||||
|
||||
if (_dialogForm == null)
|
||||
{
|
||||
Log.Warning("DialogFormController open success but form logic is invalid.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (_pendingRefresh)
|
||||
{
|
||||
TryRefreshUI();
|
||||
}
|
||||
}
|
||||
|
||||
private void CloseUIFormComplete(object sender, GameEventArgs e)
|
||||
{
|
||||
if (!(e is CloseUIFormCompleteEventArgs args))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (args.SerialId != _dialogFormSerialId)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_dialogForm = null;
|
||||
_dialogFormSerialId = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bcea24781fc934c42a5aac696d86f98d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 90a3026e140b55f47b670f4a786f7070
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+2
-9
@@ -1,18 +1,11 @@
|
||||
//------------------------------------------------------------
|
||||
// Game Framework
|
||||
// Copyright © 2013-2021 Jiang Yin. All rights reserved.
|
||||
// Homepage: https://gameframework.cn/
|
||||
// Feedback: mailto:ellan@gameframework.cn
|
||||
//------------------------------------------------------------
|
||||
|
||||
using GameFramework;
|
||||
using GameFramework;
|
||||
|
||||
namespace UI
|
||||
{
|
||||
/// <summary>
|
||||
/// 对话框显示数据。
|
||||
/// </summary>
|
||||
public class DialogParams
|
||||
public class DialogFormRawData
|
||||
{
|
||||
/// <summary>
|
||||
/// 模式,即按钮数量。取值 1、2、3。
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 61587606f17823143b72f971d68ce995
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+65
-22
@@ -29,6 +29,7 @@ namespace UI
|
||||
private GameFrameworkAction<object> _onClickConfirmGFAction = null;
|
||||
private GameFrameworkAction<object> _onClickCancelGFAction = null;
|
||||
private GameFrameworkAction<object> _onClickOtherGFAction = null;
|
||||
private DialogFormContext _context = null;
|
||||
|
||||
public int DialogMode => _dialogMode;
|
||||
|
||||
@@ -74,32 +75,19 @@ namespace UI
|
||||
{
|
||||
base.OnOpen(userData);
|
||||
|
||||
DialogParams dialogParams = (DialogParams)userData;
|
||||
if (dialogParams == null)
|
||||
if (userData is DialogFormContext context)
|
||||
{
|
||||
Log.Warning("DialogParams is invalid.");
|
||||
RefreshUI(context);
|
||||
return;
|
||||
}
|
||||
|
||||
_dialogMode = dialogParams.Mode;
|
||||
RefreshDialogMode();
|
||||
if (userData is DialogFormRawData dialogParams)
|
||||
{
|
||||
RefreshUI(BuildContext(dialogParams));
|
||||
return;
|
||||
}
|
||||
|
||||
_titleText.text = dialogParams.Title;
|
||||
_messageText.text = dialogParams.Message;
|
||||
|
||||
_pauseGame = dialogParams.PauseGame;
|
||||
RefreshPauseGame();
|
||||
|
||||
_userData = dialogParams.UserData;
|
||||
|
||||
RefreshConfirmText(dialogParams.ConfirmText);
|
||||
_onClickConfirmGFAction = dialogParams.OnClickConfirm;
|
||||
|
||||
RefreshCancelText(dialogParams.CancelText);
|
||||
_onClickCancelGFAction = dialogParams.OnClickCancel;
|
||||
|
||||
RefreshOtherText(dialogParams.OtherText);
|
||||
_onClickOtherGFAction = dialogParams.OnClickOther;
|
||||
Log.Warning("DialogForm requires DialogFormContext or DialogParams as userData.");
|
||||
}
|
||||
|
||||
#if UNITY_2017_3_OR_NEWER
|
||||
@@ -118,6 +106,7 @@ namespace UI
|
||||
_messageText.text = string.Empty;
|
||||
_pauseGame = false;
|
||||
_userData = null;
|
||||
_context = null;
|
||||
|
||||
RefreshConfirmText(string.Empty);
|
||||
_onClickConfirmGFAction = null;
|
||||
@@ -131,6 +120,60 @@ namespace UI
|
||||
base.OnClose(isShutdown, userData);
|
||||
}
|
||||
|
||||
public void RefreshUI(DialogFormContext context)
|
||||
{
|
||||
if (context == null)
|
||||
{
|
||||
Log.Warning("DialogForm context is invalid.");
|
||||
return;
|
||||
}
|
||||
|
||||
_context = context;
|
||||
|
||||
_dialogMode = context.Mode;
|
||||
RefreshDialogMode();
|
||||
|
||||
_titleText.text = context.Title;
|
||||
_messageText.text = context.Message;
|
||||
|
||||
_pauseGame = context.PauseGame;
|
||||
RefreshPauseGame();
|
||||
|
||||
_userData = context.UserData;
|
||||
|
||||
RefreshConfirmText(context.ConfirmText);
|
||||
_onClickConfirmGFAction = context.OnClickConfirm;
|
||||
|
||||
RefreshCancelText(context.CancelText);
|
||||
_onClickCancelGFAction = context.OnClickCancel;
|
||||
|
||||
RefreshOtherText(context.OtherText);
|
||||
_onClickOtherGFAction = context.OnClickOther;
|
||||
}
|
||||
|
||||
private static DialogFormContext BuildContext(DialogFormRawData rawData)
|
||||
{
|
||||
if (rawData == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return new DialogFormContext
|
||||
{
|
||||
Mode = rawData.Mode,
|
||||
Title = rawData.Title,
|
||||
Message = rawData.Message,
|
||||
PauseGame = rawData.PauseGame,
|
||||
ConfirmText = rawData.ConfirmText,
|
||||
OnClickConfirm = rawData.OnClickConfirm,
|
||||
CancelText = rawData.CancelText,
|
||||
OnClickCancel = rawData.OnClickCancel,
|
||||
OtherText = rawData.OtherText,
|
||||
OnClickOther = rawData.OnClickOther,
|
||||
UserData = rawData.UserData
|
||||
};
|
||||
}
|
||||
|
||||
private void RefreshDialogMode()
|
||||
{
|
||||
for (int i = 1; i <= _modeObjects.Length; i++)
|
||||
@@ -186,4 +229,4 @@ namespace UI
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
using Definition.Enum;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace UI
|
||||
{
|
||||
public class IconArea : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private Image _board;
|
||||
|
||||
[SerializeField] private Image _icon;
|
||||
|
||||
public void OnInit(Sprite sprite, ItemRarity rarity)
|
||||
{
|
||||
SetIcon(sprite);
|
||||
SetRarity(rarity);
|
||||
}
|
||||
|
||||
public void SetIcon(Sprite sprite)
|
||||
{
|
||||
_icon.sprite = sprite;
|
||||
}
|
||||
|
||||
public void SetRarity(ItemRarity rarity)
|
||||
{
|
||||
_board.color = rarity switch
|
||||
{
|
||||
ItemRarity.White => Color.white,
|
||||
ItemRarity.Green => Color.green,
|
||||
ItemRarity.Blue => Color.blue,
|
||||
ItemRarity.Purple => Color.magenta,
|
||||
ItemRarity.Red => Color.red,
|
||||
_ => Color.clear,
|
||||
};
|
||||
}
|
||||
|
||||
public void OnReset()
|
||||
{
|
||||
SetIcon(null);
|
||||
SetRarity(ItemRarity.None);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 578fa91d15f54e74a95ccce338d0a772
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e3e1fd66709232c439fe452b81dffab6
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace UI
|
||||
{
|
||||
public class RoleItemContext : UIContext
|
||||
{
|
||||
public int RoleId;
|
||||
public string IconName;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0337fd9faf4a5b44eb95858bff44c015
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace UI
|
||||
{
|
||||
public class RolePropertyAreaContext : UIContext
|
||||
{
|
||||
public string RoleName;
|
||||
public string InitialPropertyText;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8f37335b27f20c647a0a6175226c0b45
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace UI
|
||||
{
|
||||
public class SelectRoleFormContext : UIContext
|
||||
{
|
||||
public RoleItemContext[] RoleItemContexts;
|
||||
public RolePropertyAreaContext RolePropertyAreaContext;
|
||||
public int[] RoleIds;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6c34d5aa87925ee41b70887958e7611c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace UI
|
||||
{
|
||||
public class StartMenuFormContext : UIContext
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 77a32872255d9f84b9332418d1352514
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 70ae7a701eac84b4eb4ec27bf2ada3c1
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,293 @@
|
||||
using CustomEvent;
|
||||
using Definition.Enum;
|
||||
using GameFramework.Event;
|
||||
using UnityGameFramework.Runtime;
|
||||
|
||||
namespace UI
|
||||
{
|
||||
public class SelectRoleFormController : UIFormControllerBase<SelectRoleFormContext>
|
||||
{
|
||||
private SelectRoleFormUseCase _useCase;
|
||||
|
||||
private SelectRoleFormContext _context;
|
||||
|
||||
private SelectRoleForm _selectRoleForm;
|
||||
|
||||
private int? _selectRoleFormSerialId;
|
||||
|
||||
private bool _pendingRefresh;
|
||||
|
||||
private bool _isBindEvent;
|
||||
|
||||
private void SubscribeEvents()
|
||||
{
|
||||
if (_isBindEvent) return;
|
||||
|
||||
GameEntry.Event.Subscribe(OpenUIFormSuccessEventArgs.EventId, OpenUIFormSuccess);
|
||||
GameEntry.Event.Subscribe(CloseUIFormCompleteEventArgs.EventId, CloseUIFormComplete);
|
||||
GameEntry.Event.Subscribe(MenuSelectRoleReturnEventArgs.EventId, OnMenuSelectRoleReturn);
|
||||
GameEntry.Event.Subscribe(MenuSelectRoleSelectedEventArgs.EventId, OnMenuSelectRoleSelected);
|
||||
GameEntry.Event.Subscribe(MenuSelectRoleConfirmEventArgs.EventId, OnMenuSelectRoleConfirm);
|
||||
|
||||
_isBindEvent = true;
|
||||
}
|
||||
|
||||
private void UnsubscribeEvents()
|
||||
{
|
||||
if (!_isBindEvent) return;
|
||||
|
||||
GameEntry.Event.Unsubscribe(OpenUIFormSuccessEventArgs.EventId, OpenUIFormSuccess);
|
||||
GameEntry.Event.Unsubscribe(CloseUIFormCompleteEventArgs.EventId, CloseUIFormComplete);
|
||||
GameEntry.Event.Unsubscribe(MenuSelectRoleReturnEventArgs.EventId, OnMenuSelectRoleReturn);
|
||||
GameEntry.Event.Unsubscribe(MenuSelectRoleSelectedEventArgs.EventId, OnMenuSelectRoleSelected);
|
||||
GameEntry.Event.Unsubscribe(MenuSelectRoleConfirmEventArgs.EventId, OnMenuSelectRoleConfirm);
|
||||
|
||||
_isBindEvent = false;
|
||||
}
|
||||
|
||||
private static SelectRoleFormContext BuildContext(SelectRoleFormRawData rawData)
|
||||
{
|
||||
if (rawData == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
int count = rawData.RoleIds?.Length ?? 0;
|
||||
RoleItemContext[] roleItems = new RoleItemContext[count];
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
string iconName = rawData.RoleIconNames != null && i < rawData.RoleIconNames.Length
|
||||
? rawData.RoleIconNames[i]
|
||||
: null;
|
||||
|
||||
roleItems[i] = new RoleItemContext
|
||||
{
|
||||
RoleId = rawData.RoleIds[i],
|
||||
IconName = iconName
|
||||
};
|
||||
}
|
||||
|
||||
RolePropertyAreaContext propertyContext = null;
|
||||
if (rawData.SelectedRoleId >= 0)
|
||||
{
|
||||
propertyContext = new RolePropertyAreaContext
|
||||
{
|
||||
RoleName = rawData.SelectedRoleName,
|
||||
InitialPropertyText = rawData.SelectedRoleInitialPropertyText
|
||||
};
|
||||
}
|
||||
|
||||
return new SelectRoleFormContext
|
||||
{
|
||||
RoleItemContexts = roleItems,
|
||||
RolePropertyAreaContext = propertyContext,
|
||||
RoleIds = rawData.RoleIds
|
||||
};
|
||||
}
|
||||
|
||||
#region UI Methods
|
||||
|
||||
protected override int? OpenUIInternal(SelectRoleFormContext context)
|
||||
{
|
||||
if (context == null)
|
||||
{
|
||||
Log.Warning("SelectRoleFormController.OpenUI() context is null.");
|
||||
return null;
|
||||
}
|
||||
|
||||
_context = context;
|
||||
|
||||
if (_selectRoleForm != null && _selectRoleFormSerialId.HasValue &&
|
||||
GameEntry.UI.HasUIForm(_selectRoleFormSerialId.Value))
|
||||
{
|
||||
_selectRoleForm.RefreshUI(_context);
|
||||
return _selectRoleFormSerialId;
|
||||
}
|
||||
|
||||
CloseUI();
|
||||
_pendingRefresh = true;
|
||||
SubscribeEvents();
|
||||
_selectRoleFormSerialId = GameEntry.UI.OpenUIForm(UIFormType.SelectRoleForm, context);
|
||||
return _selectRoleFormSerialId;
|
||||
}
|
||||
|
||||
public override int? OpenUI(object userData = null)
|
||||
{
|
||||
if (userData is SelectRoleFormContext selectRoleFormContext)
|
||||
{
|
||||
return OpenUIInternal(selectRoleFormContext);
|
||||
}
|
||||
|
||||
if (userData != null)
|
||||
{
|
||||
Log.Warning("SelectRoleFormController.OpenUI() userData type is invalid.");
|
||||
return null;
|
||||
}
|
||||
|
||||
SelectRoleFormRawData rawData = _useCase.CreateModel();
|
||||
SelectRoleFormContext context = BuildContext(rawData);
|
||||
return OpenUIInternal(context);
|
||||
}
|
||||
|
||||
public override void CloseUI()
|
||||
{
|
||||
_pendingRefresh = false;
|
||||
UnsubscribeEvents();
|
||||
|
||||
if (_selectRoleFormSerialId.HasValue)
|
||||
{
|
||||
if (GameEntry.UI.HasUIForm(_selectRoleFormSerialId.Value))
|
||||
{
|
||||
GameEntry.UI.CloseUIForm(_selectRoleFormSerialId.Value);
|
||||
}
|
||||
|
||||
_selectRoleForm = null;
|
||||
_selectRoleFormSerialId = null;
|
||||
return;
|
||||
}
|
||||
|
||||
if (_selectRoleForm != null)
|
||||
{
|
||||
_selectRoleForm.Close();
|
||||
_selectRoleForm = null;
|
||||
}
|
||||
}
|
||||
|
||||
public override void BindUseCase(IUIUseCase useCase)
|
||||
{
|
||||
if (!(useCase is SelectRoleFormUseCase selectRoleUseCase))
|
||||
{
|
||||
Log.Error("SelectRoleUseCase.BindUseCase() useCase is invalid.");
|
||||
return;
|
||||
}
|
||||
|
||||
_useCase = selectRoleUseCase;
|
||||
}
|
||||
|
||||
private void TryRefreshUI()
|
||||
{
|
||||
if (_context == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (_selectRoleForm == null)
|
||||
{
|
||||
_pendingRefresh = true;
|
||||
return;
|
||||
}
|
||||
|
||||
_selectRoleForm.RefreshUI(_context);
|
||||
_pendingRefresh = false;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Service
|
||||
|
||||
public void UpdateShowRole(RolePropertyAreaContext rolePropertyAreaContext)
|
||||
{
|
||||
if (_context != null)
|
||||
{
|
||||
_context.RolePropertyAreaContext = rolePropertyAreaContext;
|
||||
}
|
||||
|
||||
if (_selectRoleForm != null)
|
||||
{
|
||||
_selectRoleForm.UpdateShowRole(rolePropertyAreaContext);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Event Handlers
|
||||
|
||||
private void OpenUIFormSuccess(object sender, GameEventArgs e)
|
||||
{
|
||||
if (!(e is OpenUIFormSuccessEventArgs args))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_selectRoleFormSerialId.HasValue)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (args.UIForm == null || args.UIForm.SerialId != _selectRoleFormSerialId.Value ||
|
||||
args.UserData != _context)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_selectRoleForm = args.UIForm.Logic as SelectRoleForm;
|
||||
|
||||
if (_selectRoleForm == null)
|
||||
{
|
||||
Log.Warning("SelectRoleFormController open success but form logic is invalid.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (_pendingRefresh)
|
||||
{
|
||||
TryRefreshUI();
|
||||
}
|
||||
}
|
||||
|
||||
private void CloseUIFormComplete(object sender, GameEventArgs e)
|
||||
{
|
||||
if (!(e is CloseUIFormCompleteEventArgs args))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (args.SerialId != _selectRoleFormSerialId)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_selectRoleForm = null;
|
||||
_selectRoleFormSerialId = null;
|
||||
}
|
||||
|
||||
private void OnMenuSelectRoleReturn(object sender, GameEventArgs e)
|
||||
{
|
||||
if (!(sender is SelectRoleForm) || !(e is MenuSelectRoleReturnEventArgs))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
CloseUI();
|
||||
}
|
||||
|
||||
private void OnMenuSelectRoleSelected(object sender, GameEventArgs e)
|
||||
{
|
||||
if (!(e is MenuSelectRoleSelectedEventArgs args))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
SelectRoleFormRawData rawData = _useCase != null ? _useCase.SelectRole(args.RoleId) : null;
|
||||
SelectRoleFormContext context = BuildContext(rawData);
|
||||
if (context == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_context = context;
|
||||
UpdateShowRole(_context.RolePropertyAreaContext);
|
||||
}
|
||||
|
||||
private void OnMenuSelectRoleConfirm(object sender, GameEventArgs e)
|
||||
{
|
||||
if (!(e is MenuSelectRoleConfirmEventArgs))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_useCase.ConfirmSelectedRole();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ff46cd6b508b0304a801223cbae79419
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,276 @@
|
||||
using CustomEvent;
|
||||
using Definition.Enum;
|
||||
using GameFramework.Event;
|
||||
using UnityGameFramework.Runtime;
|
||||
|
||||
namespace UI
|
||||
{
|
||||
public class StartMenuFormController : UIFormControllerBase<StartMenuFormContext>
|
||||
{
|
||||
private StartMenuFormContext _context;
|
||||
|
||||
private StartMenuForm _startMenuForm;
|
||||
|
||||
private int? _startMenuFormSerialId;
|
||||
|
||||
private bool _pendingRefresh;
|
||||
|
||||
private bool _isBindEvent;
|
||||
|
||||
private void SubscribeEvents()
|
||||
{
|
||||
if (_isBindEvent) return;
|
||||
|
||||
GameEntry.Event.Subscribe(OpenUIFormSuccessEventArgs.EventId, OpenUIFormSuccess);
|
||||
GameEntry.Event.Subscribe(CloseUIFormCompleteEventArgs.EventId, CloseUIFormComplete);
|
||||
|
||||
GameEntry.Event.Subscribe(MenuStartGameEventArgs.EventId, OnMenuStartGameButtonClick);
|
||||
GameEntry.Event.Subscribe(MenuFileButtonClickEventArgs.EventId, OnMenuFileButtonClick);
|
||||
GameEntry.Event.Subscribe(MenuGuideButtonClickEventArgs.EventId, OnMenuGuideButtonClick);
|
||||
GameEntry.Event.Subscribe(MenuSettingButtonClickEventArgs.EventId, OnMenuSettingButtonClick);
|
||||
GameEntry.Event.Subscribe(MenuQuitButtonClickEventArgs.EventId, OnMenuQuitButtonClick);
|
||||
GameEntry.Event.Subscribe(MenuAboutButtonClickEventArgs.EventId, OnMenuAboutButtonClick);
|
||||
|
||||
_isBindEvent = true;
|
||||
}
|
||||
|
||||
private void UnsubscribeEvents()
|
||||
{
|
||||
if (!_isBindEvent) return;
|
||||
|
||||
GameEntry.Event.Unsubscribe(OpenUIFormSuccessEventArgs.EventId, OpenUIFormSuccess);
|
||||
GameEntry.Event.Unsubscribe(CloseUIFormCompleteEventArgs.EventId, CloseUIFormComplete);
|
||||
|
||||
GameEntry.Event.Unsubscribe(MenuStartGameEventArgs.EventId, OnMenuStartGameButtonClick);
|
||||
GameEntry.Event.Unsubscribe(MenuFileButtonClickEventArgs.EventId, OnMenuFileButtonClick);
|
||||
GameEntry.Event.Unsubscribe(MenuGuideButtonClickEventArgs.EventId, OnMenuGuideButtonClick);
|
||||
GameEntry.Event.Unsubscribe(MenuSettingButtonClickEventArgs.EventId, OnMenuSettingButtonClick);
|
||||
GameEntry.Event.Unsubscribe(MenuQuitButtonClickEventArgs.EventId, OnMenuQuitButtonClick);
|
||||
GameEntry.Event.Unsubscribe(MenuAboutButtonClickEventArgs.EventId, OnMenuAboutButtonClick);
|
||||
|
||||
_isBindEvent = false;
|
||||
}
|
||||
|
||||
private static StartMenuFormContext BuildStartMenuFormContext()
|
||||
{
|
||||
return new StartMenuFormContext();
|
||||
}
|
||||
|
||||
#region UI Methods
|
||||
|
||||
protected override int? OpenUIInternal(StartMenuFormContext context)
|
||||
{
|
||||
if (context == null)
|
||||
{
|
||||
Log.Warning("StartMenuFormController.OpenUI() context is null.");
|
||||
return null;
|
||||
}
|
||||
|
||||
_context = context;
|
||||
|
||||
if (_startMenuForm != null && _startMenuFormSerialId.HasValue &&
|
||||
GameEntry.UI.HasUIForm(_startMenuFormSerialId.Value))
|
||||
{
|
||||
_startMenuForm.RefreshUI(_context);
|
||||
return _startMenuFormSerialId;
|
||||
}
|
||||
|
||||
CloseUI();
|
||||
_pendingRefresh = true;
|
||||
SubscribeEvents();
|
||||
_startMenuFormSerialId = GameEntry.UI.OpenUIForm(UIFormType.StartMenuForm, context);
|
||||
return _startMenuFormSerialId;
|
||||
}
|
||||
|
||||
public override int? OpenUI(object userData = null)
|
||||
{
|
||||
if (userData is StartMenuFormContext context)
|
||||
{
|
||||
return OpenUIInternal(context);
|
||||
}
|
||||
|
||||
if (userData != null)
|
||||
{
|
||||
Log.Warning("StartMenuFormController.OpenUI() userData type is invalid.");
|
||||
return null;
|
||||
}
|
||||
|
||||
return OpenUIInternal(BuildStartMenuFormContext());
|
||||
}
|
||||
|
||||
public int? OpenUI(StartMenuFormContext context)
|
||||
{
|
||||
return OpenUIInternal(context);
|
||||
}
|
||||
|
||||
public override void CloseUI()
|
||||
{
|
||||
_pendingRefresh = false;
|
||||
UnsubscribeEvents();
|
||||
|
||||
if (_startMenuFormSerialId.HasValue)
|
||||
{
|
||||
if (GameEntry.UI.HasUIForm(_startMenuFormSerialId.Value))
|
||||
{
|
||||
GameEntry.UI.CloseUIForm(_startMenuFormSerialId.Value);
|
||||
}
|
||||
|
||||
_startMenuForm = null;
|
||||
_startMenuFormSerialId = null;
|
||||
return;
|
||||
}
|
||||
|
||||
if (_startMenuForm != null)
|
||||
{
|
||||
_startMenuForm.Close();
|
||||
_startMenuForm = null;
|
||||
}
|
||||
}
|
||||
|
||||
public override void BindUseCase(IUIUseCase useCase)
|
||||
{
|
||||
Log.Info("StartMenuForm doesn't need UseCase");
|
||||
}
|
||||
|
||||
private void TryRefreshUI()
|
||||
{
|
||||
if (_context == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (_startMenuForm == null)
|
||||
{
|
||||
_pendingRefresh = true;
|
||||
return;
|
||||
}
|
||||
|
||||
_startMenuForm.RefreshUI(_context);
|
||||
_pendingRefresh = false;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region Event Handlers
|
||||
|
||||
private void OpenUIFormSuccess(object sender, GameEventArgs e)
|
||||
{
|
||||
if (!(e is OpenUIFormSuccessEventArgs args))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_startMenuFormSerialId.HasValue)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (args.UIForm == null || args.UIForm.SerialId != _startMenuFormSerialId.Value ||
|
||||
args.UserData != _context)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_startMenuForm = args.UIForm.Logic as StartMenuForm;
|
||||
|
||||
if (_startMenuForm == null)
|
||||
{
|
||||
Log.Warning("StartMenuFormController open success but form logic is invalid.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (_pendingRefresh)
|
||||
{
|
||||
TryRefreshUI();
|
||||
}
|
||||
}
|
||||
|
||||
private void CloseUIFormComplete(object sender, GameEventArgs e)
|
||||
{
|
||||
if (!(e is CloseUIFormCompleteEventArgs args))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (args.SerialId != _startMenuFormSerialId)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_startMenuForm = null;
|
||||
_startMenuFormSerialId = null;
|
||||
}
|
||||
|
||||
private void OnMenuStartGameButtonClick(object sender, GameEventArgs e)
|
||||
{
|
||||
if (!(sender is StartMenuForm) || !(e is MenuStartGameEventArgs))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
GameEntry.UIRouter.OpenUI(UIFormType.SelectRoleForm);
|
||||
}
|
||||
|
||||
private void OnMenuFileButtonClick(object sender, GameEventArgs e)
|
||||
{
|
||||
if (!(sender is StartMenuForm) || !(e is MenuFileButtonClickEventArgs))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Log.Warning("Menu file button click is not implemented.");
|
||||
}
|
||||
|
||||
private void OnMenuGuideButtonClick(object sender, GameEventArgs e)
|
||||
{
|
||||
if (!(sender is StartMenuForm) || !(e is MenuGuideButtonClickEventArgs))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Log.Warning("Menu guide button click is not implemented.");
|
||||
}
|
||||
|
||||
private void OnMenuSettingButtonClick(object sender, GameEventArgs e)
|
||||
{
|
||||
if (!(sender is StartMenuForm) || !(e is MenuSettingButtonClickEventArgs))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
GameEntry.UIRouter.OpenUI(UIFormType.SettingForm);
|
||||
}
|
||||
|
||||
private void OnMenuQuitButtonClick(object sender, GameEventArgs e)
|
||||
{
|
||||
if (!(sender is StartMenuForm) || !(e is MenuQuitButtonClickEventArgs))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
GameEntry.UIRouter.OpenUI(UIFormType.DialogForm, new DialogFormRawData
|
||||
{
|
||||
Mode = 2,
|
||||
Title = GameEntry.Localization.GetString("AskQuitGame.Title"),
|
||||
Message = GameEntry.Localization.GetString("AskQuitGame.Message"),
|
||||
OnClickConfirm = delegate(object userData)
|
||||
{
|
||||
UnityGameFramework.Runtime.GameEntry.Shutdown(ShutdownType.Quit);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void OnMenuAboutButtonClick(object sender, GameEventArgs e)
|
||||
{
|
||||
if (!(sender is StartMenuForm) || !(e is MenuAboutButtonClickEventArgs))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Log.Warning("Menu about button click is not implemented.");
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3feee66cf220f6f47b147bca4f7967f4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user