├── src
├── styles
│ ├── main.less
│ ├── forms.less
│ └── panel.less
├── hbs
│ └── scene
│ │ ├── panel.hbs
│ │ ├── tree.hbs
│ │ └── details.hbs
├── panels
│ ├── Panel.js
│ ├── Performance.js
│ └── Scene.js
├── util
│ ├── ui.js
│ └── Graph.js
└── index.js
├── .gitignore
├── .editorconfig
├── LICENSE
├── package.json
├── README.md
├── gulpfile.js
├── CONTRIBUTING.md
├── .jshintrc
└── dist
└── phaser-debug.js
/src/styles/main.less:
--------------------------------------------------------------------------------
1 | @import "panel.less";
2 | @import "forms.less";
3 |
--------------------------------------------------------------------------------
/src/hbs/scene/panel.hbs:
--------------------------------------------------------------------------------
1 |
3 |
4 | refresh
5 |
6 |
7 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # sublime text 2 files
2 | *.sublime*
3 | *.*~*.TMP
4 |
5 | # temp files
6 | .DS_Store
7 | Thumbs.db
8 | Desktop.ini
9 | npm-debug.log
10 |
11 | # vim swap files
12 | *.sw*
13 |
14 | # emacs temp files
15 | *~
16 | \#*#
17 |
18 | # project ignores
19 | !.gitkeep
20 | *__temp
21 | node_modules/*
22 | build/*
23 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # Unix-style newlines with a newline ending every file
2 | [*]
3 | end_of_line = lf
4 | insert_final_newline = true
5 | trim_trailing_whitespace = true
6 | indent_style = space
7 | indent_size = 4
8 |
9 | [*.md]
10 | trim_trailing_whitespace = false
11 |
12 | [{package.json,bower.json,.travis.yml}]
13 | indent_size = 2
14 |
--------------------------------------------------------------------------------
/src/hbs/scene/tree.hbs:
--------------------------------------------------------------------------------
1 | {{listItemOpen}}
2 | {{typeString}}
3 |
4 | {{#if name}}
5 | ({{name}})
6 | {{/if}}
7 |
8 | {{#if children}}
9 |
10 | {{#each children}}
11 | {{> sceneTree}}
12 | {{/each}}
13 |
14 | {{/if}}
15 |
16 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License
2 |
3 | Copyright (c) 2014 Chad Engler
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
22 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "phaser-debug",
3 | "version": "1.1.9",
4 | "description": "Simple debug module for phaser",
5 | "author": "Chad Engler ",
6 | "license": "MIT",
7 | "homepage": "https://github.com/englercj/phaser-debug",
8 | "repository": {
9 | "type": "git",
10 | "url": "https://github.com/englercj/phaser-debug.git"
11 | },
12 | "bugs": {
13 | "url": "https://github.com/englercj/phaser-debug/issues"
14 | },
15 | "keywords": [
16 | "phaser",
17 | "debug",
18 | "html5",
19 | "game",
20 | "engine"
21 | ],
22 | "dependencies": {
23 | "handlebars": "^2.0.0",
24 | "node-lessify": "^0.0.5",
25 | "hbsfy": "^2.1.0"
26 | },
27 | "devDependencies": {
28 | "browserify": "^5.11.1",
29 | "event-stream": "^3.1.7",
30 | "gulp": "^3.8.8",
31 | "gulp-bump": "^0.1.11",
32 | "gulp-git": "^0.5.3",
33 | "gulp-jshint": "^1.8.4",
34 | "gulp-util": "^3.0.1",
35 | "jshint-summary": "^0.4.0",
36 | "vinyl-source-stream": "^0.1.1",
37 | "watchify": "^1.0.2"
38 | },
39 | "main": "./dist/phaser-debug.js",
40 | "browser": "./src/index.js",
41 | "browserify": {
42 | "transform": [
43 | "hbsfy",
44 | "node-lessify"
45 | ],
46 | "transform-options": {
47 | "node-lessify": "textMode"
48 | }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Phaser Debug
2 |
3 | Simple debug module for the [Phaser][0] game framework.
4 |
5 | ![Screenshot][1]
6 |
7 | [0]: https://github.com/photonstorm/phaser
8 | [1]: https://dl.dropboxusercontent.com/u/1810371/pics/phaser-debug.png
9 |
10 | ## Usage
11 |
12 | Simply download the `phaser-debug.js` script from the [latest release][10] and include it on your page
13 | after including Phaser:
14 |
15 | ```html
16 |
17 |
18 | ```
19 |
20 | After adding the script to the page you can activate it by enabling the plugin:
21 |
22 | ```js
23 | game.add.plugin(Phaser.Plugin.Debug);
24 | ```
25 |
26 | [10]: https://github.com/englercj/phaser-debug/releases
27 |
28 | ## TypeScript Usage
29 | Add the `phaser-debug.js` script to the page (see the first part of the usage section above).
30 |
31 | In your `phaser.d.ts` file, inside `module Plugin` add:
32 | ```typescript
33 | class Debug extends Phaser.Plugin {
34 |
35 | constructor(game: Phaser.Game, parent: Phaser.PluginManager);
36 | }
37 | ```
38 | Activate the plugin:
39 |
40 | ```typescript
41 | this.game.add.plugin(new Phaser.Plugin.Debug(this.game, this.game.plugins));
42 | ```
43 |
44 | ## Browser Support
45 |
46 | Currently this module supports the following browsers:
47 |
48 | - Desktop
49 | * Firefox 30+
50 | * Chrome 27+
51 | * Safari 5.1+
52 | * Opera 23+
53 |
--------------------------------------------------------------------------------
/src/panels/Panel.js:
--------------------------------------------------------------------------------
1 | var ui = require('../util/ui');
2 |
3 | function Panel(game, parent) {
4 | this.game = game;
5 | this.parent = parent;
6 |
7 | this.name = '';
8 | this.title = '';
9 | this.active = false;
10 |
11 | this._panel = null;
12 | }
13 |
14 | Panel.prototype.constructor = Panel;
15 |
16 | module.exports = Panel;
17 |
18 | //builds the html for a panel
19 | Panel.prototype.createPanelElement = function () {
20 | var elm = this._panel = document.createElement('div');
21 | ui.addClass(elm, 'pdebug-panel ' + this.name);
22 |
23 | return elm;
24 | };
25 |
26 | //builds the html for this panels menu item
27 | Panel.prototype.createMenuElement = function () {
28 | var elm = this._menuItem = document.createElement('a');
29 |
30 | elm.href = '#' + this.name;
31 |
32 | ui.addClass(elm, 'pdebug-menu-item ' + this.name);
33 | ui.setText(elm, this.title);
34 |
35 | return elm;
36 | };
37 |
38 | Panel.prototype.toggle = function () {
39 | if (this.active) {
40 | this.hide();
41 | } else {
42 | this.show();
43 | }
44 | };
45 |
46 | Panel.prototype.show = function () {
47 | this.active = true;
48 | ui.setStyle(this._panel, 'display', 'block');
49 | };
50 |
51 | Panel.prototype.hide = function () {
52 | this.active = false;
53 | ui.setStyle(this._panel, 'display', 'none');
54 | };
55 |
56 | Panel.prototype.destroy = function () {
57 | this.game = null;
58 | this.parent = null;
59 |
60 | this.name = null;
61 | this.title = null;
62 | this.active = null;
63 |
64 | this._panel = null;
65 | };
66 |
--------------------------------------------------------------------------------
/src/hbs/scene/details.hbs:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{name}}
5 |
6 |
7 |
8 | {{typeString}}
9 |
10 |
11 |
12 | {{visible}}
13 |
14 |
15 |
16 | {{rotation}}
17 |
18 |
19 |
20 | {{position.x}} x {{position.y}}
21 |
22 |
23 |
24 | {{scale.x}} x {{scale.y}}
25 |
26 |
27 |
28 | {{alpha}}
29 |
30 |
31 |
32 |
33 |
34 | {{worldVisible}}
35 |
36 |
37 |
38 | {{worldRotation}}
39 |
40 |
41 |
42 | {{worldPosition.x}} x {{worldPosition.y}}
43 |
44 |
45 |
46 | {{worldScale.x}} x {{worldScale.y}}
47 |
48 |
49 |
50 | {{worldAlpha}}
51 |
52 |
53 |
54 |
55 | {{#if children}}
56 |
57 | {{children.length}}
58 |
59 | {{/if}}
60 |
61 | {{#if texture}}
62 |
63 | {{#if texture.baseTexture.source.src}}
64 | {{texture.baseTexture.source.src}}
65 | {{else}}
66 | {{texture.baseTexture.source}}
67 | {{/if}}
68 |
69 | {{/if}}
70 |
--------------------------------------------------------------------------------
/src/panels/Performance.js:
--------------------------------------------------------------------------------
1 | // TODO: Not measuring render time!!
2 |
3 | var Panel = require('./Panel'),
4 | Graph = require('../util/Graph');
5 |
6 | function Performance(game, parent) {
7 | Panel.call(this, game, parent);
8 |
9 | this.name = 'performance';
10 | this.title = 'Performance';
11 | this.eventQueue = [];
12 |
13 | this.graph = null;
14 |
15 | this.colorPalettes = {
16 | _default: [
17 | // Colors from: https://github.com/highslide-software/highcharts.com/blob/master/js/themes/grid.js
18 | '#058DC7', '#50B432', '#ED561B', '#DDDF00',
19 | '#24CBE5', '#64E572', '#FF9655', '#FFF263',
20 | '#6AF9C4',
21 | // Colors from: https://github.com/highslide-software/highcharts.com/blob/master/js/themes/dark-unica.js
22 | '#2b908f', '#90ee7e', '#f45b5b', '#7798BF',
23 | '#aaeeee', '#ff0066', '#eeaaee',
24 | '#55BF3B', '#DF5353', '#7798BF', '#aaeeee'
25 | ]
26 | };
27 | }
28 |
29 | Performance.prototype = Object.create(Panel.prototype);
30 | Performance.prototype.constructor = Performance;
31 |
32 | module.exports = Performance;
33 |
34 | Performance.prototype.createPanelElement = function () {
35 | var elm = Panel.prototype.createPanelElement.call(this);
36 |
37 | this.graph = new Graph(elm, window.innerWidth - 20, 256, this.colorPalettes._default);
38 |
39 | return elm;
40 | };
41 |
42 | Performance.prototype.update = function () {
43 | this.graph.addData(this.parent.timings, this.eventQueue.shift());
44 | };
45 |
46 | Performance.prototype.mark = function (label) {
47 | this.eventQueue.push(label);
48 | };
49 |
50 | Performance.prototype.destroy = function () {
51 | Panel.prototype.destroy.call(this);
52 |
53 | this.graph.destroy();
54 |
55 | this.eventQueue = null;
56 | this.graph = null;
57 | this.colorPalettes = null;
58 | };
59 |
--------------------------------------------------------------------------------
/gulpfile.js:
--------------------------------------------------------------------------------
1 | var gulp = require('gulp'),
2 | path = require('path'),
3 | git = require('gulp-git'),
4 | bump = require('gulp-bump'),
5 | gutil = require('gulp-util'),
6 | jshint = require('gulp-jshint'),
7 |
8 | es = require('event-stream'),
9 | source = require('vinyl-source-stream'),
10 | watchify = require('watchify'),
11 | browserify = require('browserify'),
12 |
13 | index = './src/index.js',
14 | outdir = './build',
15 | bundle = 'Phaser.Plugin.Debug',
16 | outfile = 'phaser-debug.js',
17 | ver = {
18 | major: 0,
19 | minor: 1,
20 | patch: 2
21 | },
22 | pkg = require('./package.json'),
23 | version = pkg.version.split('.');
24 |
25 | function rebundle(file) {
26 | if (file) {
27 | gutil.log('Rebundling,', path.basename(file[0]), 'has changes.');
28 | }
29 |
30 | return this.bundle()
31 | // log errors if they happen
32 | .on('error', gutil.log.bind(gutil, 'Browserify Error'))
33 | .pipe(source(outfile))
34 | .pipe(gulp.dest(outdir));
35 | }
36 |
37 | function createBundler(args) {
38 | args = args || {};
39 | args.standalone = bundle;
40 |
41 | return browserify(index, args);
42 | }
43 |
44 | /*****
45 | * Dev task, incrementally rebuilds the output bundle as the the sources change
46 | *****/
47 | gulp.task('dev', function() {
48 | watchify.args.standalone = bundle;
49 | var bundler = watchify(createBundler(watchify.args));
50 |
51 | bundler.on('update', rebundle);
52 |
53 | return rebundle.call(bundler);
54 | });
55 |
56 | /*****
57 | * Build task, builds the output bundle
58 | *****/
59 | gulp.task('build', function () {
60 | return rebundle.call(createBundler());
61 | });
62 |
63 | /*****
64 | * JSHint task, lints the lib and test *.js files.
65 | *****/
66 | gulp.task('jshint', function () {
67 | return gulp.src([
68 | './src/**/*.js',
69 | 'gulpfile.js'
70 | ])
71 | .pipe(jshint())
72 | .pipe(jshint.reporter('jshint-summary'));
73 | });
74 |
75 | /*****
76 | * Base task
77 | *****/
78 | gulp.task('default', ['jshint', 'build']);
79 |
80 | /*****
81 | * Release task
82 | *****/
83 | gulp.task('release', ['jshint', 'build'], function (cb) {
84 | var up = process.argv[3] || 'patch';
85 |
86 | up = up.replace('--', '');
87 |
88 | if (Object.keys(ver).indexOf(up) === -1) {
89 | return cb(new Error('Please specify major, minor, or patch release.'));
90 | }
91 |
92 | version[ver[up]]++;
93 | for (var i = 0; i < 3; ++i) {
94 | if (i > ver[up]) {
95 | version[i] = 0;
96 | }
97 | }
98 |
99 | version = 'v' + version.join('.');
100 |
101 | return es.merge(
102 | gulp.src('./package.json')
103 | .pipe(bump({ type: up }))
104 | .pipe(gulp.dest('./')),
105 | gulp.src(outdir + '/' + outfile)
106 | .pipe(gulp.dest('./dist'))
107 | )
108 | .pipe(git.commit('release ' + version))
109 | .pipe(git.tag(version, version, function () {}));
110 | });
111 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # How to contribute
2 |
3 | Please read this short guide to contributing before performing pull requests or reporting issues. The purpose
4 | of this guide is to ensure the best experience for all involved and make development as smooth as possible.
5 |
6 |
7 | ## Reporting issues
8 |
9 | To report a bug, request a feature, or even ask a question, make use of the [GitHub Issues][10] in this repo.
10 | When submitting an issue please take the following steps:
11 |
12 | **1. Search for existing issues.** Your bug may have already been fixed or addressed in an unreleased version, so
13 | be sure to search the issues first before putting in a duplicate issue.
14 |
15 | **2. Create an isolated and reproducible test case.** If you are reporting a bug, make sure you also have a minimal,
16 | runnable, code example that reproduces the problem you have.
17 |
18 | **3. Include a live example.** After narrowing your code down to only the problem areas, make use of [jsFiddle][11],
19 | [jsBin][12], or a link to your live site so that we can view a live example of the problem.
20 |
21 | **4. Share as much information as possible.** Include browser version affected, your OS, version of the library,
22 | steps to reproduce, etc. "X isn't working!!!1!" will probably just be closed.
23 |
24 | [10]: https://github.com/englercj/phaser-debug/issues
25 | [11]: http://jsfiddle.net
26 | [12]: http://jsbin.com/
27 |
28 |
29 | ## Making Changes
30 |
31 | To build the library you will need to download node.js from [nodejs.org][20]. After it has been installed open a
32 | console and run `npm install -g gulp` to install the global `gulp` executable.
33 |
34 | After that you can clone the repository and run `npm install` inside the cloned folder. This will install
35 | dependencies necessary for building the project. You can rebuild the project by running `gulp` in the cloned
36 | folder.
37 |
38 | Once that is ready, you can make your changes and submit a Pull Request:
39 |
40 | - **Send Pull Requests to the `master` branch.** All Pull Requests must be sent to the `master` branch.
41 |
42 | - **Ensure changes are jshint validated.** Our JSHint configuration file is provided in the repository and you
43 | should check against it before submitting. This should happen automatically when running `gulp` in the repo directory.
44 |
45 | - **Never commit new builds.** When making a code change you should always run `gulp` which will rebuild the project
46 | so you can test, *however* please do not commit the new builds placed in `dist/` or your PR will be closed. By default
47 | the build process will output to an ignored folder (`build/`) you should be fine.
48 |
49 | - **Only commit relevant changes.** Don't include changes that are not directly relevant to the fix you are making.
50 | The more focused a PR is, the faster it will get attention and be merged. Extra files changing only whitespace or
51 | trash files will likely get your PR closed.
52 |
53 | [20]: http://nodejs.org
54 |
55 |
56 | ## Quickie Code Style Guide
57 |
58 | Use EditorConfig and JSHint! Both tools will ensure your code is in the required styles! Either way, here are some tips:
59 |
60 | - Use 4 spaces for tabs, never tab characters.
61 |
62 | - No trailing whitespace, blank lines should have no whitespace.
63 |
64 | - Always favor strict equals `===` unless you *need* to use type coercion.
65 |
66 | - Follow conventions already in the code, and listen to jshint. Our config is set-up for a reason.
67 |
--------------------------------------------------------------------------------
/src/styles/forms.less:
--------------------------------------------------------------------------------
1 | /**
2 | * Based on: http://cssdeck.com/labs/css-checkbox-styles
3 | */
4 |
5 | .pdebug {
6 | input[type=checkbox] {
7 | visibility: hidden;
8 | }
9 |
10 | .rounded(@radius: 2px) {
11 | -webkit-border-radius: @radius;
12 | -moz-border-radius: @radius;
13 | border-radius: @radius;
14 | }
15 |
16 | .boxit(@color1, @color2) {
17 | -webkit-box-shadow: inset 0px 1px 1px @color1, 0px 1px 0px @color2;
18 | -moz-box-shadow: inset 0px 1px 1px @color1, 0px 1px 0px @color2;
19 | -o-box-shadow: inset 0px 1px 1px @color1, 0px 1px 0px @color2;
20 | -ms-box-shadow: inset 0px 1px 1px @color1, 0px 1px 0px @color2;
21 | box-shadow: inset 0px 1px 1px @color1, 0px 1px 0px @color2;
22 | }
23 |
24 | .gradit(@one, @two, @three) {
25 | background: -webkit-linear-gradient(top, @one 0%, @two 40%, @three 100%);
26 | background: -moz-linear-gradient(top, @one 0%, @two 40%, @three 100%);
27 | background: -o-linear-gradient(top, @one 0%, @two 40%, @three 100%);
28 | background: -ms-linear-gradient(top, @one 0%, @two 40%, @three 100%);
29 | background: linear-gradient(top, @one 0%, @two 40%, @three 100%);
30 | }
31 |
32 | .checkbox {
33 | width: 75px;
34 | height: 26px;
35 | background: #333;
36 | position: relative;
37 | line-height: normal;
38 | //margin: 20px auto;
39 |
40 | .rounded(50px);
41 | .boxit(rgba(0,0,0,0.5), rgba(255,255,255,0.2));
42 |
43 | &:after {
44 | content: 'OFF';
45 | font: 12px/26px Arial, sans-serif;
46 | color: #000;
47 | position: absolute;
48 | right: 10px;
49 | z-index: 0;
50 | font-weight: bold;
51 | text-shadow: 1px 1px 0px rgba(255,255,255,.15);
52 | }
53 |
54 | &:before {
55 | content: 'ON';
56 | font: 12px/26px Arial, sans-serif;
57 | color: #00bf00;
58 | position: absolute;
59 | left: 10px;
60 | z-index: 0;
61 | font-weight: bold;
62 | }
63 |
64 | & + span {
65 | position: relative;
66 | display: block;
67 | top: -25px;
68 | left: 90px;
69 | width: 200px;
70 | color: #fcfff4;
71 | font-size: 1.1em;
72 | }
73 |
74 | input[type=checkbox]:checked + label {
75 | left: 38px;
76 | }
77 |
78 |
79 | label {
80 | display: block;
81 | width: 34px;
82 | height: 20px;
83 |
84 | -webkit-border-radius: 50px;
85 | -moz-border-radius: 50px;
86 | border-radius: 50px;
87 |
88 | -webkit-transition: all .4s ease;
89 | -moz-transition: all .4s ease;
90 | -o-transition: all .4s ease;
91 | -ms-transition: all .4s ease;
92 | transition: all .4s ease;
93 | cursor: pointer;
94 | position: absolute;
95 | top: 3px;
96 | left: 3px;
97 | z-index: 1;
98 |
99 | background: #fcfff4;
100 | .gradit(#fcfff4, #dfe5d7, #b3bead);
101 | //.rounded(@cb_radius);
102 | //.boxit(@cb_accent_start, @cb_accent_stop);
103 |
104 | -webkit-box-shadow: 0px 2px 5px 0px rgba(0,0,0,0.3);
105 | -moz-box-shadow: 0px 2px 5px 0px rgba(0,0,0,0.3);
106 | box-shadow: 0px 2px 5px 0px rgba(0,0,0,0.3);
107 | }
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/src/util/ui.js:
--------------------------------------------------------------------------------
1 | //Some general dom helpers
2 | var ui = {
3 | delegate: function (dom, evt, selector, fn) {
4 | dom.addEventListener(evt, function(e) {
5 | window.target = e.target;
6 | if (e.target && e.target.matches(selector)) {
7 | e.delegateTarget = e.target;
8 |
9 | if (fn) {
10 | fn(e);
11 | }
12 | }
13 | else if (e.target.parentElement && e.target.parentElement.matches(selector)) {
14 | e.delegateTarget = e.target.parentElement;
15 |
16 | if (fn) {
17 | fn(e);
18 | }
19 | }
20 | });
21 | },
22 |
23 | on: function (dom, evt, delegate, fn) {
24 | if (typeof delegate === 'function') {
25 | fn = delegate;
26 | delegate = null;
27 | }
28 |
29 | if (delegate) {
30 | return ui.delegate(dom, evt, delegate, fn);
31 | }
32 |
33 | dom.addEventListener(evt, fn);
34 | },
35 |
36 | removeClass: function (dom, cls) {
37 | var classes = dom.className.split(' '),
38 | i = classes.indexOf(cls);
39 |
40 | if(i !== -1) {
41 | classes.splice(i, 1);
42 | dom.className = classes.join(' ').trim();
43 | }
44 | },
45 |
46 | addClass: function (dom, cls) {
47 | var classes = dom.className.split(' ');
48 |
49 | classes.push(cls);
50 | dom.className = classes.join(' ').trim();
51 | },
52 |
53 | hasClass: function (dom, cls) {
54 | return dom.className.split(' ').indexOf(cls) !== -1;
55 | },
56 |
57 | toggleClass: function (dom, cls) {
58 | if (ui.hasClass(dom, cls)) {
59 | ui.removeClass(dom, cls);
60 | } else {
61 | ui.addClass(dom, cls);
62 | }
63 | },
64 |
65 | setText: function (dom, txt) {
66 | dom.textContent = txt;
67 | },
68 |
69 | setHtml: function (dom, html) {
70 | dom.innerHTML = html;
71 | },
72 |
73 | setStyle: function (dom, style, value) {
74 | if(typeof style === 'string') {
75 | dom.style[style] = value;
76 | } else {
77 | for(var key in style) {
78 | dom.style[key] = style[key];
79 | }
80 | }
81 | },
82 |
83 | empty: function (dom) {
84 | while(dom.firstChild) {
85 | dom.removeChild(dom.firstChild);
86 | }
87 | },
88 |
89 | show: function (dom) {
90 | ui.setStyle(dom, 'display', 'block');
91 | },
92 |
93 | hide: function (dom) {
94 | ui.setStyle(dom, 'display', 'none');
95 | },
96 |
97 | clear: function () {
98 | var br = document.createElement('br');
99 | ui.setStyle(br, 'clear', 'both');
100 |
101 | return br;
102 | },
103 |
104 | addCss: function (css) {
105 | var style = document.createElement('style');
106 |
107 | style.type = 'text/css';
108 |
109 | if (style.styleSheet){
110 | style.styleSheet.cssText = css;
111 | } else {
112 | style.appendChild(document.createTextNode(css));
113 | }
114 |
115 | document.head.appendChild(style);
116 | }
117 | };
118 |
119 | module.exports = ui;
120 |
121 | // polyfill for matchesSelector
122 | if (!HTMLElement.prototype.matches) {
123 | var htmlprot = HTMLElement.prototype;
124 |
125 | htmlprot.matches =
126 | htmlprot.matches ||
127 | htmlprot.webkitMatchesSelector ||
128 | htmlprot.mozMatchesSelector ||
129 | htmlprot.msMatchesSelector ||
130 | htmlprot.oMatchesSelector ||
131 | function (selector) {
132 | // poorman's polyfill for matchesSelector
133 | var elements = this.parentElement.querySelectorAll(selector),
134 | element,
135 | i = 0;
136 |
137 | while (element = elements[i++]) {
138 | if (element === this) {
139 | return true;
140 | }
141 | }
142 |
143 | return false;
144 | };
145 | }
146 |
--------------------------------------------------------------------------------
/src/styles/panel.less:
--------------------------------------------------------------------------------
1 | @background: #333;
2 | @foreground: #aaa;
3 | @accent: #00bf00;
4 | @strong: #fff;
5 |
6 | @activeTabForeground: @accent;
7 | @activeTabBackground: #111;
8 |
9 | @seperatorWidth: 1px;
10 | @separatorColor: lighten(@background, 20%);
11 |
12 | @accentHeight: 3px;
13 |
14 | @bar_height: 32px;
15 | @panel_height: 265px;
16 |
17 | @padding: 10px;
18 |
19 | //container
20 | .pdebug {
21 | font-size: 14px;
22 | position: fixed;
23 | bottom: 0;
24 | width: 100%;
25 |
26 | color: @foreground;
27 | background: @background;
28 | border-top: @accentHeight solid @accent;
29 |
30 | z-index: 999999;
31 |
32 | a {
33 | color: @accent;
34 | }
35 |
36 | label {
37 | display: inline-block;
38 | width: 100px;
39 | }
40 |
41 | strong {
42 | font-weight: normal;
43 | color: @strong;
44 | }
45 |
46 | .weak {
47 | color: @foreground;
48 | }
49 |
50 | //menu bar
51 | .pdebug-menu {
52 | height: @bar_height;
53 | padding: 0 15px;
54 |
55 | text-shadow: 1px 1px 0 #111;
56 |
57 | background: @background;
58 |
59 | span {
60 | display: inline-block;
61 | height: @bar_height;
62 | line-height: @bar_height;
63 | }
64 |
65 | //head of the menu bar
66 | .pdebug-head {
67 | padding-right: 25px;
68 | border-right: @seperatorWidth solid @separatorColor;
69 | }
70 |
71 | //main bar stats
72 | .pdebug-stats {
73 | float:right;
74 | padding: 0 0 0 @padding;
75 |
76 | //an item on the stats bar
77 | .pdebug-stats-item {
78 | display: inline-block;
79 | width: 100px;
80 |
81 | text-align: right;
82 |
83 | & > span {
84 | color: @strong;
85 | }
86 |
87 | //fps stat item
88 | &.fps {}
89 |
90 | //ms stat item
91 | &.ms {}
92 |
93 | //sprites stat item
94 | &.obj {
95 | width: 100px;
96 | border: none;
97 | }
98 | }
99 | }
100 |
101 | //menu items (to switch between panels)
102 | .pdebug-menu-item {
103 | color: @strong;
104 |
105 | display: inline-block;
106 |
107 | text-decoration: none;
108 |
109 | padding: 0 @padding;
110 | height: @bar_height;
111 | line-height: @bar_height;
112 | border-right: @seperatorWidth solid @separatorColor;
113 |
114 | &.active {
115 | color: @activeTabForeground;
116 | background: @activeTabBackground;
117 | }
118 | }
119 | }
120 |
121 | //panels
122 | .pdebug-panel {
123 | display: none;
124 | height: @panel_height;
125 | overflow: auto;
126 |
127 | font-size: 12px;
128 |
129 | background: @activeTabBackground;
130 |
131 | //the performance panel
132 | &.performance {}
133 |
134 | //the scene tree panel
135 | &.scene {
136 | .sidebar {
137 | float: left;
138 | height: 100%;
139 |
140 | min-width: 175px;
141 | max-width: 500px;
142 |
143 | resize: horizontal;
144 | overflow: auto;
145 | }
146 |
147 | .details {
148 | float: left;
149 | height: 100%;
150 | }
151 |
152 | .refresh {
153 | position: absolute;
154 | }
155 |
156 | > ul {
157 | padding: 0;
158 | margin: 0;
159 |
160 | border-right: solid 1px @foreground;
161 | margin-right: 10px;
162 |
163 | li {
164 | color: @strong;
165 |
166 | list-style: none;
167 | cursor: pointer;
168 |
169 | &.expanded > ul {
170 | display: block;
171 | }
172 |
173 | &.selected {
174 | color: @accent;
175 | }
176 |
177 | &::before {
178 | content: '-';
179 |
180 | display: inline-block;
181 |
182 | width: 12px;
183 | height: 1px;
184 |
185 | color: @foreground;
186 | }
187 |
188 | &.has-children {
189 | &::before {
190 | content: '';
191 |
192 | display: inline-block;
193 |
194 | width: 0;
195 | height: 0;
196 |
197 | margin: 0 6px 0 0;
198 |
199 | border-top: 6px solid transparent;
200 | border-bottom: 6px solid transparent;
201 | border-right: none;
202 | border-left: 6px solid rgba(255, 255, 255, 0.3);
203 | }
204 |
205 | &.expanded::before {
206 | margin: 0 4px 0 -4px;
207 |
208 | border-top: 6px solid rgba(255, 255, 255, 0.3);
209 | border-left: 6px solid transparent;
210 | border-right: 6px solid transparent;
211 | border-bottom: none;
212 | }
213 | }
214 |
215 | > ul {
216 | display: none;
217 | padding: 0 0 0 10px;
218 | }
219 | }
220 | }
221 | }
222 | }
223 | }
224 |
--------------------------------------------------------------------------------
/src/panels/Scene.js:
--------------------------------------------------------------------------------
1 | var Panel = require('./Panel'),
2 | ui = require('../util/ui'),
3 | Handlebars = require('hbsfy/runtime');
4 |
5 | //require templates
6 | var panelHtml = require('../hbs/scene/panel.hbs'),
7 | detailsHtml = require('../hbs/scene/details.hbs'),
8 | treeHtml = require('../hbs/scene/tree.hbs'),
9 | _cache = {},
10 | _id = 0;
11 |
12 | Handlebars.registerPartial('sceneDetails', detailsHtml);
13 | Handlebars.registerPartial('sceneTree', treeHtml);
14 | Handlebars.registerHelper('typeString', typeToString);
15 | Handlebars.registerHelper('listItemOpen', listItemOpen);
16 |
17 | function Scene(game, parent) {
18 | Panel.call(this, game, parent);
19 |
20 | this.name = 'scene';
21 | this.title = 'Scene Tree';
22 |
23 | this._tree = null;
24 |
25 | this.tree = null;
26 | this.details = null;
27 | this.refresh = null;
28 |
29 | this.selected = null;
30 | }
31 |
32 | Scene.prototype = Object.create(Panel.prototype);
33 | Scene.prototype.constructor = Scene;
34 |
35 | module.exports = Scene;
36 |
37 | Scene.prototype.createPanelElement = function () {
38 | Panel.prototype.createPanelElement.call(this);
39 |
40 | this._panel.innerHTML = panelHtml(this.game.stage);
41 |
42 | this.tree = this._panel.querySelector('.sidebar');
43 | this.details = this._panel.querySelector('.details');
44 | this.refresh = this._panel.querySelector('.refresh');
45 |
46 | ui.on(this.tree, 'click', 'li', this._onLiClick.bind(this));
47 | ui.on(this.refresh, 'click', this._onRefreshClick.bind(this));
48 |
49 | this.bmd = this.game.add.bitmapData(512, 256);
50 |
51 | return this._panel;
52 | };
53 |
54 | Scene.prototype.rebuildTree = function () {
55 | ui.empty(this.tree);
56 |
57 | _cache = {};
58 |
59 | this.tree.innerHTML = treeHtml(this.game.stage);
60 |
61 | this.select(this.tree.querySelector('li:first-child'));
62 | ui.addClass(this.selected, 'expanded');
63 |
64 | this.reloadDetails();
65 | };
66 |
67 | Scene.prototype.reloadDetails = function () {
68 | var id = this.selected.dataset.id;
69 | var obj = _cache[id];
70 |
71 | this.details.innerHTML = detailsHtml(obj);
72 |
73 | if (obj.texture) {
74 | this.details.appendChild(this.bmd.canvas);
75 |
76 | var w = Math.min(512, obj.width);
77 | var h = Math.min(256, obj.height);
78 |
79 | this.bmd.clear();
80 | this.bmd.resize(w, h);
81 |
82 | try {
83 | this.bmd.draw(obj, 0, 0, w, h);
84 | } catch (e) {};
85 | }
86 | };
87 |
88 | Scene.prototype.select = function (li) {
89 | if (this.selected) {
90 | ui.removeClass(this.selected, 'selected');
91 | }
92 |
93 | this.selected = li;
94 | ui.addClass(this.selected, 'selected');
95 | };
96 |
97 | Scene.prototype.show = function () {
98 | this.rebuildTree();
99 |
100 | Panel.prototype.show.call(this);
101 | };
102 |
103 | Scene.prototype.destroy = function () {
104 | Panel.prototype.destroy.call(this);
105 |
106 | this.tree = null;
107 | this.details = null;
108 | this.refresh = null;
109 | };
110 |
111 | Scene.prototype._onLiClick = function (e) {
112 | e.stopPropagation();
113 |
114 | this.select(e.delegateTarget);
115 |
116 | ui.toggleClass(e.delegateTarget, 'expanded');
117 |
118 | this.reloadDetails();
119 | };
120 |
121 | Scene.prototype._onRefreshClick = function (e) {
122 | e.preventDefault();
123 | e.stopPropagation();
124 |
125 | this.rebuildTree();
126 | };
127 |
128 | function listItemOpen () {
129 | _cache[++_id] = this;
130 |
131 | return new Handlebars.SafeString(
132 | ''
133 | );
134 | }
135 |
136 | function typeToString () {
137 | var node = this;
138 |
139 | // If no phaser type defined, try to guess
140 | if (node.type === undefined) {
141 | // Phaser.Stage does not have its 'type' property defined, so check here.
142 | if (node instanceof Phaser.Stage) {
143 | return 'Stage';
144 | }
145 | // PIXI.Stage was removed in Phaser 2.4.4, so make sure it's defined first.
146 | else if (typeof PIXI.Stage !== 'undefined' &&
147 | node instanceof PIXI.Stage) {
148 | return 'PIXI Stage';
149 | }
150 | else if (node instanceof PIXI.Sprite) {
151 | return 'PIXI Sprite';
152 | }
153 | else if (node instanceof PIXI.DisplayObjectContainer) {
154 | return 'PIXI DisplayObjectContainer';
155 | }
156 | else if (node instanceof PIXI.DisplayObject) {
157 | return 'PIXI DisplayObject';
158 | }
159 | else {
160 | return 'Unknown';
161 | }
162 | }
163 | // return a string for the phaser type
164 | else {
165 | switch(node.type) {
166 | case Phaser.SPRITE:
167 | return 'Sprite';
168 |
169 | case Phaser.BUTTON:
170 | return 'Button';
171 |
172 | case Phaser.IMAGE:
173 | return 'Image';
174 |
175 | case Phaser.GRAPHICS:
176 | return 'Graphics';
177 |
178 | case Phaser.TEXT:
179 | return 'Text';
180 |
181 | case Phaser.TILESPRITE:
182 | return 'Tile Sprite';
183 |
184 | case Phaser.BITMAPTEXT:
185 | return 'Bitmap Text';
186 |
187 | case Phaser.GROUP:
188 | return 'Group';
189 |
190 | case Phaser.RENDERTEXTURE:
191 | return 'Render Texture';
192 |
193 | case Phaser.TILEMAP:
194 | return 'Tilemap';
195 |
196 | case Phaser.TILEMAPLAYER:
197 | return 'Tilemap Layer';
198 |
199 | case Phaser.EMITTER:
200 | return 'Emitter';
201 |
202 | case Phaser.POLYGON:
203 | return 'Polygon';
204 |
205 | case Phaser.BITMAPDATA:
206 | return 'Bitmap Data';
207 |
208 | case Phaser.CANVAS_FILTER:
209 | return 'Canvas Filter';
210 |
211 | case Phaser.WEBGL_FILTER:
212 | return 'WebGL Filter';
213 |
214 | case Phaser.ELLIPSE:
215 | return 'Ellipse';
216 |
217 | case Phaser.SPRITEBATCH:
218 | return 'Sprite Batch';
219 |
220 | case Phaser.RETROFONT:
221 | return 'Retro Font';
222 |
223 | case Phaser.POINTER:
224 | return 'Pointer';
225 |
226 | case Phaser.ROPE:
227 | return 'Rope';
228 |
229 | default:
230 | return 'Unknown';
231 | }
232 | }
233 | }
234 |
--------------------------------------------------------------------------------
/src/util/Graph.js:
--------------------------------------------------------------------------------
1 | // TODO: Move the legend into DOM?
2 |
3 | function Graph(container, width, height, colors, options) {
4 | options = options || {};
5 |
6 | this.canvas = document.createElement('canvas');
7 | this.canvas.width = width;
8 | this.canvas.height = height;
9 | container.appendChild(this.canvas);
10 |
11 | this.ctx = this.canvas.getContext('2d');
12 |
13 | this.labelStyle = 'rgba(200, 200, 200, 0.6)';
14 |
15 | this.maxValue = options.maxValue || 50;
16 | this.padding = options.labelPadding || 5;
17 |
18 | this.dataLineWidth = options.lineWidth || 1;
19 | this.legendWidth = 230;
20 | this.legendBoxSize = 10;
21 | this.legendIndent = 5;
22 |
23 | this.eventY = this.padding * 2;
24 |
25 | this.colors = colors;
26 |
27 | this.dataCanvas = document.createElement('canvas');
28 | this.dataCanvas.width = width - this.legendWidth;
29 | this.dataCanvas.height = height;
30 | this.dctx = this.dataCanvas.getContext('2d');
31 |
32 | this.dataCanvasBuffer = document.createElement('canvas');
33 | this.dataCanvasBuffer.width = this.dataCanvas.width - this.dataLineWidth;
34 | this.dataCanvasBuffer.height = this.dataCanvas.height;
35 | this.bctx = this.dataCanvasBuffer.getContext('2d');
36 | }
37 |
38 | Graph.prototype.constructor = Graph;
39 |
40 | module.exports = Graph;
41 |
42 | // render the graph with the new data point
43 | Graph.prototype.addData = function (values, event) {
44 | // clear the main canvas
45 | this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
46 |
47 | this.drawBg();
48 | this.drawLegend(values);
49 | this.drawData(values, event);
50 | };
51 |
52 | Graph.prototype.drawBg = function () {
53 | var fps60 = Math.floor(this.canvas.height - (this.canvas.height * (16 / this.maxValue))) + 0.5,
54 | fps30 = Math.floor(this.canvas.height - (this.canvas.height * (33 / this.maxValue))) + 0.5;
55 |
56 | this.ctx.strokeStyle = this.ctx.fillStyle = this.labelStyle;
57 | this.ctx.lineWidth = 1;
58 |
59 | //draw top marker line
60 | this.ctx.beginPath();
61 | this.ctx.moveTo(this.legendWidth, fps60);
62 | this.ctx.lineTo(this.canvas.width, fps60);
63 | this.ctx.stroke();
64 |
65 | this.ctx.fillText('16ms (60 fps)', this.legendWidth + this.padding, fps60 - this.padding);
66 |
67 | //draw the second marker line
68 | this.ctx.beginPath();
69 | this.ctx.moveTo(this.legendWidth, fps30);
70 | this.ctx.lineTo(this.canvas.width, fps30);
71 | this.ctx.stroke();
72 |
73 | this.ctx.fillText('33ms (30 fps)', this.legendWidth + this.padding, fps30 - this.padding);
74 |
75 | //draw baseline marker
76 | this.ctx.beginPath();
77 | this.ctx.moveTo(this.legendWidth, this.canvas.height - 0.5);
78 | this.ctx.lineTo(this.canvas.width, this.canvas.height - 0.5);
79 | this.ctx.stroke();
80 | };
81 |
82 | Graph.prototype.drawLegend = function (values) {
83 | var colorIndex = 0,
84 | yIndex = 0,
85 | x = this.padding,
86 | y = 0;
87 |
88 | for (var k in values) {
89 | y = (yIndex * this.legendBoxSize) + (this.padding * (yIndex + 1)) + this.padding;
90 |
91 | // Draw parent label
92 | this.ctx.fillStyle = this.labelStyle;
93 | this.ctx.fillText(k, x, y);
94 |
95 | ++yIndex;
96 |
97 | // Draw children
98 | for (var c in values[k]) {
99 | y = (yIndex * this.legendBoxSize) + (this.padding * yIndex);
100 |
101 | this.ctx.fillStyle = this.colors[colorIndex++ % this.colors.length];
102 | this.ctx.fillRect(x + this.legendIndent, y, this.legendBoxSize, this.legendBoxSize);
103 |
104 | this.ctx.fillStyle = this.labelStyle;
105 | this.ctx.fillText(
106 | Math.round(values[k][c]) + 'ms - ' + c,
107 | x + this.legendIndent + this.legendBoxSize + this.padding,
108 | y + this.legendBoxSize
109 | );
110 |
111 | ++yIndex;
112 |
113 | if (yIndex > 16) {
114 | x += this.legendWidth / 2;
115 | yIndex = 0;
116 | }
117 | }
118 | }
119 | };
120 |
121 | Graph.prototype.drawData = function (values, event) {
122 | var x = this.dataCanvas.width - this.dataLineWidth + 0.5,
123 | y = this.dataCanvas.height - 0.5;
124 |
125 | // clear the buffer
126 | this.bctx.clearRect(0, 0, this.dataCanvasBuffer.width, this.dataCanvasBuffer.height);
127 |
128 | // draw the data canvas to the buffer, skipping the first line
129 | this.bctx.drawImage(
130 | this.dataCanvas,
131 | this.dataLineWidth, 0, x, y,
132 | 0, 0, x, y
133 | );
134 |
135 | // clear the data canvas
136 | this.dctx.clearRect(0, 0, this.dataCanvas.width, this.dataCanvas.height);
137 |
138 | // draw the buffer back to the data canvas
139 | this.dctx.drawImage(this.dataCanvasBuffer, 0, 0);
140 |
141 | // draw event to the new line of the data canvas if there was one
142 | if (event) {
143 | this.dctx.beginPath();
144 | this.dctx.strokeStyle = this.dctx.fillStyle = '#ff0000';
145 | this.dctx.lineWidth = this.dataLineWidth;
146 |
147 | this.dctx.moveTo(x, y);
148 | this.dctx.lineTo(x, 0);
149 |
150 | this.dctx.stroke();
151 |
152 | this.dctx.textAlign = 'right';
153 | this.dctx.fillText(event, x - this.padding, this.eventY);
154 |
155 | this.eventY += (this.padding * 2);
156 |
157 | if (this.eventY > (this.dataCanvas.height / 2)) {
158 | this.eventY = (this.padding * 2);
159 | }
160 | }
161 |
162 | // draws the data values to the new line of the data canvas
163 |
164 | // draw the new data points
165 | var colorIndex = 0,
166 | step = 0;
167 |
168 | for (var k in values) {
169 | for (var c in values[k]) {
170 | this.dctx.beginPath();
171 | this.dctx.strokeStyle = this.dctx.fillStyle = this.colors[colorIndex++ % this.colors.length];
172 | this.dctx.lineWidth = this.dataLineWidth;
173 |
174 | step = ((values[k][c] / this.maxValue) * this.dataCanvas.height);
175 | step = step < 0 ? 0 : step;
176 |
177 | this.dctx.moveTo(x, y);
178 | this.dctx.lineTo(x, y-=step);
179 |
180 | this.dctx.stroke();
181 | }
182 | }
183 |
184 | // draw the data canvas to the main rendered canvas
185 | this.ctx.drawImage(this.dataCanvas, this.legendWidth, 0);
186 | };
187 |
188 | Graph.prototype.destroy = function () {
189 | this.canvas = null;
190 | this.ctx = null;
191 |
192 | this.labelStyle = null;
193 |
194 | this.maxValue = null;
195 | this.padding = null;
196 |
197 | this.dataLineWidth = null;
198 | this.legendWidth = null;
199 | this.legendBoxSize = null;
200 | this.legendIndent = null;
201 |
202 | this.colors = null;
203 |
204 | this.dataCanvas = null;
205 | this.dctx = null;
206 |
207 | this.dataCanvasBuffer = null;
208 | this.bctx = null;
209 | };
210 |
--------------------------------------------------------------------------------
/.jshintrc:
--------------------------------------------------------------------------------
1 | {
2 | // --------------------------------------------------------------------
3 | // JSHint Configuration
4 | // --------------------------------------------------------------------
5 | //
6 | // @author Chad Engler
7 |
8 | // == Enforcing Options ===============================================
9 | //
10 | // These options tell JSHint to be more strict towards your code. Use
11 | // them if you want to allow only a safe subset of JavaScript, very
12 | // useful when your codebase is shared with a big number of developers
13 | // with different skill levels.
14 |
15 | "bitwise" : false, // Disallow bitwise operators (&, |, ^, etc.).
16 | "camelcase" : true, // Force all variable names to use either camelCase or UPPER_CASE.
17 | "curly" : true, // Require {} for every new block or scope.
18 | "eqeqeq" : true, // Require triple equals i.e. `===`.
19 | "es3" : false, // Enforce conforming to ECMAScript 3.
20 | "forin" : false, // Disallow `for in` loops without `hasOwnPrototype`.
21 | "immed" : true, // Require immediate invocations to be wrapped in parens e.g. `( function(){}() );`
22 | "indent" : 4, // Require that 4 spaces are used for indentation.
23 | "latedef" : "nofunc", // Prohibit variable use before definition.
24 | "newcap" : true, // Require capitalization of all constructor functions e.g. `new F()`.
25 | "noarg" : true, // Prohibit use of `arguments.caller` and `arguments.callee`.
26 | "noempty" : true, // Prohibit use of empty blocks.
27 | "nonew" : true, // Prohibit use of constructors for side-effects.
28 | "plusplus" : false, // Disallow use of `++` & `--`.
29 | "quotmark" : true, // Force consistency when using quote marks.
30 | "undef" : true, // Require all non-global variables be declared before they are used.
31 | "unused" : true, // Warn when varaibles are created but not used.
32 | "strict" : false, // Require `use strict` pragma in every file.
33 | "trailing" : true, // Prohibit trailing whitespaces.
34 | "maxparams" : 6, // Prohibit having more than X number of params in a function.
35 | "maxdepth" : 6, // Prohibit nested blocks from going more than X levels deep.
36 | "maxstatements" : false, // Restrict the number of statements in a function.
37 | "maxcomplexity" : false, // Restrict the cyclomatic complexity of the code.
38 | "maxlen" : 120, // Require that all lines are n characters or less.
39 | "globals" : { // Register globals that are used in the code.
40 | "PIXI": false,
41 | "Phaser": false
42 | },
43 |
44 | // == Relaxing Options ================================================
45 | //
46 | // These options allow you to suppress certain types of warnings. Use
47 | // them only if you are absolutely positive that you know what you are
48 | // doing.
49 |
50 | "asi" : false, // Tolerate Automatic Semicolon Insertion (no semicolons).
51 | "boss" : true, // Tolerate assignments inside if, for & while. Usually conditions & loops are for comparison, not assignments.
52 | "debug" : false, // Allow debugger statements e.g. browser breakpoints.
53 | "eqnull" : false, // Tolerate use of `== null`.
54 | "esnext" : false, // Allow ES.next specific features such as `const` and `let`.
55 | "evil" : false, // Tolerate use of `eval`.
56 | "expr" : false, // Tolerate `ExpressionStatement` as Programs.
57 | "funcscope" : false, // Tolerate declarations of variables inside of control structures while accessing them later from the outside.
58 | "globalstrict" : false, // Allow global "use strict" (also enables 'strict').
59 | "iterator" : false, // Allow usage of __iterator__ property.
60 | "lastsemic" : false, // Tolerate missing semicolons when the it is omitted for the last statement in a one-line block.
61 | "laxbreak" : false, // Tolerate unsafe line breaks e.g. `return [\n] x` without semicolons.
62 | "laxcomma" : false, // Suppress warnings about comma-first coding style.
63 | "loopfunc" : false, // Allow functions to be defined within loops.
64 | "moz" : false, // Code that uses Mozilla JS extensions will set this to true
65 | "multistr" : false, // Tolerate multi-line strings.
66 | "proto" : false, // Tolerate __proto__ property. This property is deprecated.
67 | "scripturl" : false, // Tolerate script-targeted URLs.
68 | "smarttabs" : false, // Tolerate mixed tabs and spaces when the latter are used for alignmnent only.
69 | "shadow" : false, // Allows re-define variables later in code e.g. `var x=1; x=2;`.
70 | "sub" : false, // Tolerate all forms of subscript notation besides dot notation e.g. `dict['key']` instead of `dict.key`.
71 | "supernew" : false, // Tolerate `new function () { ... };` and `new Object;`.
72 | "validthis" : false, // Tolerate strict violations when the code is running in strict mode and you use this in a non-constructor function.
73 |
74 | // == Environments ====================================================
75 | //
76 | // These options pre-define global variables that are exposed by
77 | // popular JavaScript libraries and runtime environments—such as
78 | // browser or node.js.
79 |
80 | "browser" : true, // Standard browser globals e.g. `window`, `document`.
81 | "couch" : false, // Enable globals exposed by CouchDB.
82 | "devel" : false, // Allow development statements e.g. `console.log();`.
83 | "dojo" : false, // Enable globals exposed by Dojo Toolkit.
84 | "jquery" : false, // Enable globals exposed by jQuery JavaScript library.
85 | "mootools" : false, // Enable globals exposed by MooTools JavaScript framework.
86 | "node" : true, // Enable globals available when code is running inside of the NodeJS runtime environment. (for Gruntfile)
87 | "nonstandard" : false, // Define non-standard but widely adopted globals such as escape and unescape.
88 | "prototypejs" : false, // Enable globals exposed by Prototype JavaScript framework.
89 | "rhino" : false, // Enable globals available when your code is running inside of the Rhino runtime environment.
90 | "worker" : false, // Enable globals available when your code is running as a WebWorker.
91 | "wsh" : false, // Enable globals available when your code is running as a script for the Windows Script Host.
92 | "yui" : false, // Enable globals exposed by YUI library.
93 |
94 | // == JSLint Legacy ===================================================
95 | //
96 | // These options are legacy from JSLint. Aside from bug fixes they will
97 | // not be improved in any way and might be removed at any point.
98 |
99 | "nomen" : false, // Prohibit use of initial or trailing underbars in names.
100 | "onevar" : false, // Allow only one `var` statement per function.
101 | "passfail" : false, // Stop on first error.
102 | "white" : false, // Check against strict whitespace and indentation rules.
103 |
104 | // == Undocumented Options ============================================
105 | //
106 | // While I've found these options in [example1][2] and [example2][3]
107 | // they are not described in the [JSHint Options documentation][4].
108 | //
109 | // [4]: http://www.jshint.com/options/
110 |
111 | "maxerr" : 100 // Maximum errors before stopping.
112 | }
113 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | var ui = require('./util/ui'),
2 | css = require('./styles/main.less'),
3 | PerformancePanel = require('./panels/Performance'),
4 | ScenePanel = require('./panels/Scene');
5 |
6 | /**
7 | * @class Phaser.Plugin.Debug
8 | * @classdesc Phaser - Debug Plugin
9 | *
10 | * @constructor
11 | * @extends Phaser.Plugin
12 | *
13 | * @param {Phaser.Game} game - A reference to the currently running game.
14 | * @param {Any} parent - The object that owns this plugin, usually Phaser.PluginManager.
15 | */
16 | function Debug(game, parent) {
17 | Phaser.Plugin.call(this, game, parent);
18 |
19 | this.panels = {
20 | performance: null,
21 | scene: null
22 | };
23 |
24 | this.tickTimings = {
25 | lastStart: 0,
26 | start: 0,
27 | ms: 0
28 | };
29 |
30 | this.timings = {
31 | preUpdate: {
32 | physics : 0,
33 | state : 0,
34 | plugins : 0,
35 | stage : 0
36 | },
37 | update: {
38 | state : 0,
39 | stage : 0,
40 | tweens : 0,
41 | sound : 0,
42 | input : 0,
43 | physics : 0,
44 | particles: 0,
45 | plugins : 0
46 | },
47 | postUpdate: {
48 | stage : 0,
49 | plugins : 0
50 | },
51 | preRender: {
52 | state : 0
53 | },
54 | render: {
55 | renderer : 0,
56 | plugins : 0,
57 | state : 0
58 | },
59 | postRender: {
60 | plugins : 0
61 | }
62 | };
63 |
64 | this._container = null;
65 | this._bar = null;
66 |
67 | this._stats = {
68 | ms: null,
69 | fps: null,
70 | dpf: null,
71 | ent: null
72 | };
73 |
74 | this.timer = (window.performance ? window.performance : Date);
75 | }
76 |
77 | // Extends the Phaser.Plugin template, setting up values we need
78 | Debug.prototype = Object.create(Phaser.Plugin.prototype);
79 | Debug.prototype.constructor = Debug;
80 |
81 | Debug.PKG = require('../package.json');
82 | Debug.VERSION = Debug.PKG.version;
83 |
84 | module.exports = Debug;
85 |
86 | Debug.prototype.init = function () {
87 | // create the panels
88 | this.panels.performance = new PerformancePanel(this.game, this);
89 | this.panels.scene = new ScenePanel(this.game, this);
90 |
91 | // add elements to the page
92 | ui.addCss(css);
93 | document.body.appendChild(this._createElement());
94 |
95 | this._bindEvents();
96 |
97 | // wrap each component's update methods so we can time them
98 | for (var method in this.timings) {
99 | for (var comp in this.timings[method]) {
100 | this._wrap(this.game, comp, method, comp);
101 | }
102 | }
103 |
104 | // wrap the game update method
105 | this._wrap(this, 'game', 'update');
106 |
107 | // initialize each panel
108 | for (var p in this.panels) {
109 | if (this.panels[p].init) {
110 | this.panels[p].init.apply(this.panels[p], arguments);
111 | }
112 | }
113 | };
114 |
115 | /**
116 | * Post-Update is called after all the update methods have already been called, but before the render calls.
117 | * It is only called if active is set to true.
118 | *
119 | * @method Phaser.Plugin.Debug#postUpdate
120 | */
121 | Debug.prototype.postUpdate = function () {
122 | for (var p in this.panels) {
123 | if (this.panels[p].update && this.panels[p].active) {
124 | this.panels[p].update();
125 | }
126 | }
127 |
128 | var fps = Math.round(1000 / (this.tickTimings.start - this.tickTimings.lastStart)),
129 | dpf = this.game.renderer.renderSession.drawCount;
130 |
131 | fps = fps > 60 ? 60 : fps;
132 |
133 | // update stats indicators
134 | ui.setText(this._stats.dpf.firstElementChild, dpf === undefined ? '(N/A)' : dpf, 3);
135 | ui.setText(this._stats.ms.firstElementChild, Math.round(this.tickTimings.ms), 4);
136 | ui.setText(this._stats.fps.firstElementChild, Math.round(fps), 2);
137 | };
138 |
139 | /**
140 | * Marks a point on the performance graph with a label to help you corrolate events and timing on the graph
141 | *
142 | * @method Phaser.Plugin.Debug#mark
143 | */
144 | Debug.prototype.mark = function (label) {
145 | if (this.panels.performance) {
146 | this.panels.performance.mark(label);
147 | }
148 | };
149 |
150 | Debug.prototype.destroy = function () {
151 | Phaser.Plugin.prototype.destroy.call(this);
152 |
153 | for (var p in this.panels) {
154 | this.panels[p].destroy();
155 | }
156 |
157 | this.panels = null;
158 | this.tickTimings = null;
159 | this.timings = null;
160 |
161 | this._container = null;
162 | this._bar = null;
163 | this._stats = null;
164 |
165 | this.timer = null;
166 | };
167 |
168 | Debug.prototype._wrap = function (obj, component, method, timingStat) {
169 | if (!obj[component] || !obj[component][method]) {
170 | return;
171 | }
172 |
173 | obj[component][method] = (function(self, name, method, stat, fn) {
174 | var start = 0,
175 | end = 0;
176 |
177 | // special tick capture for game update
178 | if (name === 'game' && method === 'update' && !stat) {
179 | return function () {
180 | start = self.timer.now();
181 |
182 | self.tickTimings.lastStart = self.tickTimings.start;
183 | self.tickTimings.start = start;
184 |
185 | fn.apply(this, arguments);
186 |
187 | end = self.timer.now();
188 |
189 | self.tickTimings.ms = end - start;
190 | };
191 | }
192 | else {
193 | return function () {
194 | start = self.timer.now();
195 |
196 | fn.apply(this, arguments);
197 |
198 | end = self.timer.now();
199 |
200 | self.timings[method][stat] = end - start;
201 | };
202 | }
203 | })(this, component, method, timingStat, obj[component][method]);
204 | };
205 |
206 | Debug.prototype._bindEvents = function () {
207 | var activePanel,
208 | self = this;
209 |
210 | ui.on(this._bar, 'click', '.pdebug-menu-item', function(e) {
211 | e.preventDefault();
212 |
213 | var panel = self.panels[e.target.getAttribute('href').replace('#', '')];
214 |
215 | if(!panel) {
216 | return;
217 | }
218 |
219 | if(activePanel) {
220 | activePanel.toggle();
221 | ui.removeClass(activePanel._menuItem, 'active');
222 |
223 | if(activePanel.name === panel.name) {
224 | activePanel = null;
225 | return;
226 | }
227 | }
228 |
229 | ui.addClass(e.target, 'active');
230 | panel.toggle();
231 | activePanel = panel;
232 | });
233 | };
234 |
235 | Debug.prototype._createElement = function () {
236 | var c = this._container = document.createElement('div'),
237 | bar = this._bar = document.createElement('div');
238 |
239 | //container
240 | ui.addClass(c, 'pdebug');
241 | c.appendChild(bar);
242 |
243 | //the menu bar
244 | ui.addClass(bar, 'pdebug-menu');
245 | bar.appendChild(this._createMenuHead());
246 | bar.appendChild(this._createMenuStats());
247 |
248 | //add the panels
249 | for(var p in this.panels) {
250 | bar.appendChild(this.panels[p].createMenuElement());
251 | c.appendChild(this.panels[p].createPanelElement());
252 | }
253 |
254 | return c;
255 | };
256 |
257 | Debug.prototype._createMenuHead = function () {
258 | var div = document.createElement('span'),
259 | r = this.game.renderType,
260 | type = (r === Phaser.WEBGL ? 'WebGL' : (r === Phaser.HEADLESS ? 'Headless' : 'Canvas'));
261 |
262 | ui.addClass(div, 'pdebug-head');
263 | ui.setText(div, 'Phaser Debug (' + type + '):');
264 |
265 | return div;
266 | };
267 |
268 | Debug.prototype._createMenuStats = function () {
269 | var div = document.createElement('div');
270 |
271 | ui.addClass(div, 'pdebug-stats');
272 |
273 | this._stats.ms = document.createElement('span');
274 | this._stats.fps = document.createElement('span');
275 | this._stats.dpf = document.createElement('span');
276 | // this._stats.ent = document.createElement('span');
277 |
278 | ui.addClass(this._stats.ms, 'pdebug-stats-item ms');
279 | ui.setHtml(this._stats.ms, '0 ms');
280 | div.appendChild(this._stats.ms);
281 |
282 | ui.addClass(this._stats.fps, 'pdebug-stats-item fps');
283 | ui.setHtml(this._stats.fps, '0 fps');
284 | div.appendChild(this._stats.fps);
285 |
286 | ui.addClass(this._stats.dpf, 'pdebug-stats-item dpf');
287 | ui.setHtml(this._stats.dpf, '0 draws');
288 | div.appendChild(this._stats.dpf);
289 |
290 | // ui.addClass(this._stats.ent, 'pdebug-stats-item ent');
291 | // ui.setHtml(this._stats.ent, '0 entities');
292 | // div.appendChild(this._stats.ent);
293 |
294 | return div;
295 | };
296 |
--------------------------------------------------------------------------------
/dist/phaser-debug.js:
--------------------------------------------------------------------------------
1 | !function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var n;"undefined"!=typeof window?n=window:"undefined"!=typeof global?n=global:"undefined"!=typeof self&&(n=self);var f=n;f=f.Phaser||(f.Phaser={}),f=f.Plugin||(f.Plugin={}),f.Debug=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o 60 ? 60 : fps;
133 |
134 | // update stats indicators
135 | ui.setText(this._stats.dpf.firstElementChild, dpf === undefined ? '(N/A)' : dpf, 3);
136 | ui.setText(this._stats.ms.firstElementChild, Math.round(this.tickTimings.ms), 4);
137 | ui.setText(this._stats.fps.firstElementChild, Math.round(fps), 2);
138 | };
139 |
140 | /**
141 | * Marks a point on the performance graph with a label to help you corrolate events and timing on the graph
142 | *
143 | * @method Phaser.Plugin.Debug#mark
144 | */
145 | Debug.prototype.mark = function (label) {
146 | if (this.panels.performance) {
147 | this.panels.performance.mark(label);
148 | }
149 | };
150 |
151 | Debug.prototype.destroy = function () {
152 | Phaser.Plugin.prototype.destroy.call(this);
153 |
154 | for (var p in this.panels) {
155 | this.panels[p].destroy();
156 | }
157 |
158 | this.panels = null;
159 | this.tickTimings = null;
160 | this.timings = null;
161 |
162 | this._container = null;
163 | this._bar = null;
164 | this._stats = null;
165 |
166 | this.timer = null;
167 | };
168 |
169 | Debug.prototype._wrap = function (obj, component, method, timingStat) {
170 | if (!obj[component] || !obj[component][method]) {
171 | return;
172 | }
173 |
174 | obj[component][method] = (function(self, name, method, stat, fn) {
175 | var start = 0,
176 | end = 0;
177 |
178 | // special tick capture for game update
179 | if (name === 'game' && method === 'update' && !stat) {
180 | return function () {
181 | start = self.timer.now();
182 |
183 | self.tickTimings.lastStart = self.tickTimings.start;
184 | self.tickTimings.start = start;
185 |
186 | fn.apply(this, arguments);
187 |
188 | end = self.timer.now();
189 |
190 | self.tickTimings.ms = end - start;
191 | };
192 | }
193 | else {
194 | return function () {
195 | start = self.timer.now();
196 |
197 | fn.apply(this, arguments);
198 |
199 | end = self.timer.now();
200 |
201 | self.timings[method][stat] = end - start;
202 | };
203 | }
204 | })(this, component, method, timingStat, obj[component][method]);
205 | };
206 |
207 | Debug.prototype._bindEvents = function () {
208 | var activePanel,
209 | self = this;
210 |
211 | ui.on(this._bar, 'click', '.pdebug-menu-item', function(e) {
212 | e.preventDefault();
213 |
214 | var panel = self.panels[e.target.getAttribute('href').replace('#', '')];
215 |
216 | if(!panel) {
217 | return;
218 | }
219 |
220 | if(activePanel) {
221 | activePanel.toggle();
222 | ui.removeClass(activePanel._menuItem, 'active');
223 |
224 | if(activePanel.name === panel.name) {
225 | activePanel = null;
226 | return;
227 | }
228 | }
229 |
230 | ui.addClass(e.target, 'active');
231 | panel.toggle();
232 | activePanel = panel;
233 | });
234 | };
235 |
236 | Debug.prototype._createElement = function () {
237 | var c = this._container = document.createElement('div'),
238 | bar = this._bar = document.createElement('div');
239 |
240 | //container
241 | ui.addClass(c, 'pdebug');
242 | c.appendChild(bar);
243 |
244 | //the menu bar
245 | ui.addClass(bar, 'pdebug-menu');
246 | bar.appendChild(this._createMenuHead());
247 | bar.appendChild(this._createMenuStats());
248 |
249 | //add the panels
250 | for(var p in this.panels) {
251 | bar.appendChild(this.panels[p].createMenuElement());
252 | c.appendChild(this.panels[p].createPanelElement());
253 | }
254 |
255 | return c;
256 | };
257 |
258 | Debug.prototype._createMenuHead = function () {
259 | var div = document.createElement('span'),
260 | r = this.game.renderType,
261 | type = (r === Phaser.WEBGL ? 'WebGL' : (r === Phaser.HEADLESS ? 'Headless' : 'Canvas'));
262 |
263 | ui.addClass(div, 'pdebug-head');
264 | ui.setText(div, 'Phaser Debug (' + type + '):');
265 |
266 | return div;
267 | };
268 |
269 | Debug.prototype._createMenuStats = function () {
270 | var div = document.createElement('div');
271 |
272 | ui.addClass(div, 'pdebug-stats');
273 |
274 | this._stats.ms = document.createElement('span');
275 | this._stats.fps = document.createElement('span');
276 | this._stats.dpf = document.createElement('span');
277 | // this._stats.ent = document.createElement('span');
278 |
279 | ui.addClass(this._stats.ms, 'pdebug-stats-item ms');
280 | ui.setHtml(this._stats.ms, '0 ms');
281 | div.appendChild(this._stats.ms);
282 |
283 | ui.addClass(this._stats.fps, 'pdebug-stats-item fps');
284 | ui.setHtml(this._stats.fps, '0 fps');
285 | div.appendChild(this._stats.fps);
286 |
287 | ui.addClass(this._stats.dpf, 'pdebug-stats-item dpf');
288 | ui.setHtml(this._stats.dpf, '0 draws');
289 | div.appendChild(this._stats.dpf);
290 |
291 | // ui.addClass(this._stats.ent, 'pdebug-stats-item ent');
292 | // ui.setHtml(this._stats.ent, '0 entities');
293 | // div.appendChild(this._stats.ent);
294 |
295 | return div;
296 | };
297 |
298 | },{"../package.json":10,"./panels/Performance":15,"./panels/Scene":16,"./styles/main.less":17,"./util/ui":19}],2:[function(require,module,exports){
299 | "use strict";
300 | /*globals Handlebars: true */
301 | var base = require("./handlebars/base");
302 |
303 | // Each of these augment the Handlebars object. No need to setup here.
304 | // (This is done to easily share code between commonjs and browse envs)
305 | var SafeString = require("./handlebars/safe-string")["default"];
306 | var Exception = require("./handlebars/exception")["default"];
307 | var Utils = require("./handlebars/utils");
308 | var runtime = require("./handlebars/runtime");
309 |
310 | // For compatibility and usage outside of module systems, make the Handlebars object a namespace
311 | var create = function() {
312 | var hb = new base.HandlebarsEnvironment();
313 |
314 | Utils.extend(hb, base);
315 | hb.SafeString = SafeString;
316 | hb.Exception = Exception;
317 | hb.Utils = Utils;
318 | hb.escapeExpression = Utils.escapeExpression;
319 |
320 | hb.VM = runtime;
321 | hb.template = function(spec) {
322 | return runtime.template(spec, hb);
323 | };
324 |
325 | return hb;
326 | };
327 |
328 | var Handlebars = create();
329 | Handlebars.create = create;
330 |
331 | Handlebars['default'] = Handlebars;
332 |
333 | exports["default"] = Handlebars;
334 | },{"./handlebars/base":3,"./handlebars/exception":4,"./handlebars/runtime":5,"./handlebars/safe-string":6,"./handlebars/utils":7}],3:[function(require,module,exports){
335 | "use strict";
336 | var Utils = require("./utils");
337 | var Exception = require("./exception")["default"];
338 |
339 | var VERSION = "2.0.0";
340 | exports.VERSION = VERSION;var COMPILER_REVISION = 6;
341 | exports.COMPILER_REVISION = COMPILER_REVISION;
342 | var REVISION_CHANGES = {
343 | 1: '<= 1.0.rc.2', // 1.0.rc.2 is actually rev2 but doesn't report it
344 | 2: '== 1.0.0-rc.3',
345 | 3: '== 1.0.0-rc.4',
346 | 4: '== 1.x.x',
347 | 5: '== 2.0.0-alpha.x',
348 | 6: '>= 2.0.0-beta.1'
349 | };
350 | exports.REVISION_CHANGES = REVISION_CHANGES;
351 | var isArray = Utils.isArray,
352 | isFunction = Utils.isFunction,
353 | toString = Utils.toString,
354 | objectType = '[object Object]';
355 |
356 | function HandlebarsEnvironment(helpers, partials) {
357 | this.helpers = helpers || {};
358 | this.partials = partials || {};
359 |
360 | registerDefaultHelpers(this);
361 | }
362 |
363 | exports.HandlebarsEnvironment = HandlebarsEnvironment;HandlebarsEnvironment.prototype = {
364 | constructor: HandlebarsEnvironment,
365 |
366 | logger: logger,
367 | log: log,
368 |
369 | registerHelper: function(name, fn) {
370 | if (toString.call(name) === objectType) {
371 | if (fn) { throw new Exception('Arg not supported with multiple helpers'); }
372 | Utils.extend(this.helpers, name);
373 | } else {
374 | this.helpers[name] = fn;
375 | }
376 | },
377 | unregisterHelper: function(name) {
378 | delete this.helpers[name];
379 | },
380 |
381 | registerPartial: function(name, partial) {
382 | if (toString.call(name) === objectType) {
383 | Utils.extend(this.partials, name);
384 | } else {
385 | this.partials[name] = partial;
386 | }
387 | },
388 | unregisterPartial: function(name) {
389 | delete this.partials[name];
390 | }
391 | };
392 |
393 | function registerDefaultHelpers(instance) {
394 | instance.registerHelper('helperMissing', function(/* [args, ]options */) {
395 | if(arguments.length === 1) {
396 | // A missing field in a {{foo}} constuct.
397 | return undefined;
398 | } else {
399 | // Someone is actually trying to call something, blow up.
400 | throw new Exception("Missing helper: '" + arguments[arguments.length-1].name + "'");
401 | }
402 | });
403 |
404 | instance.registerHelper('blockHelperMissing', function(context, options) {
405 | var inverse = options.inverse,
406 | fn = options.fn;
407 |
408 | if(context === true) {
409 | return fn(this);
410 | } else if(context === false || context == null) {
411 | return inverse(this);
412 | } else if (isArray(context)) {
413 | if(context.length > 0) {
414 | if (options.ids) {
415 | options.ids = [options.name];
416 | }
417 |
418 | return instance.helpers.each(context, options);
419 | } else {
420 | return inverse(this);
421 | }
422 | } else {
423 | if (options.data && options.ids) {
424 | var data = createFrame(options.data);
425 | data.contextPath = Utils.appendContextPath(options.data.contextPath, options.name);
426 | options = {data: data};
427 | }
428 |
429 | return fn(context, options);
430 | }
431 | });
432 |
433 | instance.registerHelper('each', function(context, options) {
434 | if (!options) {
435 | throw new Exception('Must pass iterator to #each');
436 | }
437 |
438 | var fn = options.fn, inverse = options.inverse;
439 | var i = 0, ret = "", data;
440 |
441 | var contextPath;
442 | if (options.data && options.ids) {
443 | contextPath = Utils.appendContextPath(options.data.contextPath, options.ids[0]) + '.';
444 | }
445 |
446 | if (isFunction(context)) { context = context.call(this); }
447 |
448 | if (options.data) {
449 | data = createFrame(options.data);
450 | }
451 |
452 | if(context && typeof context === 'object') {
453 | if (isArray(context)) {
454 | for(var j = context.length; i": ">",
810 | '"': """,
811 | "'": "'",
812 | "`": "`"
813 | };
814 |
815 | var badChars = /[&<>"'`]/g;
816 | var possible = /[&<>"'`]/;
817 |
818 | function escapeChar(chr) {
819 | return escape[chr];
820 | }
821 |
822 | function extend(obj /* , ...source */) {
823 | for (var i = 1; i < arguments.length; i++) {
824 | for (var key in arguments[i]) {
825 | if (Object.prototype.hasOwnProperty.call(arguments[i], key)) {
826 | obj[key] = arguments[i][key];
827 | }
828 | }
829 | }
830 |
831 | return obj;
832 | }
833 |
834 | exports.extend = extend;var toString = Object.prototype.toString;
835 | exports.toString = toString;
836 | // Sourced from lodash
837 | // https://github.com/bestiejs/lodash/blob/master/LICENSE.txt
838 | var isFunction = function(value) {
839 | return typeof value === 'function';
840 | };
841 | // fallback for older versions of Chrome and Safari
842 | /* istanbul ignore next */
843 | if (isFunction(/x/)) {
844 | isFunction = function(value) {
845 | return typeof value === 'function' && toString.call(value) === '[object Function]';
846 | };
847 | }
848 | var isFunction;
849 | exports.isFunction = isFunction;
850 | /* istanbul ignore next */
851 | var isArray = Array.isArray || function(value) {
852 | return (value && typeof value === 'object') ? toString.call(value) === '[object Array]' : false;
853 | };
854 | exports.isArray = isArray;
855 |
856 | function escapeExpression(string) {
857 | // don't escape SafeStrings, since they're already safe
858 | if (string instanceof SafeString) {
859 | return string.toString();
860 | } else if (string == null) {
861 | return "";
862 | } else if (!string) {
863 | return string + '';
864 | }
865 |
866 | // Force a string conversion as this will be done by the append regardless and
867 | // the regex test will do this transparently behind the scenes, causing issues if
868 | // an object's to string has escaped characters in it.
869 | string = "" + string;
870 |
871 | if(!possible.test(string)) { return string; }
872 | return string.replace(badChars, escapeChar);
873 | }
874 |
875 | exports.escapeExpression = escapeExpression;function isEmpty(value) {
876 | if (!value && value !== 0) {
877 | return true;
878 | } else if (isArray(value) && value.length === 0) {
879 | return true;
880 | } else {
881 | return false;
882 | }
883 | }
884 |
885 | exports.isEmpty = isEmpty;function appendContextPath(contextPath, id) {
886 | return (contextPath ? contextPath + '.' : '') + id;
887 | }
888 |
889 | exports.appendContextPath = appendContextPath;
890 | },{"./safe-string":6}],8:[function(require,module,exports){
891 | // Create a simple path alias to allow browserify to resolve
892 | // the runtime on a supported path.
893 | module.exports = require('./dist/cjs/handlebars.runtime');
894 |
895 | },{"./dist/cjs/handlebars.runtime":2}],9:[function(require,module,exports){
896 | module.exports = require("handlebars/runtime")["default"];
897 |
898 | },{"handlebars/runtime":8}],10:[function(require,module,exports){
899 | module.exports={
900 | "name": "phaser-debug",
901 | "version": "1.1.9",
902 | "description": "Simple debug module for phaser",
903 | "author": "Chad Engler ",
904 | "license": "MIT",
905 | "homepage": "https://github.com/englercj/phaser-debug",
906 | "repository": {
907 | "type": "git",
908 | "url": "https://github.com/englercj/phaser-debug.git"
909 | },
910 | "bugs": {
911 | "url": "https://github.com/englercj/phaser-debug/issues"
912 | },
913 | "keywords": [
914 | "phaser",
915 | "debug",
916 | "html5",
917 | "game",
918 | "engine"
919 | ],
920 | "dependencies": {
921 | "handlebars": "^2.0.0",
922 | "node-lessify": "^0.0.5",
923 | "hbsfy": "^2.1.0"
924 | },
925 | "devDependencies": {
926 | "browserify": "^5.11.1",
927 | "event-stream": "^3.1.7",
928 | "gulp": "^3.8.8",
929 | "gulp-bump": "^0.1.11",
930 | "gulp-git": "^0.5.3",
931 | "gulp-jshint": "^1.8.4",
932 | "gulp-util": "^3.0.1",
933 | "jshint-summary": "^0.4.0",
934 | "vinyl-source-stream": "^0.1.1",
935 | "watchify": "^1.0.2"
936 | },
937 | "main": "./dist/phaser-debug.js",
938 | "browser": "./src/index.js",
939 | "browserify": {
940 | "transform": [
941 | "hbsfy",
942 | "node-lessify"
943 | ],
944 | "transform-options": {
945 | "node-lessify": "textMode"
946 | }
947 | }
948 | }
949 |
950 | },{}],11:[function(require,module,exports){
951 | // hbsfy compiled Handlebars template
952 | var HandlebarsCompiler = require('hbsfy/runtime');
953 | module.exports = HandlebarsCompiler.template({"1":function(depth0,helpers,partials,data) {
954 | var stack1, lambda=this.lambda, escapeExpression=this.escapeExpression;
955 | return " \n "
956 | + escapeExpression(lambda(((stack1 = (depth0 != null ? depth0.children : depth0)) != null ? stack1.length : stack1), depth0))
957 | + "\n
\n";
958 | },"3":function(depth0,helpers,partials,data) {
959 | var stack1, buffer = " \n";
960 | stack1 = helpers['if'].call(depth0, ((stack1 = ((stack1 = ((stack1 = (depth0 != null ? depth0.texture : depth0)) != null ? stack1.baseTexture : stack1)) != null ? stack1.source : stack1)) != null ? stack1.src : stack1), {"name":"if","hash":{},"fn":this.program(4, data),"inverse":this.program(6, data),"data":data});
961 | if (stack1 != null) { buffer += stack1; }
962 | return buffer + "
\n";
963 | },"4":function(depth0,helpers,partials,data) {
964 | var stack1, lambda=this.lambda, escapeExpression=this.escapeExpression;
965 | return " "
968 | + escapeExpression(lambda(((stack1 = ((stack1 = ((stack1 = (depth0 != null ? depth0.texture : depth0)) != null ? stack1.baseTexture : stack1)) != null ? stack1.source : stack1)) != null ? stack1.src : stack1), depth0))
969 | + "\n";
970 | },"6":function(depth0,helpers,partials,data) {
971 | var stack1, lambda=this.lambda, escapeExpression=this.escapeExpression;
972 | return " "
973 | + escapeExpression(lambda(((stack1 = ((stack1 = (depth0 != null ? depth0.texture : depth0)) != null ? stack1.baseTexture : stack1)) != null ? stack1.source : stack1), depth0))
974 | + "\n";
975 | },"compiler":[6,">= 2.0.0-beta.1"],"main":function(depth0,helpers,partials,data) {
976 | var stack1, helper, functionType="function", helperMissing=helpers.helperMissing, escapeExpression=this.escapeExpression, lambda=this.lambda, buffer = "
\n\n\n"
977 | + escapeExpression(((helper = (helper = helpers.name || (depth0 != null ? depth0.name : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"name","hash":{},"data":data}) : helper)))
978 | + "\n
\n\n\n"
979 | + escapeExpression(((helper = (helper = helpers.typeString || (depth0 != null ? depth0.typeString : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"typeString","hash":{},"data":data}) : helper)))
980 | + "\n
\n\n\n"
981 | + escapeExpression(((helper = (helper = helpers.visible || (depth0 != null ? depth0.visible : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"visible","hash":{},"data":data}) : helper)))
982 | + "\n
\n\n\n"
983 | + escapeExpression(((helper = (helper = helpers.rotation || (depth0 != null ? depth0.rotation : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"rotation","hash":{},"data":data}) : helper)))
984 | + "\n
\n\n\n"
985 | + escapeExpression(lambda(((stack1 = (depth0 != null ? depth0.position : depth0)) != null ? stack1.x : stack1), depth0))
986 | + " x "
987 | + escapeExpression(lambda(((stack1 = (depth0 != null ? depth0.position : depth0)) != null ? stack1.y : stack1), depth0))
988 | + "\n
\n\n\n"
989 | + escapeExpression(lambda(((stack1 = (depth0 != null ? depth0.scale : depth0)) != null ? stack1.x : stack1), depth0))
990 | + " x "
991 | + escapeExpression(lambda(((stack1 = (depth0 != null ? depth0.scale : depth0)) != null ? stack1.y : stack1), depth0))
992 | + "\n
\n\n\n"
993 | + escapeExpression(((helper = (helper = helpers.alpha || (depth0 != null ? depth0.alpha : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"alpha","hash":{},"data":data}) : helper)))
994 | + "\n
\n\n
\n\n\n"
995 | + escapeExpression(((helper = (helper = helpers.worldVisible || (depth0 != null ? depth0.worldVisible : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"worldVisible","hash":{},"data":data}) : helper)))
996 | + "\n
\n\n\n"
997 | + escapeExpression(((helper = (helper = helpers.worldRotation || (depth0 != null ? depth0.worldRotation : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"worldRotation","hash":{},"data":data}) : helper)))
998 | + "\n
\n\n\n"
999 | + escapeExpression(lambda(((stack1 = (depth0 != null ? depth0.worldPosition : depth0)) != null ? stack1.x : stack1), depth0))
1000 | + " x "
1001 | + escapeExpression(lambda(((stack1 = (depth0 != null ? depth0.worldPosition : depth0)) != null ? stack1.y : stack1), depth0))
1002 | + "\n
\n\n\n"
1003 | + escapeExpression(lambda(((stack1 = (depth0 != null ? depth0.worldScale : depth0)) != null ? stack1.x : stack1), depth0))
1004 | + " x "
1005 | + escapeExpression(lambda(((stack1 = (depth0 != null ? depth0.worldScale : depth0)) != null ? stack1.y : stack1), depth0))
1006 | + "\n
\n\n\n"
1007 | + escapeExpression(((helper = (helper = helpers.worldAlpha || (depth0 != null ? depth0.worldAlpha : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"worldAlpha","hash":{},"data":data}) : helper)))
1008 | + "\n
\n\n
\n\n";
1009 | stack1 = helpers['if'].call(depth0, (depth0 != null ? depth0.children : depth0), {"name":"if","hash":{},"fn":this.program(1, data),"inverse":this.noop,"data":data});
1010 | if (stack1 != null) { buffer += stack1; }
1011 | buffer += "\n";
1012 | stack1 = helpers['if'].call(depth0, (depth0 != null ? depth0.texture : depth0), {"name":"if","hash":{},"fn":this.program(3, data),"inverse":this.noop,"data":data});
1013 | if (stack1 != null) { buffer += stack1; }
1014 | return buffer;
1015 | },"useData":true});
1016 |
1017 | },{"hbsfy/runtime":9}],12:[function(require,module,exports){
1018 | // hbsfy compiled Handlebars template
1019 | var HandlebarsCompiler = require('hbsfy/runtime');
1020 | module.exports = HandlebarsCompiler.template({"compiler":[6,">= 2.0.0-beta.1"],"main":function(depth0,helpers,partials,data) {
1021 | return "\n\nrefresh\n\n
\n";
1022 | },"useData":true});
1023 |
1024 | },{"hbsfy/runtime":9}],13:[function(require,module,exports){
1025 | // hbsfy compiled Handlebars template
1026 | var HandlebarsCompiler = require('hbsfy/runtime');
1027 | module.exports = HandlebarsCompiler.template({"1":function(depth0,helpers,partials,data) {
1028 | var helper, functionType="function", helperMissing=helpers.helperMissing, escapeExpression=this.escapeExpression;
1029 | return " ("
1030 | + escapeExpression(((helper = (helper = helpers.name || (depth0 != null ? depth0.name : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"name","hash":{},"data":data}) : helper)))
1031 | + ")\n";
1032 | },"3":function(depth0,helpers,partials,data) {
1033 | var stack1, buffer = " \n";
1034 | stack1 = helpers.each.call(depth0, (depth0 != null ? depth0.children : depth0), {"name":"each","hash":{},"fn":this.program(4, data),"inverse":this.noop,"data":data});
1035 | if (stack1 != null) { buffer += stack1; }
1036 | return buffer + "
\n";
1037 | },"4":function(depth0,helpers,partials,data) {
1038 | var stack1, buffer = "";
1039 | stack1 = this.invokePartial(partials.sceneTree, ' ', 'sceneTree', depth0, undefined, helpers, partials, data);
1040 | if (stack1 != null) { buffer += stack1; }
1041 | return buffer;
1042 | },"compiler":[6,">= 2.0.0-beta.1"],"main":function(depth0,helpers,partials,data) {
1043 | var stack1, helper, functionType="function", helperMissing=helpers.helperMissing, escapeExpression=this.escapeExpression, buffer = escapeExpression(((helper = (helper = helpers.listItemOpen || (depth0 != null ? depth0.listItemOpen : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"listItemOpen","hash":{},"data":data}) : helper)))
1044 | + "\n "
1045 | + escapeExpression(((helper = (helper = helpers.typeString || (depth0 != null ? depth0.typeString : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"typeString","hash":{},"data":data}) : helper)))
1046 | + "\n\n";
1047 | stack1 = helpers['if'].call(depth0, (depth0 != null ? depth0.name : depth0), {"name":"if","hash":{},"fn":this.program(1, data),"inverse":this.noop,"data":data});
1048 | if (stack1 != null) { buffer += stack1; }
1049 | buffer += "\n";
1050 | stack1 = helpers['if'].call(depth0, (depth0 != null ? depth0.children : depth0), {"name":"if","hash":{},"fn":this.program(3, data),"inverse":this.noop,"data":data});
1051 | if (stack1 != null) { buffer += stack1; }
1052 | return buffer + "\n";
1053 | },"usePartial":true,"useData":true});
1054 |
1055 | },{"hbsfy/runtime":9}],14:[function(require,module,exports){
1056 | var ui = require('../util/ui');
1057 |
1058 | function Panel(game, parent) {
1059 | this.game = game;
1060 | this.parent = parent;
1061 |
1062 | this.name = '';
1063 | this.title = '';
1064 | this.active = false;
1065 |
1066 | this._panel = null;
1067 | }
1068 |
1069 | Panel.prototype.constructor = Panel;
1070 |
1071 | module.exports = Panel;
1072 |
1073 | //builds the html for a panel
1074 | Panel.prototype.createPanelElement = function () {
1075 | var elm = this._panel = document.createElement('div');
1076 | ui.addClass(elm, 'pdebug-panel ' + this.name);
1077 |
1078 | return elm;
1079 | };
1080 |
1081 | //builds the html for this panels menu item
1082 | Panel.prototype.createMenuElement = function () {
1083 | var elm = this._menuItem = document.createElement('a');
1084 |
1085 | elm.href = '#' + this.name;
1086 |
1087 | ui.addClass(elm, 'pdebug-menu-item ' + this.name);
1088 | ui.setText(elm, this.title);
1089 |
1090 | return elm;
1091 | };
1092 |
1093 | Panel.prototype.toggle = function () {
1094 | if (this.active) {
1095 | this.hide();
1096 | } else {
1097 | this.show();
1098 | }
1099 | };
1100 |
1101 | Panel.prototype.show = function () {
1102 | this.active = true;
1103 | ui.setStyle(this._panel, 'display', 'block');
1104 | };
1105 |
1106 | Panel.prototype.hide = function () {
1107 | this.active = false;
1108 | ui.setStyle(this._panel, 'display', 'none');
1109 | };
1110 |
1111 | Panel.prototype.destroy = function () {
1112 | this.game = null;
1113 | this.parent = null;
1114 |
1115 | this.name = null;
1116 | this.title = null;
1117 | this.active = null;
1118 |
1119 | this._panel = null;
1120 | };
1121 |
1122 | },{"../util/ui":19}],15:[function(require,module,exports){
1123 | // TODO: Not measuring render time!!
1124 |
1125 | var Panel = require('./Panel'),
1126 | Graph = require('../util/Graph');
1127 |
1128 | function Performance(game, parent) {
1129 | Panel.call(this, game, parent);
1130 |
1131 | this.name = 'performance';
1132 | this.title = 'Performance';
1133 | this.eventQueue = [];
1134 |
1135 | this.graph = null;
1136 |
1137 | this.colorPalettes = {
1138 | _default: [
1139 | // Colors from: https://github.com/highslide-software/highcharts.com/blob/master/js/themes/grid.js
1140 | '#058DC7', '#50B432', '#ED561B', '#DDDF00',
1141 | '#24CBE5', '#64E572', '#FF9655', '#FFF263',
1142 | '#6AF9C4',
1143 | // Colors from: https://github.com/highslide-software/highcharts.com/blob/master/js/themes/dark-unica.js
1144 | '#2b908f', '#90ee7e', '#f45b5b', '#7798BF',
1145 | '#aaeeee', '#ff0066', '#eeaaee',
1146 | '#55BF3B', '#DF5353', '#7798BF', '#aaeeee'
1147 | ]
1148 | };
1149 | }
1150 |
1151 | Performance.prototype = Object.create(Panel.prototype);
1152 | Performance.prototype.constructor = Performance;
1153 |
1154 | module.exports = Performance;
1155 |
1156 | Performance.prototype.createPanelElement = function () {
1157 | var elm = Panel.prototype.createPanelElement.call(this);
1158 |
1159 | this.graph = new Graph(elm, window.innerWidth - 20, 256, this.colorPalettes._default);
1160 |
1161 | return elm;
1162 | };
1163 |
1164 | Performance.prototype.update = function () {
1165 | this.graph.addData(this.parent.timings, this.eventQueue.shift());
1166 | };
1167 |
1168 | Performance.prototype.mark = function (label) {
1169 | this.eventQueue.push(label);
1170 | };
1171 |
1172 | Performance.prototype.destroy = function () {
1173 | Panel.prototype.destroy.call(this);
1174 |
1175 | this.graph.destroy();
1176 |
1177 | this.eventQueue = null;
1178 | this.graph = null;
1179 | this.colorPalettes = null;
1180 | };
1181 |
1182 | },{"../util/Graph":18,"./Panel":14}],16:[function(require,module,exports){
1183 | var Panel = require('./Panel'),
1184 | ui = require('../util/ui'),
1185 | Handlebars = require('hbsfy/runtime');
1186 |
1187 | //require templates
1188 | var panelHtml = require('../hbs/scene/panel.hbs'),
1189 | detailsHtml = require('../hbs/scene/details.hbs'),
1190 | treeHtml = require('../hbs/scene/tree.hbs'),
1191 | _cache = {},
1192 | _id = 0;
1193 |
1194 | Handlebars.registerPartial('sceneDetails', detailsHtml);
1195 | Handlebars.registerPartial('sceneTree', treeHtml);
1196 | Handlebars.registerHelper('typeString', typeToString);
1197 | Handlebars.registerHelper('listItemOpen', listItemOpen);
1198 |
1199 | function Scene(game, parent) {
1200 | Panel.call(this, game, parent);
1201 |
1202 | this.name = 'scene';
1203 | this.title = 'Scene Tree';
1204 |
1205 | this._tree = null;
1206 |
1207 | this.tree = null;
1208 | this.details = null;
1209 | this.refresh = null;
1210 |
1211 | this.selected = null;
1212 | }
1213 |
1214 | Scene.prototype = Object.create(Panel.prototype);
1215 | Scene.prototype.constructor = Scene;
1216 |
1217 | module.exports = Scene;
1218 |
1219 | Scene.prototype.createPanelElement = function () {
1220 | Panel.prototype.createPanelElement.call(this);
1221 |
1222 | this._panel.innerHTML = panelHtml(this.game.stage);
1223 |
1224 | this.tree = this._panel.querySelector('.sidebar');
1225 | this.details = this._panel.querySelector('.details');
1226 | this.refresh = this._panel.querySelector('.refresh');
1227 |
1228 | ui.on(this.tree, 'click', 'li', this._onLiClick.bind(this));
1229 | ui.on(this.refresh, 'click', this._onRefreshClick.bind(this));
1230 |
1231 | this.bmd = this.game.add.bitmapData(512, 256);
1232 |
1233 | return this._panel;
1234 | };
1235 |
1236 | Scene.prototype.rebuildTree = function () {
1237 | ui.empty(this.tree);
1238 |
1239 | _cache = {};
1240 |
1241 | this.tree.innerHTML = treeHtml(this.game.stage);
1242 |
1243 | this.select(this.tree.querySelector('li:first-child'));
1244 | ui.addClass(this.selected, 'expanded');
1245 |
1246 | this.reloadDetails();
1247 | };
1248 |
1249 | Scene.prototype.reloadDetails = function () {
1250 | var id = this.selected.dataset.id;
1251 | var obj = _cache[id];
1252 |
1253 | this.details.innerHTML = detailsHtml(obj);
1254 |
1255 | if (obj.texture) {
1256 | this.details.appendChild(this.bmd.canvas);
1257 |
1258 | var w = Math.min(512, obj.width);
1259 | var h = Math.min(256, obj.height);
1260 |
1261 | this.bmd.clear();
1262 | this.bmd.resize(w, h);
1263 |
1264 | try {
1265 | this.bmd.draw(obj, 0, 0, w, h);
1266 | } catch (e) {};
1267 | }
1268 | };
1269 |
1270 | Scene.prototype.select = function (li) {
1271 | if (this.selected) {
1272 | ui.removeClass(this.selected, 'selected');
1273 | }
1274 |
1275 | this.selected = li;
1276 | ui.addClass(this.selected, 'selected');
1277 | };
1278 |
1279 | Scene.prototype.show = function () {
1280 | this.rebuildTree();
1281 |
1282 | Panel.prototype.show.call(this);
1283 | };
1284 |
1285 | Scene.prototype.destroy = function () {
1286 | Panel.prototype.destroy.call(this);
1287 |
1288 | this.tree = null;
1289 | this.details = null;
1290 | this.refresh = null;
1291 | };
1292 |
1293 | Scene.prototype._onLiClick = function (e) {
1294 | e.stopPropagation();
1295 |
1296 | this.select(e.delegateTarget);
1297 |
1298 | ui.toggleClass(e.delegateTarget, 'expanded');
1299 |
1300 | this.reloadDetails();
1301 | };
1302 |
1303 | Scene.prototype._onRefreshClick = function (e) {
1304 | e.preventDefault();
1305 | e.stopPropagation();
1306 |
1307 | this.rebuildTree();
1308 | };
1309 |
1310 | function listItemOpen () {
1311 | _cache[++_id] = this;
1312 |
1313 | return new Handlebars.SafeString(
1314 | ''
1315 | );
1316 | }
1317 |
1318 | function typeToString () {
1319 | var node = this;
1320 |
1321 | // If no phaser type defined, try to guess
1322 | if (node.type === undefined) {
1323 | // Phaser.Stage does not have its 'type' property defined, so check here.
1324 | if (node instanceof Phaser.Stage) {
1325 | return 'Stage';
1326 | }
1327 | // PIXI.Stage was removed in Phaser 2.4.4, so make sure it's defined first.
1328 | else if (typeof PIXI.Stage !== 'undefined' &&
1329 | node instanceof PIXI.Stage) {
1330 | return 'PIXI Stage';
1331 | }
1332 | else if (node instanceof PIXI.Sprite) {
1333 | return 'PIXI Sprite';
1334 | }
1335 | else if (node instanceof PIXI.DisplayObjectContainer) {
1336 | return 'PIXI DisplayObjectContainer';
1337 | }
1338 | else if (node instanceof PIXI.DisplayObject) {
1339 | return 'PIXI DisplayObject';
1340 | }
1341 | else {
1342 | return 'Unknown';
1343 | }
1344 | }
1345 | // return a string for the phaser type
1346 | else {
1347 | switch(node.type) {
1348 | case Phaser.SPRITE:
1349 | return 'Sprite';
1350 |
1351 | case Phaser.BUTTON:
1352 | return 'Button';
1353 |
1354 | case Phaser.IMAGE:
1355 | return 'Image';
1356 |
1357 | case Phaser.GRAPHICS:
1358 | return 'Graphics';
1359 |
1360 | case Phaser.TEXT:
1361 | return 'Text';
1362 |
1363 | case Phaser.TILESPRITE:
1364 | return 'Tile Sprite';
1365 |
1366 | case Phaser.BITMAPTEXT:
1367 | return 'Bitmap Text';
1368 |
1369 | case Phaser.GROUP:
1370 | return 'Group';
1371 |
1372 | case Phaser.RENDERTEXTURE:
1373 | return 'Render Texture';
1374 |
1375 | case Phaser.TILEMAP:
1376 | return 'Tilemap';
1377 |
1378 | case Phaser.TILEMAPLAYER:
1379 | return 'Tilemap Layer';
1380 |
1381 | case Phaser.EMITTER:
1382 | return 'Emitter';
1383 |
1384 | case Phaser.POLYGON:
1385 | return 'Polygon';
1386 |
1387 | case Phaser.BITMAPDATA:
1388 | return 'Bitmap Data';
1389 |
1390 | case Phaser.CANVAS_FILTER:
1391 | return 'Canvas Filter';
1392 |
1393 | case Phaser.WEBGL_FILTER:
1394 | return 'WebGL Filter';
1395 |
1396 | case Phaser.ELLIPSE:
1397 | return 'Ellipse';
1398 |
1399 | case Phaser.SPRITEBATCH:
1400 | return 'Sprite Batch';
1401 |
1402 | case Phaser.RETROFONT:
1403 | return 'Retro Font';
1404 |
1405 | case Phaser.POINTER:
1406 | return 'Pointer';
1407 |
1408 | case Phaser.ROPE:
1409 | return 'Rope';
1410 |
1411 | default:
1412 | return 'Unknown';
1413 | }
1414 | }
1415 | }
1416 |
1417 | },{"../hbs/scene/details.hbs":11,"../hbs/scene/panel.hbs":12,"../hbs/scene/tree.hbs":13,"../util/ui":19,"./Panel":14,"hbsfy/runtime":9}],17:[function(require,module,exports){
1418 | module.exports = ".pdebug{font-size:14px;position:fixed;bottom:0;width:100%;color:#aaa;background:#333;border-top:3px solid #00bf00;z-index:999999}.pdebug a{color:#00bf00}.pdebug label{display:inline-block;width:100px}.pdebug strong{font-weight:400;color:#fff}.pdebug .weak{color:#aaa}.pdebug .pdebug-menu{height:32px;padding:0 15px;text-shadow:1px 1px 0 #111;background:#333}.pdebug .pdebug-menu span{display:inline-block;height:32px;line-height:32px}.pdebug .pdebug-menu .pdebug-head{padding-right:25px;border-right:1px solid #666}.pdebug .pdebug-menu .pdebug-stats{float:right;padding:0 0 0 10px}.pdebug .pdebug-menu .pdebug-stats .pdebug-stats-item{display:inline-block;width:100px;text-align:right}.pdebug .pdebug-menu .pdebug-stats .pdebug-stats-item>span{color:#fff}.pdebug .pdebug-menu .pdebug-stats .pdebug-stats-item.obj{width:100px;border:0}.pdebug .pdebug-menu .pdebug-menu-item{color:#fff;display:inline-block;text-decoration:none;padding:0 10px;height:32px;line-height:32px;border-right:1px solid #666}.pdebug .pdebug-menu .pdebug-menu-item.active{color:#00bf00;background:#111}.pdebug .pdebug-panel{display:none;height:265px;overflow:auto;font-size:12px;background:#111}.pdebug .pdebug-panel.scene .sidebar{float:left;height:100%;min-width:175px;max-width:500px;resize:horizontal;overflow:auto}.pdebug .pdebug-panel.scene .details{float:left;height:100%}.pdebug .pdebug-panel.scene .refresh{position:absolute}.pdebug .pdebug-panel.scene>ul{padding:0;margin:0;border-right:solid 1px #aaa;margin-right:10px}.pdebug .pdebug-panel.scene>ul li{color:#fff;list-style:none;cursor:pointer}.pdebug .pdebug-panel.scene>ul li.expanded>ul{display:block}.pdebug .pdebug-panel.scene>ul li.selected{color:#00bf00}.pdebug .pdebug-panel.scene>ul li::before{content:\'-\';display:inline-block;width:12px;height:1px;color:#aaa}.pdebug .pdebug-panel.scene>ul li.has-children::before{content:\'\';display:inline-block;width:0;height:0;margin:0 6px 0 0;border-top:6px solid transparent;border-bottom:6px solid transparent;border-right:0;border-left:6px solid rgba(255,255,255,.3)}.pdebug .pdebug-panel.scene>ul li.has-children.expanded::before{margin:0 4px 0 -4px;border-top:6px solid rgba(255,255,255,.3);border-left:6px solid transparent;border-right:6px solid transparent;border-bottom:0}.pdebug .pdebug-panel.scene>ul li>ul{display:none;padding:0 0 0 10px}.pdebug input[type=checkbox]{visibility:hidden}.pdebug .checkbox{width:75px;height:26px;background:#333;position:relative;line-height:normal;-webkit-border-radius:50px;-moz-border-radius:50px;border-radius:50px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.5),0 1px 0 rgba(255,255,255,.2);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,.5),0 1px 0 rgba(255,255,255,.2);-o-box-shadow:inset 0 1px 1px rgba(0,0,0,.5),0 1px 0 rgba(255,255,255,.2);-ms-box-shadow:inset 0 1px 1px rgba(0,0,0,.5),0 1px 0 rgba(255,255,255,.2);box-shadow:inset 0 1px 1px rgba(0,0,0,.5),0 1px 0 rgba(255,255,255,.2)}.pdebug .checkbox:after{content:\'OFF\';font:12px/26px Arial,sans-serif;color:#000;position:absolute;right:10px;z-index:0;font-weight:700;text-shadow:1px 1px 0 rgba(255,255,255,.15)}.pdebug .checkbox:before{content:\'ON\';font:12px/26px Arial,sans-serif;color:#00bf00;position:absolute;left:10px;z-index:0;font-weight:700}.pdebug .checkbox+span{position:relative;display:block;top:-25px;left:90px;width:200px;color:#fcfff4;font-size:1.1em}.pdebug .checkbox input[type=checkbox]:checked+label{left:38px}.pdebug .checkbox label{display:block;width:34px;height:20px;-webkit-border-radius:50px;-moz-border-radius:50px;border-radius:50px;-webkit-transition:all .4s ease;-moz-transition:all .4s ease;-o-transition:all .4s ease;-ms-transition:all .4s ease;transition:all .4s ease;cursor:pointer;position:absolute;top:3px;left:3px;z-index:1;background:#fcfff4;background:-webkit-linear-gradient(top,#fcfff4 0,#dfe5d7 40%,#b3bead 100%);background:-moz-linear-gradient(top,#fcfff4 0,#dfe5d7 40%,#b3bead 100%);background:-o-linear-gradient(top,#fcfff4 0,#dfe5d7 40%,#b3bead 100%);background:-ms-linear-gradient(top,#fcfff4 0,#dfe5d7 40%,#b3bead 100%);background:linear-gradient(top,#fcfff4 0,#dfe5d7 40%,#b3bead 100%);-webkit-box-shadow:0 2px 5px 0 rgba(0,0,0,.3);-moz-box-shadow:0 2px 5px 0 rgba(0,0,0,.3);box-shadow:0 2px 5px 0 rgba(0,0,0,.3)}";
1419 | },{}],18:[function(require,module,exports){
1420 | // TODO: Move the legend into DOM?
1421 |
1422 | function Graph(container, width, height, colors, options) {
1423 | options = options || {};
1424 |
1425 | this.canvas = document.createElement('canvas');
1426 | this.canvas.width = width;
1427 | this.canvas.height = height;
1428 | container.appendChild(this.canvas);
1429 |
1430 | this.ctx = this.canvas.getContext('2d');
1431 |
1432 | this.labelStyle = 'rgba(200, 200, 200, 0.6)';
1433 |
1434 | this.maxValue = options.maxValue || 50;
1435 | this.padding = options.labelPadding || 5;
1436 |
1437 | this.dataLineWidth = options.lineWidth || 1;
1438 | this.legendWidth = 230;
1439 | this.legendBoxSize = 10;
1440 | this.legendIndent = 5;
1441 |
1442 | this.eventY = this.padding * 2;
1443 |
1444 | this.colors = colors;
1445 |
1446 | this.dataCanvas = document.createElement('canvas');
1447 | this.dataCanvas.width = width - this.legendWidth;
1448 | this.dataCanvas.height = height;
1449 | this.dctx = this.dataCanvas.getContext('2d');
1450 |
1451 | this.dataCanvasBuffer = document.createElement('canvas');
1452 | this.dataCanvasBuffer.width = this.dataCanvas.width - this.dataLineWidth;
1453 | this.dataCanvasBuffer.height = this.dataCanvas.height;
1454 | this.bctx = this.dataCanvasBuffer.getContext('2d');
1455 | }
1456 |
1457 | Graph.prototype.constructor = Graph;
1458 |
1459 | module.exports = Graph;
1460 |
1461 | // render the graph with the new data point
1462 | Graph.prototype.addData = function (values, event) {
1463 | // clear the main canvas
1464 | this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
1465 |
1466 | this.drawBg();
1467 | this.drawLegend(values);
1468 | this.drawData(values, event);
1469 | };
1470 |
1471 | Graph.prototype.drawBg = function () {
1472 | var fps60 = Math.floor(this.canvas.height - (this.canvas.height * (16 / this.maxValue))) + 0.5,
1473 | fps30 = Math.floor(this.canvas.height - (this.canvas.height * (33 / this.maxValue))) + 0.5;
1474 |
1475 | this.ctx.strokeStyle = this.ctx.fillStyle = this.labelStyle;
1476 | this.ctx.lineWidth = 1;
1477 |
1478 | //draw top marker line
1479 | this.ctx.beginPath();
1480 | this.ctx.moveTo(this.legendWidth, fps60);
1481 | this.ctx.lineTo(this.canvas.width, fps60);
1482 | this.ctx.stroke();
1483 |
1484 | this.ctx.fillText('16ms (60 fps)', this.legendWidth + this.padding, fps60 - this.padding);
1485 |
1486 | //draw the second marker line
1487 | this.ctx.beginPath();
1488 | this.ctx.moveTo(this.legendWidth, fps30);
1489 | this.ctx.lineTo(this.canvas.width, fps30);
1490 | this.ctx.stroke();
1491 |
1492 | this.ctx.fillText('33ms (30 fps)', this.legendWidth + this.padding, fps30 - this.padding);
1493 |
1494 | //draw baseline marker
1495 | this.ctx.beginPath();
1496 | this.ctx.moveTo(this.legendWidth, this.canvas.height - 0.5);
1497 | this.ctx.lineTo(this.canvas.width, this.canvas.height - 0.5);
1498 | this.ctx.stroke();
1499 | };
1500 |
1501 | Graph.prototype.drawLegend = function (values) {
1502 | var colorIndex = 0,
1503 | yIndex = 0,
1504 | x = this.padding,
1505 | y = 0;
1506 |
1507 | for (var k in values) {
1508 | y = (yIndex * this.legendBoxSize) + (this.padding * (yIndex + 1)) + this.padding;
1509 |
1510 | // Draw parent label
1511 | this.ctx.fillStyle = this.labelStyle;
1512 | this.ctx.fillText(k, x, y);
1513 |
1514 | ++yIndex;
1515 |
1516 | // Draw children
1517 | for (var c in values[k]) {
1518 | y = (yIndex * this.legendBoxSize) + (this.padding * yIndex);
1519 |
1520 | this.ctx.fillStyle = this.colors[colorIndex++ % this.colors.length];
1521 | this.ctx.fillRect(x + this.legendIndent, y, this.legendBoxSize, this.legendBoxSize);
1522 |
1523 | this.ctx.fillStyle = this.labelStyle;
1524 | this.ctx.fillText(
1525 | Math.round(values[k][c]) + 'ms - ' + c,
1526 | x + this.legendIndent + this.legendBoxSize + this.padding,
1527 | y + this.legendBoxSize
1528 | );
1529 |
1530 | ++yIndex;
1531 |
1532 | if (yIndex > 16) {
1533 | x += this.legendWidth / 2;
1534 | yIndex = 0;
1535 | }
1536 | }
1537 | }
1538 | };
1539 |
1540 | Graph.prototype.drawData = function (values, event) {
1541 | var x = this.dataCanvas.width - this.dataLineWidth + 0.5,
1542 | y = this.dataCanvas.height - 0.5;
1543 |
1544 | // clear the buffer
1545 | this.bctx.clearRect(0, 0, this.dataCanvasBuffer.width, this.dataCanvasBuffer.height);
1546 |
1547 | // draw the data canvas to the buffer, skipping the first line
1548 | this.bctx.drawImage(
1549 | this.dataCanvas,
1550 | this.dataLineWidth, 0, x, y,
1551 | 0, 0, x, y
1552 | );
1553 |
1554 | // clear the data canvas
1555 | this.dctx.clearRect(0, 0, this.dataCanvas.width, this.dataCanvas.height);
1556 |
1557 | // draw the buffer back to the data canvas
1558 | this.dctx.drawImage(this.dataCanvasBuffer, 0, 0);
1559 |
1560 | // draw event to the new line of the data canvas if there was one
1561 | if (event) {
1562 | this.dctx.beginPath();
1563 | this.dctx.strokeStyle = this.dctx.fillStyle = '#ff0000';
1564 | this.dctx.lineWidth = this.dataLineWidth;
1565 |
1566 | this.dctx.moveTo(x, y);
1567 | this.dctx.lineTo(x, 0);
1568 |
1569 | this.dctx.stroke();
1570 |
1571 | this.dctx.textAlign = 'right';
1572 | this.dctx.fillText(event, x - this.padding, this.eventY);
1573 |
1574 | this.eventY += (this.padding * 2);
1575 |
1576 | if (this.eventY > (this.dataCanvas.height / 2)) {
1577 | this.eventY = (this.padding * 2);
1578 | }
1579 | }
1580 |
1581 | // draws the data values to the new line of the data canvas
1582 |
1583 | // draw the new data points
1584 | var colorIndex = 0,
1585 | step = 0;
1586 |
1587 | for (var k in values) {
1588 | for (var c in values[k]) {
1589 | this.dctx.beginPath();
1590 | this.dctx.strokeStyle = this.dctx.fillStyle = this.colors[colorIndex++ % this.colors.length];
1591 | this.dctx.lineWidth = this.dataLineWidth;
1592 |
1593 | step = ((values[k][c] / this.maxValue) * this.dataCanvas.height);
1594 | step = step < 0 ? 0 : step;
1595 |
1596 | this.dctx.moveTo(x, y);
1597 | this.dctx.lineTo(x, y-=step);
1598 |
1599 | this.dctx.stroke();
1600 | }
1601 | }
1602 |
1603 | // draw the data canvas to the main rendered canvas
1604 | this.ctx.drawImage(this.dataCanvas, this.legendWidth, 0);
1605 | };
1606 |
1607 | Graph.prototype.destroy = function () {
1608 | this.canvas = null;
1609 | this.ctx = null;
1610 |
1611 | this.labelStyle = null;
1612 |
1613 | this.maxValue = null;
1614 | this.padding = null;
1615 |
1616 | this.dataLineWidth = null;
1617 | this.legendWidth = null;
1618 | this.legendBoxSize = null;
1619 | this.legendIndent = null;
1620 |
1621 | this.colors = null;
1622 |
1623 | this.dataCanvas = null;
1624 | this.dctx = null;
1625 |
1626 | this.dataCanvasBuffer = null;
1627 | this.bctx = null;
1628 | };
1629 |
1630 | },{}],19:[function(require,module,exports){
1631 | //Some general dom helpers
1632 | var ui = {
1633 | delegate: function (dom, evt, selector, fn) {
1634 | dom.addEventListener(evt, function(e) {
1635 | window.target = e.target;
1636 | if (e.target && e.target.matches(selector)) {
1637 | e.delegateTarget = e.target;
1638 |
1639 | if (fn) {
1640 | fn(e);
1641 | }
1642 | }
1643 | else if (e.target.parentElement && e.target.parentElement.matches(selector)) {
1644 | e.delegateTarget = e.target.parentElement;
1645 |
1646 | if (fn) {
1647 | fn(e);
1648 | }
1649 | }
1650 | });
1651 | },
1652 |
1653 | on: function (dom, evt, delegate, fn) {
1654 | if (typeof delegate === 'function') {
1655 | fn = delegate;
1656 | delegate = null;
1657 | }
1658 |
1659 | if (delegate) {
1660 | return ui.delegate(dom, evt, delegate, fn);
1661 | }
1662 |
1663 | dom.addEventListener(evt, fn);
1664 | },
1665 |
1666 | removeClass: function (dom, cls) {
1667 | var classes = dom.className.split(' '),
1668 | i = classes.indexOf(cls);
1669 |
1670 | if(i !== -1) {
1671 | classes.splice(i, 1);
1672 | dom.className = classes.join(' ').trim();
1673 | }
1674 | },
1675 |
1676 | addClass: function (dom, cls) {
1677 | var classes = dom.className.split(' ');
1678 |
1679 | classes.push(cls);
1680 | dom.className = classes.join(' ').trim();
1681 | },
1682 |
1683 | hasClass: function (dom, cls) {
1684 | return dom.className.split(' ').indexOf(cls) !== -1;
1685 | },
1686 |
1687 | toggleClass: function (dom, cls) {
1688 | if (ui.hasClass(dom, cls)) {
1689 | ui.removeClass(dom, cls);
1690 | } else {
1691 | ui.addClass(dom, cls);
1692 | }
1693 | },
1694 |
1695 | setText: function (dom, txt) {
1696 | dom.textContent = txt;
1697 | },
1698 |
1699 | setHtml: function (dom, html) {
1700 | dom.innerHTML = html;
1701 | },
1702 |
1703 | setStyle: function (dom, style, value) {
1704 | if(typeof style === 'string') {
1705 | dom.style[style] = value;
1706 | } else {
1707 | for(var key in style) {
1708 | dom.style[key] = style[key];
1709 | }
1710 | }
1711 | },
1712 |
1713 | empty: function (dom) {
1714 | while(dom.firstChild) {
1715 | dom.removeChild(dom.firstChild);
1716 | }
1717 | },
1718 |
1719 | show: function (dom) {
1720 | ui.setStyle(dom, 'display', 'block');
1721 | },
1722 |
1723 | hide: function (dom) {
1724 | ui.setStyle(dom, 'display', 'none');
1725 | },
1726 |
1727 | clear: function () {
1728 | var br = document.createElement('br');
1729 | ui.setStyle(br, 'clear', 'both');
1730 |
1731 | return br;
1732 | },
1733 |
1734 | addCss: function (css) {
1735 | var style = document.createElement('style');
1736 |
1737 | style.type = 'text/css';
1738 |
1739 | if (style.styleSheet){
1740 | style.styleSheet.cssText = css;
1741 | } else {
1742 | style.appendChild(document.createTextNode(css));
1743 | }
1744 |
1745 | document.head.appendChild(style);
1746 | }
1747 | };
1748 |
1749 | module.exports = ui;
1750 |
1751 | // polyfill for matchesSelector
1752 | if (!HTMLElement.prototype.matches) {
1753 | var htmlprot = HTMLElement.prototype;
1754 |
1755 | htmlprot.matches =
1756 | htmlprot.matches ||
1757 | htmlprot.webkitMatchesSelector ||
1758 | htmlprot.mozMatchesSelector ||
1759 | htmlprot.msMatchesSelector ||
1760 | htmlprot.oMatchesSelector ||
1761 | function (selector) {
1762 | // poorman's polyfill for matchesSelector
1763 | var elements = this.parentElement.querySelectorAll(selector),
1764 | element,
1765 | i = 0;
1766 |
1767 | while (element = elements[i++]) {
1768 | if (element === this) {
1769 | return true;
1770 | }
1771 | }
1772 |
1773 | return false;
1774 | };
1775 | }
1776 |
1777 | },{}]},{},[1])(1)
1778 | });
--------------------------------------------------------------------------------