예제 #1
0
            //Deserialize without knowing type
            public static object Deserialize(string data, object[] args = null)
            {
                //extract serialized class name
                var index = data.IndexOf('(');
                var serializedClassName = data.Substring(0, index);

                //fetch all serialized classes names, and try to match it
                Type type     = null;
                var  allTypes = typeof(Serialization).Assembly.GetTypes();

                foreach (var t in allTypes)
                {
                    var classAttributes = t.GetCustomAttributes(typeof(SerializeAsAttribute), false);
                    if (classAttributes != null && classAttributes.Length == 1)
                    {
                        var name = (classAttributes[0] as SerializeAsAttribute).serializedName;
                        if (name == serializedClassName)
                        {
                            //match!
                            type = t;
                        }
                    }
                }

                if (type == null)
                {
                    Debug.LogError(ShaderGenerator2.ErrorMsg("Can't find proper Type for serialized class named '<b>" + serializedClassName + "</b>'"));
                    return(null);
                }

                //return new object with correct type
                return(Deserialize(data, type, args));
            }
예제 #2
0
            string[] ArgumentLines(string[] array, Argument[] arguments, List <string> suppliedArguments)
            {
                if (arguments == null || arguments.Length == 0)
                {
                    return(array);
                }
                else
                {
                    if (suppliedArguments.Count != arguments.Length)
                    {
                        Debug.LogError(ShaderGenerator2.ErrorMsg(string.Format("[Module {4}] Invalid number of arguments provided: got <b>{0}</b>, expected <b>{1}</b>:\nExpected: {2}\nSupplied: {3}",
                                                                               suppliedArguments.Count,
                                                                               arguments.Length,
                                                                               string.Join(", ", System.Array.ConvertAll(arguments, a => a.ToString())),
                                                                               string.Join(", ", suppliedArguments.ToArray()),
                                                                               this.name)));
                    }

                    var list = new List <string>();
                    foreach (var line in array)
                    {
                        string lineWithArgs = line;
                        for (int i = 0; i < arguments.Length; i++)
                        {
                            lineWithArgs = System.Text.RegularExpressions.Regex.Replace(lineWithArgs, @"\b" + arguments[i].name + @"\b", suppliedArguments[i]);
                        }
                        list.Add(lineWithArgs);
                    }

                    return(list.ToArray());
                }
            }
예제 #3
0
            //Process the #KEYWORDS block for this config
            internal void ProcessKeywordsBlock(Config config, List <string> conditionalFeatures, List <string> tempFeatures, List <string> tempFlags)
            {
                var depth = -1;
                var stack = new List <bool>();
                var done  = new List <bool>();

                for (var i = 0; i < textLines.Length; i++)
                {
                    var line = textLines[i];

                    if (line.StartsWith("#KEYWORDS"))
                    {
                        int keywordsStartIndex = i + 1;

                        while (i < textLines.Length)
                        {
                            line = textLines[i];
                            i++;

                            if (line.StartsWith("#END"))
                            {
                                return;
                            }

                            //Conditions
                            if (line.Contains("///"))
                            {
                                var error = ExpressionParser.ProcessCondition(line, conditionalFeatures, ref depth, ref stack, ref done);
                                if (!string.IsNullOrEmpty(error))
                                {
                                    Debug.LogError(ShaderGenerator2.ErrorMsg(error));
                                }
                            }
                            //Regular line
                            else
                            {
                                //Process line if inside valid condition block
                                if ((depth >= 0 && stack[depth]) || depth < 0)
                                {
                                    if (config.ProcessKeywords(line, tempFeatures, tempFlags))
                                    {
                                        // add the new toggled features, if any
                                        foreach (var f in tempFeatures)
                                        {
                                            Utils.AddIfMissing(conditionalFeatures, f);
                                        }

                                        // reset the loop, so that the #keywords order doesn't matter in the template
                                        i = keywordsStartIndex;
                                        continue;
                                    }
                                }
                            }
                        }
                    }
                }
            }
예제 #4
0
            //Return the Fragment Lines with the arguments replaced with their proper names
            public string[] FragmentLines(List <string> arguments, string key = "")
            {
                Argument[] args;
                string[]   lines;
                FragmentsArgs.TryGetValue(key, out args);
                Fragments.TryGetValue(key, out lines);

                if (lines == null)
                {
                    Debug.LogError(ShaderGenerator2.ErrorMsg(string.Format("Can't find #FRAGMENT/#LIGHTING for Module '{0}{1}'", this.name, string.IsNullOrEmpty(key) ? "" : ":" + key)));
                    return(null);
                }

                return(ArgumentLines(lines, args, arguments));
            }
예제 #5
0
            //Process the #INPUT block: retrieve all necessary variables
            //for Input struct (surface shader) or v2f struct (vert/frag shader)
            internal string[] GetInputBlock(ParsedLine[] parsedLines, int pass)
            {
                var variablesList = new List <string>();
                int currentPass   = -1;

                for (var i = 0; i < parsedLines.Length; i++)
                {
                    var line = parsedLines[i].line;

                    if (line.StartsWith("#PASS"))
                    {
                        currentPass++;
                    }

                    if (line.StartsWith("#INPUT_VARIABLES") && currentPass == pass)
                    {
                        i++;
                        while (i < parsedLines.Length)
                        {
                            line = parsedLines[i].line;
                            i++;

                            if (line.StartsWith("#END"))
                            {
                                return(variablesList.ToArray());
                            }

                            if (line.StartsWith("#") || string.IsNullOrEmpty(line.Trim()))
                            {
                                continue;
                            }

                            //Conditions
                            if (line.Contains("///"))
                            {
                                Debug.LogError(ShaderGenerator2.ErrorMsg("GetInputBlock: template lines should already have been parsed and cleared of conditions"));
                            }
                            //Regular line
                            else
                            {
                                variablesList.Add(line.Trim());
                            }
                        }
                    }
                }

                return(null);
            }
