Unity editor extension - a match-3 map editor based on EditorWindow

renderings

write picture description here

export configuration file
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",},
        },
    },
}

Since the exported configuration content needs to be provided to lua for table reading, there is no data structure in c# that can be converted with lua's table. At first, I wanted to combine operations with lua and c#, and then read and store data through lua, and c# was used to operate the editor. However, the slua used in the project cannot directly register c# functions into the intermediate stack like ulua when lua calls c#. It needs to export c# as a library before it can be called. Only use string operations. Thief trouble.

Editor extension control classification

Mainly GUILayout, EditorGUILayout, GUI, EditorGUI.
Among them, EditorGUILayout and EditorGUI feel that they are specially developed for editors, because they need to use UnityEditor; while GUILayout and GUI need to use UnityEngine; but in the process of use, it is found that these two controls are very contradictory. For example, GUILayout has no intpopup and EditorGUI has no buttons. So I think it's okay to mix it up.

Image overlay, button image overlay

If you use layout, there is no way to stack like this. Bar? I didn't find it anyway. .
The solution is to set the Rect by using the GUI class. GUI classes do not use Auto Layout, so you need to specify Rect when creating controls using this library. If you need a button use a layout and then overlay an image on it. At this time, the image superimposed above can use GUI.DrawTexture(rect, texture). How to get the rectangle of the button? Rect r = GUILayoutUtility.GetLastRect (); This function can get the rectangle of the control that used the layout for the last time.

#GUILayout mixed with GUI controls.

write picture description here
In fact, many buttons in the picture do not use layout layout, and the coordinates are calculated. The implementation process is

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);
Various configuration file handling

Because the editor is for planning, various practical configurations are reduced.
For example, the type of map element, get all pngs in the configuration directory as textures

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);
                }
            }
        }
all code
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 ();
    }
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324414830&siteId=291194637