using System; using System.Collections.Generic; using System.Linq; using UniGLTF; using UnityEngine; using UniJSON; using UniGLTF.ShaderPropExporter; namespace VRM { [Serializable] public class glTF_VRM_Material : JsonSerializableBase { public string name; public string shader; public int renderQueue = -1; public Dictionary floatProperties = new Dictionary(); public Dictionary vectorProperties = new Dictionary(); public Dictionary textureProperties = new Dictionary(); public Dictionary keywordMap = new Dictionary(); public Dictionary tagMap = new Dictionary(); static readonly string[] TAGS = new string[]{ "RenderType", // "Queue", }; protected override void SerializeMembers(GLTFJsonFormatter f) { f.KeyValue(() => name); f.KeyValue(() => renderQueue); f.KeyValue(() => shader); { f.Key("floatProperties"); f.BeginMap(); foreach (var kv in floatProperties) { f.Key(kv.Key); f.Value(kv.Value); } f.EndMap(); } { f.Key("vectorProperties"); f.BeginMap(); foreach (var kv in vectorProperties) { f.Key(kv.Key); f.Value(kv.Value.ToArray()); } f.EndMap(); } { f.Key("textureProperties"); f.BeginMap(); foreach (var kv in textureProperties) { f.Key(kv.Key); f.Value(kv.Value); } f.EndMap(); } { f.Key("keywordMap"); f.BeginMap(); foreach (var kv in keywordMap) { f.Key(kv.Key); f.Value(kv.Value); } f.EndMap(); } { f.Key("tagMap"); f.BeginMap(); foreach (var kv in tagMap) { f.Key(kv.Key); f.Value(kv.Value); } f.EndMap(); } } public static List Parse(string src) { var json = UniJSON.JsonParser.Parse(src)["extensions"]["VRM"]["materialProperties"]; var materials = json.DeserializeList(); var jsonItems = json.ArrayItems.ToArray(); for (int i = 0; i < materials.Count; ++i) { materials[i].floatProperties = jsonItems[i]["floatProperties"].ObjectItems.ToDictionary(x => x.Key, x => x.Value.Value.GetSingle()); materials[i].vectorProperties = jsonItems[i]["vectorProperties"].ObjectItems.ToDictionary(x => x.Key, x => { return x.Value.ArrayItems.Select(y => y.Value.GetSingle()).ToArray(); }); materials[i].keywordMap = jsonItems[i]["keywordMap"].ObjectItems.ToDictionary(x => x.Key, x => x.Value.GetBoolean()); materials[i].tagMap = jsonItems[i]["tagMap"].ObjectItems.ToDictionary(x => x.Key, x => x.Value.GetString()); materials[i].textureProperties = jsonItems[i]["textureProperties"].ObjectItems.ToDictionary(x => x.Key, x => x.Value.GetInt32()); } return materials; } public static glTF_VRM_Material CreateFromMaterial(Material m, List textures) { var material = new glTF_VRM_Material { name = m.name, shader = m.shader.name, renderQueue = m.renderQueue, }; var prop = PreShaderPropExporter.GetPropsForSupportedShader(m.shader.name); if (prop == null) { Debug.LogWarningFormat("Fail to export shader: {0}", m.shader.name); } else { // get properties //material.SetProp(prop); foreach (var kv in prop.Properties) { switch (kv.ShaderPropertyType) { case ShaderPropertyType.Color: { var value = m.GetColor(kv.Key).ToArray(); material.vectorProperties.Add(kv.Key, value); } break; case ShaderPropertyType.Range: case ShaderPropertyType.Float: { var value = m.GetFloat(kv.Key); material.floatProperties.Add(kv.Key, value); } break; case ShaderPropertyType.TexEnv: { var texture = m.GetTexture(kv.Key); if (texture != null) { var value = textures.IndexOf(texture); if (value == -1) { Debug.LogFormat("not found {0}", texture.name); } else { material.textureProperties.Add(kv.Key, value); } } // offset & scaling var offset = m.GetTextureOffset(kv.Key); var scaling = m.GetTextureScale(kv.Key); material.vectorProperties.Add(kv.Key, new float[] { offset.x, offset.y, scaling.x, scaling.y }); } break; case ShaderPropertyType.Vector: { var value = m.GetVector(kv.Key).ToArray(); material.vectorProperties.Add(kv.Key, value); } break; default: throw new NotImplementedException(); } } } foreach (var keyword in m.shaderKeywords) { material.keywordMap.Add(keyword, m.IsKeywordEnabled(keyword)); } foreach (var tag in TAGS) { var value = m.GetTag(tag, false); if (!String.IsNullOrEmpty(value)) { material.tagMap.Add(tag, value); } } return material; } } }