536 lines
22 KiB
C#
536 lines
22 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.IO;
|
|
using System.Threading.Tasks;
|
|
using Bfres.Structs;
|
|
using SharpYaml;
|
|
using SharpYaml.Events;
|
|
using SharpYaml.Serialization;
|
|
using SharpYaml.Serialization.Serializers;
|
|
using Syroot.NintenTools.NSW.Bfres;
|
|
using System.Reflection;
|
|
using System.Text.RegularExpressions;
|
|
|
|
namespace FirstPlugin
|
|
{
|
|
public class YamlFmaa
|
|
{
|
|
public class AnimConfig
|
|
{
|
|
public string Name { get; set; }
|
|
public string Path { get; set; }
|
|
public bool Loop { get; set; }
|
|
public int FrameCount { get; set; }
|
|
|
|
public List<MatAnimConfig> MaterialAnimConfigs { get; set; }
|
|
|
|
public void ToYaml(MaterialAnim materialAnim, FMAA.AnimationType animType)
|
|
{
|
|
MaterialAnimConfigs = new List<MatAnimConfig>();
|
|
|
|
Name = materialAnim.Name;
|
|
Path = materialAnim.Path;
|
|
FrameCount = materialAnim.FrameCount;
|
|
Loop = materialAnim.Loop;
|
|
|
|
foreach (var mat in materialAnim.MaterialAnimDataList)
|
|
{
|
|
MatAnimConfig matConfig = new MatAnimConfig();
|
|
matConfig.Name = mat.Name;
|
|
MaterialAnimConfigs.Add(matConfig);
|
|
|
|
foreach (var paramInfo in mat.ParamAnimInfos)
|
|
{
|
|
ParamInfo paramCfg = new ParamInfo();
|
|
paramCfg.Name = paramInfo.Name;
|
|
paramCfg.IsConstant = paramInfo.ConstantCount != 0;
|
|
matConfig.ParamInfos.Add(paramCfg);
|
|
|
|
if (paramInfo.ConstantCount != 0)
|
|
{
|
|
paramCfg.Constants = new List<ConstantConfig>();
|
|
for (int i = 0; i < paramInfo.ConstantCount; i++)
|
|
{
|
|
AnimConstant constant = mat.Constants[paramInfo.BeginConstant + i];
|
|
ConstantConfig ConstantValue = new ConstantConfig();
|
|
ConstantValue.Offset = ConvertParamOffset(constant.AnimDataOffset, animType);
|
|
ConstantValue.Value = constant.Value;
|
|
|
|
paramCfg.Constants.Add(ConstantValue);
|
|
}
|
|
}
|
|
|
|
if (paramInfo.BeginCurve != ushort.MaxValue)
|
|
{
|
|
paramCfg.CurveData = new List<CurveConfig>();
|
|
for (int i = 0; i < paramInfo.IntCurveCount + paramInfo.FloatCurveCount; i++)
|
|
{
|
|
var curve = mat.Curves[(int)paramInfo.BeginCurve + i];
|
|
var CurveCfg = new CurveConfig();
|
|
CurveCfg.Offset = ConvertParamOffset(curve.AnimDataOffset, animType);
|
|
|
|
if (curve.Scale == 0)
|
|
curve.Scale = 1;
|
|
|
|
for (int f = 0; f < curve.Frames.Length; f++)
|
|
{
|
|
int frame = (int)curve.Frames[f];
|
|
float Value = curve.Offset + curve.Keys[f, 0] * curve.Scale;
|
|
CurveCfg.KeyFrames.Add(frame, Value);
|
|
}
|
|
|
|
paramCfg.CurveData.Add(CurveCfg);
|
|
}
|
|
}
|
|
}
|
|
|
|
foreach (var patternInfo in mat.TexturePatternAnimInfos)
|
|
{
|
|
PatternInfo infoCfg = new PatternInfo();
|
|
infoCfg.Name = patternInfo.Name;
|
|
infoCfg.IsConstant = patternInfo.BeginConstant != ushort.MaxValue;
|
|
matConfig.TexturePatternInfos.Add(infoCfg);
|
|
|
|
if (infoCfg.IsConstant)
|
|
{
|
|
infoCfg.ConstantValue = new ConstantTPConfig();
|
|
int Index = (int)mat.Constants[(int)patternInfo.BeginConstant].Value;
|
|
infoCfg.ConstantValue.Texture = materialAnim.TextureNames[Index];
|
|
}
|
|
if (patternInfo.CurveIndex != ushort.MaxValue)
|
|
{
|
|
var curve = mat.Curves[(int)patternInfo.CurveIndex];
|
|
infoCfg.CurveData = new CurveTPConfig();
|
|
|
|
if (curve.Scale == 0)
|
|
curve.Scale = 1;
|
|
|
|
for (int f = 0; f < curve.Frames.Length; f++)
|
|
{
|
|
int frame = (int)curve.Frames[f];
|
|
int Value = (int)curve.Offset + (int)curve.Keys[f, 0] * (int)curve.Scale;
|
|
|
|
infoCfg.CurveData.KeyFrames.Add(frame, materialAnim.TextureNames[Value]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private uint ConvertParamOffset(string offset)
|
|
{
|
|
uint val = 0;
|
|
switch (offset)
|
|
{
|
|
case "R": return 0;
|
|
case "G": return 4;
|
|
case "B": return 8;
|
|
case "A": return 12;
|
|
case "Mode": return 0;
|
|
case "Scale X": return 4;
|
|
case "Scale Y": return 8;
|
|
case "Rotate": return 12;
|
|
case "Rotation": return 12;
|
|
case "Rotation X": return 12;
|
|
case "Rotate X": return 12;
|
|
case "Translate X": return 16;
|
|
case "Translate Y": return 20;
|
|
default:
|
|
bool isOffset = uint.TryParse(offset, out val);
|
|
if (!isOffset)
|
|
throw new Exception($"Invalid offset value {offset}");
|
|
break;
|
|
}
|
|
|
|
return val;
|
|
}
|
|
|
|
|
|
private string ConvertParamOffset(uint offset, FMAA.AnimationType animType)
|
|
{
|
|
if (animType== FMAA.AnimationType.Color)
|
|
{
|
|
switch (offset)
|
|
{
|
|
case 0: return "R";
|
|
case 4: return "G";
|
|
case 8: return "B";
|
|
case 12: return "A";
|
|
default:
|
|
return offset.ToString();
|
|
}
|
|
}
|
|
else if (animType == FMAA.AnimationType.TextureSrt)
|
|
{
|
|
switch (offset)
|
|
{
|
|
case 0: return "Mode";
|
|
case 4: return "Scale X";
|
|
case 8: return "Scale Y";
|
|
case 12: return "Rotate";
|
|
case 16: return "Translate X";
|
|
case 20: return "Translate Y";
|
|
default:
|
|
return offset.ToString();
|
|
}
|
|
}
|
|
|
|
return offset.ToString();
|
|
}
|
|
|
|
public MaterialAnim FromYaml()
|
|
{
|
|
MaterialAnim matAnim = new MaterialAnim();
|
|
matAnim.Name = Name;
|
|
matAnim.Path = Path;
|
|
matAnim.Loop = Loop;
|
|
matAnim.FrameCount = FrameCount;
|
|
matAnim.TextureNames = GenerateTextureList();
|
|
matAnim.BindIndices = new ushort[MaterialAnimConfigs.Count];
|
|
for (int i = 0; i < matAnim.BindIndices.Length; i++)
|
|
matAnim.BindIndices[i] = ushort.MaxValue;
|
|
|
|
int ShaderParamCurveIndex = 0;
|
|
int TexturePatternCurveIndex = 0;
|
|
|
|
Console.WriteLine("MaterialAnimConfigs " + MaterialAnimConfigs.Count);
|
|
foreach (var matCfg in MaterialAnimConfigs)
|
|
{
|
|
var matAnimData = new MaterialAnimData();
|
|
matAnimData.Name = matCfg.Name;
|
|
matAnimData.Constants = new List<AnimConstant>();
|
|
matAnimData.Curves = new List<AnimCurve>();
|
|
matAnimData.TexturePatternAnimInfos = new List<TexturePatternAnimInfo>();
|
|
matAnimData.ParamAnimInfos = new List<ParamAnimInfo>();
|
|
matAnimData.BeginVisalConstantIndex = -1;
|
|
matAnimData.ShaderParamCurveIndex = -1;
|
|
matAnimData.VisualConstantIndex = -1;
|
|
matAnimData.TexturePatternCurveIndex = -1;
|
|
matAnimData.VisalCurveIndex = -1;
|
|
matAnim.MaterialAnimDataList.Add(matAnimData);
|
|
|
|
ushort CurveIndex = 0;
|
|
ushort BeginConstantIndex = 0;
|
|
|
|
foreach (var texturePatternCfg in matCfg.TexturePatternInfos)
|
|
{
|
|
TexturePatternAnimInfo patternInfo = new TexturePatternAnimInfo();
|
|
patternInfo.Name = texturePatternCfg.Name;
|
|
matAnimData.TexturePatternAnimInfos.Add(patternInfo);
|
|
|
|
if (texturePatternCfg.IsConstant && texturePatternCfg.ConstantValue != null)
|
|
{
|
|
patternInfo.BeginConstant = BeginConstantIndex++;
|
|
|
|
AnimConstant constant = new AnimConstant();
|
|
constant.AnimDataOffset = 0;
|
|
constant.Value = matAnim.TextureNames.IndexOf(texturePatternCfg.ConstantValue.Texture);
|
|
matAnimData.Constants.Add(constant);
|
|
|
|
matAnimData.VisualConstantIndex = 0;
|
|
matAnimData.BeginVisalConstantIndex = 0;
|
|
}
|
|
else if (texturePatternCfg.CurveData != null)
|
|
{
|
|
patternInfo.CurveIndex = CurveIndex++;
|
|
|
|
matAnimData.TexturePatternCurveIndex = TexturePatternCurveIndex;
|
|
matAnimData.BeginVisalConstantIndex = 0;
|
|
|
|
AnimCurve curve = new AnimCurve();
|
|
matAnimData.Curves.Add(curve);
|
|
|
|
curve.Offset = 0;
|
|
curve.AnimDataOffset = 0;
|
|
curve.Scale = 1;
|
|
curve.CurveType = AnimCurveType.StepInt;
|
|
curve.StartFrame = 0;
|
|
|
|
int FrameCount = texturePatternCfg.CurveData.KeyFrames.Count;
|
|
|
|
curve.Frames = new float[FrameCount];
|
|
curve.Keys = new float[FrameCount, 1];
|
|
|
|
int MaxFrame = 0;
|
|
int MaxIndex = 0;
|
|
|
|
int i = 0;
|
|
foreach (var KeyFrame in texturePatternCfg.CurveData.KeyFrames)
|
|
{
|
|
int Index = matAnim.TextureNames.IndexOf(KeyFrame.Value);
|
|
Console.WriteLine($"{Index} {KeyFrame.Value}");
|
|
|
|
curve.Frames[i] = KeyFrame.Key;
|
|
curve.Keys[i, 0] = Index;
|
|
|
|
MaxFrame = Math.Max(MaxIndex, KeyFrame.Key);
|
|
MaxIndex = Math.Max(MaxIndex, Index);
|
|
|
|
i++;
|
|
}
|
|
|
|
curve.EndFrame = curve.Frames.Max();
|
|
|
|
if (curve.Keys.Length > 1)
|
|
{
|
|
curve.Delta = curve.Keys[curve.Keys.Length - 1,0] - curve.Keys[0, 0];
|
|
}
|
|
|
|
if (MaxFrame < byte.MaxValue)
|
|
curve.FrameType = AnimCurveFrameType.Byte;
|
|
else if (MaxFrame < ushort.MaxValue)
|
|
curve.FrameType = AnimCurveFrameType.Decimal10x5;
|
|
else
|
|
curve.FrameType = AnimCurveFrameType.Single;
|
|
|
|
if (MaxIndex < byte.MaxValue)
|
|
curve.KeyType = AnimCurveKeyType.SByte;
|
|
else if (MaxIndex < ushort.MaxValue)
|
|
curve.KeyType = AnimCurveKeyType.Int16;
|
|
else
|
|
curve.KeyType = AnimCurveKeyType.Single;
|
|
}
|
|
}
|
|
|
|
foreach (var paramCfg in matCfg.ParamInfos)
|
|
{
|
|
ParamAnimInfo paramInfo = new ParamAnimInfo();
|
|
paramInfo.Name = paramCfg.Name;
|
|
matAnimData.ParamAnimInfos.Add(paramInfo);
|
|
|
|
if (paramCfg.Constants != null && paramCfg.Constants.Count > 0)
|
|
{
|
|
paramInfo.BeginConstant = BeginConstantIndex;
|
|
paramInfo.ConstantCount = (ushort)paramCfg.Constants.Count;
|
|
|
|
BeginConstantIndex += (ushort)paramCfg.Constants.Count;
|
|
foreach (var constantCfg in paramCfg.Constants)
|
|
{
|
|
AnimConstant constant = new AnimConstant();
|
|
constant.AnimDataOffset = ConvertParamOffset(constantCfg.Offset);
|
|
constant.Value = constantCfg.Value;
|
|
matAnimData.Constants.Add(constant);
|
|
}
|
|
}
|
|
|
|
if (paramCfg.CurveData != null && paramCfg.CurveData.Count > 0)
|
|
{
|
|
matAnimData.ShaderParamCurveIndex = ShaderParamCurveIndex;
|
|
|
|
paramInfo.BeginCurve = CurveIndex;
|
|
paramInfo.FloatCurveCount = (ushort)paramCfg.CurveData.Count;
|
|
|
|
CurveIndex += (ushort)paramCfg.CurveData.Count;
|
|
foreach (var curveCfg in paramCfg.CurveData)
|
|
{
|
|
AnimCurve curve = new AnimCurve();
|
|
matAnimData.Curves.Add(curve);
|
|
curve.Offset = 0;
|
|
curve.AnimDataOffset = ConvertParamOffset(curveCfg.Offset);
|
|
curve.Scale = 1;
|
|
curve.CurveType = AnimCurveType.Linear;
|
|
curve.StartFrame = 0;
|
|
|
|
int MaxFrame = 0;
|
|
float MaxValue = 0;
|
|
|
|
int FrameCount = curveCfg.KeyFrames.Count;
|
|
curve.Frames = new float[FrameCount];
|
|
curve.Keys = new float[FrameCount, 2];
|
|
|
|
int i = 0;
|
|
var values = curveCfg.KeyFrames.Values.ToList();
|
|
foreach (var KeyFrame in curveCfg.KeyFrames)
|
|
{
|
|
curve.Frames[i] = KeyFrame.Key;
|
|
curve.Keys[i, 0] = KeyFrame.Value;
|
|
|
|
//Calculate delta
|
|
float Delta = 0;
|
|
if (i < values.Count - 1)
|
|
Delta = values[i + 1] - values[i];
|
|
|
|
curve.Keys[i, 1] = Delta;
|
|
|
|
MaxFrame = Math.Max(MaxFrame, KeyFrame.Key);
|
|
MaxValue = Math.Max(MaxValue, KeyFrame.Value);
|
|
i++;
|
|
}
|
|
|
|
curve.EndFrame = curve.Frames.Max();
|
|
|
|
if (curve.Keys.Length > 1)
|
|
{
|
|
curve.Delta = values[values.Count - 1] - values[0];
|
|
}
|
|
|
|
curve.KeyType = AnimCurveKeyType.Single;
|
|
curve.FrameType = AnimCurveFrameType.Single;
|
|
|
|
/* if (MaxFrame < byte.MaxValue)
|
|
curve.FrameType = AnimCurveFrameType.Byte;
|
|
else if (MaxFrame < ushort.MaxValue)
|
|
curve.FrameType = AnimCurveFrameType.Decimal10x5;
|
|
else
|
|
curve.FrameType = AnimCurveFrameType.Single;
|
|
|
|
if (MaxValue < byte.MaxValue)
|
|
curve.KeyType = AnimCurveKeyType.SByte;
|
|
else if (MaxValue < ushort.MaxValue)
|
|
curve.KeyType = AnimCurveKeyType.Int16;
|
|
else
|
|
curve.KeyType = AnimCurveKeyType.Single;*/
|
|
}
|
|
}
|
|
}
|
|
|
|
TexturePatternCurveIndex += matAnimData.TexturePatternAnimInfos.Where(item => item.CurveIndex != uint.MaxValue).ToList().Count;
|
|
ShaderParamCurveIndex += CurveIndex;
|
|
}
|
|
|
|
return matAnim;
|
|
}
|
|
|
|
private List<string> GenerateTextureList()
|
|
{
|
|
List<string> Textures = new List<string>();
|
|
foreach (var matCfg in MaterialAnimConfigs)
|
|
{
|
|
foreach (var texturePatternCfg in matCfg.TexturePatternInfos)
|
|
{
|
|
if (texturePatternCfg.ConstantValue != null)
|
|
{
|
|
if (!Textures.Contains(texturePatternCfg.ConstantValue.Texture))
|
|
Textures.Add(texturePatternCfg.ConstantValue.Texture);
|
|
}
|
|
|
|
if (texturePatternCfg.CurveData == null)
|
|
continue;
|
|
|
|
foreach (var KeyFrame in texturePatternCfg.CurveData.KeyFrames)
|
|
if (!Textures.Contains(KeyFrame.Value))
|
|
Textures.Add(KeyFrame.Value);
|
|
}
|
|
}
|
|
|
|
return Textures;
|
|
}
|
|
}
|
|
|
|
public class ConstantConfig
|
|
{
|
|
public string Offset { get; set; }
|
|
public float Value { get; set; }
|
|
}
|
|
|
|
public class ConstantTPConfig
|
|
{
|
|
public string Texture { get; set; }
|
|
}
|
|
|
|
public class CurveConfig
|
|
{
|
|
public Dictionary<int, float> KeyFrames { get; set; }
|
|
|
|
public string Offset;
|
|
|
|
public CurveConfig()
|
|
{
|
|
KeyFrames = new Dictionary<int, float>();
|
|
}
|
|
}
|
|
|
|
public class CurveTPConfig
|
|
{
|
|
public Dictionary<int, string> KeyFrames { get; set; }
|
|
|
|
public CurveTPConfig()
|
|
{
|
|
KeyFrames = new Dictionary<int, string>();
|
|
}
|
|
}
|
|
|
|
public class MatAnimConfig
|
|
{
|
|
public string Name { get; set; }
|
|
|
|
public List<PatternInfo> TexturePatternInfos { get; set; }
|
|
public List<ParamInfo> ParamInfos { get; set; }
|
|
|
|
public MatAnimConfig()
|
|
{
|
|
TexturePatternInfos = new List<PatternInfo>();
|
|
ParamInfos = new List<ParamInfo>();
|
|
}
|
|
}
|
|
|
|
public class ParamInfo
|
|
{
|
|
public string Name { get; set; }
|
|
|
|
public bool IsConstant { get; set; }
|
|
|
|
public List<ConstantConfig> Constants { get; set; }
|
|
|
|
public List<CurveConfig> CurveData { get; set; }
|
|
}
|
|
|
|
public class PatternInfo
|
|
{
|
|
public string Name { get; set; }
|
|
|
|
public bool IsConstant { get; set; }
|
|
|
|
public ConstantTPConfig ConstantValue { get; set; }
|
|
|
|
public CurveTPConfig CurveData { get; set; }
|
|
}
|
|
|
|
public static MaterialAnim FromYaml(string Name)
|
|
{
|
|
var serializerSettings = new SerializerSettings()
|
|
{
|
|
// EmitTags = false
|
|
};
|
|
|
|
serializerSettings.DefaultStyle = YamlStyle.Any;
|
|
serializerSettings.ComparerForKeySorting = null;
|
|
serializerSettings.RegisterTagMapping("AnimConfig", typeof(AnimConfig));
|
|
|
|
var serializer = new Serializer( serializerSettings);
|
|
AnimConfig config = serializer.Deserialize<AnimConfig>(File.ReadAllText(Name));
|
|
|
|
return config.FromYaml();
|
|
}
|
|
|
|
public static string ToYaml(string Name, MaterialAnim MatAnim, FMAA.AnimationType animType)
|
|
{
|
|
var serializerSettings = new SerializerSettings()
|
|
{
|
|
EmitTags = false,
|
|
EmitAlias = false,
|
|
EmitCapacityForList = false,
|
|
EmitShortTypeName = false
|
|
};
|
|
|
|
serializerSettings.DefaultStyle = YamlStyle.Any;
|
|
serializerSettings.ComparerForKeySorting = null;
|
|
serializerSettings.RegisterTagMapping("AnimConfig", typeof(AnimConfig));
|
|
|
|
var config = new AnimConfig();
|
|
config.ToYaml(MatAnim, animType);
|
|
|
|
var serializer = new Serializer(serializerSettings);
|
|
string yaml = serializer.Serialize(config, typeof(AnimConfig));
|
|
|
|
return yaml;
|
|
}
|
|
|
|
private void SetConfig()
|
|
{
|
|
|
|
}
|
|
}
|
|
}
|