├── Gemfile ├── Gemfile.lock ├── config.ru ├── examples ├── model │ ├── config.kb │ ├── deps.js │ ├── index.html │ ├── index_source.html │ └── modelDemo.js ├── nav_picture │ ├── compiled.js │ ├── config.kb │ ├── demoBase.js │ ├── demoHost.js │ ├── deps.js │ ├── index.html │ ├── index_source.html │ └── navLayerDemo.js └── retained │ ├── compiled.js │ ├── config.kb │ ├── demoHost.js │ ├── demos │ ├── carouselDemo.js │ ├── demoBase.js │ ├── demos.js │ ├── graphDemo.js │ ├── navLayerDemo.js │ ├── rotateTextDemo.js │ ├── scaleDemo.js │ ├── squares.js │ ├── swapDemo.js │ └── tileDemo.js │ ├── deps.js │ ├── index.html │ ├── index_source.html │ └── resources │ ├── common.css │ ├── demo.css │ ├── flatmenubutton.css │ ├── menu.css │ ├── menubutton.css │ ├── menuitem.css │ ├── menuseparator.css │ ├── pixellab.png │ ├── pixellab_transparent.png │ └── stars.png ├── readme.md ├── src ├── behavior.js ├── box2d │ ├── README.md │ ├── collision │ │ ├── ClipVertex.js │ │ ├── Features.js │ │ ├── b2AABB.js │ │ ├── b2Bound.js │ │ ├── b2BoundValues.js │ │ ├── b2BroadPhase.js │ │ ├── b2BufferedPair.js │ │ ├── b2Collision.js │ │ ├── b2ContactID.js │ │ ├── b2ContactPoint.js │ │ ├── b2Distance.js │ │ ├── b2Manifold.js │ │ ├── b2OBB.js │ │ ├── b2Pair.js │ │ ├── b2PairCallback.js │ │ ├── b2PairManager.js │ │ ├── b2Proxy.js │ │ └── shapes │ │ │ ├── b2BoxDef.js │ │ │ ├── b2CircleDef.js │ │ │ ├── b2CircleShape.js │ │ │ ├── b2MassData.js │ │ │ ├── b2PolyDef.js │ │ │ ├── b2PolyShape.js │ │ │ ├── b2Shape.js │ │ │ ├── b2ShapeDef.js │ │ │ └── b2ShapeFactory.js │ ├── common │ │ ├── b2Mat22.js │ │ ├── b2Math.js │ │ ├── b2Settings.js │ │ └── b2Vec2.js │ └── dynamics │ │ ├── b2Body.js │ │ ├── b2BodyDef.js │ │ ├── b2CollisionFilter.js │ │ ├── b2ContactManager.js │ │ ├── b2Island.js │ │ ├── b2TimeStep.js │ │ ├── b2World.js │ │ ├── b2WorldListener.js │ │ ├── contacts │ │ ├── b2CircleContact.js │ │ ├── b2Conservative.js │ │ ├── b2Contact.js │ │ ├── b2ContactConstraint.js │ │ ├── b2ContactConstraintPoint.js │ │ ├── b2ContactFactory.js │ │ ├── b2ContactNode.js │ │ ├── b2ContactRegister.js │ │ ├── b2ContactSolver.js │ │ ├── b2NullContact.js │ │ ├── b2PolyAndCircleContact.js │ │ └── b2PolyContact.js │ │ └── joints │ │ ├── b2DistanceJoint.js │ │ ├── b2DistanceJointDef.js │ │ ├── b2GearJoint.js │ │ ├── b2GearJointDef.js │ │ ├── b2Jacobian.js │ │ ├── b2Joint.js │ │ ├── b2JointDef.js │ │ ├── b2JointFactory.js │ │ ├── b2JointNode.js │ │ ├── b2MouseJoint.js │ │ ├── b2MouseJointDef.js │ │ ├── b2PrismaticJoint.js │ │ ├── b2PrismaticJointDef.js │ │ ├── b2PulleyJoint.js │ │ ├── b2PulleyJointDef.js │ │ ├── b2RevoluteJoint.js │ │ └── b2RevoluteJointDef.js ├── data │ └── model.js ├── debugDiv.js ├── ex.js ├── fpsLogger.js ├── gfx.js ├── graph.js ├── graphPhysics.js ├── graphPoint.js ├── images.js ├── keyBinding.js ├── property.js ├── qr │ ├── qr8BitByte.js │ ├── qrBitBuffer.js │ ├── qrCode.js │ ├── qrEnums.js │ ├── qrMath.js │ ├── qrPolynomial.js │ ├── qrRSBlock.js │ ├── qrUtil.js │ └── readme.md ├── retained │ ├── _navLayerTxPanel.js │ ├── alignment.js │ ├── animation.js │ ├── canvas.js │ ├── carouselPanel.js │ ├── element.js │ ├── elementParent.js │ ├── eventType.js │ ├── graphElement.js │ ├── helper.js │ ├── image.js │ ├── mouse.js │ ├── navLayer.js │ ├── panel.js │ ├── shape.js │ ├── stage.js │ ├── text.js │ └── tileLayer.js ├── soundEffect.js └── stats.js └── test ├── config.kb ├── deps.js ├── pl.ex_test.html ├── pl.graph_test.html ├── pl.model_test.html └── pl.property_test.html /Gemfile: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | 3 | gem 'rack' 4 | -------------------------------------------------------------------------------- /Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | rack (1.5.2) 5 | 6 | PLATFORMS 7 | ruby 8 | 9 | DEPENDENCIES 10 | rack 11 | -------------------------------------------------------------------------------- /config.ru: -------------------------------------------------------------------------------- 1 | map '/closure' do 2 | run Rack::Directory.new('../closure') 3 | end 4 | 5 | map '/pl' do 6 | run Rack::Directory.new(Dir.pwd) 7 | end 8 | 9 | map '/' do 10 | run Rack::Directory.new(Dir.pwd) 11 | end -------------------------------------------------------------------------------- /examples/model/config.kb: -------------------------------------------------------------------------------- 1 | closure_path: ../../../closure 2 | inputs: 3 | - modelDemo.js 4 | js_paths: 5 | - . 6 | - ../../src 7 | deps_path: deps.js 8 | compile_path: compiled.js 9 | externs: [] 10 | fix_paths: 11 | - ../../src 12 | - modelDemo.js 13 | -------------------------------------------------------------------------------- /examples/model/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 |
16 | 17 |
18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /examples/model/index_source.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 |
12 | 13 | 14 | -------------------------------------------------------------------------------- /examples/model/modelDemo.js: -------------------------------------------------------------------------------- 1 | goog.provide('ModelDemo'); 2 | 3 | goog.require('goog.asserts'); 4 | goog.require('goog.dom'); 5 | goog.require('goog.object'); 6 | goog.require('goog.string'); 7 | goog.require('goog.style'); 8 | goog.require('pl.data.Model'); 9 | 10 | /** 11 | * @constructor 12 | */ 13 | ModelDemo = function() { 14 | var m = new pl.data.Model(); 15 | alert(m.name); 16 | }; 17 | -------------------------------------------------------------------------------- /examples/nav_picture/config.kb: -------------------------------------------------------------------------------- 1 | closure_path: ../../../closure 2 | inputs: 3 | - demoHost.js 4 | js_paths: 5 | - . 6 | - ../../src 7 | deps_path: deps.js 8 | compile_path: compiled.js 9 | externs: [] 10 | fix_paths: 11 | - ../../src 12 | - demoHost.js 13 | - demos 14 | -------------------------------------------------------------------------------- /examples/nav_picture/demoBase.js: -------------------------------------------------------------------------------- 1 | goog.provide('demos.DemoBase'); 2 | 3 | goog.require('goog.array'); 4 | goog.require('goog.asserts'); 5 | goog.require('goog.debug.Logger'); 6 | goog.require('pl.retained.Element'); 7 | goog.require('pl.retained.EventType'); 8 | goog.require('pl.retained.Stage'); 9 | 10 | 11 | 12 | /** 13 | * @constructor 14 | * @extends {goog.events.EventTarget} 15 | * @param {!HTMLCanvasElement} canvas 16 | * @param {!pl.retained.Element} rootElement 17 | */ 18 | demos.DemoBase = function(canvas, rootElement) { 19 | goog.base(this); 20 | this._canvas = canvas; 21 | 22 | /** 23 | * @private 24 | * @type {!pl.retained.Stage} 25 | */ 26 | this._stage = new pl.retained.Stage(canvas, rootElement); 27 | 28 | this._stage.addEventListener(pl.retained.EventType.UPDATE, function(e) { 29 | this.dispatchEvent(pl.retained.EventType.UPDATE); 30 | }, 31 | false, this); 32 | }; 33 | goog.inherits(demos.DemoBase, goog.events.EventTarget); 34 | 35 | 36 | /** 37 | * @protected 38 | * @return {!pl.retained.Stage} 39 | */ 40 | demos.DemoBase.prototype.getStage = function() { 41 | return this._stage; 42 | }; 43 | 44 | 45 | /** 46 | * @protected 47 | * @return {!HTMLCanvasElement} 48 | */ 49 | demos.DemoBase.prototype.getCanvas = function() { 50 | return this._canvas; 51 | }; 52 | 53 | 54 | /** 55 | * @return {boolean} 56 | */ 57 | demos.DemoBase.prototype.frame = function() { 58 | return this._stage.draw(); 59 | }; 60 | 61 | demos.DemoBase.prototype._logger = goog.debug.LogManager.getRoot(); 62 | 63 | demos.DemoBase.prototype.log = function(msg) { 64 | this._logger.info(msg); 65 | }; 66 | -------------------------------------------------------------------------------- /examples/nav_picture/demoHost.js: -------------------------------------------------------------------------------- 1 | goog.provide('DemoHost'); 2 | 3 | goog.require('demos.NavLayerDemo'); 4 | goog.require('goog.Timer'); 5 | goog.require('goog.asserts'); 6 | goog.require('goog.debug.Console'); 7 | goog.require('goog.debug.LogManager'); 8 | goog.require('goog.dom'); 9 | goog.require('goog.fx.anim'); 10 | goog.require('goog.fx.anim.Animated'); 11 | goog.require('goog.string'); 12 | goog.require('pl.FpsLogger'); 13 | goog.require('pl.retained.EventType'); 14 | 15 | 16 | 17 | /** 18 | * @constructor 19 | * @implements {goog.fx.anim.Animated} 20 | */ 21 | DemoHost = function(opt_canvas) { 22 | this._logger = goog.debug.LogManager.getRoot(); 23 | this._fpsLogger = new pl.FpsLogger(); 24 | 25 | this._requestFrame(); 26 | this._canvas = opt_canvas; 27 | this._loadDemo(demos.NavLayerDemo); 28 | }; 29 | 30 | 31 | /** 32 | * @export 33 | */ 34 | DemoHost.load = function(opt_canvas) { 35 | goog.debug.Console.autoInstall(); 36 | goog.debug.Console.instance.setCapturing(true); 37 | goog.global['$demoHost'] = new DemoHost(opt_canvas); 38 | 39 | goog.debug.LogManager.getRoot().config('load finished'); 40 | }; 41 | 42 | DemoHost.prototype._frameMs = 0; 43 | 44 | 45 | /** 46 | * @param {function(new:demos.DemoBase, !HTMLCanvasElement)} demoCtr 47 | */ 48 | DemoHost.prototype._loadDemo = function(demoCtr) { 49 | if (this._canvas == null) { 50 | this._canvas = document.getElementById('content'); 51 | } 52 | goog.style.setStyle(this._canvas, 'background', 'black'); 53 | 54 | this._demo = new demoCtr(this._canvas); 55 | this._demo.addEventListener(pl.retained.EventType.UPDATE, function(e) { 56 | this._requestFrame(); 57 | }, 58 | false, this); 59 | 60 | this._requestFrame(); 61 | }; 62 | 63 | 64 | /** 65 | * Function called when a frame is requested for the animation. 66 | * 67 | * @param {number} now Current time in milliseconds. 68 | */ 69 | DemoHost.prototype.onAnimationFrame = function(now) { 70 | this._fpsLogger.AddInterval(); 71 | this._demo.frame(); 72 | }; 73 | 74 | DemoHost.prototype._requestFrame = function() { 75 | goog.fx.anim.registerAnimation(this); 76 | }; 77 | -------------------------------------------------------------------------------- /examples/nav_picture/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 |
11 | 12 | 13 | -------------------------------------------------------------------------------- /examples/nav_picture/index_source.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 |
13 | 14 | 15 | -------------------------------------------------------------------------------- /examples/nav_picture/navLayerDemo.js: -------------------------------------------------------------------------------- 1 | goog.provide('demos.NavLayerDemo'); 2 | 3 | goog.require('demos.DemoBase'); 4 | goog.require('goog.events'); 5 | goog.require('goog.events.EventType'); 6 | goog.require('goog.math.Coordinate'); 7 | goog.require('pl.retained.Canvas'); 8 | goog.require('pl.retained.NavLayer'); 9 | goog.require('pl.retained.Shape'); 10 | goog.require('pl.retained.Stage'); 11 | goog.require('pl.retained.Text'); 12 | goog.require('pl.retained.mouse'); 13 | 14 | 15 | 16 | /** 17 | * @constructor 18 | * @extends {demos.DemoBase} 19 | */ 20 | demos.NavLayerDemo = function(canvas) { 21 | this._nav = new pl.retained.NavLayer(canvas.width, canvas.height); 22 | 23 | goog.base(this, canvas, this._nav); 24 | 25 | var self = this; 26 | canvas.addEventListener('touchstart', function(e) { self._onTouchStart(e); } ); 27 | canvas.addEventListener('mousedown', function(e) { self._onMouseDown(e); } ); 28 | this._count = 0; 29 | this._forward(new goog.graphics.AffineTransform()); 30 | }; 31 | goog.inherits(demos.NavLayerDemo, demos.DemoBase); 32 | 33 | demos.NavLayerDemo.prototype._forward = function(tx) { 34 | if (this._nav.canForward()) { 35 | var demoElement = demos.NavLayerDemo._getX(++this._count); 36 | this._nav.forward(demoElement, tx); 37 | } 38 | }; 39 | 40 | demos.NavLayerDemo.prototype._onTouchStart = function(e) { 41 | e.preventDefault(); 42 | e.stopPropagation(); 43 | var touch = e.touches[0]; 44 | this.log(['touch[0]', touch.clientX, touch.clientY]); 45 | 46 | // TODO: note touch events have no 'offset'...at least not everywhere 47 | // in Chrome, but not other browsers 48 | // Should address this 49 | var coord = new goog.math.Coordinate(touch.clientX, touch.clientY); 50 | 51 | this.log(['coord', coord]); 52 | 53 | this._onPointInput(coord); 54 | }; 55 | 56 | demos.NavLayerDemo.prototype._onMouseDown = function(e) { 57 | e.preventDefault(); 58 | e.stopPropagation(); 59 | this._onPointInput(new goog.math.Coordinate(e.offsetX, e.offsetY)); 60 | }; 61 | 62 | demos.NavLayerDemo.prototype._onPointInput = function(coordinate) { 63 | this._lastMouse = coordinate; 64 | var hits = pl.retained.mouse.markMouseOver(this.getStage(), this._lastMouse); 65 | 66 | if (hits && hits.length) { 67 | var last = hits[hits.length - 1]; 68 | this._itemClick(last); 69 | } 70 | } 71 | 72 | demos.NavLayerDemo.prototype._itemClick = function(element) { 73 | var tx = new goog.graphics.AffineTransform(); 74 | if (element == this._nav || element.width === 300) { 75 | tx = goog.graphics.AffineTransform.getTranslateInstance(100, 100).scale(1 / 3, 1 / 3).createInverse(); 76 | } else { 77 | var widthRatio = element.width / 300; 78 | var heightRatio = element.height / 300; 79 | 80 | var lastTx = element.getTransform(); 81 | var x = lastTx.getTranslateX(); 82 | var y = lastTx.getTranslateY(); 83 | 84 | tx = goog.graphics.AffineTransform.getTranslateInstance(x, y).scale(widthRatio, heightRatio); 85 | } 86 | this._forward(tx); 87 | }; 88 | 89 | demos.NavLayerDemo._getX = function(count) { 90 | var container = new pl.retained.Canvas(300, 300); 91 | 92 | var back = new pl.retained.Shape(300, 300); 93 | back.fillStyle = '#333'; 94 | back.alpha = 0.5; 95 | container.addElement(back); 96 | 97 | var text = new pl.retained.Text('Click here\n\n' + count, 100, 100); 98 | text.isCentered = true; 99 | text.fillStyle = 'white'; 100 | text.textFillStyle = 'black'; 101 | text.multiLine = true; 102 | 103 | container.addElement(text); 104 | container.topLeft(text, new goog.math.Coordinate(100, 100)); 105 | 106 | var corner; 107 | 108 | // top left 109 | corner = new pl.retained.Shape(100, 100); 110 | corner.fillStyle = 'red'; 111 | container.addElement(corner); 112 | container.topLeft(corner, new goog.math.Coordinate(0, 0)); 113 | 114 | // top right 115 | corner = new pl.retained.Shape(100, 100); 116 | corner.fillStyle = 'green'; 117 | container.addElement(corner); 118 | container.topLeft(corner, new goog.math.Coordinate(200, 0)); 119 | 120 | // bottom left 121 | corner = new pl.retained.Shape(100, 100); 122 | corner.fillStyle = 'blue'; 123 | container.addElement(corner); 124 | container.topLeft(corner, new goog.math.Coordinate(0, 200)); 125 | 126 | // bottom right 127 | corner = new pl.retained.Shape(100, 100); 128 | corner.fillStyle = 'yellow'; 129 | container.addElement(corner); 130 | container.topLeft(corner, new goog.math.Coordinate(200, 200)); 131 | 132 | return container; 133 | }; 134 | -------------------------------------------------------------------------------- /examples/retained/config.kb: -------------------------------------------------------------------------------- 1 | closure_path: ../../../closure 2 | inputs: 3 | - demoHost.js 4 | js_paths: 5 | - . 6 | - ../../src 7 | deps_path: deps.js 8 | compile_path: compiled.js 9 | externs: [] 10 | fix_paths: 11 | - ../../src 12 | - demoHost.js 13 | - demos 14 | -------------------------------------------------------------------------------- /examples/retained/demoHost.js: -------------------------------------------------------------------------------- 1 | goog.provide('DemoHost'); 2 | 3 | goog.require('demos'); 4 | goog.require('goog.History'); 5 | goog.require('goog.Timer'); 6 | goog.require('goog.asserts'); 7 | goog.require('goog.debug.LogManager'); 8 | goog.require('goog.dom'); 9 | goog.require('goog.fx.anim'); 10 | goog.require('goog.fx.anim.Animated'); 11 | goog.require('goog.object'); 12 | goog.require('goog.string'); 13 | goog.require('goog.style'); 14 | goog.require('goog.ui.Component.EventType'); 15 | goog.require('goog.ui.MenuItem'); 16 | goog.require('goog.ui.Select'); 17 | goog.require('pl.DebugDiv'); 18 | goog.require('pl.FpsLogger'); 19 | goog.require('pl.ex'); 20 | goog.require('pl.images'); 21 | goog.require('pl.retained.EventType'); 22 | 23 | 24 | 25 | /** 26 | * @constructor 27 | * @implements {goog.fx.anim.Animated} 28 | */ 29 | DemoHost = function() { 30 | pl.DebugDiv.enable(); 31 | goog.style.setUnselectable(document.body, true); 32 | 33 | this._logger = goog.debug.LogManager.getRoot(); 34 | this._fpsLogger = new pl.FpsLogger(); 35 | 36 | // 37 | // Demo Selector 38 | // 39 | this._selectControl = new goog.ui.Select('Pick a demo...'); 40 | goog.object.forEach(demos.all, function(e, k, o) { 41 | this._selectControl.addItem(new goog.ui.MenuItem(k)); 42 | }, 43 | this); 44 | this._selectControl.render(goog.dom.getElement('DemoSelect')); 45 | 46 | goog.events.listen(this._selectControl, goog.ui.Component.EventType.ACTION, function(e) { 47 | var value = goog.string.urlEncode(e.target.getValue()); 48 | this._history.setToken(value); 49 | }, 50 | false, this); 51 | 52 | // 53 | // History! 54 | // 55 | var historyElement = 56 | /** @type {!HTMLInputElement} */ (document.getElementById('history_state')); 57 | 58 | this._history = new goog.History(false, undefined, historyElement); 59 | this._history.addEventListener(goog.history.EventType.NAVIGATE, this._navigate, false, this); 60 | this._history.setEnabled(true); 61 | 62 | this._requestFrame(); 63 | this._updateHUD(); 64 | }; 65 | 66 | 67 | /** 68 | * @export 69 | */ 70 | DemoHost.load = function() { 71 | DemoHost.images = new pl.images({ 72 | 'stars': 'resources/stars.png', 73 | 'pixellab': 'resources/pixellab.png', 74 | 'pixellab_transparent': 'resources/pixellab_transparent.png' 75 | }); 76 | DemoHost.images.load(function(p) {}, 77 | function() { 78 | goog.global['$demoHost'] = new DemoHost(); 79 | }); 80 | }; 81 | 82 | DemoHost.images = null; 83 | 84 | DemoHost.prototype._frameMs = 0; 85 | 86 | DemoHost.prototype._navigate = function(e) { 87 | var demoName; 88 | if (e.token.length === 0) { 89 | demoName = /** @type {string} */ (goog.object.getAnyKey(demos.all)); 90 | } else { 91 | demoName = goog.string.urlDecode(e.token); 92 | } 93 | var demo = demos.all[demoName]; 94 | goog.asserts.assert(demo, 'should have a valid demo here!'); 95 | this._selectControl.setValue(demoName); 96 | this._loadDemo(demo); 97 | }; 98 | 99 | 100 | /** 101 | * @param {function(new:demos.DemoBase, !HTMLCanvasElement)} demoCtr 102 | */ 103 | DemoHost.prototype._loadDemo = function(demoCtr) { 104 | var oldCanvas = document.getElementById('content'); 105 | var newCanvas = /** @type {!HTMLCanvasElement} */ (goog.dom.createDom('canvas', { 106 | 'id': 'content', 107 | 'width': oldCanvas.width, 108 | 'height': oldCanvas.height 109 | })); 110 | goog.style.setStyle(newCanvas, 'background', 'black'); 111 | goog.dom.replaceNode(newCanvas, oldCanvas); 112 | 113 | if (this._demo) { 114 | this._demo.dispose(); 115 | this._demo = null; 116 | } 117 | 118 | this._demo = new demoCtr(newCanvas); 119 | this._demo.addEventListener(pl.retained.EventType.UPDATE, function(e) { 120 | this._requestFrame(); 121 | }, 122 | false, this); 123 | 124 | this._requestFrame(); 125 | }; 126 | 127 | 128 | /** 129 | * Function called when a frame is requested for the animation. 130 | * 131 | * @param {number} now Current time in milliseconds. 132 | */ 133 | DemoHost.prototype.onAnimationFrame = function(now) { 134 | this._fpsLogger.AddInterval(); 135 | 136 | if (this._demo && this._demo.frame()) { 137 | // no-op 138 | } else { 139 | goog.fx.anim.unregisterAnimation(this); 140 | } 141 | }; 142 | 143 | DemoHost.prototype._requestFrame = function() { 144 | goog.fx.anim.registerAnimation(this); 145 | }; 146 | 147 | DemoHost.prototype._updateHUD = function() { 148 | pl.DebugDiv.clear(); 149 | this._logger.info(String(this._fpsLogger.fps)); 150 | 151 | var func = goog.bind(this._updateHUD, this); 152 | goog.Timer.callOnce(func, 500); 153 | }; 154 | -------------------------------------------------------------------------------- /examples/retained/demos/carouselDemo.js: -------------------------------------------------------------------------------- 1 | goog.provide('demos.CarouselDemo'); 2 | 3 | goog.require('demos.DemoBase'); 4 | goog.require('goog.events'); 5 | goog.require('goog.events.EventType'); 6 | goog.require('pl.retained.Animation'); 7 | goog.require('pl.retained.CarouselPanel'); 8 | goog.require('pl.retained.Stage'); 9 | goog.require('pl.retained.Text'); 10 | goog.require('pl.retained.helper'); 11 | 12 | 13 | 14 | /** 15 | * @constructor 16 | * @extends {demos.DemoBase} 17 | */ 18 | demos.CarouselDemo = function(canvas) { 19 | this._mouse = null; 20 | 21 | goog.events.listen(canvas, goog.events.EventType.MOUSEOUT, this._onMouseOut, false, this); 22 | goog.events.listen(canvas, goog.events.EventType.MOUSEMOVE, this._onMouseMove, false, this); 23 | 24 | var container = new pl.retained.CarouselPanel(canvas.width, canvas.height); 25 | container.radius(new goog.math.Size(190, 40)); 26 | 27 | for (var i = 0; i < 4; i++) { 28 | var img = DemoHost.images.get('pixellab_transparent'); 29 | var image = new pl.retained.Image(img, img.width, img.height); 30 | container.middleElement(image); 31 | 32 | var text = new pl.retained.Text(String(i + 1), 150, 30); 33 | text.fillStyle = i % 2 ? '#BBB' : '#DDD'; 34 | text.textFillStyle = 'black'; 35 | text.isCentered = true; 36 | container.addElement(text); 37 | } 38 | 39 | goog.base(this, canvas, container); 40 | 41 | var frameCount = 200; 42 | var animation = new pl.retained.Animation(container, frameCount, function(i, element) { 43 | element.angle(i * Math.PI * 2 / frameCount); 44 | }); 45 | }; 46 | goog.inherits(demos.CarouselDemo, demos.DemoBase); 47 | 48 | 49 | /** 50 | * @override 51 | */ 52 | demos.CarouselDemo.prototype.frame = function() { 53 | var updated = goog.base(this, 'frame'); 54 | 55 | if (this._mouse) { 56 | pl.retained.helper.borderHitTest(this.getStage(), this._mouse); 57 | } 58 | return updated; 59 | }; 60 | 61 | demos.CarouselDemo.prototype._onMouseMove = function(e) { 62 | this._mouse = new goog.math.Coordinate(e.offsetX, e.offsetY); 63 | }; 64 | 65 | demos.CarouselDemo.prototype._onMouseOut = function(e) { 66 | this._mouse = null; 67 | }; 68 | -------------------------------------------------------------------------------- /examples/retained/demos/demoBase.js: -------------------------------------------------------------------------------- 1 | goog.provide('demos.DemoBase'); 2 | 3 | goog.require('goog.array'); 4 | goog.require('goog.asserts'); 5 | goog.require('pl.retained.Element'); 6 | goog.require('pl.retained.EventType'); 7 | goog.require('pl.retained.Stage'); 8 | 9 | 10 | 11 | /** 12 | * @constructor 13 | * @extends {goog.events.EventTarget} 14 | * @param {!HTMLCanvasElement} canvas 15 | * @param {!pl.retained.Element} rootElement 16 | */ 17 | demos.DemoBase = function(canvas, rootElement) { 18 | goog.base(this); 19 | this._canvas = canvas; 20 | 21 | /** 22 | * @private 23 | * @type {!pl.retained.Stage} 24 | */ 25 | this._stage = new pl.retained.Stage(canvas, rootElement); 26 | 27 | this._stage.addEventListener(pl.retained.EventType.UPDATE, function(e) { 28 | this.dispatchEvent(pl.retained.EventType.UPDATE); 29 | }, 30 | false, this); 31 | }; 32 | goog.inherits(demos.DemoBase, goog.events.EventTarget); 33 | 34 | 35 | /** 36 | * @protected 37 | * @return {!pl.retained.Stage} 38 | */ 39 | demos.DemoBase.prototype.getStage = function() { 40 | return this._stage; 41 | }; 42 | 43 | 44 | /** 45 | * @protected 46 | * @return {!HTMLCanvasElement} 47 | */ 48 | demos.DemoBase.prototype.getCanvas = function() { 49 | return this._canvas; 50 | }; 51 | 52 | 53 | /** 54 | * @return {boolean} 55 | */ 56 | demos.DemoBase.prototype.frame = function() { 57 | return this._stage.draw(); 58 | }; 59 | -------------------------------------------------------------------------------- /examples/retained/demos/demos.js: -------------------------------------------------------------------------------- 1 | goog.provide('demos'); 2 | 3 | goog.require('demos.CarouselDemo'); 4 | goog.require('demos.DemoBase'); 5 | goog.require('demos.GraphDemo'); 6 | goog.require('demos.NavLayerDemo'); 7 | goog.require('demos.RotateTextDemo'); 8 | goog.require('demos.ScaleDemo'); 9 | goog.require('demos.Squares'); 10 | goog.require('demos.SwapDemo'); 11 | goog.require('demos.TileDemo'); 12 | 13 | 14 | /** 15 | * @type {Object.} 16 | **/ 17 | demos.all = { 18 | 'Graph': demos.GraphDemo, 19 | 'Squares': demos.Squares, 20 | 'Carousel': demos.CarouselDemo, 21 | 'Scale': demos.ScaleDemo, 22 | 'Swap': demos.SwapDemo, 23 | 'Tile': demos.TileDemo, 24 | 'Rotate': demos.RotateTextDemo, 25 | 'Nav Layer': demos.NavLayerDemo 26 | }; 27 | -------------------------------------------------------------------------------- /examples/retained/demos/graphDemo.js: -------------------------------------------------------------------------------- 1 | goog.provide('demos.GraphDemo'); 2 | goog.provide('demos.GraphDemo.Node'); 3 | 4 | goog.require('demos.DemoBase'); 5 | goog.require('goog.fx.DragEvent'); 6 | goog.require('goog.fx.Dragger'); 7 | goog.require('goog.fx.Dragger.EventType'); 8 | goog.require('goog.math.Vec2'); 9 | goog.require('pl.Graph'); 10 | goog.require('pl.gfx'); 11 | goog.require('pl.retained.GraphElement'); 12 | 13 | 14 | 15 | /** 16 | * @constructor 17 | * @extends {demos.DemoBase} 18 | */ 19 | demos.GraphDemo = function(canvas) { 20 | var g = demos.GraphDemo._createGraph(); 21 | var gp = new pl.GraphPhysics(g, pl.ex.getCanvasSize(canvas)); 22 | var graphElement = new pl.retained.GraphElement(gp, canvas.width, canvas.height); 23 | 24 | this._dragger = new goog.fx.Dragger(canvas); 25 | this._dragger.addEventListener(goog.fx.Dragger.EventType.START, this._onDragStart, undefined, this); 26 | this._dragger.addEventListener(goog.fx.Dragger.EventType.END, this._onDragEnd, undefined, this); 27 | this._dragger.addEventListener(goog.fx.Dragger.EventType.DRAG, this._onDrag, undefined, this); 28 | 29 | goog.events.listen(canvas, goog.events.EventType.MOUSEOUT, this._onMouse, false, this); 30 | goog.events.listen(canvas, goog.events.EventType.MOUSEMOVE, this._onMouse, false, this); 31 | 32 | goog.base(this, canvas, graphElement); 33 | this._graphElement = graphElement; 34 | }; 35 | goog.inherits(demos.GraphDemo, demos.DemoBase); 36 | 37 | 38 | /** 39 | * @override 40 | */ 41 | demos.GraphDemo.prototype.frame = function() { 42 | var updated = goog.base(this, 'frame'); 43 | this._updateCursor(); 44 | return updated; 45 | }; 46 | 47 | demos.GraphDemo.prototype._onDragStart = function(e) { 48 | var hits = pl.retained.mouse.markMouseOver(this.getStage(), this._mouse); 49 | if (hits && hits.length) { 50 | var node = goog.array.findRight(hits, function(e) { 51 | return pl.retained.GraphElement.isGraphElementNode(e); 52 | }); 53 | if (node) { 54 | this._dragElement = node; 55 | return true; 56 | } 57 | } 58 | this._dragElement = null; 59 | return false; 60 | }; 61 | 62 | demos.GraphDemo.prototype._onDrag = function(e) { 63 | goog.asserts.assert(this._dragElement); 64 | var point = new goog.math.Coordinate(e.browserEvent.offsetX, e.browserEvent.offsetY); 65 | this._graphElement.dragElement(this._dragElement, point); 66 | }; 67 | 68 | demos.GraphDemo.prototype._onDragEnd = function(e) { 69 | this._dragElement = null; 70 | this._graphElement.dragElement(); 71 | }; 72 | 73 | demos.GraphDemo.prototype._onMouse = function(e) { 74 | if (e.type == goog.events.EventType.MOUSEOUT) { 75 | this._mouse = null; 76 | } else { 77 | this._mouse = new goog.math.Coordinate(e.offsetX, e.offsetY); 78 | } 79 | this.dispatchEvent(pl.retained.EventType.UPDATE); 80 | }; 81 | 82 | demos.GraphDemo.prototype._updateCursor = function() { 83 | var cursor = 'auto'; 84 | var hits = pl.retained.mouse.markMouseOver(this.getStage(), this._mouse); 85 | if (hits && hits.length) { 86 | var node = goog.array.findRight(hits, function(e) { 87 | return pl.retained.GraphElement.isGraphElementNode(e); 88 | }); 89 | if (node) { 90 | cursor = 'pointer'; 91 | } 92 | } 93 | goog.style.setStyle(this.getCanvas(), 'cursor', cursor); 94 | }; 95 | 96 | demos.GraphDemo._createGraph = function() { 97 | var g = new pl.Graph(); 98 | 99 | for (var j = 0; j < 5; j++) { 100 | var n = 5 + goog.math.randomInt(10); 101 | var nodes = []; 102 | for (var i = 0; i < n; i++) { 103 | nodes.push(new demos.GraphDemo.Node(i)); 104 | } 105 | for (var i = 0; i < nodes.length; i++) { 106 | var adjacent = [new demos.GraphDemo.Node(i * i)]; 107 | if ((i + 1) < nodes.length) { 108 | adjacent.push(nodes[i + 1]); 109 | } 110 | g.addNode(nodes[i], adjacent); 111 | } 112 | } 113 | return g; 114 | }; 115 | 116 | 117 | 118 | /** 119 | * @constructor 120 | * @param {*} value 121 | */ 122 | demos.GraphDemo.Node = function(value) { 123 | this.value = value; 124 | }; 125 | 126 | 127 | /** 128 | * @return {!string} 129 | */ 130 | demos.GraphDemo.Node.prototype.toString = function() { 131 | return String(this.value); 132 | }; 133 | -------------------------------------------------------------------------------- /examples/retained/demos/navLayerDemo.js: -------------------------------------------------------------------------------- 1 | goog.provide('demos.NavLayerDemo'); 2 | 3 | goog.require('goog.events'); 4 | goog.require('goog.events.EventType'); 5 | goog.require('goog.math.Coordinate'); 6 | goog.require('pl.retained.Canvas'); 7 | goog.require('pl.retained.NavLayer'); 8 | goog.require('pl.retained.Shape'); 9 | goog.require('pl.retained.Stage'); 10 | goog.require('pl.retained.Text'); 11 | goog.require('pl.retained.mouse'); 12 | 13 | 14 | 15 | /** 16 | * @constructor 17 | * @extends {demos.DemoBase} 18 | */ 19 | demos.NavLayerDemo = function(canvas) { 20 | this._nav = new pl.retained.NavLayer(canvas.width, canvas.height); 21 | 22 | goog.base(this, canvas, this._nav); 23 | 24 | goog.events.listen(canvas, goog.events.EventType.MOUSEDOWN, this._onMouseDown, false, this); 25 | this._count = 0; 26 | this._forward(new goog.graphics.AffineTransform()); 27 | }; 28 | goog.inherits(demos.NavLayerDemo, demos.DemoBase); 29 | 30 | demos.NavLayerDemo.prototype._forward = function(tx) { 31 | if (this._nav.canForward()) { 32 | var demoElement = demos.NavLayerDemo._getX(++this._count); 33 | this._nav.forward(demoElement, tx); 34 | } 35 | }; 36 | 37 | demos.NavLayerDemo.prototype._onMouseDown = function(e) { 38 | e.stopPropagation(); 39 | 40 | this._lastMouse = new goog.math.Coordinate(e.offsetX, e.offsetY); 41 | var hits = pl.retained.mouse.markMouseOver(this.getStage(), this._lastMouse); 42 | 43 | if (hits && hits.length) { 44 | var last = hits[hits.length - 1]; 45 | this._itemClick(last); 46 | } 47 | }; 48 | 49 | demos.NavLayerDemo.prototype._itemClick = function(element) { 50 | var tx = new goog.graphics.AffineTransform(); 51 | if (element == this._nav || element.width === 300) { 52 | tx = goog.graphics.AffineTransform.getTranslateInstance(100, 100).scale(1 / 3, 1 / 3).createInverse(); 53 | } else { 54 | var widthRatio = element.width / 300; 55 | var heightRatio = element.height / 300; 56 | 57 | var lastTx = element.getTransform(); 58 | var x = lastTx.getTranslateX(); 59 | var y = lastTx.getTranslateY(); 60 | 61 | tx = goog.graphics.AffineTransform.getTranslateInstance(x, y).scale(widthRatio, heightRatio); 62 | } 63 | this._forward(tx); 64 | }; 65 | 66 | demos.NavLayerDemo._getX = function(count) { 67 | var container = new pl.retained.Canvas(300, 300); 68 | 69 | var back = new pl.retained.Shape(300, 300); 70 | back.fillStyle = '#333'; 71 | back.alpha = 0.5; 72 | container.addElement(back); 73 | 74 | var text = new pl.retained.Text('Click here\n\n' + count, 100, 100); 75 | text.isCentered = true; 76 | text.fillStyle = 'white'; 77 | text.textFillStyle = 'black'; 78 | text.multiLine = true; 79 | 80 | container.addElement(text); 81 | container.topLeft(text, new goog.math.Coordinate(100, 100)); 82 | 83 | var corner; 84 | 85 | // top left 86 | corner = new pl.retained.Shape(100, 100); 87 | corner.fillStyle = 'red'; 88 | container.addElement(corner); 89 | container.topLeft(corner, new goog.math.Coordinate(0, 0)); 90 | 91 | // top right 92 | corner = new pl.retained.Shape(100, 100); 93 | corner.fillStyle = 'green'; 94 | container.addElement(corner); 95 | container.topLeft(corner, new goog.math.Coordinate(200, 0)); 96 | 97 | // bottom left 98 | corner = new pl.retained.Shape(100, 100); 99 | corner.fillStyle = 'blue'; 100 | container.addElement(corner); 101 | container.topLeft(corner, new goog.math.Coordinate(0, 200)); 102 | 103 | // bottom right 104 | corner = new pl.retained.Shape(100, 100); 105 | corner.fillStyle = 'yellow'; 106 | container.addElement(corner); 107 | container.topLeft(corner, new goog.math.Coordinate(200, 200)); 108 | 109 | return container; 110 | }; 111 | -------------------------------------------------------------------------------- /examples/retained/demos/rotateTextDemo.js: -------------------------------------------------------------------------------- 1 | goog.provide('demos.RotateTextDemo'); 2 | 3 | goog.require('demos.DemoBase'); 4 | goog.require('pl.retained.Panel'); 5 | goog.require('pl.retained.Stage'); 6 | goog.require('pl.retained.Text'); 7 | 8 | 9 | 10 | /** 11 | * @constructor 12 | * @extends {demos.DemoBase} 13 | */ 14 | demos.RotateTextDemo = function(canvas) { 15 | var text = new pl.retained.Text('Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.', 400, 400); 16 | text.fillStyle = 'blue'; 17 | text.multiLine = true; 18 | 19 | var container = new pl.retained.Panel(400, 400); 20 | container.addElement(text); 21 | 22 | goog.base(this, canvas, container); 23 | 24 | container.addTransform().translate((canvas.width - container.width) / 2, (canvas.height - container.height) / 2); 25 | 26 | this._tx = container.addTransform(); 27 | }; 28 | goog.inherits(demos.RotateTextDemo, demos.DemoBase); 29 | 30 | 31 | /** 32 | * @override 33 | */ 34 | demos.RotateTextDemo.prototype.frame = function() { 35 | this._tx.rotate(Math.PI * 0.001, 200, 200); 36 | goog.base(this, 'frame'); 37 | return true; 38 | }; 39 | -------------------------------------------------------------------------------- /examples/retained/demos/scaleDemo.js: -------------------------------------------------------------------------------- 1 | goog.provide('demos.ScaleDemo'); 2 | 3 | goog.require('goog.math.Vec2'); 4 | goog.require('pl.gfx'); 5 | goog.require('pl.retained.Animation'); 6 | goog.require('pl.retained.Image'); 7 | goog.require('pl.retained.Stage'); 8 | 9 | 10 | 11 | /** 12 | * @constructor 13 | * @extends {demos.DemoBase} 14 | */ 15 | demos.ScaleDemo = function(canvas) { 16 | var img = DemoHost.images.get('pixellab'); 17 | 18 | var image = new pl.retained.Image(img, img.width, img.height); 19 | 20 | var vec = new goog.math.Vec2(canvas.width - image.width, canvas.height - image.height); 21 | vec.scale(0.5); 22 | var tx = image.addTransform().setToTranslation(vec.x, vec.y); 23 | 24 | goog.base(this, canvas, image); 25 | 26 | var frames = 50; 27 | 28 | var animation = new pl.retained.Animation(image, frames, function(i, element) { 29 | var scale = 1 - i / frames; 30 | pl.gfx.affineOffsetScale(tx, scale, scale, element.width / 2, element.height / 2); 31 | tx.preTranslate(vec.x, vec.y); 32 | element.invalidateDraw(); 33 | }); 34 | }; 35 | goog.inherits(demos.ScaleDemo, demos.DemoBase); 36 | -------------------------------------------------------------------------------- /examples/retained/demos/squares.js: -------------------------------------------------------------------------------- 1 | goog.provide('demos.Squares'); 2 | 3 | goog.require('demos.DemoBase'); 4 | goog.require('goog.math.Box'); 5 | goog.require('goog.math.Coordinate'); 6 | goog.require('goog.math.Size'); 7 | goog.require('pl.ex'); 8 | goog.require('pl.retained.Animation'); 9 | goog.require('pl.retained.Panel'); 10 | goog.require('pl.retained.Shape'); 11 | goog.require('pl.retained.Stage'); 12 | 13 | 14 | 15 | /** 16 | * @constructor 17 | * @extends {demos.DemoBase} 18 | */ 19 | demos.Squares = function(canvas) { 20 | this._size = new goog.math.Size(canvas.width, canvas.height); 21 | var canvasElement = new pl.retained.Canvas(canvas.width, canvas.height); 22 | goog.base(this, canvas, canvasElement); 23 | 24 | this._box = new goog.math.Box(0, 0, canvas.width, canvas.height); 25 | this._box.expand(0, 1000, 0, 1000); 26 | 27 | var boxSize = new goog.math.Size(50, 50); 28 | var position = new goog.math.Coordinate(); 29 | 30 | this._shapes = []; 31 | for (var i = 0; i < 1000; i++) { 32 | position.x = goog.math.uniformRandom(this._box.left, this._box.right); 33 | position.y = goog.math.uniformRandom(this._box.top, this._box.bottom); 34 | 35 | var shape = demos.Squares.createShape(boxSize); 36 | canvasElement.addElement(shape); 37 | canvasElement.center(shape, position); 38 | this._shapes.push(shape); 39 | } 40 | this._canvasElement = canvasElement; 41 | }; 42 | goog.inherits(demos.Squares, demos.DemoBase); 43 | 44 | demos.Squares.prototype.frame = function() { 45 | goog.base(this, 'frame'); 46 | goog.array.forEach(this._shapes, function(s) { 47 | var center = this._canvasElement.center(s); 48 | center.x += 1; 49 | if (center.x > this._box.right) { 50 | center.x = this._box.left; 51 | } 52 | this._canvasElement.center(s, center); 53 | }, this); 54 | return true; 55 | }; 56 | 57 | demos.Squares.createShape = function(size) { 58 | var shape = new pl.retained.Shape(size.width, size.height); 59 | shape.fillStyle = pl.ex.getRandom(demos.SwapDemo._fills); 60 | 61 | return shape; 62 | }; 63 | 64 | 65 | /** 66 | * @const 67 | **/ 68 | demos.Squares._fills = ['red', 'green', 'blue', 'yellow']; 69 | -------------------------------------------------------------------------------- /examples/retained/demos/swapDemo.js: -------------------------------------------------------------------------------- 1 | goog.provide('demos.SwapDemo'); 2 | 3 | goog.require('demos.DemoBase'); 4 | goog.require('goog.math.Size'); 5 | goog.require('pl.ex'); 6 | goog.require('pl.retained.Animation'); 7 | goog.require('pl.retained.Panel'); 8 | goog.require('pl.retained.Shape'); 9 | goog.require('pl.retained.Stage'); 10 | 11 | 12 | 13 | /** 14 | * @constructor 15 | * @extends {demos.DemoBase} 16 | */ 17 | demos.SwapDemo = function(canvas) { 18 | this._size = new goog.math.Size(canvas.width, canvas.height); 19 | var container = new pl.retained.Panel(canvas.width, canvas.height); 20 | goog.base(this, canvas, container); 21 | this._count = 0; 22 | }; 23 | goog.inherits(demos.SwapDemo, demos.DemoBase); 24 | 25 | demos.SwapDemo.prototype.frame = function() { 26 | var updated = goog.base(this, 'frame'); 27 | 28 | if (this._count <= 0) { 29 | this._count = 50; 30 | var shape = this._createShape(this._size.width, this._size.height); 31 | this._getRootElement().insertAt(shape); 32 | } 33 | this._count--; 34 | return updated; 35 | }; 36 | 37 | demos.SwapDemo.prototype._createShape = function(w, h) { 38 | var shape = new pl.retained.Shape(w, h); 39 | shape.fillStyle = pl.ex.getRandom(demos.SwapDemo._fills); 40 | var tx = shape.addTransform(); 41 | 42 | var frameCount = 200; 43 | new pl.retained.Animation(shape, frameCount, function(i, element) { 44 | var ratio = (frameCount - i) / frameCount; 45 | pl.gfx.affineOffsetScale(tx, ratio, ratio, element.width / 2, element.height / 2); 46 | element.alpha = ratio; 47 | element.invalidateDraw(); 48 | }, 49 | function(element) { 50 | this._getRootElement().remove(element); 51 | }); 52 | 53 | return shape; 54 | }; 55 | 56 | 57 | /** 58 | * @return {!pl.retained.Element} 59 | */ 60 | demos.SwapDemo.prototype._getRootElement = function() { 61 | return this.getStage().getRoot(); 62 | }; 63 | 64 | demos.SwapDemo._fills = ['red', 'green', 'blue', 'yellow']; 65 | -------------------------------------------------------------------------------- /examples/retained/demos/tileDemo.js: -------------------------------------------------------------------------------- 1 | goog.provide('demos.TileDemo'); 2 | 3 | goog.require('demos.DemoBase'); 4 | goog.require('goog.math.Vec2'); 5 | goog.require('pl.retained.Panel'); 6 | goog.require('pl.retained.Stage'); 7 | goog.require('pl.retained.TileLayer'); 8 | 9 | 10 | 11 | /** 12 | * @constructor 13 | * @extends {demos.DemoBase} 14 | */ 15 | demos.TileDemo = function(canvas) { 16 | var image = DemoHost.images.get('stars'); 17 | 18 | var container = new pl.retained.Panel(canvas.width, canvas.height); 19 | 20 | this._tiles = []; 21 | 22 | var size = new goog.math.Size(image.width, image.height); 23 | for (var i = 0; i < 3; i++) { 24 | var tileSize = size.clone().scale(Math.pow(2, -i)); 25 | var t = new pl.retained.TileLayer(canvas.width, canvas.height, image, tileSize); 26 | this._tiles.push(t); 27 | container.addElement(t); 28 | } 29 | 30 | this._offset = new goog.math.Vec2(0, 0); 31 | 32 | goog.base(this, canvas, container); 33 | }; 34 | goog.inherits(demos.TileDemo, demos.DemoBase); 35 | 36 | demos.TileDemo.prototype.frame = function() { 37 | this._offset.x -= 10; 38 | for (var i = 0; i < this._tiles.length; i++) { 39 | var t = this._tiles[i]; 40 | var o = this._offset.clone().scale(Math.pow(2, -i)); 41 | t.setOffset(o); 42 | } 43 | 44 | goog.base(this, 'frame'); 45 | return true; 46 | }; 47 | -------------------------------------------------------------------------------- /examples/retained/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 |
16 | 17 |
18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /examples/retained/index_source.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 |
18 | 19 |
20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /examples/retained/resources/common.css: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2009 The Closure Library Authors. All Rights Reserved. 3 | * 4 | * Use of this source code is governed by the Apache License, Version 2.0. 5 | * See the COPYING file for details. 6 | */ 7 | 8 | /* 9 | * Cross-browser implementation of the "display: inline-block" CSS property. 10 | * See http://www.w3.org/TR/CSS21/visuren.html#propdef-display for details. 11 | * Tested on IE 6 & 7, FF 1.5 & 2.0, Safari 2 & 3, Webkit, and Opera 9. 12 | * 13 | * @author attila@google.com (Attila Bodis) 14 | */ 15 | 16 | /* 17 | * Default rule; only Safari, Webkit, and Opera handle it without hacks. 18 | */ 19 | .goog-inline-block { 20 | position: relative; 21 | display: -moz-inline-box; /* Ignored by FF3 and later. */ 22 | display: inline-block; 23 | } 24 | 25 | /* 26 | * Pre-IE7 IE hack. On IE, "display: inline-block" only gives the element 27 | * layout, but doesn't give it inline behavior. Subsequently setting display 28 | * to inline does the trick. 29 | */ 30 | * html .goog-inline-block { 31 | display: inline; 32 | } 33 | 34 | /* 35 | * IE7-only hack. On IE, "display: inline-block" only gives the element 36 | * layout, but doesn't give it inline behavior. Subsequently setting display 37 | * to inline does the trick. 38 | */ 39 | *:first-child+html .goog-inline-block { 40 | display: inline; 41 | } 42 | -------------------------------------------------------------------------------- /examples/retained/resources/demo.css: -------------------------------------------------------------------------------- 1 | @import url(common.css); 2 | 3 | 4 | body { 5 | background-color: #222; 6 | font: normal 10pt Helvetica, Arial, sans-serif; 7 | } 8 | 9 | #container { 10 | margin: 20px auto; 11 | } 12 | 13 | #content { 14 | display: block; 15 | margin: 2px auto; 16 | } 17 | -------------------------------------------------------------------------------- /examples/retained/resources/flatmenubutton.css: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2009 The Closure Library Authors. All Rights Reserved. 3 | * 4 | * Use of this source code is governed by the Apache License, Version 2.0. 5 | * See the COPYING file for details. 6 | */ 7 | 8 | /* 9 | * Standard styling for buttons created by goog.ui.FlatMenuButtonRenderer. 10 | * 11 | * @author attila@google.com (Attila Bodis) 12 | * @author tlb@google.com (Thierry Le Boulenge) 13 | */ 14 | 15 | 16 | .goog-flat-menu-button { 17 | background-color: #fff; 18 | border: 1px solid #c9c9c9; 19 | color: #333; 20 | cursor: pointer; 21 | font: normal 95%; 22 | list-style: none; 23 | margin: 0 2px; 24 | outline: none; 25 | padding: 1px 4px; 26 | position: relative; 27 | text-decoration: none; 28 | vertical-align: middle; 29 | } 30 | 31 | .goog-flat-menu-button-disabled * { 32 | border-color: #ccc; 33 | color: #999; 34 | cursor: default; 35 | } 36 | 37 | .goog-flat-menu-button-hover { 38 | border-color: #9cf #69e #69e #7af !important; /* Hover border wins. */ 39 | } 40 | 41 | .goog-flat-menu-button-active { 42 | background-color: #bbb; 43 | background-position: bottom left; 44 | } 45 | 46 | .goog-flat-menu-button-focused { 47 | border-color: #bbb; 48 | } 49 | 50 | .goog-flat-menu-button-caption { 51 | padding-right: 10px; 52 | vertical-align: top; 53 | } 54 | 55 | .goog-flat-menu-button-dropdown { 56 | /* Client apps may override the URL at which they serve the sprite. */ 57 | background: url(//ssl.gstatic.com/editor/editortoolbar.png) no-repeat -388px 0; 58 | position: absolute; 59 | right: 2px; 60 | top: 0; 61 | vertical-align: top; 62 | width: 7px; 63 | } 64 | -------------------------------------------------------------------------------- /examples/retained/resources/menu.css: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2009 The Closure Library Authors. All Rights Reserved. 3 | * 4 | * Use of this source code is governed by the Apache License, Version 2.0. 5 | * See the COPYING file for details. 6 | */ 7 | 8 | /* 9 | * Standard styling for menus created by goog.ui.MenuRenderer. 10 | * 11 | * @author attila@google.com (Attila Bodis) 12 | */ 13 | 14 | 15 | .goog-menu { 16 | background: #fff; 17 | border-color: #ccc #666 #666 #ccc; 18 | border-style: solid; 19 | border-width: 1px; 20 | cursor: default; 21 | font: normal 13px Arial, sans-serif; 22 | margin: 0; 23 | outline: none; 24 | padding: 4px 0; 25 | position: absolute; 26 | z-index: 20000; /* Arbitrary, but some apps depend on it... */ 27 | } 28 | -------------------------------------------------------------------------------- /examples/retained/resources/menuitem.css: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2009 The Closure Library Authors. All Rights Reserved. 3 | * 4 | * Use of this source code is governed by the Apache License, Version 2.0. 5 | * See the COPYING file for details. 6 | */ 7 | 8 | /* 9 | * Standard styling for menus created by goog.ui.MenuItemRenderer. 10 | * 11 | * @author attila@google.com (Attila Bodis) 12 | */ 13 | 14 | 15 | /* State: resting. */ 16 | .goog-menuitem { 17 | color: #000; 18 | font: normal 13px Arial, sans-serif; 19 | list-style: none; 20 | margin: 0; 21 | /* 28px on the left for icon or checkbox; 7em on the right for shortcut. */ 22 | padding: 4px 7em 4px 28px; 23 | white-space: nowrap; 24 | } 25 | 26 | /* If a menu doesn't have checkable items or items with icons, remove padding. */ 27 | .goog-menu-nocheckbox .goog-menuitem, 28 | .goog-menu-noicon .goog-menuitem { 29 | padding-left: 12px; 30 | } 31 | 32 | /* 33 | * If a menu doesn't have items with shortcuts, leave just enough room for 34 | * submenu arrows, if they are rendered. 35 | */ 36 | .goog-menu-noaccel .goog-menuitem { 37 | padding-right: 20px; 38 | } 39 | 40 | .goog-menuitem-content { 41 | color: #000; 42 | font: normal 13px Arial, sans-serif; 43 | } 44 | 45 | /* State: disabled. */ 46 | .goog-menuitem-disabled .goog-menuitem-accel, 47 | .goog-menuitem-disabled .goog-menuitem-content { 48 | color: #ccc !important; 49 | } 50 | .goog-menuitem-disabled .goog-menuitem-icon { 51 | opacity: 0.3; 52 | -moz-opacity: 0.3; 53 | filter: alpha(opacity=30); 54 | } 55 | 56 | /* State: hover. */ 57 | .goog-menuitem-highlight, 58 | .goog-menuitem-hover { 59 | background-color: #d6e9f8; 60 | /* Use an explicit top and bottom border so that the selection is visible 61 | * in high contrast mode. */ 62 | border-color: #d6e9f8; 63 | border-style: dotted; 64 | border-width: 1px 0; 65 | padding-bottom: 3px; 66 | padding-top: 3px; 67 | } 68 | 69 | /* State: selected/checked. */ 70 | .goog-menuitem-checkbox, 71 | .goog-menuitem-icon { 72 | background-repeat: no-repeat; 73 | height: 16px; 74 | left: 6px; 75 | position: absolute; 76 | right: auto; 77 | vertical-align: middle; 78 | width: 16px; 79 | } 80 | .goog-option-selected .goog-menuitem-checkbox, 81 | .goog-option-selected .goog-menuitem-icon { 82 | /* Client apps may override the URL at which they serve the sprite. */ 83 | background: url(//ssl.gstatic.com/editor/editortoolbar.png) no-repeat -512px 0; 84 | } 85 | 86 | /* Keyboard shortcut ("accelerator") style. */ 87 | .goog-menuitem-accel { 88 | color: #999; 89 | /* Keyboard shortcuts are untranslated; always left-to-right. */ 90 | /* @noflip */ direction: ltr; 91 | left: auto; 92 | padding: 0 6px; 93 | position: absolute; 94 | right: 0; 95 | text-align: right; 96 | } 97 | -------------------------------------------------------------------------------- /examples/retained/resources/menuseparator.css: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2009 The Closure Library Authors. All Rights Reserved. 3 | * 4 | * Use of this source code is governed by the Apache License, Version 2.0. 5 | * See the COPYING file for details. 6 | */ 7 | 8 | /* 9 | * Standard styling for menus created by goog.ui.MenuSeparatorRenderer. 10 | * 11 | * @author attila@google.com (Attila Bodis) 12 | */ 13 | 14 | 15 | .goog-menuseparator { 16 | border-top: 1px solid #ccc; 17 | margin: 4px 0; 18 | padding: 0; 19 | } 20 | -------------------------------------------------------------------------------- /examples/retained/resources/pixellab.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thinkpixellab/pl/b1ae55a4e91ab4fa183e89316b2b036095d5f214/examples/retained/resources/pixellab.png -------------------------------------------------------------------------------- /examples/retained/resources/pixellab_transparent.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thinkpixellab/pl/b1ae55a4e91ab4fa183e89316b2b036095d5f214/examples/retained/resources/pixellab_transparent.png -------------------------------------------------------------------------------- /examples/retained/resources/stars.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thinkpixellab/pl/b1ae55a4e91ab4fa183e89316b2b036095d5f214/examples/retained/resources/stars.png -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # PL - A Javascript Library 2 | 3 | By your friends at [Pixel Lab](http://thinkpixellab.com) 4 | 5 | We do a lot of work in Javascript. This is our collection of libraries we have used and are using for projects. Where code was borrowed, we let you know. Aside from a bunch of miscellaneous, the big chunks are: 6 | 7 | * [Box2d](https://github.com/thinkpixellab/pl/tree/master/src/box2d) - A 2D physics library 8 | * [QR](https://github.com/thinkpixellab/pl/tree/master/src/qr) - A QR code library 9 | * [Retained](https://github.com/thinkpixellab/pl/tree/master/src/retained) - A a [retained-mod](http://en.wikipedia.org/wiki/Retained_mode) graphics library for canvas 10 | 11 | ## Notes 12 | 13 | * The library is designed to be used with [Google's Closure Tools](http://code.google.com/closure/). 14 | * [KBuild](https://github.com/kevmoo/kbuild) is a sister project to make it easier to use the closure tools. 15 | 16 | ## Getting started... 17 | 18 | *Need more here...* 19 | 20 | To get the examples working, put a copy of the closure library in a directory named `closure` next to pl. A simple way to see how this works is to clone one of the projects below (ThinkQR is the smallest). Make sure you initialize submodules. 21 | 22 | ## Used in 23 | 24 | * The [Box2d Demo site](https://github.com/thinkpixellab/box2dWeb) 25 | * [Agent 008 Ball](https://github.com/thinkpixellab/agent8ball) 26 | * [ThinkQR](https://github.com/thinkpixellab/thinkqr) 27 | 28 | ## The MIT License 29 | 30 | Copyright (c) 2011 Pixel Lab 31 | 32 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 33 | 34 | * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 35 | 36 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /src/behavior.js: -------------------------------------------------------------------------------- 1 | goog.provide('pl.Behavior'); 2 | 3 | goog.require('goog.array'); 4 | goog.require('goog.asserts'); 5 | goog.require('pl.Property'); 6 | 7 | 8 | 9 | /** 10 | * @constructor 11 | * @param {!Object} element 12 | */ 13 | pl.Behavior = function(element) { 14 | this._element = element; 15 | 16 | var behaviors = pl.Behavior._behaviorsProperty.get(element); 17 | if (!behaviors) { 18 | behaviors = []; 19 | pl.Behavior._behaviorsProperty.set(element, behaviors); 20 | } 21 | behaviors.push(this); 22 | }; 23 | 24 | pl.Behavior.prototype.detach = function() { 25 | goog.asserts.assert(this._element); 26 | var behaviors = pl.Behavior._behaviorsProperty.get(this._element); 27 | goog.asserts.assert(goog.array.contains(behaviors, this)); 28 | 29 | goog.array.remove(behaviors, this); 30 | 31 | if (behaviors.length === 0) { 32 | pl.Behavior._behaviorsProperty.clear(this._element); 33 | } 34 | 35 | this._element = undefined; 36 | }; 37 | 38 | pl.Behavior._behaviorsProperty = new pl.Property('Behaviors'); 39 | -------------------------------------------------------------------------------- /src/box2d/README.md: -------------------------------------------------------------------------------- 1 | # Box2d-JS 2 | 3 | ## Inspiration 4 | * [Box2D](http://www.box2d.org/) is an actively maintained, open-source C++ library. 5 | * [Box2D-JS](http://sourceforge.net/projects/box2d-js/) Is a javascript port of the C++ library. It was last updated 15 May, 2008. 6 | * See the original demo [here](http://box2d-js.sourceforge.net/). 7 | 8 | ## Pixel Lab Box2d-JS 9 | The folks at [Pixel Lab](http://thinkpixellab.com) modified the library to use [Google's Closure Javascript Compiler](http://code.google.com/closure/compiler/) for great compression--with the added benefit of compile-time checking. (We found a lot of bugs in the original javascript). 10 | 11 | It's being used for [Agent 008 Ball](http://www.agent8ball.com/) - an HTML5 billiards game. 12 | 13 | The demo site is [here](http://box2d.thinkpixellab.com/). 14 | 15 | The demo site source, including demo code, can be found in [this Github repository](http://github.com/thinkpixellab/box2dWeb). 16 | 17 | Please open issues or fork, fix, and send a pull request. 18 | 19 | Happy to work with you. 20 | -------------------------------------------------------------------------------- /src/box2d/collision/ClipVertex.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2007 Erin Catto http: 3 | * 4 | * This software is provided 'as-is', without any express or implied 5 | * warranty. In no event will the authors be held liable for any damages 6 | * arising from the use of this software. 7 | * Permission is granted to anyone to use this software for any purpose, 8 | * including commercial applications, and to alter it and redistribute it 9 | * freely, subject to the following restrictions: 10 | * 1. The origin of this software must not be misrepresented; you must not 11 | * claim that you wrote the original software. If you use this software 12 | * in a product, an acknowledgment in the product documentation would be 13 | * appreciated but is not required. 14 | * 2. Altered source versions must be plainly marked, and must not be 15 | * misrepresented the original software. 16 | * 3. This notice may not be removed or altered from any source distribution. 17 | */ 18 | 19 | goog.provide('box2d.ClipVertex'); 20 | 21 | goog.require('box2d.ContactID'); 22 | goog.require('box2d.Vec2'); 23 | 24 | 25 | 26 | /** 27 | @constructor 28 | */ 29 | box2d.ClipVertex = function() { 30 | // initialize instance variables for references 31 | this.v = new box2d.Vec2(); 32 | this.id = new box2d.ContactID(); 33 | }; 34 | -------------------------------------------------------------------------------- /src/box2d/collision/Features.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2007 Erin Catto http: 3 | * 4 | * This software is provided 'as-is', without any express or implied 5 | * warranty. In no event will the authors be held liable for any damages 6 | * arising from the use of this software. 7 | * Permission is granted to anyone to use this software for any purpose, 8 | * including commercial applications, and to alter it and redistribute it 9 | * freely, subject to the following restrictions: 10 | * 1. The origin of this software must not be misrepresented; you must not 11 | * claim that you wrote the original software. If you use this software 12 | * in a product, an acknowledgment in the product documentation would be 13 | * appreciated but is not required. 14 | * 2. Altered source versions must be plainly marked, and must not be 15 | * misrepresented the original software. 16 | * 3. This notice may not be removed or altered from any source distribution. 17 | */ 18 | 19 | goog.provide('box2d.Features'); 20 | 21 | 22 | 23 | /** 24 | @constructor 25 | @param {!box2d.ContactID} contactId 26 | */ 27 | box2d.Features = function(contactId) { 28 | /* 29 | @type {!box2d.ContactID} 30 | */ 31 | this._m_id = contactId; 32 | this._incidentEdg = 0; 33 | this._incidentVertex = 0; 34 | this._referenceFace = 0; 35 | this._flip = 0; 36 | }; 37 | box2d.Features.prototype.set_referenceFace = function(value) { 38 | this._referenceFace = value; 39 | this._m_id._key = (this._m_id._key & 0xffffff00) | (this._referenceFace & 0x000000ff); 40 | }; 41 | box2d.Features.prototype.get_referenceFace = function() { 42 | return this._referenceFace; 43 | }; 44 | box2d.Features.prototype.set_incidentEdge = function(value) { 45 | this._incidentEdge = value; 46 | this._m_id._key = (this._m_id._key & 0xffff00ff) | ((this._incidentEdge << 8) & 0x0000ff00); 47 | }; 48 | box2d.Features.prototype.get_incidentEdge = function() { 49 | return this._incidentEdge; 50 | }; 51 | box2d.Features.prototype.set_incidentVertex = function(value) { 52 | this._incidentVertex = value; 53 | this._m_id._key = (this._m_id._key & 0xff00ffff) | ((this._incidentVertex << 16) & 0x00ff0000); 54 | }; 55 | box2d.Features.prototype.get_incidentVertex = function() { 56 | return this._incidentVertex; 57 | }; 58 | box2d.Features.prototype.set_flip = function(value) { 59 | this._flip = value; 60 | this._m_id._key = (this._m_id._key & 0x00ffffff) | ((this._flip << 24) & 0xff000000); 61 | }; 62 | box2d.Features.prototype.get_flip = function() { 63 | return this._flip; 64 | }; 65 | -------------------------------------------------------------------------------- /src/box2d/collision/b2AABB.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2007 Erin Catto http: 3 | * 4 | * This software is provided 'as-is', without any express or implied 5 | * warranty. In no event will the authors be held liable for any damages 6 | * arising from the use of this software. 7 | * Permission is granted to anyone to use this software for any purpose, 8 | * including commercial applications, and to alter it and redistribute it 9 | * freely, subject to the following restrictions: 10 | * 1. The origin of this software must not be misrepresented; you must not 11 | * claim that you wrote the original software. If you use this software 12 | * in a product, an acknowledgment in the product documentation would be 13 | * appreciated but is not required. 14 | * 2. Altered source versions must be plainly marked, and must not be 15 | * misrepresented the original software. 16 | * 3. This notice may not be removed or altered from any source distribution. 17 | */ 18 | 19 | goog.provide('box2d.AABB'); 20 | 21 | goog.require('box2d.Vec2'); 22 | 23 | 24 | 25 | // A manifold for two touching convex shapes. 26 | /** 27 | @constructor 28 | */ 29 | box2d.AABB = function() { 30 | 31 | /** @type {box2d.Vec2} */ 32 | this.minVertex = new box2d.Vec2(); 33 | 34 | /** @type {box2d.Vec2} */ 35 | this.maxVertex = new box2d.Vec2(); 36 | }; 37 | 38 | 39 | /** @return {boolean} */ 40 | box2d.AABB.prototype.IsValid = function() { 41 | //var d = box2d.Vec2.subtract(this.maxVertex, this.minVertex); 42 | var dX = this.maxVertex.x; 43 | var dY = this.maxVertex.y; 44 | dX = this.maxVertex.x; 45 | dY = this.maxVertex.y; 46 | dX -= this.minVertex.x; 47 | dY -= this.minVertex.y; 48 | var valid = dX >= 0.0 && dY >= 0.0; 49 | valid = valid && this.minVertex.IsValid() && this.maxVertex.IsValid(); 50 | return valid; 51 | }; 52 | -------------------------------------------------------------------------------- /src/box2d/collision/b2Bound.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2007 Erin Catto http: 3 | * 4 | * This software is provided 'as-is', without any express or implied 5 | * warranty. In no event will the authors be held liable for any damages 6 | * arising from the use of this software. 7 | * Permission is granted to anyone to use this software for any purpose, 8 | * including commercial applications, and to alter it and redistribute it 9 | * freely, subject to the following restrictions: 10 | * 1. The origin of this software must not be misrepresented; you must not 11 | * claim that you wrote the original software. If you use this software 12 | * in a product, an acknowledgment in the product documentation would be 13 | * appreciated but is not required. 14 | * 2. Altered source versions must be plainly marked, and must not be 15 | * misrepresented the original software. 16 | * 3. This notice may not be removed or altered from any source distribution. 17 | */ 18 | 19 | goog.provide('box2d.Bound'); 20 | 21 | 22 | 23 | /** 24 | @constructor 25 | */ 26 | box2d.Bound = function() { 27 | this.value = 0; 28 | this.proxyId = 0; 29 | this.stabbingCount = 0; 30 | }; 31 | 32 | 33 | /** 34 | @return {boolean} 35 | */ 36 | box2d.Bound.prototype.IsLower = function() { 37 | return (this.value & 1) == 0; 38 | }; 39 | 40 | 41 | /** 42 | @return {boolean} 43 | */ 44 | box2d.Bound.prototype.IsUpper = function() { 45 | return (this.value & 1) == 1; 46 | }; 47 | box2d.Bound.prototype.Swap = function(b) { 48 | var tempValue = this.value; 49 | var tempProxyId = this.proxyId; 50 | var tempStabbingCount = this.stabbingCount; 51 | 52 | this.value = b.value; 53 | this.proxyId = b.proxyId; 54 | this.stabbingCount = b.stabbingCount; 55 | 56 | b.value = tempValue; 57 | b.proxyId = tempProxyId; 58 | b.stabbingCount = tempStabbingCount; 59 | }; 60 | -------------------------------------------------------------------------------- /src/box2d/collision/b2BoundValues.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2007 Erin Catto http: 3 | * 4 | * This software is provided 'as-is', without any express or implied 5 | * warranty. In no event will the authors be held liable for any damages 6 | * arising from the use of this software. 7 | * Permission is granted to anyone to use this software for any purpose, 8 | * including commercial applications, and to alter it and redistribute it 9 | * freely, subject to the following restrictions: 10 | * 1. The origin of this software must not be misrepresented; you must not 11 | * claim that you wrote the original software. If you use this software 12 | * in a product, an acknowledgment in the product documentation would be 13 | * appreciated but is not required. 14 | * 2. Altered source versions must be plainly marked, and must not be 15 | * misrepresented the original software. 16 | * 3. This notice may not be removed or altered from any source distribution. 17 | */ 18 | 19 | goog.provide('box2d.BoundValues'); 20 | 21 | 22 | 23 | /** 24 | @constructor 25 | */ 26 | box2d.BoundValues = function() { 27 | this.lowerValues = [0, 0]; 28 | this.upperValues = [0, 0]; 29 | }; 30 | -------------------------------------------------------------------------------- /src/box2d/collision/b2BufferedPair.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2007 Erin Catto http: 3 | * 4 | * This software is provided 'as-is', without any express or implied 5 | * warranty. In no event will the authors be held liable for any damages 6 | * arising from the use of this software. 7 | * Permission is granted to anyone to use this software for any purpose, 8 | * including commercial applications, and to alter it and redistribute it 9 | * freely, subject to the following restrictions: 10 | * 1. The origin of this software must not be misrepresented; you must not 11 | * claim that you wrote the original software. If you use this software 12 | * in a product, an acknowledgment in the product documentation would be 13 | * appreciated but is not required. 14 | * 2. Altered source versions must be plainly marked, and must not be 15 | * misrepresented the original software. 16 | * 3. This notice may not be removed or altered from any source distribution. 17 | */ 18 | 19 | goog.provide('box2d.BufferedPair'); 20 | 21 | 22 | 23 | /** 24 | @constructor 25 | */ 26 | box2d.BufferedPair = function() { 27 | this.proxyId1 = 0; 28 | this.proxyId2 = 0; 29 | }; 30 | -------------------------------------------------------------------------------- /src/box2d/collision/b2ContactID.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2007 Erin Catto http: 3 | * 4 | * This software is provided 'as-is', without any express or implied 5 | * warranty. In no event will the authors be held liable for any damages 6 | * arising from the use of this software. 7 | * Permission is granted to anyone to use this software for any purpose, 8 | * including commercial applications, and to alter it and redistribute it 9 | * freely, subject to the following restrictions: 10 | * 1. The origin of this software must not be misrepresented; you must not 11 | * claim that you wrote the original software. If you use this software 12 | * in a product, an acknowledgment in the product documentation would be 13 | * appreciated but is not required. 14 | * 2. Altered source versions must be plainly marked, and must not be 15 | * misrepresented the original software. 16 | * 3. This notice may not be removed or altered from any source distribution. 17 | */ 18 | 19 | goog.provide('box2d.ContactID'); 20 | 21 | goog.require('box2d.Features'); 22 | 23 | 24 | 25 | // We use contact ids to facilitate warm starting. 26 | /** 27 | @constructor 28 | */ 29 | box2d.ContactID = function() { 30 | this._key = 0; 31 | this.features = new box2d.Features(this); 32 | }; 33 | 34 | box2d.ContactID.prototype.Set = function(id) { 35 | this.set_key(id._key); 36 | }; 37 | box2d.ContactID.prototype.Copy = function() { 38 | var id = new box2d.ContactID(); 39 | id.set_key(this._key); 40 | return id; 41 | }; 42 | box2d.ContactID.prototype.get_key = function() { 43 | return this._key; 44 | }; 45 | box2d.ContactID.prototype.set_key = function(value) { 46 | this._key = value; 47 | this.features._referenceFace = this._key & 0x000000ff; 48 | this.features._incidentEdge = ((this._key & 0x0000ff00) >> 8) & 0x000000ff; 49 | this.features._incidentVertex = ((this._key & 0x00ff0000) >> 16) & 0x000000ff; 50 | this.features._flip = ((this._key & 0xff000000) >> 24) & 0x000000ff; 51 | }; 52 | -------------------------------------------------------------------------------- /src/box2d/collision/b2ContactPoint.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2007 Erin Catto http: 3 | * 4 | * This software is provided 'as-is', without any express or implied 5 | * warranty. In no event will the authors be held liable for any damages 6 | * arising from the use of this software. 7 | * Permission is granted to anyone to use this software for any purpose, 8 | * including commercial applications, and to alter it and redistribute it 9 | * freely, subject to the following restrictions: 10 | * 1. The origin of this software must not be misrepresented; you must not 11 | * claim that you wrote the original software. If you use this software 12 | * in a product, an acknowledgment in the product documentation would be 13 | * appreciated but is not required. 14 | * 2. Altered source versions must be plainly marked, and must not be 15 | * misrepresented the original software. 16 | * 3. This notice may not be removed or altered from any source distribution. 17 | */ 18 | 19 | goog.provide('box2d.ContactPoint'); 20 | 21 | goog.require('box2d.ContactID'); 22 | goog.require('box2d.Vec2'); 23 | 24 | 25 | 26 | // We use contact ids to facilitate warm starting. 27 | /** 28 | @constructor 29 | */ 30 | box2d.ContactPoint = function() { 31 | // initialize instance variables for references 32 | this.position = new box2d.Vec2(); 33 | this.id = new box2d.ContactID(); 34 | 35 | this.separation = null; 36 | this.normalImpulse = null; 37 | this.tangentImpulse = null; 38 | }; 39 | -------------------------------------------------------------------------------- /src/box2d/collision/b2Manifold.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2007 Erin Catto http: 3 | * 4 | * This software is provided 'as-is', without any express or implied 5 | * warranty. In no event will the authors be held liable for any damages 6 | * arising from the use of this software. 7 | * Permission is granted to anyone to use this software for any purpose, 8 | * including commercial applications, and to alter it and redistribute it 9 | * freely, subject to the following restrictions: 10 | * 1. The origin of this software must not be misrepresented; you must not 11 | * claim that you wrote the original software. If you use this software 12 | * in a product, an acknowledgment in the product documentation would be 13 | * appreciated but is not required. 14 | * 2. Altered source versions must be plainly marked, and must not be 15 | * misrepresented the original software. 16 | * 3. This notice may not be removed or altered from any source distribution. 17 | */ 18 | 19 | goog.provide('box2d.Manifold'); 20 | 21 | goog.require('box2d.ContactPoint'); 22 | goog.require('box2d.Settings'); 23 | goog.require('box2d.Vec2'); 24 | 25 | 26 | 27 | // A manifold for two touching convex shapes. 28 | /** 29 | @constructor 30 | */ 31 | box2d.Manifold = function() { 32 | this.pointCount = 0; 33 | this.points = new Array(box2d.Settings.b2_maxManifoldPoints); 34 | for (var i = 0; i < box2d.Settings.b2_maxManifoldPoints; i++) { 35 | this.points[i] = new box2d.ContactPoint(); 36 | } 37 | this.normal = new box2d.Vec2(); 38 | }; 39 | -------------------------------------------------------------------------------- /src/box2d/collision/b2OBB.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2007 Erin Catto http: 3 | * 4 | * This software is provided 'as-is', without any express or implied 5 | * warranty. In no event will the authors be held liable for any damages 6 | * arising from the use of this software. 7 | * Permission is granted to anyone to use this software for any purpose, 8 | * including commercial applications, and to alter it and redistribute it 9 | * freely, subject to the following restrictions: 10 | * 1. The origin of this software must not be misrepresented; you must not 11 | * claim that you wrote the original software. If you use this software 12 | * in a product, an acknowledgment in the product documentation would be 13 | * appreciated but is not required. 14 | * 2. Altered source versions must be plainly marked, and must not be 15 | * misrepresented the original software. 16 | * 3. This notice may not be removed or altered from any source distribution. 17 | */ 18 | 19 | goog.provide('box2d.OBB'); 20 | goog.require('box2d.Mat22'); 21 | goog.require('box2d.Vec2'); 22 | 23 | 24 | 25 | // A manifold for two touching convex shapes. 26 | /** 27 | @constructor 28 | */ 29 | box2d.OBB = function() { 30 | // initialize instance variables for references 31 | this.R = new box2d.Mat22(); 32 | this.center = new box2d.Vec2(); 33 | this.extents = new box2d.Vec2(); 34 | // 35 | }; 36 | -------------------------------------------------------------------------------- /src/box2d/collision/b2Pair.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2007 Erin Catto http: 3 | * 4 | * This software is provided 'as-is', without any express or implied 5 | * warranty. In no event will the authors be held liable for any damages 6 | * arising from the use of this software. 7 | * Permission is granted to anyone to use this software for any purpose, 8 | * including commercial applications, and to alter it and redistribute it 9 | * freely, subject to the following restrictions: 10 | * 1. The origin of this software must not be misrepresented; you must not 11 | * claim that you wrote the original software. If you use this software 12 | * in a product, an acknowledgment in the product documentation would be 13 | * appreciated but is not required. 14 | * 2. Altered source versions must be plainly marked, and must not be 15 | * misrepresented the original software. 16 | * 3. This notice may not be removed or altered from any source distribution. 17 | */ 18 | 19 | goog.provide('box2d.Pair'); 20 | 21 | goog.require('box2d.Settings'); 22 | 23 | 24 | 25 | // The pair manager is used by the broad-phase to quickly add/remove/find pairs 26 | // of overlapping proxies. It is based closely on code provided by Pierre Terdiman. 27 | // http: 28 | /** 29 | @constructor 30 | */ 31 | box2d.Pair = function() {}; 32 | box2d.Pair.prototype = { 33 | 34 | SetBuffered: function() { 35 | this.status |= box2d.Pair.Flags.pairBuffered; 36 | }, 37 | ClearBuffered: function() { 38 | this.status &= ~box2d.Pair.Flags.pairBuffered; 39 | }, 40 | IsBuffered: function() { 41 | return (this.status & box2d.Pair.Flags.pairBuffered) == box2d.Pair.Flags.pairBuffered; 42 | }, 43 | 44 | SetRemoved: function() { 45 | this.status |= box2d.Pair.Flags.pairRemoved; 46 | }, 47 | ClearRemoved: function() { 48 | this.status &= ~box2d.Pair.Flags.pairRemoved; 49 | }, 50 | IsRemoved: function() { 51 | return (this.status & box2d.Pair.Flags.pairRemoved) == box2d.Pair.Flags.pairRemoved; 52 | }, 53 | 54 | SetFinal: function() { 55 | this.status |= box2d.Pair.Flags.pairFinal; 56 | }, 57 | IsFinal: function() { 58 | return (this.status & box2d.Pair.Flags.pairFinal) == box2d.Pair.Flags.pairFinal; 59 | }, 60 | 61 | proxyId1: 0, 62 | proxyId2: 0, 63 | next: 0, 64 | status: 0 65 | }; 66 | 67 | 68 | /** 69 | @type {box2d.Contact} 70 | */ 71 | box2d.Pair.prototype.contactData = null; 72 | 73 | 74 | /** @const @type {number} */ 75 | box2d.Pair.b2_nullPair = box2d.Settings.USHRT_MAX; 76 | 77 | 78 | /** @const @type {number} */ 79 | box2d.Pair.b2_nullProxy = box2d.Settings.USHRT_MAX; 80 | 81 | 82 | /** @const @type {number} */ 83 | box2d.Pair.b2_tableCapacity = box2d.Settings.b2_maxPairs; 84 | 85 | 86 | /** @const @type {number} */ 87 | box2d.Pair.b2_tableMask = box2d.Pair.b2_tableCapacity - 1; 88 | 89 | 90 | /** 91 | @enum {number} 92 | */ 93 | box2d.Pair.Flags = { 94 | pairBuffered: 0x0001, 95 | pairRemoved: 0x0002, 96 | pairFinal: 0x0004 97 | }; 98 | -------------------------------------------------------------------------------- /src/box2d/collision/b2PairCallback.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2007 Erin Catto http: 3 | * 4 | * This software is provided 'as-is', without any express or implied 5 | * warranty. In no event will the authors be held liable for any damages 6 | * arising from the use of this software. 7 | * Permission is granted to anyone to use this software for any purpose, 8 | * including commercial applications, and to alter it and redistribute it 9 | * freely, subject to the following restrictions: 10 | * 1. The origin of this software must not be misrepresented; you must not 11 | * claim that you wrote the original software. If you use this software 12 | * in a product, an acknowledgment in the product documentation would be 13 | * appreciated but is not required. 14 | * 2. Altered source versions must be plainly marked, and must not be 15 | * misrepresented the original software. 16 | * 3. This notice may not be removed or altered from any source distribution. 17 | */ 18 | 19 | goog.provide('box2d.PairCallback'); 20 | 21 | 22 | 23 | /** 24 | @constructor 25 | */ 26 | box2d.PairCallback = function() {}; 27 | 28 | // This returns the new pair user data. 29 | box2d.PairCallback.prototype.PairAdded = function(proxyUserData1, proxyUserData2) { 30 | return null; 31 | }; 32 | 33 | // This should free the pair's user data. In extreme circumstances, it is possible 34 | // this will be called with null pairUserData because the pair never existed. 35 | box2d.PairCallback.prototype.PairRemoved = function(proxyUserData1, proxyUserData2, pairUserData) {}; 36 | -------------------------------------------------------------------------------- /src/box2d/collision/b2Proxy.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2007 Erin Catto http: 3 | * 4 | * This software is provided 'as-is', without any express or implied 5 | * warranty. In no event will the authors be held liable for any damages 6 | * arising from the use of this software. 7 | * Permission is granted to anyone to use this software for any purpose, 8 | * including commercial applications, and to alter it and redistribute it 9 | * freely, subject to the following restrictions: 10 | * 1. The origin of this software must not be misrepresented; you must not 11 | * claim that you wrote the original software. If you use this software 12 | * in a product, an acknowledgment in the product documentation would be 13 | * appreciated but is not required. 14 | * 2. Altered source versions must be plainly marked, and must not be 15 | * misrepresented the original software. 16 | * 3. This notice may not be removed or altered from any source distribution. 17 | */ 18 | 19 | goog.provide('box2d.Proxy'); 20 | 21 | goog.require('box2d.Settings'); 22 | 23 | 24 | 25 | /** 26 | @constructor 27 | */ 28 | box2d.Proxy = function() { 29 | // initialize instance variables for references 30 | this.lowerBounds = [/*uint*/(0), /*uint*/(0)]; 31 | this.upperBounds = [/*uint*/(0), /*uint*/(0)]; 32 | this.overlapCount = 0; 33 | this.timeStamp = 0; 34 | this.userData = null; 35 | }; 36 | 37 | box2d.Proxy.prototype = { 38 | GetNext: function() { return this.lowerBounds[0]; }, 39 | SetNext: function(next) { this.lowerBounds[0] = next /*& 0x0000ffff*/; }, 40 | 41 | IsValid: function() { return this.overlapCount != box2d.Settings.invalid; } 42 | }; 43 | -------------------------------------------------------------------------------- /src/box2d/collision/shapes/b2BoxDef.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2007 Erin Catto http: 3 | * 4 | * This software is provided 'as-is', without any express or implied 5 | * warranty. In no event will the authors be held liable for any damages 6 | * arising from the use of this software. 7 | * Permission is granted to anyone to use this software for any purpose, 8 | * including commercial applications, and to alter it and redistribute it 9 | * freely, subject to the following restrictions: 10 | * 1. The origin of this software must not be misrepresented; you must not 11 | * claim that you wrote the original software. If you use this software 12 | * in a product, an acknowledgment in the product documentation would be 13 | * appreciated but is not required. 14 | * 2. Altered source versions must be plainly marked, and must not be 15 | * misrepresented the original software. 16 | * 3. This notice may not be removed or altered from any source distribution. 17 | */ 18 | 19 | goog.provide('box2d.BoxDef'); 20 | 21 | goog.require('box2d.Shape'); 22 | goog.require('box2d.ShapeDef'); 23 | goog.require('box2d.Vec2'); 24 | 25 | 26 | 27 | /** 28 | @constructor 29 | @extends {box2d.ShapeDef} 30 | */ 31 | box2d.BoxDef = function() { 32 | goog.base(this); 33 | 34 | this.type = box2d.ShapeDef.Type.boxShape; 35 | /** @type {!box2d.Vec2} */ 36 | this.extents = new box2d.Vec2(1.0, 1.0); 37 | }; 38 | goog.inherits(box2d.BoxDef, box2d.ShapeDef); 39 | 40 | 41 | /** 42 | @override 43 | */ 44 | box2d.BoxDef.prototype.ComputeMass = function(massData) { 45 | massData.center = new box2d.Vec2(0.0, 0.0); 46 | 47 | if (this.density == 0.0) { 48 | massData.mass = 0.0; 49 | massData.center.Set(0.0, 0.0); 50 | massData.I = 0.0; 51 | } 52 | 53 | massData.mass = 4.0 * this.density * this.extents.x * this.extents.y; 54 | massData.center.Set(0.0, 0.0); 55 | massData.I = massData.mass / 3.0 * goog.math.Vec2.dot(this.extents, this.extents); 56 | }; 57 | -------------------------------------------------------------------------------- /src/box2d/collision/shapes/b2CircleDef.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2007 Erin Catto http: 3 | * 4 | * This software is provided 'as-is', without any express or implied 5 | * warranty. In no event will the authors be held liable for any damages 6 | * arising from the use of this software. 7 | * Permission is granted to anyone to use this software for any purpose, 8 | * including commercial applications, and to alter it and redistribute it 9 | * freely, subject to the following restrictions: 10 | * 1. The origin of this software must not be misrepresented; you must not 11 | * claim that you wrote the original software. If you use this software 12 | * in a product, an acknowledgment in the product documentation would be 13 | * appreciated but is not required. 14 | * 2. Altered source versions must be plainly marked, and must not be 15 | * misrepresented the original software. 16 | * 3. This notice may not be removed or altered from any source distribution. 17 | */ 18 | 19 | goog.provide('box2d.CircleDef'); 20 | 21 | goog.require('box2d.Shape'); 22 | goog.require('box2d.ShapeDef'); 23 | 24 | 25 | 26 | /** 27 | * @constructor 28 | * @extends {box2d.ShapeDef} 29 | */ 30 | box2d.CircleDef = function() { 31 | goog.base(this); 32 | this.type = box2d.ShapeDef.Type.circleShape; 33 | this.radius = 1.0; 34 | }; 35 | goog.inherits(box2d.CircleDef, box2d.ShapeDef); 36 | 37 | box2d.CircleDef.prototype.ComputeMass = function(massData) { 38 | massData.mass = this.density * box2d.Settings.b2_pi * this.radius * this.radius; 39 | massData.I = 0.5 * (massData.mass) * this.radius * this.radius; 40 | }; 41 | -------------------------------------------------------------------------------- /src/box2d/collision/shapes/b2MassData.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2007 Erin Catto http: 3 | * 4 | * This software is provided 'as-is', without any express or implied 5 | * warranty. In no event will the authors be held liable for any damages 6 | * arising from the use of this software. 7 | * Permission is granted to anyone to use this software for any purpose, 8 | * including commercial applications, and to alter it and redistribute it 9 | * freely, subject to the following restrictions: 10 | * 1. The origin of this software must not be misrepresented; you must not 11 | * claim that you wrote the original software. If you use this software 12 | * in a product, an acknowledgment in the product documentation would be 13 | * appreciated but is not required. 14 | * 2. Altered source versions must be plainly marked, and must not be 15 | * misrepresented the original software. 16 | * 3. This notice may not be removed or altered from any source distribution. 17 | */ 18 | 19 | goog.provide('box2d.MassData'); 20 | 21 | goog.require('box2d.Vec2'); 22 | 23 | 24 | 25 | /** @constructor */ 26 | box2d.MassData = function() { 27 | this.I = 0.0; 28 | this.mass = 0.0; 29 | this.center = new box2d.Vec2(0, 0); 30 | }; 31 | -------------------------------------------------------------------------------- /src/box2d/collision/shapes/b2PolyDef.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2007 Erin Catto http: 3 | * 4 | * This software is provided 'as-is', without any express or implied 5 | * warranty. In no event will the authors be held liable for any damages 6 | * arising from the use of this software. 7 | * Permission is granted to anyone to use this software for any purpose, 8 | * including commercial applications, and to alter it and redistribute it 9 | * freely, subject to the following restrictions: 10 | * 1. The origin of this software must not be misrepresented; you must not 11 | * claim that you wrote the original software. If you use this software 12 | * in a product, an acknowledgment in the product documentation would be 13 | * appreciated but is not required. 14 | * 2. Altered source versions must be plainly marked, and must not be 15 | * misrepresented the original software. 16 | * 3. This notice may not be removed or altered from any source distribution. 17 | */ 18 | 19 | goog.provide('box2d.PolyDef'); 20 | 21 | goog.require('box2d.Shape'); 22 | goog.require('box2d.ShapeDef'); 23 | goog.require('box2d.Vec2'); 24 | 25 | 26 | 27 | /** 28 | @constructor 29 | @extends {box2d.ShapeDef} 30 | */ 31 | box2d.PolyDef = function() { 32 | goog.base(this); 33 | 34 | // 35 | // initialize instance variables for references 36 | this.vertices = new Array(box2d.Settings.b2_maxPolyVertices); 37 | // 38 | this.type = box2d.ShapeDef.Type.polyShape; 39 | this.vertexCount = 0; 40 | 41 | for (var i = 0; i < box2d.Settings.b2_maxPolyVertices; i++) { 42 | this.vertices[i] = new box2d.Vec2(); 43 | } 44 | }; 45 | goog.inherits(box2d.PolyDef, box2d.ShapeDef); 46 | 47 | box2d.PolyDef.prototype.SetVertices = function(vertexArray) { 48 | this.vertexCount = vertexArray.length; 49 | for (var i = 0; i < vertexArray.length; i++) { 50 | this.vertices[i].Set(vertexArray[i][0], vertexArray[i][1]); 51 | } 52 | }; 53 | 54 | box2d.PolyDef.prototype.ComputeMass = function(massData) { 55 | 56 | massData.center = new box2d.Vec2(0.0, 0.0); 57 | 58 | if (this.density == 0.0) { 59 | massData.mass = 0.0; 60 | massData.center.Set(0.0, 0.0); 61 | massData.I = 0.0; 62 | } 63 | 64 | box2d.Shape.PolyMass(massData, this.vertices, this.vertexCount, this.density); 65 | }; 66 | -------------------------------------------------------------------------------- /src/box2d/collision/shapes/b2ShapeDef.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2007 Erin Catto http: 3 | * 4 | * This software is provided 'as-is', without any express or implied 5 | * warranty. In no event will the authors be held liable for any damages 6 | * arising from the use of this software. 7 | * Permission is granted to anyone to use this software for any purpose, 8 | * including commercial applications, and to alter it and redistribute it 9 | * freely, subject to the following restrictions: 10 | * 1. The origin of this software must not be misrepresented; you must not 11 | * claim that you wrote the original software. If you use this software 12 | * in a product, an acknowledgment in the product documentation would be 13 | * appreciated but is not required. 14 | * 2. Altered source versions must be plainly marked, and must not be 15 | * misrepresented the original software. 16 | * 3. This notice may not be removed or altered from any source distribution. 17 | */ 18 | 19 | goog.provide('box2d.ShapeDef'); 20 | 21 | goog.require('box2d.Vec2'); 22 | 23 | 24 | 25 | /** @constructor */ 26 | box2d.ShapeDef = function() { 27 | this.type = box2d.ShapeDef.Type.unknownShape; 28 | this.userData = null; 29 | this.localPosition = new box2d.Vec2(0.0, 0.0); 30 | this.localRotation = 0.0; 31 | this.friction = 0.2; 32 | this.restitution = 0.0; 33 | this.density = 0.0; 34 | this.categoryBits = 0x0001; 35 | this.maskBits = 0xFFFF; 36 | this.groupIndex = 0; 37 | }; 38 | 39 | box2d.ShapeDef.prototype.ComputeMass = function(massData) { 40 | massData.center = new box2d.Vec2(0.0, 0.0); 41 | massData.mass = 0.0; 42 | massData.I = 0.0; 43 | }; 44 | 45 | // The collision category bits. Normally you would just set one bit. 46 | box2d.ShapeDef.prototype.categoryBits = 0; 47 | 48 | // The collision mask bits. This states the categories that this 49 | // shape would accept for collision. 50 | box2d.ShapeDef.prototype.maskBits = 0; 51 | 52 | // Collision groups allow a certain group of objects to never collide (negative) 53 | // or always collide (positive). Zero means no collision group. Non-zero group 54 | // filtering always wins against the mask bits. 55 | box2d.ShapeDef.prototype.groupIndex = 0; 56 | 57 | 58 | /** 59 | @enum {number} 60 | */ 61 | box2d.ShapeDef.Type = { 62 | unknownShape: -1, 63 | circleShape: 0, 64 | boxShape: 1, 65 | polyShape: 2, 66 | meshShape: 3, 67 | shapeTypeCount: 4 68 | }; 69 | -------------------------------------------------------------------------------- /src/box2d/collision/shapes/b2ShapeFactory.js: -------------------------------------------------------------------------------- 1 | 2 | goog.provide('box2d.ShapeFactory'); 3 | 4 | goog.require('box2d.BoxDef'); 5 | goog.require('box2d.CircleDef'); 6 | goog.require('box2d.CircleShape'); 7 | goog.require('box2d.PolyDef'); 8 | goog.require('box2d.PolyShape'); 9 | goog.require('box2d.ShapeDef'); 10 | 11 | 12 | /** 13 | @param {!box2d.ShapeDef} def 14 | @param {!box2d.Body} body 15 | @param {!box2d.Vec2} center 16 | @return {!box2d.Shape} 17 | */ 18 | box2d.ShapeFactory.Create = function(def, body, center) { 19 | if (def instanceof box2d.CircleDef) { 20 | return new box2d.CircleShape(def, body, center); 21 | } 22 | else if (def instanceof box2d.BoxDef) { 23 | return new box2d.PolyShape(def, body, center); 24 | } 25 | else if (def instanceof box2d.PolyDef) { 26 | return new box2d.PolyShape(def, body, center); 27 | } 28 | else { 29 | throw 'unsupported ShapeDef'; 30 | } 31 | }; 32 | -------------------------------------------------------------------------------- /src/box2d/common/b2Mat22.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2007 Erin Catto http: 3 | * 4 | * This software is provided 'as-is', without any express or implied 5 | * warranty. In no event will the authors be held liable for any damages 6 | * arising from the use of this software. 7 | * Permission is granted to anyone to use this software for any purpose, 8 | * including commercial applications, and to alter it and redistribute it 9 | * freely, subject to the following restrictions: 10 | * 1. The origin of this software must not be misrepresented; you must not 11 | * claim that you wrote the original software. If you use this software 12 | * in a product, an acknowledgment in the product documentation would be 13 | * appreciated but is not required. 14 | * 2. Altered source versions must be plainly marked, and must not be 15 | * misrepresented the original software. 16 | * 3. This notice may not be removed or altered from any source distribution. 17 | */ 18 | 19 | goog.provide('box2d.Mat22'); 20 | 21 | 22 | 23 | /** @constructor 24 | @param {number=} angle 25 | @param {box2d.Vec2=} c1 26 | @param {box2d.Vec2=} c2 */ 27 | box2d.Mat22 = function(angle, c1, c2) { 28 | if (angle == null) angle = 0; 29 | // initialize instance variables for references 30 | 31 | /** @type {!box2d.Vec2} */ 32 | this.col1 = new box2d.Vec2(); 33 | 34 | /** @type {!box2d.Vec2} */ 35 | this.col2 = new box2d.Vec2(); 36 | // 37 | if (c1 != null && c2 != null) { 38 | this.col1.SetV(c1); 39 | this.col2.SetV(c2); 40 | } else { 41 | var c = Math.cos(angle); 42 | var s = Math.sin(angle); 43 | this.col1.x = c; 44 | this.col2.x = -s; 45 | this.col1.y = s; 46 | this.col2.y = c; 47 | } 48 | }; 49 | 50 | 51 | /** @param {number} angle */ 52 | box2d.Mat22.prototype.Set = function(angle) { 53 | var c = Math.cos(angle); 54 | var s = Math.sin(angle); 55 | this.col1.x = c; 56 | this.col2.x = -s; 57 | this.col1.y = s; 58 | this.col2.y = c; 59 | }; 60 | 61 | 62 | /** 63 | @param {!goog.math.Coordinate} c1 64 | @param {!goog.math.Coordinate} c2 */ 65 | box2d.Mat22.prototype.SetVV = function(c1, c2) { 66 | this.col1.SetV(c1); 67 | this.col2.SetV(c2); 68 | }; 69 | 70 | 71 | /** @return {box2d.Mat22} */ 72 | box2d.Mat22.prototype.Copy = function() { 73 | return new box2d.Mat22(0, this.col1, this.col2); 74 | }; 75 | 76 | 77 | /** @param {box2d.Mat22} m */ 78 | box2d.Mat22.prototype.SetM = function(m) { 79 | this.col1.SetV(m.col1); 80 | this.col2.SetV(m.col2); 81 | }; 82 | 83 | 84 | /** @param {box2d.Mat22} m */ 85 | box2d.Mat22.prototype.AddM = function(m) { 86 | this.col1.x += m.col1.x; 87 | this.col1.y += m.col1.y; 88 | this.col2.x += m.col2.x; 89 | this.col2.y += m.col2.y; 90 | }; 91 | 92 | box2d.Mat22.prototype.SetIdentity = function() { 93 | this.col1.x = 1.0; 94 | this.col2.x = 0.0; 95 | this.col1.y = 0.0; 96 | this.col2.y = 1.0; 97 | }; 98 | 99 | box2d.Mat22.prototype.SetZero = function() { 100 | this.col1.x = 0.0; 101 | this.col2.x = 0.0; 102 | this.col1.y = 0.0; 103 | this.col2.y = 0.0; 104 | }; 105 | 106 | 107 | /** @param {box2d.Mat22} out */ 108 | box2d.Mat22.prototype.Invert = function(out) { 109 | var a = this.col1.x; 110 | var b = this.col2.x; 111 | var c = this.col1.y; 112 | var d = this.col2.y; 113 | //var B = new box2d.Mat22(); 114 | var det = a * d - b * c; 115 | //box2d.Settings.b2Assert(det != 0.0); 116 | det = 1.0 / det; 117 | out.col1.x = det * d; 118 | out.col2.x = -det * b; 119 | out.col1.y = -det * c; 120 | out.col2.y = det * a; 121 | return out; 122 | }; 123 | 124 | 125 | // this.Solve A * x = b 126 | /** 127 | @param {box2d.Vec2} out 128 | @param {number} bX 129 | @param {number} bY */ 130 | box2d.Mat22.prototype.Solve = function(out, bX, bY) { 131 | //float32 a11 = this.col1.x, a12 = this.col2.x, a21 = this.col1.y, a22 = this.col2.y; 132 | var a11 = this.col1.x; 133 | var a12 = this.col2.x; 134 | var a21 = this.col1.y; 135 | var a22 = this.col2.y; 136 | //float32 det = a11 * a22 - a12 * a21; 137 | var det = a11 * a22 - a12 * a21; 138 | //box2d.Settings.b2Assert(det != 0.0); 139 | det = 1.0 / det; 140 | out.x = det * (a22 * bX - a12 * bY); 141 | out.y = det * (a11 * bY - a21 * bX); 142 | 143 | return out; 144 | }; 145 | 146 | box2d.Mat22.prototype.Abs = function() { 147 | this.col1.Abs(); 148 | this.col2.Abs(); 149 | }; 150 | -------------------------------------------------------------------------------- /src/box2d/common/b2Math.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2007 Erin Catto http: 3 | * 4 | * This software is provided 'as-is', without any express or implied 5 | * warranty. In no event will the authors be held liable for any damages 6 | * arising from the use of this software. 7 | * Permission is granted to anyone to use this software for any purpose, 8 | * including commercial applications, and to alter it and redistribute it 9 | * freely, subject to the following restrictions: 10 | * 1. The origin of this software must not be misrepresented; you must not 11 | * claim that you wrote the original software. If you use this software 12 | * in a product, an acknowledgment in the product documentation would be 13 | * appreciated but is not required. 14 | * 2. Altered source versions must be plainly marked, and must not be 15 | * misrepresented the original software. 16 | * 3. This notice may not be removed or altered from any source distribution. 17 | */ 18 | 19 | goog.provide('box2d.Math'); 20 | 21 | goog.require('box2d.Mat22'); 22 | goog.require('box2d.Vec2'); 23 | 24 | goog.require('goog.math'); 25 | 26 | 27 | /** 28 | @param {!box2d.Mat22} A 29 | @param {!box2d.Vec2} v 30 | @return {!box2d.Vec2} 31 | */ 32 | box2d.Math.b2MulMV = function(A, v) { 33 | return new box2d.Vec2(A.col1.x * v.x + A.col2.x * v.y, A.col1.y * v.x + A.col2.y * v.y); 34 | }; 35 | 36 | 37 | /** 38 | @return {!box2d.Vec2} 39 | */ 40 | box2d.Math.b2MulTMV = function(A, v) { 41 | return new box2d.Vec2(goog.math.Vec2.dot(v, A.col1), goog.math.Vec2.dot(v, A.col2)); 42 | }; 43 | 44 | box2d.Math.b2MulMM = function(A, B) { 45 | return new box2d.Mat22(0, box2d.Math.b2MulMV(A, B.col1), box2d.Math.b2MulMV(A, B.col2)); 46 | }; 47 | 48 | box2d.Math.b2AbsM = function(A) { 49 | return new box2d.Mat22(0, box2d.Vec2.abs(A.col1), box2d.Vec2.abs(A.col2)); 50 | }; 51 | 52 | 53 | /** 54 | @param {number} a 55 | @param {number} low 56 | @param {number} high 57 | @return {number} 58 | */ 59 | box2d.Math.b2Clamp = function(a, low, high) { 60 | return Math.max(low, Math.min(a, high)); 61 | }; 62 | -------------------------------------------------------------------------------- /src/box2d/common/b2Settings.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2007 Erin Catto http: 3 | * 4 | * This software is provided 'as-is', without any express or implied 5 | * warranty. In no event will the authors be held liable for any damages 6 | * arising from the use of this software. 7 | * Permission is granted to anyone to use this software for any purpose, 8 | * including commercial applications, and to alter it and redistribute it 9 | * freely, subject to the following restrictions: 10 | * 1. The origin of this software must not be misrepresented; you must not 11 | * claim that you wrote the original software. If you use this software 12 | * in a product, an acknowledgment in the product documentation would be 13 | * appreciated but is not required. 14 | * 2. Altered source versions must be plainly marked, and must not be 15 | * misrepresented the original software. 16 | * 3. This notice may not be removed or altered from any source distribution. 17 | */ 18 | 19 | goog.provide('box2d.Settings'); 20 | 21 | 22 | /** @const @type {number} */ 23 | box2d.Settings.USHRT_MAX = 0x0000ffff; 24 | 25 | 26 | /** @const @type {number} */ 27 | box2d.Settings.invalid = box2d.Settings.USHRT_MAX; 28 | 29 | 30 | /** @const @type {number} */ 31 | box2d.Settings.b2_pi = Math.PI; 32 | 33 | 34 | /** @const @type {number} */ 35 | box2d.Settings.b2_massUnitsPerKilogram = 1.0; 36 | 37 | 38 | /** @const @type {number} */ 39 | box2d.Settings.b2_timeUnitsPerSecond = 1.0; 40 | 41 | 42 | /** @const @type {number} */ 43 | box2d.Settings.b2_lengthUnitsPerMeter = 30.0; 44 | 45 | 46 | /** @const @type {number} */ 47 | box2d.Settings.b2_maxManifoldPoints = 2; 48 | 49 | 50 | /** @const @type {number} */ 51 | box2d.Settings.b2_maxShapesPerBody = 64; 52 | 53 | 54 | /** @const @type {number} */ 55 | box2d.Settings.b2_maxPolyVertices = 8; 56 | 57 | 58 | /** @const @type {number} */ 59 | box2d.Settings.b2_maxProxies = 1024; 60 | 61 | 62 | /** @const @type {number} */ 63 | box2d.Settings.b2_maxPairs = 8 * box2d.Settings.b2_maxProxies; 64 | 65 | 66 | /** @const @type {number} */ 67 | box2d.Settings.b2_linearSlop = 0.005 * box2d.Settings.b2_lengthUnitsPerMeter; 68 | 69 | 70 | /** @const @type {number} */ 71 | box2d.Settings.b2_angularSlop = 2.0 / 180.0 * box2d.Settings.b2_pi; 72 | 73 | 74 | /** @const @type {number} */ 75 | box2d.Settings.b2_velocityThreshold = 1.0 * box2d.Settings.b2_lengthUnitsPerMeter / box2d.Settings.b2_timeUnitsPerSecond; 76 | 77 | 78 | /** @const @type {number} */ 79 | box2d.Settings.b2_maxLinearCorrection = 0.2 * box2d.Settings.b2_lengthUnitsPerMeter; 80 | 81 | 82 | /** @const @type {number} */ 83 | box2d.Settings.b2_maxAngularCorrection = 8.0 / 180.0 * box2d.Settings.b2_pi; 84 | 85 | 86 | /** @const @type {number} */ 87 | box2d.Settings.b2_contactBaumgarte = 0.2; 88 | 89 | 90 | /** @const @type {number} */ 91 | box2d.Settings.b2_timeToSleep = 0.5 * box2d.Settings.b2_timeUnitsPerSecond; 92 | 93 | 94 | /** @const @type {number} */ 95 | box2d.Settings.b2_linearSleepTolerance = 0.01 * box2d.Settings.b2_lengthUnitsPerMeter / box2d.Settings.b2_timeUnitsPerSecond; 96 | 97 | 98 | /** @const @type {number} */ 99 | box2d.Settings.b2_angularSleepTolerance = 2.0 / 180.0 / box2d.Settings.b2_timeUnitsPerSecond; 100 | 101 | 102 | /** @const @type {number} */ 103 | box2d.Settings.FLT_EPSILON = 0.0000001192092896; 104 | 105 | 106 | /** @const @type {function(boolean)} */ 107 | box2d.Settings.b2Assert = function(a) { 108 | if (!a) { 109 | throw 'Assert Failed!'; 110 | } 111 | }; 112 | -------------------------------------------------------------------------------- /src/box2d/dynamics/b2BodyDef.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2007 Erin Catto http: 3 | * 4 | * This software is provided 'as-is', without any express or implied 5 | * warranty. In no event will the authors be held liable for any damages 6 | * arising from the use of this software. 7 | * Permission is granted to anyone to use this software for any purpose, 8 | * including commercial applications, and to alter it and redistribute it 9 | * freely, subject to the following restrictions: 10 | * 1. The origin of this software must not be misrepresented; you must not 11 | * claim that you wrote the original software. If you use this software 12 | * in a product, an acknowledgment in the product documentation would be 13 | * appreciated but is not required. 14 | * 2. Altered source versions must be plainly marked, and must not be 15 | * misrepresented the original software. 16 | * 3. This notice may not be removed or altered from any source distribution. 17 | */ 18 | 19 | goog.provide('box2d.BodyDef'); 20 | 21 | goog.require('box2d.Settings'); 22 | goog.require('box2d.ShapeDef'); 23 | 24 | 25 | 26 | /** 27 | @constructor 28 | */ 29 | box2d.BodyDef = function() { 30 | /** 31 | @type {!Array.} 32 | */ 33 | this.shapes = new Array(); 34 | /** 35 | @type {Object} 36 | */ 37 | this.userData = null; 38 | for (var i = 0; i < box2d.Settings.b2_maxShapesPerBody; i++) { 39 | this.shapes[i] = null; 40 | } 41 | /** 42 | @type {!box2d.Vec2} 43 | */ 44 | this.position = new box2d.Vec2(0.0, 0.0); 45 | /** 46 | @type {number} 47 | */ 48 | this.rotation = 0.0; 49 | /** 50 | @type {!box2d.Vec2} 51 | */ 52 | this.linearVelocity = new box2d.Vec2(0.0, 0.0); 53 | /** 54 | @type {number} 55 | */ 56 | this.angularVelocity = 0.0; 57 | /** 58 | @type {number} 59 | */ 60 | this.linearDamping = 0.0; 61 | /** 62 | @type {number} 63 | */ 64 | this.angularDamping = 0.0; 65 | /** 66 | @type {boolean} 67 | */ 68 | this.allowSleep = true; 69 | /** 70 | @type {boolean} 71 | */ 72 | this.isSleeping = false; 73 | /** 74 | @type {boolean} 75 | */ 76 | this.preventRotation = false; 77 | }; 78 | 79 | 80 | /** 81 | @param {!box2d.ShapeDef} shape 82 | */ 83 | box2d.BodyDef.prototype.AddShape = function(shape) { 84 | for (var i = 0; i < box2d.Settings.b2_maxShapesPerBody; ++i) { 85 | if (this.shapes[i] == null) { 86 | this.shapes[i] = shape; 87 | break; 88 | } 89 | } 90 | }; 91 | -------------------------------------------------------------------------------- /src/box2d/dynamics/b2CollisionFilter.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2007 Erin Catto http: 3 | * 4 | * This software is provided 'as-is', without any express or implied 5 | * warranty. In no event will the authors be held liable for any damages 6 | * arising from the use of this software. 7 | * Permission is granted to anyone to use this software for any purpose, 8 | * including commercial applications, and to alter it and redistribute it 9 | * freely, subject to the following restrictions: 10 | * 1. The origin of this software must not be misrepresented; you must not 11 | * claim that you wrote the original software. If you use this software 12 | * in a product, an acknowledgment in the product documentation would be 13 | * appreciated but is not required. 14 | * 2. Altered source versions must be plainly marked, and must not be 15 | * misrepresented the original software. 16 | * 3. This notice may not be removed or altered from any source distribution. 17 | */ 18 | 19 | goog.provide('box2d.CollisionFilter'); 20 | 21 | 22 | 23 | /** 24 | @constructor 25 | */ 26 | box2d.CollisionFilter = function() {}; 27 | 28 | 29 | /** 30 | Return true if contact calculations should be performed between these two shapes. 31 | @param {!box2d.Shape} shape1 32 | @param {!box2d.Shape} shape2 33 | @return {boolean} 34 | */ 35 | box2d.CollisionFilter.prototype.ShouldCollide = function(shape1, shape2) { 36 | if (shape1.m_groupIndex == shape2.m_groupIndex && shape1.m_groupIndex != 0) { 37 | return shape1.m_groupIndex > 0; 38 | } 39 | 40 | var collide = (shape1.maskBits & shape2.categoryBits) != 0 && (shape1.categoryBits & shape2.maskBits) != 0; 41 | return collide; 42 | }; 43 | 44 | 45 | /** 46 | @type {!box2d.CollisionFilter} 47 | @const 48 | */ 49 | box2d.CollisionFilter.b2_defaultFilter = new box2d.CollisionFilter(); 50 | -------------------------------------------------------------------------------- /src/box2d/dynamics/b2TimeStep.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2007 Erin Catto http: 3 | * 4 | * This software is provided 'as-is', without any express or implied 5 | * warranty. In no event will the authors be held liable for any damages 6 | * arising from the use of this software. 7 | * Permission is granted to anyone to use this software for any purpose, 8 | * including commercial applications, and to alter it and redistribute it 9 | * freely, subject to the following restrictions: 10 | * 1. The origin of this software must not be misrepresented; you must not 11 | * claim that you wrote the original software. If you use this software 12 | * in a product, an acknowledgment in the product documentation would be 13 | * appreciated but is not required. 14 | * 2. Altered source versions must be plainly marked, and must not be 15 | * misrepresented the original software. 16 | * 3. This notice may not be removed or altered from any source distribution. 17 | */ 18 | 19 | goog.provide('box2d.TimeStep'); 20 | 21 | 22 | 23 | /** 24 | @constructor 25 | */ 26 | box2d.TimeStep = function() { 27 | this.dt = null; 28 | this.inv_dt = null; 29 | this.iterations = 0; 30 | }; 31 | -------------------------------------------------------------------------------- /src/box2d/dynamics/b2WorldListener.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2007 Erin Catto http: 3 | * 4 | * This software is provided 'as-is', without any express or implied 5 | * warranty. In no event will the authors be held liable for any damages 6 | * arising from the use of this software. 7 | * Permission is granted to anyone to use this software for any purpose, 8 | * including commercial applications, and to alter it and redistribute it 9 | * freely, subject to the following restrictions: 10 | * 1. The origin of this software must not be misrepresented; you must not 11 | * claim that you wrote the original software. If you use this software 12 | * in a product, an acknowledgment in the product documentation would be 13 | * appreciated but is not required. 14 | * 2. Altered source versions must be plainly marked, and must not be 15 | * misrepresented the original software. 16 | * 3. This notice may not be removed or altered from any source distribution. 17 | */ 18 | 19 | goog.provide('box2d.WorldListener'); 20 | 21 | 22 | 23 | /** 24 | @constructor 25 | */ 26 | box2d.WorldListener = function() {}; 27 | 28 | // If a body is destroyed, then any joints attached to it are also destroyed. 29 | // This prevents memory leaks, but you may unexpectedly be left with an 30 | // orphaned joint pointer. 31 | // Box2D will notify you when a joint is implicitly destroyed. 32 | // It is NOT called if you directly destroy a joint. 33 | // Implement this abstract class and provide it to box2d.World via 34 | // box2d.World::SetListener(). 35 | // DO NOT modify the Box2D world inside this callback. 36 | box2d.WorldListener.prototype.NotifyJointDestroyed = function(joint) {}; 37 | 38 | // This is called when a body's shape passes outside of the world boundary. If you 39 | // override this and pass back e_destroyBody, you must nullify your copies of the 40 | // body pointer. 41 | box2d.WorldListener.prototype.NotifyBoundaryViolated = function(body) { 42 | //NOT_USED(body); 43 | return box2d.WorldListener.b2_freezeBody; 44 | }; 45 | box2d.WorldListener.b2_freezeBody = 0; 46 | box2d.WorldListener.b2_destroyBody = 1; 47 | -------------------------------------------------------------------------------- /src/box2d/dynamics/contacts/b2CircleContact.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2007 Erin Catto http: 3 | * 4 | * This software is provided 'as-is', without any express or implied 5 | * warranty. In no event will the authors be held liable for any damages 6 | * arising from the use of this software. 7 | * Permission is granted to anyone to use this software for any purpose, 8 | * including commercial applications, and to alter it and redistribute it 9 | * freely, subject to the following restrictions: 10 | * 1. The origin of this software must not be misrepresented; you must not 11 | * claim that you wrote the original software. If you use this software 12 | * in a product, an acknowledgment in the product documentation would be 13 | * appreciated but is not required. 14 | * 2. Altered source versions must be plainly marked, and must not be 15 | * misrepresented the original software. 16 | * 3. This notice may not be removed or altered from any source distribution. 17 | */ 18 | 19 | goog.provide('box2d.CircleContact'); 20 | 21 | goog.require('box2d.CircleShape'); 22 | goog.require('box2d.Collision'); 23 | goog.require('box2d.Contact'); 24 | goog.require('box2d.Manifold'); 25 | 26 | 27 | 28 | /** 29 | @constructor 30 | @extends {box2d.Contact} 31 | @param {!box2d.CircleShape} s1 32 | @param {!box2d.CircleShape} s2 33 | */ 34 | box2d.CircleContact = function(s1, s2) { 35 | // The constructor for box2d.Contact 36 | // initialize instance variables for references 37 | this.m_node1 = new box2d.ContactNode(); 38 | this.m_node2 = new box2d.ContactNode(); 39 | // 40 | this.m_flags = 0; 41 | 42 | if (!s1 || !s2) { 43 | this.m_shape1 = null; 44 | this.m_shape2 = null; 45 | return; 46 | } 47 | 48 | this.m_shape1 = s1; 49 | this.m_shape2 = s2; 50 | 51 | this.m_manifoldCount = 0; 52 | 53 | this.m_friction = Math.sqrt(this.m_shape1.m_friction * this.m_shape2.m_friction); 54 | this.m_restitution = Math.max(this.m_shape1.m_restitution, this.m_shape2.m_restitution); 55 | 56 | this.m_prev = null; 57 | this.m_next = null; 58 | 59 | this.m_node1.contact = null; 60 | this.m_node1.prev = null; 61 | this.m_node1.next = null; 62 | this.m_node1.other = null; 63 | 64 | this.m_node2.contact = null; 65 | this.m_node2.prev = null; 66 | this.m_node2.next = null; 67 | this.m_node2.other = null; 68 | // 69 | // initialize instance variables for references 70 | this.m_manifold = [new box2d.Manifold()]; 71 | 72 | this.m_manifold[0].pointCount = 0; 73 | this.m_manifold[0].points[0].normalImpulse = 0.0; 74 | this.m_manifold[0].points[0].tangentImpulse = 0.0; 75 | }; 76 | goog.inherits(box2d.CircleContact, box2d.Contact); 77 | 78 | box2d.CircleContact.prototype.getBodies = function() { 79 | return [this.m_shape1.m_body, this.m_shape2.m_body]; 80 | }; 81 | 82 | box2d.CircleContact.prototype.Evaluate = function() { 83 | box2d.Collision.b2CollideCircle(this.m_manifold[0], this.m_shape1, this.m_shape2, false); 84 | 85 | if (this.m_manifold[0].pointCount > 0) { 86 | this.m_manifoldCount = 1; 87 | } else { 88 | this.m_manifoldCount = 0; 89 | } 90 | }; 91 | 92 | box2d.CircleContact.prototype.GetManifolds = function() { 93 | return this.m_manifold; 94 | }; 95 | 96 | box2d.CircleContact.Create = function(shape1, shape2) { 97 | return new box2d.CircleContact(shape1, shape2); 98 | }; 99 | -------------------------------------------------------------------------------- /src/box2d/dynamics/contacts/b2Contact.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2007 Erin Catto http: 3 | * 4 | * This software is provided 'as-is', without any express or implied 5 | * warranty. In no event will the authors be held liable for any damages 6 | * arising from the use of this software. 7 | * Permission is granted to anyone to use this software for any purpose, 8 | * including commercial applications, and to alter it and redistribute it 9 | * freely, subject to the following restrictions: 10 | * 1. The origin of this software must not be misrepresented; you must not 11 | * claim that you wrote the original software. If you use this software 12 | * in a product, an acknowledgment in the product documentation would be 13 | * appreciated but is not required. 14 | * 2. Altered source versions must be plainly marked, and must not be 15 | * misrepresented the original software. 16 | * 3. This notice may not be removed or altered from any source distribution. 17 | */ 18 | 19 | goog.provide('box2d.Contact'); 20 | 21 | goog.require('box2d.ContactNode'); 22 | goog.require('box2d.ContactRegister'); 23 | 24 | 25 | 26 | /** 27 | @constructor 28 | */ 29 | box2d.Contact = function(s1, s2) { 30 | // initialize instance variables for references 31 | this.m_node1 = new box2d.ContactNode(); 32 | this.m_node2 = new box2d.ContactNode(); 33 | // 34 | this.m_flags = 0; 35 | 36 | if (!s1 || !s2) { 37 | this.m_shape1 = null; 38 | this.m_shape2 = null; 39 | return; 40 | } 41 | 42 | this.m_shape1 = s1; 43 | this.m_shape2 = s2; 44 | 45 | this.m_manifoldCount = 0; 46 | 47 | this.m_friction = Math.sqrt(this.m_shape1.m_friction * this.m_shape2.m_friction); 48 | this.m_restitution = Math.max(this.m_shape1.m_restitution, this.m_shape2.m_restitution); 49 | 50 | this.m_prev = null; 51 | this.m_next = null; 52 | 53 | this.m_node1.contact = null; 54 | this.m_node1.prev = null; 55 | this.m_node1.next = null; 56 | this.m_node1.other = null; 57 | 58 | this.m_node2.contact = null; 59 | this.m_node2.prev = null; 60 | this.m_node2.next = null; 61 | this.m_node2.other = null; 62 | }; 63 | 64 | box2d.Contact.prototype.GetManifolds = function() { 65 | return null; 66 | }; 67 | 68 | box2d.Contact.prototype.GetManifoldCount = function() { 69 | return this.m_manifoldCount; 70 | }; 71 | 72 | box2d.Contact.prototype.GetNext = function() { 73 | return this.m_next; 74 | }; 75 | 76 | box2d.Contact.prototype.GetShape1 = function() { 77 | return this.m_shape1; 78 | }; 79 | 80 | box2d.Contact.prototype.GetShape2 = function() { 81 | return this.m_shape2; 82 | }; 83 | 84 | box2d.Contact.prototype.Evaluate = function() {}; 85 | 86 | /* 87 | @const 88 | @type {number} 89 | */ 90 | box2d.Contact.e_islandFlag = 0x0001; 91 | /* 92 | @const 93 | @type {number} 94 | */ 95 | box2d.Contact.e_destroyFlag = 0x0002; 96 | -------------------------------------------------------------------------------- /src/box2d/dynamics/contacts/b2ContactConstraint.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2007 Erin Catto http: 3 | * 4 | * This software is provided 'as-is', without any express or implied 5 | * warranty. In no event will the authors be held liable for any damages 6 | * arising from the use of this software. 7 | * Permission is granted to anyone to use this software for any purpose, 8 | * including commercial applications, and to alter it and redistribute it 9 | * freely, subject to the following restrictions: 10 | * 1. The origin of this software must not be misrepresented; you must not 11 | * claim that you wrote the original software. If you use this software 12 | * in a product, an acknowledgment in the product documentation would be 13 | * appreciated but is not required. 14 | * 2. Altered source versions must be plainly marked, and must not be 15 | * misrepresented the original software. 16 | * 3. This notice may not be removed or altered from any source distribution. 17 | */ 18 | 19 | goog.provide('box2d.ContactConstraint'); 20 | goog.require('box2d.ContactConstraintPoint'); 21 | goog.require('box2d.Settings'); 22 | goog.require('box2d.Vec2'); 23 | 24 | 25 | 26 | /** 27 | @constructor 28 | */ 29 | box2d.ContactConstraint = function() { 30 | this.manifold = null; 31 | this.body1 = null; 32 | this.body2 = null; 33 | this.friction = null; 34 | this.restitution = null; 35 | this.pointCount = 0; 36 | this.normal = new box2d.Vec2(); 37 | 38 | this.points = new Array(box2d.Settings.b2_maxManifoldPoints); 39 | for (var i = 0; i < box2d.Settings.b2_maxManifoldPoints; i++) { 40 | this.points[i] = new box2d.ContactConstraintPoint(); 41 | } 42 | 43 | }; 44 | -------------------------------------------------------------------------------- /src/box2d/dynamics/contacts/b2ContactConstraintPoint.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2007 Erin Catto http: 3 | * 4 | * This software is provided 'as-is', without any express or implied 5 | * warranty. In no event will the authors be held liable for any damages 6 | * arising from the use of this software. 7 | * Permission is granted to anyone to use this software for any purpose, 8 | * including commercial applications, and to alter it and redistribute it 9 | * freely, subject to the following restrictions: 10 | * 1. The origin of this software must not be misrepresented; you must not 11 | * claim that you wrote the original software. If you use this software 12 | * in a product, an acknowledgment in the product documentation would be 13 | * appreciated but is not required. 14 | * 2. Altered source versions must be plainly marked, and must not be 15 | * misrepresented the original software. 16 | * 3. This notice may not be removed or altered from any source distribution. 17 | */ 18 | 19 | goog.provide('box2d.ContactConstraintPoint'); 20 | 21 | goog.require('box2d.Vec2'); 22 | 23 | 24 | 25 | /** 26 | @constructor 27 | */ 28 | box2d.ContactConstraintPoint = function() { 29 | this.localAnchor1 = new box2d.Vec2(); 30 | this.localAnchor2 = new box2d.Vec2(); 31 | this.normalImpulse = null; 32 | this.tangentImpulse = null; 33 | this.positionImpulse = null; 34 | this.normalMass = null; 35 | this.tangentMass = null; 36 | this.separation = null; 37 | this.velocityBias = null; 38 | }; 39 | -------------------------------------------------------------------------------- /src/box2d/dynamics/contacts/b2ContactFactory.js: -------------------------------------------------------------------------------- 1 | goog.provide('box2d.ContactFactory'); 2 | 3 | goog.require('box2d.CircleContact'); 4 | goog.require('box2d.PolyAndCircleContact'); 5 | goog.require('box2d.PolyContact'); 6 | goog.require('box2d.Shape'); 7 | 8 | 9 | /** 10 | @return {box2d.Contact} 11 | */ 12 | box2d.ContactFactory.Create = function(shape1, shape2) { 13 | if (box2d.ContactFactory.s_initialized == false) { 14 | box2d.ContactFactory._InitializeRegisters(); 15 | box2d.ContactFactory.s_initialized = true; 16 | } 17 | 18 | var type1 = shape1.m_type; 19 | var type2 = shape2.m_type; 20 | 21 | var createFcn = box2d.ContactFactory.s_registers[type1][type2].createFcn; 22 | if (createFcn) { 23 | if (box2d.ContactFactory.s_registers[type1][type2].primary) { 24 | return createFcn(shape1, shape2); 25 | } else { 26 | var c = createFcn(shape2, shape1); 27 | for (var i = 0; i < c.GetManifoldCount(); ++i) { 28 | var m = c.GetManifolds()[i]; 29 | m.normal = m.normal.Negative(); 30 | } 31 | return c; 32 | } 33 | } else { 34 | return null; 35 | } 36 | }; 37 | 38 | box2d.ContactFactory.Destroy = function(contact, allocator) { 39 | if (contact.GetManifoldCount() > 0) { 40 | contact.m_shape1.m_body.WakeUp(); 41 | contact.m_shape2.m_body.WakeUp(); 42 | } 43 | }; 44 | 45 | 46 | /** 47 | @private 48 | */ 49 | box2d.ContactFactory._InitializeRegisters = function() { 50 | box2d.ContactFactory.s_registers = new Array(box2d.ShapeDef.Type.shapeTypeCount); 51 | for (var i = 0; i < box2d.ShapeDef.Type.shapeTypeCount; i++) { 52 | box2d.ContactFactory.s_registers[i] = new Array(box2d.ShapeDef.Type.shapeTypeCount); 53 | for (var j = 0; j < box2d.ShapeDef.Type.shapeTypeCount; j++) { 54 | box2d.ContactFactory.s_registers[i][j] = new box2d.ContactRegister(); 55 | } 56 | } 57 | 58 | box2d.ContactFactory._AddType(box2d.CircleContact.Create, box2d.ShapeDef.Type.circleShape, box2d.ShapeDef.Type.circleShape); 59 | box2d.ContactFactory._AddType(box2d.PolyAndCircleContact.Create, box2d.ShapeDef.Type.polyShape, box2d.ShapeDef.Type.circleShape); 60 | box2d.ContactFactory._AddType(box2d.PolyContact.Create, box2d.ShapeDef.Type.polyShape, box2d.ShapeDef.Type.polyShape); 61 | 62 | }; 63 | 64 | 65 | /** 66 | @private 67 | */ 68 | box2d.ContactFactory._AddType = function(createFcn, type1, type2) { 69 | box2d.ContactFactory.s_registers[type1][type2].createFcn = createFcn; 70 | box2d.ContactFactory.s_registers[type1][type2].primary = true; 71 | 72 | if (type1 != type2) { 73 | box2d.ContactFactory.s_registers[type2][type1].createFcn = createFcn; 74 | box2d.ContactFactory.s_registers[type2][type1].primary = false; 75 | } 76 | }; 77 | 78 | 79 | /** 80 | @type {Array.>} 81 | */ 82 | box2d.ContactFactory.s_registers = null; 83 | box2d.ContactFactory.s_initialized = false; 84 | -------------------------------------------------------------------------------- /src/box2d/dynamics/contacts/b2ContactNode.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2007 Erin Catto http: 3 | * 4 | * This software is provided 'as-is', without any express or implied 5 | * warranty. In no event will the authors be held liable for any damages 6 | * arising from the use of this software. 7 | * Permission is granted to anyone to use this software for any purpose, 8 | * including commercial applications, and to alter it and redistribute it 9 | * freely, subject to the following restrictions: 10 | * 1. The origin of this software must not be misrepresented; you must not 11 | * claim that you wrote the original software. If you use this software 12 | * in a product, an acknowledgment in the product documentation would be 13 | * appreciated but is not required. 14 | * 2. Altered source versions must be plainly marked, and must not be 15 | * misrepresented the original software. 16 | * 3. This notice may not be removed or altered from any source distribution. 17 | */ 18 | 19 | goog.provide('box2d.ContactNode'); 20 | 21 | 22 | 23 | /** 24 | @constructor 25 | */ 26 | box2d.ContactNode = function() { 27 | this.other = null; 28 | this.contact = null; 29 | this.prev = null; 30 | this.next = null; 31 | }; 32 | -------------------------------------------------------------------------------- /src/box2d/dynamics/contacts/b2ContactRegister.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2007 Erin Catto http: 3 | * 4 | * This software is provided 'as-is', without any express or implied 5 | * warranty. In no event will the authors be held liable for any damages 6 | * arising from the use of this software. 7 | * Permission is granted to anyone to use this software for any purpose, 8 | * including commercial applications, and to alter it and redistribute it 9 | * freely, subject to the following restrictions: 10 | * 1. The origin of this software must not be misrepresented; you must not 11 | * claim that you wrote the original software. If you use this software 12 | * in a product, an acknowledgment in the product documentation would be 13 | * appreciated but is not required. 14 | * 2. Altered source versions must be plainly marked, and must not be 15 | * misrepresented the original software. 16 | * 3. This notice may not be removed or altered from any source distribution. 17 | */ 18 | 19 | goog.provide('box2d.ContactRegister'); 20 | 21 | 22 | 23 | /** 24 | @constructor 25 | */ 26 | box2d.ContactRegister = function() { 27 | this.createFcn = null; 28 | this.destroyFcn = null; 29 | this.primary = null; 30 | }; 31 | -------------------------------------------------------------------------------- /src/box2d/dynamics/contacts/b2NullContact.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2007 Erin Catto http: 3 | * 4 | * This software is provided 'as-is', without any express or implied 5 | * warranty. In no event will the authors be held liable for any damages 6 | * arising from the use of this software. 7 | * Permission is granted to anyone to use this software for any purpose, 8 | * including commercial applications, and to alter it and redistribute it 9 | * freely, subject to the following restrictions: 10 | * 1. The origin of this software must not be misrepresented; you must not 11 | * claim that you wrote the original software. If you use this software 12 | * in a product, an acknowledgment in the product documentation would be 13 | * appreciated but is not required. 14 | * 2. Altered source versions must be plainly marked, and must not be 15 | * misrepresented the original software. 16 | * 3. This notice may not be removed or altered from any source distribution. 17 | */ 18 | 19 | goog.provide('box2d.NullContact'); 20 | 21 | goog.require('box2d.Contact'); 22 | goog.require('box2d.ContactNode'); 23 | 24 | 25 | 26 | /** 27 | @extends {box2d.Contact} 28 | @constructor 29 | @param {Object=} s1 30 | @param {Object=} s2 31 | */ 32 | box2d.NullContact = function(s1, s2) { 33 | // The constructor for box2d.Contact 34 | // initialize instance variables for references 35 | this.m_node1 = new box2d.ContactNode(); 36 | this.m_node2 = new box2d.ContactNode(); 37 | // 38 | this.m_flags = 0; 39 | 40 | if (!s1 || !s2) { 41 | this.m_shape1 = null; 42 | this.m_shape2 = null; 43 | return; 44 | } 45 | 46 | this.m_shape1 = s1; 47 | this.m_shape2 = s2; 48 | 49 | this.m_manifoldCount = 0; 50 | 51 | this.m_friction = Math.sqrt(this.m_shape1.m_friction * this.m_shape2.m_friction); 52 | this.m_restitution = Math.max(this.m_shape1.m_restitution, this.m_shape2.m_restitution); 53 | 54 | this.m_prev = null; 55 | this.m_next = null; 56 | 57 | this.m_node1.contact = null; 58 | this.m_node1.prev = null; 59 | this.m_node1.next = null; 60 | this.m_node1.other = null; 61 | 62 | this.m_node2.contact = null; 63 | this.m_node2.prev = null; 64 | this.m_node2.next = null; 65 | this.m_node2.other = null; 66 | // 67 | }; 68 | goog.inherits(box2d.NullContact, box2d.Contact); 69 | 70 | box2d.NullContact.prototype.Evaluate = function() {}; 71 | box2d.NullContact.prototype.GetManifolds = function() { 72 | return null; 73 | }; 74 | -------------------------------------------------------------------------------- /src/box2d/dynamics/contacts/b2PolyAndCircleContact.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2007 Erin Catto http: 3 | * 4 | * This software is provided 'as-is', without any express or implied 5 | * warranty. In no event will the authors be held liable for any damages 6 | * arising from the use of this software. 7 | * Permission is granted to anyone to use this software for any purpose, 8 | * including commercial applications, and to alter it and redistribute it 9 | * freely, subject to the following restrictions: 10 | * 1. The origin of this software must not be misrepresented; you must not 11 | * claim that you wrote the original software. If you use this software 12 | * in a product, an acknowledgment in the product documentation would be 13 | * appreciated but is not required. 14 | * 2. Altered source versions must be plainly marked, and must not be 15 | * misrepresented the original software. 16 | * 3. This notice may not be removed or altered from any source distribution. 17 | */ 18 | 19 | goog.provide('box2d.PolyAndCircleContact'); 20 | 21 | goog.require('box2d.CircleShape'); 22 | goog.require('box2d.Contact'); 23 | goog.require('box2d.ContactNode'); 24 | goog.require('box2d.Manifold'); 25 | goog.require('box2d.PolyShape'); 26 | 27 | 28 | 29 | /** 30 | @constructor 31 | @extends {box2d.Contact} 32 | @param {!box2d.PolyShape} s1 33 | @param {!box2d.CircleShape} s2 34 | */ 35 | box2d.PolyAndCircleContact = function(s1, s2) { 36 | // The constructor for box2d.Contact 37 | // initialize instance variables for references 38 | this.m_node1 = new box2d.ContactNode(); 39 | this.m_node2 = new box2d.ContactNode(); 40 | // 41 | this.m_flags = 0; 42 | 43 | if (!s1 || !s2) { 44 | this.m_shape1 = null; 45 | this.m_shape2 = null; 46 | return; 47 | } 48 | 49 | this.m_shape1 = s1; 50 | this.m_shape2 = s2; 51 | 52 | this.m_manifoldCount = 0; 53 | 54 | this.m_friction = Math.sqrt(this.m_shape1.m_friction * this.m_shape2.m_friction); 55 | this.m_restitution = Math.max(this.m_shape1.m_restitution, this.m_shape2.m_restitution); 56 | 57 | this.m_prev = null; 58 | this.m_next = null; 59 | 60 | this.m_node1.contact = null; 61 | this.m_node1.prev = null; 62 | this.m_node1.next = null; 63 | this.m_node1.other = null; 64 | 65 | this.m_node2.contact = null; 66 | this.m_node2.prev = null; 67 | this.m_node2.next = null; 68 | this.m_node2.other = null; 69 | // 70 | // initialize instance variables for references 71 | this.m_manifold = [new box2d.Manifold()]; 72 | 73 | this.m_manifold[0].pointCount = 0; 74 | this.m_manifold[0].points[0].normalImpulse = 0.0; 75 | this.m_manifold[0].points[0].tangentImpulse = 0.0; 76 | }; 77 | goog.inherits(box2d.PolyAndCircleContact, box2d.Contact); 78 | 79 | box2d.PolyAndCircleContact.prototype.getBodies = function() { 80 | return [this.m_shape1.m_body, this.m_shape2.m_body]; 81 | }; 82 | 83 | box2d.PolyAndCircleContact.prototype.Evaluate = function() { 84 | box2d.Collision.b2CollidePolyAndCircle(this.m_manifold[0], this.m_shape1, this.m_shape2, false); 85 | 86 | if (this.m_manifold[0].pointCount > 0) { 87 | this.m_manifoldCount = 1; 88 | } else { 89 | this.m_manifoldCount = 0; 90 | } 91 | }; 92 | box2d.PolyAndCircleContact.prototype.GetManifolds = function() { 93 | return this.m_manifold; 94 | }; 95 | 96 | box2d.PolyAndCircleContact.Create = function(shape1, shape2) { 97 | return new box2d.PolyAndCircleContact(shape1, shape2); 98 | }; 99 | -------------------------------------------------------------------------------- /src/box2d/dynamics/contacts/b2PolyContact.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2007 Erin Catto http: 3 | * 4 | * This software is provided 'as-is', without any express or implied 5 | * warranty. In no event will the authors be held liable for any damages 6 | * arising from the use of this software. 7 | * Permission is granted to anyone to use this software for any purpose, 8 | * including commercial applications, and to alter it and redistribute it 9 | * freely, subject to the following restrictions: 10 | * 1. The origin of this software must not be misrepresented; you must not 11 | * claim that you wrote the original software. If you use this software 12 | * in a product, an acknowledgment in the product documentation would be 13 | * appreciated but is not required. 14 | * 2. Altered source versions must be plainly marked, and must not be 15 | * misrepresented the original software. 16 | * 3. This notice may not be removed or altered from any source distribution. 17 | */ 18 | 19 | goog.provide('box2d.PolyContact'); 20 | 21 | goog.require('box2d.ContactNode'); 22 | goog.require('box2d.Manifold'); 23 | goog.require('box2d.Math'); 24 | goog.require('box2d.PolyShape'); 25 | 26 | 27 | 28 | /** 29 | @constructor 30 | @extends {box2d.Contact} 31 | @param {!box2d.PolyShape} s1 32 | @param {!box2d.PolyShape} s2 33 | */ 34 | box2d.PolyContact = function(s1, s2) { 35 | // The constructor for box2d.Contact 36 | // initialize instance variables for references 37 | this.m_node1 = new box2d.ContactNode(); 38 | this.m_node2 = new box2d.ContactNode(); 39 | // 40 | this.m_flags = 0; 41 | 42 | if (!s1 || !s2) { 43 | this.m_shape1 = null; 44 | this.m_shape2 = null; 45 | return; 46 | } 47 | 48 | this.m_shape1 = s1; 49 | this.m_shape2 = s2; 50 | 51 | this.m_manifoldCount = 0; 52 | 53 | this.m_friction = Math.sqrt(this.m_shape1.m_friction * this.m_shape2.m_friction); 54 | this.m_restitution = Math.max(this.m_shape1.m_restitution, this.m_shape2.m_restitution); 55 | 56 | this.m_prev = null; 57 | this.m_next = null; 58 | 59 | this.m_node1.contact = null; 60 | this.m_node1.prev = null; 61 | this.m_node1.next = null; 62 | this.m_node1.other = null; 63 | 64 | this.m_node2.contact = null; 65 | this.m_node2.prev = null; 66 | this.m_node2.next = null; 67 | this.m_node2.other = null; 68 | // 69 | // initialize instance variables for references 70 | this.m0 = new box2d.Manifold(); 71 | this.m_manifold = [new box2d.Manifold()]; 72 | 73 | this.m_manifold[0].pointCount = 0; 74 | }; 75 | goog.inherits(box2d.PolyContact, box2d.Contact); 76 | 77 | box2d.PolyContact.prototype.Evaluate = function() { 78 | var tMani = this.m_manifold[0]; 79 | // replace memcpy 80 | // memcpy(&this.m0, &this.m_manifold, sizeof(b2Manifold)); 81 | //this.m0.points = new Array(tMani.pointCount); 82 | var tPoints = this.m0.points; 83 | 84 | for (var k = 0; k < tMani.pointCount; k++) { 85 | var tPoint = tPoints[k]; 86 | var tPoint0 = tMani.points[k]; 87 | //tPoint.separation = tPoint0.separation; 88 | tPoint.normalImpulse = tPoint0.normalImpulse; 89 | tPoint.tangentImpulse = tPoint0.tangentImpulse; 90 | //tPoint.position.SetV( tPoint0.position ); 91 | tPoint.id = tPoint0.id.Copy(); 92 | 93 | /*this.m0.points[k].id.features = new Features(); 94 | this.m0.points[k].id.features.referenceFace = this.m_manifold[0].points[k].id.features.referenceFace; 95 | this.m0.points[k].id.features.incidentEdge = this.m_manifold[0].points[k].id.features.incidentEdge; 96 | this.m0.points[k].id.features.incidentVertex = this.m_manifold[0].points[k].id.features.incidentVertex; 97 | this.m0.points[k].id.features.flip = this.m_manifold[0].points[k].id.features.flip;*/ 98 | } 99 | //this.m0.normal.SetV( tMani.normal ); 100 | this.m0.pointCount = tMani.pointCount; 101 | 102 | box2d.Collision.b2CollidePoly(tMani, this.m_shape1, this.m_shape2, false); 103 | 104 | // Match contact ids to facilitate warm starting. 105 | if (tMani.pointCount > 0) { 106 | var match = [false, false]; 107 | 108 | // Match old contact ids to new contact ids and copy the 109 | // stored impulses to warm start the solver. 110 | for (var i = 0; i < tMani.pointCount; ++i) { 111 | var cp = tMani.points[i]; 112 | 113 | cp.normalImpulse = 0.0; 114 | cp.tangentImpulse = 0.0; 115 | var idKey = cp.id.key; 116 | 117 | for (var j = 0; j < this.m0.pointCount; ++j) { 118 | 119 | if (match[j] == true) continue; 120 | 121 | var cp0 = this.m0.points[j]; 122 | var id0 = cp0.id; 123 | 124 | if (id0.key == idKey) { 125 | match[j] = true; 126 | cp.normalImpulse = cp0.normalImpulse; 127 | cp.tangentImpulse = cp0.tangentImpulse; 128 | break; 129 | } 130 | } 131 | } 132 | 133 | this.m_manifoldCount = 1; 134 | } else { 135 | this.m_manifoldCount = 0; 136 | } 137 | }; 138 | 139 | box2d.PolyContact.prototype.GetManifolds = function() { 140 | return this.m_manifold; 141 | }; 142 | 143 | box2d.PolyContact.Create = function(shape1, shape2) { 144 | return new box2d.PolyContact(shape1, shape2); 145 | }; 146 | -------------------------------------------------------------------------------- /src/box2d/dynamics/joints/b2DistanceJointDef.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2007 Erin Catto http: 3 | * 4 | * This software is provided 'as-is', without any express or implied 5 | * warranty. In no event will the authors be held liable for any damages 6 | * arising from the use of this software. 7 | * Permission is granted to anyone to use this software for any purpose, 8 | * including commercial applications, and to alter it and redistribute it 9 | * freely, subject to the following restrictions: 10 | * 1. The origin of this software must not be misrepresented; you must not 11 | * claim that you wrote the original software. If you use this software 12 | * in a product, an acknowledgment in the product documentation would be 13 | * appreciated but is not required. 14 | * 2. Altered source versions must be plainly marked, and must not be 15 | * misrepresented the original software. 16 | * 3. This notice may not be removed or altered from any source distribution. 17 | */ 18 | 19 | goog.provide('box2d.DistanceJointDef'); 20 | 21 | goog.require('box2d.JointDef'); 22 | 23 | 24 | 25 | /** 26 | @constructor 27 | @extends {box2d.JointDef} 28 | */ 29 | box2d.DistanceJointDef = function() { 30 | box2d.JointDef.call(this, false); 31 | 32 | // The constructor for b2JointDef 33 | this.type = box2d.Joint.e_unknownJoint; 34 | this.userData = null; 35 | this.body1 = null; 36 | this.body2 = null; 37 | // 38 | // initialize instance variables for references 39 | this.anchorPoint1 = new box2d.Vec2(); 40 | this.anchorPoint2 = new box2d.Vec2(); 41 | // 42 | this.type = box2d.Joint.e_distanceJoint; 43 | //this.anchorPoint1.Set(0.0, 0.0); 44 | //this.anchorPoint2.Set(0.0, 0.0); 45 | }; 46 | goog.inherits(box2d.DistanceJointDef, box2d.JointDef); 47 | -------------------------------------------------------------------------------- /src/box2d/dynamics/joints/b2GearJointDef.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2007 Erin Catto http: 3 | * 4 | * This software is provided 'as-is', without any express or implied 5 | * warranty. In no event will the authors be held liable for any damages 6 | * arising from the use of this software. 7 | * Permission is granted to anyone to use this software for any purpose, 8 | * including commercial applications, and to alter it and redistribute it 9 | * freely, subject to the following restrictions: 10 | * 1. The origin of this software must not be misrepresented; you must not 11 | * claim that you wrote the original software. If you use this software 12 | * in a product, an acknowledgment in the product documentation would be 13 | * appreciated but is not required. 14 | * 2. Altered source versions must be plainly marked, and must not be 15 | * misrepresented the original software. 16 | * 3. This notice may not be removed or altered from any source distribution. 17 | */ 18 | 19 | goog.provide('box2d.GearJointDef'); 20 | 21 | goog.require('box2d.JointDef'); 22 | 23 | 24 | 25 | // A gear joint is used to connect two joints together. Either joint 26 | // can be a revolute or prismatic joint. You specify a gear ratio 27 | // to bind the motions together: 28 | // coordinate1 + ratio * coordinate2 = constant 29 | // The ratio can be negative or positive. If one joint is a revolute joint 30 | // and the other joint is a prismatic joint, then the ratio will have units 31 | // of length or units of 1/length. 32 | // 33 | // RESTRICITON: The revolute and prismatic joints must be attached to 34 | // a fixed body (which must be body1 on those joints). 35 | /** 36 | @constructor 37 | @extends {box2d.JointDef} 38 | */ 39 | box2d.GearJointDef = function() { 40 | this.type = box2d.Joint.e_gearJoint; 41 | this.joint1 = null; 42 | this.joint2 = null; 43 | this.ratio = 1.0; 44 | }; 45 | goog.inherits(box2d.GearJointDef, box2d.JointDef); 46 | -------------------------------------------------------------------------------- /src/box2d/dynamics/joints/b2Jacobian.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2007 Erin Catto http: 3 | * 4 | * This software is provided 'as-is', without any express or implied 5 | * warranty. In no event will the authors be held liable for any damages 6 | * arising from the use of this software. 7 | * Permission is granted to anyone to use this software for any purpose, 8 | * including commercial applications, and to alter it and redistribute it 9 | * freely, subject to the following restrictions: 10 | * 1. The origin of this software must not be misrepresented; you must not 11 | * claim that you wrote the original software. If you use this software 12 | * in a product, an acknowledgment in the product documentation would be 13 | * appreciated but is not required. 14 | * 2. Altered source versions must be plainly marked, and must not be 15 | * misrepresented the original software. 16 | * 3. This notice may not be removed or altered from any source distribution. 17 | */ 18 | 19 | goog.provide('box2d.Jacobian'); 20 | 21 | goog.require('box2d.Vec2'); 22 | 23 | 24 | 25 | /** 26 | @constructor 27 | */ 28 | box2d.Jacobian = function() { 29 | // initialize instance variables for references 30 | this.linear1 = new box2d.Vec2(); 31 | this.linear2 = new box2d.Vec2(); 32 | // 33 | }; 34 | 35 | box2d.Jacobian.prototype = { 36 | angular1: null, 37 | angular2: null, 38 | 39 | SetZero: function() { 40 | this.linear1.SetZero(); 41 | this.angular1 = 0.0; 42 | this.linear2.SetZero(); 43 | this.angular2 = 0.0; 44 | }, 45 | Set: function(x1, a1, x2, a2) { 46 | this.linear1.SetV(x1); 47 | this.angular1 = a1; 48 | this.linear2.SetV(x2); 49 | this.angular2 = a2; 50 | }, 51 | Compute: function(x1, a1, x2, a2) { 52 | 53 | //return goog.math.Vec2.dot(this.linear1, x1) + this.angular1 * a1 + goog.math.Vec2.dot(this.linear2, x2) + this.angular2 * a2; 54 | return (this.linear1.x * x1.x + this.linear1.y * x1.y) + this.angular1 * a1 + (this.linear2.x * x2.x + this.linear2.y * x2.y) + this.angular2 * a2; 55 | } 56 | }; 57 | -------------------------------------------------------------------------------- /src/box2d/dynamics/joints/b2Joint.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2007 Erin Catto http: 3 | * 4 | * This software is provided 'as-is', without any express or implied 5 | * warranty. In no event will the authors be held liable for any damages 6 | * arising from the use of this software. 7 | * Permission is granted to anyone to use this software for any purpose, 8 | * including commercial applications, and to alter it and redistribute it 9 | * freely, subject to the following restrictions: 10 | * 1. The origin of this software must not be misrepresented; you must not 11 | * claim that you wrote the original software. If you use this software 12 | * in a product, an acknowledgment in the product documentation would be 13 | * appreciated but is not required. 14 | * 2. Altered source versions must be plainly marked, and must not be 15 | * misrepresented the original software. 16 | * 3. This notice may not be removed or altered from any source distribution. 17 | */ 18 | 19 | goog.provide('box2d.Joint'); 20 | 21 | goog.require('box2d.JointNode'); 22 | 23 | 24 | 25 | /** 26 | @constructor 27 | */ 28 | box2d.Joint = function(def) { 29 | // initialize instance variables for references 30 | /** 31 | @type {!box2d.JointNode} 32 | */ 33 | this.m_node1 = new box2d.JointNode(); 34 | /** 35 | @type {!box2d.JointNode} 36 | */ 37 | this.m_node2 = new box2d.JointNode(); 38 | // 39 | this.m_type = def.type; 40 | this.m_prev = null; 41 | this.m_next = null; 42 | this.m_body1 = def.body1; 43 | this.m_body2 = def.body2; 44 | this.m_collideConnected = def.getCollideConnected(); 45 | this.m_islandFlag = false; 46 | this.m_userData = def.userData; 47 | }; 48 | 49 | box2d.Joint.prototype.GetType = function() { 50 | return this.m_type; 51 | }; 52 | box2d.Joint.prototype.GetAnchor1 = function() { 53 | return null; 54 | }; 55 | box2d.Joint.prototype.GetAnchor2 = function() { 56 | return null; 57 | }; 58 | box2d.Joint.prototype.GetReactionForce = function(invTimeStep) { 59 | return null; 60 | }; 61 | box2d.Joint.prototype.GetReactionTorque = function(invTimeStep) { 62 | return 0.0; 63 | }; 64 | box2d.Joint.prototype.GetBody1 = function() { 65 | return this.m_body1; 66 | }; 67 | box2d.Joint.prototype.GetBody2 = function() { 68 | return this.m_body2; 69 | }; 70 | box2d.Joint.prototype.GetNext = function() { 71 | return this.m_next; 72 | }; 73 | box2d.Joint.prototype.GetUserData = function() { 74 | return this.m_userData; 75 | }; 76 | 77 | //--------------- Internals Below ------------------- 78 | //virtual ~b2Joint() {} 79 | box2d.Joint.prototype.PrepareVelocitySolver = function() {}; 80 | box2d.Joint.SolveVelocityConstraints = function(step) {}; 81 | 82 | // This returns true if the position errors are within tolerance. 83 | box2d.Joint.prototype.PreparePositionSolver = function() {}; 84 | box2d.Joint.prototype.SolvePositionConstraints = function() { 85 | return false; 86 | }; 87 | 88 | 89 | /** 90 | @const 91 | @type {number} 92 | */ 93 | box2d.Joint.e_unknownJoint = 0; 94 | 95 | 96 | /** 97 | @const 98 | @type {number} 99 | */ 100 | box2d.Joint.e_revoluteJoint = 1; 101 | 102 | 103 | /** 104 | @const 105 | @type {number} 106 | */ 107 | box2d.Joint.e_prismaticJoint = 2; 108 | 109 | 110 | /** 111 | @const 112 | @type {number} 113 | */ 114 | box2d.Joint.e_distanceJoint = 3; 115 | 116 | 117 | /** 118 | @const 119 | @type {number} 120 | */ 121 | box2d.Joint.e_pulleyJoint = 4; 122 | 123 | 124 | /** 125 | @const 126 | @type {number} 127 | */ 128 | box2d.Joint.e_mouseJoint = 5; 129 | 130 | 131 | /** 132 | @const 133 | @type {number} 134 | */ 135 | box2d.Joint.e_gearJoint = 6; 136 | 137 | 138 | /** 139 | @const 140 | @type {number} 141 | */ 142 | box2d.Joint.e_inactiveLimit = 0; 143 | 144 | 145 | /** 146 | @const 147 | @type {number} 148 | */ 149 | box2d.Joint.e_atLowerLimit = 1; 150 | 151 | 152 | /** 153 | @const 154 | @type {number} 155 | */ 156 | box2d.Joint.e_atUpperLimit = 2; 157 | 158 | 159 | /** 160 | @const 161 | @type {number} 162 | */ 163 | box2d.Joint.e_equalLimits = 3; 164 | -------------------------------------------------------------------------------- /src/box2d/dynamics/joints/b2JointDef.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2007 Erin Catto http: 3 | * 4 | * This software is provided 'as-is', without any express or implied 5 | * warranty. In no event will the authors be held liable for any damages 6 | * arising from the use of this software. 7 | * Permission is granted to anyone to use this software for any purpose, 8 | * including commercial applications, and to alter it and redistribute it 9 | * freely, subject to the following restrictions: 10 | * 1. The origin of this software must not be misrepresented; you must not 11 | * claim that you wrote the original software. If you use this software 12 | * in a product, an acknowledgment in the product documentation would be 13 | * appreciated but is not required. 14 | * 2. Altered source versions must be plainly marked, and must not be 15 | * misrepresented the original software. 16 | * 3. This notice may not be removed or altered from any source distribution. 17 | */ 18 | 19 | goog.provide('box2d.JointDef'); 20 | 21 | goog.require('box2d.Joint'); 22 | 23 | 24 | 25 | /** 26 | @constructor 27 | @param {boolean} collideConnected 28 | */ 29 | box2d.JointDef = function(collideConnected) { 30 | this.type = box2d.Joint.e_unknownJoint; 31 | this.userData = null; 32 | this.body1 = null; 33 | this.body2 = null; 34 | this.m_collideConnected = collideConnected; 35 | }; 36 | 37 | box2d.JointDef.prototype.getCollideConnected = function() { 38 | return this.m_collideConnected; 39 | }; 40 | -------------------------------------------------------------------------------- /src/box2d/dynamics/joints/b2JointFactory.js: -------------------------------------------------------------------------------- 1 | goog.provide('box2d.JointFactory'); 2 | 3 | goog.require('box2d.DistanceJoint'); 4 | goog.require('box2d.GearJoint'); 5 | goog.require('box2d.MouseJoint'); 6 | goog.require('box2d.PrismaticJoint'); 7 | goog.require('box2d.PulleyJoint'); 8 | goog.require('box2d.RevoluteJoint'); 9 | 10 | box2d.JointFactory.Create = function(def) { 11 | switch (def.type) { 12 | case box2d.Joint.e_distanceJoint: 13 | { 14 | return new box2d.DistanceJoint(def); 15 | } 16 | case box2d.Joint.e_mouseJoint: 17 | { 18 | return new box2d.MouseJoint(def); 19 | } 20 | case box2d.Joint.e_prismaticJoint: 21 | { 22 | return new box2d.PrismaticJoint(def); 23 | } 24 | case box2d.Joint.e_revoluteJoint: 25 | { 26 | return new box2d.RevoluteJoint(def); 27 | } 28 | case box2d.Joint.e_pulleyJoint: 29 | { 30 | return new box2d.PulleyJoint(def); 31 | } 32 | case box2d.Joint.e_gearJoint: 33 | { 34 | return new box2d.GearJoint(def); 35 | } 36 | default: 37 | throw 'def not supported'; 38 | } 39 | }; 40 | -------------------------------------------------------------------------------- /src/box2d/dynamics/joints/b2JointNode.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2007 Erin Catto http: 3 | * 4 | * This software is provided 'as-is', without any express or implied 5 | * warranty. In no event will the authors be held liable for any damages 6 | * arising from the use of this software. 7 | * Permission is granted to anyone to use this software for any purpose, 8 | * including commercial applications, and to alter it and redistribute it 9 | * freely, subject to the following restrictions: 10 | * 1. The origin of this software must not be misrepresented; you must not 11 | * claim that you wrote the original software. If you use this software 12 | * in a product, an acknowledgment in the product documentation would be 13 | * appreciated but is not required. 14 | * 2. Altered source versions must be plainly marked, and must not be 15 | * misrepresented the original software. 16 | * 3. This notice may not be removed or altered from any source distribution. 17 | */ 18 | 19 | goog.provide('box2d.JointNode'); 20 | 21 | 22 | 23 | /** 24 | @constructor 25 | */ 26 | box2d.JointNode = function() { 27 | this.other = null; 28 | this.joint = null; 29 | this.prev = null; 30 | this.next = null; 31 | }; 32 | -------------------------------------------------------------------------------- /src/box2d/dynamics/joints/b2MouseJointDef.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2007 Erin Catto http: 3 | * 4 | * This software is provided 'as-is', without any express or implied 5 | * warranty. In no event will the authors be held liable for any damages 6 | * arising from the use of this software. 7 | * Permission is granted to anyone to use this software for any purpose, 8 | * including commercial applications, and to alter it and redistribute it 9 | * freely, subject to the following restrictions: 10 | * 1. The origin of this software must not be misrepresented; you must not 11 | * claim that you wrote the original software. If you use this software 12 | * in a product, an acknowledgment in the product documentation would be 13 | * appreciated but is not required. 14 | * 2. Altered source versions must be plainly marked, and must not be 15 | * misrepresented the original software. 16 | * 3. This notice may not be removed or altered from any source distribution. 17 | */ 18 | 19 | goog.provide('box2d.MouseJointDef'); 20 | 21 | goog.require('box2d.JointDef'); 22 | 23 | 24 | 25 | /** 26 | @constructor 27 | @extends {box2d.JointDef} 28 | */ 29 | box2d.MouseJointDef = function() { 30 | box2d.JointDef.call(this, false); 31 | 32 | // The constructor for b2JointDef 33 | this.type = box2d.Joint.e_unknownJoint; 34 | this.userData = null; 35 | this.body1 = null; 36 | this.body2 = null; 37 | // 38 | // initialize instance variables for references 39 | this.target = new box2d.Vec2(); 40 | // 41 | this.type = box2d.Joint.e_mouseJoint; 42 | this.maxForce = 0.0; 43 | this.frequencyHz = 5.0; 44 | this.dampingRatio = 0.7; 45 | this.timeStep = 1.0 / 60.0; 46 | }; 47 | goog.inherits(box2d.MouseJointDef, box2d.JointDef); 48 | -------------------------------------------------------------------------------- /src/box2d/dynamics/joints/b2PrismaticJointDef.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2007 Erin Catto http: 3 | * 4 | * This software is provided 'as-is', without any express or implied 5 | * warranty. In no event will the authors be held liable for any damages 6 | * arising from the use of this software. 7 | * Permission is granted to anyone to use this software for any purpose, 8 | * including commercial applications, and to alter it and redistribute it 9 | * freely, subject to the following restrictions: 10 | * 1. The origin of this software must not be misrepresented; you must not 11 | * claim that you wrote the original software. If you use this software 12 | * in a product, an acknowledgment in the product documentation would be 13 | * appreciated but is not required. 14 | * 2. Altered source versions must be plainly marked, and must not be 15 | * misrepresented the original software. 16 | * 3. This notice may not be removed or altered from any source distribution. 17 | */ 18 | 19 | goog.provide('box2d.PrismaticJointDef'); 20 | 21 | goog.require('box2d.JointDef'); 22 | goog.require('box2d.Vec2'); 23 | 24 | 25 | 26 | /** 27 | @constructor 28 | @extends {box2d.JointDef} 29 | */ 30 | box2d.PrismaticJointDef = function() { 31 | box2d.JointDef.call(this, false); 32 | // The constructor for b2JointDef 33 | this.type = box2d.Joint.e_unknownJoint; 34 | this.userData = null; 35 | this.body1 = null; 36 | this.body2 = null; 37 | // 38 | this.type = box2d.Joint.e_prismaticJoint; 39 | this.anchorPoint = new box2d.Vec2(0.0, 0.0); 40 | this.axis = new box2d.Vec2(0.0, 0.0); 41 | this.lowerTranslation = 0.0; 42 | this.upperTranslation = 0.0; 43 | this.motorForce = 0.0; 44 | this.motorSpeed = 0.0; 45 | this.enableLimit = false; 46 | this.enableMotor = false; 47 | }; 48 | goog.inherits(box2d.PrismaticJointDef, box2d.JointDef); 49 | -------------------------------------------------------------------------------- /src/box2d/dynamics/joints/b2PulleyJointDef.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2007 Erin Catto http: 3 | * 4 | * This software is provided 'as-is', without any express or implied 5 | * warranty. In no event will the authors be held liable for any damages 6 | * arising from the use of this software. 7 | * Permission is granted to anyone to use this software for any purpose, 8 | * including commercial applications, and to alter it and redistribute it 9 | * freely, subject to the following restrictions: 10 | * 1. The origin of this software must not be misrepresented; you must not 11 | * claim that you wrote the original software. If you use this software 12 | * in a product, an acknowledgment in the product documentation would be 13 | * appreciated but is not required. 14 | * 2. Altered source versions must be plainly marked, and must not be 15 | * misrepresented the original software. 16 | * 3. This notice may not be removed or altered from any source distribution. 17 | */ 18 | 19 | goog.provide('box2d.PulleyJointDef'); 20 | 21 | goog.require('box2d.JointDef'); 22 | 23 | 24 | 25 | // The pulley joint is connected to two bodies and two fixed ground points. 26 | // The pulley supports a ratio such that: 27 | // length1 + ratio * length2 = constant 28 | // Yes, the force transmitted is scaled by the ratio. 29 | // The pulley also enforces a maximum length limit on both sides. This is 30 | // useful to prevent one side of the pulley hitting the top. 31 | /** 32 | @constructor 33 | @extends {box2d.JointDef} 34 | */ 35 | box2d.PulleyJointDef = function() { 36 | box2d.JointDef.call(this, true); 37 | // The constructor for b2JointDef 38 | this.type = box2d.Joint.e_unknownJoint; 39 | this.userData = null; 40 | this.body1 = null; 41 | this.body2 = null; 42 | // 43 | // initialize instance variables for references 44 | this.groundPoint1 = new box2d.Vec2(); 45 | this.groundPoint2 = new box2d.Vec2(); 46 | this.anchorPoint1 = new box2d.Vec2(); 47 | this.anchorPoint2 = new box2d.Vec2(); 48 | // 49 | this.type = box2d.Joint.e_pulleyJoint; 50 | this.groundPoint1.Set(-1.0, 1.0); 51 | this.groundPoint2.Set(1.0, 1.0); 52 | this.anchorPoint1.Set(-1.0, 0.0); 53 | this.anchorPoint2.Set(1.0, 0.0); 54 | this.maxLength1 = 0.5 * box2d.PulleyJoint.b2_minPulleyLength; 55 | this.maxLength2 = 0.5 * box2d.PulleyJoint.b2_minPulleyLength; 56 | this.ratio = 1.0; 57 | }; 58 | goog.inherits(box2d.PulleyJointDef, box2d.JointDef); 59 | -------------------------------------------------------------------------------- /src/box2d/dynamics/joints/b2RevoluteJointDef.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2007 Erin Catto http: 3 | * 4 | * This software is provided 'as-is', without any express or implied 5 | * warranty. In no event will the authors be held liable for any damages 6 | * arising from the use of this software. 7 | * Permission is granted to anyone to use this software for any purpose, 8 | * including commercial applications, and to alter it and redistribute it 9 | * freely, subject to the following restrictions: 10 | * 1. The origin of this software must not be misrepresented; you must not 11 | * claim that you wrote the original software. If you use this software 12 | * in a product, an acknowledgment in the product documentation would be 13 | * appreciated but is not required. 14 | * 2. Altered source versions must be plainly marked, and must not be 15 | * misrepresented the original software. 16 | * 3. This notice may not be removed or altered from any source distribution. 17 | */ 18 | 19 | goog.provide('box2d.RevoluteJointDef'); 20 | 21 | goog.require('box2d.Joint'); 22 | goog.require('box2d.JointDef'); 23 | goog.require('box2d.Vec2'); 24 | 25 | 26 | 27 | /** 28 | @constructor 29 | @extends {box2d.JointDef} 30 | */ 31 | box2d.RevoluteJointDef = function() { 32 | box2d.JointDef.call(this, false); 33 | 34 | // The constructor for b2JointDef 35 | this.type = box2d.Joint.e_unknownJoint; 36 | this.userData = null; 37 | this.body1 = null; 38 | this.body2 = null; 39 | // 40 | this.type = box2d.Joint.e_revoluteJoint; 41 | this.anchorPoint = new box2d.Vec2(0.0, 0.0); 42 | this.lowerAngle = 0.0; 43 | this.upperAngle = 0.0; 44 | this.motorTorque = 0.0; 45 | this.motorSpeed = 0.0; 46 | this.enableLimit = false; 47 | this.enableMotor = false; 48 | }; 49 | goog.inherits(box2d.RevoluteJointDef, box2d.JointDef); 50 | -------------------------------------------------------------------------------- /src/data/model.js: -------------------------------------------------------------------------------- 1 | goog.provide('pl.data.Model'); 2 | 3 | goog.require('goog.events.EventTarget'); 4 | 5 | 6 | 7 | /** 8 | * @constructor 9 | * @extends {goog.events.EventTarget} 10 | */ 11 | pl.data.Model = function() { 12 | 13 | }; 14 | goog.inherits(pl.data.Model, goog.events.EventTarget); 15 | 16 | goog.scope(function() { 17 | var c = pl.data.Model; 18 | 19 | goog.scope(function() { 20 | var p = c.prototype; 21 | 22 | }); // goog.scope 23 | }); // goog.scope 24 | -------------------------------------------------------------------------------- /src/debugDiv.js: -------------------------------------------------------------------------------- 1 | goog.provide('pl.DebugDiv'); 2 | 3 | goog.require('goog.asserts'); 4 | goog.require('goog.debug.LogManager'); 5 | goog.require('goog.dom'); 6 | goog.require('goog.style'); 7 | 8 | // call this function from a script within the document for which to enable debug output 9 | pl.DebugDiv.enable = function() { 10 | if (!pl.DebugDiv.s_debugDiv) { 11 | var div = pl.DebugDiv.s_debugDiv = goog.dom.createDom('div', { 12 | 'id': pl.DebugDiv.c_divId, 13 | 'style': 'display:block; position:absolute; top:7px; right:7px; padding:10px; width:300px; background: rgba(0,0,0,.4); color:yellowgreen; text-align:left; font-family:monospace; border:solid 1px black; z-index:9999;' 14 | }); 15 | 16 | document.body.appendChild(div); 17 | 18 | goog.debug.LogManager.getRoot().addHandler(pl.DebugDiv._onLog); 19 | } 20 | goog.asserts.assert(document.getElementById(pl.DebugDiv.c_divId)); 21 | }; 22 | 23 | pl.DebugDiv.disable = function() { 24 | if (pl.DebugDiv.s_debugDiv) { 25 | goog.dom.removeNode(pl.DebugDiv.s_debugDiv); 26 | pl.DebugDiv.s_debugDiv = null; 27 | goog.debug.LogManager.getRoot().removeHandler(pl.DebugDiv._onLog); 28 | } 29 | goog.asserts.assert(!document.getElementById(pl.DebugDiv.c_divId)); 30 | }; 31 | 32 | 33 | /** 34 | @return {boolean} true if on, false otherwise. 35 | */ 36 | pl.DebugDiv.toggle = function() { 37 | if (pl.DebugDiv.s_debugDiv) { 38 | pl.DebugDiv.disable(); 39 | return false; 40 | } 41 | else { 42 | pl.DebugDiv.enable(); 43 | return true; 44 | } 45 | }; 46 | 47 | // clears the debug output. called either manually or by the user clicking the 'clear' link in the debug div. 48 | pl.DebugDiv.clear = function() { 49 | if (pl.DebugDiv.s_debugDiv) { 50 | goog.dom.removeChildren(pl.DebugDiv.s_debugDiv); 51 | goog.style.setStyle(pl.DebugDiv.s_debugDiv, 'display', 'none'); 52 | } 53 | }; 54 | 55 | 56 | /** 57 | * Log a LogRecord. 58 | * @param {goog.debug.LogRecord} logRecord A log record to log. 59 | * @private 60 | */ 61 | pl.DebugDiv._onLog = function(logRecord) { 62 | if (pl.DebugDiv.s_debugDiv) { 63 | goog.style.setStyle(pl.DebugDiv.s_debugDiv, 'display', 'block'); 64 | var c = goog.dom.createDom('div', null, goog.string.htmlEscape(logRecord.getMessage())); 65 | goog.dom.appendChild(pl.DebugDiv.s_debugDiv, c); 66 | } 67 | }; 68 | 69 | 70 | /** 71 | @const 72 | @private 73 | @type {string} 74 | */ 75 | pl.DebugDiv.c_divId = '_debugLogDiv'; 76 | -------------------------------------------------------------------------------- /src/fpsLogger.js: -------------------------------------------------------------------------------- 1 | goog.provide('pl.FpsLogger'); 2 | 3 | 4 | 5 | /** 6 | @constructor 7 | */ 8 | pl.FpsLogger = function() { 9 | /** 10 | @private 11 | @type {number} 12 | */ 13 | this._lastTick = 0; 14 | 15 | /** 16 | @private 17 | @type {number} 18 | */ 19 | this._index = 0; 20 | this._values = []; 21 | /** 22 | @private 23 | @type {number} 24 | */ 25 | this._sum = 0; 26 | 27 | /** 28 | @type {number} 29 | */ 30 | this.fps = NaN; 31 | }; 32 | 33 | 34 | /** 35 | @return {number} 36 | **/ 37 | pl.FpsLogger.prototype.AddInterval = function() { 38 | var currentTick = goog.now(); 39 | if (this._lastTick > 0) { 40 | var secondsPerFrame = currentTick - this._lastTick; 41 | secondsPerFrame /= 1000; 42 | if (this._values.length < pl.FpsLogger.s_size) { 43 | this._values.push(secondsPerFrame); 44 | } else { 45 | this._index = (this._index + 1) % this._values.length; 46 | this._sum -= this._values[this._index]; 47 | this._values[this._index] = secondsPerFrame; 48 | } 49 | this._sum += secondsPerFrame; 50 | this.fps = this._values.length / this._sum; 51 | } 52 | this._lastTick = currentTick; 53 | 54 | return this.fps; 55 | }; 56 | 57 | 58 | /** 59 | @const 60 | @type {number} 61 | */ 62 | pl.FpsLogger.s_size = 100; 63 | -------------------------------------------------------------------------------- /src/graph.js: -------------------------------------------------------------------------------- 1 | goog.provide('pl.Graph'); 2 | 3 | goog.require('goog.array'); 4 | goog.require('goog.math'); 5 | goog.require('goog.structs.Map'); 6 | goog.require('goog.structs.Set'); 7 | goog.require('pl.ex'); 8 | 9 | 10 | 11 | /** 12 | * @constructor 13 | */ 14 | pl.Graph = function() { 15 | /** 16 | * @private 17 | */ 18 | this._set = new goog.structs.Set(); 19 | 20 | /** 21 | * @private 22 | */ 23 | this._adjacents = new goog.structs.Map(); 24 | }; 25 | 26 | 27 | /** 28 | * @param {!Object} node 29 | * @param {Array.=} opt_adjacents 30 | */ 31 | pl.Graph.prototype.addNode = function(node, opt_adjacents) { 32 | goog.asserts.assert(goog.isObject(node)); 33 | goog.asserts.assert(!opt_adjacents || !goog.array.contains(opt_adjacents, node)); 34 | this._set.add(node); 35 | 36 | if (opt_adjacents) { 37 | goog.array.forEach(opt_adjacents, function(adjNode) { 38 | goog.asserts.assert(goog.isObject(adjNode)); 39 | this._set.add(adjNode); 40 | 41 | this._ensureEdgeCore(node, adjNode); 42 | this._ensureEdgeCore(adjNode, node); 43 | }, 44 | this); 45 | } 46 | }; 47 | 48 | 49 | /** 50 | * @param {!Object} node 51 | * @return {boolean} 52 | */ 53 | pl.Graph.prototype.containsNode = function(node) { 54 | return this._set.contains(node); 55 | }; 56 | 57 | 58 | /** 59 | * @param {!Object} node1 60 | * @param {!Object} node2 61 | * @return {boolean} 62 | */ 63 | pl.Graph.prototype.containsEdge = function(node1, node2) { 64 | goog.asserts.assert(this.containsNode(node1)); 65 | goog.asserts.assert(this.containsNode(node2)); 66 | 67 | var set = this._adjacents.get(goog.getUid(node1)); 68 | 69 | return set && set.contains(node2); 70 | }; 71 | 72 | 73 | /** 74 | * @param {!Object} node 75 | * @return {!goog.iter.Iterable} 76 | */ 77 | pl.Graph.prototype.getAdjacents = function(node) { 78 | goog.asserts.assert(this.containsNode(node)); 79 | var set = this._adjacents.get(goog.getUid(node)); 80 | if (set) { 81 | return set.__iterator__(); 82 | } else { 83 | return []; 84 | } 85 | }; 86 | 87 | 88 | /** 89 | * @return {!goog.iter.Iterable} 90 | */ 91 | pl.Graph.prototype.getNodes = function() { 92 | return this._set.__iterator__(); 93 | }; 94 | 95 | 96 | /** 97 | * @return {number} 98 | */ 99 | pl.Graph.prototype.getNodeCount = function() { 100 | return this._set.getCount(); 101 | }; 102 | 103 | 104 | /** 105 | * @return {!goog.iter.Iterator} each element is an array with 2 nodes 106 | no pairs are repeated 107 | the elements are order by Uid -> smallest first. 108 | */ 109 | pl.Graph.prototype.getPairs = function() { 110 | var _this = this; 111 | return pl.ex.selectMany(this._set.__iterator__(), function(node1) { 112 | return goog.iter.filter(_this._set.__iterator__(), function(node2) { 113 | var id1 = goog.getUid(/** @type {!Object} */ (node1)); 114 | var id2 = goog.getUid(/** @type {!Object} */ (node2)); 115 | return id1 < id2; 116 | }); 117 | }); 118 | }; 119 | 120 | 121 | /** 122 | * @return {!goog.iter.Iterator} each element is an array with 2 nodes 123 | no pairs are repeated 124 | the elements are order by Uid -> smallest first. 125 | */ 126 | pl.Graph.prototype.getEdges = function() { 127 | var _this = this; 128 | return pl.ex.selectMany(this._set.__iterator__(), function(node1) { 129 | return goog.iter.filter(_this.getAdjacents(/** @type {!Object} */ (node1)), 130 | function(node2) { 131 | var id1 = goog.getUid(/** @type {!Object} */ (node1)); 132 | var id2 = goog.getUid(/** @type {!Object} */ (node2)); 133 | return id1 < id2; 134 | }); 135 | }); 136 | }; 137 | 138 | 139 | /** 140 | * @return {number} 141 | */ 142 | pl.Graph.prototype.getEdgeCount = function() { 143 | return pl.ex.count(this.getEdges()); 144 | }; 145 | 146 | // TODO: implement remove 147 | // ...and make sure attached properties are removed! 148 | 149 | 150 | /** 151 | * @private 152 | * @param {!Object} fromNode 153 | * @param {!Object} toNode 154 | */ 155 | pl.Graph.prototype._ensureEdgeCore = function(fromNode, toNode) { 156 | var adjSet = this._adjacents.get(goog.getUid(fromNode)); 157 | if (!adjSet) { 158 | this._adjacents.set(goog.getUid(fromNode), adjSet = new goog.structs.Set()); 159 | } 160 | adjSet.add(toNode); 161 | }; 162 | -------------------------------------------------------------------------------- /src/graphPoint.js: -------------------------------------------------------------------------------- 1 | goog.provide('pl.GraphPoint'); 2 | 3 | goog.require('goog.math.Vec2'); 4 | goog.require('pl.Graph'); 5 | goog.require('pl.ex'); 6 | 7 | 8 | 9 | /** 10 | * @constructor 11 | * @param {!Object} node 12 | * @param {number} width 13 | * @param {number} height 14 | */ 15 | pl.GraphPoint = function(node, width, height) { 16 | this.node = node; 17 | this.position = new goog.math.Coordinate(Math.random() * width, Math.random() * height); 18 | this.velocity = new goog.math.Vec2(0, 0); 19 | this.force = new goog.math.Vec2(0, 0); 20 | this._version = undefined; 21 | }; 22 | 23 | 24 | /** 25 | * @param {number} version 26 | */ 27 | pl.GraphPoint.prototype.ensureVersion = function(version) { 28 | if (this._version != version) { 29 | pl.ex.clearVec(this.force); 30 | this._version = version; 31 | } 32 | }; 33 | -------------------------------------------------------------------------------- /src/images.js: -------------------------------------------------------------------------------- 1 | goog.provide('pl.images'); 2 | 3 | goog.require('goog.asserts'); 4 | goog.require('goog.net.EventType'); 5 | goog.require('goog.net.ImageLoader'); 6 | goog.require('goog.object'); 7 | 8 | 9 | 10 | /** 11 | * @constructor 12 | * @param {Object.} source 13 | */ 14 | pl.images = function(source) { 15 | this._source = source; 16 | 17 | /** 18 | * @private 19 | * @type {Object.} 20 | */ 21 | this._images = {}; 22 | }; 23 | 24 | pl.images.prototype.load = function(progress, complete) { 25 | var loader = new goog.net.ImageLoader(); 26 | 27 | goog.object.forEach(this._source, function(e,i,o) { 28 | loader.addImage(i, e); 29 | }); 30 | 31 | var ratio = 0; 32 | 33 | loader.addEventListener(goog.events.EventType.LOAD, function(e) { 34 | var key = e.target.id; 35 | var image = e.target; 36 | goog.asserts.assert(key in this._source); 37 | goog.asserts.assert(!(key in this._images)); 38 | this._images[e.target.id] = e.target; 39 | 40 | ratio = goog.object.getCount(this._images) / goog.object.getCount(this._source); 41 | progress(ratio); 42 | 43 | }, false, this); 44 | 45 | loader.addEventListener(goog.net.EventType.COMPLETE, function(e) { 46 | complete(); 47 | }, false, this); 48 | 49 | loader.start(); 50 | }; 51 | 52 | 53 | /** 54 | * @param {!string} key 55 | * @param {!string} path 56 | **/ 57 | pl.images.prototype.add = function(key, path) { 58 | goog.asserts.assert(!goog.object.containsKey(this._source, key)); 59 | goog.object.set(this._source, key, path); 60 | }; 61 | 62 | 63 | /** 64 | * @param {string} key 65 | * @return {!HTMLImageElement} 66 | */ 67 | pl.images.prototype.get = function(key) { 68 | if (key in this._images) { 69 | return this._images[key]; 70 | } else { 71 | throw Error('not found'); 72 | } 73 | }; 74 | -------------------------------------------------------------------------------- /src/keyBinding.js: -------------------------------------------------------------------------------- 1 | goog.provide('pl.KeyBinding'); 2 | goog.provide('pl.KeyBindingEvent'); 3 | 4 | goog.require('goog.events.Event'); 5 | goog.require('goog.events.EventTarget'); 6 | goog.require('goog.ui.KeyboardShortcutHandler'); 7 | goog.require('goog.ui.KeyboardShortcutHandler.EventType'); 8 | 9 | 10 | 11 | /** 12 | @constructor 13 | @extends {goog.events.EventTarget} 14 | @param {boolean=} opt_skipStyles 15 | */ 16 | pl.KeyBinding = function(opt_skipStyles) { 17 | goog.base(this); 18 | this.m_shortcutHandler = new goog.ui.KeyboardShortcutHandler(document); 19 | this.m_map = []; 20 | 21 | this.m_useStyles = !opt_skipStyles; 22 | 23 | goog.events.listen( 24 | this.m_shortcutHandler, 25 | goog.ui.KeyboardShortcutHandler.EventType.SHORTCUT_TRIGGERED, 26 | goog.bind(this._handleKey, this)); 27 | }; 28 | goog.inherits(pl.KeyBinding, goog.events.EventTarget); 29 | 30 | 31 | /** 32 | @param {!string} keybinding 33 | @param {!string} description 34 | @param {function():(string|undefined)} action 35 | */ 36 | pl.KeyBinding.prototype.add = function(keybinding, description, action) { 37 | var indexStr = this.m_map.length.toString(); 38 | this.m_shortcutHandler.registerShortcut(indexStr, keybinding); 39 | this.m_map.push({ 40 | 'keybinding': keybinding, 41 | 'description': description, 42 | 'action': action 43 | }); 44 | }; 45 | 46 | pl.KeyBinding.prototype.getMap = function() { 47 | return this.m_map; 48 | }; 49 | 50 | /* 51 | @privae 52 | @param {!goog.ui.KeyboardShortcutEvent} event 53 | */ 54 | pl.KeyBinding.prototype._handleKey = function(event) { 55 | var number = new Number(event.identifier); 56 | var entry = this.m_map[number]; 57 | var result = entry['action'].call(); 58 | event.stopPropagation(); 59 | var description = result || entry['description']; 60 | this.dispatchEvent(new pl.KeyBindingEvent(entry['keybinding'], description)); 61 | }; 62 | 63 | /* 64 | @const 65 | @type {!string} 66 | */ 67 | pl.KeyBinding.TYPE = 'KeyBindingEvent'; 68 | 69 | 70 | 71 | /** 72 | @constructor 73 | @extends {goog.events.Event} 74 | */ 75 | pl.KeyBindingEvent = function(keybinding, description) { 76 | goog.events.Event.call(this, pl.KeyBinding.TYPE); 77 | this.keybinding = keybinding; 78 | this.description = description; 79 | }; 80 | goog.inherits(pl.KeyBindingEvent, goog.events.Event); 81 | -------------------------------------------------------------------------------- /src/property.js: -------------------------------------------------------------------------------- 1 | goog.provide('pl.Property'); 2 | 3 | goog.require('goog.array'); 4 | goog.require('goog.math.Coordinate'); 5 | goog.require('goog.math.Size'); 6 | 7 | 8 | 9 | /** 10 | * @constructor 11 | * @param {!string} name 12 | * @param {*=} opt_defaultValue 13 | */ 14 | pl.Property = function(name, opt_defaultValue) { 15 | this._name = name; 16 | this._defaultValue = opt_defaultValue; 17 | this._id = pl.Property._propertyId++; 18 | }; 19 | 20 | 21 | /** 22 | * @param {!Object} object 23 | */ 24 | pl.Property.prototype.clear = function(object) { 25 | if (object[pl.Property._PROP_ID_PROPERTY]) { 26 | var hash = object[pl.Property._PROP_ID_PROPERTY]; 27 | delete hash[this._id]; 28 | this._notify(object); 29 | } 30 | }; 31 | 32 | 33 | /** 34 | * @param {!Object} object 35 | */ 36 | pl.Property.prototype.get = function(object) { 37 | var coreVal = this.getCore(object); 38 | if (coreVal) { 39 | return coreVal[0]; 40 | } 41 | else { 42 | return this._defaultValue; 43 | } 44 | }; 45 | 46 | 47 | /** 48 | * @param {!Object} object 49 | */ 50 | pl.Property.prototype.set = function(object, value) { 51 | var hash = object[pl.Property._PROP_ID_PROPERTY] || (object[pl.Property._PROP_ID_PROPERTY] = {}); 52 | hash[this._id] = value; 53 | this._notify(object); 54 | }; 55 | 56 | 57 | /** 58 | * @param {!Object} object 59 | * @return {boolean} 60 | */ 61 | pl.Property.prototype.isSet = function(object) { 62 | return object[pl.Property._PROP_ID_PROPERTY] && this._id in object[pl.Property._PROP_ID_PROPERTY]; 63 | }; 64 | 65 | pl.Property.prototype._notify = function(object) { 66 | var listener = pl.Property._callbackProperty.get(object); 67 | if (listener) { 68 | listener(this); 69 | } 70 | }; 71 | 72 | 73 | /** 74 | * @param {!Object} object 75 | * @return {Array|undefined} 76 | */ 77 | pl.Property.prototype.getCore = function(object) { 78 | if (object[pl.Property._PROP_ID_PROPERTY]) { 79 | var hash = object[pl.Property._PROP_ID_PROPERTY]; 80 | if (this._id in hash) { 81 | return [hash[this._id]]; 82 | } 83 | else { 84 | return null; 85 | } 86 | } 87 | }; 88 | 89 | 90 | /** 91 | * @param {!Object} object 92 | * @param {!Function} listener. 93 | */ 94 | pl.Property.watchChanges = function(object, listener) { 95 | if (pl.Property._callbackProperty.get(object)) { 96 | throw Error('already set'); 97 | } 98 | pl.Property._callbackProperty.set(object, listener); 99 | }; 100 | 101 | 102 | /** 103 | * @type {string} 104 | * @private 105 | */ 106 | pl.Property._PROP_ID_PROPERTY = 'prop_uid_' + 107 | Math.floor(Math.random() * 2147483648).toString(36); 108 | 109 | 110 | /** 111 | * @type {number} 112 | * @private 113 | */ 114 | pl.Property._propertyId = 0; 115 | 116 | pl.Property._callbackProperty = new pl.Property('Callback'); 117 | -------------------------------------------------------------------------------- /src/qr/qr8BitByte.js: -------------------------------------------------------------------------------- 1 | goog.provide('qr.EightBitByte'); 2 | 3 | 4 | 5 | /** 6 | * @constructor 7 | * @param {string} data 8 | */ 9 | qr.EightBitByte = function(data) { 10 | this.mode = qr.Mode.MODE_8BIT_BYTE; 11 | this.data = data; 12 | }; 13 | 14 | qr.EightBitByte.prototype = { 15 | 16 | getLength: function(buffer) { 17 | return this.data.length; 18 | }, 19 | 20 | write: function(buffer) { 21 | for (var i = 0; i < this.data.length; i++) { 22 | // not JIS ... 23 | buffer.put(this.data.charCodeAt(i), 8); 24 | } 25 | } 26 | }; 27 | -------------------------------------------------------------------------------- /src/qr/qrBitBuffer.js: -------------------------------------------------------------------------------- 1 | goog.provide('qr.BitBuffer'); 2 | 3 | 4 | 5 | /** 6 | @constructor 7 | */ 8 | qr.BitBuffer = function() { 9 | this.buffer = { 10 | length: 0 11 | }; 12 | this.length = 0; 13 | }; 14 | 15 | qr.BitBuffer.prototype = { 16 | 17 | get: function(index) { 18 | var bufIndex = Math.floor(index / 8); 19 | return ((this.buffer[bufIndex] >>> (7 - index % 8)) & 1) == 1; 20 | }, 21 | 22 | /** 23 | * @param {number} num 24 | * @param {number} length 25 | */ 26 | put: function(num, length) { 27 | for (var i = 0; i < length; i++) { 28 | this.putBit(((num >>> (length - i - 1)) & 1) == 1); 29 | } 30 | }, 31 | 32 | getLengthInBits: function() { 33 | return this.length; 34 | }, 35 | 36 | putBit: function(bit) { 37 | 38 | var bufIndex = Math.floor(this.length / 8); 39 | if (this.buffer.length <= bufIndex) { 40 | this.buffer[this.buffer.length++] = 0; 41 | } 42 | 43 | if (bit) { 44 | this.buffer[bufIndex] |= (0x80 >>> (this.length % 8)); 45 | } 46 | 47 | this.length++; 48 | } 49 | }; 50 | -------------------------------------------------------------------------------- /src/qr/qrEnums.js: -------------------------------------------------------------------------------- 1 | goog.provide('qr.ErrorCorrectLevel'); 2 | goog.provide('qr.MaskPattern'); 3 | goog.provide('qr.Mode'); 4 | 5 | 6 | /** 7 | * @enum {number} 8 | */ 9 | qr.Mode = { 10 | MODE_NUMBER: 1 << 0, 11 | MODE_ALPHA_NUM: 1 << 1, 12 | MODE_8BIT_BYTE: 1 << 2, 13 | MODE_KANJI: 1 << 3 14 | }; 15 | 16 | 17 | /** 18 | * @enum {number} 19 | */ 20 | qr.ErrorCorrectLevel = { 21 | L: 1, 22 | M: 0, 23 | Q: 3, 24 | H: 2 25 | }; 26 | 27 | 28 | /** 29 | * @enum {number} 30 | */ 31 | qr.MaskPattern = { 32 | PATTERN000: 0, 33 | PATTERN001: 1, 34 | PATTERN010: 2, 35 | PATTERN011: 3, 36 | PATTERN100: 4, 37 | PATTERN101: 5, 38 | PATTERN110: 6, 39 | PATTERN111: 7 40 | }; 41 | -------------------------------------------------------------------------------- /src/qr/qrMath.js: -------------------------------------------------------------------------------- 1 | goog.provide('qr.Math'); 2 | 3 | qr.Math = { 4 | 5 | glog: function(n) { 6 | 7 | if (n < 1) { 8 | throw new Error('glog(' + n + ')'); 9 | } 10 | 11 | return qr.Math.LOG_TABLE[n]; 12 | }, 13 | 14 | gexp: function(n) { 15 | 16 | while (n < 0) { 17 | n += 255; 18 | } 19 | 20 | while (n >= 256) { 21 | n -= 255; 22 | } 23 | 24 | return qr.Math.EXP_TABLE[n]; 25 | }, 26 | 27 | EXP_TABLE: { 28 | length: 256 29 | }, 30 | 31 | LOG_TABLE: { 32 | length: 256 33 | } 34 | 35 | }; 36 | 37 | (function() { 38 | var i; 39 | for (i = 0; i < 8; i++) { 40 | qr.Math.EXP_TABLE[i] = 1 << i; 41 | } 42 | for (i = 8; i < 256; i++) { 43 | qr.Math.EXP_TABLE[i] = qr.Math.EXP_TABLE[i - 4] ^ qr.Math.EXP_TABLE[i - 5] ^ qr.Math.EXP_TABLE[i - 6] ^ qr.Math.EXP_TABLE[i - 8]; 44 | } 45 | for (i = 0; i < 255; i++) { 46 | qr.Math.LOG_TABLE[qr.Math.EXP_TABLE[i]] = i; 47 | } 48 | })(); 49 | -------------------------------------------------------------------------------- /src/qr/qrPolynomial.js: -------------------------------------------------------------------------------- 1 | goog.provide('qr.Polynomial'); 2 | 3 | 4 | 5 | /** 6 | @constructor 7 | */ 8 | qr.Polynomial = function(num, shift) { 9 | 10 | if (num.length == undefined) { 11 | throw new Error(num.length + '/' + shift); 12 | } 13 | 14 | var offset = 0; 15 | 16 | while (offset < num.length && num[offset] == 0) { 17 | offset++; 18 | } 19 | 20 | this.num = { 21 | length: num.length - offset + shift 22 | }; 23 | for (var i = 0; i < num.length - offset; i++) { 24 | this.num[i] = num[i + offset]; 25 | } 26 | }; 27 | 28 | qr.Polynomial.prototype = { 29 | 30 | get: function(index) { 31 | return this.num[index]; 32 | }, 33 | 34 | getLength: function() { 35 | return this.num.length; 36 | }, 37 | 38 | multiply: function(e) { 39 | 40 | var num = { 41 | length: this.getLength() + e.getLength() - 1 42 | }; 43 | 44 | for (var i = 0; i < this.getLength(); i++) { 45 | for (var j = 0; j < e.getLength(); j++) { 46 | num[i + j] ^= qr.Math.gexp(qr.Math.glog(this.get(i)) + qr.Math.glog(e.get(j))); 47 | } 48 | } 49 | 50 | return new qr.Polynomial(num, 0); 51 | }, 52 | 53 | mod: function(e) { 54 | 55 | if (this.getLength() - e.getLength() < 0) { 56 | return this; 57 | } 58 | 59 | var ratio = qr.Math.glog(this.get(0)) - qr.Math.glog(e.get(0)); 60 | 61 | var num = { 62 | length: this.getLength() 63 | }; 64 | 65 | var i; 66 | for (i = 0; i < this.getLength(); i++) { 67 | num[i] = this.get(i); 68 | } 69 | 70 | for (i = 0; i < e.getLength(); i++) { 71 | num[i] ^= qr.Math.gexp(qr.Math.glog(e.get(i)) + ratio); 72 | } 73 | 74 | // recursive call 75 | return new qr.Polynomial(num, 0).mod(e); 76 | } 77 | }; 78 | -------------------------------------------------------------------------------- /src/qr/qrRSBlock.js: -------------------------------------------------------------------------------- 1 | goog.provide('qr.RSBlock'); 2 | 3 | 4 | 5 | /** 6 | @constructor 7 | */ 8 | qr.RSBlock = function(totalCount, dataCount) { 9 | this.totalCount = totalCount; 10 | this.dataCount = dataCount; 11 | }; 12 | 13 | qr.RSBlock.RS_BLOCK_TABLE = [ 14 | 15 | // L 16 | // M 17 | // Q 18 | // H 19 | // 1 20 | [1, 26, 19], 21 | [1, 26, 16], 22 | [1, 26, 13], 23 | [1, 26, 9], 24 | 25 | // 2 26 | [1, 44, 34], 27 | [1, 44, 28], 28 | [1, 44, 22], 29 | [1, 44, 16], 30 | 31 | // 3 32 | [1, 70, 55], 33 | [1, 70, 44], 34 | [2, 35, 17], 35 | [2, 35, 13], 36 | 37 | // 4 38 | [1, 100, 80], 39 | [2, 50, 32], 40 | [2, 50, 24], 41 | [4, 25, 9], 42 | 43 | // 5 44 | [1, 134, 108], 45 | [2, 67, 43], 46 | [2, 33, 15, 2, 34, 16], 47 | [2, 33, 11, 2, 34, 12], 48 | 49 | // 6 50 | [2, 86, 68], 51 | [4, 43, 27], 52 | [4, 43, 19], 53 | [4, 43, 15], 54 | 55 | // 7 56 | [2, 98, 78], 57 | [4, 49, 31], 58 | [2, 32, 14, 4, 33, 15], 59 | [4, 39, 13, 1, 40, 14], 60 | 61 | // 8 62 | [2, 121, 97], 63 | [2, 60, 38, 2, 61, 39], 64 | [4, 40, 18, 2, 41, 19], 65 | [4, 40, 14, 2, 41, 15], 66 | 67 | // 9 68 | [2, 146, 116], 69 | [3, 58, 36, 2, 59, 37], 70 | [4, 36, 16, 4, 37, 17], 71 | [4, 36, 12, 4, 37, 13], 72 | 73 | // 10 74 | [2, 86, 68, 2, 87, 69], 75 | [4, 69, 43, 1, 70, 44], 76 | [6, 43, 19, 2, 44, 20], 77 | [6, 43, 15, 2, 44, 16] 78 | 79 | ]; 80 | 81 | qr.RSBlock.getRSBlocks = function(typeNumber, errorCorrectLevel) { 82 | 83 | var rsBlock = qr.RSBlock.getRsBlockTable(typeNumber, errorCorrectLevel); 84 | 85 | if (rsBlock == undefined) { 86 | throw new Error('bad rs block @ typeNumber:' + typeNumber + '/errorCorrectLevel:' + errorCorrectLevel); 87 | } 88 | 89 | var length = rsBlock.length / 3; 90 | 91 | var list = { 92 | length: 0 93 | }; 94 | 95 | for (var i = 0; i < length; i++) { 96 | 97 | var count = rsBlock[i * 3 + 0]; 98 | var totalCount = rsBlock[i * 3 + 1]; 99 | var dataCount = rsBlock[i * 3 + 2]; 100 | 101 | for (var j = 0; j < count; j++) { 102 | list[list.length++] = new qr.RSBlock(totalCount, dataCount); 103 | } 104 | } 105 | 106 | return list; 107 | }; 108 | 109 | qr.RSBlock.getRsBlockTable = function(typeNumber, errorCorrectLevel) { 110 | 111 | switch (errorCorrectLevel) { 112 | case qr.ErrorCorrectLevel.L: 113 | return qr.RSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 0]; 114 | case qr.ErrorCorrectLevel.M: 115 | return qr.RSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 1]; 116 | case qr.ErrorCorrectLevel.Q: 117 | return qr.RSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 2]; 118 | case qr.ErrorCorrectLevel.H: 119 | return qr.RSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 3]; 120 | default: 121 | return undefined; 122 | } 123 | }; 124 | -------------------------------------------------------------------------------- /src/qr/readme.md: -------------------------------------------------------------------------------- 1 | # Original License # 2 | 3 | QRCode for ActionScript 4 | version 1.0.1 5 | Copyright (C) Kazuhiko Arase all rights reserved. 6 | 7 | # The MIT License # 8 | 9 | Copyright (c) 2010-2011 Pixel Lab 10 | 11 | Permission is hereby granted, free of charge, to any person obtaining a copy 12 | of this software and associated documentation files (the "Software"), to deal 13 | in the Software without restriction, including without limitation the rights 14 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | copies of the Software, and to permit persons to whom the Software is 16 | furnished to do so, subject to the following conditions: 17 | 18 | The above copyright notice and this permission notice shall be included in 19 | all copies or substantial portions of the Software. 20 | 21 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 27 | THE SOFTWARE. -------------------------------------------------------------------------------- /src/retained/_navLayerTxPanel.js: -------------------------------------------------------------------------------- 1 | goog.provide('pl.retained._NavLayerTxPanel'); 2 | 3 | goog.require('goog.asserts'); 4 | goog.require('pl.retained.HorizontalAlignment'); 5 | goog.require('pl.retained.Panel'); 6 | goog.require('pl.retained.VerticalAlignment'); 7 | 8 | 9 | 10 | /** 11 | * @constructor 12 | * @extends {pl.retained.Panel} 13 | * @param {!HTMLCanvasElement} lastCanvas 14 | * @param {!goog.graphics.AffineTransform} startTx The transform describing the initial orientation of 15 | the new child to the old child. 16 | * @param {!goog.graphics.AffineTransform} ghostTx describes the relationship of the last child to the 17 | Container. 18 | * @param {number} frameCount 19 | * @param {!pl.retained.HorizontalAlignment} horizontalAlignment 20 | * @param {!pl.retained.VerticalAlignment} verticalAlignment 21 | * @param {!goog.math.Vec2} childOffset 22 | */ 23 | pl.retained._NavLayerTxPanel = function(width, height, lastCanvas, newChild, startTx, ghostTx, frameCount, horizontalAlignment, verticalAlignment, childOffset) { 24 | goog.base(this, width, height); 25 | this.clip = false; 26 | 27 | /** 28 | * @private 29 | * @type {number} 30 | **/ 31 | this._frames = frameCount; 32 | 33 | this._lastImage = new pl.retained.Image(lastCanvas, lastCanvas.width, lastCanvas.height); 34 | this._newChild = newChild; 35 | 36 | this.addElement(this._lastImage); 37 | this.addElement(newChild); 38 | 39 | // transform lastImage to be in the correct position, given newChild 40 | var lastTx = this._lastImage.addTransform(); 41 | lastTx.copyFrom(startTx.createInverse()); 42 | 43 | childOffset = pl.gfx.getOffsetVector(this.getSize(), newChild.getSize(), horizontalAlignment, verticalAlignment, childOffset); 44 | this._goalTx = goog.graphics.AffineTransform.getTranslateInstance(childOffset.x, childOffset.y); 45 | 46 | this._startTx = ghostTx.clone().concatenate(startTx); 47 | 48 | // at this point, the 'children' of this element are oriented correctly 49 | // new we want to add a tx to this guy to put him in the right start position 50 | this._myTx = this.addTransform(); 51 | 52 | this._myTx.copyFrom(this._startTx); 53 | 54 | this._i = 0; 55 | 56 | }; 57 | goog.inherits(pl.retained._NavLayerTxPanel, pl.retained.Panel); 58 | 59 | pl.retained._NavLayerTxPanel.prototype.isDone = function() { 60 | goog.asserts.assert(goog.math.isInt(this._frames)); 61 | goog.asserts.assert(this._frames >= 0); 62 | goog.asserts.assert(this._i >= 0); 63 | return this._i >= this._frames; 64 | }; 65 | 66 | pl.retained._NavLayerTxPanel.prototype.dispose = function() { 67 | this.remove(this._newChild); 68 | }; 69 | 70 | 71 | /** 72 | * @override 73 | **/ 74 | pl.retained._NavLayerTxPanel.prototype.update = function() { 75 | goog.asserts.assert(goog.math.isInt(this._frames)); 76 | goog.asserts.assert(this._frames >= 0); 77 | if (this._i < this._frames) { 78 | goog.asserts.assert(!this.isDone()); 79 | var ratio = this._i / (this._frames - 1); 80 | var newTx = pl.gfx.lerpTx(this._startTx, this._goalTx, ratio); 81 | this._myTx.copyFrom(newTx); 82 | 83 | this._lastImage.alpha = 1 - ratio; 84 | this._lastImage.invalidateDraw(); 85 | 86 | this._newChild.alpha = ratio; 87 | this._newChild.invalidateDraw(); 88 | 89 | goog.base(this, 'update'); 90 | this.invalidateDraw(); 91 | this._i++; 92 | } else { 93 | goog.asserts.assert(this.isDone()); 94 | goog.asserts.assert(this._newChild.alpha === 1); 95 | goog.asserts.assert(this._lastImage.alpha === 0); 96 | } 97 | }; 98 | -------------------------------------------------------------------------------- /src/retained/alignment.js: -------------------------------------------------------------------------------- 1 | goog.provide('pl.retained.HorizontalAlignment'); 2 | goog.provide('pl.retained.VerticalAlignment'); 3 | 4 | 5 | /** 6 | * @enum {string} 7 | */ 8 | pl.retained.VerticalAlignment = { 9 | TOP: 'Top', 10 | BOTTOM: 'Bottom', 11 | CENTER: 'Center' 12 | }; 13 | 14 | 15 | /** 16 | * @enum {string} 17 | */ 18 | pl.retained.HorizontalAlignment = { 19 | LEFT: 'Left', 20 | RIGHT: 'Right', 21 | CENTER: 'Center' 22 | }; 23 | -------------------------------------------------------------------------------- /src/retained/animation.js: -------------------------------------------------------------------------------- 1 | goog.provide('pl.retained.Animation'); 2 | 3 | goog.require('goog.asserts'); 4 | goog.require('pl.Behavior'); 5 | goog.require('pl.retained.EventType'); 6 | 7 | 8 | 9 | /** 10 | * @constructor 11 | * @extends {pl.Behavior} 12 | * @param {!pl.retained.Element} element 13 | * @param {number} frameCount 14 | * @param {!function(number, !pl.retained.Element)} func 15 | * @param {function(!pl.retained.Element)=} opt_finishFunc 16 | */ 17 | pl.retained.Animation = function(element, frameCount, func, opt_finishFunc) { 18 | goog.base(this, element); 19 | 20 | element.addEventListener(pl.retained.EventType.UPDATE, this._tick, false, this); 21 | 22 | this._frameCount = frameCount; 23 | this._func = func; 24 | this._finishFunc = opt_finishFunc || goog.nullFunction; 25 | this._frame = 0; 26 | }; 27 | goog.inherits(pl.retained.Animation, pl.Behavior); 28 | 29 | 30 | /** 31 | * @type {boolean} 32 | */ 33 | pl.retained.Animation.prototype.detachOnFinish = false; 34 | 35 | pl.retained.Animation.prototype.detach = function() { 36 | var removed = goog.events.unlisten(this.getElement(), pl.retained.EventType.UPDATE, this._tick, false, this); 37 | goog.asserts.assert(removed); 38 | goog.base(this, 'detach'); 39 | }; 40 | 41 | 42 | /** 43 | * @private 44 | */ 45 | pl.retained.Animation.prototype._tick = function() { 46 | var element = this.getElement(); 47 | goog.asserts.assert(element); 48 | this._func(this._frame, element); 49 | this._frame++; 50 | if (this._frame == this._frameCount) { 51 | this._finishFunc(element); 52 | if (this.detachOnFinish) { 53 | this.detach(); 54 | } 55 | } 56 | this._frame = this._frame % this._frameCount; 57 | }; 58 | 59 | 60 | /** 61 | @return {pl.retained.Element} 62 | */ 63 | pl.retained.Animation.prototype.getElement = function() { 64 | return /** @type {pl.retained.Element} */ (this._element); 65 | }; 66 | -------------------------------------------------------------------------------- /src/retained/canvas.js: -------------------------------------------------------------------------------- 1 | goog.provide('pl.retained.Canvas'); 2 | 3 | goog.require('goog.graphics.AffineTransform'); 4 | goog.require('goog.math.Coordinate'); 5 | goog.require('pl.retained.Element'); 6 | goog.require('pl.retained.Panel'); 7 | 8 | 9 | 10 | /** 11 | * @constructor 12 | * @param {number} width 13 | * @param {number} height 14 | * @param {boolean=} opt_enableCache 15 | * @extends {pl.retained.Panel} 16 | */ 17 | pl.retained.Canvas = function(width, height, opt_enableCache) { 18 | goog.base(this, width, height, opt_enableCache); 19 | }; 20 | goog.inherits(pl.retained.Canvas, pl.retained.Panel); 21 | 22 | 23 | /** 24 | * @param {!pl.retained.Element} element 25 | * @param {!goog.math.Coordinate=} opt_value 26 | * @return {!goog.math.Coordinate} 27 | */ 28 | pl.retained.Canvas.prototype.topLeft = function(element, opt_value) { 29 | var tx = this.getChildTransform(element); 30 | if (opt_value) { 31 | tx.setToTranslation(opt_value.x, opt_value.y); 32 | } 33 | return pl.ex.transformCoordinate(tx, new goog.math.Coordinate()); 34 | }; 35 | 36 | 37 | /** 38 | * @param {!pl.retained.Element} element 39 | * @param {!goog.math.Coordinate=} opt_value 40 | * @return {!goog.math.Coordinate} 41 | */ 42 | pl.retained.Canvas.prototype.center = function(element, opt_value) { 43 | var sizeOffset = new goog.math.Vec2(element.width / 2, element.height / 2); 44 | if (opt_value) { 45 | var tl = goog.math.Vec2.difference(opt_value, sizeOffset); 46 | this.topLeft(element, tl); 47 | } 48 | return sizeOffset.add(this.topLeft(element)); 49 | }; 50 | -------------------------------------------------------------------------------- /src/retained/elementParent.js: -------------------------------------------------------------------------------- 1 | goog.provide('pl.retained.ElementParent'); 2 | 3 | goog.require('goog.array'); 4 | goog.require('goog.asserts'); 5 | 6 | 7 | 8 | /** 9 | * @interface 10 | */ 11 | pl.retained.ElementParent = function() {}; 12 | 13 | 14 | /** 15 | * @param {!pl.retained.Element} child 16 | */ 17 | pl.retained.ElementParent.prototype.childInvalidated = function(child) { }; 18 | -------------------------------------------------------------------------------- /src/retained/eventType.js: -------------------------------------------------------------------------------- 1 | goog.provide('pl.retained.EventType'); 2 | 3 | 4 | /** 5 | * Constants for event names. 6 | * @enum {string} 7 | */ 8 | pl.retained.EventType = { 9 | UPDATE: 'Update' 10 | }; 11 | -------------------------------------------------------------------------------- /src/retained/helper.js: -------------------------------------------------------------------------------- 1 | goog.provide('pl.retained.helper'); 2 | 3 | goog.require('goog.array'); 4 | goog.require('goog.math.Coordinate'); 5 | goog.require('goog.math.Size'); 6 | goog.require('pl.ex'); 7 | goog.require('pl.gfx'); 8 | goog.require('pl.retained.Element'); 9 | goog.require('pl.retained.mouse'); 10 | 11 | goog.scope(function() { 12 | var h = pl.retained.helper; 13 | 14 | 15 | /** 16 | * @param {!pl.retained.Stage} stage 17 | */ 18 | h.borderElements = function(stage) { 19 | var ctx = stage.getContext(); 20 | ctx.save(); 21 | ctx.globalAlpha = 0.5; 22 | ctx.lineWidth = 5; 23 | ctx.beginPath(); 24 | h._borderElement(ctx, stage.getRoot()); 25 | ctx.stroke(); 26 | ctx.restore(); 27 | }; 28 | 29 | 30 | /** 31 | * @param {!pl.retained.Stage} stage 32 | * @param {!goog.math.Coordinate} point 33 | * @return {!Array.} 34 | */ 35 | h.hitTest = function(stage, point) { 36 | return h._hitTest(stage.getRoot(), point); 37 | }; 38 | 39 | 40 | /** 41 | * @param {!pl.retained.Stage} stage 42 | * @param {!goog.math.Coordinate} point 43 | */ 44 | h.borderHitTest = function(stage, point) { 45 | var ctx = stage.getContext(); 46 | 47 | var hits = h.hitTest(stage, point); 48 | if (hits.length) { 49 | ctx.save(); 50 | ctx.lineWidth = 2; 51 | 52 | ctx.beginPath(); 53 | goog.array.forEach(hits, function(e) { 54 | h._borderElement(ctx, e, true); 55 | }); 56 | ctx.stroke(); 57 | ctx.restore(); 58 | } 59 | }; 60 | 61 | 62 | /** 63 | * @param {!pl.retained.Element} element 64 | * @param {!goog.math.Coordinate} point 65 | * @return {!goog.math.Coordinate} 66 | */ 67 | h.transformPointLocalToGlobal = function(element, point) { 68 | var tx = element.getTransform(); 69 | return pl.ex.transformCoordinate(tx, point.clone()); 70 | }; 71 | 72 | 73 | /** 74 | * @param {!pl.retained.Element} element 75 | * @param {!goog.math.Coordinate} point 76 | * @return {!goog.math.Coordinate} 77 | */ 78 | h.transformPointGlobalToLocal = function(element, point) { 79 | var tx = element.getTransform(); 80 | return pl.ex.transformCoordinate(tx.createInverse(), point.clone()); 81 | }; 82 | 83 | 84 | /** 85 | * @param {!pl.retained.Element} element 86 | * @return {!goog.math.Rect} 87 | */ 88 | h.getBounds = function(element) { 89 | var corners = h.getCorners(element); 90 | var box = goog.math.Box.boundingBox.apply(null, corners); 91 | return goog.math.Rect.createFromBox(box); 92 | }; 93 | 94 | 95 | /** 96 | * @param {!pl.retained.Element} element 97 | * @return {!Array.} 98 | */ 99 | h.getCorners = function(element) { 100 | var rect = element.getRect(); 101 | var points = pl.ex.getPoints(rect); 102 | return goog.array.map(points, function(p) { 103 | return h.transformPointLocalToGlobal(element, p); 104 | }); 105 | }; 106 | 107 | 108 | /** 109 | * @private 110 | * @param {!CanvasRenderingContext2D} ctx 111 | * @param {!pl.retained.Element} element 112 | * @param {boolean=} opt_excludeChildren 113 | * @param {function(!pl.retained.Element):boolean=} opt_filter 114 | */ 115 | h._borderElement = function(ctx, element, opt_excludeChildren, opt_filter) { 116 | pl.gfx.transform(ctx, element.getTransform()); 117 | 118 | if (!opt_filter || opt_filter(element)) { 119 | h._borderElementCore(ctx, element); 120 | } 121 | 122 | if (!opt_excludeChildren) { 123 | for (var i = 0; i < element.getVisualChildCount(); i++) { 124 | var e = element.getVisualChild(i); 125 | ctx.save(); 126 | h._borderElement(ctx, e, false, opt_filter); 127 | ctx.restore(); 128 | } 129 | } 130 | }; 131 | 132 | 133 | /** 134 | * @private 135 | * @param {!CanvasRenderingContext2D} ctx 136 | * @param {!pl.retained.Element} element 137 | */ 138 | h._borderElementCore = function(ctx, element) { 139 | if (pl.retained.mouse.IsMouseDirectlyOverProperty.get(element)) { 140 | ctx.strokeStyle = 'red'; 141 | } else if (pl.retained.mouse.IsMouseOverProperty.get(element)) { 142 | ctx.strokeStyle = 'pink'; 143 | } else if (element.cacheEnabled) { 144 | ctx.strokeStyle = 'yellow'; 145 | } else { 146 | ctx.strokeStyle = 'blue'; 147 | } 148 | ctx.strokeRect(0, 0, element.width, element.height); 149 | }; 150 | 151 | 152 | /** 153 | * @private 154 | * @param {!pl.retained.Element} element 155 | * @param {!goog.math.Coordinate} point 156 | * @return {!Array.} 157 | */ 158 | h._hitTest = function(element, point) { 159 | point = h.transformPointGlobalToLocal(element, point); 160 | 161 | var bounds = new goog.math.Rect(0, 0, element.width, element.height); 162 | 163 | var hits = []; 164 | if (bounds.contains(point)) { 165 | 166 | var length = element.getVisualChildCount(); 167 | for (var i = 0; i < length; i++) { 168 | var e = element.getVisualChild(length - 1 - i); 169 | hits = h._hitTest(e, point); 170 | if (hits.length) { 171 | break; 172 | } 173 | } 174 | goog.array.insertAt(hits, element); 175 | return hits; 176 | } else { 177 | return []; 178 | } 179 | }; 180 | }); // goog.scope 181 | -------------------------------------------------------------------------------- /src/retained/image.js: -------------------------------------------------------------------------------- 1 | goog.provide('pl.retained.Image'); 2 | 3 | goog.require('pl.gfx'); 4 | goog.require('pl.retained.Element'); 5 | 6 | 7 | 8 | /** 9 | * @constructor 10 | * @extends {pl.retained.Element} 11 | * @param {HTMLImageElement|HTMLCanvasElement|HTMLVideoElement} value 12 | * @param {number} width 13 | * @param {number} height 14 | */ 15 | pl.retained.Image = function(value, width, height) { 16 | goog.base(this, width, height, false); 17 | this._value = value; 18 | }; 19 | goog.inherits(pl.retained.Image, pl.retained.Element); 20 | 21 | 22 | /** 23 | * @override 24 | */ 25 | pl.retained.Image.prototype.drawOverride = function(ctx) { 26 | ctx.drawImage(this._value, 0, 0, this.width, this.height); 27 | }; 28 | -------------------------------------------------------------------------------- /src/retained/mouse.js: -------------------------------------------------------------------------------- 1 | goog.provide('pl.retained.mouse'); 2 | 3 | goog.require('goog.array'); 4 | goog.require('goog.math.Coordinate'); 5 | goog.require('pl.Property'); 6 | goog.require('pl.retained.Stage'); 7 | 8 | 9 | /** 10 | * @param {!pl.retained.Stage} stage 11 | * @param {goog.math.Coordinate=} opt_coordinate 12 | * @return {?Array.} 13 | */ 14 | pl.retained.mouse.markMouseOver = function(stage, opt_coordinate) { 15 | var items = 16 | /** @type {undefined|Array.} */ 17 | (pl.retained.mouse._stageMouseCacheProperty.get(stage)); 18 | 19 | if (items) { 20 | goog.array.forEach(items, function(e) { 21 | pl.retained.mouse.IsMouseOverProperty.clear(e); 22 | pl.retained.mouse.IsMouseDirectlyOverProperty.clear(e); 23 | }); 24 | } 25 | if (opt_coordinate) { 26 | var hits = pl.retained.helper.hitTest(stage, opt_coordinate); 27 | pl.retained.mouse._stageMouseCacheProperty.set(stage, hits); 28 | goog.array.forEach(hits, function(e) { 29 | pl.retained.mouse.IsMouseOverProperty.set(e, true); 30 | }); 31 | if (hits.length) { 32 | pl.retained.mouse.IsMouseDirectlyOverProperty.set(hits[hits.length - 1], true); 33 | } 34 | return hits; 35 | } 36 | return null; 37 | }; 38 | 39 | pl.retained.mouse.IsMouseOverProperty = new pl.Property('IsMouseOver', false); 40 | pl.retained.mouse.IsMouseDirectlyOverProperty = new pl.Property('IsMouseDirectlyOver', false); 41 | 42 | pl.retained.mouse._stageMouseCacheProperty = new pl.Property('StageMouseCacheProperty'); 43 | -------------------------------------------------------------------------------- /src/retained/panel.js: -------------------------------------------------------------------------------- 1 | goog.provide('pl.retained.Panel'); 2 | 3 | goog.require('goog.array'); 4 | goog.require('goog.asserts'); 5 | goog.require('pl.Property'); 6 | goog.require('pl.retained.Element'); 7 | goog.require('pl.retained.ElementParent'); 8 | goog.require('pl.retained.helper'); 9 | 10 | 11 | 12 | /** 13 | * @constructor 14 | * @param {number} width 15 | * @param {number} height 16 | * @param {boolean=} opt_enableCache 17 | * @implements {pl.retained.ElementParent} 18 | * @extends {pl.retained.Element} 19 | */ 20 | pl.retained.Panel = function(width, height, opt_enableCache) { 21 | goog.base(this, width, height, opt_enableCache); 22 | 23 | /** @type {!Array.} */ 24 | this._children = []; 25 | }; 26 | goog.inherits(pl.retained.Panel, pl.retained.Element); 27 | 28 | 29 | /** 30 | * @param {!pl.retained.Element} element 31 | **/ 32 | pl.retained.Panel.prototype.addElement = function(element) { 33 | this.insertAt(element, this._children.length); 34 | }; 35 | 36 | 37 | /** 38 | * @param {!pl.retained.Element} element 39 | * @param {number=} opt_i The index at which to insert the object. If omitted, 40 | * treated as 0. A negative index is counted from the end of the array. 41 | **/ 42 | pl.retained.Panel.prototype.insertAt = function(element, opt_i) { 43 | goog.array.insertAt(this._children, element, opt_i); 44 | element.claim(this); 45 | goog.asserts.assert(!pl.retained.Panel._containerTransformProperty.isSet(element), 'No container transform should be set...yet'); 46 | pl.retained.Panel._containerTransformProperty.set(element, element.addTransform()); 47 | this.onChildrenChanged(); 48 | }; 49 | 50 | 51 | /** 52 | * @param {!pl.retained.Element} element 53 | */ 54 | pl.retained.Panel.prototype.remove = function(element) { 55 | if (goog.array.remove(this._children, element)) { 56 | element.disown(this); 57 | var tx = pl.retained.Panel._containerTransformProperty.get(element); 58 | goog.asserts.assert(!! tx, 'A container transform should exist'); 59 | pl.retained.Panel._containerTransformProperty.clear(element); 60 | element.removeTransform(tx); 61 | this.onChildrenChanged(); 62 | } else { 63 | throw Error('element is not a child'); 64 | } 65 | }; 66 | 67 | 68 | /** 69 | * @protected 70 | * @param {!pl.retained.Element} child 71 | * @return {!goog.graphics.AffineTransform} 72 | */ 73 | pl.retained.Panel.prototype.getChildTransform = function(child) { 74 | goog.asserts.assert(goog.array.contains(this._children, child), 'Should be a child that this container actually owns'); 75 | var tx = pl.retained.Panel._containerTransformProperty.get(child); 76 | goog.asserts.assert(!! tx, 'A container transform should exist'); 77 | return tx; 78 | }; 79 | 80 | 81 | /** 82 | * @override 83 | * @param {number} index 84 | * @return {!pl.retained.Element} 85 | */ 86 | pl.retained.Panel.prototype.getVisualChild = function(index) { 87 | return this._children[index]; 88 | }; 89 | 90 | 91 | /** 92 | * @override 93 | * @return {number} 94 | */ 95 | pl.retained.Panel.prototype.getVisualChildCount = function() { 96 | return this._children.length; 97 | }; 98 | 99 | pl.retained.Panel.prototype.onChildrenChanged = function() { 100 | this.invalidateDraw(); 101 | }; 102 | 103 | 104 | /** 105 | * returns {?math.google.Rect} 106 | */ 107 | pl.retained.Panel.prototype.getChildBounds = function() { 108 | var bounds = null; 109 | if (this._children.length) { 110 | bounds = pl.retained.helper.getBounds(this._children[0]); 111 | 112 | goog.array.forEach(this._children, function(child) { 113 | bounds.boundingRect(pl.retained.helper.getBounds(child)); 114 | }, 115 | this); 116 | } 117 | return bounds; 118 | }; 119 | 120 | 121 | /** 122 | * @override 123 | **/ 124 | pl.retained.Panel.prototype.update = function() { 125 | goog.array.forEach(this._children, function(element) { 126 | element.update(); 127 | }, 128 | this); 129 | goog.base(this, 'update'); 130 | }; 131 | 132 | 133 | /** 134 | * @override 135 | * @param {!CanvasRenderingContext2D} ctx 136 | **/ 137 | pl.retained.Panel.prototype.drawOverride = function(ctx) { 138 | var length = this.getVisualChildCount(); 139 | for (var i = 0; i < length; i++) { 140 | var element = this.getVisualChild(i); 141 | element.drawInternal(ctx); 142 | } 143 | }; 144 | 145 | 146 | /** 147 | * @param {!pl.retained.Element} child 148 | */ 149 | pl.retained.Panel.prototype.childInvalidated = function(child) { 150 | goog.asserts.assert(this.hasVisualChild(child), "Must be the container's child"); 151 | this.invalidateDraw(); 152 | }; 153 | 154 | 155 | /** 156 | * @private 157 | * @const 158 | * @type {!pl.Property} 159 | */ 160 | pl.retained.Panel._containerTransformProperty = new pl.Property('panelTransfrom'); 161 | -------------------------------------------------------------------------------- /src/retained/shape.js: -------------------------------------------------------------------------------- 1 | goog.provide('pl.retained.Shape'); 2 | goog.provide('pl.retained.ShapeType'); 3 | 4 | goog.require('pl.gfx'); 5 | goog.require('pl.retained.Element'); 6 | 7 | 8 | /** 9 | * @enum {string} 10 | */ 11 | pl.retained.ShapeType = { 12 | RECT: 'rectangle', 13 | ELLIPSE: 'ellipse' 14 | }; 15 | 16 | 17 | 18 | /** 19 | * @constructor 20 | * @extends {pl.retained.Element} 21 | * @param {number} width 22 | * @param {number} height 23 | */ 24 | pl.retained.Shape = function(width, height) { 25 | goog.base(this, width, height, true); 26 | }; 27 | goog.inherits(pl.retained.Shape, pl.retained.Element); 28 | 29 | 30 | /** 31 | * @type {!pl.retained.ShapeType} 32 | */ 33 | pl.retained.Shape.prototype.type = pl.retained.ShapeType.RECT; 34 | 35 | 36 | /** 37 | * @type {?(string|CanvasGradient|CanvasPattern)} 38 | */ 39 | pl.retained.Shape.prototype.fillStyle = 'white'; 40 | 41 | 42 | /** 43 | * @override 44 | */ 45 | pl.retained.Shape.prototype.drawOverride = function(ctx) { 46 | if (this.fillStyle) { 47 | ctx.fillStyle = this.fillStyle; 48 | switch (this.type) { 49 | case pl.retained.ShapeType.RECT: 50 | ctx.fillRect(0, 0, this.width, this.height); 51 | break; 52 | case pl.retained.ShapeType.ELLIPSE: 53 | pl.gfx.ellipse(ctx, 0, 0, this.width, this.height); 54 | ctx.fill(); 55 | break; 56 | default: 57 | throw Error("Don't know how to draw " + this.type); 58 | } 59 | } 60 | }; 61 | -------------------------------------------------------------------------------- /src/retained/stage.js: -------------------------------------------------------------------------------- 1 | goog.provide('pl.retained.Stage'); 2 | 3 | goog.require('goog.events.EventTarget'); 4 | goog.require('goog.math.Coordinate'); 5 | goog.require('goog.math.Size'); 6 | goog.require('pl.ex'); 7 | goog.require('pl.retained.Element'); 8 | goog.require('pl.retained.ElementParent'); 9 | goog.require('pl.retained.EventType'); 10 | 11 | 12 | 13 | /** 14 | * @constructor 15 | * @extends {goog.events.EventTarget} 16 | * @implements {pl.retained.ElementParent} 17 | * @param {!HTMLCanvasElement} canvas 18 | * @param {!pl.retained.Element} rootElement 19 | */ 20 | pl.retained.Stage = function(canvas, rootElement) { 21 | goog.base(this); 22 | this._canvas = canvas; 23 | this._element = rootElement; 24 | this._element.claim(this); 25 | }; 26 | goog.inherits(pl.retained.Stage, goog.events.EventTarget); 27 | 28 | 29 | /** 30 | * @return {!goog.math.Size} 31 | */ 32 | pl.retained.Stage.prototype.getSize = function() { 33 | return pl.ex.getCanvasSize(this._canvas); 34 | }; 35 | 36 | 37 | /** 38 | * @param {goog.math.Size} size 39 | * @return {boolean} 40 | */ 41 | pl.retained.Stage.prototype.setSize = function(size) { 42 | if (!goog.math.Size.equals(this.getSize(), size)) { 43 | this._canvas.width = size.width; 44 | this._canvas.height = size.height; 45 | this._ctx = null; 46 | return true; 47 | } 48 | return false; 49 | }; 50 | 51 | 52 | /** 53 | * @return {boolean} Returns 'true' if the system has updated in the last frame. 54 | * Indicates animations are running and you might want to continue 55 | * pushing frames. 56 | **/ 57 | pl.retained.Stage.prototype.draw = function() { 58 | if (!this._ctx) { 59 | this._ctx = 60 | /** @type {CanvasRenderingContext2D} */ 61 | (this._canvas.getContext('2d')); 62 | } else { 63 | this._ctx.clearRect(0, 0, this._canvas.width, this._canvas.height); 64 | } 65 | 66 | return this._element.draw(this._ctx); 67 | }; 68 | 69 | 70 | /** 71 | * @return {!CanvasRenderingContext2D} 72 | */ 73 | pl.retained.Stage.prototype.getContext = function() { 74 | if (!this._ctx) { 75 | this._ctx = 76 | /** @type {CanvasRenderingContext2D} */ 77 | (this._canvas.getContext('2d')); 78 | } 79 | return this._ctx; 80 | }; 81 | 82 | 83 | /** 84 | * @return {!pl.retained.Element} 85 | */ 86 | pl.retained.Stage.prototype.getRoot = function() { 87 | return this._element; 88 | }; 89 | 90 | 91 | /** 92 | * @param {!pl.retained.Element} child 93 | */ 94 | pl.retained.Stage.prototype.childInvalidated = function(child) { 95 | goog.asserts.assert(this._element == child); 96 | this.dispatchEvent(pl.retained.EventType.UPDATE); 97 | }; 98 | -------------------------------------------------------------------------------- /src/retained/text.js: -------------------------------------------------------------------------------- 1 | goog.provide('pl.retained.Text'); 2 | 3 | goog.require('pl.gfx'); 4 | goog.require('pl.retained.Element'); 5 | 6 | 7 | 8 | /** 9 | * @constructor 10 | * @extends {pl.retained.Element} 11 | * @param {string} value 12 | * @param {number} width 13 | * @param {number} height 14 | */ 15 | pl.retained.Text = function(value, width, height) { 16 | goog.base(this, width, height, true); 17 | this._value = value; 18 | }; 19 | goog.inherits(pl.retained.Text, pl.retained.Element); 20 | 21 | pl.retained.Text.prototype.textFillStyle = 'white'; 22 | 23 | pl.retained.Text.prototype.font = '25px Helvetica'; 24 | 25 | pl.retained.Text.prototype.lineHeight = 25; 26 | 27 | pl.retained.Text.prototype.multiLine = false; 28 | 29 | pl.retained.Text.prototype.isCentered = false; 30 | 31 | pl.retained.Text.prototype.shadowColor = undefined; 32 | pl.retained.Text.prototype.shadowBlur = 4; 33 | 34 | 35 | /** 36 | * @type {?(string|CanvasGradient|CanvasPattern)} 37 | */ 38 | pl.retained.Text.prototype.fillStyle = null; 39 | 40 | 41 | /** 42 | * @override 43 | */ 44 | pl.retained.Text.prototype.drawOverride = function(ctx) { 45 | if (this.fillStyle) { 46 | ctx.fillStyle = this.fillStyle; 47 | ctx.fillRect(0, 0, this.width, this.height); 48 | } 49 | 50 | var xStart = 0; 51 | if (this.isCentered) { 52 | ctx.textAlign = 'center'; 53 | xStart = this.width / 2; 54 | } 55 | 56 | if (this.shadowColor) { 57 | ctx.shadowColor = this.shadowColor; 58 | ctx.shadowBlur = this.shadowBlur; 59 | } 60 | 61 | ctx.font = this.font; 62 | ctx.textBaseline = 'top'; 63 | ctx.fillStyle = this.textFillStyle; 64 | if (this.multiLine) { 65 | pl.gfx.multiFillText(ctx, this._value, xStart, 0, this.lineHeight, this.width); 66 | } else { 67 | ctx.fillText(this._value, xStart, 0); 68 | } 69 | }; 70 | -------------------------------------------------------------------------------- /src/retained/tileLayer.js: -------------------------------------------------------------------------------- 1 | goog.provide('pl.retained.TileLayer'); 2 | 3 | goog.require('goog.math.Vec2'); 4 | goog.require('pl.ex'); 5 | goog.require('pl.gfx'); 6 | 7 | 8 | 9 | /** 10 | * @constructor 11 | * @param {number} width 12 | * @param {number} height 13 | * @param {!HTMLImageElement} image 14 | * @param {!goog.math.Size=} opt_tileSize 15 | * @extends {pl.retained.Element} 16 | */ 17 | pl.retained.TileLayer = function(width, height, image, opt_tileSize) { 18 | goog.base(this, width, height); 19 | this._image = image; 20 | this._tileSize = opt_tileSize ? opt_tileSize.clone() : new goog.math.Size(image.width, image.height); 21 | this._offset = new goog.math.Vec2(0, 0); 22 | this._scale = new goog.math.Vec2(this._tileSize.width / this._image.width, this._tileSize.height / this._image.height); 23 | }; 24 | goog.inherits(pl.retained.TileLayer, pl.retained.Element); 25 | 26 | 27 | /** 28 | * @param {!goog.math.Vec2} offset 29 | */ 30 | pl.retained.TileLayer.prototype.setOffset = function(offset) { 31 | this._offset.x = pl.retained.TileLayer._fix(offset.x, this._tileSize.width); 32 | this._offset.y = pl.retained.TileLayer._fix(offset.y, this._tileSize.height); 33 | }; 34 | 35 | pl.retained.TileLayer.prototype.getOffset = function() { 36 | return this._offset.clone(); 37 | }; 38 | 39 | 40 | /** 41 | * @override 42 | */ 43 | pl.retained.TileLayer.prototype.drawOverride = function(ctx) { 44 | if (!this._pattern) { 45 | this._pattern = ctx.createPattern(this._image, 'repeat'); 46 | } 47 | 48 | var rect = new goog.math.Rect(-this._offset.x / this._scale.x, -this._offset.y / this._scale.y, this.width / this._scale.x, this.height / this._scale.y); 49 | 50 | ctx.setTransform(this._scale.x, 0, 0, this._scale.y, this._offset.x, this._offset.y); 51 | 52 | ctx.fillStyle = this._pattern; 53 | pl.gfx.fillRect(ctx, rect); 54 | }; 55 | 56 | 57 | /** 58 | * @private 59 | * @param {number} input 60 | * @param {number} target 61 | * @return {number} 62 | */ 63 | pl.retained.TileLayer._fix = function(input, target) { 64 | input = input - Math.ceil(input / target) * target; 65 | input = pl.ex.round(input); 66 | return input; 67 | }; 68 | -------------------------------------------------------------------------------- /src/soundEffect.js: -------------------------------------------------------------------------------- 1 | goog.provide('pl.SoundEffect'); 2 | 3 | 4 | 5 | /** 6 | @constructor 7 | @param {string} name 8 | @param {!Array.>} locations 9 | @param {number} simulCount 10 | */ 11 | pl.SoundEffect = function(name, locations, simulCount) { 12 | /** 13 | @private 14 | @type {!Array.} 15 | */ 16 | this.m_audios = new Array(); 17 | 18 | /** 19 | @private 20 | @type {number} 21 | */ 22 | this.m_maxSimul = simulCount; 23 | 24 | /** 25 | @private 26 | @type {number} 27 | */ 28 | this.m_currSimul = 0; 29 | 30 | var existing = document.getElementsByClassName('audio_' + name); 31 | for (var i = 0; i < existing.length; i++) { 32 | this.m_audios.push(existing[i]); 33 | } 34 | 35 | for (var j = existing.length; j < simulCount; j++) { 36 | this.m_audios.push(pl.SoundEffect.create(name, locations)); 37 | } 38 | }; 39 | 40 | 41 | /** 42 | @return {Element} 43 | */ 44 | pl.SoundEffect.prototype.play = function() { 45 | // get the next audio 46 | this.m_currSimul++; 47 | this.m_currSimul %= this.m_maxSimul; 48 | var audio = this.m_audios[this.m_currSimul]; 49 | if (goog.userAgent.WEBKIT) { 50 | goog.array.forEach(audio.getElementsByTagName('source'), function(element, index, array) { 51 | var location = element.src; 52 | element.src = location; 53 | }); 54 | audio.load(); 55 | } 56 | audio.play(); 57 | return audio; 58 | }; 59 | 60 | 61 | /** 62 | * @param {string} name of the audio being added. 63 | * @param {!Array.>} data 64 | * @return {Element} 65 | */ 66 | pl.SoundEffect.create = function(name, data) { 67 | var holder = document.getElementById(pl.SoundEffect.s_audioHolderId); 68 | if (holder === undefined || holder == null) { 69 | holder = document.createElement('div'); 70 | holder.id = pl.SoundEffect.s_audioHolderId; 71 | holder.style['display'] = 'none'; 72 | document.body.appendChild(holder); 73 | } 74 | var audio = document.createElement('audio'); 75 | audio.className = 'audio_' + name; 76 | holder.appendChild(audio); 77 | for (var index in data) { 78 | var source = document.createElement('source'); 79 | source.src = data[index][0]; 80 | source.type = data[index][1]; 81 | audio.appendChild(source); 82 | } 83 | return audio; 84 | }; 85 | 86 | 87 | /** 88 | @private 89 | @type {string} 90 | @const 91 | */ 92 | pl.SoundEffect.s_audioHolderId = '_audios'; 93 | -------------------------------------------------------------------------------- /src/stats.js: -------------------------------------------------------------------------------- 1 | goog.provide('pl.Stats'); 2 | 3 | goog.require('goog.dom'); 4 | 5 | 6 | /** 7 | @param {!string} account_key 8 | */ 9 | pl.Stats.addGoogleAnalytics = function(account_key) { 10 | // TODO: support SSH 11 | pl.Stats._addScript('http://www.google-analytics.com/ga.js'); 12 | pl.Stats.gaqPush(['_setAccount', account_key]); 13 | pl.Stats.gaqPush(['_trackPageview']); 14 | }; 15 | 16 | 17 | /** 18 | * @param {Array.|function()} commandArray 19 | */ 20 | pl.Stats.gaqPush = function(commandArray) { 21 | var gaq = goog.object.get(goog.global, '_gaq', null); 22 | if (!gaq) { 23 | goog.object.add(goog.global, '_gaq', gaq = []); 24 | } 25 | gaq.push(commandArray); 26 | }; 27 | 28 | 29 | /** 30 | * @param {string} category 31 | * @param {string} action 32 | * @param {string=} opt_label 33 | * @param {number=} opt_value 34 | * @return {undefined} 35 | */ 36 | pl.Stats.gaqTrackEvent = function(category, action, opt_label, opt_value) { 37 | pl.Stats.gaqPush(['_trackEvent', category, action, opt_label, opt_value]); 38 | }; 39 | 40 | 41 | /** 42 | @param {number} projectId 43 | @param {!string} securityId 44 | */ 45 | pl.Stats.addStatCounter = function(projectId, securityId) { 46 | goog.global['sc_project'] = projectId; 47 | goog.global['sc_security'] = securityId; 48 | goog.global['sc_invisible'] = 1; 49 | 50 | pl.Stats._addScript('http://www.statcounter.com/counter/counter_xhtml.js'); 51 | }; 52 | 53 | 54 | /** 55 | @private 56 | @param {!string} script_uri 57 | */ 58 | pl.Stats._addScript = function(script_uri) { 59 | var script = document.createElement('script'); 60 | script.type = 'text/javascript'; 61 | script.async = true; 62 | script.src = script_uri; 63 | 64 | var heads = document.getElementsByTagName('head'); 65 | if (heads.length != 1) { 66 | throw Error("Couldn't find a single head tag."); 67 | } 68 | 69 | var head = heads[0]; 70 | 71 | var headScripts = head.getElementsByTagName('script'); 72 | if (headScripts.length == 0) { 73 | goog.dom.appendChild(head, script); 74 | } else { 75 | goog.dom.insertSiblingBefore(script, headScripts[0]); 76 | } 77 | }; 78 | -------------------------------------------------------------------------------- /test/config.kb: -------------------------------------------------------------------------------- 1 | closure_path: ../../closure 2 | js_paths: 3 | - . 4 | - ../src 5 | deps_path: deps.js 6 | fix_paths: 7 | - ../src 8 | -------------------------------------------------------------------------------- /test/pl.ex_test.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PL Tests - pl.ex 6 | 7 | 8 | 14 | 15 | 16 | 93 | 94 | 95 | -------------------------------------------------------------------------------- /test/pl.graph_test.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PL Tests - pl.Graph 6 | 7 | 8 | 12 | 13 | 14 | 150 | 151 | 152 | -------------------------------------------------------------------------------- /test/pl.model_test.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PL Tests - pl.Property 6 | 7 | 8 | 12 | 13 | 14 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /test/pl.property_test.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PL Tests - pl.Property 6 | 7 | 8 | 13 | 14 | 15 | 44 | 45 | 46 | --------------------------------------------------------------------------------