예제 #6
0
            //--------

            private static TextAsset LoadTextAsset(string filename)
            {
                string rootPath = Utils.FindReadmePath(true);
                var    asset    = AssetDatabase.LoadAssetAtPath <TextAsset>(string.Format("{0}/Editor/Shader Templates/{1}", rootPath, filename));

                if (asset == null)
                {
                    var filenameNoExtension = Path.GetFileNameWithoutExtension(filename);
                    var guids = AssetDatabase.FindAssets(string.Format("{0} t:TextAsset", filenameNoExtension));
                    if (guids.Length >= 1)
                    {
                        var path = AssetDatabase.GUIDToAssetPath(guids[0]);
                        asset = AssetDatabase.LoadAssetAtPath(path, typeof(TextAsset)) as TextAsset;
                    }
                    else
                    {
                        Debug.LogError(ShaderGenerator2.ErrorMsg(string.Format("Can't find template using Unity's search system. Make sure that the file '{0}' is in the project!", filename)));
                    }
                }

                return(asset);
            }
예제 #7
0
            static public Module CreateFromName(string moduleName)
            {
                string moduleFile = string.Format("Module_{0}.txt", moduleName);
                string rootPath   = Utils.FindReadmePath(true);
                string modulePath = string.Format("{0}/Shader Templates 2/Modules/{1}", rootPath, moduleFile);

                var textAsset = AssetDatabase.LoadAssetAtPath <TextAsset>(modulePath);

                //Can't find through default path, try to search for the file using AssetDatabase
                if (textAsset == null)
                {
                    var matches = AssetDatabase.FindAssets(string.Format("Module_{0} t:textasset", moduleName));
                    if (matches.Length > 0)
                    {
                        // Get the first result
                        textAsset = AssetDatabase.LoadAssetAtPath <TextAsset>(AssetDatabase.GUIDToAssetPath(matches[0]));
                    }
                    else
                    {
                        Debug.LogError(ShaderGenerator2.ErrorMsg(string.Format("Can't find module using Unity's search system. Make sure that the file 'Module_{0}' is in the project!", moduleName)));
                    }
                }

                if (textAsset == null)
                {
                    Debug.LogError(ShaderGenerator2.ErrorMsg(string.Format("Can't load module: '{0}'", moduleName)));
                    return(null);
                }

                var lines = textAsset.text.Split(new string[] { "\r\n", "\n" }, System.StringSplitOptions.None);

                List <string> features            = new List <string>();
                List <string> propertiesNew       = new List <string>();
                List <string> keywords            = new List <string>();
                List <string> shaderFeaturesBlock = new List <string>();
                List <string> propertiesBlock     = new List <string>();
                List <string> variables           = new List <string>();
                List <string> functions           = new List <string>();
                List <string> inputStruct         = new List <string>();
                bool          explicitFunctions   = false;

                Dictionary <string, List <Argument> > verticesArgs  = new Dictionary <string, List <Argument> >();
                Dictionary <string, List <Argument> > fragmentsArgs = new Dictionary <string, List <Argument> >();
                Dictionary <string, List <string> >   vertices      = new Dictionary <string, List <string> >();
                Dictionary <string, List <string> >   fragments     = new Dictionary <string, List <string> >();

                Dictionary <string, List <string> > arbitraryBlocks = new Dictionary <string, List <string> >();

                List <string> currentList = null;

                foreach (var line in lines)
                {
                    if (line.StartsWith("#") && !line.Contains("_IMPL"))
                    {
                        var lineTrim = line.Trim();

                        //fragment can have arguments, so check the start of the line instead of exact word
                        if (lineTrim.StartsWith("#VERTEX"))
                        {
                            var key = "";
                            if (lineTrim.Contains(":"))
                            {
                                int start = "#VERTEX:".Length;
                                int end   = lineTrim.IndexOf('(');
                                key = lineTrim.Substring(start, end - start);
                            }

                            currentList = new List <string>();
                            vertices.Add(key, currentList);

                            if (lineTrim.Contains("(") && lineTrim.Contains(")"))
                            {
                                //parse arguments
                                var vertexArgs = ParseArguments(lineTrim);
                                verticesArgs.Add(key, vertexArgs);
                            }
                        }
                        //#LIGHTING is an alias for fragment here, just to differentiate in the template code
                        else if (lineTrim.StartsWith("#FRAGMENT") || lineTrim.StartsWith("#LIGHTING"))
                        {
                            var key = "";
                            if (lineTrim.Contains(":"))
                            {
                                int start = "#FRAGMENT:".Length;                                 // same character count for #LIGHTING
                                int end   = lineTrim.IndexOf('(');
                                if (end >= 0)
                                {
                                    key = lineTrim.Substring(start, end - start);
                                }
                                else
                                {
                                    key = lineTrim.Substring(start);
                                }
                            }

                            currentList = new List <string>();
                            fragments.Add(key, currentList);

                            if (lineTrim.Contains("(") && lineTrim.Contains(")"))
                            {
                                //parse arguments
                                var fragmentArgs = ParseArguments(lineTrim);
                                fragmentsArgs.Add(key, fragmentArgs);
                            }
                        }
                        else if (lineTrim.StartsWith("#FUNCTIONS:EXPLICIT"))
                        {
                            // Explicit functions that have to be declared in the template with [[Module:FUNCTIONS:module_name]]
                            currentList       = functions;
                            explicitFunctions = true;
                        }
                        else
                        {
                            switch (lineTrim)
                            {
                            case "#FEATURES": currentList = features; break;

                            case "#PROPERTIES_NEW": currentList = propertiesNew; break;

                            case "#KEYWORDS": currentList = keywords; break;

                            case "#PROPERTIES_BLOCK": currentList = propertiesBlock; break;

                            case "#SHADER_FEATURES_BLOCK": currentList = shaderFeaturesBlock; break;

                            case "#FUNCTIONS": currentList = functions; break;

                            case "#VARIABLES": currentList = variables; break;

                            case "#INPUT": currentList = inputStruct; break;

                            case "#END": currentList = null; break;

                            default:
                            {
                                // An "arbitrary block" is parsed if not using a predefine keyword like above, and we are not iterating over an existing block
                                if (currentList == null)
                                {
                                    string block = lineTrim.Substring(1);
                                    if (block.Length > 0 && !char.IsWhiteSpace(block[0]))
                                    {
                                        currentList = new List <string>();
                                        arbitraryBlocks.Add(block, currentList);
                                    }
                                }
                                break;
                            }
                            }
                        }
                    }
                    else
                    {
                        if (currentList != null)
                        {
                            currentList.Add(line);
                        }
                    }
                }

                Module module = new Module();

                module.name                         = moduleName;
                module.Features                     = features.ToArray();
                module.PropertiesNew                = propertiesNew.ToArray();
                module.Keywords                     = keywords.ToArray();
                module.ShaderFeaturesBlock          = shaderFeaturesBlock.ToArray();
                module.PropertiesBlock              = propertiesBlock.ToArray();
                module.Functions                    = functions.ToArray();
                module.Variables                    = variables.ToArray();
                module.InputStruct                  = inputStruct.ToArray();
                module.ExplicitFunctionsDeclaration = explicitFunctions;
                module.ArbitraryBlocks              = arbitraryBlocks;

                // #VERTEX
                if (vertices.Count == 0)
                {
                    vertices.Add("", new List <string>());
                    verticesArgs.Add("", new List <Argument>());
                }

                foreach (var vertexPair in vertices)
                {
                    var key = vertexPair.Key;
                    module.Vertices.Add(key, vertexPair.Value.ToArray());
                    if (verticesArgs.ContainsKey(key))
                    {
                        module.VerticesArgs.Add(key, verticesArgs[key].ToArray());
                    }
                }

                // #FRAGMENT
                if (fragments.Count == 0)
                {
                    fragments.Add("", new List <string>());
                    fragmentsArgs.Add("", new List <Argument>());
                }

                foreach (var fragmentPair in fragments)
                {
                    var key = fragmentPair.Key;
                    module.Fragments.Add(key, fragmentPair.Value.ToArray());
                    if (fragmentsArgs.ContainsKey(key))
                    {
                        module.FragmentsArgs.Add(key, fragmentsArgs[key].ToArray());
                    }
                }

                module.ProcessIndentation();

                return(module);
            }
