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
|
|||
|
}
|
|||
|
}
|