597 lines
20 KiB
C#
597 lines
20 KiB
C#
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
|
||
} |