Example #1
0
	static public TCP2_Config CreateFromFile(string text)
	{
		string[] lines = text.Split(new string[]{"\n","\r\n"}, System.StringSplitOptions.RemoveEmptyEntries);
		TCP2_Config config = new TCP2_Config();

		//Flags
		ParseBlock currentBlock = ParseBlock.None;
		for(int i = 0; i < lines.Length; i++)
		{
			string line = lines[i];
			
			if(line.StartsWith("//")) continue;
			
			string[] data = line.Split(new string[]{"\t"}, System.StringSplitOptions.RemoveEmptyEntries);
			if(line.StartsWith("#"))
			{
				currentBlock = ParseBlock.None;
				
				switch(data[0])
				{
					case "#filename":	config.Filename = data[1]; break;
					case "#shadername":	config.ShaderName = data[1]; break;
					case "#features":	currentBlock = ParseBlock.Features; break;
					case "#flags":		currentBlock = ParseBlock.Flags; break;
					
					default: Debug.LogWarning("[TCP2 Shader Config] Unrecognized tag: " + data[0] + "\nline " + (i+1)); break;
				}
			}
			else
			{
				if(data.Length > 1)
				{
					bool enabled = false;
					bool.TryParse(data[1], out enabled);
					
					if(enabled)
					{
						if(currentBlock == ParseBlock.Features)
							config.Features.Add(data[0]);
						else if(currentBlock == ParseBlock.Flags)
							config.Flags.Add(data[0]);
						else
							Debug.LogWarning("[TCP2 Shader Config] Unrecognized line while parsing : " + line + "\nline " + (i+1));
					}
				}
			}
		}
		
		return config;
	}
                protected override void ForceValue(TCP2_Config config)
                {
                    var selectedValue = GetSelectedValue(config);

                    if (selectedValue < 0)
                    {
                        selectedValue = defaultValue;
                    }

                    if (forceValue && Enabled(config) && !config.HasKeyword(keyword))
                    {
                        config.SetKeyword(keyword, values[selectedValue]);
                    }
                }
Example #3
0
        protected override void OnEnabledChangedState(TCP2_Config config, bool newState)
        {
            var feature = -1;

            if (newState)
            {
                feature = GetSelectedFeature(config);
                if (feature < 0)
                {
                    feature = 0;
                }
            }

            ToggleSelectedFeature(config, feature);
        }
Example #4
0
    static private bool NeedCustomLighting(TCP2_Config config)
    {
        bool specmask      = HasFeatures(config, "SPECULAR_MASK");
        bool anisotropic   = HasFeatures(config, "SPECULAR_ANISOTROPIC");
        bool texthreshold  = HasFeatures(config, "TEXTURED_THRESHOLD");
        bool occlusion     = HasFeatures(config, "OCCLUSION");
        bool indshadows    = HasFeatures(config, "INDEPENDENT_SHADOWS");
        bool sketch        = HasFeatures(config, "SKETCH", "SKETCH_GRADIENT");
        bool lightmap      = HasFeatures(config, "LIGHTMAP");
        bool dsbWrapLight  = HasFeatures(config, "DISABLE_WRAPPED_LIGHTING");
        bool rim_lightmask = HasFeatures(config, "RIM_LIGHTMASK");
        bool color_mult    = HasFeatures(config, "COLOR_MULTIPLIERS");

        return(dsbWrapLight || specmask || anisotropic || occlusion || texthreshold || indshadows || sketch || lightmap || rim_lightmask || color_mult);
    }
Example #5
0
    private void LoadCurrentConfig(TCP2_Config config, bool loadConfigTemplate = true)
    {
        mCurrentConfig = config;
        mDirtyConfig   = false;
        if (sAutoNames)
        {
            mCurrentConfig.AutoNames();
        }
        mCurrentHash = mCurrentConfig.ToHash();

        if (loadConfigTemplate)
        {
            Template.TryLoadTextAsset(mCurrentConfig);
        }
    }
Example #6
0
        public void FeaturesGUI(TCP2_Config config)
        {
            if (this.uiFeatures == null)
            {
                EditorGUILayout.HelpBox("Couldn't parse the features from the Template.", MessageType.Error);
                return;
            }

            int length = this.uiFeatures.Length;

            for (int i = 0; i < length; i++)
            {
                this.uiFeatures[i].DrawGUI(config);
            }
        }
Example #7
0
        protected override void DrawGUI(Rect position, TCP2_Config config)
        {
            var feature = GetSelectedFeature(config);

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

            EditorGUI.BeginChangeCheck();
            feature = EditorGUI.Popup(position, feature, labels);
            if (EditorGUI.EndChangeCheck())
            {
                ToggleSelectedFeature(config, feature);
            }
        }
Example #8
0
        private void ToggleSelectedFeature(TCP2_Config config, int selectedFeature)
        {
            for (var i = 0; i < features.Length; i++)
            {
                var enable = (i == selectedFeature);
                config.ToggleFeature(features[i], enable);
            }

            if (toggles != null)
            {
                foreach (var t in toggles)
                {
                    config.ToggleFeature(t, selectedFeature > 0);
                }
            }
        }
