/*
* 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;
}
}