Unity编辑器拓展-基于EditorWindow的三消类地图编辑器

效果图

这里写图片描述

导出配置文件
rollMatrixPool =
{
    [1] =
    {
        {
            { "E","E,i_2","E","E","E,i_2","E","E",},
            { "E","E","E,i_2","E","E,i_2","E","E",},
            { "E","E","E","E,i_2","E","E","E",},
        },
    },
    [2] =
    {
        {
            { "E","E,i_1","E","E","E","E","E",},
            { "E","E,i_1","E","E","E","E","E",},
            { "E","E","E,i_1","E,i_1","E","E","E",},
        },
        {
            { "E","E","E,i_2","p","p","p","E",},
            { "E","E","E,i_2","p","p,i_2","p","E",},
            { "E","E,i_2","E","E","p","p","E",},
        },
    },
    [3] =
    {
        {
            { "E","E","E","E","E","E","E",},
            { "E","E","ceb","E","E","E","E",},
            { "E","E","ceb","ceb","E","E","E",},
        },
        {
            { "E","E","E","E","E","E","E",},
            { "E","E","E","E","E","E","E",},
            { "E","E","E","E","E","E","E",},
        },
        {
            { "E","E","ceb,i_2","E","E","E,i_2","E",},
            { "ceb","E","ceb,i_2","ceb","E,i_2","E","E",},
            { "ceb","E","E","ceb,i_2","E","E","E",},
        },
        {
            { "E","p","E","p","p","p_3","p_3",},
            { "E,i_1","E,i_1","p,i_1","p","E,i_1","p_3,i_1","p_3",},
            { "E","E","p","p,i_1","E,i_1","p_3,i_1","p_3",},
        },
    },
}

由于导出的配置内容需要提供给lua用作表读取,但是c#中没有数据结构能够与lua的表进行转换。起初想通过lua与c#结合操作,然后通过lua读取存储数据,c#用来操作编辑器。但是项目使用的slua,在lua调用c#的时候不能像ulua那样直接把c#的函数注册进中间栈,需要把c#导出成库才可以调用。只能用采用字符串操作。贼麻烦。

编辑器拓展控件分类

主要就是GUILayout、EditorGUILayout、GUI、EditorGUI。
其中EditorGUILayout、EditorGUI感觉是专门为编辑器拓展的,因为需要using UnityEditor;而GUILayout、GUI则需要using UnityEngine;但是使用过程中发现这两种控件很矛盾呀,比如GUILayout没有intpopup而EditorGUI竟然没有button。因此我感觉混合使用还行。

图片叠加、按钮图片叠加

如果使用layout是没有办法这样叠加的。吧?反正我没找到。。
解决办法就是通过利用GUI类设置Rect。GUI类没有使用自动布局,因此在使用这个类库创建控件的时候需要指定Rect。如果你需要一个按钮使用layout布局,然后在上面叠加图片。这时候上面叠加的图片可以使用GUI.DrawTexture(rect,texture),怎么获取按钮的矩形呢?Rect r = GUILayoutUtility.GetLastRect ();这个函数可以获取到最后一次使用layout的控件的矩形。

#GUILayout与GUI控件混合使用。

这里写图片描述
图中的很多button其实是没有使用layout布局的,坐标都是算出来的。实现过程是

