コード例 #1
0
 private static void LoadCachedAtlas2()
 {
     _CachedAtlasSpriteGUID.Clear();
     _CachedAtlasPath.Clear();
     if (PlatDependant.IsFileExist("EditorOutput/Runtime/atlas.txt"))
     {
         string json = "";
         using (var sr = PlatDependant.OpenReadText("EditorOutput/Runtime/atlas.txt"))
         {
             json = sr.ReadToEnd();
         }
         try
         {
             var jo = new JSONObject(json);
             try
             {
                 var joc = jo["atlas"] as JSONObject;
                 if (joc != null && joc.type == JSONObject.Type.ARRAY)
                 {
                     for (int i = 0; i < joc.list.Count; ++i)
                     {
                         var val = joc.list[i].str;
                         SaveSpriteGUID(val);
                     }
                 }
             }
             catch { }
         }
         catch { }
     }
 }
コード例 #2
0
ファイル: HotFixTest.cs プロジェクト: SilasDarkmoon/CapsLua
        public void TestVoidFunc()
        {
            HashSet <string> recordedMembers = new HashSet <string>();
            HashSet <string> compiledMembers = new HashSet <string>();

            var cachedPath = "Assets/Mods/CapsLua/LuaPrecompile/MemberList.txt";

            //var cachedPath = "EditorOutput/LuaPrecompile/CachedCommands.txt";
            if (PlatDependant.IsFileExist(cachedPath))
            {
                try
                {
                    using (var sr = PlatDependant.OpenReadText(cachedPath))
                    {
                        while (true)
                        {
                            var line = sr.ReadLine();
                            if (line == null)
                            {
                                break;
                            }

                            if (!string.IsNullOrEmpty(line))
                            {
                                recordedMembers.Add(line);
                            }
                        }
                    }
                }
                catch (Exception e)
                {
                    PlatDependant.LogError(e);
                }
            }
        }
コード例 #3
0
        static CapsAtlasLoaderEditor()
        {
            if (PlatDependant.IsFileExist("EditorOutput/Runtime/atlas.txt"))
            {
                LoadCachedAtlas();
            }
            else
            {
                CacheAllAtlas();
                SaveCachedAtlas();
            }

            UnityEngine.U2D.SpriteAtlasManager.atlasRequested += (name, funcReg) =>
            {
                if (UnityEditor.EditorSettings.spritePackerMode == UnityEditor.SpritePackerMode.AlwaysOnAtlas && !(ResManager.ResLoader is ResManager.ClientResLoader))
                {
                    string assetName;
                    if (_CachedAtlas.TryGetValue(name, out assetName))
                    {
                        var atlas = AssetDatabase.LoadAssetAtPath <UnityEngine.U2D.SpriteAtlas>(assetName);
                        if (atlas)
                        {
                            funcReg(atlas);
                        }
                    }
                }
            };
        }
コード例 #4
0
        public static void SaveCachedAtlas()
        {
            var jo  = new JSONObject(JSONObject.Type.OBJECT);
            var joc = new JSONObject(JSONObject.Type.ARRAY);

            jo["atlas"] = joc;
            foreach (var asset in _CachedAtlasRev.Keys)
            {
                joc.Add(asset);
            }

            //joc = new JSONObject(JSONObject.Type.OBJECT);
            //jo["tex"] = joc;
            //foreach (var kvp in _TexInAtlas)
            //{
            //    var name = kvp.Key;
            //    var list = kvp.Value;
            //    if (list != null && list.Count > 0)
            //    {
            //        var jlist = new JSONObject(JSONObject.Type.ARRAY);
            //        joc[name] = jlist;
            //        for (int i = 0; i < list.Count; ++i)
            //        {
            //            jlist.Add(list[i]);
            //        }
            //    }
            //}

            using (var sw = PlatDependant.OpenWriteText("EditorOutput/Runtime/atlas.txt"))
            {
                sw.Write(jo.ToString(true));
            }
        }
