Added Spine Game Object and fully working canvas renderer

This commit is contained in:
Richard Davey 2018-10-24 12:41:56 +01:00
parent 15bbcda5dd
commit f5f1e8ef15
6 changed files with 362 additions and 33 deletions

View file

@ -6,10 +6,12 @@
var Class = require('../../../src/utils/Class');
var ScenePlugin = require('../../../src/plugins/ScenePlugin');
var Skeleton = require('./Skeleton');
var SpineFile = require('./SpineFile');
var SpineCanvas = require('SpineCanvas');
var SpineWebGL = require('SpineGL');
var SpineGameObject = require('./gameobject/SpineGameObject');
var runtime;
/**
* @classdesc
@ -31,6 +33,8 @@ var SpinePlugin = new Class({
function SpinePlugin (scene, pluginManager)
{
console.log('SpinePlugin created');
ScenePlugin.call(this, scene, pluginManager);
var game = pluginManager.game;
@ -49,9 +53,20 @@ var SpinePlugin = new Class({
pluginManager.registerFileType('spine', this.spineFileCallback, scene);
// Register our game object
pluginManager.registerGameObject('spine', this.spineFactory);
// this.runtime = (game.config.renderType) ? SpineCanvas : SpineWebGL;
runtime = (game.config.renderType) ? SpineCanvas : SpineWebGL;
pluginManager.registerGameObject('spine', this.createSpineFactory(this));
},
boot: function ()
{
this.skeletonRenderer = new SpineCanvas.canvas.SkeletonRenderer(this.game.context);
},
getRuntime: function ()
{
return runtime;
},
spineFileCallback: function (key, jsonURL, atlasURL, jsonXhrSettings, atlasXhrSettings)
@ -90,23 +105,19 @@ var SpinePlugin = new Class({
*
* @return {Phaser.GameObjects.Spine} The Game Object that was created.
*/
spineFactory: function (x, y, key,)
createSpineFactory: function (plugin)
{
// var sprite = new Sprite3D(this.scene, x, y, z, key, frame);
var callback = function (x, y, key, animationName, loop)
{
var spineGO = new SpineGameObject(this.scene, plugin, x, y, key, animationName, loop);
// this.displayList.add(sprite.gameObject);
// this.updateList.add(sprite.gameObject);
this.displayList.add(spineGO);
this.updateList.add(spineGO);
return spineGO;
};
// return sprite;
},
boot: function ()
{
this.canvas = this.game.canvas;
this.context = this.game.context;
this.skeletonRenderer = new SpineCanvas.canvas.SkeletonRenderer(this.context);
return callback;
},
createSkeleton: function (key)
@ -133,16 +144,8 @@ var SpinePlugin = new Class({
var skeletonData = skeletonJson.readSkeletonData(this.json.get(key));
var skeleton = new SpineCanvas.Skeleton(skeletonData);
skeleton.flipY = true;
skeleton.setToSetupPose();
skeleton.updateWorldTransform();
skeleton.setSkinByName('default');
return skeleton;
return { skeletonData: skeletonData, skeleton: skeleton };
},
getBounds: function (skeleton)
@ -155,13 +158,13 @@ var SpinePlugin = new Class({
return { offset: offset, size: size };
},
createAnimationState: function (skeleton, animationName)
createAnimationState: function (skeleton)
{
var state = new SpineCanvas.AnimationState(new SpineCanvas.AnimationStateData(skeleton.data));
var stateData = new SpineCanvas.AnimationStateData(skeleton.data);
state.setAnimation(0, animationName, true);
var state = new SpineCanvas.AnimationState(stateData);
return state;
return { stateData: stateData, state: state };
},
/**

View file

@ -4,14 +4,21 @@
* @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
*/
var Class = require('../../../src/utils/Class');
var Class = require('../../../../src/utils/Class');
var ComponentsAlpha = require('../../../../src/gameobjects/components/Alpha');
var ComponentsBlendMode = require('../../../../src/gameobjects/components/BlendMode');
var ComponentsDepth = require('../../../../src/gameobjects/components/Depth');
var ComponentsScrollFactor = require('../../../../src/gameobjects/components/ScrollFactor');
var ComponentsTransform = require('../../../../src/gameobjects/components/Transform');
var ComponentsVisible = require('../../../../src/gameobjects/components/Visible');
var GameObject = require('../../../../src/gameobjects/GameObject');
var SpineGameObjectRender = require('./SpineGameObjectRender');
/**
* @classdesc
* TODO
*
* @class Skeleton
* @class SpineGameObject
* @constructor
* @since 3.16.0
*
@ -22,11 +29,183 @@ var SpineGameObject = new Class({
Extends: GameObject,
Mixins: [
ComponentsAlpha,
ComponentsBlendMode,
ComponentsDepth,
ComponentsScrollFactor,
ComponentsTransform,
ComponentsVisible,
SpineGameObjectRender
],
initialize:
function SpineGameObject (scene, x, y, key, animation)
function SpineGameObject (scene, plugin, x, y, key, animationName, loop)
{
this.plugin = plugin;
this.runtime = plugin.getRuntime();
GameObject.call(this, scene, 'Spine');
var data = this.plugin.createSkeleton(key);
this.skeletonData = data.skeletonData;
var skeleton = data.skeleton;
skeleton.flipY = true;
skeleton.setToSetupPose();
skeleton.updateWorldTransform();
skeleton.setSkinByName('default');
this.skeleton = skeleton;
// AnimationState
data = this.plugin.createAnimationState(skeleton);
this.state = data.state;
this.stateData = data.stateData;
var _this = this;
this.state.addListener({
event: function (trackIndex, event)
{
// Event on a Track
_this.emit('spine.event', trackIndex, event);
},
complete: function (trackIndex, loopCount)
{
// Animation on Track x completed, loop count
_this.emit('spine.complete', trackIndex, loopCount);
},
start: function (trackIndex)
{
// Animation on Track x started
_this.emit('spine.start', trackIndex);
},
end: function (trackIndex)
{
// Animation on Track x ended
_this.emit('spine.end', trackIndex);
}
});
this.renderDebug = false;
if (animationName)
{
this.setAnimation(0, animationName, loop);
}
this.setPosition(x, y);
},
// http://esotericsoftware.com/spine-runtimes-guide
setAnimation: function (trackIndex, animationName, loop)
{
// if (loop === undefined)
// {
// loop = false;
// }
this.state.setAnimation(trackIndex, animationName, loop);
return this;
},
addAnimation: function (trackIndex, animationName, loop, delay)
{
return this.state.addAnimation(trackIndex, animationName, loop, delay);
},
setEmptyAnimation: function (trackIndex, mixDuration)
{
this.state.setEmptyAnimation(trackIndex, mixDuration);
return this;
},
clearTrack: function (trackIndex)
{
this.state.clearTrack(trackIndex);
return this;
},
clearTracks: function ()
{
this.state.clearTracks();
return this;
},
setSkin: function (newSkin)
{
var skeleton = this.skeleton;
skeleton.setSkin(newSkin);
skeleton.setSlotsToSetupPose();
this.state.apply(skeleton);
return this;
},
setMix: function (fromName, toName, duration)
{
this.stateData.setMix(fromName, toName, duration);
return this;
},
findBone: function (boneName)
{
return this.skeleton.findBone(boneName);
},
getBounds: function ()
{
return this.plugin.getBounds(this.skeleton);
// this.skeleton.getBounds(this.offset, this.size, []);
},
preUpdate: function (time, delta)
{
this.state.update(delta / 1000);
this.state.apply(this.skeleton);
this.emit('spine.update', this.skeleton);
},
/**
* Internal destroy handler, called as part of the destroy process.
*
* @method Phaser.GameObjects.RenderTexture#preDestroy
* @protected
* @since 3.16.0
*/
preDestroy: function ()
{
this.state.clearListeners();
this.state.clearListenerNotifications();
this.plugin = null;
this.runtime = null;
this.skeleton = null;
this.skeletonData = null;
this.state = null;
this.stateData = null;
}
});

