public static void DoIt() { string dirName = "Assets/Animation"; string spineFileName = "hounv"; string textureName = dirName + "/" + spineFileName + "/" + spineFileName + ".png"; string atlasFileName = dirName + "/" + spineFileName + "/" + spineFileName + ".atlas.txt"; string jsonFileName = dirName + "/" + spineFileName + "/" + spineFileName + ".json.txt"; string atlasAssetName = dirName + "/" + spineFileName + "/" + spineFileName + ".asset"; string skeletonDataAssetName = dirName + "/" + spineFileName + "/" + spineFileName + "skeltonData" + ".asset"; ///1、 创建材质,并指贴图和shader Shader shader = Shader.Find("Spine/SkeletonGhost"); Material mat = new Material(shader); Texture tex = Resources.LoadAssetAtPath(textureName, typeof(Texture)) as Texture; mat.SetTexture("_MainTex", tex); AssetDatabase.CreateAsset(mat, dirName + "/" + spineFileName + "/" + spineFileName + ".mat"); AssetDatabase.SaveAssets(); ///2、 创建atlas,并指xx AtlasAsset m_AtlasAsset = AtlasAsset.CreateInstance <AtlasAsset>(); AssetDatabase.CreateAsset(m_AtlasAsset, atlasAssetName); Selection.activeObject = m_AtlasAsset; TextAsset textAsset = Resources.LoadAssetAtPath(atlasFileName, typeof(TextAsset)) as TextAsset; m_AtlasAsset.atlasFile = textAsset; m_AtlasAsset.materials = new Material[1]; m_AtlasAsset.materials[0] = mat; AssetDatabase.SaveAssets(); ///3、 创建SkeletonDataAsset,并指相关 SkeletonDataAsset m_skeltonDataAsset = SkeletonDataAsset.CreateInstance <SkeletonDataAsset>(); AssetDatabase.CreateAsset(m_skeltonDataAsset, skeletonDataAssetName); Selection.activeObject = m_skeltonDataAsset; m_skeltonDataAsset.atlasAssets = new AtlasAsset[1]; m_skeltonDataAsset.atlasAssets[0] = m_AtlasAsset; TextAsset m_jsonAsset = Resources.LoadAssetAtPath(jsonFileName, typeof(TextAsset)) as TextAsset; m_skeltonDataAsset.skeletonJSON = m_jsonAsset; AssetDatabase.SaveAssets(); /// 创建场景物件 GameObject gameObject = new GameObject(spineFileName, typeof(SkeletonAnimation)); EditorUtility.FocusProjectWindow(); Selection.activeObject = gameObject; SkeletonAnimation m_skelAnim = gameObject.GetComponent <SkeletonAnimation>(); m_skelAnim.skeletonDataAsset = m_skeltonDataAsset; //m_skelAnim.initialSkinName = "normal"; }
public void CreateSpineObject() { // 1.Spine/Skeletonのmaterialを生成 Material material = new Material(Shader.Find("Spine/Skeleton")); material.mainTexture = texture; // 2.AtlasAssetを生成して、1のmaterialを紐づける AtlasAsset atlasAsset = AtlasAsset.CreateInstance <AtlasAsset> (); atlasAsset.atlasFile = atlasText; atlasAsset.materials = new Material[1]; atlasAsset.materials [0] = material; // 3.SkeletonDataAssetを生成して、初期データを投入する SkeletonDataAsset dataAsset = SkeletonDataAsset.CreateInstance <SkeletonDataAsset> (); dataAsset.atlasAssets = new AtlasAsset[1]; dataAsset.atlasAssets [0] = atlasAsset; dataAsset.skeletonJSON = jsonText; dataAsset.fromAnimation = new string[0]; dataAsset.toAnimation = new string[0]; dataAsset.duration = new float[0]; dataAsset.defaultMix = 0.2f; dataAsset.scale = 1.0f; // 4.実際にUnityに配置するGameObjectを生成して、SkeletonAnimationをadd GameObject obj = new GameObject("SpineObject"); SkeletonAnimation anim = obj.AddComponent <SkeletonAnimation> (); MeshRenderer meshRenderer = obj.GetComponent <MeshRenderer>(); meshRenderer.sortingLayerName = "spine"; meshRenderer.sortingOrder = 0; // 5.SkeletonAnimationにSkeletonDataAssetを紐付け、skinName、reset(),animationNameを設定する。 anim.skeletonDataAsset = dataAsset; // Reset()前に呼び出す必要あり。後に呼ぶとskinデータが反映されない anim.initialSkinName = "goblin"; // Reset()時にDataAssetからAnimationデータを読みだして格納している anim.Reset(); // ループの設定はAnimation指定前じゃないと反映されない anim.loop = true; anim.AnimationName = "walk"; // アニメ終了イベントをセット anim.state.Complete += OnCompleteSpineAnim; obj.transform.SetParent(this.gameObject.transform); }
public static void GenerateAllAtlasMapping() { var files = AssetDatabase.GetAllAssetPaths().Where(p => p.EndsWith(".asset") ).ToArray(); List <int> allSprites = new List <int>(); List <string> atlasNames = new List <string>(); for (int i = 0; i < files.Length; i++) { var o = AssetDatabase.LoadAssetAtPath <AtlasAsset>(files[i]); var ti = AssetImporter.GetAtPath(files[i]); if (o != null) { var assetBundleName = ti.assetBundleName; EditorUtility.DisplayProgressBar("Processing...", "生成中... (" + i + " / " + files.Length + ")", (float)i / (float)files.Length); for (int j = 0; j < o.names.Count; j++) { allSprites.Add(o.names[j]); atlasNames.Add(assetBundleName); } } } EditorUtility.ClearProgressBar(); string atlas_path = Path.Combine(AtlasConfig.ATLAS_MAPPING_ROOT, AtlasManager.ATLAS_MAPPING_ROOT_NAME + ".asset"); //生成或者替换资源 AssetBundleMappingAsset atlas = AssetDatabase.LoadAssetAtPath <AssetBundleMappingAsset>(atlas_path); if (atlas == null) { atlas = AtlasAsset.CreateInstance <AssetBundleMappingAsset>(); AssetDatabase.CreateAsset(atlas, atlas_path); } atlas.assetNames = allSprites.ToArray(); atlas.abNames = atlasNames.ToArray(); EditorUtility.SetDirty(atlas); var import = AssetImporter.GetAtPath(atlas_path); import.assetBundleName = AtlasManager.ATLAS_MAPPING_ROOT_NAME + Common.CHECK_ASSETBUNDLE_SUFFIX; AssetDatabase.SaveAssets(); Debug.LogFormat(" save {0} count = {1} ", atlas_path, atlasNames.Count); }
public static SkeletonAnimation CreateSkeAnimFromZip(string fullZipPath) { // ====================== // 解析zip // ====================== FileInfo zipFInfo = new FileInfo(fullZipPath); DirectoryInfo zipDirInfo = zipFInfo.Directory; string spineName = Path.GetFileNameWithoutExtension(fullZipPath); ZipFile zf = new ZipFile(fullZipPath); ZipEntry jsonEntry = zf.GetEntry(spineName + ".json"); ZipEntry atlasEntry = zf.GetEntry(spineName + ".atlas"); Stream jsonStream = zf.GetInputStream(jsonEntry); Stream atlasStream = zf.GetInputStream(atlasEntry); String jsonContent = ""; string atlasContent = ""; using (StreamReader reader = new StreamReader(jsonStream)) { jsonContent = reader.ReadToEnd(); } using (StreamReader reader = new StreamReader(atlasStream)) { atlasContent = reader.ReadToEnd(); } // =================== // Atlas 文件解析 // =================== AtlasAsset atlasAsset = AtlasAsset.CreateInstance <AtlasAsset>(); atlasAsset.atlasFileContent = atlasContent; string[] atlasLines = atlasContent.Split('\n'); List <string> pageFiles = new List <string>(); for (int i = 0; i < atlasLines.Length - 1; i++) { if (atlasLines[i].Length == 0) { pageFiles.Add(atlasLines[i + 1]); } } atlasAsset.materials = new Material[pageFiles.Count]; for (int i = 0; i < pageFiles.Count; i++) { string textureKey = pageFiles[i]; string nameOnly = Path.GetFileNameWithoutExtension(textureKey); Debug.Log("贴图Key " + textureKey + " " + nameOnly); // 正确的textureKey应该是一个裸文件路径 //if (textureKey.StartsWith("/")) // textureKey = "." + textureKey; Material mat = new Material(Shader.Find("Spine/Skeleton")); mat.name = nameOnly; string fullPngPath = Path.Combine(zipDirInfo.FullName, textureKey.Replace(".png", ".jpg.mask")); if (!File.Exists(fullPngPath)) { Debug.LogError("找不到引用的png: " + textureKey); return(null); } string fullJpgPath = Path.Combine(zipDirInfo.FullName, textureKey.Replace(".png", ".jpg")); bool isSeperated = false; if (File.Exists(fullJpgPath)) { isSeperated = true; } Texture2D tex2D = null; if (isSeperated) { Bitmap colorImg = new Bitmap(fullJpgPath); Bitmap alphaImg = new Bitmap(fullPngPath); tex2D = new Texture2D(colorImg.Width, colorImg.Height, TextureFormat.ARGB32, false); for (int row = 0; row < colorImg.Height; row++) { for (int col = 0; col < colorImg.Width; col++) { System.Drawing.Color srcColor = colorImg.GetPixel(col, colorImg.Height - row - 1); float alpha = alphaImg.GetPixel(col, row).A; tex2D.SetPixel(col, row, new UnityEngine.Color(srcColor.R, srcColor.G, srcColor.B, alpha)); } } } else { Bitmap bitmap = new Bitmap(fullPngPath); MemoryStream bmpStream = new MemoryStream(); bitmap.Save(bmpStream, System.Drawing.Imaging.ImageFormat.Png); bmpStream.Seek(0, SeekOrigin.Begin); tex2D = new Texture2D(bitmap.Width, bitmap.Height, TextureFormat.ARGB32, false); tex2D.LoadImage(bmpStream.ToArray()); } tex2D.filterMode = FilterMode.Bilinear; tex2D.wrapMode = TextureWrapMode.Clamp; tex2D.Apply(); // 调试模式 - 将atlas图片存为文件 if (ToolManager.Instance.DebugMode) { File.WriteAllBytes(textureKey + ".png", tex2D.EncodeToPNG()); } mat.mainTexture = tex2D; mat.mainTexture.name = nameOnly; atlasAsset.materials[i] = mat; } // =================== // Json 文件解析 // =================== SkeletonDataAsset skelDataAsset = SkeletonDataAsset.CreateInstance <SkeletonDataAsset>(); skelDataAsset.atlasAsset = atlasAsset; skelDataAsset.jsonFileName = spineName; skelDataAsset.skeletonJsonStr = jsonContent; skelDataAsset.fromAnimation = new string[0]; skelDataAsset.toAnimation = new string[0]; skelDataAsset.duration = new float[0]; skelDataAsset.defaultMix = defaultMix; skelDataAsset.scale = defaultScale; // =================== // 实例化Spine对象 // =================== return(SpineFileReader.SpawnAnimatedSkeleton(skelDataAsset)); }
static AtlasAsset IngestSpineAtlas(TextAsset atlasText) { if (atlasText == null) { Debug.LogWarning("Atlas source cannot be null!"); return(null); } string primaryName = Path.GetFileNameWithoutExtension(atlasText.name).Replace(".atlas", ""); string assetPath = Path.GetDirectoryName(AssetDatabase.GetAssetPath(atlasText)); string atlasPath = assetPath + "/" + primaryName + "_Atlas.asset"; AtlasAsset atlasAsset = (AtlasAsset)AssetDatabase.LoadAssetAtPath(atlasPath, typeof(AtlasAsset)); List <Material> vestigialMaterials = new List <Material>(); if (atlasAsset == null) { atlasAsset = AtlasAsset.CreateInstance <AtlasAsset>(); } else { foreach (Material m in atlasAsset.materials) { vestigialMaterials.Add(m); } } atlasAsset.atlasFile = atlasText; //strip CR string atlasStr = atlasText.text; atlasStr = atlasStr.Replace("\r", ""); string[] atlasLines = atlasStr.Split('\n'); List <string> pageFiles = new List <string>(); for (int i = 0; i < atlasLines.Length - 1; i++) { if (atlasLines[i].Length == 0) { pageFiles.Add(atlasLines[i + 1]); } } atlasAsset.materials = new Material[pageFiles.Count]; for (int i = 0; i < pageFiles.Count; i++) { string texturePath = assetPath + "/" + pageFiles[i]; Texture2D texture = (Texture2D)AssetDatabase.LoadAssetAtPath(texturePath, typeof(Texture2D)); TextureImporter texImporter = (TextureImporter)TextureImporter.GetAtPath(texturePath); texImporter.textureFormat = TextureImporterFormat.AutomaticTruecolor; texImporter.mipmapEnabled = false; texImporter.alphaIsTransparency = false; texImporter.maxTextureSize = 2048; EditorUtility.SetDirty(texImporter); AssetDatabase.ImportAsset(texturePath); AssetDatabase.SaveAssets(); string pageName = Path.GetFileNameWithoutExtension(pageFiles[i]); //because this looks silly if (pageName == primaryName && pageFiles.Count == 1) { pageName = "Material"; } string materialPath = assetPath + "/" + primaryName + "_" + pageName + ".mat"; Material mat = (Material)AssetDatabase.LoadAssetAtPath(materialPath, typeof(Material)); if (mat == null) { mat = new Material(Shader.Find(defaultShader)); AssetDatabase.CreateAsset(mat, materialPath); } else { vestigialMaterials.Remove(mat); } mat.mainTexture = texture; EditorUtility.SetDirty(mat); AssetDatabase.SaveAssets(); atlasAsset.materials[i] = mat; } for (int i = 0; i < vestigialMaterials.Count; i++) { AssetDatabase.DeleteAsset(AssetDatabase.GetAssetPath(vestigialMaterials[i])); } if (AssetDatabase.GetAssetPath(atlasAsset) == "") { AssetDatabase.CreateAsset(atlasAsset, atlasPath); } else { atlasAsset.Reset(); } EditorUtility.SetDirty(atlasAsset); AssetDatabase.SaveAssets(); //iterate regions and bake marked Atlas atlas = atlasAsset.GetAtlas(); FieldInfo field = typeof(Atlas).GetField("regions", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.NonPublic); List <AtlasRegion> regions = (List <AtlasRegion>)field.GetValue(atlas); string atlasAssetPath = AssetDatabase.GetAssetPath(atlasAsset); string atlasAssetDirPath = Path.GetDirectoryName(atlasAssetPath); string bakedDirPath = Path.Combine(atlasAssetDirPath, atlasAsset.name); bool hasBakedRegions = false; for (int i = 0; i < regions.Count; i++) { AtlasRegion region = regions[i]; string bakedPrefabPath = Path.Combine(bakedDirPath, SpineEditorUtilities.GetPathSafeRegionName(region) + ".prefab").Replace("\\", "/"); GameObject prefab = (GameObject)AssetDatabase.LoadAssetAtPath(bakedPrefabPath, typeof(GameObject)); if (prefab != null) { BakeRegion(atlasAsset, region, false); hasBakedRegions = true; } } if (hasBakedRegions) { AssetDatabase.SaveAssets(); AssetDatabase.Refresh(); } return((AtlasAsset)AssetDatabase.LoadAssetAtPath(atlasPath, typeof(AtlasAsset))); }
public static void CreateAtlasAsset() { var selection = Selection.objects; string path = string.Empty; StringBuilder sb = new StringBuilder(); foreach (Object s in selection) { if (s is DefaultAsset && (path = AssetDatabase.GetAssetPath(s)) != null && Directory.Exists(path)) { var ragName = s.name.ToLower() + "_atlas.asset"; string atlas_path = Path.Combine(path, ragName); var tagName = s.name.ToLower() + "_atlas"; sb.Append("Crate atlas Asset :"); sb.Append(ragName); sb.Append("\r\n"); var allchildren = EditorUtils.getAllChildFiles(path, @"\.meta$|\.manifest$|\.DS_Store$|\.u$", null, false); int count = 0; List <int> names = new List <int>(); List <Sprite> allSprites = new List <Sprite>(); foreach (var f in allchildren) { count++; TextureImporter ti = AssetImporter.GetAtPath(f) as TextureImporter; if (ti != null) { if (ti.textureType != TextureImporterType.Sprite) { ti.textureType = TextureImporterType.Sprite; } Object[] objs = AssetDatabase.LoadAllAssetRepresentationsAtPath(f); foreach (var item in objs) { if (item is Sprite) { sb.AppendLine(item.name); names.Add(LuaHelper.StringToHash(item.name)); allSprites.Add((Sprite)item); } } ti.spritePackingTag = tagName; ti.assetBundleName = tagName + Common.CHECK_ASSETBUNDLE_SUFFIX; EditorUtility.DisplayProgressBar("Processing...", "生成中... (" + count + " / " + allchildren.Count + ")", count / allchildren.Count); } } EditorUtility.ClearProgressBar(); //生成或者替换资源 AtlasAsset atlas = AssetDatabase.LoadAssetAtPath <AtlasAsset>(atlas_path); if (atlas == null) { atlas = AtlasAsset.CreateInstance <AtlasAsset>(); AssetDatabase.CreateAsset(atlas, atlas_path); } atlas.names = names; atlas.sprites = allSprites; EditorUtility.SetDirty(atlas); var import = AssetImporter.GetAtPath(atlas_path); import.assetBundleName = Path.GetFileNameWithoutExtension(ragName) + Common.CHECK_ASSETBUNDLE_SUFFIX; sb.AppendFormat("build {0} success count = {1} ", ragName, names.Count); AssetDatabase.SaveAssets(); } } sb.AppendLine("\r\nall completed"); Debug.Log(sb.ToString()); }
static public void BatchCreateSpineData() { //string dirName = Application.dataPath + "/Arts/Spine/"; string filedirName = "Assets/Arts/Spine/"; string spineFileName = ""; //选择多个对象批量生成 UnityEngine.Object[] objects = Selection.objects; for (int iter = 0; iter < objects.Length; ++iter) { spineFileName = objects[iter].name; string path = filedirName + spineFileName + "/" + spineFileName; string textureName = path + ".png"; string jsonFileName = path + ".json.txt"; string atlasFileName = path + ".atlas.txt"; Material mat; ///1、 创建材质,并指贴图和shader和设置图片格式 { Shader shader = Shader.Find("Spine/FadeInOut"); //默认的shader,这个可以修改 mat = new Material(shader); Texture tex = AssetDatabase.LoadAssetAtPath(textureName, typeof(Texture)) as Texture; TextureImporter textureImporter = AssetImporter.GetAtPath(textureName) as TextureImporter; textureImporter.textureType = TextureImporterType.Advanced; textureImporter.mipmapEnabled = false; textureImporter.textureFormat = TextureImporterFormat.AutomaticTruecolor; mat.SetTexture("_MainTex", tex); AssetDatabase.CreateAsset(mat, path + ".mat"); AssetDatabase.SaveAssets(); } ///2、 创建atlas,并指xx AtlasAsset m_AtlasAsset = AtlasAsset.CreateInstance <AtlasAsset>(); AssetDatabase.CreateAsset(m_AtlasAsset, path + ".asset"); Selection.activeObject = m_AtlasAsset; TextAsset textAsset = AssetDatabase.LoadAssetAtPath(atlasFileName, typeof(TextAsset)) as TextAsset; m_AtlasAsset.atlasFile = textAsset; m_AtlasAsset.materials = new Material[1]; m_AtlasAsset.materials[0] = mat; AssetDatabase.SaveAssets(); ///3、 创建SkeletonDataAsset,并指相关 SkeletonDataAsset m_skeltonDataAsset = SkeletonDataAsset.CreateInstance <SkeletonDataAsset>(); AssetDatabase.CreateAsset(m_skeltonDataAsset, path + "_SkeletonData.asset"); Selection.activeObject = m_skeltonDataAsset; m_skeltonDataAsset.atlasAsset = m_AtlasAsset; TextAsset m_jsonAsset = AssetDatabase.LoadAssetAtPath(jsonFileName, typeof(TextAsset)) as TextAsset; m_skeltonDataAsset.skeletonJSON = m_jsonAsset; m_skeltonDataAsset.scale = 0.01f; AssetDatabase.SaveAssets(); /// 创建场景物件 GameObject gameObject = new GameObject(spineFileName, typeof(SkeletonAnimation)); EditorUtility.FocusProjectWindow(); Selection.activeObject = gameObject; SkeletonAnimation m_skelAnim = gameObject.GetComponent <SkeletonAnimation>(); m_skelAnim.skeletonDataAsset = m_skeltonDataAsset; } }
static AtlasAsset IngestSpineAtlas(TextAsset atlasText) { if (atlasText == null) { Debug.LogWarning("Atlas source cannot be null!"); return(null); } string primaryName = Path.GetFileNameWithoutExtension(atlasText.name).Replace(".atlas", ""); string assetPath = Path.GetDirectoryName(AssetDatabase.GetAssetPath(atlasText)); string atlasPath = assetPath + "/" + primaryName + "_Atlas.asset"; if (File.Exists(atlasPath)) { return((AtlasAsset)AssetDatabase.LoadAssetAtPath(atlasPath, typeof(AtlasAsset))); } AtlasAsset atlasAsset = AtlasAsset.CreateInstance <AtlasAsset>(); atlasAsset.atlasFile = atlasText; string[] atlasLines = atlasText.text.Split('\n'); List <string> pageFiles = new List <string>(); for (int i = 0; i < atlasLines.Length - 1; i++) { if (atlasLines[i].Length == 0) { pageFiles.Add(atlasLines[i + 1]); } } atlasAsset.materials = new Material[pageFiles.Count]; for (int i = 0; i < pageFiles.Count; i++) { string texturePath = assetPath + "/" + pageFiles[i]; Texture2D texture = (Texture2D)AssetDatabase.LoadAssetAtPath(texturePath, typeof(Texture2D)); TextureImporter texImporter = (TextureImporter)TextureImporter.GetAtPath(texturePath); texImporter.textureFormat = TextureImporterFormat.AutomaticTruecolor; texImporter.mipmapEnabled = false; EditorUtility.SetDirty(texImporter); AssetDatabase.ImportAsset(texturePath); AssetDatabase.SaveAssets(); string pageName = Path.GetFileNameWithoutExtension(pageFiles[i]); //because this looks silly if (pageName == primaryName && pageFiles.Count == 1) { pageName = "Material"; } string materialPath = assetPath + "/" + primaryName + "_" + pageName + ".mat"; Material mat = new Material(Shader.Find(defaultShader)); mat.mainTexture = texture; AssetDatabase.CreateAsset(mat, materialPath); AssetDatabase.SaveAssets(); atlasAsset.materials[i] = mat; } AssetDatabase.CreateAsset(atlasAsset, atlasPath); AssetDatabase.SaveAssets(); return((AtlasAsset)AssetDatabase.LoadAssetAtPath(atlasPath, typeof(AtlasAsset))); }
public static SkeletonAnimation CreateSkeAnimFromZip(string fullZipPath) { // ====================== // 解析zip // ====================== FileInfo zipFInfo = new FileInfo(fullZipPath); DirectoryInfo zipDirInfo = zipFInfo.Directory; string spineName = Path.GetFileNameWithoutExtension(fullZipPath); ZipFile zf = new ZipFile(fullZipPath); ZipEntry jsonEntry = zf.GetEntry(spineName + ".json"); ZipEntry atlasEntry = zf.GetEntry(spineName + ".atlas"); Stream jsonStream = zf.GetInputStream(jsonEntry); Stream atlasStream = zf.GetInputStream(atlasEntry); String jsonContent = ""; string atlasContent = ""; using (StreamReader reader = new StreamReader(jsonStream)) { jsonContent = reader.ReadToEnd(); } using (StreamReader reader = new StreamReader(atlasStream)) { atlasContent = reader.ReadToEnd(); } // =================== // Atlas 文件解析 // =================== AtlasAsset atlasAsset = AtlasAsset.CreateInstance <AtlasAsset>(); atlasAsset.atlasFileContent = atlasContent; string[] atlasLines = atlasContent.Split('\n'); List <string> pageFiles = new List <string>(); for (int i = 0; i < atlasLines.Length - 1; i++) { if (atlasLines[i].Length == 0) { pageFiles.Add(atlasLines[i + 1]); } } atlasAsset.materials = new Material[pageFiles.Count]; for (int i = 0; i < pageFiles.Count; i++) { string textureKey = pageFiles[i]; string nameOnly = Path.GetFileNameWithoutExtension(textureKey); Debug.Log("贴图Key " + textureKey + " " + nameOnly); // 正确的textureKey应该是一个裸文件路径 //if (textureKey.StartsWith("/")) // textureKey = "." + textureKey; Material mat = new Material(Shader.Find("Spine/Skeleton")); mat.name = nameOnly; string fullPngPath = Path.Combine(zipDirInfo.FullName, textureKey.Replace(".png", ".jpg.mask")); if (!File.Exists(fullPngPath)) { Debug.LogError(String.Format("找不到引用的png: {0} {1}", textureKey, fullPngPath)); return(null); } string fullJpgPath = Path.Combine(zipDirInfo.FullName, textureKey.Replace(".png", ".jpg")); bool isSeperated = false; if (File.Exists(fullJpgPath)) { isSeperated = true; } Texture2D tex2D = null; //int alphaCnt = 0; //int rCnt = 0; //int gCnt = 0; //int bCnt = 0; // WWW www = new WWW(); if (isSeperated) { Bitmap colorImg = new Bitmap(fullJpgPath); Bitmap alphaImg = new Bitmap(fullPngPath); //int imageWidth = colorImg.Width; //int imageHeight = colorImg.Height; //Bitmap combineImg = new Bitmap(imageWidth, imageHeight, colorImg.PixelFormat); //Rectangle rect = new Rectangle(0, 0, imageWidth, imageHeight); //BitmapData colorData = colorImg.LockBits(rect, ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb); //BitmapData alphaData = alphaImg.LockBits(rect, ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb); //BitmapData combineData = combineImg.LockBits(rect, ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb); //Debug.Log(colorData.Stride + " / " + imageWidth); //int byteCnt = Math.Abs(colorData.Stride) * imageHeight; //byte[] colorBytes = new byte[byteCnt]; //byte[] alphaBytes = new byte[byteCnt]; //System.Runtime.InteropServices.Marshal.Copy(colorData.Scan0, colorBytes, 0, byteCnt); //System.Runtime.InteropServices.Marshal.Copy(alphaData.Scan0, alphaBytes, 0, byteCnt); //for (int counter = 0; counter < colorBytes.Length; counter += 4) //{ // colorBytes[counter+3] = 0; // if (counter < 300) // Debug.Log(alphaBytes[counter]); //} //System.Runtime.InteropServices.Marshal.Copy(colorBytes, 0, combineData.Scan0, byteCnt); //colorImg.UnlockBits(colorData); //alphaImg.UnlockBits(alphaData); //combineImg.UnlockBits(combineData); tex2D = new Texture2D(colorImg.Width, colorImg.Height, TextureFormat.ARGB32, false); System.Drawing.Color srcColor; System.Drawing.Color alpColor; int alpha; UnityEngine.Color finalColor; // 最大瓶颈在这个 for 循环 for (int row = 0; row < colorImg.Height; row++) { for (int col = 0; col < colorImg.Width; col++) { srcColor = colorImg.GetPixel(col, colorImg.Height - row - 1); alpColor = alphaImg.GetPixel(col, colorImg.Height - row - 1); alpha = alpColor.R; // System.Drawing.Color color = combineImg.GetPixel(col, colorImg.Height - row - 1); // NOTE Bitmap是0-255,Texture是0-1 finalColor.r = srcColor.R / 255f; finalColor.g = srcColor.G / 255f; finalColor.b = srcColor.B / 255f; finalColor.a = alpha / 255f; tex2D.SetPixel(col, row, finalColor); // tex2D.SetPixel(col, row, new UnityEngine.Color(color.R/255f, color.G/255f, color.B/255f, color.A/255f)); } } } else { Bitmap bitmap = new Bitmap(fullPngPath); MemoryStream bmpStream = new MemoryStream(); bitmap.Save(bmpStream, System.Drawing.Imaging.ImageFormat.Png); bmpStream.Seek(0, SeekOrigin.Begin); tex2D = new Texture2D(bitmap.Width, bitmap.Height, TextureFormat.ARGB32, false); tex2D.LoadImage(bmpStream.ToArray()); } tex2D.filterMode = FilterMode.Bilinear; tex2D.wrapMode = TextureWrapMode.Clamp; tex2D.Apply(); // 调试模式 - 将atlas图片存为文件 if (ToolManager.Instance.DebugMode) { File.WriteAllBytes(textureKey + ".png", tex2D.EncodeToPNG()); } mat.mainTexture = tex2D; mat.mainTexture.name = nameOnly; atlasAsset.materials[i] = mat; } // =================== // Json 文件解析 // =================== SkeletonDataAsset skelDataAsset = SkeletonDataAsset.CreateInstance <SkeletonDataAsset>(); skelDataAsset.atlasAsset = atlasAsset; skelDataAsset.jsonFileName = spineName; skelDataAsset.skeletonJsonStr = jsonContent; skelDataAsset.fromAnimation = new string[0]; skelDataAsset.toAnimation = new string[0]; skelDataAsset.duration = new float[0]; skelDataAsset.defaultMix = defaultMix; skelDataAsset.scale = defaultScale; // =================== // 实例化Spine对象 // =================== return(SpineFileReader.SpawnAnimatedSkeleton(skelDataAsset)); }
// 读取Atlas文件 public static AtlasAsset IngestSpineAtlas(string atlasFilePath) { string primaryName = Path.GetFileNameWithoutExtension(atlasFilePath); string assetPath = Path.GetDirectoryName(atlasFilePath); AtlasAsset atlasAsset = AtlasAsset.CreateInstance <AtlasAsset>(); // atlasAsset.atlasFile = atlasText; atlasAsset.atlasFileContent = File.ReadAllText(atlasFilePath); string atlasTextContent = File.ReadAllText(atlasFilePath); string[] atlasLines = atlasTextContent.Split('\n'); List <string> pageFiles = new List <string>(); for (int i = 0; i < atlasLines.Length - 1; i++) { if (atlasLines[i].Length == 0) { pageFiles.Add(atlasLines[i + 1]); } } atlasAsset.materials = new Material[pageFiles.Count]; for (int i = 0; i < pageFiles.Count; i++) { string texturePath = assetPath + "/" + pageFiles[i]; Material mat = new Material(Shader.Find("Spine/Skeleton")); // TODO 异步加载Texture // Texture2D texture = null; if (texturePath.StartsWith("/")) { texturePath = "." + texturePath; } Debug.Log("贴图路径 " + texturePath); Bitmap bitmap = new Bitmap(texturePath); Texture2D tex2D = new Texture2D(bitmap.Width, bitmap.Height, TextureFormat.ARGB32, false); tex2D.name = Path.GetFileNameWithoutExtension(texturePath); int pixelCnt = 0; for (int row = 0; row < bitmap.Height; row++) { for (int col = 0; col < bitmap.Width; col++) { System.Drawing.Color srcColor = bitmap.GetPixel(col, bitmap.Height - row - 1); tex2D.SetPixel(col, row, new UnityEngine.Color(srcColor.R, srcColor.G, srcColor.B, srcColor.A)); pixelCnt++; } } tex2D.filterMode = FilterMode.Bilinear; tex2D.wrapMode = TextureWrapMode.Clamp; tex2D.Apply(); Debug.Log("拷贝像素 " + pixelCnt); mat.mainTexture = tex2D; atlasAsset.materials[i] = mat; } return(atlasAsset); }