protected override bool OnInitProperties(MaterialProperty[] props) { if (m_tags != null) { return(true); } m_show = true; m_tags = new List <TagDefine>(); // 从编辑器数据中获取用户自定义Tag var tags = m_args.GetField(Cfg.ArgsKey_CustomTag_Tags); if (tags != null && tags.IsArray && tags.list.Count > 0) { for (int i = 0; i < tags.list.Count; ++i) { var tagDef = tags.list[i]; if (tagDef.IsObject) { String type; if (tagDef.GetField(out type, Cfg.ArgsKey_CustomTag_Type, String.Empty)) { type = type.Trim(); var values = tagDef.GetField(Cfg.ArgsKey_CustomTag_Values); if (values != null && values.IsArray && values.Count > 0) { if (m_tags.Find(item => item.typename == type) != null) { Debug.LogErrorFormat("Tag {0} already exists.", type); continue; } var tagdef = new TagDefine(); tagdef.typename = type; tagDef.GetField(out tagdef.readOnly, Cfg.ArgsKey_CustomTag_Readonly, false); var _values = new List <String>(values.Count); for (int n = 0; n < values.Count; ++n) { var v = values[n]; var value = String.Empty; if (v.IsString && !String.IsNullOrEmpty(v.str) && !_values.Contains(value = v.str.Trim())) { _values.Add(value); } } // 一个定义需要升级到另外一个Tag var op = UpgradeOPType.None; var target = String.Empty; if (tagDef.GetField(out target, Cfg.ArgsKey_CustomTag_UpgradeTo, String.Empty)) { op = UpgradeOPType.Cut; } else if (tagDef.GetField(out target, Cfg.ArgsKey_CustomTag_CopyTo, String.Empty)) { op = UpgradeOPType.Copy; } target = target.Trim(); if (!String.IsNullOrEmpty(target)) { tagdef.upgradeOPType = op; tagdef.upgradeTypename = target; // 找到升级目标Tag定义 var targetTypeDef = m_tags.Find(item => item.typename == tagdef.upgradeTypename); if (targetTypeDef != null) { // 保存别名 targetTypeDef.alias = targetTypeDef.alias ?? new HashSet <String>(); targetTypeDef.alias.Add(tagdef.upgradeTypename); if (targetTypeDef.values != null) { // 把选项合并 _values.AddRange(targetTypeDef.values); } } else { Debug.LogErrorFormat("upgrade type from '{0}' to '{1}' not found.", type, tagdef.upgradeTypename); } // 测试需要升级的当前tag是否可以被删除 var material = m_MaterialEditor.target as Material; if (material != null) { var removeAble = ShaderGUIHelper.IsTagRemoveable(material, type); if (removeAble != null) { tagdef.removeAble = removeAble.Value; } } } if (_values.Count > 0) { var keepValue = tagDef.GetField(Cfg.Key_FixedValue); if (keepValue != null && keepValue.IsString) { tagdef.keep = keepValue.str.Trim(); if (!String.IsNullOrEmpty(tagdef.keep)) { if (!_values.Contains(tagdef.keep)) { Debug.LogErrorFormat("Tag value '{0}' is not defined.", tagdef.keep); } else { tagdef.readOnly = true; } } } // 去重后转换为数组 tagdef.values = _values.Distinct().ToArray(); m_tags = m_tags ?? new List <TagDefine>(); m_tags.Add(tagdef); } } } } } } // 从当前材质中获取已有的系统Tag var materials = m_MaterialEditor.targets.Where(e => e is Material).Cast <Material>().ToArray(); for (int m = 0; m < materials.Length; ++m) { var mat = materials[m]; if (mat == null) { continue; } for (int i = 0; i < BuiltinTags.Length; ++i) { var typename = BuiltinTags[i]; var value = mat.GetTag(typename, true); if (!String.IsNullOrEmpty(value)) { m_tags = m_tags ?? new List <TagDefine>(); var defIndex = m_tags.FindIndex(item => item.typename == typename); TagDefine def; if (defIndex >= 0) { def = m_tags[defIndex]; // 定义了系统Tag,把系统tag当前值追加进选项 if (def.values != null) { var _values = new List <String>(def.values); if (!_values.Contains(value)) { _values.Add(value); def.values = _values.ToArray(); } } else { // 编辑器中没有定义选项,此选项只读,唯一选项 def.values = new String[] { value }; def.readOnly = true; } if (defIndex > 0) { // 交换到前面去 var t = m_tags[0]; m_tags[0] = def; m_tags[defIndex] = t; } } else { // 编辑器没有定义,只读唯一选项 def = new TagDefine(); def.typename = typename; def.readOnly = true; def.values = new String[] { value }; m_tags.Insert(0, def); } def.builtin = true; } } } // 设置固定不变值 for (int i = 0; i < m_tags.Count; ++i) { var tagdef = m_tags[i]; if (!String.IsNullOrEmpty(tagdef.keep)) { if (tagdef.values != null) { if (Array.IndexOf(tagdef.values, tagdef.keep) >= 0) { for (int j = 0; j < materials.Length; ++j) { _SetOverrideTag(materials[j], tagdef.typename, tagdef.keep, true); } } } } } DoUpgrade(); return(true); }
void UpgradeTag(Material mat, TagDefine tagdef, TagDefine upgradeType) { if (tagdef.upgradeOPType == UpgradeOPType.None) { return; } tagdef.upgradeState = tagdef.upgradeState ?? new Dictionary <Material, UpgradeOPType>(); UpgradeOPType state; if (tagdef.upgradeState.TryGetValue(mat, out state) && state == UpgradeOPType.None) { return; } var typename = tagdef.typename; String oldVal; if (tagdef.upgradeOPType == UpgradeOPType.Cut) { var r = _RemoveOverrideTag(mat, typename, out oldVal); if (r != null && r.Value == false) { // shader自定义的tag删除不掉,只有通过设置一个表示None的有效字段覆盖 tagdef.removeAble = false; // 搜索升级类型选项 if (upgradeType.values != null) { // 选择一个表示空的选项,用于覆盖Shader默认Tag var newValue = "None"; var noneIndex = Array.FindIndex( upgradeType.values, s => s.Equals("None", StringComparison.OrdinalIgnoreCase)); if (noneIndex >= 0) { newValue = upgradeType.values[noneIndex]; } else { // 追加表示空的选项,用于覆盖默认值 var temp = new List <String>(); temp.Add(newValue); if (upgradeType.values != null) { temp.AddRange(upgradeType.values); } upgradeType.values = temp.ToArray(); } if (_SetOverrideTag(mat, typename, upgradeType.values[0], false, true)) { Debug.LogFormat("Upgrade tag '{0}' -> '{1}', cmd = {2}", typename, tagdef.upgradeTypename, tagdef.upgradeOPType); } } } } else { if (mat != null) { oldVal = mat.GetTag(typename, true); } else { oldVal = String.Empty; } } if (!String.IsNullOrEmpty(oldVal) && upgradeType.values != null && !oldVal.Equals("None", StringComparison.OrdinalIgnoreCase)) { // 把原有值写入升级后的类型中去 if (IsOptionNone(oldVal)) { // 找到目标选项中对应的空值 var noneIndex = Array.FindIndex(upgradeType.values, item => IsOptionNone(item)); if (noneIndex >= 0) { // 修正空值,保证选项中包含 oldVal = upgradeType.values[noneIndex]; } } if (Array.IndexOf(upgradeType.values, oldVal) >= 0) { // 把旧值存到新Tag类型中去 if (_SetOverrideTag(mat, upgradeType.typename, oldVal, true, false)) { Debug.LogFormat("Upgrade tag '{0}' -> '{1}', cmd = {2}", typename, tagdef.upgradeTypename, tagdef.upgradeOPType); } } } tagdef.upgradeState[mat] = UpgradeOPType.None; }