源战役客户端
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

893 lines
34 KiB

  1. /******************************************************************************
  2. * Spine Runtimes Software License v2.5
  3. *
  4. * Copyright (c) 2013-2016, Esoteric Software
  5. * All rights reserved.
  6. *
  7. * You are granted a perpetual, non-exclusive, non-sublicensable, and
  8. * non-transferable license to use, install, execute, and perform the Spine
  9. * Runtimes software and derivative works solely for personal or internal
  10. * use. Without the written permission of Esoteric Software (see Section 2 of
  11. * the Spine Software License Agreement), you may not (a) modify, translate,
  12. * adapt, or develop new applications using the Spine Runtimes or otherwise
  13. * create derivative works or improvements of the Spine Runtimes or (b) remove,
  14. * delete, alter, or obscure any trademarks or any copyright, trademark, patent,
  15. * or other intellectual property or proprietary rights notices on or in the
  16. * Software, including any copy thereof. Redistributions in binary or source
  17. * form must include this license and terms.
  18. *
  19. * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
  20. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  21. * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
  22. * EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  23. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  24. * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS INTERRUPTION, OR LOSS OF
  25. * USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
  26. * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  27. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  28. * POSSIBILITY OF SUCH DAMAGE.
  29. *****************************************************************************/
  30. #if (UNITY_5 || UNITY_5_3_OR_NEWER || UNITY_WSA || UNITY_WP8 || UNITY_WP8_1)
  31. #define IS_UNITY
  32. #endif
  33. using System;
  34. using System.IO;
  35. using System.Collections.Generic;
  36. #if WINDOWS_STOREAPP
  37. using System.Threading.Tasks;
  38. using Windows.Storage;
  39. #endif
  40. namespace Spine {
  41. public class SkeletonBinary {
  42. public const int BONE_ROTATE = 0;
  43. public const int BONE_TRANSLATE = 1;
  44. public const int BONE_SCALE = 2;
  45. public const int BONE_SHEAR = 3;
  46. public const int SLOT_ATTACHMENT = 0;
  47. public const int SLOT_COLOR = 1;
  48. public const int SLOT_TWO_COLOR = 2;
  49. public const int PATH_POSITION = 0;
  50. public const int PATH_SPACING = 1;
  51. public const int PATH_MIX = 2;
  52. public const int CURVE_LINEAR = 0;
  53. public const int CURVE_STEPPED = 1;
  54. public const int CURVE_BEZIER = 2;
  55. public float Scale { get; set; }
  56. private AttachmentLoader attachmentLoader;
  57. private byte[] buffer = new byte[32];
  58. private List<SkeletonJson.LinkedMesh> linkedMeshes = new List<SkeletonJson.LinkedMesh>();
  59. public SkeletonBinary (params Atlas[] atlasArray)
  60. : this(new AtlasAttachmentLoader(atlasArray)) {
  61. }
  62. public SkeletonBinary (AttachmentLoader attachmentLoader) {
  63. if (attachmentLoader == null) throw new ArgumentNullException("attachmentLoader");
  64. this.attachmentLoader = attachmentLoader;
  65. Scale = 1;
  66. }
  67. #if !ISUNITY && WINDOWS_STOREAPP
  68. private async Task<SkeletonData> ReadFile(string path) {
  69. var folder = Windows.ApplicationModel.Package.Current.InstalledLocation;
  70. using (var input = new BufferedStream(await folder.GetFileAsync(path).AsTask().ConfigureAwait(false))) {
  71. SkeletonData skeletonData = ReadSkeletonData(input);
  72. skeletonData.Name = Path.GetFileNameWithoutExtension(path);
  73. return skeletonData;
  74. }
  75. }
  76. public SkeletonData ReadSkeletonData (String path) {
  77. return this.ReadFile(path).Result;
  78. }
  79. #else
  80. public SkeletonData ReadSkeletonData (String path) {
  81. #if WINDOWS_PHONE
  82. using (var input = new BufferedStream(Microsoft.Xna.Framework.TitleContainer.OpenStream(path))) {
  83. #else
  84. using (var input = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read)) {
  85. #endif
  86. SkeletonData skeletonData = ReadSkeletonData(input);
  87. skeletonData.name = Path.GetFileNameWithoutExtension(path);
  88. return skeletonData;
  89. }
  90. }
  91. #endif // WINDOWS_STOREAPP
  92. public static readonly TransformMode[] TransformModeValues = {
  93. TransformMode.Normal,
  94. TransformMode.OnlyTranslation,
  95. TransformMode.NoRotationOrReflection,
  96. TransformMode.NoScale,
  97. TransformMode.NoScaleOrReflection
  98. };
  99. /// <summary>Returns the version string of binary skeleton data.</summary>
  100. public static string GetVersionString (Stream input) {
  101. if (input == null) throw new ArgumentNullException("input");
  102. try {
  103. // Hash.
  104. int byteCount = ReadVarint(input, true);
  105. if (byteCount > 1) input.Position += byteCount - 1;
  106. // Version.
  107. byteCount = ReadVarint(input, true);
  108. if (byteCount > 1) {
  109. byteCount--;
  110. var buffer = new byte[byteCount];
  111. ReadFully(input, buffer, 0, byteCount);
  112. return System.Text.Encoding.UTF8.GetString(buffer, 0, byteCount);
  113. }
  114. throw new ArgumentException("Stream does not contain a valid binary Skeleton Data.", "input");
  115. } catch (Exception e) {
  116. throw new ArgumentException("Stream does not contain a valid binary Skeleton Data.\n" + e, "input");
  117. }
  118. }
  119. public SkeletonData ReadSkeletonData (Stream input) {
  120. if (input == null) throw new ArgumentNullException("input");
  121. float scale = Scale;
  122. var skeletonData = new SkeletonData();
  123. skeletonData.hash = ReadString(input);
  124. if (skeletonData.hash.Length == 0) skeletonData.hash = null;
  125. skeletonData.version = ReadString(input);
  126. if (skeletonData.version.Length == 0) skeletonData.version = null;
  127. skeletonData.width = ReadFloat(input);
  128. skeletonData.height = ReadFloat(input);
  129. bool nonessential = ReadBoolean(input);
  130. if (nonessential) {
  131. skeletonData.fps = ReadFloat(input);
  132. skeletonData.imagesPath = ReadString(input);
  133. if (skeletonData.imagesPath.Length == 0) skeletonData.imagesPath = null;
  134. }
  135. // Bones.
  136. for (int i = 0, n = ReadVarint(input, true); i < n; i++) {
  137. String name = ReadString(input);
  138. BoneData parent = i == 0 ? null : skeletonData.bones.Items[ReadVarint(input, true)];
  139. BoneData data = new BoneData(i, name, parent);
  140. data.rotation = ReadFloat(input);
  141. data.x = ReadFloat(input) * scale;
  142. data.y = ReadFloat(input) * scale;
  143. data.scaleX = ReadFloat(input);
  144. data.scaleY = ReadFloat(input);
  145. data.shearX = ReadFloat(input);
  146. data.shearY = ReadFloat(input);
  147. data.length = ReadFloat(input) * scale;
  148. data.transformMode = TransformModeValues[ReadVarint(input, true)];
  149. if (nonessential) ReadInt(input); // Skip bone color.
  150. skeletonData.bones.Add(data);
  151. }
  152. // Slots.
  153. for (int i = 0, n = ReadVarint(input, true); i < n; i++) {
  154. String slotName = ReadString(input);
  155. BoneData boneData = skeletonData.bones.Items[ReadVarint(input, true)];
  156. SlotData slotData = new SlotData(i, slotName, boneData);
  157. int color = ReadInt(input);
  158. slotData.r = ((color & 0xff000000) >> 24) / 255f;
  159. slotData.g = ((color & 0x00ff0000) >> 16) / 255f;
  160. slotData.b = ((color & 0x0000ff00) >> 8) / 255f;
  161. slotData.a = ((color & 0x000000ff)) / 255f;
  162. int darkColor = ReadInt(input); // 0x00rrggbb
  163. if (darkColor != -1) {
  164. slotData.hasSecondColor = true;
  165. slotData.r2 = ((darkColor & 0x00ff0000) >> 16) / 255f;
  166. slotData.g2 = ((darkColor & 0x0000ff00) >> 8) / 255f;
  167. slotData.b2 = ((darkColor & 0x000000ff)) / 255f;
  168. }
  169. slotData.attachmentName = ReadString(input);
  170. slotData.blendMode = (BlendMode)ReadVarint(input, true);
  171. skeletonData.slots.Add(slotData);
  172. }
  173. // IK constraints.
  174. for (int i = 0, n = ReadVarint(input, true); i < n; i++) {
  175. IkConstraintData data = new IkConstraintData(ReadString(input));
  176. data.order = ReadVarint(input, true);
  177. for (int ii = 0, nn = ReadVarint(input, true); ii < nn; ii++)
  178. data.bones.Add(skeletonData.bones.Items[ReadVarint(input, true)]);
  179. data.target = skeletonData.bones.Items[ReadVarint(input, true)];
  180. data.mix = ReadFloat(input);
  181. data.bendDirection = ReadSByte(input);
  182. skeletonData.ikConstraints.Add(data);
  183. }
  184. // Transform constraints.
  185. for (int i = 0, n = ReadVarint(input, true); i < n; i++) {
  186. TransformConstraintData data = new TransformConstraintData(ReadString(input));
  187. data.order = ReadVarint(input, true);
  188. for (int ii = 0, nn = ReadVarint(input, true); ii < nn; ii++)
  189. data.bones.Add(skeletonData.bones.Items[ReadVarint(input, true)]);
  190. data.target = skeletonData.bones.Items[ReadVarint(input, true)];
  191. data.local = ReadBoolean(input);
  192. data.relative = ReadBoolean(input);
  193. data.offsetRotation = ReadFloat(input);
  194. data.offsetX = ReadFloat(input) * scale;
  195. data.offsetY = ReadFloat(input) * scale;
  196. data.offsetScaleX = ReadFloat(input);
  197. data.offsetScaleY = ReadFloat(input);
  198. data.offsetShearY = ReadFloat(input);
  199. data.rotateMix = ReadFloat(input);
  200. data.translateMix = ReadFloat(input);
  201. data.scaleMix = ReadFloat(input);
  202. data.shearMix = ReadFloat(input);
  203. skeletonData.transformConstraints.Add(data);
  204. }
  205. // Path constraints
  206. for (int i = 0, n = ReadVarint(input, true); i < n; i++) {
  207. PathConstraintData data = new PathConstraintData(ReadString(input));
  208. data.order = ReadVarint(input, true);
  209. for (int ii = 0, nn = ReadVarint(input, true); ii < nn; ii++)
  210. data.bones.Add(skeletonData.bones.Items[ReadVarint(input, true)]);
  211. data.target = skeletonData.slots.Items[ReadVarint(input, true)];
  212. data.positionMode = (PositionMode)Enum.GetValues(typeof(PositionMode)).GetValue(ReadVarint(input, true));
  213. data.spacingMode = (SpacingMode)Enum.GetValues(typeof(SpacingMode)).GetValue(ReadVarint(input, true));
  214. data.rotateMode = (RotateMode)Enum.GetValues(typeof(RotateMode)).GetValue(ReadVarint(input, true));
  215. data.offsetRotation = ReadFloat(input);
  216. data.position = ReadFloat(input);
  217. if (data.positionMode == PositionMode.Fixed) data.position *= scale;
  218. data.spacing = ReadFloat(input);
  219. if (data.spacingMode == SpacingMode.Length || data.spacingMode == SpacingMode.Fixed) data.spacing *= scale;
  220. data.rotateMix = ReadFloat(input);
  221. data.translateMix = ReadFloat(input);
  222. skeletonData.pathConstraints.Add(data);
  223. }
  224. // Default skin.
  225. Skin defaultSkin = ReadSkin(input, skeletonData, "default", nonessential);
  226. if (defaultSkin != null) {
  227. skeletonData.defaultSkin = defaultSkin;
  228. skeletonData.skins.Add(defaultSkin);
  229. }
  230. // Skins.
  231. for (int i = 0, n = ReadVarint(input, true); i < n; i++)
  232. skeletonData.skins.Add(ReadSkin(input, skeletonData, ReadString(input), nonessential));
  233. // Linked meshes.
  234. for (int i = 0, n = linkedMeshes.Count; i < n; i++) {
  235. SkeletonJson.LinkedMesh linkedMesh = linkedMeshes[i];
  236. Skin skin = linkedMesh.skin == null ? skeletonData.DefaultSkin : skeletonData.FindSkin(linkedMesh.skin);
  237. if (skin == null) throw new Exception("Skin not found: " + linkedMesh.skin);
  238. Attachment parent = skin.GetAttachment(linkedMesh.slotIndex, linkedMesh.parent);
  239. if (parent == null) throw new Exception("Parent mesh not found: " + linkedMesh.parent);
  240. linkedMesh.mesh.ParentMesh = (MeshAttachment)parent;
  241. linkedMesh.mesh.UpdateUVs();
  242. }
  243. linkedMeshes.Clear();
  244. // Events.
  245. for (int i = 0, n = ReadVarint(input, true); i < n; i++) {
  246. EventData data = new EventData(ReadString(input));
  247. data.Int = ReadVarint(input, false);
  248. data.Float = ReadFloat(input);
  249. data.String = ReadString(input);
  250. skeletonData.events.Add(data);
  251. }
  252. // Animations.
  253. for (int i = 0, n = ReadVarint(input, true); i < n; i++)
  254. ReadAnimation(ReadString(input), input, skeletonData);
  255. skeletonData.bones.TrimExcess();
  256. skeletonData.slots.TrimExcess();
  257. skeletonData.skins.TrimExcess();
  258. skeletonData.events.TrimExcess();
  259. skeletonData.animations.TrimExcess();
  260. skeletonData.ikConstraints.TrimExcess();
  261. skeletonData.pathConstraints.TrimExcess();
  262. return skeletonData;
  263. }
  264. /// <returns>May be null.</returns>
  265. private Skin ReadSkin (Stream input, SkeletonData skeletonData, String skinName, bool nonessential) {
  266. int slotCount = ReadVarint(input, true);
  267. if (slotCount == 0) return null;
  268. Skin skin = new Skin(skinName);
  269. for (int i = 0; i < slotCount; i++) {
  270. int slotIndex = ReadVarint(input, true);
  271. for (int ii = 0, nn = ReadVarint(input, true); ii < nn; ii++) {
  272. String name = ReadString(input);
  273. Attachment attachment = ReadAttachment(input, skeletonData, skin, slotIndex, name, nonessential);
  274. if (attachment != null) skin.AddAttachment(slotIndex, name, attachment);
  275. }
  276. }
  277. return skin;
  278. }
  279. private Attachment ReadAttachment (Stream input, SkeletonData skeletonData, Skin skin, int slotIndex, String attachmentName, bool nonessential) {
  280. float scale = Scale;
  281. String name = ReadString(input);
  282. if (name == null) name = attachmentName;
  283. AttachmentType type = (AttachmentType)input.ReadByte();
  284. switch (type) {
  285. case AttachmentType.Region: {
  286. String path = ReadString(input);
  287. float rotation = ReadFloat(input);
  288. float x = ReadFloat(input);
  289. float y = ReadFloat(input);
  290. float scaleX = ReadFloat(input);
  291. float scaleY = ReadFloat(input);
  292. float width = ReadFloat(input);
  293. float height = ReadFloat(input);
  294. int color = ReadInt(input);
  295. if (path == null) path = name;
  296. RegionAttachment region = attachmentLoader.NewRegionAttachment(skin, name, path);
  297. if (region == null) return null;
  298. region.Path = path;
  299. region.x = x * scale;
  300. region.y = y * scale;
  301. region.scaleX = scaleX;
  302. region.scaleY = scaleY;
  303. region.rotation = rotation;
  304. region.width = width * scale;
  305. region.height = height * scale;
  306. region.r = ((color & 0xff000000) >> 24) / 255f;
  307. region.g = ((color & 0x00ff0000) >> 16) / 255f;
  308. region.b = ((color & 0x0000ff00) >> 8) / 255f;
  309. region.a = ((color & 0x000000ff)) / 255f;
  310. region.UpdateOffset();
  311. return region;
  312. }
  313. case AttachmentType.Boundingbox: {
  314. int vertexCount = ReadVarint(input, true);
  315. Vertices vertices = ReadVertices(input, vertexCount);
  316. if (nonessential) ReadInt(input); //int color = nonessential ? ReadInt(input) : 0; // Avoid unused local warning.
  317. BoundingBoxAttachment box = attachmentLoader.NewBoundingBoxAttachment(skin, name);
  318. if (box == null) return null;
  319. box.worldVerticesLength = vertexCount << 1;
  320. box.vertices = vertices.vertices;
  321. box.bones = vertices.bones;
  322. return box;
  323. }
  324. case AttachmentType.Mesh: {
  325. String path = ReadString(input);
  326. int color = ReadInt(input);
  327. int vertexCount = ReadVarint(input, true);
  328. float[] uvs = ReadFloatArray(input, vertexCount << 1, 1);
  329. int[] triangles = ReadShortArray(input);
  330. Vertices vertices = ReadVertices(input, vertexCount);
  331. int hullLength = ReadVarint(input, true);
  332. int[] edges = null;
  333. float width = 0, height = 0;
  334. if (nonessential) {
  335. edges = ReadShortArray(input);
  336. width = ReadFloat(input);
  337. height = ReadFloat(input);
  338. }
  339. if (path == null) path = name;
  340. MeshAttachment mesh = attachmentLoader.NewMeshAttachment(skin, name, path);
  341. if (mesh == null) return null;
  342. mesh.Path = path;
  343. mesh.r = ((color & 0xff000000) >> 24) / 255f;
  344. mesh.g = ((color & 0x00ff0000) >> 16) / 255f;
  345. mesh.b = ((color & 0x0000ff00) >> 8) / 255f;
  346. mesh.a = ((color & 0x000000ff)) / 255f;
  347. mesh.bones = vertices.bones;
  348. mesh.vertices = vertices.vertices;
  349. mesh.WorldVerticesLength = vertexCount << 1;
  350. mesh.triangles = triangles;
  351. mesh.regionUVs = uvs;
  352. mesh.UpdateUVs();
  353. mesh.HullLength = hullLength << 1;
  354. if (nonessential) {
  355. mesh.Edges = edges;
  356. mesh.Width = width * scale;
  357. mesh.Height = height * scale;
  358. }
  359. return mesh;
  360. }
  361. case AttachmentType.Linkedmesh: {
  362. String path = ReadString(input);
  363. int color = ReadInt(input);
  364. String skinName = ReadString(input);
  365. String parent = ReadString(input);
  366. bool inheritDeform = ReadBoolean(input);
  367. float width = 0, height = 0;
  368. if (nonessential) {
  369. width = ReadFloat(input);
  370. height = ReadFloat(input);
  371. }
  372. if (path == null) path = name;
  373. MeshAttachment mesh = attachmentLoader.NewMeshAttachment(skin, name, path);
  374. if (mesh == null) return null;
  375. mesh.Path = path;
  376. mesh.r = ((color & 0xff000000) >> 24) / 255f;
  377. mesh.g = ((color & 0x00ff0000) >> 16) / 255f;
  378. mesh.b = ((color & 0x0000ff00) >> 8) / 255f;
  379. mesh.a = ((color & 0x000000ff)) / 255f;
  380. mesh.inheritDeform = inheritDeform;
  381. if (nonessential) {
  382. mesh.Width = width * scale;
  383. mesh.Height = height * scale;
  384. }
  385. linkedMeshes.Add(new SkeletonJson.LinkedMesh(mesh, skinName, slotIndex, parent));
  386. return mesh;
  387. }
  388. case AttachmentType.Path: {
  389. bool closed = ReadBoolean(input);
  390. bool constantSpeed = ReadBoolean(input);
  391. int vertexCount = ReadVarint(input, true);
  392. Vertices vertices = ReadVertices(input, vertexCount);
  393. float[] lengths = new float[vertexCount / 3];
  394. for (int i = 0, n = lengths.Length; i < n; i++)
  395. lengths[i] = ReadFloat(input) * scale;
  396. if (nonessential) ReadInt(input); //int color = nonessential ? ReadInt(input) : 0;
  397. PathAttachment path = attachmentLoader.NewPathAttachment(skin, name);
  398. if (path == null) return null;
  399. path.closed = closed;
  400. path.constantSpeed = constantSpeed;
  401. path.worldVerticesLength = vertexCount << 1;
  402. path.vertices = vertices.vertices;
  403. path.bones = vertices.bones;
  404. path.lengths = lengths;
  405. return path;
  406. }
  407. case AttachmentType.Point: {
  408. float rotation = ReadFloat(input);
  409. float x = ReadFloat(input);
  410. float y = ReadFloat(input);
  411. if (nonessential) ReadInt(input); //int color = nonessential ? ReadInt(input) : 0;
  412. PointAttachment point = attachmentLoader.NewPointAttachment(skin, name);
  413. if (point == null) return null;
  414. point.x = x * scale;
  415. point.y = y * scale;
  416. point.rotation = rotation;
  417. //if (nonessential) point.color = color;
  418. return point;
  419. }
  420. case AttachmentType.Clipping: {
  421. int endSlotIndex = ReadVarint(input, true);
  422. int vertexCount = ReadVarint(input, true);
  423. Vertices vertices = ReadVertices(input, vertexCount);
  424. if (nonessential) ReadInt(input);
  425. ClippingAttachment clip = attachmentLoader.NewClippingAttachment(skin, name);
  426. if (clip == null) return null;
  427. clip.EndSlot = skeletonData.slots.Items[endSlotIndex];
  428. clip.worldVerticesLength = vertexCount << 1;
  429. clip.vertices = vertices.vertices;
  430. clip.bones = vertices.bones;
  431. return clip;
  432. }
  433. }
  434. return null;
  435. }
  436. private Vertices ReadVertices (Stream input, int vertexCount) {
  437. float scale = Scale;
  438. int verticesLength = vertexCount << 1;
  439. Vertices vertices = new Vertices();
  440. if(!ReadBoolean(input)) {
  441. vertices.vertices = ReadFloatArray(input, verticesLength, scale);
  442. return vertices;
  443. }
  444. var weights = new ExposedList<float>(verticesLength * 3 * 3);
  445. var bonesArray = new ExposedList<int>(verticesLength * 3);
  446. for (int i = 0; i < vertexCount; i++) {
  447. int boneCount = ReadVarint(input, true);
  448. bonesArray.Add(boneCount);
  449. for (int ii = 0; ii < boneCount; ii++) {
  450. bonesArray.Add(ReadVarint(input, true));
  451. weights.Add(ReadFloat(input) * scale);
  452. weights.Add(ReadFloat(input) * scale);
  453. weights.Add(ReadFloat(input));
  454. }
  455. }
  456. vertices.vertices = weights.ToArray();
  457. vertices.bones = bonesArray.ToArray();
  458. return vertices;
  459. }
  460. private float[] ReadFloatArray (Stream input, int n, float scale) {
  461. float[] array = new float[n];
  462. if (scale == 1) {
  463. for (int i = 0; i < n; i++)
  464. array[i] = ReadFloat(input);
  465. } else {
  466. for (int i = 0; i < n; i++)
  467. array[i] = ReadFloat(input) * scale;
  468. }
  469. return array;
  470. }
  471. private int[] ReadShortArray (Stream input) {
  472. int n = ReadVarint(input, true);
  473. int[] array = new int[n];
  474. for (int i = 0; i < n; i++)
  475. array[i] = (input.ReadByte() << 8) | input.ReadByte();
  476. return array;
  477. }
  478. private void ReadAnimation (String name, Stream input, SkeletonData skeletonData) {
  479. var timelines = new ExposedList<Timeline>();
  480. float scale = Scale;
  481. float duration = 0;
  482. // Slot timelines.
  483. for (int i = 0, n = ReadVarint(input, true); i < n; i++) {
  484. int slotIndex = ReadVarint(input, true);
  485. for (int ii = 0, nn = ReadVarint(input, true); ii < nn; ii++) {
  486. int timelineType = input.ReadByte();
  487. int frameCount = ReadVarint(input, true);
  488. switch (timelineType) {
  489. case SLOT_ATTACHMENT: {
  490. AttachmentTimeline timeline = new AttachmentTimeline(frameCount);
  491. timeline.slotIndex = slotIndex;
  492. for (int frameIndex = 0; frameIndex < frameCount; frameIndex++)
  493. timeline.SetFrame(frameIndex, ReadFloat(input), ReadString(input));
  494. timelines.Add(timeline);
  495. duration = Math.Max(duration, timeline.frames[frameCount - 1]);
  496. break;
  497. }
  498. case SLOT_COLOR: {
  499. ColorTimeline timeline = new ColorTimeline(frameCount);
  500. timeline.slotIndex = slotIndex;
  501. for (int frameIndex = 0; frameIndex < frameCount; frameIndex++) {
  502. float time = ReadFloat(input);
  503. int color = ReadInt(input);
  504. float r = ((color & 0xff000000) >> 24) / 255f;
  505. float g = ((color & 0x00ff0000) >> 16) / 255f;
  506. float b = ((color & 0x0000ff00) >> 8) / 255f;
  507. float a = ((color & 0x000000ff)) / 255f;
  508. timeline.SetFrame(frameIndex, time, r, g, b, a);
  509. if (frameIndex < frameCount - 1) ReadCurve(input, frameIndex, timeline);
  510. }
  511. timelines.Add(timeline);
  512. duration = Math.Max(duration, timeline.frames[(timeline.FrameCount - 1) * ColorTimeline.ENTRIES]);
  513. break;
  514. }
  515. case SLOT_TWO_COLOR: {
  516. TwoColorTimeline timeline = new TwoColorTimeline(frameCount);
  517. timeline.slotIndex = slotIndex;
  518. for (int frameIndex = 0; frameIndex < frameCount; frameIndex++) {
  519. float time = ReadFloat(input);
  520. int color = ReadInt(input);
  521. float r = ((color & 0xff000000) >> 24) / 255f;
  522. float g = ((color & 0x00ff0000) >> 16) / 255f;
  523. float b = ((color & 0x0000ff00) >> 8) / 255f;
  524. float a = ((color & 0x000000ff)) / 255f;
  525. int color2 = ReadInt(input); // 0x00rrggbb
  526. float r2 = ((color2 & 0x00ff0000) >> 16) / 255f;
  527. float g2 = ((color2 & 0x0000ff00) >> 8) / 255f;
  528. float b2 = ((color2 & 0x000000ff)) / 255f;
  529. timeline.SetFrame(frameIndex, time, r, g, b, a, r2, g2, b2);
  530. if (frameIndex < frameCount - 1) ReadCurve(input, frameIndex, timeline);
  531. }
  532. timelines.Add(timeline);
  533. duration = Math.Max(duration, timeline.frames[(timeline.FrameCount - 1) * TwoColorTimeline.ENTRIES]);
  534. break;
  535. }
  536. }
  537. }
  538. }
  539. // Bone timelines.
  540. for (int i = 0, n = ReadVarint(input, true); i < n; i++) {
  541. int boneIndex = ReadVarint(input, true);
  542. for (int ii = 0, nn = ReadVarint(input, true); ii < nn; ii++) {
  543. int timelineType = input.ReadByte();
  544. int frameCount = ReadVarint(input, true);
  545. switch (timelineType) {
  546. case BONE_ROTATE: {
  547. RotateTimeline timeline = new RotateTimeline(frameCount);
  548. timeline.boneIndex = boneIndex;
  549. for (int frameIndex = 0; frameIndex < frameCount; frameIndex++) {
  550. timeline.SetFrame(frameIndex, ReadFloat(input), ReadFloat(input));
  551. if (frameIndex < frameCount - 1) ReadCurve(input, frameIndex, timeline);
  552. }
  553. timelines.Add(timeline);
  554. duration = Math.Max(duration, timeline.frames[(frameCount - 1) * RotateTimeline.ENTRIES]);
  555. break;
  556. }
  557. case BONE_TRANSLATE:
  558. case BONE_SCALE:
  559. case BONE_SHEAR: {
  560. TranslateTimeline timeline;
  561. float timelineScale = 1;
  562. if (timelineType == BONE_SCALE)
  563. timeline = new ScaleTimeline(frameCount);
  564. else if (timelineType == BONE_SHEAR)
  565. timeline = new ShearTimeline(frameCount);
  566. else {
  567. timeline = new TranslateTimeline(frameCount);
  568. timelineScale = scale;
  569. }
  570. timeline.boneIndex = boneIndex;
  571. for (int frameIndex = 0; frameIndex < frameCount; frameIndex++) {
  572. timeline.SetFrame(frameIndex, ReadFloat(input), ReadFloat(input) * timelineScale, ReadFloat(input)
  573. * timelineScale);
  574. if (frameIndex < frameCount - 1) ReadCurve(input, frameIndex, timeline);
  575. }
  576. timelines.Add(timeline);
  577. duration = Math.Max(duration, timeline.frames[(frameCount - 1) * TranslateTimeline.ENTRIES]);
  578. break;
  579. }
  580. }
  581. }
  582. }
  583. // IK timelines.
  584. for (int i = 0, n = ReadVarint(input, true); i < n; i++) {
  585. int index = ReadVarint(input, true);
  586. int frameCount = ReadVarint(input, true);
  587. IkConstraintTimeline timeline = new IkConstraintTimeline(frameCount);
  588. timeline.ikConstraintIndex = index;
  589. for (int frameIndex = 0; frameIndex < frameCount; frameIndex++) {
  590. timeline.SetFrame(frameIndex, ReadFloat(input), ReadFloat(input), ReadSByte(input));
  591. if (frameIndex < frameCount - 1) ReadCurve(input, frameIndex, timeline);
  592. }
  593. timelines.Add(timeline);
  594. duration = Math.Max(duration, timeline.frames[(frameCount - 1) * IkConstraintTimeline.ENTRIES]);
  595. }
  596. // Transform constraint timelines.
  597. for (int i = 0, n = ReadVarint(input, true); i < n; i++) {
  598. int index = ReadVarint(input, true);
  599. int frameCount = ReadVarint(input, true);
  600. TransformConstraintTimeline timeline = new TransformConstraintTimeline(frameCount);
  601. timeline.transformConstraintIndex = index;
  602. for (int frameIndex = 0; frameIndex < frameCount; frameIndex++) {
  603. timeline.SetFrame(frameIndex, ReadFloat(input), ReadFloat(input), ReadFloat(input), ReadFloat(input), ReadFloat(input));
  604. if (frameIndex < frameCount - 1) ReadCurve(input, frameIndex, timeline);
  605. }
  606. timelines.Add(timeline);
  607. duration = Math.Max(duration, timeline.frames[(frameCount - 1) * TransformConstraintTimeline.ENTRIES]);
  608. }
  609. // Path constraint timelines.
  610. for (int i = 0, n = ReadVarint(input, true); i < n; i++) {
  611. int index = ReadVarint(input, true);
  612. PathConstraintData data = skeletonData.pathConstraints.Items[index];
  613. for (int ii = 0, nn = ReadVarint(input, true); ii < nn; ii++) {
  614. int timelineType = ReadSByte(input);
  615. int frameCount = ReadVarint(input, true);
  616. switch(timelineType) {
  617. case PATH_POSITION:
  618. case PATH_SPACING: {
  619. PathConstraintPositionTimeline timeline;
  620. float timelineScale = 1;
  621. if (timelineType == PATH_SPACING) {
  622. timeline = new PathConstraintSpacingTimeline(frameCount);
  623. if (data.spacingMode == SpacingMode.Length || data.spacingMode == SpacingMode.Fixed) timelineScale = scale;
  624. } else {
  625. timeline = new PathConstraintPositionTimeline(frameCount);
  626. if (data.positionMode == PositionMode.Fixed) timelineScale = scale;
  627. }
  628. timeline.pathConstraintIndex = index;
  629. for (int frameIndex = 0; frameIndex < frameCount; frameIndex++) {
  630. timeline.SetFrame(frameIndex, ReadFloat(input), ReadFloat(input) * timelineScale);
  631. if (frameIndex < frameCount - 1) ReadCurve(input, frameIndex, timeline);
  632. }
  633. timelines.Add(timeline);
  634. duration = Math.Max(duration, timeline.frames[(frameCount - 1) * PathConstraintPositionTimeline.ENTRIES]);
  635. break;
  636. }
  637. case PATH_MIX: {
  638. PathConstraintMixTimeline timeline = new PathConstraintMixTimeline(frameCount);
  639. timeline.pathConstraintIndex = index;
  640. for (int frameIndex = 0; frameIndex < frameCount; frameIndex++) {
  641. timeline.SetFrame(frameIndex, ReadFloat(input), ReadFloat(input), ReadFloat(input));
  642. if (frameIndex < frameCount - 1) ReadCurve(input, frameIndex, timeline);
  643. }
  644. timelines.Add(timeline);
  645. duration = Math.Max(duration, timeline.frames[(frameCount - 1) * PathConstraintMixTimeline.ENTRIES]);
  646. break;
  647. }
  648. }
  649. }
  650. }
  651. // Deform timelines.
  652. for (int i = 0, n = ReadVarint(input, true); i < n; i++) {
  653. Skin skin = skeletonData.skins.Items[ReadVarint(input, true)];
  654. for (int ii = 0, nn = ReadVarint(input, true); ii < nn; ii++) {
  655. int slotIndex = ReadVarint(input, true);
  656. for (int iii = 0, nnn = ReadVarint(input, true); iii < nnn; iii++) {
  657. VertexAttachment attachment = (VertexAttachment)skin.GetAttachment(slotIndex, ReadString(input));
  658. bool weighted = attachment.bones != null;
  659. float[] vertices = attachment.vertices;
  660. int deformLength = weighted ? vertices.Length / 3 * 2 : vertices.Length;
  661. int frameCount = ReadVarint(input, true);
  662. DeformTimeline timeline = new DeformTimeline(frameCount);
  663. timeline.slotIndex = slotIndex;
  664. timeline.attachment = attachment;
  665. for (int frameIndex = 0; frameIndex < frameCount; frameIndex++) {
  666. float time = ReadFloat(input);
  667. float[] deform;
  668. int end = ReadVarint(input, true);
  669. if (end == 0)
  670. deform = weighted ? new float[deformLength] : vertices;
  671. else {
  672. deform = new float[deformLength];
  673. int start = ReadVarint(input, true);
  674. end += start;
  675. if (scale == 1) {
  676. for (int v = start; v < end; v++)
  677. deform[v] = ReadFloat(input);
  678. } else {
  679. for (int v = start; v < end; v++)
  680. deform[v] = ReadFloat(input) * scale;
  681. }
  682. if (!weighted) {
  683. for (int v = 0, vn = deform.Length; v < vn; v++)
  684. deform[v] += vertices[v];
  685. }
  686. }
  687. timeline.SetFrame(frameIndex, time, deform);
  688. if (frameIndex < frameCount - 1) ReadCurve(input, frameIndex, timeline);
  689. }
  690. timelines.Add(timeline);
  691. duration = Math.Max(duration, timeline.frames[frameCount - 1]);
  692. }
  693. }
  694. }
  695. // Draw order timeline.
  696. int drawOrderCount = ReadVarint(input, true);
  697. if (drawOrderCount > 0) {
  698. DrawOrderTimeline timeline = new DrawOrderTimeline(drawOrderCount);
  699. int slotCount = skeletonData.slots.Count;
  700. for (int i = 0; i < drawOrderCount; i++) {
  701. float time = ReadFloat(input);
  702. int offsetCount = ReadVarint(input, true);
  703. int[] drawOrder = new int[slotCount];
  704. for (int ii = slotCount - 1; ii >= 0; ii--)
  705. drawOrder[ii] = -1;
  706. int[] unchanged = new int[slotCount - offsetCount];
  707. int originalIndex = 0, unchangedIndex = 0;
  708. for (int ii = 0; ii < offsetCount; ii++) {
  709. int slotIndex = ReadVarint(input, true);
  710. // Collect unchanged items.
  711. while (originalIndex != slotIndex)
  712. unchanged[unchangedIndex++] = originalIndex++;
  713. // Set changed items.
  714. drawOrder[originalIndex + ReadVarint(input, true)] = originalIndex++;
  715. }
  716. // Collect remaining unchanged items.
  717. while (originalIndex < slotCount)
  718. unchanged[unchangedIndex++] = originalIndex++;
  719. // Fill in unchanged items.
  720. for (int ii = slotCount - 1; ii >= 0; ii--)
  721. if (drawOrder[ii] == -1) drawOrder[ii] = unchanged[--unchangedIndex];
  722. timeline.SetFrame(i, time, drawOrder);
  723. }
  724. timelines.Add(timeline);
  725. duration = Math.Max(duration, timeline.frames[drawOrderCount - 1]);
  726. }
  727. // Event timeline.
  728. int eventCount = ReadVarint(input, true);
  729. if (eventCount > 0) {
  730. EventTimeline timeline = new EventTimeline(eventCount);
  731. for (int i = 0; i < eventCount; i++) {
  732. float time = ReadFloat(input);
  733. EventData eventData = skeletonData.events.Items[ReadVarint(input, true)];
  734. Event e = new Event(time, eventData);
  735. e.Int = ReadVarint(input, false);
  736. e.Float = ReadFloat(input);
  737. e.String = ReadBoolean(input) ? ReadString(input) : eventData.String;
  738. timeline.SetFrame(i, e);
  739. }
  740. timelines.Add(timeline);
  741. duration = Math.Max(duration, timeline.frames[eventCount - 1]);
  742. }
  743. timelines.TrimExcess();
  744. skeletonData.animations.Add(new Animation(name, timelines, duration));
  745. }
  746. private void ReadCurve (Stream input, int frameIndex, CurveTimeline timeline) {
  747. switch (input.ReadByte()) {
  748. case CURVE_STEPPED:
  749. timeline.SetStepped(frameIndex);
  750. break;
  751. case CURVE_BEZIER:
  752. timeline.SetCurve(frameIndex, ReadFloat(input), ReadFloat(input), ReadFloat(input), ReadFloat(input));
  753. break;
  754. }
  755. }
  756. private static sbyte ReadSByte (Stream input) {
  757. int value = input.ReadByte();
  758. if (value == -1) throw new EndOfStreamException();
  759. return (sbyte)value;
  760. }
  761. private static bool ReadBoolean (Stream input) {
  762. return input.ReadByte() != 0;
  763. }
  764. private float ReadFloat (Stream input) {
  765. buffer[3] = (byte)input.ReadByte();
  766. buffer[2] = (byte)input.ReadByte();
  767. buffer[1] = (byte)input.ReadByte();
  768. buffer[0] = (byte)input.ReadByte();
  769. return BitConverter.ToSingle(buffer, 0);
  770. }
  771. private static int ReadInt (Stream input) {
  772. return (input.ReadByte() << 24) + (input.ReadByte() << 16) + (input.ReadByte() << 8) + input.ReadByte();
  773. }
  774. private static int ReadVarint (Stream input, bool optimizePositive) {
  775. int b = input.ReadByte();
  776. int result = b & 0x7F;
  777. if ((b & 0x80) != 0) {
  778. b = input.ReadByte();
  779. result |= (b & 0x7F) << 7;
  780. if ((b & 0x80) != 0) {
  781. b = input.ReadByte();
  782. result |= (b & 0x7F) << 14;
  783. if ((b & 0x80) != 0) {
  784. b = input.ReadByte();
  785. result |= (b & 0x7F) << 21;
  786. if ((b & 0x80) != 0) result |= (input.ReadByte() & 0x7F) << 28;
  787. }
  788. }
  789. }
  790. return optimizePositive ? result : ((result >> 1) ^ -(result & 1));
  791. }
  792. private string ReadString (Stream input) {
  793. int byteCount = ReadVarint(input, true);
  794. switch (byteCount) {
  795. case 0:
  796. return null;
  797. case 1:
  798. return "";
  799. }
  800. byteCount--;
  801. byte[] buffer = this.buffer;
  802. if (buffer.Length < byteCount) buffer = new byte[byteCount];
  803. ReadFully(input, buffer, 0, byteCount);
  804. return System.Text.Encoding.UTF8.GetString(buffer, 0, byteCount);
  805. }
  806. private static void ReadFully (Stream input, byte[] buffer, int offset, int length) {
  807. while (length > 0) {
  808. int count = input.Read(buffer, offset, length);
  809. if (count <= 0) throw new EndOfStreamException();
  810. offset += count;
  811. length -= count;
  812. }
  813. }
  814. internal class Vertices {
  815. public int[] bones;
  816. public float[] vertices;
  817. }
  818. }
  819. }