/* * Copyright (c) 2012, 2013 Hemanta Sapkota. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Hemanta Sapkota (laex.pearl@gmail.com) */ package com.laex.cg2d.render.impl; import com.badlogic.gdx.InputProcessor; import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.math.Vector3; import com.badlogic.gdx.physics.box2d.Body; import com.badlogic.gdx.physics.box2d.BodyDef; import com.badlogic.gdx.physics.box2d.BodyDef.BodyType; import com.badlogic.gdx.physics.box2d.Fixture; import com.badlogic.gdx.physics.box2d.QueryCallback; import com.badlogic.gdx.physics.box2d.joints.MouseJoint; import com.badlogic.gdx.physics.box2d.joints.MouseJointDef; import com.laex.cg2d.model.ScreenModel.CGShape; import com.laex.cg2d.render.ScreenScaffold; /** * MouseJointManager. Most of the code is from the LibGDX Box2d Tests. One * important thing to note is that, our camera uses a scale factor. Whenever * projecting and unprojecting hit point from camera, a scale factor should be * applied. Since we multiply the camera by a scaleFactor, for unprojecting, we * multiply the vector points by the inverse: 1/scaleFactor * * Note: this is no longer true. All scaling code has been removed. * * @author hemantasapkota * */ public class MouseJointManager implements ScreenScaffold, InputProcessor { /** The mouse joint installed. */ private boolean mouseJointInstalled; /** The ground body. */ private Body groundBody; /** The mouse joint. */ private MouseJoint mouseJoint; /** The hit body. */ private Body hitBody; /** The test point. */ Vector3 testPoint = new Vector3(); /** The target. */ Vector2 target = new Vector2(); /** The manipulator. */ private ScreenManagerImpl manipulator; /** The callback. */ QueryCallback callback = new QueryCallback() { @Override public boolean reportFixture(Fixture fixture) { // if the hit point is inside the fixture of the body // we report it if (fixture.testPoint(testPoint.x, testPoint.y)) { hitBody = fixture.getBody(); return false; } else return true; } }; /** * Instantiates a new mouse joint manager. * * @param manipulator * the manipulator */ public MouseJointManager(ScreenManagerImpl manipulator) { this.manipulator = manipulator; this.mouseJointInstalled = manipulator.model().getScreenPrefs().getDebugDrawPrefs().getInstallMouseJoint(); } /* * (non-Javadoc) * * @see com.laex.cg2d.render.IGameComponentManager#create() */ @Override public void create() { BodyDef bodyDef = new BodyDef(); groundBody = manipulator.world().createBody(bodyDef); groundBody.setUserData(CGShape.newBuilder().setId("groundBody").build()); } /* * (non-Javadoc) * * @see com.laex.cg2d.render.IGameComponentManager#render() */ @Override public void render() { } /* * (non-Javadoc) * * @see com.laex.cg2d.render.IGameComponentManager#dispose() */ @Override public void dispose() { hitBody = null; mouseJoint = null; manipulator.world().destroyBody(groundBody); groundBody = null; callback = null; } /* * (non-Javadoc) * * @see com.badlogic.gdx.InputProcessor#keyDown(int) */ @Override public boolean keyDown(int keycode) { return false; } /* * (non-Javadoc) * * @see com.badlogic.gdx.InputProcessor#keyUp(int) */ @Override public boolean keyUp(int keycode) { return false; } /* * (non-Javadoc) * * @see com.badlogic.gdx.InputProcessor#keyTyped(char) */ @Override public boolean keyTyped(char character) { return false; } /* * (non-Javadoc) * * @see com.badlogic.gdx.InputProcessor#touchDown(int, int, int, int) */ @Override public boolean touchDown(int x, int y, int pointer, int button) { if (!mouseJointInstalled) { return false; } // translate the mouse coordinates to world coordinates manipulator.camera().unproject(testPoint.set(x, y, 0)); // ask the world which bodies are within the given // bounding box around the mouse pointer hitBody = null; manipulator.world().QueryAABB(callback, testPoint.x - 0.0001f, testPoint.y - 0.0001f, testPoint.x + 0.0001f, testPoint.y + 0.0001f); if (hitBody == groundBody) { hitBody = null; } // ignore kinematic bodies, they don't work with the mouse joint if (hitBody != null && hitBody.getType() == BodyType.KinematicBody) { return false; } // if we hit something we create a new mouse joint // and attach it to the hit body. if (hitBody != null) { MouseJointDef def = new MouseJointDef(); def.bodyA = groundBody; def.bodyB = hitBody; def.collideConnected = true; def.target.set(testPoint.x, testPoint.y); def.maxForce = 1000.0f * hitBody.getMass(); mouseJoint = (MouseJoint) manipulator.world().createJoint(def); hitBody.setAwake(true); } return false; } /* * (non-Javadoc) * * @see com.badlogic.gdx.InputProcessor#touchUp(int, int, int, int) */ @Override public boolean touchUp(int x, int y, int pointer, int button) { if (!mouseJointInstalled) { return false; } // if a mouse joint exists we simply destroy it if (mouseJoint != null) { manipulator.world().destroyJoint(mouseJoint); mouseJoint = null; } return false; } /* * (non-Javadoc) * * @see com.badlogic.gdx.InputProcessor#touchDragged(int, int, int) */ @Override public boolean touchDragged(int x, int y, int pointer) { if (!mouseJointInstalled) { return false; } // if a mouse joint exists we simply update // the target of the joint based on the new // mouse coordinates if (mouseJoint != null) { manipulator.camera().unproject(testPoint.set(x, y, 0)); mouseJoint.setTarget(target.set(testPoint.x, testPoint.y)); } return false; } /* * (non-Javadoc) * * @see com.badlogic.gdx.InputProcessor#scrolled(int) */ @Override public boolean scrolled(int amount) { return false; } /* * (non-Javadoc) * * @see com.badlogic.gdx.InputProcessor#mouseMoved(int, int) */ @Override public boolean mouseMoved(int arg0, int arg1) { return false; } }