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

[ts] Fixed Canvas backend, updated README.md for Canvas backend

badlogic 9 жил өмнө
parent
commit
5ad388fe0c

+ 10 - 7
spine-ts/README.md

@@ -5,6 +5,7 @@ up into multiple modules:
 
 
 1. **Core**: `core/`, the core classes to load and process Spine models
 1. **Core**: `core/`, the core classes to load and process Spine models
 1. **WebGL**: `webgl/`, a self-contained WebGL backend, build on the core classes
 1. **WebGL**: `webgl/`, a self-contained WebGL backend, build on the core classes
+1. **Canvas**: `canvas/`, a self-contained Canvas backend, build on the core classes
 1. **Widget**: `widget/`, a self-contained widget to easily display Spine animations on your website, build on core classes & WebGL backend.
 1. **Widget**: `widget/`, a self-contained widget to easily display Spine animations on your website, build on core classes & WebGL backend.
 
 
 While the source code for the core library and backends is written in TypeScript, all code is compiled to easily consumable JavaScript.
 While the source code for the core library and backends is written in TypeScript, all code is compiled to easily consumable JavaScript.
@@ -18,7 +19,7 @@ The Spine Runtimes are developed with the intent to be used with data exported f
 
 
 spine-ts works with data exported from the latest Spine version.
 spine-ts works with data exported from the latest Spine version.
 
 
-spine-ts supports all Spine features.
+spine-ts WebGL & Widget backends supports all Spine features. The spine-ts Canvas backend does not support color tinting, mesh attachments or shearing. Mesh attachments are supported by setting `spine.canvas.SkeletonRenderer.useTriangleRendering` to true. Note that this method is slow and may lead to artifacts on some browsers.
 
 
 spine-ts does not yet support loading the binary format.
 spine-ts does not yet support loading the binary format.
 
 
