1 /** 2 * The Render Engine 3 * MouseJointComponent 4 * 5 * @fileoverview A mouse joint which can be used to link the mouse to a {@link R.physics.Simulation}. 6 * 7 * @author: Brett Fattori (brettf@renderengine.com) 8 * 9 * @author: $Author: bfattori $ 10 * @version: $Revision: 1555 $ 11 * 12 * Copyright (c) 2011 Brett Fattori (brettf@renderengine.com) 13 * 14 * Permission is hereby granted, free of charge, to any person obtaining a copy 15 * of this software and associated documentation files (the "Software"), to deal 16 * in the Software without restriction, including without limitation the rights 17 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 18 * copies of the Software, and to permit persons to whom the Software is 19 * furnished to do so, subject to the following conditions: 20 * 21 * The above copyright notice and this permission notice shall be included in 22 * all copies or substantial portions of the Software. 23 * 24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 25 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 26 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 27 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 28 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 29 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 30 * THE SOFTWARE. 31 * 32 */ 33 34 // The class this file defines and its required classes 35 R.Engine.define({ 36 "class":"R.components.physics.MouseJoint", 37 "requires":[ 38 "R.components.physics.BaseJoint", 39 "R.physics.Simulation", 40 "R.math.Math2D" 41 ] 42 }); 43 44 /** 45 * @class A mouse joint which allows the mouse to be used to interact within 46 * a {@link R.physics.Simulation}. The typical usage is to query the 47 * world at the mouse position to determine what the mouse is currently 48 * over, then you begin simulation of the <code>R.components.physics.MouseJoint</code> 49 * component which links it to the body. When movement of the object via the mouse is 50 * no longer needed, stop simulation of the joint. 51 * 52 * @param name {String} Name of the component 53 * @param body1 {R.components.physics.BaseBody} The first body for the joint 54 * @param body2 {R.components.physics.BaseBody} The second body for the joint 55 * 56 * @extends R.components.physics.BaseJoint 57 * @constructor 58 * @description Creates a mouse joint between a rigid body and the mouse. This a soft constraint 59 * with a maximum force. This allows the constraint to stretch and without applying 60 * huge forces. 61 */ 62 R.components.physics.MouseJoint = function () { 63 return R.components.physics.BaseJoint.extend(/** @scope R.components.physics.MouseJoint.prototype */{ 64 65 mousePos:null, 66 67 /** 68 * @private 69 */ 70 constructor:function (name, body, simulation) { 71 var jointDef = new Box2D.Dynamics.Joints.b2MouseJointDef(); 72 this.base(name || "MouseJoint", simulation.getGroundBody(), body, jointDef); 73 this.mousePos = new Box2D.Common.Math.b2Vec2(0, 0); 74 }, 75 76 /** 77 * Release the object back into the pool. 78 */ 79 release:function () { 80 this.base(); 81 this.mousePos = null; 82 }, 83 84 /** 85 * When simulation starts set the anchor points to the position of each rigid body. 86 * @private 87 */ 88 startSimulation:function () { 89 if (!this.getSimulation()) { 90 // The initial target is important, otherwise it's assumed to be 0,0 91 this.getJointDef().target = this.getBody().getBody().GetPosition(); 92 this.getJointDef().maxForce = this.getBody().getMass() * R.components.physics.MouseJoint.FORCE_FACTOR; 93 this.setCollideBodies(true); 94 } 95 this.base(); 96 }, 97 98 /** 99 * Set the body component which will be affected by the mouse. This should 100 * be called when the joint is not being simulated. 101 * @param body {R.components.physics.BaseBody} The body component 102 */ 103 setBody:function (body) { 104 this.setBody2(body); 105 }, 106 107 /** 108 * Get the body component linked to this joint. 109 * @return {R.components.physics.BaseBody} 110 */ 111 getBody:function () { 112 return this.getBody2(); 113 }, 114 115 /** 116 * Set the frequency which is used to determine joint softness. According to 117 * Box2d documentation the frequency should be less than half of the time step 118 * used for the simulation. In the engine, the frequency of the time step is 119 * the frame rate. 120 * 121 * @param hz {Number} The frequency in Hertz. 122 */ 123 setFrequency:function (hz) { 124 this.getJointDef().frequencyHz = hz; 125 }, 126 127 /** 128 * Get the frequency from the joint definition. 129 * @return {Number} 130 */ 131 getFrequency:function () { 132 return this.getJointDef().frequencyHz; 133 }, 134 135 /** 136 * Set the damping ratio which is used to determine joint softness. The value 137 * should be between 0.0 and 1.0, with 1.0 being extremely rigid. 138 * 139 * @param dampingRatio {Number} A value between 0.0 and 1.0 140 */ 141 setDampingRatio:function (dampingRatio) { 142 this.getJointDef().dampingRatio = dampingRatio; 143 }, 144 145 /** 146 * Get the damping ratio from the joint definition. 147 * @return {Number} 148 */ 149 getDampingRatio:function () { 150 return this.getJointDef().dampingRatio; 151 }, 152 153 /** 154 * Set the maximum force to apply to the body when the mouse moves. 155 * @param force {Number} The force to apply 156 */ 157 setMaxForce:function (force) { 158 this.getJointDef().maxForce = force; 159 }, 160 161 /** 162 * Get the maximum force being applied when the mouse moves. 163 * @return {Number} 164 */ 165 getMaxForce:function () { 166 return this.getJointDef().maxForce; 167 }, 168 169 /** 170 * Updates the target position with the mouse location. 171 * @private 172 */ 173 execute:function (renderContext, time, dt) { 174 // Get the mouse info from the context 175 var mouseInfo = renderContext.getMouseInfo(); 176 if (!mouseInfo) { 177 AssertWarn("No mouse info on render context for MouseJoint"); 178 return; 179 } 180 181 if (this.getSimulation()) { 182 var p = R.clone(mouseInfo.position).div(R.physics.Simulation.WORLD_SIZE); 183 this.mousePos.Set(p.x, p.y); 184 this.getJoint().SetTarget(this.mousePos); 185 p.destroy(); 186 } 187 188 this.base(renderContext, time, dt); 189 } 190 191 }, { /** @scope R.components.physics.MouseJoint.prototype */ 192 193 /** 194 * Get the class name of this object 195 * 196 * @return {String} "R.components.physics.MouseJoint" 197 */ 198 getClassName:function () { 199 return "R.components.physics.MouseJoint"; 200 }, 201 202 /** @private */ 203 FORCE_FACTOR:300 204 }); 205 }