Example #9
0
    static private string GetShaderTarget(TCP2_Config config)
    {
        return((config.shaderTarget / 10f).ToString("0.0"));

        /*
         * bool tessellate = HasFeatures(config, "DX11_TESSELLATION");
         * bool forcesm2 = HasFeatures(config, "FORCE_SM2");
         *
         * if(forcesm2)
         *      return "2.0";
         * else if(tessellate)
         *      return "5.0";
         * else
         *      return "3.0";
         */
    }
	static private string GetExistingShaderPath(TCP2_Config config, Shader existingShader)
	{
		//Override OutputPath if Shader already exists, to make sure we replace the original shader file
		string unityPath = AssetDatabase.GetAssetPath(existingShader);
		unityPath = unityPath.Replace(".shader", "");       //remove extension
		unityPath = Path.GetDirectoryName(unityPath);
		if (config.Filename.Contains("/"))
		{
			string filenamePath = Path.GetDirectoryName(config.Filename);
			unityPath = unityPath.Replace(filenamePath, "");       //remove subdirectories
		}
		unityPath = unityPath.Substring(6);                 //get only directory without leading "Assets"
		if (!unityPath.EndsWith("/"))
			unityPath = unityPath + "/";
		return unityPath;
	}
	static private bool GetMaskDependency(TCP2_Config config, string maskType)
	{
		switch(maskType)
		{
		case "SPEC_MASK": return HasFeatures(config, "SPECULAR", "SPECULAR_ANISOTROPIC");
		case "REFL_MASK": return HasFeatures(config, "REFLECTION");
		case "MASK_MC": return HasFeatures(config, "MATCAP");
		case "SPEC_SHIN_MASK": return HasFeatures(config, "SPECULAR", "SPECULAR_ANISOTROPIC");
		case "DETAIL_MASK": return HasFeatures(config, "DETAIL_TEX");
		case "RIM_MASK": return HasFeatures(config, "RIM","RIM_OUTLINE");
		case "EMISSION_MASK": return HasFeatures(config, "EMISSION");
		case "SS_MASK": return HasFeatures(config, "SUBSURFACE_SCATTERING");
		case "COLORMASK": return true;
		}
		return false;
	}
Example #12
0
        public void FeaturesGUI(TCP2_Config config)
        {
            if (uiFeatures == null)
            {
                EditorGUILayout.HelpBox("Couldn't parse the features from the Template.", MessageType.Error);
                return;
            }

            //Make the template accessible to UIFeatures (so that DropDown can iterate and know if any features inside are modified)
            CurrentTemplate = this;
            var length = uiFeatures.Length;

            for (var i = 0; i < length; i++)
            {
                uiFeatures[i].DrawGUI(config);
            }
        }
Example #13
0
            public static TCP2_Config CreateFromShader(Shader shader)
            {
                var shaderImporter = ShaderImporter.GetAtPath(AssetDatabase.GetAssetPath(shader)) as ShaderImporter;

                var config = new TCP2_Config();

                config.ShaderName           = shader.name;
                config.Filename             = Path.GetFileName(AssetDatabase.GetAssetPath(shader)).Replace(".shader", "");
                config.isModifiedExternally = false;
                var valid = config.ParseUserData(shaderImporter);

                if (valid)
                {
                    return(config);
                }
                return(null);
            }
Example #14
0
    private void LoadCurrentConfigFromShader(Shader shader)
    {
        ShaderImporter shaderImporter = ShaderImporter.GetAtPath(AssetDatabase.GetAssetPath(shader)) as ShaderImporter;

        string[] features;
        string[] flags;
        string[] customData;
        Dictionary <string, string> keywords;

        TCP2_ShaderGeneratorUtils.ParseUserData(shaderImporter, out features, out flags, out keywords, out customData);
        if (features != null && features.Length > 0 && features[0] == "USER")
        {
            mCurrentConfig            = new TCP2_Config();
            mCurrentConfig.ShaderName = shader.name;
            mCurrentConfig.Filename   = System.IO.Path.GetFileName(AssetDatabase.GetAssetPath(shader));
            mCurrentConfig.Features   = new List <string>(features);
            mCurrentConfig.Flags      = (flags != null) ? new List <string>(flags) : new List <string>();
            mCurrentConfig.Keywords   = (keywords != null) ? new Dictionary <string, string>(keywords) : new Dictionary <string, string>();
            mCurrentShader            = shader;
            mConfigChoice             = mUserShadersLabels.IndexOf(shader.name);
            mDirtyConfig = false;
            AutoNames();
            mCurrentHash = mCurrentConfig.ToHash();

            mIsModified = false;
            if (customData != null && customData.Length > 0)
            {
                ulong timestamp;
                if (ulong.TryParse(customData[0], out timestamp))
                {
                    if (shaderImporter.assetTimeStamp != timestamp)
                    {
                        mIsModified = true;
                    }
                }
            }
        }
        else
        {
            EditorApplication.Beep();
            this.ShowNotification(new GUIContent("Invalid shader loaded: it doesn't seem to have been generated by the TCP2 Shader Generator!"));
            mCurrentShader = null;
            NewShader();
        }
    }
Example #15
0
    static private string GetShaderTarget(TCP2_Config config)
    {
        bool tessellate = HasFeatures(config, "DX11_TESSELLATION");
        bool forcesm2   = HasFeatures(config, "FORCE_SM2");

        if (forcesm2)
        {
            return("2.0");
        }
        else if (tessellate)
        {
            return("5.0");
        }
        else
        {
            return("3.0");
        }
    }
Example #16
0
        protected override void DrawGUI(Rect position, TCP2_Config config)
        {
            var feature = Highlighted(config);

            EditorGUI.BeginChangeCheck();
            feature = EditorGUI.Toggle(position, feature);
            if (EditorGUI.EndChangeCheck())
            {
                config.ToggleFeature(keyword, feature);

                if (toggles != null)
                {
                    foreach (var t in toggles)
                    {
                        config.ToggleFeature(t, feature);
                    }
                }
            }
        }