예제 #8
0
            //--------------------------------------------------------------------------------------------------

            public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] properties)
            {
                _materialEditor = materialEditor;
                _properties     = properties;

                hasAutoTransparency = System.Array.Exists(_properties, prop => prop.name == PROP_RENDERING_MODE);

#if SHOW_DEFAULT_INSPECTOR
                base.OnGUI();
                return;
#else
                //Header
                EditorGUILayout.BeginHorizontal();
                var label = (Screen.width > 450f) ? "TOONY COLORS PRO 2 - INSPECTOR (Generated Shader)" : (Screen.width > 300f ? "TOONY COLORS PRO 2 - INSPECTOR" : "TOONY COLORS PRO 2");
                TCP2_GUI.HeaderBig(label);
                if (TCP2_GUI.Button(TCP2_GUI.CogIcon2, "SG2", "Open in Shader Generator"))
                {
                    if (targetMaterial.shader != null)
                    {
                        ShaderGenerator2.OpenWithShader(targetMaterial.shader);
                    }
                }
                EditorGUILayout.EndHorizontal();
                TCP2_GUI.Separator();

                //Iterate Shader properties
                materialEditor.serializedObject.Update();
                var mShader = materialEditor.serializedObject.FindProperty("m_Shader");
                toggledGroups.Clear();

                // Auto-transparency
                if (hasAutoTransparency)
                {
                    int indent = EditorGUI.indentLevel;
                    EditorGUI.indentLevel++;
                    {
                        EditorGUILayout.BeginHorizontal();
                        {
                            GUILayout.Space(15);
                            GUILayout.Label(TCP2_GUI.TempContent("Transparency"), EditorStyles.boldLabel);
                        }
                        EditorGUILayout.EndHorizontal();
                        HandleRenderingMode();
                    }
                    EditorGUI.indentLevel = indent;
                }

                if (materialEditor.isVisible && !mShader.hasMultipleDifferentValues && mShader.objectReferenceValue != null)
                {
                    //Retina display fix
                    EditorGUIUtility.labelWidth = Utils.ScreenWidthRetina - 120f;
                    EditorGUIUtility.fieldWidth = 64f;

                    EditorGUI.BeginChangeCheck();

                    EditorGUI.indentLevel++;
                    foreach (var p in properties)
                    {
                        var visible = (toggledGroups.Count == 0 || toggledGroups.Peek());

                        //Hacky way to separate material inspector properties into foldout groups
                        if (p.name.StartsWith("__BeginGroup"))
                        {
                            //Foldout
                            if (visible)
                            {
                                GUILayout.Space(2f);
                                Rect propertyRect = EditorGUILayout.GetControlRect(true, EditorGUIUtility.singleLineHeight, EditorStyles.layerMaskField);
                                propertyRect.x     += 12;
                                propertyRect.width -= 12;
                                p.floatValue        = EditorGUI.Foldout(propertyRect, p.floatValue > 0, p.displayName, true) ? 1 : 0;
                            }

                            EditorGUI.indentLevel++;
                            toggledGroups.Push((p.floatValue > 0) && visible);
                        }
                        else if (p.name.StartsWith("__EndGroup"))
                        {
                            EditorGUI.indentLevel--;
                            toggledGroups.Pop();
                            GUILayout.Space(2f);
                        }
                        else
                        {
                            //Draw regular property
                            if (visible && (p.flags & (MaterialProperty.PropFlags.PerRendererData | MaterialProperty.PropFlags.HideInInspector)) == MaterialProperty.PropFlags.None)
                            {
                                _materialEditor.ShaderProperty(p, p.displayName);
                            }
                        }
                    }
                    EditorGUI.indentLevel--;

                    if (EditorGUI.EndChangeCheck())
                    {
                        materialEditor.PropertiesChanged();
                    }
                }
#endif     // !SHOW_DEFAULT_INSPECTOR

#if UNITY_5_5_OR_NEWER
                TCP2_GUI.Separator();
                materialEditor.RenderQueueField();
#endif
#if UNITY_5_6_OR_NEWER
                materialEditor.EnableInstancingField();
#endif
            }