コード例 #5
0
        public static void BuildDelegateWrapperForAOT(IEnumerable <Types> deltypes, string file)
        {
            CodeCompileUnit cu = new CodeCompileUnit();
            CodeNamespace   ns = new CodeNamespace("Capstones.LuaWrap.DelWrapperAOT");

            cu.Namespaces.Add(ns);

            CodeTypeDeclaration type_Entry = new CodeTypeDeclaration("DelWrapperAOTEntry");

            type_Entry.TypeAttributes = TypeAttributes.Public | TypeAttributes.Class;
            ns.Types.Add(type_Entry);

            CodeMemberMethod method_Entry = new CodeMemberMethod();

            method_Entry.Name       = "Entry";
            method_Entry.Attributes = MemberAttributes.Private | MemberAttributes.Static;
            method_Entry.ReturnType = new CodeTypeReference(typeof(void));
            type_Entry.Members.Add(method_Entry);
            method_Entry.Statements.Add(new CodeSnippetStatement("#pragma warning disable CS0618"));

            foreach (var deltype in deltypes)
            {
                var delpars = deltype;
                if (delpars[0] == typeof(void))
                {
                    var wrapper = CapsLuaDelegateGenerator.GetWrapperType(delpars[0], delpars.Count - 1);
                    if (wrapper != null)
                    {
                        CodeTypeReference wtype = new CodeTypeReference(wrapper);
                        for (int i = 1; i < delpars.Count; ++i)
                        {
                            wtype.TypeArguments.Add(delpars[i]);
                        }
                        CodeObjectCreateExpression exp_new = new CodeObjectCreateExpression(wtype);
                        method_Entry.Statements.Add(exp_new);
                    }
                }
                else
                {
                    var wrapper = CapsLuaDelegateGenerator.GetWrapperType(delpars[0], delpars.Count - 1);
                    if (wrapper != null)
                    {
                        CodeTypeReference wtype = new CodeTypeReference(wrapper);
                        for (int i = 0; i < delpars.Count; ++i)
                        {
                            wtype.TypeArguments.Add(delpars[i]);
                        }
                        CodeObjectCreateExpression exp_new = new CodeObjectCreateExpression(wtype);
                        method_Entry.Statements.Add(exp_new);
                    }
                }
            }
            method_Entry.Statements.Add(new CodeSnippetStatement("#pragma warning restore CS0618"));

            Microsoft.CSharp.CSharpCodeProvider csharpcodeprovider = new Microsoft.CSharp.CSharpCodeProvider();
            using (var sw = PlatDependant.OpenWriteText(file))
            {
                csharpcodeprovider.GenerateCodeFromCompileUnit(cu, sw, new System.CodeDom.Compiler.CodeGeneratorOptions());
            }
        }
コード例 #6
0
        public static List <string> ParseHotFixList()
        {
            List <string> list     = new List <string>();
            var           prelists = CapsModEditor.FindAssetsInMods("LuaHotFix/MemberList.txt");

            foreach (var listfile in prelists)
            {
                using (var sr = PlatDependant.OpenReadText(listfile))
                {
                    while (true)
                    {
                        var line = sr.ReadLine();
                        if (line == null)
                        {
                            break;
                        }
                        if (!string.IsNullOrEmpty(line))
                        {
                            if (line.StartsWith("--"))
                            {
                            }
                            else
                            {
                                list.Add(line);
                            }
                        }
                    }
                }
            }
            return(list);
        }
コード例 #7
0
 public static void StartLoadRuntimeManifest()
 {
     _RuntimeRawManifest = null;
     _RuntimeManifest    = null;
     _RuntimeManifestReady.Reset();
     _RuntimeManifestTaskIdle.Reset();
     PlatDependant.RunBackground(LoadRuntimeManifest);
 }