Example #17
0
        protected override void DrawGUI(Rect position, TCP2_Config config)
        {
            EditorGUILayout.BeginHorizontal();
            TCP2_GUI.HelpButton("Shader Target");
            TCP2_GUI.SubHeader("Shader Target", "Defines the shader target level to compile for", config.shaderTarget != 30, LABEL_WIDTH - 24f);
            var newTarget = EditorGUILayout.IntPopup(config.shaderTarget,
#if UNITY_5_4_OR_NEWER
                                                     new[] { "2.0", "2.5", "3.0", "3.5", "4.0", "5.0" },
                                                     new[] { 20, 25, 30, 35, 40, 50 });
#else
                                                     new string[] { "2.0", "3.0", "4.0", "5.0" },
                                                     new int[] { 20, 30, 40, 50 });
#endif
            if (newTarget != config.shaderTarget)
            {
                config.shaderTarget = newTarget;
            }
            EditorGUILayout.EndHorizontal();
        }
Example #18
0
    //--------------------------------------------------------------------------------------------------
    // SHADER GENERATION

    private static string GetIncludePrefix(TCP2_Config config)
    {
        //Folder
        if (!config.Filename.Contains("/"))
        {
            return("");
        }

        var prefix = "";

        foreach (var c in config.Filename)
        {
            if (c == '/')
            {
                prefix += "../";
            }
        }
        return(prefix);
    }
Example #19
0
        protected override void DrawGUI(Rect position, TCP2_Config config)
        {
            //Check if any feature within that Foldout are enabled, and show different color if so
            var hasToggledFeatures = false;
            var i = Array.IndexOf(ShaderGeneratorTemplate.CurrentTemplate.uiFeatures, this);

            if (i >= 0)
            {
                for (i++; i < ShaderGeneratorTemplate.CurrentTemplate.uiFeatures.Length; i++)
                {
                    var uiFeature = ShaderGeneratorTemplate.CurrentTemplate.uiFeatures[i];
                    if (uiFeature is UIFeature_DropDownEnd)
                    {
                        break;
                    }

                    hasToggledFeatures |= uiFeature.Highlighted(config) && uiFeature.Enabled(config);
                }
            }

            var color = GUI.color;

            GUI.color *= 0.95f;
            EditorGUILayout.BeginVertical(EditorStyles.helpBox);
            GUI.color = color;
            EditorGUI.BeginChangeCheck();
            foldout = TCP2_GUI.HeaderFoldoutHighlight(foldout, guiContent, hasToggledFeatures);
            FoldoutStack.Push(foldout);
            if (EditorGUI.EndChangeCheck())
            {
                UpdatePersistentState();

                if (Event.current.alt || Event.current.control)
                {
                    var state = foldout;
                    foreach (var dd in AllDropDowns)
                    {
                        dd.foldout = state;
                        dd.UpdatePersistentState();
                    }
                }
            }
        }
Example #20
0
        //Try to load a Template according to a config type and/or file
        public void TryLoadTextAsset(TCP2_Config config = null)
        {
            string configFile = config != null ? config.templateFile : null;

            //Append file extension if necessary
            if (!string.IsNullOrEmpty(configFile) && !configFile.EndsWith(".txt"))
            {
                configFile = configFile + ".txt";
            }

            TextAsset loadedTextAsset = null;

            if (!string.IsNullOrEmpty(configFile))
            {
                TextAsset conf = LoadTextAsset(configFile);
                if (conf != null)
                {
                    loadedTextAsset = conf;
                    if (loadedTextAsset != null)
                    {
                        SetTextAsset(loadedTextAsset);
                        return;
                    }
                }
            }

            //New name as of 2.3
            loadedTextAsset = LoadTextAsset("TCP2_ShaderTemplate_Default.txt");
            if (loadedTextAsset != null)
            {
                SetTextAsset(loadedTextAsset);
                return;
            }

            //Old legacy name
            loadedTextAsset = LoadTextAsset("TCP2_User_Unity5.txt");
            if (loadedTextAsset != null)
            {
                SetTextAsset(loadedTextAsset);
                return;
            }
        }
Example #21
0
    static private string GetLightingFunction(TCP2_Config config)
    {
        bool customLighting = HasFeatures(config, "CUSTOM_LIGHTING");

        if (customLighting)
        {
            return("ToonyColorsCustom");
        }

        bool specular = HasFeatures(config, "SPECULAR", "SPECULAR_ANISOTROPIC");

        if (specular)
        {
            return("ToonyColorsSpec");
        }
        else
        {
            return("ToonyColors");
        }
    }
Example #22
0
    private void LoadCurrentConfigFromShader(Shader shader)
    {
        mCurrentConfig = TCP2_Config.CreateFromShader(shader);
        if (mCurrentConfig != null)
        {
            mCurrentShader = shader;
            mConfigChoice  = mUserShadersLabels.IndexOf(shader.name);
            mDirtyConfig   = false;
            mCurrentHash   = mCurrentConfig.ToHash();

            //Load appropriate template
            Template.TryLoadTextAsset(mCurrentConfig);
        }
        else
        {
            EditorApplication.Beep();
            this.ShowNotification(new GUIContent("Invalid shader loaded: it doesn't seem to have been generated by the TCP2 Shader Generator!"));
            mCurrentShader = null;
            NewShader();
        }
    }
	//-------------------------------------------------
	
	//Convert Config to ShaderImporter UserData
	static public string ToUserData(this TCP2_Config config, string[] customData)
	{
		string userData = "";
		if(!config.Features.Contains("USER"))
			userData = "USER,";

		foreach(string feature in config.Features)
			if(feature.Contains("USER"))
				userData += string.Format("{0},", feature);
			else
				userData += string.Format("F{0},", feature);
		foreach(string flag in config.Flags)
			userData += string.Format("f{0},", flag);
		foreach(KeyValuePair<string,string> kvp in config.Keywords)
			userData += string.Format("K{0}:{1},", kvp.Key, kvp.Value);
		foreach(string custom in customData)
			userData += string.Format("c{0},", custom);
		userData = userData.TrimEnd(',');

		return userData;
	}
