private void TestSelection()
    {
        // Selection (accounts for transparency)
        if (Input.GetMouseButtonDown(0))
        {
            RaycastHit hit;
            if (!Physics.Raycast(cam.ScreenPointToRay(Input.mousePosition), out hit))
            {
                return;
            }

            ParticleCollider hitParticleCollider = hit.transform.gameObject.GetComponent <ParticleCollider>();

            if (hitParticleCollider != null)
            {
                Renderer     rend         = hit.transform.GetComponent <Renderer>();
                MeshCollider meshCollider = hit.collider as MeshCollider;
                meshCollider.convex = false;

                if (rend == null || rend.sharedMaterial == null || rend.sharedMaterial.mainTexture == null || meshCollider == null)
                {
                    Debug.Log("HIT! " + hitParticleCollider.ParticleSys.name, this);
                    return;
                }

                Texture2D tex     = rend.material.mainTexture as Texture2D;
                Vector2   pixelUV = hit.textureCoord;

                // Apply texture sheet animation offset
                ParticleSystem.TextureSheetAnimationModule texModule = hitParticleCollider.ParticleSys.textureSheetAnimation;
                if (texModule.enabled)
                {
                    SubUVTextureInfo subUV = new SubUVTextureInfo(texModule, hitParticleCollider.Particle);
                    pixelUV.x = (subUV.currentColumn / subUV.columns) + (pixelUV.x / subUV.columns);
                    pixelUV.y = (subUV.currentRow / subUV.rows) + ((1 - pixelUV.y) / subUV.rows);
                    pixelUV.y = 1 - pixelUV.y;
                }

                pixelUV.x *= tex.width;
                pixelUV.y *= tex.height;

                Color hitColor = tex.GetPixelForced((int)pixelUV.x, (int)pixelUV.y);
                Debug.Log("Raycast hit color: " + hitColor, this);
                if (debugImg != null)
                {
                    debugImg.color = hitColor;
                }
                if (hitColor.a > hitTestAlphaCutoff)
                {
                    Debug.Log("HIT! " + hitParticleCollider.ParticleSys.name, this);
                }
            }
        }
    }
        public void ReconstructParticleSystem()
        {
            foreach (ParticleCollider curParticleCollider in particleColliders)
            {
                GameObject curGO = curParticleCollider.gameObject;
                ParticleSystem.Particle curParticle = curParticleCollider.Particle;

                float   rotationCorrection = 1f;
                Vector3 pivot = particleSystemRenderer.pivot;
                Vector3 size  = curParticle.GetCurrentSize3D(particleSys);

                // Get hierarchy scale
                Vector3 transformScale = particleSys.transform.localScale;

                // Apply position
                switch (particleSys.main.simulationSpace)
                {
                case ParticleSystemSimulationSpace.Local:
                    curGO.transform.SetParent(particleSys.gameObject.transform);
                    curGO.transform.localPosition = curParticle.position;

                    pivot = Vector3.Scale(pivot, transformScale);
                    break;

                case ParticleSystemSimulationSpace.World:
                    curGO.transform.SetParent(null);
                    curGO.transform.position = curParticle.position;

                    size = Vector3.Scale(size, transformScale);
                    break;
                }

                switch (particleSystemRenderer.renderMode)
                {
                case ParticleSystemRenderMode.Billboard:
                    // Billboard to camera
                    curGO.transform.LookAt(curGO.transform.position + cam.transform.rotation * Vector3.forward, cam.transform.rotation * Vector3.up);

                    rotationCorrection = -1f;
                    break;

                case ParticleSystemRenderMode.Mesh:
                    curGO.transform.rotation = Quaternion.identity;

                    // For mesh pivots, Z is Y and Y is Z
                    pivot.z = particleSystemRenderer.pivot.y * -1f;
                    pivot.y = particleSystemRenderer.pivot.z * -1f;

                    pivot *= curParticle.GetCurrentSize(particleSys);
                    break;

                default:
                    Debug.LogError("Unsupported render mode " + particleSystemRenderer.renderMode);
                    break;
                }

                // Apply rotation
                curGO.transform.Rotate(new Vector3(curParticle.rotation3D.x, curParticle.rotation3D.y, curParticle.rotation3D.z * rotationCorrection));

                // Apply scale
                curGO.transform.localScale = size;

                // Apply pivot
                pivot = Vector3.Scale(pivot, size);
                curGO.transform.position += (curGO.transform.right * pivot.x);
                curGO.transform.position += (curGO.transform.up * pivot.y);
                curGO.transform.position += (curGO.transform.forward * pivot.z * -1f);

                // Apply texture sheet animation
                ParticleSystem.TextureSheetAnimationModule texModule = particleSys.textureSheetAnimation;
                if (texModule.enabled)
                {
                    SubUVTextureInfo subUV = new SubUVTextureInfo(texModule, curParticle);

                    switch (texModule.animation)
                    {
                    case ParticleSystemAnimationType.WholeSheet:
                        curParticleCollider.gameObject.GetComponent <MeshRenderer>().material.mainTextureScale  = new Vector2(1 / subUV.columns, 1 / subUV.rows);
                        curParticleCollider.gameObject.GetComponent <MeshRenderer>().material.mainTextureOffset = new Vector2(subUV.currentColumn / subUV.columns, (subUV.rows - subUV.currentRow - 1) / subUV.rows);

                        break;

                    case ParticleSystemAnimationType.SingleRow:
                        Debug.Log("Single Row texture sheet animations currently not supported.");

                        break;

                    default:
                        Debug.Log("Unsupported texture sheet animation animation type.");

                        break;
                    }
                }

                // Apply color
                Color    particleColor = curParticle.GetCurrentColor(particleSys);
                Material mat           = curGO.GetComponent <MeshRenderer>().material;
                Color    matColor      = particleSystemRenderer.material.GetColor(TINT_COLOR);
                curGO.GetComponent <MeshRenderer>().material.SetColor(TINT_COLOR, particleColor * matColor);
            }
        }