Esempio n. 1
0
    /// <summary>
    /// Add an internal JelloPointMass to this JelloBody.
    /// This will also add an internal vertex to JelloBody.Shape.InternalVertices.
    /// </summary>
    /// <param name="pointMass">The new JelloPointMass to add.</param>
    /// <param name="recenterBaseShape">Whether to recenter JelloBody.Shape.</param>
    public void addInternalPointMass(JelloPointMass pointMass, bool recenterBaseShape)
    {
        if(mBaseShape == null)
            return;

        if(mBaseShape.addInternalVertex(pointMass.LocalPosition))
        {
            JelloPointMass[] oldMasses = mInternalPointMasses;
            mInternalPointMasses = new JelloPointMass[oldMasses.Length + 1];
            for(int i = 0; i < oldMasses.Length; i++)
                mInternalPointMasses[i] = oldMasses[i];

            mInternalPointMasses[mInternalPointMasses.Length - 1] = pointMass;

            mBaseShape.finish(recenterBaseShape);
        }
    }
    /// <summary>
    /// Grabs the point mass.
    /// </summary>
    public void GrabPointMass()
    {
        //i am now pulling the body.
        pulling = true;

        //clear old values from last pull
        adjacentPointMasses.Clear();
        oldMultipliers.Clear();

        //set the position to lock it in place while pulling the body
        position = body.Position;

        //get the closest point mass to the mouse positions and cache some information about it.
        mousePosInWorld = Camera.main.ScreenToWorldPoint(Input.mousePosition);
        pmIndex = body.getClosestPointMass(mousePosInWorld, false); //only grab edge point masses
        pointmass = body.getEdgePointMass(pmIndex);
        oldMultipliers.Add (pointmass.shapeMatchingMultiplier);
        pointmass.shapeMatchingMultiplier = 0f;
        adjacentPointMasses.Add (pointmass);

        //Set the body to kinematic to keep it in place while pulling.
        body.IsKinematic = true;

        int adjIndex = 0;
        int numFromStart = 0;
        //grab adjacent point masses further in the array.
        for(int i = pmIndex; i < pmIndex + numAdjacentPoints; i++)
        {
            adjIndex = i > body.EdgePointMassCount - 1 ? i - body.EdgePointMassCount : i;

            if(adjIndex > body.EdgePointMassCount - 1 || adjacentPointMasses.Contains(body.getEdgePointMass(adjIndex)))
                continue;

            //cache the point mass info and modify the shape matching values by how close it is to the grabbed point mass
            adjacentPointMasses.Add (body.getEdgePointMass(adjIndex));
            oldMultipliers.Add(body.getEdgePointMass(adjIndex).shapeMatchingMultiplier);
            numFromStart++;
            body.getEdgePointMass(adjIndex).shapeMatchingMultiplier = numFromStart / (numAdjacentPoints + 1 + adjacentDropoff);
        }
        numFromStart = 0;
        //grab adjacent point masses before the current index in the array.
        for(int i = pmIndex; i > pmIndex - numAdjacentPoints; i--)
        {
            adjIndex = i < 0 ? i + body.EdgePointMassCount: i;
            if(adjIndex < 0 || adjacentPointMasses.Contains(body.getEdgePointMass(adjIndex)))
                continue;

            //cache the point mass info and modify the shape matching values by how close it is to the grabbed point mass
            adjacentPointMasses.Add (body.getEdgePointMass(adjIndex));
            oldMultipliers.Add(body.getEdgePointMass(adjIndex).shapeMatchingMultiplier);
            numFromStart++;
            body.getEdgePointMass(adjIndex).shapeMatchingMultiplier = numFromStart / (numAdjacentPoints + 1 + adjacentDropoff);
        }
        //find any internal point masses connected to the selected point mass (via spring) and cache/modify its shape matching multiplier.
        for(int i = 0; i < body.SpringCount; i++)
        {
            if(body.getSpring(i).pointMassA == pmIndex || body.getSpring(i).pointMassB == pmIndex)
            {
                if(body.getSpring(i).pointMassA >= body.EdgePointMassCount)
                {
                    adjacentPointMasses.Add (body.getPointMass(body.getSpring(i).pointMassA));
                    oldMultipliers.Add (body.getPointMass(body.getSpring(i).pointMassA).shapeMatchingMultiplier);
                    body.getPointMass(body.getSpring(i).pointMassA).shapeMatchingMultiplier = 1 / (2 + adjacentDropoff);
                }
                else if(body.getSpring(i).pointMassB >= body.EdgePointMassCount)
                {
                    adjacentPointMasses.Add (body.getPointMass(body.getSpring(i).pointMassB));
                    oldMultipliers.Add (body.getPointMass(body.getSpring(i).pointMassB).shapeMatchingMultiplier);
                    body.getPointMass(body.getSpring(i).pointMassB).shapeMatchingMultiplier = 1 / (2 + adjacentDropoff);
                }
            }
        }
    }
