public static byte[] Serialize(SParticleRenderer input)
        {
            ComposedPrimitives prims = new ComposedPrimitives();
            prims.AddValue(input.camPos.x); prims.AddValue(input.camPos.y); prims.AddValue(input.camPos.z);
            prims.AddValue(input.camUp.x); prims.AddValue(input.camUp.y); prims.AddValue(input.camUp.z);
            prims.AddValue(input.materialInstanceID);
            prims.AddValue(input.renderMode);
            prims.AddValue(input.cameraVelocityScale);
            prims.AddValue(input.lengthScale);
            prims.AddValue(input.velocityScale);

            return prims.Compose();
        }
        public static SParticleRenderer Deserialize(byte[] input)
        {
            SParticleRenderer result = new SParticleRenderer();
            ComposedPrimitives prims = ComposedPrimitives.FromByteArray(input);
            result.camPos = new Vector3(prims.ReadNextValue<float>(), prims.ReadNextValue<float>(), prims.ReadNextValue<float>());
            result.camUp = new Vector3(prims.ReadNextValue<float>(), prims.ReadNextValue<float>(), prims.ReadNextValue<float>());
            result.materialInstanceID = prims.ReadNextValue<int>();
            result.renderMode = prims.ReadNextValue<SParticleRenderMode>();
            result.cameraVelocityScale = prims.ReadNextValue<float>();
            result.lengthScale = prims.ReadNextValue<float>();
            result.velocityScale = prims.ReadNextValue<float>();

            prims.Dispose();
            return result;
        }
        private void SetParticleRenderer(ParticleSystemRenderer renderer)
        {
            if (renderer == null)
                return;

            this.renderer = new SParticleRenderer();
            SetMainCamPos();

            switch (renderer.renderMode) {
                case ParticleSystemRenderMode.Billboard: this.renderer.renderMode = SParticleRenderMode.Billboard; break;
                case ParticleSystemRenderMode.HorizontalBillboard: this.renderer.renderMode = SParticleRenderMode.HorizontalBillboard; break;
                case ParticleSystemRenderMode.Mesh: this.renderer.renderMode = SParticleRenderMode.Mesh; break;
                case ParticleSystemRenderMode.Stretch: this.renderer.renderMode = SParticleRenderMode.Stretch; break;
                case ParticleSystemRenderMode.VerticalBillboard: this.renderer.renderMode = SParticleRenderMode.VerticalBillboard; break;
            }

            this.renderer.cameraVelocityScale = renderer.cameraVelocityScale;
            this.renderer.lengthScale = renderer.lengthScale;
            this.renderer.velocityScale = renderer.velocityScale;
        }
        public override void Dispose()
        {
            base.Dispose();

            if (particles != null)
                particles.Dispose();

            renderer = null;
            particles = null;
        }
        public void SetParticles(int frameNumber, SParticleRenderer particleRenderer, SGenericParticleArray particleData)
        {
            this.particleRenderer = particleRenderer;
            this.particleData = particleData;

            if (frameNumber != currentFrameNumber){
                SetMaterial(particleRenderer, frameNumber);
                Render();
                currentFrameNumber = frameNumber;
            }
        }
        private void SetMaterial(SParticleRenderer particleRenderer, int frameNumber)
        {
            Material newMat = EditorMaterialHelper.GetClosestAvailableMaterialByID(particleRenderer.materialInstanceID, frameNumber);
            if(newMat != null){
                if (mat != null)
                    UnityEngine.Object.DestroyImmediate(mat);

                mat = newMat;
                meshRenderer.material = newMat;
            }
            EditorMaterialHelper.SetFallbackMaterial(meshRenderer);
        }