Example #24
0
    static private bool GetMaskDependency(TCP2_Config config, string maskType)
    {
        switch (maskType)
        {
        case "SPEC_MASK": return(HasFeatures(config, "SPECULAR", "SPECULAR_ANISOTROPIC"));

        case "REFL_MASK": return(HasFeatures(config, "REFLECTION"));

        case "MASK_MC": return(HasFeatures(config, "MATCAP"));

        case "SPEC_SHIN_MASK": return(HasFeatures(config, "SPECULAR", "SPECULAR_ANISOTROPIC"));

        case "DETAIL_MASK": return(HasFeatures(config, "DETAIL_TEX"));

        case "RIM_MASK": return(HasFeatures(config, "RIM", "RIM_OUTLINE"));

        case "ILLUMIN_MASK": return(HasFeatures(config, "ILLUMINATION"));

        case "COLORMASK": return(true);
        }
        return(false);
    }
    public static Shader Compile(TCP2_Config config, string template, float progress, bool overwritePrompt, bool modifiedPrompt)
    {
        //UI
        if(progress >= 0f)
            EditorUtility.DisplayProgressBar("Hold On", "Generating Shader: " + config.ShaderName, progress);

        //Generate source
        string source = config.GenerateShaderSource(template);
        if(string.IsNullOrEmpty(source))
        {
            Debug.LogError("[TCP2 Shader Generator] Can't save Shader: source is null or empty!");
            return null;
        }

        //Save to disk
        Shader shader = SaveShader(config, source, overwritePrompt, modifiedPrompt);

        //UI
        if(progress >= 0f)
            EditorUtility.ClearProgressBar();

        return shader;
    }
