Ver código fonte

[ts][threejs] Fixed bug in core AssetManager when loading multi-page atlases. Rewrote THREE.JS renderer to support multi-page atlases. Fixed clipping in THREE.JS backend. Closes #1066, closes #677.

badlogic 7 anos atrás
pai
commit
fe9ae97747

+ 20 - 19
CHANGELOG.md

@@ -11,7 +11,7 @@
  * **Additions**
  * **Additions**
   * Added `Skeleton.getBounds` from reference implementation.
   * Added `Skeleton.getBounds` from reference implementation.
   * Added support for local and relative transform constraint calculation, including additional fields in `TransformConstraintData`
   * Added support for local and relative transform constraint calculation, including additional fields in `TransformConstraintData`
-  * Added `Bone.localToWorldRotation`(rotation given relative to x-axis, counter-clockwise, in degrees).    
+  * Added `Bone.localToWorldRotation`(rotation given relative to x-axis, counter-clockwise, in degrees).
   * Added two color tinting support, including `TwoColorTimeline` and additional fields on `Slot` and `SlotData`.
   * Added two color tinting support, including `TwoColorTimeline` and additional fields on `Slot` and `SlotData`.
   * Added `PointAttachment`, additional method `newPointAttachment` in `AttachmentLoader` interface.
   * Added `PointAttachment`, additional method `newPointAttachment` in `AttachmentLoader` interface.
   * Added `ClippingAttachment`, additional method `newClippingAttachment` in `AttachmentLoader` interface.
   * Added `ClippingAttachment`, additional method `newClippingAttachment` in `AttachmentLoader` interface.
@@ -38,10 +38,10 @@
   * Removed `spVertexIndex`from public API.
   * Removed `spVertexIndex`from public API.
   * Listeners on `spAnimationState` or `spTrackEntry` will now be also called in case a track entry is disposed as part of dispoing the `spAnimationState`.
   * Listeners on `spAnimationState` or `spTrackEntry` will now be also called in case a track entry is disposed as part of dispoing the `spAnimationState`.
  * **Additions**
  * **Additions**
-  * Added support for local and relative transform constraint calculation, including additional fields in `spTransformConstraintData`.  
+  * Added support for local and relative transform constraint calculation, including additional fields in `spTransformConstraintData`.
   * Added `spPointAttachment`, additional method `spAtlasAttachmentLoadeR_newPointAttachment`.
   * Added `spPointAttachment`, additional method `spAtlasAttachmentLoadeR_newPointAttachment`.
   * Added support for local and relative transform constraint calculation, including additional fields in `TransformConstraintData`
   * Added support for local and relative transform constraint calculation, including additional fields in `TransformConstraintData`
