Mario Zechner il y a 2 ans
Parent
commit
600e43de24

+ 297 - 298
spine-ts/spine-phaser/src/SpineGameObject.ts

@@ -30,137 +30,136 @@
 import { SPINE_GAME_OBJECT_TYPE } from "./keys";
 import { SpinePlugin } from "./SpinePlugin";
 import {
-  ComputedSizeMixin,
-  DepthMixin,
-  FlipMixin,
-  ScrollFactorMixin,
-  TransformMixin,
-  VisibleMixin,
-  AlphaMixin,
-  OriginMixin,
+	ComputedSizeMixin,
+	DepthMixin,
+	FlipMixin,
+	ScrollFactorMixin,
+	TransformMixin,
+	VisibleMixin,
+	AlphaMixin,
+	OriginMixin,
 } from "./mixins";
 import {
-  AnimationState,
-  AnimationStateData,
-  Bone,
-  MathUtils,
-  Skeleton,
-  Skin,
-  Vector2,
+	AnimationState,
+	AnimationStateData,
+	Bone,
+	MathUtils,
+	Skeleton,
+	Skin,
+	Vector2,
 } from "@esotericsoftware/spine-core";
 
 class BaseSpineGameObject extends Phaser.GameObjects.GameObject {
-  constructor(scene: Phaser.Scene, type: string) {
-    super(scene, type);
-  }
+	constructor (scene: Phaser.Scene, type: string) {
+		super(scene, type);
+	}
 }
 
 /** A bounds provider calculates the bounding box for a skeleton, which is then assigned as the size of the SpineGameObject. */
 export interface SpineGameObjectBoundsProvider {
-  // Returns the bounding box for the skeleton, in skeleton space.
-  calculateBounds(gameObject: SpineGameObject): {
-    x: number;
-    y: number;
-    width: number;
-    height: number;
-  };
+	// Returns the bounding box for the skeleton, in skeleton space.
+	calculateBounds (gameObject: SpineGameObject): {
+		x: number;
+		y: number;
+		width: number;
+		height: number;
+	};
 }
 
 /** A bounds provider that calculates the bounding box from the setup pose. */
 export class SetupPoseBoundsProvider implements SpineGameObjectBoundsProvider {
-  calculateBounds(gameObject: SpineGameObject) {
-    if (!gameObject.skeleton) return { x: 0, y: 0, width: 0, height: 0 };
-    // Make a copy of animation state and skeleton as this might be called while
-    // the skeleton in the GameObject has already been heavily modified. We can not
-    // reconstruct that state.
-    const skeleton = new Skeleton(gameObject.skeleton.data);
-    skeleton.setToSetupPose();
-    skeleton.updateWorldTransform();
-    const bounds = skeleton.getBoundsRect();
-    return bounds.width == Number.NEGATIVE_INFINITY
-      ? { x: 0, y: 0, width: 0, height: 0 }
-      : bounds;
-  }
+	calculateBounds (gameObject: SpineGameObject) {
+		if (!gameObject.skeleton) return { x: 0, y: 0, width: 0, height: 0 };
+		// Make a copy of animation state and skeleton as this might be called while
+		// the skeleton in the GameObject has already been heavily modified. We can not
+		// reconstruct that state.
+		const skeleton = new Skeleton(gameObject.skeleton.data);
+		skeleton.setToSetupPose();
+		skeleton.updateWorldTransform();
+		const bounds = skeleton.getBoundsRect();
+		return bounds.width == Number.NEGATIVE_INFINITY
+			? { x: 0, y: 0, width: 0, height: 0 }
+			: bounds;
+	}
 }
 
 /** A bounds provider that calculates the bounding box by taking the maximumg bounding box for a combination of skins and specific animation. */
 export class SkinsAndAnimationBoundsProvider