コード例 #8
0
        public static void ResetRuntimeManifest()
        {
            _RuntimeManifestTaskIdle.WaitOne();
            var filePath = ThreadSafeValues.UpdatePath + "/spt/manifest.m.txt";

            PlatDependant.DeleteFile(filePath);
            StartLoadRuntimeManifest();
        }
コード例 #9
0
        private static bool AddFontReplacement(string asset)
        {
            if (PlatDependant.IsFileExist(asset))
            {
                try
                {
                    var desc = AssetDatabase.LoadAssetAtPath <CapsFontReplacement>(asset);
                    if (desc)
                    {
                        try
                        {
                            var    phname = desc.PlaceHolderFontName;
                            var    rfont = desc.SubstituteFont;
                            string type, mod, dist;
                            string norm = ResManager.GetAssetNormPath(asset, out type, out mod, out dist);

                            if (!_FontReplacementDescs.ContainsKey(asset))
                            {
                                var info = new FontReplacement()
                                {
                                    PlaceHolderFontName = phname,
                                    SubstituteFont      = rfont,
                                    DescAssetPath       = asset,
                                    Mod  = mod,
                                    Dist = dist,
                                };
                                List <FontReplacement> list;
                                if (!_FontReplacements.TryGetValue(phname, out list))
                                {
                                    list = new List <FontReplacement>();
                                    _FontReplacements[phname] = list;
                                }
                                list.Add(info);

                                _FontReplacementDescs[asset] = info;
                                return(true);
                            }
                            else
                            {
                                var info = _FontReplacementDescs[asset];
                                if (info.PlaceHolderFontName != desc.name)
                                {
                                    RemoveFontReplacement(asset);
                                    AddFontReplacement(asset);
                                    return(true);
                                }
                            }
                        }
                        finally
                        {
                            Resources.UnloadAsset(desc);
                        }
                    }
                }
                catch { }
            }
            return(false);
        }
コード例 #10
0
        public static void LogError(this IntPtr l, object message)
        {
            PushLuaStackTrace(l);
            var lstack = l.tostring(-1);

            l.pop(1);
            var m = (message ?? "nullptr").ToString() + "\n" + lstack;

            PlatDependant.LogError(m);
        }
コード例 #11
0
 public static void ReinitGlobalLuaInEditor()
 {
     if (!Application.isPlaying)
     {
         ReinitGlobalLua();
     }
     else
     {
         PlatDependant.LogError("Cannot reinit global lua while playing.");
     }
 }
コード例 #12
0
        private static void SaveCachedPHFonts()
        {
            var jo          = new JSONObject(JSONObject.Type.OBJECT);
            var phfontsnode = new JSONObject(_PHFontNameToAssetName);

            jo["phfonts"] = phfontsnode;
            using (var sw = PlatDependant.OpenWriteText("EditorOutput/Runtime/phfont.txt"))
            {
                sw.Write(jo.ToString(true));
            }
        }
コード例 #13
0
 public static void LoadCachedAtlas()
 {
     _CachedAtlas.Clear();
     _CachedAtlasRev.Clear();
     //_TexInAtlas.Clear();
     if (PlatDependant.IsFileExist("EditorOutput/Runtime/atlas.txt"))
     {
         string json = "";
         using (var sr = PlatDependant.OpenReadText("EditorOutput/Runtime/atlas.txt"))
         {
             json = sr.ReadToEnd();
         }
         try
         {
             var jo = new JSONObject(json);
             try
             {
                 var joc = jo["atlas"] as JSONObject;
                 if (joc != null && joc.type == JSONObject.Type.ARRAY)
                 {
                     for (int i = 0; i < joc.list.Count; ++i)
                     {
                         var val  = joc.list[i].str;
                         var name = System.IO.Path.GetFileNameWithoutExtension(val);
                         _CachedAtlas[name]   = val;
                         _CachedAtlasRev[val] = name;
                     }
                 }
                 //joc = jo["tex"] as JSONObject;
                 //if (joc != null && joc.type == JSONObject.Type.OBJECT)
                 //{
                 //    for (int i = 0; i < joc.list.Count; ++i)
                 //    {
                 //        var key = joc.keys[i];
                 //        var val = joc.list[i];
                 //        if (val != null && val.type == JSONObject.Type.ARRAY)
                 //        {
                 //            var list = new List<string>();
                 //            _TexInAtlas[key] = list;
                 //            for (int j = 0; j < val.list.Count; ++j)
                 //            {
                 //                list.Add(val.list[i].str);
                 //            }
                 //        }
                 //    }
                 //}
             }
             catch { }
         }
         catch { }
     }
 }
コード例 #14
0
        public static void TestPack <TLuaPack>()
            where TLuaPack : struct, ILuaPack
        {
            var      l    = GlobalLua.L.L;
            TLuaPack pin  = default;
            TLuaPack pout = default;

            l.CallGlobal("TestPack", pin, out pout);
            for (int i = 0; i < pout.ElementCount; ++i)
            {
                PlatDependant.LogError(pout[i]);
            }
        }
コード例 #15
0
        public static void TestLua()
        {
            UnityEditor.AssetDatabase.OpenAsset(UnityEditor.AssetDatabase.LoadMainAssetAtPath(ResManager.__ASSET__), ResManager.__LINE__);

            var l = GlobalLua.L.L;

            using (var lr = l.CreateStackRecover())
            {
                l.pushnumber(250);
                string str;
                l.CallGlobal(out str, "dump", LuaPack.Pack(l.OnStack(-1)));
                PlatDependant.LogError(str);
            }
        }
コード例 #16
0
        public void OnSuccess()
        {
            var jo  = new JSONObject(JSONObject.Type.OBJECT);
            var joc = new JSONObject(_NewMap);

            jo["tex"] = joc;

            var cachefile = _Output + "/res/inatlas.txt";

            using (var sw = PlatDependant.OpenWriteText(cachefile))
            {
                sw.Write(jo.ToString(true));
            }
        }
コード例 #17
0
        private static void DeletePHFont(string fontasset)
        {
            var src     = fontasset + ".~";
            var meta    = fontasset + ".meta";
            var srcmeta = fontasset + ".meta.~";

            PlatDependant.DeleteFile(src);
            PlatDependant.DeleteFile(srcmeta);

            if (PlatDependant.IsFileExist(fontasset))
            {
                AssetDatabase.DeleteAsset(fontasset);
            }
        }
コード例 #18
0
 internal static void DisposeObj(IntPtr handle)
 {
     if (handle != IntPtr.Zero)
     {
         try
         {
             var gchandle = (GCHandle)handle;
             gchandle.Free();
         }
         catch (Exception e)
         {
             PlatDependant.LogError(e);
         }
     }
 }
コード例 #19
0
ファイル: HotFixTest.cs プロジェクト: SilasDarkmoon/CapsLua
        public int TestReturnOutFunc(string filePath, int times, out string rv)
        {
            string last = null;

            for (int i = 0; i < times; ++i)
            {
                if (i == 3)
                {
                    rv = i.ToString();
                    return(i);
                }
                HashSet <string> recordedMembers = new HashSet <string>();
                HashSet <string> compiledMembers = new HashSet <string>();

                var cachedPath = filePath + i;
                //var cachedPath = "EditorOutput/LuaPrecompile/CachedCommands.txt";
                if (PlatDependant.IsFileExist(cachedPath))
                {
                    try
                    {
                        using (var sr = PlatDependant.OpenReadText(cachedPath))
                        {
                            while (true)
                            {
                                var line = sr.ReadLine();
                                if (line == null)
                                {
                                    break;
                                }
                                last = line;
                                if (!string.IsNullOrEmpty(line))
                                {
                                    recordedMembers.Add(line);
                                }
                            }
                        }
                    }
                    catch (Exception e)
                    {
                        PlatDependant.LogError(e);
                        rv = e.Message;
                        return(i);
                    }
                }
            }
            rv = last;
            return(last?.Length ?? 0);
        }
コード例 #20
0
        private static bool CachePHFont(string fontasset)
        {
            var src     = fontasset + ".~";
            var meta    = fontasset + ".meta";
            var srcmeta = fontasset + ".meta.~";

            if (PlatDependant.IsFileExist(src) && !PlatDependant.IsFileExist(fontasset))
            {
                PlatDependant.CopyFile(src, fontasset);
                if (PlatDependant.IsFileExist(srcmeta))
                {
                    PlatDependant.CopyFile(srcmeta, meta);
                }
                AssetDatabase.ImportAsset(fontasset);
                return(true);
            }
            return(false);
        }
コード例 #21
0
        private static void SaveCachedReplacement()
        {
            var jo    = new JSONObject(JSONObject.Type.OBJECT);
            var rnode = new JSONObject(JSONObject.Type.ARRAY);

            jo["replacements"] = rnode;
            foreach (var asset in _FontReplacementDescs.Keys)
            {
                rnode.list.Add(new JSONObject(JSONObject.Type.STRING)
                {
                    str = asset
                });
            }
            using (var sw = PlatDependant.OpenWriteText("EditorOutput/Runtime/rfont.txt"))
            {
                sw.Write(jo.ToString(true));
            }
        }
コード例 #22
0
 void OnGUI()
 {
     GUILayout.BeginVertical();
     GUILayout.Label("Which precompiler symbol would you like to define?");
     _Symbol = GUILayout.TextField(_Symbol);
     if (GUILayout.Button("OK"))
     {
         if (string.IsNullOrEmpty(_Symbol))
         {
             EditorUtility.DisplayDialog("Error", "Empty Symbol!", "OK");
         }
         else if (_Symbol.EndsWith("_"))
         {
             EditorUtility.DisplayDialog("Error", "Symbol should not end with _", "OK");
         }
         else
         {
             if (System.IO.Directory.Exists("Assets/Mods/" + _Symbol))
             {
                 EditorUtility.DisplayDialog("Warning", "It seems that the mod has been already created.", "OK");
             }
             else
             {
                 var descdir = "Assets/Mods/" + _Symbol + "/Resources";
                 System.IO.Directory.CreateDirectory(descdir);
                 AssetDatabase.ImportAsset(descdir);
                 var desc = ScriptableObject.CreateInstance <CapsModDesc>();
                 desc.Mod = _Symbol;
                 AssetDatabase.CreateAsset(desc, "Assets/Mods/" + _Symbol + "/Resources/resdesc.asset");
                 var sympath = "Assets/Mods/" + _Symbol + "/Link/mcs.rsp";
                 using (var sw = PlatDependant.OpenWriteText(sympath))
                 {
                     sw.Write("-define:");
                     sw.WriteLine(_Symbol);
                 }
                 CapsModEditor.CheckModsVisibility();
                 DistributeSelectWindow.Init();
             }
             Close();
         }
     }
     GUILayout.EndVertical();
 }
コード例 #23
0
        public static T GetContainer <T>() where T : class
        {
            var handle = NativeImported.GetThreadLocalContainer();

            if (handle != IntPtr.Zero)
            {
                object obj = null;
                try
                {
                    obj = ((GCHandle)handle).Target;
                }
                catch (Exception e)
                {
                    PlatDependant.LogError(e);
                }
                return(obj as T);
            }
            return(null);
        }
コード例 #24
0
        private static bool CheckCachedPHFonts()
        {
            bool dirty  = false;
            var  assets = _PHFontAssetNameToFontName.Keys.ToArray();

            foreach (var font in assets)
            {
                if (!PlatDependant.IsFileExist(font))
                {
                    if (!CachePHFont(font))
                    {
                        var fname = _PHFontAssetNameToFontName[font];
                        _PHFontNameToAssetName.Remove(fname);
                        _PHFontAssetNameToFontName.Remove(font);
                        dirty = true;
                    }
                }
            }
            return(dirty);
        }
コード例 #25
0
        public static string FindDistributeAsset(string norm)
        {
            var strval = norm;

            if (strval.StartsWith("Assets/"))
            {
                if (PlatDependant.IsFileExist(strval))
                {
                    return(strval);
                }
            }
            string real = strval;

            if (!real.StartsWith("CapsSpt/") && !real.StartsWith("CapsRes/"))
            {
                real = "CapsRes/" + real;
            }
            real = ResManager.EditorResLoader.CheckDistributePath(real);
            return(real);
        }
コード例 #26
0
ファイル: HotFixTest.cs プロジェクト: SilasDarkmoon/CapsLua
        public void TestParamFunc(string filePath, int times)
        {
            for (int i = 0; i < times; ++i)
            {
                HashSet <string> recordedMembers = new HashSet <string>();
                HashSet <string> compiledMembers = new HashSet <string>();

                var cachedPath = filePath + i;
                //var cachedPath = "EditorOutput/LuaPrecompile/CachedCommands.txt";
                if (PlatDependant.IsFileExist(cachedPath))
                {
                    try
                    {
                        using (var sr = PlatDependant.OpenReadText(cachedPath))
                        {
                            while (true)
                            {
                                var line = sr.ReadLine();
                                if (line == null)
                                {
                                    break;
                                }

                                if (!string.IsNullOrEmpty(line))
                                {
                                    recordedMembers.Add(line);
                                }
                            }
                        }
                    }
                    catch (Exception e)
                    {
                        PlatDependant.LogError(e);
                    }
                }
            }
        }
コード例 #27
0
        public static void SaveManifest(CapsResManifest mani, string file)
        {
            var tmpfile = file + ".tmp";

            using (var sw = PlatDependant.OpenWriteText(tmpfile))
            {
                if (mani != null && mani.Root != null)
                {
                    Stack <Pack <int, CapsResManifestNode> > candis = new Stack <Pack <int, CapsResManifestNode> >();
                    candis.Push(new Pack <int, CapsResManifestNode>(0, mani.Root));
                    while (candis.Count > 0)
                    {
                        var ppair  = candis.Pop();
                        var plvl   = ppair.t1;
                        var parent = ppair.t2;

                        for (int i = 0; i < plvl; ++i)
                        {
                            sw.Write("*");
                        }
                        sw.WriteLine(parent.PPath ?? "");

                        var children = parent.Children;
                        if (children != null)
                        {
                            var clvl = plvl + 1;
                            for (int i = children.Count - 1; i >= 0; --i)
                            {
                                var child = children.Values[i];
                                candis.Push(new Pack <int, CapsResManifestNode>(clvl, child));
                            }
                        }
                    }
                }
            }
            PlatDependant.MoveFile(tmpfile, file);
        }
コード例 #28
0
 public void OnPreprocessBuild(BuildTarget target, string path)
 {
     using (var sw = PlatDependant.OpenWriteText("Assets/StreamingAssets/res/index.txt"))
     {
         var files = PlatDependant.GetAllFiles("Assets/StreamingAssets/res/mani/");
         if (files != null)
         {
             for (int i = 0; i < files.Length; ++i)
             {
                 var file = files[i];
                 if (file.EndsWith(".m.ab"))
                 {
                     var key = file.Substring("Assets/StreamingAssets/res/mani/".Length, file.Length - "Assets/StreamingAssets/res/mani/".Length - ".m.ab".Length);
                     sw.WriteLine(key);
                 }
             }
         }
     }
     using (var sw = PlatDependant.OpenWriteText("Assets/StreamingAssets/res/builtin-scenes.txt"))
     {
         var scenes = EditorBuildSettings.scenes;
         int index  = 0;
         for (int i = 0; i < scenes.Length; ++i)
         {
             var sceneinfo = scenes[i];
             if (sceneinfo.enabled)
             {
                 var guid      = sceneinfo.guid.ToString();
                 var scenepath = AssetDatabase.GUIDToAssetPath(guid);
                 sw.Write(scenepath);
                 sw.Write("|");
                 sw.WriteLine(index++);
             }
         }
     }
 }
