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