/* * @Author: 白哉 * @Description: 编辑器 * @Date: 2025年04月22日 星期二 15:04:14 * @Modify: */ using System.Collections.Generic; using System.IO; using Logic.Achievement; using Logic.AI; using Logic.CrashSight; using Logic.HeroTask; using Logic.Multilingual; using NUnit.Framework; using RuntimeData; using TH1_Logic.Core; using TH1_Logic.HeroTask; using TH1_Logic.MatchConfig; using UnityEditor; using UnityEngine; namespace Logic.Editor { public class MatchConfigEditorWindow : EditorWindow { // 滑条 private Vector2 _barPosition; // 背景 private GUIStyle _redBoxStyle; private GUIStyle _whiteBoxStyle; private List _levelStrList; private uint _selectedId; private List _mapNameList; private string _selectedMapName; private uint _newConfigId = 1; private Dictionary _settlementFoldouts = new Dictionary(); private Dictionary _taskFoldouts = new Dictionary(); [MenuItem("Tools/关卡编辑器")] private static void ShowWindow() { var window = CreateWindow(); window.titleContent = new GUIContent("关卡编辑器"); window.Show(); } private void OnEnable() { _levelStrList = new List(); _mapNameList = new List(); MatchConfigManager.Instance.Init(); RefreshMapNameList(); } private void OnGUI() { if (_redBoxStyle == null) { _redBoxStyle = InspectorUtils.GetHelpBoxStyle(); InspectorUtils.AddBorder(_redBoxStyle, new Color(0.5f, 0.4f, 0.4f, 0.6f)); } if (_whiteBoxStyle == null) { _whiteBoxStyle = InspectorUtils.GetHelpBoxStyle(); InspectorUtils.AddBorder(_whiteBoxStyle, new Color(1f, 1f, 1f, 0.2f)); } GUI.skin.button.wordWrap = true; _barPosition = EditorGUILayout.BeginScrollView(_barPosition); EditorGUILayout.BeginHorizontal(); _newConfigId = (uint)EditorGUILayout.IntField((int)_newConfigId, GUILayout.Width(300)); if (InspectorUtils.InspectorButtonWithTextWidth("新增关卡")) { MatchConfigManager.Instance.AddMatchConfig(_newConfigId); } if (InspectorUtils.InspectorButtonWithTextWidth("刷新")) { RefreshMapNameList(); } if (InspectorUtils.InspectorButtonWithTextWidth("保存")) { MatchConfigManager.Instance.SaveMatchLevelData(); } EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); InspectorUtils.InspectorTextWidthRich($" 选择关卡 : "); var index = GetIndexInLevelList(_selectedId); index = EditorGUILayout.Popup(index, _levelStrList.ToArray(), GUILayout.Width(300)); if (_levelStrList.Count != 0) _selectedId = uint.TryParse(_levelStrList[index], out var id) ? id : 0; EditorGUILayout.EndHorizontal(); EditorGUILayout.Space(); var mapConfig = MatchConfigManager.Instance.GetMatchConfig(_selectedId); if(mapConfig != null) OnGUIMapConfig(mapConfig); EditorGUILayout.EndScrollView(); } private void OnGUIMapConfig(MapConfig mapConfig) { EditorGUILayout.BeginVertical(); // 基础配置 if (InspectorUtils.InspectorButtonWithTextWidth("删除关卡")) { if (EditorUtility.DisplayDialog("确认删除", $"确定要删除关卡 {mapConfig.Id} 吗?", "确定", "取消")) { MatchConfigManager.Instance.LevelData.LevelConfigs.Remove(mapConfig.Id); _selectedId = 0; } } InspectorUtils.InspectorTextWidthRich("基础配置"); EditorGUILayout.BeginHorizontal(); InspectorUtils.InspectorTextWidthRich("关卡ID:"); mapConfig.Id = (uint)EditorGUILayout.IntField((int)mapConfig.Id, GUILayout.Width(200)); EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); InspectorUtils.InspectorTextWidthRich("地图宽度:"); mapConfig.Width = (uint)EditorGUILayout.IntField((int)mapConfig.Width, GUILayout.Width(200)); EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); InspectorUtils.InspectorTextWidthRich("地图高度:"); mapConfig.Height = (uint)EditorGUILayout.IntField((int)mapConfig.Height, GUILayout.Width(200)); EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); InspectorUtils.InspectorTextWidthRich("玩家数量:"); mapConfig.PlayerCount = (uint)EditorGUILayout.IntField((int)mapConfig.PlayerCount, GUILayout.Width(200)); EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); InspectorUtils.InspectorTextWidthRich("AI难度:"); mapConfig.AIDiff = (AIDifficult)EditorGUILayout.EnumPopup(mapConfig.AIDiff, GUILayout.Width(200)); EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); InspectorUtils.InspectorTextWidthRich("是否开启回合限时"); mapConfig.IsLimitTime = EditorGUILayout.Toggle(mapConfig.IsLimitTime, GUILayout.Width(200)); EditorGUILayout.EndHorizontal(); if (mapConfig.IsLimitTime) { EditorGUILayout.BeginHorizontal(); InspectorUtils.InspectorTextWidthRich("回合时长"); mapConfig.TimeLimitSeconds = EditorGUILayout.IntField(mapConfig.TimeLimitSeconds, GUILayout.Width(200)); EditorGUILayout.EndHorizontal(); } // 单机配置 InspectorUtils.InspectorTextWidthRich("单机配置"); EditorGUILayout.BeginHorizontal(); InspectorUtils.InspectorTextWidthRich("文明ID:"); mapConfig.selfCivId = (uint)EditorGUILayout.IntField((int)mapConfig.selfCivId, GUILayout.Width(200)); EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); InspectorUtils.InspectorTextWidthRich("势力ID:"); mapConfig.selfForceId = (uint)EditorGUILayout.IntField((int)mapConfig.selfForceId, GUILayout.Width(200)); EditorGUILayout.EndHorizontal(); EditorGUILayout.Space(); // 地图配置 InspectorUtils.InspectorTextWidthRich("地图配置"); EditorGUILayout.BeginHorizontal(); InspectorUtils.InspectorTextWidthRich("自定义地图:"); mapConfig.IsCustomMap = EditorGUILayout.Toggle(mapConfig.IsCustomMap, GUILayout.Width(200)); EditorGUILayout.EndHorizontal(); if (mapConfig.IsCustomMap) { EditorGUILayout.BeginHorizontal(); if (_mapNameList.Count == 0) InspectorUtils.InspectorTextWidthRich("无地图可用"); else { InspectorUtils.InspectorTextWidthRich("地图名称:"); var mapIndex = GetIndexInMapNameList(mapConfig.MapName); mapIndex = EditorGUILayout.Popup(mapIndex, _mapNameList.ToArray(), GUILayout.Width(200)); if (mapIndex >= 0 && mapIndex < _mapNameList.Count) { mapConfig.MapName = _mapNameList[mapIndex]; } } EditorGUILayout.EndHorizontal(); } EditorGUILayout.Space(); // Limit 配置 if (mapConfig.MatchLimits == null) mapConfig.MatchLimits = new List(); InspectorUtils.InspectorTextWidthRich("限制配置"); EditorGUILayout.BeginHorizontal(); if (InspectorUtils.InspectorButtonWithTextWidth("添加限制")) { mapConfig.MatchLimits.Add(MatchLimitType.None); mapConfig.RefreshLimits(); } EditorGUILayout.EndHorizontal(); var deleteIndex = -1; for (var i = 0; i < mapConfig.MatchLimits.Count; i++) { var limit = mapConfig.MatchLimits[i]; EditorGUILayout.BeginHorizontal(); mapConfig.MatchLimits[i] = (MatchLimitType)EditorGUILayout.EnumPopup(limit, GUILayout.Width(200)); InspectorUtils.InspectorTextWidthRich(MatchLimitData.GetMatchLimitTypeDesc(limit)); if (InspectorUtils.InspectorButtonWithTextWidth("x")) deleteIndex = i; EditorGUILayout.EndHorizontal(); } if (deleteIndex >= 0) mapConfig.MatchLimits.RemoveAt(deleteIndex); EditorGUILayout.Space(); // 结算配置 InspectorUtils.InspectorTextWidthRich("结算配置"); EditorGUILayout.BeginHorizontal(); InspectorUtils.InspectorTextWidthRich("对局结算类型:"); mapConfig.MatchSettlement = (MatchSettlementType)EditorGUILayout.EnumPopup(mapConfig.MatchSettlement, GUILayout.Width(200)); EditorGUILayout.EndHorizontal(); EditorGUILayout.Space(); if (InspectorUtils.InspectorButtonWithTextWidth("添加玩家结算器")) { mapConfig.PlayerSettlements.Add(new PlayerSettlementInfo()); } deleteIndex = -1; for (int i = 0; i < mapConfig.PlayerSettlements.Count; i++) { if (OnGUIPlayerSettlement(mapConfig.PlayerSettlements[i], i)) deleteIndex = i; } if (deleteIndex >= 0) mapConfig.PlayerSettlements.RemoveAt(deleteIndex); EditorGUILayout.EndVertical(); } private bool OnGUIPlayerSettlement(PlayerSettlementInfo settlementInfo, int index) { EditorGUILayout.BeginVertical(_redBoxStyle, GUILayout.Width(500)); EditorGUILayout.BeginHorizontal(GUILayout.Width(150)); _settlementFoldouts.TryAdd(settlementInfo, false); _settlementFoldouts[settlementInfo] = EditorGUILayout.Foldout(_settlementFoldouts[settlementInfo], $"玩家结算器 {index + 1}"); bool isDelete = InspectorUtils.InspectorButtonWithTextWidth("x"); if (!_settlementFoldouts[settlementInfo]) { EditorGUILayout.EndHorizontal(); EditorGUILayout.EndVertical(); return isDelete; } EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); InspectorUtils.InspectorTextWidthRich("玩家结算类型:"); settlementInfo.SettlementType = (PlayerSettlementType)EditorGUILayout.EnumPopup(settlementInfo.SettlementType, GUILayout.Width(200)); EditorGUILayout.EndHorizontal(); if (settlementInfo.Tasks == null) settlementInfo.Tasks = new List(); EditorGUILayout.BeginHorizontal(); if (InspectorUtils.InspectorButtonWithTextWidth("添加任务")) { var newTask = new PlayerTaskInfo(); settlementInfo.Tasks.Add(newTask); } EditorGUILayout.EndHorizontal(); // 显示所有任务 var deleteIndex = -1; for (int i = 0; i < settlementInfo.Tasks.Count; i++) { if(OnGUITask(settlementInfo.Tasks[i], i)) deleteIndex = i; } if (deleteIndex >= 0) settlementInfo.Tasks.RemoveAt(deleteIndex); EditorGUILayout.EndVertical(); EditorGUILayout.Space(); return isDelete; } private bool OnGUITask(PlayerTaskInfo taskInfo, int index) { EditorGUILayout.BeginVertical(_whiteBoxStyle, GUILayout.Width(500)); EditorGUILayout.BeginHorizontal(GUILayout.Width(150)); _taskFoldouts.TryAdd(taskInfo, false); _taskFoldouts[taskInfo] = EditorGUILayout.Foldout(_taskFoldouts[taskInfo], $"任务 {index + 1}"); bool isDelete = InspectorUtils.InspectorButtonWithTextWidth("x"); if (!_taskFoldouts[taskInfo]) { EditorGUILayout.EndHorizontal(); EditorGUILayout.EndVertical(); return isDelete; } EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); InspectorUtils.InspectorTextWidthRich("任务类型:"); taskInfo.TaskType = (PlayerTaskType)EditorGUILayout.EnumPopup(taskInfo.TaskType, GUILayout.Width(200)); EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); InspectorUtils.InspectorTextWidthRich($" 描述: {PlayerTaskLogicFactory.GetPlayerTaskTypeDesc(taskInfo.TaskType)} "); EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); InspectorUtils.InspectorTextWidthRich("参数1:"); taskInfo.Param1 = EditorGUILayout.IntField(taskInfo.Param1, GUILayout.Width(200)); EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); InspectorUtils.InspectorTextWidthRich("参数2:"); taskInfo.Param2 = EditorGUILayout.IntField(taskInfo.Param2, GUILayout.Width(200)); EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); InspectorUtils.InspectorTextWidthRich("参数3:"); taskInfo.Param3 = EditorGUILayout.IntField(taskInfo.Param3, GUILayout.Width(200)); EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); InspectorUtils.InspectorTextWidthRich("参数4:"); taskInfo.Param4 = (UnitType)EditorGUILayout.EnumPopup(taskInfo.Param4, GUILayout.Width(200)); EditorGUILayout.EndHorizontal(); EditorGUILayout.EndVertical(); EditorGUILayout.Space(); return isDelete; } private int GetIndexInLevelList(uint id) { if (_levelStrList == null) return 0; if (_levelStrList.Count != MatchConfigManager.Instance.LevelData.LevelConfigs.Count) { _levelStrList.Clear(); foreach (var kv in MatchConfigManager.Instance.LevelData.LevelConfigs) { _levelStrList.Add(kv.Value.Id.ToString()); } } for (int i = 0; i < _levelStrList.Count; i++) { if (_levelStrList[i] == id.ToString()) return i; } return 0; } private void RefreshMapNameList() { _mapNameList ??= new List(); _mapNameList.Clear(); string folderPath = "Assets/Resources/MapRecord"; if (!Directory.Exists(folderPath)) Directory.CreateDirectory(folderPath); string[] files = Directory.GetFiles(folderPath, "*.bytes"); foreach (string file in files) { string fileName = Path.GetFileNameWithoutExtension(file); if (!string.IsNullOrEmpty(fileName)) { _mapNameList.Add(fileName); } } LogSystem.LogInfo($"Init: 扫描完成,找到 {_mapNameList.Count} 个地图记录"); } private int GetIndexInMapNameList(string mapName) { if (_mapNameList == null) return 0; for (int i = 0; i < _mapNameList.Count; i++) { if (_mapNameList[i] == mapName) return i; } return 0; } } }