using System; using System.Collections.Generic; using System.Text.RegularExpressions; using UnityEditor; using UnityEngine; using UnityEngine.Rendering; namespace AllIn13DShader { [System.Serializable] public class PropertiesConfig { public Shader shader; public EffectGroup[] effectsGroups; public List singleProperties; public List advancedProperties; public int renderPreset; public int blendSrcIdx; public int blendDstIdx; public int zWriteIndex; public void CreateConfig(EffectGroupGlobalConfigCollection effectGroupGlobalConfigCollection, EffectsExtraData effectsExtraData) { effectsGroups = new EffectGroup[0]; singleProperties = new List(); advancedProperties = new List(); CreateGroups(effectGroupGlobalConfigCollection); int numProperties = shader.GetPropertyCount(); int effectIndex = 0; for (int i = 0; i < numProperties; i++) { string[] attributes = shader.GetPropertyAttributes(i); string displayName = shader.GetPropertyDescription(i); string propertyName = shader.GetPropertyName(i); ShaderPropertyFlags shaderPropertyFlags = shader.GetPropertyFlags(i); ShaderPropertyType shaderPropertyType = shader.GetPropertyType(i); if (propertyName == Constants.MATPROPERTY_RENDERING_MODE) { this.renderPreset = i; } else { if (attributes.Length > 0) { int idxOffset = 0; string firstAttribute = attributes[0]; string secondAttribute = string.Empty; if(attributes.Length >= 2) { secondAttribute = attributes[1]; } if (firstAttribute.Contains(Constants.EFFECT_ATTRIBUTE_PREFIX)) { ConfigureEffect(displayName, i, propertyName, firstAttribute, attributes[idxOffset + 1], effectsExtraData, effectIndex + 1); } else if (firstAttribute.StartsWith(Constants.EFFECT_PROPERTY_ATTRIBUTE_PREFIX)) { EffectPropertyAttributeData effectPropertyAttributeData = GetEffectPropertyAttributeData(firstAttribute, secondAttribute); ConfigureProperty(effectPropertyAttributeData, i, propertyName, displayName, shaderPropertyType, shaderPropertyFlags); } else if (firstAttribute.Contains(Constants.SINGLE_PROPERTY_ATTRIBUTE)) { singleProperties.Add(i); } else if (firstAttribute.Contains(Constants.ADVANCED_PROPERTY_ATTRIBUTE)) { advancedProperties.Add(i); } } } if (propertyName == Constants.MATPROPERTY_BLEND_SRC) { this.blendSrcIdx = i; } else if (propertyName == Constants.MATPROPERTY_BLEND_DST) { this.blendDstIdx = i; } } RefreshDisplayIndices(); zWriteIndex = FindPropertyIndex("_ZWrite"); } private void RefreshDisplayIndices() { int effectDisplayIndex = 0; for (int i = 0; i < effectsGroups.Length; i++) { for (int j = 0; j < effectsGroups[i].effects.Length; j++) { effectsGroups[i].effects[j].displayIndex = effectDisplayIndex + 1; effectDisplayIndex++; } } } private void CreateGroups(EffectGroupGlobalConfigCollection effectGroupGlobalConfigCollection) { for (int i = 0; i < effectGroupGlobalConfigCollection.effectGroupGlobalConfigs.Length; i++) { EffectGroupGlobalConfig effectGroupGlobalConfig = effectGroupGlobalConfigCollection.effectGroupGlobalConfigs[i]; //string groupID = Constants.EFFECTS_GROUPS_IDS[i]; EffectGroup group = new EffectGroup(effectGroupGlobalConfig); ArrayUtility.Add(ref effectsGroups, group); } } private EffectPropertyAttributeData GetEffectPropertyAttributeData(string attribute, string secondAttribute) { EffectPropertyAttributeData res = new EffectPropertyAttributeData(); MatchCollection matchCollection = Regex.Matches(attribute, Constants.REGEX_EFFECT_PROOPERTY_COMPLETE); if (matchCollection != null && matchCollection.Count > 0) { res.parentEffectID = matchCollection[0].Groups[1].Value; string[] keywordListSplit = matchCollection[0].Groups[4].Value.Split(","); for(int i = 0; i < keywordListSplit.Length; i++) { string kw = keywordListSplit[i].Trim(); res.AddKeyword(kw); } string[] incompatibleKwsSplit = matchCollection[0].Groups[3].Value.Split(","); for(int i = 0; i < incompatibleKwsSplit.Length; i++) { string incompatibleKw = incompatibleKwsSplit[i]; res.AddIncompatibleKeyword(incompatibleKw); } string strAllowReset = matchCollection[0].Groups[5].Value.ToUpperInvariant(); res.allowReset = strAllowReset == "TRUE"; string strKeywordsOp = matchCollection[0].Groups[2].Value.ToUpperInvariant(); if (!string.IsNullOrEmpty(strKeywordsOp)) { res.keywordsOp = strKeywordsOp == "AND" ? KeywordsOp.AND : KeywordsOp.OR; } } else { matchCollection = Regex.Matches(attribute, Constants.REGEX_EFFECT_PROPERTY); string[] contentSplit = matchCollection[0].Groups[1].Value.Split(","); string parentEffectID = contentSplit[0].Trim(); res.parentEffectID = parentEffectID; if (contentSplit.Length > 1) { for (int i = 1; i < contentSplit.Length; i++) { string kw = $"_{parentEffectID}_{contentSplit[i].Trim()}"; res.AddKeyword(kw); } } else { string kw = $"_{parentEffectID}_ON"; res.AddKeyword(kw); } } if (!string.IsNullOrEmpty(secondAttribute)) { matchCollection = Regex.Matches(secondAttribute, Constants.REGEX_KEYWORDS_ENUM); MatchCollection matchCollectionToggle = Regex.Matches(secondAttribute, Constants.REGEX_TOGGLE); if (matchCollection.Count >= 1) { string[] contentSplit = matchCollection[0].Groups[1].Value.Split(","); res.AddPropertyKeywords(contentSplit); } else if(matchCollectionToggle.Count >= 1) { res.AddPropertyKeyword(matchCollectionToggle[0].Groups[1].Value); } } return res; } private EffectKeywordData[] GetParentEffectKeywords(string attribute, string effectName) { MatchCollection matchCollection = Regex.Matches(attribute, Constants.REGEX_PARENT_EFFECT_KEYWORDS); string[] matchSplitted = matchCollection[0].Groups[1].Value.Split(","); EffectKeywordData[] res = new EffectKeywordData[matchSplitted.Length]; for (int i = 0; i < matchSplitted.Length; i++) { matchSplitted[i] = matchSplitted[i].Trim(); string displayName = matchSplitted[i]; string keyword = string.Empty; if(matchSplitted.Length == 1) { keyword = $"{matchSplitted[i].ToUpperInvariant()}"; } else { keyword = $"_{effectName}_{matchSplitted[i].ToUpperInvariant()}"; } res[i] = new EffectKeywordData(keyword, displayName); //matchSplitted[i] = matchSplitted[i].ToUpper(); } return res; } private EffectAttributeData GetEffectAttributeData(string rawAttribute) { EffectAttributeData res = new EffectAttributeData(); res.Init(); Match match = Regex.Match(rawAttribute, Constants.REGEX_EFFECT); res.effectID = match.Groups[1].Value.Trim(); res.groupID = match.Groups[2].Value.Trim(); res.dependentEffectID = match.Groups[4].Value.Trim(); res.incompatibleWithEffectID = match.Groups[5].Value.Trim(); res.docEnabled = match.Groups[6].Value.Trim().ToUpperInvariant() == "TRUE"; res.drawerID = match.Groups[7].Value.Trim(); string extraPassesRaw = match.Groups[8].Value.Trim(); if (!string.IsNullOrEmpty(extraPassesRaw)) { string[] extraPassesSplitted = extraPassesRaw.Split(",", System.StringSplitOptions.RemoveEmptyEntries); for(int i = 0; i < extraPassesSplitted.Length; i++) { ArrayUtility.Add(ref res.extraPasses, extraPassesSplitted[i].Trim()); } } if (string.IsNullOrEmpty(res.drawerID)) { res.drawerID = Constants.GENERAL_EFFECT_DRAWER_ID; } return res; } private void ConfigureEffect(string displayName, int propertyIndex, string propertyName, string rawEffectAttribute, string attributeKeywords, EffectsExtraData effectsExtraData, int displayIndex) { EffectAttributeData effectAttributeData = GetEffectAttributeData(rawEffectAttribute); string effectName = effectAttributeData.effectID; AllIn13DEffectConfig effectConfig = FindEffectConfigByID(effectAttributeData.effectID); EffectKeywordData[] keywordsDatas = GetParentEffectKeywords(attributeKeywords, effectName); EffectConfigType effectConfigType = keywordsDatas.Length == 1 ? EffectConfigType.EFFECT_TOGGLE : EffectConfigType.EFFECT_ENUM; if (effectConfig == null) { effectConfig = new AllIn13DEffectConfig(displayName, propertyName, propertyIndex, effectConfigType, effectAttributeData, effectsExtraData, displayIndex); effectConfig.AddKeywords(keywordsDatas); effectConfig.Setup(); EffectGroup effectGroup = GetEffecGroupByID(effectAttributeData.groupID); effectGroup.AddEffect(effectConfig); } } private EffectGroup GetEffecGroupByID(string groupID) { EffectGroup res = null; for (int i = 0; i < effectsGroups.Length; i++) { if (effectsGroups[i].GroupID == groupID) { res = effectsGroups[i]; break; } } return res; } //private void ConfigureProperty(string[] propertyContent, int propertyIndex, string propertyName) //{ // string effectID = propertyContent[0]; // List keywords = new List(); // if (propertyContent.Length > 1) // { // for (int i = 1; i < propertyContent.Length; i++) // { // string kw = $"_{effectID}_{propertyContent[i]}"; // keywords.Add(kw); // } // } // else // { // string kw = $"_{effectID}_ON"; // keywords.Add(kw); // } // ConfigureProperty(effectID, keywords, propertyIndex, propertyName); //} private void ConfigureProperty(EffectPropertyAttributeData data, int propertyIndex, string propertyName, string displayName, ShaderPropertyType shaderPropertyType, ShaderPropertyFlags shaderPropertyFlags) { AllIn13DEffectConfig effectConfig = FindEffectConfigByID(data.parentEffectID); EffectProperty effectProperty = effectConfig.CreateEffectProperty(propertyIndex, propertyName, displayName, shaderPropertyType, shaderPropertyFlags, data); } public AllIn13DEffectConfig FindEffectConfigByID(string effectID) { AllIn13DEffectConfig res = null; for (int groupIdx = 0; groupIdx < effectsGroups.Length; groupIdx++) { EffectGroup effectGroup = effectsGroups[groupIdx]; res = effectGroup.FindEffectByID(effectID); if (res != null) { break; } } return res; } public EffectProperty FindEffectProperty(string effectID, string propertyName) { AllIn13DEffectConfig effectConfig = FindEffectConfigByID(effectID); EffectProperty res = effectConfig.FindEffectPropertyByName(propertyName); return res; } public int FindPropertyIndex(string propertyName) { int res = shader.FindPropertyIndex(propertyName); return res; } //public EffectProperty FindGeneralEffectProperty(string propertyName) //{ // EffectProperty res = null; // for(int i = 0; i < singleProperties.Count; i++) // { // break; // } // return res; //} public List GetAllEffects() { List res = new List(); for (int groupIdx = 0; groupIdx < effectsGroups.Length; groupIdx++) { res.AddRange(effectsGroups[groupIdx].effects); } return res; } public EffectGroup FindEffectGroupByID(string groupID) { EffectGroup res = null; for(int i = 0; i < effectsGroups.Length; i++) { if (effectsGroups[i].GroupID == groupID) { res = effectsGroups[i]; break; } } return res; } public string[] GetEffectGroupsIDs() { string[] res = new string[effectsGroups.Length]; for(int i = 0; i < effectsGroups.Length; i++) { res[i] = effectsGroups[i].GroupID; } return res; } public string[] GetEffectGroupsDisplayNames() { string[] res = new string[effectsGroups.Length]; for(int i = 0; i < effectsGroups.Length; i++) { res[i] = effectsGroups[i].DisplayName; } return res; } public string[] GetGlobalPropertyNames() { string[] res = new string[singleProperties.Count]; for(int i = 0; i < singleProperties.Count; i++) { res[i] = shader.GetPropertyDescription(singleProperties[i]); } return res; } public string[] GetAdvancedPropertyNames() { string[] res = new string[advancedProperties.Count - 1]; for (int i = 1; i < advancedProperties.Count; i++) { res[i - 1] = shader.GetPropertyDescription(advancedProperties[i]); } return res; } } }