View file

@ -0,0 +1,55 @@
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2018 Photon Storm Ltd.
* @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
*/
var SetTransform = require('../../../../src/renderer/canvas/utils/SetTransform');
/**
* Renders this Game Object with the Canvas Renderer to the given Camera.
* The object will not render if any of its renderFlags are set or it is being actively filtered out by the Camera.
* This method should not be called directly. It is a utility function of the Render module.
*
* @method Phaser.GameObjects.SpineGameObject#renderCanvas
* @since 3.16.0
* @private
*
* @param {Phaser.Renderer.Canvas.CanvasRenderer} renderer - A reference to the current active Canvas renderer.
* @param {Phaser.GameObjects.SpineGameObject} src - The Game Object being rendered in this call.
* @param {number} interpolationPercentage - Reserved for future use and custom pipelines.
* @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera that is rendering the Game Object.
* @param {Phaser.GameObjects.Components.TransformMatrix} parentMatrix - This transform matrix is defined if the game object is nested
*/
var SpineGameObjectCanvasRenderer = function (renderer, src, interpolationPercentage, camera, parentMatrix)
{
var context = renderer.currentContext;
if (!SetTransform(renderer, context, src, camera, parentMatrix))
{
return;
}
src.plugin.skeletonRenderer.ctx = context;
context.save();
src.skeleton.updateWorldTransform();
src.plugin.skeletonRenderer.draw(src.skeleton);
if (src.renderDebug)
{
context.strokeStyle = '#00ff00';
context.beginPath();
context.moveTo(-1000, 0);
context.lineTo(1000, 0);
context.moveTo(0, -1000);
context.lineTo(0, 1000);
context.stroke();
}
context.restore();
};
module.exports = SpineGameObjectCanvasRenderer;

