using System.Collections.Generic;
using Thousandto.Code.Center;
using Thousandto.Core.Asset;
using UnityEngine;
using FLogger = UnityEngine.Gonbest.MagicCube.FLogger;
namespace Thousandto.Code.Logic
{
///
/// FSkinModel的配置信息
///
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 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;
}
///
/// 设置状态
///
///
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");
}
}
}
//设置布料系统
///
///
///
/// 是否使用布料
/// 柔软度,0-1之间,骨骼当前方向到目标方向的平滑度
/// 整体硬度,越小像丝带,越大像钢筋
/// 力衰减,越大越丝滑,越小像多节棍
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//私有方法
///
/// 当状态改变后对Shader进行处理
///
///
///
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 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
}
}