631 lines
19 KiB
C#
631 lines
19 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using Thousandto.Cfg.Data;
|
|
using Thousandto.Code.Center;
|
|
using Thousandto.Code.Logic;
|
|
using Thousandto.Core.Asset;
|
|
using Thousandto.Plugins.Common;
|
|
using Thousandto.Plugins.LuaType;
|
|
using UnityEngine;
|
|
using XLua;
|
|
|
|
namespace Thousandto.GameUI.Form
|
|
{
|
|
//UI上的模型管理组件
|
|
public class UIRoleSkinCompoent : LuaBehaviour
|
|
{
|
|
#region//私有变量
|
|
//父UI
|
|
protected UINormalForm _parent = null;
|
|
//transform实例
|
|
protected Transform _transformInst = null;
|
|
//模型位置边框
|
|
private UIWidget _widget = null;
|
|
//模型位置的Transform
|
|
protected Transform _widgetTrans = null;
|
|
//模型boxcollider
|
|
protected BoxCollider _collider = null;
|
|
//
|
|
protected UIEventListener _listener = null;
|
|
//模型根节点
|
|
protected Transform _modelRoot = null;
|
|
protected GameObject _modelGo = null;
|
|
//默认旋转Y值
|
|
protected float _normalRot = 180f;
|
|
//默认旋转值
|
|
protected Vector3 _nomalEuleAngles = Vector3.zero;
|
|
//默认位置
|
|
protected Vector3 _nomalPos = Vector3.zero;
|
|
//已经装备的数据
|
|
protected Dictionary<int, int> _equips = new Dictionary<int, int>();
|
|
protected Dictionary<int, Dictionary<string, bool>> _anims = new Dictionary<int, System.Collections.Generic.Dictionary<string, bool>>();
|
|
//装备接口
|
|
protected FSkinModel _skin = null;
|
|
//是否可以拖动旋转
|
|
protected bool _enableDrag = true;
|
|
//使用的层
|
|
protected int _layer = LayerUtils.AresUI;
|
|
|
|
protected string[] _defaultClipNames = null;
|
|
|
|
protected UIPanel renderQvalue;
|
|
|
|
//场景模型旋转
|
|
private Transform _uiModelDragTrs = null;
|
|
|
|
//神兵头部开始动画位置
|
|
private Vector3 _godWeaponHeadPos = new Vector3(0, 0, 0.4f);
|
|
//神兵身体开始动画位置
|
|
private Vector3 _godWeaponBodyPos = new Vector3(0, 0, -0.4f);
|
|
//神兵动画曲线
|
|
private AnimationCurve _godWeaponCurve = new AnimationCurve(new Keyframe(0f, 0f, 0f, 1), new Keyframe(0.8f, 0.25f, 1, 1), new Keyframe(1f, 1f, 1f, 0f));
|
|
private Action<FSkinBase, int> _partChangedCallBack;
|
|
private int _showFrameCount = 0;
|
|
private List<Renderer> _skinAllRenders = new List<Renderer>();
|
|
#endregion
|
|
|
|
#region//属性
|
|
public Transform TransformInst
|
|
{
|
|
get
|
|
{
|
|
if (_transformInst == null)
|
|
{
|
|
_transformInst = transform;
|
|
}
|
|
return _transformInst;
|
|
}
|
|
}
|
|
|
|
public bool EnableDrag
|
|
{
|
|
get
|
|
{
|
|
return _enableDrag;
|
|
}
|
|
set
|
|
{
|
|
_enableDrag = value;
|
|
_collider.enabled = _enableDrag;
|
|
}
|
|
}
|
|
|
|
public UIWidget Widget
|
|
{
|
|
get
|
|
{
|
|
return _widget;
|
|
}
|
|
|
|
set
|
|
{
|
|
_widget = value;
|
|
}
|
|
}
|
|
|
|
//使用的摄像机大小
|
|
public void SetCameraSize(float size)
|
|
{
|
|
if (_modelRoot == null)
|
|
{
|
|
return;
|
|
}
|
|
//设置的摄像机大小不可以小于0
|
|
if (size <= 0)
|
|
{
|
|
_modelRoot.localScale = new Vector3(320, 320, 320);
|
|
}
|
|
else
|
|
{
|
|
_modelRoot.localScale = new Vector3(320 / size, 320 / size, 320 / size);
|
|
}
|
|
}
|
|
|
|
//设置缩放值
|
|
public void SetLocalScale(float scale)
|
|
{
|
|
if (_modelRoot == null)
|
|
{
|
|
return;
|
|
}
|
|
//设置的摄像机大小不可以小于0
|
|
if (scale <= 0)
|
|
{
|
|
_modelRoot.localScale = new Vector3(320, 320, 320);
|
|
}
|
|
else
|
|
{
|
|
_modelRoot.localScale = new Vector3(scale, scale, scale);
|
|
}
|
|
}
|
|
|
|
//设置UI上的位置
|
|
public void SetPos(float posX,float posY, float posZ = 0)
|
|
{
|
|
_nomalPos = new Vector3(posX, posY, posZ == 0 ? _modelRoot.localPosition.z : posZ);
|
|
if (_modelRoot == null)
|
|
{
|
|
return;
|
|
}
|
|
_modelRoot.localPosition = _nomalPos;
|
|
}
|
|
|
|
public Vector3 GetEulerAngles()
|
|
{
|
|
return _modelRoot.localEulerAngles;
|
|
}
|
|
|
|
//设置EulerAngles
|
|
public void SetEulerAngles(float angleX, float angleY, float angleZ)
|
|
{
|
|
_nomalEuleAngles = new Vector3(angleX, angleY, angleZ);
|
|
_normalRot = angleY;
|
|
if (_modelRoot != null)
|
|
{
|
|
_modelRoot.localEulerAngles = _nomalEuleAngles;
|
|
}
|
|
}
|
|
|
|
//默认旋转值
|
|
public float NormalRot
|
|
{
|
|
get
|
|
{
|
|
return _normalRot;
|
|
}
|
|
set
|
|
{
|
|
_normalRot = value;
|
|
_nomalEuleAngles.y = _normalRot;
|
|
}
|
|
}
|
|
|
|
//当前旋转值
|
|
public float CurRot
|
|
{
|
|
get
|
|
{
|
|
if (_modelRoot != null)
|
|
{
|
|
return _modelRoot.localEulerAngles.y;
|
|
}
|
|
return 0;
|
|
}
|
|
set
|
|
{
|
|
if (_modelRoot != null)
|
|
{
|
|
var angles = _modelRoot.localEulerAngles;
|
|
angles.y = value;
|
|
_modelRoot.localEulerAngles = angles;
|
|
if (_uiModelDragTrs != null)
|
|
{
|
|
_uiModelDragTrs.localEulerAngles = angles;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//使用的层
|
|
public int Layer
|
|
{
|
|
get
|
|
{
|
|
return _layer;
|
|
}
|
|
set
|
|
{
|
|
if (_layer != value)
|
|
{
|
|
_layer = value;
|
|
_skin.SetLayer(_layer, true);
|
|
}
|
|
}
|
|
}
|
|
|
|
//装备接口
|
|
public FSkinModel Skin
|
|
{
|
|
get
|
|
{
|
|
return _skin;
|
|
}
|
|
}
|
|
|
|
public FSkinTypeCode SkinTypeCode
|
|
{
|
|
get
|
|
{
|
|
return _skin.SkinTypeCode;
|
|
}
|
|
set
|
|
{
|
|
_skin.SkinTypeCode = value;
|
|
}
|
|
}
|
|
|
|
public AnimatorCullingMode SkinAnimationCullingType
|
|
{
|
|
get
|
|
{
|
|
return _skin.CullingType;
|
|
}
|
|
set
|
|
{
|
|
_skin.CullingType = value;
|
|
}
|
|
}
|
|
|
|
public int AnimUpdateRate
|
|
{
|
|
get
|
|
{
|
|
return _skin.AnimUpdateRate;
|
|
}
|
|
set
|
|
{
|
|
_skin.AnimUpdateRate = value;
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region//公有函数
|
|
public virtual void OnFirstShow(UINormalForm parent, FSkinTypeCode skinType = FSkinTypeCode.Monster, string defaultAnim = AnimClipNameDefine.NormalIdle, float animSpeed = 1,bool isUseUIValue = false,bool isUIModel = true)
|
|
{
|
|
if (_parent != null)
|
|
{
|
|
//UnityEngine.Debug.LogErrorFormat("UIRoleSkinCompoent 重复调用 OnFirstShow 请检查错误");
|
|
return;
|
|
}
|
|
_parent = parent;
|
|
_widgetTrans = TransformInst.Find("Box");
|
|
_widget = _widgetTrans.GetComponent<UIWidget>();
|
|
_widget.pivot = UIWidget.Pivot.Bottom;
|
|
if (_widget.depth <= 0) _widget.depth = 1;
|
|
_collider = TransformInst.Find("Box").GetComponent<BoxCollider>();
|
|
_collider.enabled = _enableDrag;
|
|
_collider.center = new Vector3(0f, _collider.size.y / 2f, 0f);
|
|
_modelRoot = TransformInst.Find("Box/ModelRoot");
|
|
_modelGo = _modelRoot.gameObject;
|
|
if (isUseUIValue)
|
|
{
|
|
_nomalPos = _modelRoot.localPosition;
|
|
_nomalEuleAngles = _modelRoot.localRotation.eulerAngles;
|
|
_normalRot = _modelRoot.localRotation.eulerAngles.y;
|
|
}
|
|
else
|
|
{
|
|
_nomalEuleAngles.x = 0;
|
|
_nomalEuleAngles.y = _normalRot;
|
|
_nomalEuleAngles.z = 0;
|
|
}
|
|
_listener = _widgetTrans.RequireComponent<UIEventListener>();
|
|
_listener.onDrag = OnDrag;
|
|
CalculatePos();
|
|
|
|
//默认的动作
|
|
_defaultClipNames = new string[] { defaultAnim };
|
|
renderQvalue = TransformInst.GetComponent<UIPanel>();
|
|
renderQvalue.onRenderQueueChanged = RenderQueueChanged;
|
|
|
|
//初始化
|
|
_skin = GameCenter.LuaSystem.Adaptor.CreateFSkinModel(skinType);
|
|
_skin.SetParent(_modelRoot, true);
|
|
_skin.SetLayer(_layer, true);
|
|
_skin.PlayAnim(defaultAnim, AnimationPartType.AllBody, WrapMode.Loop, true, 0.2f, animSpeed);
|
|
_skin.SetDefaultAnim(defaultAnim, AnimationPartType.AllBody);
|
|
_skin.SetBreastJiggly(true);
|
|
_skin.IsPriorityLoad = true;
|
|
_skin.SetRenderQueue(renderQvalue.startingRenderQueue + 1);
|
|
_skin.SetOnSkinPartChangedHandler(OnSkinChange);
|
|
_skin.IsUIModel = isUIModel;
|
|
_skin.CullingType = AnimatorCullingMode.AlwaysAnimate;
|
|
//FGameObjectBody body = _skin.GetSkinPart(FSkinPartCode.Body) as FGameObjectBody;
|
|
//body.UserCloth = true;
|
|
}
|
|
|
|
//RenderQueue的改变事件
|
|
private void RenderQueueChanged(int sq)
|
|
{
|
|
if (_skin != null)
|
|
{
|
|
if (_skin.RenderQueue != sq + 1)
|
|
{
|
|
_skin.SetRenderQueue(sq + 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
public void SetDefaultAnim(string name, AnimationPartType type)
|
|
{
|
|
if (_skin != null)
|
|
{
|
|
_skin.SetDefaultAnim(name, type);
|
|
}
|
|
}
|
|
|
|
public void SetSkinPos(Vector3 pos)
|
|
{
|
|
_skin.SetLocalPosition(pos);
|
|
}
|
|
|
|
public void SetSkinRot(Vector3 angle)
|
|
{
|
|
_skin.SetLocalEulerAngles(angle);
|
|
}
|
|
|
|
public void CalculatePos()
|
|
{
|
|
_modelRoot.localPosition = _nomalPos;
|
|
}
|
|
|
|
public int GetEquipID(int type)
|
|
{
|
|
int result = 0;
|
|
_equips.TryGetValue((int)type, out result);
|
|
return result;
|
|
}
|
|
|
|
public void SetEquip(int type, int id, Dictionary<string, bool> animList = null, string slot = null)
|
|
{
|
|
//_skin.SetBoneClothEnable(true);
|
|
if ( !GameExtentScript._showPlayerModel ) return;
|
|
|
|
_equips[(int)type] = id;
|
|
if (animList != null)
|
|
{
|
|
_anims[(int)type] = animList;
|
|
}
|
|
if (gameObject.activeInHierarchy)
|
|
{
|
|
_skin.SetSkinPartFromCfgID(type, id, _anims.ContainsKey((int)type) ? _anims[(int)type] : null, false, slot);
|
|
}
|
|
}
|
|
|
|
public void SetEquip(int type, int id, LuaTable animTable)
|
|
{
|
|
_equips[(int)type] = id;
|
|
if(animTable != null)
|
|
{
|
|
var clipCount = animTable.Length;
|
|
var animList = new Dictionary<string, bool>(clipCount);
|
|
var tmpStr = string.Empty;
|
|
for(int i = 0; i < clipCount; ++i)
|
|
{
|
|
if(animTable.TryGet<int, string>(i + 1, out tmpStr))
|
|
{
|
|
animList[tmpStr] = false;
|
|
}
|
|
}
|
|
_anims[(int)type] = animList;
|
|
}
|
|
if (gameObject.activeInHierarchy)
|
|
{
|
|
_skin.SetSkinPartFromCfgID(type, id, _anims.ContainsKey((int)type) ? _anims[(int)type] : null, false);
|
|
}
|
|
}
|
|
|
|
//设置神兵动画,给神兵UI界面用的
|
|
public void SetGodWeaponAnim(int godweaponVfxid, Transform trs)
|
|
{
|
|
var head = _skin.GetSkinPart(FSkinPartCode.GodWeaponHead);
|
|
var body = _skin.GetSkinPart(FSkinPartCode.GodWeaponBody);
|
|
if (body != null && head != null)
|
|
{
|
|
SetEquip(FSkinPartCode.GodWeaponVfx, 0);
|
|
var headtween = head.RootTransform.RequireComponent<TweenPosition>();
|
|
var bodytween = body.RootTransform.RequireComponent<TweenPosition>();
|
|
head.RootTransform.localPosition = _godWeaponHeadPos;
|
|
body.RootTransform.localPosition = _godWeaponBodyPos;
|
|
headtween.from = _godWeaponHeadPos;
|
|
headtween.to = Vector3.zero;
|
|
headtween.duration = 0.4f;
|
|
headtween.animationCurve = _godWeaponCurve;
|
|
headtween.style = UITweener.Style.Once;
|
|
headtween.ResetToBeginning();
|
|
headtween.PlayForward();
|
|
|
|
bodytween.from = _godWeaponBodyPos;
|
|
bodytween.to = Vector3.zero;
|
|
bodytween.duration = 0.4f;
|
|
bodytween.style = UITweener.Style.Once;
|
|
bodytween.animationCurve = _godWeaponCurve;
|
|
bodytween.ResetToBeginning();
|
|
bodytween.PlayForward();
|
|
bodytween.SetOnFinished(() =>
|
|
{
|
|
SetEquip(FSkinPartCode.GodWeaponVfx, godweaponVfxid);
|
|
if (trs != null)
|
|
{
|
|
var _vfx = trs.RequireComponent<UIVfxSkinCompoent>();
|
|
_vfx.OnCreateAndPlay(ModelTypeCode.UIVFX, 39, LayerUtils.AresUI);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
//设置头发颜色
|
|
public void SetHairColor(float r, float g, float b)
|
|
{
|
|
_skin.SetHairColor(new Color(r, g, b));
|
|
}
|
|
|
|
//重置模型数据
|
|
public void ResetSkin()
|
|
{
|
|
_equips.Clear();
|
|
_anims.Clear();
|
|
if (_skin != null)
|
|
{
|
|
_skin.RemoveAllSkinPart();
|
|
}
|
|
}
|
|
|
|
//重置旋转角度
|
|
public void ResetRot()
|
|
{
|
|
_modelRoot.localEulerAngles = _nomalEuleAngles;
|
|
}
|
|
//设置点击回调
|
|
public void SetClickCallBack(UIEventListener.VoidDelegate callBack)
|
|
{
|
|
_listener.onClick = callBack;
|
|
}
|
|
|
|
//播放动作
|
|
public void Play(string animName, AnimationPartType partType, WrapMode wrapMode, float animSpeed)
|
|
{
|
|
_skin.PlayAnim(animName, partType, wrapMode, true, 0.2f, animSpeed);
|
|
}
|
|
|
|
public bool IsPlaying()
|
|
{
|
|
return _skin.IsPlaying();
|
|
}
|
|
//设置皮肤部位改变的处理
|
|
public void SetOnSkinPartChangedHandler(Action<FSkinBase, int> handler)
|
|
{
|
|
_partChangedCallBack = handler;
|
|
}
|
|
|
|
//获取所有渲染列表
|
|
public List<Renderer> GetAllRenders()
|
|
{
|
|
_skinAllRenders.Clear();
|
|
if (_skin != null)
|
|
{
|
|
_skin.GetRenderers(_skinAllRenders);
|
|
}
|
|
return _skinAllRenders;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region//子类继承
|
|
protected virtual void OnSkinChange(FSkinBase skin, int part)
|
|
{
|
|
if (_partChangedCallBack != null) _partChangedCallBack(skin, part);
|
|
}
|
|
|
|
protected virtual void OnUpdate(float dt)
|
|
{
|
|
|
|
}
|
|
#endregion
|
|
|
|
#region//私有函数
|
|
private void OnDrag(GameObject go, Vector2 value)
|
|
{
|
|
if (!EnableDrag)
|
|
{
|
|
return;
|
|
}
|
|
var angles = _modelRoot.localEulerAngles;
|
|
angles.y -= value.x;
|
|
_modelRoot.localEulerAngles = angles;
|
|
if (_uiModelDragTrs != null)
|
|
{
|
|
_uiModelDragTrs.localEulerAngles = angles;
|
|
}
|
|
}
|
|
|
|
public void SetUIModelDrag(Transform trs)
|
|
{
|
|
_uiModelDragTrs = trs;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region //Behaviour的方法
|
|
protected override void OnBehaviourAwake()
|
|
{
|
|
_showFrameCount = 2;
|
|
if(_modelGo == null)
|
|
{
|
|
_modelRoot = TransformInst.Find("Box/ModelRoot");
|
|
_modelGo = _modelRoot.gameObject;
|
|
}
|
|
_modelGo.SetActive(false);
|
|
}
|
|
protected override void OnBehaviourOnEnable()
|
|
{
|
|
_showFrameCount = 2;
|
|
if (_modelGo == null)
|
|
{
|
|
_modelRoot = TransformInst.Find("Box/ModelRoot");
|
|
_modelGo = _modelRoot.gameObject;
|
|
}
|
|
_modelGo.SetActive(false);
|
|
if (_skin != null && !_skin.IsFreeze)
|
|
{
|
|
_skin.SetActive(true);
|
|
if (_equips.Count > 0)
|
|
{
|
|
var iter = _equips.GetEnumerator();
|
|
try
|
|
{
|
|
while (iter.MoveNext())
|
|
{
|
|
_skin.SetSkinPartFromCfgID(iter.Current.Key, iter.Current.Value, _anims.ContainsKey(iter.Current.Key) ? _anims[iter.Current.Key] : null);
|
|
}
|
|
}
|
|
finally
|
|
{
|
|
iter.Dispose();
|
|
}
|
|
}
|
|
_skin.PlayLastAnimInfo();
|
|
|
|
CalculatePos();
|
|
_modelRoot.localEulerAngles = _nomalEuleAngles;
|
|
}
|
|
base.OnBehaviourOnEnable();
|
|
}
|
|
|
|
protected override void OnBehaviourOnDisable()
|
|
{
|
|
if (_skin != null)
|
|
{
|
|
_skin.RemoveAllSkinPart();
|
|
_skin.SetActive(false);
|
|
}
|
|
base.OnBehaviourOnDisable();
|
|
}
|
|
|
|
protected override void OnBehaviourOnDestroy()
|
|
{
|
|
if (_skin != null)
|
|
{
|
|
_skin.Destroy();
|
|
}
|
|
_listener.onClick = null;
|
|
_listener.onDrag = null;
|
|
base.OnBehaviourOnDestroy();
|
|
}
|
|
|
|
private void Update()
|
|
{
|
|
if(renderQvalue != null)
|
|
{
|
|
var active = renderQvalue.finalAlpha > 0.002f;
|
|
if(active != _modelGo.activeSelf)
|
|
{
|
|
_modelGo.SetActive(active);
|
|
}
|
|
}
|
|
if (_skin != null)
|
|
{
|
|
_skin.Update(Time.deltaTime);
|
|
}
|
|
OnUpdate(Time.deltaTime);
|
|
base.OnBehaviourOnUpdate();
|
|
}
|
|
#endregion
|
|
|
|
#region//静态函数
|
|
|
|
#endregion
|
|
}
|
|
}
|