Esempio n. 3
0
    /// <summary>
    /// Add an internal JelloPointMass to this JelloBody.
    /// This will also add an internal vertex to JelloBody.Shape.InternalVertices.
    /// Smartly means that most edits made to the JelloBody will be retained and is done via the JelloBody.smartSetShape() method.
    /// </summary>
    /// <param name="pointMass">The new JelloPointMass to add.</param>
    /// <param name="recenterBaseShape">Whether to recenter JelloBody.Shape.</param>
    /// <param name="options">ShapeSettingOptions on how Subcomponents should be modified as the JelloPointMass and JelloClosedShape vertex is added .</param>
    /// <param name="smartOptions">SmartShapeSettingOptions options on how Subcomponents should be modified as the JelloPointMass and JelloClosedShape vertex is added.</param>
    public void smartAddInternalPointMass(JelloPointMass pointMass, bool recenterBaseShape, ShapeSettingOptions options = ShapeSettingOptions.None, SmartShapeSettingOptions smartOptions = SmartShapeSettingOptions.None)
    {
        if(mBaseShape == null)
            return;

        JelloClosedShape newShape = new JelloClosedShape(mBaseShape.EdgeVertices, mBaseShape.InternalVertices, false);

        if(!newShape.addInternalVertex(pointMass.LocalPosition))
            return;

        newShape.finish(recenterBaseShape);

        smartSetShape(newShape, options, smartOptions);

        mInternalPointMasses[mInternalPointMasses.Length - 1] = pointMass;
    }
Esempio n. 4
0
    /// <summary>
    /// Smartly sets JelloBody.Shape to a new JelloClosedShape object.
    /// Make sure your JelloShape does not contain any duplicate points ( Use JelloShapeTools.RemoveDuplicates() ).
    /// This method will attemp to retain as much information as possible from the previous shape.
    /// The subcomponents that will be processed in order to try and retained are JelloPointMass, JelloJoint, JelloAttachPoint, and JelloSpring.
    /// </summary>
    /// <param name="shape">New JelloClosedShape.</param>
    /// <param name="options">ShapeSettingOptions for setting the JelloClosedShape.</param>
    /// <param name="smartOptions">SmartShapeSettingOptions for setting the JelloClosedShape.</param>
    public virtual void smartSetShape(JelloClosedShape shape, ShapeSettingOptions options = ShapeSettingOptions.None, SmartShapeSettingOptions smartOptions = SmartShapeSettingOptions.None)
    {
        //no need to run smart method if no shape yet assigned.
        if(mBaseShape == null)
        {
            setShape(shape, options);
            return;
        }

        setComponentReferences();

        //find common points between the old shape and the new one.
        List<int[]> indexPairs = new List<int[]>();

        //start with the edges...???
        for(int a = 0;  a < shape.EdgeVertexCount; a++)
        {
            bool found = false;
            for(int i = 0; i < mBaseShape.EdgeVertexCount; i++)
            {
                if(mBaseShape.EdgeVertices[i] == shape.EdgeVertices[a])
                {
                    indexPairs.Add (new int[2]{a, i});
                    found = true;
                    break;
                }
            }

            if(!found)
                indexPairs.Add (new int[2]{a, -1});
        }

        for(int a = 0;  a < shape.InternalVertexCount; a++)
        {
            bool found = false;
            for(int i = 0; i < mBaseShape.InternalVertexCount; i++)
            {
                if(mBaseShape.InternalVertices[i] == shape.InternalVertices[a])
                {
                    indexPairs.Add (new int[2]{a, i});
                    found = true;
                    break;
                }
            }

            if(!found)
                indexPairs.Add (new int[2]{a, -1});
        }

        bool movePointMasses = (options & ShapeSettingOptions.MovePointMasses) == ShapeSettingOptions.MovePointMasses;

        //reconfigure point masses
        JelloPointMass[] tempPointMasses = new JelloPointMass[shape.EdgeVertexCount];
        for(int i = 0; i < shape.EdgeVertexCount; i++)
        {
            //this is a new point, create a point mass here
            if(indexPairs[i][1] == -1)
            {
                Vector2 pos;

                if(movePointMasses)
                    pos =  myTransform.TransformPoint(shape.EdgeVertices[indexPairs[i][0]]);
                else
                    pos = Position;

                tempPointMasses[i] = new JelloPointMass(Mass, pos, this, false);
            }
            else//this point exists from the old shape, move that point mass into this index.
            {
                tempPointMasses[i] = mEdgePointMasses[indexPairs[i][1]];
            }
        }
        mEdgePointMasses = tempPointMasses;

        tempPointMasses = new JelloPointMass[shape.InternalVertexCount];
        for(int i = 0; i < shape.InternalVertexCount; i++)
        {
            //this is a new point, create a point mass here
            if(indexPairs[i + shape.EdgeVertexCount][1] == -1)
            {
                Vector2 pos;

                if(movePointMasses)
                    pos =  myTransform.TransformPoint(shape.InternalVertices[indexPairs[i + shape.EdgeVertexCount][0]]);
                else
                    pos = Position;

                tempPointMasses[i] = new JelloPointMass(Mass, pos, this, false);
            }
            else//this point exists from the old shape, move that point mass into this index.
            {
                tempPointMasses[i] = mInternalPointMasses[indexPairs[i + shape.EdgeVertexCount][1]];
            }
        }
        mInternalPointMasses = tempPointMasses;

        pivotOffset = JelloShapeTools.FindCenter(shape.EdgeVertices);

        //offset index pairs for internal points
        for(int i = 0;  i < shape.InternalVertexCount; i++)
        {
            indexPairs[shape.EdgeVertexCount + i][0] += shape.EdgeVertexCount;
            indexPairs[shape.EdgeVertexCount + i][1] += mBaseShape.EdgeVertexCount;
        }

        //		//TODO remove this? it seems a bit redundant...
        //		for(int i = 0; i < mEdgePointMasses.Length; i++)
        //			mEdgePointMasses[i].body = this;
        //		for(int i = 0; i < mInternalPointMasses.Length; i++)
        //			mInternalPointMasses[i].body = this;

        processSmartSetShape(indexPairs, shape, options, smartOptions);

        ClearInvalidSubComponents(); //this is joints and attach points....

        mBaseShape = shape;
    }
