using System.Text.RegularExpressions; using System; using System.Linq.Expressions; using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEditor; using System.IO; using Newtonsoft.Json; using Newtonsoft.Json.Linq; namespace BFEditor { public class BoardEditorWindow : EditorWindow { // private static void ShowWindow() { // var window = GetWindow(); // window.titleContent = new GUIContent("BoardWindow"); // window.Show(); // } const string BOARD_EXCEL_KEY = "bf_board_excel_key"; const string BOARD_GRID_TYPE_KEY = "bf_board_grid_type_key"; const string BOARD_GRID_EDGE_KEY = "bf_board_grid_edge_key"; int gridCount = 49; string battleImgDirectory = "Assets/arts/textures/ui/battle/"; string boardFilepath; string boardGridTypePath; string boardGridEdgePath; string boardFiledName = "board"; string boardEdgeFiledName = "grid_edge"; string randomTypeStr = ""; string boardEdgeStr = ""; int curIndex = 1; int maxRow = 7; Dictionary> boardGridTypeDict = new Dictionary>(); Dictionary boardDict = new Dictionary(); Dictionary outPutBoardDict = new Dictionary(); Dictionary imgDict = new Dictionary(); Dictionary> boardGridEdgeDict = new Dictionary>(); Dictionary edgeDict = new Dictionary(); Dictionary outPutBoardEdgeDict = new Dictionary(); bool loadExcelOver = false; Dictionary elementTypeImgDict = new Dictionary(){ [1] = "red_1", [2] = "yellow_1", [3] = "green_1", [4] = "blue_1", [5] = "purple_1" }; Texture boardImg; private void OnEnable() { loadExcelOver = false; boardFilepath = GetBoardExcelPath(); if (boardFilepath.Equals("")) { boardFilepath = "选择配置表路径"; } boardGridTypePath = GetBoardGridTypePath(); if (boardGridTypePath.Equals("")) { boardGridTypePath = "选择grid_type配置表路径"; } boardGridEdgePath = GetBoardGridEdgePath(); if (boardGridEdgePath.Equals("")) { boardGridEdgePath = "选择grid_edge_type配置表路径"; } string[] paths = Directory.GetFiles(battleImgDirectory); foreach(var path in paths) { if(!path.EndsWith(".meta")) { string formatPath = Path.GetFileNameWithoutExtension(path); imgDict[formatPath] = AssetDatabase.LoadAssetAtPath(path); } } boardImg = AssetDatabase.LoadAssetAtPath("Assets/arts/textures/background/battle_common/chessboard_1.png"); } string GetBoardExcelPath() { return PlayerPrefs.GetString(BOARD_EXCEL_KEY, ""); } void SetBoardExcelPath(string path) { PlayerPrefs.SetString(BOARD_EXCEL_KEY, path); } string GetBoardGridTypePath() { return PlayerPrefs.GetString(BOARD_GRID_TYPE_KEY, ""); } void SetBoardGridTypePath(string path) { PlayerPrefs.SetString(BOARD_GRID_TYPE_KEY, path); } string GetBoardGridEdgePath() { return PlayerPrefs.GetString(BOARD_GRID_EDGE_KEY, ""); } void SetBoardGridEdgePath(string path) { PlayerPrefs.SetString(BOARD_GRID_EDGE_KEY, path); } BoardEditorWindow() { this.titleContent = new GUIContent("棋盘编辑器"); } private void OnGUI() { DrawBaseInfo(); DragBoard(); } void DrawBaseInfo() { GUILayout.BeginVertical(); GUILayout.Space(10); GUILayout.BeginHorizontal(); GUILayout.Label("grid_type 路径", GUILayout.Width(100)); GUILayout.Space(10); GUILayout.TextField(boardGridTypePath, GUILayout.Width(300)); if (GUILayout.Button("选择", GUILayout.Width(80))) { string openPath = EditorUtility.OpenFilePanel("选择配置表", GetBoardGridTypePath(), ""); if (openPath.CompareTo("") != 0) { boardGridTypePath = openPath; SetBoardGridTypePath(openPath); } } GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); GUILayout.Label("grid_edge 路径", GUILayout.Width(100)); GUILayout.Space(10); GUILayout.TextField(boardGridEdgePath, GUILayout.Width(300)); if (GUILayout.Button("选择", GUILayout.Width(80))) { string openPath = EditorUtility.OpenFilePanel("选择配置表", GetBoardGridEdgePath(), ""); if (openPath.CompareTo("") != 0) { boardGridEdgePath = openPath; SetBoardGridEdgePath(openPath); } } GUILayout.EndHorizontal(); GUILayout.Space(10); GUILayout.BeginHorizontal(); GUILayout.Label("配置表路径", GUILayout.Width(100)); GUILayout.Space(10); GUILayout.TextField(boardFilepath, GUILayout.Width(300)); if (GUILayout.Button("选择", GUILayout.Width(80))) { string openPath = EditorUtility.OpenFilePanel("选择配置表", GetBoardExcelPath(), ""); if (openPath.CompareTo("") != 0) { boardFilepath = openPath; SetBoardExcelPath(openPath); } } GUILayout.EndHorizontal(); GUILayout.Space(10); GUILayout.BeginHorizontal(); GUILayout.Label("字段名称", GUILayout.Width(100)); GUILayout.Space(10); boardFiledName = GUILayout.TextField(boardFiledName, GUILayout.Width(200)); GUILayout.EndHorizontal(); GUILayout.Space(10); GUILayout.BeginHorizontal(); if (GUILayout.Button("加载棋盘", GUILayout.Width(80))) { LoadBoardExcel(); } GUILayout.Label("棋盘数量", GUILayout.Width(100)); gridCount = int.Parse(GUILayout.TextField(gridCount.ToString(), GUILayout.Width(200))); maxRow = (int)(gridCount / 7); GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); if (!IsInNewBoard()) { if (GUILayout.Button("上一张", GUILayout.Width(80))) { showSwitchBoardSaveDialog(Math.Max(curIndex - 1, 1)); } } GUILayout.BeginHorizontal(GUILayout.Width(80)); GUIStyle style = new GUIStyle(GUI.skin.label); style.alignment = TextAnchor.MiddleCenter; GUILayout.Label("当前编号id = ", style); showSwitchBoardSaveDialog(int.Parse(GUILayout.TextField(curIndex.ToString(), GUILayout.Width(40)))); GUILayout.EndHorizontal(); if (!IsInNewBoard()) { if (GUILayout.Button("下一张", GUILayout.Width(80))) { showSwitchBoardSaveDialog(Math.Min(curIndex + 1, boardDict.Count)); } } if (GUILayout.Button("复制当前棋盘", GUILayout.Width(80))) { if (!boardDict.ContainsKey(curIndex)) { return; } JArray jo = boardDict[curIndex]; GUIUtility.systemCopyBuffer = JsonConvert.SerializeObject(jo); } if (GUILayout.Button("粘贴棋盘", GUILayout.Width(80))) { JArray jo = (JArray)JsonConvert.DeserializeObject(GUIUtility.systemCopyBuffer); if (jo == null) { return; } boardDict[curIndex] = jo; } if (!IsInNewBoard()) { if (GUILayout.Button("新建棋盘", GUILayout.Width(80))) { curIndex = outPutBoardDict.Count + 1; boardDict[curIndex] = new JArray(); for (int i = 0; i < gridCount; i++) { JArray unit = (JArray)JsonConvert.DeserializeObject("[0, 0]"); boardDict[curIndex].Add(unit); } } } else { if (GUILayout.Button("退出新建棋盘", GUILayout.Width(80))) { boardDict.Remove(curIndex); curIndex = outPutBoardDict.Count; } if (GUILayout.Button("保存当前棋盘", GUILayout.Width(80))) { SaveBoard(curIndex); } } GUILayout.EndHorizontal(); GUILayout.EndVertical(); GUILayout.BeginArea(new Rect(730, 500, 500, 100)); GUILayout.BeginVertical(); GUILayout.Label("随机类型和数量[类型,数量] 空格 [类型,数量]"); randomTypeStr = GUILayout.TextField(randomTypeStr, GUILayout.Width(500)); GUILayout.BeginHorizontal(); if(GUILayout.Button("生成随机棋盘", GUILayout.Width(80))) { string[] units = randomTypeStr.Split('['); Dictionary dict = new Dictionary(); for (int i = 0; i < units.Length; i++) { string formatStr = units[i].Replace("[", "").Replace("]", "").Replace(" ", ""); string[] unitList = formatStr.Split(','); if (unitList.Length >= 2) { dict[int.Parse(unitList[0])] = int.Parse(unitList[1]); } } List list = new List(); for (int i = 0; i < gridCount; i++) { list.Add(i); } JArray ja = new JArray(); for (int i = 0; i < gridCount; i++) { JArray unit = (JArray)JsonConvert.DeserializeObject("[0, 0]"); ja.Add(unit); } foreach (int gridType in dict.Keys) { for(int i = 0; i < dict[gridType]; i++) { int index = UnityEngine.Random.Range(0, list.Count); ja[list[index]][0] = gridType; list.RemoveAt(index); } } boardDict[curIndex] = ja; } if(GUILayout.Button("生成随机棋盘+元素", GUILayout.Width(110))) { string[] units = randomTypeStr.Split('['); Dictionary dict = new Dictionary(); for (int i = 0; i < units.Length; i++) { string formatStr = units[i].Replace("[", "").Replace("]", "").Replace(" ", ""); string[] unitList = formatStr.Split(','); if (unitList.Length >= 2) { dict[int.Parse(unitList[0])] = int.Parse(unitList[1]); } } List list = new List(); for (int i = 0; i < gridCount; i++) { list.Add(i); } JArray ja = new JArray(); for (int i = 0; i < gridCount; i++) { ja.Add(getNewGridUnitInfo()); } foreach (int gridType in dict.Keys) { for(int i = 0; i < dict[gridType]; i++) { int index = UnityEngine.Random.Range(0, list.Count); ja[list[index]][0] = gridType; list.RemoveAt(index); } } for (int i = 0; i < ja.Count; i++) { int gridType = (int)(ja[i][0]); Dictionary gridTypeDict = boardGridTypeDict[gridType]; if (gridTypeDict.ContainsKey("break_stay_element") || !gridTypeDict.ContainsKey("element_invalid")) { ja[i][1] = UnityEngine.Random.Range(1, 6); } } boardDict[curIndex] = ja; } GUILayout.EndHorizontal(); GUILayout.EndVertical(); GUILayout.EndArea(); GUILayout.BeginArea(new Rect(730, 650, 500, 100)); GUILayout.BeginVertical(); GUILayout.Label("棋盘边缘元素"); boardEdgeStr = GUILayout.TextField(boardEdgeStr, GUILayout.Width(500), GUILayout.Height(300)); if(GUILayout.Button("加载边缘元素配置")) { JArray edgeJo = edgeDict[curIndex]; string str = "["; for (int i = 0; i < edgeJo.Count; i++) { JArray gridInfo = (JArray)edgeJo[i]; if (gridInfo.Count < 3) { continue; } string s = "{"; for (int j = 0; j < 3; j++) { s = s + gridInfo[j].ToString(); if(j != 2) { s = s + ", "; } } s = s + "}"; str = str + s; if (i != edgeJo.Count) { str = str + ", "; } } boardEdgeStr = str; } if(GUILayout.Button("重新刷新边缘元素")) { string[] units = boardEdgeStr.Split('{'); List edgeList = new List(); for (int i = 0; i < units.Length; i++) { string formatStr = units[i].Replace("[", "").Replace("]", "").Replace(" ", "").Replace("}", ""); string[] unitList = formatStr.Split(','); if (unitList.Length >= 3) { string str = "["; for(int j = 0; j < 3; j++) { str = str + unitList[j]; if (j != 2) { str = str + ","; } } str = str + "]"; edgeList.Add(str); } } JArray ja = new JArray(); for (int i = 0; i < edgeList.Count; i++) { JArray unit = (JArray)JsonConvert.DeserializeObject(edgeList[i]); ja.Add(unit); } edgeDict[curIndex] = ja; } GUILayout.EndVertical(); GUILayout.EndArea(); if(GUI.Button(new Rect(1050, 10, 100, 30), "导出到Excel")) { if (CheckBoardChanged(curIndex)) { switch (EditorUtility.DisplayDialogComplex("提示", "当前棋盘已经改变,是否保存", "确定", "放弃", "再次确认")) { case 0: SaveBoard(curIndex); SaveBoardExcel(); break; case 1: AbortBoard(curIndex); SaveBoardExcel(); break; case 2: break; default: break; } } else { SaveBoardExcel(); } } } void LoadBoardExcel() { var desktopDir = System.Environment.GetFolderPath(System.Environment.SpecialFolder.DesktopDirectory); var tempPath = System.IO.Path.Combine(desktopDir, "BoardEditorTemp.txt"); string relitivePath = Application.dataPath; relitivePath = relitivePath.Remove(relitivePath.Length - 6, 6); string pythonToolPath = relitivePath + "Tools/tranexcel_new"; // 读取grid_type配置表 BFEditorUtils.RunCommond("python", "load_board.py " + tempPath + " " + boardGridTypePath, pythonToolPath); string boardGridTypeJson = File.ReadAllText(tempPath); JObject jsonObj = (JObject)JsonConvert.DeserializeObject(boardGridTypeJson); foreach (var item in jsonObj) { int key = int.Parse(item.Key); Dictionary dict = new Dictionary(); foreach (var item2 in (JObject)item.Value) { dict[item2.Key] = item2.Value.ToString(); } boardGridTypeDict[key] = dict; } // 读取grid_edge_type配置表 BFEditorUtils.RunCommond("python", "load_board.py " + tempPath + " " + boardGridEdgePath, pythonToolPath); string boardGridEdgeJson = File.ReadAllText(tempPath); jsonObj = (JObject)JsonConvert.DeserializeObject(boardGridEdgeJson); foreach (var item in jsonObj) { int key = int.Parse(item.Key); Dictionary dict = new Dictionary(); foreach (var item2 in (JObject)item.Value) { dict[item2.Key] = item2.Value.ToString(); } boardGridEdgeDict[key] = dict; } // 读取boardFile配置表 BFEditorUtils.RunCommond("python", "load_board.py " + tempPath + " " + boardFilepath, pythonToolPath); string boardFileJson = File.ReadAllText(tempPath); jsonObj = (JObject)JsonConvert.DeserializeObject(boardFileJson); foreach (var item in jsonObj){ if (item.Value[boardFiledName] != null) { int key = int.Parse(item.Key); boardDict[key] = copyBoard((JArray)item.Value[boardFiledName]); outPutBoardDict[key] = copyBoard((JArray)item.Value[boardFiledName]); } if (item.Value[boardEdgeFiledName] != null) { int key = int.Parse(item.Key); edgeDict[key] = copyBoard((JArray)item.Value[boardEdgeFiledName]); outPutBoardEdgeDict[key] = copyBoard((JArray)item.Value[boardEdgeFiledName]); } } loadExcelOver = true; } void SaveBoardExcel() { var desktopDir = System.Environment.GetFolderPath(System.Environment.SpecialFolder.DesktopDirectory); var tempPath = System.IO.Path.Combine(desktopDir, "BoardEditorTemp.txt"); Dictionary> output = new Dictionary>(); foreach(int key in outPutBoardDict.Keys) { output[key] = new Dictionary(); output[key][boardFiledName] = copyBoard(outPutBoardDict[key]); } string relitivePath = Application.dataPath; relitivePath = relitivePath.Remove(relitivePath.Length - 6, 6); string pythonToolPath = relitivePath + "Tools/tranexcel_new"; File.WriteAllText(tempPath, JsonConvert.SerializeObject(output)); BFEditorUtils.RunCommond("python", "save_board.py " + tempPath + " " + boardFilepath, pythonToolPath); } void DragBoard() { Texture img; GUI.DrawTexture(new Rect(0, 200, 702, 702), boardImg); if(!loadExcelOver) { return; } int startOffset = 22 * 7 / maxRow; int textureWidth = 94 * 7 / maxRow; if (!boardDict.ContainsKey(curIndex)) { return; } GUILayout.BeginArea(new Rect(0, 200, 702, 702)); GUILayout.BeginVertical(); JArray jo = boardDict[curIndex]; int posIndex = 0; for (int row = 1; row <= maxRow; row++) { GUILayout.BeginHorizontal(); for (int col = 1; col <= 7; col++) { if (jo.Count == posIndex) { jo.Add(getNewGridUnitInfo()); } JArray gridInfo = (JArray)jo[posIndex]; if(gridInfo.Count < 2) { continue; } int gridType = (int)gridInfo[0]; int gridElementType = (int)gridInfo[1]; if(!boardGridTypeDict.ContainsKey(gridType)) { continue; } // 绘制元素 if (elementTypeImgDict.ContainsKey(gridElementType)) { img = imgDict[elementTypeImgDict[gridElementType]]; GUI.DrawTexture(new Rect(startOffset + (col - 1) * textureWidth, startOffset + (row - 1) * textureWidth, textureWidth, textureWidth), img); } // 绘制类型 if(boardGridTypeDict[gridType].ContainsKey("icon")) { string icon = boardGridTypeDict[gridType]["icon"]; if (imgDict.ContainsKey(icon)) { img = imgDict[icon]; GUI.DrawTexture(new Rect(startOffset + (col - 1) * textureWidth, startOffset + (row - 1) * textureWidth, textureWidth, textureWidth), img); } } posIndex++; } GUILayout.EndHorizontal(); } GUILayout.EndVertical(); if (edgeDict.ContainsKey(curIndex)) { JArray edgeJo = edgeDict[curIndex]; for (int i = 0; i < edgeJo.Count; i++) { JArray gridInfo = (JArray)edgeJo[i]; if(gridInfo.Count < 3) { continue; } int posId = (int)gridInfo[0]; int edgeType = (int)gridInfo[1]; int dir = (int)gridInfo[2]; // 绘制类型 if(boardGridEdgeDict[edgeType].ContainsKey("icon")) { string icon = boardGridEdgeDict[edgeType]["icon"]; if (imgDict.ContainsKey(icon)) { int row = posId / 10; int col = posId % 10; img = imgDict[icon]; if (dir == 1) { GUI.DrawTexture(new Rect(startOffset + (col - 1) * textureWidth, startOffset + (row - 1) * textureWidth - 16, 92, 32), img); } else if (dir == 2) { GUI.DrawTexture(new Rect(startOffset + (col - 1) * textureWidth, startOffset + (row - 1) * textureWidth - 16 + textureWidth, 92, 32), img); } else if (dir == 3) { GUI.DrawTexture(new Rect(startOffset + (col - 1) * textureWidth - 16, startOffset + (row - 1) * textureWidth - 16, 32, 92), img); } else if (dir == 4) { GUI.DrawTexture(new Rect(startOffset + (col - 1) * textureWidth - 16 + textureWidth, startOffset + (row - 1) * textureWidth - 16, 32, 92), img); } } } } } GUILayout.EndArea(); GUILayout.BeginArea(new Rect(730, 200, 510 * 7, 550 / 7 * maxRow)); GUILayout.BeginVertical(); GUILayout.BeginHorizontal(); GUILayout.Label("棋盘配置信息", GUILayout.Width(100), GUILayout.Height(30)); GUILayout.EndHorizontal(); posIndex = 0; for (int row = 1; row <= maxRow; row++) { GUILayout.BeginHorizontal(); for (int col = 1; col <= 7; col++) { JArray gridInfo = (JArray)jo[posIndex]; if(gridInfo.Count < 2) { continue; } gridInfo[0] = int.Parse(GUILayout.TextField(gridInfo[0].ToString(), GUILayout.Width(25))); gridInfo[1] = int.Parse(GUILayout.TextField(gridInfo[1].ToString(), GUILayout.Width(25))); GUILayout.Space(10); posIndex++; } GUILayout.EndHorizontal(); GUILayout.Space(10); } GUILayout.EndVertical(); GUILayout.EndArea(); } bool CheckBoardChanged(int index) { if(boardDict.ContainsKey(index) && outPutBoardDict.ContainsKey(index)) { if(outPutBoardDict[index].Count != boardDict[index].Count) { return true; } for (int i = 0; i < boardDict[index].Count; i++) { JArray tArray = (JArray)boardDict[index][i]; JArray tArray2 = (JArray)outPutBoardDict[index][i]; if (tArray.Count != tArray2.Count) { return true; } for (int j = 0; j < tArray.Count; j++) { if (tArray[j].ToString() != tArray2[j].ToString()) { return true; } } } } return false; } void SaveBoard(int index) { if(!boardDict.ContainsKey(index)) { return; } outPutBoardDict[index] = copyBoard(boardDict[index]); } void AbortBoard(int index) { if(!outPutBoardDict.ContainsKey(index)) { boardDict.Remove(index); return; } boardDict[index] = copyBoard(outPutBoardDict[index]); } void showSwitchBoardSaveDialog(int targetIndex) { if (IsInNewBoard()) { return; } if (targetIndex == curIndex) { return; } if (CheckBoardChanged(curIndex)) { switch (EditorUtility.DisplayDialogComplex("提示", "当前棋盘已经改变,是否保存", "确定", "放弃", "再次确认")) { case 0: SaveBoard(curIndex); curIndex = targetIndex; break; case 1: AbortBoard(curIndex); curIndex = targetIndex; break; case 2: break; default: break; } } else { curIndex = targetIndex; } } JArray copyBoard(JArray targetArray) { JArray resultArray = new JArray(); for (int i = 0; i < targetArray.Count; i++) { JArray unit = new JArray(); resultArray.Add(unit); JArray temp = (JArray)targetArray[i]; for (int j = 0; j < temp.Count; j++) { unit.Add(int.Parse(temp[j].ToString())); } } return resultArray; } bool IsInNewBoard() { if(!boardDict.ContainsKey(curIndex) && !outPutBoardDict.ContainsKey(curIndex)) { return false; } return !outPutBoardDict.ContainsKey(curIndex); } JArray getNewGridUnitInfo() { return (JArray)JsonConvert.DeserializeObject("[0, 0]"); } } }