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 }