Example #1
0
 public void Load(ISaveable saveable)
 {
     if (IsRegistered(saveable))
     {
         string saveString = storage?.GetString(saveable.SaveKey, string.Empty);
         if (string.IsNullOrEmpty(saveString))
         {
             saveable.LoadDefaults();
         }
         else
         {
             try {
                 object save = JsonConvert.DeserializeObject(saveString, saveable.SaveType);
                 saveable.LoadSave(save);
             } catch (System.Exception exception) {
                 UDebug.LogError(exception.Message);
                 saveable.LoadDefaults();
             }
         }
     }
     else
     {
         throw new UnityException($"Load: saveable of type => {saveable.GetType().Name} is not registered on ISaveService");
     }
 }
Example #2
0
        public AssetBundle SyncLoadAssetBundle(string path)
        {
            try
            {
#if UNITY_EDITOR || UNITY_STANDALONE_WIN || UNITY_IOS
                if (DevelopSetting.IsUsePersistent)
                {
                    path = path.Replace("file:///", "");
                }
                else
                {
                    path = path.Replace("file://", "");
                }
#elif UNITY_ANDROID
                if (DevelopSetting.IsUsePersistent)
                {
                    path = path.Replace("file:///", "");
                }
#endif
                AssetBundle ab = AssetBundle.LoadFromFile(path);
                return(ab);
            }
            catch (System.Exception e)
            {
                UDebug.LogError(e.Message);
                return(null);
            }
        }
Example #3
0
    IEnumerator MyTest(string FileUrl)
    {
        float maxNum = 100;

        for (int i = 0; i < maxNum; i++)
        {
            int randomNum = Random.Range(1, 100000);
            FileUrl = FileUrl + "?v=" + randomNum;
            WWW www = new WWW(FileUrl);
            yield return(www);

            if (string.IsNullOrEmpty(www.error))
            {
                UDebug.Log("WriteFile:  loginwindow.ab ");
                string tempFilePath = PathHelper.PersistentPath + "loginwindow" + i + ".ab";
                Util.WriteFile(tempFilePath, www.bytes);
            }
            else
            {
                UDebug.LogError(string.Format("{0}down failed:{1}", FileUrl, www.error));
                yield break;
            }
            GameStateManager.Instance.DownProgressChangeEvent(i + 1, maxNum, (float)i / maxNum);
            yield return(new WaitForSeconds(0.2f));
        }
    }
Example #4
0
 public Object[] loadAllResource(string path)
 {
     Object[] objs = Resources.LoadAll(path);
     if (objs == null)
     {
         UDebug.LogError("resName:" + path + " not found in Resources");
     }
     return(objs);
 }
Example #5
0
    public int PackRects(NativeAPI.stbrp_rect[] rects)
    {
        var addedCount = 0;
        var input      = new List <NativeAPI.stbrp_rect>(rects);
        var next       = new List <NativeAPI.stbrp_rect>();

        while (input.Count > 0)
        {
            input.Sort(
                (l, r) => {
                if (r.h > l.h)
                {
                    return(-1);
                }
                if (r.h < l.h)
                {
                    return(1);
                }
                return((r.w > l.w) ? -1 : ((r.w < l.w) ? 1 : 0));
            }
                );
            while (input.Count > 0)
            {
                var last = input.Count - 1;
                var cur  = input[last];
                input.RemoveAt(last);
                var added = false;
                for (int i = 0; i < m_pagePacker.Count; ++i)
                {
                    var tp = m_pagePacker[i];
                    if (tp.Add(cur))
                    {
                        ++addedCount;
                        added = true;
                        break;
                    }
                }
                if (!added)
                {
                    next.Add(cur);
                }
            }
            if (next.Count > 0)
            {
                if (m_pagePacker.Count > MaxPage)
                {
                    UDebug.LogError("There is too many rects to pack: MaxPage = {0}", MaxPage);
                    break;
                }
                var temp = next;
                next  = input;
                input = temp;
                m_pagePacker.Add(new _PagePacker());
            }
        }
        return(addedCount);
    }
Example #6
0
        public Object loadResources(string path)
        {
            Object obj = Resources.Load(path);

            if (obj == null)
            {
                UDebug.LogError("resName:" + path + " not found in Resources");
            }
            return(obj);
        }
Example #7
0
    IEnumerator CheckFileListMd5(VersionConfig serverVersionConfig, FileUpdateVo versionVo)
    {
        string        content = File.ReadAllText(versionVo.PersistentPath);
        VersionConfig persistentVersionConfig = JsonUtility.FromJson <VersionConfig>(content);
        int           persistentVersion       = persistentVersionConfig.resVersion;
        int           serverVersion           = serverVersionConfig.resVersion;

        if (serverVersion >= persistentVersion)
        {
            bool            versionConfigChange = false;
            FileUpdateVo    fileListVo          = new FileUpdateVo(AppConst.FileListName, versionVo.Url, versionVo.Random, string.Empty, 100);
            string          fileListMd5         = Util.Md5file(fileListVo.PersistentPath);
            FileCheckResult checkResult         = null;
            byte[]          fileListBytes       = null;
            if (!serverVersionConfig.fileListMd5.Equals(fileListMd5))
            {
                versionConfigChange = true;
                WWW www = new WWW(fileListVo.FileUrl);
                yield return(www);

                if (string.IsNullOrEmpty(www.error))
                {
                    string[]      fileList       = www.text.Split(new[] { Environment.NewLine }, StringSplitOptions.None);
                    List <string> serverFileList = new List <string>(fileList);
                    fileList = File.ReadAllLines(fileListVo.PersistentPath);
                    List <string> persistentFileList = new List <string>(fileList);
                    checkResult   = Util.GetChangList(persistentFileList, serverFileList);
                    fileListBytes = www.bytes;
                }
                else
                {
                    UDebug.LogError(string.Format("{0}down failed:{1}", fileListVo.FileUrl, www.error));
                    yield break;
                }
                www.Dispose();
                //下载云端list
            }
            else if (serverVersion > persistentVersion)//只是version改变了,实际资源没有变,或者上次资源下载好了,但是version写入没有成功
            {
                versionConfigChange = true;
            }

            VersionConfig toWriteVersionConfig = versionConfigChange ? serverVersionConfig : null;
            CheckResourceComplete(toWriteVersionConfig, checkResult, fileListBytes, versionVo);
        }
        else
        {
            if (GameStateManager.Instance.showGameStateLog)
            {
                UDebug.Log("本资源比较超前,不做资源版本更新: " + "persistentVersion" + persistentVersion.ToString() + "    serverVersion:" + serverVersion.ToString());
            }
            CheckResourceComplete(null, null, null, versionVo);
        }
        yield return(new WaitForEndOfFrame());
    }
Example #8
0
        public static Byte[] stbi_loadfromfile(String filename, out int x, out int y, out int comp, int req_comp = 0)
        {
            Byte[] data = null;
            var    ptr  = IntPtr.Zero;

            x    = 0;
            y    = 0;
            comp = 0;
            try {
                ptr = stbi_load(filename, out x, out y, out comp, req_comp);
                if (ptr != IntPtr.Zero)
                {
                    var size = x * y * comp;
                    if (size > 0)
                    {
                        data = new byte[size];
                        Marshal.Copy(ptr, data, 0, size);
                    }
                }
            } catch (Exception e) {
                if (!(e is DllNotFoundException))
                {
                    UDebug.LogException(e);
                }
            } finally {
                if (ptr != IntPtr.Zero)
                {
                    stbi_image_free(ptr);
                }
                else
                {
                    var errorPtr = stbi_failure_reason();
                    for ( ; ;)
                    {
                        if (errorPtr != IntPtr.Zero)
                        {
                            var error = Marshal.PtrToStringAnsi(errorPtr);
                            if (!String.IsNullOrEmpty(error))
                            {
                                UDebug.LogError("stbi_loadfromfile failed: {0}", error);
                                break;
                            }
                        }
                        UDebug.LogError("stbi_loadfromfile failed: reason unknown.");
                        break;
                    }
                }
            }
            return(data);
        }
Example #9
0
    /// <summary>
    ///
    /// </summary>
    /// <param name="serverVersionConfig">如果不为空,则需要写入</param>
    /// <param name="checkResult">如果不为空,则需要删除文件或者下载文件</param>
    /// <param name="fileListBytes">下载之后的文本列表</param>
    /// <param name="url"></param>
    /// <param name="random"></param>
    /// <returns></returns>
    IEnumerator StartDownRes(VersionConfig serverVersionConfig, byte[] fileListBytes, List <FileUpdateVo> fileVoList, FileUpdateVo versionVo)
    {
        FileUpdateVo fileUpdateVo;
        string       url     = versionVo.Url;
        string       random  = versionVo.Random;
        float        allSize = Util.SumSize(fileVoList, fileVoList.Count);

        for (int i = 0; i < fileVoList.Count; i++)
        {
            GameStateManager.Instance.DownProgressHandle(GameStates.DownResource, fileVoList, i, allSize);
            fileUpdateVo = fileVoList[i];

            WWW www = new WWW(fileUpdateVo.FileUrl);
            yield return(www);

            if (string.IsNullOrEmpty(www.error))
            {
                Util.WriteFile(fileUpdateVo.PersistentPath, www.bytes);
            }
            else
            {
                UDebug.LogError(string.Format("{0}down failed:{1}", fileUpdateVo.FileUrl, www.error));
                yield break;
            }
            www.Dispose();
        }

        if (fileListBytes != null)
        {
            fileUpdateVo = new FileUpdateVo(AppConst.FileListName, url, random, string.Empty, 0);
            Util.WriteFile(fileUpdateVo.PersistentPath, fileListBytes);
        }

        if (serverVersionConfig != null)
        {
            if (File.Exists(versionVo.PersistentPath))
            {
                File.Delete(versionVo.PersistentPath);
                string json = JsonUtility.ToJson(serverVersionConfig);
                File.WriteAllText(versionVo.PersistentPath, json);
            }
        }
        GameStateManager.Instance.DownProgressHandle(GameStates.DownResource, fileVoList, fileVoList.Count, allSize);

        yield return(new WaitForEndOfFrame());

        DownResourceComplete();
    }
Example #10
0
    /// <summary>
    /// 把当前场景的lightmap像素以HDR格式读取出来保存成未压缩的浮点格式
    /// </summary>
    /// <returns></returns>
    unsafe static List <LightmapInfo> LoadAllLightmapData()
    {
        var litmapData = new List <LightmapInfo>();
        var lightmaps  = LightmapSettings.lightmaps;
        var count      = 0;

        for (int j = 0; j < lightmaps.Length; ++j)
        {
            var out_data  = IntPtr.Zero;
            var err       = IntPtr.Zero;
            var width     = 0;
            var height    = 0;
            var assetPath = AssetDatabase.GetAssetPath(lightmaps[j].lightmapColor);
            var ld        = new LightmapInfo();
            ld.assetPath = assetPath;
            try {
                if (NativeAPI.LoadEXR(ref out_data, out width, out height, ld.assetPath, ref err) >= 0)
                {
                    ld.pixels = new Vector4[width * height];
                    ld.width  = width;
                    ld.height = height;
                    var src = ( Vector4 * )out_data;
                    for (int n = 0; n < ld.pixels.Length; ++n)
                    {
                        ld.pixels[n] = *src++;
                    }
                    ++count;
                }
                else
                {
                    if (err != IntPtr.Zero)
                    {
                        var errorInfo = Marshal.PtrToStringAnsi(err);
                        UDebug.LogError(errorInfo);
                    }
                }
            } finally {
                if (out_data != IntPtr.Zero)
                {
                    NativeAPI.crt_free(out_data);
                }
            }
            litmapData.Add(ld);
        }
        return(count == lightmaps.Length ? litmapData : null);
    }
Example #11
0
        public void Realloc(int maxSize)
        {
            maxSize = MathLib.CeilPowerOfTwo(maxSize);
            if (maxSize != m_atlasSize)
            {
                if (m_pool != null)
                {
                    m_poolHandle.Free();
                }
                m_usedWidth  = 0;
                m_usedHeight = 0;
                m_usedArea   = 0;
                m_atlasSize  = maxSize;
                m_pool       = new NativeAPI.stbrp_node[m_atlasSize * 4];
                UDebug.Assert(m_pool != null && m_pool.Length > 0);
                m_poolHandle = GCHandle.Alloc(m_pool, GCHandleType.Pinned);
                var packedRects = m_packedRects;
                m_packedRects = new List <NativeAPI.stbrp_rect>();
                m_ctx         = new NativeAPI.stbrp_context();
                fixed(NativeAPI.stbrp_context *_ctx = &m_ctx)
                {
                    NativeAPI.stbrp_init_target(_ctx, m_atlasSize, m_atlasSize, (NativeAPI.stbrp_node *)m_poolHandle.AddrOfPinnedObject(), m_pool.Length);
                    NativeAPI.stbrp_setup_allow_out_of_mem(_ctx, 1);
                }

                for (int i = 0; i < packedRects.Count; ++i)
                {
                    var rect  = packedRects[i];
                    var _rect = new NativeAPI.stbrp_rect();
                    _rect.w  = rect.w;
                    _rect.h  = rect.h;
                    _rect.id = rect.id;
                    if (!Add(rect))
                    {
                        UDebug.LogError("Realloc failed!");
                        break;
                    }
                }
            }
        }
Example #12
0
        public AssetBundle SyncLoadStreamingAssetsAB(string path)
        {
            StringBuilder sb = new StringBuilder();

#if UNITY_ANDROID && !UNITY_EDITOR
            sb.Append(Application.dataPath);
            sb.Append("!assets/");
#else
            sb.Append(Application.streamingAssetsPath);
            sb.Append(System.IO.Path.DirectorySeparatorChar);
#endif
            sb.Append(path);

            try
            {
                AssetBundle ab = AssetBundle.LoadFromFile(sb.ToString());
                return(ab);
            }
            catch (System.Exception e)
            {
                UDebug.LogError(e.Message);
                return(null);
            }
        }
Example #13
0
 private bool OnSaveCheck()
 {
     nameDic = new Dictionary <string, int>();
     string[] contents = File.ReadAllLines(Application.dataPath + "/Character.csv");
     for (int i = 0; i < contents.Length; i++)
     {
         if (string.IsNullOrEmpty(contents[i]))
         {
             continue;
         }
         string   kv      = contents[i];
         string[] kvArray = kv.Split(',');
         nameDic.Add(kvArray[1], int.Parse(kvArray[0]));
     }
     for (int i = 0; i < nodeRootList.Count; i++)
     {
         StoryNode sn = nodeRootList[i] as StoryNode;
         if (string.IsNullOrEmpty(sn.characterName))
         {
             sn.roleId = 0;
             continue;
         }
         else if (!nameDic.ContainsKey(sn.characterName))
         {
             UDebug.LogError(sn.characterName + " is not exist!");
             nameDic.Clear();
             return(false);
         }
         else
         {
             sn.roleId = nameDic[sn.characterName];
         }
     }
     nameDic.Clear();
     return(true);
 }
Example #14
0
    private void Save()
    {
        SaveFileDlg pth = new SaveFileDlg();

        pth.structSize   = Marshal.SizeOf(pth);
        pth.filter       = "bytes (*.bytes)";
        pth.file         = new string(new char[256]);
        pth.maxFile      = pth.file.Length;
        pth.fileTitle    = new string(new char[64]);
        pth.maxFileTitle = pth.fileTitle.Length;
        pth.initialDir   = Application.dataPath + "/HotUpdateRes/Story";        // default path
        UDebug.Log(Application.dataPath + "/HotUpdateRes/Story");
        pth.title  = "保存story数据";
        pth.defExt = "bytes";
        pth.flags  = 0x00080000 | 0x00001000 | 0x00000800 | 0x00000200 | 0x00000008;

        Dictionary <string, int> plottext = new Dictionary <string, int>();
        string path = Application.dataPath + "/HotUpdateRes/Config/PlotTextConfig.txt";

        if (!File.Exists(path))
        {
            UDebug.LogError("can not find file : " + path);
            return;
        }
        string[] text           = File.ReadAllLines(path);
        bool     isChangeConfig = false;

        for (int i = 2; i < text.Length; i++)
        {
            if (string.IsNullOrEmpty(text[i]))
            {
                continue;
            }
            string[] plot = text[i].Split('\t');
            try
            {
                plottext.Add(plot[1], int.Parse(plot[0]));
            }
            catch (Exception e)
            {
                UDebug.Log(e.Message);
                UDebug.LogError("第一段:" + plot[0]);
                UDebug.LogError("第二段:" + plot[1]);
                throw;
            }
        }
        for (int i = 0; i < nodeRootList.Count; i++)
        {
            if (string.IsNullOrEmpty(((StoryNode)nodeRootList[i]).text))
            {
                ((StoryNode)nodeRootList[i]).textId = 0;
            }
            else if (plottext.ContainsKey(((StoryNode)nodeRootList[i]).text))
            {
                ((StoryNode)nodeRootList[i]).textId = plottext[((StoryNode)nodeRootList[i]).text];
            }
            else
            {
                int pltid = plottext[plottext.Keys.Last <string>()] + 1;
                plottext.Add(((StoryNode)nodeRootList[i]).text, pltid);
                ((StoryNode)nodeRootList[i]).textId = pltid;
                isChangeConfig = true;
            }
        }
        if (isChangeConfig)
        {
            string[] newtext = new string[plottext.Count + 2];
            int      i       = 2;
            newtext[0] = "id" + "\t" + "text";
            newtext[1] = "int" + "\t" + "string";
            foreach (var item in plottext)
            {
                newtext[i] = item.Value + "\t" + item.Key;
                i++;
            }
            File.WriteAllLines(Application.dataPath + "/HotUpdateRes/Config/PlotTextConfig.txt", newtext);
        }

        if (SaveFileDialog.GetSaveFileName(pth))
        {
            string filepath = pth.file;            //选择的文件路径;
            if (!OnSaveCheck())
            {
                return;
            }
            bool isSuccess = BinaryUtil.ObjectToFile(filepath, nodeRootList[0]);
            if (isSuccess)
            {
                path = filepath;
                UDebug.Log("Save succeed!");
            }
            else
            {
                UDebug.LogError("Save failed!");
            }
        }
    }
Example #15
0
 private void DownErrorHandle(string path, string errorInfo)
 {
     UDebug.LogError(string.Format("{0}下载错误{1}", path, errorInfo));
     popUpBox.Open("资源下载错误!", GameStateManager.Instance.Quit);
 }
Example #16
0
    unsafe static void _RepackLightmap()
    {
        var gos      = Selection.gameObjects;
        var checkMSG = false;

REOPEN:
        if (gos.Length == 0)
        {
            UDebug.LogError("Please select a GameObject in hierarchy to process!");
            return;
        }
        var hierarchy = UnityUtils.GetHierarchyPath(gos[0].transform);

        if (!checkMSG)
        {
            checkMSG = true;
            if (!EditorUtility.DisplayDialog(Title, "请确认:处理的是原始场景,如果已经处理过,请重新加载场景。", "直接整", "好吧,重新加载场景"))
            {
                UnityEditor.SceneManagement.EditorSceneManager.OpenScene(currentScene);
                gos = new GameObject[] { GameObject.Find(hierarchy) };
                goto REOPEN;
            }
        }
        // 经过测试,这个值确实是输出到了最终lightmap纹理中纹理单位的间隔
        var    Padding = LightmapEditorSettings.padding;
        Bounds bounds;
        var    workingPath  = CleanTempFolder();
        var    allRenderers = CollectAllLightmapedRenderers(gos, out bounds).Values.ToList();
        // 把搜集到的原始Mesh重新保存成asset格式,便于后面的修改(FBX无法修改)
        var meshes = new Dictionary <Mesh, Mesh>();

        for (int i = 0; i < allRenderers.Count; ++i)
        {
            var ri      = allRenderers[i];
            var srcMesh = ri.mesh;
            if (!srcMesh.isReadable)
            {
                UDebug.LogError("Mesh \"{0}\" is not readable!");
                continue;
            }
            var mf = ri.renderer.transform.GetComponent <MeshFilter>();
            if (mf == null)
            {
                continue;
            }
            Mesh dstMesh = null;
            if (!meshes.TryGetValue(srcMesh, out dstMesh))
            {
                var assetPath = String.Format("{0}/{1}_{2}.mesh.asset", workingPath, srcMesh.name, meshes.Count);
                if (File.Exists(assetPath))
                {
                    AssetDatabase.DeleteAsset(assetPath);
                }
                AssetDatabase.CreateAsset(UnityEngine.Object.Instantiate <Mesh>(srcMesh), assetPath);
                dstMesh = AssetDatabase.LoadAssetAtPath <Mesh>(assetPath);
                meshes.Add(srcMesh, dstMesh);
            }
            //覆盖原始模型
            mf.sharedMesh = dstMesh;
        }
        if (meshes.Count > 0)
        {
            var litmapData = LoadAllLightmapData();
            if (litmapData == null)
            {
                UDebug.LogError("Load source lightmaps failed.");
                return;
            }
            var inputRects           = new List <NativeAPI.stbrp_rect>();
            var all_atlas_pixels     = new Dictionary <int, AtlasPixelsPage>();
            var lightmapRectInfoList = new List <LightmapRect>();
            using (var tp = new TexturePacker()) {
                for (int i = 0; i < allRenderers.Count; ++i)
                {
                    var ri            = allRenderers[i];
                    var r             = ri.renderer;
                    var uv2BoundsInfo = GetMeshUV2Bounds(r);
                    int lightmapIndex = uv2BoundsInfo.lightmapIndex;
                    if (lightmapIndex >= 0 && lightmapIndex < litmapData.Count)
                    {
                        var  lightmapData     = litmapData[r.lightmapIndex];
                        var  meshUVBounds     = uv2BoundsInfo.srcUVBounds;
                        var  lightmapUVBounds = uv2BoundsInfo.lightmapUVBounds;
                        Real fMinX            = lightmapUVBounds.x * lightmapData.width;
                        Real fMaxX            = lightmapUVBounds.z * lightmapData.width;
                        Real fMinY            = lightmapUVBounds.y * lightmapData.height;
                        Real fMaxY            = lightmapUVBounds.w * lightmapData.height;
#if LIGHTMAPREPACKER_PRECISION_HIGH
                        int pixMinX = ( int )Math.Max(Math.Floor(lightmapUVBounds.x * lightmapData.width), 0);
                        int pixMaxX = ( int )Math.Min(Math.Ceiling(lightmapUVBounds.z * lightmapData.width), lightmapData.width);
                        int pixMinY = ( int )Math.Max(Math.Floor(lightmapUVBounds.y * lightmapData.height), 0);
                        int pixMaxY = ( int )Math.Min(Math.Ceiling(lightmapUVBounds.w * lightmapData.height), lightmapData.height);
#else
                        int pixMinX = ( int )Math.Max(Mathf.Floor(lightmapUVBounds.x * lightmapData.width), 0);
                        int pixMaxX = ( int )Math.Min(Mathf.Ceil(lightmapUVBounds.z * lightmapData.width), lightmapData.width);
                        int pixMinY = ( int )Math.Max(Mathf.Floor(lightmapUVBounds.y * lightmapData.height), 0);
                        int pixMaxY = ( int )Math.Min(Mathf.Ceil(lightmapUVBounds.w * lightmapData.height), lightmapData.height);
#endif
                        if (pixMaxX <= pixMinX || pixMaxY <= pixMinY)
                        {
                            UDebug.LogError("Invalid LightmapUV: {0}", UnityUtils.GetHierarchyPath(r.transform));
                            continue;
                        }
                        // 传入自己的TexturePacker之前,把border大小加上去
                        var rt = default(NativeAPI.stbrp_rect);
                        rt.w = ( ushort )((pixMaxX - pixMinX) + Padding);
                        rt.h = ( ushort )((pixMaxY - pixMinY) + Padding);

                        var lightmapRect = new LightmapRect();
                        lightmapRect.renderer             = r;
                        lightmapRect.lightmapUVBounds     = lightmapUVBounds;
                        lightmapRect.meshUVBounds         = meshUVBounds;
                        lightmapRect.lightmapPixelBounds  = new Vector4i(pixMinX, pixMinY, pixMaxX, pixMaxY);
                        lightmapRect.lightmapPixelFBounds = new Vector4d(fMinX, fMinY, fMaxX, fMaxY);
                        rt.id = lightmapRectInfoList.Count;
                        inputRects.Add(rt);
                        lightmapRectInfoList.Add(lightmapRect);
                    }
                }
                tp.PackRects(inputRects.ToArray());
                tp.ForEach(
                    (page, atlasSize, rt) => {
                    var lightmapRect = lightmapRectInfoList[rt.id];
                    var renderer     = lightmapRect.renderer;
                    var lightmapData = litmapData[renderer.lightmapIndex];
                    AtlasPixelsPage atlas_pixels;
                    if (!all_atlas_pixels.TryGetValue(page, out atlas_pixels))
                    {
                        atlas_pixels = new AtlasPixelsPage {
                            pixels = new Vector4[atlasSize * atlasSize],
                            size   = atlasSize
                        };
                        all_atlas_pixels.Add(page, atlas_pixels);
                    }
                    // 原始像素包围盒,不包含Border
                    var i_minx = ( int )lightmapRect.lightmapPixelBounds.x;
                    var i_miny = ( int )lightmapRect.lightmapPixelBounds.y;
                    var i_maxx = ( int )lightmapRect.lightmapPixelBounds.z;
                    var i_maxy = ( int )lightmapRect.lightmapPixelBounds.w;

#if FIXING_LIGHTMAP_UVBORDER
                    int rtOffset = Padding / 2;
                    if (Padding > 0)
                    {
                        // 扩大边框,多拷贝一些边缘像素消除黑边
                        i_minx -= Padding / 2;
                        i_miny -= Padding / 2;
                        i_maxx += Padding - Padding / 2;
                        i_maxy += Padding - Padding / 2;
                    }
#else
                    int rtOffset = 0;
#endif
                    // lightmap像素块copy
                    fixed(Vector4 * _atlas_pixels = atlas_pixels.pixels)
                    {
                        for (int y = i_miny; y < i_maxy; y++)
                        {
                            int dy = y - i_miny + (rt.y - rtOffset);
                            if (dy < 0 || dy >= atlasSize)
                            {
                                continue;
                            }
                            // 纹理坐标需要翻转一下,像素是翻转了的
                            int _dy        = atlasSize - 1 - dy;
                            int _sy        = lightmapData.height - 1 - y;
                            int _dy_stride = _dy * atlasSize;
                            int _sy_stride = _sy * lightmapData.width;
                            for (int x = i_minx; x < i_maxx; x++)
                            {
                                int dx = x - i_minx + (rt.x - rtOffset);
                                if (dx < 0 || dx >= atlasSize)
                                {
                                    continue;
                                }
                                _atlas_pixels[_dy_stride + dx] = lightmapData.GetPixelClamped(x, _sy);
                            }
                        }
                    }

                    var uvBounds = new Vector4d();

                    Real errorX = 0;
                    Real errorY = 0;
                    Real errorZ = 0;
                    Real errorW = 0;

#if FIXING_LIGHTMAP_UVERROR
                    errorX = lightmapRect.lightmapPixelFBounds.x - lightmapRect.lightmapPixelBounds.x;
                    errorY = lightmapRect.lightmapPixelFBounds.y - lightmapRect.lightmapPixelBounds.y;
                    errorZ = lightmapRect.lightmapPixelFBounds.z - lightmapRect.lightmapPixelBounds.z;
                    errorW = lightmapRect.lightmapPixelFBounds.w - lightmapRect.lightmapPixelBounds.w;
#endif
                    uvBounds.x = ((rt.x + errorX) / ( Real )atlasSize);
                    uvBounds.y = ((rt.y + errorY) / ( Real )atlasSize);
                    // 计算在新的lightmap纹理下的纹理坐标包围盒,由于pack之前我们人为加了一个Padding,所以这里计算要减去
                    uvBounds.z = (((rt.x + rt.w + errorZ) - Padding) / ( Real )atlasSize);
                    uvBounds.w = (((rt.y + rt.h + errorW) - Padding) / ( Real )atlasSize);

                    if (Mathf.Approximately(( float )lightmapRect.meshUVBounds.z, ( float )lightmapRect.meshUVBounds.x) ||
                        Mathf.Approximately(( float )lightmapRect.meshUVBounds.w, ( float )lightmapRect.meshUVBounds.y))
                    {
                        // 无效
                        renderer.lightmapIndex       = -1;
                        renderer.lightmapScaleOffset = new Vector4(1, 1, 0, 0);
                        UDebug.LogError("Invalid LightmapUV's bounds: {0}", UnityUtils.GetHierarchyPath(lightmapRect.renderer.transform));
                    }
                    else
                    {
                        // 计算新的ScaleOffset,映射到新的lightmap纹理
                        renderer.lightmapIndex = page;
                        var sf = CalculateUVScaleOffset(lightmapRect.meshUVBounds, uvBounds);
                        renderer.lightmapScaleOffset = new Vector4(( float )sf.x, ( float )sf.y, ( float )sf.z, ( float )sf.w);
                    }
                }
                    );
                if (all_atlas_pixels.Count > 0)
                {
                    var lightmapOutputPath = workingPath;
                    var lightmaps          = new LightmapData[all_atlas_pixels.Count];
                    var lightmapPathList   = new List <KeyValuePair <String, int> >(all_atlas_pixels.Count);
                    int pageIndex          = 0;
                    foreach (var pagePixels in all_atlas_pixels)
                    {
                        fixed(Vector4 *_atlas_pixels = pagePixels.Value.pixels)
                        {
                            EditorUtility.DisplayProgressBar(Title, "Saving lightmap atlas...", ( float )pageIndex / ( float )all_atlas_pixels.Count);
                            pageIndex++;
                            int atlasSize = pagePixels.Value.size;
                            var path      = String.Format("{0}/lightmap_{1}.exr", lightmapOutputPath, pagePixels.Key);

                            if (File.Exists(path))
                            {
                                AssetDatabase.DeleteAsset(path);
                            }
                            NativeAPI.SaveEXR(( IntPtr )_atlas_pixels, atlasSize, atlasSize, 4, 0, path);
                            lightmapPathList.Add(new KeyValuePair <String, int>(path, pagePixels.Key));
                        }
                    }
                    try {
                        AssetDatabase.Refresh();
                        pageIndex = 0;
                        for (int j = 0; j < lightmapPathList.Count; j++)
                        {
                            var path = lightmapPathList[j].Key;
                            var page = lightmapPathList[j].Value;
                            EditorUtility.DisplayProgressBar(Title, "Apply lightmap atlas...", ( float )pageIndex / ( float )all_atlas_pixels.Count);
                            pageIndex++;
                            var ti = AssetImporter.GetAtPath(path) as TextureImporter;
                            if (ti != null)
                            {
                                if (ti.textureType != TextureImporterType.Lightmap || ti.isReadable || ti.wrapMode != TextureWrapMode.Clamp)
                                {
                                    ti.textureType = TextureImporterType.Lightmap;
                                    ti.isReadable  = false;
                                    ti.wrapMode    = TextureWrapMode.Clamp;
                                    AssetDatabase.ImportAsset(ti.assetPath);
                                }
                                var tex = AssetDatabase.LoadAssetAtPath(path, typeof(Texture2D)) as Texture2D;
                                if (tex != null)
                                {
                                    lightmaps[page] = new LightmapData();
                                    lightmaps[page].lightmapColor = tex;
                                }
                            }
                        }
                    } finally {
                        LightmapSettings.lightmaps = lightmaps;
                    }
                }
            }
        }
    }
    unsafe static void _RepackLightmap()
    {
        var gos      = Selection.gameObjects;
        var checkMSG = false;

REOPEN:
        if (gos.Length == 0)
        {
            UDebug.LogError("Please select a GameObject in hierarchy to process!");
            return;
        }
        var hierarchy = UnityUtils.GetHierarchyPath(gos[0].transform);

        if (!checkMSG)
        {
            checkMSG = true;
            if (!EditorUtility.DisplayDialog(Title, "请确认:处理的是原始场景,如果已经处理过,请重新加载场景。", "直接整", "好吧,重新加载场景"))
            {
                UnityEditor.SceneManagement.EditorSceneManager.OpenScene(currentScene);
                gos = new GameObject[] { GameObject.Find(hierarchy) };
                goto REOPEN;
            }
        }
        // 经过测试,这个值确实是输出到了最终lightmap纹理中纹理单位的间隔
        var    Padding = LightmapEditorSettings.padding;
        Bounds bounds;
        var    workingPath  = CleanTempFolder();
        var    allRenderers = CollectAllLightmapedRenderers(gos, out bounds).Values.ToList();
        // 把搜集到的原始Mesh重新保存成asset格式,便于后面的修改(FBX无法修改)
        var meshes = new Dictionary <Mesh, Mesh>();

        for (int i = 0; i < allRenderers.Count; ++i)
        {
            var ri      = allRenderers[i];
            var srcMesh = ri.mesh;
            if (!srcMesh.isReadable)
            {
                UDebug.LogError("Mesh \"{0}\" is not readable!");
                continue;
            }
            var mf = ri.renderer.transform.GetComponent <MeshFilter>();
            if (mf == null)
            {
                continue;
            }
            Mesh dstMesh = null;
            if (!meshes.TryGetValue(srcMesh, out dstMesh))
            {
                var assetPath = String.Format("{0}/{1}_{2}.mesh.asset", workingPath, srcMesh.name, meshes.Count);
                if (File.Exists(assetPath))
                {
                    AssetDatabase.DeleteAsset(assetPath);
                }
                AssetDatabase.CreateAsset(UnityEngine.Object.Instantiate <Mesh>(srcMesh), assetPath);
                dstMesh = AssetDatabase.LoadAssetAtPath <Mesh>(assetPath);
                meshes.Add(srcMesh, dstMesh);
            }
            //覆盖原始模型
            mf.sharedMesh = dstMesh;
        }
        if (meshes.Count > 0)
        {
            var litmapData = LoadAllLightmapData();
            if (litmapData == null)
            {
                UDebug.LogError("Load source lightmaps failed.");
                return;
            }
            var inputRects           = new List <NativeAPI.stbrp_rect>();
            var all_atlas_pixels     = new Dictionary <int, AtlasPixelsPage>();
            var lightmapRectInfoList = new List <LightmapRect>();
            using (var tp = new TexturePacker()) {
                for (int i = 0; i < allRenderers.Count; ++i)
                {
                    var ri            = allRenderers[i];
                    var r             = ri.renderer;
                    var uv2BoundsInfo = GetMeshUV2Bounds(r);
                    int lightmapIndex = uv2BoundsInfo.lightmapIndex;
                    if (lightmapIndex >= 0 && lightmapIndex < litmapData.Count)
                    {
                        var lightmapData      = litmapData[r.lightmapIndex];
                        var meshUVBounds      = uv2BoundsInfo.srcUVBounds;
                        var lightmapUVBounds  = uv2BoundsInfo.lightmapUVBounds;
                        var _lightmapUVBounds = lightmapUVBounds;

                        // 当前发现有些美术自己展开的UV有超过01现象,尝试自己模拟一下Repeat采样纹理坐标的计算
                        _lightmapUVBounds.x = MathLib.ClampRepeatUV(_lightmapUVBounds.x);
                        _lightmapUVBounds.y = MathLib.ClampRepeatUV(_lightmapUVBounds.y);
                        _lightmapUVBounds.z = MathLib.ClampRepeatUV(_lightmapUVBounds.z);
                        _lightmapUVBounds.w = MathLib.ClampRepeatUV(_lightmapUVBounds.w);

                        // 防止包围盒上下左右颠倒,重新翻转一下
                        if (_lightmapUVBounds.x > _lightmapUVBounds.z)
                        {
                            var temp = _lightmapUVBounds.x;
                            _lightmapUVBounds.x = _lightmapUVBounds.z;
                            _lightmapUVBounds.z = temp;
                        }
                        if (_lightmapUVBounds.y > _lightmapUVBounds.w)
                        {
                            var temp = _lightmapUVBounds.y;
                            _lightmapUVBounds.y = _lightmapUVBounds.w;
                            _lightmapUVBounds.w = temp;
                        }

                        // 纹理坐标到像素坐标转换,此处代码查看了网上流传出来unity4.3里面源码
                        var i_minx   = Mathf.FloorToInt(_lightmapUVBounds.x * ( float )lightmapData.width);
                        var i_miny   = Mathf.FloorToInt(_lightmapUVBounds.y * ( float )lightmapData.height);
                        var i_width  = Mathf.CeilToInt((_lightmapUVBounds.z - _lightmapUVBounds.x) * ( float )lightmapData.width);
                        var i_height = Mathf.CeilToInt((_lightmapUVBounds.w - _lightmapUVBounds.y) * ( float )lightmapData.height);

                        if (i_width <= 0 || i_height <= 0)
                        {
                            UDebug.LogError("Invalid LightmapUV: {0}", UnityUtils.GetHierarchyPath(r.transform));
                            continue;
                        }
                        var i_maxx = i_minx + i_width;
                        var i_maxy = i_miny + i_height;
                        i_minx = Mathf.Clamp(i_minx, 0, lightmapData.width);
                        i_maxx = Mathf.Clamp(i_maxx, 0, lightmapData.width);
                        i_miny = Mathf.Clamp(i_miny, 0, lightmapData.height);
                        i_maxy = Mathf.Clamp(i_maxy, 0, lightmapData.height);

                        // 传入自己的TexturePacker之前,把border大小加上去
                        var rt = default(NativeAPI.stbrp_rect);
                        rt.w = ( ushort )(i_width + Padding);
                        rt.h = ( ushort )(i_height + Padding);

                        var lightmapRect = new LightmapRect();
                        lightmapRect.renderer            = r;
                        lightmapRect.lightmapUVBounds    = lightmapUVBounds;
                        lightmapRect.meshUVBounds        = meshUVBounds;
                        lightmapRect.lightmapPixelBounds = new Vector4(i_minx, i_miny, i_maxx, i_maxy);
                        rt.id = lightmapRectInfoList.Count;
                        inputRects.Add(rt);
                        lightmapRectInfoList.Add(lightmapRect);
                    }
                }
                tp.PackRects(inputRects.ToArray());
                tp.ForEach(
                    (page, atlasSize, rt) => {
                    var lightmapRect = lightmapRectInfoList[rt.id];
                    var renderer     = lightmapRect.renderer;
                    var lightmapData = litmapData[renderer.lightmapIndex];
                    AtlasPixelsPage atlas_pixels;
                    if (!all_atlas_pixels.TryGetValue(page, out atlas_pixels))
                    {
                        atlas_pixels = new AtlasPixelsPage {
                            pixels = new Vector4[atlasSize * atlasSize],
                            size   = atlasSize
                        };
                        all_atlas_pixels.Add(page, atlas_pixels);
                    }
                    int i_minx = ( int )lightmapRect.lightmapPixelBounds.x;
                    int i_miny = ( int )lightmapRect.lightmapPixelBounds.y;
                    int i_maxx = ( int )lightmapRect.lightmapPixelBounds.z;
                    int i_maxy = ( int )lightmapRect.lightmapPixelBounds.w;

                    // lightmap像素块copy
                    fixed(Vector4 * _atlas_pixels = atlas_pixels.pixels)
                    {
                        for (int y = i_miny; y < i_maxy; y++)
                        {
                            int dy = y - i_miny + rt.y;
                            // 纹理坐标需要翻转一下,像素是翻转了的
                            int _dy        = atlasSize - 1 - dy;
                            int _sy        = lightmapData.height - 1 - y;
                            int _dy_stride = _dy * atlasSize;
                            int _sy_stride = _sy * lightmapData.width;
                            for (int x = i_minx; x < i_maxx; x++)
                            {
                                int dx = x - i_minx + rt.x;
                                _atlas_pixels[_dy_stride + dx] = lightmapData.pixels[_sy_stride + x];
                            }
                        }
                    }
                    // 计算在新的lightmap纹理下的纹理坐标包围盒,由于pack之前我们认为加了一个Padding,所以这里计算要减去
                    // 这里估计会有各种影藏的因素导致最终效果和原始效果出现偏差,黑边,偏移,防缩等
                    // 因为在复制像素的时候,包围盒因取整引入了误差,这里为了防止出现黑边,我人为的往里缩小了0.5
                    Vector4 uvBounds;
                    uvBounds.x = ( float )(rt.x + 0.5f) / ( float )atlasSize;
                    uvBounds.y = ( float )(rt.y + 0.5f) / ( float )atlasSize;
                    uvBounds.z = ( float )((rt.x + rt.w) - Padding - 0.5f) / ( float )atlasSize;
                    uvBounds.w = ( float )((rt.y + rt.h) - Padding - 0.5f) / ( float )atlasSize;
                    if (Mathf.Approximately(lightmapRect.meshUVBounds.z, lightmapRect.meshUVBounds.x) ||
                        Mathf.Approximately(lightmapRect.meshUVBounds.w, lightmapRect.meshUVBounds.y))
                    {
                        // 无效
                        renderer.lightmapIndex       = -1;
                        renderer.lightmapScaleOffset = new Vector4(1, 1, 0, 0);
                        UDebug.LogError("Invalid LightmapUV's bounds: {0}", UnityUtils.GetHierarchyPath(lightmapRect.renderer.transform));
                    }
                    else
                    {
                        // 计算新的ScaleOffset,映射到新的lightmap纹理
                        renderer.lightmapIndex       = page;
                        renderer.lightmapScaleOffset = MathLib.CalculateUVScaleOffset(lightmapRect.meshUVBounds, uvBounds);
                    }
                }
                    );
                if (all_atlas_pixels.Count > 0)
                {
                    var lightmapOutputPath = workingPath;
                    var lightmaps          = new LightmapData[all_atlas_pixels.Count];
                    var lightmapPathList   = new List <KeyValuePair <String, int> >(all_atlas_pixels.Count);
                    int pageIndex          = 0;
                    foreach (var pagePixels in all_atlas_pixels)
                    {
                        fixed(Vector4 *_atlas_pixels = pagePixels.Value.pixels)
                        {
                            EditorUtility.DisplayProgressBar(Title, "Saving lightmap atlas...", ( float )pageIndex / ( float )all_atlas_pixels.Count);
                            pageIndex++;
                            int atlasSize = pagePixels.Value.size;
                            var path      = String.Format("{0}/lightmap_{1}.exr", lightmapOutputPath, pagePixels.Key);

                            if (File.Exists(path))
                            {
                                AssetDatabase.DeleteAsset(path);
                            }
                            NativeAPI.SaveEXR(( IntPtr )_atlas_pixels, atlasSize, atlasSize, 4, 0, path);
                            lightmapPathList.Add(new KeyValuePair <String, int>(path, pagePixels.Key));
                        }
                    }
                    try {
                        AssetDatabase.Refresh();
                        pageIndex = 0;
                        for (int j = 0; j < lightmapPathList.Count; j++)
                        {
                            var path = lightmapPathList[j].Key;
                            var page = lightmapPathList[j].Value;
                            EditorUtility.DisplayProgressBar(Title, "Apply lightmap atlas...", ( float )pageIndex / ( float )all_atlas_pixels.Count);
                            pageIndex++;
                            var ti = AssetImporter.GetAtPath(path) as TextureImporter;
                            if (ti != null)
                            {
                                if (ti.textureType != TextureImporterType.Lightmap || ti.isReadable || ti.wrapMode != TextureWrapMode.Clamp)
                                {
                                    ti.textureType = TextureImporterType.Lightmap;
                                    ti.isReadable  = false;
                                    ti.wrapMode    = TextureWrapMode.Clamp;
                                    AssetDatabase.ImportAsset(ti.assetPath);
                                }
                                var tex = AssetDatabase.LoadAssetAtPath(path, typeof(Texture2D)) as Texture2D;
                                if (tex != null)
                                {
                                    lightmaps[page] = new LightmapData();
                                    lightmaps[page].lightmapLight = tex;
                                }
                            }
                        }
                    } finally {
                        LightmapSettings.lightmaps = lightmaps;
                    }
                }
            }
        }
    }
        void CreateAnimationButtons()
        {
            skillIDDict.Clear();
            animationButtons.Clear();
            animationButtonSource.gameObject.SetActive(true);
            while (animationButtonSource.transform.parent.childCount > 1)
            {
                if (animationButtonSource.transform.parent.GetChild(0).name == animationButtonSource.gameObject.name)
                {
                    DestroyImmediate(animationButtonSource.transform.parent.GetChild(1).gameObject);
                }
                else
                {
                    DestroyImmediate(animationButtonSource.transform.parent.GetChild(0).gameObject);
                }
            }

            if (m_mainRole != null)
            {
                if (m_mainRole.GetComponent <Animation>() != null)
                {
                    m_roleAnim = m_mainRole.GetComponent <Animation>();
                    if (m_PrefabSkillID != null)
                    {
                        bool isFounding = true;
                        while (isFounding)
                        {
                            isFounding = false;
                            foreach (AnimationState state in m_roleAnim)
                            {
                                isFounding = true;
                                m_roleAnim.RemoveClip(state.clip);
                            }
                        }

                        checkNone = false;
                        for (int i = 0; i < m_PrefabSkillID.m_Animations.Count; i++)
                        {
                            if (m_PrefabSkillID.m_Animations[i] != null)
                            {
                                m_roleAnim.AddClip(m_PrefabSkillID.m_Animations[i], m_PrefabSkillID.m_Animations[i].name + "/" + m_PrefabSkillID.m_SkillIDList[i].ToString());
                            }
                            else
                            {
                                Debug.LogException(new NoneObjectException(string.Format("{0}的第{1}个AnimationClip为空!!!", m_mainRole.name, i)), m_RSS);
                                checkNone = true;
                            }
                        }
                        if (checkNone)
                        {
                            EditorApplication.ExecuteMenuItem("Edit/Play");
                        }

                        if (m_roleAnim.GetClip("idle/0") != null)
                        {
                            m_roleAnim.clip = m_roleAnim.GetClip("idle/0");
                        }
                        else
                        {
                            m_roleAnim.clip = m_roleAnim.GetClip(m_PrefabSkillID.m_Animations[0].name);
                        }

                        currentState = m_roleAnim[m_roleAnim.clip.name];
                        m_roleAnim.Play(currentState.name);
                    }
                    int index = -1;
                    foreach (AnimationState state in m_roleAnim)
                    {
                        index += 1;
                        int    tempIndex = index;
                        Button button    = Instantiate(animationButtonSource, animationButtonSource.transform.parent);
                        button.name = "  " + state.clip.name;
                        button.transform.Find("Name").GetComponent <Text>().text = button.name.Substring(0, button.name.IndexOf('/'));
                        button.transform.Find("Time").GetComponent <Text>().text = string.Format("{0:0.00}", state.length);
                        button.onClick.AddListener(delegate
                        {
                            if (playTogetherToggle.isOn)
                            {
                                Button newBtn = Instantiate(button, playTogetherTransform);
                                newBtn.name   = button.name;
                                newBtn.onClick.RemoveAllListeners();
                                newBtn.onClick.AddListener(delegate
                                {
                                    DestroyImmediate(newBtn.gameObject);
                                });
                            }
                            else
                            {
                                m_roleAnim.Play(state.name, PlayMode.StopAll);
                                lastState    = currentState;
                                currentState = m_roleAnim[state.name];
                                PlaySFX(button.name, m_PrefabSkillID.m_SkillIDList[tempIndex], m_SFXLevel);
                                frameCount          = ( int )(state.length * state.clip.frameRate);
                                animSlider.maxValue = frameCount;
                            }
                        });
                        animationButtons.Add(state.name, button);
                        skillIDDict.Add(state.clip.name, tempIndex);
                    }
                    animationButtonSource.gameObject.SetActive(false);
                }
                else
                {
                    UDebug.LogError("There's no animation attatched to the player!!!!!");
                }
            }
            else
            {
                UDebug.LogError("No player exist!!!!!!");
            }
        }