Files
Main/Assets/Code/Logic/_Required/FGameObject/FSkin/FSkinModel.cs
2025-01-25 04:38:09 +08:00

437 lines
16 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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