Esempio n. 5
0
    /// <summary>
    /// Sets JelloBody.Shape to a new JelloClosedShape object.
    /// Make sure your JelloShape does not contain any duplicate points ( Use JelloShapeTools.RemoveDuplicates() ).
    /// This method will remove any existing JelloPointMass objects, and replace them with new ones if
    /// the new shape has a different JelloClosedShape.VertexCount than the previous one. In this case
    /// the JelloPointMass.Mass for each newly added JelloPointMass will be set to JelloBody.Mass. 
    /// Otherwise the JelloBody.Shape is just updated, not affecting the existing JelloPointMass objects other than thier positions.
    /// Any JelloJoint, JelloSpring, or AttachPoint made invalid by the new shape will be removed.
    /// </summary>
    /// <param name="shape">New JelloClosedShape.</param>
    /// <param name="options">ShapeSettingOptions for setting the JelloClosedShape.</param>
    /// 
    /// <dl class="example"><dt>Example</dt></dl>
    /// ~~~{.c}
    /// //Change the shape of the body to match the shape of the collider collided against
    /// JelloSpringBody springBody;
    /// 
    /// void OnTriggerEnter2D(Collider2D coll)
    /// {
    /// 	if(coll.GetType() == typeof(PolygonCollider2D))
    /// 	{
    /// 		PolygonCollider2D polyColl = (PolygonCollider2D)coll;
    /// 		
    /// 		JelloClosedShape shape = new JelloClosedShape(polyColl.points, true);
    /// 		
    /// 		springBody.setShape(shape, true);
    /// 	}
    /// }
    /// ~~~
    public virtual void setShape(JelloClosedShape shape, ShapeSettingOptions options = ShapeSettingOptions.None)
    {
        //TODO make this all work better...
        mBaseShape = shape;

        bool movePointMasses = (options & ShapeSettingOptions.MovePointMasses) == ShapeSettingOptions.MovePointMasses;

        setComponentReferences();

        if (mBaseShape.EdgeVertices.Length != mEdgePointMasses.Length)
        {
            Vector2 pos;
        //			JelloPointMass[] oldPointMasses = mPointMasses;
            mEdgePointMasses = new JelloPointMass[mBaseShape.EdgeVertices.Length];

            //how to make this work so that it doesnt move the point masses... what about mesh link options?
            for (int i = 0; i < mBaseShape.EdgeVertices.Length; i++)
            {
        //				if(i < oldPointMasses.Length)
        //				{
        //					mPointMasses[i] = oldPointMasses[i]; //retain as many of the original point masses?
        //
        //					if(movePointMasses)
        //						mPointMasses[i].Position = myTransform.TransformPoint(mBaseShape.EdgeVertices[i]);
        //				}
        //				else
        //				{
                    if(movePointMasses)
                        pos =  myTransform.TransformPoint(mBaseShape.EdgeVertices[i]);
                    else
                        pos = Position;

                    mEdgePointMasses[i] = new JelloPointMass(Mass, pos, this, false);
        //				}
            }
        }
        else if(movePointMasses)
        {
            for(int i = 0; i < EdgePointMassCount; i++)
                mEdgePointMasses[i].Position = myTransform.TransformPoint(mBaseShape.EdgeVertices[i]);
        }

        if (mBaseShape.InternalVertices.Length != mInternalPointMasses.Length)
        {
            Vector2 pos;
        //			JelloPointMass[] oldPointMasses = mInternalPointMasses;
            mInternalPointMasses = new JelloPointMass[mBaseShape.InternalVertices.Length];

            //how to make this work so that it doesnt move the point masses... what about mesh link options?
            for (int i = 0; i < mBaseShape.InternalVertices.Length; i++)
            {
        //				if(i < oldPointMasses.Length)
        //				{
        //					mInternalPointMasses[i] = oldPointMasses[i]; //retain as many of the original point masses?
        //
        //					if(movePointMasses)
        //						mInternalPointMasses[i].Position = myTransform.TransformPoint(mBaseShape.InternalVertices[i]);
        //				}
        //				else
        //				{
                    if(movePointMasses)
                        pos =  myTransform.TransformPoint(mBaseShape.InternalVertices[i]);
                    else
                        pos = Position;

                    mInternalPointMasses[i] = new JelloPointMass(Mass, pos, this, false);
        //				}
            }
        }
        else if(movePointMasses)
        {
            for(int i = 0; i < mInternalPointMasses.Length; i++)
                mInternalPointMasses[i].Position = myTransform.TransformPoint(mBaseShape.InternalVertices[i]);
        }

        pivotOffset = JelloShapeTools.FindCenter(mBaseShape.EdgeVertices);

        for(int i = 0; i < mEdgePointMasses.Length; i++)
            mEdgePointMasses[i].body = this;
        for(int i = 0; i < mInternalPointMasses.Length; i++)
            mInternalPointMasses[i].body = this;

        ClearInvalidSubComponents();
    }
