简体   繁体   中英

How can I change enum items using a button?

using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityEditor.IMGUI;

public class ChangeShaderRenderingModes : EditorWindow
{
    public enum BlendMode
    {
        Opaque,
        Cutout,
        Fade,
        Transparent
    }

    static Material material;
    static Material objectMat;
    static int modeIndex = 0;

    [MenuItem("Tools/Change Rendering Modes")]
    public static void ShowWindow()
    {
        GetWindow<ChangeShaderRenderingModes>("ChangeRenderingModes");
    }

    private void OnGUI()
    {
        if(GUI.Button(new Rect(50,50,50,50), "Switch Mode"))
        {
            var objects = Selection.objects;

            Shader shader = Shader.Find("Standard");
            material = new Material(shader);

            if (modeIndex == 4)
                modeIndex = 0;

            ChangeRenderMode(material, BlendMode.Opaque);

            GameObject go = GameObject.Find("test");

            objectMat = go.GetComponent<Renderer>().sharedMaterial;
            objectMat = material;
            go.GetComponent<Renderer>().sharedMaterial = material;
        }
    }

    public static void ChangeRenderMode(Material standardShaderMaterial, BlendMode blendMode)
    {
        switch (blendMode)
        {
            case BlendMode.Opaque:
                standardShaderMaterial.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
                standardShaderMaterial.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero);
                standardShaderMaterial.SetInt("_ZWrite", 1);
                standardShaderMaterial.DisableKeyword("_ALPHATEST_ON");
                standardShaderMaterial.DisableKeyword("_ALPHABLEND_ON");
                standardShaderMaterial.DisableKeyword("_ALPHAPREMULTIPLY_ON");
                standardShaderMaterial.renderQueue = -1;
                break;
            case BlendMode.Cutout:
                standardShaderMaterial.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
                standardShaderMaterial.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero);
                standardShaderMaterial.SetInt("_ZWrite", 1);
                standardShaderMaterial.EnableKeyword("_ALPHATEST_ON");
                standardShaderMaterial.DisableKeyword("_ALPHABLEND_ON");
                standardShaderMaterial.DisableKeyword("_ALPHAPREMULTIPLY_ON");
                standardShaderMaterial.renderQueue = 2450;
                break;
            case BlendMode.Fade:
                standardShaderMaterial.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha);
                standardShaderMaterial.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
                standardShaderMaterial.SetInt("_ZWrite", 0);
                standardShaderMaterial.DisableKeyword("_ALPHATEST_ON");
                standardShaderMaterial.EnableKeyword("_ALPHABLEND_ON");
                standardShaderMaterial.DisableKeyword("_ALPHAPREMULTIPLY_ON");
                standardShaderMaterial.renderQueue = 3000;
                break;
            case BlendMode.Transparent:
                standardShaderMaterial.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
                standardShaderMaterial.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
                standardShaderMaterial.SetInt("_ZWrite", 0);
                standardShaderMaterial.DisableKeyword("_ALPHATEST_ON");
                standardShaderMaterial.DisableKeyword("_ALPHABLEND_ON");
                standardShaderMaterial.EnableKeyword("_ALPHAPREMULTIPLY_ON");
                standardShaderMaterial.renderQueue = 3000;
                break;
        }
    }
}

I want to make that each time I click the button it will change to the next mode. Opaque, Cutout, Fade, Transparent

And after Transparent back to the first one Opaque

The problem is that the method ChangeRenderMode get one specific mode. I want when clicking the button once ChangeRenderMode will get Opaque then next click it will get Cutout then Fade and Transparent.

enum s start with default value of 0, increasing 1 per item, so

public enum BlendMode
{
    Opaque,   // = 0
    Cutout,   // = 1
    Fade,     // = 2
    Transparent  // = 3
}

So you can parse it into int calculate the next value and then parse it again to BlendMode :

In your OnGUI function, replace

if (modeIndex == 4)
    modeIndex = 0;
ChangeRenderMode(material, BlendMode.Opaque);

with

var values = (BlendMode[])Enum.GetValues(typeof(BlendMode))
modeIndex = (BlendMode)((modeIndex+1) % values.Length);
ChangeRenderMode(material, blendMode);

You can try to use a Dictionary key be current state value be next state.

Dictionary<BlendMode, BlendMode> dict = new Dictionary<BlendMode, BlendMode>();
dict.Add(BlendMode.Opaque, BlendMode.Cutout);
dict.Add(BlendMode.Cutout, BlendMode.Fade);
dict.Add(BlendMode.Fade, BlendMode.Transparent);
dict.Add(BlendMode.Transparent, BlendMode.Opaque);

and declare a value in the class to store BlendMode state.

BlendMode currentMode = BlendMode.Cutout;

Then you can use this currentMode (key) to get the next Mode.

currentMode = dict[currentMode];

Full code will be like

public class ChangeShaderRenderingModes : EditorWindow
{
    //store mode
    static BlendMode currentMode = BlendMode.Opaque;

    static Dictionary<BlendMode, BlendMode> dict = new Dictionary<BlendMode, BlendMode>();


    public void Awake()
    {
        dict.Add(BlendMode.Opaque, BlendMode.Cutout);
        dict.Add(BlendMode.Cutout, BlendMode.Fade);
        dict.Add(BlendMode.Fade, BlendMode.Transparent);
        dict.Add(BlendMode.Transparent, BlendMode.Opaque);
    }


    public enum BlendMode
    {
        Opaque,
        Cutout,
        Fade,
        Transparent
    }

    static Material material;
    static Material objectMat;
    static int modeIndex = 0;

    [MenuItem("Tools/Change Rendering Modes")]
    public static void ShowWindow()
    {
        GetWindow<ChangeShaderRenderingModes>("ChangeRenderingModes");
    }

    private void OnGUI()
    {
        if(GUI.Button(new Rect(50,50,50,50), "Switch Mode"))
        {
            var objects = Selection.objects;

            Shader shader = Shader.Find("Standard");
            material = new Material(shader);

            if (modeIndex == 4)
                modeIndex = 0;

            // take out the parameter
            ChangeRenderMode(material);

            GameObject go = GameObject.Find("test");

            objectMat = go.GetComponent<Renderer>().sharedMaterial;
            objectMat = material;
            go.GetComponent<Renderer>().sharedMaterial = material;
        }
    }

    public static void ChangeRenderMode(Material standardShaderMaterial)
    {
        switch (blendMode)
        {
            ....
        }
        // set next mode
        currentMode = dict[currentMode];
    }
}

NOTE

This solution can be flexible to determine what the next Mode is.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM