using UnityEngine;  
 | 
using System.Collections.Generic;  
 | 
using UnityEditor;  
 | 
using System.IO;  
 | 
using UnityEngine.AI;  
 | 
using System;  
 | 
  
 | 
public class NavMeshExport : EditorWindow  
 | 
{  
 | 
    static byte[] _writedBytes = null;  
 | 
    /** 字节写入位置索引 */  
 | 
    static int _writeIndex = 128;  
 | 
  
 | 
    private static int[][] m_Datas;  
 | 
    // 主文件  
 | 
    private static List<List<int>> m_MainData = null;  
 | 
  
 | 
    [MenuItem("美术工具/场景/合并布怪区")]  
 | 
    static void Init()  
 | 
    {  
 | 
        var _window = CreateInstance<NavMeshExport>();  
 | 
        _window.Show();  
 | 
    }  
 | 
  
 | 
    private void BuildCurData()  
 | 
    {  
 | 
        float _navWidth;  
 | 
        float _navHeight;  
 | 
        float _maxWidth;  
 | 
        float _maxHeight;  
 | 
  
 | 
        Vector3[] _navVertices = NavMesh.CalculateTriangulation().vertices;  
 | 
        if (_navVertices == null || _navVertices.Length <= 0)  
 | 
        {  
 | 
            return;  
 | 
        }  
 | 
  
 | 
        List<Vector3> _chkList = new List<Vector3>(_navVertices);  
 | 
        _chkList.Sort((Vector3 v1, Vector3 v2) =>  
 | 
        {  
 | 
            return v1.x > v2.x ? -1 : 1;  
 | 
        });  
 | 
  
 | 
        _navWidth = _chkList[0].x - _chkList[_chkList.Count - 1].x;  
 | 
        _maxWidth = _navWidth + _chkList[_chkList.Count - 1].x;  
 | 
  
 | 
        _chkList.Sort((Vector3 v1, Vector3 v2) =>  
 | 
        {  
 | 
            return v1.z > v2.z ? -1 : 1;  
 | 
        });  
 | 
  
 | 
        _navHeight = _chkList[0].z - _chkList[_chkList.Count - 1].z;  
 | 
        _maxHeight = _navHeight + _chkList[_chkList.Count - 1].z;  
 | 
  
 | 
        float _outWidth = (int)(_maxWidth * 2) + 1;  
 | 
        float _outHeight = (int)(_maxHeight * 2) + 1;  
 | 
  
 | 
        float _column;  
 | 
        float _row;  
 | 
  
 | 
        var _curData = new List<List<int>>();  
 | 
  
 | 
        for (int r = 0; r < _outHeight; ++r)  
 | 
        {  
 | 
            List<int> _rowData = new List<int>();  
 | 
            for (int c = 0; c < _outWidth; ++c)  
 | 
            {  
 | 
                _column = c * .5f;  
 | 
                _row = r * .5f;  
 | 
  
 | 
                if (IsInNavmeshArea(_column, _row))  
 | 
                {  
 | 
                    _rowData.Add(00);  
 | 
                }  
 | 
                else  
 | 
                {  
 | 
                    _rowData.Add(03);  
 | 
                }  
 | 
            }  
 | 
            _curData.Add(_rowData);  
 | 
        }  
 | 
  
 | 
        MapCollide _file = new MapCollide();  
 | 
        _file.width = _curData[0].Count;  
 | 
        _file.height = _curData.Count;  
 | 
  
 | 
        _file.data = new int[_curData.Count][];  
 | 
        for (int r = 0; r < _curData.Count; ++r)  
 | 
        {  
 | 
            _file.data[r] = new int[_curData[r].Count];  
 | 
            for (int c = 0; c < _curData[r].Count; ++c)  
 | 
            {  
 | 
                _file.data[r][c] = _curData[r][c];  
 | 
            }  
 | 
        }  
 | 
  
 | 
        LitJson.JsonData _jsonData = LitJson.JsonMapper.ToJson(_file);  
 | 
  
 | 
        string _dirPath = Application.dataPath + "/Editor/MapCollideFiles/";  
 | 
  
 | 
        if (!Directory.Exists(_dirPath))  
 | 
        {  
 | 
            Directory.CreateDirectory(_dirPath);  
 | 
        }  
 | 
  
 | 
        string _filePath = _dirPath + UnityEngine.SceneManagement.SceneManager.GetActiveScene().name + ".json";  
 | 
  
 | 
        using (StreamWriter _sw = new StreamWriter(_filePath))  
 | 
        {  
 | 
            _sw.Write(_jsonData.ToString());  
 | 
        }  
 | 
  
 | 
        AssetDatabase.Refresh();  
 | 
    }  
 | 
  
 | 
    private void CombineFromFile()  
 | 
    {  
 | 
        string _inputPath = EditorUtility.OpenFilePanel("打开合并文件",  
 | 
            Application.dataPath + "/Editor/MapCollideFiles/", "asset");  
 | 
  
 | 
        if (string.IsNullOrEmpty(_inputPath))  
 | 
        {  
 | 
            return;  
 | 
        }  
 | 
  
 | 
        string _fileName = Path.GetFileNameWithoutExtension(_inputPath);  
 | 
  
 | 
        string _configPath = "Assets/Editor/MapCollideFiles/" + _fileName + ".asset";  
 | 
        MapCombine _config = AssetDatabase.LoadAssetAtPath<MapCombine>(_configPath);  
 | 
  
 | 
        if (_config == null)  
 | 
        {  
 | 
            Debug.LogErrorFormat("{0} 文件无法读取.", _configPath);  
 | 
            return;  
 | 
        }  
 | 
  
 | 
        string _mainFilePath = Application.dataPath + "/Editor/MapCollideFiles/" + _config.mainFileName + ".json";  
 | 
        string _jsonData = string.Empty;  
 | 
  
 | 
        using (StreamReader _sr = new StreamReader(_mainFilePath))  
 | 
        {  
 | 
            _jsonData = _sr.ReadToEnd();  
 | 
        }  
 | 
  
 | 
        if (string.IsNullOrEmpty(_jsonData))  
 | 
        {  
 | 
            Debug.LogErrorFormat("{0} 文件无法读取.", _config.mainFileName);  
 | 
            return;  
 | 
        }  
 | 
  
 | 
        MapCollide _file = LitJson.JsonMapper.ToObject<MapCollide>(_jsonData);  
 | 
  
 | 
        if (m_MainData == null)  
 | 
        {  
 | 
            m_MainData = new List<List<int>>();  
 | 
        }  
 | 
        else  
 | 
        {  
 | 
            m_MainData.Clear();  
 | 
        }  
 | 
  
 | 
        for (int i = 0; i < _file.height; ++i)  
 | 
        {  
 | 
            List<int> _row = new List<int>();  
 | 
            for (int j = 0; j < _file.width; ++j)  
 | 
            {  
 | 
                _row.Add(_file.data[i][j]);  
 | 
            }  
 | 
            m_MainData.Add(_row);  
 | 
        }  
 | 
  
 | 
        for (int i = 0; i < _config.dataList.Count; ++i)  
 | 
        {  
 | 
            Combine(_config.dataList[i]);  
 | 
        }  
 | 
  
 | 
        _writedBytes = null;  
 | 
  
 | 
        string _exportPath = EditorUtility.SaveFilePanel("",  
 | 
                                                  "",  
 | 
                                                  _config.mainFileName,  
 | 
                                                  "col");  
 | 
  
 | 
        if (string.IsNullOrEmpty(_exportPath))  
 | 
        {  
 | 
            return;  
 | 
        }  
 | 
  
 | 
        if (File.Exists(_exportPath))  
 | 
        {  
 | 
            File.Delete(_exportPath);  
 | 
        }  
 | 
  
 | 
        WriteBytes(BitConverter.GetBytes((uint)(m_MainData[0].Count)));  
 | 
        WriteBytes(BitConverter.GetBytes((uint)(m_MainData.Count)));  
 | 
  
 | 
        m_Datas = new int[m_MainData.Count][];  
 | 
        for (int i = 0; i < m_Datas.Length; ++i)  
 | 
        {  
 | 
            m_Datas[i] = new int[m_MainData[i].Count];  
 | 
        }  
 | 
  
 | 
        for (int r = 0; r < m_MainData.Count; ++r)  
 | 
        {  
 | 
            for (int c = 0; c < m_MainData[r].Count; ++c)  
 | 
            {  
 | 
                m_Datas[r][c] = m_MainData[r][c];  
 | 
            }  
 | 
        }  
 | 
  
 | 
        for (int i = 0; i < m_Datas.Length; i++)  
 | 
        {  
 | 
            WriteBytes(m_Datas[i]);  
 | 
        }  
 | 
  
 | 
        WriteToFile(_exportPath);  
 | 
    }  
 | 
  
 | 
    private Vector3 m_ChkPos;  
 | 
  
 | 
    private void OnGUI()  
 | 
    {  
 | 
        if (GUILayout.Button("合并配置文件地图"))  
 | 
        {  
 | 
            CombineFromFile();  
 | 
        }  
 | 
  
 | 
        if (GUILayout.Button("生成当前地图的合并文件"))  
 | 
        {  
 | 
            BuildCurData();  
 | 
        }  
 | 
  
 | 
        GUILayout.Space(10);  
 | 
        EditorGUILayout.BeginHorizontal();  
 | 
        m_ChkPos = EditorGUILayout.Vector3Field("测试点", m_ChkPos);  
 | 
        if (GUILayout.Button("测试"))  
 | 
        {  
 | 
            if (IsInNavmeshArea(m_ChkPos.x, m_ChkPos.z))  
 | 
            {  
 | 
                Debug.Log("正常点...........");  
 | 
            }  
 | 
            else  
 | 
            {  
 | 
                Debug.Log("障碍点...........");  
 | 
            }  
 | 
        }  
 | 
        EditorGUILayout.EndHorizontal();  
 | 
  
 | 
        if (GUILayout.Button("直接导出当前地图.col文件"))  
 | 
        {  
 | 
            Export();  
 | 
        }  
 | 
  
 | 
        if (m_Datas == null)  
 | 
        {  
 | 
            return;  
 | 
        }  
 | 
  
 | 
        Rect _rect = new Rect(0, 0, 2, 2);  
 | 
  
 | 
        for (int i = 0; i < m_Datas.Length; ++i)  
 | 
        {  
 | 
            if (m_Datas[i] == null)  
 | 
            {  
 | 
                continue;  
 | 
            }  
 | 
  
 | 
            for (int j = 0; j < m_Datas[i].Length; ++j)  
 | 
            {  
 | 
                if (m_Datas[i][j] == 00)  
 | 
                {  
 | 
                    GUI.color = Color.green;  
 | 
                }  
 | 
                else if (m_Datas[i][j] == 03)  
 | 
                {  
 | 
                    GUI.color = Color.red;  
 | 
                }  
 | 
  
 | 
                _rect.position = new Vector2(j * 2 + 4, i * 2 + 72);  
 | 
  
 | 
                GUI.Box(_rect, "");  
 | 
            }  
 | 
        }  
 | 
    }  
 | 
  
 | 
    private void OnDisable()  
 | 
    {  
 | 
        m_Datas = null;  
 | 
        m_MainData = null;  
 | 
    }  
 | 
  
 | 
    private void Combine(MapCombine.MapCombineInfo info)  
 | 
    {  
 | 
        if (m_MainData == null)  
 | 
        {  
 | 
            return;  
 | 
        }  
 | 
  
 | 
        // 读取文件  
 | 
        string _filePath = Application.dataPath + "/Editor/MapCollideFiles/" + info.fileName + ".json";  
 | 
        string _jsonData = string.Empty;  
 | 
  
 | 
        using (StreamReader _sr = new StreamReader(_filePath))  
 | 
        {  
 | 
            _jsonData = _sr.ReadToEnd();  
 | 
        }  
 | 
  
 | 
        if (string.IsNullOrEmpty(_jsonData))  
 | 
        {  
 | 
            Debug.LogErrorFormat("{0} 文件无法读取.", info.fileName);  
 | 
            return;  
 | 
        }  
 | 
  
 | 
        MapCollide _file = LitJson.JsonMapper.ToObject<MapCollide>(_jsonData);  
 | 
  
 | 
        int _prevRowCount = m_MainData.Count;  
 | 
        int _prevColumnCount = m_MainData[0].Count;  
 | 
  
 | 
        int _curRowCount = _file.height;  
 | 
        int _curColumnCount = _file.width;  
 | 
  
 | 
        int _newRowCount = 0;  
 | 
        int _newColumnCount = 0;  
 | 
  
 | 
        // 填入的偏移R + 新地图的高度 与 之前地图的高度进行对比, 得到差值  
 | 
        int _deltaRowCount = info.offsetY + _curRowCount - _prevRowCount;  
 | 
  
 | 
        // 差值大于0, 则新建一个数组, 此数组为旧的R + 差值  
 | 
        if (_deltaRowCount > 0)  
 | 
        {  
 | 
            _newRowCount = _prevRowCount + _deltaRowCount;  
 | 
        }  
 | 
        else  
 | 
        {  
 | 
            _newRowCount = _prevRowCount;  
 | 
        }  
 | 
  
 | 
        // 列同理  
 | 
        int _deltaColumnCount = info.offsetX + _curColumnCount - _prevColumnCount;  
 | 
  
 | 
        if (_deltaColumnCount > 0)  
 | 
        {  
 | 
            _newColumnCount = _prevColumnCount + _deltaColumnCount;  
 | 
        }  
 | 
        else  
 | 
        {  
 | 
            _newColumnCount = _prevColumnCount;  
 | 
        }  
 | 
  
 | 
        // 扩容  
 | 
        for (int i = m_MainData.Count; i < _newRowCount; ++i)  
 | 
        {  
 | 
            List<int> _tmp = new List<int>();  
 | 
            for (int j = 0; j < _prevColumnCount; ++j)  
 | 
            {  
 | 
                _tmp.Add(03);  
 | 
            }  
 | 
            m_MainData.Add(_tmp);  
 | 
        }  
 | 
  
 | 
        for (int i = 0; i < m_MainData.Count; ++i)  
 | 
        {  
 | 
            for (int j = _prevColumnCount; j < _newColumnCount; ++j)  
 | 
            {  
 | 
                m_MainData[i].Add(03);  
 | 
            }  
 | 
        }  
 | 
  
 | 
        // 赋值  
 | 
        for (int i = 0; i < _file.data.Length; ++i)  
 | 
        {  
 | 
            for (int j = 0; j < _file.data[i].Length; ++j)  
 | 
            {  
 | 
                m_MainData[i + info.offsetY][j + info.offsetX] = _file.data[i][j];  
 | 
            }  
 | 
        }  
 | 
    }  
 | 
  
 | 
    static void Export()  
 | 
    {  
 | 
        string path = EditorUtility.SaveFilePanel("",  
 | 
                                                  "",  
 | 
                                                  UnityEngine.SceneManagement.SceneManager.GetActiveScene().name,  
 | 
                                                  "col");  
 | 
  
 | 
        if (string.IsNullOrEmpty(path))  
 | 
        {  
 | 
            return;  
 | 
        }  
 | 
  
 | 
        if (File.Exists(path))  
 | 
        {  
 | 
            File.Delete(path);  
 | 
        }  
 | 
  
 | 
        float _navWidth;  
 | 
        float _navHeight;  
 | 
        float _maxWidth;  
 | 
        float _maxHeight;  
 | 
  
 | 
        Vector3[] _navVertices = NavMesh.CalculateTriangulation().vertices;  
 | 
        if (_navVertices == null || _navVertices.Length <= 0)  
 | 
        {  
 | 
            return;  
 | 
        }  
 | 
  
 | 
        List<Vector3> _chkList = new List<Vector3>(_navVertices);  
 | 
        _chkList.Sort((Vector3 v1, Vector3 v2) =>  
 | 
        {  
 | 
            return v1.x > v2.x ? -1 : 1;  
 | 
        });  
 | 
  
 | 
        _navWidth = _chkList[0].x - _chkList[_chkList.Count - 1].x;  
 | 
        _maxWidth = _navWidth + _chkList[_chkList.Count - 1].x;  
 | 
  
 | 
        _chkList.Sort((Vector3 v1, Vector3 v2) =>  
 | 
        {  
 | 
            return v1.z > v2.z ? -1 : 1;  
 | 
        });  
 | 
  
 | 
        _navHeight = _chkList[0].z - _chkList[_chkList.Count - 1].z;  
 | 
        _maxHeight = _navHeight + _chkList[_chkList.Count - 1].z;  
 | 
  
 | 
        int _outWidth = (int)(_maxWidth * 2) + 1;  
 | 
        int _outHeight = (int)(_maxHeight * 2) + 1;  
 | 
  
 | 
        WriteBytes(BitConverter.GetBytes((uint)(_outWidth)));  
 | 
        WriteBytes(BitConverter.GetBytes((uint)(_outHeight)));  
 | 
  
 | 
        Debug.LogFormat("地图宽度: {0}, 地图高度: {1}", _outWidth, _outHeight);  
 | 
  
 | 
        float _column;  
 | 
        float _row;  
 | 
  
 | 
        int[][] _datas = new int[_outHeight][];  
 | 
        for (int i = 0; i < _datas.Length; i++)  
 | 
        {  
 | 
            _datas[i] = new int[_outWidth];  
 | 
        }  
 | 
  
 | 
        //System.Text.StringBuilder _sb1 = new System.Text.StringBuilder();  
 | 
  
 | 
        for (int r = 0; r < _outHeight; ++r)  
 | 
        {  
 | 
            for (int c = 0; c < _outWidth; ++c)  
 | 
            {  
 | 
                _column = c * .5f;  
 | 
                _row = r * .5f;  
 | 
  
 | 
                if (IsInNavmeshArea(_column, _row))  
 | 
                {  
 | 
                    _datas[r][c] = 00;  
 | 
                    //_sb1.Append("0");  
 | 
                }  
 | 
                else  
 | 
                {  
 | 
                    _datas[r][c] = 03;  
 | 
                    //_sb1.Append("#");  
 | 
                }  
 | 
  
 | 
            }  
 | 
            //_sb1.Append("\r\n");  
 | 
        }  
 | 
  
 | 
        //using (StreamWriter _writer = new StreamWriter(Application.dataPath + "/aaa.txt"))  
 | 
        //{  
 | 
        //    _writer.Write(_sb1.ToString());  
 | 
        //}  
 | 
  
 | 
        for (int i = 0; i < _datas.Length; i++)  
 | 
        {  
 | 
            WriteBytes(_datas[i]);  
 | 
        }  
 | 
  
 | 
        WriteToFile(path);  
 | 
    }  
 | 
  
 | 
    private static bool IsInNavmeshArea(float column, float row)  
 | 
    {  
 | 
        int _mask = 1 << LayerMask.NameToLayer("Navmesh");  
 | 
        return Physics.Raycast(new Vector3(column, 100, row), Vector3.down, 200, _mask)  
 | 
            || Physics.Raycast(new Vector3(column + .5f, 100, row), Vector3.down, 200, _mask)  
 | 
            || Physics.Raycast(new Vector3(column, 100, row + .5f), Vector3.down, 200, _mask)  
 | 
            || Physics.Raycast(new Vector3(column + .5f, 100, row + .5f), Vector3.down, 200, _mask);  
 | 
    }  
 | 
  
 | 
  
 | 
    private static void WriteToFile(string path)  
 | 
    {  
 | 
        FileStream fs = File.Open(path, FileMode.CreateNew, FileAccess.ReadWrite);  
 | 
        BinaryWriter bw = new BinaryWriter(fs);  
 | 
        //将byte数组写入文件中  
 | 
        bw.Write(_writedBytes, 0, _writedBytes.Length);  
 | 
        bw.Flush();  
 | 
        bw.Close();  
 | 
        fs.Dispose();  
 | 
        fs.Close();  
 | 
        _writeIndex = 128;  
 | 
        _writedBytes = null;  
 | 
    }  
 | 
  
 | 
    /// <summary>  
 | 
    /// 写入一段字节数据  
 | 
    /// </summary>  
 | 
    /// <param name="vBytes"></param>  
 | 
    private static void WriteBytes(byte[] vBytes)  
 | 
    {  
 | 
        Array.Resize(ref _writedBytes, _writeIndex + vBytes.Length);  
 | 
        vBytes.CopyTo(_writedBytes, _writeIndex);  
 | 
        _writeIndex = _writedBytes.Length;  
 | 
    }  
 | 
  
 | 
    /// <summary>  
 | 
    /// 转整型数值数组为字节  
 | 
    /// </summary>  
 | 
    /// <param name="vInts"></param>  
 | 
    /// <param name="vType"></param>  
 | 
    private static void WriteBytes(int[] vInts)  
 | 
    {  
 | 
        int l = vInts.Length;  
 | 
        byte[] vRst;  
 | 
        int i;  
 | 
        vRst = new byte[l];  
 | 
        for (i = 0; i < l; i++)  
 | 
        {  
 | 
            Array.Copy(BitConverter.GetBytes((byte)vInts[i]), 0, vRst, i, 1);  
 | 
        }  
 | 
        WriteBytes(vRst);  
 | 
    }  
 | 
} 
 |