using System; using UnityEngine; namespace Obi { [RequireComponent(typeof(LineRenderer))] [RequireComponent(typeof(ObiParticlePicker))] public class ObiParticleDragger : MonoBehaviour { public float springStiffness = 500; public float springDamping = 50; public bool drawSpring = true; private LineRenderer lineRenderer; private ObiParticlePicker picker; private ObiParticlePicker.ParticlePickEventArgs pickArgs; void OnEnable() { lineRenderer = GetComponent(); picker = GetComponent(); picker.OnParticlePicked.AddListener(Picker_OnParticleDragged); picker.OnParticleDragged.AddListener(Picker_OnParticleDragged); picker.OnParticleReleased.AddListener(Picker_OnParticleReleased); picker.solver.OnSimulationStart += Solver_OnEndSimulation; } void OnDisable() { picker.solver.OnSimulationStart -= Solver_OnEndSimulation; picker.OnParticlePicked.RemoveListener(Picker_OnParticleDragged); picker.OnParticleDragged.RemoveListener(Picker_OnParticleDragged); picker.OnParticleReleased.RemoveListener(Picker_OnParticleReleased); lineRenderer.positionCount = 0; } private void Solver_OnEndSimulation(ObiSolver solver, float timeToSimulate, float substepTime) { if (solver != null && pickArgs != null) { // Calculate picking position in solver space: Vector4 targetPosition = solver.transform.InverseTransformPoint(pickArgs.worldPosition); // Calculate effective inverse mass: float invMass = solver.invMasses[pickArgs.particleIndex]; if (invMass > 0) { // Calculate and apply spring force: Vector4 position = solver.positions[pickArgs.particleIndex]; Vector4 velocity = solver.velocities[pickArgs.particleIndex]; solver.externalForces[pickArgs.particleIndex] = ((targetPosition - position) * springStiffness - velocity * springDamping) / invMass; if (drawSpring) { lineRenderer.positionCount = 2; lineRenderer.SetPosition(0, pickArgs.worldPosition); lineRenderer.SetPosition(1, solver.transform.TransformPoint(position)); } else { lineRenderer.positionCount = 0; } } } } void Picker_OnParticleDragged(ObiParticlePicker.ParticlePickEventArgs e) { pickArgs = e; } void Picker_OnParticleReleased(ObiParticlePicker.ParticlePickEventArgs e) { pickArgs = null; lineRenderer.positionCount = 0; } } }