OSDN Git Service

Added pause and resume methods for Sound
[mikumikustudio/libgdx-mikumikustudio.git] / gdx / src / com / badlogic / gdx / physics / box2d / World.java
1 /*******************************************************************************\r
2  * Copyright 2011 See AUTHORS file.\r
3  * \r
4  * Licensed under the Apache License, Version 2.0 (the "License");\r
5  * you may not use this file except in compliance with the License.\r
6  * You may obtain a copy of the License at\r
7  * \r
8  *   http://www.apache.org/licenses/LICENSE-2.0\r
9  * \r
10  * Unless required by applicable law or agreed to in writing, software\r
11  * distributed under the License is distributed on an "AS IS" BASIS,\r
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
13  * See the License for the specific language governing permissions and\r
14  * limitations under the License.\r
15  ******************************************************************************/\r
16 \r
17 package com.badlogic.gdx.physics.box2d;\r
18 \r
19 import java.util.ArrayList;\r
20 import java.util.Iterator;\r
21 import java.util.List;\r
22 \r
23 import com.badlogic.gdx.math.Vector2;\r
24 import com.badlogic.gdx.physics.box2d.JointDef.JointType;\r
25 import com.badlogic.gdx.physics.box2d.joints.DistanceJoint;\r
26 import com.badlogic.gdx.physics.box2d.joints.DistanceJointDef;\r
27 import com.badlogic.gdx.physics.box2d.joints.FrictionJoint;\r
28 import com.badlogic.gdx.physics.box2d.joints.FrictionJointDef;\r
29 import com.badlogic.gdx.physics.box2d.joints.GearJoint;\r
30 import com.badlogic.gdx.physics.box2d.joints.GearJointDef;\r
31 import com.badlogic.gdx.physics.box2d.joints.MouseJoint;\r
32 import com.badlogic.gdx.physics.box2d.joints.MouseJointDef;\r
33 import com.badlogic.gdx.physics.box2d.joints.PrismaticJoint;\r
34 import com.badlogic.gdx.physics.box2d.joints.PrismaticJointDef;\r
35 import com.badlogic.gdx.physics.box2d.joints.PulleyJoint;\r
36 import com.badlogic.gdx.physics.box2d.joints.PulleyJointDef;\r
37 import com.badlogic.gdx.physics.box2d.joints.RevoluteJoint;\r
38 import com.badlogic.gdx.physics.box2d.joints.RevoluteJointDef;\r
39 import com.badlogic.gdx.physics.box2d.joints.RopeJoint;\r
40 import com.badlogic.gdx.physics.box2d.joints.RopeJointDef;\r
41 import com.badlogic.gdx.physics.box2d.joints.WeldJoint;\r
42 import com.badlogic.gdx.physics.box2d.joints.WeldJointDef;\r
43 import com.badlogic.gdx.physics.box2d.joints.WheelJoint;\r
44 import com.badlogic.gdx.physics.box2d.joints.WheelJointDef;\r
45 import com.badlogic.gdx.utils.Array;\r
46 import com.badlogic.gdx.utils.Disposable;\r
47 import com.badlogic.gdx.utils.LongMap;\r
48 import com.badlogic.gdx.utils.Pool;\r
49 \r
50 /** The world class manages all physics entities, dynamic simulation, and asynchronous queries. The world also contains efficient\r
51  * memory management facilities.\r
52  * @author mzechner */\r
53 public final class World implements Disposable {\r
54         // @off\r
55         /*JNI\r
56 #include <Box2D/Box2D.h>\r
57 \r
58 static jclass worldClass = 0;\r
59 static jmethodID shouldCollideID = 0;\r
60 static jmethodID beginContactID = 0;\r
61 static jmethodID endContactID = 0;\r
62 static jmethodID preSolveID = 0;\r
63 static jmethodID postSolveID = 0;\r
64 static jmethodID reportFixtureID = 0;\r
65 static jmethodID reportRayFixtureID = 0;\r
66 \r
67 class CustomRayCastCallback: public b2RayCastCallback\r
68 {\r
69 private:\r
70         JNIEnv* env;\r
71         jobject obj;\r
72 \r
73 public:\r
74         CustomRayCastCallback( JNIEnv *env, jobject obj )\r
75         {\r
76                 this->env = env;\r
77                 this->obj = obj;\r
78         }\r
79 \r
80         virtual float32 ReportFixture( b2Fixture* fixture, const b2Vec2& point, const b2Vec2& normal, float32 fraction)\r
81         {\r
82                 return env->CallFloatMethod(obj, reportRayFixtureID, (jlong)fixture, (jfloat)point.x, (jfloat)point.y,\r
83                                                                                                                                 (jfloat)normal.x, (jfloat)normal.y, (jfloat)fraction );\r
84         }\r
85 };\r
86 \r
87 class CustomContactFilter: public b2ContactFilter\r
88 {\r
89 private:\r
90         JNIEnv* env;\r
91         jobject obj;\r
92 \r
93 public:\r
94         CustomContactFilter( JNIEnv* env, jobject obj )\r
95         {\r
96                 this->env = env;\r
97                 this->obj = obj;\r
98         }\r
99 \r
100         virtual bool ShouldCollide(b2Fixture* fixtureA, b2Fixture* fixtureB)\r
101         {\r
102                 if( shouldCollideID != 0 )\r
103                         return env->CallBooleanMethod( obj, shouldCollideID, (jlong)fixtureA, (jlong)fixtureB );\r
104                 else\r
105                         return true;\r
106         }\r
107 };\r
108 \r
109 class CustomContactListener: public b2ContactListener\r
110 {\r
111 private:\r
112         JNIEnv* env;\r
113         jobject obj;\r
114 \r
115 public:\r
116                 CustomContactListener( JNIEnv* env, jobject obj )\r
117                 {\r
118                         this->env = env;\r
119                         this->obj = obj;\r
120                 }\r
121 \r
122                 /// Called when two fixtures begin to touch.\r
123                 virtual void BeginContact(b2Contact* contact)\r
124                 {\r
125                         if( beginContactID != 0 )\r
126                                 env->CallVoidMethod(obj, beginContactID, (jlong)contact );\r
127                 }\r
128 \r
129                 /// Called when two fixtures cease to touch.\r
130                 virtual void EndContact(b2Contact* contact)\r
131                 {\r
132                         if( endContactID != 0 )\r
133                                 env->CallVoidMethod(obj, endContactID, (jlong)contact);\r
134                 }\r
135                 \r
136                 /// This is called after a contact is updated.\r
137                 virtual void PreSolve(b2Contact* contact, const b2Manifold* oldManifold)\r
138                 {\r
139                         if( preSolveID != 0 )\r
140                                 env->CallVoidMethod(obj, preSolveID, (jlong)contact, (jlong)oldManifold);\r
141                 }\r
142         \r
143                 /// This lets you inspect a contact after the solver is finished.\r
144                 virtual void PostSolve(b2Contact* contact, const b2ContactImpulse* impulse)\r
145                 {\r
146                         if( postSolveID != 0 )\r
147                                 env->CallVoidMethod(obj, postSolveID, (jlong)contact, (jlong)impulse);\r
148                 }\r
149 };\r
150 \r
151 class CustomQueryCallback: public b2QueryCallback\r
152 {\r
153 private:\r
154         JNIEnv* env;\r
155         jobject obj;\r
156 \r
157 public:\r
158         CustomQueryCallback( JNIEnv* env, jobject obj )\r
159         {\r
160                 this->env = env;\r
161                 this->obj = obj;\r
162         }\r
163 \r
164         virtual bool ReportFixture( b2Fixture* fixture )\r
165         {\r
166                 return env->CallBooleanMethod(obj, reportFixtureID, (jlong)fixture );\r
167         }\r
168 }; \r
169 \r
170 inline b2BodyType getBodyType( int type )\r
171 {\r
172         switch( type )\r
173         {\r
174         case 0: return b2_staticBody;\r
175         case 1: return b2_kinematicBody;\r
176         case 2: return b2_dynamicBody;\r
177         default:\r
178                 return b2_staticBody;\r
179         }\r
180 }\r
181 \r
182 b2ContactFilter defaultFilter;\r
183          */\r
184         \r
185         /** pool for bodies **/\r
186         protected final Pool<Body> freeBodies = new Pool<Body>(100, 200) {\r
187                 @Override\r
188                 protected Body newObject () {\r
189                         return new Body(World.this, 0);\r
190                 }\r
191         };\r
192 \r
193         /** pool for fixtures **/\r
194         protected final Pool<Fixture> freeFixtures = new Pool<Fixture>(100, 200) {\r
195                 @Override\r
196                 protected Fixture newObject () {\r
197                         return new Fixture(null, 0);\r
198                 }\r
199         };\r
200 \r
201         /** the address of the world instance **/\r
202         private final long addr;\r
203 \r
204         /** all known bodies **/\r
205         protected final LongMap<Body> bodies = new LongMap<Body>(100);\r
206 \r
207         /** all known fixtures **/\r
208         protected final LongMap<Fixture> fixtures = new LongMap<Fixture>(100);\r
209 \r
210         /** all known joints **/\r
211         protected final LongMap<Joint> joints = new LongMap<Joint>(100);\r
212 \r
213         /** Contact filter **/\r
214         protected ContactFilter contactFilter = null;\r
215 \r
216         /** Contact listener **/\r
217         protected ContactListener contactListener = null;\r
218 \r
219         /** Construct a world object.\r
220          * @param gravity the world gravity vector.\r
221          * @param doSleep improve performance by not simulating inactive bodies. */\r
222         public World (Vector2 gravity, boolean doSleep) {\r
223                 addr = newWorld(gravity.x, gravity.y, doSleep);\r
224 \r
225                 contacts.ensureCapacity(contactAddrs.length);\r
226                 freeContacts.ensureCapacity(contactAddrs.length);\r
227 \r
228                 for (int i = 0; i < contactAddrs.length; i++)\r
229                         freeContacts.add(new Contact(this, 0));\r
230         }\r
231 \r
232         private native long newWorld (float gravityX, float gravityY, boolean doSleep); /*\r
233                 // we leak one global ref. \r
234                 if(!worldClass) {\r
235                         worldClass = (jclass)env->NewGlobalRef(env->GetObjectClass(object));\r
236                         beginContactID = env->GetMethodID(worldClass, "beginContact", "(J)V" );\r
237                         endContactID = env->GetMethodID( worldClass, "endContact", "(J)V" );\r
238                         preSolveID = env->GetMethodID( worldClass, "preSolve", "(JJ)V" );\r
239                         postSolveID = env->GetMethodID( worldClass, "postSolve", "(JJ)V" );\r
240                         reportFixtureID = env->GetMethodID(worldClass, "reportFixture", "(J)Z" );\r
241                         reportRayFixtureID = env->GetMethodID(worldClass, "reportRayFixture", "(JFFFFF)F" );\r
242                         shouldCollideID = env->GetMethodID( worldClass, "contactFilter", "(JJ)Z");\r
243                 }\r
244         \r
245                 b2World* world = new b2World( b2Vec2( gravityX, gravityY ));\r
246                 world->SetAllowSleeping( doSleep );\r
247                 return (jlong)world;\r
248         */\r
249 \r
250         /** Register a destruction listener. The listener is owned by you and must remain in scope. */\r
251         public void setDestructionListener (DestructionListener listener) {\r
252 \r
253         }\r
254 \r
255         /** Register a contact filter to provide specific control over collision. Otherwise the default filter is used\r
256          * (b2_defaultFilter). The listener is owned by you and must remain in scope. */\r
257         public void setContactFilter (ContactFilter filter) {\r
258                 this.contactFilter = filter;\r
259                 setUseDefaultContactFilter(filter == null);\r
260         }\r
261         \r
262         /** tells the native code not to call the Java world class if use is false **/\r
263         private native void setUseDefaultContactFilter(boolean use); /*\r
264                 // FIXME\r
265         */\r
266 \r
267         /** Register a contact event listener. The listener is owned by you and must remain in scope. */\r
268         public void setContactListener (ContactListener listener) {\r
269                 this.contactListener = listener;\r
270         }\r
271 \r
272         /** Create a rigid body given a definition. No reference to the definition is retained.\r
273          * @warning This function is locked during callbacks. */\r
274         public Body createBody (BodyDef def) {\r
275                 long bodyAddr = jniCreateBody(addr, def.type.getValue(), def.position.x, def.position.y, def.angle, def.linearVelocity.x,\r
276                         def.linearVelocity.y, def.angularVelocity, def.linearDamping, def.angularDamping, def.allowSleep, def.awake,\r
277                         def.fixedRotation, def.bullet, def.active, def.gravityScale);\r
278                 Body body = freeBodies.obtain();\r
279                 body.reset(bodyAddr);\r
280                 this.bodies.put(body.addr, body);\r
281                 return body;\r
282         }\r
283 \r
284         private native long jniCreateBody (long addr, int type, float positionX, float positionY, float angle, float linearVelocityX,\r
285                 float linearVelocityY, float angularVelocity, float linearDamping, float angularDamping, boolean allowSleep, boolean awake,\r
286                 boolean fixedRotation, boolean bullet, boolean active, float inertiaScale); /*\r
287                 b2BodyDef bodyDef;\r
288                 bodyDef.type = getBodyType(type);\r
289                 bodyDef.position.Set( positionX, positionY );\r
290                 bodyDef.angle = angle;\r
291                 bodyDef.linearVelocity.Set( linearVelocityX, linearVelocityY );\r
292                 bodyDef.angularVelocity = angularVelocity;\r
293                 bodyDef.linearDamping = linearDamping;\r
294                 bodyDef.angularDamping = angularDamping;\r
295                 bodyDef.allowSleep = allowSleep;\r
296                 bodyDef.awake = awake;\r
297                 bodyDef.fixedRotation = fixedRotation;\r
298                 bodyDef.bullet = bullet;\r
299                 bodyDef.active = active;\r
300                 bodyDef.gravityScale = inertiaScale;\r
301         \r
302                 b2World* world = (b2World*)addr;\r
303                 b2Body* body = world->CreateBody( &bodyDef );\r
304                 return (jlong)body;\r
305         */\r
306 \r
307         /** Destroy a rigid body given a definition. No reference to the definition is retained. This function is locked during\r
308          * callbacks.\r
309          * @warning This automatically deletes all associated shapes and joints.\r
310          * @warning This function is locked during callbacks. */\r
311         public void destroyBody (Body body) {\r
312                 body.setUserData(null);\r
313                 this.bodies.remove(body.addr);\r
314                 List<Fixture> fixtureList = body.getFixtureList();\r
315                 while(!fixtureList.isEmpty()) {\r
316                         this.fixtures.remove(fixtureList.remove(0).addr).setUserData(null);\r
317                 }\r
318                 List<JointEdge> jointList = body.getJointList();\r
319                 while (!jointList.isEmpty())\r
320                         destroyJoint(body.getJointList().get(0).joint);\r
321                 jniDestroyBody(addr, body.addr);\r
322                 freeBodies.free(body);\r
323         }\r
324 \r
325         private native void jniDestroyBody (long addr, long bodyAddr); /*\r
326                 b2World* world = (b2World*)addr;\r
327                 b2Body* body = (b2Body*)bodyAddr;\r
328                 CustomContactFilter contactFilter(env, object);\r
329                 CustomContactListener contactListener(env,object);\r
330                 world->SetContactFilter(&contactFilter);\r
331                 world->SetContactListener(&contactListener);\r
332                 world->DestroyBody(body);\r
333                 world->SetContactFilter(&defaultFilter);\r
334                 world->SetContactListener(0);\r
335         */\r
336 \r
337         /** Create a joint to constrain bodies together. No reference to the definition is retained. This may cause the connected bodies\r
338          * to cease colliding.\r
339          * @warning This function is locked during callbacks. */\r
340         public Joint createJoint (JointDef def) {\r
341                 long jointAddr = createProperJoint(def);\r
342                 Joint joint = null;\r
343                 if (def.type == JointType.DistanceJoint) joint = new DistanceJoint(this, jointAddr);\r
344                 if (def.type == JointType.FrictionJoint) joint = new FrictionJoint(this, jointAddr);\r
345                 if (def.type == JointType.GearJoint) joint = new GearJoint(this, jointAddr);\r
346                 if (def.type == JointType.MouseJoint) joint = new MouseJoint(this, jointAddr);\r
347                 if (def.type == JointType.PrismaticJoint) joint = new PrismaticJoint(this, jointAddr);\r
348                 if (def.type == JointType.PulleyJoint) joint = new PulleyJoint(this, jointAddr);\r
349                 if (def.type == JointType.RevoluteJoint) joint = new RevoluteJoint(this, jointAddr);\r
350                 if (def.type == JointType.WeldJoint) joint = new WeldJoint(this, jointAddr);\r
351                 if (def.type == JointType.RopeJoint) joint = new RopeJoint(this, jointAddr);\r
352                 if (def.type == JointType.WheelJoint) joint = new WheelJoint(this, jointAddr);\r
353                 if (joint != null) joints.put(joint.addr, joint);\r
354                 JointEdge jointEdgeA = new JointEdge(def.bodyB, joint);\r
355                 JointEdge jointEdgeB = new JointEdge(def.bodyA, joint);\r
356                 joint.jointEdgeA = jointEdgeA;\r
357                 joint.jointEdgeB = jointEdgeB;\r
358                 def.bodyA.joints.add(jointEdgeA);\r
359                 def.bodyB.joints.add(jointEdgeB);\r
360                 return joint;\r
361         }\r
362 \r
363         private long createProperJoint (JointDef def) {\r
364                 if (def.type == JointType.DistanceJoint) {\r
365                         DistanceJointDef d = (DistanceJointDef)def;\r
366                         return jniCreateDistanceJoint(addr, d.bodyA.addr, d.bodyB.addr, d.collideConnected, d.localAnchorA.x, d.localAnchorA.y,\r
367                                 d.localAnchorB.x, d.localAnchorB.y, d.length, d.frequencyHz, d.dampingRatio);\r
368                 }\r
369                 if (def.type == JointType.FrictionJoint) {\r
370                         FrictionJointDef d = (FrictionJointDef)def;\r
371                         return jniCreateFrictionJoint(addr, d.bodyA.addr, d.bodyB.addr, d.collideConnected, d.localAnchorA.x, d.localAnchorA.y,\r
372                                 d.localAnchorB.x, d.localAnchorB.y, d.maxForce, d.maxTorque);\r
373                 }\r
374                 if (def.type == JointType.GearJoint) {\r
375                         GearJointDef d = (GearJointDef)def;\r
376                         return jniCreateGearJoint(addr, d.bodyA.addr, d.bodyB.addr, d.collideConnected, d.joint1.addr, d.joint2.addr, d.ratio);\r
377                 }\r
378                 if (def.type == JointType.MouseJoint) {\r
379                         MouseJointDef d = (MouseJointDef)def;\r
380                         return jniCreateMouseJoint(addr, d.bodyA.addr, d.bodyB.addr, d.collideConnected, d.target.x, d.target.y, d.maxForce,\r
381                                 d.frequencyHz, d.dampingRatio);\r
382                 }\r
383                 if (def.type == JointType.PrismaticJoint) {\r
384                         PrismaticJointDef d = (PrismaticJointDef)def;\r
385                         return jniCreatePrismaticJoint(addr, d.bodyA.addr, d.bodyB.addr, d.collideConnected, d.localAnchorA.x, d.localAnchorA.y,\r
386                                 d.localAnchorB.x, d.localAnchorB.y, d.localAxisA.x, d.localAxisA.y, d.referenceAngle, d.enableLimit,\r
387                                 d.lowerTranslation, d.upperTranslation, d.enableMotor, d.maxMotorForce, d.motorSpeed);\r
388                 }\r
389                 if (def.type == JointType.PulleyJoint) {\r
390                         PulleyJointDef d = (PulleyJointDef)def;\r
391                         return jniCreatePulleyJoint(addr, d.bodyA.addr, d.bodyB.addr, d.collideConnected, d.groundAnchorA.x, d.groundAnchorA.y,\r
392                                 d.groundAnchorB.x, d.groundAnchorB.y, d.localAnchorA.x, d.localAnchorA.y, d.localAnchorB.x, d.localAnchorB.y,\r
393                                 d.lengthA, d.lengthB, d.ratio);\r
394 \r
395                 }\r
396                 if (def.type == JointType.RevoluteJoint) {\r
397                         RevoluteJointDef d = (RevoluteJointDef)def;\r
398                         return jniCreateRevoluteJoint(addr, d.bodyA.addr, d.bodyB.addr, d.collideConnected, d.localAnchorA.x, d.localAnchorA.y,\r
399                                 d.localAnchorB.x, d.localAnchorB.y, d.referenceAngle, d.enableLimit, d.lowerAngle, d.upperAngle, d.enableMotor,\r
400                                 d.motorSpeed, d.maxMotorTorque);\r
401                 }\r
402                 if (def.type == JointType.WeldJoint) {\r
403                         WeldJointDef d = (WeldJointDef)def;\r
404                         return jniCreateWeldJoint(addr, d.bodyA.addr, d.bodyB.addr, d.collideConnected, d.localAnchorA.x, d.localAnchorA.y,\r
405                                 d.localAnchorB.x, d.localAnchorB.y, d.referenceAngle);\r
406                 }\r
407                 if (def.type == JointType.RopeJoint) {\r
408                         RopeJointDef d = (RopeJointDef)def;\r
409                         return jniCreateRopeJoint(addr, d.bodyA.addr, d.bodyB.addr, d.collideConnected, d.localAnchorA.x, d.localAnchorA.y,\r
410                                 d.localAnchorB.x, d.localAnchorB.y, d.maxLength);\r
411                 }\r
412                 if (def.type == JointType.WheelJoint) {\r
413                         WheelJointDef d = (WheelJointDef)def;\r
414                         return jniCreateWheelJoint(addr, d.bodyA.addr, d.bodyB.addr, d.collideConnected, d.localAnchorA.x, d.localAnchorA.y,\r
415                                 d.localAnchorB.x, d.localAnchorB.y, d.localAxisA.x, d.localAxisA.y, d.enableMotor, d.maxMotorTorque, d.motorSpeed,\r
416                                 d.frequencyHz, d.dampingRatio);\r
417                 }\r
418 \r
419                 return 0;\r
420         }\r
421 \r
422         private native long jniCreateWheelJoint (long addr, long bodyA, long bodyB, boolean collideConnected, float localAnchorAX,\r
423                 float localAnchorAY, float localAnchorBX, float localAnchorBY, float localAxisAX, float localAxisAY, boolean enableMotor,\r
424                 float maxMotorTorque, float motorSpeed, float frequencyHz, float dampingRatio); /*\r
425                 b2World* world = (b2World*)addr;\r
426                 b2WheelJointDef def;\r
427                 def.bodyA = (b2Body*)bodyA;\r
428                 def.bodyB = (b2Body*)bodyB;\r
429                 def.collideConnected = collideConnected;\r
430                 def.localAnchorA = b2Vec2(localAnchorAX, localAnchorAY);\r
431                 def.localAnchorB = b2Vec2(localAnchorBX, localAnchorBY);\r
432                 def.localAxisA = b2Vec2(localAxisAX, localAxisAY);\r
433                 def.enableMotor = enableMotor;\r
434                 def.maxMotorTorque = maxMotorTorque;\r
435                 def.motorSpeed = motorSpeed;\r
436                 def.frequencyHz = frequencyHz;\r
437                 def.dampingRatio = dampingRatio;\r
438                 \r
439                 return (jlong)world->CreateJoint(&def);\r
440         */\r
441 \r
442         private native long jniCreateRopeJoint (long addr, long bodyA, long bodyB, boolean collideConnected, float localAnchorAX,\r
443                 float localAnchorAY, float localAnchorBX, float localAnchorBY, float maxLength); /*\r
444                 b2World* world = (b2World*)addr;\r
445                 b2RopeJointDef def;\r
446                 def.bodyA = (b2Body*)bodyA;\r
447                 def.bodyB = (b2Body*)bodyB;\r
448                 def.collideConnected = collideConnected;\r
449                 def.localAnchorA = b2Vec2(localAnchorAX, localAnchorAY);\r
450                 def.localAnchorB = b2Vec2(localAnchorBX, localAnchorBY);\r
451                 def.maxLength = maxLength;\r
452         \r
453                 return (jlong)world->CreateJoint(&def);\r
454         */\r
455 \r
456         private native long jniCreateDistanceJoint (long addr, long bodyA, long bodyB, boolean collideConnected, float localAnchorAX,\r
457                 float localAnchorAY, float localAnchorBX, float localAnchorBY, float length, float frequencyHz, float dampingRatio); /*\r
458                 b2World* world = (b2World*)addr;\r
459                 b2DistanceJointDef def;\r
460                 def.bodyA = (b2Body*)bodyA;\r
461                 def.bodyB = (b2Body*)bodyB;\r
462                 def.collideConnected = collideConnected;\r
463                 def.localAnchorA = b2Vec2(localAnchorAX, localAnchorAY);\r
464                 def.localAnchorB = b2Vec2(localAnchorBX, localAnchorBY);\r
465                 def.length = length;\r
466                 def.frequencyHz = frequencyHz;\r
467                 def.dampingRatio = dampingRatio;\r
468         \r
469                 return (jlong)world->CreateJoint(&def);\r
470         */\r
471 \r
472         private native long jniCreateFrictionJoint (long addr, long bodyA, long bodyB, boolean collideConnected, float localAnchorAX,\r
473                 float localAnchorAY, float localAnchorBX, float localAnchorBY, float maxForce, float maxTorque); /*\r
474                 b2World* world = (b2World*)addr;\r
475                 b2FrictionJointDef def;\r
476                 def.bodyA = (b2Body*)bodyA;\r
477                 def.bodyB = (b2Body*)bodyB;\r
478                 def.collideConnected = collideConnected;\r
479                 def.localAnchorA = b2Vec2(localAnchorAX, localAnchorAY);\r
480                 def.localAnchorB = b2Vec2(localAnchorBX, localAnchorBY);\r
481                 def.maxForce = maxForce;\r
482                 def.maxTorque = maxTorque;\r
483                 return (jlong)world->CreateJoint(&def);\r
484         */\r
485 \r
486         private native long jniCreateGearJoint (long addr, long bodyA, long bodyB, boolean collideConnected, long joint1, long joint2,\r
487                 float ratio); /*\r
488                 b2World* world = (b2World*)addr;\r
489                 b2GearJointDef def;\r
490                 def.bodyA = (b2Body*)bodyA;\r
491                 def.bodyB = (b2Body*)bodyB;\r
492                 def.collideConnected = collideConnected;\r
493                 def.joint1 = (b2Joint*)joint1;\r
494                 def.joint2 = (b2Joint*)joint2;\r
495                 def.ratio = ratio;\r
496                 return (jlong)world->CreateJoint(&def);\r
497         */\r
498 \r
499         private native long jniCreateMouseJoint (long addr, long bodyA, long bodyB, boolean collideConnected, float targetX,\r
500                 float targetY, float maxForce, float frequencyHz, float dampingRatio); /*\r
501                 b2World* world = (b2World*)addr;\r
502                 b2MouseJointDef def;\r
503                 def.bodyA = (b2Body*)bodyA;\r
504                 def.bodyB = (b2Body*)bodyB;\r
505                 def.collideConnected = collideConnected;\r
506                 def.target = b2Vec2( targetX, targetY );\r
507                 def.maxForce = maxForce;\r
508                 def.frequencyHz = frequencyHz;\r
509                 def.dampingRatio = dampingRatio;\r
510                 return (jlong)world->CreateJoint(&def);\r
511         */\r
512 \r
513         private native long jniCreatePrismaticJoint (long addr, long bodyA, long bodyB, boolean collideConnected, float localAnchorAX,\r
514                 float localAnchorAY, float localAnchorBX, float localAnchorBY, float localAxisAX, float localAxisAY, float referenceAngle,\r
515                 boolean enableLimit, float lowerTranslation, float upperTranslation, boolean enableMotor, float maxMotorForce,\r
516                 float motorSpeed); /*\r
517                 b2World* world = (b2World*)addr;\r
518                 b2PrismaticJointDef def;\r
519                 def.bodyA = (b2Body*)bodyA;\r
520                 def.bodyB = (b2Body*)bodyB;\r
521                 def.collideConnected = collideConnected;\r
522                 def.localAnchorA = b2Vec2(localAnchorAX, localAnchorAY);\r
523                 def.localAnchorB = b2Vec2(localAnchorBX, localAnchorBY);\r
524                 def.localAxisA = b2Vec2( localAxisAX, localAxisAY );\r
525                 def.referenceAngle = referenceAngle;\r
526                 def.enableLimit = enableLimit;\r
527                 def.lowerTranslation = lowerTranslation;\r
528                 def.upperTranslation = upperTranslation;\r
529                 def.enableMotor = enableMotor;\r
530                 def.maxMotorForce = maxMotorForce;\r
531                 def.motorSpeed = motorSpeed;\r
532                 return (jlong)world->CreateJoint(&def);\r
533         */\r
534 \r
535         private native long jniCreatePulleyJoint (long addr, long bodyA, long bodyB, boolean collideConnected, float groundAnchorAX,\r
536                 float groundAnchorAY, float groundAnchorBX, float groundAnchorBY, float localAnchorAX, float localAnchorAY,\r
537                 float localAnchorBX, float localAnchorBY, float lengthA, float lengthB, float ratio); /*\r
538                 b2World* world = (b2World*)addr;\r
539                 b2PulleyJointDef def;\r
540                 def.bodyA = (b2Body*)bodyA;\r
541                 def.bodyB = (b2Body*)bodyB;\r
542                 def.collideConnected = collideConnected;\r
543                 def.groundAnchorA = b2Vec2( groundAnchorAX, groundAnchorAY );\r
544                 def.groundAnchorB = b2Vec2( groundAnchorBX, groundAnchorBY );\r
545                 def.localAnchorA = b2Vec2(localAnchorAX, localAnchorAY);\r
546                 def.localAnchorB = b2Vec2(localAnchorBX, localAnchorBY);\r
547                 def.lengthA = lengthA;\r
548                 def.lengthB = lengthB;\r
549                 def.ratio = ratio;\r
550         \r
551                 return (jlong)world->CreateJoint(&def);\r
552         */\r
553 \r
554         private native long jniCreateRevoluteJoint (long addr, long bodyA, long bodyB, boolean collideConnected, float localAnchorAX,\r
555                 float localAnchorAY, float localAnchorBX, float localAnchorBY, float referenceAngle, boolean enableLimit, float lowerAngle,\r
556                 float upperAngle, boolean enableMotor, float motorSpeed, float maxMotorTorque); /*\r
557                 b2World* world = (b2World*)addr;\r
558                 b2RevoluteJointDef def;\r
559                 def.bodyA = (b2Body*)bodyA;\r
560                 def.bodyB = (b2Body*)bodyB;\r
561                 def.collideConnected = collideConnected;\r
562                 def.localAnchorA = b2Vec2(localAnchorAX, localAnchorAY);\r
563                 def.localAnchorB = b2Vec2(localAnchorBX, localAnchorBY);\r
564                 def.referenceAngle = referenceAngle;\r
565                 def.enableLimit = enableLimit;\r
566                 def.lowerAngle = lowerAngle;\r
567                 def.upperAngle = upperAngle;\r
568                 def.enableMotor = enableMotor;\r
569                 def.motorSpeed = motorSpeed;\r
570                 def.maxMotorTorque = maxMotorTorque;\r
571                 return (jlong)world->CreateJoint(&def);\r
572         */\r
573 \r
574         private native long jniCreateWeldJoint (long addr, long bodyA, long bodyB, boolean collideConnected, float localAnchorAX,\r
575                 float localAnchorAY, float localAnchorBX, float localAnchorBY, float referenceAngle); /*\r
576                 b2World* world = (b2World*)addr;\r
577                 b2WeldJointDef def;\r
578                 def.bodyA = (b2Body*)bodyA;\r
579                 def.bodyB = (b2Body*)bodyB;\r
580                 def.collideConnected = collideConnected;\r
581                 def.localAnchorA = b2Vec2(localAnchorAX, localAnchorAY);\r
582                 def.localAnchorB = b2Vec2(localAnchorBX, localAnchorBY);\r
583                 def.referenceAngle = referenceAngle;\r
584         \r
585                 return (jlong)world->CreateJoint(&def);\r
586         */\r
587 \r
588         /** Destroy a joint. This may cause the connected bodies to begin colliding.\r
589          * @warning This function is locked during callbacks. */\r
590         public void destroyJoint (Joint joint) {\r
591                 joint.setUserData(null);\r
592                 joints.remove(joint.addr);\r
593                 joint.jointEdgeA.other.joints.remove(joint.jointEdgeB);\r
594                 joint.jointEdgeB.other.joints.remove(joint.jointEdgeA);\r
595                 jniDestroyJoint(addr, joint.addr);\r
596         }\r
597 \r
598         private native void jniDestroyJoint (long addr, long jointAddr); /*\r
599                 b2World* world = (b2World*)addr;\r
600                 b2Joint* joint = (b2Joint*)jointAddr;\r
601                 CustomContactFilter contactFilter(env, object);\r
602                 CustomContactListener contactListener(env,object);\r
603                 world->SetContactFilter(&contactFilter);\r
604                 world->SetContactListener(&contactListener);\r
605                 world->DestroyJoint( joint );\r
606                 world->SetContactFilter(&defaultFilter);\r
607                 world->SetContactListener(0);\r
608         */\r
609 \r
610         /** Take a time step. This performs collision detection, integration, and constraint solution.\r
611          * @param timeStep the amount of time to simulate, this should not vary.\r
612          * @param velocityIterations for the velocity constraint solver.\r
613          * @param positionIterations for the position constraint solver. */\r
614         public void step (float timeStep, int velocityIterations, int positionIterations) {\r
615                 jniStep(addr, timeStep, velocityIterations, positionIterations);\r
616         }\r
617 \r
618         private native void jniStep (long addr, float timeStep, int velocityIterations, int positionIterations); /*\r
619                 b2World* world = (b2World*)addr;\r
620                 CustomContactFilter contactFilter(env, object);\r
621                 CustomContactListener contactListener(env,object);\r
622                 world->SetContactFilter(&contactFilter);\r
623                 world->SetContactListener(&contactListener);\r
624                 world->Step( timeStep, velocityIterations, positionIterations );\r
625                 world->SetContactFilter(&defaultFilter);\r
626                 world->SetContactListener(0);\r
627         */\r
628 \r
629         /** Manually clear the force buffer on all bodies. By default, forces are cleared automatically after each call to Step. The\r
630          * default behavior is modified by calling SetAutoClearForces. The purpose of this function is to support sub-stepping.\r
631          * Sub-stepping is often used to maintain a fixed sized time step under a variable frame-rate. When you perform sub-stepping\r
632          * you will disable auto clearing of forces and instead call ClearForces after all sub-steps are complete in one pass of your\r
633          * game loop. {@link #setAutoClearForces(boolean)} */\r
634         public void clearForces () {\r
635                 jniClearForces(addr);\r
636         }\r
637 \r
638         private native void jniClearForces (long addr); /*\r
639                 b2World* world = (b2World*)addr;\r
640                 world->ClearForces();\r
641         */\r
642 \r
643         /** Enable/disable warm starting. For testing. */\r
644         public void setWarmStarting (boolean flag) {\r
645                 jniSetWarmStarting(addr, flag);\r
646         }\r
647 \r
648         private native void jniSetWarmStarting (long addr, boolean flag); /*\r
649                 b2World* world = (b2World*)addr;\r
650                 world->SetWarmStarting(flag);\r
651         */\r
652 \r
653         /** Enable/disable continuous physics. For testing. */\r
654         public void setContinuousPhysics (boolean flag) {\r
655                 jniSetContiousPhysics(addr, flag);\r
656         }\r
657 \r
658         private native void jniSetContiousPhysics (long addr, boolean flag); /*\r
659                 b2World* world = (b2World*)addr;\r
660                 world->SetContinuousPhysics(flag);\r
661         */\r
662 \r
663         /** Get the number of broad-phase proxies. */\r
664         public int getProxyCount () {\r
665                 return jniGetProxyCount(addr);\r
666         }\r
667 \r
668         private native int jniGetProxyCount (long addr); /*\r
669                 b2World* world = (b2World*)addr;\r
670                 return world->GetProxyCount();\r
671         */\r
672 \r
673         /** Get the number of bodies. */\r
674         public int getBodyCount () {\r
675                 return jniGetBodyCount(addr);\r
676         }\r
677 \r
678         private native int jniGetBodyCount (long addr); /*\r
679                 b2World* world = (b2World*)addr;\r
680                 return world->GetBodyCount();\r
681         */\r
682 \r
683         /** Get the number of joints. */\r
684         public int getJointCount () {\r
685                 return jniGetJointcount(addr);\r
686         }\r
687 \r
688         private native int jniGetJointcount (long addr); /*\r
689                 b2World* world = (b2World*)addr;\r
690                 return world->GetJointCount();\r
691         */\r
692 \r
693         /** Get the number of contacts (each may have 0 or more contact points). */\r
694         public int getContactCount () {\r
695                 return jniGetContactCount(addr);\r
696         }\r
697 \r
698         private native int jniGetContactCount (long addr); /*\r
699                 b2World* world = (b2World*)addr;\r
700                 return world->GetContactCount();\r
701         */\r
702 \r
703         /** Change the global gravity vector. */\r
704         public void setGravity (Vector2 gravity) {\r
705                 jniSetGravity(addr, gravity.x, gravity.y);\r
706         }\r
707 \r
708         private native void jniSetGravity (long addr, float gravityX, float gravityY); /*\r
709                 b2World* world = (b2World*)addr;\r
710                 world->SetGravity( b2Vec2( gravityX, gravityY ) );\r
711         */\r
712 \r
713         /** Get the global gravity vector. */\r
714         final float[] tmpGravity = new float[2];\r
715         final Vector2 gravity = new Vector2();\r
716 \r
717         public Vector2 getGravity () {\r
718                 jniGetGravity(addr, tmpGravity);\r
719                 gravity.x = tmpGravity[0];\r
720                 gravity.y = tmpGravity[1];\r
721                 return gravity;\r
722         }\r
723 \r
724         private native void jniGetGravity (long addr, float[] gravity); /*\r
725                 b2World* world = (b2World*)addr;\r
726                 b2Vec2 g = world->GetGravity();\r
727                 gravity[0] = g.x;\r
728                 gravity[1] = g.y;\r
729         */\r
730 \r
731         /** Is the world locked (in the middle of a time step). */\r
732         public boolean isLocked () {\r
733                 return jniIsLocked(addr);\r
734         }\r
735 \r
736         private native boolean jniIsLocked (long addr); /*\r
737                 b2World* world = (b2World*)addr;\r
738                 return world->IsLocked();\r
739         */\r
740 \r
741         /** Set flag to control automatic clearing of forces after each time step. */\r
742         public void setAutoClearForces (boolean flag) {\r
743                 jniSetAutoClearForces(addr, flag);\r
744         }\r
745 \r
746         private native void jniSetAutoClearForces (long addr, boolean flag); /*\r
747                 b2World* world = (b2World*)addr;\r
748                 world->SetAutoClearForces(flag);\r
749         */\r
750 \r
751         /** Get the flag that controls automatic clearing of forces after each time step. */\r
752         public boolean getAutoClearForces () {\r
753                 return jniGetAutoClearForces(addr);\r
754         }\r
755 \r
756         private native boolean jniGetAutoClearForces (long addr); /*\r
757                 b2World* world = (b2World*)addr;\r
758                 return world->GetAutoClearForces();\r
759         */\r
760 \r
761         /** Query the world for all fixtures that potentially overlap the provided AABB.\r
762          * @param callback a user implemented callback class.\r
763          * @param lowerX the x coordinate of the lower left corner\r
764          * @param lowerY the y coordinate of the lower left corner\r
765          * @param upperX the x coordinate of the upper right corner\r
766          * @param upperY the y coordinate of the upper right corner */\r
767         public void QueryAABB (QueryCallback callback, float lowerX, float lowerY, float upperX, float upperY) {\r
768                 queryCallback = callback;\r
769                 jniQueryAABB(addr, lowerX, lowerY, upperX, upperY);\r
770         }\r
771 \r
772         private QueryCallback queryCallback = null;;\r
773 \r
774         private native void jniQueryAABB (long addr, float lowX, float lowY, float upX, float upY); /*\r
775                 b2World* world = (b2World*)addr;\r
776                 b2AABB aabb;\r
777                 aabb.lowerBound = b2Vec2( lowX, lowY );\r
778                 aabb.upperBound = b2Vec2( upX, upY );\r
779         \r
780                 CustomQueryCallback callback( env, object );\r
781                 world->QueryAABB( &callback, aabb );\r
782         */\r
783 \r
784 //\r
785 // /// Ray-cast the world for all fixtures in the path of the ray. Your callback\r
786 // /// controls whether you get the closest point, any point, or n-points.\r
787 // /// The ray-cast ignores shapes that contain the starting point.\r
788 // /// @param callback a user implemented callback class.\r
789 // /// @param point1 the ray starting point\r
790 // /// @param point2 the ray ending point\r
791 // void RayCast(b2RayCastCallback* callback, const b2Vec2& point1, const b2Vec2& point2) const;\r
792 //\r
793 // /// Get the world contact list. With the returned contact, use b2Contact::GetNext to get\r
794 // /// the next contact in the world list. A NULL contact indicates the end of the list.\r
795 // /// @return the head of the world contact list.\r
796 // /// @warning contacts are\r
797 // b2Contact* GetContactList();\r
798 \r
799         private long[] contactAddrs = new long[200];\r
800         private final ArrayList<Contact> contacts = new ArrayList<Contact>();\r
801         private final ArrayList<Contact> freeContacts = new ArrayList<Contact>();\r
802 \r
803         /** Returns the list of {@link Contact} instances produced by the last call to {@link #step(float, int, int)}. Note that the\r
804          * returned list will have O(1) access times when using indexing. contacts are created and destroyed in the middle of a time\r
805          * step. Use {@link ContactListener} to avoid missing contacts\r
806          * @return the contact list */\r
807         public List<Contact> getContactList () {\r
808                 int numContacts = getContactCount();\r
809                 if (numContacts > contactAddrs.length) {\r
810                         int newSize = 2 * numContacts;\r
811                         contactAddrs = new long[newSize];\r
812                         contacts.ensureCapacity(newSize);\r
813                         freeContacts.ensureCapacity(newSize);\r
814                 }\r
815                 if (numContacts > freeContacts.size()) {\r
816                         int freeConts = freeContacts.size();\r
817                         for (int i = 0; i < numContacts - freeConts; i++)\r
818                                 freeContacts.add(new Contact(this, 0));\r
819                 }\r
820                 jniGetContactList(addr, contactAddrs);\r
821 \r
822                 contacts.clear();\r
823                 for (int i = 0; i < numContacts; i++) {\r
824                         Contact contact = freeContacts.get(i);\r
825                         contact.addr = contactAddrs[i];\r
826                         contacts.add(contact);\r
827                 }\r
828 \r
829                 return contacts;\r
830         }\r
831 \r
832         /** @param bodies an Array in which to place all bodies currently in the simulation */\r
833         public void getBodies (Array<Body> bodies) {\r
834                 bodies.clear();\r
835                 bodies.ensureCapacity(this.bodies.size);\r
836                 for (Iterator<Body> iter = this.bodies.values(); iter.hasNext();) {\r
837                         bodies.add(iter.next());\r
838                 }               \r
839         }\r
840 \r
841         /** @param joints an Array in which to place all joints currently in the simulation */\r
842         public void getJoints (Array<Joint> joints) {\r
843                 joints.clear();\r
844                 joints.ensureCapacity(this.joints.size);\r
845                 for (Iterator<Joint> iter = this.joints.values(); iter.hasNext();) {\r
846                         joints.add(iter.next());\r
847                 }\r
848         }\r
849 \r
850         private native void jniGetContactList (long addr, long[] contacts); /*\r
851                 b2World* world = (b2World*)addr;\r
852         \r
853                 b2Contact* contact = world->GetContactList();\r
854                 int i = 0;\r
855                 while( contact != 0 )\r
856                 {\r
857                         contacts[i++] = (long long)contact;\r
858                         contact = contact->GetNext();\r
859                 }\r
860         */\r
861 \r
862         public void dispose () {\r
863                 jniDispose(addr);\r
864         }\r
865 \r
866         private native void jniDispose (long addr); /*\r
867                 b2World* world = (b2World*)(addr);\r
868                 delete world;\r
869         */\r
870 \r
871         /** Internal method called from JNI in case a contact happens\r
872          * @param fixtureA\r
873          * @param fixtureB\r
874          * @return whether the things collided */\r
875         private boolean contactFilter (long fixtureA, long fixtureB) {\r
876                 if (contactFilter != null)\r
877                         return contactFilter.shouldCollide(fixtures.get(fixtureA), fixtures.get(fixtureB));\r
878                 else {\r
879                         Filter filterA = fixtures.get(fixtureA).getFilterData();\r
880                         Filter filterB = fixtures.get(fixtureB).getFilterData();\r
881 \r
882                         if (filterA.groupIndex == filterB.groupIndex && filterA.groupIndex != 0) {\r
883                                 return filterA.groupIndex > 0;\r
884                         }\r
885 \r
886                         boolean collide = (filterA.maskBits & filterB.categoryBits) != 0 && (filterA.categoryBits & filterB.maskBits) != 0;\r
887                         return collide;\r
888                 }\r
889         }\r
890 \r
891         private final Contact contact = new Contact(this, 0);\r
892         private final Manifold manifold = new Manifold(0);\r
893         private final ContactImpulse impulse = new ContactImpulse(this, 0);\r
894 \r
895         private void beginContact (long contactAddr) {\r
896                 contact.addr = contactAddr;\r
897                 if (contactListener != null) contactListener.beginContact(contact);\r
898         }\r
899 \r
900         private void endContact (long contactAddr) {\r
901                 contact.addr = contactAddr;\r
902                 if (contactListener != null) contactListener.endContact(contact);\r
903         }\r
904 \r
905         private void preSolve (long contactAddr, long manifoldAddr) {\r
906                 contact.addr = contactAddr;\r
907                 manifold.addr = manifoldAddr;\r
908                 if (contactListener != null) contactListener.preSolve(contact, manifold);\r
909         }\r
910 \r
911         private void postSolve (long contactAddr, long impulseAddr) {\r
912                 contact.addr = contactAddr;\r
913                 impulse.addr = impulseAddr;\r
914                 if (contactListener != null) contactListener.postSolve(contact, impulse);\r
915         }\r
916 \r
917         private boolean reportFixture (long addr) {\r
918                 if (queryCallback != null)\r
919                         return queryCallback.reportFixture(fixtures.get(addr));\r
920                 else\r
921                         return false;\r
922         }\r
923 \r
924         /** Sets the box2d velocity threshold globally, for all World instances.\r
925          * @param threshold the threshold, default 1.0f */\r
926         public static native void setVelocityThreshold (float threshold); /*\r
927                 b2_velocityThreshold = threshold;\r
928         */\r
929 \r
930         /** @return the global box2d velocity threshold. */\r
931         public static native float getVelocityThreshold (); /*\r
932                 return b2_velocityThreshold;\r
933         */\r
934         \r
935         /** Ray-cast the world for all fixtures in the path of the ray. The ray-cast ignores shapes that contain the starting point.\r
936          * @param callback a user implemented callback class.\r
937          * @param point1 the ray starting point\r
938          * @param point2 the ray ending point */\r
939         public void rayCast (RayCastCallback callback, Vector2 point1, Vector2 point2) {\r
940                 rayCastCallback = callback;\r
941                 jniRayCast(addr, point1.x, point1.y, point2.x, point2.y);\r
942         }\r
943 \r
944         private RayCastCallback rayCastCallback = null;\r
945 \r
946         private native void jniRayCast (long addr, float aX, float aY, float bX, float bY); /*\r
947                 b2World *world = (b2World*)addr;\r
948                 CustomRayCastCallback callback( env, object );  \r
949                 world->RayCast( &callback, b2Vec2(aX,aY), b2Vec2(bX,bY) );\r
950         */\r
951 \r
952         private Vector2 rayPoint = new Vector2();\r
953         private Vector2 rayNormal = new Vector2();\r
954 \r
955         private float reportRayFixture (long addr, float pX, float pY, float nX, float nY, float fraction) {\r
956                 if (rayCastCallback != null) {\r
957                         rayPoint.x = pX;\r
958                         rayPoint.y = pY;\r
959                         rayNormal.x = nX;\r
960                         rayNormal.y = nY;\r
961                         return rayCastCallback.reportRayFixture(fixtures.get(addr), rayPoint, rayNormal, fraction);\r
962                 } else {\r
963                         return 0.0f;\r
964                 }\r
965         }\r
966 }\r