@@ -26,6 +27,7 @@ spine-ts does not yet support loading the binary format.
 1. Download the Spine Runtimes source using [git](https://help.github.com/articles/set-up-git) or by downloading it [as a zip](https://github.com/EsotericSoftware/spine-runtimes/archive/master.zip).
 1. Download the Spine Runtimes source using [git](https://help.github.com/articles/set-up-git) or by downloading it [as a zip](https://github.com/EsotericSoftware/spine-runtimes/archive/master.zip).
 2. To use only the core library without rendering support, include the `build/spine-core.js` file in your project.
 2. To use only the core library without rendering support, include the `build/spine-core.js` file in your project.
 3. To use the WebGL backend, include the `spine-webgl.js` file in your project.
 3. To use the WebGL backend, include the `spine-webgl.js` file in your project.
+3. To use the Canvas backend, include the `spine-canvas.js` file in your project.
 4. To use the Widget, include `spine-widget.js` file in your project.
 4. To use the Widget, include `spine-widget.js` file in your project.
 
 
 All `*.js` files are self-contained and include both the core and respective backend classes.
 All `*.js` files are self-contained and include both the core and respective backend classes.
@@ -41,7 +43,7 @@ cd spine-ts
 python -m SimpleHTTPServer
 python -m SimpleHTTPServer
 ````
 ````
 
 
-Then open `http://localhost:8000/webgl/example` or `http://localhost:8000/widget/example` in your browser.
+Then open `http://localhost:8000/webgl/example`, `http://localhost:8000/canvas/example` or `http://localhost:8000/widget/example` in your browser.
 
 
 ## Development Setup
 ## Development Setup
 The spine-ts runtime and the various backends are implemented in TypeScript for greater maintainability and better tooling support. To
 The spine-ts runtime and the various backends are implemented in TypeScript for greater maintainability and better tooling support. To
@@ -52,11 +54,12 @@ setup a development environment, follow these steps.
 3. Install [Visual Studio Code](https://code.visualstudio.com/)
 3. Install [Visual Studio Code](https://code.visualstudio.com/)
 4. On the command line, change into the `spine-ts` directory
 4. On the command line, change into the `spine-ts` directory
 5. Start the TypeScript compiler in watcher mode for the backend you want to work on:
 5. Start the TypeScript compiler in watcher mode for the backend you want to work on:
-  1. **Core**: `tsc -w -p tsconfig.core.json`, builds `core/src`, outputs `build/spine-core.js|d.ts|js.map`
-  2. **WebGL**: `tsc -w -p tsconfig.webgl.json`, builds `core/src` and `webgl/src`, outputs `build/spine-webgl.js|d.ts|js.map`
-  3. **Widget**: `tsc -w -p tsconfig.widget.json`, builds `core/src` and `widget/src`, outputs `build/spine-widget.js|d.ts|js.map`
+  * **Core**: `tsc -w -p tsconfig.core.json`, builds `core/src`, outputs `build/spine-core.js|d.ts|js.map`
+  * **WebGL**: `tsc -w -p tsconfig.webgl.json`, builds `core/src` and `webgl/src`, outputs `build/spine-webgl.js|d.ts|js.map`
+  * **WebGL**: `tsc -w -p tsconfig.canvas.json`, builds `core/src` and `canvas/src`, outputs `build/spine-canvas.js|d.ts|js.map`
+  * **Widget**: `tsc -w -p tsconfig.widget.json`, builds `core/src` and `widget/src`, outputs `build/spine-widget.js|d.ts|js.map`
 6. Open the `spine-ts` folder in Visual Studio Code. VS Code will use the `tsconfig.json` file all source files from core and all 
 6. Open the `spine-ts` folder in Visual Studio Code. VS Code will use the `tsconfig.json` file all source files from core and all 
-backends for your development pleasure. The actual JavaScript output is still created by the command line TypeScript compiler process from the previous step.  
+backends for your development pleasure. The actual JavaScript output is still created by the command line TypeScript compiler process from the previous step.
 
 
 Each backend contains an `example/` folder with an `index.html` file that demonstrates the respective backend. For development, we
 Each backend contains an `example/` folder with an `index.html` file that demonstrates the respective backend. For development, we
 suggest to run a HTTP server in the root of `spine-ts`, e.g.
 suggest to run a HTTP server in the root of `spine-ts`, e.g.
@@ -66,4 +69,4 @@ cd spine-ts
 python -m SimpleHTTPServer
 python -m SimpleHTTPServer
 ```
 ```
 
 
-Then navigate to `http://localhost:8000/webgl/example` or `http://localhost:8000/widget/example`
+Then navigate to `http://localhost:8000/webgl/example`, `http://localhost:8000/canvas/example` or `http://localhost:8000/widget/example`

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


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


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


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


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


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


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


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


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


+ 7 - 5
spine-ts/canvas/example/assets/test.json

@@ -1,15 +1,17 @@
 {
 {
-"skeleton": { "hash": "lDI/ipVg9yXAdln1ZwTDAuXPGng", "spine": "3.4.02", "width": 650.27, "height": 650.27, "images": "./images/" },
+"skeleton": { "hash": "IupPHodxMJRnAG/MhbCuGMvI6B0", "spine": "3.4.02", "width": 62.32, "height": 62.32, "images": "./images/" },
 "bones": [
 "bones": [
-	{ "name": "root" }
+	{ "name": "root" },
+	{ "name": "bone", "parent": "root", "y": 142.84 }
 ],
 ],
 "slots": [
 "slots": [
-	{ "name": "badlogic", "bone": "root", "attachment": "badlogic" }
+	{ "name": "badlogic2", "bone": "bone", "attachment": "badlogic" },
+	{ "name": "badlogic", "bone": "root" }
 ],
 ],
 "skins": {
 "skins": {
 	"default": {
 	"default": {
-		"badlogic": {
-			"badlogic": { "rotation": 43.36, "width": 460, "height": 460 }
+		"badlogic2": {
+			"badlogic": { "x": 30.33, "y": -69.62, "scaleX": 0.1, "scaleY": 0.1, "rotation": 61.65, "width": 460, "height": 460 }
 		}
 		}
 	}
 	}
 },
 },

+ 6 - 1
spine-ts/canvas/example/index.html

@@ -23,6 +23,10 @@ function init () {
 	context = canvas.getContext("2d");
 	context = canvas.getContext("2d");
 
 
 	skeletonRenderer = new spine.canvas.SkeletonRenderer(context);
 	skeletonRenderer = new spine.canvas.SkeletonRenderer(context);
+	// enable debug rendering
+	skeletonRenderer.useDebugRendering = true;
+	// enable the triangle renderer, supports meshes, but may produce artifacts in some browsers
+	skeletonRenderer.useTriangleRendering = true;
 
 
 	assetManager = new spine.AssetManager(function(image) {
 	assetManager = new spine.AssetManager(function(image) {
 		return new spine.canvas.CanvasTexture(image);
 		return new spine.canvas.CanvasTexture(image);
@@ -43,7 +47,7 @@ function init () {
 
 
 function load () {
 function load () {
 	if (assetManager.isLoadingComplete()) {
 	if (assetManager.isLoadingComplete()) {
-		var data = loadSkeleton("raptor", 0.3, "walk", 320, 20, "default");
+		var data = loadSkeleton("spineboy", 0.7, "walk", 320, 460, "default");
 		skeleton = data.skeleton;
 		skeleton = data.skeleton;
 		state = data.state;		
 		state = data.state;		
 		requestAnimationFrame(render);
 		requestAnimationFrame(render);
@@ -73,6 +77,7 @@ function loadSkeleton (name, scale, initialAnimation, positionX, positionY, skin
 	var skeleton = new spine.Skeleton(skeletonData);
 	var skeleton = new spine.Skeleton(skeletonData);
 	skeleton.x = positionX;
 	skeleton.x = positionX;
 	skeleton.y = positionY;
 	skeleton.y = positionY;
+	skeleton.flipY = true;
 	skeleton.setSkinByName(skin);
 	skeleton.setSkinByName(skin);
 
 
 	// Create an AnimationState, and set the initial animation in looping mode.
 	// Create an AnimationState, and set the initial animation in looping mode.

+ 77 - 21
spine-ts/canvas/src/SkeletonRenderer.ts

@@ -34,14 +34,66 @@ module spine.canvas {
 		static QUAD_TRIANGLES = [0, 1, 2, 2, 3, 0];
 		static QUAD_TRIANGLES = [0, 1, 2, 2, 3, 0];
 		
 		
 		private _ctx: CanvasRenderingContext2D;
 		private _ctx: CanvasRenderingContext2D;
+
+		public useTriangleRendering = false;
+		public useDebugRendering = false;
 		
 		
 		constructor (context: CanvasRenderingContext2D) {
 		constructor (context: CanvasRenderingContext2D) {
 			this._ctx = context;
 			this._ctx = context;
 		}
 		}
 
 
-		draw (skeleton: Skeleton) {			
-			let blendMode: BlendMode = null;
+		draw (skeleton: Skeleton) {
+			if (this.useTriangleRendering) this.drawTriangles(skeleton);
+			else this.drawImages(skeleton);
+		}
+
+		private drawImages (skeleton: Skeleton) {
 			let ctx = this._ctx;
 			let ctx = this._ctx;
+			let drawOrder = skeleton.drawOrder;
+
+			if (this.useDebugRendering) ctx.strokeStyle = "green";			
+
+			for (let i = 0, n = drawOrder.length; i < n; i++) {				
+				let slot = drawOrder[i];
+				let attachment = slot.getAttachment();
+				let region: TextureAtlasRegion = null;
+				let image: HTMLImageElement = null;
+				let vertices: ArrayLike<number> = null;	
+				if (attachment instanceof RegionAttachment) {
+					let regionAttachment = <RegionAttachment>attachment;
+					vertices = regionAttachment.updateWorldVertices(slot, false);
+					region = <TextureAtlasRegion>regionAttachment.region;										
+					image = (<CanvasTexture>(region).texture).getImage();
+
+				} else continue;							
+
+				let att = <RegionAttachment>attachment;
+				let bone = slot.bone;
+				let x = vertices[0];
+				let y = vertices[1];
+				let rotation = (bone.getWorldRotationX() - att.rotation) * Math.PI / 180;
+				let xx = vertices[24] - vertices[0];
+				let xy = vertices[25] - vertices[1];
+				let yx = vertices[8] - vertices[0];
+				let yy = vertices[9] - vertices[1];
+				let w = Math.sqrt(xx * xx + xy * xy), h = -Math.sqrt(yx * yx + yy * yy);				
+				ctx.translate(x, y);
+				ctx.rotate(rotation);				
+				if (region.rotate) {
+					ctx.rotate(Math.PI / 2);
+					ctx.drawImage(image, region.x, region.y, region.height, region.width, 0, 0, h, -w);
+					ctx.rotate(-Math.PI / 2);					
+				} else {
+					ctx.drawImage(image, region.x, region.y, region.width, region.height, 0, 0, w, h);
+				}
+				if (this.useDebugRendering) ctx.strokeRect(0, 0, w, h);
+				ctx.rotate(-rotation);
+				ctx.translate(-x, -y);				
+			}			
+		}
+
+		private drawTriangles (skeleton: Skeleton) {			
+			let blendMode: BlendMode = null;			
 
 
 			let vertices: ArrayLike<number> = null;
 			let vertices: ArrayLike<number> = null;
 			let triangles: Array<number>  = null;
 			let triangles: Array<number>  = null;
@@ -64,7 +116,7 @@ module spine.canvas {
 					vertices = mesh.updateWorldVertices(slot, false);
 					vertices = mesh.updateWorldVertices(slot, false);
 					triangles = mesh.triangles;
 					triangles = mesh.triangles;
 					texture = (<TextureAtlasRegion>mesh.region.renderObject).texture.getImage();
 					texture = (<TextureAtlasRegion>mesh.region.renderObject).texture.getImage();
-				} else continue;
+				} else continue;				
 
 
 				if (texture != null) {
 				if (texture != null) {
 					let slotBlendMode = slot.data.blendMode;
 					let slotBlendMode = slot.data.blendMode;
@@ -72,30 +124,34 @@ module spine.canvas {
 						blendMode = slotBlendMode;						
 						blendMode = slotBlendMode;						
 					}
 					}
 
 
-					this.drawTriangles(texture, vertices, triangles);
-
-					// ctx.drawImage(texture, 0, 0);				
-				}
-			}			
-		}
+					let ctx = this._ctx;		
 
 
-		drawTriangles(texture: HTMLImageElement, vertices: ArrayLike<number>, triangles: ArrayLike<number>) {
-			let ctx = this._ctx;		
+					for (var j = 0; j < triangles.length; j+=3) {
+						let t1 = triangles[j] * 8, t2 = triangles[j+1] * 8, t3 = triangles[j+2] * 8;
 
 
-			for (var i = 0; i < triangles.length; i+=3) {
-				let t1 = triangles[i] * 8, t2 = triangles[i+1] * 8, t3 = triangles[i+2] * 8;
+						let x0 = vertices[t1], y0 = vertices[t1 + 1], u0 = vertices[t1 + 6], v0 = vertices[t1 + 7];
+						let x1 = vertices[t2], y1 = vertices[t2 + 1], u1 = vertices[t2 + 6], v1 = vertices[t2 + 7];
+						let x2 = vertices[t3], y2 = vertices[t3 + 1], u2 = vertices[t3 + 6], v2 = vertices[t3 + 7];				
 
 
-				let x0 = vertices[t1], y0 = vertices[t1 + 1], u0 = vertices[t1 + 6], v0 = vertices[t1 + 7];
-				let x1 = vertices[t2], y1 = vertices[t2 + 1], u1 = vertices[t2 + 6], v1 = vertices[t2 + 7];
-				let x2 = vertices[t3], y2 = vertices[t3 + 1], u2 = vertices[t3 + 6], v2 = vertices[t3 + 7];				
+						this.drawTriangle(texture, x0, y0, u0, v0, x1, y1, u1, v1, x2, y2, u2, v2);
 
 
-				this.drawTriangle(texture, x0, y0, u0, v0, x1, y1, u1, v1, x2, y2, u2, v2);
-			}
-		}
+						if (this.useDebugRendering) {
+							ctx.strokeStyle = "green";
+							ctx.beginPath();
+							ctx.moveTo(x0, y0);
+							ctx.lineTo(x1, y1);
+							ctx.lineTo(x2, y2);
+							ctx.lineTo(x0, y0);				
+							ctx.stroke();
+						}
+					}												
+				}				
+			}			
+		}		
 
 
 		// Adapted from http://extremelysatisfactorytotalitarianism.com/blog/?p=2120
 		// Adapted from http://extremelysatisfactorytotalitarianism.com/blog/?p=2120
 		// Apache 2 licensed
 		// Apache 2 licensed
-		drawTriangle(img: HTMLImageElement, x0: number, y0: number, u0: number, v0: number,
+		private drawTriangle(img: HTMLImageElement, x0: number, y0: number, u0: number, v0: number,
 						x1: number, y1: number, u1: number, v1: number,
 						x1: number, y1: number, u1: number, v1: number,
 						x2: number, y2: number, u2: number, v2: number) {
 						x2: number, y2: number, u2: number, v2: number) {
 			let ctx = this._ctx;
 			let ctx = this._ctx;
@@ -139,7 +195,7 @@ module spine.canvas {
 			ctx.transform(a, b, c, d, e, f);
 			ctx.transform(a, b, c, d, e, f);
 			ctx.clip();
 			ctx.clip();
 			ctx.drawImage(img, 0, 0);
 			ctx.drawImage(img, 0, 0);
-			ctx.restore();
+			ctx.restore();			
 		}
 		}
 	}
 	}
 }
 }

+ 2 - 4
spine-ts/widget/src/Widget.ts

@@ -114,14 +114,12 @@ module spine {
 					else throw new Error("Failed to load assets: " + JSON.stringify(assetManager.errors));
 					else throw new Error("Failed to load assets: " + JSON.stringify(assetManager.errors));
 				}
 				}
 
 
-				let atlas = new spine.TextureAtlas(this._assetManager.get(this._config.atlas) as string, (path: string, minFilter: TextureFilter, magFilter: TextureFilter, uWrap: TextureWrap, vWrap: TextureWrap) => {
+				let atlas = new spine.TextureAtlas(this._assetManager.get(this._config.atlas) as string, (path: string) => {
 					let texture = assetManager.get(imagesPath + path) as spine.webgl.GLTexture;
 					let texture = assetManager.get(imagesPath + path) as spine.webgl.GLTexture;
-					texture.setFilters(minFilter, magFilter);
-					texture.setWraps(uWrap, vWrap);
 					return texture;
 					return texture;
 				});
 				});
 				
 				
-				let atlasLoader = new spine.webgl.TextureAtlasAttachmentLoader(atlas);				
+				let atlasLoader = new spine.TextureAtlasAttachmentLoader(atlas);				
 				var skeletonJson = new spine.SkeletonJson(atlasLoader);
 				var skeletonJson = new spine.SkeletonJson(atlasLoader);
 				
 				
 				// Set the scale to apply during parsing, parse the file, and create a new skeleton.
 				// Set the scale to apply during parsing, parse the file, and create a new skeleton.

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