GUILayout.Box("",GUILayout.Width(col*gridWidth),GUILayout.Height(row*gridWidth));
                Rect r = GUILayoutUtility.GetLastRect ();
                var item = spanList [m];
                for (int i = 0; i < row; i++) {
                    float y = r.y + i * gridWidth;
                    for (int j = 0; j < col; j++) {
                        float x = r.x + j * gridWidth;
                        var grid = item [i, j];
                        grid.setPos (x, y);
各种配置文件处理

因为编辑器是给策划用的,因此降低各种实用配置。
比如,地图元素的种类,获取配置目录里面的全部png都当做贴图

DirectoryInfo direction = new DirectoryInfo(rootPath); 
        FileInfo[] files = direction.GetFiles("*.png",SearchOption.AllDirectories); 
        Debug.Log ("地图贴图个数: " + files.Length);

        foreach (var file in files) {
            var tex = AssetDatabase.LoadAssetAtPath<Texture> (rootPath + file.Name);
            var chunk = new GUIContent (tex);
            if (chunk != null) {
                if (IsMantle (chunk.image.name)) {
                    contentMantle.Add (chunk);
                } else {
                    contentGround.Add (chunk);
                }
            }
        }
全部代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System.IO; 

using System;

public class MapChunk{
    public GUIContent con;
    public Rect rect;
    public Texture mantleTexture;
    public MapChunk(){
        var width = BattleMatrixEditor.gridWidth;
        rect = new Rect (0, 0, width, width);
    }
    public MapChunk(GUIContent con):this(){
        this.con = con;
    }
    public void setPos(float x, float y){
        rect.x = x;
        rect.y = y;
    }
    public void setGround(string name){
        if (con == null) {
            con = new GUIContent ();
        }
        con.image = AssetDatabase.LoadAssetAtPath<Texture> (BattleMatrixEditor.rootPath + name + ".png");
    }
    public void setMatrix(string name){
        mantleTexture = AssetDatabase.LoadAssetAtPath<Texture> (BattleMatrixEditor.rootPath + name + ".png");
    }
}

public class BattleMatrixEditor : EditorWindow {

    [MenuItem("Edit/BattleMatrixEditor", false, 1)]
    static void OpenWindow()
    {
        var window = GetWindow<BattleMatrixEditor>(false, "BattleMatrixEditor");
        if (window.position.position == Vector2.zero)
        {
            Resolution res = Screen.currentResolution;
        }

        window.position = new Rect(100, 20, 400, 700);
        window.Show();
    }
    //------------------------------配置
    int row=3;
    int col = 7;
    public static string[] isMantle = {"i_1","i_2","i_3"};
    public static float gridWidth = 40;
    public static string rootPath = "Assets/Editor/BattleMatrixEditor/";

    List<GUIContent> contentGround;
    List<GUIContent> contentMantle;

    public bool IsMantle(string name){
        foreach (var con  in isMantle) {
            if (name.Equals (con)) {
                return true;
            }
        }
        return false;
    } 

    private void LoadBattleFlag(){
        contentGround = new List<GUIContent> ();
        contentMantle = new List<GUIContent> ();

        DirectoryInfo direction = new DirectoryInfo(rootPath); 
        FileInfo[] files = direction.GetFiles("*.png",SearchOption.AllDirectories); 
        Debug.Log ("地图贴图个数: " + files.Length);

        foreach (var file in files) {
            var tex = AssetDatabase.LoadAssetAtPath<Texture> (rootPath + file.Name);
            var chunk = new GUIContent (tex);
            if (chunk != null) {
                if (IsMantle (chunk.image.name)) {
                    contentMantle.Add (chunk);
                } else {
                    contentGround.Add (chunk);
                }
            }
        }

        dufaultTexture = AssetDatabase.LoadAssetAtPath<Texture> (rootPath + defaultName +".png");
    }

    List<List<MapChunk[,]>> diffiList = new List<List<MapChunk[,]>>();

    private void AddSpanConfig(List<MapChunk[,]> spanList){
        MapChunk[,] spanItemList = new MapChunk[row,col];
        for (int i = 0; i < row; i++) {
            for (int j = 0; j < col; j++) {
                spanItemList [i, j] = new MapChunk(new GUIContent (dufaultTexture));
            }
        }
        spanList.Add (spanItemList);
    }

    private void AddDiffiConfig(){
        List<MapChunk[,]> spanList = new List<MapChunk[,]>();
        diffiList.Add (spanList);
    }

    string defaultName = "E";
    Texture dufaultTexture;
    public void Awake(){
        LoadBattleFlag ();
    }

    private string align( int count){
        string s = "";
        for (int i = 0; i < count; i++) {
            s += "\t";
        }
        return s;
    }

    private void Save(){
        using (FileStream fs = File.Open (rootPath + "map.txt", FileMode.Create))
        {
            StreamWriter sw = new StreamWriter(fs);
            sw.WriteLine("rollMatrixPool =");
            sw.WriteLine("{");
            for (int i = 1; i <= diffiList.Count; i++) {
                sw.WriteLine(align(1) + "["+ i +"] =");
                sw.WriteLine(align(1) + "{");
                var cons = diffiList [i-1];
                foreach (var con in cons) {
                    sw.WriteLine(align(2) + "{");
                    for (int m = 0; m < row; m++) {
                        string s = align(3) + "{ ";
                        for (int n = 0; n < col; n++) {
                            var chunk = con[m, n];
                            s += "\"";
                            if (chunk.con != null && chunk.con.image && chunk.con.image)
                                s += chunk.con.image.name;
                            if (chunk.mantleTexture != null)
                                s += "," + chunk.mantleTexture.name;
                            s += "\",";

                        }
                        s += "},";
                        sw.WriteLine(s);
                    }
                    sw.WriteLine(align(2) + "},");
                }
                sw.WriteLine(align(1) + "},");
            }
            sw.WriteLine("}");
            sw.Close();
            fs.Close();
            Debug.Log ("SAVE FINISH ");
        }
    }

    private void Load(){
        diffiList.Clear ();
        using (FileStream fs = File.Open (rootPath + "map.txt", FileMode.Open)) {
            StreamReader sr = new StreamReader (fs);
            string szMap = sr.ReadToEnd ();

            List<string> grid = new List<string> ();

            int diffiIndex = 0;
            while (diffiIndex >= 0) {
                int diffiIndexB = szMap.IndexOf ('[', diffiIndex);
                int diffiIndexE = -1;
                string work = "";
                if (diffiIndexB >= 0) {
                    diffiIndexE = szMap.IndexOf ('[', diffiIndexB+1);
                    if (diffiIndexE >= 0) {
                        work = szMap.Substring (diffiIndexB, diffiIndexE - diffiIndexB);
                    } else {
                        work = szMap.Substring (diffiIndexB);
                    }
                }

                string[] info =  work.Split ('\"');
                for (int i = 0; i < info.Length; i++) {
                    if (i % 2 == 1) {
                        grid.Add (info [i]);
                    }
                }
                LoadConfigToDiffic (grid);
//              int gridIndex = 1;
//              while (gridIndex >= 1) {
//                  int gridIndexB = work.IndexOf ('\"', gridIndex);
//                  int gridIndexE = -1;
//                  string szGrid = "";
//                  if (gridIndexB >= 0) {
//                      gridIndexB++;
//                      gridIndexE = work.IndexOf ('\"', gridIndexB);
//                      if (gridIndexE >= 0) {
//                          count++;
//                          szGrid = work.Substring (gridIndexB, gridIndexE - gridIndexB);
//                      }
//                  }
//                  Debug.Log (szGrid);
//                  gridIndex = gridIndexE + 1;
//              }
                grid.Clear();
                diffiIndex = diffiIndexE;
            }
            Debug.Log ("LOAD FINISH");
            sr.Close ();
            fs.Close ();
        }
    }

    private void LoadConfigToDiffic(List<string> confs){
        if (confs == null) {return;}

        int confCount = confs.Count / (row * col);
        int index = 0;
        List<MapChunk[,]> spanList = new List<MapChunk[,]>();
        for (int i = 0; i < confCount; i++) {
            MapChunk[,] spanItemList = new MapChunk[row,col];
            for (int m = 0; m < row; m++) {
                for (int n = 0; n < col; n++) {
                    spanItemList [m, n] = madeMapGrid(confs[index++]) ;//new MapChunk(new GUIContent (dufaultTexture));
                }
            }
            spanList.Add (spanItemList);
        }
        diffiList.Add (spanList);
    }

    private MapChunk madeMapGrid(string name){
        var chunk = new MapChunk ();
        string[] gI = name.Split (',');
        if (gI.Length >= 0) {
            chunk.setGround (gI [0]);
        }
        if (gI.Length > 1) {
            chunk.setMatrix (gI [1]);
        }
        return chunk;
    }

    int currentGroundIndex = -1;
    int currentMantleIndex = -1;
    Vector2 scrollPos;

    private void OnGUI(){
        EditorGUILayout.BeginHorizontal();
        if (GUILayout.Button("保存", GUILayout.Width(100))){
            Save ();
        } 
        if (GUILayout.Button("读取", GUILayout.Width(100))){
            Load ();
        } 
        EditorGUILayout.EndHorizontal ();
        EditorGUILayout.BeginHorizontal();
        for (int i = 0; i < contentGround.Count; i++) {
            var con = contentGround [i];
            if (GUILayout.Button(con, GUILayout.Width(40), GUILayout.Height(40))){
                currentGroundIndex = i;
                currentMantleIndex = -1;
            }
        }
        EditorGUILayout.EndHorizontal ();
        EditorGUILayout.BeginHorizontal();
        for (int i = 0; i < contentMantle.Count; i++) {
            var con = contentMantle [i];
            if (GUILayout.Button(con, GUILayout.Width(40), GUILayout.Height(40))){
                currentMantleIndex = i;
                currentGroundIndex = -1;
            }
        }
        EditorGUILayout.EndHorizontal ();

        if (GUILayout.Button("添加难度", GUILayout.Width(100))){
            AddDiffiConfig ();
        } 

        scrollPos = EditorGUILayout.BeginScrollView (scrollPos);
        for (int n = 0; n < diffiList.Count; n++) {
            var spanList = diffiList [n];

            EditorGUILayout.BeginHorizontal();
            GUILayout.Space(30);
            EditorGUILayout.LabelField ("难度:"+n.ToString(), GUILayout.Width(50));
            if (GUILayout.Button("添加配置", GUILayout.Width(100))){
                AddSpanConfig (spanList);
            } 
            if (GUILayout.Button("删除该难度", GUILayout.Width(100))){
                diffiList.Remove(spanList);
            } 
            EditorGUILayout.EndHorizontal ();

            for (int m = 0; m < spanList.Count; m++) {

                EditorGUILayout.BeginHorizontal();
                GUILayout.Space(60);

                EditorGUILayout.LabelField ("配置:"+m.ToString(),GUILayout.Width(50));
                if (GUILayout.Button("删除配置", GUILayout.Width(100))){
                    spanList.RemoveAt (m);
                    return;
                } 
                EditorGUILayout.EndHorizontal ();
                GUILayout.BeginHorizontal();
                GUILayout.Space(60);
                GUILayout.Box("",GUILayout.Width(col*gridWidth),GUILayout.Height(row*gridWidth));
                Rect r = GUILayoutUtility.GetLastRect ();
                var item = spanList [m];
                for (int i = 0; i < row; i++) {
                    float y = r.y + i * gridWidth;
                    for (int j = 0; j < col; j++) {
                        float x = r.x + j * gridWidth;
                        var grid = item [i, j];
                        grid.setPos (x, y);
                        var con = grid.con;
                        if (GUI.Button(grid.rect, con)){
                            if (currentGroundIndex >= 0) {
                                con.image = contentGround [currentGroundIndex].image;
                            }
                            if (currentMantleIndex >= 0) {
                                var tex = grid.mantleTexture;
                                var curTex = contentMantle [currentMantleIndex].image;
                                if (grid.mantleTexture == null) {
                                    grid.mantleTexture = curTex;
                                } else {
                                    if (tex.Equals (curTex))
                                        grid.mantleTexture = null;
                                    else
                                        grid.mantleTexture = curTex;
                                }
                            }
                        }
                        if (grid.mantleTexture != null) {
                            GUI.DrawTexture (grid.rect, grid.mantleTexture);
                        }
                    }
                }
                GUILayout.EndHorizontal ();
            }
        }
        EditorGUILayout.EndScrollView ();
    }
}

猜你喜欢

转载自blog.csdn.net/wdsdsdsds/article/details/79913707