View file

@ -0,0 +1,33 @@
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2018 Photon Storm Ltd.
* @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
*/
var SpineGameObject = require('./SpineGameObject');
var GameObjectFactory = require('../../../../src/gameobjects/GameObjectFactory');
/**
* Creates a new Spine Game Object Game Object and adds it to the Scene.
*
* Note: This method will only be available if the Spine Plugin has been built or loaded into Phaser.
*
* @method Phaser.GameObjects.GameObjectFactory#spine
* @since 3.16.0
*
* @param {number} x - The horizontal position of this Game Object.
* @param {number} y - The vertical position of this Game Object.
* @param {string} texture - The key of the Texture this Game Object will use to render with, as stored in the Texture Manager.
* @param {(string|integer)} [frame] - An optional frame from the Texture this Game Object is rendering with.
*
* @return {Phaser.GameObjects.SpineGameObject} The Game Object that was created.
*/
GameObjectFactory.register('spine', function (x, y, key, animation)
{
var spine = new SpineGameObject(this.scene, x, y, key, animation);
this.displayList.add(spine);
this.updateList.add(spine);
return spine;
});

View file

@ -0,0 +1,25 @@
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2018 Photon Storm Ltd.
* @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
*/
var renderWebGL = require('../../../../src/utils/NOOP');
var renderCanvas = require('../../../../src/utils/NOOP');
if (typeof WEBGL_RENDERER)
{
renderWebGL = require('./SpineGameObjectWebGLRenderer');
}
if (typeof CANVAS_RENDERER)
{
renderCanvas = require('./SpineGameObjectCanvasRenderer');
}
module.exports = {
renderWebGL: renderWebGL,
renderCanvas: renderCanvas
};

View file

@ -0,0 +1,34 @@
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2018 Photon Storm Ltd.
* @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
*/
var SetTransform = require('../../../../src/renderer/canvas/utils/SetTransform');
/**
* Renders this Game Object with the Canvas Renderer to the given Camera.
* The object will not render if any of its renderFlags are set or it is being actively filtered out by the Camera.
* This method should not be called directly. It is a utility function of the Render module.
*
* @method Phaser.GameObjects.SpineGameObject#renderCanvas
* @since 3.16.0
* @private
*
* @param {Phaser.Renderer.Canvas.CanvasRenderer} renderer - A reference to the current active Canvas renderer.
* @param {Phaser.GameObjects.SpineGameObject} src - The Game Object being rendered in this call.
* @param {number} interpolationPercentage - Reserved for future use and custom pipelines.
* @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera that is rendering the Game Object.
* @param {Phaser.GameObjects.Components.TransformMatrix} parentMatrix - This transform matrix is defined if the game object is nested
*/
var SpineGameObjectWebGLRenderer = function (renderer, src, interpolationPercentage, camera, parentMatrix)
{
src.plugin.skeletonRenderer.ctx = context;
src.skeleton.updateWorldTransform();
src.plugin.skeletonRenderer.draw(src.skeleton);
};
module.exports = SpineGameObjectWebGLRenderer;