437 lines
16 KiB
C#
437 lines
16 KiB
C#
using System.Collections.Generic;
|
||
using Thousandto.Code.Center;
|
||
using Thousandto.Core.Asset;
|
||
using UnityEngine;
|
||
using FLogger = UnityEngine.Gonbest.MagicCube.FLogger;
|
||
|
||
namespace Thousandto.Code.Logic
|
||
{
|
||
/// <summary>
|
||
/// FSkinModel的配置信息
|
||
/// </summary>
|
||
public class FSkinModel : FSkinBase
|
||
{
|
||
#region//私有变量
|
||
//Skin类型
|
||
private FSkinTypeCode _skinTypeCode;
|
||
//状态类型
|
||
private FSkinStatusCode _skinStatus = FSkinStatusCode.Normal;
|
||
//记录是否开启乳摇系统
|
||
private bool _bjEnable = false;
|
||
|
||
//部位的配置ID
|
||
private RecordSkinPartInfo[] _SkinPartConfigIDs = new RecordSkinPartInfo[(int)FSkinPartCode.MaxCount];
|
||
|
||
public FSkinStatusCode SkinStatus
|
||
{
|
||
get
|
||
{
|
||
return _skinStatus;
|
||
}
|
||
}
|
||
|
||
public FSkinTypeCode SkinTypeCode
|
||
{
|
||
get
|
||
{
|
||
return _skinTypeCode;
|
||
}
|
||
set
|
||
{
|
||
_skinTypeCode = value;
|
||
}
|
||
}
|
||
#endregion
|
||
|
||
#region//构造函数
|
||
|
||
//构造函数
|
||
protected FSkinModel(FSkinTypeCode code)
|
||
{
|
||
_skinTypeCode = code;
|
||
}
|
||
|
||
//拷贝构造函数
|
||
protected FSkinModel(FSkinModel from)
|
||
: base(from)
|
||
{
|
||
_skinTypeCode = from._skinTypeCode;
|
||
_skinStatus = from._skinStatus;
|
||
|
||
}
|
||
#endregion
|
||
|
||
#region//公共接口
|
||
//隐藏某个部位
|
||
public void HideSkinPart(int code)
|
||
{
|
||
_SkinPartConfigIDs[(int)code].IsHide = true;
|
||
base.RemoveSkinPart(code);
|
||
}
|
||
|
||
//显示某个部位
|
||
public void ShowSkinPart(int code, bool bClearVfx = true)
|
||
{
|
||
if (_SkinPartConfigIDs[(int)code].IsHide)
|
||
{
|
||
_SkinPartConfigIDs[(int)code].IsHide = false;
|
||
if (_SkinPartConfigIDs[(int)code].CfgID > 0)
|
||
{
|
||
SetSkinPartFromCfgID(code, _SkinPartConfigIDs[(int)code].CfgID, _SkinPartConfigIDs[(int)code].Anims, _SkinPartConfigIDs[(int)code].isScene, _SkinPartConfigIDs[(int)code].SlotName, bClearVfx);
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
//隐藏所有部位的特效
|
||
public void HideAllPartVfx()
|
||
{
|
||
for (int i = 0; i < _SkinPartConfigIDs.Length; i++)
|
||
{
|
||
if (!_SkinPartConfigIDs[i].IsHide && _SkinPartConfigIDs[i].CfgID > 0)
|
||
{
|
||
RemoveSkinPartVFX(i);
|
||
}
|
||
}
|
||
}
|
||
|
||
//显示所有部位的特效
|
||
public void ShowAllPartVfx()
|
||
{
|
||
for (int code = 0; code < _SkinPartConfigIDs.Length; code++)
|
||
{
|
||
if (!_SkinPartConfigIDs[code].IsHide && _SkinPartConfigIDs[code].CfgID > 0)
|
||
{
|
||
RemoveSkinPartVFX(code);
|
||
var model = FSkinModelConfig.GetConfigData(_SkinPartConfigIDs[code].CfgID);
|
||
if (model != null)
|
||
{
|
||
for (int i = 0; i < model.VfxList.Count; i++)
|
||
{
|
||
AddVFX(model.VfxList[i].VfxType, model.VfxList[i].VfxID, model.VfxList[i].SlotName, code, false, true, false);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
//设置某个部位
|
||
public void SetSkinPartFromCfgID(int code, int cfgID, Dictionary<string, bool> animNames = null, bool isScene = false, string slotName = null, bool bClearAllVfx = true)
|
||
{
|
||
//?????????????这里屏蔽翅膀
|
||
//if (code == FSkinPartCode.Wing) cfgID = -1;
|
||
//记录设置信息
|
||
_SkinPartConfigIDs[(int)code].CfgID = cfgID;
|
||
_SkinPartConfigIDs[(int)code].Cfg = null;
|
||
_SkinPartConfigIDs[(int)code].Anims = animNames;
|
||
_SkinPartConfigIDs[(int)code].isScene = isScene;
|
||
_SkinPartConfigIDs[(int)code].SlotName = SlotName;
|
||
_SkinPartConfigIDs[(int)code].UseEffectStatus = FSkinStatusCode.Normal;
|
||
if (code == FSkinPartCode.Wing && isScene)
|
||
{
|
||
_SkinPartConfigIDs[(int)code].IsHide = GameObjectLimit.IsCanShowWing();
|
||
}
|
||
|
||
if (cfgID <= 0)
|
||
{
|
||
base.RemoveSkinPart(code);
|
||
}
|
||
else
|
||
{
|
||
//如果是隐藏,那么就不再显示
|
||
if (_SkinPartConfigIDs[(int)code].IsHide || !IsActive())
|
||
{
|
||
return;
|
||
}
|
||
|
||
var model = FSkinModelConfig.GetConfigData(cfgID);
|
||
if (model != null)
|
||
{
|
||
_SkinPartConfigIDs[(int)code].Cfg = model;
|
||
_SkinPartConfigIDs[(int)code].UseEffectStatus = model.ApplyStatus;
|
||
|
||
//如果角色在场景中,并且动作片段没有特别设定,那么就直接通过模型类型和模型ID来读取
|
||
if (animNames == null && model.ModelType == ModelTypeCode.Player)
|
||
{
|
||
if (isScene)
|
||
{
|
||
animNames = FPlayerAnimRelation.SceneAnims;
|
||
}
|
||
else
|
||
{
|
||
animNames = FPlayerAnimRelation.UISimpleAnims;
|
||
}
|
||
}
|
||
//移除之前的特效
|
||
RemoveSkinPartVFX(code, bClearAllVfx);
|
||
SetSkinPart(code, model.ModelType, model.ModelID, model.IsShow, animNames, model.GetShaderName(_skinTypeCode), model.ShaderProperties, slotName);
|
||
//只针对场景角色,对于UI界面上的角色不做处理
|
||
if (!isScene || GameCenter.GameSetting.IsEnabled(GameSettingKeyCode.EnableModelVFX) || (LogicObject != null && LogicObject.ID == LocalPlayerRoot.LocalPlayerID))
|
||
{
|
||
for (int i = 0; i < model.VfxList.Count; i++)
|
||
{
|
||
AddVFX(model.VfxList[i].VfxType, model.VfxList[i].VfxID, model.VfxList[i].SlotName, code, false, true, false);
|
||
}
|
||
}
|
||
|
||
if (code == FSkinPartCode.Body && _bjEnable)
|
||
{
|
||
SetBreastJiggly(_bjEnable);
|
||
}
|
||
OnStatusChanged(code, _skinStatus);
|
||
|
||
}
|
||
else
|
||
{
|
||
|
||
FLogger.DebugLogError("SetSkinPart [" + code + "] 从表ModelConfig中没有找到ID=" + cfgID + "的模型信息!");
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
//获取Skin部位的配置ID
|
||
public int GetSkinPartCfgID(int code)
|
||
{
|
||
return _SkinPartConfigIDs[(int)code].CfgID;
|
||
}
|
||
|
||
//添加特效
|
||
public FGameObjectVFX AddSkinPartVFXFromCfgID(int code, string slot, int cfgID, bool immediatelyLoad = true, bool startActive = false, bool IsFinishedDestory = false)
|
||
{
|
||
if (cfgID > 0 || !IsActive())
|
||
{
|
||
var model = FSkinModelConfig.GetConfigData(cfgID);
|
||
if (model != null)
|
||
{
|
||
return AddVFX(model.ModelType, model.ModelID, slot, code, immediatelyLoad, startActive, IsFinishedDestory);
|
||
}
|
||
else
|
||
{
|
||
FLogger.DebugLogError("AddSkinPartVFX [" + code + "][" + slot + "] 从表ModelConfig中没有找到ID=" + cfgID + "的模型信息!");
|
||
}
|
||
}
|
||
return null;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 设置状态
|
||
/// </summary>
|
||
/// <param name="code"></param>
|
||
public void SetStatus(FSkinStatusCode code)
|
||
{
|
||
if (_skinStatus != code)
|
||
{
|
||
_skinStatus = code;
|
||
//状态改变,这里只针对模型而不针对特效信息
|
||
for (int i = (int)FSkinPartCode.Mount; i <= (int)FSkinPartCode.LastModel; i++)
|
||
{
|
||
OnStatusChanged(i, _skinStatus);
|
||
}
|
||
}
|
||
}
|
||
|
||
//设置乳摇系统
|
||
public void SetBreastJiggly(bool isEnable)
|
||
{
|
||
_bjEnable = isEnable;
|
||
var f = GetSkinPart(FSkinPartCode.Body);
|
||
if (f != null)
|
||
{
|
||
if (isEnable)
|
||
{
|
||
f.AddDynamicBone("xiongL", DynamicBoneType.Breast);
|
||
f.AddDynamicBone("xiongR", DynamicBoneType.Breast);
|
||
}
|
||
else
|
||
{
|
||
f.RemoveDynamicBone("xiongL");
|
||
f.RemoveDynamicBone("xiongR");
|
||
}
|
||
}
|
||
}
|
||
|
||
//设置布料系统
|
||
/// <summary>
|
||
///
|
||
/// </summary>
|
||
/// <param name="isEnable">是否使用布料</param>
|
||
/// <param name="dynamicRatio"> 柔软度,0-1之间,骨骼当前方向到目标方向的平滑度</param>
|
||
/// <param name="stiffnessForce">整体硬度,越小像丝带,越大像钢筋</param>
|
||
/// <param name="dragForce">力衰减,越大越丝滑,越小像多节棍</param>
|
||
public void SetClothEnable(bool isEnable, float dynamicRatio = 0, float stiffnessForce = 0, float dragForce = 0)
|
||
{
|
||
if (isEnable)
|
||
{
|
||
FGameObjectBody body = GetSkinPart(FSkinPartCode.Body) as FGameObjectBody;
|
||
if (body != null)
|
||
{
|
||
body.SetClothAnimParams(isEnable, dynamicRatio, stiffnessForce, dragForce);
|
||
}
|
||
}
|
||
}
|
||
|
||
//设置是否开启翅膀柔体
|
||
public void SetBoneClothEnable(bool isEnable)
|
||
{
|
||
FGameObjectBody body = GetSkinPart(FSkinPartCode.Body) as FGameObjectBody;
|
||
if (body != null)
|
||
{
|
||
body.UseBoneCloth = true;
|
||
}
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region //重写父类的函数 -- new
|
||
//移除所有SkinPart
|
||
public new void RemoveAllSkinPart(bool isStopAnim = false)
|
||
{
|
||
//把所有配置信息清理了.
|
||
for (int i = 0; i < _SkinPartConfigIDs.Length; i++)
|
||
{
|
||
_SkinPartConfigIDs[i].Reset();
|
||
}
|
||
base.RemoveAllSkinPart(isStopAnim);
|
||
}
|
||
#endregion
|
||
|
||
#region//重写父类函数 保护
|
||
|
||
//激活状态被改变
|
||
protected override void OnActiveChanged(bool active)
|
||
{
|
||
if (active)
|
||
{
|
||
//如果是激活状态
|
||
for (int code = 0; code < _SkinPartConfigIDs.Length; code++)
|
||
{
|
||
if (!_SkinPartConfigIDs[code].IsHide)
|
||
{
|
||
if (_SkinPartConfigIDs[code].CfgID > 0)
|
||
{
|
||
SetSkinPartFromCfgID(code, _SkinPartConfigIDs[code].CfgID, _SkinPartConfigIDs[code].Anims, _SkinPartConfigIDs[(int)code].isScene, _SkinPartConfigIDs[code].SlotName, true);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{ //如果变为非激活状态
|
||
for (int i = 0; i < _SkinPartConfigIDs.Length; i++)
|
||
{
|
||
base.RemoveSkinPart(i);
|
||
}
|
||
}
|
||
base.OnActiveChanged(active);
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region//私有方法
|
||
|
||
/// <summary>
|
||
/// 当状态改变后对Shader进行处理
|
||
/// </summary>
|
||
/// <param name="part"></param>
|
||
/// <param name="status"></param>
|
||
private void OnStatusChanged(int part, FSkinStatusCode status)
|
||
{
|
||
var skincfg = _SkinPartConfigIDs[(int)part];
|
||
if (skincfg.Cfg == null) return;
|
||
|
||
//如果这个模型效果ID小于0,那么就对于他的shader不做任何改变
|
||
if (skincfg.Cfg.ModelEffectID < 0)
|
||
{
|
||
//设置为null,表示当前模型不进行任何Shader的替换
|
||
SetRealShader(part, null);
|
||
return;
|
||
}
|
||
|
||
//Debug.LogError("AAAAAAAAAA:" + skincfg.Cfg.ModelID + ":::" + skincfg.CfgID + ":::" + skincfg.Cfg.ModelEffectID+":::"+ part);
|
||
if ((status & skincfg.UseEffectStatus) == status)
|
||
{//如果当前状态在适用范围,那么就适用配置表给的Shader和属性 ,其中normal永远是适用的.
|
||
var modelInfo = GetSkinPartModelInfo(part);
|
||
if (modelInfo != null)
|
||
{
|
||
if (modelInfo.ShaderName != null)
|
||
{
|
||
SetShader(part, modelInfo.ShaderName);
|
||
if (modelInfo.ShaderProperties != null)
|
||
{
|
||
var e = modelInfo.ShaderProperties.GetEnumerator();
|
||
while (e.MoveNext())
|
||
{
|
||
SetValue(part, e.Current.Key, e.Current.Value);
|
||
}
|
||
}
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
|
||
//如果在上面没有找到Shader,那么就直接使用当前状态的默认Shader来处理
|
||
var shader = FSkinShaderRelation.GetStatusShader(_skinTypeCode, part, status);
|
||
if (shader != null)
|
||
{
|
||
SetShader(part, shader);
|
||
if (_SkinPartConfigIDs[(int)part].Cfg != null)
|
||
{
|
||
// SetValue(part, ShaderPropertyNameDefine.CN_SPN_OUTLINE, _SkinPartConfigIDs[(int)part].Cfg.OutLineWidth);
|
||
//SetValue(part, ShaderPropertyNameDefine.CN_SPN_OUTLINECOLOR, _SkinPartConfigIDs[(int)part].Cfg.OutLineColor);
|
||
}
|
||
}
|
||
}
|
||
|
||
//从表格中获取模型类型
|
||
private ModelTypeCode GetModelType(RoleSkinModelType type)
|
||
{
|
||
switch (type)
|
||
{
|
||
case RoleSkinModelType.PlayerBody://角色身体
|
||
return ModelTypeCode.Player;
|
||
case RoleSkinModelType.PlayerWeapon://武器
|
||
return ModelTypeCode.Weapon;
|
||
case RoleSkinModelType.PlayerWing: //翅膀
|
||
return ModelTypeCode.Wing;
|
||
case RoleSkinModelType.PlayerMount://角色坐骑
|
||
return ModelTypeCode.Mount;
|
||
case RoleSkinModelType.MonsterBody://怪物,npc主体
|
||
return ModelTypeCode.Monster;
|
||
case RoleSkinModelType.CollectionBody://采集物主体
|
||
return ModelTypeCode.Object;
|
||
case RoleSkinModelType.PlayerStrengthenVfx://角色强化特效
|
||
return ModelTypeCode.StrengthenVfx;
|
||
case RoleSkinModelType.DrapItem: //用于展示的武器
|
||
return ModelTypeCode.Object;
|
||
default:
|
||
return ModelTypeCode.Object;
|
||
}
|
||
}
|
||
#endregion
|
||
|
||
#region//私有类
|
||
//记录皮肤的某个部分的信息
|
||
private struct RecordSkinPartInfo
|
||
{
|
||
public bool IsHide;
|
||
public int CfgID;
|
||
public FSkinModelConfig Cfg;
|
||
public Dictionary<string, bool> Anims;
|
||
public bool isScene;
|
||
public string SlotName;
|
||
public FSkinStatusCode UseEffectStatus;
|
||
public void Reset()
|
||
{
|
||
IsHide = false;
|
||
CfgID = -1;
|
||
Cfg = null;
|
||
Anims = null;
|
||
isScene = false;
|
||
SlotName = null;
|
||
UseEffectStatus = FSkinStatusCode.Normal;
|
||
}
|
||
}
|
||
#endregion
|
||
}
|
||
}
|