Skip to content

Commit f5f1e8e

Browse files
committed
Added Spine Game Object and fully working canvas renderer
1 parent 15bbcda commit f5f1e8e

6 files changed

Lines changed: 362 additions & 33 deletions

File tree

plugins/spine/src/SpinePlugin.js

Lines changed: 33 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,12 @@
66

77
var Class = require('../../../src/utils/Class');
88
var ScenePlugin = require('../../../src/plugins/ScenePlugin');
9-
var Skeleton = require('./Skeleton');
109
var SpineFile = require('./SpineFile');
1110
var SpineCanvas = require('SpineCanvas');
1211
var SpineWebGL = require('SpineGL');
12+
var SpineGameObject = require('./gameobject/SpineGameObject');
13+
14+
var runtime;
1315

1416
/**
1517
* @classdesc
@@ -31,6 +33,8 @@ var SpinePlugin = new Class({
3133

3234
function SpinePlugin (scene, pluginManager)
3335
{
36+
console.log('SpinePlugin created');
37+
3438
ScenePlugin.call(this, scene, pluginManager);
3539

3640
var game = pluginManager.game;
@@ -49,9 +53,20 @@ var SpinePlugin = new Class({
4953
pluginManager.registerFileType('spine', this.spineFileCallback, scene);
5054

5155
// Register our game object
52-
pluginManager.registerGameObject('spine', this.spineFactory);
5356

54-
// this.runtime = (game.config.renderType) ? SpineCanvas : SpineWebGL;
57+
runtime = (game.config.renderType) ? SpineCanvas : SpineWebGL;
58+
59+
pluginManager.registerGameObject('spine', this.createSpineFactory(this));
60+
},
61+
62+
boot: function ()
63+
{
64+
this.skeletonRenderer = new SpineCanvas.canvas.SkeletonRenderer(this.game.context);
65+
},
66+
67+
getRuntime: function ()
68+
{
69+
return runtime;
5570
},
5671

5772
spineFileCallback: function (key, jsonURL, atlasURL, jsonXhrSettings, atlasXhrSettings)
@@ -90,23 +105,19 @@ var SpinePlugin = new Class({
90105
*
91106
* @return {Phaser.GameObjects.Spine} The Game Object that was created.
92107
*/
93-
spineFactory: function (x, y, key,)
94-
{
95-
// var sprite = new Sprite3D(this.scene, x, y, z, key, frame);
96-
97-
// this.displayList.add(sprite.gameObject);
98-
// this.updateList.add(sprite.gameObject);
99-
100-
// return sprite;
101-
},
102-
103-
boot: function ()
108+
createSpineFactory: function (plugin)
104109
{
105-
this.canvas = this.game.canvas;
110+
var callback = function (x, y, key, animationName, loop)
111+
{
112+
var spineGO = new SpineGameObject(this.scene, plugin, x, y, key, animationName, loop);
106113

107-
this.context = this.game.context;
114+
this.displayList.add(spineGO);
115+
this.updateList.add(spineGO);
116+
117+
return spineGO;
118+
};
108119

109-
this.skeletonRenderer = new SpineCanvas.canvas.SkeletonRenderer(this.context);
120+
return callback;
110121
},
111122