Example #26
0
    //Generate the source code for the shader as a string
    private static string GenerateShaderSource(this TCP2_Config config, TCP2_ShaderGenerator.ShaderGeneratorTemplate template, Shader existingShader = null)
    {
        if (config == null)
        {
            var error = "[TCP2 Shader Generator] Config file is null";
            Debug.LogError(error);
            return(error);
        }

        if (template == null)
        {
            var error = "[TCP2 Shader Generator] Template is null";
            Debug.LogError(error);
            return(error);
        }

        if (template.textAsset == null || string.IsNullOrEmpty(template.textAsset.text))
        {
            var error = "[TCP2 Shader Generator] Template string is null or empty";
            Debug.LogError(error);
            return(error);
        }

        //------------------------------------------------
        // SHADER PARAMETERS

        //Masks
        bool mask1 = false, mask2 = false, mask3 = false, vcolors_mask = false, mainTex_mask = false;
        var  mask1features = "";
        var  mask2features = "";
        var  mask3features = "";

        //Enable Masks according to their dependencies (new system using Template)
        foreach (var kvp in config.Keywords)
        {
            if (kvp.Value == "mask1")
            {
                var maskEnabled = template.GetMaskDependency(kvp.Key, config);
                mask1 |= maskEnabled;
                if (maskEnabled)
                {
                    mask1features += template.GetMaskDisplayName(kvp.Key) + ",";
                }
            }
            else if (kvp.Value == "mask2")
            {
                var maskEnabled = template.GetMaskDependency(kvp.Key, config);
                mask2 |= maskEnabled;
                if (maskEnabled)
                {
                    mask2features += template.GetMaskDisplayName(kvp.Key) + ",";
                }
            }
            else if (kvp.Value == "mask3")
            {
                var maskEnabled = template.GetMaskDependency(kvp.Key, config);
                mask3 |= maskEnabled;
                if (maskEnabled)
                {
                    mask3features += template.GetMaskDisplayName(kvp.Key) + ",";
                }
            }
            else if (kvp.Value == "IN.color" || kvp.Value == "vcolors")
            {
                vcolors_mask |= template.GetMaskDependency(kvp.Key, config);
            }
            else if (kvp.Value == "mainTex")
            {
                mainTex_mask |= template.GetMaskDependency(kvp.Key, config);
            }
        }

        //Only enable Independent UVs if relevant Mask is actually enabled
        foreach (var kvp in config.Keywords)
        {
            if (kvp.Key == "UV_mask1")
            {
                config.ToggleFeature("UVMASK1", (kvp.Value == "Independent UV" || kvp.Value == "Independent UV0") && mask1);
                config.ToggleFeature("UVMASK1_UV2", kvp.Value == "Independent UV1" && mask1);
            }
            else if (kvp.Key == "UV_mask2")
            {
                config.ToggleFeature("UVMASK2", (kvp.Value == "Independent UV" || kvp.Value == "Independent UV0") && mask2);
                config.ToggleFeature("UVMASK2_UV2", kvp.Value == "Independent UV1" && mask2);
            }
            else if (kvp.Key == "UV_mask3")
            {
                config.ToggleFeature("UVMASK3", (kvp.Value == "Independent UV" || kvp.Value == "Independent UV0") && mask3);
                config.ToggleFeature("UVMASK3_UV2", kvp.Value == "Independent UV1" && mask3);
            }
        }
        mask1features = mask1features.TrimEnd(',');
        mask2features = mask2features.TrimEnd(',');
        mask3features = mask3features.TrimEnd(',');

        config.ToggleFeature("MASK1", mask1);
        config.ToggleFeature("MASK2", mask2);
        config.ToggleFeature("MASK3", mask3);
        config.ToggleFeature("VCOLORS_MASK", vcolors_mask);
        config.ToggleFeature("MASK_MAINTEX", mainTex_mask);

        //---

        var keywords = new Dictionary <string, string>(config.Keywords);
        var flags    = new List <string>(config.Flags);
        var features = new List <string>(config.Features);

        //Unity version
#if UNITY_5_4_OR_NEWER
        TCP2_Utils.AddIfMissing(features, "UNITY_5_4");
#endif
#if UNITY_5_5_OR_NEWER
        TCP2_Utils.AddIfMissing(features, "UNITY_5_5");
#endif
#if UNITY_2017_1_OR_NEWER
        TCP2_Utils.AddIfMissing(features, "UNITY_2017_1");
#endif
#if UNITY_2018_1_OR_NEWER
        TCP2_Utils.AddIfMissing(features, "UNITY_2018_1");
#endif
#if UNITY_2018_2_OR_NEWER
        TCP2_Utils.AddIfMissing(features, "UNITY_2018_2");
#endif

        //Masks
        keywords.Add("MASK1", mask1features);
        keywords.Add("MASK2", mask2features);
        keywords.Add("MASK3", mask3features);

        //Shader name
        keywords.Add("SHADER_NAME", config.ShaderName);

        //Include path
        var include = GetIncludePrefix(config) + GetIncludeRelativePath(config, existingShader).TrimEnd('/');
        keywords.Add("INCLUDE_PATH", include);

        //Shader Model target (old templates)
        if (!keywords.ContainsKey("SHADER_TARGET"))
        {
            var target = GetShaderTarget(config);
            keywords.Add("SHADER_TARGET", target);
            if (config.shaderTarget == 20)
            {
                TCP2_Utils.AddIfMissing(features, "FORCE_SM2");
            }
        }

        //Generate Surface parameters
        var strFlags = ArrayToString(flags.ToArray(), " ");
        keywords.Add("SURF_PARAMS", strFlags);

        //------------------------------------------------
        // PARSING & GENERATION

        var sb            = new StringBuilder();
        var templateLines = template.textAsset.text.Split(new[] { "\r\n", "\n" }, StringSplitOptions.None);

        var depth = -1;
        var stack = new List <bool>();
        var done  = new List <bool>();

        //Parse template file
        string line = null;
        for (var i = 0; i < templateLines.Length; i++)
        {
            line = templateLines[i];

            //Comment
            if (line.StartsWith("#"))
            {
                //Meta
                if (line.StartsWith("#CONFIG="))
                {
                    config.configType = line.Substring(8).TrimEnd().ToLower();
                }

                //Features UI
                if (line.StartsWith("#FEATURES"))
                {
                    while (i < templateLines.Length)
                    {
                        i++;
                        if (templateLines[i] == "#END")
                        {
                            break;
                        }
                    }
                    continue;
                }

                //Keywords
                if (line.StartsWith("#KEYWORDS"))
                {
                    while (i < templateLines.Length)
                    {
                        i++;
                        if (templateLines[i] == "#END")
                        {
                            break;
                        }

                        var error = ProcessKeywords(templateLines[i], config, ref features, ref flags, ref keywords, ref i, ref depth, ref stack, ref done);
                        if (!string.IsNullOrEmpty(error))
                        {
                            return(error);
                        }
                    }

                    //Update Surface parameters
                    strFlags = ArrayToString(flags.ToArray(), " ");
                    if (keywords.ContainsKey("SURF_PARAMS"))
                    {
                        keywords["SURF_PARAMS"] = strFlags;
                    }
                    else
                    {
                        keywords.Add("SURF_PARAMS", strFlags);
                    }
                }

                //Debugging
                if (line.StartsWith("#break"))
                {
                    Debug.Log("[TCP2] Parse Break @ " + i);
                }

                continue;
            }

            //Line break
            if (string.IsNullOrEmpty(line) && ((depth >= 0 && stack[depth]) || depth < 0))
            {
                sb.AppendLine(line);
                continue;
            }

            //Conditions
            if (line.Contains("///"))
            {
                var error = ProcessCondition(line, ref features, ref i, ref depth, ref stack, ref done);
                if (!string.IsNullOrEmpty(error))
                {
                    return(error);
                }
            }
            //Regular line
            else
            {
                //Replace keywords
                line = ReplaceKeywords(line, keywords);

                //Append line if inside valid condition block
                if ((depth >= 0 && stack[depth]) || depth < 0)
                {
                    sb.AppendLine(line);
                }
            }
        }

        if (depth >= 0)
        {
            Debug.LogWarning("[TCP2 Shader Generator] Missing " + (depth + 1) + " ending '///' tags");
        }

        var sourceCode = sb.ToString();

        //Normalize line endings
        sourceCode = sourceCode.Replace("\r\n", "\n");

        return(sourceCode);
    }
