|
@@ -0,0 +1,372 @@
|
|
|
+using System;
|
|
|
+using System.Collections.Generic;
|
|
|
+using System.IO;
|
|
|
+using System.Linq;
|
|
|
+using System.Reflection;
|
|
|
+using System.Text;
|
|
|
+using CommandLine;
|
|
|
+using YamlDotNet.Core;
|
|
|
+using YamlDotNet.Serialization;
|
|
|
+
|
|
|
+namespace ArcToolkitCLI.Commands.Converters
|
|
|
+{
|
|
|
+ [Verb("mate", HelpText = "Convert MATE files into YAML and back")]
|
|
|
+ public class MateConverter : BaseConverter
|
|
|
+ {
|
|
|
+ private const string MATE_TAG = "CM3D2_MATERIAL";
|
|
|
+
|
|
|
+ private readonly Dictionary<string, Type> mappingTypes;
|
|
|
+
|
|
|
+ public MateConverter()
|
|
|
+ {
|
|
|
+ Converters = new Dictionary<string, Func<string, int>>
|
|
|
+ {
|
|
|
+ [".mate"] = MateToYaml,
|
|
|
+ [".yaml"] = YamlToMate
|
|
|
+ };
|
|
|
+
|
|
|
+ mappingTypes = GetType().GetNestedTypes(BindingFlags.NonPublic).Select(t => new
|
|
|
+ {
|
|
|
+ type = t,
|
|
|
+ attrs = t.GetCustomAttributes(typeof(TagAttribute), true).Cast<TagAttribute>().ToArray()
|
|
|
+ })
|
|
|
+ .Where(d => d.attrs.Length != 0)
|
|
|
+ .ToDictionary(d => $"!{d.attrs.First().Tag}", d => d.type);
|
|
|
+ }
|
|
|
+
|
|
|
+ private int YamlToMate(string file)
|
|
|
+ {
|
|
|
+ var fileName = Path.GetFileNameWithoutExtension(file);
|
|
|
+
|
|
|
+ if (!fileName.ToLowerInvariant().EndsWith(".mate"))
|
|
|
+ {
|
|
|
+ Console.WriteLine($"Filename of {file} must have .mate.yaml extension! Skipping...");
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ var db = new DeserializerBuilder();
|
|
|
+
|
|
|
+ foreach (var kv in mappingTypes)
|
|
|
+ db.WithTagMapping(kv.Key, kv.Value);
|
|
|
+
|
|
|
+ var deserializer = db.Build();
|
|
|
+
|
|
|
+ MateFile data;
|
|
|
+ try
|
|
|
+ {
|
|
|
+ data = deserializer.Deserialize<MateFile>(new StreamReader(file, Encoding.UTF8));
|
|
|
+ }
|
|
|
+ catch (YamlException e)
|
|
|
+ {
|
|
|
+ Console.WriteLine($"Failed to read YAML file because {e.Message}: {e.InnerException?.Message}");
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ using var bw =
|
|
|
+ new BinaryWriter(File.Create(Path.Combine(Output, fileName)),
|
|
|
+ Encoding.UTF8);
|
|
|
+
|
|
|
+ data.Serialize(bw);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ private int MateToYaml(string file)
|
|
|
+ {
|
|
|
+ using var br = new BinaryReader(File.OpenRead(file), Encoding.UTF8);
|
|
|
+ var tag = br.ReadString();
|
|
|
+ if (tag != MATE_TAG)
|
|
|
+ {
|
|
|
+ Console.WriteLine("Provided file is not a valid MATE file!");
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ var mateFile = new MateFile
|
|
|
+ {
|
|
|
+ Version = br.ReadInt32(),
|
|
|
+ Path = br.ReadString(),
|
|
|
+ Name = br.ReadString(),
|
|
|
+ ShaderName = br.ReadString(),
|
|
|
+ DefMaterial = br.ReadString(),
|
|
|
+ ShaderProperties = new List<ShaderVariable>()
|
|
|
+ };
|
|
|
+
|
|
|
+ while (true)
|
|
|
+ {
|
|
|
+ var prop = br.ReadString();
|
|
|
+
|
|
|
+ if (prop == "end")
|
|
|
+ {
|
|
|
+ mateFile.ShaderProperties.Add(new EndTag());
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ var paramName = br.ReadString();
|
|
|
+ ShaderVariable sVar;
|
|
|
+ switch (prop)
|
|
|
+ {
|
|
|
+ case "tex":
|
|
|
+ var texType = br.ReadString();
|
|
|
+ sVar = texType switch
|
|
|
+ {
|
|
|
+ "null" => new TexNullVar(),
|
|
|
+ "tex2d" => new Tex2DVar
|
|
|
+ {
|
|
|
+ TextureName = br.ReadString(),
|
|
|
+ Path = br.ReadString(),
|
|
|
+ Offset = new Vec2
|
|
|
+ {
|
|
|
+ X = br.ReadSingle(),
|
|
|
+ Y = br.ReadSingle()
|
|
|
+ },
|
|
|
+ Scale = new Vec2
|
|
|
+ {
|
|
|
+ X = br.ReadSingle(),
|
|
|
+ Y = br.ReadSingle()
|
|
|
+ }
|
|
|
+ },
|
|
|
+ "texRT" => new TexRTVar
|
|
|
+ {
|
|
|
+ TextureName = br.ReadString(),
|
|
|
+ Path = br.ReadString()
|
|
|
+ },
|
|
|
+ _ => throw new Exception($"Invalid prop {texType} in file {file}")
|
|
|
+ };
|
|
|
+ break;
|
|
|
+ case "col":
|
|
|
+ sVar = new ColVar
|
|
|
+ {
|
|
|
+ Red = br.ReadSingle(),
|
|
|
+ Green = br.ReadSingle(),
|
|
|
+ Blue = br.ReadSingle(),
|
|
|
+ Alpha = br.ReadSingle()
|
|
|
+ };
|
|
|
+ break;
|
|
|
+ case "vec":
|
|
|
+ sVar = new Vec4Var
|
|
|
+ {
|
|
|
+ X = br.ReadSingle(),
|
|
|
+ Y = br.ReadSingle(),
|
|
|
+ Z = br.ReadSingle(),
|
|
|
+ W = br.ReadSingle()
|
|
|
+ };
|
|
|
+ break;
|
|
|
+ case "f":
|
|
|
+ sVar = new FloatVar
|
|
|
+ {
|
|
|
+ Value = br.ReadSingle()
|
|
|
+ };
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ Console.WriteLine($"Invalid prop {prop} in file {file}");
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ sVar.ShaderProperty = paramName;
|
|
|
+ mateFile.ShaderProperties.Add(sVar);
|
|
|
+ }
|
|
|
+
|
|
|
+ var sb = new SerializerBuilder();
|
|
|
+ sb.ConfigureDefaultValuesHandling(DefaultValuesHandling.OmitNull);
|
|
|
+ foreach (var kv in mappingTypes)
|
|
|
+ sb.WithTagMapping(kv.Key, kv.Value);
|
|
|
+ var serializer = sb.Build();
|
|
|
+
|
|
|
+ var yaml = serializer.Serialize(mateFile);
|
|
|
+ File.WriteAllText(Path.Combine(Output, $"{Path.GetFileName(file)}.yaml"), yaml);
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ [AttributeUsage(AttributeTargets.Class, Inherited = false)]
|
|
|
+ private class TagAttribute : Attribute
|
|
|
+ {
|
|
|
+ public TagAttribute(string Tag)
|
|
|
+ {
|
|
|
+ this.Tag = Tag;
|
|
|
+ }
|
|
|
+
|
|
|
+ public string Tag { get; }
|
|
|
+
|
|
|
+ public bool WriteShaderProp { get; set; } = true;
|
|
|
+ }
|
|
|
+
|
|
|
+ private class ShaderVariable
|
|
|
+ {
|
|
|
+ [YamlMember(Alias = "property")] public string ShaderProperty { get; set; }
|
|
|
+
|
|
|
+ public virtual void Serialize(BinaryWriter bw)
|
|
|
+ {
|
|
|
+ var tagAttribute = GetType().GetCustomAttributes(typeof(TagAttribute), true).Cast<TagAttribute>()
|
|
|
+ .FirstOrDefault();
|
|
|
+
|
|
|
+ if (tagAttribute == null)
|
|
|
+ return;
|
|
|
+
|
|
|
+ bw.Write(tagAttribute.Tag);
|
|
|
+
|
|
|
+ if (tagAttribute.WriteShaderProp)
|
|
|
+ bw.Write(ShaderProperty);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ [Tag("end", WriteShaderProp = false)]
|
|
|
+ private class EndTag : ShaderVariable
|
|
|
+ {
|
|
|
+ }
|
|
|
+
|
|
|
+ private class TexVar : ShaderVariable
|
|
|
+ {
|
|
|
+ public override void Serialize(BinaryWriter bw)
|
|
|
+ {
|
|
|
+ var tagAttribute = GetType().GetCustomAttributes(typeof(TagAttribute), true).Cast<TagAttribute>()
|
|
|
+ .FirstOrDefault();
|
|
|
+ if (tagAttribute == null)
|
|
|
+ return;
|
|
|
+
|
|
|
+ bw.Write("tex");
|
|
|
+ bw.Write(ShaderProperty);
|
|
|
+ bw.Write(tagAttribute.Tag);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ [Tag("tex_null")]
|
|
|
+ private class TexNullVar : TexVar
|
|
|
+ {
|
|
|
+ public override void Serialize(BinaryWriter bw)
|
|
|
+ {
|
|
|
+ bw.Write("tex");
|
|
|
+ bw.Write(ShaderProperty);
|
|
|
+ bw.Write("null");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ [Tag("tex2d")]
|
|
|
+ private class Tex2DVar : TexVar
|
|
|
+ {
|
|
|
+ [YamlMember(Alias = "texname")] public string TextureName { get; set; }
|
|
|
+
|
|
|
+ [YamlMember(Alias = "path")] public string Path { get; set; }
|
|
|
+
|
|
|
+ [YamlMember(Alias = "offset")] public Vec2 Offset { get; set; }
|
|
|
+
|
|
|
+ [YamlMember(Alias = "scale")] public Vec2 Scale { get; set; }
|
|
|
+
|
|
|
+ public override void Serialize(BinaryWriter bw)
|
|
|
+ {
|
|
|
+ base.Serialize(bw);
|
|
|
+ bw.Write(TextureName);
|
|
|
+ bw.Write(Path);
|
|
|
+ bw.Write(Offset.X);
|
|
|
+ bw.Write(Offset.Y);
|
|
|
+ bw.Write(Scale.X);
|
|
|
+ bw.Write(Scale.Y);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ [Tag("texRT")]
|
|
|
+ private class TexRTVar : TexVar
|
|
|
+ {
|
|
|
+ [YamlMember(Alias = "texname")] public string TextureName { get; set; }
|
|
|
+
|
|
|
+ [YamlMember(Alias = "path")] public string Path { get; set; }
|
|
|
+
|
|
|
+ public override void Serialize(BinaryWriter bw)
|
|
|
+ {
|
|
|
+ base.Serialize(bw);
|
|
|
+ bw.Write(Path);
|
|
|
+ bw.Write(TextureName);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ [Tag("col")]
|
|
|
+ private class ColVar : ShaderVariable
|
|
|
+ {
|
|
|
+ [YamlMember(Alias = "r")] public float Red { get; set; }
|
|
|
+
|
|
|
+ [YamlMember(Alias = "g")] public float Green { get; set; }
|
|
|
+
|
|
|
+ [YamlMember(Alias = "b")] public float Blue { get; set; }
|
|
|
+
|
|
|
+ [YamlMember(Alias = "a")] public float Alpha { get; set; }
|
|
|
+
|
|
|
+ public override void Serialize(BinaryWriter bw)
|
|
|
+ {
|
|
|
+ base.Serialize(bw);
|
|
|
+ bw.Write(Red);
|
|
|
+ bw.Write(Green);
|
|
|
+ bw.Write(Blue);
|
|
|
+ bw.Write(Alpha);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ [Tag("vec")]
|
|
|
+ private class Vec4Var : ShaderVariable
|
|
|
+ {
|
|
|
+ [YamlMember(Alias = "x")] public float X { get; set; }
|
|
|
+
|
|
|
+ [YamlMember(Alias = "y")] public float Y { get; set; }
|
|
|
+
|
|
|
+ [YamlMember(Alias = "z")] public float Z { get; set; }
|
|
|
+
|
|
|
+ [YamlMember(Alias = "w")] public float W { get; set; }
|
|
|
+
|
|
|
+ public override void Serialize(BinaryWriter bw)
|
|
|
+ {
|
|
|
+ base.Serialize(bw);
|
|
|
+ bw.Write(X);
|
|
|
+ bw.Write(Y);
|
|
|
+ bw.Write(Z);
|
|
|
+ bw.Write(W);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ [Tag("f")]
|
|
|
+ private class FloatVar : ShaderVariable
|
|
|
+ {
|
|
|
+ [YamlMember(Alias = "value")] public float Value { get; set; }
|
|
|
+
|
|
|
+ public override void Serialize(BinaryWriter bw)
|
|
|
+ {
|
|
|
+ base.Serialize(bw);
|
|
|
+ bw.Write(Value);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private class Vec2
|
|
|
+ {
|
|
|
+ [YamlMember(Alias = "x")] public float X { get; set; }
|
|
|
+
|
|
|
+ [YamlMember(Alias = "y")] public float Y { get; set; }
|
|
|
+ }
|
|
|
+
|
|
|
+ private class MateFile
|
|
|
+ {
|
|
|
+ [YamlMember(Alias = "version")] public int Version { get; set; }
|
|
|
+
|
|
|
+ [YamlMember(Alias = "path")] public string Path { get; set; }
|
|
|
+
|
|
|
+ [YamlMember(Alias = "name")] public string Name { get; set; }
|
|
|
+
|
|
|
+ [YamlMember(Alias = "shader")] public string ShaderName { get; set; }
|
|
|
+
|
|
|
+ [YamlMember(Alias = "def_material")] public string DefMaterial { get; set; }
|
|
|
+
|
|
|
+ [YamlMember(Alias = "shader_props")] public List<ShaderVariable> ShaderProperties { get; set; }
|
|
|
+
|
|
|
+ public void Serialize(BinaryWriter bw)
|
|
|
+ {
|
|
|
+ bw.Write(MATE_TAG);
|
|
|
+ bw.Write(Version);
|
|
|
+ bw.Write(Path);
|
|
|
+ bw.Write(Name);
|
|
|
+ bw.Write(ShaderName);
|
|
|
+ bw.Write(DefMaterial);
|
|
|
+
|
|
|
+ foreach (var shaderProperty in ShaderProperties)
|
|
|
+ shaderProperty.Serialize(bw);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|