PageRenderTime 57ms CodeModel.GetById 17ms RepoModel.GetById 13ms app.codeStats 0ms

/Assets/Spine/Runtime/spine-unity/Asset Types/SpineAtlasAsset.cs

https://gitlab.com/hoangduy09100/falling-box
C# | 245 lines | 169 code | 34 blank | 42 comment | 38 complexity | 0a60e5fc06db8a90338d3beddb475cb8 MD5 | raw file
  1. /******************************************************************************
  2. * Spine Runtimes License Agreement
  3. * Last updated January 1, 2020. Replaces all prior versions.
  4. *
  5. * Copyright (c) 2013-2020, Esoteric Software LLC
  6. *
  7. * Integration of the Spine Runtimes into software or otherwise creating
  8. * derivative works of the Spine Runtimes is permitted under the terms and
  9. * conditions of Section 2 of the Spine Editor License Agreement:
  10. * http://esotericsoftware.com/spine-editor-license
  11. *
  12. * Otherwise, it is permitted to integrate the Spine Runtimes into software
  13. * or otherwise create derivative works of the Spine Runtimes (collectively,
  14. * "Products"), provided that each user of the Products must obtain their own
  15. * Spine Editor license and redistribution of the Products in any form must
  16. * include this license and copyright notice.
  17. *
  18. * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
  19. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  20. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  21. * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
  22. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  23. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
  24. * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
  25. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  26. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  27. * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  28. *****************************************************************************/
  29. using System;
  30. using System.Collections.Generic;
  31. using System.IO;
  32. using UnityEngine;
  33. using Spine;
  34. namespace Spine.Unity {
  35. /// <summary>Loads and stores a Spine atlas and list of materials.</summary>
  36. [CreateAssetMenu(fileName = "New Spine Atlas Asset", menuName = "Spine/Spine Atlas Asset")]
  37. public class SpineAtlasAsset : AtlasAssetBase {
  38. public TextAsset atlasFile;
  39. public Material[] materials;
  40. protected Atlas atlas;
  41. public override bool IsLoaded { get { return this.atlas != null; } }
  42. public override IEnumerable<Material> Materials { get { return materials; } }
  43. public override int MaterialCount { get { return materials == null ? 0 : materials.Length; } }
  44. public override Material PrimaryMaterial { get { return materials[0]; } }
  45. #region Runtime Instantiation
  46. /// <summary>
  47. /// Creates a runtime AtlasAsset</summary>
  48. public static SpineAtlasAsset CreateRuntimeInstance (TextAsset atlasText, Material[] materials, bool initialize) {
  49. SpineAtlasAsset atlasAsset = ScriptableObject.CreateInstance<SpineAtlasAsset>();
  50. atlasAsset.Reset();
  51. atlasAsset.atlasFile = atlasText;
  52. atlasAsset.materials = materials;
  53. if (initialize)
  54. atlasAsset.GetAtlas();
  55. return atlasAsset;
  56. }
  57. /// <summary>
  58. /// Creates a runtime AtlasAsset. Only providing the textures is slower because it has to search for atlas page matches. <seealso cref="Spine.Unity.SpineAtlasAsset.CreateRuntimeInstance(TextAsset, Material[], bool)"/></summary>
  59. public static SpineAtlasAsset CreateRuntimeInstance (TextAsset atlasText, Texture2D[] textures, Material materialPropertySource, bool initialize) {
  60. // Get atlas page names.
  61. string atlasString = atlasText.text;
  62. atlasString = atlasString.Replace("\r", "");
  63. string[] atlasLines = atlasString.Split('\n');
  64. var pages = new List<string>();
  65. for (int i = 0; i < atlasLines.Length - 1; i++) {
  66. if (atlasLines[i].Trim().Length == 0)
  67. pages.Add(atlasLines[i + 1].Trim().Replace(".png", ""));
  68. }
  69. // Populate Materials[] by matching texture names with page names.
  70. var materials = new Material[pages.Count];
  71. for (int i = 0, n = pages.Count; i < n; i++) {
  72. Material mat = null;
  73. // Search for a match.
  74. string pageName = pages[i];
  75. for (int j = 0, m = textures.Length; j < m; j++) {
  76. if (string.Equals(pageName, textures[j].name, System.StringComparison.OrdinalIgnoreCase)) {
  77. // Match found.
  78. mat = new Material(materialPropertySource);
  79. mat.mainTexture = textures[j];
  80. break;
  81. }
  82. }
  83. if (mat != null)
  84. materials[i] = mat;
  85. else
  86. throw new ArgumentException("Could not find matching atlas page in the texture array.");
  87. }
  88. // Create AtlasAsset normally
  89. return CreateRuntimeInstance(atlasText, materials, initialize);
  90. }
  91. /// <summary>
  92. /// Creates a runtime AtlasAsset. Only providing the textures is slower because it has to search for atlas page matches. <seealso cref="Spine.Unity.AtlasAssetBase.CreateRuntimeInstance(TextAsset, Material[], bool)"/></summary>
  93. public static SpineAtlasAsset CreateRuntimeInstance (TextAsset atlasText, Texture2D[] textures, Shader shader, bool initialize) {
  94. if (shader == null)
  95. shader = Shader.Find("Spine/Skeleton");
  96. Material materialProperySource = new Material(shader);
  97. var oa = CreateRuntimeInstance(atlasText, textures, materialProperySource, initialize);
  98. return oa;
  99. }
  100. #endregion
  101. void Reset () {
  102. Clear();
  103. }
  104. public override void Clear () {
  105. atlas = null;
  106. }
  107. /// <returns>The atlas or null if it could not be loaded.</returns>
  108. public override Atlas GetAtlas () {
  109. if (atlasFile == null) {
  110. Debug.LogError("Atlas file not set for atlas asset: " + name, this);
  111. Clear();
  112. return null;
  113. }
  114. if (materials == null || materials.Length == 0) {
  115. Debug.LogError("Materials not set for atlas asset: " + name, this);
  116. Clear();
  117. return null;
  118. }
  119. if (atlas != null) return atlas;
  120. try {
  121. atlas = new Atlas(new StringReader(atlasFile.text), "", new MaterialsTextureLoader(this));
  122. atlas.FlipV();
  123. return atlas;
  124. } catch (Exception ex) {
  125. Debug.LogError("Error reading atlas file for atlas asset: " + name + "\n" + ex.Message + "\n" + ex.StackTrace, this);
  126. return null;
  127. }
  128. }
  129. public Mesh GenerateMesh (string name, Mesh mesh, out Material material, float scale = 0.01f) {
  130. AtlasRegion region = atlas.FindRegion(name);
  131. material = null;
  132. if (region != null) {
  133. if (mesh == null) {
  134. mesh = new Mesh();
  135. mesh.name = name;
  136. }
  137. Vector3[] verts = new Vector3[4];
  138. Vector2[] uvs = new Vector2[4];
  139. Color[] colors = { Color.white, Color.white, Color.white, Color.white };
  140. int[] triangles = { 0, 1, 2, 2, 3, 0 };
  141. float left, right, top, bottom;
  142. left = region.width / -2f;
  143. right = left * -1f;
  144. top = region.height / 2f;
  145. bottom = top * -1;
  146. verts[0] = new Vector3(left, bottom, 0) * scale;
  147. verts[1] = new Vector3(left, top, 0) * scale;
  148. verts[2] = new Vector3(right, top, 0) * scale;
  149. verts[3] = new Vector3(right, bottom, 0) * scale;
  150. float u, v, u2, v2;
  151. u = region.u;
  152. v = region.v;
  153. u2 = region.u2;
  154. v2 = region.v2;
  155. if (!region.rotate) {
  156. uvs[0] = new Vector2(u, v2);
  157. uvs[1] = new Vector2(u, v);
  158. uvs[2] = new Vector2(u2, v);
  159. uvs[3] = new Vector2(u2, v2);
  160. } else {
  161. uvs[0] = new Vector2(u2, v2);
  162. uvs[1] = new Vector2(u, v2);
  163. uvs[2] = new Vector2(u, v);
  164. uvs[3] = new Vector2(u2, v);
  165. }
  166. mesh.triangles = new int[0];
  167. mesh.vertices = verts;
  168. mesh.uv = uvs;
  169. mesh.colors = colors;
  170. mesh.triangles = triangles;
  171. mesh.RecalculateNormals();
  172. mesh.RecalculateBounds();
  173. material = (Material)region.page.rendererObject;
  174. } else {
  175. mesh = null;
  176. }
  177. return mesh;
  178. }
  179. }
  180. public class MaterialsTextureLoader : TextureLoader {
  181. SpineAtlasAsset atlasAsset;
  182. public MaterialsTextureLoader (SpineAtlasAsset atlasAsset) {
  183. this.atlasAsset = atlasAsset;
  184. }
  185. public void Load (AtlasPage page, string path) {
  186. String name = Path.GetFileNameWithoutExtension(path);
  187. Material material = null;
  188. foreach (Material other in atlasAsset.materials) {
  189. if (other.mainTexture == null) {
  190. Debug.LogError("Material is missing texture: " + other.name, other);
  191. return;
  192. }
  193. if (other.mainTexture.name == name) {
  194. material = other;
  195. break;
  196. }
  197. }
  198. if (material == null) {
  199. Debug.LogError("Material with texture name \"" + name + "\" not found for atlas asset: " + atlasAsset.name, atlasAsset);
  200. return;
  201. }
  202. page.rendererObject = material;
  203. // Very old atlas files expected the texture's actual size to be used at runtime.
  204. if (page.width == 0 || page.height == 0) {
  205. page.width = material.mainTexture.width;
  206. page.height = material.mainTexture.height;
  207. }
  208. }
  209. public void Unload (object texture) { }
  210. }
  211. }