Example #27
0
    public static Shader Compile(TCP2_Config config, Shader existingShader, TCP2_ShaderGenerator.ShaderGeneratorTemplate template, float progress, bool overwritePrompt)
    {
        //UI
        if (progress >= 0f)
        {
            EditorUtility.DisplayProgressBar("Hold On", "Generating Shader: " + config.ShaderName, progress);
        }

        //Generate source
        string source = config.GenerateShaderSource(template, existingShader);

        if (string.IsNullOrEmpty(source))
        {
            Debug.LogError("[TCP2 Shader Generator] Can't save Shader: source is null or empty!");
            return(null);
        }

        //Save to disk
        var shader = SaveShader(config, existingShader, source, overwritePrompt, config.isModifiedExternally);

        if (config.configType == "terrain")
        {
            //Generate Base shader
            var baseConfig = config.Copy();
            baseConfig.Filename   = baseConfig.Filename + "_Base";
            baseConfig.ShaderName = "Hidden/" + baseConfig.ShaderName + "-Base";
            baseConfig.Features.Add("TERRAIN_BASE");

            source = baseConfig.GenerateShaderSource(template, existingShader);
            if (string.IsNullOrEmpty(source))
            {
                Debug.LogError("[TCP2 Shader Generator] Can't save Terrain Base Shader: source is null or empty!");
            }
            else
            {
                SaveShader(baseConfig, existingShader, source, false, false);
            }

            //Generate AddPass shader
            var addPassConfig = config.Copy();
            addPassConfig.Filename   = addPassConfig.Filename + "_AddPass";
            addPassConfig.ShaderName = "Hidden/" + addPassConfig.ShaderName + "-AddPass";
            addPassConfig.Features.Add("TERRAIN_ADDPASS");
            addPassConfig.Flags.Add("decal:add");

            source = addPassConfig.GenerateShaderSource(template, existingShader);
            if (string.IsNullOrEmpty(source))
            {
                Debug.LogError("[TCP2 Shader Generator] Can't save Terrain AddPass Shader: source is null or empty!");
            }
            else
            {
                SaveShader(addPassConfig, existingShader, source, false, false);
            }
        }

        //UI
        if (progress >= 0f)
        {
            EditorUtility.ClearProgressBar();
        }

        return(shader);
    }
Example #28
0
    //--------------------------------------------------------------------------------------------------
    // GENERATION

    public static Shader Compile(TCP2_Config config, Shader existingShader, TCP2_ShaderGenerator.ShaderGeneratorTemplate template, bool showProgressBar = true, bool overwritePrompt = true)
    {
        return(Compile(config, existingShader, template, showProgressBar ? 0f : -1f, overwritePrompt));
    }
 private static string GetIncludeFile(TCP2_Config config)
 {
     return "TCP2_Include.cginc";
 }
 private static bool GetMaskDependency(TCP2_Config config, string maskType)
 {
     switch(maskType)
     {
     case "SPEC_MASK": return HasFeatures(config, "SPECULAR", "SPECULAR_ANISOTROPIC");
     case "REFL_MASK": return HasFeatures(config, "REFLECTION");
     case "MASK_MC": return HasFeatures(config, "MATCAP");
     case "SPEC_SHIN_MASK": return HasFeatures(config, "SPECULAR", "SPECULAR_ANISOTROPIC");
     case "DETAIL_MASK": return HasFeatures(config, "DETAIL_TEX");
     case "RIM_MASK": return HasFeatures(config, "RIM","RIM_OUTLINE");
     case "ILLUMIN_MASK": return HasFeatures(config, "ILLUMINATION");
     case "COLORMASK": return true;
     }
     return false;
 }
	private void CopyShader()
	{
		mCurrentShader = null;
		mConfigChoice = 0;
		mIsModified = false;
		TCP2_Config newConfig = new TCP2_Config();
		newConfig.Features = mCurrentConfig.Features;
		newConfig.Flags = mCurrentConfig.Flags;
		newConfig.Keywords = mCurrentConfig.Keywords;
		newConfig.ShaderName = mCurrentConfig.ShaderName + " Copy";
		newConfig.Filename = mCurrentConfig.Filename + " Copy";
		LoadCurrentConfig(newConfig);
	}
Example #32
0
 private static string GetShaderTarget(TCP2_Config config)
 {
     return((config.shaderTarget / 10f).ToString("0.0"));
 }
 public static bool HasFeatures(TCP2_Config config, bool anyFeature, params string[] features)
 {
     return HasFeatures(config.Features, anyFeature, features);
 }
    private static string GetLightingFunction(TCP2_Config config)
    {
        bool customLighting = HasFeatures(config, "CUSTOM_LIGHTING");
        if(customLighting)
            return "ToonyColorsCustom";

        bool specular = HasFeatures(config, "SPECULAR", "SPECULAR_ANISOTROPIC");

        if(specular)
            return "ToonyColorsSpec";
        else
            return "ToonyColors";
    }
 private static string GetSurfaceOutput(TCP2_Config config)
 {
     return "SurfaceOutput";
 }
 public static Shader Compile(TCP2_Config config, string template, bool showProgressBar = true, bool overwritePrompt = true, bool modifiedPrompt = false)
 {
     return Compile(config, template, showProgressBar ? 0f : -1f, overwritePrompt, modifiedPrompt);
 }
 public static string GetKeyword(TCP2_Config config, string key)
 {
     return GetKeyword(config.Keywords, key);
 }
    private static bool NeedCustomAmbient(TCP2_Config config)
    {
        bool occlusion = HasFeatures(config, "OCCLUSION");
        bool cubeambient = HasFeatures(config, "CUBE_AMBIENT");
        bool dirambient = HasFeatures(config, "DIRAMBIENT");

        return cubeambient || occlusion || dirambient;
    }