-  * Added `spBone_localToWorldRotation`(rotation given relative to x-axis, counter-clockwise, in degrees).  	
+  * Added `spBone_localToWorldRotation`(rotation given relative to x-axis, counter-clockwise, in degrees).
    * Added two color tinting support, including `spTwoColorTimeline` and additional fields on `spSlot` and `spSlotData`.
    * Added two color tinting support, including `spTwoColorTimeline` and additional fields on `spSlot` and `spSlotData`.
   * Added `userData` field to `spTrackEntry`, so users can expose data in `spAnimationState` callbacks.
   * Added `userData` field to `spTrackEntry`, so users can expose data in `spAnimationState` callbacks.
   * Modified kvec.h used by SkeletonBinary.c to use Spine's MALLOC/FREE macros. That way there's only one place to inject custom allocators ([extension.h](https://github.com/EsotericSoftware/spine-runtimes/blob/master/spine-c/spine-c/include/spine/extension.h)) [commit](https://github.com/EsotericSoftware/spine-runtimes/commit/c2cfbc6cb8709daa082726222d558188d75a004f)
   * Modified kvec.h used by SkeletonBinary.c to use Spine's MALLOC/FREE macros. That way there's only one place to inject custom allocators ([extension.h](https://github.com/EsotericSoftware/spine-runtimes/blob/master/spine-c/spine-c/include/spine/extension.h)) [commit](https://github.com/EsotericSoftware/spine-runtimes/commit/c2cfbc6cb8709daa082726222d558188d75a004f)
@@ -95,10 +95,10 @@
   * Added `stride` parameter to `VertexAttachment.ComputeWorldVertices`.
   * Added `stride` parameter to `VertexAttachment.ComputeWorldVertices`.
   * Removed `RegionAttachment.Vertices` field. The vertices array is provided to `RegionAttachment.ComputeWorldVertices` by the API user now.
   * Removed `RegionAttachment.Vertices` field. The vertices array is provided to `RegionAttachment.ComputeWorldVertices` by the API user now.
   * Removed `RegionAttachment.UpdateWorldVertices`, added `RegionAttachment.ComputeWorldVertices`. The new method now computes the x/y positions of the 4 vertices of the corner and places them in the provided `worldVertices` array, starting at `offset`, then moving by `stride` array elements when advancing to the next vertex. This allows to directly compose the vertex buffer and avoids a copy. The computation of the full vertices, including vertex colors and texture coordinates, is now done by the backend's respective renderer.
   * Removed `RegionAttachment.UpdateWorldVertices`, added `RegionAttachment.ComputeWorldVertices`. The new method now computes the x/y positions of the 4 vertices of the corner and places them in the provided `worldVertices` array, starting at `offset`, then moving by `stride` array elements when advancing to the next vertex. This allows to directly compose the vertex buffer and avoids a copy. The computation of the full vertices, including vertex colors and texture coordinates, is now done by the backend's respective renderer.
- * **Additions**  
+ * **Additions**
   * Added support for local and relative transform constraint calculation, including additional fields in `TransformConstraintData`
   * Added support for local and relative transform constraint calculation, including additional fields in `TransformConstraintData`
-  * Added `Bone.localToWorldRotation`(rotation given relative to x-axis, counter-clockwise, in degrees).  
-  * Added two color tinting support, including `TwoColorTimeline` and additional fields on `Slot` and `SlotData`.  
+  * Added `Bone.localToWorldRotation`(rotation given relative to x-axis, counter-clockwise, in degrees).
+  * Added two color tinting support, including `TwoColorTimeline` and additional fields on `Slot` and `SlotData`.
   * Added `PointAttachment`, additional method `NewPointAttachment` in `AttachmentLoader` interface.
   * Added `PointAttachment`, additional method `NewPointAttachment` in `AttachmentLoader` interface.
   * Added `ClippingAttachment`, additional method `NewClippingAttachment` in `AttachmentLoader` interface.
   * Added `ClippingAttachment`, additional method `NewClippingAttachment` in `AttachmentLoader` interface.
   * Added `SkeletonClipper` and `Triangulator`, used to implement software clipping of attachments.
   * Added `SkeletonClipper` and `Triangulator`, used to implement software clipping of attachments.
@@ -110,10 +110,10 @@
    * **Two color tinting** is currently supported via extra UV2 and UV3 mesh vertex streams. To use Two color tinting, you need to:
    * **Two color tinting** is currently supported via extra UV2 and UV3 mesh vertex streams. To use Two color tinting, you need to:
      * switch on "Tint Black" under "Advanced...",
      * switch on "Tint Black" under "Advanced...",
      * use the new `Spine/Skeleton Tint Black` shader, or your own shader that treats the UV2 and UV3 streams similarly.
      * use the new `Spine/Skeleton Tint Black` shader, or your own shader that treats the UV2 and UV3 streams similarly.
-     * Additionally, for SkeletonGraphic, you can use `Spine/SkeletonGraphic Tint Black` (or the bundled SkeletonGraphicTintBlack material) or your own shader that uses UV2 and UV3 streams similarly. **Additional Shader Channels** TexCoord1 and TexCoord2 will need to be enabled from the Canvas component's inspector. These correspond to UV2 and UV3. 
+     * Additionally, for SkeletonGraphic, you can use `Spine/SkeletonGraphic Tint Black` (or the bundled SkeletonGraphicTintBlack material) or your own shader that uses UV2 and UV3 streams similarly. **Additional Shader Channels** TexCoord1 and TexCoord2 will need to be enabled from the Canvas component's inspector. These correspond to UV2 and UV3.
    * **Clipping** is now supported. Caution: The SkeletonAnimation switches to slightly slower mesh generation code when clipping so limit your use of `ClippingAttachment`s when using on large numbers of skeletons.
    * **Clipping** is now supported. Caution: The SkeletonAnimation switches to slightly slower mesh generation code when clipping so limit your use of `ClippingAttachment`s when using on large numbers of skeletons.
- * **SkeletonRenderer.initialFlip** Spine components such as SkeletonRenderer, SkeletonAnimation, SkeletonAnimator now has `initialFlipX` and `initialFlipY` fields which are also visible in the inspector under "Advanced...". It will allow you to set and preview a starting flip value for your skeleton component. This is applied immediately when the internal skeleton object is instantiated. 
- * **[SpineAttribute] Improvements** 
+ * **SkeletonRenderer.initialFlip** Spine components such as SkeletonRenderer, SkeletonAnimation, SkeletonAnimator now has `initialFlipX` and `initialFlipY` fields which are also visible in the inspector under "Advanced...". It will allow you to set and preview a starting flip value for your skeleton component. This is applied immediately when the internal skeleton object is instantiated.
+ * **[SpineAttribute] Improvements**
    * **Icons have been added to SpineAttributeDrawers**. This should make your default inspectors easier to understand at a glance.
    * **Icons have been added to SpineAttributeDrawers**. This should make your default inspectors easier to understand at a glance.
    * **Added Constraint Attributes** You can now use `[SpineIkConstraint]` `[SpineTransformConstraint]` `[SpinePathConstraint]`
    * **Added Constraint Attributes** You can now use `[SpineIkConstraint]` `[SpineTransformConstraint]` `[SpinePathConstraint]`
    * **SpineAttribute dataField** parameter can also now detect sibling fields within arrays and serializable structs/classes.
    * **SpineAttribute dataField** parameter can also now detect sibling fields within arrays and serializable structs/classes.
@@ -127,12 +127,12 @@
  * **SkeletonRenderer.OnPostProcessVertices** is a new callback that gives you a reference to the MeshGenerator after it has generated a mesh from the current skeleton pose. You can access `meshGenerator.VertexBuffer` or `meshGenerator.ColorBuffer` to modify these before they get pushed into the UnityEngine.Mesh for rendering. This can be useful for non-shader vertex effects.
  * **SkeletonRenderer.OnPostProcessVertices** is a new callback that gives you a reference to the MeshGenerator after it has generated a mesh from the current skeleton pose. You can access `meshGenerator.VertexBuffer` or `meshGenerator.ColorBuffer` to modify these before they get pushed into the UnityEngine.Mesh for rendering. This can be useful for non-shader vertex effects.
  * **Examples**
  * **Examples**
    * **Examples now use properties**. The code in the example scripts have been switched over to using properties instead of fields to encourage their use for consistency. This is in anticipation of both users who want to move the Spine folders to the Unity Plugins folder (compiled as a different assembly), and of Unity 2017's ability to manually define different assemblies for shorter compilation times.
    * **Examples now use properties**. The code in the example scripts have been switched over to using properties instead of fields to encourage their use for consistency. This is in anticipation of both users who want to move the Spine folders to the Unity Plugins folder (compiled as a different assembly), and of Unity 2017's ability to manually define different assemblies for shorter compilation times.
-   * **Mix And Match**. The mix-and-match example scene, code and data have been updated to reflect the current recommended setup for animation-compatible custom equip systems The underlying API has changed since 3.5 and the new API calls in MixAndMatch.cs is recommended. Documentation is in progress.  
+   * **Mix And Match**. The mix-and-match example scene, code and data have been updated to reflect the current recommended setup for animation-compatible custom equip systems The underlying API has changed since 3.5 and the new API calls in MixAndMatch.cs is recommended. Documentation is in progress.
    * **Sample Components**. `AtasRegionAttacher` and `SpriteAttacher` are now part of `Sample Components`, to reflect that they are meant to be used as sample code rather than production. A few other sample components have also been added. New imports of the unitypackage Examples folder will see a "Legacy" folder comprised of old sample components that no longer contain the most up-to-date and recommended workflows, but are kept in case old setups used them for production.
    * **Sample Components**. `AtasRegionAttacher` and `SpriteAttacher` are now part of `Sample Components`, to reflect that they are meant to be used as sample code rather than production. A few other sample components have also been added. New imports of the unitypackage Examples folder will see a "Legacy" folder comprised of old sample components that no longer contain the most up-to-date and recommended workflows, but are kept in case old setups used them for production.
  * **Spine folder**. In the unitypackage, the "spine-csharp" and "spine-unity" folders are now inside a "Spine" folder. This change will only affect fresh imports. Importing the unitypackage to update Spine-Unity in your existing project will update the appropriate files however you chose to arrange them, as long as the meta files are intact.
  * **Spine folder**. In the unitypackage, the "spine-csharp" and "spine-unity" folders are now inside a "Spine" folder. This change will only affect fresh imports. Importing the unitypackage to update Spine-Unity in your existing project will update the appropriate files however you chose to arrange them, as long as the meta files are intact.
  * **Breaking changes**
  * **Breaking changes**
    * The Sprite shaders module was updated to the latest version from the [source](https://github.com/traggett/UnitySpriteShaders/commits/master). Some changes were made to the underlying keyword structure. You may need to review the settings of your lit materials. Particularly, your Fixed Normals settings.
    * The Sprite shaders module was updated to the latest version from the [source](https://github.com/traggett/UnitySpriteShaders/commits/master). Some changes were made to the underlying keyword structure. You may need to review the settings of your lit materials. Particularly, your Fixed Normals settings.
-   * The `Spine/Skeleton Lit` shader was switched over to non-fixed-function code. It now no longer requires mesh normals and has fixed normals at the shader level. 
+   * The `Spine/Skeleton Lit` shader was switched over to non-fixed-function code. It now no longer requires mesh normals and has fixed normals at the shader level.
    * The old MeshGenerator classes, interfaces and code in `Spine.Unity.MeshGeneration` are now deprecated. All mesh-generating components now share the class `Spine.Unity.MeshGenerator` defined in `SpineMesh.cs`. MeshGenerator is a serializable class.
    * The old MeshGenerator classes, interfaces and code in `Spine.Unity.MeshGeneration` are now deprecated. All mesh-generating components now share the class `Spine.Unity.MeshGenerator` defined in `SpineMesh.cs`. MeshGenerator is a serializable class.
      * The `SkeletonRenderer.renderMeshes` optimization is currently non-functional.
      * The `SkeletonRenderer.renderMeshes` optimization is currently non-functional.
      * Old triangle-winding code has been removed from `SkeletonRenderer`. Please use shaders that have backface culling off.
      * Old triangle-winding code has been removed from `SkeletonRenderer`. Please use shaders that have backface culling off.
@@ -161,15 +161,15 @@
   * Removed `RegionAttachment.updateWorldVertices`, added `RegionAttachment.computeWorldVertices`. The new method now computes the x/y positions of the 4 vertices of the corner and places them in the provided `worldVertices` array, starting at `offset`, then moving by `stride` array elements when advancing to the next vertex. This allows to directly compose the vertex buffer and avoids a copy. The computation of the full vertices, including vertex colors and texture coordinates, is now done by the backend's respective renderer.
   * Removed `RegionAttachment.updateWorldVertices`, added `RegionAttachment.computeWorldVertices`. The new method now computes the x/y positions of the 4 vertices of the corner and places them in the provided `worldVertices` array, starting at `offset`, then moving by `stride` array elements when advancing to the next vertex. This allows to directly compose the vertex buffer and avoids a copy. The computation of the full vertices, including vertex colors and texture coordinates, is now done by the backend's respective renderer.
   * Skeleton attachments: Moved update of attached skeleton out of libGDX `SkeletonRenderer`, added overloaded method `Skeleton#updateWorldTransform(Bone), used for `SkeletonAttachment`. You now MUST call this new method
   * Skeleton attachments: Moved update of attached skeleton out of libGDX `SkeletonRenderer`, added overloaded method `Skeleton#updateWorldTransform(Bone), used for `SkeletonAttachment`. You now MUST call this new method
   with the bone of the parent skeleton to which the child skeleton is attached. See `SkeletonAttachmentTest` for and example.
   with the bone of the parent skeleton to which the child skeleton is attached. See `SkeletonAttachmentTest` for and example.
- * **Additions**  
+ * **Additions**
   * Added support for local and relative transform constraint calculation, including additional fields in `TransformConstraintData`
   * Added support for local and relative transform constraint calculation, including additional fields in `TransformConstraintData`
-  * Added `Bone.localToWorldRotation`(rotation given relative to x-axis, counter-clockwise, in degrees).  
-  * Added two color tinting support, including `TwoColorTimeline` and additional fields on `Slot` and `SlotData`.  
+  * Added `Bone.localToWorldRotation`(rotation given relative to x-axis, counter-clockwise, in degrees).
+  * Added two color tinting support, including `TwoColorTimeline` and additional fields on `Slot` and `SlotData`.
   * Added `PointAttachment`, additional method `newPointAttachment` in `AttachmentLoader` interface.
   * Added `PointAttachment`, additional method `newPointAttachment` in `AttachmentLoader` interface.
   * Added `ClippingAttachment`, additional method `newClippingAttachment` in `AttachmentLoader` interface.
   * Added `ClippingAttachment`, additional method `newClippingAttachment` in `AttachmentLoader` interface.
   * Added `SkeletonClipper` and `Triangulator`, used to implement software clipping of attachments.
   * Added `SkeletonClipper` and `Triangulator`, used to implement software clipping of attachments.
   * `AnimationState#apply` returns boolean indicating if any timeline was applied or not.
   * `AnimationState#apply` returns boolean indicating if any timeline was applied or not.
-  * `Animation#apply` and `Timeline#apply`` now take enums `MixPose` and `MixDirection` instead of booleans  
+  * `Animation#apply` and `Timeline#apply`` now take enums `MixPose` and `MixDirection` instead of booleans
 
 
 ### libGDX
 ### libGDX
  * Fixed renderer to work with 3.6 changes
  * Fixed renderer to work with 3.6 changes
@@ -187,7 +187,7 @@
  * **Additions**
  * **Additions**
   * Added `Bone:localToWorldRotation`(rotation given relative to x-axis, counter-clockwise, in degrees).
   * Added `Bone:localToWorldRotation`(rotation given relative to x-axis, counter-clockwise, in degrees).
   * Added two color tinting support, including `TwoColorTimeline` and additional fields on `Slot` and `SlotData`.
   * Added two color tinting support, including `TwoColorTimeline` and additional fields on `Slot` and `SlotData`.
-  * Added `PointAttachment`, additional method `newPointAttachment` in `AttachmentLoader` interface.  
+  * Added `PointAttachment`, additional method `newPointAttachment` in `AttachmentLoader` interface.
   * Added support for local and relative transform constraint calculation, including additional fields in `TransformConstraintData`
   * Added support for local and relative transform constraint calculation, including additional fields in `TransformConstraintData`
   * Added `ClippingAttachment`, additional method `newClippingAttachment` in `AttachmentLoader` interface.
   * Added `ClippingAttachment`, additional method `newClippingAttachment` in `AttachmentLoader` interface.
   * Added `SkeletonClipper` and `Triangulator`, used to implement software clipping of attachments.
   * Added `SkeletonClipper` and `Triangulator`, used to implement software clipping of attachments.
@@ -213,10 +213,10 @@
   * Removed `VertexAttachment.computeWorldVertices` overload, changed `VertexAttachment.computeWorldVerticesWith` to `VertexAttachment.computeWorldVertices`, added `stride` parameter.
   * Removed `VertexAttachment.computeWorldVertices` overload, changed `VertexAttachment.computeWorldVerticesWith` to `VertexAttachment.computeWorldVertices`, added `stride` parameter.
   * Removed `RegionAttachment.vertices` field. The vertices array is provided to `RegionAttachment.computeWorldVertices` by the API user now.
   * Removed `RegionAttachment.vertices` field. The vertices array is provided to `RegionAttachment.computeWorldVertices` by the API user now.
   * Removed `RegionAttachment.updateWorldVertices`, added `RegionAttachment.computeWorldVertices`. The new method now computes the x/y positions of the 4 vertices of the corner and places them in the provided `worldVertices` array, starting at `offset`, then moving by `stride` array elements when advancing to the next vertex. This allows to directly compose the vertex buffer and avoids a copy. The computation of the full vertices, including vertex colors and texture coordinates, is now done by the backend's respective renderer.
   * Removed `RegionAttachment.updateWorldVertices`, added `RegionAttachment.computeWorldVertices`. The new method now computes the x/y positions of the 4 vertices of the corner and places them in the provided `worldVertices` array, starting at `offset`, then moving by `stride` array elements when advancing to the next vertex. This allows to directly compose the vertex buffer and avoids a copy. The computation of the full vertices, including vertex colors and texture coordinates, is now done by the backend's respective renderer.
- * **Additions**  
+ * **Additions**
   * Added support for local and relative transform constraint calculation, including additional fields in `TransformConstraintData`
   * Added support for local and relative transform constraint calculation, including additional fields in `TransformConstraintData`
-  * Added `Bone.localToWorldRotation`(rotation given relative to x-axis, counter-clockwise, in degrees).  
-  * Added two color tinting support, including `TwoColorTimeline` and additional fields on `Slot` and `SlotData`.  
+  * Added `Bone.localToWorldRotation`(rotation given relative to x-axis, counter-clockwise, in degrees).
+  * Added two color tinting support, including `TwoColorTimeline` and additional fields on `Slot` and `SlotData`.
   * Added `PointAttachment`, additional method `newPointAttachment` in `AttachmentLoader` interface.
   * Added `PointAttachment`, additional method `newPointAttachment` in `AttachmentLoader` interface.
   * Added `ClippingAttachment`, additional method `newClippingAttachment` in `AttachmentLoader` interface.
   * Added `ClippingAttachment`, additional method `newClippingAttachment` in `AttachmentLoader` interface.
   * Added `SkeletonClipper` and `Triangulator`, used to implement software clipping of attachments.
   * Added `SkeletonClipper` and `Triangulator`, used to implement software clipping of attachments.
@@ -250,6 +250,7 @@
  * Fixed renderer to work with 3.6 changes. Two color tinting is not supported.
  * Fixed renderer to work with 3.6 changes. Two color tinting is not supported.
  * Added clipping support
  * Added clipping support
  * Added `VertexEffect` interface, instances of which can be set on `SkeletonMesh`. Allows to modify vertices before submitting them to GPU. See `SwirlEffect`, `JitterEffect`.
  * Added `VertexEffect` interface, instances of which can be set on `SkeletonMesh`. Allows to modify vertices before submitting them to GPU. See `SwirlEffect`, `JitterEffect`.
+ * Added support for multi-page atlases
 
 
 ### Widget backend
 ### Widget backend
  * Fixed WebGL context loss (see WebGL backend changes). Enabled automatically.
  * Fixed WebGL context loss (see WebGL backend changes). Enabled automatically.

+ 4 - 4
spine-ts/README.md

@@ -20,11 +20,11 @@ The Spine Runtimes are developed with the intent to be used with data exported f
 
 
 spine-ts works with data exported from Spine 3.6.xx.
 spine-ts works with data exported from Spine 3.6.xx.
 
 
-spine-ts WebGL & Widget backends supports all Spine features. 
+spine-ts WebGL & Widget backends supports all Spine features.
 
 
-spine-ts Canvas does not support color tinting, mesh attachments and clipping. Only the alpha channel from tint colors is applied. Experimental support for mesh attachments can be enabled by setting `spine.canvas.SkeletonRenderer.useTriangleRendering` to true. Note that this method is slow and may lead to artifacts on some browsers. 
+spine-ts Canvas does not support color tinting, mesh attachments and clipping. Only the alpha channel from tint colors is applied. Experimental support for mesh attachments can be enabled by setting `spine.canvas.SkeletonRenderer.useTriangleRendering` to true. Note that this method is slow and may lead to artifacts on some browsers.
 
 
-spine-ts THREE.JS does not support color tinting, blend modes and clipping. The THREE.JS backend provides `SkeletonMesh.zOffset` to avoid z-fighting. Adjust to your near/far plane settings.
+spine-ts THREE.JS does not support two color tinting & blend modes. The THREE.JS backend provides `SkeletonMesh.zOffset` to avoid z-fighting. Adjust to your near/far plane settings.
 
 
 spine-ts does not yet support loading the binary format.
 spine-ts does not yet support loading the binary format.
 
 
@@ -115,7 +115,7 @@ You can disable two-color tinting like this:
 // If you use SceneRenderer, disable two-color tinting via the last constructor argument
 // If you use SceneRenderer, disable two-color tinting via the last constructor argument
 var sceneRenderer = new spine.SceneRenderer(canvas, gl, false);
 var sceneRenderer = new spine.SceneRenderer(canvas, gl, false);
 
 
-// If you use SkeletonRenderer and PolygonBatcher directly, 
+// If you use SkeletonRenderer and PolygonBatcher directly,
 // disable two-color tinting in the respective constructor
 // disable two-color tinting in the respective constructor
 // and use the shader returned by Shader.newColoredTextured()
 // and use the shader returned by Shader.newColoredTextured()
 // instead of Shader.newTwoColoredTextured()
 // instead of Shader.newTwoColoredTextured()

+ 12 - 5
spine-ts/build/spine-all.d.ts

@@ -1701,22 +1701,26 @@ declare module spine.threejs {
 	}
 	}
 }
 }
 declare module spine.threejs {
 declare module spine.threejs {
-	class MeshBatcher {
-		mesh: THREE.Mesh;
+	class MeshBatcher extends THREE.Mesh {
 		private static VERTEX_SIZE;
 		private static VERTEX_SIZE;
 		private vertexBuffer;
 		private vertexBuffer;
 		private vertices;
 		private vertices;
 		private verticesLength;
 		private verticesLength;
 		private indices;
 		private indices;
 		private indicesLength;
 		private indicesLength;
-		constructor(mesh: THREE.Mesh, maxVertices?: number);
+		constructor(maxVertices?: number);
+		clear(): void;
 		begin(): void;
 		begin(): void;
+		canBatch(verticesLength: number, indicesLength: number): boolean;
 		batch(vertices: ArrayLike<number>, verticesLength: number, indices: ArrayLike<number>, indicesLength: number, z?: number): void;
 		batch(vertices: ArrayLike<number>, verticesLength: number, indices: ArrayLike<number>, indicesLength: number, z?: number): void;
 		end(): void;
 		end(): void;
 	}
 	}
 }
 }
 declare module spine.threejs {
 declare module spine.threejs {
-	class SkeletonMesh extends THREE.Mesh {
+	class SkeletonMeshMaterial extends THREE.ShaderMaterial {
+		constructor();
+	}
+	class SkeletonMesh extends THREE.Object3D {
 		tempPos: Vector2;
 		tempPos: Vector2;
 		tempUv: Vector2;
 		tempUv: Vector2;
 		tempLight: Color;
 		tempLight: Color;
@@ -1725,7 +1729,8 @@ declare module spine.threejs {
 		state: AnimationState;
 		state: AnimationState;
 		zOffset: number;
 		zOffset: number;
 		vertexEffect: VertexEffect;
 		vertexEffect: VertexEffect;
-		private batcher;
+		private batches;
+		private nextBatchIndex;
 		private clipper;
 		private clipper;
 		static QUAD_TRIANGLES: number[];
 		static QUAD_TRIANGLES: number[];
 		static VERTEX_SIZE: number;
 		static VERTEX_SIZE: number;
@@ -1733,6 +1738,8 @@ declare module spine.threejs {
 		private tempColor;
 		private tempColor;
 		constructor(skeletonData: SkeletonData);
 		constructor(skeletonData: SkeletonData);
 		update(deltaTime: number): void;
 		update(deltaTime: number): void;
+		private clearBatches();
+		private nextBatch();
 		private updateGeometry();
 		private updateGeometry();
 	}
 	}
 }
 }

+ 113 - 33
spine-ts/build/spine-all.js

@@ -2001,6 +2001,7 @@ var spine;
 			path = this.pathPrefix + path;
 			path = this.pathPrefix + path;
 			this.toLoad++;
 			this.toLoad++;
 			AssetManager.downloadText(path, function (atlasData) {
 			AssetManager.downloadText(path, function (atlasData) {
+				var pagesLoaded = { count: 0 };
 				var atlasPages = new Array();
 				var atlasPages = new Array();
 				try {
 				try {
 					var atlas = new spine.TextureAtlas(atlasData, function (path) {
 					var atlas = new spine.TextureAtlas(atlasData, function (path) {
@@ -2021,11 +2022,10 @@ var spine;
 					return;
 					return;
 				}
 				}
 				var _loop_1 = function (atlasPage) {
 				var _loop_1 = function (atlasPage) {
-					var pagesLoaded = 0;
 					var pageLoadError = false;
 					var pageLoadError = false;
 					_this.loadTexture(atlasPage, function (imagePath, image) {
 					_this.loadTexture(atlasPage, function (imagePath, image) {
-						pagesLoaded++;
-						if (pagesLoaded == atlasPages.length) {
+						pagesLoaded.count++;
+						if (pagesLoaded.count == atlasPages.length) {
 							if (!pageLoadError) {
 							if (!pageLoadError) {
 								try {
 								try {
 									var atlas = new spine.TextureAtlas(atlasData, function (path) {
 									var atlas = new spine.TextureAtlas(atlasData, function (path) {
@@ -2056,8 +2056,8 @@ var spine;
 						}
 						}
 					}, function (imagePath, errorMessage) {
 					}, function (imagePath, errorMessage) {
 						pageLoadError = true;
 						pageLoadError = true;
-						pagesLoaded++;
-						if (pagesLoaded == atlasPages.length) {
+						pagesLoaded.count++;
+						if (pagesLoaded.count == atlasPages.length) {
 							_this.errors[path] = "Couldn't load texture atlas page " + imagePath + "} of atlas " + path;
 							_this.errors[path] = "Couldn't load texture atlas page " + imagePath + "} of atlas " + path;
 							if (error)
 							if (error)
 								error(path, "Couldn't load texture atlas page " + imagePath + " of atlas " + path);
 								error(path, "Couldn't load texture atlas page " + imagePath + " of atlas " + path);
@@ -9433,18 +9433,19 @@ var spine;
 (function (spine) {
 (function (spine) {
 	var threejs;
 	var threejs;
 	(function (threejs) {
 	(function (threejs) {
-		var MeshBatcher = (function () {
-			function MeshBatcher(mesh, maxVertices) {
+		var MeshBatcher = (function (_super) {
+			__extends(MeshBatcher, _super);
+			function MeshBatcher(maxVertices) {
 				if (maxVertices === void 0) { maxVertices = 10920; }
 				if (maxVertices === void 0) { maxVertices = 10920; }
-				this.verticesLength = 0;
-				this.indicesLength = 0;
+				var _this = _super.call(this) || this;
+				_this.verticesLength = 0;
+				_this.indicesLength = 0;
 				if (maxVertices > 10920)
 				if (maxVertices > 10920)
 					throw new Error("Can't have more than 10920 triangles per batch: " + maxVertices);
 					throw new Error("Can't have more than 10920 triangles per batch: " + maxVertices);
-				var vertices = this.vertices = new Float32Array(maxVertices * MeshBatcher.VERTEX_SIZE);
-				var indices = this.indices = new Uint16Array(maxVertices * 3);
-				this.mesh = mesh;
+				var vertices = _this.vertices = new Float32Array(maxVertices * MeshBatcher.VERTEX_SIZE);
+				var indices = _this.indices = new Uint16Array(maxVertices * 3);
 				var geo = new THREE.BufferGeometry();
 				var geo = new THREE.BufferGeometry();
-				var vertexBuffer = this.vertexBuffer = new THREE.InterleavedBuffer(vertices, MeshBatcher.VERTEX_SIZE);
+				var vertexBuffer = _this.vertexBuffer = new THREE.InterleavedBuffer(vertices, MeshBatcher.VERTEX_SIZE);
 				vertexBuffer.dynamic = true;
 				vertexBuffer.dynamic = true;
 				geo.addAttribute("position", new THREE.InterleavedBufferAttribute(vertexBuffer, 3, 0, false));
 				geo.addAttribute("position", new THREE.InterleavedBufferAttribute(vertexBuffer, 3, 0, false));
 				geo.addAttribute("color", new THREE.InterleavedBufferAttribute(vertexBuffer, 4, 3, false));
 				geo.addAttribute("color", new THREE.InterleavedBufferAttribute(vertexBuffer, 4, 3, false));
@@ -9453,12 +9454,27 @@ var spine;
 				geo.getIndex().dynamic = true;
 				geo.getIndex().dynamic = true;
 				geo.drawRange.start = 0;
 				geo.drawRange.start = 0;
 				geo.drawRange.count = 0;
 				geo.drawRange.count = 0;
-				mesh.geometry = geo;
+				_this.geometry = geo;
+				_this.material = new threejs.SkeletonMeshMaterial();
+				return _this;
 			}
 			}
+			MeshBatcher.prototype.clear = function () {
+				var geo = this.geometry;
+				geo.drawRange.start = 0;
+				geo.drawRange.count = 0;
+				this.material.uniforms.map.value = null;
+			};
 			MeshBatcher.prototype.begin = function () {
 			MeshBatcher.prototype.begin = function () {
 				this.verticesLength = 0;
 				this.verticesLength = 0;
 				this.indicesLength = 0;
 				this.indicesLength = 0;
 			};
 			};
+			MeshBatcher.prototype.canBatch = function (verticesLength, indicesLength) {
+				if (this.indicesLength + indicesLength >= this.indices.byteLength / 2)
+					return false;
+				if (this.verticesLength + verticesLength >= this.vertices.byteLength / 2)
+					return false;
+				return true;
+			};
 			MeshBatcher.prototype.batch = function (vertices, verticesLength, indices, indicesLength, z) {
 			MeshBatcher.prototype.batch = function (vertices, verticesLength, indices, indicesLength, z) {
 				if (z === void 0) { z = 0; }
 				if (z === void 0) { z = 0; }
 				var indexStart = this.verticesLength / MeshBatcher.VERTEX_SIZE;
 				var indexStart = this.verticesLength / MeshBatcher.VERTEX_SIZE;
@@ -9486,7 +9502,7 @@ var spine;
 				this.vertexBuffer.needsUpdate = true;
 				this.vertexBuffer.needsUpdate = true;
 				this.vertexBuffer.updateRange.offset = 0;
 				this.vertexBuffer.updateRange.offset = 0;
 				this.vertexBuffer.updateRange.count = this.verticesLength;
 				this.vertexBuffer.updateRange.count = this.verticesLength;
-				var geo = this.mesh.geometry;
+				var geo = this.geometry;
 				geo.getIndex().needsUpdate = true;
 				geo.getIndex().needsUpdate = true;
 				geo.getIndex().updateRange.offset = 0;
 				geo.getIndex().updateRange.offset = 0;
 				geo.getIndex().updateRange.count = this.indicesLength;
 				geo.getIndex().updateRange.count = this.indicesLength;
@@ -9494,7 +9510,7 @@ var spine;
 				geo.drawRange.count = this.indicesLength;
 				geo.drawRange.count = this.indicesLength;
 			};
 			};
 			return MeshBatcher;
 			return MeshBatcher;
-		}());
+		}(THREE.Mesh));
 		MeshBatcher.VERTEX_SIZE = 9;
 		MeshBatcher.VERTEX_SIZE = 9;
 		threejs.MeshBatcher = MeshBatcher;
 		threejs.MeshBatcher = MeshBatcher;
 	})(threejs = spine.threejs || (spine.threejs = {}));
 	})(threejs = spine.threejs || (spine.threejs = {}));
@@ -9503,6 +9519,29 @@ var spine;
 (function (spine) {
 (function (spine) {
 	var threejs;
 	var threejs;
 	(function (threejs) {
 	(function (threejs) {
+		var SkeletonMeshMaterial = (function (_super) {
+			__extends(SkeletonMeshMaterial, _super);
+			function SkeletonMeshMaterial() {
+				var _this = this;
+				var vertexShader = "\n\t\t\t\tattribute vec4 color;\n\t\t\t\tvarying vec2 vUv;\n\t\t\t\tvarying vec4 vColor;\n\t\t\t\tvoid main() {\n\t\t\t\t\tvUv = uv;\n\t\t\t\t\tvColor = color;\n\t\t\t\t\tgl_Position = projectionMatrix*modelViewMatrix*vec4(position,1.0);\n\t\t\t\t}\n\t\t\t";
+				var fragmentShader = "\n\t\t\t\tuniform sampler2D map;\n\t\t\t\tvarying vec2 vUv;\n\t\t\t\tvarying vec4 vColor;\n\t\t\t\tvoid main(void) {\n\t\t\t\t\tgl_FragColor = texture2D(map, vUv)*vColor;\n\t\t\t\t}\n\t\t\t";
+				var parameters = {
+					uniforms: {
+						map: { type: "t", value: null }
+					},
+					vertexShader: vertexShader,
+					fragmentShader: fragmentShader,
+					side: THREE.DoubleSide,
+					transparent: true,
+					alphaTest: 0.5
+				};
+				_this = _super.call(this, parameters) || this;
+				return _this;
+			}
+			;
+			return SkeletonMeshMaterial;
+		}(THREE.ShaderMaterial));
+		threejs.SkeletonMeshMaterial = SkeletonMeshMaterial;
 		var SkeletonMesh = (function (_super) {
 		var SkeletonMesh = (function (_super) {
 			__extends(SkeletonMesh, _super);
 			__extends(SkeletonMesh, _super);
 			function SkeletonMesh(skeletonData) {
 			function SkeletonMesh(skeletonData) {
@@ -9512,17 +9551,14 @@ var spine;
 				_this.tempLight = new spine.Color();
 				_this.tempLight = new spine.Color();
 				_this.tempDark = new spine.Color();
 				_this.tempDark = new spine.Color();
 				_this.zOffset = 0.1;
 				_this.zOffset = 0.1;
+				_this.batches = new Array();
+				_this.nextBatchIndex = 0;
 				_this.clipper = new spine.SkeletonClipping();
 				_this.clipper = new spine.SkeletonClipping();
 				_this.vertices = spine.Utils.newFloatArray(1024);
 				_this.vertices = spine.Utils.newFloatArray(1024);
 				_this.tempColor = new spine.Color();
 				_this.tempColor = new spine.Color();
 				_this.skeleton = new spine.Skeleton(skeletonData);
 				_this.skeleton = new spine.Skeleton(skeletonData);
 				var animData = new spine.AnimationStateData(skeletonData);
 				var animData = new spine.AnimationStateData(skeletonData);
 				_this.state = new spine.AnimationState(animData);
 				_this.state = new spine.AnimationState(animData);
-				var material = _this.material = new THREE.MeshBasicMaterial();
-				material.side = THREE.DoubleSide;
-				material.transparent = true;
-				material.alphaTest = 0.5;
-				_this.batcher = new threejs.MeshBatcher(_this);
 				return _this;
 				return _this;
 			}
 			}
 			SkeletonMesh.prototype.update = function (deltaTime) {
 			SkeletonMesh.prototype.update = function (deltaTime) {
@@ -9533,12 +9569,29 @@ var spine;
 				skeleton.updateWorldTransform();
 				skeleton.updateWorldTransform();
 				this.updateGeometry();
 				this.updateGeometry();
 			};
 			};
+			SkeletonMesh.prototype.clearBatches = function () {
+				for (var i = 0; i < this.batches.length; i++) {
+					this.batches[i].clear();
+					this.batches[i].visible = false;
+				}
+				this.nextBatchIndex = 0;
+			};
+			SkeletonMesh.prototype.nextBatch = function () {
+				if (this.batches.length == this.nextBatchIndex) {
+					var batch_1 = new threejs.MeshBatcher();
+					this.add(batch_1);
+					this.batches.push(batch_1);
+				}
+				var batch = this.batches[this.nextBatchIndex++];
+				batch.visible = true;
+				return batch;
+			};
 			SkeletonMesh.prototype.updateGeometry = function () {
 			SkeletonMesh.prototype.updateGeometry = function () {
+				this.clearBatches();
 				var tempPos = this.tempPos;
 				var tempPos = this.tempPos;
 				var tempUv = this.tempUv;
 				var tempUv = this.tempUv;
 				var tempLight = this.tempLight;
 				var tempLight = this.tempLight;
 				var tempDark = this.tempDark;
 				var tempDark = this.tempDark;
-				var geometry = this.geometry;
 				var numVertices = 0;
 				var numVertices = 0;
 				var verticesLength = 0;
 				var verticesLength = 0;
 				var indicesLength = 0;
 				var indicesLength = 0;
@@ -9548,8 +9601,8 @@ var spine;
 				var triangles = null;
 				var triangles = null;
 				var uvs = null;
 				var uvs = null;
 				var drawOrder = this.skeleton.drawOrder;
 				var drawOrder = this.skeleton.drawOrder;
-				var batcher = this.batcher;
-				batcher.begin();
+				var batch = this.nextBatch();
+				batch.begin();
 				var z = 0;
 				var z = 0;
 				var zOffset = this.zOffset;
 				var zOffset = this.zOffset;
 				for (var i = 0, n = drawOrder.length; i < n; i++) {
 				for (var i = 0, n = drawOrder.length; i < n; i++) {
@@ -9590,17 +9643,16 @@ var spine;
 					else
 					else
 						continue;
 						continue;
 					if (texture != null) {
 					if (texture != null) {
-						if (!this.material.map) {
-							var mat = this.material;
-							mat.map = texture.texture;
-							mat.needsUpdate = true;
-						}
 						var skeleton = slot.bone.skeleton;
 						var skeleton = slot.bone.skeleton;
 						var skeletonColor = skeleton.color;
 						var skeletonColor = skeleton.color;
 						var slotColor = slot.color;
 						var slotColor = slot.color;
 						var alpha = skeletonColor.a * slotColor.a * attachmentColor.a;
 						var alpha = skeletonColor.a * slotColor.a * attachmentColor.a;
 						var color = this.tempColor;
 						var color = this.tempColor;
 						color.set(skeletonColor.r * slotColor.r * attachmentColor.r, skeletonColor.g * slotColor.g * attachmentColor.g, skeletonColor.b * slotColor.b * attachmentColor.b, alpha);
 						color.set(skeletonColor.r * slotColor.r * attachmentColor.r, skeletonColor.g * slotColor.g * attachmentColor.g, skeletonColor.b * slotColor.b * attachmentColor.b, alpha);
+						var finalVertices = void 0;
+						var finalVerticesLength = void 0;
+						var finalIndices = void 0;
+						var finalIndicesLength = void 0;
 						if (clipper.isClipping()) {
 						if (clipper.isClipping()) {
 							clipper.clipTriangles(vertices, numFloats, triangles, triangles.length, uvs, color, null, false);
 							clipper.clipTriangles(vertices, numFloats, triangles, triangles.length, uvs, color, null, false);
 							var clippedVertices = clipper.clippedVertices;
 							var clippedVertices = clipper.clippedVertices;
@@ -9626,7 +9678,10 @@ var spine;
 									verts[v + 7] = tempUv.y;
 									verts[v + 7] = tempUv.y;
 								}
 								}
 							}
 							}
-							batcher.batch(clippedVertices, clippedVertices.length, clippedTriangles, clippedTriangles.length, z);
+							finalVertices = clippedVertices;
+							finalVerticesLength = clippedVertices.length;
+							finalIndices = clippedTriangles;
+							finalIndicesLength = clippedTriangles.length;
 						}
 						}
 						else {
 						else {
 							var verts = vertices;
 							var verts = vertices;
@@ -9660,15 +9715,40 @@ var spine;
 									verts[v + 5] = uvs[u + 1];
 									verts[v + 5] = uvs[u + 1];
 								}
 								}
 							}
 							}
-							batcher.batch(vertices, numFloats, triangles, triangles.length, z);
+							finalVertices = vertices;
+							finalVerticesLength = numFloats;
+							finalIndices = triangles;
+							finalIndicesLength = triangles.length;
 						}
 						}
+						if (finalVerticesLength == 0 || finalIndicesLength == 0)
+							continue;
+						if (!batch.canBatch(finalVerticesLength, finalIndicesLength)) {
+							batch.end();
+							batch = this.nextBatch();
+							batch.begin();
+						}
+						var batchMaterial = batch.material;
+						if (batchMaterial.uniforms.map.value == null) {
+							batchMaterial.uniforms.map.value = texture.texture;
+						}
+						if (batchMaterial.uniforms.map.value != texture.texture) {
+							batch.end();
+							batch = this.nextBatch();
+							batch.begin();
+							batchMaterial = batch.material;
+							batchMaterial.uniforms.map.value = texture.texture;
+						}
+						batchMaterial.needsUpdate = true;
+						batch.batch(finalVertices, finalVerticesLength, finalIndices, finalIndicesLength, z);
 						z += zOffset;
 						z += zOffset;
 					}
 					}
+					clipper.clipEndWithSlot(slot);
 				}
 				}
-				batcher.end();
+				clipper.clipEnd();
+				batch.end();
 			};
 			};
 			return SkeletonMesh;
 			return SkeletonMesh;
-		}(THREE.Mesh));
+		}(THREE.Object3D));
 		SkeletonMesh.QUAD_TRIANGLES = [0, 1, 2, 2, 3, 0];
 		SkeletonMesh.QUAD_TRIANGLES = [0, 1, 2, 2, 3, 0];
 		SkeletonMesh.VERTEX_SIZE = 2 + 2 + 4;
 		SkeletonMesh.VERTEX_SIZE = 2 + 2 + 4;
 		threejs.SkeletonMesh = SkeletonMesh;
 		threejs.SkeletonMesh = SkeletonMesh;

Diferenças do arquivo suprimidas por serem muito extensas
+ 0 - 0
spine-ts/build/spine-all.js.map


+ 5 - 5
spine-ts/build/spine-canvas.js

@@ -2001,6 +2001,7 @@ var spine;
 			path = this.pathPrefix + path;
 			path = this.pathPrefix + path;
 			this.toLoad++;
 			this.toLoad++;
 			AssetManager.downloadText(path, function (atlasData) {
 			AssetManager.downloadText(path, function (atlasData) {
+				var pagesLoaded = { count: 0 };
 				var atlasPages = new Array();
 				var atlasPages = new Array();
 				try {
 				try {
 					var atlas = new spine.TextureAtlas(atlasData, function (path) {
 					var atlas = new spine.TextureAtlas(atlasData, function (path) {
@@ -2021,11 +2022,10 @@ var spine;
 					return;
 					return;
 				}
 				}
 				var _loop_1 = function (atlasPage) {
 				var _loop_1 = function (atlasPage) {
-					var pagesLoaded = 0;
 					var pageLoadError = false;
 					var pageLoadError = false;
 					_this.loadTexture(atlasPage, function (imagePath, image) {
 					_this.loadTexture(atlasPage, function (imagePath, image) {
-						pagesLoaded++;
-						if (pagesLoaded == atlasPages.length) {
+						pagesLoaded.count++;
+						if (pagesLoaded.count == atlasPages.length) {
 							if (!pageLoadError) {
 							if (!pageLoadError) {
 								try {
 								try {
 									var atlas = new spine.TextureAtlas(atlasData, function (path) {
 									var atlas = new spine.TextureAtlas(atlasData, function (path) {
@@ -2056,8 +2056,8 @@ var spine;
 						}
 						}
 					}, function (imagePath, errorMessage) {
 					}, function (imagePath, errorMessage) {
 						pageLoadError = true;
 						pageLoadError = true;
-						pagesLoaded++;
-						if (pagesLoaded == atlasPages.length) {
+						pagesLoaded.count++;
+						if (pagesLoaded.count == atlasPages.length) {
 							_this.errors[path] = "Couldn't load texture atlas page " + imagePath + "} of atlas " + path;
 							_this.errors[path] = "Couldn't load texture atlas page " + imagePath + "} of atlas " + path;
 							if (error)
 							if (error)
 								error(path, "Couldn't load texture atlas page " + imagePath + " of atlas " + path);
 								error(path, "Couldn't load texture atlas page " + imagePath + " of atlas " + path);

Diferenças do arquivo suprimidas por serem muito extensas
+ 0 - 0
spine-ts/build/spine-canvas.js.map


+ 5 - 5
spine-ts/build/spine-core.js

@@ -2001,6 +2001,7 @@ var spine;
 			path = this.pathPrefix + path;
 			path = this.pathPrefix + path;
 			this.toLoad++;
 			this.toLoad++;
 			AssetManager.downloadText(path, function (atlasData) {
 			AssetManager.downloadText(path, function (atlasData) {
+				var pagesLoaded = { count: 0 };
 				var atlasPages = new Array();
 				var atlasPages = new Array();
 				try {
 				try {
 					var atlas = new spine.TextureAtlas(atlasData, function (path) {
 					var atlas = new spine.TextureAtlas(atlasData, function (path) {
@@ -2021,11 +2022,10 @@ var spine;
 					return;
 					return;
 				}
 				}
 				var _loop_1 = function (atlasPage) {
 				var _loop_1 = function (atlasPage) {
-					var pagesLoaded = 0;
 					var pageLoadError = false;
 					var pageLoadError = false;
 					_this.loadTexture(atlasPage, function (imagePath, image) {
 					_this.loadTexture(atlasPage, function (imagePath, image) {
-						pagesLoaded++;
-						if (pagesLoaded == atlasPages.length) {
+						pagesLoaded.count++;
+						if (pagesLoaded.count == atlasPages.length) {
 							if (!pageLoadError) {
 							if (!pageLoadError) {
 								try {
 								try {
 									var atlas = new spine.TextureAtlas(atlasData, function (path) {
 									var atlas = new spine.TextureAtlas(atlasData, function (path) {
@@ -2056,8 +2056,8 @@ var spine;
 						}
 						}
 					}, function (imagePath, errorMessage) {
 					}, function (imagePath, errorMessage) {
 						pageLoadError = true;
 						pageLoadError = true;
-						pagesLoaded++;
-						if (pagesLoaded == atlasPages.length) {
+						pagesLoaded.count++;
+						if (pagesLoaded.count == atlasPages.length) {
 							_this.errors[path] = "Couldn't load texture atlas page " + imagePath + "} of atlas " + path;
 							_this.errors[path] = "Couldn't load texture atlas page " + imagePath + "} of atlas " + path;
 							if (error)
 							if (error)
 								error(path, "Couldn't load texture atlas page " + imagePath + " of atlas " + path);
 								error(path, "Couldn't load texture atlas page " + imagePath + " of atlas " + path);

Diferenças do arquivo suprimidas por serem muito extensas
+ 0 - 0
spine-ts/build/spine-core.js.map


+ 12 - 5
spine-ts/build/spine-threejs.d.ts

@@ -1235,22 +1235,26 @@ declare module spine.threejs {
 	}
 	}
 }
 }
 declare module spine.threejs {
 declare module spine.threejs {
-	class MeshBatcher {
-		mesh: THREE.Mesh;
+	class MeshBatcher extends THREE.Mesh {
 		private static VERTEX_SIZE;
 		private static VERTEX_SIZE;
 		private vertexBuffer;
 		private vertexBuffer;
 		private vertices;
 		private vertices;
 		private verticesLength;
 		private verticesLength;
 		private indices;
 		private indices;
 		private indicesLength;
 		private indicesLength;
-		constructor(mesh: THREE.Mesh, maxVertices?: number);
+		constructor(maxVertices?: number);
+		clear(): void;
 		begin(): void;
 		begin(): void;
+		canBatch(verticesLength: number, indicesLength: number): boolean;
 		batch(vertices: ArrayLike<number>, verticesLength: number, indices: ArrayLike<number>, indicesLength: number, z?: number): void;
 		batch(vertices: ArrayLike<number>, verticesLength: number, indices: ArrayLike<number>, indicesLength: number, z?: number): void;
 		end(): void;
 		end(): void;
 	}
 	}
 }
 }
 declare module spine.threejs {
 declare module spine.threejs {
-	class SkeletonMesh extends THREE.Mesh {
+	class SkeletonMeshMaterial extends THREE.ShaderMaterial {
+		constructor();
+	}
+	class SkeletonMesh extends THREE.Object3D {
 		tempPos: Vector2;
 		tempPos: Vector2;
 		tempUv: Vector2;
 		tempUv: Vector2;
 		tempLight: Color;
 		tempLight: Color;
@@ -1259,7 +1263,8 @@ declare module spine.threejs {
 		state: AnimationState;
 		state: AnimationState;
 		zOffset: number;
 		zOffset: number;
 		vertexEffect: VertexEffect;
 		vertexEffect: VertexEffect;
-		private batcher;
+		private batches;
+		private nextBatchIndex;
 		private clipper;
 		private clipper;
 		static QUAD_TRIANGLES: number[];
 		static QUAD_TRIANGLES: number[];
 		static VERTEX_SIZE: number;
 		static VERTEX_SIZE: number;
@@ -1267,6 +1272,8 @@ declare module spine.threejs {
 		private tempColor;
 		private tempColor;
 		constructor(skeletonData: SkeletonData);
 		constructor(skeletonData: SkeletonData);
 		update(deltaTime: number): void;
 		update(deltaTime: number): void;
+		private clearBatches();
+		private nextBatch();
 		private updateGeometry();
 		private updateGeometry();
 	}
 	}
 }
 }

+ 113 - 33
spine-ts/build/spine-threejs.js

@@ -2001,6 +2001,7 @@ var spine;
 			path = this.pathPrefix + path;
 			path = this.pathPrefix + path;
 			this.toLoad++;
 			this.toLoad++;
 			AssetManager.downloadText(path, function (atlasData) {
 			AssetManager.downloadText(path, function (atlasData) {
+				var pagesLoaded = { count: 0 };
 				var atlasPages = new Array();
 				var atlasPages = new Array();
 				try {
 				try {
 					var atlas = new spine.TextureAtlas(atlasData, function (path) {
 					var atlas = new spine.TextureAtlas(atlasData, function (path) {
@@ -2021,11 +2022,10 @@ var spine;
 					return;
 					return;
 				}
 				}
 				var _loop_1 = function (atlasPage) {
 				var _loop_1 = function (atlasPage) {
-					var pagesLoaded = 0;
 					var pageLoadError = false;
 					var pageLoadError = false;
 					_this.loadTexture(atlasPage, function (imagePath, image) {
 					_this.loadTexture(atlasPage, function (imagePath, image) {
-						pagesLoaded++;
-						if (pagesLoaded == atlasPages.length) {
+						pagesLoaded.count++;
+						if (pagesLoaded.count == atlasPages.length) {
 							if (!pageLoadError) {
 							if (!pageLoadError) {
 								try {
 								try {
 									var atlas = new spine.TextureAtlas(atlasData, function (path) {
 									var atlas = new spine.TextureAtlas(atlasData, function (path) {
@@ -2056,8 +2056,8 @@ var spine;
 						}
 						}
 					}, function (imagePath, errorMessage) {
 					}, function (imagePath, errorMessage) {
 						pageLoadError = true;
 						pageLoadError = true;
-						pagesLoaded++;
-						if (pagesLoaded == atlasPages.length) {
+						pagesLoaded.count++;
+						if (pagesLoaded.count == atlasPages.length) {
 							_this.errors[path] = "Couldn't load texture atlas page " + imagePath + "} of atlas " + path;
 							_this.errors[path] = "Couldn't load texture atlas page " + imagePath + "} of atlas " + path;
 							if (error)
 							if (error)
 								error(path, "Couldn't load texture atlas page " + imagePath + " of atlas " + path);
 								error(path, "Couldn't load texture atlas page " + imagePath + " of atlas " + path);
@@ -6604,18 +6604,19 @@ var spine;
 (function (spine) {
 (function (spine) {
 	var threejs;
 	var threejs;
 	(function (threejs) {
 	(function (threejs) {
-		var MeshBatcher = (function () {
-			function MeshBatcher(mesh, maxVertices) {
+		var MeshBatcher = (function (_super) {
+			__extends(MeshBatcher, _super);
+			function MeshBatcher(maxVertices) {
 				if (maxVertices === void 0) { maxVertices = 10920; }
 				if (maxVertices === void 0) { maxVertices = 10920; }
-				this.verticesLength = 0;
-				this.indicesLength = 0;
+				var _this = _super.call(this) || this;
+				_this.verticesLength = 0;
+				_this.indicesLength = 0;
 				if (maxVertices > 10920)
 				if (maxVertices > 10920)
 					throw new Error("Can't have more than 10920 triangles per batch: " + maxVertices);
 					throw new Error("Can't have more than 10920 triangles per batch: " + maxVertices);
-				var vertices = this.vertices = new Float32Array(maxVertices * MeshBatcher.VERTEX_SIZE);
-				var indices = this.indices = new Uint16Array(maxVertices * 3);
-				this.mesh = mesh;
+				var vertices = _this.vertices = new Float32Array(maxVertices * MeshBatcher.VERTEX_SIZE);
+				var indices = _this.indices = new Uint16Array(maxVertices * 3);
 				var geo = new THREE.BufferGeometry();
 				var geo = new THREE.BufferGeometry();
-				var vertexBuffer = this.vertexBuffer = new THREE.InterleavedBuffer(vertices, MeshBatcher.VERTEX_SIZE);
+				var vertexBuffer = _this.vertexBuffer = new THREE.InterleavedBuffer(vertices, MeshBatcher.VERTEX_SIZE);
 				vertexBuffer.dynamic = true;
 				vertexBuffer.dynamic = true;
 				geo.addAttribute("position", new THREE.InterleavedBufferAttribute(vertexBuffer, 3, 0, false));
 				geo.addAttribute("position", new THREE.InterleavedBufferAttribute(vertexBuffer, 3, 0, false));
 				geo.addAttribute("color", new THREE.InterleavedBufferAttribute(vertexBuffer, 4, 3, false));
 				geo.addAttribute("color", new THREE.InterleavedBufferAttribute(vertexBuffer, 4, 3, false));
@@ -6624,12 +6625,27 @@ var spine;
 				geo.getIndex().dynamic = true;
 				geo.getIndex().dynamic = true;
 				geo.drawRange.start = 0;
 				geo.drawRange.start = 0;
 				geo.drawRange.count = 0;
 				geo.drawRange.count = 0;
-				mesh.geometry = geo;
+				_this.geometry = geo;
+				_this.material = new threejs.SkeletonMeshMaterial();
+				return _this;
 			}
 			}
+			MeshBatcher.prototype.clear = function () {
+				var geo = this.geometry;
+				geo.drawRange.start = 0;
+				geo.drawRange.count = 0;
+				this.material.uniforms.map.value = null;
+			};
 			MeshBatcher.prototype.begin = function () {
 			MeshBatcher.prototype.begin = function () {
 				this.verticesLength = 0;
 				this.verticesLength = 0;
 				this.indicesLength = 0;
 				this.indicesLength = 0;
 			};
 			};
+			MeshBatcher.prototype.canBatch = function (verticesLength, indicesLength) {
+				if (this.indicesLength + indicesLength >= this.indices.byteLength / 2)
+					return false;
+				if (this.verticesLength + verticesLength >= this.vertices.byteLength / 2)
+					return false;
+				return true;
+			};
 			MeshBatcher.prototype.batch = function (vertices, verticesLength, indices, indicesLength, z) {
 			MeshBatcher.prototype.batch = function (vertices, verticesLength, indices, indicesLength, z) {
 				if (z === void 0) { z = 0; }
 				if (z === void 0) { z = 0; }
 				var indexStart = this.verticesLength / MeshBatcher.VERTEX_SIZE;
 				var indexStart = this.verticesLength / MeshBatcher.VERTEX_SIZE;
@@ -6657,7 +6673,7 @@ var spine;
 				this.vertexBuffer.needsUpdate = true;
 				this.vertexBuffer.needsUpdate = true;
 				this.vertexBuffer.updateRange.offset = 0;
 				this.vertexBuffer.updateRange.offset = 0;
 				this.vertexBuffer.updateRange.count = this.verticesLength;
 				this.vertexBuffer.updateRange.count = this.verticesLength;
-				var geo = this.mesh.geometry;
+				var geo = this.geometry;
 				geo.getIndex().needsUpdate = true;
 				geo.getIndex().needsUpdate = true;
 				geo.getIndex().updateRange.offset = 0;
 				geo.getIndex().updateRange.offset = 0;
 				geo.getIndex().updateRange.count = this.indicesLength;
 				geo.getIndex().updateRange.count = this.indicesLength;
@@ -6665,7 +6681,7 @@ var spine;
 				geo.drawRange.count = this.indicesLength;
 				geo.drawRange.count = this.indicesLength;
 			};
 			};
 			return MeshBatcher;
 			return MeshBatcher;
-		}());
+		}(THREE.Mesh));
 		MeshBatcher.VERTEX_SIZE = 9;
 		MeshBatcher.VERTEX_SIZE = 9;
 		threejs.MeshBatcher = MeshBatcher;
 		threejs.MeshBatcher = MeshBatcher;
 	})(threejs = spine.threejs || (spine.threejs = {}));
 	})(threejs = spine.threejs || (spine.threejs = {}));
@@ -6674,6 +6690,29 @@ var spine;
 (function (spine) {
 (function (spine) {
 	var threejs;
 	var threejs;
 	(function (threejs) {
 	(function (threejs) {
+		var SkeletonMeshMaterial = (function (_super) {
+			__extends(SkeletonMeshMaterial, _super);
+			function SkeletonMeshMaterial() {
+				var _this = this;
+				var vertexShader = "\n\t\t\t\tattribute vec4 color;\n\t\t\t\tvarying vec2 vUv;\n\t\t\t\tvarying vec4 vColor;\n\t\t\t\tvoid main() {\n\t\t\t\t\tvUv = uv;\n\t\t\t\t\tvColor = color;\n\t\t\t\t\tgl_Position = projectionMatrix*modelViewMatrix*vec4(position,1.0);\n\t\t\t\t}\n\t\t\t";
+				var fragmentShader = "\n\t\t\t\tuniform sampler2D map;\n\t\t\t\tvarying vec2 vUv;\n\t\t\t\tvarying vec4 vColor;\n\t\t\t\tvoid main(void) {\n\t\t\t\t\tgl_FragColor = texture2D(map, vUv)*vColor;\n\t\t\t\t}\n\t\t\t";
+				var parameters = {
+					uniforms: {
+						map: { type: "t", value: null }
+					},
+					vertexShader: vertexShader,
+					fragmentShader: fragmentShader,
+					side: THREE.DoubleSide,
+					transparent: true,
+					alphaTest: 0.5
+				};
+				_this = _super.call(this, parameters) || this;
+				return _this;
+			}
+			;
+			return SkeletonMeshMaterial;
+		}(THREE.ShaderMaterial));
+		threejs.SkeletonMeshMaterial = SkeletonMeshMaterial;
 		var SkeletonMesh = (function (_super) {
 		var SkeletonMesh = (function (_super) {
 			__extends(SkeletonMesh, _super);
 			__extends(SkeletonMesh, _super);
 			function SkeletonMesh(skeletonData) {
 			function SkeletonMesh(skeletonData) {
@@ -6683,17 +6722,14 @@ var spine;
 				_this.tempLight = new spine.Color();
 				_this.tempLight = new spine.Color();
 				_this.tempDark = new spine.Color();
 				_this.tempDark = new spine.Color();
 				_this.zOffset = 0.1;
 				_this.zOffset = 0.1;
+				_this.batches = new Array();
+				_this.nextBatchIndex = 0;
 				_this.clipper = new spine.SkeletonClipping();
 				_this.clipper = new spine.SkeletonClipping();
 				_this.vertices = spine.Utils.newFloatArray(1024);
 				_this.vertices = spine.Utils.newFloatArray(1024);
 				_this.tempColor = new spine.Color();
 				_this.tempColor = new spine.Color();
 				_this.skeleton = new spine.Skeleton(skeletonData);
 				_this.skeleton = new spine.Skeleton(skeletonData);
 				var animData = new spine.AnimationStateData(skeletonData);
 				var animData = new spine.AnimationStateData(skeletonData);
 				_this.state = new spine.AnimationState(animData);
 				_this.state = new spine.AnimationState(animData);
-				var material = _this.material = new THREE.MeshBasicMaterial();
-				material.side = THREE.DoubleSide;
-				material.transparent = true;
-				material.alphaTest = 0.5;
-				_this.batcher = new threejs.MeshBatcher(_this);
 				return _this;
 				return _this;
 			}
 			}
 			SkeletonMesh.prototype.update = function (deltaTime) {
 			SkeletonMesh.prototype.update = function (deltaTime) {
@@ -6704,12 +6740,29 @@ var spine;
 				skeleton.updateWorldTransform();
 				skeleton.updateWorldTransform();
 				this.updateGeometry();
 				this.updateGeometry();
 			};
 			};
+			SkeletonMesh.prototype.clearBatches = function () {
+				for (var i = 0; i < this.batches.length; i++) {
+					this.batches[i].clear();
+					this.batches[i].visible = false;
+				}
+				this.nextBatchIndex = 0;
+			};
+			SkeletonMesh.prototype.nextBatch = function () {
+				if (this.batches.length == this.nextBatchIndex) {
+					var batch_1 = new threejs.MeshBatcher();
+					this.add(batch_1);
+					this.batches.push(batch_1);
+				}
+				var batch = this.batches[this.nextBatchIndex++];
+				batch.visible = true;
+				return batch;
+			};
 			SkeletonMesh.prototype.updateGeometry = function () {
 			SkeletonMesh.prototype.updateGeometry = function () {
+				this.clearBatches();
 				var tempPos = this.tempPos;
 				var tempPos = this.tempPos;
 				var tempUv = this.tempUv;
 				var tempUv = this.tempUv;
 				var tempLight = this.tempLight;
 				var tempLight = this.tempLight;
 				var tempDark = this.tempDark;
 				var tempDark = this.tempDark;
-				var geometry = this.geometry;
 				var numVertices = 0;
 				var numVertices = 0;
 				var verticesLength = 0;
 				var verticesLength = 0;
 				var indicesLength = 0;
 				var indicesLength = 0;
@@ -6719,8 +6772,8 @@ var spine;
 				var triangles = null;
 				var triangles = null;
 				var uvs = null;
 				var uvs = null;
 				var drawOrder = this.skeleton.drawOrder;
 				var drawOrder = this.skeleton.drawOrder;
-				var batcher = this.batcher;
-				batcher.begin();
+				var batch = this.nextBatch();
+				batch.begin();
 				var z = 0;
 				var z = 0;
 				var zOffset = this.zOffset;
 				var zOffset = this.zOffset;
 				for (var i = 0, n = drawOrder.length; i < n; i++) {
 				for (var i = 0, n = drawOrder.length; i < n; i++) {
@@ -6761,17 +6814,16 @@ var spine;
 					else
 					else
 						continue;
 						continue;
 					if (texture != null) {
 					if (texture != null) {
-						if (!this.material.map) {
-							var mat = this.material;
-							mat.map = texture.texture;
-							mat.needsUpdate = true;
-						}
 						var skeleton = slot.bone.skeleton;
 						var skeleton = slot.bone.skeleton;
 						var skeletonColor = skeleton.color;
 						var skeletonColor = skeleton.color;
 						var slotColor = slot.color;
 						var slotColor = slot.color;
 						var alpha = skeletonColor.a * slotColor.a * attachmentColor.a;
 						var alpha = skeletonColor.a * slotColor.a * attachmentColor.a;
 						var color = this.tempColor;
 						var color = this.tempColor;
 						color.set(skeletonColor.r * slotColor.r * attachmentColor.r, skeletonColor.g * slotColor.g * attachmentColor.g, skeletonColor.b * slotColor.b * attachmentColor.b, alpha);
 						color.set(skeletonColor.r * slotColor.r * attachmentColor.r, skeletonColor.g * slotColor.g * attachmentColor.g, skeletonColor.b * slotColor.b * attachmentColor.b, alpha);
+						var finalVertices = void 0;
+						var finalVerticesLength = void 0;
+						var finalIndices = void 0;
+						var finalIndicesLength = void 0;
 						if (clipper.isClipping()) {
 						if (clipper.isClipping()) {
 							clipper.clipTriangles(vertices, numFloats, triangles, triangles.length, uvs, color, null, false);
 							clipper.clipTriangles(vertices, numFloats, triangles, triangles.length, uvs, color, null, false);
 							var clippedVertices = clipper.clippedVertices;
 							var clippedVertices = clipper.clippedVertices;
@@ -6797,7 +6849,10 @@ var spine;
 									verts[v + 7] = tempUv.y;
 									verts[v + 7] = tempUv.y;
 								}
 								}
 							}
 							}
-							batcher.batch(clippedVertices, clippedVertices.length, clippedTriangles, clippedTriangles.length, z);
+							finalVertices = clippedVertices;
+							finalVerticesLength = clippedVertices.length;
+							finalIndices = clippedTriangles;
+							finalIndicesLength = clippedTriangles.length;
 						}
 						}
 						else {
 						else {
 							var verts = vertices;
 							var verts = vertices;
@@ -6831,15 +6886,40 @@ var spine;
 									verts[v + 5] = uvs[u + 1];
 									verts[v + 5] = uvs[u + 1];
 								}
 								}
 							}
 							}
-							batcher.batch(vertices, numFloats, triangles, triangles.length, z);
+							finalVertices = vertices;
+							finalVerticesLength = numFloats;
+							finalIndices = triangles;
+							finalIndicesLength = triangles.length;
 						}
 						}
+						if (finalVerticesLength == 0 || finalIndicesLength == 0)
+							continue;
+						if (!batch.canBatch(finalVerticesLength, finalIndicesLength)) {
+							batch.end();
+							batch = this.nextBatch();
+							batch.begin();
+						}
+						var batchMaterial = batch.material;
+						if (batchMaterial.uniforms.map.value == null) {
+							batchMaterial.uniforms.map.value = texture.texture;
+						}
+						if (batchMaterial.uniforms.map.value != texture.texture) {
+							batch.end();
+							batch = this.nextBatch();
+							batch.begin();
+							batchMaterial = batch.material;
+							batchMaterial.uniforms.map.value = texture.texture;
+						}
+						batchMaterial.needsUpdate = true;
+						batch.batch(finalVertices, finalVerticesLength, finalIndices, finalIndicesLength, z);
 						z += zOffset;
 						z += zOffset;
 					}
 					}
+					clipper.clipEndWithSlot(slot);
 				}
 				}
-				batcher.end();
+				clipper.clipEnd();
+				batch.end();
 			};
 			};
 			return SkeletonMesh;
 			return SkeletonMesh;
-		}(THREE.Mesh));
+		}(THREE.Object3D));
 		SkeletonMesh.QUAD_TRIANGLES = [0, 1, 2, 2, 3, 0];
 		SkeletonMesh.QUAD_TRIANGLES = [0, 1, 2, 2, 3, 0];
 		SkeletonMesh.VERTEX_SIZE = 2 + 2 + 4;
 		SkeletonMesh.VERTEX_SIZE = 2 + 2 + 4;
 		threejs.SkeletonMesh = SkeletonMesh;
 		threejs.SkeletonMesh = SkeletonMesh;

Diferenças do arquivo suprimidas por serem muito extensas
+ 0 - 0
spine-ts/build/spine-threejs.js.map


+ 5 - 5
spine-ts/build/spine-webgl.js

@@ -2001,6 +2001,7 @@ var spine;
 			path = this.pathPrefix + path;
 			path = this.pathPrefix + path;
 			this.toLoad++;
 			this.toLoad++;
 			AssetManager.downloadText(path, function (atlasData) {
 			AssetManager.downloadText(path, function (atlasData) {
+				var pagesLoaded = { count: 0 };
 				var atlasPages = new Array();
 				var atlasPages = new Array();
 				try {
 				try {
 					var atlas = new spine.TextureAtlas(atlasData, function (path) {
 					var atlas = new spine.TextureAtlas(atlasData, function (path) {
@@ -2021,11 +2022,10 @@ var spine;
 					return;
 					return;
 				}
 				}
 				var _loop_1 = function (atlasPage) {
 				var _loop_1 = function (atlasPage) {
-					var pagesLoaded = 0;
 					var pageLoadError = false;
 					var pageLoadError = false;
 					_this.loadTexture(atlasPage, function (imagePath, image) {
 					_this.loadTexture(atlasPage, function (imagePath, image) {
-						pagesLoaded++;
-						if (pagesLoaded == atlasPages.length) {
+						pagesLoaded.count++;
+						if (pagesLoaded.count == atlasPages.length) {
 							if (!pageLoadError) {
 							if (!pageLoadError) {
 								try {
 								try {
 									var atlas = new spine.TextureAtlas(atlasData, function (path) {
 									var atlas = new spine.TextureAtlas(atlasData, function (path) {
@@ -2056,8 +2056,8 @@ var spine;
 						}
 						}
 					}, function (imagePath, errorMessage) {
 					}, function (imagePath, errorMessage) {
 						pageLoadError = true;
 						pageLoadError = true;
-						pagesLoaded++;
-						if (pagesLoaded == atlasPages.length) {
+						pagesLoaded.count++;
+						if (pagesLoaded.count == atlasPages.length) {
 							_this.errors[path] = "Couldn't load texture atlas page " + imagePath + "} of atlas " + path;
 							_this.errors[path] = "Couldn't load texture atlas page " + imagePath + "} of atlas " + path;
 							if (error)
 							if (error)
 								error(path, "Couldn't load texture atlas page " + imagePath + " of atlas " + path);
 								error(path, "Couldn't load texture atlas page " + imagePath + " of atlas " + path);

Diferenças do arquivo suprimidas por serem muito extensas
+ 0 - 0
spine-ts/build/spine-webgl.js.map


+ 5 - 5
spine-ts/build/spine-widget.js

@@ -2001,6 +2001,7 @@ var spine;
 			path = this.pathPrefix + path;
 			path = this.pathPrefix + path;
 			this.toLoad++;
 			this.toLoad++;
 			AssetManager.downloadText(path, function (atlasData) {
 			AssetManager.downloadText(path, function (atlasData) {
+				var pagesLoaded = { count: 0 };
 				var atlasPages = new Array();
 				var atlasPages = new Array();
 				try {
 				try {
 					var atlas = new spine.TextureAtlas(atlasData, function (path) {
 					var atlas = new spine.TextureAtlas(atlasData, function (path) {
@@ -2021,11 +2022,10 @@ var spine;
 					return;
 					return;
 				}
 				}
 				var _loop_1 = function (atlasPage) {
 				var _loop_1 = function (atlasPage) {
-					var pagesLoaded = 0;
 					var pageLoadError = false;
 					var pageLoadError = false;
 					_this.loadTexture(atlasPage, function (imagePath, image) {
 					_this.loadTexture(atlasPage, function (imagePath, image) {
-						pagesLoaded++;
-						if (pagesLoaded == atlasPages.length) {
+						pagesLoaded.count++;
+						if (pagesLoaded.count == atlasPages.length) {
 							if (!pageLoadError) {
 							if (!pageLoadError) {
 								try {
 								try {
 									var atlas = new spine.TextureAtlas(atlasData, function (path) {
 									var atlas = new spine.TextureAtlas(atlasData, function (path) {
@@ -2056,8 +2056,8 @@ var spine;
 						}
 						}
 					}, function (imagePath, errorMessage) {
 					}, function (imagePath, errorMessage) {
 						pageLoadError = true;
 						pageLoadError = true;
-						pagesLoaded++;
-						if (pagesLoaded == atlasPages.length) {
+						pagesLoaded.count++;
+						if (pagesLoaded.count == atlasPages.length) {
 							_this.errors[path] = "Couldn't load texture atlas page " + imagePath + "} of atlas " + path;
 							_this.errors[path] = "Couldn't load texture atlas page " + imagePath + "} of atlas " + path;
 							if (error)
 							if (error)
 								error(path, "Couldn't load texture atlas page " + imagePath + " of atlas " + path);
 								error(path, "Couldn't load texture atlas page " + imagePath + " of atlas " + path);

Diferenças do arquivo suprimidas por serem muito extensas
+ 0 - 0
spine-ts/build/spine-widget.js.map


+ 5 - 5
spine-ts/core/src/AssetManager.ts

@@ -147,6 +147,7 @@ module spine {
 			this.toLoad++;
 			this.toLoad++;
 
 
 			AssetManager.downloadText(path, (atlasData: string): void => {
 			AssetManager.downloadText(path, (atlasData: string): void => {
+				var pagesLoaded: any = { count: 0 };
 				var atlasPages = new Array<string>();
 				var atlasPages = new Array<string>();
 				try {
 				try {
 					let atlas = new spine.TextureAtlas(atlasData, (path: string) => {
 					let atlas = new spine.TextureAtlas(atlasData, (path: string) => {
@@ -166,12 +167,11 @@ module spine {
 				}
 				}
 
 
 				for (let atlasPage of atlasPages) {
 				for (let atlasPage of atlasPages) {
-					let pagesLoaded = 0;
 					let pageLoadError = false;
 					let pageLoadError = false;
 					this.loadTexture(atlasPage, (imagePath: string, image: HTMLImageElement) => {
 					this.loadTexture(atlasPage, (imagePath: string, image: HTMLImageElement) => {
-						pagesLoaded++;
+						pagesLoaded.count++;
 
 
-						if (pagesLoaded == atlasPages.length) {
+						if (pagesLoaded.count == atlasPages.length) {
 							if (!pageLoadError) {
 							if (!pageLoadError) {
 								try {
 								try {
 									let atlas = new spine.TextureAtlas(atlasData, (path: string) => {
 									let atlas = new spine.TextureAtlas(atlasData, (path: string) => {
@@ -197,9 +197,9 @@ module spine {
 						}
 						}
 					}, (imagePath: string, errorMessage: string) => {
 					}, (imagePath: string, errorMessage: string) => {
 						pageLoadError = true;
 						pageLoadError = true;
-						pagesLoaded++;
+						pagesLoaded.count++;
 
 
-						if (pagesLoaded == atlasPages.length) {
+						if (pagesLoaded.count == atlasPages.length) {
 							this.errors[path] = `Couldn't load texture atlas page ${imagePath}} of atlas ${path}`;
 							this.errors[path] = `Couldn't load texture atlas page ${imagePath}} of atlas ${path}`;
 							if (error) error(path, `Couldn't load texture atlas page ${imagePath} of atlas ${path}`);
 							if (error) error(path, `Couldn't load texture atlas page ${imagePath} of atlas ${path}`);
 							this.toLoad--;
 							this.toLoad--;

+ 20 - 28
spine-ts/threejs/example/index.html

@@ -19,6 +19,11 @@ var assetManager;
 var canvas;
 var canvas;
 var lastFrameTime = Date.now() / 1000;
 var lastFrameTime = Date.now() / 1000;
 
 
+var baseUrl = "assets/";
+var skeletonFile = "raptor-pro.json";
+var atlasFile = skeletonFile.replace("-pro", "").replace("-ess", "").replace(".json", ".atlas");
+var animation = "walk";
+
 function init () {
 function init () {
 	// create the THREE.JS camera, scene and renderer (WebGL)
 	// create the THREE.JS camera, scene and renderer (WebGL)
 	var width = window.innerWidth, height = window.innerHeight;
 	var width = window.innerWidth, height = window.innerHeight;
@@ -32,10 +37,9 @@ function init () {
 	canvas = renderer.domElement;
 	canvas = renderer.domElement;
 
 
 	// load the assets required to display the Raptor model
 	// load the assets required to display the Raptor model
-	assetManager = new spine.threejs.AssetManager();
-	assetManager.loadText("assets/raptor-pro.json");
-	assetManager.loadText("assets/raptor.atlas");
-	assetManager.loadTexture("assets/raptor.png");
+	assetManager = new spine.threejs.AssetManager(baseUrl);
+	assetManager.loadText(skeletonFile);
+	assetManager.loadTextureAtlas(atlasFile);
 
 
 	requestAnimationFrame(load);
 	requestAnimationFrame(load);
 }
 }
@@ -50,39 +54,27 @@ function load (name, scale) {
 
 
 		// Load the texture atlas using name.atlas and name.png from the AssetManager.
 		// Load the texture atlas using name.atlas and name.png from the AssetManager.
 		// The function passed to TextureAtlas is used to resolve relative paths.
 		// The function passed to TextureAtlas is used to resolve relative paths.
-		atlas = new spine.TextureAtlas(assetManager.get("assets/raptor.atlas"), function(path) {
-			return assetManager.get("assets/" + path);
-		});
-		var skeletonData = loadSkeleton("raptor-pro", 0.4);
+		atlas = assetManager.get(atlasFile);
+
+		// Create a AtlasAttachmentLoader that resolves region, mesh, boundingbox and path attachments
+		atlasLoader = new spine.AtlasAttachmentLoader(atlas);
+
+		// Create a SkeletonJson instance for parsing the .json file.
+		var skeletonJson = new spine.SkeletonJson(atlasLoader);
+
+		// Set the scale to apply during parsing, parse the file, and create a new skeleton.
+		skeletonJson.scale = 0.4;
+		var skeletonData = skeletonJson.readSkeletonData(assetManager.get(skeletonFile));
 
 
 		// Create a SkeletonMesh from the data and attach it to the scene
 		// Create a SkeletonMesh from the data and attach it to the scene
 		skeletonMesh = new spine.threejs.SkeletonMesh(skeletonData);
 		skeletonMesh = new spine.threejs.SkeletonMesh(skeletonData);
-		skeletonMesh.state.setAnimation(0, "walk", true);
+		skeletonMesh.state.setAnimation(0, animation, true);
 		mesh.add(skeletonMesh);
 		mesh.add(skeletonMesh);
 
 
 		requestAnimationFrame(render);
 		requestAnimationFrame(render);
 	} else requestAnimationFrame(load);
 	} else requestAnimationFrame(load);
 }
 }
 
 
-function loadSkeleton (name, scale) {
-	// Load the texture atlas using name.atlas and name.png from the AssetManager.
-	// The function passed to TextureAtlas is used to resolve relative paths.
-	atlas = new spine.TextureAtlas(assetManager.get("assets/" + name.replace("-pro", "") + ".atlas"), function(path) {
-		return assetManager.get("assets/" + path);
-	});
-
-	// Create a AtlasAttachmentLoader that resolves region, mesh, boundingbox and path attachments
-	atlasLoader = new spine.AtlasAttachmentLoader(atlas);
-
-	// Create a SkeletonJson instance for parsing the .json file.
-	var skeletonJson = new spine.SkeletonJson(atlasLoader);
-
-	// Set the scale to apply during parsing, parse the file, and create a new skeleton.
-	skeletonJson.scale = scale;
-	var skeletonData = skeletonJson.readSkeletonData(assetManager.get("assets/" + name + ".json"));
-	return skeletonData;
-}
-
 var lastTime = Date.now();
 var lastTime = Date.now();
 function render() {
 function render() {
 	// calculate delta time for animation purposes
 	// calculate delta time for animation purposes

+ 19 - 8
spine-ts/threejs/src/MeshBatcher.ts

@@ -29,9 +29,7 @@
  *****************************************************************************/
  *****************************************************************************/
 
 
 module spine.threejs {
 module spine.threejs {
-	export class MeshBatcher {
-		mesh: THREE.Mesh;
-
+	export class MeshBatcher extends THREE.Mesh {
 		private static VERTEX_SIZE = 9;
 		private static VERTEX_SIZE = 9;
 		private vertexBuffer: THREE.InterleavedBuffer;
 		private vertexBuffer: THREE.InterleavedBuffer;
 		private vertices: Float32Array;
 		private vertices: Float32Array;
@@ -39,12 +37,11 @@ module spine.threejs {
 		private indices: Uint16Array;
 		private indices: Uint16Array;
 		private indicesLength = 0;
 		private indicesLength = 0;
 
 
-		constructor (mesh: THREE.Mesh, maxVertices: number = 10920) {
+		constructor (maxVertices: number = 10920) {
+			super();
 			if (maxVertices > 10920) throw new Error("Can't have more than 10920 triangles per batch: " + maxVertices);
 			if (maxVertices > 10920) throw new Error("Can't have more than 10920 triangles per batch: " + maxVertices);
-
 			let vertices = this.vertices = new Float32Array(maxVertices * MeshBatcher.VERTEX_SIZE);
 			let vertices = this.vertices = new Float32Array(maxVertices * MeshBatcher.VERTEX_SIZE);
 			let indices = this.indices = new Uint16Array(maxVertices * 3);
 			let indices = this.indices = new Uint16Array(maxVertices * 3);
-			this.mesh = mesh;
 			let geo = new THREE.BufferGeometry();
 			let geo = new THREE.BufferGeometry();
 			let vertexBuffer = this.vertexBuffer = new THREE.InterleavedBuffer(vertices, MeshBatcher.VERTEX_SIZE);
 			let vertexBuffer = this.vertexBuffer = new THREE.InterleavedBuffer(vertices, MeshBatcher.VERTEX_SIZE);
 			vertexBuffer.dynamic = true;
 			vertexBuffer.dynamic = true;
@@ -55,7 +52,15 @@ module spine.threejs {
 			geo.getIndex().dynamic = true;
 			geo.getIndex().dynamic = true;
 			geo.drawRange.start = 0;
 			geo.drawRange.start = 0;
 			geo.drawRange.count = 0;
 			geo.drawRange.count = 0;
-			mesh.geometry = geo;
+			this.geometry = geo;
+			this.material = new SkeletonMeshMaterial();
+		}
+
+		clear () {
+			let geo = (<THREE.BufferGeometry>this.geometry);
+			geo.drawRange.start = 0;
+			geo.drawRange.count = 0;
+			(<SkeletonMeshMaterial>this.material).uniforms.map.value = null;
 		}
 		}
 
 
 		begin () {
 		begin () {
@@ -63,6 +68,12 @@ module spine.threejs {
 			this.indicesLength = 0;
 			this.indicesLength = 0;
 		}
 		}
 
 
+		canBatch(verticesLength: number, indicesLength: number) {
+			if (this.indicesLength + indicesLength >= this.indices.byteLength / 2) return false;
+			if (this.verticesLength + verticesLength >= this.vertices.byteLength / 2) return false;
+			return true;
+		}
+
 		batch (vertices: ArrayLike<number>, verticesLength: number, indices: ArrayLike<number>, indicesLength: number, z: number = 0) {
 		batch (vertices: ArrayLike<number>, verticesLength: number, indices: ArrayLike<number>, indicesLength: number, z: number = 0) {
 			let indexStart = this.verticesLength / MeshBatcher.VERTEX_SIZE;
 			let indexStart = this.verticesLength / MeshBatcher.VERTEX_SIZE;
 			let vertexBuffer = this.vertices;
 			let vertexBuffer = this.vertices;
@@ -91,7 +102,7 @@ module spine.threejs {
 			this.vertexBuffer.needsUpdate = true;
 			this.vertexBuffer.needsUpdate = true;
 			this.vertexBuffer.updateRange.offset = 0;
 			this.vertexBuffer.updateRange.offset = 0;
 			this.vertexBuffer.updateRange.count = this.verticesLength;
 			this.vertexBuffer.updateRange.count = this.verticesLength;
-			let geo = (<THREE.BufferGeometry>this.mesh.geometry);
+			let geo = (<THREE.BufferGeometry>this.geometry);
 			geo.getIndex().needsUpdate = true;
 			geo.getIndex().needsUpdate = true;
 			geo.getIndex().updateRange.offset = 0;
 			geo.getIndex().updateRange.offset = 0;
 			geo.getIndex().updateRange.count = this.indicesLength;
 			geo.getIndex().updateRange.count = this.indicesLength;

+ 110 - 27
spine-ts/threejs/src/SkeletonMesh.ts

@@ -29,7 +29,42 @@
  *****************************************************************************/
  *****************************************************************************/
 
 
 module spine.threejs {
 module spine.threejs {
-	export class SkeletonMesh extends THREE.Mesh {
+	export class SkeletonMeshMaterial extends THREE.ShaderMaterial {
+		constructor () {
+			let vertexShader = `
+				attribute vec4 color;
+				varying vec2 vUv;
+				varying vec4 vColor;
+				void main() {
+					vUv = uv;
+					vColor = color;
+					gl_Position = projectionMatrix*modelViewMatrix*vec4(position,1.0);
+				}
+			`;
+			let fragmentShader = `
+				uniform sampler2D map;
+				varying vec2 vUv;
+				varying vec4 vColor;
+				void main(void) {
+					gl_FragColor = texture2D(map, vUv)*vColor;
+				}
+			`;
+
+			let parameters: THREE.ShaderMaterialParameters = {
+				uniforms: {
+					map: { type: "t", value: null }
+				},
+				vertexShader: vertexShader,
+				fragmentShader: fragmentShader,
+				side: THREE.DoubleSide,
+				transparent: true,
+				alphaTest: 0.5
+			};
+			super(parameters);
+		};
+	}
+
+	export class SkeletonMesh extends THREE.Object3D {
 		tempPos: Vector2 = new Vector2();
 		tempPos: Vector2 = new Vector2();
 		tempUv: Vector2 = new Vector2();
 		tempUv: Vector2 = new Vector2();
 		tempLight = new Color();
 		tempLight = new Color();
@@ -39,7 +74,8 @@ module spine.threejs {
 		zOffset: number = 0.1;
 		zOffset: number = 0.1;
 		vertexEffect: VertexEffect;
 		vertexEffect: VertexEffect;
 
 
-		private batcher: MeshBatcher;
+		private batches = new Array<MeshBatcher>();
+		private nextBatchIndex = 0;
 		private clipper: SkeletonClipping = new SkeletonClipping();
 		private clipper: SkeletonClipping = new SkeletonClipping();
 
 
 		static QUAD_TRIANGLES = [0, 1, 2, 2, 3, 0];
 		static QUAD_TRIANGLES = [0, 1, 2, 2, 3, 0];
@@ -54,12 +90,6 @@ module spine.threejs {
 			this.skeleton = new Skeleton(skeletonData);
 			this.skeleton = new Skeleton(skeletonData);
 			let animData = new AnimationStateData(skeletonData);
 			let animData = new AnimationStateData(skeletonData);
 			this.state = new AnimationState(animData);
 			this.state = new AnimationState(animData);
-
-			let material = this.material = new THREE.MeshBasicMaterial();
-			material.side = THREE.DoubleSide;
-			material.transparent = true;
-			material.alphaTest = 0.5;
-			this.batcher = new MeshBatcher(this);
 		}
 		}
 
 
 		update(deltaTime: number) {
 		update(deltaTime: number) {
@@ -73,13 +103,33 @@ module spine.threejs {
 			this.updateGeometry();
 			this.updateGeometry();
 		}
 		}
 
 
+		private clearBatches () {
+			for (var i = 0; i < this.batches.length; i++) {
+				this.batches[i].clear();
+				this.batches[i].visible = false;
+			}
+			this.nextBatchIndex = 0;
+		}
+
+		private nextBatch () {
+			if (this.batches.length == this.nextBatchIndex) {
+				let batch = new MeshBatcher();
+				this.add(batch);
+				this.batches.push(batch);
+			}
+			let batch = this.batches[this.nextBatchIndex++];
+			batch.visible = true;
+			return batch;
+		}
+
 		private updateGeometry() {
 		private updateGeometry() {
+			this.clearBatches();
+
 			let tempPos = this.tempPos;
 			let tempPos = this.tempPos;
 			let tempUv = this.tempUv;
 			let tempUv = this.tempUv;
 			let tempLight = this.tempLight;
 			let tempLight = this.tempLight;
 			let tempDark = this.tempDark;
 			let tempDark = this.tempDark;
 
 
-			let geometry = <THREE.BufferGeometry>this.geometry;
 			var numVertices = 0;
 			var numVertices = 0;
 			var verticesLength = 0;
 			var verticesLength = 0;
 			var indicesLength = 0;
 			var indicesLength = 0;
@@ -91,8 +141,8 @@ module spine.threejs {
 			let triangles: Array<number> = null;
 			let triangles: Array<number> = null;
 			let uvs: ArrayLike<number> = null;
 			let uvs: ArrayLike<number> = null;
 			let drawOrder = this.skeleton.drawOrder;
 			let drawOrder = this.skeleton.drawOrder;
-			let batcher = this.batcher;
-			batcher.begin();
+			let batch = this.nextBatch();
+			batch.begin();
 			let z = 0;
 			let z = 0;
 			let zOffset = this.zOffset;
 			let zOffset = this.zOffset;
 			for (let i = 0, n = drawOrder.length; i < n; i++) {
 			for (let i = 0, n = drawOrder.length; i < n; i++) {
@@ -130,12 +180,6 @@ module spine.threejs {
 				} else continue;
 				} else continue;
 
 
 				if (texture != null) {
 				if (texture != null) {
-					if (!(<THREE.MeshBasicMaterial>this.material).map) {
-						let mat = <THREE.MeshBasicMaterial>this.material;
-						mat.map = texture.texture;
-						mat.needsUpdate = true;
-					}
-
 					let skeleton = slot.bone.skeleton;
 					let skeleton = slot.bone.skeleton;
 					let skeletonColor = skeleton.color;
 					let skeletonColor = skeleton.color;
 					let slotColor = slot.color;
 					let slotColor = slot.color;
@@ -145,12 +189,11 @@ module spine.threejs {
 							skeletonColor.g * slotColor.g * attachmentColor.g,
 							skeletonColor.g * slotColor.g * attachmentColor.g,
 							skeletonColor.b * slotColor.b * attachmentColor.b,
 							skeletonColor.b * slotColor.b * attachmentColor.b,
 							alpha);
 							alpha);
-					// FIXME per slot blending would require multiple material support
-					//let slotBlendMode = slot.data.blendMode;
-					//if (slotBlendMode != blendMode) {
-					//	blendMode = slotBlendMode;
-					//	batcher.setBlendMode(getSourceGLBlendMode(this._gl, blendMode, premultipliedAlpha), getDestGLBlendMode(this._gl, blendMode));
-					//}
+
+					let finalVertices: ArrayLike<number>;
+					let finalVerticesLength: number;
+					let finalIndices: ArrayLike<number>;
+					let finalIndicesLength: number;
 
 
 					if (clipper.isClipping()) {
 					if (clipper.isClipping()) {
 						clipper.clipTriangles(vertices, numFloats, triangles, triangles.length, uvs, color, null, false);
 						clipper.clipTriangles(vertices, numFloats, triangles, triangles.length, uvs, color, null, false);
@@ -177,7 +220,10 @@ module spine.threejs {
 								verts[v + 7] = tempUv.y;
 								verts[v + 7] = tempUv.y;
 							}
 							}
 						}
 						}
-						batcher.batch(clippedVertices, clippedVertices.length, clippedTriangles, clippedTriangles.length, z);
+						finalVertices = clippedVertices;
+						finalVerticesLength = clippedVertices.length;
+						finalIndices = clippedTriangles;
+						finalIndicesLength = clippedTriangles.length;
 					} else {
 					} else {
 						let verts = vertices;
 						let verts = vertices;
 						if (this.vertexEffect != null) {
 						if (this.vertexEffect != null) {
@@ -209,13 +255,50 @@ module spine.threejs {
 								verts[v + 5] = uvs[u + 1];
 								verts[v + 5] = uvs[u + 1];
 							}
 							}
 						}
 						}
-						batcher.batch(vertices, numFloats, triangles, triangles.length, z);
+						finalVertices = vertices;
+						finalVerticesLength = numFloats;
+						finalIndices = triangles;
+						finalIndicesLength = triangles.length;
+					}
+
+					if (finalVerticesLength == 0 || finalIndicesLength == 0)
+						continue;
+
+					// Start new batch if this one can't hold vertices/indices
+					if (!batch.canBatch(finalVerticesLength, finalIndicesLength)) {
+						batch.end();
+						batch = this.nextBatch();
+						batch.begin();
 					}
 					}
+
+					// FIXME per slot blending would require multiple material support
+					//let slotBlendMode = slot.data.blendMode;
+					//if (slotBlendMode != blendMode) {
+					//	blendMode = slotBlendMode;
+					//	batcher.setBlendMode(getSourceGLBlendMode(this._gl, blendMode, premultipliedAlpha), getDestGLBlendMode(this._gl, blendMode));
+					//}
+
+					let batchMaterial = <SkeletonMeshMaterial>batch.material;
+					if (batchMaterial.uniforms.map.value == null) {
+						batchMaterial.uniforms.map.value = texture.texture;
+					}
+					if (batchMaterial.uniforms.map.value != texture.texture) {
+						batch.end();
+						batch = this.nextBatch();
+						batch.begin();
+						batchMaterial = <SkeletonMeshMaterial>batch.material;
+						batchMaterial.uniforms.map.value = texture.texture;
+					}
+					batchMaterial.needsUpdate = true;
+
+					batch.batch(finalVertices, finalVerticesLength, finalIndices, finalIndicesLength, z);
 					z += zOffset;
 					z += zOffset;
 				}
 				}
-			}
 
 
-			batcher.end();
+				clipper.clipEndWithSlot(slot);
+			}
+			clipper.clipEnd();
+			batch.end();
 		}
 		}
 	}
 	}
 }
 }

Alguns arquivos não foram mostrados porque muitos arquivos mudaram nesse diff