예제 #9
0
            internal List <List <ShaderProperty> > FindUsedShaderPropertiesPerPass(ParsedLine[] parsedLines)
            {
                // Find used shader properties depending on the current pass, to extract used features per pass
                var shaderPropertiesPerPass = new List <List <ShaderProperty> >();

                // Find available Generic Implementations based on the current features
                ShaderProperty.Imp_GenericFromTemplate.InitList();
                int    passIndex = -1;
                string program   = "undefined";

                for (var i = 0; i < parsedLines.Length; i++)
                {
                    var line = parsedLines[i].line.Trim();

                    if (line.StartsWith("#PASS"))
                    {
                        passIndex++;
                        shaderPropertiesPerPass.Add(new List <ShaderProperty>());
                        continue;
                    }

                    if (line.StartsWith("#VERTEX"))
                    {
                        program = "vertex";
                        continue;
                    }

                    if (line.StartsWith("#FRAGMENT"))
                    {
                        program = "fragment";
                        continue;
                    }

                    if (line.StartsWith("#LIGHTING"))
                    {
                        program = "lighting";
                        continue;
                    }

                    if (passIndex < 0)
                    {
                        continue;
                    }

                    // enabled generic implementation
                    if (line.StartsWith("#ENABLE_IMPL"))
                    {
                        ShaderProperty.Imp_GenericFromTemplate.EnableFromLine(line, passIndex, program);
                        continue;
                    }
                    // disabled generic implementation
                    if (line.StartsWith("#DISABLE_IMPL"))
                    {
                        if (line.Contains("DISABLE_IMPL_ALL"))
                        {
                            ShaderProperty.Imp_GenericFromTemplate.DisableAll();
                        }
                        else
                        {
                            ShaderProperty.Imp_GenericFromTemplate.DisableFromLine(line, passIndex, program);
                        }
                        continue;
                    }

                    var end = 0;
                    while (line.IndexOf("[[", end) >= 0)
                    {
                        var start = line.IndexOf("[[", end);
                        end = line.IndexOf("]]", end + 1);
                        var tag = line.Substring(start + 2, end - start - 2);
                        if (tag.StartsWith("VALUE:") || tag.StartsWith("SAMPLE_VALUE_SHADER_PROPERTY:"))
                        {
                            var propName  = tag.Substring(tag.IndexOf(':') + 1);
                            int argsStart = propName.IndexOf('(');
                            if (argsStart > 0)
                            {
                                propName = propName.Substring(0, argsStart);
                            }

                            var sp = GetShaderPropertyByName(propName);
                            if (sp != null)
                            {
                                //add to used Shader Properties for current parsed pass
                                if (!shaderPropertiesPerPass[passIndex].Contains(sp))
                                {
                                    shaderPropertiesPerPass[passIndex].Add(sp);
                                }

                                ShaderProperty.Imp_GenericFromTemplate.AddCompatibleShaderProperty(sp);
                            }
                            else
                            {
                                Debug.LogError(ShaderGenerator2.ErrorMsg(string.Format("No match for used Shader Property in code: '<b>{0}</b>'", tag)));
                            }
                        }
                    }
                }

                ShaderProperty.Imp_GenericFromTemplate.ListCompleted();

                // Iterate through properties, and take into account referenced ones
                Action <ShaderProperty, List <ShaderProperty> > findAndAddLinkedShaderProperties = null;

                findAndAddLinkedShaderProperties = (sp, list) =>
                {
                    foreach (var imp in sp.implementations)
                    {
                        var impSpRef = imp as ShaderProperty.Imp_ShaderPropertyReference;
                        if (impSpRef != null)
                        {
                            // linked shader property can't be null during compilation, or something went wrong
                            if (!list.Contains(impSpRef.LinkedShaderProperty))
                            {
                                list.Add(impSpRef.LinkedShaderProperty);

                                // recursive
                                findAndAddLinkedShaderProperties(impSpRef.LinkedShaderProperty, list);
                            }
                        }
                    }
                };
                for (int i = 0; i < shaderPropertiesPerPass.Count; i++)
                {
                    var list = shaderPropertiesPerPass[i];
                    foreach (var sp in list.ToArray())
                    {
                        findAndAddLinkedShaderProperties(sp, list);
                    }
                }

                return(shaderPropertiesPerPass);
            }
