﻿// A set of helper functions for custom material editors
// By Mochie
// Mochie#8794

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

public class ShaderGUIHelper {

    public static bool Foldout(Texture2D tex, bool display, float height){
        GUIStyle formatting = new GUIStyle("ShurikenModuleTitle");
        formatting.contentOffset = new Vector2(20.0f, -3.0f);
        formatting.fixedHeight = height;
        Rect rect = GUILayoutUtility.GetRect(5.0f, height, formatting);
        rect.x -= 8.0f;
        rect.width = GetInspectorWidth()+8.0f;
        GUI.Box(rect, tex, formatting);
        return DoToggle(display, rect);
    }

    public static bool Foldout(string header, bool display, float height){
        GUIStyle formatting = new GUIStyle("ShurikenModuleTitle");
        formatting.contentOffset = new Vector2(18.0f, -2.0f);
        formatting.fixedHeight = height;
        GUIStyle headerFont = new GUIStyle(EditorStyles.boldLabel);
        formatting.font = headerFont.font;
        Rect rect = GUILayoutUtility.GetRect(5.0f, height, formatting);
        GUI.Box(rect, header, formatting);
        return DoToggle(display, rect);
    }

    private static bool DoToggle(bool show, Rect rect){
        Event currentEvent = Event.current;
        Rect arrowRect = new Rect(rect.x+4.0f, rect.y+4.0f, 0.0f, 0.0f);
        if (currentEvent.type == EventType.Repaint)
            EditorStyles.foldout.Draw(arrowRect, false, false, show, false);
        if (currentEvent.type == EventType.MouseDown && rect.Contains(currentEvent.mousePosition)){
            show = !show;
            currentEvent.Use();
        }
        return show;
    }

    public static bool SmallFoldout(string header, bool display, float height){
        GUIStyle formatting = new GUIStyle("ShurikenModuleTitle");
        GUILayoutOption clickArea = GUILayout.MaxWidth(EditorGUIUtility.labelWidth-13);
        formatting.contentOffset = new Vector2(14.0f, -2.0f);
        formatting.fixedHeight = height;
        formatting.fontSize = 9;
        formatting.wordWrap = true;
        Rect boxRect = GUILayoutUtility.GetRect(5.0f, height, formatting);
        GUI.Box(boxRect, header, formatting);
        GUILayout.Space(-height);
        Rect toggleRect = GUILayoutUtility.GetRect(5.0f, height, formatting, clickArea);
        return DoSmallToggle(display, toggleRect);
    }

    private static bool DoSmallToggle(bool show, Rect rect){
        Event currentEvent = Event.current;
        Rect arrowRect = new Rect(rect.x+1.0f, rect.y+1.5f, 0.0f, 0.0f);
        if (currentEvent.type == EventType.Repaint)
            EditorStyles.foldout.Draw(arrowRect, false, false, show, false);
        if (currentEvent.type == EventType.MouseDown && rect.Contains(currentEvent.mousePosition)){
            show = !show;
            currentEvent.Use();
        }
        GUILayout.Space(-22.0f);
        return show;
    }

    public static bool SimpleFoldout(string header, bool display){
        GUIStyle formatting = new GUIStyle("ShurikenModuleTitle");
        float lw = EditorGUIUtility.labelWidth-13;
        GUILayoutOption clickArea = GUILayout.MaxWidth(lw);
        formatting.contentOffset = new Vector2(18.0f, -.5f);
        formatting.fixedHeight = 18.0f;
        formatting.fixedWidth = lw;
        formatting.wordWrap = true;
        Rect rect = GUILayoutUtility.GetRect(5.0f, 18.0f, clickArea);
        GUILayout.Space(-20);
        header = "    " + header;
        EditorGUILayout.LabelField(header);
        
        return DoSimpleToggle(display, rect);
    }

    private static bool DoSimpleToggle(bool show, Rect rect){
        Event currentEvent = Event.current;
        Rect arrowRect = new Rect(rect.x+2.0f, rect.y+1.0f, 0.0f, 0.0f);
        if (currentEvent.type == EventType.Repaint)
            EditorStyles.foldout.Draw(arrowRect, false, false, show, false);
        if (currentEvent.type == EventType.MouseDown && rect.Contains(currentEvent.mousePosition)){
            show = !show;
            currentEvent.Use();
        }
        GUILayout.Space(-18);
        return show;
    }

