Эх сурвалжийг харах

[ts] Added 2 color tinting support, made it default, barely a performance difference. You can disable it via the constructors of SceneRenderer, SkeletonRenderer and PolygonBatcher, depending on which level of granularity you use. Also fixed performance issue submitting geometry as STATIC_DRAW instead of DYNAMIC_DRAW. Fixed another performance issue regarding size of buffer data that's being updated.

badlogic 8 жил өмнө
parent
commit
9eb42b65f2

+ 26 - 6
spine-ts/build/spine-all.d.ts

@@ -1122,6 +1122,17 @@ declare module spine {
 		length: number;
 		[n: number]: T;
 	}
+	class WindowedMean {
+		values: Array<number>;
+		addedValues: number;
+		lastValue: number;
+		mean: number;
+		dirty: boolean;
+		constructor(windowSize?: number);
+		hasEnoughData(): boolean;
+		addValue(value: number): void;
+		getMean(): number;
+	}
 }
 declare module spine.threejs {
 	class AssetManager extends spine.AssetManager {
@@ -1322,6 +1333,7 @@ declare module spine.webgl {
 		numIndices(): number;
 		setIndicesLength(length: number): void;
 		getIndices(): Uint16Array;
+		getVertexSizeInFloats(): number;
 		constructor(gl: WebGLRenderingContext, attributes: VertexAttribute[], maxVertices: number, maxIndices: number);
 		setVertices(vertices: Array<number>): void;
 		setIndices(indices: Array<number>): void;
@@ -1350,6 +1362,9 @@ declare module spine.webgl {
 	class ColorAttribute extends VertexAttribute {
 		constructor();
 	}
+	class Color2Attribute extends VertexAttribute {
+		constructor();
+	}
 	enum VertexAttributeType {
 		Float = 0,
 	}
@@ -1366,7 +1381,7 @@ declare module spine.webgl {
 		private indicesLength;
 		private srcBlend;
 		private dstBlend;
-		constructor(gl: WebGLRenderingContext, maxVertices?: number);
+		constructor(gl: WebGLRenderingContext, twoColorTint?: boolean, maxVertices?: number);
 		begin(shader: Shader): void;
 		setBlendMode(srcBlend: number, dstBlend: number): void;
 		draw(texture: GLTexture, vertices: ArrayLike<number>, indices: Array<number>): void;
@@ -1391,7 +1406,7 @@ declare module spine.webgl {
 		private QUAD;
 		private QUAD_TRIANGLES;
 		private WHITE;
-		constructor(canvas: HTMLCanvasElement, gl: WebGLRenderingContext);
+		constructor(canvas: HTMLCanvasElement, gl: WebGLRenderingContext, twoColorTint?: boolean);
 		begin(): void;
 		drawSkeleton(skeleton: Skeleton, premultipliedAlpha?: boolean): void;
 		drawSkeletonDebug(skeleton: Skeleton, premultipliedAlpha?: boolean, ignoredBones?: Array<string>): void;
@@ -1424,6 +1439,7 @@ declare module spine.webgl {
 		static MVP_MATRIX: string;
 		static POSITION: string;
 		static COLOR: string;
+		static COLOR2: string;
 		static TEXCOORDS: string;
 		static SAMPLER: string;
 		private gl;
@@ -1454,6 +1470,7 @@ declare module spine.webgl {
 		getAttributeLocation(attribute: string): number;
 		dispose(): void;
 		static newColoredTextured(gl: WebGLRenderingContext): Shader;
+		static newTwoColorTextured(gl: WebGLRenderingContext): Shader;
 		static newColored(gl: WebGLRenderingContext): Shader;
 	}
 }
@@ -1527,16 +1544,19 @@ declare module spine.webgl {
 }
 declare module spine.webgl {
 	class SkeletonRenderer {
-		static VERTEX_SIZE: number;
 		static QUAD_TRIANGLES: number[];
 		premultipliedAlpha: boolean;
 		private gl;
 		private tempColor;
+		private tempColor2;
 		private vertices;
-		constructor(gl: WebGLRenderingContext);
+		private vertexSize;
+		private twoColorTint;
+		private renderable;
+		constructor(gl: WebGLRenderingContext, twoColorTint?: boolean);
 		draw(batcher: PolygonBatcher, skeleton: Skeleton): void;
-		computeRegionVertices(slot: Slot, region: RegionAttachment, pma: boolean): ArrayLike<number>;
-		computeMeshVertices(slot: Slot, mesh: MeshAttachment, pma: boolean): ArrayLike<number>;
+		private computeRegionVertices(slot, region, pma, twoColorTint?);
+		private computeMeshVertices(slot, mesh, pma, twoColorTint?);
 	}
 }
 declare module spine.webgl {

+ 202 - 57
spine-ts/build/spine-all.js

@@ -4376,8 +4376,10 @@ var spine;
 					if (color != null)
 						data.color.setFromString(color);
 					var dark = this.getValue(slotMap, "dark", null);
-					if (dark != null)
-						data.darkColor.setFromString(color);
+					if (dark != null) {
+						data.darkColor = new spine.Color(1, 1, 1, 1);
+						data.darkColor.setFromString(dark);
+					}
 					data.attachmentName = this.getValue(slotMap, "attachment", null);
 					data.blendMode = SkeletonJson.blendModeFromString(this.getValue(slotMap, "blend", "normal"));
 					skeletonData.slots.push(data);
@@ -4680,7 +4682,7 @@ var spine;
 								var valueMap = timelineMap[i];
 								var light = new spine.Color();
 								var dark = new spine.Color();
-								light.setFromString(valueMap.color);
+								light.setFromString(valueMap.light);
 								dark.setFromString(valueMap.dark);
 								timeline.setFrame(frameIndex, valueMap.time, light.r, light.g, light.b, light.a, dark.r, dark.g, dark.b);
 								this.readCurve(valueMap, timeline, frameIndex);
@@ -5818,6 +5820,45 @@ var spine;
 		return TimeKeeper;
 	}());
 	spine.TimeKeeper = TimeKeeper;
+	var WindowedMean = (function () {
+		function WindowedMean(windowSize) {
+			if (windowSize === void 0) { windowSize = 32; }
+			this.addedValues = 0;
+			this.lastValue = 0;
+			this.mean = 0;
+			this.dirty = true;
+			this.values = new Array(windowSize);
+		}
+		WindowedMean.prototype.hasEnoughData = function () {
+			return this.addedValues >= this.values.length;
+		};
+		WindowedMean.prototype.addValue = function (value) {
+			if (this.addedValues < this.values.length)
+				this.addedValues++;
+			this.values[this.lastValue++] = value;
+			if (this.lastValue > this.values.length - 1)
+				this.lastValue = 0;
+			this.dirty = true;
+		};
+		WindowedMean.prototype.getMean = function () {
+			if (this.hasEnoughData()) {
+				if (this.dirty) {
+					var mean = 0;
+					for (var i = 0; i < this.values.length; i++) {
+						mean += this.values[i];
+					}
+					this.mean = mean / this.values.length;
+					this.dirty = false;
+				}
+				return this.mean;
+			}
+			else {
+				return 0;
+			}
+		};
+		return WindowedMean;
+	}());
+	spine.WindowedMean = WindowedMean;
 })(spine || (spine = {}));
 var spine;
 (function (spine) {
@@ -6848,6 +6889,14 @@ var spine;
 			};
 			Mesh.prototype.getIndices = function () { return this.indices; };
 			;
+			Mesh.prototype.getVertexSizeInFloats = function () {
+				var size = 0;
+				for (var i = 0; i < this.attributes.length; i++) {
+					var attribute = this.attributes[i];
+					size += attribute.numElements;
+				}
+				return size;
+			};
 			Mesh.prototype.setVertices = function (vertices) {
 				this.dirtyVertices = true;
 				if (vertices.length > this.vertices.length)
@@ -6908,7 +6957,7 @@ var spine;
 						this.verticesBuffer = gl.createBuffer();
 					}
 					gl.bindBuffer(gl.ARRAY_BUFFER, this.verticesBuffer);
-					gl.bufferData(gl.ARRAY_BUFFER, this.vertices.subarray(0, this.verticesLength), gl.STATIC_DRAW);
+					gl.bufferData(gl.ARRAY_BUFFER, this.vertices.subarray(0, this.verticesLength), gl.DYNAMIC_DRAW);
 					this.dirtyVertices = false;
 				}
 				if (this.dirtyIndices) {
@@ -6916,7 +6965,7 @@ var spine;
 						this.indicesBuffer = gl.createBuffer();
 					}
 					gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indicesBuffer);
-					gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this.indices.subarray(0, this.indicesLength), gl.STATIC_DRAW);
+					gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this.indices.subarray(0, this.indicesLength), gl.DYNAMIC_DRAW);
 					this.dirtyIndices = false;
 				}
 			};
@@ -6970,6 +7019,14 @@ var spine;
 			return ColorAttribute;
 		}(VertexAttribute));
 		webgl.ColorAttribute = ColorAttribute;
+		var Color2Attribute = (function (_super) {
+			__extends(Color2Attribute, _super);
+			function Color2Attribute() {
+				_super.call(this, webgl.Shader.COLOR2, VertexAttributeType.Float, 4);
+			}
+			return Color2Attribute;
+		}(VertexAttribute));
+		webgl.Color2Attribute = Color2Attribute;
 		(function (VertexAttributeType) {
 			VertexAttributeType[VertexAttributeType["Float"] = 0] = "Float";
 		})(webgl.VertexAttributeType || (webgl.VertexAttributeType = {}));
