├── .babelrc
├── .gitignore
├── .npmignore
├── LICENSE.txt
├── README.md
├── examples
├── assets
│ ├── baddie.png
│ ├── button_sprite_sheet.png
│ ├── diamond.png
│ ├── dude.png
│ ├── firstaid.png
│ ├── platform.png
│ ├── sky.png
│ ├── star.png
│ ├── states_player.png
│ └── states_win.png
├── button
│ ├── button.js
│ └── index.html
├── graphics-button
│ ├── graphics-button.js
│ └── index.html
├── graphics
│ ├── graphics.js
│ └── index.html
├── part5
│ ├── index.html
│ └── part5.js
├── part6
│ ├── index.html
│ └── part6.js
├── part7
│ ├── index.html
│ └── part7.js
├── part8
│ ├── index.html
│ └── part8.js
├── phaser
│ ├── phaser.js
│ └── phaser.map
└── states
│ ├── index.html
│ └── states.js
├── gulpfile.js
├── package.json
├── src
├── examples
│ ├── button.js
│ ├── graphics-button.js
│ ├── graphics.js
│ ├── part5.js
│ ├── part6.js
│ ├── part7.js
│ ├── part8.js
│ └── states.js
├── impl
│ ├── nodes.js
│ ├── physic-system-name.js
│ ├── properties
│ │ ├── base
│ │ │ ├── PIXI.DisplayObject.js
│ │ │ ├── PIXI.DisplayObjectContainer.js
│ │ │ ├── PIXI.Graphics.js
│ │ │ ├── PIXI.Sprite.js
│ │ │ ├── Phaser.Button.js
│ │ │ ├── Phaser.Component.Angle.js
│ │ │ ├── Phaser.Component.Animation.js
│ │ │ ├── Phaser.Component.AutoCull.js
│ │ │ ├── Phaser.Component.Bounds.js
│ │ │ ├── Phaser.Component.BringToTop.js
│ │ │ ├── Phaser.Component.Core.js
│ │ │ ├── Phaser.Component.Crop.js
│ │ │ ├── Phaser.Component.Delta.js
│ │ │ ├── Phaser.Component.Destroy.js
│ │ │ ├── Phaser.Component.FixedToCamera.js
│ │ │ ├── Phaser.Component.Health.js
│ │ │ ├── Phaser.Component.InCamera.js
│ │ │ ├── Phaser.Component.InWorld.js
│ │ │ ├── Phaser.Component.InputEnabled.js
│ │ │ ├── Phaser.Component.LifeSpan.js
│ │ │ ├── Phaser.Component.LoadTexture.js
│ │ │ ├── Phaser.Component.Overlap.js
│ │ │ ├── Phaser.Component.PhysicsBody.js
│ │ │ ├── Phaser.Component.Reset.js
│ │ │ ├── Phaser.Component.ScaleMinMax.js
│ │ │ ├── Phaser.Component.Smoothed.js
│ │ │ ├── Phaser.Game.js
│ │ │ ├── Phaser.Graphics.js
│ │ │ ├── Phaser.Group.js
│ │ │ ├── Phaser.Image.js
│ │ │ ├── Phaser.Sprite.js
│ │ │ └── Phaser.Text.js
│ │ ├── custom
│ │ │ ├── body.js
│ │ │ └── key.js
│ │ └── utils.js
│ ├── tree-utils.js
│ └── types
│ │ ├── animation.js
│ │ ├── button.js
│ │ ├── collides.js
│ │ ├── game.js
│ │ ├── graphics
│ │ ├── create-graphics-item.js
│ │ ├── graphics.js
│ │ ├── index.js
│ │ ├── renderers.js
│ │ ├── renderimage.js
│ │ ├── rendertexture.js
│ │ └── texturetext.js
│ │ ├── group.js
│ │ ├── index.js
│ │ ├── input
│ │ ├── index.js
│ │ ├── input.js
│ │ └── key.js
│ │ ├── overlaps.js
│ │ ├── sprite.js
│ │ ├── state.js
│ │ └── text.js
├── index.js
├── native.js
├── node-management
│ ├── node-init-adapter.js
│ └── node-tree-adapter.js
└── phaser-implementation.js
└── tests
└── node-management
├── node-init-adapter-test.js
└── node-tree-adapter-test.js
/.babelrc:
--------------------------------------------------------------------------------
1 | { "presets": ["react", "es2015"] }
2 |
3 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea
2 | node_modules
3 |
4 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/evilfer/react-phaser/29ebb4b3d1fb468774ef2e8cef292672689d1e2f/.npmignore
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | Copyright (c) 2016-present, Eloy Villasclaras
2 | All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions are met:
6 |
7 | 1. Redistributions of source code must retain the above copyright notice, this
8 | list of conditions and the following disclaimer.
9 | 2. Redistributions in binary form must reproduce the above copyright notice,
10 | this list of conditions and the following disclaimer in the documentation
11 | and/or other materials provided with the distribution.
12 |
13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
14 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
17 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
20 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
22 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 |
24 | The views and conclusions contained in the software and documentation are those
25 | of the authors and should not be interpreted as representing official policies,
26 | either expressed or implied, of the FreeBSD Project.
27 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # React-phaser
2 |
3 | A React-based wrapper for phaser.
4 |
5 | React-phaser allows game developers to create Phaser games using React. Main features:
6 |
7 | - Phaser objects are represented as React VDOM nodes; react-phaser reacts to VDOM changes by adding, updating or removing Phaser objects.
8 | - React-phaser users a React version unhooked from browser DOM manipulation.
9 |
10 | See the [example code](https://github.com/evilfer/react-phaser/tree/master/src/examples) to see an implementation of the Phaser [Making your first game tutorial](http://phaser.io/tutorials/making-your-first-phaser-game).
11 |
12 | ## Getting started
13 |
14 | Install with:
15 | ```bash
16 | npm install react-phaser
17 | ```
18 |
19 | In your code:
20 |
21 | ```javascript
22 | var React = require('react-phaser'),
23 |
24 | MyGame = React.createClass({
25 | render: function () {
26 | return ;
27 | }
28 | });
29 |
30 | React.render(, 'game');
31 | ```
32 |
33 | - `require('react-phaser')` provides the same object as `require('react')`; however, when react-phaser is first loaded it removes the DOM manipulation functionality from React, and inject the Phaser wrapper.
34 | - `React.render` is a method added by react-phaser. that initializes the React lifecycle for the passed element. The second parameter (a string) identifies the virtual container where the game is rendered. This is not a DOM element, but simply a react-phaser internal unique string.
35 | - `` is one of the tags that react-phaser makes available (see [list of available tags](https://github.com/evilfer/react-phaser/wiki/Tags)).
36 |
37 |
38 |
39 | ## Further reading
40 |
41 | - [react-phaser wiki](https://github.com/evilfer/react-phaser/wiki)
--------------------------------------------------------------------------------
/examples/assets/baddie.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/evilfer/react-phaser/29ebb4b3d1fb468774ef2e8cef292672689d1e2f/examples/assets/baddie.png
--------------------------------------------------------------------------------
/examples/assets/button_sprite_sheet.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/evilfer/react-phaser/29ebb4b3d1fb468774ef2e8cef292672689d1e2f/examples/assets/button_sprite_sheet.png
--------------------------------------------------------------------------------
/examples/assets/diamond.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/evilfer/react-phaser/29ebb4b3d1fb468774ef2e8cef292672689d1e2f/examples/assets/diamond.png
--------------------------------------------------------------------------------
/examples/assets/dude.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/evilfer/react-phaser/29ebb4b3d1fb468774ef2e8cef292672689d1e2f/examples/assets/dude.png
--------------------------------------------------------------------------------
/examples/assets/firstaid.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/evilfer/react-phaser/29ebb4b3d1fb468774ef2e8cef292672689d1e2f/examples/assets/firstaid.png
--------------------------------------------------------------------------------
/examples/assets/platform.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/evilfer/react-phaser/29ebb4b3d1fb468774ef2e8cef292672689d1e2f/examples/assets/platform.png
--------------------------------------------------------------------------------
/examples/assets/sky.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/evilfer/react-phaser/29ebb4b3d1fb468774ef2e8cef292672689d1e2f/examples/assets/sky.png
--------------------------------------------------------------------------------
/examples/assets/star.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/evilfer/react-phaser/29ebb4b3d1fb468774ef2e8cef292672689d1e2f/examples/assets/star.png
--------------------------------------------------------------------------------
/examples/assets/states_player.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/evilfer/react-phaser/29ebb4b3d1fb468774ef2e8cef292672689d1e2f/examples/assets/states_player.png
--------------------------------------------------------------------------------
/examples/assets/states_win.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/evilfer/react-phaser/29ebb4b3d1fb468774ef2e8cef292672689d1e2f/examples/assets/states_win.png
--------------------------------------------------------------------------------
/examples/button/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/examples/graphics-button/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/examples/graphics/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/examples/part5/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/examples/part6/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/examples/part7/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/examples/part8/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/examples/states/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/gulpfile.js:
--------------------------------------------------------------------------------
1 | var gulp = require('gulp'),
2 | path = require('path'),
3 | gutil = require('gulp-util'),
4 |
5 | webpack = require('webpack'),
6 |
7 | jsTaskGen = function (mode) {
8 | var isProd = mode === 'prod',
9 | doWatch = mode === 'watch',
10 | output = './examples/';
11 |
12 | return function () {
13 | return webpack({
14 | entry: {
15 | 'part5/part5': './src/examples/part5.js',
16 | 'part6/part6': './src/examples/part6.js',
17 | 'part7/part7': './src/examples/part7.js',
18 | 'part8/part8': './src/examples/part8.js',
19 | 'button/button': './src/examples/button.js',
20 | 'graphics/graphics': './src/examples/graphics.js',
21 | 'graphics-button/graphics-button': './src/examples/graphics-button.js',
22 | 'states/states': './src/examples/states.js'
23 | },
24 | watch: doWatch,
25 | module: {
26 | loaders: [{
27 | test: /.jsx?$/,
28 | loader: 'babel-loader',
29 | exclude: /node_modules/,
30 | query: {
31 | presets: ['es2015', 'react']
32 | }
33 | }]
34 | },
35 | plugins: isProd ? [new webpack.optimize.UglifyJsPlugin()] : [],
36 | output: {
37 | path: path.join(__dirname, output),
38 | filename: '[name].' + (isProd ? 'min.js' : 'js')
39 | },
40 | devtool: !isProd && '#inline-source-map'
41 | }, function (err, stats) {
42 | if (err) throw new gutil.PluginError("webpack", err);
43 | gutil.log("[webpack]", stats.toString({}));
44 | });
45 | }
46 | };
47 |
48 |
49 | gulp.task('js-dev', jsTaskGen('dev', 'web'));
50 | gulp.task('js-prod', jsTaskGen('prod', 'web'));
51 | gulp.task('js-watch', jsTaskGen('watch', 'web'));
52 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-phaser",
3 | "version": "0.1.6",
4 | "description": "Phaser implementation for React",
5 | "repository": {
6 | "type": "git",
7 | "url": "https://github.com/evilfer/react-phaser.git"
8 | },
9 | "main": "src/index.js",
10 | "scripts": {
11 | "test": "echo \"Error: no test specified\" && exit 1"
12 | },
13 | "author": "Eloy Villasclaras ",
14 | "license": "BSD",
15 | "bugs": {
16 | "url": "https://github.com/evilfer/react-phaser/issues"
17 | },
18 | "keywords": [
19 | "React",
20 | "Phaser"
21 | ],
22 | "dependencies": {
23 | "extend": "^3.0.0",
24 | "invariant": "^2.2.1",
25 | "p2": "^0.7.1",
26 | "phaser": "^2.4.6",
27 | "react-anything": "^0.1.5"
28 | },
29 | "devDependencies": {
30 | "babel-core": "^6.7.6",
31 | "babel-loader": "^6.2.4",
32 | "babel-preset-es2015": "6.6.0",
33 | "babel-preset-react": "6.5.0",
34 | "chai": "^3.5.0",
35 | "gulp": "^3.9.1",
36 | "gulp-util": "^3.0.7",
37 | "mocha": "^2.4.5",
38 | "script": "^0.1.4",
39 | "sinon": "^1.17.3",
40 | "sinon-chai": "^2.8.0",
41 | "webpack": "^1.12.14"
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/src/examples/button.js:
--------------------------------------------------------------------------------
1 | var React = require('../native'),
2 |
3 | assets = {
4 | 'sky': {type: 'image', src: '../assets/sky.png'},
5 | 'ground': {type: 'image', src: '../assets/platform.png'},
6 | 'star': {type: 'image', src: '../assets/star.png'},
7 | 'dude': {type: 'spritesheet', src: '../assets/dude.png', width: 32, height: 48},
8 | 'button': {type: 'spritesheet', src: '../assets/button_sprite_sheet.png', width: 193, height: 71}
9 | },
10 |
11 | scoreStyle = {
12 | fontSize: '32px',
13 | fill: '#000'
14 | },
15 |
16 | MyGame = React.createClass({
17 | getInitialState: function () {
18 | return {
19 | stars: Array.apply(null, {length: 12}).map(function (_, i) {
20 | return [i, 0.7 + Math.random() * 0.2];
21 | }),
22 | score: 0
23 | };
24 | },
25 |
26 | onInput: function (context) {
27 | var player = context.nodes.player.obj,
28 | cursors = context.input.cursors;
29 |
30 | if (cursors.left.isDown) {
31 | player.body.velocity.x = -150;
32 | player.animations.play('left');
33 | } else if (cursors.right.isDown) {
34 | player.body.velocity.x = 150;
35 | player.animations.play('right');
36 | } else {
37 | player.body.velocity.x = 0;
38 | player.animations.stop();
39 | player.frame = 4;
40 | }
41 |
42 | if (cursors.up.isDown && player.body.touching.down) {
43 | player.body.velocity.y = -350;
44 | }
45 | },
46 |
47 | collectStar: function (playerNode, starNode) {
48 | this.setState({
49 | stars: this.state.stars.filter(function (_, i) {
50 | return i !== starNode.props.i;
51 | }),
52 | score: this.state.score + 10
53 | });
54 | },
55 |
56 | render: function () {
57 | var stars = this.state.stars.map(function (star, i) {
58 | return
60 | });
61 |
62 |
63 | return (
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 | {stars}
74 |
75 |
78 |
79 |
80 |
81 |
82 |
83 |
85 |
88 |
89 |
90 | );
91 | }
92 | });
93 |
94 |
95 | React.render(, 'game');
--------------------------------------------------------------------------------
/src/examples/graphics-button.js:
--------------------------------------------------------------------------------
1 | var React = require('../native'),
2 |
3 | buttonShape = {
4 | width: 200,
5 | height: 40,
6 | radius: 5
7 | },
8 |
9 | MyGame = React.createClass({
10 |
11 | render: function () {
12 | return (
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
25 |
26 |
27 |
29 |
30 |
31 |
33 |
34 |
35 |
37 |
38 |
39 |
42 |
43 |
44 | );
45 | }
46 | });
47 |
48 |
49 | React.render(, 'game');
--------------------------------------------------------------------------------
/src/examples/graphics.js:
--------------------------------------------------------------------------------
1 | var React = require('../native'),
2 |
3 | assets = {
4 | 'sky': {type: 'image', src: '../assets/sky.png'},
5 | 'ground': {type: 'image', src: '../assets/platform.png'},
6 | 'star': {type: 'image', src: '../assets/star.png'},
7 | 'dude': {type: 'spritesheet', src: '../assets/dude.png', width: 32, height: 48},
8 | 'button': {type: 'spritesheet', src: '../assets/button_sprite_sheet.png', width: 193, height: 71}
9 | },
10 |
11 | scoreStyle = {
12 | fontSize: '32px',
13 | fill: '#000'
14 | },
15 |
16 | MyGame = React.createClass({
17 | getInitialState: function () {
18 | return {
19 | stars: Array.apply(null, {length: 12}).map(function (_, i) {
20 | return [i, 0.7 + Math.random() * 0.2];
21 | }),
22 | score: 0
23 | };
24 | },
25 |
26 | onInput: function (context) {
27 | var player = context.nodes.player.obj,
28 | cursors = context.input.cursors;
29 |
30 | if (cursors.left.isDown) {
31 | player.body.velocity.x = -150;
32 | player.animations.play('left');
33 | } else if (cursors.right.isDown) {
34 | player.body.velocity.x = 150;
35 | player.animations.play('right');
36 | } else {
37 | player.body.velocity.x = 0;
38 | player.animations.stop();
39 | player.frame = 4;
40 | }
41 |
42 | if (cursors.up.isDown && player.body.touching.down) {
43 | player.body.velocity.y = -350;
44 | }
45 | },
46 |
47 | collectStar: function (playerNode, starNode) {
48 | this.setState({
49 | stars: this.state.stars.filter(function (_, i) {
50 | return i !== starNode.props.i;
51 | }),
52 | score: this.state.score + 10
53 | });
54 | },
55 |
56 | render: function () {
57 | var stars = this.state.stars.map(function (star, i) {
58 | return
60 | });
61 |
62 |
63 | return (
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 | {stars}
74 |
75 |
78 |
79 |
80 |
81 |
82 |
83 |
85 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
108 |
110 |
111 |
113 |
114 |
115 |
116 |
117 | );
118 | }
119 | });
120 |
121 |
122 | React.render(, 'game');
--------------------------------------------------------------------------------
/src/examples/part5.js:
--------------------------------------------------------------------------------
1 | var React = require('../native'),
2 |
3 | assets = {
4 | 'sky': {type: 'image', src: '../assets/sky.png'},
5 | 'ground': {type: 'image', src: '../assets/platform.png'},
6 | 'star': {type: 'image', src: '../assets/star.png'},
7 | 'dude': {type: 'spritesheet', src: '../assets/dude.png', width: 32, height: 48}
8 | };
9 |
10 | React.render((
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 | ), 'game');
--------------------------------------------------------------------------------
/src/examples/part6.js:
--------------------------------------------------------------------------------
1 | var React = require('../native'),
2 |
3 | assets = {
4 | 'sky': {type: 'image', src: '../assets/sky.png'},
5 | 'ground': {type: 'image', src: '../assets/platform.png'},
6 | 'star': {type: 'image', src: '../assets/star.png'},
7 | 'dude': {type: 'spritesheet', src: '../assets/dude.png', width: 32, height: 48}
8 | },
9 |
10 | onInput = function (context) {
11 | var player = context.nodes.player.obj,
12 | cursors = context.input.cursors;
13 |
14 | if (cursors.left.isDown) {
15 | player.body.velocity.x = -150;
16 | player.animations.play('left');
17 | } else if (cursors.right.isDown) {
18 | player.body.velocity.x = 150;
19 | player.animations.play('right');
20 | } else {
21 | player.body.velocity.x = 0;
22 | player.animations.stop();
23 | player.frame = 4;
24 | }
25 |
26 | if (cursors.up.isDown && player.body.touching.down) {
27 | player.body.velocity.y = -350;
28 | }
29 | };
30 |
31 | React.render((
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
43 |
44 |
45 |
46 |
47 |
48 |
49 | ), 'game');
--------------------------------------------------------------------------------
/src/examples/part7.js:
--------------------------------------------------------------------------------
1 | var React = require('../native'),
2 |
3 | assets = {
4 | 'sky': {type: 'image', src: '../assets/sky.png'},
5 | 'ground': {type: 'image', src: '../assets/platform.png'},
6 | 'star': {type: 'image', src: '../assets/star.png'},
7 | 'dude': {type: 'spritesheet', src: '../assets/dude.png', width: 32, height: 48}
8 | },
9 |
10 | MyGame = React.createClass({
11 | getInitialState: function () {
12 | return {
13 | stars: Array.apply(null, {length: 12}).map(function (_, i) {
14 | return [i, 0.7 + Math.random() * 0.2];
15 | })
16 | };
17 | },
18 |
19 | onInput: function (context) {
20 | var player = context.nodes.player.obj,
21 | cursors = context.input.cursors;
22 |
23 | if (cursors.left.isDown) {
24 | player.body.velocity.x = -150;
25 | player.animations.play('left');
26 | } else if (cursors.right.isDown) {
27 | player.body.velocity.x = 150;
28 | player.animations.play('right');
29 | } else {
30 | player.body.velocity.x = 0;
31 | player.animations.stop();
32 | player.frame = 4;
33 | }
34 |
35 | if (cursors.up.isDown && player.body.touching.down) {
36 | player.body.velocity.y = -350;
37 | }
38 | },
39 |
40 | collectStar: function (playerNode, starNode) {
41 | this.setState({
42 | stars: this.state.stars.filter(function (_, i) {
43 | return i !== starNode.props.i;
44 | })
45 | });
46 | },
47 |
48 | render: function () {
49 | var stars = this.state.stars.map(function (star, i) {
50 | return
52 | });
53 |
54 |
55 | return (
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 | {stars}
66 |
67 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 | );
78 | }
79 | });
80 |
81 |
82 | React.render(, 'game');
--------------------------------------------------------------------------------
/src/examples/part8.js:
--------------------------------------------------------------------------------
1 | var React = require('../native'),
2 |
3 | assets = {
4 | 'sky': {type: 'image', src: '../assets/sky.png'},
5 | 'ground': {type: 'image', src: '../assets/platform.png'},
6 | 'star': {type: 'image', src: '../assets/star.png'},
7 | 'dude': {type: 'spritesheet', src: '../assets/dude.png', width: 32, height: 48}
8 | },
9 |
10 | scoreStyle = {
11 | fontSize: '32px',
12 | fill: '#000'
13 | },
14 |
15 | MyGame = React.createClass({
16 | getInitialState: function () {
17 | return {
18 | stars: Array.apply(null, {length: 12}).map(function (_, i) {
19 | return [i, 0.7 + Math.random() * 0.2];
20 | }),
21 | score: 0
22 | };
23 | },
24 |
25 | onInput: function (context) {
26 | var player = context.nodes.player.obj,
27 | cursors = context.input.cursors;
28 |
29 | if (cursors.left.isDown) {
30 | player.body.velocity.x = -150;
31 | player.animations.play('left');
32 | } else if (cursors.right.isDown) {
33 | player.body.velocity.x = 150;
34 | player.animations.play('right');
35 | } else {
36 | player.body.velocity.x = 0;
37 | player.animations.stop();
38 | player.frame = 4;
39 | }
40 |
41 | if (cursors.up.isDown && player.body.touching.down) {
42 | player.body.velocity.y = -350;
43 | }
44 | },
45 |
46 | collectStar: function (playerNode, starNode) {
47 | this.setState({
48 | stars: this.state.stars.filter(function (_, i) {
49 | return i !== starNode.props.i;
50 | }),
51 | score: this.state.score + 10
52 | });
53 | },
54 |
55 | render: function () {
56 | var stars = this.state.stars.map(function (star, i) {
57 | return
59 | });
60 |
61 |
62 | return (
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 | {stars}
73 |
74 |
77 |
78 |
79 |
80 |
81 |
82 |
84 |
85 |
86 | );
87 | }
88 | });
89 |
90 |
91 | React.render(, 'game');
--------------------------------------------------------------------------------
/src/examples/states.js:
--------------------------------------------------------------------------------
1 | var React = require('../native'),
2 |
3 | textStyle = {
4 | fontSize: '12px',
5 | fill: '#fff'
6 | },
7 |
8 | MyGame = React.createClass({
9 | getInitialState: function () {
10 | return {
11 | name: "stateA"
12 | };
13 | },
14 |
15 | startState: function (stateName) {
16 | this.setState({name: stateName});
17 | },
18 |
19 | render: function () {
20 | return (
21 |
22 |
23 |
24 |
26 |
27 |
28 |
29 |
30 |
31 |
33 |
34 |
35 |
36 |
37 | );
38 | }
39 | });
40 |
41 |
42 | React.render(, 'game');
--------------------------------------------------------------------------------
/src/impl/nodes.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var nodeTypes = require('./types'),
4 |
5 | Nodes = function () {
6 | this.gameNode = null;
7 | this.ids = {};
8 | this.name2node = {};
9 | this.transactionListeners = [];
10 | };
11 |
12 | Nodes.prototype.setGameNode = function (node) {
13 | this.gameNode = node;
14 | };
15 |
16 |
17 | Nodes.prototype.requestTransactionNofitication = function (nodeid) {
18 | if (this.transactionListeners.indexOf(nodeid) < 0) {
19 | this.transactionListeners.push(nodeid);
20 | }
21 | };
22 |
23 | Nodes.prototype.cancelTransactionNofitication = function (nodeid) {
24 | var index = this.transactionListeners.indexOf(nodeid);
25 | if (index >= 0) {
26 | this.transactionListeners.splice(index, 1);
27 | }
28 | };
29 |
30 | Nodes.prototype.game = function () {
31 | return this.gameNode.obj;
32 | };
33 |
34 |
35 | Nodes.prototype._registerName = function (node) {
36 | this.ids[node.id] = node;
37 | if (node.props.name) {
38 | this.name2node[node.props.name] = node;
39 | }
40 | };
41 |
42 | Nodes.prototype._updateName = function (node, lastProps) {
43 | if (lastProps.name !== node.props.name) {
44 | delete this.name2node[lastProps.name];
45 | this.name2node[node.props.name] = node;
46 | }
47 | };
48 |
49 | Nodes.prototype._unregisterName = function (node) {
50 | delete this.ids[node.id];
51 | if (node.props.name) {
52 | delete this.name2node[node.props.name];
53 | }
54 | };
55 |
56 | Nodes.prototype.byId = function (id) {
57 | return this.ids[id];
58 | };
59 |
60 |
61 | Nodes.prototype.byName = function (name) {
62 | return this.name2node[name];
63 | };
64 |
65 | Nodes.prototype.parent = function (node, tag) {
66 | while (true) {
67 | var parent = this.ids[node.parent] || null;
68 | if (!parent || parent.tag === tag) {
69 | return parent;
70 | } else {
71 | node = parent;
72 | }
73 | }
74 | };
75 |
76 |
77 | Nodes.prototype.gameState = function (node) {
78 | while (true) {
79 | var parent = this.ids[node.parent] || null;
80 | if (!parent || parent.tag === 'game' || parent.tag === 'state') {
81 | return parent;
82 | } else {
83 | node = parent;
84 | }
85 | }
86 | };
87 |
88 | Nodes.prototype.context = function (node) {
89 | return this.gameState(node).context;
90 | };
91 |
92 |
93 | Nodes.prototype.parentInitd = function (node) {
94 | var parent = this.ids[node.parent];
95 |
96 | return !parent || parent.initialized;
97 | };
98 |
99 | Nodes.prototype._invoke = function (node, method) {
100 | var nodeType = nodeTypes[node.tag];
101 | if (nodeType && nodeType[method]) {
102 | nodeType[method](this, node);
103 | }
104 | };
105 |
106 | Nodes.prototype.mountNode = function (node) {
107 | this.ids[node.id] = node;
108 | if (node.tag === 'game') {
109 | this.setGameNode(node);
110 | }
111 |
112 | if (!node.initialized && this.parentInitd(node) && this.initImmediately(node)) {
113 | this._initNode(node, 'init');
114 | }
115 | };
116 |
117 | Nodes.prototype._initNode = function (node, method) {
118 | node.initialized = true;
119 | this._registerName(node);
120 | this._invoke(node, method);
121 | if (node.obj) {
122 | node.obj.rnodeid = node.id;
123 | }
124 | };
125 |
126 | Nodes.prototype.updateNode = function (node, prevProps) {
127 | this._updateName(node, prevProps);
128 |
129 | var nodeType = nodeTypes[node.tag];
130 | if (nodeType && nodeType.update) {
131 | var changedProps = Object.keys(node.props);
132 | changedProps = changedProps.filter(function (key) {
133 | return key !== 'children' && node.props[key] !== prevProps[key];
134 | });
135 |
136 | Object.keys(prevProps).forEach(function (key) {
137 | if (key !== 'children' && !(key in node.props)) {
138 | changedProps.push(key);
139 | }
140 | });
141 |
142 | if (changedProps.length > 0) {
143 | nodeType.update(this, node, changedProps, prevProps);
144 | }
145 | }
146 | };
147 |
148 | Nodes.prototype.unmountNode = function (node) {
149 | this._unregisterName(node);
150 | this._invoke(node, 'kill');
151 | };
152 |
153 | Nodes.prototype.onChildrenMount = function (node) {
154 | if (this.parentInitd(node)) {
155 | if (node.initialized) {
156 | this._invoke(node, 'onChildrenInit')
157 | } else {
158 | this._initNode(node, 'onChildrenInit');
159 | }
160 | }
161 | };
162 |
163 | Nodes.prototype.notifyTransaction = function () {
164 | if (this.transactionListeners.length > 0) {
165 | for (var i = 0; i < this.transactionListeners.length; i++) {
166 | var node = this.ids[this.transactionListeners[i]];
167 | if (node) {
168 | this._invoke(node, 'notifyTransaction');
169 | }
170 | }
171 | }
172 | };
173 |
174 | Nodes.prototype.clearChildren = function (children, options) {
175 | var options = options || {},
176 | include = options.include,
177 | exclude = options.exclude;
178 |
179 | for (var i = 0; i < children.length; i++) {
180 | var child = this.ids[children[i]],
181 | shouldClear = child.initialized &&
182 | (!include || include.indexOf(child.tag) >= 0) &&
183 | (!exclude || exclude.indexOf(child.tag) < 0);
184 |
185 | if (shouldClear) {
186 | this._invoke(child, 'clear');
187 | child.initialized = false;
188 | if (child.children.length > 0) {
189 | this.clearChildren(child.children);
190 | }
191 | }
192 | }
193 | };
194 |
195 | Nodes.prototype.initChildren = function (children, options) {
196 | var _options = options || {},
197 | include = _options.include,
198 | exclude = _options.exclude;
199 |
200 | for (var i = 0; i < children.length; i++) {
201 | var child = this.ids[children[i]],
202 | shouldInit = this.parentInitd(child) && !child.initialized &&
203 | (!include || include.indexOf(child.tag) >= 0) &&
204 | (!exclude || exclude.indexOf(child.tag) < 0);
205 |
206 | if (shouldInit) {
207 | if (this.initImmediately(child)) {
208 | this._initNode(child, 'init');
209 | if (child.children.length > 0) {
210 | this.initChildren(child.children);
211 | this._invoke(child, 'onChildrenInit');
212 | }
213 | } else {
214 | this._initNode(child, 'onChildrenInit');
215 | }
216 | }
217 | }
218 | };
219 |
220 | Nodes.prototype.initImmediately = function (node) {
221 | var nodeType = nodeTypes[node.tag];
222 | return nodeType && !nodeType.initOnChildrenMount;
223 | };
224 |
225 | module.exports = Nodes;
226 |
--------------------------------------------------------------------------------
/src/impl/physic-system-name.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var names = {};
4 |
5 | names[Phaser.Physics.ARCADE] = 'arcade';
6 | names[Phaser.Physics.BOX2D] = 'box2d';
7 | names[Phaser.Physics.CHIPMUNK] = 'chipmunk';
8 | names[Phaser.Physics.MATTERJS] = 'matter';
9 | names[Phaser.Physics.NINJA] = 'ninja';
10 | names[Phaser.Physics.P2JS] = 'p2';
11 |
12 | module.exports = function (system) {
13 | return names[system] || 'arcade';
14 | };
15 |
--------------------------------------------------------------------------------
/src/impl/properties/base/PIXI.DisplayObject.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var utils = require('../utils');
4 |
5 | module.exports = utils.generatePointPropMap(['scale']);
6 |
--------------------------------------------------------------------------------
/src/impl/properties/base/PIXI.DisplayObjectContainer.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var extend = require('extend');
4 |
5 | module.exports = extend(
6 | {},
7 | require('./PIXI.DisplayObject')
8 | );
9 |
--------------------------------------------------------------------------------
/src/impl/properties/base/PIXI.Graphics.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var extend = require('extend');
4 |
5 | module.exports = extend(
6 | {},
7 | require('./PIXI.DisplayObjectContainer')
8 | );
9 |
--------------------------------------------------------------------------------
/src/impl/properties/base/PIXI.Sprite.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var extend = require('extend');
4 |
5 | module.exports = extend(
6 | {},
7 | require('./PIXI.DisplayObjectContainer')
8 | );
9 |
--------------------------------------------------------------------------------
/src/impl/properties/base/Phaser.Button.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 |
4 | var extend = require('extend');
5 |
6 | module.exports = extend(
7 | {},
8 | require('./Phaser.Image')
9 | );
10 |
11 |
--------------------------------------------------------------------------------
/src/impl/properties/base/Phaser.Component.Angle.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 |
4 |
5 | var generateBasicPropMap = require('../utils').generateBasicPropMap;
6 |
7 | module.exports = generateBasicPropMap(['angle']);
8 |
--------------------------------------------------------------------------------
/src/impl/properties/base/Phaser.Component.Animation.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = {};
4 |
--------------------------------------------------------------------------------
/src/impl/properties/base/Phaser.Component.AutoCull.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 |
4 |
5 | var generateBasicPropMap = require('../utils').generateBasicPropMap;
6 |
7 | module.exports = generateBasicPropMap(['autocull']);
8 | /**
9 | * inCamera
10 | */
11 |
--------------------------------------------------------------------------------
/src/impl/properties/base/Phaser.Component.Bounds.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = {};
4 |
--------------------------------------------------------------------------------
/src/impl/properties/base/Phaser.Component.BringToTop.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = {};
4 |
--------------------------------------------------------------------------------
/src/impl/properties/base/Phaser.Component.Core.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var utils = require('../utils');
4 |
5 | module.exports = utils.generateAliasPropMap({
6 | assetKey: 'key'
7 | });
8 |
--------------------------------------------------------------------------------
/src/impl/properties/base/Phaser.Component.Crop.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | module.exports = {};
3 |
--------------------------------------------------------------------------------
/src/impl/properties/base/Phaser.Component.Delta.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = {};
4 |
--------------------------------------------------------------------------------
/src/impl/properties/base/Phaser.Component.Destroy.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = {};
4 |
--------------------------------------------------------------------------------
/src/impl/properties/base/Phaser.Component.FixedToCamera.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = {};
4 |
--------------------------------------------------------------------------------
/src/impl/properties/base/Phaser.Component.Health.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = {};
4 |
--------------------------------------------------------------------------------
/src/impl/properties/base/Phaser.Component.InCamera.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = {};
4 |
--------------------------------------------------------------------------------
/src/impl/properties/base/Phaser.Component.InWorld.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 |
4 |
5 | var generateBasicPropMap = require('../utils').generateBasicPropMap;
6 |
7 | module.exports = generateBasicPropMap(['checkWorldBounds', 'outOfBoundsKill']);
8 | /**
9 | * inWorld
10 | */
11 |
--------------------------------------------------------------------------------
/src/impl/properties/base/Phaser.Component.InputEnabled.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = {};
4 |
--------------------------------------------------------------------------------
/src/impl/properties/base/Phaser.Component.LifeSpan.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var generateBasicPropMap = require('../utils').generateBasicPropMap;
4 |
5 | module.exports = generateBasicPropMap(['alive', 'lifespan']);
6 |
--------------------------------------------------------------------------------
/src/impl/properties/base/Phaser.Component.LoadTexture.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var generateBasicPropMap = require('../utils').generateBasicPropMap;
4 |
5 | module.exports = generateBasicPropMap(['frame', 'frameName']);
6 |
--------------------------------------------------------------------------------
/src/impl/properties/base/Phaser.Component.Overlap.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = {};
4 |
--------------------------------------------------------------------------------
/src/impl/properties/base/Phaser.Component.PhysicsBody.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var extend = require('extend'),
4 | utils = require('../utils');
5 |
6 | module.exports = extend(
7 | {},
8 | utils.generateBasicPropMap(['x', 'y']),
9 | require('../custom/body')
10 | );
11 |
--------------------------------------------------------------------------------
/src/impl/properties/base/Phaser.Component.Reset.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = {};
4 |
--------------------------------------------------------------------------------
/src/impl/properties/base/Phaser.Component.ScaleMinMax.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = {};
4 |
--------------------------------------------------------------------------------
/src/impl/properties/base/Phaser.Component.Smoothed.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var generateBasicPropMap = require('../utils').generateBasicPropMap;
4 |
5 | module.exports = generateBasicPropMap(['smoothed'])
--------------------------------------------------------------------------------
/src/impl/properties/base/Phaser.Game.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var extend = require('extend'),
4 | utils = require('../utils'),
5 |
6 | generateCustomPropMap = utils.generateCustomPropMap,
7 | generatePrefixedBasicPropMap = utils.generatePrefixedBasicPropMap;
8 |
9 |
10 | module.exports = extend(
11 | generateCustomPropMap({
12 | 'stateName': function (node, value) {
13 | if (value) {
14 | node.obj.state.start(value);
15 | }
16 | }
17 | }),
18 | generatePrefixedBasicPropMap('stage', ['backgroundColor'])
19 | );
20 |
--------------------------------------------------------------------------------
/src/impl/properties/base/Phaser.Graphics.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var extend = require('extend');
4 |
5 | module.exports = extend(
6 | {},
7 | require('./PIXI.Graphics'),
8 | require('./Phaser.Component.Core'),
9 | require('./Phaser.Component.Angle'),
10 | require('./Phaser.Component.AutoCull'),
11 | require('./Phaser.Component.Bounds'),
12 | require('./Phaser.Component.Destroy'),
13 | require('./Phaser.Component.FixedToCamera'),
14 | require('./Phaser.Component.InputEnabled'),
15 | require('./Phaser.Component.InWorld'),
16 | require('./Phaser.Component.LifeSpan'),
17 | require('./Phaser.Component.PhysicsBody'),
18 | require('./Phaser.Component.Reset')
19 | );
20 |
21 |
--------------------------------------------------------------------------------
/src/impl/properties/base/Phaser.Group.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 |
4 | var extend = require('extend'),
5 | generateBasicPropMap = require('../utils').generateBasicPropMap;
6 |
7 | module.exports = extend(
8 | {},
9 | require('./PIXI.DisplayObjectContainer'),
10 | generateBasicPropMap(['enableBody'])
11 | );
12 |
--------------------------------------------------------------------------------
/src/impl/properties/base/Phaser.Image.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 |
4 | var extend = require('extend');
5 |
6 | module.exports = extend(
7 | {},
8 | require('./PIXI.Sprite'),
9 | require('./Phaser.Component.Core'),
10 | require('./Phaser.Component.Angle'),
11 | require('./Phaser.Component.Animation'),
12 | require('./Phaser.Component.AutoCull'),
13 | require('./Phaser.Component.Bounds'),
14 | require('./Phaser.Component.BringToTop'),
15 | require('./Phaser.Component.Crop'),
16 | require('./Phaser.Component.Delta'),
17 | require('./Phaser.Component.Destroy'),
18 | require('./Phaser.Component.FixedToCamera'),
19 | require('./Phaser.Component.InputEnabled'),
20 | require('./Phaser.Component.LifeSpan'),
21 | require('./Phaser.Component.LoadTexture'),
22 | require('./Phaser.Component.Overlap'),
23 | require('./Phaser.Component.Reset'),
24 | require('./Phaser.Component.Smoothed')
25 | );
26 |
27 |
--------------------------------------------------------------------------------
/src/impl/properties/base/Phaser.Sprite.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 |
4 | var extend = require('extend');
5 |
6 | module.exports = extend(
7 | {},
8 | require('./PIXI.Sprite'),
9 | require('./Phaser.Component.Core'),
10 | require('./Phaser.Component.Angle'),
11 | require('./Phaser.Component.Animation'),
12 | require('./Phaser.Component.AutoCull'),
13 | require('./Phaser.Component.Bounds'),
14 | require('./Phaser.Component.BringToTop'),
15 | require('./Phaser.Component.Crop'),
16 | require('./Phaser.Component.Delta'),
17 | require('./Phaser.Component.Destroy'),
18 | require('./Phaser.Component.FixedToCamera'),
19 | require('./Phaser.Component.Health'),
20 | require('./Phaser.Component.InCamera'),
21 | require('./Phaser.Component.InputEnabled'),
22 | require('./Phaser.Component.InWorld'),
23 | require('./Phaser.Component.LifeSpan'),
24 | require('./Phaser.Component.LoadTexture'),
25 | require('./Phaser.Component.Overlap'),
26 | require('./Phaser.Component.PhysicsBody'),
27 | require('./Phaser.Component.Reset'),
28 | require('./Phaser.Component.ScaleMinMax'),
29 | require('./Phaser.Component.Smoothed')
30 | );
31 |
32 |
--------------------------------------------------------------------------------
/src/impl/properties/base/Phaser.Text.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 |
4 | var extend = require('extend'),
5 | utils = require('../utils');
6 |
7 | module.exports = extend(
8 | {},
9 | require('./Phaser.Sprite'),
10 | utils.generateBasicPropMap(['text'])
11 | );
12 |
13 |
--------------------------------------------------------------------------------
/src/impl/properties/custom/body.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var extend = require('extend'),
4 | utils = require('../utils'),
5 | treeUtils = require('../../tree-utils');
6 |
7 | module.exports = extend(
8 | {},
9 | utils.generatePrefixedBasicPropMap('body', ['immovable', 'collideWorldBounds']),
10 | utils.generatePrefixedPointPropMap('body', ['bounce', 'gravity']),
11 | utils.generateMountOnlyPropMap({
12 | bodyPhysics: function (node, value, tree) {
13 | var physics = treeUtils.physics(node, tree),
14 | system = value !== true ? value : physics.system;
15 |
16 | physics.enable(node.obj, system);
17 | }
18 | })
19 | );
20 |
--------------------------------------------------------------------------------
/src/impl/properties/custom/key.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var utils = require('../utils');
4 |
5 | module.exports = utils.generateFixedPropMap(['keyName', 'keyCode']);
6 |
--------------------------------------------------------------------------------
/src/impl/properties/utils.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var invariant = require('invariant'),
4 |
5 | generateBasicPropMap = function (props) {
6 | return props.reduce(function (acc, prop) {
7 | acc[prop] = function (node, value) {
8 | node.obj[prop] = value;
9 | };
10 | return acc;
11 | }, {});
12 | },
13 |
14 | generatePrefixedBasicPropMap = function (prefix, props) {
15 | return props.reduce(function (acc, prop) {
16 | acc[prefix + prop.charAt(0).toUpperCase() + prop.slice(1)] = function (node, value) {
17 | console.log(node.obj);
18 | console.log(node.obj[prefix]);
19 | console.log(prefix, prop, value);
20 | node.obj[prefix][prop] = value;
21 | };
22 | return acc;
23 | }, {});
24 | },
25 |
26 |
27 | generatePointPropMap = function (props) {
28 | return props.reduce(function (acc, prop) {
29 | acc[prop] = function (node, value, prevValue, isNew) {
30 | var point = node.obj[prop];
31 | if (isNew || value.x !== prevValue.x) {
32 | point.x = value.x;
33 | }
34 | if (isNew || value.y !== prevValue.y) {
35 | point.y = value.y;
36 | }
37 | };
38 | acc[prop + 'X'] = function (node, value) {
39 | node.obj[prop].x = value;
40 | };
41 | acc[prop + 'Y'] = function (node, value) {
42 | node.obj[prop].y = value;
43 | };
44 | return acc;
45 | }, {});
46 | },
47 |
48 | generatePrefixedPointPropMap = function (prefix, props) {
49 | return props.reduce(function (acc, prop) {
50 | var prefixedProp = prefix + prop.charAt(0).toUpperCase() + prop.slice(1);
51 | acc[prefixedProp] = function (node, value, prevValue, isNew) {
52 | var point = node.obj[prefix][prop];
53 | if (isNew || value.x !== prevValue.x) {
54 | point.x = value.x;
55 | }
56 | if (isNew || value.y !== prevValue.y) {
57 | point.y = value.y;
58 | }
59 | };
60 | acc[prefixedProp + 'X'] = function (node, value) {
61 | node.obj[prefix][prop].x = value;
62 | };
63 | acc[prefixedProp + 'Y'] = function (node, value) {
64 | node.obj[prefix][prop].y = value;
65 | };
66 | return acc;
67 | }, {});
68 | },
69 |
70 | generateAliasPropMap = function (aliases) {
71 | return Object.keys(aliases).reduce(function (acc, alias) {
72 | var prop = aliases[alias];
73 | acc[alias] = function (node, value) {
74 | node.obj[prop] = value;
75 | };
76 | return acc;
77 | }, {});
78 | },
79 | generateMountOnlyPropMap = function (propMap) {
80 | return Object.keys(propMap).reduce(function (acc, prop) {
81 | var impl = propMap[prop];
82 | acc[prop] = function (node, value, prevValue, isNew, deleted, tree) {
83 | if (isNew) {
84 | impl(node, value, tree);
85 | }
86 | };
87 | return acc;
88 | }, {});
89 | },
90 |
91 | generateCustomPropMap = function (props) {
92 | return props;
93 | },
94 |
95 | generateFixedPropMap = function (props) {
96 | return props.reduce(function (acc, prop) {
97 | acc[prop] = function (node, value, prevValue, isNew) {
98 | invariant(isNew, "Property '%s' of '%s' cannot change.", prop, node.tag);
99 | };
100 | return acc;
101 | }, {});
102 | };
103 |
104 | module.exports = {
105 | generateBasicPropMap: generateBasicPropMap,
106 | generatePrefixedBasicPropMap: generatePrefixedBasicPropMap,
107 | generatePointPropMap: generatePointPropMap,
108 | generatePrefixedPointPropMap: generatePrefixedPointPropMap,
109 | generateAliasPropMap: generateAliasPropMap,
110 | generateMountOnlyPropMap: generateMountOnlyPropMap,
111 | generateCustomPropMap: generateCustomPropMap,
112 | generateFixedPropMap: generateFixedPropMap
113 | };
114 |
--------------------------------------------------------------------------------
/src/impl/tree-utils.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var propsChanged = function (nextProps, lastProps) {
4 | if (!lastProps) {
5 | return true;
6 | }
7 |
8 | var npl = Object.keys(nextProps),
9 | lpl = Object.keys(lastProps);
10 |
11 | if (npl.length !== lpl.length) {
12 | return true;
13 | }
14 |
15 | for (var i = 0; i < npl.length; i++) {
16 | var prop = npl[i];
17 | if (nextProps[prop] !== lastProps[prop]) {
18 | return true;
19 | }
20 | }
21 |
22 | return false;
23 | },
24 |
25 | genPropertyMapUpdate = function (props) {
26 | return function (node, prevProps, tree) {
27 | if (prevProps) {
28 | Object.keys(prevProps).forEach(function (prop) {
29 | if (props[prop] && typeof node.props[prop] === 'undefined') {
30 | props[prop](node, node.props[prop], prevProps[prop], false, true, tree);
31 | }
32 | });
33 | }
34 | Object.keys(node.props).forEach(function (prop) {
35 | if (props[prop] && (!prevProps || node.props[prop] !== prevProps[prop])) {
36 | props[prop](node, node.props[prop], prevProps && prevProps[prop], !prevProps, false, tree);
37 | }
38 | });
39 | }
40 | },
41 |
42 | game = function (tree) {
43 | return tree.root && tree.root.obj;
44 | },
45 |
46 | parent = function (node, tree, type) {
47 | while (true) {
48 | node = tree.nodes[node.parent];
49 | if (!node || !type || type === node.tag) {
50 | return node;
51 | }
52 | }
53 | },
54 |
55 | stateNode = function (node, tree) {
56 | while (true) {
57 | node = tree.nodes[node.parent];
58 | if (!node || node.tag === 'game' || node.tag === 'state') {
59 | return node;
60 | }
61 | }
62 | },
63 |
64 | addDisplayObject = function (node, tree, obj) {
65 | var parent = tree.nodes[node.parent],
66 | group = parent.obj.world || parent.obj;
67 |
68 | group.add(obj || node.obj);
69 | },
70 |
71 | physics = function (node, tree) {
72 | var physicsNode = stateNode(node, tree);
73 | return physicsNode && physicsNode.obj.physics;
74 | };
75 |
76 | module.exports = {
77 | propsChanged: propsChanged,
78 | genPropertyMapUpdate: genPropertyMapUpdate,
79 | game: game,
80 | parent: parent,
81 | addDisplayObject: addDisplayObject,
82 | stateNode: stateNode,
83 | physics: physics
84 | };
85 |
--------------------------------------------------------------------------------
/src/impl/types/animation.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var treeUtils = require('../tree-utils'),
4 |
5 | initAnimation = function (node, tree) {
6 | var parentNode = treeUtils.parent(node, tree);
7 | node.obj = parentNode.obj.animations.add(node.props.id, node.props.frames, node.props.fps, node.props.loop);
8 | };
9 |
10 | module.exports = {
11 | init: initAnimation,
12 | kill: null,
13 | update: null
14 | };
15 |
--------------------------------------------------------------------------------
/src/impl/types/button.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var treeUtils = require('../tree-utils'),
4 | buttonPropertes = require('../properties/base/Phaser.Button'),
5 |
6 | updateButton = treeUtils.genPropertyMapUpdate(buttonPropertes),
7 |
8 | initButton = function (node, tree) {
9 | var props = node.props,
10 | key = props.assetKey,
11 | game = treeUtils.game(tree);
12 |
13 | node.button = new Phaser.Button(
14 | game,
15 | props.x,
16 | props.y,
17 | key,
18 | props.onClick,
19 | node,
20 | props.frames[0],
21 | props.frames[1],
22 | props.frames[2],
23 | props.frames[3]
24 | );
25 |
26 | if (node.props.children) {
27 | node.obj = new Phaser.Group(game);
28 | node.obj.add(node.button);
29 | } else {
30 | node.obj = node.button;
31 | }
32 |
33 | treeUtils.addDisplayObject(node, tree);
34 | updateButton(node, null, tree);
35 | },
36 |
37 | killButton = function (node, tree) {
38 | if (node.obj !== node.button) {
39 | node.obj.destroy();
40 | } else {
41 | node.obj.kill();
42 | }
43 | };
44 |
45 | module.exports = {
46 | init: initButton,
47 | kill: killButton,
48 | update: updateButton
49 | };
50 |
--------------------------------------------------------------------------------
/src/impl/types/collides.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var treeUtils = require('../tree-utils'),
4 | systemName = require('../physic-system-name'),
5 |
6 | initCollides = function (node, tree) {
7 | var a = tree.nodes[node.parent],
8 | b = tree.byname[node.props.with],
9 | name = systemName(node.props.system),
10 | stateNode = treeUtils.stateNode(node, tree);
11 |
12 | node.obj = {
13 | a: a,
14 | b: b,
15 | onUpdate: function (context) {
16 | context.game.physics[name].collide(a.obj, b.obj);
17 | }
18 | };
19 |
20 | stateNode.addUpdateListener(node.obj.onUpdate);
21 | },
22 |
23 | killCollides = function (node, tree) {
24 | var stateNode = treeUtils.stateNode(node, tree);
25 | stateNode.removeUpdateListener(node.obj.onUpdate);
26 | };
27 |
28 | module.exports = {
29 | init: initCollides,
30 | kill: killCollides,
31 | update: null
32 | };
33 |
--------------------------------------------------------------------------------
/src/impl/types/game.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var treeUtils = require('../tree-utils'),
4 | gamePropertes = require('../properties/base/Phaser.Game'),
5 |
6 | updateGame = treeUtils.genPropertyMapUpdate(gamePropertes),
7 |
8 | onChildrenInit = function (node, tree, nodeMethods) {
9 | node._updateMethods = [];
10 | node.addUpdateListener = function (listener) {
11 | node._updateMethods.push(listener);
12 | };
13 | node.removeUpdateListener = function (listener) {
14 | var index = node._updateMethods.indexOf(listener);
15 | if (index >= 0) {
16 | node._updateMethods.splice(index, 1);
17 | }
18 | };
19 |
20 | var props = node.props,
21 | gameImpl = {
22 | preload: function () {
23 | updateGame(node, null, tree);
24 | if (props.assets) {
25 | Object.keys(props.assets).forEach(function (key) {
26 | var asset = props.assets[key];
27 | switch (asset.type) {
28 | case 'image':
29 | game.load.image(key, asset.src);
30 | break;
31 | case 'spritesheet':
32 | game.load.spritesheet(key, asset.src, asset.width, asset.height);
33 | break;
34 | }
35 | });
36 | }
37 | nodeMethods.initChildren(node, tree, {include: ['assets']});
38 | },
39 | create: function () {
40 |
41 | if (node.props.hasOwnProperty('physics')) {
42 | node.obj.physics.startSystem(node.props.physics);
43 | }
44 |
45 | nodeMethods.initChildren(node, tree);
46 |
47 | if (node.props.stateName) {
48 | game.state.start(node.props.stateName);
49 | }
50 | },
51 | update: function () {
52 | for (var i = 0; i < node._updateMethods.length; i++) {
53 | node._updateMethods[i](context);
54 | }
55 | }
56 | },
57 |
58 | game = new Phaser.Game(props.width, props.height, props.mode || Phaser.AUTO, '', gameImpl),
59 | context = {
60 | game: game,
61 | nodes: tree.byname
62 | };
63 |
64 | node.obj = game;
65 | node.context = context;
66 | };
67 |
68 | module.exports = {
69 | init: null,
70 | onChildrenInit: onChildrenInit,
71 | update: updateGame,
72 | kill: null,
73 | deferredInit: true
74 | };
75 |
--------------------------------------------------------------------------------
/src/impl/types/graphics/create-graphics-item.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var treeUtils = require('../../tree-utils'),
4 | create = function (draw) {
5 |
6 | var requestNotification = function (node, tree, treeMethods) {
7 | var graphics = treeUtils.parent(node, tree, 'graphics');
8 | if (graphics) {
9 | treeMethods.requestTransactionNofitication(graphics.id);
10 | }
11 | },
12 |
13 | update = function (node, prevProps, tree, treeMethods) {
14 | if (treeUtils.propsChanged(node.props, prevProps)) {
15 | requestNotification(node, tree, treeMethods);
16 | }
17 | },
18 |
19 |
20 | drawWrapper = function (node, tree, graphics, x0, y0) {
21 | var fill = typeof node.props.fill !== 'undefined',
22 | line = typeof node.props.stroke!== 'undefined' ||
23 | typeof node.props.strokeWidth !== 'undefined' ||
24 | typeof node.props.strokeAlpha !== 'undefined';
25 |
26 | if (fill) {
27 | var fillColor = typeof node.props.fill !== 'undefined' ? node.props.fill : 0x000000,
28 | fillAlpha = typeof node.props.fillAlpha === 'number' ? node.props.fillAlpha : 1;
29 | graphics.beginFill(fillColor, fillAlpha);
30 | }
31 | if (line) {
32 | var lineColor = typeof node.props.stroke !== 'undefined' ? node.props.stroke : 0x000000,
33 | lineAlpha = typeof node.props.strokeAlpha === 'number' ? node.props.strokeAlpha : 1,
34 | lineWidth = typeof node.props.strokeWidth === 'number' ? node.props.strokeWidth : 1;
35 | graphics.lineStyle(lineWidth, lineColor, lineAlpha);
36 | } else {
37 | graphics.lineStyle(0);
38 | }
39 |
40 | draw(node, tree, graphics, x0, y0);
41 |
42 | if (fill) {
43 | graphics.endFill();
44 | }
45 | };
46 |
47 | return {
48 | init: requestNotification,
49 | kill: requestNotification,
50 | update: update,
51 | draw: drawWrapper
52 | };
53 | };
54 |
55 | module.exports = create;
56 |
--------------------------------------------------------------------------------
/src/impl/types/graphics/graphics.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var treeUtils = require('../../tree-utils'),
4 | graphicsPropertes = require('../../properties/base/Phaser.Graphics'),
5 |
6 | updateGraphics = treeUtils.genPropertyMapUpdate(graphicsPropertes),
7 |
8 | itemTypes = require('./renderers'),
9 |
10 | initGraphics = function (node, tree) {
11 | var props = node.props;
12 | node.obj = new Phaser.Graphics(treeUtils.game(tree), props.x, props.y);
13 | treeUtils.addDisplayObject(node, tree);
14 | updateGraphics(node, tree);
15 | },
16 |
17 | killGraphics = function (node) {
18 | node.obj.kill();
19 | },
20 |
21 | onChildrenInit = function (node, tree, treeMethods) {
22 | treeMethods.cancelTransactionNofitication(node.id);
23 | draw(node, tree);
24 | },
25 |
26 | redraw = function (node, tree) {
27 | node.obj.clear();
28 | draw(node, tree);
29 | },
30 |
31 | draw = function (node, tree) {
32 | for (var i = 0; i < node.children.length; i++) {
33 | var child = tree.nodes[node.children[i]];
34 | if (itemTypes[child.tag]) {
35 | itemTypes[child.tag].draw(child, tree, node.obj, 0, 0);
36 | }
37 | }
38 | };
39 |
40 | module.exports = {
41 | init: initGraphics,
42 | onChildrenInit: onChildrenInit,
43 | kill: killGraphics,
44 | update: updateGraphics,
45 | notifyTransaction: redraw
46 | };
47 |
--------------------------------------------------------------------------------
/src/impl/types/graphics/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var extend = require('extend');
4 |
5 | module.exports = extend(
6 | {
7 | graphics: require('./graphics'),
8 | rendertexture: require('./rendertexture'),
9 | renderimage: require('./renderimage')
10 | },
11 | require('./renderers')
12 | );
13 |
--------------------------------------------------------------------------------
/src/impl/types/graphics/renderers.js:
--------------------------------------------------------------------------------
1 | var createGraphicsNode = require('./create-graphics-item'),
2 |
3 | renderers = {
4 | arc: function (node, tree, graphics, x0, y0) {
5 | graphics.arc(
6 | x0 + (node.props.x || 0),
7 | y0 + (node.props.y || 0),
8 | node.props.radius || 0,
9 | node.props.startAngle || 0,
10 | node.props.endAngle || 2 * Math.PI,
11 | node.props.anticlockwise || false,
12 | node.props.segments
13 | );
14 | },
15 | circle: function (node, tree, graphics, x0, y0) {
16 | graphics.drawCircle(
17 | x0 + (node.props.x || 0),
18 | y0 + (node.props.y || 0),
19 | node.props.diameter || 0
20 | );
21 | },
22 | ellipse: function (node, tree, graphics, x0, y0) {
23 | graphics.drawEllipse(
24 | x0 + (node.props.x || 0),
25 | y0 + (node.props.y || 0),
26 | node.props.width || 0,
27 | node.props.height || 0
28 | );
29 | },
30 | rect: function (node, tree, graphics, x0, y0) {
31 | graphics.drawRect(
32 | x0 + (node.props.x || 0),
33 | y0 + (node.props.y || 0),
34 | node.props.width || 0,
35 | node.props.height || 0
36 | );
37 | },
38 | roundedrect: function (node, tree, graphics, x0, y0) {
39 | graphics.drawRoundedRect(
40 | x0 + (node.props.x || 0),
41 | y0 + (node.props.y || 0),
42 | node.props.width || 0,
43 | node.props.height || 0,
44 | node.props.radius || 0
45 | );
46 | },
47 | line: function (node, tree, graphics, x0, y0) {
48 | graphics.moveTo(
49 | x0 + (node.props.x1 || 0),
50 | y0 + (node.props.y1 || 0)
51 | );
52 | graphics.lineTo(
53 | x0 + (node.props.x2 || 0),
54 | y0 + (node.props.y2 || 0)
55 | );
56 | },
57 | lineto: function (node, tree, graphics, x0, y0) {
58 | graphics.lineTo(
59 | x0 + (node.props.x || 0),
60 | y0 + (node.props.y || 0)
61 | );
62 | },
63 | quadraticcurveto: function (node, tree, graphics, x0, y0) {
64 | graphics.quadraticCurveTo(
65 | node.props.cpx + x0,
66 | node.props.cpy + y0,
67 | node.props.x + x0,
68 | node.props.y + y0
69 | );
70 | },
71 | beziercurveto: function (node, tree, graphics, x0, y0) {
72 | graphics.quadraticCurveTo(
73 | node.props.cpx + x0,
74 | node.props.cpy + y0,
75 | node.props.cpx2 + x0,
76 | node.props.cpy2 + y0,
77 | node.props.x + x0,
78 | node.props.y + y0
79 | );
80 | },
81 | shape: function (node, tree, graphics, x0, y0) {
82 | var sx0 = x0 + (node.props.x || 0),
83 | sy0 = y0 + (node.props.y || 0);
84 |
85 | if (node.props.s) {
86 | var parts = node.props.s.replace(/\s/g, '').match(/([a-z][0-9,]+)/g);
87 | for (var i = 0; i < parts.length; i++) {
88 | var part = parts[i],
89 | command = part.charAt(0),
90 | v = part.match(/[0-9]+/g).map(function (v) {
91 | return parseFloat(v);
92 | });
93 |
94 | switch (command) {
95 | case 'a':
96 | graphics.arc(v[0] + sx0, v[1] + sy0, v[2], v[3], v[4], !!v[5], v[6]);
97 | break;
98 | case 'l':
99 | graphics.lineTo(v[0] + sx0, v[1] + sy0);
100 | break;
101 | case 'c':
102 | graphics.drawCircle(v[0] + sx0, v[1] + sy0, v[2]);
103 | break;
104 | case 'e':
105 | graphics.drawEllipse(v[0] + sx0, v[1] + sy0, v[2], v[3]);
106 | break;
107 | case 'r':
108 | graphics.drawRect(v[0] + sx0, v[1] + sy0, v[2], v[3]);
109 | break;
110 | case 'd':
111 | graphics.drawRoundedRect(v[0] + sx0, v[1] + sy0, v[2], v[3], v[4]);
112 | break;
113 | case 'm':
114 | graphics.moveTo(v[0] + sx0, v[1] + sy0);
115 | break;
116 | case 'b':
117 | graphics.bezierCurveTo(v[0] + sx0, v[1] + sy0, v[2] + sx0, v[3] + sy0, v[4] + sx0, v[5] + sy0);
118 | break;
119 | case 'q':
120 | graphics.quadraticCurveTo(v[0] + sx0, v[1] + sy0, v[2] + sx0, v[3] + sy0);
121 | break;
122 | }
123 | }
124 | }
125 |
126 | for (i = 0; i < node.children.length; i++) {
127 | var child = tree.nodes[node.children[i]];
128 | if (renderers[child.tag]) {
129 | renderers[child.tag](child, tree, graphics, sx0, sy0);
130 | }
131 | }
132 | }
133 | };
134 |
135 | module.exports = Object.keys(renderers).reduce(function (acc, type) {
136 | acc[type] = createGraphicsNode(renderers[type]);
137 | return acc;
138 | }, {});
139 |
--------------------------------------------------------------------------------
/src/impl/types/graphics/renderimage.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var treeUtils = require('../../tree-utils'),
4 | graphicsPropertes = require('../../properties/base/Phaser.Graphics'),
5 |
6 | updateGraphics = treeUtils.genPropertyMapUpdate(graphicsPropertes),
7 |
8 | itemTypes = require('./renderers'),
9 | onTextureTypes = {
10 | 'texturetext': require('./texturetext')
11 | },
12 |
13 |
14 | initGraphics = function (node, tree) {
15 | node.obj = new Phaser.Graphics(treeUtils.game(tree), 0, 0);
16 | updateGraphics(node, null, tree);
17 | },
18 |
19 | killGraphics = function (node) {
20 | node.obj.kill();
21 | },
22 |
23 | onChildrenInit = function (node, tree) {
24 | draw(node, tree);
25 |
26 | var game = treeUtils.game(tree),
27 | texture = new Phaser.RenderTexture(game, node.obj.width, node.obj.height);
28 |
29 | texture.renderXY(node.obj, 0, 0);
30 | renderOnTexture(node, tree, texture);
31 |
32 | var url = texture.getBase64();
33 |
34 | texture.destroy();
35 | node.obj.destroy();
36 |
37 | if (node.props.frameWidth || node.props.frameHeight) {
38 | var w = node.props.frameWidth || texture.width,
39 | h = node.props.frameHeight || texture.height;
40 |
41 | node.obj = game.load.spritesheet(node.props.assetKey, url, w, h);
42 | } else {
43 | node.obj = game.load.image(node.props.assetKey, url);
44 | }
45 | },
46 |
47 | draw = function (node, tree) {
48 | for (var i = 0; i < node.children.length; i++) {
49 | var child = tree.nodes[node.children[i]];
50 | if (itemTypes[child.tag]) {
51 | itemTypes[child.tag].draw(child, tree, node.obj, 0, 0);
52 | }
53 | }
54 | },
55 |
56 | renderOnTexture = function (node, tree, texture) {
57 | for (var i = 0; i < node.children.length; i++) {
58 | var child = tree.nodes[node.children[i]];
59 | console.log(child.tag, onTextureTypes[child.tag]);
60 | if (onTextureTypes[child.tag]) {
61 | onTextureTypes[child.tag].draw(child, tree, texture);
62 | }
63 | }
64 | };
65 |
66 | module.exports = {
67 | init: initGraphics,
68 | onChildrenInit: onChildrenInit,
69 | kill: killGraphics,
70 | update: updateGraphics
71 | };
72 |
--------------------------------------------------------------------------------
/src/impl/types/graphics/rendertexture.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var treeUtils = require('../../tree-utils'),
4 | graphicsPropertes = require('../../properties/base/Phaser.Graphics'),
5 |
6 | updateGraphics = treeUtils.genPropertyMapUpdate(graphicsPropertes),
7 |
8 | itemTypes = require('./renderers'),
9 | onTextureTypes = {
10 | 'texturetext': require('./texturetext')
11 | },
12 |
13 | initGraphics = function (node, tree) {
14 | node.obj = new Phaser.Graphics(treeUtils.game(tree), 0, 0);
15 | updateGraphics(node, null, tree);
16 | },
17 |
18 | killGraphics = function (node) {
19 | node.obj.kill();
20 | },
21 |
22 | onChildrenInit = function (node, tree) {
23 | draw(node, tree);
24 |
25 | var game = treeUtils.game(tree),
26 | texture = new Phaser.RenderTexture(game, node.obj.width, node.obj.height);
27 |
28 | texture.renderXY(node.obj, 0, 0);
29 | node.obj.destroy();
30 |
31 | renderOnTexture(node, tree, texture);
32 |
33 | game.cache.addRenderTexture(node.props.assetKey, texture);
34 |
35 | },
36 |
37 | draw = function (node, tree) {
38 | for (var i = 0; i < node.children.length; i++) {
39 | var child = tree.nodes[node.children[i]];
40 | if (itemTypes[child.tag]) {
41 | itemTypes[child.tag].draw(child, tree, node.obj, 0, 0);
42 | }
43 | }
44 | },
45 |
46 | renderOnTexture = function (node, tree, texture) {
47 | for (var i = 0; i < node.children.length; i++) {
48 | var child = tree.nodes[node.children[i]];
49 | if (onTextureTypes[child.tag]) {
50 | onTextureTypes[child.tag].draw(child, tree, texture);
51 | }
52 | }
53 | };
54 |
55 | module.exports = {
56 | init: initGraphics,
57 | onChildrenInit: onChildrenInit,
58 | kill: killGraphics,
59 | update: updateGraphics
60 | };
61 |
62 |
--------------------------------------------------------------------------------
/src/impl/types/graphics/texturetext.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var treeUtils = require('../../tree-utils'),
4 |
5 | drawTextureText = function (node, tree, texture) {
6 | var props = node.props,
7 | text = new Phaser.Text(treeUtils.game(tree), 0, 0, props.text, props.style),
8 | x = (props.x || 0) +
9 | (props.align ? (props.align.indexOf('right') >= 0 ? -text.width :
10 | (props.align.indexOf('center') >= 0 ? -0.5 * text.width : 0)) : 0),
11 | y = (props.y || 0) +
12 | (props.align ? (props.align.indexOf('bottom') >= 0 ? -text.height:
13 | (props.align.indexOf('middle') >= 0 ? -0.5 * text.height : 0)) : 0);
14 |
15 | texture.renderXY(text, x, y);
16 | text.destroy();
17 | };
18 |
19 | module.exports = {
20 | draw: drawTextureText
21 | };
22 |
--------------------------------------------------------------------------------
/src/impl/types/group.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var treeUtils = require('../tree-utils'),
4 | groupPropertes = require('../properties/base/Phaser.Group'),
5 |
6 | updateGroup = treeUtils.genPropertyMapUpdate(groupPropertes),
7 |
8 | initGroup = function (node, tree) {
9 | node.obj = new Phaser.Group(treeUtils.game(tree));
10 | treeUtils.addDisplayObject(node, tree);
11 | updateGroup(node, null, tree);
12 | },
13 |
14 | killGroup = function (node) {
15 | node.obj.destroy();
16 | };
17 |
18 | module.exports = {
19 | init: initGroup,
20 | kill: killGroup,
21 | update: updateGroup
22 | };
23 |
--------------------------------------------------------------------------------
/src/impl/types/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var extend = require('extend');
4 |
5 | module.exports = extend(
6 | {
7 | game: require('./game'),
8 | state: require('./state'),
9 | sprite: require('./sprite'),
10 | group: require('./group'),
11 | animation: require('./animation'),
12 | collides: require('./collides'),
13 | overlaps: require('./overlaps'),
14 | text: require('./text'),
15 | button: require('./button')
16 | },
17 | require('./graphics'),
18 | require('./input')
19 | );
20 |
21 |
--------------------------------------------------------------------------------
/src/impl/types/input/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = {
4 | input: require('./input'),
5 | key: require('./key')
6 | };
7 |
--------------------------------------------------------------------------------
/src/impl/types/input/input.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var treeUtils = require('../../tree-utils'),
4 |
5 | defaultPointerNumber = 2,
6 | events = ["onDown", "onUp", "onTap", "onHold"],
7 |
8 | clearInput = function (node, tree) {
9 | var context = treeUtils.stateNode(node, tree).context;
10 | delete context.input;
11 | },
12 |
13 | initInput = function (node, tree) {
14 | var stateNode = treeUtils.stateNode(node, tree);
15 | if (!stateNode.context.input) {
16 | var phaserInput = stateNode.obj.input,
17 | pointerCount = node.props.pointers || defaultPointerNumber,
18 | input = {
19 | mousePointer: phaserInput.mousePointer,
20 | activePointer: phaserInput.activePointer,
21 | pointers: []
22 | };
23 |
24 | node.obj = {
25 | input: input
26 | };
27 |
28 | stateNode.context.input = input;
29 |
30 | for (var i = 0; i < pointerCount; i++) {
31 | if (i >= defaultPointerNumber) {
32 | phaserInput.addPointer();
33 | }
34 | input.pointers[i] = phaserInput['pointer' + (i + 1)];
35 | }
36 |
37 | events.forEach(function (event) {
38 | var listener = node.props[event];
39 | if (listener) {
40 | phaserInput[event].add(function (pointer) {
41 | listener(pointer, stateNode.context);
42 | });
43 | }
44 | });
45 |
46 | if (node.props.cursors) {
47 | input.cursors = phaserInput.keyboard.createCursorKeys();
48 | }
49 |
50 | if (node.props.keys) {
51 | input.keys = Object.keys(node.props.keys).reduce(function (acc, key) {
52 | acc[key] = phaserInput.keyboard.addKey(node.props.keys[key]);
53 | }, {});
54 | }
55 |
56 | if (node.props.onInput) {
57 | stateNode.addUpdateListener(node.props.onInput);
58 | }
59 | }
60 | };
61 |
62 | module.exports = {
63 | init: initInput,
64 | clear: clearInput,
65 | kill: null,
66 | update: null
67 | };
68 |
--------------------------------------------------------------------------------
/src/impl/types/input/key.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var treeUtils= require('../../tree-utils'),
4 | keyPropertes = require('../../properties/custom/key'),
5 |
6 | updateKey = treeUtils.genPropertyMapUpdate(keyPropertes),
7 |
8 | events = ["onDown", "onUp", "onHoldCallback"],
9 |
10 | initKey = function (node, tree) {
11 | var stateNode = treeUtils.stateNode(node, tree);
12 | if (stateNode.context.input && node.props.keyName && node.props.keyCode) {
13 | var phaserInput = stateNode.obj.input,
14 | input = stateNode.context.input,
15 | key = phaserInput.keyboard.addKey(node.props.keyCode);
16 |
17 | if (!input.keys) {
18 | input.keys = {};
19 | }
20 |
21 | node.obj = key;
22 | input.keys[node.props.keyName] = node.obj;
23 |
24 | events.forEach(function (event) {
25 | var listener = node.props[event];
26 | if (listener) {
27 | key[event].add(function (key) {
28 | listener(key, stateNode.context);
29 | });
30 | }
31 | });
32 | }
33 | },
34 |
35 | killKey = function (node, tree) {
36 | if (node.obj) {
37 | var stateNode = treeUtils.stateNode(node, tree);
38 |
39 | stateNode.obj.keyboard.removeKey(node.obj.keyCode);
40 | delete stateNode.context.input[node.props.keyName];
41 | }
42 | };
43 |
44 | module.exports = {
45 | init: initKey,
46 | kill: killKey,
47 | update: updateKey
48 | };
49 |
--------------------------------------------------------------------------------
/src/impl/types/overlaps.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var treeUtils = require('../tree-utils'),
4 | systemName = require('../physic-system-name'),
5 |
6 | initOverlaps = function (node, tree) {
7 | var a = tree.nodes[node.parent],
8 | b = tree.byname[node.props.with],
9 | name = systemName(node.props.system),
10 | stateNode = treeUtils.stateNode(node, tree),
11 | onOverlap = node.props.onOverlap;
12 |
13 | node.obj = {
14 | a: a,
15 | b: b,
16 | onUpdate: function (context) {
17 | context.game.physics[name].overlap(a.obj, b.obj, function (overlappingA, overlappingB) {
18 | onOverlap(tree.nodes[overlappingA.rnodeid], tree.nodes[overlappingB.rnodeid], context, a, b);
19 | });
20 | }
21 | };
22 |
23 | stateNode.addUpdateListener(node.obj.onUpdate);
24 | },
25 |
26 | killOverlaps = function (nodes, node) {
27 | nodes.gameNode.removeUpdateListener(node.obj.onUpdate);
28 | };
29 |
30 | module.exports = {
31 | init: initOverlaps,
32 | kill: killOverlaps,
33 | update: null
34 | };
35 |
--------------------------------------------------------------------------------
/src/impl/types/sprite.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var treeUtils = require('../tree-utils'),
4 | spritePropertes = require('../properties/base/Phaser.Sprite'),
5 |
6 | updateSprite = treeUtils.genPropertyMapUpdate(spritePropertes),
7 |
8 | initSprite = function (node, tree) {
9 | var props = node.props;
10 | node.obj = new Phaser.Sprite(treeUtils.game(tree), props.x, props.y, props.assetKey);
11 | treeUtils.addDisplayObject(node, tree);
12 | updateSprite(node, null, tree);
13 | },
14 |
15 | killSprite = function (node, tree) {
16 | node.obj.kill();
17 | };
18 |
19 | module.exports = {
20 | init: initSprite,
21 | kill: killSprite,
22 | update: updateSprite
23 | };
24 |
--------------------------------------------------------------------------------
/src/impl/types/state.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var treeUtils = require('../tree-utils'),
4 |
5 | onChildrenInit = function (node, tree, treeMethods) {
6 | node._updateMethods = [];
7 | node.addUpdateListener = function (listener) {
8 | node._updateMethods.push(listener);
9 | };
10 | node.removeUpdateListener = function (listener) {
11 | var index = node._updateMethods.indexOf(listener);
12 | if (index >= 0) {
13 | node._updateMethods.splice(index, 1);
14 | }
15 | };
16 |
17 | var props = node.props,
18 | stateImpl = {
19 | create: function () {
20 | if (node.props.hasOwnProperty('physics')) {
21 | node.obj.physics.startSystem(node.props.physics);
22 | }
23 |
24 | treeMethods.clearChildren(node, tree);
25 | treeMethods.initChildren(node, tree);
26 | },
27 | update: function () {
28 | for (var i = 0; i < node._updateMethods.length; i++) {
29 | node._updateMethods[i](context);
30 | }
31 | }
32 | },
33 | game = treeUtils.game(tree),
34 | state = game.state.add(props.name, stateImpl),
35 | context = {
36 | game: game,
37 | state: state,
38 | nodes: tree.byname
39 | };
40 |
41 | node.obj = state;
42 | node.context = context;
43 | };
44 |
45 | module.exports = {
46 | init: null,
47 | onChildrenInit: onChildrenInit,
48 | kill: null,
49 | deferredInit: true
50 | };
51 |
--------------------------------------------------------------------------------
/src/impl/types/text.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var treeUtils = require('../tree-utils'),
4 | textPropertes = require('../properties/base/Phaser.Text'),
5 |
6 | updateText = treeUtils.genPropertyMapUpdate(textPropertes),
7 |
8 | initText = function (node, tree) {
9 | var props = node.props,
10 | text = new Phaser.Text(treeUtils.game(tree), 0, 0, props.text, props.style),
11 | container = treeUtils.parent(node, tree).obj,
12 | x = props.x || (props.align && (container.width - text.width) * (props.align.indexOf('right') >= 0 ? 1 :
13 | (props.align.indexOf('center') >= 0 ? .5 : 0))) || 0,
14 | y = props.y || (props.align && (container.height - text.height) * (props.align.indexOf('bottom') >= 0 ? 1 :
15 | (props.align.indexOf('middle') >= 0 ? .5 : 0))) || 0;
16 |
17 | text.x = x;
18 | text.y = y;
19 | node.obj = text;
20 | treeUtils.addDisplayObject(node, tree);
21 | },
22 |
23 | killText = function (node, tree) {
24 | node.obj.kill();
25 | };
26 |
27 | module.exports = {
28 | init: initText,
29 | kill: killText,
30 | update: updateText
31 | };
32 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 |
2 | var createReactAnything = require('react-anything');
3 | var phaserImplementation = require('./phaser-implementation');
4 |
5 | var ReactPhaser = createReactAnything(phaserImplementation);
6 | var React = ReactPhaser.React;
7 |
8 | React.render = ReactPhaser.render;
9 |
10 | module.exports = React;
11 |
--------------------------------------------------------------------------------
/src/native.js:
--------------------------------------------------------------------------------
1 |
2 | var createReactAnything = require('react-anything/src/native');
3 | var phaserImplementation = require('./phaser-implementation');
4 |
5 | var ReactPhaser = createReactAnything(phaserImplementation);
6 | var React = ReactPhaser.React;
7 |
8 | React.render = ReactPhaser.render;
9 |
10 | module.exports = React;
11 |
--------------------------------------------------------------------------------
/src/node-management/node-init-adapter.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2016-present, Eloy Villasclaras
3 | * All rights reserved.
4 | *
5 | * This source code is licensed under the BSD-style license found in the
6 | * LICENSE file in the root directory of this source tree.
7 | *
8 | */
9 | 'use strict';
10 |
11 | var create = function (nodeTypes) {
12 |
13 | var transactionListeners = [],
14 |
15 | parentInitd = function (node, tree) {
16 | var parent = tree.nodes[node.parent];
17 | return !parent || parent.initialized;
18 | },
19 |
20 | invoke = function (method, node, a, b, c) {
21 | var nodeType = nodeTypes[node.tag],
22 | f = nodeType && nodeType[method];
23 |
24 | if (f) {
25 | f(node, a, b, c);
26 | }
27 | },
28 |
29 | initImmediately = function (node) {
30 | var nodeType = nodeTypes[node.tag];
31 | return !nodeType || !nodeTypes[node.tag].deferredInit;
32 | },
33 |
34 | init = function (method, node, tree) {
35 | node.initialized = true;
36 | invoke(method, node, tree, methods);
37 | if (node.obj) {
38 | node.obj.rnodeid = node.id;
39 | }
40 | },
41 |
42 | initChildren = function (parent, tree, options) {
43 | var _options = options || {},
44 | include = _options.include,
45 | exclude = _options.exclude;
46 |
47 | for (var i = 0; i < parent.children.length; i++) {
48 | var child = tree.nodes[parent.children[i]],
49 | doInit = !child.initialized &&
50 | (!include || include.indexOf(child.tag) >= 0) &&
51 | (!exclude || exclude.indexOf(child.tag) < 0);
52 |
53 | if (doInit) {
54 | if (initImmediately(child)) {
55 | init('init', child, tree);
56 | methods.initChildren(child, tree);
57 | invoke('onChildrenInit', child, tree, methods);
58 | } else {
59 | init('onChildrenInit', child, tree, methods);
60 | }
61 | }
62 | }
63 | },
64 |
65 | clearChildren = function (parent, tree, options) {
66 | var _options = options || {},
67 | include = _options.include,
68 | exclude = _options.exclude;
69 |
70 | for (var i = 0; i < parent.children.length; i++) {
71 | var child = tree.nodes[parent.children[i]],
72 | shouldClear = child.initialized &&
73 | (!include || include.indexOf(child.tag) >= 0) &&
74 | (!exclude || exclude.indexOf(child.tag) < 0);
75 |
76 | if (shouldClear) {
77 | invoke('clear', tree, methods);
78 | child.initialized = false;
79 | if (child.children.length > 0) {
80 | clearChildren(child, tree);
81 | }
82 | }
83 | }
84 | },
85 |
86 | requestTransactionNofitication = function (nodeid) {
87 | if (transactionListeners.indexOf(nodeid) < 0) {
88 | transactionListeners.push(nodeid);
89 | }
90 | },
91 |
92 | cancelTransactionNofitication = function (nodeid) {
93 | var index = transactionListeners.indexOf(nodeid);
94 | if (index >= 0) {
95 | transactionListeners.splice(index, 1);
96 | }
97 | },
98 |
99 | methods = {
100 | initChildren: initChildren,
101 | clearChildren: clearChildren,
102 | requestTransactionNofitication: requestTransactionNofitication,
103 | cancelTransactionNofitication: cancelTransactionNofitication
104 | },
105 |
106 | impl = {
107 | components: {
108 | mount: function (node, tree) {
109 | if (initImmediately(node) && parentInitd(node, tree)) {
110 | init('init', node, tree);
111 | }
112 | },
113 | childrenMount: function (node, tree) {
114 | if (node.initialized) {
115 | invoke('onChildrenInit', node, tree, methods);
116 | } else if (parentInitd(node, tree)) {
117 | init('onChildrenInit', node, tree, methods);
118 | }
119 | },
120 | unmount: function (node, tree) {
121 | invoke('kill', node, tree);
122 | },
123 | update: function (node, prevProps, tree) {
124 | invoke('update', node, prevProps, tree, methods);
125 | }
126 | },
127 | transaction: {
128 | close: function (tree) {
129 | if (transactionListeners.length > 0) {
130 | for (var i = 0; i < transactionListeners.length; i++) {
131 | var node = tree.nodes[transactionListeners[i]];
132 | if (node) {
133 | invoke('notifyTransaction', node, tree);
134 | }
135 | }
136 | transactionListeners = [];
137 | }
138 | }
139 | }
140 | };
141 |
142 | return impl;
143 | }
144 | ;
145 |
146 | module.exports = create;
147 |
--------------------------------------------------------------------------------
/src/node-management/node-tree-adapter.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2016-present, Eloy Villasclaras
3 | * All rights reserved.
4 | *
5 | * This source code is licensed under the BSD-style license found in the
6 | * LICENSE file in the root directory of this source tree.
7 | *
8 | */
9 | 'use strict';
10 |
11 | var create = function (impl) {
12 | var tree = {
13 | root: null,
14 | nodes: {},
15 | byname: {}
16 | },
17 | treeImpl = {
18 | components: {
19 | mount: function (id, tag, props, parent) {
20 | var node = {
21 | id: id,
22 | tag: tag,
23 | props: props,
24 | parent: parent && parent.id,
25 | children: [],
26 | initialized: false
27 | };
28 |
29 | if (parent) {
30 | parent.children.push(id);
31 | } else {
32 | tree.root = node;
33 | }
34 | tree.nodes[id] = node;
35 |
36 | if (props.name) {
37 | tree.byname[props.name] = node;
38 | }
39 |
40 | impl.components.mount(node, tree);
41 | return node;
42 | },
43 | childrenMount: function (node) {
44 | impl.components.childrenMount(node, tree);
45 | },
46 | unmount: function (node) {
47 | impl.components.unmount(node, tree);
48 | delete tree.nodes[node.id];
49 | if (node.parent) {
50 | var parent = tree.nodes[node.parent];
51 | parent.children.splice(parent.children.indexOf(node.id), 1);
52 | }
53 | delete tree.nodes[node.id];
54 | if (node === tree.root) {
55 | tree.root = null;
56 | }
57 |
58 | if (node.props.name) {
59 | delete tree.byname[node.props.name];
60 | }
61 | },
62 | update: function (node, nextProps, prevProps) {
63 | node.props = nextProps;
64 | impl.components.update(node, prevProps, tree);
65 | if (nextProps.name !== prevProps.name) {
66 | if (prevProps.name) {
67 | delete tree.byname[prevProps.name];
68 | }
69 | if (nextProps.name) {
70 | tree.byname[nextProps.name] = node;
71 | }
72 | }
73 | }
74 | },
75 | transaction: {
76 | initialize: impl.transaction.initialize && function () {
77 | impl.transaction.initialize(tree);
78 | },
79 | close: impl.transaction.close && function () {
80 | impl.transaction.close(tree);
81 | }
82 | }
83 | };
84 |
85 | return treeImpl;
86 | };
87 |
88 | module.exports = create;
89 |
--------------------------------------------------------------------------------
/src/phaser-implementation.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2016-present, Eloy Villasclaras
3 | * All rights reserved.
4 | *
5 | * This source code is licensed under the BSD-style license found in the
6 | * LICENSE file in the root directory of this source tree.
7 | *
8 | */
9 | 'use strict';
10 |
11 | var createTreeImpl = require('./node-management/node-tree-adapter'),
12 | createInitAdapter = require('./node-management/node-init-adapter'),
13 | nodeTypes = require('./impl/types');
14 |
15 | module.exports = createTreeImpl(createInitAdapter(nodeTypes));
16 |
--------------------------------------------------------------------------------
/tests/node-management/node-init-adapter-test.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | var chai = require("chai");
3 | var sinon = require("sinon");
4 | var sinonChai = require("sinon-chai");
5 | var expect = chai.expect;
6 | chai.use(sinonChai);
7 |
8 | var createInitmpl = require('../../src/node-management/node-init-adapter');
9 | var createTreeImpl = require('../../src/node-management/node-tree-adapter');
10 |
11 | describe('node init adapter', function () {
12 | var nodeTypes, impl, treeImpl;
13 |
14 | beforeEach(function () {
15 | nodeTypes = {
16 | a: {
17 | init: sinon.spy(),
18 | onChildrenInit: sinon.spy()
19 | },
20 | b: {
21 | init: sinon.spy(),
22 | onChildrenInit: sinon.spy()
23 | },
24 | c: {
25 | init: sinon.spy(),
26 | onChildrenInit: sinon.spy()
27 | }
28 | };
29 | impl = createInitmpl(nodeTypes);
30 | treeImpl = createTreeImpl(impl);
31 | });
32 |
33 |
34 | it('should invoke node init by default', function () {
35 | var a = treeImpl.components.mount(1, 'a', {}, null);
36 | expect(nodeTypes.a.init).to.have.been.calledOnce;
37 | expect(nodeTypes.a.init).to.have.been.calledWith(a);
38 | });
39 |
40 | it('should invoke node init on children by default', function () {
41 | var a = treeImpl.components.mount(1, 'a', {}, null),
42 | b = treeImpl.components.mount(2, 'a', {}, a);
43 |
44 | expect(nodeTypes.a.init).to.have.been.calledTwice;
45 | expect(nodeTypes.a.init.getCall(0)).to.have.been.calledWith(a);
46 | expect(nodeTypes.a.init.getCall(1)).to.have.been.calledWith(b);
47 | });
48 |
49 | it('should invoke mount children', function () {
50 | var a = treeImpl.components.mount(1, 'a', {}, null),
51 | b = treeImpl.components.mount(2, 'a', {}, a);
52 |
53 | treeImpl.components.childrenMount(a);
54 |
55 | expect(nodeTypes.a.onChildrenInit).to.have.been.calledOnce;
56 | expect(nodeTypes.a.onChildrenInit.getCall(0)).to.have.been.calledWith(a);
57 | });
58 |
59 | it('should not init children for deferred parents', function () {
60 | nodeTypes.a.deferredInit = true;
61 |
62 | var a = treeImpl.components.mount(1, 'a', {}, null),
63 | b = treeImpl.components.mount(2, 'b', {}, a);
64 | treeImpl.components.childrenMount(a);
65 |
66 | expect(nodeTypes.a.init).not.to.have.been.calledOnce;
67 | expect(nodeTypes.a.onChildrenInit).to.have.been.calledOnce;
68 | expect(nodeTypes.b.init).not.to.have.been.called;
69 | });
70 |
71 | it('should not init children for deferred parents', function () {
72 | nodeTypes.a.deferredInit = true;
73 |
74 | var a = treeImpl.components.mount(1, 'a', {}, null),
75 | b = treeImpl.components.mount(2, 'b', {}, a);
76 | treeImpl.components.childrenMount(a);
77 |
78 | expect(nodeTypes.a.init).not.to.have.been.calledOnce;
79 | expect(nodeTypes.a.onChildrenInit).to.have.been.calledOnce;
80 | expect(nodeTypes.b.init).not.to.have.been.called;
81 |
82 | expect(a.initialized).to.equal(true);
83 | expect(b.initialized).to.equal(false);
84 | });
85 |
86 |
87 | it('should init children for deferred parents on request', function () {
88 | nodeTypes.a.deferredInit = true;
89 | nodeTypes.a.onChildrenInit = sinon.spy(function (node, tree, implMethods) {
90 | implMethods.initChildren(node, tree);
91 | });
92 |
93 | var a = treeImpl.components.mount(1, 'a', {}, null),
94 | b = treeImpl.components.mount(2, 'b', {}, a);
95 | treeImpl.components.childrenMount(a);
96 |
97 | expect(nodeTypes.a.init).not.to.have.been.calledOnce;
98 | expect(nodeTypes.a.onChildrenInit).to.have.been.calledOnce;
99 | expect(nodeTypes.b.init).to.have.been.calledOnce;
100 | });
101 |
102 | it('should not init nested children by default, when deferred', function () {
103 | nodeTypes.a.deferredInit = true;
104 | nodeTypes.a.onChildrenInit = sinon.spy(function (node, tree, implMethods) {
105 | implMethods.initChildren(node, tree);
106 | });
107 |
108 | nodeTypes.b.deferredInit = true;
109 | nodeTypes.b.onChildrenInit = sinon.spy(function (node, tree, implMethods) {
110 | });
111 |
112 | var a1 = treeImpl.components.mount(1, 'a', {}, null),
113 | a2 = treeImpl.components.mount(2, 'b', {}, a1),
114 | b = treeImpl.components.mount(3, 'c', {}, a2);
115 | treeImpl.components.childrenMount(a1);
116 |
117 | expect(nodeTypes.a.init).not.to.have.been.called;
118 | expect(nodeTypes.a.onChildrenInit).to.have.been.calledOnce;
119 | expect(nodeTypes.b.init).not.to.have.been.called;
120 | expect(nodeTypes.b.onChildrenInit).to.have.been.calledOnce;
121 | expect(nodeTypes.b.init).not.to.have.been.calledOnce;
122 | });
123 |
124 | it('should filter children on deferred init children');
125 |
126 | });
127 |
--------------------------------------------------------------------------------
/tests/node-management/node-tree-adapter-test.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | var chai = require("chai");
3 | var sinon = require("sinon");
4 | var sinonChai = require("sinon-chai");
5 | var expect = chai.expect;
6 | chai.use(sinonChai);
7 |
8 | var createNativeImpl = require('../../src/node-management/node-tree-adapter');
9 |
10 | describe('node tree adapter', function () {
11 |
12 | var nodes, nativeImpl;
13 |
14 | beforeEach(function () {
15 | nodes = {
16 | components: {
17 | mount: sinon.spy(),
18 | childrenMount: sinon.spy(),
19 | update: sinon.spy(),
20 | unmount: sinon.spy()
21 | },
22 | transaction: {}
23 | };
24 | nativeImpl = createNativeImpl(nodes);
25 | });
26 |
27 | it('should mount root node', function () {
28 | var node = nativeImpl.components.mount(1, 'a', {}, null);
29 |
30 | expect(node).to.deep.eql({
31 | id: 1,
32 | tag: 'a',
33 | props: {},
34 | parent: null,
35 | children: [],
36 | initialized: false
37 | });
38 |
39 | expect(nodes.components.mount).to.have.been.calledOnce;
40 | expect(nodes.components.mount).to.have.been.calledWith({
41 | id: 1,
42 | tag: 'a',
43 | props: {},
44 | parent: null,
45 | children: [],
46 | initialized: false
47 | });
48 | });
49 |
50 | it('should mount child root node', function () {
51 | var a = nativeImpl.components.mount(1, 'a', {}, null),
52 | b = nativeImpl.components.mount(2, 'b', {}, a);
53 |
54 | expect(a).to.deep.eql({
55 | id: 1,
56 | tag: 'a',
57 | props: {},
58 | parent: null,
59 | children: [2],
60 | initialized: false
61 | });
62 |
63 | expect(b).to.deep.eql({
64 | id: 2,
65 | tag: 'b',
66 | props: {},
67 | parent: 1,
68 | children: [],
69 | initialized: false
70 | });
71 |
72 | expect(nodes.components.mount).to.have.been.calledTwice;
73 | expect(nodes.components.mount.getCall(0)).to.have.been.calledWith(a);
74 | expect(nodes.components.mount.getCall(1)).to.have.been.calledWith(b);
75 | });
76 |
77 | it('should notify after children mounted', function () {
78 | var a = nativeImpl.components.mount(1, 'a', {}, null),
79 | b = nativeImpl.components.mount(2, 'b', {}, a);
80 |
81 | nativeImpl.components.childrenMount(a);
82 |
83 |
84 | expect(nodes.components.childrenMount).to.have.been.calledOnce;
85 | expect(nodes.components.childrenMount).to.have.been.calledWith(a);
86 | });
87 |
88 | it('should notify node update', function () {
89 | var a = nativeImpl.components.mount(1, 'a', {p: 0}, null);
90 | nativeImpl.components.update(a, {p: 1}, a.props);
91 |
92 | expect(nodes.components.update).to.have.been.calledOnce;
93 | expect(nodes.components.update).to.have.been.calledWith(a, {p: 0});
94 | expect(a.props).to.eql({p: 1});
95 | });
96 |
97 | it('should unmount node from tree', function () {
98 | var a = nativeImpl.components.mount(1, 'a', {}, null),
99 | b = nativeImpl.components.mount(2, 'b', {}, a);
100 |
101 | expect(a.children).to.eql([2]);
102 |
103 | nativeImpl.components.unmount(b);
104 |
105 | expect(a.children).to.eql([]);
106 |
107 | expect(nodes.components.unmount).to.have.been.calledOnce;
108 | expect(nodes.components.unmount).to.have.been.calledWith(b);
109 | });
110 | });
111 |
--------------------------------------------------------------------------------