├── .gitignore ├── demo ├── primary │ ├── cube │ │ ├── main.js │ │ └── index.html │ ├── pyramid │ │ ├── main.js │ │ └── index.html │ ├── brick │ │ ├── main.js │ │ └── index.html │ └── side │ │ ├── main.js │ │ └── index.html ├── advanced │ ├── flexible-cube │ │ ├── index.html │ │ └── main.js │ ├── gif-rendering │ │ ├── main.js │ │ └── index.html │ ├── input-text-rendering │ │ ├── index.html │ │ └── main.js │ └── flappy-bird │ │ ├── index.html │ │ └── main.js └── vendor │ ├── modernizr-2.6.2.min.js │ ├── dat.gui.min.js │ └── easeljs-0.6.1.min.js ├── src ├── namespace.js ├── geom │ ├── Point.js │ ├── Point3D.js │ └── Matrix.js ├── utils │ ├── CanvasTool.js │ ├── CanvasManager.js │ ├── ColorPattern.js │ └── ColorGeom.js ├── dimensions │ ├── PyramidDimension.js │ ├── SideXDimension.js │ ├── SideYDimension.js │ ├── BrickDimension.js │ ├── AbstractDimension.js │ └── CubeDimension.js ├── colors │ ├── SideColor.js │ ├── PyramidColor.js │ ├── AbstractColor.js │ └── CubeColor.js ├── display │ ├── PixelObject.js │ ├── PixelView.js │ └── BitmapData.js └── primitives │ ├── AbstractPrimitive.js │ ├── SideX.js │ ├── SideY.js │ ├── Brick.js │ ├── Cube.js │ └── Pyramid.js ├── bower.json ├── package.json ├── LICENSE ├── Gruntfile.js └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | /node_modules 3 | /.idea 4 | /local -------------------------------------------------------------------------------- /demo/primary/cube/main.js: -------------------------------------------------------------------------------- 1 | // get DOM or jQuery element 2 | // like: $('#canvas-demo') 3 | var canvas = document.getElementById('canvas-demo'); 4 | 5 | // create pixel view container in point 6 | var point = new obelisk.Point(500, 240); 7 | var pixelView = new obelisk.PixelView(canvas, point); 8 | 9 | // create cube 10 | var dimension = new obelisk.CubeDimension(120, 200, 60); 11 | var color = new obelisk.CubeColor().getByHorizontalColor(obelisk.ColorPattern.GRAY); 12 | var cube = new obelisk.Cube(dimension, color); 13 | //var cube = new obelisk.Cube(dimension, color, false); 14 | pixelView.renderObject(cube); 15 | -------------------------------------------------------------------------------- /demo/primary/pyramid/main.js: -------------------------------------------------------------------------------- 1 | // get DOM or jQuery element 2 | // like: $('#canvas-demo') 3 | var canvas = document.getElementById('canvas-demo'); 4 | 5 | // create pixel view container in point 6 | var point = new obelisk.Point(500, 240); 7 | var pixelView = new obelisk.PixelView(canvas, point); 8 | 9 | // create pyramid 10 | //var dimension = new obelisk.PyramidDimension(120, true); 11 | var dimension = new obelisk.PyramidDimension(120); 12 | var color = new obelisk.PyramidColor().getByRightColor(obelisk.ColorPattern.YELLOW); 13 | var pyramid = new obelisk.Pyramid(dimension, color); 14 | pixelView.renderObject(pyramid); 15 | -------------------------------------------------------------------------------- /src/namespace.js: -------------------------------------------------------------------------------- 1 | /*global window:true*/ 2 | 3 | /* 4 | * obelisk 5 | */ 6 | 7 | (function (window) { 8 | "use strict"; 9 | 10 | /** 11 | * Static class holding library specific information 12 | * the library. 13 | * @class obelisk 14 | **/ 15 | var obelisk = {}; 16 | 17 | /** 18 | * @property version 19 | * @type String 20 | * @static 21 | **/ 22 | obelisk.version = '1.0.2'; 23 | 24 | /** 25 | * @property author 26 | * @type String 27 | * @static 28 | **/ 29 | obelisk.author = 'max huang'; 30 | 31 | window.obelisk = obelisk; 32 | }(window)); 33 | -------------------------------------------------------------------------------- /demo/primary/brick/main.js: -------------------------------------------------------------------------------- 1 | // get DOM or jQuery element 2 | // like: $('#canvas-demo') 3 | var canvas = document.getElementById('canvas-demo'); 4 | 5 | // create pixel view container in point 6 | var point = new obelisk.Point(500, 20); 7 | var pixelView = new obelisk.PixelView(canvas, point); 8 | 9 | // create brick 10 | var color = new obelisk.SideColor().getByInnerColor(obelisk.ColorPattern.PINK); 11 | var dimension = new obelisk.BrickDimension(300, 400); 12 | var brick = new obelisk.Brick(dimension, color); 13 | 14 | // render in view 15 | pixelView.renderObject(brick); 16 | //var p3D = new obelisk.Point3D(20, 20, 0); 17 | //pixelView.renderObject(brick, p3D); 18 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name":"obelisk.js", 3 | "version":"1.0.2", 4 | "homepage":"https://github.com/nosir/obelisk.js", 5 | "authors":[ 6 | "max huang risonhuang@gmail.com" 7 | ], 8 | "description":"JavaScript Engine for Building Pixel Isometric Element with HTML5 Canvas", 9 | "main":"build/obelisk.min.js", 10 | "keywords":[ 11 | "javascript", 12 | "canvas", 13 | "pixel", 14 | "isometric", 15 | "game", 16 | "graphic", 17 | "art", 18 | "2.5D" 19 | ], 20 | "license":"MIT", 21 | "ignore":[ 22 | "**/.*", 23 | "node_modules", 24 | "bower_components", 25 | "test", 26 | "tests" 27 | ] 28 | } 29 | -------------------------------------------------------------------------------- /src/geom/Point.js: -------------------------------------------------------------------------------- 1 | /*global obelisk:true*/ 2 | 3 | /* 4 | * Point 5 | */ 6 | 7 | (function (obelisk) { 8 | "use strict"; 9 | 10 | var Point, p; 11 | Point = function (x, y) { 12 | this.initialize(x, y); 13 | }; 14 | p = Point.prototype; 15 | 16 | // public properties 17 | p.x = 0; 18 | p.y = 0; 19 | 20 | // constructor 21 | p.initialize = function (x, y) { 22 | this.x = (x === undefined ? 0 : x); 23 | this.y = (y === undefined ? 0 : y); 24 | return this; 25 | }; 26 | 27 | // public methods 28 | p.toString = function () { 29 | return "[Point x : " + this.x + ", y : " + this.y + "]"; 30 | }; 31 | 32 | // private methods 33 | 34 | obelisk.Point = Point; 35 | }(obelisk)); 36 | -------------------------------------------------------------------------------- /src/utils/CanvasTool.js: -------------------------------------------------------------------------------- 1 | /*global obelisk:true*/ 2 | 3 | /* 4 | * CanvasTool 5 | */ 6 | 7 | (function (obelisk) { 8 | "use strict"; 9 | 10 | var CanvasTool, p; 11 | 12 | CanvasTool = function () { 13 | throw new Error('CanvasTool is a static Class, cannot be instanced.'); 14 | }; 15 | p = CanvasTool; 16 | 17 | // public methods 18 | p.getPixel = function (imageData, x, y) { 19 | var data, index, r, g, b; 20 | data = imageData.data; 21 | index = (y * imageData.width + x) * 4; 22 | r = data[index]; 23 | g = data[index + 1]; 24 | b = data[index + 2]; 25 | 26 | return ((r << 16) | (g << 8) | b); 27 | }; 28 | 29 | p.toString = function () { 30 | return "[CanvasTool]"; 31 | }; 32 | 33 | obelisk.CanvasTool = CanvasTool; 34 | }(obelisk)); 35 | -------------------------------------------------------------------------------- /demo/primary/side/main.js: -------------------------------------------------------------------------------- 1 | // get DOM or jQuery element 2 | // like: $('#canvas-demo') 3 | var canvas = document.getElementById('canvas-demo'); 4 | 5 | // create pixel view container in point 6 | var point = new obelisk.Point(500, 200); 7 | var pixelView = new obelisk.PixelView(canvas, point); 8 | 9 | // create brick 10 | var colorX = new obelisk.SideColor().getByInnerColor(obelisk.ColorPattern.PINK); 11 | var colorY = new obelisk.SideColor().getByInnerColor(obelisk.ColorPattern.GRASS_GREEN); 12 | var dimensionX = new obelisk.SideXDimension(300, 100); 13 | var dimensionY = new obelisk.SideYDimension(300, 100); 14 | var sideX = new obelisk.SideX(dimensionX, colorX); 15 | var sideY = new obelisk.SideY(dimensionY, colorY); 16 | 17 | // render in view 18 | pixelView.renderObject(sideX); 19 | 20 | var p3DY = new obelisk.Point3D(0, 30, 0); 21 | pixelView.renderObject(sideY, p3DY); -------------------------------------------------------------------------------- /demo/primary/brick/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | obelisk.js Demo 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /demo/primary/cube/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | obelisk.js Demo 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /demo/primary/side/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | obelisk.js Demo 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/geom/Point3D.js: -------------------------------------------------------------------------------- 1 | /*global obelisk:true*/ 2 | 3 | /* 4 | * Point3D 5 | */ 6 | 7 | (function (obelisk) { 8 | "use strict"; 9 | 10 | var Point3D, p; 11 | Point3D = function (x, y, z) { 12 | this.initialize(x, y, z); 13 | }; 14 | p = Point3D.prototype; 15 | 16 | // public properties 17 | p.x = 0; 18 | p.y = 0; 19 | p.z = 0; 20 | 21 | // constructor 22 | p.initialize = function (x, y, z) { 23 | this.x = (x === undefined ? 0 : x); 24 | this.y = (y === undefined ? 0 : y); 25 | this.z = (z === undefined ? 0 : z); 26 | return this; 27 | }; 28 | 29 | // public methods 30 | p.toString = function () { 31 | return "[Point3D x : " + this.x + ", y : " + this.y + ", z: " + this.z + "]"; 32 | }; 33 | 34 | // private methods 35 | 36 | obelisk.Point3D = Point3D; 37 | }(obelisk)); 38 | -------------------------------------------------------------------------------- /demo/primary/pyramid/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | obelisk.js Demo 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/utils/CanvasManager.js: -------------------------------------------------------------------------------- 1 | /*global obelisk:true, document:true*/ 2 | 3 | /* 4 | * CanvasManager 5 | */ 6 | 7 | (function (obelisk, document) { 8 | "use strict"; 9 | 10 | var CanvasManager, p; 11 | CanvasManager = function () { 12 | throw new Error('ColorGeom is a static Class, cannot be instanced.'); 13 | }; 14 | p = CanvasManager; 15 | 16 | // public properties 17 | p.defaultCanvas = null; 18 | 19 | // public methods 20 | p.getDefaultCanvas = function () { 21 | p.defaultCanvas = p.defaultCanvas || document.createElement('canvas'); 22 | return p.defaultCanvas; 23 | }; 24 | 25 | p.getNewCanvas = function () { 26 | return document.createElement('canvas'); 27 | }; 28 | 29 | p.toString = function () { 30 | return "[CanvasManager]"; 31 | }; 32 | 33 | obelisk.CanvasManager = CanvasManager; 34 | }(obelisk, document)); 35 | -------------------------------------------------------------------------------- /demo/advanced/flexible-cube/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | obelisk.js Demo 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /src/dimensions/PyramidDimension.js: -------------------------------------------------------------------------------- 1 | /*global obelisk:true*/ 2 | 3 | /* 4 | * PyramidDimension 5 | */ 6 | 7 | (function (obelisk) { 8 | "use strict"; 9 | 10 | var PyramidDimension, p; 11 | PyramidDimension = function (axis, tall) { 12 | this.initialize(axis, tall); 13 | }; 14 | p = PyramidDimension.prototype = new obelisk.AbstractDimension(); 15 | 16 | // constructor 17 | p.initialize = function (axis, tall) { 18 | this.xAxis = axis || 30; 19 | this.yAxis = axis || 30; 20 | this.tall = tall || false; 21 | 22 | if (this.xAxis % 2 === 1) { 23 | throw new Error("axis must be even number"); 24 | } 25 | 26 | if (this.xAxis <= 4) { 27 | throw new Error("dimension is too small"); 28 | } 29 | 30 | return this; 31 | }; 32 | 33 | p.toString = function () { 34 | return "[PyramidDimension]"; 35 | }; 36 | 37 | obelisk.PyramidDimension = PyramidDimension; 38 | }(obelisk)); 39 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name":"obelisk.js", 3 | "version":"1.0.2", 4 | "description":"JavaScript Engine for Building Pixel Isometric Element with HTML5 Canvas", 5 | "main":"Gruntfile.js", 6 | "dependencies":{ 7 | "grunt":"~0.4.1" 8 | }, 9 | "devDependencies":{ 10 | "grunt-contrib-watch":"*", 11 | "grunt-contrib-concat":"*", 12 | "grunt-contrib-uglify":"*" 13 | }, 14 | "scripts":{ 15 | "test":"grunt test", 16 | "start":"" 17 | }, 18 | "repository":{ 19 | "type":"git", 20 | "url":"https://github.com/rison/obelisk.js.git" 21 | }, 22 | "keywords":[ 23 | "javascript", 24 | "canvas", 25 | "pixel", 26 | "isometric", 27 | "game", 28 | "graphic", 29 | "art", 30 | "2.5D" 31 | ], 32 | "author":"max huang risonhuang@gmail.com", 33 | "license":"MIT", 34 | "readmeFilename":"README.md", 35 | "gitHead":"23cba75da3465a1d207a9ffdfb20050bf9de2fdc" 36 | } 37 | -------------------------------------------------------------------------------- /src/dimensions/SideXDimension.js: -------------------------------------------------------------------------------- 1 | /*global obelisk:true*/ 2 | 3 | /* 4 | * SideXDimension 5 | */ 6 | 7 | (function (obelisk) { 8 | "use strict"; 9 | 10 | var SideXDimension, p; 11 | SideXDimension = function (xAxis, zAxis) { 12 | this.initialize(xAxis, zAxis); 13 | }; 14 | p = SideXDimension.prototype = new obelisk.AbstractDimension(); 15 | 16 | // constructor 17 | p.initialize = function (xAxis, zAxis) { 18 | this.xAxis = xAxis || 30; 19 | this.zAxis = zAxis || 30; 20 | 21 | if (this.xAxis % 2 === 1) { 22 | throw new Error("xAxis must be even number"); 23 | } 24 | 25 | // xAxis || zAxis = 4 floodFill could not be applied 26 | if (this.xAxis <= 4 || this.zAxis <= 2) { 27 | throw new Error("dimension is too small"); 28 | } 29 | 30 | return this; 31 | }; 32 | 33 | p.toString = function () { 34 | return "[SideXDimension]"; 35 | }; 36 | 37 | obelisk.SideXDimension = SideXDimension; 38 | }(obelisk)); 39 | -------------------------------------------------------------------------------- /src/dimensions/SideYDimension.js: -------------------------------------------------------------------------------- 1 | /*global obelisk:true*/ 2 | 3 | /* 4 | * SideYDimension 5 | */ 6 | 7 | (function (obelisk) { 8 | "use strict"; 9 | 10 | var SideYDimension, p; 11 | 12 | SideYDimension = function (yAxis, zAxis) { 13 | this.initialize(yAxis, zAxis); 14 | }; 15 | p = SideYDimension.prototype = new obelisk.AbstractDimension(); 16 | 17 | // constructor 18 | p.initialize = function (yAxis, zAxis) { 19 | this.yAxis = yAxis || 30; 20 | this.zAxis = zAxis || 30; 21 | 22 | if (this.yAxis % 2 === 1) { 23 | throw new Error("yAxis must be even number"); 24 | } 25 | 26 | // yAxis || zAxis = 4 floodFill could not be applied 27 | if (this.yAxis <= 4 || this.zAxis <= 2) { 28 | throw new Error("dimension is too small"); 29 | } 30 | 31 | return this; 32 | }; 33 | 34 | p.toString = function () { 35 | return "[SideYDimension]"; 36 | }; 37 | 38 | obelisk.SideYDimension = SideYDimension; 39 | }(obelisk)); 40 | -------------------------------------------------------------------------------- /src/dimensions/BrickDimension.js: -------------------------------------------------------------------------------- 1 | /*global obelisk:true*/ 2 | 3 | /* 4 | * BrickDimension 5 | */ 6 | 7 | (function (obelisk) { 8 | "use strict"; 9 | 10 | var BrickDimension, p; 11 | BrickDimension = function (xAxis, yAxis) { 12 | this.initialize(xAxis, yAxis); 13 | }; 14 | p = BrickDimension.prototype = new obelisk.AbstractDimension(); 15 | 16 | // constructor 17 | p.initialize = function (xAxis, yAxis) { 18 | this.xAxis = xAxis || 30; 19 | this.yAxis = yAxis || 30; 20 | 21 | if (this.xAxis % 2 === 1 || this.yAxis % 2 === 1) { 22 | throw new Error("x,yAxis must be even number"); 23 | } 24 | 25 | // xAxis || yAxis = 4 floodFill could not be applied 26 | if (this.xAxis <= 4 || this.yAxis <= 4) { 27 | throw new Error("dimension is too small"); 28 | } 29 | 30 | return this; 31 | }; 32 | 33 | p.toString = function () { 34 | return "[BrickDimension]"; 35 | }; 36 | 37 | obelisk.BrickDimension = BrickDimension; 38 | }(obelisk)); 39 | -------------------------------------------------------------------------------- /src/dimensions/AbstractDimension.js: -------------------------------------------------------------------------------- 1 | /*global obelisk:true*/ 2 | 3 | /* 4 | * AbstractDimension 5 | */ 6 | 7 | (function (obelisk) { 8 | "use strict"; 9 | 10 | var AbstractDimension, p; 11 | AbstractDimension = function () { 12 | this.initialize(); 13 | }; 14 | p = AbstractDimension.prototype; 15 | 16 | // public properties 17 | /** 18 | * The x Axis dimensions in 22.6 degrees coordinate 19 | */ 20 | p.xAxis = null; 21 | 22 | /** 23 | * The y Axis dimensions in 22.6 degrees coordinate 24 | */ 25 | p.yAxis = null; 26 | 27 | /** 28 | * The z Axis dimensions in 22.6 degrees coordinate 29 | */ 30 | p.zAxis = null; 31 | 32 | /** 33 | * Pyramid tall mode 34 | */ 35 | p.tall = false; 36 | 37 | // constructor 38 | p.initialize = function () { 39 | return this; 40 | }; 41 | 42 | // public methods 43 | p.toString = function () { 44 | return "[AbstractDimension]"; 45 | }; 46 | 47 | // private methods 48 | 49 | obelisk.AbstractDimension = AbstractDimension; 50 | }(obelisk)); 51 | -------------------------------------------------------------------------------- /src/colors/SideColor.js: -------------------------------------------------------------------------------- 1 | /*global obelisk:true*/ 2 | 3 | /* 4 | * SideColor 5 | */ 6 | 7 | (function (obelisk) { 8 | "use strict"; 9 | 10 | var SideColor, p; 11 | SideColor = function (border, inner) { 12 | this.initialize(border, inner); 13 | }; 14 | p = SideColor.prototype = new obelisk.AbstractColor(); 15 | 16 | // public properties 17 | p.BRIGHTNESS_GAIN = -20; 18 | 19 | // constructor 20 | p.initialize = function (border, inner) { 21 | this.border = obelisk.ColorGeom.get32(border === undefined ? 0x878787 : border); 22 | this.inner = obelisk.ColorGeom.get32(inner === undefined ? 0xEEEEEE : inner); 23 | return this; 24 | }; 25 | 26 | // public methods 27 | p.getByInnerColor = function (inner) { 28 | return new obelisk.SideColor( 29 | obelisk.ColorGeom.applyBrightness(inner, this.BRIGHTNESS_GAIN * 4), 30 | inner 31 | ); 32 | }; 33 | 34 | p.toString = function () { 35 | return "[SideColor]"; 36 | }; 37 | 38 | // private methods 39 | 40 | obelisk.SideColor = SideColor; 41 | }(obelisk)); 42 | -------------------------------------------------------------------------------- /src/dimensions/CubeDimension.js: -------------------------------------------------------------------------------- 1 | /*global obelisk:true*/ 2 | 3 | /* 4 | * CubeDimension 5 | */ 6 | 7 | (function (obelisk) { 8 | "use strict"; 9 | 10 | var CubeDimension, p; 11 | CubeDimension = function (xAxis, yAxis, zAxis) { 12 | this.initialize(xAxis, yAxis, zAxis); 13 | }; 14 | p = CubeDimension.prototype = new obelisk.AbstractDimension(); 15 | 16 | // constructor 17 | p.initialize = function (xAxis, yAxis, zAxis) { 18 | this.xAxis = xAxis || 30; 19 | this.yAxis = yAxis || 30; 20 | this.zAxis = zAxis || 30; 21 | 22 | if (this.xAxis % 2 === 1 || this.yAxis % 2 === 1) { 23 | throw new Error("x,yAxis must be even number"); 24 | } 25 | 26 | // xAxis || yAxis = 4 floodFill could not be applied 27 | if (this.xAxis <= 4 || this.yAxis <= 4 || this.zAxis <= 2) { 28 | throw new Error("dimension is too small"); 29 | } 30 | 31 | return this; 32 | }; 33 | 34 | p.toString = function () { 35 | return "[CubeDimension]"; 36 | }; 37 | 38 | obelisk.CubeDimension = CubeDimension; 39 | }(obelisk)); 40 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013 Max Huang 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | 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, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /src/display/PixelObject.js: -------------------------------------------------------------------------------- 1 | /*global obelisk:true*/ 2 | 3 | /* 4 | * PixelObject 5 | */ 6 | 7 | (function (obelisk) { 8 | "use strict"; 9 | 10 | var PixelObject, p; 11 | PixelObject = function (primitive, point3D) { 12 | this.initialize(primitive, point3D); 13 | }; 14 | p = PixelObject.prototype; 15 | 16 | // public properties 17 | p.x = null; 18 | p.y = null; 19 | p.canvas = null; 20 | 21 | // constructor 22 | p.initialize = function (primitive, point3D) { 23 | if (!primitive) { 24 | throw new Error("Primitive is not defined"); 25 | } 26 | 27 | var p3D = point3D || new obelisk.Point3D(); 28 | 29 | this.canvas = primitive.canvas; 30 | this.x = primitive.matrix.tx + p3D.x - p3D.y; 31 | this.y = primitive.matrix.ty + Math.floor(p3D.x / 2 + p3D.y / 2) - p3D.z; 32 | 33 | return this; 34 | }; 35 | 36 | // public methods 37 | 38 | // todo: add canvas remove method 39 | 40 | p.toString = function () { 41 | return "[PixelObject]"; 42 | }; 43 | 44 | // private methods 45 | 46 | obelisk.PixelObject = PixelObject; 47 | }(obelisk)); 48 | -------------------------------------------------------------------------------- /src/utils/ColorPattern.js: -------------------------------------------------------------------------------- 1 | /*global obelisk:true*/ 2 | 3 | /* 4 | * ColorPattern 5 | */ 6 | 7 | (function (obelisk) { 8 | "use strict"; 9 | 10 | var ColorPattren, p; 11 | 12 | ColorPattren = function () { 13 | throw new Error('ColorGeom is a static Class, cannot be instanced.'); 14 | }; 15 | p = ColorPattren; 16 | 17 | // public properties 18 | p.GRASS_GREEN = 0xCCFF00; 19 | p.YELLOW = 0xFFFF00; 20 | p.WINE_RED = 0xFF0099; 21 | p.PINK = 0xFF7CBF; 22 | p.PURPLE = 0xCC00FF; 23 | p.BLUE = 0x00CCFF; 24 | p.GRAY = 0xEEEEEE; 25 | p.BLACK = 0x666666; 26 | p.FINE_COLORS = 27 | [ 28 | p.GRASS_GREEN, 29 | p.YELLOW, 30 | p.WINE_RED, 31 | p.PINK, 32 | p.PURPLE, 33 | p.BLUE, 34 | p.GRAY, 35 | p.BLACK 36 | ]; 37 | 38 | // public methods 39 | p.getRandomComfortableColor = function () { 40 | return p.FINE_COLORS[Math.floor(Math.random() * p.FINE_COLORS.length)]; 41 | }; 42 | 43 | p.toString = function () { 44 | return "[ColorPattern]"; 45 | }; 46 | 47 | obelisk.ColorPattern = ColorPattren; 48 | }(obelisk)); 49 | -------------------------------------------------------------------------------- /src/display/PixelView.js: -------------------------------------------------------------------------------- 1 | /*global obelisk:true, jQuery:true*/ 2 | 3 | /* 4 | * PixelView 5 | */ 6 | 7 | (function (obelisk) { 8 | "use strict"; 9 | 10 | var PixelView, p; 11 | PixelView = function (canvas, point) { 12 | this.initialize(canvas, point); 13 | }; 14 | p = PixelView.prototype; 15 | 16 | // public properties 17 | p.canvas = null; 18 | p.context = null; 19 | p.point = null; 20 | 21 | // constructor 22 | p.initialize = function (canvas, point) { 23 | if (!canvas) { 24 | throw new Error("Canvas is not defined"); 25 | } 26 | 27 | try { 28 | if (canvas instanceof jQuery) { 29 | canvas = canvas.get(0); 30 | } 31 | } catch (e) { 32 | } 33 | 34 | this.canvas = canvas; 35 | this.context = this.canvas.getContext('2d'); 36 | this.point = point || new obelisk.Point(0, 0); 37 | 38 | return this; 39 | }; 40 | 41 | // public methods 42 | p.renderObject = function (primitive, point3D) { 43 | var po = new obelisk.PixelObject(primitive, point3D); 44 | this.context.drawImage(po.canvas, this.point.x + po.x, this.point.y + po.y); 45 | }; 46 | 47 | p.clear = function () { 48 | this.context.clearRect(0, 0, this.canvas.width, this.canvas.height); 49 | }; 50 | 51 | p.toString = function () { 52 | return "[PixelView]"; 53 | }; 54 | 55 | obelisk.PixelView = PixelView; 56 | }(obelisk)); 57 | -------------------------------------------------------------------------------- /src/colors/PyramidColor.js: -------------------------------------------------------------------------------- 1 | /*global obelisk:true*/ 2 | 3 | /* 4 | * PyramidColor 5 | */ 6 | 7 | (function (obelisk) { 8 | "use strict"; 9 | 10 | var PyramidColor, p; 11 | PyramidColor = function (border, borderHighlight, left, right) { 12 | this.initialize(border, borderHighlight, left, right); 13 | }; 14 | p = PyramidColor.prototype = new obelisk.AbstractColor(); 15 | 16 | // public properties 17 | p.BRIGHTNESS_GAIN = -20; 18 | 19 | // constructor 20 | p.initialize = function (border, borderHighlight, left, right) { 21 | this.border = obelisk.ColorGeom.get32(border === undefined ? 0x949698 : border); 22 | this.borderHighlight = obelisk.ColorGeom.get32(borderHighlight === undefined ? 0xFFFFFF : borderHighlight); 23 | this.left = obelisk.ColorGeom.get32(left === undefined ? 0xE6E8E9 : left); 24 | this.right = obelisk.ColorGeom.get32(right === undefined ? 0xEEEFF0 : right); 25 | return this; 26 | }; 27 | 28 | // public methods 29 | p.getByRightColor = function (right) { 30 | return new PyramidColor( 31 | obelisk.ColorGeom.applyBrightness(right, this.BRIGHTNESS_GAIN * 4), 32 | //apply hightlight 33 | obelisk.ColorGeom.applyBrightness(right, 0, true), 34 | obelisk.ColorGeom.applyBrightness(right, this.BRIGHTNESS_GAIN), 35 | right 36 | ); 37 | }; 38 | 39 | p.toString = function () { 40 | return "[PyramidColor]"; 41 | }; 42 | 43 | // private methods 44 | 45 | obelisk.PyramidColor = PyramidColor; 46 | }(obelisk)); 47 | -------------------------------------------------------------------------------- /demo/advanced/flexible-cube/main.js: -------------------------------------------------------------------------------- 1 | var canvas = document.getElementById('canvas-demo'); 2 | 3 | var point = new obelisk.Point(500, 200); 4 | var pixelView = new obelisk.PixelView(canvas, point); 5 | 6 | function buildCube(xDimension, yDimension, zDimension, border) { 7 | var color = new obelisk.CubeColor().getByHorizontalColor(obelisk.ColorPattern.GRASS_GREEN); 8 | var dimension = new obelisk.CubeDimension(xDimension, yDimension, zDimension); 9 | var cube = new obelisk.Cube(dimension, color, border); 10 | pixelView.clear(); 11 | pixelView.renderObject(cube); 12 | } 13 | 14 | // control bar 15 | var ControlBar = function () { 16 | this.xDimension = 80; 17 | this.yDimension = 120; 18 | this.zDimension = 50; 19 | this.border = true; 20 | }; 21 | 22 | var con = new ControlBar(); 23 | var gui = new dat.GUI(); 24 | 25 | var conX = gui.add(con, 'xDimension', 6, 400).step(2); 26 | conX.onChange(function (value) { 27 | buildCube(value, con.yDimension, con.zDimension, con.border); 28 | }); 29 | 30 | var conY = gui.add(con, 'yDimension', 6, 400).step(2); 31 | conY.onChange(function (value) { 32 | buildCube(con.xDimension, value, con.zDimension, con.border); 33 | }); 34 | 35 | var conZ = gui.add(con, 'zDimension', 6, 400).step(2); 36 | conZ.onChange(function (value) { 37 | buildCube(con.xDimension, con.yDimension, value, con.border); 38 | }); 39 | 40 | var conBorder = gui.add(con, 'border'); 41 | conBorder.onChange(function (value) { 42 | buildCube(con.xDimension, con.yDimension, con.zDimension, value); 43 | }); 44 | 45 | // build first one 46 | buildCube(con.xDimension, con.yDimension, con.zDimension, con.border); 47 | -------------------------------------------------------------------------------- /src/colors/AbstractColor.js: -------------------------------------------------------------------------------- 1 | /*global obelisk:true*/ 2 | 3 | /* 4 | * AbstractColor 5 | */ 6 | 7 | (function (obelisk) { 8 | "use strict"; 9 | 10 | var AbstractColor, p; 11 | 12 | AbstractColor = function () { 13 | this.initialize(); 14 | }; 15 | p = AbstractColor.prototype; 16 | 17 | // public properties 18 | /** 19 | * The inner colors for elements of certain primitive 20 | */ 21 | p.inner = null; 22 | 23 | /** 24 | * The border colors for elements of certain primitive 25 | */ 26 | p.border = null; 27 | 28 | /** 29 | * The borderHighlight colors for elements of certain primitive 30 | */ 31 | p.borderHighlight = null; 32 | 33 | /** 34 | * The left side colors for elements of certain primitive 35 | */ 36 | p.left = null; 37 | 38 | /** 39 | * The right side colors for elements of certain primitive 40 | */ 41 | p.right = null; 42 | 43 | /** 44 | * The horizontal colors for elements of certain primitive 45 | */ 46 | p.horizontal = null; 47 | 48 | /** 49 | * The left slot side colors for elements of certain primitive 50 | */ 51 | p.leftSlope = null; 52 | 53 | /** 54 | * The right slot side colors for elements of certain primitive 55 | */ 56 | p.rightSlope = null; 57 | 58 | // constructor 59 | p.initialize = function () { 60 | return this; 61 | }; 62 | 63 | // public methods 64 | p.toString = function () { 65 | return "[AbstractColor]"; 66 | }; 67 | 68 | // private methods 69 | 70 | obelisk.AbstractColor = AbstractColor; 71 | }(obelisk)); 72 | -------------------------------------------------------------------------------- /Gruntfile.js: -------------------------------------------------------------------------------- 1 | /* global module:false */ 2 | module.exports = function (grunt) { 3 | 4 | // Project configuration 5 | grunt.initConfig({ 6 | pkg:grunt.file.readJSON('package.json'), 7 | meta:{ 8 | banner:'/*!\n' + 9 | ' * obelisk.js <%= pkg.version %>\n' + 10 | ' * https://github.com/nosir/obelisk.js\n' + 11 | ' * MIT licensed\n' + 12 | ' *\n' + 13 | ' * Copyright (C) 2012 Max Huang https://github.com/nosir/\n' + 14 | ' */', 15 | version:'<%= pkg.version %>' 16 | }, 17 | 18 | concat:{ 19 | core:{ 20 | src:[ 21 | 'src/namespace.js', 22 | 'src/*/**/*.js' 23 | ], 24 | dest:'build/obelisk.js' 25 | } 26 | }, 27 | 28 | uglify:{ 29 | options:{ 30 | banner:'<%= meta.banner %>\n' 31 | }, 32 | build:{ 33 | src:'<%= concat.core.dest %>', 34 | dest:'build/obelisk.min.js' 35 | } 36 | }, 37 | 38 | watch:{ 39 | scripts:{ 40 | files:[ 41 | 'src/**/*.js' 42 | ], 43 | tasks:['concat'] 44 | } 45 | } 46 | }); 47 | 48 | // Dependencies 49 | grunt.loadNpmTasks('grunt-contrib-watch'); 50 | grunt.loadNpmTasks('grunt-contrib-concat'); 51 | grunt.loadNpmTasks('grunt-contrib-uglify'); 52 | 53 | // Default task 54 | grunt.registerTask('default', [ 'concat', 'uglify']); 55 | 56 | }; 57 | -------------------------------------------------------------------------------- /src/geom/Matrix.js: -------------------------------------------------------------------------------- 1 | /*global obelisk:true*/ 2 | 3 | /* 4 | * Matrix 5 | */ 6 | 7 | (function (obelisk) { 8 | "use strict"; 9 | 10 | var Matrix, p; 11 | Matrix = function (a, b, c, d, tx, ty) { 12 | this.initialize(a, b, c, d, tx, ty); 13 | }; 14 | p = Matrix.prototype; 15 | 16 | // public properties: 17 | /** 18 | * Position (0, 0) in a 3x3 matrix. 19 | * @property a 20 | * @type Number 21 | **/ 22 | p.a = 1; 23 | 24 | /** 25 | * Position (0, 1) in a 3x3 matrix. 26 | * @property b 27 | * @type Number 28 | **/ 29 | p.b = 0; 30 | 31 | /** 32 | * Position (1, 0) in a 3x3 matrix. 33 | * @property c 34 | * @type Number 35 | **/ 36 | p.c = 0; 37 | 38 | /** 39 | * Position (1, 1) in a 3x3 matrix. 40 | * @property d 41 | * @type Number 42 | **/ 43 | p.d = 1; 44 | 45 | /** 46 | * Position (2, 0) in a 3x3 matrix. 47 | * @property tx 48 | * @type Number 49 | **/ 50 | p.tx = 0; 51 | 52 | /** 53 | * Position (2, 1) in a 3x3 matrix. 54 | * @property ty 55 | * @type Number 56 | **/ 57 | p.ty = 0; 58 | 59 | // constructor 60 | p.initialize = function (a, b, c, d, tx, ty) { 61 | this.a = (a === undefined) ? 1 : a; 62 | this.b = b || 0; 63 | this.c = c || 0; 64 | this.d = (d === undefined) ? 1 : d; 65 | this.tx = tx || 0; 66 | this.ty = ty || 0; 67 | return this; 68 | }; 69 | 70 | // public methods 71 | p.toString = function () { 72 | return "[Matrix]"; 73 | }; 74 | 75 | obelisk.Matrix = Matrix; 76 | }(obelisk)); 77 | -------------------------------------------------------------------------------- /src/utils/ColorGeom.js: -------------------------------------------------------------------------------- 1 | /*global obelisk:true*/ 2 | 3 | /* 4 | * ColorGeom 5 | */ 6 | 7 | (function (obelisk) { 8 | "use strict"; 9 | 10 | var ColorGeom, p; 11 | 12 | ColorGeom = function () { 13 | throw new Error('ColorGeom is a static Class, cannot be instanced.'); 14 | }; 15 | p = ColorGeom; 16 | 17 | // public methods 18 | p.get32 = function (color) { 19 | return color < 0xFF000000 ? (color + 0xFF000000) : color; 20 | }; 21 | 22 | p.applyBrightness = function (color, brightness, highlight) { 23 | var a, r, g, b, y, v, u; 24 | a = ((color >>> 24) & 0x000000FF); 25 | r = ((color >>> 16) & 0x000000FF); 26 | g = ((color >>> 8) & 0x000000FF); 27 | b = (color & 0x000000FF); 28 | 29 | y = ((r * 313524) >> 20) + ((g * 615514) >> 20) + ((b * 119538) >> 20); 30 | u = -((155189 * r) >> 20) - ((303038 * g) >> 20) + ((458227 * b) >> 20); 31 | v = ((644874 * r) >> 20) - ((540016 * g) >> 20) - ((104857 * b) >> 20); 32 | 33 | if (!highlight) { 34 | y += brightness; 35 | } else { 36 | y = 60 + Math.pow(y, 1.2); 37 | } 38 | 39 | r = y + ((1195376 * v) >> 20); 40 | g = y - ((408944 * u) >> 20) - ((608174 * v) >> 20); 41 | b = y + ((2128609 * u) >> 20); 42 | 43 | r = Math.max(0, Math.min(r, 255)); 44 | g = Math.max(0, Math.min(g, 255)); 45 | b = Math.max(0, Math.min(b, 255)); 46 | 47 | return (a << 24) | (r << 16) | (g << 8) | b; 48 | }; 49 | 50 | p.toString = function () { 51 | return "[ColorGeom]"; 52 | }; 53 | 54 | obelisk.ColorGeom = ColorGeom; 55 | }(obelisk)); 56 | -------------------------------------------------------------------------------- /src/primitives/AbstractPrimitive.js: -------------------------------------------------------------------------------- 1 | /*global obelisk:true*/ 2 | 3 | /* 4 | * AbstractPrimitive 5 | */ 6 | 7 | (function (obelisk) { 8 | "use strict"; 9 | 10 | var AbstractPrimitive, p; 11 | AbstractPrimitive = function () { 12 | this.initialize(); 13 | }; 14 | p = AbstractPrimitive.prototype; 15 | 16 | // public properties 17 | /** 18 | * the canvas for drawImage to any canvas 19 | */ 20 | p.canvas = null; 21 | 22 | // protect properties 23 | /** 24 | * the width of the bitmap in 2d flash coordinate 25 | */ 26 | p.w = null; 27 | 28 | /** 29 | * the height of the bitmap in 2d flash coordinate 30 | */ 31 | p.h = null; 32 | 33 | /** 34 | * the dimension of primitive in 3d pixel coordinate 35 | */ 36 | p.dimension = null; 37 | 38 | /** 39 | * the color obj of the primitive 40 | */ 41 | p.color = null; 42 | 43 | /** 44 | * the border option of the primitive 45 | */ 46 | p.border = null; 47 | 48 | /** 49 | * the source bitmapdata contains pixel graphic 50 | */ 51 | p.bitmapData = null; 52 | 53 | /** 54 | * the preserve canvas option 55 | */ 56 | p.useDefaultCanvas = null; 57 | 58 | /** 59 | * the matrix offset between the bitmap and the 3d pixel coordinate ZERO point 60 | */ 61 | p.matrix = null; 62 | 63 | // constructor 64 | p.initialize = function () { 65 | return this; 66 | }; 67 | 68 | // public methods 69 | p.toString = function () { 70 | return "[AbstractPrimitive]"; 71 | }; 72 | 73 | // private methods 74 | 75 | obelisk.AbstractPrimitive = AbstractPrimitive; 76 | }(obelisk)); 77 | -------------------------------------------------------------------------------- /src/colors/CubeColor.js: -------------------------------------------------------------------------------- 1 | /*global obelisk:true*/ 2 | 3 | /* 4 | * CubeColor 5 | */ 6 | 7 | (function (obelisk) { 8 | "use strict"; 9 | 10 | var CubeColor, p; 11 | CubeColor = function (border, borderHighlight, left, right, horizontal) { 12 | this.initialize(border, borderHighlight, left, right, horizontal); 13 | }; 14 | p = CubeColor.prototype = new obelisk.AbstractColor(); 15 | 16 | // public properties 17 | p.BRIGHTNESS_GAIN = -20; 18 | 19 | // constructor 20 | p.initialize = function (border, borderHighlight, left, right, horizontal) { 21 | this.border = obelisk.ColorGeom.get32(border === undefined ? 0x878787 : border); 22 | this.borderHighlight = obelisk.ColorGeom.get32(borderHighlight === undefined ? 0xFFFFFF : borderHighlight); 23 | this.left = obelisk.ColorGeom.get32(left === undefined ? 0xC9CFD0 : left); 24 | this.right = obelisk.ColorGeom.get32(right === undefined ? 0xE3E3E3 : right); 25 | this.horizontal = obelisk.ColorGeom.get32(horizontal === undefined ? 0xEEEFF0 : horizontal); 26 | return this; 27 | }; 28 | 29 | // public methods 30 | p.getByHorizontalColor = function (horizontal) { 31 | return new CubeColor( 32 | obelisk.ColorGeom.applyBrightness(horizontal, this.BRIGHTNESS_GAIN * 4), 33 | //apply hightlight 34 | obelisk.ColorGeom.applyBrightness(horizontal, 0, true), 35 | obelisk.ColorGeom.applyBrightness(horizontal, this.BRIGHTNESS_GAIN * 2), 36 | obelisk.ColorGeom.applyBrightness(horizontal, this.BRIGHTNESS_GAIN), 37 | horizontal 38 | ); 39 | }; 40 | 41 | p.toString = function () { 42 | return "[CubeColor]"; 43 | }; 44 | 45 | // private methods 46 | 47 | obelisk.CubeColor = CubeColor; 48 | }(obelisk)); 49 | -------------------------------------------------------------------------------- /demo/advanced/gif-rendering/main.js: -------------------------------------------------------------------------------- 1 | var WIDTH = 64; 2 | var HEIGHT = 28; 3 | 4 | var img = document.getElementById('animation'); 5 | var ctx = document.createElement('canvas').getContext("2d"); 6 | var canvas = document.getElementById('canvas-uncle'); 7 | 8 | var stack = []; 9 | var size = 8; 10 | var point = new obelisk.Point(50, 120); 11 | var pixelView = new obelisk.PixelView(canvas, point); 12 | 13 | function draw() { 14 | ctx.drawImage(img, 0, 0, WIDTH, HEIGHT); 15 | var imgData = ctx.getImageData(0, 0, WIDTH, HEIGHT); 16 | pixelView.clear(); 17 | for (var y = HEIGHT - 1; y >= 0; y--) { 18 | for (var x = 0; x < WIDTH - 1; x++) { 19 | var pixelColor = obelisk.CanvasTool.getPixel(imgData, x, y); 20 | if (pixelColor !== 0xFFFFFF) { 21 | var cube; 22 | var flag = false; 23 | for (var i in stack) { 24 | if (stack[i][1] === pixelColor) { 25 | cube = stack[i][0]; 26 | flag = true; 27 | break; 28 | } 29 | } 30 | if (!flag) { 31 | var fixedColor = obelisk.ColorGeom.applyBrightness(pixelColor, 50) 32 | var color = new obelisk.CubeColor().getByHorizontalColor(fixedColor); 33 | var dimension = new obelisk.CubeDimension(size, size + 2, size); 34 | cube = new obelisk.Cube(dimension, color, false); 35 | stack.push([cube, pixelColor]); 36 | } 37 | var p3d = new obelisk.Point3D(x * (size - 2), 0, (HEIGHT - 1 - y) * (size)); 38 | pixelView.renderObject(cube, p3d); 39 | } 40 | } 41 | } 42 | } 43 | // render interval 44 | window.setInterval(draw, 50); 45 | 46 | // build floor 47 | var canvasFloor = document.getElementById('canvas-floor'); 48 | var pixelViewFloor = new obelisk.PixelView(canvasFloor, point); 49 | var floorDimension = new obelisk.CubeDimension((size - 2) * (WIDTH + 2), (size - 2) * 9, size); 50 | var floor = new obelisk.Cube(floorDimension, new obelisk.CubeColor(), false); 51 | pixelViewFloor.renderObject(floor, new obelisk.Point3D(-20, -30, 0)); 52 | -------------------------------------------------------------------------------- /demo/advanced/input-text-rendering/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 |
64 | 65 | 66 | 67 |
68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /demo/advanced/flappy-bird/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | obelisk.js Demo 10 | 11 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /demo/advanced/flappy-bird/main.js: -------------------------------------------------------------------------------- 1 | // control bar 2 | var ControlBar = function () { 3 | this.size = 20; 4 | this.snap = false; 5 | }; 6 | 7 | var con = new ControlBar(); 8 | var gui = new dat.GUI(); 9 | 10 | var conSize = gui.add(con, 'size', 6, 40).step(2); 11 | conSize.onChange(function () { 12 | draw(); 13 | }); 14 | 15 | var conSnap = gui.add(con, 'snap'); 16 | conSnap.onChange(function () { 17 | draw(); 18 | }); 19 | 20 | var WIDTH = 17; 21 | var HEIGHT = 12; 22 | 23 | var img = document.getElementById('animation'); 24 | var ctx = document.createElement('canvas').getContext("2d"); 25 | var canvas = document.getElementById('canvas-demo'); 26 | 27 | var stack = []; 28 | var point = new obelisk.Point(400, 50); 29 | var pixelView = new obelisk.PixelView(canvas, point); 30 | 31 | function getPixel(data, x, y) { 32 | var index = (y * WIDTH + x) * 4; 33 | var r = data[index]; 34 | var g = data[index + 1]; 35 | var b = data[index + 2]; 36 | return ((r << 16) | (g << 8) | b); 37 | } 38 | 39 | function draw() { 40 | var size = con.size; 41 | var snap = con.snap ? 2 : 0; 42 | stack = []; 43 | ctx.drawImage(img, 0, 0, WIDTH, HEIGHT); 44 | var imgData = ctx.getImageData(0, 0, WIDTH, HEIGHT); 45 | pixelView.clear(); 46 | 47 | var color = new obelisk.SideColor().getByInnerColor(obelisk.ColorPattern.GRAY); 48 | var dimension = new obelisk.BrickDimension(size, size); 49 | var brick = new obelisk.Brick(dimension, color); 50 | for (var y = 0; y <= HEIGHT; y++) { 51 | for (var x = 0; x <= WIDTH; x++) { 52 | var p3d = new obelisk.Point3D(x * (size - snap), y * (size - snap), 0); 53 | pixelView.renderObject(brick, p3d) 54 | } 55 | } 56 | 57 | for (var y = 0; y < HEIGHT; y++) { 58 | for (var x = 0; x < WIDTH; x++) { 59 | var pixelColor = getPixel(imgData.data, x, y); 60 | if (pixelColor !== 0xFFFFFF) { 61 | var cube; 62 | var flag = false; 63 | for (var i in stack) { 64 | if (stack[i][1] === pixelColor) { 65 | cube = stack[i][0]; 66 | flag = true; 67 | break; 68 | } 69 | } 70 | 71 | if (!flag) { 72 | var color = new obelisk.CubeColor().getByHorizontalColor(pixelColor); 73 | var dimension = new obelisk.CubeDimension(size, size, size - 2); 74 | cube = new obelisk.Cube(dimension, color, false); 75 | stack.push([cube, pixelColor]); 76 | } 77 | var p3d = new obelisk.Point3D(x * (size - snap), y * (size - snap), 0); 78 | pixelView.renderObject(cube, p3d); 79 | } 80 | } 81 | } 82 | } 83 | 84 | draw(); 85 | -------------------------------------------------------------------------------- /src/primitives/SideX.js: -------------------------------------------------------------------------------- 1 | /*global obelisk:true*/ 2 | 3 | /* 4 | * SideX 5 | */ 6 | 7 | (function (obelisk) { 8 | "use strict"; 9 | var SideX, p; 10 | SideX = function (dimension, color, border, useDefaultCanvas) { 11 | this.initialize(dimension, color, border, useDefaultCanvas); 12 | }; 13 | p = SideX.prototype = new obelisk.AbstractPrimitive(); 14 | 15 | // public properties 16 | 17 | // constructor 18 | p.initialize = function (dimension, color, border, useDefaultCanvas) { 19 | this.initRender(dimension, color, border, useDefaultCanvas); 20 | this.initRectangle(); 21 | this.initBitmapData(); 22 | this.build(); 23 | this.renderBitmapDataForCanvas(); 24 | return this; 25 | }; 26 | 27 | // private method 28 | p.initRender = function (dimension, color, border, useDefaultCanvas) { 29 | this.useDefaultCanvas = useDefaultCanvas || false; 30 | this.border = border || border === undefined; 31 | this.dimension = dimension === undefined ? new obelisk.SideXDimension() : dimension; 32 | this.color = color === undefined ? new obelisk.SideColor() : color; 33 | }; 34 | 35 | p.initRectangle = function () { 36 | this.w = this.dimension.xAxis; 37 | this.h = this.dimension.zAxis + this.dimension.xAxis / 2; 38 | 39 | // the matrix offset between the bitmap and the 3d pixel coordinate ZERO point 40 | this.matrix = new obelisk.Matrix(); 41 | this.matrix.tx = 0; 42 | this.matrix.ty = -this.dimension.zAxis; 43 | }; 44 | 45 | p.initBitmapData = function () { 46 | this.bitmapData = new obelisk.BitmapData(this.w, this.h, this.useDefaultCanvas); 47 | }; 48 | p.renderBitmapDataForCanvas = function () { 49 | this.bitmapData.context.putImageData(this.bitmapData.imageData, 0, 0); 50 | this.canvas = this.bitmapData.canvas; 51 | }; 52 | 53 | p.build = function () { 54 | var xOffsetInner, yOffsetInner, xOffsetOut, yOffsetOut, i, j, borderColor; 55 | 56 | xOffsetInner = 0; 57 | yOffsetInner = this.dimension.zAxis; 58 | xOffsetOut = this.dimension.xAxis - 1; 59 | yOffsetOut = this.h - this.dimension.zAxis - 1; 60 | borderColor = this.border ? this.color.border : this.color.inner; 61 | 62 | //x axis 63 | for (i = 0; i < this.dimension.xAxis; i += 1) { 64 | this.bitmapData.setPixel(xOffsetInner + i, yOffsetInner + Math.floor(i / 2), borderColor); 65 | this.bitmapData.setPixel(xOffsetOut - i, yOffsetOut - Math.floor(i / 2), borderColor); 66 | } 67 | 68 | //z axis 69 | for (j = 0; j < this.dimension.zAxis; j += 1) { 70 | this.bitmapData.setPixel(xOffsetInner, yOffsetInner - j, borderColor); 71 | this.bitmapData.setPixel(xOffsetOut, yOffsetOut + j, borderColor); 72 | } 73 | 74 | //fill an pixel graphic enclosed 75 | this.bitmapData.floodFill(Math.floor(this.w / 2), Math.floor(this.h / 2), this.color.inner); 76 | }; 77 | 78 | // public methods 79 | p.toString = function () { 80 | return "[SideX]"; 81 | }; 82 | 83 | obelisk.SideX = SideX; 84 | }(obelisk)); 85 | -------------------------------------------------------------------------------- /src/primitives/SideY.js: -------------------------------------------------------------------------------- 1 | /*global obelisk:true*/ 2 | 3 | /* 4 | * SideY 5 | */ 6 | 7 | (function (obelisk) { 8 | "use strict"; 9 | 10 | var SideY, p; 11 | SideY = function (dimension, color, border, useDefaultCanvas) { 12 | this.initialize(dimension, color, border, useDefaultCanvas); 13 | }; 14 | p = SideY.prototype = new obelisk.AbstractPrimitive(); 15 | 16 | // public properties 17 | 18 | // constructor 19 | p.initialize = function (dimension, color, border, useDefaultCanvas) { 20 | this.initRender(dimension, color, border, useDefaultCanvas); 21 | this.initRectangle(); 22 | this.initBitmapData(); 23 | this.build(); 24 | this.renderBitmapDataForCanvas(); 25 | return this; 26 | }; 27 | 28 | // private method 29 | p.initRender = function (dimension, color, border, useDefaultCanvas) { 30 | this.useDefaultCanvas = useDefaultCanvas || false; 31 | this.border = border || border === undefined; 32 | this.dimension = dimension === undefined ? new obelisk.SideYDimension() : dimension; 33 | this.color = color === undefined ? new obelisk.SideColor() : color; 34 | }; 35 | 36 | p.initRectangle = function () { 37 | this.w = this.dimension.yAxis; 38 | this.h = this.dimension.zAxis + this.dimension.yAxis / 2; 39 | 40 | // the matrix offset between the bitmap and the 3d pixel coordinate ZERO point 41 | this.matrix = new obelisk.Matrix(); 42 | this.matrix.tx = -this.dimension.yAxis + 2; 43 | this.matrix.ty = -this.dimension.zAxis; 44 | }; 45 | 46 | p.initBitmapData = function () { 47 | this.bitmapData = new obelisk.BitmapData(this.w, this.h, this.useDefaultCanvas); 48 | }; 49 | p.renderBitmapDataForCanvas = function () { 50 | this.bitmapData.context.putImageData(this.bitmapData.imageData, 0, 0); 51 | this.canvas = this.bitmapData.canvas; 52 | }; 53 | 54 | p.build = function () { 55 | var xOffsetInner, yOffsetInner, xOffsetOut, yOffsetOut, i, j, borderColor; 56 | xOffsetInner = 0; 57 | yOffsetInner = this.h - this.dimension.zAxis - 1; 58 | xOffsetOut = this.dimension.yAxis - 1; 59 | yOffsetOut = this.dimension.zAxis; 60 | borderColor = this.border ? this.color.border : this.color.inner; 61 | 62 | //y axis 63 | for (i = 0; i < this.dimension.yAxis; i += 1) { 64 | this.bitmapData.setPixel(xOffsetInner + i, yOffsetInner - Math.floor(i / 2), borderColor); 65 | this.bitmapData.setPixel(xOffsetOut - i, yOffsetOut + Math.floor(i / 2), borderColor); 66 | } 67 | 68 | //z axis 69 | for (j = 0; j < this.dimension.zAxis; j += 1) { 70 | this.bitmapData.setPixel(xOffsetInner, yOffsetInner + j, borderColor); 71 | this.bitmapData.setPixel(xOffsetOut, yOffsetOut - j, borderColor); 72 | } 73 | 74 | //fill an pixel graphic enclosed 75 | this.bitmapData.floodFill(Math.floor(this.w / 2), Math.floor(this.h / 2), this.color.inner); 76 | }; 77 | 78 | // public methods 79 | p.toString = function () { 80 | return "[SideY]"; 81 | }; 82 | 83 | obelisk.SideY = SideY; 84 | }(obelisk)); 85 | -------------------------------------------------------------------------------- /src/primitives/Brick.js: -------------------------------------------------------------------------------- 1 | /*global obelisk:true*/ 2 | 3 | /* 4 | * Brick 5 | */ 6 | 7 | (function (obelisk) { 8 | "use strict"; 9 | 10 | var Brick, p; 11 | Brick = function (dimension, color, border, useDefaultCanvas) { 12 | this.initialize(dimension, color, border, useDefaultCanvas); 13 | }; 14 | p = Brick.prototype = new obelisk.AbstractPrimitive(); 15 | 16 | // public properties 17 | 18 | // constructor 19 | p.initialize = function (dimension, color, border, useDefaultCanvas) { 20 | this.initRender(dimension, color, border, useDefaultCanvas); 21 | this.initRectangle(); 22 | this.initBitmapData(); 23 | this.build(); 24 | this.renderBitmapDataForCanvas(); 25 | return this; 26 | }; 27 | 28 | // private method 29 | p.initRender = function (dimension, color, border, useDefaultCanvas) { 30 | this.useDefaultCanvas = useDefaultCanvas || false; 31 | this.border = border || border === undefined; 32 | this.dimension = dimension === undefined ? new obelisk.BrickDimension() : dimension; 33 | this.color = color === undefined ? new obelisk.SideColor() : color; 34 | }; 35 | 36 | p.initRectangle = function () { 37 | this.w = this.dimension.xAxis + this.dimension.yAxis; 38 | this.h = (this.dimension.xAxis + this.dimension.yAxis) / 2; 39 | 40 | // 22.6 degrees implementation 41 | this.w -= 2; 42 | this.h -= 1; 43 | 44 | // the matrix offset between the bitmap and the 3d pixel coordinate ZERO point 45 | this.matrix = new obelisk.Matrix(); 46 | this.matrix.tx = -this.dimension.yAxis + 2; 47 | this.matrix.ty = 0; 48 | }; 49 | 50 | p.initBitmapData = function () { 51 | this.bitmapData = new obelisk.BitmapData(this.w, this.h, this.useDefaultCanvas); 52 | }; 53 | p.renderBitmapDataForCanvas = function () { 54 | this.bitmapData.context.putImageData(this.bitmapData.imageData, 0, 0); 55 | this.canvas = this.bitmapData.canvas; 56 | }; 57 | 58 | p.build = function () { 59 | var xOffsetInner, yOffsetInner, xOffsetOut, yOffsetOut, i, j, borderColor; 60 | xOffsetInner = this.dimension.yAxis - 2; 61 | yOffsetInner = 0; 62 | xOffsetOut = this.dimension.xAxis - 1; 63 | yOffsetOut = this.h - 1; 64 | borderColor = this.border ? this.color.border : this.color.inner; 65 | 66 | //x axis 67 | for (i = 0; i < this.dimension.xAxis; i += 1) { 68 | this.bitmapData.setPixel(xOffsetInner + i, yOffsetInner + Math.floor(i / 2), borderColor); 69 | this.bitmapData.setPixel(xOffsetOut - i, yOffsetOut - Math.floor(i / 2), borderColor); 70 | } 71 | 72 | //y axis 73 | for (j = 0; j < this.dimension.yAxis; j += 1) { 74 | this.bitmapData.setPixel(xOffsetInner + 1 - j, yOffsetInner + Math.floor(j / 2), borderColor); 75 | this.bitmapData.setPixel(xOffsetOut - 1 + j, yOffsetOut - Math.floor(j / 2), borderColor); 76 | } 77 | 78 | //fill an pixel graphic enclosed 79 | this.bitmapData.floodFill(Math.floor(this.w / 2), Math.floor(this.h / 2), this.color.inner); 80 | }; 81 | 82 | // public methods 83 | p.toString = function () { 84 | return "[Brick]"; 85 | }; 86 | 87 | obelisk.Brick = Brick; 88 | }(obelisk)); 89 | -------------------------------------------------------------------------------- /demo/advanced/input-text-rendering/main.js: -------------------------------------------------------------------------------- 1 | // control bar 2 | var ControlBar = function () { 3 | this.size = 10; 4 | this.height = 24; 5 | this.threshold = 130; 6 | }; 7 | var con = new ControlBar(); 8 | var gui = new dat.GUI(); 9 | var conSize = gui.add(con, 'size', 6, 20).step(2); 10 | var conHeight = gui.add(con, 'height', 4, 100).step(1); 11 | var conThreshold = gui.add(con, 'threshold', 80, 200).step(1); 12 | conSize.onChange(function () { 13 | buildPrimitive(); 14 | draw(); 15 | }); 16 | conHeight.onChange(function () { 17 | buildPrimitive(); 18 | draw(); 19 | }); 20 | conThreshold.onChange(function () { 21 | buildPrimitive(); 22 | draw(); 23 | }); 24 | 25 | // color patterns 26 | var colorData = ['#CCFF00', '#FF0099', '#FF7CBF', '#EEEEEE', '#666666']; 27 | var iMax = colorData.length; 28 | var colorHtml = ''; 29 | for (var i = 0; i < iMax; i++) { 30 | colorHtml += '
  • '; 31 | } 32 | $('#color-box').html(colorHtml); 33 | $('#color-box').find('li').on('click', function () { 34 | var index = $(this).index(); 35 | color = parseInt(colorData[index].replace('#', '0x'), 16); 36 | buildPrimitive(); 37 | draw(); 38 | }); 39 | 40 | // input field 41 | var ipt = $('#ipt'); 42 | ipt.on('keyup', draw); 43 | ipt.on('click', function () { 44 | $(this).select(); 45 | }); 46 | 47 | // input off canvas 48 | var offCanvas = $('#canvas-txt').get(0); 49 | var ctx = offCanvas.getContext("2d"); 50 | ctx.font = "20px Helvetica,sans-serif"; 51 | 52 | // pixel view 53 | var canvas = $('#canvas-demo'); 54 | var point = new obelisk.Point(150, 30); 55 | var pixelView = new obelisk.PixelView(canvas, point); 56 | var brick; 57 | var cube; 58 | var color = 0xCCFF00; 59 | 60 | // build method 61 | function buildPrimitive() { 62 | // floor 63 | var colorBrick = new obelisk.SideColor(0xAAAAAA, 0xEEEEEE); 64 | var dimensionBrick = new obelisk.BrickDimension(con.size, con.size); 65 | brick = new obelisk.Brick(dimensionBrick, colorBrick); 66 | 67 | // cube 68 | var colorCube = new obelisk.CubeColor().getByHorizontalColor(color); 69 | var dimensionCube = new obelisk.CubeDimension(con.size, con.size, con.height); 70 | cube = new obelisk.Cube(dimensionCube, colorCube, false); 71 | } 72 | function draw() { 73 | var size = con.size; 74 | var txtWidth = offCanvas.width; 75 | var txtHeight = offCanvas.height; 76 | 77 | // clear everything 78 | pixelView.clear(); 79 | ctx.clearRect(0, 0, txtWidth, txtHeight); 80 | 81 | ctx.fillText(ipt.val(), 2, 18); 82 | var textData = ctx.getImageData(0, 0, txtWidth, txtHeight); 83 | 84 | for (var y = 0; y <= txtHeight; y++) { 85 | for (var x = 0; x <= txtWidth; x++) { 86 | var p3d = new obelisk.Point3D(x * (size - 2), y * (size - 2), 0); 87 | pixelView.renderObject(brick, p3d); 88 | } 89 | } 90 | 91 | for (var y = 0; y < txtHeight; y++) { 92 | for (var x = 0; x < txtWidth; x++) { 93 | // check pixel 94 | var index = (y * textData.width + x) * 4; 95 | 96 | if (textData.data[index + 3] > con.threshold) { 97 | var p3d = new obelisk.Point3D(x * (size - 2), y * (size - 2), 0); 98 | pixelView.renderObject(cube, p3d); 99 | } 100 | } 101 | } 102 | } 103 | 104 | // main 105 | buildPrimitive(); 106 | draw(); 107 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Obelisk.js 2 | 3 | Obelisk.js is a JavaScript Engine for building isometric pixel objects. 4 | 5 | With the simple and flexible API provided by this engine, you can easily add isometric pixel element like brick, cube, pyramid onto HTML5 canvas. Obelisk.js strictly follows the pixel neat pattern: lines with 1:2 pixel dot arrangement, leading to an angle of 22.6 degrees. Also you should know this is not only for game, just try it out and pixelate something. Have fun. 6 | 7 | 8 | 9 | ## Showcase 10 | 11 | Experiments: 12 | - GIF Animation Rendering: http://codepen.io/nosir/details/mdiHe (WebKit browser only - Chrome, Safari) 13 | - Input Text Rendering: http://codepen.io/nosir/details/IxBJn 14 | - Pixel Isometirc Flappy Bird: http://codepen.io/nosir/details/rzaLA 15 | - Cube Generator: http://codepen.io/nosir/details/ganrh 16 | 17 | User Contributed: 18 | - Github Contribution Chart Isometric View Chrome Extension: [Github URL](https://github.com/jasonlong/isometric-contributions) by [@jasonlong](https://twitter.com/jasonlong) 19 | - Snake Game: http://codepen.io/sfaedo/full/AwGjg (Use ← → Key) by [@Sebastian Faedo](http://codepen.io/sfaedo) 20 | - Mario 3D Model: http://jsdo.it/cx20/bQtQ by [@cx20](https://twitter.com/cx20) 21 | - Conway's Game of Life: http://codepen.io/safx/full/Ewcym by [@safxdev](https://twitter.com/safxdev) 22 | 23 | ## Getting started 24 | 25 | Simply include obelisk.js in your project 26 | ```html 27 | 28 | ``` 29 | 30 | Create pixel world 31 | ```javascript 32 | // create a canvas 2D point for pixel view world 33 | var point = new obelisk.Point(200, 200); 34 | 35 | // create view instance to nest everything 36 | // canvas could be either DOM or jQuery element 37 | var pixelView = new obelisk.PixelView(canvas, point); 38 | 39 | // create cube dimension and color instance 40 | var dimension = new obelisk.CubeDimension(80, 100, 120); 41 | var gray = obelisk.ColorPattern.GRAY; 42 | var color = new obelisk.CubeColor().getByHorizontalColor(gray); 43 | 44 | // build cube with dimension and color instance 45 | var cube = new obelisk.Cube(dimension, color, true); 46 | 47 | // render cube primitive into view 48 | pixelView.renderObject(cube); 49 | ``` 50 | You can find out more details in tutorial part 1: [To build the first cube](https://github.com/nosir/obelisk.js/wiki/Tutorial-Part-1%3A-To-build-the-first-cube) or [try the code yourself](http://jsfiddle.net/nosir/ygWEW/) 51 | 52 | ## Tutorials 53 | Step by step: 54 | - Part 1: [To build the first cube](https://github.com/nosir/obelisk.js/wiki/Tutorial-Part-1%3A-To-build-the-first-cube) 55 | - Part 2: [Coordinate system](https://github.com/nosir/obelisk.js/wiki/Tutorial-Part-2%3A-Coordinate-system) 56 | - Part 3: [Primitives](https://github.com/nosir/obelisk.js/wiki/Tutorial-Part-3%3A-Primitives) 57 | - Part 4: [Color](https://github.com/nosir/obelisk.js/wiki/Tutorial-Part-4%3A-Color) 58 | - Part 5: [Dimension](https://github.com/nosir/obelisk.js/wiki/Tutorial-Part-5%3A-Dimension) 59 | 60 | Sample code for building all primitives: 61 | - Cube: http://jsfiddle.net/nosir/ygWEW/ 62 | - Pyramid : http://jsfiddle.net/nosir/ZVURu/ 63 | - Brick: http://jsfiddle.net/nosir/6MuVr/ 64 | - SideX & SideY: http://jsfiddle.net/nosir/bLsew/ 65 | 66 | ## Roadmap 67 | 68 | To add more pixel primitives - 4 directions [slopes](http://nosir.github.io/obelisk.js/images/slope.gif) will be the first 69 | 70 | ## Get in Touch 71 | 72 | - Build any cool stuff with obelisk.js? Please feel free to add it here: [User Contributed Showcase](https://github.com/nosir/obelisk.js/wiki/User-Contributed-Showcase) 73 | - Bugs & Suggestions: [open an issue](https://github.com/nosir/obelisk.js/issues) 74 | - Twitter: [@rison](https://twitter.com/rison) 75 | 76 | ## Changelog 77 | 78 | See details in the [release notes](https://github.com/nosir/obelisk.js/releases). 79 | 80 | ## References 81 | Pixel art is a form of digital art, where images are edited and displayed on the pixel level. The isometric projection is commonly seen in games to provide a 3D view without using any real 3D processing. 82 | 83 | - Isometric projection http://en.wikipedia.org/wiki/Isometric_projection 84 | - Flood fill implementation http://en.wikipedia.org/wiki/Flood_fill 85 | - Pixel grapic - Eboy http://eboy.com 86 | 87 | ## License 88 | 89 | Obelisk.js is released under the [MIT License](http://opensource.org/licenses/MIT) 90 | -------------------------------------------------------------------------------- /src/primitives/Cube.js: -------------------------------------------------------------------------------- 1 | /*global obelisk:true*/ 2 | 3 | /* 4 | * Cube 5 | */ 6 | 7 | (function (obelisk) { 8 | "use strict"; 9 | 10 | var Cube, p; 11 | Cube = function (dimension, color, border, useDefaultCanvas) { 12 | this.initialize(dimension, color, border, useDefaultCanvas); 13 | }; 14 | p = Cube.prototype = new obelisk.AbstractPrimitive(); 15 | 16 | // public properties 17 | 18 | // constructor 19 | p.initialize = function (dimension, color, border, useDefaultCanvas) { 20 | this.initRender(dimension, color, border, useDefaultCanvas); 21 | this.initRectangle(); 22 | this.initBitmapData(); 23 | this.build(); 24 | this.renderBitmapDataForCanvas(); 25 | return this; 26 | }; 27 | 28 | // private method 29 | p.initRender = function (dimension, color, border, useDefaultCanvas) { 30 | this.useDefaultCanvas = useDefaultCanvas || false; 31 | this.border = border || border === undefined; 32 | this.dimension = dimension === undefined ? new obelisk.CubeDimension() : dimension; 33 | this.color = color === undefined ? new obelisk.CubeColor() : color; 34 | }; 35 | 36 | p.initRectangle = function () { 37 | this.w = this.dimension.xAxis + this.dimension.yAxis; 38 | this.h = this.dimension.zAxis + (this.dimension.xAxis + this.dimension.yAxis) / 2; 39 | 40 | // 22.6 degrees implementation 41 | this.w -= 2; 42 | this.h -= 1; 43 | 44 | // the matrix offset between the bitmap and the 3d pixel coordinate ZERO point 45 | this.matrix = new obelisk.Matrix(); 46 | this.matrix.tx = -this.dimension.yAxis + 2; 47 | this.matrix.ty = -this.dimension.zAxis; 48 | }; 49 | 50 | p.initBitmapData = function () { 51 | this.bitmapData = new obelisk.BitmapData(this.w, this.h, this.useDefaultCanvas); 52 | }; 53 | p.renderBitmapDataForCanvas = function () { 54 | this.canvas = this.bitmapData.canvas; 55 | }; 56 | 57 | p.build = function () { 58 | var brick, sideX, sideY, po_brick, po_x, po_y, ctx, bmd, offsetX, offsetY, 59 | i, j, k; 60 | // horizontal layer 61 | brick = new obelisk.Brick( 62 | new obelisk.BrickDimension(this.dimension.xAxis, this.dimension.yAxis), 63 | new obelisk.SideColor(this.color.border, this.color.horizontal), 64 | this.border 65 | ); 66 | 67 | // left side 68 | sideX = new obelisk.SideX( 69 | new obelisk.SideXDimension(this.dimension.xAxis, this.dimension.zAxis), 70 | new obelisk.SideColor(this.color.border, this.color.left), 71 | this.border 72 | ); 73 | 74 | // right side 75 | sideY = new obelisk.SideY( 76 | new obelisk.SideYDimension(this.dimension.yAxis, this.dimension.zAxis), 77 | new obelisk.SideColor(this.color.border, this.color.right), 78 | this.border 79 | ); 80 | 81 | po_brick = new obelisk.PixelObject(brick); 82 | po_x = new obelisk.PixelObject(sideX); 83 | po_y = new obelisk.PixelObject(sideY); 84 | 85 | ctx = this.bitmapData.context; 86 | ctx.drawImage(po_brick.canvas, po_brick.x + this.dimension.yAxis - 2, po_brick.y); 87 | ctx.drawImage(po_x.canvas, po_x.x, po_x.y + this.dimension.zAxis + this.dimension.yAxis / 2 - 1); 88 | ctx.drawImage(po_y.canvas, po_y.x + this.w - 2, po_x.y + this.dimension.zAxis + this.dimension.xAxis / 2 - 1); 89 | 90 | // highlight & highlight fix 91 | bmd = new obelisk.BitmapData(this.w, this.h); 92 | 93 | if (this.border) { 94 | offsetX = this.dimension.xAxis - 2; 95 | offsetY = (this.dimension.xAxis + this.dimension.yAxis) / 2 - 2; 96 | 97 | //the 2px in bounding without hightlight 98 | for (i = 0; i < this.dimension.xAxis - 2; i += 1) { 99 | bmd.setPixel(offsetX + 1 - i, offsetY - Math.floor(i / 2), this.color.borderHighlight); 100 | } 101 | 102 | //the 2px in bounding without hightlight 103 | for (j = 0; j < this.dimension.yAxis - 2; j += 1) { 104 | bmd.setPixel(offsetX + j, offsetY - Math.floor(j / 2), this.color.borderHighlight); 105 | } 106 | 107 | for (k = 0; k < this.dimension.zAxis; k += 1) { 108 | bmd.setPixel(offsetX, offsetY + k, this.color.borderHighlight); 109 | } 110 | } else { 111 | for (i = 0; i < this.dimension.zAxis; i += 1) { 112 | bmd.setPixel(this.dimension.xAxis - 2, (this.dimension.xAxis + this.dimension.yAxis) / 2 - 1 + i, this.color.left); 113 | } 114 | } 115 | bmd.context.putImageData(bmd.imageData, 0, 0); 116 | ctx.drawImage(bmd.canvas, 0, 0); 117 | }; 118 | 119 | // public methods 120 | p.toString = function () { 121 | return "[Cube]"; 122 | }; 123 | 124 | obelisk.Cube = Cube; 125 | }(obelisk)); 126 | -------------------------------------------------------------------------------- /src/primitives/Pyramid.js: -------------------------------------------------------------------------------- 1 | /*global obelisk:true*/ 2 | 3 | /* 4 | * Pyramid 5 | */ 6 | 7 | (function (obelisk) { 8 | "use strict"; 9 | 10 | var Pyramid, p; 11 | Pyramid = function (dimension, color, border, useDefaultCanvas) { 12 | this.initialize(dimension, color, border, useDefaultCanvas); 13 | }; 14 | p = Pyramid.prototype = new obelisk.AbstractPrimitive(); 15 | 16 | // private properties 17 | p.hSize = null; 18 | p.hOffset = null; 19 | 20 | // constructor 21 | p.initialize = function (dimension, color, border, useDefaultCanvas) { 22 | this.initRender(dimension, color, border, useDefaultCanvas); 23 | this.initRectangle(); 24 | this.initBitmapData(); 25 | this.build(); 26 | this.renderBitmapDataForCanvas(); 27 | return this; 28 | }; 29 | 30 | // private method 31 | p.initRender = function (dimension, color, border, useDefaultCanvas) { 32 | this.useDefaultCanvas = useDefaultCanvas || false; 33 | this.border = border || border === undefined; 34 | this.dimension = dimension === undefined ? new obelisk.PyramidDimension() : dimension; 35 | this.color = color === undefined ? new obelisk.PyramidColor() : color; 36 | 37 | this.hSize = this.dimension.tall ? this.dimension.xAxis * 2 : this.dimension.xAxis; 38 | this.hOffset = this.dimension.tall ? -3 : -2; 39 | }; 40 | 41 | p.initRectangle = function () { 42 | this.w = this.dimension.xAxis + this.dimension.yAxis; 43 | this.h = this.hSize + this.dimension.xAxis / 2; 44 | 45 | // 22.6 degrees implementation 46 | this.w -= 2; 47 | this.h += this.hOffset; 48 | 49 | // the matrix offset between the bitmap and the 3d pixel coordinate ZERO point 50 | this.matrix = new obelisk.Matrix(); 51 | this.matrix.tx = -this.dimension.xAxis + 2; 52 | this.matrix.ty = -this.hSize / 2 + 2 - (this.dimension.tall ? this.dimension.xAxis / 2 : 1); 53 | }; 54 | 55 | p.initBitmapData = function () { 56 | this.bitmapData = new obelisk.BitmapData(this.w, this.h, this.useDefaultCanvas); 57 | }; 58 | p.renderBitmapDataForCanvas = function () { 59 | this.bitmapData.context.putImageData(this.bitmapData.imageData, 0, 0); 60 | this.canvas = this.bitmapData.canvas; 61 | }; 62 | 63 | p.build = function () { 64 | var colorborder_left, colorborder_right, colorborder_highlight, 65 | i, j, k, l1, m1, l2, m2; 66 | colorborder_left = this.border ? this.color.border : this.color.left; 67 | colorborder_right = this.border ? this.color.border : this.color.right; 68 | 69 | colorborder_highlight = this.border ? this.color.borderHighlight : colorborder_left; 70 | 71 | //z axis || hightlight 72 | for (k = 0; k < this.hSize + this.dimension.xAxis / 2 - 4; k += 1) { 73 | this.bitmapData.setPixel(this.dimension.xAxis - 2, k + 3 + this.hOffset, colorborder_highlight); 74 | } 75 | 76 | //x axis 77 | for (i = 0; i < this.dimension.xAxis; i += 1) { 78 | this.bitmapData.setPixel(i, this.hSize + Math.floor(i / 2) + this.hOffset, colorborder_left); 79 | } 80 | 81 | //y axis 82 | for (j = 0; j < this.dimension.xAxis; j += 1) { 83 | this.bitmapData.setPixel(j + this.dimension.xAxis - 2, this.hSize + this.dimension.xAxis / 2 - Math.floor(j / 2) - 1 + this.hOffset, colorborder_right); 84 | } 85 | 86 | if (!this.dimension.tall) { 87 | //left edge 88 | for (l1 = 0; l1 < this.hSize; l1 += 1) { 89 | this.bitmapData.setPixel(l1, this.hSize - l1 + this.hOffset, colorborder_left); 90 | } 91 | 92 | //right edge 93 | for (m1 = 0; m1 < this.hSize; m1 += 1) { 94 | this.bitmapData.setPixel(m1 + this.hSize - 2, m1 + 1 + this.hOffset, colorborder_right); 95 | } 96 | } else { 97 | //left edge 98 | for (l2 = 0; l2 < this.hSize - 2; l2 += 1) { 99 | this.bitmapData.setPixel(Math.floor(l2 / 2), this.hSize - l2 + this.hOffset, colorborder_left); 100 | } 101 | 102 | //right edge 103 | for (m2 = 2; m2 < this.hSize; m2 += 1) { 104 | this.bitmapData.setPixel(Math.floor(m2 / 2) + this.dimension.xAxis - 2, m2 + 1 + this.hOffset, colorborder_right); 105 | } 106 | } 107 | 108 | if (!this.border) { 109 | this.bitmapData.setPixel(this.dimension.xAxis - 2, this.hSize + this.dimension.xAxis / 2 - 1 + this.hOffset, colorborder_left); 110 | } 111 | 112 | //floodfill 113 | this.bitmapData.floodFill(this.dimension.xAxis - 1, this.hSize + Math.floor((this.dimension.xAxis - 1) / 2) + this.hOffset - 1, this.color.right); 114 | this.bitmapData.floodFill(this.dimension.xAxis - 3, this.hSize + Math.floor((this.dimension.xAxis - 1) / 2) + this.hOffset - 2, this.color.left); 115 | }; 116 | 117 | // public methods 118 | p.toString = function () { 119 | return "[Pyramid]"; 120 | }; 121 | 122 | obelisk.Pyramid = Pyramid; 123 | }(obelisk)); 124 | -------------------------------------------------------------------------------- /src/display/BitmapData.js: -------------------------------------------------------------------------------- 1 | /*global obelisk:true*/ 2 | 3 | /* 4 | * BitmapData 5 | */ 6 | 7 | (function (obelisk) { 8 | "use strict"; 9 | 10 | var BitmapData, p; 11 | BitmapData = function (w, h, useDefaultCanvas) { 12 | this.initialize(w, h, useDefaultCanvas); 13 | }; 14 | p = BitmapData.prototype; 15 | 16 | // public property 17 | p.imageData = null; 18 | p.canvas = null; 19 | p.context = null; 20 | 21 | // constructor 22 | p.initialize = function (w, h, useDefaultCanvas) { 23 | if (w === undefined || h === undefined) { 24 | throw new Error("BitmapData width or height is missing"); 25 | } 26 | 27 | if (useDefaultCanvas) { 28 | this.canvas = obelisk.CanvasManager.getDefaultCanvas(); 29 | } else { 30 | this.canvas = obelisk.CanvasManager.getNewCanvas(); 31 | } 32 | 33 | this.canvas.setAttribute('width', w); 34 | this.canvas.setAttribute('height', h); 35 | 36 | this.context = this.canvas.getContext('2d'); 37 | this.context.clearRect(0, 0, this.canvas.width, this.canvas.height); 38 | 39 | this.imageData = this.context.createImageData(w, h); 40 | 41 | return this; 42 | }; 43 | 44 | p.setPixel = function (posX, posY, color) { 45 | var index = (posY * this.imageData.width + posX) * 4; 46 | this.setPixelByIndex(index, color); 47 | }; 48 | 49 | p.setPixelByIndex = function (index, color) { 50 | var pixels = this.imageData.data; 51 | pixels[index] = (color >>> 16) & 0xFF; 52 | pixels[index + 1] = (color >>> 8) & 0xFF; 53 | pixels[index + 2] = (color >>> 0) & 0xFF; 54 | pixels[index + 3] = (color >>> 24) & 0xFF; 55 | }; 56 | 57 | p.checkPixelAvailable = function (x, y) { 58 | var index = (y * this.imageData.width + x) * 4; 59 | return this.imageData.data[index + 3] === 0; 60 | }; 61 | 62 | p.floodFill = function (posX, posY, color) { 63 | if (((color >>> 24) & 0xFF) === 0x00) { 64 | // transparent flood fill 65 | return; 66 | } 67 | 68 | var x = posX, y = posY, 69 | stack = [], 70 | nowCol = [], 71 | prevCol = [], 72 | col, row, matchFlag, 73 | w = this.imageData.width, 74 | h = this.imageData.height, 75 | i, j; 76 | 77 | // bound reach 78 | if (x < 0 || y < 0 || x >= w || y >= h) { 79 | return; 80 | } 81 | 82 | // first point check fail 83 | if (!this.checkPixelAvailable(x, y)) { 84 | throw new Error("Start point for flood fill is already filled"); 85 | } 86 | 87 | // left side flood fill 88 | for (col = x; col >= 0; col -= 1) { 89 | // top side 90 | for (row = y; row >= 0; row -= 1) { 91 | if (this.checkPixelAvailable(col, row)) { 92 | // available pixel 93 | stack.push((row * w + col) * 4); 94 | nowCol.push(row); 95 | } else { 96 | // unavailable pixel 97 | if (!(row === y && this.checkPixelAvailable(col + 1, row - 1))) { 98 | break; 99 | } 100 | // let's continue to check more data in this column 101 | } 102 | } 103 | 104 | // top side 105 | for (row = y; row < h; row += 1) { 106 | if (this.checkPixelAvailable(col, row)) { 107 | // available pixel 108 | stack.push((row * w + col) * 4); 109 | nowCol.push(row); 110 | } else { 111 | // unavailable pixel 112 | if (!(row === y && this.checkPixelAvailable(col + 1, row + 1))) { 113 | break; 114 | } 115 | // let's continue to check more data in this column 116 | } 117 | } 118 | 119 | // compare with previous column 120 | // for first column 121 | // the given point should be inside the container 122 | if (col === x) { 123 | prevCol = nowCol.concat(); 124 | } 125 | 126 | matchFlag = false; 127 | 128 | for (i = 0; i < prevCol.length; i += 1) { 129 | for (j = 0; j < prevCol.length; j += 1) { 130 | if (nowCol[j] === prevCol[i]) { 131 | matchFlag = true; 132 | y = prevCol[i]; 133 | break; 134 | } 135 | } 136 | 137 | if (matchFlag) { 138 | break; 139 | } 140 | } 141 | 142 | if (matchFlag) { 143 | prevCol = nowCol.concat(); 144 | nowCol = []; 145 | } else { 146 | // bound reach 147 | break; 148 | } 149 | } 150 | 151 | // reset start point 152 | x = posX; 153 | y = posY; 154 | prevCol = []; 155 | nowCol = []; 156 | 157 | // right side flood fill 158 | for (col = x; col < w; col += 1) { 159 | // top side 160 | for (row = y; row >= 0; row -= 1) { 161 | if (this.checkPixelAvailable(col, row)) { 162 | // available pixel 163 | stack.push((row * w + col) * 4); 164 | nowCol.push(row); 165 | } else { 166 | // unavailable pixel 167 | if (!(row === y && this.checkPixelAvailable(col - 1, row - 1))) { 168 | break; 169 | } 170 | // let's continue to check more data in this column 171 | } 172 | } 173 | 174 | // top side 175 | for (row = y; row < h; row += 1) { 176 | if (this.checkPixelAvailable(col, row)) { 177 | // available pixel 178 | stack.push((row * w + col) * 4); 179 | nowCol.push(row); 180 | } else { 181 | // unavailable pixel 182 | if (!(row === y && this.checkPixelAvailable(col - 1, row + 1))) { 183 | break; 184 | } 185 | // let's continue to check more data in this column 186 | } 187 | } 188 | 189 | // compare with previous column 190 | // for first column 191 | // the given point should be inside the container 192 | if (col === x) { 193 | prevCol = nowCol.concat(); 194 | } 195 | 196 | matchFlag = false; 197 | 198 | for (i = 0; i < prevCol.length; i += 1) { 199 | for (j = 0; j < prevCol.length; j += 1) { 200 | if (nowCol[j] === prevCol[i]) { 201 | matchFlag = true; 202 | y = prevCol[i]; 203 | break; 204 | } 205 | } 206 | 207 | if (matchFlag) { 208 | break; 209 | } 210 | } 211 | 212 | if (matchFlag) { 213 | prevCol = nowCol.concat(); 214 | nowCol = []; 215 | } else { 216 | // bound reach 217 | break; 218 | } 219 | } 220 | 221 | // fill image data 222 | for (i = 0; i < stack.length; i += 1) { 223 | this.setPixelByIndex(stack[i], color); 224 | } 225 | }; 226 | 227 | p.toString = function () { 228 | return "[BitmapData]"; 229 | }; 230 | 231 | obelisk.BitmapData = BitmapData; 232 | }(obelisk)); 233 | -------------------------------------------------------------------------------- /demo/vendor/modernizr-2.6.2.min.js: -------------------------------------------------------------------------------- 1 | /* Modernizr 2.6.2 (Custom Build) | MIT & BSD 2 | * Build: http://modernizr.com/download/#-fontface-backgroundsize-borderimage-borderradius-boxshadow-flexbox-hsla-multiplebgs-opacity-rgba-textshadow-cssanimations-csscolumns-generatedcontent-cssgradients-cssreflections-csstransforms-csstransforms3d-csstransitions-applicationcache-canvas-canvastext-draganddrop-hashchange-history-audio-video-indexeddb-input-inputtypes-localstorage-postmessage-sessionstorage-websockets-websqldatabase-webworkers-geolocation-inlinesvg-smil-svg-svgclippaths-touch-webgl-shiv-mq-cssclasses-addtest-prefixed-teststyles-testprop-testallprops-hasevent-prefixes-domprefixes-load 3 | */ 4 | ;window.Modernizr=function(a,b,c){function D(a){j.cssText=a}function E(a,b){return D(n.join(a+";")+(b||""))}function F(a,b){return typeof a===b}function G(a,b){return!!~(""+a).indexOf(b)}function H(a,b){for(var d in a){var e=a[d];if(!G(e,"-")&&j[e]!==c)return b=="pfx"?e:!0}return!1}function I(a,b,d){for(var e in a){var f=b[a[e]];if(f!==c)return d===!1?a[e]:F(f,"function")?f.bind(d||b):f}return!1}function J(a,b,c){var d=a.charAt(0).toUpperCase()+a.slice(1),e=(a+" "+p.join(d+" ")+d).split(" ");return F(b,"string")||F(b,"undefined")?H(e,b):(e=(a+" "+q.join(d+" ")+d).split(" "),I(e,b,c))}function K(){e.input=function(c){for(var d=0,e=c.length;d',a,""].join(""),l.id=h,(m?l:n).innerHTML+=f,n.appendChild(l),m||(n.style.background="",n.style.overflow="hidden",k=g.style.overflow,g.style.overflow="hidden",g.appendChild(n)),i=c(l,a),m?l.parentNode.removeChild(l):(n.parentNode.removeChild(n),g.style.overflow=k),!!i},z=function(b){var c=a.matchMedia||a.msMatchMedia;if(c)return c(b).matches;var d;return y("@media "+b+" { #"+h+" { position: absolute; } }",function(b){d=(a.getComputedStyle?getComputedStyle(b,null):b.currentStyle)["position"]=="absolute"}),d},A=function(){function d(d,e){e=e||b.createElement(a[d]||"div"),d="on"+d;var f=d in e;return f||(e.setAttribute||(e=b.createElement("div")),e.setAttribute&&e.removeAttribute&&(e.setAttribute(d,""),f=F(e[d],"function"),F(e[d],"undefined")||(e[d]=c),e.removeAttribute(d))),e=null,f}var a={select:"input",change:"input",submit:"form",reset:"form",error:"img",load:"img",abort:"img"};return d}(),B={}.hasOwnProperty,C;!F(B,"undefined")&&!F(B.call,"undefined")?C=function(a,b){return B.call(a,b)}:C=function(a,b){return b in a&&F(a.constructor.prototype[b],"undefined")},Function.prototype.bind||(Function.prototype.bind=function(b){var c=this;if(typeof c!="function")throw new TypeError;var d=w.call(arguments,1),e=function(){if(this instanceof e){var a=function(){};a.prototype=c.prototype;var f=new a,g=c.apply(f,d.concat(w.call(arguments)));return Object(g)===g?g:f}return c.apply(b,d.concat(w.call(arguments)))};return e}),s.flexbox=function(){return J("flexWrap")},s.canvas=function(){var a=b.createElement("canvas");return!!a.getContext&&!!a.getContext("2d")},s.canvastext=function(){return!!e.canvas&&!!F(b.createElement("canvas").getContext("2d").fillText,"function")},s.webgl=function(){return!!a.WebGLRenderingContext},s.touch=function(){var c;return"ontouchstart"in a||a.DocumentTouch&&b instanceof DocumentTouch?c=!0:y(["@media (",n.join("touch-enabled),("),h,")","{#modernizr{top:9px;position:absolute}}"].join(""),function(a){c=a.offsetTop===9}),c},s.geolocation=function(){return"geolocation"in navigator},s.postmessage=function(){return!!a.postMessage},s.websqldatabase=function(){return!!a.openDatabase},s.indexedDB=function(){return!!J("indexedDB",a)},s.hashchange=function(){return A("hashchange",a)&&(b.documentMode===c||b.documentMode>7)},s.history=function(){return!!a.history&&!!history.pushState},s.draganddrop=function(){var a=b.createElement("div");return"draggable"in a||"ondragstart"in a&&"ondrop"in a},s.websockets=function(){return"WebSocket"in a||"MozWebSocket"in a},s.rgba=function(){return D("background-color:rgba(150,255,150,.5)"),G(j.backgroundColor,"rgba")},s.hsla=function(){return D("background-color:hsla(120,40%,100%,.5)"),G(j.backgroundColor,"rgba")||G(j.backgroundColor,"hsla")},s.multiplebgs=function(){return D("background:url(https://),url(https://),red url(https://)"),/(url\s*\(.*?){3}/.test(j.background)},s.backgroundsize=function(){return J("backgroundSize")},s.borderimage=function(){return J("borderImage")},s.borderradius=function(){return J("borderRadius")},s.boxshadow=function(){return J("boxShadow")},s.textshadow=function(){return b.createElement("div").style.textShadow===""},s.opacity=function(){return E("opacity:.55"),/^0.55$/.test(j.opacity)},s.cssanimations=function(){return J("animationName")},s.csscolumns=function(){return J("columnCount")},s.cssgradients=function(){var a="background-image:",b="gradient(linear,left top,right bottom,from(#9f9),to(white));",c="linear-gradient(left top,#9f9, white);";return D((a+"-webkit- ".split(" ").join(b+a)+n.join(c+a)).slice(0,-a.length)),G(j.backgroundImage,"gradient")},s.cssreflections=function(){return J("boxReflect")},s.csstransforms=function(){return!!J("transform")},s.csstransforms3d=function(){var a=!!J("perspective");return a&&"webkitPerspective"in g.style&&y("@media (transform-3d),(-webkit-transform-3d){#modernizr{left:9px;position:absolute;height:3px;}}",function(b,c){a=b.offsetLeft===9&&b.offsetHeight===3}),a},s.csstransitions=function(){return J("transition")},s.fontface=function(){var a;return y('@font-face {font-family:"font";src:url("https://")}',function(c,d){var e=b.getElementById("smodernizr"),f=e.sheet||e.styleSheet,g=f?f.cssRules&&f.cssRules[0]?f.cssRules[0].cssText:f.cssText||"":"";a=/src/i.test(g)&&g.indexOf(d.split(" ")[0])===0}),a},s.generatedcontent=function(){var a;return y(["#",h,"{font:0/0 a}#",h,':after{content:"',l,'";visibility:hidden;font:3px/1 a}'].join(""),function(b){a=b.offsetHeight>=3}),a},s.video=function(){var a=b.createElement("video"),c=!1;try{if(c=!!a.canPlayType)c=new Boolean(c),c.ogg=a.canPlayType('video/ogg; codecs="theora"').replace(/^no$/,""),c.h264=a.canPlayType('video/mp4; codecs="avc1.42E01E"').replace(/^no$/,""),c.webm=a.canPlayType('video/webm; codecs="vp8, vorbis"').replace(/^no$/,"")}catch(d){}return c},s.audio=function(){var a=b.createElement("audio"),c=!1;try{if(c=!!a.canPlayType)c=new Boolean(c),c.ogg=a.canPlayType('audio/ogg; codecs="vorbis"').replace(/^no$/,""),c.mp3=a.canPlayType("audio/mpeg;").replace(/^no$/,""),c.wav=a.canPlayType('audio/wav; codecs="1"').replace(/^no$/,""),c.m4a=(a.canPlayType("audio/x-m4a;")||a.canPlayType("audio/aac;")).replace(/^no$/,"")}catch(d){}return c},s.localstorage=function(){try{return localStorage.setItem(h,h),localStorage.removeItem(h),!0}catch(a){return!1}},s.sessionstorage=function(){try{return sessionStorage.setItem(h,h),sessionStorage.removeItem(h),!0}catch(a){return!1}},s.webworkers=function(){return!!a.Worker},s.applicationcache=function(){return!!a.applicationCache},s.svg=function(){return!!b.createElementNS&&!!b.createElementNS(r.svg,"svg").createSVGRect},s.inlinesvg=function(){var a=b.createElement("div");return a.innerHTML="",(a.firstChild&&a.firstChild.namespaceURI)==r.svg},s.smil=function(){return!!b.createElementNS&&/SVGAnimate/.test(m.call(b.createElementNS(r.svg,"animate")))},s.svgclippaths=function(){return!!b.createElementNS&&/SVGClipPath/.test(m.call(b.createElementNS(r.svg,"clipPath")))};for(var L in s)C(s,L)&&(x=L.toLowerCase(),e[x]=s[L](),v.push((e[x]?"":"no-")+x));return e.input||K(),e.addTest=function(a,b){if(typeof a=="object")for(var d in a)C(a,d)&&e.addTest(d,a[d]);else{a=a.toLowerCase();if(e[a]!==c)return e;b=typeof b=="function"?b():b,typeof f!="undefined"&&f&&(g.className+=" "+(b?"":"no-")+a),e[a]=b}return e},D(""),i=k=null,function(a,b){function k(a,b){var c=a.createElement("p"),d=a.getElementsByTagName("head")[0]||a.documentElement;return c.innerHTML="x",d.insertBefore(c.lastChild,d.firstChild)}function l(){var a=r.elements;return typeof a=="string"?a.split(" "):a}function m(a){var b=i[a[g]];return b||(b={},h++,a[g]=h,i[h]=b),b}function n(a,c,f){c||(c=b);if(j)return c.createElement(a);f||(f=m(c));var g;return f.cache[a]?g=f.cache[a].cloneNode():e.test(a)?g=(f.cache[a]=f.createElem(a)).cloneNode():g=f.createElem(a),g.canHaveChildren&&!d.test(a)?f.frag.appendChild(g):g}function o(a,c){a||(a=b);if(j)return a.createDocumentFragment();c=c||m(a);var d=c.frag.cloneNode(),e=0,f=l(),g=f.length;for(;e",f="hidden"in a,j=a.childNodes.length==1||function(){b.createElement("a");var a=b.createDocumentFragment();return typeof a.cloneNode=="undefined"||typeof a.createDocumentFragment=="undefined"||typeof a.createElement=="undefined"}()}catch(c){f=!0,j=!0}})();var r={elements:c.elements||"abbr article aside audio bdi canvas data datalist details figcaption figure footer header hgroup mark meter nav output progress section summary time video",shivCSS:c.shivCSS!==!1,supportsUnknownElements:j,shivMethods:c.shivMethods!==!1,type:"default",shivDocument:q,createElement:n,createDocumentFragment:o};a.html5=r,q(b)}(this,b),e._version=d,e._prefixes=n,e._domPrefixes=q,e._cssomPrefixes=p,e.mq=z,e.hasEvent=A,e.testProp=function(a){return H([a])},e.testAllProps=J,e.testStyles=y,e.prefixed=function(a,b,c){return b?J(a,b,c):J(a,"pfx")},g.className=g.className.replace(/(^|\s)no-js(\s|$)/,"$1$2")+(f?" js "+v.join(" "):""),e}(this,this.document),function(a,b,c){function d(a){return"[object Function]"==o.call(a)}function e(a){return"string"==typeof a}function f(){}function g(a){return!a||"loaded"==a||"complete"==a||"uninitialized"==a}function h(){var a=p.shift();q=1,a?a.t?m(function(){("c"==a.t?B.injectCss:B.injectJs)(a.s,0,a.a,a.x,a.e,1)},0):(a(),h()):q=0}function i(a,c,d,e,f,i,j){function k(b){if(!o&&g(l.readyState)&&(u.r=o=1,!q&&h(),l.onload=l.onreadystatechange=null,b)){"img"!=a&&m(function(){t.removeChild(l)},50);for(var d in y[c])y[c].hasOwnProperty(d)&&y[c][d].onload()}}var j=j||B.errorTimeout,l=b.createElement(a),o=0,r=0,u={t:d,s:c,e:f,a:i,x:j};1===y[c]&&(r=1,y[c]=[]),"object"==a?l.data=c:(l.src=c,l.type=a),l.width=l.height="0",l.onerror=l.onload=l.onreadystatechange=function(){k.call(this,r)},p.splice(e,0,u),"img"!=a&&(r||2===y[c]?(t.insertBefore(l,s?null:n),m(k,j)):y[c].push(l))}function j(a,b,c,d,f){return q=0,b=b||"j",e(a)?i("c"==b?v:u,a,b,this.i++,c,d,f):(p.splice(this.i++,0,a),1==p.length&&h()),this}function k(){var a=B;return a.loader={load:j,i:0},a}var l=b.documentElement,m=a.setTimeout,n=b.getElementsByTagName("script")[0],o={}.toString,p=[],q=0,r="MozAppearance"in l.style,s=r&&!!b.createRange().compareNode,t=s?l:n.parentNode,l=a.opera&&"[object Opera]"==o.call(a.opera),l=!!b.attachEvent&&!l,u=r?"object":l?"script":"img",v=l?"script":u,w=Array.isArray||function(a){return"[object Array]"==o.call(a)},x=[],y={},z={timeout:function(a,b){return b.length&&(a.timeout=b[0]),a}},A,B;B=function(a){function b(a){var a=a.split("!"),b=x.length,c=a.pop(),d=a.length,c={url:c,origUrl:c,prefixes:a},e,f,g;for(f=0;f 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | obelisk.js Demo 10 | 11 | 34 | 35 | 36 |
    37 | 38 | 39 | 40 |
    41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /demo/vendor/dat.gui.min.js: -------------------------------------------------------------------------------- 1 | /** 2 | * dat-gui JavaScript Controller Library 3 | * http://code.google.com/p/dat-gui 4 | * 5 | * Copyright 2011 Data Arts Team, Google Creative Lab 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | */ 13 | var dat=dat||{};dat.gui=dat.gui||{};dat.utils=dat.utils||{};dat.controllers=dat.controllers||{};dat.dom=dat.dom||{};dat.color=dat.color||{};dat.utils.css=function(){return{load:function(e,a){var a=a||document,c=a.createElement("link");c.type="text/css";c.rel="stylesheet";c.href=e;a.getElementsByTagName("head")[0].appendChild(c)},inject:function(e,a){var a=a||document,c=document.createElement("style");c.type="text/css";c.innerHTML=e;a.getElementsByTagName("head")[0].appendChild(c)}}}(); 14 | dat.utils.common=function(){var e=Array.prototype.forEach,a=Array.prototype.slice;return{BREAK:{},extend:function(c){this.each(a.call(arguments,1),function(a){for(var f in a)this.isUndefined(a[f])||(c[f]=a[f])},this);return c},defaults:function(c){this.each(a.call(arguments,1),function(a){for(var f in a)this.isUndefined(c[f])&&(c[f]=a[f])},this);return c},compose:function(){var c=a.call(arguments);return function(){for(var d=a.call(arguments),f=c.length-1;f>=0;f--)d=[c[f].apply(this,d)];return d[0]}}, 15 | each:function(a,d,f){if(e&&a.forEach===e)a.forEach(d,f);else if(a.length===a.length+0)for(var b=0,n=a.length;b-1?d.length-d.indexOf(".")-1:0};c.superclass=e;a.extend(c.prototype,e.prototype,{setValue:function(a){if(this.__min!==void 0&&athis.__max)a=this.__max;this.__step!==void 0&&a%this.__step!=0&&(a=Math.round(a/this.__step)*this.__step);return c.superclass.prototype.setValue.call(this,a)},min:function(a){this.__min=a;return this},max:function(a){this.__max=a;return this},step:function(a){this.__step=a;return this}});return c}(dat.controllers.Controller,dat.utils.common); 29 | dat.controllers.NumberControllerBox=function(e,a,c){var d=function(f,b,e){function h(){var a=parseFloat(l.__input.value);c.isNaN(a)||l.setValue(a)}function j(a){var b=o-a.clientY;l.setValue(l.getValue()+b*l.__impliedStep);o=a.clientY}function m(){a.unbind(window,"mousemove",j);a.unbind(window,"mouseup",m)}this.__truncationSuspended=false;d.superclass.call(this,f,b,e);var l=this,o;this.__input=document.createElement("input");this.__input.setAttribute("type","text");a.bind(this.__input,"change",h); 30 | a.bind(this.__input,"blur",function(){h();l.__onFinishChange&&l.__onFinishChange.call(l,l.getValue())});a.bind(this.__input,"mousedown",function(b){a.bind(window,"mousemove",j);a.bind(window,"mouseup",m);o=b.clientY});a.bind(this.__input,"keydown",function(a){if(a.keyCode===13)l.__truncationSuspended=true,this.blur(),l.__truncationSuspended=false});this.updateDisplay();this.domElement.appendChild(this.__input)};d.superclass=e;c.extend(d.prototype,e.prototype,{updateDisplay:function(){var a=this.__input, 31 | b;if(this.__truncationSuspended)b=this.getValue();else{b=this.getValue();var c=Math.pow(10,this.__precision);b=Math.round(b*c)/c}a.value=b;return d.superclass.prototype.updateDisplay.call(this)}});return d}(dat.controllers.NumberController,dat.dom.dom,dat.utils.common); 32 | dat.controllers.NumberControllerSlider=function(e,a,c,d,f){var b=function(d,c,f,e,l){function o(b){b.preventDefault();var d=a.getOffset(g.__background),c=a.getWidth(g.__background);g.setValue(g.__min+(g.__max-g.__min)*((b.clientX-d.left)/(d.left+c-d.left)));return false}function y(){a.unbind(window,"mousemove",o);a.unbind(window,"mouseup",y);g.__onFinishChange&&g.__onFinishChange.call(g,g.getValue())}b.superclass.call(this,d,c,{min:f,max:e,step:l});var g=this;this.__background=document.createElement("div"); 33 | this.__foreground=document.createElement("div");a.bind(this.__background,"mousedown",function(b){a.bind(window,"mousemove",o);a.bind(window,"mouseup",y);o(b)});a.addClass(this.__background,"slider");a.addClass(this.__foreground,"slider-fg");this.updateDisplay();this.__background.appendChild(this.__foreground);this.domElement.appendChild(this.__background)};b.superclass=e;b.useDefaultStyles=function(){c.inject(f)};d.extend(b.prototype,e.prototype,{updateDisplay:function(){this.__foreground.style.width= 34 | (this.getValue()-this.__min)/(this.__max-this.__min)*100+"%";return b.superclass.prototype.updateDisplay.call(this)}});return b}(dat.controllers.NumberController,dat.dom.dom,dat.utils.css,dat.utils.common,".slider {\n box-shadow: inset 0 2px 4px rgba(0,0,0,0.15);\n height: 1em;\n border-radius: 1em;\n background-color: #eee;\n padding: 0 0.5em;\n overflow: hidden;\n}\n\n.slider-fg {\n padding: 1px 0 2px 0;\n background-color: #aaa;\n height: 1em;\n margin-left: -0.5em;\n padding-right: 0.5em;\n border-radius: 1em 0 0 1em;\n}\n\n.slider-fg:after {\n display: inline-block;\n border-radius: 1em;\n background-color: #fff;\n border: 1px solid #aaa;\n content: '';\n float: right;\n margin-right: -1em;\n margin-top: -1px;\n height: 0.9em;\n width: 0.9em;\n}"); 35 | dat.controllers.FunctionController=function(e,a,c){var d=function(c,b,e){d.superclass.call(this,c,b);var h=this;this.__button=document.createElement("div");this.__button.innerHTML=e===void 0?"Fire":e;a.bind(this.__button,"click",function(a){a.preventDefault();h.fire();return false});a.addClass(this.__button,"button");this.domElement.appendChild(this.__button)};d.superclass=e;c.extend(d.prototype,e.prototype,{fire:function(){this.__onChange&&this.__onChange.call(this);this.__onFinishChange&&this.__onFinishChange.call(this, 36 | this.getValue());this.getValue().call(this.object)}});return d}(dat.controllers.Controller,dat.dom.dom,dat.utils.common); 37 | dat.controllers.BooleanController=function(e,a,c){var d=function(c,b){d.superclass.call(this,c,b);var e=this;this.__prev=this.getValue();this.__checkbox=document.createElement("input");this.__checkbox.setAttribute("type","checkbox");a.bind(this.__checkbox,"change",function(){e.setValue(!e.__prev)},false);this.domElement.appendChild(this.__checkbox);this.updateDisplay()};d.superclass=e;c.extend(d.prototype,e.prototype,{setValue:function(a){a=d.superclass.prototype.setValue.call(this,a);this.__onFinishChange&& 38 | this.__onFinishChange.call(this,this.getValue());this.__prev=this.getValue();return a},updateDisplay:function(){this.getValue()===true?(this.__checkbox.setAttribute("checked","checked"),this.__checkbox.checked=true):this.__checkbox.checked=false;return d.superclass.prototype.updateDisplay.call(this)}});return d}(dat.controllers.Controller,dat.dom.dom,dat.utils.common); 39 | dat.color.toString=function(e){return function(a){if(a.a==1||e.isUndefined(a.a)){for(a=a.hex.toString(16);a.length<6;)a="0"+a;return"#"+a}else return"rgba("+Math.round(a.r)+","+Math.round(a.g)+","+Math.round(a.b)+","+a.a+")"}}(dat.utils.common); 40 | dat.color.interpret=function(e,a){var c,d,f=[{litmus:a.isString,conversions:{THREE_CHAR_HEX:{read:function(a){a=a.match(/^#([A-F0-9])([A-F0-9])([A-F0-9])$/i);return a===null?false:{space:"HEX",hex:parseInt("0x"+a[1].toString()+a[1].toString()+a[2].toString()+a[2].toString()+a[3].toString()+a[3].toString())}},write:e},SIX_CHAR_HEX:{read:function(a){a=a.match(/^#([A-F0-9]{6})$/i);return a===null?false:{space:"HEX",hex:parseInt("0x"+a[1].toString())}},write:e},CSS_RGB:{read:function(a){a=a.match(/^rgb\(\s*(.+)\s*,\s*(.+)\s*,\s*(.+)\s*\)/); 41 | return a===null?false:{space:"RGB",r:parseFloat(a[1]),g:parseFloat(a[2]),b:parseFloat(a[3])}},write:e},CSS_RGBA:{read:function(a){a=a.match(/^rgba\(\s*(.+)\s*,\s*(.+)\s*,\s*(.+)\s*\,\s*(.+)\s*\)/);return a===null?false:{space:"RGB",r:parseFloat(a[1]),g:parseFloat(a[2]),b:parseFloat(a[3]),a:parseFloat(a[4])}},write:e}}},{litmus:a.isNumber,conversions:{HEX:{read:function(a){return{space:"HEX",hex:a,conversionName:"HEX"}},write:function(a){return a.hex}}}},{litmus:a.isArray,conversions:{RGB_ARRAY:{read:function(a){return a.length!= 42 | 3?false:{space:"RGB",r:a[0],g:a[1],b:a[2]}},write:function(a){return[a.r,a.g,a.b]}},RGBA_ARRAY:{read:function(a){return a.length!=4?false:{space:"RGB",r:a[0],g:a[1],b:a[2],a:a[3]}},write:function(a){return[a.r,a.g,a.b,a.a]}}}},{litmus:a.isObject,conversions:{RGBA_OBJ:{read:function(b){return a.isNumber(b.r)&&a.isNumber(b.g)&&a.isNumber(b.b)&&a.isNumber(b.a)?{space:"RGB",r:b.r,g:b.g,b:b.b,a:b.a}:false},write:function(a){return{r:a.r,g:a.g,b:a.b,a:a.a}}},RGB_OBJ:{read:function(b){return a.isNumber(b.r)&& 43 | a.isNumber(b.g)&&a.isNumber(b.b)?{space:"RGB",r:b.r,g:b.g,b:b.b}:false},write:function(a){return{r:a.r,g:a.g,b:a.b}}},HSVA_OBJ:{read:function(b){return a.isNumber(b.h)&&a.isNumber(b.s)&&a.isNumber(b.v)&&a.isNumber(b.a)?{space:"HSV",h:b.h,s:b.s,v:b.v,a:b.a}:false},write:function(a){return{h:a.h,s:a.s,v:a.v,a:a.a}}},HSV_OBJ:{read:function(b){return a.isNumber(b.h)&&a.isNumber(b.s)&&a.isNumber(b.v)?{space:"HSV",h:b.h,s:b.s,v:b.v}:false},write:function(a){return{h:a.h,s:a.s,v:a.v}}}}}];return function(){d= 44 | false;var b=arguments.length>1?a.toArray(arguments):arguments[0];a.each(f,function(e){if(e.litmus(b))return a.each(e.conversions,function(e,f){c=e.read(b);if(d===false&&c!==false)return d=c,c.conversionName=f,c.conversion=e,a.BREAK}),a.BREAK});return d}}(dat.color.toString,dat.utils.common); 45 | dat.GUI=dat.gui.GUI=function(e,a,c,d,f,b,n,h,j,m,l,o,y,g,i){function q(a,b,r,c){if(b[r]===void 0)throw Error("Object "+b+' has no property "'+r+'"');c.color?b=new l(b,r):(b=[b,r].concat(c.factoryArgs),b=d.apply(a,b));if(c.before instanceof f)c.before=c.before.__li;t(a,b);g.addClass(b.domElement,"c");r=document.createElement("span");g.addClass(r,"property-name");r.innerHTML=b.property;var e=document.createElement("div");e.appendChild(r);e.appendChild(b.domElement);c=s(a,e,c.before);g.addClass(c,k.CLASS_CONTROLLER_ROW); 46 | g.addClass(c,typeof b.getValue());p(a,c,b);a.__controllers.push(b);return b}function s(a,b,d){var c=document.createElement("li");b&&c.appendChild(b);d?a.__ul.insertBefore(c,params.before):a.__ul.appendChild(c);a.onResize();return c}function p(a,d,c){c.__li=d;c.__gui=a;i.extend(c,{options:function(b){if(arguments.length>1)return c.remove(),q(a,c.object,c.property,{before:c.__li.nextElementSibling,factoryArgs:[i.toArray(arguments)]});if(i.isArray(b)||i.isObject(b))return c.remove(),q(a,c.object,c.property, 47 | {before:c.__li.nextElementSibling,factoryArgs:[b]})},name:function(a){c.__li.firstElementChild.firstElementChild.innerHTML=a;return c},listen:function(){c.__gui.listen(c);return c},remove:function(){c.__gui.remove(c);return c}});if(c instanceof j){var e=new h(c.object,c.property,{min:c.__min,max:c.__max,step:c.__step});i.each(["updateDisplay","onChange","onFinishChange"],function(a){var b=c[a],H=e[a];c[a]=e[a]=function(){var a=Array.prototype.slice.call(arguments);b.apply(c,a);return H.apply(e,a)}}); 48 | g.addClass(d,"has-slider");c.domElement.insertBefore(e.domElement,c.domElement.firstElementChild)}else if(c instanceof h){var f=function(b){return i.isNumber(c.__min)&&i.isNumber(c.__max)?(c.remove(),q(a,c.object,c.property,{before:c.__li.nextElementSibling,factoryArgs:[c.__min,c.__max,c.__step]})):b};c.min=i.compose(f,c.min);c.max=i.compose(f,c.max)}else if(c instanceof b)g.bind(d,"click",function(){g.fakeEvent(c.__checkbox,"click")}),g.bind(c.__checkbox,"click",function(a){a.stopPropagation()}); 49 | else if(c instanceof n)g.bind(d,"click",function(){g.fakeEvent(c.__button,"click")}),g.bind(d,"mouseover",function(){g.addClass(c.__button,"hover")}),g.bind(d,"mouseout",function(){g.removeClass(c.__button,"hover")});else if(c instanceof l)g.addClass(d,"color"),c.updateDisplay=i.compose(function(a){d.style.borderLeftColor=c.__color.toString();return a},c.updateDisplay),c.updateDisplay();c.setValue=i.compose(function(b){a.getRoot().__preset_select&&c.isModified()&&B(a.getRoot(),true);return b},c.setValue)} 50 | function t(a,b){var c=a.getRoot(),d=c.__rememberedObjects.indexOf(b.object);if(d!=-1){var e=c.__rememberedObjectIndecesToControllers[d];e===void 0&&(e={},c.__rememberedObjectIndecesToControllers[d]=e);e[b.property]=b;if(c.load&&c.load.remembered){c=c.load.remembered;if(c[a.preset])c=c[a.preset];else if(c[w])c=c[w];else return;if(c[d]&&c[d][b.property]!==void 0)d=c[d][b.property],b.initialValue=d,b.setValue(d)}}}function I(a){var b=a.__save_row=document.createElement("li");g.addClass(a.domElement, 51 | "has-save");a.__ul.insertBefore(b,a.__ul.firstChild);g.addClass(b,"save-row");var c=document.createElement("span");c.innerHTML=" ";g.addClass(c,"button gears");var d=document.createElement("span");d.innerHTML="Save";g.addClass(d,"button");g.addClass(d,"save");var e=document.createElement("span");e.innerHTML="New";g.addClass(e,"button");g.addClass(e,"save-as");var f=document.createElement("span");f.innerHTML="Revert";g.addClass(f,"button");g.addClass(f,"revert");var m=a.__preset_select=document.createElement("select"); 52 | a.load&&a.load.remembered?i.each(a.load.remembered,function(b,c){C(a,c,c==a.preset)}):C(a,w,false);g.bind(m,"change",function(){for(var b=0;b0){a.preset=this.preset;if(!a.remembered)a.remembered={};a.remembered[this.preset]=z(this)}a.folders={};i.each(this.__folders,function(b, 69 | c){a.folders[c]=b.getSaveObject()});return a},save:function(){if(!this.load.remembered)this.load.remembered={};this.load.remembered[this.preset]=z(this);B(this,false)},saveAs:function(a){if(!this.load.remembered)this.load.remembered={},this.load.remembered[w]=z(this,true);this.load.remembered[a]=z(this);this.preset=a;C(this,a,true)},revert:function(a){i.each(this.__controllers,function(b){this.getRoot().load.remembered?t(a||this.getRoot(),b):b.setValue(b.initialValue)},this);i.each(this.__folders, 70 | function(a){a.revert(a)});a||B(this.getRoot(),false)},listen:function(a){var b=this.__listening.length==0;this.__listening.push(a);b&&E(this.__listening)}});return k}(dat.utils.css,'
    \n\n Here\'s the new load parameter for your GUI\'s constructor:\n\n \n\n
    \n\n Automatically save\n values to localStorage on exit.\n\n
    The values saved to localStorage will\n override those passed to dat.GUI\'s constructor. This makes it\n easier to work incrementally, but localStorage is fragile,\n and your friends may not see the same values you do.\n \n
    \n \n
    \n\n
    ', 71 | ".dg ul{list-style:none;margin:0;padding:0;width:100%;clear:both}.dg.ac{position:fixed;top:0;left:0;right:0;height:0;z-index:0}.dg:not(.ac) .main{overflow:hidden}.dg.main{-webkit-transition:opacity 0.1s linear;-o-transition:opacity 0.1s linear;-moz-transition:opacity 0.1s linear;transition:opacity 0.1s linear}.dg.main.taller-than-window{overflow-y:auto}.dg.main.taller-than-window .close-button{opacity:1;margin-top:-1px;border-top:1px solid #2c2c2c}.dg.main ul.closed .close-button{opacity:1 !important}.dg.main:hover .close-button,.dg.main .close-button.drag{opacity:1}.dg.main .close-button{-webkit-transition:opacity 0.1s linear;-o-transition:opacity 0.1s linear;-moz-transition:opacity 0.1s linear;transition:opacity 0.1s linear;border:0;position:absolute;line-height:19px;height:20px;cursor:pointer;text-align:center;background-color:#000}.dg.main .close-button:hover{background-color:#111}.dg.a{float:right;margin-right:15px;overflow-x:hidden}.dg.a.has-save ul{margin-top:27px}.dg.a.has-save ul.closed{margin-top:0}.dg.a .save-row{position:fixed;top:0;z-index:1002}.dg li{-webkit-transition:height 0.1s ease-out;-o-transition:height 0.1s ease-out;-moz-transition:height 0.1s ease-out;transition:height 0.1s ease-out}.dg li:not(.folder){cursor:auto;height:27px;line-height:27px;overflow:hidden;padding:0 4px 0 5px}.dg li.folder{padding:0;border-left:4px solid rgba(0,0,0,0)}.dg li.title{cursor:pointer;margin-left:-4px}.dg .closed li:not(.title),.dg .closed ul li,.dg .closed ul li > *{height:0;overflow:hidden;border:0}.dg .cr{clear:both;padding-left:3px;height:27px}.dg .property-name{cursor:default;float:left;clear:left;width:40%;overflow:hidden;text-overflow:ellipsis}.dg .c{float:left;width:60%}.dg .c input[type=text]{border:0;margin-top:4px;padding:3px;width:100%;float:right}.dg .has-slider input[type=text]{width:30%;margin-left:0}.dg .slider{float:left;width:66%;margin-left:-5px;margin-right:0;height:19px;margin-top:4px}.dg .slider-fg{height:100%}.dg .c input[type=checkbox]{margin-top:9px}.dg .c select{margin-top:5px}.dg .cr.function,.dg .cr.function .property-name,.dg .cr.function *,.dg .cr.boolean,.dg .cr.boolean *{cursor:pointer}.dg .selector{display:none;position:absolute;margin-left:-9px;margin-top:23px;z-index:10}.dg .c:hover .selector,.dg .selector.drag{display:block}.dg li.save-row{padding:0}.dg li.save-row .button{display:inline-block;padding:0px 6px}.dg.dialogue{background-color:#222;width:460px;padding:15px;font-size:13px;line-height:15px}#dg-new-constructor{padding:10px;color:#222;font-family:Monaco, monospace;font-size:10px;border:0;resize:none;box-shadow:inset 1px 1px 1px #888;word-wrap:break-word;margin:12px 0;display:block;width:440px;overflow-y:scroll;height:100px;position:relative}#dg-local-explain{display:none;font-size:11px;line-height:17px;border-radius:3px;background-color:#333;padding:8px;margin-top:10px}#dg-local-explain code{font-size:10px}#dat-gui-save-locally{display:none}.dg{color:#eee;font:11px 'Lucida Grande', sans-serif;text-shadow:0 -1px 0 #111}.dg.main::-webkit-scrollbar{width:5px;background:#1a1a1a}.dg.main::-webkit-scrollbar-corner{height:0;display:none}.dg.main::-webkit-scrollbar-thumb{border-radius:5px;background:#676767}.dg li:not(.folder){background:#1a1a1a;border-bottom:1px solid #2c2c2c}.dg li.save-row{line-height:25px;background:#dad5cb;border:0}.dg li.save-row select{margin-left:5px;width:108px}.dg li.save-row .button{margin-left:5px;margin-top:1px;border-radius:2px;font-size:9px;line-height:7px;padding:4px 4px 5px 4px;background:#c5bdad;color:#fff;text-shadow:0 1px 0 #b0a58f;box-shadow:0 -1px 0 #b0a58f;cursor:pointer}.dg li.save-row .button.gears{background:#c5bdad url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAsAAAANCAYAAAB/9ZQ7AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAQJJREFUeNpiYKAU/P//PwGIC/ApCABiBSAW+I8AClAcgKxQ4T9hoMAEUrxx2QSGN6+egDX+/vWT4e7N82AMYoPAx/evwWoYoSYbACX2s7KxCxzcsezDh3evFoDEBYTEEqycggWAzA9AuUSQQgeYPa9fPv6/YWm/Acx5IPb7ty/fw+QZblw67vDs8R0YHyQhgObx+yAJkBqmG5dPPDh1aPOGR/eugW0G4vlIoTIfyFcA+QekhhHJhPdQxbiAIguMBTQZrPD7108M6roWYDFQiIAAv6Aow/1bFwXgis+f2LUAynwoIaNcz8XNx3Dl7MEJUDGQpx9gtQ8YCueB+D26OECAAQDadt7e46D42QAAAABJRU5ErkJggg==) 2px 1px no-repeat;height:7px;width:8px}.dg li.save-row .button:hover{background-color:#bab19e;box-shadow:0 -1px 0 #b0a58f}.dg li.folder{border-bottom:0}.dg li.title{padding-left:16px;background:#000 url(data:image/gif;base64,R0lGODlhBQAFAJEAAP////Pz8////////yH5BAEAAAIALAAAAAAFAAUAAAIIlI+hKgFxoCgAOw==) 6px 10px no-repeat;cursor:pointer;border-bottom:1px solid rgba(255,255,255,0.2)}.dg .closed li.title{background-image:url(data:image/gif;base64,R0lGODlhBQAFAJEAAP////Pz8////////yH5BAEAAAIALAAAAAAFAAUAAAIIlGIWqMCbWAEAOw==)}.dg .cr.boolean{border-left:3px solid #806787}.dg .cr.function{border-left:3px solid #e61d5f}.dg .cr.number{border-left:3px solid #2fa1d6}.dg .cr.number input[type=text]{color:#2fa1d6}.dg .cr.string{border-left:3px solid #1ed36f}.dg .cr.string input[type=text]{color:#1ed36f}.dg .cr.function:hover,.dg .cr.boolean:hover{background:#111}.dg .c input[type=text]{background:#303030;outline:none}.dg .c input[type=text]:hover{background:#3c3c3c}.dg .c input[type=text]:focus{background:#494949;color:#fff}.dg .c .slider{background:#303030;cursor:ew-resize}.dg .c .slider-fg{background:#2fa1d6}.dg .c .slider:hover{background:#3c3c3c}.dg .c .slider:hover .slider-fg{background:#44abda}\n", 72 | dat.controllers.factory=function(e,a,c,d,f,b,n){return function(h,j,m,l){var o=h[j];if(n.isArray(m)||n.isObject(m))return new e(h,j,m);if(n.isNumber(o))return n.isNumber(m)&&n.isNumber(l)?new c(h,j,m,l):new a(h,j,{min:m,max:l});if(n.isString(o))return new d(h,j);if(n.isFunction(o))return new f(h,j,"");if(n.isBoolean(o))return new b(h,j)}}(dat.controllers.OptionController,dat.controllers.NumberControllerBox,dat.controllers.NumberControllerSlider,dat.controllers.StringController=function(e,a,c){var d= 73 | function(c,b){function e(){h.setValue(h.__input.value)}d.superclass.call(this,c,b);var h=this;this.__input=document.createElement("input");this.__input.setAttribute("type","text");a.bind(this.__input,"keyup",e);a.bind(this.__input,"change",e);a.bind(this.__input,"blur",function(){h.__onFinishChange&&h.__onFinishChange.call(h,h.getValue())});a.bind(this.__input,"keydown",function(a){a.keyCode===13&&this.blur()});this.updateDisplay();this.domElement.appendChild(this.__input)};d.superclass=e;c.extend(d.prototype, 74 | e.prototype,{updateDisplay:function(){if(!a.isActive(this.__input))this.__input.value=this.getValue();return d.superclass.prototype.updateDisplay.call(this)}});return d}(dat.controllers.Controller,dat.dom.dom,dat.utils.common),dat.controllers.FunctionController,dat.controllers.BooleanController,dat.utils.common),dat.controllers.Controller,dat.controllers.BooleanController,dat.controllers.FunctionController,dat.controllers.NumberControllerBox,dat.controllers.NumberControllerSlider,dat.controllers.OptionController, 75 | dat.controllers.ColorController=function(e,a,c,d,f){function b(a,b,c,d){a.style.background="";f.each(j,function(e){a.style.cssText+="background: "+e+"linear-gradient("+b+", "+c+" 0%, "+d+" 100%); "})}function n(a){a.style.background="";a.style.cssText+="background: -moz-linear-gradient(top, #ff0000 0%, #ff00ff 17%, #0000ff 34%, #00ffff 50%, #00ff00 67%, #ffff00 84%, #ff0000 100%);";a.style.cssText+="background: -webkit-linear-gradient(top, #ff0000 0%,#ff00ff 17%,#0000ff 34%,#00ffff 50%,#00ff00 67%,#ffff00 84%,#ff0000 100%);"; 76 | a.style.cssText+="background: -o-linear-gradient(top, #ff0000 0%,#ff00ff 17%,#0000ff 34%,#00ffff 50%,#00ff00 67%,#ffff00 84%,#ff0000 100%);";a.style.cssText+="background: -ms-linear-gradient(top, #ff0000 0%,#ff00ff 17%,#0000ff 34%,#00ffff 50%,#00ff00 67%,#ffff00 84%,#ff0000 100%);";a.style.cssText+="background: linear-gradient(top, #ff0000 0%,#ff00ff 17%,#0000ff 34%,#00ffff 50%,#00ff00 67%,#ffff00 84%,#ff0000 100%);"}var h=function(e,l){function o(b){q(b);a.bind(window,"mousemove",q);a.bind(window, 77 | "mouseup",j)}function j(){a.unbind(window,"mousemove",q);a.unbind(window,"mouseup",j)}function g(){var a=d(this.value);a!==false?(p.__color.__state=a,p.setValue(p.__color.toOriginal())):this.value=p.__color.toString()}function i(){a.unbind(window,"mousemove",s);a.unbind(window,"mouseup",i)}function q(b){b.preventDefault();var c=a.getWidth(p.__saturation_field),d=a.getOffset(p.__saturation_field),e=(b.clientX-d.left+document.body.scrollLeft)/c,b=1-(b.clientY-d.top+document.body.scrollTop)/c;b>1?b= 78 | 1:b<0&&(b=0);e>1?e=1:e<0&&(e=0);p.__color.v=b;p.__color.s=e;p.setValue(p.__color.toOriginal());return false}function s(b){b.preventDefault();var c=a.getHeight(p.__hue_field),d=a.getOffset(p.__hue_field),b=1-(b.clientY-d.top+document.body.scrollTop)/c;b>1?b=1:b<0&&(b=0);p.__color.h=b*360;p.setValue(p.__color.toOriginal());return false}h.superclass.call(this,e,l);this.__color=new c(this.getValue());this.__temp=new c(0);var p=this;this.domElement=document.createElement("div");a.makeSelectable(this.domElement, 79 | false);this.__selector=document.createElement("div");this.__selector.className="selector";this.__saturation_field=document.createElement("div");this.__saturation_field.className="saturation-field";this.__field_knob=document.createElement("div");this.__field_knob.className="field-knob";this.__field_knob_border="2px solid ";this.__hue_knob=document.createElement("div");this.__hue_knob.className="hue-knob";this.__hue_field=document.createElement("div");this.__hue_field.className="hue-field";this.__input= 80 | document.createElement("input");this.__input.type="text";this.__input_textShadow="0 1px 1px ";a.bind(this.__input,"keydown",function(a){a.keyCode===13&&g.call(this)});a.bind(this.__input,"blur",g);a.bind(this.__selector,"mousedown",function(){a.addClass(this,"drag").bind(window,"mouseup",function(){a.removeClass(p.__selector,"drag")})});var t=document.createElement("div");f.extend(this.__selector.style,{width:"122px",height:"102px",padding:"3px",backgroundColor:"#222",boxShadow:"0px 1px 3px rgba(0,0,0,0.3)"}); 81 | f.extend(this.__field_knob.style,{position:"absolute",width:"12px",height:"12px",border:this.__field_knob_border+(this.__color.v<0.5?"#fff":"#000"),boxShadow:"0px 1px 3px rgba(0,0,0,0.5)",borderRadius:"12px",zIndex:1});f.extend(this.__hue_knob.style,{position:"absolute",width:"15px",height:"2px",borderRight:"4px solid #fff",zIndex:1});f.extend(this.__saturation_field.style,{width:"100px",height:"100px",border:"1px solid #555",marginRight:"3px",display:"inline-block",cursor:"pointer"});f.extend(t.style, 82 | {width:"100%",height:"100%",background:"none"});b(t,"top","rgba(0,0,0,0)","#000");f.extend(this.__hue_field.style,{width:"15px",height:"100px",display:"inline-block",border:"1px solid #555",cursor:"ns-resize"});n(this.__hue_field);f.extend(this.__input.style,{outline:"none",textAlign:"center",color:"#fff",border:0,fontWeight:"bold",textShadow:this.__input_textShadow+"rgba(0,0,0,0.7)"});a.bind(this.__saturation_field,"mousedown",o);a.bind(this.__field_knob,"mousedown",o);a.bind(this.__hue_field,"mousedown", 83 | function(b){s(b);a.bind(window,"mousemove",s);a.bind(window,"mouseup",i)});this.__saturation_field.appendChild(t);this.__selector.appendChild(this.__field_knob);this.__selector.appendChild(this.__saturation_field);this.__selector.appendChild(this.__hue_field);this.__hue_field.appendChild(this.__hue_knob);this.domElement.appendChild(this.__input);this.domElement.appendChild(this.__selector);this.updateDisplay()};h.superclass=e;f.extend(h.prototype,e.prototype,{updateDisplay:function(){var a=d(this.getValue()); 84 | if(a!==false){var e=false;f.each(c.COMPONENTS,function(b){if(!f.isUndefined(a[b])&&!f.isUndefined(this.__color.__state[b])&&a[b]!==this.__color.__state[b])return e=true,{}},this);e&&f.extend(this.__color.__state,a)}f.extend(this.__temp.__state,this.__color.__state);this.__temp.a=1;var h=this.__color.v<0.5||this.__color.s>0.5?255:0,j=255-h;f.extend(this.__field_knob.style,{marginLeft:100*this.__color.s-7+"px",marginTop:100*(1-this.__color.v)-7+"px",backgroundColor:this.__temp.toString(),border:this.__field_knob_border+ 85 | "rgb("+h+","+h+","+h+")"});this.__hue_knob.style.marginTop=(1-this.__color.h/360)*100+"px";this.__temp.s=1;this.__temp.v=1;b(this.__saturation_field,"left","#fff",this.__temp.toString());f.extend(this.__input.style,{backgroundColor:this.__input.value=this.__color.toString(),color:"rgb("+h+","+h+","+h+")",textShadow:this.__input_textShadow+"rgba("+j+","+j+","+j+",.7)"})}});var j=["-moz-","-o-","-webkit-","-ms-",""];return h}(dat.controllers.Controller,dat.dom.dom,dat.color.Color=function(e,a,c,d){function f(a, 86 | b,c){Object.defineProperty(a,b,{get:function(){if(this.__state.space==="RGB")return this.__state[b];n(this,b,c);return this.__state[b]},set:function(a){if(this.__state.space!=="RGB")n(this,b,c),this.__state.space="RGB";this.__state[b]=a}})}function b(a,b){Object.defineProperty(a,b,{get:function(){if(this.__state.space==="HSV")return this.__state[b];h(this);return this.__state[b]},set:function(a){if(this.__state.space!=="HSV")h(this),this.__state.space="HSV";this.__state[b]=a}})}function n(b,c,e){if(b.__state.space=== 87 | "HEX")b.__state[c]=a.component_from_hex(b.__state.hex,e);else if(b.__state.space==="HSV")d.extend(b.__state,a.hsv_to_rgb(b.__state.h,b.__state.s,b.__state.v));else throw"Corrupted color state";}function h(b){var c=a.rgb_to_hsv(b.r,b.g,b.b);d.extend(b.__state,{s:c.s,v:c.v});if(d.isNaN(c.h)){if(d.isUndefined(b.__state.h))b.__state.h=0}else b.__state.h=c.h}var j=function(){this.__state=e.apply(this,arguments);if(this.__state===false)throw"Failed to interpret color arguments";this.__state.a=this.__state.a|| 88 | 1};j.COMPONENTS="r,g,b,h,s,v,hex,a".split(",");d.extend(j.prototype,{toString:function(){return c(this)},toOriginal:function(){return this.__state.conversion.write(this)}});f(j.prototype,"r",2);f(j.prototype,"g",1);f(j.prototype,"b",0);b(j.prototype,"h");b(j.prototype,"s");b(j.prototype,"v");Object.defineProperty(j.prototype,"a",{get:function(){return this.__state.a},set:function(a){this.__state.a=a}});Object.defineProperty(j.prototype,"hex",{get:function(){if(!this.__state.space!=="HEX")this.__state.hex= 89 | a.rgb_to_hex(this.r,this.g,this.b);return this.__state.hex},set:function(a){this.__state.space="HEX";this.__state.hex=a}});return j}(dat.color.interpret,dat.color.math=function(){var e;return{hsv_to_rgb:function(a,c,d){var e=a/60-Math.floor(a/60),b=d*(1-c),n=d*(1-e*c),c=d*(1-(1-e)*c),a=[[d,c,b],[n,d,b],[b,d,c],[b,n,d],[c,b,d],[d,b,n]][Math.floor(a/60)%6];return{r:a[0]*255,g:a[1]*255,b:a[2]*255}},rgb_to_hsv:function(a,c,d){var e=Math.min(a,c,d),b=Math.max(a,c,d),e=b-e;if(b==0)return{h:NaN,s:0,v:0}; 90 | a=a==b?(c-d)/e:c==b?2+(d-a)/e:4+(a-c)/e;a/=6;a<0&&(a+=1);return{h:a*360,s:e/b,v:b/255}},rgb_to_hex:function(a,c,d){a=this.hex_with_component(0,2,a);a=this.hex_with_component(a,1,c);return a=this.hex_with_component(a,0,d)},component_from_hex:function(a,c){return a>>c*8&255},hex_with_component:function(a,c,d){return d<<(e=c*8)|a&~(255<c._times.length)return-1;null==a&&(a=c.getFPS()|0);a=Math.min(c._times.length-1,a);return 1E3/((c._times[0]-c._times[a])/a)};c.setPaused=function(a){c._paused=a};c.getPaused=function(){return c._paused};c.getTime=function(a){return c._getTime()-c._startTime-(a?c._pausedTime:0)};c.getTicks=function(a){return c._ticks-(a? 19 | c._pausedTicks:0)};c._handleAF=function(){c._rafActive=!1;c._setupTick();c._getTime()-c._lastTime>=0.97*(c._interval-1)&&c._tick()};c._handleTimeout=function(){c.timeoutID=null;c._setupTick();c._tick()};c._setupTick=function(){if(!(c._rafActive||null!=c.timeoutID)){if(c.useRAF){var a=window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame;if(a){a(c._handleAF);c._rafActive=!0;return}}c.timeoutID= 20 | setTimeout(c._handleTimeout,c._interval)}};c._tick=function(){var a=c._getTime();c._ticks++;var m=a-c._lastTime,b=c._paused;b&&(c._pausedTicks++,c._pausedTime+=m);c._lastTime=a;for(var d=c._pauseable,e=c._listeners.slice(),f=e?e.length:0,h=0;hthis.a&&0<=this.d&&(a.rotation+=0>=a.rotation?180:-180),a.skewX=a.skewY= 30 | 0):(a.skewX=b/c.DEG_TO_RAD,a.skewY=g/c.DEG_TO_RAD);return a};b.reinitialize=function(a,b,g,d,c,f,h,k,j){this.initialize(a,b,g,d,c,f);this.alpha=h||1;this.shadow=k;this.compositeOperation=j;return this};b.appendProperties=function(a,b,g){this.alpha*=a;this.shadow=b||this.shadow;this.compositeOperation=g||this.compositeOperation;return this};b.prependProperties=function(a,b,g){this.alpha*=a;this.shadow=this.shadow||b;this.compositeOperation=this.compositeOperation||g;return this};b.clone=function(){var a= 31 | new c(this.a,this.b,this.c,this.d,this.tx,this.ty);a.shadow=this.shadow;a.alpha=this.alpha;a.compositeOperation=this.compositeOperation;return a};b.toString=function(){return"[Matrix2D (a="+this.a+" b="+this.b+" c="+this.c+" d="+this.d+" tx="+this.tx+" ty="+this.ty+")]"};c.identity=new c(1,0,0,1,0,0);createjs.Matrix2D=c})();this.createjs=this.createjs||{};(function(){var c=function(a,b){this.initialize(a,b)},b=c.prototype;b.x=0;b.y=0;b.initialize=function(a,b){this.x=null==a?0:a;this.y=null==b?0:b};b.clone=function(){return new c(this.x,this.y)};b.toString=function(){return"[Point (x="+this.x+" y="+this.y+")]"};createjs.Point=c})();this.createjs=this.createjs||{};(function(){var c=function(a,b,g,d){this.initialize(a,b,g,d)},b=c.prototype;b.x=0;b.y=0;b.width=0;b.height=0;b.initialize=function(a,b,g,d){this.x=null==a?0:a;this.y=null==b?0:b;this.width=null==g?0:g;this.height=null==d?0:d};b.clone=function(){return new c(this.x,this.y,this.width,this.height)};b.toString=function(){return"[Rectangle (x="+this.x+" y="+this.y+" width="+this.width+" height="+this.height+")]"};createjs.Rectangle=c})();this.createjs=this.createjs||{}; 32 | (function(){var c=function(a,b,g,d,c,f,h){this.initialize(a,b,g,d,c,f,h)},b=c.prototype;b.target=null;b.overLabel=null;b.outLabel=null;b.downLabel=null;b.play=!1;b._isPressed=!1;b._isOver=!1;b.initialize=function(a,b,g,d,c,f,h){a.addEventListener&&(this.target=a,a.cursor="pointer",this.overLabel=null==g?"over":g,this.outLabel=null==b?"out":b,this.downLabel=null==d?"down":d,this.play=c,this.setEnabled(!0),this.handleEvent({}),f&&(h&&(f.actionsEnabled=!1,f.gotoAndStop&&f.gotoAndStop(h)),a.hitArea=f))}; 33 | b.setEnabled=function(a){var b=this.target;a?(b.addEventListener("mouseover",this),b.addEventListener("mouseout",this),b.addEventListener("mousedown",this)):(b.removeEventListener("mouseover",this),b.removeEventListener("mouseout",this),b.removeEventListener("mousedown",this))};b.toString=function(){return"[ButtonHelper]"};b.handleEvent=function(a){var b=this.target,g=a.type;"mousedown"==g?(a.addEventListener("mouseup",this),this._isPressed=!0,a=this.downLabel):"mouseup"==g?(this._isPressed=!1,a= 34 | this._isOver?this.overLabel:this.outLabel):"mouseover"==g?(this._isOver=!0,a=this._isPressed?this.downLabel:this.overLabel):(this._isOver=!1,a=this._isPressed?this.overLabel:this.outLabel);this.play?b.gotoAndPlay&&b.gotoAndPlay(a):b.gotoAndStop&&b.gotoAndStop(a)};createjs.ButtonHelper=c})();this.createjs=this.createjs||{};(function(){var c=function(a,b,g,d){this.initialize(a,b,g,d)},b=c.prototype;c.identity=null;b.color=null;b.offsetX=0;b.offsetY=0;b.blur=0;b.initialize=function(a,b,g,d){this.color=a;this.offsetX=b;this.offsetY=g;this.blur=d};b.toString=function(){return"[Shadow]"};b.clone=function(){return new c(this.color,this.offsetX,this.offsetY,this.blur)};c.identity=new c("transparent",0,0,0);createjs.Shadow=c})();this.createjs=this.createjs||{}; 35 | (function(){var c=function(a){this.initialize(a)},b=c.prototype;b.complete=!0;b.onComplete=null;b.addEventListener=null;b.removeEventListener=null;b.removeAllEventListeners=null;b.dispatchEvent=null;b.hasEventListener=null;b._listeners=null;createjs.EventDispatcher.initialize(b);b._animations=null;b._frames=null;b._images=null;b._data=null;b._loadCount=0;b._frameHeight=0;b._frameWidth=0;b._numFrames=0;b._regX=0;b._regY=0;b.initialize=function(a){var b,g,d;if(null!=a){if(a.images&&0<(g=a.images.length)){d= 36 | this._images=[];for(b=0;bd.length||!1==a.next?null:null==a.next||!0==a.next?h:a.next;a.frequency||(a.frequency=1);this._animations.push(h);this._data[h]=a}}}};b.getNumFrames=function(a){if(null==a)return this._frames?this._frames.length:this._numFrames;a=this._data[a];return null==a?0:a.frames.length};b.getAnimations=function(){return this._animations.slice(0)};b.getAnimation=function(a){return this._data[a]};b.getFrame=function(a){var b;return this.complete&&this._frames&&(b=this._frames[a])?b:null}; 39 | b.getFrameBounds=function(a){return(a=this.getFrame(a))?new createjs.Rectangle(-a.regX,-a.regY,a.rect.width,a.rect.height):null};b.toString=function(){return"[SpriteSheet]"};b.clone=function(){var a=new c;a.complete=this.complete;a._animations=this._animations;a._frames=this._frames;a._images=this._images;a._data=this._data;a._frameHeight=this._frameHeight;a._frameWidth=this._frameWidth;a._numFrames=this._numFrames;a._loadCount=this._loadCount;return a};b._handleImageLoad=function(){0==--this._loadCount&& 40 | (this._calculateFrames(),this.complete=!0,this.onComplete&&this.onComplete(),this.dispatchEvent("complete"))};b._calculateFrames=function(){if(!(this._frames||0==this._frameWidth)){this._frames=[];for(var a=0,b=this._frameWidth,g=this._frameHeight,d=0,c=this._images;d>8&255,a=a>>16&255);return null==c?"rgb("+a+","+b+","+d+")":"rgba("+a+","+b+","+d+","+c+")"};b.getHSL=function(a,b,d,c){return null==c?"hsl("+a%360+","+b+"%,"+d+"%)":"hsla("+a%360+","+b+"%,"+d+"%,"+c+")"};b.BASE_64={A:0,B:1,C:2,D:3,E:4,F:5,G:6,H:7,I:8,J:9, 43 | K:10,L:11,M:12,N:13,O:14,P:15,Q:16,R:17,S:18,T:19,U:20,V:21,W:22,X:23,Y:24,Z:25,a:26,b:27,c:28,d:29,e:30,f:31,g:32,h:33,i:34,j:35,k:36,l:37,m:38,n:39,o:40,p:41,q:42,r:43,s:44,t:45,u:46,v:47,w:48,x:49,y:50,z:51,"0":52,1:53,2:54,3:55,4:56,5:57,6:58,7:59,8:60,9:61,"+":62,"/":63};b.STROKE_CAPS_MAP=["butt","round","square"];b.STROKE_JOINTS_MAP=["miter","round","bevel"];b._ctx=(createjs.createCanvas?createjs.createCanvas():document.createElement("canvas")).getContext("2d");b.beginCmd=new c(b._ctx.beginPath, 44 | [],!1);b.fillCmd=new c(b._ctx.fill,[],!1);b.strokeCmd=new c(b._ctx.stroke,[],!1);a._strokeInstructions=null;a._strokeStyleInstructions=null;a._ignoreScaleStroke=!1;a._fillInstructions=null;a._instructions=null;a._oldInstructions=null;a._activeInstructions=null;a._active=!1;a._dirty=!1;a.initialize=function(){this.clear();this._ctx=b._ctx};a.isEmpty=function(){return!(this._instructions.length||this._oldInstructions.length||this._activeInstructions.length)};a.draw=function(a){this._dirty&&this._updateInstructions(); 45 | for(var b=this._instructions,d=0,c=b.length;df&&(f*=n=-1);f>l&&(f=l);0>h&&(h*=q=-1);h>l&&(h=l);0>k&&(k*=p=-1);k>l&&(k=l);0>j&&(j*=s=-1);j>l&&(j=l);this._dirty=this._active=!0;var l=this._ctx.arcTo,r=this._ctx.lineTo;this._activeInstructions.push(new c(this._ctx.moveTo,[a+d-h,b]),new c(l,[a+d+h*q,b-h*q,a+d,b+h,h]),new c(r,[a+d,b+e-k]),new c(l,[a+d+k*p,b+e+k*p,a+d-k,b+e,k]),new c(r,[a+j,b+e]),new c(l,[a-j*s,b+e+j*s,a,b+e-j,j]),new c(r,[a,b+f]),new c(l,[a-f*n,b-f*n,a+f,b,f]),new c(this._ctx.closePath));return this};a.drawCircle= 54 | function(a,b,d){this.arc(a,b,d,0,2*Math.PI);return this};a.drawEllipse=function(a,b,d,e){this._dirty=this._active=!0;var f=0.5522848*(d/2),h=0.5522848*(e/2),k=a+d,j=b+e;d=a+d/2;e=b+e/2;this._activeInstructions.push(new c(this._ctx.moveTo,[a,e]),new c(this._ctx.bezierCurveTo,[a,e-h,d-f,b,d,b]),new c(this._ctx.bezierCurveTo,[d+f,b,k,e-h,k,e]),new c(this._ctx.bezierCurveTo,[k,e+h,d+f,j,d,j]),new c(this._ctx.bezierCurveTo,[d-f,j,a,e+h,a,e]));return this};a.drawPolyStar=function(a,b,d,e,f,h){this._dirty= 55 | this._active=!0;null==f&&(f=0);f=1-f;h=null==h?0:h/(180/Math.PI);var k=Math.PI/e;this._activeInstructions.push(new c(this._ctx.moveTo,[a+Math.cos(h)*d,b+Math.sin(h)*d]));for(var j=0;j>3,s=g[p];if(!s||q&3)throw"bad path data (@"+c+"): "+n;n=d[p];p||(k=j=0);h.length=0;c++;q=(q>>2&1)+2;for(p=0;p>5?-1:1,r=(r&31)<<6|l[a.charAt(c+1)];3==q&&(r=r<<6|l[a.charAt(c+2)]);r=u*r/10;p%2?k=r+=k:j=r+=j;h[p]=r;c+=q}s.apply(this,h)}return this};a.clone=function(){var a=new b;a._instructions=this._instructions.slice();a._activeInstructions=this._activeInstructions.slice(); 57 | a._oldInstructions=this._oldInstructions.slice();this._fillInstructions&&(a._fillInstructions=this._fillInstructions.slice());this._strokeInstructions&&(a._strokeInstructions=this._strokeInstructions.slice());this._strokeStyleInstructions&&(a._strokeStyleInstructions=this._strokeStyleInstructions.slice());a._active=this._active;a._dirty=this._dirty;return a};a.toString=function(){return"[Graphics]"};a.mt=a.moveTo;a.lt=a.lineTo;a.at=a.arcTo;a.bt=a.bezierCurveTo;a.qt=a.quadraticCurveTo;a.a=a.arc;a.r= 58 | a.rect;a.cp=a.closePath;a.c=a.clear;a.f=a.beginFill;a.lf=a.beginLinearGradientFill;a.rf=a.beginRadialGradientFill;a.bf=a.beginBitmapFill;a.ef=a.endFill;a.ss=a.setStrokeStyle;a.s=a.beginStroke;a.ls=a.beginLinearGradientStroke;a.rs=a.beginRadialGradientStroke;a.bs=a.beginBitmapStroke;a.es=a.endStroke;a.dr=a.drawRect;a.rr=a.drawRoundRect;a.rc=a.drawRoundRectComplex;a.dc=a.drawCircle;a.de=a.drawEllipse;a.dp=a.drawPolyStar;a.p=a.decodePath;a._updateInstructions=function(){this._instructions=this._oldInstructions.slice(); 59 | this._instructions.push(b.beginCmd);this._instructions.push.apply(this._instructions,this._activeInstructions);this._fillInstructions&&this._instructions.push.apply(this._instructions,this._fillInstructions);this._strokeInstructions&&(this._strokeStyleInstructions&&this._instructions.push.apply(this._instructions,this._strokeStyleInstructions),this._instructions.push.apply(this._instructions,this._strokeInstructions),this._ignoreScaleStroke?this._instructions.push(new c(this._ctx.save,[],!1),new c(this._ctx.setTransform, 60 | [1,0,0,1,0,0],!1),b.strokeCmd,new c(this._ctx.restore,[],!1)):this._instructions.push(b.strokeCmd))};a._newPath=function(){this._dirty&&this._updateInstructions();this._oldInstructions=this._instructions;this._activeInstructions=[];this._active=this._dirty=!1};a._setProp=function(a,b){this[a]=b};createjs.Graphics=b})();this.createjs=this.createjs||{}; 61 | (function(){var c=function(){this.initialize()},b=c.prototype;c.suppressCrossDomainErrors=!1;c._hitTestCanvas=createjs.createCanvas?createjs.createCanvas():document.createElement("canvas");c._hitTestCanvas.width=c._hitTestCanvas.height=1;c._hitTestContext=c._hitTestCanvas.getContext("2d");c._nextCacheID=1;b.alpha=1;b.cacheCanvas=null;b.id=-1;b.mouseEnabled=!0;b.name=null;b.parent=null;b.regX=0;b.regY=0;b.rotation=0;b.scaleX=1;b.scaleY=1;b.skewX=0;b.skewY=0;b.shadow=null;b.visible=!0;b.x=0;b.y=0;b.compositeOperation= 62 | null;b.snapToPixel=!1;b.onPress=null;b.onClick=null;b.onDoubleClick=null;b.onMouseOver=null;b.onMouseOut=null;b.onTick=null;b.filters=null;b.cacheID=0;b.mask=null;b.hitArea=null;b.cursor=null;b.addEventListener=null;b.removeEventListener=null;b.removeAllEventListeners=null;b.dispatchEvent=null;b.hasEventListener=null;b._listeners=null;createjs.EventDispatcher.initialize(b);b._cacheOffsetX=0;b._cacheOffsetY=0;b._cacheScale=1;b._cacheDataURLID=0;b._cacheDataURL=null;b._matrix=null;b.initialize=function(){this.id= 63 | createjs.UID.get();this._matrix=new createjs.Matrix2D};b.isVisible=function(){return!(!this.visible||!(0d||d>this.children.length)return arguments[c-2];if(2a||a>this.children.length- 77 | 1)return!1;if(b=this.children[a])b.parent=null;this.children.splice(a,1);return!0};b.removeAllChildren=function(){for(var a=this.children;a.length;)a.pop().parent=null};b.getChildAt=function(a){return this.children[a]};b.getChildByName=function(a){for(var b=this.children,c=0,d=b.length;cb||b>=d)){for(var e=0;e=a)return;var b=this;this._mouseOverIntervalID=setInterval(function(){b._testMouseOver()},1E3/Math.min(50,a))};b.enableDOMEvents=function(a){null==a&&(a=!0);var b,c=this._eventListeners;if(!a&&c){for(b in c)a=c[b],a.t.removeEventListener(b,a.f);this._eventListeners=null}else if(a&&!c&&this.canvas){a=window.addEventListener?window:document;var d=this,c=this._eventListeners={};c.mouseup={t:a,f:function(a){d._handleMouseUp(a)}}; 87 | c.mousemove={t:a,f:function(a){d._handleMouseMove(a)}};c.dblclick={t:a,f:function(a){d._handleDoubleClick(a)}};c.mousedown={t:this.canvas,f:function(a){d._handleMouseDown(a)}};for(b in c)a=c[b],a.t.addEventListener(b,a.f)}};b.clone=function(){var a=new c(null);this.cloneProps(a);return a};b.toString=function(){return"[Stage (name="+this.name+")]"};b._getPointerData=function(a){var b=this._pointerData[a];if(!b&&(b=this._pointerData[a]={x:0,y:0},null==this._primaryPointerID||-1==this._primaryPointerID))this._primaryPointerID= 88 | a;return b};b._handleMouseMove=function(a){a||(a=window.event);this._handlePointerMove(-1,a,a.pageX,a.pageY)};b._handlePointerMove=function(a,b,c,d){if(this.canvas){var e=this._getPointerData(a),f=e.inBounds;this._updatePointerPosition(a,c,d);if(f||e.inBounds||this.mouseMoveOutside){if(this.onMouseMove||this.hasEventListener("stagemousemove"))c=new createjs.MouseEvent("stagemousemove",e.x,e.y,this,b,a,a==this._primaryPointerID,e.rawX,e.rawY),this.onMouseMove&&this.onMouseMove(c),this.dispatchEvent(c); 89 | if((d=e.event)&&(d.onMouseMove||d.hasEventListener("mousemove")))c=new createjs.MouseEvent("mousemove",e.x,e.y,d.target,b,a,a==this._primaryPointerID,e.rawX,e.rawY),d.onMouseMove&&d.onMouseMove(c),d.dispatchEvent(c,d.target)}}};b._updatePointerPosition=function(a,b,c){var d=this._getElementRect(this.canvas);b-=d.left;c-=d.top;var e=this.canvas.width,f=this.canvas.height;b/=(d.right-d.left)/e;c/=(d.bottom-d.top)/f;d=this._getPointerData(a);(d.inBounds=0<=b&&0<=c&&b<=e-1&&c<=f-1)?(d.x=b,d.y=c):this.mouseMoveOutside&& 90 | (d.x=0>b?0:b>e-1?e-1:b,d.y=0>c?0:c>f-1?f-1:c);d.rawX=b;d.rawY=c;a==this._primaryPointerID&&(this.mouseX=d.x,this.mouseY=d.y,this.mouseInBounds=d.inBounds)};b._getElementRect=function(a){var b;try{b=a.getBoundingClientRect()}catch(c){b={top:a.offsetTop,left:a.offsetLeft,width:a.offsetWidth,height:a.offsetHeight}}var d=(window.pageXOffset||document.scrollLeft||0)-(document.clientLeft||document.body.clientLeft||0),e=(window.pageYOffset||document.scrollTop||0)-(document.clientTop||document.body.clientTop|| 91 | 0),f=window.getComputedStyle?getComputedStyle(a):a.currentStyle;a=parseInt(f.paddingLeft)+parseInt(f.borderLeftWidth);var h=parseInt(f.paddingTop)+parseInt(f.borderTopWidth),k=parseInt(f.paddingRight)+parseInt(f.borderRightWidth),f=parseInt(f.paddingBottom)+parseInt(f.borderBottomWidth);return{left:b.left+d+a,right:b.right+d-k,top:b.top+e+h,bottom:b.bottom+e-f}};b._handleMouseUp=function(a){this._handlePointerUp(-1,a,!1)};b._handlePointerUp=function(a,b,c){var d=this._getPointerData(a),e;if(this.onMouseMove|| 92 | this.hasEventListener("stagemouseup"))e=new createjs.MouseEvent("stagemouseup",d.x,d.y,this,b,a,a==this._primaryPointerID,d.rawX,d.rawY),this.onMouseUp&&this.onMouseUp(e),this.dispatchEvent(e);var f=d.event;if(f&&(f.onMouseUp||f.hasEventListener("mouseup")))e=new createjs.MouseEvent("mouseup",d.x,d.y,f.target,b,a,a==this._primaryPointerID,d.rawX,d.rawY),f.onMouseUp&&f.onMouseUp(e),f.dispatchEvent(e,f.target);if((f=d.target)&&(f.onClick||f.hasEventListener("click"))&&this._getObjectsUnderPoint(d.x, 93 | d.y,null,!0,this._mouseOverIntervalID?3:1)==f)e=new createjs.MouseEvent("click",d.x,d.y,f,b,a,a==this._primaryPointerID,d.rawX,d.rawY),f.onClick&&f.onClick(e),f.dispatchEvent(e);c?(a==this._primaryPointerID&&(this._primaryPointerID=null),delete this._pointerData[a]):d.event=d.target=null};b._handleMouseDown=function(a){this._handlePointerDown(-1,a,!1)};b._handlePointerDown=function(a,b,c,d){var e=this._getPointerData(a);null!=d&&this._updatePointerPosition(a,c,d);if(this.onMouseDown||this.hasEventListener("stagemousedown"))c= 94 | new createjs.MouseEvent("stagemousedown",e.x,e.y,this,b,a,a==this._primaryPointerID,e.rawX,e.rawY),this.onMouseDown&&this.onMouseDown(c),this.dispatchEvent(c);if(d=this._getObjectsUnderPoint(e.x,e.y,null,this._mouseOverIntervalID?3:1))if(e.target=d,d.onPress||d.hasEventListener("mousedown"))if(c=new createjs.MouseEvent("mousedown",e.x,e.y,d,b,a,a==this._primaryPointerID,e.rawX,e.rawY),d.onPress&&d.onPress(c),d.dispatchEvent(c),c.onMouseMove||c.onMouseUp||c.hasEventListener("mousemove")||c.hasEventListener("mouseup"))e.event= 95 | c};b._testMouseOver=function(){if(-1==this._primaryPointerID&&!(this.mouseX==this._mouseOverX&&this.mouseY==this._mouseOverY&&this.mouseInBounds)){var a=null;this.mouseInBounds&&(a=this._getObjectsUnderPoint(this.mouseX,this.mouseY,null,3),this._mouseOverX=this.mouseX,this._mouseOverY=this.mouseY);var b=this._mouseOverTarget;if(b!=a){var c=this._getPointerData(-1);if(b&&(b.onMouseOut||b.hasEventListener("mouseout"))){var d=new createjs.MouseEvent("mouseout",c.x,c.y,b,null,-1,c.rawX,c.rawY);b.onMouseOut&& 96 | b.onMouseOut(d);b.dispatchEvent(d)}b&&(this.canvas.style.cursor="");if(a&&(a.onMouseOver||a.hasEventListener("mouseover")))d=new createjs.MouseEvent("mouseover",c.x,c.y,a,null,-1,c.rawX,c.rawY),a.onMouseOver&&a.onMouseOver(d),a.dispatchEvent(d);a&&(this.canvas.style.cursor=a.cursor||"");this._mouseOverTarget=a}}};b._handleDoubleClick=function(a){var b=this._getPointerData(-1),c=this._getObjectsUnderPoint(b.x,b.y,null,this._mouseOverIntervalID?3:1);if(c&&(c.onDoubleClick||c.hasEventListener("dblclick")))evt= 97 | new createjs.MouseEvent("dblclick",b.x,b.y,c,a,-1,!0,b.rawX,b.rawY),c.onDoubleClick&&c.onDoubleClick(evt),c.dispatchEvent(evt)};createjs.Stage=c})();this.createjs=this.createjs||{}; 98 | (function(){var c=function(a){this.initialize(a)},b=c.prototype=new createjs.DisplayObject;b.image=null;b.snapToPixel=!0;b.sourceRect=null;b.DisplayObject_initialize=b.initialize;b.initialize=function(a){this.DisplayObject_initialize();"string"==typeof a?(this.image=new Image,this.image.src=a):this.image=a};b.isVisible=function(){var a=this.cacheCanvas||this.image&&(this.image.complete||this.image.getContext||2<=this.image.readyState);return!(!this.visible||!(0=d){var e=a.next;this._dispatchAnimationEnd(a,b,c,e,d-1)||(e?this._goto(e):(this.paused=!0,this.currentAnimationFrame=a.frames.length-1,this.currentFrame= 104 | a.frames[this.currentAnimationFrame]))}else this.currentFrame=a.frames[this.currentAnimationFrame];else d=this.spriteSheet.getNumFrames(),b>=d&&!this._dispatchAnimationEnd(a,b,c,d-1)&&(this.currentFrame=0)};b._dispatchAnimationEnd=function(a,b,c,d,e){var f=a?a.name:null;this.onAnimationEnd&&this.onAnimationEnd(this,f,d);this.dispatchEvent({type:"animationend",name:f,next:d});!c&&this.paused&&(this.currentAnimationFrame=e);return this.paused!=c||this._animation!=a||this.currentFrame!=b};b.DisplayObject_cloneProps= 105 | b.cloneProps;b.cloneProps=function(a){this.DisplayObject_cloneProps(a);a.onAnimationEnd=this.onAnimationEnd;a.currentFrame=this.currentFrame;a.currentAnimation=this.currentAnimation;a.paused=this.paused;a.offset=this.offset;a._animation=this._animation;a.currentAnimationFrame=this.currentAnimationFrame};b._goto=function(a){if(isNaN(a)){var b=this.spriteSheet.getAnimation(a);b&&(this.currentAnimationFrame=0,this._animation=b,this.currentAnimation=a,this._normalizeFrame())}else this.currentAnimation= 106 | this._animation=null,this.currentFrame=a};createjs.BitmapAnimation=c})();this.createjs=this.createjs||{}; 107 | (function(){var c=function(a){this.initialize(a)},b=c.prototype=new createjs.DisplayObject;b.graphics=null;b.DisplayObject_initialize=b.initialize;b.initialize=function(a){this.DisplayObject_initialize();this.graphics=a?a:new createjs.Graphics};b.isVisible=function(){var a=this.cacheCanvas||this.graphics&&!this.graphics.isEmpty();return!(!this.visible||!(0this.lineWidth?(b&&this._drawTextLine(a,j,e*d),e++,j=k[l+1]):j+=k[l]+k[l+1];b&&this._drawTextLine(a,j,e*d)}e++}return e};b._drawTextLine=function(a,b,c){this.outline?a.strokeText(b,0,c,this.maxWidth||65535):a.fillText(b,0,c,this.maxWidth||65535)};createjs.Text=c})();this.createjs=this.createjs||{}; 114 | (function(){var c=function(){throw"SpriteSheetUtils cannot be instantiated";};c._workingCanvas=createjs.createCanvas?createjs.createCanvas():document.createElement("canvas");c._workingContext=c._workingCanvas.getContext("2d");c.addFlippedFrames=function(b,a,m,g){if(a||m||g){var d=0;a&&c._flip(b,++d,!0,!1);m&&c._flip(b,++d,!1,!0);g&&c._flip(b,++d,!0,!0)}};c.extractFrame=function(b,a){isNaN(a)&&(a=b.getAnimation(a).frames[0]);var m=b.getFrame(a);if(!m)return null;var g=m.rect,d=c._workingCanvas;d.width= 115 | g.width;d.height=g.height;c._workingContext.drawImage(m.image,g.x,g.y,g.width,g.height,0,0,g.width,g.height);m=new Image;m.src=d.toDataURL("image/png");return m};c.mergeAlpha=function(b,a,c){c||(c=createjs.createCanvas?createjs.createCanvas():document.createElement("canvas"));c.width=Math.max(a.width,b.width);c.height=Math.max(a.height,b.height);var g=c.getContext("2d");g.save();g.drawImage(b,0,0);g.globalCompositeOperation="destination-in";g.drawImage(a,0,0);g.restore();return c};c._flip=function(b, 116 | a,m,g){for(var d=b._images,e=c._workingCanvas,f=c._workingContext,h=d.length/a,k=0;kthis.maxHeight)throw c.ERR_DIMENSIONS;for(var d=0,e=0,f=0;g.length;){var h=this._fillRow(g,d,f,b,a);h.w>e&&(e=h.w);d+=h.h;if(!h.h||!g.length){var k=createjs.createCanvas?createjs.createCanvas():document.createElement("canvas");k.width=this._getSize(e,this.maxWidth);k.height=this._getSize(d,this.maxHeight);this._data.images[f]=k;h.h||(e=d=0,f++)}}};b._getSize=function(a,b){for(var c=4;Math.pow(2,++c)f)throw c.ERR_DIMENSIONS;t>h||k+p>f||(n.img=g,n.rect=new createjs.Rectangle(k,b,p,t),j=j||t,a.splice(l,1),d[n.index]=[k,b,p,t,g,Math.round(-r+q*s.regX-e),Math.round(-u+q*s.regY-e)],k+=p)}return{w:k,h:j}};b._endBuild=function(){this.spriteSheet=new createjs.SpriteSheet(this._data); 125 | this._data=null;this.progress=1;this.onComplete&&this.onComplete(this);this.dispatchEvent("complete")};b._run=function(){for(var a=50*Math.max(0.01,Math.min(0.99,this.timeSlice||0.3)),b=(new Date).getTime()+a,c=!1;b>(new Date).getTime();)if(!this._drawNext()){c=!0;break}if(c)this._endBuild();else{var d=this;this._timerID=setTimeout(function(){d._run()},50-a)}a=this.progress=this._index/this._frames.length;this.onProgress&&this.onProgress(this,a);this.dispatchEvent({type:"progress",progress:a})};b._drawNext= 126 | function(){var a=this._frames[this._index],b=a.scale*this._scale,c=a.rect,d=a.sourceRect,e=this._data.images[a.img].getContext("2d");a.funct&&a.funct.apply(a.scope,a.params);e.save();e.beginPath();e.rect(c.x,c.y,c.width,c.height);e.clip();e.translate(Math.ceil(c.x-d.x*b),Math.ceil(c.y-d.y*b));e.scale(b,b);a.source.draw(e);e.restore();return++this._index