342 lines
13 KiB
C#
342 lines
13 KiB
C#
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, // 倒计时面板
|
||
}
|
||
}
|
||
} |