1. 程式人生 > >對Unity Editor 控制元件的封裝 (4.3.2f1)

對Unity Editor 控制元件的封裝 (4.3.2f1)

/// <summary>
/// 編輯器控制元件基類
/// </summary>
public class EditorControlBase
{
    public string Name;
    public float Width { private set; get; }
    public float Height{ private set; get; }

    protected List<GUILayoutOption> guiLayout = new List<GUILayoutOption>();

    public EditorControlBase(string name)
    {
        this.Name = name;
    }

    public void SetSize(float width, float height)
    {
        this.Width = width;
        this.Height = height;
        guiLayout.Clear();
        guiLayout.Add(GUILayout.Width(Width));
        guiLayout.Add(GUILayout.Height(Height));
    }

    public virtual void OnGUIUpdate()
    {
    }
}

/// <summary>
/// 編輯器控制元件  - 按鍵
/// </summary>
public class ECButton : EditorControlBase
{
    public delegate void ECButtonDel();
    public ECButtonDel OnClick;

    public ECButton(string name)
        : base(name)
    {
    }

    public override void OnGUIUpdate()
    {
        if (GUILayout.Button(this.Name, guiLayout.ToArray()))
        {
            if (OnClick != null)
            {
                OnClick();
            }
        }
    }
}

/// <summary>
/// 編輯器控制元件  - 文字框
/// </summary>
public class ECLabel : EditorControlBase
{
    public string Text;

    public ECLabel(string name)
        : base(name)
    {
        Text = name;
    }

    public override void OnGUIUpdate()
    {
        EditorGUILayout.LabelField(this.Text,guiLayout.ToArray());
    }
}

/// <summary>
/// 編輯器控制元件  - 下拉框
/// </summary>
public class ECPopup<T> : EditorControlBase 
{
    int popup = 0;
    public List<T> Items = new List<T>();

    /// <summary>
    /// 當前選中的
    /// </summary>
    public T SelectItem { private set; get; }

    /// <summary>
    /// 當前選中的
    /// </summary>
    public int SelectItemIndex { private set; get; }

    public ECPopup(string name)
        : base(name)
    {
    }

    /// <summary>
    /// 返回選中的專案
    /// </summary>
    public override void OnGUIUpdate()
    {
        List<string> names = new List<string>();
        foreach (T i in Items)
            names.Add(i.ToString());

        popup = EditorGUILayout.Popup(this.Name, popup, names.ToArray(),guiLayout.ToArray());

        if (popup >= 0 && popup < Items.Count)
        {
            SelectItem = Items[popup];
            SelectItemIndex = popup;
        }
    }
}

/// <summary>
/// 編輯器控制元件  - 空白
/// </summary>
public class ECSpace : EditorControlBase
{
    float pixels;
    public ECSpace(float pixels)
        : base("")
    {
        this.pixels = pixels;
    }

    public override void OnGUIUpdate()
    {
        GUILayout.Space(pixels);
    }
}

/// <summary>
/// 編輯器控制元件  - 文字框
/// </summary>
public class ECText : EditorControlBase
{
    public string Text { private set; get; }

    public ECText(string name,string text)
        : base(name)
    {
        this.Text = text;
    }

    /// <summary>
    /// 返回選中的專案
    /// </summary>
    public override void OnGUIUpdate()
    {
        Text = EditorGUILayout.TextField(this.Name, Text,guiLayout.ToArray()); 
    }
}

/// <summary>
/// 編輯器控制元件  - 多選框
/// </summary>
public class ECToggle : EditorControlBase
{
    public delegate void ECToggleDel(bool isbool);
    public ECToggleDel OnClick;
    ECLabel ecLabel;
    bool nowbool = false;
    bool lastbool = false;

    public bool IsCheck
    {
        get { return nowbool; }
        set { nowbool = value; }
    }

    public new string Name { set { this.ecLabel.Text = value; } }

    public ECToggle(string name, bool initBool)
        : base(name)
    {
        this.nowbool = initBool;
        this.lastbool = initBool;
        ecLabel = new ECLabel(name); 
    }