Esempio n. 6
0
 /// <summary>
 /// Set the internal JelloPointMass at the given index.
 /// </summary>
 /// <param name="pointMass">The new JelloPointMass.</param>
 /// <param name="index">The index that the new JelloPointMass will occupy. Operation will fail if index is out of range.</param>
 public void setInternalPointMass(JelloPointMass pointMass, int index)
 {
     if(index >= 0 && index < mInternalPointMasses.Length)
         mInternalPointMasses[index] = pointMass;
 }
Esempio n. 7
0
 /// <summary>
 /// Set the edge JelloPointMass at the given index.
 /// </summary>
 /// <param name="pointMass">The new JelloPointMass.</param>
 /// <param name="index">The index that the new JelloPointMass will occupy. Operation will fail if index is out of range.</param>
 public void setEdgePointMass(JelloPointMass pointMass, int index)
 {
     if(index >= 0 && index < mEdgePointMasses.Length)
         mEdgePointMasses[index] = pointMass;
 }
Esempio n. 8
0
    /// <summary>
    /// Flip the body about its local x-axis.
    /// </summary>
    public virtual void FlipY()
    {
        JelloPointMass[] tempMasses = new JelloPointMass[mEdgePointMasses.Length];
        Vector2[] tempVertices = new Vector2[polyCollider.points.Length];

        for(int i = 0; i < mEdgePointMasses.Length; i++)
        {
            mEdgePointMasses[i].Position = new Vector2(mEdgePointMasses[i].Position.x, mEdgePointMasses[i].Position.y + 2 * (Position.y - mEdgePointMasses[i].Position.y));
            tempMasses[mEdgePointMasses.Length - i - 1] = mEdgePointMasses[i];

            polyCollider.points[i] = new Vector2(polyCollider.points[i].x, polyCollider.points[i].y + 2 * (Position.y - polyCollider.points[i].y));
            tempVertices[polyCollider.points.Length - i - 1] = polyCollider.points[i];
        }

        mEdgePointMasses = tempMasses;
        polyCollider.points = tempVertices;
        pivotOffset = new Vector2(pivotOffset.x, -pivotOffset.y);

        tempMasses = new JelloPointMass[mInternalPointMasses.Length];
        for(int i = 0; i < mInternalPointMasses.Length; i++)
        {
            mInternalPointMasses[i].Position = new Vector2(mInternalPointMasses[i].Position.x, mInternalPointMasses[i].Position.y + 2 * (Position.y - mInternalPointMasses[i].Position.y));
            tempMasses[mInternalPointMasses.Length - i - 1] = mEdgePointMasses[i];
        }
        mInternalPointMasses = tempMasses;

        mBaseShape.flipY();
    }
	/// <summary>
	/// Grabs the point mass.
	/// </summary>
	public void GrabPointMass()
	{
		//i am now pulling the body.
		pulling = true;
	
		//clear old values from last pull
		adjacentPointMasses.Clear();
		oldMultipliers.Clear();

		//set the position to lock it in place while pulling the body
		position = body.Position;

		//get the closest point mass to the mouse positions and cache some information about it.
		mousePosInWorld = Camera.main.ScreenToWorldPoint(Input.mousePosition);
		pmIndex = body.getClosestPointMass(mousePosInWorld, false); //only grab edge point masses
		pointmass = body.getEdgePointMass(pmIndex);
		oldMultipliers.Add (pointmass.shapeMatchingMultiplier);
		pointmass.shapeMatchingMultiplier = 0f;
		adjacentPointMasses.Add (pointmass);

		//Set the body to kinematic to keep it in place while pulling.
		body.IsKinematic = true; 
		
		int adjIndex = 0;
		int numFromStart = 0;
		//grab adjacent point masses further in the array.
		for(int i = pmIndex; i < pmIndex + numAdjacentPoints; i++)
		{
			adjIndex = i > body.EdgePointMassCount - 1 ? i - body.EdgePointMassCount : i;
			
			if(adjIndex > body.EdgePointMassCount - 1 || adjacentPointMasses.Contains(body.getEdgePointMass(adjIndex)))
				continue;

			//cache the point mass info and modify the shape matching values by how close it is to the grabbed point mass
			adjacentPointMasses.Add (body.getEdgePointMass(adjIndex));
			oldMultipliers.Add(body.getEdgePointMass(adjIndex).shapeMatchingMultiplier);
			numFromStart++;
			body.getEdgePointMass(adjIndex).shapeMatchingMultiplier = numFromStart / (numAdjacentPoints + 1 + adjacentDropoff);
		}
		numFromStart = 0;
		//grab adjacent point masses before the current index in the array.
		for(int i = pmIndex; i > pmIndex - numAdjacentPoints; i--)
		{
			adjIndex = i < 0 ? i + body.EdgePointMassCount: i;
			if(adjIndex < 0 || adjacentPointMasses.Contains(body.getEdgePointMass(adjIndex)))
				continue;

			//cache the point mass info and modify the shape matching values by how close it is to the grabbed point mass
			adjacentPointMasses.Add (body.getEdgePointMass(adjIndex));
			oldMultipliers.Add(body.getEdgePointMass(adjIndex).shapeMatchingMultiplier);
			numFromStart++;
			body.getEdgePointMass(adjIndex).shapeMatchingMultiplier = numFromStart / (numAdjacentPoints + 1 + adjacentDropoff);
		}
		//find any internal point masses connected to the selected point mass (via spring) and cache/modify its shape matching multiplier.
		for(int i = 0; i < body.SpringCount; i++)
		{
			if(body.getSpring(i).pointMassA == pmIndex || body.getSpring(i).pointMassB == pmIndex)
			{
				if(body.getSpring(i).pointMassA >= body.EdgePointMassCount)
				{
					adjacentPointMasses.Add (body.getPointMass(body.getSpring(i).pointMassA));
					oldMultipliers.Add (body.getPointMass(body.getSpring(i).pointMassA).shapeMatchingMultiplier);
					body.getPointMass(body.getSpring(i).pointMassA).shapeMatchingMultiplier = 1 / (2 + adjacentDropoff);
				}
				else if(body.getSpring(i).pointMassB >= body.EdgePointMassCount)
				{
					adjacentPointMasses.Add (body.getPointMass(body.getSpring(i).pointMassB));
					oldMultipliers.Add (body.getPointMass(body.getSpring(i).pointMassB).shapeMatchingMultiplier);
					body.getPointMass(body.getSpring(i).pointMassB).shapeMatchingMultiplier = 1 / (2 + adjacentDropoff);
				}
			}
		}
	}