-  implements SpineGameObjectBoundsProvider
-{
-  /**
-   * @param animation The animation to use for calculating the bounds. If null, the setup pose is used.
-   * @param skins The skins to use for calculating the bounds. If empty, the default skin is used.
-   * @param timeStep The time step to use for calculating the bounds. A smaller time step means more precision, but slower calculation.
-   */
-  constructor(
-    private animation: string | null,
-    private skins: string[] = [],
-    private timeStep: number = 0.05
-  ) {}
+	implements SpineGameObjectBoundsProvider {
+	/**
+	 * @param animation The animation to use for calculating the bounds. If null, the setup pose is used.
+	 * @param skins The skins to use for calculating the bounds. If empty, the default skin is used.
+	 * @param timeStep The time step to use for calculating the bounds. A smaller time step means more precision, but slower calculation.
+	 */
+	constructor (
+		private animation: string | null,
+		private skins: string[] = [],
+		private timeStep: number = 0.05
+	) { }
 
-  calculateBounds(gameObject: SpineGameObject): {
-    x: number;
-    y: number;
-    width: number;
-    height: number;
-  } {
-    if (!gameObject.skeleton || !gameObject.animationState)
-      return { x: 0, y: 0, width: 0, height: 0 };
-    // Make a copy of animation state and skeleton as this might be called while
-    // the skeleton in the GameObject has already been heavily modified. We can not
-    // reconstruct that state.
-    const animationState = new AnimationState(gameObject.animationState.data);
-    const skeleton = new Skeleton(gameObject.skeleton.data);
-    const data = skeleton.data;
-    if (this.skins.length > 0) {
-      let customSkin = new Skin("custom-skin");
-      for (const skinName of this.skins) {
-        const skin = data.findSkin(skinName);
-        if (skin == null) continue;
-        customSkin.addSkin(skin);
-      }
-      skeleton.setSkin(customSkin);
-    }
-    skeleton.setToSetupPose();
+	calculateBounds (gameObject: SpineGameObject): {
+		x: number;
+		y: number;
+		width: number;
+		height: number;
+	} {
+		if (!gameObject.skeleton || !gameObject.animationState)
+			return { x: 0, y: 0, width: 0, height: 0 };
+		// Make a copy of animation state and skeleton as this might be called while
+		// the skeleton in the GameObject has already been heavily modified. We can not
+		// reconstruct that state.
+		const animationState = new AnimationState(gameObject.animationState.data);
+		const skeleton = new Skeleton(gameObject.skeleton.data);
+		const data = skeleton.data;
+		if (this.skins.length > 0) {
+			let customSkin = new Skin("custom-skin");
+			for (const skinName of this.skins) {
+				const skin = data.findSkin(skinName);
+				if (skin == null) continue;
+				customSkin.addSkin(skin);
+			}
+			skeleton.setSkin(customSkin);
+		}
+		skeleton.setToSetupPose();
 
-    const animation =
-      this.animation != null ? data.findAnimation(this.animation!) : null;
-    if (animation == null) {
-      skeleton.updateWorldTransform();
-      const bounds = skeleton.getBoundsRect();
-      return bounds.width == Number.NEGATIVE_INFINITY
-        ? { x: 0, y: 0, width: 0, height: 0 }
-        : bounds;
-    } else {
-      let minX = Number.POSITIVE_INFINITY,
-        minY = Number.POSITIVE_INFINITY,
-        maxX = Number.NEGATIVE_INFINITY,
-        maxY = Number.NEGATIVE_INFINITY;
-      animationState.clearTracks();
-      animationState.setAnimationWith(0, animation, false);
-      const steps = Math.max(animation.duration / this.timeStep, 1.0);
-      for (let i = 0; i < steps; i++) {
-        animationState.update(i > 0 ? this.timeStep : 0);
-        animationState.apply(skeleton);
-        skeleton.updateWorldTransform();
+		const animation =
+			this.animation != null ? data.findAnimation(this.animation!) : null;
+		if (animation == null) {
+			skeleton.updateWorldTransform();
+			const bounds = skeleton.getBoundsRect();
+			return bounds.width == Number.NEGATIVE_INFINITY
+				? { x: 0, y: 0, width: 0, height: 0 }
+				: bounds;
+		} else {
+			let minX = Number.POSITIVE_INFINITY,
+				minY = Number.POSITIVE_INFINITY,
+				maxX = Number.NEGATIVE_INFINITY,
+				maxY = Number.NEGATIVE_INFINITY;
+			animationState.clearTracks();
+			animationState.setAnimationWith(0, animation, false);
+			const steps = Math.max(animation.duration / this.timeStep, 1.0);
+			for (let i = 0; i < steps; i++) {
+				animationState.update(i > 0 ? this.timeStep : 0);
+				animationState.apply(skeleton);
+				skeleton.updateWorldTransform();
 
-        const bounds = skeleton.getBoundsRect();
-        minX = Math.min(minX, bounds.x);
-        minY = Math.min(minY, bounds.y);
-        maxX = Math.max(maxX, minX + bounds.width);
-        maxY = Math.max(maxY, minY + bounds.height);
-      }
-      const bounds = {
-        x: minX,
-        y: minY,
-        width: maxX - minX,
-        height: maxY - minY,
-      };
-      return bounds.width == Number.NEGATIVE_INFINITY
-        ? { x: 0, y: 0, width: 0, height: 0 }
-        : bounds;
-    }
-  }
+				const bounds = skeleton.getBoundsRect();
+				minX = Math.min(minX, bounds.x);
+				minY = Math.min(minY, bounds.y);
+				maxX = Math.max(maxX, minX + bounds.width);
+				maxY = Math.max(maxY, minY + bounds.height);
+			}
+			const bounds = {
+				x: minX,
+				y: minY,
+				width: maxX - minX,
+				height: maxY - minY,
+			};
+			return bounds.width == Number.NEGATIVE_INFINITY
+				? { x: 0, y: 0, width: 0, height: 0 }
+				: bounds;
+		}
+	}
 }
 
 /**
@@ -185,214 +184,214 @@ export class SkinsAndAnimationBoundsProvider
  * See {@link skeletonToPhaserWorldCoordinates}, {@link phaserWorldCoordinatesToSkeleton}, and {@link phaserWorldCoordinatesToBoneLocal.}
  */
 export class SpineGameObject extends DepthMixin(
-  OriginMixin(
-    ComputedSizeMixin(
-      FlipMixin(
-        ScrollFactorMixin(
-          TransformMixin(VisibleMixin(AlphaMixin(BaseSpineGameObject)))
-        )
-      )
-    )
-  )
+	OriginMixin(
+		ComputedSizeMixin(
+			FlipMixin(
+				ScrollFactorMixin(
+					TransformMixin(VisibleMixin(AlphaMixin(BaseSpineGameObject)))
+				)
+			)
+		)
+	)
 ) {
-  blendMode = -1;
-  skeleton: Skeleton;
-  animationStateData: AnimationStateData;
-  animationState: AnimationState;
-  beforeUpdateWorldTransforms: (object: SpineGameObject) => void = () => {};
-  afterUpdateWorldTransforms: (object: SpineGameObject) => void = () => {};
-  private premultipliedAlpha = false;
+	blendMode = -1;
+	skeleton: Skeleton;
+	animationStateData: AnimationStateData;
+	animationState: AnimationState;
+	beforeUpdateWorldTransforms: (object: SpineGameObject) => void = () => { };
+	afterUpdateWorldTransforms: (object: SpineGameObject) => void = () => { };
+	private premultipliedAlpha = false;
 
-  constructor(
-    scene: Phaser.Scene,
-    private plugin: SpinePlugin,
-    x: number,
-    y: number,
-    dataKey: string,
-    atlasKey: string,
-    public boundsProvider: SpineGameObjectBoundsProvider = new SetupPoseBoundsProvider()
-  ) {
-    super(scene, (window as any).SPINE_GAME_OBJECT_TYPE ? (window as any).SPINE_GAME_OBJECT_TYPE : SPINE_GAME_OBJECT_TYPE);
-    this.setPosition(x, y);
+	constructor (
+		scene: Phaser.Scene,
+		private plugin: SpinePlugin,
+		x: number,
+		y: number,
+		dataKey: string,
+		atlasKey: string,
+		public boundsProvider: SpineGameObjectBoundsProvider = new SetupPoseBoundsProvider()
+	) {
+		super(scene, (window as any).SPINE_GAME_OBJECT_TYPE ? (window as any).SPINE_GAME_OBJECT_TYPE : SPINE_GAME_OBJECT_TYPE);
+		this.setPosition(x, y);
 
-    this.premultipliedAlpha = this.plugin.isAtlasPremultiplied(atlasKey);
-    this.skeleton = this.plugin.createSkeleton(dataKey, atlasKey);
-    this.animationStateData = new AnimationStateData(this.skeleton.data);
-    this.animationState = new AnimationState(this.animationStateData);
-    this.skeleton.updateWorldTransform();
-    this.updateSize();
-  }
+		this.premultipliedAlpha = this.plugin.isAtlasPremultiplied(atlasKey);
+		this.skeleton = this.plugin.createSkeleton(dataKey, atlasKey);
+		this.animationStateData = new AnimationStateData(this.skeleton.data);
+		this.animationState = new AnimationState(this.animationStateData);
+		this.skeleton.updateWorldTransform();
+		this.updateSize();
+	}
 
-  updateSize() {
-    if (!this.skeleton) return;
-    let bounds = this.boundsProvider.calculateBounds(this);
-    // For some reason the TS compiler and the ComputedSize mixin don't work well together and we have
-    // to cast to any.
-    let self = this as any;
-    self.width = bounds.width;
-    self.height = bounds.height;
-    this.displayOriginX = -bounds.x;
-    this.displayOriginY = -bounds.y;
-  }
+	updateSize () {
+		if (!this.skeleton) return;
+		let bounds = this.boundsProvider.calculateBounds(this);
+		// For some reason the TS compiler and the ComputedSize mixin don't work well together and we have
+		// to cast to any.
+		let self = this as any;
+		self.width = bounds.width;
+		self.height = bounds.height;
+		this.displayOriginX = -bounds.x;
+		this.displayOriginY = -bounds.y;
+	}
 
-  /** Converts a point from the skeleton coordinate system to the Phaser world coordinate system. */
-  skeletonToPhaserWorldCoordinates(point: { x: number; y: number }) {
-    let transform = this.getWorldTransformMatrix();
-    let a = transform.a,
-      b = transform.b,
-      c = transform.c,
-      d = transform.d,
-      tx = transform.tx,
-      ty = transform.ty;
-    let x = point.x;
-    let y = point.y;
-    point.x = x * a + y * c + tx;
-    point.y = x * b + y * d + ty;
-  }
+	/** Converts a point from the skeleton coordinate system to the Phaser world coordinate system. */
+	skeletonToPhaserWorldCoordinates (point: { x: number; y: number }) {
+		let transform = this.getWorldTransformMatrix();
+		let a = transform.a,
+			b = transform.b,
+			c = transform.c,
+			d = transform.d,
+			tx = transform.tx,
+			ty = transform.ty;
+		let x = point.x;
+		let y = point.y;
+		point.x = x * a + y * c + tx;
+		point.y = x * b + y * d + ty;
+	}
 
-  /** Converts a point from the Phaser world coordinate system to the skeleton coordinate system. */
-  phaserWorldCoordinatesToSkeleton(point: { x: number; y: number }) {
-    let transform = this.getWorldTransformMatrix();
-    transform = transform.invert();
-    let a = transform.a,
-      b = transform.b,
-      c = transform.c,
-      d = transform.d,
-      tx = transform.tx,
-      ty = transform.ty;
-    let x = point.x;
-    let y = point.y;
-    point.x = x * a + y * c + tx;
-    point.y = x * b + y * d + ty;
-  }
+	/** Converts a point from the Phaser world coordinate system to the skeleton coordinate system. */
+	phaserWorldCoordinatesToSkeleton (point: { x: number; y: number }) {
+		let transform = this.getWorldTransformMatrix();
+		transform = transform.invert();
+		let a = transform.a,
+			b = transform.b,
+			c = transform.c,
+			d = transform.d,
+			tx = transform.tx,
+			ty = transform.ty;
+		let x = point.x;
+		let y = point.y;
+		point.x = x * a + y * c + tx;
+		point.y = x * b + y * d + ty;
+	}
 
-  /** Converts a point from the Phaser world coordinate system to the bone's local coordinate system. */
-  phaserWorldCoordinatesToBone(point: { x: number; y: number }, bone: Bone) {
-    this.phaserWorldCoordinatesToSkeleton(point);
-    if (bone.parent) {
-      bone.parent.worldToLocal(point as Vector2);
-    } else {
-      bone.worldToLocal(point as Vector2);
-    }
-  }
+	/** Converts a point from the Phaser world coordinate system to the bone's local coordinate system. */
+	phaserWorldCoordinatesToBone (point: { x: number; y: number }, bone: Bone) {
+		this.phaserWorldCoordinatesToSkeleton(point);
+		if (bone.parent) {
+			bone.parent.worldToLocal(point as Vector2);
+		} else {
+			bone.worldToLocal(point as Vector2);
+		}
+	}
 
-  /**
-   * Updates the {@link AnimationState}, applies it to the {@link Skeleton}, then updates the world transforms of all bones.
-   * @param delta The time delta in milliseconds
-   */
-  updatePose(delta: number) {
-    this.animationState.update(delta / 1000);
-    this.animationState.apply(this.skeleton);
-    this.beforeUpdateWorldTransforms(this);
-    this.skeleton.updateWorldTransform();
-    this.afterUpdateWorldTransforms(this);
-  }
+	/**
+	 * Updates the {@link AnimationState}, applies it to the {@link Skeleton}, then updates the world transforms of all bones.
+	 * @param delta The time delta in milliseconds
+	 */
+	updatePose (delta: number) {
+		this.animationState.update(delta / 1000);
+		this.animationState.apply(this.skeleton);
+		this.beforeUpdateWorldTransforms(this);
+		this.skeleton.updateWorldTransform();
+		this.afterUpdateWorldTransforms(this);
+	}
 
-  preUpdate(time: number, delta: number) {
-    if (!this.skeleton || !this.animationState) return;
-    this.updatePose(delta);
-  }
+	preUpdate (time: number, delta: number) {
+		if (!this.skeleton || !this.animationState) return;
+		this.updatePose(delta);
+	}
 
-  preDestroy() {
-    // FIXME tear down any event emitters
-  }
+	preDestroy () {
+		// FIXME tear down any event emitters
+	}
 
-  willRender(camera: Phaser.Cameras.Scene2D.Camera) {
-    if (!this.visible) return false;
+	willRender (camera: Phaser.Cameras.Scene2D.Camera) {
+		if (!this.visible) return false;
 
-    var GameObjectRenderMask = 0xf;
-    var result = !this.skeleton || !(GameObjectRenderMask !== this.renderFlags || (this.cameraFilter !== 0 && this.cameraFilter & camera.id));
+		var GameObjectRenderMask = 0xf;
+		var result = !this.skeleton || !(GameObjectRenderMask !== this.renderFlags || (this.cameraFilter !== 0 && this.cameraFilter & camera.id));
 
-    if (!result && this.parentContainer && this.plugin.webGLRenderer) {
-      var sceneRenderer = this.plugin.webGLRenderer;
+		if (!result && this.parentContainer && this.plugin.webGLRenderer) {
+			var sceneRenderer = this.plugin.webGLRenderer;
 
-      if (this.plugin.gl && this.plugin.phaserRenderer instanceof Phaser.Renderer.WebGL.WebGLRenderer && sceneRenderer.batcher.isDrawing) {
-        sceneRenderer.end();
-        this.plugin.phaserRenderer.pipelines.rebind();
-      }
-    }
+			if (this.plugin.gl && this.plugin.phaserRenderer instanceof Phaser.Renderer.WebGL.WebGLRenderer && sceneRenderer.batcher.isDrawing) {
+				sceneRenderer.end();
+				this.plugin.phaserRenderer.pipelines.rebind();
+			}
+		}
 
-    return result;
-  }
+		return result;
+	}
 
-  renderWebGL(
-    renderer: Phaser.Renderer.WebGL.WebGLRenderer,
-    src: SpineGameObject,
-    camera: Phaser.Cameras.Scene2D.Camera,
-    parentMatrix: Phaser.GameObjects.Components.TransformMatrix
-  ) {
-    if (!this.skeleton || !this.animationState || !this.plugin.webGLRenderer)
-      return;
+	renderWebGL (
+		renderer: Phaser.Renderer.WebGL.WebGLRenderer,
+		src: SpineGameObject,
+		camera: Phaser.Cameras.Scene2D.Camera,
+		parentMatrix: Phaser.GameObjects.Components.TransformMatrix
+	) {
+		if (!this.skeleton || !this.animationState || !this.plugin.webGLRenderer)
+			return;
 
-    let sceneRenderer = this.plugin.webGLRenderer;
-    if (renderer.newType) {
-      renderer.pipelines.clear();
-      sceneRenderer.begin();
-    }
+		let sceneRenderer = this.plugin.webGLRenderer;
+		if (renderer.newType) {
+			renderer.pipelines.clear();
+			sceneRenderer.begin();
+		}
 
-    camera.addToRenderList(src);
-    let transform = Phaser.GameObjects.GetCalcMatrix(
-      src,
-      camera,
-      parentMatrix
-    ).calc;
-    let a = transform.a,
-      b = transform.b,
-      c = transform.c,
-      d = transform.d,
-      tx = transform.tx,
-      ty = transform.ty;
-    sceneRenderer.drawSkeleton(
-      this.skeleton,
-      this.premultipliedAlpha,
-      -1,
-      -1,
-      (vertices, numVertices, stride) => {
-        for (let i = 0; i < numVertices; i += stride) {
-          let vx = vertices[i];
-          let vy = vertices[i + 1];
-          vertices[i] = vx * a + vy * c + tx;
-          vertices[i + 1] = vx * b + vy * d + ty;
-        }
-      }
-    );
+		camera.addToRenderList(src);
+		let transform = Phaser.GameObjects.GetCalcMatrix(
+			src,
+			camera,
+			parentMatrix
+		).calc;
+		let a = transform.a,
+			b = transform.b,
+			c = transform.c,
+			d = transform.d,
+			tx = transform.tx,
+			ty = transform.ty;
+		sceneRenderer.drawSkeleton(
+			this.skeleton,
+			this.premultipliedAlpha,
+			-1,
+			-1,
+			(vertices, numVertices, stride) => {
+				for (let i = 0; i < numVertices; i += stride) {
+					let vx = vertices[i];
+					let vy = vertices[i + 1];
+					vertices[i] = vx * a + vy * c + tx;
+					vertices[i + 1] = vx * b + vy * d + ty;
+				}
+			}
+		);
 
-    if (!renderer.nextTypeMatch) {
-      sceneRenderer.end();
-      renderer.pipelines.rebind();
-    }
-  }
+		if (!renderer.nextTypeMatch) {
+			sceneRenderer.end();
+			renderer.pipelines.rebind();
+		}
+	}
 
-  renderCanvas(
-    renderer: Phaser.Renderer.Canvas.CanvasRenderer,
-    src: SpineGameObject,
-    camera: Phaser.Cameras.Scene2D.Camera,
-    parentMatrix: Phaser.GameObjects.Components.TransformMatrix
-  ) {
-    if (!this.skeleton || !this.animationState || !this.plugin.canvasRenderer)
-      return;
+	renderCanvas (
+		renderer: Phaser.Renderer.Canvas.CanvasRenderer,
+		src: SpineGameObject,
+		camera: Phaser.Cameras.Scene2D.Camera,
+		parentMatrix: Phaser.GameObjects.Components.TransformMatrix
+	) {
+		if (!this.skeleton || !this.animationState || !this.plugin.canvasRenderer)
+			return;
 
-    let context = renderer.currentContext;
-    let skeletonRenderer = this.plugin.canvasRenderer;
-    (skeletonRenderer as any).ctx = context;
+		let context = renderer.currentContext;
+		let skeletonRenderer = this.plugin.canvasRenderer;
+		(skeletonRenderer as any).ctx = context;
 
-    camera.addToRenderList(src);
-    let transform = Phaser.GameObjects.GetCalcMatrix(
-      src,
-      camera,
-      parentMatrix
-    ).calc;
-    let skeleton = this.skeleton;
-    skeleton.x = transform.tx;
-    skeleton.y = transform.ty;
-    skeleton.scaleX = transform.scaleX;
-    skeleton.scaleY = transform.scaleY;
-    let root = skeleton.getRootBone()!;
-    root.rotation = -MathUtils.radiansToDegrees * transform.rotationNormalized;
-    this.skeleton.updateWorldTransform();
+		camera.addToRenderList(src);
+		let transform = Phaser.GameObjects.GetCalcMatrix(
+			src,
+			camera,
+			parentMatrix
+		).calc;
+		let skeleton = this.skeleton;
+		skeleton.x = transform.tx;
+		skeleton.y = transform.ty;
+		skeleton.scaleX = transform.scaleX;
+		skeleton.scaleY = transform.scaleY;
+		let root = skeleton.getRootBone()!;
+		root.rotation = -MathUtils.radiansToDegrees * transform.rotationNormalized;
+		this.skeleton.updateWorldTransform();
 
-    context.save();
-    skeletonRenderer.draw(skeleton);
-    context.restore();
-  }
+		context.save();
+		skeletonRenderer.draw(skeleton);
+		context.restore();
+	}
 }

+ 1 - 1
spine-ts/spine-phaser/src/SpinePlugin.ts

@@ -271,7 +271,7 @@ class SpineSkeletonDataFile extends Phaser.Loader.MultiFile {
 			url = config.url;
 			fileType = config.type === "spineJson" ? SpineSkeletonDataFileType.json : SpineSkeletonDataFileType.binary;
 			xhrSettings = config.xhrSettings;
-      }
+		}
 		let file = null;
 		let isJson = fileType == SpineSkeletonDataFileType.json;
 		if (isJson) {

+ 242 - 242
spine-ts/spine-threejs/src/SkeletonMesh.ts

@@ -28,32 +28,32 @@
  *****************************************************************************/
 
 import {
-  AnimationState,
-  AnimationStateData,
-  BlendMode,
-  ClippingAttachment,
-  Color,
-  MeshAttachment,
-  NumberArrayLike,
-  RegionAttachment,
-  Skeleton,
-  SkeletonClipping,
-  SkeletonData,
-  TextureAtlasRegion,
-  Utils,
-  Vector2,
+	AnimationState,
+	AnimationStateData,
+	BlendMode,
+	ClippingAttachment,
+	Color,
+	MeshAttachment,
+	NumberArrayLike,
+	RegionAttachment,
+	Skeleton,
+	SkeletonClipping,
+	SkeletonData,
+	TextureAtlasRegion,
+	Utils,
+	Vector2,
 } from "@esotericsoftware/spine-core";
 import { MeshBatcher } from "./MeshBatcher";
 import * as THREE from "three";
 import { ThreeJsTexture } from "./ThreeJsTexture";
 
 export type SkeletonMeshMaterialParametersCustomizer = (
-  materialParameters: THREE.ShaderMaterialParameters
+	materialParameters: THREE.ShaderMaterialParameters
 ) => void;
 
 export class SkeletonMeshMaterial extends THREE.ShaderMaterial {
-  constructor(customizer: SkeletonMeshMaterialParametersCustomizer) {
-    let vertexShader = `
+	constructor (customizer: SkeletonMeshMaterialParametersCustomizer) {
+		let vertexShader = `
 			attribute vec4 color;
 			varying vec2 vUv;
 			varying vec4 vColor;
@@ -63,7 +63,7 @@ export class SkeletonMeshMaterial extends THREE.ShaderMaterial {
 				gl_Position = projectionMatrix*modelViewMatrix*vec4(position,1.0);
 			}
 		`;
-    let fragmentShader = `
+		let fragmentShader = `
 			uniform sampler2D map;
 			#ifdef USE_SPINE_ALPHATEST
 			uniform float alphaTest;
@@ -78,253 +78,253 @@ export class SkeletonMeshMaterial extends THREE.ShaderMaterial {
 			}
 		`;
 
-    let parameters: THREE.ShaderMaterialParameters = {
-      uniforms: {
-        map: { value: null },
-      },
-      vertexShader: vertexShader,
-      fragmentShader: fragmentShader,
-      side: THREE.DoubleSide,
-      transparent: true,
-      depthWrite: true,
-      alphaTest: 0.0,
-    };
-    customizer(parameters);
-    if (parameters.alphaTest && parameters.alphaTest > 0) {
-      parameters.defines = { USE_SPINE_ALPHATEST: 1 };
-      if (!parameters.uniforms) parameters.uniforms = {};
-      parameters.uniforms["alphaTest"] = { value: parameters.alphaTest };
-    }
-    super(parameters);
-  }
+		let parameters: THREE.ShaderMaterialParameters = {
+			uniforms: {
+				map: { value: null },
+			},
+			vertexShader: vertexShader,
+			fragmentShader: fragmentShader,
+			side: THREE.DoubleSide,
+			transparent: true,
+			depthWrite: true,
+			alphaTest: 0.0,
+		};
+		customizer(parameters);
+		if (parameters.alphaTest && parameters.alphaTest > 0) {
+			parameters.defines = { USE_SPINE_ALPHATEST: 1 };
+			if (!parameters.uniforms) parameters.uniforms = {};
+			parameters.uniforms["alphaTest"] = { value: parameters.alphaTest };
+		}
+		super(parameters);
+	}
 }
 
 export class SkeletonMesh extends THREE.Object3D {
-  tempPos: Vector2 = new Vector2();
-  tempUv: Vector2 = new Vector2();
-  tempLight = new Color();
-  tempDark = new Color();
-  skeleton: Skeleton;
-  state: AnimationState;
-  zOffset: number = 0.1;
+	tempPos: Vector2 = new Vector2();
+	tempUv: Vector2 = new Vector2();
+	tempLight = new Color();
+	tempDark = new Color();
+	skeleton: Skeleton;
+	state: AnimationState;
+	zOffset: number = 0.1;
 
-  private batches = new Array<MeshBatcher>();
-  private nextBatchIndex = 0;
-  private clipper: SkeletonClipping = new SkeletonClipping();
+	private batches = new Array<MeshBatcher>();
+	private nextBatchIndex = 0;
+	private clipper: SkeletonClipping = new SkeletonClipping();
 
-  static QUAD_TRIANGLES = [0, 1, 2, 2, 3, 0];
-  static VERTEX_SIZE = 2 + 2 + 4;
+	static QUAD_TRIANGLES = [0, 1, 2, 2, 3, 0];
+	static VERTEX_SIZE = 2 + 2 + 4;
 
-  private vertices = Utils.newFloatArray(1024);
-  private tempColor = new Color();
+	private vertices = Utils.newFloatArray(1024);
+	private tempColor = new Color();
 
-  constructor(
-    skeletonData: SkeletonData,
-    private materialCustomerizer: SkeletonMeshMaterialParametersCustomizer = (
-      material
-    ) => {}
-  ) {
-    super();
+	constructor (
+		skeletonData: SkeletonData,
+		private materialCustomerizer: SkeletonMeshMaterialParametersCustomizer = (
+			material
+		) => { }
+	) {
+		super();
 
-    this.skeleton = new Skeleton(skeletonData);
-    let animData = new AnimationStateData(skeletonData);
-    this.state = new AnimationState(animData);
-  }
+		this.skeleton = new Skeleton(skeletonData);
+		let animData = new AnimationStateData(skeletonData);
+		this.state = new AnimationState(animData);
+	}
 
-  update(deltaTime: number) {
-    let state = this.state;
-    let skeleton = this.skeleton;
+	update (deltaTime: number) {
+		let state = this.state;
+		let skeleton = this.skeleton;
 
-    state.update(deltaTime);
-    state.apply(skeleton);
-    skeleton.updateWorldTransform();
+		state.update(deltaTime);
+		state.apply(skeleton);
+		skeleton.updateWorldTransform();
 
-    this.updateGeometry();
-  }
+		this.updateGeometry();
+	}
 
-  dispose() {
-    for (var i = 0; i < this.batches.length; i++) {
-      this.batches[i].dispose();
-    }
-  }
+	dispose () {
+		for (var i = 0; i < this.batches.length; i++) {
+			this.batches[i].dispose();
+		}
+	}
 
-  private clearBatches() {
-    for (var i = 0; i < this.batches.length; i++) {
-      this.batches[i].clear();
-      this.batches[i].visible = false;
-    }
-    this.nextBatchIndex = 0;
-  }
+	private clearBatches () {
+		for (var i = 0; i < this.batches.length; i++) {
+			this.batches[i].clear();
+			this.batches[i].visible = false;
+		}
+		this.nextBatchIndex = 0;
+	}
 
-  private nextBatch() {
-    if (this.batches.length == this.nextBatchIndex) {
-      let batch = new MeshBatcher(10920, this.materialCustomerizer);
-      this.add(batch);
-      this.batches.push(batch);
-    }
-    let batch = this.batches[this.nextBatchIndex++];
-    batch.visible = true;
-    return batch;
-  }
+	private nextBatch () {
+		if (this.batches.length == this.nextBatchIndex) {
+			let batch = new MeshBatcher(10920, this.materialCustomerizer);
+			this.add(batch);
+			this.batches.push(batch);
+		}
+		let batch = this.batches[this.nextBatchIndex++];
+		batch.visible = true;
+		return batch;
+	}
 
-  private updateGeometry() {
-    this.clearBatches();
+	private updateGeometry () {
+		this.clearBatches();
 
-    let tempPos = this.tempPos;
-    let tempUv = this.tempUv;
-    let tempLight = this.tempLight;
-    let tempDark = this.tempDark;
-    let clipper = this.clipper;
+		let tempPos = this.tempPos;
+		let tempUv = this.tempUv;
+		let tempLight = this.tempLight;
+		let tempDark = this.tempDark;
+		let clipper = this.clipper;
 
-    let vertices: NumberArrayLike = this.vertices;
-    let triangles: Array<number> | null = null;
-    let uvs: NumberArrayLike | null = null;
-    let drawOrder = this.skeleton.drawOrder;
-    let batch = this.nextBatch();
-    batch.begin();
-    let z = 0;
-    let zOffset = this.zOffset;
-    for (let i = 0, n = drawOrder.length; i < n; i++) {
-      let vertexSize = clipper.isClipping() ? 2 : SkeletonMesh.VERTEX_SIZE;
-      let slot = drawOrder[i];
-      if (!slot.bone.active) {
-        clipper.clipEndWithSlot(slot);
-        continue;
-      }
-      let attachment = slot.getAttachment();
-      let attachmentColor: Color | null;
-      let texture: ThreeJsTexture | null;
-      let numFloats = 0;
-      if (attachment instanceof RegionAttachment) {
-        let region = <RegionAttachment>attachment;
-        attachmentColor = region.color;
-        vertices = this.vertices;
-        numFloats = vertexSize * 4;
-        region.computeWorldVertices(slot, vertices, 0, vertexSize);
-        triangles = SkeletonMesh.QUAD_TRIANGLES;
-        uvs = region.uvs;
-        texture = <ThreeJsTexture>region.region!.texture;
-      } else if (attachment instanceof MeshAttachment) {
-        let mesh = <MeshAttachment>attachment;
-        attachmentColor = mesh.color;
-        vertices = this.vertices;
-        numFloats = (mesh.worldVerticesLength >> 1) * vertexSize;
-        if (numFloats > vertices.length) {
-          vertices = this.vertices = Utils.newFloatArray(numFloats);
-        }
-        mesh.computeWorldVertices(
-          slot,
-          0,
-          mesh.worldVerticesLength,
-          vertices,
-          0,
-          vertexSize
-        );
-        triangles = mesh.triangles;
-        uvs = mesh.uvs;
-        texture = <ThreeJsTexture>mesh.region!.texture;
-      } else if (attachment instanceof ClippingAttachment) {
-        let clip = <ClippingAttachment>attachment;
-        clipper.clipStart(slot, clip);
-        continue;
-      } else {
-        clipper.clipEndWithSlot(slot);
-        continue;
-      }
+		let vertices: NumberArrayLike = this.vertices;
+		let triangles: Array<number> | null = null;
+		let uvs: NumberArrayLike | null = null;
+		let drawOrder = this.skeleton.drawOrder;
+		let batch = this.nextBatch();
+		batch.begin();
+		let z = 0;
+		let zOffset = this.zOffset;
+		for (let i = 0, n = drawOrder.length; i < n; i++) {
+			let vertexSize = clipper.isClipping() ? 2 : SkeletonMesh.VERTEX_SIZE;
+			let slot = drawOrder[i];
+			if (!slot.bone.active) {
+				clipper.clipEndWithSlot(slot);
+				continue;
+			}
+			let attachment = slot.getAttachment();
+			let attachmentColor: Color | null;
+			let texture: ThreeJsTexture | null;
+			let numFloats = 0;
+			if (attachment instanceof RegionAttachment) {
+				let region = <RegionAttachment>attachment;
+				attachmentColor = region.color;
+				vertices = this.vertices;
+				numFloats = vertexSize * 4;
+				region.computeWorldVertices(slot, vertices, 0, vertexSize);
+				triangles = SkeletonMesh.QUAD_TRIANGLES;
+				uvs = region.uvs;
+				texture = <ThreeJsTexture>region.region!.texture;
+			} else if (attachment instanceof MeshAttachment) {
+				let mesh = <MeshAttachment>attachment;
+				attachmentColor = mesh.color;
+				vertices = this.vertices;
+				numFloats = (mesh.worldVerticesLength >> 1) * vertexSize;
+				if (numFloats > vertices.length) {
+					vertices = this.vertices = Utils.newFloatArray(numFloats);
+				}
+				mesh.computeWorldVertices(
+					slot,
+					0,
+					mesh.worldVerticesLength,
+					vertices,
+					0,
+					vertexSize
+				);
+				triangles = mesh.triangles;
+				uvs = mesh.uvs;
+				texture = <ThreeJsTexture>mesh.region!.texture;
+			} else if (attachment instanceof ClippingAttachment) {
+				let clip = <ClippingAttachment>attachment;
+				clipper.clipStart(slot, clip);
+				continue;
+			} else {
+				clipper.clipEndWithSlot(slot);
+				continue;
+			}
 
-      if (texture != null) {
-        let skeleton = slot.bone.skeleton;
-        let skeletonColor = skeleton.color;
-        let slotColor = slot.color;
-        let alpha = skeletonColor.a * slotColor.a * attachmentColor.a;
-        let color = this.tempColor;
-        color.set(
-          skeletonColor.r * slotColor.r * attachmentColor.r,
-          skeletonColor.g * slotColor.g * attachmentColor.g,
-          skeletonColor.b * slotColor.b * attachmentColor.b,
-          alpha
-        );
+			if (texture != null) {
+				let skeleton = slot.bone.skeleton;
+				let skeletonColor = skeleton.color;
+				let slotColor = slot.color;
+				let alpha = skeletonColor.a * slotColor.a * attachmentColor.a;
+				let color = this.tempColor;
+				color.set(
+					skeletonColor.r * slotColor.r * attachmentColor.r,
+					skeletonColor.g * slotColor.g * attachmentColor.g,
+					skeletonColor.b * slotColor.b * attachmentColor.b,
+					alpha
+				);
 
-        let finalVertices: NumberArrayLike;
-        let finalVerticesLength: number;
-        let finalIndices: NumberArrayLike;
-        let finalIndicesLength: number;
+				let finalVertices: NumberArrayLike;
+				let finalVerticesLength: number;
+				let finalIndices: NumberArrayLike;
+				let finalIndicesLength: number;
 
-        if (clipper.isClipping()) {
-          clipper.clipTriangles(
-            vertices,
-            numFloats,
-            triangles,
-            triangles.length,
-            uvs,
-            color,
-            tempLight,
-            false
-          );
-          let clippedVertices = clipper.clippedVertices;
-          let clippedTriangles = clipper.clippedTriangles;
-          finalVertices = clippedVertices;
-          finalVerticesLength = clippedVertices.length;
-          finalIndices = clippedTriangles;
-          finalIndicesLength = clippedTriangles.length;
-        } else {
-          let verts = vertices;
-          for (
-            let v = 2, u = 0, n = numFloats;
-            v < n;
-            v += vertexSize, u += 2
-          ) {
-            verts[v] = color.r;
-            verts[v + 1] = color.g;
-            verts[v + 2] = color.b;
-            verts[v + 3] = color.a;
-            verts[v + 4] = uvs[u];
-            verts[v + 5] = uvs[u + 1];
-          }
-          finalVertices = vertices;
-          finalVerticesLength = numFloats;
-          finalIndices = triangles;
-          finalIndicesLength = triangles.length;
-        }
+				if (clipper.isClipping()) {
+					clipper.clipTriangles(
+						vertices,
+						numFloats,
+						triangles,
+						triangles.length,
+						uvs,
+						color,
+						tempLight,
+						false
+					);
+					let clippedVertices = clipper.clippedVertices;
+					let clippedTriangles = clipper.clippedTriangles;
+					finalVertices = clippedVertices;
+					finalVerticesLength = clippedVertices.length;
+					finalIndices = clippedTriangles;
+					finalIndicesLength = clippedTriangles.length;
+				} else {
+					let verts = vertices;
+					for (
+						let v = 2, u = 0, n = numFloats;
+						v < n;
+						v += vertexSize, u += 2
+					) {
+						verts[v] = color.r;
+						verts[v + 1] = color.g;
+						verts[v + 2] = color.b;
+						verts[v + 3] = color.a;
+						verts[v + 4] = uvs[u];
+						verts[v + 5] = uvs[u + 1];
+					}
+					finalVertices = vertices;
+					finalVerticesLength = numFloats;
+					finalIndices = triangles;
+					finalIndicesLength = triangles.length;
+				}
 
-        if (finalVerticesLength == 0 || finalIndicesLength == 0) {
-          clipper.clipEndWithSlot(slot);
-          continue;
-        }
+				if (finalVerticesLength == 0 || finalIndicesLength == 0) {
+					clipper.clipEndWithSlot(slot);
+					continue;
+				}
 
-        // Start new batch if this one can't hold vertices/indices
-        if (
-          !batch.canBatch(
-            finalVerticesLength / SkeletonMesh.VERTEX_SIZE,
-            finalIndicesLength
-          )
-        ) {
-          batch.end();
-          batch = this.nextBatch();
-          batch.begin();
-        }
+				// Start new batch if this one can't hold vertices/indices
+				if (
+					!batch.canBatch(
+						finalVerticesLength / SkeletonMesh.VERTEX_SIZE,
+						finalIndicesLength
+					)
+				) {
+					batch.end();
+					batch = this.nextBatch();
+					batch.begin();
+				}
 
-        const slotBlendMode = slot.data.blendMode;
-        const slotTexture = texture.texture;
-        const materialGroup = batch.findMaterialGroup(
-          slotTexture,
-          slotBlendMode
-        );
+				const slotBlendMode = slot.data.blendMode;
+				const slotTexture = texture.texture;
+				const materialGroup = batch.findMaterialGroup(
+					slotTexture,
+					slotBlendMode
+				);
 
-        batch.addMaterialGroup(finalIndicesLength, materialGroup);
-        batch.batch(
-          finalVertices,
-          finalVerticesLength,
-          finalIndices,
-          finalIndicesLength,
-          z
-        );
-        z += zOffset;
-      }
+				batch.addMaterialGroup(finalIndicesLength, materialGroup);
+				batch.batch(
+					finalVertices,
+					finalVerticesLength,
+					finalIndices,
+					finalIndicesLength,
+					z
+				);
+				z += zOffset;
+			}
 
-      clipper.clipEndWithSlot(slot);
-    }
-    clipper.clipEnd();
-    batch.end();
-  }
+			clipper.clipEndWithSlot(slot);
+		}
+		clipper.clipEnd();
+		batch.end();
+	}
 }

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

@@ -170,7 +170,7 @@ export class SkeletonRenderer {
 						WebGLBlendModeConverter.getSourceColorGLBlendMode(blendMode, premultipliedAlpha),
 						WebGLBlendModeConverter.getSourceAlphaGLBlendMode(blendMode, premultipliedAlpha),
 						WebGLBlendModeConverter.getDestColorGLBlendMode(blendMode),
-						WebGLBlendModeConverter.getDestAlphaGLBlendMode(blendMode, premultipliedAlpha) );
+						WebGLBlendModeConverter.getDestAlphaGLBlendMode(blendMode, premultipliedAlpha));
 				}
 
 				if (clipper.isClipping()) {