    public override void OnGUIUpdate()
    {
        GUILayout.BeginHorizontal();
        nowbool = EditorGUILayout.Toggle(nowbool, GUILayout.Width(30), GUILayout.Height(20));
        ecLabel.OnGUIUpdate();
        GUILayout.EndHorizontal();

        if (nowbool != lastbool)
        {
            if (OnClick != null)
                OnClick(nowbool);
            lastbool = nowbool;
        }
    }
}

    /// <summary>
    /// 編輯器控制元件  - 資料表
    /// </summary>
    public class ECTable : EditorControlBase
    {
        public List<DataRow> DataRows = new List<DataRow>(); //DataRow 類存放一行的所有資料

        protected ECSpace ecSpace;
        protected Dictionary<string, int> columnName_Width = new Dictionary<string, int>(); // 列名和寬度

        //事件
        public delegate void OnDeleteRowDel(int ID);
        public OnDeleteRowDel OnDeleteRow;

        //資料快取. 針對每個LevelEnemyOneRow鍵一個快取字典, int is LevelEnemyOneRow.ID,  string is  columnName
        protected Dictionary<int, Dictionary<string, ValueCache>> inputDataCache = new Dictionary<int, Dictionary<string, ValueCache>>();

        public ECTable(string name)
            : base(name)
        {
        }

        protected class ValueCache
        {
            public Type Type;
            public object ObjValue;
            public ValueType ValueType = ValueType.Assigned;

            public ValueCache(object objValue, Type type)
            {
                this.ObjValue = objValue;
                this.Type = type;
            }
        }

        /// <summary>
        /// 值衝突型別
        /// </summary>
        protected enum ValueType
        {
            Assigned, //正常值,已經賦值了的
            BeModify, //被修改了還沒有賦值的
            Error, //錯誤資料, 還沒有賦值
        }

        protected Color GetColor(ValueType v)
        {
            if (v == ValueType.Error)
                return Color.red;
            if (v == ValueType.BeModify)
                return Color.yellow;

            return Color.green;
        }

        protected void DisplayText<T>(int rowID, T _value, string colName)
        {
            //找出快取中對應的項
            ValueCache vc;
            if (inputDataCache[rowID].ContainsKey(colName) == true)
                vc = inputDataCache[rowID][colName];
            else
                vc = new ValueCache(_value, typeof(T));

            GUI.color = GetColor(vc.ValueType);

            string temp =  vc.ObjValue.ToString();
            vc.ObjValue = GUILayout.TextField(vc.ObjValue.ToString(), GUILayout.Width(columnName_Width[colName]));

            if (vc.ValueType == ValueType.Assigned && temp != vc.ObjValue.ToString())
                vc.ValueType = ValueType.BeModify;

            //更新快取
            if (inputDataCache[rowID].ContainsKey(colName) == true)
                inputDataCache[rowID][colName] = vc;
            else
                inputDataCache[rowID].Add(colName, vc);

            GUI.color = Color.white;
        }

        protected void DisplayText<T>(T _value, string colName)
        {
            GUILayout.TextField(_value.ToString(), GUILayout.Width(columnName_Width[colName]));
        }

        //_value為要賦值的真正資料
        protected static void ConvertData<T>(ValueCache vc, ref T _value, float min, float max)
        {
            try
            {
                //限制必須是數字
                T temp = (T)Convert.ChangeType(vc.ObjValue, typeof(T));
                //限制數字的大小, 超過限制就走 catch
                if (Helper.IsNumericalLimits(float.Parse(temp.ToString()), max, min) == false)
                    throw new Exception();

                _value = temp;
                vc.ValueType = ECTable.ValueType.Assigned;
            }
            catch
            {
                vc.ValueType = ECTable.ValueType.Error;
            }
        }
    }
    /// <summary>
    ///編輯器控制元件  - 資料表 使用例項 繼承ECTable
    /// </summary>
    public class ECTable_test : ECTable
    {
        public List<EditorSModel> SoldierModels = new List<EditorSModel>();

        //事件
        public delegate void OnDeleteSoldierDel(EditorSModel esm);
        public OnDeleteSoldierDel OnDeleteSoldier;

        public ECTable_test(string name, float backspace)
            : base(name)
        {
            ecSpace = new ECSpace(backspace);

            columnName_Width.Add("單位ID", 50);
            columnName_Width.Add("士兵等級", 60);
            columnName_Width.Add("X", 40);
            columnName_Width.Add("Y", 40);
        }

        public override void OnGUIUpdate()
        {
            Display();
        }

        public void ClearAll()
        {
            for (int i = 0; i < SoldierModels.Count; i++)
            {
                GameObject.DestroyImmediate(SoldierModels[i].gameObject);
            }
            SoldierModels.Clear();
        }

        void Display()
        {
            //列名
            GUILayout.BeginHorizontal();
            ecSpace.OnGUIUpdate();
            foreach (var col in columnName_Width)
            {
                GUILayout.Label(col.Key, GUILayout.Width(col.Value));
            }
            GUILayout.EndHorizontal();

            for (int i = 0; i < SoldierModels.Count; i++)
            {
                EditorSModel esm = SoldierModels[i];
                GUILayout.BeginHorizontal();
                ecSpace.OnGUIUpdate();

                DisplayText<int>(esm.SoldierID, "單位ID");
                DisplayText<int>(esm.SoldierLevel, "士兵等級");
                DisplayText<float>(esm.LayPosition.x, "X");
                DisplayText<float>(esm.LayPosition.y, "Y");

                //刪除一行
                if (GUILayout.Button("刪除", GUILayout.Width(38)))
                {
                    if (OnDeleteSoldier != null)
                        OnDeleteSoldier(esm);
                    SoldierModels.RemoveAt(i);
                    i--;
                }

                GUILayout.EndHorizontal();
            }
        }
    }