Source: motion.js

const DynObject = require("./dynObject");
const Centroid = require("./tools/centroid");

// Try to import matter-js as a commonJS module

var Matter;

if(typeof window === "object") {
	Matter = window.Matter;
}

else {
	Matter = require("matter-js");
}

/**
 * Namespace of functions used to move objects in various ways.
 * @memberof PhSim
 * @namespace
 * 
 */

var Motion = {}

/**
 * 
 * Apply force to a dynamic object.
 * Force is ineffective against locked, semi-locked and permanetly static objects.
 * 
 * @function
 * @param {PhSim.DynObject} dynObject 
 * @param {Vector} position 
 * @param {Vector} forceVector
 *   
 */

Motion.applyForce = function(dynObject,position,forceVector) {
	if(!dynObject.locked && !dynObject.noDyn) {
		return Matter.Body.applyForce(dynObject.matter,position,forceVector);
	}
}


/**
 * 
 * Apply velocity to a dynamic object.
 * Velocity does not effect locked, semi-locked objects or static objects.
 * 
 * @function
 * @param {PhSim.DynObject} dynObject 
 * @param {Vector} velocityVector 
 */

Motion.setVelocity = function(dynObject,velocityVector) {
	if(!dynObject.locked) {
		return Matter.Body.setVelocity(dynObject.matter,velocityVector);
	}

}

/**
 * 
 * Apply a transformation to a dynamic object.
 * Transformation does not move locked objects.
 * However, it moves semi-locked objects and static objects.
 * 
 * @function
 * @param {PhSimObject} o 
 * @param {Vector} translationVector 
 */

Motion.translate = function(o,translationVector) {
	if(!o.locked) {

		if(o.shape === "polygon") {
			for(let i = 0; i < o.verts.length; i++) {
				o.verts[i].x = o.verts[i].x + translationVector.x;
				o.verts[i].y = o.verts[i].y + translationVector.y;
			}
		}

		if(o.shape === "circle" || o.shape === "rectangle" || o.shape === "regPolygon") {
				o.x = o.x + translationVector.x;
				o.y = o.y + translationVector.y;
		}

		if(o instanceof DynObject) {
			return Matter.Body.translate(o.matter,translationVector);
		}

	}
	
}

/**
 * Apply a transformation to a dynamic object.
 * Setting positions is ineffective against locked and permanetly static objects.
 * 
 * @function
 * @param {PhSim.DynObject} o 
 * @param {Vector} position 
 */

Motion.setPosition = function(o,position) {

	var c;

	if(!o.locked) {

		if(o.type === "circle" || o.type === "regPolygon") {
			o.x = position.x;
			o.y = position.y;
		}

		if(o.shape === "rectangle") {
			c = Centroid.rectangle(o);
			o.x = (o.x - c.x) + position.x;
			o.y = (o.y - c.y) + position.y;
		}

		if(o.shape === "polygon") {

			c = Centroid.polygon(o)

			for(var i = 0; i < o.verts.length; i++) {
				o.verts[i].x = (o.verts[i].x - c.x) + position.x;
				o.verts[i].y = (o.verts[i].y - c.y) + position.y;
			}

		}

		if(o instanceof DynObject) {
			Matter.Body.setPosition(o.matter,position);
		}

	}
}

/**
 * @function
 * @param {PhSim.DynObject} dynObject 
 * @param {Number} angle 
 * @param {Vector} point 
 */

Motion.rotate = function(dynObject,angle,point) {

	if(!dynObject.locked) {

		if(dynObject.skinmesh) {
			Matter.Vertices.rotate(dynObject.skinmesh,angle,point);
		}

		return Matter.Body.rotate(dynObject.matter, angle, point)

	}
}

/**
 * Rotate dynamic object towards point
 * 
 * @param {PhSim.DynObject} dynObject 
 * @param {Vector} point 
 */

Motion.rotateTowards = function(dynObject,point) {

	var a = Math.atan2(point.y - dynObject.matter.position.y ,point.x - dynObject.matter.position.x)

	Motion.rotate(dynObject,a,dynObject.matter.position);
}

/**
 * @function
 * @param {PhSim.DynObject} dynObject 
 * @param {Number} angle 
 */

Motion.setAngle = function(dynObject,angle) {

	if(!dynObject.locked) {

		if(dynObject.skinmesh) {
			Matter.Vertices.rotate(dynObject.skinmesh,-dynObject.cycle,dynObject);
			Matter.Vertices.rotate(dynObject.skinmesh,angle,dynObject);
		}

		return Matter.Body.setAngle(dynObject.matter,angle);

	}
}

module.exports = Motion;