<commit_before>package com.bitwaffle.spaceguts.entities;

import javax.vecmath.Quat4f;

import org.lwjgl.opengl.GL11;
import org.lwjgl.util.vector.Quaternion;
import org.lwjgl.util.vector.Vector3f;


import com.bitwaffle.spaceguts.graphics.render.Render3D;
import com.bitwaffle.spaceguts.input.KeyBindings;
import com.bitwaffle.spaceguts.input.MouseManager;
import com.bitwaffle.spaceguts.physics.Builder;
import com.bitwaffle.spaceguts.physics.CollisionTypes;
import com.bitwaffle.spaceguts.physics.Physics;
import com.bitwaffle.spaceguts.util.DisplayHelper;
import com.bitwaffle.spaceguts.util.QuaternionHelper;
import com.bitwaffle.spaceguts.util.console.Console;
import com.bitwaffle.spaceout.resources.Textures;
import com.bulletphysics.collision.dispatch.CollisionWorld.ClosestRayResultCallback;
import com.bulletphysics.collision.shapes.SphereShape;
import com.bulletphysics.linearmath.Transform;

/**
 * A camera that describes how the scene is being looked at and can move around inside of the physics world
 * There should only be one camera at a time, Entities.camera
 * 
 * @author TranquilMarmot
 */
public class Camera extends DynamicEntity {
	/** initial values for when the camera is created */
	private static final float INIT_ZOOM = 12.0f;
	private static final float INIT_XOFFSET = 0.0f;
	private static final float INIT_YOFFSET = -2.7F;

	/** the entity that the camera is following */
	public Entity following;
	
	/** handles special interactions with the game world */
	public Builder builder;

	/** how fast the camera moves in free mode */
	public float speed = 350.0f;
	private float maxSpeed = 10000.0f, minSpeed = 0.01f;

	/** Offset along Y axis */
	public float yOffset;
	/** Offset along X axis */
	public float xOffset;
	
	/** used to preserve offset when switching modes */
	private float oldYOffset, oldXOffset, oldMinZoom;

	/** zoom level */
	public float zoom;
	/** maximum and minimum zoom level */
	private float maxZoom = 3000.0f, minZoom = 10.0f;
	/** changes how fast the zoom is based on the current zoom distance */
	float zoomSensitivity = 10;
	private float oldZoom;
	
	/** for switching into/out of build mode */
	private Vector3f oldLocation = new Vector3f(0.0f, 0.0f, 0.0f);

	/**
	 * The camera has three main modes:
	 * 	Normal Mode - vanityMode = false, freeMode = false
	 * 		Camera simply follows behind whatever it's attached to
	 * 	Vanity Mode - vanityMode = true, freeMode = false
	 * 		Camera spins around whatever it's following
	 * 	Free Mode - vanityMode = false, freeMode = true
	 * 		Camera can move about freely on its own and zoom out real far
	 */
	// FIXME there's a more clever way to do this- it could easily be a short with each bit representing a mode- 00 would be normal, 01 would be vanity, 10 would be free, and 11 would be build
	public boolean vanityMode = false;
	public boolean freeMode = false;
	public boolean buildMode = false;
	
	/** how fast the camera rolls */
	float rollSpeed = 100.0f;
	
	// FIXME should the crosshair be its own class?
	public int crosshairWidth = 8, crosshairHeight = 8;
	public int handWidth = 15, handHeight = 17;
	private int currentCrosshairWidth = crosshairWidth, currentCrosshairHeight = crosshairHeight;
	private Textures currentCrosshair = Textures.CROSSHAIR;
	public Vector3f defaultCrosshairColor = new Vector3f(1.0f, 1.0f, 1.0f);

	/**
	 * Camera constructor
	 */
	public Camera() {
		super(new Vector3f(0.0f, 0.0f, 0.0f), new Quaternion(0.0f, 0.0f, 0.0f, 1.0f), new SphereShape(10.0f), 0.0001f, 0.01f, CollisionTypes.NOTHING, (short)-1);
		this.zoom = INIT_ZOOM;
		this.yOffset = INIT_YOFFSET;
		this.xOffset = INIT_XOFFSET;
		rotation = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
		this.type = "camera";
		builder = new Builder(this);
	}

	/**
	 * Update the camera. This handles following other things, mode switches etc.
	 */
	public void update(float timeStep) {
		// make sure the rigid body is active
		if(!this.rigidBody.isActive())
			this.rigidBody.activate();
		
		// get the rigid body's tranform
		Transform trans = new Transform();
		this.rigidBody.getWorldTransform(trans);
		
		// set location to be with rigid body
		this.location.set(trans.origin.x, trans.origin.y, trans.origin.z);
		
		// set rotation to be with rigid body
		Quat4f rot = new Quat4f();
		trans.getRotation(rot);
		this.rotation.set(rot.x, rot.y, rot.z, rot.w);
		
		if(buildMode)
			builder.update(timeStep);
		
		// if we're not following anything, we're in free mode
		if (following == null) {
			vanityMode = false;
			freeMode = true;
		}

		// perform zoom logic
		mousewheelLogic();

		// check for any key presses
		checkForModeSwitch();
		
		// only look around if the builder isn't rotating something
		if(!builder.rightGrabbed){
			lookLogic(timeStep, trans);
		}

		// if we're not in free mode, move the camera to be behind whatever it's
		// following
		if (!freeMode) {
			this.location.set(following.location);
			
			trans.origin.set(location.x, location.y, location.z);
		} else if (freeMode && !vanityMode) {
			// else do logic for moving around in free mode
			freeMode(timeStep, trans);
		}
		
		this.rigidBody.setWorldTransform(trans);
	}
	