112123
createSkeleton: function (key)
@@ -133,16 +144,8 @@ var SpinePlugin = new Class({
133144
var skeletonData = skeletonJson.readSkeletonData(this.json.get(key));
134145

135146
var skeleton = new SpineCanvas.Skeleton(skeletonData);
136-
137-
skeleton.flipY = true;
138-
139-
skeleton.setToSetupPose();
140-
141-
skeleton.updateWorldTransform();
142-
143-
skeleton.setSkinByName('default');
144147

145-
return skeleton;
148+
return { skeletonData: skeletonData, skeleton: skeleton };
146149
},
147150

148151
getBounds: function (skeleton)
@@ -155,13 +158,13 @@ var SpinePlugin = new Class({
155158
return { offset: offset, size: size };
156159
},
157160

158-
createAnimationState: function (skeleton, animationName)
161+
createAnimationState: function (skeleton)
159162
{
160-
var state = new SpineCanvas.AnimationState(new SpineCanvas.AnimationStateData(skeleton.data));
163+
var stateData = new SpineCanvas.AnimationStateData(skeleton.data);
161164

162-
state.setAnimation(0, animationName, true);
165+
var state = new SpineCanvas.AnimationState(stateData);
163166

164-
return state;
167+
return { stateData: stateData, state: state };
165168
},
166169

167170
/**

plugins/spine/src/gameobject/SpineGameObject.js

Lines changed: 182 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,21 @@
44
* @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
55
*/
66

7-
var Class = require('../../../src/utils/Class');
7+
var Class = require('../../../../src/utils/Class');
8+
var ComponentsAlpha = require('../../../../src/gameobjects/components/Alpha');
9+
var ComponentsBlendMode = require('../../../../src/gameobjects/components/BlendMode');
10+
var ComponentsDepth = require('../../../../src/gameobjects/components/Depth');
11+
var ComponentsScrollFactor = require('../../../../src/gameobjects/components/ScrollFactor');
12+
var ComponentsTransform = require('../../../../src/gameobjects/components/Transform');
13+
var ComponentsVisible = require('../../../../src/gameobjects/components/Visible');
814
var GameObject = require('../../../../src/gameobjects/GameObject');
15+
var SpineGameObjectRender = require('./SpineGameObjectRender');
916

1017
/**
1118
* @classdesc
1219
* TODO
1320
*
14-
* @class Skeleton
21+
* @class SpineGameObject
1522
* @constructor
1623
* @since 3.16.0
1724
*
@@ -22,11 +29,183 @@ var SpineGameObject = new Class({
2229

2330
Extends: GameObject,
2431

32+
Mixins: [
33+
ComponentsAlpha,
34+
ComponentsBlendMode,
35+
ComponentsDepth,
36+
ComponentsScrollFactor,
37+
ComponentsTransform,
38+
ComponentsVisible,
39+
SpineGameObjectRender
40+
],
41+
2542
initialize:
2643

27-
function SpineGameObject (scene, x, y, key, animation)
44+
function SpineGameObject (scene, plugin, x, y, key, animationName, loop)
2845
{
46+
this.plugin = plugin;
47+
48+
this.runtime = plugin.getRuntime();
49+
2950
GameObject.call(this, scene, 'Spine');
51+
52+
var data = this.plugin.createSkeleton(key);
53+
54+
this.skeletonData = data.skeletonData;
55+
56+
var skeleton = data.skeleton;
57+
58+
skeleton.flipY = true;
59+
60+
skeleton.setToSetupPose();
61+
62+
skeleton.updateWorldTransform();
63+
64+
skeleton.setSkinByName('default');
65+
66+
this.skeleton = skeleton;
67+
68+
// AnimationState
69+
data = this.plugin.createAnimationState(skeleton);
70+
71+
this.state = data.state;
72+
73+
this.stateData = data.stateData;
74+
75+
var _this = this;
76+
77+
this.state.addListener({
78+
event: function (trackIndex, event)
79+
{
80+
// Event on a Track
81+
_this.emit('spine.event', trackIndex, event);
82+
},
83+
complete: function (trackIndex, loopCount)
84+
{
85+
// Animation on Track x completed, loop count
86+
_this.emit('spine.complete', trackIndex, loopCount);
87+
},
88+
start: function (trackIndex)
89+
{
90+
// Animation on Track x started
91+
_this.emit('spine.start', trackIndex);
92+
},
93+
end: function (trackIndex)
94+
{
95+
// Animation on Track x ended
96+
_this.emit('spine.end', trackIndex);
97+
}
98+
});
99+
100+
this.renderDebug = false;
101+
102+
if (animationName)
103+
{
104+
this.setAnimation(0, animationName, loop);
105+
}
106+
107+
this.setPosition(x, y);
108+
},
109+
110+
// http://esotericsoftware.com/spine-runtimes-guide
111+
112+
setAnimation: function (trackIndex, animationName, loop)
113+
{
114+
// if (loop === undefined)
115+
// {
116+
// loop = false;
117+
// }
118+
119+
this.state.setAnimation(trackIndex, animationName, loop);
120+
121+
return this;
122+
},
123+
124+
addAnimation: function (trackIndex, animationName, loop, delay)
125+
{
126+
return this.state.addAnimation(trackIndex, animationName, loop, delay);
127+
},
128+
129+
setEmptyAnimation: function (trackIndex, mixDuration)
130+
{
131+
this.state.setEmptyAnimation(trackIndex, mixDuration);
132+
133+
return this;
134+
},
135+
136+
clearTrack: function (trackIndex)
137+
{
138+
this.state.clearTrack(trackIndex);
139+
140+
return this;
141+
},
142+
143+
clearTracks: function ()
144+
{
145+
this.state.clearTracks();
146+
147+
return this;
148+
},
149+
150+
setSkin: function (newSkin)
151+
{
152+
var skeleton = this.skeleton;
153+
154+
skeleton.setSkin(newSkin);
155+
156+
skeleton.setSlotsToSetupPose();
157+
158+
this.state.apply(skeleton);
159+
160+
return this;
161+
},
162+
163+
setMix: function (fromName, toName, duration)
164+
{
165+
this.stateData.setMix(fromName, toName, duration);
166+
167+
return this;
168+
},
169+
170+
findBone: function (boneName)
171+
{
172+
return this.skeleton.findBone(boneName);
173+
},
174+
175+
getBounds: function ()
176+
{
177+
return this.plugin.getBounds(this.skeleton);
178+
179+
// this.skeleton.getBounds(this.offset, this.size, []);
180+
},
181+
182+
preUpdate: function (time, delta)
183+
{
184+
this.state.update(delta / 1000);
185+
186+
this.state.apply(this.skeleton);
187+
188+
this.emit('spine.update', this.skeleton);
189+
},
190+
191+
/**
192+
* Internal destroy handler, called as part of the destroy process.
193+
*
194+
* @method Phaser.GameObjects.RenderTexture#preDestroy
195+
* @protected
196+
* @since 3.16.0
197+
*/
198+
preDestroy: function ()
199+
{
200+
this.state.clearListeners();
201+
this.state.clearListenerNotifications();
202+
203+
this.plugin = null;
204+
this.runtime = null;
205+
this.skeleton = null;
206+
this.skeletonData = null;
207+
this.state = null;
208+
this.stateData = null;
30209
}
31210

32211
});
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/**
2+
* @author Richard Davey <rich@photonstorm.com>
3+
* @copyright 2018 Photon Storm Ltd.
4+
* @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
5+
*/
6+
7+
var SetTransform = require('../../../../src/renderer/canvas/utils/SetTransform');
8+
9+
/**
10+
* Renders this Game Object with the Canvas Renderer to the given Camera.
11+
* The object will not render if any of its renderFlags are set or it is being actively filtered out by the Camera.
12+
* This method should not be called directly. It is a utility function of the Render module.
13+
*
14+
* @method Phaser.GameObjects.SpineGameObject#renderCanvas
15+
* @since 3.16.0
16+
* @private
17+
*
18+
* @param {Phaser.Renderer.Canvas.CanvasRenderer} renderer - A reference to the current active Canvas renderer.
19+
* @param {Phaser.GameObjects.SpineGameObject} src - The Game Object being rendered in this call.
20+
* @param {number} interpolationPercentage - Reserved for future use and custom pipelines.
21+
* @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera that is rendering the Game Object.
22+
* @param {Phaser.GameObjects.Components.TransformMatrix} parentMatrix - This transform matrix is defined if the game object is nested
23+
*/
24+
var SpineGameObjectCanvasRenderer = function (renderer, src, interpolationPercentage, camera, parentMatrix)
25+
{
26+
var context = renderer.currentContext;
27+
28+
if (!SetTransform(renderer, context, src, camera, parentMatrix))
29+
{
30+
return;
31+
}
32+
33+
src.plugin.skeletonRenderer.ctx = context;
34+
35+
context.save();
36+
37+
src.skeleton.updateWorldTransform();
38+
39+
src.plugin.skeletonRenderer.draw(src.skeleton);
40+
41+
if (src.renderDebug)
42+
{
43+
context.strokeStyle = '#00ff00';
44+
context.beginPath();
45+
context.moveTo(-1000, 0);
46+
context.lineTo(1000, 0);
47+
context.moveTo(0, -1000);
48+
context.lineTo(0, 1000);
49+
context.stroke();
50+
}
51+
52+
context.restore();
53+
};
54+
55+
module.exports = SpineGameObjectCanvasRenderer;

0 commit comments

Comments
 (0)