    // Slider with a toggle
    public static void ToggleSlider(MaterialEditor materialEditor, string label, MaterialProperty toggle, MaterialProperty slider){
        float lw = EditorGUIUtility.labelWidth;
        float indent = lw + 25.0f;
        GUILayoutOption clickArea = GUILayout.MaxWidth(lw+13.0f);
        toggle.floatValue = EditorGUILayout.Toggle(label, toggle.floatValue==1, clickArea)?1:0;
        if (toggle.floatValue == 1){
            GUILayout.Space(-18);
            Rect r = EditorGUILayout.GetControlRect();
            r.x += indent;
            r.width -= indent;
            materialEditor.RangeProperty(r, slider, "");
        }
    }

    public static void ScruffyButton(string label, string buttonText, float buttonWidth){
        float x = EditorGUIUtility.labelWidth - buttonWidth;
        Rect r = EditorGUILayout.GetControlRect();
        GUI.Label(r, label);
        r.x += x;
        r.width -= x;
        GUI.Button(r, buttonText);
    }

    // Vector4 property with a toggle
    public static void ToggleVector4(string label, MaterialProperty toggle, MaterialProperty vec){
        GUIContent g = new GUIContent(label, "");
        ToggleVector4(g, toggle, vec);
    }
    public static void ToggleVector4(GUIContent label, MaterialProperty toggle, MaterialProperty vec){
        Vector4 newVec = vec.vectorValue;
        float lw = EditorGUIUtility.labelWidth;
        float iw = GetInspectorWidth();
        float labelSpace = 13.0f;
        float indent = lw + 20.0f;
        float space = ((iw-lw)/4.0f)-18.59f;
        GUILayoutOption clickArea = GUILayout.MaxWidth(lw+13.0f);
        toggle.floatValue = EditorGUILayout.Toggle(label, toggle.floatValue==1, clickArea)?1:0;
        EditorGUI.BeginDisabledGroup(toggle.floatValue == 0);
            GUILayout.Space(-18);
            Rect r = EditorGUILayout.GetControlRect();
            r.x += indent;
            r.width = space;
            EditorGUI.LabelField(r, "X");
            r.x += labelSpace;
            newVec.x = EditorGUI.FloatField(r, newVec.x);
            r.x += space;
            EditorGUI.LabelField(r, "Y");
            r.x += labelSpace;
            newVec.y = EditorGUI.FloatField(r, newVec.y);
            r.x += space;
            EditorGUI.LabelField(r, "Z");
            r.x += labelSpace;
            newVec.z = EditorGUI.FloatField(r, newVec.z);
            r.x += space;
            EditorGUI.LabelField(r, "W");
            r.x += labelSpace+2.0f;
            newVec.w = EditorGUI.FloatField(r, newVec.w);
            r.x += space;
            vec.vectorValue = newVec;
        EditorGUI.EndDisabledGroup();
    }

    // Vector3 property with a toggle
    public static void ToggleVector3(string label, MaterialProperty toggle, MaterialProperty vec){
        GUIContent g = new GUIContent(label, "");
        ToggleVector3(g, toggle, vec);
    }
    public static void ToggleVector3(GUIContent label, MaterialProperty toggle, MaterialProperty vec){
        Vector4 newVec = vec.vectorValue;
        float lw = EditorGUIUtility.labelWidth;
        float iw = GetInspectorWidth();
        float labelSpace = 13.0f;
        float indent = lw + 20.0f;
        float space = ((iw-lw)/3.0f)-19.76f;
        GUILayoutOption clickArea = GUILayout.MaxWidth(lw+13.0f);
        toggle.floatValue = EditorGUILayout.Toggle(label, toggle.floatValue==1, clickArea)?1:0;
        EditorGUI.BeginDisabledGroup(toggle.floatValue == 0);
            GUILayout.Space(-18);
            Rect r = EditorGUILayout.GetControlRect();
            r.x += indent;
            r.width = space;
            EditorGUI.LabelField(r, "X");
            r.x += labelSpace;
            newVec.x = EditorGUI.FloatField(r, newVec.x);
            r.x += space;
            EditorGUI.LabelField(r, "Y");
            r.x += labelSpace;
            newVec.y = EditorGUI.FloatField(r, newVec.y);
            r.x += space;
            EditorGUI.LabelField(r, "Z");
            r.x += labelSpace;
            newVec.z = EditorGUI.FloatField(r, newVec.z);
            r.x += space;
            vec.vectorValue = newVec;
        EditorGUI.EndDisabledGroup();
    }