예제 #10
0
            internal ShaderProperty[] GetConditionalShaderProperties(ParsedLine[] parsedLines, out Dictionary <int, GUIContent> headers)
            {
                headers = new Dictionary <int, GUIContent>();

                var shaderPropertiesList = new List <ShaderProperty>();

                for (var i = 0; i < parsedLines.Length; i++)
                {
                    var line = parsedLines[i].line;

                    if (line.StartsWith("#PROPERTIES_NEW"))
                    {
                        while (i < parsedLines.Length)
                        {
                            line = parsedLines[i].line;
                            i++;

                            if (line.StartsWith("#END"))
                            {
                                return(shaderPropertiesList.ToArray());
                            }

                            if (line.StartsWith("//") || line.StartsWith("#") || string.IsNullOrEmpty(line))
                            {
                                continue;
                            }

                            if (line.Trim().StartsWith("header"))
                            {
                                var data = line.Split(new string[] { "\t" }, System.StringSplitOptions.RemoveEmptyEntries);
                                var gc   = new GUIContent(data[1], data.Length > 2 ? data[2].Trim('\"') : null);
                                if (!headers.ContainsKey(shaderPropertiesList.Count))
                                {
                                    headers.Add(shaderPropertiesList.Count, null);
                                }
                                headers[shaderPropertiesList.Count] = gc;                                       // only take the last one into account, so that empty headers will be ignored
                                continue;
                            }

                            try
                            {
                                var shaderProperty = ShaderProperty.CreateFromTemplateData(line);
                                var match          = GetShaderPropertyByName(shaderProperty.Name);
                                if (match == null)
                                {
                                    Debug.LogError(ShaderGenerator2.ErrorMsg("Can't find Shader Property in Template, yet it was found for Config"));
                                }
                                else
                                {
                                    shaderPropertiesList.Add(match);
                                }
                            }
                            catch (Exception e)
                            {
                                Debug.LogError(ShaderGenerator2.ErrorMsg(string.Format("Parsing error in <b>#PROPERTIES_NEW</b> block:\n'{0}'\n{1}", e.Message, e.StackTrace)));
                            }
                        }
                    }
                }

                return(shaderPropertiesList.ToArray());
            }
예제 #11
0
            //Get all Shader Properties regardless of conditions, only their visibility will be affected by the Config
            //This ensures that they are always in the correct order
            //Also link the pending Imp_ShaderPropertyReferences at this time, if any
            //and assign the correct pass bitmask based on usage
            static ShaderProperty[] GetShaderProperties(string[] lines, int i)
            {
                var    shaderPropertiesList = new List <ShaderProperty>();
                string subline;

                do
                {
                    subline = lines[i];
                    i++;

                    if (subline == "#END")
                    {
                        break;
                    }

                    if (subline.Trim().StartsWith("//") || subline.StartsWith("#") || string.IsNullOrEmpty(subline))
                    {
                        continue;
                    }

                    if (subline.Trim().StartsWith("header"))
                    {
                        continue;
                    }

                    try
                    {
                        var shaderProperty = ShaderProperty.CreateFromTemplateData(subline);
                        shaderPropertiesList.Add(shaderProperty);
                    }
                    catch (Exception e)
                    {
                        Debug.LogError(ShaderGenerator2.ErrorMsg(string.Format("Parsing error in <b>#PROPERTIES_NEW</b> block:\n\nError: '{0}'\n\nLine: '{1}'", e.ToString(), subline)));
                    }
                }while (subline != "#END" && subline != null);

                //link shader property references
                foreach (var shaderProperty in shaderPropertiesList)
                {
                    if (shaderProperty.implementations != null && shaderProperty.implementations.Count > 0)
                    {
                        foreach (var imp in shaderProperty.implementations)
                        {
                            var impSpRef = imp as ShaderProperty.Imp_ShaderPropertyReference;
                            if (impSpRef != null && !string.IsNullOrEmpty(impSpRef.LinkedShaderPropertyName))
                            {
                                var match = shaderPropertiesList.Find(sp => sp.Name == impSpRef.LinkedShaderPropertyName);
                                if (match != null)
                                {
                                    var channels = impSpRef.Channels;
                                    impSpRef.LinkedShaderProperty = match;
                                    //restore channels from template data, it's up to the template to match the referenced shader property
                                    if (!string.IsNullOrEmpty(channels))
                                    {
                                        impSpRef.Channels = channels.ToUpperInvariant();
                                    }
                                    impSpRef.ForceUpdateParentDefaultHash();
                                }
                                else
                                {
                                    Debug.LogError(ShaderGenerator2.ErrorMsg(string.Format("Can't find referenced Shader Property in template.\n'{0}' tried to reference '{1}'", shaderProperty.Name, impSpRef.LinkedShaderPropertyName)));
                                }
                            }
                        }
                    }
                }

                //iterate rest of template to check usage of each shader property per pass

                int currentPass = -1;

                for (; i < lines.Length; i++)
                {
                    var line = lines[i].Trim();

                    // update pass
                    if (line.StartsWith("#PASS"))
                    {
                        currentPass++;
                        continue;
                    }

                    // check value usage: used in which pass(es), and which generic implementation they can use
                    var end = 0;
                    while (line.IndexOf("[[", end) >= 0)
                    {
                        var start = line.IndexOf("[[", end);
                        end = line.IndexOf("]]", end + 1);
                        var tag = line.Substring(start + 2, end - start - 2);
                        if (tag.StartsWith("VALUE:") || tag.StartsWith("SAMPLE_VALUE_SHADER_PROPERTY:"))
                        {
                            var propName  = tag.Substring(tag.IndexOf(':') + 1);
                            int argsStart = propName.IndexOf('(');
                            if (argsStart > 0)
                            {
                                propName = propName.Substring(0, argsStart);
                            }

                            var sp = shaderPropertiesList.Find(x => x.Name == propName);
                            if (sp != null)
                            {
                                // found used Shader Property
                                sp.AddPassUsage(currentPass);
                            }
                            else
                            {
                                Debug.LogError(ShaderGenerator2.ErrorMsg(string.Format("No match for used Shader Property in code: '<b>{0}</b>'", tag)));
                            }
                        }
                    }
                }

                return(shaderPropertiesList.ToArray());
            }
예제 #12
0
            private void UpdateTemplateMeta()
            {
                uiFeatures       = null;
                templateInfo     = null;
                templateWarning  = null;
                templateType     = null;
                templateKeywords = null;
                id = null;

                UIFeature.ClearFoldoutStack();

                if (textAsset != null && !string.IsNullOrEmpty(textAsset.text))
                {
                    //First pass: parse #MODULES and replace related keywords
                    var newTemplateLines = new List <string>();
                    Dictionary <string, Module> modules = new Dictionary <string, Module>();
                    var usedModulesVariables            = new HashSet <Module>();
                    var usedModulesInput = new HashSet <Module>();
                    for (int i = 0; i < originalTextLines.Length; i++)
                    {
                        string line = originalTextLines[i];

                        //Parse #MODULES
                        if (line.StartsWith("#MODULES"))
                        {
                            //Iterate module names and try to find matching TextAssets
                            while (line != "#END" && i < originalTextLines.Length)
                            {
                                line = originalTextLines[i];
                                i++;

                                if (line == "#END")
                                {
                                    break;
                                }

                                if (line.StartsWith("//") || line.StartsWith("#") || string.IsNullOrEmpty(line))
                                {
                                    continue;
                                }

                                try
                                {
                                    var moduleName = line.Trim();
                                    var module     = Module.CreateFromName(moduleName);
                                    if (module != null)
                                    {
                                        modules.Add(moduleName, module);
                                    }
                                }
                                catch (Exception e)
                                {
                                    Debug.LogError(ShaderGenerator2.ErrorMsg(string.Format("Parsing error in <b>#MODULES</b> block:\nLine: '{0}'\n'{1}'\n{2}", line, e.Message, e.StackTrace)));
                                }
                            }
                        }

                        //Replace module keywords
                        if (line.Trim().StartsWith("[[MODULE") && i < originalTextLines.Length)
                        {
                            //extract indentation
                            var indent = "";
                            foreach (var c in line)
                            {
                                if (char.IsWhiteSpace(c))
                                {
                                    indent += c;
                                }
                                else
                                {
                                    break;
                                }
                            }

                            var start = line.IndexOf("[[MODULE:");
                            var end   = line.LastIndexOf("]]");
                            var tag   = line.Substring(start + "[[MODULE:".Length, end - start - "[[MODULE:".Length);

                            var moduleName = "";
                            var key        = "";
                            if (tag.IndexOf(':') > 0)
                            {
                                moduleName = tag.Substring(tag.IndexOf(':') + 1);

                                //remove arguments if any
                                if (moduleName.Contains("("))
                                {
                                    moduleName = moduleName.Substring(0, moduleName.IndexOf("("));
                                }

                                //extract key, if any
                                int keyStart = moduleName.IndexOf(':');
                                if (keyStart > 0)
                                {
                                    key        = moduleName.Substring(keyStart + 1);
                                    moduleName = moduleName.Substring(0, keyStart);
                                }
                            }

                            if (!string.IsNullOrEmpty(moduleName) && !modules.ContainsKey(moduleName))
                            {
                                Debug.LogError(ShaderGenerator2.ErrorMsg(string.Format("Can't find module: '{0}' for '{1}'", moduleName, line.Trim())));
                                continue;
                            }

                            if (tag.StartsWith("INPUT:"))
                            {
                                //Print Input block from specific module
                                foreach (var module in modules.Values)
                                {
                                    if (module.name == moduleName)
                                    {
                                        AddRangeWithIndent(newTemplateLines, module.InputStruct, indent);
                                        usedModulesInput.Add(module);
                                    }
                                }
                            }
                            if (tag == "INPUT")
                            {
                                //Print all Input lines from all modules
                                foreach (var module in modules.Values)
                                {
                                    if (!usedModulesInput.Contains(module))
                                    {
                                        AddRangeWithIndent(newTemplateLines, module.InputStruct, indent);
                                    }
                                }
                            }
                            else if (tag.StartsWith("VARIABLES:"))
                            {
                                //Print Variables line from specific module
                                foreach (var module in modules.Values)
                                {
                                    if (module.name == moduleName)
                                    {
                                        AddRangeWithIndent(newTemplateLines, module.Variables, indent);
                                        usedModulesVariables.Add(module);
                                    }
                                }
                            }
                            else if (tag == "VARIABLES")
                            {
                                //Print all Variables lines from all modules
                                foreach (var module in modules.Values)
                                {
                                    if (!usedModulesVariables.Contains(module))
                                    {
                                        AddRangeWithIndent(newTemplateLines, module.Variables, indent);
                                    }
                                }
                            }
                            else if (tag == "KEYWORDS")
                            {
                                //Print all Keywords lines from all modules
                                foreach (var module in modules.Values)
                                {
                                    AddRangeWithIndent(newTemplateLines, module.Keywords, indent);
                                }
                            }
                            else if (tag.StartsWith("FEATURES:"))
                            {
                                AddRangeWithIndent(newTemplateLines, modules[moduleName].Features, indent);
                            }
                            else if (tag.StartsWith("PROPERTIES_NEW:"))
                            {
                                AddRangeWithIndent(newTemplateLines, modules[moduleName].PropertiesNew, indent);
                            }
                            else if (tag.StartsWith("PROPERTIES_BLOCK:"))
                            {
                                AddRangeWithIndent(newTemplateLines, modules[moduleName].PropertiesBlock, indent);
                            }
                            else if (tag.StartsWith("SHADER_FEATURES_BLOCK"))
                            {
                                AddRangeWithIndent(newTemplateLines, modules[moduleName].ShaderFeaturesBlock, indent);
                            }
                            else if (tag.StartsWith("VERTEX:"))
                            {
                                //Get arguments if any
                                var args     = new List <string>();
                                int argStart = tag.IndexOf("(") + 1;
                                int argEnd   = tag.IndexOf(")");
                                if (argStart > 0 && argEnd > 0)
                                {
                                    string arguments      = tag.Substring(argStart, argEnd - argStart);
                                    var    argumentsSplit = arguments.Split(',');
                                    foreach (var a in argumentsSplit)
                                    {
                                        args.Add(a.Trim());
                                    }
                                }

                                AddRangeWithIndent(newTemplateLines, modules[moduleName].VertexLines(args, key), indent);
                            }
                            else if (tag.StartsWith("FRAGMENT:"))
                            {
                                //Get arguments if any
                                var args     = new List <string>();
                                int argStart = tag.IndexOf("(") + 1;
                                int argEnd   = tag.IndexOf(")");
                                if (argStart > 0 && argEnd > 0)
                                {
                                    string arguments      = tag.Substring(argStart, argEnd - argStart);
                                    var    argumentsSplit = arguments.Split(',');
                                    foreach (var a in argumentsSplit)
                                    {
                                        args.Add(a.Trim());
                                    }
                                }

                                AddRangeWithIndent(newTemplateLines, modules[moduleName].FragmentLines(args, key), indent);
                            }
                        }
                        else
                        {
                            newTemplateLines.Add(line);
                        }
                    }

                    //Apply to textLines
                    this.textLines = newTemplateLines.ToArray();

                    //Second pass: parse other blocks
                    for (int i = 0; i < textLines.Length; i++)
                    {
                        var line = textLines[i];
                        if (line.StartsWith("#INFO="))
                        {
                            templateInfo = line.Substring("#INFO=".Length).TrimEnd().Replace("  ", "\n");
                        }

                        else if (line.StartsWith("#WARNING="))
                        {
                            templateWarning = line.Substring("#WARNING=".Length).TrimEnd().Replace("  ", "\n");
                        }

                        else if (line.StartsWith("#CONFIG="))
                        {
                            templateType = line.Substring("#CONFIG=".Length).TrimEnd().ToLower();
                        }

                        else if (line.StartsWith("#TEMPLATE_KEYWORDS="))
                        {
                            templateKeywords = line.Substring("#TEMPLATE_KEYWORDS=".Length).TrimEnd().Split(',');
                        }

                        else if (line.StartsWith("#ID="))
                        {
                            id = line.Substring("#ID=".Length).TrimEnd();
                        }

                        else if (line.StartsWith("#FEATURES"))
                        {
                            uiFeatures = UIFeature.GetUIFeatures(textLines, ref i, this);
                        }

                        else if (line.StartsWith("#PROPERTIES_NEW"))
                        {
                            shaderProperties = GetShaderProperties(textLines, i);
                            return;
                        }

                        //Config meta should appear before the Shader name line
                        else if (line.StartsWith("Shader"))
                        {
                            return;
                        }
                    }

                    if (id == null)
                    {
                        Debug.LogWarning(ShaderGenerator2.ErrorMsg("Missing ID in template metadata!"));
                    }
                }
            }
