Files
JJBB/Assets/Project/Script/GUI/Board/WorldUIRoot.cs

342 lines
13 KiB
C#
Raw Permalink Normal View History

2024-08-23 15:49:34 +08:00
using System;
using Games.Events;
using Module.Log;
using System.Collections.Generic;
using GCGame.Table;
using UnityEngine;
using UnityEngine.Events;
namespace Games.LogicObj
{
// 近世界层UI该层UI可以认为是每一帧都需要重新拼合
public class WorldUIRoot : MonoBehaviour
{
// 暂时不构造从UiManager向下初始化的结构不析构的管理器直接用Instance自己管理
public static WorldUIRoot Instance { get; private set; }
//public const float maxScale = 1f;
//public const float minScale = 0.2f;
//// 像素宽度到世界宽度转化数值
//public float PixelToWorld { get; private set; }
private List<WorldUIItem> _uiItemList;
private UiItemPool<WorldUIItem, WorldUiLoadData, WorldUiLoadTask> _uiItemPool;
// Destroy之后不回收任何物品
private bool _isDestroyed;
private Canvas _canvas;
#region Head UI
public static bool ShowHeadUi
{
get { return PlayerPreferenceData.SystemNameBoard; }
}
private RectTransform _headUiRoot;
private RectTransform _damageUiRoot;
public void ShowOrHideHeadRoot(bool IsShow)
{
if (_headUiRoot)
_headUiRoot.gameObject.SetActive(IsShow);
}
public void ResetShowHeadUi()
{
for (var i = 0; i < _uiItemList.Count; i++)
{
var headUi = _uiItemList[i] as Obj_HeadUI;
if (headUi)
headUi.ResetShow();
}
}
/// <summary>
/// 请求一个HeadUi物体
/// </summary>
public void LoadHeadUi(ObjParent objParent)
{
var loadData = new WorldUiLoadData(objParent, _headUiRoot, OnHeadUiLoadTaskComplete);
_uiItemPool.PullItem(loadData, objParent.HeadUiPath);
}
public void StopLoadHeadUi(ObjParent objParent)
{
// 无视这个警告 - 常规指针检测方式
#pragma warning disable 252,253
_uiItemPool.RemoveLoadTask(a => a.data == objParent);
#pragma warning restore 252,253
}
private void OnHeadUiLoadTaskComplete(WorldUIItem worldUiItem, WorldUiLoadData loadData)
{
if (worldUiItem == null)
return;
// Obj在加载中被析构的稀有情况
if (loadData.data == null)
_uiItemPool.PushItem(worldUiItem.uiPathData, worldUiItem);
else
{
var error = false;
try
{
((ObjParent)loadData.data).BindHeadUi(worldUiItem);
}
catch (Exception e)
{
LogModule.ErrorLog(e.ToString());
error = true;
}
if (error)
worldUiItem.BackToPool();
else
_uiItemList.Add(worldUiItem);
}
}
#endregion
#region Damage Board
/// <summary>
/// 显示伤害信息
/// </summary>
/// <param name="nType">伤害类型</param>
/// <param name="strValue">字符串</param>
/// <param name="pos">世界位置</param>
/// <param name="isProfessionSkill">是否职业技能</param>
public void ShowDamageBoard(int nType, string strValue, Vector3 pos, bool isProfessionSkill = true)
{
if (!PlayerPreferenceData.SystemDamageBoardEnable)
return;
var data = DamageBoardManager.damageBoardManager.TryAddDamageBoard(nType);
if (data != null)
{
bool hightLayer = (
(nType == (int)Games.GlobeDefine.GameDefine_Globe.DAMAGEBOARD_TYPE.PLAYER_EXP_UP)
|| (nType == (int)Games.GlobeDefine.GameDefine_Globe.DAMAGEBOARD_TYPE.YINPIAO_UP)
|| (nType == (int)Games.GlobeDefine.GameDefine_Globe.DAMAGEBOARD_TYPE.YINLING_UP)
|| (nType == (int)Games.GlobeDefine.GameDefine_Globe.DAMAGEBOARD_TYPE.YUANBAO_UP)
|| (nType == (int)Games.GlobeDefine.GameDefine_Globe.DAMAGEBOARD_TYPE.LINGYU_UP)
);
RectTransform _damageExpUiRoot = (UIManager.Instance() != null ? UIManager.Instance().DamageHightRoot : null);
RectTransform root = (hightLayer && _damageExpUiRoot != null ? _damageExpUiRoot : _damageUiRoot);
var taskStarter = new WorldUiLoadData(new DamageBoardData(data, strValue, pos, isProfessionSkill), root, OnDamageBoardLoadTaskComplete);
_uiItemPool.PullItem(taskStarter, DamageBoard.PathData);
}
}
private void OnDamageBoardLoadTaskComplete(WorldUIItem damageUiItem, WorldUiLoadData loadData)
{
var data = (DamageBoardData) loadData.data;
var damageBoard = (DamageBoard) damageUiItem;
damageBoard.ActiveDamageBoard(data.data, data.strValue, data.worldPos, data.isProfessionSkill);
_uiItemList.Add(damageBoard);
}
// 注这个指令应该同所有角色析构是同一帧因此可以析构HeadUi
public void ClearDamageBoard()
{
if (!_isDestroyed)
{
for (var i = 0; i < _uiItemList.Count; i++)
{
var uiItem = _uiItemList[i];
if (uiItem.itemType == WorldUiItemType.DamageBoard)
Recovery(uiItem.uiPathData, uiItem);
}
DamageBoardManager.damageBoardManager.ClearNumber();
}
}
#endregion
#region AnchoredText
public void ShowCountdownOnCharacter(int objId, int countdown)
{
var textData = new AnchoredTextData(objId, Time.unscaledTime + (float)countdown);
var taskStarter = new WorldUiLoadData(textData, _damageUiRoot, OnCountDownLoadTaskComplete);
_uiItemPool.PullItem(taskStarter, AnchoredText.PathData);
}
private void OnCountDownLoadTaskComplete(WorldUIItem damageUiItem, WorldUiLoadData loadData)
{
var data = (AnchoredTextData) loadData.data;
var anchoredText = (AnchoredText) damageUiItem;
anchoredText.SetInitData(data);
_uiItemList.Add(anchoredText);
}
#endregion
private void Awake()
{
Instance = this;
_canvas = GetComponent<Canvas>();
_uiItemList = new List<WorldUIItem>();
_uiItemPool = new UiItemPool<WorldUIItem, WorldUiLoadData, WorldUiLoadTask>((RectTransform)transform.Find("PoolRoot"));
_headUiRoot = (RectTransform)transform.Find("NameBoardRoot");
_damageUiRoot = (RectTransform) transform.Find("DamageBoardRoot");
}
private void Start()
{
EventDispatcher.Instance.Add(Events.EventId.PostMainCameraMove, PostMainCameraMove);
EventDispatcher.Instance.Add(Events.EventId.UiCameraCopy, OnUiCameraCopy);
// 等TableManager一帧
// PixelToWorld = 1f; float.Parse(TableManager.GetSystemParamByID(6, 0).StringValue);
}
private void OnDestroy()
{
if (Instance == this)
Instance = null;
_isDestroyed = true;
EventDispatcher.Instance.Remove(Events.EventId.PostMainCameraMove, PostMainCameraMove);
EventDispatcher.Instance.Remove(Events.EventId.UiCameraCopy, OnUiCameraCopy);
}
private int _hideCamera;
private void OnUiCameraCopy(object args)
{
var start = (bool)args;
_hideCamera = _hideCamera.ReplaceFlag(0.ToFlag(), start);
ResetHideCamera();
}
//private void OnSceneMovie(object args)
//{
// var start = (bool)args;
// _hideCamera = _hideCamera.ReplaceFlag(1.ToFlag(), start);
// ResetHideCamera();
//}
private void ResetHideCamera()
{
_canvas.enabled = _hideCamera <= 0;
}
private void PostMainCameraMove(object args)
{
// 注:可能有设置位置时,要求被回收的情况
for (var i = _uiItemList.Count - 1; i >= 0; i--)
{
// 加固,防止固化流程被其他模块破坏
try
{
var activeItem = _uiItemList[i];
if (activeItem.CheckPositionValid() && activeItem.CheckDuration())
{
// 屏蔽缩放功能直到修复
//if (activeItem.scaleByWorldPos)
// uiPos = GetUiPositionAndScale(activeItem.worldPosition, activeItem.pixelWidth, out scale);
//else
//{
var uiPos = UIManager.Instance().WorldToUiPoint(activeItem.worldPosition);
const float scale = 1f;
//}
activeItem.SetPositionAndScale(uiPos, scale);
}
else
{
// 伤害面板回收需要清除使用计数
if (activeItem.itemType == WorldUiItemType.DamageBoard && DamageBoardManager.damageBoardManager != null)
{
var damageBoard = (DamageBoard) activeItem;
DamageBoardManager.damageBoardManager.RemoveDamageBoard(damageBoard.data.DamageBoardTypeID);
}
activeItem.BackToPool();
}
}
catch (System.Exception e)
{
LogModule.ErrorLog(_uiItemList[i] == null
? "World Ui Root 中发现为空的物体!"
: string.Format("{0}发生故障!", _uiItemList[i].transform.GetHierarchyName()));
LogModule.ErrorLog(e.ToString());
}
}
}
/// <summary>
/// 世界坐标转到UI坐标体系下的位置和缩放
/// </summary>
/// <param name="worldPos">世界坐标位置</param>
/// <param name="pixelWidth">组件预期像素宽度</param>
/// <param name="scale">Ui空间的缩放数值</param>
//public Vector3 GetUiPositionAndScale(Vector3 worldPos, float pixelWidth, out float scale)
//{
// var sceneCamera = UIManager.Instance().GetWorldCamera();
// var worldWidth = pixelWidth * PixelToWorld;
// // 默认世界摄像机是投影摄像机
// // 实际是摄像机的forward叉乘之后才是right
// var right = worldPos - sceneCamera.transform.position;
// right = Vector3.Cross(Vector3.up, right);
// if (right == Vector3.zero)
// right = sceneCamera.transform.right;
// right = right.normalized;
// var pos0 = worldPos - right * 0.5f * worldWidth;
// var pos1 = worldPos + right * 0.5f * worldWidth;
// // 像素位置
// pos0 = UIManager.Instance().WorldToUiPoint(pos0);
// pos1 = UIManager.Instance().WorldToUiPoint(pos1);
// scale = Mathf.Clamp((pos1.x - pos0.x) / pixelWidth, minScale, maxScale);
// return (pos0 + pos1) * 0.5f;
//}
public void SetShow(bool isShow)
{
_canvas.enabled = isShow;
}
public void Recovery(UIPathData pathData, WorldUIItem item)
{
if (!_isDestroyed)
{
_uiItemList.Remove(item);
_uiItemPool.PushItem(pathData, item);
}
}
public class WorldUiLoadData : BaseLoadData<WorldUIItem, WorldUiLoadData>
{
public object data;
public WorldUiLoadData(object pData, Transform root, UnityAction<WorldUIItem, WorldUiLoadData> callback) : base(root, callback)
{
data = pData;
}
}
public class WorldUiLoadTask : BaseLoadTask<WorldUIItem, WorldUiLoadData, WorldUiLoadTask>
{
}
public class DamageBoardData
{
public Tab_DamageBoardType data;
public string strValue;
public Vector3 worldPos;
public bool isProfessionSkill;
public DamageBoardData(Tab_DamageBoardType data, string strValue, Vector3 worldPos, bool isProfessionSkill)
{
this.data = data;
this.strValue = strValue;
this.worldPos = worldPos;
this.isProfessionSkill = isProfessionSkill;
}
}
public class AnchoredTextData
{
public int objId;
public float endTime;
public AnchoredTextData(int objId, float endTime)
{
this.objId = objId;
this.endTime = endTime;
}
}
public enum WorldUiItemType
{
HeadInfo, // 头顶面板
DamageBoard, // 伤害面板
AnchorText, // 倒计时面板
}
}
}