private void UpdateFeaturesFromShader()
    {
        if (targetMaterial != null && targetMaterial.shader != null)
        {
            var name = targetMaterial.shader.name;
            if (name.Contains("Mobile"))
            {
                isMobileShader = true;
            }
            else
            {
                isMobileShader = false;
            }
            var nameFeatures = new List <string>(name.Split(' '));
            for (var i = 0; i < ShaderVariants.Count; i++)
            {
                ShaderVariantsEnabled[i] = nameFeatures.Contains(ShaderVariants[i]);
            }
            //Get flags for compiled shader to hide certain parts of the UI
            var shaderImporter = ShaderImporter.GetAtPath(AssetDatabase.GetAssetPath(targetMaterial.shader)) as ShaderImporter;
            if (shaderImporter != null)
            {
//				mShaderFeatures = new List<string>(shaderImporter.userData.Split(new string[]{","}, System.StringSplitOptions.RemoveEmptyEntries));
                TCP2_ShaderGeneratorUtils.ParseUserData(shaderImporter, out mShaderFeatures);
                if (mShaderFeatures.Count > 0 && mShaderFeatures[0] == "USER")
                {
                    isGeneratedShader = true;
                }
            }
        }
    }
    private Shader[] GetUserShaders()
    {
        var rootPath = Application.dataPath + (sLoadAllShaders ? "" : TCP2_ShaderGeneratorUtils.OutputPath);

        if (Directory.Exists(rootPath))
        {
            var paths      = TCP2_ShaderGeneratorUtils.GetFilesSafe(rootPath, "*.shader");
            var shaderList = new List <Shader>();

            foreach (var path in paths)
            {
#if UNITY_EDITOR_WIN
                var assetPath = "Assets" + path.Replace(@"\", @"/").Replace(Application.dataPath, "");
#else
                string assetPath = "Assets" + path.Replace(Application.dataPath, "");
#endif
                var shaderImporter = ShaderImporter.GetAtPath(assetPath) as ShaderImporter;
                if (shaderImporter != null)
                {
                    if (shaderImporter.userData.Contains("USER"))
                    {
                        var shader = AssetDatabase.LoadAssetAtPath(assetPath, typeof(Shader)) as Shader;
                        if (shader != null && !shaderList.Contains(shader))
                        {
                            shaderList.Add(shader);
                        }
                    }
                }
            }

            return(shaderList.ToArray());
        }

        return(new Shader[0]);
    }
    private TextAsset[] LoadAllTemplates()
    {
        var list = new List <TextAsset>();

        var systemPath = Application.dataPath + @"/JMO Assets/Toony Colors Pro/Editor/Shader Templates/";

        if (!Directory.Exists(systemPath))
        {
            var rootDir = TCP2_Utils.FindReadmePath();
            systemPath = rootDir.Replace(@"\", "/") + "/Editor/Shader Templates/";
        }

        if (Directory.Exists(systemPath))
        {
            var txtFiles = TCP2_ShaderGeneratorUtils.GetFilesSafe(systemPath, "*.txt");

            foreach (var sysPath in txtFiles)
            {
                var unityPath = sysPath;
                if (TCP2_Utils.SystemToUnityPath(ref unityPath))
                {
                    var textAsset = AssetDatabase.LoadAssetAtPath <TextAsset>(unityPath);
                    if (textAsset != null && !list.Contains(textAsset))
                    {
                        list.Add(textAsset);
                    }
                }
            }

            list.Sort((x, y) => x.name.CompareTo(y.name));
            return(list.ToArray());
        }

        return(null);
    }
    public void ToggleFeature(string feature, bool enable)
    {
        if (string.IsNullOrEmpty(feature))
        {
            return;
        }

        TCP2_ShaderGeneratorUtils.ToggleEntry(this.Features, feature, enable);
    }
    private bool GUIMultipleFeaturesInternal(string label, string tooltip, string[] labelsAndFeatures, bool enabled = true, bool increaseIndentLevel = false, string helpTopic = null, bool showHelp = true, float width = 146, bool visible = true)
    {
        if (!enabled)
        {
            GUI.enabled = false;
        }
        if (increaseIndentLevel)
        {
            label = "▪  " + label;
        }

        string[] labels   = new string[labelsAndFeatures.Length];
        string[] features = new string[labelsAndFeatures.Length];

        int feature = 0;

        for (int i = 0; i < labelsAndFeatures.Length; i++)
        {
            string[] data = labelsAndFeatures[i].Split('|');
            labels[i]   = data[0];
            features[i] = data[1];

            if (data.Length > 1 && !string.IsNullOrEmpty(features[i]))
            {
                if (TCP2_ShaderGeneratorUtils.HasFeatures(mCurrentConfig, features[i]))
                {
                    feature = i;
                }
            }
        }

        visible = mHideDisabled ? enabled : visible;

        if (visible)
        {
            string help = string.IsNullOrEmpty(helpTopic) ? label.TrimStart('▪', ' ') : helpTopic;
            EditorGUILayout.BeginHorizontal();
            if (showHelp)
            {
                TCP2_GUI.HelpButton(label.TrimStart('▪', ' '), help);
            }
            TCP2_GUI.SubHeader(label, tooltip, (feature > 0) && enabled, width);
            feature = EditorGUILayout.Popup(feature, labels);
            EditorGUILayout.EndHorizontal();
        }

        TCP2_ShaderGeneratorUtils.ToggleMultipleFeatures(mCurrentConfig.Features, feature, features);

        if (!enabled)
        {
            GUI.enabled = mGUIEnabled;
        }

        return(feature > 0);
    }
    private bool HasFeatOr(params string[] features)
    {
        bool ret = false;

        if (mCurrentConfig != null)
        {
            foreach (string f in features)
            {
                ret |= TCP2_ShaderGeneratorUtils.HasFeatures(mCurrentConfig, f);
            }
        }
        return(ret);
    }
    //--------------------------------------------------------------------------------------------------
    // FEATURES

    private void GUISingleFeature(string featureName, string label, string tooltip = null,
                                  bool enabled     = true, bool increaseIndentLevel = false, bool visible = true,
                                  string helpTopic = null, bool showHelp            = true)
    {
        if (!enabled)
        {
            GUI.enabled = false;
        }
        if (increaseIndentLevel)
        {
            label = "▪  " + label;
        }

        bool feature = TCP2_ShaderGeneratorUtils.HasFeatures(mCurrentConfig, featureName);

        if (mHideDisabled)
        {
            visible = enabled;
        }

        if (visible)
        {
            EditorGUILayout.BeginHorizontal();
            if (increaseIndentLevel)
            {
                TCP2_GUI.SubHeader(label, tooltip, feature && enabled, 165);
                feature = EditorGUILayout.Toggle(feature);
            }
            else
            {
                GUI.enabled = mGUIEnabled;
                if (showHelp)
                {
                    TCP2_GUI.HelpButton(label.TrimStart('▪', ' '), string.IsNullOrEmpty(helpTopic) ? label.TrimStart('▪', ' ') : helpTopic);
                }
                GUI.enabled = enabled;
                TCP2_GUI.SubHeader(label, tooltip, feature && enabled, 145);
                feature = EditorGUILayout.Toggle(feature);
            }
            EditorGUILayout.EndHorizontal();
        }

        TCP2_ShaderGeneratorUtils.ToggleSingleFeature(mCurrentConfig.Features, featureName, feature);

        if (!enabled)
        {
            GUI.enabled = mGUIEnabled;
        }
    }
Exemple #8
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();
        }
    }
    //--------------------------------------------------------------------------------------------------

    public override void AssignNewShaderToMaterial(Material material, Shader oldShader, Shader newShader)
    {
        base.AssignNewShaderToMaterial(material, oldShader, newShader);

        //Detect if User Shader (from Shader Generator)
        isGeneratedShader = false;
        mShaderFeatures   = null;
        ShaderImporter shaderImporter = ShaderImporter.GetAtPath(AssetDatabase.GetAssetPath(newShader)) as ShaderImporter;

        if (shaderImporter != null)
        {
            TCP2_ShaderGeneratorUtils.ParseUserData(shaderImporter, out mShaderFeatures);
            if (mShaderFeatures.Count > 0 && mShaderFeatures[0] == "USER")
            {
                isGeneratedShader = true;
            }
        }
    }
