|  | @@ -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;
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +                
 | 
	
		
			
				|  |  | +                // 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);
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +}
 |