Example #39
0
    //--------------------------------------------------------------------------------------------------
    // IO

    //Save .shader file
    private static Shader SaveShader(TCP2_Config config, Shader existingShader, string sourceCode, bool overwritePrompt, bool modifiedPrompt)
    {
        if (string.IsNullOrEmpty(config.Filename))
        {
            Debug.LogError("[TCP2 Shader Generator] Can't save Shader: filename is null or empty!");
            return(null);
        }

        //Save file
        var outputPath = OutputPath;
        var filename   = config.Filename;

        //Get existing shader exact path
        if (existingShader != null)
        {
            outputPath = GetExistingShaderPath(config, existingShader);

            /*
             * if(config.Filename.Contains("/"))
             * {
             *      filename = config.Filename.Substring(config.Filename.LastIndexOf('/')+1);
             * }
             */
        }

        var systemPath = Application.dataPath + outputPath;

        if (!Directory.Exists(systemPath))
        {
            Directory.CreateDirectory(systemPath);
        }

        var fullPath  = systemPath + filename + ".shader";
        var overwrite = true;

        if (overwritePrompt && File.Exists(fullPath))
        {
            overwrite = EditorUtility.DisplayDialog("TCP2 : Shader Generation", "The following shader already exists:\n\n" + fullPath + "\n\nOverwrite?", "Yes", "No");
        }

        if (modifiedPrompt)
        {
            overwrite = EditorUtility.DisplayDialog("TCP2 : Shader Generation", "The following shader seems to have been modified externally or manually:\n\n" + fullPath + "\n\nOverwrite anyway?", "Yes", "No");
        }

        if (overwrite)
        {
            var directory = Path.GetDirectoryName(fullPath);
            if (!Directory.Exists(directory))
            {
                Directory.CreateDirectory(directory);
            }

            //Write file to disk
            File.WriteAllText(fullPath, sourceCode, Encoding.UTF8);
            AssetDatabase.Refresh(ImportAssetOptions.ForceSynchronousImport);

            //Import (to compile shader)
            var assetPath = fullPath.Replace(Application.dataPath, "Assets");

            var shader = AssetDatabase.LoadAssetAtPath(assetPath, typeof(Shader)) as Shader;
            if (SelectGeneratedShader)
            {
                Selection.objects = new Object[] { shader };
            }

            //Set ShaderImporter userData
            var shaderImporter = ShaderImporter.GetAtPath(assetPath) as ShaderImporter;
            if (shaderImporter != null)
            {
                //Get file hash to verify if it has been manually altered afterwards
                var shaderHash = GetShaderContentHash(shaderImporter);

                //Use hash if available, else use timestamp
                var customDataList = new List <string>();
                customDataList.Add(!string.IsNullOrEmpty(shaderHash) ? shaderHash : shaderImporter.assetTimeStamp.ToString());
                customDataList.Add(config.GetShaderTargetCustomData());
                var configTypeCustomData = config.GetConfigTypeCustomData();
                if (configTypeCustomData != null)
                {
                    customDataList.Add(configTypeCustomData);
                }
                customDataList.Add(config.GetConfigFileCustomData());

                var userData = config.ToUserData(customDataList.ToArray());
                shaderImporter.userData = userData;

                //Needed to save userData in .meta file
                AssetDatabase.ImportAsset(assetPath, ImportAssetOptions.Default);
            }
            else
            {
                Debug.LogWarning("[TCP2 Shader Generator] Couldn't find ShaderImporter.\nMetadatas will be missing from the shader file.");
            }

            return(shader);
        }

        return(null);
    }
 //--------------------------------------------------------------------------------------------------
 // UTILS
 public static bool HasFeatures(TCP2_Config config, params string[] features)
 {
     return HasFeatures(config, true, features);
 }
    private static string GetShaderTarget(TCP2_Config config)
    {
        bool tessellate = HasFeatures(config, "DX11_TESSELLATION");
        bool forcesm2 = HasFeatures(config, "FORCE_SM2");

        if(forcesm2)
            return "2.0";
        else if(tessellate)
            return "5.0";
        else
            return "3.0";
    }
 private static bool NeedFinalColorFunction(TCP2_Config config)
 {
     return false;
 }
	private void LoadCurrentConfig(TCP2_Config config)
	{
		mCurrentConfig = config;
		mDirtyConfig = false;
		if(mAutoNames)
		{
			AutoNames();
		}
		mCurrentHash = mCurrentConfig.ToHash();
	}
    private static bool NeedVertexFunction(TCP2_Config config)
    {
        bool vFunc = HasFeatures(config, "VERTEX_FUNC");
        bool anisotropic = HasFeatures(config, "SPECULAR_ANISOTROPIC");
        bool matcap = HasFeatures(config, "MATCAP");
        bool sketch = HasFeatures(config, "SKETCH", "SKETCH_GRADIENT");
        bool rimdir = HasFeatures(config, "RIMDIR");
        bool rim = HasFeatures(config, "RIM", "RIM_OUTLINE");
        bool rimvertex = HasFeatures(config, "RIM_VERTEX");
        bool bump = HasFeatures(config, "BUMP");
        bool cstamb = HasFeatures(config, "CUSTOM_AMBIENT");

        return vFunc || matcap || sketch || (rimvertex && rim) || (bump && rimdir && rim) || anisotropic || cstamb;
    }
	private void LoadCurrentConfigFromShader(Shader shader)
	{
		ShaderImporter shaderImporter = ShaderImporter.GetAtPath(AssetDatabase.GetAssetPath(shader)) as ShaderImporter;
		string[] features;
		string[] flags;
		string[] customData;
		Dictionary<string,string> keywords;
		TCP2_ShaderGeneratorUtils.ParseUserData(shaderImporter, out features, out flags, out keywords, out customData);
		if(features != null && features.Length > 0 && features[0] == "USER")
		{
			mCurrentConfig = new TCP2_Config();
			mCurrentConfig.ShaderName = shader.name;
			mCurrentConfig.Filename = System.IO.Path.GetFileName(AssetDatabase.GetAssetPath(shader));
			mCurrentConfig.Features = new List<string>(features);
			mCurrentConfig.Flags = (flags != null) ? new List<string>(flags) : new List<string>();
			mCurrentConfig.Keywords = (keywords != null) ? new Dictionary<string,string>(keywords) : new Dictionary<string,string>();
			mCurrentShader = shader;
			mConfigChoice = mUserShadersLabels.IndexOf(shader.name);
			mDirtyConfig = false;
			AutoNames();
			mCurrentHash = mCurrentConfig.ToHash();

			mIsModified = false;
			if(customData != null && customData.Length > 0)
			{
				foreach(string data in customData)
				{
					//Hash
					if(data.Length > 0 && data[0] == 'h')
					{
						string dataHash = data;
						string fileHash = TCP2_ShaderGeneratorUtils.GetShaderContentHash(shaderImporter);

						if(!string.IsNullOrEmpty(fileHash) && dataHash != fileHash)
						{
							mIsModified = true;
						}
					}
					//Timestamp
					else
					{
						ulong timestamp;
						if(ulong.TryParse(data, out timestamp))
						{
							if(shaderImporter.assetTimeStamp != timestamp)
							{
								mIsModified = true;
							}
						}
					}
				}
			}
		}
		else
		{
			EditorApplication.Beep();
			this.ShowNotification(new GUIContent("Invalid shader loaded: it doesn't seem to have been generated by the TCP2 Shader Generator!"));
			mCurrentShader = null;
			NewShader();
		}
	}