Exemple #10
0
	//--------------------------------------------------------------------------------------------------------------------------------

	public static string FindReadmePath(bool relativeToAssets = false)
	{
		var readmePath = TCP2_ShaderGeneratorUtils.GetFileSafe(Application.dataPath, "!ToonyColorsPro Readme.txt");
		if (readmePath == null)
		{
			return null;
		}

		readmePath = ToSystemSlashPath(Path.GetDirectoryName(readmePath));
		if (relativeToAssets)
		{
#if UNITY_EDITOR_WIN
			readmePath = readmePath.Replace(ToSystemSlashPath(Application.dataPath), "").Replace(@"\", "/");
#else
			readmePath = readmePath.Replace(ToSystemSlashPath(Application.dataPath), "");
#endif
		}
		return readmePath;
	}
Exemple #11
0
    void OnGUI()
    {
        sGUIEnabled = GUI.enabled;

        EditorGUILayout.BeginHorizontal();
        TCP2_GUI.HeaderBig("TOONY COLORS PRO 2 - SHADER GENERATOR");
        TCP2_GUI.HelpButton("Shader Generator");
        EditorGUILayout.EndHorizontal();
        TCP2_GUI.Separator();

        float lW = EditorGUIUtility.labelWidth;

        EditorGUIUtility.labelWidth = 105f;

        //Avoid refreshing Template meta at every Repaint
        EditorGUILayout.BeginHorizontal();
        TextAsset _tmpTemplate = EditorGUILayout.ObjectField("Template:", Template.textAsset, typeof(TextAsset), false) as TextAsset;

        if (_tmpTemplate != Template.textAsset)
        {
            Template.SetTextAsset(_tmpTemplate);
        }
        //Load template
        if (loadTemplateMenu != null)
        {
            if (GUILayout.Button("Load ▼", EditorStyles.miniButton, GUILayout.ExpandWidth(false)))
            {
                loadTemplateMenu.ShowAsContext();
            }
        }
        EditorGUILayout.EndHorizontal();

        //Template not found
        if (Template == null || Template.textAsset == null)
        {
            EditorGUILayout.HelpBox("Couldn't find template file!\n\nVerify that the file 'TCP2_ShaderTemplate_Default.txt' is in your project.\nPlease reimport the pack if you can't find it!", MessageType.Error);
            return;
        }

        //Infobox for custom templates
        if (!string.IsNullOrEmpty(Template.templateInfo))
        {
            EditorGUILayout.HelpBox(Template.templateInfo, MessageType.Info);
        }
        if (!string.IsNullOrEmpty(Template.templateWarning))
        {
            EditorGUILayout.HelpBox(Template.templateWarning, MessageType.Warning);
        }

        TCP2_GUI.Separator();

        EditorGUI.BeginChangeCheck();
        EditorGUILayout.BeginHorizontal();
        mCurrentShader = EditorGUILayout.ObjectField("Current Shader:", mCurrentShader, typeof(Shader), false) as Shader;
        if (EditorGUI.EndChangeCheck())
        {
            if (mCurrentShader != null)
            {
                LoadCurrentConfigFromShader(mCurrentShader);
            }
        }
        if (GUILayout.Button("Copy Shader", EditorStyles.miniButton, GUILayout.Width(78f)))
        {
            CopyShader();
        }
        if (GUILayout.Button("New Shader", EditorStyles.miniButton, GUILayout.Width(76f)))
        {
            NewShader();
        }
        EditorGUILayout.EndHorizontal();

        if (mCurrentConfig.isModifiedExternally)
        {
            EditorGUILayout.HelpBox("It looks like this shader has been modified externally/manually. Updating it will overwrite the changes.", MessageType.Warning);
        }

        if (mUserShaders != null && mUserShaders.Length > 0)
        {
            EditorGUI.BeginChangeCheck();
            int   prevChoice = mConfigChoice;
            Color gColor     = GUI.color;
            GUI.color = mDirtyConfig ? gColor * Color.yellow : GUI.color;
            GUILayout.BeginHorizontal();
            mConfigChoice = EditorGUILayout.Popup("Load Shader:", mConfigChoice, mUserShadersLabels.ToArray());
            if (GUILayout.Button("◄", EditorStyles.miniButtonLeft, GUILayout.Width(22)))
            {
                mConfigChoice--;
                if (mConfigChoice < 1)
                {
                    mConfigChoice = mUserShaders.Length;
                }
            }
            if (GUILayout.Button("►", EditorStyles.miniButtonRight, GUILayout.Width(22)))
            {
                mConfigChoice++;
                if (mConfigChoice > mUserShaders.Length)
                {
                    mConfigChoice = 1;
                }
            }
            GUILayout.EndHorizontal();
            GUI.color = gColor;
            if (EditorGUI.EndChangeCheck() && prevChoice != mConfigChoice)
            {
                bool load = true;
                if (mDirtyConfig)
                {
                    if (mCurrentShader != null)
                    {
                        load = EditorUtility.DisplayDialog("TCP2 : Shader Generation", "You have unsaved changes for the following shader:\n\n" + mCurrentShader.name + "\n\nDiscard the changes and load a new shader?", "Yes", "No");
                    }
                    else
                    {
                        load = EditorUtility.DisplayDialog("TCP2 : Shader Generation", "You have unsaved changes.\n\nDiscard the changes and load a new shader?", "Yes", "No");
                    }
                }

                if (load)
                {
                    //New Shader
                    if (mConfigChoice == 0)
                    {
                        NewShader();
                    }
                    else
                    {
                        //Load selected Shader
                        Shader selectedShader = mUserShaders[mConfigChoice - 1];
                        mCurrentShader = selectedShader;
                        LoadCurrentConfigFromShader(mCurrentShader);
                    }
                }
                else
                {
                    //Revert choice
                    mConfigChoice = prevChoice;
                }
            }
        }

        EditorGUIUtility.labelWidth = lW;

        if (mCurrentConfig == null)
        {
            NewShader();
        }

        //Name & Filename
        TCP2_GUI.Separator();
        GUI.enabled = (mCurrentShader == null);
        EditorGUI.BeginChangeCheck();
        mCurrentConfig.ShaderName = EditorGUILayout.TextField(new GUIContent("Shader Name", "Path will indicate how to find the Shader in Unity's drop-down list"), mCurrentConfig.ShaderName);
        mCurrentConfig.ShaderName = Regex.Replace(mCurrentConfig.ShaderName, @"[^a-zA-Z0-9 _!/]", "");
        if (EditorGUI.EndChangeCheck() && sAutoNames)
        {
            mCurrentConfig.AutoNames();
        }
        GUI.enabled &= !sAutoNames;
        EditorGUILayout.BeginHorizontal();
        mCurrentConfig.Filename = EditorGUILayout.TextField("File Name", mCurrentConfig.Filename);
        mCurrentConfig.Filename = Regex.Replace(mCurrentConfig.Filename, @"[^a-zA-Z0-9 _!/]", "");
        GUILayout.Label(".shader", GUILayout.Width(50f));
        EditorGUILayout.EndHorizontal();
        GUI.enabled = sGUIEnabled;

        Space();

        //########################################################################################################
        // FEATURES

        TCP2_GUI.Header("FEATURES");

        //Scroll view
        mScrollPosition = EditorGUILayout.BeginScrollView(mScrollPosition);
        EditorGUI.BeginChangeCheck();

        if (Template.newSystem)
        {
            //New UI embedded into Template
            Template.FeaturesGUI(mCurrentConfig);
        }
        else
        {
            EditorGUILayout.HelpBox("Old template versions aren't supported anymore.", MessageType.Warning);
        }

#if DEBUG_MODE
        TCP2_GUI.SeparatorBig();

        TCP2_GUI.SubHeaderGray("DEBUG MODE");

        GUILayout.BeginHorizontal();
        mDebugText = EditorGUILayout.TextField("Custom", mDebugText);
        if (GUILayout.Button("Add Feature", EditorStyles.miniButtonLeft, GUILayout.Width(80f)))
        {
            mCurrentConfig.Features.Add(mDebugText);
        }
        if (GUILayout.Button("Add Flag", EditorStyles.miniButtonRight, GUILayout.Width(80f)))
        {
            mCurrentConfig.Flags.Add(mDebugText);
        }

        GUILayout.EndHorizontal();
        GUILayout.Label("Features:");
        GUILayout.BeginHorizontal();
        int count = 0;
        for (int i = 0; i < mCurrentConfig.Features.Count; i++)
        {
            if (count >= 3)
            {
                count = 0;
                GUILayout.EndHorizontal();
                GUILayout.BeginHorizontal();
            }
            count++;
            if (GUILayout.Button(mCurrentConfig.Features[i], EditorStyles.toolbarButton, GUILayout.ExpandWidth(false)))
            {
                mCurrentConfig.Features.RemoveAt(i);
                break;
            }
        }
        GUILayout.EndHorizontal();
        GUILayout.Label("Flags:");
        GUILayout.BeginHorizontal();
        count = 0;
        for (int i = 0; i < mCurrentConfig.Flags.Count; i++)
        {
            if (count >= 3)
            {
                count = 0;
                GUILayout.EndHorizontal();
                GUILayout.BeginHorizontal();
            }
            count++;
            if (GUILayout.Button(mCurrentConfig.Flags[i], EditorStyles.toolbarButton, GUILayout.ExpandWidth(false)))
            {
                mCurrentConfig.Flags.RemoveAt(i);
                break;
            }
        }
        GUILayout.EndHorizontal();
        GUILayout.Label("Keywords:");
        GUILayout.BeginHorizontal();
        count = 0;
        foreach (KeyValuePair <string, string> kvp in mCurrentConfig.Keywords)
        {
            if (count >= 3)
            {
                count = 0;
                GUILayout.EndHorizontal();
                GUILayout.BeginHorizontal();
            }
            count++;
            if (GUILayout.Button(kvp.Key + ":" + kvp.Value, EditorStyles.toolbarButton, GUILayout.ExpandWidth(false)))
            {
                mCurrentConfig.Keywords.Remove(kvp.Key);
                break;
            }
        }
        GUILayout.EndHorizontal();

        //----------------------------------------------------------------

        Space();
        if (mCurrentShader != null)
        {
            if (mCurrentShaderImporter == null)
            {
                mCurrentShaderImporter = ShaderImporter.GetAtPath(AssetDatabase.GetAssetPath(mCurrentShader)) as ShaderImporter;
            }

            if (mCurrentShaderImporter != null && mCurrentShaderImporter.GetShader() == mCurrentShader)
            {
                mDebugExpandUserData = EditorGUILayout.Foldout(mDebugExpandUserData, "Shader UserData");
                if (mDebugExpandUserData)
                {
                    string[] userData = mCurrentShaderImporter.userData.Split(',');
                    foreach (var str in userData)
                    {
                        GUILayout.Label(str);
                    }
                }
            }
        }
#endif

        //Update config
        if (EditorGUI.EndChangeCheck())
        {
            int newHash = mCurrentConfig.ToHash();
            if (newHash != mCurrentHash)
            {
                mDirtyConfig = true;
            }
            else
            {
                mDirtyConfig = false;
            }
        }

        //Scroll view
        EditorGUILayout.EndScrollView();

        Space();

        //GENERATE

        EditorGUILayout.BeginHorizontal();
        GUILayout.FlexibleSpace();
        if (GUILayout.Button(mCurrentShader == null ? "Generate Shader" : "Update Shader", GUILayout.Width(120f), GUILayout.Height(30f)))
        {
            if (Template == null)
            {
                EditorUtility.DisplayDialog("TCP2 : Shader Generation", "Can't generate shader: no Template file defined!\n\nYou most likely want to link the TCP2_User.txt file to the Template field in the Shader Generator.", "Ok");
                return;
            }

            //Set config type
            if (Template.templateType != null)
            {
                mCurrentConfig.configType = Template.templateType;
            }

            //Set config file
            mCurrentConfig.templateFile = Template.textAsset.name;

            Shader generatedShader = TCP2_ShaderGeneratorUtils.Compile(mCurrentConfig, mCurrentShader, Template, true, !sOverwriteConfigs);
            ReloadUserShaders();
            if (generatedShader != null)
            {
                mDirtyConfig = false;
                LoadCurrentConfigFromShader(generatedShader);
            }
        }
        EditorGUILayout.EndHorizontal();
        TCP2_GUI.Separator();

        // OPTIONS
        TCP2_GUI.Header("OPTIONS");

        GUILayout.BeginHorizontal();
        sSelectGeneratedShader = GUILayout.Toggle(sSelectGeneratedShader, new GUIContent("Select Generated Shader", "Will select the generated file in the Project view"), GUILayout.Width(180f));
        sAutoNames             = GUILayout.Toggle(sAutoNames, new GUIContent("Automatic Name", "Will automatically generate the shader filename based on its UI name"), GUILayout.ExpandWidth(false));
        GUILayout.EndHorizontal();
        GUILayout.BeginHorizontal();
        sOverwriteConfigs = GUILayout.Toggle(sOverwriteConfigs, new GUIContent("Always overwrite shaders", "Overwrite shaders when generating/updating (no prompt)"), GUILayout.Width(180f));
        sHideDisabled     = GUILayout.Toggle(sHideDisabled, new GUIContent("Hide disabled fields", "Hide properties settings when they cannot be accessed"), GUILayout.ExpandWidth(false));
        GUILayout.EndHorizontal();

        EditorGUILayout.BeginHorizontal();
        EditorGUI.BeginChangeCheck();
        TCP2_ShaderGeneratorUtils.CustomOutputDir = GUILayout.Toggle(TCP2_ShaderGeneratorUtils.CustomOutputDir, new GUIContent("Custom Output Directory:", "Will save the generated shaders in a custom directory within the Project"), GUILayout.Width(165f));
        GUI.enabled &= TCP2_ShaderGeneratorUtils.CustomOutputDir;
        if (TCP2_ShaderGeneratorUtils.CustomOutputDir)
        {
            TCP2_ShaderGeneratorUtils.OutputPath = EditorGUILayout.TextField("", TCP2_ShaderGeneratorUtils.OutputPath);
            if (GUILayout.Button("Select...", EditorStyles.miniButton, GUILayout.ExpandWidth(false)))
            {
                string path = EditorUtility.OpenFolderPanel("Choose custom output directory for TCP2 generated shaders", Application.dataPath, "");
                if (!string.IsNullOrEmpty(path))
                {
                    bool validPath = TCP2_Utils.SystemToUnityPath(ref path);
                    if (validPath)
                    {
                        if (path == "Assets")
                        {
                            TCP2_ShaderGeneratorUtils.OutputPath = "/";
                        }
                        else
                        {
                            TCP2_ShaderGeneratorUtils.OutputPath = path.Substring("Assets/".Length);
                        }
                    }
                    else
                    {
                        EditorApplication.Beep();
                        EditorUtility.DisplayDialog("Invalid Path", "The selected path is invalid.\n\nPlease select a folder inside the \"Assets\" folder of your project!", "Ok");
                    }
                }
            }
        }
        else
        {
            EditorGUILayout.TextField("", TCP2_ShaderGeneratorUtils.OUTPUT_PATH);
        }
        if (EditorGUI.EndChangeCheck())
        {
            ReloadUserShaders();
        }

        GUI.enabled = sGUIEnabled;
        EditorGUILayout.EndHorizontal();

        EditorGUI.BeginChangeCheck();
        sLoadAllShaders = GUILayout.Toggle(sLoadAllShaders, new GUIContent("Reload Shaders from all Project", "Load shaders from all your Project folders instead of just Toony Colors Pro 2.\nEnable it if you move your generated shader files outside of the default TCP2 Generated folder."), GUILayout.ExpandWidth(false));
        if (EditorGUI.EndChangeCheck())
        {
            ReloadUserShaders();
        }

        TCP2_ShaderGeneratorUtils.SelectGeneratedShader = sSelectGeneratedShader;
    }
Exemple #12
0
 public bool HasFlagsAny(params string[] flags)
 {
     return(TCP2_ShaderGeneratorUtils.HasAnyEntries(Flags, flags));
 }
 private bool HasFeat(string feature)
 {
     return(mCurrentConfig != null && TCP2_ShaderGeneratorUtils.HasFeatures(mCurrentConfig, feature));
 }
    private bool GUIMask(string label, string tooltip, string maskKeyword, string channelKeyword, string feature = null, bool enabled = true, bool increaseIndentLevel = false, bool visible = true, string helpTopic = null)
    {
        string[] labelsAndKeywords = new string[] {
            "Off|",
            "Main Texture|mainTex",
            "Mask 1|mask1", "Mask 2|mask2", "Mask 3|mask3"
        };

        if (!enabled)
        {
            GUI.enabled = false;
        }
        if (increaseIndentLevel)
        {
            label = "▪  " + label;
        }

        string[] labels = new string[labelsAndKeywords.Length];
        string[] masks  = new string[labelsAndKeywords.Length];
        string[] uvs    = new string[] { "Main Tex UV", "Independent UV" };

        for (int i = 0; i < labelsAndKeywords.Length; i++)
        {
            string[] data = labelsAndKeywords[i].Split('|');
            labels[i] = data[0];
            masks[i]  = data[1];
        }

        int curMask = System.Array.IndexOf(masks, TCP2_ShaderGeneratorUtils.GetKeyword(mCurrentConfig, maskKeyword));

        if (curMask < 0)
        {
            curMask = 0;
        }
        TCP2_Utils.TextureChannel curChannel = TCP2_Utils.FromShader(TCP2_ShaderGeneratorUtils.GetKeyword(mCurrentConfig, channelKeyword));
        if (curMask <= 1)
        {
            curChannel = TCP2_Utils.TextureChannel.Alpha;
        }
        string uvKey = (curMask > 1) ? "UV_" + masks[curMask] : null;
        int    curUv = System.Array.IndexOf(uvs, TCP2_ShaderGeneratorUtils.GetKeyword(mCurrentConfig, uvKey));

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

        if (mHideDisabled)
        {
            visible = enabled;
        }

        if (visible)
        {
            EditorGUILayout.BeginHorizontal();
            float w = 166;
            if (!string.IsNullOrEmpty(helpTopic))
            {
                w -= 20;
                TCP2_GUI.HelpButton(label.TrimStart('▪', ' '), helpTopic);
            }
            TCP2_GUI.SubHeader(label, tooltip, (curMask > 0) && enabled, w);
            curMask     = EditorGUILayout.Popup(curMask, labels);
            GUI.enabled = curMask > 1;
            curChannel  = (TCP2_Utils.TextureChannel)EditorGUILayout.EnumPopup(curChannel);
            curUv       = EditorGUILayout.Popup(curUv, uvs);
            GUI.enabled = mGUIEnabled;
            TCP2_GUI.HelpButton("Masks");
            EditorGUILayout.EndHorizontal();
        }

        TCP2_ShaderGeneratorUtils.SetKeyword(mCurrentConfig.Keywords, maskKeyword, masks[curMask]);
        if (curMask > 0)
        {
            TCP2_ShaderGeneratorUtils.SetKeyword(mCurrentConfig.Keywords, channelKeyword, curChannel.ToShader());
        }
        if (curMask > 1 && !string.IsNullOrEmpty(uvKey))
        {
            TCP2_ShaderGeneratorUtils.SetKeyword(mCurrentConfig.Keywords, uvKey, uvs[curUv]);
        }
        TCP2_ShaderGeneratorUtils.ToggleSingleFeature(mCurrentConfig.Features, feature, (curMask > 0));

        if (!enabled)
        {
            GUI.enabled = mGUIEnabled;
        }

        return(curMask > 0);
    }
Exemple #15
0
    bool ParseUserData(ShaderImporter importer)
    {
        if (string.IsNullOrEmpty(importer.userData))
        {
            return(false);
        }

        string[]      data           = importer.userData.Split(new string[] { "," }, System.StringSplitOptions.RemoveEmptyEntries);
        List <string> customDataList = new List <string>();

        foreach (string d in data)
        {
            if (string.IsNullOrEmpty(d))
            {
                continue;
            }

            switch (d[0])
            {
            //Features
            case 'F':
                if (d == "F")
                {
                    break;                                  //Prevent getting "empty" feature
                }
                this.Features.Add(d.Substring(1));
                break;

            //Flags
            case 'f': this.Flags.Add(d.Substring(1)); break;

            //Keywords
            case 'K':
                string[] kw = d.Substring(1).Split(':');
                if (kw.Length != 2)
                {
                    Debug.LogError("[TCP2 Shader Generator] Error while parsing userData: invalid Keywords format.");
                    return(false);
                }
                else
                {
                    this.Keywords.Add(kw[0], kw[1]);
                }
                break;

            //Custom Data
            case 'c': customDataList.Add(d.Substring(1)); break;

            //old format
            default: this.Features.Add(d); break;
            }
        }

        foreach (string customData in customDataList)
        {
            //Hash
            if (customData.Length > 0 && customData[0] == 'h')
            {
                string dataHash = customData;
                string fileHash = TCP2_ShaderGeneratorUtils.GetShaderContentHash(importer);

                if (!string.IsNullOrEmpty(fileHash) && dataHash != fileHash)
                {
                    this.isModifiedExternally = true;
                }
            }
            //Timestamp
            else
            {
                ulong timestamp;
                if (ulong.TryParse(customData, out timestamp))
                {
                    if (importer.assetTimeStamp != timestamp)
                    {
                        this.isModifiedExternally = true;
                    }
                }
            }

            //Shader Model target
            if (customData.StartsWith("SM:"))
            {
                this.shaderTarget = int.Parse(customData.Substring(3));
            }

            //Configuration Type
            if (customData.StartsWith("CT:"))
            {
                this.configType = customData.Substring(3);
            }

            //Configuration File
            if (customData.StartsWith("CF:"))
            {
                this.templateFile = customData.Substring(3);
            }
        }

        return(true);
    }
    static public TCP2_Config CreateFromShader(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")
        {
            var config = new TCP2_Config();
            config.ShaderName = shader.name;
            config.Filename   = System.IO.Path.GetFileName(AssetDatabase.GetAssetPath(shader));
            config.Features   = new List <string>(features);
            config.Flags      = (flags != null) ? new List <string>(flags) : new List <string>();
            config.Keywords   = (keywords != null) ? new Dictionary <string, string>(keywords) : new Dictionary <string, string>();
            config.AutoNames();

            //mCurrentShader = shader;
            //mConfigChoice = mUserShadersLabels.IndexOf(shader.name);
            //mDirtyConfig = false;
            //AutoNames();
            //mCurrentHash = mCurrentConfig.ToHash();

            config.isModifiedExternally = 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)
                        {
                            config.isModifiedExternally = true;
                        }
                    }
                    //Timestamp
                    else
                    {
                        ulong timestamp;
                        if (ulong.TryParse(data, out timestamp))
                        {
                            if (shaderImporter.assetTimeStamp != timestamp)
                            {
                                config.isModifiedExternally = true;
                            }
                        }
                    }

                    //Shader Model target
                    if (data.StartsWith("SM:"))
                    {
                        config.shaderTarget = int.Parse(data.Substring(3));
                    }

                    //Configuration Type
                    if (data.StartsWith("CT:"))
                    {
                        config.configType = data.Substring(3);
                    }

                    //Configuration File
                    if (data.StartsWith("CF:"))
                    {
                        config.templateFile = data.Substring(3);
                    }
                }
            }

            return(config);
        }
        else
        {
            return(null);
        }
    }
    void OnGUI()
    {
        EditorGUILayout.BeginHorizontal();
        TCP2_GUI.HeaderBig("TOONY COLORS PRO 2 - SHADER GENERATOR");
        TCP2_GUI.HelpButton("Shader Generator");
        EditorGUILayout.EndHorizontal();
        TCP2_GUI.Separator();

        float lW = EditorGUIUtility.labelWidth;

        EditorGUIUtility.labelWidth = 105f;

        EditorGUI.BeginChangeCheck();
        EditorGUILayout.BeginHorizontal();
        mCurrentShader = EditorGUILayout.ObjectField("Current Shader:", mCurrentShader, typeof(Shader), false) as Shader;
        if (EditorGUI.EndChangeCheck())
        {
            if (mCurrentShader != null)
            {
                LoadCurrentConfigFromShader(mCurrentShader);
            }
        }
        if (GUILayout.Button("Copy Shader", EditorStyles.miniButton, GUILayout.Width(78f)))
        {
            CopyShader();
        }
        if (GUILayout.Button("New Shader", EditorStyles.miniButton, GUILayout.Width(76f)))
        {
            NewShader();
        }
        EditorGUILayout.EndHorizontal();

        if (mIsModified)
        {
            EditorGUILayout.HelpBox("It looks like this shader has been modified externally/manually. Updating it will overwrite the changes.", MessageType.Warning);
        }

        if (mUserShaders != null && mUserShaders.Length > 0)
        {
            EditorGUI.BeginChangeCheck();
            int   prevChoice = mConfigChoice;
            Color gColor     = GUI.color;
            GUI.color = mDirtyConfig ? gColor * Color.yellow : GUI.color;
            GUILayout.BeginHorizontal();
            mConfigChoice = EditorGUILayout.Popup("Load Shader:", mConfigChoice, mUserShadersLabels.ToArray());
            if (GUILayout.Button("◄", EditorStyles.miniButtonLeft, GUILayout.Width(22)))
            {
                mConfigChoice--;
                if (mConfigChoice < 1)
                {
                    mConfigChoice = mUserShaders.Length;
                }
            }
            if (GUILayout.Button("►", EditorStyles.miniButtonRight, GUILayout.Width(22)))
            {
                mConfigChoice++;
                if (mConfigChoice > mUserShaders.Length)
                {
                    mConfigChoice = 1;
                }
            }
            GUILayout.EndHorizontal();
            GUI.color = gColor;
            if (EditorGUI.EndChangeCheck() && prevChoice != mConfigChoice)
            {
                bool load = true;
                if (mDirtyConfig)
                {
                    if (mCurrentShader != null)
                    {
                        load = EditorUtility.DisplayDialog("TCP2 : Shader Generation", "You have unsaved changes for the following shader:\n\n" + mCurrentShader.name + "\n\nDiscard the changes and load a new shader?", "Yes", "No");
                    }
                    else
                    {
                        load = EditorUtility.DisplayDialog("TCP2 : Shader Generation", "You have unsaved changes.\n\nDiscard the changes and load a new shader?", "Yes", "No");
                    }
                }

                if (load)
                {
                    //New Shader
                    if (mConfigChoice == 0)
                    {
                        NewShader();
                    }
                    else
                    {
                        //Load selected Shader
                        Shader selectedShader = mUserShaders[mConfigChoice - 1];
                        mCurrentShader = selectedShader;
                        LoadCurrentConfigFromShader(mCurrentShader);
                    }
                }
                else
                {
                    //Revert choice
                    mConfigChoice = prevChoice;
                }
            }
        }

        Template = EditorGUILayout.ObjectField("Template:", Template, typeof(TextAsset), false) as TextAsset;
        EditorGUIUtility.labelWidth = lW;

        if (mCurrentConfig == null)
        {
            NewShader();
        }
        mGUIEnabled = GUI.enabled;

        //Name & Filename
        TCP2_GUI.Header("NAME");
        GUI.enabled = (mCurrentShader == null);
        EditorGUI.BeginChangeCheck();
        mCurrentConfig.ShaderName = EditorGUILayout.TextField(new GUIContent("Shader Name", "Path will indicate how to find the Shader in Unity's drop-down list"), mCurrentConfig.ShaderName);
        mCurrentConfig.ShaderName = Regex.Replace(mCurrentConfig.ShaderName, @"[^a-zA-Z0-9 _!/]", "");
        if (EditorGUI.EndChangeCheck() && mAutoNames)
        {
            AutoNames();
        }
        GUI.enabled &= !mAutoNames;
        EditorGUILayout.BeginHorizontal();
        mCurrentConfig.Filename = EditorGUILayout.TextField("File Name", mCurrentConfig.Filename);
        mCurrentConfig.Filename = Regex.Replace(mCurrentConfig.Filename, @"[^a-zA-Z0-9 _!/]", "");
        GUILayout.Label(".shader", GUILayout.Width(50f));
        EditorGUILayout.EndHorizontal();
        GUI.enabled = mGUIEnabled;

        Space();

        //########################################################################################################
        // FEATURES
        TCP2_GUI.Header("FEATURES");

        //Scroll view
        mScrollPosition = EditorGUILayout.BeginScrollView(mScrollPosition);
        EditorGUI.BeginChangeCheck();

#if DEBUG_MODE
        //Custom Lighting
        GUISingleFeature("CUSTOM_LIGHTING_FORCE", "Custom Lighting", "Use an inline custom lighting model, allowing more flexibility per shader over lighting");
        GUISingleFeature("VERTEX_FUNC", "Vertex Function", "Force custom vertex function in surface shader");
        Space();
        //----------------------------------------------------------------
#endif
        //Ramp
        GUIMultipleFeatures("Ramp Style", "Defines the transitioning between dark and lit areas of the model", "Slider Ramp|", "Texture Ramp|TEXTURE_RAMP");
        //Textured Threshold
        GUISingleFeature("TEXTURED_THRESHOLD", "Textured Threshold", "Adds a textured variation to the highlight/shadow threshold, allowing handpainting like effects for example");
        Space();
        //----------------------------------------------------------------
        //Detail
        GUISingleFeature("DETAIL_TEX", "Detail Texture");
        //Detail UV2
        GUISingleFeature("DETAIL_UV2", "Use UV2 coordinates", "Use second texture coordinates for the detail texture", HasFeat("DETAIL_TEX"), true);
        GUIMask("Detail Mask", null, "DETAIL_MASK", "DETAIL_MASK_CHANNEL", "DETAIL_MASK", HasFeatOr("DETAIL_TEX"), true);
        Space();
        //----------------------------------------------------------------
        //Color Mask
        GUIMask("Color Mask", "Adds a mask to the main Color", "COLORMASK", "COLORMASK_CHANNEL", "COLORMASK", true, helpTopic: "Color Mask");
        Space();
        //----------------------------------------------------------------
        //Vertex Colors
        GUISingleFeature("VCOLORS", "Vertex Colors", "Multiplies the color with vertex colors");
        //Texture Blend
        GUISingleFeature("VCOLORS_BLENDING", "Vertex Texture Blending", "Enables 2-way texture blending based on the mesh's vertex color alpha");
        Space();
        //----------------------------------------------------------------
        //Self-Illumination
        GUIMask("Self-Illumination Map", null, "ILLUMIN_MASK", "ILLUMIN_MASK_CHANNEL", "ILLUMINATION", helpTopic: "Self-Illumination Map");
        //Self-Illumination Color
        GUISingleFeature("ILLUM_COLOR", "Self-Illumination Color", null, HasFeat("ILLUMINATION"), true);
        Space();
        //----------------------------------------------------------------
        //Bump
        GUISingleFeature("BUMP", "Normal/Bump map", helpTopic: "normal_bump_map_sg");
        //Parallax
        GUISingleFeature("PARALLAX", "Parallax/Height map", null, HasFeat("BUMP"), true);
        Space();
        //----------------------------------------------------------------
        //Occlusion
//		GUISingleFeature("OCCLUSION", "Occlusion Map", "Use an Occlusion Map that will be multiplied with the Ambient lighting");
        //Occlusion RGB
//		GUISingleFeature("OCCL_RGB", "Use RGB map", "Use the RGB channels for Occlusion Map if enabled, use Alpha channel is disabled", HasFeat("OCCLUSION"), true);
//		Space();
        //----------------------------------------------------------------
        //Specular
        GUIMultipleFeaturesHelp("Specular", null, "specular_sg", "Off|", "Regular|SPECULAR", "Anisotropic|SPECULAR_ANISOTROPIC");
        if (HasFeatAnd("FORCE_SM2", "SPECULAR_ANISOTROPIC"))
        {
            EditorGUILayout.HelpBox("Anisotropic Specular will not compile with Shader Model 2!\n(too many instructions used)", MessageType.Warning);
        }
        //Specular Mask
        GUIMask("Specular Mask", "Enables specular mask (gloss map)", "SPEC_MASK", "SPEC_MASK_CHANNEL", "SPECULAR_MASK", HasFeatOr("SPECULAR", "SPECULAR_ANISOTROPIC"), true);
        //Specular Shininess Mask
        GUIMask("Shininess Mask", null, "SPEC_SHIN_MASK", "SPEC_SHIN_MASK_CHANNEL", "SPEC_SHIN_MASK", HasFeatOr("SPECULAR", "SPECULAR_ANISOTROPIC"), true);
        //Cartoon Specular
        GUISingleFeature("SPECULAR_TOON", "Cartoon Specular", "Enables clear delimitation of specular color", HasFeatOr("SPECULAR", "SPECULAR_ANISOTROPIC"), true);
        Space();
        //----------------------------------------------------------------
        //Reflection
        GUISingleFeature("REFLECTION", "Reflection", "Enables cubemap reflection", helpTopic: "reflection_sg");
        //Reflection Mask
        GUIMask("Reflection Mask", null, "REFL_MASK", "REFL_MASK_CHANNEL", "REFL_MASK", HasFeatOr("REFLECTION"), true);
#if UNITY_5
        //Unity5 Reflection Probes
        GUISingleFeature("U5_REFLPROBE", "Reflection Probes (Unity5)", "Pick reflection from Unity 5 Reflection Probes", HasFeat("REFLECTION"), true, helpTopic: "Reflection Probes");
#endif
        //Reflection Color
        GUISingleFeature("REFL_COLOR", "Reflection Color", "Enables reflection color control", HasFeat("REFLECTION"), true);
        //Reflection Roughness
        GUISingleFeature("REFL_ROUGH", "Reflection Roughness", "Simulates reflection roughness using the Cubemap's LOD levels\n\nREQUIRES MipMaps ENABLED IN THE CUBEMAP TEXTURE!", HasFeat("REFLECTION") && !HasFeat("U5_REFLPROBE"), true);
        //Rim Reflection
        GUISingleFeature("RIM_REFL", "Rim Reflection/Fresnel", "Reflection will be multiplied by rim lighting, resulting in a fresnel-like effect", HasFeat("REFLECTION"), true);
        Space();
        //----------------------------------------------------------------
        //Cubemap Ambient
        GUIMultipleFeaturesInternal("Custom Ambient", "Custom ambient lighting", new string[] { "Off|", "Cubemap Ambient|CUBE_AMBIENT", "Directional Ambient|DIRAMBIENT" });
        Space();
        //----------------------------------------------------------------
        //Independent Shadows
        GUISingleFeature("INDEPENDENT_SHADOWS", "Independent Shadows", "Disable shadow color influence for cast shadows");
        Space();
        //----------------------------------------------------------------
        //Rim
        GUIMultipleFeaturesInternal("Rim", "Rim effects (fake light coming from behind the model)", new string[] { "Off|", "Rim Lighting|RIM", "Rim Outline|RIM_OUTLINE" }, !(HasFeatAnd("REFLECTION", "RIM_REFL")), false, "rim_sg");
        if (HasFeat("REFLECTION") && HasFeat("RIM_REFL"))
        {
            TCP2_ShaderGeneratorUtils.ToggleSingleFeature(mCurrentConfig.Features, "RIM", true);
        }
        //Vertex Rim
        GUISingleFeature("RIM_VERTEX", "Vertex Rim", "Compute rim lighting per-vertex (faster but innacurate)", HasFeatOr("RIM", "RIM_OUTLINE"), true);
        //Directional Rim
        GUISingleFeature("RIMDIR", "Directional Rim", null, HasFeatOr("RIM", "RIM_OUTLINE"), true);
        //Rim Mask
        GUIMask("Rim Mask", null, "RIM_MASK", "RIM_MASK_CHANNEL", "RIM_MASK", HasFeatOr("RIM", "RIM_OUTLINE"), true);
        Space();
        //----------------------------------------------------------------
        //MatCap
        GUIMultipleFeaturesHelp("MatCap", "MatCap effects (fast fake reflection using a spherical texture)", "matcap_sg", "Off|", "MatCap Add|MATCAP_ADD", "MatCap Multiply|MATCAP_MULT");
        //MatCap Mask
        GUIMask("MatCap Mask", null, "MASK_MC", "MASK_MC_CHANNEL", "MASK_MC", HasFeatOr("MATCAP_ADD", "MATCAP_MULT"), true);
        //MatCap Pixel
        GUISingleFeature("MATCAP_PIXEL", "Pixel MatCap", "If enabled, will calculate MatCap per-pixel\nRequires normal map", HasFeat("BUMP") && HasFeatOr("MATCAP_ADD", "MATCAP_MULT"), true);
        //MatCap Color
        GUISingleFeature("MC_COLOR", "MatCap Color", null, HasFeatOr("MATCAP_ADD", "MATCAP_MULT"), true);
        Space();
        //----------------------------------------------------------------
        //Sketch
        GUIMultipleFeatures("Sketch", "Sketch texture overlay on the shadowed areas\nOverlay: regular texture overlay\nGradient: used for halftone-like effects", "Off|", "Sketch Overlay|SKETCH", "Sketch Gradient|SKETCH_GRADIENT");
        //Sketch Blending
        GUIMultipleFeaturesInternal("Sketch Blending", "Defines how to blend the Sketch texture with the model",
                                    new string[] { "Regular|", "Color Burn|SKETCH_COLORBURN" },
                                    HasFeat("SKETCH") && !HasFeat("SKETCH_GRADIENT"), true, null, false, 166);
        //Sketch Anim
        GUISingleFeature("SKETCH_ANIM", "Animated Sketch", "Animates the sketch overlay texture, simulating a hand-drawn animation style",
                         HasFeatOr("SKETCH", "SKETCH_GRADIENT"), true);
        //Sketch Vertex
        GUISingleFeature("SKETCH_VERTEX", "Vertex Coords", "Compute screen coordinates in vertex shader (faster but can cause distortions)\nIf disabled will compute in pixel shader (slower)",
                         HasFeatOr("SKETCH", "SKETCH_GRADIENT"), true);
        //Sketch Scale
        GUISingleFeature("SKETCH_SCALE", "Scale with model", "If enabled, overlay texture scale will depend on model's distance from view",
                         HasFeatOr("SKETCH", "SKETCH_GRADIENT"), true);
        Space();
        //----------------------------------------------------------------
        //Outline
        GUIMultipleFeatures("Outline", "Outline around the model", "Off|", "Opaque Outline|OUTLINE", "Blended Outline|OUTLINE_BLENDING");
        GUISingleFeature("OUTLINE_BEHIND", "Outline behind model", "If enabled, outline will only show behind model",
                         HasFeatOr("OUTLINE", "OUTLINE_BLENDING"), true);
        Space();
        //----------------------------------------------------------------
        //Lightmaps
        GUISingleFeature("LIGHTMAP", "TCP2 Lightmap", "Will use TCP2's lightmap decoding, affecting it with ramp and color settings", helpTopic: "Lightmap");
        Space();
        //----------------------------------------------------------------
        //Alpha Blending
        GUISingleFeature("ALPHA", "Alpha Blending");
        //Alpha Testing
        GUISingleFeature("CUTOUT", "Alpha Testing (Cutout)");
        Space();
        //----------------------------------------------------------------
        //Culling
        int cull = TCP2_ShaderGeneratorUtils.HasFeatures(mCurrentConfig, "CULL_FRONT") ? 1 : TCP2_ShaderGeneratorUtils.HasFeatures(mCurrentConfig, "CULL_OFF") ? 2 : 0;
        EditorGUILayout.BeginHorizontal();
        TCP2_GUI.SubHeader("Culling", "Defines how to cull faces", cull > 0, 166);
        cull = EditorGUILayout.Popup(cull, new string[] { "Default", "Front", "Off (double-sided)" });
        TCP2_ShaderGeneratorUtils.ToggleSingleFeature(mCurrentConfig.Features, "CULL_FRONT", cull == 1);
        TCP2_ShaderGeneratorUtils.ToggleSingleFeature(mCurrentConfig.Features, "CULL_OFF", cull == 2);
        EditorGUILayout.EndHorizontal();
        Space();
        //----------------------------------------------------------------

        //########################################################################################################
        // FLAGS
        TCP2_GUI.Header("FLAGS");
        GUISingleFlag("addshadow", "Add Shadow Passes", "Force the shader to have the Shadow Caster and Collector passes.\nCan help if shadows don't work properly with the shader");
        GUISingleFlag("fullforwardshadows", "Full Forward Shadows", "Enable support for all shadow types in Forward rendering path");
#if UNITY_5
        GUISingleFlag("noshadow", "Disable Shadows", "Disables all shadow receiving support in this shader");
        GUISingleFlag("nofog", "Disable Fog", "Disables Unity Fog support.\nCan help if you run out of vertex interpolators and don't need lightmaps!");
#endif
        GUISingleFlag("nolightmap", "Disable Lightmaps", "Disables all lightmapping support in this shader.\nCan help if you run out of vertex interpolators and don't need lightmaps!");
        GUISingleFlag("noambient", "Disable Ambient Lighting", "Enable support for all shadow types in Forward rendering path", !HasFeatOr("DIRAMBIENT", "CUBE_AMBIENT", "OCCLUSION"));
        GUISingleFlag("novertexlights", "Disable Vertex Lighting", "Disable vertex lights and spherical harmonics (light probes)");
        GUISingleFeature("FORCE_SM2", "Force Shader Model 2", "Compile with Shader Model 2 target. Useful for (very) old GPU compatibility, but some features may not work with it.", showHelp: false);

        TCP2_GUI.Header("FLAGS (Mobile-friendly)", null, true);
        GUISingleFlag("noforwardadd", "One Directional Light", "Use additive lights as vertex lights.\nRecommended for Mobile");
#if UNITY_5
        GUISingleFlag("interpolateview", "Vertex View Dir", "Calculate view direction per-vertex instead of per-pixel.\nRecommended for Mobile");
#else
        GUISingleFlag("approxview", "Vertex View Dir", "Calculate view direction per-vertex instead of per-pixel.\nRecommended for Mobile");
#endif
        GUISingleFlag("halfasview", "Half as View", "Pass half-direction vector into the lighting function instead of view-direction.\nFaster but inaccurate.\nRecommended for Specular, but use Vertex Rim to optimize Rim Effects instead");

#if DEBUG_MODE
        TCP2_GUI.SeparatorBig();
        GUILayout.BeginHorizontal();
        mDebugText = EditorGUILayout.TextField("Debug", mDebugText);
        if (GUILayout.Button("Add Feature", EditorStyles.miniButtonLeft, GUILayout.Width(80f)))
        {
            mCurrentConfig.Features.Add(mDebugText);
        }
        if (GUILayout.Button("Add Flag", EditorStyles.miniButtonRight, GUILayout.Width(80f)))
        {
            mCurrentConfig.Flags.Add(mDebugText);
        }

        GUILayout.EndHorizontal();
        GUILayout.Label("Features:");
        GUILayout.BeginHorizontal();
        int count = 0;
        for (int i = 0; i < mCurrentConfig.Features.Count; i++)
        {
            if (count >= 3)
            {
                count = 0;
                GUILayout.EndHorizontal();
                GUILayout.BeginHorizontal();
            }
            count++;
            if (GUILayout.Button(mCurrentConfig.Features[i], EditorStyles.toolbarButton, GUILayout.ExpandWidth(false)))
            {
                mCurrentConfig.Features.RemoveAt(i);
                break;
            }
        }
        GUILayout.EndHorizontal();
        GUILayout.Label("Flags:");
        GUILayout.BeginHorizontal();
        count = 0;
        for (int i = 0; i < mCurrentConfig.Flags.Count; i++)
        {
            if (count >= 3)
            {
                count = 0;
                GUILayout.EndHorizontal();
                GUILayout.BeginHorizontal();
            }
            count++;
            if (GUILayout.Button(mCurrentConfig.Flags[i], EditorStyles.toolbarButton, GUILayout.ExpandWidth(false)))
            {
                mCurrentConfig.Flags.RemoveAt(i);
                break;
            }
        }
        GUILayout.EndHorizontal();
        GUILayout.Label("Keywords:");
        GUILayout.BeginHorizontal();
        count = 0;
        foreach (KeyValuePair <string, string> kvp in mCurrentConfig.Keywords)
        {
            if (count >= 3)
            {
                count = 0;
                GUILayout.EndHorizontal();
                GUILayout.BeginHorizontal();
            }
            count++;
            if (GUILayout.Button(kvp.Key + ":" + kvp.Value, EditorStyles.toolbarButton, GUILayout.ExpandWidth(false)))
            {
                mCurrentConfig.Keywords.Remove(kvp.Key);
                break;
            }
        }
        GUILayout.EndHorizontal();

        //----------------------------------------------------------------
#endif

        //Update config
        if (EditorGUI.EndChangeCheck())
        {
            int newHash = mCurrentConfig.ToHash();
            if (newHash != mCurrentHash)
            {
                mDirtyConfig = true;
            }
            else
            {
                mDirtyConfig = false;
            }
        }

        //Scroll view
        EditorGUILayout.EndScrollView();

        Space();

        //GENERATE

        EditorGUILayout.BeginHorizontal();
        GUILayout.FlexibleSpace();
#if DEBUG_MODE
        if (GUILayout.Button("Re-Generate All", GUILayout.Width(120f), GUILayout.Height(30f)))
        {
            float progress = 0;
            float total    = mUserShaders.Length;
            foreach (Shader s in mUserShaders)
            {
                progress++;
                EditorUtility.DisplayProgressBar("Hold On", "Generating Shader: " + s.name, progress / total);

                mCurrentShader = null;
                LoadCurrentConfigFromShader(s);
                if (mCurrentShader != null && mCurrentConfig != null)
                {
                    TCP2_ShaderGeneratorUtils.Compile(mCurrentConfig, Template.text, false, !mOverwriteConfigs, mIsModified);
                }
            }
            EditorUtility.ClearProgressBar();
        }
#endif
        if (GUILayout.Button(mCurrentShader == null ? "Generate Shader" : "Update Shader", GUILayout.Width(120f), GUILayout.Height(30f)))
        {
            if (Template == null)
            {
                EditorUtility.DisplayDialog("TCP2 : Shader Generation", "Can't generate shader: no Template file defined!\n\nYou most likely want to link the TCP2_User.txt file to the Template field in the Shader Generator.", "Ok");
                return;
            }

            Shader generatedShader = TCP2_ShaderGeneratorUtils.Compile(mCurrentConfig, Template.text, true, !mOverwriteConfigs, mIsModified);
            ReloadUserShaders();
            if (generatedShader != null)
            {
                mDirtyConfig = false;
                LoadCurrentConfigFromShader(generatedShader);
                mIsModified = false;
            }
        }
        EditorGUILayout.EndHorizontal();
        TCP2_GUI.Separator();

        // OPTIONS
        TCP2_GUI.Header("OPTIONS");

        GUILayout.BeginHorizontal();
        mSelectGeneratedShader = GUILayout.Toggle(mSelectGeneratedShader, new GUIContent("Select Generated Shader", "Will select the generated file in the Project view"), GUILayout.Width(180f));
        mAutoNames             = GUILayout.Toggle(mAutoNames, new GUIContent("Automatic Name", "Will automatically generate the shader filename based on its UI name"), GUILayout.ExpandWidth(false));
        GUILayout.EndHorizontal();
        GUILayout.BeginHorizontal();
        mOverwriteConfigs = GUILayout.Toggle(mOverwriteConfigs, new GUIContent("Always overwrite shaders", "Overwrite shaders when generating/updating (no prompt)"), GUILayout.Width(180f));
        mHideDisabled     = GUILayout.Toggle(mHideDisabled, new GUIContent("Hide disabled fields", "Hide properties settings when they cannot be accessed"), GUILayout.ExpandWidth(false));
        GUILayout.EndHorizontal();
        EditorGUI.BeginChangeCheck();
        mLoadAllShaders = GUILayout.Toggle(mLoadAllShaders, new GUIContent("Reload Shaders from all Project", "Load shaders from all your Project folders instead of just Toony Colors Pro 2.\nEnable it if you move your generated shader files outside of the default TCP2 Generated folder."), GUILayout.ExpandWidth(false));
        if (EditorGUI.EndChangeCheck())
        {
            ReloadUserShaders();
        }

        TCP2_ShaderGeneratorUtils.SelectGeneratedShader = mSelectGeneratedShader;
    }
 public void ToggleFlag(string flag, bool enable)
 {
     TCP2_ShaderGeneratorUtils.ToggleEntry(this.Flags, flag, enable);
 }
 public bool HasFlagsAll(params string[] flags)
 {
     return(TCP2_ShaderGeneratorUtils.HasAllEntries(this.Flags, flags));
 }