	/**
	 * Changes where the camera is looking based on mouse movement/keyboard input
	 * @param timeStep Time since last update
	 * @param trans Transform to modify
	 */
	private void lookLogic(float timeStep, Transform trans){
		float dz = 0.0f;
		// roll left/right
		boolean rollRight = KeyBindings.CONTROL_ROLL_RIGHT.isPressed();
		boolean rollLeft = KeyBindings.CONTROL_ROLL_LEFT.isPressed();
		if (rollRight)
			dz = timeStep * rollSpeed;
		if (rollLeft)
			dz = timeStep * -rollSpeed;
		
		// apply any rotation changes
		this.rotation = QuaternionHelper.rotate(this.rotation, new Vector3f(MouseManager.dy, MouseManager.dx, dz));
		// update rigid body transform
		trans.setRotation(new Quat4f(rotation.x, rotation.y, rotation.z, rotation.w));
	}

	/**
	 * Checks if the mode change button has been pressed and changes states
	 * accordingly
	 */
	private void checkForModeSwitch() {
		// check for mode key
		if(!Console.consoleOn){
			if(!buildMode){
				// swap the camera mode
				if (KeyBindings.SYS_CAMERA_MODE.pressedOnce()) {
					// three states: normal (vanity false free false), vanity (vanity true
					// free false), free (vanity false free true)
					if (!vanityMode && !freeMode) {
						vanityMode = true;
						oldYOffset = yOffset;
						oldXOffset = xOffset;
						//oldMinZoom = minZoom;
						yOffset = 0;
						xOffset = 0;
						//minZoom = 0;
					} else if (vanityMode && !freeMode) {<commit_msg>Switched camera roll directions (it was backwards)<commit_after>package com.bitwaffle.spaceguts.entities;

import javax.vecmath.Quat4f;

import org.lwjgl.opengl.GL11;
import org.lwjgl.util.vector.Quaternion;
import org.lwjgl.util.vector.Vector3f;


import com.bitwaffle.spaceguts.graphics.render.Render3D;
import com.bitwaffle.spaceguts.input.KeyBindings;
import com.bitwaffle.spaceguts.input.MouseManager;
import com.bitwaffle.spaceguts.physics.Builder;
import com.bitwaffle.spaceguts.physics.CollisionTypes;
import com.bitwaffle.spaceguts.physics.Physics;
import com.bitwaffle.spaceguts.util.DisplayHelper;
import com.bitwaffle.spaceguts.util.QuaternionHelper;
import com.bitwaffle.spaceguts.util.console.Console;
import com.bitwaffle.spaceout.resources.Textures;
import com.bulletphysics.collision.dispatch.CollisionWorld.ClosestRayResultCallback;
import com.bulletphysics.collision.shapes.SphereShape;
import com.bulletphysics.linearmath.Transform;

/**
 * A camera that describes how the scene is being looked at and can move around inside of the physics world
 * There should only be one camera at a time, Entities.camera
 * 
 * @author TranquilMarmot
 */
public class Camera extends DynamicEntity {
	/** initial values for when the camera is created */
	private static final float INIT_ZOOM = 12.0f;
	private static final float INIT_XOFFSET = 0.0f;
	private static final float INIT_YOFFSET = -2.7F;

	/** the entity that the camera is following */
	public Entity following;
	
	/** handles special interactions with the game world */
	public Builder builder;

	/** how fast the camera moves in free mode */
	public float speed = 350.0f;
	private float maxSpeed = 10000.0f, minSpeed = 0.01f;

	/** Offset along Y axis */
	public float yOffset;
	/** Offset along X axis */
	public float xOffset;
	
	/** used to preserve offset when switching modes */
	private float oldYOffset, oldXOffset, oldMinZoom;

	/** zoom level */
	public float zoom;
	/** maximum and minimum zoom level */
	private float maxZoom = 3000.0f, minZoom = 10.0f;
	/** changes how fast the zoom is based on the current zoom distance */
	float zoomSensitivity = 10;
	private float oldZoom;
	
	/** for switching into/out of build mode */
	private Vector3f oldLocation = new Vector3f(0.0f, 0.0f, 0.0f);

	/**
	 * The camera has three main modes:
	 * 	Normal Mode - vanityMode = false, freeMode = false
	 * 		Camera simply follows behind whatever it's attached to
	 * 	Vanity Mode - vanityMode = true, freeMode = false
	 * 		Camera spins around whatever it's following
	 * 	Free Mode - vanityMode = false, freeMode = true
	 * 		Camera can move about freely on its own and zoom out real far
	 */
	// FIXME there's a more clever way to do this- it could easily be a short with each bit representing a mode- 00 would be normal, 01 would be vanity, 10 would be free, and 11 would be build
	public boolean vanityMode = false;
	public boolean freeMode = false;
	public boolean buildMode = false;
	
	/** how fast the camera rolls */
	float rollSpeed = 100.0f;
	
	// FIXME should the crosshair be its own class?
	public int crosshairWidth = 8, crosshairHeight = 8;
	public int handWidth = 15, handHeight = 17;
	private int currentCrosshairWidth = crosshairWidth, currentCrosshairHeight = crosshairHeight;
	private Textures currentCrosshair = Textures.CROSSHAIR;
	public Vector3f defaultCrosshairColor = new Vector3f(1.0f, 1.0f, 1.0f);

	/**
	 * Camera constructor
	 */
	public Camera() {
		super(new Vector3f(0.0f, 0.0f, 0.0f), new Quaternion(0.0f, 0.0f, 0.0f, 1.0f), new SphereShape(10.0f), 0.0001f, 0.01f, CollisionTypes.NOTHING, (short)-1);
		this.zoom = INIT_ZOOM;
		this.yOffset = INIT_YOFFSET;
		this.xOffset = INIT_XOFFSET;
		rotation = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
		this.type = "camera";
		builder = new Builder(this);
	}

	/**
	 * Update the camera. This handles following other things, mode switches etc.
	 */
	public void update(float timeStep) {
		// make sure the rigid body is active
		if(!this.rigidBody.isActive())
			this.rigidBody.activate();
		
		// get the rigid body's tranform
		Transform trans = new Transform();
		this.rigidBody.getWorldTransform(trans);
		
		// set location to be with rigid body
		this.location.set(trans.origin.x, trans.origin.y, trans.origin.z);
		
		// set rotation to be with rigid body
		Quat4f rot = new Quat4f();
		trans.getRotation(rot);
		this.rotation.set(rot.x, rot.y, rot.z, rot.w);
		
		if(buildMode)
			builder.update(timeStep);
		
		// if we're not following anything, we're in free mode
		if (following == null) {
			vanityMode = false;
			freeMode = true;
		}

		// perform zoom logic
		mousewheelLogic();

		// check for any key presses
		checkForModeSwitch();
		
		// only look around if the builder isn't rotating something
		if(!builder.rightGrabbed){
			lookLogic(timeStep, trans);
		}

		// if we're not in free mode, move the camera to be behind whatever it's
		// following
		if (!freeMode) {
			this.location.set(following.location);
			
			trans.origin.set(location.x, location.y, location.z);
		} else if (freeMode && !vanityMode) {
			// else do logic for moving around in free mode
			freeMode(timeStep, trans);
		}
		
		this.rigidBody.setWorldTransform(trans);
	}
	
	/**
	 * Changes where the camera is looking based on mouse movement/keyboard input
	 * @param timeStep Time since last update
	 * @param trans Transform to modify
	 */
	private void lookLogic(float timeStep, Transform trans){
		float dz = 0.0f;
		// roll left/right
		boolean rollRight = KeyBindings.CONTROL_ROLL_RIGHT.isPressed();
		boolean rollLeft = KeyBindings.CONTROL_ROLL_LEFT.isPressed();
		if (rollRight)
			dz = timeStep * -rollSpeed;
		if (rollLeft)
			dz = timeStep * rollSpeed;
		
		// apply any rotation changes
		this.rotation = QuaternionHelper.rotate(this.rotation, new Vector3f(MouseManager.dy, MouseManager.dx, dz));
		// update rigid body transform
		trans.setRotation(new Quat4f(rotation.x, rotation.y, rotation.z, rotation.w));
	}

	/**
	 * Checks if the mode change button has been pressed and changes states
	 * accordingly
	 */
	private void checkForModeSwitch() {
		// check for mode key
		if(!Console.consoleOn){
			if(!buildMode){
				// swap the camera mode
				if (KeyBindings.SYS_CAMERA_MODE.pressedOnce()) {
					// three states: normal (vanity false free false), vanity (vanity true
					// free false), free (vanity false free true)
					if (!vanityMode && !freeMode) {
						vanityMode = true;
						oldYOffset = yOffset;
						oldXOffset = xOffset;
						//oldMinZoom = minZoom;
						yOffset = 0;
						xOffset = 0;
						//minZoom = 0;
					} else if (vanityMode && !freeMode) {
{'fraction_non_alphanumeric': 0.10167183599364552, 'fraction_numerical': 0.01709660337393146, 'mean_word_length': 3.633718892393971, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '127954', 'n_tokens_mistral': 4776, 'n_tokens_neox': 4152, 'n_words': 1332}