public static ShaderPropertyAttrebute ParseToAttrebute(string line) { var result = new ShaderPropertyAttrebute(); var matches = AttrebutesRegex.Matches(line).Cast <Match>().Select(x => x.Value); var enumerable = matches as string[] ?? matches.ToArray(); result.HasHideInInspector = enumerable.Any(x => x.ToLower().Contains("hideininspector")); result.HasNoScaleOffset = enumerable.Any(x => x.ToLower().Contains("noscaleoffset")); result.HasNormal = enumerable.Any(x => x.ToLower().Contains("normal")); result.HasHDR = enumerable.Any(x => x.ToLower().Contains("hdr")); result.HasGamma = enumerable.Any(x => x.ToLower().Contains("gamma")); result.HasPerRendererData = enumerable.Any(x => x.ToLower().Contains("perrenderdata")); result.HasToggle = enumerable.Any(x => x.ToLower().Contains("toggle")); result.HasEnum = enumerable.Any(x => x.ToLower().Contains("enum")); result.HasPowerSlider = enumerable.Any(x => x.ToLower().Contains("powerslider")); result.HasHeader = enumerable.Any(x => x.ToLower().Contains("header")); if (result.HasHeader) { var headerAtter = enumerable.First(x => x.ToLower().Contains("header")); result.Header = HeaderRegex.Match(headerAtter).Value; } line = AttrebutesRegex.Replace(line, string.Empty); var content = ContentRegex.Match(line).Value.Split(','); result.IsTexture = content.Any(x => x.Contains("2D") || x.Contains("Cube") || x.Contains("3D")); var names = NamesRegex.Matches(line) .Cast <Match>() .Select(x => x.Groups.Cast <Group>()) .SelectMany(x => x) .Skip(1); var groups = names as Group[] ?? names.ToArray(); if (!groups.Any()) { return(result); } result.Name = groups.FirstOrDefault().Value.Trim(); result.DisplayName = groups.LastOrDefault().Value.Trim(); return(result); }
private void Generate() { var file = File.ReadAllText(Application.dataPath.Replace("Assets", string.Empty) + AssetDatabase.GetAssetPath(shaderFile)); var regex = new Regex("(?<=(properties)).*?(?=(subshader))", RegexOptions.Singleline | RegexOptions.IgnoreCase); var match = regex.Match(file).Value; if (string.IsNullOrEmpty(match)) { return; } var lines = match .Split(new string[] { "\r\n", "\n" }, StringSplitOptions.None) .Select(x => x.Trim().Trim('\t')) .Where(x => !string.IsNullOrEmpty(x) && !x.StartsWith("/") && x.Length > 4); var attrebutes = new List <ShaderPropertyAttrebute>(); var attrebuteTemp = new List <ShaderPropertyAttrebute>(); foreach (var line in lines) { var attrebute = ShaderPropertyAttrebute.ParseToAttrebute(line); if (string.IsNullOrEmpty(attrebute.Name)) { attrebuteTemp.Add(attrebute); } else { attrebuteTemp.Select(x => { return(x.GetType().GetProperties() .Where(y => !y.Name.Contains("Name")) .Select(y => { var value = y.GetValue(x, null); if (Equals(value, null) || Equals(value, false)) { return y; } attrebute.GetType().GetProperties().First(z => z.Name == y.Name).SetValue(attrebute, value, null); return y; }) .ToList()); }) .ToList(); attrebutes.Add(attrebute); attrebuteTemp.Clear(); } } var predicate = new Func <ShaderPropertyAttrebute, bool>(x => !x.HasHideInInspector && !x.HasPerRendererData); var maxVariableLength = attrebutes .Where(predicate) .Max(x => x.Name.Length); var fields = attrebutes .Where(predicate) .Select(x => { var camelVariable = x.Name.ToCamelCase(); return(string.Format ( "private string {0}{1}= \"_{2}\"; ", camelVariable, "".AppendIndent(maxVariableLength - camelVariable.Length), x.Name ).AppendIndent(4)); }).ToList(); var foldFields = attrebutes .Where(x => x.HasHeader) .Select(x => string.Format("private bool {0}Fold = false;", x.Name.ToCamelCase()).AppendIndent(4)) .ToList(); var headers = attrebutes.Where(x => x.HasHeader).Select(x => x.Header); var toggleFields = attrebutes .Where(x => x.Name.ToLower().Contains("use") && headers.Any(y => y.ToLower().Contains(x.Name.ToLower().Replace("use", string.Empty)))) .Select(x => { var camelVariable = x.Name.ToCamelCase(); return(new { Field = string.Format("private bool {0}Toggle = true;", camelVariable).AppendIndent(4), Variable = string.Format("{0}Toggle", camelVariable), PropertyName = x.Name }); }) .ToList(); fields.AddRange(foldFields); fields.AddRange(toggleFields.Select(x => x.Field)); var template = File.ReadAllText(Application.dataPath.Replace("Assets", string.Empty) + AssetDatabase.GetAssetPath(templateFile)); var fieldsArray = fields.ToArray(); template = template.Replace("<#fields#>", string.Join(Environment.NewLine, fieldsArray)); var inFold = false; var propertyFoldGroup = string.Empty; var properties = new List <string>(); var attrebuteProps = attrebutes .Where(predicate) .Select(x => { var camelVariable = x.Name.ToCamelCase(); return(new { Attrebute = x, FindProperty = string.Format ( "var {0}Prop {1}= FindProperty(this.{0}, properties);", camelVariable, "".AppendIndent(maxVariableLength - camelVariable.Length) ).AppendIndent(8), PropertyVariable = string.Format("{0}Prop", camelVariable) }); }) .ToList(); var findProps = string.Join(Environment.NewLine, attrebuteProps.Select(x => x.FindProperty).ToArray()); template = template.Replace("<#findProps#>", findProps); var setKeywords = toggleFields .Select(x => string.Format("UiUtils.SetKeyword({0}Prop, this.{1});", x.PropertyName.ToCamelCase(), x.Variable).AppendIndent(12)) .ToArray(); template = template.Replace("<#setKeywords#>", string.Join(Environment.NewLine, setKeywords)); var initializeToggles = toggleFields .Select(x => string.Format("this.{0} = {1}Prop.floatValue > 0;", x.Variable, x.PropertyName.ToCamelCase()).AppendIndent(16)) .ToArray(); template = template.Replace("<#initialToggle#>", string.Join(Environment.NewLine, initializeToggles)); foreach (var toggleField in toggleFields) { attrebuteProps.RemoveAll(x => x.Attrebute.Name.Contains(toggleField.PropertyName)); } foreach (var attrebute in attrebuteProps) { if (attrebute.Attrebute.HasHeader) { if (inFold) { propertyFoldGroup += string.Format("}});{0}{0}", Environment.NewLine).AppendIndent(12); } var toggle = toggleFields.FirstOrDefault(x => attrebute.Attrebute.Header.ToLower().Contains(x.PropertyName.ToLower().Replace("use", string.Empty))); if (toggle == null) { propertyFoldGroup += string.Format ( "UiUtils.PropertyFoldGroup(\"{0}\", ref this.{1}Fold, () => {2}", attrebute.Attrebute.Header, attrebute.Attrebute.Name.ToCamelCase(), Environment.NewLine ).AppendIndent(12); } else { propertyFoldGroup += string.Format ( "UiUtils.PropertyToggleFoldGroup(\"{0}\", ref this.{1}Fold, ref this.{2}, () => {3}", attrebute.Attrebute.Header, attrebute.Attrebute.Name.ToCamelCase(), toggle.Variable, Environment.NewLine ).AppendIndent(12); } propertyFoldGroup += string.Format("{{{0}", Environment.NewLine).AppendIndent(12); inFold = true; } if (attrebute.Attrebute.HasNoScaleOffset) { propertyFoldGroup += string.Format ( "materialEditor.TexturePropertySingleLine(new GUIContent(\"{0}\"), {1}); ", attrebute.Attrebute.DisplayName, attrebute.PropertyVariable ).AppendIndent(16) + Environment.NewLine; } else if (attrebute.Attrebute.IsTexture) { propertyFoldGroup += string.Format ( "materialEditor.ShaderProperty({0}, \"{1}\");", attrebute.PropertyVariable, attrebute.Attrebute.DisplayName ).AppendIndent(16) + Environment.NewLine; } else { propertyFoldGroup += string.Format ( "materialEditor.ShaderProperty({0}, \"{1}\");", attrebute.PropertyVariable, attrebute.Attrebute.DisplayName ).AppendIndent(16) + Environment.NewLine; } } if (inFold) { propertyFoldGroup += string.Format("}});{0}{0}", Environment.NewLine).AppendIndent(12); } template = template.Replace("<#propGroup#>", propertyFoldGroup); template = template.Replace("<#=generatorName#>", "ShaderPropertyGenerator"); template = template.Replace("<#=dateTimeNow#>", DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss")); template = template.Replace("<#=className#>", className.ToPascalCase()); template = template.Replace("<#=guid#>", AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(shaderFile))); Directory.CreateDirectory(Application.dataPath.Replace("Assets", string.Empty) + "/Editor/"); File.WriteAllText(Application.dataPath + "/Editor/" + className.ToPascalCase() + ".cs", template); AssetDatabase.Refresh(); }