Exemple #20
0
    void OnGUI()
    {
        sGUIEnabled = GUI.enabled;

        EditorGUILayout.BeginHorizontal();
        TCP2_GUI.HeaderBig("TOONY COLORS PRO 2 - SHADER GENERATOR");
        TCP2_GUI.HelpButton("Shader Generator");
        EditorGUILayout.EndHorizontal();
        TCP2_GUI.Separator();

        var lW = EditorGUIUtility.labelWidth;

        EditorGUIUtility.labelWidth = 105f;

        //Avoid refreshing Template meta at every Repaint
        EditorGUILayout.BeginHorizontal();
        var _tmpTemplate = EditorGUILayout.ObjectField("Template:", Template.textAsset, typeof(TextAsset), false) as TextAsset;

        if (_tmpTemplate != Template.textAsset)
        {
            Template.SetTextAsset(_tmpTemplate);
        }
        //Load template
        if (loadTemplateMenu != null)
        {
            if (GUILayout.Button("Load ▼", EditorStyles.miniButton, GUILayout.ExpandWidth(false)))
            {
                loadTemplateMenu.ShowAsContext();
            }
        }

        /*
         * if(GUILayout.Button("Reload", EditorStyles.miniButton, GUILayout.ExpandWidth(false)))
         * {
         *      Template.Reload();
         * }
         */
        EditorGUILayout.EndHorizontal();

        //Template not found
        if (Template == null || Template.textAsset == null)
        {
            EditorGUILayout.HelpBox("Couldn't find template file!\n\nVerify that the file 'TCP2_ShaderTemplate_Default.txt' is in your project.\nPlease reimport the pack if you can't find it!", MessageType.Error);
            return;
        }

        //Infobox for custom templates
        if (!string.IsNullOrEmpty(Template.templateInfo))
        {
            TCP2_GUI.HelpBoxLayout(Template.templateInfo, MessageType.Info);
        }
        if (!string.IsNullOrEmpty(Template.templateWarning))
        {
            TCP2_GUI.HelpBoxLayout(Template.templateWarning, MessageType.Warning);
        }

        TCP2_GUI.Separator();

        //If current shader is unsaved, show yellow color
        var gColor = GUI.color;

        GUI.color = mDirtyConfig ? gColor * unsavedChangesColor : GUI.color;

        EditorGUI.BeginChangeCheck();
        mCurrentShader = EditorGUILayout.ObjectField("Current Shader:", mCurrentShader, typeof(Shader), false) as Shader;
        if (EditorGUI.EndChangeCheck())
        {
            if (mCurrentShader != null)
            {
                LoadCurrentConfigFromShader(mCurrentShader);
            }
        }
        EditorGUILayout.BeginHorizontal();

        GUILayout.Space(EditorGUIUtility.labelWidth + 4);
        if (mDirtyConfig)
        {
            var guiContent = new GUIContent("Unsaved changes");
            var rect       = GUILayoutUtility.GetRect(guiContent, EditorStyles.helpBox, GUILayout.Height(16));
            rect.y -= 2;
            GUI.Label(rect, guiContent, EditorStyles.helpBox);
        }

        GUILayout.FlexibleSpace();
        using (new EditorGUI.DisabledScope(mCurrentShader == null))
        {
            if (GUILayout.Button("Copy", EditorStyles.miniButtonLeft, GUILayout.Width(60f), GUILayout.Height(16)))
            {
                CopyShader();
            }
        }
        if (GUILayout.Button("Load ▼", EditorStyles.miniButtonMid, GUILayout.Width(60f), GUILayout.Height(16)))
        {
            loadShadersMenu.ShowAsContext();
        }
        if (GUILayout.Button("New", EditorStyles.miniButtonRight, GUILayout.Width(60f), GUILayout.Height(16)))
        {
            NewShader();
        }
        GUILayout.Space(18);            //leave space to align with the Object Field box
        EditorGUILayout.EndHorizontal();
        GUI.color = gColor;

        if (mCurrentConfig == null)
        {
            NewShader();
        }

        if (mCurrentConfig.isModifiedExternally)
        {
            EditorGUILayout.HelpBox("It looks like this shader has been modified externally/manually. Updating it will overwrite the changes.", MessageType.Warning);
        }

        EditorGUIUtility.labelWidth = lW;

        //Name & Filename
        TCP2_GUI.Separator();
        GUI.enabled = (mCurrentShader == null);
        EditorGUI.BeginChangeCheck();
        mCurrentConfig.ShaderName = EditorGUILayout.TextField(new GUIContent("Shader Name", "Path will indicate how to find the Shader in Unity's drop-down list"), mCurrentConfig.ShaderName);
        mCurrentConfig.ShaderName = Regex.Replace(mCurrentConfig.ShaderName, @"[^a-zA-Z0-9 _!/]", "");
        if (EditorGUI.EndChangeCheck() && sAutoNames)
        {
            mCurrentConfig.AutoNames();
        }
        GUI.enabled &= !sAutoNames;
        EditorGUILayout.BeginHorizontal();
        mCurrentConfig.Filename = EditorGUILayout.TextField("File Name", mCurrentConfig.Filename);
        mCurrentConfig.Filename = Regex.Replace(mCurrentConfig.Filename, @"[^a-zA-Z0-9 _!/]", "");
        GUILayout.Label(".shader", GUILayout.Width(50f));
        EditorGUILayout.EndHorizontal();
        GUI.enabled = sGUIEnabled;

        TCP2_GUI.Separator();

        //########################################################################################################
        // FEATURES

        TCP2_GUI.Header("FEATURES");

        //Scroll view
        mScrollPosition = EditorGUILayout.BeginScrollView(mScrollPosition);
        EditorGUI.BeginChangeCheck();

        if (Template.newSystem)
        {
            //New UI embedded into Template
            Template.FeaturesGUI(mCurrentConfig);

            if (mFirstHashPass)
            {
                mCurrentHash   = mCurrentConfig.ToHash();
                mFirstHashPass = false;
            }
        }
        else
        {
            EditorGUILayout.HelpBox("Old template versions aren't supported anymore.", MessageType.Warning);
        }

#if DEBUG_MODE
        TCP2_GUI.SeparatorBig();

        TCP2_GUI.SubHeaderGray("DEBUG MODE");

        GUILayout.BeginHorizontal();
        mDebugText = EditorGUILayout.TextField("Custom", mDebugText);
        if (GUILayout.Button("Add Feature", EditorStyles.miniButtonLeft, GUILayout.Width(80f)))
        {
            mCurrentConfig.Features.Add(mDebugText);
        }
        if (GUILayout.Button("Add Flag", EditorStyles.miniButtonRight, GUILayout.Width(80f)))
        {
            mCurrentConfig.Flags.Add(mDebugText);
        }

        GUILayout.EndHorizontal();
        GUILayout.Label("Features:");
        GUILayout.BeginHorizontal();
        int count = 0;
        for (int i = 0; i < mCurrentConfig.Features.Count; i++)
        {
            if (count >= 3)
            {
                count = 0;
                GUILayout.EndHorizontal();
                GUILayout.BeginHorizontal();
            }
            count++;
            if (GUILayout.Button(mCurrentConfig.Features[i], EditorStyles.toolbarButton, GUILayout.ExpandWidth(false)))
            {
                mCurrentConfig.Features.RemoveAt(i);
                break;
            }
        }
        GUILayout.EndHorizontal();
        GUILayout.Label("Flags:");
        GUILayout.BeginHorizontal();
        count = 0;
        for (int i = 0; i < mCurrentConfig.Flags.Count; i++)
        {
            if (count >= 3)
            {
                count = 0;
                GUILayout.EndHorizontal();
                GUILayout.BeginHorizontal();
            }
            count++;
            if (GUILayout.Button(mCurrentConfig.Flags[i], EditorStyles.toolbarButton, GUILayout.ExpandWidth(false)))
            {
                mCurrentConfig.Flags.RemoveAt(i);
                break;
            }
        }
        GUILayout.EndHorizontal();
        GUILayout.Label("Keywords:");
        GUILayout.BeginHorizontal();
        count = 0;
        foreach (KeyValuePair <string, string> kvp in mCurrentConfig.Keywords)
        {
            if (count >= 3)
            {
                count = 0;
                GUILayout.EndHorizontal();
                GUILayout.BeginHorizontal();
            }
            count++;
            if (GUILayout.Button(kvp.Key + ":" + kvp.Value, EditorStyles.toolbarButton, GUILayout.ExpandWidth(false)))
            {
                mCurrentConfig.Keywords.Remove(kvp.Key);
                break;
            }
        }
        GUILayout.EndHorizontal();

        //----------------------------------------------------------------

        Space();
        if (mCurrentShader != null)
        {
            if (mCurrentShaderImporter == null)
            {
                mCurrentShaderImporter = ShaderImporter.GetAtPath(AssetDatabase.GetAssetPath(mCurrentShader)) as ShaderImporter;
            }

            if (mCurrentShaderImporter != null && mCurrentShaderImporter.GetShader() == mCurrentShader)
            {
                mDebugExpandUserData = EditorGUILayout.Foldout(mDebugExpandUserData, "Shader UserData");
                if (mDebugExpandUserData)
                {
                    string[] userData = mCurrentShaderImporter.userData.Split(',');
                    foreach (var str in userData)
                    {
                        GUILayout.Label(str);
                    }
                }
            }
        }
#endif

        //Update config
        if (EditorGUI.EndChangeCheck())
        {
            var newHash = mCurrentConfig.ToHash();
            if (newHash != mCurrentHash)
            {
                mDirtyConfig = true;
            }
            else
            {
                mDirtyConfig = false;
            }
        }

        //Scroll view
        EditorGUILayout.EndScrollView();

        Space();

        //GENERATE

        EditorGUILayout.BeginHorizontal();
        GUILayout.FlexibleSpace();
        GUI.color = mDirtyConfig ? gColor * unsavedChangesColor : GUI.color;
        if (GUILayout.Button(mCurrentShader == null ? "Generate Shader" : "Update Shader", GUILayout.Width(120f), GUILayout.Height(30f)))
        {
            if (Template == null)
            {
                EditorUtility.DisplayDialog("TCP2 : Shader Generation", "Can't generate shader: no Template file defined!\n\nYou most likely want to link the TCP2_User.txt file to the Template field in the Shader Generator.", "Ok");
                return;
            }

            //Set config type
            if (Template.templateType != null)
            {
                mCurrentConfig.configType = Template.templateType;
            }

            //Set config file
            mCurrentConfig.templateFile = Template.textAsset.name;

            var generatedShader = TCP2_ShaderGeneratorUtils.Compile(mCurrentConfig, mCurrentShader, Template, true, !sOverwriteConfigs);
            ReloadUserShaders();
            if (generatedShader != null)
            {
                mDirtyConfig = false;
                LoadCurrentConfigFromShader(generatedShader);
            }

            //Workaround to force the inspector to refresh, so that state is reset.
            //Needed in case of switching between specular/metallic and related
            //options, while the inspector is opened, so that it shows/hides the
            //relevant properties according to the changes.
            TCP2_MaterialInspector_SurfacePBS_SG.InspectorNeedsUpdate = true;
        }
        GUI.color = gColor;
        EditorGUILayout.EndHorizontal();
        TCP2_GUI.Separator();

        // OPTIONS
        TCP2_GUI.Header("OPTIONS");

        GUILayout.BeginHorizontal();
        sSelectGeneratedShader = GUILayout.Toggle(sSelectGeneratedShader, new GUIContent("Select Generated Shader", "Will select the generated file in the Project view"), GUILayout.Width(180f));
        sAutoNames             = GUILayout.Toggle(sAutoNames, new GUIContent("Automatic Name", "Will automatically generate the shader filename based on its UI name"), GUILayout.ExpandWidth(false));
        GUILayout.EndHorizontal();
        GUILayout.BeginHorizontal();
        sOverwriteConfigs = GUILayout.Toggle(sOverwriteConfigs, new GUIContent("Always overwrite shaders", "Overwrite shaders when generating/updating (no prompt)"), GUILayout.Width(180f));
        sHideDisabled     = GUILayout.Toggle(sHideDisabled, new GUIContent("Hide disabled fields", "Hide properties settings when they cannot be accessed"), GUILayout.ExpandWidth(false));
        GUILayout.EndHorizontal();

        EditorGUILayout.BeginHorizontal();
        EditorGUI.BeginChangeCheck();
        TCP2_ShaderGeneratorUtils.CustomOutputDir = GUILayout.Toggle(TCP2_ShaderGeneratorUtils.CustomOutputDir, new GUIContent("Custom Output Directory:", "Will save the generated shaders in a custom directory within the Project"), GUILayout.Width(165f));
        GUI.enabled &= TCP2_ShaderGeneratorUtils.CustomOutputDir;
        if (TCP2_ShaderGeneratorUtils.CustomOutputDir)
        {
            TCP2_ShaderGeneratorUtils.OutputPath = EditorGUILayout.TextField("", TCP2_ShaderGeneratorUtils.OutputPath);
            if (GUILayout.Button("Select...", EditorStyles.miniButton, GUILayout.ExpandWidth(false)))
            {
                var outputPath = TCP2_Utils.OpenFolderPanel_ProjectPath("Choose custom output directory for TCP2 generated shaders");
                if (!string.IsNullOrEmpty(outputPath))
                {
                    TCP2_ShaderGeneratorUtils.OutputPath = outputPath;
                }
            }
        }
        else
        {
            EditorGUILayout.TextField("", TCP2_ShaderGeneratorUtils.OUTPUT_PATH);
        }
        if (EditorGUI.EndChangeCheck())
        {
            ReloadUserShaders();
        }

        GUI.enabled = sGUIEnabled;
        EditorGUILayout.EndHorizontal();

        EditorGUI.BeginChangeCheck();
        sLoadAllShaders = GUILayout.Toggle(sLoadAllShaders, new GUIContent("Reload Shaders from all Project", "Load shaders from all your Project folders instead of just Toony Colors Pro 2.\nEnable it if you move your generated shader files outside of the default TCP2 Generated folder."), GUILayout.ExpandWidth(false));
        if (EditorGUI.EndChangeCheck())
        {
            ReloadUserShaders();
        }

        TCP2_ShaderGeneratorUtils.SelectGeneratedShader = sSelectGeneratedShader;
    }
 public bool HasFeaturesAll(params string[] features)
 {
     return(TCP2_ShaderGeneratorUtils.HasAllEntries(this.Features, features));
 }
    //--------------------------------------------------------------------------------------------------
    // FEATURES

    public bool HasFeature(string feature)
    {
        return(TCP2_ShaderGeneratorUtils.HasEntry(this.Features, feature));
    }
    //--------------------------------------------------------------------------------------------------
    // FLAGS

    public bool HasFlag(string flag)
    {
        return(TCP2_ShaderGeneratorUtils.HasEntry(this.Flags, flag));
    }
Exemple #24
0
 public void ToggleFeature(string feature, bool enable)
 {
     TCP2_ShaderGeneratorUtils.ToggleEntry(this.Features, feature, enable);
 }