123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372 |
- 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;
- }
-
- // TODO: Clean up
- 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);
- }
- }
- }
- }
|