/// <summary>
 /// Determines whether a particle is inside the area of a Manipulator.
 /// </summary>
 /// <returns><c>true</c> if this particle is inside manipulator; otherwise, <c>false</c>.</returns>
 public bool IsParticleInsideManipulator(int particleId, ManipulatorObjectC manipulator)
 {
     return (manipulator.Contains (playgroundCache.position[particleId], (localSpace?manipulator.transform.localPosition:manipulator.transform.position)));
 }
        /// <summary>
        /// Calculates the effect from Manipulator's properties.
        /// </summary>
        /// <param name="playgroundParticles">Playground particles.</param>
        /// <param name="thisManipulator">This manipulator.</param>
        /// <param name="thisManipulatorProperty">This manipulator property.</param>
        /// <param name="p">Particle index.</param>
        /// <param name="t">Delta time.</param>
        /// <param name="particlePosition">Particle position.</param>
        /// <param name="manipulatorPosition">Manipulator position.</param>
        /// <param name="localSpace">Is calculation in local space?</param>
        /// <param name="contains">Does the Manipulator contain the particle at index?</param>
        public static void PropertyManipulator(PlaygroundParticlesC playgroundParticles, ManipulatorObjectC thisManipulator, ManipulatorPropertyC thisManipulatorProperty, int p, float t, Vector3 particlePosition, Vector3 manipulatorPosition, float manipulatorDistance, bool localSpace, bool contains)
        {
            if (contains) {
                switch (thisManipulatorProperty.type) {

                    // Math Property
                    case MANIPULATORPROPERTYTYPEC.Math:
                    if (thisManipulatorProperty.mathProperty.type == MATHMANIPULATORTYPE.Sin || thisManipulatorProperty.mathProperty.type == MATHMANIPULATORTYPE.Cos)
                        t = playgroundParticles.localTime;
                    switch (thisManipulatorProperty.mathProperty.property) {
                        case MATHMANIPULATORPROPERTY.Position:
                            playgroundParticles.playgroundCache.position[p] = thisManipulatorProperty.mathProperty.EvaluatePosition(playgroundParticles.playgroundCache.position[p], t);
                        break;
                        case MATHMANIPULATORPROPERTY.Velocity:
                            playgroundParticles.playgroundCache.velocity[p] = thisManipulatorProperty.mathProperty.Evaluate(playgroundParticles.playgroundCache.velocity[p], t);
                        break;
                        case MATHMANIPULATORPROPERTY.Rotation:
                            if (!playgroundParticles.rotateTowardsDirection)
                                playgroundParticles.playgroundCache.rotation[p] = thisManipulatorProperty.mathProperty.Evaluate(playgroundParticles.playgroundCache.rotation[p], t)%360f;
                        break;
                        case MATHMANIPULATORPROPERTY.Size:
                            playgroundParticles.playgroundCache.size[p] = thisManipulatorProperty.mathProperty.Evaluate(playgroundParticles.playgroundCache.size[p], t);
                            playgroundParticles.playgroundCache.changedByPropertySize[p] = true;
                        break;
                    }
                    break;

                    // Velocity Property
                    case MANIPULATORPROPERTYTYPEC.Velocity:
                    if (thisManipulatorProperty.transition == MANIPULATORPROPERTYTRANSITIONC.None)
                        playgroundParticles.playgroundCache.velocity[p] = thisManipulatorProperty.useLocalRotation?
                            thisManipulatorProperty.localVelocity
                            :
                            thisManipulatorProperty.velocity;
                    else {
                        manipulatorDistance = thisManipulator.strengthDistanceEffect>0?Vector3.SqrMagnitude (manipulatorPosition - particlePosition)/thisManipulator.strengthDistanceEffect:10f;
                        playgroundParticles.playgroundCache.velocity[p] = Vector3.Lerp(playgroundParticles.playgroundCache.velocity[p], thisManipulatorProperty.useLocalRotation?
                            thisManipulatorProperty.localVelocity
                            :
                        thisManipulatorProperty.velocity, (t*thisManipulatorProperty.strength*thisManipulator.strength/manipulatorDistance)/thisManipulator.strengthSmoothing);
                    }
                    break;

                    // Additive Velocity Property
                    case MANIPULATORPROPERTYTYPEC.AdditiveVelocity:
                        manipulatorDistance = thisManipulator.strengthDistanceEffect>0?Vector3.SqrMagnitude (manipulatorPosition - particlePosition)/thisManipulator.strengthDistanceEffect:10f;
                        playgroundParticles.playgroundCache.velocity[p] += thisManipulatorProperty.useLocalRotation?
                            thisManipulatorProperty.localVelocity*((t*thisManipulatorProperty.strength*thisManipulator.strength/manipulatorDistance)/thisManipulator.strengthSmoothing)
                            :
                            thisManipulatorProperty.velocity*((t*thisManipulatorProperty.strength*thisManipulator.strength/manipulatorDistance)/thisManipulator.strengthSmoothing);
                    break;

                    // Color Property
                    case MANIPULATORPROPERTYTYPEC.Color:
                    Color staticColor;
                    if (thisManipulatorProperty.transition == MANIPULATORPROPERTYTRANSITIONC.None) {
                        if (thisManipulatorProperty.keepColorAlphas) {
                            staticColor = thisManipulatorProperty.color;
                            staticColor.a = Mathf.Clamp(playgroundParticles.lifetimeColor.Evaluate(playgroundParticles.playgroundCache.life[p]/playgroundParticles.lifetime).a, 0, staticColor.a);
                            playgroundParticles.particleCache[p].color = staticColor;
                        } else playgroundParticles.particleCache[p].color = thisManipulatorProperty.color;
                    } else {
                        if (thisManipulatorProperty.keepColorAlphas) {
                            manipulatorDistance = thisManipulator.strengthDistanceEffect>0?Vector3.SqrMagnitude (manipulatorPosition - particlePosition)/thisManipulator.strengthDistanceEffect:10f;
                            staticColor = thisManipulatorProperty.color;
                            staticColor.a = Mathf.Clamp(playgroundParticles.lifetimeColor.Evaluate(playgroundParticles.playgroundCache.life[p]/playgroundParticles.lifetime).a, 0, staticColor.a);
                            playgroundParticles.particleCache[p].color = Color.Lerp(playgroundParticles.particleCache[p].color, staticColor, (t*thisManipulatorProperty.strength*thisManipulator.strength/manipulatorDistance)/thisManipulator.strengthSmoothing);
                        } else playgroundParticles.particleCache[p].color = Color.Lerp(playgroundParticles.particleCache[p].color, thisManipulatorProperty.color, (t*thisManipulatorProperty.strength*thisManipulator.strength/manipulatorDistance)/thisManipulator.strengthSmoothing);
                        playgroundParticles.playgroundCache.changedByPropertyColorLerp[p] = true;
                    }

                    // Only color in range of manipulator boundaries
                    playgroundParticles.playgroundCache.changedByPropertyColor[p] = true;

                    // Keep alpha of original color
                    if (thisManipulatorProperty.keepColorAlphas)
                        playgroundParticles.playgroundCache.changedByPropertyColorKeepAlpha[p] = true;

                    // Set color pairing key
                    if (playgroundParticles.playgroundCache.propertyColorId[p] != thisManipulator.manipulatorId) {
                        playgroundParticles.playgroundCache.propertyColorId[p] = thisManipulator.manipulatorId;
                    }
                    break;

                    // Lifetime Color Property
                    case MANIPULATORPROPERTYTYPEC.LifetimeColor:
                    if (thisManipulatorProperty.transition == MANIPULATORPROPERTYTRANSITIONC.None) {
                        playgroundParticles.particleCache[p].color = thisManipulatorProperty.lifetimeColor.Evaluate(playgroundParticles.lifetime>0?playgroundParticles.playgroundCache.life[p]/playgroundParticles.lifetime:0);
                    } else {
                        playgroundParticles.particleCache[p].color = Color.Lerp(playgroundParticles.particleCache[p].color, thisManipulatorProperty.lifetimeColor.Evaluate(playgroundParticles.lifetime>0?playgroundParticles.playgroundCache.life[p]/playgroundParticles.lifetime:0), (t*thisManipulatorProperty.strength*thisManipulator.strength/manipulatorDistance)/thisManipulator.strengthSmoothing);
                        playgroundParticles.playgroundCache.changedByPropertyColorLerp[p] = true;
                    }

                    // Only color in range of manipulator boundaries
                    playgroundParticles.playgroundCache.changedByPropertyColor[p] = true;

                    // Set color pairing key
                    if (playgroundParticles.playgroundCache.propertyColorId[p] != thisManipulator.manipulatorId) {
                        playgroundParticles.playgroundCache.propertyColorId[p] = thisManipulator.manipulatorId;
                    }
                    break;

                    // Size Property
                    case MANIPULATORPROPERTYTYPEC.Size:
                    if (thisManipulatorProperty.transition == MANIPULATORPROPERTYTRANSITIONC.None) {
                        manipulatorDistance = thisManipulator.strengthDistanceEffect>0f?Vector3.SqrMagnitude (manipulatorPosition - particlePosition)/thisManipulator.strengthDistanceEffect:0;
                        if (manipulatorDistance==0)
                            playgroundParticles.playgroundCache.size[p] = thisManipulatorProperty.size;
                        else
                            playgroundParticles.playgroundCache.size[p] = thisManipulatorProperty.size+(thisManipulatorProperty.size/(1f+(manipulatorDistance/thisManipulator.strengthSmoothing))*(thisManipulator.strength*thisManipulatorProperty.strength));
                    } else if (thisManipulatorProperty.transition == MANIPULATORPROPERTYTRANSITIONC.Lerp) {
                        manipulatorDistance = thisManipulator.strengthDistanceEffect>0?Vector3.SqrMagnitude (manipulatorPosition - particlePosition)/thisManipulator.strengthDistanceEffect:10f;
                        playgroundParticles.playgroundCache.size[p] = Mathf.Lerp(playgroundParticles.playgroundCache.size[p], thisManipulatorProperty.size, (t*thisManipulatorProperty.strength*thisManipulator.strength/manipulatorDistance)/thisManipulator.strengthSmoothing);
                    } else if (thisManipulatorProperty.transition == MANIPULATORPROPERTYTRANSITIONC.Linear) {
                        manipulatorDistance = thisManipulator.strengthDistanceEffect>0?Vector3.SqrMagnitude (manipulatorPosition - particlePosition)/thisManipulator.strengthDistanceEffect:10f;
                        playgroundParticles.playgroundCache.size[p] = Mathf.MoveTowards(playgroundParticles.playgroundCache.size[p], thisManipulatorProperty.size, (t*thisManipulatorProperty.strength*thisManipulator.strength/manipulatorDistance)/thisManipulator.strengthSmoothing);
                    }

                    playgroundParticles.playgroundCache.changedByPropertySize[p] = true;
                    break;

                    // Target Property
                    case MANIPULATORPROPERTYTYPEC.Target:
                    if (thisManipulatorProperty.targets.Count>0 && thisManipulatorProperty.targets[thisManipulatorProperty.targetPointer].available) {

                        // Set target pointer
                        if (playgroundParticles.playgroundCache.propertyId[p] != thisManipulator.manipulatorId) {

                            playgroundParticles.playgroundCache.propertyTarget[p] = thisManipulatorProperty.targetPointer;
                            thisManipulatorProperty.targetPointer++; thisManipulatorProperty.targetPointer=thisManipulatorProperty.targetPointer%thisManipulatorProperty.targets.Count;
                            playgroundParticles.playgroundCache.propertyId[p] = thisManipulator.manipulatorId;
                        }

                        // Teleport or lerp to position based on transition type
                        if (playgroundParticles.playgroundCache.propertyId[p] == thisManipulator.manipulatorId && thisManipulatorProperty.targets[playgroundParticles.playgroundCache.propertyTarget[p]%thisManipulatorProperty.targets.Count].available) {
                            if (thisManipulatorProperty.transition == MANIPULATORPROPERTYTRANSITIONC.None)
                                playgroundParticles.playgroundCache.position[p] = localSpace?
                                    thisManipulatorProperty.targets[playgroundParticles.playgroundCache.propertyTarget[p]%thisManipulatorProperty.targets.Count].localPosition
                                :
                                    thisManipulatorProperty.targets[playgroundParticles.playgroundCache.propertyTarget[p]%thisManipulatorProperty.targets.Count].position;
                            else if (thisManipulatorProperty.transition == MANIPULATORPROPERTYTRANSITIONC.Lerp) {
                                manipulatorDistance = thisManipulator.strengthDistanceEffect>0?Vector3.SqrMagnitude (manipulatorPosition - particlePosition)/thisManipulator.strengthDistanceEffect:10f;
                                playgroundParticles.playgroundCache.position[p] = localSpace?
                                        Vector3.Lerp(particlePosition, thisManipulatorProperty.targets[playgroundParticles.playgroundCache.propertyTarget[p]%thisManipulatorProperty.targets.Count].localPosition, (t*thisManipulatorProperty.strength*thisManipulator.strength/manipulatorDistance)/thisManipulator.strengthSmoothing)
                                :
                                            Vector3.Lerp(particlePosition, thisManipulatorProperty.targets[playgroundParticles.playgroundCache.propertyTarget[p]%thisManipulatorProperty.targets.Count].position, (t*thisManipulatorProperty.strength*thisManipulator.strength/manipulatorDistance)/thisManipulator.strengthSmoothing);
                                if (thisManipulatorProperty.zeroVelocityStrength>0)
                                    playgroundParticles.playgroundCache.velocity[p] = Vector3.Lerp(playgroundParticles.playgroundCache.velocity[p], Vector3.zero, t*thisManipulatorProperty.zeroVelocityStrength);
                            } else if (thisManipulatorProperty.transition == MANIPULATORPROPERTYTRANSITIONC.Linear) {
                                manipulatorDistance = thisManipulator.strengthDistanceEffect>0?Vector3.SqrMagnitude (manipulatorPosition - particlePosition)/thisManipulator.strengthDistanceEffect:10f;
                                playgroundParticles.playgroundCache.position[p] = localSpace?
                                        Vector3.MoveTowards(particlePosition, thisManipulatorProperty.targets[playgroundParticles.playgroundCache.propertyTarget[p]%thisManipulatorProperty.targets.Count].localPosition, (t*thisManipulatorProperty.strength*thisManipulator.strength/manipulatorDistance)/thisManipulator.strengthSmoothing)
                                :
                                            Vector3.MoveTowards(particlePosition, thisManipulatorProperty.targets[playgroundParticles.playgroundCache.propertyTarget[p]%thisManipulatorProperty.targets.Count].position, (t*thisManipulatorProperty.strength*thisManipulator.strength/manipulatorDistance)/thisManipulator.strengthSmoothing);
                                if (thisManipulatorProperty.zeroVelocityStrength>0)
                                    playgroundParticles.playgroundCache.velocity[p] = Vector3.Lerp(playgroundParticles.playgroundCache.velocity[p], Vector3.zero, t*thisManipulatorProperty.zeroVelocityStrength);
                            }

                            // This particle was changed by a target property
                            playgroundParticles.playgroundCache.changedByPropertyTarget[p] = true;
                        }
                    }
                    break;

                    // Death Property
                    case MANIPULATORPROPERTYTYPEC.Death:
                    if (thisManipulatorProperty.transition == MANIPULATORPROPERTYTRANSITIONC.None)
                        playgroundParticles.playgroundCache.life[p] = playgroundParticles.lifetime;
                    else {
                        manipulatorDistance = thisManipulator.strengthDistanceEffect>0?Vector3.SqrMagnitude (manipulatorPosition - particlePosition)/thisManipulator.strengthDistanceEffect:10f;
                        playgroundParticles.playgroundCache.birth[p] -= (t*thisManipulatorProperty.strength*thisManipulator.strength/manipulatorDistance)/thisManipulator.strengthSmoothing;
                    }

                    // This particle was changed by a death property
                    playgroundParticles.playgroundCache.changedByPropertyDeath[p] = true;
                    break;

                    // Attractors
                    case MANIPULATORPROPERTYTYPEC.Attractor:
                    if (!playgroundParticles.onlySourcePositioning) {
                        manipulatorDistance = thisManipulator.strengthDistanceEffect>0?Vector3.Distance (manipulatorPosition, playgroundParticles.playgroundCache.position[p])/thisManipulator.strengthDistanceEffect:10f;
                        playgroundParticles.playgroundCache.velocity[p] = Vector3.Lerp(playgroundParticles.playgroundCache.velocity[p], (manipulatorPosition-particlePosition)*((thisManipulatorProperty.strength*thisManipulator.strength)/manipulatorDistance), t*((thisManipulatorProperty.strength*thisManipulator.strength)/manipulatorDistance)/thisManipulator.strengthSmoothing);
                    }
                    break;

                    // Attractors Gravitational
                    case MANIPULATORPROPERTYTYPEC.Gravitational:
                    if (!playgroundParticles.onlySourcePositioning) {
                        manipulatorDistance = thisManipulator.strengthDistanceEffect>0?Vector3.Distance (manipulatorPosition, playgroundParticles.playgroundCache.position[p])/thisManipulator.strengthDistanceEffect:10f;
                        playgroundParticles.playgroundCache.velocity[p] = Vector3.Lerp(playgroundParticles.playgroundCache.velocity[p], (manipulatorPosition-particlePosition)*(thisManipulatorProperty.strength*thisManipulator.strength)/manipulatorDistance, t/thisManipulator.strengthSmoothing);
                    }
                    break;

                    // Repellents
                    case MANIPULATORPROPERTYTYPEC.Repellent:
                    if (!playgroundParticles.onlySourcePositioning) {
                        manipulatorDistance = thisManipulator.strengthDistanceEffect>0?Vector3.Distance (manipulatorPosition, playgroundParticles.playgroundCache.position[p])/thisManipulator.strengthDistanceEffect:10f;
                        playgroundParticles.playgroundCache.velocity[p] = Vector3.Lerp(playgroundParticles.playgroundCache.velocity[p], (particlePosition-manipulatorPosition)*((thisManipulatorProperty.strength*thisManipulator.strength)/manipulatorDistance), t*((thisManipulatorProperty.strength*thisManipulator.strength)/manipulatorDistance)/thisManipulator.strengthSmoothing);
                    }
                    break;

                    // Vortex
                    case MANIPULATORPROPERTYTYPEC.Vortex:
                    if (!playgroundParticles.onlySourcePositioning) {
                        manipulatorDistance = thisManipulator.strengthDistanceEffect>0?Vector3.Distance (manipulatorPosition, playgroundParticles.playgroundCache.position[p])/thisManipulator.strengthDistanceEffect:10f;
                        playgroundParticles.playgroundCache.velocity[p] = Vector3.Lerp(playgroundParticles.playgroundCache.velocity[p], ((manipulatorPosition-particlePosition)*(thisManipulator.strength*thisManipulatorProperty.strength)/manipulatorDistance)-Vector3.Cross(thisManipulator.transform.up, (manipulatorPosition-particlePosition))*(thisManipulator.strength*thisManipulatorProperty.strength)/manipulatorDistance, (t*(thisManipulator.strength*thisManipulatorProperty.strength)/manipulatorDistance)/thisManipulator.strengthSmoothing);
                    }
                    break;

                    // Turbulence
                    case MANIPULATORPROPERTYTYPEC.Turbulence:
                    if (!playgroundParticles.onlySourcePositioning && thisManipulatorProperty.turbulenceType!=TURBULENCETYPE.None) {
                        manipulatorDistance = thisManipulator.strengthDistanceEffect>0?Vector3.Distance (manipulatorPosition, particlePosition)/thisManipulator.strengthDistanceEffect:10f;
                        Turbulence (
                            playgroundParticles,
                            thisManipulatorProperty.turbulenceSimplex,
                            p,
                            t/thisManipulator.strengthSmoothing,
                            thisManipulatorProperty.turbulenceType,
                            thisManipulatorProperty.turbulenceTimeScale,
                            thisManipulatorProperty.turbulenceScale,
                            ((thisManipulatorProperty.strength*thisManipulator.strength)/manipulatorDistance),
                            thisManipulatorProperty.turbulenceApplyLifetimeStrength,
                            thisManipulatorProperty.turbulenceLifetimeStrength
                        );
                    }
                    break;

                    // Mesh Target
                    case MANIPULATORPROPERTYTYPEC.MeshTarget:
                    if (!playgroundParticles.onlySourcePositioning && thisManipulatorProperty.meshTarget.initialized) {

                        // Set target pointer
                        if (playgroundParticles.playgroundCache.propertyId[p] != thisManipulator.manipulatorId) {
                            playgroundParticles.playgroundCache.propertyTarget[p] = thisManipulatorProperty.targetSortingList[thisManipulatorProperty.targetPointer];
                            thisManipulatorProperty.targetPointer++; thisManipulatorProperty.targetPointer=thisManipulatorProperty.targetPointer%thisManipulatorProperty.meshTarget.vertexPositions.Length;
                            playgroundParticles.playgroundCache.propertyId[p] = thisManipulator.manipulatorId;
                        }

                        // Teleport or lerp to position based on transition type
                        if (playgroundParticles.playgroundCache.propertyId[p] == thisManipulator.manipulatorId) {
                            if (thisManipulatorProperty.transition == MANIPULATORPROPERTYTRANSITIONC.None) {
                                playgroundParticles.playgroundCache.position[p] = thisManipulatorProperty.meshTargetMatrix.MultiplyPoint3x4(thisManipulatorProperty.meshTarget.vertexPositions[playgroundParticles.playgroundCache.propertyTarget[p]%thisManipulatorProperty.meshTarget.vertexPositions.Length]);
                                playgroundParticles.playgroundCache.velocity[p] = Vector3.zero;
                            } else if (thisManipulatorProperty.transition == MANIPULATORPROPERTYTRANSITIONC.Lerp) {
                                    playgroundParticles.playgroundCache.position[p] = Vector3.Lerp(particlePosition, thisManipulatorProperty.meshTargetMatrix.MultiplyPoint3x4(thisManipulatorProperty.meshTarget.vertexPositions[playgroundParticles.playgroundCache.propertyTarget[p]%thisManipulatorProperty.meshTarget.vertexPositions.Length]), (t*thisManipulatorProperty.strength*thisManipulator.strength/manipulatorDistance)/thisManipulator.strengthSmoothing);
                                if (thisManipulatorProperty.zeroVelocityStrength>0)
                                    playgroundParticles.playgroundCache.velocity[p] = Vector3.Lerp(playgroundParticles.playgroundCache.velocity[p], Vector3.zero, t*thisManipulatorProperty.zeroVelocityStrength);
                            } else if (thisManipulatorProperty.transition == MANIPULATORPROPERTYTRANSITIONC.Linear) {
                                    playgroundParticles.playgroundCache.position[p] = Vector3.MoveTowards(particlePosition, thisManipulatorProperty.meshTargetMatrix.MultiplyPoint3x4(thisManipulatorProperty.meshTarget.vertexPositions[playgroundParticles.playgroundCache.propertyTarget[p]%thisManipulatorProperty.meshTarget.vertexPositions.Length]), (t*thisManipulatorProperty.strength*thisManipulator.strength/manipulatorDistance)/thisManipulator.strengthSmoothing);
                                if (thisManipulatorProperty.zeroVelocityStrength>0)
                                    playgroundParticles.playgroundCache.velocity[p] = Vector3.Lerp(playgroundParticles.playgroundCache.velocity[p], Vector3.zero, t*thisManipulatorProperty.zeroVelocityStrength);
                            }

                            // This particle was changed by a target property
                            playgroundParticles.playgroundCache.changedByPropertyTarget[p] = true;
                        }

                    }
                    break;

                    // Skinned Mesh Target
                    case MANIPULATORPROPERTYTYPEC.SkinnedMeshTarget:
                    if (!playgroundParticles.onlySourcePositioning && thisManipulatorProperty.skinnedMeshTarget.initialized) {

                        // Set target pointer
                        if (playgroundParticles.playgroundCache.propertyId[p] != thisManipulator.manipulatorId) {
                            playgroundParticles.playgroundCache.propertyTarget[p] = thisManipulatorProperty.targetSortingList[thisManipulatorProperty.targetPointer];
                            thisManipulatorProperty.targetPointer++; thisManipulatorProperty.targetPointer=thisManipulatorProperty.targetPointer%thisManipulatorProperty.skinnedMeshTarget.vertexPositions.Length;
                            playgroundParticles.playgroundCache.propertyId[p] = thisManipulator.manipulatorId;
                        }

                        // Teleport or lerp to position based on transition type
                        if (playgroundParticles.playgroundCache.propertyId[p] == thisManipulator.manipulatorId) {
                            if (thisManipulatorProperty.transition == MANIPULATORPROPERTYTRANSITIONC.None) {
                                playgroundParticles.playgroundCache.position[p] = thisManipulatorProperty.skinnedMeshTarget.vertexPositions[playgroundParticles.playgroundCache.propertyTarget[p]%thisManipulatorProperty.skinnedMeshTarget.vertexPositions.Length];
                                playgroundParticles.playgroundCache.velocity[p] = Vector3.zero;
                            } else if (thisManipulatorProperty.transition == MANIPULATORPROPERTYTRANSITIONC.Lerp) {
                                manipulatorDistance = thisManipulator.strengthDistanceEffect>0?Vector3.SqrMagnitude (manipulatorPosition - particlePosition)/thisManipulator.strengthDistanceEffect:10f;
                                playgroundParticles.playgroundCache.position[p] = Vector3.Lerp(particlePosition, thisManipulatorProperty.skinnedMeshTarget.vertexPositions[playgroundParticles.playgroundCache.propertyTarget[p]%thisManipulatorProperty.skinnedMeshTarget.vertexPositions.Length], t*(thisManipulatorProperty.strength*thisManipulator.strength/manipulatorDistance)/thisManipulator.strengthSmoothing);
                                if (thisManipulatorProperty.zeroVelocityStrength>0)
                                    playgroundParticles.playgroundCache.velocity[p] = Vector3.Lerp(playgroundParticles.playgroundCache.velocity[p], Vector3.zero, t*thisManipulatorProperty.zeroVelocityStrength);
                            } else if (thisManipulatorProperty.transition == MANIPULATORPROPERTYTRANSITIONC.Linear) {
                                manipulatorDistance = thisManipulator.strengthDistanceEffect>0?Vector3.SqrMagnitude (manipulatorPosition - particlePosition)/thisManipulator.strengthDistanceEffect:10f;
                                playgroundParticles.playgroundCache.position[p] = Vector3.MoveTowards(particlePosition, thisManipulatorProperty.skinnedMeshTarget.vertexPositions[playgroundParticles.playgroundCache.propertyTarget[p]%thisManipulatorProperty.skinnedMeshTarget.vertexPositions.Length], t*(thisManipulatorProperty.strength*thisManipulator.strength/manipulatorDistance)/thisManipulator.strengthSmoothing);
                                if (thisManipulatorProperty.zeroVelocityStrength>0)
                                    playgroundParticles.playgroundCache.velocity[p] = Vector3.Lerp(playgroundParticles.playgroundCache.velocity[p], Vector3.zero, t*thisManipulatorProperty.zeroVelocityStrength);
                            }

                            // This particle was changed by a target property
                            playgroundParticles.playgroundCache.changedByPropertyTarget[p] = true;
                        }
                    }
                    break;

                    // State Target
                    case MANIPULATORPROPERTYTYPEC.StateTarget:
                    if (!playgroundParticles.onlySourcePositioning && thisManipulatorProperty.stateTarget.initialized && !thisManipulatorProperty.stateTarget.IsInitializing()) {

                        // Set target pointer
                        if (playgroundParticles.playgroundCache.propertyId[p] != thisManipulator.manipulatorId) {
                            playgroundParticles.playgroundCache.propertyTarget[p] = thisManipulatorProperty.targetSortingList[thisManipulatorProperty.targetPointer%thisManipulatorProperty.targetSortingList.Length];
                            thisManipulatorProperty.targetPointer++; thisManipulatorProperty.targetPointer=thisManipulatorProperty.targetPointer%thisManipulatorProperty.stateTarget.positionLength;
                            playgroundParticles.playgroundCache.propertyId[p] = thisManipulator.manipulatorId;
                        }

                        // Teleport or lerp to position based on transition type
                        if (playgroundParticles.playgroundCache.propertyId[p] == thisManipulator.manipulatorId) {
                            Vector3 newPos = thisManipulatorProperty.stateTarget.stateTransformMx.MultiplyPoint3x4(thisManipulatorProperty.stateTarget.GetPosition(playgroundParticles.playgroundCache.propertyTarget[p]%thisManipulatorProperty.stateTarget.positionLength));
                            if (!thisManipulatorProperty.onlyPositionInRange || thisManipulatorProperty.onlyPositionInRange && thisManipulator.Contains (newPos, manipulatorPosition)) {
                                if (thisManipulatorProperty.transition == MANIPULATORPROPERTYTRANSITIONC.None) {
                                    playgroundParticles.playgroundCache.position[p] = newPos;
                                    playgroundParticles.playgroundCache.velocity[p] = Vector3.zero;
                                } else if (thisManipulatorProperty.transition == MANIPULATORPROPERTYTRANSITIONC.Lerp) {
                                    manipulatorDistance = thisManipulator.strengthDistanceEffect>0?Vector3.SqrMagnitude (manipulatorPosition - particlePosition)/thisManipulator.strengthDistanceEffect:10f;
                                    playgroundParticles.playgroundCache.position[p] = Vector3.Lerp(particlePosition, newPos, t*(thisManipulatorProperty.strength*thisManipulator.strength/manipulatorDistance)/thisManipulator.strengthSmoothing);
                                    if (thisManipulatorProperty.zeroVelocityStrength>0)
                                        playgroundParticles.playgroundCache.velocity[p] = Vector3.Lerp(playgroundParticles.playgroundCache.velocity[p], Vector3.zero, t*thisManipulatorProperty.zeroVelocityStrength);
                                } else if (thisManipulatorProperty.transition == MANIPULATORPROPERTYTRANSITIONC.Linear) {
                                    manipulatorDistance = thisManipulator.strengthDistanceEffect>0?Vector3.SqrMagnitude (manipulatorPosition - particlePosition)/thisManipulator.strengthDistanceEffect:10f;
                                    playgroundParticles.playgroundCache.position[p] = Vector3.MoveTowards(particlePosition, newPos, t*(thisManipulatorProperty.strength*thisManipulator.strength/manipulatorDistance)/thisManipulator.strengthSmoothing);
                                    if (thisManipulatorProperty.zeroVelocityStrength>0)
                                        playgroundParticles.playgroundCache.velocity[p] = Vector3.Lerp(playgroundParticles.playgroundCache.velocity[p], Vector3.zero, t*thisManipulatorProperty.zeroVelocityStrength);
                                }

                                // This particle was changed by a target property
                                playgroundParticles.playgroundCache.changedByPropertyTarget[p] = true;
                            }

                        }

                    }
                    break;

                    // Spline Target
                    case MANIPULATORPROPERTYTYPEC.SplineTarget:
                    if (!playgroundParticles.onlySourcePositioning && thisManipulatorProperty.SplineTargetIsReady()) {

                        // Set target pointer
                        if (playgroundParticles.playgroundCache.propertyId[p] != thisManipulator.manipulatorId) {
                            playgroundParticles.playgroundCache.propertyId[p] = thisManipulator.manipulatorId;
                        }

                        // Teleport or lerp to position based on transition type
                        if (playgroundParticles.playgroundCache.propertyId[p] == thisManipulator.manipulatorId) {
                            Vector3 newPos = thisManipulatorProperty.splineTarget.GetPoint(thisManipulatorProperty.splineTargetMethod==SPLINETARGETMETHOD.SplineTime? ((p*1f)/(playgroundParticles.particleCount*1f))+thisManipulatorProperty.splineTimeOffset : ((playgroundParticles.playgroundCache.life[p]+playgroundParticles.playgroundCache.lifetimeSubtraction[p])/playgroundParticles.lifetime)+thisManipulatorProperty.splineTimeOffset);
                            if (!thisManipulatorProperty.onlyPositionInRange || thisManipulatorProperty.onlyPositionInRange && thisManipulator.Contains (newPos, manipulatorPosition)) {
                                if (thisManipulatorProperty.transition == MANIPULATORPROPERTYTRANSITIONC.None) {
                                    playgroundParticles.playgroundCache.position[p] = newPos;
                                    playgroundParticles.playgroundCache.velocity[p] = Vector3.zero;
                                } else if (thisManipulatorProperty.transition == MANIPULATORPROPERTYTRANSITIONC.Lerp) {
                                    manipulatorDistance = thisManipulator.strengthDistanceEffect>0?Vector3.SqrMagnitude (manipulatorPosition - particlePosition)/thisManipulator.strengthDistanceEffect:10f;
                                    playgroundParticles.playgroundCache.position[p] = Vector3.Lerp(particlePosition, newPos, t*(thisManipulatorProperty.strength*thisManipulator.strength/manipulatorDistance)/thisManipulator.strengthSmoothing);
                                    if (thisManipulatorProperty.zeroVelocityStrength>0)
                                        playgroundParticles.playgroundCache.velocity[p] = Vector3.Lerp(playgroundParticles.playgroundCache.velocity[p], Vector3.zero, t*thisManipulatorProperty.zeroVelocityStrength);
                                } else if (thisManipulatorProperty.transition == MANIPULATORPROPERTYTRANSITIONC.Linear) {
                                    manipulatorDistance = thisManipulator.strengthDistanceEffect>0?Vector3.SqrMagnitude (manipulatorPosition - particlePosition)/thisManipulator.strengthDistanceEffect:10f;
                                    playgroundParticles.playgroundCache.position[p] = Vector3.MoveTowards(particlePosition, newPos, t*(thisManipulatorProperty.strength*thisManipulator.strength/manipulatorDistance)/thisManipulator.strengthSmoothing);
                                    if (thisManipulatorProperty.zeroVelocityStrength>0)
                                        playgroundParticles.playgroundCache.velocity[p] = Vector3.Lerp(playgroundParticles.playgroundCache.velocity[p], Vector3.zero, t*thisManipulatorProperty.zeroVelocityStrength);
                                }

                                // This particle was changed by a target property
                                playgroundParticles.playgroundCache.changedByPropertyTarget[p] = true;
                            }

                        }

                    }
                    break;
                }

                playgroundParticles.playgroundCache.changedByProperty[p] = true;

            } else {

                // Handle size outside
                if (thisManipulatorProperty.onlySizeInRange)
                    playgroundParticles.playgroundCache.changedByPropertySize[p] = false;

                // Handle colors outside of property manipulator range
                if (playgroundParticles.playgroundCache.propertyColorId[p] == thisManipulator.manipulatorId && (thisManipulatorProperty.type == MANIPULATORPROPERTYTYPEC.Color || thisManipulatorProperty.type == MANIPULATORPROPERTYTYPEC.LifetimeColor)) {

                    // Lerp back color with previous set key
                    if (playgroundParticles.playgroundCache.changedByPropertyColorLerp[p] && thisManipulatorProperty.transition != MANIPULATORPROPERTYTRANSITIONC.None && thisManipulatorProperty.onlyColorInRange) {
                        playgroundParticles.particleCache[p].color = Color.Lerp(playgroundParticles.particleCache[p].color, playgroundParticles.lifetimeColor.Evaluate(playgroundParticles.playgroundCache.life[p]/playgroundParticles.lifetime), t*thisManipulatorProperty.strength*thisManipulator.strength);
                    }

                    if (thisManipulatorProperty.type == MANIPULATORPROPERTYTYPEC.LifetimeColor && !thisManipulatorProperty.onlyColorInRange) {
                        if (thisManipulatorProperty.transition == MANIPULATORPROPERTYTRANSITIONC.None) {
                            playgroundParticles.particleCache[p].color = thisManipulatorProperty.lifetimeColor.Evaluate(playgroundParticles.lifetime>0?playgroundParticles.playgroundCache.life[p]/playgroundParticles.lifetime:0);
                        } else {
                            manipulatorDistance = thisManipulator.strengthDistanceEffect>0?Vector3.SqrMagnitude (manipulatorPosition - particlePosition)/thisManipulator.strengthDistanceEffect:10f;
                            playgroundParticles.particleCache[p].color = Color.Lerp(playgroundParticles.particleCache[p].color, thisManipulatorProperty.lifetimeColor.Evaluate(playgroundParticles.lifetime>0?playgroundParticles.playgroundCache.life[p]/playgroundParticles.lifetime:0), (t*thisManipulatorProperty.strength*thisManipulator.strength/manipulatorDistance)/thisManipulator.strengthSmoothing);
                        }
                    }

                    if (thisManipulatorProperty.onlyColorInRange)
                        playgroundParticles.playgroundCache.changedByPropertyColor[p] = false;
                }

                // Position onto targets when outside of range
                if (!playgroundParticles.onlySourcePositioning && !thisManipulatorProperty.onlyPositionInRange && thisManipulatorProperty.transition != MANIPULATORPROPERTYTRANSITIONC.None) {

                    // Target (Transform) positioning outside of range
                    if (thisManipulatorProperty.type == MANIPULATORPROPERTYTYPEC.Target) {
                        if (thisManipulatorProperty.targets.Count>0 && thisManipulatorProperty.targets[playgroundParticles.playgroundCache.propertyTarget[p]%thisManipulatorProperty.targets.Count]!=null) {
                            if (playgroundParticles.playgroundCache.changedByPropertyTarget[p] && thisManipulatorProperty.targets[playgroundParticles.playgroundCache.propertyTarget[p]%thisManipulatorProperty.targets.Count].available && playgroundParticles.playgroundCache.propertyId[p] == thisManipulator.transform.GetInstanceID()) {
                                if (thisManipulatorProperty.transition == MANIPULATORPROPERTYTRANSITIONC.Lerp)
                                    playgroundParticles.playgroundCache.position[p] = localSpace?
                                        Vector3.Lerp(particlePosition, thisManipulatorProperty.targets[playgroundParticles.playgroundCache.propertyTarget[p]%thisManipulatorProperty.targets.Count].localPosition, t*(thisManipulatorProperty.strength*thisManipulator.strength)/thisManipulator.strengthSmoothing)
                                        :
                                        Vector3.Lerp(particlePosition, thisManipulatorProperty.targets[playgroundParticles.playgroundCache.propertyTarget[p]%thisManipulatorProperty.targets.Count].position, t*(thisManipulatorProperty.strength*thisManipulator.strength)/thisManipulator.strengthSmoothing);
                                else
                                    playgroundParticles.playgroundCache.position[p] = localSpace?
                                        Vector3.MoveTowards(particlePosition, thisManipulatorProperty.targets[playgroundParticles.playgroundCache.propertyTarget[p]%thisManipulatorProperty.targets.Count].localPosition, t*(thisManipulatorProperty.strength*thisManipulator.strength)/thisManipulator.strengthSmoothing)
                                        :
                                        Vector3.MoveTowards(particlePosition, thisManipulatorProperty.targets[playgroundParticles.playgroundCache.propertyTarget[p]%thisManipulatorProperty.targets.Count].position, t*(thisManipulatorProperty.strength*thisManipulator.strength)/thisManipulator.strengthSmoothing);

                                if (thisManipulatorProperty.zeroVelocityStrength>0)
                                    playgroundParticles.playgroundCache.velocity[p] = Vector3.Lerp(playgroundParticles.playgroundCache.velocity[p], Vector3.zero, t*thisManipulatorProperty.zeroVelocityStrength);
                            }
                        }
                    }

                    // Mesh Target positioning outside of range
                    if (thisManipulatorProperty.type == MANIPULATORPROPERTYTYPEC.MeshTarget && thisManipulatorProperty.meshTarget.initialized && playgroundParticles.playgroundCache.propertyId[p] == thisManipulator.manipulatorId) {
                        if (thisManipulatorProperty.transition == MANIPULATORPROPERTYTRANSITIONC.Lerp) {
                            manipulatorDistance = thisManipulator.strengthDistanceEffect>0?Vector3.SqrMagnitude (manipulatorPosition - particlePosition)/thisManipulator.strengthDistanceEffect:10f;
                            playgroundParticles.playgroundCache.position[p] = Vector3.Lerp(particlePosition, thisManipulatorProperty.meshTargetMatrix.MultiplyPoint3x4(thisManipulatorProperty.meshTarget.vertexPositions[playgroundParticles.playgroundCache.propertyTarget[p]%thisManipulatorProperty.meshTarget.vertexPositions.Length]), (t*thisManipulatorProperty.strength*thisManipulator.strength/manipulatorDistance)/thisManipulator.strengthSmoothing);
                            if (thisManipulatorProperty.zeroVelocityStrength>0)
                                playgroundParticles.playgroundCache.velocity[p] = Vector3.Lerp(playgroundParticles.playgroundCache.velocity[p], Vector3.zero, t*thisManipulatorProperty.zeroVelocityStrength);
                        } else if (thisManipulatorProperty.transition == MANIPULATORPROPERTYTRANSITIONC.Linear) {
                            manipulatorDistance = thisManipulator.strengthDistanceEffect>0?Vector3.SqrMagnitude (manipulatorPosition - particlePosition)/thisManipulator.strengthDistanceEffect:10f;
                            playgroundParticles.playgroundCache.position[p] = Vector3.MoveTowards(particlePosition, thisManipulatorProperty.meshTargetMatrix.MultiplyPoint3x4(thisManipulatorProperty.meshTarget.vertexPositions[playgroundParticles.playgroundCache.propertyTarget[p]%thisManipulatorProperty.meshTarget.vertexPositions.Length]), (t*thisManipulatorProperty.strength*thisManipulator.strength/manipulatorDistance)/thisManipulator.strengthSmoothing);
                            if (thisManipulatorProperty.zeroVelocityStrength>0)
                                playgroundParticles.playgroundCache.velocity[p] = Vector3.Lerp(playgroundParticles.playgroundCache.velocity[p], Vector3.zero, t*thisManipulatorProperty.zeroVelocityStrength);
                        }
                    }

                    // Skinned Mesh Target positioning outside of range
                    if (thisManipulatorProperty.type == MANIPULATORPROPERTYTYPEC.SkinnedMeshTarget && thisManipulatorProperty.skinnedMeshTarget.initialized && playgroundParticles.playgroundCache.propertyId[p] == thisManipulator.manipulatorId) {
                        if (thisManipulatorProperty.transition == MANIPULATORPROPERTYTRANSITIONC.Lerp) {
                            manipulatorDistance = thisManipulator.strengthDistanceEffect>0?Vector3.SqrMagnitude (manipulatorPosition - particlePosition)/thisManipulator.strengthDistanceEffect:10f;
                            playgroundParticles.playgroundCache.position[p] = Vector3.Lerp(particlePosition, thisManipulatorProperty.skinnedMeshTarget.vertexPositions[playgroundParticles.playgroundCache.propertyTarget[p]%thisManipulatorProperty.skinnedMeshTarget.vertexPositions.Length], t*(thisManipulatorProperty.strength*thisManipulator.strength/manipulatorDistance)/thisManipulator.strengthSmoothing);
                            if (thisManipulatorProperty.zeroVelocityStrength>0)
                                playgroundParticles.playgroundCache.velocity[p] = Vector3.Lerp(playgroundParticles.playgroundCache.velocity[p], Vector3.zero, t*thisManipulatorProperty.zeroVelocityStrength);
                        } else if (thisManipulatorProperty.transition == MANIPULATORPROPERTYTRANSITIONC.Linear) {
                            manipulatorDistance = thisManipulator.strengthDistanceEffect>0?Vector3.SqrMagnitude (manipulatorPosition - particlePosition)/thisManipulator.strengthDistanceEffect:10f;
                            playgroundParticles.playgroundCache.position[p] = Vector3.MoveTowards(particlePosition, thisManipulatorProperty.skinnedMeshTarget.vertexPositions[playgroundParticles.playgroundCache.propertyTarget[p]%thisManipulatorProperty.skinnedMeshTarget.vertexPositions.Length], t*(thisManipulatorProperty.strength*thisManipulator.strength/manipulatorDistance)/thisManipulator.strengthSmoothing);
                            if (thisManipulatorProperty.zeroVelocityStrength>0)
                                playgroundParticles.playgroundCache.velocity[p] = Vector3.Lerp(playgroundParticles.playgroundCache.velocity[p], Vector3.zero, t*thisManipulatorProperty.zeroVelocityStrength);
                        }
                    }

                    // State Target positioning outside of range
                    if (thisManipulatorProperty.type == MANIPULATORPROPERTYTYPEC.StateTarget && thisManipulatorProperty.stateTarget.initialized && !thisManipulatorProperty.stateTarget.IsInitializing() && playgroundParticles.playgroundCache.propertyId[p] == thisManipulator.manipulatorId) {
                        if (thisManipulatorProperty.transition == MANIPULATORPROPERTYTRANSITIONC.Lerp) {
                            manipulatorDistance = thisManipulator.strengthDistanceEffect>0?Vector3.SqrMagnitude (manipulatorPosition - particlePosition)/thisManipulator.strengthDistanceEffect:10f;
                            playgroundParticles.playgroundCache.position[p] = Vector3.Lerp(particlePosition, thisManipulatorProperty.stateTarget.stateTransformMx.MultiplyPoint3x4(thisManipulatorProperty.stateTarget.GetPosition(playgroundParticles.playgroundCache.propertyTarget[p]%thisManipulatorProperty.stateTarget.positionLength)), t*(thisManipulatorProperty.strength*thisManipulator.strength/manipulatorDistance)/thisManipulator.strengthSmoothing);
                            if (thisManipulatorProperty.zeroVelocityStrength>0)
                                playgroundParticles.playgroundCache.velocity[p] = Vector3.Lerp(playgroundParticles.playgroundCache.velocity[p], Vector3.zero, t*thisManipulatorProperty.zeroVelocityStrength);
                        } else if (thisManipulatorProperty.transition == MANIPULATORPROPERTYTRANSITIONC.Linear) {
                            manipulatorDistance = thisManipulator.strengthDistanceEffect>0?Vector3.SqrMagnitude (manipulatorPosition - particlePosition)/thisManipulator.strengthDistanceEffect:10f;
                            playgroundParticles.playgroundCache.position[p] = Vector3.MoveTowards(particlePosition, thisManipulatorProperty.stateTarget.stateTransformMx.MultiplyPoint3x4(thisManipulatorProperty.stateTarget.GetPosition(playgroundParticles.playgroundCache.propertyTarget[p]%thisManipulatorProperty.stateTarget.positionLength)), t*(thisManipulatorProperty.strength*thisManipulator.strength/manipulatorDistance)/thisManipulator.strengthSmoothing);
                            if (thisManipulatorProperty.zeroVelocityStrength>0)
                                playgroundParticles.playgroundCache.velocity[p] = Vector3.Lerp(playgroundParticles.playgroundCache.velocity[p], Vector3.zero, t*thisManipulatorProperty.zeroVelocityStrength);
                        }
                    }
                }
            }
        }
		// Calculate the effect from manipulator properties
		public static void PropertyManipulator (PlaygroundParticlesC playgroundParticles, ManipulatorObjectC thisManipulator, ManipulatorPropertyC thisManipulatorProperty, int p, float t, Vector3 particlePosition, Vector3 manipulatorPosition, float manipulatorDistance, bool localSpace) {
			if (thisManipulator.Contains(particlePosition, manipulatorPosition)) {
				switch (thisManipulatorProperty.type) {
					
					// Velocity Property
					case MANIPULATORPROPERTYTYPEC.Velocity:
					if (thisManipulatorProperty.transition == MANIPULATORPROPERTYTRANSITIONC.None)
						playgroundParticles.playgroundCache.velocity[p] = thisManipulatorProperty.useLocalRotation?
							thisManipulatorProperty.localVelocity
							:
							thisManipulatorProperty.velocity;
					else
						playgroundParticles.playgroundCache.velocity[p] = Vector3.Lerp(playgroundParticles.playgroundCache.velocity[p], thisManipulatorProperty.useLocalRotation?
							thisManipulatorProperty.localVelocity
							:
						thisManipulatorProperty.velocity, (t*thisManipulatorProperty.strength*thisManipulator.strength/manipulatorDistance)/thisManipulator.strengthSmoothing);
					break;
					
					// Additive Velocity Property
					case MANIPULATORPROPERTYTYPEC.AdditiveVelocity:
					if (thisManipulatorProperty.transition == MANIPULATORPROPERTYTRANSITIONC.None)
						playgroundParticles.playgroundCache.velocity[p] += thisManipulatorProperty.useLocalRotation?
							thisManipulatorProperty.localVelocity*(t*thisManipulatorProperty.strength*thisManipulator.strength)
							:
							thisManipulatorProperty.velocity*(t*thisManipulatorProperty.strength*thisManipulator.strength);
					else
						playgroundParticles.playgroundCache.velocity[p] += Vector3.Lerp(playgroundParticles.playgroundCache.velocity[p], thisManipulatorProperty.useLocalRotation?
						    thisManipulatorProperty.localVelocity 
						    : 
						    thisManipulatorProperty.velocity,
						(t*thisManipulatorProperty.strength*thisManipulator.strength/manipulatorDistance)/thisManipulator.strengthSmoothing);
					break;
					
					// Color Property
					case MANIPULATORPROPERTYTYPEC.Color:
					Color staticColor;
					if (thisManipulatorProperty.transition == MANIPULATORPROPERTYTRANSITIONC.None) {
						if (thisManipulatorProperty.keepColorAlphas) {
							staticColor = thisManipulatorProperty.color;
							staticColor.a = Mathf.Clamp(playgroundParticles.lifetimeColor.Evaluate(playgroundParticles.playgroundCache.life[p]/playgroundParticles.lifetime).a, 0, staticColor.a);
							playgroundParticles.particleCache[p].color = staticColor;
						} else playgroundParticles.particleCache[p].color = thisManipulatorProperty.color;
					} else {
						if (thisManipulatorProperty.keepColorAlphas) {
							staticColor = thisManipulatorProperty.color;
							staticColor.a = Mathf.Clamp(playgroundParticles.lifetimeColor.Evaluate(playgroundParticles.playgroundCache.life[p]/playgroundParticles.lifetime).a, 0, staticColor.a);
							playgroundParticles.particleCache[p].color = Color.Lerp(playgroundParticles.particleCache[p].color, staticColor, (t*thisManipulatorProperty.strength*thisManipulator.strength/manipulatorDistance)/thisManipulator.strengthSmoothing);
						} else playgroundParticles.particleCache[p].color = Color.Lerp(playgroundParticles.particleCache[p].color, thisManipulatorProperty.color, (t*thisManipulatorProperty.strength*thisManipulator.strength/manipulatorDistance)/thisManipulator.strengthSmoothing);
						playgroundParticles.playgroundCache.changedByPropertyColorLerp[p] = true;
					}
					
					// Only color in range of manipulator boundaries
					if (!thisManipulatorProperty.onlyColorInRange)
						playgroundParticles.playgroundCache.changedByPropertyColor[p] = true;

					// Keep alpha of original color
					if (thisManipulatorProperty.keepColorAlphas)
						playgroundParticles.playgroundCache.changedByPropertyColorKeepAlpha[p] = true;
					
					// Set color pairing key
					else if (playgroundParticles.playgroundCache.propertyColorId[p] != thisManipulator.manipulatorId) {
						playgroundParticles.playgroundCache.propertyColorId[p] = thisManipulator.manipulatorId;
					}
					break;
					
					// Lifetime Color Property
					case MANIPULATORPROPERTYTYPEC.LifetimeColor:
					if (thisManipulatorProperty.transition == MANIPULATORPROPERTYTRANSITIONC.None) {
						playgroundParticles.particleCache[p].color = thisManipulatorProperty.lifetimeColor.Evaluate(playgroundParticles.lifetime>0?playgroundParticles.playgroundCache.life[p]/playgroundParticles.lifetime:0);
					} else {
						playgroundParticles.particleCache[p].color = Color.Lerp(playgroundParticles.particleCache[p].color, thisManipulatorProperty.lifetimeColor.Evaluate(playgroundParticles.lifetime>0?playgroundParticles.playgroundCache.life[p]/playgroundParticles.lifetime:0), (t*thisManipulatorProperty.strength*thisManipulator.strength/manipulatorDistance)/thisManipulator.strengthSmoothing);
						playgroundParticles.playgroundCache.changedByPropertyColorLerp[p] = true;
					}
					
					// Only color in range of manipulator boundaries
					if (!thisManipulatorProperty.onlyColorInRange)
						playgroundParticles.playgroundCache.changedByPropertyColor[p] = true;
					
					// Set color pairing key
					else if (playgroundParticles.playgroundCache.propertyColorId[p] != thisManipulator.manipulatorId) {
						playgroundParticles.playgroundCache.propertyColorId[p] = thisManipulator.manipulatorId;
					}
					break;
					
					// Size Property
					case MANIPULATORPROPERTYTYPEC.Size:
					if (thisManipulatorProperty.transition == MANIPULATORPROPERTYTRANSITIONC.None)
						playgroundParticles.playgroundCache.size[p] = thisManipulatorProperty.size;
					else if (thisManipulatorProperty.transition == MANIPULATORPROPERTYTRANSITIONC.Lerp)
						playgroundParticles.playgroundCache.size[p] = Mathf.Lerp(playgroundParticles.playgroundCache.size[p], thisManipulatorProperty.size, (t*thisManipulatorProperty.strength*thisManipulator.strength/manipulatorDistance)/thisManipulator.strengthSmoothing);
					else if (thisManipulatorProperty.transition == MANIPULATORPROPERTYTRANSITIONC.Linear)
						playgroundParticles.playgroundCache.size[p] = Mathf.MoveTowards(playgroundParticles.playgroundCache.size[p], thisManipulatorProperty.size, (t*thisManipulatorProperty.strength*thisManipulator.strength/manipulatorDistance)/thisManipulator.strengthSmoothing);
					playgroundParticles.playgroundCache.changedByPropertySize[p] = true;
					break;
					
					// Target Property
					case MANIPULATORPROPERTYTYPEC.Target:
					if (thisManipulatorProperty.targets.Count>0 && thisManipulatorProperty.targets[thisManipulatorProperty.targetPointer].available) {
						
						
						// Set target pointer
						if (playgroundParticles.playgroundCache.propertyId[p] != thisManipulator.manipulatorId) {

							playgroundParticles.playgroundCache.propertyTarget[p] = thisManipulatorProperty.targetPointer;
							thisManipulatorProperty.targetPointer++; thisManipulatorProperty.targetPointer=thisManipulatorProperty.targetPointer%thisManipulatorProperty.targets.Count;
							playgroundParticles.playgroundCache.propertyId[p] = thisManipulator.manipulatorId;
						}

						// Teleport or lerp to position based on transition type
						if (playgroundParticles.playgroundCache.propertyId[p] == thisManipulator.manipulatorId && thisManipulatorProperty.targets[playgroundParticles.playgroundCache.propertyTarget[p]%thisManipulatorProperty.targets.Count].available) {
							if (thisManipulatorProperty.transition == MANIPULATORPROPERTYTRANSITIONC.None)
								playgroundParticles.playgroundCache.position[p] = localSpace? 
									thisManipulatorProperty.targets[playgroundParticles.playgroundCache.propertyTarget[p]%thisManipulatorProperty.targets.Count].localPosition
								: 
									thisManipulatorProperty.targets[playgroundParticles.playgroundCache.propertyTarget[p]%thisManipulatorProperty.targets.Count].position;
							else if (thisManipulatorProperty.transition == MANIPULATORPROPERTYTRANSITIONC.Lerp) {
								playgroundParticles.playgroundCache.position[p] = localSpace? 
										Vector3.Lerp(particlePosition, thisManipulatorProperty.targets[playgroundParticles.playgroundCache.propertyTarget[p]%thisManipulatorProperty.targets.Count].localPosition, (t*thisManipulatorProperty.strength*thisManipulator.strength/manipulatorDistance)/thisManipulator.strengthSmoothing)
								:
											Vector3.Lerp(particlePosition, thisManipulatorProperty.targets[playgroundParticles.playgroundCache.propertyTarget[p]%thisManipulatorProperty.targets.Count].position, (t*thisManipulatorProperty.strength*thisManipulator.strength/manipulatorDistance)/thisManipulator.strengthSmoothing);
								if (thisManipulatorProperty.zeroVelocityStrength>0)
									playgroundParticles.playgroundCache.velocity[p] = Vector3.Lerp(playgroundParticles.playgroundCache.velocity[p], Vector3.zero, t*thisManipulatorProperty.zeroVelocityStrength);
							} else if (thisManipulatorProperty.transition == MANIPULATORPROPERTYTRANSITIONC.Linear) {
								playgroundParticles.playgroundCache.position[p] = localSpace?
										Vector3.MoveTowards(particlePosition, thisManipulatorProperty.targets[playgroundParticles.playgroundCache.propertyTarget[p]%thisManipulatorProperty.targets.Count].localPosition, (t*thisManipulatorProperty.strength*thisManipulator.strength/manipulatorDistance)/thisManipulator.strengthSmoothing)
								:
											Vector3.MoveTowards(particlePosition, thisManipulatorProperty.targets[playgroundParticles.playgroundCache.propertyTarget[p]%thisManipulatorProperty.targets.Count].position, (t*thisManipulatorProperty.strength*thisManipulator.strength/manipulatorDistance)/thisManipulator.strengthSmoothing);
								if (thisManipulatorProperty.zeroVelocityStrength>0)
									playgroundParticles.playgroundCache.velocity[p] = Vector3.Lerp(playgroundParticles.playgroundCache.velocity[p], Vector3.zero, t*thisManipulatorProperty.zeroVelocityStrength);
							}
							
							// This particle was changed by a target property
							playgroundParticles.playgroundCache.changedByPropertyTarget[p] = true;
						}
					}
					break;
					
					// Death Property
					case MANIPULATORPROPERTYTYPEC.Death:
					if (thisManipulatorProperty.transition == MANIPULATORPROPERTYTRANSITIONC.None)
						playgroundParticles.playgroundCache.life[p] = playgroundParticles.lifetime;
					else
						playgroundParticles.playgroundCache.birth[p] -= (t*thisManipulatorProperty.strength*thisManipulator.strength/manipulatorDistance)/thisManipulator.strengthSmoothing;
					
					// This particle was changed by a death property
					playgroundParticles.playgroundCache.changedByPropertyDeath[p] = true;
					break;
					
					
					// Attractors
					case MANIPULATORPROPERTYTYPEC.Attractor:
					if (!playgroundParticles.onlySourcePositioning) {
						playgroundParticles.playgroundCache.velocity[p] = Vector3.Lerp(playgroundParticles.playgroundCache.velocity[p], (manipulatorPosition-particlePosition)*((thisManipulatorProperty.strength*thisManipulator.strength)/manipulatorDistance), t*((thisManipulatorProperty.strength*thisManipulator.strength)/manipulatorDistance)/thisManipulator.strengthSmoothing);
					}
					break;
					
					// Attractors Gravitational
					case MANIPULATORPROPERTYTYPEC.Gravitational:
					if (!playgroundParticles.onlySourcePositioning) {
						playgroundParticles.playgroundCache.velocity[p] = Vector3.Lerp(playgroundParticles.playgroundCache.velocity[p], (manipulatorPosition-particlePosition)*(thisManipulatorProperty.strength*thisManipulator.strength)/manipulatorDistance, t/thisManipulator.strengthSmoothing);
					}
					break;
					
					// Repellents 
					case MANIPULATORPROPERTYTYPEC.Repellent:
					if (!playgroundParticles.onlySourcePositioning) {
						playgroundParticles.playgroundCache.velocity[p] = Vector3.Lerp(playgroundParticles.playgroundCache.velocity[p], (particlePosition-manipulatorPosition)*((thisManipulatorProperty.strength*thisManipulator.strength)/manipulatorDistance), t*((thisManipulatorProperty.strength*thisManipulator.strength)/manipulatorDistance)/thisManipulator.strengthSmoothing);
					}
					break;

					// Vortex
					case MANIPULATORPROPERTYTYPEC.Vortex:
					if (!playgroundParticles.onlySourcePositioning) {
						playgroundParticles.playgroundCache.velocity[p] = Vector3.Lerp(playgroundParticles.playgroundCache.velocity[p], ((manipulatorPosition-particlePosition)*(thisManipulator.strength*thisManipulatorProperty.strength)/manipulatorDistance)-Vector3.Cross(thisManipulator.transform.up, (manipulatorPosition-particlePosition))*(thisManipulator.strength*thisManipulatorProperty.strength)/manipulatorDistance, (t*(thisManipulator.strength*thisManipulatorProperty.strength)/manipulatorDistance)/thisManipulator.strengthSmoothing);
					}
					break;

					// Mesh Target
					case MANIPULATORPROPERTYTYPEC.MeshTarget:
					if (!playgroundParticles.onlySourcePositioning && thisManipulatorProperty.meshTarget.initialized) {

						// Set target pointer
						if (playgroundParticles.playgroundCache.propertyId[p] != thisManipulator.manipulatorId) {
							playgroundParticles.playgroundCache.propertyTarget[p] = thisManipulatorProperty.targetSortingList[thisManipulatorProperty.targetPointer];
							thisManipulatorProperty.targetPointer++; thisManipulatorProperty.targetPointer=thisManipulatorProperty.targetPointer%thisManipulatorProperty.meshTarget.vertexPositions.Length;
							playgroundParticles.playgroundCache.propertyId[p] = thisManipulator.manipulatorId;
						}

						// Teleport or lerp to position based on transition type
						if (playgroundParticles.playgroundCache.propertyId[p] == thisManipulator.manipulatorId) {
							if (thisManipulatorProperty.transition == MANIPULATORPROPERTYTRANSITIONC.None) {
								playgroundParticles.playgroundCache.position[p] = thisManipulatorProperty.meshTargetMatrix.MultiplyPoint3x4(thisManipulatorProperty.meshTarget.vertexPositions[playgroundParticles.playgroundCache.propertyTarget[p]%thisManipulatorProperty.meshTarget.vertexPositions.Length]);
								playgroundParticles.playgroundCache.velocity[p] = Vector3.zero;
							} else if (thisManipulatorProperty.transition == MANIPULATORPROPERTYTRANSITIONC.Lerp) {
									playgroundParticles.playgroundCache.position[p] = Vector3.Lerp(particlePosition, thisManipulatorProperty.meshTargetMatrix.MultiplyPoint3x4(thisManipulatorProperty.meshTarget.vertexPositions[playgroundParticles.playgroundCache.propertyTarget[p]%thisManipulatorProperty.meshTarget.vertexPositions.Length]), (t*thisManipulatorProperty.strength*thisManipulator.strength/manipulatorDistance)/thisManipulator.strengthSmoothing);
								if (thisManipulatorProperty.zeroVelocityStrength>0)
									playgroundParticles.playgroundCache.velocity[p] = Vector3.Lerp(playgroundParticles.playgroundCache.velocity[p], Vector3.zero, t*thisManipulatorProperty.zeroVelocityStrength);
							} else if (thisManipulatorProperty.transition == MANIPULATORPROPERTYTRANSITIONC.Linear) {
									playgroundParticles.playgroundCache.position[p] = Vector3.MoveTowards(particlePosition, thisManipulatorProperty.meshTargetMatrix.MultiplyPoint3x4(thisManipulatorProperty.meshTarget.vertexPositions[playgroundParticles.playgroundCache.propertyTarget[p]%thisManipulatorProperty.meshTarget.vertexPositions.Length]), (t*thisManipulatorProperty.strength*thisManipulator.strength/manipulatorDistance)/thisManipulator.strengthSmoothing);
								if (thisManipulatorProperty.zeroVelocityStrength>0)
									playgroundParticles.playgroundCache.velocity[p] = Vector3.Lerp(playgroundParticles.playgroundCache.velocity[p], Vector3.zero, t*thisManipulatorProperty.zeroVelocityStrength);
							}
							
							// This particle was changed by a target property
							playgroundParticles.playgroundCache.changedByPropertyTarget[p] = true;
						}

					}
					break;
				
					// Skinned Mesh Target
					case MANIPULATORPROPERTYTYPEC.SkinnedMeshTarget:
					if (!playgroundParticles.onlySourcePositioning && thisManipulatorProperty.skinnedMeshTarget.initialized) {
							
						// Set target pointer
						if (playgroundParticles.playgroundCache.propertyId[p] != thisManipulator.manipulatorId) {
							playgroundParticles.playgroundCache.propertyTarget[p] = thisManipulatorProperty.targetSortingList[thisManipulatorProperty.targetPointer];
							thisManipulatorProperty.targetPointer++; thisManipulatorProperty.targetPointer=thisManipulatorProperty.targetPointer%thisManipulatorProperty.skinnedMeshTarget.vertexPositions.Length;
							playgroundParticles.playgroundCache.propertyId[p] = thisManipulator.manipulatorId;
						}

						// Teleport or lerp to position based on transition type
						if (playgroundParticles.playgroundCache.propertyId[p] == thisManipulator.manipulatorId) {
							if (thisManipulatorProperty.transition == MANIPULATORPROPERTYTRANSITIONC.None) {
								playgroundParticles.playgroundCache.position[p] = thisManipulatorProperty.skinnedMeshTarget.vertexPositions[playgroundParticles.playgroundCache.propertyTarget[p]%thisManipulatorProperty.skinnedMeshTarget.vertexPositions.Length];
								playgroundParticles.playgroundCache.velocity[p] = Vector3.zero;
							} else if (thisManipulatorProperty.transition == MANIPULATORPROPERTYTRANSITIONC.Lerp) {
									playgroundParticles.playgroundCache.position[p] = Vector3.Lerp(particlePosition, thisManipulatorProperty.skinnedMeshTarget.vertexPositions[playgroundParticles.playgroundCache.propertyTarget[p]%thisManipulatorProperty.skinnedMeshTarget.vertexPositions.Length], t*(thisManipulatorProperty.strength*thisManipulator.strength/manipulatorDistance)/thisManipulator.strengthSmoothing);
								if (thisManipulatorProperty.zeroVelocityStrength>0)
									playgroundParticles.playgroundCache.velocity[p] = Vector3.Lerp(playgroundParticles.playgroundCache.velocity[p], Vector3.zero, t*thisManipulatorProperty.zeroVelocityStrength);
							} else if (thisManipulatorProperty.transition == MANIPULATORPROPERTYTRANSITIONC.Linear) {
									playgroundParticles.playgroundCache.position[p] = Vector3.MoveTowards(particlePosition, thisManipulatorProperty.skinnedMeshTarget.vertexPositions[playgroundParticles.playgroundCache.propertyTarget[p]%thisManipulatorProperty.skinnedMeshTarget.vertexPositions.Length], t*(thisManipulatorProperty.strength*thisManipulator.strength/manipulatorDistance)/thisManipulator.strengthSmoothing);
								if (thisManipulatorProperty.zeroVelocityStrength>0)
									playgroundParticles.playgroundCache.velocity[p] = Vector3.Lerp(playgroundParticles.playgroundCache.velocity[p], Vector3.zero, t*thisManipulatorProperty.zeroVelocityStrength);
							}
							
							// This particle was changed by a target property
							playgroundParticles.playgroundCache.changedByPropertyTarget[p] = true;
						}
					}
					break;
				}
				
				playgroundParticles.playgroundCache.changedByProperty[p] = true;
				
			} else {
				
				// Handle colors outside of property manipulator range
				if (playgroundParticles.playgroundCache.propertyColorId[p] == thisManipulator.transform.GetInstanceID() && (thisManipulatorProperty.type == MANIPULATORPROPERTYTYPEC.Color || thisManipulatorProperty.type == MANIPULATORPROPERTYTYPEC.LifetimeColor)) {

					// Lerp back color with previous set key
					if (playgroundParticles.playgroundCache.changedByPropertyColorLerp[p] && thisManipulatorProperty.transition != MANIPULATORPROPERTYTRANSITIONC.None && thisManipulatorProperty.onlyColorInRange)
						playgroundParticles.particleCache[p].color = Color.Lerp(playgroundParticles.particleCache[p].color, playgroundParticles.lifetimeColor.Evaluate(playgroundParticles.playgroundCache.life[p]/playgroundParticles.lifetime), t*thisManipulatorProperty.strength*thisManipulator.strength);
				}

				// Position onto targets when outside of range
				if (!playgroundParticles.onlySourcePositioning && !thisManipulatorProperty.onlyPositionInRange && thisManipulatorProperty.transition != MANIPULATORPROPERTYTRANSITIONC.None) {

					// Target positioning outside of range
					if (thisManipulatorProperty.type == MANIPULATORPROPERTYTYPEC.Target) {
						if (thisManipulatorProperty.targets.Count>0 && thisManipulatorProperty.targets[playgroundParticles.playgroundCache.propertyTarget[p]%thisManipulatorProperty.targets.Count]!=null) {
							if (playgroundParticles.playgroundCache.changedByPropertyTarget[p] && thisManipulatorProperty.targets[playgroundParticles.playgroundCache.propertyTarget[p]%thisManipulatorProperty.targets.Count].available && playgroundParticles.playgroundCache.propertyId[p] == thisManipulator.transform.GetInstanceID()) {
								if (thisManipulatorProperty.transition == MANIPULATORPROPERTYTRANSITIONC.Lerp)
									playgroundParticles.playgroundCache.position[p] = localSpace?
										Vector3.Lerp(particlePosition, thisManipulatorProperty.targets[playgroundParticles.playgroundCache.propertyTarget[p]%thisManipulatorProperty.targets.Count].localPosition, t*(thisManipulatorProperty.strength*thisManipulator.strength)/thisManipulator.strengthSmoothing)
										:	
										Vector3.Lerp(particlePosition, thisManipulatorProperty.targets[playgroundParticles.playgroundCache.propertyTarget[p]%thisManipulatorProperty.targets.Count].position, t*(thisManipulatorProperty.strength*thisManipulator.strength)/thisManipulator.strengthSmoothing);
								else
									playgroundParticles.playgroundCache.position[p] = localSpace?
										Vector3.MoveTowards(particlePosition, thisManipulatorProperty.targets[playgroundParticles.playgroundCache.propertyTarget[p]%thisManipulatorProperty.targets.Count].localPosition, t*(thisManipulatorProperty.strength*thisManipulator.strength)/thisManipulator.strengthSmoothing)
										:
										Vector3.MoveTowards(particlePosition, thisManipulatorProperty.targets[playgroundParticles.playgroundCache.propertyTarget[p]%thisManipulatorProperty.targets.Count].position, t*(thisManipulatorProperty.strength*thisManipulator.strength)/thisManipulator.strengthSmoothing);
								
								if (thisManipulatorProperty.zeroVelocityStrength>0)
									playgroundParticles.playgroundCache.velocity[p] = Vector3.Lerp(playgroundParticles.playgroundCache.velocity[p], Vector3.zero, t*thisManipulatorProperty.zeroVelocityStrength);
							}
						}
					}

					// Mesh Target positioning outside of range
					if (thisManipulatorProperty.type == MANIPULATORPROPERTYTYPEC.MeshTarget && thisManipulatorProperty.meshTarget.initialized && playgroundParticles.playgroundCache.propertyId[p] == thisManipulator.manipulatorId) {
						if (thisManipulatorProperty.transition == MANIPULATORPROPERTYTRANSITIONC.Lerp) {
							playgroundParticles.playgroundCache.position[p] = Vector3.Lerp(particlePosition, thisManipulatorProperty.meshTargetMatrix.MultiplyPoint3x4(thisManipulatorProperty.meshTarget.vertexPositions[playgroundParticles.playgroundCache.propertyTarget[p]%thisManipulatorProperty.meshTarget.vertexPositions.Length]), (t*thisManipulatorProperty.strength*thisManipulator.strength/manipulatorDistance)/thisManipulator.strengthSmoothing);
							if (thisManipulatorProperty.zeroVelocityStrength>0)
								playgroundParticles.playgroundCache.velocity[p] = Vector3.Lerp(playgroundParticles.playgroundCache.velocity[p], Vector3.zero, t*thisManipulatorProperty.zeroVelocityStrength);
						} else if (thisManipulatorProperty.transition == MANIPULATORPROPERTYTRANSITIONC.Linear) {
							playgroundParticles.playgroundCache.position[p] = Vector3.MoveTowards(particlePosition, thisManipulatorProperty.meshTargetMatrix.MultiplyPoint3x4(thisManipulatorProperty.meshTarget.vertexPositions[playgroundParticles.playgroundCache.propertyTarget[p]%thisManipulatorProperty.meshTarget.vertexPositions.Length]), (t*thisManipulatorProperty.strength*thisManipulator.strength/manipulatorDistance)/thisManipulator.strengthSmoothing);
							if (thisManipulatorProperty.zeroVelocityStrength>0)
								playgroundParticles.playgroundCache.velocity[p] = Vector3.Lerp(playgroundParticles.playgroundCache.velocity[p], Vector3.zero, t*thisManipulatorProperty.zeroVelocityStrength);
						}
					}

					// Skinned Mesh Target positioning outside of range
					if (thisManipulatorProperty.type == MANIPULATORPROPERTYTYPEC.SkinnedMeshTarget && thisManipulatorProperty.skinnedMeshTarget.initialized && playgroundParticles.playgroundCache.propertyId[p] == thisManipulator.manipulatorId) {
						if (thisManipulatorProperty.transition == MANIPULATORPROPERTYTRANSITIONC.Lerp) {
							playgroundParticles.playgroundCache.position[p] = Vector3.Lerp(particlePosition, thisManipulatorProperty.skinnedMeshTarget.vertexPositions[playgroundParticles.playgroundCache.propertyTarget[p]%thisManipulatorProperty.skinnedMeshTarget.vertexPositions.Length], t*(thisManipulatorProperty.strength*thisManipulator.strength/manipulatorDistance)/thisManipulator.strengthSmoothing);
							if (thisManipulatorProperty.zeroVelocityStrength>0)
								playgroundParticles.playgroundCache.velocity[p] = Vector3.Lerp(playgroundParticles.playgroundCache.velocity[p], Vector3.zero, t*thisManipulatorProperty.zeroVelocityStrength);
						} else if (thisManipulatorProperty.transition == MANIPULATORPROPERTYTRANSITIONC.Linear) {
							playgroundParticles.playgroundCache.position[p] = Vector3.MoveTowards(particlePosition, thisManipulatorProperty.skinnedMeshTarget.vertexPositions[playgroundParticles.playgroundCache.propertyTarget[p]%thisManipulatorProperty.skinnedMeshTarget.vertexPositions.Length], t*(thisManipulatorProperty.strength*thisManipulator.strength/manipulatorDistance)/thisManipulator.strengthSmoothing);
							if (thisManipulatorProperty.zeroVelocityStrength>0)
								playgroundParticles.playgroundCache.velocity[p] = Vector3.Lerp(playgroundParticles.playgroundCache.velocity[p], Vector3.zero, t*thisManipulatorProperty.zeroVelocityStrength);
						}
					}
				}
			}
		}
        /// <summary>
        /// Calculates the effect from a Manipulator.
        /// </summary>
        /// <param name="playgroundParticles">Playground particles.</param>
        /// <param name="thisManipulator">This manipulator.</param>
        /// <param name="p">Particle index.</param>
        /// <param name="t">Delta time.</param>
        /// <param name="life">Lifetime.</param>
        /// <param name="particlePosition">Particle position.</param>
        /// <param name="manipulatorPosition">Manipulator position.</param>
        /// <param name="manipulatorDistance">Manipulator distance.</param>
        /// <param name="localSpace">Is calculation in local space?</param>
        public static void CalculateManipulator(PlaygroundParticlesC playgroundParticles, ManipulatorObjectC thisManipulator, int p, float t, float life, Vector3 particlePosition, Vector3 manipulatorPosition, bool localSpace)
        {
            if (thisManipulator.enabled && thisManipulator.transform.available && thisManipulator.strength!=0 && thisManipulator.LifetimeFilter(life, playgroundParticles.lifetime) && thisManipulator.ParticleFilter (p, playgroundParticles.particleCount)) {

                bool contains = thisManipulator.Contains(localSpace?(playgroundParticles.particleSystemRotation*particlePosition):particlePosition, localSpace?(playgroundParticles.particleSystemRotation*manipulatorPosition):manipulatorPosition);

                // Is this a particle which shouldn't be affected by this manipulator?
                if (contains && (playgroundParticles.playgroundCache.excludeFromManipulatorId[p]==thisManipulator.manipulatorId || thisManipulator.nonAffectedParticles.Count>0 && thisManipulator.ContainsNonAffectedParticle(playgroundParticles.particleSystemId, p))) {
                    return;
                }

                // Manipulator events
                if (thisManipulator.trackParticles) {

                    // Particle entering
                    if (contains) {
                        if ((thisManipulator.trackingMethod==TrackingMethod.ManipulatorId && !thisManipulator.IsSameId(playgroundParticles.playgroundCache.manipulatorId[p])) || (thisManipulator.trackingMethod==TrackingMethod.ParticleId && !thisManipulator.ContainsParticle(playgroundParticles.particleSystemId, p))) {
                            playgroundParticles.playgroundCache.manipulatorId[p] = thisManipulator.manipulatorId;
                            thisManipulator.AddParticle(playgroundParticles.particleSystemId, p);
                            if (thisManipulator.sendEventEnter) {
                                playgroundParticles.UpdateEventParticle(thisManipulator.manipulatorEventParticle, p);
                                thisManipulator.SendParticleEventEnter();
                            }
                        }
                    } else {

                        // Particle exiting
                        if ((thisManipulator.trackingMethod==TrackingMethod.ManipulatorId && thisManipulator.IsSameId(playgroundParticles.playgroundCache.manipulatorId[p])) || (thisManipulator.trackingMethod==TrackingMethod.ParticleId && thisManipulator.ContainsParticle(playgroundParticles.particleSystemId, p))) {
                            playgroundParticles.playgroundCache.manipulatorId[p] = 0;
                            thisManipulator.RemoveParticle(playgroundParticles.particleSystemId, p);
                            if (thisManipulator.sendEventExit) {
                                playgroundParticles.UpdateEventParticle(thisManipulator.manipulatorEventParticle, p);
                                thisManipulator.SendParticleEventExit();
                            }
                        }
                    }
                }

                float manipulatorDistance = 0;

                if (!playgroundParticles.onlySourcePositioning && !playgroundParticles.playgroundCache.noForce[p]) {
                    // Attractors
                    if (thisManipulator.type==MANIPULATORTYPEC.Attractor) {
                        if (contains) {
                            manipulatorDistance = thisManipulator.strengthDistanceEffect>0?Vector3.Distance (manipulatorPosition, playgroundParticles.playgroundCache.position[p])/thisManipulator.strengthDistanceEffect:10f;
                            playgroundParticles.playgroundCache.velocity[p] = Vector3.Lerp(playgroundParticles.playgroundCache.velocity[p], (manipulatorPosition-particlePosition)*(thisManipulator.strength/manipulatorDistance), t*(thisManipulator.strength/manipulatorDistance)/thisManipulator.strengthSmoothing);
                        }
                    } else

                    // Attractors Gravitational
                    if (thisManipulator.type==MANIPULATORTYPEC.AttractorGravitational) {
                        if (contains) {
                            manipulatorDistance = thisManipulator.strengthDistanceEffect>0?Vector3.Distance (manipulatorPosition, playgroundParticles.playgroundCache.position[p])/thisManipulator.strengthDistanceEffect:10f;
                            playgroundParticles.playgroundCache.velocity[p] = Vector3.Lerp(playgroundParticles.playgroundCache.velocity[p], (manipulatorPosition-particlePosition)*thisManipulator.strength/manipulatorDistance, t/thisManipulator.strengthSmoothing);
                        }
                    } else

                    // Repellents
                    if (thisManipulator.type==MANIPULATORTYPEC.Repellent) {
                        if (contains) {
                            manipulatorDistance = thisManipulator.strengthDistanceEffect>0?Vector3.Distance (manipulatorPosition, playgroundParticles.playgroundCache.position[p])/thisManipulator.strengthDistanceEffect:10f;
                            playgroundParticles.playgroundCache.velocity[p] = Vector3.Lerp(playgroundParticles.playgroundCache.velocity[p], (particlePosition-manipulatorPosition)*(thisManipulator.strength/manipulatorDistance), t*(thisManipulator.strength/manipulatorDistance)/thisManipulator.strengthSmoothing);
                        }
                    } else

                    // Vortex
                    if (thisManipulator.type==MANIPULATORTYPEC.Vortex) {
                        if (contains) {
                            manipulatorDistance = thisManipulator.strengthDistanceEffect>0?Vector3.Distance (manipulatorPosition, playgroundParticles.playgroundCache.position[p])/thisManipulator.strengthDistanceEffect:10f;
                            playgroundParticles.playgroundCache.velocity[p] = Vector3.Lerp(playgroundParticles.playgroundCache.velocity[p], ((manipulatorPosition-particlePosition)*thisManipulator.strength/manipulatorDistance)-Vector3.Cross(thisManipulator.transform.up, (manipulatorPosition-particlePosition))*thisManipulator.strength/manipulatorDistance, (t*thisManipulator.strength/manipulatorDistance)/thisManipulator.strengthSmoothing);
                        }
                    }
                }

                // Properties
                if (thisManipulator.type==MANIPULATORTYPEC.Property) {
                    manipulatorDistance = thisManipulator.strengthDistanceEffect>0?Vector3.SqrMagnitude (manipulatorPosition - particlePosition)/thisManipulator.strengthDistanceEffect:10f;
                    PropertyManipulator(playgroundParticles, thisManipulator, thisManipulator.property, p, t, particlePosition, manipulatorPosition, manipulatorDistance, localSpace, contains);
                } else

                // Combined
                if (thisManipulator.type==MANIPULATORTYPEC.Combined) {
                    manipulatorDistance = thisManipulator.strengthDistanceEffect>0?Vector3.SqrMagnitude (manipulatorPosition - particlePosition)/thisManipulator.strengthDistanceEffect:10f;
                    for (int i = 0; i<thisManipulator.properties.Count; i++)
                        PropertyManipulator(playgroundParticles, thisManipulator, thisManipulator.properties[i], p, t, particlePosition, manipulatorPosition, manipulatorDistance, localSpace, contains);
                }
            }
        }
		// Calculate the effect from a manipulator
		public static void CalculateManipulator (PlaygroundParticlesC playgroundParticles, ManipulatorObjectC thisManipulator, int p, float t, float life, Vector3 particlePosition, Vector3 manipulatorPosition, float manipulatorDistance, bool localSpace) {
			if (thisManipulator.enabled && thisManipulator.transform.available && thisManipulator.strength!=0 && thisManipulator.willAffect && thisManipulator.LifetimeFilter(life)) {
				if (!playgroundParticles.onlySourcePositioning) {
					// Attractors
					if (thisManipulator.type==MANIPULATORTYPEC.Attractor) {
						if (thisManipulator.Contains(particlePosition, manipulatorPosition)) {
							playgroundParticles.playgroundCache.velocity[p] = Vector3.Lerp(playgroundParticles.playgroundCache.velocity[p], (manipulatorPosition-particlePosition)*(thisManipulator.strength/manipulatorDistance), t*(thisManipulator.strength/manipulatorDistance)/thisManipulator.strengthSmoothing);
						}
					} else
						
					// Attractors Gravitational
					if (thisManipulator.type==MANIPULATORTYPEC.AttractorGravitational) {
						if (thisManipulator.Contains(particlePosition, manipulatorPosition)) {
							playgroundParticles.playgroundCache.velocity[p] = Vector3.Lerp(playgroundParticles.playgroundCache.velocity[p], (manipulatorPosition-particlePosition)*thisManipulator.strength/manipulatorDistance, t/thisManipulator.strengthSmoothing);
						}
					} else
						
					// Repellents 
					if (thisManipulator.type==MANIPULATORTYPEC.Repellent) {
						if (thisManipulator.Contains(particlePosition, manipulatorPosition)) {
							playgroundParticles.playgroundCache.velocity[p] = Vector3.Lerp(playgroundParticles.playgroundCache.velocity[p], (particlePosition-manipulatorPosition)*(thisManipulator.strength/manipulatorDistance), t*(thisManipulator.strength/manipulatorDistance)/thisManipulator.strengthSmoothing);
						}
					} else

					// Vortex
					if (thisManipulator.type==MANIPULATORTYPEC.Vortex) {
						if (thisManipulator.Contains(particlePosition, manipulatorPosition)) {
							playgroundParticles.playgroundCache.velocity[p] = Vector3.Lerp(playgroundParticles.playgroundCache.velocity[p], ((manipulatorPosition-particlePosition)*thisManipulator.strength/manipulatorDistance)-Vector3.Cross(thisManipulator.transform.up, (manipulatorPosition-particlePosition))*thisManipulator.strength/manipulatorDistance, (t*thisManipulator.strength/manipulatorDistance)/thisManipulator.strengthSmoothing);
						}
					}
				}
				
				// Properties
				if (thisManipulator.type==MANIPULATORTYPEC.Property) {
					PropertyManipulator(playgroundParticles, thisManipulator, thisManipulator.property, p, t, particlePosition, manipulatorPosition, manipulatorDistance, localSpace);
				} else
				
				// Combined
				if (thisManipulator.type==MANIPULATORTYPEC.Combined) {
					for (int i = 0; i<thisManipulator.properties.Count; i++)
						PropertyManipulator(playgroundParticles, thisManipulator, thisManipulator.properties[i], p, t, particlePosition, manipulatorPosition, manipulatorDistance, localSpace);
				}
			}
		}