Files
JJBB/Assets/Project/Script/GUI/Base/UICameraTexture.cs

597 lines
20 KiB
C#
Raw Normal View History

2024-08-23 15:49:34 +08:00
using System.Collections;
using Games.Events;
using Games.GlobeDefine;
using Games.LogicObj;
using GCGame.Table;
using Module.Log;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;
using UnityEngine.UI;
using Object = UnityEngine.Object;
public class UICameraTexture : UIBase, IDragHandler
{
public delegate void InitModelPathCallBack();
//加载MountModel坐骑表不在CharModel中
public delegate void InitOverCallBack();
private static int _callTimes;
private int _openRawImageFrame = int.MaxValue;
public GameObject _CameraPrefab;
public bool isPerspective;
public FakeShowObj _FakeObj { get; private set; }
public RawImage _RawImage;
public float cameraSize = 1;
public event UnityAction<GameObject> onModelUpdate;
public bool isPreview;
private Camera _cameraInstance;
private bool _hideFakeShow;
private bool _currentHideFakeShow;
private void InitImage()
{
if (_FakeObj == null)
{
var cameraGo = Instantiate(_CameraPrefab);
cameraGo.transform.SetParent(null);
cameraGo.transform.position = new Vector3(1000 + 100 * _callTimes, -1000, 0);
++_callTimes;
// 避开旋转造成模型光照方向不正常,部分模型需要维持在各场景世界方向不变
// cameraGo.transform.rotation = Camera.main.transform.rotation;
cameraGo.transform.localRotation = Quaternion.identity;
cameraGo.transform.localScale = Vector3.one;
var objTransform = cameraGo.transform.Find("GameObject");
_cameraInstance = cameraGo.GetComponent<Camera>();
if (objTransform != null && _cameraInstance != null)
{
_cameraInstance.orthographic = !isPerspective;
_FakeObj = new FakeShowObj(objTransform.gameObject, _cameraInstance, cameraSize, _RawImage);
_FakeObj.FakeObj.onModelUpdate += OnFakeShowModelUpdate;
}
else
LogModule.ErrorLog("FakeObj无法正常初始化于物体" + transform.GetHierarchyName());
_RawImage.material = CommonUtility.LoadSharedMaterial("UiRenderTexture");
OnEnable();
}
else
{
DisAbleFake();
}
// 注以下部分在ShowingModel加载时再次调用CreateNewFake会导致多次构造FakeObj。暂时先修改有其他影响再看如何处理。
//if (_FakeObj == null || _FakeObj.ShowingModel == null)
// _FakeObj = CreateNewFake();
}
public void SetBlack()
{
if(_FakeObj!=null && _FakeObj.FakeObj!=null)
{
_FakeObj.FakeObj.ChangeToBlack();
}
}
public void RemoveBlack()
{
if (_FakeObj != null && _FakeObj.FakeObj != null)
{
_FakeObj.FakeObj.RemoveBlack();
}
}
private void OnFakeShowModelUpdate(GameObject modelGameObject)
{
_hideFakeShow = false;
_currentHideFakeShow = false;
if (modelGameObject != null)
modelGameObject.SetActive(!_currentHideFakeShow);
SetOpenFrame();
if (onModelUpdate != null)
onModelUpdate(modelGameObject);
}
private void Update()
{
// 跳过第一帧激活 - 动画机会有一帧的刷新时间,没有找到避开的办法
if (Time.frameCount > _openRawImageFrame && _FakeObj != null && !_FakeObj.IsInAnimTransistion())
{
_openRawImageFrame = int.MaxValue;
_RawImage.color = Color.white;
}
}
private void OnEnable()
{
// 注使用_FakeObj作为OnEnable标签_FakeObj构造完成或者重新激活时执行一次OnEnable。
if (_FakeObj != null)
{
_FakeObj.Enable();
_RawImage.texture = _FakeObj.renderTexture;
}
if (!isPreview)
_RawImage.color = new Color(0f, 0f, 0f, 0f);
}
private void OnDisable()
{
if (!GameManager.applicationQuit)
{
if (_FakeObj != null)
{
_FakeObj.Disable();
_RawImage.texture = null;
_RawImage.color = Color.white;
}
_openRawImageFrame = int.MaxValue;
}
}
public void SetOpenFrame()
{
_openRawImageFrame = Time.frameCount + 1;
}
private void OnDestroy()
{
if (!GameManager.applicationQuit)
DestroyObj();
}
public void DestroyObj()
{
if (_FakeObj != null)
{
_FakeObj.Destroy();
_FakeObj = null;
}
}
// public void ShowRawImage()
// {
// if (enabled && gameObject.activeInHierarchy)
// StartCoroutine(ShowRawImageNextFrame());
// else
// _RawImage.enabled = true;
// }
// private IEnumerator ShowRawImageNextFrame()
// {
// yield return null;
// _RawImage.enabled = true;
// }
private Obj_FakeShow InitFakeShowObj()
{
var result = _FakeObj == null ? null : _FakeObj.FakeObj;
return result;
}
public void DisAbleFake()
{
_hideFakeShow = true;
}
public void EnAbleFake()
{
_hideFakeShow = false;
}
private void LateUpdate()
{
if (_hideFakeShow != _currentHideFakeShow)
{
_currentHideFakeShow = _hideFakeShow;
if (_FakeObj != null && _FakeObj.ShowingModel != null)
_FakeObj.ShowingModel.SetActive(_currentHideFakeShow);
}
}
private void InitFakeShow(Obj_FakeShow fakeShow, Obj_FakeShow_Init_Data initData)
{
if (initData.m_Hash == null)
initData.m_Hash = new Hashtable();
//initData.m_Hash["ShowRawImage"] = (InitOverCallBack) ShowRawImage;
fakeShow.Init(initData);
}
private void CreateModel(Obj_FakeShow fakeShow, Obj_FakeShow_Init_Data initData, string modelPath, bool isBody,
string bodyPos, string bodyRot, string halfPos, string halfRot, Hashtable table = null)
{
if (table == null)
table = new Hashtable();
table["_FakeObj"] = _FakeObj;
//table["ShowRawImage"] = (InitOverCallBack) ShowRawImage;
if (isBody)
{
table["Pos"] = StrToVector3(bodyPos);
table["Rot"] = StrToVector3(bodyRot);
}
else
{
table["Pos"] = StrToVector3(halfPos);
table["Rot"] = StrToVector3(halfRot);
}
if (initData != null)
{
initData.m_Hash = table;
fakeShow.Init(initData);
}
else
{
fakeShow.CreateModel(-1, modelPath, table);
}
}
/// <summary>
/// 清空当前使用的模型文件
/// </summary>
public void RemoveModel()
{
if (_FakeObj != null && _FakeObj.FakeObj != null)
_FakeObj.FakeObj.RemoveModels();
}
// isBody = true 全身像; fase 半身像
public bool InitModelPath(string resPath, Tab_CharModel modelTab, string bundle = LoadAssetBundle.BUNDLE_PATH_MODEL,
bool isBody = false, InitModelPathCallBack callBack = null,
bool isSettedOrthSize = false, int profession = -1)
{
InitImage();
var fakeShow = InitFakeShowObj();
if (fakeShow != null)
{
if (string.IsNullOrEmpty(resPath) && modelTab != null && modelTab.Id == fakeShow.ModelID)
{
SetOpenFrame();
EnAbleFake();
return false;
}
if (fakeShow.ModelNode != null && modelTab == null && string.IsNullOrEmpty(resPath) == false &&
resPath == fakeShow.ModelNode.targetModel)
{
SetOpenFrame();
EnAbleFake();
return false;
}
var initData = new Obj_FakeShow_Init_Data
{
m_nProfession = -1,
m_ModelVisualID = -1,
m_WeaponDataID = -1,
m_WeaponEffectGem = -1,
m_WingAuraId = -1,
m_EffectAuraId = -1,
m_AdvanceWingId = -1,
BundlePath = bundle,
FakeModelPath = resPath
};
if (modelTab != null)
initData.m_ModelVisualID = modelTab.Id;
if (profession != -1)
initData.m_nProfession = profession;
if (callBack != null)
{
if (initData.m_Hash == null)
initData.m_Hash = new Hashtable();
initData.m_Hash.Add("InitModelPathCallBack", callBack);
}
if (isSettedOrthSize)
{
if (initData.m_Hash == null)
initData.m_Hash = new Hashtable();
initData.m_Hash.Add("isSettedOrthSize", callBack);
}
if (modelTab == null)
InitFakeShow(fakeShow, initData);
else
CreateModel(fakeShow, initData, "", isBody, modelTab.BodyPos, modelTab.BodyRot, modelTab.HalfPos,
modelTab.HalfRot, initData.m_Hash);
}
return true;
}
/// <summary>
/// CharModelId如果是人物时装需要转换成对应的CharModelId
/// 通过:Globaldata.GetCharModel(职业, 时装ID)获取
/// </summary>
/// <param name="profession"></param>
/// <param name="charModeld"></param>
/// <param name="weaponID"></param>
/// <param name="WingID"></param>
/// <param name="weaponEffectID"></param>
/// <param name="modelEffectID"></param>
/// <param name="advanceWingId"></param>
/// <param name="charModel"></param>
/// <param name="isBody"></param>
public void InitModel(int profession, int charModeld, int weaponID = -1, int WingID = -1, int weaponEffectID = -1,
int modelEffectID = -1, int advanceWingId = -1, Tab_CharModel charModel = null, bool isBody = true)
{
InitImage();
var fakeShow = InitFakeShowObj();
if (fakeShow == null) return;
var initData = new Obj_FakeShow_Init_Data
{
m_nProfession = profession,
m_ModelVisualID = charModeld,
m_WeaponDataID = weaponID,
m_WeaponEffectGem = weaponEffectID,
m_WingAuraId = WingID,
m_EffectAuraId = modelEffectID,
m_AdvanceWingId = advanceWingId
};
if (fakeShow.ModelNode.model != null && initData.IsVisualMatch(fakeShow))
{
fakeShow.ModelNode.model.transform.localRotation = Quaternion.identity;
}
else
{
if (charModel == null)
charModel = TableManager.GetCharModelByID(initData.m_ModelVisualID, 0);
if (charModel == null)
InitFakeShow(fakeShow, initData);
else
CreateModel(fakeShow, initData, string.Empty, isBody, charModel.BodyPos, charModel.BodyRot,
charModel.HalfPos,
charModel.HalfRot);
}
}
public void InitPlayerModel(Obj_Character Shower_Character, bool isBody = true, InitOverCallBack callBack = null)
{
if (Shower_Character == null)
return;
InitImage();
var fakeShow = InitFakeShowObj();
if (fakeShow == null)
return;
if (fakeShow.ModelNode.model != null &&
fakeShow.IsVisualMatch(Shower_Character))
{
_FakeObj.ShowingModel.transform.localRotation = Quaternion.identity;
SetOpenFrame();
EnAbleFake();
}
else
{
//没有时装显示默认模型
var tabItemVisual = TableManager.GetItemVisualByID(Shower_Character.ModelVisualID, 0);
if (tabItemVisual == null)
{
tabItemVisual = TableManager.GetItemVisualByID(GlobeVar.DEFAULT_VISUAL_ID, 0);
if (tabItemVisual == null) return;
}
var nCharmodelId = fakeShow.GetCharModelID(tabItemVisual, Shower_Character.Profession);
var charModel = TableManager.GetCharModelByID(nCharmodelId, 0);
if (charModel == null) return;
var initData = new Obj_FakeShow_Init_Data
{
m_nProfession = Shower_Character.Profession,
m_ModelVisualID = nCharmodelId,
m_WeaponDataID = Shower_Character.WeaponDataID,
m_WeaponEffectGem = Shower_Character.WeaponEffectGem,
m_WingAuraId = Shower_Character.WingModelAuraid,
m_EffectAuraId = Shower_Character.EffectAuraId,
m_AdvanceWingId = Shower_Character.IsShowWing ? Shower_Character.AdvanceWingId : -1
};
if (callBack != null)
{
if (initData.m_Hash == null)
initData.m_Hash = new Hashtable();
initData.m_Hash.Add("InitOverCallBack", callBack);
}
CreateModel(fakeShow, initData, "", isBody, charModel.BodyPos, charModel.BodyRot, charModel.HalfPos,
charModel.HalfRot, initData.m_Hash);
}
}
public void InitMountModelPath(Tab_CharMount mountTab, InitOverCallBack callBack = null)
{
if (mountTab == null)
return;
InitImage();
var fakeShow = InitFakeShowObj();
if (fakeShow != null)
{
Hashtable hash = null;
if (callBack != null)
hash = new Hashtable {{"InitOverCallBack", callBack}};
CreateModel(fakeShow, null, mountTab.MountModel, true, mountTab.BodyPos, mountTab.BodyRot, "", "", hash);
}
}
public void InitWingModelPath(Tab_AdvanceBase advanceBase, Tab_WeaponModel wingData = null,
InitOverCallBack callBack = null)
{
InitImage();
if (wingData == null)
{
var auraConfig = TableManager.GetAuraConfigByID(advanceBase.ModelId, 0);
if (auraConfig == null)
return;
switch (GameManager.gameManager.PlayerDataPool.MainPlayerBaseAttr.Profession)
{
case (int) CharacterDefine.PROFESSION.TIANJI:
{
wingData = TableManager.GetWeaponModelByID(auraConfig.TianJiWingModelId, 0);
break;
}
case (int) CharacterDefine.PROFESSION.SHUSHAN:
{
wingData = TableManager.GetWeaponModelByID(auraConfig.ShuShanWingModelId, 0);
break;
}
case (int) CharacterDefine.PROFESSION.LIUSHAN:
{
wingData = TableManager.GetWeaponModelByID(auraConfig.LiuShanWingModelId, 0);
break;
}
case (int) CharacterDefine.PROFESSION.XUANNV:
{
wingData = TableManager.GetWeaponModelByID(auraConfig.XuanNvWingModelId, 0);
break;
}
}
}
if (wingData == null)
return;
var fakeShow = InitFakeShowObj();
// 注:"isWing"这个标签唯一作用是强制配置ResPath到默认加载路径实际底层会自动回落到默认路径
// "isWing"标签已经在底层移除
//hash.Add("isWing", true);
if (fakeShow != null)
{
var hash = new Hashtable();
if (callBack != null)
hash.Add("InitOverCallBack", callBack);
fakeShow.RealoadWingModel();
CreateModel(fakeShow, null, wingData.ResPathR, true, wingData.BodyPos, wingData.BodyRot, "", "", hash);
}
}
private static Vector3 StrToVector3(string strValue)
{
var splitStrs = strValue.Split(';');
if (splitStrs.Length != 3)
{
LogModule.ErrorLog("StrToVector3 error:" + strValue);
return Vector3.zero;
}
return new Vector3(float.Parse(splitStrs[0]), float.Parse(splitStrs[1]), float.Parse(splitStrs[2]));
}
#region
public class FakeShowObj
{
public FakeShowObj(GameObject rootObj, Camera camera, float cameraSize, RawImage rawImage)
{
FakeObj = rootObj.EnsureComponent<Obj_FakeShow>();
renderCamera = camera;
renderCamera.orthographicSize = cameraSize <= 0f ? 1f : cameraSize;
renderCamera.cullingMask = renderCamera.gameObject.layer.ToFlag();
renderCamera.enabled = false;
_rawImage = rawImage;
DontDestroyOnLoad(renderCamera.gameObject);
}
public Obj_FakeShow FakeObj { get; private set; }
public Camera renderCamera { get; private set; }
public RenderTexture renderTexture { get; private set; }
private readonly RawImage _rawImage;
public GameObject ShowingModel
{
get
{
return FakeObj != null && FakeObj.ModelNode.model != null ? FakeObj.ModelNode.model.gameObject : null;
}
}
public void Enable()
{
if (renderTexture == null)
{
var size = GetTextureSize();
if (size != Vector2.zero)
renderTexture = RenderTexturePool.Instance.GetRenderTexture(size);
}
if (renderTexture != null)
{
renderCamera.targetTexture = renderTexture;
EventDispatcher.Instance.Remove(Games.Events.EventId.PostUiCameraRender, OnUiCameraRender);
EventDispatcher.Instance.Add(Games.Events.EventId.PostUiCameraRender, OnUiCameraRender);
//renderCamera.enabled = true;
}
}
public void Disable()
{
if (renderTexture != null)
{
RenderTexturePool.Instance.ReleaseRenderTexture(renderTexture);
renderTexture = null;
}
if (renderCamera != null)
{
renderCamera.enabled = false;
EventDispatcher.Instance.Remove(Games.Events.EventId.PostUiCameraRender, OnUiCameraRender);
//renderCamera.targetTexture = null;
}
FakeObj.RemoveModels();
}
private void OnUiCameraRender(object args)
{
renderCamera.Render();
}
public bool IsInAnimTransistion()
{
return FakeObj != null && FakeObj.IsInAnimTransistion();
}
public void Destroy()
{
Disable();
if (FakeObj != null)
{
FakeObj.DestroyObj();
Object.Destroy(FakeObj.gameObject);
FakeObj = null;
}
if (renderCamera != null)
{
Object.Destroy(renderCamera.gameObject);
renderCamera = null;
}
}
private Vector2 GetTextureSize()
{
var result = Vector2.zero;
if (_rawImage != null)
{
var imageSize = _rawImage.rectTransform.rect.size;
if (imageSize.x > 0f && imageSize.y > 0f)
{
// 贴图尺寸校正到单边不超过512
//var ratio = Mathf.Min(512f / imageSize.x, 512f / imageSize.y, 1f);
result = imageSize;// * ratio;
}
}
return result;
}
}
#endregion
#region opt
public bool _CanDrag = true; //有些模型需要不能转动
public void OnDrag(PointerEventData eventData)
{
if (_CanDrag)
if (_FakeObj != null && _FakeObj.FakeObj != null)
{
var eular = _FakeObj.FakeObj.transform.localRotation.eulerAngles;
eular.y -= eventData.delta.x;
_FakeObj.FakeObj.transform.localRotation = Quaternion.Euler(eular);
}
}
#endregion
}