Files
JJBB/Assets/Project/Script/GUI/Board/WorldUIRoot.cs
2024-08-23 15:49:34 +08:00

342 lines
13 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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, // 倒计时面板
}
}
}