    // Vector2 property with a toggle
    public static void ToggleVector2(string label, MaterialProperty toggle, MaterialProperty vec){
        GUIContent g = new GUIContent(label, "");
        ToggleVector2(g, toggle, vec);
    }
    public static void ToggleVector2(GUIContent label, MaterialProperty toggle, MaterialProperty vec){
        Vector4 newVec = vec.vectorValue;
        float lw = EditorGUIUtility.labelWidth;
        float iw = GetInspectorWidth();
        float labelSpace = 13.0f;
        float indent = lw + 20.0f;
        float space = ((iw-lw)/2.0f)-23.14f;
        GUILayoutOption clickArea = GUILayout.MaxWidth(lw+13.0f);
        toggle.floatValue = EditorGUILayout.Toggle(label, toggle.floatValue==1, clickArea)?1:0;
        EditorGUI.BeginDisabledGroup(toggle.floatValue == 0);
            GUILayout.Space(-18);
            Rect r = EditorGUILayout.GetControlRect();
            r.x += indent;
            r.width = space;
            EditorGUI.LabelField(r, "X");
            r.x += labelSpace;
            newVec.x = EditorGUI.FloatField(r, newVec.x);
            r.x += space;
            EditorGUI.LabelField(r, "Y");
            r.x += labelSpace;
            newVec.y = EditorGUI.FloatField(r, newVec.y);
            r.x += space;
            vec.vectorValue = newVec;
        EditorGUI.EndDisabledGroup();
    }

    // Draws up to 3 textures centered in the editor window
    public static void CenteredTexture(Texture2D tex1, Texture2D tex2, Texture2D tex3, float spacing, float upperMargin, float lowerMargin){
        GUILayout.Space(upperMargin); 
        GUILayout.BeginHorizontal();
        GUILayout.FlexibleSpace();
        GUILayout.Label(tex1);
        GUILayout.Space(spacing);
        GUILayout.Label(tex2);
        GUILayout.Space(spacing);
        GUILayout.Label(tex3);
        GUILayout.FlexibleSpace();
        GUILayout.EndHorizontal();
        GUILayout.Space(lowerMargin);
    }
    public static void CenteredTexture(Texture2D tex1, Texture2D tex2, float spacing, float upperMargin, float lowerMargin){
        GUILayout.Space(upperMargin);
        GUILayout.BeginHorizontal();
        GUILayout.FlexibleSpace();
        GUILayout.Label(tex1);
        GUILayout.Space(spacing);
        GUILayout.Label(tex2);
        GUILayout.FlexibleSpace();
        GUILayout.EndHorizontal();
        GUILayout.Space(lowerMargin);
    }
    public static void CenteredTexture(Texture2D tex, float upperMargin, float lowerMargin){
        GUILayout.Space(upperMargin);
        GUILayout.BeginHorizontal();
        GUILayout.FlexibleSpace();
        GUILayout.Label(tex);
        GUILayout.FlexibleSpace();
        GUILayout.EndHorizontal();
        GUILayout.Space(lowerMargin);
    }

    public static void CenteredText(string text, int fontSize, float upperMargin, float lowerMargin){
        GUIStyle f = new GUIStyle(EditorStyles.boldLabel);
        f.fontSize = fontSize;
        GUILayout.Space(upperMargin);
        GUILayout.BeginHorizontal();
        GUILayout.FlexibleSpace();
        GUILayout.Label(text, f);
        GUILayout.FlexibleSpace();
        GUILayout.EndHorizontal();
        GUILayout.Space(lowerMargin);
    }

    public static void ToggleLabel(string text, int offset){
        GUILayout.Space(-20);
        Rect rm = EditorGUILayout.GetControlRect();
        rm.x += GetInspectorWidth()-offset;
        EditorGUI.LabelField(rm, text);
    }

    private const float b = 0.4f;
    public static void ContentBox(float boxSize){
        GUILayout.Space(4);
        Rect pos = GUILayoutUtility.GetRect(0f, boxSize);
        pos.width = GetInspectorWidth()+6.0f;
        pos.x -= 4.0f;
        GUILayout.Space(4);
        GUI.Box(pos, "");
        GUILayout.Space(-boxSize);
    }

    public static float GetInspectorWidth(){
        EditorGUILayout.BeginHorizontal();
        GUILayout.FlexibleSpace();
        EditorGUILayout.EndHorizontal();
        return GUILayoutUtility.GetLastRect().width;
    }

    public static bool CheckName(string name, Material mat){
        return mat.shader.name.Contains(name);
    }
}