using Games.LogicObj; using GCGame.Table; using Module.Log; using System.Collections.Generic; using UnityEngine; using StringComparison = System.StringComparison; //所有需要改变材质属性值得,都通过该类管理实现 /// EffectParams /// 参数1 类型个数 /// 参数2 属性类型 int float color 等 /// 参数3 属性名称 /// 参数4 属性开始数值 当是 Color Vector等类型时 配置形式 1,1,1,1。配置Default表示材质默认值。 /// 参数5 属性结束数值 当是 Color Vector等类型时 配置形式 1,1,1,1。配置Default表示材质默认值。 /// 参数6 渐变参数,该属性从开始到结束过渡方式 -1整个过程渐变,0保持开始数值,>0渐变(渐变持续时间) public class ChangeMatPro { private const string _defaultValueName = "Default"; private const string _intTypeName = "int"; private const string _floatTypeName = "float"; private const string _colorTypeName = "color"; private const string _vectorTypeName = "vector"; private const string _macroTypeName = "macro"; protected Obj obj; protected int part; protected Tab_EffectParam effectParam; private readonly List _floatTokenList; private readonly List _vectorTokenList; private readonly List _macroTokenList; public ChangeMatPro(Obj obj, int part, Tab_EffectParam effectParam) { this.obj = obj; this.part = part; this.effectParam = effectParam; _floatTokenList = new List(); _vectorTokenList = new List(); _macroTokenList = new List(); } public void Start(Tab_EffectParam param, float duration) { if (obj != null && param != null) { var countStr = param.GetParamValuebyIndex(0); int count; if (!string.IsNullOrEmpty(countStr) && int.TryParse(countStr, out count)) { for (var i = 0; i < count; i++) { var index = i * 5 + 1; var properType = param.GetParamValuebyIndex(index); var properName = param.GetParamValuebyIndex(index + 1); var startValue = param.GetParamValuebyIndex(index + 2); var endValue = param.GetParamValuebyIndex(index + 3); var fadeOutTime = param.GetParamValuebyIndex(index + 4); AddProperty(properType, properName, startValue, endValue, fadeOutTime, duration); } } } } public void SetRatio(float ratio) { for (var i = 0; i < _floatTokenList.Count; i++) { var token = _floatTokenList[i]; token.SetRatio(ratio); obj.ModifyFloatPropertyMod(token.token, token.Current, part); } for (var i = 0; i < _vectorTokenList.Count; i++) { var token = _vectorTokenList[i]; token.SetRatio(ratio); obj.ModifyVectorPropertyMod(token.token, token.Current, part); } } private void AddProperty(string propertyType, string propertyName, string startValue, string endValue, string fadeOutTime, float duration) { // 临时使用这个变量提高代码重用率,0 = 无效,1 = float, 2 = vector; var propertyTypeInt = 0; if (string.Equals(propertyType, _intTypeName, StringComparison.CurrentCultureIgnoreCase) || string.Equals(propertyType, _floatTypeName, StringComparison.CurrentCultureIgnoreCase)) propertyTypeInt = 1; else if (string.Equals(propertyType, _colorTypeName, StringComparison.CurrentCultureIgnoreCase) || string.Equals(propertyType, _vectorTypeName, StringComparison.CurrentCultureIgnoreCase)) propertyTypeInt = 2; else if (string.Equals(propertyType, _macroTypeName, StringComparison.CurrentCultureIgnoreCase)) propertyTypeInt = 3; if (propertyTypeInt > 0) { float fadeStart; if (float.TryParse(fadeOutTime, out fadeStart)) { if (fadeStart <= -1f) fadeStart = Time.time; else if (fadeStart <= 0f) fadeStart = Time.time + duration; else fadeStart = Time.time + Mathf.Max(0f, duration - fadeStart); } else { LogModule.ErrorLog(string.Format("效果参数id={0}中,渐变时间{1}无法转换为浮点数!", effectParam.EffectParamID, fadeOutTime)); fadeStart = Time.time + duration; } switch (propertyTypeInt) { case 1: { // Float类型属性 var targetValue = StringToFloatValue(startValue, propertyName); var defaultValue = StringToFloatValue(endValue, propertyName); var nameId = Shader.PropertyToID(propertyName); var token = obj.CreateFloatPropertyMod(nameId, targetValue, part); var floatToken = new MatProFloatToken(token, targetValue, defaultValue, duration, fadeStart); _floatTokenList.Add(floatToken); } break; case 2: { // Vector类型属性 var targetValue = StringToVectorValue(startValue, propertyName); var defaultValue = StringToVectorValue(endValue, propertyName); var nameId = Shader.PropertyToID(propertyName); var token = obj.CreateVectorPropertyMod(nameId, targetValue, part); var vectorToken = new MatProVectorToken(token, targetValue, defaultValue, duration, fadeStart); _vectorTokenList.Add(vectorToken); } break; case 3: { // 材质宏属性 var token = obj.CreateMacroPropertyMod(propertyName, part); _macroTokenList.Add(token); } break; } } } private float StringToFloatValue(string stringValue, string propertyName) { float result; if (string.Equals(stringValue, _defaultValueName, StringComparison.CurrentCultureIgnoreCase)) result = obj.GetDefaultFloat(0, propertyName, part); else { if (!float.TryParse(stringValue, out result)) { LogPropertyValueParseError(effectParam.EffectParamID, stringValue, "Float"); result = default(float); } } return result; } private Vector4 StringToVectorValue(string stringValue, string propertyName) { const string vectorTypeName = "Vector"; Vector4 result; if (string.Equals(stringValue, _defaultValueName, StringComparison.CurrentCultureIgnoreCase)) result = obj.GetDefaultVector(0, propertyName, part); else { result = default(Vector4); var targetStrArray = stringValue.Trim('"').Split(','); if (targetStrArray.Length == 4) { for (var i = 0; i < targetStrArray.Length; i++) { float floatValue; if (float.TryParse(targetStrArray[i], out floatValue)) result[i] = floatValue; else { LogPropertyValueParseError(effectParam.EffectParamID, stringValue, vectorTypeName); break; } } } else LogPropertyValueParseError(effectParam.EffectParamID, stringValue, vectorTypeName); } return result; } private static void LogPropertyValueParseError(int id, string properValue, string propertyType) { LogModule.ErrorLog(string.Format("效果参数id={0}中,{1}数值无法转换为{2}!", id, properValue, propertyType)); } public void StopEffect() { if (obj != null) { // 应该StopEffect后,上层会抛弃数据,因此不额外清空数列 for (var i = 0; i < _floatTokenList.Count; i++) obj.RemoveFloatPropertyMod(_floatTokenList[i].token, part); for (var i = 0; i < _vectorTokenList.Count; i++) obj.RemoveVectorPropertyMod(_vectorTokenList[i].token, part); for (var i = 0; i < _macroTokenList.Count; i++) obj.RemoveMacroPropertyMode(_macroTokenList[i], part); } } public void OnUpdate() { if (obj != null) { for (var i = 0; i < _floatTokenList.Count; i++) { var token = _floatTokenList[i]; token.Update(); if (token.ValueUpdate) obj.ModifyFloatPropertyMod(token.token, token.Current, part); } for (var i = 0; i < _vectorTokenList.Count; i++) { var token = _vectorTokenList[i]; token.Update(); if (token.ValueUpdate) obj.ModifyVectorPropertyMod(token.token, token.Current, part); } } } public abstract class MatProToken { public int token; public T targetValue; public T defaultValue; public float duration; public float fadeStart; public bool ValueUpdate { get; private set; } public T Current { get; private set; } protected MatProToken(int token, T targetValue, T defaultValue, float duration, float fadeStart) { this.token = token; this.targetValue = targetValue; this.defaultValue = defaultValue; this.duration = duration; this.fadeStart = fadeStart; } public void Update() { var value = GetValue(); ValueUpdate = !value.Equals(Current); Current = value; } public void SetRatio(float ratio) { Current = LerpValue(targetValue, defaultValue, ratio); } private T GetValue() { if (Time.time > fadeStart) return LerpValue(targetValue, defaultValue, (Time.time - fadeStart) / duration); else return targetValue; } protected abstract T LerpValue(T start, T end, float ratio); } public class MatProFloatToken : MatProToken { public MatProFloatToken(int token, float targetValue, float defaultValue, float duration, float fadeStart) : base(token, targetValue, defaultValue, duration, fadeStart) { } protected override float LerpValue(float start, float end, float ratio) { return Mathf.Lerp(start, end, ratio); } } public class MatProVectorToken : MatProToken { public MatProVectorToken(int token, Vector4 targetValue, Vector4 defaultValue, float duration, float fadeStart) : base(token, targetValue, defaultValue, duration, fadeStart) { } protected override Vector4 LerpValue(Vector4 start, Vector4 end, float ratio) { return Vector4.Lerp(start, end, ratio); } } }