@@ -6981,7 +7038,8 @@ var spine;
 	var webgl;
 	(function (webgl) {
 		var PolygonBatcher = (function () {
-			function PolygonBatcher(gl, maxVertices) {
+			function PolygonBatcher(gl, twoColorTint, maxVertices) {
+				if (twoColorTint === void 0) { twoColorTint = true; }
 				if (maxVertices === void 0) { maxVertices = 10920; }
 				this.isDrawing = false;
 				this.shader = null;
@@ -6993,7 +7051,10 @@ var spine;
 				if (maxVertices > 10920)
 					throw new Error("Can't have more than 10920 triangles per batch: " + maxVertices);
 				this.gl = gl;
-				this.mesh = new webgl.Mesh(gl, [new webgl.Position2Attribute(), new webgl.ColorAttribute(), new webgl.TexCoordAttribute()], maxVertices, maxVertices * 3);
+				var attributes = twoColorTint ?
+					[new webgl.Position2Attribute(), new webgl.ColorAttribute(), new webgl.TexCoordAttribute(), new webgl.Color2Attribute()] :
+					[new webgl.Position2Attribute(), new webgl.ColorAttribute(), new webgl.TexCoordAttribute()];
+				this.mesh = new webgl.Mesh(gl, attributes, maxVertices, maxVertices * 3);
 			}
 			PolygonBatcher.prototype.begin = function (shader) {
 				var gl = this.gl;
@@ -7071,7 +7132,8 @@ var spine;
 	var webgl;
 	(function (webgl) {
 		var SceneRenderer = (function () {
-			function SceneRenderer(canvas, gl) {
+			function SceneRenderer(canvas, gl, twoColorTint) {
+				if (twoColorTint === void 0) { twoColorTint = true; }
 				this.activeRenderer = null;
 				this.QUAD = [
 					0, 0, 1, 1, 1, 1, 0, 0,
@@ -7084,11 +7146,11 @@ var spine;
 				this.canvas = canvas;
 				this.gl = gl;
 				this.camera = new webgl.OrthoCamera(canvas.width, canvas.height);
-				this.batcherShader = webgl.Shader.newColoredTextured(gl);
-				this.batcher = new webgl.PolygonBatcher(gl);
+				this.batcherShader = twoColorTint ? webgl.Shader.newTwoColorTextured(gl) : webgl.Shader.newColoredTextured(gl);
+				this.batcher = new webgl.PolygonBatcher(gl, twoColorTint);
 				this.shapesShader = webgl.Shader.newColored(gl);
 				this.shapes = new webgl.ShapeRenderer(gl);
-				this.skeletonRenderer = new webgl.SkeletonRenderer(gl);
+				this.skeletonRenderer = new webgl.SkeletonRenderer(gl, twoColorTint);
 				this.skeletonDebugRenderer = new webgl.SkeletonDebugRenderer(gl);
 			}
 			SceneRenderer.prototype.begin = function () {
@@ -7526,6 +7588,11 @@ var spine;
 				var fs = "\n\t\t\t\t#ifdef GL_ES\n\t\t\t\t\t#define LOWP lowp\n\t\t\t\t\tprecision mediump float;\n\t\t\t\t#else\n\t\t\t\t\t#define LOWP\n\t\t\t\t#endif\n\t\t\t\tvarying LOWP vec4 v_color;\n\t\t\t\tvarying vec2 v_texCoords;\n\t\t\t\tuniform sampler2D u_texture;\n\n\t\t\t\tvoid main () {\n\t\t\t\t\tgl_FragColor = v_color * texture2D(u_texture, v_texCoords);\n\t\t\t\t}\n\t\t\t";
 				return new Shader(gl, vs, fs);
 			};
+			Shader.newTwoColorTextured = function (gl) {
+				var vs = "\n\t\t\t\tattribute vec4 " + Shader.POSITION + ";\n\t\t\t\tattribute vec4 " + Shader.COLOR + ";\n\t\t\t\tattribute vec4 " + Shader.COLOR2 + ";\n\t\t\t\tattribute vec2 " + Shader.TEXCOORDS + ";\n\t\t\t\tuniform mat4 " + Shader.MVP_MATRIX + ";\n\t\t\t\tvarying vec4 v_light;\n\t\t\t\tvarying vec4 v_dark;\n\t\t\t\tvarying vec2 v_texCoords;\n\n\t\t\t\tvoid main () {\n\t\t\t\t\tv_light = " + Shader.COLOR + ";\n\t\t\t\t\tv_dark = " + Shader.COLOR2 + ";\n\t\t\t\t\tv_texCoords = " + Shader.TEXCOORDS + ";\n\t\t\t\t\tgl_Position = " + Shader.MVP_MATRIX + " * " + Shader.POSITION + ";\n\t\t\t\t}\n\t\t\t";
+				var fs = "\n\t\t\t\t#ifdef GL_ES\n\t\t\t\t\t#define LOWP lowp\n\t\t\t\t\tprecision mediump float;\n\t\t\t\t#else\n\t\t\t\t\t#define LOWP\n\t\t\t\t#endif\n\t\t\t\tvarying LOWP vec4 v_light;\n\t\t\t\tvarying LOWP vec4 v_dark;\n\t\t\t\tvarying vec2 v_texCoords;\n\t\t\t\tuniform sampler2D u_texture;\n\n\t\t\t\tvoid main () {\n\t\t\t\t\tvec4 texColor = texture2D(u_texture, v_texCoords);\n\t\t\t\t\tfloat alpha = texColor.a * v_light.a;\n\t\t\t\t\tgl_FragColor.a = alpha;\n\t\t\t\t\tgl_FragColor.rgb = (1.0 - texColor.rgb) * v_dark.rgb * alpha + texColor.rgb * v_light.rgb;\n\t\t\t\t}\n\t\t\t";
+				return new Shader(gl, vs, fs);
+			};
 			Shader.newColored = function (gl) {
 				var vs = "\n\t\t\t\tattribute vec4 " + Shader.POSITION + ";\n\t\t\t\tattribute vec4 " + Shader.COLOR + ";\n\t\t\t\tuniform mat4 " + Shader.MVP_MATRIX + ";\n\t\t\t\tvarying vec4 v_color;\n\n\t\t\t\tvoid main () {\n\t\t\t\t\tv_color = " + Shader.COLOR + ";\n\t\t\t\t\tgl_Position = " + Shader.MVP_MATRIX + " * " + Shader.POSITION + ";\n\t\t\t\t}\n\t\t\t";
 				var fs = "\n\t\t\t\t#ifdef GL_ES\n\t\t\t\t\t#define LOWP lowp\n\t\t\t\t\tprecision mediump float;\n\t\t\t\t#else\n\t\t\t\t\t#define LOWP\n\t\t\t\t#endif\n\t\t\t\tvarying LOWP vec4 v_color;\n\n\t\t\t\tvoid main () {\n\t\t\t\t\tgl_FragColor = v_color;\n\t\t\t\t}\n\t\t\t";
@@ -7534,6 +7601,7 @@ var spine;
 			Shader.MVP_MATRIX = "u_projTrans";
 			Shader.POSITION = "a_position";
 			Shader.COLOR = "a_color";
+			Shader.COLOR2 = "a_color2";
 			Shader.TEXCOORDS = "a_texCoords";
 			Shader.SAMPLER = "u_texture";
 			return Shader;
@@ -7889,7 +7957,7 @@ var spine;
 				this.boneWidth = 2;
 				this.bounds = new spine.SkeletonBounds();
 				this.temp = new Array();
-				this.vertices = spine.Utils.newFloatArray(webgl.SkeletonRenderer.VERTEX_SIZE * 1024);
+				this.vertices = spine.Utils.newFloatArray(2 * 1024);
 				this.gl = gl;
 			}
 			SkeletonDebugRenderer.prototype.draw = function (shapes, skeleton, ignoredBones) {
@@ -8038,12 +8106,28 @@ var spine;
 (function (spine) {
 	var webgl;
 	(function (webgl) {
+		var Renderable = (function () {
+			function Renderable(vertices, numFloats) {
+				this.vertices = vertices;
+				this.numFloats = numFloats;
+			}
+			return Renderable;
+		}());
+		;
 		var SkeletonRenderer = (function () {
-			function SkeletonRenderer(gl) {
+			function SkeletonRenderer(gl, twoColorTint) {
+				if (twoColorTint === void 0) { twoColorTint = true; }
 				this.premultipliedAlpha = false;
 				this.tempColor = new spine.Color();
-				this.vertices = spine.Utils.newFloatArray(SkeletonRenderer.VERTEX_SIZE * 1024);
+				this.tempColor2 = new spine.Color();
+				this.vertexSize = 2 + 2 + 4;
+				this.twoColorTint = false;
+				this.renderable = new Renderable(null, 0);
 				this.gl = gl;
+				this.twoColorTint = twoColorTint;
+				if (twoColorTint)
+					this.vertexSize += 4;
+				this.vertices = spine.Utils.newFloatArray(this.vertexSize * 1024);
 			}
 			SkeletonRenderer.prototype.draw = function (batcher, skeleton) {
 				var premultipliedAlpha = this.premultipliedAlpha;
@@ -8057,13 +8141,13 @@ var spine;
 					var texture = null;
 					if (attachment instanceof spine.RegionAttachment) {
 						var region = attachment;
-						vertices = this.computeRegionVertices(slot, region, premultipliedAlpha);
+						vertices = this.computeRegionVertices(slot, region, premultipliedAlpha, this.twoColorTint);
 						triangles = SkeletonRenderer.QUAD_TRIANGLES;
 						texture = region.region.renderObject.texture;
 					}
 					else if (attachment instanceof spine.MeshAttachment) {
 						var mesh = attachment;
-						vertices = this.computeMeshVertices(slot, mesh, premultipliedAlpha);
+						vertices = this.computeMeshVertices(slot, mesh, premultipliedAlpha, this.twoColorTint);
 						triangles = mesh.triangles;
 						texture = mesh.region.renderObject.texture;
 					}
@@ -8075,11 +8159,13 @@ var spine;
 							blendMode = slotBlendMode;
 							batcher.setBlendMode(webgl.getSourceGLBlendMode(this.gl, blendMode, premultipliedAlpha), webgl.getDestGLBlendMode(this.gl, blendMode));
 						}
-						batcher.draw(texture, vertices, triangles);
+						var view = vertices.vertices.subarray(0, vertices.numFloats);
+						batcher.draw(texture, view, triangles);
 					}
 				}
 			};
-			SkeletonRenderer.prototype.computeRegionVertices = function (slot, region, pma) {
+			SkeletonRenderer.prototype.computeRegionVertices = function (slot, region, pma, twoColorTint) {
+				if (twoColorTint === void 0) { twoColorTint = false; }
 				var skeleton = slot.bone.skeleton;
 				var skeletonColor = skeleton.color;
 				var slotColor = slot.color;
@@ -8088,36 +8174,72 @@ var spine;
 				var multiplier = pma ? alpha : 1;
 				var color = this.tempColor;
 				color.set(skeletonColor.r * slotColor.r * regionColor.r * multiplier, skeletonColor.g * slotColor.g * regionColor.g * multiplier, skeletonColor.b * slotColor.b * regionColor.b * multiplier, alpha);
-				region.computeWorldVertices(slot.bone, this.vertices, 0, SkeletonRenderer.VERTEX_SIZE);
+				var dark = this.tempColor2;
+				if (slot.darkColor == null)
+					dark.set(0, 0, 0, 1);
+				else
+					dark.setFromColor(slot.darkColor);
+				region.computeWorldVertices(slot.bone, this.vertices, 0, this.vertexSize);
 				var vertices = this.vertices;
 				var uvs = region.uvs;
-				vertices[spine.RegionAttachment.C1R] = color.r;
-				vertices[spine.RegionAttachment.C1G] = color.g;
-				vertices[spine.RegionAttachment.C1B] = color.b;
-				vertices[spine.RegionAttachment.C1A] = color.a;
-				vertices[spine.RegionAttachment.U1] = uvs[0];
-				vertices[spine.RegionAttachment.V1] = uvs[1];
-				vertices[spine.RegionAttachment.C2R] = color.r;
-				vertices[spine.RegionAttachment.C2G] = color.g;
-				vertices[spine.RegionAttachment.C2B] = color.b;
-				vertices[spine.RegionAttachment.C2A] = color.a;
-				vertices[spine.RegionAttachment.U2] = uvs[2];
-				vertices[spine.RegionAttachment.V2] = uvs[3];
-				vertices[spine.RegionAttachment.C3R] = color.r;
-				vertices[spine.RegionAttachment.C3G] = color.g;
-				vertices[spine.RegionAttachment.C3B] = color.b;
-				vertices[spine.RegionAttachment.C3A] = color.a;
-				vertices[spine.RegionAttachment.U3] = uvs[4];
-				vertices[spine.RegionAttachment.V3] = uvs[5];
-				vertices[spine.RegionAttachment.C4R] = color.r;
-				vertices[spine.RegionAttachment.C4G] = color.g;
-				vertices[spine.RegionAttachment.C4B] = color.b;
-				vertices[spine.RegionAttachment.C4A] = color.a;
-				vertices[spine.RegionAttachment.U4] = uvs[6];
-				vertices[spine.RegionAttachment.V4] = uvs[7];
-				return vertices;
-			};
-			SkeletonRenderer.prototype.computeMeshVertices = function (slot, mesh, pma) {
+				var i = 2;
+				vertices[i++] = color.r;
+				vertices[i++] = color.g;
+				vertices[i++] = color.b;
+				vertices[i++] = color.a;
+				vertices[i++] = uvs[0];
+				vertices[i++] = uvs[1];
+				if (twoColorTint) {
+					vertices[i++] = dark.r;
+					vertices[i++] = dark.g;
+					vertices[i++] = dark.b;
+					vertices[i++] = 1;
+				}
+				i += 2;
+				vertices[i++] = color.r;
+				vertices[i++] = color.g;
+				vertices[i++] = color.b;
+				vertices[i++] = color.a;
+				vertices[i++] = uvs[2];
+				vertices[i++] = uvs[3];
+				if (twoColorTint) {
+					vertices[i++] = dark.r;
+					vertices[i++] = dark.g;
+					vertices[i++] = dark.b;
+					vertices[i++] = 1;
+				}
+				i += 2;
+				vertices[i++] = color.r;
+				vertices[i++] = color.g;
+				vertices[i++] = color.b;
+				vertices[i++] = color.a;
+				vertices[i++] = uvs[4];
+				vertices[i++] = uvs[5];
+				if (twoColorTint) {
+					vertices[i++] = dark.r;
+					vertices[i++] = dark.g;
+					vertices[i++] = dark.b;
+					vertices[i++] = 1;
+				}
+				i += 2;
+				vertices[i++] = color.r;
+				vertices[i++] = color.g;
+				vertices[i++] = color.b;
+				vertices[i++] = color.a;
+				vertices[i++] = uvs[6];
+				vertices[i++] = uvs[7];
+				if (twoColorTint) {
+					vertices[i++] = dark.r;
+					vertices[i++] = dark.g;
+					vertices[i++] = dark.b;
+					vertices[i++] = 1;
+				}
+				this.renderable.vertices = vertices;
+				this.renderable.numFloats = 4 * (twoColorTint ? 12 : 8);
+				return this.renderable;
+			};
+			SkeletonRenderer.prototype.computeMeshVertices = function (slot, mesh, pma, twoColorTint) {
+				if (twoColorTint === void 0) { twoColorTint = false; }
 				var skeleton = slot.bone.skeleton;
 				var skeletonColor = skeleton.color;
 				var slotColor = slot.color;
@@ -8126,25 +8248,48 @@ var spine;
 				var multiplier = pma ? alpha : 1;
 				var color = this.tempColor;
 				color.set(skeletonColor.r * slotColor.r * regionColor.r * multiplier, skeletonColor.g * slotColor.g * regionColor.g * multiplier, skeletonColor.b * slotColor.b * regionColor.b * multiplier, alpha);
+				var dark = this.tempColor2;
+				if (slot.darkColor == null)
+					dark.set(0, 0, 0, 1);
+				else
+					dark.setFromColor(slot.darkColor);
 				var numVertices = mesh.worldVerticesLength / 2;
 				if (this.vertices.length < mesh.worldVerticesLength) {
 					this.vertices = spine.Utils.newFloatArray(mesh.worldVerticesLength);
 				}
 				var vertices = this.vertices;
-				mesh.computeWorldVertices(slot, 0, mesh.worldVerticesLength, vertices, 0, SkeletonRenderer.VERTEX_SIZE);
+				mesh.computeWorldVertices(slot, 0, mesh.worldVerticesLength, vertices, 0, this.vertexSize);
 				var uvs = mesh.uvs;
-				for (var i = 0, n = numVertices, u = 0, v = 2; i < n; i++) {
-					vertices[v++] = color.r;
-					vertices[v++] = color.g;
-					vertices[v++] = color.b;
-					vertices[v++] = color.a;
-					vertices[v++] = uvs[u++];
-					vertices[v++] = uvs[u++];
-					v += 2;
+				if (!twoColorTint) {
+					for (var i = 0, n = numVertices, u = 0, v = 2; i < n; i++) {
+						vertices[v++] = color.r;
+						vertices[v++] = color.g;
+						vertices[v++] = color.b;
+						vertices[v++] = color.a;
+						vertices[v++] = uvs[u++];
+						vertices[v++] = uvs[u++];
+						v += 2;
+					}
 				}
-				return vertices;
+				else {
+					for (var i = 0, n = numVertices, u = 0, v = 2; i < n; i++) {
+						vertices[v++] = color.r;
+						vertices[v++] = color.g;
+						vertices[v++] = color.b;
+						vertices[v++] = color.a;
+						vertices[v++] = uvs[u++];
+						vertices[v++] = uvs[u++];
+						vertices[v++] = dark.r;
+						vertices[v++] = dark.g;
+						vertices[v++] = dark.b;
+						vertices[v++] = 1;
+						v += 2;
+					}
+				}
+				this.renderable.vertices = vertices;
+				this.renderable.numFloats = numVertices * (twoColorTint ? 12 : 8);
+				return this.renderable;
 			};
-			SkeletonRenderer.VERTEX_SIZE = 2 + 2 + 4;
 			SkeletonRenderer.QUAD_TRIANGLES = [0, 1, 2, 2, 3, 0];
 			return SkeletonRenderer;
 		}());

Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 0 - 0
spine-ts/build/spine-all.js.map


+ 11 - 0
spine-ts/build/spine-canvas.d.ts

@@ -1122,4 +1122,15 @@ declare module spine {
 		length: number;
 		[n: number]: T;
 	}
+	class WindowedMean {
+		values: Array<number>;
+		addedValues: number;
+		lastValue: number;
+		mean: number;
+		dirty: boolean;
+		constructor(windowSize?: number);
+		hasEnoughData(): boolean;
+		addValue(value: number): void;
+		getMean(): number;
+	}
 }

+ 44 - 3
spine-ts/build/spine-canvas.js

@@ -4376,8 +4376,10 @@ var spine;
 					if (color != null)
 						data.color.setFromString(color);
 					var dark = this.getValue(slotMap, "dark", null);
-					if (dark != null)
-						data.darkColor.setFromString(color);
+					if (dark != null) {
+						data.darkColor = new spine.Color(1, 1, 1, 1);
+						data.darkColor.setFromString(dark);
+					}
 					data.attachmentName = this.getValue(slotMap, "attachment", null);
 					data.blendMode = SkeletonJson.blendModeFromString(this.getValue(slotMap, "blend", "normal"));
 					skeletonData.slots.push(data);
@@ -4680,7 +4682,7 @@ var spine;
 								var valueMap = timelineMap[i];
 								var light = new spine.Color();
 								var dark = new spine.Color();
-								light.setFromString(valueMap.color);
+								light.setFromString(valueMap.light);
 								dark.setFromString(valueMap.dark);
 								timeline.setFrame(frameIndex, valueMap.time, light.r, light.g, light.b, light.a, dark.r, dark.g, dark.b);
 								this.readCurve(valueMap, timeline, frameIndex);
@@ -5818,5 +5820,44 @@ var spine;
 		return TimeKeeper;
 	}());
 	spine.TimeKeeper = TimeKeeper;
+	var WindowedMean = (function () {
+		function WindowedMean(windowSize) {
+			if (windowSize === void 0) { windowSize = 32; }
+			this.addedValues = 0;
+			this.lastValue = 0;
+			this.mean = 0;
+			this.dirty = true;
+			this.values = new Array(windowSize);
+		}
+		WindowedMean.prototype.hasEnoughData = function () {
+			return this.addedValues >= this.values.length;
+		};
+		WindowedMean.prototype.addValue = function (value) {
+			if (this.addedValues < this.values.length)
+				this.addedValues++;
+			this.values[this.lastValue++] = value;
+			if (this.lastValue > this.values.length - 1)
+				this.lastValue = 0;
+			this.dirty = true;
+		};
+		WindowedMean.prototype.getMean = function () {
+			if (this.hasEnoughData()) {
+				if (this.dirty) {
+					var mean = 0;
+					for (var i = 0; i < this.values.length; i++) {
+						mean += this.values[i];
+					}
+					this.mean = mean / this.values.length;
+					this.dirty = false;
+				}
+				return this.mean;
+			}
+			else {
+				return 0;
+			}
+		};
+		return WindowedMean;
+	}());
+	spine.WindowedMean = WindowedMean;
 })(spine || (spine = {}));
 //# sourceMappingURL=spine-canvas.js.map

Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 0 - 0
spine-ts/build/spine-canvas.js.map


+ 11 - 0
spine-ts/build/spine-core.d.ts

@@ -1091,4 +1091,15 @@ declare module spine {
 		length: number;
 		[n: number]: T;
 	}
+	class WindowedMean {
+		values: Array<number>;
+		addedValues: number;
+		lastValue: number;
+		mean: number;
+		dirty: boolean;
+		constructor(windowSize?: number);
+		hasEnoughData(): boolean;
+		addValue(value: number): void;
+		getMean(): number;
+	}
 }

+ 44 - 3
spine-ts/build/spine-core.js

@@ -4065,8 +4065,10 @@ var spine;
 					if (color != null)
 						data.color.setFromString(color);
 					var dark = this.getValue(slotMap, "dark", null);
-					if (dark != null)
-						data.darkColor.setFromString(color);
+					if (dark != null) {
+						data.darkColor = new spine.Color(1, 1, 1, 1);
+						data.darkColor.setFromString(dark);
+					}
 					data.attachmentName = this.getValue(slotMap, "attachment", null);
 					data.blendMode = SkeletonJson.blendModeFromString(this.getValue(slotMap, "blend", "normal"));
 					skeletonData.slots.push(data);
@@ -4369,7 +4371,7 @@ var spine;
 								var valueMap = timelineMap[i];
 								var light = new spine.Color();
 								var dark = new spine.Color();
-								light.setFromString(valueMap.color);
+								light.setFromString(valueMap.light);
 								dark.setFromString(valueMap.dark);
 								timeline.setFrame(frameIndex, valueMap.time, light.r, light.g, light.b, light.a, dark.r, dark.g, dark.b);
 								this.readCurve(valueMap, timeline, frameIndex);
@@ -5573,5 +5575,44 @@ var spine;
 		return TimeKeeper;
 	}());
 	spine.TimeKeeper = TimeKeeper;
+	var WindowedMean = (function () {
+		function WindowedMean(windowSize) {
+			if (windowSize === void 0) { windowSize = 32; }
+			this.addedValues = 0;
+			this.lastValue = 0;
+			this.mean = 0;
+			this.dirty = true;
+			this.values = new Array(windowSize);
+		}
+		WindowedMean.prototype.hasEnoughData = function () {
+			return this.addedValues >= this.values.length;
+		};
+		WindowedMean.prototype.addValue = function (value) {
+			if (this.addedValues < this.values.length)
+				this.addedValues++;
+			this.values[this.lastValue++] = value;
+			if (this.lastValue > this.values.length - 1)
+				this.lastValue = 0;
+			this.dirty = true;
+		};
+		WindowedMean.prototype.getMean = function () {
+			if (this.hasEnoughData()) {
+				if (this.dirty) {
+					var mean = 0;
+					for (var i = 0; i < this.values.length; i++) {
+						mean += this.values[i];
+					}
+					this.mean = mean / this.values.length;
+					this.dirty = false;
+				}
+				return this.mean;
+			}
+			else {
+				return 0;
+			}
+		};
+		return WindowedMean;
+	}());
+	spine.WindowedMean = WindowedMean;
 })(spine || (spine = {}));
 //# sourceMappingURL=spine-core.js.map

Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 0 - 0
spine-ts/build/spine-core.js.map


+ 11 - 0
spine-ts/build/spine-threejs.d.ts

@@ -1091,6 +1091,17 @@ declare module spine {
 		length: number;
 		[n: number]: T;
 	}
+	class WindowedMean {
+		values: Array<number>;
+		addedValues: number;
+		lastValue: number;
+		mean: number;
+		dirty: boolean;
+		constructor(windowSize?: number);
+		hasEnoughData(): boolean;
+		addValue(value: number): void;
+		getMean(): number;
+	}
 }
 declare module spine.threejs {
 	class AssetManager extends spine.AssetManager {

+ 44 - 3
spine-ts/build/spine-threejs.js

@@ -4065,8 +4065,10 @@ var spine;
 					if (color != null)
 						data.color.setFromString(color);
 					var dark = this.getValue(slotMap, "dark", null);
-					if (dark != null)
-						data.darkColor.setFromString(color);
+					if (dark != null) {
+						data.darkColor = new spine.Color(1, 1, 1, 1);
+						data.darkColor.setFromString(dark);
+					}
 					data.attachmentName = this.getValue(slotMap, "attachment", null);
 					data.blendMode = SkeletonJson.blendModeFromString(this.getValue(slotMap, "blend", "normal"));
 					skeletonData.slots.push(data);
@@ -4369,7 +4371,7 @@ var spine;
 								var valueMap = timelineMap[i];
 								var light = new spine.Color();
 								var dark = new spine.Color();
-								light.setFromString(valueMap.color);
+								light.setFromString(valueMap.light);
 								dark.setFromString(valueMap.dark);
 								timeline.setFrame(frameIndex, valueMap.time, light.r, light.g, light.b, light.a, dark.r, dark.g, dark.b);
 								this.readCurve(valueMap, timeline, frameIndex);
@@ -5573,6 +5575,45 @@ var spine;
 		return TimeKeeper;
 	}());
 	spine.TimeKeeper = TimeKeeper;
+	var WindowedMean = (function () {
+		function WindowedMean(windowSize) {
+			if (windowSize === void 0) { windowSize = 32; }
+			this.addedValues = 0;
+			this.lastValue = 0;
+			this.mean = 0;
+			this.dirty = true;
+			this.values = new Array(windowSize);
+		}
+		WindowedMean.prototype.hasEnoughData = function () {
+			return this.addedValues >= this.values.length;
+		};
+		WindowedMean.prototype.addValue = function (value) {
+			if (this.addedValues < this.values.length)
+				this.addedValues++;
+			this.values[this.lastValue++] = value;
+			if (this.lastValue > this.values.length - 1)
+				this.lastValue = 0;
+			this.dirty = true;
+		};
+		WindowedMean.prototype.getMean = function () {
+			if (this.hasEnoughData()) {
+				if (this.dirty) {
+					var mean = 0;
+					for (var i = 0; i < this.values.length; i++) {
+						mean += this.values[i];
+					}
+					this.mean = mean / this.values.length;
+					this.dirty = false;
+				}
+				return this.mean;
+			}
+			else {
+				return 0;
+			}
+		};
+		return WindowedMean;
+	}());
+	spine.WindowedMean = WindowedMean;
 })(spine || (spine = {}));
 var spine;
 (function (spine) {

Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 0 - 0
spine-ts/build/spine-threejs.js.map


+ 26 - 6
spine-ts/build/spine-webgl.d.ts

@@ -1091,6 +1091,17 @@ declare module spine {
 		length: number;
 		[n: number]: T;
 	}
+	class WindowedMean {
+		values: Array<number>;
+		addedValues: number;
+		lastValue: number;
+		mean: number;
+		dirty: boolean;
+		constructor(windowSize?: number);
+		hasEnoughData(): boolean;
+		addValue(value: number): void;
+		getMean(): number;
+	}
 }
 declare module spine.webgl {
 	class AssetManager extends spine.AssetManager {
@@ -1243,6 +1254,7 @@ declare module spine.webgl {
 		numIndices(): number;
 		setIndicesLength(length: number): void;
 		getIndices(): Uint16Array;
+		getVertexSizeInFloats(): number;
 		constructor(gl: WebGLRenderingContext, attributes: VertexAttribute[], maxVertices: number, maxIndices: number);
 		setVertices(vertices: Array<number>): void;
 		setIndices(indices: Array<number>): void;
@@ -1271,6 +1283,9 @@ declare module spine.webgl {
 	class ColorAttribute extends VertexAttribute {
 		constructor();
 	}
+	class Color2Attribute extends VertexAttribute {
+		constructor();
+	}
 	enum VertexAttributeType {
 		Float = 0,
 	}
@@ -1287,7 +1302,7 @@ declare module spine.webgl {
 		private indicesLength;
 		private srcBlend;
 		private dstBlend;
-		constructor(gl: WebGLRenderingContext, maxVertices?: number);
+		constructor(gl: WebGLRenderingContext, twoColorTint?: boolean, maxVertices?: number);
 		begin(shader: Shader): void;
 		setBlendMode(srcBlend: number, dstBlend: number): void;
 		draw(texture: GLTexture, vertices: ArrayLike<number>, indices: Array<number>): void;
@@ -1312,7 +1327,7 @@ declare module spine.webgl {
 		private QUAD;
 		private QUAD_TRIANGLES;
 		private WHITE;
-		constructor(canvas: HTMLCanvasElement, gl: WebGLRenderingContext);
+		constructor(canvas: HTMLCanvasElement, gl: WebGLRenderingContext, twoColorTint?: boolean);
 		begin(): void;
 		drawSkeleton(skeleton: Skeleton, premultipliedAlpha?: boolean): void;
 		drawSkeletonDebug(skeleton: Skeleton, premultipliedAlpha?: boolean, ignoredBones?: Array<string>): void;
@@ -1345,6 +1360,7 @@ declare module spine.webgl {
 		static MVP_MATRIX: string;
 		static POSITION: string;
 		static COLOR: string;
+		static COLOR2: string;
 		static TEXCOORDS: string;
 		static SAMPLER: string;
 		private gl;
@@ -1375,6 +1391,7 @@ declare module spine.webgl {
 		getAttributeLocation(attribute: string): number;
 		dispose(): void;
 		static newColoredTextured(gl: WebGLRenderingContext): Shader;
+		static newTwoColorTextured(gl: WebGLRenderingContext): Shader;
 		static newColored(gl: WebGLRenderingContext): Shader;
 	}
 }
@@ -1448,16 +1465,19 @@ declare module spine.webgl {
 }
 declare module spine.webgl {
 	class SkeletonRenderer {
-		static VERTEX_SIZE: number;
 		static QUAD_TRIANGLES: number[];
 		premultipliedAlpha: boolean;
 		private gl;
 		private tempColor;
+		private tempColor2;
 		private vertices;
-		constructor(gl: WebGLRenderingContext);
+		private vertexSize;
+		private twoColorTint;
+		private renderable;
+		constructor(gl: WebGLRenderingContext, twoColorTint?: boolean);
 		draw(batcher: PolygonBatcher, skeleton: Skeleton): void;
-		computeRegionVertices(slot: Slot, region: RegionAttachment, pma: boolean): ArrayLike<number>;
-		computeMeshVertices(slot: Slot, mesh: MeshAttachment, pma: boolean): ArrayLike<number>;
+		private computeRegionVertices(slot, region, pma, twoColorTint?);
+		private computeMeshVertices(slot, mesh, pma, twoColorTint?);
 	}
 }
 declare module spine.webgl {

+ 202 - 57
spine-ts/build/spine-webgl.js

@@ -4065,8 +4065,10 @@ var spine;
 					if (color != null)
 						data.color.setFromString(color);
 					var dark = this.getValue(slotMap, "dark", null);
-					if (dark != null)
-						data.darkColor.setFromString(color);
+					if (dark != null) {
+						data.darkColor = new spine.Color(1, 1, 1, 1);
+						data.darkColor.setFromString(dark);
+					}
 					data.attachmentName = this.getValue(slotMap, "attachment", null);
 					data.blendMode = SkeletonJson.blendModeFromString(this.getValue(slotMap, "blend", "normal"));
 					skeletonData.slots.push(data);
@@ -4369,7 +4371,7 @@ var spine;
 								var valueMap = timelineMap[i];
 								var light = new spine.Color();
 								var dark = new spine.Color();
-								light.setFromString(valueMap.color);
+								light.setFromString(valueMap.light);
 								dark.setFromString(valueMap.dark);
 								timeline.setFrame(frameIndex, valueMap.time, light.r, light.g, light.b, light.a, dark.r, dark.g, dark.b);
 								this.readCurve(valueMap, timeline, frameIndex);
@@ -5573,6 +5575,45 @@ var spine;
 		return TimeKeeper;
 	}());
 	spine.TimeKeeper = TimeKeeper;
+	var WindowedMean = (function () {
+		function WindowedMean(windowSize) {
+			if (windowSize === void 0) { windowSize = 32; }
+			this.addedValues = 0;
+			this.lastValue = 0;
+			this.mean = 0;
+			this.dirty = true;
+			this.values = new Array(windowSize);
+		}
+		WindowedMean.prototype.hasEnoughData = function () {
+			return this.addedValues >= this.values.length;
+		};
+		WindowedMean.prototype.addValue = function (value) {
+			if (this.addedValues < this.values.length)
+				this.addedValues++;
+			this.values[this.lastValue++] = value;
+			if (this.lastValue > this.values.length - 1)
+				this.lastValue = 0;
+			this.dirty = true;
+		};
+		WindowedMean.prototype.getMean = function () {
+			if (this.hasEnoughData()) {
+				if (this.dirty) {
+					var mean = 0;
+					for (var i = 0; i < this.values.length; i++) {
+						mean += this.values[i];
+					}
+					this.mean = mean / this.values.length;
+					this.dirty = false;
+				}
+				return this.mean;
+			}
+			else {
+				return 0;
+			}
+		};
+		return WindowedMean;
+	}());
+	spine.WindowedMean = WindowedMean;
 })(spine || (spine = {}));
 var spine;
 (function (spine) {
@@ -6319,6 +6360,14 @@ var spine;
 			};
 			Mesh.prototype.getIndices = function () { return this.indices; };
 			;
+			Mesh.prototype.getVertexSizeInFloats = function () {
+				var size = 0;
+				for (var i = 0; i < this.attributes.length; i++) {
+					var attribute = this.attributes[i];
+					size += attribute.numElements;
+				}
+				return size;
+			};
 			Mesh.prototype.setVertices = function (vertices) {
 				this.dirtyVertices = true;
 				if (vertices.length > this.vertices.length)
@@ -6379,7 +6428,7 @@ var spine;
 						this.verticesBuffer = gl.createBuffer();
 					}
 					gl.bindBuffer(gl.ARRAY_BUFFER, this.verticesBuffer);
-					gl.bufferData(gl.ARRAY_BUFFER, this.vertices.subarray(0, this.verticesLength), gl.STATIC_DRAW);
+					gl.bufferData(gl.ARRAY_BUFFER, this.vertices.subarray(0, this.verticesLength), gl.DYNAMIC_DRAW);
 					this.dirtyVertices = false;
 				}
 				if (this.dirtyIndices) {
@@ -6387,7 +6436,7 @@ var spine;
 						this.indicesBuffer = gl.createBuffer();
 					}
 					gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indicesBuffer);
-					gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this.indices.subarray(0, this.indicesLength), gl.STATIC_DRAW);
+					gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this.indices.subarray(0, this.indicesLength), gl.DYNAMIC_DRAW);
 					this.dirtyIndices = false;
 				}
 			};
@@ -6441,6 +6490,14 @@ var spine;
 			return ColorAttribute;
 		}(VertexAttribute));
 		webgl.ColorAttribute = ColorAttribute;
+		var Color2Attribute = (function (_super) {
+			__extends(Color2Attribute, _super);
+			function Color2Attribute() {
+				_super.call(this, webgl.Shader.COLOR2, VertexAttributeType.Float, 4);
+			}
+			return Color2Attribute;
+		}(VertexAttribute));
+		webgl.Color2Attribute = Color2Attribute;
 		(function (VertexAttributeType) {
 			VertexAttributeType[VertexAttributeType["Float"] = 0] = "Float";
 		})(webgl.VertexAttributeType || (webgl.VertexAttributeType = {}));
@@ -6452,7 +6509,8 @@ var spine;
 	var webgl;
 	(function (webgl) {
 		var PolygonBatcher = (function () {
-			function PolygonBatcher(gl, maxVertices) {
+			function PolygonBatcher(gl, twoColorTint, maxVertices) {
+				if (twoColorTint === void 0) { twoColorTint = true; }
 				if (maxVertices === void 0) { maxVertices = 10920; }
 				this.isDrawing = false;
 				this.shader = null;
@@ -6464,7 +6522,10 @@ var spine;
 				if (maxVertices > 10920)
 					throw new Error("Can't have more than 10920 triangles per batch: " + maxVertices);
 				this.gl = gl;
-				this.mesh = new webgl.Mesh(gl, [new webgl.Position2Attribute(), new webgl.ColorAttribute(), new webgl.TexCoordAttribute()], maxVertices, maxVertices * 3);
+				var attributes = twoColorTint ?
+					[new webgl.Position2Attribute(), new webgl.ColorAttribute(), new webgl.TexCoordAttribute(), new webgl.Color2Attribute()] :
+					[new webgl.Position2Attribute(), new webgl.ColorAttribute(), new webgl.TexCoordAttribute()];
+				this.mesh = new webgl.Mesh(gl, attributes, maxVertices, maxVertices * 3);
 			}
 			PolygonBatcher.prototype.begin = function (shader) {
 				var gl = this.gl;
@@ -6542,7 +6603,8 @@ var spine;
 	var webgl;
 	(function (webgl) {
 		var SceneRenderer = (function () {
-			function SceneRenderer(canvas, gl) {
+			function SceneRenderer(canvas, gl, twoColorTint) {
+				if (twoColorTint === void 0) { twoColorTint = true; }
 				this.activeRenderer = null;
 				this.QUAD = [
 					0, 0, 1, 1, 1, 1, 0, 0,
@@ -6555,11 +6617,11 @@ var spine;
 				this.canvas = canvas;
 				this.gl = gl;
 				this.camera = new webgl.OrthoCamera(canvas.width, canvas.height);
-				this.batcherShader = webgl.Shader.newColoredTextured(gl);
-				this.batcher = new webgl.PolygonBatcher(gl);
+				this.batcherShader = twoColorTint ? webgl.Shader.newTwoColorTextured(gl) : webgl.Shader.newColoredTextured(gl);
+				this.batcher = new webgl.PolygonBatcher(gl, twoColorTint);
 				this.shapesShader = webgl.Shader.newColored(gl);
 				this.shapes = new webgl.ShapeRenderer(gl);
-				this.skeletonRenderer = new webgl.SkeletonRenderer(gl);
+				this.skeletonRenderer = new webgl.SkeletonRenderer(gl, twoColorTint);
 				this.skeletonDebugRenderer = new webgl.SkeletonDebugRenderer(gl);
 			}
 			SceneRenderer.prototype.begin = function () {
@@ -6997,6 +7059,11 @@ var spine;
 				var fs = "\n\t\t\t\t#ifdef GL_ES\n\t\t\t\t\t#define LOWP lowp\n\t\t\t\t\tprecision mediump float;\n\t\t\t\t#else\n\t\t\t\t\t#define LOWP\n\t\t\t\t#endif\n\t\t\t\tvarying LOWP vec4 v_color;\n\t\t\t\tvarying vec2 v_texCoords;\n\t\t\t\tuniform sampler2D u_texture;\n\n\t\t\t\tvoid main () {\n\t\t\t\t\tgl_FragColor = v_color * texture2D(u_texture, v_texCoords);\n\t\t\t\t}\n\t\t\t";
 				return new Shader(gl, vs, fs);
 			};
+			Shader.newTwoColorTextured = function (gl) {
+				var vs = "\n\t\t\t\tattribute vec4 " + Shader.POSITION + ";\n\t\t\t\tattribute vec4 " + Shader.COLOR + ";\n\t\t\t\tattribute vec4 " + Shader.COLOR2 + ";\n\t\t\t\tattribute vec2 " + Shader.TEXCOORDS + ";\n\t\t\t\tuniform mat4 " + Shader.MVP_MATRIX + ";\n\t\t\t\tvarying vec4 v_light;\n\t\t\t\tvarying vec4 v_dark;\n\t\t\t\tvarying vec2 v_texCoords;\n\n\t\t\t\tvoid main () {\n\t\t\t\t\tv_light = " + Shader.COLOR + ";\n\t\t\t\t\tv_dark = " + Shader.COLOR2 + ";\n\t\t\t\t\tv_texCoords = " + Shader.TEXCOORDS + ";\n\t\t\t\t\tgl_Position = " + Shader.MVP_MATRIX + " * " + Shader.POSITION + ";\n\t\t\t\t}\n\t\t\t";
+				var fs = "\n\t\t\t\t#ifdef GL_ES\n\t\t\t\t\t#define LOWP lowp\n\t\t\t\t\tprecision mediump float;\n\t\t\t\t#else\n\t\t\t\t\t#define LOWP\n\t\t\t\t#endif\n\t\t\t\tvarying LOWP vec4 v_light;\n\t\t\t\tvarying LOWP vec4 v_dark;\n\t\t\t\tvarying vec2 v_texCoords;\n\t\t\t\tuniform sampler2D u_texture;\n\n\t\t\t\tvoid main () {\n\t\t\t\t\tvec4 texColor = texture2D(u_texture, v_texCoords);\n\t\t\t\t\tfloat alpha = texColor.a * v_light.a;\n\t\t\t\t\tgl_FragColor.a = alpha;\n\t\t\t\t\tgl_FragColor.rgb = (1.0 - texColor.rgb) * v_dark.rgb * alpha + texColor.rgb * v_light.rgb;\n\t\t\t\t}\n\t\t\t";
+				return new Shader(gl, vs, fs);
+			};
 			Shader.newColored = function (gl) {
 				var vs = "\n\t\t\t\tattribute vec4 " + Shader.POSITION + ";\n\t\t\t\tattribute vec4 " + Shader.COLOR + ";\n\t\t\t\tuniform mat4 " + Shader.MVP_MATRIX + ";\n\t\t\t\tvarying vec4 v_color;\n\n\t\t\t\tvoid main () {\n\t\t\t\t\tv_color = " + Shader.COLOR + ";\n\t\t\t\t\tgl_Position = " + Shader.MVP_MATRIX + " * " + Shader.POSITION + ";\n\t\t\t\t}\n\t\t\t";
 				var fs = "\n\t\t\t\t#ifdef GL_ES\n\t\t\t\t\t#define LOWP lowp\n\t\t\t\t\tprecision mediump float;\n\t\t\t\t#else\n\t\t\t\t\t#define LOWP\n\t\t\t\t#endif\n\t\t\t\tvarying LOWP vec4 v_color;\n\n\t\t\t\tvoid main () {\n\t\t\t\t\tgl_FragColor = v_color;\n\t\t\t\t}\n\t\t\t";
@@ -7005,6 +7072,7 @@ var spine;
 			Shader.MVP_MATRIX = "u_projTrans";
 			Shader.POSITION = "a_position";
 			Shader.COLOR = "a_color";
+			Shader.COLOR2 = "a_color2";
 			Shader.TEXCOORDS = "a_texCoords";
 			Shader.SAMPLER = "u_texture";
 			return Shader;
@@ -7360,7 +7428,7 @@ var spine;
 				this.boneWidth = 2;
 				this.bounds = new spine.SkeletonBounds();
 				this.temp = new Array();
-				this.vertices = spine.Utils.newFloatArray(webgl.SkeletonRenderer.VERTEX_SIZE * 1024);
+				this.vertices = spine.Utils.newFloatArray(2 * 1024);
 				this.gl = gl;
 			}
 			SkeletonDebugRenderer.prototype.draw = function (shapes, skeleton, ignoredBones) {
@@ -7509,12 +7577,28 @@ var spine;
 (function (spine) {
 	var webgl;
 	(function (webgl) {
+		var Renderable = (function () {
+			function Renderable(vertices, numFloats) {
+				this.vertices = vertices;
+				this.numFloats = numFloats;
+			}
+			return Renderable;
+		}());
+		;
 		var SkeletonRenderer = (function () {
-			function SkeletonRenderer(gl) {
+			function SkeletonRenderer(gl, twoColorTint) {
+				if (twoColorTint === void 0) { twoColorTint = true; }
 				this.premultipliedAlpha = false;
 				this.tempColor = new spine.Color();
-				this.vertices = spine.Utils.newFloatArray(SkeletonRenderer.VERTEX_SIZE * 1024);
+				this.tempColor2 = new spine.Color();
+				this.vertexSize = 2 + 2 + 4;
+				this.twoColorTint = false;
+				this.renderable = new Renderable(null, 0);
 				this.gl = gl;
+				this.twoColorTint = twoColorTint;
+				if (twoColorTint)
+					this.vertexSize += 4;
+				this.vertices = spine.Utils.newFloatArray(this.vertexSize * 1024);
 			}
 			SkeletonRenderer.prototype.draw = function (batcher, skeleton) {
 				var premultipliedAlpha = this.premultipliedAlpha;
@@ -7528,13 +7612,13 @@ var spine;
 					var texture = null;
 					if (attachment instanceof spine.RegionAttachment) {
 						var region = attachment;
-						vertices = this.computeRegionVertices(slot, region, premultipliedAlpha);
+						vertices = this.computeRegionVertices(slot, region, premultipliedAlpha, this.twoColorTint);
 						triangles = SkeletonRenderer.QUAD_TRIANGLES;
 						texture = region.region.renderObject.texture;
 					}
 					else if (attachment instanceof spine.MeshAttachment) {
 						var mesh = attachment;
-						vertices = this.computeMeshVertices(slot, mesh, premultipliedAlpha);
+						vertices = this.computeMeshVertices(slot, mesh, premultipliedAlpha, this.twoColorTint);
 						triangles = mesh.triangles;
 						texture = mesh.region.renderObject.texture;
 					}
@@ -7546,11 +7630,13 @@ var spine;
 							blendMode = slotBlendMode;
 							batcher.setBlendMode(webgl.getSourceGLBlendMode(this.gl, blendMode, premultipliedAlpha), webgl.getDestGLBlendMode(this.gl, blendMode));
 						}
-						batcher.draw(texture, vertices, triangles);
+						var view = vertices.vertices.subarray(0, vertices.numFloats);
+						batcher.draw(texture, view, triangles);
 					}
 				}
 			};
-			SkeletonRenderer.prototype.computeRegionVertices = function (slot, region, pma) {
+			SkeletonRenderer.prototype.computeRegionVertices = function (slot, region, pma, twoColorTint) {
+				if (twoColorTint === void 0) { twoColorTint = false; }
 				var skeleton = slot.bone.skeleton;
 				var skeletonColor = skeleton.color;
 				var slotColor = slot.color;
@@ -7559,36 +7645,72 @@ var spine;
 				var multiplier = pma ? alpha : 1;
 				var color = this.tempColor;
 				color.set(skeletonColor.r * slotColor.r * regionColor.r * multiplier, skeletonColor.g * slotColor.g * regionColor.g * multiplier, skeletonColor.b * slotColor.b * regionColor.b * multiplier, alpha);
-				region.computeWorldVertices(slot.bone, this.vertices, 0, SkeletonRenderer.VERTEX_SIZE);
+				var dark = this.tempColor2;
+				if (slot.darkColor == null)
+					dark.set(0, 0, 0, 1);
+				else
+					dark.setFromColor(slot.darkColor);
+				region.computeWorldVertices(slot.bone, this.vertices, 0, this.vertexSize);
 				var vertices = this.vertices;
 				var uvs = region.uvs;
-				vertices[spine.RegionAttachment.C1R] = color.r;
-				vertices[spine.RegionAttachment.C1G] = color.g;
-				vertices[spine.RegionAttachment.C1B] = color.b;
-				vertices[spine.RegionAttachment.C1A] = color.a;
-				vertices[spine.RegionAttachment.U1] = uvs[0];
-				vertices[spine.RegionAttachment.V1] = uvs[1];
-				vertices[spine.RegionAttachment.C2R] = color.r;
-				vertices[spine.RegionAttachment.C2G] = color.g;
-				vertices[spine.RegionAttachment.C2B] = color.b;
-				vertices[spine.RegionAttachment.C2A] = color.a;
-				vertices[spine.RegionAttachment.U2] = uvs[2];
-				vertices[spine.RegionAttachment.V2] = uvs[3];
-				vertices[spine.RegionAttachment.C3R] = color.r;
-				vertices[spine.RegionAttachment.C3G] = color.g;
-				vertices[spine.RegionAttachment.C3B] = color.b;
-				vertices[spine.RegionAttachment.C3A] = color.a;
-				vertices[spine.RegionAttachment.U3] = uvs[4];
-				vertices[spine.RegionAttachment.V3] = uvs[5];
-				vertices[spine.RegionAttachment.C4R] = color.r;
-				vertices[spine.RegionAttachment.C4G] = color.g;
-				vertices[spine.RegionAttachment.C4B] = color.b;
-				vertices[spine.RegionAttachment.C4A] = color.a;
-				vertices[spine.RegionAttachment.U4] = uvs[6];
-				vertices[spine.RegionAttachment.V4] = uvs[7];
-				return vertices;
+				var i = 2;
+				vertices[i++] = color.r;
+				vertices[i++] = color.g;
+				vertices[i++] = color.b;
+				vertices[i++] = color.a;
+				vertices[i++] = uvs[0];
+				vertices[i++] = uvs[1];
+				if (twoColorTint) {
+					vertices[i++] = dark.r;
+					vertices[i++] = dark.g;
+					vertices[i++] = dark.b;
+					vertices[i++] = 1;
+				}
+				i += 2;
+				vertices[i++] = color.r;
+				vertices[i++] = color.g;
+				vertices[i++] = color.b;
+				vertices[i++] = color.a;
+				vertices[i++] = uvs[2];
+				vertices[i++] = uvs[3];
+				if (twoColorTint) {
+					vertices[i++] = dark.r;
+					vertices[i++] = dark.g;
+					vertices[i++] = dark.b;
+					vertices[i++] = 1;
+				}
+				i += 2;
+				vertices[i++] = color.r;
+				vertices[i++] = color.g;
+				vertices[i++] = color.b;
+				vertices[i++] = color.a;
+				vertices[i++] = uvs[4];
+				vertices[i++] = uvs[5];
+				if (twoColorTint) {
+					vertices[i++] = dark.r;
+					vertices[i++] = dark.g;
+					vertices[i++] = dark.b;
+					vertices[i++] = 1;
+				}
+				i += 2;
+				vertices[i++] = color.r;
+				vertices[i++] = color.g;
+				vertices[i++] = color.b;
+				vertices[i++] = color.a;
+				vertices[i++] = uvs[6];
+				vertices[i++] = uvs[7];
+				if (twoColorTint) {
+					vertices[i++] = dark.r;
+					vertices[i++] = dark.g;
+					vertices[i++] = dark.b;
+					vertices[i++] = 1;
+				}
+				this.renderable.vertices = vertices;
+				this.renderable.numFloats = 4 * (twoColorTint ? 12 : 8);
+				return this.renderable;
 			};
-			SkeletonRenderer.prototype.computeMeshVertices = function (slot, mesh, pma) {
+			SkeletonRenderer.prototype.computeMeshVertices = function (slot, mesh, pma, twoColorTint) {
+				if (twoColorTint === void 0) { twoColorTint = false; }
 				var skeleton = slot.bone.skeleton;
 				var skeletonColor = skeleton.color;
 				var slotColor = slot.color;
@@ -7597,25 +7719,48 @@ var spine;
 				var multiplier = pma ? alpha : 1;
 				var color = this.tempColor;
 				color.set(skeletonColor.r * slotColor.r * regionColor.r * multiplier, skeletonColor.g * slotColor.g * regionColor.g * multiplier, skeletonColor.b * slotColor.b * regionColor.b * multiplier, alpha);
+				var dark = this.tempColor2;
+				if (slot.darkColor == null)
+					dark.set(0, 0, 0, 1);
+				else
+					dark.setFromColor(slot.darkColor);
 				var numVertices = mesh.worldVerticesLength / 2;
 				if (this.vertices.length < mesh.worldVerticesLength) {
 					this.vertices = spine.Utils.newFloatArray(mesh.worldVerticesLength);
 				}
 				var vertices = this.vertices;
-				mesh.computeWorldVertices(slot, 0, mesh.worldVerticesLength, vertices, 0, SkeletonRenderer.VERTEX_SIZE);
+				mesh.computeWorldVertices(slot, 0, mesh.worldVerticesLength, vertices, 0, this.vertexSize);
 				var uvs = mesh.uvs;
-				for (var i = 0, n = numVertices, u = 0, v = 2; i < n; i++) {
-					vertices[v++] = color.r;
-					vertices[v++] = color.g;
-					vertices[v++] = color.b;
-					vertices[v++] = color.a;
-					vertices[v++] = uvs[u++];
-					vertices[v++] = uvs[u++];
-					v += 2;
-				}
-				return vertices;
+				if (!twoColorTint) {
+					for (var i = 0, n = numVertices, u = 0, v = 2; i < n; i++) {
+						vertices[v++] = color.r;
+						vertices[v++] = color.g;
+						vertices[v++] = color.b;
+						vertices[v++] = color.a;
+						vertices[v++] = uvs[u++];
+						vertices[v++] = uvs[u++];
+						v += 2;
+					}
+				}
+				else {
+					for (var i = 0, n = numVertices, u = 0, v = 2; i < n; i++) {
+						vertices[v++] = color.r;
+						vertices[v++] = color.g;
+						vertices[v++] = color.b;
+						vertices[v++] = color.a;
+						vertices[v++] = uvs[u++];
+						vertices[v++] = uvs[u++];
+						vertices[v++] = dark.r;
+						vertices[v++] = dark.g;
+						vertices[v++] = dark.b;
+						vertices[v++] = 1;
+						v += 2;
+					}
+				}
+				this.renderable.vertices = vertices;
+				this.renderable.numFloats = numVertices * (twoColorTint ? 12 : 8);
+				return this.renderable;
 			};
-			SkeletonRenderer.VERTEX_SIZE = 2 + 2 + 4;
 			SkeletonRenderer.QUAD_TRIANGLES = [0, 1, 2, 2, 3, 0];
 			return SkeletonRenderer;
 		}());

Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 0 - 0
spine-ts/build/spine-webgl.js.map


+ 26 - 6
spine-ts/build/spine-widget.d.ts

@@ -1091,6 +1091,17 @@ declare module spine {
 		length: number;
 		[n: number]: T;
 	}
+	class WindowedMean {
+		values: Array<number>;
+		addedValues: number;
+		lastValue: number;
+		mean: number;
+		dirty: boolean;
+		constructor(windowSize?: number);
+		hasEnoughData(): boolean;
+		addValue(value: number): void;
+		getMean(): number;
+	}
 }
 declare module spine.webgl {
 	class AssetManager extends spine.AssetManager {
@@ -1243,6 +1254,7 @@ declare module spine.webgl {
 		numIndices(): number;
 		setIndicesLength(length: number): void;
 		getIndices(): Uint16Array;
+		getVertexSizeInFloats(): number;
 		constructor(gl: WebGLRenderingContext, attributes: VertexAttribute[], maxVertices: number, maxIndices: number);
 		setVertices(vertices: Array<number>): void;
 		setIndices(indices: Array<number>): void;
@@ -1271,6 +1283,9 @@ declare module spine.webgl {
 	class ColorAttribute extends VertexAttribute {
 		constructor();
 	}
+	class Color2Attribute extends VertexAttribute {
+		constructor();
+	}
 	enum VertexAttributeType {
 		Float = 0,
 	}
@@ -1287,7 +1302,7 @@ declare module spine.webgl {
 		private indicesLength;
 		private srcBlend;
 		private dstBlend;
-		constructor(gl: WebGLRenderingContext, maxVertices?: number);
+		constructor(gl: WebGLRenderingContext, twoColorTint?: boolean, maxVertices?: number);
 		begin(shader: Shader): void;
 		setBlendMode(srcBlend: number, dstBlend: number): void;
 		draw(texture: GLTexture, vertices: ArrayLike<number>, indices: Array<number>): void;
@@ -1312,7 +1327,7 @@ declare module spine.webgl {
 		private QUAD;
 		private QUAD_TRIANGLES;
 		private WHITE;
-		constructor(canvas: HTMLCanvasElement, gl: WebGLRenderingContext);
+		constructor(canvas: HTMLCanvasElement, gl: WebGLRenderingContext, twoColorTint?: boolean);
 		begin(): void;
 		drawSkeleton(skeleton: Skeleton, premultipliedAlpha?: boolean): void;
 		drawSkeletonDebug(skeleton: Skeleton, premultipliedAlpha?: boolean, ignoredBones?: Array<string>): void;
@@ -1345,6 +1360,7 @@ declare module spine.webgl {
 		static MVP_MATRIX: string;
 		static POSITION: string;
 		static COLOR: string;
+		static COLOR2: string;
 		static TEXCOORDS: string;
 		static SAMPLER: string;
 		private gl;
@@ -1375,6 +1391,7 @@ declare module spine.webgl {
 		getAttributeLocation(attribute: string): number;
 		dispose(): void;
 		static newColoredTextured(gl: WebGLRenderingContext): Shader;
+		static newTwoColorTextured(gl: WebGLRenderingContext): Shader;
 		static newColored(gl: WebGLRenderingContext): Shader;
 	}
 }
@@ -1448,16 +1465,19 @@ declare module spine.webgl {
 }
 declare module spine.webgl {
 	class SkeletonRenderer {
-		static VERTEX_SIZE: number;
 		static QUAD_TRIANGLES: number[];
 		premultipliedAlpha: boolean;
 		private gl;
 		private tempColor;
+		private tempColor2;
 		private vertices;
-		constructor(gl: WebGLRenderingContext);
+		private vertexSize;
+		private twoColorTint;
+		private renderable;
+		constructor(gl: WebGLRenderingContext, twoColorTint?: boolean);
 		draw(batcher: PolygonBatcher, skeleton: Skeleton): void;
-		computeRegionVertices(slot: Slot, region: RegionAttachment, pma: boolean): ArrayLike<number>;
-		computeMeshVertices(slot: Slot, mesh: MeshAttachment, pma: boolean): ArrayLike<number>;
+		private computeRegionVertices(slot, region, pma, twoColorTint?);
+		private computeMeshVertices(slot, mesh, pma, twoColorTint?);
 	}
 }
 declare module spine.webgl {

+ 202 - 57
spine-ts/build/spine-widget.js

@@ -4065,8 +4065,10 @@ var spine;
 					if (color != null)
 						data.color.setFromString(color);
 					var dark = this.getValue(slotMap, "dark", null);
-					if (dark != null)
-						data.darkColor.setFromString(color);
+					if (dark != null) {
+						data.darkColor = new spine.Color(1, 1, 1, 1);
+						data.darkColor.setFromString(dark);
+					}
 					data.attachmentName = this.getValue(slotMap, "attachment", null);
 					data.blendMode = SkeletonJson.blendModeFromString(this.getValue(slotMap, "blend", "normal"));
 					skeletonData.slots.push(data);
@@ -4369,7 +4371,7 @@ var spine;
 								var valueMap = timelineMap[i];
 								var light = new spine.Color();
 								var dark = new spine.Color();
-								light.setFromString(valueMap.color);
+								light.setFromString(valueMap.light);
 								dark.setFromString(valueMap.dark);
 								timeline.setFrame(frameIndex, valueMap.time, light.r, light.g, light.b, light.a, dark.r, dark.g, dark.b);
 								this.readCurve(valueMap, timeline, frameIndex);
@@ -5573,6 +5575,45 @@ var spine;
 		return TimeKeeper;
 	}());
 	spine.TimeKeeper = TimeKeeper;
+	var WindowedMean = (function () {
+		function WindowedMean(windowSize) {
+			if (windowSize === void 0) { windowSize = 32; }
+			this.addedValues = 0;
+			this.lastValue = 0;
+			this.mean = 0;
+			this.dirty = true;
+			this.values = new Array(windowSize);
+		}
+		WindowedMean.prototype.hasEnoughData = function () {
+			return this.addedValues >= this.values.length;
+		};
+		WindowedMean.prototype.addValue = function (value) {
+			if (this.addedValues < this.values.length)
+				this.addedValues++;
+			this.values[this.lastValue++] = value;
+			if (this.lastValue > this.values.length - 1)
+				this.lastValue = 0;
+			this.dirty = true;
+		};
+		WindowedMean.prototype.getMean = function () {
+			if (this.hasEnoughData()) {
+				if (this.dirty) {
+					var mean = 0;
+					for (var i = 0; i < this.values.length; i++) {
+						mean += this.values[i];
+					}
+					this.mean = mean / this.values.length;
+					this.dirty = false;
+				}
+				return this.mean;
+			}
+			else {
+				return 0;
+			}
+		};
+		return WindowedMean;
+	}());
+	spine.WindowedMean = WindowedMean;
 })(spine || (spine = {}));
 var spine;
 (function (spine) {
@@ -6319,6 +6360,14 @@ var spine;
 			};
 			Mesh.prototype.getIndices = function () { return this.indices; };
 			;
+			Mesh.prototype.getVertexSizeInFloats = function () {
+				var size = 0;
+				for (var i = 0; i < this.attributes.length; i++) {
+					var attribute = this.attributes[i];
+					size += attribute.numElements;
+				}
+				return size;
+			};
 			Mesh.prototype.setVertices = function (vertices) {
 				this.dirtyVertices = true;
 				if (vertices.length > this.vertices.length)
@@ -6379,7 +6428,7 @@ var spine;
 						this.verticesBuffer = gl.createBuffer();
 					}
 					gl.bindBuffer(gl.ARRAY_BUFFER, this.verticesBuffer);
-					gl.bufferData(gl.ARRAY_BUFFER, this.vertices.subarray(0, this.verticesLength), gl.STATIC_DRAW);
+					gl.bufferData(gl.ARRAY_BUFFER, this.vertices.subarray(0, this.verticesLength), gl.DYNAMIC_DRAW);
 					this.dirtyVertices = false;
 				}
 				if (this.dirtyIndices) {
@@ -6387,7 +6436,7 @@ var spine;
 						this.indicesBuffer = gl.createBuffer();
 					}
 					gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indicesBuffer);
-					gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this.indices.subarray(0, this.indicesLength), gl.STATIC_DRAW);
+					gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this.indices.subarray(0, this.indicesLength), gl.DYNAMIC_DRAW);
 					this.dirtyIndices = false;
 				}
 			};
@@ -6441,6 +6490,14 @@ var spine;
 			return ColorAttribute;
 		}(VertexAttribute));
 		webgl.ColorAttribute = ColorAttribute;
+		var Color2Attribute = (function (_super) {
+			__extends(Color2Attribute, _super);
+			function Color2Attribute() {
+				_super.call(this, webgl.Shader.COLOR2, VertexAttributeType.Float, 4);
+			}
+			return Color2Attribute;
+		}(VertexAttribute));
+		webgl.Color2Attribute = Color2Attribute;
 		(function (VertexAttributeType) {
 			VertexAttributeType[VertexAttributeType["Float"] = 0] = "Float";
 		})(webgl.VertexAttributeType || (webgl.VertexAttributeType = {}));
@@ -6452,7 +6509,8 @@ var spine;
 	var webgl;
 	(function (webgl) {
 		var PolygonBatcher = (function () {
-			function PolygonBatcher(gl, maxVertices) {
+			function PolygonBatcher(gl, twoColorTint, maxVertices) {
+				if (twoColorTint === void 0) { twoColorTint = true; }
 				if (maxVertices === void 0) { maxVertices = 10920; }
 				this.isDrawing = false;
 				this.shader = null;
@@ -6464,7 +6522,10 @@ var spine;
 				if (maxVertices > 10920)
 					throw new Error("Can't have more than 10920 triangles per batch: " + maxVertices);
 				this.gl = gl;
-				this.mesh = new webgl.Mesh(gl, [new webgl.Position2Attribute(), new webgl.ColorAttribute(), new webgl.TexCoordAttribute()], maxVertices, maxVertices * 3);
+				var attributes = twoColorTint ?
+					[new webgl.Position2Attribute(), new webgl.ColorAttribute(), new webgl.TexCoordAttribute(), new webgl.Color2Attribute()] :
+					[new webgl.Position2Attribute(), new webgl.ColorAttribute(), new webgl.TexCoordAttribute()];
+				this.mesh = new webgl.Mesh(gl, attributes, maxVertices, maxVertices * 3);
 			}
 			PolygonBatcher.prototype.begin = function (shader) {
 				var gl = this.gl;
@@ -6542,7 +6603,8 @@ var spine;
 	var webgl;
 	(function (webgl) {
 		var SceneRenderer = (function () {
-			function SceneRenderer(canvas, gl) {
+			function SceneRenderer(canvas, gl, twoColorTint) {
+				if (twoColorTint === void 0) { twoColorTint = true; }
 				this.activeRenderer = null;
 				this.QUAD = [
 					0, 0, 1, 1, 1, 1, 0, 0,
@@ -6555,11 +6617,11 @@ var spine;
 				this.canvas = canvas;
 				this.gl = gl;
 				this.camera = new webgl.OrthoCamera(canvas.width, canvas.height);
-				this.batcherShader = webgl.Shader.newColoredTextured(gl);
-				this.batcher = new webgl.PolygonBatcher(gl);
+				this.batcherShader = twoColorTint ? webgl.Shader.newTwoColorTextured(gl) : webgl.Shader.newColoredTextured(gl);
+				this.batcher = new webgl.PolygonBatcher(gl, twoColorTint);
 				this.shapesShader = webgl.Shader.newColored(gl);
 				this.shapes = new webgl.ShapeRenderer(gl);
-				this.skeletonRenderer = new webgl.SkeletonRenderer(gl);
+				this.skeletonRenderer = new webgl.SkeletonRenderer(gl, twoColorTint);
 				this.skeletonDebugRenderer = new webgl.SkeletonDebugRenderer(gl);
 			}
 			SceneRenderer.prototype.begin = function () {
@@ -6997,6 +7059,11 @@ var spine;
 				var fs = "\n\t\t\t\t#ifdef GL_ES\n\t\t\t\t\t#define LOWP lowp\n\t\t\t\t\tprecision mediump float;\n\t\t\t\t#else\n\t\t\t\t\t#define LOWP\n\t\t\t\t#endif\n\t\t\t\tvarying LOWP vec4 v_color;\n\t\t\t\tvarying vec2 v_texCoords;\n\t\t\t\tuniform sampler2D u_texture;\n\n\t\t\t\tvoid main () {\n\t\t\t\t\tgl_FragColor = v_color * texture2D(u_texture, v_texCoords);\n\t\t\t\t}\n\t\t\t";
 				return new Shader(gl, vs, fs);
 			};
+			Shader.newTwoColorTextured = function (gl) {
+				var vs = "\n\t\t\t\tattribute vec4 " + Shader.POSITION + ";\n\t\t\t\tattribute vec4 " + Shader.COLOR + ";\n\t\t\t\tattribute vec4 " + Shader.COLOR2 + ";\n\t\t\t\tattribute vec2 " + Shader.TEXCOORDS + ";\n\t\t\t\tuniform mat4 " + Shader.MVP_MATRIX + ";\n\t\t\t\tvarying vec4 v_light;\n\t\t\t\tvarying vec4 v_dark;\n\t\t\t\tvarying vec2 v_texCoords;\n\n\t\t\t\tvoid main () {\n\t\t\t\t\tv_light = " + Shader.COLOR + ";\n\t\t\t\t\tv_dark = " + Shader.COLOR2 + ";\n\t\t\t\t\tv_texCoords = " + Shader.TEXCOORDS + ";\n\t\t\t\t\tgl_Position = " + Shader.MVP_MATRIX + " * " + Shader.POSITION + ";\n\t\t\t\t}\n\t\t\t";
+				var fs = "\n\t\t\t\t#ifdef GL_ES\n\t\t\t\t\t#define LOWP lowp\n\t\t\t\t\tprecision mediump float;\n\t\t\t\t#else\n\t\t\t\t\t#define LOWP\n\t\t\t\t#endif\n\t\t\t\tvarying LOWP vec4 v_light;\n\t\t\t\tvarying LOWP vec4 v_dark;\n\t\t\t\tvarying vec2 v_texCoords;\n\t\t\t\tuniform sampler2D u_texture;\n\n\t\t\t\tvoid main () {\n\t\t\t\t\tvec4 texColor = texture2D(u_texture, v_texCoords);\n\t\t\t\t\tfloat alpha = texColor.a * v_light.a;\n\t\t\t\t\tgl_FragColor.a = alpha;\n\t\t\t\t\tgl_FragColor.rgb = (1.0 - texColor.rgb) * v_dark.rgb * alpha + texColor.rgb * v_light.rgb;\n\t\t\t\t}\n\t\t\t";
+				return new Shader(gl, vs, fs);
+			};
 			Shader.newColored = function (gl) {
 				var vs = "\n\t\t\t\tattribute vec4 " + Shader.POSITION + ";\n\t\t\t\tattribute vec4 " + Shader.COLOR + ";\n\t\t\t\tuniform mat4 " + Shader.MVP_MATRIX + ";\n\t\t\t\tvarying vec4 v_color;\n\n\t\t\t\tvoid main () {\n\t\t\t\t\tv_color = " + Shader.COLOR + ";\n\t\t\t\t\tgl_Position = " + Shader.MVP_MATRIX + " * " + Shader.POSITION + ";\n\t\t\t\t}\n\t\t\t";
 				var fs = "\n\t\t\t\t#ifdef GL_ES\n\t\t\t\t\t#define LOWP lowp\n\t\t\t\t\tprecision mediump float;\n\t\t\t\t#else\n\t\t\t\t\t#define LOWP\n\t\t\t\t#endif\n\t\t\t\tvarying LOWP vec4 v_color;\n\n\t\t\t\tvoid main () {\n\t\t\t\t\tgl_FragColor = v_color;\n\t\t\t\t}\n\t\t\t";
@@ -7005,6 +7072,7 @@ var spine;
 			Shader.MVP_MATRIX = "u_projTrans";
 			Shader.POSITION = "a_position";
 			Shader.COLOR = "a_color";
+			Shader.COLOR2 = "a_color2";
 			Shader.TEXCOORDS = "a_texCoords";
 			Shader.SAMPLER = "u_texture";
 			return Shader;
@@ -7360,7 +7428,7 @@ var spine;
 				this.boneWidth = 2;
 				this.bounds = new spine.SkeletonBounds();
 				this.temp = new Array();
-				this.vertices = spine.Utils.newFloatArray(webgl.SkeletonRenderer.VERTEX_SIZE * 1024);
+				this.vertices = spine.Utils.newFloatArray(2 * 1024);
 				this.gl = gl;
 			}
 			SkeletonDebugRenderer.prototype.draw = function (shapes, skeleton, ignoredBones) {
@@ -7509,12 +7577,28 @@ var spine;
 (function (spine) {
 	var webgl;
 	(function (webgl) {
+		var Renderable = (function () {
+			function Renderable(vertices, numFloats) {
+				this.vertices = vertices;
+				this.numFloats = numFloats;
+			}
+			return Renderable;
+		}());
+		;
 		var SkeletonRenderer = (function () {
-			function SkeletonRenderer(gl) {
+			function SkeletonRenderer(gl, twoColorTint) {
+				if (twoColorTint === void 0) { twoColorTint = true; }
 				this.premultipliedAlpha = false;
 				this.tempColor = new spine.Color();
-				this.vertices = spine.Utils.newFloatArray(SkeletonRenderer.VERTEX_SIZE * 1024);
+				this.tempColor2 = new spine.Color();
+				this.vertexSize = 2 + 2 + 4;
+				this.twoColorTint = false;
+				this.renderable = new Renderable(null, 0);
 				this.gl = gl;
+				this.twoColorTint = twoColorTint;
+				if (twoColorTint)
+					this.vertexSize += 4;
+				this.vertices = spine.Utils.newFloatArray(this.vertexSize * 1024);
 			}
 			SkeletonRenderer.prototype.draw = function (batcher, skeleton) {
 				var premultipliedAlpha = this.premultipliedAlpha;
@@ -7528,13 +7612,13 @@ var spine;
 					var texture = null;
 					if (attachment instanceof spine.RegionAttachment) {
 						var region = attachment;
-						vertices = this.computeRegionVertices(slot, region, premultipliedAlpha);
+						vertices = this.computeRegionVertices(slot, region, premultipliedAlpha, this.twoColorTint);
 						triangles = SkeletonRenderer.QUAD_TRIANGLES;
 						texture = region.region.renderObject.texture;
 					}
 					else if (attachment instanceof spine.MeshAttachment) {
 						var mesh = attachment;
-						vertices = this.computeMeshVertices(slot, mesh, premultipliedAlpha);
+						vertices = this.computeMeshVertices(slot, mesh, premultipliedAlpha, this.twoColorTint);
 						triangles = mesh.triangles;
 						texture = mesh.region.renderObject.texture;
 					}
@@ -7546,11 +7630,13 @@ var spine;
 							blendMode = slotBlendMode;
 							batcher.setBlendMode(webgl.getSourceGLBlendMode(this.gl, blendMode, premultipliedAlpha), webgl.getDestGLBlendMode(this.gl, blendMode));
 						}
-						batcher.draw(texture, vertices, triangles);
+						var view = vertices.vertices.subarray(0, vertices.numFloats);
+						batcher.draw(texture, view, triangles);
 					}
 				}
 			};
-			SkeletonRenderer.prototype.computeRegionVertices = function (slot, region, pma) {
+			SkeletonRenderer.prototype.computeRegionVertices = function (slot, region, pma, twoColorTint) {
+				if (twoColorTint === void 0) { twoColorTint = false; }
 				var skeleton = slot.bone.skeleton;
 				var skeletonColor = skeleton.color;
 				var slotColor = slot.color;
@@ -7559,36 +7645,72 @@ var spine;
 				var multiplier = pma ? alpha : 1;
 				var color = this.tempColor;
 				color.set(skeletonColor.r * slotColor.r * regionColor.r * multiplier, skeletonColor.g * slotColor.g * regionColor.g * multiplier, skeletonColor.b * slotColor.b * regionColor.b * multiplier, alpha);
-				region.computeWorldVertices(slot.bone, this.vertices, 0, SkeletonRenderer.VERTEX_SIZE);
+				var dark = this.tempColor2;
+				if (slot.darkColor == null)
+					dark.set(0, 0, 0, 1);
+				else
+					dark.setFromColor(slot.darkColor);
+				region.computeWorldVertices(slot.bone, this.vertices, 0, this.vertexSize);
 				var vertices = this.vertices;
 				var uvs = region.uvs;
-				vertices[spine.RegionAttachment.C1R] = color.r;
-				vertices[spine.RegionAttachment.C1G] = color.g;
-				vertices[spine.RegionAttachment.C1B] = color.b;
-				vertices[spine.RegionAttachment.C1A] = color.a;
-				vertices[spine.RegionAttachment.U1] = uvs[0];
-				vertices[spine.RegionAttachment.V1] = uvs[1];
-				vertices[spine.RegionAttachment.C2R] = color.r;
-				vertices[spine.RegionAttachment.C2G] = color.g;
-				vertices[spine.RegionAttachment.C2B] = color.b;
-				vertices[spine.RegionAttachment.C2A] = color.a;
-				vertices[spine.RegionAttachment.U2] = uvs[2];
-				vertices[spine.RegionAttachment.V2] = uvs[3];
-				vertices[spine.RegionAttachment.C3R] = color.r;
-				vertices[spine.RegionAttachment.C3G] = color.g;
-				vertices[spine.RegionAttachment.C3B] = color.b;
-				vertices[spine.RegionAttachment.C3A] = color.a;
-				vertices[spine.RegionAttachment.U3] = uvs[4];
-				vertices[spine.RegionAttachment.V3] = uvs[5];
-				vertices[spine.RegionAttachment.C4R] = color.r;
-				vertices[spine.RegionAttachment.C4G] = color.g;
-				vertices[spine.RegionAttachment.C4B] = color.b;
-				vertices[spine.RegionAttachment.C4A] = color.a;
-				vertices[spine.RegionAttachment.U4] = uvs[6];
-				vertices[spine.RegionAttachment.V4] = uvs[7];
-				return vertices;
+				var i = 2;
+				vertices[i++] = color.r;
+				vertices[i++] = color.g;
+				vertices[i++] = color.b;
+				vertices[i++] = color.a;
+				vertices[i++] = uvs[0];
+				vertices[i++] = uvs[1];
+				if (twoColorTint) {
+					vertices[i++] = dark.r;
+					vertices[i++] = dark.g;
+					vertices[i++] = dark.b;
+					vertices[i++] = 1;
+				}
+				i += 2;
+				vertices[i++] = color.r;
+				vertices[i++] = color.g;
+				vertices[i++] = color.b;
+				vertices[i++] = color.a;
+				vertices[i++] = uvs[2];
+				vertices[i++] = uvs[3];
+				if (twoColorTint) {
+					vertices[i++] = dark.r;
+					vertices[i++] = dark.g;
+					vertices[i++] = dark.b;
+					vertices[i++] = 1;
+				}
+				i += 2;
+				vertices[i++] = color.r;
+				vertices[i++] = color.g;
+				vertices[i++] = color.b;
+				vertices[i++] = color.a;
+				vertices[i++] = uvs[4];
+				vertices[i++] = uvs[5];
+				if (twoColorTint) {
+					vertices[i++] = dark.r;
+					vertices[i++] = dark.g;
+					vertices[i++] = dark.b;
+					vertices[i++] = 1;
+				}
+				i += 2;
+				vertices[i++] = color.r;
+				vertices[i++] = color.g;
+				vertices[i++] = color.b;
+				vertices[i++] = color.a;
+				vertices[i++] = uvs[6];
+				vertices[i++] = uvs[7];
+				if (twoColorTint) {
+					vertices[i++] = dark.r;
+					vertices[i++] = dark.g;
+					vertices[i++] = dark.b;
+					vertices[i++] = 1;
+				}
+				this.renderable.vertices = vertices;
+				this.renderable.numFloats = 4 * (twoColorTint ? 12 : 8);
+				return this.renderable;
 			};
-			SkeletonRenderer.prototype.computeMeshVertices = function (slot, mesh, pma) {
+			SkeletonRenderer.prototype.computeMeshVertices = function (slot, mesh, pma, twoColorTint) {
+				if (twoColorTint === void 0) { twoColorTint = false; }
 				var skeleton = slot.bone.skeleton;
 				var skeletonColor = skeleton.color;
 				var slotColor = slot.color;
@@ -7597,25 +7719,48 @@ var spine;
 				var multiplier = pma ? alpha : 1;
 				var color = this.tempColor;
 				color.set(skeletonColor.r * slotColor.r * regionColor.r * multiplier, skeletonColor.g * slotColor.g * regionColor.g * multiplier, skeletonColor.b * slotColor.b * regionColor.b * multiplier, alpha);
+				var dark = this.tempColor2;
+				if (slot.darkColor == null)
+					dark.set(0, 0, 0, 1);
+				else
+					dark.setFromColor(slot.darkColor);
 				var numVertices = mesh.worldVerticesLength / 2;
 				if (this.vertices.length < mesh.worldVerticesLength) {
 					this.vertices = spine.Utils.newFloatArray(mesh.worldVerticesLength);
 				}
 				var vertices = this.vertices;
-				mesh.computeWorldVertices(slot, 0, mesh.worldVerticesLength, vertices, 0, SkeletonRenderer.VERTEX_SIZE);
+				mesh.computeWorldVertices(slot, 0, mesh.worldVerticesLength, vertices, 0, this.vertexSize);
 				var uvs = mesh.uvs;
-				for (var i = 0, n = numVertices, u = 0, v = 2; i < n; i++) {
-					vertices[v++] = color.r;
-					vertices[v++] = color.g;
-					vertices[v++] = color.b;
-					vertices[v++] = color.a;
-					vertices[v++] = uvs[u++];
-					vertices[v++] = uvs[u++];
-					v += 2;
-				}
-				return vertices;
+				if (!twoColorTint) {
+					for (var i = 0, n = numVertices, u = 0, v = 2; i < n; i++) {
+						vertices[v++] = color.r;
+						vertices[v++] = color.g;
+						vertices[v++] = color.b;
+						vertices[v++] = color.a;
+						vertices[v++] = uvs[u++];
+						vertices[v++] = uvs[u++];
+						v += 2;
+					}
+				}
+				else {
+					for (var i = 0, n = numVertices, u = 0, v = 2; i < n; i++) {
+						vertices[v++] = color.r;
+						vertices[v++] = color.g;
+						vertices[v++] = color.b;
+						vertices[v++] = color.a;
+						vertices[v++] = uvs[u++];
+						vertices[v++] = uvs[u++];
+						vertices[v++] = dark.r;
+						vertices[v++] = dark.g;
+						vertices[v++] = dark.b;
+						vertices[v++] = 1;
+						v += 2;
+					}
+				}
+				this.renderable.vertices = vertices;
+				this.renderable.numFloats = numVertices * (twoColorTint ? 12 : 8);
+				return this.renderable;
 			};
-			SkeletonRenderer.VERTEX_SIZE = 2 + 2 + 4;
 			SkeletonRenderer.QUAD_TRIANGLES = [0, 1, 2, 2, 3, 0];
 			return SkeletonRenderer;
 		}());

Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 0 - 0
spine-ts/build/spine-widget.js.map


+ 5 - 2
spine-ts/core/src/SkeletonJson.ts

@@ -94,7 +94,10 @@ module spine {
 					if (color != null) data.color.setFromString(color);
 
 					let dark: string = this.getValue(slotMap, "dark", null);
-					if (dark != null) data.darkColor.setFromString(color);
+					if (dark != null) {
+						data.darkColor = new Color(1, 1, 1, 1);
+						data.darkColor.setFromString(dark);
+					}
 
 					data.attachmentName = this.getValue(slotMap, "attachment", null);
 					data.blendMode = SkeletonJson.blendModeFromString(this.getValue(slotMap, "blend", "normal"));
@@ -421,7 +424,7 @@ module spine {
 								let valueMap = timelineMap[i];
 								let light = new Color();
 								let dark = new Color();
-								light.setFromString(valueMap.color);
+								light.setFromString(valueMap.light);
 								dark.setFromString(valueMap.dark);
 								timeline.setFrame(frameIndex, valueMap.time, light.r, light.g, light.b, light.a, dark.r, dark.g, dark.b);
 								this.readCurve(valueMap, timeline, frameIndex);

+ 40 - 0
spine-ts/core/src/Utils.ts

@@ -296,4 +296,44 @@ module spine {
 		length: number;
 		[n: number]: T;
 	}
+
+	export class WindowedMean {
+		values: Array<number>;
+		addedValues = 0;
+		lastValue = 0;
+		mean = 0;
+		dirty = true;
+
+		constructor (windowSize: number = 32) {
+			this.values = new Array<number>(windowSize);
+		}
+
+		hasEnoughData () {
+			return this.addedValues >= this.values.length;
+		}
+
+		addValue (value: number) {
+			if (this.addedValues < this.values.length)
+				this.addedValues++;
+			this.values[this.lastValue++] = value;
+			if (this.lastValue > this.values.length - 1) this.lastValue = 0;
+			this.dirty = true;
+		}
+
+		getMean () {
+			if (this.hasEnoughData()) {
+				if (this.dirty) {
+					let mean = 0;
+					for (let i = 0; i < this.values.length; i++) {
+						mean += this.values[i];
+					}
+					this.mean = mean / this.values.length;
+					this.dirty = false;
+				}
+				return this.mean;
+			} else {
+				return 0;
+			}
+		}
+	}
 }

+ 13 - 0
spine-ts/webgl/example/assets/twocolor.atlas

@@ -0,0 +1,13 @@
+
+twocolor.png
+size: 512,512
+format: RGBA8888
+filter: Linear,Linear
+repeat: none
+squareWithBorder
+  rotate: false
+  xy: 2, 2
+  size: 300, 300
+  orig: 300, 300
+  offset: 0, 0
+  index: -1

+ 66 - 0
spine-ts/webgl/example/assets/twocolor.json

@@ -0,0 +1,66 @@
+{
+"skeleton": { "hash": "F1HM8+VG3WR6tPJTA5IpJM8nDs4", "spine": "3.6.05-beta", "width": 300.48, "height": 300.48 },
+"bones": [
+	{ "name": "root", "rotation": -0.09 },
+	{ "name": "singleColorTint", "parent": "root", "x": -400 },
+	{ "name": "twoColorTint", "parent": "root", "x": 800 },
+	{ "name": "twoColorTint (blackOnly)", "parent": "root" },
+	{ "name": "twoColorTint (colorOnly)", "parent": "root", "x": 400 }
+],
+"slots": [
+	{ "name": "squareWithBorder", "bone": "singleColorTint", "attachment": "squareWithBorder" },
+	{ "name": "squareWithBorder2", "bone": "twoColorTint (blackOnly)", "dark": "000000", "attachment": "squareWithBorder" },
+	{ "name": "squareWithBorder4", "bone": "twoColorTint (colorOnly)", "dark": "000000", "attachment": "squareWithBorder" },
+	{ "name": "squareWithBorder3", "bone": "twoColorTint", "dark": "000000", "attachment": "squareWithBorder" }
+],
+"skins": {
+	"default": {
+		"squareWithBorder": {
+			"squareWithBorder": { "width": 300, "height": 300 }
+		},
+		"squareWithBorder2": {
+			"squareWithBorder": { "width": 300, "height": 300 }
+		},
+		"squareWithBorder3": {
+			"squareWithBorder": { "width": 300, "height": 300 }
+		},
+		"squareWithBorder4": {
+			"squareWithBorder": { "width": 300, "height": 300 }
+		}
+	}
+},
+"animations": {
+	"animation": {
+		"slots": {
+			"squareWithBorder": {
+				"color": [
+					{ "time": 0, "color": "fffffffe" },
+					{ "time": 1, "color": "9e17b3fe" },
+					{ "time": 2, "color": "fffffffe" }
+				]
+			},
+			"squareWithBorder2": {
+				"twoColor": [
+					{ "time": 0, "light": "fffffffe", "dark": "000000" },
+					{ "time": 1, "light": "fffffffe", "dark": "ff0000" },
+					{ "time": 2, "light": "fffffffe", "dark": "000000" }
+				]
+			},
+			"squareWithBorder3": {
+				"twoColor": [
+					{ "time": 0, "light": "fffffffe", "dark": "000000" },
+					{ "time": 1, "light": "80ff00fe", "dark": "001cff" },
+					{ "time": 2, "light": "fffffffe", "dark": "000000" }
+				]
+			},
+			"squareWithBorder4": {
+				"twoColor": [
+					{ "time": 0, "light": "fffffffe", "dark": "000000" },
+					{ "time": 1, "light": "ffd300fe", "dark": "000000" },
+					{ "time": 2, "light": "fffffffe", "dark": "000000" }
+				]
+			}
+		}
+	}
+}
+}

BIN
spine-ts/webgl/example/assets/twocolor.png


+ 40 - 19
spine-ts/webgl/example/test.html

@@ -7,13 +7,17 @@
 	canvas { position: absolute; width: 100% ;height: 100%; }
 </style>
 <body>
+<div id="label" style="position: absolute; top: 0; left: 0; color: #fff; z-index: 10"></div>
 <canvas id="canvas"></canvas>
 </body>
 <script>
 
 var canvas, gl, renderer, input, assetManager;
-var skeleton, bounds, state;
+var skeletons = [];
 var timeKeeper;
+var label = document.getElementById("label");
+var updateMean = new spine.WindowedMean();
+var renderMean = new spine.WindowedMean();
 
 function init() {
 	canvas = document.getElementById("canvas");
@@ -24,9 +28,9 @@ function init() {
 	assetManager = new spine.webgl.AssetManager(gl, "assets/");
 	var textureLoader = function(img) { return new spine.webgl.GLTexture(gl, img); };
 	input = new spine.webgl.Input(canvas);
-	assetManager.loadTexture("raptor.png");
-	assetManager.loadText("raptor.atlas");
-	assetManager.loadText("raptor.json");
+	assetManager.loadTexture("spineboy.png");
+	assetManager.loadText("spineboy.atlas");
+	assetManager.loadText("spineboy.json");
 	timeKeeper = new spine.TimeKeeper();
 	requestAnimationFrame(load);
 }
@@ -34,21 +38,25 @@ function init() {
 function load() {
 	timeKeeper.update();
 	if (assetManager.isLoadingComplete()) {
-		var atlas = new spine.TextureAtlas(assetManager.get("raptor.atlas"), function(path) {
+		var atlas = new spine.TextureAtlas(assetManager.get("spineboy.atlas"), function(path) {
 			return assetManager.get(path);
 		});
 		var atlasLoader = new spine.AtlasAttachmentLoader(atlas);
 		var skeletonJson = new spine.SkeletonJson(atlasLoader);
-		skeletonJson.scale = 0.5;
-		var skeletonData = skeletonJson.readSkeletonData(JSON.parse(assetManager.get("raptor.json")));
-		skeleton = new spine.Skeleton(skeletonData);
-		var stateData = new spine.AnimationStateData(skeleton.data);
-		state = new spine.AnimationState(stateData);
-		stateData.setMix("walk", "Jump", 0.5);
-		state.setAnimation(0, "walk", false);
-		state.addAnimation(0, "Jump", false, 0);
-		state.apply(skeleton);
-		skeleton.updateWorldTransform();
+		skeletonJson.scale = 0.01;
+		var skeletonData = skeletonJson.readSkeletonData(JSON.parse(assetManager.get("spineboy.json")));
+
+		for (var i = 0; i < 1000; i++) {
+			skeleton = new spine.Skeleton(skeletonData);
+			var stateData = new spine.AnimationStateData(skeleton.data);
+			state = new spine.AnimationState(stateData);
+			state.setAnimation(0, "walk", true);
+			state.apply(skeleton);
+			skeleton.x = Math.random() * 200 - Math.random() * 200;
+			skeleton.y = Math.random() * 200 - Math.random() * 200;
+			skeleton.updateWorldTransform();
+			skeletons.push({ skeleton: skeleton, state: state });
+		}
 
 		requestAnimationFrame(render);
 	} else {
@@ -57,23 +65,36 @@ function load() {
 }
 
 function render() {
+	var start = Date.now()
 	timeKeeper.update();
 	var delta = timeKeeper.delta;
 	delta = 0.016;
 
-	state.update(delta);
-	state.apply(skeleton);
-	skeleton.updateWorldTransform();
+	for (var i = 0; i < skeletons.length; i++) {
+		var state = skeletons[i].state;
+		var skeleton = skeletons[i].skeleton;
+		state.update(delta);
+		state.apply(skeleton);
+		skeleton.updateWorldTransform();
+	}
+	updateMean.addValue(Date.now() - start);
+	start = Date.now();
 
 	gl.clearColor(0, 0, 0, 1);
 	gl.clear(gl.COLOR_BUFFER_BIT);
 
 	renderer.resize(spine.webgl.ResizeMode.Fit);
 	renderer.begin();
-	renderer.drawSkeleton(skeleton);
+	for (var i = 0; i < skeletons.length; i++) {
+		var skeleton = skeletons[i].skeleton;
+		renderer.drawSkeleton(skeleton);
+	}
 	renderer.end();
 
 	requestAnimationFrame(render)
+	renderMean.addValue(Date.now() - start);
+	label.innerHTML = ("Update time: " + Number(updateMean.getMean()).toFixed(2) + " ms\n" +
+					   "Render time: " + Number(renderMean.getMean()).toFixed(2) + " ms\n");
 }
 
 init();

+ 17 - 2
spine-ts/webgl/src/Mesh.ts

@@ -59,6 +59,15 @@ module spine.webgl {
 		}
 		getIndices (): Uint16Array { return this.indices };
 
+		getVertexSizeInFloats (): number {
+			let size = 0;
+			for (var i = 0; i < this.attributes.length; i++) {
+				let attribute = this.attributes[i];
+				size += attribute.numElements;
+			}
+			return size;
+		}
+
 		constructor (gl: WebGLRenderingContext, private attributes: VertexAttribute[], maxVertices: number, maxIndices: number) {
 			this.gl = gl;
 			this.elementsPerVertex = 0;
@@ -128,7 +137,7 @@ module spine.webgl {
 					this.verticesBuffer = gl.createBuffer();
 				}
 				gl.bindBuffer(gl.ARRAY_BUFFER, this.verticesBuffer);
-				gl.bufferData(gl.ARRAY_BUFFER, this.vertices.subarray(0, this.verticesLength), gl.STATIC_DRAW);
+				gl.bufferData(gl.ARRAY_BUFFER, this.vertices.subarray(0, this.verticesLength), gl.DYNAMIC_DRAW);
 				this.dirtyVertices = false;
 			}
 
@@ -137,7 +146,7 @@ module spine.webgl {
 					this.indicesBuffer = gl.createBuffer();
 				}
 				gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indicesBuffer);
-				gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this.indices.subarray(0, this.indicesLength), gl.STATIC_DRAW);
+				gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this.indices.subarray(0, this.indicesLength), gl.DYNAMIC_DRAW);
 				this.dirtyIndices = false;
 			}
 		}
@@ -177,6 +186,12 @@ module spine.webgl {
 		}
 	}
 
+	export class Color2Attribute extends VertexAttribute {
+		constructor () {
+			super(Shader.COLOR2, VertexAttributeType.Float, 4);
+		}
+	}
+
 	export enum VertexAttributeType {
 		Float
 	}

+ 5 - 2
spine-ts/webgl/src/PolygonBatcher.ts

@@ -41,10 +41,13 @@ module spine.webgl {
 		private srcBlend: number = WebGLRenderingContext.SRC_ALPHA;
 		private dstBlend: number = WebGLRenderingContext.ONE_MINUS_SRC_ALPHA;
 
-		constructor (gl: WebGLRenderingContext, maxVertices: number = 10920) {
+		constructor (gl: WebGLRenderingContext, twoColorTint: boolean = true, maxVertices: number = 10920) {
 			if (maxVertices > 10920) throw new Error("Can't have more than 10920 triangles per batch: " + maxVertices);
 			this.gl = gl;
-			this.mesh = new Mesh(gl, [new Position2Attribute(), new ColorAttribute(), new TexCoordAttribute()], maxVertices, maxVertices * 3);
+			let attributes = twoColorTint ?
+					[new Position2Attribute(), new ColorAttribute(), new TexCoordAttribute(), new Color2Attribute()] :
+					[new Position2Attribute(), new ColorAttribute(), new TexCoordAttribute()];
+			this.mesh = new Mesh(gl, attributes, maxVertices, maxVertices * 3);
 		}
 
 		begin (shader: Shader) {

+ 5 - 5
spine-ts/webgl/src/SceneRenderer.ts

@@ -49,15 +49,15 @@ module spine.webgl {
 		private QUAD_TRIANGLES = [0, 1, 2, 2, 3, 0];
 		private WHITE = new Color(1, 1, 1, 1);
 
-		constructor (canvas: HTMLCanvasElement, gl: WebGLRenderingContext) {
+		constructor (canvas: HTMLCanvasElement, gl: WebGLRenderingContext, twoColorTint: boolean = true) {
 			this.canvas = canvas;
 			this.gl = gl;
 			this.camera = new OrthoCamera(canvas.width, canvas.height);
-			this.batcherShader = Shader.newColoredTextured(gl);
-			this.batcher = new PolygonBatcher(gl);
+			this.batcherShader = twoColorTint ? Shader.newTwoColorTextured(gl) : Shader.newColoredTextured(gl);
+			this.batcher = new PolygonBatcher(gl, twoColorTint);
 			this.shapesShader = Shader.newColored(gl);
-			this.shapes = new ShapeRenderer(gl); 
-			this.skeletonRenderer = new SkeletonRenderer(gl);
+			this.shapes = new ShapeRenderer(gl);
+			this.skeletonRenderer = new SkeletonRenderer(gl, twoColorTint);
 			this.skeletonDebugRenderer = new SkeletonDebugRenderer(gl);
 		}
 

+ 43 - 0
spine-ts/webgl/src/Shader.ts

@@ -33,6 +33,7 @@ module spine.webgl {
 		public static MVP_MATRIX = "u_projTrans";
 		public static POSITION = "a_position";
 		public static COLOR = "a_color";
+		public static COLOR2 = "a_color2";
 		public static TEXCOORDS = "a_texCoords";
 		public static SAMPLER = "u_texture";
 
@@ -206,6 +207,48 @@ module spine.webgl {
 			return new Shader(gl, vs, fs);
 		}
 
+		public static newTwoColorTextured (gl: WebGLRenderingContext): Shader {
+			let vs = `
+				attribute vec4 ${Shader.POSITION};
+				attribute vec4 ${Shader.COLOR};
+				attribute vec4 ${Shader.COLOR2};
+				attribute vec2 ${Shader.TEXCOORDS};
+				uniform mat4 ${Shader.MVP_MATRIX};
+				varying vec4 v_light;
+				varying vec4 v_dark;
+				varying vec2 v_texCoords;
+
+				void main () {
+					v_light = ${Shader.COLOR};
+					v_dark = ${Shader.COLOR2};
+					v_texCoords = ${Shader.TEXCOORDS};
+					gl_Position = ${Shader.MVP_MATRIX} * ${Shader.POSITION};
+				}
+			`;
+
+			let fs = `
+				#ifdef GL_ES
+					#define LOWP lowp
+					precision mediump float;
+				#else
+					#define LOWP
+				#endif
+				varying LOWP vec4 v_light;
+				varying LOWP vec4 v_dark;
+				varying vec2 v_texCoords;
+				uniform sampler2D u_texture;
+
+				void main () {
+					vec4 texColor = texture2D(u_texture, v_texCoords);
+					float alpha = texColor.a * v_light.a;
+					gl_FragColor.a = alpha;
+					gl_FragColor.rgb = (1.0 - texColor.rgb) * v_dark.rgb * alpha + texColor.rgb * v_light.rgb;
+				}
+			`;
+
+			return new Shader(gl, vs, fs);
+		}
+
 		public static newColored (gl: WebGLRenderingContext): Shader {
 			let vs = `
 				attribute vec4 ${Shader.POSITION};

+ 1 - 1
spine-ts/webgl/src/SkeletonDebugRenderer.ts

@@ -50,7 +50,7 @@ module spine.webgl {
 		private gl: WebGLRenderingContext;
 		private bounds = new SkeletonBounds();
 		private temp = new Array<number>();
-		private vertices = Utils.newFloatArray(SkeletonRenderer.VERTEX_SIZE * 1024);
+		private vertices = Utils.newFloatArray(2 * 1024);
 		private static LIGHT_GRAY = new Color(192 / 255, 192 / 255, 192 / 255, 1);
 		private static GREEN = new Color(0, 1, 0, 1);
 

+ 116 - 49
spine-ts/webgl/src/SkeletonRenderer.ts

@@ -29,24 +29,35 @@
  *****************************************************************************/
 
 module spine.webgl {
+	class Renderable {
+		constructor(public vertices: ArrayLike<number>, public numFloats: number) {}
+	};
+
 	export class SkeletonRenderer {
-		static VERTEX_SIZE = 2 + 2 + 4;
 		static QUAD_TRIANGLES = [0, 1, 2, 2, 3, 0];
 
 		premultipliedAlpha = false;
 		private gl: WebGLRenderingContext;
 		private tempColor = new Color();
-		private vertices = Utils.newFloatArray(SkeletonRenderer.VERTEX_SIZE * 1024);
+		private tempColor2 = new Color();
+		private vertices:ArrayLike<number>;
+		private vertexSize = 2 + 2 + 4;
+		private twoColorTint = false;
+		private renderable: Renderable = new Renderable(null, 0);
 
-		constructor (gl: WebGLRenderingContext) {
+		constructor (gl: WebGLRenderingContext, twoColorTint: boolean = true) {
 			this.gl = gl;
+			this.twoColorTint = twoColorTint;
+			if (twoColorTint)
+				this.vertexSize += 4;
+			this.vertices = Utils.newFloatArray(this.vertexSize * 1024);
 		}
 
 		draw (batcher: PolygonBatcher, skeleton: Skeleton) {
 			let premultipliedAlpha = this.premultipliedAlpha;
 			let blendMode: BlendMode = null;
 
-			let vertices: ArrayLike<number> = null;
+			let vertices: Renderable = null;
 			let triangles: Array<number> = null;
 			let drawOrder = skeleton.drawOrder;
 			for (let i = 0, n = drawOrder.length; i < n; i++) {
@@ -55,13 +66,13 @@ module spine.webgl {
 				let texture: GLTexture = null;
 				if (attachment instanceof RegionAttachment) {
 					let region = <RegionAttachment>attachment;
-					vertices = this.computeRegionVertices(slot, region, premultipliedAlpha);
+					vertices = this.computeRegionVertices(slot, region, premultipliedAlpha, this.twoColorTint);
 					triangles = SkeletonRenderer.QUAD_TRIANGLES;
 					texture = <GLTexture>(<TextureAtlasRegion>region.region.renderObject).texture;
 
 				} else if (attachment instanceof MeshAttachment) {
 					let mesh = <MeshAttachment>attachment;
-					vertices = this.computeMeshVertices(slot, mesh, premultipliedAlpha);
+					vertices = this.computeMeshVertices(slot, mesh, premultipliedAlpha, this.twoColorTint);
 					triangles = mesh.triangles;
 					texture = <GLTexture>(<TextureAtlasRegion>mesh.region.renderObject).texture;
 				} else continue;
@@ -72,12 +83,14 @@ module spine.webgl {
 						blendMode = slotBlendMode;
 						batcher.setBlendMode(getSourceGLBlendMode(this.gl, blendMode, premultipliedAlpha), getDestGLBlendMode(this.gl, blendMode));
 					}
-					batcher.draw(texture, vertices, triangles);
+
+					let view = (vertices.vertices as Float32Array).subarray(0, vertices.numFloats);
+					batcher.draw(texture, view, triangles);
 				}
 			}
 		}
 
-		computeRegionVertices(slot: Slot, region: RegionAttachment, pma: boolean) {
+		private computeRegionVertices(slot: Slot, region: RegionAttachment, pma: boolean, twoColorTint: boolean = false) {
 			let skeleton = slot.bone.skeleton;
 			let skeletonColor = skeleton.color;
 			let slotColor = slot.color;
@@ -89,44 +102,77 @@ module spine.webgl {
 					  skeletonColor.g * slotColor.g * regionColor.g * multiplier,
 					  skeletonColor.b * slotColor.b * regionColor.b * multiplier,
 					  alpha);
+			let dark = this.tempColor2;
+			if (slot.darkColor == null) dark.set(0, 0, 0, 1);
+			else dark.setFromColor(slot.darkColor);
 
-			region.computeWorldVertices(slot.bone, this.vertices, 0, SkeletonRenderer.VERTEX_SIZE);
+			region.computeWorldVertices(slot.bone, this.vertices, 0, this.vertexSize);
 
 			let vertices = this.vertices;
 			let uvs = region.uvs;
 
-			vertices[RegionAttachment.C1R] = color.r;
-			vertices[RegionAttachment.C1G] = color.g;
-			vertices[RegionAttachment.C1B] = color.b;
-			vertices[RegionAttachment.C1A] = color.a;
-			vertices[RegionAttachment.U1] = uvs[0];
-			vertices[RegionAttachment.V1] = uvs[1];
-
-			vertices[RegionAttachment.C2R] = color.r;
-			vertices[RegionAttachment.C2G] = color.g;
-			vertices[RegionAttachment.C2B] = color.b;
-			vertices[RegionAttachment.C2A] = color.a;
-			vertices[RegionAttachment.U2] = uvs[2];
-			vertices[RegionAttachment.V2] = uvs[3];
-
-			vertices[RegionAttachment.C3R] = color.r;
-			vertices[RegionAttachment.C3G] = color.g;
-			vertices[RegionAttachment.C3B] = color.b;
-			vertices[RegionAttachment.C3A] = color.a;
-			vertices[RegionAttachment.U3] = uvs[4];
-			vertices[RegionAttachment.V3] = uvs[5];
-
-			vertices[RegionAttachment.C4R] = color.r;
-			vertices[RegionAttachment.C4G] = color.g;
-			vertices[RegionAttachment.C4B] = color.b;
-			vertices[RegionAttachment.C4A] = color.a;
-			vertices[RegionAttachment.U4] = uvs[6];
-			vertices[RegionAttachment.V4] = uvs[7];
-
-			return vertices;
+			let i = 2;
+			vertices[i++] = color.r;
+			vertices[i++] = color.g;
+			vertices[i++] = color.b;
+			vertices[i++] = color.a;
+			vertices[i++] = uvs[0];
+			vertices[i++] = uvs[1];
+			if (twoColorTint) {
+				vertices[i++] = dark.r;
+				vertices[i++] = dark.g;
+				vertices[i++] = dark.b;
+				vertices[i++] = 1;
+			}
+			i+=2;
+
+			vertices[i++] = color.r;
+			vertices[i++] = color.g;
+			vertices[i++] = color.b;
+			vertices[i++] = color.a;
+			vertices[i++] = uvs[2];
+			vertices[i++] = uvs[3];
+			if (twoColorTint) {
+				vertices[i++] = dark.r;
+				vertices[i++] = dark.g;
+				vertices[i++] = dark.b;
+				vertices[i++] = 1;
+			}
+			i+=2;
+
+			vertices[i++] = color.r;
+			vertices[i++] = color.g;
+			vertices[i++] = color.b;
+			vertices[i++] = color.a;
+			vertices[i++] = uvs[4];
+			vertices[i++] = uvs[5];
+			if (twoColorTint) {
+				vertices[i++] = dark.r;
+				vertices[i++] = dark.g;
+				vertices[i++] = dark.b;
+				vertices[i++] = 1;
+			}
+			i+=2;
+
+			vertices[i++] = color.r;
+			vertices[i++] = color.g;
+			vertices[i++] = color.b;
+			vertices[i++] = color.a;
+			vertices[i++] = uvs[6];
+			vertices[i++] = uvs[7];
+			if (twoColorTint) {
+				vertices[i++] = dark.r;
+				vertices[i++] = dark.g;
+				vertices[i++] = dark.b;
+				vertices[i++] = 1;
+			}
+
+			this.renderable.vertices = vertices;
+			this.renderable.numFloats = 4 * (twoColorTint ? 12 :  8);
+			return this.renderable;
 		}
 
-		computeMeshVertices(slot: Slot, mesh: MeshAttachment, pma: boolean) {
+		private computeMeshVertices(slot: Slot, mesh: MeshAttachment, pma: boolean, twoColorTint: boolean = false) {
 			let skeleton = slot.bone.skeleton;
 			let skeletonColor = skeleton.color;
 			let slotColor = slot.color;
@@ -138,26 +184,47 @@ module spine.webgl {
 					  skeletonColor.g * slotColor.g * regionColor.g * multiplier,
 					  skeletonColor.b * slotColor.b * regionColor.b * multiplier,
 					  alpha);
+			let dark = this.tempColor2;
+			if (slot.darkColor == null) dark.set(0, 0, 0, 1);
+			else dark.setFromColor(slot.darkColor);
 
 			let numVertices = mesh.worldVerticesLength / 2;
 			if (this.vertices.length < mesh.worldVerticesLength) {
 				this.vertices = Utils.newFloatArray(mesh.worldVerticesLength);
 			}
 			let vertices = this.vertices;
-			mesh.computeWorldVertices(slot, 0, mesh.worldVerticesLength, vertices, 0, SkeletonRenderer.VERTEX_SIZE);
+			mesh.computeWorldVertices(slot, 0, mesh.worldVerticesLength, vertices, 0, this.vertexSize);
 
 			let uvs = mesh.uvs;
-			for (let i = 0, n = numVertices, u = 0, v = 2; i < n; i++) {
-				vertices[v++] = color.r;
-				vertices[v++] = color.g;
-				vertices[v++] = color.b;
-				vertices[v++] = color.a;
-				vertices[v++] = uvs[u++];
-				vertices[v++] = uvs[u++];
-				v += 2;
+			if (!twoColorTint) {
+				for (let i = 0, n = numVertices, u = 0, v = 2; i < n; i++) {
+					vertices[v++] = color.r;
+					vertices[v++] = color.g;
+					vertices[v++] = color.b;
+					vertices[v++] = color.a;
+					vertices[v++] = uvs[u++];
+					vertices[v++] = uvs[u++];
+					v += 2;
+				}
+			} else {
+				for (let i = 0, n = numVertices, u = 0, v = 2; i < n; i++) {
+					vertices[v++] = color.r;
+					vertices[v++] = color.g;
+					vertices[v++] = color.b;
+					vertices[v++] = color.a;
+					vertices[v++] = uvs[u++];
+					vertices[v++] = uvs[u++];
+					vertices[v++] = dark.r;
+					vertices[v++] = dark.g;
+					vertices[v++] = dark.b;
+					vertices[v++] = 1;
+					v += 2;
+				}
 			}
 
-			return vertices;
+			this.renderable.vertices = vertices;
+			this.renderable.numFloats = numVertices * (twoColorTint ? 12 :  8);
+			return this.renderable;
 		}
 	}
 }

Энэ ялгаанд хэт олон файл өөрчлөгдсөн тул зарим файлыг харуулаагүй болно