예제 #13
0
            //Returns an array of parsed lines based on the current features enabled, with their corresponding original line number (for error reporting)
            //Only keeps the lines necessary to generate the shader source, e.g. #FEATURES will be skipped
            //Conditions are now only processed in this function, all the other code should ignore them
            internal ParsedLine[] GetParsedLinesFromConditions(Config config, List <string> flags)
            {
                var list = new List <ParsedLine>();

                int depth     = -1;
                var stack     = new List <bool>();
                var done      = new List <bool>();
                var features  = new List <string>(config.Features);
                int passIndex = -1;

                //clear optional features from shader properties options
                config.ClearShaderPropertiesFeatures();

                //make sure to use all needed features as config features for conditions
                var conditionFeatures = new List <string>(config.GetShaderPropertiesNeededFeaturesAll());

                conditionFeatures.AddRange(config.Features);
                conditionFeatures.AddRange(config.ExtraTempFeatures);

                //make sure keywords have been processed
                var keywordsFeatures = new List <string>();

                ProcessKeywordsBlock(config, conditionFeatures, keywordsFeatures, flags);
                features.AddRange(keywordsFeatures);

                //before first #PASS tag: use needed features from _all_ passes:
                //this is to make sure that the CGINCLUDE block with needed #VARIABLES:MODULES gets processed correctly
                features.AddRange(config.GetShaderPropertiesNeededFeaturesAll());
                features.AddRange(config.GetHooksNeededFeatures());

                //parse lines and strip based on conditions
                for (var i = 0; i < textLines.Length; i++)
                {
                    var line = textLines[i];

                    if (line.Length > 0 && line[0] == '#')
                    {
                        if (line.StartsWith("#PASS"))
                        {
                            //new pass: get the specific features for this pass
                            passIndex++;
                            features = new List <string>(config.Features);
                            features.AddRange(config.GetHooksNeededFeatures());
                            features.AddRange(config.GetShaderPropertiesNeededFeaturesForPass(passIndex));

                            var passKeywordsFeatures = new List <string>();
                            ProcessKeywordsBlock(config, features, passKeywordsFeatures, flags);
                            features.AddRange(passKeywordsFeatures);
                        }

                        //Skip #FEATURES block
                        if (line.StartsWith("#FEATURES"))
                        {
                            while (i < textLines.Length)
                            {
                                i++;
                                line = textLines[i];
                                if (line == "#END")
                                {
                                    break;
                                }
                            }
                        }
                    }

                    //Conditions
                    if (line.Contains("///"))
                    {
                        var error = ExpressionParser.ProcessCondition(line, features, ref depth, ref stack, ref done);
                        if (!string.IsNullOrEmpty(error))
                        {
                            Debug.LogError(ShaderGenerator2.ErrorMsg(error + "\n@ line " + i));
                        }
                    }
                    //Regular line
                    else
                    {
                        //Append line if inside valid condition block
                        if ((depth >= 0 && stack[depth]) || depth < 0)
                        {
                            list.Add(new ParsedLine {
                                line = line, lineNumber = i + 1
                            });
                        }
                    }
                }

                //error?
                if (depth >= 0)
                {
                    //Analyze and try to find where the issue is
                    var st = new Stack <ParsedLine>();
                    for (var i = 0; i < textLines.Length; i++)
                    {
                        var tline = textLines[i].TrimStart();

                        if (tline == "///")
                        {
                            st.Pop();
                        }
                        else if (tline.StartsWith("/// IF"))
                        {
                            st.Push(new ParsedLine {
                                line = textLines[i], lineNumber = i + 1
                            });
                        }
                    }

                    if (st.Count > 0)
                    {
                        var pl = st.Pop();
                        Debug.LogError(ShaderGenerator2.ErrorMsg(string.Format("Missing {0} ending '///' tag{1} at line {2}:\n{3}", depth + 1, depth > 0 ? "s" : "", pl.lineNumber, pl.line)));
                    }
                    else
                    {
                        Debug.LogError(ShaderGenerator2.ErrorMsg(string.Format("Missing {0} ending '///' tag{1}", depth + 1, depth > 0 ? "s" : "")));
                    }
                }

                return(list.ToArray());
            }