Example #46
0
    //--------------------------------------------------------------------------------------------------
    // GENERATION

    static public Shader Compile(TCP2_Config config, Shader existingShader, string template, bool showProgressBar = true, bool overwritePrompt = true, bool modifiedPrompt = false)
    {
        return(Compile(config, existingShader, template, showProgressBar ? 0f : -1f, overwritePrompt, modifiedPrompt));
    }
Example #47
0
 static public string GetKeyword(TCP2_Config config, string key)
 {
     return(GetKeyword(config.Keywords, key));
 }
    private static bool NeedCustomLighting(TCP2_Config config)
    {
        bool specmask = HasFeatures(config, "SPECULAR_MASK");
        bool anisotropic = HasFeatures(config, "SPECULAR_ANISOTROPIC");
        bool texthreshold = HasFeatures(config, "TEXTURED_THRESHOLD");
        bool occlusion = HasFeatures(config, "OCCLUSION");
        bool indshadows = HasFeatures(config, "INDEPENDENT_SHADOWS");
        bool sketch = HasFeatures(config, "SKETCH", "SKETCH_GRADIENT");
        bool lightmap = HasFeatures(config, "LIGHTMAP");

        return specmask || anisotropic || occlusion || texthreshold || indshadows || sketch || lightmap;
    }
    //--------------------------------------------------------------------------------------------------
    // PRIVATE - SHADER GENERATION
    private static string GetIncludePrefix(TCP2_Config config)
    {
        //Folder
        if(!config.Filename.Contains("/"))
            return "";

        string prefix = "";
        foreach(char c in config.Filename) if(c == '/') prefix += "../";
        return prefix;
    }
    //--------------------------------------------------------------------------------------------------
    // IO
    //Save .shader file
    private static Shader SaveShader(TCP2_Config config, string sourceCode, bool overwritePrompt, bool modifiedPrompt)
    {
        if(string.IsNullOrEmpty(config.Filename))
        {
            Debug.LogError("[TCP2 Shader Generator] Can't save Shader: filename is null or empty!");
            return null;
        }

        //Save file
        string path = Application.dataPath + OUTPUT_PATH;
        if(!System.IO.Directory.Exists(path))
        {
            System.IO.Directory.CreateDirectory(path);
        }

        string fullPath = path + config.Filename + ".shader";
        bool overwrite = true;
        if(overwritePrompt && System.IO.File.Exists(fullPath))
        {
            overwrite = EditorUtility.DisplayDialog("TCP2 : Shader Generation", "The following shader already exists:\n\n" + fullPath + "\n\nOverwrite?", "Yes", "No");
        }

        if(modifiedPrompt)
        {
            overwrite = EditorUtility.DisplayDialog("TCP2 : Shader Generation", "The following shader seems to have been modified externally or manually:\n\n" + fullPath + "\n\nOverwrite anyway?", "Yes", "No");
        }

        if(overwrite)
        {
            string directory = System.IO.Path.GetDirectoryName(path + config.Filename);
            if(!System.IO.Directory.Exists(directory))
            {
                System.IO.Directory.CreateDirectory(directory);
            }

            //Write file to disk
            System.IO.File.WriteAllText(path + config.Filename + ".shader", sourceCode, System.Text.Encoding.UTF8);
            AssetDatabase.Refresh(ImportAssetOptions.ForceSynchronousImport);

            //Import (to compile shader)
            string assetPath = "Assets" + OUTPUT_PATH + config.Filename + ".shader";

            Shader shader = AssetDatabase.LoadAssetAtPath(assetPath, typeof(Shader)) as Shader;
            if(SelectGeneratedShader)
            {
                Selection.objects = new Object[]{ shader };
            }

            //Set ShaderImporter userData
            ShaderImporter shaderImporter = ShaderImporter.GetAtPath(assetPath) as ShaderImporter;
            if(shaderImporter != null)
            {
                //Get file hash to verify if it has been manually altered afterwards
                string shaderHash = GetShaderContentHash(shaderImporter);

                //Use hash if available, else use timestamp
                string[] customData = new string[]{ !string.IsNullOrEmpty(shaderHash) ? shaderHash : shaderImporter.assetTimeStamp.ToString() };

                string userData = config.ToUserData( customData );
                shaderImporter.userData = userData;

                //Needed to save userData in .meta file
                AssetDatabase.ImportAsset(assetPath, ImportAssetOptions.Default);
            }
            else
            {
                Debug.LogWarning("[TCP2 Shader Generator] Couldn't find ShaderImporter.\nMetadatas will be missing from the shader file.");
            }

            return shader;
        }

        return null;
    }