public void ChangeLength(float newLength) { // clamp new length to sane limits: newLength = Mathf.Clamp(newLength, 0, (rope.blueprint.particleCount - 1) * rope.ropeBlueprint.interParticleDistance); // calculate the change in rope length: float lengthChange = newLength - rope.restLength; // remove: if (lengthChange < 0) { lengthChange = -lengthChange; while (lengthChange > m_CursorElement.restLength) { lengthChange -= m_CursorElement.restLength; int index = rope.elements.IndexOf(m_CursorElement); if (index >= 0) { // positive direction: if (direction) { RemoveParticleAt(rope.solver.particleToActor[m_CursorElement.particle2].indexInActor); rope.elements.RemoveAt(index); if (index < rope.elements.Count && rope.elements[index].particle1 == m_CursorElement.particle2) { rope.elements[index].particle1 = m_CursorElement.particle1; } m_CursorElement = rope.elements[index]; } else // negative direction: { RemoveParticleAt(rope.solver.particleToActor[m_CursorElement.particle1].indexInActor); rope.elements.RemoveAt(index); if (index > 0) { if (rope.elements[index - 1].particle2 == m_CursorElement.particle1) { rope.elements[index - 1].particle2 = m_CursorElement.particle2; } m_CursorElement = rope.elements[index - 1]; } else { m_CursorElement = rope.elements[0]; } } } } // the remaining length is subtracted from the current constraint: if (lengthChange > 0) { m_CursorElement.restLength = Mathf.Max(0, m_CursorElement.restLength - lengthChange); } } // add else { float lengthDelta = Mathf.Min(lengthChange, Mathf.Max(0, rope.ropeBlueprint.interParticleDistance - m_CursorElement.restLength)); // extend the current element, if possible: if (lengthDelta > 0) { m_CursorElement.restLength += lengthDelta; lengthChange -= lengthDelta; } // once the current element has been extended, see if we must add new elements: while (m_CursorElement.restLength + lengthChange > rope.ropeBlueprint.interParticleDistance) { // calculate added length: lengthDelta = Mathf.Min(lengthChange, rope.ropeBlueprint.interParticleDistance); lengthChange -= lengthDelta; if (direction) { // add new particle: int newParticleSolverIndex = AddParticleAt(rope.solver.particleToActor[m_CursorElement.particle1].indexInActor); // insert a new element: ObiStructuralElement newElement = new ObiStructuralElement(); newElement.restLength = lengthDelta; newElement.particle1 = m_CursorElement.particle1; newElement.particle2 = newParticleSolverIndex; m_CursorElement.particle1 = newParticleSolverIndex; int index = rope.elements.IndexOf(m_CursorElement); rope.elements.Insert(index, newElement); m_CursorElement = newElement; } else { // add new particle: int newParticleSolverIndex = AddParticleAt(rope.solver.particleToActor[m_CursorElement.particle2].indexInActor); // insert a new element: ObiStructuralElement newElement = new ObiStructuralElement(); newElement.restLength = lengthDelta; newElement.particle1 = newParticleSolverIndex; newElement.particle2 = m_CursorElement.particle2; m_CursorElement.particle2 = newParticleSolverIndex; int index = rope.elements.IndexOf(m_CursorElement); rope.elements.Insert(index + 1, newElement); m_CursorElement = newElement; } } // the remaining length is added to the current constraint: if (lengthChange > 0) { m_CursorElement.restLength += lengthChange; } } rope.RebuildConstraintsFromElements(); rope.RecalculateRestLength(); }