예제 #14
0
            protected override void DrawGUI(Rect position, Config config)
            {
                // Fetch embedded Shader Property
                bool highlighted = Highlighted(config);

                if (shaderProperty == null && highlighted)                 // the SP only exists if the feature is enabled
                {
                    var match = Array.Find(config.AllShaderProperties, sp => sp.Name == shaderPropertyName);
                    if (match == null)
                    {
                        Debug.LogError(ShaderGenerator2.ErrorMsg("Can't find matching embedded Shader Property with name: '" + shaderPropertyName + "'"));
                    }
                    shaderProperty = match;
                }

                int feature = highlighted ? (shaderProperty.implementations[0] as ShaderProperty.Imp_Enum).ValueType + 1 : 0;

                if (feature < 0)
                {
                    feature = 0;
                }

                EditorGUI.BeginChangeCheck();
                feature = EditorGUI.Popup(position, feature, labels);
                if (EditorGUI.EndChangeCheck())
                {
                    config.ToggleFeature(keyword, feature > 0);

                    // Update Fixed Function value type
                    var ffv = fixedFunctionValues[feature];
                    if (feature > 0 && !string.IsNullOrEmpty(ffv) && shaderProperty != null)
                    {
                        (shaderProperty.implementations[0] as ShaderProperty.Imp_Enum).SetValueTypeFromString(ffv);
                        shaderProperty.CheckHash();
                        shaderProperty.CheckErrors();
                    }
                }

                // Show embedded Shader Property UI
                if (highlighted && shaderProperty != null)
                {
                    if (shaderProperty.Type != ShaderProperty.VariableType.fixed_function_enum)
                    {
                        EditorGUILayout.HelpBox("Embedded Shader Property should be a Fixed Function enum.", MessageType.Error);
                    }
                    else
                    {
                        var imp = shaderProperty.implementations[0] as ShaderProperty.Imp_Enum;
                        if (imp == null)
                        {
                            EditorGUILayout.HelpBox("First implementation of enum Shader Property isn't an Imp_Enum.", MessageType.Error);
                        }
                        else
                        {
                            EditorGUI.BeginChangeCheck();
                            {
                                imp.EmbeddedGUI(28, 170);
                            }
                            if (EditorGUI.EndChangeCheck())
                            {
                                shaderProperty.CheckHash();
                                shaderProperty.CheckErrors();
                            }
                        }
                    }
                }
            }