Files
HX_MapEditor/Assets/Scripts/UI/UIMapPanel.cs
2025-09-10 20:01:05 +08:00

354 lines
12 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.Collections;
using System.Collections.Generic;
using System.Data.Common;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using UnityEditor;
using UnityEngine;
using UnityEngine.UI;
///最上面
///功能:扫描地图、打开地图、关闭地图、放弃设置
public class UIMapPanel : MonoBehaviour
{
public ToggleGroup mapEditorGroup;
public Dropdown dropMap;
private bool _saving;
// Start is called before the first frame update
void Start()
{
_saving = false;
dropMap.onValueChanged.AddListener(delegate {
if (dropMap.options.Count > 0)
{
int mapId = Convert.ToInt32(dropMap.options[dropMap.value].text);
UICellInfo.Instance.ShowMapWidthAndHeight(mapId);
}
});
}
void OnDataLoaded()
{
// 获取所有地图文件夹
string mapsDirectory = Path.Combine(Application.dataPath, "GameAssets", "Maps");
if (!Directory.Exists(mapsDirectory))
{
Debug.LogError($"Maps directory not found: {mapsDirectory}");
return;
}
MapManager.Instance.allMaps.Clear();
string[] mapFolders = Directory.GetDirectories(mapsDirectory);
// 按 mapId 数字部分升序排序
var sortedMapFolders = mapFolders
.OrderBy(folderPath =>
{
string folderName = Path.GetFileName(folderPath); // 例如 "v1000"
// 提取数字部分
var match = Regex.Match(folderName, @"\d+");
return match.Success ? int.Parse(match.Value) : int.MaxValue;
})
.ToArray();
foreach (string folderPath in sortedMapFolders)
{
string[] pathSplit = folderPath.Split(Path.DirectorySeparatorChar);
string mapId = pathSplit[pathSplit.Length - 1]; // 例如 "v1000"
string textureDirectory = Path.Combine(folderPath, "Texture");
if (Directory.Exists(textureDirectory))
{
string[] imageFiles = Directory.GetFiles(textureDirectory, "*.jpg");
int maxRow = 0;
int maxCol = 0;
string pattern = $@"r(\d+)_c(\d+)"; // 正则表达式:匹配 v1000_rXX_cYY
Regex regex = new Regex(pattern);
foreach (string filePath in imageFiles)
{
string fileName = Path.GetFileNameWithoutExtension(filePath); // 例如 "v1000_r11_c14"
Match match = regex.Match(fileName);
if (match.Success)
{
if (int.TryParse(match.Groups[1].Value, out int row) && int.TryParse(match.Groups[2].Value, out int col))
{
maxRow = Mathf.Max(maxRow, row);
maxCol = Mathf.Max(maxCol, col);
}
}
else
{
Debug.LogWarning($"Filename {fileName} does not match expected pattern: {pattern}");
}
}
MapManager.Instance.allMaps[mapId] = (maxCol, maxRow, imageFiles.Length);
}
else
{
Debug.LogWarning($"Texture directory not found for map {mapId}: {textureDirectory}");
}
}
}
/// <summary>
/// 重命名图片格式从 map_x 到 v{mapId}_rx_cx 格式(包含重复检查)
/// </summary>
public void ReNamePicFormat()
{
int mapId = Convert.ToInt32(dropMap.options[dropMap.value].text);
int width = UICellInfo.Instance.CustomMapWidth; // 地图宽度(列数)
string mapsDirectory = Path.Combine(Application.dataPath, "GameAssets", "Maps", $"{mapId}", "Texture");
if (!Directory.Exists(mapsDirectory))
{
Debug.LogError($"Maps directory not found: {mapsDirectory}");
return;
}
// 获取所有jpg文件
string[] imageFiles = Directory.GetFiles(mapsDirectory, "*.jpg");
int totalFiles = imageFiles.Length;
if (totalFiles == 0)
{
UIWindow.Instance.ShowMessage($"No jpg files found in directory: {mapsDirectory}");
return;
}
// 检查是否已经是目标命名格式
if (IsAlreadyRenamed(imageFiles, mapId))
{
UIWindow.Instance.ShowMessage($"文件夹 {mapId} 已经是目标命名格式,跳过重命名");
return;
}
// 检查是否混合格式(部分已重命名,部分未重命名)
if (IsMixedFormat(imageFiles, mapId))
{
UIWindow.Instance.ShowMessage($"文件夹 {mapId} 包含混合格式的文件,请先清理文件夹");
return;
}
// 按数字排序map_格式的文件
var mapFiles = imageFiles
.Where(file => Path.GetFileNameWithoutExtension(file).StartsWith("map_"))
.OrderBy(file =>
{
string fileName = Path.GetFileNameWithoutExtension(file);
if (int.TryParse(fileName.Substring(4), out int number))
{
return number;
}
return int.MaxValue;
})
.ToArray();
if (mapFiles.Length == 0)
{
UIWindow.Instance.ShowMessage($"没有找到map_格式的文件但也不是目标格式");
return;
}
// 计算行数
int height = Mathf.CeilToInt((float)mapFiles.Length / width);
UIWindow.Instance.ShowMessage($"Renaming {mapFiles.Length} files with grid size: {width}x{height}");
int renamedCount = 0;
int errorCount = 0;
// 执行重命名操作
for (int index = 0; index < mapFiles.Length; index++)
{
string oldFilePath = mapFiles[index];
string fileName = Path.GetFileNameWithoutExtension(oldFilePath);
string fileExtension = Path.GetExtension(oldFilePath);
try
{
// 计算行列位置从1开始
int row = (index / width) + 1;
int col = (index % width) + 1;
// 生成新文件名使用地图ID
string newFileName = $"r{row}_c{col}";
string newFilePath = Path.Combine(mapsDirectory, newFileName + fileExtension);
// 重命名文件
File.Move(oldFilePath, newFilePath);
renamedCount++;
Debug.Log($"Renamed: {fileName} -> {newFileName}");
}
catch (Exception ex)
{
errorCount++;
Debug.LogError($"Error renaming file {fileName}: {ex.Message}");
}
}
Debug.Log($"Rename completed. Success: {renamedCount}, Errors: {errorCount}");
// 刷新AssetDatabase
#if UNITY_EDITOR
UnityEditor.AssetDatabase.Refresh();
#endif
OnDataLoaded();
}
/// <summary>
/// 检查是否已经是目标命名格式
/// </summary>
private bool IsAlreadyRenamed(string[] imageFiles, int mapId)
{
// 目标格式的正则表达式v{mapId}_r数字_c数字
string pattern = $"^r\\d+_c\\d+$";
var regex = new System.Text.RegularExpressions.Regex(pattern);
foreach (string filePath in imageFiles)
{
string fileName = Path.GetFileNameWithoutExtension(filePath);
// 如果发现任何非目标格式的文件,就不是已重命名状态
if (!regex.IsMatch(fileName) && !fileName.StartsWith("map_"))
{
return false;
}
}
// 检查是否至少有一个目标格式的文件
bool hasTargetFormat = imageFiles.Any(file =>
regex.IsMatch(Path.GetFileNameWithoutExtension(file)));
return hasTargetFormat;
}
/// <summary>
/// 检查是否混合格式既有目标格式又有map_格式
/// </summary>
private bool IsMixedFormat(string[] imageFiles, int mapId)
{
bool hasMapFormat = false;
bool hasTargetFormat = false;
string pattern = $"^r\\d+_c\\d+$";
var regex = new System.Text.RegularExpressions.Regex(pattern);
foreach (string filePath in imageFiles)
{
string fileName = Path.GetFileNameWithoutExtension(filePath);
if (fileName.StartsWith("map_"))
{
hasMapFormat = true;
}
else if (regex.IsMatch(fileName))
{
hasTargetFormat = true;
}
// 如果同时存在两种格式,就是混合状态
if (hasMapFormat && hasTargetFormat)
{
return true;
}
}
return false;
}
public void ExportMap()
{
MapManager.Instance.SaveAtlasToFile();
}
public void ScanMap()
{
MapManager.Instance.allMaps.Clear();
OnDataLoaded();
dropMap.options.Clear();
foreach (var map in MapManager.Instance.allMaps)
{
Dropdown.OptionData od = new Dropdown.OptionData();
od.text = map.Key;
dropMap.options.Add(od);
}
dropMap.value = 1;
dropMap.value = 0; //为了默认选中第一项
}
public void OpenMap()
{
if(dropMap.options.Count == 0)
{
UIWindow.Instance.ShowMessage("请先扫描地图");
return;
}
if(MapManager.Instance._curOpenMapId > 0)
{
UIWindow.Instance.ShowMessage("请先关闭已有地图");
return;
}
int mapId = Convert.ToInt32(dropMap.options[dropMap.value].text);
MapManager.Instance._curOpenMapId = mapId;
MapManager.Instance.LoadMapRegionSprites(mapId);
MapManager.Instance.LoadMapObs(mapId);
UIWindow.Instance.uiEditMapConfig.LoadMapConfig(mapId);
UIWindow.Instance.uiMonstersPanel.LoadMonsterConfig(mapId);
UIWindow.Instance.uiNpcsPanel.LoadNpcsConfig(mapId);
UIWindow.Instance.uiTriggersPanel.LoadTriggersConfig(mapId);
UIWindow.Instance.uiFuBensPanel.LoadFuBenConfig(mapId);
UIWindow.Instance.uiJuBaosPanel.LoadJuBaoConfig(mapId);
//如果没有配置,需要创建阻隔点
if (MapManager.Instance.map == null)
{
MapManager.Instance.CreateObs(mapId);
}
UICellInfo.Instance.ShowMapCellInfo();
}
public void CloseMap()
{
MapManager.Instance.CloseMap();
MapManager.Instance._curOpenMapId = -1;
foreach (var toggle in mapEditorGroup.ActiveToggles())
{
toggle.isOn = false;
}
}
public bool HasMap(string mapId)
{
return MapManager.Instance.allMaps.ContainsKey(mapId);
}
private void Update()
{
if (Input.GetKey(KeyCode.LeftControl) && Input.GetKey(KeyCode.S))
{
if (_saving)
return;
SaveAll();
}
}
public void SaveAll()
{
_saving = true;
Debug.Log("正在保存所有数据...");
MapManager.Instance.SaveRegionXML();
MapManager.Instance.SaveMapObs();
UIWindow.Instance.uiEditMapConfig.SaveMapConfig();
UIWindow.Instance.uiMonstersPanel.SaveMonsterConfig();
UIWindow.Instance.uiNpcsPanel.SaveNpcsConfig();
UIWindow.Instance.uiTriggersPanel.SaveTriggersConfig();
UIWindow.Instance.uiJuBaosPanel.SaveJuBaoConfig();
UIWindow.Instance.uiFuBensPanel.SaveFuBenConfig();
UIWindow.Instance.ShowMessage("保存成功");
_saving = false;
#if UNITY_EDITOR
AssetDatabase.Refresh();
#endif
}
}