コード例 #29
0
        static CapsPHFontEditor()
        {
            if (PlatDependant.IsFileExist("EditorOutput/Runtime/phfont.txt"))
            {
                ParseCachedPHFonts();
                if (CheckCachedPHFonts())
                {
                    SaveCachedPHFonts();
                }
            }
            else
            {
                CheckAllPHFonts();
                SaveCachedPHFonts();
            }

            CapsModEditor.ShouldAlreadyInit();
            CapsPackageEditor.OnPackagesChanged += () =>
            {
                if (PlatDependant.IsFileExist("EditorOutput/Runtime/rfont.txt"))
                {
                    if (LoadCachedReplacement())
                    {
                        SaveCachedReplacement();
                    }
                }
                else
                {
                    CheckAllReplacements();
                    SaveCachedReplacement();
                }

                ReplaceRuntimePHFonts();
            };
            CapsDistributeEditor.OnDistributeFlagsChanged += ReplaceRuntimePHFonts;
        }
コード例 #30
0
        public static void CreateFontReplacement()
        {
            var sids = Selection.instanceIDs;

            if (sids != null && sids.Length > 0)
            {
                bool found        = false;
                Font selectedFont = null;
                int  fid          = 0;
                for (int i = sids.Length - 1; i >= 0; --i)
                {
                    var sid = sids[i];
                    var obj = EditorUtility.InstanceIDToObject(sid);
                    if (obj is Font)
                    {
                        var font = obj as Font;
                        try
                        {
                            var fi = AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(font)) as TrueTypeFontImporter;
                            if (fi != null)
                            {
                                if (!_PHFontNameToAssetName.ContainsKey(fi.fontTTFName))
                                {
                                    selectedFont = font;
                                    break;
                                }
                            }
                        }
                        catch { }
                    }
                }
                for (int i = sids.Length - 1; i >= 0; --i)
                {
                    var sid = sids[i];
                    if (ProjectWindowUtil.IsFolder(sid))
                    {
                        fid   = sid;
                        found = true;
                        break;
                    }
                }
                string folder;
                if (!found)
                {
                    folder = ProjectWindowUtil.GetContainingFolder(AssetDatabase.GetAssetPath(EditorUtility.InstanceIDToObject(sids[0])));
                }
                else
                {
                    folder = AssetDatabase.GetAssetPath(EditorUtility.InstanceIDToObject(fid));
                }
                var asset = folder;
                folder = CapsModEditor.GetAssetPath(folder); // this seems to be useless. Unity's System.IO lib can handle path like Packages/cn.capstones.phfont/xxx

                var desc = ScriptableObject.CreateInstance <CapsFontReplacement>();
                desc.PlaceHolderFontName = GetFontReplacementPHFontName(asset) ?? "CapstonesPHFont00000";
                desc.SubstituteFont      = selectedFont;

                var fileName = "FontReplacement";
                if (PlatDependant.IsFileExist(folder + "/" + fileName + ".fr.asset"))
                {
                    for (int i = 0; ; ++i)
                    {
                        fileName = "FontReplacement" + i;
                        if (!PlatDependant.IsFileExist(folder + "/" + fileName + ".fr.asset"))
                        {
                            break;
                        }
                    }
                }

                AssetDatabase.CreateAsset(desc, asset + "/" + fileName + ".fr.asset");
                AssetDatabase.ImportAsset(asset + "/" + fileName + ".fr.asset");
            }
        }